YM2608-LLE, part 11

now with per-channel osc
This commit is contained in:
tildearrow 2024-04-28 02:21:31 -05:00
parent ff9d5370c5
commit 4fab971b7d
4 changed files with 79 additions and 50 deletions

View file

@ -2430,10 +2430,11 @@ void FMOPNA_2612_Clock(fmopna_2612_t* chip, int clk)
}; };
// tildearrow: per-channel oscilloscope for SSG
chip->o_analog = 0; chip->o_analog = 0;
chip->o_analog += volume_lut[sign_a ? 0 : vol_a]; chip->o_analog += chip->o_analog_ch[0] = volume_lut[sign_a ? 0 : vol_a];
chip->o_analog += volume_lut[sign_b ? 0 : vol_b]; chip->o_analog += chip->o_analog_ch[1] = volume_lut[sign_b ? 0 : vol_b];
chip->o_analog += volume_lut[sign_c ? 0 : vol_c]; chip->o_analog += chip->o_analog_ch[2] = volume_lut[sign_c ? 0 : vol_c];
} }
{ {
@ -5368,6 +5369,8 @@ void FMOPNA_2612_Clock(fmopna_2612_t* chip, int clk)
chip->ac_rss_load = chip->rss_cnt2[1] == 0; chip->ac_rss_load = chip->rss_cnt2[1] == 0;
// tildearrow: per-channel osc
chip->last_rss_sample = rss_sample & 0xffff;
} }
if (chip->rss_eclk2) if (chip->rss_eclk2)
{ {

View file

@ -845,6 +845,8 @@ typedef struct {
int sh1_l; int sh1_l;
int sh2_l; int sh2_l;
int opo_fm; int opo_fm;
int last_rss_sample;
#endif #endif
int busy_cnt[2]; int busy_cnt[2];
@ -932,6 +934,7 @@ typedef struct {
#ifndef FMOPNA_YM2612 #ifndef FMOPNA_YM2612
float o_analog; float o_analog;
float o_analog_ch[3];
int o_sh1; int o_sh1;
int o_sh2; int o_sh2;
int o_opo; int o_opo;

View file

@ -490,21 +490,28 @@ void DivPlatformYM2608::acquire_ymfm(short** buf, size_t len) {
} }
} }
static const unsigned char subCycleMap[6]={
3, 4, 5, 0, 1, 2
};
// ac_fm_output // ac_fm_output
void DivPlatformYM2608::acquire_lle(short** buf, size_t len) { void DivPlatformYM2608::acquire_lle(short** buf, size_t len) {
thread_local int fmOut[6];
for (size_t h=0; h<len; h++) { for (size_t h=0; h<len; h++) {
bool have0=false; bool have0=false;
bool have1=false; bool have1=false;
unsigned char howLong=0; unsigned char howLong=0;
unsigned char subCycle=0x100-12; signed char subCycle=0;
unsigned char subSubCycle=0; unsigned char subSubCycle=0;
for (int i=0; i<6; i++) {
fmOut[i]=0;
}
while (true) { while (true) {
bool canWeWrite=fm_lle.prescaler_latch[1]&1; bool canWeWrite=fm_lle.prescaler_latch[1]&1;
lastS=fm_lle.o_s;
lastSH=fm_lle.o_sh1;
lastSH2=fm_lle.o_sh2;
if (canWeWrite) { if (canWeWrite) {
if (delay>0) { if (delay>0) {
if (delay==3) { if (delay==3) {
@ -563,10 +570,18 @@ void DivPlatformYM2608::acquire_lle(short** buf, size_t len) {
if (++subSubCycle>=6) { if (++subSubCycle>=6) {
subSubCycle=0; subSubCycle=0;
if (subCycle<12) { if (subCycle>=0 && subCycle<6 && fm_lle.ac_fm_output_en) {
oscBuf[subCycle]->data[oscBuf[subCycle]->needle++]=fm_lle.ac_fm_output; fmOut[subCycleMap[subCycle]]+=((short)fm_lle.ac_fm_output)<<2;
}
if (++subCycle>=6) subCycle=0;
}
if (fm_lle.rss_eclk1) {
if (++rssSubCycle>=24) {
rssSubCycle=0;
rssOut[rssCycle]=(short)fm_lle.last_rss_sample;
if (++rssCycle>=6) rssCycle=0;
} }
subCycle++;
} }
if (canWeWrite) { if (canWeWrite) {
@ -577,45 +592,26 @@ void DivPlatformYM2608::acquire_lle(short** buf, size_t len) {
} }
} }
} }
if (!fm_lle.o_s && lastS) {
if (!fm_lle.o_sh1 && lastSH) {
dacOut[0]=dacVal^0x8000;
have0=true;
}
if (!fm_lle.o_sh2 && lastSH2) {
dacOut[1]=dacVal^0x8000;
have1=true;
}
if (fm_lle.o_s && !lastS) {
dacVal>>=1; dacVal>>=1;
dacVal|=(fm_lle.o_opo&1)<<14; dacVal|=(fm_lle.o_opo&1)<<15;
howLong++; howLong++;
lastSH=fm_lle.o_sh1;
lastSH2=fm_lle.o_sh2;
} }
if (!fm_lle.o_sh1 && lastSH) { lastS=fm_lle.o_s;
if (dacVal&0x2000) { // positive
int e=(dacVal>>10)&7;
int m=(dacVal>>0)&1023;
dacOut[0]=m<<e;
if (e) dacOut[0]+=512<<e;
} else { // negative
int e=((dacVal>>10)&7)^7;
int m=((dacVal>>0)&1023)^1023;
dacOut[0]=-(m<<e);
if (e) dacOut[0]-=512<<e;
}
//int e=(dacVal>>10)&7;
//int m=(dacVal>>0)&1023;
//m-=512;
have0=true;
}
if (!fm_lle.o_sh2 && lastSH2) {
if (dacVal&0x2000) { // positive
int e=(dacVal>>10)&7;
int m=(dacVal>>0)&1023;
dacOut[1]=(m<<e);
if (e) dacOut[1]+=512<<e;
} else { // negative
int e=((dacVal>>10)&7)^7;
int m=((dacVal>>0)&1023)^1023;
dacOut[1]=-(m<<e);
if (e) dacOut[1]-=512<<e;
}
have1=true;
}
// ADPCM data bus // ADPCM data bus
// thanks nukeykt // thanks nukeykt
@ -643,12 +639,32 @@ void DivPlatformYM2608::acquire_lle(short** buf, size_t len) {
//logW("NOT 48! %d",howLong); //logW("NOT 48! %d",howLong);
} }
// DAC // chan osc
int accm1=dacOut[0]; // FM
int accm2=dacOut[1]; for (int i=0; i<6; i++) {
if (fmOut[i]<-32768) fmOut[i]=-32768;
if (fmOut[i]>32767) fmOut[i]=32767;
oscBuf[i]->data[oscBuf[i]->needle++]=fmOut[i];
}
// SSG
for (int i=0; i<3; i++) {
oscBuf[i+6]->data[oscBuf[i+6]->needle++]=fm_lle.o_analog_ch[i]*32767;
}
// RSS
for (int i=0; i<6; i++) {
if (rssOut[i]<-32768) rssOut[i]=-32768;
if (rssOut[i]>32767) rssOut[i]=32767;
oscBuf[9+i]->data[oscBuf[9+i]->needle++]=rssOut[i];
}
// ADPCM
oscBuf[15]->data[oscBuf[15]->needle++]=fm_lle.ac_ad_output;
int outL=(accm1<<1)+fm_lle.o_analog*ssgVol*42; // DAC
int outR=(accm2<<1)+fm_lle.o_analog*ssgVol*42; int accm1=(short)dacOut[0];
int accm2=(short)dacOut[1];
int outL=(accm1)+fm_lle.o_analog*ssgVol*42;
int outR=(accm2)+fm_lle.o_analog*ssgVol*42;
if (outL<-32768) outL=-32768; if (outL<-32768) outL=-32768;
if (outL>32767) outL=32767; if (outL>32767) outL=32767;
@ -1745,6 +1761,12 @@ void DivPlatformYM2608::reset() {
writeRSSOff=0; writeRSSOff=0;
writeRSSOn=0; writeRSSOn=0;
globalRSSVolume=0x3f; globalRSSVolume=0x3f;
rssCycle=0;
rssSubCycle=0;
for (int i=0; i<6; i++) {
rssOut[i]=0;
}
delay=0; delay=0;

View file

@ -57,10 +57,11 @@ class DivPlatformYM2608: public DivPlatformOPN {
unsigned int dacVal; unsigned int dacVal;
unsigned int dacVal2; unsigned int dacVal2;
int dacOut[2]; int dacOut[2];
int rssOut[6];
bool lastSH; bool lastSH;
bool lastSH2; bool lastSH2;
bool lastS; bool lastS;
unsigned char cas, ras; unsigned char cas, ras, rssCycle, rssSubCycle;
unsigned short adMemAddr; unsigned short adMemAddr;
int adReadCount; int adReadCount;