Sigrid Solveig Haflínudóttirdo not quit on alt+f45d8df0e3 years agoHistory
955 lines · 24.1 KB · C
RawDownload
// for finding memory leaks in debug mode with Visual Studio #if defined _DEBUG && defined _MSC_VER#include <crtdbg.h>#endif #include <stdio.h>#include <stdlib.h>#include <stdint.h>#include <stdbool.h>#include <string.h>#ifdef _WIN32#define WIN32_MEAN_AND_LEAN#include <windows.h>#include <SDL2/SDL_syswm.h>#else#include <signal.h>#include <unistd.h> // chdir()#endif#include <sys/stat.h>#include "pt2_helpers.h"#include "pt2_keyboard.h"#include "pt2_textout.h"#include "pt2_mouse.h"#include "pt2_diskop.h"#include "pt2_sampler.h"#include "pt2_config.h"#include "pt2_visuals.h"#include "pt2_edit.h"#include "pt2_module_loader.h"#include "pt2_module_saver.h"#include "pt2_scopes.h"#include "pt2_audio.h"#include "pt2_bmp.h"#include "pt2_visuals_sync.h"#include "pt2_sampling.h"#include "pt2_askbox.h"#include "pt2_replayer.h"#include "pt2_textedit.h" #define CRASH_TEXT "Oh no! The ProTracker 2 clone has crashed...\nA backup .mod was hopefully " \                   "saved to the current module directory.\n\nPlease report this bug if you can.\n" \                   "Try to mention what you did before the crash happened.\n" \                   "My email is on the bottom of https://16-bits.org" module_t *song = NULL; // globalized static bool backupMadeAfterCrash; #ifdef _WIN32#define SYSMSG_FILE_ARG (WM_USER + 1)#define ARGV_SHARED_MEM_MAX_LEN ((MAX_PATH * 2) + 2) #ifndef _DEBUGbool windowsKeyIsDown;HHOOK g_hKeyboardHook;#endif static HWND hWnd_to;static HANDLE oneInstHandle, hMapFile;static LPCTSTR sharedMemBuf;static TCHAR sharedHwndName[] = TEXT("Local\\PT2CloneHwnd");static TCHAR sharedFileName[] = TEXT("Local\\PT2CloneFilename");static bool handleSingleInstancing(int32_t argc, char **argv);static void closeSingleInstancing(void);static void handleSysMsg(SDL_Event inputEvent);#endif #ifndef _DEBUG#ifdef _WIN32static LONG WINAPI exceptionHandler(EXCEPTION_POINTERS *ptr);#elsestatic void exceptionHandler(int32_t signal);#endif#endif #ifdef _WIN32static void makeSureDirIsProgramDir(void);static void disableWasapi(void);#endif #ifdef __APPLE__static void osxSetDirToProgramDirFromArgs(char **argv);static bool checkIfAppWasTranslocated(int argc, char **argv);#endif static void handleInput(void);static bool initializeVars(void);static void handleSigTerm(void);static void cleanUp(void); static void clearStructs(void){	memset(&keyb, 0, sizeof (keyb));	memset(&mouse, 0, sizeof (mouse));	memset(&video, 0, sizeof (video));	memset(&editor, 0, sizeof (editor));	memset(&diskop, 0, sizeof (diskop));	memset(&cursor, 0, sizeof (cursor));	memset(&ui, 0, sizeof (ui));	memset(&config, 0, sizeof (config));	memset(&audio, 0, sizeof (audio));	memset(&textEdit, 0, sizeof (textEdit)); 	audio.rescanAudioDevicesSupported = true;} int main(int argc, char *argv[]){#ifndef _WIN32	struct sigaction act, oldAct;#endif #if defined _WIN32 || defined __APPLE__	SDL_version sdlVer;#endif 	// for finding memory leaks in debug mode with Visual Studio#if defined _DEBUG && defined _MSC_VER	_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);#endif #if SDL_MAJOR_VERSION == 2 && SDL_MINOR_VERSION == 0 && SDL_PATCHLEVEL < 5#pragma message("WARNING: The SDL2 dev lib is older than ver 2.0.5. You'll get fullscreen mode issues and no audio input sampling.")#pragma message("At least version 2.0.7 is recommended.")#endif 	SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH);	SDL_EnableScreenSaver(); // allow screensaver to activate 	clearStructs(); 	// set up crash handler#ifndef _DEBUG#ifdef _WIN32	SetUnhandledExceptionFilter(exceptionHandler);#else	memset(&act, 0, sizeof (act));	act.sa_handler = exceptionHandler;	act.sa_flags = SA_RESETHAND; 	sigaction(SIGILL | SIGABRT | SIGFPE | SIGSEGV, &act, &oldAct);	sigaction(SIGILL, &act, &oldAct);	sigaction(SIGABRT, &act, &oldAct);	sigaction(SIGFPE, &act, &oldAct);	sigaction(SIGSEGV, &act, &oldAct);#endif#endif 	// on Windows and macOS, test what version SDL2.DLL is (against library version used in compilation)#if defined _WIN32 || defined __APPLE__	SDL_GetVersion(&sdlVer);	if (sdlVer.major != SDL_MAJOR_VERSION || sdlVer.minor != SDL_MINOR_VERSION || sdlVer.patch != SDL_PATCHLEVEL)	{#ifdef _WIN32		showErrorMsgBox("SDL2.dll is not the expected version, the program will terminate.\n\n" \		                "Loaded dll version: %d.%d.%d\n" \		                "Required (compiled with) version: %d.%d.%d",		                sdlVer.major, sdlVer.minor, sdlVer.patch,		                SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL);#else		showErrorMsgBox("The loaded SDL2 library is not the expected version, the program will terminate.\n\n" \		                "Loaded library version: %d.%d.%d\n" \		                "Required (compiled with) version: %d.%d.%d",		                sdlVer.major, sdlVer.minor, sdlVer.patch,		                SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL);#endif		return 0;	}#endif #if defined(_WIN32) || defined(__plan9__)	// ALT+F4 is used in ProTracker, but is "close program" in Windows...#if SDL_MINOR_VERSION >= 24 || (SDL_MINOR_VERSION == 0 && SDL_PATCHLEVEL >= 4)	SDL_SetHint(SDL_HINT_WINDOWS_NO_CLOSE_ON_ALT_F4, "1");#endif#endif #ifdef _WIN32 #ifndef _MSC_VER	SetProcessDPIAware();#endif 	if (!SDL_HasSSE())	{		showErrorMsgBox("Your computer's processor doesn't have the SSE instruction set\n" \		                "which is needed for this program to run. Sorry!");		return 0;	} 	if (!SDL_HasSSE2())	{		showErrorMsgBox("Your computer's processor doesn't have the SSE2 instruction set\n" \		                "which is needed for this program to run. Sorry!");		return 0;	} 	disableWasapi(); // disable problematic WASAPI SDL2 audio driver on Windows (causes clicks/pops sometimes...)	                 // 13.03.2020: This is still needed with SDL 2.0.12...#endif 	/* SDL 2.0.9 for Windows has a serious bug where you need to initialize the joystick subsystem	** (even if you don't use it) or else weird things happen like random stutters, keyboard (rarely) being	** reinitialized in Windows and what not.	** Ref.: https://bugzilla.libsdl.org/show_bug.cgi?id=4391	*/#if defined _WIN32 && SDL_MAJOR_VERSION == 2 && SDL_MINOR_VERSION == 0 && SDL_PATCHLEVEL == 9	if (SDL_Init(SDL_INIT_AUDIO | SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) != 0)#else	if (SDL_Init(SDL_INIT_AUDIO | SDL_INIT_VIDEO) != 0)#endif	{		showErrorMsgBox("Couldn't initialize SDL: %s", SDL_GetError());		return 0;	} 	/* Text input is started by default in SDL2, turn it off to remove ~2ms spikes per key press.	** We manuallay start it again when someone clicks on a text edit box, and stop it when done.	** Ref.: https://bugzilla.libsdl.org/show_bug.cgi?id=4166	*/	SDL_StopTextInput();  #ifdef __APPLE__	if (checkIfAppWasTranslocated(argc, argv))	{		SDL_Quit();		return 0;	}#endif #ifdef __APPLE__	osxSetDirToProgramDirFromArgs(argv);#endif #ifdef _WIN32 	// Windows: the Win key has to be taken over to work like the Amiga key#ifndef _DEBUG	windowsKeyIsDown = false;	g_hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, lowLevelKeyboardProc, GetModuleHandle(NULL), 0);#endif 	makeSureDirIsProgramDir();#endif 	if (!initializeVars())	{		cleanUp();		SDL_Quit();		return 1;	} 	loadConfig(); 	if (!setupVideo())	{		cleanUp();		SDL_Quit();		return 1;	} #ifdef _WIN32	// allow only one instance, and send arguments to it (song to play)	if (handleSingleInstancing(argc, argv))	{		cleanUp();		SDL_Quit();		return 0; // close current instance, the main instance got a message now	} 	SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE);#endif 	hpc_Init();	hpc_SetDurationInHz(&video.vblankHpc, VBLANK_HZ); 	if (!initKaiserTable() || !setupAudio() || !unpackBMPs())	{		cleanUp();		SDL_Quit();		return 1;	} 	setupSprites(); 	song = createEmptyMod();	if (song == NULL)	{		cleanUp();		SDL_Quit();		return 1;	} 	// setup GUI text pointers (for recently allocated song structure)	editor.currEditPatternDisp = &song->currPattern;	editor.currPosDisp = &song->currPos;	editor.currPatternDisp = &song->header.patternTable[0];	editor.currPosEdPattDisp = &song->header.patternTable[0];	editor.currLengthDisp = &song->header.songLength; 	if (!initScopes())	{		cleanUp();		SDL_Quit();		return 1;	} 	modSetTempo(editor.initialTempo, false);	modSetSpeed(editor.initialSpeed); 	updateWindowTitle(MOD_NOT_MODIFIED);	pointerSetMode(POINTER_MODE_IDLE, DO_CARRY);	statusAllRight();	setStatusMessage("PROTRACKER V2.3D", NO_CARRY); 	// load a .MOD from the command arguments if passed (also ignore OS X < 10.9 -psn argument on double-click launch)	if ((argc >= 2 && argv[1][0] != '\0') && (argc != 2 || strncmp(argv[1], "-psn_", 5)))	{		loadModFromArg(argv[1]); 		// play song		if (song->loaded)		{			editor.playMode = PLAY_MODE_NORMAL;			modPlay(DONT_SET_PATTERN, 0, DONT_SET_ROW);			editor.currMode = MODE_PLAY;			pointerSetMode(POINTER_MODE_PLAY, DO_CARRY);			statusAllRight();		}	}	else if (!editor.configFound)	{		displayErrorMsg("CONFIG NOT FOUND!");	} 	displayMainScreen();	fillToVuMetersBgBuffer();	updateCursorPos(); 	SDL_ShowWindow(video.window); 	if (config.startInFullscreen)		toggleFullscreen(); 	changePathToDesktop(); // change path to desktop now	diskOpSetInitPath(); // set path to custom path in config (if present) 	SDL_EventState(SDL_DROPFILE, SDL_ENABLE); 	editor.mainLoopOngoing = true;	hpc_ResetCounters(&video.vblankHpc); // this must be the last thing we do before entering the main loop 	// XXX: if you change anything in the main loop, make sure it goes in the askBox()(pt2_askbox.c) loop too, if needed	while (editor.programRunning)	{		handleThreadedAskBox();		sinkVisualizerBars();		updateChannelSyncBuffer();		readMouseXY();		readKeyModifiers(); // set/clear CTRL/ALT/SHIFT/AMIGA key states		handleInput();		updateMouseCounters();		handleKeyRepeat(keyb.lastRepKey); 		if (!mouse.buttonWaiting && ui.sampleMarkingPos == -1 && !ui.forceSampleDrag && !ui.forceVolDrag && !ui.forceSampleEdit)			handleGUIButtonRepeat(); 		renderFrame();		flipFrame();	} 	cleanUp();	SDL_Quit(); 	return 0;} static void handleInput(void){		SDL_Event event;	while (SDL_PollEvent(&event))	{		if (event.type == SDL_WINDOWEVENT)		{			if (event.window.event == SDL_WINDOWEVENT_HIDDEN)				video.windowHidden = true;			else if (event.window.event == SDL_WINDOWEVENT_SHOWN)				video.windowHidden = false; 			// reset vblank end time if we minimize window			if (event.window.event == SDL_WINDOWEVENT_MINIMIZED || event.window.event == SDL_WINDOWEVENT_FOCUS_LOST)				hpc_ResetCounters(&video.vblankHpc);		} #ifdef _WIN32		handleSysMsg(event);#endif		if (ui.editTextFlag && event.type == SDL_TEXTINPUT)		{			// text input when editing texts/numbers 			char inputChar = event.text.text[0];			if (inputChar == '\0')				continue; 			handleTextEditInputChar(inputChar);			continue; // continue SDL event loop		}		else if (event.type == SDL_MOUSEWHEEL)		{			     if (event.wheel.y < 0) mouseWheelDownHandler();			else if (event.wheel.y > 0) mouseWheelUpHandler();		}		else if (event.type == SDL_DROPFILE)		{			loadDroppedFile(event.drop.file, (uint32_t)strlen(event.drop.file), false, true);			SDL_free(event.drop.file); 			SDL_RestoreWindow(video.window);			SDL_RaiseWindow(video.window);		}		else if (event.type == SDL_QUIT)		{#ifdef __APPLE__			/* On Mac, command+Q sends a quit signal to the program.			** However, command+Q is also one of the transpose keys in this ProTracker port.			** Ignore the signal if command+Q was pressed.			*/			if (!editor.macCmdQIssued)#endif				handleSigTerm(); #ifdef __APPLE__			editor.macCmdQIssued = false; // read note above#endif		}		else if (event.type == SDL_KEYUP)		{			keyUpHandler(event.key.keysym.scancode);		}		else if (event.type == SDL_KEYDOWN)		{			if (editor.repeatKeyFlag || keyb.lastRepKey != event.key.keysym.scancode)				keyDownHandler(event.key.keysym.scancode, event.key.keysym.sym);		}		else if (event.type == SDL_MOUSEBUTTONUP)		{			mouseButtonUpHandler(event.button.button); 			if (ui.introTextShown)			{				if (!ui.diskOpScreenShown && !editor.errorMsgActive && !ui.askBoxShown)					statusAllRight(); 				ui.introTextShown = false;			}		}		else if (event.type == SDL_MOUSEBUTTONDOWN)		{			if (ui.sampleMarkingPos == -1 && !ui.forceSampleDrag && !ui.forceVolDrag && !ui.forceSampleEdit)				mouseButtonDownHandler(event.button.button);		} 		if (ui.throwExit)		{			editor.programRunning = false; 			if (diskop.isFilling)			{				diskop.isFilling = false; 				diskop.forceStopReading = true;				SDL_WaitThread(diskop.fillThread, NULL);			} 			if (editor.mod2WavOngoing)			{				editor.mod2WavOngoing = false; 				editor.abortMod2Wav = true;				SDL_WaitThread(editor.mod2WavThread, NULL);			}		}	}} static bool initializeVars(void){	setDefaultPalette(); 	editor.repeatKeyFlag = (SDL_GetModState() & KMOD_CAPS) ? true : false; 	// 0.52 fixed-point delta for Amiga PAL vblank (~49.92Hz) at VBLANK_HZ (60.0Hz)	const double dRatio = AMIGA_PAL_VBLANK_HZ / (double)VBLANK_HZ;	video.amigaVblankDelta = (uint64_t)((dRatio * (1ULL << 52)) + 0.5); 	strcpy(editor.mixText, "MIX 01+02 TO 03"); 	// allocate some memory

Lines 1–500 of 955.

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