Compare commits

...

18 Commits

Author SHA1 Message Date
tildearrow 35aeb51b79 ugh why 2023-08-31 02:31:33 -05:00
tildearrow 05d5eb5ca3 asd 2023-08-31 02:19:27 -05:00
tildearrow 879e770e58 and again 2023-08-31 02:09:54 -05:00
tildearrow 7f35d06ccb why does this happen 2023-08-31 01:59:37 -05:00
tildearrow 43ef57390a GUI: clamp CWSliders 2023-08-31 01:52:11 -05:00
tildearrow 4ad1ae78fa ASDFGHJKL 2023-08-31 01:43:19 -05:00
tildearrow a882d7bcf2 GUI: detect UI scale factor when moving window 2023-08-31 01:24:06 -05:00
tildearrow 9caa2f38f4 SoundUnit: fix getPan() 2023-08-31 00:42:25 -05:00
tildearrow 5140acd51f
Merge pull request #1443 from tildearrow/doc-general
Small documentation fixes and improvements.
2023-08-31 00:20:18 -05:00
tildearrow 9aacc706f1 Merge branch 'master' into doc-general 2023-08-31 00:20:05 -05:00
Electric Keet fb3a3890d5 And the rest of the fixes. 2023-08-30 22:18:15 -07:00
Electric Keet 29c2879397 Small correction. 2023-08-30 22:07:06 -07:00
tildearrow 8b3fc84b51 don't show JACK/PA backends if not available 2023-08-30 23:23:27 -05:00
tildearrow 922800d864 oh crap 2023-08-30 23:14:47 -05:00
tildearrow 274ce8a646 remove many TODOs 2023-08-30 19:21:38 -05:00
Electric Keet 1ebf828743 A couple more slight edits.
Typo fix and update for new macro props indicator, just to show what that looks like.
2023-08-30 14:13:06 -07:00
Electric Keet da5d110e73 Doc update for new features. 2023-08-29 10:52:07 -07:00
Electric Keet 2813e8e3b3 Merge branch 'master' into doc-general 2023-08-28 14:51:17 -07:00
26 changed files with 165 additions and 68 deletions

View File

@ -221,6 +221,8 @@ if (WITH_PORTAUDIO)
message(STATUS "Using system-installed PortAudio")
else()
set(PA_BUILD_SHARED_LIBS OFF CACHE BOOL "Build dynamic library" FORCE)
# don't - Furnace has its own implementation
set(PA_USE_JACK OFF CACHE BOOL "Enable support for JACK Audio Connection Kit" FORCE)
add_subdirectory(extern/portaudio EXCLUDE_FROM_ALL)
list(APPEND DEPENDENCIES_LIBRARIES PortAudio)
message(STATUS "Using vendored PortAudio")

View File

@ -39,14 +39,8 @@ items in _italics_ don't appear in basic mode and are only available in advanced
- only available when there's a YM2151 and/or VERA.
- **export command stream...**: export song data to a command stream file. see next section for more details.
- this option is for developers.
- _**add chip...**:_ add a chip to the current song.
- _**configure chip...**:_ set a chip's parameters.
- for a list of parameters, see [7-systems](../7-systems/README.md).
- _**change chip...**:_ change a chip to another.
- **Preserve channel positions**: enable this option to make sure Furnace does not auto-arrange/delete channels to compensate for differing channel counts. this can be useful for doing ports, e.g. from Genesis to PC-98.
- _**remove chip...**_: remove a chip.
- **Preserve channel positions**: same thing as above.
- **manage chips**: opens the [Chip Manager](../8-advanced/chip-manager.md) dialog.
- **restore backup**: restores a previously saved backup.
- Furnace keeps up to 5 backups of a song.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

After

Width:  |  Height:  |  Size: 80 KiB

View File

@ -193,7 +193,7 @@ settings are saved when clicking the **OK** or **Apply** buttons at the bottom o
- **Import**
- **Export**
- **Reset defaults**
- several categories of keybinds...
- [grouped list of keybinds...](keyboard.md)
- click on a keybind then enter a key or key combination to change it
- right-click to clear the keybind
@ -327,6 +327,7 @@ settings are saved when clicking the **OK** or **Apply** buttons at the bottom o
- **Cursor details or file path**
- **Nothing**
- **Capitalize menu bar**
- **Display add/configure/change/remove chip menus in File menu**: if enabled, the "manage chips" item in the file menu is split into the four listed items for quick access.
### Orders

View File

@ -50,8 +50,9 @@ The very first numeric entry sets the visible width of the bars in sequence-type
Each macro has two buttons on the left.
- Macro type (explained below).
- Timing editor, which pops up a small dialog:
- Step Length (ticks): Determines how many ticks pass before each change of value.
- Delay: Delays the start of the macro until this many ticks have passed.
- Step Length (ticks): Determines how many ticks pass before each change of value. Default is 1.
- Delay: Delays the start of the macro until this many ticks have passed. Default is 0.
- The button is highlighted if either of these is set differently from default.
## macro types

View File

@ -22,11 +22,10 @@ These apply to the instrument as a whole:
- Right-click returns to algorithm view.
- **DC (half-sine carrier)**: Sets the waveform produced by carrier operator to half-sine
- **DM (half-sine modulator)**: Sets the waveform produced by modulator operator to half-sine
- preset dropdown: select OPLL preset instrument.
- preset dropdown: selects OPLL preset instrument.
These apply to each operator:
- The crossed-arrows button can be dragged to rearrange operators.
- The **OP1** and **OP2** buttons enable or disable those operators.
- **Amplitude Modulation (AM)**: Makes the operator affected by LFO tremolo.
- **Envelope generator sustain flag (EGS)**: When enabled, value of Sustain Level is in effect.
- **Attack Rate (AR)**: determines the rising time for the sound. The bigger the value, the faster the attack. (0-15 range)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 31 KiB

View File

@ -20,7 +20,7 @@ these tabs are unique to the editor for SNES instruments.
- **Delayed (write R on release)**: after release, waits until A and D have completed before starting exponential decrease.
if envelope is off:
- **Gain Mode**: select gain mode.
- **Gain Mode**: selects gain mode.
- **Direct**: direct gain from 0 to 127
- **Decrease (linear)**: linear gain from -0 to -31
- **Decrease (logarithmic)**: exponential gain from -0 to -31

View File

@ -111,7 +111,7 @@ input waveforms should match the size of the wavetable or unexpected results may
- synthesizer type: selects the synthesis algorithm.
- waveform displays.
- **Wave 1**: selects input waveform.
- this will turn yellow to indicate that a Waveform macro is set; remove the macro to work with the synthesizer.
- this will turn yellow to indicate that a Waveform macro is set.
- **Wave 2**: selects second input waveform. only appears when a dual-waveform synthesizer is selected.
- **Pause preview**: toggles live waveform preview.
- **Restart preview**: restarts preview from initial state.

View File

@ -184,7 +184,7 @@ this chip uses the [TIA](../4-instrument/tia.md) instrument editor.
| 30 | 32.7 | C-1 | 0.0 | 32.5 | C-1 | -11
| 31 | 31.7 | B-0 | +44 | 31.5 | B-0 | +33
## shapes 8
## shape 8
| pitch | NTSC | note | cent | PAL | note | cent
|------:|--------:|:----:|-----:|--------:|:----:|-----:

View File

@ -658,8 +658,6 @@ int DivPlatformAY8910::dispatch(DivCommand c) {
return 15;
break;
case DIV_CMD_PRE_PORTA:
// TODO: FIX wtr_envelope.dmf
// the brokenPortaArp update broke it
if (chan[c.chan].active && c.value2) {
if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_AY));
}

View File

@ -502,8 +502,7 @@ void DivPlatformC140::notifyInsChange(int ins) {
}
void DivPlatformC140::notifyWaveChange(int wave) {
// TODO when wavetables are added
// TODO they probably won't be added unless the samples reside in RAM
}
void DivPlatformC140::notifyInsDeletion(void* ins) {

View File

@ -1107,8 +1107,6 @@ void DivPlatformES5506::notifyInsChange(int ins) {
}
void DivPlatformES5506::notifyWaveChange(int wave) {
// TODO when wavetables are added
// TODO they probably won't be added unless the samples reside in RAM
}
void DivPlatformES5506::notifyInsDeletion(void* ins) {

View File

@ -388,8 +388,6 @@ void DivPlatformGA20::notifyInsChange(int ins) {
}
void DivPlatformGA20::notifyWaveChange(int wave) {
// TODO when wavetables are added
// TODO they probably won't be added unless the samples reside in RAM
}
void DivPlatformGA20::notifyInsDeletion(void* ins) {

View File

@ -473,8 +473,6 @@ void DivPlatformK007232::notifyInsChange(int ins) {
}
void DivPlatformK007232::notifyWaveChange(int wave) {
// TODO when wavetables are added
// TODO they probably won't be added unless the samples reside in RAM
}
void DivPlatformK007232::notifyInsDeletion(void* ins) {

View File

@ -409,8 +409,6 @@ void DivPlatformK053260::notifyInsChange(int ins) {
}
void DivPlatformK053260::notifyWaveChange(int wave) {
// TODO when wavetables are added
// TODO they probably won't be added unless the samples reside in RAM
}
void DivPlatformK053260::notifyInsDeletion(void* ins) {

View File

@ -355,8 +355,6 @@ void DivPlatformRF5C68::notifyInsChange(int ins) {
}
void DivPlatformRF5C68::notifyWaveChange(int wave) {
// TODO when wavetables are added
// TODO they probably won't be added unless the samples reside in RAM
}
void DivPlatformRF5C68::notifyInsDeletion(void* ins) {

View File

@ -459,7 +459,7 @@ DivMacroInt* DivPlatformSoundUnit::getChanMacroInt(int ch) {
}
unsigned short DivPlatformSoundUnit::getPan(int ch) {
return parent->convertPanLinearToSplit(chan[ch].pan,8,255);
return parent->convertPanLinearToSplit(chan[ch].pan^0x80,8,255);
}
DivDispatchOscBuffer* DivPlatformSoundUnit::getOscBuffer(int ch) {

View File

@ -478,8 +478,6 @@ void FurnaceGUI::drawChanOsc() {
needlePos-=phase;
}
chanOscPitch[ch]=(float)point/32.0f;
needlePos-=displaySize;
for (unsigned short i=0; i<precision; i++) {

View File

@ -417,6 +417,7 @@ void FurnaceGUI::decodeMMLStr(String& source, int* macro, unsigned char& macroLe
}
bool FurnaceGUI::CWSliderScalar(const char* label, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags) {
flags^=ImGuiSliderFlags_AlwaysClamp;
if (ImGui::SliderScalar(label,data_type,p_data,p_min,p_max,format,flags)) {
return true;
}
@ -453,6 +454,7 @@ bool FurnaceGUI::CWSliderScalar(const char* label, ImGuiDataType data_type, void
}
bool FurnaceGUI::CWVSliderScalar(const char* label, const ImVec2& size, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags) {
flags^=ImGuiSliderFlags_AlwaysClamp;
if (ImGui::VSliderScalar(label,size,data_type,p_data,p_min,p_max,format,flags)) {
return true;
}
@ -3491,6 +3493,7 @@ bool FurnaceGUI::loop() {
scrX=ev.window.data1;
scrY=ev.window.data2;
updateWindow=true;
shallDetectScale=2;
logV("window moved to %dx%d",scrX,scrY);
break;
case SDL_WINDOWEVENT_SIZE_CHANGED:
@ -6140,7 +6143,38 @@ bool FurnaceGUI::loop() {
if (shallDetectScale) {
if (--shallDetectScale<1) {
if (settings.dpiScale<0.5f) {
applyUISettings();
const char* videoBackend=SDL_GetCurrentVideoDriver();
double newScale=getScaleFactor(videoBackend,sdlWin);
if (newScale<0.1f) {
logW("scale what?");
newScale=1.0f;
}
if (newScale!=dpiScale) {
logD("auto UI scale changed (%f != %f) - applying settings...",newScale,dpiScale);
ImGui::GetIO().Fonts->Clear();
applyUISettings();
if (rend) rend->destroyFontsTexture();
if (!ImGui::GetIO().Fonts->Build()) {
logE("error while building font atlas!");
showError("error while loading fonts! please check your settings.");
ImGui::GetIO().Fonts->Clear();
mainFont=ImGui::GetIO().Fonts->AddFontDefault();
patFont=mainFont;
bigFont=mainFont;
headFont=mainFont;
if (rend) rend->destroyFontsTexture();
if (!ImGui::GetIO().Fonts->Build()) {
logE("error again while building font atlas!");
} else {
rend->createFontsTexture();
}
} else {
rend->createFontsTexture();
}
}
}
}
}
@ -6368,7 +6402,7 @@ bool FurnaceGUI::init() {
dpiScale=settings.dpiScale;
} else {
logD("auto-detecting UI scale factor.");
dpiScale=getScaleFactor(videoBackend);
dpiScale=getScaleFactor(videoBackend,sdlWin);
logD("scale factor: %f",dpiScale);
if (dpiScale<0.1f) {
logW("scale what?");
@ -6914,6 +6948,8 @@ FurnaceGUI::FurnaceGUI():
displayEditString(false),
mobileEdit(false),
killGraphics(false),
audioEngineChanged(false),
settingsChanged(false),
vgmExportVersion(0x171),
vgmExportTrailingTicks(-1),
drawHalt(10),

View File

@ -1334,6 +1334,7 @@ class FurnaceGUI {
bool displayPendingIns, pendingInsSingle, displayPendingRawSample, snesFilterHex, modTableHex, displayEditString;
bool mobileEdit;
bool killGraphics;
bool audioEngineChanged, settingsChanged;
bool willExport[DIV_MAX_CHIPS];
int vgmExportVersion;
int vgmExportTrailingTicks;

View File

@ -17,4 +17,4 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
double getMacDPIScale();
double getMacDPIScale(void* sysWin, unsigned char isUIKit);

View File

@ -20,7 +20,30 @@
#include <Cocoa/Cocoa.h>
#include "macstuff.h"
double getMacDPIScale() {
CGFloat val=[[NSScreen mainScreen] backingScaleFactor];
double getMacDPIScale(void* sysWin, unsigned char isUIKit) {
NSScreen* screen=nil;
if (sysWin!=NULL) {
if (isUIKit) {
return 1.0;
/*
UIWindow* win=(UIWindow*)sysWin;
UIWindowScene* winScene=[win windowScene];
if (winScene!=nil) {
UIScreen* winScreen=[winScene screen];
CGFloat ret=[winScreen scale];
return (double)ret;
}*/
} else {
NSWindow* win=(NSWindow*)sysWin;
screen=[win screen];
}
}
if (screen==nil) {
screen=[NSScreen mainScreen];
}
if (screen==nil) {
return 1.0;
}
CGFloat val=[screen backingScaleFactor];
return (double)val;
}

View File

@ -21,6 +21,7 @@
#include "scaling.h"
#include "../ta-log.h"
#include <SDL.h>
#include <SDL_syswm.h>
#ifdef _WIN32
#include <windows.h>
@ -42,14 +43,23 @@ typedef int (*XDS)(void*);
typedef int (*XDW)(void*,int);
#endif
double getScaleFactor(const char* driverHint) {
double getScaleFactor(const char* driverHint, void* windowHint) {
double ret=1.0;
// Windows
#ifdef _WIN32
POINT nullPoint;
nullPoint.x=-1;
nullPoint.y=-1;
if (windowHint!=NULL) {
int px=0;
int py=0;
SDL_GetWindowPosition((SDL_Window*)windowHint,&px,&py);
nullPoint.x=px;
nullPoint.y=py;
} else {
nullPoint.x=-1;
nullPoint.y=-1;
}
HMONITOR disp=MonitorFromPoint(nullPoint,MONITOR_DEFAULTTOPRIMARY);
if (disp==NULL) {
@ -93,12 +103,34 @@ double getScaleFactor(const char* driverHint) {
return ret;
#endif
// macOS - backingScaleFactor
// macOS
#ifdef __APPLE__
if (driverHint==NULL) {
return getMacDPIScale();
} else if (strcmp(driverHint,"cocoa")==0 || strcmp(driverHint,"uikit")==0) {
return getMacDPIScale();
return getMacDPIScale(NULL,false);
} else if (strcmp(driverHint,"cocoa")==0) {
#ifdef SDL_VIDEO_DRIVER_COCOA
void* nsWindow=NULL;
SDL_SysWMinfo wmInfo;
if (windowHint!=NULL) {
SDL_VERSION(&wmInfo.version)
if (SDL_GetWindowWMInfo((SDL_Window*)windowHint,&wmInfo)==SDL_TRUE) {
nsWindow=wmInfo.info.cocoa.window;
}
}
return getMacDPIScale(nsWindow,false);
#endif
} else if (strcmp(driverHint,"uikit")==0) {
#ifdef SDL_VIDEO_DRIVER_UIKIT
void* uiWindow=NULL;
SDL_SysWMinfo wmInfo;
if (windowHint!=NULL) {
SDL_VERSION(&wmInfo.version)
if (SDL_GetWindowWMInfo((SDL_Window*)windowHint,&wmInfo)==SDL_TRUE) {
uiWindow=wmInfo.info.uikit.window;
}
}
return getMacDPIScale(uiWindow,true);
#endif
}
#endif

View File

@ -17,4 +17,4 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
double getScaleFactor(const char* driverHint);
double getScaleFactor(const char* driverHint, void* windowHint);

View File

@ -734,16 +734,21 @@ void FurnaceGUI::drawSettings() {
ImGui::TableNextColumn();
int prevAudioEngine=settings.audioEngine;
if (ImGui::BeginCombo("##Backend",audioBackends[settings.audioEngine])) {
#ifdef HAVE_JACK
if (ImGui::Selectable("JACK",settings.audioEngine==DIV_AUDIO_JACK)) {
settings.audioEngine=DIV_AUDIO_JACK;
}
#endif
if (ImGui::Selectable("SDL",settings.audioEngine==DIV_AUDIO_SDL)) {
settings.audioEngine=DIV_AUDIO_SDL;
}
#ifdef HAVE_PA
if (ImGui::Selectable("PortAudio",settings.audioEngine==DIV_AUDIO_PORTAUDIO)) {
settings.audioEngine=DIV_AUDIO_PORTAUDIO;
}
#endif
if (settings.audioEngine!=prevAudioEngine) {
audioEngineChanged=true;
if (!isProAudio[settings.audioEngine]) settings.audioChans=2;
}
ImGui::EndCombo();
@ -777,17 +782,30 @@ void FurnaceGUI::drawSettings() {
ImGui::AlignTextToFramePadding();
ImGui::Text("Device");
ImGui::TableNextColumn();
String audioDevName=settings.audioDevice.empty()?"<System default>":settings.audioDevice;
if (ImGui::BeginCombo("##AudioDevice",audioDevName.c_str())) {
if (ImGui::Selectable("<System default>",settings.audioDevice.empty())) {
settings.audioDevice="";
}
for (String& i: e->getAudioDevices()) {
if (ImGui::Selectable(i.c_str(),i==settings.audioDevice)) {
settings.audioDevice=i;
if (audioEngineChanged) {
ImGui::BeginDisabled();
if (ImGui::BeginCombo("##AudioDevice","<click on OK or Apply first>")) {
ImGui::Text("ALERT - TRESPASSER DETECTED");
if (ImGui::IsItemHovered()) {
showError("you have been arrested for trying to engage with a disabled combo box.");
ImGui::CloseCurrentPopup();
}
ImGui::EndCombo();
}
ImGui::EndDisabled();
} else {
String audioDevName=settings.audioDevice.empty()?"<System default>":settings.audioDevice;
if (ImGui::BeginCombo("##AudioDevice",audioDevName.c_str())) {
if (ImGui::Selectable("<System default>",settings.audioDevice.empty())) {
settings.audioDevice="";
}
for (String& i: e->getAudioDevices()) {
if (ImGui::Selectable(i.c_str(),i==settings.audioDevice)) {
settings.audioDevice=i;
}
}
ImGui::EndCombo();
}
ImGui::EndCombo();
}
ImGui::TableNextRow();
@ -3031,6 +3049,7 @@ void FurnaceGUI::drawSettings() {
ImGui::SameLine();
if (ImGui::Button("Cancel##SettingsCancel")) {
settingsOpen=false;
audioEngineChanged=false;
syncSettings();
}
ImGui::SameLine();
@ -3057,7 +3076,7 @@ void FurnaceGUI::syncSettings() {
settings.patFontSize=e->getConfInt("patFontSize",18);
settings.iconSize=e->getConfInt("iconSize",16);
settings.audioEngine=(e->getConfString("audioEngine","SDL")=="SDL")?1:0;
if (e->getConfString("audioEngine","SDL")=="PortAudio") {
if (e->getConfString("audioEngine","SDL")=="JACK") {
settings.audioEngine=DIV_AUDIO_JACK;
} else if (e->getConfString("audioEngine","SDL")=="PortAudio") {
settings.audioEngine=DIV_AUDIO_PORTAUDIO;
@ -3690,6 +3709,8 @@ void FurnaceGUI::commitSettings() {
} else {
rend->createFontsTexture();
}
audioEngineChanged=false;
}
bool FurnaceGUI::importColors(String path) {
@ -4132,18 +4153,20 @@ void FurnaceGUI::applyUISettings(bool updateFonts) {
setupLabel(settings.emptyLabel.c_str(),emptyLabel,3);
setupLabel(settings.emptyLabel2.c_str(),emptyLabel2,2);
// get scale factor
const char* videoBackend=SDL_GetCurrentVideoDriver();
if (settings.dpiScale>=0.5f) {
logD("setting UI scale factor from config (%f).",settings.dpiScale);
dpiScale=settings.dpiScale;
} else {
logD("auto-detecting UI scale factor.");
dpiScale=getScaleFactor(videoBackend);
logD("scale factor: %f",dpiScale);
if (dpiScale<0.1f) {
logW("scale what?");
dpiScale=1.0f;
if (updateFonts) {
// get scale factor
const char* videoBackend=SDL_GetCurrentVideoDriver();
if (settings.dpiScale>=0.5f) {
logD("setting UI scale factor from config (%f).",settings.dpiScale);
dpiScale=settings.dpiScale;
} else {
logD("auto-detecting UI scale factor.");
dpiScale=getScaleFactor(videoBackend,sdlWin);
logD("scale factor: %f",dpiScale);
if (dpiScale<0.1f) {
logW("scale what?");
dpiScale=1.0f;
}
}
}