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 <stdio.h>
7 #include <stdbool.h>
8 #include "ft2_header.h"
9 #include "ft2_gui.h"
10 #include "ft2_about.h"
11 #include "ft2_video.h"
12 #include "ft2_config.h"
13 #include "ft2_audioselector.h"
14 #include "ft2_audio.h"
15 #include "ft2_help.h"
16 #include "ft2_sample_ed.h"
17 #include "ft2_nibbles.h"
18 #include "ft2_inst_ed.h"
19 #include "ft2_pattern_ed.h"
20 #include "ft2_sample_loader.h"
21 #include "ft2_diskop.h"
22 #include "ft2_wav_renderer.h"
23 #include "ft2_trim.h"
24 #include "ft2_sampling.h"
25 #include "ft2_module_loader.h"
26 #include "ft2_midi.h"
27 #include "ft2_midi.h"
28 #include "ft2_mouse.h"
29 #include "ft2_edit.h"
30 #include "ft2_sample_ed_features.h"
31 #include "ft2_palette.h"
32 #include "ft2_structs.h"
33 
34 pushButton_t pushButtons[NUM_PUSHBUTTONS] =
35 {
36 	// ------ RESERVED PUSHBUTTONS ------
37 	{ 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 },
38 
39 	/*
40 	** -- STRUCT INFO: --
41 	**  x          = x position
42 	**  y          = y position
43 	**  w          = width
44 	**  h          = height
45 	**  p (0,1,2)  = button delay after the first trigger (f.ex. used on scrollbar buttons)
46 	**                0 = no delay, 1 = normal delay, 2 = two-phase delay
47 	**  d          = function call repeat delay while button is being held down (number of frames)
48 	**  text #1    = text line #1
49 	**  text #2    = text line #2 (if present, it will be rendered below text #1)
50 	**  funcOnDown = function to call when pressed
51 	**  funcOnUp   = function to call when released
52 	*/
53 
54 	// ------ POSITION EDITOR PUSHBUTTONS ------
55 	//x,  y,  w,  h,  p, d, text #1,           text #2, funcOnDown,      funcOnUp
56 	{ 55,  2, 18, 13, 1, 4, ARROW_UP_STRING,   NULL,    pbPosEdPosDown,  NULL },
57 	{ 55, 36, 18, 13, 1, 4, ARROW_DOWN_STRING, NULL,    pbPosEdPosUp,    NULL },
58 	{ 74,  2, 35, 16, 1, 6, "Ins.",            NULL,    pbPosEdIns,      NULL },
59 	{ 74, 19, 18, 13, 1, 6, ARROW_UP_STRING,   NULL,    pbPosEdPattUp,   NULL },
60 	{ 91, 19, 18, 13, 1, 6, ARROW_DOWN_STRING, NULL,    pbPosEdPattDown, NULL },
61 	{ 74, 33, 35, 16, 1, 6, "Del.",            NULL,    pbPosEdDel,      NULL },
62 	{ 74, 50, 18, 13, 1, 4, ARROW_UP_STRING,   NULL,    pbPosEdLenUp,    NULL },
63 	{ 91, 50, 18, 13, 1, 4, ARROW_DOWN_STRING, NULL,    pbPosEdLenDown,  NULL },
64 	{ 74, 62, 18, 13, 1, 4, ARROW_UP_STRING,   NULL,    pbPosEdRepSUp,   NULL },
65 	{ 91, 62, 18, 13, 1, 4, ARROW_DOWN_STRING, NULL,    pbPosEdRepSDown, NULL },
66 
67 	// ------ SONG/PATTERN PUSHBUTTONS ------
68 	//x,   y,  w,  h,  p, d, text #1,           text #2, funcOnDown,     funcOnUp
69 	{ 168, 34, 18, 13, 1, 4, ARROW_UP_STRING,   NULL,    pbBPMUp,        NULL },
70 	{ 185, 34, 18, 13, 1, 4, ARROW_DOWN_STRING, NULL,    pbBPMDown,      NULL },
71 	{ 168, 48, 18, 13, 1, 4, ARROW_UP_STRING,   NULL,    pbSpeedUp,      NULL },
72 	{ 185, 48, 18, 13, 1, 4, ARROW_DOWN_STRING, NULL,    pbSpeedDown,    NULL },
73 	{ 168, 62, 18, 13, 1, 4, ARROW_UP_STRING,   NULL,    pbIncAdd,       NULL },
74 	{ 185, 62, 18, 13, 1, 4, ARROW_DOWN_STRING, NULL,    pbDecAdd,       NULL },
75 	{ 253, 34, 18, 13, 1, 4, ARROW_UP_STRING,   NULL,    pbEditPattUp,   NULL },
76 	{ 270, 34, 18, 13, 1, 4, ARROW_DOWN_STRING, NULL,    pbEditPattDown, NULL },
77 	{ 253, 48, 18, 13, 1, 4, ARROW_UP_STRING,   NULL,    pbPattLenUp,    NULL },
78 	{ 270, 48, 18, 13, 1, 4, ARROW_DOWN_STRING, NULL,    pbPattLenDown,  NULL },
79 	{ 209, 62, 40, 13, 0, 0, "Expd.",           NULL,    NULL,           expandPattern },
80 	{ 248, 62, 40, 13, 0, 0, "Srnk.",           NULL,    NULL,           shrinkPattern },
81 
82 	// ------ LOGO PUSHBUTTON ------
83 	//x,   y, w,   h,  p, d, text #1, text #2, funcOnDown, funcOnUp
84 	{ 112, 0, 154, 32, 0, 0, NULL,    NULL,    NULL,       pbToggleLogo  },
85 	{ 266, 0,  25, 32, 0, 0, NULL,    NULL,    NULL,       pbToggleBadge },
86 
87 	// ------ MAIN SCREEN PUSHBUTTONS ------
88 	//x,   y,   w,  h,  p, d, text #1,      text #2, funcOnDown, funcOnUp
89 	{ 294,   2, 59, 16, 0, 0, "About",      NULL,    NULL,       showAboutScreen },
90 	{ 294,  19, 59, 16, 0, 0, "Nibbles",    NULL,    NULL,       pbNibbles },
91 	{ 294,  36, 59, 16, 0, 0, "Zap",        NULL,    NULL,       pbZap },
92 	{ 294,  53, 59, 16, 0, 0, "Trim",       NULL,    NULL,       toggleTrimScreen },
93 	{ 294,  70, 59, 16, 0, 0, "Extend",     NULL,    NULL,       patternEditorExtended },
94 	{ 294,  87, 59, 16, 0, 0, "Transps.",   NULL,    NULL,       toggleTranspose },
95 	{ 294, 104, 59, 16, 0, 0, "I.E.Ext.",   NULL,    NULL,       toggleInstEditorExt },
96 	{ 294, 121, 59, 16, 0, 0, "S.E.Ext.",   NULL,    NULL,       toggleSampleEditorExt },
97 	{ 294, 138, 59, 16, 0, 0, "Adv. Edit",  NULL,    NULL,       toggleAdvEdit },
98 	{ 294, 155, 30, 16, 0, 0, "Add",        NULL,    NULL,       pbAddChan },
99 	{ 323, 155, 30, 16, 0, 0, "Sub",        NULL,    NULL,       pbSubChan },
100 	{ 359,   2, 59, 16, 0, 0, "Play sng.",  NULL,    NULL,       pbPlaySong },
101 	{ 359,  19, 59, 16, 0, 0, "Play ptn.",  NULL,    NULL,       pbPlayPtn },
102 	{ 359,  36, 59, 16, 0, 0, "Stop",       NULL,    NULL,       stopPlaying },
103 	{ 359,  53, 59, 16, 0, 0, "Rec. sng.",  NULL,    NULL,       pbRecSng },
104 	{ 359,  70, 59, 16, 0, 0, "Rec. ptn.",  NULL,    NULL,       pbRecPtn },
105 	{ 359,  87, 59, 16, 0, 0, "Disk op.",   NULL,    NULL,       toggleDiskOpScreen },
106 	{ 359, 104, 59, 16, 0, 0, "Instr. Ed.", NULL,    NULL,       toggleInstEditor },
107 	{ 359, 121, 59, 16, 0, 0, "Smp. Ed.",   NULL,    NULL,       toggleSampleEditor },
108 	{ 359, 138, 59, 16, 0, 0, "Config",     NULL,    NULL,       showConfigScreen },
109 	{ 359, 155, 59, 16, 0, 0, "Help",       NULL,    NULL,       showHelpScreen },
110 	{ 115,  35, 46, 16, 0, 0, "Exit",       NULL,    NULL,       exitPatternEditorExtended },
111 
112 	// ------ INSTRUMENT SWITCHER PUSHBUTTONS ------
113 	//x,   y,   w,  h,  p, d, text #1,           text #2, funcOnDown,           funcOnUp
114 	{ 590,   2, 39, 16, 0, 0, "01-08",           NULL,    NULL,                 pbSetInstrBank1 },
115 	{ 590,  19, 39, 16, 0, 0, "09-10",           NULL,    NULL,                 pbSetInstrBank2 },
116 	{ 590,  36, 39, 16, 0, 0, "11-18",           NULL,    NULL,                 pbSetInstrBank3 },
117 	{ 590,  53, 39, 16, 0, 0, "19-20",           NULL,    NULL,                 pbSetInstrBank4 },
118 	{ 590,  73, 39, 16, 0, 0, "21-28",           NULL,    NULL,                 pbSetInstrBank5 },
119 	{ 590,  90, 39, 16, 0, 0, "29-30",           NULL,    NULL,                 pbSetInstrBank6 },
120 	{ 590, 107, 39, 16, 0, 0, "31-38",           NULL,    NULL,                 pbSetInstrBank7 },
121 	{ 590, 124, 39, 16, 0, 0, "39-40",           NULL,    NULL,                 pbSetInstrBank8 },
122 	{ 590,   2, 39, 16, 0, 0, "41-48",           NULL,    NULL,                 pbSetInstrBank9 },
123 	{ 590,  19, 39, 16, 0, 0, "49-50",           NULL,    NULL,                 pbSetInstrBank10 },
124 	{ 590,  36, 39, 16, 0, 0, "51-58",           NULL,    NULL,                 pbSetInstrBank11 },
125 	{ 590,  53, 39, 16, 0, 0, "59-60",           NULL,    NULL,                 pbSetInstrBank12 },
126 	{ 590,  73, 39, 16, 0, 0, "61-68",           NULL,    NULL,                 pbSetInstrBank13,},
127 	{ 590,  90, 39, 16, 0, 0, "69-70",           NULL,    NULL,                 pbSetInstrBank14 },
128 	{ 590, 107, 39, 16, 0, 0, "71-78",           NULL,    NULL,                 pbSetInstrBank15 },
129 	{ 590, 124, 39, 16, 0, 0, "79-80",           NULL,    NULL,                 pbSetInstrBank16 },
130 	{ 590, 144, 39, 27, 0, 0, "Swap",            "Bank",  NULL,                 pbSwapInstrBank },
131 	{ 566,  99, 18, 13, 1, 4, ARROW_UP_STRING,   NULL,    sampleListScrollUp,   NULL },
132 	{ 566, 140, 18, 13, 1, 4, ARROW_DOWN_STRING, NULL,    sampleListScrollDown, NULL },
133 
134 	// ------ NIBBLES SCREEN PUSHBUTTONS ------
135 	//x,   y,   w,  h,  p, d, text #1, text #2, funcOnDown, funcOnUp
136 	{ 568, 104, 61, 16, 0, 0, "Play",  NULL,    NULL,       nibblesPlay },
137 	{ 568, 121, 61, 16, 0, 0, "Help",  NULL,    NULL,       nibblesHelp  },
138 	{ 568, 138, 61, 16, 0, 0, "Highs", NULL,    NULL,       nibblesHighScore },
139 	{ 568, 155, 61, 16, 0, 0, "Exit",  NULL,    NULL,       nibblesExit },
140 
141 	// ------ ADVANCED EDIT PUSHBUTTONS ------
142 	//x,  y,   w,  h,  p, d, text #1,   text #2, funcOnDown, funcOnUp
143 	{  3, 138, 51, 16, 0, 0, "Track",   NULL,    NULL,       remapTrack },
144 	{ 55, 138, 52, 16, 0, 0, "Pattern", NULL,    NULL,       remapPattern },
145 	{  3, 155, 51, 16, 0, 0, "Song",    NULL,    NULL,       remapSong },
146 	{ 55, 155, 52, 16, 0, 0, "Block",   NULL,    NULL,       remapBlock },
147 
148 	// ------ ABOUT SCREEN PUSHBUTTONS ------
149 	//x, y,   w,  h,  p, d, text #1, text #2, funcOnDown, funcOnUp
150 	{ 4, 153, 59, 16, 0, 0, "Exit",  NULL,    NULL,       exitAboutScreen },
151 
152 	// ------ HELP SCREEN PUSHBUTTONS ------
153 	//x,   y,   w,  h,  p, d, text #1,           text #2, funcOnDown,     funcOnUp
154 	{   3, 155, 59, 16, 0, 0, "Exit",            NULL,    NULL,           exitHelpScreen },
155 	{ 611,   2, 18, 13, 1, 3, ARROW_UP_STRING,   NULL,    helpScrollUp,   NULL },
156 	{ 611, 158, 18, 13, 1, 3, ARROW_DOWN_STRING, NULL,    helpScrollDown, NULL },
157 
158 	// ------ PATTERN EDITOR PUSHBUTTONS ------
159 	//x,   y,   w,  h,  p, d, text #1,            text #2, funcOnDown,         funcOnUp
160 	{   3, 385, 25, 13, 1, 4, ARROW_LEFT_STRING,  NULL,    scrollChannelLeft,  NULL },
161 	{ 604, 385, 25, 13, 1, 4, ARROW_RIGHT_STRING, NULL,    scrollChannelRight, NULL },
162 
163 	// ------ TRANSPOSE PUSHBUTTONS ------
164 	//x,   y,   w,  h,  p, d, text #1,text #2, funcOnDown, funcOnUp
165 	{  56, 110, 21, 16, 0, 0, "up",   NULL,    NULL,       trackTranspCurInsUp },
166 	{  76, 110, 21, 16, 0, 0, "dn",   NULL,    NULL,       trackTranspCurInsDn },
167 	{  98, 110, 36, 16, 0, 0, "12up", NULL,    NULL,       trackTranspCurIns12Up },
168 	{ 133, 110, 36, 16, 0, 0, "12dn", NULL,    NULL,       trackTranspCurIns12Dn },
169 	{ 175, 110, 21, 16, 0, 0, "up",   NULL,    NULL,       trackTranspAllInsUp },
170 	{ 195, 110, 21, 16, 0, 0, "dn",   NULL,    NULL,       trackTranspAllInsDn },
171 	{ 217, 110, 36, 16, 0, 0, "12up", NULL,    NULL,       trackTranspAllIns12Up },
172 	{ 252, 110, 36, 16, 0, 0, "12dn", NULL,    NULL,       trackTranspAllIns12Dn },
173 	{  56, 125, 21, 16, 0, 0, "up",   NULL,    NULL,       pattTranspCurInsUp },
174 	{  76, 125, 21, 16, 0, 0, "dn",   NULL,    NULL,       pattTranspCurInsDn },
175 	{  98, 125, 36, 16, 0, 0, "12up", NULL,    NULL,       pattTranspCurIns12Up },
176 	{ 133, 125, 36, 16, 0, 0, "12dn", NULL,    NULL,       pattTranspCurIns12Dn },
177 	{ 175, 125, 21, 16, 0, 0, "up",   NULL,    NULL,       pattTranspAllInsUp },
178 	{ 195, 125, 21, 16, 0, 0, "dn",   NULL,    NULL,       pattTranspAllInsDn },
179 	{ 217, 125, 36, 16, 0, 0, "12up", NULL,    NULL,       pattTranspAllIns12Up },
180 	{ 252, 125, 36, 16, 0, 0, "12dn", NULL,    NULL,       pattTranspAllIns12Dn },
181 	{  56, 140, 21, 16, 0, 0, "up",   NULL,    NULL,       songTranspCurInsUp },
182 	{  76, 140, 21, 16, 0, 0, "dn",   NULL,    NULL,       songTranspCurInsDn },
183 	{  98, 140, 36, 16, 0, 0, "12up", NULL,    NULL,       songTranspCurIns12Up },
184 	{ 133, 140, 36, 16, 0, 0, "12dn", NULL,    NULL,       songTranspCurIns12Dn },
185 	{ 175, 140, 21, 16, 0, 0, "up",   NULL,    NULL,       songTranspAllInsUp },
186 	{ 195, 140, 21, 16, 0, 0, "dn",   NULL,    NULL,       songTranspAllInsDn },
187 	{ 217, 140, 36, 16, 0, 0, "12up", NULL,    NULL,       songTranspAllIns12Up },
188 	{ 252, 140, 36, 16, 0, 0, "12dn", NULL,    NULL,       songTranspAllIns12Dn },
189 	{  56, 155, 21, 16, 0, 0, "up",   NULL,    NULL,       blockTranspCurInsUp },
190 	{  76, 155, 21, 16, 0, 0, "dn",   NULL,    NULL,       blockTranspCurInsDn },
191 	{  98, 155, 36, 16, 0, 0, "12up", NULL,    NULL,       blockTranspCurIns12Up },
192 	{ 133, 155, 36, 16, 0, 0, "12dn", NULL,    NULL,       blockTranspCurIns12Dn },
193 	{ 175, 155, 21, 16, 0, 0, "up",   NULL,    NULL,       blockTranspAllInsUp },
194 	{ 195, 155, 21, 16, 0, 0, "dn",   NULL,    NULL,       blockTranspAllInsDn },
195 	{ 217, 155, 36, 16, 0, 0, "12up", NULL,    NULL,       blockTranspAllIns12Up },
196 	{ 252, 155, 36, 16, 0, 0, "12dn", NULL,    NULL,       blockTranspAllIns12Dn },
197 
198 	// ------ SAMPLE EDITOR PUSHBUTTONS ------
199 	//x,   y,   w,  h,  p, d, text #1,            text #2, funcOnDown,            funcOnUp
200 	{   3, 331, 23, 13, 1, 3, ARROW_LEFT_STRING,  NULL,    scrollSampleDataLeft,  NULL },
201 	{ 606, 331, 23, 13, 1, 3, ARROW_RIGHT_STRING, NULL,    scrollSampleDataRight, NULL },
202 	{  38, 356, 18, 13, 1, 4, ARROW_UP_STRING,    NULL,    sampPlayNoteUp,        NULL },
203 	{  38, 368, 18, 13, 1, 4, ARROW_DOWN_STRING,  NULL,    sampPlayNoteDown,      NULL },
204 	{   3, 382, 53, 16, 0, 0, "Stop",             NULL,    NULL,                  smpEdStop},
205 	{  57, 348, 55, 16, 0, 0, "Wave",             NULL,    NULL,                  sampPlayWave },
206 	{  57, 365, 55, 16, 0, 0, "Range",            NULL,    NULL,                  sampPlayRange },
207 	{  57, 382, 55, 16, 0, 0, "Display",          NULL,    NULL,                  sampPlayDisplay },
208 	{ 118, 348, 63, 16, 0, 0, "Show r.",          NULL,    NULL,                  showRange },
209 	{ 118, 365, 63, 16, 0, 0, "Range all",        NULL,    NULL,                  rangeAll },
210 	{ 118, 382, 63, 16, 0, 0, "Sample",           NULL,    NULL,                  startSampling },
211 	{ 182, 348, 63, 16, 0, 0, "Zoom out",         NULL,    NULL,                  zoomOut },
212 	{ 182, 365, 63, 16, 0, 0, "Show all",         NULL,    NULL,                  showAll },
213 	{ 182, 382, 63, 16, 0, 0, "Save rng.",        NULL,    NULL,                  saveRange },
214 	{ 251, 348, 43, 16, 0, 0, "Cut",              NULL,    NULL,                  sampCut },
215 	{ 251, 365, 43, 16, 0, 0, "Copy",             NULL,    NULL,                  sampCopy },
216 	{ 251, 382, 43, 16, 0, 0, "Paste",            NULL,    NULL,                  sampPaste },
217 	{ 300, 348, 50, 16, 0, 0, "Crop",             NULL,    NULL,                  sampCrop },
218 	{ 300, 365, 50, 16, 0, 0, "Volume",           NULL,    NULL,                  pbSampleVolume },
219 	{ 300, 382, 50, 16, 0, 0, "X-Fade",           NULL,    NULL,                  sampXFade },
220 	{ 430, 348, 54, 16, 0, 0, "Exit",             NULL,    NULL,                  exitSampleEditor },
221 	{ 594, 348, 35, 13, 0, 0, "Clr S.",           NULL,    NULL,                  clearSample },
222 	{ 594, 360, 35, 13, 0, 0, "Min.",             NULL,    NULL,                  sampMinimize },
223 	{ 594, 373, 18, 13, 2, 4, ARROW_UP_STRING,    NULL,    sampRepeatUp,          NULL },
224 	{ 611, 373, 18, 13, 2, 4, ARROW_DOWN_STRING,  NULL,    sampRepeatDown,        NULL },
225 	{ 594, 385, 18, 13, 2, 4, ARROW_UP_STRING,    NULL,    sampReplenUp,          NULL },
226 	{ 611, 385, 18, 13, 2, 4, ARROW_DOWN_STRING,  NULL,    sampReplenDown,        NULL },
227 
228 	// ------ SAMPLE EDITOR EXTENSION PUSHBUTTONS ------
229 	//x,   y,   w,  h,  p, d, text #1,     text #2, funcOnDown, funcOnUp
230 	{   3, 138, 52, 16, 0, 0, "Clr. c.bf", NULL,    NULL,       clearCopyBuffer },
231 	{  56, 138, 49, 16, 0, 0, "Sign",      NULL,    NULL,       sampleChangeSign },
232 	{ 106, 138, 49, 16, 0, 0, "Echo",      NULL,    NULL,       pbSampleEcho },
233 	{   3, 155, 52, 16, 0, 0, "Backw.",    NULL,    NULL,       sampleBackwards },
234 	{  56, 155, 49, 16, 0, 0, "B. swap",    NULL,    NULL,      sampleByteSwap },
235 	{ 106, 155, 49, 16, 0, 0, "Fix DC",    NULL,    NULL,       fixDC },
236 	{ 161, 121, 60, 16, 0, 0, "Copy ins.", NULL,    NULL,       copyInstr },
237 	{ 222, 121, 66, 16, 0, 0, "Copy smp.", NULL,    NULL,       copySmp },
238 	{ 161, 138, 60, 16, 0, 0, "Xchg ins.", NULL,    NULL,       xchgInstr },
239 	{ 222, 138, 66, 16, 0, 0, "Xchg smp.", NULL,    NULL,       xchgSmp },
240 	{ 161, 155, 60, 16, 0, 0, "Resample",  NULL,    NULL,       pbSampleResample },
241 	{ 222, 155, 66, 16, 0, 0, "Mix smp.",  NULL,    NULL,       pbSampleMix },
242 
243 	// ------ INSTRUMENT EDITOR PUSHBUTTONS ------
244 	//x,   y,   w,  h,  p, d, text #1,            text #2, funcOnDown,     funcOnUp
245 	{ 200, 175, 23, 12, 0, 0, SMALL_1_STRING,     NULL,    NULL,           volPreDef1 },
246 	{ 222, 175, 24, 12, 0, 0, SMALL_2_STRING,     NULL,    NULL,           volPreDef2 },
247 	{ 245, 175, 24, 12, 0, 0, SMALL_3_STRING,     NULL,    NULL,           volPreDef3 },
248 	{ 268, 175, 24, 12, 0, 0, SMALL_4_STRING,     NULL,    NULL,           volPreDef4 },
249 	{ 291, 175, 24, 12, 0, 0, SMALL_5_STRING,     NULL,    NULL,           volPreDef5 },
250 	{ 314, 175, 24, 12, 0, 0, SMALL_6_STRING,     NULL,    NULL,           volPreDef6 },
251 	{ 200, 262, 23, 12, 0, 0, SMALL_1_STRING,     NULL,    NULL,           panPreDef1 },
252 	{ 222, 262, 24, 12, 0, 0, SMALL_2_STRING,     NULL,    NULL,           panPreDef2 },
253 	{ 245, 262, 24, 12, 0, 0, SMALL_3_STRING,     NULL,    NULL,           panPreDef3 },
254 	{ 268, 262, 24, 12, 0, 0, SMALL_4_STRING,     NULL,    NULL,           panPreDef4 },
255 	{ 291, 262, 24, 12, 0, 0, SMALL_5_STRING,     NULL,    NULL,           panPreDef5 },
256 	{ 314, 262, 24, 12, 0, 0, SMALL_6_STRING,     NULL,    NULL,           panPreDef6 },
257 	{ 570, 276, 59, 16, 0, 0, "Exit",             NULL,    NULL,           exitInstEditor },
258 	{ 341, 175, 47, 16, 1, 4, "Add",              NULL,    volEnvAdd,      NULL },
259 	{ 389, 175, 46, 16, 1, 4, "Del",              NULL,    volEnvDel,      NULL },
260 	{ 398, 204, 19, 13, 1, 4, ARROW_UP_STRING,    NULL,    volEnvSusUp,    NULL },
261 	{ 416, 204, 19, 13, 1, 4, ARROW_DOWN_STRING,  NULL,    volEnvSusDown,  NULL },
262 	{ 398, 231, 19, 13, 1, 4, ARROW_UP_STRING,    NULL,    volEnvRepSUp,   NULL },
263 	{ 416, 231, 19, 13, 1, 4, ARROW_DOWN_STRING,  NULL,    volEnvRepSDown, NULL },
264 	{ 398, 245, 19, 13, 1, 4, ARROW_UP_STRING,    NULL,    volEnvRepEUp,   NULL },
265 	{ 416, 245, 19, 13, 1, 4, ARROW_DOWN_STRING,  NULL,    volEnvRepEDown, NULL },
266 	{ 341, 262, 47, 16, 1, 4, "Add",              NULL,    panEnvAdd,      NULL },
267 	{ 389, 262, 46, 16, 1, 4, "Del",              NULL,    panEnvDel,      NULL },
268 	{ 398, 291, 19, 13, 1, 4, ARROW_UP_STRING,    NULL,    panEnvSusUp,    NULL },
269 	{ 416, 291, 19, 13, 1, 4, ARROW_DOWN_STRING,  NULL,    panEnvSusDown,  NULL },
270 	{ 398, 318, 19, 13, 1, 4, ARROW_UP_STRING,    NULL,    panEnvRepSUp,   NULL },
271 	{ 416, 318, 19, 13, 1, 4, ARROW_DOWN_STRING,  NULL,    panEnvRepSDown, NULL },
272 	{ 398, 332, 19, 13, 1, 4, ARROW_UP_STRING,    NULL,    panEnvRepEUp,   NULL },
273 	{ 416, 332, 19, 13, 1, 4, ARROW_DOWN_STRING,  NULL,    panEnvRepEDown, NULL },
274 	{ 521, 175, 23, 13, 1, 4, ARROW_LEFT_STRING,  NULL,    volDown,        NULL },
275 	{ 606, 175, 23, 13, 1, 4, ARROW_RIGHT_STRING, NULL,    volUp,          NULL },
276 	{ 521, 189, 23, 13, 2, 4, ARROW_LEFT_STRING,  NULL,    panDown,        NULL },
277 	{ 606, 189, 23, 13, 2, 4, ARROW_RIGHT_STRING, NULL,    panUp,          NULL },
278 	{ 521, 203, 23, 13, 1, 4, ARROW_LEFT_STRING,  NULL,    ftuneDown,      NULL },
279 	{ 606, 203, 23, 13, 1, 4, ARROW_RIGHT_STRING, NULL,    ftuneUp,        NULL },
280 	{ 521, 220, 23, 13, 2, 4, ARROW_LEFT_STRING,  NULL,    fadeoutDown,    NULL },
281 	{ 606, 220, 23, 13, 2, 4, ARROW_RIGHT_STRING, NULL,    fadeoutUp,      NULL },
282 	{ 521, 234, 23, 13, 1, 4, ARROW_LEFT_STRING,  NULL,    vibSpeedDown,   NULL },
283 	{ 606, 234, 23, 13, 1, 4, ARROW_RIGHT_STRING, NULL,    vibSpeedUp,     NULL },
284 	{ 521, 248, 23, 13, 1, 4, ARROW_LEFT_STRING,  NULL,    vibDepthDown,   NULL },
285 	{ 606, 248, 23, 13, 1, 4, ARROW_RIGHT_STRING, NULL,    vibDepthUp,     NULL },
286 	{ 521, 262, 23, 13, 1, 4, ARROW_LEFT_STRING,  NULL,    vibSweepDown,   NULL },
287 	{ 606, 262, 23, 13, 1, 4, ARROW_RIGHT_STRING, NULL,    vibSweepUp,     NULL },
288 	{ 441, 312, 94, 16, 1, 4, "Octave up",        NULL,    relativeNoteOctUp,   NULL },
289 	{ 536, 312, 93, 16, 1, 4, "Halftone up",      NULL,    relativeNoteUp,      NULL },
290 	{ 441, 329, 94, 16, 1, 4, "Octave down",      NULL,    relativeNoteOctDown, NULL },
291 	{ 536, 329, 93, 16, 1, 4, "Halftone down",    NULL,    relativeNoteDown,    NULL },
292 
293 	// ------ INSTRUMENT EDITOR EXTENSION PUSHBUTTONS ------
294 	//x,   y,   w,  h,  p, d, text #1,            text #2, funcOnDown,   funcOnUp
295 	{ 172, 130, 23, 13, 1, 4, ARROW_LEFT_STRING,  NULL,    midiChDown,   NULL },
296 	{ 265, 130, 23, 13, 1, 4, ARROW_RIGHT_STRING, NULL,    midiChUp,     NULL },
297 	{ 172, 144, 23, 13, 1, 4, ARROW_LEFT_STRING,  NULL,    midiPrgDown,  NULL },
298 	{ 265, 144, 23, 13, 1, 4, ARROW_RIGHT_STRING, NULL,    midiPrgUp,    NULL },
299 	{ 172, 158, 23, 13, 1, 4, ARROW_LEFT_STRING,  NULL,    midiBendDown, NULL },
300 	{ 265, 158, 23, 13, 1, 4, ARROW_RIGHT_STRING, NULL,    midiBendUp,   NULL },
301 
302 	// ------ TRIM SCREEN PUSHBUTTONS ------
303 	//x,   y,   w,  h,  p, d, text #1,     text #2, funcOnDown, funcOnUp
304 	{ 139, 155, 74, 16, 0, 0, "Calculate", NULL,    NULL,       pbTrimCalc },
305 	{ 214, 155, 74, 16, 0, 0, "Trim",      NULL,    NULL,       pbTrimDoTrim },
306 
307 	// ------ CONFIG LEFT PANEL PUSHBUTTONS ------
308 	//x, y,   w,   h,  p, d, text #1,         text #2, funcOnDown, funcOnUp
309 	{ 3, 104, 104, 16, 0, 0, "Reset config",  NULL,    NULL,       resetConfig },
310 	{ 3, 121, 104, 16, 0, 0, "Load config",   NULL,    NULL,       loadConfig2 },
311 	{ 3, 138, 104, 16, 0, 0, "Save config",   NULL,    NULL,       saveConfig2 },
312 	{ 3, 155, 104, 16, 0, 0, "Exit",          NULL,    NULL,       exitConfigScreen },
313 
314 	// ------ CONFIG AUDIO PUSHBUTTONS ------
315 	//x,   y,   w,  h,  p, d, text #1,            text #2, funcOnDown,                 funcOnUp
316 	{ 326,   2, 57, 13, 0, 0, "Re-scan",          NULL,    NULL,                       rescanAudioDevices },
317 	{ 365,  16, 18, 13, 1, 4, ARROW_UP_STRING,    NULL,    scrollAudOutputDevListUp,   NULL },
318 	{ 365,  72, 18, 13, 1, 4, ARROW_DOWN_STRING,  NULL,    scrollAudOutputDevListDown, NULL },
319 	{ 365, 103, 18, 13, 1, 4, ARROW_UP_STRING,    NULL,    scrollAudInputDevListUp,    NULL },
320 	{ 365, 137, 18, 13, 1, 4, ARROW_DOWN_STRING,  NULL,    scrollAudInputDevListDown,  NULL },
321 	{ 508, 132, 21, 13, 1, 4, ARROW_LEFT_STRING,  NULL,    configAmpDown,              NULL },
322 	{ 608, 132, 21, 13, 1, 4, ARROW_RIGHT_STRING, NULL,    configAmpUp,                NULL },
323 	{ 508, 158, 21, 13, 1, 0, ARROW_LEFT_STRING,  NULL,    configMasterVolDown,        NULL },
324 	{ 608, 158, 21, 13, 1, 0, ARROW_RIGHT_STRING, NULL,    configMasterVolUp,          NULL },
325 
326 	// ------ CONFIG LAYOUT PUSHBUTTONS ------
327 	//x,   y,  w,  h,  p, d, text #1,            text #2, funcOnDown,        funcOnUp
328 	{ 513, 15, 23, 13, 1, 4, ARROW_LEFT_STRING,  NULL,    configPalRDown,    NULL },
329 	{ 606, 15, 23, 13, 1, 4, ARROW_RIGHT_STRING, NULL,    configPalRUp,      NULL },
330 	{ 513, 29, 23, 13, 1, 4, ARROW_LEFT_STRING,  NULL,    configPalGDown,    NULL },
331 	{ 606, 29, 23, 13, 1, 4, ARROW_RIGHT_STRING, NULL,    configPalGUp,      NULL },
332 	{ 513, 43, 23, 13, 1, 4, ARROW_LEFT_STRING,  NULL,    configPalBDown,    NULL },
333 	{ 606, 43, 23, 13, 1, 4, ARROW_RIGHT_STRING, NULL,    configPalBUp,      NULL },
334 	{ 513, 71, 23, 13, 1, 4, ARROW_LEFT_STRING,  NULL,    configPalContDown, NULL },
335 	{ 606, 71, 23, 13, 1, 4, ARROW_RIGHT_STRING, NULL,    configPalContUp,   NULL },
336 
337 	// ------ CONFIG MISCELLANEOUS PUSHBUTTONS ------
338 	//x,   y,   w,  h,  p, d, text #1,            text #2, funcOnDown,          funcOnUp
339 	{ 370, 121, 18, 13, 1, 4, ARROW_UP_STRING,    NULL,    configQuantizeUp,    NULL },
340 	{ 387, 121, 18, 13, 1, 4, ARROW_DOWN_STRING,  NULL,    configQuantizeDown,  NULL },
341 	{ 594, 106, 18, 13, 1, 4, ARROW_UP_STRING,    NULL,    configMIDIChnUp,     NULL },
342 	{ 611, 106, 18, 13, 1, 4, ARROW_DOWN_STRING,  NULL,    configMIDIChnDown,   NULL },
343 	{ 594, 120, 18, 13, 1, 4, ARROW_UP_STRING,    NULL,    configMIDITransUp,   NULL },
344 	{ 611, 120, 18, 13, 1, 4, ARROW_DOWN_STRING,  NULL,    configMIDITransDown, NULL },
345 	{ 556, 158, 22, 13, 1, 4, ARROW_LEFT_STRING,  NULL,    configMIDISensDown,  NULL },
346 	{ 607, 158, 22, 13, 1, 4, ARROW_RIGHT_STRING, NULL,    configMIDISensUp,    NULL },
347 
348 #ifdef HAS_MIDI
349 	// ------ CONFIG MIDI PUSHBUTTONS ------
350 	//x,   y,   w,  h,  p, d, text #1,           text #2, funcOnDown,                 funcOnUp
351 	{ 483,   2, 18, 13, 1, 4, ARROW_UP_STRING,   NULL,    scrollMidiInputDevListUp,   NULL },
352 	{ 483, 158, 18, 13, 1, 4, ARROW_DOWN_STRING, NULL,    scrollMidiInputDevListDown, NULL },
353 #endif
354 
355 	// ------ DISK OP. PUSHBUTTONS ------
356 	//x,   y,   w,  h,  p, d, text #1,           text #2, funcOnDown,       funcOnUp
357 	{  70,   2, 58, 16, 0, 0, "Save",            NULL,    NULL,             pbDiskOpSave },
358 	{  70,  19, 58, 16, 0, 0, "Delete",          NULL,    NULL,             pbDiskOpDelete },
359 	{  70,  36, 58, 16, 0, 0, "Rename",          NULL,    NULL,             pbDiskOpRename },
360 	{  70,  53, 58, 16, 0, 0, "Make dir.",       NULL,    NULL,             pbDiskOpMakeDir },
361 	{  70,  70, 58, 16, 0, 0, "Refresh",         NULL,    NULL,             pbDiskOpRefresh },
362 	{  70,  87, 58, 16, 0, 0, "Set path",        NULL,    NULL,             pbDiskOpSetPath },
363 	{  70, 104, 58, 16, 0, 0, "Show all",        NULL,    NULL,             pbDiskOpShowAll },
364 	{  70, 121, 58, 19, 0, 0, "Exit",            NULL,    NULL,             pbDiskOpExit },
365 #ifdef _WIN32 // partition letters
366 	{ 134,   2, 31, 13, 0, 0, ".\001",           NULL,    NULL,             pbDiskOpParent },
367 	{ 134,  16, 31, 12, 0, 0, "\\",              NULL,    NULL,             pbDiskOpRoot },
368 	{ 134,  29, 31, 13, 0, 0, NULL,              NULL,    NULL,             pbDiskOpDrive1 },
369 	{ 134,  43, 31, 13, 0, 0, NULL,              NULL,    NULL,             pbDiskOpDrive2 },
370 	{ 134,  57, 31, 13, 0, 0, NULL,              NULL,    NULL,             pbDiskOpDrive3 },
371 	{ 134,  71, 31, 13, 0, 0, NULL,              NULL,    NULL,             pbDiskOpDrive4 },
372 	{ 134,  85, 31, 13, 0, 0, NULL,              NULL,    NULL,             pbDiskOpDrive5 },
373 	{ 134,  99, 31, 13, 0, 0, NULL,              NULL,    NULL,             pbDiskOpDrive6 },
374 	{ 134, 113, 31, 13, 0, 0, NULL,              NULL,    NULL,             pbDiskOpDrive7 },
375 	{ 134, 127, 31, 13, 0, 0, NULL,              NULL,    NULL,             pbDiskOpDrive8 },
376 #else
377 	{ 134,   2, 31, 13, 0, 0, "../",             NULL,    NULL,             pbDiskOpParent },
378 	{ 134,  16, 31, 12, 0, 0, "/",               NULL,    NULL,             pbDiskOpRoot },
379 #endif
380 	{ 335,   2, 18, 13, 1, 3, ARROW_UP_STRING,   NULL,    pbDiskOpListUp,   NULL },
381 	{ 335, 158, 18, 13, 1, 3, ARROW_DOWN_STRING, NULL,    pbDiskOpListDown, NULL },
382 
383 	// ------ WAV RENDERER PUSHBUTTONS ------
384 	//x,   y,   w,  h,  p, d, text #1,           text #2, funcOnDown,         funcOnUp
385 	{   3, 111, 73, 43, 0, 0, "Export",          NULL,    NULL,               pbWavRender },
386 	{   3, 155, 73, 16, 0, 0, "Exit",            NULL,    NULL,               pbWavExit },
387 	{ 253, 114, 18, 13, 1, 6, ARROW_UP_STRING,   NULL,    pbWavFreqUp,        NULL },
388 	{ 270, 114, 18, 13, 1, 6, ARROW_DOWN_STRING, NULL,    pbWavFreqDown,      NULL },
389 	{ 253, 128, 18, 13, 1, 4, ARROW_UP_STRING,   NULL,    pbWavAmpUp,         NULL },
390 	{ 270, 128, 18, 13, 1, 4, ARROW_DOWN_STRING, NULL,    pbWavAmpDown,       NULL },
391 	{ 253, 142, 18, 13, 1, 4, ARROW_UP_STRING,   NULL,    pbWavSongStartUp,   NULL },
392 	{ 270, 142, 18, 13, 1, 4, ARROW_DOWN_STRING, NULL,    pbWavSongStartDown, NULL },
393 	{ 253, 156, 18, 13, 1, 4, ARROW_UP_STRING,   NULL,    pbWavSongEndUp,     NULL },
394 	{ 270, 156, 18, 13, 1, 4, ARROW_DOWN_STRING, NULL,    pbWavSongEndDown,   NULL }
395 };
396 
397 static uint32_t tmpCounter;
398 
drawPushButton(uint16_t pushButtonID)399 void drawPushButton(uint16_t pushButtonID)
400 {
401 	uint16_t textX, textY, textW;
402 
403 	assert(pushButtonID < NUM_PUSHBUTTONS);
404 
405 	pushButton_t *b = &pushButtons[pushButtonID];
406 	if (!b->visible)
407 		return;
408 
409 	uint8_t state = b->state;
410 
411 	uint16_t x = b->x;
412 	uint16_t y = b->y;
413 	uint16_t w = b->w;
414 	uint16_t h = b->h;
415 
416 	assert(x < SCREEN_W && y < SCREEN_H && w >= 4 && h >= 4);
417 
418 	if (b->bitmapFlag)
419 	{
420 		blitFast(x, y, (state == PUSHBUTTON_UNPRESSED) ? b->bitmapUnpressed : b->bitmapPressed, w, h);
421 		return;
422 	}
423 
424 	// fill button background
425 	fillRect(x + 1, y + 1, w - 2, h - 2, PAL_BUTTONS);
426 
427 	// draw outer border
428 	hLine(x,         y,         w, PAL_BCKGRND);
429 	hLine(x,         y + h - 1, w, PAL_BCKGRND);
430 	vLine(x,         y,         h, PAL_BCKGRND);
431 	vLine(x + w - 1, y,         h, PAL_BCKGRND);
432 
433 	//draw inner borders
434 	if (state == PUSHBUTTON_UNPRESSED)
435 	{
436 		// top left corner inner border
437 		hLine(x + 1, y + 1, w - 3, PAL_BUTTON1);
438 		vLine(x + 1, y + 2, h - 4, PAL_BUTTON1);
439 
440 		// bottom right corner inner border
441 		hLine(x + 1 - 0, y + h - 2, w - 2, PAL_BUTTON2);
442 		vLine(x + w - 2, y + 1 - 0, h - 3, PAL_BUTTON2);
443 	}
444 	else
445 	{
446 		// top left corner inner border
447 		hLine(x + 1, y + 1, w - 2, PAL_BUTTON2);
448 		vLine(x + 1, y + 2, h - 3, PAL_BUTTON2);
449 	}
450 
451 	// render button text(s)
452 	if (b->caption != NULL && *b->caption != '\0')
453 	{
454 		// button text #2
455 		if (b->caption2 != NULL && *b->caption2 != '\0')
456 		{
457 			textW = textWidth(b->caption2);
458 			textX = x + ((w - textW) / 2);
459 			textY = y + 6 + ((h - (FONT1_CHAR_H - 2)) / 2);
460 
461 			if (state == PUSHBUTTON_PRESSED)
462 				textOut(textX + 1, textY + 1, PAL_BTNTEXT, b->caption2);
463 			else
464 				textOut(textX, textY, PAL_BTNTEXT, b->caption2);
465 
466 			y -= 5; // if two text lines, bias y position of first (upper) text
467 		}
468 
469 		// button text #1
470 		textW = textWidth(b->caption);
471 		textX = x + ((w - textW) / 2);
472 		textY = y + ((h - (FONT1_CHAR_H - 2)) / 2);
473 
474 		if (state == PUSHBUTTON_PRESSED)
475 			textOut(textX + 1, textY + 1, PAL_BTNTEXT, b->caption);
476 		else
477 			textOut(textX, textY, PAL_BTNTEXT, b->caption);
478 	}
479 }
480 
showPushButton(uint16_t pushButtonID)481 void showPushButton(uint16_t pushButtonID)
482 {
483 	assert(pushButtonID < NUM_PUSHBUTTONS);
484 	pushButtons[pushButtonID].visible = true;
485 	drawPushButton(pushButtonID);
486 }
487 
hidePushButton(uint16_t pushButtonID)488 void hidePushButton(uint16_t pushButtonID)
489 {
490 	assert(pushButtonID < NUM_PUSHBUTTONS);
491 	pushButtons[pushButtonID].state = 0;
492 	pushButtons[pushButtonID].visible = false;
493 }
494 
handlePushButtonsWhileMouseDown(void)495 void handlePushButtonsWhileMouseDown(void)
496 {
497 	int8_t buttonDelay;
498 
499 	assert(mouse.lastUsedObjectID >= 0 && mouse.lastUsedObjectID < NUM_PUSHBUTTONS);
500 	pushButton_t *pushButton = &pushButtons[mouse.lastUsedObjectID];
501 	if (!pushButton->visible)
502 		return;
503 
504 	pushButton->state = PUSHBUTTON_UNPRESSED;
505 	if (mouse.x >= pushButton->x && mouse.x < pushButton->x+pushButton->w &&
506         mouse.y >= pushButton->y && mouse.y < pushButton->y+pushButton->h)
507 	{
508 		pushButton->state = PUSHBUTTON_PRESSED;
509 	}
510 
511 	if (mouse.lastX != mouse.x || mouse.lastY != mouse.y)
512 	{
513 		mouse.lastX = mouse.x;
514 		mouse.lastY = mouse.y;
515 
516 		drawPushButton(mouse.lastUsedObjectID);
517 	}
518 
519 	// long delay before repeat
520 	if (pushButton->preDelay && mouse.firstTimePressingButton)
521 	{
522 		tmpCounter = 0;
523 
524 		if (++mouse.buttonCounter >= BUTTON_DOWN_DELAY)
525 		{
526 			mouse.buttonCounter = 0;
527 			mouse.firstTimePressingButton = false;
528 		}
529 		else
530 		{
531 			return; // we're delaying
532 		}
533 	}
534 
535 	if (pushButton->state == PUSHBUTTON_PRESSED)
536 	{
537 		// button delay stuff
538 		if (mouse.rightButtonPressed)
539 			buttonDelay = pushButton->delayFrames >> 1;
540 		else if (pushButton->preDelay == 2 && (!mouse.firstTimePressingButton && ++tmpCounter >= 50)) // special mode
541 			buttonDelay = 0;
542 		else
543 			buttonDelay = pushButton->delayFrames;
544 
545 		// main repeat delay
546 		if (++mouse.buttonCounter >= buttonDelay)
547 		{
548 			mouse.buttonCounter = 0;
549 			if (pushButton->callbackFuncOnDown != NULL)
550 				pushButton->callbackFuncOnDown();
551 		}
552 	}
553 }
554 
testPushButtonMouseDown(void)555 bool testPushButtonMouseDown(void)
556 {
557 	uint16_t start, end;
558 
559 	if (ui.sysReqShown)
560 	{
561 		// if a system request is open, only test the first eight pushbuttons (reserved)
562 		start = 0;
563 		end = 8;
564 	}
565 	else
566 	{
567 		start = 8;
568 		end = NUM_PUSHBUTTONS;
569 	}
570 
571 	pushButton_t *pushButton = &pushButtons[start];
572 	for (uint16_t i = start; i < end; i++, pushButton++)
573 	{
574 		if (!pushButton->visible)
575 			continue;
576 
577 		if (mouse.x >= pushButton->x && mouse.x < pushButton->x+pushButton->w &&
578 		    mouse.y >= pushButton->y && mouse.y < pushButton->y+pushButton->h)
579 		{
580 			mouse.lastUsedObjectID = i;
581 			mouse.lastUsedObjectType = OBJECT_PUSHBUTTON;
582 
583 			if (!mouse.rightButtonPressed)
584 			{
585 				mouse.firstTimePressingButton = true;
586 				mouse.buttonCounter = 0;
587 
588 				pushButton->state = PUSHBUTTON_PRESSED;
589 				drawPushButton(i);
590 
591 				if (pushButton->callbackFuncOnDown != NULL)
592 					pushButton->callbackFuncOnDown();
593 			}
594 
595 			return true;
596 		}
597 	}
598 
599 	return false;
600 }
601 
testPushButtonMouseRelease(bool runCallback)602 int16_t testPushButtonMouseRelease(bool runCallback)
603 {
604 	if (mouse.lastUsedObjectType != OBJECT_PUSHBUTTON || mouse.lastUsedObjectID == OBJECT_ID_NONE)
605 		return -1;
606 
607 	assert(mouse.lastUsedObjectID < NUM_PUSHBUTTONS);
608 	pushButton_t *pushButton = &pushButtons[mouse.lastUsedObjectID];
609 	if (!pushButton->visible)
610 		return -1;
611 
612 	if (mouse.x >= pushButton->x && mouse.x < pushButton->x+pushButton->w &&
613 		mouse.y >= pushButton->y && mouse.y < pushButton->y+pushButton->h)
614 	{
615 		pushButton->state = PUSHBUTTON_UNPRESSED;
616 		drawPushButton(mouse.lastUsedObjectID);
617 
618 		if (runCallback)
619 		{
620 			if (pushButton->callbackFuncOnUp != NULL)
621 				pushButton->callbackFuncOnUp();
622 		}
623 
624 		return mouse.lastUsedObjectID;
625 	}
626 
627 	return -1;
628 }
629