22 #define SCREEN_FORMAT SDL_PIXELFORMAT_ARGB8888
24 #define USE_LOCKED_TEXTURE 0
25 #define RENDER_SCALE_QUALITY 1
26 #define SCREEN_WIDTH 800
27 #define SCREEN_HEIGHT 400
28 #define FRAME_DELAY 40
29 #define STATUS_COLOUR_INDEX 1
30 #define BACKGROUND_COLOUR_INDEX 6
32 #define NORMAL_COLOUR_INDEX 1
33 #define SELECT_COLOUR_INDEX 1
34 #define OVER_COLOUR_INDEX 2
35 #define KEYTEST_COLOUR_INDEX 1
36 #define CONFLICT_COLOUR_INDEX 1
37 #define UNUSABLE_COLOUR_INDEX 1
38 #define LETTER_COLOUR_INDEX 0
39 #define STATUS(...) do { char buffer[1024]; snprintf(buffer, sizeof buffer, __VA_ARGS__); write_status(buffer); } while(0)
40 #define OSD_TRAY(...) OSD(-1,SCREEN_HEIGHT-20,__VA_ARGS__)
43 static const Uint8 init_vic2_palette_rgb[16 * 3] = {
61 static Uint32 palette[256];
70 static int load_keymap (
const char *
fn,
void (*callback)(
const char*, SDL_Scancode) )
73 FILE *fp = fopen(
fn,
"rb");
78 while (fgets(line,
sizeof line, fp)) {
79 if (strlen(line) > 250) {
84 if (*line ==
'\0' || *line ==
'#')
86 char *p1 = line + strlen(line) - 1;
87 while (*p1 <= 0x20 && p1 >= line)
90 printf(
"line=[%s]\n", line);
94 while (*p1 <= 0x20 && *p1 !=
'\0')
97 printf(
"bad1=[%s]\n", line);
109 while (*p2 <= 0x20 && *p2 !=
'\0')
119 printf(
"F1=[%s] F2=[%s] %d\n", p1,p2,SDL_GetScancodeFromName(p2));
120 callback(p1, SDL_GetScancodeFromName(p2));
126 static void clear_screen (
void )
132 static void clear_area (
int x1,
int y1,
int x2,
int y2,
Uint32 colour )
137 for (
int x = x1;
x <= x2;
x++)
148 if ((
signed char)chr < 32)
150 for (
int y = 0;
y < 16;
y++)
152 if ((b & 0x8000) && (
x < char_start))
154 for (
int y = 0;
y < 16;
y++) {
164 return chr ==
' ' ? 5 : char_width + 2;
167 static int write_string_min_x = 0, write_string_min_y = 0;
168 static int write_string_max_x = 0, write_string_max_y = 0;
169 static int clear_boundary_box = 1;
171 static void write_string (
int x1,
int y1,
const char *str,
Uint32 colour )
174 if (clear_boundary_box) {
175 write_string_min_x = x1;
176 write_string_min_y = y1;
177 write_string_max_x = 0;
178 write_string_max_y = 0;
181 if (*str == 1 && str[1]) {
182 colour = palette[str[1] & 15];
184 }
else if (*str ==
'\n') {
190 if (clear_boundary_box) {
191 if (y1 > write_string_max_y)
192 write_string_max_y = y1;
193 if (
x > write_string_max_x)
194 write_string_max_x =
x;
201 static void write_status (
const char *str )
204 for (
int a = 0; str[a]; a++)
205 if (str[a] ==
'\n' && str[a + 1])
207 if (write_string_max_x && clear_boundary_box)
208 clear_area(write_string_min_x, write_string_min_y, write_string_max_x, write_string_max_y + 16, palette[
BACKGROUND_COLOUR_INDEX]);
218 static struct keyboard_st keyboard_storage[256], *keyboard_limit = keyboard_storage;
221 static struct keyboard_st *search_key_by_coord (
int x,
int y )
224 while (k < keyboard_limit)
225 if (
x >= k->
x1 && x <= k->
x2 &&
y >= k->
y1 && y <= k->
y2)
234 while (k < keyboard_limit)
244 while (k < keyboard_limit)
254 static void construct_key (
int x1,
int y1,
int x2,
int y2,
const char *
title,
const char *
name, SDL_Scancode
code )
256 keyboard_limit->
x1 =
x1;
257 keyboard_limit->
y1 =
y1;
258 keyboard_limit->
x2 =
x2;
259 keyboard_limit->
y2 =
y2;
267 static void draw_key (
struct keyboard_st *k,
int mode )
269 clear_area(k->
x1, k->
y1, k->
x2, k->
y2, palette[mode]);
270 clear_boundary_box = 0;
272 clear_boundary_box = 1;
276 static void assign_named_key (
const char *
name, SDL_Scancode
code )
287 static void draw_full_keyboard (
void )
290 while (k < keyboard_limit)
294 static double construct_keyboard_row (
double x,
double y,
double x_step,
int width,
int height,
const char *desc )
296 char buffer[4096], *s = buffer;
297 strcpy(buffer, desc);
299 char *e = strchr(s,
'\1');
302 char *p = strchr(s,
'=');
307 construct_key(
x,
y,
x + width,
y + height, s, p, SDL_SCANCODE_UNKNOWN);
317 static void construct_mega_keyboard (
void )
320 construct_keyboard_row( 28 , 4, 48.5, 26, 30,
"stop");
321 construct_keyboard_row( 28 + 2*48.5, 4, 48.5, 26, 30,
"esc\1alt\1lock\1no.sc");
322 construct_keyboard_row( 28 + 7*48.5, 4, 48.5, 26, 30,
"F1\1F3\1F5\1F7");
323 construct_keyboard_row( 28 + 12*48.5, 4, 48.5, 26, 30,
"F9\1F11\1F13\1help");
325 construct_keyboard_row( 28, 68, 48.5, 26, 30,
"<-\1" "1\1" "2\1" "3\1" "4\1" "5\1" "6\1" "7\1" "8\1" "9\1" "0\1+\1-\1pnd\1clr\1DEL");
327 construct_keyboard_row(100, 114, 48.5, 26, 26,
"Q\1W\1E\1R\1T\1Y\1U\1I\1O\1P\1a\1b\1c");
329 construct_keyboard_row( 15, 159, 48.5, 26, 26,
"ctrl\1lck\1A\1S\1D\1F\1G\1H\1J\1K\1L\1d\1e\1f");
331 construct_keyboard_row(136, 202, 48.5, 26, 26,
"Z\1X\1C\1V\1B\1N\1M\1<\n,\1>\n.\1?\n/");
335 int main (
int argc,
char **argv )
337 static const char boring_warning[] =
"\nThis program is not meant to be used manually.\nPlease use the menu of an Xemu emulator which supports key re-mapping.";
340 FATAL(
"Missing specifier(s) from command line.%s", boring_warning);
341 if (!strcmp(argv[3],
"mega65"))
342 construct_mega_keyboard();
344 FATAL(
"Bad target specifier: \"%s\"%s", argv[3], boring_warning);
346 if (load_keymap(argv[1], assign_named_key))
358 init_vic2_palette_rgb,
366 const Uint8 osd_palette[] = {
374 sizeof(osd_palette) >> 2,
378 OSD_TRAY(
"Welcome to Xemu's Keymap Configurator!");
380 SDL_Surface *surf = SDL_LoadBMP(
"mega65-kbd.bmp");
382 printf(
"Colours=%d\n", surf->format->palette->ncolors);
383 for (
int a = 0; a < 128; a++)
384 palette[128 + (a & 127)] = SDL_MapRGBA(
386 surf->format->palette->colors[a].r,
387 surf->format->palette->colors[a].g,
388 surf->format->palette->colors[a].b,
391 printf(
"BitsPerPixel=%d BytesPerPixel=%d\n",
392 surf->format->BitsPerPixel,
393 surf->format->BytesPerPixel
395 for (
int a = 0; a < 800 * 300; a++)
398 FATAL(
"Cannot load keyboard image: %s", SDL_GetError());
399 draw_full_keyboard();
403 static const char help_msg[] =
"Quick help: click on a key to assign, then press a key\non your keyboard to define it\nClose window to save or cancel your mapping.";
408 struct keyboard_st *wait_for_assignment = NULL, *mouse_on_key = NULL;
409 SDL_Scancode result_for_assignment = SDL_SCANCODE_UNKNOWN;
411 int force_render = 0;
413 old_ticks = SDL_GetTicks();
414 while (SDL_PollEvent(&ev)) {
421 if (wait_for_assignment) {
423 OSD_TRAY(
"ERROR: key repeats, too long press!");
424 }
else if (result_for_assignment != ev.key.keysym.scancode && ev.key.keysym.scancode != SDL_SCANCODE_UNKNOWN) {
425 OSD_TRAY(
"ERROR: multiple keypresses are used!");
426 result_for_assignment = SDL_SCANCODE_UNKNOWN;
427 }
else if (result_for_assignment == ev.key.keysym.scancode && result_for_assignment != SDL_SCANCODE_UNKNOWN) {
432 OSD_TRAY(
"OK: assigned key: %s", SDL_GetScancodeName(ev.key.keysym.scancode));
433 STATUS(
"Last operation: assigned key: %s\nDo not give up, assign a new key today! Just here and now!", SDL_GetScancodeName(ev.key.keysym.scancode));
434 wait_for_assignment->
code = result_for_assignment;
435 result_for_assignment = SDL_SCANCODE_UNKNOWN;
436 wait_for_assignment = NULL;
443 if (ev.key.keysym.scancode == SDL_SCANCODE_ESCAPE)
445 if (wait_for_assignment) {
447 OSD_TRAY(
"ERROR: key repeats, too long press!");
448 }
else if (result_for_assignment != SDL_SCANCODE_UNKNOWN) {
449 OSD_TRAY(
"ERROR: multiple keypresses are used!");
452 if (ev.key.keysym.scancode == SDL_SCANCODE_UNKNOWN)
453 OSD_TRAY(
"ERROR: This key has no proper SDL decode!");
455 result_for_assignment = ev.key.keysym.scancode;
459 struct keyboard_st *k = search_key_by_code(ev.key.keysym.scancode);
460 const char *sname = SDL_GetScancodeName(ev.key.keysym.scancode);
462 STATUS(
"KEY: %s %s %s", k->
title, k->
name, *sname ? sname :
"UNASSIGNED");
464 STATUS(
"The pressed key (%s) is not assigned to any emulated key.", sname);
469 case SDL_MOUSEBUTTONDOWN:
472 OSD_TRAY(
"Waiting your keypress to assign!!");
473 STATUS(
"Now please press a key on your keyboard to assign for the emulated key: %s", mouse_on_key->name);
474 wait_for_assignment = mouse_on_key;
477 }
else if (wait_for_assignment)
478 OSD_TRAY(
"Not possible before assigning the selected key");
481 case SDL_MOUSEMOTION:
482 if (!wait_for_assignment && ev.motion.x >= 0 && ev.motion.x <
SCREEN_WIDTH && ev.motion.y >= 0 && ev.motion.y <
SCREEN_HEIGHT) {
485 struct keyboard_st *k = search_key_by_coord(ev.motion.x, ev.motion.y);
487 if (mouse_on_key != k) {
489 draw_full_keyboard();
491 const char *sname = SDL_GetScancodeName(k->
code);
492 STATUS(
"KEY: %s %s %s", k->
title, k->
name, *sname ? sname :
"UNASSIGNED");
495 }
else if (mouse_on_key) {
497 draw_full_keyboard();
503 case SDL_WINDOWEVENT:
521 Uint32 new_ticks = SDL_GetTicks();