1 // for finding memory leaks in debug mode with Visual Studio
2 #if defined _DEBUG && defined _MSC_VER
3 #include <crtdbg.h>
4 #endif
5 
6 #include <stdint.h>
7 #include <stdbool.h>
8 #ifndef _WIN32
9 #include <unistd.h>
10 #endif
11 #include <stdio.h>
12 #include "pt2_header.h"
13 #include "pt2_mouse.h"
14 #include "pt2_helpers.h"
15 #include "pt2_diskop.h"
16 #include "pt2_sampler.h"
17 #include "pt2_module_loader.h"
18 #include "pt2_edit.h"
19 #include "pt2_sample_loader.h"
20 #include "pt2_visuals.h"
21 #include "pt2_tables.h"
22 #include "pt2_audio.h"
23 #include "pt2_textout.h"
24 #include "pt2_keyboard.h"
25 #include "pt2_config.h"
26 #include "pt2_bmp.h"
27 #include "pt2_sampling.h"
28 #include "pt2_chordmaker.h"
29 
30 /* TODO: Move irrelevant routines outta here! Disgusting design!
31 ** Keep in mind that this was programmed in my early programming days...
32 **/
33 
34 SDL_Cursor *cursors[NUM_CURSORS];
35 
36 void edNote1UpButton(void);
37 void edNote1DownButton(void);
38 void edNote2UpButton(void);
39 void edNote2DownButton(void);
40 void edNote3UpButton(void);
41 void edNote3DownButton(void);
42 void edNote4UpButton(void);
43 void edNote4DownButton(void);
44 void edPosUpButton(bool fast);
45 void edPosDownButton(bool fast);
46 void edModUpButton(void);
47 void edModDownButton(void);
48 void edVolUpButton(void);
49 void edVolDownButton(void);
50 void sampleUpButton(void);
51 void sampleDownButton(void);
52 void sampleFineTuneUpButton(void);
53 void sampleFineTuneDownButton(void);
54 void sampleVolumeUpButton(void);
55 void sampleVolumeDownButton(void);
56 void sampleLengthUpButton(bool fast);
57 void sampleLengthDownButton(bool fast);
58 void sampleRepeatUpButton(bool fast);
59 void sampleRepeatDownButton(bool fast);
60 void sampleRepeatLengthUpButton(bool fast);
61 void sampleRepeatLengthDownButton(bool fast);
62 void tempoUpButton(void);
63 void tempoDownButton(void);
64 void songLengthUpButton(void);
65 void songLengthDownButton(void);
66 void patternUpButton(void);
67 void patternDownButton(void);
68 void positionUpButton(void);
69 void positionDownButton(void);
70 void handleSamplerVolumeBox(void);
71 
72 int32_t checkGUIButtons(void);
73 void handleTextEditing(uint8_t mouseButton);
74 bool handleRightMouseButton(void);
75 bool handleLeftMouseButton(void);
76 static bool handleGUIButtons(int32_t button);
77 static void handleRepeatedGUIButtons(void);
78 static void handleRepeatedSamplerFilterButtons(void);
79 
pointerSetColor(uint8_t cursorColorIndex)80 static void pointerSetColor(uint8_t cursorColorIndex)
81 {
82 	assert(cursorColorIndex <= 5);
83 
84 	video.palette[PAL_MOUSE_1] = cursorColors[cursorColorIndex][0];
85 	video.palette[PAL_MOUSE_2] = cursorColors[cursorColorIndex][1];
86 	video.palette[PAL_MOUSE_3] = cursorColors[cursorColorIndex][2];
87 
88 	if (config.hwMouse)
89 		setSystemCursor(cursors[cursorColorIndex]);
90 }
91 
pointerSetMode(uint8_t pointerMode,bool carry)92 void pointerSetMode(uint8_t pointerMode, bool carry)
93 {
94 	assert(pointerMode <= 5);
95 
96 	ui.pointerMode = pointerMode;
97 	if (carry)
98 		ui.previousPointerMode = ui.pointerMode;
99 
100 	switch (pointerMode)
101 	{
102 		case POINTER_MODE_IDLE:   pointerSetColor(POINTER_GRAY);   break;
103 		case POINTER_MODE_PLAY:   pointerSetColor(POINTER_YELLOW); break;
104 		case POINTER_MODE_EDIT:   pointerSetColor(POINTER_BLUE);   break;
105 		case POINTER_MODE_RECORD: pointerSetColor(POINTER_BLUE);   break;
106 		case POINTER_MODE_MSG1:   pointerSetColor(POINTER_PURPLE); break;
107 		case POINTER_MODE_MSG2:   pointerSetColor(POINTER_GREEN);  break;
108 		default: break;
109 	}
110 }
111 
pointerResetThreadSafe(void)112 void pointerResetThreadSafe(void) // used for effect F00 in replayer (stop song)
113 {
114 	ui.previousPointerMode = ui.pointerMode = POINTER_MODE_IDLE;
115 
116 	if (config.hwMouse)
117 		mouse.resetCursorColorFlag = true;
118 }
119 
pointerSetPreviousMode(void)120 void pointerSetPreviousMode(void)
121 {
122 	if (ui.editTextFlag || ui.askScreenShown || ui.clearScreenShown)
123 		pointerSetMode(POINTER_MODE_MSG1, NO_CARRY);
124 	else
125 		pointerSetMode(ui.previousPointerMode, NO_CARRY);
126 }
127 
setMsgPointer(void)128 void setMsgPointer(void)
129 {
130 	pointerSetMode(POINTER_MODE_MSG2, false);
131 }
132 
setErrPointer(void)133 void setErrPointer(void)
134 {
135 	pointerSetColor(POINTER_RED);
136 }
137 
setSystemCursor(SDL_Cursor * cur)138 bool setSystemCursor(SDL_Cursor *cur)
139 {
140 	if (cur == NULL)
141 	{
142 		SDL_SetCursor(SDL_GetDefaultCursor());
143 		return false;
144 	}
145 
146 	SDL_SetCursor(cur);
147 	return true;
148 }
149 
freeMouseCursors(void)150 void freeMouseCursors(void)
151 {
152 	SDL_SetCursor(SDL_GetDefaultCursor());
153 	for (uint32_t i = 0; i < NUM_CURSORS; i++)
154 	{
155 		if (cursors[i] != NULL)
156 		{
157 			SDL_FreeCursor(cursors[i]);
158 			cursors[i] = NULL;
159 		}
160 	}
161 }
162 
createMouseCursors(void)163 bool createMouseCursors(void) // creates scaled SDL surfaces for current mouse pointer shape
164 {
165 	freeMouseCursors();
166 
167 	const uint32_t scaleFactor = video.yScale;
168 
169 	for (uint32_t i = 0; i < NUM_CURSORS; i++)
170 	{
171 		SDL_Surface *surface = SDL_CreateRGBSurface(0, POINTER_W*scaleFactor, POINTER_H*scaleFactor, 32, 0, 0, 0, 0);
172 		if (surface == NULL)
173 		{
174 			freeMouseCursors();
175 			config.hwMouse = false; // enable software mouse
176 			return false;
177 		}
178 
179 		uint32_t color1 = cursorColors[i][0];
180 		uint32_t color2 = cursorColors[i][1];
181 		uint32_t color3 = cursorColors[i][2];
182 		uint32_t colorkey = 0x12345678;
183 
184 		color1 = SDL_MapRGB(surface->format, R24(color1), G24(color1), B24(color1));
185 		color2 = SDL_MapRGB(surface->format, R24(color2), G24(color2), B24(color2));
186 		color3 = SDL_MapRGB(surface->format, R24(color3), G24(color3), B24(color3));
187 		colorkey = SDL_MapRGB(surface->format, R24(colorkey), G24(colorkey), B24(colorkey));
188 
189 		SDL_SetSurfaceBlendMode(surface, SDL_BLENDMODE_NONE);
190 		SDL_SetColorKey(surface, SDL_TRUE, colorkey);
191 		SDL_SetSurfaceRLE(surface, SDL_TRUE);
192 
193 		const uint8_t *srcPixels8 = mousePointerBMP;
194 		SDL_LockSurface(surface);
195 
196 		uint32_t *dstPixels32 = (uint32_t *)surface->pixels;
197 		for (int32_t k = 0; k < surface->w*surface->h; k++) // fill surface with colorkey pixels
198 			dstPixels32[k] = colorkey;
199 
200 		// blit upscaled cursor to surface
201 		for (uint32_t y = 0; y < POINTER_H; y++)
202 		{
203 			uint32_t *outX = &dstPixels32[(y * scaleFactor) * surface->w];
204 			for (uint32_t yScale = 0; yScale < scaleFactor; yScale++)
205 			{
206 				for (uint32_t x = 0; x < POINTER_W; x++)
207 				{
208 					uint8_t srcPix = srcPixels8[(y * POINTER_W) + x];
209 					if (srcPix != PAL_COLORKEY)
210 					{
211 						uint32_t pixel = colorkey; // make compiler happy
212 
213 						     if (srcPix == PAL_MOUSE_1) pixel = color1;
214 						else if (srcPix == PAL_MOUSE_2) pixel = color2;
215 						else if (srcPix == PAL_MOUSE_3) pixel = color3;
216 
217 						for (uint32_t xScale = 0; xScale < scaleFactor; xScale++)
218 							outX[xScale] = pixel;
219 					}
220 
221 					outX += scaleFactor;
222 				}
223 			}
224 		}
225 
226 		SDL_UnlockSurface(surface);
227 
228 		cursors[i] = SDL_CreateColorCursor(surface, 0, 0);
229 		if (cursors[i] == NULL)
230 		{
231 			SDL_FreeSurface(surface);
232 			freeMouseCursors();
233 			config.hwMouse = false; // enable software mouse
234 			return false;
235 		}
236 
237 		SDL_FreeSurface(surface);
238 	}
239 
240 	pointerSetPreviousMode(); // this sets the appropriate the hardware cursor
241 	return true;
242 }
243 
updateMouseScaling(void)244 void updateMouseScaling(void)
245 {
246 	if (video.renderW > 0) video.fMouseXMul = (float)SCREEN_W / video.renderW;
247 	if (video.renderH > 0) video.fMouseYMul = (float)SCREEN_H / video.renderH;
248 }
249 
readMouseXY(void)250 void readMouseXY(void)
251 {
252 	int32_t mx, my, windowX, windowY;
253 
254 	if (mouse.resetCursorColorFlag) // used for effect F00 in replayer (stop song)
255 	{
256 		mouse.resetCursorColorFlag = false;
257 		pointerSetColor(POINTER_GRAY);
258 	}
259 
260 	if (mouse.setPosFlag)
261 	{
262 		if (!video.windowHidden)
263 			SDL_WarpMouseInWindow(video.window, mouse.setPosX, mouse.setPosY);
264 
265 		mouse.setPosFlag = false;
266 		return;
267 	}
268 
269 	if (video.useDesktopMouseCoords)
270 	{
271 		mouse.buttonState = SDL_GetGlobalMouseState(&mx, &my);
272 
273 		// convert desktop coords to window coords
274 		SDL_GetWindowPosition(video.window, &windowX, &windowY);
275 		mx -= windowX;
276 		my -= windowY;
277 	}
278 	else
279 	{
280 		mouse.buttonState = SDL_GetMouseState(&mx, &my);
281 	}
282 
283 	if (video.fullscreen)
284 	{
285 		// centered fullscreen mode (not stretched) needs further coord translation
286 		if (!config.fullScreenStretch)
287 		{
288 			// if software mouse is enabled, warp mouse inside render space
289 			if (!config.hwMouse)
290 			{
291 				bool warpMouse = false;
292 
293 				if (mx < video.renderX)
294 				{
295 					mx = video.renderX;
296 					warpMouse = true;
297 				}
298 				else if (mx >= video.renderX+video.renderW)
299 				{
300 					mx = (video.renderX + video.renderW) - 1;
301 					warpMouse = true;
302 				}
303 
304 				if (my < video.renderY)
305 				{
306 					my = video.renderY;
307 					warpMouse = true;
308 				}
309 				else if (my >= video.renderY+video.renderH)
310 				{
311 					my = (video.renderY + video.renderH) - 1;
312 					warpMouse = true;
313 				}
314 
315 				if (warpMouse)
316 					SDL_WarpMouseInWindow(video.window, mx, my);
317 			}
318 
319 			// convert fullscreen coords to window (centered image) coords
320 			mx -= video.renderX;
321 			my -= video.renderY;
322 		}
323 	}
324 
325 	// multiply coords by video upscaling factors (don't round)
326 	mouse.x = (int32_t)(mx * video.fMouseXMul);
327 	mouse.y = (int32_t)(my * video.fMouseYMul);
328 
329 	if (config.hwMouse)
330 	{
331 		// hardware mouse mode (OS)
332 		hideSprite(SPRITE_MOUSE_POINTER);
333 	}
334 	else
335 	{
336 		// software mouse mode (PT mouse)
337 		setSpritePos(SPRITE_MOUSE_POINTER, mouse.x, mouse.y);
338 	}
339 }
340 
mouseButtonUpHandler(uint8_t mouseButton)341 void mouseButtonUpHandler(uint8_t mouseButton)
342 {
343 	mouse.buttonWaitCounter = 0;
344 	mouse.buttonWaiting = false;
345 
346 	if (mouseButton == SDL_BUTTON_LEFT)
347 	{
348 		mouse.leftButtonPressed = false;
349 		ui.forceSampleDrag = false;
350 		ui.forceVolDrag = false;
351 		ui.leftLoopPinMoving = false;
352 		ui.rightLoopPinMoving = false;
353 		ui.sampleMarkingPos = -1;
354 
355 		switch (mouse.lastGUIButton)
356 		{
357 			case PTB_SLENGTHU:
358 			case PTB_SLENGTHD:
359 			{
360 				if (ui.samplerScreenShown)
361 					redrawSample();
362 
363 				recalcChordLength();
364 				updateSamplePos();
365 
366 				ui.updateSongSize = true;
367 			}
368 			break;
369 
370 			case PTB_LENGTHU:
371 			case PTB_LENGTHD:
372 			case PTB_PATTERNU:
373 			case PTB_PATTERND:
374 			{
375 				ui.updateSongSize = true;
376 				if (ui.posEdScreenShown)
377 					ui.updatePosEd = true;
378 			}
379 			break;
380 
381 			default:
382 				break;
383 		}
384 
385 		mouse.lastGUIButton = -1;
386 		mouse.lastSmpFilterButton = -1;
387 		mouse.lastSamplingButton = -1;
388 	}
389 
390 	if (mouseButton == SDL_BUTTON_RIGHT)
391 	{
392 		mouse.rightButtonPressed = false;
393 		ui.forceSampleEdit = false;
394 	}
395 }
396 
mouseButtonDownHandler(uint8_t mouseButton)397 void mouseButtonDownHandler(uint8_t mouseButton)
398 {
399 	if (mouseButton == SDL_BUTTON_LEFT)
400 	{
401 		mouse.leftButtonPressed = true;
402 		mouse.buttonWaiting = true;
403 	}
404 
405 	if (mouseButton == SDL_BUTTON_RIGHT)
406 		mouse.rightButtonPressed = true;
407 
408 	// when red mouse pointer (error), block further input for a while
409 	if (editor.errorMsgActive && editor.errorMsgBlock)
410 		return;
411 
412 	if (handleRightMouseButton() || handleLeftMouseButton())
413 		return;
414 
415 	handleTextEditing(mouseButton);
416 }
417 
handleGUIButtonRepeat(void)418 void handleGUIButtonRepeat(void)
419 {
420 	if (!mouse.leftButtonPressed)
421 	{
422 		// left mouse button released, stop repeating buttons
423 		mouse.repeatCounter = 0;
424 		return;
425 	}
426 
427 	if (ui.samplerFiltersBoxShown)
428 	{
429 		handleRepeatedSamplerFilterButtons();
430 		return;
431 	}
432 
433 	if (ui.samplingBoxShown)
434 	{
435 		handleRepeatedSamplingButtons();
436 		return;
437 	}
438 
439 	if (mouse.lastGUIButton != checkGUIButtons()) // FIXME: This can potentially do a ton of iterations, bad design!
440 	{
441 		// only repeat the button that was first clicked (e.g. if you hold and move mouse to another button)
442 		mouse.repeatCounter = 0;
443 		return;
444 	}
445 
446 	handleRepeatedGUIButtons();
447 	mouse.repeatCounter++;
448 }
449 
edNote1UpButton(void)450 void edNote1UpButton(void)
451 {
452 	if (mouse.rightButtonPressed)
453 		editor.note1 += 12;
454 	else
455 		editor.note1++;
456 
457 	if (editor.note1 > 36)
458 		editor.note1 = 36;
459 
460 	ui.updateNote1Text = true;
461 	recalcChordLength();
462 }
463 
edNote1DownButton(void)464 void edNote1DownButton(void)
465 {
466 	if (mouse.rightButtonPressed)
467 		editor.note1 -= 12;
468 	else
469 		editor.note1--;
470 
471 	if (editor.note1 < 0)
472 		editor.note1 = 0;
473 
474 	ui.updateNote1Text = true;
475 	recalcChordLength();
476 }
477 
edNote2UpButton(void)478 void edNote2UpButton(void)
479 {
480 	if (mouse.rightButtonPressed)
481 		editor.note2 += 12;
482 	else
483 		editor.note2++;
484 
485 	if (editor.note2 > 36)
486 		editor.note2 = 36;
487 
488 	ui.updateNote2Text = true;
489 	recalcChordLength();
490 }
491 
edNote2DownButton(void)492 void edNote2DownButton(void)
493 {
494 	if (mouse.rightButtonPressed)
495 		editor.note2 -= 12;
496 	else
497 		editor.note2--;
498 
499 	if (editor.note2 < 0)
500 		editor.note2 = 0;
501 
502 	ui.updateNote2Text = true;
503 	recalcChordLength();
504 }
505 
edNote3UpButton(void)506 void edNote3UpButton(void)
507 {
508 	if (mouse.rightButtonPressed)
509 		editor.note3 += 12;
510 	else
511 		editor.note3++;
512 
513 	if (editor.note3 > 36)
514 		editor.note3 = 36;
515 
516 	ui.updateNote3Text = true;
517 	recalcChordLength();
518 }
519 
edNote3DownButton(void)520 void edNote3DownButton(void)
521 {
522 	if (mouse.rightButtonPressed)
523 		editor.note3 -= 12;
524 	else
525 		editor.note3--;
526 
527 	if (editor.note3 < 0)
528 		editor.note3 = 0;
529 
530 	ui.updateNote3Text = true;
531 	recalcChordLength();
532 }
533 
edNote4UpButton(void)534 void edNote4UpButton(void)
535 {
536 	if (mouse.rightButtonPressed)
537 		editor.note4 += 12;
538 	else
539 		editor.note4++;
540 
541 	if (editor.note4 > 36)
542 		editor.note4 = 36;
543 
544 	ui.updateNote4Text = true;
545 	recalcChordLength();
546 }
547 
edNote4DownButton(void)548 void edNote4DownButton(void)
549 {
550 	if (mouse.rightButtonPressed)
551 		editor.note4 -= 12;
552 	else
553 		editor.note4--;
554 
555 	if (editor.note4 < 0)
556 		editor.note4 = 0;
557 
558 	ui.updateNote4Text = true;
559 	recalcChordLength();
560 }
561 
edPosUpButton(bool fast)562 void edPosUpButton(bool fast)
563 {
564 	if (mouse.rightButtonPressed)
565 	{
566 		if (fast)
567 		{
568 			if (editor.samplePos <= 0xFFFF-64)
569 				editor.samplePos += 64;
570 			else
571 				editor.samplePos = 0xFFFF;
572 		}
573 		else
574 		{
575 			if (editor.samplePos <= 0xFFFF-16)
576 				editor.samplePos += 16;
577 			else
578 				editor.samplePos = 0xFFFF;
579 		}
580 	}
581 	else
582 	{
583 		if (fast)
584 		{
585 			if (editor.samplePos <= 0xFFFF-64)
586 				editor.samplePos += 64;
587 			else
588 				editor.samplePos = 0xFFFF;
589 		}
590 		else
591 		{
592 			if (editor.samplePos < 0xFFFF)
593 				editor.samplePos++;
594 			else
595 				editor.samplePos = 0xFFFF;
596 		}
597 	}
598 
599 	if (editor.samplePos > song->samples[editor.currSample].length)
600 		editor.samplePos = song->samples[editor.currSample].length;
601 
602 	ui.updatePosText = true;
603 }
604 
edPosDownButton(bool fast)605 void edPosDownButton(bool fast)
606 {
607 	if (mouse.rightButtonPressed)
608 	{
609 		if (fast)
610 		{
611 			if (editor.samplePos > 64)
612 				editor.samplePos -= 64;
613 			else
614 				editor.samplePos = 0;
615 		}
616 		else
617 		{
618 			if (editor.samplePos > 16)
619 				editor.samplePos -= 16;
620 			else
621 				editor.samplePos = 0;
622 		}
623 	}
624 	else
625 	{
626 		if (fast)
627 		{
628 			if (editor.samplePos > 64)
629 				editor.samplePos -= 64;
630 			else
631 				editor.samplePos = 0;
632 		}
633 		else
634 		{
635 			if (editor.samplePos > 0)
636 				editor.samplePos--;
637 			else
638 				editor.samplePos = 0;
639 		}
640 	}
641 
642 	ui.updatePosText = true;
643 }
644 
edModUpButton(void)645 void edModUpButton(void)
646 {
647 	if (mouse.rightButtonPressed)
648 		editor.modulateSpeed += 10;
649 	else
650 		editor.modulateSpeed++;
651 
652 	if (editor.modulateSpeed > 127)
653 		editor.modulateSpeed = 127;
654 
655 	ui.updateModText = true;
656 }
657 
edModDownButton(void)658 void edModDownButton(void)
659 {
660 	if (mouse.rightButtonPressed)
661 	{
662 		editor.modulateSpeed -= 10;
663 	}
664 	else
665 	{
666 		editor.modulateSpeed--;
667 	}
668 
669 	if (editor.modulateSpeed < -128)
670 		editor.modulateSpeed = -128;
671 
672 	ui.updateModText = true;
673 }
674 
edVolUpButton(void)675 void edVolUpButton(void)
676 {
677 	if (mouse.rightButtonPressed)
678 	{
679 		if (editor.sampleVol <= 999-10)
680 			editor.sampleVol += 10;
681 		else
682 			editor.sampleVol = 999;
683 	}
684 	else
685 	{
686 		if (editor.sampleVol < 999)
687 			editor.sampleVol++;
688 	}
689 
690 	ui.updateVolText = true;
691 }
692 
edVolDownButton(void)693 void edVolDownButton(void)
694 {
695 	if (mouse.rightButtonPressed)
696 	{
697 		if (editor.sampleVol >= 10)
698 			editor.sampleVol -= 10;
699 		else
700 			editor.sampleVol = 0;
701 	}
702 	else
703 	{
704 		if (editor.sampleVol > 0)
705 			editor.sampleVol--;
706 	}
707 
708 	ui.updateVolText = true;
709 }
710 
sampleUpButton(void)711 void sampleUpButton(void)
712 {
713 	if (editor.sampleZero)
714 	{
715 		editor.sampleZero = false;
716 		editor.currSample = 0;
717 	}
718 	else if (editor.currSample < 30)
719 	{
720 		editor.currSample++;
721 	}
722 
723 	updateCurrSample();
724 }
725 
sampleDownButton(void)726 void sampleDownButton(void)
727 {
728 	if (!editor.sampleZero && editor.currSample > 0)
729 	{
730 		editor.currSample--;
731 		updateCurrSample();
732 	}
733 }
734 
sampleFineTuneUpButton(void)735 void sampleFineTuneUpButton(void)
736 {
737 	int8_t finetune = song->samples[editor.currSample].fineTune & 0xF;
738 	if (finetune != 7)
739 		song->samples[editor.currSample].fineTune = (finetune + 1) & 0xF;
740 
741 	if (mouse.rightButtonPressed)
742 		song->samples[editor.currSample].fineTune = 0;
743 
744 	recalcChordLength();
745 	ui.updateCurrSampleFineTune = true;
746 }
747 
sampleFineTuneDownButton(void)748 void sampleFineTuneDownButton(void)
749 {
750 	int8_t finetune = song->samples[editor.currSample].fineTune & 0xF;
751 	if (finetune != 8)
752 		song->samples[editor.currSample].fineTune = (finetune - 1) & 0xF;
753 
754 	if (mouse.rightButtonPressed)
755 		song->samples[editor.currSample].fineTune = 0;
756 
757 	recalcChordLength();
758 	ui.updateCurrSampleFineTune = true;
759 }
760 
sampleVolumeUpButton(void)761 void sampleVolumeUpButton(void)
762 {
763 	int8_t val = song->samples[editor.currSample].volume;
764 
765 	if (mouse.rightButtonPressed)
766 		val += 16;
767 	else
768 		val++;
769 
770 	if (val > 64)
771 		val = 64;
772 
773 	song->samples[editor.currSample].volume = (uint8_t)val;
774 	ui.updateCurrSampleVolume = true;
775 }
776 
sampleVolumeDownButton(void)777 void sampleVolumeDownButton(void)
778 {
779 	int8_t val = song->samples[editor.currSample].volume;
780 
781 	if (mouse.rightButtonPressed)
782 		val -= 16;
783 	else
784 		val--;
785 
786 	if (val < 0)
787 		val = 0;
788 
789 	song->samples[editor.currSample].volume = (uint8_t)val;
790 	ui.updateCurrSampleVolume = true;
791 }
792 
sampleLengthUpButton(bool fast)793 void sampleLengthUpButton(bool fast)
794 {
795 	int32_t val;
796 
797 	if (song->samples[editor.currSample].length == MAX_SAMPLE_LEN)
798 		return;
799 
800 	val = song->samples[editor.currSample].length;
801 	if (mouse.rightButtonPressed)
802 	{
803 		if (fast)
804 			val += 64;
805 		else
806 			val += 16;
807 	}
808 	else
809 	{
810 		if (fast)
811 			val += 10;
812 		else
813 			val += 2;
814 	}
815 
816 	if (val > MAX_SAMPLE_LEN)
817 		val = MAX_SAMPLE_LEN;
818 
819 	song->samples[editor.currSample].length = (uint16_t)val;
820 	ui.updateCurrSampleLength = true;
821 }
822 
sampleLengthDownButton(bool fast)823 void sampleLengthDownButton(bool fast)
824 {
825 	int32_t val;
826 	moduleSample_t *s;
827 
828 	s = &song->samples[editor.currSample];
829 	if (s->loopStart+s->loopLength > 2)
830 	{
831 		if (s->length == s->loopStart+s->loopLength)
832 			return;
833 	}
834 	else
835 	{
836 		if (s->length == 0)
837 			return;
838 	}
839 
840 	val = song->samples[editor.currSample].length;
841 	if (mouse.rightButtonPressed)
842 	{
843 		if (fast)
844 			val -= 64;
845 		else
846 			val -= 16;
847 	}
848 	else
849 	{
850 		if (fast)
851 			val -= 10;
852 		else
853 			val -= 2;
854 	}
855 
856 	if (val < 0)
857 		val = 0;
858 
859 	if (s->loopStart+s->loopLength > 2)
860 	{
861 		if (val < s->loopStart+s->loopLength)
862 			val = s->loopStart+s->loopLength;
863 	}
864 
865 	s->length = (uint16_t)val;
866 
867 	ui.updateCurrSampleLength = true;
868 }
869 
sampleRepeatUpButton(bool fast)870 void sampleRepeatUpButton(bool fast)
871 {
872 	int32_t val, loopLen, len;
873 
874 	val = song->samples[editor.currSample].loopStart;
875 	loopLen = song->samples[editor.currSample].loopLength;
876 	len = song->samples[editor.currSample].length;
877 
878 	if (len == 0)
879 	{
880 		song->samples[editor.currSample].loopStart = 0;
881 		return;
882 	}
883 
884 	if (mouse.rightButtonPressed)
885 	{
886 		if (fast)
887 			val += 64;
888 		else
889 			val += 16;
890 	}
891 	else
892 	{
893 		if (fast)
894 			val += 10;
895 		else
896 			val += 2;
897 	}
898 
899 	if (val > len-loopLen)
900 		val = len-loopLen;
901 
902 	song->samples[editor.currSample].loopStart = (uint16_t)val;
903 	ui.updateCurrSampleRepeat = true;
904 
905 	mixerUpdateLoops();
906 
907 	if (ui.samplerScreenShown)
908 		setLoopSprites();
909 
910 	if (ui.editOpScreenShown && ui.editOpScreen == 3) // sample chord editor
911 		ui.updateLengthText = true;
912 }
913 
sampleRepeatDownButton(bool fast)914 void sampleRepeatDownButton(bool fast)
915 {
916 	int32_t val, len;
917 
918 	val = song->samples[editor.currSample].loopStart;
919 	len = song->samples[editor.currSample].length;
920 
921 	if (len == 0)
922 	{
923 		song->samples[editor.currSample].loopStart = 0;
924 		return;
925 	}
926 
927 	if (mouse.rightButtonPressed)
928 	{
929 		if (fast)
930 			val -= 64;
931 		else
932 			val -= 16;
933 	}
934 	else
935 	{
936 		if (fast)
937 			val -= 10;
938 		else
939 			val -= 2;
940 	}
941 
942 	if (val < 0)
943 		val = 0;
944 
945 	song->samples[editor.currSample].loopStart = (uint16_t)val;
946 	ui.updateCurrSampleRepeat = true;
947 
948 	mixerUpdateLoops();
949 
950 	if (ui.samplerScreenShown)
951 		setLoopSprites();
952 
953 	if (ui.editOpScreenShown && ui.editOpScreen == 3) // sample chord editor
954 		ui.updateLengthText = true;
955 }
956 
sampleRepeatLengthUpButton(bool fast)957 void sampleRepeatLengthUpButton(bool fast)
958 {
959 	int32_t val, loopStart, len;
960 
961 	val = song->samples[editor.currSample].loopLength;
962 	loopStart = song->samples[editor.currSample].loopStart;
963 	len = song->samples[editor.currSample].length;
964 
965 	if (len == 0)
966 	{
967 		song->samples[editor.currSample].loopLength = 2;
968 		return;
969 	}
970 
971 	if (mouse.rightButtonPressed)
972 	{
973 		if (fast)
974 			val += 64;
975 		else
976 			val += 16;
977 	}
978 	else
979 	{
980 		if (fast)
981 			val += 10;
982 		else
983 			val += 2;
984 	}
985 
986 	if (val > len-loopStart)
987 		val = len-loopStart;
988 
989 	song->samples[editor.currSample].loopLength = (uint16_t)val;
990 	ui.updateCurrSampleReplen = true;
991 
992 	mixerUpdateLoops();
993 
994 	if (ui.samplerScreenShown)
995 		setLoopSprites();
996 
997 	if (ui.editOpScreenShown && ui.editOpScreen == 3) // sample chord editor
998 		ui.updateLengthText = true;
999 }
1000 
sampleRepeatLengthDownButton(bool fast)1001 void sampleRepeatLengthDownButton(bool fast)
1002 {
1003 	int32_t val, len;
1004 
1005 	val = song->samples[editor.currSample].loopLength;
1006 	len = song->samples[editor.currSample].length;
1007 
1008 	if (len == 0)
1009 	{
1010 		song->samples[editor.currSample].loopLength = 2;
1011 		return;
1012 	}
1013 
1014 	if (mouse.rightButtonPressed)
1015 	{
1016 		if (fast)
1017 			val -= 64;
1018 		else
1019 			val -= 16;
1020 	}
1021 	else
1022 	{
1023 		if (fast)
1024 			val -= 10;
1025 		else
1026 			val -= 2;
1027 	}
1028 
1029 	if (val < 2)
1030 		val = 2;
1031 
1032 	song->samples[editor.currSample].loopLength = (uint16_t)val;
1033 	ui.updateCurrSampleReplen = true;
1034 
1035 	mixerUpdateLoops();
1036 
1037 	if (ui.samplerScreenShown)
1038 		setLoopSprites();
1039 
1040 	if (ui.editOpScreenShown && ui.editOpScreen == 3) // sample chord editor
1041 		ui.updateLengthText = true;
1042 }
1043 
tempoUpButton(void)1044 void tempoUpButton(void)
1045 {
1046 	int32_t val;
1047 
1048 	if (editor.timingMode == TEMPO_MODE_VBLANK)
1049 		return;
1050 
1051 	val = song->currBPM;
1052 	if (mouse.rightButtonPressed)
1053 		val += 10;
1054 	else
1055 		val++;
1056 
1057 	if (val > 255)
1058 		val = 255;
1059 
1060 	song->currBPM = val;
1061 	modSetTempo(song->currBPM, true);
1062 	ui.updateSongBPM = true;
1063 }
1064 
tempoDownButton(void)1065 void tempoDownButton(void)
1066 {
1067 	int32_t val;
1068 
1069 	if (editor.timingMode == TEMPO_MODE_VBLANK)
1070 		return;
1071 
1072 	val = song->currBPM;
1073 	if (mouse.rightButtonPressed)
1074 		val -= 10;
1075 	else
1076 		val--;
1077 
1078 	if (val < 32)
1079 		val = 32;
1080 
1081 	song->currBPM = val;
1082 	modSetTempo(song->currBPM, true);
1083 	ui.updateSongBPM = true;
1084 }
1085 
songLengthUpButton(void)1086 void songLengthUpButton(void)
1087 {
1088 	int16_t val;
1089 
1090 	val = song->header.numOrders;
1091 	if (mouse.rightButtonPressed)
1092 		val += 10;
1093 	else
1094 		val++;
1095 
1096 	if (val > 128)
1097 		val = 128;
1098 
1099 	song->header.numOrders = (uint8_t)val;
1100 
1101 	val = song->currOrder;
1102 	if (val > song->header.numOrders-1)
1103 		val = song->header.numOrders-1;
1104 
1105 	editor.currPosEdPattDisp = &song->header.order[val];
1106 	ui.updateSongLength = true;
1107 }
1108 
songLengthDownButton(void)1109 void songLengthDownButton(void)
1110 {
1111 	int16_t val = song->header.numOrders;
1112 
1113 	if (mouse.rightButtonPressed)
1114 		val -= 10;
1115 	else
1116 		val--;
1117 
1118 	if (val < 1)
1119 		val = 1;
1120 
1121 	song->header.numOrders = (uint8_t)val;
1122 
1123 	val = song->currOrder;
1124 	if (val > song->header.numOrders-1)
1125 		val = song->header.numOrders-1;
1126 
1127 	editor.currPosEdPattDisp = &song->header.order[val];
1128 	ui.updateSongLength = true;
1129 }
1130 
patternUpButton(void)1131 void patternUpButton(void)
1132 {
1133 	int16_t val = song->header.order[song->currOrder];
1134 
1135 	if (mouse.rightButtonPressed)
1136 		val += 10;
1137 	else
1138 		val++;
1139 
1140 	if (val > MAX_PATTERNS-1)
1141 		val = MAX_PATTERNS-1;
1142 
1143 	song->header.order[song->currOrder] = (uint8_t)val;
1144 
1145 	if (ui.posEdScreenShown)
1146 		ui.updatePosEd = true;
1147 
1148 	ui.updateSongPattern = true;
1149 }
1150 
patternDownButton(void)1151 void patternDownButton(void)
1152 {
1153 	int16_t val = song->header.order[song->currOrder];
1154 
1155 	if (mouse.rightButtonPressed)
1156 		val -= 10;
1157 	else
1158 		val--;
1159 
1160 	if (val < 0)
1161 		val = 0;
1162 
1163 	song->header.order[song->currOrder] = (uint8_t)val;
1164 
1165 	if (ui.posEdScreenShown)
1166 		ui.updatePosEd = true;
1167 
1168 	ui.updateSongPattern = true;
1169 }
1170 
positionUpButton(void)1171 void positionUpButton(void)
1172 {
1173 	int16_t val = song->currOrder;
1174 
1175 	if (mouse.rightButtonPressed)
1176 		val += 10;
1177 	else
1178 		val++;
1179 
1180 	if (val > 127)
1181 		val = 127;
1182 
1183 	modSetPos(val, DONT_SET_ROW);
1184 }
1185 
positionDownButton(void)1186 void positionDownButton(void)
1187 {
1188 	int16_t val = song->currOrder;
1189 
1190 	if (mouse.rightButtonPressed)
1191 		val -= 10;
1192 	else
1193 		val--;
1194 
1195 	if (val < 0)
1196 		val = 0;
1197 
1198 	modSetPos(val, DONT_SET_ROW);
1199 }
1200 
handleSamplerVolumeBox(void)1201 void handleSamplerVolumeBox(void)
1202 {
1203 	int8_t *sampleData;
1204 	uint8_t i;
1205 	int16_t sample, sampleVol;
1206 	int32_t smp32, sampleIndex, sampleLength;
1207 	double dSmp;
1208 	moduleSample_t *s;
1209 
1210 	if (mouse.rightButtonPressed)
1211 	{
1212 		if (ui.editTextFlag)
1213 		{
1214 			exitGetTextLine(EDIT_TEXT_NO_UPDATE);
1215 		}
1216 		else
1217 		{
1218 			ui.samplerVolBoxShown = false;
1219 			removeSamplerVolBox();
1220 		}
1221 
1222 		return;
1223 	}
1224 
1225 	if (ui.editTextFlag)
1226 		return;
1227 
1228 	// check buttons
1229 	if (mouse.leftButtonPressed)
1230 	{
1231 		// restore sample ask dialog
1232 		if (ui.askScreenShown && ui.askScreenType == ASK_RESTORE_SAMPLE)
1233 		{
1234 			if (mouse.y >= 71 && mouse.y <= 81)
1235 			{
1236 				if (mouse.x >= 171 && mouse.x <= 196)
1237 				{
1238 					// YES button
1239 					ui.askScreenShown = false;
1240 					ui.answerNo = false;
1241 					ui.answerYes = true;
1242 					handleAskYes();
1243 				}
1244 				else if (mouse.x >= 234 && mouse.x <= 252)
1245 				{
1246 					// NO button
1247 					ui.askScreenShown = false;
1248 					ui.answerNo = true;
1249 					ui.answerYes = false;
1250 					handleAskNo();
1251 				}
1252 			}
1253 
1254 			return;
1255 		}
1256 
1257 		// MAIN SCREEN STOP
1258 		if (!ui.diskOpScreenShown && !ui.posEdScreenShown)
1259 		{
1260 			if (mouse.x >= 182 && mouse.x <= 243 && mouse.y >= 0 && mouse.y <= 10)
1261 			{
1262 				modStop();
1263 				return;
1264 			}
1265 		}
1266 
1267 		if (mouse.x >= 32 && mouse.x <= 95)
1268 		{
1269 			// SAMPLER SCREEN PLAY WAVEFORM
1270 			if (mouse.y >= 211 && mouse.y <= 221)
1271 			{
1272 				samplerPlayWaveform();
1273 				return;
1274 			}
1275 
1276 			// SAMPLER SCREEN PLAY DISPLAY
1277 			else if (mouse.y >= 222 && mouse.y <= 232)
1278 			{
1279 				samplerPlayDisplay();
1280 				return;
1281 			}
1282 
1283 			// SAMPLER SCREEN PLAY RANGE
1284 			else if (mouse.y >= 233 && mouse.y <= 243)
1285 			{
1286 				samplerPlayRange();
1287 				return;
1288 			}
1289 		}
1290 
1291 		// SAMPLER SCREEN STOP
1292 		if (mouse.x >= 0 && mouse.x <= 31 && mouse.y >= 222 && mouse.y <= 243)
1293 		{
1294 			for (i = 0; i < AMIGA_VOICES; i++)
1295 				mixerKillVoice(i);
1296 			return;
1297 		}
1298 
1299 		// VOLUME button (toggle)
1300 		if (mouse.x >= 96 && mouse.x <= 135 && mouse.y >= 244 && mouse.y <= 254)
1301 		{
1302 			ui.samplerVolBoxShown = false;
1303 			removeSamplerVolBox();
1304 			return;
1305 		}
1306 
1307 		// DRAG BOXES
1308 		if (mouse.x >= 72 && mouse.x <= 173 && mouse.y >= 154 && mouse.y <= 175)
1309 		{
1310 			volBoxBarPressed(MOUSE_BUTTON_NOT_HELD);
1311 			return;
1312 		}
1313 
1314 		if (mouse.x >= 174 && mouse.x <= 207)
1315 		{
1316 			// FROM NUM
1317 			if (mouse.y >= 154 && mouse.y <= 164)
1318 			{
1319 				ui.tmpDisp16 = editor.vol1;
1320 				editor.vol1Disp = &ui.tmpDisp16;
1321 				ui.numPtr16 = &ui.tmpDisp16;
1322 				ui.numLen = 3;
1323 				ui.editTextPos = 6342; // (y * 40) + x
1324 				getNumLine(TEXT_EDIT_DECIMAL, PTB_SA_VOL_FROM_NUM);
1325 				return;
1326 			}
1327 
1328 			// TO NUM
1329 			else if (mouse.y >= 165 && mouse.y <= 175)
1330 			{
1331 				ui.tmpDisp16 = editor.vol2;
1332 				editor.vol2Disp = &ui.tmpDisp16;
1333 				ui.numPtr16 = &ui.tmpDisp16;
1334 				ui.numLen = 3;
1335 				ui.editTextPos = 6782; // (y * 40) + x
1336 				getNumLine(TEXT_EDIT_DECIMAL, PTB_SA_VOL_TO_NUM);
1337 				return;
1338 			}
1339 		}
1340 
1341 		if (mouse.y >= 176 && mouse.y <= 186)
1342 		{
1343 			// NORMALIZE
1344 			if (mouse.x >= 101 && mouse.x <= 143)
1345 			{
1346 				if (editor.sampleZero)
1347 				{
1348 					statusNotSampleZero();
1349 					return;
1350 				}
1351 
1352 				s = &song->samples[editor.currSample];
1353 				if (s->length == 0)
1354 				{
1355 					statusSampleIsEmpty();
1356 					return;
1357 				}
1358 
1359 				sampleData = &song->sampleData[s->offset];
1360 				if (editor.markStartOfs != -1)
1361 				{
1362 					sampleData += editor.markStartOfs;
1363 					sampleLength = editor.markEndOfs - editor.markStartOfs;
1364 				}
1365 				else
1366 				{
1367 					sampleLength = s->length;
1368 				}
1369 
1370 				sampleVol = 0;
1371 				sampleIndex = 0;
1372 
1373 				while (sampleIndex < sampleLength)
1374 				{
1375 					sample = *sampleData++;
1376 					sample = ABS(sample);
1377 
1378 					if (sampleVol < sample)
1379 						sampleVol = sample;
1380 
1381 					sampleIndex++;
1382 				}
1383 
1384 				if (sampleVol <= 0 || sampleVol > 127)
1385 				{
1386 					editor.vol1 = 100;
1387 					editor.vol2 = 100;
1388 				}
1389 				else if (sampleVol < 64)
1390 				{
1391 					editor.vol1 = 200;
1392 					editor.vol2 = 200;
1393 				}
1394 				else
1395 				{
1396 					editor.vol1 = (uint16_t)((100 * 127) / sampleVol);
1397 					editor.vol2 = (uint16_t)((100 * 127) / sampleVol);
1398 				}
1399 
1400 				ui.updateVolFromText = true;
1401 				ui.updateVolToText = true;
1402 
1403 				showVolFromSlider();
1404 				showVolToSlider();
1405 				return;
1406 			}
1407 
1408 			// RAMP DOWN
1409 			else if (mouse.x >= 144 && mouse.x <= 153)
1410 			{
1411 				editor.vol1 = 100;
1412 				editor.vol2 = 0;
1413 				ui.updateVolFromText = true;
1414 				ui.updateVolToText = true;
1415 				showVolFromSlider();
1416 				showVolToSlider();
1417 				return;
1418 			}
1419 
1420 			// RAMP UP
1421 			else if (mouse.x >= 154 && mouse.x <= 163)
1422 			{
1423 				editor.vol1 = 0;
1424 				editor.vol2 = 100;
1425 				ui.updateVolFromText = true;
1426 				ui.updateVolToText = true;
1427 				showVolFromSlider();
1428 				showVolToSlider();
1429 				return;
1430 			}
1431 
1432 			// RAMP UNITY
1433 			else if (mouse.x >= 164 && mouse.x <= 173)
1434 			{
1435 				editor.vol1 = 100;
1436 				editor.vol2 = 100;
1437 				ui.updateVolFromText = true;
1438 				ui.updateVolToText = true;
1439 				showVolFromSlider();
1440 				showVolToSlider();
1441 				return;
1442 			}
1443 
1444 			// CANCEL
1445 			else if (mouse.x >= 174 && mouse.x <= 207)
1446 			{
1447 				ui.samplerVolBoxShown = false;
1448 				removeSamplerVolBox();
1449 				return;
1450 			}
1451 
1452 			// RAMP
1453 			else if (mouse.x >= 72 && mouse.x <= 100)
1454 			{
1455 				if (editor.sampleZero)
1456 				{
1457 					statusNotSampleZero();
1458 					return;
1459 				}
1460 
1461 				s = &song->samples[editor.currSample];
1462 				if (s->length == 0)
1463 				{
1464 					statusSampleIsEmpty();
1465 					return;
1466 				}
1467 
1468 				if (editor.vol1 == 100 && editor.vol2 == 100)
1469 				{
1470 					ui.samplerVolBoxShown = false;
1471 					removeSamplerVolBox();
1472 					return;
1473 				}
1474 
1475 				sampleData = &song->sampleData[s->offset];
1476 				if (editor.markStartOfs != -1 && editor.markEndOfs-editor.markStartOfs >= 1)
1477 				{
1478 					sampleData += editor.markStartOfs;
1479 					sampleLength = editor.markEndOfs - editor.markStartOfs;
1480 				}
1481 				else
1482 				{
1483 					sampleLength = s->length;
1484 				}
1485 
1486 				if (sampleLength > 0)
1487 				{
1488 					double dSampleLengthMul = 1.0 / sampleLength;
1489 
1490 					sampleIndex = 0;
1491 					while (sampleIndex < sampleLength)
1492 					{
1493 						dSmp = (sampleIndex * editor.vol2) * dSampleLengthMul;
1494 						dSmp += ((sampleLength - sampleIndex) * editor.vol1) * dSampleLengthMul;
1495 						dSmp *= *sampleData;
1496 						dSmp *= (1.0 / 100.0);
1497 
1498 						smp32 = (int32_t)dSmp;
1499 						CLAMP8(smp32);
1500 
1501 						*sampleData++ = (int8_t)smp32;
1502 						sampleIndex++;
1503 					}
1504 				}
1505 
1506 				fixSampleBeep(s);
1507 
1508 				ui.samplerVolBoxShown = false;
1509 				removeSamplerVolBox();
1510 
1511 				updateWindowTitle(MOD_IS_MODIFIED);
1512 			}
1513 		}
1514 	}
1515 }
1516 
handleRepeatedSamplerFilterButtons(void)1517 static void handleRepeatedSamplerFilterButtons(void)
1518 {
1519 	if (!mouse.leftButtonPressed || mouse.lastSmpFilterButton == -1)
1520 		return;
1521 
1522 	switch (mouse.lastSmpFilterButton)
1523 	{
1524 		case 0: // low-pass cutoff up
1525 		{
1526 			if (mouse.rightButtonPressed)
1527 			{
1528 				if (editor.lpCutOff <= 0xFFFF-50)
1529 					editor.lpCutOff += 50;
1530 				else
1531 					editor.lpCutOff = 0xFFFF;
1532 			}
1533 			else
1534 			{
1535 				if (editor.lpCutOff < 0xFFFF)
1536 					editor.lpCutOff++;
1537 				else
1538 					editor.lpCutOff = 0xFFFF;
1539 			}
1540 
1541 			if (editor.lpCutOff > (uint16_t)(FILTERS_BASE_FREQ/2))
1542 				editor.lpCutOff = (uint16_t)(FILTERS_BASE_FREQ/2);
1543 
1544 			ui.updateLPText = true;
1545 		}
1546 		break;
1547 
1548 		case 1: // low-pass cutoff down
1549 		{
1550 			if (mouse.rightButtonPressed)
1551 			{
1552 				if (editor.lpCutOff >= 50)
1553 					editor.lpCutOff -= 50;
1554 				else
1555 					editor.lpCutOff = 0;
1556 			}
1557 			else
1558 			{
1559 				if (editor.lpCutOff > 0)
1560 					editor.lpCutOff--;
1561 				else
1562 					editor.lpCutOff = 0;
1563 			}
1564 
1565 			ui.updateLPText = true;
1566 		}
1567 		break;
1568 
1569 		case 2: // high-pass cutoff up
1570 		{
1571 			if (mouse.rightButtonPressed)
1572 			{
1573 				if (editor.hpCutOff <= 0xFFFF-50)
1574 					editor.hpCutOff += 50;
1575 				else
1576 					editor.hpCutOff = 0xFFFF;
1577 			}
1578 			else
1579 			{
1580 				if (editor.hpCutOff < 0xFFFF)
1581 					editor.hpCutOff++;
1582 				else
1583 					editor.hpCutOff = 0xFFFF;
1584 			}
1585 
1586 			if (editor.hpCutOff > (uint16_t)(FILTERS_BASE_FREQ/2))
1587 				editor.hpCutOff = (uint16_t)(FILTERS_BASE_FREQ/2);
1588 
1589 			ui.updateHPText = true;
1590 		}
1591 		break;
1592 
1593 		case 3: // high-pass cutoff down
1594 		{
1595 			if (mouse.rightButtonPressed)
1596 			{
1597 				if (editor.hpCutOff >= 50)
1598 					editor.hpCutOff -= 50;
1599 				else
1600 					editor.hpCutOff = 0;
1601 			}
1602 			else
1603 			{
1604 				if (editor.hpCutOff > 0)
1605 					editor.hpCutOff--;
1606 				else
1607 					editor.hpCutOff = 0;
1608 			}
1609 
1610 			ui.updateHPText = true;
1611 		}
1612 		break;
1613 
1614 		default: break;
1615 	}
1616 }
1617 
handleSamplerFiltersBox(void)1618 void handleSamplerFiltersBox(void)
1619 {
1620 	uint8_t i;
1621 	moduleSample_t *s;
1622 
1623 	if (mouse.rightButtonPressed && ui.editTextFlag)
1624 	{
1625 		exitGetTextLine(EDIT_TEXT_NO_UPDATE);
1626 		return;
1627 	}
1628 
1629 	if (ui.editTextFlag || mouse.lastSmpFilterButton > -1 || !mouse.leftButtonPressed)
1630 		return;
1631 
1632 	// restore sample ask dialog
1633 	if (ui.askScreenShown && ui.askScreenType == ASK_RESTORE_SAMPLE)
1634 	{
1635 		if (mouse.y >= 71 && mouse.y <= 81)
1636 		{
1637 			if (mouse.x >= 171 && mouse.x <= 196)
1638 			{
1639 				// YES button
1640 				ui.askScreenShown = false;
1641 				ui.answerNo = false;
1642 				ui.answerYes = true;
1643 				handleAskYes();
1644 			}
1645 			else if ((mouse.x >= 234) && (mouse.x <= 252))
1646 			{
1647 				// NO button
1648 				ui.askScreenShown = false;
1649 				ui.answerNo = true;
1650 				ui.answerYes = false;
1651 				handleAskNo();
1652 			}
1653 		}
1654 
1655 		return;
1656 	}
1657 
1658 	// FILTERS button (toggle)
1659 	if (mouse.x >= 211 && mouse.x <= 245 && mouse.y >= 244 && mouse.y <= 254)
1660 	{
1661 		ui.samplerFiltersBoxShown = false;
1662 		removeSamplerFiltersBox();
1663 		return;
1664 	}
1665 
1666 	// MAIN SCREEN STOP
1667 	if (!ui.diskOpScreenShown && !ui.posEdScreenShown)
1668 	{
1669 		if (mouse.x >= 182 && mouse.x <= 243 && mouse.y >= 0 && mouse.y <= 10)
1670 		{
1671 			modStop();
1672 			return;
1673 		}
1674 	}
1675 
1676 	if (mouse.x >= 32 && mouse.x <= 95)
1677 	{
1678 		// SAMPLER SCREEN PLAY WAVEFORM
1679 		if (mouse.y >= 211 && mouse.y <= 221)
1680 		{
1681 			samplerPlayWaveform();
1682 			return;
1683 		}
1684 
1685 		// SAMPLER SCREEN PLAY DISPLAY
1686 		else if (mouse.y >= 222 && mouse.y <= 232)
1687 		{
1688 			samplerPlayDisplay();
1689 			return;
1690 		}
1691 
1692 		// SAMPLER SCREEN PLAY RANGE
1693 		else if (mouse.y >= 233 && mouse.y <= 243)
1694 		{
1695 			samplerPlayRange();
1696 			return;
1697 		}
1698 	}
1699 
1700 	// SAMPLER SCREEN STOP
1701 	if (mouse.x >= 0 && mouse.x <= 31 && mouse.y >= 222 && mouse.y <= 243)
1702 	{
1703 		for (i = 0; i < AMIGA_VOICES; i++)
1704 			mixerKillVoice(i);
1705 		return;
1706 	}
1707 
1708 	// UNDO
1709 	if (mouse.x >= 65 && mouse.x <= 75 && mouse.y >= 154 && mouse.y <= 184)
1710 	{
1711 		if (editor.sampleZero)
1712 		{
1713 			statusNotSampleZero();
1714 			return;
1715 		}
1716 
1717 		s = &song->samples[editor.currSample];
1718 		if (s->length == 0)
1719 		{
1720 			statusSampleIsEmpty();
1721 		}
1722 		else
1723 		{
1724 			memcpy(&song->sampleData[s->offset], editor.tempSample, MAX_SAMPLE_LEN);
1725 			redrawSample();
1726 			updateWindowTitle(MOD_IS_MODIFIED);
1727 			renderSamplerFiltersBox();
1728 		}
1729 
1730 		return;
1731 	}
1732 
1733 	if (mouse.y >= 154 && mouse.y <= 164)
1734 	{
1735 		// DO LOW-PASS FILTER
1736 		if (mouse.x >= 76 && mouse.x <= 165)
1737 		{
1738 			lowPassSample(editor.lpCutOff);
1739 			renderSamplerFiltersBox();
1740 			return;
1741 		}
1742 
1743 		// LOW-PASS CUTOFF
1744 		else if (mouse.x >= 166 && mouse.x <= 217)
1745 		{
1746 			if (mouse.rightButtonPressed)
1747 			{
1748 				editor.lpCutOff = 0;
1749 				ui.updateLPText = true;
1750 			}
1751 			else
1752 			{
1753 				ui.tmpDisp16 = editor.lpCutOff;
1754 				editor.lpCutOffDisp = &ui.tmpDisp16;
1755 				ui.numPtr16 = &ui.tmpDisp16;
1756 				ui.numLen = 4;
1757 				ui.editTextPos = 6341; // (y * 40) + x
1758 				getNumLine(TEXT_EDIT_DECIMAL, PTB_SA_FIL_LP_CUTOFF);
1759 			}
1760 
1761 			return;
1762 		}
1763 
1764 		// LOW-PASS CUTOFF UP
1765 		else if (mouse.x >= 218 && mouse.x <= 228)
1766 		{
1767 			mouse.lastSmpFilterButton = 0;
1768 			if (mouse.rightButtonPressed)
1769 			{
1770 				if (editor.lpCutOff <= 0xFFFF-100)
1771 					editor.lpCutOff += 100;
1772 				else
1773 					editor.lpCutOff = 0xFFFF;
1774 			}
1775 			else
1776 			{
1777 				if (editor.lpCutOff < 0xFFFF)
1778 					editor.lpCutOff++;
1779 				else
1780 					editor.lpCutOff = 0xFFFF;
1781 			}
1782 
1783 			if (editor.lpCutOff > (uint16_t)(FILTERS_BASE_FREQ/2))
1784 				editor.lpCutOff = (uint16_t)(FILTERS_BASE_FREQ/2);
1785 
1786 			ui.updateLPText = true;
1787 			return;
1788 		}
1789 
1790 		// LOW-PASS CUTOFF DOWN
1791 		else if (mouse.x >= 229 && mouse.x <= 239)
1792 		{
1793 			mouse.lastSmpFilterButton = 1;
1794 			if (mouse.rightButtonPressed)
1795 			{
1796 				if (editor.lpCutOff >= 100)
1797 					editor.lpCutOff -= 100;
1798 				else
1799 					editor.lpCutOff = 0;
1800 			}
1801 			else
1802 			{
1803 				if (editor.lpCutOff > 0)
1804 					editor.lpCutOff--;
1805 				else
1806 					editor.lpCutOff = 0;
1807 			}
1808 
1809 			ui.updateLPText = true;
1810 			return;
1811 		}
1812 	}
1813 
1814 	if (mouse.y >= 164 && mouse.y <= 174)
1815 	{
1816 		// DO HIGH-PASS FILTER
1817 		if (mouse.x >= 76 && mouse.x <= 165)
1818 		{
1819 			highPassSample(editor.hpCutOff);
1820 			renderSamplerFiltersBox();
1821 			return;
1822 		}
1823 
1824 		// HIGH-PASS CUTOFF
1825 		else if (mouse.x >= 166 && mouse.x <= 217)
1826 		{
1827 			if (mouse.rightButtonPressed)
1828 			{
1829 				editor.hpCutOff = 0;
1830 				ui.updateHPText = true;
1831 			}
1832 			else
1833 			{
1834 				ui.tmpDisp16 = editor.hpCutOff;
1835 				editor.hpCutOffDisp = &ui.tmpDisp16;
1836 				ui.numPtr16 = &ui.tmpDisp16;
1837 				ui.numLen = 4;
1838 				ui.editTextPos = 6781; // (y * 40) + x
1839 				getNumLine(TEXT_EDIT_DECIMAL, PTB_SA_FIL_HP_CUTOFF);
1840 			}
1841 
1842 			return;
1843 		}
1844 
1845 		// HIGH-PASS CUTOFF UP
1846 		else if (mouse.x >= 218 && mouse.x <= 228)
1847 		{
1848 			mouse.lastSmpFilterButton = 2;
1849 			if (mouse.rightButtonPressed)
1850 			{
1851 				if (editor.hpCutOff <= 0xFFFF-100)
1852 					editor.hpCutOff += 100;
1853 				else
1854 					editor.hpCutOff = 0xFFFF;
1855 			}
1856 			else
1857 			{
1858 				if (editor.hpCutOff < 0xFFFF)
1859 					editor.hpCutOff++;
1860 				else
1861 					editor.hpCutOff = 0xFFFF;
1862 			}
1863 
1864 			if (editor.hpCutOff > (uint16_t)(FILTERS_BASE_FREQ/2))
1865 				editor.hpCutOff = (uint16_t)(FILTERS_BASE_FREQ/2);
1866 
1867 			ui.updateHPText = true;
1868 			return;
1869 		}
1870 
1871 		// HIGH-PASS CUTOFF DOWN
1872 		else if (mouse.x >= 229 && mouse.x <= 239)
1873 		{
1874 			mouse.lastSmpFilterButton = 3;
1875 			if (mouse.rightButtonPressed)
1876 			{
1877 				if (editor.hpCutOff >= 100)
1878 					editor.hpCutOff -= 100;
1879 				else
1880 					editor.hpCutOff = 0;
1881 			}
1882 			else
1883 			{
1884 				if (editor.hpCutOff > 0)
1885 					editor.hpCutOff--;
1886 				else
1887 					editor.hpCutOff = 0;
1888 			}
1889 
1890 			ui.updateHPText = true;
1891 			return;
1892 		}
1893 	}
1894 
1895 	// NORMALIZE SAMPLE FLAG
1896 	if (mouse.x >= 76 && mouse.x <= 239 && mouse.y >= 174 && mouse.y <= 186)
1897 	{
1898 		editor.normalizeFiltersFlag ^= 1;
1899 		ui.updateNormFlag = true;
1900 		return;
1901 	}
1902 
1903 	// EXIT
1904 	if (mouse.x >= 240 && mouse.x <= 250 && mouse.y >= 154 && mouse.y <= 186)
1905 	{
1906 		ui.samplerFiltersBoxShown = false;
1907 		removeSamplerFiltersBox();
1908 	}
1909 }
1910 
withinButtonRect(const guiButton_t * b)1911 static bool withinButtonRect(const guiButton_t *b)
1912 {
1913 	if (mouse.x >= b->x1 && mouse.x <= b->x2 && mouse.y >= b->y1 && mouse.y <= b->y2)
1914 		return true;
1915 
1916 	return false;
1917 }
1918 
1919 #define TEST_BUTTONS(bStruct, bNum) \
1920 for (uint32_t i = 0; i < bNum; i++) \
1921 	if (withinButtonRect(&bStruct[i])) \
1922 		return bStruct[i].b; \
1923 
checkGUIButtons(void)1924 int32_t checkGUIButtons(void)
1925 {
1926 	// these two makes *no other* buttons clickable
1927 	if (ui.askScreenShown)
1928 	{
1929 		if (ui.pat2SmpDialogShown)
1930 		{
1931 			TEST_BUTTONS(bPat2SmpAsk, PAT2SMP_ASK_BUTTONS);
1932 		}
1933 		else
1934 		{
1935 			TEST_BUTTONS(bAsk, ASK_BUTTONS);
1936 		}
1937 
1938 		return -1;
1939 	}
1940 	else if (ui.clearScreenShown)
1941 	{
1942 		TEST_BUTTONS(bClear, CLEAR_BUTTONS);
1943 		return -1;
1944 	}
1945 
1946 	// QUIT (xy 0,0) works on all screens except for ask/clear screen
1947 	if (mouse.x == 0 && mouse.y == 0)
1948 		return PTB_QUIT;
1949 
1950 	// top screen buttons
1951 	if (ui.diskOpScreenShown)
1952 	{
1953 		TEST_BUTTONS(bDiskOp, DISKOP_BUTTONS);
1954 	}
1955 	else
1956 	{
1957 		if (ui.posEdScreenShown)
1958 		{
1959 			TEST_BUTTONS(bPosEd, POSED_BUTTONS);
1960 		}
1961 		else if (ui.editOpScreenShown)
1962 		{
1963 			switch (ui.editOpScreen)
1964 			{
1965 				default:
1966 				case 0: TEST_BUTTONS(bEditOp1, EDITOP1_BUTTONS); break;
1967 				case 1: TEST_BUTTONS(bEditOp2, EDITOP2_BUTTONS); break;
1968 				case 2: TEST_BUTTONS(bEditOp3, EDITOP3_BUTTONS); break;
1969 				case 3: TEST_BUTTONS(bEditOp4, EDITOP4_BUTTONS); break;
1970 			}
1971 		}
1972 
1973 		TEST_BUTTONS(bTopScreen, TOPSCREEN_BUTTONS);
1974 	}
1975 
1976 	// middle buttons (always present)
1977 	TEST_BUTTONS(bMidScreen, MIDSCREEN_BUTTONS);
1978 
1979 	// bottom screen buttons
1980 	if (ui.samplerScreenShown)
1981 	{
1982 		TEST_BUTTONS(bSampler, SAMPLER_BUTTONS);
1983 	}
1984 	else
1985 	{
1986 		TEST_BUTTONS(bBotScreen, BOTSCREEN_BUTTONS);
1987 	}
1988 
1989 	return -1;
1990 }
1991 
handleTextEditing(uint8_t mouseButton)1992 void handleTextEditing(uint8_t mouseButton)
1993 {
1994 	char *tmpRead;
1995 	int32_t tmp32;
1996 
1997 	// handle mouse while editing text/numbers
1998 	if (ui.editTextFlag)
1999 	{
2000 		if (ui.editTextType != TEXT_EDIT_STRING)
2001 		{
2002 			if (mouseButton == SDL_BUTTON_RIGHT)
2003 				exitGetTextLine(EDIT_TEXT_NO_UPDATE);
2004 		}
2005 		else if (mouseButton == SDL_BUTTON_LEFT && !editor.mixFlag)
2006 		{
2007 			tmp32 = mouse.y - ui.lineCurY;
2008 			if (tmp32 <= 2 && tmp32 >= -9)
2009 			{
2010 				tmp32 = (int32_t)((mouse.x - ui.lineCurX) + 4) >> 3;
2011 				while (tmp32 != 0) // 0 = pos we want
2012 				{
2013 					if (tmp32 > 0)
2014 					{
2015 						if (ui.editPos < ui.textEndPtr && *ui.editPos != '\0')
2016 						{
2017 							ui.editPos++;
2018 							textMarkerMoveRight();
2019 						}
2020 						tmp32--;
2021 					}
2022 					else if (tmp32 < 0)
2023 					{
2024 						if (ui.editPos > ui.dstPtr)
2025 						{
2026 							ui.editPos--;
2027 							textMarkerMoveLeft();
2028 						}
2029 						tmp32++;
2030 					}
2031 				}
2032 			}
2033 			else
2034 			{
2035 				exitGetTextLine(EDIT_TEXT_UPDATE);
2036 			}
2037 		}
2038 		else if (mouseButton == SDL_BUTTON_RIGHT)
2039 		{
2040 			if (editor.mixFlag)
2041 			{
2042 				exitGetTextLine(EDIT_TEXT_UPDATE);
2043 				editor.mixFlag = false;
2044 				ui.updateMixText = true;
2045 			}
2046 			else
2047 			{
2048 				tmpRead = ui.dstPtr;
2049 				while (tmpRead < ui.textEndPtr)
2050 					*tmpRead++ = '\0';
2051 
2052 				*ui.textEndPtr = '\0';
2053 
2054 				// don't exit text edit mode if the disk op. path was about to be deleted
2055 				if (ui.editObject == PTB_DO_DATAPATH)
2056 				{
2057 					// move text cursor to pos 0
2058 					while (ui.editPos > ui.dstPtr)
2059 					{
2060 						ui.editPos--;
2061 						textMarkerMoveLeft();
2062 					}
2063 
2064 					ui.updateDiskOpPathText = true;
2065 				}
2066 				else
2067 				{
2068 					if (ui.editObject == PTB_SONGNAME)
2069 						ui.updateSongName = true;
2070 					else if (ui.editObject == PTB_SAMPLENAME)
2071 						ui.updateCurrSampleName = true;
2072 
2073 					exitGetTextLine(EDIT_TEXT_UPDATE);
2074 				}
2075 			}
2076 		}
2077 	}
2078 }
2079 
mouseWheelUpHandler(void)2080 void mouseWheelUpHandler(void)
2081 {
2082 	if (ui.editTextFlag || ui.askScreenShown || ui.clearScreenShown || editor.swapChannelFlag ||
2083 		ui.samplingBoxShown || ui.samplerVolBoxShown || ui.samplerFiltersBoxShown)
2084 		return;
2085 
2086 	if (mouse.y < 121)
2087 	{
2088 		// upper part of screen
2089 		if (ui.diskOpScreenShown)
2090 		{
2091 			if (diskop.scrollOffset > 0)
2092 			{
2093 				diskop.scrollOffset--;
2094 				ui.updateDiskOpFileList = true;
2095 			}
2096 		}
2097 		else if (ui.posEdScreenShown && song->currOrder > 0)
2098 		{
2099 			modSetPos(song->currOrder - 1, DONT_SET_ROW);
2100 		}
2101 	}
2102 	else if (ui.samplerScreenShown) // lower part of screen
2103 	{
2104 			samplerZoomInMouseWheel();
2105 	}
2106 	else if (!editor.songPlaying && song->currRow > 0)
2107 	{
2108 		modSetPos(DONT_SET_ORDER, song->currRow - 1); // pattern data
2109 	}
2110 }
2111 
mouseWheelDownHandler(void)2112 void mouseWheelDownHandler(void)
2113 {
2114 	if (ui.editTextFlag || ui.askScreenShown || ui.clearScreenShown || editor.swapChannelFlag ||
2115 		ui.samplingBoxShown || ui.samplerVolBoxShown || ui.samplerFiltersBoxShown)
2116 		return;
2117 
2118 	if (mouse.y < 121)
2119 	{
2120 		// upper part of screen
2121 		if (ui.diskOpScreenShown)
2122 		{
2123 			if (diskop.numEntries > DISKOP_LINES && diskop.scrollOffset < diskop.numEntries-DISKOP_LINES)
2124 			{
2125 				diskop.scrollOffset++;
2126 				ui.updateDiskOpFileList = true;
2127 			}
2128 		}
2129 		else if (ui.posEdScreenShown && song->currOrder < song->header.numOrders-1)
2130 		{
2131 			modSetPos(song->currOrder + 1, DONT_SET_ROW);
2132 		}
2133 	}
2134 	else if (ui.samplerScreenShown) // lower part of screen
2135 	{
2136 		if (!ui.samplerVolBoxShown && !ui.samplerFiltersBoxShown)
2137 			samplerZoomOutMouseWheel();
2138 	}
2139 	else if (!editor.songPlaying && song->currRow < MOD_ROWS)
2140 	{
2141 		modSetPos(DONT_SET_ORDER, song->currRow + 1); // pattern data
2142 	}
2143 }
2144 
handleRightMouseButton(void)2145 bool handleRightMouseButton(void)
2146 {
2147 	if (!mouse.rightButtonPressed)
2148 		return false;
2149 
2150 	// exit sample swap mode with right mouse button (if present)
2151 	if (editor.swapChannelFlag)
2152 	{
2153 		editor.swapChannelFlag = false;
2154 		pointerSetPreviousMode();
2155 		setPrevStatusMessage();
2156 		return true;
2157 	}
2158 
2159 	// close clear dialog with right mouse button
2160 	if (ui.clearScreenShown)
2161 	{
2162 		ui.clearScreenShown = false;
2163 		setPrevStatusMessage();
2164 		pointerSetPreviousMode();
2165 		removeClearScreen();
2166 		return true;
2167 	}
2168 
2169 	// close ask dialogs with right mouse button
2170 	if (ui.askScreenShown)
2171 	{
2172 		ui.askScreenShown = false;
2173 		ui.answerNo = true;
2174 		ui.answerYes = false;
2175 		handleAskNo(); // mouse pointer is set to error (red) in here
2176 		return true;
2177 	}
2178 
2179 	// toggle channel muting with right mouse button
2180 	if (ui.visualizerMode == VISUAL_QUADRASCOPE && mouse.y >= 55 && mouse.y <= 87)
2181 	{
2182 		if (!ui.posEdScreenShown && !ui.editOpScreenShown && !ui.diskOpScreenShown &&
2183 			!ui.aboutScreenShown && !ui.samplerVolBoxShown &&
2184 			!ui.samplerFiltersBoxShown && !ui.samplingBoxShown &&
2185 			!editor.isWAVRendering)
2186 		{
2187 			     if (mouse.x > 127 && mouse.x <= 167) editor.muted[0] ^= 1;
2188 			else if (mouse.x > 175 && mouse.x <= 215) editor.muted[1] ^= 1;
2189 			else if (mouse.x > 223 && mouse.x <= 263) editor.muted[2] ^= 1;
2190 			else if (mouse.x > 271 && mouse.x <= 311) editor.muted[3] ^= 1;
2191 
2192 			renderMuteButtons();
2193 		}
2194 	}
2195 
2196 	// sample hand drawing
2197 	if (mouse.y >= 138 && mouse.y <= 201 && ui.samplerScreenShown &&
2198 		!ui.samplerVolBoxShown && !ui.samplerFiltersBoxShown && !ui.samplingBoxShown)
2199 	{
2200 		samplerEditSample(false);
2201 	}
2202 
2203 	return false;
2204 }
2205 
handleLeftMouseButton(void)2206 bool handleLeftMouseButton(void)
2207 {
2208 	int32_t guiButton;
2209 
2210 	if (editor.swapChannelFlag || ui.editTextFlag)
2211 		return false;
2212 
2213 	// handle volume toolbox in sampler screen
2214 	if (ui.samplerVolBoxShown)
2215 	{
2216 		handleSamplerVolumeBox();
2217 		return true;
2218 	}
2219 
2220 	// handle filters toolbox in sampler screen
2221 	else if (ui.samplerFiltersBoxShown)
2222 	{
2223 		handleSamplerFiltersBox();
2224 		return true;
2225 	}
2226 
2227 	// handle sampling toolbox in sampler screen
2228 	else if (ui.samplingBoxShown)
2229 	{
2230 		handleSamplingBox();
2231 		return true;
2232 	}
2233 
2234 	// "downsample before loading sample" ask dialog
2235 	if (ui.askScreenShown && ui.askScreenType == ASK_LOAD_DOWNSAMPLE)
2236 	{
2237 		if (mouse.y >= 83 && mouse.y <= 93)
2238 		{
2239 			if (mouse.x >= 179 && mouse.x <= 204)
2240 			{
2241 				// YES button
2242 				ui.askScreenShown = false;
2243 				ui.answerNo = false;
2244 				ui.answerYes = true;
2245 				handleAskYes();
2246 				return true;
2247 			}
2248 			else if (mouse.x >= 242 && mouse.x <= 260)
2249 			{
2250 				// NO button
2251 				ui.askScreenShown = false;
2252 				ui.answerNo = true;
2253 				ui.answerYes = false;
2254 				handleAskNo();
2255 				return true;
2256 			}
2257 		}
2258 
2259 		return false;
2260 	}
2261 
2262 	// cancel note input gadgets with left/right mouse button
2263 	if (ui.changingSmpResample || ui.changingChordNote || ui.changingDrumPadNote || ui.changingSamplingNote)
2264 	{
2265 		if (mouse.leftButtonPressed || mouse.rightButtonPressed)
2266 		{
2267 			ui.changingSmpResample = false;
2268 			ui.changingSamplingNote = false;
2269 			ui.changingChordNote = false;
2270 			ui.changingDrumPadNote = false;
2271 
2272 			ui.updateResampleNote = true;
2273 			ui.updateNote1Text = true;
2274 			ui.updateNote2Text = true;
2275 			ui.updateNote3Text = true;
2276 			ui.updateNote4Text = true;
2277 
2278 			setPrevStatusMessage();
2279 			pointerSetPreviousMode();
2280 		}
2281 
2282 		return true;
2283 	}
2284 
2285 	if (!mouse.leftButtonPressed)
2286 		return false;
2287 
2288 	// handle QUIT ask dialog while Disk Op. filling is ongoing
2289 	if (diskop.isFilling)
2290 	{
2291 		if (ui.askScreenShown && ui.askScreenType == ASK_QUIT)
2292 		{
2293 			if (mouse.y >= 71 && mouse.y <= 81)
2294 			{
2295 				if (mouse.x >= 171 && mouse.x <= 196)
2296 				{
2297 					// YES button
2298 					ui.askScreenShown = false;
2299 					ui.answerNo = false;
2300 					ui.answerYes = true;
2301 					handleAskYes();
2302 				}
2303 				else if (mouse.x >= 234 && mouse.x <= 252)
2304 				{
2305 					// NO button
2306 					ui.askScreenShown = false;
2307 					ui.answerNo = true;
2308 					ui.answerYes = false;
2309 					handleAskNo();
2310 				}
2311 			}
2312 		}
2313 
2314 		return true;
2315 	}
2316 
2317 	// CANCEL and YES/NO (ask exit) buttons while MOD2WAV is ongoing
2318 	if (editor.isWAVRendering)
2319 	{
2320 		if (ui.askScreenShown && ui.askScreenType == ASK_QUIT)
2321 		{
2322 			if (mouse.x >= 171 && mouse.x <= 196)
2323 			{
2324 				// YES button
2325 				editor.isWAVRendering = false;
2326 				SDL_WaitThread(editor.mod2WavThread, NULL);
2327 
2328 				ui.askScreenShown = false;
2329 				ui.answerNo = false;
2330 				ui.answerYes = true;
2331 				handleAskYes();
2332 			}
2333 			else if (mouse.x >= 234 && mouse.x <= 252)
2334 			{
2335 				// NO button
2336 				ui.askScreenShown = false;
2337 				ui.answerNo = true;
2338 				ui.answerYes = false;
2339 				handleAskNo();
2340 
2341 				pointerSetMode(POINTER_MODE_MSG2, NO_CARRY);
2342 				setStatusMessage("RENDERING MOD...", NO_CARRY);
2343 			}
2344 		}
2345 		else if (mouse.y >= 58 && mouse.y <= 68 && mouse.x >= 133 && mouse.x <= 186)
2346 		{
2347 			// CANCEL button
2348 			editor.abortMod2Wav = true;
2349 		}
2350 
2351 		return true;
2352 	}
2353 
2354 	guiButton = checkGUIButtons();
2355 	if (guiButton == -1)
2356 		return false;
2357 
2358 	return handleGUIButtons(guiButton);
2359 }
2360 
updateMouseCounters(void)2361 void updateMouseCounters(void)
2362 {
2363 	if (mouse.buttonWaiting)
2364 	{
2365 		if (++mouse.buttonWaitCounter > VBLANK_HZ/4) // quarter of a second
2366 		{
2367 			mouse.buttonWaitCounter = 0;
2368 			mouse.buttonWaiting = false;
2369 		}
2370 	}
2371 
2372 	if (editor.errorMsgActive)
2373 	{
2374 		if (++editor.errorMsgCounter >= 55)
2375 		{
2376 			editor.errorMsgCounter = 0;
2377 
2378 			// don't reset status text/mouse color during certain modes
2379 			if (!ui.askScreenShown && !ui.clearScreenShown &&
2380 				!ui.pat2SmpDialogShown && !ui.changingChordNote &&
2381 				!ui.changingDrumPadNote && !ui.changingSmpResample &&
2382 				!editor.swapChannelFlag && !ui.changingSamplingNote)
2383 			{
2384 				pointerSetPreviousMode();
2385 				setPrevStatusMessage();
2386 			}
2387 
2388 			editor.errorMsgActive = false;
2389 			editor.errorMsgBlock = false;
2390 
2391 			diskOpShowSelectText();
2392 		}
2393 	}
2394 }
2395 
handleGUIButtons(int32_t button)2396 static bool handleGUIButtons(int32_t button) // are you prepared to enter the jungle?
2397 {
2398 	char pat2SmpText[24];
2399 	int8_t *ptr8_1, *ptr8_2, *ptr8_3, *ptr8_4, tmpSmp, modTmp, modDat;
2400 	uint8_t i;
2401 	int16_t tmp16;
2402 	int32_t smp32, j, modPos, oldVal, tmp32;
2403 	double dSmp;
2404 	moduleSample_t *s;
2405 
2406 	switch (button)
2407 	{
2408 		case PTB_DUMMY: return false; // for gaps/empty spaces/dummies
2409 
2410 		case PTB_PAT2SMP:
2411 		{
2412 			ui.askScreenShown = true;
2413 			ui.askScreenType = ASK_PAT2SMP;
2414 			ui.pat2SmpDialogShown = true;
2415 			pointerSetMode(POINTER_MODE_MSG1, NO_CARRY);
2416 
2417 			if (editor.songPlaying)
2418 				sprintf(pat2SmpText, "ROW 00 TO SMP %02X?", editor.currSample + 1);
2419 			else
2420 				sprintf(pat2SmpText, "ROW %02d TO SMP %02X?", song->currRow, editor.currSample + 1);
2421 
2422 			setStatusMessage(pat2SmpText, NO_CARRY);
2423 			renderAskDialog();
2424 		}
2425 		break;
2426 
2427 		// Edit Op. All Screens
2428 		case PTB_EO_TITLEBAR:
2429 		{
2430 			     if (ui.editOpScreen == 0) editor.sampleAllFlag ^= 1;
2431 			else if (ui.editOpScreen == 1) editor.trackPattFlag = (editor.trackPattFlag + 1) % 3;
2432 			else if (ui.editOpScreen == 2) editor.halfClipFlag ^= 1;
2433 			else if (ui.editOpScreen == 3) editor.newOldFlag ^= 1;
2434 
2435 			renderEditOpMode();
2436 		}
2437 		break;
2438 
2439 		case PTB_EO_1:
2440 		{
2441 			ui.editOpScreen = 0;
2442 			renderEditOpScreen();
2443 		}
2444 		break;
2445 
2446 		case PTB_EO_2:
2447 		{
2448 			ui.editOpScreen = 1;
2449 			renderEditOpScreen();
2450 		}
2451 		break;
2452 
2453 		case PTB_EO_3:
2454 		{
2455 			ui.editOpScreen = 2;
2456 			renderEditOpScreen();
2457 		}
2458 		break;
2459 
2460 		case PTB_EO_EXIT:
2461 		{
2462 			ui.aboutScreenShown = false;
2463 			ui.editOpScreenShown = false;
2464 			displayMainScreen();
2465 		}
2466 		break;
2467 		// ----------------------------------------------------------
2468 
2469 		// Edit Op. Screen #1
2470 		case PTB_EO_TRACK_NOTE_UP: trackNoteUp(editor.sampleAllFlag, 0, MOD_ROWS - 1); break;
2471 		case PTB_EO_TRACK_NOTE_DOWN: trackNoteDown(editor.sampleAllFlag, 0, MOD_ROWS - 1); break;
2472 		case PTB_EO_TRACK_OCTA_UP: trackOctaUp(editor.sampleAllFlag, 0, MOD_ROWS - 1); break;
2473 		case PTB_EO_TRACK_OCTA_DOWN: trackOctaDown(editor.sampleAllFlag, 0, MOD_ROWS - 1); break;
2474 		case PTB_EO_PATT_NOTE_UP: pattNoteUp(editor.sampleAllFlag); break;
2475 		case PTB_EO_PATT_NOTE_DOWN: pattNoteDown(editor.sampleAllFlag); break;
2476 		case PTB_EO_PATT_OCTA_UP: pattOctaUp(editor.sampleAllFlag); break;
2477 		case PTB_EO_PATT_OCTA_DOWN: pattOctaDown(editor.sampleAllFlag); break;
2478 		// ----------------------------------------------------------
2479 
2480 		// Edit Op. Screen #2
2481 		case PTB_EO_RECORD:
2482 		{
2483 			editor.recordMode ^= 1;
2484 			ui.updateRecordText = true;
2485 		}
2486 		break;
2487 
2488 		case PTB_EO_DELETE: delSampleTrack(); break;
2489 		case PTB_EO_EXCHGE: exchSampleTrack(); break;
2490 		case PTB_EO_COPY: copySampleTrack(); break;
2491 
2492 		case PTB_EO_FROM:
2493 		{
2494 			editor.sampleFrom = editor.currSample + 1;
2495 			ui.updateFromText = true;
2496 		}
2497 		break;
2498 
2499 		case PTB_EO_TO:
2500 		{
2501 			editor.sampleTo = editor.currSample + 1;
2502 			ui.updateToText = true;
2503 		}
2504 		break;
2505 
2506 		case PTB_EO_KILL:
2507 		{
2508 			ui.askScreenShown = true;
2509 			ui.askScreenType = ASK_KILL_SAMPLE;
2510 			pointerSetMode(POINTER_MODE_MSG1, NO_CARRY);
2511 			setStatusMessage("KILL SAMPLE ?", NO_CARRY);
2512 			renderAskDialog();
2513 		}
2514 		break;
2515 
2516 		case PTB_EO_QUANTIZE:
2517 		{
2518 			ui.tmpDisp16 = config.quantizeValue;
2519 			editor.quantizeValueDisp = &ui.tmpDisp16;
2520 			ui.numPtr16 = &ui.tmpDisp16;
2521 			ui.numLen = 2;
2522 			ui.editTextPos = 2824; // (y * 40) + x
2523 			getNumLine(TEXT_EDIT_DECIMAL, PTB_EO_QUANTIZE);
2524 		}
2525 		break;
2526 
2527 		case PTB_EO_METRO_1: // metronome speed
2528 		{
2529 			ui.tmpDisp16 = editor.metroSpeed;
2530 			editor.metroSpeedDisp = &ui.tmpDisp16;
2531 			ui.numPtr16 = &ui.tmpDisp16;
2532 			ui.numLen = 2;
2533 			ui.editTextPos = 3261; // (y * 40) + x
2534 			getNumLine(TEXT_EDIT_DECIMAL, PTB_EO_METRO_1);
2535 		}
2536 		break;
2537 
2538 		case PTB_EO_METRO_2: // metronome channel
2539 		{
2540 			ui.tmpDisp16 = editor.metroChannel;
2541 			editor.metroChannelDisp = &ui.tmpDisp16;
2542 			ui.numPtr16 = &ui.tmpDisp16;
2543 			ui.numLen = 2;
2544 			ui.editTextPos = 3264; // (y * 40) + x
2545 			getNumLine(TEXT_EDIT_DECIMAL, PTB_EO_METRO_2);
2546 		}
2547 		break;
2548 
2549 		case PTB_EO_FROM_NUM:
2550 		{
2551 			ui.tmpDisp8 = editor.sampleFrom;
2552 			editor.sampleFromDisp = &ui.tmpDisp8;
2553 			ui.numPtr8 = &ui.tmpDisp8;
2554 			ui.numLen = 2;
2555 			ui.numBits = 8;
2556 			ui.editTextPos = 3273; // (y * 40) + x
2557 			getNumLine(TEXT_EDIT_HEX, PTB_EO_FROM_NUM);
2558 		}
2559 		break;
2560 
2561 		case PTB_EO_TO_NUM:
2562 		{
2563 			ui.tmpDisp8 = editor.sampleTo;
2564 			editor.sampleToDisp = &ui.tmpDisp8;
2565 			ui.numPtr8 = &ui.tmpDisp8;
2566 			ui.numLen = 2;
2567 			ui.numBits = 8;
2568 			ui.editTextPos = 3713; // (y * 40) + x
2569 			getNumLine(TEXT_EDIT_HEX, PTB_EO_TO_NUM);
2570 		}
2571 		break;
2572 
2573 		case PTB_EO_FROM_UP:
2574 		{
2575 			if (editor.sampleFrom < 0x1F)
2576 			{
2577 				editor.sampleFrom++;
2578 				ui.updateFromText = true;
2579 			}
2580 		}
2581 		break;
2582 
2583 		case PTB_EO_FROM_DOWN:
2584 		{
2585 			if (editor.sampleFrom > 0x00)
2586 			{
2587 				editor.sampleFrom--;
2588 				ui.updateFromText = true;
2589 			}
2590 		}
2591 		break;
2592 
2593 		case PTB_EO_TO_UP:
2594 		{
2595 			if (editor.sampleTo < 0x1F)
2596 			{
2597 				editor.sampleTo++;
2598 				ui.updateToText = true;
2599 			}
2600 		}
2601 		break;
2602 
2603 		case PTB_EO_TO_DOWN:
2604 		{
2605 			if (editor.sampleTo > 0x00)
2606 			{
2607 				editor.sampleTo--;
2608 				ui.updateToText = true;
2609 			}
2610 		}
2611 		break;
2612 
2613 		case PTB_EO_KEYS:
2614 		{
2615 			editor.multiFlag ^= 1;
2616 			ui.updateTrackerFlags = true;
2617 			ui.updateKeysText = true;
2618 		}
2619 		break;
2620 		// ----------------------------------------------------------
2621 
2622 		// Edit Op. Screen #3
2623 
2624 		case PTB_EO_MIX:
2625 		{
2626 			if (!mouse.rightButtonPressed)
2627 			{
2628 				editor.mixFlag = true;
2629 				ui.showTextPtr = editor.mixText;
2630 				ui.textEndPtr = editor.mixText + 15;
2631 				ui.textLength = 16;
2632 				ui.editTextPos = 1936; // (y * 40) + x
2633 				ui.dstOffset = NULL;
2634 				ui.dstOffsetEnd = false;
2635 				ui.updateMixText = true;
2636 				getTextLine(PTB_EO_MIX);
2637 			}
2638 			else
2639 			{
2640 				if (editor.sampleZero)
2641 				{
2642 					statusNotSampleZero();
2643 					break;
2644 				}
2645 
2646 				s = &song->samples[editor.currSample];
2647 				if (s->length == 0)
2648 				{
2649 					statusSampleIsEmpty();
2650 					break;
2651 				}
2652 
2653 				if (editor.samplePos == s->length)
2654 				{
2655 					displayErrorMsg("INVALID POS !");
2656 					break;
2657 				}
2658 
2659 				ptr8_1 = (int8_t *)malloc(MAX_SAMPLE_LEN);
2660 				if (ptr8_1 == NULL)
2661 				{
2662 					statusOutOfMemory();
2663 					return true;
2664 				}
2665 
2666 				memcpy(ptr8_1, &song->sampleData[s->offset], MAX_SAMPLE_LEN);
2667 
2668 				ptr8_2 = &song->sampleData[s->offset+editor.samplePos];
2669 				ptr8_3 = &song->sampleData[s->offset+s->length-1];
2670 				ptr8_4 = ptr8_1;
2671 
2672 				editor.modulateOffset = 0;
2673 				editor.modulatePos = 0;
2674 
2675 				do
2676 				{
2677 					tmp16 = *ptr8_2 + *ptr8_1;
2678 					if (editor.halfClipFlag == 0)
2679 						tmp16 >>= 1;
2680 
2681 					CLAMP8(tmp16);
2682 					*ptr8_2++ = (int8_t)tmp16;
2683 
2684 					if (editor.modulateSpeed == 0)
2685 					{
2686 						ptr8_1++;
2687 					}
2688 					else
2689 					{
2690 						editor.modulatePos += editor.modulateSpeed;
2691 
2692 						modTmp = (editor.modulatePos >> 12) & 0xFF;
2693 						modDat = vibratoTable[modTmp & 0x1F] >> 2;
2694 						modPos = ((modTmp & 32) ? (editor.modulateOffset - modDat) : (editor.modulateOffset + modDat)) + 2048;
2695 
2696 						editor.modulateOffset = modPos;
2697 						modPos >>= 11;
2698 						modPos = CLAMP(modPos, 0, s->length - 1);
2699 						ptr8_1 = &ptr8_4[modPos];
2700 					}
2701 				}
2702 				while (ptr8_2 < ptr8_3);
2703 				free(ptr8_4);
2704 
2705 				fixSampleBeep(s);
2706 				if (ui.samplerScreenShown)
2707 					displaySample();
2708 
2709 				updateWindowTitle(MOD_IS_MODIFIED);
2710 			}
2711 		}
2712 		break;
2713 
2714 		case PTB_EO_ECHO:
2715 		{
2716 			if (editor.sampleZero)
2717 			{
2718 				statusNotSampleZero();
2719 				break;
2720 			}
2721 
2722 			s = &song->samples[editor.currSample];
2723 			if (s->length == 0)
2724 			{
2725 				statusSampleIsEmpty();
2726 				break;
2727 			}
2728 
2729 			if (editor.samplePos == 0)
2730 			{
2731 				displayErrorMsg("SET SAMPLE POS !");
2732 				break;
2733 			}
2734 
2735 			if (editor.samplePos == s->length)
2736 			{
2737 				displayErrorMsg("INVALID POS !");
2738 				break;
2739 			}
2740 
2741 			ptr8_1 = &song->sampleData[s->offset+editor.samplePos];
2742 			ptr8_2 = &song->sampleData[s->offset];
2743 			ptr8_3 = ptr8_2;
2744 
2745 			editor.modulateOffset = 0;
2746 			editor.modulatePos = 0;
2747 
2748 			for (j = 0; j < s->length; j++)
2749 			{
2750 				tmp16 = (*ptr8_2 + *ptr8_1) >> 1;
2751 				CLAMP8(tmp16);
2752 
2753 				*ptr8_1++ = (int8_t)tmp16;
2754 
2755 				if (editor.modulateSpeed == 0)
2756 				{
2757 					ptr8_2++;
2758 				}
2759 				else
2760 				{
2761 					editor.modulatePos += editor.modulateSpeed;
2762 
2763 					modTmp = (editor.modulatePos >> 12) & 0xFF;
2764 					modDat = vibratoTable[modTmp & 0x1F] >> 2;
2765 					modPos = ((modTmp & 32) ? (editor.modulateOffset - modDat) : (editor.modulateOffset + modDat)) + 2048;
2766 
2767 					editor.modulateOffset = modPos;
2768 					modPos >>= 11;
2769 					modPos = CLAMP(modPos, 0, s->length - 1);
2770 					ptr8_2 = &ptr8_3[modPos];
2771 				}
2772 			}
2773 
2774 			if (editor.halfClipFlag != 0)
2775 			{
2776 				for (j = 0; j < s->length; j++)
2777 				{
2778 					tmp16 = ptr8_3[j] + ptr8_3[j];
2779 					CLAMP8(tmp16);
2780 					ptr8_3[j] = (int8_t)tmp16;
2781 				}
2782 			}
2783 
2784 			fixSampleBeep(s);
2785 			if (ui.samplerScreenShown)
2786 				displaySample();
2787 
2788 			updateWindowTitle(MOD_IS_MODIFIED);
2789 		}
2790 		break;
2791 
2792 		case PTB_EO_POS_NUM:
2793 		{
2794 			if (mouse.rightButtonPressed)
2795 			{
2796 				editor.samplePos = 0;
2797 				ui.updatePosText = true;
2798 			}
2799 			else
2800 			{
2801 				ui.tmpDisp16 = editor.samplePos;
2802 				editor.samplePosDisp = &ui.tmpDisp16;
2803 				ui.numPtr16 = &ui.tmpDisp16;
2804 				ui.numLen = 4;
2805 				ui.numBits = 16;
2806 				ui.editTextPos = 2391; // (y * 40) + x
2807 				getNumLine(TEXT_EDIT_HEX, PTB_EO_POS_NUM);
2808 			}
2809 		}
2810 		break;
2811 
2812 		case PTB_EO_POS_UP: edPosUpButton(INCREMENT_SLOW); break;
2813 		case PTB_EO_POS_DOWN: edPosDownButton(INCREMENT_SLOW); break;
2814 
2815 		case PTB_EO_BOOST: // this is actually treble increase
2816 		{
2817 			if (editor.sampleZero)
2818 			{
2819 				statusNotSampleZero();
2820 				break;
2821 			}
2822 
2823 			s = &song->samples[editor.currSample];
2824 			if (s->length == 0)
2825 			{
2826 				statusSampleIsEmpty();
2827 				break;
2828 			}
2829 
2830 			boostSample(editor.currSample, false);
2831 			if (ui.samplerScreenShown)
2832 				displaySample();
2833 
2834 			updateWindowTitle(MOD_IS_MODIFIED);
2835 		}
2836 		break;
2837 
2838 		case PTB_EO_FILTER: // this is actually treble decrease
2839 		{
2840 			if (editor.sampleZero)
2841 			{
2842 				statusNotSampleZero();
2843 				break;
2844 			}
2845 
2846 			s = &song->samples[editor.currSample];
2847 			if (s->length == 0)
2848 			{
2849 				statusSampleIsEmpty();
2850 				break;
2851 			}
2852 
2853 			filterSample(editor.currSample, false);
2854 			if (ui.samplerScreenShown)
2855 				displaySample();
2856 
2857 			updateWindowTitle(MOD_IS_MODIFIED);
2858 		}
2859 		break;
2860 
2861 		case PTB_EO_MOD_NUM:
2862 		{
2863 			if (mouse.rightButtonPressed)
2864 			{
2865 				editor.modulateSpeed = 0;
2866 				ui.updateModText = true;
2867 			}
2868 		}
2869 		break;
2870 
2871 		case PTB_EO_MOD:
2872 		{
2873 			if (editor.sampleZero)
2874 			{
2875 				statusNotSampleZero();
2876 				break;
2877 			}
2878 
2879 			s = &song->samples[editor.currSample];
2880 			if (s->length == 0)
2881 			{
2882 				statusSampleIsEmpty();
2883 				break;
2884 			}
2885 
2886 			if (editor.modulateSpeed == 0)
2887 			{
2888 				displayErrorMsg("SET MOD. SPEED !");
2889 				break;
2890 			}
2891 
2892 			ptr8_1 = &song->sampleData[s->offset];
2893 
2894 			ptr8_3 = (int8_t *)malloc(MAX_SAMPLE_LEN);
2895 			if (ptr8_3 == NULL)
2896 			{
2897 				statusOutOfMemory();
2898 				return true;
2899 			}
2900 
2901 			ptr8_2 = ptr8_3;
2902 
2903 			memcpy(ptr8_2, ptr8_1, MAX_SAMPLE_LEN);
2904 
2905 			editor.modulateOffset = 0;
2906 			editor.modulatePos = 0;
2907 
2908 			for (j = 0; j < s->length; j++)
2909 			{
2910 				*ptr8_1++ = *ptr8_2;
2911 
2912 				editor.modulatePos += editor.modulateSpeed;
2913 
2914 				modTmp = (editor.modulatePos >> 12) & 0xFF;
2915 				modDat = vibratoTable[modTmp & 0x1F] >> 2;
2916 				modPos = ((modTmp & 32) ? (editor.modulateOffset - modDat) : (editor.modulateOffset + modDat)) + 2048;
2917 
2918 				editor.modulateOffset = modPos;
2919 
2920 				modPos >>= 11;
2921 				modPos = CLAMP(modPos, 0, s->length - 1);
2922 				ptr8_2 = &ptr8_3[modPos];
2923 			}
2924 
2925 			free(ptr8_3);
2926 
2927 			fixSampleBeep(s);
2928 			if (ui.samplerScreenShown)
2929 				displaySample();
2930 
2931 			updateWindowTitle(MOD_IS_MODIFIED);
2932 		}
2933 		break;
2934 
2935 		case PTB_EO_MOD_UP: edModUpButton(); break;
2936 		case PTB_EO_MOD_DOWN: edModDownButton(); break;
2937 
2938 		case PTB_EO_X_FADE:
2939 		{
2940 			if (editor.sampleZero)
2941 			{
2942 				statusNotSampleZero();
2943 				break;
2944 			}
2945 
2946 			s = &song->samples[editor.currSample];
2947 
2948 			if (s->length == 0)
2949 			{
2950 				statusSampleIsEmpty();
2951 				break;
2952 			}
2953 
2954 			ptr8_1 = &song->sampleData[s->offset];
2955 			ptr8_2 = &song->sampleData[s->offset+s->length-1];
2956 
2957 			do
2958 			{
2959 				tmp16 = *ptr8_1 + *ptr8_2;
2960 				if (editor.halfClipFlag == 0)
2961 					tmp16 >>= 1;
2962 
2963 				CLAMP8(tmp16);
2964 				tmpSmp = (int8_t)tmp16;
2965 
2966 				*ptr8_1++ = tmpSmp;
2967 				*ptr8_2-- = tmpSmp;
2968 			}
2969 			while (ptr8_1 < ptr8_2);
2970 
2971 			fixSampleBeep(s);
2972 			if (ui.samplerScreenShown)
2973 				displaySample();
2974 
2975 			updateWindowTitle(MOD_IS_MODIFIED);
2976 		}
2977 		break;
2978 
2979 		case PTB_EO_BACKWD:
2980 		{
2981 			if (editor.sampleZero)
2982 			{
2983 				statusNotSampleZero();
2984 				break;
2985 			}
2986 
2987 			s = &song->samples[editor.currSample];
2988 			if (s->length == 0)
2989 			{
2990 				statusSampleIsEmpty();
2991 				break;
2992 			}
2993 
2994 			if (editor.markStartOfs != -1 && editor.markStartOfs != editor.markEndOfs && editor.markEndOfs != 0)
2995 			{
2996 				ptr8_1 = &song->sampleData[s->offset+editor.markStartOfs];
2997 				ptr8_2 = &song->sampleData[s->offset+editor.markEndOfs-1];
2998 			}
2999 			else
3000 			{
3001 				ptr8_1 = &song->sampleData[s->offset];
3002 				ptr8_2 = &song->sampleData[s->offset+s->length-1];
3003 			}
3004 
3005 			do
3006 			{
3007 				tmpSmp = *ptr8_1;
3008 				*ptr8_1++ = *ptr8_2;
3009 				*ptr8_2-- = tmpSmp;
3010 			}
3011 			while (ptr8_1 < ptr8_2);
3012 
3013 			fixSampleBeep(s);
3014 			if (ui.samplerScreenShown)
3015 				displaySample();
3016 
3017 			updateWindowTitle(MOD_IS_MODIFIED);
3018 		}
3019 		break;
3020 
3021 		case PTB_EO_CB:
3022 		{
3023 			if (editor.sampleZero)
3024 			{
3025 				statusNotSampleZero();
3026 				break;
3027 			}
3028 
3029 			s = &song->samples[editor.currSample];
3030 			if (s->length == 0)
3031 			{
3032 				statusSampleIsEmpty();
3033 				break;
3034 			}
3035 
3036 			if (editor.samplePos == 0)
3037 			{
3038 				displayErrorMsg("SET SAMPLE POS !");
3039 				break;
3040 			}
3041 
3042 			if (editor.samplePos >= s->length)
3043 			{
3044 				displayErrorMsg("INVALID POS !");
3045 				break;
3046 			}
3047 
3048 			turnOffVoices();
3049 
3050 			memcpy(&song->sampleData[s->offset], &song->sampleData[s->offset + editor.samplePos], MAX_SAMPLE_LEN - editor.samplePos);
3051 			memset(&song->sampleData[s->offset + (MAX_SAMPLE_LEN - editor.samplePos)], 0, editor.samplePos);
3052 
3053 			if (editor.samplePos > s->loopStart)
3054 			{
3055 				s->loopStart = 0;
3056 				s->loopLength = 2;
3057 			}
3058 			else
3059 			{
3060 				s->loopStart = (s->loopStart - editor.samplePos) & 0xFFFE;
3061 			}
3062 
3063 			s->length = (s->length - editor.samplePos) & 0xFFFE;
3064 
3065 			editor.samplePos = 0;
3066 			fixSampleBeep(s);
3067 			updateCurrSample();
3068 
3069 			updateWindowTitle(MOD_IS_MODIFIED);
3070 		}
3071 		break;
3072 
3073 		case PTB_EO_CHORD:
3074 		{
3075 			ui.editOpScreen = 3;
3076 			renderEditOpScreen();
3077 		}
3078 		break;
3079 
3080 		// fade up
3081 		case PTB_EO_FU:
3082 		{
3083 			if (editor.sampleZero)
3084 			{
3085 				statusNotSampleZero();
3086 				break;
3087 			}
3088 
3089 			s = &song->samples[editor.currSample];
3090 			if (s->length == 0)
3091 			{
3092 				statusSampleIsEmpty();
3093 				break;
3094 			}
3095 
3096 			if (editor.samplePos == 0)
3097 			{
3098 				displayErrorMsg("INVALID POS !");
3099 				break;
3100 			}
3101 
3102 			double dSamplePosMul = 1.0 / editor.samplePos;
3103 
3104 			ptr8_1 = &song->sampleData[s->offset];
3105 			for (j = 0; j < editor.samplePos; j++)
3106 			{
3107 				dSmp = ((*ptr8_1) * j) * dSamplePosMul;
3108 				smp32 = (int32_t)dSmp;
3109 				CLAMP8(smp32);
3110 				*ptr8_1++ = (int8_t)smp32;
3111 			}
3112 
3113 			fixSampleBeep(s);
3114 			if (ui.samplerScreenShown)
3115 				displaySample();
3116 
3117 			updateWindowTitle(MOD_IS_MODIFIED);
3118 		}
3119 		break;
3120 
3121 		// fade down
3122 		case PTB_EO_FD:
3123 		{
3124 			if (editor.sampleZero)
3125 			{
3126 				statusNotSampleZero();
3127 				break;
3128 			}
3129 
3130 			s = &song->samples[editor.currSample];
3131 			if (s->length == 0)
3132 			{
3133 				statusSampleIsEmpty();
3134 				break;
3135 			}
3136 
3137 			if (editor.samplePos >= s->length-1)
3138 			{
3139 				displayErrorMsg("INVALID POS !");
3140 				break;
3141 			}
3142 
3143 			tmp32 = (s->length - 1) - editor.samplePos;
3144 			if (tmp32 == 0)
3145 				tmp32 = 1;
3146 
3147 			double dSampleMul = 1.0 / tmp32;
3148 
3149 			ptr8_1 = &song->sampleData[s->offset+s->length-1];
3150 
3151 			int32_t idx = 0;
3152 			for (j = editor.samplePos; j < s->length; j++)
3153 			{
3154 				dSmp = ((*ptr8_1) * idx) * dSampleMul;
3155 				smp32 = (int32_t)dSmp;
3156 				CLAMP8(smp32);
3157 				*ptr8_1-- = (int8_t)smp32;
3158 
3159 				idx++;
3160 			}
3161 
3162 			fixSampleBeep(s);
3163 			if (ui.samplerScreenShown)
3164 				displaySample();
3165 
3166 			updateWindowTitle(MOD_IS_MODIFIED);
3167 		}
3168 		break;
3169 
3170 		case PTB_EO_UPSAMP:
3171 		{
3172 			s = &song->samples[editor.currSample];
3173 			if (s->length == 0)
3174 			{
3175 				statusSampleIsEmpty();
3176 				break;
3177 			}
3178 
3179 			ui.askScreenShown = true;
3180 			ui.askScreenType = ASK_UPSAMPLE;
3181 			pointerSetMode(POINTER_MODE_MSG1, NO_CARRY);
3182 			setStatusMessage("UPSAMPLE ?", NO_CARRY);
3183 			renderAskDialog();
3184 		}
3185 		break;
3186 
3187 		case PTB_EO_DNSAMP:
3188 		{
3189 			s = &song->samples[editor.currSample];
3190 			if (s->length == 0)
3191 			{
3192 				statusSampleIsEmpty();
3193 				break;
3194 			}
3195 
3196 			ui.askScreenShown = true;
3197 			ui.askScreenType = ASK_DOWNSAMPLE;
3198 			pointerSetMode(POINTER_MODE_MSG1, NO_CARRY);
3199 			setStatusMessage("DOWNSAMPLE ?", NO_CARRY);
3200 			renderAskDialog();
3201 		}
3202 		break;
3203 
3204 		case PTB_EO_VOL_NUM:
3205 		{
3206 			if (mouse.rightButtonPressed)
3207 			{
3208 				editor.sampleVol = 100;
3209 				ui.updateVolText = true;
3210 			}
3211 			else
3212 			{
3213 				ui.tmpDisp16 = editor.sampleVol;
3214 				editor.sampleVolDisp = &ui.tmpDisp16;
3215 				ui.numPtr16 = &ui.tmpDisp16;
3216 				ui.numLen = 3;
3217 				ui.editTextPos = 3711; // (y * 40) + x
3218 				getNumLine(TEXT_EDIT_DECIMAL, PTB_EO_VOL_NUM);
3219 			}
3220 		}
3221 		break;
3222 
3223 		case PTB_EO_VOL:
3224 		{
3225 			if (editor.sampleZero)
3226 			{
3227 				statusNotSampleZero();
3228 				break;
3229 			}
3230 
3231 			s = &song->samples[editor.currSample];
3232 			if (s->length == 0)
3233 			{
3234 				statusSampleIsEmpty();
3235 				break;
3236 			}
3237 
3238 			if (editor.sampleVol != 100)
3239 			{
3240 				ptr8_1 = &song->sampleData[s->offset];
3241 				int32_t sampleMul = (((1UL << 19) * editor.sampleVol) + 50) / 100;
3242 
3243 				for (j = 0; j < s->length; j++)
3244 				{
3245 					tmp16 = (ptr8_1[j] * sampleMul) >> 19;
3246 					CLAMP8(tmp16);
3247 					ptr8_1[j] = (int8_t)tmp16;
3248 				}
3249 
3250 				fixSampleBeep(s);
3251 				if (ui.samplerScreenShown)
3252 					displaySample();
3253 
3254 				updateWindowTitle(MOD_IS_MODIFIED);
3255 			}
3256 		}
3257 		break;
3258 
3259 		case PTB_EO_VOL_UP: edVolUpButton(); break;
3260 		case PTB_EO_VOL_DOWN: edVolDownButton(); break;
3261 		// ----------------------------------------------------------
3262 
3263 		// Edit Op. Screen #4 (chord maker)
3264 
3265 		case PTB_EO_DOCHORD: makeChord(); break;
3266 		case PTB_EO_NOTE1: selectChordNote1(); break;
3267 		case PTB_EO_NOTE2: selectChordNote2(); break;
3268 		case PTB_EO_NOTE3: selectChordNote3(); break;
3269 		case PTB_EO_NOTE4: selectChordNote4(); break;
3270 		case PTB_EO_NOTE1_UP: edNote1UpButton(); break;
3271 		case PTB_EO_NOTE1_DOWN: edNote1DownButton(); break;
3272 		case PTB_EO_NOTE2_UP: edNote2UpButton(); break;
3273 		case PTB_EO_NOTE2_DOWN: edNote2DownButton(); break;
3274 		case PTB_EO_NOTE3_UP: edNote3UpButton(); break;
3275 		case PTB_EO_NOTE3_DOWN: edNote3DownButton(); break;
3276 		case PTB_EO_NOTE4_UP: edNote4UpButton(); break;
3277 		case PTB_EO_NOTE4_DOWN: edNote4DownButton(); break;
3278 		case PTB_EO_RESET: resetChord(); break;
3279 		case PTB_EO_UNDO: undoChord(); break;
3280 		case PTB_EO_LENGTH: toggleChordLength(); break;
3281 		case PTB_EO_MAJOR: setChordMajor(); break;
3282 		case PTB_EO_MINOR: setChordMinor(); break;
3283 		case PTB_EO_SUS4: setChordSus4(); break;
3284 		case PTB_EO_MAJOR7: setChordMajor7(); break;
3285 		case PTB_EO_MINOR7: setChordMinor7(); break;
3286 		case PTB_EO_MAJOR6: setChordMajor6(); break;
3287 		case PTB_EO_MINOR6: setChordMinor6(); break;
3288 		// ----------------------------------------------------------
3289 
3290 		case PTB_ABOUT:
3291 		{
3292 			ui.aboutScreenShown ^= 1;
3293 
3294 			if (ui.aboutScreenShown)
3295 				renderAboutScreen();
3296 			else if (ui.visualizerMode == VISUAL_QUADRASCOPE)
3297 				renderQuadrascopeBg();
3298 			else if (ui.visualizerMode == VISUAL_SPECTRUM)
3299 				renderSpectrumAnalyzerBg();
3300 		}
3301 		break;
3302 
3303 		case PTB_PE_PATT:
3304 		{
3305 			if (editor.currMode == MODE_IDLE || editor.currMode == MODE_EDIT)
3306 			{
3307 				ui.tmpDisp16 = song->currOrder;
3308 				if (ui.tmpDisp16 > song->header.numOrders-1)
3309 					ui.tmpDisp16 = song->header.numOrders-1;
3310 
3311 				ui.tmpDisp16 = song->header.order[ui.tmpDisp16];
3312 				editor.currPosEdPattDisp = &ui.tmpDisp16;
3313 				ui.numPtr16 = &ui.tmpDisp16;
3314 				ui.numLen = 2;
3315 				ui.editTextPos = 2180; // (y * 40) + x
3316 				getNumLine(TEXT_EDIT_DECIMAL, PTB_PE_PATT);
3317 			}
3318 		}
3319 		break;
3320 
3321 		case PTB_PE_SCROLLTOP:
3322 		{
3323 			if (song->currOrder != 0)
3324 				modSetPos(0, DONT_SET_ROW);
3325 		}
3326 		break;
3327 
3328 		case PTB_PE_SCROLLUP:
3329 		{
3330 			if (song->currOrder > 0)
3331 				modSetPos(song->currOrder - 1, DONT_SET_ROW);
3332 		}
3333 		break;
3334 
3335 		case PTB_PE_SCROLLDOWN:
3336 		{
3337 			if (song->currOrder < song->header.numOrders-1)
3338 				modSetPos(song->currOrder + 1, DONT_SET_ROW);
3339 		}
3340 		break;
3341 
3342 		case PTB_PE_SCROLLBOT:
3343 		{
3344 			if (song->currOrder != song->header.numOrders-1)
3345 				modSetPos(song->header.numOrders - 1, DONT_SET_ROW);
3346 		}
3347 		break;
3348 
3349 		case PTB_PE_EXIT:
3350 		{
3351 			ui.aboutScreenShown = false;
3352 			ui.posEdScreenShown = false;
3353 			displayMainScreen();
3354 		}
3355 		break;
3356 
3357 		case PTB_POS:
3358 		case PTB_POSED:
3359 		{
3360 			ui.posEdScreenShown ^= 1;
3361 			if (ui.posEdScreenShown)
3362 			{
3363 				renderPosEdScreen();
3364 				ui.updatePosEd = true;
3365 			}
3366 			else
3367 			{
3368 				displayMainScreen();
3369 			}
3370 		}
3371 		break;
3372 
3373 		case PTB_POSS:
3374 		{
3375 			if (editor.currMode == MODE_IDLE || editor.currMode == MODE_EDIT)
3376 			{
3377 				if (mouse.rightButtonPressed)
3378 				{
3379 					song->currOrder = 0;
3380 					editor.currPatternDisp = &song->header.order[song->currOrder];
3381 
3382 					if (ui.posEdScreenShown)
3383 						ui.updatePosEd = true;
3384 				}
3385 				else
3386 				{
3387 					ui.tmpDisp16 = song->currOrder;
3388 					editor.currPosDisp = &ui.tmpDisp16;
3389 					ui.numPtr16 = &ui.tmpDisp16;
3390 					ui.numLen = 3;
3391 					ui.editTextPos = 169; // (y * 40) + x
3392 					getNumLine(TEXT_EDIT_DECIMAL, PTB_POSS);
3393 				}
3394 			}
3395 		}
3396 		break;
3397 
3398 		case PTB_PATTERNS:
3399 		{
3400 			if (editor.currMode == MODE_IDLE || editor.currMode == MODE_EDIT)
3401 			{
3402 				if (mouse.rightButtonPressed)
3403 				{
3404 					song->header.order[song->currOrder] = 0;
3405 
3406 					ui.updateSongSize = true;
3407 					updateWindowTitle(MOD_IS_MODIFIED);
3408 
3409 					if (ui.posEdScreenShown)
3410 						ui.updatePosEd = true;
3411 				}
3412 				else
3413 				{
3414 					ui.tmpDisp16 = song->header.order[song->currOrder];
3415 					editor.currPatternDisp = &ui.tmpDisp16;
3416 					ui.numPtr16 = &ui.tmpDisp16;
3417 					ui.numLen = 2;
3418 					ui.editTextPos = 610; // (y * 40) + x
3419 					getNumLine(TEXT_EDIT_DECIMAL, PTB_PATTERNS);
3420 				}
3421 			}
3422 		}
3423 		break;
3424 
3425 		case PTB_LENGTHS:
3426 		{
3427 			if (editor.currMode == MODE_IDLE || editor.currMode == MODE_EDIT)
3428 			{
3429 				if (mouse.rightButtonPressed)
3430 				{
3431 					song->header.numOrders = 1;
3432 
3433 					tmp16 = song->currOrder;
3434 					if (tmp16 > song->header.numOrders-1)
3435 						tmp16 = song->header.numOrders-1;
3436 
3437 					editor.currPosEdPattDisp = &song->header.order[tmp16];
3438 
3439 					ui.updateSongSize = true;
3440 					updateWindowTitle(MOD_IS_MODIFIED);
3441 
3442 					if (ui.posEdScreenShown)
3443 						ui.updatePosEd = true;
3444 				}
3445 				else
3446 				{
3447 					ui.tmpDisp16 = song->header.numOrders;
3448 					editor.currLengthDisp = &ui.tmpDisp16;
3449 					ui.numPtr16 = &ui.tmpDisp16;
3450 					ui.numLen = 3;
3451 					ui.editTextPos = 1049; // (y * 40) + x
3452 					getNumLine(TEXT_EDIT_DECIMAL, PTB_LENGTHS);
3453 				}
3454 			}
3455 		}
3456 		break;
3457 
3458 		case PTB_PATTBOX:
3459 		case PTB_PATTDATA:
3460 		{
3461 			if (!ui.introScreenShown && (editor.currMode == MODE_IDLE || editor.currMode == MODE_EDIT || editor.playMode != PLAY_MODE_NORMAL))
3462 			{
3463 				ui.tmpDisp16 = song->currPattern;
3464 				editor.currEditPatternDisp = &ui.tmpDisp16;
3465 				ui.numPtr16 = &ui.tmpDisp16;
3466 				ui.numLen = 2;
3467 				ui.editTextPos = 5121; // (y * 40) + x
3468 				getNumLine(TEXT_EDIT_DECIMAL, PTB_PATTDATA);
3469 			}
3470 		}
3471 		break;
3472 
3473 		case PTB_SAMPLES:
3474 		{
3475 			if (editor.sampleZero)
3476 			{
3477 				editor.sampleZero = false;
3478 				ui.updateCurrSampleNum = true;
3479 			}
3480 
3481 			ui.tmpDisp8 = editor.currSample;
3482 			editor.currSampleDisp = &ui.tmpDisp8;
3483 			ui.numPtr8 = &ui.tmpDisp8;
3484 			ui.numLen = 2;
3485 			ui.numBits = 8;
3486 			ui.editTextPos = 1930; // (y * 40) + x
3487 			getNumLine(TEXT_EDIT_HEX, PTB_SAMPLES);
3488 		}
3489 		break;
3490 
3491 		case PTB_SVOLUMES:
3492 		{
3493 			if (editor.sampleZero)
3494 			{
3495 				statusNotSampleZero();
3496 				break;
3497 			}
3498 
3499 			if (mouse.rightButtonPressed)
3500 			{
3501 				song->samples[editor.currSample].volume = 0;
3502 			}
3503 			else
3504 			{
3505 				ui.tmpDisp8 = song->samples[editor.currSample].volume;
3506 				song->samples[editor.currSample].volumeDisp = &ui.tmpDisp8;
3507 				ui.numPtr8 = &ui.tmpDisp8;
3508 				ui.numLen = 2;
3509 				ui.numBits = 8;
3510 				ui.editTextPos = 2370; // (y * 40) + x
3511 				getNumLine(TEXT_EDIT_HEX, PTB_SVOLUMES);
3512 			}
3513 		}
3514 		break;
3515 
3516 		case PTB_SLENGTHS:
3517 		{
3518 			if (editor.sampleZero)
3519 			{
3520 				statusNotSampleZero();
3521 				break;
3522 			}
3523 
3524 			if (mouse.rightButtonPressed)
3525 			{
3526 				s = &song->samples[editor.currSample];
3527 
3528 				turnOffVoices();
3529 
3530 				s->length = 0;
3531 				if (s->loopStart+s->loopLength > 2)
3532 				{
3533 					if (s->length < s->loopStart+s->loopLength)
3534 						s->length = s->loopStart+s->loopLength;
3535 				}
3536 
3537 				ui.updateSongSize = true;
3538 				ui.updateCurrSampleLength = true;
3539 
3540 				if (ui.samplerScreenShown)
3541 					redrawSample();
3542 
3543 				recalcChordLength();
3544 				updateWindowTitle(MOD_IS_MODIFIED);
3545 			}
3546 			else
3547 			{
3548 				ui.tmpDisp16 = song->samples[editor.currSample].length;
3549 				song->samples[editor.currSample].lengthDisp = &ui.tmpDisp16;
3550 				ui.numPtr16 = &ui.tmpDisp16;
3551 				ui.numLen = 4;
3552 				ui.numBits = 16;
3553 				ui.editTextPos = 2808; // (y * 40) + x
3554 				getNumLine(TEXT_EDIT_HEX, PTB_SLENGTHS);
3555 			}
3556 		}
3557 		break;
3558 
3559 		case PTB_SREPEATS:
3560 		{
3561 			if (editor.sampleZero)
3562 			{
3563 				statusNotSampleZero();
3564 				break;
3565 			}
3566 
3567 			if (mouse.rightButtonPressed)
3568 			{
3569 				s = &song->samples[editor.currSample];
3570 
3571 				s->loopStart = 0;
3572 				if (s->length >= s->loopLength)
3573 				{
3574 					if (s->loopStart+s->loopLength > s->length)
3575 						s->loopStart = s->length-s->loopLength;
3576 				}
3577 				else
3578 				{
3579 					s->loopStart = 0;
3580 				}
3581 
3582 				ui.updateCurrSampleRepeat = true;
3583 				if (ui.editOpScreenShown && ui.editOpScreen == 3)
3584 					ui.updateLengthText = true;
3585 
3586 				if (ui.samplerScreenShown)
3587 					setLoopSprites();
3588 
3589 				mixerUpdateLoops();
3590 				updateWindowTitle(MOD_IS_MODIFIED);
3591 			}
3592 			else
3593 			{
3594 				ui.tmpDisp16 = song->samples[editor.currSample].loopStart;
3595 				song->samples[editor.currSample].loopStartDisp = &ui.tmpDisp16;
3596 				ui.numPtr16 = &ui.tmpDisp16;
3597 				ui.numLen = 4;
3598 				ui.numBits = 16;
3599 				ui.editTextPos = 3248; // (y * 40) + x
3600 				getNumLine(TEXT_EDIT_HEX, PTB_SREPEATS);
3601 			}
3602 		}
3603 		break;
3604 
3605 		case PTB_SREPLENS:
3606 		{
3607 			if (editor.sampleZero)
3608 			{
3609 				statusNotSampleZero();
3610 				break;
3611 			}
3612 
3613 			if (mouse.rightButtonPressed)
3614 			{
3615 				s = &song->samples[editor.currSample];
3616 
3617 				s->loopLength = 0;
3618 				if (s->length >= s->loopStart)
3619 				{
3620 					if (s->loopStart+s->loopLength > s->length)
3621 						s->loopLength = s->length-s->loopStart;
3622 				}
3623 				else
3624 				{
3625 					s->loopLength = 2;
3626 				}
3627 
3628 				if (s->loopLength < 2)
3629 					s->loopLength = 2;
3630 
3631 				ui.updateCurrSampleReplen = true;
3632 				if (ui.editOpScreenShown && ui.editOpScreen == 3)
3633 					ui.updateLengthText = true;
3634 
3635 				if (ui.samplerScreenShown)
3636 					setLoopSprites();
3637 
3638 				mixerUpdateLoops();
3639 				updateWindowTitle(MOD_IS_MODIFIED);
3640 			}
3641 			else
3642 			{
3643 				ui.tmpDisp16 = song->samples[editor.currSample].loopLength;
3644 				song->samples[editor.currSample].loopLengthDisp = &ui.tmpDisp16;
3645 				ui.numPtr16 = &ui.tmpDisp16;
3646 				ui.numLen = 4;
3647 				ui.numBits = 16;
3648 				ui.editTextPos = 3688; // (y * 40) + x
3649 				getNumLine(TEXT_EDIT_HEX, PTB_SREPLENS);
3650 			}
3651 		}
3652 		break;
3653 
3654 		case PTB_EDITOP:
3655 		{
3656 			if (ui.editOpScreenShown)
3657 			{
3658 				if (ui.editOpScreen == 3)
3659 					ui.editOpScreen = 0;
3660 				else
3661 					ui.editOpScreen = (ui.editOpScreen + 1) % 3;
3662 			}
3663 			else
3664 			{
3665 				ui.editOpScreenShown = true;
3666 			}
3667 
3668 			renderEditOpScreen();
3669 		}
3670 		break;
3671 
3672 		case PTB_DO_LOADMODULE:
3673 		{
3674 			diskop.mode = DISKOP_MODE_MOD;
3675 			setPathFromDiskOpMode();
3676 			diskop.scrollOffset = 0;
3677 			diskop.cached = false;
3678 			ui.updateDiskOpFileList = true;
3679 			ui.updateLoadMode = true;
3680 		}
3681 		break;
3682 
3683 		case PTB_DO_LOADSAMPLE:
3684 		{
3685 			diskop.mode = DISKOP_MODE_SMP;
3686 			setPathFromDiskOpMode();
3687 			diskop.scrollOffset = 0;
3688 			diskop.cached = false;
3689 			ui.updateDiskOpFileList = true;
3690 			ui.updateLoadMode = true;
3691 		}
3692 		break;
3693 
3694 		case PTB_LOADSAMPLE: // "LOAD" button next to sample name
3695 		{
3696 			ui.posEdScreenShown = false;
3697 			diskop.mode = DISKOP_MODE_SMP;
3698 			setPathFromDiskOpMode();
3699 			diskop.scrollOffset = 0;
3700 			diskop.cached = false;
3701 
3702 			if (!ui.diskOpScreenShown)
3703 			{
3704 				ui.diskOpScreenShown = true;
3705 				renderDiskOpScreen();
3706 			}
3707 			else
3708 			{
3709 				ui.updateDiskOpFileList = true;
3710 				ui.updateLoadMode = true;
3711 			}
3712 		}
3713 		break;
3714 
3715 		case PTB_DO_SAVESAMPLE:
3716 		{
3717 			if (diskop.mode != DISKOP_MODE_SMP)
3718 			{
3719 				diskop.mode = DISKOP_MODE_SMP;
3720 				setPathFromDiskOpMode();
3721 				diskop.scrollOffset = 0;
3722 				diskop.cached = false;
3723 				ui.updateLoadMode = true;
3724 			}
3725 
3726 			ui.askScreenShown = true;
3727 			ui.askScreenType = ASK_SAVE_SAMPLE;
3728 			pointerSetMode(POINTER_MODE_MSG1, NO_CARRY);
3729 			setStatusMessage("SAVE SAMPLE ?", NO_CARRY);
3730 			renderAskDialog();
3731 		}
3732 		break;
3733 
3734 		case PTB_MOD2WAV:
3735 		{
3736 			ui.askScreenShown = true;
3737 			ui.askScreenType = ASK_MOD2WAV;
3738 			pointerSetMode(POINTER_MODE_MSG1, NO_CARRY);
3739 			setStatusMessage("RENDER WAV FILE?", NO_CARRY);
3740 			renderAskDialog();
3741 		}
3742 		break;
3743 
3744 		case PTB_SA_SAMPLE:
3745 		{
3746 			ui.samplingBoxShown = true;
3747 			renderSamplingBox();
3748 		}
3749 		break;
3750 
3751 		case PTB_SA_RESAMPLE:
3752 		{
3753 			ui.askScreenShown = true;
3754 			ui.askScreenType = ASK_RESAMPLE;
3755 			pointerSetMode(POINTER_MODE_MSG1, NO_CARRY);
3756 			setStatusMessage("RESAMPLE?", NO_CARRY);
3757 			renderAskDialog();
3758 		}
3759 		break;
3760 
3761 		case PTB_SA_RESAMPLENOTE:
3762 		{
3763 			ui.changingSmpResample = true;
3764 			ui.updateResampleNote = true;
3765 			setStatusMessage("SELECT NOTE", NO_CARRY);
3766 			pointerSetMode(POINTER_MODE_MSG1, NO_CARRY);
3767 		}
3768 		break;
3769 
3770 		case PTB_SA_SAMPLEAREA:
3771 		{
3772 			if (ui.sampleMarkingPos == -1)
3773 			{
3774 				samplerSamplePressed(MOUSE_BUTTON_NOT_HELD);
3775 				return true;
3776 			}
3777 		}
3778 		break;
3779 
3780 		case PTB_SA_ZOOMBARAREA:
3781 		{
3782 			mouse.lastGUIButton = button;
3783 			if (!ui.forceSampleDrag)
3784 			{
3785 				samplerBarPressed(MOUSE_BUTTON_NOT_HELD);
3786 				return true;
3787 			}
3788 		}
3789 		break;
3790 
3791 		case PTB_SA_FIXDC: samplerRemoveDcOffset(); break;
3792 		case PTB_SA_CUT: samplerSamDelete(SAMPLE_CUT); break;
3793 		case PTB_SA_PASTE: samplerSamPaste(); break;
3794 		case PTB_SA_COPY: samplerSamCopy(); break;
3795 		case PTB_SA_LOOP: samplerLoopToggle(); break;
3796 		case PTB_SA_PLAYWAVE: samplerPlayWaveform(); break;
3797 		case PTB_SA_PLAYDISPLAY: samplerPlayDisplay(); break;
3798 		case PTB_SA_PLAYRANGE: samplerPlayRange(); break;
3799 		case PTB_SA_RANGEALL: samplerRangeAll(); break;
3800 		case PTB_SA_SHOWALL: samplerShowAll(); break;
3801 		case PTB_SA_SHOWRANGE: samplerShowRange(); break;
3802 		case PTB_SA_RANGECENTER: sampleMarkerToCenter(); break;
3803 		case PTB_SA_RANGEBEG: sampleMarkerToBeg(); break;
3804 		case PTB_SA_RANGEEND: sampleMarkerToEnd(); break;
3805 		case PTB_SA_ZOOMOUT: samplerZoomOut2x(); break;
3806 
3807 		case PTB_SA_VOLUME:
3808 		{
3809 			ui.samplerVolBoxShown = true;
3810 			renderSamplerVolBox();
3811 		}
3812 		break;
3813 
3814 		case PTB_SA_FILTERS:
3815 		{
3816 			ui.samplerFiltersBoxShown = true;
3817 			renderSamplerFiltersBox();
3818 			fillSampleFilterUndoBuffer();
3819 		}
3820 		break;
3821 
3822 		case PTB_SA_STOP:
3823 		{
3824 			for (i = 0; i < AMIGA_VOICES; i++)
3825 				mixerKillVoice(i);
3826 		}
3827 		break;
3828 
3829 		case PTB_DO_REFRESH:
3830 		{
3831 			diskop.scrollOffset = 0;
3832 			diskop.cached = false;
3833 			ui.updateDiskOpFileList = true;
3834 		}
3835 		break;
3836 
3837 		// TODO: Find a PowerPacker packer and enable this
3838 		// case PTB_DO_PACKMOD: diskop.modPackFlg ^= 1; break;
3839 
3840 		case PTB_DO_SAMPLEFORMAT:
3841 		{
3842 			diskop.smpSaveType = (diskop.smpSaveType + 1) % 3;
3843 			ui.updateSaveFormatText = true;
3844 		}
3845 		break;
3846 
3847 		case PTB_DO_MODARROW:
3848 		{
3849 			diskop.mode = DISKOP_MODE_MOD;
3850 			diskop.scrollOffset = 0;
3851 			diskop.cached = false;
3852 			ui.updateDiskOpFileList = true;
3853 			ui.updateLoadMode = true;
3854 		}
3855 		break;
3856 
3857 		case PTB_DO_SAMPLEARROW:
3858 		{
3859 			diskop.mode = DISKOP_MODE_SMP;
3860 			diskop.scrollOffset = 0;
3861 			diskop.cached = false;
3862 			ui.updateDiskOpFileList = true;
3863 			ui.updateLoadMode = true;
3864 		}
3865 		break;
3866 
3867 		case PTB_SA_TUNETONE: toggleTuningTone(); break;
3868 
3869 		case PTB_POSINS:
3870 		{
3871 			if ((editor.currMode == MODE_IDLE || editor.currMode == MODE_EDIT) && song->header.numOrders < 128)
3872 			{
3873 				for (i = 0; i < 127-song->currOrder; i++)
3874 					song->header.order[127-i] = song->header.order[(127-i)-1];
3875 				song->header.order[song->currOrder] = 0;
3876 
3877 				song->header.numOrders++;
3878 				if (song->currOrder > song->header.numOrders-1)
3879 					editor.currPosEdPattDisp = &song->header.order[song->header.numOrders-1];
3880 
3881 				updateWindowTitle(MOD_IS_MODIFIED);
3882 
3883 				ui.updateSongSize = true;
3884 				ui.updateSongLength = true;
3885 				ui.updateSongPattern = true;
3886 
3887 				if (ui.posEdScreenShown)
3888 					ui.updatePosEd = true;
3889 			}
3890 		}
3891 		break;
3892 
3893 		case PTB_POSDEL:
3894 		{
3895 			if ((editor.currMode == MODE_IDLE || editor.currMode == MODE_EDIT) && song->header.numOrders > 1)
3896 			{
3897 				for (i = 0; i < 128-song->currOrder; i++)
3898 					song->header.order[song->currOrder+i] = song->header.order[song->currOrder+i+1];
3899 				song->header.order[127] = 0;
3900 
3901 				song->header.numOrders--;
3902 				if (song->currOrder > song->header.numOrders-1)
3903 					editor.currPosEdPattDisp = &song->header.order[song->header.numOrders-1];
3904 
3905 				updateWindowTitle(MOD_IS_MODIFIED);
3906 
3907 				ui.updateSongSize = true;
3908 				ui.updateSongLength = true;
3909 				ui.updateSongPattern = true;
3910 
3911 				if (ui.posEdScreenShown)
3912 					ui.updatePosEd = true;
3913 			}
3914 		}
3915 		break;
3916 
3917 		case PTB_DO_SAVEMODULE:
3918 		{
3919 			if (diskop.mode != DISKOP_MODE_MOD)
3920 			{
3921 				diskop.mode = DISKOP_MODE_MOD;
3922 				setPathFromDiskOpMode();
3923 				diskop.scrollOffset = 0;
3924 				diskop.cached = false;
3925 				ui.updateLoadMode = true;
3926 			}
3927 
3928 			ui.askScreenShown = true;
3929 			ui.askScreenType = ASK_SAVE_MODULE;
3930 			pointerSetMode(POINTER_MODE_MSG1, NO_CARRY);
3931 			setStatusMessage("SAVE MODULE ?", NO_CARRY);
3932 			renderAskDialog();
3933 		}
3934 		break;
3935 
3936 		case PTB_DO_DATAPATH:
3937 		{
3938 			if (mouse.rightButtonPressed)
3939 			{
3940 				memset(editor.currPath, 0, PATH_MAX + 1);
3941 				ui.updateDiskOpPathText = true;
3942 			}
3943 
3944 			ui.showTextPtr = editor.currPath;
3945 			ui.textEndPtr = &editor.currPath[PATH_MAX - 1];
3946 			ui.textLength = 26;
3947 			ui.editTextPos = 1043; // (y * 40) + x
3948 			ui.dstOffset = &ui.diskOpPathTextOffset;
3949 			ui.dstOffsetEnd = false;
3950 			getTextLine(PTB_DO_DATAPATH);
3951 		}
3952 		break;
3953 
3954 		case PTB_SONGNAME:
3955 		{
3956 			if (mouse.rightButtonPressed)
3957 			{
3958 				memset(song->header.name, 0, sizeof (song->header.name));
3959 				ui.updateSongName = true;
3960 				updateWindowTitle(MOD_IS_MODIFIED);
3961 			}
3962 			else
3963 			{
3964 				ui.showTextPtr = song->header.name;
3965 				ui.textEndPtr = song->header.name + 19;
3966 				ui.textLength = 20;
3967 				ui.editTextPos = 4133; // (y * 40) + x
3968 				ui.dstOffset = NULL;
3969 				ui.dstOffsetEnd = false;
3970 				getTextLine(PTB_SONGNAME);
3971 			}
3972 		}
3973 		break;
3974 
3975 		case PTB_SAMPLENAME:
3976 		{
3977 			if (mouse.rightButtonPressed)
3978 			{
3979 				memset(song->samples[editor.currSample].text, 0, sizeof (song->samples[editor.currSample].text));
3980 				ui.updateCurrSampleName = true;
3981 				updateWindowTitle(MOD_IS_MODIFIED);
3982 			}
3983 			else
3984 			{
3985 				ui.showTextPtr = song->samples[editor.currSample].text;
3986 				ui.textEndPtr = song->samples[editor.currSample].text + 21;
3987 				ui.textLength = 22;
3988 				ui.editTextPos = 4573; // (y * 40) + x
3989 				ui.dstOffset = NULL;
3990 				ui.dstOffsetEnd = false;
3991 				getTextLine(PTB_SAMPLENAME);
3992 			}
3993 		}
3994 		break;
3995 
3996 		case PTB_PAT2SMP_HI:
3997 		{
3998 			ui.askScreenShown = false;
3999 			ui.answerNo = false;
4000 			ui.answerYes = true;
4001 			editor.pat2SmpHQ = true;
4002 			handleAskYes();
4003 		}
4004 		break;
4005 
4006 		case PTB_PAT2SMP_LO:
4007 		{
4008 			ui.askScreenShown = false;
4009 			ui.answerNo = false;
4010 			ui.answerYes = true;
4011 			editor.pat2SmpHQ = false;
4012 			handleAskYes();
4013 		}
4014 		break;
4015 
4016 		case PTB_SUREY:
4017 		{
4018 			ui.askScreenShown = false;
4019 			ui.answerNo = false;
4020 			ui.answerYes = true;
4021 			handleAskYes();
4022 		}
4023 		break;
4024 
4025 		case PTB_PAT2SMP_ABORT:
4026 		case PTB_SUREN:
4027 		{
4028 			ui.askScreenShown = false;
4029 			ui.answerNo = true;
4030 			ui.answerYes = false;
4031 			handleAskNo();
4032 		}
4033 		break;
4034 
4035 		case PTB_VISUALS:
4036 		{
4037 			if (ui.aboutScreenShown)
4038 			{
4039 				ui.aboutScreenShown = false;
4040 			}
4041 			else if (!mouse.rightButtonPressed)
4042 			{
4043 				ui.visualizerMode = (ui.visualizerMode + 1) % 2;
4044 				if (ui.visualizerMode == VISUAL_SPECTRUM)
4045 					memset((int8_t *)editor.spectrumVolumes, 0, sizeof (editor.spectrumVolumes));
4046 			}
4047 
4048 			if (ui.visualizerMode == VISUAL_QUADRASCOPE)
4049 				renderQuadrascopeBg();
4050 			else if (ui.visualizerMode == VISUAL_SPECTRUM)
4051 				renderSpectrumAnalyzerBg();
4052 		}
4053 		break;
4054 
4055 		case PTB_QUIT:
4056 		{
4057 			ui.askScreenShown = true;
4058 			ui.askScreenType = ASK_QUIT;
4059 			pointerSetMode(POINTER_MODE_MSG1, NO_CARRY);
4060 			setStatusMessage("REALLY QUIT ?", NO_CARRY);
4061 			renderAskDialog();
4062 		}
4063 		break;
4064 
4065 		case PTB_CHAN1:
4066 		{
4067 			if (mouse.rightButtonPressed)
4068 			{
4069 				editor.muted[0] = false;
4070 				editor.muted[1] = true;
4071 				editor.muted[2] = true;
4072 				editor.muted[3] = true;
4073 			}
4074 			else
4075 			{
4076 				editor.muted[0] ^= 1;
4077 			}
4078 
4079 			renderMuteButtons();
4080 		}
4081 		break;
4082 
4083 		case PTB_CHAN2:
4084 		{
4085 			if (mouse.rightButtonPressed)
4086 			{
4087 				editor.muted[0] = true;
4088 				editor.muted[1] = false;
4089 				editor.muted[2] = true;
4090 				editor.muted[3] = true;
4091 			}
4092 			else
4093 			{
4094 				editor.muted[1] ^= 1;
4095 			}
4096 
4097 			renderMuteButtons();
4098 		}
4099 		break;
4100 
4101 		case PTB_CHAN3:
4102 		{
4103 			if (mouse.rightButtonPressed)
4104 			{
4105 				editor.muted[0] = true;
4106 				editor.muted[1] = true;
4107 				editor.muted[2] = false;
4108 				editor.muted[3] = true;
4109 			}
4110 			else
4111 			{
4112 				editor.muted[2] ^= 1;
4113 			}
4114 
4115 			renderMuteButtons();
4116 		}
4117 		break;
4118 
4119 		case PTB_CHAN4:
4120 		{
4121 			if (mouse.rightButtonPressed)
4122 			{
4123 				editor.muted[0] = true;
4124 				editor.muted[1] = true;
4125 				editor.muted[2] = true;
4126 				editor.muted[3] = false;
4127 			}
4128 			else
4129 			{
4130 				editor.muted[3] ^= 1;
4131 			}
4132 
4133 			renderMuteButtons();
4134 		}
4135 		break;
4136 
4137 		case PTB_SAMPLER: samplerScreen(); break;
4138 		case PTB_SA_EXIT: exitFromSam();   break;
4139 
4140 		case PTB_DO_FILEAREA: diskOpLoadFile((mouse.y - 34) / 6, true); break;
4141 		case PTB_DO_PARENT:
4142 		{
4143 #ifdef _WIN32
4144 			diskOpSetPath(L"..", DISKOP_CACHE);
4145 #else
4146 			diskOpSetPath("..", DISKOP_CACHE);
4147 #endif
4148 		}
4149 		break;
4150 
4151 		case PTB_DISKOP:
4152 		{
4153 			editor.blockMarkFlag = false;
4154 			ui.diskOpScreenShown = true;
4155 			renderDiskOpScreen();
4156 		}
4157 		break;
4158 
4159 		case PTB_DO_EXIT:
4160 		{
4161 			ui.aboutScreenShown = false;
4162 			ui.diskOpScreenShown = false;
4163 			editor.blockMarkFlag = false;
4164 			pointerSetPreviousMode();
4165 			setPrevStatusMessage();
4166 			displayMainScreen();
4167 		}
4168 		break;
4169 
4170 		case PTB_DO_SCROLLUP:
4171 		{
4172 			if (diskop.scrollOffset > 0)
4173 			{
4174 				diskop.scrollOffset--;
4175 				ui.updateDiskOpFileList = true;
4176 			}
4177 		}
4178 		break;
4179 
4180 		case PTB_DO_SCROLLTOP:
4181 		{
4182 			diskop.scrollOffset = 0;
4183 			ui.updateDiskOpFileList = true;
4184 		}
4185 		break;
4186 
4187 		case PTB_DO_SCROLLDOWN:
4188 		{
4189 			if (diskop.numEntries > DISKOP_LINES && diskop.scrollOffset < diskop.numEntries-DISKOP_LINES)
4190 			{
4191 				diskop.scrollOffset++;
4192 				ui.updateDiskOpFileList = true;
4193 			}
4194 		}
4195 		break;
4196 
4197 		case PTB_DO_SCROLLBOT:
4198 		{
4199 			if (diskop.numEntries > DISKOP_LINES)
4200 			{
4201 				diskop.scrollOffset = diskop.numEntries - DISKOP_LINES;
4202 				ui.updateDiskOpFileList = true;
4203 			}
4204 		}
4205 		break;
4206 
4207 		case PTB_STOP:
4208 		{
4209 			editor.playMode = PLAY_MODE_NORMAL;
4210 			modStop();
4211 			editor.currMode = MODE_IDLE;
4212 			pointerSetMode(POINTER_MODE_IDLE, DO_CARRY);
4213 			statusAllRight();
4214 		}
4215 		break;
4216 
4217 		case PTB_PLAY:
4218 		{
4219 			editor.playMode = PLAY_MODE_NORMAL;
4220 
4221 			if (mouse.rightButtonPressed)
4222 				modPlay(DONT_SET_PATTERN, song->currOrder, song->currRow);
4223 			else
4224 				modPlay(DONT_SET_PATTERN, song->currOrder, DONT_SET_ROW);
4225 
4226 			editor.currMode = MODE_PLAY;
4227 			pointerSetMode(POINTER_MODE_PLAY, DO_CARRY);
4228 			statusAllRight();
4229 		}
4230 		break;
4231 
4232 		case PTB_PATTERN:
4233 		{
4234 			editor.playMode = PLAY_MODE_PATTERN;
4235 
4236 			if (mouse.rightButtonPressed)
4237 				modPlay(song->currPattern, DONT_SET_ORDER, song->currRow);
4238 			else
4239 				modPlay(song->currPattern, DONT_SET_ORDER, DONT_SET_ROW);
4240 
4241 			editor.currMode = MODE_PLAY;
4242 			pointerSetMode(POINTER_MODE_PLAY, DO_CARRY);
4243 			statusAllRight();
4244 		}
4245 		break;
4246 
4247 		case PTB_EDIT:
4248 		{
4249 			if (!ui.samplerScreenShown)
4250 			{
4251 				editor.playMode = PLAY_MODE_NORMAL;
4252 				modStop();
4253 				editor.currMode = MODE_EDIT;
4254 				pointerSetMode(POINTER_MODE_EDIT, DO_CARRY);
4255 				statusAllRight();
4256 			}
4257 		}
4258 		break;
4259 
4260 		case PTB_RECORD:
4261 		{
4262 			if (!ui.samplerScreenShown)
4263 			{
4264 				editor.playMode = PLAY_MODE_PATTERN;
4265 
4266 				if (mouse.rightButtonPressed)
4267 					modPlay(song->currPattern, DONT_SET_ORDER, song->currRow);
4268 				else
4269 					modPlay(song->currPattern, DONT_SET_ORDER, DONT_SET_ROW);
4270 
4271 				editor.currMode = MODE_RECORD;
4272 				pointerSetMode(POINTER_MODE_EDIT, DO_CARRY);
4273 				statusAllRight();
4274 			}
4275 		}
4276 		break;
4277 
4278 		case PTB_CLEAR:
4279 		{
4280 			ui.clearScreenShown = true;
4281 			pointerSetMode(POINTER_MODE_MSG1, NO_CARRY);
4282 			setStatusMessage("PLEASE SELECT", NO_CARRY);
4283 			renderClearScreen();
4284 		}
4285 		break;
4286 
4287 		case PTB_CLEARSONG:
4288 		{
4289 			ui.clearScreenShown = false;
4290 			removeClearScreen();
4291 			editor.playMode = PLAY_MODE_NORMAL;
4292 			modStop();
4293 			clearSong();
4294 			editor.currMode = MODE_IDLE;
4295 			pointerSetMode(POINTER_MODE_IDLE, DO_CARRY);
4296 			statusAllRight();
4297 		}
4298 		break;
4299 
4300 		case PTB_CLEARSAMPLES:
4301 		{
4302 			ui.clearScreenShown = false;
4303 			removeClearScreen();
4304 			editor.playMode = PLAY_MODE_NORMAL;
4305 			modStop();
4306 			clearSamples();
4307 			editor.currMode = MODE_IDLE;
4308 			pointerSetMode(POINTER_MODE_IDLE, DO_CARRY);
4309 			statusAllRight();
4310 		}
4311 		break;
4312 
4313 		case PTB_CLEARALL:
4314 		{
4315 			ui.clearScreenShown = false;
4316 			removeClearScreen();
4317 			editor.playMode = PLAY_MODE_NORMAL;
4318 			modStop();
4319 			clearAll();
4320 			editor.currMode = MODE_IDLE;
4321 			pointerSetMode(POINTER_MODE_IDLE, DO_CARRY);
4322 			statusAllRight();
4323 		}
4324 		break;
4325 
4326 		case PTB_CLEARCANCEL:
4327 		{
4328 			ui.clearScreenShown = false;
4329 			removeClearScreen();
4330 			setPrevStatusMessage();
4331 			pointerSetPreviousMode();
4332 		}
4333 		break;
4334 
4335 		case PTB_SAMPLEU:
4336 		{
4337 			if (mouse.rightButtonPressed)
4338 			{
4339 				editor.sampleZero = true;
4340 				ui.updateCurrSampleNum = true;
4341 			}
4342 			else
4343 			{
4344 				sampleUpButton();
4345 			}
4346 		}
4347 		break;
4348 
4349 		case PTB_SAMPLED:
4350 		{
4351 			if (mouse.rightButtonPressed)
4352 			{
4353 				editor.sampleZero = true;
4354 				ui.updateCurrSampleNum = true;
4355 			}
4356 			else
4357 			{
4358 				sampleDownButton();
4359 			}
4360 		}
4361 		break;
4362 
4363 		case PTB_FTUNEU:
4364 		{
4365 			if (!editor.sampleZero && (song->samples[editor.currSample].fineTune & 0xF) != 7)
4366 			{
4367 				sampleFineTuneUpButton();
4368 				updateWindowTitle(MOD_IS_MODIFIED);
4369 			}
4370 		}
4371 		break;
4372 
4373 		case PTB_FTUNED:
4374 		{
4375 			if (!editor.sampleZero && (song->samples[editor.currSample].fineTune & 0xF) != 8)
4376 			{
4377 				sampleFineTuneDownButton();
4378 				updateWindowTitle(MOD_IS_MODIFIED);
4379 			}
4380 		}
4381 		break;
4382 
4383 		case PTB_SVOLUMEU:
4384 		{
4385 			if (!editor.sampleZero && song->samples[editor.currSample].volume < 64)
4386 			{
4387 				sampleVolumeUpButton();
4388 				updateWindowTitle(MOD_IS_MODIFIED);
4389 			}
4390 		}
4391 		break;
4392 
4393 		case PTB_SVOLUMED:
4394 		{
4395 			if (!editor.sampleZero && song->samples[editor.currSample].volume > 0)
4396 			{
4397 				sampleVolumeDownButton();
4398 				updateWindowTitle(MOD_IS_MODIFIED);
4399 			}
4400 		}
4401 		break;
4402 
4403 		case PTB_SLENGTHU:
4404 		{
4405 			if (!editor.sampleZero && song->samples[editor.currSample].length < MAX_SAMPLE_LEN)
4406 			{
4407 				sampleLengthUpButton(INCREMENT_SLOW);
4408 				updateWindowTitle(MOD_IS_MODIFIED);
4409 			}
4410 		}
4411 		break;
4412 
4413 		case PTB_SLENGTHD:
4414 		{
4415 			if (!editor.sampleZero && song->samples[editor.currSample].length > 0)
4416 			{
4417 				sampleLengthDownButton(INCREMENT_SLOW);
4418 				updateWindowTitle(MOD_IS_MODIFIED);
4419 			}
4420 		}
4421 		break;
4422 
4423 		case PTB_SREPEATU:
4424 		{
4425 			if (!editor.sampleZero)
4426 			{
4427 				oldVal = song->samples[editor.currSample].loopStart;
4428 				sampleRepeatUpButton(INCREMENT_SLOW);
4429 				if (song->samples[editor.currSample].loopStart != oldVal)
4430 					updateWindowTitle(MOD_IS_MODIFIED);
4431 			}
4432 		}
4433 		break;
4434 
4435 		case PTB_SREPEATD:
4436 		{
4437 			if (!editor.sampleZero)
4438 			{
4439 				oldVal = song->samples[editor.currSample].loopStart;
4440 				sampleRepeatDownButton(INCREMENT_SLOW);
4441 				if (song->samples[editor.currSample].loopStart != oldVal)
4442 					updateWindowTitle(MOD_IS_MODIFIED);
4443 			}
4444 		}
4445 		break;
4446 
4447 		case PTB_SREPLENU:
4448 		{
4449 			if (!editor.sampleZero)
4450 			{
4451 				oldVal = song->samples[editor.currSample].loopLength;
4452 				sampleRepeatLengthUpButton(INCREMENT_SLOW);
4453 				if (song->samples[editor.currSample].loopLength != oldVal)
4454 					updateWindowTitle(MOD_IS_MODIFIED);
4455 			}
4456 		}
4457 		break;
4458 
4459 		case PTB_SREPLEND:
4460 		{
4461 			if (!editor.sampleZero)
4462 			{
4463 				oldVal = song->samples[editor.currSample].loopLength;
4464 				sampleRepeatLengthDownButton(INCREMENT_SLOW);
4465 				if (song->samples[editor.currSample].loopLength != oldVal)
4466 					updateWindowTitle(MOD_IS_MODIFIED);
4467 			}
4468 		}
4469 		break;
4470 
4471 		case PTB_TEMPOU: tempoUpButton(); break;
4472 		case PTB_TEMPOD: tempoDownButton(); break;
4473 
4474 		case PTB_LENGTHU:
4475 		{
4476 			if (song->header.numOrders < 128)
4477 			{
4478 				songLengthUpButton();
4479 				updateWindowTitle(MOD_IS_MODIFIED);
4480 			}
4481 		}
4482 		break;
4483 
4484 		case PTB_LENGTHD:
4485 		{
4486 			if (song->header.numOrders > 1)
4487 			{
4488 				songLengthDownButton();
4489 				updateWindowTitle(MOD_IS_MODIFIED);
4490 			}
4491 		}
4492 		break;
4493 
4494 		case PTB_PATTERNU:
4495 		{
4496 			if (song->header.order[song->currOrder] < 99)
4497 			{
4498 				patternUpButton();
4499 				updateWindowTitle(MOD_IS_MODIFIED);
4500 			}
4501 		}
4502 		break;
4503 
4504 		case PTB_PATTERND:
4505 		{
4506 			if (song->header.order[song->currOrder] > 0)
4507 			{
4508 				patternDownButton();
4509 				updateWindowTitle(MOD_IS_MODIFIED);
4510 			}
4511 		}
4512 		break;
4513 
4514 		case PTB_POSU: positionUpButton(); break;
4515 		case PTB_POSD: positionDownButton(); break;
4516 
4517 		default: displayErrorMsg("NOT IMPLEMENTED"); return false; // button not mapped
4518 	}
4519 
4520 	mouse.lastGUIButton = button;
4521 	return false;
4522 }
4523 
handleRepeatedGUIButtons(void)4524 static void handleRepeatedGUIButtons(void)
4525 {
4526 	// repeat button
4527 	switch (mouse.lastGUIButton)
4528 	{
4529 		case PTB_EO_NOTE1_UP:
4530 		{
4531 			if (mouse.repeatCounter >= 4)
4532 			{
4533 				mouse.repeatCounter = 0;
4534 				edNote1UpButton();
4535 			}
4536 		}
4537 		break;
4538 
4539 		case PTB_EO_NOTE1_DOWN:
4540 		{
4541 			if (mouse.repeatCounter >= 4)
4542 			{
4543 				mouse.repeatCounter = 0;
4544 				edNote1DownButton();
4545 			}
4546 		}
4547 		break;
4548 
4549 		case PTB_EO_NOTE2_UP:
4550 		{
4551 			if (mouse.repeatCounter >= 4)
4552 			{
4553 				mouse.repeatCounter = 0;
4554 				edNote2UpButton();
4555 			}
4556 		}
4557 		break;
4558 
4559 		case PTB_EO_NOTE2_DOWN:
4560 		{
4561 			if (mouse.repeatCounter >= 4)
4562 			{
4563 				mouse.repeatCounter = 0;
4564 				edNote2DownButton();
4565 			}
4566 		}
4567 		break;
4568 
4569 		case PTB_EO_NOTE3_UP:
4570 		{
4571 			if (mouse.repeatCounter >= 4)
4572 			{
4573 				mouse.repeatCounter = 0;
4574 				edNote3UpButton();
4575 			}
4576 		}
4577 		break;
4578 
4579 		case PTB_EO_NOTE3_DOWN:
4580 		{
4581 			if (mouse.repeatCounter >= 4)
4582 			{
4583 				mouse.repeatCounter = 0;
4584 				edNote3DownButton();
4585 			}
4586 		}
4587 		break;
4588 
4589 		case PTB_EO_NOTE4_UP:
4590 		{
4591 			if (mouse.repeatCounter >= 4)
4592 			{
4593 				mouse.repeatCounter = 0;
4594 				edNote4UpButton();
4595 			}
4596 		}
4597 		break;
4598 
4599 		case PTB_EO_NOTE4_DOWN:
4600 		{
4601 			if (mouse.repeatCounter >= 4)
4602 			{
4603 				mouse.repeatCounter = 0;
4604 				edNote4DownButton();
4605 			}
4606 		}
4607 		break;
4608 
4609 		case PTB_EO_VOL_UP:
4610 		{
4611 			if (mouse.repeatCounter >= 2)
4612 			{
4613 				mouse.repeatCounter = 0;
4614 				edVolUpButton();
4615 			}
4616 		}
4617 		break;
4618 
4619 		case PTB_EO_VOL_DOWN:
4620 		{
4621 			if (mouse.repeatCounter >= 2)
4622 			{
4623 				mouse.repeatCounter = 0;
4624 				edVolDownButton();
4625 			}
4626 		}
4627 		break;
4628 
4629 		case PTB_EO_MOD_UP:
4630 		{
4631 			if (mouse.repeatCounter >= 2)
4632 			{
4633 				mouse.repeatCounter = 0;
4634 				edModUpButton();
4635 			}
4636 		}
4637 		break;
4638 
4639 		case PTB_EO_MOD_DOWN:
4640 		{
4641 			if (mouse.repeatCounter >= 2)
4642 			{
4643 				mouse.repeatCounter = 0;
4644 				edModDownButton();
4645 			}
4646 		}
4647 		break;
4648 
4649 		case PTB_EO_POS_UP:
4650 		{
4651 			if (mouse.repeatCounter >= 1)
4652 			{
4653 				mouse.repeatCounter = 0;
4654 				edPosUpButton(INCREMENT_FAST);
4655 			}
4656 		}
4657 		break;
4658 
4659 		case PTB_EO_POS_DOWN:
4660 		{
4661 			if (mouse.repeatCounter >= 1)
4662 			{
4663 				mouse.repeatCounter = 0;
4664 				edPosDownButton(INCREMENT_FAST);
4665 			}
4666 		}
4667 		break;
4668 
4669 		case PTB_EO_FROM_UP:
4670 		{
4671 			if (mouse.repeatCounter >= 2)
4672 			{
4673 				mouse.repeatCounter = 0;
4674 				if (editor.sampleFrom < 0x1F)
4675 				{
4676 					editor.sampleFrom++;
4677 					ui.updateFromText = true;
4678 				}
4679 			}
4680 		}
4681 		break;
4682 
4683 		case PTB_EO_FROM_DOWN:
4684 		{
4685 			if (mouse.repeatCounter >= 2)
4686 			{
4687 				mouse.repeatCounter = 0;
4688 				if (editor.sampleFrom > 0x00)
4689 				{
4690 					editor.sampleFrom--;
4691 					ui.updateFromText = true;
4692 				}
4693 			}
4694 		}
4695 		break;
4696 
4697 		case PTB_EO_TO_UP:
4698 		{
4699 			if (mouse.repeatCounter >= 2)
4700 			{
4701 				mouse.repeatCounter = 0;
4702 				if (editor.sampleTo < 0x1F)
4703 				{
4704 					editor.sampleTo++;
4705 					ui.updateToText = true;
4706 				}
4707 			}
4708 		}
4709 		break;
4710 
4711 		case PTB_EO_TO_DOWN:
4712 		{
4713 			if (mouse.repeatCounter >= 2)
4714 			{
4715 				mouse.repeatCounter = 0;
4716 				if (editor.sampleTo > 0x00)
4717 				{
4718 					editor.sampleTo--;
4719 					ui.updateToText = true;
4720 				}
4721 			}
4722 		}
4723 		break;
4724 
4725 		case PTB_SAMPLEU:
4726 		{
4727 			if (mouse.repeatCounter >= 5)
4728 			{
4729 				mouse.repeatCounter = 0;
4730 				if (!mouse.rightButtonPressed)
4731 					sampleUpButton();
4732 				else
4733 					ui.updateCurrSampleNum = true;
4734 			}
4735 		}
4736 		break;
4737 
4738 		case PTB_SAMPLED:
4739 		{
4740 			if (mouse.repeatCounter >= 5)
4741 			{
4742 				mouse.repeatCounter = 0;
4743 				if (!mouse.rightButtonPressed)
4744 					sampleDownButton();
4745 				else
4746 					ui.updateCurrSampleNum = true;
4747 			}
4748 		}
4749 		break;
4750 
4751 		case PTB_FTUNEU:
4752 		{
4753 			if (mouse.repeatCounter >= 5)
4754 			{
4755 				mouse.repeatCounter = 0;
4756 				sampleFineTuneUpButton();
4757 			}
4758 		}
4759 		break;
4760 
4761 		case PTB_FTUNED:
4762 		{
4763 			if (mouse.repeatCounter >= 5)
4764 			{
4765 				mouse.repeatCounter = 0;
4766 				sampleFineTuneDownButton();
4767 			}
4768 		}
4769 		break;
4770 
4771 		case PTB_SVOLUMEU:
4772 		{
4773 			if (mouse.repeatCounter >= 5)
4774 			{
4775 				mouse.repeatCounter = 0;
4776 				sampleVolumeUpButton();
4777 			}
4778 		}
4779 		break;
4780 
4781 		case PTB_SVOLUMED:
4782 		{
4783 			if (mouse.repeatCounter >= 5)
4784 			{
4785 				mouse.repeatCounter = 0;
4786 				sampleVolumeDownButton();
4787 			}
4788 		}
4789 		break;
4790 
4791 		case PTB_SLENGTHU:
4792 		{
4793 			if (mouse.rightButtonPressed || mouse.repeatCounter >= 1)
4794 			{
4795 				mouse.repeatCounter = 0;
4796 				sampleLengthUpButton(INCREMENT_FAST);
4797 			}
4798 		}
4799 		break;
4800 
4801 		case PTB_SLENGTHD:
4802 		{
4803 			if (mouse.rightButtonPressed || mouse.repeatCounter >= 1)
4804 			{
4805 				mouse.repeatCounter = 0;
4806 				sampleLengthDownButton(INCREMENT_FAST);
4807 			}
4808 		}
4809 		break;
4810 
4811 		case PTB_SREPEATU:
4812 		{
4813 			if (mouse.rightButtonPressed || mouse.repeatCounter >= 1)
4814 			{
4815 				mouse.repeatCounter = 0;
4816 				sampleRepeatUpButton(INCREMENT_FAST);
4817 			}
4818 		}
4819 		break;
4820 
4821 		case PTB_SREPEATD:
4822 		{
4823 			if (mouse.rightButtonPressed || mouse.repeatCounter >= 1)
4824 			{
4825 				mouse.repeatCounter = 0;
4826 				sampleRepeatDownButton(INCREMENT_FAST);
4827 			}
4828 		}
4829 		break;
4830 
4831 		case PTB_SREPLENU:
4832 		{
4833 			if (mouse.rightButtonPressed || mouse.repeatCounter >= 1)
4834 			{
4835 				mouse.repeatCounter = 0;
4836 				sampleRepeatLengthUpButton(INCREMENT_FAST);
4837 			}
4838 		}
4839 		break;
4840 
4841 		case PTB_SREPLEND:
4842 		{
4843 			if (mouse.rightButtonPressed || mouse.repeatCounter >= 1)
4844 			{
4845 				mouse.repeatCounter = 0;
4846 				sampleRepeatLengthDownButton(INCREMENT_FAST);
4847 			}
4848 		}
4849 		break;
4850 
4851 		case PTB_TEMPOU:
4852 		{
4853 			if (mouse.repeatCounter >= 3)
4854 			{
4855 				mouse.repeatCounter = 0;
4856 				tempoUpButton();
4857 			}
4858 		}
4859 		break;
4860 
4861 		case PTB_TEMPOD:
4862 		{
4863 			if (mouse.repeatCounter >= 3)
4864 			{
4865 				mouse.repeatCounter = 0;
4866 				tempoDownButton();
4867 			}
4868 		}
4869 		break;
4870 
4871 		case PTB_LENGTHU:
4872 		{
4873 			if (mouse.repeatCounter >= 7)
4874 			{
4875 				mouse.repeatCounter = 0;
4876 				songLengthUpButton();
4877 			}
4878 		}
4879 		break;
4880 
4881 		case PTB_LENGTHD:
4882 		{
4883 			if (mouse.repeatCounter >= 7)
4884 			{
4885 				mouse.repeatCounter = 0;
4886 				songLengthDownButton();
4887 			}
4888 		}
4889 		break;
4890 
4891 		case PTB_PATTERNU:
4892 		{
4893 			if (mouse.repeatCounter >= 7)
4894 			{
4895 				mouse.repeatCounter = 0;
4896 				patternUpButton();
4897 			}
4898 		}
4899 		break;
4900 
4901 		case PTB_PATTERND:
4902 		{
4903 			if (mouse.repeatCounter >= 7)
4904 			{
4905 				mouse.repeatCounter = 0;
4906 				patternDownButton();
4907 			}
4908 		}
4909 		break;
4910 
4911 		case PTB_POSU:
4912 		{
4913 			if (mouse.repeatCounter >= 7)
4914 			{
4915 				mouse.repeatCounter = 0;
4916 				positionUpButton();
4917 			}
4918 		}
4919 		break;
4920 
4921 		case PTB_POSD:
4922 		{
4923 			if (mouse.repeatCounter >= 7)
4924 			{
4925 				mouse.repeatCounter = 0;
4926 				positionDownButton();
4927 			}
4928 		}
4929 		break;
4930 
4931 		case PTB_PE_SCROLLUP:
4932 		{
4933 			if (mouse.repeatCounter >= 2)
4934 			{
4935 				mouse.repeatCounter = 0;
4936 				if (song->currOrder > 0)
4937 					modSetPos(song->currOrder - 1, DONT_SET_ROW);
4938 			}
4939 		}
4940 		break;
4941 
4942 		case PTB_PE_SCROLLDOWN:
4943 		{
4944 			if (mouse.repeatCounter >= 2)
4945 			{
4946 				mouse.repeatCounter = 0;
4947 				if (song->currOrder < song->header.numOrders-1)
4948 					modSetPos(song->currOrder + 1, DONT_SET_ROW);
4949 			}
4950 		}
4951 		break;
4952 
4953 		case PTB_DO_SCROLLUP:
4954 		{
4955 			if (mouse.repeatCounter >= 1)
4956 			{
4957 				mouse.repeatCounter = 0;
4958 
4959 				diskop.scrollOffset--;
4960 				if (mouse.rightButtonPressed)
4961 					diskop.scrollOffset -= 3;
4962 
4963 				if (diskop.scrollOffset < 0)
4964 					diskop.scrollOffset = 0;
4965 
4966 				ui.updateDiskOpFileList = true;
4967 			}
4968 		}
4969 		break;
4970 
4971 		case PTB_DO_SCROLLDOWN:
4972 		{
4973 			if (mouse.repeatCounter >= 1)
4974 			{
4975 				mouse.repeatCounter = 0;
4976 
4977 				if (diskop.numEntries > DISKOP_LINES)
4978 				{
4979 					diskop.scrollOffset++;
4980 					if (mouse.rightButtonPressed)
4981 						diskop.scrollOffset += 3;
4982 
4983 					if (diskop.scrollOffset > diskop.numEntries-DISKOP_LINES)
4984 						diskop.scrollOffset = diskop.numEntries-DISKOP_LINES;
4985 
4986 					ui.updateDiskOpFileList = true;
4987 				}
4988 			}
4989 		}
4990 		break;
4991 
4992 		case PTB_SA_ZOOMBARAREA:
4993 		{
4994 			if (mouse.repeatCounter >= 4)
4995 			{
4996 				mouse.repeatCounter = 0;
4997 				if (!ui.forceSampleDrag)
4998 					samplerBarPressed(MOUSE_BUTTON_NOT_HELD);
4999 			}
5000 		}
5001 		break;
5002 
5003 		default: break;
5004 	}
5005 }
5006