ft2-clone

Fasttracker 2 clone
Log | Files | Refs | README | LICENSE

commit d501f401aefda30c7c20de806d4b3b48fe4d9218
parent edb61e26be52bda77fee50071b96ab49675acec6
Author: Olav Sørensen <olav.sorensen@live.no>
Date:   Sun,  1 Oct 2023 18:43:53 +0200

Pushed v1.70 code

- Bugfix: Shrink Pattern ("Srnk.") could lead to a pattern length of 0
- Better variable sanitation for some pattern editing routines, may (?) prevent some rare crashes
- CTRL+F5 (Paste Pattern) had wrong button names in its message box when asking to adjust the pattern length after pasting
- Changed the above message box text to be easier to understand
- Removed audio dithering for 16-bit audio bit depth mode. It seemed to be wrongly implemented anyway
- Some small changes done to the about screen
- Code cleanup

Diffstat:
Msrc/ft2_about.c | 56+++++++++++++++++++++++++++++++++++++++++++++++++-------
Msrc/ft2_audio.c | 95++++++++++++++++++++++++++-----------------------------------------------------
Msrc/ft2_audio.h | 1-
Msrc/ft2_audioselector.c | 2+-
Msrc/ft2_config.c | 44++++++++++++++++++--------------------------
Msrc/ft2_diskop.c | 78+++++++++++++++++++++++++++++++++++++++---------------------------------------
Msrc/ft2_edit.c | 889+++++++++++++++++++++++++++++++++++++++++++------------------------------------
Msrc/ft2_edit.h | 1-
Msrc/ft2_events.c | 2+-
Msrc/ft2_gui.c | 68+++++---------------------------------------------------------------
Msrc/ft2_header.h | 2+-
Msrc/ft2_help.c | 4++--
Msrc/ft2_inst_ed.c | 48++++++++++++++++++++++++------------------------
Msrc/ft2_keyboard.c | 14++++++--------
Msrc/ft2_main.c | 6+++---
Msrc/ft2_module_loader.c | 14+++++++-------
Msrc/ft2_module_saver.c | 46+++++++++++++++++++++++-----------------------
Msrc/ft2_nibbles.c | 32++++++++++++++++----------------
Msrc/ft2_palette.c | 4++--
Msrc/ft2_pattern_draw.c | 131+------------------------------------------------------------------------------
Msrc/ft2_pattern_ed.c | 160+++++++++++++++++++++++++++++++++++++++++++++----------------------------------
Msrc/ft2_pattern_ed.h | 10+++++-----
Msrc/ft2_replayer.c | 7+++----
Msrc/ft2_sample_ed.c | 98++++++++++++++++++++++++++++++++++++++++----------------------------------------
Msrc/ft2_sample_ed_features.c | 16++++++++--------
Msrc/ft2_sample_saver.c | 18+++++++++---------
Msrc/ft2_sampling.c | 14+++++++-------
Msrc/ft2_sysreqs.c | 139+++++++++++++++++++++++++++++++++++++------------------------------------------
Msrc/ft2_sysreqs.h | 10+++++++---
Msrc/ft2_textboxes.c | 4++--
Msrc/ft2_trim.c | 6+++---
Msrc/ft2_wav_renderer.c | 23++++++++++++-----------
Msrc/modloaders/ft2_load_s3m.c | 2+-
Msrc/smploaders/ft2_load_aiff.c | 2+-
Msrc/smploaders/ft2_load_flac.c | 4++--
Msrc/smploaders/ft2_load_raw.c | 2+-
Msrc/smploaders/ft2_load_wav.c | 2+-
37 files changed, 983 insertions(+), 1071 deletions(-)

diff --git a/src/ft2_about.c b/src/ft2_about.c @@ -7,8 +7,8 @@ #include "ft2_video.h" #include "ft2_structs.h" -#define NUM_STARS 2048 -#define ALPHA_FADE_MILLISECS 2100 /* amount of milliseconds until content is fully faded in */ +#define NUM_STARS 3000 +#define ALPHA_FADE_MILLISECS 2000 /* amount of milliseconds until content is fully faded in */ #define ABOUT_SCREEN_W 626 #define ABOUT_SCREEN_H 167 #define ABOUT_LOGO_W 449 @@ -30,7 +30,7 @@ static char *customText1 = "Clone by Olav \"8bitbubsy\" S\025rensen"; static char *customText2 = "https://16-bits.org"; static char customText3[256]; static int16_t customText1Y, customText2Y, customText3Y, customText1X, customText2X, customText3X; -static uint32_t alphaValue, randSeed, frameCounter; +static uint32_t logoTimer, alphaValue, randSeed, frameCounter; static vector_t starPoints[NUM_STARS], rotation; static matrix_t matrix; @@ -91,6 +91,24 @@ static void aboutInit(void) rotation.x = rotation.y = rotation.z = 0.0f; alphaValue = 0; frameCounter = 0; + logoTimer = 0; +} + +static void blendPixel(int32_t x, int32_t y, int32_t r, int32_t g, int32_t b, int32_t alpha) +{ + uint32_t *p = &video.frameBuffer[(y * SCREEN_W) + x]; + + const uint32_t srcPixel = *p; + + const int32_t srcR = RGB32_R(srcPixel); + const int32_t srcG = RGB32_G(srcPixel); + const int32_t srcB = RGB32_B(srcPixel); + + r = ((srcR * (65536-alpha)) + (r * alpha)) >> 16; + g = ((srcG * (65536-alpha)) + (g * alpha)) >> 16; + b = ((srcB * (65536-alpha)) + (b * alpha)) >> 16; + + *p = RGB32(r, g, b); } static void starfield(void) @@ -136,7 +154,24 @@ static void starfield(void) if (b > 255) b = 255; - video.frameBuffer[(outY * SCREEN_W) + outX] = RGB32(r, g, b); + // blend sides of star + + const int32_t sidesAlpha = 13000; + + if (outX-1 >= 3) + blendPixel(outX-1, outY, r, g, b, sidesAlpha); + + if (outX+1 < 3+ABOUT_SCREEN_W) + blendPixel(outX+1, outY, r, g, b, sidesAlpha); + + if (outY-1 >= 3) + blendPixel(outX, outY-1, r, g, b, sidesAlpha); + + if (outY+1 < 3+ABOUT_SCREEN_H) + blendPixel(outX, outY+1, r, g, b, sidesAlpha); + + // plot main star pixel + blendPixel(outX, outY, r, g, b, 60000); } } @@ -156,9 +191,16 @@ void aboutFrame(void) // called every frame when the about screen is shown textOutAlpha(customText2X, customText2Y, PAL_FORGRND, customText2, alphaValue); textOutAlpha(customText3X, customText3Y, PAL_FORGRND, customText3, alphaValue); - alphaValue += (uint32_t)((65536.0 / (ALPHA_FADE_MILLISECS / (1000.0 / VBLANK_HZ))) + 0.5); - if (alphaValue > 65536) - alphaValue = 65536; + if (logoTimer > (int32_t)(VBLANK_HZ/4.0)) + { + alphaValue += (uint32_t)((65536.0 / (ALPHA_FADE_MILLISECS / (1000.0 / VBLANK_HZ))) + 0.5); + if (alphaValue > 65536) + alphaValue = 65536; + } + else + { + logoTimer++; + } // the exit button has to be redrawn since it gets overwritten :) showPushButton(PB_EXIT_ABOUT); diff --git a/src/ft2_audio.c b/src/ft2_audio.c @@ -23,12 +23,10 @@ #pragma warning(disable: 4996) #endif -#define INITIAL_DITHER_SEED 0x12345000 - static int32_t smpShiftValue; -static uint32_t oldAudioFreq, tickTimeLenInt, randSeed = INITIAL_DITHER_SEED; +static uint32_t oldAudioFreq, tickTimeLenInt; static uint64_t tickTimeLenFrac; -static double dAudioNormalizeMul, dSqrtPanningTable[256+1], dPrngStateL, dPrngStateR; +static double dAudioNormalizeMul, dSqrtPanningTable[256+1]; static voice_t voice[MAX_CHANNELS * 2]; // globalized @@ -94,7 +92,7 @@ bool setNewAudioSettings(void) // only call this from the main input/video threa // if it didn't work to use the old settings again, then something is seriously wrong... if (!setupAudio(CONFIG_HIDE_ERRORS)) - okBox(0, "System message", "Couldn't find a working audio mode... You'll get no sound / replayer timer!"); + okBox(0, "System message", "Couldn't find a working audio mode... You'll get no sound / replayer timer!", NULL); resumeAudio(); return false; @@ -420,47 +418,18 @@ void updateVoices(void) } } -void resetAudioDither(void) -{ - randSeed = INITIAL_DITHER_SEED; - dPrngStateL = 0.0; - dPrngStateR = 0.0; -} - -static inline int32_t random32(void) -{ - // LCG 32-bit random - randSeed *= 134775813; - randSeed++; - - return (int32_t)randSeed; -} - -static void sendSamples16BitDitherStereo(uint8_t *stream, uint32_t sampleBlockLength) +static void sendSamples16BitStereo(uint8_t *stream, uint32_t sampleBlockLength) { - int32_t out32; - double dOut, dPrng; - int16_t *streamPointer16 = (int16_t *)stream; for (uint32_t i = 0; i < sampleBlockLength; i++) { - // left channel - 1-bit triangular dithering - dPrng = random32() * (0.5 / INT32_MAX); // -0.5 .. 0.5 - dOut = (double)audio.fMixBufferL[i] * dAudioNormalizeMul; - dOut = (dOut + dPrng) - dPrngStateL; - dPrngStateL = dPrng; - out32 = (int32_t)dOut; - CLAMP16(out32); - *streamPointer16++ = (int16_t)out32; - - // right channel - 1-bit triangular dithering - dPrng = random32() * (0.5 / INT32_MAX); // -0.5 .. 0.5 - dOut = (double)audio.fMixBufferR[i] * dAudioNormalizeMul; - dOut = (dOut + dPrng) - dPrngStateR; - dPrngStateR = dPrng; - out32 = (int32_t)dOut; - CLAMP16(out32); - *streamPointer16++ = (int16_t)out32; + int32_t L = (int32_t)((double)audio.fMixBufferL[i] * dAudioNormalizeMul); + CLAMP16(L); + *streamPointer16++ = (int16_t)L; + + int32_t R = (int32_t)((double)audio.fMixBufferR[i] * dAudioNormalizeMul); + CLAMP16(R); + *streamPointer16++ = (int16_t)R; // clear what we read from the mixing buffer audio.fMixBufferL[i] = 0.0f; @@ -468,21 +437,18 @@ static void sendSamples16BitDitherStereo(uint8_t *stream, uint32_t sampleBlockLe } } -static void sendSamples32BitStereo(uint8_t *stream, uint32_t sampleBlockLength) +static void sendSamples32BitFloatStereo(uint8_t *stream, uint32_t sampleBlockLength) { - double dOut; float *fStreamPointer32 = (float *)stream; for (uint32_t i = 0; i < sampleBlockLength; i++) { - // left channel - dOut = (double)audio.fMixBufferL[i] * dAudioNormalizeMul; - dOut = CLAMP(dOut, -1.0, 1.0); - *fStreamPointer32++ = (float)dOut; + double dL = (double)audio.fMixBufferL[i] * dAudioNormalizeMul; + dL = CLAMP(dL, -1.0, 1.0); + *fStreamPointer32++ = (float)dL; - // right channel - dOut = (double)audio.fMixBufferR[i] * dAudioNormalizeMul; - dOut = CLAMP(dOut, -1.0, 1.0); - *fStreamPointer32++ = (float)dOut; + double dR = (double)audio.fMixBufferR[i] * dAudioNormalizeMul; + dR = CLAMP(dR, -1.0, 1.0); + *fStreamPointer32++ = (float)dR; // clear what we read from the mixing buffer audio.fMixBufferL[i] = 0.0f; @@ -535,9 +501,9 @@ void mixReplayerTickToBuffer(uint32_t samplesToMix, uint8_t *stream, uint8_t bit // normalize mix buffer and send to audio stream if (bitDepth == 16) - sendSamples16BitDitherStereo(stream, samplesToMix); + sendSamples16BitStereo(stream, samplesToMix); else - sendSamples32BitStereo(stream, samplesToMix); + sendSamples32BitFloatStereo(stream, samplesToMix); } int32_t pattQueueReadSize(void) @@ -878,13 +844,16 @@ static void SDLCALL audioCallback(void *userdata, Uint8 *stream, int len) if (audio.tickSampleCounter == 0) // new replayer tick { replayerBusy = true; + if (!musicPaused) // important, don't remove this check! (also used for safety) + { + if (audio.volumeRampingFlag) + resetRampVolumes(); - if (audio.volumeRampingFlag) - resetRampVolumes(); - - tickReplayer(); - updateVoices(); - fillVisualsSyncBuffer(); + tickReplayer(); + updateVoices(); + fillVisualsSyncBuffer(); + } + replayerBusy = false; audio.tickSampleCounter = audio.samplesPerTickInt; @@ -894,8 +863,6 @@ static void SDLCALL audioCallback(void *userdata, Uint8 *stream, int len) audio.tickSampleCounterFrac &= BPM_FRAC_MASK; audio.tickSampleCounter++; } - - replayerBusy = false; } uint32_t samplesToMix = samplesLeft; @@ -910,9 +877,9 @@ static void SDLCALL audioCallback(void *userdata, Uint8 *stream, int len) } if (config.specialFlags & BITDEPTH_16) - sendSamples16BitDitherStereo(stream, len); + sendSamples16BitStereo(stream, len); else - sendSamples32BitStereo(stream, len); + sendSamples32BitFloatStereo(stream, len); (void)userdata; } diff --git a/src/ft2_audio.h b/src/ft2_audio.h @@ -149,7 +149,6 @@ void closeAudio(void); void pauseAudio(void); void resumeAudio(void); bool setNewAudioSettings(void); -void resetAudioDither(void); void lockAudio(void); void unlockAudio(void); void lockMixerCallback(void); diff --git a/src/ft2_audioselector.c b/src/ft2_audioselector.c @@ -267,7 +267,7 @@ bool testAudioDeviceListsMouseDown(void) strcpy(audio.currOutputDevice, devString); if (!setNewAudioSettings()) - okBox(0, "System message", "Couldn't open audio input device!"); + okBox(0, "System message", "Couldn't open audio input device!", NULL); else drawAudioOutputList(); } diff --git a/src/ft2_config.c b/src/ft2_config.c @@ -247,7 +247,7 @@ static void updateImageStretchAndPixelFilter(uint8_t oldWindowFlags, uint8_t old void resetConfig(void) { - if (okBox(2, "System request", "Are you sure you want to reset your FT2 configuration?") != 1) + if (okBox(2, "System request", "Are you sure you want to reset your FT2 configuration?", NULL) != 1) return; const uint8_t oldWindowFlags = config.windowFlags; @@ -305,7 +305,7 @@ bool loadConfig(bool showErrorFlag) if (editor.configFileLocationU == NULL) { if (showErrorFlag) - okBox(0, "System message", "Error opening config file for reading!"); + okBox(0, "System message", "Error opening config file for reading!", NULL); return false; } @@ -314,7 +314,7 @@ bool loadConfig(bool showErrorFlag) if (f == NULL) { if (showErrorFlag) - okBox(0, "System message", "Error opening config file for reading!"); + okBox(0, "System message", "Error opening config file for reading!", NULL); return false; } @@ -328,7 +328,7 @@ bool loadConfig(bool showErrorFlag) { fclose(f); if (showErrorFlag) - okBox(0, "System message", "Error loading config: the config file is not valid!"); + okBox(0, "System message", "Error loading config: the config file is not valid!", NULL); return false; } @@ -341,7 +341,7 @@ bool loadConfig(bool showErrorFlag) { fclose(f); if (showErrorFlag) - okBox(0, "System message", "Error opening config file for reading!"); + okBox(0, "System message", "Error opening config file for reading!", NULL); return false; } @@ -353,7 +353,7 @@ bool loadConfig(bool showErrorFlag) if (memcmp(&configBuffer[0], CFG_ID_STR, 35) != 0) { if (showErrorFlag) - okBox(0, "System message", "Error loading config: the config file is not valid!"); + okBox(0, "System message", "Error loading config: the config file is not valid!", NULL); return false; } @@ -387,7 +387,7 @@ 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?"); + okBox(0, "System message", "General I/O error during saving! Is the file in use?", NULL); return false; } @@ -401,7 +401,7 @@ bool saveConfig(bool showErrorFlag) if (f == NULL) { if (showErrorFlag) - okBox(0, "System message", "General I/O error during config saving! Is the file in use?"); + okBox(0, "System message", "General I/O error during config saving! Is the file in use?", NULL); return false; } @@ -427,7 +427,7 @@ bool saveConfig(bool showErrorFlag) fclose(f); if (showErrorFlag) - okBox(0, "System message", "General I/O error during config saving! Is the file in use?"); + okBox(0, "System message", "General I/O error during config saving! Is the file in use?", NULL); return false; } @@ -1789,7 +1789,7 @@ void cbSoftwareMouse(void) { config.specialFlags2 ^= HARDWARE_MOUSE; if (!createMouseCursors()) - okBox(0, "System message", "Error: Couldn't create/show mouse cursor!"); + okBox(0, "System message", "Error: Couldn't create/show mouse cursor!", NULL); if (config.specialFlags2 & HARDWARE_MOUSE) { @@ -1948,7 +1948,7 @@ void rbWinSizeAuto(void) { if (video.fullscreen) { - okBox(0, "System message", "You can't change the window size while in fullscreen mode!"); + okBox(0, "System message", "You can't change the window size while in fullscreen mode!", NULL); return; } @@ -1962,7 +1962,7 @@ void rbWinSize1x(void) { if (video.fullscreen) { - okBox(0, "System message", "You can't change the window size while in fullscreen mode!"); + okBox(0, "System message", "You can't change the window size while in fullscreen mode!", NULL); return; } @@ -1976,7 +1976,7 @@ void rbWinSize2x(void) { if (video.fullscreen) { - okBox(0, "System message", "You can't change the window size while in fullscreen mode!"); + okBox(0, "System message", "You can't change the window size while in fullscreen mode!", NULL); return; } @@ -1990,36 +1990,28 @@ void rbWinSize3x(void) { if (video.fullscreen) { - okBox(0, "System message", "You can't change the window size while in fullscreen mode!"); + okBox(0, "System message", "You can't change the window size while in fullscreen mode!", NULL); return; } -#ifdef __arm__ - okBox(0, "System message", "3x video upscaling is not supported on ARM devices for performance reasons."); -#else config.windowFlags &= ~(WINSIZE_AUTO + WINSIZE_1X + WINSIZE_2X + WINSIZE_4X); config.windowFlags |= WINSIZE_3X; setWindowSizeFromConfig(true); checkRadioButton(RB_CONFIG_WIN_SIZE_3X); -#endif } void rbWinSize4x(void) { if (video.fullscreen) { - okBox(0, "System message", "You can't change the window size while in fullscreen mode!"); + okBox(0, "System message", "You can't change the window size while in fullscreen mode!", NULL); return; } -#ifdef __arm__ - okBox(0, "System message", "4x video upscaling is not supported on ARM devices for performance reasons."); -#else config.windowFlags &= ~(WINSIZE_AUTO + WINSIZE_1X + WINSIZE_2X + WINSIZE_3X); config.windowFlags |= WINSIZE_4X; setWindowSizeFromConfig(true); checkRadioButton(RB_CONFIG_WIN_SIZE_4X); -#endif } void cbSampCutToBuff(void) @@ -2085,7 +2077,7 @@ void cbMIDIEnable(void) checkBoxes[CB_CONF_MIDI_ENABLE].checked = false; drawCheckBox(CB_CONF_MIDI_ENABLE); - okBox(0, "System message", "This program was not compiled with MIDI functionality!"); + okBox(0, "System message", "This program was not compiled with MIDI functionality!", NULL); #endif } @@ -2114,7 +2106,7 @@ void cbVsyncOff(void) config.windowFlags ^= FORCE_VSYNC_OFF; if (!(config.dontShowAgainFlags & DONT_SHOW_NOT_YET_APPLIED_WARNING_FLAG)) - okBox(7, "System message", "This setting is not applied until you close and reopen the program."); + okBox(0, "System message", "This setting is not applied until you close and reopen the program.", configToggleNotYetAppliedWarning); } void cbFullScreen(void) @@ -2122,7 +2114,7 @@ void cbFullScreen(void) config.windowFlags ^= START_IN_FULLSCR; if (!(config.dontShowAgainFlags & DONT_SHOW_NOT_YET_APPLIED_WARNING_FLAG)) - okBox(7, "System message", "This setting is not applied until you close and reopen the program."); + okBox(0, "System message", "This setting is not applied until you close and reopen the program.", configToggleNotYetAppliedWarning); } void cbPixelFilter(void) diff --git a/src/ft2_diskop.c b/src/ft2_diskop.c @@ -467,18 +467,18 @@ static void openDrive(char *str) // Windows only { if (mouse.mode == MOUSE_MODE_DELETE) { - okBox(8, "System complaint", "Very funny."); + okBox(0, "System message", "Drive deletion is not implemented!", NULL); return; } if (str == NULL || *str == '\0') { - okBox(0, "System message", "Couldn't open drive!"); + okBox(0, "System message", "Couldn't open drive!", NULL); return; } if (chdir(str) != 0) - okBox(0, "System message", "Couldn't open drive! Please make sure there's a disk in it."); + okBox(0, "System message", "Couldn't open drive! Please make sure there's a disk in it.", NULL); else editor.diskOpReadDir = true; } @@ -575,12 +575,12 @@ static void openDirectory(UNICHAR *strU) { if (strU == NULL || UNICHAR_STRLEN(strU) == 0) { - okBox(0, "System message", "Couldn't open directory! No permission or in use?"); + okBox(0, "System message", "Couldn't open directory! No permission or in use?", NULL); return; } if (UNICHAR_CHDIR(strU) != 0) - okBox(0, "System message", "Couldn't open directory! No permission or in use?"); + okBox(0, "System message", "Couldn't open directory! No permission or in use?", NULL); else editor.diskOpReadDir = true; } @@ -710,7 +710,7 @@ static void openFile(UNICHAR *filenameU, bool songModifiedCheck) FILE *f = UNICHAR_FOPEN(filenameU, "rb"); if (f == NULL) { - okBox(0, "System message", "Couldn't open file/directory! No permission or in use?"); + okBox(0, "System message", "Couldn't open file/directory! No permission or in use?", NULL); return; } fclose(f); @@ -718,13 +718,13 @@ static void openFile(UNICHAR *filenameU, bool songModifiedCheck) const int32_t filesize = getFileSize(filenameU); if (filesize == -1) // >2GB { - okBox(0, "System message", "The file is too big and can't be loaded (over 2GB)."); + okBox(0, "System message", "The file is too big and can't be loaded (over 2GB).", NULL); return; } if (filesize >= 128L*1024*1024) // 128MB { - if (okBox(2, "System request", "Are you sure you want to load such a big file?") != 1) + if (okBox(2, "System request", "Are you sure you want to load such a big file?", NULL) != 1) return; } @@ -740,7 +740,7 @@ static void openFile(UNICHAR *filenameU, bool songModifiedCheck) FReq_EntrySelected = -1; diskOp_DrawFilelist(); - if (okBox(2, "System request", "You have unsaved changes in your song. Load new song and lose all changes?") != 1) + if (okBox(2, "System request", "You have unsaved changes in your song. Load new song and lose all changes?", NULL) != 1) return; } @@ -871,21 +871,21 @@ static void diskOpSave(bool checkOverwrite) if (FReq_FileName[0] == '\0') { - okBox(0, "System message", "Filename can't be empty!"); + okBox(0, "System message", "Filename can't be empty!", NULL); return; } // test if the very first character has a dot... if (FReq_FileName[0] == '.') { - okBox(0, "System message", "The very first character in the filename can't be '.' (dot)!"); + okBox(0, "System message", "The very first character in the filename can't be '.' (dot)!", NULL); return; } // test for illegal file name if (FReq_FileName[0] == '\0' || strpbrk(FReq_FileName, "\\/:*?\"<>|") != NULL) { - okBox(0, "System message", "The filename can't contain the following characters: \\ / : * ? \" < > |"); + okBox(0, "System message", "The filename can't contain the following characters: \\ / : * ? \" < > |", NULL); return; } @@ -912,14 +912,14 @@ static void diskOpSave(bool checkOverwrite) if (checkOverwrite && fileExistsAnsi(FReq_FileName)) { createFileOverwriteText(FReq_FileName, FReq_SysReqText); - if (okBox(2, "System request", FReq_SysReqText) != 1) + if (okBox(2, "System request", FReq_SysReqText, NULL) != 1) return; } fileNameU = cp437ToUnichar(FReq_FileName); if (fileNameU == NULL) { - okBox(0, "System message", "General I/O error during saving! Is the file in use?"); + okBox(0, "System message", "General I/O error during saving! Is the file in use?", NULL); return; } @@ -936,14 +936,14 @@ static void diskOpSave(bool checkOverwrite) if (checkOverwrite && fileExistsAnsi(FReq_FileName)) { createFileOverwriteText(FReq_FileName, FReq_SysReqText); - if (okBox(2, "System request", FReq_SysReqText) != 1) + if (okBox(2, "System request", FReq_SysReqText, NULL) != 1) return; } fileNameU = cp437ToUnichar(FReq_FileName); if (fileNameU == NULL) { - okBox(0, "System message", "General I/O error during saving! Is the file in use?"); + okBox(0, "System message", "General I/O error during saving! Is the file in use?", NULL); return; } @@ -965,14 +965,14 @@ static void diskOpSave(bool checkOverwrite) if (checkOverwrite && fileExistsAnsi(FReq_FileName)) { createFileOverwriteText(FReq_FileName, FReq_SysReqText); - if (okBox(2, "System request", FReq_SysReqText) != 1) + if (okBox(2, "System request", FReq_SysReqText, NULL) != 1) return; } fileNameU = cp437ToUnichar(FReq_FileName); if (fileNameU == NULL) { - okBox(0, "System message", "General I/O error during saving! Is the file in use?"); + okBox(0, "System message", "General I/O error during saving! Is the file in use?", NULL); return; } @@ -989,14 +989,14 @@ static void diskOpSave(bool checkOverwrite) if (checkOverwrite && fileExistsAnsi(FReq_FileName)) { createFileOverwriteText(FReq_FileName, FReq_SysReqText); - if (okBox(2, "System request", FReq_SysReqText) != 1) + if (okBox(2, "System request", FReq_SysReqText, NULL) != 1) return; } fileNameU = cp437ToUnichar(FReq_FileName); if (fileNameU == NULL) { - okBox(0, "System message", "General I/O error during saving! Is the file in use?"); + okBox(0, "System message", "General I/O error during saving! Is the file in use?", NULL); return; } @@ -1012,14 +1012,14 @@ static void diskOpSave(bool checkOverwrite) if (checkOverwrite && fileExistsAnsi(FReq_FileName)) { createFileOverwriteText(FReq_FileName, FReq_SysReqText); - if (okBox(2, "System request", FReq_SysReqText) != 1) + if (okBox(2, "System request", FReq_SysReqText, NULL) != 1) return; } fileNameU = cp437ToUnichar(FReq_FileName); if (fileNameU == NULL) { - okBox(0, "System message", "General I/O error during saving! Is the file in use?"); + okBox(0, "System message", "General I/O error during saving! Is the file in use?", NULL); return; } @@ -1086,13 +1086,13 @@ static void fileListPressed(int32_t index) free(nameTmp); - if (okBox(2, "System request", FReq_SysReqText) == 1) + if (okBox(2, "System request", FReq_SysReqText, NULL) == 1) { if (dirEntry->isDir) { result = deleteDirRecursive(dirEntry->nameU); if (!result) - okBox(0, "System message", "Couldn't delete folder: Access denied!"); + okBox(0, "System message", "Couldn't delete folder: Access denied!", NULL); else editor.diskOpReadDir = true; } @@ -1100,7 +1100,7 @@ static void fileListPressed(int32_t index) { result = (UNICHAR_REMOVE(dirEntry->nameU) == 0); if (!result) - okBox(0, "System message", "Couldn't delete file: Access denied!"); + okBox(0, "System message", "Couldn't delete file: Access denied!", NULL); else editor.diskOpReadDir = true; } @@ -1129,16 +1129,16 @@ static void fileListPressed(int32_t index) { if (FReq_NameTemp == NULL || FReq_NameTemp[0] == '\0') { - okBox(0, "System message", "New name can't be empty!"); + okBox(0, "System message", "New name can't be empty!", NULL); break; } if (!renameAnsi(dirEntry->nameU, FReq_NameTemp)) { if (dirEntry->isDir) - okBox(0, "System message", "Couldn't rename directory: Access denied, or dir already exists!"); + okBox(0, "System message", "Couldn't rename directory: Access denied, or dir already exists!", NULL); else - okBox(0, "System message", "Couldn't rename file: Access denied, or file already exists!"); + okBox(0, "System message", "Couldn't rename file: Access denied, or file already exists!", NULL); } else { @@ -1657,7 +1657,7 @@ static void sortDirectory(void) { if (p1 != NULL) free(p1); if (p2 != NULL) free(p2); - okBox(0, "System message", "Not enough memory!"); + okBox(0, "System message", "Not enough memory!", NULL); return; } @@ -1753,7 +1753,7 @@ static void displayCurrPath(void) char *asciiPath = unicharToCp437(FReq_CurPathU, true); if (asciiPath == NULL) { - okBox(0, "System message", "Not enough memory!"); + okBox(0, "System message", "Not enough memory!", NULL); return; } @@ -1916,13 +1916,13 @@ static int32_t SDLCALL diskOp_ReadDirectoryThread(void *ptr) { findClose(); - okBoxThreadSafe(0, "System message", "Not enough memory!"); + okBoxThreadSafe(0, "System message", "Not enough memory!", NULL); FReq_Buffer = bufferCreateEmptyDir(); if (FReq_Buffer != NULL) FReq_FileCount = 1; else - okBoxThreadSafe(0, "System message", "Not enough memory!"); + okBoxThreadSafe(0, "System message", "Not enough memory!", NULL); setMouseBusy(false); return false; @@ -1942,7 +1942,7 @@ static int32_t SDLCALL diskOp_ReadDirectoryThread(void *ptr) if (newPtr == NULL) { freeDirRecBuffer(); - okBoxThreadSafe(0, "System message", "Not enough memory!"); + okBoxThreadSafe(0, "System message", "Not enough memory!", NULL); break; } @@ -1966,7 +1966,7 @@ static int32_t SDLCALL diskOp_ReadDirectoryThread(void *ptr) if (FReq_Buffer != NULL) FReq_FileCount = 1; else - okBoxThreadSafe(0, "System message", "Not enough memory!"); + okBoxThreadSafe(0, "System message", "Not enough memory!", NULL); } editor.diskOpReadDone = true; @@ -1986,7 +1986,7 @@ void diskOp_StartDirReadThread(void) if (thread == NULL) { editor.diskOpReadDone = true; - okBox(0, "System message", "Couldn't create thread!"); + okBox(0, "System message", "Couldn't create thread!", NULL); return; } @@ -2408,14 +2408,14 @@ void pbDiskOpMakeDir(void) { if (FReq_NameTemp[0] == '\0') { - okBox(0, "System message", "Name can't be empty!"); + okBox(0, "System message", "Name can't be empty!", NULL); return; } if (makeDirAnsi(FReq_NameTemp)) editor.diskOpReadDir = true; else - okBox(0, "System message", "Couldn't create directory: Access denied, or a dir with the same name already exists!"); + okBox(0, "System message", "Couldn't create directory: Access denied, or a dir with the same name already exists!", NULL); } } @@ -2434,14 +2434,14 @@ void pbDiskOpSetPath(void) { if (FReq_NameTemp[0] == '\0') { - okBox(0, "System message", "Name can't be empty!"); + okBox(0, "System message", "Name can't be empty!", NULL); return; } if (chdir(FReq_NameTemp) == 0) editor.diskOpReadDir = true; else - okBox(0, "System message", "Couldn't set directory path!"); + okBox(0, "System message", "Couldn't set directory path!", NULL); } } diff --git a/src/ft2_edit.c b/src/ft2_edit.c @@ -26,19 +26,13 @@ static double dVolScaleFK1 = 1.0, dVolScaleFK2 = 1.0; // for block cut/copy/paste static bool blockCopied; -static int16_t markXSize, markYSize; static uint16_t ptnBufLen, trkBufLen; - -// for transposing - these are set and tested accordingly -static int8_t lastTranspVal; -static uint8_t lastInsMode, lastTranspMode; -static uint32_t transpDelNotes; // count of under-/overflowing notes for warning message -static note_t clearNote; - +static int32_t markXSize, markYSize; static note_t blkCopyBuff[MAX_PATT_LEN * MAX_CHANNELS]; static note_t ptnCopyBuff[MAX_PATT_LEN * MAX_CHANNELS]; static note_t trackCopyBuff[MAX_PATT_LEN]; +// for recordNote() static const int8_t tickArr[16] = { 16, 8, 0, 4, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1 }; void recordNote(uint8_t note, int8_t vol); @@ -52,14 +46,19 @@ static bool testNoteKeys(SDL_Scancode scancode) // inserts "note off" if editing song if (playMode == PLAYMODE_EDIT || playMode == PLAYMODE_RECPATT || playMode == PLAYMODE_RECSONG) { - if (!allocatePattern(editor.editPattern)) + pauseMusic(); + const volatile uint16_t curPattern = editor.editPattern; + int16_t row = editor.row; + resumeMusic(); + + if (!allocatePattern(curPattern)) return true; // key pressed - pattern[editor.editPattern][(editor.row * MAX_CHANNELS) + cursor.ch].note = NOTE_OFF; + pattern[curPattern][(row * MAX_CHANNELS) + cursor.ch].note = NOTE_OFF; - const uint16_t numRows = patternNumRows[editor.editPattern]; + const uint16_t numRows = patternNumRows[curPattern]; if (playMode == PLAYMODE_EDIT && numRows >= 1) - setPos(-1, (editor.row + editor.editRowSkip) % numRows, true); + setPos(-1, (row + editor.editRowSkip) % numRows, true); ui.updatePatternEditor = true; setSongModifiedFlag(); @@ -155,12 +154,17 @@ static bool testEditKeys(SDL_Scancode scancode, SDL_Keycode keycode) i = -1; // invalid key for slot } - if (i == -1 || !allocatePattern(editor.editPattern)) + pauseMusic(); + const volatile uint16_t curPattern = editor.editPattern; + int16_t row = editor.row; + resumeMusic(); + + if (i == -1 || !allocatePattern(curPattern)) return false; // no edit to be done // insert slot data - note_t *p = &pattern[editor.editPattern][(editor.row * MAX_CHANNELS) + cursor.ch]; + note_t *p = &pattern[curPattern][(row * MAX_CHANNELS) + cursor.ch]; switch (cursor.object) { case CURSOR_INST1: @@ -251,12 +255,12 @@ static bool testEditKeys(SDL_Scancode scancode, SDL_Keycode keycode) // increase row (only in edit mode) - const int16_t numRows = patternNumRows[editor.editPattern]; + const int16_t numRows = patternNumRows[curPattern]; if (playMode == PLAYMODE_EDIT && numRows >= 1) - setPos(-1, (editor.row + editor.editRowSkip) % numRows, true); + setPos(-1, (row + editor.editRowSkip) % numRows, true); - if (i == 0) // if we inserted a zero, check if pattern is empty, for killing - killPatternIfUnused(editor.editPattern); + if (i == 0) // if we inserted a zero, check if pattern is empty + killPatternIfUnused(curPattern); ui.updatePatternEditor = true; return true; @@ -269,7 +273,7 @@ static void evaluateTimeStamp(int16_t *songPos, int16_t *pattNum, int16_t *row, int16_t outRow = editor.row; int16_t outTick = editor.speed - editor.tick; - outTick = CLAMP(outTick, 0, editor.speed - 1); + outTick = CLAMP(outTick, 0, editor.speed-1); // this is needed, but also breaks quantization on speed>15 if (outTick > 15) @@ -359,7 +363,7 @@ void recordNote(uint8_t noteNum, int8_t vol) // directly ported from the origina if ((config.multiEdit && editmode) || (config.multiRec && recmode)) { - time = 0x7FFFFFFF; + time = INT32_MAX; for (i = 0; i < song.numChannels; i++) { if (editor.chnMode[i] && config.multiRecChn[i] && editor.keyOffTime[i] < time && editor.keyOnTab[i] == 0) @@ -385,7 +389,7 @@ void recordNote(uint8_t noteNum, int8_t vol) // directly ported from the origina // find out what channel is the most suitable in idle/play mode (jamming) if (config.multiKeyJazz) { - time = 0x7FFFFFFF; + time = INT32_MAX; c = 0; if (songPlaying) @@ -400,7 +404,7 @@ void recordNote(uint8_t noteNum, int8_t vol) // directly ported from the origina } } - if (time == 0x7FFFFFFF) + if (time == INT32_MAX) { for (i = 0; i < song.numChannels; i++) { @@ -563,10 +567,15 @@ bool handleEditKeys(SDL_Keycode keycode, SDL_Scancode scancode) if (playMode != PLAYMODE_EDIT && playMode != PLAYMODE_RECSONG && playMode != PLAYMODE_RECPATT) return false; // we're not editing, test other keys - if (pattern[editor.editPattern] == NULL) + pauseMusic(); + const volatile uint16_t curPattern = editor.editPattern; + int16_t row = editor.row; + resumeMusic(); + + if (pattern[curPattern] == NULL) return true; - note_t *p = &pattern[editor.editPattern][(editor.row * MAX_CHANNELS) + cursor.ch]; + note_t *p = &pattern[curPattern][(row * MAX_CHANNELS) + cursor.ch]; if (keyb.leftShiftPressed) { @@ -601,12 +610,12 @@ bool handleEditKeys(SDL_Keycode keycode, SDL_Scancode scancode) } } - killPatternIfUnused(editor.editPattern); + killPatternIfUnused(curPattern); // increase row (only in edit mode) - const int16_t numRows = patternNumRows[editor.editPattern]; + const int16_t numRows = patternNumRows[curPattern]; if (playMode == PLAYMODE_EDIT && numRows >= 1) - setPos(-1, (editor.row + editor.editRowSkip) % numRows, true); + setPos(-1, (row + editor.editRowSkip) % numRows, true); ui.updatePatternEditor = true; setSongModifiedFlag(); @@ -626,12 +635,17 @@ bool handleEditKeys(SDL_Keycode keycode, SDL_Scancode scancode) void writeToMacroSlot(uint8_t slot) { + pauseMusic(); + const volatile uint16_t curPattern = editor.editPattern; + int16_t row = editor.row; + resumeMusic(); + uint16_t writeVol = 0; uint16_t writeEfx = 0; - if (pattern[editor.editPattern] != NULL) + if (pattern[curPattern] != NULL) { - note_t *p = &pattern[editor.editPattern][(editor.row * MAX_CHANNELS) + cursor.ch]; + note_t *p = &pattern[curPattern][(row * MAX_CHANNELS) + cursor.ch]; writeVol = p->vol; writeEfx = (p->efx << 8) | p->efxData; } @@ -644,13 +658,18 @@ void writeToMacroSlot(uint8_t slot) void writeFromMacroSlot(uint8_t slot) { + pauseMusic(); + const volatile uint16_t curPattern = editor.editPattern; + int16_t row = editor.row; + resumeMusic(); + if (playMode != PLAYMODE_EDIT && playMode != PLAYMODE_RECSONG && playMode != PLAYMODE_RECPATT) return; - if (!allocatePattern(editor.editPattern)) + if (!allocatePattern(curPattern)) return; - note_t *p = &pattern[editor.editPattern][(editor.row * MAX_CHANNELS) + cursor.ch]; + note_t *p = &pattern[curPattern][(row * MAX_CHANNELS) + cursor.ch]; if (cursor.object == CURSOR_VOL1 || cursor.object == CURSOR_VOL2) { p->vol = (uint8_t)config.volMacro[slot]; @@ -671,11 +690,11 @@ void writeFromMacroSlot(uint8_t slot) } } - const int16_t numRows = patternNumRows[editor.editPattern]; + const int16_t numRows = patternNumRows[curPattern]; if (playMode == PLAYMODE_EDIT && numRows >= 1) - setPos(-1, (editor.row + editor.editRowSkip) % numRows, true); + setPos(-1, (row + editor.editRowSkip) % numRows, true); - killPatternIfUnused(editor.editPattern); + killPatternIfUnused(curPattern); ui.updatePatternEditor = true; setSongModifiedFlag(); @@ -683,15 +702,19 @@ void writeFromMacroSlot(uint8_t slot) void insertPatternNote(void) { + pauseMusic(); + const volatile uint16_t curPattern = editor.editPattern; + int16_t row = editor.row; + resumeMusic(); + if (playMode != PLAYMODE_EDIT && playMode != PLAYMODE_RECPATT && playMode != PLAYMODE_RECSONG) return; - note_t *p = pattern[editor.editPattern]; + note_t *p = pattern[curPattern]; if (p == NULL) return; - const int16_t row = editor.row; - const int16_t numRows = patternNumRows[editor.editPattern]; + const int16_t numRows = patternNumRows[curPattern]; if (numRows > 1) { @@ -701,7 +724,7 @@ void insertPatternNote(void) memset(&p[(row * MAX_CHANNELS) + cursor.ch], 0, sizeof (note_t)); - killPatternIfUnused(editor.editPattern); + killPatternIfUnused(curPattern); ui.updatePatternEditor = true; setSongModifiedFlag(); @@ -709,16 +732,20 @@ void insertPatternNote(void) void insertPatternLine(void) { + pauseMusic(); + const volatile uint16_t curPattern = editor.editPattern; + int16_t row = editor.row; + resumeMusic(); + if (playMode != PLAYMODE_EDIT && playMode != PLAYMODE_RECPATT && playMode != PLAYMODE_RECSONG) return; - setPatternLen(editor.editPattern, patternNumRows[editor.editPattern] + config.recTrueInsert); // config.recTrueInsert is 0 or 1 + setPatternLen(curPattern, patternNumRows[curPattern] + config.recTrueInsert); // config.recTrueInsert is 0 or 1 - note_t *p = pattern[editor.editPattern]; + note_t *p = pattern[curPattern]; if (p != NULL) { - const int16_t row = editor.row; - const int16_t numRows = patternNumRows[editor.editPattern]; + const int16_t numRows = patternNumRows[curPattern]; if (numRows > 1) { @@ -731,7 +758,7 @@ void insertPatternLine(void) memset(&p[row * MAX_CHANNELS], 0, TRACK_WIDTH); - killPatternIfUnused(editor.editPattern); + killPatternIfUnused(curPattern); } ui.updatePatternEditor = true; @@ -740,13 +767,17 @@ void insertPatternLine(void) void deletePatternNote(void) { + pauseMusic(); + const volatile uint16_t curPattern = editor.editPattern; + int16_t row = editor.row; + resumeMusic(); + if (playMode != PLAYMODE_EDIT && playMode != PLAYMODE_RECPATT && playMode != PLAYMODE_RECSONG) return; - int16_t row = editor.row; - const int16_t numRows = patternNumRows[editor.editPattern]; + const int16_t numRows = patternNumRows[curPattern]; - note_t *p = pattern[editor.editPattern]; + note_t *p = pattern[curPattern]; if (p != NULL) { if (row > 0) @@ -769,7 +800,7 @@ void deletePatternNote(void) } } - killPatternIfUnused(editor.editPattern); + killPatternIfUnused(curPattern); ui.updatePatternEditor = true; setSongModifiedFlag(); @@ -777,13 +808,16 @@ void deletePatternNote(void) void deletePatternLine(void) { + pauseMusic(); + const volatile uint16_t curPattern = editor.editPattern; + int16_t row = editor.row; + resumeMusic(); + if (playMode != PLAYMODE_EDIT && playMode != PLAYMODE_RECPATT && playMode != PLAYMODE_RECSONG) return; - int16_t row = editor.row; - const int16_t numRows = patternNumRows[editor.editPattern]; - - note_t *p = pattern[editor.editPattern]; + const int16_t numRows = patternNumRows[curPattern]; + note_t *p = pattern[curPattern]; if (p != NULL) { if (row > 0) @@ -810,9 +844,9 @@ void deletePatternLine(void) } if (config.recTrueInsert && numRows > 1) - setPatternLen(editor.editPattern, numRows-1); + setPatternLen(curPattern, numRows-1); - killPatternIfUnused(editor.editPattern); + killPatternIfUnused(curPattern); ui.updatePatternEditor = true; setSongModifiedFlag(); @@ -820,26 +854,28 @@ void deletePatternLine(void) // ----- TRANSPOSE FUNCTIONS ----- -static void countOverflowingNotes(uint8_t currInsOnly, uint8_t transpMode, int8_t addVal) +static uint32_t countOverflowingNotes(uint8_t mode, int8_t addValue, bool allInstrumentsFlag, + uint16_t curPattern, int32_t numRows, int32_t markX1, int32_t markX2, int32_t markY1, int32_t markY2) { - transpDelNotes = 0; - switch (transpMode) + uint32_t notesToDelete = 0; + + // "addValue" is never <-12 or >12, so unsigned 8-bit testing for >96 is safe + switch (mode) { case TRANSP_TRACK: { - note_t *p = pattern[editor.editPattern]; + note_t *p = pattern[curPattern]; if (p == NULL) - return; // empty pattern + return 0; // empty pattern p += cursor.ch; - const int32_t numRows = patternNumRows[editor.editPattern]; for (int32_t row = 0; row < numRows; row++, p += MAX_CHANNELS) { - if ((p->note >= 1 && p->note <= 96) && (!currInsOnly || p->instr == editor.curInstr)) + if ((p->note >= 1 && p->note <= 96) && (allInstrumentsFlag || p->instr == editor.curInstr)) { - if ((int8_t)p->note+addVal > 96 || (int8_t)p->note+addVal <= 0) - transpDelNotes++; + if ((int8_t)p->note+addValue > 96 || (int8_t)p->note+addValue <= 0) + notesToDelete++; } } } @@ -847,21 +883,19 @@ static void countOverflowingNotes(uint8_t currInsOnly, uint8_t transpMode, int8_ case TRANSP_PATT: { - note_t *p = pattern[editor.editPattern]; + note_t *p = pattern[curPattern]; if (p == NULL) - return; // empty pattern + return 0; // empty pattern - const int32_t numRows = patternNumRows[editor.editPattern]; const int32_t pitch = MAX_CHANNELS-song.numChannels; - for (int32_t row = 0; row < numRows; row++, p += pitch) { for (int32_t ch = 0; ch < song.numChannels; ch++, p++) { - if ((p->note >= 1 && p->note <= 96) && (!currInsOnly || p->instr == editor.curInstr)) + if ((p->note >= 1 && p->note <= 96) && (allInstrumentsFlag || p->instr == editor.curInstr)) { - if ((int8_t)p->note+addVal > 96 || (int8_t)p->note+addVal <= 0) - transpDelNotes++; + if ((int8_t)p->note+addValue > 96 || (int8_t)p->note+addValue <= 0) + notesToDelete++; } } } @@ -870,22 +904,21 @@ static void countOverflowingNotes(uint8_t currInsOnly, uint8_t transpMode, int8_ case TRANSP_SONG: { - const int32_t pitch = MAX_CHANNELS-song.numChannels; + const int32_t pitch = MAX_CHANNELS - song.numChannels; for (int32_t i = 0; i < MAX_PATTERNS; i++) { note_t *p = pattern[i]; if (p == NULL) - continue; // empty pattern + return 0; // empty pattern - const int32_t numRows = patternNumRows[i]; - for (int32_t row = 0; row < numRows; row++, p += pitch) + for (int32_t row = 0; row < patternNumRows[i]; row++, p += pitch) { for (int32_t ch = 0; ch < song.numChannels; ch++, p++) { - if ((p->note >= 1 && p->note <= 96) && (!currInsOnly || p->instr == editor.curInstr)) + if ((p->note >= 1 && p->note <= 96) && (allInstrumentsFlag || p->instr == editor.curInstr)) { - if ((int8_t)p->note+addVal > 96 || (int8_t)p->note+addVal <= 0) - transpDelNotes++; + if ((int8_t)p->note+addValue > 96 || (int8_t)p->note+addValue <= 0) + notesToDelete++; } } } @@ -895,24 +928,36 @@ static void countOverflowingNotes(uint8_t currInsOnly, uint8_t transpMode, int8_ case TRANSP_BLOCK: { - if (pattMark.markY1 == pattMark.markY2) - return; // no pattern marking + if (markY1 == markY2 || markY1 > markY2) + return 0; - note_t *p = pattern[editor.editPattern]; - if (p == NULL) - return; // empty pattern + if (markX1 >= song.numChannels-1) + markX1 = song.numChannels-2; - p += (pattMark.markY1 * MAX_CHANNELS) + pattMark.markX1; + if (markX2 >= song.numChannels) + markX2 = (song.numChannels-1)-markX1; - const int32_t pitch = MAX_CHANNELS - ((pattMark.markX2 + 1) - pattMark.markX1); - for (int32_t row = pattMark.markY1; row < pattMark.markY2; row++, p += pitch) + if (markY1 >= numRows) + markY1 = numRows-1; + + if (markY2 > numRows) + markY2 = numRows-markY1; + + note_t *p = pattern[curPattern]; + if (p == NULL || markX1 < 0 || markY1 < 0 || markX2 < 0 || markY2 < 0) + return 0; + + p += (markY1 * MAX_CHANNELS) + markX1; + + const int32_t pitch = MAX_CHANNELS - ((markX2 + 1) - markX1); + for (int32_t row = markY1; row < markY2; row++, p += pitch) { - for (int32_t ch = pattMark.markX1; ch <= pattMark.markX2; ch++, p++) + for (int32_t ch = markX1; ch <= markX2; ch++, p++) { - if ((p->note >= 1 && p->note <= 96) && (!currInsOnly || p->instr == editor.curInstr)) + if ((p->note >= 1 && p->note <= 96) && (allInstrumentsFlag || p->instr == editor.curInstr)) { - if ((int8_t)p->note+addVal > 96 || (int8_t)p->note+addVal <= 0) - transpDelNotes++; + if ((int8_t)p->note+addValue > 96 || (int8_t)p->note+addValue <= 0) + notesToDelete++; } } } @@ -921,38 +966,48 @@ static void countOverflowingNotes(uint8_t currInsOnly, uint8_t transpMode, int8_ default: break; } + + return notesToDelete; } -void doTranspose(void) +static void doTranspose(uint8_t mode, int8_t addValue, bool allInstrumentsFlag) { - char text[48]; - - countOverflowingNotes(lastInsMode, lastTranspMode, lastTranspVal); - if (transpDelNotes > 0) + pauseMusic(); + const volatile uint16_t curPattern = editor.editPattern; + const int32_t numRows = patternNumRows[curPattern]; + volatile int32_t markX1 = pattMark.markX1; + volatile int32_t markX2 = pattMark.markX2; + volatile int32_t markY1 = pattMark.markY1; + volatile int32_t markY2 = pattMark.markY2; + resumeMusic(); + + uint32_t overflowingNotes = countOverflowingNotes(mode, addValue, allInstrumentsFlag, + curPattern, numRows, markX1, markX2, markY1, markY2); + if (overflowingNotes > 0) { - sprintf(text, "%d note(s) will be erased! Proceed?", (int32_t)transpDelNotes); - if (okBox(2, "System request", text) != 1) + char text[48]; + sprintf(text, "%u note(s) will be erased! Proceed?", overflowingNotes); + if (okBox(2, "System request", text, NULL) != 1) return; } - // lastTranspVal is never <-12 or >12, so unsigned testing for >96 is safe - switch (lastTranspMode) + // "addValue" is never <-12 or >12, so unsigned 8-bit testing for >96 is safe + switch (mode) { case TRANSP_TRACK: { - note_t *p = pattern[editor.editPattern]; + note_t *p = pattern[curPattern]; if (p == NULL) - return; // empty pattern + return; p += cursor.ch; - const int32_t numRows = patternNumRows[editor.editPattern]; for (int32_t row = 0; row < numRows; row++, p += MAX_CHANNELS) { - uint8_t note = p->note; - if ((note >= 1 && note <= 96) && (!lastInsMode || p->instr == editor.curInstr)) + volatile uint8_t note = p->note; + if ((note >= 1 && note <= 96) && (allInstrumentsFlag || p->instr == editor.curInstr)) { - note += lastTranspVal; + note += addValue; if (note > 96) note = 0; // also handles underflow @@ -964,21 +1019,19 @@ void doTranspose(void) case TRANSP_PATT: { - note_t *p = pattern[editor.editPattern]; + note_t *p = pattern[curPattern]; if (p == NULL) - return; // empty pattern + return; - const int32_t numRows = patternNumRows[editor.editPattern]; const int32_t pitch = MAX_CHANNELS - song.numChannels; - for (int32_t row = 0; row < numRows; row++, p += pitch) { for (int32_t ch = 0; ch < song.numChannels; ch++, p++) { - uint8_t note = p->note; - if ((note >= 1 && note <= 96) && (!lastInsMode || p->instr == editor.curInstr)) + volatile uint8_t note = p->note; + if ((note >= 1 && note <= 96) && (allInstrumentsFlag || p->instr == editor.curInstr)) { - note += lastTranspVal; + note += addValue; if (note > 96) note = 0; // also handles underflow @@ -998,15 +1051,14 @@ void doTranspose(void) if (p == NULL) continue; // empty pattern - const int32_t numRows = patternNumRows[i]; - for (int32_t row = 0; row < numRows; row++, p += pitch) + for (int32_t row = 0; row < patternNumRows[i]; row++, p += pitch) { for (int32_t ch = 0; ch < song.numChannels; ch++, p++) { - uint8_t note = p->note; - if ((note >= 1 && note <= 96) && (!lastInsMode || p->instr == editor.curInstr)) + volatile uint8_t note = p->note; + if ((note >= 1 && note <= 96) && (allInstrumentsFlag || p->instr == editor.curInstr)) { - note += lastTranspVal; + note += addValue; if (note > 96) note = 0; // also handles underflow @@ -1020,24 +1072,36 @@ void doTranspose(void) case TRANSP_BLOCK: { - if (pattMark.markY1 == pattMark.markY2) - return; // no pattern marking + if (markY1 == markY2 || markY1 > markY2) + return; - note_t *p = pattern[editor.editPattern]; - if (p == NULL) - return; // empty pattern + if (markX1 >= song.numChannels-1) + markX1 = song.numChannels-2; + + if (markX2 >= song.numChannels) + markX2 = (song.numChannels-1)-markX1; + + if (markY1 >= numRows) + markY1 = numRows-1; + + if (markY2 > numRows) + markY2 = numRows-markY1; + + note_t *p = pattern[curPattern]; + if (p == NULL || markX1 < 0 || markY1 < 0 || markX2 < 0 || markY2 < 0) + return; - p += (pattMark.markY1 * MAX_CHANNELS) + pattMark.markX1; + p += (markY1 * MAX_CHANNELS) + markX1; - const int32_t pitch = MAX_CHANNELS - ((pattMark.markX2 + 1) - pattMark.markX1); - for (int32_t row = pattMark.markY1; row < pattMark.markY2; row++, p += pitch) + const int32_t pitch = MAX_CHANNELS - ((markX2 + 1) - markX1); + for (int32_t row = markY1; row < markY2; row++, p += pitch) { - for (int32_t ch = pattMark.markX1; ch <= pattMark.markX2; ch++, p++) + for (int32_t ch = markX1; ch <= markX2; ch++, p++) { - uint8_t note = p->note; - if ((note >= 1 && note <= 96) && (!lastInsMode || p->instr == editor.curInstr)) + volatile uint8_t note = p->note; + if ((note >= 1 && note <= 96) && (allInstrumentsFlag || p->instr == editor.curInstr)) { - note += lastTranspVal; + note += addValue; if (note > 96) note = 0; // also handles underflow @@ -1057,269 +1121,182 @@ void doTranspose(void) void trackTranspCurInsUp(void) { - lastTranspMode = TRANSP_TRACK; - lastTranspVal = 1; - lastInsMode = TRANSP_CUR_INST; - doTranspose(); + doTranspose(TRANSP_TRACK, 1, TRANSP_CUR_INSTRUMENT); } void trackTranspCurInsDn(void) { - lastTranspMode = TRANSP_TRACK; - lastTranspVal = -1; - lastInsMode = TRANSP_CUR_INST; - doTranspose(); + doTranspose(TRANSP_TRACK, -1, TRANSP_CUR_INSTRUMENT); } void trackTranspCurIns12Up(void) { - lastTranspMode = TRANSP_TRACK; - lastTranspVal = 12; - lastInsMode = TRANSP_CUR_INST; - doTranspose(); + doTranspose(TRANSP_TRACK, 12, TRANSP_CUR_INSTRUMENT); } void trackTranspCurIns12Dn(void) { - lastTranspMode = TRANSP_TRACK; - lastTranspVal = -12; - lastInsMode = TRANSP_CUR_INST; - doTranspose(); + doTranspose(TRANSP_TRACK, -12, TRANSP_CUR_INSTRUMENT); } void trackTranspAllInsUp(void) { - lastTranspMode = TRANSP_TRACK; - lastTranspVal = 1; - lastInsMode = TRANSP_ALL_INST; - doTranspose(); + doTranspose(TRANSP_TRACK, 1, TRANSP_ALL_INSTRUMENTS); } void trackTranspAllInsDn(void) { - lastTranspMode = TRANSP_TRACK; - lastTranspVal = -1; - lastInsMode = TRANSP_ALL_INST; - doTranspose(); + doTranspose(TRANSP_TRACK, -1, TRANSP_ALL_INSTRUMENTS); } void trackTranspAllIns12Up(void) { - lastTranspMode = TRANSP_TRACK; - lastTranspVal = 12; - lastInsMode = TRANSP_ALL_INST; - doTranspose(); + doTranspose(TRANSP_TRACK, 12, TRANSP_ALL_INSTRUMENTS); } void trackTranspAllIns12Dn(void) { - lastTranspMode = TRANSP_TRACK; - lastTranspVal = -12; - lastInsMode = TRANSP_ALL_INST; - doTranspose(); + doTranspose(TRANSP_TRACK, -12, TRANSP_ALL_INSTRUMENTS); } void pattTranspCurInsUp(void) { - lastTranspMode = TRANSP_PATT; - lastTranspVal = 1; - lastInsMode = TRANSP_CUR_INST; - doTranspose(); + doTranspose(TRANSP_PATT, 1, TRANSP_CUR_INSTRUMENT); } void pattTranspCurInsDn(void) { - lastTranspMode = TRANSP_PATT; - lastTranspVal = -1; - lastInsMode = TRANSP_CUR_INST; - doTranspose(); + doTranspose(TRANSP_PATT, -1, TRANSP_CUR_INSTRUMENT); } void pattTranspCurIns12Up(void) { - lastTranspMode = TRANSP_PATT; - lastTranspVal = 12; - lastInsMode = TRANSP_CUR_INST; - doTranspose(); + doTranspose(TRANSP_PATT, 12, TRANSP_CUR_INSTRUMENT); } void pattTranspCurIns12Dn(void) { - lastTranspMode = TRANSP_PATT; - lastTranspVal = -12; - lastInsMode = TRANSP_CUR_INST; - doTranspose(); + doTranspose(TRANSP_PATT, -12, TRANSP_CUR_INSTRUMENT); } void pattTranspAllInsUp(void) { - lastTranspMode = TRANSP_PATT; - lastTranspVal = 1; - lastInsMode = TRANSP_ALL_INST; - doTranspose(); + doTranspose(TRANSP_PATT, 1, TRANSP_ALL_INSTRUMENTS); } void pattTranspAllInsDn(void) { - lastTranspMode = TRANSP_PATT; - lastTranspVal = -1; - lastInsMode = TRANSP_ALL_INST; - doTranspose(); + doTranspose(TRANSP_PATT, -1, TRANSP_ALL_INSTRUMENTS); } void pattTranspAllIns12Up(void) { - lastTranspMode = TRANSP_PATT; - lastTranspVal = 12; - lastInsMode = TRANSP_ALL_INST; - doTranspose(); + doTranspose(TRANSP_PATT, 12, TRANSP_ALL_INSTRUMENTS); } void pattTranspAllIns12Dn(void) { - lastTranspMode = TRANSP_PATT; - lastTranspVal = -12; - lastInsMode = TRANSP_ALL_INST; - doTranspose(); + doTranspose(TRANSP_PATT, -12, TRANSP_ALL_INSTRUMENTS); } void songTranspCurInsUp(void) { - lastTranspMode = TRANSP_SONG; - lastTranspVal = 1; - lastInsMode = TRANSP_CUR_INST; - doTranspose(); + doTranspose(TRANSP_SONG, 1, TRANSP_CUR_INSTRUMENT); } void songTranspCurInsDn(void) { - lastTranspMode = TRANSP_SONG; - lastTranspVal = -1; - lastInsMode = TRANSP_CUR_INST; - doTranspose(); + doTranspose(TRANSP_SONG, -1, TRANSP_CUR_INSTRUMENT); } void songTranspCurIns12Up(void) { - lastTranspMode = TRANSP_SONG; - lastTranspVal = 12; - lastInsMode = TRANSP_CUR_INST; - doTranspose(); + doTranspose(TRANSP_SONG, 12, TRANSP_CUR_INSTRUMENT); } void songTranspCurIns12Dn(void) { - lastTranspMode = TRANSP_SONG; - lastTranspVal = -12; - lastInsMode = TRANSP_CUR_INST; - doTranspose(); + doTranspose(TRANSP_SONG, -12, TRANSP_CUR_INSTRUMENT); } void songTranspAllInsUp(void) { - lastTranspMode = TRANSP_SONG; - lastTranspVal = 1; - lastInsMode = TRANSP_ALL_INST; - doTranspose(); + doTranspose(TRANSP_SONG, 1, TRANSP_ALL_INSTRUMENTS); } void songTranspAllInsDn(void) { - lastTranspMode = TRANSP_SONG; - lastTranspVal = -1; - lastInsMode = TRANSP_ALL_INST; - doTranspose(); + doTranspose(TRANSP_SONG, -1, TRANSP_ALL_INSTRUMENTS); } void songTranspAllIns12Up(void) { - lastTranspMode = TRANSP_SONG; - lastTranspVal = 12; - lastInsMode = TRANSP_ALL_INST; - doTranspose(); + doTranspose(TRANSP_SONG, 12, TRANSP_ALL_INSTRUMENTS); } void songTranspAllIns12Dn(void) { - lastTranspMode = TRANSP_SONG; - lastTranspVal = -12; - lastInsMode = TRANSP_ALL_INST; - doTranspose(); + doTranspose(TRANSP_SONG, -12, TRANSP_ALL_INSTRUMENTS); } void blockTranspCurInsUp(void) { - lastTranspMode = TRANSP_BLOCK; - lastTranspVal = 1; - lastInsMode = TRANSP_CUR_INST; - doTranspose(); + doTranspose(TRANSP_BLOCK, 1, TRANSP_CUR_INSTRUMENT); } void blockTranspCurInsDn(void) { - lastTranspMode = TRANSP_BLOCK; - lastTranspVal = -1; - lastInsMode = TRANSP_CUR_INST; - doTranspose(); + doTranspose(TRANSP_BLOCK, -1, TRANSP_CUR_INSTRUMENT); } void blockTranspCurIns12Up(void) { - lastTranspMode = TRANSP_BLOCK; - lastTranspVal = 12; - lastInsMode = TRANSP_CUR_INST; - doTranspose(); + doTranspose(TRANSP_BLOCK, 12, TRANSP_CUR_INSTRUMENT); } void blockTranspCurIns12Dn(void) { - lastTranspMode = TRANSP_BLOCK; - lastTranspVal = -12; - lastInsMode = TRANSP_CUR_INST; - doTranspose(); + doTranspose(TRANSP_BLOCK, -12, TRANSP_CUR_INSTRUMENT); } void blockTranspAllInsUp(void) { - lastTranspMode = TRANSP_BLOCK; - lastTranspVal = 1; - lastInsMode = TRANSP_ALL_INST; - doTranspose(); + doTranspose(TRANSP_BLOCK, 1, TRANSP_ALL_INSTRUMENTS); } void blockTranspAllInsDn(void) { - lastTranspMode = TRANSP_BLOCK; - lastTranspVal = -1; - lastInsMode = TRANSP_ALL_INST; - doTranspose(); + doTranspose(TRANSP_BLOCK, -1, TRANSP_ALL_INSTRUMENTS); } void blockTranspAllIns12Up(void) { - lastTranspMode = TRANSP_BLOCK; - lastTranspVal = 12; - lastInsMode = TRANSP_ALL_INST; - doTranspose(); + doTranspose(TRANSP_BLOCK, 12, TRANSP_ALL_INSTRUMENTS); } void blockTranspAllIns12Dn(void) { - lastTranspMode = TRANSP_BLOCK; - lastTranspVal = -12; - lastInsMode = TRANSP_ALL_INST; - doTranspose(); + doTranspose(TRANSP_BLOCK, -12, TRANSP_ALL_INSTRUMENTS); } -void copyNote(note_t *src, note_t *dst) +static void copyNote(note_t *src, note_t *dst) { if (editor.copyMaskEnable) { - if (editor.copyMask[0]) dst->note = src->note; - if (editor.copyMask[1]) dst->instr = src->instr; - if (editor.copyMask[2]) dst->vol = src->vol; - if (editor.copyMask[3]) dst->efx = src->efx; - if (editor.copyMask[4]) dst->efxData = src->efxData; + if (editor.copyMask[0]) + dst->note = src->note; + + if (editor.copyMask[1]) + dst->instr = src->instr; + + if (editor.copyMask[2]) + dst->vol = src->vol; + + if (editor.copyMask[3]) + dst->efx = src->efx; + + if (editor.copyMask[4]) + dst->efxData = src->efxData; } else { @@ -1327,15 +1304,24 @@ void copyNote(note_t *src, note_t *dst) } } -void pasteNote(note_t *src, note_t *dst) +static void pasteNote(note_t *src, note_t *dst) { if (editor.copyMaskEnable) { - if (editor.copyMask[0] && (src->note != 0 || !editor.transpMask[0])) dst->note = src->note; - if (editor.copyMask[1] && (src->instr != 0 || !editor.transpMask[1])) dst->instr = src->instr; - if (editor.copyMask[2] && (src->vol != 0 || !editor.transpMask[2])) dst->vol = src->vol; - if (editor.copyMask[3] && (src->efx != 0 || !editor.transpMask[3])) dst->efx = src->efx; - if (editor.copyMask[4] && (src->efxData != 0 || !editor.transpMask[4])) dst->efxData = src->efxData; + if (editor.copyMask[0] && (src->note != 0 || !editor.transpMask[0])) + dst->note = src->note; + + if (editor.copyMask[1] && (src->instr != 0 || !editor.transpMask[1])) + dst->instr = src->instr; + + if (editor.copyMask[2] && (src->vol != 0 || !editor.transpMask[2])) + dst->vol = src->vol; + + if (editor.copyMask[3] && (src->efx != 0 || !editor.transpMask[3])) + dst->efx = src->efx; + + if (editor.copyMask[4] && (src->efxData != 0 || !editor.transpMask[4])) + dst->efxData = src->efxData; } else { @@ -1345,15 +1331,18 @@ void pasteNote(note_t *src, note_t *dst) void cutTrack(void) { - note_t *p = pattern[editor.editPattern]; + const volatile uint16_t curPattern = editor.editPattern; + + note_t *p = pattern[curPattern]; if (p == NULL) return; - const int16_t numRows = patternNumRows[editor.editPattern]; + const int16_t numRows = patternNumRows[curPattern]; if (config.ptnCutToBuffer) { - memset(trackCopyBuff, 0, MAX_PATT_LEN * sizeof (note_t)); + memset(trackCopyBuff, 0, sizeof (trackCopyBuff)); + for (int16_t i = 0; i < numRows; i++) copyNote(&p[(i * MAX_CHANNELS) + cursor.ch], &trackCopyBuff[i]); @@ -1362,10 +1351,10 @@ void cutTrack(void) pauseMusic(); for (int16_t i = 0; i < numRows; i++) - pasteNote(&clearNote, &p[(i * MAX_CHANNELS) + cursor.ch]); + memset(&p[(i * MAX_CHANNELS) + cursor.ch], 0, sizeof (note_t)); resumeMusic(); - killPatternIfUnused(editor.editPattern); + killPatternIfUnused(curPattern); ui.updatePatternEditor = true; setSongModifiedFlag(); @@ -1373,33 +1362,37 @@ void cutTrack(void) void copyTrack(void) { - note_t *p = pattern[editor.editPattern]; - if (p == NULL) - return; + const volatile uint16_t curPattern = editor.editPattern; - const int16_t numRows = patternNumRows[editor.editPattern]; + note_t *p = pattern[curPattern]; + if (p != NULL) + { + memset(trackCopyBuff, 0, sizeof (trackCopyBuff)); - memset(trackCopyBuff, 0, MAX_PATT_LEN * sizeof (note_t)); - for (int16_t i = 0; i < numRows; i++) - copyNote(&p[(i * MAX_CHANNELS) + cursor.ch], &trackCopyBuff[i]); + const int16_t numRows = patternNumRows[curPattern]; + for (int16_t i = 0; i < numRows; i++) + copyNote(&p[(i * MAX_CHANNELS) + cursor.ch], &trackCopyBuff[i]); - trkBufLen = numRows; + trkBufLen = numRows; + } } void pasteTrack(void) { - if (trkBufLen == 0 || !allocatePattern(editor.editPattern)) + const volatile uint16_t curPattern = editor.editPattern; + + if (trkBufLen == 0 || !allocatePattern(curPattern)) return; - note_t *p = pattern[editor.editPattern]; - const int16_t numRows = patternNumRows[editor.editPattern]; + note_t *p = pattern[curPattern]; + const int16_t numRows = patternNumRows[curPattern]; pauseMusic(); for (int16_t i = 0; i < numRows; i++) pasteNote(&trackCopyBuff[i], &p[(i * MAX_CHANNELS) + cursor.ch]); resumeMusic(); - killPatternIfUnused(editor.editPattern); + killPatternIfUnused(curPattern); ui.updatePatternEditor = true; setSongModifiedFlag(); @@ -1407,15 +1400,18 @@ void pasteTrack(void) void cutPattern(void) { - note_t *p = pattern[editor.editPattern]; + const volatile uint16_t curPattern = editor.editPattern; + + note_t *p = pattern[curPattern]; if (p == NULL) return; - const int16_t numRows = patternNumRows[editor.editPattern]; + const int16_t numRows = patternNumRows[curPattern]; if (config.ptnCutToBuffer) { memset(ptnCopyBuff, 0, (MAX_PATT_LEN * MAX_CHANNELS) * sizeof (note_t)); + for (int16_t x = 0; x < song.numChannels; x++) { for (int16_t i = 0; i < numRows; i++) @@ -1429,11 +1425,11 @@ void cutPattern(void) for (int16_t x = 0; x < song.numChannels; x++) { for (int16_t i = 0; i < numRows; i++) - pasteNote(&clearNote, &p[(i * MAX_CHANNELS) + x]); + memset(&p[(i * MAX_CHANNELS) + x], 0, sizeof (note_t)); } resumeMusic(); - killPatternIfUnused(editor.editPattern); + killPatternIfUnused(curPattern); ui.updatePatternEditor = true; setSongModifiedFlag(); @@ -1441,41 +1437,43 @@ void cutPattern(void) void copyPattern(void) { - note_t *p = pattern[editor.editPattern]; - if (p == NULL) - return; - - const int16_t numRows = patternNumRows[editor.editPattern]; + const volatile uint16_t curPattern = editor.editPattern; - memset(ptnCopyBuff, 0, (MAX_PATT_LEN * MAX_CHANNELS) * sizeof (note_t)); - for (int16_t x = 0; x < song.numChannels; x++) + note_t *p = pattern[curPattern]; + if (p != NULL) { - for (int16_t i = 0; i < numRows; i++) - copyNote(&p[(i * MAX_CHANNELS) + x], &ptnCopyBuff[(i * MAX_CHANNELS) + x]); - } + memset(ptnCopyBuff, 0, (MAX_PATT_LEN * MAX_CHANNELS) * sizeof (note_t)); - ptnBufLen = numRows; + const int16_t numRows = patternNumRows[curPattern]; + for (int16_t x = 0; x < song.numChannels; x++) + { + for (int16_t i = 0; i < numRows; i++) + copyNote(&p[(i * MAX_CHANNELS) + x], &ptnCopyBuff[(i * MAX_CHANNELS) + x]); + } - ui.updatePatternEditor = true; + ptnBufLen = numRows; + } } void pastePattern(void) { + const volatile uint16_t curPattern = editor.editPattern; + if (ptnBufLen == 0) return; - if (patternNumRows[editor.editPattern] != ptnBufLen) + if (patternNumRows[curPattern] != ptnBufLen) { - if (okBox(1, "System request", "Change pattern length to copybuffer's length?") == 1) - setPatternLen(editor.editPattern, ptnBufLen); + if (okBox(2, "System request", "Adjust pattern length to match copied pattern length?", NULL) == 1) + setPatternLen(curPattern, ptnBufLen); } - if (!allocatePattern(editor.editPattern)) + if (!allocatePattern(curPattern)) return; - note_t *p = pattern[editor.editPattern]; - const int16_t numRows = patternNumRows[editor.editPattern]; - + note_t *p = pattern[curPattern]; + const int16_t numRows = patternNumRows[curPattern]; + pauseMusic(); for (int16_t x = 0; x < song.numChannels; x++) { @@ -1484,7 +1482,7 @@ void pastePattern(void) } resumeMusic(); - killPatternIfUnused(editor.editPattern); + killPatternIfUnused(curPattern); ui.updatePatternEditor = true; setSongModifiedFlag(); @@ -1492,117 +1490,177 @@ void pastePattern(void) void cutBlock(void) { - if (pattMark.markY1 == pattMark.markY2 || pattMark.markY1 > pattMark.markY2) - return; + pauseMusic(); + const volatile uint16_t curPattern = editor.editPattern; + volatile int32_t markX1 = pattMark.markX1; + volatile int32_t markX2 = pattMark.markX2; + volatile int32_t markY1 = pattMark.markY1; + volatile int32_t markY2 = pattMark.markY2; + resumeMusic(); - note_t *p = pattern[editor.editPattern]; - if (p == NULL) + const int16_t numRows = patternNumRows[curPattern]; + + if (markY1 == markY2 || markY1 > markY2) return; - if (config.ptnCutToBuffer) + if (markX1 >= song.numChannels-1) + markX1 = song.numChannels-2; + + if (markX2 >= song.numChannels) + markX2 = (song.numChannels-1)-markX1; + + if (markY1 >= numRows) + markY1 = numRows-1; + + if (markY2 > numRows) + markY2 = numRows-markY1; + + note_t *p = pattern[curPattern]; + if (p != NULL && markY1 >= 0 && markX1 >= 0 && markX2 >= 0 && markY2 >= 0) { - for (int16_t x = pattMark.markX1; x <= pattMark.markX2; x++) + pauseMusic(); + for (int32_t x = markX1; x < markX2; x++) { - for (int16_t y = pattMark.markY1; y < pattMark.markY2; y++) + for (int32_t y = markY1; y < markY2; y++) { - assert(x < song.numChannels && y < patternNumRows[editor.editPattern]); - copyNote(&p[(y * MAX_CHANNELS) + x], &blkCopyBuff[((y - pattMark.markY1) * MAX_CHANNELS) + (x - pattMark.markX1)]); + note_t *n = &p[(y * MAX_CHANNELS) + x]; + + if (config.ptnCutToBuffer) + copyNote(n, &blkCopyBuff[((y - markY1) * MAX_CHANNELS) + (x - markX1)]); + + memset(n, 0, sizeof (note_t)); } } - } - - pauseMusic(); - for (int16_t x = pattMark.markX1; x <= pattMark.markX2; x++) - { - for (int16_t y = pattMark.markY1; y < pattMark.markY2; y++) - pasteNote(&clearNote, &p[(y * MAX_CHANNELS) + x]); - } - resumeMusic(); + resumeMusic(); - markXSize = pattMark.markX2 - pattMark.markX1; - markYSize = pattMark.markY2 - pattMark.markY1; - blockCopied = true; + killPatternIfUnused(curPattern); - killPatternIfUnused(editor.editPattern); + if (config.ptnCutToBuffer) + { + markXSize = markX2 - markX1; + markYSize = markY2 - markY1; + blockCopied = true; + } - ui.updatePatternEditor = true; - setSongModifiedFlag(); + ui.updatePatternEditor = true; + setSongModifiedFlag(); + } } void copyBlock(void) { - if (pattMark.markY1 == pattMark.markY2 || pattMark.markY1 > pattMark.markY2) - return; + pauseMusic(); + const volatile uint16_t curPattern = editor.editPattern; + volatile int32_t markX1 = pattMark.markX1; + volatile int32_t markX2 = pattMark.markX2; + volatile int32_t markY1 = pattMark.markY1; + volatile int32_t markY2 = pattMark.markY2; + resumeMusic(); - note_t *p = pattern[editor.editPattern]; - if (p == NULL) + const int16_t numRows = patternNumRows[curPattern]; + + if (markY1 == markY2 || markY1 > markY2) return; - for (int16_t x = pattMark.markX1; x <= pattMark.markX2; x++) + if (markX1 >= song.numChannels-1) + markX1 = song.numChannels-2; + + if (markX2 >= song.numChannels) + markX2 = (song.numChannels-1)-markX1; + + if (markY1 >= numRows) + markY1 = numRows-1; + + if (markY2 > numRows) + markY2 = numRows-markY1; + + note_t *p = pattern[curPattern]; + if (p != NULL && markY1 >= 0 && markX1 >= 0 && markX2 >= 0 && markY2 >= 0) { - for (int16_t y = pattMark.markY1; y < pattMark.markY2; y++) + for (int32_t x = markX1; x < markX2; x++) { - assert(x < song.numChannels && y < patternNumRows[editor.editPattern]); - copyNote(&p[(y * MAX_CHANNELS) + x], &blkCopyBuff[((y - pattMark.markY1) * MAX_CHANNELS) + (x - pattMark.markX1)]); + for (int32_t y = markY1; y < markY2; y++) + copyNote(&p[(y * MAX_CHANNELS) + x], &blkCopyBuff[((y - markY1) * MAX_CHANNELS) + (x - markX1)]); } - } - markXSize = pattMark.markX2 - pattMark.markX1; - markYSize = pattMark.markY2 - pattMark.markY1; - blockCopied = true; + markXSize = markX2 - markX1; + markYSize = markY2 - markY1; + blockCopied = true; + } } void pasteBlock(void) { - if (!blockCopied || !allocatePattern(editor.editPattern)) + pauseMusic(); + const volatile uint16_t curPattern = editor.editPattern; + const volatile uint16_t curRow = editor.row; + resumeMusic(); + + if (!blockCopied || !allocatePattern(curPattern)) return; - const int16_t numRows = patternNumRows[editor.editPattern]; + int32_t chStart = cursor.ch; + int32_t rowStart = curRow; + const int16_t numRows = patternNumRows[curPattern]; - const int32_t xpos = cursor.ch; - const int32_t ypos = editor.row; + if (chStart >= song.numChannels) + chStart = song.numChannels-1; - int32_t j = markXSize; - if (j+xpos >= song.numChannels) - j = song.numChannels - xpos - 1; + if (rowStart >= numRows) + rowStart = numRows-1; - int32_t k = markYSize; - if (k+ypos >= numRows) - k = numRows-ypos; + int32_t markedChannels = markXSize + 1; + if (chStart+markedChannels > song.numChannels) + markedChannels = song.numChannels - chStart; - note_t *p = pattern[editor.editPattern]; + int32_t markedRows = markYSize; + if (rowStart+markedRows > numRows) + markedRows = numRows - rowStart; - pauseMusic(); - for (int32_t x = xpos; x <= xpos+j; x++) + if (markedChannels > 0 && markedRows > 0) { - for (int32_t y = ypos; y < ypos+k; y++) + note_t *p = pattern[curPattern]; + + pauseMusic(); + for (int32_t x = chStart; x < chStart+markedChannels; x++) { - assert(x < song.numChannels && y < numRows); - pasteNote(&blkCopyBuff[((y - ypos) * MAX_CHANNELS) + (x - xpos)], &p[(y * MAX_CHANNELS) + x]); + for (int32_t y = rowStart; y < rowStart+markedRows; y++) + pasteNote(&blkCopyBuff[((y - rowStart) * MAX_CHANNELS) + (x - chStart)], &p[(y * MAX_CHANNELS) + x]); } + resumeMusic(); } - resumeMusic(); - killPatternIfUnused(editor.editPattern); + killPatternIfUnused(curPattern); ui.updatePatternEditor = true; setSongModifiedFlag(); } -static void remapInstrXY(uint16_t pattNum, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint8_t src, uint8_t dst) +static void remapInstrXY(int32_t pattNum, int32_t x1, int32_t y1, int32_t x2, int32_t y2, uint8_t src, uint8_t dst) { - // this routine is only used sanely, so no need to check input - note_t *pattPtr = pattern[pattNum]; if (pattPtr == NULL) return; - note_t *p = &pattPtr[(y1 * MAX_CHANNELS) + x1]; + if (x1 >= song.numChannels-1) + x1 = song.numChannels-2; + if (x2 >= song.numChannels) + x2 = (song.numChannels-1)-x1; + + const int16_t numRows = patternNumRows[pattNum]; + if (y1 >= numRows) + y1 = numRows-1; + + if (y2 > numRows) + y2 = numRows-y1; + + note_t *p = &pattPtr[(y1 * MAX_CHANNELS) + x1]; const int32_t pitch = MAX_CHANNELS - ((x2 + 1) - x1); - for (uint16_t y = y1; y <= y2; y++, p += pitch) + + for (int32_t y = y1; y <= y2; y++, p += pitch) { - for (uint16_t x = x1; x <= x2; x++, p++) + for (int32_t x = x1; x <= x2; x++, p++) { if (p->instr == src) p->instr = dst; @@ -1612,13 +1670,20 @@ static void remapInstrXY(uint16_t pattNum, uint16_t x1, uint16_t y1, uint16_t x2 void remapBlock(void) { - if (editor.srcInstr == editor.curInstr || pattMark.markY1 == pattMark.markY2 || pattMark.markY1 > pattMark.markY2) + pauseMusic(); + const volatile uint16_t curPattern = editor.editPattern; + volatile int32_t markX1 = pattMark.markX1; + volatile int32_t markX2 = pattMark.markX2; + volatile int32_t markY1 = pattMark.markY1; + volatile int32_t markY2 = pattMark.markY2; + resumeMusic(); + + if (editor.srcInstr == editor.curInstr || markY1 == markY2 || markY1 > markY2) return; - pauseMusic(); - remapInstrXY(editor.editPattern, - pattMark.markX1, pattMark.markY1, - pattMark.markX2, pattMark.markY2 - 1, + remapInstrXY(curPattern, + markX1, markY1, + markX2, markY2 - 1, editor.srcInstr, editor.curInstr); resumeMusic(); @@ -1628,13 +1693,15 @@ void remapBlock(void) void remapTrack(void) { + const volatile uint16_t curPattern = editor.editPattern; + if (editor.srcInstr == editor.curInstr) return; pauseMusic(); - remapInstrXY(editor.editPattern, + remapInstrXY(curPattern, cursor.ch, 0, - cursor.ch, patternNumRows[editor.editPattern] - 1, + cursor.ch, patternNumRows[curPattern]-1, editor.srcInstr, editor.curInstr); resumeMusic(); @@ -1644,13 +1711,15 @@ void remapTrack(void) void remapPattern(void) { + const volatile uint16_t curPattern = editor.editPattern; + if (editor.srcInstr == editor.curInstr) return; pauseMusic(); - remapInstrXY(editor.editPattern, + remapInstrXY(curPattern, 0, 0, - (uint16_t)(song.numChannels - 1), patternNumRows[editor.editPattern] - 1, + song.numChannels-1, patternNumRows[curPattern]-1, editor.srcInstr, editor.curInstr); resumeMusic(); @@ -1666,11 +1735,10 @@ void remapSong(void) pauseMusic(); for (int32_t i = 0; i < MAX_PATTERNS; i++) { - const uint8_t pattNum = (uint8_t)i; - - remapInstrXY(pattNum, + // remapInstrXY() also checks if pattern is not allocated! + remapInstrXY(i, 0, 0, - (uint16_t)(song.numChannels - 1), patternNumRows[pattNum] - 1, + song.numChannels-1, patternNumRows[i]-1, editor.srcInstr, editor.curInstr); } resumeMusic(); @@ -1713,6 +1781,9 @@ static void setNoteVolume(note_t *p, int8_t newVol) if (newVol < 0) return; + if (newVol > 64) + newVol = 64; + const int8_t oldv = getNoteVolume(p); if (p->vol == oldv) return; // volume is the same @@ -1723,12 +1794,12 @@ static void setNoteVolume(note_t *p, int8_t newVol) p->vol = 0x10 + newVol; // volume column } -static void scaleNote(uint16_t pattNum, int8_t ch, int16_t row, double dScale) +static void scaleNote(int32_t pattNum, int32_t ch, int32_t row, double dScale) { if (pattern[pattNum] == NULL) return; - const int16_t numRows = patternNumRows[pattNum]; + const int32_t numRows = patternNumRows[pattNum]; if (row < 0 || row >= numRows || ch < 0 || ch >= song.numChannels) return; @@ -1748,22 +1819,22 @@ static bool askForScaleFade(char *msg) char volstr[32+1]; sprintf(volstr, "%0.2f,%0.2f", dVolScaleFK1, dVolScaleFK2); - if (inputBox(1, msg, volstr, sizeof (volstr) - 1) != 1) + if (inputBox(1, msg, volstr, sizeof (volstr)-1) != 1) return false; - bool err = false; + bool error = false; char *val1 = volstr; if (strlen(val1) < 3) - err = true; + error = true; char *val2 = strchr(volstr, ','); if (val2 == NULL || strlen(val2) < 3) - err = true; + error = true; - if (err) + if (error) { - okBox(0, "System message", "Invalid constant expressions."); + okBox(0, "System message", "Invalid constant expressions.", NULL); return false; } @@ -1778,10 +1849,12 @@ void scaleFadeVolumeTrack(void) if (!askForScaleFade("Volume scale-fade track (start-, end scale)")) return; - if (pattern[editor.editPattern] == NULL) + const volatile uint16_t curPattern = editor.editPattern; + + if (pattern[curPattern] == NULL) return; - const int32_t numRows = patternNumRows[editor.editPattern]; + const int32_t numRows = patternNumRows[curPattern]; double dVolDelta = 0.0; if (numRows > 0) @@ -1790,9 +1863,9 @@ void scaleFadeVolumeTrack(void) double dVol = dVolScaleFK1; pauseMusic(); - for (int16_t row = 0; row < numRows; row++) + for (int32_t row = 0; row < numRows; row++) { - scaleNote(editor.editPattern, cursor.ch, row, dVol); + scaleNote(curPattern, cursor.ch, row, dVol); dVol += dVolDelta; } resumeMusic(); @@ -1803,10 +1876,12 @@ void scaleFadeVolumePattern(void) if (!askForScaleFade("Volume scale-fade pattern (start-, end scale)")) return; - if (pattern[editor.editPattern] == NULL) + const volatile uint16_t curPattern = editor.editPattern; + + if (pattern[curPattern] == NULL) return; - const int32_t numRows = patternNumRows[editor.editPattern]; + const int32_t numRows = patternNumRows[curPattern]; double dVolDelta = 0.0; if (numRows > 0) @@ -1815,10 +1890,10 @@ void scaleFadeVolumePattern(void) double dVol = dVolScaleFK1; pauseMusic(); - for (int16_t row = 0; row < numRows; row++) + for (int32_t row = 0; row < numRows; row++) { - for (int8_t ch = 0; ch < song.numChannels; ch++) - scaleNote(editor.editPattern, ch, row, dVol); + for (int32_t ch = 0; ch < song.numChannels; ch++) + scaleNote(curPattern, ch, row, dVol); dVol += dVolDelta; } @@ -1830,10 +1905,18 @@ void scaleFadeVolumeBlock(void) if (!askForScaleFade("Volume scale-fade block (start-, end scale)")) return; - if (pattern[editor.editPattern] == NULL || pattMark.markY1 == pattMark.markY2 || pattMark.markY1 > pattMark.markY2) + pauseMusic(); + const volatile uint16_t curPattern = editor.editPattern; + volatile int32_t markX1 = pattMark.markX1; + volatile int32_t markX2 = pattMark.markX2; + volatile int32_t markY1 = pattMark.markY1; + volatile int32_t markY2 = pattMark.markY2; + resumeMusic(); + + if (pattern[curPattern] == NULL || markY1 == markY2 || markY1 > markY2) return; - const int32_t numRows = pattMark.markY2 - pattMark.markY1; + const int32_t numRows = markY2 - markY1; double dVolDelta = 0.0; if (numRows > 0) @@ -1842,10 +1925,10 @@ void scaleFadeVolumeBlock(void) double dVol = dVolScaleFK1; pauseMusic(); - for (int16_t row = pattMark.markY1; row < pattMark.markY2; row++) + for (int32_t row = markY1; row < markY2; row++) { - for (int16_t ch = pattMark.markX1; ch <= pattMark.markX2; ch++) - scaleNote(editor.editPattern, (uint8_t)ch, row, dVol); + for (int32_t ch = markX1; ch <= markX2; ch++) + scaleNote(curPattern, ch, row, dVol); dVol += dVolDelta; } diff --git a/src/ft2_edit.h b/src/ft2_edit.h @@ -63,7 +63,6 @@ void blockTranspAllInsUp(void); void blockTranspAllInsDn(void); void blockTranspAllIns12Up(void); void blockTranspAllIns12Dn(void); -void doTranspose(void); // called from buttons above or specific sys req. void cutTrack(void); void copyTrack(void); void pasteTrack(void); diff --git a/src/ft2_events.c b/src/ft2_events.c @@ -64,7 +64,7 @@ void handleThreadEvents(void) { if (okBoxData.active) { - okBoxData.returnData = okBox(okBoxData.type, okBoxData.headline, okBoxData.text); + okBoxData.returnData = okBox(okBoxData.type, okBoxData.headline, okBoxData.text, okBoxData.checkBoxCallback); okBoxData.active = false; } } diff --git a/src/ft2_gui.c b/src/ft2_gui.c @@ -43,12 +43,11 @@ static void releaseMouseStates(void) void unstuckLastUsedGUIElement(void) { + /* If last object ID is OBJECT_ID_NONE, check if we moved + ** the sample data loop pins, and unstuck them if so. + */ if (mouse.lastUsedObjectID == OBJECT_ID_NONE) { - /* If last object ID is OBJECT_ID_NONE, check if we moved the - ** sample data loop pins, and unstuck them if so - */ - if (ui.leftLoopPinMoving) { setLeftLoopPinState(false); @@ -321,15 +320,8 @@ void textOutTiny(int32_t xPos, int32_t yPos, char *str, uint32_t color) // A..Z/ { for (int32_t x = 0; x < FONT3_CHAR_W; x++) { -#ifdef __arm__ if (srcPtr[x] != 0) dstPtr[x] = color; -#else - // carefully written like this to generate conditional move instructions (font data is hard to predict) - uint32_t tmp = dstPtr[x]; - if (srcPtr[x] != 0) tmp = color; - dstPtr[x] = tmp; -#endif } srcPtr += FONT3_WIDTH; @@ -369,15 +361,8 @@ void charOut(uint16_t xPos, uint16_t yPos, uint8_t paletteIndex, char chr) { for (uint32_t x = 0; x < FONT1_CHAR_W; x++) { -#ifdef __arm__ if (srcPtr[x] != 0) dstPtr[x] = pixVal; -#else - // carefully written like this to generate conditional move instructions (font data is hard to predict) - uint32_t tmp = dstPtr[x]; - if (srcPtr[x] != 0) tmp = pixVal; - dstPtr[x] = tmp; -#endif } srcPtr += FONT1_WIDTH; @@ -448,7 +433,7 @@ void charOutBg(uint16_t xPos, uint16_t yPos, uint8_t fgPalette, uint8_t bgPalett for (int32_t y = 0; y < FONT1_CHAR_H; y++) { for (int32_t x = 0; x < FONT1_CHAR_W-1; x++) - dstPtr[x] = srcPtr[x] ? fg : bg; // compiles nicely into conditional move instructions + dstPtr[x] = srcPtr[x] ? fg : bg; srcPtr += FONT1_WIDTH; dstPtr += SCREEN_W; @@ -483,22 +468,11 @@ void charOutShadow(uint16_t xPos, uint16_t yPos, uint8_t paletteIndex, uint8_t s { for (int32_t x = 0; x < FONT1_CHAR_W; x++) { -#ifdef __arm__ if (srcPtr[x] != 0) { dstPtr2[x] = pixVal2; dstPtr1[x] = pixVal1; } -#else - // carefully written like this to generate conditional move instructions (font data is hard to predict) - uint32_t tmp = dstPtr2[x]; - if (srcPtr[x] != 0) tmp = pixVal2; - dstPtr2[x] = tmp; - - tmp = dstPtr1[x]; - if (srcPtr[x] != 0) tmp = pixVal1; - dstPtr1[x] = tmp; -#endif } srcPtr += FONT1_WIDTH; @@ -530,15 +504,8 @@ void charOutClipX(uint16_t xPos, uint16_t yPos, uint8_t paletteIndex, char chr, { for (int32_t x = 0; x < width; x++) { -#ifdef __arm__ if (srcPtr[x] != 0) dstPtr[x] = pixVal; -#else - // carefully written like this to generate conditional move instructions (font data is hard to predict) - uint32_t tmp = dstPtr[x]; - if (srcPtr[x] != 0) tmp = pixVal; - dstPtr[x] = tmp; -#endif } srcPtr += FONT1_WIDTH; @@ -562,15 +529,8 @@ void bigCharOut(uint16_t xPos, uint16_t yPos, uint8_t paletteIndex, char chr) { for (int32_t x = 0; x < FONT2_CHAR_W; x++) { -#ifdef __arm__ if (srcPtr[x] != 0) dstPtr[x] = pixVal; -#else - // carefully written like this to generate conditional move instructions (font data is hard to predict) - uint32_t tmp = dstPtr[x]; - if (srcPtr[x] != 0) tmp = pixVal; - dstPtr[x] = tmp; -#endif } srcPtr += FONT2_WIDTH; @@ -596,22 +556,11 @@ static void bigCharOutShadow(uint16_t xPos, uint16_t yPos, uint8_t paletteIndex, { for (int32_t x = 0; x < FONT2_CHAR_W; x++) { -#ifdef __arm__ if (srcPtr[x] != 0) { dstPtr2[x] = pixVal2; dstPtr1[x] = pixVal1; } -#else - // carefully written like this to generate conditional move instructions (font data is hard to predict) - uint32_t tmp = dstPtr2[x]; - if (srcPtr[x] != 0) tmp = pixVal2; - dstPtr2[x] = tmp; - - tmp = dstPtr1[x]; - if (srcPtr[x] != 0) tmp = pixVal1; - dstPtr1[x] = tmp; -#endif } srcPtr += FONT2_WIDTH; @@ -771,15 +720,8 @@ void hexOut(uint16_t xPos, uint16_t yPos, uint8_t paletteIndex, uint32_t val, ui { for (int32_t x = 0; x < FONT6_CHAR_W; x++) { -#ifdef __arm__ if (srcPtr[x] != 0) dstPtr[x] = pixVal; -#else - // carefully written like this to generate conditional move instructions (font data is hard to predict) - uint32_t tmp = dstPtr[x]; - if (srcPtr[x] != 0) tmp = pixVal; - dstPtr[x] = tmp; -#endif } srcPtr += FONT6_WIDTH; @@ -807,7 +749,7 @@ void hexOutBg(uint16_t xPos, uint16_t yPos, uint8_t fgPalette, uint8_t bgPalette for (int32_t y = 0; y < FONT6_CHAR_H; y++) { for (int32_t x = 0; x < FONT6_CHAR_W; x++) - dstPtr[x] = srcPtr[x] ? fg : bg; // compiles nicely into conditional move instructions + dstPtr[x] = srcPtr[x] ? fg : bg; srcPtr += FONT6_WIDTH; dstPtr += SCREEN_W; diff --git a/src/ft2_header.h b/src/ft2_header.h @@ -12,7 +12,7 @@ #endif #include "ft2_replayer.h" -#define PROG_VER_STR "1.69" +#define PROG_VER_STR "1.70" // do NOT change these! It will only mess things up... diff --git a/src/ft2_help.c b/src/ft2_help.c @@ -109,7 +109,7 @@ static void readHelp(void) // this is a bit messy... helpRec *tempText = (helpRec *)malloc(HELP_SIZE * MAX_HELP_LINES); if (tempText == NULL) { - okBox(0, "System message", "Not enough memory!"); + okBox(0, "System message", "Not enough memory!", NULL); return; } @@ -251,7 +251,7 @@ static void readHelp(void) // this is a bit messy... subjPtrArr[subj] = (helpRec *)malloc(HELP_SIZE * textLine); if (subjPtrArr[subj] == NULL) { - okBox(0, "System message", "Not enough memory!"); + okBox(0, "System message", "Not enough memory!", NULL); break; } diff --git a/src/ft2_inst_ed.c b/src/ft2_inst_ed.c @@ -212,7 +212,7 @@ static int32_t SDLCALL copyInstrThread(void *ptr) resumeAudio(); if (error) - okBoxThreadSafe(0, "System message", "Not enough memory!"); + okBoxThreadSafe(0, "System message", "Not enough memory!", NULL); // do not change instrument names! @@ -237,7 +237,7 @@ void copyInstr(void) // dstInstr = srcInstr thread = SDL_CreateThread(copyInstrThread, NULL, NULL); if (thread == NULL) { - okBox(0, "System message", "Couldn't create thread!"); + okBox(0, "System message", "Couldn't create thread!", NULL); return; } @@ -2915,21 +2915,21 @@ static int32_t SDLCALL saveInstrThread(void *ptr) if (editor.tmpFilenameU == NULL) { - okBoxThreadSafe(0, "System message", "General I/O error during saving! Is the file in use?"); + okBoxThreadSafe(0, "System message", "General I/O error during saving! Is the file in use?", NULL); return false; } const int32_t numSamples = getUsedSamples(saveInstrNum); if (numSamples == 0 || instr[saveInstrNum] == NULL) { - okBoxThreadSafe(0, "System message", "Instrument is empty!"); + okBoxThreadSafe(0, "System message", "Instrument is empty!", NULL); return false; } FILE *f = UNICHAR_FOPEN(editor.tmpFilenameU, "wb"); if (f == NULL) { - okBoxThreadSafe(0, "System message", "General I/O error during saving! Is the file in use?"); + okBoxThreadSafe(0, "System message", "General I/O error during saving! Is the file in use?", NULL); return false; } @@ -3026,7 +3026,7 @@ static int32_t SDLCALL saveInstrThread(void *ptr) if (result != 1) { fclose(f); - okBoxThreadSafe(0, "System message", "Error saving instrument: general I/O error!"); + okBoxThreadSafe(0, "System message", "Error saving instrument: general I/O error!", NULL); return false; } @@ -3048,7 +3048,7 @@ static int32_t SDLCALL saveInstrThread(void *ptr) { resumeAudio(); fclose(f); - okBoxThreadSafe(0, "System message", "Error saving instrument: general I/O error!"); + okBoxThreadSafe(0, "System message", "Error saving instrument: general I/O error!", NULL); return false; } } @@ -3077,7 +3077,7 @@ void saveInstr(UNICHAR *filenameU, int16_t insNum) thread = SDL_CreateThread(saveInstrThread, NULL, NULL); if (thread == NULL) { - okBox(0, "System message", "Couldn't create thread!"); + okBox(0, "System message", "Couldn't create thread!", NULL); return; } @@ -3108,14 +3108,14 @@ static int32_t SDLCALL loadInstrThread(void *ptr) if (editor.tmpInstrFilenameU == NULL) { - okBoxThreadSafe(0, "System message", "General I/O error during loading! Is the file in use?"); + okBoxThreadSafe(0, "System message", "General I/O error during loading! Is the file in use?", NULL); return false; } FILE *f = UNICHAR_FOPEN(editor.tmpInstrFilenameU, "rb"); if (f == NULL) { - okBoxThreadSafe(0, "System message", "General I/O error during loading! Is the file in use?"); + okBoxThreadSafe(0, "System message", "General I/O error during loading! Is the file in use?", NULL); return false; } @@ -3130,7 +3130,7 @@ static int32_t SDLCALL loadInstrThread(void *ptr) if (xi_h.version != 0x0101 && xi_h.version != 0x0102) { - okBoxThreadSafe(0, "System message", "Incompatible format version!"); + okBoxThreadSafe(0, "System message", "Incompatible format version!", NULL); goto loadDone; } @@ -3158,7 +3158,7 @@ static int32_t SDLCALL loadInstrThread(void *ptr) if (!allocateInstr(editor.curInstr)) { resumeAudio(); - okBoxThreadSafe(0, "System message", "Not enough memory!"); + okBoxThreadSafe(0, "System message", "Not enough memory!", NULL); goto loadDone; } @@ -3198,7 +3198,7 @@ static int32_t SDLCALL loadInstrThread(void *ptr) { freeInstr(editor.curInstr); resumeAudio(); - okBoxThreadSafe(0, "System message", "General I/O error during loading! Is the file in use?"); + okBoxThreadSafe(0, "System message", "General I/O error during loading! Is the file in use?", NULL); goto loadDone; } @@ -3261,7 +3261,7 @@ static int32_t SDLCALL loadInstrThread(void *ptr) { freeInstr(editor.curInstr); resumeAudio(); - okBoxThreadSafe(0, "System message", "Not enough memory!"); + okBoxThreadSafe(0, "System message", "Not enough memory!", NULL); goto loadDone; } @@ -3270,7 +3270,7 @@ static int32_t SDLCALL loadInstrThread(void *ptr) { freeInstr(editor.curInstr); resumeAudio(); - okBoxThreadSafe(0, "System message", "General I/O error during loading! Is the file in use?"); + okBoxThreadSafe(0, "System message", "General I/O error during loading! Is the file in use?", NULL); goto loadDone; } @@ -3310,7 +3310,7 @@ static int32_t SDLCALL loadInstrThread(void *ptr) if (pat_h.layers > 1 || pat_h.numSamples > MAX_SMP_PER_INST) { - okBoxThreadSafe(0, "System message", "Incompatible instrument!"); + okBoxThreadSafe(0, "System message", "Incompatible instrument!", NULL); goto loadDone; } @@ -3321,7 +3321,7 @@ static int32_t SDLCALL loadInstrThread(void *ptr) if (!allocateInstr(editor.curInstr)) { - okBoxThreadSafe(0, "System message", "Not enough memory!"); + okBoxThreadSafe(0, "System message", "Not enough memory!", NULL); goto loadDone; } @@ -3337,7 +3337,7 @@ static int32_t SDLCALL loadInstrThread(void *ptr) { freeInstr(editor.curInstr); resumeAudio(); - okBoxThreadSafe(0, "System message", "General I/O error during loading! Is the file in use?"); + okBoxThreadSafe(0, "System message", "General I/O error during loading! Is the file in use?", NULL); goto loadDone; } @@ -3359,7 +3359,7 @@ static int32_t SDLCALL loadInstrThread(void *ptr) { freeInstr(editor.curInstr); resumeAudio(); - okBoxThreadSafe(0, "System message", "Not enough memory!"); + okBoxThreadSafe(0, "System message", "Not enough memory!", NULL); goto loadDone; } @@ -3414,7 +3414,7 @@ static int32_t SDLCALL loadInstrThread(void *ptr) { freeInstr(editor.curInstr); resumeAudio(); - okBoxThreadSafe(0, "System message", "General I/O error during loading! Is the file in use?"); + okBoxThreadSafe(0, "System message", "General I/O error during loading! Is the file in use?", NULL); goto loadDone; } @@ -3457,10 +3457,10 @@ loadDone: editor.updateCurInstr = true; // setMouseBusy(false) is called in the input/video thread when done if (numLoadedSamples > MAX_SMP_PER_INST) - okBoxThreadSafe(0, "System message", "Warning: The instrument contained >16 samples. The extra samples were discarded!"); + okBoxThreadSafe(0, "System message", "Warning: The instrument contained >16 samples. The extra samples were discarded!", NULL); if (stereoWarning) - okBoxThreadSafe(0, "System message", "Warning: The instrument contained stereo sample(s). They were mixed to mono!"); + okBoxThreadSafe(0, "System message", "Warning: The instrument contained stereo sample(s). They were mixed to mono!", NULL); return true; (void)ptr; @@ -3486,7 +3486,7 @@ void loadInstr(UNICHAR *filenameU) { if (editor.curInstr == 0) { - okBox(0, "System message", "The zero-instrument cannot hold intrument data."); + okBox(0, "System message", "The zero-instrument cannot hold intrument data.", NULL); return; } @@ -3499,7 +3499,7 @@ void loadInstr(UNICHAR *filenameU) thread = SDL_CreateThread(loadInstrThread, NULL, NULL); if (thread == NULL) { - okBox(0, "System message", "Couldn't create thread!"); + okBox(0, "System message", "Couldn't create thread!", NULL); return; } diff --git a/src/ft2_keyboard.c b/src/ft2_keyboard.c @@ -296,7 +296,7 @@ static void handleKeys(SDL_Keycode keycode, SDL_Scancode scanKey) if (editor.curInstr == 0 || instr[editor.curInstr] == NULL) return; - if (okBox(1, "System request", "Clear instrument?") == 1) + if (okBox(1, "System request", "Clear instrument?", NULL) == 1) { freeInstr(editor.curInstr); memset(song.instrName[editor.curInstr], 0, sizeof(song.instrName[editor.curInstr])); @@ -615,9 +615,8 @@ static void handleKeys(SDL_Keycode keycode, SDL_Scancode scanKey) if (audioWasntLocked) lockAudio(); - if (song.row >= 16) - song.row -= 16; - else + song.row -= 16; + if (song.row < 0) song.row = 0; if (!songPlaying) @@ -637,9 +636,8 @@ static void handleKeys(SDL_Keycode keycode, SDL_Scancode scanKey) if (audioWasntLocked) lockAudio(); - if (song.row < song.currNumRows-16) - song.row += 16; - else + song.row += 16; + if (song.row >= song.currNumRows) song.row = song.currNumRows-1; if (!songPlaying) @@ -677,7 +675,7 @@ static void handleKeys(SDL_Keycode keycode, SDL_Scancode scanKey) if (audioWasntLocked) lockAudio(); - song.row = patternNumRows[song.pattNum] - 1; + song.row = song.currNumRows - 1; if (!songPlaying) { editor.row = (uint8_t)song.row; diff --git a/src/ft2_main.c b/src/ft2_main.c @@ -273,7 +273,7 @@ static void initializeVars(void) memset(&keyb, 0, sizeof (keyb)); memset(&mouse, 0, sizeof (mouse)); memset(&editor, 0, sizeof (editor)); - memset(&pattMark, 0, sizeof (pattMark)); + memset((void *)&pattMark, 0, sizeof (pattMark)); memset(&pattSync, 0, sizeof (pattSync)); memset(&chSync, 0, sizeof (chSync)); memset(&song, 0, sizeof (song)); @@ -319,11 +319,11 @@ static void initializeVars(void) #endif editor.diskOpReadOnOpen = true; - editor.programRunning = true; audio.linearPeriodsFlag = true; - calcReplayerLogTab(); + + editor.programRunning = true; } static void cleanUpAndExit(void) // never call this inside the main loop! diff --git a/src/ft2_module_loader.c b/src/ft2_module_loader.c @@ -246,7 +246,7 @@ void loadMusic(UNICHAR *filenameU) if (thread == NULL) { editor.loadMusicEvent = EVENT_NONE; - okBox(0, "System message", "Couldn't create thread!"); + okBox(0, "System message", "Couldn't create thread!", NULL); musicIsLoading = false; return; } @@ -537,7 +537,7 @@ bool handleModuleLoadFromArg(int argc, char **argv) UNICHAR *tmpPathU = (UNICHAR *)malloc((PATH_MAX + 1) * sizeof (UNICHAR)); if (tmpPathU == NULL) { - okBox(0, "System message", "Not enough memory!"); + okBox(0, "System message", "Not enough memory!", NULL); return false; } @@ -545,7 +545,7 @@ bool handleModuleLoadFromArg(int argc, char **argv) if (filenameU == NULL) { free(tmpPathU); - okBox(0, "System message", "Not enough memory!"); + okBox(0, "System message", "Not enough memory!", NULL); return false; } @@ -571,7 +571,7 @@ bool handleModuleLoadFromArg(int argc, char **argv) UNICHAR_CHDIR(tmpPathU); // set old path back free(tmpPathU); - okBox(0, "System message", "Error: The module is too big to be loaded!"); + okBox(0, "System message", "Error: The module is too big to be loaded!", NULL); return false; } @@ -654,7 +654,7 @@ void loadDroppedFile(char *fullPathUTF8, bool songModifiedCheck) UNICHAR *fullPathU = (UNICHAR *)malloc((fullPathLen + 1) * sizeof (UNICHAR)); if (fullPathU == NULL) { - okBox(0, "System message", "Not enough memory!"); + okBox(0, "System message", "Not enough memory!", NULL); return; } @@ -670,14 +670,14 @@ void loadDroppedFile(char *fullPathUTF8, bool songModifiedCheck) if (filesize == -1) // >2GB { - okBox(0, "System message", "The file is too big and can't be loaded (over 2GB)."); + okBox(0, "System message", "The file is too big and can't be loaded (over 2GB).", NULL); free(fullPathU); return; } if (filesize >= 128L*1024*1024) // 128MB { - if (okBox(2, "System request", "Are you sure you want to load such a big file?") != 1) + if (okBox(2, "System request", "Are you sure you want to load such a big file?", NULL) != 1) { free(fullPathU); return; diff --git a/src/ft2_module_saver.c b/src/ft2_module_saver.c @@ -42,7 +42,7 @@ bool saveXM(UNICHAR *filenameU) FILE *f = UNICHAR_FOPEN(filenameU, "wb"); if (f == NULL) { - okBoxThreadSafe(0, "System message", "Error opening file for saving, is it in use?"); + okBoxThreadSafe(0, "System message", "Error opening file for saving, is it in use?", NULL); return false; } @@ -100,7 +100,7 @@ bool saveXM(UNICHAR *filenameU) if (fwrite(&h, sizeof (h), 1, f) != 1) { fclose(f); - okBoxThreadSafe(0, "System message", "Error saving module: general I/O error!"); + okBoxThreadSafe(0, "System message", "Error saving module: general I/O error!", NULL); return false; } @@ -127,7 +127,7 @@ bool saveXM(UNICHAR *filenameU) if (fwrite(&ph, ph.headerSize, 1, f) != 1) { fclose(f); - okBoxThreadSafe(0, "System message", "Error saving module: general I/O error!"); + okBoxThreadSafe(0, "System message", "Error saving module: general I/O error!", NULL); return false; } } @@ -141,7 +141,7 @@ bool saveXM(UNICHAR *filenameU) if (result != 2) // write was not OK { fclose(f); - okBoxThreadSafe(0, "System message", "Error saving module: general I/O error!"); + okBoxThreadSafe(0, "System message", "Error saving module: general I/O error!", NULL); return false; } } @@ -245,7 +245,7 @@ bool saveXM(UNICHAR *filenameU) if (fwrite(&ih, ih.instrSize + (a * sizeof (xmSmpHdr_t)), 1, f) != 1) { fclose(f); - okBoxThreadSafe(0, "System message", "Error saving module: general I/O error!"); + okBoxThreadSafe(0, "System message", "Error saving module: general I/O error!", NULL); return false; } @@ -265,7 +265,7 @@ bool saveXM(UNICHAR *filenameU) if (result != (size_t)SAMPLE_LENGTH_BYTES(s)) // write not OK { fclose(f); - okBoxThreadSafe(0, "System message", "Error saving module: general I/O error!"); + okBoxThreadSafe(0, "System message", "Error saving module: general I/O error!", NULL); return false; } } @@ -300,7 +300,7 @@ static bool saveMOD(UNICHAR *filenameU) if (songLength > 128) { songLength = 128; - okBoxThreadSafe(0, "System message", "Warning: Song length is above 128!"); + okBoxThreadSafe(0, "System message", "Warning: Song length is above 128!", NULL); } // calculate number of patterns referenced (max 128 orders) @@ -315,7 +315,7 @@ static bool saveMOD(UNICHAR *filenameU) if (numPatterns > 100) { numPatterns = 100; - okBoxThreadSafe(0, "System message", "Warning: Song has more than 100 patterns!"); + okBoxThreadSafe(0, "System message", "Warning: Song has more than 100 patterns!", NULL); } // check if song has more than 31 instruments @@ -323,7 +323,7 @@ static bool saveMOD(UNICHAR *filenameU) { if (getRealUsedSamples(i) > 0) { - okBoxThreadSafe(0, "System message", "Warning: Song has more than 31 instruments!"); + okBoxThreadSafe(0, "System message", "Warning: Song has more than 31 instruments!", NULL); break; } } @@ -344,8 +344,8 @@ static bool saveMOD(UNICHAR *filenameU) else if (smp->length > 65534) test2 = true; } - if (test) okBoxThreadSafe(0, "System message", "Warning: Song has sample lengths that are too long for the MOD format!"); - else if (test2) okBoxThreadSafe(0, "System message", "Warning: Song has sample lengths above 65534! Not all MOD players support this."); + if (test) okBoxThreadSafe(0, "System message", "Warning: Song has sample lengths that are too long for the MOD format!", NULL); + else if (test2) okBoxThreadSafe(0, "System message", "Warning: Song has sample lengths above 65534! Not all MOD players support this.", NULL); // check if XM instrument features are being used test = false; @@ -374,7 +374,7 @@ static bool saveMOD(UNICHAR *filenameU) } } } - if (test) okBoxThreadSafe(0, "System message", "Warning: Song is using XM instrument features!"); + if (test) okBoxThreadSafe(0, "System message", "Warning: Song is using XM instrument features!", NULL); bool tooLongPatterns = false; bool tooManyInstr = false; @@ -388,7 +388,7 @@ static bool saveMOD(UNICHAR *filenameU) if (patternNumRows[i] < 64) { - okBoxThreadSafe(0, "System message", "Error: Pattern lengths can't be below 64! Module wasn't saved."); + okBoxThreadSafe(0, "System message", "Error: Pattern lengths can't be below 64! Module wasn't saved.", NULL); return false; } @@ -414,10 +414,10 @@ static bool saveMOD(UNICHAR *filenameU) } } - if (tooLongPatterns) okBoxThreadSafe(0, "System message", "Warning: Song has pattern lengths above 64!"); - if (tooManyInstr) okBoxThreadSafe(0, "System message", "Warning: Patterns have instrument numbers above 31!"); - if (incompatEfx) okBoxThreadSafe(0, "System message", "Warning: Patterns have incompatible effects!"); - if (noteUnderflow) okBoxThreadSafe(0, "System message", "Warning: Patterns have notes below A-0!"); + if (tooLongPatterns) okBoxThreadSafe(0, "System message", "Warning: Song has pattern lengths above 64!", NULL); + if (tooManyInstr) okBoxThreadSafe(0, "System message", "Warning: Patterns have instrument numbers above 31!", NULL); + if (incompatEfx) okBoxThreadSafe(0, "System message", "Warning: Patterns have incompatible effects!", NULL); + if (noteUnderflow) okBoxThreadSafe(0, "System message", "Warning: Patterns have notes below A-0!", NULL); // save module now @@ -499,14 +499,14 @@ static bool saveMOD(UNICHAR *filenameU) FILE *f = UNICHAR_FOPEN(filenameU, "wb"); if (f == NULL) { - okBoxThreadSafe(0, "System message", "Error opening file for saving, is it in use?"); + okBoxThreadSafe(0, "System message", "Error opening file for saving, is it in use?", NULL); return false; } // write header if (fwrite(&hdr, 1, sizeof (hdr), f) != sizeof (hdr)) { - okBoxThreadSafe(0, "System message", "Error saving module: general I/O error!"); + okBoxThreadSafe(0, "System message", "Error saving module: general I/O error!", NULL); goto modSaveError; } @@ -572,7 +572,7 @@ static bool saveMOD(UNICHAR *filenameU) if (fwrite(modPattData, 1, patternBytes, f) != (size_t)patternBytes) { - okBoxThreadSafe(0, "System message", "Error saving module: general I/O error!"); + okBoxThreadSafe(0, "System message", "Error saving module: general I/O error!", NULL); goto modSaveError; } } @@ -612,7 +612,7 @@ static bool saveMOD(UNICHAR *filenameU) if (fwrite(dstPtr, 1, samplesToWrite, f) != (size_t)samplesToWrite) { fixSample(smp); - okBoxThreadSafe(0, "System message", "Error saving module: general I/O error!"); + okBoxThreadSafe(0, "System message", "Error saving module: general I/O error!", NULL); goto modSaveError; } @@ -624,7 +624,7 @@ static bool saveMOD(UNICHAR *filenameU) if (fwrite(smp->dataPtr, 1, sampleBytes, f) != (size_t)sampleBytes) { fixSample(smp); - okBoxThreadSafe(0, "System message", "Error saving module: general I/O error!"); + okBoxThreadSafe(0, "System message", "Error saving module: general I/O error!", NULL); goto modSaveError; } } @@ -672,7 +672,7 @@ void saveMusic(UNICHAR *filenameU) thread = SDL_CreateThread(saveMusicThread, NULL, NULL); if (thread == NULL) { - okBoxThreadSafe(0, "System message", "Couldn't create thread!"); + okBoxThreadSafe(0, "System message", "Couldn't create thread!", NULL); return; } diff --git a/src/ft2_nibbles.c b/src/ft2_nibbles.c @@ -299,7 +299,7 @@ void nibblesHighScore(void) { if (editor.NI_Play) { - okBox(0, "Nibbles message", "The highscore table is not available during play."); + okBox(0, "Nibbles message", "The highscore table is not available during play.", NULL); return; } @@ -430,20 +430,20 @@ static void nibblesDecLives(int16_t l1, int16_t l2) if (l1+l2 == 2) { - okBox(0, "Nibbles message", "Both players died!"); + okBox(0, "Nibbles message", "Both players died!", NULL); } else { if (l2 == 0) - okBox(0, "Nibbles message", "Player 1 died!"); + okBox(0, "Nibbles message", "Player 1 died!", NULL); else - okBox(0, "Nibbles message", "Player 2 died!"); + okBox(0, "Nibbles message", "Player 2 died!", NULL); } if (NI_P1Lives == 0 || NI_P2Lives == 0) { editor.NI_Play = false; - okBox(0, "Nibbles message", "GAME OVER"); + okBox(0, "Nibbles message", "GAME OVER", NULL); // prevent highscore table from showing overflowing level graphics if (NI_Level >= NI_MAXLEVEL) @@ -462,7 +462,7 @@ static void nibblesDecLives(int16_t l1, int16_t l2) memcpy(&config.NI_HighScore[k+1], &config.NI_HighScore[k], sizeof (highScoreType)); if (i == 0) - okBox(0, "Nibbles message", "You've probably cheated!"); + okBox(0, "Nibbles message", "You've probably cheated!", NULL); h = &config.NI_HighScore[i]; @@ -488,7 +488,7 @@ static void nibblesDecLives(int16_t l1, int16_t l2) memcpy(&config.NI_HighScore[k+1], &config.NI_HighScore[k], sizeof (highScoreType)); if (i == 0) - okBox(0, "Nibbles message", "You've probably cheated!"); + okBox(0, "Nibbles message", "You've probably cheated!", NULL); h = &config.NI_HighScore[i]; k = (int16_t)strlen(name); @@ -521,7 +521,7 @@ static void nibblesNewLevel(void) char text[24]; sprintf(text, "Level %d finished!", NI_Level+1); - okBox(0, "Nibbles message", text); + okBox(0, "Nibbles message", text, NULL); // cast to int16_t to simulate a bug in FT2 NI_P1Score += 0x10000 + (int16_t)((12 - NI_CurSpeed) * 0x2000); @@ -814,18 +814,18 @@ void nibblesPlay(void) { if (editor.NI_Play) { - if (okBox(2, "Nibbles request", "Restart current game of Nibbles?") != 1) + if (okBox(2, "Nibbles request", "Restart current game of Nibbles?", NULL) != 1) return; } if (config.NI_Surround && config.NI_NumPlayers == 0) { - okBox(0, "Nibbles message", "Surround mode is not appropriate in one-player mode."); + okBox(0, "Nibbles message", "Surround mode is not appropriate in one-player mode.", NULL); return; } if (wallColorsAreCloseToBlack()) - okBox(0, "Nibbles warning", "The Desktop/Button colors are set to values that make the walls hard to see!"); + okBox(0, "Nibbles warning", "The Desktop/Button colors are set to values that make the walls hard to see!", NULL); assert(config.NI_Speed < 4); NI_CurSpeed = NI_Speeds[config.NI_Speed]; @@ -848,7 +848,7 @@ void nibblesHelp(void) { if (editor.NI_Play) { - okBox(0, "System message", "Help is not available during play."); + okBox(0, "System message", "Help is not available during play.", NULL); return; } @@ -863,7 +863,7 @@ void nibblesExit(void) { if (editor.NI_Play) { - if (okBox(2, "System request", "Quit current game of Nibbles?") == 1) + if (okBox(2, "System request", "Quit current game of Nibbles?", NULL) == 1) { editor.NI_Play = false; exitNibblesScreen(); @@ -946,7 +946,7 @@ void nibblesKeyAdministrator(SDL_Scancode scancode) { if (scancode == SDL_SCANCODE_ESCAPE) { - if (okBox(2, "System request", "Quit current game of Nibbles?") == 1) + if (okBox(2, "System request", "Quit current game of Nibbles?", NULL) == 1) { editor.NI_Play = false; exitNibblesScreen(); @@ -1013,9 +1013,9 @@ bool testNibblesCheatCodes(SDL_Keycode keycode) // not directly ported, but same { NI_EternalLives ^= 1; if (NI_EternalLives) - okBox(0, "Triton productions declares:", "Eternal lives activated!"); + okBox(0, "Triton productions declares:", "Eternal lives activated!", NULL); else - okBox(0, "Triton productions declares:", "Eternal lives deactivated!"); + okBox(0, "Triton productions declares:", "Eternal lives deactivated!", NULL); } } diff --git a/src/ft2_palette.c b/src/ft2_palette.c @@ -69,12 +69,12 @@ void setPal16(pal16 *p, bool redrawScreen) static void showColorErrorMsg(void) { - okBox(0, "System message", "Default colors cannot be modified."); + okBox(0, "System message", "Default colors cannot be modified.", NULL); } static void showMouseColorErrorMsg(void) { - okBox(0, "System message", "Mouse color can only be changed when \"Software mouse\" is enabled."); + okBox(0, "System message", "Mouse color can only be changed when \"Software mouse\" is enabled.", NULL); } static double palPow(double dX, double dY) diff --git a/src/ft2_pattern_draw.c b/src/ft2_pattern_draw.c @@ -745,7 +745,7 @@ void writePattern(int32_t currRow, int32_t currPattern) drawChannelNumbering(pattCoord->upperRowsTextY); } -// ========== OPTIMIZED CHARACTER DRAWING ROUTINES FOR PATTERN EDITOR ========== +// ========== CHARACTER DRAWING ROUTINES FOR PATTERN EDITOR ========== void pattTwoHexOut(uint32_t xPos, uint32_t yPos, uint8_t val, uint32_t color) { @@ -757,19 +757,8 @@ void pattTwoHexOut(uint32_t xPos, uint32_t yPos, uint8_t val, uint32_t color) { for (int32_t x = 0; x < FONT4_CHAR_W; x++) { -#ifdef __arm__ if (ch1Ptr[x] != 0) dstPtr[x] = color; if (ch2Ptr[x] != 0) dstPtr[FONT4_CHAR_W+x] = color; -#else - // carefully written like this to generate conditional move instructions (font data is hard to predict) - uint32_t tmp = dstPtr[x]; - if (ch1Ptr[x] != 0) tmp = color; - dstPtr[x] = tmp; - - tmp = dstPtr[FONT4_CHAR_W+x]; - if (ch2Ptr[x] != 0) tmp = color; - dstPtr[FONT4_CHAR_W+x] = tmp; -#endif } ch1Ptr += FONT4_WIDTH; @@ -782,9 +771,6 @@ static void pattCharOut(uint32_t xPos, uint32_t yPos, uint8_t chr, uint8_t fontT { const uint8_t *srcPtr; int32_t x, y; -#ifndef __arm__ - uint32_t tmp; -#endif uint32_t *dstPtr = &video.frameBuffer[(yPos * SCREEN_W) + xPos]; @@ -795,15 +781,8 @@ static void pattCharOut(uint32_t xPos, uint32_t yPos, uint8_t chr, uint8_t fontT { for (x = 0; x < FONT3_CHAR_W; x++) { -#ifdef __arm__ if (srcPtr[x] != 0) dstPtr[x] = color; -#else - // carefully written like this to generate conditional move instructions (font data is hard to predict) - tmp = dstPtr[x]; - if (srcPtr[x] != 0) tmp = color; - dstPtr[x] = tmp; -#endif } srcPtr += FONT3_WIDTH; @@ -817,15 +796,8 @@ static void pattCharOut(uint32_t xPos, uint32_t yPos, uint8_t chr, uint8_t fontT { for (x = 0; x < FONT4_CHAR_W; x++) { -#ifdef __arm__ if (srcPtr[x] != 0) dstPtr[x] = color; -#else - // carefully written like this to generate conditional move instructions (font data is hard to predict) - tmp = dstPtr[x]; - if (srcPtr[x] != 0) tmp = color; - dstPtr[x] = tmp; -#endif } srcPtr += FONT4_WIDTH; @@ -839,15 +811,8 @@ static void pattCharOut(uint32_t xPos, uint32_t yPos, uint8_t chr, uint8_t fontT { for (x = 0; x < FONT5_CHAR_W; x++) { -#ifdef __arm__ if (srcPtr[x] != 0) dstPtr[x] = color; -#else - // carefully written like this to generate conditional move instructions (font data is hard to predict) - tmp = dstPtr[x]; - if (srcPtr[x] != 0) tmp = color; - dstPtr[x] = tmp; -#endif } srcPtr += FONT5_WIDTH; @@ -861,15 +826,8 @@ static void pattCharOut(uint32_t xPos, uint32_t yPos, uint8_t chr, uint8_t fontT { for (x = 0; x < FONT7_CHAR_W; x++) { -#ifdef __arm__ if (srcPtr[x] != 0) dstPtr[x] = color; -#else - // carefully written like this to generate conditional move instructions (font data is hard to predict) - tmp = dstPtr[x]; - if (srcPtr[x] != 0) tmp = color; - dstPtr[x] = tmp; -#endif } srcPtr += FONT7_WIDTH; @@ -887,15 +845,8 @@ static void drawEmptyNoteSmall(uint32_t xPos, uint32_t yPos, uint32_t color) { for (int32_t x = 0; x < FONT7_CHAR_W*3; x++) { -#ifdef __arm__ if (srcPtr[x] != 0) dstPtr[x] = color; -#else - // carefully written like this to generate conditional move instructions (font data is hard to predict) - uint32_t tmp = dstPtr[x]; - if (srcPtr[x] != 0) tmp = color; - dstPtr[x] = tmp; -#endif } srcPtr += FONT7_WIDTH; @@ -912,15 +863,8 @@ static void drawKeyOffSmall(uint32_t xPos, uint32_t yPos, uint32_t color) { for (int32_t x = 0; x < FONT7_CHAR_W*2; x++) { -#ifdef __arm__ if (srcPtr[x] != 0) dstPtr[x] = color; -#else - // carefully written like this to generate conditional move instructions (font data is hard to predict) - uint32_t tmp = dstPtr[x]; - if (srcPtr[x] != 0) tmp = color; - dstPtr[x] = tmp; -#endif } srcPtr += FONT7_WIDTH; @@ -957,24 +901,9 @@ static void drawNoteSmall(uint32_t xPos, uint32_t yPos, int32_t noteNum, uint32_ { for (int32_t x = 0; x < FONT7_CHAR_W; x++) { -#ifdef __arm__ if (ch1Ptr[x] != 0) dstPtr[x] = color; if (ch2Ptr[x] != 0) dstPtr[FONT7_CHAR_W+x] = color; if (ch3Ptr[x] != 0) dstPtr[((FONT7_CHAR_W*2)-2)+x] = color; -#else - // carefully written like this to generate conditional move instructions (font data is hard to predict) - uint32_t tmp = dstPtr[x]; - if (ch1Ptr[x] != 0) tmp = color; - dstPtr[x] = tmp; - - tmp = dstPtr[FONT7_CHAR_W+x]; - if (ch2Ptr[x] != 0) tmp = color; - dstPtr[FONT7_CHAR_W+x] = tmp; - - tmp = dstPtr[((FONT7_CHAR_W*2)-2)+x]; // -2 to get correct alignment for ending glyph - if (ch3Ptr[x] != 0) tmp = color; - dstPtr[((FONT7_CHAR_W*2)-2)+x] = tmp; -#endif } ch1Ptr += FONT7_WIDTH; @@ -993,15 +922,8 @@ static void drawEmptyNoteMedium(uint32_t xPos, uint32_t yPos, uint32_t color) { for (int32_t x = 0; x < FONT4_CHAR_W*3; x++) { -#ifdef __arm__ if (srcPtr[x] != 0) dstPtr[x] = color; -#else - // carefully written like this to generate conditional move instructions (font data is hard to predict) - uint32_t tmp = dstPtr[x]; - if (srcPtr[x] != 0) tmp = color; - dstPtr[x] = tmp; -#endif } srcPtr += FONT4_WIDTH; @@ -1018,15 +940,8 @@ static void drawKeyOffMedium(uint32_t xPos, uint32_t yPos, uint32_t color) { for (int32_t x = 0; x < FONT4_CHAR_W*3; x++) { -#ifdef __arm__ if (srcPtr[x] != 0) dstPtr[x] = color; -#else - // carefully written like this to generate conditional move instructions (font data is hard to predict) - uint32_t tmp = dstPtr[x]; - if (srcPtr[x] != 0) tmp = color; - dstPtr[x] = tmp; -#endif } srcPtr += FONT4_WIDTH; @@ -1063,24 +978,9 @@ static void drawNoteMedium(uint32_t xPos, uint32_t yPos, int32_t noteNum, uint32 { for (int32_t x = 0; x < FONT4_CHAR_W; x++) { -#ifdef __arm__ if (ch1Ptr[x] != 0) dstPtr[x] = color; if (ch2Ptr[x] != 0) dstPtr[FONT4_CHAR_W+x] = color; if (ch3Ptr[x] != 0) dstPtr[(FONT4_CHAR_W*2)+x] = color; -#else - // carefully written like this to generate conditional move instructions (font data is hard to predict) - uint32_t tmp = dstPtr[x]; - if (ch1Ptr[x] != 0) tmp = color; - dstPtr[x] = tmp; - - tmp = dstPtr[FONT4_CHAR_W+x]; - if (ch2Ptr[x] != 0) tmp = color; - dstPtr[FONT4_CHAR_W+x] = tmp; - - tmp = dstPtr[(FONT4_CHAR_W*2)+x]; - if (ch3Ptr[x] != 0) tmp = color; - dstPtr[(FONT4_CHAR_W*2)+x] = tmp; -#endif } ch1Ptr += FONT4_WIDTH; @@ -1099,15 +999,8 @@ static void drawEmptyNoteBig(uint32_t xPos, uint32_t yPos, uint32_t color) { for (int32_t x = 0; x < FONT4_CHAR_W*6; x++) { -#ifdef __arm__ if (srcPtr[x] != 0) dstPtr[x] = color; -#else - // carefully written like this to generate conditional move instructions (font data is hard to predict) - uint32_t tmp = dstPtr[x]; - if (srcPtr[x] != 0) tmp = color; - dstPtr[x] = tmp; -#endif } srcPtr += FONT4_WIDTH; @@ -1124,15 +1017,8 @@ static void drawKeyOffBig(uint32_t xPos, uint32_t yPos, uint32_t color) { for (int32_t x = 0; x < FONT4_CHAR_W*6; x++) { -#ifdef __arm__ if (srcPtr[x] != 0) dstPtr[x] = color; -#else - // carefully written like this to generate conditional move instructions (font data is hard to predict) - uint32_t tmp = dstPtr[x]; - if (srcPtr[x] != 0) tmp = color; - dstPtr[x] = tmp; -#endif } srcPtr += FONT4_WIDTH; @@ -1169,24 +1055,9 @@ static void drawNoteBig(uint32_t xPos, uint32_t yPos, int32_t noteNum, uint32_t { for (int32_t x = 0; x < FONT5_CHAR_W; x++) { -#ifdef __arm__ if (ch1Ptr[x] != 0) dstPtr[x] = color; if (ch2Ptr[x] != 0) dstPtr[FONT5_CHAR_W+x] = color; if (ch3Ptr[x] != 0) dstPtr[(FONT5_CHAR_W*2)+x] = color; -#else - // carefully written like this to generate conditional move instructions (font data is hard to predict) - uint32_t tmp = dstPtr[x]; - if (ch1Ptr[x] != 0) tmp = color; - dstPtr[x] = tmp; - - tmp = dstPtr[FONT5_CHAR_W+x]; - if (ch2Ptr[x] != 0) tmp = color; - dstPtr[FONT5_CHAR_W+x] = tmp; - - tmp = dstPtr[(FONT5_CHAR_W*2)+x]; - if (ch3Ptr[x] != 0) tmp = color; - dstPtr[(FONT5_CHAR_W*2)+x] = tmp; -#endif } ch1Ptr += FONT5_WIDTH; diff --git a/src/ft2_pattern_ed.c b/src/ft2_pattern_ed.c @@ -43,7 +43,7 @@ static int32_t last_TimeH, last_TimeM, last_TimeS; static note_t tmpPattern[MAX_CHANNELS * MAX_PATT_LEN]; -pattMark_t pattMark; // globalized +volatile pattMark_t pattMark; // globalized bool allocatePattern(uint16_t pattNum) // for tracker use only, not in loader! { @@ -721,7 +721,7 @@ void togglePatternEditorExtended(void) void clearPattMark(void) { - memset(&pattMark, 0, sizeof (pattMark)); + memset((void *)&pattMark, 0, sizeof (pattMark)); lastMarkX1 = -1; lastMarkX2 = -1; @@ -731,17 +731,27 @@ void clearPattMark(void) void checkMarkLimits(void) { - const uint16_t limitY = patternNumRows[editor.editPattern]; - pattMark.markY1 = CLAMP(pattMark.markY1, 0, limitY); - pattMark.markY2 = CLAMP(pattMark.markY2, 0, limitY); + volatile int16_t markX1 = pattMark.markX1; + volatile int16_t markX2 = pattMark.markX2; + volatile int16_t markY1 = pattMark.markY1; + volatile int16_t markY2 = pattMark.markY2; - const uint16_t limitX = (uint16_t)(song.numChannels - 1); - pattMark.markX1 = CLAMP(pattMark.markX1, 0, limitX); - pattMark.markX2 = CLAMP(pattMark.markX2, 0, limitX); + const int16_t limitY = patternNumRows[editor.editPattern]; + markY1 = CLAMP(markY1, 0, limitY); + markY2 = CLAMP(markY2, 0, limitY); + + const int16_t limitX = (int16_t)(song.numChannels - 1); + markX1 = CLAMP(markX1, 0, limitX); + markX2 = CLAMP(markX2, 0, limitX); // XXX: will probably never happen? FT2 has this in CheckMarkLimits() though... - if (pattMark.markX1 > pattMark.markX2) - pattMark.markX1 = pattMark.markX2; + if (markX1 > markX2) + markX1 = markX2; + + pattMark.markX1 = markX1; + pattMark.markX2 = markX2; + pattMark.markY1 = markY1; + pattMark.markY2 = markY2; } static int8_t mouseXToCh(void) // used to get channel num from mouse x (for pattern marking) @@ -951,11 +961,15 @@ void rowOneUpWrap(void) if (audioWasntLocked) lockAudio(); - song.row = (song.row - 1 + song.currNumRows) % song.currNumRows; - if (!songPlaying) + if (song.currNumRows > 0) { - editor.row = (uint8_t)song.row; - ui.updatePatternEditor = true; + song.row = (song.row - 1 + song.currNumRows) % song.currNumRows; + + if (!songPlaying) + { + editor.row = (uint8_t)song.row; + ui.updatePatternEditor = true; + } } if (audioWasntLocked) @@ -972,7 +986,7 @@ void rowOneDownWrap(void) { song.tick = 2; } - else + else if (song.currNumRows > 0) { song.row = (song.row + 1 + song.currNumRows) % song.currNumRows; editor.row = (uint8_t)song.row; @@ -1160,19 +1174,19 @@ bool loadTrack(UNICHAR *filenameU) FILE *f = UNICHAR_FOPEN(filenameU, "rb"); if (f == NULL) { - okBox(0, "System message", "General I/O error during loading! Is the file in use?"); + okBox(0, "System message", "General I/O error during loading! Is the file in use?", NULL); return false; } if (fread(&h, 1, sizeof (h), f) != sizeof (h)) { - okBox(0, "System message", "General I/O error during loading! Is the file in use?"); + okBox(0, "System message", "General I/O error during loading! Is the file in use?", NULL); goto trackLoadError; } if (h.version != 1) { - okBox(0, "System message", "Incompatible format version!"); + okBox(0, "System message", "Incompatible format version!", NULL); goto trackLoadError; } @@ -1185,13 +1199,13 @@ bool loadTrack(UNICHAR *filenameU) if (fread(loadBuff, numRows * sizeof (note_t), 1, f) != 1) { - okBox(0, "System message", "General I/O error during loading! Is the file in use?"); + okBox(0, "System message", "General I/O error during loading! Is the file in use?", NULL); goto trackLoadError; } if (!allocatePattern(editor.editPattern)) { - okBox(0, "System message", "Not enough memory!"); + okBox(0, "System message", "Not enough memory!", NULL); goto trackLoadError; } @@ -1241,14 +1255,14 @@ bool saveTrack(UNICHAR *filenameU) note_t *p = pattern[editor.editPattern]; if (p == NULL) { - okBox(0, "System message", "The current pattern is empty!"); + okBox(0, "System message", "The current pattern is empty!", NULL); return false; } FILE *f = UNICHAR_FOPEN(filenameU, "wb"); if (f == NULL) { - okBox(0, "System message", "General I/O error during saving! Is the file in use?"); + okBox(0, "System message", "General I/O error during saving! Is the file in use?", NULL); return false; } @@ -1261,14 +1275,14 @@ bool saveTrack(UNICHAR *filenameU) if (fwrite(&h, sizeof (h), 1, f) != 1) { fclose(f); - okBox(0, "System message", "General I/O error during saving! Is the file in use?"); + okBox(0, "System message", "General I/O error during saving! Is the file in use?", NULL); return false; } if (fwrite(saveBuff, h.numRows * sizeof (note_t), 1, f) != 1) { fclose(f); - okBox(0, "System message", "General I/O error during saving! Is the file in use?"); + okBox(0, "System message", "General I/O error during saving! Is the file in use?", NULL); return false; } @@ -1283,25 +1297,25 @@ bool loadPattern(UNICHAR *filenameU) FILE *f = UNICHAR_FOPEN(filenameU, "rb"); if (f == NULL) { - okBox(0, "System message", "General I/O error during loading! Is the file in use?"); + okBox(0, "System message", "General I/O error during loading! Is the file in use?", NULL); return false; } if (!allocatePattern(editor.editPattern)) { - okBox(0, "System message", "Not enough memory!"); + okBox(0, "System message", "Not enough memory!", NULL); goto loadPattError; } if (fread(&h, 1, sizeof (h), f) != sizeof (h)) { - okBox(0, "System message", "General I/O error during loading! Is the file in use?"); + okBox(0, "System message", "General I/O error during loading! Is the file in use?", NULL); goto loadPattError; } if (h.version != 1) { - okBox(0, "System message", "Incompatible format version!"); + okBox(0, "System message", "Incompatible format version!", NULL); goto loadPattError; } @@ -1314,7 +1328,7 @@ bool loadPattern(UNICHAR *filenameU) if (fread(p, h.numRows * TRACK_WIDTH, 1, f) != 1) { unlockMixerCallback(); - okBox(0, "System message", "General I/O error during loading! Is the file in use?"); + okBox(0, "System message", "General I/O error during loading! Is the file in use?", NULL); goto loadPattError; } @@ -1373,14 +1387,14 @@ bool savePattern(UNICHAR *filenameU) note_t *p = pattern[editor.editPattern]; if (p == NULL) { - okBox(0, "System message", "The current pattern is empty!"); + okBox(0, "System message", "The current pattern is empty!", NULL); return false; } FILE *f = UNICHAR_FOPEN(filenameU, "wb"); if (f == NULL) { - okBox(0, "System message", "General I/O error during saving! Is the file in use?"); + okBox(0, "System message", "General I/O error during saving! Is the file in use?", NULL); return false; } @@ -1390,14 +1404,14 @@ bool savePattern(UNICHAR *filenameU) if (fwrite(&h, 1, sizeof (h), f) != sizeof (h)) { fclose(f); - okBox(0, "System message", "General I/O error during saving! Is the file in use?"); + okBox(0, "System message", "General I/O error during saving! Is the file in use?", NULL); return false; } if (fwrite(p, h.numRows * TRACK_WIDTH, 1, f) != 1) { fclose(f); - okBox(0, "System message", "General I/O error during saving! Is the file in use?"); + okBox(0, "System message", "General I/O error during saving! Is the file in use?", NULL); return false; } @@ -2635,7 +2649,7 @@ static void zapInstrs(void) void pbZap(void) { - const int16_t choice = okBox(4, "System request", "Total devastation of the..."); + const int16_t choice = okBox(3, "System request", "Total devastation of the...", NULL); if (choice == 1) // zap all { @@ -2695,16 +2709,23 @@ void resetChannelOffset(void) void shrinkPattern(void) { - if (okBox(2, "System request", "Shrink pattern?") != 1) - return; - + pauseMusic(); + const volatile uint16_t curPattern = editor.editPattern; int16_t numRows = patternNumRows[editor.editPattern]; + resumeMusic(); + if (numRows <= 1) + { + okBox(0, "System message", "Pattern is too short to be shrunk!", NULL); + return; + } + + if (okBox(2, "System request", "Shrink pattern?", NULL) != 1) return; lockMixerCallback(); - note_t *p = pattern[editor.editPattern]; + note_t *p = pattern[curPattern]; if (p != NULL) { for (int32_t i = 0; i < numRows / 2; i++) @@ -2714,10 +2735,10 @@ void shrinkPattern(void) } } - patternNumRows[editor.editPattern] /= 2; - numRows = patternNumRows[editor.editPattern]; + patternNumRows[curPattern] /= 2; + numRows = patternNumRows[curPattern]; - if (song.pattNum == editor.editPattern) + if (song.pattNum == curPattern) song.currNumRows = numRows; song.row /= 2; @@ -2735,45 +2756,48 @@ void shrinkPattern(void) void expandPattern(void) { + pauseMusic(); + const volatile uint16_t curPattern = editor.editPattern; int16_t numRows = patternNumRows[editor.editPattern]; + resumeMusic(); + if (numRows > MAX_PATT_LEN/2) { - okBox(0, "System message", "Pattern is too long to be expanded."); + okBox(0, "System message", "Pattern is too long to be expanded!", NULL); + return; } - else + + lockMixerCallback(); + + note_t *p = pattern[curPattern]; + if (p != NULL) { - lockMixerCallback(); + memcpy(tmpPattern, p, numRows * TRACK_WIDTH); - if (pattern[editor.editPattern] != NULL) + for (int32_t i = 0; i < numRows; i++) { - note_t *p = pattern[editor.editPattern]; - memcpy(tmpPattern, p, numRows * TRACK_WIDTH); - - for (int32_t i = 0; i < numRows; i++) - { - for (int32_t j = 0; j < MAX_CHANNELS; j++) - p[((i * 2) * MAX_CHANNELS) + j] = tmpPattern[(i * MAX_CHANNELS) + j]; + for (int32_t j = 0; j < MAX_CHANNELS; j++) + p[((i * 2) * MAX_CHANNELS) + j] = tmpPattern[(i * MAX_CHANNELS) + j]; - memset(&p[((i * 2) + 1) * MAX_CHANNELS], 0, TRACK_WIDTH); - } + memset(&p[((i * 2) + 1) * MAX_CHANNELS], 0, TRACK_WIDTH); } + } + + patternNumRows[curPattern] *= 2; + numRows = patternNumRows[curPattern]; - patternNumRows[editor.editPattern] *= 2; - numRows = patternNumRows[editor.editPattern]; - - if (song.pattNum == editor.editPattern) - song.currNumRows = numRows; + if (song.pattNum == curPattern) + song.currNumRows = numRows; - song.row *= 2; - if (song.row >= numRows) - song.row = numRows-1; + song.row *= 2; + if (song.row >= numRows) + song.row = numRows-1; - editor.row = song.row; + editor.row = song.row; - ui.updatePatternEditor = true; - ui.updatePosSections = true; + ui.updatePatternEditor = true; + ui.updatePosSections = true; - unlockMixerCallback(); - setSongModifiedFlag(); - } + unlockMixerCallback(); + setSongModifiedFlag(); } diff --git a/src/ft2_pattern_ed.h b/src/ft2_pattern_ed.h @@ -9,13 +9,13 @@ enum VOLUME_COLUMN_HIDDEN = 0, VOLUME_COLUMN_SHOWN = 1, - TRANSP_ALL_INST = 0, - TRANSP_CUR_INST = 1, - TRANSP_TRACK = 0, TRANSP_PATT = 1, TRANSP_SONG = 2, - TRANSP_BLOCK = 3 + TRANSP_BLOCK = 3, + + TRANSP_CUR_INSTRUMENT = false, + TRANSP_ALL_INSTRUMENTS = true, }; typedef struct xtHdr_t @@ -57,7 +57,7 @@ typedef struct pattMark_t int16_t markX1, markX2, markY1, markY2; } pattMark_t; -extern pattMark_t pattMark; // ft2_pattern_ed.c +extern volatile pattMark_t pattMark; // ft2_pattern_ed.c void resetPlaybackTime(void); diff --git a/src/ft2_replayer.c b/src/ft2_replayer.c @@ -271,7 +271,7 @@ double dAmigaPeriod2Hz(int32_t period) if (period == 0) return 0.0; // in FT2, a period of 0 results in 0Hz - return (double)(8363 * 1712) / period; + return (8363.0 * 1712.0) / period; } double dPeriod2Hz(int32_t period) @@ -2236,7 +2236,7 @@ void tickReplayer(void) // periodically called from audio callback int32_t i; channel_t *ch; - if (musicPaused || !songPlaying) + if (!songPlaying) { ch = channel; for (i = 0; i < song.numChannels; i++, ch++) @@ -2799,7 +2799,7 @@ bool setupReplayer(void) calcPanningTable(); - setPos(0, 0, true); + setPos(0, 0, true); // important! if (!allocateInstr(0)) { @@ -3113,7 +3113,6 @@ void stopVoices(void) editor.curPlaySmp = 255; stopAllScopes(); - resetAudioDither(); resetCachedMixerVars(); // wait for scope thread to finish, so that we know pointers aren't deprecated diff --git a/src/ft2_sample_ed.c b/src/ft2_sample_ed.c @@ -728,7 +728,7 @@ static int32_t SDLCALL copySampleThread(void *ptr) error: resumeAudio(); - okBoxThreadSafe(0, "System message", "Not enough memory!"); + okBoxThreadSafe(0, "System message", "Not enough memory!", NULL); return true; (void)ptr; @@ -743,7 +743,7 @@ void copySmp(void) // copy sample from srcInstr->srcSmp to curInstr->curSmp thread = SDL_CreateThread(copySampleThread, NULL, NULL); if (thread == NULL) { - okBox(0, "System message", "Couldn't create thread!"); + okBox(0, "System message", "Couldn't create thread!", NULL); return; } @@ -1644,7 +1644,7 @@ void showRange(void) } else { - okBox(0, "System message", "Cannot show empty range!"); + okBox(0, "System message", "Cannot show empty range!", NULL); } } @@ -1829,7 +1829,7 @@ void saveRange(void) if (smpEd_Rx1 == smpEd_Rx2) { - okBox(0, "System message", "No range specified!"); + okBox(0, "System message", "No range specified!", NULL); return; } @@ -1839,19 +1839,19 @@ void saveRange(void) if (smpEd_SysReqText[0] == '\0') { - okBox(0, "System message", "Filename can't be empty!"); + okBox(0, "System message", "Filename can't be empty!", NULL); return; } if (smpEd_SysReqText[0] == '.') { - okBox(0, "System message", "The very first character in the filename can't be '.' (dot)!"); + okBox(0, "System message", "The very first character in the filename can't be '.' (dot)!", NULL); return; } if (strpbrk(smpEd_SysReqText, "\\/:*?\"<>|") != NULL) { - okBox(0, "System message", "The filename can't contain the following characters: \\ / : * ? \" < > |"); + okBox(0, "System message", "The filename can't contain the following characters: \\ / : * ? \" < > |", NULL); return; } @@ -1865,7 +1865,7 @@ void saveRange(void) UNICHAR *filenameU = cp437ToUnichar(smpEd_SysReqText); if (filenameU == NULL) { - okBox(0, "System message", "Out of memory!"); + okBox(0, "System message", "Not enough memory!", NULL); return; } @@ -1873,7 +1873,7 @@ void saveRange(void) { char buf[256]; createFileOverwriteText(smpEd_SysReqText, buf); - if (okBox(2, "System request", buf) != 1) + if (okBox(2, "System request", buf, NULL) != 1) return; } @@ -1904,7 +1904,7 @@ static bool cutRange(bool cropMode, int32_t r1, int32_t r2) fixSample(s); resumeAudio(); - okBoxThreadSafe(0, "System message", "Not enough memory!"); + okBoxThreadSafe(0, "System message", "Not enough memory!", NULL); return false; } @@ -1926,7 +1926,7 @@ static bool cutRange(bool cropMode, int32_t r1, int32_t r2) if (!cropMode) resumeAudio(); - okBoxThreadSafe(0, "System message", "Not enough memory!"); + okBoxThreadSafe(0, "System message", "Not enough memory!", NULL); return false; } @@ -1986,7 +1986,7 @@ static bool cutRange(bool cropMode, int32_t r1, int32_t r2) static int32_t SDLCALL sampCutThread(void *ptr) { if (!cutRange(false, smpEd_Rx1, smpEd_Rx2)) - okBoxThreadSafe(0, "System message", "Not enough memory! (Disable \"cut to buffer\")"); + okBoxThreadSafe(0, "System message", "Not enough memory! (Disable \"cut to buffer\")", NULL); else writeSampleFlag = true; @@ -2005,7 +2005,7 @@ void sampCut(void) thread = SDL_CreateThread(sampCutThread, NULL, NULL); if (thread == NULL) { - okBox(0, "System message", "Couldn't create thread!"); + okBox(0, "System message", "Couldn't create thread!", NULL); return; } @@ -2020,7 +2020,7 @@ static int32_t SDLCALL sampCopyThread(void *ptr) if (!getCopyBuffer(smpEd_Rx2- smpEd_Rx1, sample16Bit)) { - okBoxThreadSafe(0, "System message", "Not enough memory!"); + okBoxThreadSafe(0, "System message", "Not enough memory!", NULL); return true; } @@ -2053,7 +2053,7 @@ void sampCopy(void) thread = SDL_CreateThread(sampCopyThread, NULL, NULL); if (thread == NULL) { - okBox(0, "System message", "Couldn't create thread!"); + okBox(0, "System message", "Couldn't create thread!", NULL); return; } @@ -2066,7 +2066,7 @@ static void pasteOverwrite(sample_t *s) if (!reallocateSmpData(s, smpCopySize, sample16Bit)) { - okBoxThreadSafe(0, "System message", "Not enough memory!"); + okBoxThreadSafe(0, "System message", "Not enough memory!", NULL); return; } @@ -2152,7 +2152,7 @@ static int32_t SDLCALL sampPasteThread(void *ptr) if (instr[editor.curInstr] == NULL && !allocateInstr(editor.curInstr)) { - okBoxThreadSafe(0, "System message", "Not enough memory!"); + okBoxThreadSafe(0, "System message", "Not enough memory!", NULL); return true; } @@ -2167,7 +2167,7 @@ static int32_t SDLCALL sampPasteThread(void *ptr) if (s->length+smpCopySize > MAX_SAMPLE_LEN) { - okBoxThreadSafe(0, "System message", "Not enough room in sample!"); + okBoxThreadSafe(0, "System message", "Not enough room in sample!", NULL); return true; } @@ -2177,13 +2177,13 @@ static int32_t SDLCALL sampPasteThread(void *ptr) if (newLength > MAX_SAMPLE_LEN) { - okBoxThreadSafe(0, "System message", "Not enough room in sample!"); + okBoxThreadSafe(0, "System message", "Not enough room in sample!", NULL); return true; } if (!allocateSmpDataPtr(&sp, newLength, sample16Bit)) { - okBoxThreadSafe(0, "System message", "Not enough memory!"); + okBoxThreadSafe(0, "System message", "Not enough memory!", NULL); return true; } @@ -2255,7 +2255,7 @@ void sampPaste(void) sample_t *s = getCurSample(); if (s != NULL && s->dataPtr != NULL && s->length > 0) { - if (okBox(2, "System request", "The current sample is not empty. Do you really want to overwrite it?") != 1) + if (okBox(2, "System request", "The current sample is not empty. Do you really want to overwrite it?", NULL) != 1) return; } } @@ -2264,7 +2264,7 @@ void sampPaste(void) thread = SDL_CreateThread(sampPasteThread, NULL, NULL); if (thread == NULL) { - okBox(0, "System message", "Couldn't create thread!"); + okBox(0, "System message", "Couldn't create thread!", NULL); return; } @@ -2319,7 +2319,7 @@ void sampCrop(void) thread = SDL_CreateThread(sampCropThread, NULL, NULL); if (thread == NULL) { - okBox(0, "System message", "Couldn't create thread!"); + okBox(0, "System message", "Couldn't create thread!", NULL); return; } @@ -2337,21 +2337,21 @@ void sampXFade(void) // check if the sample has the loop flag enabled if (GET_LOOPTYPE(s->flags) == LOOP_OFF) { - okBox(0, "System message", "X-Fade can only be used on a loop-enabled sample!"); + okBox(0, "System message", "X-Fade can only be used on a loop-enabled sample!", NULL); return; } // check if we selected a range if (smpEd_Rx2 == 0) { - okBox(0, "System message", "No range selected! Make a small range that includes loop start or loop end."); + okBox(0, "System message", "No range selected! Make a small range that includes loop start or loop end.", NULL); return; } // check if we selected a valid range length if (smpEd_Rx2-smpEd_Rx1 <= 2) { - okBox(0, "System message", "Invalid range!"); + okBox(0, "System message", "Invalid range!", NULL); return; } @@ -2367,7 +2367,7 @@ void sampXFade(void) { if (x2 <= y1 || x2 >= s->loopStart+s->loopLength) { - okBox(0, "System message", "Error: No loop point found inside marked data."); + okBox(0, "System message", "Error: No loop point found inside marked data.", NULL); return; } @@ -2380,13 +2380,13 @@ void sampXFade(void) if (d1 < 1 || d2 < 1 || d3 < 1) { - okBox(0, "System message", "Invalid range! Try to mark more data."); + okBox(0, "System message", "Invalid range! Try to mark more data.", NULL); return; } if (y1-d1 < 0 || y1+d1 >= s->length) { - okBox(0, "System message", "Not enough sample data outside loop!"); + okBox(0, "System message", "Not enough sample data outside loop!", NULL); return; } @@ -2430,7 +2430,7 @@ void sampXFade(void) y1 += s->loopLength; if (x1 >= y1 || x2 <= y1 || x2 >= s->length) { - okBox(0, "System message", "Error: No loop point found inside marked data."); + okBox(0, "System message", "Error: No loop point found inside marked data.", NULL); return; } @@ -2443,13 +2443,13 @@ void sampXFade(void) if (d1 < 1 || d2 < 1 || d3 < 1) { - okBox(0, "System message", "Invalid range! Try to mark more data."); + okBox(0, "System message", "Invalid range! Try to mark more data.", NULL); return; } if (y1-d1 < 0 || y1+d1 >= s->length) { - okBox(0, "System message", "Not enough sample data outside loop!"); + okBox(0, "System message", "Not enough sample data outside loop!", NULL); return; } @@ -2499,7 +2499,7 @@ void sampXFade(void) if (x1 < 0 || x2 <= x1 || x2 >= s->length) { - okBox(0, "System message", "Invalid range!"); + okBox(0, "System message", "Invalid range!", NULL); return; } @@ -2511,7 +2511,7 @@ void sampXFade(void) if (y1 < 0 || y2+length >= s->length) { - okBox(0, "System message", "Not enough sample data outside loop!"); + okBox(0, "System message", "Not enough sample data outside loop!", NULL); return; } @@ -2521,7 +2521,7 @@ void sampXFade(void) if (y1+length <= s->loopStart || d1 == 0 || d3 == 0 || d1 > s->loopLength) { - okBox(0, "System message", "Invalid range!"); + okBox(0, "System message", "Invalid range!", NULL); return; } @@ -2680,13 +2680,13 @@ void rbSample8bit(void) if (s == NULL || s->dataPtr == NULL || s->length <= 0) return; - if (okBox(2, "System request", "Convert sampledata?") == 1) + if (okBox(2, "System request", "Pre-convert sample data?", NULL) == 1) { mouseAnimOn(); thread = SDL_CreateThread(convSmp8Bit, NULL, NULL); if (thread == NULL) { - okBox(0, "System message", "Couldn't create thread!"); + okBox(0, "System message", "Couldn't create thread!", NULL); return; } @@ -2720,7 +2720,7 @@ static int32_t SDLCALL convSmp16Bit(void *ptr) if (!reallocateSmpData(s, s->length, true)) { - okBoxThreadSafe(0, "System message", "Not enough memory!"); + okBoxThreadSafe(0, "System message", "Not enough memory!", NULL); return true; } @@ -2748,13 +2748,13 @@ void rbSample16bit(void) if (s == NULL || s->dataPtr == NULL || s->length <= 0) return; - if (okBox(2, "System request", "Convert sampledata?") == 1) + if (okBox(2, "System request", "Pre-convert sample data?", NULL) == 1) { mouseAnimOn(); thread = SDL_CreateThread(convSmp16Bit, NULL, NULL); if (thread == NULL) { - okBox(0, "System message", "Couldn't create thread!"); + okBox(0, "System message", "Couldn't create thread!", NULL); return; } @@ -2785,7 +2785,7 @@ void clearSample(void) if (s == NULL || s->dataPtr == NULL || s->length <= 0) return; - if (okBox(1, "System request", "Clear sample?") != 1) + if (okBox(1, "System request", "Clear sample?", NULL) != 1) return; freeSample(editor.curInstr, editor.curSmp); @@ -2802,17 +2802,17 @@ void sampMinimize(void) const bool hasLoop = GET_LOOPTYPE(s->flags) != LOOP_OFF; if (!hasLoop) { - okBox(0, "System message", "Only a looped sample can be minimized!"); + okBox(0, "System message", "Only a looped sample can be minimized!", NULL); return; } if (s->loopStart+s->loopLength >= s->length) { - okBox(0, "System message", "The sample can't be minimized any further."); + okBox(0, "System message", "This sample is already minimized.", NULL); return; } - if (okBox(1, "System request", "Minimize sample?") != 1) + if (okBox(1, "System request", "Minimize sample?", NULL) != 1) return; lockMixerCallback(); @@ -3613,7 +3613,7 @@ void sampleBackwards(void) thread = SDL_CreateThread(sampleBackwardsThread, NULL, NULL); if (thread == NULL) { - okBox(0, "System message", "Couldn't create thread!"); + okBox(0, "System message", "Couldn't create thread!", NULL); return; } @@ -3662,7 +3662,7 @@ void sampleChangeSign(void) thread = SDL_CreateThread(sampleChangeSignThread, NULL, NULL); if (thread == NULL) { - okBox(0, "System message", "Couldn't create thread!"); + okBox(0, "System message", "Couldn't create thread!", NULL); return; } @@ -3708,7 +3708,7 @@ void sampleByteSwap(void) if (!(s->flags & SAMPLE_16BIT)) { - if (okBox(2, "System request", "Byte swapping only makes sense on a 16-bit sample. Continue?") != 1) + if (okBox(2, "System request", "Byte swapping rarely makes sense on an 8-bit sample. Continue?", NULL) != 1) return; } @@ -3716,7 +3716,7 @@ void sampleByteSwap(void) thread = SDL_CreateThread(sampleByteSwapThread, NULL, NULL); if (thread == NULL) { - okBox(0, "System message", "Couldn't create thread!"); + okBox(0, "System message", "Couldn't create thread!", NULL); return; } @@ -3828,7 +3828,7 @@ void fixDC(void) thread = SDL_CreateThread(fixDCThread, NULL, NULL); if (thread == NULL) { - okBox(0, "System message", "Couldn't create thread!"); + okBox(0, "System message", "Couldn't create thread!", NULL); return; } diff --git a/src/ft2_sample_ed_features.c b/src/ft2_sample_ed_features.c @@ -178,7 +178,7 @@ static void pbDoResampling(void) thread = SDL_CreateThread(resampleThread, NULL, NULL); if (thread == NULL) { - okBox(0, "System message", "Couldn't create thread!"); + okBox(0, "System message", "Couldn't create thread!", NULL); return; } @@ -345,7 +345,7 @@ void pbSampleResample(void) windowClose(false); if (outOfMemory) - okBox(0, "System message", "Not enough memory!"); + okBox(0, "System message", "Not enough memory!", NULL); } static void cbEchoAddMemory(void) @@ -559,7 +559,7 @@ static void pbCreateEcho(void) thread = SDL_CreateThread(createEchoThread, NULL, NULL); if (thread == NULL) { - okBox(0, "System message", "Couldn't create thread!"); + okBox(0, "System message", "Couldn't create thread!", NULL); return; } @@ -803,7 +803,7 @@ void pbSampleEcho(void) windowClose(echo_AddMemory ? false : true); if (outOfMemory) - okBox(0, "System message", "Not enough memory!"); + okBox(0, "System message", "Not enough memory!", NULL); } static int32_t SDLCALL mixThread(void *ptr) @@ -946,7 +946,7 @@ static void pbMix(void) thread = SDL_CreateThread(mixThread, NULL, NULL); if (thread == NULL) { - okBox(0, "System message", "Couldn't create thread!"); + okBox(0, "System message", "Couldn't create thread!", NULL); return; } @@ -1101,7 +1101,7 @@ void pbSampleMix(void) windowClose(false); if (outOfMemory) - okBox(0, "System message", "Not enough memory!"); + okBox(0, "System message", "Not enough memory!", NULL); } static void sbSetStartVolPos(uint32_t pos) @@ -1285,7 +1285,7 @@ static void pbApplyVolume(void) thread = SDL_CreateThread(applyVolumeThread, NULL, NULL); if (thread == NULL) { - okBox(0, "System message", "Couldn't create thread!"); + okBox(0, "System message", "Couldn't create thread!", NULL); return; } @@ -1391,7 +1391,7 @@ static void pbGetMaxScale(void) thread = SDL_CreateThread(getMaxScaleThread, NULL, NULL); if (thread == NULL) { - okBox(0, "System message", "Couldn't create thread!"); + okBox(0, "System message", "Couldn't create thread!", NULL); return; } diff --git a/src/ft2_sample_saver.c b/src/ft2_sample_saver.c @@ -122,7 +122,7 @@ static bool saveRawSample(UNICHAR *filenameU, bool saveRangedData) instr_t *ins = instr[editor.curInstr]; if (ins == NULL || ins->smp[editor.curSmp].dataPtr == NULL || ins->smp[editor.curSmp].length == 0) { - okBoxThreadSafe(0, "System message", "The sample is empty!"); + okBoxThreadSafe(0, "System message", "The sample is empty!", NULL); return false; } @@ -143,14 +143,14 @@ static bool saveRawSample(UNICHAR *filenameU, bool saveRangedData) FILE *f = UNICHAR_FOPEN(filenameU, "wb"); if (f == NULL) { - okBoxThreadSafe(0, "System message", "General I/O error during saving! Is the file in use?"); + okBoxThreadSafe(0, "System message", "General I/O error during saving! Is the file in use?", NULL); return false; } if (fwrite(samplePtr, sampleLen, 1, f) != 1) { fclose(f); - okBoxThreadSafe(0, "System message", "Error saving sample: General I/O error!"); + okBoxThreadSafe(0, "System message", "Error saving sample: General I/O error!", NULL); return false; } @@ -206,7 +206,7 @@ static bool saveIFFSample(UNICHAR *filenameU, bool saveRangedData) instr_t *ins = instr[editor.curInstr]; if (ins == NULL || ins->smp[editor.curSmp].dataPtr == NULL || ins->smp[editor.curSmp].length == 0) { - okBoxThreadSafe(0, "System message", "The sample is empty!"); + okBoxThreadSafe(0, "System message", "The sample is empty!", NULL); return false; } @@ -215,7 +215,7 @@ static bool saveIFFSample(UNICHAR *filenameU, bool saveRangedData) FILE *f = UNICHAR_FOPEN(filenameU, "wb"); if (f == NULL) { - okBoxThreadSafe(0, "System message", "General I/O error during saving! Is the file in use?"); + okBoxThreadSafe(0, "System message", "General I/O error during saving! Is the file in use?", NULL); return false; } @@ -331,7 +331,7 @@ static bool saveWAVSample(UNICHAR *filenameU, bool saveRangedData) instr_t *ins = instr[editor.curInstr]; if (ins == NULL || ins->smp[editor.curSmp].dataPtr == NULL || ins->smp[editor.curSmp].length == 0) { - okBoxThreadSafe(0, "System message", "The sample is empty!"); + okBoxThreadSafe(0, "System message", "The sample is empty!", NULL); return false; } @@ -340,7 +340,7 @@ static bool saveWAVSample(UNICHAR *filenameU, bool saveRangedData) FILE *f = UNICHAR_FOPEN(filenameU, "wb"); if (f == NULL) { - okBoxThreadSafe(0, "System message", "General I/O error during saving! Is the file in use?"); + okBoxThreadSafe(0, "System message", "General I/O error during saving! Is the file in use?", NULL); return false; } @@ -503,7 +503,7 @@ static int32_t SDLCALL saveSampleThread(void *ptr) { if (editor.tmpFilenameU == NULL) { - okBoxThreadSafe(0, "System message", "General I/O error during saving! Is the file in use?"); + okBoxThreadSafe(0, "System message", "General I/O error during saving! Is the file in use?", NULL); return false; } @@ -538,7 +538,7 @@ void saveSample(UNICHAR *filenameU, bool saveAsRange) thread = SDL_CreateThread(saveSampleThread, NULL, NULL); if (thread == NULL) { - okBoxThreadSafe(0, "System message", "Couldn't create thread!"); + okBoxThreadSafe(0, "System message", "Couldn't create thread!", NULL); return; } diff --git a/src/ft2_sampling.c b/src/ft2_sampling.c @@ -298,7 +298,7 @@ void handleSamplingUpdates(void) { outOfMemoryFlag = false; stopSampling(); - okBox(0, "System message", "Not enough memory!"); + okBox(0, "System message", "Not enough memory!", NULL); return; } @@ -306,7 +306,7 @@ void handleSamplingUpdates(void) { noMoreRoomFlag = false; stopSampling(); - okBox(0, "System message", "Not more room in sample!"); + okBox(0, "System message", "Not more room in sample!", NULL); return; } @@ -326,7 +326,7 @@ void handleSamplingUpdates(void) void startSampling(void) { #if SDL_MAJOR_VERSION == 2 && SDL_MINOR_VERSION == 0 && SDL_PATCHLEVEL < 5 - okBox(0, "System message", "This program needs to be compiled with SDL 2.0.5 or later to support audio sampling."); + okBox(0, "System message", "This program needs to be compiled with SDL 2.0.5 or later to support audio sampling.", NULL); return; #else SDL_AudioSpec want, have; @@ -334,7 +334,7 @@ void startSampling(void) if (editor.samplingAudioFlag || editor.curInstr == 0) return; - int16_t result = okBox(9, "System request", "Stereo sampling will use the next sample slot. While ongoing, press any key to stop."); + int16_t result = okBox(5, "System request", "Stereo sampling will use the next sample slot. While ongoing, press any key to stop.", NULL); if (result == 0 || result == 3) return; @@ -358,7 +358,7 @@ void startSampling(void) recordDev = SDL_OpenAudioDevice(audio.currInputDevice, true, &want, &have, 0); if (recordDev == 0) { - okBox(0, "System message", "Couldn't open the input device! Try adjusting the input rate at the config screen."); + okBox(0, "System message", "Couldn't open the input device! Try adjusting the input rate at the config screen.", NULL); return; } @@ -370,14 +370,14 @@ void startSampling(void) if (instr[editor.curInstr] == NULL && !allocateInstr(editor.curInstr)) { stopSampling(); - okBox(0, "System message", "Not enough memory!"); + okBox(0, "System message", "Not enough memory!", NULL); return; } if (sampleInStereo && editor.curSmp+1 >= MAX_SMP_PER_INST) { stopSampling(); - okBox(0, "System message", "Error: No free sample slot for the right channel!"); + okBox(0, "System message", "Error: No free sample slot for the right channel!", NULL); return; } diff --git a/src/ft2_sysreqs.c b/src/ft2_sysreqs.c @@ -15,40 +15,38 @@ #define SYSTEM_REQUEST_Y 249 #define SYSTEM_REQUEST_Y_EXT 91 -#define NUM_SYSREQ_TYPES 10 - // globalized okBoxData_t okBoxData; void (*loaderMsgBox)(const char *, ...); -int16_t (*loaderSysReq)(int16_t, const char *, const char *); +int16_t (*loaderSysReq)(int16_t, const char *, const char *, void (*)(void)); // ---------------- +#define NUM_SYSREQ_TYPES 6 + static char *buttonText[NUM_SYSREQ_TYPES][5] = { + // generic dialogs { "OK", "","","","" }, { "OK", "Cancel", "","","" }, { "Yes", "No", "","","" }, - { "","","","","" }, // removed (TODO: Re-arrange and fix all sysreq call offsets...) - { "All", "Song", "Instruments", "Cancel", "" }, - { "Read left", "Read right", "Convert", "", "" }, - { "OK", "","","","" }, - { "OK", "","","","" }, - { "Sorry...", "","","","" }, - { "Mono", "Stereo", "Cancel", "","" } + + // custom dialogs + { "All", "Song", "Instruments", "Cancel", "" }, // "song clear" dialog + { "Read left", "Read right", "Convert", "", "" }, // "stereo sample loader" dialog + { "Mono", "Stereo", "Cancel", "","" } // "audio sampling" dialog }; static SDL_Keycode shortCut[NUM_SYSREQ_TYPES][5] = { + // generic dialogs { SDLK_o, 0, 0, 0, 0 }, { SDLK_o, SDLK_c, 0, 0, 0 }, { SDLK_y, SDLK_n, 0, 0, 0 }, - { 0, 0, 0, 0, 0 }, // deprecated - { SDLK_a, SDLK_s, SDLK_i, SDLK_c, 0 }, - { SDLK_l, SDLK_r, SDLK_c, 0, 0 }, - { SDLK_o, 0, 0, 0, 0 }, - { SDLK_o, 0, 0, 0, 0 }, - { SDLK_s, 0, 0, 0, 0 }, - { SDLK_m, SDLK_s, SDLK_c, 0, 0 }, + + // custom dialogs + { SDLK_a, SDLK_s, SDLK_i, SDLK_c, 0 }, // "song clear" dialog + { SDLK_l, SDLK_r, SDLK_c, 0, 0 }, // "stereo sample loader" dialog + { SDLK_m, SDLK_s, SDLK_c, 0, 0 }, // "audio sampling" dialog }; typedef struct quitType_t @@ -61,7 +59,7 @@ typedef struct quitType_t static quitType_t quitMessage[QUIT_MESSAGES] = { - // removed unsuitable/offensive ones... + // edited (and removed) some of the original quit texts... { "Do you really want to quit?", 2 }, { "Tired already?", 2 }, @@ -72,7 +70,7 @@ static quitType_t quitMessage[QUIT_MESSAGES] = { "Did you really press the right key?", 2 }, { "Hope ya did some good. Press >OK< to quit.", 1 }, { "Quit? Only for a good reason you are allowed to press >OK<.", 1 }, - { "Are we at the end of a Fasttracker round?", 2 }, + { "Are we at the end of a Fasttracker II round?", 2 }, { "Hope you're doing the compulsory \"Exit ceremony\" before pressing >OK<.", 1 }, }; @@ -86,7 +84,7 @@ void myLoaderMsgBoxThreadSafe(const char *fmt, ...) vsnprintf(strBuf, sizeof (strBuf), fmt, args); va_end(args); - okBoxThreadSafe(0, "System message", fmt); + okBoxThreadSafe(0, "System message", fmt, NULL); } void myLoaderMsgBox(const char *fmt, ...) @@ -99,13 +97,13 @@ void myLoaderMsgBox(const char *fmt, ...) vsnprintf(strBuf, sizeof (strBuf), fmt, args); va_end(args); - okBox(0, "System message", fmt); + okBox(0, "System message", fmt, NULL); } static void drawWindow(uint16_t w) { const uint16_t h = SYSTEM_REQUEST_H; - const uint16_t x = (SCREEN_W - w) >> 1; + const uint16_t x = (SCREEN_W - w) / 2; const uint16_t y = ui.extended ? 91 : SYSTEM_REQUEST_Y; // main fill @@ -181,13 +179,12 @@ static bool mouseButtonUpLogic(uint8_t mouseButton) } // WARNING: This routine must ONLY be called from the main input/video thread! -int16_t okBox(int16_t type, const char *headline, const char *text) +// If the checkBoxCallback argument is set, then you get a "Do not show again" checkbox. +int16_t okBox(int16_t type, const char *headline, const char *text, void (*checkBoxCallback)(void)) { #define PUSHBUTTON_W 80 - uint16_t i; SDL_Event inputEvent; - pushButton_t *p; if (editor.editTextFlag) exitTextEditing(); @@ -227,19 +224,19 @@ int16_t okBox(int16_t type, const char *headline, const char *text) if (wlen > 600) wlen = 600; - uint16_t headlineX = (SCREEN_W - hlen) >> 1; - uint16_t textX = (SCREEN_W - tlen) >> 1; - uint16_t x = (SCREEN_W - wlen) >> 1; + const uint16_t headlineX = (SCREEN_W - hlen) / 2; + const uint16_t textX = (SCREEN_W - tlen) / 2; + const uint16_t x = (SCREEN_W - wlen) / 2; - // the box y position differs in extended pattern editor mode - uint16_t y = ui.extended ? SYSTEM_REQUEST_Y_EXT : SYSTEM_REQUEST_Y; + // the dialog's y position differs in extended pattern editor mode + const uint16_t y = ui.extended ? SYSTEM_REQUEST_Y_EXT : SYSTEM_REQUEST_Y; // set up buttons - for (i = 0; i < numButtons; i++) + for (uint16_t i = 0; i < numButtons; i++) { - p = &pushButtons[i]; + pushButton_t *p = &pushButtons[i]; - p->x = ((SCREEN_W - tx) >> 1) + (i * 100); + p->x = ((SCREEN_W - tx) / 2) + (i * 100); p->y = y + 42; p->w = PUSHBUTTON_W; p->h = 16; @@ -247,8 +244,9 @@ int16_t okBox(int16_t type, const char *headline, const char *text) p->visible = true; } - // set up checkbox (special okBox types only!) - if (type >= 6 && type <= 7) + // set up "don't show again" checkbox (if callback present) + bool hasCheckbox = (checkBoxCallback != NULL); + if (hasCheckbox) { checkBox_t *c = &checkBoxes[0]; c->x = x + 5; @@ -256,18 +254,7 @@ int16_t okBox(int16_t type, const char *headline, const char *text) c->clickAreaWidth = 116; c->clickAreaHeight = 12; c->checked = false; - - if (type == 6) - { - // S3M load warning - c->callbackFunc = configToggleImportWarning; - } - else if (type == 7) - { - // "setting not yet applied" - c->callbackFunc = configToggleNotYetAppliedWarning; - } - + c->callbackFunc = checkBoxCallback; c->visible = true; } @@ -313,7 +300,7 @@ int16_t okBox(int16_t type, const char *headline, const char *text) keyb.ignoreCurrKeyUp = true; // don't handle key up event for any keys that were pressed } - for (i = 0; i < numButtons; i++) + for (uint16_t i = 0; i < numButtons; i++) { if (shortCut[type][i] == inputEvent.key.keysym.sym) { @@ -328,7 +315,7 @@ int16_t okBox(int16_t type, const char *headline, const char *text) { if (mouseButtonUpLogic(inputEvent.button.button)) { - if (type >= 6 && type <= 7) + if (hasCheckbox) testCheckBoxMouseRelease(); returnVal = testPushButtonMouseRelease(false) + 1; @@ -361,8 +348,8 @@ int16_t okBox(int16_t type, const char *headline, const char *text) drawWindow(wlen); textOutShadow(headlineX, y + 4, PAL_FORGRND, PAL_BUTTON2, headline); textOutShadow(textX, y + 24, PAL_FORGRND, PAL_BUTTON2, text); - for (i = 0; i < numButtons; i++) drawPushButton(i); - if (type >= 6 && type <= 7) + for (uint16_t i = 0; i < numButtons; i++) drawPushButton(i); + if (hasCheckbox) { drawCheckBox(0); textOutShadow(x + 21, y + 52, PAL_FORGRND, PAL_BUTTON2, "Don't show again"); @@ -372,10 +359,10 @@ int16_t okBox(int16_t type, const char *headline, const char *text) endFPSCounter(); } - for (i = 0; i < numButtons; i++) + for (uint16_t i = 0; i < numButtons; i++) hidePushButton(i); - if (type >= 6 && type <= 7) + if (hasCheckbox) hideCheckBox(0); mouse.lastUsedObjectID = oldLastUsedObjectID; @@ -390,14 +377,13 @@ int16_t okBox(int16_t type, const char *headline, const char *text) /* WARNING: ** - This routine must ONLY be called from the main input/video thread!! -** - edText must be null-terminated +** - edText must be NUL-terminated */ int16_t inputBox(int16_t type, const char *headline, char *edText, uint16_t maxStrLen) { #define PUSHBUTTON_W 80 #define TEXTBOX_W 250 - uint16_t wlen, i; SDL_Event inputEvent; if (editor.editTextFlag) @@ -426,12 +412,12 @@ int16_t inputBox(int16_t type, const char *headline, char *edText, uint16_t maxS t->changeMouseCursor = true; t->renderBufW = (9 + 1) * t->maxChars; // 9 = max character/glyph width possible t->renderBufH = 10; // 10 = max character height possible - t->renderW = t->w - (t->tx << 1); + t->renderW = t->w - (t->tx * 2); t->renderBuf = (uint8_t *)malloc(t->renderBufW * t->renderBufH * sizeof (int8_t)); if (t->renderBuf == NULL) { - okBox(0, "System message", "Not enough memory!"); + okBox(0, "System message", "Not enough memory!", NULL); return 0; } @@ -440,8 +426,8 @@ int16_t inputBox(int16_t type, const char *headline, char *edText, uint16_t maxS ui.sysReqShown = true; mouseAnimOff(); - wlen = textWidth(headline); - uint16_t headlineX = (SCREEN_W - wlen) >> 1; + uint16_t wlen = textWidth(headline); + const uint16_t headlineX = (SCREEN_W - wlen) / 2; // count number of buttons uint16_t numButtons = 0; @@ -461,21 +447,21 @@ int16_t inputBox(int16_t type, const char *headline, char *edText, uint16_t maxS wlen = 600; // the box y position differs in extended pattern editor mode - uint16_t y = ui.extended ? SYSTEM_REQUEST_Y_EXT : SYSTEM_REQUEST_Y; + const uint16_t y = ui.extended ? SYSTEM_REQUEST_Y_EXT : SYSTEM_REQUEST_Y; // set further text box settings - t->x = (SCREEN_W - TEXTBOX_W) >> 1; + t->x = (SCREEN_W - TEXTBOX_W) / 2; t->y = y + 24; t->visible = true; // setup buttons pushButton_t *p = pushButtons; - for (i = 0; i < numButtons; i++, p++) + for (uint16_t i = 0; i < numButtons; i++, p++) { p->w = PUSHBUTTON_W; p->h = 16; - p->x = ((SCREEN_W - tx) >> 1) + (i * 100); + p->x = ((SCREEN_W - tx) / 2) + (i * 100); p->y = y + 42; p->caption = buttonText[type][i]; p->visible = true; @@ -554,7 +540,7 @@ int16_t inputBox(int16_t type, const char *headline, char *edText, uint16_t maxS } else { - for (i = 0; i < numButtons; i++) + for (uint16_t i = 0; i < numButtons; i++) { if (shortCut[1][i] == inputEvent.key.keysym.sym) { @@ -605,7 +591,7 @@ int16_t inputBox(int16_t type, const char *headline, char *edText, uint16_t maxS hLine(t->x, t->y + t->h, t->w + 1, PAL_BUTTON1); vLine(t->x + t->w, t->y, t->h, PAL_BUTTON1); drawTextBox(0); - for (i = 0; i < numButtons; i++) drawPushButton(i); + for (uint16_t i = 0; i < numButtons; i++) drawPushButton(i); flipFrame(); endFPSCounter(); @@ -614,7 +600,7 @@ int16_t inputBox(int16_t type, const char *headline, char *edText, uint16_t maxS editor.editTextFlag = false; SDL_StopTextInput(); - for (i = 0; i < numButtons; i++) + for (uint16_t i = 0; i < numButtons; i++) hidePushButton(i); hideTextBox(0); @@ -631,31 +617,36 @@ int16_t inputBox(int16_t type, const char *headline, char *edText, uint16_t maxS } // WARNING: This routine must NOT be called from the main input/video thread! -int16_t okBoxThreadSafe(int16_t type, const char *headline, const char *text) +// If the checkBoxCallback argument is set, then you get a "Do not show again" checkbox. +int16_t okBoxThreadSafe(int16_t type, const char *headline, const char *text, void (*checkBoxCallback)(void)) { if (!editor.mainLoopOngoing) return 0; // main loop was not even started yet, bail out. - // block multiple calls before they are completed (for safety) + // the amount of time to wait is not important, but close to one video frame makes sense + const uint32_t waitTime = (uint32_t)((1000.0 / VBLANK_HZ) + 0.5); + + // block multiple calls before they are completed (just in case, for safety) while (okBoxData.active) - SDL_Delay(1000 / VBLANK_HZ); // accuracy is not important here + SDL_Delay(waitTime); + okBoxData.checkBoxCallback = checkBoxCallback; okBoxData.type = type; okBoxData.headline = headline; okBoxData.text = text; okBoxData.active = true; while (okBoxData.active) - SDL_Delay(1000 / VBLANK_HZ); // accuracy is not important here + SDL_Delay(waitTime); return okBoxData.returnData; } static bool askQuit_RandomMsg(void) { - uint8_t msg = rand() % QUIT_MESSAGES; - int16_t button = okBox(quitMessage[msg].type, "System request", quitMessage[msg].text); + quitType_t *q = &quitMessage[rand() % QUIT_MESSAGES]; + int16_t button = okBox(q->type, "System request", q->text, NULL); return (button == 1) ? true : false; } @@ -666,12 +657,12 @@ bool askUnsavedChanges(uint8_t type) if (type == ASK_TYPE_QUIT) { button = okBox(2, "System request", - "You have unsaved changes in your song. Do you still want to quit and lose ALL changes?"); + "You have unsaved changes in your song. Do you still want to quit and lose ALL changes?", NULL); } else { button = okBox(2, "System request", - "You have unsaved changes in your song. Load new song and lose ALL changes?"); + "You have unsaved changes in your song. Load new song and lose ALL changes?", NULL); } return (button == 1) ? true : false; diff --git a/src/ft2_sysreqs.h b/src/ft2_sysreqs.h @@ -15,10 +15,14 @@ typedef struct okBoxData_t volatile bool active; int16_t type, returnData; const char *headline, *text; + void (*checkBoxCallback)(void); } okBoxData_t; -int16_t okBoxThreadSafe(int16_t type, const char *headline, const char *text); -int16_t okBox(int16_t type, const char *headline, const char *text); +// If the checkBoxCallback argument is set, then you get a "Do not show again" checkbox. +int16_t okBoxThreadSafe(int16_t type, const char *headline, const char *text, void (*checkBoxCallback)(void)); +int16_t okBox(int16_t type, const char *headline, const char *text, void (*checkBoxCallback)(void)); +// ----------- + int16_t quitBox(bool skipQuitMsg); int16_t inputBox(int16_t type, const char *headline, char *edText, uint16_t maxStrLen); bool askUnsavedChanges(uint8_t type); @@ -29,5 +33,5 @@ void myLoaderMsgBox(const char *fmt, ...); // ft2_sysreqs.c extern okBoxData_t okBoxData; extern void (*loaderMsgBox)(const char *, ...); -extern int16_t (*loaderSysReq)(int16_t, const char *, const char *); +extern int16_t (*loaderSysReq)(int16_t, const char *, const char *, void (*)(void)); // --------------- diff --git a/src/ft2_textboxes.c b/src/ft2_textboxes.c @@ -145,7 +145,7 @@ static void deleteMarkedText(textBox_t *t) for (int32_t i = start; i < end; i++) deleteTextWidth += charWidth(t->textPtr[i]); - // copy markEnd part to markStart, and add null termination + // copy markEnd part to markStart, and add NUL-termination const int32_t length = (int32_t)strlen(&t->textPtr[end]); if (length > 0) memcpy(&t->textPtr[start], &t->textPtr[end], length); @@ -298,7 +298,7 @@ static void pasteText(textBox_t *t) if (endPart == NULL) { free(copiedText); - okBox(0, "System message", "Not enough memory!"); + okBox(0, "System message", "Not enough memory!", NULL); return; } } diff --git a/src/ft2_trim.c b/src/ft2_trim.c @@ -711,7 +711,7 @@ static int64_t calculateTrimSize(void) if (!setTmpInstruments()) { - okBox(0, "System message", "Not enough memory!"); + okBox(0, "System message", "Not enough memory!", NULL); return 0; } @@ -834,7 +834,7 @@ static int32_t SDLCALL trimThreadFunc(void *ptr) if (!setTmpInstruments()) { - okBoxThreadSafe(0, "System message", "Not enough memory!"); + okBoxThreadSafe(0, "System message", "Not enough memory!", NULL); return true; } @@ -1184,7 +1184,7 @@ void pbTrimDoTrim(void) if (!removePatt && !removeInst && !removeSamp && !removeChans && !removeSmpDataAfterLoop && !convSmpsTo8Bit) return; // nothing to trim... - if (okBox(2, "System request", "Are you sure you want to trim the song? Making a backup of the song first is recommended.") != 1) + if (okBox(2, "System request", "Are you sure you want to trim the song? Making a backup of the song first is recommended.", NULL) != 1) return; mouseAnimOn(); diff --git a/src/ft2_wav_renderer.c b/src/ft2_wav_renderer.c @@ -297,13 +297,14 @@ static bool dump_EndOfTune(int16_t endSongPos) void dump_TickReplayer(void) { replayerBusy = true; + if (!musicPaused) + { + if (audio.volumeRampingFlag) + resetRampVolumes(); - if (audio.volumeRampingFlag) - resetRampVolumes(); - - tickReplayer(); - updateVoices(); - + tickReplayer(); + updateVoices(); + } replayerBusy = false; } @@ -337,7 +338,7 @@ static int32_t SDLCALL renderWavThread(void *ptr) if (!dump_Init(WDFrequency, WDAmp, WDStartPos)) { resumeAudio(); - okBoxThreadSafe(0, "System message", "Not enough memory!"); + okBoxThreadSafe(0, "System message", "Not enough memory!", NULL); return true; } @@ -425,7 +426,7 @@ static int32_t SDLCALL renderWavThread(void *ptr) resumeAudio(); if (overflow) - okBoxThreadSafe(0, "System message", "Rendering stopped, file exceeded 2GB!"); + okBoxThreadSafe(0, "System message", "Rendering stopped, file exceeded 2GB!", NULL); editor.diskOpReadOnOpen = true; return true; @@ -445,14 +446,14 @@ static void wavRender(bool checkOverwrite) { char buf[256]; createFileOverwriteText(filename, buf); - if (okBox(2, "System request", buf) != 1) + if (okBox(2, "System request", buf, NULL) != 1) return; } editor.wavRendererFileHandle = fopen(filename, "wb"); if (editor.wavRendererFileHandle == NULL) { - okBox(0, "System message", "General I/O error while writing to WAV (is the file in use)?"); + okBox(0, "System message", "General I/O error while writing to WAV (is the file in use)?", NULL); return; } @@ -461,7 +462,7 @@ static void wavRender(bool checkOverwrite) if (thread == NULL) { fclose((FILE *)editor.wavRendererFileHandle); - okBox(0, "System message", "Couldn't create thread!"); + okBox(0, "System message", "Couldn't create thread!", NULL); return; } diff --git a/src/modloaders/ft2_load_s3m.c b/src/modloaders/ft2_load_s3m.c @@ -623,7 +623,7 @@ bool loadS3M(FILE *f, uint32_t filesize) loaderMsgBox("Warning: The module contains unsupported AdLib instruments!"); if (!(config.dontShowAgainFlags & DONT_SHOW_IMPORT_WARNING_FLAG)) - loaderSysReq(6, "System message", "Loading of this format is not fully supported and can have issues."); + loaderSysReq(0, "System message", "Loading of this format is not fully supported and can have issues.", configToggleImportWarning); return true; } diff --git a/src/smploaders/ft2_load_aiff.c b/src/smploaders/ft2_load_aiff.c @@ -149,7 +149,7 @@ bool loadAIFF(FILE *f, uint32_t filesize) int16_t stereoSampleLoadMode = -1; if (aiffIsStereo(f)) - stereoSampleLoadMode = loaderSysReq(5, "System request", "This is a stereo sample..."); + stereoSampleLoadMode = loaderSysReq(4, "System request", "This is a stereo sample...", NULL); // read sample data diff --git a/src/smploaders/ft2_load_flac.c b/src/smploaders/ft2_load_flac.c @@ -208,7 +208,7 @@ static void metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__St stereoSampleLoadMode = -1; if (numChannels == 2) - stereoSampleLoadMode = loaderSysReq(5, "System request", "This is a stereo sample..."); + stereoSampleLoadMode = loaderSysReq(4, "System request", "This is a stereo sample...", NULL); } // check for RIFF chunks (loop/vol/pan information) @@ -338,7 +338,7 @@ static FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder * { if (!allocateSmpData(s, sampleLength, sample16Bit)) { - loaderMsgBox("Error loading sample: Out of memory!"); + loaderMsgBox("Error loading sample: Not enough memory!"); return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; } diff --git a/src/smploaders/ft2_load_raw.c b/src/smploaders/ft2_load_raw.c @@ -23,7 +23,7 @@ bool loadRAW(FILE *f, uint32_t filesize) if (fread(s->dataPtr, filesize, 1, f) != 1) { - okBoxThreadSafe(0, "System message", "General I/O error during loading! Is the file in use?"); + okBoxThreadSafe(0, "System message", "General I/O error during loading! Is the file in use?", NULL); return false; } diff --git a/src/smploaders/ft2_load_wav.c b/src/smploaders/ft2_load_wav.c @@ -180,7 +180,7 @@ bool loadWAV(FILE *f, uint32_t filesize) int16_t stereoSampleLoadMode = -1; if (wavIsStereo(f)) - stereoSampleLoadMode = loaderSysReq(5, "System request", "This is a stereo sample..."); + stereoSampleLoadMode = loaderSysReq(4, "System request", "This is a stereo sample...", NULL); if (bitsPerSample == 8) // 8-BIT INTEGER SAMPLE {