GUI: rate change and new window title
This commit is contained in:
parent
ebb28d912b
commit
c54df74df1
|
@ -108,6 +108,7 @@ class DivDispatch {
|
|||
|
||||
virtual bool isStereo();
|
||||
virtual bool keyOffAffectsArp(int ch);
|
||||
virtual void setPAL(bool pal);
|
||||
|
||||
/**
|
||||
* initialize this DivDispatch.
|
||||
|
|
|
@ -133,6 +133,38 @@ int DivEngine::getChannelCount(DivSystem sys) {
|
|||
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) {
|
||||
return (sys==DIV_SYSTEM_GENESIS ||
|
||||
sys==DIV_SYSTEM_GENESIS_EXT ||
|
||||
|
@ -453,6 +485,7 @@ bool DivEngine::load(void* f, size_t slen) {
|
|||
if (ds.version>0x03) {
|
||||
ds.speed2=reader.readC();
|
||||
ds.pal=reader.readC();
|
||||
ds.hz=(ds.pal)?60:50;
|
||||
ds.customTempo=reader.readC();
|
||||
} else {
|
||||
ds.speed2=ds.speed1;
|
||||
|
@ -1193,6 +1226,17 @@ void DivEngine::setOrder(unsigned char order) {
|
|||
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) {
|
||||
audioEngine=which;
|
||||
}
|
||||
|
|
|
@ -119,6 +119,9 @@ class DivEngine {
|
|||
// get sys channel count
|
||||
int getChannelCount(DivSystem sys);
|
||||
|
||||
// get sys name
|
||||
const char* getSystemName(DivSystem sys);
|
||||
|
||||
// is FM system
|
||||
bool isFMSystem(DivSystem sys);
|
||||
|
||||
|
@ -152,6 +155,9 @@ class DivEngine {
|
|||
// go to order
|
||||
void setOrder(unsigned char order);
|
||||
|
||||
// set Hz
|
||||
void setSongRate(int hz, bool pal);
|
||||
|
||||
// set remaining loops. -1 means loop forever.
|
||||
void setLoops(int loops);
|
||||
|
||||
|
|
|
@ -21,6 +21,15 @@ DivPattern* DivChannelData::getPattern(int index, bool create) {
|
|||
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():
|
||||
effectRows(1) {
|
||||
memset(data,0,128*sizeof(void*));
|
||||
|
|
|
@ -14,5 +14,6 @@ struct DivChannelData {
|
|||
// 4-5+: effect/effect value
|
||||
DivPattern* data[128];
|
||||
DivPattern* getPattern(int index, bool create);
|
||||
void wipePatterns();
|
||||
DivChannelData();
|
||||
};
|
||||
|
|
|
@ -21,6 +21,9 @@ bool DivDispatch::keyOffAffectsArp(int ch) {
|
|||
return false;
|
||||
}
|
||||
|
||||
void DivDispatch::setPAL(bool pal) {
|
||||
}
|
||||
|
||||
int DivDispatch::init(DivEngine* p, int channels, int sugRate, bool pal) {
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -302,13 +302,17 @@ void DivPlatformC64::setChipModel(bool is6581) {
|
|||
}
|
||||
}
|
||||
|
||||
int DivPlatformC64::init(DivEngine* p, int channels, int sugRate, bool pal) {
|
||||
parent=p;
|
||||
void DivPlatformC64::setPAL(bool pal) {
|
||||
if (pal) {
|
||||
rate=985248;
|
||||
} else {
|
||||
rate=1022727;
|
||||
}
|
||||
}
|
||||
|
||||
int DivPlatformC64::init(DivEngine* p, int channels, int sugRate, bool pal) {
|
||||
parent=p;
|
||||
setPAL(pal);
|
||||
|
||||
reset();
|
||||
|
||||
|
|
|
@ -57,6 +57,7 @@ class DivPlatformC64: public DivDispatch {
|
|||
int dispatch(DivCommand c);
|
||||
void reset();
|
||||
void tick();
|
||||
void setPAL(bool pal);
|
||||
int init(DivEngine* parent, int channels, int sugRate, bool pal);
|
||||
void setChipModel(bool is6581);
|
||||
void quit();
|
||||
|
|
|
@ -400,13 +400,17 @@ bool DivPlatformGenesis::keyOffAffectsArp(int ch) {
|
|||
return (ch>5);
|
||||
}
|
||||
|
||||
int DivPlatformGenesis::init(DivEngine* p, int channels, int sugRate, bool pal) {
|
||||
parent=p;
|
||||
void DivPlatformGenesis::setPAL(bool pal) {
|
||||
if (pal) {
|
||||
rate=211125;
|
||||
} else {
|
||||
rate=213068;
|
||||
}
|
||||
}
|
||||
|
||||
int DivPlatformGenesis::init(DivEngine* p, int channels, int sugRate, bool pal) {
|
||||
parent=p;
|
||||
setPAL(pal);
|
||||
// PSG
|
||||
psg.init(p,4,sugRate,pal);
|
||||
|
||||
|
|
|
@ -55,6 +55,7 @@ class DivPlatformGenesis: public DivDispatch {
|
|||
void tick();
|
||||
bool isStereo();
|
||||
bool keyOffAffectsArp(int ch);
|
||||
void setPAL(bool pal);
|
||||
int init(DivEngine* parent, int channels, int sugRate, bool pal);
|
||||
void quit();
|
||||
~DivPlatformGenesis();
|
||||
|
|
|
@ -296,8 +296,7 @@ bool DivPlatformNES::keyOffAffectsArp(int ch) {
|
|||
return true;
|
||||
}
|
||||
|
||||
int DivPlatformNES::init(DivEngine* p, int channels, int sugRate, bool pal) {
|
||||
parent=p;
|
||||
void DivPlatformNES::setPAL(bool pal) {
|
||||
if (pal) {
|
||||
rate=1662607;
|
||||
freqBase=FREQ_BASE_PAL;
|
||||
|
@ -305,6 +304,11 @@ int DivPlatformNES::init(DivEngine* p, int channels, int sugRate, bool pal) {
|
|||
rate=1789773;
|
||||
freqBase=FREQ_BASE;
|
||||
}
|
||||
}
|
||||
|
||||
int DivPlatformNES::init(DivEngine* p, int channels, int sugRate, bool pal) {
|
||||
parent=p;
|
||||
setPAL(pal);
|
||||
|
||||
init_nla_table(500,500);
|
||||
reset();
|
||||
|
|
|
@ -47,6 +47,7 @@ class DivPlatformNES: public DivDispatch {
|
|||
void reset();
|
||||
void tick();
|
||||
bool keyOffAffectsArp(int ch);
|
||||
void setPAL(bool pal);
|
||||
int init(DivEngine* parent, int channels, int sugRate, bool pal);
|
||||
void quit();
|
||||
~DivPlatformNES();
|
||||
|
|
|
@ -293,13 +293,17 @@ bool DivPlatformPCE::keyOffAffectsArp(int ch) {
|
|||
return true;
|
||||
}
|
||||
|
||||
int DivPlatformPCE::init(DivEngine* p, int channels, int sugRate, bool pal) {
|
||||
parent=p;
|
||||
void DivPlatformPCE::setPAL(bool pal) {
|
||||
if (pal) { // technically there is no PAL PC Engine but oh well...
|
||||
rate=1773448;
|
||||
} else {
|
||||
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);
|
||||
reset();
|
||||
return 6;
|
||||
|
|
|
@ -59,6 +59,7 @@ class DivPlatformPCE: public DivDispatch {
|
|||
void tick();
|
||||
bool isStereo();
|
||||
bool keyOffAffectsArp(int ch);
|
||||
void setPAL(bool pal);
|
||||
int init(DivEngine* parent, int channels, int sugRate, bool pal);
|
||||
void quit();
|
||||
~DivPlatformPCE();
|
||||
|
|
|
@ -172,13 +172,17 @@ bool DivPlatformSMS::keyOffAffectsArp(int ch) {
|
|||
return true;
|
||||
}
|
||||
|
||||
int DivPlatformSMS::init(DivEngine* p, int channels, int sugRate, bool pal) {
|
||||
parent=p;
|
||||
void DivPlatformSMS::setPAL(bool pal) {
|
||||
if (pal) {
|
||||
rate=221681;
|
||||
} else {
|
||||
rate=223722;
|
||||
}
|
||||
}
|
||||
|
||||
int DivPlatformSMS::init(DivEngine* p, int channels, int sugRate, bool pal) {
|
||||
parent=p;
|
||||
setPAL(pal);
|
||||
sn=new sn76496_device(rate);
|
||||
reset();
|
||||
return 4;
|
||||
|
|
|
@ -37,6 +37,7 @@ class DivPlatformSMS: public DivDispatch {
|
|||
void reset();
|
||||
void tick();
|
||||
bool keyOffAffectsArp(int ch);
|
||||
void setPAL(bool pal);
|
||||
int init(DivEngine* parent, int channels, int sugRate, bool pal);
|
||||
void quit();
|
||||
~DivPlatformSMS();
|
||||
|
|
|
@ -14,5 +14,9 @@ void DivSong::unload() {
|
|||
for (DivSample* i: sample) {
|
||||
delete i;
|
||||
}
|
||||
sample.clear();
|
||||
sample.clear();
|
||||
|
||||
for (int i=0; i<17; i++) {
|
||||
pat[i].wipePatterns();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -104,19 +104,24 @@ void FurnaceGUI::updateScroll(int amount) {
|
|||
nextScroll=lineHeight*amount;
|
||||
}
|
||||
|
||||
void FurnaceGUI::drawSongInfo() {
|
||||
if (!songInfoOpen) return;
|
||||
if (ImGui::Begin("Song Information",&songInfoOpen)) {
|
||||
ImGui::InputText("Name",&e->song.name);
|
||||
ImGui::InputText("Author",&e->song.author);
|
||||
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);
|
||||
unsigned char ord=e->getOrder();
|
||||
if (ImGui::InputScalar("Order",ImGuiDataType_U8,&ord)) {
|
||||
e->setOrder(ord);
|
||||
void FurnaceGUI::updateWindowTitle() {
|
||||
if (e->song.name.empty()) {
|
||||
SDL_SetWindowTitle(sdlWin,fmt::sprintf("Furnace (%s)",e->getSystemName(e->song.system)).c_str());
|
||||
} else {
|
||||
SDL_SetWindowTitle(sdlWin,fmt::sprintf("%s - Furnace (%s)",e->song.name,e->getSystemName(e->song.system)).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void FurnaceGUI::drawEditControls() {
|
||||
if (!editControlsOpen) return;
|
||||
if (ImGui::Begin("Play/Edit Controls",&editControlsOpen)) {
|
||||
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")) {
|
||||
e->play();
|
||||
}
|
||||
|
@ -125,6 +130,64 @@ void FurnaceGUI::drawSongInfo() {
|
|||
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;
|
||||
ImGui::End();
|
||||
}
|
||||
|
@ -582,6 +645,7 @@ void FurnaceGUI::drawPattern() {
|
|||
startSelection(j,0,i);
|
||||
}
|
||||
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) {
|
||||
//ImGui::SetTooltip("N: %d O: %d",pat->data[i][0],pat->data[i][1]);
|
||||
updateSelection(j,0,i);
|
||||
}
|
||||
ImGui::PopStyleColor();
|
||||
|
@ -822,6 +886,11 @@ void FurnaceGUI::keyDown(SDL_Event& ev) {
|
|||
|
||||
pat->data[selStart.y][0]=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();
|
||||
} catch (std::out_of_range& e) {
|
||||
}
|
||||
|
@ -994,6 +1063,7 @@ int FurnaceGUI::load(String path) {
|
|||
e->initDispatch();
|
||||
e->reset();
|
||||
}
|
||||
updateWindowTitle();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1080,6 +1150,7 @@ bool FurnaceGUI::loop() {
|
|||
ImGui::EndMenu();
|
||||
}
|
||||
if (ImGui::BeginMenu("window")) {
|
||||
if (ImGui::MenuItem("play/edit controls")) editControlsOpen=!editControlsOpen;
|
||||
if (ImGui::MenuItem("song information")) songInfoOpen=!songInfoOpen;
|
||||
if (ImGui::MenuItem("instruments")) insListOpen=!insListOpen;
|
||||
if (ImGui::MenuItem("instrument editor")) insEditOpen=!insEditOpen;
|
||||
|
@ -1091,6 +1162,7 @@ bool FurnaceGUI::loop() {
|
|||
|
||||
ImGui::DockSpaceOverViewport();
|
||||
|
||||
drawEditControls();
|
||||
drawSongInfo();
|
||||
drawOrders();
|
||||
drawInsList();
|
||||
|
@ -1191,6 +1263,8 @@ bool FurnaceGUI::init() {
|
|||
logE("could not load pattern font!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
updateWindowTitle();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1205,6 +1279,7 @@ FurnaceGUI::FurnaceGUI():
|
|||
curOctave(3),
|
||||
oldRow(0),
|
||||
editStep(1),
|
||||
editControlsOpen(true),
|
||||
ordersOpen(true),
|
||||
insListOpen(true),
|
||||
songInfoOpen(true),
|
||||
|
|
|
@ -35,6 +35,7 @@ enum FurnaceGUIColors {
|
|||
|
||||
enum FurnaceGUIWindows {
|
||||
GUI_WINDOW_NOTHING=0,
|
||||
GUI_WINDOW_EDIT_CONTROLS,
|
||||
GUI_WINDOW_SONG_INFO,
|
||||
GUI_WINDOW_ORDERS,
|
||||
GUI_WINDOW_INS_LIST,
|
||||
|
@ -69,7 +70,7 @@ class FurnaceGUI {
|
|||
ImVec4 volColors[128];
|
||||
|
||||
int curIns, curOctave, oldRow, editStep;
|
||||
bool ordersOpen, insListOpen, songInfoOpen, patternOpen, insEditOpen;
|
||||
bool editControlsOpen, ordersOpen, insListOpen, songInfoOpen, patternOpen, insEditOpen;
|
||||
SelectionPoint selStart, selEnd;
|
||||
bool selecting, curNibble;
|
||||
FurnaceGUIWindows curWindow;
|
||||
|
@ -94,6 +95,9 @@ class FurnaceGUI {
|
|||
|
||||
float nextScroll;
|
||||
|
||||
void updateWindowTitle();
|
||||
|
||||
void drawEditControls();
|
||||
void drawSongInfo();
|
||||
void drawOrders();
|
||||
void drawInsList();
|
||||
|
|
Loading…
Reference in New Issue