comparison nuklear_ui/blastem_nuklear.c @ 2202:ee6d30c56eeb

Add separate model/IO selection settings for SMS/GG
author Michael Pavone <pavone@retrodev.com>
date Mon, 22 Aug 2022 22:56:05 -0700
parents 1270fe86eb89
children ff700f50541c
comparison
equal deleted inserted replaced
2201:2f8984ff5c85 2202:ee6d30c56eeb
29 uint32_t *image_data; 29 uint32_t *image_data;
30 uint32_t width, height; 30 uint32_t width, height;
31 struct nk_image ui; 31 struct nk_image ui;
32 } ui_image; 32 } ui_image;
33 33
34 static ui_image **ui_images, *controller_360, *controller_ps4, 34 static ui_image **ui_images, *controller_360, *controller_ps4,
35 *controller_ps4_6b, *controller_wiiu, *controller_gen_6b; 35 *controller_ps4_6b, *controller_wiiu, *controller_gen_6b;
36 static uint32_t num_ui_images, ui_image_storage; 36 static uint32_t num_ui_images, ui_image_storage;
37 37
38 typedef void (*view_fun)(struct nk_context *); 38 typedef void (*view_fun)(struct nk_context *);
39 static view_fun current_view; 39 static view_fun current_view;
67 num_prev = 0; 67 num_prev = 0;
68 } 68 }
69 69
70 void view_play(struct nk_context *context) 70 void view_play(struct nk_context *context)
71 { 71 {
72 72
73 } 73 }
74 74
75 static char *browser_cur_path; 75 static char *browser_cur_path;
76 static const char *browser_label; 76 static const char *browser_label;
77 static const char *browser_setting_path; 77 static const char *browser_setting_path;
161 current_system->request_exit(current_system); 161 current_system->request_exit(current_system);
162 } else { 162 } else {
163 init_system_with_media(full_path, SYSTEM_UNKNOWN); 163 init_system_with_media(full_path, SYSTEM_UNKNOWN);
164 free(full_path); 164 free(full_path);
165 } 165 }
166 166
167 clear_view_stack(); 167 clear_view_stack();
168 show_play_view(); 168 show_play_view();
169 } else if (browser_setting_path) { 169 } else if (browser_setting_path) {
170 config = tern_insert_path(config, browser_setting_path, (tern_val){.ptrval = full_path}, TVAL_PTR); 170 config = tern_insert_path(config, browser_setting_path, (tern_val){.ptrval = full_path}, TVAL_PTR);
171 config_dirty = 1; 171 config_dirty = 1;
172 browser_ext_list = NULL; 172 browser_ext_list = NULL;
173 pop_view(); 173 pop_view();
174 } else { 174 } else {
175 lockon_media(full_path); 175 lockon_media(full_path);
176 free(full_path); 176 free(full_path);
177 177
178 clear_view_stack(); 178 clear_view_stack();
179 show_play_view(); 179 show_play_view();
180 } 180 }
181 } 181 }
182 selected_entry = -1; 182 selected_entry = -1;
320 static void menu(struct nk_context *context, uint32_t num_entries, const menu_item *items, menu_handler handler) 320 static void menu(struct nk_context *context, uint32_t num_entries, const menu_item *items, menu_handler handler)
321 { 321 {
322 const uint32_t button_height = context->style.font->height * 1.75; 322 const uint32_t button_height = context->style.font->height * 1.75;
323 const uint32_t ideal_button_width = context->style.font->height * 10; 323 const uint32_t ideal_button_width = context->style.font->height * 10;
324 const uint32_t button_space = 6; 324 const uint32_t button_space = 6;
325 325
326 uint32_t width = render_width(); 326 uint32_t width = render_width();
327 uint32_t height = render_height(); 327 uint32_t height = render_height();
328 uint32_t top = height/2 - (button_height * num_entries)/2; 328 uint32_t top = height/2 - (button_height * num_entries)/2;
329 uint32_t button_width = width > ideal_button_width ? ideal_button_width : width; 329 uint32_t button_width = width > ideal_button_width ? ideal_button_width : width;
330 uint32_t left = width/2 - button_width/2; 330 uint32_t left = width/2 - button_width/2;
331 331
332 nk_layout_space_begin(context, NK_STATIC, top + button_height * num_entries, num_entries); 332 nk_layout_space_begin(context, NK_STATIC, top + button_height * num_entries, num_entries);
333 for (uint32_t i = 0; i < num_entries; i++) 333 for (uint32_t i = 0; i < num_entries; i++)
334 { 334 {
335 nk_layout_space_push(context, nk_rect(left, top + i * button_height, button_width, button_height-button_space)); 335 nk_layout_space_push(context, nk_rect(left, top + i * button_height, button_width, button_height-button_space));
336 if (nk_button_label(context, items[i].title)) { 336 if (nk_button_label(context, items[i].title)) {
367 void binding_group(struct nk_context *context, char *name, const char **binds, const char **bind_names, uint32_t num_binds, tern_node *binding_lookup) 367 void binding_group(struct nk_context *context, char *name, const char **binds, const char **bind_names, uint32_t num_binds, tern_node *binding_lookup)
368 { 368 {
369 nk_layout_row_static(context, (context->style.font->height + 4)*num_binds+context->style.font->height+30, render_width() - 80, 1); 369 nk_layout_row_static(context, (context->style.font->height + 4)*num_binds+context->style.font->height+30, render_width() - 80, 1);
370 if (nk_group_begin(context, name, NK_WINDOW_TITLE)) { 370 if (nk_group_begin(context, name, NK_WINDOW_TITLE)) {
371 nk_layout_row_static(context, context->style.font->height, render_width()/2 - 80, 2); 371 nk_layout_row_static(context, context->style.font->height, render_width()/2 - 80, 2);
372 372
373 for (int i = 0; i < num_binds; i++) 373 for (int i = 0; i < num_binds; i++)
374 { 374 {
375 char *label_alloc = bind_names ? NULL : path_extension(binds[i]); 375 char *label_alloc = bind_names ? NULL : path_extension(binds[i]);
376 const char *label = label_alloc; 376 const char *label = label_alloc;
377 if (!label) { 377 if (!label) {
498 static const char *debug_binds[] = { 498 static const char *debug_binds[] = {
499 "ui.enter_debugger", "ui.plane_debug", "ui.vram_debug", "ui.cram_debug", 499 "ui.enter_debugger", "ui.plane_debug", "ui.vram_debug", "ui.cram_debug",
500 "ui.compositing_debug", "ui.vdp_debug_mode" 500 "ui.compositing_debug", "ui.vdp_debug_mode"
501 }; 501 };
502 const char *debug_names[] = { 502 const char *debug_names[] = {
503 "CPU Debugger", "Plane Debugger", "VRAM Debugger", "CRAM Debugger", 503 "CPU Debugger", "Plane Debugger", "VRAM Debugger", "CRAM Debugger",
504 "Layer Debugger", "Cycle Mode/Pal" 504 "Layer Debugger", "Cycle Mode/Pal"
505 }; 505 };
506 const uint32_t NUM_C1_BINDS = sizeof(controller1_binds)/sizeof(*controller1_binds); 506 const uint32_t NUM_C1_BINDS = sizeof(controller1_binds)/sizeof(*controller1_binds);
507 const uint32_t NUM_C2_BINDS = sizeof(controller2_binds)/sizeof(*controller2_binds); 507 const uint32_t NUM_C2_BINDS = sizeof(controller2_binds)/sizeof(*controller2_binds);
508 const uint32_t NUM_SPEED_BINDS = sizeof(speed_binds)/sizeof(*speed_binds); 508 const uint32_t NUM_SPEED_BINDS = sizeof(speed_binds)/sizeof(*speed_binds);
555 uint32_t suffix_len = strlen(name) + 1; 555 uint32_t suffix_len = strlen(name) + 1;
556 char *path = malloc(prefix_len + suffix_len + 1); 556 char *path = malloc(prefix_len + suffix_len + 1);
557 memcpy(path, "bindings\0keys\0", prefix_len); 557 memcpy(path, "bindings\0keys\0", prefix_len);
558 memcpy(path + prefix_len, name, suffix_len); 558 memcpy(path + prefix_len, name, suffix_len);
559 path[prefix_len + suffix_len] = 0; 559 path[prefix_len + suffix_len] = 0;
560 560
561 config_dirty = 1; 561 config_dirty = 1;
562 config = tern_insert_path(config, path, (tern_val){.ptrval = strdup(set_binding)}, TVAL_PTR); 562 config = tern_insert_path(config, path, (tern_val){.ptrval = strdup(set_binding)}, TVAL_PTR);
563 free(path); 563 free(path);
564 free(name); 564 free(name);
565 tern_free(binding_lookup); 565 tern_free(binding_lookup);
598 [SDL_CONTROLLER_BUTTON_RIGHTSHOULDER] = "r1", 598 [SDL_CONTROLLER_BUTTON_RIGHTSHOULDER] = "r1",
599 [SDL_CONTROLLER_BUTTON_LEFTSTICK] = "l3", 599 [SDL_CONTROLLER_BUTTON_LEFTSTICK] = "l3",
600 [SDL_CONTROLLER_BUTTON_RIGHTSTICK] = "r3", 600 [SDL_CONTROLLER_BUTTON_RIGHTSTICK] = "r3",
601 }; 601 };
602 602
603 typedef struct { 603 typedef struct {
604 const char *button_binds[SDL_CONTROLLER_BUTTON_MAX]; 604 const char *button_binds[SDL_CONTROLLER_BUTTON_MAX];
605 const char *left_stick[NUM_AXIS_DIRS]; 605 const char *left_stick[NUM_AXIS_DIRS];
606 const char *right_stick[NUM_AXIS_DIRS]; 606 const char *right_stick[NUM_AXIS_DIRS];
607 const char *triggers[2]; 607 const char *triggers[2];
608 } pad_bind_config; 608 } pad_bind_config;
721 "ui.set_speed.6", 721 "ui.set_speed.6",
722 "ui.set_speed.7", 722 "ui.set_speed.7",
723 "ui.set_speed.8", 723 "ui.set_speed.8",
724 "ui.set_speed.9" 724 "ui.set_speed.9"
725 }; 725 };
726 726
727 if (nk_begin(context, "Button Binding", nk_rect(0, 0, render_width(), render_height()), 0)) { 727 if (nk_begin(context, "Button Binding", nk_rect(0, 0, render_width(), render_height()), 0)) {
728 bind_option_group(context, "Controller Buttons", pad_opts, sizeof(pad_opts)/sizeof(*pad_opts)); 728 bind_option_group(context, "Controller Buttons", pad_opts, sizeof(pad_opts)/sizeof(*pad_opts));
729 bind_option_group(context, "System Buttons", system_buttons, sizeof(system_buttons)/sizeof(*system_buttons)); 729 bind_option_group(context, "System Buttons", system_buttons, sizeof(system_buttons)/sizeof(*system_buttons));
730 bind_option_group(context, "Emulator Control", emu_control, sizeof(emu_control)/sizeof(*emu_control)); 730 bind_option_group(context, "Emulator Control", emu_control, sizeof(emu_control)/sizeof(*emu_control));
731 bind_option_group(context, "Debugging", debugger, sizeof(debugger)/sizeof(*debugger)); 731 bind_option_group(context, "Debugging", debugger, sizeof(debugger)/sizeof(*debugger));
732 bind_option_group(context, "Speed Control", speeds, sizeof(speeds)/sizeof(*speeds)); 732 bind_option_group(context, "Speed Control", speeds, sizeof(speeds)/sizeof(*speeds));
733 733
734 nk_layout_row_static(context, context->style.font->height, (render_width() - 80)/4, 1); 734 nk_layout_row_static(context, context->style.font->height, (render_width() - 80)/4, 1);
735 if (nk_button_label(context, "Back")) { 735 if (nk_button_label(context, "Back")) {
736 pop_view(); 736 pop_view();
737 } 737 }
738 nk_end(context); 738 nk_end(context);
741 741
742 static void binding_box(struct nk_context *context, pad_bind_config *bindings, char *name, float x, float y, float width, int num_binds, int *binds) 742 static void binding_box(struct nk_context *context, pad_bind_config *bindings, char *name, float x, float y, float width, int num_binds, int *binds)
743 { 743 {
744 const struct nk_user_font *font = context->style.font; 744 const struct nk_user_font *font = context->style.font;
745 float row_height = font->height * 2; 745 float row_height = font->height * 2;
746 746
747 char const **labels = calloc(sizeof(char *), num_binds); 747 char const **labels = calloc(sizeof(char *), num_binds);
748 char const ***conf_vals = calloc(sizeof(char *), num_binds); 748 char const ***conf_vals = calloc(sizeof(char *), num_binds);
749 float max_width = 0.0f; 749 float max_width = 0.0f;
750 750
751 int skipped = 0; 751 int skipped = 0;
752 for (int i = 0; i < num_binds; i++) 752 for (int i = 0; i < num_binds; i++)
753 { 753 {
754 if (binds[i] & AXIS) { 754 if (binds[i] & AXIS) {
755 labels[i] = get_axis_label(&selected_controller_info, binds[i] & ~AXIS); 755 labels[i] = get_axis_label(&selected_controller_info, binds[i] & ~AXIS);
769 float lb_width = font->width(font->userdata, font->height, labels[i], strlen(labels[i])); 769 float lb_width = font->width(font->userdata, font->height, labels[i], strlen(labels[i]));
770 max_width = max_width < lb_width ? lb_width : max_width; 770 max_width = max_width < lb_width ? lb_width : max_width;
771 } 771 }
772 nk_layout_space_push(context, nk_rect(x, y, width, (num_binds - skipped) * (row_height + 4) + 4)); 772 nk_layout_space_push(context, nk_rect(x, y, width, (num_binds - skipped) * (row_height + 4) + 4));
773 nk_group_begin(context, name, NK_WINDOW_BORDER | NK_WINDOW_NO_SCROLLBAR); 773 nk_group_begin(context, name, NK_WINDOW_BORDER | NK_WINDOW_NO_SCROLLBAR);
774 774
775 float widths[] = {max_width + 3, width - (max_width + 6)}; 775 float widths[] = {max_width + 3, width - (max_width + 6)};
776 nk_layout_row(context, NK_STATIC, row_height, 2, widths); 776 nk_layout_row(context, NK_STATIC, row_height, 2, widths);
777 for (int i = 0; i < num_binds; i++) 777 for (int i = 0; i < num_binds; i++)
778 { 778 {
779 if (!labels[i]) { 779 if (!labels[i]) {
872 memcpy(full_key, axes_key, axes_key_size); 872 memcpy(full_key, axes_key, axes_key_size);
873 memcpy(full_key + axes_key_size, prefix, prefix_len); 873 memcpy(full_key + axes_key_size, prefix, prefix_len);
874 full_key[axes_key_size+prefix_len] = axis; 874 full_key[axes_key_size+prefix_len] = axis;
875 memcpy(full_key + axes_key_size + prefix_len + 1, suffix, suffix_len +1); 875 memcpy(full_key + axes_key_size + prefix_len + 1, suffix, suffix_len +1);
876 full_key[axes_key_size + prefix_len + 1 + suffix_len + 1] = 0; 876 full_key[axes_key_size + prefix_len + 1 + suffix_len + 1] = 0;
877 877
878 if (bindings[i]) { 878 if (bindings[i]) {
879 tern_insert_path(config, full_key, (tern_val){.ptrval = strdup(bindings[i])}, TVAL_PTR); 879 tern_insert_path(config, full_key, (tern_val){.ptrval = strdup(bindings[i])}, TVAL_PTR);
880 } else { 880 } else {
881 tern_val prev_val; 881 tern_val prev_val;
882 uint8_t prev_type = tern_delete_path(&config, full_key, &prev_val); 882 uint8_t prev_type = tern_delete_path(&config, full_key, &prev_val);
883 if (prev_type == TVAL_PTR) { 883 if (prev_type == TVAL_PTR) {
884 free(prev_val.ptrval); 884 free(prev_val.ptrval);
885 } 885 }
886 } 886 }
887 887
888 free(full_key); 888 free(full_key);
889 } 889 }
890 } 890 }
891 891
892 static pad_bind_config *bindings; 892 static pad_bind_config *bindings;
923 static const char button_base[] = "buttons"; 923 static const char button_base[] = "buttons";
924 size_t button_key_size = pad_key_size + sizeof(button_base); 924 size_t button_key_size = pad_key_size + sizeof(button_base);
925 char *button_key = malloc(button_key_size); 925 char *button_key = malloc(button_key_size);
926 memcpy(button_key, pad_key, pad_key_size); 926 memcpy(button_key, pad_key, pad_key_size);
927 memcpy(button_key + pad_key_size, button_base, sizeof(button_base)); 927 memcpy(button_key + pad_key_size, button_base, sizeof(button_base));
928 928
929 char *final_key; 929 char *final_key;
930 for (int i = 0; i < SDL_CONTROLLER_BUTTON_MAX; i++) 930 for (int i = 0; i < SDL_CONTROLLER_BUTTON_MAX; i++)
931 { 931 {
932 char *base; 932 char *base;
933 const char *suffix; 933 const char *suffix;
934 size_t base_key_len; 934 size_t base_key_len;
935 if ( i < SDL_CONTROLLER_BUTTON_DPAD_UP) { 935 if ( i < SDL_CONTROLLER_BUTTON_DPAD_UP) {
936 suffix = SDL_GameControllerGetStringForButton(i); 936 suffix = SDL_GameControllerGetStringForButton(i);
937 base_key_len = button_key_size; 937 base_key_len = button_key_size;
938 base = button_key; 938 base = button_key;
939 939
940 940
941 } else { 941 } else {
942 static const char *dir_keys[] = {"up", "down", "left", "right"}; 942 static const char *dir_keys[] = {"up", "down", "left", "right"};
943 suffix = dir_keys[i - SDL_CONTROLLER_BUTTON_DPAD_UP]; 943 suffix = dir_keys[i - SDL_CONTROLLER_BUTTON_DPAD_UP];
944 base = dpad_key; 944 base = dpad_key;
945 base_key_len = dpad_key_size; 945 base_key_len = dpad_key_size;
960 } 960 }
961 free(final_key); 961 free(final_key);
962 } 962 }
963 free(button_key); 963 free(button_key);
964 free(dpad_key); 964 free(dpad_key);
965 965
966 static const char axes_base[] = "axes"; 966 static const char axes_base[] = "axes";
967 size_t axes_key_size = pad_key_size + sizeof(axes_base); 967 size_t axes_key_size = pad_key_size + sizeof(axes_base);
968 char *axes_key = malloc(axes_key_size); 968 char *axes_key = malloc(axes_key_size);
969 memcpy(axes_key, pad_key, pad_key_size); 969 memcpy(axes_key, pad_key, pad_key_size);
970 memcpy(axes_key + pad_key_size, axes_base, sizeof(axes_base)); 970 memcpy(axes_key + pad_key_size, axes_base, sizeof(axes_base));
971 971
972 save_stick_binds(axes_key, axes_key_size,bindings->left_stick, "left"); 972 save_stick_binds(axes_key, axes_key_size,bindings->left_stick, "left");
973 save_stick_binds(axes_key, axes_key_size,bindings->right_stick, "right"); 973 save_stick_binds(axes_key, axes_key_size,bindings->right_stick, "right");
974 for (int i = SDL_CONTROLLER_AXIS_TRIGGERLEFT; i < SDL_CONTROLLER_AXIS_MAX; i++) 974 for (int i = SDL_CONTROLLER_AXIS_TRIGGERLEFT; i < SDL_CONTROLLER_AXIS_MAX; i++)
975 { 975 {
976 const char *suffix = SDL_GameControllerGetStringForAxis(i); 976 const char *suffix = SDL_GameControllerGetStringForAxis(i);
989 } 989 }
990 } 990 }
991 free(final_key); 991 free(final_key);
992 } 992 }
993 free(axes_key); 993 free(axes_key);
994 994
995 free(pad_key); 995 free(pad_key);
996 if (dest == SIMILAR_CONTROLLERS) { 996 if (dest == SIMILAR_CONTROLLERS) {
997 free(key); 997 free(key);
998 } 998 }
999 pop_view(); 999 pop_view();
1005 static menu_item options[NUM_DEST_TYPES]; 1005 static menu_item options[NUM_DEST_TYPES];
1006 options[IDENTICAL_CONTROLLERS].title = "Use for identical controllers"; 1006 options[IDENTICAL_CONTROLLERS].title = "Use for identical controllers";
1007 options[DEFAULT].title = "Use as default"; 1007 options[DEFAULT].title = "Use as default";
1008 options[BY_INDEX].title = by_index_names[selected_controller]; 1008 options[BY_INDEX].title = by_index_names[selected_controller];
1009 options[SIMILAR_CONTROLLERS].title = make_human_readable_type_name(&selected_controller_info); 1009 options[SIMILAR_CONTROLLERS].title = make_human_readable_type_name(&selected_controller_info);
1010 1010
1011 if (nk_begin(context, "Select Binding Dest", nk_rect(0, 0, render_width(), render_height()), NK_WINDOW_NO_SCROLLBAR)) { 1011 if (nk_begin(context, "Select Binding Dest", nk_rect(0, 0, render_width(), render_height()), NK_WINDOW_NO_SCROLLBAR)) {
1012 menu(context, NUM_DEST_TYPES, options, handle_dest_clicked); 1012 menu(context, NUM_DEST_TYPES, options, handle_dest_clicked);
1013 nk_end(context); 1013 nk_end(context);
1014 } 1014 }
1015 free((char *)options[SIMILAR_CONTROLLERS].title); 1015 free((char *)options[SIMILAR_CONTROLLERS].title);
1048 { 1048 {
1049 bindings->button_binds[button_idx[i]] = tern_find_ptr(dpad, dir_keys[i]); 1049 bindings->button_binds[button_idx[i]] = tern_find_ptr(dpad, dir_keys[i]);
1050 } 1050 }
1051 } 1051 }
1052 } 1052 }
1053 1053
1054 float orig_height = def_font->handle.height; 1054 float orig_height = def_font->handle.height;
1055 def_font->handle.height *= 0.5f; 1055 def_font->handle.height *= 0.5f;
1056 1056
1057 uint32_t avail_height = render_height() - 2 * orig_height; 1057 uint32_t avail_height = render_height() - 2 * orig_height;
1058 float desired_width = render_width() * 0.5f, desired_height = avail_height * 0.5f; 1058 float desired_width = render_width() * 0.5f, desired_height = avail_height * 0.5f;
1059 ui_image *controller_image = select_best_image(&selected_controller_info); 1059 ui_image *controller_image = select_best_image(&selected_controller_info);
1060 1060
1061 float controller_ratio = (float)controller_image->width / (float)controller_image->height; 1061 float controller_ratio = (float)controller_image->width / (float)controller_image->height;
1062 1062
1063 const struct nk_user_font *font = context->style.font; 1063 const struct nk_user_font *font = context->style.font;
1064 int MIN_BIND_BOX_WIDTH = font->width(font->userdata, font->height, "Right", strlen("Right")) 1064 int MIN_BIND_BOX_WIDTH = font->width(font->userdata, font->height, "Right", strlen("Right"))
1065 + def_font->handle.width(font->userdata, font->height, "Internal Screenshot", strlen("Internal Screenshot")); 1065 + def_font->handle.width(font->userdata, font->height, "Internal Screenshot", strlen("Internal Screenshot"));
1066 1066
1067 if (render_width() - desired_width < 2.5f*MIN_BIND_BOX_WIDTH) { 1067 if (render_width() - desired_width < 2.5f*MIN_BIND_BOX_WIDTH) {
1068 desired_width = render_width() - 2.5f*MIN_BIND_BOX_WIDTH; 1068 desired_width = render_width() - 2.5f*MIN_BIND_BOX_WIDTH;
1069 } 1069 }
1070 1070
1071 if (desired_width / desired_height > controller_ratio) { 1071 if (desired_width / desired_height > controller_ratio) {
1072 desired_width = desired_height * controller_ratio; 1072 desired_width = desired_height * controller_ratio;
1073 } else { 1073 } else {
1074 desired_height = desired_width / controller_ratio; 1074 desired_height = desired_width / controller_ratio;
1075 } 1075 }
1078 float img_right = img_left + desired_width; 1078 float img_right = img_left + desired_width;
1079 float img_bot = img_top + desired_height; 1079 float img_bot = img_top + desired_height;
1080 nk_layout_space_begin(context, NK_STATIC, avail_height, INT_MAX); 1080 nk_layout_space_begin(context, NK_STATIC, avail_height, INT_MAX);
1081 nk_layout_space_push(context, nk_rect(img_left, img_top, desired_width, desired_height)); 1081 nk_layout_space_push(context, nk_rect(img_left, img_top, desired_width, desired_height));
1082 nk_image(context, controller_image->ui); 1082 nk_image(context, controller_image->ui);
1083 1083
1084 float bind_box_width = (render_width() - img_right) * 0.8f; 1084 float bind_box_width = (render_width() - img_right) * 0.8f;
1085 if (bind_box_width < MIN_BIND_BOX_WIDTH) { 1085 if (bind_box_width < MIN_BIND_BOX_WIDTH) {
1086 bind_box_width = render_width() - img_right; 1086 bind_box_width = render_width() - img_right;
1087 if (bind_box_width > MIN_BIND_BOX_WIDTH) { 1087 if (bind_box_width > MIN_BIND_BOX_WIDTH) {
1088 bind_box_width = MIN_BIND_BOX_WIDTH; 1088 bind_box_width = MIN_BIND_BOX_WIDTH;
1094 if (bind_box_width >= (render_width() - img_right)) { 1094 if (bind_box_width >= (render_width() - img_right)) {
1095 bind_box_left = img_right; 1095 bind_box_left = img_right;
1096 } else { 1096 } else {
1097 bind_box_left = img_right + (render_width() - img_right) / 2.0f - bind_box_width / 2.0f; 1097 bind_box_left = img_right + (render_width() - img_right) / 2.0f - bind_box_width / 2.0f;
1098 } 1098 }
1099 1099
1100 if (selected_controller_info.variant == VARIANT_NORMAL) { 1100 if (selected_controller_info.variant == VARIANT_NORMAL) {
1101 binding_box(context, bindings, "Action Buttons", bind_box_left, img_top, bind_box_width, 4, (int[]){ 1101 binding_box(context, bindings, "Action Buttons", bind_box_left, img_top, bind_box_width, 4, (int[]){
1102 SDL_CONTROLLER_BUTTON_A, 1102 SDL_CONTROLLER_BUTTON_A,
1103 SDL_CONTROLLER_BUTTON_B, 1103 SDL_CONTROLLER_BUTTON_B,
1104 SDL_CONTROLLER_BUTTON_X, 1104 SDL_CONTROLLER_BUTTON_X,
1112 SDL_CONTROLLER_BUTTON_X, 1112 SDL_CONTROLLER_BUTTON_X,
1113 SDL_CONTROLLER_BUTTON_Y, 1113 SDL_CONTROLLER_BUTTON_Y,
1114 selected_controller_info.variant == VARIANT_6B_RIGHT ? SDL_CONTROLLER_BUTTON_RIGHTSHOULDER : SDL_CONTROLLER_BUTTON_LEFTSHOULDER, 1114 selected_controller_info.variant == VARIANT_6B_RIGHT ? SDL_CONTROLLER_BUTTON_RIGHTSHOULDER : SDL_CONTROLLER_BUTTON_LEFTSHOULDER,
1115 }); 1115 });
1116 } 1116 }
1117 1117
1118 if (selected_controller_info.variant == VARIANT_NORMAL) { 1118 if (selected_controller_info.variant == VARIANT_NORMAL) {
1119 binding_box(context, bindings, "Right Shoulder", bind_box_left, font->height/2, bind_box_width, 2, (int[]){ 1119 binding_box(context, bindings, "Right Shoulder", bind_box_left, font->height/2, bind_box_width, 2, (int[]){
1120 SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, 1120 SDL_CONTROLLER_BUTTON_RIGHTSHOULDER,
1121 AXIS | SDL_CONTROLLER_AXIS_TRIGGERRIGHT 1121 AXIS | SDL_CONTROLLER_AXIS_TRIGGERRIGHT
1122 }); 1122 });
1123 } else { 1123 } else {
1124 binding_box(context, bindings, "Right Shoulder", bind_box_left, font->height/2, bind_box_width, 1124 binding_box(context, bindings, "Right Shoulder", bind_box_left, font->height/2, bind_box_width,
1125 selected_controller_info.variant == VARIANT_6B_BUMPERS ? 1 : 2, 1125 selected_controller_info.variant == VARIANT_6B_BUMPERS ? 1 : 2,
1126 (int[]){ 1126 (int[]){
1127 selected_controller_info.variant == VARIANT_6B_RIGHT ? SDL_CONTROLLER_BUTTON_LEFTSHOULDER : AXIS | SDL_CONTROLLER_AXIS_TRIGGERRIGHT, 1127 selected_controller_info.variant == VARIANT_6B_RIGHT ? SDL_CONTROLLER_BUTTON_LEFTSHOULDER : AXIS | SDL_CONTROLLER_AXIS_TRIGGERRIGHT,
1128 AXIS | SDL_CONTROLLER_AXIS_TRIGGERLEFT 1128 AXIS | SDL_CONTROLLER_AXIS_TRIGGERLEFT
1129 }); 1129 });
1130 } 1130 }
1131 1131
1132 binding_box(context, bindings, "Misc Buttons", (render_width() - bind_box_width) / 2, font->height/2, bind_box_width, 3, (int[]){ 1132 binding_box(context, bindings, "Misc Buttons", (render_width() - bind_box_width) / 2, font->height/2, bind_box_width, 3, (int[]){
1133 SDL_CONTROLLER_BUTTON_BACK, 1133 SDL_CONTROLLER_BUTTON_BACK,
1134 SDL_CONTROLLER_BUTTON_GUIDE, 1134 SDL_CONTROLLER_BUTTON_GUIDE,
1135 SDL_CONTROLLER_BUTTON_START 1135 SDL_CONTROLLER_BUTTON_START
1136 }); 1136 });
1137 1137
1138 if (selected_controller_info.variant == VARIANT_NORMAL) 1138 if (selected_controller_info.variant == VARIANT_NORMAL)
1139 { 1139 {
1140 binding_box(context, bindings, "Right Stick", img_right - desired_width/3, img_bot, bind_box_width, 5, (int[]){ 1140 binding_box(context, bindings, "Right Stick", img_right - desired_width/3, img_bot, bind_box_width, 5, (int[]){
1141 RIGHTSTICK | UP, 1141 RIGHTSTICK | UP,
1142 RIGHTSTICK | DOWN, 1142 RIGHTSTICK | DOWN,
1143 RIGHTSTICK | LEFT, 1143 RIGHTSTICK | LEFT,
1144 RIGHTSTICK | RIGHT, 1144 RIGHTSTICK | RIGHT,
1145 SDL_CONTROLLER_BUTTON_RIGHTSTICK 1145 SDL_CONTROLLER_BUTTON_RIGHTSTICK
1146 }); 1146 });
1147 } 1147 }
1148 1148
1149 bind_box_left -= img_right; 1149 bind_box_left -= img_right;
1150 float dpad_left, dpad_top; 1150 float dpad_left, dpad_top;
1151 if (selected_controller_info.variant == VARIANT_NORMAL) 1151 if (selected_controller_info.variant == VARIANT_NORMAL)
1152 { 1152 {
1153 binding_box(context, bindings, "Left Stick", bind_box_left, img_top, bind_box_width, 5, (int[]){ 1153 binding_box(context, bindings, "Left Stick", bind_box_left, img_top, bind_box_width, 5, (int[]){
1161 dpad_top = img_bot + font->height * 1.5; 1161 dpad_top = img_bot + font->height * 1.5;
1162 } else { 1162 } else {
1163 dpad_left = bind_box_left; 1163 dpad_left = bind_box_left;
1164 dpad_top = img_top; 1164 dpad_top = img_top;
1165 } 1165 }
1166 1166
1167 if (selected_controller_info.variant == VARIANT_NORMAL) { 1167 if (selected_controller_info.variant == VARIANT_NORMAL) {
1168 binding_box(context, bindings, "Left Shoulder", bind_box_left, font->height/2, bind_box_width, 2, (int[]){ 1168 binding_box(context, bindings, "Left Shoulder", bind_box_left, font->height/2, bind_box_width, 2, (int[]){
1169 SDL_CONTROLLER_BUTTON_LEFTSHOULDER, 1169 SDL_CONTROLLER_BUTTON_LEFTSHOULDER,
1170 AXIS | SDL_CONTROLLER_AXIS_TRIGGERLEFT 1170 AXIS | SDL_CONTROLLER_AXIS_TRIGGERLEFT
1171 }); 1171 });
1172 } else { 1172 } else {
1173 binding_box(context, bindings, "Left Shoulder", bind_box_left, font->height/2, bind_box_width, 1173 binding_box(context, bindings, "Left Shoulder", bind_box_left, font->height/2, bind_box_width,
1174 selected_controller_info.variant == VARIANT_6B_BUMPERS ? 1 : 2, 1174 selected_controller_info.variant == VARIANT_6B_BUMPERS ? 1 : 2,
1175 (int[]){ 1175 (int[]){
1176 selected_controller_info.variant == VARIANT_6B_RIGHT ? SDL_CONTROLLER_BUTTON_LEFTSTICK : AXIS | SDL_CONTROLLER_AXIS_TRIGGERLEFT, 1176 selected_controller_info.variant == VARIANT_6B_RIGHT ? SDL_CONTROLLER_BUTTON_LEFTSTICK : AXIS | SDL_CONTROLLER_AXIS_TRIGGERLEFT,
1177 SDL_CONTROLLER_BUTTON_RIGHTSTICK 1177 SDL_CONTROLLER_BUTTON_RIGHTSTICK
1178 }); 1178 });
1179 } 1179 }
1180 1180
1181 binding_box(context, bindings, "D-pad", dpad_left, dpad_top, bind_box_width, 4, (int[]){ 1181 binding_box(context, bindings, "D-pad", dpad_left, dpad_top, bind_box_width, 4, (int[]){
1182 SDL_CONTROLLER_BUTTON_DPAD_UP, 1182 SDL_CONTROLLER_BUTTON_DPAD_UP,
1183 SDL_CONTROLLER_BUTTON_DPAD_DOWN, 1183 SDL_CONTROLLER_BUTTON_DPAD_DOWN,
1184 SDL_CONTROLLER_BUTTON_DPAD_LEFT, 1184 SDL_CONTROLLER_BUTTON_DPAD_LEFT,
1185 SDL_CONTROLLER_BUTTON_DPAD_RIGHT 1185 SDL_CONTROLLER_BUTTON_DPAD_RIGHT
1186 }); 1186 });
1187 1187
1188 nk_layout_space_end(context); 1188 nk_layout_space_end(context);
1189 1189
1190 def_font->handle.height = orig_height; 1190 def_font->handle.height = orig_height;
1191 nk_layout_row_static(context, orig_height + 4, (render_width() - 2*orig_height) / 4, 1); 1191 nk_layout_row_static(context, orig_height + 4, (render_width() - 2*orig_height) / 4, 1);
1192 if (nk_button_label(context, controller_binding_changed ? "Save" : "Back")) { 1192 if (nk_button_label(context, controller_binding_changed ? "Save" : "Back")) {
1193 pop_view(); 1193 pop_view();
1194 if (controller_binding_changed) { 1194 if (controller_binding_changed) {
1228 { 1228 {
1229 char buffer[512]; 1229 char buffer[512];
1230 static int quiet, button_a = -1, button_a_axis = -1; 1230 static int quiet, button_a = -1, button_a_axis = -1;
1231 uint8_t added_mapping = 0; 1231 uint8_t added_mapping = 0;
1232 if (nk_begin(context, "Controllers", nk_rect(0, 0, render_width(), render_height()), NK_WINDOW_NO_SCROLLBAR)) { 1232 if (nk_begin(context, "Controllers", nk_rect(0, 0, render_width(), render_height()), NK_WINDOW_NO_SCROLLBAR)) {
1233 1233
1234 nk_layout_space_begin(context, NK_STATIC, render_height() - context->style.font->height, 3); 1234 nk_layout_space_begin(context, NK_STATIC, render_height() - context->style.font->height, 3);
1235 1235
1236 if (current_button < SDL_CONTROLLER_BUTTON_MAX) { 1236 if (current_button < SDL_CONTROLLER_BUTTON_MAX) {
1237 snprintf(buffer, sizeof(buffer), "Press Button %s", get_button_label(&selected_controller_info, current_button)); 1237 snprintf(buffer, sizeof(buffer), "Press Button %s", get_button_label(&selected_controller_info, current_button));
1238 } else { 1238 } else {
1239 snprintf(buffer, sizeof(buffer), "Move Axis %s", get_axis_label(&selected_controller_info, current_axis)); 1239 snprintf(buffer, sizeof(buffer), "Move Axis %s", get_axis_label(&selected_controller_info, current_axis));
1240 } 1240 }
1241 1241
1242 float height = context->style.font->height * 1.25; 1242 float height = context->style.font->height * 1.25;
1243 float top = render_height()/2 - 1.5 * height; 1243 float top = render_height()/2 - 1.5 * height;
1244 float width = render_width() - context->style.font->height; 1244 float width = render_width() - context->style.font->height;
1245 1245
1246 nk_layout_space_push(context, nk_rect(0, top, width, height)); 1246 nk_layout_space_push(context, nk_rect(0, top, width, height));
1247 nk_label(context, buffer, NK_TEXT_CENTERED); 1247 nk_label(context, buffer, NK_TEXT_CENTERED);
1248 if (current_button > SDL_CONTROLLER_BUTTON_B) { 1248 if (current_button > SDL_CONTROLLER_BUTTON_B) {
1249 nk_layout_space_push(context, nk_rect(0, top + height, width, height)); 1249 nk_layout_space_push(context, nk_rect(0, top + height, width, height));
1250 nk_label(context, "OR", NK_TEXT_CENTERED); 1250 nk_label(context, "OR", NK_TEXT_CENTERED);
1251 1251
1252 nk_layout_space_push(context, nk_rect(0, top + 2.0 * height, width, height)); 1252 nk_layout_space_push(context, nk_rect(0, top + 2.0 * height, width, height));
1253 snprintf(buffer, sizeof(buffer), "Press Button %s to skip", get_button_label(&selected_controller_info, SDL_CONTROLLER_BUTTON_A)); 1253 snprintf(buffer, sizeof(buffer), "Press Button %s to skip", get_button_label(&selected_controller_info, SDL_CONTROLLER_BUTTON_A));
1254 nk_label(context, buffer, NK_TEXT_CENTERED); 1254 nk_label(context, buffer, NK_TEXT_CENTERED);
1255 } 1255 }
1256 1256
1257 nk_layout_space_end(context); 1257 nk_layout_space_end(context);
1258 if (quiet) { 1258 if (quiet) {
1259 --quiet; 1259 --quiet;
1260 } else { 1260 } else {
1261 if (button_pressed >= 0 && button_pressed != last_button) { 1261 if (button_pressed >= 0 && button_pressed != last_button) {
1277 mapping_string[mapping_pos++] = 'h'; 1277 mapping_string[mapping_pos++] = 'h';
1278 mapping_string[mapping_pos++] = '0' + hat_moved; 1278 mapping_string[mapping_pos++] = '0' + hat_moved;
1279 mapping_string[mapping_pos++] = '.'; 1279 mapping_string[mapping_pos++] = '.';
1280 mapping_string[mapping_pos++] = '0' + hat_value; 1280 mapping_string[mapping_pos++] = '0' + hat_value;
1281 added_mapping = 1; 1281 added_mapping = 1;
1282 1282
1283 last_hat = hat_moved; 1283 last_hat = hat_moved;
1284 last_hat_value = hat_value; 1284 last_hat_value = hat_value;
1285 } else if (axis_moved >= 0 && abs(axis_value) > 1000 && ( 1285 } else if (axis_moved >= 0 && abs(axis_value) > 1000 && (
1286 axis_moved != last_axis || ( 1286 axis_moved != last_axis || (
1287 axis_value/abs(axis_value) != last_axis_value/abs(axis_value) && current_button >= SDL_CONTROLLER_BUTTON_DPAD_UP 1287 axis_value/abs(axis_value) != last_axis_value/abs(axis_value) && current_button >= SDL_CONTROLLER_BUTTON_DPAD_UP
1301 last_axis_value = axis_value; 1301 last_axis_value = axis_value;
1302 } 1302 }
1303 added_mapping = 1; 1303 added_mapping = 1;
1304 } 1304 }
1305 } 1305 }
1306 1306
1307 while (added_mapping) { 1307 while (added_mapping) {
1308 quiet = QUIET_FRAMES; 1308 quiet = QUIET_FRAMES;
1309 if (current_button < SDL_CONTROLLER_BUTTON_MAX) { 1309 if (current_button < SDL_CONTROLLER_BUTTON_MAX) {
1310 current_button++; 1310 current_button++;
1311 if (current_button == SDL_CONTROLLER_BUTTON_MAX) { 1311 if (current_button == SDL_CONTROLLER_BUTTON_MAX) {
1361 if (c == ',' || c == '\n' || c == '\r') { 1361 if (c == ',' || c == '\n' || c == '\r') {
1362 c = ' '; 1362 c = ' ';
1363 } 1363 }
1364 mapping_string[mapping_pos] = c; 1364 mapping_string[mapping_pos] = c;
1365 } 1365 }
1366 1366
1367 push_view(view_controller_mappings); 1367 push_view(view_controller_mappings);
1368 } 1368 }
1369 1369
1370 static void view_controller_variant(struct nk_context *context) 1370 static void view_controller_variant(struct nk_context *context)
1371 { 1371 {
1393 if (nk_button_label(context, "4 face buttons")) { 1393 if (nk_button_label(context, "4 face buttons")) {
1394 selected_controller_info.variant = VARIANT_NORMAL; 1394 selected_controller_info.variant = VARIANT_NORMAL;
1395 selected = 1; 1395 selected = 1;
1396 } 1396 }
1397 char buffer[512]; 1397 char buffer[512];
1398 snprintf(buffer, sizeof(buffer), "6 face buttons including %s and %s", 1398 snprintf(buffer, sizeof(buffer), "6 face buttons including %s and %s",
1399 get_button_label(&selected_controller_info, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER), 1399 get_button_label(&selected_controller_info, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER),
1400 get_axis_label(&selected_controller_info, SDL_CONTROLLER_AXIS_TRIGGERRIGHT) 1400 get_axis_label(&selected_controller_info, SDL_CONTROLLER_AXIS_TRIGGERRIGHT)
1401 ); 1401 );
1402 if (nk_button_label(context, buffer)) { 1402 if (nk_button_label(context, buffer)) {
1403 selected_controller_info.variant = VARIANT_6B_RIGHT; 1403 selected_controller_info.variant = VARIANT_6B_RIGHT;
1404 selected = 1; 1404 selected = 1;
1405 } 1405 }
1406 snprintf(buffer, sizeof(buffer), "6 face buttons including %s and %s", 1406 snprintf(buffer, sizeof(buffer), "6 face buttons including %s and %s",
1407 get_button_label(&selected_controller_info, SDL_CONTROLLER_BUTTON_LEFTSHOULDER), 1407 get_button_label(&selected_controller_info, SDL_CONTROLLER_BUTTON_LEFTSHOULDER),
1408 get_button_label(&selected_controller_info, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER) 1408 get_button_label(&selected_controller_info, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER)
1409 ); 1409 );
1410 if (nk_button_label(context, buffer)) { 1410 if (nk_button_label(context, buffer)) {
1411 selected_controller_info.variant = VARIANT_6B_BUMPERS; 1411 selected_controller_info.variant = VARIANT_6B_BUMPERS;
1412 selected = 1; 1412 selected = 1;
1493 int change_type_width = font->width(font->userdata, font->height, "Change Type", strlen("Change Type")) + context->style.button.padding.x * 2; 1493 int change_type_width = font->width(font->userdata, font->height, "Change Type", strlen("Change Type")) + context->style.button.padding.x * 2;
1494 int total = bindings_width + remap_width + change_type_width; 1494 int total = bindings_width + remap_width + change_type_width;
1495 float bindings_ratio = (float)bindings_width / total; 1495 float bindings_ratio = (float)bindings_width / total;
1496 float remap_ratio = (float)remap_width / total; 1496 float remap_ratio = (float)remap_width / total;
1497 float change_type_ratio = (float)change_type_width / total; 1497 float change_type_ratio = (float)change_type_width / total;
1498 1498
1499 1499
1500 uint8_t found_controller = 0; 1500 uint8_t found_controller = 0;
1501 for (int i = 0; i < MAX_JOYSTICKS; i++) 1501 for (int i = 0; i < MAX_JOYSTICKS; i++)
1502 { 1502 {
1503 SDL_Joystick *joy = render_get_joystick(i); 1503 SDL_Joystick *joy = render_get_joystick(i);
1504 if (joy) { 1504 if (joy) {
1513 } else { 1513 } else {
1514 nk_image(context, controller_image->ui); 1514 nk_image(context, controller_image->ui);
1515 } 1515 }
1516 int button_start = image_width + context->style.font->height; 1516 int button_start = image_width + context->style.font->height;
1517 int button_area_width = render_width() - image_width - 2 * context->style.font->height; 1517 int button_area_width = render_width() - image_width - 2 * context->style.font->height;
1518 1518
1519 nk_layout_space_push(context, nk_rect(button_start, 0, button_area_width, inner_height/2)); 1519 nk_layout_space_push(context, nk_rect(button_start, 0, button_area_width, inner_height/2));
1520 nk_label(context, info.name, NK_TEXT_CENTERED); 1520 nk_label(context, info.name, NK_TEXT_CENTERED);
1521 const struct nk_user_font *font = context->style.font; 1521 const struct nk_user_font *font = context->style.font;
1522 if (info.type == TYPE_UNKNOWN || info.type == TYPE_GENERIC_MAPPING) { 1522 if (info.type == TYPE_UNKNOWN || info.type == TYPE_GENERIC_MAPPING) {
1523 int button_width = font->width(font->userdata, font->height, "Configure", strlen("Configure")); 1523 int button_width = font->width(font->userdata, font->height, "Configure", strlen("Configure"));
1635 buffer[len] = 0; 1635 buffer[len] = 0;
1636 if (strcmp(buffer, curstr)) { 1636 if (strcmp(buffer, curstr)) {
1637 config_dirty = 1; 1637 config_dirty = 1;
1638 config = tern_insert_path(config, path, (tern_val){.ptrval = strdup(buffer)}, TVAL_PTR); 1638 config = tern_insert_path(config, path, (tern_val){.ptrval = strdup(buffer)}, TVAL_PTR);
1639 } 1639 }
1640 1640
1641 nk_spacing(context, 1); 1641 nk_spacing(context, 1);
1642 if (nk_button_label(context, "Browse")) { 1642 if (nk_button_label(context, "Browse")) {
1643 browser_label = label; 1643 browser_label = label;
1644 browser_setting_path = path; 1644 browser_setting_path = path;
1645 browser_ext_list = exts; 1645 browser_ext_list = exts;
1690 shader_prog *get_shader_progs(dir_entry *entries, size_t num_entries, shader_prog *progs, uint32_t *num_existing, uint32_t *storage) 1690 shader_prog *get_shader_progs(dir_entry *entries, size_t num_entries, shader_prog *progs, uint32_t *num_existing, uint32_t *storage)
1691 { 1691 {
1692 uint32_t num_progs = *num_existing; 1692 uint32_t num_progs = *num_existing;
1693 uint32_t prog_storage = *storage; 1693 uint32_t prog_storage = *storage;
1694 uint32_t starting = num_progs; 1694 uint32_t starting = num_progs;
1695 1695
1696 for (uint32_t i = 0; i < num_entries; i++) { 1696 for (uint32_t i = 0; i < num_entries; i++) {
1697 if (entries[i].is_dir) { 1697 if (entries[i].is_dir) {
1698 continue; 1698 continue;
1699 } 1699 }
1700 char *no_ext = basename_no_extension(entries[i].name); 1700 char *no_ext = basename_no_extension(entries[i].name);
1711 if (num_progs == prog_storage) { 1711 if (num_progs == prog_storage) {
1712 prog_storage = prog_storage ? prog_storage*2 : 4; 1712 prog_storage = prog_storage ? prog_storage*2 : 4;
1713 progs = realloc(progs, sizeof(*progs) * prog_storage); 1713 progs = realloc(progs, sizeof(*progs) * prog_storage);
1714 } 1714 }
1715 progs[num_progs].vertex = NULL; 1715 progs[num_progs].vertex = NULL;
1716 progs[num_progs++].fragment = strdup(entries[i].name); 1716 progs[num_progs++].fragment = strdup(entries[i].name);
1717 } 1717 }
1718 } 1718 }
1719 free(no_ext); 1719 free(no_ext);
1720 } 1720 }
1721 1721
1722 for (uint32_t i = 0; i < num_entries; i++) { 1722 for (uint32_t i = 0; i < num_entries; i++) {
1723 if (entries[i].is_dir) { 1723 if (entries[i].is_dir) {
1724 continue; 1724 continue;
1725 } 1725 }
1726 char *no_ext = basename_no_extension(entries[i].name); 1726 char *no_ext = basename_no_extension(entries[i].name);
1872 settings_int_property(context, "", "Right", "video\0ntsc\0overscan\0right\0", 14, 0, 32); 1872 settings_int_property(context, "", "Right", "video\0ntsc\0overscan\0right\0", 14, 0, 32);
1873 settings_int_property(context, "PAL Overscan", "Top", "video\0pal\0overscan\0top\0", 2, 0, 32); 1873 settings_int_property(context, "PAL Overscan", "Top", "video\0pal\0overscan\0top\0", 2, 0, 32);
1874 settings_int_property(context, "", "Bottom", "video\0pal\0overscan\0bottom\0", 17, 0, 32); 1874 settings_int_property(context, "", "Bottom", "video\0pal\0overscan\0bottom\0", 17, 0, 32);
1875 settings_int_property(context, "", "Left", "video\0pal\0overscan\0left\0", 13, 0, 32); 1875 settings_int_property(context, "", "Left", "video\0pal\0overscan\0left\0", 13, 0, 32);
1876 settings_int_property(context, "", "Right", "video\0pal\0overscan\0right\0", 14, 0, 32); 1876 settings_int_property(context, "", "Right", "video\0pal\0overscan\0right\0", 14, 0, 32);
1877 1877
1878 if (nk_button_label(context, "Back")) { 1878 if (nk_button_label(context, "Back")) {
1879 pop_view(); 1879 pop_view();
1880 } 1880 }
1881 nk_end(context); 1881 nk_end(context);
1882 } 1882 }
1941 typedef struct { 1941 typedef struct {
1942 const char **models; 1942 const char **models;
1943 const char **names; 1943 const char **names;
1944 uint32_t num_models; 1944 uint32_t num_models;
1945 uint32_t storage; 1945 uint32_t storage;
1946 uint8_t genesis_only;
1946 } model_foreach_state; 1947 } model_foreach_state;
1947 void model_iter(char *key, tern_val val, uint8_t valtype, void *data) 1948 void model_iter(char *key, tern_val val, uint8_t valtype, void *data)
1948 { 1949 {
1949 if (valtype != TVAL_NODE) { 1950 if (valtype != TVAL_NODE) {
1950 return; 1951 return;
1951 } 1952 }
1953 if (!strcmp(tern_find_ptr_default(val.ptrval, "show", "yes"), "no")) {
1954 return;
1955 }
1952 model_foreach_state *state = data; 1956 model_foreach_state *state = data;
1957 if (state->genesis_only && strcmp(tern_find_ptr_default(val.ptrval, "vdp", "genesis"), "genesis")) {
1958 return;
1959 }
1953 if (state->num_models == state->storage) { 1960 if (state->num_models == state->storage) {
1954 state->storage *= 2; 1961 state->storage *= 2;
1955 state->models = realloc(state->models, state->storage * sizeof(char *)); 1962 state->models = realloc(state->models, state->storage * sizeof(char *));
1956 state->names = realloc(state->names, state->storage * sizeof(char *)); 1963 state->names = realloc(state->names, state->storage * sizeof(char *));
1957 } 1964 }
1963 typedef struct { 1970 typedef struct {
1964 const char **models; 1971 const char **models;
1965 const char **names; 1972 const char **names;
1966 } models; 1973 } models;
1967 1974
1968 models get_models(uint32_t *num_out) 1975 models get_models(uint32_t *num_out, uint8_t genesis_only)
1969 { 1976 {
1970 tern_node *systems = get_systems_config(); 1977 tern_node *systems = get_systems_config();
1971 model_foreach_state state = { 1978 model_foreach_state state = {
1972 .models = calloc(4, sizeof(char *)), 1979 .models = calloc(4, sizeof(char *)),
1973 .names = calloc(4, sizeof(char *)), 1980 .names = calloc(4, sizeof(char *)),
1974 .num_models = 0, 1981 .num_models = 0,
1975 .storage = 4 1982 .storage = 4,
1983 .genesis_only = genesis_only
1976 }; 1984 };
1977 tern_foreach(systems, model_iter, &state); 1985 tern_foreach(systems, model_iter, &state);
1978 *num_out = state.num_models; 1986 *num_out = state.num_models;
1979 return (models){ 1987 return (models){
1980 .models = state.models, 1988 .models = state.models,
2002 const uint32_t num_regions = sizeof(regions)/sizeof(*regions); 2010 const uint32_t num_regions = sizeof(regions)/sizeof(*regions);
2003 static int32_t selected_region = -1; 2011 static int32_t selected_region = -1;
2004 if (selected_region < 0) { 2012 if (selected_region < 0) {
2005 selected_region = find_match(region_codes, num_regions, "system\0default_region\0", "U"); 2013 selected_region = find_match(region_codes, num_regions, "system\0default_region\0", "U");
2006 } 2014 }
2007 static const char **model_opts; 2015 static const char **model_opts, **sms_model_opts;
2008 static const char **model_names; 2016 static const char **model_names, **sms_model_names;
2009 static uint32_t num_models; 2017 static uint32_t num_models, num_sms_models;
2010 if (!model_opts) { 2018 if (!model_opts) {
2011 models m = get_models(&num_models); 2019 models m = get_models(&num_models, 1);
2012 model_opts = m.models; 2020 model_opts = m.models;
2013 model_names = m.names; 2021 model_names = m.names;
2014 } 2022 m = get_models(&num_sms_models, 0);
2023 sms_model_opts = m.models;
2024 sms_model_names = m.names;
2025 }
2026 static uint8_t old_show_sms;
2027 uint8_t show_sms = current_system && current_system->type == SYSTEM_SMS;
2028
2015 static int32_t selected_model = -1; 2029 static int32_t selected_model = -1;
2016 if (selected_model < 0) { 2030 if (selected_model < 0 || show_sms != old_show_sms) {
2017 selected_model = find_match(model_opts, num_models, "system\0model\0", "md1va3"); 2031 if (show_sms) {
2018 } 2032 selected_model = find_match(sms_model_opts, num_sms_models, "sms\0system\0model\0", "md1va3");
2019 2033 } else {
2034 selected_model = find_match(model_opts, num_models, "system\0model\0", "md1va3");
2035 }
2036 }
2037
2020 const char *formats[] = { 2038 const char *formats[] = {
2021 "native", 2039 "native",
2022 "gst" 2040 "gst"
2023 }; 2041 };
2024 const uint32_t num_formats = sizeof(formats)/sizeof(*formats); 2042 const uint32_t num_formats = sizeof(formats)/sizeof(*formats);
2054 "xband keyboard" 2072 "xband keyboard"
2055 }; 2073 };
2056 static int32_t selected_io_1 = -1; 2074 static int32_t selected_io_1 = -1;
2057 static int32_t selected_io_2 = -1; 2075 static int32_t selected_io_2 = -1;
2058 const uint32_t num_io = sizeof(io_opts_1)/sizeof(*io_opts_1); 2076 const uint32_t num_io = sizeof(io_opts_1)/sizeof(*io_opts_1);
2059 if (selected_io_1 < 0 || selected_io_2 < 0) { 2077 if (selected_io_1 < 0 || selected_io_2 < 0 || show_sms != old_show_sms) {
2060 selected_io_1 = find_match(io_opts_1, num_io, "io\0devices\0""1\0", "gamepad6.1"); 2078 if (show_sms) {
2061 selected_io_2 = find_match(io_opts_2, num_io, "io\0devices\0""2\0", "gamepad6.2"); 2079 selected_io_1 = find_match(io_opts_1, num_io, "sms\0io\0devices\0""1\0", "gamepad2.1");
2062 } 2080 selected_io_2 = find_match(io_opts_2, num_io, "sms\0io\0devices\0""2\0", "gamepad2.2");
2063 2081 } else {
2082 selected_io_1 = find_match(io_opts_1, num_io, "io\0devices\0""1\0", "gamepad6.1");
2083 selected_io_2 = find_match(io_opts_2, num_io, "io\0devices\0""2\0", "gamepad6.2");
2084 }
2085 }
2086 old_show_sms = show_sms;
2087
2064 uint32_t width = render_width(); 2088 uint32_t width = render_width();
2065 uint32_t height = render_height(); 2089 uint32_t height = render_height();
2066 uint32_t desired_width = context->style.font->height * 10; 2090 uint32_t desired_width = context->style.font->height * 10;
2067 if (nk_begin(context, "System Settings", nk_rect(0, 0, width, height), 0)) { 2091 if (nk_begin(context, "System Settings", nk_rect(0, 0, width, height), 0)) {
2068 nk_layout_row_static(context, context->style.font->height, desired_width, 2); 2092 nk_layout_row_static(context, context->style.font->height, desired_width, 2);
2069 2093
2070 selected_model = settings_dropdown_ex(context, "Model", model_opts, model_names, num_models, selected_model, "system\0model\0"); 2094 if (show_sms) {
2071 selected_io_1 = settings_dropdown_ex(context, "IO Port 1 Device", io_opts_1, device_type_names, num_io, selected_io_1, "io\0devices\0""1\0"); 2095 selected_model = settings_dropdown_ex(context, "Model", sms_model_opts, sms_model_names, num_sms_models, selected_model, "sms\0system\0model\0");
2072 selected_io_2 = settings_dropdown_ex(context, "IO Port 2 Device", io_opts_2, device_type_names, num_io, selected_io_2, "io\0devices\0""2\0"); 2096 } else {
2097 selected_model = settings_dropdown_ex(context, "Model", model_opts, model_names, num_models, selected_model, "system\0model\0");
2098 }
2099 selected_io_1 = settings_dropdown_ex(context, "IO Port 1 Device", io_opts_1, device_type_names, num_io, selected_io_1, show_sms ? "sms\0io\0devices\0""1\0" : "io\0devices\0""1\0");
2100 selected_io_2 = settings_dropdown_ex(context, "IO Port 2 Device", io_opts_2, device_type_names, num_io, selected_io_2, show_sms ? "sms\0io\0devices\0""2\0" : "io\0devices\0""2\0");
2073 selected_region = settings_dropdown_ex(context, "Default Region", region_codes, regions, num_regions, selected_region, "system\0default_region\0"); 2101 selected_region = settings_dropdown_ex(context, "Default Region", region_codes, regions, num_regions, selected_region, "system\0default_region\0");
2074 selected_sync = settings_dropdown(context, "Sync Source", sync_opts, num_sync_opts, selected_sync, "system\0sync_source\0"); 2102 selected_sync = settings_dropdown(context, "Sync Source", sync_opts, num_sync_opts, selected_sync, "system\0sync_source\0");
2075 settings_int_property(context, "68000 Clock Divider", "", "clocks\0m68k_divider\0", 7, 1, 53); 2103 if (!show_sms) {
2076 selected_format = settings_dropdown(context, "Save State Format", formats, num_formats, selected_format, "ui\0state_format\0"); 2104 settings_int_property(context, "68000 Clock Divider", "", "clocks\0m68k_divider\0", 7, 1, 53);
2105 selected_format = settings_dropdown(context, "Save State Format", formats, num_formats, selected_format, "ui\0state_format\0");
2106 }
2077 selected_init = settings_dropdown(context, "Initial RAM Value", ram_inits, num_inits, selected_init, "system\0ram_init\0"); 2107 selected_init = settings_dropdown(context, "Initial RAM Value", ram_inits, num_inits, selected_init, "system\0ram_init\0");
2078 settings_toggle(context, "Remember ROM Path", "ui\0remember_path\0", 1); 2108 settings_toggle(context, "Remember ROM Path", "ui\0remember_path\0", 1);
2079 settings_toggle(context, "Save config with EXE", "ui\0config_in_exe_dir\0", 0); 2109 settings_toggle(context, "Save config with EXE", "ui\0config_in_exe_dir\0", 0);
2080 settings_string(context, "Game Save Path", "ui\0save_path\0", "$USERDATA/blastem/$ROMNAME"); 2110 settings_string(context, "Game Save Path", "ui\0save_path\0", "$USERDATA/blastem/$ROMNAME");
2081 2111
2082 if (nk_button_label(context, "Back")) { 2112 if (nk_button_label(context, "Back")) {
2083 pop_view(); 2113 pop_view();
2084 } 2114 }
2085 nk_end(context); 2115 nk_end(context);
2086 } 2116 }
2143 {"System", view_system_settings}, 2173 {"System", view_system_settings},
2144 {"Firmware", view_bios_settings}, 2174 {"Firmware", view_bios_settings},
2145 {"Reset to Defaults", view_confirm_reset}, 2175 {"Reset to Defaults", view_confirm_reset},
2146 {"Back", view_back} 2176 {"Back", view_back}
2147 }; 2177 };
2148 2178
2149 if (nk_begin(context, "Settings Menu", nk_rect(0, 0, render_width(), render_height()), 0)) { 2179 if (nk_begin(context, "Settings Menu", nk_rect(0, 0, render_width(), render_height()), 0)) {
2150 menu(context, sizeof(items)/sizeof(*items), items, NULL); 2180 menu(context, sizeof(items)/sizeof(*items), items, NULL);
2151 nk_end(context); 2181 nk_end(context);
2152 } 2182 }
2153 } 2183 }
2166 {"Save State", view_save_state}, 2196 {"Save State", view_save_state},
2167 {"Load State", view_load_state}, 2197 {"Load State", view_load_state},
2168 {"Settings", view_settings}, 2198 {"Settings", view_settings},
2169 {"Exit", NULL} 2199 {"Exit", NULL}
2170 }; 2200 };
2171 2201
2172 if (nk_begin(context, "Main Menu", nk_rect(0, 0, render_width(), render_height()), 0)) { 2202 if (nk_begin(context, "Main Menu", nk_rect(0, 0, render_width(), render_height()), 0)) {
2173 menu(context, sizeof(items)/sizeof(*items), items, exit_handler); 2203 menu(context, sizeof(items)/sizeof(*items), items, exit_handler);
2174 nk_end(context); 2204 nk_end(context);
2175 } 2205 }
2176 } 2206 }
2181 {"Load ROM", view_load}, 2211 {"Load ROM", view_load},
2182 {"Settings", view_settings}, 2212 {"Settings", view_settings},
2183 {"About", view_about}, 2213 {"About", view_about},
2184 {"Exit", NULL} 2214 {"Exit", NULL}
2185 }; 2215 };
2186 2216
2187 if (nk_begin(context, "Main Menu", nk_rect(0, 0, render_width(), render_height()), 0)) { 2217 if (nk_begin(context, "Main Menu", nk_rect(0, 0, render_width(), render_height()), 0)) {
2188 menu(context, sizeof(items)/sizeof(*items), items, exit_handler); 2218 menu(context, sizeof(items)/sizeof(*items), items, exit_handler);
2189 nk_end(context); 2219 nk_end(context);
2190 } 2220 }
2191 } 2221 }
2454 render_set_ui_fb_resize_handler(fb_resize); 2484 render_set_ui_fb_resize_handler(fb_resize);
2455 #ifndef DISABLE_OPENGL 2485 #ifndef DISABLE_OPENGL
2456 } 2486 }
2457 #endif 2487 #endif
2458 style_init(); 2488 style_init();
2459 2489
2460 controller_360 = load_ui_image("images/360.png"); 2490 controller_360 = load_ui_image("images/360.png");
2461 controller_ps4 = load_ui_image("images/ps4.png"); 2491 controller_ps4 = load_ui_image("images/ps4.png");
2462 controller_ps4_6b = load_ui_image("images/ps4_6b.png"); 2492 controller_ps4_6b = load_ui_image("images/ps4_6b.png");
2463 controller_wiiu = load_ui_image("images/wiiu.png"); 2493 controller_wiiu = load_ui_image("images/wiiu.png");
2464 controller_gen_6b = load_ui_image("images/genesis_6b.png"); 2494 controller_gen_6b = load_ui_image("images/genesis_6b.png");
2465 2495
2466 texture_init(); 2496 texture_init();
2467 2497
2468 if (file_loaded) { 2498 if (file_loaded) {
2469 current_view = view_play; 2499 current_view = view_play;
2470 } else { 2500 } else {
2471 current_view = view_menu; 2501 current_view = view_menu;
2472 set_content_binding_state(0); 2502 set_content_binding_state(0);
2473 } 2503 }
2474 render_set_ui_render_fun(blastem_nuklear_render); 2504 render_set_ui_render_fun(blastem_nuklear_render);
2475 render_set_event_handler(handle_event); 2505 render_set_event_handler(handle_event);
2476 render_set_gl_context_handlers(context_destroyed, context_created); 2506 render_set_gl_context_handlers(context_destroyed, context_created);
2477 2507
2478 atexit(persist_config_exit); 2508 atexit(persist_config_exit);
2479 2509
2480 active = 1; 2510 active = 1;
2481 ui_idle_loop(); 2511 ui_idle_loop();
2482 } 2512 }