mirror of
https://github.com/tildearrow/furnace.git
synced 2024-11-30 16:33:01 +00:00
Merge branch 'master' of https://github.com/tildearrow/furnace into sample_macro
This commit is contained in:
commit
e00758d67c
54 changed files with 1068 additions and 219 deletions
7
TODO.md
7
TODO.md
|
@ -1,7 +0,0 @@
|
||||||
# to-do for 0.6pre1.5
|
|
||||||
|
|
||||||
- stereo separation control for AY
|
|
||||||
- "paste with instrument"
|
|
||||||
- FM operator muting
|
|
||||||
- FM operator swap
|
|
||||||
- bug fixes
|
|
BIN
demos/Moon.fur
Normal file
BIN
demos/Moon.fur
Normal file
Binary file not shown.
BIN
demos/You're_Doing_Well!_GB.fur
Normal file
BIN
demos/You're_Doing_Well!_GB.fur
Normal file
Binary file not shown.
4
extern/imgui_patched/imgui.h
vendored
4
extern/imgui_patched/imgui.h
vendored
|
@ -1042,7 +1042,7 @@ enum ImGuiInputTextFlags_
|
||||||
ImGuiInputTextFlags_AlwaysOverwrite = 1 << 13, // Overwrite mode
|
ImGuiInputTextFlags_AlwaysOverwrite = 1 << 13, // Overwrite mode
|
||||||
ImGuiInputTextFlags_ReadOnly = 1 << 14, // Read-only mode
|
ImGuiInputTextFlags_ReadOnly = 1 << 14, // Read-only mode
|
||||||
ImGuiInputTextFlags_Password = 1 << 15, // Password mode, display all characters as '*'
|
ImGuiInputTextFlags_Password = 1 << 15, // Password mode, display all characters as '*'
|
||||||
ImGuiInputTextFlags_NoUndoRedo = 1 << 16, // Disable undo/redo. Note that input text owns the text data while active, if you want to provide your own undo/redo stack you need e.g. to call ClearActiveID().
|
ImGuiInputTextFlags_UndoRedo = 1 << 16, // Enable undo/redo. Note that input text owns the text data while active, if you want to provide your own undo/redo stack you need e.g. to call ClearActiveID().
|
||||||
ImGuiInputTextFlags_CharsScientific = 1 << 17, // Allow 0123456789.+-*/eE (Scientific notation input)
|
ImGuiInputTextFlags_CharsScientific = 1 << 17, // Allow 0123456789.+-*/eE (Scientific notation input)
|
||||||
ImGuiInputTextFlags_CallbackResize = 1 << 18, // Callback on buffer capacity changes request (beyond 'buf_size' parameter value), allowing the string to grow. Notify when the string wants to be resized (for string types which hold a cache of their Size). You will be provided a new BufSize in the callback and NEED to honor it. (see misc/cpp/imgui_stdlib.h for an example of using this)
|
ImGuiInputTextFlags_CallbackResize = 1 << 18, // Callback on buffer capacity changes request (beyond 'buf_size' parameter value), allowing the string to grow. Notify when the string wants to be resized (for string types which hold a cache of their Size). You will be provided a new BufSize in the callback and NEED to honor it. (see misc/cpp/imgui_stdlib.h for an example of using this)
|
||||||
ImGuiInputTextFlags_CallbackEdit = 1 << 19 // Callback on any edit (note that InputText() already returns true on edit, the callback is useful mainly to manipulate the underlying buffer while focus is active)
|
ImGuiInputTextFlags_CallbackEdit = 1 << 19 // Callback on any edit (note that InputText() already returns true on edit, the callback is useful mainly to manipulate the underlying buffer while focus is active)
|
||||||
|
@ -1220,6 +1220,8 @@ enum ImGuiTableFlags_
|
||||||
// Sorting
|
// Sorting
|
||||||
ImGuiTableFlags_SortMulti = 1 << 26, // Hold shift when clicking headers to sort on multiple column. TableGetSortSpecs() may return specs where (SpecsCount > 1).
|
ImGuiTableFlags_SortMulti = 1 << 26, // Hold shift when clicking headers to sort on multiple column. TableGetSortSpecs() may return specs where (SpecsCount > 1).
|
||||||
ImGuiTableFlags_SortTristate = 1 << 27, // Allow no sorting, disable default sorting. TableGetSortSpecs() may return specs where (SpecsCount == 0).
|
ImGuiTableFlags_SortTristate = 1 << 27, // Allow no sorting, disable default sorting. TableGetSortSpecs() may return specs where (SpecsCount == 0).
|
||||||
|
// tildearrow
|
||||||
|
ImGuiTableFlags_NoBordersInFrozenArea = 1 << 28, // Disable vertical borders in frozen area.
|
||||||
|
|
||||||
// [Internal] Combinations and masks
|
// [Internal] Combinations and masks
|
||||||
ImGuiTableFlags_SizingMask_ = ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_SizingFixedSame | ImGuiTableFlags_SizingStretchProp | ImGuiTableFlags_SizingStretchSame
|
ImGuiTableFlags_SizingMask_ = ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_SizingFixedSame | ImGuiTableFlags_SizingStretchProp | ImGuiTableFlags_SizingStretchSame
|
||||||
|
|
2
extern/imgui_patched/imgui_tables.cpp
vendored
2
extern/imgui_patched/imgui_tables.cpp
vendored
|
@ -2532,7 +2532,7 @@ void ImGui::TableDrawBorders(ImGuiTable* table)
|
||||||
// Draw inner border and resizing feedback
|
// Draw inner border and resizing feedback
|
||||||
ImGuiTableInstanceData* table_instance = TableGetInstanceData(table, table->InstanceCurrent);
|
ImGuiTableInstanceData* table_instance = TableGetInstanceData(table, table->InstanceCurrent);
|
||||||
const float border_size = TABLE_BORDER_SIZE;
|
const float border_size = TABLE_BORDER_SIZE;
|
||||||
const float draw_y1 = table->InnerRect.Min.y;
|
const float draw_y1 = table->InnerRect.Min.y + ((table->Flags & ImGuiTableFlags_NoBordersInFrozenArea)?table_instance->LastFirstRowHeight:0.0f);
|
||||||
const float draw_y2_body = table->InnerRect.Max.y;
|
const float draw_y2_body = table->InnerRect.Max.y;
|
||||||
const float draw_y2_head = table->IsUsingHeaders ? ImMin(table->InnerRect.Max.y, (table->FreezeRowsCount >= 1 ? table->InnerRect.Min.y : table->WorkRect.Min.y) + table_instance->LastFirstRowHeight) : draw_y1;
|
const float draw_y2_head = table->IsUsingHeaders ? ImMin(table->InnerRect.Max.y, (table->FreezeRowsCount >= 1 ? table->InnerRect.Min.y : table->WorkRect.Min.y) + table_instance->LastFirstRowHeight) : draw_y1;
|
||||||
if (table->Flags & ImGuiTableFlags_BordersInnerV)
|
if (table->Flags & ImGuiTableFlags_BordersInnerV)
|
||||||
|
|
14
extern/imgui_patched/imgui_widgets.cpp
vendored
14
extern/imgui_patched/imgui_widgets.cpp
vendored
|
@ -3713,7 +3713,12 @@ static bool STB_TEXTEDIT_INSERTCHARS(ImGuiInputTextState* obj, int pos, const Im
|
||||||
{
|
{
|
||||||
const bool is_resizable = (obj->Flags & ImGuiInputTextFlags_CallbackResize) != 0;
|
const bool is_resizable = (obj->Flags & ImGuiInputTextFlags_CallbackResize) != 0;
|
||||||
const int text_len = obj->CurLenW;
|
const int text_len = obj->CurLenW;
|
||||||
IM_ASSERT(pos <= text_len);
|
if (pos > text_len) {
|
||||||
|
printf("failing STB_TEXTEDIT_INSERTCHARS assertion! oh man...\n");
|
||||||
|
obj->Edited = true; // ???
|
||||||
|
obj->ClearText();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
const int new_text_len_utf8 = ImTextCountUtf8BytesFromStr(new_text, new_text + new_text_len);
|
const int new_text_len_utf8 = ImTextCountUtf8BytesFromStr(new_text, new_text + new_text_len);
|
||||||
if (!is_resizable && (new_text_len_utf8 + obj->CurLenA + 1 > obj->BufCapacityA))
|
if (!is_resizable && (new_text_len_utf8 + obj->CurLenA + 1 > obj->BufCapacityA))
|
||||||
|
@ -3776,8 +3781,11 @@ static void stb_textedit_replace(ImGuiInputTextState* str, STB_TexteditState* st
|
||||||
state->cursor = text_len;
|
state->cursor = text_len;
|
||||||
state->has_preferred_x = 0;
|
state->has_preferred_x = 0;
|
||||||
return;
|
return;
|
||||||
|
} else {
|
||||||
|
state->cursor = 0;
|
||||||
|
printf("STB_TEXTEDIT_INSERTCHARS fail!\n");
|
||||||
}
|
}
|
||||||
IM_ASSERT(0); // Failed to insert character, normally shouldn't happen because of how we currently use stb_textedit_replace()
|
//IM_ASSERT(0); // Failed to insert character, normally shouldn't happen because of how we currently use stb_textedit_replace()
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ImStb
|
} // namespace ImStb
|
||||||
|
@ -3962,7 +3970,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||||
const bool is_multiline = (flags & ImGuiInputTextFlags_Multiline) != 0;
|
const bool is_multiline = (flags & ImGuiInputTextFlags_Multiline) != 0;
|
||||||
const bool is_readonly = (flags & ImGuiInputTextFlags_ReadOnly) != 0;
|
const bool is_readonly = (flags & ImGuiInputTextFlags_ReadOnly) != 0;
|
||||||
const bool is_password = (flags & ImGuiInputTextFlags_Password) != 0;
|
const bool is_password = (flags & ImGuiInputTextFlags_Password) != 0;
|
||||||
const bool is_undoable = (flags & ImGuiInputTextFlags_NoUndoRedo) == 0;
|
const bool is_undoable = (flags & ImGuiInputTextFlags_UndoRedo) != 0;
|
||||||
const bool is_resizable = (flags & ImGuiInputTextFlags_CallbackResize) != 0;
|
const bool is_resizable = (flags & ImGuiInputTextFlags_CallbackResize) != 0;
|
||||||
if (is_resizable)
|
if (is_resizable)
|
||||||
IM_ASSERT(callback != NULL); // Must provide a callback if you set the ImGuiInputTextFlags_CallbackResize flag!
|
IM_ASSERT(callback != NULL); // Must provide a callback if you set the ImGuiInputTextFlags_CallbackResize flag!
|
||||||
|
|
33
extern/imgui_patched/imstb_textedit.h
vendored
33
extern/imgui_patched/imstb_textedit.h
vendored
|
@ -717,6 +717,9 @@ static int stb_textedit_paste_internal(STB_TEXTEDIT_STRING *str, STB_TexteditSta
|
||||||
state->cursor += len;
|
state->cursor += len;
|
||||||
state->has_preferred_x = 0;
|
state->has_preferred_x = 0;
|
||||||
return 1;
|
return 1;
|
||||||
|
} else {
|
||||||
|
printf("stb_textedit_paste_internal failed.\n");
|
||||||
|
state->cursor=0;
|
||||||
}
|
}
|
||||||
// note: paste failure will leave deleted selection, may be restored with an undo (see https://github.com/nothings/stb/issues/734 for details)
|
// note: paste failure will leave deleted selection, may be restored with an undo (see https://github.com/nothings/stb/issues/734 for details)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -746,6 +749,9 @@ retry:
|
||||||
if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, &ch, 1)) {
|
if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, &ch, 1)) {
|
||||||
++state->cursor;
|
++state->cursor;
|
||||||
state->has_preferred_x = 0;
|
state->has_preferred_x = 0;
|
||||||
|
} else {
|
||||||
|
printf("key failed: first section.\n");
|
||||||
|
state->cursor=0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
stb_textedit_delete_selection(str,state); // implicitly clamps
|
stb_textedit_delete_selection(str,state); // implicitly clamps
|
||||||
|
@ -753,6 +759,9 @@ retry:
|
||||||
stb_text_makeundo_insert(state, state->cursor, 1);
|
stb_text_makeundo_insert(state, state->cursor, 1);
|
||||||
++state->cursor;
|
++state->cursor;
|
||||||
state->has_preferred_x = 0;
|
state->has_preferred_x = 0;
|
||||||
|
} else {
|
||||||
|
printf("key failed: second section.\n");
|
||||||
|
state->cursor=0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1275,14 +1284,22 @@ static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
||||||
STB_TEXTEDIT_DELETECHARS(str, u.where, u.delete_length);
|
STB_TEXTEDIT_DELETECHARS(str, u.where, u.delete_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool steFailed=false;
|
||||||
|
|
||||||
// check type of recorded action:
|
// check type of recorded action:
|
||||||
if (u.insert_length) {
|
if (u.insert_length) {
|
||||||
// easy case: was a deletion, so we need to insert n characters
|
// easy case: was a deletion, so we need to insert n characters
|
||||||
STB_TEXTEDIT_INSERTCHARS(str, u.where, &s->undo_char[u.char_storage], u.insert_length);
|
if (!STB_TEXTEDIT_INSERTCHARS(str, u.where, &s->undo_char[u.char_storage], u.insert_length)) {
|
||||||
|
printf("undo u.insert_length failed\n");
|
||||||
|
state->cursor=0;
|
||||||
|
steFailed=true;
|
||||||
|
}
|
||||||
s->undo_char_point -= u.insert_length;
|
s->undo_char_point -= u.insert_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
state->cursor = u.where + u.insert_length;
|
if (!steFailed) {
|
||||||
|
state->cursor = u.where + u.insert_length;
|
||||||
|
}
|
||||||
|
|
||||||
s->undo_point--;
|
s->undo_point--;
|
||||||
s->redo_point--;
|
s->redo_point--;
|
||||||
|
@ -1327,13 +1344,21 @@ static void stb_text_redo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
||||||
STB_TEXTEDIT_DELETECHARS(str, r.where, r.delete_length);
|
STB_TEXTEDIT_DELETECHARS(str, r.where, r.delete_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool steFailed=false;
|
||||||
|
|
||||||
if (r.insert_length) {
|
if (r.insert_length) {
|
||||||
// easy case: need to insert n characters
|
// easy case: need to insert n characters
|
||||||
STB_TEXTEDIT_INSERTCHARS(str, r.where, &s->undo_char[r.char_storage], r.insert_length);
|
if (!STB_TEXTEDIT_INSERTCHARS(str, r.where, &s->undo_char[r.char_storage], r.insert_length)) {
|
||||||
|
printf("redo insert char failed\n");
|
||||||
|
state->cursor=0;
|
||||||
|
steFailed=true;
|
||||||
|
}
|
||||||
s->redo_char_point += r.insert_length;
|
s->redo_char_point += r.insert_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
state->cursor = r.where + r.insert_length;
|
if (!steFailed) {
|
||||||
|
state->cursor = r.where + r.insert_length;
|
||||||
|
}
|
||||||
|
|
||||||
s->undo_point++;
|
s->undo_point++;
|
||||||
s->redo_point++;
|
s->redo_point++;
|
||||||
|
|
7
papers/doc/7-systems/dac.md
Normal file
7
papers/doc/7-systems/dac.md
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
# Generic PCM DAC
|
||||||
|
|
||||||
|
Realtek HD Audio's predecessor. It's just a 1/8/16-bit sample channel, with freely selectable rate and mono/stereo settings. With it, you can emulate PCM DACs found in Williams arcade boards, Sound Blasters, MSX TurboR, Atari STE, NEC PC-9801-86 etc.
|
||||||
|
|
||||||
|
# effects
|
||||||
|
|
||||||
|
none yet.
|
|
@ -9,4 +9,4 @@ additionally, it offers an 8-bit DAC which can be used to play samples. only one
|
||||||
# effects
|
# effects
|
||||||
|
|
||||||
- `12xx`: set duty cycle or noise mode of channel.
|
- `12xx`: set duty cycle or noise mode of channel.
|
||||||
- may be 0-3 for the pulse channels and 0-1 for the noise channel.
|
- may be 0-3 for the pulse channels.
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
# Namco 163 (also called N163, Namco C163, Namco 106 (sic), Namco 160 or Namco 129)
|
# Namco 163 (also called N163, Namco C163, Namco 106 (sic), Namco 160 or Namco 129)
|
||||||
|
|
||||||
This is one of Namco's NES mappers, with up to 8 wavetable channels. It has also 128 byte of internal RAM, and both channel register and wavetables are stored here. Wavetables are variable size and freely allocable anywhere in RAM, it means it can use part of or continuously pre-loaded waveform and its sequences in RAM. But waveform RAM area becomes smaller as more channels are activated; as channel registers consumes 8 bytes for each channel. You must avoid conflict with channel register area and waveform for avoid broken channel playback.
|
This is one of Namco's NES mappers, with up to 8 wavetable channels. It has also 256 nibbles (128 bytes) of internal RAM, and both channel registers and wavetables are stored here. Wavetables are variable in size and freely allocable anywhere in RAM, it means it can use part of or continuously pre-loaded waveform and its sequences in RAM. At least 128 nibbles (64 bytes) can be dedicated to waves, with more available if not all channels are used - waveform RAM area becomes smaller as more channels are activated, since channel registers consume 8 bytes for each channel. You must avoid conflict with channel register area and waveform to avoid broken channel playback.
|
||||||
|
|
||||||
It outputs only a single channel at clock; so its sound quality gets more crunchy as more channels are activated.
|
Namco 163 uses time-division multiplexing for its output. this means that only one channel is output per sample (like OPLL and OPN2). therefore, its sound quality gets worse as more channels are activated.
|
||||||
|
|
||||||
Furnace supports loading waveforms into RAM and waveform playback simultaneously, and channel limit is dynamically changeable with effect commands.
|
Furnace supports loading waveforms into RAM and waveform playback simultaneously, and channel limit is dynamically changeable with effect commands.
|
||||||
You must load waveform to RAM first for playback, as its load behavior auto-updates when every waveform changes.
|
You must load waveform to RAM first for playback, as its load behavior auto-updates when every waveform changes.
|
||||||
|
|
|
@ -32,6 +32,8 @@ these fields are 0 in format versions prior to 100 (0.6pre1).
|
||||||
|
|
||||||
the format versions are:
|
the format versions are:
|
||||||
|
|
||||||
|
- 116: Furnace 0.6pre1.5
|
||||||
|
- 115: Furnace dev115
|
||||||
- 114: Furnace dev114
|
- 114: Furnace dev114
|
||||||
- 113: Furnace dev113
|
- 113: Furnace dev113
|
||||||
- 112: Furnace dev112
|
- 112: Furnace dev112
|
||||||
|
@ -342,7 +344,9 @@ size | description
|
||||||
1 | SN periods under 8 are treated as 1 (>=108) or reserved
|
1 | SN periods under 8 are treated as 1 (>=108) or reserved
|
||||||
1 | cut/delay effect policy (>=110) or reserved
|
1 | cut/delay effect policy (>=110) or reserved
|
||||||
1 | 0B/0D effect treatment (>=113) or reserved
|
1 | 0B/0D effect treatment (>=113) or reserved
|
||||||
4 | reserved
|
1 | automatic system name detection (>=115) or reserved
|
||||||
|
| - this one isn't a compatibility flag, but it's here for convenience...
|
||||||
|
3 | reserved
|
||||||
--- | **virtual tempo data**
|
--- | **virtual tempo data**
|
||||||
2 | virtual tempo numerator of first song (>=96) or reserved
|
2 | virtual tempo numerator of first song (>=96) or reserved
|
||||||
2 | virtual tempo denominator of first song (>=96) or reserved
|
2 | virtual tempo denominator of first song (>=96) or reserved
|
||||||
|
@ -499,7 +503,11 @@ size | description
|
||||||
1 | ws
|
1 | ws
|
||||||
1 | ksr
|
1 | ksr
|
||||||
1 | operator enabled (>=114) or reserved
|
1 | operator enabled (>=114) or reserved
|
||||||
11 | reserved
|
1 | KVS mode (>=115) or reserved
|
||||||
|
| - 0: off
|
||||||
|
| - 1: on
|
||||||
|
| - 2: auto (depending on alg)
|
||||||
|
10 | reserved
|
||||||
--- | **Game Boy instrument data**
|
--- | **Game Boy instrument data**
|
||||||
1 | volume
|
1 | volume
|
||||||
1 | direction
|
1 | direction
|
||||||
|
|
|
@ -2004,6 +2004,14 @@ void DivEngine::recalcChans() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivEngine::reset() {
|
void DivEngine::reset() {
|
||||||
|
if (output) if (output->midiOut!=NULL) {
|
||||||
|
output->midiOut->send(TAMidiMessage(TA_MIDI_MACHINE_STOP,0,0));
|
||||||
|
for (int i=0; i<chans; i++) {
|
||||||
|
if (chan[i].curMidiNote>=0) {
|
||||||
|
output->midiOut->send(TAMidiMessage(0x80|(i&15),chan[i].curMidiNote,0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
for (int i=0; i<DIV_MAX_CHANS; i++) {
|
for (int i=0; i<DIV_MAX_CHANS; i++) {
|
||||||
chan[i]=DivChannelState();
|
chan[i]=DivChannelState();
|
||||||
if (i<chans) chan[i].volMax=(disCont[dispatchOfChan[i]].dispatch->dispatch(DivCommand(DIV_CMD_GET_VOLMAX,dispatchChanOfChan[i]))<<8)|0xff;
|
if (i<chans) chan[i].volMax=(disCont[dispatchOfChan[i]].dispatch->dispatch(DivCommand(DIV_CMD_GET_VOLMAX,dispatchChanOfChan[i]))<<8)|0xff;
|
||||||
|
|
|
@ -46,8 +46,8 @@
|
||||||
#define BUSY_BEGIN_SOFT softLocked=true; isBusy.lock();
|
#define BUSY_BEGIN_SOFT softLocked=true; isBusy.lock();
|
||||||
#define BUSY_END isBusy.unlock(); softLocked=false;
|
#define BUSY_END isBusy.unlock(); softLocked=false;
|
||||||
|
|
||||||
#define DIV_VERSION "dev114"
|
#define DIV_VERSION "0.6pre1.5"
|
||||||
#define DIV_ENGINE_VERSION 114
|
#define DIV_ENGINE_VERSION 116
|
||||||
// for imports
|
// for imports
|
||||||
#define DIV_VERSION_MOD 0xff01
|
#define DIV_VERSION_MOD 0xff01
|
||||||
#define DIV_VERSION_FC 0xff02
|
#define DIV_VERSION_FC 0xff02
|
||||||
|
|
|
@ -196,6 +196,15 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) {
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Genesis detuned on Defle v10 and earlier
|
||||||
|
/*if (ds.version<19 && ds.system[0]==DIV_SYSTEM_GENESIS) {
|
||||||
|
ds.tuning=443.23;
|
||||||
|
}*/
|
||||||
|
// C64 detuned on Defle v11 and earlier
|
||||||
|
/*if (ds.version<21 && (ds.system[0]==DIV_SYSTEM_C64_6581 || ds.system[0]==DIV_SYSTEM_C64_8580)) {
|
||||||
|
ds.tuning=433.2;
|
||||||
|
}*/
|
||||||
|
|
||||||
logI("reading module data...");
|
logI("reading module data...");
|
||||||
if (ds.version>0x0c) {
|
if (ds.version>0x0c) {
|
||||||
ds.subsong[0]->hilightA=reader.readC();
|
ds.subsong[0]->hilightA=reader.readC();
|
||||||
|
@ -449,6 +458,9 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) {
|
||||||
ins->fm.op[j].ssgEnv=reader.readC();
|
ins->fm.op[j].ssgEnv=reader.readC();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (ds.version<0x12) { // before version 10 all ops were responsive to volume
|
||||||
|
ins->fm.op[j].kvs=1;
|
||||||
|
}
|
||||||
|
|
||||||
logD("OP%d: AM %d AR %d DAM %d DR %d DVB %d EGT %d KSL %d MULT %d RR %d SL %d SUS %d TL %d VIB %d WS %d RS %d DT %d D2R %d SSG-EG %d",j,
|
logD("OP%d: AM %d AR %d DAM %d DR %d DVB %d EGT %d KSL %d MULT %d RR %d SL %d SUS %d TL %d VIB %d WS %d RS %d DT %d D2R %d SSG-EG %d",j,
|
||||||
ins->fm.op[j].am,
|
ins->fm.op[j].am,
|
||||||
|
@ -1085,6 +1097,9 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) {
|
||||||
if (ds.version<113) {
|
if (ds.version<113) {
|
||||||
ds.jumpTreatment=1;
|
ds.jumpTreatment=1;
|
||||||
}
|
}
|
||||||
|
if (ds.version<115) {
|
||||||
|
ds.autoSystem=false;
|
||||||
|
}
|
||||||
ds.isDMF=false;
|
ds.isDMF=false;
|
||||||
|
|
||||||
reader.readS(); // reserved
|
reader.readS(); // reserved
|
||||||
|
@ -1512,7 +1527,12 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) {
|
||||||
} else {
|
} else {
|
||||||
reader.readC();
|
reader.readC();
|
||||||
}
|
}
|
||||||
for (int i=0; i<4; i++) {
|
if (ds.version>=115) {
|
||||||
|
ds.autoSystem=reader.readC();
|
||||||
|
} else {
|
||||||
|
reader.readC();
|
||||||
|
}
|
||||||
|
for (int i=0; i<3; i++) {
|
||||||
reader.readC();
|
reader.readC();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1549,6 +1569,7 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) {
|
||||||
ds.categoryJ=reader.readString();
|
ds.categoryJ=reader.readString();
|
||||||
} else {
|
} else {
|
||||||
ds.systemName=getSongSystemLegacyName(ds,!getConfInt("noMultiSystem",0));
|
ds.systemName=getSongSystemLegacyName(ds,!getConfInt("noMultiSystem",0));
|
||||||
|
ds.autoSystem=true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// read subsongs
|
// read subsongs
|
||||||
|
@ -1774,14 +1795,8 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) {
|
||||||
|
|
||||||
#ifdef TA_BIG_ENDIAN
|
#ifdef TA_BIG_ENDIAN
|
||||||
// convert 16-bit samples to big-endian
|
// convert 16-bit samples to big-endian
|
||||||
if (sample->depth==DIV_SAMPLE_DEPTH_16BIT) {
|
for (int pos=0; pos<length; pos++) {
|
||||||
unsigned char* sampleBuf=(unsigned char*)sample->getCurBuf();
|
data[pos]=((unsigned short)data[pos]>>8)|((unsigned short)data[pos]<<8);
|
||||||
size_t sampleBufLen=sample->getCurBufLen();
|
|
||||||
for (size_t pos=0; pos<sampleBufLen; pos+=2) {
|
|
||||||
sampleBuf[pos]^=sampleBuf[pos+1];
|
|
||||||
sampleBuf[pos+1]^=sampleBuf[pos];
|
|
||||||
sampleBuf[pos]^=sampleBuf[pos+1];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -3761,7 +3776,8 @@ SafeWriter* DivEngine::saveFur(bool notPrimary) {
|
||||||
w->writeC(song.snNoLowPeriods);
|
w->writeC(song.snNoLowPeriods);
|
||||||
w->writeC(song.delayBehavior);
|
w->writeC(song.delayBehavior);
|
||||||
w->writeC(song.jumpTreatment);
|
w->writeC(song.jumpTreatment);
|
||||||
for (int i=0; i<4; i++) {
|
w->writeC(song.autoSystem);
|
||||||
|
for (int i=0; i<3; i++) {
|
||||||
w->writeC(0);
|
w->writeC(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -72,9 +72,10 @@ void DivInstrument::putInsData(SafeWriter* w) {
|
||||||
w->writeC(op.ksr);
|
w->writeC(op.ksr);
|
||||||
|
|
||||||
w->writeC(op.enable);
|
w->writeC(op.enable);
|
||||||
|
w->writeC(op.kvs);
|
||||||
|
|
||||||
// reserved
|
// reserved
|
||||||
for (int k=0; k<11; k++) {
|
for (int k=0; k<10; k++) {
|
||||||
w->writeC(0);
|
w->writeC(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -724,8 +725,15 @@ DivDataErrors DivInstrument::readInsData(SafeReader& reader, short version) {
|
||||||
reader.readC();
|
reader.readC();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (version>=115) {
|
||||||
|
op.kvs=reader.readC();
|
||||||
|
} else {
|
||||||
|
op.kvs=2;
|
||||||
|
reader.readC();
|
||||||
|
}
|
||||||
|
|
||||||
// reserved
|
// reserved
|
||||||
for (int k=0; k<11; k++) reader.readC();
|
for (int k=0; k<10; k++) reader.readC();
|
||||||
}
|
}
|
||||||
|
|
||||||
// GB
|
// GB
|
||||||
|
|
|
@ -97,6 +97,7 @@ struct DivInstrumentFM {
|
||||||
bool enable;
|
bool enable;
|
||||||
unsigned char am, ar, dr, mult, rr, sl, tl, dt2, rs, dt, d2r, ssgEnv;
|
unsigned char am, ar, dr, mult, rr, sl, tl, dt2, rs, dt, d2r, ssgEnv;
|
||||||
unsigned char dam, dvb, egt, ksl, sus, vib, ws, ksr; // YMU759/OPL/OPZ
|
unsigned char dam, dvb, egt, ksl, sus, vib, ws, ksr; // YMU759/OPL/OPZ
|
||||||
|
unsigned char kvs;
|
||||||
Operator():
|
Operator():
|
||||||
enable(true),
|
enable(true),
|
||||||
am(0),
|
am(0),
|
||||||
|
@ -118,7 +119,8 @@ struct DivInstrumentFM {
|
||||||
sus(0),
|
sus(0),
|
||||||
vib(0),
|
vib(0),
|
||||||
ws(0),
|
ws(0),
|
||||||
ksr(0) {}
|
ksr(0),
|
||||||
|
kvs(2) {}
|
||||||
} op[4];
|
} op[4];
|
||||||
DivInstrumentFM():
|
DivInstrumentFM():
|
||||||
alg(0),
|
alg(0),
|
||||||
|
|
|
@ -151,7 +151,7 @@ void DivPlatformArcade::tick(bool sysTick) {
|
||||||
for (int j=0; j<4; j++) {
|
for (int j=0; j<4; j++) {
|
||||||
unsigned short baseAddr=chanOffs[i]|opOffs[j];
|
unsigned short baseAddr=chanOffs[i]|opOffs[j];
|
||||||
DivInstrumentFM::Operator& op=chan[i].state.op[j];
|
DivInstrumentFM::Operator& op=chan[i].state.op[j];
|
||||||
if (isOutput[chan[i].state.alg][j]) {
|
if (KVS(i,j)) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
@ -231,7 +231,7 @@ void DivPlatformArcade::tick(bool sysTick) {
|
||||||
if (isMuted[i]) {
|
if (isMuted[i]) {
|
||||||
rWrite(baseAddr+ADDR_TL,127);
|
rWrite(baseAddr+ADDR_TL,127);
|
||||||
} else {
|
} else {
|
||||||
if (isOutput[chan[i].state.alg][j]) {
|
if (KVS(i,j)) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
@ -289,7 +289,7 @@ void DivPlatformArcade::tick(bool sysTick) {
|
||||||
}
|
}
|
||||||
if (m.tl.had) {
|
if (m.tl.had) {
|
||||||
op.tl=127-m.tl.val;
|
op.tl=127-m.tl.val;
|
||||||
if (isOutput[chan[i].state.alg][j]) {
|
if (KVS(i,j)) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
@ -390,7 +390,7 @@ int DivPlatformArcade::dispatch(DivCommand c) {
|
||||||
for (int i=0; i<4; i++) {
|
for (int i=0; i<4; i++) {
|
||||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||||
DivInstrumentFM::Operator op=chan[c.chan].state.op[i];
|
DivInstrumentFM::Operator op=chan[c.chan].state.op[i];
|
||||||
if (isOutput[chan[c.chan].state.alg][i]) {
|
if (KVS(c.chan,i)) {
|
||||||
if (!chan[c.chan].active || chan[c.chan].insChanged) {
|
if (!chan[c.chan].active || chan[c.chan].insChanged) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[c.chan].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[c.chan].outVol&0x7f,127));
|
||||||
}
|
}
|
||||||
|
@ -448,7 +448,7 @@ int DivPlatformArcade::dispatch(DivCommand c) {
|
||||||
for (int i=0; i<4; i++) {
|
for (int i=0; i<4; i++) {
|
||||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
||||||
if (isOutput[chan[c.chan].state.alg][i]) {
|
if (KVS(c.chan,i)) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[c.chan].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[c.chan].outVol&0x7f,127));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
@ -545,7 +545,7 @@ int DivPlatformArcade::dispatch(DivCommand c) {
|
||||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
||||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
||||||
op.tl=c.value2;
|
op.tl=c.value2;
|
||||||
if (isOutput[chan[c.chan].state.alg][c.value]) {
|
if (KVS(c.chan,c.value)) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[c.chan].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[c.chan].outVol&0x7f,127));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
@ -746,7 +746,7 @@ void DivPlatformArcade::forceIns() {
|
||||||
for (int j=0; j<4; j++) {
|
for (int j=0; j<4; j++) {
|
||||||
unsigned short baseAddr=chanOffs[i]|opOffs[j];
|
unsigned short baseAddr=chanOffs[i]|opOffs[j];
|
||||||
DivInstrumentFM::Operator op=chan[i].state.op[j];
|
DivInstrumentFM::Operator op=chan[i].state.op[j];
|
||||||
if (isOutput[chan[i].state.alg][j]) {
|
if (KVS(i,j)) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
|
|
@ -156,8 +156,8 @@ void DivPlatformAY8910::acquire(short* bufL, short* bufR, size_t start, size_t l
|
||||||
ay->sound_stream_update(ayBuf,len);
|
ay->sound_stream_update(ayBuf,len);
|
||||||
if (stereo) {
|
if (stereo) {
|
||||||
for (size_t i=0; i<len; i++) {
|
for (size_t i=0; i<len; i++) {
|
||||||
bufL[i+start]=ayBuf[0][i]+ayBuf[1][i];
|
bufL[i+start]=ayBuf[0][i]+ayBuf[1][i]+((ayBuf[2][i]*stereoSep)>>8);
|
||||||
bufR[i+start]=ayBuf[1][i]+ayBuf[2][i];
|
bufR[i+start]=((ayBuf[0][i]*stereoSep)>>8)+ayBuf[1][i]+ayBuf[2][i];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (size_t i=0; i<len; i++) {
|
for (size_t i=0; i<len; i++) {
|
||||||
|
@ -167,7 +167,7 @@ void DivPlatformAY8910::acquire(short* bufL, short* bufR, size_t start, size_t l
|
||||||
}
|
}
|
||||||
for (int ch=0; ch<3; ch++) {
|
for (int ch=0; ch<3; ch++) {
|
||||||
for (size_t i=0; i<len; i++) {
|
for (size_t i=0; i<len; i++) {
|
||||||
oscBuf[ch]->data[oscBuf[ch]->needle++]=ayBuf[ch][i];
|
oscBuf[ch]->data[oscBuf[ch]->needle++]=ayBuf[ch][i]<<2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -803,6 +803,7 @@ void DivPlatformAY8910::setFlags(unsigned int flags) {
|
||||||
ay->device_reset();
|
ay->device_reset();
|
||||||
|
|
||||||
stereo=(flags>>6)&1;
|
stereo=(flags>>6)&1;
|
||||||
|
stereoSep=(flags>>8)&255;
|
||||||
}
|
}
|
||||||
|
|
||||||
int DivPlatformAY8910::init(DivEngine* p, int channels, int sugRate, unsigned int flags) {
|
int DivPlatformAY8910::init(DivEngine* p, int channels, int sugRate, unsigned int flags) {
|
||||||
|
|
|
@ -124,6 +124,7 @@ class DivPlatformAY8910: public DivDispatch {
|
||||||
unsigned char lastBusy;
|
unsigned char lastBusy;
|
||||||
|
|
||||||
unsigned char sampleBank;
|
unsigned char sampleBank;
|
||||||
|
unsigned char stereoSep;
|
||||||
|
|
||||||
int delay;
|
int delay;
|
||||||
|
|
||||||
|
|
|
@ -140,8 +140,8 @@ void DivPlatformAY8930::acquire(short* bufL, short* bufR, size_t start, size_t l
|
||||||
ay->sound_stream_update(ayBuf,len);
|
ay->sound_stream_update(ayBuf,len);
|
||||||
if (stereo) {
|
if (stereo) {
|
||||||
for (size_t i=0; i<len; i++) {
|
for (size_t i=0; i<len; i++) {
|
||||||
bufL[i+start]=ayBuf[0][i]+ayBuf[1][i];
|
bufL[i+start]=ayBuf[0][i]+ayBuf[1][i]+((ayBuf[2][i]*stereoSep)>>8);
|
||||||
bufR[i+start]=ayBuf[1][i]+ayBuf[2][i];
|
bufR[i+start]=((ayBuf[0][i]*stereoSep)>>8)+ayBuf[1][i]+ayBuf[2][i];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (size_t i=0; i<len; i++) {
|
for (size_t i=0; i<len; i++) {
|
||||||
|
@ -152,7 +152,7 @@ void DivPlatformAY8930::acquire(short* bufL, short* bufR, size_t start, size_t l
|
||||||
|
|
||||||
for (int ch=0; ch<3; ch++) {
|
for (int ch=0; ch<3; ch++) {
|
||||||
for (size_t i=0; i<len; i++) {
|
for (size_t i=0; i<len; i++) {
|
||||||
oscBuf[ch]->data[oscBuf[ch]->needle++]=ayBuf[ch][i];
|
oscBuf[ch]->data[oscBuf[ch]->needle++]=ayBuf[ch][i]<<2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -760,6 +760,7 @@ void DivPlatformAY8930::setFlags(unsigned int flags) {
|
||||||
}
|
}
|
||||||
|
|
||||||
stereo=(flags>>6)&1;
|
stereo=(flags>>6)&1;
|
||||||
|
stereoSep=(flags>>8)&255;
|
||||||
}
|
}
|
||||||
|
|
||||||
int DivPlatformAY8930::init(DivEngine* p, int channels, int sugRate, unsigned int flags) {
|
int DivPlatformAY8930::init(DivEngine* p, int channels, int sugRate, unsigned int flags) {
|
||||||
|
|
|
@ -132,6 +132,7 @@ class DivPlatformAY8930: public DivDispatch {
|
||||||
DivDispatchOscBuffer* oscBuf[3];
|
DivDispatchOscBuffer* oscBuf[3];
|
||||||
unsigned char regPool[32];
|
unsigned char regPool[32];
|
||||||
unsigned char ayNoiseAnd, ayNoiseOr;
|
unsigned char ayNoiseAnd, ayNoiseOr;
|
||||||
|
unsigned char stereoSep;
|
||||||
bool bank;
|
bool bank;
|
||||||
|
|
||||||
unsigned char sampleBank;
|
unsigned char sampleBank;
|
||||||
|
|
|
@ -23,6 +23,8 @@
|
||||||
#include "../dispatch.h"
|
#include "../dispatch.h"
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
|
||||||
|
#define KVS(x,y) ((chan[x].state.op[y].kvs==2 && isOutput[chan[x].state.alg][y]) || chan[x].state.op[y].kvs==1)
|
||||||
|
|
||||||
class DivPlatformFMBase: public DivDispatch {
|
class DivPlatformFMBase: public DivDispatch {
|
||||||
protected:
|
protected:
|
||||||
const bool isOutput[8][4]={
|
const bool isOutput[8][4]={
|
||||||
|
|
|
@ -254,7 +254,7 @@ void DivPlatformGenesis::tick(bool sysTick) {
|
||||||
if (isMuted[i]) {
|
if (isMuted[i]) {
|
||||||
rWrite(baseAddr+ADDR_TL,127);
|
rWrite(baseAddr+ADDR_TL,127);
|
||||||
} else {
|
} else {
|
||||||
if (isOutput[chan[i].state.alg][j]) {
|
if (KVS(i,j)) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
@ -327,7 +327,7 @@ void DivPlatformGenesis::tick(bool sysTick) {
|
||||||
if (isMuted[i]) {
|
if (isMuted[i]) {
|
||||||
rWrite(baseAddr+ADDR_TL,127);
|
rWrite(baseAddr+ADDR_TL,127);
|
||||||
} else {
|
} else {
|
||||||
if (isOutput[chan[i].state.alg][j]) {
|
if (KVS(i,j)) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
@ -384,7 +384,7 @@ void DivPlatformGenesis::tick(bool sysTick) {
|
||||||
if (isMuted[i]) {
|
if (isMuted[i]) {
|
||||||
rWrite(baseAddr+ADDR_TL,127);
|
rWrite(baseAddr+ADDR_TL,127);
|
||||||
} else {
|
} else {
|
||||||
if (isOutput[chan[i].state.alg][j]) {
|
if (KVS(i,j)) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
@ -501,7 +501,7 @@ void DivPlatformGenesis::muteChannel(int ch, bool mute) {
|
||||||
if (isMuted[ch]) {
|
if (isMuted[ch]) {
|
||||||
rWrite(baseAddr+ADDR_TL,127);
|
rWrite(baseAddr+ADDR_TL,127);
|
||||||
} else {
|
} else {
|
||||||
if (isOutput[chan[ch].state.alg][j]) {
|
if (KVS(ch,j)) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[ch].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[ch].outVol&0x7f,127));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
@ -614,7 +614,7 @@ int DivPlatformGenesis::dispatch(DivCommand c) {
|
||||||
if (isMuted[c.chan]) {
|
if (isMuted[c.chan]) {
|
||||||
rWrite(baseAddr+ADDR_TL,127);
|
rWrite(baseAddr+ADDR_TL,127);
|
||||||
} else {
|
} else {
|
||||||
if (isOutput[chan[c.chan].state.alg][i]) {
|
if (KVS(c.chan,i)) {
|
||||||
if (!chan[c.chan].active || chan[c.chan].insChanged) {
|
if (!chan[c.chan].active || chan[c.chan].insChanged) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[c.chan].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[c.chan].outVol&0x7f,127));
|
||||||
}
|
}
|
||||||
|
@ -687,7 +687,7 @@ int DivPlatformGenesis::dispatch(DivCommand c) {
|
||||||
if (isMuted[c.chan]) {
|
if (isMuted[c.chan]) {
|
||||||
rWrite(baseAddr+ADDR_TL,127);
|
rWrite(baseAddr+ADDR_TL,127);
|
||||||
} else {
|
} else {
|
||||||
if (isOutput[chan[c.chan].state.alg][i]) {
|
if (KVS(c.chan,i)) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[c.chan].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[c.chan].outVol&0x7f,127));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
@ -860,7 +860,7 @@ int DivPlatformGenesis::dispatch(DivCommand c) {
|
||||||
if (isMuted[c.chan]) {
|
if (isMuted[c.chan]) {
|
||||||
rWrite(baseAddr+ADDR_TL,127);
|
rWrite(baseAddr+ADDR_TL,127);
|
||||||
} else {
|
} else {
|
||||||
if (isOutput[chan[c.chan].state.alg][c.value]) {
|
if (KVS(c.chan,c.value)) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[c.chan].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[c.chan].outVol&0x7f,127));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
@ -1051,7 +1051,7 @@ void DivPlatformGenesis::forceIns() {
|
||||||
if (isMuted[i]) {
|
if (isMuted[i]) {
|
||||||
rWrite(baseAddr+ADDR_TL,127);
|
rWrite(baseAddr+ADDR_TL,127);
|
||||||
} else {
|
} else {
|
||||||
if (isOutput[chan[i].state.alg][j]) {
|
if (KVS(i,j)) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
|
|
@ -209,7 +209,7 @@ int DivPlatformGenesisExt::dispatch(DivCommand c) {
|
||||||
op.tl=c.value2;
|
op.tl=c.value2;
|
||||||
if (isOpMuted[ch]) {
|
if (isOpMuted[ch]) {
|
||||||
rWrite(baseAddr+0x40,127);
|
rWrite(baseAddr+0x40,127);
|
||||||
} else if (isOutput[chan[2].state.alg][c.value]) {
|
} else if (KVS(2,c.value)) {
|
||||||
rWrite(baseAddr+0x40,127-VOL_SCALE_LOG(127-op.tl,opChan[ch].vol&0x7f,127));
|
rWrite(baseAddr+0x40,127-VOL_SCALE_LOG(127-op.tl,opChan[ch].vol&0x7f,127));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+0x40,op.tl);
|
rWrite(baseAddr+0x40,op.tl);
|
||||||
|
@ -392,7 +392,7 @@ void DivPlatformGenesisExt::muteChannel(int ch, bool mute) {
|
||||||
if (isOpMuted[ch-2]) {
|
if (isOpMuted[ch-2]) {
|
||||||
rWrite(baseAddr+0x40,127);
|
rWrite(baseAddr+0x40,127);
|
||||||
immWrite(baseAddr+0x40,127);
|
immWrite(baseAddr+0x40,127);
|
||||||
} else if (isOutput[chan[2].state.alg][ordch]) {
|
} else if (KVS(2,ordch)) {
|
||||||
rWrite(baseAddr+0x40,127-VOL_SCALE_LOG(127-op.tl,opChan[ch-2].vol&0x7f,127));
|
rWrite(baseAddr+0x40,127-VOL_SCALE_LOG(127-op.tl,opChan[ch-2].vol&0x7f,127));
|
||||||
immWrite(baseAddr+0x40,127-VOL_SCALE_LOG(127-op.tl,opChan[ch-2].vol&0x7f,127));
|
immWrite(baseAddr+0x40,127-VOL_SCALE_LOG(127-op.tl,opChan[ch-2].vol&0x7f,127));
|
||||||
} else {
|
} else {
|
||||||
|
@ -526,7 +526,7 @@ void DivPlatformGenesisExt::forceIns() {
|
||||||
if (i==2 && extMode) { // extended channel
|
if (i==2 && extMode) { // extended channel
|
||||||
if (isOpMuted[j]) {
|
if (isOpMuted[j]) {
|
||||||
rWrite(baseAddr+0x40,127);
|
rWrite(baseAddr+0x40,127);
|
||||||
} else if (isOutput[chan[i].state.alg][j]) {
|
} else if (KVS(i,j)) {
|
||||||
rWrite(baseAddr+0x40,127-VOL_SCALE_LOG(127-op.tl,opChan[j].vol&0x7f,127));
|
rWrite(baseAddr+0x40,127-VOL_SCALE_LOG(127-op.tl,opChan[j].vol&0x7f,127));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+0x40,op.tl);
|
rWrite(baseAddr+0x40,op.tl);
|
||||||
|
@ -535,7 +535,7 @@ void DivPlatformGenesisExt::forceIns() {
|
||||||
if (isMuted[i]) {
|
if (isMuted[i]) {
|
||||||
rWrite(baseAddr+ADDR_TL,127);
|
rWrite(baseAddr+ADDR_TL,127);
|
||||||
} else {
|
} else {
|
||||||
if (isOutput[chan[i].state.alg][j]) {
|
if (KVS(i,j)) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
|
|
@ -26,6 +26,8 @@
|
||||||
#define rWrite(a,v) if (!skipRegisterWrites) {pendingWrites[a]=v;}
|
#define rWrite(a,v) if (!skipRegisterWrites) {pendingWrites[a]=v;}
|
||||||
#define immWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);} }
|
#define immWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);} }
|
||||||
|
|
||||||
|
#define KVSL(x,y) ((chan[x].state.op[orderedOpsL1[ops==4][y]].kvs==2 && isOutputL[ops==4][chan[x].state.alg][y]) || chan[x].state.op[orderedOpsL1[ops==4][y]].kvs==1)
|
||||||
|
|
||||||
#define CHIP_FREQBASE chipFreqBase
|
#define CHIP_FREQBASE chipFreqBase
|
||||||
|
|
||||||
// N = invalid
|
// N = invalid
|
||||||
|
@ -138,6 +140,11 @@ const bool isOutputL[2][4][4]={
|
||||||
|
|
||||||
#undef N
|
#undef N
|
||||||
|
|
||||||
|
const int orderedOpsL1[2][4]={
|
||||||
|
{0, 1, 0, 1}, // 2-op
|
||||||
|
{0, 2, 1, 3} // 4-op
|
||||||
|
};
|
||||||
|
|
||||||
const int orderedOpsL[4]={
|
const int orderedOpsL[4]={
|
||||||
0,2,1,3
|
0,2,1,3
|
||||||
};
|
};
|
||||||
|
@ -288,7 +295,7 @@ void DivPlatformOPL::tick(bool sysTick) {
|
||||||
if (isMuted[i]) {
|
if (isMuted[i]) {
|
||||||
rWrite(baseAddr+ADDR_KSL_TL,63|(op.ksl<<6));
|
rWrite(baseAddr+ADDR_KSL_TL,63|(op.ksl<<6));
|
||||||
} else {
|
} else {
|
||||||
if (isOutputL[ops==4][chan[i].state.alg][j] || i>melodicChans) {
|
if (KVSL(i,j) || i>melodicChans) {
|
||||||
rWrite(baseAddr+ADDR_KSL_TL,(63-VOL_SCALE_LOG(63-op.tl,chan[i].outVol&0x3f,63))|(op.ksl<<6));
|
rWrite(baseAddr+ADDR_KSL_TL,(63-VOL_SCALE_LOG(63-op.tl,chan[i].outVol&0x3f,63))|(op.ksl<<6));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_KSL_TL,op.tl|(op.ksl<<6));
|
rWrite(baseAddr+ADDR_KSL_TL,op.tl|(op.ksl<<6));
|
||||||
|
@ -406,7 +413,7 @@ void DivPlatformOPL::tick(bool sysTick) {
|
||||||
if (isMuted[i]) {
|
if (isMuted[i]) {
|
||||||
rWrite(baseAddr+ADDR_KSL_TL,63|(op.ksl<<6));
|
rWrite(baseAddr+ADDR_KSL_TL,63|(op.ksl<<6));
|
||||||
} else {
|
} else {
|
||||||
if (isOutputL[ops==4][chan[i].state.alg][j] || i>melodicChans) {
|
if (KVSL(i,j) || i>melodicChans) {
|
||||||
rWrite(baseAddr+ADDR_KSL_TL,(63-VOL_SCALE_LOG(63-op.tl,chan[i].outVol&0x3f,63))|(op.ksl<<6));
|
rWrite(baseAddr+ADDR_KSL_TL,(63-VOL_SCALE_LOG(63-op.tl,chan[i].outVol&0x3f,63))|(op.ksl<<6));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_KSL_TL,op.tl|(op.ksl<<6));
|
rWrite(baseAddr+ADDR_KSL_TL,op.tl|(op.ksl<<6));
|
||||||
|
@ -626,7 +633,7 @@ void DivPlatformOPL::muteChannel(int ch, bool mute) {
|
||||||
if (isMuted[ch]) {
|
if (isMuted[ch]) {
|
||||||
rWrite(baseAddr+ADDR_KSL_TL,63|(op.ksl<<6));
|
rWrite(baseAddr+ADDR_KSL_TL,63|(op.ksl<<6));
|
||||||
} else {
|
} else {
|
||||||
if (isOutputL[ops==4][chan[ch].state.alg][i] || ch>melodicChans) {
|
if (KVSL(ch,i) || ch>melodicChans) {
|
||||||
rWrite(baseAddr+ADDR_KSL_TL,(63-VOL_SCALE_LOG(63-op.tl,chan[ch].outVol&0x3f,63))|(op.ksl<<6));
|
rWrite(baseAddr+ADDR_KSL_TL,(63-VOL_SCALE_LOG(63-op.tl,chan[ch].outVol&0x3f,63))|(op.ksl<<6));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_KSL_TL,op.tl|(op.ksl<<6));
|
rWrite(baseAddr+ADDR_KSL_TL,op.tl|(op.ksl<<6));
|
||||||
|
@ -802,7 +809,7 @@ int DivPlatformOPL::dispatch(DivCommand c) {
|
||||||
if (isMuted[c.chan]) {
|
if (isMuted[c.chan]) {
|
||||||
rWrite(baseAddr+ADDR_KSL_TL,63|(op.ksl<<6));
|
rWrite(baseAddr+ADDR_KSL_TL,63|(op.ksl<<6));
|
||||||
} else {
|
} else {
|
||||||
if (isOutputL[ops==4][chan[c.chan].state.alg][i] || c.chan>melodicChans) {
|
if (KVSL(c.chan,i) || c.chan>melodicChans) {
|
||||||
rWrite(baseAddr+ADDR_KSL_TL,(63-VOL_SCALE_LOG(63-op.tl,chan[c.chan].outVol&0x3f,63))|(op.ksl<<6));
|
rWrite(baseAddr+ADDR_KSL_TL,(63-VOL_SCALE_LOG(63-op.tl,chan[c.chan].outVol&0x3f,63))|(op.ksl<<6));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_KSL_TL,op.tl|(op.ksl<<6));
|
rWrite(baseAddr+ADDR_KSL_TL,op.tl|(op.ksl<<6));
|
||||||
|
@ -910,7 +917,7 @@ int DivPlatformOPL::dispatch(DivCommand c) {
|
||||||
if (isMuted[c.chan]) {
|
if (isMuted[c.chan]) {
|
||||||
rWrite(baseAddr+ADDR_KSL_TL,63|(op.ksl<<6));
|
rWrite(baseAddr+ADDR_KSL_TL,63|(op.ksl<<6));
|
||||||
} else {
|
} else {
|
||||||
if (isOutputL[ops==4][chan[c.chan].state.alg][i] || c.chan>melodicChans) {
|
if (KVSL(c.chan,i) || c.chan>melodicChans) {
|
||||||
rWrite(baseAddr+ADDR_KSL_TL,(63-VOL_SCALE_LOG(63-op.tl,chan[c.chan].outVol&0x3f,63))|(op.ksl<<6));
|
rWrite(baseAddr+ADDR_KSL_TL,(63-VOL_SCALE_LOG(63-op.tl,chan[c.chan].outVol&0x3f,63))|(op.ksl<<6));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_KSL_TL,op.tl|(op.ksl<<6));
|
rWrite(baseAddr+ADDR_KSL_TL,op.tl|(op.ksl<<6));
|
||||||
|
@ -1059,7 +1066,7 @@ int DivPlatformOPL::dispatch(DivCommand c) {
|
||||||
if (isMuted[c.chan]) {
|
if (isMuted[c.chan]) {
|
||||||
rWrite(baseAddr+ADDR_KSL_TL,63|(op.ksl<<6));
|
rWrite(baseAddr+ADDR_KSL_TL,63|(op.ksl<<6));
|
||||||
} else {
|
} else {
|
||||||
if (isOutputL[ops==4][chan[c.chan].state.alg][c.value] || c.chan>melodicChans) {
|
if (KVSL(c.chan,c.value) || c.chan>melodicChans) {
|
||||||
rWrite(baseAddr+ADDR_KSL_TL,(63-VOL_SCALE_LOG(63-op.tl,chan[c.chan].outVol&0x3f,63))|(op.ksl<<6));
|
rWrite(baseAddr+ADDR_KSL_TL,(63-VOL_SCALE_LOG(63-op.tl,chan[c.chan].outVol&0x3f,63))|(op.ksl<<6));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_KSL_TL,op.tl|(op.ksl<<6));
|
rWrite(baseAddr+ADDR_KSL_TL,op.tl|(op.ksl<<6));
|
||||||
|
@ -1289,7 +1296,7 @@ int DivPlatformOPL::dispatch(DivCommand c) {
|
||||||
if (isMuted[c.chan]) {
|
if (isMuted[c.chan]) {
|
||||||
rWrite(baseAddr+ADDR_KSL_TL,63|(op.ksl<<6));
|
rWrite(baseAddr+ADDR_KSL_TL,63|(op.ksl<<6));
|
||||||
} else {
|
} else {
|
||||||
if (isOutputL[ops==4][chan[c.chan].state.alg][i] || c.chan>melodicChans) {
|
if (KVSL(c.chan,i) || c.chan>melodicChans) {
|
||||||
rWrite(baseAddr+ADDR_KSL_TL,(63-VOL_SCALE_LOG(63-op.tl,chan[c.chan].outVol&0x3f,63))|(op.ksl<<6));
|
rWrite(baseAddr+ADDR_KSL_TL,(63-VOL_SCALE_LOG(63-op.tl,chan[c.chan].outVol&0x3f,63))|(op.ksl<<6));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_KSL_TL,op.tl|(op.ksl<<6));
|
rWrite(baseAddr+ADDR_KSL_TL,op.tl|(op.ksl<<6));
|
||||||
|
@ -1306,7 +1313,7 @@ int DivPlatformOPL::dispatch(DivCommand c) {
|
||||||
if (isMuted[c.chan]) {
|
if (isMuted[c.chan]) {
|
||||||
rWrite(baseAddr+ADDR_KSL_TL,63|(op.ksl<<6));
|
rWrite(baseAddr+ADDR_KSL_TL,63|(op.ksl<<6));
|
||||||
} else {
|
} else {
|
||||||
if (isOutputL[ops==4][chan[c.chan].state.alg][c.value] || c.chan>melodicChans) {
|
if (KVSL(c.chan,c.value) || c.chan>melodicChans) {
|
||||||
rWrite(baseAddr+ADDR_KSL_TL,(63-VOL_SCALE_LOG(63-op.tl,chan[c.chan].outVol&0x3f,63))|(op.ksl<<6));
|
rWrite(baseAddr+ADDR_KSL_TL,(63-VOL_SCALE_LOG(63-op.tl,chan[c.chan].outVol&0x3f,63))|(op.ksl<<6));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_KSL_TL,op.tl|(op.ksl<<6));
|
rWrite(baseAddr+ADDR_KSL_TL,op.tl|(op.ksl<<6));
|
||||||
|
@ -1383,7 +1390,7 @@ void DivPlatformOPL::forceIns() {
|
||||||
if (isMuted[i]) {
|
if (isMuted[i]) {
|
||||||
rWrite(baseAddr+ADDR_KSL_TL,63|(op.ksl<<6));
|
rWrite(baseAddr+ADDR_KSL_TL,63|(op.ksl<<6));
|
||||||
} else {
|
} else {
|
||||||
if (isOutputL[ops==4][chan[i].state.alg][j] || i>melodicChans) {
|
if (KVSL(i,j) || i>melodicChans) {
|
||||||
rWrite(baseAddr+ADDR_KSL_TL,(63-VOL_SCALE_LOG(63-op.tl,chan[i].outVol&0x3f,63))|(op.ksl<<6));
|
rWrite(baseAddr+ADDR_KSL_TL,(63-VOL_SCALE_LOG(63-op.tl,chan[i].outVol&0x3f,63))|(op.ksl<<6));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_KSL_TL,op.tl|(op.ksl<<6));
|
rWrite(baseAddr+ADDR_KSL_TL,op.tl|(op.ksl<<6));
|
||||||
|
@ -1432,6 +1439,15 @@ DivMacroInt* DivPlatformOPL::getChanMacroInt(int ch) {
|
||||||
|
|
||||||
DivDispatchOscBuffer* DivPlatformOPL::getOscBuffer(int ch) {
|
DivDispatchOscBuffer* DivPlatformOPL::getOscBuffer(int ch) {
|
||||||
if (ch>=18) return NULL;
|
if (ch>=18) return NULL;
|
||||||
|
if (oplType==3 && ch<12) {
|
||||||
|
if (chan[ch&(~1)].fourOp) {
|
||||||
|
if (ch&1) {
|
||||||
|
return oscBuf[ch-1];
|
||||||
|
} else {
|
||||||
|
return oscBuf[ch+1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return oscBuf[ch];
|
return oscBuf[ch];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,7 @@ void DivPlatformSMS::acquire_nuked(short* bufL, short* bufR, size_t start, size_
|
||||||
if (isMuted[i]) {
|
if (isMuted[i]) {
|
||||||
oscBuf[i]->data[oscBuf[i]->needle++]=0;
|
oscBuf[i]->data[oscBuf[i]->needle++]=0;
|
||||||
} else {
|
} else {
|
||||||
oscBuf[i]->data[oscBuf[i]->needle++]=sn_nuked.vol_table[sn_nuked.volume_out[i]];
|
oscBuf[i]->data[oscBuf[i]->needle++]=sn_nuked.vol_table[sn_nuked.volume_out[i]]*3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -104,7 +104,7 @@ void DivPlatformSMS::acquire_mame(short* bufL, short* bufR, size_t start, size_t
|
||||||
if (isMuted[i]) {
|
if (isMuted[i]) {
|
||||||
oscBuf[i]->data[oscBuf[i]->needle++]=0;
|
oscBuf[i]->data[oscBuf[i]->needle++]=0;
|
||||||
} else {
|
} else {
|
||||||
oscBuf[i]->data[oscBuf[i]->needle++]=sn->get_channel_output(i);
|
oscBuf[i]->data[oscBuf[i]->needle++]=sn->get_channel_output(i)*3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,7 +112,7 @@ void DivPlatformTX81Z::tick(bool sysTick) {
|
||||||
if (isMuted[i]) {
|
if (isMuted[i]) {
|
||||||
rWrite(baseAddr+ADDR_TL,127);
|
rWrite(baseAddr+ADDR_TL,127);
|
||||||
} else {
|
} else {
|
||||||
if (isOutput[chan[i].state.alg][j]) {
|
if (KVS(i,j)) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
@ -179,7 +179,7 @@ void DivPlatformTX81Z::tick(bool sysTick) {
|
||||||
if (isMuted[i]) {
|
if (isMuted[i]) {
|
||||||
rWrite(baseAddr+ADDR_TL,127);
|
rWrite(baseAddr+ADDR_TL,127);
|
||||||
} else {
|
} else {
|
||||||
if (isOutput[chan[i].state.alg][j]) {
|
if (KVS(i,j)) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
@ -232,7 +232,7 @@ void DivPlatformTX81Z::tick(bool sysTick) {
|
||||||
if (isMuted[i]) {
|
if (isMuted[i]) {
|
||||||
rWrite(baseAddr+ADDR_TL,127);
|
rWrite(baseAddr+ADDR_TL,127);
|
||||||
} else {
|
} else {
|
||||||
if (isOutput[chan[i].state.alg][j]) {
|
if (KVS(i,j)) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
@ -324,7 +324,7 @@ void DivPlatformTX81Z::muteChannel(int ch, bool mute) {
|
||||||
if (isMuted[ch]) {
|
if (isMuted[ch]) {
|
||||||
rWrite(baseAddr+ADDR_TL,127);
|
rWrite(baseAddr+ADDR_TL,127);
|
||||||
} else {
|
} else {
|
||||||
if (isOutput[chan[ch].state.alg][i]) {
|
if (KVS(ch,i)) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[ch].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[ch].outVol&0x7f,127));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
@ -353,7 +353,7 @@ int DivPlatformTX81Z::dispatch(DivCommand c) {
|
||||||
if (isMuted[c.chan]) {
|
if (isMuted[c.chan]) {
|
||||||
rWrite(baseAddr+ADDR_TL,127);
|
rWrite(baseAddr+ADDR_TL,127);
|
||||||
} else {
|
} else {
|
||||||
if (isOutput[chan[c.chan].state.alg][i]) {
|
if (KVS(c.chan,i)) {
|
||||||
if (!chan[c.chan].active || chan[c.chan].insChanged) {
|
if (!chan[c.chan].active || chan[c.chan].insChanged) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[c.chan].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[c.chan].outVol&0x7f,127));
|
||||||
}
|
}
|
||||||
|
@ -419,7 +419,7 @@ int DivPlatformTX81Z::dispatch(DivCommand c) {
|
||||||
if (isMuted[c.chan]) {
|
if (isMuted[c.chan]) {
|
||||||
rWrite(baseAddr+ADDR_TL,127);
|
rWrite(baseAddr+ADDR_TL,127);
|
||||||
} else {
|
} else {
|
||||||
if (isOutput[chan[c.chan].state.alg][i]) {
|
if (KVS(c.chan,i)) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[c.chan].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[c.chan].outVol&0x7f,127));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
@ -519,7 +519,7 @@ int DivPlatformTX81Z::dispatch(DivCommand c) {
|
||||||
if (isMuted[c.chan]) {
|
if (isMuted[c.chan]) {
|
||||||
rWrite(baseAddr+ADDR_TL,127);
|
rWrite(baseAddr+ADDR_TL,127);
|
||||||
} else {
|
} else {
|
||||||
if (isOutput[chan[c.chan].state.alg][c.value]) {
|
if (KVS(c.chan,c.value)) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[c.chan].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[c.chan].outVol&0x7f,127));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
@ -811,7 +811,7 @@ void DivPlatformTX81Z::forceIns() {
|
||||||
if (isMuted[i]) {
|
if (isMuted[i]) {
|
||||||
rWrite(baseAddr+ADDR_TL,127);
|
rWrite(baseAddr+ADDR_TL,127);
|
||||||
} else {
|
} else {
|
||||||
if (isOutput[chan[i].state.alg][j]) {
|
if (KVS(i,j)) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
|
|
@ -220,7 +220,7 @@ void DivPlatformYM2203::tick(bool sysTick) {
|
||||||
if (isMuted[i]) {
|
if (isMuted[i]) {
|
||||||
rWrite(baseAddr+ADDR_TL,127);
|
rWrite(baseAddr+ADDR_TL,127);
|
||||||
} else {
|
} else {
|
||||||
if (isOutput[chan[i].state.alg][j]) {
|
if (KVS(i,j)) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
@ -261,7 +261,7 @@ void DivPlatformYM2203::tick(bool sysTick) {
|
||||||
if (isMuted[i]) {
|
if (isMuted[i]) {
|
||||||
rWrite(baseAddr+ADDR_TL,127);
|
rWrite(baseAddr+ADDR_TL,127);
|
||||||
} else {
|
} else {
|
||||||
if (isOutput[chan[i].state.alg][j]) {
|
if (KVS(i,j)) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
@ -310,7 +310,7 @@ void DivPlatformYM2203::tick(bool sysTick) {
|
||||||
if (isMuted[i]) {
|
if (isMuted[i]) {
|
||||||
rWrite(baseAddr+ADDR_TL,127);
|
rWrite(baseAddr+ADDR_TL,127);
|
||||||
} else {
|
} else {
|
||||||
if (isOutput[chan[i].state.alg][j]) {
|
if (KVS(i,j)) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
@ -427,7 +427,7 @@ int DivPlatformYM2203::dispatch(DivCommand c) {
|
||||||
if (isMuted[c.chan]) {
|
if (isMuted[c.chan]) {
|
||||||
rWrite(baseAddr+ADDR_TL,127);
|
rWrite(baseAddr+ADDR_TL,127);
|
||||||
} else {
|
} else {
|
||||||
if (isOutput[chan[c.chan].state.alg][i]) {
|
if (KVS(c.chan,i)) {
|
||||||
if (!chan[c.chan].active || chan[c.chan].insChanged) {
|
if (!chan[c.chan].active || chan[c.chan].insChanged) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[c.chan].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[c.chan].outVol&0x7f,127));
|
||||||
}
|
}
|
||||||
|
@ -487,7 +487,7 @@ int DivPlatformYM2203::dispatch(DivCommand c) {
|
||||||
if (isMuted[c.chan]) {
|
if (isMuted[c.chan]) {
|
||||||
rWrite(baseAddr+ADDR_TL,127);
|
rWrite(baseAddr+ADDR_TL,127);
|
||||||
} else {
|
} else {
|
||||||
if (isOutput[chan[c.chan].state.alg][i]) {
|
if (KVS(c.chan,i)) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[c.chan].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[c.chan].outVol&0x7f,127));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
@ -572,7 +572,7 @@ int DivPlatformYM2203::dispatch(DivCommand c) {
|
||||||
if (isMuted[c.chan]) {
|
if (isMuted[c.chan]) {
|
||||||
rWrite(baseAddr+ADDR_TL,127);
|
rWrite(baseAddr+ADDR_TL,127);
|
||||||
} else {
|
} else {
|
||||||
if (isOutput[chan[c.chan].state.alg][c.value]) {
|
if (KVS(c.chan,c.value)) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[c.chan].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[c.chan].outVol&0x7f,127));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
@ -764,7 +764,7 @@ void DivPlatformYM2203::muteChannel(int ch, bool mute) {
|
||||||
if (isMuted[ch]) {
|
if (isMuted[ch]) {
|
||||||
rWrite(baseAddr+ADDR_TL,127);
|
rWrite(baseAddr+ADDR_TL,127);
|
||||||
} else {
|
} else {
|
||||||
if (isOutput[chan[ch].state.alg][j]) {
|
if (KVS(ch,j)) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[ch].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[ch].outVol&0x7f,127));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
@ -781,7 +781,7 @@ void DivPlatformYM2203::forceIns() {
|
||||||
if (isMuted[i]) {
|
if (isMuted[i]) {
|
||||||
rWrite(baseAddr+ADDR_TL,127);
|
rWrite(baseAddr+ADDR_TL,127);
|
||||||
} else {
|
} else {
|
||||||
if (isOutput[chan[i].state.alg][j]) {
|
if (KVS(i,j)) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
|
|
@ -442,7 +442,7 @@ void DivPlatformYM2203Ext::forceIns() {
|
||||||
if (isMuted[i]) {
|
if (isMuted[i]) {
|
||||||
rWrite(baseAddr+ADDR_TL,127);
|
rWrite(baseAddr+ADDR_TL,127);
|
||||||
} else {
|
} else {
|
||||||
if (isOutput[chan[i].state.alg][j]) {
|
if (KVS(i,j)) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
|
|
@ -376,7 +376,7 @@ void DivPlatformYM2608::tick(bool sysTick) {
|
||||||
for (int j=0; j<4; j++) {
|
for (int j=0; j<4; j++) {
|
||||||
unsigned short baseAddr=chanOffs[i]|opOffs[j];
|
unsigned short baseAddr=chanOffs[i]|opOffs[j];
|
||||||
DivInstrumentFM::Operator& op=chan[i].state.op[j];
|
DivInstrumentFM::Operator& op=chan[i].state.op[j];
|
||||||
if (isOutput[chan[i].state.alg][j]) {
|
if (KVS(i,j)) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
@ -421,7 +421,7 @@ void DivPlatformYM2608::tick(bool sysTick) {
|
||||||
if (isMuted[i]) {
|
if (isMuted[i]) {
|
||||||
rWrite(baseAddr+ADDR_TL,127);
|
rWrite(baseAddr+ADDR_TL,127);
|
||||||
} else {
|
} else {
|
||||||
if (isOutput[chan[i].state.alg][j]) {
|
if (KVS(i,j)) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
@ -475,7 +475,7 @@ void DivPlatformYM2608::tick(bool sysTick) {
|
||||||
}
|
}
|
||||||
if (m.tl.had) {
|
if (m.tl.had) {
|
||||||
op.tl=127-m.tl.val;
|
op.tl=127-m.tl.val;
|
||||||
if (isOutput[chan[i].state.alg][j]) {
|
if (KVS(i,j)) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
@ -781,7 +781,7 @@ int DivPlatformYM2608::dispatch(DivCommand c) {
|
||||||
for (int i=0; i<4; i++) {
|
for (int i=0; i<4; i++) {
|
||||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
||||||
if (isOutput[chan[c.chan].state.alg][i]) {
|
if (KVS(c.chan,i)) {
|
||||||
if (!chan[c.chan].active || chan[c.chan].insChanged) {
|
if (!chan[c.chan].active || chan[c.chan].insChanged) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[c.chan].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[c.chan].outVol&0x7f,127));
|
||||||
}
|
}
|
||||||
|
@ -846,7 +846,7 @@ int DivPlatformYM2608::dispatch(DivCommand c) {
|
||||||
for (int i=0; i<4; i++) {
|
for (int i=0; i<4; i++) {
|
||||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
||||||
if (isOutput[chan[c.chan].state.alg][i]) {
|
if (KVS(c.chan,i)) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[c.chan].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[c.chan].outVol&0x7f,127));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
@ -957,7 +957,7 @@ int DivPlatformYM2608::dispatch(DivCommand c) {
|
||||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
||||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
||||||
op.tl=c.value2;
|
op.tl=c.value2;
|
||||||
if (isOutput[chan[c.chan].state.alg][c.value]) {
|
if (KVS(c.chan,c.value)) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[c.chan].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[c.chan].outVol&0x7f,127));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
@ -1160,7 +1160,7 @@ void DivPlatformYM2608::forceIns() {
|
||||||
for (int j=0; j<4; j++) {
|
for (int j=0; j<4; j++) {
|
||||||
unsigned short baseAddr=chanOffs[i]|opOffs[j];
|
unsigned short baseAddr=chanOffs[i]|opOffs[j];
|
||||||
DivInstrumentFM::Operator& op=chan[i].state.op[j];
|
DivInstrumentFM::Operator& op=chan[i].state.op[j];
|
||||||
if (isOutput[chan[i].state.alg][j]) {
|
if (KVS(i,j)) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
@ -1181,6 +1181,11 @@ void DivPlatformYM2608::forceIns() {
|
||||||
}
|
}
|
||||||
for (int i=9; i<16; i++) {
|
for (int i=9; i<16; i++) {
|
||||||
chan[i].insChanged=true;
|
chan[i].insChanged=true;
|
||||||
|
if (i>14) { // ADPCM-B
|
||||||
|
immWrite(0x10b,chan[i].outVol);
|
||||||
|
} else {
|
||||||
|
immWrite(0x18+(i-9),isMuted[i]?0:((chan[i].pan<<6)|chan[i].vol));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ay->forceIns();
|
ay->forceIns();
|
||||||
|
|
|
@ -442,7 +442,7 @@ void DivPlatformYM2608Ext::forceIns() {
|
||||||
if (i==2) { // extended channel
|
if (i==2) { // extended channel
|
||||||
if (isOpMuted[j]) {
|
if (isOpMuted[j]) {
|
||||||
rWrite(baseAddr+0x40,127);
|
rWrite(baseAddr+0x40,127);
|
||||||
} else if (isOutput[chan[i].state.alg][j]) {
|
} else if (KVS(i,j)) {
|
||||||
rWrite(baseAddr+0x40,127-VOL_SCALE_LOG(127-op.tl,opChan[j].vol&0x7f,127));
|
rWrite(baseAddr+0x40,127-VOL_SCALE_LOG(127-op.tl,opChan[j].vol&0x7f,127));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+0x40,op.tl);
|
rWrite(baseAddr+0x40,op.tl);
|
||||||
|
@ -451,7 +451,7 @@ void DivPlatformYM2608Ext::forceIns() {
|
||||||
if (isMuted[i]) {
|
if (isMuted[i]) {
|
||||||
rWrite(baseAddr+ADDR_TL,127);
|
rWrite(baseAddr+ADDR_TL,127);
|
||||||
} else {
|
} else {
|
||||||
if (isOutput[chan[i].state.alg][j]) {
|
if (KVS(i,j)) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
@ -472,8 +472,13 @@ void DivPlatformYM2608Ext::forceIns() {
|
||||||
chan[i].freqChanged=true;
|
chan[i].freqChanged=true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int i=6; i<16; i++) {
|
for (int i=9; i<16; i++) {
|
||||||
chan[i].insChanged=true;
|
chan[i].insChanged=true;
|
||||||
|
if (i>14) { // ADPCM-B
|
||||||
|
immWrite(0x10b,chan[i].outVol);
|
||||||
|
} else {
|
||||||
|
immWrite(0x18+(i-9),isMuted[i]?0:((chan[i].pan<<6)|chan[i].vol));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ay->forceIns();
|
ay->forceIns();
|
||||||
ay->flushWrites();
|
ay->flushWrites();
|
||||||
|
|
|
@ -313,7 +313,7 @@ void DivPlatformYM2610::tick(bool sysTick) {
|
||||||
for (int j=0; j<4; j++) {
|
for (int j=0; j<4; j++) {
|
||||||
unsigned short baseAddr=chanOffs[i]|opOffs[j];
|
unsigned short baseAddr=chanOffs[i]|opOffs[j];
|
||||||
DivInstrumentFM::Operator& op=chan[i].state.op[j];
|
DivInstrumentFM::Operator& op=chan[i].state.op[j];
|
||||||
if (isOutput[chan[i].state.alg][j]) {
|
if (KVS(i,j)) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
@ -358,7 +358,7 @@ void DivPlatformYM2610::tick(bool sysTick) {
|
||||||
if (isMuted[i]) {
|
if (isMuted[i]) {
|
||||||
rWrite(baseAddr+ADDR_TL,127);
|
rWrite(baseAddr+ADDR_TL,127);
|
||||||
} else {
|
} else {
|
||||||
if (isOutput[chan[i].state.alg][j]) {
|
if (KVS(i,j)) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
@ -412,7 +412,7 @@ void DivPlatformYM2610::tick(bool sysTick) {
|
||||||
}
|
}
|
||||||
if (m.tl.had) {
|
if (m.tl.had) {
|
||||||
op.tl=127-m.tl.val;
|
op.tl=127-m.tl.val;
|
||||||
if (isOutput[chan[i].state.alg][j]) {
|
if (KVS(i,j)) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
@ -764,7 +764,7 @@ int DivPlatformYM2610::dispatch(DivCommand c) {
|
||||||
for (int i=0; i<4; i++) {
|
for (int i=0; i<4; i++) {
|
||||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
||||||
if (isOutput[chan[c.chan].state.alg][i]) {
|
if (KVS(c.chan,i)) {
|
||||||
if (!chan[c.chan].active || chan[c.chan].insChanged) {
|
if (!chan[c.chan].active || chan[c.chan].insChanged) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[c.chan].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[c.chan].outVol&0x7f,127));
|
||||||
}
|
}
|
||||||
|
@ -829,7 +829,7 @@ int DivPlatformYM2610::dispatch(DivCommand c) {
|
||||||
for (int i=0; i<4; i++) {
|
for (int i=0; i<4; i++) {
|
||||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
||||||
if (isOutput[chan[c.chan].state.alg][i]) {
|
if (KVS(c.chan,i)) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[c.chan].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[c.chan].outVol&0x7f,127));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
@ -947,7 +947,7 @@ int DivPlatformYM2610::dispatch(DivCommand c) {
|
||||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
||||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
||||||
op.tl=c.value2;
|
op.tl=c.value2;
|
||||||
if (isOutput[chan[c.chan].state.alg][c.value]) {
|
if (KVS(c.chan,c.value)) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[c.chan].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[c.chan].outVol&0x7f,127));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
@ -1143,7 +1143,7 @@ void DivPlatformYM2610::forceIns() {
|
||||||
for (int j=0; j<4; j++) {
|
for (int j=0; j<4; j++) {
|
||||||
unsigned short baseAddr=chanOffs[i]|opOffs[j];
|
unsigned short baseAddr=chanOffs[i]|opOffs[j];
|
||||||
DivInstrumentFM::Operator& op=chan[i].state.op[j];
|
DivInstrumentFM::Operator& op=chan[i].state.op[j];
|
||||||
if (isOutput[chan[i].state.alg][j]) {
|
if (KVS(i,j)) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
|
|
@ -376,7 +376,7 @@ void DivPlatformYM2610B::tick(bool sysTick) {
|
||||||
for (int j=0; j<4; j++) {
|
for (int j=0; j<4; j++) {
|
||||||
unsigned short baseAddr=chanOffs[i]|opOffs[j];
|
unsigned short baseAddr=chanOffs[i]|opOffs[j];
|
||||||
DivInstrumentFM::Operator& op=chan[i].state.op[j];
|
DivInstrumentFM::Operator& op=chan[i].state.op[j];
|
||||||
if (isOutput[chan[i].state.alg][j]) {
|
if (KVS(i,j)) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
@ -421,7 +421,7 @@ void DivPlatformYM2610B::tick(bool sysTick) {
|
||||||
if (isMuted[i]) {
|
if (isMuted[i]) {
|
||||||
rWrite(baseAddr+ADDR_TL,127);
|
rWrite(baseAddr+ADDR_TL,127);
|
||||||
} else {
|
} else {
|
||||||
if (isOutput[chan[i].state.alg][j]) {
|
if (KVS(i,j)) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
@ -475,7 +475,7 @@ void DivPlatformYM2610B::tick(bool sysTick) {
|
||||||
}
|
}
|
||||||
if (m.tl.had) {
|
if (m.tl.had) {
|
||||||
op.tl=127-m.tl.val;
|
op.tl=127-m.tl.val;
|
||||||
if (isOutput[chan[i].state.alg][j]) {
|
if (KVS(i,j)) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
@ -826,7 +826,7 @@ int DivPlatformYM2610B::dispatch(DivCommand c) {
|
||||||
for (int i=0; i<4; i++) {
|
for (int i=0; i<4; i++) {
|
||||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
||||||
if (isOutput[chan[c.chan].state.alg][i]) {
|
if (KVS(c.chan,i)) {
|
||||||
if (!chan[c.chan].active || chan[c.chan].insChanged) {
|
if (!chan[c.chan].active || chan[c.chan].insChanged) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[c.chan].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[c.chan].outVol&0x7f,127));
|
||||||
}
|
}
|
||||||
|
@ -891,7 +891,7 @@ int DivPlatformYM2610B::dispatch(DivCommand c) {
|
||||||
for (int i=0; i<4; i++) {
|
for (int i=0; i<4; i++) {
|
||||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
||||||
if (isOutput[chan[c.chan].state.alg][i]) {
|
if (KVS(c.chan,i)) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[c.chan].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[c.chan].outVol&0x7f,127));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
@ -1009,7 +1009,7 @@ int DivPlatformYM2610B::dispatch(DivCommand c) {
|
||||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
||||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
||||||
op.tl=c.value2;
|
op.tl=c.value2;
|
||||||
if (isOutput[chan[c.chan].state.alg][c.value]) {
|
if (KVS(c.chan,c.value)) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[c.chan].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[c.chan].outVol&0x7f,127));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
@ -1205,7 +1205,7 @@ void DivPlatformYM2610B::forceIns() {
|
||||||
for (int j=0; j<4; j++) {
|
for (int j=0; j<4; j++) {
|
||||||
unsigned short baseAddr=chanOffs[i]|opOffs[j];
|
unsigned short baseAddr=chanOffs[i]|opOffs[j];
|
||||||
DivInstrumentFM::Operator& op=chan[i].state.op[j];
|
DivInstrumentFM::Operator& op=chan[i].state.op[j];
|
||||||
if (isOutput[chan[i].state.alg][j]) {
|
if (KVS(i,j)) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
|
|
@ -438,7 +438,7 @@ void DivPlatformYM2610BExt::forceIns() {
|
||||||
if (i==2 && extMode) { // extended channel
|
if (i==2 && extMode) { // extended channel
|
||||||
if (isOpMuted[j]) {
|
if (isOpMuted[j]) {
|
||||||
rWrite(baseAddr+0x40,127);
|
rWrite(baseAddr+0x40,127);
|
||||||
} else if (isOutput[chan[i].state.alg][j]) {
|
} else if (KVS(i,j)) {
|
||||||
rWrite(baseAddr+0x40,127-VOL_SCALE_LOG(127-op.tl,opChan[j].vol&0x7f,127));
|
rWrite(baseAddr+0x40,127-VOL_SCALE_LOG(127-op.tl,opChan[j].vol&0x7f,127));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+0x40,op.tl);
|
rWrite(baseAddr+0x40,op.tl);
|
||||||
|
@ -447,7 +447,7 @@ void DivPlatformYM2610BExt::forceIns() {
|
||||||
if (isMuted[i]) {
|
if (isMuted[i]) {
|
||||||
rWrite(baseAddr+ADDR_TL,127);
|
rWrite(baseAddr+ADDR_TL,127);
|
||||||
} else {
|
} else {
|
||||||
if (isOutput[chan[i].state.alg][j]) {
|
if (KVS(i,j)) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
|
|
@ -438,7 +438,7 @@ void DivPlatformYM2610Ext::forceIns() {
|
||||||
if (i==1 && extMode) { // extended channel
|
if (i==1 && extMode) { // extended channel
|
||||||
if (isOpMuted[j]) {
|
if (isOpMuted[j]) {
|
||||||
rWrite(baseAddr+0x40,127);
|
rWrite(baseAddr+0x40,127);
|
||||||
} else if (isOutput[chan[i].state.alg][j]) {
|
} else if (KVS(i,j)) {
|
||||||
rWrite(baseAddr+0x40,127-VOL_SCALE_LOG(127-op.tl,opChan[j].vol&0x7f,127));
|
rWrite(baseAddr+0x40,127-VOL_SCALE_LOG(127-op.tl,opChan[j].vol&0x7f,127));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+0x40,op.tl);
|
rWrite(baseAddr+0x40,op.tl);
|
||||||
|
@ -447,7 +447,7 @@ void DivPlatformYM2610Ext::forceIns() {
|
||||||
if (isMuted[i]) {
|
if (isMuted[i]) {
|
||||||
rWrite(baseAddr+ADDR_TL,127);
|
rWrite(baseAddr+ADDR_TL,127);
|
||||||
} else {
|
} else {
|
||||||
if (isOutput[chan[i].state.alg][j]) {
|
if (KVS(i,j)) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG(127-op.tl,chan[i].outVol&0x7f,127));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
|
|
@ -382,7 +382,7 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
||||||
break;
|
break;
|
||||||
case 0xed: // delay
|
case 0xed: // delay
|
||||||
if (effectVal!=0) {
|
if (effectVal!=0) {
|
||||||
bool comparison=(song.delayBehavior==1)?(effectVal<=nextSpeed):(effectVal<nextSpeed);
|
bool comparison=(song.delayBehavior==1)?(effectVal<=nextSpeed):(effectVal<(nextSpeed*(curSubSong->timeBase+1)));
|
||||||
if (song.delayBehavior==2) comparison=true;
|
if (song.delayBehavior==2) comparison=true;
|
||||||
if (comparison) {
|
if (comparison) {
|
||||||
chan[i].rowDelay=effectVal+1;
|
chan[i].rowDelay=effectVal+1;
|
||||||
|
|
|
@ -511,6 +511,7 @@ struct DivSong {
|
||||||
bool e1e2StopOnSameNote;
|
bool e1e2StopOnSameNote;
|
||||||
bool brokenPortaArp;
|
bool brokenPortaArp;
|
||||||
bool snNoLowPeriods;
|
bool snNoLowPeriods;
|
||||||
|
bool autoSystem;
|
||||||
|
|
||||||
std::vector<DivInstrument*> ins;
|
std::vector<DivInstrument*> ins;
|
||||||
std::vector<DivWavetable*> wave;
|
std::vector<DivWavetable*> wave;
|
||||||
|
@ -614,7 +615,8 @@ struct DivSong {
|
||||||
brokenOutVol(false),
|
brokenOutVol(false),
|
||||||
e1e2StopOnSameNote(false),
|
e1e2StopOnSameNote(false),
|
||||||
brokenPortaArp(false),
|
brokenPortaArp(false),
|
||||||
snNoLowPeriods(false) {
|
snNoLowPeriods(false),
|
||||||
|
autoSystem(true) {
|
||||||
for (int i=0; i<32; i++) {
|
for (int i=0; i<32; i++) {
|
||||||
system[i]=DIV_SYSTEM_NULL;
|
system[i]=DIV_SYSTEM_NULL;
|
||||||
systemVol[i]=64;
|
systemVol[i]=64;
|
||||||
|
|
|
@ -23,16 +23,17 @@
|
||||||
|
|
||||||
const char* aboutLine[]={
|
const char* aboutLine[]={
|
||||||
"tildearrow",
|
"tildearrow",
|
||||||
"is proud to present",
|
"is not so happy to present",
|
||||||
"",
|
"",
|
||||||
("Furnace " DIV_VERSION),
|
("Furnace " DIV_VERSION),
|
||||||
"",
|
"",
|
||||||
"the biggest multi-system chiptune tracker!",
|
"the biggest multi-system chiptune tracker!",
|
||||||
"featuring DefleMask song compatibility.",
|
"featuring DefleMask song compatibility.",
|
||||||
"",
|
"",
|
||||||
"zero disassembly.",
|
"what a mess of a versioning scheme we have...",
|
||||||
"just clean-room design,",
|
"I mean it! these pre-releases are like normal releases",
|
||||||
"time and dedication.",
|
"by now but only because I promised you to have SNES in",
|
||||||
|
"0.6pre2 I am doing this whole mess...",
|
||||||
"",
|
"",
|
||||||
"> CREDITS <",
|
"> CREDITS <",
|
||||||
"",
|
"",
|
||||||
|
|
|
@ -63,12 +63,45 @@ float FurnaceGUI::computeGradPos(int type, int chan) {
|
||||||
return chanOscBright[chan];
|
return chanOscBright[chan];
|
||||||
break;
|
break;
|
||||||
case GUI_OSCREF_NOTE_TRIGGER:
|
case GUI_OSCREF_NOTE_TRIGGER:
|
||||||
return keyHit[chan]*5.0f;
|
return keyHit1[chan];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FurnaceGUI::calcChanOsc() {
|
||||||
|
std::vector<DivDispatchOscBuffer*> oscBufs;
|
||||||
|
std::vector<ChanOscStatus*> oscFFTs;
|
||||||
|
std::vector<int> oscChans;
|
||||||
|
|
||||||
|
int chans=e->getTotalChannelCount();
|
||||||
|
|
||||||
|
for (int i=0; i<chans; i++) {
|
||||||
|
DivDispatchOscBuffer* buf=e->getOscBuffer(i);
|
||||||
|
if (buf!=NULL && e->curSubSong->chanShow[i]) {
|
||||||
|
// 30ms should be enough
|
||||||
|
int displaySize=(float)(buf->rate)*0.03f;
|
||||||
|
if (e->isRunning()) {
|
||||||
|
float minLevel=1.0f;
|
||||||
|
float maxLevel=-1.0f;
|
||||||
|
unsigned short needlePos=buf->needle;
|
||||||
|
needlePos-=displaySize;
|
||||||
|
for (unsigned short i=0; i<512; i++) {
|
||||||
|
float y=(float)buf->data[(unsigned short)(needlePos+(i*displaySize/512))]/65536.0f;
|
||||||
|
if (minLevel>y) minLevel=y;
|
||||||
|
if (maxLevel<y) maxLevel=y;
|
||||||
|
}
|
||||||
|
float estimate=pow(maxLevel-minLevel,0.5f);
|
||||||
|
if (estimate>1.0f) estimate=1.0f;
|
||||||
|
chanOscVol[i]=MAX(chanOscVol[i]*0.87f,estimate);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
chanOscVol[i]=MAX(chanOscVol[i]*0.87f,0.0f);
|
||||||
|
}
|
||||||
|
if (chanOscVol[i]<0.00001f) chanOscVol[i]=0.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void FurnaceGUI::drawChanOsc() {
|
void FurnaceGUI::drawChanOsc() {
|
||||||
if (nextWindow==GUI_WINDOW_CHAN_OSC) {
|
if (nextWindow==GUI_WINDOW_CHAN_OSC) {
|
||||||
chanOscOpen=true;
|
chanOscOpen=true;
|
||||||
|
@ -361,7 +394,6 @@ void FurnaceGUI::drawChanOsc() {
|
||||||
if (maxLevel<y) maxLevel=y;
|
if (maxLevel<y) maxLevel=y;
|
||||||
}
|
}
|
||||||
dcOff=(minLevel+maxLevel)*0.5f;
|
dcOff=(minLevel+maxLevel)*0.5f;
|
||||||
chanOscVol[ch]=MAX(chanOscVol[ch]*0.87f,maxLevel-minLevel);
|
|
||||||
for (unsigned short i=0; i<512; i++) {
|
for (unsigned short i=0; i<512; i++) {
|
||||||
float x=(float)i/512.0f;
|
float x=(float)i/512.0f;
|
||||||
float y=(float)buf->data[(unsigned short)(needlePos+(i*displaySize/512))]/65536.0f;
|
float y=(float)buf->data[(unsigned short)(needlePos+(i*displaySize/512))]/65536.0f;
|
||||||
|
|
|
@ -645,6 +645,7 @@ void FurnaceGUI::doAction(int what) {
|
||||||
} else {
|
} else {
|
||||||
wantScrollList=true;
|
wantScrollList=true;
|
||||||
MARK_MODIFIED;
|
MARK_MODIFIED;
|
||||||
|
RESET_WAVE_MACRO_ZOOM;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GUI_ACTION_WAVE_LIST_DUPLICATE:
|
case GUI_ACTION_WAVE_LIST_DUPLICATE:
|
||||||
|
@ -657,6 +658,7 @@ void FurnaceGUI::doAction(int what) {
|
||||||
(*e->song.wave[curWave])=(*e->song.wave[prevWave]);
|
(*e->song.wave[curWave])=(*e->song.wave[prevWave]);
|
||||||
wantScrollList=true;
|
wantScrollList=true;
|
||||||
MARK_MODIFIED;
|
MARK_MODIFIED;
|
||||||
|
RESET_WAVE_MACRO_ZOOM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1329,6 +1331,7 @@ void FurnaceGUI::doAction(int what) {
|
||||||
}
|
}
|
||||||
nextWindow=GUI_WINDOW_WAVE_EDIT;
|
nextWindow=GUI_WINDOW_WAVE_EDIT;
|
||||||
MARK_MODIFIED;
|
MARK_MODIFIED;
|
||||||
|
RESET_WAVE_MACRO_ZOOM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -405,7 +405,7 @@ void FurnaceGUI::doCopy(bool cut) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FurnaceGUI::doPaste(PasteMode mode) {
|
void FurnaceGUI::doPaste(PasteMode mode, int arg) {
|
||||||
finishSelection();
|
finishSelection();
|
||||||
prepareUndo(GUI_UNDO_PATTERN_PASTE);
|
prepareUndo(GUI_UNDO_PATTERN_PASTE);
|
||||||
char* clipText=SDL_GetClipboardText();
|
char* clipText=SDL_GetClipboardText();
|
||||||
|
@ -481,14 +481,16 @@ void FurnaceGUI::doPaste(PasteMode mode) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((mode==GUI_PASTE_MODE_MIX_BG || mode==GUI_PASTE_MODE_MIX_FG) && strcmp(note,"...")==0) {
|
if ((mode==GUI_PASTE_MODE_MIX_BG || mode==GUI_PASTE_MODE_MIX_FG ||
|
||||||
|
mode==GUI_PASTE_MODE_INS_BG || mode==GUI_PASTE_MODE_INS_FG) && strcmp(note,"...")==0) {
|
||||||
// do nothing.
|
// do nothing.
|
||||||
} else {
|
} else {
|
||||||
if (mode!=GUI_PASTE_MODE_MIX_BG || (pat->data[j][0]==0 && pat->data[j][1]==0)) {
|
if (!(mode==GUI_PASTE_MODE_MIX_BG || mode==GUI_PASTE_MODE_INS_BG) || (pat->data[j][0]==0 && pat->data[j][1]==0)) {
|
||||||
if (!decodeNote(note,pat->data[j][0],pat->data[j][1])) {
|
if (!decodeNote(note,pat->data[j][0],pat->data[j][1])) {
|
||||||
invalidData=true;
|
invalidData=true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (mode==GUI_PASTE_MODE_INS_BG || mode==GUI_PASTE_MODE_INS_FG) pat->data[j][2]=arg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -505,7 +507,7 @@ void FurnaceGUI::doPaste(PasteMode mode) {
|
||||||
note[2]=0;
|
note[2]=0;
|
||||||
|
|
||||||
if (iFine==1) {
|
if (iFine==1) {
|
||||||
if (!opMaskPaste.ins) {
|
if (!opMaskPaste.ins || mode==GUI_PASTE_MODE_INS_BG || mode==GUI_PASTE_MODE_INS_FG) {
|
||||||
iFine++;
|
iFine++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -527,7 +529,8 @@ void FurnaceGUI::doPaste(PasteMode mode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(note,"..")==0) {
|
if (strcmp(note,"..")==0) {
|
||||||
if (!(mode==GUI_PASTE_MODE_MIX_BG || mode==GUI_PASTE_MODE_MIX_FG)) {
|
if (!(mode==GUI_PASTE_MODE_MIX_BG || mode==GUI_PASTE_MODE_MIX_FG ||
|
||||||
|
mode==GUI_PASTE_MODE_INS_BG || mode==GUI_PASTE_MODE_INS_FG)) {
|
||||||
pat->data[j][iFine+1]=-1;
|
pat->data[j][iFine+1]=-1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -536,7 +539,7 @@ void FurnaceGUI::doPaste(PasteMode mode) {
|
||||||
invalidData=true;
|
invalidData=true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (mode!=GUI_PASTE_MODE_MIX_BG || pat->data[j][iFine+1]==-1) {
|
if (!(mode==GUI_PASTE_MODE_MIX_BG || mode==GUI_PASTE_MODE_INS_BG) || pat->data[j][iFine+1]==-1) {
|
||||||
if (iFine<(3+e->curPat[iCoarse].effectCols*2)) pat->data[j][iFine+1]=val;
|
if (iFine<(3+e->curPat[iCoarse].effectCols*2)) pat->data[j][iFine+1]=val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
225
src/gui/gui.cpp
225
src/gui/gui.cpp
|
@ -584,13 +584,117 @@ void FurnaceGUI::updateWindowTitle() {
|
||||||
if (sdlWin!=NULL) SDL_SetWindowTitle(sdlWin,title.c_str());
|
if (sdlWin!=NULL) SDL_SetWindowTitle(sdlWin,title.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FurnaceGUI::autoDetectSystem() {
|
||||||
|
std::map<DivSystem,int> sysCountMap;
|
||||||
|
for (int i=0; i<e->song.systemLen; i++) {
|
||||||
|
try {
|
||||||
|
sysCountMap.at(e->song.system[i])++;
|
||||||
|
} catch (std::exception& ex) {
|
||||||
|
sysCountMap[e->song.system[i]]=1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
logV("sysCountMap:");
|
||||||
|
for (std::pair<DivSystem,int> k: sysCountMap) {
|
||||||
|
logV("%s: %d",e->getSystemName(k.first),k.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isMatch=false;
|
||||||
|
std::map<DivSystem,int> defCountMap;
|
||||||
|
for (FurnaceGUISysCategory& i: sysCategories) {
|
||||||
|
for (FurnaceGUISysDef& j: i.systems) {
|
||||||
|
defCountMap.clear();
|
||||||
|
for (size_t k=0; k<j.definition.size(); k+=4) {
|
||||||
|
if (j.definition[k]==0) break;
|
||||||
|
try {
|
||||||
|
defCountMap.at((DivSystem)j.definition[k])++;
|
||||||
|
} catch (std::exception& ex) {
|
||||||
|
defCountMap[(DivSystem)j.definition[k]]=1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (defCountMap.size()!=sysCountMap.size()) continue;
|
||||||
|
isMatch=true;
|
||||||
|
logV("trying on defCountMap: %s",j.name);
|
||||||
|
for (std::pair<DivSystem,int> k: defCountMap) {
|
||||||
|
logV("- %s: %d",e->getSystemName(k.first),k.second);
|
||||||
|
}
|
||||||
|
for (std::pair<DivSystem,int> k: defCountMap) {
|
||||||
|
try {
|
||||||
|
if (sysCountMap.at(k.first)!=k.second) {
|
||||||
|
isMatch=false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch (std::exception& ex) {
|
||||||
|
isMatch=false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isMatch) {
|
||||||
|
logV("match found!");
|
||||||
|
e->song.systemName=j.name;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isMatch) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isMatch) {
|
||||||
|
bool isFirst=true;
|
||||||
|
e->song.systemName="";
|
||||||
|
for (std::pair<DivSystem,int> k: sysCountMap) {
|
||||||
|
if (!isFirst) e->song.systemName+=" + ";
|
||||||
|
if (k.second>1) {
|
||||||
|
e->song.systemName+=fmt::sprintf("%d×",k.second);
|
||||||
|
}
|
||||||
|
if (k.first==DIV_SYSTEM_N163) {
|
||||||
|
e->song.systemName+=settings.c163Name;
|
||||||
|
} else {
|
||||||
|
e->song.systemName+=e->getSystemName(k.first);
|
||||||
|
}
|
||||||
|
isFirst=false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImVec4 FurnaceGUI::channelColor(int ch) {
|
||||||
|
switch (settings.channelColors) {
|
||||||
|
case 0:
|
||||||
|
return uiColors[GUI_COLOR_CHANNEL_BG];
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
return uiColors[GUI_COLOR_CHANNEL_FM+e->getChannelType(ch)];
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
return uiColors[GUI_COLOR_INSTR_STD+e->getPreferInsType(ch)];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// invalid
|
||||||
|
return uiColors[GUI_COLOR_TEXT];
|
||||||
|
}
|
||||||
|
|
||||||
|
ImVec4 FurnaceGUI::channelTextColor(int ch) {
|
||||||
|
switch (settings.channelTextColors) {
|
||||||
|
case 0:
|
||||||
|
return uiColors[GUI_COLOR_CHANNEL_FG];
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
return uiColors[GUI_COLOR_CHANNEL_FM+e->getChannelType(ch)];
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
return uiColors[GUI_COLOR_INSTR_STD+e->getPreferInsType(ch)];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// invalid
|
||||||
|
return uiColors[GUI_COLOR_TEXT];
|
||||||
|
}
|
||||||
|
|
||||||
const char* defaultLayout="[Window][DockSpaceViewport_11111111]\n\
|
const char* defaultLayout="[Window][DockSpaceViewport_11111111]\n\
|
||||||
Pos=0,24\n\
|
Pos=0,24\n\
|
||||||
Size=1280,731\n\
|
Size=1280,776\n\
|
||||||
Collapsed=0\n\
|
Collapsed=0\n\
|
||||||
\n\
|
\n\
|
||||||
[Window][Debug##Default]\n\
|
[Window][Debug##Default]\n\
|
||||||
Pos=54,0\n\
|
Pos=54,19\n\
|
||||||
Size=400,400\n\
|
Size=400,400\n\
|
||||||
Collapsed=0\n\
|
Collapsed=0\n\
|
||||||
\n\
|
\n\
|
||||||
|
@ -601,9 +705,9 @@ Collapsed=0\n\
|
||||||
\n\
|
\n\
|
||||||
[Window][Song Information]\n\
|
[Window][Song Information]\n\
|
||||||
Pos=978,24\n\
|
Pos=978,24\n\
|
||||||
Size=302,217\n\
|
Size=302,179\n\
|
||||||
Collapsed=0\n\
|
Collapsed=0\n\
|
||||||
DockId=0x00000004,0\n\
|
DockId=0x0000000F,0\n\
|
||||||
\n\
|
\n\
|
||||||
[Window][Orders]\n\
|
[Window][Orders]\n\
|
||||||
Pos=0,24\n\
|
Pos=0,24\n\
|
||||||
|
@ -615,7 +719,7 @@ DockId=0x00000007,0\n\
|
||||||
Pos=653,24\n\
|
Pos=653,24\n\
|
||||||
Size=323,217\n\
|
Size=323,217\n\
|
||||||
Collapsed=0\n\
|
Collapsed=0\n\
|
||||||
DockId=0x00000006,2\n\
|
DockId=0x00000006,0\n\
|
||||||
\n\
|
\n\
|
||||||
[Window][Wavetables]\n\
|
[Window][Wavetables]\n\
|
||||||
Pos=653,24\n\
|
Pos=653,24\n\
|
||||||
|
@ -627,13 +731,13 @@ DockId=0x00000006,1\n\
|
||||||
Pos=653,24\n\
|
Pos=653,24\n\
|
||||||
Size=323,217\n\
|
Size=323,217\n\
|
||||||
Collapsed=0\n\
|
Collapsed=0\n\
|
||||||
DockId=0x00000006,0\n\
|
DockId=0x00000006,2\n\
|
||||||
\n\
|
\n\
|
||||||
[Window][Pattern]\n\
|
[Window][Pattern]\n\
|
||||||
Pos=0,243\n\
|
Pos=0,243\n\
|
||||||
Size=1246,512\n\
|
Size=1246,557\n\
|
||||||
Collapsed=0\n\
|
Collapsed=0\n\
|
||||||
DockId=0x0000000B,0\n\
|
DockId=0x00000013,0\n\
|
||||||
\n\
|
\n\
|
||||||
[Window][Instrument Editor]\n\
|
[Window][Instrument Editor]\n\
|
||||||
Pos=372,102\n\
|
Pos=372,102\n\
|
||||||
|
@ -642,7 +746,7 @@ Collapsed=0\n\
|
||||||
\n\
|
\n\
|
||||||
[Window][Warning]\n\
|
[Window][Warning]\n\
|
||||||
Pos=481,338\n\
|
Pos=481,338\n\
|
||||||
Size=346,71\n\
|
Size=264,86\n\
|
||||||
Collapsed=0\n\
|
Collapsed=0\n\
|
||||||
\n\
|
\n\
|
||||||
[Window][Sample Editor]\n\
|
[Window][Sample Editor]\n\
|
||||||
|
@ -675,8 +779,8 @@ Size=514,71\n\
|
||||||
Collapsed=0\n\
|
Collapsed=0\n\
|
||||||
\n\
|
\n\
|
||||||
[Window][Mixer]\n\
|
[Window][Mixer]\n\
|
||||||
Pos=63,55\n\
|
Pos=429,198\n\
|
||||||
Size=450,215\n\
|
Size=453,355\n\
|
||||||
Collapsed=0\n\
|
Collapsed=0\n\
|
||||||
\n\
|
\n\
|
||||||
[Window][Oscilloscope]\n\
|
[Window][Oscilloscope]\n\
|
||||||
|
@ -687,7 +791,7 @@ DockId=0x0000000E,0\n\
|
||||||
\n\
|
\n\
|
||||||
[Window][Volume Meter]\n\
|
[Window][Volume Meter]\n\
|
||||||
Pos=1248,243\n\
|
Pos=1248,243\n\
|
||||||
Size=32,512\n\
|
Size=32,557\n\
|
||||||
Collapsed=0\n\
|
Collapsed=0\n\
|
||||||
DockId=0x0000000C,0\n\
|
DockId=0x0000000C,0\n\
|
||||||
\n\
|
\n\
|
||||||
|
@ -762,9 +866,10 @@ Size=368,449\n\
|
||||||
Collapsed=0\n\
|
Collapsed=0\n\
|
||||||
\n\
|
\n\
|
||||||
[Window][Register View]\n\
|
[Window][Register View]\n\
|
||||||
Pos=847,180\n\
|
Pos=829,243\n\
|
||||||
Size=417,393\n\
|
Size=417,557\n\
|
||||||
Collapsed=0\n\
|
Collapsed=0\n\
|
||||||
|
DockId=0x00000014,0\n\
|
||||||
\n\
|
\n\
|
||||||
[Window][New Song]\n\
|
[Window][New Song]\n\
|
||||||
Pos=267,110\n\
|
Pos=267,110\n\
|
||||||
|
@ -783,8 +888,40 @@ Size=304,40\n\
|
||||||
Collapsed=0\n\
|
Collapsed=0\n\
|
||||||
DockId=0x0000000A,0\n\
|
DockId=0x0000000A,0\n\
|
||||||
\n\
|
\n\
|
||||||
|
[Window][Subsongs]\n\
|
||||||
|
Pos=978,205\n\
|
||||||
|
Size=302,36\n\
|
||||||
|
Collapsed=0\n\
|
||||||
|
DockId=0x00000010,0\n\
|
||||||
|
\n\
|
||||||
|
[Window][Oscilloscope (per-channel)]\n\
|
||||||
|
Pos=1095,243\n\
|
||||||
|
Size=151,557\n\
|
||||||
|
Collapsed=0\n\
|
||||||
|
DockId=0x00000012,0\n\
|
||||||
|
\n\
|
||||||
|
[Window][Piano]\n\
|
||||||
|
Pos=177,669\n\
|
||||||
|
Size=922,118\n\
|
||||||
|
Collapsed=0\n\
|
||||||
|
\n\
|
||||||
|
[Window][Log Viewer]\n\
|
||||||
|
Pos=60,60\n\
|
||||||
|
Size=541,637\n\
|
||||||
|
Collapsed=0\n\
|
||||||
|
\n\
|
||||||
|
[Window][Pattern Manager]\n\
|
||||||
|
Pos=60,60\n\
|
||||||
|
Size=1099,366\n\
|
||||||
|
Collapsed=0\n\
|
||||||
|
\n\
|
||||||
|
[Window][Chip Manager]\n\
|
||||||
|
Pos=60,60\n\
|
||||||
|
Size=490,407\n\
|
||||||
|
Collapsed=0\n\
|
||||||
|
\n\
|
||||||
[Docking][Data]\n\
|
[Docking][Data]\n\
|
||||||
DockSpace ID=0x8B93E3BD Window=0xA787BDB4 Pos=0,24 Size=1280,731 Split=Y Selected=0x6C01C512\n\
|
DockSpace ID=0x8B93E3BD Window=0xA787BDB4 Pos=0,24 Size=1280,776 Split=Y Selected=0x6C01C512\n\
|
||||||
DockNode ID=0x00000001 Parent=0x8B93E3BD SizeRef=1280,217 Split=X Selected=0xF3094A52\n\
|
DockNode ID=0x00000001 Parent=0x8B93E3BD SizeRef=1280,217 Split=X Selected=0xF3094A52\n\
|
||||||
DockNode ID=0x00000003 Parent=0x00000001 SizeRef=976,231 Split=X Selected=0x65CC51DC\n\
|
DockNode ID=0x00000003 Parent=0x00000001 SizeRef=976,231 Split=X Selected=0x65CC51DC\n\
|
||||||
DockNode ID=0x00000007 Parent=0x00000003 SizeRef=345,231 HiddenTabBar=1 Selected=0x8F5BFC9A\n\
|
DockNode ID=0x00000007 Parent=0x00000003 SizeRef=345,231 HiddenTabBar=1 Selected=0x8F5BFC9A\n\
|
||||||
|
@ -795,10 +932,17 @@ DockSpace ID=0x8B93E3BD Window=0xA787BDB4 Pos=0,24 Size=1280,731 Spl
|
||||||
DockNode ID=0x0000000E Parent=0x00000009 SizeRef=292,105 HiddenTabBar=1 Selected=0x6D682373\n\
|
DockNode ID=0x0000000E Parent=0x00000009 SizeRef=292,105 HiddenTabBar=1 Selected=0x6D682373\n\
|
||||||
DockNode ID=0x0000000A Parent=0x00000005 SizeRef=292,40 HiddenTabBar=1 Selected=0x0DE44CFF\n\
|
DockNode ID=0x0000000A Parent=0x00000005 SizeRef=292,40 HiddenTabBar=1 Selected=0x0DE44CFF\n\
|
||||||
DockNode ID=0x00000006 Parent=0x00000008 SizeRef=323,406 Selected=0xD2AD486B\n\
|
DockNode ID=0x00000006 Parent=0x00000008 SizeRef=323,406 Selected=0xD2AD486B\n\
|
||||||
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=302,231 Selected=0x60B9D088\n\
|
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=302,231 Split=Y Selected=0x60B9D088\n\
|
||||||
|
DockNode ID=0x0000000F Parent=0x00000004 SizeRef=302,179 Selected=0x60B9D088\n\
|
||||||
|
DockNode ID=0x00000010 Parent=0x00000004 SizeRef=302,36 HiddenTabBar=1 Selected=0x723A6369\n\
|
||||||
DockNode ID=0x00000002 Parent=0x8B93E3BD SizeRef=1280,512 Split=X Selected=0x6C01C512\n\
|
DockNode ID=0x00000002 Parent=0x8B93E3BD SizeRef=1280,512 Split=X Selected=0x6C01C512\n\
|
||||||
DockNode ID=0x0000000B Parent=0x00000002 SizeRef=1246,503 CentralNode=1 HiddenTabBar=1 Selected=0xB9ADD0D5\n\
|
DockNode ID=0x0000000B Parent=0x00000002 SizeRef=1246,503 Split=X Selected=0xB9ADD0D5\n\
|
||||||
DockNode ID=0x0000000C Parent=0x00000002 SizeRef=32,503 HiddenTabBar=1 Selected=0x644DA2C1\n\n";
|
DockNode ID=0x00000011 Parent=0x0000000B SizeRef=1093,557 Split=X Selected=0xB9ADD0D5\n\
|
||||||
|
DockNode ID=0x00000013 Parent=0x00000011 SizeRef=827,557 CentralNode=1 HiddenTabBar=1 Selected=0xB9ADD0D5\n\
|
||||||
|
DockNode ID=0x00000014 Parent=0x00000011 SizeRef=417,557 Selected=0x425428FB\n\
|
||||||
|
DockNode ID=0x00000012 Parent=0x0000000B SizeRef=151,557 HiddenTabBar=1 Selected=0x4C07BC58\n\
|
||||||
|
DockNode ID=0x0000000C Parent=0x00000002 SizeRef=32,503 HiddenTabBar=1 Selected=0x644DA2C1\n";
|
||||||
|
|
||||||
|
|
||||||
void FurnaceGUI::prepareLayout() {
|
void FurnaceGUI::prepareLayout() {
|
||||||
FILE* check;
|
FILE* check;
|
||||||
|
@ -2076,6 +2220,30 @@ void FurnaceGUI::editOptions(bool topMenu) {
|
||||||
if (ImGui::BeginMenu("paste special...")) {
|
if (ImGui::BeginMenu("paste special...")) {
|
||||||
if (ImGui::MenuItem("paste mix",BIND_FOR(GUI_ACTION_PAT_PASTE_MIX))) doPaste(GUI_PASTE_MODE_MIX_FG);
|
if (ImGui::MenuItem("paste mix",BIND_FOR(GUI_ACTION_PAT_PASTE_MIX))) doPaste(GUI_PASTE_MODE_MIX_FG);
|
||||||
if (ImGui::MenuItem("paste mix (background)",BIND_FOR(GUI_ACTION_PAT_PASTE_MIX_BG))) doPaste(GUI_PASTE_MODE_MIX_BG);
|
if (ImGui::MenuItem("paste mix (background)",BIND_FOR(GUI_ACTION_PAT_PASTE_MIX_BG))) doPaste(GUI_PASTE_MODE_MIX_BG);
|
||||||
|
if (ImGui::BeginMenu("paste with ins (foreground)")) {
|
||||||
|
if (e->song.ins.empty()) {
|
||||||
|
ImGui::Text("no instruments available");
|
||||||
|
}
|
||||||
|
for (size_t i=0; i<e->song.ins.size(); i++) {
|
||||||
|
snprintf(id,4095,"%.2X: %s",(int)i,e->song.ins[i]->name.c_str());
|
||||||
|
if (ImGui::MenuItem(id)) {
|
||||||
|
doPaste(GUI_PASTE_MODE_INS_FG,i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::EndMenu();
|
||||||
|
}
|
||||||
|
if (ImGui::BeginMenu("paste with ins (background)")) {
|
||||||
|
if (e->song.ins.empty()) {
|
||||||
|
ImGui::Text("no instruments available");
|
||||||
|
}
|
||||||
|
for (size_t i=0; i<e->song.ins.size(); i++) {
|
||||||
|
snprintf(id,4095,"%.2X: %s",(int)i,e->song.ins[i]->name.c_str());
|
||||||
|
if (ImGui::MenuItem(id)) {
|
||||||
|
doPaste(GUI_PASTE_MODE_INS_BG,i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::EndMenu();
|
||||||
|
}
|
||||||
if (ImGui::MenuItem("paste flood",BIND_FOR(GUI_ACTION_PAT_PASTE_FLOOD))) doPaste(GUI_PASTE_MODE_FLOOD);
|
if (ImGui::MenuItem("paste flood",BIND_FOR(GUI_ACTION_PAT_PASTE_FLOOD))) doPaste(GUI_PASTE_MODE_FLOOD);
|
||||||
if (ImGui::MenuItem("paste overflow",BIND_FOR(GUI_ACTION_PAT_PASTE_OVERFLOW))) doPaste(GUI_PASTE_MODE_OVERFLOW);
|
if (ImGui::MenuItem("paste overflow",BIND_FOR(GUI_ACTION_PAT_PASTE_OVERFLOW))) doPaste(GUI_PASTE_MODE_OVERFLOW);
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
|
@ -3230,6 +3398,9 @@ bool FurnaceGUI::loop() {
|
||||||
showError("cannot add chip! ("+e->getLastError()+")");
|
showError("cannot add chip! ("+e->getLastError()+")");
|
||||||
}
|
}
|
||||||
ImGui::CloseCurrentPopup();
|
ImGui::CloseCurrentPopup();
|
||||||
|
if (e->song.autoSystem) {
|
||||||
|
autoDetectSystem();
|
||||||
|
}
|
||||||
updateWindowTitle();
|
updateWindowTitle();
|
||||||
}
|
}
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
|
@ -3250,6 +3421,9 @@ bool FurnaceGUI::loop() {
|
||||||
DivSystem picked=systemPicker();
|
DivSystem picked=systemPicker();
|
||||||
if (picked!=DIV_SYSTEM_NULL) {
|
if (picked!=DIV_SYSTEM_NULL) {
|
||||||
e->changeSystem(i,picked,preserveChanPos);
|
e->changeSystem(i,picked,preserveChanPos);
|
||||||
|
if (e->song.autoSystem) {
|
||||||
|
autoDetectSystem();
|
||||||
|
}
|
||||||
updateWindowTitle();
|
updateWindowTitle();
|
||||||
ImGui::CloseCurrentPopup();
|
ImGui::CloseCurrentPopup();
|
||||||
}
|
}
|
||||||
|
@ -3265,6 +3439,10 @@ bool FurnaceGUI::loop() {
|
||||||
if (!e->removeSystem(i,preserveChanPos)) {
|
if (!e->removeSystem(i,preserveChanPos)) {
|
||||||
showError("cannot remove chip! ("+e->getLastError()+")");
|
showError("cannot remove chip! ("+e->getLastError()+")");
|
||||||
}
|
}
|
||||||
|
if (e->song.autoSystem) {
|
||||||
|
autoDetectSystem();
|
||||||
|
updateWindowTitle();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
|
@ -3439,6 +3617,8 @@ bool FurnaceGUI::loop() {
|
||||||
ImGui::EndMainMenuBar();
|
ImGui::EndMainMenuBar();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
calcChanOsc();
|
||||||
|
|
||||||
if (mobileUI) {
|
if (mobileUI) {
|
||||||
globalWinFlags=ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoBringToFrontOnFocus;
|
globalWinFlags=ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoBringToFrontOnFocus;
|
||||||
//globalWinFlags=ImGuiWindowFlags_NoTitleBar;
|
//globalWinFlags=ImGuiWindowFlags_NoTitleBar;
|
||||||
|
@ -3884,6 +4064,7 @@ bool FurnaceGUI::loop() {
|
||||||
showError("cannot load wavetable! ("+e->getLastError()+")");
|
showError("cannot load wavetable! ("+e->getLastError()+")");
|
||||||
} else {
|
} else {
|
||||||
MARK_MODIFIED;
|
MARK_MODIFIED;
|
||||||
|
RESET_WAVE_MACRO_ZOOM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -4380,6 +4561,10 @@ bool FurnaceGUI::loop() {
|
||||||
case GUI_WARN_SYSTEM_DEL:
|
case GUI_WARN_SYSTEM_DEL:
|
||||||
if (ImGui::Button("Yes")) {
|
if (ImGui::Button("Yes")) {
|
||||||
e->removeSystem(sysToDelete,preserveChanPos);
|
e->removeSystem(sysToDelete,preserveChanPos);
|
||||||
|
if (e->song.autoSystem) {
|
||||||
|
autoDetectSystem();
|
||||||
|
updateWindowTitle();
|
||||||
|
}
|
||||||
ImGui::CloseCurrentPopup();
|
ImGui::CloseCurrentPopup();
|
||||||
}
|
}
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
@ -5034,6 +5219,7 @@ FurnaceGUI::FurnaceGUI():
|
||||||
macroPointSize(16),
|
macroPointSize(16),
|
||||||
waveEditStyle(0),
|
waveEditStyle(0),
|
||||||
mobileMenuPos(0.0f),
|
mobileMenuPos(0.0f),
|
||||||
|
autoButtonSize(0.0f),
|
||||||
curSysSection(NULL),
|
curSysSection(NULL),
|
||||||
pendingRawSampleDepth(8),
|
pendingRawSampleDepth(8),
|
||||||
pendingRawSampleChannels(1),
|
pendingRawSampleChannels(1),
|
||||||
|
@ -5421,6 +5607,9 @@ FurnaceGUI::FurnaceGUI():
|
||||||
waveGenFMCon2[0]=true;
|
waveGenFMCon2[0]=true;
|
||||||
waveGenFMCon3[0]=true;
|
waveGenFMCon3[0]=true;
|
||||||
|
|
||||||
|
memset(keyHit,0,sizeof(float)*DIV_MAX_CHANS);
|
||||||
|
memset(keyHit1,0,sizeof(float)*DIV_MAX_CHANS);
|
||||||
|
|
||||||
memset(pianoKeyHit,0,sizeof(float)*180);
|
memset(pianoKeyHit,0,sizeof(float)*180);
|
||||||
memset(pianoKeyPressed,0,sizeof(bool)*180);
|
memset(pianoKeyPressed,0,sizeof(bool)*180);
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,12 @@
|
||||||
#define MARK_MODIFIED modified=true;
|
#define MARK_MODIFIED modified=true;
|
||||||
#define WAKE_UP drawHalt=16;
|
#define WAKE_UP drawHalt=16;
|
||||||
|
|
||||||
|
#define RESET_WAVE_MACRO_ZOOM \
|
||||||
|
for (DivInstrument* _wi: e->song.ins) { \
|
||||||
|
_wi->std.waveMacro.vZoom=-1; \
|
||||||
|
_wi->std.waveMacro.vScroll=-1; \
|
||||||
|
}
|
||||||
|
|
||||||
#define BIND_FOR(x) getKeyName(actionKeys[x],true).c_str()
|
#define BIND_FOR(x) getKeyName(actionKeys[x],true).c_str()
|
||||||
|
|
||||||
// TODO:
|
// TODO:
|
||||||
|
@ -163,6 +169,8 @@ enum FurnaceGUIColors {
|
||||||
GUI_COLOR_INSTR_RF5C68,
|
GUI_COLOR_INSTR_RF5C68,
|
||||||
GUI_COLOR_INSTR_UNKNOWN,
|
GUI_COLOR_INSTR_UNKNOWN,
|
||||||
|
|
||||||
|
GUI_COLOR_CHANNEL_BG,
|
||||||
|
GUI_COLOR_CHANNEL_FG,
|
||||||
GUI_COLOR_CHANNEL_FM,
|
GUI_COLOR_CHANNEL_FM,
|
||||||
GUI_COLOR_CHANNEL_PULSE,
|
GUI_COLOR_CHANNEL_PULSE,
|
||||||
GUI_COLOR_CHANNEL_NOISE,
|
GUI_COLOR_CHANNEL_NOISE,
|
||||||
|
@ -596,7 +604,9 @@ enum PasteMode {
|
||||||
GUI_PASTE_MODE_MIX_FG,
|
GUI_PASTE_MODE_MIX_FG,
|
||||||
GUI_PASTE_MODE_MIX_BG,
|
GUI_PASTE_MODE_MIX_BG,
|
||||||
GUI_PASTE_MODE_FLOOD,
|
GUI_PASTE_MODE_FLOOD,
|
||||||
GUI_PASTE_MODE_OVERFLOW
|
GUI_PASTE_MODE_OVERFLOW,
|
||||||
|
GUI_PASTE_MODE_INS_FG,
|
||||||
|
GUI_PASTE_MODE_INS_BG
|
||||||
};
|
};
|
||||||
|
|
||||||
#define FURKMOD_CTRL (1U<<31)
|
#define FURKMOD_CTRL (1U<<31)
|
||||||
|
@ -1018,7 +1028,7 @@ class FurnaceGUI {
|
||||||
int drawHalt;
|
int drawHalt;
|
||||||
int macroPointSize;
|
int macroPointSize;
|
||||||
int waveEditStyle;
|
int waveEditStyle;
|
||||||
float mobileMenuPos;
|
float mobileMenuPos, autoButtonSize;
|
||||||
const int* curSysSection;
|
const int* curSysSection;
|
||||||
|
|
||||||
String pendingRawSample;
|
String pendingRawSample;
|
||||||
|
@ -1178,6 +1188,8 @@ class FurnaceGUI {
|
||||||
int channelStyle;
|
int channelStyle;
|
||||||
int channelVolStyle;
|
int channelVolStyle;
|
||||||
int channelFeedbackStyle;
|
int channelFeedbackStyle;
|
||||||
|
int channelFont;
|
||||||
|
int channelTextCenter;
|
||||||
int maxRecentFile;
|
int maxRecentFile;
|
||||||
unsigned int maxUndoSteps;
|
unsigned int maxUndoSteps;
|
||||||
String mainFontPath;
|
String mainFontPath;
|
||||||
|
@ -1296,9 +1308,11 @@ class FurnaceGUI {
|
||||||
saveUnusedPatterns(0),
|
saveUnusedPatterns(0),
|
||||||
channelColors(1),
|
channelColors(1),
|
||||||
channelTextColors(0),
|
channelTextColors(0),
|
||||||
channelStyle(0),
|
channelStyle(1),
|
||||||
channelVolStyle(0),
|
channelVolStyle(0),
|
||||||
channelFeedbackStyle(1),
|
channelFeedbackStyle(1),
|
||||||
|
channelFont(1),
|
||||||
|
channelTextCenter(1),
|
||||||
maxRecentFile(10),
|
maxRecentFile(10),
|
||||||
maxUndoSteps(100),
|
maxUndoSteps(100),
|
||||||
mainFontPath(""),
|
mainFontPath(""),
|
||||||
|
@ -1556,6 +1570,7 @@ class FurnaceGUI {
|
||||||
|
|
||||||
// visualizer
|
// visualizer
|
||||||
float keyHit[DIV_MAX_CHANS];
|
float keyHit[DIV_MAX_CHANS];
|
||||||
|
float keyHit1[DIV_MAX_CHANS];
|
||||||
int lastIns[DIV_MAX_CHANS];
|
int lastIns[DIV_MAX_CHANS];
|
||||||
|
|
||||||
// log window
|
// log window
|
||||||
|
@ -1596,6 +1611,7 @@ class FurnaceGUI {
|
||||||
void drawFMEnv(unsigned char tl, unsigned char ar, unsigned char dr, unsigned char d2r, unsigned char rr, unsigned char sl, unsigned char sus, unsigned char egt, unsigned char algOrGlobalSus, float maxTl, float maxArDr, const ImVec2& size, unsigned short instType);
|
void drawFMEnv(unsigned char tl, unsigned char ar, unsigned char dr, unsigned char d2r, unsigned char rr, unsigned char sl, unsigned char sus, unsigned char egt, unsigned char algOrGlobalSus, float maxTl, float maxArDr, const ImVec2& size, unsigned short instType);
|
||||||
void drawGBEnv(unsigned char vol, unsigned char len, unsigned char sLen, bool dir, const ImVec2& size);
|
void drawGBEnv(unsigned char vol, unsigned char len, unsigned char sLen, bool dir, const ImVec2& size);
|
||||||
void drawSysConf(int chan, DivSystem type, unsigned int& flags, bool modifyOnChange);
|
void drawSysConf(int chan, DivSystem type, unsigned int& flags, bool modifyOnChange);
|
||||||
|
void kvsConfig(DivInstrument* ins);
|
||||||
|
|
||||||
// these ones offer ctrl-wheel fine value changes.
|
// these ones offer ctrl-wheel fine value changes.
|
||||||
bool CWSliderScalar(const char* label, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, const char* format=NULL, ImGuiSliderFlags flags=0);
|
bool CWSliderScalar(const char* label, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, const char* format=NULL, ImGuiSliderFlags flags=0);
|
||||||
|
@ -1605,9 +1621,13 @@ class FurnaceGUI {
|
||||||
bool CWVSliderInt(const char* label, const ImVec2& size, int* v, int v_min, int v_max, const char* format="%d", ImGuiSliderFlags flags=0);
|
bool CWVSliderInt(const char* label, const ImVec2& size, int* v, int v_min, int v_max, const char* format="%d", ImGuiSliderFlags flags=0);
|
||||||
|
|
||||||
void updateWindowTitle();
|
void updateWindowTitle();
|
||||||
|
void autoDetectSystem();
|
||||||
void prepareLayout();
|
void prepareLayout();
|
||||||
|
ImVec4 channelColor(int ch);
|
||||||
|
ImVec4 channelTextColor(int ch);
|
||||||
|
|
||||||
void readOsc();
|
void readOsc();
|
||||||
|
void calcChanOsc();
|
||||||
|
|
||||||
void pushAccentColors(const ImVec4& one, const ImVec4& two, const ImVec4& border, const ImVec4& borderShadow);
|
void pushAccentColors(const ImVec4& one, const ImVec4& two, const ImVec4& border, const ImVec4& borderShadow);
|
||||||
void popAccentColors();
|
void popAccentColors();
|
||||||
|
@ -1699,7 +1719,7 @@ class FurnaceGUI {
|
||||||
void doInsert();
|
void doInsert();
|
||||||
void doTranspose(int amount, OperationMask& mask);
|
void doTranspose(int amount, OperationMask& mask);
|
||||||
void doCopy(bool cut);
|
void doCopy(bool cut);
|
||||||
void doPaste(PasteMode mode=GUI_PASTE_MODE_NORMAL);
|
void doPaste(PasteMode mode=GUI_PASTE_MODE_NORMAL, int arg=0);
|
||||||
void doChangeIns(int ins);
|
void doChangeIns(int ins);
|
||||||
void doInterpolate();
|
void doInterpolate();
|
||||||
void doFade(int p0, int p1, bool mode);
|
void doFade(int p0, int p1, bool mode);
|
||||||
|
|
|
@ -796,6 +796,8 @@ const FurnaceGUIColorDef guiColors[GUI_COLOR_MAX]={
|
||||||
D(GUI_COLOR_INSTR_RF5C68,"",ImVec4(1.0f,0.5f,0.5f,1.0f)),
|
D(GUI_COLOR_INSTR_RF5C68,"",ImVec4(1.0f,0.5f,0.5f,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_BG,"",ImVec4(0.4f,0.6f,0.8f,1.0f)),
|
||||||
|
D(GUI_COLOR_CHANNEL_FG,"",ImVec4(1.0f,1.0f,1.0f,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)),
|
||||||
D(GUI_COLOR_CHANNEL_PULSE,"",ImVec4(0.4f,1.0f,0.2f,1.0f)),
|
D(GUI_COLOR_CHANNEL_PULSE,"",ImVec4(0.4f,1.0f,0.2f,1.0f)),
|
||||||
D(GUI_COLOR_CHANNEL_NOISE,"",ImVec4(0.8f,0.8f,0.8f,1.0f)),
|
D(GUI_COLOR_CHANNEL_NOISE,"",ImVec4(0.8f,0.8f,0.8f,1.0f)),
|
||||||
|
|
|
@ -1211,6 +1211,46 @@ inline bool enBit30(const int val) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FurnaceGUI::kvsConfig(DivInstrument* ins) {
|
||||||
|
if (ImGui::IsItemHovered()) {
|
||||||
|
ImGui::SetTooltip("(click to configure KVS)");
|
||||||
|
}
|
||||||
|
int opCount=4;
|
||||||
|
if (ins->type==DIV_INS_OPLL) opCount=2;
|
||||||
|
if (ins->type==DIV_INS_OPL) opCount=(ins->fm.ops==4)?4:2;
|
||||||
|
if (ImGui::BeginPopupContextItem("IKVSOpt",ImGuiPopupFlags_MouseButtonLeft)) {
|
||||||
|
ImGui::Text("operator level changes with volume?");
|
||||||
|
if (ImGui::BeginTable("KVSTable",4,ImGuiTableFlags_BordersInner)) {
|
||||||
|
ImGui::TableSetupColumn("c0",ImGuiTableColumnFlags_WidthFixed);
|
||||||
|
ImGui::TableSetupColumn("c1",ImGuiTableColumnFlags_WidthStretch);
|
||||||
|
ImGui::TableSetupColumn("c2",ImGuiTableColumnFlags_WidthFixed);
|
||||||
|
ImGui::TableSetupColumn("c3",ImGuiTableColumnFlags_WidthStretch);
|
||||||
|
for (int i=0; i<4; i++) {
|
||||||
|
int o=(opCount==4)?orderedOps[i]:i;
|
||||||
|
if (!(i&1)) ImGui::TableNextRow();
|
||||||
|
const char* label="AUTO##OPKVS";
|
||||||
|
if (ins->fm.op[o].kvs==0) {
|
||||||
|
label="NO##OPKVS";
|
||||||
|
} else if (ins->fm.op[o].kvs==1) {
|
||||||
|
label="YES##OPKVS";
|
||||||
|
}
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::Text("%d",i+1);
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::PushID(o);
|
||||||
|
if (ImGui::Button(label,ImVec2(ImGui::GetContentRegionAvail().x,0.0f))) {
|
||||||
|
if (++ins->fm.op[o].kvs>2) ins->fm.op[o].kvs=0;
|
||||||
|
PARAMETER;
|
||||||
|
}
|
||||||
|
ImGui::PopID();
|
||||||
|
}
|
||||||
|
ImGui::EndTable();
|
||||||
|
}
|
||||||
|
ImGui::EndPopup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void FurnaceGUI::drawMacros(std::vector<FurnaceGUIMacroDesc>& macros) {
|
void FurnaceGUI::drawMacros(std::vector<FurnaceGUIMacroDesc>& macros) {
|
||||||
float asFloat[256];
|
float asFloat[256];
|
||||||
int asInt[256];
|
int asInt[256];
|
||||||
|
@ -1769,6 +1809,7 @@ void FurnaceGUI::drawInsEdit() {
|
||||||
P(CWSliderScalar(FM_NAME(FM_AMS),ImGuiDataType_U8,&ins->fm.ams,&_ZERO,&_THREE)); rightClickable
|
P(CWSliderScalar(FM_NAME(FM_AMS),ImGuiDataType_U8,&ins->fm.ams,&_ZERO,&_THREE)); rightClickable
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
drawAlgorithm(ins->fm.alg,FM_ALGS_4OP,ImVec2(ImGui::GetContentRegionAvail().x,48.0*dpiScale));
|
drawAlgorithm(ins->fm.alg,FM_ALGS_4OP,ImVec2(ImGui::GetContentRegionAvail().x,48.0*dpiScale));
|
||||||
|
kvsConfig(ins);
|
||||||
break;
|
break;
|
||||||
case DIV_INS_OPZ:
|
case DIV_INS_OPZ:
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
|
@ -1781,6 +1822,8 @@ void FurnaceGUI::drawInsEdit() {
|
||||||
P(CWSliderScalar(FM_NAME(FM_AMS2),ImGuiDataType_U8,&ins->fm.ams2,&_ZERO,&_THREE)); rightClickable
|
P(CWSliderScalar(FM_NAME(FM_AMS2),ImGuiDataType_U8,&ins->fm.ams2,&_ZERO,&_THREE)); rightClickable
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
drawAlgorithm(ins->fm.alg,FM_ALGS_4OP,ImVec2(ImGui::GetContentRegionAvail().x,48.0*dpiScale));
|
drawAlgorithm(ins->fm.alg,FM_ALGS_4OP,ImVec2(ImGui::GetContentRegionAvail().x,48.0*dpiScale));
|
||||||
|
kvsConfig(ins);
|
||||||
|
|
||||||
if (ImGui::Button("Request from TX81Z")) {
|
if (ImGui::Button("Request from TX81Z")) {
|
||||||
doAction(GUI_ACTION_TX81Z_REQUEST);
|
doAction(GUI_ACTION_TX81Z_REQUEST);
|
||||||
}
|
}
|
||||||
|
@ -1813,6 +1856,7 @@ void FurnaceGUI::drawInsEdit() {
|
||||||
}
|
}
|
||||||
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));
|
||||||
|
kvsConfig(ins);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DIV_INS_OPLL: {
|
case DIV_INS_OPLL: {
|
||||||
|
@ -1837,6 +1881,7 @@ void FurnaceGUI::drawInsEdit() {
|
||||||
ImGui::EndDisabled();
|
ImGui::EndDisabled();
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
drawAlgorithm(0,FM_ALGS_2OP_OPL,ImVec2(ImGui::GetContentRegionAvail().x,24.0*dpiScale));
|
drawAlgorithm(0,FM_ALGS_2OP_OPL,ImVec2(ImGui::GetContentRegionAvail().x,24.0*dpiScale));
|
||||||
|
|
||||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||||
|
|
||||||
bool isPresent[4];
|
bool isPresent[4];
|
||||||
|
@ -2928,6 +2973,14 @@ void FurnaceGUI::drawInsEdit() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ins->type==DIV_INS_OPZ) {
|
||||||
|
ImGui::SameLine();
|
||||||
|
bool fixedOn=op.egt;
|
||||||
|
if (ImGui::Checkbox("Fixed",&fixedOn)) { PARAMETER
|
||||||
|
op.egt=fixedOn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//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_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);
|
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
|
||||||
|
@ -3012,23 +3065,85 @@ void FurnaceGUI::drawInsEdit() {
|
||||||
ImGui::Text("%s",FM_NAME(FM_KSL));
|
ImGui::Text("%s",FM_NAME(FM_KSL));
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::TableNextRow();
|
if (ins->type==DIV_INS_OPZ) {
|
||||||
ImGui::TableNextColumn();
|
|
||||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
|
||||||
P(CWSliderScalar(FM_NAME(FM_MULT),ImGuiDataType_U8,&op.mult,&_ZERO,&_FIFTEEN)); rightClickable
|
|
||||||
ImGui::TableNextColumn();
|
|
||||||
ImGui::Text("%s",FM_NAME(FM_MULT));
|
|
||||||
|
|
||||||
if (ins->type==DIV_INS_FM || ins->type==DIV_INS_OPZ) {
|
|
||||||
int detune=(op.dt&7)-(settings.unsignedDetune?0:3);
|
|
||||||
ImGui::TableNextRow();
|
ImGui::TableNextRow();
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||||
if (CWSliderInt("##DT",&detune,-3,4)) { PARAMETER
|
P(CWSliderScalar(FM_NAME(FM_EGSHIFT),ImGuiDataType_U8,&op.ksl,&_ZERO,&_THREE)); rightClickable
|
||||||
op.dt=detune+(settings.unsignedDetune?0:3);
|
|
||||||
} rightClickable
|
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
ImGui::Text("%s",FM_NAME(FM_DT));
|
ImGui::Text("%s",FM_NAME(FM_EGSHIFT));
|
||||||
|
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||||
|
P(CWSliderScalar(FM_NAME(FM_REV),ImGuiDataType_U8,&op.dam,&_ZERO,&_SEVEN)); rightClickable
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::Text("%s",FM_NAME(FM_REV));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ins->type==DIV_INS_OPZ) {
|
||||||
|
if (op.egt) {
|
||||||
|
int block=op.dt;
|
||||||
|
int freqNum=(op.mult<<4)|(op.dvb&15);
|
||||||
|
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||||
|
if (CWSliderInt(FM_NAME(FM_MULT),&block,0,7)) { PARAMETER
|
||||||
|
if (block<0) block=0;
|
||||||
|
if (block>7) block=7;
|
||||||
|
op.dt=block;
|
||||||
|
} rightClickable
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::Text("Block");
|
||||||
|
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||||
|
if (CWSliderInt(FM_NAME(FM_FINE),&freqNum,0,255)) { PARAMETER
|
||||||
|
if (freqNum<0) freqNum=0;
|
||||||
|
if (freqNum>255) freqNum=255;
|
||||||
|
op.mult=freqNum>>4;
|
||||||
|
op.dvb=freqNum&15;
|
||||||
|
} rightClickable
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::Text("FreqNum");
|
||||||
|
} else {
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||||
|
P(CWSliderScalar(FM_NAME(FM_MULT),ImGuiDataType_U8,&op.mult,&_ZERO,&_FIFTEEN)); rightClickable
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::Text("%s",FM_NAME(FM_MULT));
|
||||||
|
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||||
|
P(CWSliderScalar(FM_NAME(FM_FINE),ImGuiDataType_U8,&op.dvb,&_ZERO,&_FIFTEEN)); rightClickable
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::Text("%s",FM_NAME(FM_FINE));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||||
|
P(CWSliderScalar(FM_NAME(FM_MULT),ImGuiDataType_U8,&op.mult,&_ZERO,&_FIFTEEN)); rightClickable
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::Text("%s",FM_NAME(FM_MULT));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ins->type==DIV_INS_FM || ins->type==DIV_INS_OPZ) {
|
||||||
|
if (!(ins->type==DIV_INS_OPZ && op.egt)) {
|
||||||
|
int detune=(op.dt&7)-(settings.unsignedDetune?0:3);
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||||
|
if (CWSliderInt("##DT",&detune,-3,4)) { PARAMETER
|
||||||
|
op.dt=detune+(settings.unsignedDetune?0:3);
|
||||||
|
} rightClickable
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::Text("%s",FM_NAME(FM_DT));
|
||||||
|
}
|
||||||
|
|
||||||
ImGui::TableNextRow();
|
ImGui::TableNextRow();
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
|
@ -4277,7 +4392,7 @@ void FurnaceGUI::drawInsEdit() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* waveLabel="Waveform";
|
const char* waveLabel="Waveform";
|
||||||
int waveMax=(ins->type==DIV_INS_VERA)?3:255;
|
int waveMax=(ins->type==DIV_INS_VERA)?3:(MAX(1,e->song.waveLen-1));
|
||||||
bool waveBitMode=false;
|
bool waveBitMode=false;
|
||||||
if (ins->type==DIV_INS_C64 || ins->type==DIV_INS_SAA1099) {
|
if (ins->type==DIV_INS_C64 || ins->type==DIV_INS_SAA1099) {
|
||||||
waveBitMode=true;
|
waveBitMode=true;
|
||||||
|
@ -4295,7 +4410,7 @@ void FurnaceGUI::drawInsEdit() {
|
||||||
waveBitMode=true;
|
waveBitMode=true;
|
||||||
}
|
}
|
||||||
if (ins->type==DIV_INS_VRC6) {
|
if (ins->type==DIV_INS_VRC6) {
|
||||||
waveMax=ins->amiga.useSample?255:0;
|
waveMax=ins->amiga.useSample?(MAX(1,e->song.waveLen-1)):0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ins->type==DIV_INS_OPLL) {
|
if (ins->type==DIV_INS_OPLL) {
|
||||||
|
@ -4303,7 +4418,7 @@ void FurnaceGUI::drawInsEdit() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ins->type==DIV_INS_AY || ins->type==DIV_INS_AY8930) {
|
if (ins->type==DIV_INS_AY || ins->type==DIV_INS_AY8930) {
|
||||||
waveMax=ins->amiga.useSample?255:3;
|
waveMax=ins->amiga.useSample?(MAX(1,e->song.waveLen-1)):3;
|
||||||
waveBitMode=ins->amiga.useSample?false:true;
|
waveBitMode=ins->amiga.useSample?false:true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// for suck's fake Clang extension!
|
||||||
|
#include <imgui.h>
|
||||||
#define _USE_MATH_DEFINES
|
#define _USE_MATH_DEFINES
|
||||||
#include "gui.h"
|
#include "gui.h"
|
||||||
#include "../ta-log.h"
|
#include "../ta-log.h"
|
||||||
|
@ -24,6 +26,7 @@
|
||||||
#include "IconsFontAwesome4.h"
|
#include "IconsFontAwesome4.h"
|
||||||
#include "misc/cpp/imgui_stdlib.h"
|
#include "misc/cpp/imgui_stdlib.h"
|
||||||
#include "guiConst.h"
|
#include "guiConst.h"
|
||||||
|
#include "../utfutils.h"
|
||||||
#include <fmt/printf.h>
|
#include <fmt/printf.h>
|
||||||
|
|
||||||
inline float randRange(float min, float max) {
|
inline float randRange(float min, float max) {
|
||||||
|
@ -400,7 +403,7 @@ void FurnaceGUI::drawPattern() {
|
||||||
ImGui::PushStyleColor(ImGuiCol_Header,uiColors[GUI_COLOR_PATTERN_SELECTION]);
|
ImGui::PushStyleColor(ImGuiCol_Header,uiColors[GUI_COLOR_PATTERN_SELECTION]);
|
||||||
ImGui::PushStyleColor(ImGuiCol_HeaderHovered,uiColors[GUI_COLOR_PATTERN_SELECTION_HOVER]);
|
ImGui::PushStyleColor(ImGuiCol_HeaderHovered,uiColors[GUI_COLOR_PATTERN_SELECTION_HOVER]);
|
||||||
ImGui::PushStyleColor(ImGuiCol_HeaderActive,uiColors[GUI_COLOR_PATTERN_SELECTION_ACTIVE]);
|
ImGui::PushStyleColor(ImGuiCol_HeaderActive,uiColors[GUI_COLOR_PATTERN_SELECTION_ACTIVE]);
|
||||||
if (ImGui::BeginTable("PatternView",displayChans+2,ImGuiTableFlags_BordersInnerV|ImGuiTableFlags_ScrollX|ImGuiTableFlags_ScrollY|ImGuiTableFlags_NoPadInnerX)) {
|
if (ImGui::BeginTable("PatternView",displayChans+2,ImGuiTableFlags_BordersInnerV|ImGuiTableFlags_ScrollX|ImGuiTableFlags_ScrollY|ImGuiTableFlags_NoPadInnerX|ImGuiTableFlags_NoBordersInFrozenArea)) {
|
||||||
ImGui::TableSetupColumn("pos",ImGuiTableColumnFlags_WidthFixed);
|
ImGui::TableSetupColumn("pos",ImGuiTableColumnFlags_WidthFixed);
|
||||||
char chanID[2048];
|
char chanID[2048];
|
||||||
float lineHeight=(ImGui::GetTextLineHeight()+2*dpiScale);
|
float lineHeight=(ImGui::GetTextLineHeight()+2*dpiScale);
|
||||||
|
@ -447,41 +450,46 @@ void FurnaceGUI::drawPattern() {
|
||||||
if (!e->curSubSong->chanShow[i]) continue;
|
if (!e->curSubSong->chanShow[i]) continue;
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
bool displayTooltip=false;
|
bool displayTooltip=false;
|
||||||
if (e->curSubSong->chanCollapse[i]) {
|
|
||||||
const char* chName=e->getChannelShortName(i);
|
|
||||||
if (strlen(chName)>3) {
|
|
||||||
snprintf(chanID,2048,"...##_CH%d",i);
|
|
||||||
} else {
|
|
||||||
snprintf(chanID,2048,"%s##_CH%d",chName,i);
|
|
||||||
}
|
|
||||||
displayTooltip=true;
|
|
||||||
} else {
|
|
||||||
const char* chName=e->getChannelName(i);
|
|
||||||
size_t chNameLimit=6+4*e->curPat[i].effectCols;
|
|
||||||
if (strlen(chName)>chNameLimit) {
|
|
||||||
String shortChName=chName;
|
|
||||||
shortChName.resize(chNameLimit-3);
|
|
||||||
shortChName+="...";
|
|
||||||
snprintf(chanID,2048," %s##_CH%d",shortChName.c_str(),i);
|
|
||||||
displayTooltip=true;
|
|
||||||
} else {
|
|
||||||
snprintf(chanID,2048," %s##_CH%d",chName,i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bool muted=e->isChannelMuted(i);
|
bool muted=e->isChannelMuted(i);
|
||||||
ImVec4 chanHead=muted?uiColors[GUI_COLOR_CHANNEL_MUTED]:uiColors[GUI_COLOR_CHANNEL_FM+e->getChannelType(i)];
|
ImVec4 chanHead=muted?uiColors[GUI_COLOR_CHANNEL_MUTED]:channelColor(i);
|
||||||
ImVec4 chanHeadActive=chanHead;
|
ImVec4 chanHeadActive=chanHead;
|
||||||
ImVec4 chanHeadHover=chanHead;
|
ImVec4 chanHeadHover=chanHead;
|
||||||
|
ImVec4 chanHeadBase=chanHead;
|
||||||
|
|
||||||
if (e->keyHit[i]) {
|
if (e->keyHit[i]) {
|
||||||
keyHit[i]=0.2;
|
keyHit1[i]=1.0f;
|
||||||
if (!muted) {
|
if (settings.channelFeedbackStyle==1) {
|
||||||
int note=e->getChanState(i)->note+60;
|
keyHit[i]=0.2;
|
||||||
if (note>=0 && note<180) {
|
if (!muted) {
|
||||||
pianoKeyHit[note]=1.0;
|
int note=e->getChanState(i)->note+60;
|
||||||
|
if (note>=0 && note<180) {
|
||||||
|
pianoKeyHit[note]=1.0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
e->keyHit[i]=false;
|
e->keyHit[i]=false;
|
||||||
}
|
}
|
||||||
|
if (settings.channelFeedbackStyle==2 && e->isRunning()) {
|
||||||
|
float amount=((float)(e->getChanState(i)->volume>>8)/(float)e->getMaxVolumeChan(i));
|
||||||
|
if (!e->getChanState(i)->keyOn) amount=0.0f;
|
||||||
|
keyHit[i]=amount*0.2f;
|
||||||
|
if (!muted) {
|
||||||
|
int note=e->getChanState(i)->note+60;
|
||||||
|
if (note>=0 && note<180) {
|
||||||
|
pianoKeyHit[note]=amount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (settings.channelFeedbackStyle==3 && e->isRunning()) {
|
||||||
|
bool active=e->getChanState(i)->keyOn;
|
||||||
|
keyHit[i]=active?0.2f:0.0f;
|
||||||
|
if (!muted) {
|
||||||
|
int note=e->getChanState(i)->note+60;
|
||||||
|
if (note>=0 && note<180) {
|
||||||
|
pianoKeyHit[note]=active?1.0f:0.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (settings.guiColorsBase) {
|
if (settings.guiColorsBase) {
|
||||||
chanHead.x*=1.0-keyHit[i]; chanHead.y*=1.0-keyHit[i]; chanHead.z*=1.0-keyHit[i];
|
chanHead.x*=1.0-keyHit[i]; chanHead.y*=1.0-keyHit[i]; chanHead.z*=1.0-keyHit[i];
|
||||||
chanHeadActive.x*=0.5; chanHeadActive.y*=0.5; chanHeadActive.z*=0.5;
|
chanHeadActive.x*=0.5; chanHeadActive.y*=0.5; chanHeadActive.z*=0.5;
|
||||||
|
@ -491,17 +499,210 @@ void FurnaceGUI::drawPattern() {
|
||||||
chanHeadActive.x*=0.8; chanHeadActive.y*=0.8; chanHeadActive.z*=0.8;
|
chanHeadActive.x*=0.8; chanHeadActive.y*=0.8; chanHeadActive.z*=0.8;
|
||||||
chanHeadHover.x*=0.4+keyHit[i]; chanHeadHover.y*=0.4+keyHit[i]; chanHeadHover.z*=0.4+keyHit[i];
|
chanHeadHover.x*=0.4+keyHit[i]; chanHeadHover.y*=0.4+keyHit[i]; chanHeadHover.z*=0.4+keyHit[i];
|
||||||
}
|
}
|
||||||
keyHit[i]-=0.02*60.0*ImGui::GetIO().DeltaTime;
|
keyHit[i]-=((settings.channelStyle==0)?0.02:0.01)*60.0*ImGui::GetIO().DeltaTime;
|
||||||
if (keyHit[i]<0) keyHit[i]=0;
|
if (keyHit[i]<0) keyHit[i]=0;
|
||||||
ImGui::PushStyleColor(ImGuiCol_Header,chanHead);
|
ImGui::PushStyleColor(ImGuiCol_Header,chanHead);
|
||||||
ImGui::PushStyleColor(ImGuiCol_HeaderActive,chanHeadActive);
|
ImGui::PushStyleColor(ImGuiCol_HeaderActive,chanHeadActive);
|
||||||
ImGui::PushStyleColor(ImGuiCol_HeaderHovered,chanHeadHover);
|
ImGui::PushStyleColor(ImGuiCol_HeaderHovered,chanHeadHover);
|
||||||
ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg,ImGui::GetColorU32(chanHead));
|
ImGui::PushStyleColor(ImGuiCol_Text,ImGui::GetColorU32(channelTextColor(i)));
|
||||||
|
if (settings.channelStyle==0) ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg,ImGui::GetColorU32(chanHead));
|
||||||
if (muted) ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_CHANNEL_MUTED]);
|
if (muted) ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_CHANNEL_MUTED]);
|
||||||
ImGui::Selectable(chanID,true,ImGuiSelectableFlags_NoPadWithHalfSpacing,ImVec2(0.0f,lineHeight+1.0f*dpiScale));
|
if (settings.channelFont==0) ImGui::PushFont(mainFont);
|
||||||
|
|
||||||
|
// TODO: appearance
|
||||||
|
ImGuiWindow* window=ImGui::GetCurrentWindow();
|
||||||
|
ImVec2 size=ImVec2(
|
||||||
|
1.0f,
|
||||||
|
lineHeight+1.0f*dpiScale
|
||||||
|
);
|
||||||
|
ImDrawList* dl=ImGui::GetWindowDrawList();
|
||||||
|
|
||||||
|
if (settings.channelStyle!=0) {
|
||||||
|
size.y+=6.0f*dpiScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (settings.channelStyle==2) {
|
||||||
|
size.y+=6.0f*dpiScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImVec2 minArea=window->DC.CursorPos;
|
||||||
|
ImVec2 maxArea=ImVec2(
|
||||||
|
minArea.x+window->WorkRect.Max.x-window->WorkRect.Min.x,
|
||||||
|
minArea.y+size.y
|
||||||
|
);
|
||||||
|
ImRect rect=ImRect(minArea,maxArea);
|
||||||
|
float padding=ImGui::CalcTextSize("A").x;
|
||||||
|
|
||||||
|
ImVec2 minLabelArea=minArea;
|
||||||
|
ImVec2 maxLabelArea=maxArea;
|
||||||
|
|
||||||
|
if (e->curSubSong->chanCollapse[i]) {
|
||||||
|
const char* chName=e->getChannelShortName(i);
|
||||||
|
if (strlen(chName)>3) {
|
||||||
|
snprintf(chanID,2048,"...");
|
||||||
|
} else {
|
||||||
|
snprintf(chanID,2048,"%s",chName);
|
||||||
|
}
|
||||||
|
displayTooltip=true;
|
||||||
|
} else {
|
||||||
|
minLabelArea.x+=padding;
|
||||||
|
maxLabelArea.x-=padding;
|
||||||
|
if (settings.channelStyle==3) { // split button
|
||||||
|
maxLabelArea.x-=ImGui::GetFrameHeightWithSpacing();
|
||||||
|
}
|
||||||
|
const char* chName=e->getChannelName(i);
|
||||||
|
float chNameLimit=maxLabelArea.x-minLabelArea.x;
|
||||||
|
if (ImGui::CalcTextSize(chName).x>chNameLimit) {
|
||||||
|
String shortChName;
|
||||||
|
float totalAdvanced=0.0f;
|
||||||
|
float ellipsisSize=ImGui::CalcTextSize("...").x;
|
||||||
|
for (const char* j=chName; *j;) {
|
||||||
|
signed char l;
|
||||||
|
int ch=decodeUTF8((const unsigned char*)j,l);
|
||||||
|
|
||||||
|
totalAdvanced+=ImGui::GetFont()->GetCharAdvance(ch);
|
||||||
|
if (totalAdvanced>(chNameLimit-ellipsisSize)) break;
|
||||||
|
|
||||||
|
for (int k=0; k<l; k++) {
|
||||||
|
shortChName+=j[k];
|
||||||
|
}
|
||||||
|
|
||||||
|
j+=l;
|
||||||
|
}
|
||||||
|
shortChName+="...";
|
||||||
|
snprintf(chanID,2048,"%s",shortChName.c_str());
|
||||||
|
displayTooltip=true;
|
||||||
|
} else {
|
||||||
|
snprintf(chanID,2048,"%s",chName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (settings.channelTextCenter) {
|
||||||
|
minLabelArea.x+=0.5f*(maxLabelArea.x-minLabelArea.x-ImGui::CalcTextSize(chanID).x);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (extraChannelButtons==0 || settings.channelVolStyle!=0) ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing,ImVec2(0.0f,0.0f));
|
||||||
|
|
||||||
|
ImGui::PushID(2048+i);
|
||||||
|
switch (settings.channelStyle) {
|
||||||
|
case 0: // classic
|
||||||
|
ImGui::ItemSize(size,ImGui::GetStyle().FramePadding.y);
|
||||||
|
if (ImGui::ItemAdd(rect,ImGui::GetID(chanID))) {
|
||||||
|
bool hovered=ImGui::ItemHoverable(rect,ImGui::GetID(chanID));
|
||||||
|
ImU32 col=hovered?ImGui::GetColorU32(ImGuiCol_HeaderHovered):ImGui::GetColorU32(ImGuiCol_Header);
|
||||||
|
dl->AddRectFilled(rect.Min,rect.Max,col);
|
||||||
|
dl->AddText(ImVec2(minLabelArea.x,rect.Min.y),ImGui::GetColorU32(channelTextColor(i)),chanID);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 1: { // line
|
||||||
|
ImGui::ItemSize(size,ImGui::GetStyle().FramePadding.y);
|
||||||
|
if (ImGui::ItemAdd(rect,ImGui::GetID(chanID))) {
|
||||||
|
bool hovered=ImGui::ItemHoverable(rect,ImGui::GetID(chanID));
|
||||||
|
ImU32 fadeCol0=ImGui::GetColorU32(ImVec4(
|
||||||
|
chanHeadBase.x,
|
||||||
|
chanHeadBase.y,
|
||||||
|
chanHeadBase.z,
|
||||||
|
hovered?0.25f:0.0f
|
||||||
|
));
|
||||||
|
ImU32 fadeCol=ImGui::GetColorU32(ImVec4(
|
||||||
|
chanHeadBase.x,
|
||||||
|
chanHeadBase.y,
|
||||||
|
chanHeadBase.z,
|
||||||
|
hovered?0.5f:MIN(1.0f,chanHeadBase.w*keyHit[i]*4.0f)
|
||||||
|
));
|
||||||
|
dl->AddRectFilledMultiColor(rect.Min,rect.Max,fadeCol0,fadeCol0,fadeCol,fadeCol);
|
||||||
|
dl->AddLine(ImVec2(rect.Min.x,rect.Max.y),ImVec2(rect.Max.x,rect.Max.y),ImGui::GetColorU32(chanHeadBase),2.0f*dpiScale);
|
||||||
|
dl->AddText(ImVec2(minLabelArea.x,rect.Min.y+3.0*dpiScale),ImGui::GetColorU32(channelTextColor(i)),chanID);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2: { // round
|
||||||
|
ImGui::ItemSize(size,ImGui::GetStyle().FramePadding.y);
|
||||||
|
if (ImGui::ItemAdd(rect,ImGui::GetID(chanID))) {
|
||||||
|
bool hovered=ImGui::ItemHoverable(rect,ImGui::GetID(chanID));
|
||||||
|
ImU32 fadeCol0=ImGui::GetColorU32(ImVec4(
|
||||||
|
chanHeadBase.x,
|
||||||
|
chanHeadBase.y,
|
||||||
|
chanHeadBase.z,
|
||||||
|
hovered?0.5f:MIN(1.0f,0.3f+chanHeadBase.w*keyHit[i]*1.5f)
|
||||||
|
));
|
||||||
|
ImU32 fadeCol=ImGui::GetColorU32(ImVec4(
|
||||||
|
chanHeadBase.x,
|
||||||
|
chanHeadBase.y,
|
||||||
|
chanHeadBase.z,
|
||||||
|
hovered?0.3f:MIN(1.0f,0.2f+chanHeadBase.w*keyHit[i]*1.2f)
|
||||||
|
));
|
||||||
|
ImVec2 rMin=rect.Min;
|
||||||
|
ImVec2 rMax=rect.Max;
|
||||||
|
rMin.x+=3.0f*dpiScale;
|
||||||
|
rMin.y+=6.0f*dpiScale;
|
||||||
|
rMax.x-=3.0f*dpiScale;
|
||||||
|
rMax.y-=6.0f*dpiScale;
|
||||||
|
dl->AddRectFilledMultiColor(rMin,rMax,fadeCol0,fadeCol0,fadeCol,fadeCol,4.0f*dpiScale);
|
||||||
|
dl->AddText(ImVec2(minLabelArea.x,rect.Min.y+6.0*dpiScale),ImGui::GetColorU32(channelTextColor(i)),chanID);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 3: // split button
|
||||||
|
ImGui::Dummy(ImVec2(1.0f,2.0f*dpiScale));
|
||||||
|
ImGui::SetCursorPosX(minLabelArea.x);
|
||||||
|
ImGui::TextUnformatted(chanID);
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::PushFont(mainFont);
|
||||||
|
ImGui::SmallButton(muted?ICON_FA_VOLUME_OFF:ICON_FA_VOLUME_UP);
|
||||||
|
ImGui::PopFont();
|
||||||
|
break;
|
||||||
|
case 4: { // square border
|
||||||
|
ImGui::ItemSize(size,ImGui::GetStyle().FramePadding.y);
|
||||||
|
if (ImGui::ItemAdd(rect,ImGui::GetID(chanID))) {
|
||||||
|
bool hovered=ImGui::ItemHoverable(rect,ImGui::GetID(chanID));
|
||||||
|
ImU32 fadeCol=ImGui::GetColorU32(ImVec4(
|
||||||
|
chanHeadBase.x,
|
||||||
|
chanHeadBase.y,
|
||||||
|
chanHeadBase.z,
|
||||||
|
hovered?1.0f:MIN(1.0f,0.2f+chanHeadBase.w*keyHit[i]*4.0f)
|
||||||
|
));
|
||||||
|
ImVec2 rMin=rect.Min;
|
||||||
|
ImVec2 rMax=rect.Max;
|
||||||
|
rMin.x+=2.0f*dpiScale;
|
||||||
|
rMin.y+=3.0f*dpiScale;
|
||||||
|
rMax.x-=3.0f*dpiScale;
|
||||||
|
rMax.y-=3.0f*dpiScale;
|
||||||
|
dl->AddRect(rMin,rMax,fadeCol,0.0f,2.0*dpiScale);
|
||||||
|
dl->AddText(ImVec2(minLabelArea.x,rect.Min.y+3.0*dpiScale),ImGui::GetColorU32(channelTextColor(i)),chanID);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 5: { // round border
|
||||||
|
ImGui::ItemSize(size,ImGui::GetStyle().FramePadding.y);
|
||||||
|
if (ImGui::ItemAdd(rect,ImGui::GetID(chanID))) {
|
||||||
|
bool hovered=ImGui::ItemHoverable(rect,ImGui::GetID(chanID));
|
||||||
|
ImU32 fadeCol=ImGui::GetColorU32(ImVec4(
|
||||||
|
chanHeadBase.x,
|
||||||
|
chanHeadBase.y,
|
||||||
|
chanHeadBase.z,
|
||||||
|
hovered?1.0f:MIN(1.0f,0.2f+chanHeadBase.w*keyHit[i]*4.0f)
|
||||||
|
));
|
||||||
|
ImVec2 rMin=rect.Min;
|
||||||
|
ImVec2 rMax=rect.Max;
|
||||||
|
rMin.x+=2.0f*dpiScale;
|
||||||
|
rMin.y+=3.0f*dpiScale;
|
||||||
|
rMax.x-=3.0f*dpiScale;
|
||||||
|
rMax.y-=3.0f*dpiScale;
|
||||||
|
dl->AddRect(rMin,rMax,fadeCol,4.0f*dpiScale,ImDrawFlags_RoundCornersAll,2.0*dpiScale);
|
||||||
|
dl->AddText(ImVec2(minLabelArea.x,rect.Min.y+3.0*dpiScale),ImGui::GetColorU32(channelTextColor(i)),chanID);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::PopID();
|
||||||
|
|
||||||
|
if (extraChannelButtons==0 || settings.channelVolStyle!=0) ImGui::PopStyleVar();
|
||||||
|
|
||||||
if (displayTooltip && ImGui::IsItemHovered()) {
|
if (displayTooltip && ImGui::IsItemHovered()) {
|
||||||
ImGui::SetTooltip("%s",e->getChannelName(i));
|
ImGui::SetTooltip("%s",e->getChannelName(i));
|
||||||
}
|
}
|
||||||
|
if (settings.channelFont==0) ImGui::PopFont();
|
||||||
if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) {
|
if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) {
|
||||||
if (settings.soloAction!=1 && soloTimeout>0 && soloChan==i) {
|
if (settings.soloAction!=1 && soloTimeout>0 && soloChan==i) {
|
||||||
e->toggleSolo(i);
|
e->toggleSolo(i);
|
||||||
|
@ -513,11 +714,72 @@ void FurnaceGUI::drawPattern() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (muted) ImGui::PopStyleColor();
|
if (muted) ImGui::PopStyleColor();
|
||||||
ImGui::PopStyleColor(3);
|
ImGui::PopStyleColor(4);
|
||||||
if (settings.soloAction!=2) if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) {
|
if (settings.soloAction!=2) if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) {
|
||||||
inhibitMenu=true;
|
inhibitMenu=true;
|
||||||
e->toggleSolo(i);
|
e->toggleSolo(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (settings.channelStyle==3) {
|
||||||
|
ImGui::Dummy(ImVec2(1.0f,2.0f*dpiScale));
|
||||||
|
}
|
||||||
|
|
||||||
|
// volume bar
|
||||||
|
if (settings.channelVolStyle!=0) {
|
||||||
|
ImVec2 sizeV=ImVec2(
|
||||||
|
1.0f,
|
||||||
|
6.0*dpiScale
|
||||||
|
);
|
||||||
|
ImVec2 minAreaV=window->DC.CursorPos;
|
||||||
|
ImVec2 maxAreaV=ImVec2(
|
||||||
|
minAreaV.x+window->WorkRect.Max.x-window->WorkRect.Min.x,
|
||||||
|
minAreaV.y+sizeV.y
|
||||||
|
);
|
||||||
|
ImRect rectV=ImRect(minAreaV,maxAreaV);
|
||||||
|
ImGui::ItemSize(sizeV,ImGui::GetStyle().FramePadding.y);
|
||||||
|
if (ImGui::ItemAdd(rectV,ImGui::GetID(chanID))) {
|
||||||
|
float xLeft=0.0f;
|
||||||
|
float xRight=1.0f;
|
||||||
|
|
||||||
|
if (e->keyHit[i]) {
|
||||||
|
keyHit1[i]=1.0f;
|
||||||
|
e->keyHit[i]=false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e->isRunning()) {
|
||||||
|
DivChannelState* cs=e->getChanState(i);
|
||||||
|
float stereoPan=(float)(e->convertPanSplitToLinearLR(cs->panL,cs->panR,256)-128)/128.0;
|
||||||
|
switch (settings.channelVolStyle) {
|
||||||
|
case 1: // simple
|
||||||
|
xRight=((float)(e->getChanState(i)->volume>>8)/(float)e->getMaxVolumeChan(i))*0.9+(keyHit1[i]*0.1f);
|
||||||
|
break;
|
||||||
|
case 2: { // stereo
|
||||||
|
float amount=((float)(e->getChanState(i)->volume>>8)/(float)e->getMaxVolumeChan(i))*0.4+(keyHit1[i]*0.1f);
|
||||||
|
xRight=0.5+amount*(1.0+MIN(0.0,stereoPan));
|
||||||
|
xLeft=0.5-amount*(1.0-MAX(0.0,stereoPan));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 3: // real
|
||||||
|
xRight=chanOscVol[i];
|
||||||
|
break;
|
||||||
|
case 4: // real (stereo)
|
||||||
|
xRight=0.5+chanOscVol[i]*0.5*(1.0+MIN(0.0,stereoPan));
|
||||||
|
xLeft=0.5-chanOscVol[i]*0.5*(1.0-MAX(0.0,stereoPan));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl->AddRectFilled(
|
||||||
|
ImLerp(rectV.Min,rectV.Max,ImVec2(xLeft,0.0f)),
|
||||||
|
ImLerp(rectV.Min,rectV.Max,ImVec2(xRight,1.0f)),
|
||||||
|
ImGui::GetColorU32(chanHeadBase)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
keyHit1[i]-=0.2f;
|
||||||
|
if (keyHit1[i]<0.0f) keyHit1[i]=0.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// extra buttons
|
||||||
if (extraChannelButtons==2) {
|
if (extraChannelButtons==2) {
|
||||||
DivPattern* pat=e->curPat[i].getPattern(e->curOrders->ord[i][ord],true);
|
DivPattern* pat=e->curPat[i].getPattern(e->curOrders->ord[i][ord],true);
|
||||||
ImGui::PushFont(mainFont);
|
ImGui::PushFont(mainFont);
|
||||||
|
|
|
@ -960,11 +960,27 @@ void FurnaceGUI::initSystemPresets() {
|
||||||
cat.systems.push_back(FurnaceGUISysDef(
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
"NEC PC-98 (with PC-9801-86)", { // -73 also has OPNA
|
"NEC PC-98 (with PC-9801-86)", { // -73 also has OPNA
|
||||||
DIV_SYSTEM_PC98, 64, 0, 1,
|
DIV_SYSTEM_PC98, 64, 0, 1,
|
||||||
|
DIV_SYSTEM_PCM_DAC, 64, 0, 44099|(15<<16), // 2x 16-bit Burr Brown DAC
|
||||||
|
DIV_SYSTEM_PCM_DAC, 64, 0, 44099|(15<<16),
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
cat.systems.push_back(FurnaceGUISysDef(
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
"NEC PC-98 (with PC-9801-86; extended channel 3)", { // -73 also has OPNA
|
"NEC PC-98 (with PC-9801-86; extended channel 3)", { // -73 also has OPNA
|
||||||
|
DIV_SYSTEM_PC98_EXT, 64, 0, 1,
|
||||||
|
DIV_SYSTEM_PCM_DAC, 64, 0, 44099|(15<<16),
|
||||||
|
DIV_SYSTEM_PCM_DAC, 64, 0, 44099|(15<<16),
|
||||||
|
0
|
||||||
|
}
|
||||||
|
));
|
||||||
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
|
"NEC PC-98 (with PC-9801-73)", {
|
||||||
|
DIV_SYSTEM_PC98, 64, 0, 1,
|
||||||
|
0
|
||||||
|
}
|
||||||
|
));
|
||||||
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
|
"NEC PC-98 (with PC-9801-73; extended channel 3)", {
|
||||||
DIV_SYSTEM_PC98_EXT, 64, 0, 1,
|
DIV_SYSTEM_PC98_EXT, 64, 0, 1,
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
@ -972,6 +988,7 @@ void FurnaceGUI::initSystemPresets() {
|
||||||
cat.systems.push_back(FurnaceGUISysDef(
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
"NEC PC-98 (with Sound Blaster 16 for PC-9800 w/PC-9801-26/K compatible)", {
|
"NEC PC-98 (with Sound Blaster 16 for PC-9800 w/PC-9801-26/K compatible)", {
|
||||||
DIV_SYSTEM_OPN, 64, 0, 2, // 4MHz
|
DIV_SYSTEM_OPN, 64, 0, 2, // 4MHz
|
||||||
|
DIV_SYSTEM_PCM_DAC, 64, 0, 44099|(15<<16)|(1<<20),
|
||||||
DIV_SYSTEM_OPL3, 64, 0, 0,
|
DIV_SYSTEM_OPL3, 64, 0, 0,
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
@ -979,6 +996,7 @@ void FurnaceGUI::initSystemPresets() {
|
||||||
cat.systems.push_back(FurnaceGUISysDef(
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
"NEC PC-98 (with Sound Blaster 16 for PC-9800 w/PC-9801-26/K compatible; extended channel 3)", {
|
"NEC PC-98 (with Sound Blaster 16 for PC-9800 w/PC-9801-26/K compatible; extended channel 3)", {
|
||||||
DIV_SYSTEM_OPN_EXT, 64, 0, 2, // 4MHz
|
DIV_SYSTEM_OPN_EXT, 64, 0, 2, // 4MHz
|
||||||
|
DIV_SYSTEM_PCM_DAC, 64, 0, 44099|(15<<16)|(1<<20),
|
||||||
DIV_SYSTEM_OPL3, 64, 0, 0,
|
DIV_SYSTEM_OPL3, 64, 0, 0,
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
@ -986,6 +1004,7 @@ void FurnaceGUI::initSystemPresets() {
|
||||||
cat.systems.push_back(FurnaceGUISysDef(
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
"NEC PC-98 (with Sound Blaster 16 for PC-9800 w/PC-9801-26/K compatible in drums mode)", {
|
"NEC PC-98 (with Sound Blaster 16 for PC-9800 w/PC-9801-26/K compatible in drums mode)", {
|
||||||
DIV_SYSTEM_OPN, 64, 0, 2, // 4MHz
|
DIV_SYSTEM_OPN, 64, 0, 2, // 4MHz
|
||||||
|
DIV_SYSTEM_PCM_DAC, 64, 0, 44099|(15<<16)|(1<<20),
|
||||||
DIV_SYSTEM_OPL3_DRUMS, 64, 0, 2,
|
DIV_SYSTEM_OPL3_DRUMS, 64, 0, 2,
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
@ -993,6 +1012,7 @@ void FurnaceGUI::initSystemPresets() {
|
||||||
cat.systems.push_back(FurnaceGUISysDef(
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
"NEC PC-98 (with Sound Blaster 16 for PC-9800 w/PC-9801-26/K compatible in drums mode; extended channel 3)", {
|
"NEC PC-98 (with Sound Blaster 16 for PC-9800 w/PC-9801-26/K compatible in drums mode; extended channel 3)", {
|
||||||
DIV_SYSTEM_OPN_EXT, 64, 0, 2, // 4MHz
|
DIV_SYSTEM_OPN_EXT, 64, 0, 2, // 4MHz
|
||||||
|
DIV_SYSTEM_PCM_DAC, 64, 0, 44099|(15<<16)|(1<<20),
|
||||||
DIV_SYSTEM_OPL3_DRUMS, 64, 0, 2,
|
DIV_SYSTEM_OPL3_DRUMS, 64, 0, 2,
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
@ -1092,6 +1112,20 @@ void FurnaceGUI::initSystemPresets() {
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
|
"Atari ST", {
|
||||||
|
DIV_SYSTEM_AY8910, 64, 0, 19,
|
||||||
|
0
|
||||||
|
}
|
||||||
|
));
|
||||||
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
|
"Atari STE", {
|
||||||
|
DIV_SYSTEM_AY8910, 64, 0, 19,
|
||||||
|
DIV_SYSTEM_PCM_DAC, 64, 0, 50667|(7<<16),
|
||||||
|
DIV_SYSTEM_PCM_DAC, 64, 0, 50667|(7<<16),
|
||||||
|
0
|
||||||
|
}
|
||||||
|
));
|
||||||
cat.systems.push_back(FurnaceGUISysDef(
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
"SAM Coupé", {
|
"SAM Coupé", {
|
||||||
DIV_SYSTEM_SAA1099, 64, 0, 0,
|
DIV_SYSTEM_SAA1099, 64, 0, 0,
|
||||||
|
@ -1146,17 +1180,33 @@ void FurnaceGUI::initSystemPresets() {
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
cat.systems.push_back(FurnaceGUISysDef(
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
"PC + AdLib/Sound Blaster", {
|
"PC + AdLib", {
|
||||||
DIV_SYSTEM_OPL2, 64, 0, 0,
|
DIV_SYSTEM_OPL2, 64, 0, 0,
|
||||||
DIV_SYSTEM_PCSPKR, 64, 0, 0,
|
DIV_SYSTEM_PCSPKR, 64, 0, 0,
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
));
|
||||||
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
|
"PC + AdLib (drums mode)", {
|
||||||
|
DIV_SYSTEM_OPL2, 64, 0, 0,
|
||||||
|
DIV_SYSTEM_PCSPKR, 64, 0, 0,
|
||||||
|
0
|
||||||
|
}
|
||||||
|
));
|
||||||
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
|
"PC + Sound Blaster", {
|
||||||
|
DIV_SYSTEM_OPL2, 64, 0, 0,
|
||||||
|
DIV_SYSTEM_PCSPKR, 64, 0, 0,
|
||||||
|
DIV_SYSTEM_PCM_DAC, 64, 0, 22049|(7<<16),
|
||||||
|
0
|
||||||
|
}
|
||||||
));
|
));
|
||||||
cat.systems.push_back(FurnaceGUISysDef(
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
"PC + AdLib/Sound Blaster (drums mode)", {
|
"PC + AdLib/Sound Blaster (drums mode)", {
|
||||||
DIV_SYSTEM_OPL2_DRUMS, 64, 0, 0,
|
DIV_SYSTEM_OPL2_DRUMS, 64, 0, 0,
|
||||||
DIV_SYSTEM_PCSPKR, 64, 0, 0,
|
DIV_SYSTEM_PCSPKR, 64, 0, 0,
|
||||||
|
DIV_SYSTEM_PCM_DAC, 64, 0, 22049|(7<<16),
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
@ -1165,6 +1215,7 @@ void FurnaceGUI::initSystemPresets() {
|
||||||
DIV_SYSTEM_OPL2, 64, 0, 0,
|
DIV_SYSTEM_OPL2, 64, 0, 0,
|
||||||
DIV_SYSTEM_SAA1099, 64, 0, 1,
|
DIV_SYSTEM_SAA1099, 64, 0, 1,
|
||||||
DIV_SYSTEM_SAA1099, 64, 0, 1,
|
DIV_SYSTEM_SAA1099, 64, 0, 1,
|
||||||
|
DIV_SYSTEM_PCM_DAC, 64, 0, 22049|(7<<16),
|
||||||
DIV_SYSTEM_PCSPKR, 64, 0, 0,
|
DIV_SYSTEM_PCSPKR, 64, 0, 0,
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
@ -1174,6 +1225,7 @@ void FurnaceGUI::initSystemPresets() {
|
||||||
DIV_SYSTEM_OPL2_DRUMS, 64, 0, 0,
|
DIV_SYSTEM_OPL2_DRUMS, 64, 0, 0,
|
||||||
DIV_SYSTEM_SAA1099, 64, 0, 1,
|
DIV_SYSTEM_SAA1099, 64, 0, 1,
|
||||||
DIV_SYSTEM_SAA1099, 64, 0, 1,
|
DIV_SYSTEM_SAA1099, 64, 0, 1,
|
||||||
|
DIV_SYSTEM_PCM_DAC, 64, 0, 22049|(7<<16),
|
||||||
DIV_SYSTEM_PCSPKR, 64, 0, 0,
|
DIV_SYSTEM_PCSPKR, 64, 0, 0,
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
@ -1182,6 +1234,7 @@ void FurnaceGUI::initSystemPresets() {
|
||||||
"PC + Sound Blaster Pro", {
|
"PC + Sound Blaster Pro", {
|
||||||
DIV_SYSTEM_OPL2, 64, -127, 0,
|
DIV_SYSTEM_OPL2, 64, -127, 0,
|
||||||
DIV_SYSTEM_OPL2, 64, 127, 0,
|
DIV_SYSTEM_OPL2, 64, 127, 0,
|
||||||
|
DIV_SYSTEM_PCM_DAC, 64, 0, 22049|(7<<16)|(1<<20), //alternatively 44.1 khz mono
|
||||||
DIV_SYSTEM_PCSPKR, 64, 0, 0,
|
DIV_SYSTEM_PCSPKR, 64, 0, 0,
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
@ -1190,6 +1243,7 @@ void FurnaceGUI::initSystemPresets() {
|
||||||
"PC + Sound Blaster Pro (drums mode)", {
|
"PC + Sound Blaster Pro (drums mode)", {
|
||||||
DIV_SYSTEM_OPL2_DRUMS, 64, -127, 0,
|
DIV_SYSTEM_OPL2_DRUMS, 64, -127, 0,
|
||||||
DIV_SYSTEM_OPL2_DRUMS, 64, 127, 0,
|
DIV_SYSTEM_OPL2_DRUMS, 64, 127, 0,
|
||||||
|
DIV_SYSTEM_PCM_DAC, 64, 0, 22049|(7<<16)|(1<<20), //alternatively 44.1 khz mono
|
||||||
DIV_SYSTEM_PCSPKR, 64, 0, 0,
|
DIV_SYSTEM_PCSPKR, 64, 0, 0,
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
@ -1197,6 +1251,7 @@ void FurnaceGUI::initSystemPresets() {
|
||||||
cat.systems.push_back(FurnaceGUISysDef(
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
"PC + Sound Blaster Pro 2", {
|
"PC + Sound Blaster Pro 2", {
|
||||||
DIV_SYSTEM_OPL3, 64, 0, 0,
|
DIV_SYSTEM_OPL3, 64, 0, 0,
|
||||||
|
DIV_SYSTEM_PCM_DAC, 64, 0, 44099|(15<<16)|(1<<20),
|
||||||
DIV_SYSTEM_PCSPKR, 64, 0, 0,
|
DIV_SYSTEM_PCSPKR, 64, 0, 0,
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
@ -1204,6 +1259,7 @@ void FurnaceGUI::initSystemPresets() {
|
||||||
cat.systems.push_back(FurnaceGUISysDef(
|
cat.systems.push_back(FurnaceGUISysDef(
|
||||||
"PC + Sound Blaster Pro 2 (drums mode)", {
|
"PC + Sound Blaster Pro 2 (drums mode)", {
|
||||||
DIV_SYSTEM_OPL3_DRUMS, 64, 0, 0,
|
DIV_SYSTEM_OPL3_DRUMS, 64, 0, 0,
|
||||||
|
DIV_SYSTEM_PCM_DAC, 64, 0, 44099|(15<<16)|(1<<20),
|
||||||
DIV_SYSTEM_PCSPKR, 64, 0, 0,
|
DIV_SYSTEM_PCSPKR, 64, 0, 0,
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
|
@ -1284,14 +1284,14 @@ void FurnaceGUI::drawSettings() {
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::Text("Channel name colors:");
|
ImGui::Text("Channel name colors:");
|
||||||
if (ImGui::RadioButton("Single##CTC0",settings.channelColors==0)) {
|
if (ImGui::RadioButton("Single##CTC0",settings.channelTextColors==0)) {
|
||||||
settings.channelColors=0;
|
settings.channelTextColors=0;
|
||||||
}
|
}
|
||||||
if (ImGui::RadioButton("Channel type##CTC1",settings.channelColors==1)) {
|
if (ImGui::RadioButton("Channel type##CTC1",settings.channelTextColors==1)) {
|
||||||
settings.channelColors=1;
|
settings.channelTextColors=1;
|
||||||
}
|
}
|
||||||
if (ImGui::RadioButton("Instrument type##CTC2",settings.channelColors==2)) {
|
if (ImGui::RadioButton("Instrument type##CTC2",settings.channelTextColors==2)) {
|
||||||
settings.channelColors=2;
|
settings.channelTextColors=2;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::Text("Channel style:");
|
ImGui::Text("Channel style:");
|
||||||
|
@ -1327,6 +1327,9 @@ void FurnaceGUI::drawSettings() {
|
||||||
if (ImGui::RadioButton("Real##CHV3",settings.channelVolStyle==3)) {
|
if (ImGui::RadioButton("Real##CHV3",settings.channelVolStyle==3)) {
|
||||||
settings.channelVolStyle=3;
|
settings.channelVolStyle=3;
|
||||||
}
|
}
|
||||||
|
if (ImGui::RadioButton("Real (stereo)##CHV4",settings.channelVolStyle==4)) {
|
||||||
|
settings.channelVolStyle=4;
|
||||||
|
}
|
||||||
|
|
||||||
ImGui::Text("Channel feedback style:");
|
ImGui::Text("Channel feedback style:");
|
||||||
|
|
||||||
|
@ -1343,6 +1346,20 @@ void FurnaceGUI::drawSettings() {
|
||||||
settings.channelFeedbackStyle=3;
|
settings.channelFeedbackStyle=3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImGui::Text("Channel font:");
|
||||||
|
|
||||||
|
if (ImGui::RadioButton("Regular##CHFont0",settings.channelFont==0)) {
|
||||||
|
settings.channelFont=0;
|
||||||
|
}
|
||||||
|
if (ImGui::RadioButton("Monospace##CHFont1",settings.channelFont==1)) {
|
||||||
|
settings.channelFont=1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool channelTextCenterB=settings.channelTextCenter;
|
||||||
|
if (ImGui::Checkbox("Center channel name",&channelTextCenterB)) {
|
||||||
|
settings.channelTextCenter=channelTextCenterB;
|
||||||
|
}
|
||||||
|
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
|
||||||
bool insEditColorizeB=settings.insEditColorize;
|
bool insEditColorizeB=settings.insEditColorize;
|
||||||
|
@ -1668,6 +1685,8 @@ void FurnaceGUI::drawSettings() {
|
||||||
ImGui::TreePop();
|
ImGui::TreePop();
|
||||||
}
|
}
|
||||||
if (ImGui::TreeNode("Channel")) {
|
if (ImGui::TreeNode("Channel")) {
|
||||||
|
UI_COLOR_CONFIG(GUI_COLOR_CHANNEL_BG,"Single color (background)");
|
||||||
|
UI_COLOR_CONFIG(GUI_COLOR_CHANNEL_FG,"Single color (text)");
|
||||||
UI_COLOR_CONFIG(GUI_COLOR_CHANNEL_FM,"FM");
|
UI_COLOR_CONFIG(GUI_COLOR_CHANNEL_FM,"FM");
|
||||||
UI_COLOR_CONFIG(GUI_COLOR_CHANNEL_PULSE,"Pulse");
|
UI_COLOR_CONFIG(GUI_COLOR_CHANNEL_PULSE,"Pulse");
|
||||||
UI_COLOR_CONFIG(GUI_COLOR_CHANNEL_NOISE,"Noise");
|
UI_COLOR_CONFIG(GUI_COLOR_CHANNEL_NOISE,"Noise");
|
||||||
|
@ -2286,9 +2305,11 @@ void FurnaceGUI::syncSettings() {
|
||||||
settings.saveUnusedPatterns=e->getConfInt("saveUnusedPatterns",0);
|
settings.saveUnusedPatterns=e->getConfInt("saveUnusedPatterns",0);
|
||||||
settings.channelColors=e->getConfInt("channelColors",1);
|
settings.channelColors=e->getConfInt("channelColors",1);
|
||||||
settings.channelTextColors=e->getConfInt("channelTextColors",0);
|
settings.channelTextColors=e->getConfInt("channelTextColors",0);
|
||||||
settings.channelStyle=e->getConfInt("channelStyle",0);
|
settings.channelStyle=e->getConfInt("channelStyle",1);
|
||||||
settings.channelVolStyle=e->getConfInt("channelVolStyle",0);
|
settings.channelVolStyle=e->getConfInt("channelVolStyle",0);
|
||||||
settings.channelFeedbackStyle=e->getConfInt("channelFeedbackStyle",1);
|
settings.channelFeedbackStyle=e->getConfInt("channelFeedbackStyle",1);
|
||||||
|
settings.channelFont=e->getConfInt("channelFont",1);
|
||||||
|
settings.channelTextCenter=e->getConfInt("channelTextCenter",1);
|
||||||
settings.maxRecentFile=e->getConfInt("maxRecentFile",10);
|
settings.maxRecentFile=e->getConfInt("maxRecentFile",10);
|
||||||
|
|
||||||
clampSetting(settings.mainFontSize,2,96);
|
clampSetting(settings.mainFontSize,2,96);
|
||||||
|
@ -2386,8 +2407,10 @@ void FurnaceGUI::syncSettings() {
|
||||||
clampSetting(settings.channelColors,0,2);
|
clampSetting(settings.channelColors,0,2);
|
||||||
clampSetting(settings.channelTextColors,0,2);
|
clampSetting(settings.channelTextColors,0,2);
|
||||||
clampSetting(settings.channelStyle,0,5);
|
clampSetting(settings.channelStyle,0,5);
|
||||||
clampSetting(settings.channelVolStyle,0,3);
|
clampSetting(settings.channelVolStyle,0,4);
|
||||||
clampSetting(settings.channelFeedbackStyle,0,3);
|
clampSetting(settings.channelFeedbackStyle,0,3);
|
||||||
|
clampSetting(settings.channelFont,0,1);
|
||||||
|
clampSetting(settings.channelTextCenter,0,1);
|
||||||
clampSetting(settings.maxRecentFile,0,30);
|
clampSetting(settings.maxRecentFile,0,30);
|
||||||
|
|
||||||
settings.initialSys=e->decodeSysDesc(e->getConfString("initialSys",""));
|
settings.initialSys=e->decodeSysDesc(e->getConfString("initialSys",""));
|
||||||
|
@ -2543,6 +2566,8 @@ void FurnaceGUI::commitSettings() {
|
||||||
e->setConf("channelStyle",settings.channelStyle);
|
e->setConf("channelStyle",settings.channelStyle);
|
||||||
e->setConf("channelVolStyle",settings.channelVolStyle);
|
e->setConf("channelVolStyle",settings.channelVolStyle);
|
||||||
e->setConf("channelFeedbackStyle",settings.channelFeedbackStyle);
|
e->setConf("channelFeedbackStyle",settings.channelFeedbackStyle);
|
||||||
|
e->setConf("channelFont",settings.channelFont);
|
||||||
|
e->setConf("channelTextCenter",settings.channelTextCenter);
|
||||||
e->setConf("maxRecentFile",settings.maxRecentFile);
|
e->setConf("maxRecentFile",settings.maxRecentFile);
|
||||||
|
|
||||||
// colors
|
// colors
|
||||||
|
|
|
@ -39,7 +39,7 @@ void FurnaceGUI::drawSongInfo() {
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
float avail=ImGui::GetContentRegionAvail().x;
|
float avail=ImGui::GetContentRegionAvail().x;
|
||||||
ImGui::SetNextItemWidth(avail);
|
ImGui::SetNextItemWidth(avail);
|
||||||
if (ImGui::InputText("##Name",&e->song.name)) { MARK_MODIFIED
|
if (ImGui::InputText("##Name",&e->song.name,ImGuiInputTextFlags_UndoRedo)) { MARK_MODIFIED
|
||||||
updateWindowTitle();
|
updateWindowTitle();
|
||||||
}
|
}
|
||||||
if (e->song.insLen==2) {
|
if (e->song.insLen==2) {
|
||||||
|
@ -61,7 +61,7 @@ void FurnaceGUI::drawSongInfo() {
|
||||||
ImGui::Text("Author");
|
ImGui::Text("Author");
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
ImGui::SetNextItemWidth(avail);
|
ImGui::SetNextItemWidth(avail);
|
||||||
if (ImGui::InputText("##Author",&e->song.author)) {
|
if (ImGui::InputText("##Author",&e->song.author,ImGuiInputTextFlags_UndoRedo)) {
|
||||||
MARK_MODIFIED;
|
MARK_MODIFIED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,18 +70,30 @@ void FurnaceGUI::drawSongInfo() {
|
||||||
ImGui::Text("Album");
|
ImGui::Text("Album");
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
ImGui::SetNextItemWidth(avail);
|
ImGui::SetNextItemWidth(avail);
|
||||||
if (ImGui::InputText("##Category",&e->song.category)) {
|
if (ImGui::InputText("##Category",&e->song.category,ImGuiInputTextFlags_UndoRedo)) {
|
||||||
MARK_MODIFIED;
|
MARK_MODIFIED;
|
||||||
}
|
}
|
||||||
ImGui::TableNextRow();
|
ImGui::TableNextRow();
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
ImGui::Text("System");
|
ImGui::Text("System");
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
ImGui::SetNextItemWidth(avail);
|
ImGui::SetNextItemWidth(MAX(16.0f*dpiScale,avail-autoButtonSize-ImGui::GetStyle().ItemSpacing.x));
|
||||||
if (ImGui::InputText("##SystemName",&e->song.systemName)) {
|
if (ImGui::InputText("##SystemName",&e->song.systemName,ImGuiInputTextFlags_UndoRedo)) {
|
||||||
MARK_MODIFIED;
|
MARK_MODIFIED;
|
||||||
updateWindowTitle();
|
updateWindowTitle();
|
||||||
|
e->song.autoSystem=false;
|
||||||
}
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
pushToggleColors(e->song.autoSystem);
|
||||||
|
if (ImGui::Button("Auto")) {
|
||||||
|
e->song.autoSystem=!e->song.autoSystem;
|
||||||
|
if (e->song.autoSystem) {
|
||||||
|
autoDetectSystem();
|
||||||
|
updateWindowTitle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
popToggleColors();
|
||||||
|
autoButtonSize=ImGui::GetItemRectSize().x;
|
||||||
|
|
||||||
ImGui::EndTable();
|
ImGui::EndTable();
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ void FurnaceGUI::drawNotes() {
|
||||||
}
|
}
|
||||||
if (!notesOpen) return;
|
if (!notesOpen) return;
|
||||||
if (ImGui::Begin("Song Comments",¬esOpen,globalWinFlags)) {
|
if (ImGui::Begin("Song Comments",¬esOpen,globalWinFlags)) {
|
||||||
ImGui::InputTextMultiline("##SongNotes",&e->song.notes,ImGui::GetContentRegionAvail());
|
ImGui::InputTextMultiline("##SongNotes",&e->song.notes,ImGui::GetContentRegionAvail(),ImGuiInputTextFlags_UndoRedo);
|
||||||
}
|
}
|
||||||
if (ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows)) curWindow=GUI_WINDOW_NOTES;
|
if (ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows)) curWindow=GUI_WINDOW_NOTES;
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
|
|
|
@ -91,7 +91,7 @@ void FurnaceGUI::drawSubSongs() {
|
||||||
ImGui::Text("Name");
|
ImGui::Text("Name");
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||||
if (ImGui::InputText("##SubSongName",&e->curSubSong->name)) {
|
if (ImGui::InputText("##SubSongName",&e->curSubSong->name,ImGuiInputTextFlags_UndoRedo)) {
|
||||||
MARK_MODIFIED;
|
MARK_MODIFIED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -217,7 +217,7 @@ void FurnaceGUI::drawSysConf(int chan, DivSystem type, unsigned int& flags, bool
|
||||||
if (ImGui::RadioButton("PAL (3.55MHz)",(flags&15)==1)) {
|
if (ImGui::RadioButton("PAL (3.55MHz)",(flags&15)==1)) {
|
||||||
copyOfFlags=(flags&(~15))|1;
|
copyOfFlags=(flags&(~15))|1;
|
||||||
}
|
}
|
||||||
if (ImGui::RadioButton("BBC Micro (4MHz)",(flags&15)==2)) {
|
if (ImGui::RadioButton("Arcade (4MHz)",(flags&15)==2)) {
|
||||||
copyOfFlags=(flags&(~15))|2;
|
copyOfFlags=(flags&(~15))|2;
|
||||||
}
|
}
|
||||||
if (ImGui::RadioButton("Half NTSC (1.79MHz)",(flags&15)==3)) {
|
if (ImGui::RadioButton("Half NTSC (1.79MHz)",(flags&15)==3)) {
|
||||||
|
@ -358,6 +358,14 @@ void FurnaceGUI::drawSysConf(int chan, DivSystem type, unsigned int& flags, bool
|
||||||
if (ImGui::Checkbox("Stereo##_AY_STEREO",&stereo)) {
|
if (ImGui::Checkbox("Stereo##_AY_STEREO",&stereo)) {
|
||||||
copyOfFlags=(flags&(~0x40))|(stereo?0x40:0);
|
copyOfFlags=(flags&(~0x40))|(stereo?0x40:0);
|
||||||
}
|
}
|
||||||
|
if (stereo) {
|
||||||
|
int sep=256-((flags>>8)&255);
|
||||||
|
if (CWSliderInt("Separation",&sep,1,256)) {
|
||||||
|
if (sep<1) sep=1;
|
||||||
|
if (sep>256) sep=256;
|
||||||
|
copyOfFlags=(flags&(~0xff00))|((256-sep)<<8);
|
||||||
|
}
|
||||||
|
}
|
||||||
ImGui::EndDisabled();
|
ImGui::EndDisabled();
|
||||||
bool clockSel=flags&0x80;
|
bool clockSel=flags&0x80;
|
||||||
ImGui::BeginDisabled((type==DIV_SYSTEM_AY8910) && ((flags&0x30)!=16));
|
ImGui::BeginDisabled((type==DIV_SYSTEM_AY8910) && ((flags&0x30)!=16));
|
||||||
|
@ -765,6 +773,9 @@ void FurnaceGUI::drawSysConf(int chan, DivSystem type, unsigned int& flags, bool
|
||||||
if (copyOfFlags!=flags) {
|
if (copyOfFlags!=flags) {
|
||||||
if (chan>=0) {
|
if (chan>=0) {
|
||||||
e->setSysFlags(chan,copyOfFlags,restart);
|
e->setSysFlags(chan,copyOfFlags,restart);
|
||||||
|
if (e->song.autoSystem) {
|
||||||
|
autoDetectSystem();
|
||||||
|
}
|
||||||
updateWindowTitle();
|
updateWindowTitle();
|
||||||
} else {
|
} else {
|
||||||
flags=copyOfFlags;
|
flags=copyOfFlags;
|
||||||
|
|
|
@ -60,6 +60,7 @@ bool FurnaceGUI::parseSysEx(unsigned char* data, size_t len) {
|
||||||
op.rs=reader.readC();
|
op.rs=reader.readC();
|
||||||
reader.readC(); // EBS - ignore
|
reader.readC(); // EBS - ignore
|
||||||
op.am=reader.readC();
|
op.am=reader.readC();
|
||||||
|
// TODO: don't ignore after I add KVS to Furnace
|
||||||
reader.readC(); // KVS - ignore
|
reader.readC(); // KVS - ignore
|
||||||
op.tl=3+((99-reader.readC())*124)/99;
|
op.tl=3+((99-reader.readC())*124)/99;
|
||||||
unsigned char freq=reader.readC();
|
unsigned char freq=reader.readC();
|
||||||
|
|
|
@ -82,6 +82,9 @@ void FurnaceGUI::drawSysManager() {
|
||||||
DivSystem picked=systemPicker();
|
DivSystem picked=systemPicker();
|
||||||
if (picked!=DIV_SYSTEM_NULL) {
|
if (picked!=DIV_SYSTEM_NULL) {
|
||||||
e->changeSystem(i,picked,preserveChanPos);
|
e->changeSystem(i,picked,preserveChanPos);
|
||||||
|
if (e->song.autoSystem) {
|
||||||
|
autoDetectSystem();
|
||||||
|
}
|
||||||
updateWindowTitle();
|
updateWindowTitle();
|
||||||
ImGui::CloseCurrentPopup();
|
ImGui::CloseCurrentPopup();
|
||||||
}
|
}
|
||||||
|
@ -110,6 +113,9 @@ void FurnaceGUI::drawSysManager() {
|
||||||
if (!e->addSystem(picked)) {
|
if (!e->addSystem(picked)) {
|
||||||
showError("cannot add chip! ("+e->getLastError()+")");
|
showError("cannot add chip! ("+e->getLastError()+")");
|
||||||
}
|
}
|
||||||
|
if (e->song.autoSystem) {
|
||||||
|
autoDetectSystem();
|
||||||
|
}
|
||||||
updateWindowTitle();
|
updateWindowTitle();
|
||||||
ImGui::CloseCurrentPopup();
|
ImGui::CloseCurrentPopup();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue