From 22f612b32a998de6ac0fcb996ddb96bb48ad8740 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sun, 28 Apr 2024 12:57:45 -0500 Subject: [PATCH] YM2608-LLE, part 15 OPNB early progress --- extern/YM2608-LLE/fmopna_impl.c | 3 +- extern/YM2608-LLE/fmopna_impl.h | 2 + src/engine/platform/ym2608.cpp | 1 - src/engine/platform/ym2608.h | 1 - src/engine/platform/ym2610.cpp | 187 ++++++++++++++++++++++++++++- src/engine/platform/ym2610.h | 1 + src/engine/platform/ym2610b.h | 1 + src/engine/platform/ym2610shared.h | 68 ++++++++++- 8 files changed, 259 insertions(+), 5 deletions(-) diff --git a/extern/YM2608-LLE/fmopna_impl.c b/extern/YM2608-LLE/fmopna_impl.c index 187918c39..fa622ed91 100644 --- a/extern/YM2608-LLE/fmopna_impl.c +++ b/extern/YM2608-LLE/fmopna_impl.c @@ -939,7 +939,8 @@ void FMOPNA_2612_Clock(fmopna_2612_t* chip, int clk) #endif ) #ifdef FMOPNA_YM2610 - && (chip->reg_kon_channel[0] & 3) != 0 + // tildearrow: changed to allow YM2610B emulation + && (chip->ym2610b || (chip->reg_kon_channel[0] & 3) != 0) #endif ; diff --git a/extern/YM2608-LLE/fmopna_impl.h b/extern/YM2608-LLE/fmopna_impl.h index 96bd713a4..c076f0145 100644 --- a/extern/YM2608-LLE/fmopna_impl.h +++ b/extern/YM2608-LLE/fmopna_impl.h @@ -930,6 +930,8 @@ typedef struct { int o_pad; int o_pad_d; int o_pa8; + + int ym2610b; #endif #ifndef FMOPNA_YM2612 diff --git a/src/engine/platform/ym2608.cpp b/src/engine/platform/ym2608.cpp index b54143839..4c240e556 100644 --- a/src/engine/platform/ym2608.cpp +++ b/src/engine/platform/ym2608.cpp @@ -1763,7 +1763,6 @@ void DivPlatformYM2608::reset() { lastS=false; cas=0; ras=0; - adReadCount=0; adMemAddr=0; } diff --git a/src/engine/platform/ym2608.h b/src/engine/platform/ym2608.h index c7a6ba252..2b92ae5e0 100644 --- a/src/engine/platform/ym2608.h +++ b/src/engine/platform/ym2608.h @@ -63,7 +63,6 @@ class DivPlatformYM2608: public DivPlatformOPN { bool lastS; unsigned char cas, ras, rssCycle, rssSubCycle; unsigned int adMemAddr; - int adReadCount; unsigned char* adpcmBMem; size_t adpcmBMemLen; diff --git a/src/engine/platform/ym2610.cpp b/src/engine/platform/ym2610.cpp index 79d5169ad..45b881986 100644 --- a/src/engine/platform/ym2610.cpp +++ b/src/engine/platform/ym2610.cpp @@ -233,7 +233,9 @@ const char** DivPlatformYM2610::getRegisterSheet() { } void DivPlatformYM2610::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); @@ -421,6 +423,189 @@ void DivPlatformYM2610::acquire_ymfm(short** buf, size_t len) { } } +static const unsigned char subCycleMap[6]={ + 4, 2, 3, 5, 0, 1 +}; + +void DivPlatformYM2610::acquire_lle(short** buf, size_t len) { + thread_local int fmOut[6]; + + for (size_t h=0; h0) { + 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.addrOrVal) { + fm_lle.input.cs=0; + fm_lle.input.rd=1; + fm_lle.input.wr=0; + fm_lle.input.a1=w.addr>>8; + 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=w.addr>>8; + 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_2610_Clock(&fm_lle,0); + FMOPNA_2610_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 (fm_lle.rss_eclk1) { + if (++rssSubCycle>=24) { + rssSubCycle=0; + rssOut[rssCycle]=(short)fm_lle.last_rss_sample; + if (++rssCycle>=6) rssCycle=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; + + // ADPCM data bus + if (!fm_lle.o_roe) { + fm_lle.input.rad=adpcmAMem[adMemAddrA&0xffffff]; + } else { + if (!fm_lle.o_rmpx && rmpx) { + adMemAddrA&=~0x3ff; + adMemAddrA=(fm_lle.o_rad&0xff)|(fm_lle.o_ra8<<8); + } + if (fm_lle.o_rmpx && !rmpx) { + adMemAddrA&=0x3ff; + adMemAddrA=((fm_lle.o_rad&0xff)|(fm_lle.o_ra8<<8)|(fm_lle.o_ra20<<10))<<10; + } + rmpx=fm_lle.o_rmpx; + } + + if (have0 && have1) break; + } + + // chan osc + // FM + for (int i=0; i<4; 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+4]->data[oscBuf[i+4]->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[7+i]->data[oscBuf[7+i]->needle++]=rssOut[i]; + } + // ADPCM + oscBuf[13]->data[oscBuf[13]->needle++]=fm_lle.ac_ad_output; + + // DAC + int accm1=(short)dacOut[0]; + int accm2=(short)dacOut[1]; + + int outL=((accm1*fmVol)>>8)+fm_lle.o_analog*ssgVol*42; + int outR=((accm2*fmVol)>>8)+fm_lle.o_analog*ssgVol*42; + + if (outL<-32768) outL=-32768; + if (outL>32767) outL=32767; + if (outR<-32768) outR=-32768; + if (outR>32767) outR=32767; + + buf[0][h]=outL; + buf[1][h]=outR; + } +} + void DivPlatformYM2610::tick(bool sysTick) { // FM for (int i=0; i +extern "C" { +#include "../../../extern/YM2608-LLE/fmopna_2610.h" +} #define CHIP_FREQBASE fmFreqBase #define CHIP_DIVIDER fmDivBase @@ -54,6 +57,17 @@ class DivPlatformYM2610Base: public DivPlatformOPN { ymfm::ym2610b* fm; ymfm::ym2610b::output_data fmout; DivPlatformAY8910* ay; + fmopna_2610_t fm_lle; + unsigned int dacVal; + unsigned int dacVal2; + int dacOut[2]; + int rssOut[6]; + bool lastSH; + bool lastSH2; + bool lastS; + unsigned char rmpx, pmpx, rssCycle, rssSubCycle; + unsigned int adMemAddrA; + unsigned int adMemAddrB; unsigned char* adpcmAMem; size_t adpcmAMemLen; @@ -102,6 +116,54 @@ class DivPlatformYM2610Base: public DivPlatformOPN { OPN2_Reset(&fm_nuked); OPN2_SetChipType(&fm_nuked,ym3438_mode_opn); + 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.rad=0; + fm_lle.input.pad=0; + fm_lle.input.test=1; + + fm_lle.input.ic=1; + for (size_t h=0; h<576; h++) { + FMOPNA_2610_Clock(&fm_lle,0); + FMOPNA_2610_Clock(&fm_lle,1); + } + + fm_lle.input.ic=0; + for (size_t h=0; h<576; h++) { + FMOPNA_2610_Clock(&fm_lle,0); + FMOPNA_2610_Clock(&fm_lle,1); + } + + fm_lle.input.ic=1; + for (size_t h=0; h<576; h++) { + FMOPNA_2610_Clock(&fm_lle,0); + FMOPNA_2610_Clock(&fm_lle,1); + } + + for (int i=0; i<6; i++) { + rssOut[i]=0; + } + + dacVal=0; + dacVal2=0; + dacOut[0]=0; + dacOut[1]=0; + lastSH=0; + lastSH2=0; + lastS=0; + rmpx=0; + pmpx=0; + rssCycle=0; + rssSubCycle=0; + adMemAddrA=0; + adMemAddrB=0; + } + ay->reset(); ay->getRegisterWrites().clear(); ay->flushWrites(); @@ -247,7 +309,11 @@ class DivPlatformYM2610Base: public DivPlatformOPN { 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/144; + } else { + rate=fm->sample_rate(chipClock); + } for (int i=0; i<16; i++) { oscBuf[i]->rate=rate; }