mirror of
https://github.com/tildearrow/furnace.git
synced 2024-11-01 10:32:40 +00:00
YM2608-LLE, part 14
now on YM2203
This commit is contained in:
parent
ebe10ee37f
commit
42fd63847e
3 changed files with 219 additions and 9 deletions
|
@ -157,7 +157,9 @@ const char** DivPlatformYM2203::getRegisterSheet() {
|
|||
}
|
||||
|
||||
void DivPlatformYM2203::acquire(short** buf, size_t len) {
|
||||
if (useCombo) {
|
||||
if (useCombo==2) {
|
||||
acquire_lle(buf,len);
|
||||
} else if (useCombo==1) {
|
||||
acquire_combo(buf,len);
|
||||
} else {
|
||||
acquire_ymfm(buf,len);
|
||||
|
@ -292,6 +294,164 @@ void DivPlatformYM2203::acquire_ymfm(short** buf, size_t len) {
|
|||
}
|
||||
}
|
||||
|
||||
static const unsigned char subCycleMap[6]={
|
||||
3, 4, 5, 0, 1, 2
|
||||
};
|
||||
|
||||
void DivPlatformYM2203::acquire_lle(short** buf, size_t len) {
|
||||
thread_local int fmOut[6];
|
||||
|
||||
for (size_t h=0; h<len; h++) {
|
||||
bool have0=false;
|
||||
bool have1=false;
|
||||
signed char subCycle=0;
|
||||
unsigned char subSubCycle=0;
|
||||
|
||||
for (int i=0; i<6; i++) {
|
||||
fmOut[i]=0;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
bool canWeWrite=fm_lle.prescaler_latch[1]&1;
|
||||
|
||||
if (canWeWrite) {
|
||||
if (delay>0) {
|
||||
if (delay==3) {
|
||||
fm_lle.input.cs=1;
|
||||
fm_lle.input.rd=1;
|
||||
fm_lle.input.wr=1;
|
||||
fm_lle.input.a0=0;
|
||||
fm_lle.input.a1=0;
|
||||
delay=0;
|
||||
} else {
|
||||
fm_lle.input.cs=0;
|
||||
fm_lle.input.rd=0;
|
||||
fm_lle.input.wr=1;
|
||||
fm_lle.input.a0=0;
|
||||
fm_lle.input.a1=0;
|
||||
fm_lle.input.data=0;
|
||||
delay=1;
|
||||
}
|
||||
} else if (!writes.empty()) {
|
||||
QueuedWrite& w=writes.front();
|
||||
if (w.addr==0x2e || w.addr==0x2f) {
|
||||
// ignore prescaler writes since it doesn't work too well
|
||||
fm_lle.input.cs=1;
|
||||
fm_lle.input.rd=1;
|
||||
fm_lle.input.wr=1;
|
||||
fm_lle.input.a1=0;
|
||||
fm_lle.input.a0=0;
|
||||
fm_lle.input.data=0;
|
||||
|
||||
regPool[w.addr&0x1ff]=w.val;
|
||||
writes.pop_front();
|
||||
} else if (w.addrOrVal) {
|
||||
fm_lle.input.cs=0;
|
||||
fm_lle.input.rd=1;
|
||||
fm_lle.input.wr=0;
|
||||
fm_lle.input.a1=0;
|
||||
fm_lle.input.a0=1;
|
||||
fm_lle.input.data=w.val;
|
||||
|
||||
delay=2;
|
||||
|
||||
regPool[w.addr&0x1ff]=w.val;
|
||||
writes.pop_front();
|
||||
} else {
|
||||
fm_lle.input.cs=0;
|
||||
fm_lle.input.rd=1;
|
||||
fm_lle.input.wr=0;
|
||||
fm_lle.input.a1=0;
|
||||
fm_lle.input.a0=0;
|
||||
fm_lle.input.data=w.addr&0xff;
|
||||
|
||||
delay=2;
|
||||
|
||||
w.addrOrVal=true;
|
||||
}
|
||||
} else {
|
||||
fm_lle.input.cs=1;
|
||||
fm_lle.input.rd=1;
|
||||
fm_lle.input.wr=1;
|
||||
fm_lle.input.a0=0;
|
||||
fm_lle.input.a1=0;
|
||||
}
|
||||
}
|
||||
|
||||
FMOPNA_Clock(&fm_lle,0);
|
||||
FMOPNA_Clock(&fm_lle,1);
|
||||
|
||||
if (++subSubCycle>=6) {
|
||||
subSubCycle=0;
|
||||
if (subCycle>=0 && subCycle<6 && fm_lle.ac_fm_output_en) {
|
||||
fmOut[subCycleMap[subCycle]]+=((short)fm_lle.ac_fm_output)<<2;
|
||||
}
|
||||
if (++subCycle>=6) subCycle=0;
|
||||
}
|
||||
|
||||
if (canWeWrite) {
|
||||
if (delay==1) {
|
||||
// check busy status here
|
||||
if (!fm_lle.busy_cnt_en[1]) {
|
||||
delay=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!fm_lle.o_s && lastS) {
|
||||
if (!fm_lle.o_sh1 && lastSH) {
|
||||
dacVal2=dacVal;
|
||||
}
|
||||
|
||||
if (!fm_lle.o_sh2 && lastSH2) {
|
||||
dacVal2=dacVal;
|
||||
}
|
||||
|
||||
if (fm_lle.o_sh1 && !lastSH) {
|
||||
dacOut[0]=dacVal2^0x8000;
|
||||
have0=true;
|
||||
}
|
||||
|
||||
if (fm_lle.o_sh2 && !lastSH2) {
|
||||
dacOut[1]=dacVal2^0x8000;
|
||||
have1=true;
|
||||
}
|
||||
|
||||
dacVal>>=1;
|
||||
dacVal|=(fm_lle.o_opo&1)<<15;
|
||||
|
||||
lastSH=fm_lle.o_sh1;
|
||||
lastSH2=fm_lle.o_sh2;
|
||||
}
|
||||
|
||||
lastS=fm_lle.o_s;
|
||||
|
||||
if (have0 && have1) break;
|
||||
}
|
||||
|
||||
// chan osc
|
||||
// FM
|
||||
for (int i=0; i<3; 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+3]->data[oscBuf[i+3]->needle++]=fm_lle.o_analog_ch[i]*32767;
|
||||
}
|
||||
|
||||
// DAC
|
||||
int accm1=(short)dacOut[0];
|
||||
|
||||
int outL=((accm1*fmVol)>>8)+fm_lle.o_analog*ssgVol*42;
|
||||
|
||||
if (outL<-32768) outL=-32768;
|
||||
if (outL>32767) outL=32767;
|
||||
|
||||
buf[0][h]=outL;
|
||||
}
|
||||
}
|
||||
|
||||
void DivPlatformYM2203::tick(bool sysTick) {
|
||||
// PSG
|
||||
ay->tick(sysTick);
|
||||
|
@ -984,6 +1144,7 @@ void DivPlatformYM2203::reset() {
|
|||
OPN2_Reset(&fm_nuked);
|
||||
OPN2_SetChipType(&fm_nuked,ym3438_mode_opn);
|
||||
fm->reset();
|
||||
memset(&fm_lle,0,sizeof(fmopna_t));
|
||||
for (int i=0; i<6; i++) {
|
||||
chan[i]=DivPlatformOPN::OPNChannel();
|
||||
chan[i].std.setEngine(parent);
|
||||
|
@ -1001,6 +1162,46 @@ void DivPlatformYM2203::reset() {
|
|||
pendingWrites[i]=-1;
|
||||
}
|
||||
|
||||
if (useCombo==2) {
|
||||
fm_lle.input.cs=1;
|
||||
fm_lle.input.rd=0;
|
||||
fm_lle.input.wr=0;
|
||||
fm_lle.input.a0=0;
|
||||
fm_lle.input.a1=0;
|
||||
fm_lle.input.data=0;
|
||||
fm_lle.input.ad=0;
|
||||
fm_lle.input.da=0;
|
||||
fm_lle.input.dm=0;
|
||||
fm_lle.input.test=1;
|
||||
fm_lle.input.dt0=0;
|
||||
|
||||
fm_lle.input.ic=1;
|
||||
for (size_t h=0; h<576; h++) {
|
||||
FMOPNA_Clock(&fm_lle,0);
|
||||
FMOPNA_Clock(&fm_lle,1);
|
||||
}
|
||||
|
||||
fm_lle.input.ic=0;
|
||||
for (size_t h=0; h<576; h++) {
|
||||
FMOPNA_Clock(&fm_lle,0);
|
||||
FMOPNA_Clock(&fm_lle,1);
|
||||
}
|
||||
|
||||
fm_lle.input.ic=1;
|
||||
for (size_t h=0; h<576; h++) {
|
||||
FMOPNA_Clock(&fm_lle,0);
|
||||
FMOPNA_Clock(&fm_lle,1);
|
||||
}
|
||||
|
||||
dacVal=0;
|
||||
dacVal2=0;
|
||||
dacOut[0]=0;
|
||||
dacOut[1]=0;
|
||||
lastSH=false;
|
||||
lastSH2=false;
|
||||
lastS=false;
|
||||
}
|
||||
|
||||
lastBusy=60;
|
||||
sampleBank=0;
|
||||
|
||||
|
@ -1097,7 +1298,11 @@ void DivPlatformYM2203::setFlags(const DivConfig& flags) {
|
|||
fbAllOps=flags.getBool("fbAllOps",false);
|
||||
ssgVol=flags.getInt("ssgVol",128);
|
||||
fmVol=flags.getInt("fmVol",256);
|
||||
rate=fm->sample_rate(chipClock);
|
||||
if (useCombo==2) {
|
||||
rate=chipClock/(fmDivBase*2);
|
||||
} else {
|
||||
rate=fm->sample_rate(chipClock);
|
||||
}
|
||||
for (int i=0; i<6; i++) {
|
||||
oscBuf[i]->rate=rate;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,9 @@
|
|||
|
||||
#include "fmshared_OPN.h"
|
||||
#include "sound/ymfm/ymfm_opn.h"
|
||||
extern "C" {
|
||||
#include "../../../extern/YM2608-LLE/fmopna_2608.h"
|
||||
}
|
||||
|
||||
#include "ay.h"
|
||||
|
||||
|
@ -46,6 +49,14 @@ class DivPlatformYM2203: public DivPlatformOPN {
|
|||
ymfm::ym2203* fm;
|
||||
ymfm::ym2203::output_data fmout;
|
||||
DivYM2203Interface iface;
|
||||
fmopna_t fm_lle;
|
||||
unsigned int dacVal;
|
||||
unsigned int dacVal2;
|
||||
int dacOut[2];
|
||||
int rssOut[6];
|
||||
bool lastSH;
|
||||
bool lastSH2;
|
||||
bool lastS;
|
||||
|
||||
DivPlatformAY8910* ay;
|
||||
unsigned char sampleBank;
|
||||
|
@ -59,6 +70,7 @@ class DivPlatformYM2203: public DivPlatformOPN {
|
|||
|
||||
void acquire_combo(short** buf, size_t len);
|
||||
void acquire_ymfm(short** buf, size_t len);
|
||||
void acquire_lle(short** buf, size_t len);
|
||||
|
||||
public:
|
||||
void acquire(short** buf, size_t len);
|
||||
|
|
|
@ -494,14 +494,12 @@ static const unsigned char subCycleMap[6]={
|
|||
3, 4, 5, 0, 1, 2
|
||||
};
|
||||
|
||||
// ac_fm_output
|
||||
void DivPlatformYM2608::acquire_lle(short** buf, size_t len) {
|
||||
thread_local int fmOut[6];
|
||||
|
||||
for (size_t h=0; h<len; h++) {
|
||||
bool have0=false;
|
||||
bool have1=false;
|
||||
unsigned char howLong=0;
|
||||
signed char subCycle=0;
|
||||
unsigned char subSubCycle=0;
|
||||
|
||||
|
@ -624,7 +622,6 @@ void DivPlatformYM2608::acquire_lle(short** buf, size_t len) {
|
|||
|
||||
dacVal>>=1;
|
||||
dacVal|=(fm_lle.o_opo&1)<<15;
|
||||
howLong++;
|
||||
|
||||
lastSH=fm_lle.o_sh1;
|
||||
lastSH2=fm_lle.o_sh2;
|
||||
|
@ -654,10 +651,6 @@ void DivPlatformYM2608::acquire_lle(short** buf, size_t len) {
|
|||
if (have0 && have1) break;
|
||||
}
|
||||
|
||||
if (howLong!=48) {
|
||||
logW("NOT 48! %d",howLong);
|
||||
}
|
||||
|
||||
// chan osc
|
||||
// FM
|
||||
for (int i=0; i<6; i++) {
|
||||
|
|
Loading…
Reference in a new issue