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