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 keyOffAffectsArp(int ch);
virtual void setPAL(bool pal);
/**
* initialize this DivDispatch.

View File

@ -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;
}

View File

@ -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);

View File

@ -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*));

View File

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

View File

@ -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;
}

View File

@ -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();

View File

@ -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();

View File

@ -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);

View File

@ -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();

View File

@ -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();

View File

@ -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();

View File

@ -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;

View File

@ -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();

View File

@ -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;

View File

@ -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();

View File

@ -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();
}
}

View File

@ -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),

View File

@ -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();