// for finding memory leaks in debug mode with Visual Studio#if defined _DEBUG && defined _MSC_VER#include <crtdbg.h>#endif #include <stdint.h>#include <stdio.h>#include <math.h>#ifdef _WIN32#define _WIN32_IE 0x0500#define WIN32_MEAN_AND_LEAN#include <windows.h>#include <shlobj.h>#include <direct.h>#else#include <sys/stat.h>#include <unistd.h>#endif#include "ft2_header.h"#include "ft2_video.h"#include "ft2_audio.h"#include "ft2_config.h"#include "ft2_gui.h"#include "ft2_pattern_ed.h"#include "ft2_mouse.h"#include "ft2_wav_renderer.h"#include "ft2_sampling.h"#include "ft2_audioselector.h"#include "ft2_midi.h"#include "ft2_palette.h"#include "ft2_pattern_draw.h"#include "ft2_tables.h"#include "ft2_bmp.h"#include "ft2_structs.h"#include "ft2_cpu.h" config_t config; // globalized #ifdef _MSC_VER // hide POSIX warnings#pragma warning(disable: 4996)#endif static uint8_t configBuffer[CONFIG_FILE_SIZE]; static void xorConfigBuffer(uint8_t *ptr8){ for (int32_t i = 0; i < CONFIG_FILE_SIZE; i++) ptr8[i] ^= i*7;} static int32_t calcChecksum(const uint8_t *p, uint16_t len) // for Nibbles highscore data{ if (len == 0) return 0; uint16_t data = 0; uint32_t checksum = 0; for (uint16_t i = len; i > 0; i--) { data = ((data | *p++) + i) ^ i; checksum += data; data <<= 8; } return checksum;} static void loadConfigFromBuffer(bool defaults){ lockMixerCallback(); assert(sizeof(config) == CONFIG_FILE_SIZE); memcpy(&config, configBuffer, CONFIG_FILE_SIZE); if (defaults) config.audioFreq = DEFAULT_AUDIO_FREQ; if (config.audioFreq > MAX_AUDIO_FREQ) config.audioFreq = MAX_AUDIO_FREQ; // if Nibbles highscore checksum is incorrect, load default highscores instead const int32_t newChecksum = calcChecksum((uint8_t *)&config.NI_HighScore, sizeof (config.NI_HighScore)); if (newChecksum != config.NI_HighScoreChecksum) memcpy(&config.NI_HighScore, &defConfigData[636], sizeof (config.NI_HighScore)); // sanitize Nibbles highscore names for (int32_t i = 0; i < 10; i++) { config.NI_HighScore[i].name[21] = '\0'; if (config.NI_HighScore[i].nameLen > 21) config.NI_HighScore[i].nameLen = 21; } // clamp user palette values for (int32_t i = 0; i < 16; i++) { config.userPal->r = palMax(config.userPal->r); config.userPal->g = palMax(config.userPal->g); config.userPal->b = palMax(config.userPal->b); } // copy over user palette memcpy(palTable[11], config.userPal, sizeof (pal16) * 16); // sanitize certain values config.modulesPath[80-1] = '\0'; config.instrPath[80-1] = '\0'; config.samplesPath[80-1] = '\0'; config.patternsPath[80-1] = '\0'; config.tracksPath[80-1] = '\0'; // clear data after the actual Pascal string length. FT2 can save garbage in that area. if (config.modulesPathLen < 80) memset(&config.modulesPath[config.modulesPathLen], 0, 80-config.modulesPathLen); if (config.instrPathLen < 80) memset(&config.instrPath[config.instrPathLen], 0, 80-config.instrPathLen); if (config.samplesPathLen < 80) memset(&config.samplesPath[config.samplesPathLen], 0, 80-config.samplesPathLen); if (config.patternsPathLen < 80) memset(&config.patternsPath[config.patternsPathLen], 0, 80-config.patternsPathLen); if (config.tracksPathLen < 80) memset(&config.tracksPath[config.tracksPathLen], 0, 80-config.tracksPathLen); config.boostLevel = CLAMP(config.boostLevel, 1, 32); config.masterVol = CLAMP(config.masterVol, 0, 256); config.ptnMaxChannels = CLAMP(config.ptnMaxChannels, 0, 3); config.ptnFont = CLAMP(config.ptnFont, 0, 3); config.mouseType = CLAMP(config.mouseType, 0, 3); config.cfg_StdPalNum = CLAMP(config.cfg_StdPalNum, 0, 11); config.cfg_SortPriority = CLAMP(config.cfg_SortPriority, 0, 1); config.NI_NumPlayers = CLAMP(config.NI_NumPlayers, 0, 1); config.NI_Speed = CLAMP(config.NI_Speed, 0, 3); config.recMIDIVolSens = CLAMP(config.recMIDIVolSens, 0, 200); config.recMIDIChn = CLAMP(config.recMIDIChn, 1, 16); config.interpolation &= 3; // one extra bit used in FT2 clone (off, sinc, linear) if (config.recTrueInsert > 1) config.recTrueInsert = 1; if (config.mouseAnimType != 0 && config.mouseAnimType != 2) config.mouseAnimType = 0; if (config.recQuantRes != 1 && config.recQuantRes != 2 && config.recQuantRes != 4 && config.recQuantRes != 8 && config.recQuantRes != 16) { config.recQuantRes = 16; } #if CPU_64BIT if (config.audioFreq != 44100 && config.audioFreq != 48000 && config.audioFreq != 96000)#else if (config.audioFreq != 44100 && config.audioFreq != 48000)#endif config.audioFreq = DEFAULT_AUDIO_FREQ; if (config.audioInputFreq <= 1) // default value from FT2 (this was cdr_Sync) - set defaults config.audioInputFreq = INPUT_FREQ_48KHZ; if (config.specialFlags == 64) // default value from FT2 (this was ptnDefaultLen byte #1) - set defaults config.specialFlags = BUFFSIZE_1024 | BITDEPTH_16; if (config.specialFlags & 64) // deprecated BUFFSIZE_4096 ("Very large") setting { // set to current highest setting ("Large" aka. 2048) config.specialFlags &= ~(BUFFSIZE_1024 + 64); config.specialFlags |= BUFFSIZE_2048; } if (config.windowFlags == 0) // default value from FT2 (this was ptnDefaultLen byte #2) - set defaults config.windowFlags = WINSIZE_AUTO; // audio bit depth - remove 32-bit flag if both are enabled if ((config.specialFlags & BITDEPTH_16) && (config.specialFlags & BITDEPTH_32)) config.specialFlags &= ~BITDEPTH_32; if (audio.dev != 0) setNewAudioSettings(); audioSetInterpolationType(config.interpolation); audioSetVolRamp((config.specialFlags & NO_VOLRAMP_FLAG) ? false : true); setAudioAmp(config.boostLevel, config.masterVol, !!(config.specialFlags & BITDEPTH_32)); setMouseShape(config.mouseType); changeLogoType(config.id_FastLogo); changeBadgeType(config.id_TritonProd); ui.maxVisibleChannels = (uint8_t)(2 + ((config.ptnMaxChannels + 1) * 2)); setPal16(palTable[config.cfg_StdPalNum], true); updatePattFontPtrs(); unlockMixerCallback();} static void configDrawAmp(void){ char str[8]; sprintf(str, "%02d", config.boostLevel); textOutFixed(607, 105, PAL_FORGRND, PAL_DESKTOP, str);} static void configDrawMasterVol(void){ char str[9]; sprintf(str, "%3d", config.masterVol); fillRect(607, 133, 20, 8, PAL_DESKTOP); textOutFixed(607, 133, PAL_FORGRND, PAL_DESKTOP, str);} static void setDefaultConfigSettings(void){ memcpy(configBuffer, defConfigData, CONFIG_FILE_SIZE); loadConfigFromBuffer(true);} static void updateImageStretchAndPixelFilter(uint8_t oldWindowFlags, uint8_t oldSpecialFlags2){ bool didFullscreenUpdate = false; // handle pixel filter change if ((oldWindowFlags & PIXEL_FILTER) != (config.windowFlags & PIXEL_FILTER)) { recreateTexture(); if (video.fullscreen) // force an update if in fullscreen mode { leaveFullscreen(); enterFullscreen(); didFullscreenUpdate = true; } } // handle image stretch change if ((oldSpecialFlags2 & STRETCH_IMAGE) != (config.specialFlags2 & STRETCH_IMAGE)) { if (video.fullscreen && !didFullscreenUpdate) // force an update if in fullscreen mode { leaveFullscreen(); enterFullscreen(); } }} void resetConfig(void){ if (okBox(2, "System request", "Are you sure you want to reset your FT2 configuration?") != 1) return; const uint8_t oldWindowFlags = config.windowFlags; const uint8_t oldSpecialFlags2 = config.specialFlags2; setDefaultConfigSettings(); setToDefaultAudioOutputDevice(); setToDefaultAudioInputDevice(); saveConfig(false); // redraw new changes showTopScreen(false); showBottomScreen(); setWindowSizeFromConfig(true); updateImageStretchAndPixelFilter(oldWindowFlags, oldSpecialFlags2); if (config.specialFlags2 & HARDWARE_MOUSE) SDL_ShowCursor(SDL_TRUE); else SDL_ShowCursor(SDL_FALSE);} bool loadConfig(bool showErrorFlag){ // this routine can be called at any time, so make sure we free these first... if (audio.currOutputDevice != NULL) { free(audio.currOutputDevice); audio.currOutputDevice = NULL; } if (audio.currInputDevice != NULL) { free(audio.currInputDevice); audio.currInputDevice = NULL; } // now we can get the audio devices from audiodev.ini audio.currOutputDevice = getAudioOutputDeviceFromConfig(); audio.currInputDevice = getAudioInputDeviceFromConfig(); #ifdef HAS_MIDI if (midi.initThreadDone) { setMidiInputDeviceFromConfig(); if (ui.configScreenShown && editor.currConfigScreen == CONFIG_SCREEN_MIDI_INPUT) drawMidiInputList(); }#endif if (editor.configFileLocationU == NULL) { if (showErrorFlag) okBox(0, "System message", "Error opening config file for reading!"); return false; } FILE *f = UNICHAR_FOPEN(editor.configFileLocationU, "rb"); if (f == NULL) { if (showErrorFlag) okBox(0, "System message", "Error opening config file for reading!"); return false; } fseek(f, 0, SEEK_END); const size_t fileSize = ftell(f); rewind(f); // check if it's a valid FT2 config file (FT2.CFG filesize varies depending on version) if (fileSize < 1732 || fileSize > CONFIG_FILE_SIZE) { fclose(f); if (showErrorFlag) okBox(0, "System message", "Error loading config: the config file is not valid!"); return false; } if (fileSize < CONFIG_FILE_SIZE) // old version, make sure unloaded entries are zeroed out memset(configBuffer, 0, CONFIG_FILE_SIZE); // read to config buffer and close file handle if (fread(configBuffer, fileSize, 1, f) != 1) { fclose(f); if (showErrorFlag) okBox(0, "System message", "Error opening config file for reading!"); return false; } fclose(f); xorConfigBuffer(configBuffer); // decrypt config buffer if (memcmp(&configBuffer[0], CFG_ID_STR, 35) != 0) { if (showErrorFlag) okBox(0, "System message", "Error loading config: the config file is not valid!"); return false; } loadConfigFromBuffer(false); return true;} void loadConfig2(void) // called by "Load config" button{ const uint8_t oldWindowFlags = config.windowFlags; const uint8_t oldSpecialFlags2 = config.specialFlags2; loadConfig(CONFIG_SHOW_ERRORS); // redraw new changes showTopScreen(false); showBottomScreen(); setWindowSizeFromConfig(true); updateImageStretchAndPixelFilter(oldWindowFlags, oldSpecialFlags2); if (config.specialFlags2 & HARDWARE_MOUSE) SDL_ShowCursor(SDL_TRUE); else SDL_ShowCursor(SDL_FALSE);} bool saveConfig(bool showErrorFlag){ if (editor.configFileLocationU == NULL) { if (showErrorFlag) okBox(0, "System message", "General I/O error during saving! Is the file in use?"); return false; } saveAudioDevicesToConfig(audio.currOutputDevice, audio.currInputDevice);#ifdef HAS_MIDI saveMidiInputDeviceToConfig();#endif FILE *f = UNICHAR_FOPEN(editor.configFileLocationU, "wb"); if (f == NULL) { if (showErrorFlag) okBox(0, "System message", "General I/O error during config saving! Is the file in use?"); return false; } config.NI_HighScoreChecksum = calcChecksum((uint8_t *)config.NI_HighScore, sizeof (config.NI_HighScore)); // set default path lengths (Pascal strings) config.modulesPathLen = (uint8_t)strlen(config.modulesPath); config.instrPathLen = (uint8_t)strlen(config.instrPath); config.samplesPathLen = (uint8_t)strlen(config.samplesPath); config.patternsPathLen = (uint8_t)strlen(config.patternsPath); config.tracksPathLen = (uint8_t)strlen(config.tracksPath); // copy over user palette memcpy(config.userPal, palTable[11], sizeof (pal16) * 16); // copy config to buffer and encrypt it memcpy(configBuffer, &config, CONFIG_FILE_SIZE); xorConfigBuffer(configBuffer); if (fwrite(configBuffer, 1, CONFIG_FILE_SIZE, f) != CONFIG_FILE_SIZE) { fclose(f); if (showErrorFlag) okBox(0, "System message", "General I/O error during config saving! Is the file in use?"); return false; } fclose(f); return true;} void saveConfig2(void) // called by "Save config" button{ saveConfig(CONFIG_SHOW_ERRORS);} static UNICHAR *getFullAudDevConfigPathU(void) // kinda hackish{ int32_t audiodevDotIniStrLen, ft2DotCfgStrLen; if (editor.configFileLocationU == NULL) return NULL; const int32_t ft2ConfPathLen = (int32_t)UNICHAR_STRLEN(editor.configFileLocationU); #ifdef _WIN32 audiodevDotIniStrLen = (int32_t)UNICHAR_STRLEN(L"audiodev.ini"); ft2DotCfgStrLen = (int32_t)UNICHAR_STRLEN(L"FT2.CFG");#else audiodevDotIniStrLen = (int32_t)UNICHAR_STRLEN("audiodev.ini"); ft2DotCfgStrLen = (int32_t)UNICHAR_STRLEN("FT2.CFG");#endif UNICHAR *filePathU = (UNICHAR *)malloc((ft2ConfPathLen + audiodevDotIniStrLen + 1) * sizeof (UNICHAR)); filePathU[0] = 0; UNICHAR_STRCPY(filePathU, editor.configFileLocationU); filePathU[ft2ConfPathLen-ft2DotCfgStrLen] = 0; #ifdef _WIN32 UNICHAR_STRCAT(filePathU, L"audiodev.ini");#else UNICHAR_STRCAT(filePathU, "audiodev.ini");#endif return filePathU;} static UNICHAR *getFullMidiDevConfigPathU(void) // kinda hackish{ int32_t mididevDotIniStrLen, ft2DotCfgStrLen; if (editor.configFileLocationU == NULL) return NULL; const int32_t ft2ConfPathLen = (int32_t)UNICHAR_STRLEN(editor.configFileLocationU); #ifdef _WIN32 mididevDotIniStrLen = (int32_t)UNICHAR_STRLEN(L"mididev.ini"); ft2DotCfgStrLen = (int32_t)UNICHAR_STRLEN(L"FT2.CFG");#else mididevDotIniStrLen = (int32_t)UNICHAR_STRLEN("mididev.ini"); ft2DotCfgStrLen = (int32_t)UNICHAR_STRLEN("FT2.CFG");#endif UNICHAR *filePathU = (UNICHAR *)malloc((ft2ConfPathLen + mididevDotIniStrLen + 1) * sizeof (UNICHAR)); filePathU[0] = 0; UNICHAR_STRCPY(filePathU, editor.configFileLocationU); filePathU[ft2ConfPathLen-ft2DotCfgStrLen] = 0; #ifdef _WIN32 UNICHAR_STRCAT(filePathU, L"mididev.ini");Lines 1–500 of 2261. Load more
// for finding memory leaks in debug mode with Visual Studio #if defined _DEBUG && defined _MSC_VER #include <crtdbg.h> #endif #include <stdint.h> #include <stdio.h> #include <math.h> #ifdef _WIN32 #define _WIN32_IE 0x0500 #define WIN32_MEAN_AND_LEAN #include <windows.h> #include <shlobj.h> #include <direct.h> #else #include <sys/stat.h> #include <unistd.h> #endif #include "ft2_header.h" #include "ft2_video.h" #include "ft2_audio.h" #include "ft2_config.h" #include "ft2_gui.h" #include "ft2_pattern_ed.h" #include "ft2_mouse.h" #include "ft2_wav_renderer.h" #include "ft2_sampling.h" #include "ft2_audioselector.h" #include "ft2_midi.h" #include "ft2_palette.h" #include "ft2_pattern_draw.h" #include "ft2_tables.h" #include "ft2_bmp.h" #include "ft2_structs.h" #include "ft2_cpu.h" config_t config; // globalized #ifdef _MSC_VER // hide POSIX warnings #pragma warning(disable: 4996) #endif static uint8_t configBuffer[CONFIG_FILE_SIZE]; static void xorConfigBuffer(uint8_t *ptr8) { for (int32_t i = 0; i < CONFIG_FILE_SIZE; i++) ptr8[i] ^= i*7; } static int32_t calcChecksum(const uint8_t *p, uint16_t len) // for Nibbles highscore data { if (len == 0) return 0; uint16_t data = 0; uint32_t checksum = 0; for (uint16_t i = len; i > 0; i--) { data = ((data | *p++) + i) ^ i; checksum += data; data <<= 8; } return checksum; } static void loadConfigFromBuffer(bool defaults) { lockMixerCallback(); assert(sizeof(config) == CONFIG_FILE_SIZE); memcpy(&config, configBuffer, CONFIG_FILE_SIZE); if (defaults) config.audioFreq = DEFAULT_AUDIO_FREQ; if (config.audioFreq > MAX_AUDIO_FREQ) config.audioFreq = MAX_AUDIO_FREQ; // if Nibbles highscore checksum is incorrect, load default highscores instead const int32_t newChecksum = calcChecksum((uint8_t *)&config.NI_HighScore, sizeof (config.NI_HighScore)); if (newChecksum != config.NI_HighScoreChecksum) memcpy(&config.NI_HighScore, &defConfigData[636], sizeof (config.NI_HighScore)); // sanitize Nibbles highscore names for (int32_t i = 0; i < 10; i++) { config.NI_HighScore[i].name[21] = '\0'; if (config.NI_HighScore[i].nameLen > 21) config.NI_HighScore[i].nameLen = 21; } // clamp user palette values for (int32_t i = 0; i < 16; i++) { config.userPal->r = palMax(config.userPal->r); config.userPal->g = palMax(config.userPal->g); config.userPal->b = palMax(config.userPal->b); } // copy over user palette memcpy(palTable[11], config.userPal, sizeof (pal16) * 16); // sanitize certain values config.modulesPath[80-1] = '\0'; config.instrPath[80-1] = '\0'; config.samplesPath[80-1] = '\0'; config.patternsPath[80-1] = '\0'; config.tracksPath[80-1] = '\0'; // clear data after the actual Pascal string length. FT2 can save garbage in that area. if (config.modulesPathLen < 80) memset(&config.modulesPath[config.modulesPathLen], 0, 80-config.modulesPathLen); if (config.instrPathLen < 80) memset(&config.instrPath[config.instrPathLen], 0, 80-config.instrPathLen); if (config.samplesPathLen < 80) memset(&config.samplesPath[config.samplesPathLen], 0, 80-config.samplesPathLen); if (config.patternsPathLen < 80) memset(&config.patternsPath[config.patternsPathLen], 0, 80-config.patternsPathLen); if (config.tracksPathLen < 80) memset(&config.tracksPath[config.tracksPathLen], 0, 80-config.tracksPathLen); config.boostLevel = CLAMP(config.boostLevel, 1, 32); config.masterVol = CLAMP(config.masterVol, 0, 256); config.ptnMaxChannels = CLAMP(config.ptnMaxChannels, 0, 3); config.ptnFont = CLAMP(config.ptnFont, 0, 3); config.mouseType = CLAMP(config.mouseType, 0, 3); config.cfg_StdPalNum = CLAMP(config.cfg_StdPalNum, 0, 11); config.cfg_SortPriority = CLAMP(config.cfg_SortPriority, 0, 1); config.NI_NumPlayers = CLAMP(config.NI_NumPlayers, 0, 1); config.NI_Speed = CLAMP(config.NI_Speed, 0, 3); config.recMIDIVolSens = CLAMP(config.recMIDIVolSens, 0, 200); config.recMIDIChn = CLAMP(config.recMIDIChn, 1, 16); config.interpolation &= 3; // one extra bit used in FT2 clone (off, sinc, linear) if (config.recTrueInsert > 1) config.recTrueInsert = 1; if (config.mouseAnimType != 0 && config.mouseAnimType != 2) config.mouseAnimType = 0; if (config.recQuantRes != 1 && config.recQuantRes != 2 && config.recQuantRes != 4 && config.recQuantRes != 8 && config.recQuantRes != 16) { config.recQuantRes = 16; } #if CPU_64BIT if (config.audioFreq != 44100 && config.audioFreq != 48000 && config.audioFreq != 96000) #else if (config.audioFreq != 44100 && config.audioFreq != 48000) #endif config.audioFreq = DEFAULT_AUDIO_FREQ; if (config.audioInputFreq <= 1) // default value from FT2 (this was cdr_Sync) - set defaults config.audioInputFreq = INPUT_FREQ_48KHZ; if (config.specialFlags == 64) // default value from FT2 (this was ptnDefaultLen byte #1) - set defaults config.specialFlags = BUFFSIZE_1024 | BITDEPTH_16; if (config.specialFlags & 64) // deprecated BUFFSIZE_4096 ("Very large") setting { // set to current highest setting ("Large" aka. 2048) config.specialFlags &= ~(BUFFSIZE_1024 + 64); config.specialFlags |= BUFFSIZE_2048; } if (config.windowFlags == 0) // default value from FT2 (this was ptnDefaultLen byte #2) - set defaults config.windowFlags = WINSIZE_AUTO; // audio bit depth - remove 32-bit flag if both are enabled if ((config.specialFlags & BITDEPTH_16) && (config.specialFlags & BITDEPTH_32)) config.specialFlags &= ~BITDEPTH_32; if (audio.dev != 0) setNewAudioSettings(); audioSetInterpolationType(config.interpolation); audioSetVolRamp((config.specialFlags & NO_VOLRAMP_FLAG) ? false : true); setAudioAmp(config.boostLevel, config.masterVol, !!(config.specialFlags & BITDEPTH_32)); setMouseShape(config.mouseType); changeLogoType(config.id_FastLogo); changeBadgeType(config.id_TritonProd); ui.maxVisibleChannels = (uint8_t)(2 + ((config.ptnMaxChannels + 1) * 2)); setPal16(palTable[config.cfg_StdPalNum], true); updatePattFontPtrs(); unlockMixerCallback(); } static void configDrawAmp(void) { char str[8]; sprintf(str, "%02d", config.boostLevel); textOutFixed(607, 105, PAL_FORGRND, PAL_DESKTOP, str); } static void configDrawMasterVol(void) { char str[9]; sprintf(str, "%3d", config.masterVol); fillRect(607, 133, 20, 8, PAL_DESKTOP); textOutFixed(607, 133, PAL_FORGRND, PAL_DESKTOP, str); } static void setDefaultConfigSettings(void) { memcpy(configBuffer, defConfigData, CONFIG_FILE_SIZE); loadConfigFromBuffer(true); } static void updateImageStretchAndPixelFilter(uint8_t oldWindowFlags, uint8_t oldSpecialFlags2) { bool didFullscreenUpdate = false; // handle pixel filter change if ((oldWindowFlags & PIXEL_FILTER) != (config.windowFlags & PIXEL_FILTER)) { recreateTexture(); if (video.fullscreen) // force an update if in fullscreen mode { leaveFullscreen(); enterFullscreen(); didFullscreenUpdate = true; } } // handle image stretch change if ((oldSpecialFlags2 & STRETCH_IMAGE) != (config.specialFlags2 & STRETCH_IMAGE)) { if (video.fullscreen && !didFullscreenUpdate) // force an update if in fullscreen mode { leaveFullscreen(); enterFullscreen(); } } } void resetConfig(void) { if (okBox(2, "System request", "Are you sure you want to reset your FT2 configuration?") != 1) return; const uint8_t oldWindowFlags = config.windowFlags; const uint8_t oldSpecialFlags2 = config.specialFlags2; setDefaultConfigSettings(); setToDefaultAudioOutputDevice(); setToDefaultAudioInputDevice(); saveConfig(false); // redraw new changes showTopScreen(false); showBottomScreen(); setWindowSizeFromConfig(true); updateImageStretchAndPixelFilter(oldWindowFlags, oldSpecialFlags2); if (config.specialFlags2 & HARDWARE_MOUSE) SDL_ShowCursor(SDL_TRUE); else SDL_ShowCursor(SDL_FALSE); } bool loadConfig(bool showErrorFlag) { // this routine can be called at any time, so make sure we free these first... if (audio.currOutputDevice != NULL) { free(audio.currOutputDevice); audio.currOutputDevice = NULL; } if (audio.currInputDevice != NULL) { free(audio.currInputDevice); audio.currInputDevice = NULL; } // now we can get the audio devices from audiodev.ini audio.currOutputDevice = getAudioOutputDeviceFromConfig(); audio.currInputDevice = getAudioInputDeviceFromConfig(); #ifdef HAS_MIDI if (midi.initThreadDone) { setMidiInputDeviceFromConfig(); if (ui.configScreenShown && editor.currConfigScreen == CONFIG_SCREEN_MIDI_INPUT) drawMidiInputList(); } #endif if (editor.configFileLocationU == NULL) { if (showErrorFlag) okBox(0, "System message", "Error opening config file for reading!"); return false; } FILE *f = UNICHAR_FOPEN(editor.configFileLocationU, "rb"); if (f == NULL) { if (showErrorFlag) okBox(0, "System message", "Error opening config file for reading!"); return false; } fseek(f, 0, SEEK_END); const size_t fileSize = ftell(f); rewind(f); // check if it's a valid FT2 config file (FT2.CFG filesize varies depending on version) if (fileSize < 1732 || fileSize > CONFIG_FILE_SIZE) { fclose(f); if (showErrorFlag) okBox(0, "System message", "Error loading config: the config file is not valid!"); return false; } if (fileSize < CONFIG_FILE_SIZE) // old version, make sure unloaded entries are zeroed out memset(configBuffer, 0, CONFIG_FILE_SIZE); // read to config buffer and close file handle if (fread(configBuffer, fileSize, 1, f) != 1) { fclose(f); if (showErrorFlag) okBox(0, "System message", "Error opening config file for reading!"); return false; } fclose(f); xorConfigBuffer(configBuffer); // decrypt config buffer if (memcmp(&configBuffer[0], CFG_ID_STR, 35) != 0) { if (showErrorFlag) okBox(0, "System message", "Error loading config: the config file is not valid!"); return false; } loadConfigFromBuffer(false); return true; } void loadConfig2(void) // called by "Load config" button { const uint8_t oldWindowFlags = config.windowFlags; const uint8_t oldSpecialFlags2 = config.specialFlags2; loadConfig(CONFIG_SHOW_ERRORS); // redraw new changes showTopScreen(false); showBottomScreen(); setWindowSizeFromConfig(true); updateImageStretchAndPixelFilter(oldWindowFlags, oldSpecialFlags2); if (config.specialFlags2 & HARDWARE_MOUSE) SDL_ShowCursor(SDL_TRUE); else SDL_ShowCursor(SDL_FALSE); } bool saveConfig(bool showErrorFlag) { if (editor.configFileLocationU == NULL) { if (showErrorFlag) okBox(0, "System message", "General I/O error during saving! Is the file in use?"); return false; } saveAudioDevicesToConfig(audio.currOutputDevice, audio.currInputDevice); #ifdef HAS_MIDI saveMidiInputDeviceToConfig(); #endif FILE *f = UNICHAR_FOPEN(editor.configFileLocationU, "wb"); if (f == NULL) { if (showErrorFlag) okBox(0, "System message", "General I/O error during config saving! Is the file in use?"); return false; } config.NI_HighScoreChecksum = calcChecksum((uint8_t *)config.NI_HighScore, sizeof (config.NI_HighScore)); // set default path lengths (Pascal strings) config.modulesPathLen = (uint8_t)strlen(config.modulesPath); config.instrPathLen = (uint8_t)strlen(config.instrPath); config.samplesPathLen = (uint8_t)strlen(config.samplesPath); config.patternsPathLen = (uint8_t)strlen(config.patternsPath); config.tracksPathLen = (uint8_t)strlen(config.tracksPath); // copy over user palette memcpy(config.userPal, palTable[11], sizeof (pal16) * 16); // copy config to buffer and encrypt it memcpy(configBuffer, &config, CONFIG_FILE_SIZE); xorConfigBuffer(configBuffer); if (fwrite(configBuffer, 1, CONFIG_FILE_SIZE, f) != CONFIG_FILE_SIZE) { fclose(f); if (showErrorFlag) okBox(0, "System message", "General I/O error during config saving! Is the file in use?"); return false; } fclose(f); return true; } void saveConfig2(void) // called by "Save config" button { saveConfig(CONFIG_SHOW_ERRORS); } static UNICHAR *getFullAudDevConfigPathU(void) // kinda hackish { int32_t audiodevDotIniStrLen, ft2DotCfgStrLen; if (editor.configFileLocationU == NULL) return NULL; const int32_t ft2ConfPathLen = (int32_t)UNICHAR_STRLEN(editor.configFileLocationU); #ifdef _WIN32 audiodevDotIniStrLen = (int32_t)UNICHAR_STRLEN(L"audiodev.ini"); ft2DotCfgStrLen = (int32_t)UNICHAR_STRLEN(L"FT2.CFG"); #else audiodevDotIniStrLen = (int32_t)UNICHAR_STRLEN("audiodev.ini"); ft2DotCfgStrLen = (int32_t)UNICHAR_STRLEN("FT2.CFG"); #endif UNICHAR *filePathU = (UNICHAR *)malloc((ft2ConfPathLen + audiodevDotIniStrLen + 1) * sizeof (UNICHAR)); filePathU[0] = 0; UNICHAR_STRCPY(filePathU, editor.configFileLocationU); filePathU[ft2ConfPathLen-ft2DotCfgStrLen] = 0; #ifdef _WIN32 UNICHAR_STRCAT(filePathU, L"audiodev.ini"); #else UNICHAR_STRCAT(filePathU, "audiodev.ini"); #endif return filePathU; } static UNICHAR *getFullMidiDevConfigPathU(void) // kinda hackish { int32_t mididevDotIniStrLen, ft2DotCfgStrLen; if (editor.configFileLocationU == NULL) return NULL; const int32_t ft2ConfPathLen = (int32_t)UNICHAR_STRLEN(editor.configFileLocationU); #ifdef _WIN32 mididevDotIniStrLen = (int32_t)UNICHAR_STRLEN(L"mididev.ini"); ft2DotCfgStrLen = (int32_t)UNICHAR_STRLEN(L"FT2.CFG"); #else mididevDotIniStrLen = (int32_t)UNICHAR_STRLEN("mididev.ini"); ft2DotCfgStrLen = (int32_t)UNICHAR_STRLEN("FT2.CFG"); #endif UNICHAR *filePathU = (UNICHAR *)malloc((ft2ConfPathLen + mididevDotIniStrLen + 1) * sizeof (UNICHAR)); filePathU[0] = 0; UNICHAR_STRCPY(filePathU, editor.configFileLocationU); filePathU[ft2ConfPathLen-ft2DotCfgStrLen] = 0; #ifdef _WIN32 UNICHAR_STRCAT(filePathU, L"mididev.ini");