ESFM: add "fast" mode
alters ESFMu to add a fast feedback calculation path
This commit is contained in:
parent
3e645e58f2
commit
0ac63d817d
4
extern/ESFMu/README.md
vendored
4
extern/ESFMu/README.md
vendored
|
@ -1,3 +1,7 @@
|
||||||
|
# MODIFIED
|
||||||
|
|
||||||
|
this is a modified version of ESFMu which adds a "fast" mode that uses OPL3 feedback calculation rather than patent workaround calculation (which is slow but accurate).
|
||||||
|
|
||||||
# ESFMu
|
# ESFMu
|
||||||
|
|
||||||
An emulator for the ESS "ESFM" enhanced OPL3 clone, based on Nuke.YKT's **Nuked OPL3** and reverse-engineering efforts from the community.
|
An emulator for the ESS "ESFM" enhanced OPL3 clone, based on Nuke.YKT's **Nuked OPL3** and reverse-engineering efforts from the community.
|
||||||
|
|
9
extern/ESFMu/esfm.c
vendored
9
extern/ESFMu/esfm.c
vendored
|
@ -1776,6 +1776,14 @@ ESFM_process_feedback(esfm_chip *chip)
|
||||||
phase_acc = (uint32_t)(slot->in.phase_acc - phase_offset * 28);
|
phase_acc = (uint32_t)(slot->in.phase_acc - phase_offset * 28);
|
||||||
eg_output = slot->in.eg_output;
|
eg_output = slot->in.eg_output;
|
||||||
|
|
||||||
|
if (chip->fast_mode) {
|
||||||
|
phase_feedback = (slot->in.fb_out0 + slot->in.fb_out1) >> 2;
|
||||||
|
slot->in.fb_out1 = slot->in.fb_out0;
|
||||||
|
phase = phase_feedback >> mod_in_shift;
|
||||||
|
phase += phase_acc >> 9;
|
||||||
|
wave_out = slot->in.fb_out0 = ESFM_envelope_wavegen(waveform, phase, eg_output);
|
||||||
|
phase_acc += phase_offset;
|
||||||
|
} else {
|
||||||
// ASM optimizaions!
|
// ASM optimizaions!
|
||||||
#if defined(__GNUC__) && defined(__x86_64__)
|
#if defined(__GNUC__) && defined(__x86_64__)
|
||||||
asm (
|
asm (
|
||||||
|
@ -1974,6 +1982,7 @@ ESFM_process_feedback(esfm_chip *chip)
|
||||||
phase_acc += phase_offset;
|
phase_acc += phase_offset;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Figure out - is this how the ESFM chip does it, like the
|
// TODO: Figure out - is this how the ESFM chip does it, like the
|
||||||
// patent literally says? (it's really hacky...)
|
// patent literally says? (it's really hacky...)
|
||||||
|
|
6
extern/ESFMu/esfm.h
vendored
6
extern/ESFMu/esfm.h
vendored
|
@ -58,7 +58,7 @@ typedef struct _esfm_channel esfm_channel;
|
||||||
typedef struct _esfm_chip esfm_chip;
|
typedef struct _esfm_chip esfm_chip;
|
||||||
|
|
||||||
|
|
||||||
void ESFM_init (esfm_chip *chip);
|
void ESFM_init (esfm_chip *chip, uint8_t fast);
|
||||||
void ESFM_write_reg (esfm_chip *chip, uint16_t address, uint8_t data);
|
void ESFM_write_reg (esfm_chip *chip, uint16_t address, uint8_t data);
|
||||||
void ESFM_write_reg_buffered (esfm_chip *chip, uint16_t address, uint8_t data);
|
void ESFM_write_reg_buffered (esfm_chip *chip, uint16_t address, uint8_t data);
|
||||||
void ESFM_write_reg_buffered_fast (esfm_chip *chip, uint16_t address, uint8_t data);
|
void ESFM_write_reg_buffered_fast (esfm_chip *chip, uint16_t address, uint8_t data);
|
||||||
|
@ -148,6 +148,8 @@ typedef struct _esfm_slot_internal
|
||||||
uint16 eg_delay_counter;
|
uint16 eg_delay_counter;
|
||||||
uint16 eg_delay_counter_compare;
|
uint16 eg_delay_counter_compare;
|
||||||
|
|
||||||
|
uint16 fb_out0;
|
||||||
|
uint16 fb_out1;
|
||||||
} esfm_slot_internal;
|
} esfm_slot_internal;
|
||||||
|
|
||||||
struct _esfm_slot
|
struct _esfm_slot
|
||||||
|
@ -270,6 +272,8 @@ struct _esfm_chip
|
||||||
size_t write_buf_start;
|
size_t write_buf_start;
|
||||||
size_t write_buf_end;
|
size_t write_buf_end;
|
||||||
uint64_t write_buf_timestamp;
|
uint64_t write_buf_timestamp;
|
||||||
|
|
||||||
|
flag fast_mode;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
3
extern/ESFMu/esfm_registers.c
vendored
3
extern/ESFMu/esfm_registers.c
vendored
|
@ -948,7 +948,7 @@ ESFM_set_mode (esfm_chip *chip, bool native_mode)
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
void
|
void
|
||||||
ESFM_init (esfm_chip *chip)
|
ESFM_init (esfm_chip *chip, uint8_t fast)
|
||||||
{
|
{
|
||||||
esfm_slot *slot;
|
esfm_slot *slot;
|
||||||
esfm_channel *channel;
|
esfm_channel *channel;
|
||||||
|
@ -999,5 +999,6 @@ ESFM_init (esfm_chip *chip)
|
||||||
}
|
}
|
||||||
|
|
||||||
chip->lfsr = 1;
|
chip->lfsr = 1;
|
||||||
|
chip->fast_mode = fast;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -649,6 +649,11 @@ void DivDispatchContainer::init(DivSystem sys, DivEngine* eng, int chanCount, do
|
||||||
break;
|
break;
|
||||||
case DIV_SYSTEM_ESFM:
|
case DIV_SYSTEM_ESFM:
|
||||||
dispatch=new DivPlatformESFM;
|
dispatch=new DivPlatformESFM;
|
||||||
|
if (isRender) {
|
||||||
|
((DivPlatformESFM*)dispatch)->setFast(eng->getConfInt("esfmCoreRender",0));
|
||||||
|
} else {
|
||||||
|
((DivPlatformESFM*)dispatch)->setFast(eng->getConfInt("esfmCore",0));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case DIV_SYSTEM_POWERNOISE:
|
case DIV_SYSTEM_POWERNOISE:
|
||||||
dispatch=new DivPlatformPowerNoise;
|
dispatch=new DivPlatformPowerNoise;
|
||||||
|
|
|
@ -983,7 +983,7 @@ int DivPlatformESFM::getRegisterPoolSize() {
|
||||||
void DivPlatformESFM::reset() {
|
void DivPlatformESFM::reset() {
|
||||||
while (!writes.empty()) writes.pop();
|
while (!writes.empty()) writes.pop();
|
||||||
|
|
||||||
ESFM_init(&chip);
|
ESFM_init(&chip,isFast?1:0);
|
||||||
// set chip to native mode
|
// set chip to native mode
|
||||||
ESFM_write_reg(&chip, 0x105, 0x80);
|
ESFM_write_reg(&chip, 0x105, 0x80);
|
||||||
// ensure NTS bit in register 0x408 is reset, for smooth envelope rate scaling
|
// ensure NTS bit in register 0x408 is reset, for smooth envelope rate scaling
|
||||||
|
@ -1053,6 +1053,10 @@ void DivPlatformESFM::setFlags(const DivConfig& flags) {
|
||||||
rate=chipClock/288.0;
|
rate=chipClock/288.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DivPlatformESFM::setFast(bool fast) {
|
||||||
|
isFast=fast;
|
||||||
|
}
|
||||||
|
|
||||||
int DivPlatformESFM::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) {
|
int DivPlatformESFM::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) {
|
||||||
parent=p;
|
parent=p;
|
||||||
dumpWrites=false;
|
dumpWrites=false;
|
||||||
|
|
|
@ -120,6 +120,7 @@ class DivPlatformESFM: public DivDispatch {
|
||||||
};
|
};
|
||||||
FixedQueue<QueuedWrite,2048> writes;
|
FixedQueue<QueuedWrite,2048> writes;
|
||||||
esfm_chip chip;
|
esfm_chip chip;
|
||||||
|
bool isFast;
|
||||||
|
|
||||||
unsigned char regPool[ESFM_REG_POOL_SIZE];
|
unsigned char regPool[ESFM_REG_POOL_SIZE];
|
||||||
short oldWrites[ESFM_REG_POOL_SIZE];
|
short oldWrites[ESFM_REG_POOL_SIZE];
|
||||||
|
@ -201,6 +202,7 @@ class DivPlatformESFM: public DivDispatch {
|
||||||
void poke(unsigned int addr, unsigned short val);
|
void poke(unsigned int addr, unsigned short val);
|
||||||
void poke(std::vector<DivRegWrite>& wlist);
|
void poke(std::vector<DivRegWrite>& wlist);
|
||||||
void setFlags(const DivConfig& flags);
|
void setFlags(const DivConfig& flags);
|
||||||
|
void setFast(bool fast);
|
||||||
int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags);
|
int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags);
|
||||||
void quit();
|
void quit();
|
||||||
~DivPlatformESFM();
|
~DivPlatformESFM();
|
||||||
|
|
|
@ -216,7 +216,7 @@ const char* aboutLine[]={
|
||||||
"adpcm by superctr",
|
"adpcm by superctr",
|
||||||
"Nuked-OPL3/OPLL/OPM/OPN2/PSG by nukeykt",
|
"Nuked-OPL3/OPLL/OPM/OPN2/PSG by nukeykt",
|
||||||
"YM3812-LLE, YMF262-LLE and YMF276-LLE by nukeykt",
|
"YM3812-LLE, YMF262-LLE and YMF276-LLE by nukeykt",
|
||||||
"ESFMu by Kagamiin~",
|
"ESFMu (modified version) by Kagamiin~",
|
||||||
"ymfm by Aaron Giles",
|
"ymfm by Aaron Giles",
|
||||||
"MAME SN76496 by Nicola Salmoria",
|
"MAME SN76496 by Nicola Salmoria",
|
||||||
"MAME AY-3-8910 by Couriersud",
|
"MAME AY-3-8910 by Couriersud",
|
||||||
|
|
|
@ -350,7 +350,7 @@ void FurnaceGUI::renderFMPreviewESFM(const DivInstrumentFM& params, const DivIns
|
||||||
bool mult0=false;
|
bool mult0=false;
|
||||||
|
|
||||||
if (pos==0) {
|
if (pos==0) {
|
||||||
ESFM_init((esfm_chip*)fmPreviewESFM);
|
ESFM_init((esfm_chip*)fmPreviewESFM,0);
|
||||||
// set native mode
|
// set native mode
|
||||||
ESFM_WRITE(0x105, 0x80);
|
ESFM_WRITE(0x105, 0x80);
|
||||||
|
|
||||||
|
|
|
@ -1638,6 +1638,7 @@ class FurnaceGUI {
|
||||||
int opnCore;
|
int opnCore;
|
||||||
int opl2Core;
|
int opl2Core;
|
||||||
int opl3Core;
|
int opl3Core;
|
||||||
|
int esfmCore;
|
||||||
int arcadeCoreRender;
|
int arcadeCoreRender;
|
||||||
int ym2612CoreRender;
|
int ym2612CoreRender;
|
||||||
int snCoreRender;
|
int snCoreRender;
|
||||||
|
@ -1648,6 +1649,7 @@ class FurnaceGUI {
|
||||||
int opnCoreRender;
|
int opnCoreRender;
|
||||||
int opl2CoreRender;
|
int opl2CoreRender;
|
||||||
int opl3CoreRender;
|
int opl3CoreRender;
|
||||||
|
int esfmCoreRender;
|
||||||
int pcSpeakerOutMethod;
|
int pcSpeakerOutMethod;
|
||||||
String yrw801Path;
|
String yrw801Path;
|
||||||
String tg100Path;
|
String tg100Path;
|
||||||
|
@ -1843,6 +1845,7 @@ class FurnaceGUI {
|
||||||
opnCore(1),
|
opnCore(1),
|
||||||
opl2Core(0),
|
opl2Core(0),
|
||||||
opl3Core(0),
|
opl3Core(0),
|
||||||
|
esfmCore(0),
|
||||||
arcadeCoreRender(1),
|
arcadeCoreRender(1),
|
||||||
ym2612CoreRender(0),
|
ym2612CoreRender(0),
|
||||||
snCoreRender(0),
|
snCoreRender(0),
|
||||||
|
@ -1853,6 +1856,7 @@ class FurnaceGUI {
|
||||||
opnCoreRender(1),
|
opnCoreRender(1),
|
||||||
opl2CoreRender(0),
|
opl2CoreRender(0),
|
||||||
opl3CoreRender(0),
|
opl3CoreRender(0),
|
||||||
|
esfmCoreRender(0),
|
||||||
pcSpeakerOutMethod(0),
|
pcSpeakerOutMethod(0),
|
||||||
yrw801Path(""),
|
yrw801Path(""),
|
||||||
tg100Path(""),
|
tg100Path(""),
|
||||||
|
|
|
@ -169,6 +169,11 @@ const char* opl3Cores[]={
|
||||||
"YMF262-LLE"
|
"YMF262-LLE"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const char* esfmCores[]={
|
||||||
|
"ESFMu",
|
||||||
|
"ESFMu (fast)"
|
||||||
|
};
|
||||||
|
|
||||||
const char* pcspkrOutMethods[]={
|
const char* pcspkrOutMethods[]={
|
||||||
"evdev SND_TONE",
|
"evdev SND_TONE",
|
||||||
"KIOCSOUND on /dev/tty1",
|
"KIOCSOUND on /dev/tty1",
|
||||||
|
@ -1629,6 +1634,17 @@ void FurnaceGUI::drawSettings() {
|
||||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||||
if (ImGui::Combo("##OPL3CoreRender",&settings.opl3CoreRender,opl3Cores,3)) settingsChanged=true;
|
if (ImGui::Combo("##OPL3CoreRender",&settings.opl3CoreRender,opl3Cores,3)) settingsChanged=true;
|
||||||
|
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::AlignTextToFramePadding();
|
||||||
|
ImGui::Text("ESFM");
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||||
|
if (ImGui::Combo("##ESFMCore",&settings.esfmCore,esfmCores,2)) settingsChanged=true;
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||||
|
if (ImGui::Combo("##ESFMCoreRender",&settings.esfmCoreRender,esfmCores,2)) settingsChanged=true;
|
||||||
|
|
||||||
ImGui::EndTable();
|
ImGui::EndTable();
|
||||||
}
|
}
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
@ -4108,6 +4124,7 @@ void FurnaceGUI::readConfig(DivConfig& conf, FurnaceGUISettingGroups groups) {
|
||||||
settings.opnCore=conf.getInt("opnCore",1);
|
settings.opnCore=conf.getInt("opnCore",1);
|
||||||
settings.opl2Core=conf.getInt("opl2Core",0);
|
settings.opl2Core=conf.getInt("opl2Core",0);
|
||||||
settings.opl3Core=conf.getInt("opl3Core",0);
|
settings.opl3Core=conf.getInt("opl3Core",0);
|
||||||
|
settings.esfmCore=conf.getInt("esfmCore",0);
|
||||||
settings.arcadeCoreRender=conf.getInt("arcadeCoreRender",1);
|
settings.arcadeCoreRender=conf.getInt("arcadeCoreRender",1);
|
||||||
settings.ym2612CoreRender=conf.getInt("ym2612CoreRender",0);
|
settings.ym2612CoreRender=conf.getInt("ym2612CoreRender",0);
|
||||||
settings.snCoreRender=conf.getInt("snCoreRender",0);
|
settings.snCoreRender=conf.getInt("snCoreRender",0);
|
||||||
|
@ -4118,6 +4135,7 @@ void FurnaceGUI::readConfig(DivConfig& conf, FurnaceGUISettingGroups groups) {
|
||||||
settings.opnCoreRender=conf.getInt("opnCoreRender",1);
|
settings.opnCoreRender=conf.getInt("opnCoreRender",1);
|
||||||
settings.opl2CoreRender=conf.getInt("opl2CoreRender",0);
|
settings.opl2CoreRender=conf.getInt("opl2CoreRender",0);
|
||||||
settings.opl3CoreRender=conf.getInt("opl3CoreRender",0);
|
settings.opl3CoreRender=conf.getInt("opl3CoreRender",0);
|
||||||
|
settings.esfmCoreRender=conf.getInt("esfmCoreRender",0);
|
||||||
|
|
||||||
settings.pcSpeakerOutMethod=conf.getInt("pcSpeakerOutMethod",0);
|
settings.pcSpeakerOutMethod=conf.getInt("pcSpeakerOutMethod",0);
|
||||||
|
|
||||||
|
@ -4146,6 +4164,7 @@ void FurnaceGUI::readConfig(DivConfig& conf, FurnaceGUISettingGroups groups) {
|
||||||
clampSetting(settings.opnCore,0,1);
|
clampSetting(settings.opnCore,0,1);
|
||||||
clampSetting(settings.opl2Core,0,2);
|
clampSetting(settings.opl2Core,0,2);
|
||||||
clampSetting(settings.opl3Core,0,2);
|
clampSetting(settings.opl3Core,0,2);
|
||||||
|
clampSetting(settings.esfmCore,0,1);
|
||||||
clampSetting(settings.arcadeCoreRender,0,1);
|
clampSetting(settings.arcadeCoreRender,0,1);
|
||||||
clampSetting(settings.ym2612CoreRender,0,2);
|
clampSetting(settings.ym2612CoreRender,0,2);
|
||||||
clampSetting(settings.snCoreRender,0,1);
|
clampSetting(settings.snCoreRender,0,1);
|
||||||
|
@ -4156,6 +4175,7 @@ void FurnaceGUI::readConfig(DivConfig& conf, FurnaceGUISettingGroups groups) {
|
||||||
clampSetting(settings.opnCoreRender,0,1);
|
clampSetting(settings.opnCoreRender,0,1);
|
||||||
clampSetting(settings.opl2CoreRender,0,2);
|
clampSetting(settings.opl2CoreRender,0,2);
|
||||||
clampSetting(settings.opl3CoreRender,0,2);
|
clampSetting(settings.opl3CoreRender,0,2);
|
||||||
|
clampSetting(settings.esfmCoreRender,0,1);
|
||||||
clampSetting(settings.pcSpeakerOutMethod,0,4);
|
clampSetting(settings.pcSpeakerOutMethod,0,4);
|
||||||
clampSetting(settings.mainFont,0,6);
|
clampSetting(settings.mainFont,0,6);
|
||||||
clampSetting(settings.patFont,0,6);
|
clampSetting(settings.patFont,0,6);
|
||||||
|
@ -4579,6 +4599,7 @@ void FurnaceGUI::writeConfig(DivConfig& conf, FurnaceGUISettingGroups groups) {
|
||||||
conf.set("opnCore",settings.opnCore);
|
conf.set("opnCore",settings.opnCore);
|
||||||
conf.set("opl2Core",settings.opl2Core);
|
conf.set("opl2Core",settings.opl2Core);
|
||||||
conf.set("opl3Core",settings.opl3Core);
|
conf.set("opl3Core",settings.opl3Core);
|
||||||
|
conf.set("esfmCore",settings.esfmCore);
|
||||||
conf.set("arcadeCoreRender",settings.arcadeCoreRender);
|
conf.set("arcadeCoreRender",settings.arcadeCoreRender);
|
||||||
conf.set("ym2612CoreRender",settings.ym2612CoreRender);
|
conf.set("ym2612CoreRender",settings.ym2612CoreRender);
|
||||||
conf.set("snCoreRender",settings.snCoreRender);
|
conf.set("snCoreRender",settings.snCoreRender);
|
||||||
|
@ -4589,6 +4610,7 @@ void FurnaceGUI::writeConfig(DivConfig& conf, FurnaceGUISettingGroups groups) {
|
||||||
conf.set("opnCoreRender",settings.opnCoreRender);
|
conf.set("opnCoreRender",settings.opnCoreRender);
|
||||||
conf.set("opl2CoreRender",settings.opl2CoreRender);
|
conf.set("opl2CoreRender",settings.opl2CoreRender);
|
||||||
conf.set("opl3CoreRender",settings.opl3CoreRender);
|
conf.set("opl3CoreRender",settings.opl3CoreRender);
|
||||||
|
conf.set("esfmCoreRender",settings.esfmCoreRender);
|
||||||
|
|
||||||
conf.set("pcSpeakerOutMethod",settings.pcSpeakerOutMethod);
|
conf.set("pcSpeakerOutMethod",settings.pcSpeakerOutMethod);
|
||||||
|
|
||||||
|
@ -4629,6 +4651,7 @@ void FurnaceGUI::commitSettings() {
|
||||||
settings.opnCore!=e->getConfInt("opnCore",1) ||
|
settings.opnCore!=e->getConfInt("opnCore",1) ||
|
||||||
settings.opl2Core!=e->getConfInt("opl2Core",0) ||
|
settings.opl2Core!=e->getConfInt("opl2Core",0) ||
|
||||||
settings.opl3Core!=e->getConfInt("opl3Core",0) ||
|
settings.opl3Core!=e->getConfInt("opl3Core",0) ||
|
||||||
|
settings.esfmCore!=e->getConfInt("esfmCore",0) ||
|
||||||
settings.arcadeCoreRender!=e->getConfInt("arcadeCoreRender",0) ||
|
settings.arcadeCoreRender!=e->getConfInt("arcadeCoreRender",0) ||
|
||||||
settings.ym2612CoreRender!=e->getConfInt("ym2612CoreRender",0) ||
|
settings.ym2612CoreRender!=e->getConfInt("ym2612CoreRender",0) ||
|
||||||
settings.snCoreRender!=e->getConfInt("snCoreRender",0) ||
|
settings.snCoreRender!=e->getConfInt("snCoreRender",0) ||
|
||||||
|
@ -4639,6 +4662,7 @@ void FurnaceGUI::commitSettings() {
|
||||||
settings.opnCoreRender!=e->getConfInt("opnCoreRender",1) ||
|
settings.opnCoreRender!=e->getConfInt("opnCoreRender",1) ||
|
||||||
settings.opl2CoreRender!=e->getConfInt("opl2CoreRender",0) ||
|
settings.opl2CoreRender!=e->getConfInt("opl2CoreRender",0) ||
|
||||||
settings.opl3CoreRender!=e->getConfInt("opl3CoreRender",0) ||
|
settings.opl3CoreRender!=e->getConfInt("opl3CoreRender",0) ||
|
||||||
|
settings.esfmCoreRender!=e->getConfInt("esfmCoreRender",0) ||
|
||||||
settings.audioQuality!=e->getConfInt("audioQuality",0) ||
|
settings.audioQuality!=e->getConfInt("audioQuality",0) ||
|
||||||
settings.audioHiPass!=e->getConfInt("audioHiPass",1)
|
settings.audioHiPass!=e->getConfInt("audioHiPass",1)
|
||||||
);
|
);
|
||||||
|
|
|
@ -212,7 +212,7 @@ TAParamResult pVersion(String) {
|
||||||
printf("- YM3812-LLE by nukeykt (GPLv2)\n");
|
printf("- YM3812-LLE by nukeykt (GPLv2)\n");
|
||||||
printf("- YMF262-LLE by nukeykt (GPLv2)\n");
|
printf("- YMF262-LLE by nukeykt (GPLv2)\n");
|
||||||
printf("- YMF276-LLE by nukeykt (GPLv2)\n");
|
printf("- YMF276-LLE by nukeykt (GPLv2)\n");
|
||||||
printf("- ESFMu by Kagamiin~ (LGPLv2.1)\n");
|
printf("- ESFMu (modified version) by Kagamiin~ (LGPLv2.1)\n");
|
||||||
printf("- ymfm by Aaron Giles (BSD 3-clause)\n");
|
printf("- ymfm by Aaron Giles (BSD 3-clause)\n");
|
||||||
printf("- adpcm by superctr (public domain)\n");
|
printf("- adpcm by superctr (public domain)\n");
|
||||||
printf("- MAME SN76496 emulation core by Nicola Salmoria (BSD 3-clause)\n");
|
printf("- MAME SN76496 emulation core by Nicola Salmoria (BSD 3-clause)\n");
|
||||||
|
|
Loading…
Reference in a new issue