Merge branch 'master' of https://github.com/tildearrow/furnace into tildearrow-master
This commit is contained in:
commit
5d6dcd60bf
138 changed files with 203 additions and 45 deletions
|
|
@ -155,43 +155,76 @@ void DivPlatformAY8910::runDAC() {
|
|||
}
|
||||
|
||||
void DivPlatformAY8910::runTFX() {
|
||||
if (selCore) return;
|
||||
/*
|
||||
developer's note: if you are checking for intellivision
|
||||
make sure to add "&& selCore"
|
||||
because for some reason, the register remap doesn't work
|
||||
when the user uses AtomicSSG core
|
||||
*/
|
||||
int timerPeriod, output;
|
||||
for (int i=0; i<3; i++) {
|
||||
if (chan[i].active && (chan[i].curPSGMode.val&16) && !(chan[i].curPSGMode.val&8) && chan[i].tfx.mode!=-1) {
|
||||
if (chan[i].tfx.mode == -1 && !isMuted[i]) {
|
||||
/*
|
||||
bug: if in the timer FX macro the user enables
|
||||
and then disables PWM while there is no volume macro
|
||||
there is now a random chance that the resulting output
|
||||
is silent or has volume set incorrectly
|
||||
i've tried to implement a fix, but it seems to be
|
||||
ineffective, so...
|
||||
TODO: actually implement a proper fix
|
||||
*/
|
||||
if (intellivision && chan[i].curPSGMode.getEnvelope()) {
|
||||
immWrite(0x08+i,(chan[i].outVol&0xc)<<2);
|
||||
continue;
|
||||
} else {
|
||||
immWrite(0x08+i,(chan[i].outVol&15)|((chan[i].curPSGMode.getEnvelope())<<2));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
chan[i].tfx.counter += 1;
|
||||
if (chan[i].tfx.counter >= chan[i].tfx.period && chan[i].tfx.mode == 0) {
|
||||
chan[i].tfx.counter = 0;
|
||||
chan[i].tfx.out ^= 1;
|
||||
output = MAX(0, ((chan[i].tfx.out) ? (chan[i].outVol&15) : (chan[i].tfx.lowBound-(15-chan[i].outVol))));
|
||||
output &= 15;
|
||||
output = ((chan[i].tfx.out) ? chan[i].outVol : (chan[i].tfx.lowBound-(15-chan[i].outVol)));
|
||||
// TODO: fix this stupid crackling noise that happens
|
||||
// everytime the volume changes
|
||||
output = (output <= 0) ? 0 : output; // underflow
|
||||
output = (output >= 15) ? 15 : output; // overflow
|
||||
output &= 15; // i don't know if i need this but i'm too scared to remove it
|
||||
if (!isMuted[i]) {
|
||||
immWrite(0x08+i,output|(chan[i].curPSGMode.getEnvelope()<<2));
|
||||
if (intellivision && selCore) {
|
||||
immWrite(0x0b+i,(output&0xc)<<2);
|
||||
} else {
|
||||
immWrite(0x08+i,output|(chan[i].curPSGMode.getEnvelope()<<2));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (chan[i].tfx.counter >= chan[i].tfx.period && chan[i].tfx.mode == 1) {
|
||||
chan[i].tfx.counter = 0;
|
||||
if (!isMuted[i]) {
|
||||
immWrite(0xd, ayEnvMode);
|
||||
if (intellivision && selCore) {
|
||||
immWrite(0xa, ayEnvMode);
|
||||
} else {
|
||||
immWrite(0xd, ayEnvMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (chan[i].tfx.counter >= chan[i].tfx.period && chan[i].tfx.mode == 2) {
|
||||
chan[i].tfx.counter = 0;
|
||||
}
|
||||
if (chan[i].tfx.mode == -1 && !isMuted[i]) {
|
||||
if (intellivision && chan[i].curPSGMode.getEnvelope()) {
|
||||
immWrite(0x08+i,(chan[i].outVol&0xc)<<2);
|
||||
} else {
|
||||
immWrite(0x08+i,(chan[i].outVol&15)|((chan[i].curPSGMode.getEnvelope())<<2));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (chan[i].tfx.num > 0) {
|
||||
timerPeriod = chan[i].freq*chan[i].tfx.den/chan[i].tfx.num;
|
||||
} else {
|
||||
timerPeriod = chan[i].freq*chan[i].tfx.den;
|
||||
}
|
||||
timerPeriod = chan[i].freq*chan[i].tfx.den/chan[i].tfx.num;
|
||||
} else {
|
||||
timerPeriod = chan[i].freq*chan[i].tfx.den;
|
||||
}
|
||||
if (chan[i].tfx.num > 0 && chan[i].tfx.den > 0) chan[i].tfx.period=timerPeriod+chan[i].tfx.offset;
|
||||
// stupid pitch correction because:
|
||||
// YM2149 half-clock and Sunsoft 5B: timers run an octave too high
|
||||
// on AtomicSSG core timers run 2 octaves too high
|
||||
if (clockSel || sunsoft) chan[i].tfx.period = chan[i].tfx.period * 2;
|
||||
if (selCore) chan[i].tfx.period = chan[i].tfx.period * 4;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -388,6 +421,7 @@ void DivPlatformAY8910::tick(bool sysTick) {
|
|||
if (chan[i].std.phaseReset.had) {
|
||||
if (chan[i].std.phaseReset.val==1) {
|
||||
chan[i].tfx.counter = 0;
|
||||
chan[i].tfx.out = 0;
|
||||
if (chan[i].nextPSGMode.val&8) {
|
||||
if (dumpWrites) addWrite(0xffff0002+(i<<8),0);
|
||||
if (chan[i].dac.sample<0 || chan[i].dac.sample>=parent->song.sampleLen) {
|
||||
|
|
@ -726,12 +760,10 @@ int DivPlatformAY8910::dispatch(DivCommand c) {
|
|||
break;
|
||||
}
|
||||
case DIV_CMD_STD_NOISE_MODE:
|
||||
if (c.value&0xf0 && !(chan[c.chan].nextPSGMode.val&8)) {
|
||||
chan[c.chan].nextPSGMode.val|=16;
|
||||
chan[c.chan].tfx.mode = (c.value&3);
|
||||
}
|
||||
if (!(chan[c.chan].nextPSGMode.val&8)) {
|
||||
if (c.value<16) {
|
||||
chan[c.chan].nextPSGMode.val|=16;
|
||||
chan[c.chan].tfx.mode=(((c.value&0xf0)>>4)&3)-1;
|
||||
if ((c.value&15)<16) {
|
||||
chan[c.chan].nextPSGMode.val=(c.value+1)&7;
|
||||
chan[c.chan].nextPSGMode.val|=chan[c.chan].curPSGMode.val&16;
|
||||
if (chan[c.chan].active) {
|
||||
|
|
@ -805,9 +837,16 @@ int DivPlatformAY8910::dispatch(DivCommand c) {
|
|||
updateOutSel(true);
|
||||
immWrite(14+(c.value?1:0),(c.value?portBVal:portAVal));
|
||||
break;
|
||||
case DIV_CMD_AY_AUTO_PWM:
|
||||
chan[c.chan].tfx.offset=c.value;
|
||||
case DIV_CMD_AY_NOISE_MASK_AND:
|
||||
chan[c.chan].tfx.num=c.value>>4;
|
||||
chan[c.chan].tfx.den=c.value&15;
|
||||
break;
|
||||
case DIV_CMD_AY_AUTO_PWM: {
|
||||
// best way i could find to do signed :/
|
||||
signed char signVal=c.value;
|
||||
chan[c.chan].tfx.offset=signVal;
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_SAMPLE_MODE:
|
||||
if (c.value>0) {
|
||||
chan[c.chan].nextPSGMode.val|=8;
|
||||
|
|
|
|||
|
|
@ -142,6 +142,8 @@ enum DivSystem {
|
|||
DIV_SYSTEM_BIFURCATOR,
|
||||
DIV_SYSTEM_SID2,
|
||||
DIV_SYSTEM_SID3,
|
||||
|
||||
DIV_SYSTEM_MAX
|
||||
};
|
||||
|
||||
enum DivEffectType: unsigned short {
|
||||
|
|
|
|||
|
|
@ -433,6 +433,7 @@ void DivEngine::registerSystems() {
|
|||
{0x25, {DIV_CMD_AY_ENVELOPE_SLIDE, _("25xx: Envelope slide up"), negEffectVal}},
|
||||
{0x26, {DIV_CMD_AY_ENVELOPE_SLIDE, _("26xx: Envelope slide down")}},
|
||||
{0x29, {DIV_CMD_AY_AUTO_ENVELOPE, _("29xy: Set auto-envelope (x: numerator; y: denominator)")}},
|
||||
{0x2c, {DIV_CMD_AY_AUTO_PWM, _("2Cxx: Set timer period offset (bit 7: sign)")}},
|
||||
{0x2e, {DIV_CMD_AY_IO_WRITE, _("2Exx: Write to I/O port A"), constVal<0>, effectVal}},
|
||||
{0x2f, {DIV_CMD_AY_IO_WRITE, _("2Fxx: Write to I/O port B"), constVal<1>, effectVal}},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ const char* aboutLine[]={
|
|||
"Polski: freq-mod, PoznańskiSzybkowiec",
|
||||
"Português (Brasil): Kagamiin~",
|
||||
"Русский: Background2982, LTVA",
|
||||
"Slovenčina: Mr. Hassium",
|
||||
"Slovenčina: Wegfrei",
|
||||
"Svenska: RevvoBolt",
|
||||
"ไทย: akumanatt",
|
||||
"",
|
||||
|
|
@ -206,6 +206,7 @@ const char* aboutLine[]={
|
|||
"Ultraprogramer",
|
||||
"UserSniper",
|
||||
"Weeppiko",
|
||||
"Wegfrei",
|
||||
"Xan",
|
||||
"Yuzu4K",
|
||||
"Zabir",
|
||||
|
|
|
|||
|
|
@ -130,7 +130,7 @@ const bool mobileButtonPersist[32]={
|
|||
// page 1
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
|
|
|
|||
|
|
@ -249,16 +249,18 @@ void FurnaceGUI::drawExportROM(bool onWindow) {
|
|||
for (int i=0; i<DIV_ROM_MAX; i++) {
|
||||
const DivROMExportDef* newDef=e->getROMExportDef((DivROMExportOptions)i);
|
||||
if (newDef!=NULL) {
|
||||
if (ImGui::Selectable(newDef->name)) {
|
||||
romTarget=(DivROMExportOptions)i;
|
||||
romMultiFile=newDef->multiOutput;
|
||||
romConfig=DivConfig();
|
||||
if (newDef->fileExt==NULL) {
|
||||
romFilterName="";
|
||||
romFilterExt="";
|
||||
} else {
|
||||
romFilterName=newDef->fileType;
|
||||
romFilterExt=newDef->fileExt;
|
||||
if (romExportAvail[i]) {
|
||||
if (ImGui::Selectable(newDef->name)) {
|
||||
romTarget=(DivROMExportOptions)i;
|
||||
romMultiFile=newDef->multiOutput;
|
||||
romConfig=DivConfig();
|
||||
if (newDef->fileExt==NULL) {
|
||||
romFilterName="";
|
||||
romFilterExt="";
|
||||
} else {
|
||||
romFilterName=newDef->fileType;
|
||||
romFilterExt=newDef->fileExt;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -436,9 +438,11 @@ void FurnaceGUI::drawExport() {
|
|||
drawExportVGM(true);
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
if (ImGui::BeginTabItem(_("ROM"))) {
|
||||
drawExportROM(true);
|
||||
ImGui::EndTabItem();
|
||||
if (romExportExists) {
|
||||
if (ImGui::BeginTabItem(_("ROM"))) {
|
||||
drawExportROM(true);
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
}
|
||||
int numZSMCompat=0;
|
||||
for (int i=0; i<e->song.systemLen; i++) {
|
||||
|
|
|
|||
110
src/gui/gui.cpp
110
src/gui/gui.cpp
|
|
@ -752,6 +752,88 @@ void FurnaceGUI::autoDetectSystem() {
|
|||
}
|
||||
}
|
||||
|
||||
void FurnaceGUI::updateROMExportAvail() {
|
||||
unsigned char sysReqCount[DIV_SYSTEM_MAX];
|
||||
unsigned char defReqCount[DIV_SYSTEM_MAX];
|
||||
|
||||
memset(sysReqCount,0,DIV_SYSTEM_MAX);
|
||||
for (int i=0; i<e->song.systemLen; i++) {
|
||||
sysReqCount[e->song.system[i]]++;
|
||||
}
|
||||
|
||||
memset(romExportAvail,0,sizeof(bool)*DIV_ROM_MAX);
|
||||
romExportExists=false;
|
||||
|
||||
for (int i=0; i<DIV_ROM_MAX; i++) {
|
||||
const DivROMExportDef* newDef=e->getROMExportDef((DivROMExportOptions)i);
|
||||
if (newDef!=NULL) {
|
||||
// check for viability
|
||||
bool viable=true;
|
||||
|
||||
memset(defReqCount,0,DIV_SYSTEM_MAX);
|
||||
for (DivSystem j: newDef->requisites) {
|
||||
defReqCount[j]++;
|
||||
}
|
||||
|
||||
switch (newDef->requisitePolicy) {
|
||||
case DIV_REQPOL_EXACT:
|
||||
for (int j=0; j<DIV_SYSTEM_MAX; j++) {
|
||||
if (defReqCount[j]!=sysReqCount[j]) {
|
||||
viable=false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DIV_REQPOL_ANY:
|
||||
for (int j=0; j<DIV_SYSTEM_MAX; j++) {
|
||||
if (defReqCount[j]>sysReqCount[j]) {
|
||||
viable=false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DIV_REQPOL_LAX:
|
||||
viable=false;
|
||||
for (DivSystem j: newDef->requisites) {
|
||||
if (defReqCount[j]<=sysReqCount[j]) {
|
||||
viable=true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (viable) {
|
||||
romExportAvail[i]=true;
|
||||
romExportExists=true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!romExportAvail[romTarget]) {
|
||||
// find a new one
|
||||
romTarget=DIV_ROM_ABSTRACT;
|
||||
for (int i=0; i<DIV_ROM_MAX; i++) {
|
||||
const DivROMExportDef* newDef=e->getROMExportDef((DivROMExportOptions)i);
|
||||
if (newDef!=NULL) {
|
||||
if (romExportAvail[i]) {
|
||||
romTarget=(DivROMExportOptions)i;
|
||||
romMultiFile=newDef->multiOutput;
|
||||
romConfig=DivConfig();
|
||||
if (newDef->fileExt==NULL) {
|
||||
romFilterName="";
|
||||
romFilterExt="";
|
||||
} else {
|
||||
romFilterName=newDef->fileType;
|
||||
romFilterExt=newDef->fileExt;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImVec4 FurnaceGUI::channelColor(int ch) {
|
||||
switch (settings.channelColors) {
|
||||
case 0:
|
||||
|
|
@ -2359,6 +2441,7 @@ int FurnaceGUI::load(String path) {
|
|||
undoHist.clear();
|
||||
redoHist.clear();
|
||||
updateWindowTitle();
|
||||
updateROMExportAvail();
|
||||
updateScroll(0);
|
||||
if (!e->getWarnings().empty()) {
|
||||
showWarning(e->getWarnings(),GUI_WARN_GENERIC);
|
||||
|
|
@ -4301,9 +4384,11 @@ bool FurnaceGUI::loop() {
|
|||
drawExportVGM();
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
if (ImGui::BeginMenu(_("export ROM..."))) {
|
||||
drawExportROM();
|
||||
ImGui::EndMenu();
|
||||
if (romExportExists) {
|
||||
if (ImGui::BeginMenu(_("export ROM..."))) {
|
||||
drawExportROM();
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
}
|
||||
int numZSMCompat=0;
|
||||
for (int i=0; i<e->song.systemLen; i++) {
|
||||
|
|
@ -4336,9 +4421,11 @@ bool FurnaceGUI::loop() {
|
|||
curExportType=GUI_EXPORT_VGM;
|
||||
displayExport=true;
|
||||
}
|
||||
if (ImGui::MenuItem(_("export ROM..."))) {
|
||||
curExportType=GUI_EXPORT_ROM;
|
||||
displayExport=true;
|
||||
if (romExportExists) {
|
||||
if (ImGui::MenuItem(_("export ROM..."))) {
|
||||
curExportType=GUI_EXPORT_ROM;
|
||||
displayExport=true;
|
||||
}
|
||||
}
|
||||
int numZSMCompat=0;
|
||||
for (int i=0; i<e->song.systemLen; i++) {
|
||||
|
|
@ -4387,6 +4474,7 @@ bool FurnaceGUI::loop() {
|
|||
autoDetectSystem();
|
||||
}
|
||||
updateWindowTitle();
|
||||
updateROMExportAvail();
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
|
@ -4413,6 +4501,7 @@ bool FurnaceGUI::loop() {
|
|||
autoDetectSystem();
|
||||
}
|
||||
updateWindowTitle();
|
||||
updateROMExportAvail();
|
||||
} else {
|
||||
showError(fmt::sprintf(_("cannot change chip! (%s)"),e->getLastError()));
|
||||
}
|
||||
|
|
@ -4437,6 +4526,7 @@ bool FurnaceGUI::loop() {
|
|||
autoDetectSystem();
|
||||
updateWindowTitle();
|
||||
}
|
||||
updateROMExportAvail();
|
||||
}
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
|
|
@ -5695,6 +5785,7 @@ bool FurnaceGUI::loop() {
|
|||
selEnd=SelectionPoint();
|
||||
cursor=SelectionPoint();
|
||||
updateWindowTitle();
|
||||
updateROMExportAvail();
|
||||
} else {
|
||||
ImGui::OpenPopup(_("New Song"));
|
||||
}
|
||||
|
|
@ -6245,6 +6336,7 @@ bool FurnaceGUI::loop() {
|
|||
updateWindowTitle();
|
||||
MARK_MODIFIED;
|
||||
}
|
||||
updateROMExportAvail();
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
|
|
@ -7263,6 +7355,7 @@ bool FurnaceGUI::init() {
|
|||
}
|
||||
|
||||
updateWindowTitle();
|
||||
updateROMExportAvail();
|
||||
|
||||
logV("max texture size: %dx%d",rend->getMaxTextureWidth(),rend->getMaxTextureHeight());
|
||||
|
||||
|
|
@ -8397,7 +8490,8 @@ FurnaceGUI::FurnaceGUI():
|
|||
romTarget(DIV_ROM_ABSTRACT),
|
||||
romMultiFile(false),
|
||||
romExportSave(false),
|
||||
pendingExport(NULL) {
|
||||
pendingExport(NULL),
|
||||
romExportExists(false) {
|
||||
// value keys
|
||||
valueKeys[SDLK_0]=0;
|
||||
valueKeys[SDLK_1]=1;
|
||||
|
|
@ -8516,6 +8610,8 @@ FurnaceGUI::FurnaceGUI():
|
|||
// effect sorting
|
||||
memset(effectsShow,1,sizeof(bool)*10);
|
||||
|
||||
memset(romExportAvail,0,sizeof(bool)*DIV_ROM_MAX);
|
||||
|
||||
strncpy(noteOffLabel,"OFF",32);
|
||||
strncpy(noteRelLabel,"===",32);
|
||||
strncpy(macroRelLabel,"REL",32);
|
||||
|
|
|
|||
|
|
@ -2684,6 +2684,8 @@ class FurnaceGUI {
|
|||
String romFilterName, romFilterExt;
|
||||
String romExportPath;
|
||||
DivROMExport* pendingExport;
|
||||
bool romExportAvail[DIV_ROM_MAX];
|
||||
bool romExportExists;
|
||||
|
||||
// user presets window
|
||||
std::vector<int> selectedUserPreset;
|
||||
|
|
@ -2735,6 +2737,7 @@ class FurnaceGUI {
|
|||
bool portSet(String label, unsigned int portSetID, int ins, int outs, int activeIns, int activeOuts, int& clickedPort, std::map<unsigned int,ImVec2>& portPos);
|
||||
|
||||
void updateWindowTitle();
|
||||
void updateROMExportAvail();
|
||||
void autoDetectSystem();
|
||||
void autoDetectSystemIter(std::vector<FurnaceGUISysDef>& category, bool& isMatch, std::map<DivSystem,int>& defCountMap, std::map<DivSystem,DivConfig>& defConfMap, std::map<DivSystem,int>& sysCountMap, std::map<DivSystem,DivConfig>& sysConfMap);
|
||||
void prepareLayout();
|
||||
|
|
|
|||
|
|
@ -8507,6 +8507,10 @@ void FurnaceGUI::drawInsEdit() {
|
|||
macroList.push_back(FurnaceGUIMacroDesc(_("Timer Num"),&ins->std.ex8Macro,0,15,64,uiColors[GUI_COLOR_MACRO_OTHER]));
|
||||
macroList.push_back(FurnaceGUIMacroDesc(_("Timer Den"),&ins->std.fmsMacro,0,15,64,uiColors[GUI_COLOR_MACRO_OTHER]));
|
||||
macroList.push_back(FurnaceGUIMacroDesc(_("PWM Boundary"),&ins->std.amsMacro,0,15,64,uiColors[GUI_COLOR_MACRO_OTHER]));
|
||||
// workaround, because the gui will not set
|
||||
// zoom or scroll if we're not in macros tab
|
||||
ins->std.ex7Macro.vZoom=128;
|
||||
ins->std.ex7Macro.vScroll=2048-64;
|
||||
drawMacros(macroList,macroEditStateMacros);
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -289,6 +289,7 @@ void FurnaceGUI::drawNewSong() {
|
|||
selEnd=SelectionPoint();
|
||||
cursor=SelectionPoint();
|
||||
updateWindowTitle();
|
||||
updateROMExportAvail();
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -91,6 +91,11 @@ void FurnaceGUI::drawSysManager() {
|
|||
if (!e->duplicateSystem(i,sysDupCloneChannels,sysDupEnd)) {
|
||||
showError(fmt::sprintf(_("cannot clone chip! (%s)"),e->getLastError()));
|
||||
} else {
|
||||
if (e->song.autoSystem) {
|
||||
autoDetectSystem();
|
||||
updateWindowTitle();
|
||||
}
|
||||
updateROMExportAvail();
|
||||
MARK_MODIFIED;
|
||||
}
|
||||
}
|
||||
|
|
@ -105,6 +110,7 @@ void FurnaceGUI::drawSysManager() {
|
|||
autoDetectSystem();
|
||||
}
|
||||
updateWindowTitle();
|
||||
updateROMExportAvail();
|
||||
} else {
|
||||
showError(fmt::sprintf(_("cannot change chip! (%s)"),e->getLastError()));
|
||||
}
|
||||
|
|
@ -143,6 +149,7 @@ void FurnaceGUI::drawSysManager() {
|
|||
autoDetectSystem();
|
||||
}
|
||||
updateWindowTitle();
|
||||
updateROMExportAvail();
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue