Exemple #1
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;
}
Exemple #2
0
static int httpserver_handle_get_mmaps(struct mg_connection* conn, void* cbdata)
{
  const struct mg_request_info* req = mg_get_request_info(conn);
  const char* comma = "";
  rarch_system_info_t* system;
  const struct retro_memory_map* mmaps;
  const struct retro_memory_descriptor* mmap;
  unsigned id;

  if (strcmp(req->request_method, "GET"))
  {
    return httpserver_error(conn, 405, "Unimplemented method in %s: %s", __FUNCTION__, req->request_method);
  }

  if (!runloop_ctl(RUNLOOP_CTL_SYSTEM_INFO_GET, &system))
  {
    return httpserver_error(conn, 500, "Could not get system information in %s", __FUNCTION__);
  }

  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++, comma = ",")
  {
    mg_printf(conn, "%s", comma);

    mg_printf(conn,
      "{"
      "\"id\":%u,"
      "\"flags\":" STRING_REP_UINT64 ","
      "\"ptr\":\"%p\","
      "\"offset\":" STRING_REP_UINT64 ","
      "\"start\":" STRING_REP_UINT64 ","
      "\"select\":" STRING_REP_UINT64 ","
      "\"disconnect\":" STRING_REP_UINT64 ","
      "\"len\":" STRING_REP_UINT64 ","
      "\"addrspace\":",
      id,
      mmap->flags,
      mmap->ptr,
      mmap->offset,
      mmap->start,
      mmap->select,
      mmap->disconnect,
      mmap->len
      );

    if (mmap->addrspace)
    {
      mg_printf(conn, "\"%s\"", mmap->addrspace);
    }
    else
    {
      mg_printf(conn, "null");
    }

    mg_printf(conn, "}");
  }

  mg_printf(conn, "]");
  return 1;
}
Exemple #3
0
static int httpserver_handle_get_mmap(struct mg_connection* conn, void* cbdata)
{
  static const char* hexdigits = "0123456789ABCDEF";

  const struct mg_request_info* req = mg_get_request_info(conn);
  const char* comma = "";
  rarch_system_info_t* system;
  const struct retro_memory_map* mmaps;
  const struct retro_memory_descriptor* mmap;
  unsigned id;
  uLong buflen;
  Bytef* buffer;

  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, "/mmaps/%u", &id) != 1)
  {
    return httpserver_error(conn, 500, "Malformed request in %s: %s", __FUNCTION__, req->request_uri);
  }

  if (!runloop_ctl(RUNLOOP_CTL_SYSTEM_INFO_GET, &system))
  {
    return httpserver_error(conn, 500, "Could not get system information in %s", __FUNCTION__);
  }

  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;
  buflen = compressBound(mmap->len);
  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, mmap->len, 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,
    "{"
    "\"length\":" STRING_REP_UINT64 ","
    "\"compressedLength\":" STRING_REP_ULONG ","
    "\"bytesZ85\":\"%s\""
    "}",
    mmap->len,
    (size_t)buflen,
    (char*)buffer
  );

  free((void*)buffer);
  return 1;
}
Exemple #4
0
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;
}
Exemple #5
0
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(&region);

   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;
}