Merge pull request #825 from tildearrow/ymf289b
Prepare to YMF289B OPL3-L support
This commit is contained in:
commit
7be0079c62
|
@ -1,4 +1,4 @@
|
|||
# modification disclaimer
|
||||
|
||||
this is a modified version of Nuked-OPL3 which implements channel muting in the core.
|
||||
this is a modified version of Nuked-OPL3 which implements channel muting in the core, and resampling function.
|
||||
see [this issue](https://github.com/tildearrow/furnace/issues/414) for more information.
|
||||
|
|
|
@ -1362,6 +1362,11 @@ void OPL3_Reset(opl3_chip *chip, uint32_t samplerate)
|
|||
#endif
|
||||
}
|
||||
|
||||
void OPL3_Resample(opl3_chip *chip, uint32_t samplerate)
|
||||
{
|
||||
chip->rateratio = (samplerate << RSM_FRAC) / 49716;
|
||||
}
|
||||
|
||||
void OPL3_WriteReg(opl3_chip *chip, uint16_t reg, uint8_t v)
|
||||
{
|
||||
uint8_t high = (reg >> 8) & 0x01;
|
||||
|
|
|
@ -158,6 +158,7 @@ struct _opl3_chip {
|
|||
void OPL3_Generate(opl3_chip *chip, int16_t *buf);
|
||||
void OPL3_GenerateResampled(opl3_chip *chip, int16_t *buf);
|
||||
void OPL3_Reset(opl3_chip *chip, uint32_t samplerate);
|
||||
void OPL3_Resample(opl3_chip *chip, uint32_t samplerate);
|
||||
void OPL3_WriteReg(opl3_chip *chip, uint16_t reg, uint8_t v);
|
||||
void OPL3_WriteRegBuffered(opl3_chip *chip, uint16_t reg, uint8_t v);
|
||||
void OPL3_GenerateStream(opl3_chip *chip, int16_t *sndptr, uint32_t numsamples);
|
||||
|
|
|
@ -275,11 +275,20 @@ void DivPlatformOPL::acquire_nuked(short** buf, size_t len) {
|
|||
if (os[3]>32767) os[3]=32767;
|
||||
|
||||
buf[0][h]=os[0];
|
||||
if (oplType==3 || oplType==759) {
|
||||
if (totalOutputs>1) {
|
||||
buf[1][h]=os[1];
|
||||
}
|
||||
if (totalOutputs>2) {
|
||||
buf[2][h]=os[2];
|
||||
}
|
||||
if (totalOutputs>3) {
|
||||
buf[3][h]=os[3];
|
||||
}
|
||||
if (totalOutputs==6) {
|
||||
// placeholder for OPL4
|
||||
buf[4][h]=0;
|
||||
buf[5][h]=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1590,7 +1599,7 @@ void DivPlatformOPL::reset() {
|
|||
}
|
||||
*/
|
||||
if (downsample) {
|
||||
const unsigned int downsampledRate=(unsigned int)((double)rate*rate/chipRateBase);
|
||||
const unsigned int downsampledRate=(unsigned int)((double)rate*round(COLOR_NTSC/72.0)/(double)chipRateBase);
|
||||
OPL3_Reset(&fm,downsampledRate);
|
||||
} else {
|
||||
OPL3_Reset(&fm,rate);
|
||||
|
@ -1671,7 +1680,7 @@ void DivPlatformOPL::reset() {
|
|||
}
|
||||
|
||||
int DivPlatformOPL::getOutputCount() {
|
||||
return (oplType==3 || oplType==759)?4:1;
|
||||
return totalOutputs;
|
||||
}
|
||||
|
||||
bool DivPlatformOPL::keyOffAffectsArp(int ch) {
|
||||
|
@ -1730,6 +1739,7 @@ void DivPlatformOPL::setOPLType(int type, bool drums) {
|
|||
if (type==8950) {
|
||||
adpcmChan=drums?11:9;
|
||||
}
|
||||
totalOutputs=1;
|
||||
break;
|
||||
case 3: case 4: case 759:
|
||||
slotsNonDrums=slotsOPL3;
|
||||
|
@ -1748,6 +1758,7 @@ void DivPlatformOPL::setOPLType(int type, bool drums) {
|
|||
chipFreqBase=32768*684;
|
||||
downsample=true;
|
||||
}
|
||||
totalOutputs=(type==4)?6:4;
|
||||
break;
|
||||
}
|
||||
chipType=type;
|
||||
|
@ -1829,14 +1840,36 @@ void DivPlatformOPL::setFlags(const DivConfig& flags) {
|
|||
case 0x04:
|
||||
chipClock=15000000.0;
|
||||
break;
|
||||
case 0x05:
|
||||
chipClock=33868800.0;
|
||||
break;
|
||||
default:
|
||||
chipClock=COLOR_NTSC*4.0;
|
||||
break;
|
||||
}
|
||||
CHECK_CUSTOM_CLOCK;
|
||||
rate=chipClock/288;
|
||||
chipRateBase=rate;
|
||||
compatPan=flags.getBool("compatPan",false);
|
||||
switch (flags.getInt("chipType",0)) {
|
||||
case 1: // YMF289B
|
||||
chipFreqBase=32768*684;
|
||||
rate=chipClock/768;
|
||||
chipRateBase=chipClock/684;
|
||||
downsample=true;
|
||||
totalOutputs=2; // Stereo output only
|
||||
break;
|
||||
default: // YMF262
|
||||
chipFreqBase=32768*288;
|
||||
rate=chipClock/288;
|
||||
chipRateBase=rate;
|
||||
downsample=false;
|
||||
totalOutputs=4;
|
||||
break;
|
||||
}
|
||||
if (downsample) {
|
||||
const unsigned int downsampledRate=(unsigned int)((double)rate*round(COLOR_NTSC/72.0)/(double)chipRateBase);
|
||||
OPL3_Resample(&fm,downsampledRate);
|
||||
} else {
|
||||
OPL3_Resample(&fm,rate);
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
switch (flags.getInt("clockSel",0)) {
|
||||
|
@ -1860,6 +1893,7 @@ void DivPlatformOPL::setFlags(const DivConfig& flags) {
|
|||
chipClock=rate*288;
|
||||
break;
|
||||
}
|
||||
compatPan=flags.getBool("compatPan",false);
|
||||
|
||||
for (int i=0; i<20; i++) {
|
||||
oscBuf[i]->rate=rate;
|
||||
|
|
|
@ -82,7 +82,7 @@ class DivPlatformOPL: public DivDispatch {
|
|||
const unsigned short* chanMap;
|
||||
const unsigned char* outChanMap;
|
||||
int chipFreqBase, chipRateBase;
|
||||
int delay, chipType, oplType, chans, melodicChans, totalChans, adpcmChan, sampleBank;
|
||||
int delay, chipType, oplType, chans, melodicChans, totalChans, adpcmChan, sampleBank, totalOutputs;
|
||||
unsigned char lastBusy;
|
||||
unsigned char drumState;
|
||||
unsigned char drumVol[5];
|
||||
|
|
|
@ -2334,6 +2334,22 @@ void FurnaceGUI::initSystemPresets() {
|
|||
CH(DIV_SYSTEM_OPL3_DRUMS, 1.0f, 0, "")
|
||||
}
|
||||
);
|
||||
ENTRY(
|
||||
"Yamaha YMF289B (OPL3-L)", {
|
||||
CH(DIV_SYSTEM_OPL3, 1.0f, 0,
|
||||
"clockSel=5\n"
|
||||
"chipType=1\n"
|
||||
)
|
||||
}
|
||||
);
|
||||
ENTRY(
|
||||
"Yamaha YMF289B (drums mode)", {
|
||||
CH(DIV_SYSTEM_OPL3_DRUMS, 1.0f, 0,
|
||||
"clockSel=5\n"
|
||||
"chipType=1\n"
|
||||
)
|
||||
}
|
||||
);
|
||||
if (settings.hiddenSystems) {
|
||||
ENTRY(
|
||||
"Yamaha YMU759 (MA-2)", {
|
||||
|
|
|
@ -1478,6 +1478,7 @@ bool FurnaceGUI::drawSysConf(int chan, DivSystem type, DivConfig& flags, bool mo
|
|||
case DIV_SYSTEM_OPL3:
|
||||
case DIV_SYSTEM_OPL3_DRUMS: {
|
||||
int clockSel=flags.getInt("clockSel",0);
|
||||
int chipType=flags.getInt("chipType",0);
|
||||
bool compatPan=flags.getBool("compatPan",false);
|
||||
|
||||
ImGui::Text("Clock rate:");
|
||||
|
@ -1502,6 +1503,19 @@ bool FurnaceGUI::drawSysConf(int chan, DivSystem type, DivConfig& flags, bool mo
|
|||
clockSel=4;
|
||||
altered=true;
|
||||
}
|
||||
if (ImGui::RadioButton("33.8688MHz (OPL3-L)",clockSel==5)) {
|
||||
clockSel=5;
|
||||
altered=true;
|
||||
}
|
||||
ImGui::Text("Chip type:");
|
||||
if (ImGui::RadioButton("OPL3 (YMF262)",chipType==0)) {
|
||||
chipType=0;
|
||||
altered=true;
|
||||
}
|
||||
if (ImGui::RadioButton("OPL3-L (YMF289B)",chipType==1)) {
|
||||
chipType=1;
|
||||
altered=true;
|
||||
}
|
||||
ImGui::Unindent();
|
||||
|
||||
if (ImGui::Checkbox("Compatible panning (0800)",&compatPan)) {
|
||||
|
@ -1511,6 +1525,7 @@ bool FurnaceGUI::drawSysConf(int chan, DivSystem type, DivConfig& flags, bool mo
|
|||
if (altered) {
|
||||
e->lockSave([&]() {
|
||||
flags.set("clockSel",clockSel);
|
||||
flags.set("chipType",chipType);
|
||||
flags.set("compatPan",compatPan);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -156,9 +156,15 @@ const char* FurnaceGUI::getSystemPartNumber(DivSystem sys, DivConfig& flags) {
|
|||
return "YM3812";
|
||||
break;
|
||||
case DIV_SYSTEM_OPL3:
|
||||
case DIV_SYSTEM_OPL3_DRUMS:
|
||||
return "YMF262";
|
||||
case DIV_SYSTEM_OPL3_DRUMS:{
|
||||
int chipType=flags.getInt("chipType",0);
|
||||
if (chipType==1) {
|
||||
return "YMF289B";
|
||||
} else {
|
||||
return "YMF262";
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_SYSTEM_OPL4:
|
||||
case DIV_SYSTEM_OPL4_DRUMS:
|
||||
return "YMF278";
|
||||
|
|
Loading…
Reference in New Issue