ref: ba9a38b8266fd42f2bc327b7e6e60866812cbb92
dir: /src/pt2_mouse.c/
// for finding memory leaks in debug mode with Visual Studio #if defined _DEBUG && defined _MSC_VER #include <crtdbg.h> #endif #include <stdint.h> #include <stdbool.h> #ifndef _WIN32 #include <unistd.h> #endif #include <stdio.h> #include "pt2_helpers.h" #include "pt2_diskop.h" #include "pt2_sampler.h" #include "pt2_module_saver.h" #include "pt2_edit.h" #include "pt2_sample_saver.h" #include "pt2_visuals.h" #include "pt2_tables.h" #include "pt2_audio.h" #include "pt2_textout.h" #include "pt2_keyboard.h" #include "pt2_config.h" #include "pt2_bmp.h" #include "pt2_sampling.h" #include "pt2_chordmaker.h" #include "pt2_pat2smp.h" #include "pt2_mod2wav.h" #include "pt2_askbox.h" #include "pt2_replayer.h" SDL_Cursor *cursors[NUM_CURSORS]; // globalized static int32_t checkGUIButtons(void); static void handleTextEditing(uint8_t mouseButton); static bool handleRightMouseButton(void); static bool handleLeftMouseButton(void); static bool handleGUIButtons(int32_t button); static void handleRepeatedGUIButtons(void); static void handleRepeatedSamplerFilterButtons(void); void sampleUpButton(void) { if (editor.sampleZero) { editor.sampleZero = false; editor.currSample = 0; } else if (editor.currSample < 30) { editor.currSample++; } updateCurrSample(); } void sampleDownButton(void) { if (!editor.sampleZero && editor.currSample > 0) { editor.currSample--; updateCurrSample(); } } static void pointerSetColor(uint8_t cursorColorIndex) { assert(cursorColorIndex <= 5); video.palette[PAL_MOUSE_1] = cursorColors[cursorColorIndex][0]; video.palette[PAL_MOUSE_2] = cursorColors[cursorColorIndex][1]; video.palette[PAL_MOUSE_3] = cursorColors[cursorColorIndex][2]; if (config.hwMouse) setSystemCursor(cursors[cursorColorIndex]); } void updatePointerColor(void) { switch (ui.pointerMode) { case POINTER_MODE_IDLE: pointerSetColor(POINTER_GRAY); break; case POINTER_MODE_PLAY: pointerSetColor(POINTER_YELLOW); break; case POINTER_MODE_EDIT: pointerSetColor(POINTER_BLUE); break; case POINTER_MODE_RECORD: pointerSetColor(POINTER_BLUE); break; case POINTER_MODE_MSG1: pointerSetColor(POINTER_PURPLE); break; case POINTER_MODE_MSG2: pointerSetColor(POINTER_GREEN); break; default: break; } } void pointerSetMode(uint8_t pointerMode, bool carry) { assert(pointerMode <= 5); ui.pointerMode = pointerMode; if (carry) ui.previousPointerMode = ui.pointerMode; updatePointerColor(); } void pointerSetModeThreadSafe(uint8_t pointerMode, bool carry) { assert(pointerMode <= 5); ui.pointerMode = pointerMode; if (carry) ui.previousPointerMode = ui.pointerMode; // in hardware mouse mode, the pointer color can only be changed from the main thread if (config.hwMouse) mouse.updatePointerColorFlag = true; else updatePointerColor(); } void pointerSetPreviousMode(void) { if (ui.editTextFlag || ui.askBoxShown) pointerSetMode(POINTER_MODE_MSG1, NO_CARRY); else pointerSetMode(ui.previousPointerMode, NO_CARRY); } void setMsgPointer(void) { pointerSetMode(POINTER_MODE_MSG2, false); } void setErrPointer(void) { pointerSetColor(POINTER_RED); } bool setSystemCursor(SDL_Cursor *cur) { if (cur == NULL) { SDL_SetCursor(SDL_GetDefaultCursor()); return false; } SDL_SetCursor(cur); return true; } void freeMouseCursors(void) { SDL_SetCursor(SDL_GetDefaultCursor()); for (uint32_t i = 0; i < NUM_CURSORS; i++) { if (cursors[i] != NULL) { SDL_FreeCursor(cursors[i]); cursors[i] = NULL; } } } bool createMouseCursors(void) // creates scaled SDL surfaces for current mouse pointer shape { freeMouseCursors(); const uint32_t scaleFactor = video.yScale; for (uint32_t i = 0; i < NUM_CURSORS; i++) { SDL_Surface *surface = SDL_CreateRGBSurface(0, POINTER_W*scaleFactor, POINTER_H*scaleFactor, 32, 0, 0, 0, 0); if (surface == NULL) { freeMouseCursors(); config.hwMouse = false; // enable software mouse return false; } uint32_t color1 = cursorColors[i][0]; uint32_t color2 = cursorColors[i][1]; uint32_t color3 = cursorColors[i][2]; uint32_t colorkey = 0x12345678; color1 = SDL_MapRGB(surface->format, R24(color1), G24(color1), B24(color1)); color2 = SDL_MapRGB(surface->format, R24(color2), G24(color2), B24(color2)); color3 = SDL_MapRGB(surface->format, R24(color3), G24(color3), B24(color3)); colorkey = SDL_MapRGB(surface->format, R24(colorkey), G24(colorkey), B24(colorkey)); SDL_SetSurfaceBlendMode(surface, SDL_BLENDMODE_NONE); SDL_SetColorKey(surface, SDL_TRUE, colorkey); SDL_SetSurfaceRLE(surface, SDL_TRUE); const uint8_t *srcPixels8 = mousePointerBMP; SDL_LockSurface(surface); uint32_t *dstPixels32 = (uint32_t *)surface->pixels; for (int32_t k = 0; k < surface->w*surface->h; k++) // fill surface with colorkey pixels dstPixels32[k] = colorkey; // blit upscaled cursor to surface for (uint32_t y = 0; y < POINTER_H; y++) { uint32_t *outX = &dstPixels32[(y * scaleFactor) * surface->w]; for (uint32_t yScale = 0; yScale < scaleFactor; yScale++) { for (uint32_t x = 0; x < POINTER_W; x++) { uint8_t srcPix = srcPixels8[(y * POINTER_W) + x]; if (srcPix != PAL_COLORKEY) { uint32_t pixel = colorkey; // make compiler happy if (srcPix == PAL_MOUSE_1) pixel = color1; else if (srcPix == PAL_MOUSE_2) pixel = color2; else if (srcPix == PAL_MOUSE_3) pixel = color3; for (uint32_t xScale = 0; xScale < scaleFactor; xScale++) outX[xScale] = pixel; } outX += scaleFactor; } } } SDL_UnlockSurface(surface); cursors[i] = SDL_CreateColorCursor(surface, 0, 0); if (cursors[i] == NULL) { SDL_FreeSurface(surface); freeMouseCursors(); config.hwMouse = false; // enable software mouse return false; } SDL_FreeSurface(surface); } pointerSetPreviousMode(); // this sets the appropriate the hardware cursor return true; } void updateMouseScaling(void) { if (video.renderW > 0) video.fMouseXMul = (float)SCREEN_W / video.renderW; if (video.renderH > 0) video.fMouseYMul = (float)SCREEN_H / video.renderH; } void readMouseXY(void) { int32_t mx, my, windowX, windowY; if (mouse.updatePointerColorFlag) // used when changing pointer color from other threads { mouse.updatePointerColorFlag = false; updatePointerColor(); } if (mouse.setPosFlag) { if (!video.windowHidden) SDL_WarpMouseInWindow(video.window, mouse.setPosX, mouse.setPosY); mouse.setPosFlag = false; return; } if (video.useDesktopMouseCoords) { mouse.buttonState = SDL_GetGlobalMouseState(&mx, &my); // convert desktop coords to window coords SDL_GetWindowPosition(video.window, &windowX, &windowY); mx -= windowX; my -= windowY; } else { // special mode for KMSDRM (XXX: Confirm that this still works...) mouse.buttonState = SDL_GetMouseState(&mx, &my); } mouse.rawX = mx; mouse.rawY = my; if (video.fullscreen) { // centered fullscreen mode (not stretched) needs further coord translation if (!config.fullScreenStretch) { // if software mouse is enabled, warp mouse inside render space if (!config.hwMouse) { bool warpMouse = false; if (mx < video.renderX) { mx = video.renderX; warpMouse = true; } else if (mx >= video.renderX+video.renderW) { mx = (video.renderX + video.renderW) - 1; warpMouse = true; } if (my < video.renderY) { my = video.renderY; warpMouse = true; } else if (my >= video.renderY+video.renderH) { my = (video.renderY + video.renderH) - 1; warpMouse = true; } if (warpMouse) SDL_WarpMouseInWindow(video.window, mx, my); } // convert fullscreen coords to window (centered image) coords mx -= video.renderX; my -= video.renderY; } } // multiply coords by video upscaling factors (don't round) mouse.x = (int32_t)(mx * video.fMouseXMul); mouse.y = (int32_t)(my * video.fMouseYMul); if (config.hwMouse) { // hardware mouse mode (OS) hideSprite(SPRITE_MOUSE_POINTER); } else { // software mouse mode (PT mouse) setSpritePos(SPRITE_MOUSE_POINTER, mouse.x, mouse.y); } } void mouseButtonUpHandler(uint8_t mouseButton) { mouse.buttonWaitCounter = 0; mouse.buttonWaiting = false; if (mouseButton == SDL_BUTTON_LEFT) { mouse.leftButtonPressed = false; ui.forceSampleDrag = false; ui.forceVolDrag = false; ui.leftLoopPinMoving = false; ui.rightLoopPinMoving = false; ui.sampleMarkingPos = -1; switch (mouse.lastGUIButton) { case PTB_SLENGTHU: case PTB_SLENGTHD: { if (ui.samplerScreenShown) redrawSample(); recalcChordLength(); updateSamplePos(); ui.updateSongSize = true; } break; case PTB_LENGTHU: case PTB_LENGTHD: case PTB_PATTERNU: case PTB_PATTERND: { ui.updateSongSize = true; if (ui.posEdScreenShown) ui.updatePosEd = true; } break; default: break; } mouse.lastGUIButton = -1; mouse.lastSmpFilterButton = -1; mouse.lastSamplingButton = -1; } if (mouseButton == SDL_BUTTON_RIGHT) { mouse.rightButtonPressed = false; ui.forceSampleEdit = false; } } void mouseButtonDownHandler(uint8_t mouseButton) { if (mouseButton == SDL_BUTTON_LEFT) { mouse.leftButtonPressed = true; mouse.buttonWaiting = true; } if (mouseButton == SDL_BUTTON_RIGHT) mouse.rightButtonPressed = true; // when red mouse pointer (error), block further input for a while if (editor.errorMsgActive && editor.errorMsgBlock) return; if (handleRightMouseButton() || handleLeftMouseButton()) return; handleTextEditing(mouseButton); } void handleGUIButtonRepeat(void) { if (!mouse.leftButtonPressed) { // left mouse button released, stop repeating buttons mouse.repeatCounter = 0; return; } if (ui.samplerFiltersBoxShown) { handleRepeatedSamplerFilterButtons(); return; } if (ui.samplingBoxShown) { handleRepeatedSamplingButtons(); return; } if (mouse.lastGUIButton != checkGUIButtons()) // FIXME: This can potentially do a ton of iterations, bad design! { // only repeat the button that was first clicked (e.g. if you hold and move mouse to another button) mouse.repeatCounter = 0; return; } handleRepeatedGUIButtons(); mouse.repeatCounter++; } static void edNote1UpButton(void) { if (mouse.rightButtonPressed) editor.note1 += 12; else editor.note1++; if (editor.note1 > 36) editor.note1 = 36; ui.updateChordNote1Text = true; recalcChordLength(); } static void edNote1DownButton(void) { if (mouse.rightButtonPressed) editor.note1 -= 12; else editor.note1--; if (editor.note1 < 0) editor.note1 = 0; ui.updateChordNote1Text = true; recalcChordLength(); } static void edNote2UpButton(void) { if (mouse.rightButtonPressed) editor.note2 += 12; else editor.note2++; if (editor.note2 > 36) editor.note2 = 36; ui.updateChordNote2Text = true; recalcChordLength(); } static void edNote2DownButton(void) { if (mouse.rightButtonPressed) editor.note2 -= 12; else editor.note2--; if (editor.note2 < 0) editor.note2 = 0; ui.updateChordNote2Text = true; recalcChordLength(); } static void edNote3UpButton(void) { if (mouse.rightButtonPressed) editor.note3 += 12; else editor.note3++; if (editor.note3 > 36) editor.note3 = 36; ui.updateChordNote3Text = true; recalcChordLength(); } static void edNote3DownButton(void) { if (mouse.rightButtonPressed) editor.note3 -= 12; else editor.note3--; if (editor.note3 < 0) editor.note3 = 0; ui.updateChordNote3Text = true; recalcChordLength(); } static void edNote4UpButton(void) { if (mouse.rightButtonPressed) editor.note4 += 12; else editor.note4++; if (editor.note4 > 36) editor.note4 = 36; ui.updateChordNote4Text = true; recalcChordLength(); } static void edNote4DownButton(void) { if (mouse.rightButtonPressed) editor.note4 -= 12; else editor.note4--; if (editor.note4 < 0) editor.note4 = 0; ui.updateChordNote4Text = true; recalcChordLength(); } static void edPosUpButton(bool fast) { if (mouse.rightButtonPressed) { if (fast) { if (editor.samplePos <= config.maxSampleLength-64) editor.samplePos += 64; else editor.samplePos = config.maxSampleLength; } else { if (editor.samplePos <= config.maxSampleLength-16) editor.samplePos += 16; else editor.samplePos = config.maxSampleLength; } } else { if (fast) { if (editor.samplePos <= config.maxSampleLength-64) editor.samplePos += 64; else editor.samplePos = config.maxSampleLength; } else { if (editor.samplePos < config.maxSampleLength) editor.samplePos++; else editor.samplePos = config.maxSampleLength; } } if (editor.samplePos > song->samples[editor.currSample].length) editor.samplePos = song->samples[editor.currSample].length; ui.updatePosText = true; } static void edPosDownButton(bool fast) { if (mouse.rightButtonPressed) { if (fast) { if (editor.samplePos > 64) editor.samplePos -= 64; else editor.samplePos = 0; } else { if (editor.samplePos > 16) editor.samplePos -= 16; else editor.samplePos = 0; } } else { if (fast) { if (editor.samplePos > 64) editor.samplePos -= 64; else editor.samplePos = 0; } else { if (editor.samplePos > 0) editor.samplePos--; else editor.samplePos = 0; } } ui.updatePosText = true; } static void edModUpButton(void) { if (mouse.rightButtonPressed) editor.modulateSpeed += 10; else editor.modulateSpeed++; if (editor.modulateSpeed > 127) editor.modulateSpeed = 127; ui.updateModText = true; } static void edModDownButton(void) { if (mouse.rightButtonPressed) { editor.modulateSpeed -= 10; } else { editor.modulateSpeed--; } if (editor.modulateSpeed < -128) editor.modulateSpeed = -128; ui.updateModText = true; } static void edVolUpButton(void) { if (mouse.rightButtonPressed) { if (editor.sampleVol <= 999-10) editor.sampleVol += 10; else editor.sampleVol = 999; } else { if (editor.sampleVol < 999) editor.sampleVol++; } ui.updateVolText = true; } static void edVolDownButton(void) { if (mouse.rightButtonPressed) { if (editor.sampleVol >= 10) editor.sampleVol -= 10; else editor.sampleVol = 0; } else { if (editor.sampleVol > 0) editor.sampleVol--; } ui.updateVolText = true; } static void sampleFineTuneUpButton(void) { int8_t finetune = song->samples[editor.currSample].fineTune & 0xF; if (finetune != 7) song->samples[editor.currSample].fineTune = (finetune + 1) & 0xF; if (mouse.rightButtonPressed) song->samples[editor.currSample].fineTune = 0; recalcChordLength(); ui.updateCurrSampleFineTune = true; } static void sampleFineTuneDownButton(void) { int8_t finetune = song->samples[editor.currSample].fineTune & 0xF; if (finetune != 8) song->samples[editor.currSample].fineTune = (finetune - 1) & 0xF; if (mouse.rightButtonPressed) song->samples[editor.currSample].fineTune = 0; recalcChordLength(); ui.updateCurrSampleFineTune = true; } static void sampleVolumeUpButton(void) { int8_t val = song->samples[editor.currSample].volume; if (mouse.rightButtonPressed) val += 16; else val++; if (val > 64) val = 64; song->samples[editor.currSample].volume = (uint8_t)val; ui.updateCurrSampleVolume = true; } static void sampleVolumeDownButton(void) { int8_t val = song->samples[editor.currSample].volume; if (mouse.rightButtonPressed) val -= 16; else val--; if (val < 0) val = 0; song->samples[editor.currSample].volume = (uint8_t)val; ui.updateCurrSampleVolume = true; } static void sampleLengthUpButton(bool fast) { if (song->samples[editor.currSample].length == config.maxSampleLength) return; int32_t val = song->samples[editor.currSample].length; if (mouse.rightButtonPressed) { if (fast) val += 64; else val += 16; } else { if (fast) val += 10; else val += 2; } if (val > config.maxSampleLength) val = config.maxSampleLength; song->samples[editor.currSample].length = val; ui.updateCurrSampleLength = true; } static void sampleLengthDownButton(bool fast) { moduleSample_t *s = &song->samples[editor.currSample]; if (s->loopStart+s->loopLength > 2) { if (s->length == s->loopStart+s->loopLength) return; } else { if (s->length == 0) return; } int32_t val = song->samples[editor.currSample].length; if (mouse.rightButtonPressed) { if (fast) val -= 64; else val -= 16; } else { if (fast) val -= 10; else val -= 2; } if (val < 0) val = 0; if (s->loopStart+s->loopLength > 2) { if (val < s->loopStart+s->loopLength) val = s->loopStart+s->loopLength; } s->length = val; ui.updateCurrSampleLength = true; } static void sampleRepeatUpButton(bool fast) { int32_t val = song->samples[editor.currSample].loopStart; int32_t loopLen = song->samples[editor.currSample].loopLength; int32_t len = song->samples[editor.currSample].length; if (len == 0) { song->samples[editor.currSample].loopStart = 0; return; } if (mouse.rightButtonPressed) { if (fast) val += 64; else val += 16; } else { if (fast) val += 10; else val += 2; } if (val > len-loopLen) val = len-loopLen; song->samples[editor.currSample].loopStart = val; ui.updateCurrSampleRepeat = true; updatePaulaLoops(); if (ui.samplerScreenShown) setLoopSprites(); if (ui.editOpScreenShown && ui.editOpScreen == 3) // sample chord editor ui.updateChordLengthText = true; } static void sampleRepeatDownButton(bool fast) { int32_t val = song->samples[editor.currSample].loopStart; int32_t len = song->samples[editor.currSample].length; if (len == 0) { song->samples[editor.currSample].loopStart = 0; return; } if (mouse.rightButtonPressed) { if (fast) val -= 64; else val -= 16; } else { if (fast) val -= 10; else val -= 2; } if (val < 0) val = 0; song->samples[editor.currSample].loopStart = val; ui.updateCurrSampleRepeat = true; updatePaulaLoops(); if (ui.samplerScreenShown) setLoopSprites(); if (ui.editOpScreenShown && ui.editOpScreen == 3) // sample chord editor ui.updateChordLengthText = true; } static void sampleRepeatLengthUpButton(bool fast) { int32_t val = song->samples[editor.currSample].loopLength; int32_t loopStart = song->samples[editor.currSample].loopStart; int32_t len = song->samples[editor.currSample].length; if (len == 0) { song->samples[editor.currSample].loopLength = 2; return; } if (mouse.rightButtonPressed) { if (fast) val += 64; else val += 16; } else { if (fast) val += 10; else val += 2; } if (val > len-loopStart) val = len-loopStart; song->samples[editor.currSample].loopLength = val; ui.updateCurrSampleReplen = true; updatePaulaLoops(); if (ui.samplerScreenShown) setLoopSprites(); if (ui.editOpScreenShown && ui.editOpScreen == 3) // sample chord editor ui.updateChordLengthText = true; } static void sampleRepeatLengthDownButton(bool fast) { int32_t val = song->samples[editor.currSample].loopLength; int32_t len = song->samples[editor.currSample].length; if (len == 0) { song->samples[editor.currSample].loopLength = 2; return; } if (mouse.rightButtonPressed) { if (fast) val -= 64; else val -= 16; } else { if (fast) val -= 10; else val -= 2; } if (val < 2) val = 2; song->samples[editor.currSample].loopLength = val; ui.updateCurrSampleReplen = true; updatePaulaLoops(); if (ui.samplerScreenShown) setLoopSprites(); if (ui.editOpScreenShown && ui.editOpScreen == 3) // sample chord editor ui.updateChordLengthText = true; } static void tempoUpButton(void) { if (editor.timingMode == TEMPO_MODE_VBLANK) return; int32_t val = song->currBPM; if (mouse.rightButtonPressed) val += 10; else val++; if (val > 255) val = 255; song->currBPM = val; modSetTempo(song->currBPM, true); ui.updateSongBPM = true; } static void tempoDownButton(void) { if (editor.timingMode == TEMPO_MODE_VBLANK) return; int32_t val = song->currBPM; if (mouse.rightButtonPressed) val -= 10; else val--; if (val < 32) val = 32; song->currBPM = val; modSetTempo(song->currBPM, true); ui.updateSongBPM = true; } static void songLengthUpButton(void) { int16_t val = song->header.numOrders; if (mouse.rightButtonPressed) val += 10; else val++; if (val > 128) val = 128; song->header.numOrders = (uint8_t)val; val = song->currOrder; if (val > song->header.numOrders-1) val = song->header.numOrders-1; editor.currPosEdPattDisp = &song->header.order[val]; ui.updateSongLength = true; } static void songLengthDownButton(void) { int16_t val = song->header.numOrders; if (mouse.rightButtonPressed) val -= 10; else val--; if (val < 1) val = 1; song->header.numOrders = (uint8_t)val; val = song->currOrder; if (val > song->header.numOrders-1) val = song->header.numOrders-1; editor.currPosEdPattDisp = &song->header.order[val]; ui.updateSongLength = true; } static void patternUpButton(void) { int16_t val = song->header.order[song->currOrder]; if (mouse.rightButtonPressed) val += 10; else val++; if (val > MAX_PATTERNS-1) val = MAX_PATTERNS-1; song->header.order[song->currOrder] = (uint8_t)val; if (ui.posEdScreenShown) ui.updatePosEd = true; ui.updateSongPattern = true; } static void patternDownButton(void) { int16_t val = song->header.order[song->currOrder]; if (mouse.rightButtonPressed) val -= 10; else val--; if (val < 0) val = 0; song->header.order[song->currOrder] = (uint8_t)val; if (ui.posEdScreenShown) ui.updatePosEd = true; ui.updateSongPattern = true; } static void positionUpButton(void) { int16_t val = song->currOrder; if (mouse.rightButtonPressed) val += 10; else val++; if (val > 127) val = 127; modSetPos(val, DONT_SET_ROW); } static void positionDownButton(void) { int16_t val = song->currOrder; if (mouse.rightButtonPressed) val -= 10; else val--; if (val < 0) val = 0; modSetPos(val, DONT_SET_ROW); } static void handleSamplerVolumeBox(void) { if (mouse.rightButtonPressed) { if (ui.editTextFlag) { exitGetTextLine(EDIT_TEXT_NO_UPDATE); } else { ui.samplerVolBoxShown = false; removeSamplerVolBox(); } return; } if (ui.editTextFlag) return; // check buttons if (mouse.leftButtonPressed) { // MAIN SCREEN STOP if (!ui.diskOpScreenShown && !ui.posEdScreenShown) { if (mouse.x >= 182 && mouse.x <= 243 && mouse.y >= 0 && mouse.y <= 10) { modStop(); return; } } if (mouse.x >= 32 && mouse.x <= 95) { // SAMPLER SCREEN PLAY WAVEFORM if (mouse.y >= 211 && mouse.y <= 221) { samplerPlayWaveform(); return; } // SAMPLER SCREEN PLAY DISPLAY else if (mouse.y >= 222 && mouse.y <= 232) { samplerPlayDisplay(); return; } // SAMPLER SCREEN PLAY RANGE else if (mouse.y >= 233 && mouse.y <= 243) { samplerPlayRange(); return; } } // SAMPLER SCREEN STOP if (mouse.x >= 0 && mouse.x <= 31 && mouse.y >= 222 && mouse.y <= 243) { turnOffVoices(); return; } // VOLUME button (toggle) if (mouse.x >= 96 && mouse.x <= 135 && mouse.y >= 244 && mouse.y <= 254) { ui.samplerVolBoxShown = false; removeSamplerVolBox(); return; } // DRAG BOXES if (mouse.x >= 72 && mouse.x <= 173 && mouse.y >= 154 && mouse.y <= 175) { volBoxBarPressed(MOUSE_BUTTON_NOT_HELD); return; } if (mouse.x >= 174 && mouse.x <= 207) { // FROM NUM if (mouse.y >= 154 && mouse.y <= 164) { ui.tmpDisp16 = editor.vol1; editor.vol1Disp = &ui.tmpDisp16; ui.numPtr16 = &ui.tmpDisp16; ui.numLen = 3; ui.editTextPos = 6342; // (y * 40) + x getNumLine(TEXT_EDIT_DECIMAL, PTB_SA_VOL_FROM_NUM); return; } // TO NUM else if (mouse.y >= 165 && mouse.y <= 175) { ui.tmpDisp16 = editor.vol2; editor.vol2Disp = &ui.tmpDisp16; ui.numPtr16 = &ui.tmpDisp16; ui.numLen = 3; ui.editTextPos = 6782; // (y * 40) + x getNumLine(TEXT_EDIT_DECIMAL, PTB_SA_VOL_TO_NUM); return; } } if (mouse.y >= 176 && mouse.y <= 186) { // NORMALIZE if (mouse.x >= 101 && mouse.x <= 143) { int32_t sampleLength; if (editor.sampleZero) { statusNotSampleZero(); return; } moduleSample_t *s = &song->samples[editor.currSample]; if (s->length == 0) { statusSampleIsEmpty(); return; } int8_t *sampleData = &song->sampleData[s->offset]; if (editor.markStartOfs != -1) { sampleData += editor.markStartOfs; sampleLength = editor.markEndOfs - editor.markStartOfs; } else { sampleLength = s->length; } int16_t sampleVol = 0; int32_t sampleIndex = 0; while (sampleIndex < sampleLength) { int16_t sample = *sampleData++; sample = ABS(sample); if (sampleVol < sample) sampleVol = sample; sampleIndex++; } if (sampleVol <= 0 || sampleVol > 127) { editor.vol1 = 100; editor.vol2 = 100; } else if (sampleVol < 64) { editor.vol1 = 200; editor.vol2 = 200; } else { editor.vol1 = (uint16_t)((100 * 127) / sampleVol); editor.vol2 = (uint16_t)((100 * 127) / sampleVol); } ui.updateVolFromText = true; ui.updateVolToText = true; showVolFromSlider(); showVolToSlider(); return; } // RAMP DOWN else if (mouse.x >= 144 && mouse.x <= 153) { editor.vol1 = 100; editor.vol2 = 0; ui.updateVolFromText = true; ui.updateVolToText = true; showVolFromSlider(); showVolToSlider(); return; } // RAMP UP else if (mouse.x >= 154 && mouse.x <= 163) { editor.vol1 = 0; editor.vol2 = 100; ui.updateVolFromText = true; ui.updateVolToText = true; showVolFromSlider(); showVolToSlider(); return; } // RAMP UNITY else if (mouse.x >= 164 && mouse.x <= 173) { editor.vol1 = 100; editor.vol2 = 100; ui.updateVolFromText = true; ui.updateVolToText = true; showVolFromSlider(); showVolToSlider(); return; } // CANCEL else if (mouse.x >= 174 && mouse.x <= 207) { ui.samplerVolBoxShown = false; removeSamplerVolBox(); return; } // RAMP else if (mouse.x >= 72 && mouse.x <= 100) { int32_t sampleLength; if (editor.sampleZero) { statusNotSampleZero(); return; } moduleSample_t *s = &song->samples[editor.currSample]; if (s->length == 0) { statusSampleIsEmpty(); return; } if (editor.vol1 == 100 && editor.vol2 == 100) { ui.samplerVolBoxShown = false; removeSamplerVolBox(); return; } int8_t *sampleData = &song->sampleData[s->offset]; if (editor.markStartOfs != -1 && editor.markEndOfs-editor.markStartOfs >= 1) { sampleData += editor.markStartOfs; sampleLength = editor.markEndOfs - editor.markStartOfs; } else { sampleLength = s->length; } if (sampleLength > 0) { double dSampleLengthMul = 1.0 / sampleLength; int32_t sampleIndex = 0; while (sampleIndex < sampleLength) { double dSmp = (sampleIndex * editor.vol2) * dSampleLengthMul; dSmp += ((sampleLength - sampleIndex) * editor.vol1) * dSampleLengthMul; dSmp *= *sampleData; dSmp *= (1.0 / 100.0); int32_t smp32 = (int32_t)dSmp; CLAMP8(smp32); *sampleData++ = (int8_t)smp32; sampleIndex++; } } fixSampleBeep(s); ui.samplerVolBoxShown = false; removeSamplerVolBox(); updateWindowTitle(MOD_IS_MODIFIED); } } } } static void handleRepeatedSamplerFilterButtons(void) { if (!mouse.leftButtonPressed || mouse.lastSmpFilterButton == -1) return; switch (mouse.lastSmpFilterButton) { case 0: // low-pass cutoff up { if (mouse.rightButtonPressed) { if (editor.lpCutOff <= 0xFFFF-50) editor.lpCutOff += 50; else editor.lpCutOff = 0xFFFF; } else { if (editor.lpCutOff < 0xFFFF) editor.lpCutOff++; else editor.lpCutOff = 0xFFFF; } if (editor.lpCutOff > (uint16_t)(FILTERS_BASE_FREQ/2)) editor.lpCutOff = (uint16_t)(FILTERS_BASE_FREQ/2); ui.updateLPText = true; } break; case 1: // low-pass cutoff down { if (mouse.rightButtonPressed) { if (editor.lpCutOff >= 50) editor.lpCutOff -= 50; else editor.lpCutOff = 0; } else { if (editor.lpCutOff > 0) editor.lpCutOff--; else editor.lpCutOff = 0; } ui.updateLPText = true; } break; case 2: // high-pass cutoff up { if (mouse.rightButtonPressed) { if (editor.hpCutOff <= 0xFFFF-50) editor.hpCutOff += 50; else editor.hpCutOff = 0xFFFF; } else { if (editor.hpCutOff < 0xFFFF) editor.hpCutOff++; else editor.hpCutOff = 0xFFFF; } if (editor.hpCutOff > (uint16_t)(FILTERS_BASE_FREQ/2)) editor.hpCutOff = (uint16_t)(FILTERS_BASE_FREQ/2); ui.updateHPText = true; } break; case 3: // high-pass cutoff down { if (mouse.rightButtonPressed) { if (editor.hpCutOff >= 50) editor.hpCutOff -= 50; else editor.hpCutOff = 0; } else { if (editor.hpCutOff > 0) editor.hpCutOff--; else editor.hpCutOff = 0; } ui.updateHPText = true; } break; default: break; } } static void handleSamplerFiltersBox(void) { if (mouse.rightButtonPressed && ui.editTextFlag) { exitGetTextLine(EDIT_TEXT_NO_UPDATE); return; } if (ui.editTextFlag || mouse.lastSmpFilterButton > -1 || !mouse.leftButtonPressed) return; // FILTERS button (toggle) if (mouse.x >= 211 && mouse.x <= 245 && mouse.y >= 244 && mouse.y <= 254) { ui.samplerFiltersBoxShown = false; removeSamplerFiltersBox(); return; } // MAIN SCREEN STOP if (!ui.diskOpScreenShown && !ui.posEdScreenShown) { if (mouse.x >= 182 && mouse.x <= 243 && mouse.y >= 0 && mouse.y <= 10) { modStop(); return; } } if (mouse.x >= 32 && mouse.x <= 95) { // SAMPLER SCREEN PLAY WAVEFORM if (mouse.y >= 211 && mouse.y <= 221) { samplerPlayWaveform(); return; } // SAMPLER SCREEN PLAY DISPLAY else if (mouse.y >= 222 && mouse.y <= 232) { samplerPlayDisplay(); return; } // SAMPLER SCREEN PLAY RANGE else if (mouse.y >= 233 && mouse.y <= 243) { samplerPlayRange(); return; } } // SAMPLER SCREEN STOP if (mouse.x >= 0 && mouse.x <= 31 && mouse.y >= 222 && mouse.y <= 243) { turnOffVoices(); return; } // UNDO if (mouse.x >= 65 && mouse.x <= 75 && mouse.y >= 154 && mouse.y <= 184) { if (editor.sampleZero) { statusNotSampleZero(); return; } moduleSample_t *s = &song->samples[editor.currSample]; if (s->length == 0) { statusSampleIsEmpty(); } else { memcpy(&song->sampleData[s->offset], editor.tempSample, config.maxSampleLength); redrawSample(); updateWindowTitle(MOD_IS_MODIFIED); renderSamplerFiltersBox(); } return; } if (mouse.y >= 154 && mouse.y <= 164) { // DO LOW-PASS FILTER if (mouse.x >= 76 && mouse.x <= 165) { lowPassSample(editor.lpCutOff); renderSamplerFiltersBox(); return; } // LOW-PASS CUTOFF else if (mouse.x >= 166 && mouse.x <= 217) { if (mouse.rightButtonPressed) { editor.lpCutOff = 0; ui.updateLPText = true; } else { ui.tmpDisp16 = editor.lpCutOff; editor.lpCutOffDisp = &ui.tmpDisp16; ui.numPtr16 = &ui.tmpDisp16; ui.numLen = 4; ui.editTextPos = 6341; // (y * 40) + x getNumLine(TEXT_EDIT_DECIMAL, PTB_SA_FIL_LP_CUTOFF); } return; } // LOW-PASS CUTOFF UP else if (mouse.x >= 218 && mouse.x <= 228) { mouse.lastSmpFilterButton = 0; if (mouse.rightButtonPressed) { if (editor.lpCutOff <= 0xFFFF-100) editor.lpCutOff += 100; else editor.lpCutOff = 0xFFFF; } else { if (editor.lpCutOff < 0xFFFF) editor.lpCutOff++; else editor.lpCutOff = 0xFFFF; } if (editor.lpCutOff > (uint16_t)(FILTERS_BASE_FREQ/2)) editor.lpCutOff = (uint16_t)(FILTERS_BASE_FREQ/2); ui.updateLPText = true; return; } // LOW-PASS CUTOFF DOWN else if (mouse.x >= 229 && mouse.x <= 239) { mouse.lastSmpFilterButton = 1; if (mouse.rightButtonPressed) { if (editor.lpCutOff >= 100) editor.lpCutOff -= 100; else editor.lpCutOff = 0; } else { if (editor.lpCutOff > 0) editor.lpCutOff--; else editor.lpCutOff = 0; } ui.updateLPText = true; return; } } if (mouse.y >= 164 && mouse.y <= 174) { // DO HIGH-PASS FILTER if (mouse.x >= 76 && mouse.x <= 165) { highPassSample(editor.hpCutOff); renderSamplerFiltersBox(); return; } // HIGH-PASS CUTOFF else if (mouse.x >= 166 && mouse.x <= 217) { if (mouse.rightButtonPressed) { editor.hpCutOff = 0; ui.updateHPText = true; } else { ui.tmpDisp16 = editor.hpCutOff; editor.hpCutOffDisp = &ui.tmpDisp16; ui.numPtr16 = &ui.tmpDisp16; ui.numLen = 4; ui.editTextPos = 6781; // (y * 40) + x getNumLine(TEXT_EDIT_DECIMAL, PTB_SA_FIL_HP_CUTOFF); } return; } // HIGH-PASS CUTOFF UP else if (mouse.x >= 218 && mouse.x <= 228) { mouse.lastSmpFilterButton = 2; if (mouse.rightButtonPressed) { if (editor.hpCutOff <= 0xFFFF-100) editor.hpCutOff += 100; else editor.hpCutOff = 0xFFFF; } else { if (editor.hpCutOff < 0xFFFF) editor.hpCutOff++; else editor.hpCutOff = 0xFFFF; } if (editor.hpCutOff > (uint16_t)(FILTERS_BASE_FREQ/2)) editor.hpCutOff = (uint16_t)(FILTERS_BASE_FREQ/2); ui.updateHPText = true; return; } // HIGH-PASS CUTOFF DOWN else if (mouse.x >= 229 && mouse.x <= 239) { mouse.lastSmpFilterButton = 3; if (mouse.rightButtonPressed) { if (editor.hpCutOff >= 100) editor.hpCutOff -= 100; else editor.hpCutOff = 0; } else { if (editor.hpCutOff > 0) editor.hpCutOff--; else editor.hpCutOff = 0; } ui.updateHPText = true; return; } } // NORMALIZE SAMPLE FLAG if (mouse.x >= 76 && mouse.x <= 239 && mouse.y >= 174 && mouse.y <= 186) { editor.normalizeFiltersFlag ^= 1; ui.updateNormFlag = true; return; } // EXIT if (mouse.x >= 240 && mouse.x <= 250 && mouse.y >= 154 && mouse.y <= 186) { ui.samplerFiltersBoxShown = false; removeSamplerFiltersBox(); } } static bool withinButtonRect(const guiButton_t *b) { if (mouse.x >= b->x1 && mouse.x <= b->x2 && mouse.y >= b->y1 && mouse.y <= b->y2) return true; return false; } #define TEST_BUTTONS(bStruct, bNum) \ for (uint32_t i = 0; i < bNum; i++) \ if (withinButtonRect(&bStruct[i])) \ return bStruct[i].b; \ static int32_t checkGUIButtons(void) { // QUIT (xy 0,0) works on all screens except for ask/clear screen if (mouse.x == 0 && mouse.y == 0) return PTB_QUIT; // top screen buttons if (ui.diskOpScreenShown) { TEST_BUTTONS(bDiskOp, DISKOP_BUTTONS); } else { if (ui.posEdScreenShown) { TEST_BUTTONS(bPosEd, POSED_BUTTONS); } else if (ui.editOpScreenShown) { switch (ui.editOpScreen) { default: case 0: TEST_BUTTONS(bEditOp1, EDITOP1_BUTTONS); break; case 1: TEST_BUTTONS(bEditOp2, EDITOP2_BUTTONS); break; case 2: TEST_BUTTONS(bEditOp3, EDITOP3_BUTTONS); break; case 3: TEST_BUTTONS(bEditOp4, EDITOP4_BUTTONS); break; } } TEST_BUTTONS(bTopScreen, TOPSCREEN_BUTTONS); } // middle buttons (always present) TEST_BUTTONS(bMidScreen, MIDSCREEN_BUTTONS); // bottom screen buttons if (ui.samplerScreenShown) { TEST_BUTTONS(bSampler, SAMPLER_BUTTONS); } else { TEST_BUTTONS(bBotScreen, BOTSCREEN_BUTTONS); } return -1; } static void handleTextEditing(uint8_t mouseButton) { // handle mouse while editing text/numbers if (!ui.editTextFlag) return; if (ui.editTextType != TEXT_EDIT_STRING) { if (mouseButton == SDL_BUTTON_RIGHT) exitGetTextLine(EDIT_TEXT_NO_UPDATE); } else if (mouseButton == SDL_BUTTON_LEFT && !editor.mixFlag) { int32_t tmp32 = mouse.y - ui.lineCurY; if (tmp32 <= 2 && tmp32 >= -9) { tmp32 = (int32_t)((mouse.x - ui.lineCurX) + 4) >> 3; while (tmp32 != 0) // 0 = pos we want { if (tmp32 > 0) { if (ui.editPos < ui.textEndPtr && *ui.editPos != '\0') { ui.editPos++; textMarkerMoveRight(); } tmp32--; } else if (tmp32 < 0) { if (ui.editPos > ui.dstPtr) { ui.editPos--; textMarkerMoveLeft(); } tmp32++; } } } else { exitGetTextLine(EDIT_TEXT_UPDATE); } } else if (mouseButton == SDL_BUTTON_RIGHT) { if (editor.mixFlag) { exitGetTextLine(EDIT_TEXT_UPDATE); editor.mixFlag = false; ui.updateMixText = true; } else { char *tmpRead = ui.dstPtr; while (tmpRead < ui.textEndPtr) *tmpRead++ = '\0'; *ui.textEndPtr = '\0'; // don't exit text edit mode if the disk op. path was about to be deleted if (ui.editObject == PTB_DO_DATAPATH) { // move text cursor to pos 0 while (ui.editPos > ui.dstPtr) { ui.editPos--; textMarkerMoveLeft(); } ui.updateDiskOpPathText = true; } else { if (ui.editObject == PTB_SONGNAME) ui.updateSongName = true; else if (ui.editObject == PTB_SAMPLENAME) ui.updateCurrSampleName = true; exitGetTextLine(EDIT_TEXT_UPDATE); } } } } void mouseWheelUpHandler(void) { if (ui.editTextFlag || ui.askBoxShown || editor.swapChannelFlag || ui.samplingBoxShown || ui.samplerVolBoxShown || ui.samplerFiltersBoxShown) return; if (mouse.y < 121) { // upper part of screen if (ui.diskOpScreenShown) { if (diskop.scrollOffset > 0) { diskop.scrollOffset--; ui.updateDiskOpFileList = true; } } else if (ui.posEdScreenShown && song->currOrder > 0) { modSetPos(song->currOrder - 1, DONT_SET_ROW); } } else if (ui.samplerScreenShown) // lower part of screen { samplerZoomInMouseWheel(); } else if (!editor.songPlaying && song->currRow > 0) { modSetPos(DONT_SET_ORDER, song->currRow - 1); // pattern data } } void mouseWheelDownHandler(void) { if (ui.editTextFlag || ui.askBoxShown || editor.swapChannelFlag || ui.samplingBoxShown || ui.samplerVolBoxShown || ui.samplerFiltersBoxShown) return; if (mouse.y < 121) { // upper part of screen if (ui.diskOpScreenShown) { if (diskop.numEntries > DISKOP_LINES && diskop.scrollOffset < diskop.numEntries-DISKOP_LINES) { diskop.scrollOffset++; ui.updateDiskOpFileList = true; } } else if (ui.posEdScreenShown && song->currOrder < song->header.numOrders-1) { modSetPos(song->currOrder + 1, DONT_SET_ROW); } } else if (ui.samplerScreenShown) // lower part of screen { if (!ui.samplerVolBoxShown && !ui.samplerFiltersBoxShown) samplerZoomOutMouseWheel(); } else if (!editor.songPlaying && song->currRow < MOD_ROWS) { modSetPos(DONT_SET_ORDER, song->currRow + 1); // pattern data } } static bool handleRightMouseButton(void) { if (!mouse.rightButtonPressed) return false; // exit sample swap mode with right mouse button (if present) if (editor.swapChannelFlag) { editor.swapChannelFlag = false; pointerSetPreviousMode(); setPrevStatusMessage(); return true; } // toggle channel muting with right mouse button if (ui.visualizerMode == VISUAL_QUADRASCOPE && mouse.y >= 55 && mouse.y <= 87) { if (!ui.posEdScreenShown && !ui.editOpScreenShown && !ui.diskOpScreenShown && !ui.aboutScreenShown && !ui.samplerVolBoxShown && !ui.samplerFiltersBoxShown && !ui.samplingBoxShown && !editor.mod2WavOngoing) { if (mouse.x > 127 && mouse.x <= 167) editor.muted[0] ^= 1; else if (mouse.x > 175 && mouse.x <= 215) editor.muted[1] ^= 1; else if (mouse.x > 223 && mouse.x <= 263) editor.muted[2] ^= 1; else if (mouse.x > 271 && mouse.x <= 311) editor.muted[3] ^= 1; renderMuteButtons(); } } // sample hand drawing if (mouse.y >= 138 && mouse.y <= 201 && ui.samplerScreenShown && !ui.samplerVolBoxShown && !ui.samplerFiltersBoxShown && !ui.samplingBoxShown) { samplerEditSample(false); } return false; } static bool handleLeftMouseButton(void) { if (editor.swapChannelFlag || ui.editTextFlag) return false; // handle volume toolbox in sampler screen if (ui.samplerVolBoxShown) { handleSamplerVolumeBox(); return true; } // handle filters toolbox in sampler screen else if (ui.samplerFiltersBoxShown) { handleSamplerFiltersBox(); return true; } // handle sampling toolbox in sampler screen else if (ui.samplingBoxShown) { handleSamplingBox(); return true; } // cancel note input gadgets with left/right mouse button if (ui.changingSmpResample || ui.changingChordNote || ui.changingDrumPadNote || ui.changingSamplingNote) { if (mouse.leftButtonPressed || mouse.rightButtonPressed) { ui.changingSmpResample = false; ui.changingSamplingNote = false; ui.changingChordNote = false; ui.changingDrumPadNote = false; ui.updateResampleNote = true; ui.updateChordNote1Text = true; ui.updateChordNote2Text = true; ui.updateChordNote3Text = true; ui.updateChordNote4Text = true; setPrevStatusMessage(); pointerSetPreviousMode(); } return true; } if (!mouse.leftButtonPressed) return false; // if MOD2WAV is ongoing, only check CANCEL button if (editor.mod2WavOngoing) { if (mouse.x >= MOD2WAV_CANCEL_BTN_X1 && mouse.x <= MOD2WAV_CANCEL_BTN_X2 && mouse.y >= MOD2WAV_CANCEL_BTN_Y1 && mouse.y <= MOD2WAV_CANCEL_BTN_Y2) { editor.abortMod2Wav = true; } return true; // don't handle other buttons } // if in fullscreen mode and the image isn't filling the whole screen, handle top left corner as quit if (video.fullscreen && (video.renderX > 0 || video.renderY > 0) && (mouse.rawX == 0 && mouse.rawY == 0)) return handleGUIButtons(PTB_QUIT); int32_t guiButton = checkGUIButtons(); if (guiButton == -1) return false; return handleGUIButtons(guiButton); } void updateMouseCounters(void) { if (mouse.buttonWaiting) { if (++mouse.buttonWaitCounter > VBLANK_HZ/4) // quarter of a second { mouse.buttonWaitCounter = 0; mouse.buttonWaiting = false; } } if (editor.errorMsgActive) { if (++editor.errorMsgCounter >= VBLANK_HZ) // 1 second { editor.errorMsgCounter = 0; // don't reset status text/mouse color during certain modes if (!ui.askBoxShown && !ui.changingChordNote && !ui.changingDrumPadNote && !ui.changingSmpResample && !editor.swapChannelFlag && !ui.changingSamplingNote) { pointerSetPreviousMode(); setPrevStatusMessage(); } editor.errorMsgActive = false; editor.errorMsgBlock = false; if (ui.diskOpScreenShown) diskOpShowSelectText(); } } } static bool handleGUIButtons(int32_t button) // are you prepared to enter the jungle? { ui.force32BitNumPtr = false; switch (button) { case PTB_DUMMY: return false; // for gaps / empty spaces / dummies case PTB_PAT2SMP: { if (askBox(ASKBOX_PAT2SMP, "PLEASE SELECT")) pat2SmpRender(); } break; // Edit Op. All Screens case PTB_EO_TITLEBAR: { if (ui.editOpScreen == 0) editor.sampleAllFlag ^= 1; else if (ui.editOpScreen == 1) editor.trackPattFlag = (editor.trackPattFlag + 1) % 3; else if (ui.editOpScreen == 2) editor.halfClipFlag ^= 1; else if (ui.editOpScreen == 3) editor.newOldFlag ^= 1; renderEditOpMode(); } break; case PTB_EO_1: { ui.editOpScreen = 0; renderEditOpScreen(); } break; case PTB_EO_2: { ui.editOpScreen = 1; renderEditOpScreen(); } break; case PTB_EO_3: { ui.editOpScreen = 2; renderEditOpScreen(); } break; case PTB_EO_EXIT: { ui.aboutScreenShown = false; ui.editOpScreenShown = false; displayMainScreen(); } break; // ---------------------------------------------------------- // Edit Op. Screen #1 case PTB_EO_TRACK_NOTE_UP: trackNoteUp(editor.sampleAllFlag, 0, MOD_ROWS - 1); break; case PTB_EO_TRACK_NOTE_DOWN: trackNoteDown(editor.sampleAllFlag, 0, MOD_ROWS - 1); break; case PTB_EO_TRACK_OCTA_UP: trackOctaUp(editor.sampleAllFlag, 0, MOD_ROWS - 1); break; case PTB_EO_TRACK_OCTA_DOWN: trackOctaDown(editor.sampleAllFlag, 0, MOD_ROWS - 1); break; case PTB_EO_PATT_NOTE_UP: pattNoteUp(editor.sampleAllFlag); break; case PTB_EO_PATT_NOTE_DOWN: pattNoteDown(editor.sampleAllFlag); break; case PTB_EO_PATT_OCTA_UP: pattOctaUp(editor.sampleAllFlag); break; case PTB_EO_PATT_OCTA_DOWN: pattOctaDown(editor.sampleAllFlag); break; // ---------------------------------------------------------- // Edit Op. Screen #2 case PTB_EO_RECORD: { editor.recordMode ^= 1; ui.updateRecordText = true; } break; case PTB_EO_DELETE: delSampleTrack(); break; case PTB_EO_EXCHGE: exchSampleTrack(); break; case PTB_EO_COPY: copySampleTrack(); break; case PTB_EO_FROM: { editor.sampleFrom = editor.currSample + 1; ui.updateFromText = true; } break; case PTB_EO_TO: { editor.sampleTo = editor.currSample + 1; ui.updateToText = true; } break; case PTB_EO_KILL: { if (askBox(ASKBOX_YES_NO, "KILL SAMPLE ?")) killSample(); } break; case PTB_EO_QUANTIZE: { ui.tmpDisp16 = config.quantizeValue; editor.quantizeValueDisp = &ui.tmpDisp16; ui.numPtr16 = &ui.tmpDisp16; ui.numLen = 2; ui.editTextPos = 2824; // (y * 40) + x getNumLine(TEXT_EDIT_DECIMAL, PTB_EO_QUANTIZE); } break; case PTB_EO_METRO_1: // metronome speed { ui.tmpDisp16 = editor.metroSpeed; editor.metroSpeedDisp = &ui.tmpDisp16; ui.numPtr16 = &ui.tmpDisp16; ui.numLen = 2; ui.editTextPos = 3261; // (y * 40) + x getNumLine(TEXT_EDIT_DECIMAL, PTB_EO_METRO_1); } break; case PTB_EO_METRO_2: // metronome channel { ui.tmpDisp16 = editor.metroChannel; editor.metroChannelDisp = &ui.tmpDisp16; ui.numPtr16 = &ui.tmpDisp16; ui.numLen = 2; ui.editTextPos = 3264; // (y * 40) + x getNumLine(TEXT_EDIT_DECIMAL, PTB_EO_METRO_2); } break; case PTB_EO_FROM_NUM: { ui.tmpDisp8 = editor.sampleFrom; editor.sampleFromDisp = &ui.tmpDisp8; ui.numPtr8 = &ui.tmpDisp8; ui.numLen = 2; ui.numBits = 8; ui.editTextPos = 3273; // (y * 40) + x getNumLine(TEXT_EDIT_HEX, PTB_EO_FROM_NUM); } break; case PTB_EO_TO_NUM: { ui.tmpDisp8 = editor.sampleTo; editor.sampleToDisp = &ui.tmpDisp8; ui.numPtr8 = &ui.tmpDisp8; ui.numLen = 2; ui.numBits = 8; ui.editTextPos = 3713; // (y * 40) + x getNumLine(TEXT_EDIT_HEX, PTB_EO_TO_NUM); } break; case PTB_EO_FROM_UP: { if (editor.sampleFrom < 0x1F) { editor.sampleFrom++; ui.updateFromText = true; } } break; case PTB_EO_FROM_DOWN: { if (editor.sampleFrom > 0x00) { editor.sampleFrom--; ui.updateFromText = true; } } break; case PTB_EO_TO_UP: { if (editor.sampleTo < 0x1F) { editor.sampleTo++; ui.updateToText = true; } } break; case PTB_EO_TO_DOWN: { if (editor.sampleTo > 0x00) { editor.sampleTo--; ui.updateToText = true; } } break; case PTB_EO_KEYS: { editor.multiFlag ^= 1; ui.updateTrackerFlags = true; ui.updateKeysText = true; } break; // ---------------------------------------------------------- // Edit Op. Screen #3 case PTB_EO_MIX: { if (!mouse.rightButtonPressed) { editor.mixFlag = true; ui.showTextPtr = editor.mixText; ui.textEndPtr = editor.mixText + 15; ui.textLength = 16; ui.editTextPos = 1936; // (y * 40) + x ui.dstOffset = NULL; ui.dstOffsetEnd = false; ui.updateMixText = true; getTextLine(PTB_EO_MIX); } else { if (editor.sampleZero) { statusNotSampleZero(); break; } moduleSample_t *s = &song->samples[editor.currSample]; if (s->length == 0) { statusSampleIsEmpty(); break; } if (editor.samplePos == s->length) { displayErrorMsg("INVALID POS !"); break; } int8_t *ptr8_1 = (int8_t *)malloc(config.maxSampleLength); if (ptr8_1 == NULL) { statusOutOfMemory(); return true; } memcpy(ptr8_1, &song->sampleData[s->offset], config.maxSampleLength); int8_t *ptr8_2 = &song->sampleData[s->offset+editor.samplePos]; int8_t *ptr8_3 = &song->sampleData[s->offset+s->length-1]; int8_t *ptr8_4 = ptr8_1; editor.modulateOffset = 0; editor.modulatePos = 0; do { int16_t tmp16 = *ptr8_2 + *ptr8_1; if (editor.halfClipFlag == 0) tmp16 >>= 1; CLAMP8(tmp16); *ptr8_2++ = (int8_t)tmp16; if (editor.modulateSpeed == 0) { ptr8_1++; } else { editor.modulatePos += editor.modulateSpeed; int8_t modTmp = (editor.modulatePos >> 12) & 0xFF; int8_t modDat = vibratoTable[modTmp & 0x1F] >> 2; int32_t modPos = ((modTmp & 32) ? (editor.modulateOffset - modDat) : (editor.modulateOffset + modDat)) + 2048; editor.modulateOffset = modPos; modPos >>= 11; modPos = CLAMP(modPos, 0, s->length - 1); ptr8_1 = &ptr8_4[modPos]; } } while (ptr8_2 < ptr8_3); free(ptr8_4); fixSampleBeep(s); if (ui.samplerScreenShown) displaySample(); updateWindowTitle(MOD_IS_MODIFIED); } } break; case PTB_EO_ECHO: { if (editor.sampleZero) { statusNotSampleZero(); break; } moduleSample_t *s = &song->samples[editor.currSample]; if (s->length == 0) { statusSampleIsEmpty(); break; } if (editor.samplePos == 0) { displayErrorMsg("SET SAMPLE POS !"); break; } if (editor.samplePos == s->length) { displayErrorMsg("INVALID POS !"); break; } int8_t *ptr8_1 = &song->sampleData[s->offset+editor.samplePos]; int8_t *ptr8_2 = &song->sampleData[s->offset]; int8_t *ptr8_3 = ptr8_2; editor.modulateOffset = 0; editor.modulatePos = 0; for (int32_t j = 0; j < s->length; j++) { int16_t tmp16 = (*ptr8_2 + *ptr8_1) >> 1; CLAMP8(tmp16); *ptr8_1++ = (int8_t)tmp16; if (editor.modulateSpeed == 0) { ptr8_2++; } else { editor.modulatePos += editor.modulateSpeed; int8_t modTmp = (editor.modulatePos >> 12) & 0xFF; int8_t modDat = vibratoTable[modTmp & 0x1F] >> 2; int32_t modPos = ((modTmp & 32) ? (editor.modulateOffset - modDat) : (editor.modulateOffset + modDat)) + 2048; editor.modulateOffset = modPos; modPos >>= 11; modPos = CLAMP(modPos, 0, s->length - 1); ptr8_2 = &ptr8_3[modPos]; } } if (editor.halfClipFlag != 0) { for (int32_t j = 0; j < s->length; j++) { int16_t tmp16 = ptr8_3[j] + ptr8_3[j]; CLAMP8(tmp16); ptr8_3[j] = (int8_t)tmp16; } } fixSampleBeep(s); if (ui.samplerScreenShown) displaySample(); updateWindowTitle(MOD_IS_MODIFIED); } break; case PTB_EO_POS_NUM: { if (config.maxSampleLength == 65534 && mouse.x < 244) // yuck! break; if (mouse.rightButtonPressed) { editor.samplePos = 0; ui.updatePosText = true; } else { ui.force32BitNumPtr = true; ui.tmpDisp32 = editor.samplePos; editor.samplePosDisp = &ui.tmpDisp32; ui.numPtr32 = &ui.tmpDisp32; if (config.maxSampleLength == 65534) { ui.numLen = 4; ui.numBits = 16; ui.editTextPos = 2391; // (y * 40) + x } else { ui.numLen = 5; ui.numBits = 17; ui.editTextPos = 2390; // (y * 40) + x } getNumLine(TEXT_EDIT_HEX, PTB_EO_POS_NUM); } } break; case PTB_EO_POS_UP: edPosUpButton(INCREMENT_SLOW); break; case PTB_EO_POS_DOWN: edPosDownButton(INCREMENT_SLOW); break; case PTB_EO_BOOST: // this is actually treble increase { if (editor.sampleZero) { statusNotSampleZero(); break; } moduleSample_t *s = &song->samples[editor.currSample]; if (s->length == 0) { statusSampleIsEmpty(); break; } boostSample(editor.currSample, false); if (ui.samplerScreenShown) displaySample(); updateWindowTitle(MOD_IS_MODIFIED); } break; case PTB_EO_FILTER: // this is actually treble decrease { if (editor.sampleZero) { statusNotSampleZero(); break; } moduleSample_t *s = &song->samples[editor.currSample]; if (s->length == 0) { statusSampleIsEmpty(); break; } filterSample(editor.currSample, false); if (ui.samplerScreenShown) displaySample(); updateWindowTitle(MOD_IS_MODIFIED); } break; case PTB_EO_MOD_NUM: { if (mouse.rightButtonPressed) { editor.modulateSpeed = 0; ui.updateModText = true; } } break; case PTB_EO_MOD: { if (editor.sampleZero) { statusNotSampleZero(); break; } moduleSample_t *s = &song->samples[editor.currSample]; if (s->length == 0) { statusSampleIsEmpty(); break; } if (editor.modulateSpeed == 0) { displayErrorMsg("SET MOD. SPEED !"); break; } int8_t *ptr8_1 = &song->sampleData[s->offset]; int8_t *ptr8_3 = (int8_t *)malloc(config.maxSampleLength); if (ptr8_3 == NULL) { statusOutOfMemory(); return true; } int8_t *ptr8_2 = ptr8_3; memcpy(ptr8_2, ptr8_1, config.maxSampleLength); editor.modulateOffset = 0; editor.modulatePos = 0; for (int32_t j = 0; j < s->length; j++) { *ptr8_1++ = *ptr8_2; editor.modulatePos += editor.modulateSpeed; int8_t modTmp = (editor.modulatePos >> 12) & 0xFF; int8_t modDat = vibratoTable[modTmp & 0x1F] >> 2; int32_t modPos = ((modTmp & 32) ? (editor.modulateOffset - modDat) : (editor.modulateOffset + modDat)) + 2048; editor.modulateOffset = modPos; modPos >>= 11; modPos = CLAMP(modPos, 0, s->length - 1); ptr8_2 = &ptr8_3[modPos]; } free(ptr8_3); fixSampleBeep(s); if (ui.samplerScreenShown) displaySample(); updateWindowTitle(MOD_IS_MODIFIED); } break; case PTB_EO_MOD_UP: edModUpButton(); break; case PTB_EO_MOD_DOWN: edModDownButton(); break; case PTB_EO_X_FADE: { if (editor.sampleZero) { statusNotSampleZero(); break; } moduleSample_t *s = &song->samples[editor.currSample]; if (s->length == 0) { statusSampleIsEmpty(); break; } int8_t *ptr8_1 = &song->sampleData[s->offset]; int8_t *ptr8_2 = &song->sampleData[s->offset+s->length-1]; do { int16_t tmp16 = *ptr8_1 + *ptr8_2; if (editor.halfClipFlag == 0) tmp16 >>= 1; CLAMP8(tmp16); int8_t tmpSmp = (int8_t)tmp16; *ptr8_1++ = tmpSmp; *ptr8_2-- = tmpSmp; } while (ptr8_1 < ptr8_2); fixSampleBeep(s); if (ui.samplerScreenShown) displaySample(); updateWindowTitle(MOD_IS_MODIFIED); } break; case PTB_EO_BACKWD: { int8_t *ptr8_1, *ptr8_2; if (editor.sampleZero) { statusNotSampleZero(); break; } moduleSample_t *s = &song->samples[editor.currSample]; if (s->length == 0) { statusSampleIsEmpty(); break; } if (editor.markStartOfs != -1 && editor.markStartOfs != editor.markEndOfs && editor.markEndOfs != 0) { ptr8_1 = &song->sampleData[s->offset+editor.markStartOfs]; ptr8_2 = &song->sampleData[s->offset+editor.markEndOfs-1]; } else { ptr8_1 = &song->sampleData[s->offset]; ptr8_2 = &song->sampleData[s->offset+s->length-1]; } do { int8_t tmpSmp = *ptr8_1; *ptr8_1++ = *ptr8_2; *ptr8_2-- = tmpSmp; } while (ptr8_1 < ptr8_2); fixSampleBeep(s); if (ui.samplerScreenShown) displaySample(); updateWindowTitle(MOD_IS_MODIFIED); } break; case PTB_EO_CB: { if (editor.sampleZero) { statusNotSampleZero(); break; } moduleSample_t *s = &song->samples[editor.currSample]; if (s->length == 0) { statusSampleIsEmpty(); break; } if (editor.samplePos == 0) { displayErrorMsg("SET SAMPLE POS !"); break; } if (editor.samplePos >= s->length) { displayErrorMsg("INVALID POS !"); break; } turnOffVoices(); memcpy(&song->sampleData[s->offset], &song->sampleData[s->offset + editor.samplePos], config.maxSampleLength - editor.samplePos); memset(&song->sampleData[s->offset + (config.maxSampleLength - editor.samplePos)], 0, editor.samplePos); if (editor.samplePos > s->loopStart) { s->loopStart = 0; s->loopLength = 2; } else { s->loopStart = (s->loopStart - editor.samplePos) & config.maxSampleLength; } s->length = (s->length - editor.samplePos) & config.maxSampleLength; editor.samplePos = 0; fixSampleBeep(s); updateCurrSample(); updateWindowTitle(MOD_IS_MODIFIED); } break; case PTB_EO_CHORD: { ui.editOpScreen = 3; renderEditOpScreen(); } break; // fade up case PTB_EO_FU: { if (editor.sampleZero) { statusNotSampleZero(); break; } moduleSample_t *s = &song->samples[editor.currSample]; if (s->length == 0) { statusSampleIsEmpty(); break; } if (editor.samplePos == 0) { displayErrorMsg("INVALID POS !"); break; } double dSamplePosMul = 1.0 / editor.samplePos; int8_t *ptr8 = &song->sampleData[s->offset]; for (int32_t j = 0; j < editor.samplePos; j++) { double dSmp = ((*ptr8) * j) * dSamplePosMul; int32_t smp32 = (int32_t)dSmp; CLAMP8(smp32); *ptr8++ = (int8_t)smp32; } fixSampleBeep(s); if (ui.samplerScreenShown) displaySample(); updateWindowTitle(MOD_IS_MODIFIED); } break; // fade down case PTB_EO_FD: { if (editor.sampleZero) { statusNotSampleZero(); break; } moduleSample_t *s = &song->samples[editor.currSample]; if (s->length == 0) { statusSampleIsEmpty(); break; } if (editor.samplePos >= s->length-1) { displayErrorMsg("INVALID POS !"); break; } int32_t tmp32 = (s->length - 1) - editor.samplePos; if (tmp32 == 0) tmp32 = 1; double dSampleMul = 1.0 / tmp32; int8_t *ptr8 = &song->sampleData[s->offset+s->length-1]; int32_t idx = 0; for (int32_t j = editor.samplePos; j < s->length; j++) { double dSmp = ((*ptr8) * idx) * dSampleMul; int32_t smp32 = (int32_t)dSmp; CLAMP8(smp32); *ptr8-- = (int8_t)smp32; idx++; } fixSampleBeep(s); if (ui.samplerScreenShown) displaySample(); updateWindowTitle(MOD_IS_MODIFIED); } break; case PTB_EO_UPSAMP: { moduleSample_t *s = &song->samples[editor.currSample]; if (s->length == 0) { statusSampleIsEmpty(); break; } if (askBox(ASKBOX_YES_NO, "UPSAMPLE ?")) upSample(); } break; case PTB_EO_DNSAMP: { moduleSample_t *s = &song->samples[editor.currSample]; if (s->length == 0) { statusSampleIsEmpty(); break; } if (askBox(ASKBOX_YES_NO, "DOWNSAMPLE ?")) downSample(); } break; case PTB_EO_VOL_NUM: { if (mouse.rightButtonPressed) { editor.sampleVol = 100; ui.updateVolText = true; } else { ui.tmpDisp16 = editor.sampleVol; editor.sampleVolDisp = &ui.tmpDisp16; ui.numPtr16 = &ui.tmpDisp16; ui.numLen = 3; ui.editTextPos = 3711; // (y * 40) + x getNumLine(TEXT_EDIT_DECIMAL, PTB_EO_VOL_NUM); } } break; case PTB_EO_VOL: { if (editor.sampleZero) { statusNotSampleZero(); break; } moduleSample_t *s = &song->samples[editor.currSample]; if (s->length == 0) { statusSampleIsEmpty(); break; } if (editor.sampleVol != 100) { int8_t *ptr8 = &song->sampleData[s->offset]; int32_t sampleMul = (((1UL << 19) * editor.sampleVol) + 50) / 100; for (int32_t j = 0; j < s->length; j++) { int16_t tmp16 = (ptr8[j] * sampleMul) >> 19; CLAMP8(tmp16); ptr8[j] = (int8_t)tmp16; } fixSampleBeep(s); if (ui.samplerScreenShown) displaySample(); updateWindowTitle(MOD_IS_MODIFIED); } } break; case PTB_EO_VOL_UP: edVolUpButton(); break; case PTB_EO_VOL_DOWN: edVolDownButton(); break; // ---------------------------------------------------------- // Edit Op. Screen #4 (chord maker) case PTB_EO_DOCHORD: { if (askBox(ASKBOX_YES_NO, "MAKE CHORD?")) mixChordSample(); } break; case PTB_EO_NOTE1: selectChordNote1(); break; case PTB_EO_NOTE2: selectChordNote2(); break; case PTB_EO_NOTE3: selectChordNote3(); break; case PTB_EO_NOTE4: selectChordNote4(); break; case PTB_EO_NOTE1_UP: edNote1UpButton(); break; case PTB_EO_NOTE1_DOWN: edNote1DownButton(); break; case PTB_EO_NOTE2_UP: edNote2UpButton(); break; case PTB_EO_NOTE2_DOWN: edNote2DownButton(); break; case PTB_EO_NOTE3_UP: edNote3UpButton(); break; case PTB_EO_NOTE3_DOWN: edNote3DownButton(); break; case PTB_EO_NOTE4_UP: edNote4UpButton(); break; case PTB_EO_NOTE4_DOWN: edNote4DownButton(); break; case PTB_EO_RESET: resetChord(); break; case PTB_EO_UNDO: undoChord(); break; case PTB_EO_LENGTH: { if (config.maxSampleLength != 65534 && mouse.x > 157) // yuck! break; toggleChordLength(); } break; case PTB_EO_MAJOR: setChordMajor(); break; case PTB_EO_MINOR: setChordMinor(); break; case PTB_EO_SUS4: setChordSus4(); break; case PTB_EO_MAJOR7: setChordMajor7(); break; case PTB_EO_MINOR7: setChordMinor7(); break; case PTB_EO_MAJOR6: setChordMajor6(); break; case PTB_EO_MINOR6: setChordMinor6(); break; // ---------------------------------------------------------- case PTB_ABOUT: { ui.aboutScreenShown ^= 1; if (ui.aboutScreenShown) renderAboutScreen(); else if (ui.visualizerMode == VISUAL_QUADRASCOPE) renderQuadrascopeBg(); else if (ui.visualizerMode == VISUAL_SPECTRUM) renderSpectrumAnalyzerBg(); } break; case PTB_PE_PATT: { if (editor.currMode == MODE_IDLE || editor.currMode == MODE_EDIT) { ui.tmpDisp16 = song->currOrder; if (ui.tmpDisp16 > song->header.numOrders-1) ui.tmpDisp16 = song->header.numOrders-1; ui.tmpDisp16 = song->header.order[ui.tmpDisp16]; editor.currPosEdPattDisp = &ui.tmpDisp16; ui.numPtr16 = &ui.tmpDisp16; ui.numLen = 2; ui.editTextPos = 2180; // (y * 40) + x getNumLine(TEXT_EDIT_DECIMAL, PTB_PE_PATT); } } break; case PTB_PE_SCROLLTOP: { if (song->currOrder != 0) modSetPos(0, DONT_SET_ROW); } break; case PTB_PE_SCROLLUP: { if (song->currOrder > 0) modSetPos(song->currOrder - 1, DONT_SET_ROW); } break; case PTB_PE_SCROLLDOWN: { if (song->currOrder < song->header.numOrders-1) modSetPos(song->currOrder + 1, DONT_SET_ROW); } break; case PTB_PE_SCROLLBOT: { if (song->currOrder != song->header.numOrders-1) modSetPos(song->header.numOrders - 1, DONT_SET_ROW); } break; case PTB_PE_EXIT: { ui.aboutScreenShown = false; ui.posEdScreenShown = false; displayMainScreen(); } break; case PTB_POS: case PTB_POSED: { ui.posEdScreenShown ^= 1; if (ui.posEdScreenShown) { renderPosEdScreen(); ui.updatePosEd = true; } else { displayMainScreen(); } } break; case PTB_POSS: { if (editor.currMode == MODE_IDLE || editor.currMode == MODE_EDIT) { if (mouse.rightButtonPressed) { song->currOrder = 0; editor.currPatternDisp = &song->header.order[song->currOrder]; if (ui.posEdScreenShown) ui.updatePosEd = true; } else { ui.tmpDisp16 = song->currOrder; editor.currPosDisp = &ui.tmpDisp16; ui.numPtr16 = &ui.tmpDisp16; ui.numLen = 3; ui.editTextPos = 169; // (y * 40) + x getNumLine(TEXT_EDIT_DECIMAL, PTB_POSS); } } } break; case PTB_PATTERNS: { if (editor.currMode == MODE_IDLE || editor.currMode == MODE_EDIT) { if (mouse.rightButtonPressed) { song->header.order[song->currOrder] = 0; ui.updateSongSize = true; updateWindowTitle(MOD_IS_MODIFIED); if (ui.posEdScreenShown) ui.updatePosEd = true; } else { ui.tmpDisp16 = song->header.order[song->currOrder]; editor.currPatternDisp = &ui.tmpDisp16; ui.numPtr16 = &ui.tmpDisp16; ui.numLen = 2; ui.editTextPos = 610; // (y * 40) + x getNumLine(TEXT_EDIT_DECIMAL, PTB_PATTERNS); } } } break; case PTB_LENGTHS: { if (editor.currMode == MODE_IDLE || editor.currMode == MODE_EDIT) { if (mouse.rightButtonPressed) { song->header.numOrders = 1; int16_t tmp16 = song->currOrder; if (tmp16 > song->header.numOrders-1) tmp16 = song->header.numOrders-1; editor.currPosEdPattDisp = &song->header.order[tmp16]; ui.updateSongSize = true; updateWindowTitle(MOD_IS_MODIFIED); if (ui.posEdScreenShown) ui.updatePosEd = true; } else { ui.tmpDisp16 = song->header.numOrders; editor.currLengthDisp = &ui.tmpDisp16; ui.numPtr16 = &ui.tmpDisp16; ui.numLen = 3; ui.editTextPos = 1049; // (y * 40) + x getNumLine(TEXT_EDIT_DECIMAL, PTB_LENGTHS); } } } break; case PTB_PATTBOX: case PTB_PATTDATA: { if (!ui.introTextShown && (editor.currMode == MODE_IDLE || editor.currMode == MODE_EDIT || editor.playMode != PLAY_MODE_NORMAL)) { ui.tmpDisp16 = song->currPattern; editor.currEditPatternDisp = &ui.tmpDisp16; ui.numPtr16 = &ui.tmpDisp16; ui.numLen = 2; ui.editTextPos = 5121; // (y * 40) + x getNumLine(TEXT_EDIT_DECIMAL, PTB_PATTDATA); } } break; case PTB_SAMPLES: { if (editor.sampleZero) { editor.sampleZero = false; ui.updateCurrSampleNum = true; } ui.tmpDisp8 = editor.currSample; editor.currSampleDisp = &ui.tmpDisp8; ui.numPtr8 = &ui.tmpDisp8; ui.numLen = 2; ui.numBits = 8; ui.editTextPos = 1930; // (y * 40) + x getNumLine(TEXT_EDIT_HEX, PTB_SAMPLES); } break; case PTB_SVOLUMES: { if (editor.sampleZero) { statusNotSampleZero(); break; } if (mouse.rightButtonPressed) { song->samples[editor.currSample].volume = 0; } else { ui.tmpDisp8 = song->samples[editor.currSample].volume; song->samples[editor.currSample].volumeDisp = &ui.tmpDisp8; ui.numPtr8 = &ui.tmpDisp8; ui.numLen = 2; ui.numBits = 8; ui.editTextPos = 2370; // (y * 40) + x getNumLine(TEXT_EDIT_HEX, PTB_SVOLUMES); } } break; case PTB_SLENGTHS: { if (config.maxSampleLength == 65534 && mouse.x < 62) // yuck! break; if (editor.sampleZero) { statusNotSampleZero(); break; } if (mouse.rightButtonPressed) { moduleSample_t *s = &song->samples[editor.currSample]; turnOffVoices(); s->length = 0; if (s->loopStart+s->loopLength > 2) { if (s->length < s->loopStart+s->loopLength) s->length = s->loopStart+s->loopLength; } ui.updateSongSize = true; ui.updateCurrSampleLength = true; if (ui.samplerScreenShown) redrawSample(); recalcChordLength(); updateWindowTitle(MOD_IS_MODIFIED); } else { ui.force32BitNumPtr = true; ui.tmpDisp32 = song->samples[editor.currSample].length; song->samples[editor.currSample].lengthDisp = &ui.tmpDisp32; ui.numPtr32 = &ui.tmpDisp32; if (config.maxSampleLength == 65534) { ui.numLen = 4; ui.numBits = 16; ui.editTextPos = 2808; // (y * 40) + x } else { ui.numLen = 5; ui.numBits = 17; ui.editTextPos = 2807; // (y * 40) + x } getNumLine(TEXT_EDIT_HEX, PTB_SLENGTHS); } } break; case PTB_SREPEATS: { if (config.maxSampleLength == 65534 && mouse.x < 62) // yuck! break; if (editor.sampleZero) { statusNotSampleZero(); break; } if (mouse.rightButtonPressed) { moduleSample_t *s = &song->samples[editor.currSample]; s->loopStart = 0; if (s->length >= s->loopLength) { if (s->loopStart+s->loopLength > s->length) s->loopStart = s->length-s->loopLength; } else { s->loopStart = 0; } ui.updateCurrSampleRepeat = true; if (ui.editOpScreenShown && ui.editOpScreen == 3) ui.updateChordLengthText = true; if (ui.samplerScreenShown) setLoopSprites(); updatePaulaLoops(); updateWindowTitle(MOD_IS_MODIFIED); } else { ui.force32BitNumPtr = true; ui.tmpDisp32 = song->samples[editor.currSample].loopStart; song->samples[editor.currSample].loopStartDisp = &ui.tmpDisp32; ui.numPtr32 = &ui.tmpDisp32; if (config.maxSampleLength == 65534) { ui.numLen = 4; ui.numBits = 16; ui.editTextPos = 3248; // (y * 40) + x } else { ui.numLen = 5; ui.numBits = 17; ui.editTextPos = 3247; // (y * 40) + x } getNumLine(TEXT_EDIT_HEX, PTB_SREPEATS); } } break; case PTB_SREPLENS: { if (config.maxSampleLength == 65534 && mouse.x < 62) // yuck! break; if (editor.sampleZero) { statusNotSampleZero(); break; } if (mouse.rightButtonPressed) { moduleSample_t *s = &song->samples[editor.currSample]; s->loopLength = 0; if (s->length >= s->loopStart) { if (s->loopStart+s->loopLength > s->length) s->loopLength = s->length-s->loopStart; } else { s->loopLength = 2; } if (s->loopLength < 2) s->loopLength = 2; ui.updateCurrSampleReplen = true; if (ui.editOpScreenShown && ui.editOpScreen == 3) ui.updateChordLengthText = true; if (ui.samplerScreenShown) setLoopSprites(); updatePaulaLoops(); updateWindowTitle(MOD_IS_MODIFIED); } else { ui.force32BitNumPtr = true; ui.tmpDisp32 = song->samples[editor.currSample].loopLength; song->samples[editor.currSample].loopLengthDisp = &ui.tmpDisp32; ui.numPtr32 = &ui.tmpDisp32; if (config.maxSampleLength == 0xFFFE) { ui.numLen = 4; ui.numBits = 16; ui.editTextPos = 3688; // (y * 40) + x } else { ui.numLen = 5; ui.numBits = 17; ui.editTextPos = 3687; // (y * 40) + x } getNumLine(TEXT_EDIT_HEX, PTB_SREPLENS); } } break; case PTB_EDITOP: { if (ui.editOpScreenShown) { if (ui.editOpScreen == 3) ui.editOpScreen = 0; else ui.editOpScreen = (ui.editOpScreen + 1) % 3; } else { ui.editOpScreenShown = true; } renderEditOpScreen(); } break; case PTB_DO_LOADMODULE: { diskop.mode = DISKOP_MODE_MOD; setPathFromDiskOpMode(); diskop.scrollOffset = 0; diskop.cached = false; ui.updateDiskOpFileList = true; ui.updateLoadMode = true; } break; case PTB_DO_LOADSAMPLE: { diskop.mode = DISKOP_MODE_SMP; setPathFromDiskOpMode(); diskop.scrollOffset = 0; diskop.cached = false; ui.updateDiskOpFileList = true; ui.updateLoadMode = true; } break; case PTB_LOADSAMPLE: // "LOAD" button next to sample name { ui.posEdScreenShown = false; diskop.mode = DISKOP_MODE_SMP; setPathFromDiskOpMode(); diskop.scrollOffset = 0; diskop.cached = false; if (!ui.diskOpScreenShown) { ui.diskOpScreenShown = true; renderDiskOpScreen(); } else { ui.updateDiskOpFileList = true; ui.updateLoadMode = true; } } break; case PTB_DO_SAVESAMPLE: { bool changeLoadMode = (diskop.mode != DISKOP_MODE_SMP); if (changeLoadMode) { diskop.mode = DISKOP_MODE_SMP; setPathFromDiskOpMode(); ui.updateLoadMode = true; // redraw load mode cursor updateDiskOp(); } if (askBox(ASKBOX_YES_NO, "SAVE SAMPLE ?")) saveSample(CHECK_IF_FILE_EXIST, DONT_GIVE_NEW_FILENAME); // also updates file list // if we changed mode, re-read directory in Disk Op. if (changeLoadMode) { diskop.scrollOffset = 0; diskop.cached = false; // read new directory ui.updateDiskOpFileList = true; updateDiskOp(); } } break; case PTB_MOD2WAV: { if (askBox(ASKBOX_MOD2WAV, "PLEASE SELECT")) { char fileName[20 + 4 + 1]; memset(fileName, 0, sizeof (fileName)); if (song->header.name[0] != '\0') { for (int32_t i = 0; i < 20; i++) { fileName[i] = (char)tolower(song->header.name[i]); if (fileName[i] == '\0') break; sanitizeFilenameChar(&fileName[i]); } strcat(fileName, ".wav"); } else { strcpy(fileName, "untitled.wav"); } mod2WavRender(fileName); } } break; case PTB_SA_SAMPLE: { ui.samplingBoxShown = true; renderSamplingBox(); } break; case PTB_SA_RESAMPLE: { if (askBox(ASKBOX_YES_NO, "RESAMPLE?")) samplerResample(); } break; case PTB_SA_RESAMPLENOTE: { ui.changingSmpResample = true; ui.updateResampleNote = true; setStatusMessage("SELECT NOTE", NO_CARRY); pointerSetMode(POINTER_MODE_MSG1, NO_CARRY); } break; case PTB_SA_SAMPLEAREA: { if (ui.sampleMarkingPos == -1) { samplerSamplePressed(MOUSE_BUTTON_NOT_HELD); return true; } } break; case PTB_SA_ZOOMBARAREA: { mouse.lastGUIButton = button; if (!ui.forceSampleDrag) { samplerBarPressed(MOUSE_BUTTON_NOT_HELD); return true; } } break; case PTB_SA_FIXDC: samplerRemoveDcOffset(); break; case PTB_SA_CUT: samplerSamDelete(SAMPLE_CUT); break; case PTB_SA_PASTE: samplerSamPaste(); break; case PTB_SA_COPY: samplerSamCopy(); break; case PTB_SA_LOOP: samplerLoopToggle(); break; case PTB_SA_PLAYWAVE: samplerPlayWaveform(); break; case PTB_SA_PLAYDISPLAY: samplerPlayDisplay(); break; case PTB_SA_PLAYRANGE: samplerPlayRange(); break; case PTB_SA_RANGEALL: samplerRangeAll(); break; case PTB_SA_SHOWALL: samplerShowAll(); break; case PTB_SA_SHOWRANGE: samplerShowRange(); break; case PTB_SA_RANGECENTER: sampleMarkerToCenter(); break; case PTB_SA_RANGEBEG: sampleMarkerToBeg(); break; case PTB_SA_RANGEEND: sampleMarkerToEnd(); break; case PTB_SA_ZOOMOUT: samplerZoomOut2x(); break; case PTB_SA_VOLUME: { ui.samplerVolBoxShown = true; renderSamplerVolBox(); } break; case PTB_SA_FILTERS: { ui.samplerFiltersBoxShown = true; renderSamplerFiltersBox(); fillSampleFilterUndoBuffer(); } break; case PTB_SA_STOP: turnOffVoices(); break; case PTB_DO_REFRESH: { diskop.scrollOffset = 0; diskop.cached = false; ui.updateDiskOpFileList = true; } break; // TODO: Find a PowerPacker packer and enable this // case PTB_DO_PACKMOD: diskop.modPackFlg ^= 1; break; case PTB_DO_SAMPLEFORMAT: { diskop.smpSaveType = (diskop.smpSaveType + 1) % 3; ui.updateSaveFormatText = true; } break; case PTB_DO_MODARROW: { diskop.mode = DISKOP_MODE_MOD; diskop.scrollOffset = 0; diskop.cached = false; ui.updateDiskOpFileList = true; ui.updateLoadMode = true; } break; case PTB_DO_SAMPLEARROW: { diskop.mode = DISKOP_MODE_SMP; diskop.scrollOffset = 0; diskop.cached = false; ui.updateDiskOpFileList = true; ui.updateLoadMode = true; } break; case PTB_SA_TUNETONE: toggleTuningTone(); break; case PTB_POSINS: { if ((editor.currMode == MODE_IDLE || editor.currMode == MODE_EDIT) && song->header.numOrders < 128) { for (int32_t i = 0; i < 127-song->currOrder; i++) song->header.order[127-i] = song->header.order[(127-i)-1]; song->header.order[song->currOrder] = 0; song->header.numOrders++; if (song->currOrder > song->header.numOrders-1) editor.currPosEdPattDisp = &song->header.order[song->header.numOrders-1]; updateWindowTitle(MOD_IS_MODIFIED); ui.updateSongSize = true; ui.updateSongLength = true; ui.updateSongPattern = true; if (ui.posEdScreenShown) ui.updatePosEd = true; } } break; case PTB_POSDEL: { if ((editor.currMode == MODE_IDLE || editor.currMode == MODE_EDIT) && song->header.numOrders > 1) { for (int32_t i = 0; i < 128-song->currOrder; i++) song->header.order[song->currOrder+i] = song->header.order[song->currOrder+i+1]; song->header.order[127] = 0; song->header.numOrders--; if (song->currOrder > song->header.numOrders-1) editor.currPosEdPattDisp = &song->header.order[song->header.numOrders-1]; updateWindowTitle(MOD_IS_MODIFIED); ui.updateSongSize = true; ui.updateSongLength = true; ui.updateSongPattern = true; if (ui.posEdScreenShown) ui.updatePosEd = true; } } break; case PTB_DO_SAVEMODULE: { bool changeLoadMode = (diskop.mode != DISKOP_MODE_MOD); if (changeLoadMode) { diskop.mode = DISKOP_MODE_MOD; setPathFromDiskOpMode(); ui.updateLoadMode = true; // redraw load mode cursor updateDiskOp(); } if (askBox(ASKBOX_YES_NO, "SAVE MODULE ?")) saveModule(CHECK_IF_FILE_EXIST, DONT_GIVE_NEW_FILENAME); // also updates file list // if we changed mode, re-read directory in Disk Op. if (changeLoadMode) { diskop.scrollOffset = 0; diskop.cached = false; // read new directory ui.updateDiskOpFileList = true; updateDiskOp(); } } break; case PTB_DO_DATAPATH: { if (mouse.rightButtonPressed) { memset(editor.currPath, 0, PATH_MAX + 1); ui.updateDiskOpPathText = true; } ui.showTextPtr = editor.currPath; ui.textEndPtr = &editor.currPath[PATH_MAX - 1]; ui.textLength = 26; ui.editTextPos = 1043; // (y * 40) + x ui.dstOffset = &ui.diskOpPathTextOffset; ui.dstOffsetEnd = false; getTextLine(PTB_DO_DATAPATH); } break; case PTB_SONGNAME: { if (mouse.rightButtonPressed) { memset(song->header.name, 0, sizeof (song->header.name)); ui.updateSongName = true; updateWindowTitle(MOD_IS_MODIFIED); } else { ui.showTextPtr = song->header.name; ui.textEndPtr = song->header.name + 19; ui.textLength = 20; ui.editTextPos = 4133; // (y * 40) + x ui.dstOffset = NULL; ui.dstOffsetEnd = false; getTextLine(PTB_SONGNAME); } } break; case PTB_SAMPLENAME: { if (mouse.rightButtonPressed) { memset(song->samples[editor.currSample].text, 0, sizeof (song->samples[editor.currSample].text)); ui.updateCurrSampleName = true; updateWindowTitle(MOD_IS_MODIFIED); } else { ui.showTextPtr = song->samples[editor.currSample].text; ui.textEndPtr = song->samples[editor.currSample].text + 21; ui.textLength = 22; ui.editTextPos = 4573; // (y * 40) + x ui.dstOffset = NULL; ui.dstOffsetEnd = false; getTextLine(PTB_SAMPLENAME); } } break; case PTB_VISUALS: { if (ui.aboutScreenShown) { ui.aboutScreenShown = false; } else if (!mouse.rightButtonPressed) { ui.visualizerMode = (ui.visualizerMode + 1) % 2; if (ui.visualizerMode == VISUAL_SPECTRUM) memset((int8_t *)editor.spectrumVolumes, 0, sizeof (editor.spectrumVolumes)); } if (ui.visualizerMode == VISUAL_QUADRASCOPE) renderQuadrascopeBg(); else if (ui.visualizerMode == VISUAL_SPECTRUM) renderSpectrumAnalyzerBg(); } break; case PTB_QUIT: { if (askBox(ASKBOX_YES_NO, "REALLY QUIT ?")) ui.throwExit = true; } break; case PTB_CHAN1: { if (mouse.rightButtonPressed) { editor.muted[0] = false; editor.muted[1] = true; editor.muted[2] = true; editor.muted[3] = true; } else { editor.muted[0] ^= 1; } renderMuteButtons(); } break; case PTB_CHAN2: { if (mouse.rightButtonPressed) { editor.muted[0] = true; editor.muted[1] = false; editor.muted[2] = true; editor.muted[3] = true; } else { editor.muted[1] ^= 1; } renderMuteButtons(); } break; case PTB_CHAN3: { if (mouse.rightButtonPressed) { editor.muted[0] = true; editor.muted[1] = true; editor.muted[2] = false; editor.muted[3] = true; } else { editor.muted[2] ^= 1; } renderMuteButtons(); } break; case PTB_CHAN4: { if (mouse.rightButtonPressed) { editor.muted[0] = true; editor.muted[1] = true; editor.muted[2] = true; editor.muted[3] = false; } else { editor.muted[3] ^= 1; } renderMuteButtons(); } break; case PTB_SAMPLER: samplerScreen(); break; case PTB_SA_EXIT: exitFromSam(); break; case PTB_DO_FILEAREA: diskOpLoadFile((mouse.y - 34) / 6, true); break; case PTB_DO_PARENT: { #ifdef _WIN32 diskOpSetPath(L"..", DISKOP_CACHE); #else diskOpSetPath("..", DISKOP_CACHE); #endif } break; case PTB_DISKOP: { editor.blockMarkFlag = false; ui.diskOpScreenShown = true; renderDiskOpScreen(); } break; case PTB_DO_EXIT: { ui.aboutScreenShown = false; ui.diskOpScreenShown = false; editor.blockMarkFlag = false; pointerSetPreviousMode(); setPrevStatusMessage(); displayMainScreen(); } break; case PTB_DO_SCROLLUP: { if (diskop.scrollOffset > 0) { diskop.scrollOffset--; ui.updateDiskOpFileList = true; } } break; case PTB_DO_SCROLLTOP: { diskop.scrollOffset = 0; ui.updateDiskOpFileList = true; } break; case PTB_DO_SCROLLDOWN: { if (diskop.numEntries > DISKOP_LINES && diskop.scrollOffset < diskop.numEntries-DISKOP_LINES) { diskop.scrollOffset++; ui.updateDiskOpFileList = true; } } break; case PTB_DO_SCROLLBOT: { if (diskop.numEntries > DISKOP_LINES) { diskop.scrollOffset = diskop.numEntries - DISKOP_LINES; ui.updateDiskOpFileList = true; } } break; case PTB_STOP: { editor.playMode = PLAY_MODE_NORMAL; modStop(); editor.currMode = MODE_IDLE; pointerSetMode(POINTER_MODE_IDLE, DO_CARRY); statusAllRight(); } break; case PTB_PLAY: { editor.playMode = PLAY_MODE_NORMAL; if (mouse.rightButtonPressed) modPlay(DONT_SET_PATTERN, song->currOrder, song->currRow); else modPlay(DONT_SET_PATTERN, song->currOrder, DONT_SET_ROW); editor.currMode = MODE_PLAY; pointerSetMode(POINTER_MODE_PLAY, DO_CARRY); statusAllRight(); } break; case PTB_PATTERN: { editor.playMode = PLAY_MODE_PATTERN; if (mouse.rightButtonPressed) modPlay(song->currPattern, DONT_SET_ORDER, song->currRow); else modPlay(song->currPattern, DONT_SET_ORDER, DONT_SET_ROW); editor.currMode = MODE_PLAY; pointerSetMode(POINTER_MODE_PLAY, DO_CARRY); statusAllRight(); } break; case PTB_EDIT: { if (!ui.samplerScreenShown) { editor.playMode = PLAY_MODE_NORMAL; modStop(); editor.currMode = MODE_EDIT; pointerSetMode(POINTER_MODE_EDIT, DO_CARRY); statusAllRight(); } } break; case PTB_RECORD: { if (!ui.samplerScreenShown) { editor.playMode = PLAY_MODE_PATTERN; if (mouse.rightButtonPressed) modPlay(song->currPattern, DONT_SET_ORDER, song->currRow); else modPlay(song->currPattern, DONT_SET_ORDER, DONT_SET_ROW); editor.currMode = MODE_RECORD; pointerSetMode(POINTER_MODE_EDIT, DO_CARRY); statusAllRight(); } } break; case PTB_CLEAR: { int32_t result = askBox(ASKBOX_CLEAR, "PLEASE SELECT"); if (result == ASKBOX_CLEAR_CANCEL) break; editor.playMode = PLAY_MODE_NORMAL; modStop(); if (result == ASKBOX_CLEAR_SONG) { clearSong(); } else if (result == ASKBOX_CLEAR_SAMPLES) { clearSamples(); } else if (result == ASKBOX_CLEAR_ALL) { clearSong(); clearSamples(); } editor.currMode = MODE_IDLE; pointerSetMode(POINTER_MODE_IDLE, DO_CARRY); statusAllRight(); updateWindowTitle(MOD_IS_MODIFIED); } break; case PTB_SAMPLEU: { if (mouse.rightButtonPressed) { editor.sampleZero = true; ui.updateCurrSampleNum = true; } else { sampleUpButton(); } } break; case PTB_SAMPLED: { if (mouse.rightButtonPressed) { editor.sampleZero = true; ui.updateCurrSampleNum = true; } else { sampleDownButton(); } } break; case PTB_FTUNEU: { if (!editor.sampleZero && (song->samples[editor.currSample].fineTune & 0xF) != 7) { sampleFineTuneUpButton(); updateWindowTitle(MOD_IS_MODIFIED); } } break; case PTB_FTUNED: { if (!editor.sampleZero && (song->samples[editor.currSample].fineTune & 0xF) != 8) { sampleFineTuneDownButton(); updateWindowTitle(MOD_IS_MODIFIED); } } break; case PTB_SVOLUMEU: { if (!editor.sampleZero && song->samples[editor.currSample].volume < 64) { sampleVolumeUpButton(); updateWindowTitle(MOD_IS_MODIFIED); } } break; case PTB_SVOLUMED: { if (!editor.sampleZero && song->samples[editor.currSample].volume > 0) { sampleVolumeDownButton(); updateWindowTitle(MOD_IS_MODIFIED); } } break; case PTB_SLENGTHU: { if (!editor.sampleZero && song->samples[editor.currSample].length < config.maxSampleLength) { sampleLengthUpButton(INCREMENT_SLOW); updateWindowTitle(MOD_IS_MODIFIED); } } break; case PTB_SLENGTHD: { if (!editor.sampleZero && song->samples[editor.currSample].length > 0) { sampleLengthDownButton(INCREMENT_SLOW); updateWindowTitle(MOD_IS_MODIFIED); } } break; case PTB_SREPEATU: { if (!editor.sampleZero) { int32_t oldVal = song->samples[editor.currSample].loopStart; sampleRepeatUpButton(INCREMENT_SLOW); if (song->samples[editor.currSample].loopStart != oldVal) updateWindowTitle(MOD_IS_MODIFIED); } } break; case PTB_SREPEATD: { if (!editor.sampleZero) { int32_t oldVal = song->samples[editor.currSample].loopStart; sampleRepeatDownButton(INCREMENT_SLOW); if (song->samples[editor.currSample].loopStart != oldVal) updateWindowTitle(MOD_IS_MODIFIED); } } break; case PTB_SREPLENU: { if (!editor.sampleZero) { int32_t oldVal = song->samples[editor.currSample].loopLength; sampleRepeatLengthUpButton(INCREMENT_SLOW); if (song->samples[editor.currSample].loopLength != oldVal) updateWindowTitle(MOD_IS_MODIFIED); } } break; case PTB_SREPLEND: { if (!editor.sampleZero) { int32_t oldVal = song->samples[editor.currSample].loopLength; sampleRepeatLengthDownButton(INCREMENT_SLOW); if (song->samples[editor.currSample].loopLength != oldVal) updateWindowTitle(MOD_IS_MODIFIED); } } break; case PTB_TEMPOU: tempoUpButton(); break; case PTB_TEMPOD: tempoDownButton(); break; case PTB_LENGTHU: { if (song->header.numOrders < 128) { songLengthUpButton(); updateWindowTitle(MOD_IS_MODIFIED); } } break; case PTB_LENGTHD: { if (song->header.numOrders > 1) { songLengthDownButton(); updateWindowTitle(MOD_IS_MODIFIED); } } break; case PTB_PATTERNU: { if (song->header.order[song->currOrder] < 99) { patternUpButton(); updateWindowTitle(MOD_IS_MODIFIED); } } break; case PTB_PATTERND: { if (song->header.order[song->currOrder] > 0) { patternDownButton(); updateWindowTitle(MOD_IS_MODIFIED); } } break; case PTB_POSU: positionUpButton(); break; case PTB_POSD: positionDownButton(); break; default: displayErrorMsg("NOT IMPLEMENTED"); return false; // button not mapped } mouse.lastGUIButton = button; return false; } static void handleRepeatedGUIButtons(void) { // repeat button switch (mouse.lastGUIButton) { case PTB_EO_NOTE1_UP: { if (mouse.repeatCounter >= 4) { mouse.repeatCounter = 0; edNote1UpButton(); } } break; case PTB_EO_NOTE1_DOWN: { if (mouse.repeatCounter >= 4) { mouse.repeatCounter = 0; edNote1DownButton(); } } break; case PTB_EO_NOTE2_UP: { if (mouse.repeatCounter >= 4) { mouse.repeatCounter = 0; edNote2UpButton(); } } break; case PTB_EO_NOTE2_DOWN: { if (mouse.repeatCounter >= 4) { mouse.repeatCounter = 0; edNote2DownButton(); } } break; case PTB_EO_NOTE3_UP: { if (mouse.repeatCounter >= 4) { mouse.repeatCounter = 0; edNote3UpButton(); } } break; case PTB_EO_NOTE3_DOWN: { if (mouse.repeatCounter >= 4) { mouse.repeatCounter = 0; edNote3DownButton(); } } break; case PTB_EO_NOTE4_UP: { if (mouse.repeatCounter >= 4) { mouse.repeatCounter = 0; edNote4UpButton(); } } break; case PTB_EO_NOTE4_DOWN: { if (mouse.repeatCounter >= 4) { mouse.repeatCounter = 0; edNote4DownButton(); } } break; case PTB_EO_VOL_UP: { if (mouse.repeatCounter >= 2) { mouse.repeatCounter = 0; edVolUpButton(); } } break; case PTB_EO_VOL_DOWN: { if (mouse.repeatCounter >= 2) { mouse.repeatCounter = 0; edVolDownButton(); } } break; case PTB_EO_MOD_UP: { if (mouse.repeatCounter >= 2) { mouse.repeatCounter = 0; edModUpButton(); } } break; case PTB_EO_MOD_DOWN: { if (mouse.repeatCounter >= 2) { mouse.repeatCounter = 0; edModDownButton(); } } break; case PTB_EO_POS_UP: { if (mouse.repeatCounter >= 1) { mouse.repeatCounter = 0; edPosUpButton(INCREMENT_FAST); } } break; case PTB_EO_POS_DOWN: { if (mouse.repeatCounter >= 1) { mouse.repeatCounter = 0; edPosDownButton(INCREMENT_FAST); } } break; case PTB_EO_FROM_UP: { if (mouse.repeatCounter >= 2) { mouse.repeatCounter = 0; if (editor.sampleFrom < 0x1F) { editor.sampleFrom++; ui.updateFromText = true; } } } break; case PTB_EO_FROM_DOWN: { if (mouse.repeatCounter >= 2) { mouse.repeatCounter = 0; if (editor.sampleFrom > 0x00) { editor.sampleFrom--; ui.updateFromText = true; } } } break; case PTB_EO_TO_UP: { if (mouse.repeatCounter >= 2) { mouse.repeatCounter = 0; if (editor.sampleTo < 0x1F) { editor.sampleTo++; ui.updateToText = true; } } } break; case PTB_EO_TO_DOWN: { if (mouse.repeatCounter >= 2) { mouse.repeatCounter = 0; if (editor.sampleTo > 0x00) { editor.sampleTo--; ui.updateToText = true; } } } break; case PTB_SAMPLEU: { if (mouse.repeatCounter >= 5) { mouse.repeatCounter = 0; if (!mouse.rightButtonPressed) sampleUpButton(); else ui.updateCurrSampleNum = true; } } break; case PTB_SAMPLED: { if (mouse.repeatCounter >= 5) { mouse.repeatCounter = 0; if (!mouse.rightButtonPressed) sampleDownButton(); else ui.updateCurrSampleNum = true; } } break; case PTB_FTUNEU: { if (mouse.repeatCounter >= 5) { mouse.repeatCounter = 0; sampleFineTuneUpButton(); } } break; case PTB_FTUNED: { if (mouse.repeatCounter >= 5) { mouse.repeatCounter = 0; sampleFineTuneDownButton(); } } break; case PTB_SVOLUMEU: { if (mouse.repeatCounter >= 5) { mouse.repeatCounter = 0; sampleVolumeUpButton(); } } break; case PTB_SVOLUMED: { if (mouse.repeatCounter >= 5) { mouse.repeatCounter = 0; sampleVolumeDownButton(); } } break; case PTB_SLENGTHU: { if (mouse.rightButtonPressed || mouse.repeatCounter >= 1) { mouse.repeatCounter = 0; sampleLengthUpButton(INCREMENT_FAST); } } break; case PTB_SLENGTHD: { if (mouse.rightButtonPressed || mouse.repeatCounter >= 1) { mouse.repeatCounter = 0; sampleLengthDownButton(INCREMENT_FAST); } } break; case PTB_SREPEATU: { if (mouse.rightButtonPressed || mouse.repeatCounter >= 1) { mouse.repeatCounter = 0; sampleRepeatUpButton(INCREMENT_FAST); } } break; case PTB_SREPEATD: { if (mouse.rightButtonPressed || mouse.repeatCounter >= 1) { mouse.repeatCounter = 0; sampleRepeatDownButton(INCREMENT_FAST); } } break; case PTB_SREPLENU: { if (mouse.rightButtonPressed || mouse.repeatCounter >= 1) { mouse.repeatCounter = 0; sampleRepeatLengthUpButton(INCREMENT_FAST); } } break; case PTB_SREPLEND: { if (mouse.rightButtonPressed || mouse.repeatCounter >= 1) { mouse.repeatCounter = 0; sampleRepeatLengthDownButton(INCREMENT_FAST); } } break; case PTB_TEMPOU: { if (mouse.repeatCounter >= 3) { mouse.repeatCounter = 0; tempoUpButton(); } } break; case PTB_TEMPOD: { if (mouse.repeatCounter >= 3) { mouse.repeatCounter = 0; tempoDownButton(); } } break; case PTB_LENGTHU: { if (mouse.repeatCounter >= 7) { mouse.repeatCounter = 0; songLengthUpButton(); } } break; case PTB_LENGTHD: { if (mouse.repeatCounter >= 7) { mouse.repeatCounter = 0; songLengthDownButton(); } } break; case PTB_PATTERNU: { if (mouse.repeatCounter >= 7) { mouse.repeatCounter = 0; patternUpButton(); } } break; case PTB_PATTERND: { if (mouse.repeatCounter >= 7) { mouse.repeatCounter = 0; patternDownButton(); } } break; case PTB_POSU: { if (mouse.repeatCounter >= 7) { mouse.repeatCounter = 0; positionUpButton(); } } break; case PTB_POSD: { if (mouse.repeatCounter >= 7) { mouse.repeatCounter = 0; positionDownButton(); } } break; case PTB_PE_SCROLLUP: { if (mouse.repeatCounter >= 2) { mouse.repeatCounter = 0; if (song->currOrder > 0) modSetPos(song->currOrder - 1, DONT_SET_ROW); } } break; case PTB_PE_SCROLLDOWN: { if (mouse.repeatCounter >= 2) { mouse.repeatCounter = 0; if (song->currOrder < song->header.numOrders-1) modSetPos(song->currOrder + 1, DONT_SET_ROW); } } break; case PTB_DO_SCROLLUP: { if (mouse.repeatCounter >= 1) { mouse.repeatCounter = 0; diskop.scrollOffset--; if (mouse.rightButtonPressed) diskop.scrollOffset -= 3; if (diskop.scrollOffset < 0) diskop.scrollOffset = 0; ui.updateDiskOpFileList = true; } } break; case PTB_DO_SCROLLDOWN: { if (mouse.repeatCounter >= 1) { mouse.repeatCounter = 0; if (diskop.numEntries > DISKOP_LINES) { diskop.scrollOffset++; if (mouse.rightButtonPressed) diskop.scrollOffset += 3; if (diskop.scrollOffset > diskop.numEntries-DISKOP_LINES) diskop.scrollOffset = diskop.numEntries-DISKOP_LINES; ui.updateDiskOpFileList = true; } } } break; case PTB_SA_ZOOMBARAREA: { if (mouse.repeatCounter >= 4) { mouse.repeatCounter = 0; if (!ui.forceSampleDrag) samplerBarPressed(MOUSE_BUTTON_NOT_HELD); } } break; default: break; } }