1 #include "libretro-core.h"
2 #include "libretro-graph.h"
3 #include "libretro-vkbd.h"
4
5 bool retro_vkbd = false;
6 bool retro_vkbd_transparent = true;
7 extern bool retro_capslock;
8 extern int vkflag[10];
9 extern unsigned int opt_vkbd_theme;
10 extern libretro_graph_alpha_t opt_vkbd_alpha;
11 extern unsigned int zoom_mode_id;
12
RGB(int r,int g,int b)13 int RGB(int r, int g, int b)
14 {
15 if (pix_bytes == 4)
16 return ARGB888(255, r, g, b);
17 else
18 return RGB565(r, g, b);
19 }
20
BKG_PADDING(int len)21 static int BKG_PADDING(int len)
22 {
23 static int font_width = 6;
24 switch (len)
25 {
26 case 2:
27 return -font_width;
28 break;
29 case 3:
30 return -((font_width / 2) * 3);
31 break;
32 }
33 return 0;
34 }
35
print_vkbd(unsigned short int * pixels)36 void print_vkbd(unsigned short int *pixels)
37 {
38 int x, y;
39 bool shifted;
40 int page = 0;
41 uint16_t *pix = &pixels[0];
42
43 int XKEY = 0;
44 int YKEY = 0;
45 int XTEXT = 0;
46 int YTEXT = 0;
47 int XOFFSET = 0;
48 int XPADDING = 0;
49 int YOFFSET = 0;
50 int YPADDING = 0;
51 int XKEYSPACING = 1;
52 int YKEYSPACING = 1;
53 libretro_graph_alpha_t ALPHA = opt_vkbd_alpha;
54 libretro_graph_alpha_t BKG_ALPHA = ALPHA;
55 int BKG_PADDING_X = 0;
56 int BKG_PADDING_Y = 0;
57 int BKG_COLOR = 0;
58 int BKG_COLOR_NORMAL = 0;
59 int BKG_COLOR_ALT = 0;
60 int BKG_COLOR_EXTRA = 0;
61 int BKG_COLOR_EXTRA2 = 0;
62 int BKG_COLOR_SEL = 0;
63 int BKG_COLOR_ACTIVE = 0;
64 int FONT_MAX = 3;
65 int FONT_WIDTH = 1;
66 int FONT_HEIGHT = 1;
67 int FONT_COLOR = 0;
68 int FONT_COLOR_NORMAL = 0;
69 int FONT_COLOR_SEL = 0;
70 libretro_graph_alpha_t FONT_ALPHA = 0;
71
72 switch (opt_vkbd_theme)
73 {
74 default:
75 case 0: /* C64 */
76 BKG_COLOR_NORMAL = RGB( 68, 59, 58);
77 BKG_COLOR_ALT = RGB(123, 127, 130);
78 BKG_COLOR_EXTRA = RGB(143, 140, 129);
79 BKG_COLOR_EXTRA2 = RGB( 89, 79, 78);
80 BKG_COLOR_SEL = RGB(160, 160, 160);
81 BKG_COLOR_ACTIVE = RGB( 48, 44, 45);
82 FONT_COLOR_NORMAL = RGB(250, 250, 250);
83 FONT_COLOR_SEL = RGB( 10, 10, 10);
84 break;
85
86 case 1: /* C64C */
87 BKG_COLOR_NORMAL = RGB(216, 209, 201);
88 BKG_COLOR_ALT = RGB(159, 154, 150);
89 BKG_COLOR_EXTRA = RGB(143, 140, 129);
90 BKG_COLOR_EXTRA2 = RGB(109, 99, 98);
91 BKG_COLOR_SEL = RGB( 60, 60, 60);
92 BKG_COLOR_ACTIVE = RGB(250, 250, 250);
93 FONT_COLOR_NORMAL = RGB( 10, 10, 10);
94 FONT_COLOR_SEL = RGB(250, 250, 250);
95 break;
96
97 case 2: /* Dark */
98 BKG_COLOR_NORMAL = RGB( 32, 32, 32);
99 BKG_COLOR_ALT = RGB( 70, 70, 70);
100 BKG_COLOR_EXTRA = RGB( 14, 14, 14);
101 BKG_COLOR_EXTRA2 = RGB( 50, 50, 50);
102 BKG_COLOR_SEL = RGB(140, 140, 140);
103 BKG_COLOR_ACTIVE = RGB( 16, 16, 16);
104 FONT_COLOR_NORMAL = RGB(250, 250, 250);
105 FONT_COLOR_SEL = RGB( 10, 10, 10);
106 break;
107
108 case 3: /* Light */
109 BKG_COLOR_NORMAL = RGB(210, 210, 210);
110 BKG_COLOR_ALT = RGB(180, 180, 180);
111 BKG_COLOR_EXTRA = RGB(150, 150, 150);
112 BKG_COLOR_EXTRA2 = RGB(190, 190, 190);
113 BKG_COLOR_SEL = RGB( 60, 60, 60);
114 BKG_COLOR_ACTIVE = RGB(250, 250, 250);
115 FONT_COLOR_NORMAL = RGB( 10, 10, 10);
116 FONT_COLOR_SEL = RGB(250, 250, 250);
117 break;
118 }
119
120 int BKG_PADDING_X_DEFAULT = -3;
121 int BKG_PADDING_Y_DEFAULT = -3;
122
123 #if defined(__XVIC__)
124 if (retro_region == RETRO_REGION_NTSC)
125 {
126 XOFFSET = 9;
127 YOFFSET = -3;
128 XPADDING = 44;
129 YPADDING = 58;
130
131 if (zoom_mode_id == 3)
132 {
133 if (opt_statusbar & STATUSBAR_TOP)
134 YOFFSET = -2;
135 else
136 YOFFSET = -7;
137 }
138 }
139 else
140 {
141 XOFFSET = 4;
142 YOFFSET = -3;
143 XPADDING = 98;
144 YPADDING = 108;
145
146 if (zoom_mode_id == 3)
147 {
148 if (opt_statusbar & STATUSBAR_TOP)
149 YOFFSET = 2;
150 else
151 YOFFSET = -6;
152 }
153 }
154 #elif defined(__XPLUS4__)
155 if (retro_region == RETRO_REGION_NTSC)
156 {
157 XOFFSET = 0;
158 YOFFSET = -3;
159 XPADDING = 64;
160 YPADDING = 52;
161
162 if (zoom_mode_id == 3)
163 {
164 if (opt_statusbar & STATUSBAR_TOP)
165 YOFFSET = 1;
166 else
167 YOFFSET = -7;
168 }
169 }
170 else
171 {
172 XOFFSET = 4;
173 YOFFSET = -3;
174 XPADDING = 66;
175 YPADDING = 96;
176
177 if (zoom_mode_id == 3)
178 {
179 if (opt_statusbar & STATUSBAR_TOP)
180 YOFFSET = 1;
181 else
182 YOFFSET = -7;
183 }
184 }
185 #else
186 XOFFSET = 0;
187 YOFFSET = 1;
188 XPADDING = 74;
189 YPADDING = 78;
190
191 if (retro_region != RETRO_REGION_NTSC)
192 {
193 if (zoom_mode_id == 3)
194 YOFFSET = -3;
195 }
196
197 if (opt_statusbar & STATUSBAR_TOP)
198 YOFFSET = 5;
199 #endif
200
201 int XSIDE = (retrow - XPADDING) / VKBDX;
202 int YSIDE = (retroh - YPADDING) / VKBDY;
203
204 int XBASEKEY = (XPADDING > 0) ? (XPADDING / 2) : 0;
205 int YBASEKEY = (YPADDING > 0) ? (YPADDING / 2) : 0;
206
207 int XBASETEXT = ((XPADDING > 0) ? (XPADDING / 2) : 0) + (XSIDE / 2);
208 int YBASETEXT = YBASEKEY + (YSIDE / 2);
209
210 /* Coordinates */
211 vkbd_x_min = XBASEKEY + XKEYSPACING;
212 vkbd_x_max = -XBASEKEY + retrow - XKEYSPACING;
213 vkbd_y_min = YOFFSET + YBASEKEY + YKEYSPACING;
214 vkbd_y_max = YOFFSET + YBASEKEY + (YSIDE * VKBDY);
215
216 /* Opacity */
217 BKG_ALPHA = (retro_vkbd_transparent) ? ALPHA : GRAPH_ALPHA_100;
218 switch (BKG_ALPHA)
219 {
220 case GRAPH_ALPHA_0:
221 case GRAPH_ALPHA_25:
222 case GRAPH_ALPHA_50:
223 FONT_ALPHA = GRAPH_ALPHA_50;
224 break;
225 case GRAPH_ALPHA_75:
226 case GRAPH_ALPHA_100:
227 default:
228 FONT_ALPHA = GRAPH_ALPHA_25;
229 break;
230 }
231
232 /* Alternate color keys */
233 int alt_keys[] =
234 {
235 RETROK_F1, RETROK_F3, RETROK_F5, RETROK_F7,
236 #ifdef __XPLUS4__
237 RETROK_F2, RETROK_F8
238 #endif
239 };
240 int alt_keys_len = sizeof(alt_keys) / sizeof(alt_keys[0]);
241
242 /* Extra color keys */
243 int extra_keys[] =
244 {
245 -3 /* STB */ , -4 /* JOY */, -20 /* TTF */
246 };
247 int extra_keys_len = sizeof(extra_keys) / sizeof(extra_keys[0]);
248
249 /* Datasette color keys */
250 int datasette_keys[] =
251 {
252 -11, -12, -13, -14, -15
253 };
254 int datasette_keys_len = sizeof(datasette_keys) / sizeof(datasette_keys[0]);
255
256 /* Key label shifted */
257 shifted = false;
258 if (retro_capslock || vkey_sticky1 == RETROK_LSHIFT || vkey_sticky2 == RETROK_LSHIFT ||
259 vkey_sticky1 == RETROK_RSHIFT || vkey_sticky2 == RETROK_RSHIFT)
260 shifted = true;
261 if (vkflag[RETRO_DEVICE_ID_JOYPAD_B] && (vkey_pressed == RETROK_LSHIFT || vkey_pressed == RETROK_RSHIFT))
262 shifted = true;
263
264 /* Key layout */
265 for (x = 0; x < VKBDX; x++)
266 {
267 for (y = 0; y < VKBDY; y++)
268 {
269 /* Default key color */
270 BKG_COLOR = BKG_COLOR_NORMAL;
271 BKG_ALPHA = (retro_vkbd_transparent) ? ALPHA : GRAPH_ALPHA_100;
272
273 /* Reset key color */
274 if (vkeys[(y * VKBDX) + x].value == -2)
275 BKG_COLOR = RGB(128, 0, 0);
276 else
277 {
278 /* Alternate key color */
279 for (int alt_key = 0; alt_key < alt_keys_len; ++alt_key)
280 if (alt_keys[alt_key] == vkeys[(y * VKBDX) + x + page].value)
281 BKG_COLOR = BKG_COLOR_ALT;
282
283 /* Extra key color */
284 for (int extra_key = 0; extra_key < extra_keys_len; ++extra_key)
285 if (extra_keys[extra_key] == vkeys[(y * VKBDX) + x + page].value)
286 BKG_COLOR = BKG_COLOR_EXTRA;
287
288 /* Datasette key color */
289 for (int datasette_key = 0; datasette_key < datasette_keys_len; ++datasette_key)
290 if (datasette_keys[datasette_key] == vkeys[(y * VKBDX) + x + page].value)
291 BKG_COLOR = BKG_COLOR_EXTRA2;
292 }
293
294 /* Key centering */
295 BKG_PADDING_X = BKG_PADDING_X_DEFAULT;
296 BKG_PADDING_Y = BKG_PADDING_Y_DEFAULT;
297 if (!shifted && strlen(vkeys[(y * VKBDX) + x + page].normal) > 1)
298 BKG_PADDING_X = BKG_PADDING(strlen(vkeys[(y * VKBDX) + x + page].normal));
299 else if (shifted && strlen(vkeys[(y * VKBDX) + x + page].shift) > 1)
300 BKG_PADDING_X = BKG_PADDING(strlen(vkeys[(y * VKBDX) + x + page].shift));
301
302 /* Key positions */
303 XKEY = XBASEKEY + (x * XSIDE) + XOFFSET;
304 XTEXT = XBASETEXT + BKG_PADDING_X + (x * XSIDE) + XOFFSET;
305 YKEY = YOFFSET + YBASEKEY + (y * YSIDE);
306 YTEXT = YOFFSET + YBASETEXT + BKG_PADDING_Y + (y * YSIDE);
307
308 /* Default font color */
309 FONT_COLOR = FONT_COLOR_NORMAL;
310
311 /* Sticky + CapsLock + pressed colors */
312 if ( (vkey_sticky1 == vkeys[(y * VKBDX) + x + page].value
313 || vkey_sticky2 == vkeys[(y * VKBDX) + x + page].value
314 ||(retro_capslock && vkeys[(y * VKBDX) + x + page].value == -5)
315 ||(vkflag[RETRO_DEVICE_ID_JOYPAD_START] && vkeys[(y * VKBDX) + x + page].value == RETROK_RETURN))
316 && BKG_COLOR != BKG_COLOR_EXTRA && vkeys[(y * VKBDX) + x + page].value != -2)
317 {
318 FONT_COLOR = FONT_COLOR_NORMAL;
319 BKG_COLOR = BKG_COLOR_ACTIVE;
320
321 switch (BKG_ALPHA)
322 {
323 case GRAPH_ALPHA_0:
324 case GRAPH_ALPHA_25:
325 case GRAPH_ALPHA_50:
326 BKG_ALPHA = GRAPH_ALPHA_75;
327 break;
328 case GRAPH_ALPHA_75:
329 case GRAPH_ALPHA_100:
330 default:
331 /* Do nothing */
332 break;
333 }
334 }
335
336 /* Key background */
337 if (pix_bytes == 4)
338 DrawFBoxBmp32((uint32_t *)pix,
339 XKEY+XKEYSPACING, YKEY+YKEYSPACING, XSIDE-XKEYSPACING, YSIDE-YKEYSPACING,
340 BKG_COLOR, BKG_ALPHA);
341 else
342 DrawFBoxBmp(pix,
343 XKEY+XKEYSPACING, YKEY+YKEYSPACING, XSIDE-XKEYSPACING, YSIDE-YKEYSPACING,
344 BKG_COLOR, BKG_ALPHA);
345
346 /* Key text shadow */
347 if (pix_bytes == 4)
348 Draw_text32((uint32_t *)pix,
349 (FONT_COLOR_SEL == RGB(250, 250, 250) ? XTEXT+FONT_WIDTH : XTEXT-FONT_WIDTH),
350 (FONT_COLOR_SEL == RGB(250, 250, 250) ? YTEXT+FONT_WIDTH : YTEXT-FONT_WIDTH),
351 (FONT_COLOR_SEL == RGB(250, 250, 250) ? RGB(100, 100, 100) : RGB(50, 50, 50)),
352 BKG_COLOR, FONT_ALPHA, false, FONT_WIDTH, FONT_HEIGHT, FONT_MAX,
353 (!shifted) ? vkeys[(y * VKBDX) + x + page].normal : vkeys[(y * VKBDX) + x + page].shift);
354 else
355 Draw_text(pix,
356 (FONT_COLOR_SEL == RGB(250, 250, 250) ? XTEXT+FONT_WIDTH : XTEXT-FONT_WIDTH),
357 (FONT_COLOR_SEL == RGB(250, 250, 250) ? YTEXT+FONT_WIDTH : YTEXT-FONT_WIDTH),
358 (FONT_COLOR_SEL == RGB(250, 250, 250) ? RGB(100, 100, 100) : RGB(50, 50, 50)),
359 BKG_COLOR, FONT_ALPHA, false, FONT_WIDTH, FONT_HEIGHT, FONT_MAX,
360 (!shifted) ? vkeys[(y * VKBDX) + x + page].normal : vkeys[(y * VKBDX) + x + page].shift);
361
362 /* Key text */
363 if (pix_bytes == 4)
364 {
365 Draw_text32((uint32_t *)pix,
366 XTEXT, YTEXT, FONT_COLOR, BKG_COLOR, GRAPH_ALPHA_100, false, FONT_WIDTH, FONT_HEIGHT, FONT_MAX,
367 (!shifted) ? vkeys[(y * VKBDX) + x + page].normal : vkeys[(y * VKBDX) + x + page].shift);
368 }
369 else
370 {
371 Draw_text(pix,
372 XTEXT, YTEXT, FONT_COLOR, BKG_COLOR, GRAPH_ALPHA_100, false, FONT_WIDTH, FONT_HEIGHT, FONT_MAX,
373 (!shifted) ? vkeys[(y * VKBDX) + x + page].normal : vkeys[(y * VKBDX) + x + page].shift);
374 }
375 }
376 }
377
378 /* Key centering */
379 BKG_PADDING_X = BKG_PADDING_X_DEFAULT;
380 BKG_PADDING_Y = BKG_PADDING_Y_DEFAULT;
381 if (!shifted && strlen(vkeys[(vkey_pos_y * VKBDX) + vkey_pos_x + page].normal) > 1)
382 BKG_PADDING_X = BKG_PADDING(strlen(vkeys[(vkey_pos_y * VKBDX) + vkey_pos_x + page].normal));
383 else if (shifted && strlen(vkeys[(vkey_pos_y * VKBDX) + vkey_pos_x + page].shift) > 1)
384 BKG_PADDING_X = BKG_PADDING(strlen(vkeys[(vkey_pos_y * VKBDX) + vkey_pos_x + page].shift));
385
386 /* Selected key position */
387 XKEY = XBASEKEY + (vkey_pos_x * XSIDE) + XOFFSET;
388 XTEXT = XBASETEXT + BKG_PADDING_X + (vkey_pos_x * XSIDE) + XOFFSET;
389 YKEY = YOFFSET + YBASEKEY + (vkey_pos_y * YSIDE);
390 YTEXT = YOFFSET + YBASETEXT + BKG_PADDING_Y + (vkey_pos_y * YSIDE);
391
392 /* Opacity */
393 BKG_ALPHA = (retro_vkbd_transparent) ?
394 ((BKG_ALPHA == GRAPH_ALPHA_100) ? GRAPH_ALPHA_100 : GRAPH_ALPHA_75) : GRAPH_ALPHA_100;
395
396 /* Pressed key color */
397 if (vkflag[RETRO_DEVICE_ID_JOYPAD_B] && (vkeys[(vkey_pos_y * VKBDX) + vkey_pos_x + page].value == vkey_sticky1 ||
398 vkeys[(vkey_pos_y * VKBDX) + vkey_pos_x + page].value == vkey_sticky2))
399 ; /* no-op */
400 else if (vkflag[RETRO_DEVICE_ID_JOYPAD_B])
401 BKG_COLOR_SEL = BKG_COLOR_ACTIVE;
402 else
403 FONT_COLOR = FONT_COLOR_SEL;
404
405 /* Selected key background */
406 if (pix_bytes == 4)
407 DrawFBoxBmp32((uint32_t *)pix,
408 XKEY+XKEYSPACING, YKEY+YKEYSPACING, XSIDE-XKEYSPACING, YSIDE-YKEYSPACING,
409 BKG_COLOR_SEL, BKG_ALPHA);
410 else
411 DrawFBoxBmp(pix,
412 XKEY+XKEYSPACING, YKEY+YKEYSPACING, XSIDE-XKEYSPACING, YSIDE-YKEYSPACING,
413 BKG_COLOR_SEL, BKG_ALPHA);
414
415 /* Selected key text */
416 if (pix_bytes == 4)
417 {
418 Draw_text32((uint32_t *)pix,
419 XTEXT, YTEXT, FONT_COLOR, 0, GRAPH_ALPHA_100, false, FONT_WIDTH, FONT_HEIGHT, FONT_MAX,
420 (!shifted) ? vkeys[(vkey_pos_y * VKBDX) + vkey_pos_x + page].normal
421 : vkeys[(vkey_pos_y * VKBDX) + vkey_pos_x + page].shift);
422 }
423 else
424 {
425 Draw_text(pix,
426 XTEXT, YTEXT, FONT_COLOR, 0, GRAPH_ALPHA_100, false, FONT_WIDTH, FONT_HEIGHT, FONT_MAX,
427 (!shifted) ? vkeys[(vkey_pos_y * VKBDX) + vkey_pos_x + page].normal
428 : vkeys[(vkey_pos_y * VKBDX) + vkey_pos_x + page].shift);
429 }
430
431 #ifdef POINTER_DEBUG
432 if (pix_bytes == 4)
433 DrawHlineBmp32((uint32_t *)retro_bmp,
434 pointer_x, pointer_y, 1, 1,
435 RGB888(255, 0, 255));
436 else
437 DrawHlineBmp(retro_bmp,
438 pointer_x, pointer_y, 1, 1,
439 RGB565(255, 0, 255));
440 #endif
441 }
442
check_vkey(int x,int y)443 int check_vkey(int x, int y)
444 {
445 /* Check which key is pressed */
446 int page = 0;
447 return vkeys[(y * VKBDX) + x + page].value;
448 }
449