GUI: rate change and new window title

This commit is contained in:
tildearrow 2021-12-15 17:32:08 -05:00
parent ebb28d912b
commit c54df74df1
19 changed files with 196 additions and 24 deletions

View file

@ -108,6 +108,7 @@ class DivDispatch {
virtual bool isStereo(); virtual bool isStereo();
virtual bool keyOffAffectsArp(int ch); virtual bool keyOffAffectsArp(int ch);
virtual void setPAL(bool pal);
/** /**
* initialize this DivDispatch. * initialize this DivDispatch.

View file

@ -133,6 +133,38 @@ int DivEngine::getChannelCount(DivSystem sys) {
return 0; return 0;
} }
const char* DivEngine::getSystemName(DivSystem sys) {
switch (sys) {
case DIV_SYSTEM_NULL:
return "Unknown";
case DIV_SYSTEM_YMU759:
return "Yamaha YMU759";
case DIV_SYSTEM_GENESIS:
return "Sega Genesis/Mega Drive";
case DIV_SYSTEM_SMS:
return "Sega Master System";
case DIV_SYSTEM_GB:
return "Game Boy";
case DIV_SYSTEM_PCE:
return "PC Engine/TurboGrafx-16";
case DIV_SYSTEM_NES:
return "NES";
case DIV_SYSTEM_C64_6581:
return "Commodore 64 with 6581";
case DIV_SYSTEM_C64_8580:
return "Commodore 64 with 8580";
case DIV_SYSTEM_ARCADE:
return "Arcade";
case DIV_SYSTEM_GENESIS_EXT:
return "Sega Genesis Extended Channel 3";
case DIV_SYSTEM_YM2610:
return "Neo Geo";
case DIV_SYSTEM_YM2610_EXT:
return "Neo Geo Extended Channel 3";
}
return "Unknown";
}
bool DivEngine::isFMSystem(DivSystem sys) { bool DivEngine::isFMSystem(DivSystem sys) {
return (sys==DIV_SYSTEM_GENESIS || return (sys==DIV_SYSTEM_GENESIS ||
sys==DIV_SYSTEM_GENESIS_EXT || sys==DIV_SYSTEM_GENESIS_EXT ||
@ -453,6 +485,7 @@ bool DivEngine::load(void* f, size_t slen) {
if (ds.version>0x03) { if (ds.version>0x03) {
ds.speed2=reader.readC(); ds.speed2=reader.readC();
ds.pal=reader.readC(); ds.pal=reader.readC();
ds.hz=(ds.pal)?60:50;
ds.customTempo=reader.readC(); ds.customTempo=reader.readC();
} else { } else {
ds.speed2=ds.speed1; ds.speed2=ds.speed1;
@ -1193,6 +1226,17 @@ void DivEngine::setOrder(unsigned char order) {
isBusy.unlock(); isBusy.unlock();
} }
void DivEngine::setSongRate(int hz, bool pal) {
isBusy.lock();
song.pal=!pal;
song.hz=hz;
song.customTempo=(song.hz!=50 && song.hz!=60);
dispatch->setPAL((!song.pal) || (song.customTempo!=0 && song.hz<53));
blip_set_rates(bb[0],dispatch->rate,got.rate);
blip_set_rates(bb[1],dispatch->rate,got.rate);
isBusy.unlock();
}
void DivEngine::setAudio(DivAudioEngines which) { void DivEngine::setAudio(DivAudioEngines which) {
audioEngine=which; audioEngine=which;
} }

View file

@ -119,6 +119,9 @@ class DivEngine {
// get sys channel count // get sys channel count
int getChannelCount(DivSystem sys); int getChannelCount(DivSystem sys);
// get sys name
const char* getSystemName(DivSystem sys);
// is FM system // is FM system
bool isFMSystem(DivSystem sys); bool isFMSystem(DivSystem sys);
@ -152,6 +155,9 @@ class DivEngine {
// go to order // go to order
void setOrder(unsigned char order); void setOrder(unsigned char order);
// set Hz
void setSongRate(int hz, bool pal);
// set remaining loops. -1 means loop forever. // set remaining loops. -1 means loop forever.
void setLoops(int loops); void setLoops(int loops);

View file

@ -21,6 +21,15 @@ DivPattern* DivChannelData::getPattern(int index, bool create) {
return data[index]; return data[index];
} }
void DivChannelData::wipePatterns() {
for (int i=0; i<128; i++) {
if (data[i]!=NULL) {
delete data[i];
data[i]=NULL;
}
}
}
DivChannelData::DivChannelData(): DivChannelData::DivChannelData():
effectRows(1) { effectRows(1) {
memset(data,0,128*sizeof(void*)); memset(data,0,128*sizeof(void*));

View file

@ -14,5 +14,6 @@ struct DivChannelData {
// 4-5+: effect/effect value // 4-5+: effect/effect value
DivPattern* data[128]; DivPattern* data[128];
DivPattern* getPattern(int index, bool create); DivPattern* getPattern(int index, bool create);
void wipePatterns();
DivChannelData(); DivChannelData();
}; };

View file

@ -21,6 +21,9 @@ bool DivDispatch::keyOffAffectsArp(int ch) {
return false; return false;
} }
void DivDispatch::setPAL(bool pal) {
}
int DivDispatch::init(DivEngine* p, int channels, int sugRate, bool pal) { int DivDispatch::init(DivEngine* p, int channels, int sugRate, bool pal) {
return 0; return 0;
} }

View file

@ -302,13 +302,17 @@ void DivPlatformC64::setChipModel(bool is6581) {
} }
} }
int DivPlatformC64::init(DivEngine* p, int channels, int sugRate, bool pal) { void DivPlatformC64::setPAL(bool pal) {
parent=p;
if (pal) { if (pal) {
rate=985248; rate=985248;
} else { } else {
rate=1022727; rate=1022727;
} }
}
int DivPlatformC64::init(DivEngine* p, int channels, int sugRate, bool pal) {
parent=p;
setPAL(pal);
reset(); reset();

View file

@ -57,6 +57,7 @@ class DivPlatformC64: public DivDispatch {
int dispatch(DivCommand c); int dispatch(DivCommand c);
void reset(); void reset();
void tick(); void tick();
void setPAL(bool pal);
int init(DivEngine* parent, int channels, int sugRate, bool pal); int init(DivEngine* parent, int channels, int sugRate, bool pal);
void setChipModel(bool is6581); void setChipModel(bool is6581);
void quit(); void quit();

View file

@ -400,13 +400,17 @@ bool DivPlatformGenesis::keyOffAffectsArp(int ch) {
return (ch>5); return (ch>5);
} }
int DivPlatformGenesis::init(DivEngine* p, int channels, int sugRate, bool pal) { void DivPlatformGenesis::setPAL(bool pal) {
parent=p;
if (pal) { if (pal) {
rate=211125; rate=211125;
} else { } else {
rate=213068; rate=213068;
} }
}
int DivPlatformGenesis::init(DivEngine* p, int channels, int sugRate, bool pal) {
parent=p;
setPAL(pal);
// PSG // PSG
psg.init(p,4,sugRate,pal); psg.init(p,4,sugRate,pal);

View file

@ -55,6 +55,7 @@ class DivPlatformGenesis: public DivDispatch {
void tick(); void tick();
bool isStereo(); bool isStereo();
bool keyOffAffectsArp(int ch); bool keyOffAffectsArp(int ch);
void setPAL(bool pal);
int init(DivEngine* parent, int channels, int sugRate, bool pal); int init(DivEngine* parent, int channels, int sugRate, bool pal);
void quit(); void quit();
~DivPlatformGenesis(); ~DivPlatformGenesis();

View file

@ -296,8 +296,7 @@ bool DivPlatformNES::keyOffAffectsArp(int ch) {
return true; return true;
} }
int DivPlatformNES::init(DivEngine* p, int channels, int sugRate, bool pal) { void DivPlatformNES::setPAL(bool pal) {
parent=p;
if (pal) { if (pal) {
rate=1662607; rate=1662607;
freqBase=FREQ_BASE_PAL; freqBase=FREQ_BASE_PAL;
@ -305,6 +304,11 @@ int DivPlatformNES::init(DivEngine* p, int channels, int sugRate, bool pal) {
rate=1789773; rate=1789773;
freqBase=FREQ_BASE; freqBase=FREQ_BASE;
} }
}
int DivPlatformNES::init(DivEngine* p, int channels, int sugRate, bool pal) {
parent=p;
setPAL(pal);
init_nla_table(500,500); init_nla_table(500,500);
reset(); reset();

View file

@ -47,6 +47,7 @@ class DivPlatformNES: public DivDispatch {
void reset(); void reset();
void tick(); void tick();
bool keyOffAffectsArp(int ch); bool keyOffAffectsArp(int ch);
void setPAL(bool pal);
int init(DivEngine* parent, int channels, int sugRate, bool pal); int init(DivEngine* parent, int channels, int sugRate, bool pal);
void quit(); void quit();
~DivPlatformNES(); ~DivPlatformNES();

View file

@ -293,13 +293,17 @@ bool DivPlatformPCE::keyOffAffectsArp(int ch) {
return true; return true;
} }
int DivPlatformPCE::init(DivEngine* p, int channels, int sugRate, bool pal) { void DivPlatformPCE::setPAL(bool pal) {
parent=p;
if (pal) { // technically there is no PAL PC Engine but oh well... if (pal) { // technically there is no PAL PC Engine but oh well...
rate=1773448; rate=1773448;
} else { } else {
rate=1789773; rate=1789773;
} }
}
int DivPlatformPCE::init(DivEngine* p, int channels, int sugRate, bool pal) {
parent=p;
setPAL(pal);
pce=new PCE_PSG(&tempL,&tempR,PCE_PSG::REVISION_HUC6280); pce=new PCE_PSG(&tempL,&tempR,PCE_PSG::REVISION_HUC6280);
reset(); reset();
return 6; return 6;

View file

@ -59,6 +59,7 @@ class DivPlatformPCE: public DivDispatch {
void tick(); void tick();
bool isStereo(); bool isStereo();
bool keyOffAffectsArp(int ch); bool keyOffAffectsArp(int ch);
void setPAL(bool pal);
int init(DivEngine* parent, int channels, int sugRate, bool pal); int init(DivEngine* parent, int channels, int sugRate, bool pal);
void quit(); void quit();
~DivPlatformPCE(); ~DivPlatformPCE();

View file

@ -172,13 +172,17 @@ bool DivPlatformSMS::keyOffAffectsArp(int ch) {
return true; return true;
} }
int DivPlatformSMS::init(DivEngine* p, int channels, int sugRate, bool pal) { void DivPlatformSMS::setPAL(bool pal) {
parent=p;
if (pal) { if (pal) {
rate=221681; rate=221681;
} else { } else {
rate=223722; rate=223722;
} }
}
int DivPlatformSMS::init(DivEngine* p, int channels, int sugRate, bool pal) {
parent=p;
setPAL(pal);
sn=new sn76496_device(rate); sn=new sn76496_device(rate);
reset(); reset();
return 4; return 4;

View file

@ -37,6 +37,7 @@ class DivPlatformSMS: public DivDispatch {
void reset(); void reset();
void tick(); void tick();
bool keyOffAffectsArp(int ch); bool keyOffAffectsArp(int ch);
void setPAL(bool pal);
int init(DivEngine* parent, int channels, int sugRate, bool pal); int init(DivEngine* parent, int channels, int sugRate, bool pal);
void quit(); void quit();
~DivPlatformSMS(); ~DivPlatformSMS();

View file

@ -14,5 +14,9 @@ void DivSong::unload() {
for (DivSample* i: sample) { for (DivSample* i: sample) {
delete i; delete i;
} }
sample.clear(); sample.clear();
for (int i=0; i<17; i++) {
pat[i].wipePatterns();
}
} }

View file

@ -104,19 +104,24 @@ void FurnaceGUI::updateScroll(int amount) {
nextScroll=lineHeight*amount; nextScroll=lineHeight*amount;
} }
void FurnaceGUI::drawSongInfo() { void FurnaceGUI::updateWindowTitle() {
if (!songInfoOpen) return; if (e->song.name.empty()) {
if (ImGui::Begin("Song Information",&songInfoOpen)) { SDL_SetWindowTitle(sdlWin,fmt::sprintf("Furnace (%s)",e->getSystemName(e->song.system)).c_str());
ImGui::InputText("Name",&e->song.name); } else {
ImGui::InputText("Author",&e->song.author); SDL_SetWindowTitle(sdlWin,fmt::sprintf("%s - Furnace (%s)",e->song.name,e->getSystemName(e->song.system)).c_str());
ImGui::InputScalar("Speed 1",ImGuiDataType_U8,&e->song.speed1,&_ONE,&_THREE); }
ImGui::InputScalar("Speed 2",ImGuiDataType_U8,&e->song.speed2,&_ONE,&_THREE); }
ImGui::InputScalar("Highlight 1",ImGuiDataType_U8,&e->song.hilightA,&_ONE,&_THREE);
ImGui::InputScalar("Highlight 2",ImGuiDataType_U8,&e->song.hilightB,&_ONE,&_THREE); void FurnaceGUI::drawEditControls() {
unsigned char ord=e->getOrder(); if (!editControlsOpen) return;
if (ImGui::InputScalar("Order",ImGuiDataType_U8,&ord)) { if (ImGui::Begin("Play/Edit Controls",&editControlsOpen)) {
e->setOrder(ord); ImGui::Text("Octave");
ImGui::SameLine();
if (ImGui::InputInt("##Octave",&curOctave,1,1)) {
if (curOctave>6) curOctave=6;
if (curOctave<0) curOctave=0;
} }
if (ImGui::Button("Play")) { if (ImGui::Button("Play")) {
e->play(); e->play();
} }
@ -125,6 +130,64 @@ void FurnaceGUI::drawSongInfo() {
e->stop(); e->stop();
} }
} }
if (ImGui::IsWindowFocused()) curWindow=GUI_WINDOW_EDIT_CONTROLS;
ImGui::End();
}
void FurnaceGUI::drawSongInfo() {
if (!songInfoOpen) return;
if (ImGui::Begin("Song Information",&songInfoOpen)) {
ImGui::Text("Name");
ImGui::SameLine();
if (ImGui::InputText("##Name",&e->song.name)) updateWindowTitle();
ImGui::Text("Author");
ImGui::SameLine();
ImGui::InputText("##Author",&e->song.author);
ImGui::Text("TimeBase");
ImGui::SameLine();
ImGui::SetNextItemWidth(120.0f*dpiScale);
unsigned char realTB=e->song.timeBase+1;
if (ImGui::InputScalar("##TimeBase",ImGuiDataType_U8,&realTB,&_ONE,&_THREE)) {
if (realTB<1) realTB=1;
if (realTB>16) realTB=16;
e->song.timeBase=realTB-1;
}
ImGui::Text("Speed");
ImGui::SameLine();
ImGui::SetNextItemWidth(120.0f*dpiScale);
ImGui::InputScalar("##Speed1",ImGuiDataType_U8,&e->song.speed1,&_ONE,&_THREE);
ImGui::SameLine();
ImGui::SetNextItemWidth(120.0f*dpiScale);
ImGui::InputScalar("##Speed2",ImGuiDataType_U8,&e->song.speed2,&_ONE,&_THREE);
ImGui::Text("Highlight");
ImGui::SameLine();
ImGui::SetNextItemWidth(120.0f*dpiScale);
ImGui::InputScalar("##Highlight1",ImGuiDataType_U8,&e->song.hilightA,&_ONE,&_THREE);
ImGui::SameLine();
ImGui::SetNextItemWidth(120.0f*dpiScale);
ImGui::InputScalar("##Highlight2",ImGuiDataType_U8,&e->song.hilightB,&_ONE,&_THREE);
ImGui::Text("Rate");
ImGui::SameLine();
ImGui::SetNextItemWidth(120.0f*dpiScale);
int setHz=e->song.hz;
if (ImGui::InputInt("##Rate",&setHz)) {
if (setHz<10) setHz=10;
if (setHz>999) setHz=999;
e->setSongRate(setHz,setHz<52);
}
if (e->song.hz==50) {
ImGui::SameLine();
ImGui::Text("PAL");
}
if (e->song.hz==60) {
ImGui::SameLine();
ImGui::Text("NTSC");
}
}
if (ImGui::IsWindowFocused()) curWindow=GUI_WINDOW_SONG_INFO; if (ImGui::IsWindowFocused()) curWindow=GUI_WINDOW_SONG_INFO;
ImGui::End(); ImGui::End();
} }
@ -582,6 +645,7 @@ void FurnaceGUI::drawPattern() {
startSelection(j,0,i); startSelection(j,0,i);
} }
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) { if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) {
//ImGui::SetTooltip("N: %d O: %d",pat->data[i][0],pat->data[i][1]);
updateSelection(j,0,i); updateSelection(j,0,i);
} }
ImGui::PopStyleColor(); ImGui::PopStyleColor();
@ -822,6 +886,11 @@ void FurnaceGUI::keyDown(SDL_Event& ev) {
pat->data[selStart.y][0]=num%12; pat->data[selStart.y][0]=num%12;
pat->data[selStart.y][1]=num/12; pat->data[selStart.y][1]=num/12;
if (pat->data[selStart.y][0]==0) {
pat->data[selStart.y][0]=12;
pat->data[selStart.y][1]--;
}
pat->data[selStart.y][2]=curIns;
editAdvance(); editAdvance();
} catch (std::out_of_range& e) { } catch (std::out_of_range& e) {
} }
@ -994,6 +1063,7 @@ int FurnaceGUI::load(String path) {
e->initDispatch(); e->initDispatch();
e->reset(); e->reset();
} }
updateWindowTitle();
return 0; return 0;
} }
@ -1080,6 +1150,7 @@ bool FurnaceGUI::loop() {
ImGui::EndMenu(); ImGui::EndMenu();
} }
if (ImGui::BeginMenu("window")) { if (ImGui::BeginMenu("window")) {
if (ImGui::MenuItem("play/edit controls")) editControlsOpen=!editControlsOpen;
if (ImGui::MenuItem("song information")) songInfoOpen=!songInfoOpen; if (ImGui::MenuItem("song information")) songInfoOpen=!songInfoOpen;
if (ImGui::MenuItem("instruments")) insListOpen=!insListOpen; if (ImGui::MenuItem("instruments")) insListOpen=!insListOpen;
if (ImGui::MenuItem("instrument editor")) insEditOpen=!insEditOpen; if (ImGui::MenuItem("instrument editor")) insEditOpen=!insEditOpen;
@ -1091,6 +1162,7 @@ bool FurnaceGUI::loop() {
ImGui::DockSpaceOverViewport(); ImGui::DockSpaceOverViewport();
drawEditControls();
drawSongInfo(); drawSongInfo();
drawOrders(); drawOrders();
drawInsList(); drawInsList();
@ -1191,6 +1263,8 @@ bool FurnaceGUI::init() {
logE("could not load pattern font!\n"); logE("could not load pattern font!\n");
return false; return false;
} }
updateWindowTitle();
return true; return true;
} }
@ -1205,6 +1279,7 @@ FurnaceGUI::FurnaceGUI():
curOctave(3), curOctave(3),
oldRow(0), oldRow(0),
editStep(1), editStep(1),
editControlsOpen(true),
ordersOpen(true), ordersOpen(true),
insListOpen(true), insListOpen(true),
songInfoOpen(true), songInfoOpen(true),

View file

@ -35,6 +35,7 @@ enum FurnaceGUIColors {
enum FurnaceGUIWindows { enum FurnaceGUIWindows {
GUI_WINDOW_NOTHING=0, GUI_WINDOW_NOTHING=0,
GUI_WINDOW_EDIT_CONTROLS,
GUI_WINDOW_SONG_INFO, GUI_WINDOW_SONG_INFO,
GUI_WINDOW_ORDERS, GUI_WINDOW_ORDERS,
GUI_WINDOW_INS_LIST, GUI_WINDOW_INS_LIST,
@ -69,7 +70,7 @@ class FurnaceGUI {
ImVec4 volColors[128]; ImVec4 volColors[128];
int curIns, curOctave, oldRow, editStep; int curIns, curOctave, oldRow, editStep;
bool ordersOpen, insListOpen, songInfoOpen, patternOpen, insEditOpen; bool editControlsOpen, ordersOpen, insListOpen, songInfoOpen, patternOpen, insEditOpen;
SelectionPoint selStart, selEnd; SelectionPoint selStart, selEnd;
bool selecting, curNibble; bool selecting, curNibble;
FurnaceGUIWindows curWindow; FurnaceGUIWindows curWindow;
@ -94,6 +95,9 @@ class FurnaceGUI {
float nextScroll; float nextScroll;
void updateWindowTitle();
void drawEditControls();
void drawSongInfo(); void drawSongInfo();
void drawOrders(); void drawOrders();
void drawInsList(); void drawInsList();