Merge remote-tracking branch 'upstream/master' into es5506_alt

This commit is contained in:
cam900 2022-05-31 12:18:46 +09:00
commit a3bca9efa7
20 changed files with 184 additions and 94 deletions

View file

@ -17,7 +17,6 @@
- volume commands should work on Game Boy - volume commands should work on Game Boy
- add another FM editor layout - add another FM editor layout
- if macros have release, note off should release them - if macros have release, note off should release them
- add ability to select a column by double clicking
- add ability to move selection by dragging - add ability to move selection by dragging
- Apply button in settings - Apply button in settings
- find and replace - find and replace

View file

@ -566,9 +566,8 @@ struct ImBitArray
void SetBit(int n) { n += OFFSET; IM_ASSERT(n >= 0 && n < BITCOUNT); ImBitArraySetBit(Storage, n); } void SetBit(int n) { n += OFFSET; IM_ASSERT(n >= 0 && n < BITCOUNT); ImBitArraySetBit(Storage, n); }
void ClearBit(int n) { n += OFFSET; IM_ASSERT(n >= 0 && n < BITCOUNT); ImBitArrayClearBit(Storage, n); } void ClearBit(int n) { n += OFFSET; IM_ASSERT(n >= 0 && n < BITCOUNT); ImBitArrayClearBit(Storage, n); }
void SetBitRange(int n, int n2) { n += OFFSET; n2 += OFFSET; IM_ASSERT(n >= 0 && n < BITCOUNT && n2 > n && n2 <= BITCOUNT); ImBitArraySetBitRange(Storage, n, n2); } // Works on range [n..n2) void SetBitRange(int n, int n2) { n += OFFSET; n2 += OFFSET; IM_ASSERT(n >= 0 && n < BITCOUNT && n2 > n && n2 <= BITCOUNT); ImBitArraySetBitRange(Storage, n, n2); } // Works on range [n..n2)
bool operator[](int n) const { n += OFFSET; IM_ASSERT(n >= 0 && n < BITCOUNT); return ImBitArrayTestBit(Storage, n); } bool operator[](int n) const { return TestBit(n); }
ImBitArray& operator|=(int n) { n += OFFSET; IM_ASSERT(n >= 0 && n < BITCOUNT); ImBitArraySetBit(Storage, n); return *this; } bool operator&(int n) const { return TestBit(n); }
bool operator&(int n) const { n += OFFSET; IM_ASSERT(n >= 0 && n < BITCOUNT); return ImBitArrayTestBit(Storage, n); }
bool operator==(ImBitArray const &a) const bool operator==(ImBitArray const &a) const
{ {
for (int i = 0; i < ((BITCOUNT + 31) >> 5); ++i) for (int i = 0; i < ((BITCOUNT + 31) >> 5); ++i)
@ -614,23 +613,17 @@ struct IMGUI_API ImBitVector
void SetBit(int n) { IM_ASSERT(n >= 0 && n < BitCount); ImBitArraySetBit(Storage.Data, n); } void SetBit(int n) { IM_ASSERT(n >= 0 && n < BitCount); ImBitArraySetBit(Storage.Data, n); }
void SetBitRange(int n, int n2) { IM_ASSERT(n >= 0 && n < BitCount && n2 > n && n2 <= BitCount); ImBitArraySetBitRange(Storage.Data, n, n2); } // Works on range [n..n2) void SetBitRange(int n, int n2) { IM_ASSERT(n >= 0 && n < BitCount && n2 > n && n2 <= BitCount); ImBitArraySetBitRange(Storage.Data, n, n2); } // Works on range [n..n2)
void ClearBit(int n) { IM_ASSERT(n >= 0 && n < BitCount); ImBitArrayClearBit(Storage.Data, n); } void ClearBit(int n) { IM_ASSERT(n >= 0 && n < BitCount); ImBitArrayClearBit(Storage.Data, n); }
bool operator[](int n) const { IM_ASSERT(n >= 0 && n < BitCount); return ImBitArrayTestBit(Storage.Data, n); } bool CheckEqual(ImBitVector const &a) const
ImBitVector& operator|=(int n) { IM_ASSERT(n >= 0 && n < BitCount); ImBitArraySetBit(Storage.Data, n); return *this; }
bool operator&(int n) const { IM_ASSERT(n >= 0 && n < BitCount); return ImBitArrayTestBit(Storage.Data, n); }
bool operator==(ImBitVector const &a) const
{ {
for (int i = 0; i < ImMin((a.BitCount + 31) >> 5, (BitCount + 31) >> 5); ++i) for (int i = 0; i < ImMin((a.BitCount + 31) >> 5, (BitCount + 31) >> 5); ++i)
if (Storage[i] != a.Storage[i]) if (Storage[i] != a.Storage[i])
return false; return false;
return true; return true;
} }
bool operator!=(ImBitVector const &a) const bool operator[](int n) const { return TestBit(n); }
{ bool operator&(int n) const { return TestBit(n); }
for (int i = 0; i < ImMin((a.BitCount + 31) >> 5, (BitCount + 31) >> 5); ++i) bool operator==(ImBitVector const &a) const { return CheckEqual(a); }
if (Storage[i] == a.Storage[i]) bool operator!=(ImBitVector const &a) const { return !CheckEqual(a); }
return false;
return true;
}
}; };
// Helper: ImSpan<> // Helper: ImSpan<>
@ -2503,8 +2496,8 @@ struct IMGUI_API ImGuiTabBar
#define IMGUI_TABLE_DRAW_CHANNELS(c) (4 + (c) * 2) // See TableSetupDrawChannels() #define IMGUI_TABLE_DRAW_CHANNELS(c) (4 + (c) * 2) // See TableSetupDrawChannels()
// Our current column maximum is IMGUI_TABLE_MAX_COLUMNS but we may raise that in the future. // Our current column maximum is IMGUI_TABLE_MAX_COLUMNS but we may raise that in the future.
typedef ImS32 ImGuiTableColumnIdx; typedef ImS16 ImGuiTableColumnIdx;
typedef ImU32 ImGuiTableDrawChannelIdx; typedef ImU16 ImGuiTableDrawChannelIdx;
// [Internal] sizeof() ~ 104 // [Internal] sizeof() ~ 104
// We use the terminology "Enabled" to refer to a column that is not Hidden by user/api. // We use the terminology "Enabled" to refer to a column that is not Hidden by user/api.
@ -2563,7 +2556,7 @@ struct ImGuiTableColumn
PrevEnabledColumn = NextEnabledColumn = -1; PrevEnabledColumn = NextEnabledColumn = -1;
SortOrder = -1; SortOrder = -1;
SortDirection = ImGuiSortDirection_None; SortDirection = ImGuiSortDirection_None;
DrawChannelCurrent = DrawChannelFrozen = DrawChannelUnfrozen = (ImU32)-1; DrawChannelCurrent = DrawChannelFrozen = DrawChannelUnfrozen = (ImU16)-1;
} }
}; };

View file

@ -797,8 +797,8 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
else else
table->LeftMostEnabledColumn = (ImGuiTableColumnIdx)column_n; table->LeftMostEnabledColumn = (ImGuiTableColumnIdx)column_n;
column->IndexWithinEnabledSet = table->ColumnsEnabledCount++; column->IndexWithinEnabledSet = table->ColumnsEnabledCount++;
table->EnabledMaskByIndex |= column_n; table->EnabledMaskByIndex.SetBit(column_n);
table->EnabledMaskByDisplayOrder |= column->DisplayOrder; table->EnabledMaskByDisplayOrder.SetBit(column->DisplayOrder);
prev_visible_column_idx = column_n; prev_visible_column_idx = column_n;
IM_ASSERT(column->IndexWithinEnabledSet <= column->DisplayOrder); IM_ASSERT(column->IndexWithinEnabledSet <= column->DisplayOrder);
@ -846,7 +846,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
table->LeftMostStretchedColumn = table->RightMostStretchedColumn = -1; table->LeftMostStretchedColumn = table->RightMostStretchedColumn = -1;
for (int column_n = 0; column_n < table->ColumnsCount; column_n++) for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
{ {
if (!(table->EnabledMaskByIndex & column_n)) if (!table->EnabledMaskByIndex.TestBit(column_n))
continue; continue;
ImGuiTableColumn* column = &table->Columns[column_n]; ImGuiTableColumn* column = &table->Columns[column_n];
@ -862,7 +862,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
// Latch initial size for fixed columns and update it constantly for auto-resizing column (unless clipped!) // Latch initial size for fixed columns and update it constantly for auto-resizing column (unless clipped!)
if (column->AutoFitQueue != 0x00) if (column->AutoFitQueue != 0x00)
column->WidthRequest = width_auto; column->WidthRequest = width_auto;
else if ((column->Flags & ImGuiTableColumnFlags_WidthFixed) && !column_is_resizable && (table->RequestOutputMaskByIndex & column_n)) else if ((column->Flags & ImGuiTableColumnFlags_WidthFixed) && !column_is_resizable && (table->RequestOutputMaskByIndex.TestBit(column_n)))
column->WidthRequest = width_auto; column->WidthRequest = width_auto;
// FIXME-TABLE: Increase minimum size during init frame to avoid biasing auto-fitting widgets // FIXME-TABLE: Increase minimum size during init frame to avoid biasing auto-fitting widgets
@ -909,7 +909,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
table->ColumnsGivenWidth = width_spacings + (table->CellPaddingX * 2.0f) * table->ColumnsEnabledCount; table->ColumnsGivenWidth = width_spacings + (table->CellPaddingX * 2.0f) * table->ColumnsEnabledCount;
for (int column_n = 0; column_n < table->ColumnsCount; column_n++) for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
{ {
if (!(table->EnabledMaskByIndex & column_n)) if (!table->EnabledMaskByIndex.TestBit(column_n))
continue; continue;
ImGuiTableColumn* column = &table->Columns[column_n]; ImGuiTableColumn* column = &table->Columns[column_n];
@ -936,7 +936,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
if (width_remaining_for_stretched_columns >= 1.0f && !(table->Flags & ImGuiTableFlags_PreciseWidths)) if (width_remaining_for_stretched_columns >= 1.0f && !(table->Flags & ImGuiTableFlags_PreciseWidths))
for (int order_n = table->ColumnsCount - 1; stretch_sum_weights > 0.0f && width_remaining_for_stretched_columns >= 1.0f && order_n >= 0; order_n--) for (int order_n = table->ColumnsCount - 1; stretch_sum_weights > 0.0f && width_remaining_for_stretched_columns >= 1.0f && order_n >= 0; order_n--)
{ {
if (!(table->EnabledMaskByDisplayOrder & order_n)) if (!table->EnabledMaskByDisplayOrder.TestBit(order_n))
continue; continue;
ImGuiTableColumn* column = &table->Columns[table->DisplayOrderToIndex[order_n]]; ImGuiTableColumn* column = &table->Columns[table->DisplayOrderToIndex[order_n]];
if (!(column->Flags & ImGuiTableColumnFlags_WidthStretch)) if (!(column->Flags & ImGuiTableColumnFlags_WidthStretch))
@ -977,7 +977,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
// Clear status flags // Clear status flags
column->Flags &= ~ImGuiTableColumnFlags_StatusMask_; column->Flags &= ~ImGuiTableColumnFlags_StatusMask_;
if ((table->EnabledMaskByDisplayOrder & order_n) == 0) if (!table->EnabledMaskByDisplayOrder.TestBit(order_n))
{ {
// Hidden column: clear a few fields and we are done with it for the remainder of the function. // Hidden column: clear a few fields and we are done with it for the remainder of the function.
// We set a zero-width clip rect but set Min.y/Max.y properly to not interfere with the clipper. // We set a zero-width clip rect but set Min.y/Max.y properly to not interfere with the clipper.
@ -1030,12 +1030,12 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
column->IsVisibleY = true; // (column->ClipRect.Max.y > column->ClipRect.Min.y); column->IsVisibleY = true; // (column->ClipRect.Max.y > column->ClipRect.Min.y);
const bool is_visible = column->IsVisibleX; //&& column->IsVisibleY; const bool is_visible = column->IsVisibleX; //&& column->IsVisibleY;
if (is_visible) if (is_visible)
table->VisibleMaskByIndex |= column_n; table->VisibleMaskByIndex.SetBit(column_n);
// Mark column as requesting output from user. Note that fixed + non-resizable sets are auto-fitting at all times and therefore always request output. // Mark column as requesting output from user. Note that fixed + non-resizable sets are auto-fitting at all times and therefore always request output.
column->IsRequestOutput = is_visible || column->AutoFitQueue != 0 || column->CannotSkipItemsQueue != 0; column->IsRequestOutput = is_visible || column->AutoFitQueue != 0 || column->CannotSkipItemsQueue != 0;
if (column->IsRequestOutput) if (column->IsRequestOutput)
table->RequestOutputMaskByIndex |= column_n; table->RequestOutputMaskByIndex.SetBit(column_n);
// Mark column as SkipItems (ignoring all items/layout) // Mark column as SkipItems (ignoring all items/layout)
column->IsSkipItems = !column->IsEnabled || table->HostSkipItems; column->IsSkipItems = !column->IsEnabled || table->HostSkipItems;
@ -1163,7 +1163,7 @@ void ImGui::TableUpdateBorders(ImGuiTable* table)
for (int order_n = 0; order_n < table->ColumnsCount; order_n++) for (int order_n = 0; order_n < table->ColumnsCount; order_n++)
{ {
if (!(table->EnabledMaskByDisplayOrder & order_n)) if (!table->EnabledMaskByDisplayOrder.TestBit(order_n))
continue; continue;
const int column_n = table->DisplayOrderToIndex[order_n]; const int column_n = table->DisplayOrderToIndex[order_n];
@ -1299,7 +1299,7 @@ void ImGui::EndTable()
float auto_fit_width_for_stretched = 0.0f; float auto_fit_width_for_stretched = 0.0f;
float auto_fit_width_for_stretched_min = 0.0f; float auto_fit_width_for_stretched_min = 0.0f;
for (int column_n = 0; column_n < table->ColumnsCount; column_n++) for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
if (table->EnabledMaskByIndex & column_n) if (table->EnabledMaskByIndex.TestBit(column_n))
{ {
ImGuiTableColumn* column = &table->Columns[column_n]; ImGuiTableColumn* column = &table->Columns[column_n];
float column_width_request = ((column->Flags & ImGuiTableColumnFlags_WidthFixed) && !(column->Flags & ImGuiTableColumnFlags_NoResize)) ? column->WidthRequest : TableGetColumnWidthAuto(table, column); float column_width_request = ((column->Flags & ImGuiTableColumnFlags_WidthFixed) && !(column->Flags & ImGuiTableColumnFlags_NoResize)) ? column->WidthRequest : TableGetColumnWidthAuto(table, column);
@ -1645,7 +1645,7 @@ void ImGui::TableSetBgColor(ImGuiTableBgTarget target, ImU32 color, int column_n
return; return;
if (column_n == -1) if (column_n == -1)
column_n = table->CurrentColumn; column_n = table->CurrentColumn;
if ((table->VisibleMaskByIndex & column_n) == 0) if (!table->VisibleMaskByIndex.TestBit(column_n))
return; return;
if (table->RowCellDataCurrent < 0 || table->RowCellData[table->RowCellDataCurrent].Column != column_n) if (table->RowCellDataCurrent < 0 || table->RowCellData[table->RowCellDataCurrent].Column != column_n)
table->RowCellDataCurrent++; table->RowCellDataCurrent++;
@ -1920,7 +1920,7 @@ bool ImGui::TableSetColumnIndex(int column_n)
// Return whether the column is visible. User may choose to skip submitting items based on this return value, // Return whether the column is visible. User may choose to skip submitting items based on this return value,
// however they shouldn't skip submitting for columns that may have the tallest contribution to row height. // however they shouldn't skip submitting for columns that may have the tallest contribution to row height.
return (table->RequestOutputMaskByIndex & column_n) != 0; return table->RequestOutputMaskByIndex.TestBit(column_n);
} }
// [Public] Append into the next column, wrap and create a new row when already on last column // [Public] Append into the next column, wrap and create a new row when already on last column
@ -1946,7 +1946,7 @@ bool ImGui::TableNextColumn()
// Return whether the column is visible. User may choose to skip submitting items based on this return value, // Return whether the column is visible. User may choose to skip submitting items based on this return value,
// however they shouldn't skip submitting for columns that may have the tallest contribution to row height. // however they shouldn't skip submitting for columns that may have the tallest contribution to row height.
int column_n = table->CurrentColumn; int column_n = table->CurrentColumn;
return (table->RequestOutputMaskByIndex & column_n) != 0; return table->RequestOutputMaskByIndex.TestBit(column_n);
} }
@ -1998,11 +1998,6 @@ void ImGui::TableBeginCell(ImGuiTable* table, int column_n)
{ {
// FIXME-TABLE: Could avoid this if draw channel is dummy channel? // FIXME-TABLE: Could avoid this if draw channel is dummy channel?
SetWindowClipRectBeforeSetChannel(window, column->ClipRect); SetWindowClipRectBeforeSetChannel(window, column->ClipRect);
if (column->DrawChannelCurrent==(ImGuiTableDrawChannelIdx)-1) {
// temporary workaround for #502
//printf("sorry!\n");
column->DrawChannelCurrent=column_n;
}
table->DrawSplitter->SetCurrentChannel(window->DrawList, column->DrawChannelCurrent); table->DrawSplitter->SetCurrentChannel(window->DrawList, column->DrawChannelCurrent);
} }
@ -2380,7 +2375,7 @@ void ImGui::TableMergeDrawChannels(ImGuiTable* table)
// 1. Scan channels and take note of those which can be merged // 1. Scan channels and take note of those which can be merged
for (int column_n = 0; column_n < table->ColumnsCount; column_n++) for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
{ {
if ((table->VisibleMaskByIndex & column_n) == 0) if (!table->VisibleMaskByIndex.TestBit(column_n))
continue; continue;
ImGuiTableColumn* column = &table->Columns[column_n]; ImGuiTableColumn* column = &table->Columns[column_n];
@ -2544,7 +2539,7 @@ void ImGui::TableDrawBorders(ImGuiTable* table)
{ {
for (int order_n = 0; order_n < table->ColumnsCount; order_n++) for (int order_n = 0; order_n < table->ColumnsCount; order_n++)
{ {
if (!(table->EnabledMaskByDisplayOrder & order_n)) if (!table->EnabledMaskByDisplayOrder.TestBit(order_n))
continue; continue;
const int column_n = table->DisplayOrderToIndex[order_n]; const int column_n = table->DisplayOrderToIndex[order_n];

View file

@ -2160,6 +2160,7 @@ void DivEngine::delSample(int index) {
void DivEngine::addOrder(bool duplicate, bool where) { void DivEngine::addOrder(bool duplicate, bool where) {
unsigned char order[DIV_MAX_CHANS]; unsigned char order[DIV_MAX_CHANS];
if (curSubSong->ordersLen>=0xff) return; if (curSubSong->ordersLen>=0xff) return;
memset(order,0,DIV_MAX_CHANS);
BUSY_BEGIN_SOFT; BUSY_BEGIN_SOFT;
if (duplicate) { if (duplicate) {
for (int i=0; i<DIV_MAX_CHANS; i++) { for (int i=0; i<DIV_MAX_CHANS; i++) {
@ -2986,6 +2987,9 @@ bool DivEngine::init() {
oscBuf[0]=new float[32768]; oscBuf[0]=new float[32768];
oscBuf[1]=new float[32768]; oscBuf[1]=new float[32768];
memset(oscBuf[0],0,32768*sizeof(float));
memset(oscBuf[1],0,32768*sizeof(float));
initDispatch(); initDispatch();
renderSamples(); renderSamples();
reset(); reset();

View file

@ -61,6 +61,7 @@ enum DivInstrumentType: unsigned short {
DIV_INS_SNES=29, DIV_INS_SNES=29,
DIV_INS_SU=30, DIV_INS_SU=30,
DIV_INS_NAMCO=31, DIV_INS_NAMCO=31,
DIV_INS_OPL_DRUMS=32,
DIV_INS_MAX, DIV_INS_MAX,
DIV_INS_NULL DIV_INS_NULL
}; };

View file

@ -179,6 +179,11 @@ int DivPlatformGenesisExt::dispatch(DivCommand c) {
rWrite(0x22,lfoValue); rWrite(0x22,lfoValue);
break; break;
} }
case DIV_CMD_FM_FB: {
chan[2].state.fb=c.value&7;
rWrite(chanOffs[2]+ADDR_FB_ALG,(chan[2].state.alg&7)|(chan[2].state.fb<<3));
break;
}
case DIV_CMD_FM_MULT: { // TODO case DIV_CMD_FM_MULT: { // TODO
unsigned short baseAddr=chanOffs[2]|opOffs[orderedOps[c.value]]; unsigned short baseAddr=chanOffs[2]|opOffs[orderedOps[c.value]];
DivInstrumentFM::Operator& op=chan[2].state.op[orderedOps[c.value]]; DivInstrumentFM::Operator& op=chan[2].state.op[orderedOps[c.value]];

View file

@ -155,6 +155,11 @@ int DivPlatformYM2203Ext::dispatch(DivCommand c) {
rWrite(0x22,(c.value&7)|((c.value>>4)<<3)); rWrite(0x22,(c.value&7)|((c.value>>4)<<3));
break; break;
} }
case DIV_CMD_FM_FB: {
chan[2].state.fb=c.value&7;
rWrite(chanOffs[2]+ADDR_FB_ALG,(chan[2].state.alg&7)|(chan[2].state.fb<<3));
break;
}
case DIV_CMD_FM_MULT: { // TODO case DIV_CMD_FM_MULT: { // TODO
unsigned short baseAddr=chanOffs[2]|opOffs[orderedOps[c.value]]; unsigned short baseAddr=chanOffs[2]|opOffs[orderedOps[c.value]];
DivInstrument* ins=parent->getIns(opChan[ch].ins,DIV_INS_FM); DivInstrument* ins=parent->getIns(opChan[ch].ins,DIV_INS_FM);

View file

@ -155,6 +155,11 @@ int DivPlatformYM2608Ext::dispatch(DivCommand c) {
rWrite(0x22,(c.value&7)|((c.value>>4)<<3)); rWrite(0x22,(c.value&7)|((c.value>>4)<<3));
break; break;
} }
case DIV_CMD_FM_FB: {
chan[2].state.fb=c.value&7;
rWrite(chanOffs[2]+ADDR_FB_ALG,(chan[2].state.alg&7)|(chan[2].state.fb<<3));
break;
}
case DIV_CMD_FM_MULT: { // TODO case DIV_CMD_FM_MULT: { // TODO
unsigned short baseAddr=chanOffs[2]|opOffs[orderedOps[c.value]]; unsigned short baseAddr=chanOffs[2]|opOffs[orderedOps[c.value]];
DivInstrument* ins=parent->getIns(opChan[ch].ins,DIV_INS_FM); DivInstrument* ins=parent->getIns(opChan[ch].ins,DIV_INS_FM);

View file

@ -155,6 +155,11 @@ int DivPlatformYM2610BExt::dispatch(DivCommand c) {
rWrite(0x22,(c.value&7)|((c.value>>4)<<3)); rWrite(0x22,(c.value&7)|((c.value>>4)<<3));
break; break;
} }
case DIV_CMD_FM_FB: {
chan[2].state.fb=c.value&7;
rWrite(chanOffs[2]+ADDR_FB_ALG,(chan[2].state.alg&7)|(chan[2].state.fb<<3));
break;
}
case DIV_CMD_FM_MULT: { // TODO case DIV_CMD_FM_MULT: { // TODO
unsigned short baseAddr=chanOffs[2]|opOffs[orderedOps[c.value]]; unsigned short baseAddr=chanOffs[2]|opOffs[orderedOps[c.value]];
DivInstrument* ins=parent->getIns(opChan[ch].ins,DIV_INS_FM); DivInstrument* ins=parent->getIns(opChan[ch].ins,DIV_INS_FM);

View file

@ -155,6 +155,11 @@ int DivPlatformYM2610Ext::dispatch(DivCommand c) {
rWrite(0x22,(c.value&7)|((c.value>>4)<<3)); rWrite(0x22,(c.value&7)|((c.value>>4)<<3));
break; break;
} }
case DIV_CMD_FM_FB: {
chan[1].state.fb=c.value&7;
rWrite(chanOffs[1]+ADDR_FB_ALG,(chan[1].state.alg&7)|(chan[1].state.fb<<3));
break;
}
case DIV_CMD_FM_MULT: { // TODO case DIV_CMD_FM_MULT: { // TODO
unsigned short baseAddr=chanOffs[1]|opOffs[orderedOps[c.value]]; unsigned short baseAddr=chanOffs[1]|opOffs[orderedOps[c.value]];
DivInstrument* ins=parent->getIns(opChan[ch].ins,DIV_INS_FM); DivInstrument* ins=parent->getIns(opChan[ch].ins,DIV_INS_FM);

View file

@ -409,7 +409,7 @@ struct DivSong {
std::vector<DivSubSong*> subsong; std::vector<DivSubSong*> subsong;
DivInstrument nullIns, nullInsOPLL, nullInsOPL, nullInsQSound; DivInstrument nullIns, nullInsOPLL, nullInsOPL, nullInsOPLDrums, nullInsQSound;
DivWavetable nullWave; DivWavetable nullWave;
DivSample nullSample; DivSample nullSample;
@ -552,6 +552,9 @@ struct DivSong {
nullInsOPL.fm.op[1].rr=12; nullInsOPL.fm.op[1].rr=12;
nullInsOPL.fm.op[1].mult=1; nullInsOPL.fm.op[1].mult=1;
nullInsOPL.name="This is a bug! Report!"; nullInsOPL.name="This is a bug! Report!";
nullInsOPL.fm.kickFreq=0x520;
nullInsOPL.fm.snareHatFreq=0x550;
nullInsOPL.fm.tomTopFreq=0x1c0;
nullInsQSound.std.panLMacro.mode=true; nullInsQSound.std.panLMacro.mode=true;
} }

View file

@ -19,6 +19,7 @@
#include "dispatch.h" #include "dispatch.h"
#include "engine.h" #include "engine.h"
#include "instrument.h"
#include "song.h" #include "song.h"
#include "../ta-log.h" #include "../ta-log.h"
@ -1579,11 +1580,11 @@ void DivEngine::registerSystems() {
sysDefs[DIV_SYSTEM_OPL_DRUMS]=new DivSysDef( sysDefs[DIV_SYSTEM_OPL_DRUMS]=new DivSysDef(
"Yamaha YM3526 (OPL) with drums", NULL, 0xa2, 0, 11, true, false, 0x151, false, "Yamaha YM3526 (OPL) with drums", NULL, 0xa2, 0, 11, true, false, 0x151, false,
"the OPL chip but with drums mode enabled.", "the OPL chip but with drums mode enabled.",
{"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "Kick", "Snare", "Tom", "Top", "HiHat"}, {"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "Kick/FM 7", "Snare", "Tom", "Top", "HiHat"},
{"F1", "F2", "F3", "F4", "F5", "F6", "BD", "SD", "TM", "TP", "HH"}, {"F1", "F2", "F3", "F4", "F5", "F6", "BD", "SD", "TM", "TP", "HH"},
{DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE}, {DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE},
{DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL}, {DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL_DRUMS, DIV_INS_OPL_DRUMS, DIV_INS_OPL_DRUMS, DIV_INS_OPL_DRUMS},
{}, {DIV_INS_NULL, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL},
oplDrumsEffectHandler, oplDrumsEffectHandler,
fmOPLPostEffectHandler fmOPLPostEffectHandler
); );
@ -1591,11 +1592,11 @@ void DivEngine::registerSystems() {
sysDefs[DIV_SYSTEM_OPL2_DRUMS]=new DivSysDef( sysDefs[DIV_SYSTEM_OPL2_DRUMS]=new DivSysDef(
"Yamaha YM3812 (OPL2) with drums", NULL, 0xa3, 0, 11, true, false, 0x151, false, "Yamaha YM3812 (OPL2) with drums", NULL, 0xa3, 0, 11, true, false, 0x151, false,
"the OPL2 chip but with drums mode enabled.", "the OPL2 chip but with drums mode enabled.",
{"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "Kick", "Snare", "Tom", "Top", "HiHat"}, {"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "Kick/FM 7", "Snare", "Tom", "Top", "HiHat"},
{"F1", "F2", "F3", "F4", "F5", "F6", "BD", "SD", "TM", "TP", "HH"}, {"F1", "F2", "F3", "F4", "F5", "F6", "BD", "SD", "TM", "TP", "HH"},
{DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE}, {DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE},
{DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL}, {DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL_DRUMS, DIV_INS_OPL_DRUMS, DIV_INS_OPL_DRUMS, DIV_INS_OPL_DRUMS},
{}, {DIV_INS_NULL, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL},
oplDrumsEffectHandler, oplDrumsEffectHandler,
fmOPLPostEffectHandler fmOPLPostEffectHandler
); );
@ -1603,11 +1604,11 @@ void DivEngine::registerSystems() {
sysDefs[DIV_SYSTEM_OPL3_DRUMS]=new DivSysDef( sysDefs[DIV_SYSTEM_OPL3_DRUMS]=new DivSysDef(
"Yamaha YMF262 (OPL3) with drums", NULL, 0xa4, 0, 20, true, false, 0x151, false, "Yamaha YMF262 (OPL3) with drums", NULL, 0xa4, 0, 20, true, false, 0x151, false,
"the OPL3 chip but with drums mode enabled.", "the OPL3 chip but with drums mode enabled.",
{"4OP 1", "FM 2", "4OP 3", "FM 4", "4OP 5", "FM 6", "4OP 7", "FM 8", "4OP 9", "FM 10", "4OP 11", "FM 12", "FM 13", "FM 14", "FM 15", "Kick", "Snare", "Tom", "Top", "HiHat"}, {"4OP 1", "FM 2", "4OP 3", "FM 4", "4OP 5", "FM 6", "4OP 7", "FM 8", "4OP 9", "FM 10", "4OP 11", "FM 12", "FM 13", "FM 14", "FM 15", "Kick/FM 16", "Snare", "Tom", "Top", "HiHat"},
{"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "BD", "SD", "TM", "TP", "HH"}, {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "BD", "SD", "TM", "TP", "HH"},
{DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE}, {DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE},
{DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL}, {DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL_DRUMS, DIV_INS_OPL_DRUMS, DIV_INS_OPL_DRUMS, DIV_INS_OPL_DRUMS},
{}, {DIV_INS_NULL, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL},
oplDrumsEffectHandler, oplDrumsEffectHandler,
fmOPLPostEffectHandler fmOPLPostEffectHandler
); );
@ -1820,7 +1821,7 @@ void DivEngine::registerSystems() {
sysDefs[DIV_SYSTEM_OPL4_DRUMS]=new DivSysDef( sysDefs[DIV_SYSTEM_OPL4_DRUMS]=new DivSysDef(
"Yamaha OPL4 with drums", NULL, 0xaf, 0, 44, true, true, 0, false, "Yamaha OPL4 with drums", NULL, 0xaf, 0, 44, true, true, 0, false,
"the OPL4 but with drums mode turned on.", "the OPL4 but with drums mode turned on.",
{"4OP 1", "FM 2", "4OP 3", "FM 4", "4OP 5", "FM 6", "4OP 7", "FM 8", "4OP 9", "FM 10", "4OP 11", "FM 12", "FM 13", "FM 14", "FM 15", "Kick", "Snare", "Tom", "Top", "HiHat", "PCM 1", "PCM 2", "PCM 3", "PCM 4", "PCM 5", "PCM 6", "PCM 7", "PCM 8", "PCM 9", "PCM 10", "PCM 11", "PCM 12", "PCM 13", "PCM 14", "PCM 15", "PCM 16", "PCM 17", "PCM 18", "PCM 19", "PCM 20", "PCM 21", "PCM 22", "PCM 23", "PCM 24"}, {"4OP 1", "FM 2", "4OP 3", "FM 4", "4OP 5", "FM 6", "4OP 7", "FM 8", "4OP 9", "FM 10", "4OP 11", "FM 12", "FM 13", "FM 14", "FM 15", "Kick/FM 16", "Snare", "Tom", "Top", "HiHat", "PCM 1", "PCM 2", "PCM 3", "PCM 4", "PCM 5", "PCM 6", "PCM 7", "PCM 8", "PCM 9", "PCM 10", "PCM 11", "PCM 12", "PCM 13", "PCM 14", "PCM 15", "PCM 16", "PCM 17", "PCM 18", "PCM 19", "PCM 20", "PCM 21", "PCM 22", "PCM 23", "PCM 24"},
{"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", "F13", "F14", "F15", "BD", "SD", "TM", "TP", "HH", "P1", "P2", "P3", "P4", "P5", "P6", "P7", "P8", "P8", "P10", "P11", "P12", "P13", "P14", "P15", "P16", "P17", "P18", "P19", "P20", "P21", "P22", "P23", "P24"}, {"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", "F13", "F14", "F15", "BD", "SD", "TM", "TP", "HH", "P1", "P2", "P3", "P4", "P5", "P6", "P7", "P8", "P8", "P10", "P11", "P12", "P13", "P14", "P15", "P16", "P17", "P18", "P19", "P20", "P21", "P22", "P23", "P24"},
{DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM}, {DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM},
{DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM} {DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM}
@ -1928,11 +1929,11 @@ void DivEngine::registerSystems() {
sysDefs[DIV_SYSTEM_Y8950_DRUMS]=new DivSysDef( sysDefs[DIV_SYSTEM_Y8950_DRUMS]=new DivSysDef(
"Yamaha Y8950 with drums", NULL, 0xb3, 0, 12, true, false, 0x151, false, "Yamaha Y8950 with drums", NULL, 0xb3, 0, 12, true, false, 0x151, false,
"the Y8950 chip, in drums mode.", "the Y8950 chip, in drums mode.",
{"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "Kick", "Snare", "Tom", "Top", "HiHat", "PCM"}, {"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "Kick/FM 7", "Snare", "Tom", "Top", "HiHat", "PCM"},
{"F1", "F2", "F3", "F4", "F5", "F6", "BD", "SD", "TM", "TP", "HH", "PCM"}, {"F1", "F2", "F3", "F4", "F5", "F6", "BD", "SD", "TM", "TP", "HH", "PCM"},
{DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_PCM}, {DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_PCM},
{DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_AMIGA}, {DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL_DRUMS, DIV_INS_OPL_DRUMS, DIV_INS_OPL_DRUMS, DIV_INS_OPL_DRUMS, DIV_INS_AMIGA},
{}, {DIV_INS_NULL, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_NULL},
oplEffectHandler, oplEffectHandler,
fmOPLPostEffectHandler fmOPLPostEffectHandler
); );

View file

@ -27,6 +27,21 @@ void FurnaceGUI::startSelection(int xCoarse, int xFine, int y, bool fullRow) {
if (xCoarse!=selStart.xCoarse || xFine!=selStart.xFine || y!=selStart.y) { if (xCoarse!=selStart.xCoarse || xFine!=selStart.xFine || y!=selStart.y) {
curNibble=false; curNibble=false;
} }
if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left) && !fullRow && settings.doubleClickColumn) {
if (cursor.xCoarse==xCoarse && cursor.xFine==xFine && cursor.y==y) {
// select entire channel
selStart.xCoarse=xCoarse;
selStart.xFine=0;
selStart.y=0;
selEnd.xCoarse=xCoarse;
selEnd.xFine=2+e->curPat[selEnd.xCoarse].effectCols*2;
selEnd.y=e->curSubSong->patLen-1;
finishSelection();
return;
}
}
if (fullRow) { if (fullRow) {
selStart.xCoarse=firstChannel; selStart.xCoarse=firstChannel;
@ -314,4 +329,4 @@ void FurnaceGUI::editAdvance() {
selStart=cursor; selStart=cursor;
selEnd=cursor; selEnd=cursor;
updateScroll(cursor.y); updateScroll(cursor.y);
} }

View file

@ -313,6 +313,10 @@ void FurnaceGUI::drawInsList() {
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_INSTR_NAMCO]); ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_INSTR_NAMCO]);
name=fmt::sprintf(ICON_FA_PIE_CHART " %.2X: %s##_INS%d",i,ins->name,i); name=fmt::sprintf(ICON_FA_PIE_CHART " %.2X: %s##_INS%d",i,ins->name,i);
break; break;
case DIV_INS_OPL_DRUMS:
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_INSTR_OPL_DRUMS]);
name=fmt::sprintf(ICON_FA_COFFEE " %.2X: %s##_INS%d",i,ins->name,i);
break;
default: default:
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_INSTR_UNKNOWN]); ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_INSTR_UNKNOWN]);
name=fmt::sprintf(ICON_FA_QUESTION " %.2X: %s##_INS%d",i,ins->name,i); name=fmt::sprintf(ICON_FA_QUESTION " %.2X: %s##_INS%d",i,ins->name,i);

View file

@ -3927,6 +3927,9 @@ bool FurnaceGUI::init() {
if (orderEditMode<0) orderEditMode=0; if (orderEditMode<0) orderEditMode=0;
if (orderEditMode>3) orderEditMode=3; if (orderEditMode>3) orderEditMode=3;
oscZoom=e->getConfFloat("oscZoom",0.5f);
oscWindowSize=e->getConfFloat("oscWindowSize",20.0f);
pianoOctaves=e->getConfInt("pianoOctaves",pianoOctaves); pianoOctaves=e->getConfInt("pianoOctaves",pianoOctaves);
pianoOctavesEdit=e->getConfInt("pianoOctavesEdit",pianoOctavesEdit); pianoOctavesEdit=e->getConfInt("pianoOctavesEdit",pianoOctavesEdit);
pianoOptions=e->getConfBool("pianoOptions",pianoOptions); pianoOptions=e->getConfBool("pianoOptions",pianoOptions);
@ -4137,6 +4140,10 @@ bool FurnaceGUI::finish() {
e->setConf("followPattern",followPattern); e->setConf("followPattern",followPattern);
e->setConf("orderEditMode",orderEditMode); e->setConf("orderEditMode",orderEditMode);
// commit oscilloscope state
e->setConf("oscZoom",oscZoom);
e->setConf("oscWindowSize",oscWindowSize);
// commit piano state // commit piano state
e->setConf("pianoOctaves",pianoOctaves); e->setConf("pianoOctaves",pianoOctaves);
e->setConf("pianoOctavesEdit",pianoOctavesEdit); e->setConf("pianoOctavesEdit",pianoOctavesEdit);
@ -4422,6 +4429,7 @@ FurnaceGUI::FurnaceGUI():
openSampleFilterOpt(false), openSampleFilterOpt(false),
oscTotal(0), oscTotal(0),
oscZoom(0.5f), oscZoom(0.5f),
oscWindowSize(20.0f),
oscZoomSlider(false), oscZoomSlider(false),
chanOscCols(3), chanOscCols(3),
chanOscWindowSize(20.0f), chanOscWindowSize(20.0f),

View file

@ -151,6 +151,7 @@ enum FurnaceGUIColors {
GUI_COLOR_INSTR_SNES, GUI_COLOR_INSTR_SNES,
GUI_COLOR_INSTR_SU, GUI_COLOR_INSTR_SU,
GUI_COLOR_INSTR_NAMCO, GUI_COLOR_INSTR_NAMCO,
GUI_COLOR_INSTR_OPL_DRUMS,
GUI_COLOR_INSTR_UNKNOWN, GUI_COLOR_INSTR_UNKNOWN,
GUI_COLOR_CHANNEL_FM, GUI_COLOR_CHANNEL_FM,
@ -950,6 +951,7 @@ class FurnaceGUI {
int volCellSpacing; int volCellSpacing;
int effectCellSpacing; int effectCellSpacing;
int effectValCellSpacing; int effectValCellSpacing;
int doubleClickColumn;
unsigned int maxUndoSteps; unsigned int maxUndoSteps;
String mainFontPath; String mainFontPath;
String patFontPath; String patFontPath;
@ -1048,6 +1050,7 @@ class FurnaceGUI {
volCellSpacing(0), volCellSpacing(0),
effectCellSpacing(0), effectCellSpacing(0),
effectValCellSpacing(0), effectValCellSpacing(0),
doubleClickColumn(1),
maxUndoSteps(100), maxUndoSteps(100),
mainFontPath(""), mainFontPath(""),
patFontPath(""), patFontPath(""),
@ -1238,6 +1241,7 @@ class FurnaceGUI {
int oscTotal; int oscTotal;
float oscValues[512]; float oscValues[512];
float oscZoom; float oscZoom;
float oscWindowSize;
bool oscZoomSlider; bool oscZoomSlider;
// per-channel oscilloscope // per-channel oscilloscope

View file

@ -112,6 +112,7 @@ const char* insTypes[DIV_INS_MAX+1]={
"SNES", "SNES",
"Sound Unit", "Sound Unit",
"Namco WSG", "Namco WSG",
"OPL (drums)",
NULL NULL
}; };
@ -765,6 +766,7 @@ const FurnaceGUIColorDef guiColors[GUI_COLOR_MAX]={
D(GUI_COLOR_INSTR_SNES,"",ImVec4(0.8f,0.7f,1.0f,1.0f)), D(GUI_COLOR_INSTR_SNES,"",ImVec4(0.8f,0.7f,1.0f,1.0f)),
D(GUI_COLOR_INSTR_SU,"",ImVec4(0.95f,0.98f,1.0f,1.0f)), D(GUI_COLOR_INSTR_SU,"",ImVec4(0.95f,0.98f,1.0f,1.0f)),
D(GUI_COLOR_INSTR_NAMCO,"",ImVec4(1.0f,1.0f,0.0f,1.0f)), D(GUI_COLOR_INSTR_NAMCO,"",ImVec4(1.0f,1.0f,0.0f,1.0f)),
D(GUI_COLOR_INSTR_OPL_DRUMS,"",ImVec4(0.3f,1.0f,0.9f,1.0f)),
D(GUI_COLOR_INSTR_UNKNOWN,"",ImVec4(0.3f,0.3f,0.3f,1.0f)), D(GUI_COLOR_INSTR_UNKNOWN,"",ImVec4(0.3f,0.3f,0.3f,1.0f)),
D(GUI_COLOR_CHANNEL_FM,"",ImVec4(0.2f,0.8f,1.0f,1.0f)), D(GUI_COLOR_CHANNEL_FM,"",ImVec4(0.2f,0.8f,1.0f,1.0f)),

View file

@ -75,6 +75,10 @@ const char* opzWaveforms[8]={
"Sine", "Triangle", "Cut Sine", "Cut Triangle", "Squished Sine", "Squished Triangle", "Squished AbsSine", "Squished AbsTriangle" "Sine", "Triangle", "Cut Sine", "Cut Triangle", "Squished Sine", "Squished Triangle", "Squished AbsSine", "Squished AbsTriangle"
}; };
const char* oplDrumNames[4]={
"Snare", "Tom", "Top", "HiHat"
};
const bool opIsOutput[8][4]={ const bool opIsOutput[8][4]={
{false,false,false,true}, {false,false,false,true},
{false,false,false,true}, {false,false,false,true},
@ -1537,7 +1541,7 @@ void FurnaceGUI::drawInsEdit() {
if (ImGui::BeginTabBar("insEditTab")) { if (ImGui::BeginTabBar("insEditTab")) {
std::vector<FurnaceGUIMacroDesc> macroList; std::vector<FurnaceGUIMacroDesc> macroList;
if (ins->type==DIV_INS_FM || ins->type==DIV_INS_OPL || ins->type==DIV_INS_OPLL || ins->type==DIV_INS_OPZ) { if (ins->type==DIV_INS_FM || ins->type==DIV_INS_OPL || ins->type==DIV_INS_OPLL || ins->type==DIV_INS_OPZ || ins->type==DIV_INS_OPL_DRUMS) {
char label[32]; char label[32];
int opCount=4; int opCount=4;
if (ins->type==DIV_INS_OPLL) opCount=2; if (ins->type==DIV_INS_OPLL) opCount=2;
@ -1579,22 +1583,27 @@ void FurnaceGUI::drawInsEdit() {
showError("Coming soon!"); showError("Coming soon!");
} }
break; break;
case DIV_INS_OPL: { case DIV_INS_OPL:
bool fourOp=(ins->fm.ops==4); case DIV_INS_OPL_DRUMS: {
bool fourOp=(ins->fm.ops==4 || ins->type==DIV_INS_OPL_DRUMS);
bool drums=ins->fm.opllPreset==16; bool drums=ins->fm.opllPreset==16;
int algMax=fourOp?3:1; int algMax=fourOp?3:1;
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ins->fm.alg&=algMax; ins->fm.alg&=algMax;
P(CWSliderScalar(FM_NAME(FM_FB),ImGuiDataType_U8,&ins->fm.fb,&_ZERO,&_SEVEN)); rightClickable P(CWSliderScalar(FM_NAME(FM_FB),ImGuiDataType_U8,&ins->fm.fb,&_ZERO,&_SEVEN)); rightClickable
ImGui::BeginDisabled(ins->fm.opllPreset==16); if (ins->type==DIV_INS_OPL) {
if (ImGui::Checkbox("4-op",&fourOp)) { PARAMETER ImGui::BeginDisabled(ins->fm.opllPreset==16);
ins->fm.ops=fourOp?4:2; if (ImGui::Checkbox("4-op",&fourOp)) { PARAMETER
ins->fm.ops=fourOp?4:2;
}
ImGui::EndDisabled();
} }
ImGui::EndDisabled();
ImGui::TableNextColumn(); ImGui::TableNextColumn();
P(CWSliderScalar(FM_NAME(FM_ALG),ImGuiDataType_U8,&ins->fm.alg,&_ZERO,&algMax)); rightClickable P(CWSliderScalar(FM_NAME(FM_ALG),ImGuiDataType_U8,&ins->fm.alg,&_ZERO,&algMax)); rightClickable
if (ImGui::Checkbox("Drums",&drums)) { PARAMETER if (ins->type==DIV_INS_OPL) {
ins->fm.opllPreset=drums?16:0; if (ImGui::Checkbox("Drums",&drums)) { PARAMETER
ins->fm.opllPreset=drums?16:0;
}
} }
ImGui::TableNextColumn(); ImGui::TableNextColumn();
drawAlgorithm(ins->fm.alg&algMax,fourOp?FM_ALGS_4OP_OPL:FM_ALGS_2OP_OPL,ImVec2(ImGui::GetContentRegionAvail().x,48.0*dpiScale)); drawAlgorithm(ins->fm.alg&algMax,fourOp?FM_ALGS_4OP_OPL:FM_ALGS_2OP_OPL,ImVec2(ImGui::GetContentRegionAvail().x,48.0*dpiScale));
@ -1639,7 +1648,7 @@ void FurnaceGUI::drawInsEdit() {
ImGui::EndTable(); ImGui::EndTable();
} }
if ((ins->type==DIV_INS_OPLL || ins->type==DIV_INS_OPL) && ins->fm.opllPreset==16) { if (((ins->type==DIV_INS_OPLL || ins->type==DIV_INS_OPL) && ins->fm.opllPreset==16) || ins->type==DIV_INS_OPL_DRUMS) {
ins->fm.ops=2; ins->fm.ops=2;
P(ImGui::Checkbox("Fixed frequency mode",&ins->fm.fixedDrums)); P(ImGui::Checkbox("Fixed frequency mode",&ins->fm.fixedDrums));
if (ImGui::IsItemHovered()) { if (ImGui::IsItemHovered()) {
@ -1674,7 +1683,7 @@ void FurnaceGUI::drawInsEdit() {
if (willDisplayOps) { if (willDisplayOps) {
if (settings.fmLayout==0) { if (settings.fmLayout==0) {
int numCols=16; int numCols=16;
if (ins->type==DIV_INS_OPL) numCols=13; if (ins->type==DIV_INS_OPL ||ins->type==DIV_INS_OPL_DRUMS) numCols=13;
if (ins->type==DIV_INS_OPLL) numCols=12; if (ins->type==DIV_INS_OPLL) numCols=12;
if (ins->type==DIV_INS_OPZ) numCols=19; if (ins->type==DIV_INS_OPZ) numCols=19;
if (ImGui::BeginTable("FMOperators",numCols,ImGuiTableFlags_SizingStretchProp|ImGuiTableFlags_BordersH|ImGuiTableFlags_BordersOuterV)) { if (ImGui::BeginTable("FMOperators",numCols,ImGuiTableFlags_SizingStretchProp|ImGuiTableFlags_BordersH|ImGuiTableFlags_BordersOuterV)) {
@ -1785,7 +1794,7 @@ void FurnaceGUI::drawInsEdit() {
ImGui::TextUnformatted("Other"); ImGui::TextUnformatted("Other");
} }
ImGui::TableNextColumn(); ImGui::TableNextColumn();
if (ins->type==DIV_INS_OPL || ins->type==DIV_INS_OPZ) { if (ins->type==DIV_INS_OPL || ins->type==DIV_INS_OPL_DRUMS || ins->type==DIV_INS_OPZ) {
ImGui::TableNextColumn(); ImGui::TableNextColumn();
CENTER_TEXT(FM_NAME(FM_WS)); CENTER_TEXT(FM_NAME(FM_WS));
ImGui::TextUnformatted(FM_NAME(FM_WS)); ImGui::TextUnformatted(FM_NAME(FM_WS));
@ -1801,14 +1810,16 @@ void FurnaceGUI::drawInsEdit() {
float sliderHeight=32.0f*dpiScale; float sliderHeight=32.0f*dpiScale;
for (int i=0; i<opCount; i++) { for (int i=0; i<opCount; i++) {
DivInstrumentFM::Operator& op=ins->fm.op[(opCount==4)?opOrder[i]:i]; DivInstrumentFM::Operator& op=ins->fm.op[(opCount==4 && ins->type!=DIV_INS_OPL_DRUMS)?opOrder[i]:i];
ImGui::TableNextRow(); ImGui::TableNextRow();
ImGui::TableNextColumn(); ImGui::TableNextColumn();
// push colors // push colors
if (settings.separateFMColors) { if (settings.separateFMColors) {
bool mod=true; bool mod=true;
if (opCount==4) { if (ins->type==DIV_INS_OPL_DRUMS) {
mod=false;
} else if (opCount==4) {
if (ins->type==DIV_INS_OPL) { if (ins->type==DIV_INS_OPL) {
if (opIsOutputOPL[ins->fm.alg&3][i]) mod=false; if (opIsOutputOPL[ins->fm.alg&3][i]) mod=false;
} else { } else {
@ -1837,7 +1848,9 @@ void FurnaceGUI::drawInsEdit() {
if (i==0) sliderHeight=(ImGui::GetContentRegionAvail().y/opCount)-ImGui::GetStyle().ItemSpacing.y; if (i==0) sliderHeight=(ImGui::GetContentRegionAvail().y/opCount)-ImGui::GetStyle().ItemSpacing.y;
ImGui::PushID(fmt::sprintf("op%d",i).c_str()); ImGui::PushID(fmt::sprintf("op%d",i).c_str());
if (ins->type==DIV_INS_OPL && ins->fm.opllPreset==16) { if (ins->type==DIV_INS_OPL_DRUMS) {
ImGui::Text("%s",oplDrumNames[i]);
} else if (ins->type==DIV_INS_OPL && ins->fm.opllPreset==16) {
if (i==1) { if (i==1) {
ImGui::Text("Kick"); ImGui::Text("Kick");
} else { } else {
@ -1855,7 +1868,7 @@ void FurnaceGUI::drawInsEdit() {
maxTl=63; maxTl=63;
} }
} }
if (ins->type==DIV_INS_OPL) { if (ins->type==DIV_INS_OPL || ins->type==DIV_INS_OPL_DRUMS) {
maxTl=63; maxTl=63;
} }
int maxArDr=(ins->type==DIV_INS_FM || ins->type==DIV_INS_OPZ)?31:15; int maxArDr=(ins->type==DIV_INS_FM || ins->type==DIV_INS_OPZ)?31:15;
@ -1989,7 +2002,7 @@ void FurnaceGUI::drawInsEdit() {
} }
} }
if (ins->type!=DIV_INS_OPL && ins->type!=DIV_INS_OPZ) { if (ins->type!=DIV_INS_OPL && ins->type!=DIV_INS_OPL_DRUMS && ins->type!=DIV_INS_OPZ) {
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGui::Dummy(ImVec2(4.0f*dpiScale,2.0f*dpiScale)); ImGui::Dummy(ImVec2(4.0f*dpiScale,2.0f*dpiScale));
ImGui::TableNextColumn(); ImGui::TableNextColumn();
@ -2024,7 +2037,7 @@ void FurnaceGUI::drawInsEdit() {
if (ImGui::Checkbox(FM_NAME(FM_KSR),&ksrOn)) { PARAMETER if (ImGui::Checkbox(FM_NAME(FM_KSR),&ksrOn)) { PARAMETER
op.ksr=ksrOn; op.ksr=ksrOn;
} }
if (ins->type==DIV_INS_OPL) { if (ins->type==DIV_INS_OPL || ins->type==DIV_INS_OPL_DRUMS) {
if (ImGui::Checkbox(FM_NAME(FM_SUS),&susOn)) { PARAMETER if (ImGui::Checkbox(FM_NAME(FM_SUS),&susOn)) { PARAMETER
op.sus=susOn; op.sus=susOn;
} }
@ -2035,7 +2048,7 @@ void FurnaceGUI::drawInsEdit() {
} }
} }
if (ins->type==DIV_INS_OPL || ins->type==DIV_INS_OPZ) { if (ins->type==DIV_INS_OPL || ins->type==DIV_INS_OPL_DRUMS || ins->type==DIV_INS_OPZ) {
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGui::Dummy(ImVec2(4.0f*dpiScale,2.0f*dpiScale)); ImGui::Dummy(ImVec2(4.0f*dpiScale,2.0f*dpiScale));
ImGui::TableNextColumn(); ImGui::TableNextColumn();
@ -2043,7 +2056,7 @@ void FurnaceGUI::drawInsEdit() {
drawWaveform(op.ws&7,ins->type==DIV_INS_OPZ,ImVec2(ImGui::GetContentRegionAvail().x,sliderHeight-ImGui::GetFrameHeightWithSpacing())); drawWaveform(op.ws&7,ins->type==DIV_INS_OPZ,ImVec2(ImGui::GetContentRegionAvail().x,sliderHeight-ImGui::GetFrameHeightWithSpacing()));
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
P(CWSliderScalar("##WS",ImGuiDataType_U8,&op.ws,&_ZERO,&_SEVEN,(ins->type==DIV_INS_OPZ)?opzWaveforms[op.ws&7]:(settings.oplStandardWaveNames?oplWaveformsStandard[op.ws&7]:oplWaveforms[op.ws&7]))); rightClickable P(CWSliderScalar("##WS",ImGuiDataType_U8,&op.ws,&_ZERO,&_SEVEN,(ins->type==DIV_INS_OPZ)?opzWaveforms[op.ws&7]:(settings.oplStandardWaveNames?oplWaveformsStandard[op.ws&7]:oplWaveforms[op.ws&7]))); rightClickable
if (ins->type==DIV_INS_OPL && ImGui::IsItemHovered()) { if ((ins->type==DIV_INS_OPL || ins->type==DIV_INS_OPL_DRUMS) && ImGui::IsItemHovered()) {
ImGui::SetTooltip("OPL2/3 only (last 4 waveforms are OPL3 only)"); ImGui::SetTooltip("OPL2/3 only (last 4 waveforms are OPL3 only)");
} }
} else if (ins->type==DIV_INS_OPLL) { } else if (ins->type==DIV_INS_OPLL) {
@ -2052,7 +2065,7 @@ void FurnaceGUI::drawInsEdit() {
} }
ImGui::TableNextColumn(); ImGui::TableNextColumn();
drawFMEnv(op.tl&maxTl,op.ar&maxArDr,op.dr&maxArDr,(ins->type==DIV_INS_OPL || ins->type==DIV_INS_OPLL)?((op.rr&15)*2):op.d2r&31,op.rr&15,op.sl&15,op.sus,op.ssgEnv&8,ins->fm.alg,maxTl,maxArDr,ImVec2(ImGui::GetContentRegionAvail().x,sliderHeight),ins->type); drawFMEnv(op.tl&maxTl,op.ar&maxArDr,op.dr&maxArDr,(ins->type==DIV_INS_OPL || ins->type==DIV_INS_OPL_DRUMS || ins->type==DIV_INS_OPLL)?((op.rr&15)*2):op.d2r&31,op.rr&15,op.sl&15,op.sus,op.ssgEnv&8,ins->fm.alg,maxTl,maxArDr,ImVec2(ImGui::GetContentRegionAvail().x,sliderHeight),ins->type);
if (settings.separateFMColors) { if (settings.separateFMColors) {
popAccentColors(); popAccentColors();
@ -2078,7 +2091,7 @@ void FurnaceGUI::drawInsEdit() {
} }
if (ImGui::BeginTable("FMOperators",columns,ImGuiTableFlags_SizingStretchSame)) { if (ImGui::BeginTable("FMOperators",columns,ImGuiTableFlags_SizingStretchSame)) {
for (int i=0; i<opCount; i++) { for (int i=0; i<opCount; i++) {
DivInstrumentFM::Operator& op=ins->fm.op[(opCount==4)?opOrder[i]:i]; DivInstrumentFM::Operator& op=ins->fm.op[(opCount==4 && ins->type!=DIV_INS_OPL_DRUMS)?opOrder[i]:i];
if ((settings.fmLayout!=3 && ((i+1)&1)) || i==0 || settings.fmLayout==2) ImGui::TableNextRow(); if ((settings.fmLayout!=3 && ((i+1)&1)) || i==0 || settings.fmLayout==2) ImGui::TableNextRow();
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGui::Separator(); ImGui::Separator();
@ -2087,7 +2100,9 @@ void FurnaceGUI::drawInsEdit() {
// push colors // push colors
if (settings.separateFMColors) { if (settings.separateFMColors) {
bool mod=true; bool mod=true;
if (opCount==4) { if (ins->type==DIV_INS_OPL_DRUMS) {
mod=false;
} else if (opCount==4) {
if (ins->type==DIV_INS_OPL) { if (ins->type==DIV_INS_OPL) {
if (opIsOutputOPL[ins->fm.alg&3][i]) mod=false; if (opIsOutputOPL[ins->fm.alg&3][i]) mod=false;
} else { } else {
@ -2114,7 +2129,9 @@ void FurnaceGUI::drawInsEdit() {
} }
ImGui::Dummy(ImVec2(dpiScale,dpiScale)); ImGui::Dummy(ImVec2(dpiScale,dpiScale));
if (ins->type==DIV_INS_OPL && ins->fm.opllPreset==16) { if (ins->type==DIV_INS_OPL_DRUMS) {
ImGui::Text("%s",oplDrumNames[i]);
} else if (ins->type==DIV_INS_OPL && ins->fm.opllPreset==16) {
if (i==1) { if (i==1) {
ImGui::Text("Envelope 2 (kick only)"); ImGui::Text("Envelope 2 (kick only)");
} else { } else {
@ -2139,7 +2156,7 @@ void FurnaceGUI::drawInsEdit() {
maxTl=63; maxTl=63;
} }
} }
if (ins->type==DIV_INS_OPL) { if (ins->type==DIV_INS_OPL || ins->type==DIV_INS_OPL_DRUMS) {
maxTl=63; maxTl=63;
} }
int maxArDr=(ins->type==DIV_INS_FM || ins->type==DIV_INS_OPZ)?31:15; int maxArDr=(ins->type==DIV_INS_FM || ins->type==DIV_INS_OPZ)?31:15;
@ -2149,7 +2166,7 @@ void FurnaceGUI::drawInsEdit() {
bool vibOn=op.vib; bool vibOn=op.vib;
bool susOn=op.sus; // don't you make fun of this one bool susOn=op.sus; // don't you make fun of this one
unsigned char ssgEnv=op.ssgEnv&7; unsigned char ssgEnv=op.ssgEnv&7;
if (ins->type!=DIV_INS_OPL && ins->type!=DIV_INS_OPZ) { if (ins->type!=DIV_INS_OPL && ins->type!=DIV_INS_OPL_DRUMS && ins->type!=DIV_INS_OPZ) {
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::Checkbox((ins->type==DIV_INS_OPLL)?FM_NAME(FM_EGS):"SSG On",&ssgOn)) { PARAMETER if (ImGui::Checkbox((ins->type==DIV_INS_OPLL)?FM_NAME(FM_EGS):"SSG On",&ssgOn)) { PARAMETER
op.ssgEnv=(op.ssgEnv&7)|(ssgOn<<3); op.ssgEnv=(op.ssgEnv&7)|(ssgOn<<3);
@ -2161,7 +2178,7 @@ void FurnaceGUI::drawInsEdit() {
} }
} }
if (ins->type==DIV_INS_OPL) { if (ins->type==DIV_INS_OPL || ins->type==DIV_INS_OPL_DRUMS) {
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::Checkbox(FM_NAME(FM_SUS),&susOn)) { PARAMETER if (ImGui::Checkbox(FM_NAME(FM_SUS),&susOn)) { PARAMETER
op.sus=susOn; op.sus=susOn;
@ -2169,7 +2186,7 @@ void FurnaceGUI::drawInsEdit() {
} }
//52.0 controls vert scaling; default 96 //52.0 controls vert scaling; default 96
drawFMEnv(op.tl&maxTl,op.ar&maxArDr,op.dr&maxArDr,(ins->type==DIV_INS_OPL || ins->type==DIV_INS_OPLL)?((op.rr&15)*2):op.d2r&31,op.rr&15,op.sl&15,op.sus,op.ssgEnv&8,ins->fm.alg,maxTl,maxArDr,ImVec2(ImGui::GetContentRegionAvail().x,52.0*dpiScale),ins->type); drawFMEnv(op.tl&maxTl,op.ar&maxArDr,op.dr&maxArDr,(ins->type==DIV_INS_OPL || ins->type==DIV_INS_OPL_DRUMS || ins->type==DIV_INS_OPLL)?((op.rr&15)*2):op.d2r&31,op.rr&15,op.sl&15,op.sus,op.ssgEnv&8,ins->fm.alg,maxTl,maxArDr,ImVec2(ImGui::GetContentRegionAvail().x,52.0*dpiScale),ins->type);
//P(CWSliderScalar(FM_NAME(FM_AR),ImGuiDataType_U8,&op.ar,&_ZERO,&_THIRTY_ONE)); rightClickable //P(CWSliderScalar(FM_NAME(FM_AR),ImGuiDataType_U8,&op.ar,&_ZERO,&_THIRTY_ONE)); rightClickable
if (ImGui::BeginTable("opParams",2,ImGuiTableFlags_SizingStretchProp)) { if (ImGui::BeginTable("opParams",2,ImGuiTableFlags_SizingStretchProp)) {
ImGui::TableSetupColumn("c0",ImGuiTableColumnFlags_WidthStretch,0.0); \ ImGui::TableSetupColumn("c0",ImGuiTableColumnFlags_WidthStretch,0.0); \
@ -2292,12 +2309,12 @@ void FurnaceGUI::drawInsEdit() {
} }
} }
if (ins->type==DIV_INS_OPL || ins->type==DIV_INS_OPZ) { if (ins->type==DIV_INS_OPL || ins->type==DIV_INS_OPL_DRUMS || ins->type==DIV_INS_OPZ) {
ImGui::TableNextRow(); ImGui::TableNextRow();
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
P(CWSliderScalar("##WS",ImGuiDataType_U8,&op.ws,&_ZERO,&_SEVEN,(ins->type==DIV_INS_OPZ)?opzWaveforms[op.ws&7]:(settings.oplStandardWaveNames?oplWaveformsStandard[op.ws&7]:oplWaveforms[op.ws&7]))); rightClickable P(CWSliderScalar("##WS",ImGuiDataType_U8,&op.ws,&_ZERO,&_SEVEN,(ins->type==DIV_INS_OPZ)?opzWaveforms[op.ws&7]:(settings.oplStandardWaveNames?oplWaveformsStandard[op.ws&7]:oplWaveforms[op.ws&7]))); rightClickable
if (ins->type==DIV_INS_OPL && ImGui::IsItemHovered()) { if ((ins->type==DIV_INS_OPL || ins->type==DIV_INS_OPL_DRUMS) && ImGui::IsItemHovered()) {
ImGui::SetTooltip("OPL2/3 only (last 4 waveforms are OPL3 only)"); ImGui::SetTooltip("OPL2/3 only (last 4 waveforms are OPL3 only)");
} }
ImGui::TableNextColumn(); ImGui::TableNextColumn();
@ -2307,7 +2324,7 @@ void FurnaceGUI::drawInsEdit() {
ImGui::EndTable(); ImGui::EndTable();
} }
if (ins->type==DIV_INS_OPLL || ins->type==DIV_INS_OPL) { if (ins->type==DIV_INS_OPLL || ins->type==DIV_INS_OPL || ins->type==DIV_INS_OPL_DRUMS) {
if (ImGui::Checkbox(FM_NAME(FM_VIB),&vibOn)) { PARAMETER if (ImGui::Checkbox(FM_NAME(FM_VIB),&vibOn)) { PARAMETER
op.vib=vibOn; op.vib=vibOn;
} }
@ -2338,7 +2355,7 @@ void FurnaceGUI::drawInsEdit() {
} else { } else {
macroList.push_back(FurnaceGUIMacroDesc(FM_NAME(FM_ALG),&ins->std.algMacro,0,7,96,uiColors[GUI_COLOR_MACRO_OTHER])); macroList.push_back(FurnaceGUIMacroDesc(FM_NAME(FM_ALG),&ins->std.algMacro,0,7,96,uiColors[GUI_COLOR_MACRO_OTHER]));
macroList.push_back(FurnaceGUIMacroDesc(FM_NAME(FM_FB),&ins->std.fbMacro,0,7,96,uiColors[GUI_COLOR_MACRO_OTHER])); macroList.push_back(FurnaceGUIMacroDesc(FM_NAME(FM_FB),&ins->std.fbMacro,0,7,96,uiColors[GUI_COLOR_MACRO_OTHER]));
if (ins->type!=DIV_INS_OPL) { if (ins->type!=DIV_INS_OPL && ins->type!=DIV_INS_OPL_DRUMS) {
if (ins->type==DIV_INS_OPZ) { if (ins->type==DIV_INS_OPZ) {
// TODO: FMS2/AMS2 macros // TODO: FMS2/AMS2 macros
macroList.push_back(FurnaceGUIMacroDesc(FM_NAME(FM_FMS),&ins->std.fmsMacro,0,7,96,uiColors[GUI_COLOR_MACRO_OTHER])); macroList.push_back(FurnaceGUIMacroDesc(FM_NAME(FM_FMS),&ins->std.fmsMacro,0,7,96,uiColors[GUI_COLOR_MACRO_OTHER]));
@ -2361,7 +2378,11 @@ void FurnaceGUI::drawInsEdit() {
ImGui::EndTabItem(); ImGui::EndTabItem();
} }
for (int i=0; i<opCount; i++) { for (int i=0; i<opCount; i++) {
snprintf(label,31,"OP%d Macros",i+1); if (ins->type==DIV_INS_OPL_DRUMS) {
snprintf(label,31,"%s Macros",oplDrumNames[i]);
} else {
snprintf(label,31,"OP%d Macros",i+1);
}
if (ImGui::BeginTabItem(label)) { if (ImGui::BeginTabItem(label)) {
ImGui::PushID(i); ImGui::PushID(i);
int ordi=(opCount==4)?orderedOps[i]:i; int ordi=(opCount==4)?orderedOps[i]:i;
@ -2373,12 +2394,12 @@ void FurnaceGUI::drawInsEdit() {
maxTl=63; maxTl=63;
} }
} }
if (ins->type==DIV_INS_OPL) { if (ins->type==DIV_INS_OPL || ins->type==DIV_INS_OPL_DRUMS) {
maxTl=63; maxTl=63;
} }
int maxArDr=(ins->type==DIV_INS_FM || ins->type==DIV_INS_OPZ)?31:15; int maxArDr=(ins->type==DIV_INS_FM || ins->type==DIV_INS_OPZ)?31:15;
if (ins->type==DIV_INS_OPL) { if (ins->type==DIV_INS_OPL || ins->type==DIV_INS_OPL_DRUMS) {
macroList.push_back(FurnaceGUIMacroDesc(FM_NAME(FM_TL),&ins->std.opMacros[ordi].tlMacro,0,maxTl,128,uiColors[GUI_COLOR_MACRO_OTHER])); macroList.push_back(FurnaceGUIMacroDesc(FM_NAME(FM_TL),&ins->std.opMacros[ordi].tlMacro,0,maxTl,128,uiColors[GUI_COLOR_MACRO_OTHER]));
macroList.push_back(FurnaceGUIMacroDesc(FM_NAME(FM_AR),&ins->std.opMacros[ordi].arMacro,0,maxArDr,64,uiColors[GUI_COLOR_MACRO_OTHER])); macroList.push_back(FurnaceGUIMacroDesc(FM_NAME(FM_AR),&ins->std.opMacros[ordi].arMacro,0,maxArDr,64,uiColors[GUI_COLOR_MACRO_OTHER]));
macroList.push_back(FurnaceGUIMacroDesc(FM_NAME(FM_DR),&ins->std.opMacros[ordi].drMacro,0,maxArDr,64,uiColors[GUI_COLOR_MACRO_OTHER])); macroList.push_back(FurnaceGUIMacroDesc(FM_NAME(FM_DR),&ins->std.opMacros[ordi].drMacro,0,maxArDr,64,uiColors[GUI_COLOR_MACRO_OTHER]));

View file

@ -21,9 +21,6 @@
#include "imgui_internal.h" #include "imgui_internal.h"
#include <imgui.h> #include <imgui.h>
// TODO:
// - potentially move oscilloscope seek position to the end, and read the last samples
// - this allows for setting up the window size
void FurnaceGUI::readOsc() { void FurnaceGUI::readOsc() {
int writePos=e->oscWritePos; int writePos=e->oscWritePos;
int readPos=e->oscReadPos; int readPos=e->oscReadPos;
@ -47,8 +44,11 @@ void FurnaceGUI::readOsc() {
total=oscTotal+(bias>>6); total=oscTotal+(bias>>6);
if (total>avail) total=avail; if (total>avail) total=avail;
//printf("total: %d. avail: %d bias: %d\n",total,avail,bias); //printf("total: %d. avail: %d bias: %d\n",total,avail,bias);
int winSize=e->getAudioDescGot().rate*(oscWindowSize/1000.0);
int oscReadPos=(writePos-winSize)&0x7fff;
for (int i=0; i<512; i++) { for (int i=0; i<512; i++) {
int pos=(readPos+(i*total/512))&0x7fff; int pos=(oscReadPos+(i*winSize/512))&0x7fff;
oscValues[i]=(e->oscBuf[0][pos]+e->oscBuf[1][pos])*0.5f; oscValues[i]=(e->oscBuf[0][pos]+e->oscBuf[1][pos])*0.5f;
if (oscValues[i]>0.001f || oscValues[i]<-0.001f) { if (oscValues[i]>0.001f || oscValues[i]<-0.001f) {
WAKE_UP; WAKE_UP;
@ -97,6 +97,14 @@ void FurnaceGUI::drawOsc() {
if (oscZoom>2.0) oscZoom=2.0; if (oscZoom>2.0) oscZoom=2.0;
} }
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::VSliderFloat("##OscWinSize",ImVec2(20.0f*dpiScale,ImGui::GetContentRegionAvail().y),&oscWindowSize,5.0,100.0)) {
if (oscWindowSize<5.0) oscWindowSize=5.0;
if (oscWindowSize>100.0) oscWindowSize=100.0;
}
if (ImGui::IsItemClicked(ImGuiMouseButton_Middle)) {
oscWindowSize=20.0;
}
ImGui::SameLine();
} }
ImDrawList* dl=ImGui::GetWindowDrawList(); ImDrawList* dl=ImGui::GetWindowDrawList();

View file

@ -404,6 +404,11 @@ void FurnaceGUI::drawSettings() {
settings.cursorMoveNoScroll=cursorMoveNoScrollB; settings.cursorMoveNoScroll=cursorMoveNoScrollB;
} }
bool doubleClickColumnB=settings.doubleClickColumn;
if (ImGui::Checkbox("Double click selects entire column",&doubleClickColumnB)) {
settings.doubleClickColumn=doubleClickColumnB;
}
bool allowEditDockingB=settings.allowEditDocking; bool allowEditDockingB=settings.allowEditDocking;
if (ImGui::Checkbox("Allow docking editors",&allowEditDockingB)) { if (ImGui::Checkbox("Allow docking editors",&allowEditDockingB)) {
settings.allowEditDocking=allowEditDockingB; settings.allowEditDocking=allowEditDockingB;
@ -2009,7 +2014,7 @@ void FurnaceGUI::syncSettings() {
settings.insCellSpacing=e->getConfInt("insCellSpacing",0); settings.insCellSpacing=e->getConfInt("insCellSpacing",0);
settings.volCellSpacing=e->getConfInt("volCellSpacing",0); settings.volCellSpacing=e->getConfInt("volCellSpacing",0);
settings.effectCellSpacing=e->getConfInt("effectCellSpacing",0); settings.effectCellSpacing=e->getConfInt("effectCellSpacing",0);
settings.effectValCellSpacing=e->getConfInt("effectValCellSpacing",0); settings.doubleClickColumn=e->getConfInt("doubleClickColumn",0);
clampSetting(settings.mainFontSize,2,96); clampSetting(settings.mainFontSize,2,96);
clampSetting(settings.patFontSize,2,96); clampSetting(settings.patFontSize,2,96);
@ -2092,6 +2097,7 @@ void FurnaceGUI::syncSettings() {
clampSetting(settings.volCellSpacing,0,32); clampSetting(settings.volCellSpacing,0,32);
clampSetting(settings.effectCellSpacing,0,32); clampSetting(settings.effectCellSpacing,0,32);
clampSetting(settings.effectValCellSpacing,0,32); clampSetting(settings.effectValCellSpacing,0,32);
clampSetting(settings.doubleClickColumn,0,1);
settings.initialSys=e->decodeSysDesc(e->getConfString("initialSys","")); settings.initialSys=e->decodeSysDesc(e->getConfString("initialSys",""));
if (settings.initialSys.size()<4) { if (settings.initialSys.size()<4) {
@ -2223,6 +2229,7 @@ void FurnaceGUI::commitSettings() {
e->setConf("volCellSpacing",settings.volCellSpacing); e->setConf("volCellSpacing",settings.volCellSpacing);
e->setConf("effectCellSpacing",settings.effectCellSpacing); e->setConf("effectCellSpacing",settings.effectCellSpacing);
e->setConf("effectValCellSpacing",settings.effectValCellSpacing); e->setConf("effectValCellSpacing",settings.effectValCellSpacing);
e->setConf("doubleClickColumn",settings.doubleClickColumn);
// colors // colors
for (int i=0; i<GUI_COLOR_MAX; i++) { for (int i=0; i<GUI_COLOR_MAX; i++) {