mirror of
https://github.com/tildearrow/furnace.git
synced 2024-11-26 14:33:01 +00:00
Merge branch 'master' into doc-general
This commit is contained in:
commit
9f53463ec2
47 changed files with 1800 additions and 143 deletions
BIN
demos/gameboy/freedom.fur
Normal file
BIN
demos/gameboy/freedom.fur
Normal file
Binary file not shown.
BIN
demos/gameboy/minos.fur
Normal file
BIN
demos/gameboy/minos.fur
Normal file
Binary file not shown.
BIN
demos/gameboy/spreadtro.fur
Normal file
BIN
demos/gameboy/spreadtro.fur
Normal file
Binary file not shown.
BIN
demos/multichip/track8_n163_k053260.fur
Normal file
BIN
demos/multichip/track8_n163_k053260.fur
Normal file
Binary file not shown.
|
@ -11,21 +11,19 @@ settings are saved when clicking the **OK** button at the bottom of the dialog.
|
|||
- **Render backend**
|
||||
- changing this may help with performace issues.
|
||||
- **Late render clear**
|
||||
- **Power-saving mode**
|
||||
- saves power by lowering the frame rate to 2fps when idle.
|
||||
- **Power-saving mode**: saves power by lowering the frame rate to 2fps when idle.
|
||||
- may cause issues under Mesa drivers!
|
||||
- **Disable threaded input (restart after changing!)**
|
||||
- threaded input processes key presses for note preview on a separate thread (on supported platforms), which reduces latency.
|
||||
- **Disable threaded input (restart after changing!)**: processes key presses for note preview on a separate thread (on supported platforms), which reduces latency.
|
||||
- however, crashes have been reported when threaded input is on. enable this option if that is the case.
|
||||
- **Enable event delay**
|
||||
- may cause issues with high-polling-rate mice when previewing notes.
|
||||
|
||||
### File
|
||||
|
||||
- **Use system file picker**: use native OS file dialog instead of Furnace's.
|
||||
- **Number of recent files**
|
||||
- **Use system file picker**: uses native OS file dialog instead of Furnace's.
|
||||
- **Number of recent files**: number of files to show in the _open recent..._ menu.
|
||||
- **Compress when saving**
|
||||
- use zlib to compress saved songs.
|
||||
- uses zlib to compress saved songs.
|
||||
- **Save unused patterns**
|
||||
- **Use new pattern format when saving**
|
||||
- **Don't apply compatibility flags when loading .dmf**
|
||||
|
@ -39,11 +37,11 @@ settings are saved when clicking the **OK** button at the bottom of the dialog.
|
|||
|
||||
- **Initial system**: the system of chips loaded on starting Furnace.
|
||||
- **Current system**: sets current chips as default.
|
||||
- **Randomize**: set default to a random system.
|
||||
- **Randomize**: sets default to a random system.
|
||||
- this will not choose a random system at each start.
|
||||
- **Reset to defaults**: sets default to "Sega Genesis/Mega Drive".
|
||||
- **Name**: name for the default system. may be set to any text.
|
||||
- system configuration: same as in the [chip manager](../8-advanced/chip-manager.md) and [mixer](../8-advanced/mixer.md).
|
||||
- **Configure:**: same as in the [chip manager](../8-advanced/chip-manager.md) and [mixer](../8-advanced/mixer.md).
|
||||
- **When creating new song**:
|
||||
- **Display system preset selector**
|
||||
- **Start with initial system**
|
||||
|
@ -70,12 +68,12 @@ settings are saved when clicking the **OK** button at the bottom of the dialog.
|
|||
|
||||
### Output
|
||||
|
||||
- **Backend**: select SDL or JACK for audio output.
|
||||
- **Backend**: selects SDL or JACK for audio output.
|
||||
- only appears on Linux, or MacOS compiled with JACK support
|
||||
- **Driver**
|
||||
- **Device**: audio device for playback.
|
||||
- **Sample rate**
|
||||
- **Outputs**: select number of audio outputs created, up to 16.
|
||||
- **Outputs**: number of audio outputs created, up to 16.
|
||||
- only appears when Backend is JACK.
|
||||
- **Channels**: number of output channels to use.
|
||||
- **Buffer size**: size of buffer in both samples and milliseconds.
|
||||
|
@ -209,8 +207,7 @@ settings are saved when clicking the **OK** button at the bottom of the dialog.
|
|||
- **Export**: writes current layout to a .ini file.
|
||||
- **Reset**: resets layout to default.
|
||||
- **Allow docking editors**
|
||||
- **Remember window position**
|
||||
- remembers the window's last position on start-up.
|
||||
- **Remember window position**: remembers the window's last position on start-up.
|
||||
- **Only allow window movement when clicking on title bar**
|
||||
- **Play/edit controls layout:**
|
||||
- **Classic**
|
||||
|
@ -236,7 +233,7 @@ settings are saved when clicking the **OK** button at the bottom of the dialog.
|
|||
- **No**
|
||||
- **Yes**
|
||||
- **Yes (while holding Ctrl only)**
|
||||
- **Toggle channel solo on:** select which interactions with a channel header will toggle solo for that channel.
|
||||
- **Toggle channel solo on:** selects which interactions with a channel header will toggle solo for that channel.
|
||||
- Right-click or double click
|
||||
- Right-click
|
||||
- Double-click
|
||||
|
@ -248,13 +245,15 @@ settings are saved when clicking the **OK** button at the bottom of the dialog.
|
|||
- **Pull delete affects entire channel row**
|
||||
- **Push value when overwriting instead of clearing it**: in the order list and pattern editors, typing into an already-filled value will shift digits instead of starting fresh.
|
||||
- if off: moving the cursor onto the value `A5` and typing a "B" results in `0B`.
|
||||
- if on: with the cursor on the value `A5` and typing a "B" results in `5B`.
|
||||
- if on: moving the cursor onto the value `A5` and typing a "B" results in `5B`.
|
||||
- **Effect input behavior:**
|
||||
- **Move down**
|
||||
- **Move to effect value (otherwise move down)**
|
||||
- **Move to effect value/next effect and wrap around**
|
||||
- **Delete effect value when deleting effect**
|
||||
- **Change current instrument when changing instrument column (absorb)**
|
||||
- **Remove instrument value when inserting note off/release**
|
||||
- **Remove volume value when inserting note off/release**
|
||||
|
||||
|
||||
### Cursor movement
|
||||
|
@ -293,16 +292,17 @@ settings are saved when clicking the **OK** button at the bottom of the dialog.
|
|||
|
||||
### Scaling
|
||||
|
||||
- **Automatic UI scaling factor**: automatically match the OS's UI scaling.
|
||||
- **UI scaling factor**: only if "Automatic UI scaling factor" is off.
|
||||
- **Automatic UI scaling factor**: automatically matches the OS's UI scaling.
|
||||
- **UI scaling factor**: only appears if "Automatic UI scaling factor" is off.
|
||||
- **Icon size**
|
||||
|
||||
### Text
|
||||
|
||||
- **Main font**: if "Custom...", a file path selector will appear beneath.
|
||||
- **Size**
|
||||
- **Pattern font**: if "Custom...", a file path selector will appear beneath.
|
||||
- **Size**
|
||||
- **Main font**: overall interface font.\
|
||||
**Header font**: font for section headers.\
|
||||
**Pattern font** font for the pattern view, the order list, and related.
|
||||
- if "Custom...", a file path selector will appear.
|
||||
- **Size**: font size.
|
||||
- **Display Japanese characters**\
|
||||
**Display Chinese (Simplified) characters**\
|
||||
**Display Chinese (Traditional) characters**\
|
||||
|
@ -358,7 +358,7 @@ settings are saved when clicking the **OK** button at the bottom of the dialog.
|
|||
|
||||
### Channel
|
||||
|
||||
- **Channel style:**
|
||||
- **Channel style:** sets the appearance of channel headers in pattern view.
|
||||
- **Classic**
|
||||
- **Line**
|
||||
- **Round**
|
||||
|
@ -428,11 +428,11 @@ settings are saved when clicking the **OK** button at the bottom of the dialog.
|
|||
- **Between Decay and Sustain Rate**
|
||||
- **After Release Rate**
|
||||
- **Use separate colors for carriers/modulators in FM editor**
|
||||
- **Unsigned FM detune values**
|
||||
- **Unsigned FM detune values**: uses the internal representation of detune values, such that detune amounts of -1, -2, and -3 are shown as 5, 6, and 7.
|
||||
|
||||
### Statistics
|
||||
|
||||
- **Chip memory usage unit:**
|
||||
- **Chip memory usage unit:** unit for displaying memory usage in the Statistics window.
|
||||
- **Bytes**
|
||||
- **Kilobytes**
|
||||
|
||||
|
@ -440,15 +440,20 @@ settings are saved when clicking the **OK** button at the bottom of the dialog.
|
|||
|
||||
- **Rounded corners**
|
||||
- **Border**
|
||||
- **Fill entire window**
|
||||
- **Waveform goes out of bounds**
|
||||
- **Mono**: displays a single monaural waveform of all sound mixed together.
|
||||
- if turned off, waves will be drawn on top of each other for each output channel.
|
||||
- all colors are configurable via _Settings > Color > Color scheme > Oscilloscope > Wave (non-mono)._
|
||||
- **Anti-aliased**: smoothes the lines of the waveform.
|
||||
- slight performance cost and slightly buggy.
|
||||
- **Fill entire window**: removes the gap between the waveform and the edge of the window.
|
||||
- **Waveform goes out of bounds**: allows the waveform to draw past the top and bottom of the oscilloscope.
|
||||
|
||||
### Windows
|
||||
|
||||
- **Rounded window corners**
|
||||
- **Rounded buttons**
|
||||
- **Rounded menu corners**
|
||||
- **Borders around widgets**
|
||||
- **Borders around widgets**: draws thin borders on buttons, checkboxes, text widgets, and the like.
|
||||
|
||||
|
||||
|
||||
|
|
4
extern/imgui_patched/imconfig.h
vendored
4
extern/imgui_patched/imconfig.h
vendored
|
@ -97,7 +97,9 @@
|
|||
// Your renderer backend will need to support it (most example renderer backends support both 16/32-bit indices).
|
||||
// Another way to allow large meshes while keeping 16-bit indices is to handle ImDrawCmd::VtxOffset in your renderer.
|
||||
// Read about ImGuiBackendFlags_RendererHasVtxOffset for details.
|
||||
//#define ImDrawIdx unsigned int
|
||||
#ifndef IS_MOBILE
|
||||
#define ImDrawIdx unsigned int
|
||||
#endif
|
||||
|
||||
//---- Override ImDrawCallback signature (will need to modify renderer backends accordingly)
|
||||
//struct ImDrawList;
|
||||
|
|
4
extern/imgui_patched/imconfig_fur.h
vendored
4
extern/imgui_patched/imconfig_fur.h
vendored
|
@ -96,7 +96,9 @@
|
|||
// Your renderer backend will need to support it (most example renderer backends support both 16/32-bit indices).
|
||||
// Another way to allow large meshes while keeping 16-bit indices is to handle ImDrawCmd::VtxOffset in your renderer.
|
||||
// Read about ImGuiBackendFlags_RendererHasVtxOffset for details.
|
||||
//#define ImDrawIdx unsigned int
|
||||
#ifndef IS_MOBILE
|
||||
#define ImDrawIdx unsigned int
|
||||
#endif
|
||||
|
||||
//---- Override ImDrawCallback signature (will need to modify renderer backends accordingly)
|
||||
//struct ImDrawList;
|
||||
|
|
19
extern/nfd-modified/src/nfd_win.cpp
vendored
19
extern/nfd-modified/src/nfd_win.cpp
vendored
|
@ -532,6 +532,9 @@ nfdresult_t NFD_OpenDialogMultiple( const std::vector<std::string>& filterList,
|
|||
nfdselcallback_t selCallback )
|
||||
{
|
||||
nfdresult_t nfdResult = NFD_ERROR;
|
||||
NFDWinEvents* winEvents;
|
||||
bool hasEvents=true;
|
||||
DWORD eventID=0;
|
||||
|
||||
|
||||
HRESULT coResult = COMInit();
|
||||
|
@ -566,6 +569,16 @@ nfdresult_t NFD_OpenDialogMultiple( const std::vector<std::string>& filterList,
|
|||
goto end;
|
||||
}
|
||||
|
||||
// Pass the callback
|
||||
winEvents=new NFDWinEvents(selCallback);
|
||||
if ( !SUCCEEDED(fileOpenDialog->Advise(winEvents,&eventID)) ) {
|
||||
// error... ignore
|
||||
hasEvents=false;
|
||||
winEvents->Release();
|
||||
} else {
|
||||
winEvents->Release();
|
||||
}
|
||||
|
||||
// Set a flag for multiple options
|
||||
DWORD dwFlags;
|
||||
result = fileOpenDialog->GetOptions(&dwFlags);
|
||||
|
@ -613,8 +626,12 @@ nfdresult_t NFD_OpenDialogMultiple( const std::vector<std::string>& filterList,
|
|||
}
|
||||
|
||||
end:
|
||||
if ( fileOpenDialog )
|
||||
if (fileOpenDialog) {
|
||||
if (hasEvents) {
|
||||
fileOpenDialog->Unadvise(eventID);
|
||||
}
|
||||
fileOpenDialog->Release();
|
||||
}
|
||||
|
||||
COMUninit(coResult);
|
||||
|
||||
|
|
1306
res/icons.sfd
Normal file
1306
res/icons.sfd
Normal file
File diff suppressed because it is too large
Load diff
BIN
res/icons.ttf
Normal file
BIN
res/icons.ttf
Normal file
Binary file not shown.
|
@ -485,6 +485,12 @@ class DivDispatch {
|
|||
*/
|
||||
virtual bool keyOffAffectsPorta(int ch);
|
||||
|
||||
/**
|
||||
* test whether volume is global.
|
||||
* @return whether it is.
|
||||
*/
|
||||
virtual bool isVolGlobal();
|
||||
|
||||
/**
|
||||
* get the lowest note in a portamento.
|
||||
* @param ch the channel in question.
|
||||
|
|
|
@ -216,13 +216,6 @@ void DivDispatchContainer::clear() {
|
|||
if (dispatch->getDCOffRequired()) {
|
||||
dcOffCompensation=true;
|
||||
}
|
||||
// run for one cycle to determine DC offset
|
||||
// TODO: SAA1099 doesn't like that
|
||||
/*dispatch->acquire(bbIn[0],bbIn[1],0,1);
|
||||
temp[0]=bbIn[0][0];
|
||||
temp[1]=bbIn[1][0];
|
||||
prevSample[0]=temp[0];
|
||||
prevSample[1]=temp[1];*/
|
||||
}
|
||||
|
||||
void DivDispatchContainer::init(DivSystem sys, DivEngine* eng, int chanCount, double gotRate, const DivConfig& flags) {
|
||||
|
@ -479,7 +472,7 @@ void DivDispatchContainer::init(DivSystem sys, DivEngine* eng, int chanCount, do
|
|||
break;
|
||||
case DIV_SYSTEM_NAMCO:
|
||||
dispatch=new DivPlatformNamcoWSG;
|
||||
// Pac-Man (TODO: support Pole Position?)
|
||||
// Pac-Man
|
||||
((DivPlatformNamcoWSG*)dispatch)->setDeviceType(1);
|
||||
break;
|
||||
case DIV_SYSTEM_NAMCO_15XX:
|
||||
|
|
|
@ -2346,7 +2346,7 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) {
|
|||
}
|
||||
}
|
||||
|
||||
if (ds.version>=136) song.patchbayAuto=reader.readC();
|
||||
if (ds.version>=136) ds.patchbayAuto=reader.readC();
|
||||
|
||||
if (ds.version>=138) {
|
||||
ds.brokenPortaLegato=reader.readC();
|
||||
|
|
|
@ -86,6 +86,10 @@ bool DivDispatch::keyOffAffectsPorta(int ch) {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool DivDispatch::isVolGlobal() {
|
||||
return false;
|
||||
}
|
||||
|
||||
int DivDispatch::getPortaFloor(int ch) {
|
||||
return 0x00;
|
||||
}
|
||||
|
|
|
@ -566,6 +566,10 @@ bool DivPlatformC64::getWantPreNote() {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool DivPlatformC64::isVolGlobal() {
|
||||
return true;
|
||||
}
|
||||
|
||||
float DivPlatformC64::getPostAmp() {
|
||||
return (sidCore==1)?3.0f:1.0f;
|
||||
}
|
||||
|
|
|
@ -105,6 +105,7 @@ class DivPlatformC64: public DivDispatch {
|
|||
void notifyInsChange(int ins);
|
||||
bool getDCOffRequired();
|
||||
bool getWantPreNote();
|
||||
bool isVolGlobal();
|
||||
float getPostAmp();
|
||||
DivMacroInt* getChanMacroInt(int ch);
|
||||
void notifyInsDeletion(void* ins);
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
|
||||
#define CHIP_FREQBASE 1180068
|
||||
|
||||
#define DRUM_VOL(_x) (drumActivated[_x]?drumVol[_x]:15)
|
||||
|
||||
const unsigned char cycleMapOPLL[18]={
|
||||
8, 7, 6, 7, 8, 7, 8, 6, 0, 1, 2, 7, 8, 9, 3, 4, 5, 9
|
||||
};
|
||||
|
@ -52,7 +54,7 @@ void DivPlatformOPLL::acquire_nuked(short** buf, size_t len) {
|
|||
QueuedWrite& w=writes.front();
|
||||
if (w.addrOrVal) {
|
||||
OPLL_Write(&fm,1,w.val);
|
||||
//printf("write: %x = %.2x\n",w.addr,w.val);
|
||||
//logV("write: %x = %.2x",w.addr,w.val);
|
||||
regPool[w.addr&0xff]=w.val;
|
||||
writes.pop();
|
||||
delay=21;
|
||||
|
@ -104,10 +106,10 @@ void DivPlatformOPLL::tick(bool sysTick) {
|
|||
|
||||
if (i>=6 && properDrums) {
|
||||
drumVol[i-6]=15-chan[i].outVol;
|
||||
rWrite(0x36,drumVol[0]);
|
||||
rWrite(0x37,drumVol[1]|(drumVol[4]<<4));
|
||||
rWrite(0x38,drumVol[3]|(drumVol[2]<<4));
|
||||
} else if (i<6 || !drums) {
|
||||
rWrite(0x36,DRUM_VOL(0));
|
||||
rWrite(0x37,DRUM_VOL(1)|(DRUM_VOL(4)<<4));
|
||||
rWrite(0x38,DRUM_VOL(3)|(DRUM_VOL(2)<<4));
|
||||
} else if (i<6 || !crapDrums) {
|
||||
if (i<9) {
|
||||
rWrite(0x30+i,((15-VOL_SCALE_LOG_BROKEN(chan[i].outVol,15-chan[i].state.op[1].tl,15))&15)|(chan[i].state.opllPreset<<4));
|
||||
}
|
||||
|
@ -230,16 +232,16 @@ void DivPlatformOPLL::tick(bool sysTick) {
|
|||
if (i>=6 && properDrums) {
|
||||
drumState&=~(0x10>>(i-6));
|
||||
immWrite(0x0e,0x20|drumState);
|
||||
logV("properDrums %d",i);
|
||||
} else if (i>=6 && drums) {
|
||||
//logV("properDrums %d",i);
|
||||
} else if (i>=6 && crapDrums) {
|
||||
drumState&=~(0x10>>(chan[i].note%12));
|
||||
immWrite(0x0e,0x20|drumState);
|
||||
logV("drums %d",i);
|
||||
//logV("drums %d",i);
|
||||
} else {
|
||||
if (i<9) {
|
||||
immWrite(0x20+i,(chan[i].freqH)|(chan[i].state.alg?0x20:0));
|
||||
}
|
||||
logV("normal %d",i);
|
||||
//logV("normal %d",i);
|
||||
}
|
||||
//chan[i].keyOn=false;
|
||||
chan[i].keyOff=false;
|
||||
|
@ -265,7 +267,21 @@ void DivPlatformOPLL::tick(bool sysTick) {
|
|||
if (i>=6 && properDrums && (i<9 || !noTopHatFreq)) {
|
||||
immWrite(0x10+drumSlot[i],freqt&0xff);
|
||||
immWrite(0x20+drumSlot[i],freqt>>8);
|
||||
} else if (i<6 || !drums) {
|
||||
switch (i) {
|
||||
case 7:
|
||||
lastFreqSH=0;
|
||||
break;
|
||||
case 8:
|
||||
lastFreqTT=0;
|
||||
break;
|
||||
case 9:
|
||||
lastFreqTT=1;
|
||||
break;
|
||||
case 19:
|
||||
lastFreqSH=1;
|
||||
break;
|
||||
}
|
||||
} else if (i<6 || !crapDrums) {
|
||||
if (i<9) {
|
||||
immWrite(0x10+i,freqt&0xff);
|
||||
}
|
||||
|
@ -278,7 +294,7 @@ void DivPlatformOPLL::tick(bool sysTick) {
|
|||
immWrite(0x0e,0x20|drumState);
|
||||
}
|
||||
chan[i].keyOn=false;
|
||||
} else if (chan[i].keyOn && i>=6 && drums) {
|
||||
} else if (chan[i].keyOn && i>=6 && crapDrums) {
|
||||
//printf("%d\n",chan[i].note%12);
|
||||
drumState|=(0x10>>(chan[i].note%12));
|
||||
immWrite(0x0e,0x20|drumState);
|
||||
|
@ -365,22 +381,24 @@ void DivPlatformOPLL::commitState(int ch, DivInstrument* ins) {
|
|||
}
|
||||
if (chan[ch].state.opllPreset==16) { // compatible drums mode
|
||||
if (ch>=6) {
|
||||
drums=true;
|
||||
immWrite(0x16,0x20);
|
||||
immWrite(0x26,0x05);
|
||||
immWrite(0x16,0x20);
|
||||
immWrite(0x26,0x05);
|
||||
immWrite(0x17,0x50);
|
||||
immWrite(0x27,0x05);
|
||||
immWrite(0x17,0x50);
|
||||
immWrite(0x27,0x05);
|
||||
immWrite(0x18,0xC0);
|
||||
immWrite(0x28,0x01);
|
||||
if (!properDrumsSys) {
|
||||
crapDrums=true;
|
||||
immWrite(0x16,0x20);
|
||||
immWrite(0x26,0x05);
|
||||
immWrite(0x16,0x20);
|
||||
immWrite(0x26,0x05);
|
||||
immWrite(0x17,0x50);
|
||||
immWrite(0x27,0x05);
|
||||
immWrite(0x17,0x50);
|
||||
immWrite(0x27,0x05);
|
||||
immWrite(0x18,0xC0);
|
||||
immWrite(0x28,0x01);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (ch>=6) {
|
||||
if (drums) {
|
||||
drums=false;
|
||||
if (crapDrums) {
|
||||
crapDrums=false;
|
||||
immWrite(0x0e,0);
|
||||
drumState=0;
|
||||
}
|
||||
|
@ -395,10 +413,40 @@ void DivPlatformOPLL::commitState(int ch, DivInstrument* ins) {
|
|||
void DivPlatformOPLL::switchMode(bool mode) {
|
||||
if (mode==properDrums) return;
|
||||
if (mode) {
|
||||
//logV("mode switch to DRUMS");
|
||||
for (int i=0; i<5; i++) {
|
||||
drumActivated[i]=chan[6+i].keyOn;
|
||||
}
|
||||
|
||||
immWrite(0x26,0);
|
||||
immWrite(0x27,0);
|
||||
immWrite(0x28,0);
|
||||
immWrite(0x16,0);
|
||||
immWrite(0x17,0);
|
||||
immWrite(0x18,0);
|
||||
immWrite(0x0e,0x20);
|
||||
rWrite(0x36,DRUM_VOL(0));
|
||||
rWrite(0x37,DRUM_VOL(1)|(DRUM_VOL(4)<<4));
|
||||
rWrite(0x38,DRUM_VOL(3)|(DRUM_VOL(2)<<4));
|
||||
oldWrites[0x36]=-1;
|
||||
oldWrites[0x37]=-1;
|
||||
oldWrites[0x38]=-1;
|
||||
} else {
|
||||
|
||||
//logV("mode switch to NORMAL");
|
||||
immWrite(0x0e,0x20);
|
||||
immWrite(0x0e,0x00);
|
||||
for (int i=6; i<9; i++) {
|
||||
if (chan[i].active) {
|
||||
chan[i].freqChanged=true;
|
||||
chan[i].keyOff=false;
|
||||
chan[i].keyOn=true;
|
||||
oldWrites[0x30+i]=-1;
|
||||
}
|
||||
chan[i].insChanged=true;
|
||||
}
|
||||
}
|
||||
properDrums=mode;
|
||||
drumState=0;
|
||||
}
|
||||
|
||||
int DivPlatformOPLL::dispatch(DivCommand c) {
|
||||
|
@ -417,18 +465,31 @@ int DivPlatformOPLL::dispatch(DivCommand c) {
|
|||
|
||||
if (c.chan>=6 && properDrums) { // drums mode
|
||||
chan[c.chan].insChanged=false;
|
||||
drumActivated[c.chan-6]=true;
|
||||
if (c.value!=DIV_NOTE_NULL) {
|
||||
if (chan[c.chan].state.opllPreset==16 && chan[c.chan].state.fixedDrums) {
|
||||
switch (c.chan) {
|
||||
case 6:
|
||||
chan[c.chan].fixedFreq=(chan[c.chan].state.kickFreq&511)<<(chan[c.chan].state.kickFreq>>9);
|
||||
break;
|
||||
case 7: case 10:
|
||||
chan[c.chan].fixedFreq=(chan[c.chan].state.snareHatFreq&511)<<(chan[c.chan].state.snareHatFreq>>9);
|
||||
break;
|
||||
case 8: case 9:
|
||||
chan[c.chan].fixedFreq=(chan[c.chan].state.tomTopFreq&511)<<(chan[c.chan].state.tomTopFreq>>9);
|
||||
break;
|
||||
if (fixedAll) {
|
||||
chan[6].fixedFreq=(chan[c.chan].state.kickFreq&511)<<(chan[c.chan].state.kickFreq>>9);
|
||||
chan[7].fixedFreq=(chan[c.chan].state.snareHatFreq&511)<<(chan[c.chan].state.snareHatFreq>>9);
|
||||
chan[8].fixedFreq=(chan[c.chan].state.tomTopFreq&511)<<(chan[c.chan].state.tomTopFreq>>9);
|
||||
chan[9].fixedFreq=(chan[c.chan].state.tomTopFreq&511)<<(chan[c.chan].state.tomTopFreq>>9);
|
||||
chan[10].fixedFreq=(chan[c.chan].state.snareHatFreq&511)<<(chan[c.chan].state.snareHatFreq>>9);
|
||||
|
||||
chan[7].freqChanged=true;
|
||||
chan[8].freqChanged=true;
|
||||
chan[9].freqChanged=true;
|
||||
} else {
|
||||
switch (c.chan) {
|
||||
case 6:
|
||||
chan[c.chan].fixedFreq=(chan[c.chan].state.kickFreq&511)<<(chan[c.chan].state.kickFreq>>9);
|
||||
break;
|
||||
case 7: case 10:
|
||||
chan[c.chan].fixedFreq=(chan[c.chan].state.snareHatFreq&511)<<(chan[c.chan].state.snareHatFreq>>9);
|
||||
break;
|
||||
case 8: case 9:
|
||||
chan[c.chan].fixedFreq=(chan[c.chan].state.tomTopFreq&511)<<(chan[c.chan].state.tomTopFreq>>9);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
chan[c.chan].baseFreq=NOTE_FREQUENCY(c.value);
|
||||
|
@ -438,6 +499,10 @@ int DivPlatformOPLL::dispatch(DivCommand c) {
|
|||
}
|
||||
chan[c.chan].keyOn=true;
|
||||
chan[c.chan].active=true;
|
||||
|
||||
rWrite(0x36,DRUM_VOL(0));
|
||||
rWrite(0x37,DRUM_VOL(1)|(DRUM_VOL(4)<<4));
|
||||
rWrite(0x38,DRUM_VOL(3)|(DRUM_VOL(2)<<4));
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -448,7 +513,7 @@ int DivPlatformOPLL::dispatch(DivCommand c) {
|
|||
chan[c.chan].baseFreq=NOTE_FREQUENCY(c.value);
|
||||
chan[c.chan].note=c.value;
|
||||
|
||||
if (c.chan>=6 && drums) {
|
||||
if (c.chan>=6 && crapDrums) {
|
||||
switch (chan[c.chan].note%12) {
|
||||
case 0: // kick
|
||||
drumVol[0]=(15-(chan[c.chan].outVol*(15-chan[c.chan].state.op[1].tl))/15);
|
||||
|
@ -466,9 +531,9 @@ int DivPlatformOPLL::dispatch(DivCommand c) {
|
|||
drumVol[4]=(15-(chan[c.chan].outVol*(15-chan[c.chan].state.op[1].tl))/15);
|
||||
break;
|
||||
}
|
||||
rWrite(0x36,drumVol[0]);
|
||||
rWrite(0x37,drumVol[1]|(drumVol[4]<<4));
|
||||
rWrite(0x38,drumVol[3]|(drumVol[2]<<4));
|
||||
rWrite(0x36,DRUM_VOL(0));
|
||||
rWrite(0x37,DRUM_VOL(1)|(DRUM_VOL(4)<<4));
|
||||
rWrite(0x38,DRUM_VOL(3)|(DRUM_VOL(2)<<4));
|
||||
}
|
||||
chan[c.chan].freqChanged=true;
|
||||
}
|
||||
|
@ -503,11 +568,11 @@ int DivPlatformOPLL::dispatch(DivCommand c) {
|
|||
}
|
||||
if (c.chan>=6 && properDrums) {
|
||||
drumVol[c.chan-6]=15-chan[c.chan].outVol;
|
||||
rWrite(0x36,drumVol[0]);
|
||||
rWrite(0x37,drumVol[1]|(drumVol[4]<<4));
|
||||
rWrite(0x38,drumVol[3]|(drumVol[2]<<4));
|
||||
rWrite(0x36,DRUM_VOL(0));
|
||||
rWrite(0x37,DRUM_VOL(1)|(DRUM_VOL(4)<<4));
|
||||
rWrite(0x38,DRUM_VOL(3)|(DRUM_VOL(2)<<4));
|
||||
break;
|
||||
} else if (c.chan<6 || !drums) {
|
||||
} else if (c.chan<6 || !crapDrums) {
|
||||
if (c.chan<9) {
|
||||
rWrite(0x30+c.chan,((15-VOL_SCALE_LOG_BROKEN(chan[c.chan].outVol,15-chan[c.chan].state.op[1].tl,15))&15)|(chan[c.chan].state.opllPreset<<4));
|
||||
}
|
||||
|
@ -565,7 +630,7 @@ int DivPlatformOPLL::dispatch(DivCommand c) {
|
|||
}
|
||||
case DIV_CMD_LEGATO: {
|
||||
if (c.chan>=9 && !properDrums) return 0;
|
||||
if (c.chan<6 || (!drums && !properDrums)) {
|
||||
if (c.chan<6 || (!crapDrums && !properDrums)) {
|
||||
if (chan[c.chan].insChanged) {
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_OPLL);
|
||||
commitState(c.chan,ins);
|
||||
|
@ -780,12 +845,7 @@ int DivPlatformOPLL::dispatch(DivCommand c) {
|
|||
case DIV_CMD_FM_EXTCH:
|
||||
if (!properDrumsSys) break;
|
||||
if ((int)properDrums==c.value) break;
|
||||
if (c.value) {
|
||||
properDrums=true;
|
||||
} else {
|
||||
properDrums=false;
|
||||
}
|
||||
switchMode(properDrums);
|
||||
switchMode(c.value);
|
||||
break;
|
||||
case DIV_CMD_MACRO_OFF:
|
||||
chan[c.chan].std.mask(c.value,true);
|
||||
|
@ -840,7 +900,7 @@ void DivPlatformOPLL::forceIns() {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (drums) { // WHAT?! FIX THIS!
|
||||
if (crapDrums) { // WHAT?! FIX THIS!
|
||||
immWrite(0x16,0x20);
|
||||
immWrite(0x26,0x05);
|
||||
immWrite(0x16,0x20);
|
||||
|
@ -852,11 +912,25 @@ void DivPlatformOPLL::forceIns() {
|
|||
immWrite(0x18,0xC0);
|
||||
immWrite(0x28,0x01);
|
||||
}
|
||||
// restore drum volumes
|
||||
// restore drum volumes and state
|
||||
if (properDrums) {
|
||||
rWrite(0x36,drumVol[0]);
|
||||
rWrite(0x37,drumVol[1]|(drumVol[4]<<4));
|
||||
rWrite(0x38,drumVol[3]|(drumVol[2]<<4));
|
||||
rWrite(0x36,DRUM_VOL(0));
|
||||
rWrite(0x37,DRUM_VOL(1)|(DRUM_VOL(4)<<4));
|
||||
rWrite(0x38,DRUM_VOL(3)|(DRUM_VOL(2)<<4));
|
||||
|
||||
if (lastFreqSH==0) {
|
||||
chan[7].freqChanged=true;
|
||||
} else if (lastFreqSH==1) {
|
||||
chan[10].freqChanged=true;
|
||||
}
|
||||
|
||||
if (lastFreqTT==0) {
|
||||
chan[8].freqChanged=true;
|
||||
} else if (lastFreqTT==1) {
|
||||
chan[9].freqChanged=true;
|
||||
}
|
||||
|
||||
chan[6].freqChanged=true;
|
||||
}
|
||||
drumState=0;
|
||||
}
|
||||
|
@ -937,16 +1011,18 @@ void DivPlatformOPLL::reset() {
|
|||
drumState=0;
|
||||
lastCustomMemory=-1;
|
||||
|
||||
drumVol[0]=0;
|
||||
drumVol[1]=0;
|
||||
drumVol[2]=0;
|
||||
drumVol[3]=0;
|
||||
drumVol[4]=0;
|
||||
for (int i=0; i<5; i++) {
|
||||
drumVol[i]=0;
|
||||
drumActivated[i]=true;
|
||||
}
|
||||
|
||||
delay=0;
|
||||
drums=false;
|
||||
crapDrums=false;
|
||||
properDrums=properDrumsSys;
|
||||
|
||||
lastFreqSH=-1;
|
||||
lastFreqTT=-1;
|
||||
|
||||
if (properDrums) {
|
||||
immWrite(0x0e,0x20);
|
||||
}
|
||||
|
@ -1012,6 +1088,7 @@ void DivPlatformOPLL::setFlags(const DivConfig& flags) {
|
|||
oscBuf[i]->rate=rate/2;
|
||||
}
|
||||
noTopHatFreq=flags.getBool("noTopHatFreq",false);
|
||||
fixedAll=flags.getBool("fixedAll",false);
|
||||
}
|
||||
|
||||
int DivPlatformOPLL::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) {
|
||||
|
|
|
@ -59,12 +59,18 @@ class DivPlatformOPLL: public DivDispatch {
|
|||
unsigned char lastBusy;
|
||||
unsigned char drumState;
|
||||
unsigned char drumVol[5];
|
||||
bool drumActivated[5];
|
||||
|
||||
// -1: undefined
|
||||
// 0: snare/tom
|
||||
// 1: hi-hat/top
|
||||
signed char lastFreqSH, lastFreqTT;
|
||||
|
||||
unsigned char regPool[256];
|
||||
|
||||
bool useYMFM;
|
||||
bool drums;
|
||||
bool properDrums, properDrumsSys, noTopHatFreq;
|
||||
bool crapDrums;
|
||||
bool properDrums, properDrumsSys, noTopHatFreq, fixedAll;
|
||||
bool vrc7;
|
||||
|
||||
unsigned char patchSet;
|
||||
|
|
|
@ -257,6 +257,10 @@ void DivPlatformTED::forceIns() {
|
|||
updateCtrl=true;
|
||||
}
|
||||
|
||||
bool DivPlatformTED::isVolGlobal() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void* DivPlatformTED::getChanState(int ch) {
|
||||
return &chan[ch];
|
||||
}
|
||||
|
|
|
@ -54,6 +54,7 @@ class DivPlatformTED: public DivDispatch {
|
|||
public:
|
||||
void acquire(short** buf, size_t len);
|
||||
int dispatch(DivCommand c);
|
||||
bool isVolGlobal();
|
||||
void* getChanState(int chan);
|
||||
DivMacroInt* getChanMacroInt(int ch);
|
||||
DivDispatchOscBuffer* getOscBuffer(int chan);
|
||||
|
|
|
@ -278,6 +278,10 @@ void DivPlatformVIC20::forceIns() {
|
|||
}
|
||||
}
|
||||
|
||||
bool DivPlatformVIC20::isVolGlobal() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void* DivPlatformVIC20::getChanState(int ch) {
|
||||
return &chan[ch];
|
||||
}
|
||||
|
|
|
@ -46,6 +46,7 @@ class DivPlatformVIC20: public DivDispatch {
|
|||
public:
|
||||
void acquire(short** buf, size_t len);
|
||||
int dispatch(DivCommand c);
|
||||
bool isVolGlobal();
|
||||
void* getChanState(int chan);
|
||||
DivMacroInt* getChanMacroInt(int ch);
|
||||
DivDispatchOscBuffer* getOscBuffer(int chan);
|
||||
|
|
|
@ -1307,7 +1307,7 @@ bool DivEngine::nextTick(bool noAccum, bool inhibitLowLat) {
|
|||
} else {
|
||||
DivMacroInt* macroInt=disCont[dispatchOfChan[note.channel]].dispatch->getChanMacroInt(dispatchChanOfChan[note.channel]);
|
||||
if (macroInt!=NULL) {
|
||||
if (macroInt->hasRelease) {
|
||||
if (macroInt->hasRelease && !disCont[dispatchOfChan[note.channel]].dispatch->isVolGlobal()) {
|
||||
dispatchCmd(DivCommand(DIV_CMD_NOTE_OFF_ENV,note.channel));
|
||||
} else {
|
||||
dispatchCmd(DivCommand(DIV_CMD_NOTE_OFF,note.channel));
|
||||
|
|
|
@ -131,6 +131,7 @@ void FurnaceGUI::drawChanOsc() {
|
|||
if (ImGui::BeginTable("ChanOscSettings",3)) {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Columns");
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
|
@ -154,6 +155,7 @@ void FurnaceGUI::drawChanOsc() {
|
|||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Automatic columns");
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
|
@ -169,6 +171,7 @@ void FurnaceGUI::drawChanOsc() {
|
|||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Amplitude");
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
|
@ -261,6 +264,7 @@ void FurnaceGUI::drawChanOsc() {
|
|||
if (ImGui::ColorPicker4("Color",(float*)&i.color)) {
|
||||
updateChanOscGradTex=true;
|
||||
}
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Distance");
|
||||
ImGui::SameLine();
|
||||
float pDist=i.distance*100.0f;
|
||||
|
@ -269,6 +273,7 @@ void FurnaceGUI::drawChanOsc() {
|
|||
updateChanOscGradTex=true;
|
||||
}
|
||||
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Spread");
|
||||
ImGui::SameLine();
|
||||
float pSpread=i.spread*100.0f;
|
||||
|
@ -313,6 +318,7 @@ void FurnaceGUI::drawChanOsc() {
|
|||
ImGui::ColorPicker4("Color",(float*)&chanOscColor);
|
||||
}
|
||||
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Text format:");
|
||||
ImGui::SameLine();
|
||||
ImGui::InputText("##TextFormat",&chanOscTextFormat);
|
||||
|
|
|
@ -199,6 +199,7 @@ void FurnaceGUI::drawCompatFlags() {
|
|||
}
|
||||
if (ImGui::BeginTabItem("Pitch/Playback")) {
|
||||
ImGui::Text("Pitch linearity:");
|
||||
ImGui::Indent();
|
||||
if (ImGui::RadioButton("None",e->song.linearPitch==0)) {
|
||||
e->song.linearPitch=0;
|
||||
}
|
||||
|
@ -217,6 +218,7 @@ void FurnaceGUI::drawCompatFlags() {
|
|||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("like Impulse Tracker");
|
||||
}
|
||||
ImGui::Unindent();
|
||||
|
||||
if (e->song.linearPitch==2) {
|
||||
ImGui::SameLine();
|
||||
|
@ -228,6 +230,7 @@ void FurnaceGUI::drawCompatFlags() {
|
|||
}
|
||||
|
||||
ImGui::Text("Loop modality:");
|
||||
ImGui::Indent();
|
||||
if (ImGui::RadioButton("Reset channels",e->song.loopModality==0)) {
|
||||
e->song.loopModality=0;
|
||||
}
|
||||
|
@ -246,8 +249,10 @@ void FurnaceGUI::drawCompatFlags() {
|
|||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("select to not reset channels on loop.");
|
||||
}
|
||||
ImGui::Unindent();
|
||||
|
||||
ImGui::Text("Cut/delay effect policy:");
|
||||
ImGui::Indent();
|
||||
if (ImGui::RadioButton("Strict",e->song.delayBehavior==0)) {
|
||||
e->song.delayBehavior=0;
|
||||
}
|
||||
|
@ -266,8 +271,10 @@ void FurnaceGUI::drawCompatFlags() {
|
|||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("no checks");
|
||||
}
|
||||
ImGui::Unindent();
|
||||
|
||||
ImGui::Text("Simultaneous jump (0B+0D) treatment:");
|
||||
ImGui::Indent();
|
||||
if (ImGui::RadioButton("Normal",e->song.jumpTreatment==0)) {
|
||||
e->song.jumpTreatment=0;
|
||||
}
|
||||
|
@ -286,6 +293,7 @@ void FurnaceGUI::drawCompatFlags() {
|
|||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("only accept 0Dxx");
|
||||
}
|
||||
ImGui::Unindent();
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
if (ImGui::BeginTabItem("Other")) {
|
||||
|
|
|
@ -486,6 +486,7 @@ void FurnaceGUI::drawDebug() {
|
|||
pgProgram.clear();
|
||||
}
|
||||
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Address");
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(100.0f*dpiScale);
|
||||
|
|
|
@ -589,14 +589,34 @@ void FurnaceGUI::doAction(int what) {
|
|||
case GUI_ACTION_PAT_EXPAND_SONG:
|
||||
doExpandSong(collapseAmount);
|
||||
break;
|
||||
case GUI_ACTION_PAT_LATCH: // TODO
|
||||
case GUI_ACTION_PAT_LATCH: {
|
||||
DivPattern* pat=e->curPat[cursor.xCoarse].getPattern(e->curOrders->ord[cursor.xCoarse][curOrder],true);
|
||||
latchIns=pat->data[cursor.y][2];
|
||||
latchVol=pat->data[cursor.y][3];
|
||||
latchEffect=pat->data[cursor.y][4];
|
||||
latchEffectVal=pat->data[cursor.y][5];
|
||||
latchTarget=0;
|
||||
latchNibble=false;
|
||||
break;
|
||||
case GUI_ACTION_PAT_SCROLL_MODE: // TODO
|
||||
break;
|
||||
case GUI_ACTION_PAT_CLEAR_LATCH: // TODO
|
||||
}
|
||||
case GUI_ACTION_PAT_CLEAR_LATCH:
|
||||
latchIns=-2;
|
||||
latchVol=-1;
|
||||
latchEffect=-1;
|
||||
latchEffectVal=-1;
|
||||
latchTarget=0;
|
||||
latchNibble=false;
|
||||
break;
|
||||
|
||||
case GUI_ACTION_INS_LIST_ADD:
|
||||
if (settings.insTypeMenu) {
|
||||
makeInsTypeList=e->getPossibleInsTypes();
|
||||
if (makeInsTypeList.size()>1) {
|
||||
displayInsTypeList=true;
|
||||
displayInsTypeListMakeInsSample=-1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
curIns=e->addInstrument(cursor.xCoarse);
|
||||
if (curIns==-1) {
|
||||
showError("too many instruments!");
|
||||
|
@ -1265,7 +1285,7 @@ void FurnaceGUI::doAction(int what) {
|
|||
} else if (sample->depth==DIV_SAMPLE_DEPTH_8BIT) {
|
||||
for (unsigned int i=start; i<end; i++) {
|
||||
sample->data8[i]=-sample->data8[i];
|
||||
if (sample->data16[i]==-128) sample->data16[i]=127;
|
||||
if (sample->data8[i]==-128) sample->data8[i]=127;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -619,6 +619,7 @@ void FurnaceGUI::drawMobileControls() {
|
|||
"Furnace Amiga emulator is working properly by\n"
|
||||
"comparing it with real Amiga output."
|
||||
);
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Directory");
|
||||
ImGui::SameLine();
|
||||
ImGui::InputText("##AVDPath",&workingDirROMExport);
|
||||
|
@ -717,6 +718,7 @@ void FurnaceGUI::drawEditControls() {
|
|||
e->setMetronome(metro);
|
||||
}
|
||||
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Follow");
|
||||
ImGui::SameLine();
|
||||
unimportant(ImGui::Checkbox("Orders",&followOrders));
|
||||
|
@ -1063,6 +1065,7 @@ void FurnaceGUI::drawEditControls() {
|
|||
|
||||
if (ImGui::Begin("Edit Controls",&editControlsOpen,globalWinFlags)) {
|
||||
ImGui::Columns(2);
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Octave");
|
||||
ImGui::SameLine();
|
||||
float cursor=ImGui::GetCursorPosX();
|
||||
|
@ -1078,6 +1081,7 @@ void FurnaceGUI::drawEditControls() {
|
|||
}
|
||||
}
|
||||
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Step");
|
||||
ImGui::SameLine();
|
||||
ImGui::SetCursorPosX(cursor);
|
||||
|
|
|
@ -68,7 +68,7 @@ void FurnaceGUI::prepareUndo(ActionType action) {
|
|||
}
|
||||
break;
|
||||
case GUI_UNDO_PATTERN_COLLAPSE_SONG:
|
||||
case GUI_UNDO_PATTERN_EXPAND_SONG: // TODO
|
||||
case GUI_UNDO_PATTERN_EXPAND_SONG: // this is handled by doCollapseSong/doExpandSong
|
||||
break;
|
||||
case GUI_UNDO_REPLACE: // this is handled by doReplace()
|
||||
break;
|
||||
|
@ -134,7 +134,7 @@ void FurnaceGUI::makeUndo(ActionType action) {
|
|||
}
|
||||
break;
|
||||
case GUI_UNDO_PATTERN_COLLAPSE_SONG:
|
||||
case GUI_UNDO_PATTERN_EXPAND_SONG: // TODO
|
||||
case GUI_UNDO_PATTERN_EXPAND_SONG: // this is handled by doCollapseSong/doExpandSong
|
||||
break;
|
||||
case GUI_UNDO_REPLACE: // this is handled by doReplace()
|
||||
break;
|
||||
|
|
|
@ -47,22 +47,56 @@ void FurnaceGUI::drawEffectList() {
|
|||
const char* prevName=NULL;
|
||||
for (int i=0; i<256; i++) {
|
||||
const char* name=e->getEffectDesc(i,cursor.xCoarse);
|
||||
bool effectShow = true;
|
||||
bool effectShow=true;
|
||||
if (name==prevName) {
|
||||
continue;
|
||||
}
|
||||
prevName=name;
|
||||
switch (fxColors[i]) {
|
||||
case GUI_COLOR_PATTERN_EFFECT_MISC: effectShow = effectsShow[8]; break;
|
||||
case GUI_COLOR_PATTERN_EFFECT_SONG: effectShow = effectsShow[1]; break;
|
||||
case GUI_COLOR_PATTERN_EFFECT_SPEED: effectShow = effectsShow[3]; break;
|
||||
case GUI_COLOR_PATTERN_EFFECT_TIME: effectShow = effectsShow[2]; break;
|
||||
case GUI_COLOR_PATTERN_EFFECT_PITCH: effectShow = effectsShow[0]; break;
|
||||
case GUI_COLOR_PATTERN_EFFECT_PANNING: effectShow = effectsShow[4]; break;
|
||||
case GUI_COLOR_PATTERN_EFFECT_VOLUME: effectShow = effectsShow[5]; break;
|
||||
case GUI_COLOR_PATTERN_EFFECT_SYS_PRIMARY: effectShow = effectsShow[6]; break;
|
||||
case GUI_COLOR_PATTERN_EFFECT_SYS_SECONDARY: effectShow = effectsShow[7]; break;
|
||||
default: effectShow = true; break;
|
||||
case GUI_COLOR_PATTERN_EFFECT_MISC:
|
||||
effectShow=effectsShow[8];
|
||||
break;
|
||||
case GUI_COLOR_PATTERN_EFFECT_SONG:
|
||||
effectShow=effectsShow[1];
|
||||
break;
|
||||
case GUI_COLOR_PATTERN_EFFECT_SPEED:
|
||||
effectShow=effectsShow[3];
|
||||
break;
|
||||
case GUI_COLOR_PATTERN_EFFECT_TIME:
|
||||
effectShow=effectsShow[2];
|
||||
break;
|
||||
case GUI_COLOR_PATTERN_EFFECT_PITCH:
|
||||
effectShow=effectsShow[0];
|
||||
break;
|
||||
case GUI_COLOR_PATTERN_EFFECT_PANNING:
|
||||
effectShow=effectsShow[4];
|
||||
break;
|
||||
case GUI_COLOR_PATTERN_EFFECT_VOLUME:
|
||||
effectShow=effectsShow[5];
|
||||
break;
|
||||
case GUI_COLOR_PATTERN_EFFECT_SYS_PRIMARY:
|
||||
effectShow=effectsShow[6];
|
||||
break;
|
||||
case GUI_COLOR_PATTERN_EFFECT_SYS_SECONDARY:
|
||||
effectShow=effectsShow[7];
|
||||
break;
|
||||
default:
|
||||
effectShow=true;
|
||||
break;
|
||||
}
|
||||
if (fxColors[i]==GUI_COLOR_PATTERN_EFFECT_PANNING) {
|
||||
DivDispatch* dispatch=e->getDispatch(e->dispatchOfChan[cursor.xCoarse]);
|
||||
if (dispatch!=NULL) {
|
||||
int outputs=dispatch->getOutputCount();
|
||||
if (outputs<2) {
|
||||
effectShow=false;
|
||||
}
|
||||
if (outputs<3) {
|
||||
if (i>=0x88 && i<=0x8f) {
|
||||
effectShow=false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (name!=NULL && effectShow) {
|
||||
ImGui::TableNextRow();
|
||||
|
|
|
@ -28,7 +28,6 @@ struct NFDState {
|
|||
}
|
||||
};
|
||||
|
||||
// TODO: filter
|
||||
void _nfdThread(const NFDState state, std::atomic<bool>* ok, std::vector<String>* result, bool* errorOutput) {
|
||||
nfdchar_t* out=NULL;
|
||||
nfdresult_t ret=NFD_CANCEL;
|
||||
|
|
|
@ -595,6 +595,7 @@ void FurnaceGUI::drawFindReplace() {
|
|||
ImGui::TableSetupColumn("c3",ImGuiTableColumnFlags_WidthStretch,0.25);
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Note");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
|
@ -662,6 +663,7 @@ void FurnaceGUI::drawFindReplace() {
|
|||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Ins");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
|
@ -697,6 +699,7 @@ void FurnaceGUI::drawFindReplace() {
|
|||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Volume");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
|
@ -734,6 +737,7 @@ void FurnaceGUI::drawFindReplace() {
|
|||
ImGui::PushID(0x1000+j);
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Effect");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
|
@ -769,6 +773,7 @@ void FurnaceGUI::drawFindReplace() {
|
|||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Value");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
|
|
|
@ -77,6 +77,14 @@ bool Particle::update(float frameTime) {
|
|||
return (life>0);
|
||||
}
|
||||
|
||||
void FurnaceGUI::centerNextWindow(const char* name, float w, float h) {
|
||||
if (ImGui::IsPopupOpen(name)) {
|
||||
if (settings.centerPopup) {
|
||||
ImGui::SetNextWindowPos(ImVec2(w*0.5,h*0.5),ImGuiCond_Always,ImVec2(0.5,0.5));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FurnaceGUI::bindEngine(DivEngine* eng) {
|
||||
e=eng;
|
||||
wavePreview.setEngine(e);
|
||||
|
@ -2783,6 +2791,7 @@ void FurnaceGUI::editOptions(bool topMenu) {
|
|||
if (ImGui::MenuItem("values up (+16)",BIND_FOR(GUI_ACTION_PAT_VALUE_UP_COARSE))) doTranspose(16,opMaskTransposeValue);
|
||||
if (ImGui::MenuItem("values down (-16)",BIND_FOR(GUI_ACTION_PAT_VALUE_DOWN_COARSE))) doTranspose(-16,opMaskTransposeValue);
|
||||
ImGui::Separator();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("transpose");
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(120.0f*dpiScale);
|
||||
|
@ -3918,7 +3927,7 @@ bool FurnaceGUI::loop() {
|
|||
|
||||
if (!mobileUI) {
|
||||
ImGui::BeginMainMenuBar();
|
||||
if (ImGui::BeginMenu("file")) {
|
||||
if (ImGui::BeginMenu(settings.capitalMenuBar?"File":"file")) {
|
||||
if (ImGui::MenuItem("new...",BIND_FOR(GUI_ACTION_NEW))) {
|
||||
if (modified) {
|
||||
showWarning("Unsaved changes! Save changes before creating a new song?",GUI_WARN_NEW);
|
||||
|
@ -4013,6 +4022,7 @@ bool FurnaceGUI::loop() {
|
|||
ImGui::Checkbox("loop",&vgmExportLoop);
|
||||
if (vgmExportLoop && e->song.loopModality==2) {
|
||||
ImGui::Text("loop trail:");
|
||||
ImGui::Indent();
|
||||
if (ImGui::RadioButton("auto-detect",vgmExportTrailingTicks==-1)) {
|
||||
vgmExportTrailingTicks=-1;
|
||||
}
|
||||
|
@ -4028,6 +4038,7 @@ bool FurnaceGUI::loop() {
|
|||
if (vgmExportTrailingTicks<0) vgmExportTrailingTicks=0;
|
||||
}
|
||||
}
|
||||
ImGui::Unindent();
|
||||
}
|
||||
ImGui::Checkbox("add pattern change hints",&vgmExportPatternHints);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
|
@ -4116,6 +4127,7 @@ bool FurnaceGUI::loop() {
|
|||
"Furnace Amiga emulator is working properly by\n"
|
||||
"comparing it with real Amiga output."
|
||||
);
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Directory");
|
||||
ImGui::SameLine();
|
||||
ImGui::InputText("##AVDPath",&workingDirROMExport);
|
||||
|
@ -4241,7 +4253,7 @@ bool FurnaceGUI::loop() {
|
|||
} else {
|
||||
exitDisabledTimer=0;
|
||||
}
|
||||
if (ImGui::BeginMenu("edit")) {
|
||||
if (ImGui::BeginMenu(settings.capitalMenuBar?"Edit":"edit")) {
|
||||
ImGui::Text("...");
|
||||
ImGui::Separator();
|
||||
if (ImGui::MenuItem("undo",BIND_FOR(GUI_ACTION_UNDO))) doUndo();
|
||||
|
@ -4254,7 +4266,7 @@ bool FurnaceGUI::loop() {
|
|||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
if (ImGui::BeginMenu("settings")) {
|
||||
if (ImGui::BeginMenu(settings.capitalMenuBar?"Settings":"settings")) {
|
||||
#ifndef IS_MOBILE
|
||||
if (ImGui::MenuItem("full screen",BIND_FOR(GUI_ACTION_FULLSCREEN),fullScreen)) {
|
||||
doAction(GUI_ACTION_FULLSCREEN);
|
||||
|
@ -4290,7 +4302,7 @@ bool FurnaceGUI::loop() {
|
|||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
if (ImGui::BeginMenu("window")) {
|
||||
if (ImGui::BeginMenu(settings.capitalMenuBar?"Window":"window")) {
|
||||
if (ImGui::MenuItem("song information",BIND_FOR(GUI_ACTION_WINDOW_SONG_INFO),songInfoOpen)) songInfoOpen=!songInfoOpen;
|
||||
if (ImGui::MenuItem("subsongs",BIND_FOR(GUI_ACTION_WINDOW_SUBSONGS),subSongsOpen)) subSongsOpen=!subSongsOpen;
|
||||
if (ImGui::MenuItem("speed",BIND_FOR(GUI_ACTION_WINDOW_SPEED),speedOpen)) speedOpen=!speedOpen;
|
||||
|
@ -4332,7 +4344,7 @@ bool FurnaceGUI::loop() {
|
|||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
if (ImGui::BeginMenu("help")) {
|
||||
if (ImGui::BeginMenu(settings.capitalMenuBar?"Help":"help")) {
|
||||
if (ImGui::MenuItem("effect list",BIND_FOR(GUI_ACTION_WINDOW_EFFECT_LIST),effectListOpen)) effectListOpen=!effectListOpen;
|
||||
if (ImGui::MenuItem("debug menu",BIND_FOR(GUI_ACTION_WINDOW_DEBUG))) debugOpen=!debugOpen;
|
||||
if (ImGui::MenuItem("inspector",BIND_FOR(GUI_ACTION_WINDOW_DEBUG))) inspectorOpen=!inspectorOpen;
|
||||
|
@ -5233,6 +5245,7 @@ bool FurnaceGUI::loop() {
|
|||
|
||||
MEASURE_BEGIN(popup);
|
||||
|
||||
centerNextWindow("Rendering...",canvasW,canvasH);
|
||||
if (ImGui::BeginPopupModal("Rendering...",NULL,ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
ImGui::Text("Please wait...");
|
||||
if (ImGui::Button("Abort")) {
|
||||
|
@ -5260,6 +5273,7 @@ bool FurnaceGUI::loop() {
|
|||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
centerNextWindow("Error",canvasW,canvasH);
|
||||
if (ImGui::BeginPopupModal("Error",NULL,ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
ImGui::Text("%s",errorString.c_str());
|
||||
if (ImGui::Button("OK")) {
|
||||
|
@ -5268,6 +5282,7 @@ bool FurnaceGUI::loop() {
|
|||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
centerNextWindow("Warning",canvasW,canvasH);
|
||||
if (ImGui::BeginPopupModal("Warning",NULL,ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
ImGui::Text("%s",warnString.c_str());
|
||||
switch (warnAction) {
|
||||
|
@ -5626,6 +5641,19 @@ bool FurnaceGUI::loop() {
|
|||
wavePreviewInit=true;
|
||||
updateFMPreview=true;
|
||||
}
|
||||
|
||||
if (settings.blankIns) {
|
||||
e->song.ins[curIns]->fm.fb=0;
|
||||
for (int i=0; i<4; i++) {
|
||||
e->song.ins[curIns]->fm.op[i]=DivInstrumentFM::Operator();
|
||||
e->song.ins[curIns]->fm.op[i].ar=31;
|
||||
e->song.ins[curIns]->fm.op[i].dr=31;
|
||||
e->song.ins[curIns]->fm.op[i].rr=15;
|
||||
e->song.ins[curIns]->fm.op[i].tl=127;
|
||||
e->song.ins[curIns]->fm.op[i].dt=3;
|
||||
}
|
||||
}
|
||||
|
||||
MARK_MODIFIED;
|
||||
}
|
||||
}
|
||||
|
@ -5636,11 +5664,13 @@ bool FurnaceGUI::loop() {
|
|||
// TODO:
|
||||
// - multiple selection
|
||||
// - replace instrument
|
||||
centerNextWindow("Select Instrument",canvasW,canvasH);
|
||||
if (ImGui::BeginPopupModal("Select Instrument",NULL,ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
bool quitPlease=false;
|
||||
if (pendingInsSingle) {
|
||||
ImGui::Text("this is an instrument bank! select which one to use:");
|
||||
} else {
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("this is an instrument bank! select which ones to load:");
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("All")) {
|
||||
|
@ -5713,6 +5743,7 @@ bool FurnaceGUI::loop() {
|
|||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
centerNextWindow("Import Raw Sample",canvasW,canvasH);
|
||||
if (ImGui::BeginPopupModal("Import Raw Sample",NULL,ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
ImGui::Text("Data type:");
|
||||
for (int i=0; i<DIV_SAMPLE_DEPTH_MAX; i++) {
|
||||
|
@ -5728,6 +5759,7 @@ bool FurnaceGUI::loop() {
|
|||
}
|
||||
|
||||
ImGui::BeginDisabled(pendingRawSampleDepth!=DIV_SAMPLE_DEPTH_8BIT && pendingRawSampleDepth!=DIV_SAMPLE_DEPTH_16BIT);
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Channels");
|
||||
ImGui::SameLine();
|
||||
if (ImGui::InputInt("##RSChans",&pendingRawSampleChannels)) {
|
||||
|
|
|
@ -1548,6 +1548,9 @@ class FurnaceGUI {
|
|||
int removeInsOff;
|
||||
int removeVolOff;
|
||||
int playOnLoad;
|
||||
int insTypeMenu;
|
||||
int capitalMenuBar;
|
||||
int centerPopup;
|
||||
unsigned int maxUndoSteps;
|
||||
String mainFontPath;
|
||||
String headFontPath;
|
||||
|
@ -1710,6 +1713,9 @@ class FurnaceGUI {
|
|||
removeInsOff(0),
|
||||
removeVolOff(0),
|
||||
playOnLoad(0),
|
||||
insTypeMenu(1),
|
||||
capitalMenuBar(0),
|
||||
centerPopup(1),
|
||||
maxUndoSteps(100),
|
||||
mainFontPath(""),
|
||||
headFontPath(""),
|
||||
|
@ -2135,6 +2141,8 @@ class FurnaceGUI {
|
|||
ImVec4 channelColor(int ch);
|
||||
ImVec4 channelTextColor(int ch);
|
||||
|
||||
void centerNextWindow(const char* name, float w, float h);
|
||||
|
||||
void readOsc();
|
||||
void calcChanOsc();
|
||||
|
||||
|
|
|
@ -4264,6 +4264,7 @@ void FurnaceGUI::drawInsEdit() {
|
|||
ImGui::EndTabItem();
|
||||
}
|
||||
if (ins->type==DIV_INS_C64) if (ImGui::BeginTabItem("C64")) {
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Waveform");
|
||||
ImGui::SameLine();
|
||||
pushToggleColors(ins->c64.triOn);
|
||||
|
@ -4348,6 +4349,7 @@ void FurnaceGUI::drawInsEdit() {
|
|||
P(CWSliderScalar("Cutoff",ImGuiDataType_U16,&ins->c64.cut,&_ZERO,&_TWO_THOUSAND_FORTY_SEVEN)); rightClickable
|
||||
P(CWSliderScalar("Resonance",ImGuiDataType_U8,&ins->c64.res,&_ZERO,&_FIFTEEN)); rightClickable
|
||||
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Filter Mode");
|
||||
ImGui::SameLine();
|
||||
pushToggleColors(ins->c64.lp);
|
||||
|
@ -5250,6 +5252,7 @@ void FurnaceGUI::drawInsEdit() {
|
|||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Wave 1");
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
|
@ -5260,6 +5263,7 @@ void FurnaceGUI::drawInsEdit() {
|
|||
}
|
||||
if (isSingleWaveFX) {
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Wave 2");
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
|
|
|
@ -244,6 +244,7 @@ void FurnaceGUI::drawMixer() {
|
|||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("%d. %s",i+1,getSystemName(e->song.system[i]));
|
||||
ImGui::TableNextColumn();
|
||||
if (ImGui::Checkbox("Invert",&doInvert)) {
|
||||
|
|
|
@ -100,6 +100,7 @@ void FurnaceGUI::drawPiano() {
|
|||
}
|
||||
if (ImGui::BeginPopupContextItem("PianoOptions",ImGuiPopupFlags_MouseButtonLeft)) {
|
||||
ImGui::Text("Key layout:");
|
||||
ImGui::Indent();
|
||||
if (ImGui::RadioButton("Automatic",pianoView==PIANO_LAYOUT_AUTOMATIC)) {
|
||||
pianoView=PIANO_LAYOUT_AUTOMATIC;
|
||||
}
|
||||
|
@ -109,7 +110,9 @@ void FurnaceGUI::drawPiano() {
|
|||
if (ImGui::RadioButton("Continuous",pianoView==PIANO_LAYOUT_CONTINUOUS)) {
|
||||
pianoView=PIANO_LAYOUT_CONTINUOUS;
|
||||
}
|
||||
ImGui::Unindent();
|
||||
ImGui::Text("Value input pad:");
|
||||
ImGui::Indent();
|
||||
if (ImGui::RadioButton("Disabled",pianoInputPadMode==PIANO_INPUT_PAD_DISABLE)) {
|
||||
pianoInputPadMode=PIANO_INPUT_PAD_DISABLE;
|
||||
}
|
||||
|
@ -122,6 +125,7 @@ void FurnaceGUI::drawPiano() {
|
|||
if (ImGui::RadioButton("Split (always visible)",pianoInputPadMode==PIANO_INPUT_PAD_SPLIT_VISIBLE)) {
|
||||
pianoInputPadMode=PIANO_INPUT_PAD_SPLIT_VISIBLE;
|
||||
}
|
||||
ImGui::Unindent();
|
||||
ImGui::Checkbox("Share play/edit offset/range",&pianoSharePosition);
|
||||
ImGui::Checkbox("Read-only (can't input notes)",&pianoReadonly);
|
||||
ImGui::EndPopup();
|
||||
|
@ -377,7 +381,6 @@ void FurnaceGUI::drawPiano() {
|
|||
pianoOptions=!pianoOptions;
|
||||
}
|
||||
|
||||
// TODO: wave and sample preview
|
||||
// first check released keys
|
||||
for (int i=0; i<180; i++) {
|
||||
int note=i-60;
|
||||
|
|
|
@ -1407,28 +1407,40 @@ void FurnaceGUI::initSystemPresets() {
|
|||
"Sega System 32", {
|
||||
CH(DIV_SYSTEM_YM2612, 1.0f, 0, "clockSel=4"), // discrete 8.05MHz YM3438
|
||||
CH(DIV_SYSTEM_YM2612, 1.0f, 0, "clockSel=4"), // ^^
|
||||
CH(DIV_SYSTEM_RF5C68, 1.0f, 0, "clockSel=2") // 12.5MHz
|
||||
CH(DIV_SYSTEM_RF5C68, 1.0f, 0,
|
||||
"clockSel=2\n"
|
||||
"chipType=1\n"
|
||||
) // 12.5MHz
|
||||
}
|
||||
);
|
||||
ENTRY(
|
||||
"Sega System 32 (extended channel 3 on first OPN2C)", {
|
||||
CH(DIV_SYSTEM_YM2612_EXT, 1.0f, 0, "clockSel=4"), // discrete 8.05MHz YM3438
|
||||
CH(DIV_SYSTEM_YM2612, 1.0f, 0, "clockSel=4"), // ^^
|
||||
CH(DIV_SYSTEM_RF5C68, 1.0f, 0, "clockSel=2") // 12.5MHz
|
||||
CH(DIV_SYSTEM_RF5C68, 1.0f, 0,
|
||||
"clockSel=2\n"
|
||||
"chipType=1\n"
|
||||
) // 12.5MHz
|
||||
}
|
||||
);
|
||||
ENTRY(
|
||||
"Sega System 32 (extended channel 3 on second OPN2C)", {
|
||||
CH(DIV_SYSTEM_YM2612, 1.0f, 0, "clockSel=4"), // discrete 8.05MHz YM3438
|
||||
CH(DIV_SYSTEM_YM2612_EXT, 1.0f, 0, "clockSel=4"), // ^^
|
||||
CH(DIV_SYSTEM_RF5C68, 1.0f, 0, "clockSel=2") // 12.5MHz
|
||||
CH(DIV_SYSTEM_RF5C68, 1.0f, 0,
|
||||
"clockSel=2\n"
|
||||
"chipType=1\n"
|
||||
) // 12.5MHz
|
||||
}
|
||||
);
|
||||
ENTRY(
|
||||
"Sega System 32 (extended channel 3 on both OPN2Cs)", {
|
||||
CH(DIV_SYSTEM_YM2612_EXT, 1.0f, 0, "clockSel=4"), // discrete 8.05MHz YM3438
|
||||
CH(DIV_SYSTEM_YM2612_EXT, 1.0f, 0, "clockSel=4"), // ^^
|
||||
CH(DIV_SYSTEM_RF5C68, 1.0f, 0, "clockSel=2") // 12.5MHz
|
||||
CH(DIV_SYSTEM_RF5C68, 1.0f, 0,
|
||||
"clockSel=2\n"
|
||||
"chipType=1\n"
|
||||
) // 12.5MHz
|
||||
}
|
||||
);
|
||||
ENTRY(
|
||||
|
|
|
@ -372,6 +372,7 @@ void FurnaceGUI::drawSampleEdit() {
|
|||
if (sampleInfo) {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Type");
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
|
@ -445,6 +446,7 @@ void FurnaceGUI::drawSampleEdit() {
|
|||
bool coarseChanged=false;
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Hz");
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
|
@ -459,6 +461,7 @@ void FurnaceGUI::drawSampleEdit() {
|
|||
}
|
||||
}
|
||||
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Note");
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
|
@ -501,6 +504,7 @@ void FurnaceGUI::drawSampleEdit() {
|
|||
}
|
||||
}
|
||||
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Fine");
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
|
@ -537,6 +541,7 @@ void FurnaceGUI::drawSampleEdit() {
|
|||
ImGui::TableNextColumn();
|
||||
ImGui::BeginDisabled(!(doLoop || keepLoopAlive));
|
||||
keepLoopAlive=false;
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Mode");
|
||||
ImGui::SameLine();
|
||||
pushWarningColor(!warnLoopMode.empty());
|
||||
|
@ -560,6 +565,7 @@ void FurnaceGUI::drawSampleEdit() {
|
|||
popWarningColor();
|
||||
|
||||
pushWarningColor(!warnLoopPos.empty());
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Start");
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
|
@ -585,6 +591,7 @@ void FurnaceGUI::drawSampleEdit() {
|
|||
ImGui::SetTooltip("%s",warnLoopPos.c_str());
|
||||
}
|
||||
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("End");
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
|
@ -1018,6 +1025,7 @@ void FurnaceGUI::drawSampleEdit() {
|
|||
if (sampleFilterRes<0.0f) sampleFilterRes=0.0f;
|
||||
if (sampleFilterRes>0.99f) sampleFilterRes=0.99f;
|
||||
}
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Power");
|
||||
ImGui::SameLine();
|
||||
if (ImGui::RadioButton("1x",sampleFilterPower==1)) {
|
||||
|
@ -1601,7 +1609,7 @@ void FurnaceGUI::drawSampleEdit() {
|
|||
posX=samplePos+pos.x*sampleZoom;
|
||||
if (posX>(int)sample->samples) posX=-1;
|
||||
}
|
||||
posY=(0.5-pos.y/rectSize.y)*((sample->depth==DIV_SAMPLE_DEPTH_8BIT)?255:32767);
|
||||
posY=(0.5-pos.y/rectSize.y)*((sample->depth==DIV_SAMPLE_DEPTH_8BIT)?255:65535);
|
||||
if (posX>=0) {
|
||||
statusBar2=fmt::sprintf("(%d, %d)",posX,posY);
|
||||
}
|
||||
|
|
|
@ -239,6 +239,7 @@ const char* specificControls[18]={
|
|||
#define UI_KEYBIND_CONFIG(what) \
|
||||
ImGui::TableNextRow(); \
|
||||
ImGui::TableNextColumn(); \
|
||||
ImGui::AlignTextToFramePadding();\
|
||||
ImGui::TextUnformatted(guiActions[what].friendlyName); \
|
||||
ImGui::TableNextColumn(); \
|
||||
if (ImGui::Button(fmt::sprintf("%s##KC_" #what,(bindSetPending && bindSetTarget==what)?"Press key...":getKeyName(actionKeys[what])).c_str())) { \
|
||||
|
@ -474,6 +475,7 @@ void FurnaceGUI::drawSettings() {
|
|||
|
||||
// SUBSECTION CHIP
|
||||
CONFIG_SUBSECTION("Chip");
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Initial system:");
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Current system")) {
|
||||
|
@ -552,6 +554,7 @@ void FurnaceGUI::drawSettings() {
|
|||
settings.initialSysName="Sega Genesis/Mega Drive";
|
||||
}
|
||||
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Name");
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
|
@ -720,6 +723,7 @@ void FurnaceGUI::drawSettings() {
|
|||
// SUBSECTION OUTPUT
|
||||
CONFIG_SUBSECTION("Output");
|
||||
#ifdef HAVE_JACK
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Backend");
|
||||
ImGui::SameLine();
|
||||
int prevAudioEngine=settings.audioEngine;
|
||||
|
@ -731,6 +735,7 @@ void FurnaceGUI::drawSettings() {
|
|||
#endif
|
||||
|
||||
if (settings.audioEngine==DIV_AUDIO_SDL) {
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Driver");
|
||||
ImGui::SameLine();
|
||||
if (ImGui::BeginCombo("##SDLADriver",settings.sdlAudioDriver.empty()?"Automatic":settings.sdlAudioDriver.c_str())) {
|
||||
|
@ -749,6 +754,7 @@ void FurnaceGUI::drawSettings() {
|
|||
}
|
||||
}
|
||||
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Device");
|
||||
ImGui::SameLine();
|
||||
String audioDevName=settings.audioDevice.empty()?"<System default>":settings.audioDevice;
|
||||
|
@ -764,6 +770,7 @@ void FurnaceGUI::drawSettings() {
|
|||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Sample rate");
|
||||
ImGui::SameLine();
|
||||
String sr=fmt::sprintf("%d",settings.audioRate);
|
||||
|
@ -788,6 +795,7 @@ void FurnaceGUI::drawSettings() {
|
|||
if (settings.audioChans>16) settings.audioChans=16;
|
||||
}
|
||||
} else {
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Channels");
|
||||
ImGui::SameLine();
|
||||
String chStr=(settings.audioChans<1 || settings.audioChans>8)?"What?":nonProAudioOuts[settings.audioChans-1];
|
||||
|
@ -801,6 +809,7 @@ void FurnaceGUI::drawSettings() {
|
|||
}
|
||||
}
|
||||
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Buffer size");
|
||||
ImGui::SameLine();
|
||||
String bs=fmt::sprintf("%d (latency: ~%.1fms)",settings.audioBufSize,2000.0*(double)settings.audioBufSize/(double)MAX(1,settings.audioRate));
|
||||
|
@ -835,6 +844,7 @@ void FurnaceGUI::drawSettings() {
|
|||
|
||||
// SUBSECTION MIXING
|
||||
CONFIG_SUBSECTION("Mixing");
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Quality");
|
||||
ImGui::SameLine();
|
||||
ImGui::Combo("##Quality",&settings.audioQuality,audioQualities,2);
|
||||
|
@ -846,6 +856,7 @@ void FurnaceGUI::drawSettings() {
|
|||
|
||||
// SUBSECTION METRONOME
|
||||
CONFIG_SUBSECTION("Metronome");
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Metronome volume");
|
||||
ImGui::SameLine();
|
||||
if (ImGui::SliderInt("##MetroVol",&settings.metroVol,0,200,"%d%%")) {
|
||||
|
@ -859,6 +870,7 @@ void FurnaceGUI::drawSettings() {
|
|||
CONFIG_SECTION("MIDI") {
|
||||
// SUBSECTION MIDI INPUT
|
||||
CONFIG_SUBSECTION("MIDI input");
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("MIDI input");
|
||||
ImGui::SameLine();
|
||||
String midiInName=settings.midiInDevice.empty()?"<disabled>":settings.midiInDevice;
|
||||
|
@ -947,6 +959,7 @@ void FurnaceGUI::drawSettings() {
|
|||
}
|
||||
ImGui::PlotLines("##VolCurveDisplay",curve,128,0,"Volume curve",0.0,127.0,ImVec2(200.0f*dpiScale,200.0f*dpiScale));
|
||||
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Actions:");
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button(ICON_FA_PLUS "##AddAction")) {
|
||||
|
@ -1109,6 +1122,7 @@ void FurnaceGUI::drawSettings() {
|
|||
|
||||
// SUBSECTION MIDI OUTPUT
|
||||
CONFIG_SUBSECTION("MIDI output");
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("MIDI output");
|
||||
ImGui::SameLine();
|
||||
String midiOutName=settings.midiOutDevice.empty()?"<disabled>":settings.midiOutDevice;
|
||||
|
@ -1179,40 +1193,49 @@ void FurnaceGUI::drawSettings() {
|
|||
CONFIG_SECTION("Emulation") {
|
||||
// SUBSECTION LAYOUT
|
||||
CONFIG_SUBSECTION("Cores");
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Arcade/YM2151 core");
|
||||
ImGui::SameLine();
|
||||
ImGui::Combo("##ArcadeCore",&settings.arcadeCore,arcadeCores,2);
|
||||
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Genesis/YM2612 core");
|
||||
ImGui::SameLine();
|
||||
ImGui::Combo("##YM2612Core",&settings.ym2612Core,ym2612Cores,2);
|
||||
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("SN76489 core");
|
||||
ImGui::SameLine();
|
||||
ImGui::Combo("##SNCore",&settings.snCore,snCores,2);
|
||||
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("NES core");
|
||||
ImGui::SameLine();
|
||||
ImGui::Combo("##NESCore",&settings.nesCore,nesCores,2);
|
||||
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("FDS core");
|
||||
ImGui::SameLine();
|
||||
ImGui::Combo("##FDSCore",&settings.fdsCore,nesCores,2);
|
||||
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("SID core");
|
||||
ImGui::SameLine();
|
||||
ImGui::Combo("##C64Core",&settings.c64Core,c64Cores,3);
|
||||
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("POKEY core");
|
||||
ImGui::SameLine();
|
||||
ImGui::Combo("##POKEYCore",&settings.pokeyCore,pokeyCores,2);
|
||||
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("OPN/OPNA/OPNB cores");
|
||||
ImGui::SameLine();
|
||||
ImGui::Combo("##OPNCore",&settings.opnCore,opnCores,2);
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("PC Speaker strategy");
|
||||
ImGui::SameLine();
|
||||
ImGui::Combo("##PCSOutMethod",&settings.pcSpeakerOutMethod,pcspkrOutMethods,5);
|
||||
|
@ -1220,6 +1243,7 @@ void FurnaceGUI::drawSettings() {
|
|||
ImGui::Separator();
|
||||
ImGui::Text("Sample ROMs:");
|
||||
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("OPL4 YRW801 path");
|
||||
ImGui::SameLine();
|
||||
ImGui::InputText("##YRW801Path",&settings.yrw801Path);
|
||||
|
@ -1228,6 +1252,7 @@ void FurnaceGUI::drawSettings() {
|
|||
openFileDialog(GUI_FILE_YRW801_ROM_OPEN);
|
||||
}
|
||||
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("MultiPCM TG100 path");
|
||||
ImGui::SameLine();
|
||||
ImGui::InputText("##TG100Path",&settings.tg100Path);
|
||||
|
@ -1236,6 +1261,7 @@ void FurnaceGUI::drawSettings() {
|
|||
openFileDialog(GUI_FILE_TG100_ROM_OPEN);
|
||||
}
|
||||
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("MultiPCM MU5 path");
|
||||
ImGui::SameLine();
|
||||
ImGui::InputText("##MU5Path",&settings.mu5Path);
|
||||
|
@ -1478,6 +1504,7 @@ void FurnaceGUI::drawSettings() {
|
|||
UI_KEYBIND_CONFIG(GUI_ACTION_PAT_COLLAPSE_SONG);
|
||||
UI_KEYBIND_CONFIG(GUI_ACTION_PAT_EXPAND_SONG);
|
||||
UI_KEYBIND_CONFIG(GUI_ACTION_PAT_LATCH);
|
||||
UI_KEYBIND_CONFIG(GUI_ACTION_PAT_CLEAR_LATCH);
|
||||
|
||||
KEYBIND_CONFIG_END;
|
||||
ImGui::TreePop();
|
||||
|
@ -1604,6 +1631,7 @@ void FurnaceGUI::drawSettings() {
|
|||
CONFIG_SECTION("Interface") {
|
||||
// SUBSECTION LAYOUT
|
||||
CONFIG_SUBSECTION("Layout");
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Workspace layout:");
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Import")) {
|
||||
|
@ -1639,6 +1667,11 @@ void FurnaceGUI::drawSettings() {
|
|||
applyUISettings(false);
|
||||
}
|
||||
|
||||
bool centerPopupB=settings.centerPopup;
|
||||
if (ImGui::Checkbox("Center pop-up windows",¢erPopupB)) {
|
||||
settings.centerPopup=centerPopupB;
|
||||
}
|
||||
|
||||
ImGui::Text("Play/edit controls layout:");
|
||||
ImGui::Indent();
|
||||
if (ImGui::RadioButton("Classic##ecl0",settings.controlLayout==0)) {
|
||||
|
@ -1908,6 +1941,7 @@ void FurnaceGUI::drawSettings() {
|
|||
|
||||
// SUBSECTION TEXT
|
||||
CONFIG_SUBSECTION("Text");
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Main font");
|
||||
ImGui::SameLine();
|
||||
ImGui::Combo("##MainFont",&settings.mainFont,mainFonts,7);
|
||||
|
@ -1924,6 +1958,7 @@ void FurnaceGUI::drawSettings() {
|
|||
if (settings.mainFontSize>96) settings.mainFontSize=96;
|
||||
}
|
||||
ImGui::Unindent();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Header font");
|
||||
ImGui::SameLine();
|
||||
ImGui::Combo("##HeadFont",&settings.headFont,headFonts,7);
|
||||
|
@ -1940,6 +1975,7 @@ void FurnaceGUI::drawSettings() {
|
|||
if (settings.headFontSize>96) settings.headFontSize=96;
|
||||
}
|
||||
ImGui::Unindent();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Pattern font");
|
||||
ImGui::SameLine();
|
||||
ImGui::Combo("##PatFont",&settings.patFont,patFonts,7);
|
||||
|
@ -2059,6 +2095,11 @@ void FurnaceGUI::drawSettings() {
|
|||
}
|
||||
ImGui::Unindent();
|
||||
|
||||
bool capitalMenuBarB=settings.capitalMenuBar;
|
||||
if (ImGui::Checkbox("Capitalize menu bar",&capitalMenuBarB)) {
|
||||
settings.capitalMenuBar=capitalMenuBarB;
|
||||
}
|
||||
|
||||
// SUBSECTION ORDERS
|
||||
CONFIG_SUBSECTION("Orders");
|
||||
// sorry. temporarily disabled until ImGui has a way to add separators in tables arbitrarily.
|
||||
|
@ -2281,6 +2322,11 @@ void FurnaceGUI::drawSettings() {
|
|||
settings.insEditColorize=insEditColorizeB;
|
||||
}
|
||||
|
||||
bool insTypeMenuB=settings.insTypeMenu;
|
||||
if (ImGui::Checkbox("Display instrument type menu when adding instrument",&insTypeMenuB)) {
|
||||
settings.insTypeMenu=insTypeMenuB;
|
||||
}
|
||||
|
||||
// SUBSECTION MACRO EDITOR
|
||||
CONFIG_SUBSECTION("Macro Editor");
|
||||
ImGui::Text("Macro editor layout:");
|
||||
|
@ -3017,6 +3063,9 @@ void FurnaceGUI::syncSettings() {
|
|||
settings.removeInsOff=e->getConfInt("removeInsOff",0);
|
||||
settings.removeVolOff=e->getConfInt("removeVolOff",0);
|
||||
settings.playOnLoad=e->getConfInt("playOnLoad",0);
|
||||
settings.insTypeMenu=e->getConfInt("insTypeMenu",1);
|
||||
settings.capitalMenuBar=e->getConfInt("capitalMenuBar",0);
|
||||
settings.centerPopup=e->getConfInt("centerPopup",1);
|
||||
|
||||
clampSetting(settings.mainFontSize,2,96);
|
||||
clampSetting(settings.headFontSize,2,96);
|
||||
|
@ -3151,6 +3200,9 @@ void FurnaceGUI::syncSettings() {
|
|||
clampSetting(settings.removeInsOff,0,1);
|
||||
clampSetting(settings.removeVolOff,0,1);
|
||||
clampSetting(settings.playOnLoad,0,2);
|
||||
clampSetting(settings.insTypeMenu,0,1);
|
||||
clampSetting(settings.capitalMenuBar,0,1);
|
||||
clampSetting(settings.centerPopup,0,1);
|
||||
|
||||
if (settings.exportLoops<0.0) settings.exportLoops=0.0;
|
||||
if (settings.exportFadeOut<0.0) settings.exportFadeOut=0.0;
|
||||
|
@ -3385,6 +3437,9 @@ void FurnaceGUI::commitSettings() {
|
|||
e->setConf("removeInsOff",settings.removeInsOff);
|
||||
e->setConf("removeVolOff",settings.removeVolOff);
|
||||
e->setConf("playOnLoad",settings.playOnLoad);
|
||||
e->setConf("insTypeMenu",settings.insTypeMenu);
|
||||
e->setConf("capitalMenuBar",settings.capitalMenuBar);
|
||||
e->setConf("centerPopup",settings.centerPopup);
|
||||
|
||||
// colors
|
||||
for (int i=0; i<GUI_COLOR_MAX; i++) {
|
||||
|
@ -3813,14 +3868,10 @@ void FurnaceGUI::popWarningColor() {
|
|||
#ifdef _WIN32
|
||||
#define SYSTEM_FONT_PATH_1 "C:\\Windows\\Fonts\\segoeui.ttf"
|
||||
#define SYSTEM_FONT_PATH_2 "C:\\Windows\\Fonts\\tahoma.ttf"
|
||||
// TODO!
|
||||
#define SYSTEM_FONT_PATH_3 "C:\\Windows\\Fonts\\tahoma.ttf"
|
||||
// TODO!
|
||||
#define SYSTEM_FONT_PATH_3 "C:\\Windows\\Fonts\\micross.ttf"
|
||||
#define SYSTEM_HEAD_FONT_PATH_1 "C:\\Windows\\Fonts\\segoeui.ttf"
|
||||
#define SYSTEM_HEAD_FONT_PATH_2 "C:\\Windows\\Fonts\\tahoma.ttf"
|
||||
// TODO!
|
||||
#define SYSTEM_HEAD_FONT_PATH_3 "C:\\Windows\\Fonts\\tahoma.ttf"
|
||||
// TODO!
|
||||
#define SYSTEM_HEAD_FONT_PATH_3 "C:\\Windows\\Fonts\\micross.ttf"
|
||||
#define SYSTEM_PAT_FONT_PATH_1 "C:\\Windows\\Fonts\\consola.ttf"
|
||||
#define SYSTEM_PAT_FONT_PATH_2 "C:\\Windows\\Fonts\\cour.ttf"
|
||||
// GOOD LUCK WITH THIS ONE - UNTESTED
|
||||
|
@ -4234,7 +4285,6 @@ void FurnaceGUI::applyUISettings(bool updateFonts) {
|
|||
mainFont->EllipsisCharCount=3;
|
||||
}
|
||||
|
||||
// TODO: allow changing these colors.
|
||||
ImGuiFileDialog::Instance()->SetFileStyle(IGFD_FileStyleByTypeDir,"",uiColors[GUI_COLOR_FILE_DIR],ICON_FA_FOLDER_O);
|
||||
ImGuiFileDialog::Instance()->SetFileStyle(IGFD_FileStyleByTypeFile,"",uiColors[GUI_COLOR_FILE_OTHER],ICON_FA_FILE_O);
|
||||
ImGuiFileDialog::Instance()->SetFileStyle(IGFD_FileStyleByExtension,".fur",uiColors[GUI_COLOR_FILE_SONG_NATIVE],ICON_FA_FILE);
|
||||
|
|
|
@ -36,6 +36,7 @@ void FurnaceGUI::drawSongInfo(bool asChild) {
|
|||
ImGui::TableSetupColumn("c1",ImGuiTableColumnFlags_WidthStretch,0.0);
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Name");
|
||||
ImGui::TableNextColumn();
|
||||
float avail=ImGui::GetContentRegionAvail().x;
|
||||
|
@ -59,6 +60,7 @@ void FurnaceGUI::drawSongInfo(bool asChild) {
|
|||
}
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Author");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::SetNextItemWidth(avail);
|
||||
|
@ -68,6 +70,7 @@ void FurnaceGUI::drawSongInfo(bool asChild) {
|
|||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Album");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::SetNextItemWidth(avail);
|
||||
|
@ -77,6 +80,7 @@ void FurnaceGUI::drawSongInfo(bool asChild) {
|
|||
if (!basicMode) {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("System");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::SetNextItemWidth(MAX(16.0f*dpiScale,avail-autoButtonSize-ImGui::GetStyle().ItemSpacing.x));
|
||||
|
@ -112,6 +116,7 @@ void FurnaceGUI::drawSongInfo(bool asChild) {
|
|||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Tuning (A-4)");
|
||||
ImGui::TableNextColumn();
|
||||
float tune=e->song.tuning;
|
||||
|
|
|
@ -37,6 +37,7 @@ void FurnaceGUI::drawSpeed(bool asChild) {
|
|||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
if (ImGui::SmallButton(tempoView?"Base Tempo##TempoOrHz":"Tick Rate##TempoOrHz")) {
|
||||
tempoView=!tempoView;
|
||||
}
|
||||
|
@ -74,6 +75,7 @@ void FurnaceGUI::drawSpeed(bool asChild) {
|
|||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
if (keepGrooveAlive || e->curSubSong->speeds.len>2) {
|
||||
if (ImGui::SmallButton("Groove")) {
|
||||
e->lockEngine([this]() {
|
||||
|
@ -163,6 +165,7 @@ void FurnaceGUI::drawSpeed(bool asChild) {
|
|||
if (!basicMode) {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Virtual Tempo");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::SetNextItemWidth(halfAvail);
|
||||
|
@ -185,6 +188,7 @@ void FurnaceGUI::drawSpeed(bool asChild) {
|
|||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Divider");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::SetNextItemWidth(halfAvail);
|
||||
|
@ -200,6 +204,7 @@ void FurnaceGUI::drawSpeed(bool asChild) {
|
|||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Highlight");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::SetNextItemWidth(halfAvail);
|
||||
|
@ -222,6 +227,7 @@ void FurnaceGUI::drawSpeed(bool asChild) {
|
|||
ImGui::TableSetupColumn("c2",ImGuiTableColumnFlags_WidthStretch,0.0);
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Pattern Length");
|
||||
ImGui::TableNextColumn();
|
||||
float avail=ImGui::GetContentRegionAvail().x;
|
||||
|
@ -236,6 +242,7 @@ void FurnaceGUI::drawSpeed(bool asChild) {
|
|||
if (!basicMode) {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Song Length");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::SetNextItemWidth(avail);
|
||||
|
|
|
@ -32,6 +32,7 @@ void FurnaceGUI::drawStats() {
|
|||
size_t lastProcTime=e->processTime;
|
||||
double maxGot=1000000000.0*(double)e->getAudioDescGot().bufsize/(double)e->getAudioDescGot().rate;
|
||||
String procStr=fmt::sprintf("%.1f%%",100.0*((double)lastProcTime/(double)maxGot));
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Audio load");
|
||||
ImGui::SameLine();
|
||||
ImGui::ProgressBar((double)lastProcTime/maxGot,ImVec2(-FLT_MIN,0),procStr.c_str());
|
||||
|
@ -47,6 +48,7 @@ void FurnaceGUI::drawStats() {
|
|||
} else {
|
||||
usageStr=fmt::sprintf("%d/%d",usage,capacity);
|
||||
}
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("%s [%d]", e->getSystemName(e->song.system[i]), j);
|
||||
ImGui::SameLine();
|
||||
ImGui::ProgressBar(((float)usage)/((float)capacity),ImVec2(-FLT_MIN,0),usageStr.c_str());
|
||||
|
|
|
@ -127,6 +127,7 @@ void FurnaceGUI::drawSubSongs(bool asChild) {
|
|||
ImGui::SetTooltip("Remove");
|
||||
}
|
||||
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Name");
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
|
|
|
@ -395,6 +395,7 @@ bool FurnaceGUI::drawSysConf(int chan, DivSystem type, DivConfig& flags, bool mo
|
|||
int clockSel=flags.getInt("clockSel",0);
|
||||
int patchSet=flags.getInt("patchSet",0);
|
||||
bool noTopHatFreq=flags.getBool("noTopHatFreq",false);
|
||||
bool fixedAll=flags.getBool("fixedAll",false);
|
||||
|
||||
ImGui::Text("Clock rate:");
|
||||
ImGui::Indent();
|
||||
|
@ -441,6 +442,9 @@ bool FurnaceGUI::drawSysConf(int chan, DivSystem type, DivConfig& flags, bool mo
|
|||
if (ImGui::Checkbox("Ignore top/hi-hat frequency changes",&noTopHatFreq)) {
|
||||
altered=true;
|
||||
}
|
||||
if (ImGui::Checkbox("Apply fixed frequency to all drums at once",&fixedAll)) {
|
||||
altered=true;
|
||||
}
|
||||
}
|
||||
|
||||
if (altered) {
|
||||
|
@ -450,6 +454,7 @@ bool FurnaceGUI::drawSysConf(int chan, DivSystem type, DivConfig& flags, bool mo
|
|||
flags.set("patchSet",patchSet);
|
||||
}
|
||||
flags.set("noTopHatFreq",noTopHatFreq);
|
||||
flags.set("fixedAll",fixedAll);
|
||||
});
|
||||
}
|
||||
break;
|
||||
|
@ -1602,7 +1607,7 @@ bool FurnaceGUI::drawSysConf(int chan, DivSystem type, DivConfig& flags, bool mo
|
|||
}
|
||||
break;
|
||||
}
|
||||
case DIV_SYSTEM_SNES: { // TODO: echo
|
||||
case DIV_SYSTEM_SNES: {
|
||||
char temp[64];
|
||||
int vsL=127-(flags.getInt("volScaleL",0)&127);
|
||||
int vsR=127-(flags.getInt("volScaleR",0)&127);
|
||||
|
|
|
@ -60,8 +60,7 @@ bool FurnaceGUI::parseSysEx(unsigned char* data, size_t len) {
|
|||
op.rs=reader.readC();
|
||||
reader.readC(); // EBS - ignore
|
||||
op.am=reader.readC();
|
||||
// TODO: don't ignore after I add KVS to Furnace
|
||||
reader.readC(); // KVS - ignore
|
||||
op.kvs=(reader.readC()>2)?1:0;
|
||||
op.tl=3+((99-reader.readC())*124)/99;
|
||||
unsigned char freq=reader.readC();
|
||||
logV("OP%d freq: %d",i,freq);
|
||||
|
|
|
@ -593,6 +593,7 @@ void FurnaceGUI::drawWaveEdit() {
|
|||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Duty");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
|
@ -602,6 +603,7 @@ void FurnaceGUI::drawWaveEdit() {
|
|||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Exponent");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
|
@ -611,6 +613,7 @@ void FurnaceGUI::drawWaveEdit() {
|
|||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("XOR Point");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
|
@ -630,6 +633,7 @@ void FurnaceGUI::drawWaveEdit() {
|
|||
for (int i=0; i<16; i++) {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("%d",i+1);
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::PushID(140+i);
|
||||
|
@ -683,6 +687,7 @@ void FurnaceGUI::drawWaveEdit() {
|
|||
for (int i=0; i<4; i++) {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("%d",i+1);
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
|
@ -727,6 +732,7 @@ void FurnaceGUI::drawWaveEdit() {
|
|||
for (int i=0; i<4; i++) {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("%d",i+1);
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
|
@ -760,6 +766,7 @@ void FurnaceGUI::drawWaveEdit() {
|
|||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("1");
|
||||
ImGui::TableNextColumn();
|
||||
if (ImGui::Checkbox("##ConO1",&waveGenFMCon0[0])) {
|
||||
|
@ -784,6 +791,7 @@ void FurnaceGUI::drawWaveEdit() {
|
|||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("2");
|
||||
ImGui::TableNextColumn();
|
||||
if (ImGui::Checkbox("##Con11",&waveGenFMCon1[0])) {
|
||||
|
@ -808,6 +816,7 @@ void FurnaceGUI::drawWaveEdit() {
|
|||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("3");
|
||||
ImGui::TableNextColumn();
|
||||
if (ImGui::Checkbox("##Con21",&waveGenFMCon2[0])) {
|
||||
|
@ -832,6 +841,7 @@ void FurnaceGUI::drawWaveEdit() {
|
|||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("4");
|
||||
ImGui::TableNextColumn();
|
||||
if (ImGui::Checkbox("##Con31",&waveGenFMCon3[0])) {
|
||||
|
|
Loading…
Reference in a new issue