// 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 memoryLines 1–500 of 955. Load more
// 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 _DEBUG bool 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 _WIN32 static LONG WINAPI exceptionHandler(EXCEPTION_POINTERS *ptr); #else static void exceptionHandler(int32_t signal); #endif #endif #ifdef _WIN32 static 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