2261 lines · 63.2 KB · C
RawDownload
// 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.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t