MMC5: acquireDirect(), part 1
no samples also fixed chan osc
This commit is contained in:
parent
86fb92595a
commit
1070fb5d10
|
@ -24,7 +24,7 @@
|
|||
|
||||
#define CHIP_DIVIDER 16
|
||||
|
||||
#define rWrite(a,v) if (!skipRegisterWrites) {extcl_cpu_wr_mem_MMC5(mmc5,a,v); regPool[(a)&0x7f]=v; if (dumpWrites) {addWrite(a,v);} }
|
||||
#define rWrite(a,v) if (!skipRegisterWrites) {writes.push(QueuedWrite((a),v)); if (dumpWrites) {addWrite(a,v);} }
|
||||
|
||||
const char* regCheatSheetMMC5[]={
|
||||
"S0Volume", "5000",
|
||||
|
@ -43,12 +43,27 @@ const char** DivPlatformMMC5::getRegisterSheet() {
|
|||
return regCheatSheetMMC5;
|
||||
}
|
||||
|
||||
void DivPlatformMMC5::acquire(short** buf, size_t len) {
|
||||
void DivPlatformMMC5::acquireDirect(blip_buffer_t** bb, size_t len) {
|
||||
for (int i=0; i<3; i++) {
|
||||
oscBuf[i]->begin(len);
|
||||
mmc5->oscBuf[i]=oscBuf[i];
|
||||
}
|
||||
|
||||
mmc5->bb=bb[0];
|
||||
mmc5->timestamp=0;
|
||||
|
||||
while (!writes.empty()) {
|
||||
QueuedWrite w=writes.front();
|
||||
regPool[(w.addr)&0x7f]=w.val;
|
||||
extcl_cpu_wr_mem_MMC5(mmc5,0,w.addr,w.val);
|
||||
writes.pop();
|
||||
}
|
||||
|
||||
// TODO: does this matter?
|
||||
extcl_envelope_clock_MMC5(mmc5);
|
||||
extcl_length_clock_MMC5(mmc5);
|
||||
for (size_t i=0; i<len; i++) {
|
||||
/*
|
||||
if (dacSample!=-1) {
|
||||
dacPeriod+=dacRate;
|
||||
if (dacPeriod>=rate) {
|
||||
|
@ -69,10 +84,12 @@ void DivPlatformMMC5::acquire(short** buf, size_t len) {
|
|||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
extcl_envelope_clock_MMC5(mmc5);
|
||||
extcl_length_clock_MMC5(mmc5);
|
||||
extcl_apu_tick_MMC5(mmc5);
|
||||
|
||||
extcl_apu_tick_MMC5(mmc5,len);
|
||||
break;
|
||||
/*
|
||||
if (mmc5->clocked) {
|
||||
mmc5->clocked=false;
|
||||
}
|
||||
|
@ -92,7 +109,7 @@ void DivPlatformMMC5::acquire(short** buf, size_t len) {
|
|||
oscBuf[0]->putSample(i,isMuted[0]?0:((mmc5->S3.output)<<11));
|
||||
oscBuf[1]->putSample(i,isMuted[1]?0:((mmc5->S4.output)<<11));
|
||||
oscBuf[2]->putSample(i,isMuted[2]?0:((mmc5->pcm.output)<<7));
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
for (int i=0; i<3; i++) {
|
||||
|
@ -364,6 +381,7 @@ int DivPlatformMMC5::dispatch(DivCommand c) {
|
|||
|
||||
void DivPlatformMMC5::muteChannel(int ch, bool mute) {
|
||||
isMuted[ch]=mute;
|
||||
mmc5->muted[ch]=mute;
|
||||
}
|
||||
|
||||
void DivPlatformMMC5::forceIns() {
|
||||
|
@ -415,6 +433,10 @@ void DivPlatformMMC5::reset() {
|
|||
map_init_MMC5(mmc5);
|
||||
memset(regPool,0,128);
|
||||
|
||||
mmc5->muted[0]=isMuted[0];
|
||||
mmc5->muted[1]=isMuted[1];
|
||||
mmc5->muted[2]=isMuted[2];
|
||||
|
||||
rWrite(0x5015,0x03);
|
||||
rWrite(0x5010,0x00);
|
||||
}
|
||||
|
@ -423,6 +445,10 @@ bool DivPlatformMMC5::keyOffAffectsArp(int ch) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool DivPlatformMMC5::hasAcquireDirect() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void DivPlatformMMC5::setFlags(const DivConfig& flags) {
|
||||
int clockSel=flags.getInt("clockSel",0);
|
||||
if (clockSel==2) { // Dendy
|
||||
|
|
|
@ -39,6 +39,13 @@ class DivPlatformMMC5: public DivDispatch {
|
|||
Channel chan[5];
|
||||
DivDispatchOscBuffer* oscBuf[3];
|
||||
bool isMuted[5];
|
||||
struct QueuedWrite {
|
||||
unsigned short addr;
|
||||
unsigned char val;
|
||||
QueuedWrite(): addr(0), val(0) {}
|
||||
QueuedWrite(unsigned short a, unsigned char v): addr(a), val(v) {}
|
||||
};
|
||||
FixedQueue<QueuedWrite,128> writes;
|
||||
int dacPeriod, dacRate;
|
||||
unsigned int dacPos;
|
||||
int dacSample;
|
||||
|
@ -51,7 +58,7 @@ class DivPlatformMMC5: public DivDispatch {
|
|||
friend void putDispatchChan(void*,int,int);
|
||||
|
||||
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);
|
||||
|
@ -63,6 +70,7 @@ class DivPlatformMMC5: public DivDispatch {
|
|||
void tick(bool sysTick=true);
|
||||
void muteChannel(int ch, bool mute);
|
||||
bool keyOffAffectsArp(int ch);
|
||||
bool hasAcquireDirect();
|
||||
float getPostAmp();
|
||||
void setFlags(const DivConfig& flags);
|
||||
void notifyInsDeletion(void* ins);
|
||||
|
|
|
@ -60,6 +60,8 @@ void apu_tick(struct NESAPU* a, int len) {
|
|||
}
|
||||
if (advance<1) advance=1;
|
||||
|
||||
int postTS=a->timestamp+advance-1;
|
||||
|
||||
/* sottraggo il numero di cicli eseguiti */
|
||||
a->apu.cycles-=advance;
|
||||
/*
|
||||
|
@ -220,7 +222,7 @@ void apu_tick(struct NESAPU* a, int len) {
|
|||
square_output(a->S1, 0)
|
||||
a->S1.frequency = (a->S1.timer + 1) << 1;
|
||||
a->S1.sequencer = (a->S1.sequencer + 1) & 0x07;
|
||||
a->oscBuf[0]->putSample(a->timestamp,a->muted[0]?0:(a->S1.output<<11));
|
||||
a->oscBuf[0]->putSample(postTS,a->muted[0]?0:(a->S1.output<<11));
|
||||
}
|
||||
|
||||
// SQUARE 2 TICK
|
||||
|
@ -228,7 +230,7 @@ void apu_tick(struct NESAPU* a, int len) {
|
|||
square_output(a->S2, 0)
|
||||
a->S2.frequency = (a->S2.timer + 1) << 1;
|
||||
a->S2.sequencer = (a->S2.sequencer + 1) & 0x07;
|
||||
a->oscBuf[1]->putSample(a->timestamp,a->muted[1]?0:(a->S2.output<<11));
|
||||
a->oscBuf[1]->putSample(postTS,a->muted[1]?0:(a->S2.output<<11));
|
||||
}
|
||||
|
||||
// TRIANGLE TICK
|
||||
|
@ -237,7 +239,7 @@ void apu_tick(struct NESAPU* a, int len) {
|
|||
if (a->TR.length.value && a->TR.linear.value) {
|
||||
a->TR.sequencer = (a->TR.sequencer + 1) & 0x1F;
|
||||
triangle_output()
|
||||
a->oscBuf[2]->putSample(a->timestamp,a->muted[2]?0:(a->TR.output<<11));
|
||||
a->oscBuf[2]->putSample(postTS,a->muted[2]?0:(a->TR.output<<11));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -251,7 +253,7 @@ void apu_tick(struct NESAPU* a, int len) {
|
|||
a->NS.shift &= 0x7FFF;
|
||||
noise_output()
|
||||
a->NS.frequency = noise_timer[a->apu.type][a->NS.timer];
|
||||
a->oscBuf[3]->putSample(a->timestamp,a->muted[3]?0:(a->NS.output<<11));
|
||||
a->oscBuf[3]->putSample(postTS,a->muted[3]?0:(a->NS.output<<11));
|
||||
}
|
||||
|
||||
// DMC TICK
|
||||
|
@ -280,7 +282,7 @@ void apu_tick(struct NESAPU* a, int len) {
|
|||
}
|
||||
}
|
||||
a->DMC.frequency = dmc_rate[a->apu.type][a->DMC.rate_index];
|
||||
a->oscBuf[4]->putSample(a->timestamp,a->muted[4]?0:(a->DMC.output<<8));
|
||||
a->oscBuf[4]->putSample(postTS,a->muted[4]?0:(a->DMC.output<<8));
|
||||
}
|
||||
if (a->DMC.empty && a->DMC.remain) {
|
||||
BYTE tick = 4;
|
||||
|
@ -323,7 +325,7 @@ void apu_tick(struct NESAPU* a, int len) {
|
|||
}
|
||||
|
||||
// output sample
|
||||
a->timestamp+=advance-1;
|
||||
a->timestamp=postTS;
|
||||
int sample=(pulse_output(a)+tnd_output(a))<<6;
|
||||
if (sample!=a->lastSample) {
|
||||
blip_add_delta(a->bb,a->timestamp,sample-a->lastSample);
|
||||
|
|
|
@ -35,12 +35,21 @@ void map_init_MMC5(struct _mmc5* mmc5) {
|
|||
mmc5->S3.length.value = 0;
|
||||
mmc5->S4.length.enabled = 0;
|
||||
mmc5->S4.length.value = 0;
|
||||
|
||||
mmc5->timestamp = 0;
|
||||
mmc5->lastSample = 0;
|
||||
mmc5->bb = NULL;
|
||||
mmc5->oscBuf[0] = NULL;
|
||||
mmc5->oscBuf[1] = NULL;
|
||||
mmc5->oscBuf[2] = NULL;
|
||||
}
|
||||
void extcl_cpu_wr_mem_MMC5(struct _mmc5* mmc5, WORD address, BYTE value) {
|
||||
void extcl_cpu_wr_mem_MMC5(struct _mmc5* mmc5, int ts, WORD address, BYTE value) {
|
||||
if (address < 0x5000) {
|
||||
return;
|
||||
}
|
||||
|
||||
extcl_apu_tick_MMC5(mmc5,ts);
|
||||
|
||||
switch (address) {
|
||||
case 0x5000:
|
||||
square_reg0(mmc5->S3);
|
||||
|
@ -71,16 +80,18 @@ void extcl_cpu_wr_mem_MMC5(struct _mmc5* mmc5, WORD address, BYTE value) {
|
|||
mmc5->pcm.output = 0;
|
||||
if (mmc5->pcm.enabled) {
|
||||
mmc5->pcm.output = mmc5->pcm.amp;
|
||||
mmc5->oscBuf[2]->putSample(mmc5->timestamp,mmc5->muted[2]?0:(mmc5->pcm.output<<7));
|
||||
}
|
||||
mmc5->clocked = TRUE;
|
||||
//mmc5->clocked = TRUE;
|
||||
return;
|
||||
case 0x5011:
|
||||
mmc5->pcm.amp = value;
|
||||
mmc5->pcm.output = 0;
|
||||
if (mmc5->pcm.enabled) {
|
||||
mmc5->pcm.output = mmc5->pcm.amp;
|
||||
mmc5->oscBuf[2]->putSample(mmc5->timestamp,mmc5->muted[2]?0:(mmc5->pcm.output<<7));
|
||||
}
|
||||
mmc5->clocked = TRUE;
|
||||
//mmc5->clocked = TRUE;
|
||||
return;
|
||||
case 0x5015:
|
||||
if (!(mmc5->S3.length.enabled = value & 0x01)) {
|
||||
|
@ -100,20 +111,70 @@ void extcl_envelope_clock_MMC5(struct _mmc5* mmc5) {
|
|||
envelope_run(mmc5->S3)
|
||||
envelope_run(mmc5->S4)
|
||||
}
|
||||
void extcl_apu_tick_MMC5(struct _mmc5* mmc5) {
|
||||
// SQUARE 3 TICK
|
||||
if (!(--mmc5->S3.frequency)) {
|
||||
square_output(mmc5->S3, 0)
|
||||
mmc5->S3.frequency = (mmc5->S3.timer + 1) << 1;
|
||||
mmc5->S3.sequencer = (mmc5->S3.sequencer + 1) & 0x07;
|
||||
mmc5->clocked = TRUE;
|
||||
void extcl_apu_tick_MMC5(struct _mmc5* mmc5, int len) {
|
||||
if (len<=mmc5->timestamp) return;
|
||||
|
||||
int rem=len-mmc5->timestamp;
|
||||
if (rem>1) {
|
||||
// output now just in case
|
||||
int sample=mmc5->muted[0]?0:(mmc5->S3.output*10);
|
||||
if (!mmc5->muted[1]) {
|
||||
sample+=mmc5->S4.output*10;
|
||||
}
|
||||
if (!mmc5->muted[2]) {
|
||||
sample+=mmc5->pcm.output*2;
|
||||
}
|
||||
if (sample!=mmc5->lastSample) {
|
||||
blip_add_delta(mmc5->bb,mmc5->timestamp,sample-mmc5->lastSample);
|
||||
mmc5->lastSample=sample;
|
||||
}
|
||||
}
|
||||
|
||||
// SQUARE 4 TICK
|
||||
if (!(--mmc5->S4.frequency)) {
|
||||
square_output(mmc5->S4, 0)
|
||||
mmc5->S4.frequency = (mmc5->S4.timer + 1) << 1;
|
||||
mmc5->S4.sequencer = (mmc5->S4.sequencer + 1) & 0x07;
|
||||
mmc5->clocked = TRUE;
|
||||
while (rem>0) {
|
||||
// predict advance
|
||||
int advance=rem;
|
||||
if (advance>mmc5->S3.frequency) {
|
||||
advance=mmc5->S3.frequency;
|
||||
}
|
||||
if (advance>mmc5->S4.frequency) {
|
||||
advance=mmc5->S4.frequency;
|
||||
}
|
||||
if (advance<1) advance=1;
|
||||
|
||||
int postTS=mmc5->timestamp+advance-1;
|
||||
|
||||
// SQUARE 3 TICK
|
||||
if (!(mmc5->S3.frequency-=advance)) {
|
||||
square_output(mmc5->S3, 0)
|
||||
mmc5->S3.frequency = (mmc5->S3.timer + 1) << 1;
|
||||
mmc5->S3.sequencer = (mmc5->S3.sequencer + 1) & 0x07;
|
||||
mmc5->oscBuf[0]->putSample(postTS,mmc5->muted[0]?0:(mmc5->S3.output<<11));
|
||||
}
|
||||
|
||||
// SQUARE 4 TICK
|
||||
if (!(mmc5->S4.frequency-=advance)) {
|
||||
square_output(mmc5->S4, 0)
|
||||
mmc5->S4.frequency = (mmc5->S4.timer + 1) << 1;
|
||||
mmc5->S4.sequencer = (mmc5->S4.sequencer + 1) & 0x07;
|
||||
mmc5->oscBuf[1]->putSample(postTS,mmc5->muted[1]?0:(mmc5->S4.output<<11));
|
||||
}
|
||||
|
||||
// output sample
|
||||
mmc5->timestamp=postTS;
|
||||
int sample=mmc5->muted[0]?0:(mmc5->S3.output*10);
|
||||
if (!mmc5->muted[1]) {
|
||||
sample+=mmc5->S4.output*10;
|
||||
}
|
||||
if (!mmc5->muted[2]) {
|
||||
sample+=mmc5->pcm.output*2;
|
||||
}
|
||||
if (sample!=mmc5->lastSample) {
|
||||
blip_add_delta(mmc5->bb,mmc5->timestamp,sample-mmc5->lastSample);
|
||||
mmc5->lastSample=sample;
|
||||
}
|
||||
|
||||
rem-=advance;
|
||||
mmc5->timestamp++;
|
||||
}
|
||||
mmc5->timestamp=len;
|
||||
}
|
||||
|
|
|
@ -54,19 +54,18 @@ struct _mmc5 {
|
|||
BYTE output;
|
||||
BYTE amp;
|
||||
} pcm;
|
||||
BYTE filler[50];
|
||||
int timestamp;
|
||||
int lastSample;
|
||||
BYTE muted[3];
|
||||
|
||||
/* ------------------------------------------------------- */
|
||||
/* questi valori non e' necessario salvarli nei savestates */
|
||||
/* ------------------------------------------------------- */
|
||||
/* */ BYTE clocked; /* */
|
||||
/* ------------------------------------------------------- */
|
||||
blip_buffer_t* bb;
|
||||
DivDispatchOscBuffer* oscBuf[5];
|
||||
};
|
||||
|
||||
void map_init_MMC5(struct _mmc5* mmc5);
|
||||
void extcl_cpu_wr_mem_MMC5(struct _mmc5* mmc5, WORD address, BYTE value);
|
||||
void extcl_cpu_wr_mem_MMC5(struct _mmc5* mmc5, int ts, WORD address, BYTE value);
|
||||
void extcl_length_clock_MMC5(struct _mmc5* mmc5);
|
||||
void extcl_envelope_clock_MMC5(struct _mmc5* mmc5);
|
||||
void extcl_apu_tick_MMC5(struct _mmc5* mmc5);
|
||||
void extcl_apu_tick_MMC5(struct _mmc5* mmc5, int len);
|
||||
|
||||
#endif /* MAPPER_MMC5_H_ */
|
||||
|
|
Loading…
Reference in a new issue