/* fix-me: incomplete, lacks error checking */ int action_right_input_desc(unsigned type, const char *label, bool wraparound) { rarch_system_info_t *system = runloop_get_system_info(); settings_t *settings = config_get_ptr(); unsigned btn_idx, user_idx, remap_idx; if (!settings || !system) return 0; user_idx = (type - MENU_SETTINGS_INPUT_DESC_BEGIN) / (RARCH_FIRST_CUSTOM_BIND + 8); btn_idx = (type - MENU_SETTINGS_INPUT_DESC_BEGIN) - (RARCH_FIRST_CUSTOM_BIND + 8) * user_idx; if (settings->uints.input_remap_ids[user_idx][btn_idx] < RARCH_CUSTOM_BIND_LIST_END - 1) settings->uints.input_remap_ids[user_idx][btn_idx]++; else if (settings->uints.input_remap_ids[user_idx][btn_idx] == RARCH_CUSTOM_BIND_LIST_END - 1) settings->uints.input_remap_ids[user_idx][btn_idx] = RARCH_UNMAPPED; else settings->uints.input_remap_ids[user_idx][btn_idx] = 0; remap_idx = settings->uints.input_remap_ids[user_idx][btn_idx]; /* skip the not used buttons (unless they are at the end by calling the right desc function recursively also skip all the axes until analog remapping is implemented */ if (remap_idx != RARCH_UNMAPPED) { if ((string_is_empty(system->input_desc_btn[user_idx][remap_idx]) && remap_idx < RARCH_CUSTOM_BIND_LIST_END)) action_right_input_desc(type, label, wraparound); } return 0; }
/* Sets 's' to the name of the current core * (shown at the top of the UI). */ int menu_entries_get_core_title(char *s, size_t len) { const char *core_name = NULL; const char *core_version = NULL; rarch_system_info_t *info = runloop_get_system_info(); struct retro_system_info *system = &info->info; if (system) { core_name = system->library_name; core_version = system->library_version; } if (string_is_empty(core_name) && info) core_name = info->info.library_name; if (string_is_empty(core_name)) core_name = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_CORE); if (!core_version && info) core_version = info->info.library_version; if (!core_version) core_version = ""; snprintf(s, len, "%s - %s %s", PACKAGE_VERSION, core_name, core_version); return 0; }
static void netplay_announce(void) { char buf [2048]; char url [2048] = "http://newlobby.libretro.com/add/"; char *username = NULL; char *corename = NULL; char *gamename = NULL; char *coreversion = NULL; char *frontend_ident = NULL; settings_t *settings = config_get_ptr(); rarch_system_info_t *system = runloop_get_system_info(); uint32_t content_crc = content_get_crc(); char frontend_architecture[PATH_MAX_LENGTH]; netplay_get_architecture(frontend_architecture, sizeof(frontend_architecture)); net_http_urlencode(&username, settings->paths.username); net_http_urlencode(&corename, system->info.library_name); net_http_urlencode(&gamename, !string_is_empty(path_basename(path_get(RARCH_PATH_BASENAME))) ? path_basename(path_get(RARCH_PATH_BASENAME)) : "N/A"); net_http_urlencode(&coreversion, system->info.library_version); net_http_urlencode(&frontend_ident, frontend_architecture); buf[0] = '\0'; snprintf(buf, sizeof(buf), "username=%s&core_name=%s&core_version=%s&" "game_name=%s&game_crc=%08X&port=%d&mitm_server=%s" "&has_password=%d&has_spectate_password=%d&force_mitm=%d&retroarch_version=%s&frontend=%s", username, corename, coreversion, gamename, content_crc, settings->uints.netplay_port, settings->arrays.netplay_mitm_server, *settings->paths.netplay_password ? 1 : 0, *settings->paths.netplay_spectate_password ? 1 : 0, settings->bools.netplay_use_mitm_server, PACKAGE_VERSION, frontend_architecture); #if 0 RARCH_LOG("[netplay] announcement URL: %s\n", buf); #endif task_push_http_post_transfer(url, buf, true, NULL, netplay_announce_cb, NULL); if (username) free(username); if (corename) free(corename); if (gamename) free(gamename); if (coreversion) free(coreversion); if (frontend_ident) free(frontend_ident); }
/* Sets 's' to the name of the current core * (shown at the top of the UI). */ int menu_entries_get_core_title(char *s, size_t len) { const char *core_name = NULL; const char *core_version = NULL; rarch_system_info_t *info = runloop_get_system_info(); struct retro_system_info *system = &info->info; #if _MSC_VER == 1200 const char *extra_version = " msvc6"; #elif _MSC_VER == 1300 const char *extra_version = " msvc2002"; #elif _MSC_VER == 1310 const char *extra_version = " msvc2003"; #elif _MSC_VER == 1400 const char *extra_version = " msvc2005"; #elif _MSC_VER == 1500 const char *extra_version = " msvc2008"; #elif _MSC_VER == 1600 const char *extra_version = " msvc2010"; #elif _MSC_VER == 1700 const char *extra_version = " msvc2012"; #elif _MSC_VER == 1800 const char *extra_version = " msvc2013"; #elif _MSC_VER == 1900 const char *extra_version = " msvc2015"; #elif _MSC_VER >= 1910 && _MSC_VER < 2000 const char *extra_version = " msvc2017"; #else const char *extra_version = ""; #endif if (system) { core_name = system->library_name; core_version = system->library_version; } if (string_is_empty(core_name) && info) core_name = info->info.library_name; if (string_is_empty(core_name)) core_name = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_CORE); if (!core_version && info) core_version = info->info.library_version; if (!core_version) core_version = ""; snprintf(s, len, "%s%s - %s %s", PACKAGE_VERSION, extra_version, core_name, core_version); return 0; }
static int httpserver_handle_get_mmaps(struct mg_connection* conn, void* cbdata) { unsigned id; const struct mg_request_info* req = mg_get_request_info(conn); const char* comma = ""; const struct retro_memory_map* mmaps = NULL; const struct retro_memory_descriptor* mmap = NULL; rarch_system_info_t *system = runloop_get_system_info(); if (strcmp(req->request_method, "GET")) return httpserver_error(conn, 405, "Unimplemented method in %s: %s", __FUNCTION__, req->request_method); mmaps = &system->mmaps; mmap = mmaps->descriptors; mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n"); mg_printf(conn, "["); for (id = 0; id < mmaps->num_descriptors; id++, mmap++) { mg_printf(conn, "%s{" "\"id\":%u," "\"flags\":" STRING_REP_UINT64 "," "\"ptr\":\"%" PRIXPTR "\"," "\"offset\":" STRING_REP_UINT64 "," "\"start\":" STRING_REP_UINT64 "," "\"select\":" STRING_REP_UINT64 "," "\"disconnect\":" STRING_REP_UINT64 "," "\"len\":" STRING_REP_UINT64 "," "\"addrspace\":\"%s\"" "}", comma, id, mmap->flags, (uintptr_t)mmap->ptr, mmap->offset, mmap->start, mmap->select, mmap->disconnect, mmap->len, mmap->addrspace ? mmap->addrspace : "" ); comma = ","; } mg_printf(conn, "]"); return 1; }
static void menu_action_setting_disp_set_label_input_desc( file_list_t* list, unsigned *w, unsigned type, unsigned i, const char *label, char *s, size_t len, const char *entry_label, const char *path, char *s2, size_t len2) { rarch_system_info_t *system = runloop_get_system_info(); settings_t *settings = config_get_ptr(); const char* descriptor = NULL; char buf[256]; unsigned btn_idx, user_idx, remap_idx; if (!settings) return; user_idx = (type - MENU_SETTINGS_INPUT_DESC_BEGIN) / (RARCH_FIRST_CUSTOM_BIND + 8); btn_idx = (type - MENU_SETTINGS_INPUT_DESC_BEGIN) - (RARCH_FIRST_CUSTOM_BIND + 8) * user_idx; remap_idx = settings->uints.input_remap_ids[user_idx][btn_idx]; if (!system) return; if (remap_idx != RARCH_UNMAPPED) descriptor = system->input_desc_btn[user_idx][remap_idx]; if (!string_is_empty(descriptor) && remap_idx < RARCH_FIRST_CUSTOM_BIND) strlcpy(s, descriptor, len); else if (!string_is_empty(descriptor) && remap_idx >= RARCH_FIRST_CUSTOM_BIND && remap_idx % 2 == 0) { snprintf(buf, sizeof(buf), "%s %c", descriptor, '+'); strlcpy(s, buf, len); } else if (!string_is_empty(descriptor) && remap_idx >= RARCH_FIRST_CUSTOM_BIND && remap_idx % 2 != 0) { snprintf(buf, sizeof(buf), "%s %c", descriptor, '-'); strlcpy(s, buf, len); } else strlcpy(s, "---", len); *w = 19; strlcpy(s2, path, len2); }
int menu_entries_get_core_name(char *s, size_t len) { rarch_system_info_t *info = runloop_get_system_info(); struct retro_system_info *system = &info->info; const char *core_name = NULL; if (system) core_name = system->library_name; if (string_is_empty(core_name) && info) core_name = info->info.library_name; if (string_is_empty(core_name)) core_name = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_CORE); snprintf(s, len, "%s", core_name); return 0; }
static void menu_action_setting_disp_set_label_menu_disk_index( file_list_t* list, unsigned *w, unsigned type, unsigned i, const char *label, char *s, size_t len, const char *entry_label, const char *path, char *s2, size_t len2) { unsigned images = 0, current = 0; struct retro_disk_control_callback *control = NULL; rarch_system_info_t *system = runloop_get_system_info(); if (!system) return; control = &system->disk_control_cb; if (!control) return; *w = 19; *s = '\0'; strlcpy(s2, path, len2); if (!control->get_num_images) return; if (!control->get_image_index) return; images = control->get_num_images(); current = control->get_image_index(); if (current >= images) strlcpy(s, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_DISK), len); else snprintf(s, len, "%u", current + 1); }
/** * netplay_lan_ad_server * * Respond to any LAN ad queries that the netplay server has received. */ bool netplay_lan_ad_server(netplay_t *netplay) { fd_set fds; struct timeval tmp_tv = {0}; struct sockaddr their_addr; socklen_t addr_size; rarch_system_info_t *info = NULL; if (lan_ad_server_fd < 0 && !init_lan_ad_server_socket(netplay, RARCH_DEFAULT_PORT)) return false; /* Check for any ad queries */ while (1) { FD_ZERO(&fds); FD_SET(lan_ad_server_fd, &fds); if (socket_select(lan_ad_server_fd + 1, &fds, NULL, NULL, &tmp_tv) <= 0) break; if (!FD_ISSET(lan_ad_server_fd, &fds)) break; /* Somebody queried, so check that it's valid */ addr_size = sizeof(their_addr); if (recvfrom(lan_ad_server_fd, (char*)&ad_packet_buffer, sizeof(struct ad_packet), 0, &their_addr, &addr_size) >= (ssize_t) (2*sizeof(uint32_t))) { char s[NETPLAY_HOST_STR_LEN]; uint32_t content_crc = 0; /* Make sure it's a valid query */ if (memcmp((void *) &ad_packet_buffer, "RANQ", 4)) continue; /* For this version */ if (ntohl(ad_packet_buffer.protocol_version) != NETPLAY_PROTOCOL_VERSION) continue; info = runloop_get_system_info(); /* Now build our response */ content_crc = content_get_crc(); memset(&ad_packet_buffer, 0, sizeof(struct ad_packet)); memcpy(&ad_packet_buffer, "RANS", 4); ad_packet_buffer.protocol_version = htonl(NETPLAY_PROTOCOL_VERSION); ad_packet_buffer.port = htonl(netplay->tcp_port); strlcpy(ad_packet_buffer.retroarch_version, PACKAGE_VERSION, NETPLAY_HOST_STR_LEN); strlcpy(ad_packet_buffer.content, !string_is_empty( path_basename(path_get(RARCH_PATH_BASENAME))) ? path_basename(path_get(RARCH_PATH_BASENAME)) : "N/A", NETPLAY_HOST_LONGSTR_LEN); strlcpy(ad_packet_buffer.nick, netplay->nick, NETPLAY_HOST_STR_LEN); if (info) { strlcpy(ad_packet_buffer.core, info->info.library_name, NETPLAY_HOST_STR_LEN); strlcpy(ad_packet_buffer.core_version, info->info.library_version, NETPLAY_HOST_STR_LEN); } snprintf(s, sizeof(s), "%d", content_crc); strlcpy(ad_packet_buffer.content_crc, s, NETPLAY_HOST_STR_LEN); /* And send it */ sendto(lan_ad_server_fd, (const char*)&ad_packet_buffer, sizeof(struct ad_packet), 0, &their_addr, addr_size); } } return true; }
static int httpserver_handle_get_mmap(struct mg_connection* conn, void* cbdata) { size_t start, length; unsigned id; uLong buflen; const struct mg_request_info * req = mg_get_request_info(conn); const char * comma = ""; const struct retro_memory_map* mmaps = NULL; const struct retro_memory_descriptor* mmap = NULL; const char* param = NULL; Bytef* buffer = NULL; rarch_system_info_t *system = runloop_get_system_info(); if (strcmp(req->request_method, "GET")) return httpserver_error(conn, 405, "Unimplemented method in %s: %s", __FUNCTION__, req->request_method); if (sscanf(req->request_uri, "/" MEMORY_MAP "/%u", &id) != 1) return httpserver_error(conn, 500, "Malformed request in %s: %s", __FUNCTION__, req->request_uri); mmaps = &system->mmaps; if (id >= mmaps->num_descriptors) return httpserver_error(conn, 404, "Invalid memory map id in %s: %u", __FUNCTION__, id); mmap = mmaps->descriptors + id; start = 0; length = mmap->len; if (req->query_string != NULL) { param = strstr(req->query_string, "start="); if (param != NULL) start = atoll(param + 6); param = strstr(req->query_string, "length="); if (param != NULL) length = atoll(param + 7); } if (start >= mmap->len) start = mmap->len - 1; if (length > mmap->len - start) length = mmap->len - start; buflen = compressBound(length); buffer = (Bytef*)malloc(((buflen + 3) / 4) * 5); if (buffer == NULL) return httpserver_error(conn, 500, "Out of memory in %s", __FUNCTION__); if (compress2(buffer, &buflen, (Bytef*)mmap->ptr + start, length, Z_BEST_COMPRESSION) != Z_OK) { free((void*)buffer); return httpserver_error(conn, 500, "Error during compression in %s", __FUNCTION__); } buffer[buflen] = 0; buffer[buflen + 1] = 0; buffer[buflen + 2] = 0; httpserver_z85_encode_inplace(buffer, (buflen + 3) & ~3); mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n"); mg_printf(conn, "{" "\"start\":" STRING_REP_ULONG "," "\"length\":" STRING_REP_ULONG "," "\"compression\":\"deflate\"," "\"compressedLength\":" STRING_REP_ULONG "," "\"encoding\":\"Z85\"," "\"data\":\"%s\"" "}", start, length, (size_t)buflen, (char*)buffer ); free((void*)buffer); return 1; }
static int httpserver_handle_basic_info(struct mg_connection* conn, void* cbdata) { static const char *libretro_btn_desc[] = { "B (bottom)", "Y (left)", "Select", "Start", "D-Pad Up", "D-Pad Down", "D-Pad Left", "D-Pad Right", "A (right)", "X (up)", "L", "R", "L2", "R2", "L3", "R3", }; unsigned p, q, r; retro_ctx_api_info_t api; retro_ctx_region_info_t region; retro_ctx_memory_info_t sram; retro_ctx_memory_info_t rtc; retro_ctx_memory_info_t sysram; retro_ctx_memory_info_t vram; char core_path[PATH_MAX_LENGTH] = {0}; const char* pixel_format = NULL; const struct retro_subsystem_info* subsys = NULL; const struct retro_subsystem_rom_info* rom = NULL; const struct retro_subsystem_memory_info* mem = NULL; const struct retro_controller_description* ctrl = NULL; const char* comma = NULL; const struct core_option* opts = NULL; const struct retro_system_av_info* av_info = NULL; const core_option_manager_t* core_opts = NULL; const struct mg_request_info * req = mg_get_request_info(conn); const settings_t * settings = config_get_ptr(); rarch_system_info_t *system = runloop_get_system_info(); if (string_is_empty(system->info.library_name)) return httpserver_error(conn, 500, "Core not initialized in %s", __FUNCTION__); if (!core_is_game_loaded()) return httpserver_error(conn, 500, "Game not loaded in %s", __FUNCTION__); json_string_encode(core_path, sizeof(core_path), config_get_active_core_path()); core_api_version(&api); core_get_region(®ion); switch (video_driver_get_pixel_format()) { case RETRO_PIXEL_FORMAT_0RGB1555: pixel_format = "RETRO_PIXEL_FORMAT_0RGB1555"; break; case RETRO_PIXEL_FORMAT_XRGB8888: pixel_format = "RETRO_PIXEL_FORMAT_XRGB8888"; break; case RETRO_PIXEL_FORMAT_RGB565: pixel_format = "RETRO_PIXEL_FORMAT_RGB565"; break; default: pixel_format = "?"; break; } sram.id = RETRO_MEMORY_SAVE_RAM; core_get_memory(&sram); rtc.id = RETRO_MEMORY_RTC; core_get_memory(&rtc); sysram.id = RETRO_MEMORY_SYSTEM_RAM; core_get_memory(&sysram); vram.id = RETRO_MEMORY_VIDEO_RAM; core_get_memory(&vram); mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n" "{" "\"corePath\":\"%s\"," "\"apiVersion\":%u," "\"systemInfo\":" "{" "\"libraryName\":\"%s\"," "\"libraryVersion\":\"%s\"," "\"validExtensions\":\"%s\"," "\"needsFullpath\":%s," "\"blockExtract\":%s" "}," "\"region\":\"%s\"," "\"pixelFormat\":\"%s\"," "\"rotation\":%u," "\"performaceLevel\":%u," "\"supportsNoGame\":%s," #ifdef HAVE_CHEEVOS "\"frontendSupportsAchievements\":true," "\"coreSupportsAchievements\":%s," #else "\"frontendSupportsAchievements\":false," "\"coreSupportsAchievements\":null," #endif "\"saveRam\":{\"pointer\":\"%" PRIXPTR "\",\"size\":" STRING_REP_UINT64 "}," "\"rtcRam\":{\"pointer\":\"%" PRIXPTR "\",\"size\":" STRING_REP_UINT64 "}," "\"systemRam\":{\"pointer\":\"%" PRIXPTR "\",\"size\":" STRING_REP_UINT64 "}," "\"videoRam\":{\"pointer\":\"%" PRIXPTR "\",\"size\":" STRING_REP_UINT64 "},", core_path, api.version, system->info.library_name, system->info.library_version, system->info.valid_extensions, system->info.need_fullpath ? "true" : "false", system->info.block_extract ? "true" : "false", region.region ? "RETRO_REGION_PAL" : "RETRO_REGION_NTSC", pixel_format, system->rotation, system->performance_level, content_does_not_need_content() ? "true" : "false", #ifdef HAVE_CHEEVOS cheevos_get_support_cheevos() ? "true" : "false", #endif (uintptr_t)sram.data, sram.size, (uintptr_t)rtc.data, rtc.size, (uintptr_t)sysram.data, sysram.size, (uintptr_t)vram.data, vram.size ); mg_printf(conn, "\"subSystems\":["); subsys = system->subsystem.data; for (p = 0; p < system->subsystem.size; p++, subsys++) { mg_printf(conn, "%s{\"id\":%u,\"description\":\"%s\",\"identifier\":\"%s\",\"roms\":[", p == 0 ? "" : ",", subsys->id, subsys->desc, subsys->ident); rom = subsys->roms; for (q = 0; q < subsys->num_roms; q++, rom++) { mg_printf(conn, "%s{" "\"description\":\"%s\"," "\"extensions\":\"%s\"," "\"needsFullpath\":%s," "\"blockExtract\":%s," "\"required\":%s," "\"memory\":[", q == 0 ? "" : ",", rom->desc, rom->valid_extensions, rom->need_fullpath ? "true" : "false", rom->block_extract ? "true" : "false", rom->required ? "true" : "false" ); mem = rom->memory; comma = ""; for (r = 0; r < rom->num_memory; r++, mem++) { mg_printf(conn, "%s{\"extension\":\"%s\",\"type\":%u}", comma, mem->extension, mem->type); comma = ","; } mg_printf(conn, "]}"); } mg_printf(conn, "]}"); } av_info = video_viewport_get_system_av_info(); mg_printf(conn, "],\"avInfo\":{" "\"geometry\":{" "\"baseWidth\":%u," "\"baseHeight\":%u," "\"maxWidth\":%u," "\"maxHeight\":%u," "\"aspectRatio\":%f" "}," "\"timing\":{" "\"fps\":%f," "\"sampleRate\":%f" "}" "},", av_info->geometry.base_width, av_info->geometry.base_height, av_info->geometry.max_width, av_info->geometry.max_height, av_info->geometry.aspect_ratio, av_info->timing.fps, av_info->timing.sample_rate ); mg_printf(conn, "\"ports\":["); comma = ""; for (p = 0; p < system->ports.size; p++) { ctrl = system->ports.data[p].types; for (q = 0; q < system->ports.data[p].num_types; q++, ctrl++) { mg_printf(conn, "%s{\"id\":%u,\"description\":\"%s\"}", comma, ctrl->id, ctrl->desc); comma = ","; } } mg_printf(conn, "],\"inputDescriptors\":["); comma = ""; if (core_has_set_input_descriptor()) { for (p = 0; p < settings->input.max_users; p++) { for (q = 0; q < RARCH_FIRST_CUSTOM_BIND; q++) { const char* description = system->input_desc_btn[p][q]; if (description) { mg_printf(conn, "%s{\"player\":%u,\"button\":\"%s\",\"description\":\"%s\"}", comma, p + 1, libretro_btn_desc[q], description ); comma = ","; } } } } mg_printf(conn, "],\"coreOptions\":["); rarch_ctl(RARCH_CTL_CORE_OPTIONS_LIST_GET, (void*)&core_opts); opts = core_opts->opts; for (p = 0; p < core_opts->size; p++, opts++) { mg_printf(conn, "%s{\"key\":\"%s\",\"description\":\"%s\",\"values\":[", p == 0 ? "" : ",", opts->key, opts->desc); comma = ""; for (q = 0; q < opts->vals->size; q++) { mg_printf(conn, "%s\"%s\"", comma, opts->vals->elems[q].data); comma = ","; } mg_printf(conn, "]}"); } mg_printf(conn, "]}"); return 1; }
int setting_action_left_libretro_device_type( void *data, bool wraparound) { retro_ctx_controller_info_t pad; unsigned current_device, current_idx, i, devices[128], types = 0, port = 0; const struct retro_controller_info *desc = NULL; rarch_setting_t *setting = (rarch_setting_t*)data; rarch_system_info_t *system = NULL; if (!setting) return -1; port = setting->index_offset; devices[types++] = RETRO_DEVICE_NONE; devices[types++] = RETRO_DEVICE_JOYPAD; system = runloop_get_system_info(); if (system) { /* Only push RETRO_DEVICE_ANALOG as default if we use an * older core which doesn't use SET_CONTROLLER_INFO. */ if (!system->ports.size) devices[types++] = RETRO_DEVICE_ANALOG; if (port < system->ports.size) desc = &system->ports.data[port]; } if (desc) { for (i = 0; i < desc->num_types; i++) { unsigned id = desc->types[i].id; if (types < ARRAY_SIZE(devices) && id != RETRO_DEVICE_NONE && id != RETRO_DEVICE_JOYPAD) devices[types++] = id; } } current_device = input_config_get_device(port); current_idx = 0; for (i = 0; i < types; i++) { if (current_device != devices[i]) continue; current_idx = i; break; } current_device = devices [(current_idx + types - 1) % types]; input_config_set_device(port, current_device); pad.port = port; pad.device = current_device; core_set_controller_port_device(&pad); return 0; }