[retro-gtk/wip/aplazas/0.13: 23/26] Port CoreDescriptor to C



commit 20f441f35ae5773c7c9acbb6aeb928d60281cfed
Author: Adrien Plazas <kekun plazas laposte net>
Date:   Thu Sep 7 12:10:03 2017 +0200

    Port CoreDescriptor to C

 retro-gtk/Makefile.am                    |    3 +
 retro-gtk/retro-core-descriptor-extern.c | 1302 ++++++++++++++++++++++++++++++
 retro-gtk/retro-core-descriptor.h        |  191 +++++
 retro-gtk/retro-core-descriptor.vala     |   32 +-
 retro-gtk/vapi/retro-gtk-c.vapi          |   36 +
 5 files changed, 1538 insertions(+), 26 deletions(-)
---
diff --git a/retro-gtk/Makefile.am b/retro-gtk/Makefile.am
index 923d708..1f6a988 100644
--- a/retro-gtk/Makefile.am
+++ b/retro-gtk/Makefile.am
@@ -45,6 +45,7 @@ libretro_gtk_la_SOURCES = \
        retro-cairo-display.c \
        retro-core-descriptor.vala \
        retro-core-descriptor-error.vala \
+       retro-core-descriptor-extern.c \
        retro-core-view.c \
        retro-core-view-input-device.c \
        retro-game-info.c \
@@ -68,6 +69,8 @@ video/retro-video-converter.c: retro-gtk-internal.h
 
 retro-core.c: retro-gtk-internal.h
 
+retro-core-descriptor-extern.c: retro-gtk-internal.h
+
 retro-core-view.c: retro-gtk-internal.h
 
 retro-core-view-input-device.c: retro-gtk-internal.h
diff --git a/retro-gtk/retro-core-descriptor-extern.c b/retro-gtk/retro-core-descriptor-extern.c
new file mode 100644
index 0000000..67f80ed
--- /dev/null
+++ b/retro-gtk/retro-core-descriptor-extern.c
@@ -0,0 +1,1302 @@
+// This file is part of retro-gtk. License: GPL-3.0+.
+
+#include "retro-gtk-internal.h"
+
+
+#define RETRO_CORE_DESCRIPTOR_LIBRETRO_GROUP "Libretro"
+#define RETRO_CORE_DESCRIPTOR_PLATFORM_GROUP_PREFIX "Platform:"
+#define RETRO_CORE_DESCRIPTOR_FIRMWARE_GROUP_PREFIX "Firmware:"
+
+#define RETRO_CORE_DESCRIPTOR_TYPE_KEY "Type"
+#define RETRO_CORE_DESCRIPTOR_NAME_KEY "Name"
+#define RETRO_CORE_DESCRIPTOR_ICON_KEY "Icon"
+#define RETRO_CORE_DESCRIPTOR_MODULE_KEY "Module"
+#define RETRO_CORE_DESCRIPTOR_LIBRETRO_VERSION_KEY "LibretroVersion"
+
+#define RETRO_CORE_DESCRIPTOR_PLATFORM_MIME_TYPE_KEY "MimeType"
+#define RETRO_CORE_DESCRIPTOR_PLATFORM_FIRMWARES_KEY "Firmwares"
+
+#define RETRO_CORE_DESCRIPTOR_FIRMWARE_PATH_KEY "Path"
+#define RETRO_CORE_DESCRIPTOR_FIRMWARE_MD5_KEY "MD5"
+#define RETRO_CORE_DESCRIPTOR_FIRMWARE_SHA512_KEY "SHA-512"
+#define RETRO_CORE_DESCRIPTOR_FIRMWARE_MANDATORY_KEY "Mandatory"
+
+#define RETRO_CORE_DESCRIPTOR_TYPE_GAME "Game"
+#define RETRO_CORE_DESCRIPTOR_TYPE_EMULATOR "Emulator"
+
+/* #include <glib.h> */
+/* #include <glib-object.h> */
+/* #include <stdlib.h> */
+/* #include <string.h> */
+/* #include <gio/gio.h> */
+
+
+/* #define RETRO_TYPE_CORE_DESCRIPTOR (retro_core_descriptor_get_type ()) */
+/* #define RETRO_CORE_DESCRIPTOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), RETRO_TYPE_CORE_DESCRIPTOR, 
RetroCoreDescriptor)) */
+/* #define RETRO_CORE_DESCRIPTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), RETRO_TYPE_CORE_DESCRIPTOR, 
RetroCoreDescriptorClass)) */
+/* #define RETRO_IS_CORE_DESCRIPTOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), RETRO_TYPE_CORE_DESCRIPTOR)) */
+/* #define RETRO_IS_CORE_DESCRIPTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), 
RETRO_TYPE_CORE_DESCRIPTOR)) */
+/* #define RETRO_CORE_DESCRIPTOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), 
RETRO_TYPE_CORE_DESCRIPTOR, RetroCoreDescriptorClass)) */
+
+/* typedef struct _RetroCoreDescriptor RetroCoreDescriptor; */
+/* typedef struct _RetroCoreDescriptorClass RetroCoreDescriptorClass; */
+/* typedef struct _RetroCoreDescriptorPrivate RetroCoreDescriptorPrivate; */
+/* enum  { */
+/*   RETRO_CORE_DESCRIPTOR_DUMMY_PROPERTY, */
+/*   RETRO_CORE_DESCRIPTOR_LAST_PROPERTY */
+/* }; */
+/* static GParamSpec* retro_core_descriptor_properties[RETRO_CORE_DESCRIPTOR_LAST_PROPERTY]; */
+/* #define _g_free0(var) (var = (g_free (var), NULL)) */
+/* #define _g_key_file_unref0(var) ((var == NULL) ? NULL : (var = (g_key_file_unref (var), NULL))) */
+/* #define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL))) */
+
+/* #define RETRO_CORE_DESCRIPTOR_TYPE_PLATFORM (retro_core_descriptor_platform_get_type ()) */
+/* #define RETRO_CORE_DESCRIPTOR_PLATFORM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), 
RETRO_CORE_DESCRIPTOR_TYPE_PLATFORM, RetroCoreDescriptorPlatform)) */
+/* #define RETRO_CORE_DESCRIPTOR_PLATFORM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), 
RETRO_CORE_DESCRIPTOR_TYPE_PLATFORM, RetroCoreDescriptorPlatformClass)) */
+/* #define RETRO_CORE_DESCRIPTOR_IS_PLATFORM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), 
RETRO_CORE_DESCRIPTOR_TYPE_PLATFORM)) */
+/* #define RETRO_CORE_DESCRIPTOR_IS_PLATFORM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), 
RETRO_CORE_DESCRIPTOR_TYPE_PLATFORM)) */
+/* #define RETRO_CORE_DESCRIPTOR_PLATFORM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), 
RETRO_CORE_DESCRIPTOR_TYPE_PLATFORM, RetroCoreDescriptorPlatformClass)) */
+
+/* typedef struct _RetroCoreDescriptorPlatform RetroCoreDescriptorPlatform; */
+/* typedef struct _RetroCoreDescriptorPlatformClass RetroCoreDescriptorPlatformClass; */
+/* typedef struct _RetroCoreDescriptorPlatformPrivate RetroCoreDescriptorPlatformPrivate; */
+/* enum  { */
+/*   RETRO_CORE_DESCRIPTOR_PLATFORM_DUMMY_PROPERTY, */
+/*   RETRO_CORE_DESCRIPTOR_PLATFORM_LAST_PROPERTY */
+/* }; */
+/* static GParamSpec* 
retro_core_descriptor_platform_properties[RETRO_CORE_DESCRIPTOR_PLATFORM_LAST_PROPERTY]; */
+
+/* struct _RetroCoreDescriptor { */
+/*   GObject parent_instance; */
+/*   RetroCoreDescriptorPrivate * priv; */
+/* }; */
+
+/* struct _RetroCoreDescriptorClass { */
+/*   GObjectClass parent_class; */
+/* }; */
+
+/* struct _RetroCoreDescriptorPrivate { */
+/*   gchar* filename; */
+/*   GKeyFile* key_file; */
+/* }; */
+
+/* typedef enum  { */
+/*   RETRO_CORE_DESCRIPTOR_ERROR_REQUIRED_GROUP_NOT_FOUND, */
+/*   RETRO_CORE_DESCRIPTOR_ERROR_REQUIRED_KEY_NOT_FOUND, */
+/*   RETRO_CORE_DESCRIPTOR_ERROR_FIRMWARE_NOT_FOUND */
+/* } RetroCoreDescriptorError; */
+/* #define RETRO_CORE_DESCRIPTOR_ERROR retro_core_descriptor_error_quark () */
+/* struct _RetroCoreDescriptorPlatform { */
+/*   GObject parent_instance; */
+/*   RetroCoreDescriptorPlatformPrivate * priv; */
+/* }; */
+
+/* struct _RetroCoreDescriptorPlatformClass { */
+/*   GObjectClass parent_class; */
+/* }; */
+
+/* struct _RetroCoreDescriptorPlatformPrivate { */
+/*   GKeyFile* key_file; */
+/*   gchar* group; */
+/* }; */
+
+
+/* static gpointer retro_core_descriptor_parent_class = NULL; */
+/* static gpointer retro_core_descriptor_platform_parent_class = NULL; */
+
+/* GType retro_core_descriptor_get_type (void) G_GNUC_CONST; */
+/* #define RETRO_CORE_DESCRIPTOR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), 
RETRO_TYPE_CORE_DESCRIPTOR, RetroCoreDescriptorPrivate)) */
+/* RetroCoreDescriptor* retro_core_descriptor_new (const gchar* filename, GError** error); */
+/* RetroCoreDescriptor* retro_core_descriptor_construct (GType object_type, const gchar* filename, GError** 
error); */
+/* GQuark retro_core_descriptor_error_quark (void); */
+/* static void retro_core_descriptor_check_libretro_group (RetroCoreDescriptor* self, GError** error); */
+/* static void retro_core_descriptor_check_platform_group (RetroCoreDescriptor* self, const gchar* group, 
GError** error); */
+/* static void retro_core_descriptor_check_firmware_group (RetroCoreDescriptor* self, const gchar* group, 
GError** error); */
+/* gboolean retro_core_descriptor_has_icon (RetroCoreDescriptor* self, GError** error); */
+/* gchar* retro_core_descriptor_get_uri (RetroCoreDescriptor* self); */
+/* gchar* retro_core_descriptor_get_id (RetroCoreDescriptor* self); */
+/* gboolean retro_core_descriptor_get_is_game (RetroCoreDescriptor* self, GError** error); */
+/* gboolean retro_core_descriptor_get_is_emulator (RetroCoreDescriptor* self, GError** error); */
+/* gchar* retro_core_descriptor_get_name (RetroCoreDescriptor* self, GError** error); */
+/* GIcon* retro_core_descriptor_get_icon (RetroCoreDescriptor* self, GError** error); */
+/* gchar* retro_core_descriptor_get_module (RetroCoreDescriptor* self, GError** error); */
+/* GFile* retro_core_descriptor_get_module_file (RetroCoreDescriptor* self, GError** error); */
+/* gboolean retro_core_descriptor_has_platform (RetroCoreDescriptor* self, const gchar* platform); */
+/* gboolean retro_core_descriptor_has_firmwares (RetroCoreDescriptor* self, const gchar* platform, GError** 
error); */
+/* gboolean retro_core_descriptor_has_firmware_md5 (RetroCoreDescriptor* self, const gchar* firmware, 
GError** error); */
+/* gboolean retro_core_descriptor_has_firmware_sha512 (RetroCoreDescriptor* self, const gchar* firmware, 
GError** error); */
+/* gchar** retro_core_descriptor_get_mime_type (RetroCoreDescriptor* self, const gchar* platform, int* 
result_length1, GError** error); */
+/* gchar** retro_core_descriptor_get_firmwares (RetroCoreDescriptor* self, const gchar* platform, int* 
result_length1, GError** error); */
+/* gchar* retro_core_descriptor_get_firmware_path (RetroCoreDescriptor* self, const gchar* firmware, 
GError** error); */
+/* gchar* retro_core_descriptor_get_firmware_md5 (RetroCoreDescriptor* self, const gchar* firmware, GError** 
error); */
+/* gchar* retro_core_descriptor_get_firmware_sha512 (RetroCoreDescriptor* self, const gchar* firmware, 
GError** error); */
+/* gboolean retro_core_descriptor_get_is_firmware_mandatory (RetroCoreDescriptor* self, const gchar* 
firmware, GError** error); */
+/* gboolean retro_core_descriptor_get_platform_supports_mime_types (RetroCoreDescriptor* self, const gchar* 
platform, gchar** mime_types, int mime_types_length1, GError** error); */
+/* static gboolean _vala_string_array_contains (gchar* * stack, int stack_length, gchar* needle); */
+/* static void retro_core_descriptor_check_has_required_key (RetroCoreDescriptor* self, const gchar* group, 
const gchar* key, GError** error); */
+/* GType retro_core_descriptor_platform_get_type (void) G_GNUC_CONST; */
+/* #define RETRO_CORE_DESCRIPTOR_PLATFORM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), 
RETRO_CORE_DESCRIPTOR_TYPE_PLATFORM, RetroCoreDescriptorPlatformPrivate)) */
+/* static RetroCoreDescriptorPlatform* retro_core_descriptor_platform_new (GKeyFile* key_file, const gchar* 
platform); */
+/* static RetroCoreDescriptorPlatform* retro_core_descriptor_platform_construct (GType object_type, 
GKeyFile* key_file, const gchar* platform); */
+/* static void retro_core_descriptor_platform_finalize (GObject * obj); */
+/* static void retro_core_descriptor_finalize (GObject * obj); */
+/* static void _vala_array_destroy (gpointer array, gint array_length, GDestroyNotify destroy_func); */
+/* static void _vala_array_free (gpointer array, gint array_length, GDestroyNotify destroy_func); */
+
+
+/* RetroCoreDescriptor* retro_core_descriptor_construct (GType object_type, const gchar* filename, GError** 
error) { */
+/*   RetroCoreDescriptor * self = NULL; */
+/*   const gchar* _tmp0_; */
+/*   gchar* _tmp1_; */
+/*   GKeyFile* _tmp2_; */
+/*   GKeyFile* _tmp3_; */
+/*   const gchar* _tmp4_; */
+/*   GKeyFile* _tmp5_; */
+/*   gsize _tmp6_; */
+/*   gchar** _tmp7_; */
+/*   GError *tmp_error = NULL; */
+/*   g_return_val_if_fail (filename != NULL, NULL); */
+/*   self = (RetroCoreDescriptor*) g_object_new (object_type, NULL); */
+/*   _tmp0_ = filename; */
+/*   _tmp1_ = g_strdup (_tmp0_); */
+/*   _g_free0 (self->filename); */
+/*   self->filename = _tmp1_; */
+/*   _tmp2_ = g_key_file_new (); */
+/*   _g_key_file_unref0 (self->key_file); */
+/*   self->key_file = _tmp2_; */
+/*   _tmp3_ = self->key_file; */
+/*   _tmp4_ = filename; */
+/*   g_key_file_load_from_file (_tmp3_, _tmp4_, G_KEY_FILE_NONE, &tmp_error); */
+/*   if (G_UNLIKELY (tmp_error != NULL)) { */
+/*     g_propagate_error (error, tmp_error); */
+/*     _g_object_unref0 (self); */
+/*     return NULL; */
+/*   } */
+/*   retro_core_descriptor_check_libretro_group (self, &tmp_error); */
+/*   if (G_UNLIKELY (tmp_error != NULL)) { */
+/*     g_propagate_error (error, tmp_error); */
+/*     _g_object_unref0 (self); */
+/*     return NULL; */
+/*   } */
+/*   _tmp5_ = self->key_file; */
+/*   _tmp7_ = g_key_file_get_groups (_tmp5_, &_tmp6_); */
+/*   { */
+/*     gchar** group_collection = NULL; */
+/*     gint group_collection_length1 = 0; */
+/*     gint _group_collection_size_ = 0; */
+/*     gint group_it = 0; */
+/*     group_collection = _tmp7_; */
+/*     group_collection_length1 = _tmp6_; */
+/*     for (group_it = 0; group_it < _tmp6_; group_it = group_it + 1) { */
+/*       gchar* _tmp8_; */
+/*       gchar* group = NULL; */
+/*       _tmp8_ = g_strdup (group_collection[group_it]); */
+/*       group = _tmp8_; */
+/*       { */
+/*         const gchar* _tmp9_; */
+/*         gboolean _tmp10_; */
+/*         _tmp9_ = group; */
+/*         _tmp10_ = g_str_has_prefix (_tmp9_, RETRO_CORE_DESCRIPTOR_PLATFORM_GROUP_PREFIX); */
+/*         if (_tmp10_) { */
+/*           const gchar* _tmp11_; */
+/*           _tmp11_ = group; */
+/*           retro_core_descriptor_check_platform_group (self, _tmp11_, &tmp_error); */
+/*           if (G_UNLIKELY (tmp_error != NULL)) { */
+/*             g_propagate_error (error, tmp_error); */
+/*             _g_free0 (group); */
+/*             group_collection = (_vala_array_free (group_collection, group_collection_length1, 
(GDestroyNotify) g_free), NULL); */
+/*             _g_object_unref0 (self); */
+/*             return NULL; */
+/*           } */
+/*         } else { */
+/*           const gchar* _tmp12_; */
+/*           gboolean _tmp13_; */
+/*           _tmp12_ = group; */
+/*           _tmp13_ = g_str_has_prefix (_tmp12_, RETRO_CORE_DESCRIPTOR_FIRMWARE_GROUP_PREFIX); */
+/*           if (_tmp13_) { */
+/*             const gchar* _tmp14_; */
+/*             _tmp14_ = group; */
+/*             retro_core_descriptor_check_firmware_group (self, _tmp14_, &tmp_error); */
+/*             if (G_UNLIKELY (tmp_error != NULL)) { */
+/*               g_propagate_error (error, tmp_error); */
+/*               _g_free0 (group); */
+/*               group_collection = (_vala_array_free (group_collection, group_collection_length1, 
(GDestroyNotify) g_free), NULL); */
+/*               _g_object_unref0 (self); */
+/*               return NULL; */
+/*             } */
+/*           } */
+/*         } */
+/*         _g_free0 (group); */
+/*       } */
+/*     } */
+/*     group_collection = (_vala_array_free (group_collection, group_collection_length1, (GDestroyNotify) 
g_free), NULL); */
+/*   } */
+/*   return self; */
+/* } */
+
+
+/* RetroCoreDescriptor* retro_core_descriptor_new (const gchar* filename, GError** error) { */
+/*   return retro_core_descriptor_construct (RETRO_TYPE_CORE_DESCRIPTOR, filename, error); */
+/* } */
+
+
+/* gboolean retro_core_descriptor_has_icon (RetroCoreDescriptor* self, GError** error) { */
+/*   gboolean result = FALSE; */
+/*   gboolean _tmp0_ = FALSE; */
+/*   GKeyFile* _tmp1_; */
+/*   gboolean _tmp2_; */
+/*   GError *tmp_error = NULL; */
+/*   g_return_val_if_fail (self != NULL, FALSE); */
+/*   _tmp1_ = self->key_file; */
+/*   _tmp2_ = g_key_file_has_key (_tmp1_, RETRO_CORE_DESCRIPTOR_LIBRETRO_GROUP, 
RETRO_CORE_DESCRIPTOR_ICON_KEY, &tmp_error); */
+/*   _tmp0_ = _tmp2_; */
+/*   if (G_UNLIKELY (tmp_error != NULL)) { */
+/*     if (tmp_error->domain == G_KEY_FILE_ERROR) { */
+/*       gboolean _tmp3_ = FALSE; */
+/*       g_propagate_error (error, tmp_error); */
+/*       return _tmp3_; */
+/*     } else { */
+/*       gboolean _tmp4_ = FALSE; */
+/*       g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, 
tmp_error->message, g_quark_to_string (tmp_error->domain), tmp_error->code); */
+/*       g_clear_error (&tmp_error); */
+/*       return _tmp4_; */
+/*     } */
+/*   } */
+/*   result = _tmp0_; */
+/*   return result; */
+/* } */
+
+
+/* gchar* retro_core_descriptor_get_uri (RetroCoreDescriptor* self) { */
+/*   gchar* result = NULL; */
+/*   GFile* file = NULL; */
+/*   const gchar* _tmp0_; */
+/*   GFile* _tmp1_; */
+/*   gchar* _tmp2_; */
+/*   g_return_val_if_fail (self != NULL, NULL); */
+/*   _tmp0_ = self->filename; */
+/*   _tmp1_ = g_file_new_for_path (_tmp0_); */
+/*   file = _tmp1_; */
+/*   _tmp2_ = g_file_get_uri (file); */
+/*   result = _tmp2_; */
+/*   _g_object_unref0 (file); */
+/*   return result; */
+/* } */
+
+
+/* gchar* retro_core_descriptor_get_id (RetroCoreDescriptor* self) { */
+/*   gchar* result = NULL; */
+/*   const gchar* _tmp0_; */
+/*   gchar* _tmp1_; */
+/*   g_return_val_if_fail (self != NULL, NULL); */
+/*   _tmp0_ = self->filename; */
+/*   _tmp1_ = g_path_get_basename (_tmp0_); */
+/*   result = _tmp1_; */
+/*   return result; */
+/* } */
+
+
+/* gboolean retro_core_descriptor_get_is_game (RetroCoreDescriptor* self, GError** error) { */
+/*   gboolean result = FALSE; */
+/*   gchar* _tmp0_ = NULL; */
+/*   GKeyFile* _tmp1_; */
+/*   gchar* _tmp2_; */
+/*   gchar* _tmp5_; */
+/*   gchar* _tmp6_; */
+/*   gboolean _tmp7_; */
+/*   GError *tmp_error = NULL; */
+/*   g_return_val_if_fail (self != NULL, FALSE); */
+/*   _tmp1_ = self->key_file; */
+/*   _tmp2_ = g_key_file_get_string (_tmp1_, RETRO_CORE_DESCRIPTOR_LIBRETRO_GROUP, 
RETRO_CORE_DESCRIPTOR_TYPE_KEY, &tmp_error); */
+/*   _tmp0_ = _tmp2_; */
+/*   if (G_UNLIKELY (tmp_error != NULL)) { */
+/*     if (tmp_error->domain == G_KEY_FILE_ERROR) { */
+/*       gboolean _tmp3_ = FALSE; */
+/*       g_propagate_error (error, tmp_error); */
+/*       return _tmp3_; */
+/*     } else { */
+/*       gboolean _tmp4_ = FALSE; */
+/*       g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, 
tmp_error->message, g_quark_to_string (tmp_error->domain), tmp_error->code); */
+/*       g_clear_error (&tmp_error); */
+/*       return _tmp4_; */
+/*     } */
+/*   } */
+/*   _tmp5_ = _tmp0_; */
+/*   _tmp0_ = NULL; */
+/*   _tmp6_ = _tmp5_; */
+/*   _tmp7_ = g_strcmp0 (_tmp6_, RETRO_CORE_DESCRIPTOR_TYPE_GAME) == 0; */
+/*   _g_free0 (_tmp6_); */
+/*   result = _tmp7_; */
+/*   _g_free0 (_tmp0_); */
+/*   return result; */
+/* } */
+
+
+/* gboolean retro_core_descriptor_get_is_emulator (RetroCoreDescriptor* self, GError** error) { */
+/*   gboolean result = FALSE; */
+/*   gchar* _tmp0_ = NULL; */
+/*   GKeyFile* _tmp1_; */
+/*   gchar* _tmp2_; */
+/*   gchar* _tmp5_; */
+/*   gchar* _tmp6_; */
+/*   gboolean _tmp7_; */
+/*   GError *tmp_error = NULL; */
+/*   g_return_val_if_fail (self != NULL, FALSE); */
+/*   _tmp1_ = self->key_file; */
+/*   _tmp2_ = g_key_file_get_string (_tmp1_, RETRO_CORE_DESCRIPTOR_LIBRETRO_GROUP, 
RETRO_CORE_DESCRIPTOR_TYPE_KEY, &tmp_error); */
+/*   _tmp0_ = _tmp2_; */
+/*   if (G_UNLIKELY (tmp_error != NULL)) { */
+/*     if (tmp_error->domain == G_KEY_FILE_ERROR) { */
+/*       gboolean _tmp3_ = FALSE; */
+/*       g_propagate_error (error, tmp_error); */
+/*       return _tmp3_; */
+/*     } else { */
+/*       gboolean _tmp4_ = FALSE; */
+/*       g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, 
tmp_error->message, g_quark_to_string (tmp_error->domain), tmp_error->code); */
+/*       g_clear_error (&tmp_error); */
+/*       return _tmp4_; */
+/*     } */
+/*   } */
+/*   _tmp5_ = _tmp0_; */
+/*   _tmp0_ = NULL; */
+/*   _tmp6_ = _tmp5_; */
+/*   _tmp7_ = g_strcmp0 (_tmp6_, RETRO_CORE_DESCRIPTOR_TYPE_EMULATOR) == 0; */
+/*   _g_free0 (_tmp6_); */
+/*   result = _tmp7_; */
+/*   _g_free0 (_tmp0_); */
+/*   return result; */
+/* } */
+
+
+/* gchar* retro_core_descriptor_get_name (RetroCoreDescriptor* self, GError** error) { */
+/*   gchar* result = NULL; */
+/*   gchar* _tmp0_ = NULL; */
+/*   GKeyFile* _tmp1_; */
+/*   gchar* _tmp2_; */
+/*   gchar* _tmp3_; */
+/*   GError *tmp_error = NULL; */
+/*   g_return_val_if_fail (self != NULL, NULL); */
+/*   _tmp1_ = self->key_file; */
+/*   _tmp2_ = g_key_file_get_string (_tmp1_, RETRO_CORE_DESCRIPTOR_LIBRETRO_GROUP, 
RETRO_CORE_DESCRIPTOR_NAME_KEY, &tmp_error); */
+/*   _tmp0_ = _tmp2_; */
+/*   if (G_UNLIKELY (tmp_error != NULL)) { */
+/*     if (tmp_error->domain == G_KEY_FILE_ERROR) { */
+/*       g_propagate_error (error, tmp_error); */
+/*       return NULL; */
+/*     } else { */
+/*       g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, 
tmp_error->message, g_quark_to_string (tmp_error->domain), tmp_error->code); */
+/*       g_clear_error (&tmp_error); */
+/*       return NULL; */
+/*     } */
+/*   } */
+/*   _tmp3_ = _tmp0_; */
+/*   _tmp0_ = NULL; */
+/*   result = _tmp3_; */
+/*   _g_free0 (_tmp0_); */
+/*   return result; */
+/* } */
+
+
+/* GIcon* retro_core_descriptor_get_icon (RetroCoreDescriptor* self, GError** error) { */
+/*   GIcon* result = NULL; */
+/*   gchar* icon_name = NULL; */
+/*   GKeyFile* _tmp0_; */
+/*   gchar* _tmp1_; */
+/*   GThemedIcon* _tmp2_; */
+/*   GError *tmp_error = NULL; */
+/*   g_return_val_if_fail (self != NULL, NULL); */
+/*   _tmp0_ = self->key_file; */
+/*   _tmp1_ = g_key_file_get_string (_tmp0_, RETRO_CORE_DESCRIPTOR_LIBRETRO_GROUP, 
RETRO_CORE_DESCRIPTOR_ICON_KEY, &tmp_error); */
+/*   icon_name = _tmp1_; */
+/*   if (G_UNLIKELY (tmp_error != NULL)) { */
+/*     if (tmp_error->domain == G_KEY_FILE_ERROR) { */
+/*       g_propagate_error (error, tmp_error); */
+/*       return NULL; */
+/*     } else { */
+/*       g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, 
tmp_error->message, g_quark_to_string (tmp_error->domain), tmp_error->code); */
+/*       g_clear_error (&tmp_error); */
+/*       return NULL; */
+/*     } */
+/*   } */
+/*   _tmp2_ = (GThemedIcon*) g_themed_icon_new (icon_name); */
+/*   result = (GIcon*) _tmp2_; */
+/*   _g_free0 (icon_name); */
+/*   return result; */
+/* } */
+
+
+/* gchar* retro_core_descriptor_get_module (RetroCoreDescriptor* self, GError** error) { */
+/*   gchar* result = NULL; */
+/*   gchar* _tmp0_ = NULL; */
+/*   GKeyFile* _tmp1_; */
+/*   gchar* _tmp2_; */
+/*   gchar* _tmp3_; */
+/*   GError *tmp_error = NULL; */
+/*   g_return_val_if_fail (self != NULL, NULL); */
+/*   _tmp1_ = self->key_file; */
+/*   _tmp2_ = g_key_file_get_string (_tmp1_, RETRO_CORE_DESCRIPTOR_LIBRETRO_GROUP, 
RETRO_CORE_DESCRIPTOR_MODULE_KEY, &tmp_error); */
+/*   _tmp0_ = _tmp2_; */
+/*   if (G_UNLIKELY (tmp_error != NULL)) { */
+/*     if (tmp_error->domain == G_KEY_FILE_ERROR) { */
+/*       g_propagate_error (error, tmp_error); */
+/*       return NULL; */
+/*     } else { */
+/*       g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, 
tmp_error->message, g_quark_to_string (tmp_error->domain), tmp_error->code); */
+/*       g_clear_error (&tmp_error); */
+/*       return NULL; */
+/*     } */
+/*   } */
+/*   _tmp3_ = _tmp0_; */
+/*   _tmp0_ = NULL; */
+/*   result = _tmp3_; */
+/*   _g_free0 (_tmp0_); */
+/*   return result; */
+/* } */
+
+
+/* GFile* retro_core_descriptor_get_module_file (RetroCoreDescriptor* self, GError** error) { */
+/*   GFile* result = NULL; */
+/*   GFile* file = NULL; */
+/*   const gchar* _tmp0_; */
+/*   GFile* _tmp1_; */
+/*   GFile* dir = NULL; */
+/*   GFile* _tmp2_; */
+/*   GFile* _tmp3_; */
+/*   GFile* _tmp4_; */
+/*   gchar* module = NULL; */
+/*   gchar* _tmp5_; */
+/*   GFile* module_file = NULL; */
+/*   GFile* _tmp6_; */
+/*   const gchar* _tmp7_; */
+/*   GFile* _tmp8_; */
+/*   GFile* _tmp9_; */
+/*   gboolean _tmp10_; */
+/*   GError *tmp_error = NULL; */
+/*   g_return_val_if_fail (self != NULL, NULL); */
+/*   _tmp0_ = self->filename; */
+/*   _tmp1_ = g_file_new_for_path (_tmp0_); */
+/*   file = _tmp1_; */
+/*   _tmp2_ = file; */
+/*   _tmp3_ = g_file_get_parent (_tmp2_); */
+/*   dir = _tmp3_; */
+/*   _tmp4_ = dir; */
+/*   if (_tmp4_ == NULL) { */
+/*     result = NULL; */
+/*     _g_object_unref0 (dir); */
+/*     _g_object_unref0 (file); */
+/*     return result; */
+/*   } */
+/*   _tmp5_ = retro_core_descriptor_get_module (self, &tmp_error); */
+/*   module = _tmp5_; */
+/*   if (G_UNLIKELY (tmp_error != NULL)) { */
+/*     if (tmp_error->domain == G_KEY_FILE_ERROR) { */
+/*       g_propagate_error (error, tmp_error); */
+/*       _g_object_unref0 (dir); */
+/*       _g_object_unref0 (file); */
+/*       return NULL; */
+/*     } else { */
+/*       _g_object_unref0 (dir); */
+/*       _g_object_unref0 (file); */
+/*       g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, 
tmp_error->message, g_quark_to_string (tmp_error->domain), tmp_error->code); */
+/*       g_clear_error (&tmp_error); */
+/*       return NULL; */
+/*     } */
+/*   } */
+/*   _tmp6_ = dir; */
+/*   _tmp7_ = module; */
+/*   _tmp8_ = g_file_get_child (_tmp6_, _tmp7_); */
+/*   module_file = _tmp8_; */
+/*   _tmp9_ = module_file; */
+/*   _tmp10_ = g_file_query_exists (_tmp9_, NULL); */
+/*   if (!_tmp10_) { */
+/*     result = NULL; */
+/*     _g_object_unref0 (module_file); */
+/*     _g_free0 (module); */
+/*     _g_object_unref0 (dir); */
+/*     _g_object_unref0 (file); */
+/*     return result; */
+/*   } */
+/*   result = module_file; */
+/*   _g_free0 (module); */
+/*   _g_object_unref0 (dir); */
+/*   _g_object_unref0 (file); */
+/*   return result; */
+/* } */
+
+
+/* gboolean retro_core_descriptor_has_platform (RetroCoreDescriptor* self, const gchar* platform) { */
+/*   gboolean result = FALSE; */
+/*   GKeyFile* _tmp0_; */
+/*   const gchar* _tmp1_; */
+/*   gchar* _tmp2_; */
+/*   gchar* _tmp3_; */
+/*   gboolean _tmp4_; */
+/*   gboolean _tmp5_; */
+/*   g_return_val_if_fail (self != NULL, FALSE); */
+/*   g_return_val_if_fail (platform != NULL, FALSE); */
+/*   _tmp0_ = self->key_file; */
+/*   _tmp1_ = platform; */
+/*   _tmp2_ = g_strconcat (RETRO_CORE_DESCRIPTOR_PLATFORM_GROUP_PREFIX, _tmp1_, NULL); */
+/*   _tmp3_ = _tmp2_; */
+/*   _tmp4_ = g_key_file_has_group (_tmp0_, _tmp3_); */
+/*   _tmp5_ = _tmp4_; */
+/*   _g_free0 (_tmp3_); */
+/*   result = _tmp5_; */
+/*   return result; */
+/* } */
+
+
+/* gboolean retro_core_descriptor_has_firmwares (RetroCoreDescriptor* self, const gchar* platform, GError** 
error) { */
+/*   gboolean result = FALSE; */
+/*   gboolean _tmp0_ = FALSE; */
+/*   GKeyFile* _tmp1_; */
+/*   const gchar* _tmp2_; */
+/*   gchar* _tmp3_; */
+/*   gchar* _tmp4_; */
+/*   gboolean _tmp5_; */
+/*   gboolean _tmp6_; */
+/*   GError *tmp_error = NULL; */
+/*   g_return_val_if_fail (self != NULL, FALSE); */
+/*   g_return_val_if_fail (platform != NULL, FALSE); */
+/*   _tmp1_ = self->key_file; */
+/*   _tmp2_ = platform; */
+/*   _tmp3_ = g_strconcat (RETRO_CORE_DESCRIPTOR_PLATFORM_GROUP_PREFIX, _tmp2_, NULL); */
+/*   _tmp4_ = _tmp3_; */
+/*   _tmp5_ = g_key_file_has_key (_tmp1_, _tmp4_, RETRO_CORE_DESCRIPTOR_PLATFORM_FIRMWARES_KEY, &tmp_error); 
*/
+/*   _tmp6_ = _tmp5_; */
+/*   _g_free0 (_tmp4_); */
+/*   _tmp0_ = _tmp6_; */
+/*   if (G_UNLIKELY (tmp_error != NULL)) { */
+/*     if (tmp_error->domain == G_KEY_FILE_ERROR) { */
+/*       gboolean _tmp7_ = FALSE; */
+/*       g_propagate_error (error, tmp_error); */
+/*       return _tmp7_; */
+/*     } else { */
+/*       gboolean _tmp8_ = FALSE; */
+/*       g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, 
tmp_error->message, g_quark_to_string (tmp_error->domain), tmp_error->code); */
+/*       g_clear_error (&tmp_error); */
+/*       return _tmp8_; */
+/*     } */
+/*   } */
+/*   result = _tmp0_; */
+/*   return result; */
+/* } */
+
+
+/* gboolean retro_core_descriptor_has_firmware_md5 (RetroCoreDescriptor* self, const gchar* firmware, 
GError** error) { */
+/*   gboolean result = FALSE; */
+/*   gboolean _tmp0_ = FALSE; */
+/*   GKeyFile* _tmp1_; */
+/*   const gchar* _tmp2_; */
+/*   gchar* _tmp3_; */
+/*   gchar* _tmp4_; */
+/*   gboolean _tmp5_; */
+/*   gboolean _tmp6_; */
+/*   GError *tmp_error = NULL; */
+/*   g_return_val_if_fail (self != NULL, FALSE); */
+/*   g_return_val_if_fail (firmware != NULL, FALSE); */
+/*   _tmp1_ = self->key_file; */
+/*   _tmp2_ = firmware; */
+/*   _tmp3_ = g_strconcat (RETRO_CORE_DESCRIPTOR_FIRMWARE_GROUP_PREFIX, _tmp2_, NULL); */
+/*   _tmp4_ = _tmp3_; */
+/*   _tmp5_ = g_key_file_has_key (_tmp1_, _tmp4_, RETRO_CORE_DESCRIPTOR_FIRMWARE_MD5_KEY, &tmp_error); */
+/*   _tmp6_ = _tmp5_; */
+/*   _g_free0 (_tmp4_); */
+/*   _tmp0_ = _tmp6_; */
+/*   if (G_UNLIKELY (tmp_error != NULL)) { */
+/*     if (tmp_error->domain == G_KEY_FILE_ERROR) { */
+/*       gboolean _tmp7_ = FALSE; */
+/*       g_propagate_error (error, tmp_error); */
+/*       return _tmp7_; */
+/*     } else { */
+/*       gboolean _tmp8_ = FALSE; */
+/*       g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, 
tmp_error->message, g_quark_to_string (tmp_error->domain), tmp_error->code); */
+/*       g_clear_error (&tmp_error); */
+/*       return _tmp8_; */
+/*     } */
+/*   } */
+/*   result = _tmp0_; */
+/*   return result; */
+/* } */
+
+
+/* gboolean retro_core_descriptor_has_firmware_sha512 (RetroCoreDescriptor* self, const gchar* firmware, 
GError** error) { */
+/*   gboolean result = FALSE; */
+/*   gboolean _tmp0_ = FALSE; */
+/*   GKeyFile* _tmp1_; */
+/*   const gchar* _tmp2_; */
+/*   gchar* _tmp3_; */
+/*   gchar* _tmp4_; */
+/*   gboolean _tmp5_; */
+/*   gboolean _tmp6_; */
+/*   GError *tmp_error = NULL; */
+/*   g_return_val_if_fail (self != NULL, FALSE); */
+/*   g_return_val_if_fail (firmware != NULL, FALSE); */
+/*   _tmp1_ = self->key_file; */
+/*   _tmp2_ = firmware; */
+/*   _tmp3_ = g_strconcat (RETRO_CORE_DESCRIPTOR_FIRMWARE_GROUP_PREFIX, _tmp2_, NULL); */
+/*   _tmp4_ = _tmp3_; */
+/*   _tmp5_ = g_key_file_has_key (_tmp1_, _tmp4_, RETRO_CORE_DESCRIPTOR_FIRMWARE_SHA512_KEY, &tmp_error); */
+/*   _tmp6_ = _tmp5_; */
+/*   _g_free0 (_tmp4_); */
+/*   _tmp0_ = _tmp6_; */
+/*   if (G_UNLIKELY (tmp_error != NULL)) { */
+/*     if (tmp_error->domain == G_KEY_FILE_ERROR) { */
+/*       gboolean _tmp7_ = FALSE; */
+/*       g_propagate_error (error, tmp_error); */
+/*       return _tmp7_; */
+/*     } else { */
+/*       gboolean _tmp8_ = FALSE; */
+/*       g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, 
tmp_error->message, g_quark_to_string (tmp_error->domain), tmp_error->code); */
+/*       g_clear_error (&tmp_error); */
+/*       return _tmp8_; */
+/*     } */
+/*   } */
+/*   result = _tmp0_; */
+/*   return result; */
+/* } */
+
+
+/* gchar** retro_core_descriptor_get_mime_type (RetroCoreDescriptor* self, const gchar* platform, int* 
result_length1, GError** error) { */
+/*   gchar** result = NULL; */
+/*   gchar** _tmp0_ = NULL; */
+/*   GKeyFile* _tmp1_; */
+/*   const gchar* _tmp2_; */
+/*   gchar* _tmp3_; */
+/*   gchar* _tmp4_; */
+/*   gsize _tmp5_; */
+/*   gchar** _tmp6_; */
+/*   gchar** _tmp7_; */
+/*   gint _tmp7__length1; */
+/*   gint _tmp0__length1; */
+/*   gint __tmp0__size_; */
+/*   gchar** _tmp8_; */
+/*   gint _tmp8__length1; */
+/*   gchar** _tmp9_; */
+/*   gint _tmp9__length1; */
+/*   GError *tmp_error = NULL; */
+/*   g_return_val_if_fail (self != NULL, NULL); */
+/*   g_return_val_if_fail (platform != NULL, NULL); */
+/*   _tmp1_ = self->key_file; */
+/*   _tmp2_ = platform; */
+/*   _tmp3_ = g_strconcat (RETRO_CORE_DESCRIPTOR_PLATFORM_GROUP_PREFIX, _tmp2_, NULL); */
+/*   _tmp4_ = _tmp3_; */
+/*   _tmp6_ = g_key_file_get_string_list (_tmp1_, _tmp4_, RETRO_CORE_DESCRIPTOR_PLATFORM_MIME_TYPE_KEY, 
&_tmp5_, &tmp_error); */
+/*   _tmp7_ = _tmp6_; */
+/*   _tmp7__length1 = _tmp5_; */
+/*   _g_free0 (_tmp4_); */
+/*   _tmp0_ = _tmp7_; */
+/*   _tmp0__length1 = _tmp7__length1; */
+/*   __tmp0__size_ = _tmp0__length1; */
+/*   if (G_UNLIKELY (tmp_error != NULL)) { */
+/*     if (tmp_error->domain == G_KEY_FILE_ERROR) { */
+/*       g_propagate_error (error, tmp_error); */
+/*       return NULL; */
+/*     } else { */
+/*       g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, 
tmp_error->message, g_quark_to_string (tmp_error->domain), tmp_error->code); */
+/*       g_clear_error (&tmp_error); */
+/*       return NULL; */
+/*     } */
+/*   } */
+/*   _tmp8_ = _tmp0_; */
+/*   _tmp8__length1 = _tmp0__length1; */
+/*   _tmp0_ = NULL; */
+/*   _tmp0__length1 = 0; */
+/*   _tmp9_ = _tmp8_; */
+/*   _tmp9__length1 = _tmp8__length1; */
+/*   if (result_length1) { */
+/*     *result_length1 = _tmp9__length1; */
+/*   } */
+/*   result = _tmp9_; */
+/*   _tmp0_ = (_vala_array_free (_tmp0_, _tmp0__length1, (GDestroyNotify) g_free), NULL); */
+/*   return result; */
+/* } */
+
+
+/* gchar** retro_core_descriptor_get_firmwares (RetroCoreDescriptor* self, const gchar* platform, int* 
result_length1, GError** error) { */
+/*   gchar** result = NULL; */
+/*   gchar** _tmp0_ = NULL; */
+/*   GKeyFile* _tmp1_; */
+/*   const gchar* _tmp2_; */
+/*   gchar* _tmp3_; */
+/*   gchar* _tmp4_; */
+/*   gsize _tmp5_; */
+/*   gchar** _tmp6_; */
+/*   gchar** _tmp7_; */
+/*   gint _tmp7__length1; */
+/*   gint _tmp0__length1; */
+/*   gint __tmp0__size_; */
+/*   gchar** _tmp8_; */
+/*   gint _tmp8__length1; */
+/*   gchar** _tmp9_; */
+/*   gint _tmp9__length1; */
+/*   GError *tmp_error = NULL; */
+/*   g_return_val_if_fail (self != NULL, NULL); */
+/*   g_return_val_if_fail (platform != NULL, NULL); */
+/*   _tmp1_ = self->key_file; */
+/*   _tmp2_ = platform; */
+/*   _tmp3_ = g_strconcat (RETRO_CORE_DESCRIPTOR_PLATFORM_GROUP_PREFIX, _tmp2_, NULL); */
+/*   _tmp4_ = _tmp3_; */
+/*   _tmp6_ = g_key_file_get_string_list (_tmp1_, _tmp4_, RETRO_CORE_DESCRIPTOR_PLATFORM_FIRMWARES_KEY, 
&_tmp5_, &tmp_error); */
+/*   _tmp7_ = _tmp6_; */
+/*   _tmp7__length1 = _tmp5_; */
+/*   _g_free0 (_tmp4_); */
+/*   _tmp0_ = _tmp7_; */
+/*   _tmp0__length1 = _tmp7__length1; */
+/*   __tmp0__size_ = _tmp0__length1; */
+/*   if (G_UNLIKELY (tmp_error != NULL)) { */
+/*     if (tmp_error->domain == G_KEY_FILE_ERROR) { */
+/*       g_propagate_error (error, tmp_error); */
+/*       return NULL; */
+/*     } else { */
+/*       g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, 
tmp_error->message, g_quark_to_string (tmp_error->domain), tmp_error->code); */
+/*       g_clear_error (&tmp_error); */
+/*       return NULL; */
+/*     } */
+/*   } */
+/*   _tmp8_ = _tmp0_; */
+/*   _tmp8__length1 = _tmp0__length1; */
+/*   _tmp0_ = NULL; */
+/*   _tmp0__length1 = 0; */
+/*   _tmp9_ = _tmp8_; */
+/*   _tmp9__length1 = _tmp8__length1; */
+/*   if (result_length1) { */
+/*     *result_length1 = _tmp9__length1; */
+/*   } */
+/*   result = _tmp9_; */
+/*   _tmp0_ = (_vala_array_free (_tmp0_, _tmp0__length1, (GDestroyNotify) g_free), NULL); */
+/*   return result; */
+/* } */
+
+
+/* gchar* retro_core_descriptor_get_firmware_path (RetroCoreDescriptor* self, const gchar* firmware, 
GError** error) { */
+/*   gchar* result = NULL; */
+/*   gchar* _tmp0_ = NULL; */
+/*   GKeyFile* _tmp1_; */
+/*   const gchar* _tmp2_; */
+/*   gchar* _tmp3_; */
+/*   gchar* _tmp4_; */
+/*   gchar* _tmp5_; */
+/*   gchar* _tmp6_; */
+/*   gchar* _tmp7_; */
+/*   GError *tmp_error = NULL; */
+/*   g_return_val_if_fail (self != NULL, NULL); */
+/*   g_return_val_if_fail (firmware != NULL, NULL); */
+/*   _tmp1_ = self->key_file; */
+/*   _tmp2_ = firmware; */
+/*   _tmp3_ = g_strconcat (RETRO_CORE_DESCRIPTOR_FIRMWARE_GROUP_PREFIX, _tmp2_, NULL); */
+/*   _tmp4_ = _tmp3_; */
+/*   _tmp5_ = g_key_file_get_string (_tmp1_, _tmp4_, RETRO_CORE_DESCRIPTOR_FIRMWARE_PATH_KEY, &tmp_error); */
+/*   _tmp6_ = _tmp5_; */
+/*   _g_free0 (_tmp4_); */
+/*   _tmp0_ = _tmp6_; */
+/*   if (G_UNLIKELY (tmp_error != NULL)) { */
+/*     if (tmp_error->domain == G_KEY_FILE_ERROR) { */
+/*       g_propagate_error (error, tmp_error); */
+/*       return NULL; */
+/*     } else { */
+/*       g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, 
tmp_error->message, g_quark_to_string (tmp_error->domain), tmp_error->code); */
+/*       g_clear_error (&tmp_error); */
+/*       return NULL; */
+/*     } */
+/*   } */
+/*   _tmp7_ = _tmp0_; */
+/*   _tmp0_ = NULL; */
+/*   result = _tmp7_; */
+/*   _g_free0 (_tmp0_); */
+/*   return result; */
+/* } */
+
+
+/* gchar* retro_core_descriptor_get_firmware_md5 (RetroCoreDescriptor* self, const gchar* firmware, GError** 
error) { */
+/*   gchar* result = NULL; */
+/*   gchar* _tmp0_ = NULL; */
+/*   GKeyFile* _tmp1_; */
+/*   const gchar* _tmp2_; */
+/*   gchar* _tmp3_; */
+/*   gchar* _tmp4_; */
+/*   gchar* _tmp5_; */
+/*   gchar* _tmp6_; */
+/*   gchar* _tmp7_; */
+/*   GError *tmp_error = NULL; */
+/*   g_return_val_if_fail (self != NULL, NULL); */
+/*   g_return_val_if_fail (firmware != NULL, NULL); */
+/*   _tmp1_ = self->key_file; */
+/*   _tmp2_ = firmware; */
+/*   _tmp3_ = g_strconcat (RETRO_CORE_DESCRIPTOR_FIRMWARE_GROUP_PREFIX, _tmp2_, NULL); */
+/*   _tmp4_ = _tmp3_; */
+/*   _tmp5_ = g_key_file_get_string (_tmp1_, _tmp4_, RETRO_CORE_DESCRIPTOR_FIRMWARE_MD5_KEY, &tmp_error); */
+/*   _tmp6_ = _tmp5_; */
+/*   _g_free0 (_tmp4_); */
+/*   _tmp0_ = _tmp6_; */
+/*   if (G_UNLIKELY (tmp_error != NULL)) { */
+/*     if (tmp_error->domain == G_KEY_FILE_ERROR) { */
+/*       g_propagate_error (error, tmp_error); */
+/*       return NULL; */
+/*     } else { */
+/*       g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, 
tmp_error->message, g_quark_to_string (tmp_error->domain), tmp_error->code); */
+/*       g_clear_error (&tmp_error); */
+/*       return NULL; */
+/*     } */
+/*   } */
+/*   _tmp7_ = _tmp0_; */
+/*   _tmp0_ = NULL; */
+/*   result = _tmp7_; */
+/*   _g_free0 (_tmp0_); */
+/*   return result; */
+/* } */
+
+
+/* gchar* retro_core_descriptor_get_firmware_sha512 (RetroCoreDescriptor* self, const gchar* firmware, 
GError** error) { */
+/*   gchar* result = NULL; */
+/*   gchar* _tmp0_ = NULL; */
+/*   GKeyFile* _tmp1_; */
+/*   const gchar* _tmp2_; */
+/*   gchar* _tmp3_; */
+/*   gchar* _tmp4_; */
+/*   gchar* _tmp5_; */
+/*   gchar* _tmp6_; */
+/*   gchar* _tmp7_; */
+/*   GError *tmp_error = NULL; */
+/*   g_return_val_if_fail (self != NULL, NULL); */
+/*   g_return_val_if_fail (firmware != NULL, NULL); */
+/*   _tmp1_ = self->key_file; */
+/*   _tmp2_ = firmware; */
+/*   _tmp3_ = g_strconcat (RETRO_CORE_DESCRIPTOR_FIRMWARE_GROUP_PREFIX, _tmp2_, NULL); */
+/*   _tmp4_ = _tmp3_; */
+/*   _tmp5_ = g_key_file_get_string (_tmp1_, _tmp4_, RETRO_CORE_DESCRIPTOR_FIRMWARE_SHA512_KEY, &tmp_error); 
*/
+/*   _tmp6_ = _tmp5_; */
+/*   _g_free0 (_tmp4_); */
+/*   _tmp0_ = _tmp6_; */
+/*   if (G_UNLIKELY (tmp_error != NULL)) { */
+/*     if (tmp_error->domain == G_KEY_FILE_ERROR) { */
+/*       g_propagate_error (error, tmp_error); */
+/*       return NULL; */
+/*     } else { */
+/*       g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, 
tmp_error->message, g_quark_to_string (tmp_error->domain), tmp_error->code); */
+/*       g_clear_error (&tmp_error); */
+/*       return NULL; */
+/*     } */
+/*   } */
+/*   _tmp7_ = _tmp0_; */
+/*   _tmp0_ = NULL; */
+/*   result = _tmp7_; */
+/*   _g_free0 (_tmp0_); */
+/*   return result; */
+/* } */
+
+
+/* gboolean retro_core_descriptor_get_is_firmware_mandatory (RetroCoreDescriptor* self, const gchar* 
firmware, GError** error) { */
+/*   gboolean result = FALSE; */
+/*   gboolean _tmp0_ = FALSE; */
+/*   GKeyFile* _tmp1_; */
+/*   const gchar* _tmp2_; */
+/*   gchar* _tmp3_; */
+/*   gchar* _tmp4_; */
+/*   gboolean _tmp5_; */
+/*   gboolean _tmp6_; */
+/*   GError *tmp_error = NULL; */
+/*   g_return_val_if_fail (self != NULL, FALSE); */
+/*   g_return_val_if_fail (firmware != NULL, FALSE); */
+/*   _tmp1_ = self->key_file; */
+/*   _tmp2_ = firmware; */
+/*   _tmp3_ = g_strconcat (RETRO_CORE_DESCRIPTOR_FIRMWARE_GROUP_PREFIX, _tmp2_, NULL); */
+/*   _tmp4_ = _tmp3_; */
+/*   _tmp5_ = g_key_file_get_boolean (_tmp1_, _tmp4_, RETRO_CORE_DESCRIPTOR_FIRMWARE_MANDATORY_KEY, 
&tmp_error); */
+/*   _tmp6_ = _tmp5_; */
+/*   _g_free0 (_tmp4_); */
+/*   _tmp0_ = _tmp6_; */
+/*   if (G_UNLIKELY (tmp_error != NULL)) { */
+/*     if (tmp_error->domain == G_KEY_FILE_ERROR) { */
+/*       gboolean _tmp7_ = FALSE; */
+/*       g_propagate_error (error, tmp_error); */
+/*       return _tmp7_; */
+/*     } else { */
+/*       gboolean _tmp8_ = FALSE; */
+/*       g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, 
tmp_error->message, g_quark_to_string (tmp_error->domain), tmp_error->code); */
+/*       g_clear_error (&tmp_error); */
+/*       return _tmp8_; */
+/*     } */
+/*   } */
+/*   result = _tmp0_; */
+/*   return result; */
+/* } */
+
+
+/* static gboolean _vala_string_array_contains (gchar* * stack, int stack_length, gchar* needle) { */
+/*   int i; */
+/*   for (i = 0; i < stack_length; i++) { */
+/*     if (g_strcmp0 (stack[i], needle) == 0) { */
+/*       return TRUE; */
+/*     } */
+/*   } */
+/*   return FALSE; */
+/* } */
+
+
+/* gboolean retro_core_descriptor_get_platform_supports_mime_types (RetroCoreDescriptor* self, const gchar* 
platform, gchar** mime_types, int mime_types_length1, GError** error) { */
+/*   gboolean result = FALSE; */
+/*   gchar** supported_mime_types = NULL; */
+/*   const gchar* _tmp0_; */
+/*   gint _tmp1_; */
+/*   gchar** _tmp2_; */
+/*   gint supported_mime_types_length1; */
+/*   gint _supported_mime_types_size_; */
+/*   gchar** _tmp5_; */
+/*   gint _tmp5__length1; */
+/*   GError *tmp_error = NULL; */
+/*   g_return_val_if_fail (self != NULL, FALSE); */
+/*   g_return_val_if_fail (platform != NULL, FALSE); */
+/*   _tmp0_ = platform; */
+/*   _tmp2_ = retro_core_descriptor_get_mime_type (self, _tmp0_, &_tmp1_, &tmp_error); */
+/*   supported_mime_types = _tmp2_; */
+/*   supported_mime_types_length1 = _tmp1_; */
+/*   _supported_mime_types_size_ = supported_mime_types_length1; */
+/*   if (G_UNLIKELY (tmp_error != NULL)) { */
+/*     if (tmp_error->domain == G_KEY_FILE_ERROR) { */
+/*       gboolean _tmp3_ = FALSE; */
+/*       g_propagate_error (error, tmp_error); */
+/*       return _tmp3_; */
+/*     } else { */
+/*       gboolean _tmp4_ = FALSE; */
+/*       g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, 
tmp_error->message, g_quark_to_string (tmp_error->domain), tmp_error->code); */
+/*       g_clear_error (&tmp_error); */
+/*       return _tmp4_; */
+/*     } */
+/*   } */
+/*   _tmp5_ = mime_types; */
+/*   _tmp5__length1 = mime_types_length1; */
+/*   { */
+/*     gchar** mime_type_collection = NULL; */
+/*     gint mime_type_collection_length1 = 0; */
+/*     gint _mime_type_collection_size_ = 0; */
+/*     gint mime_type_it = 0; */
+/*     mime_type_collection = _tmp5_; */
+/*     mime_type_collection_length1 = _tmp5__length1; */
+/*     for (mime_type_it = 0; mime_type_it < _tmp5__length1; mime_type_it = mime_type_it + 1) { */
+/*       gchar* _tmp6_; */
+/*       gchar* mime_type = NULL; */
+/*       _tmp6_ = g_strdup (mime_type_collection[mime_type_it]); */
+/*       mime_type = _tmp6_; */
+/*       { */
+/*         const gchar* _tmp7_; */
+/*         _tmp7_ = mime_type; */
+/*         if (!_vala_string_array_contains (supported_mime_types, supported_mime_types_length1, _tmp7_)) { 
*/
+/*           result = FALSE; */
+/*           _g_free0 (mime_type); */
+/*           supported_mime_types = (_vala_array_free (supported_mime_types, supported_mime_types_length1, 
(GDestroyNotify) g_free), NULL); */
+/*           return result; */
+/*         } */
+/*         _g_free0 (mime_type); */
+/*       } */
+/*     } */
+/*   } */
+/*   result = TRUE; */
+/*   supported_mime_types = (_vala_array_free (supported_mime_types, supported_mime_types_length1, 
(GDestroyNotify) g_free), NULL); */
+/*   return result; */
+/* } */
+
+// FIXME static
+void
+retro_core_descriptor_check_libretro_group (RetroCoreDescriptor  *self,
+                                            GError              **error)
+{
+  GError *tmp_error = NULL;
+
+  g_return_if_fail (self != NULL);
+
+  retro_core_descriptor_check_has_required_key (self,
+                                                RETRO_CORE_DESCRIPTOR_LIBRETRO_GROUP,
+                                                RETRO_CORE_DESCRIPTOR_TYPE_KEY,
+                                                &tmp_error);
+  if (G_UNLIKELY (tmp_error != NULL)) {
+    g_propagate_error (error, tmp_error);
+
+    return;
+  }
+
+  retro_core_descriptor_check_has_required_key (self,
+                                                RETRO_CORE_DESCRIPTOR_LIBRETRO_GROUP,
+                                                RETRO_CORE_DESCRIPTOR_NAME_KEY,
+                                                &tmp_error);
+  if (G_UNLIKELY (tmp_error != NULL)) {
+    g_propagate_error (error, tmp_error);
+
+    return;
+  }
+
+  retro_core_descriptor_check_has_required_key (self,
+                                                RETRO_CORE_DESCRIPTOR_LIBRETRO_GROUP,
+                                                RETRO_CORE_DESCRIPTOR_MODULE_KEY,
+                                                &tmp_error);
+  if (G_UNLIKELY (tmp_error != NULL)) {
+    g_propagate_error (error, tmp_error);
+
+    return;
+  }
+
+  retro_core_descriptor_check_has_required_key (self,
+                                                RETRO_CORE_DESCRIPTOR_LIBRETRO_GROUP,
+                                                RETRO_CORE_DESCRIPTOR_LIBRETRO_VERSION_KEY,
+                                                &tmp_error);
+  if (G_UNLIKELY (tmp_error != NULL)) {
+    g_propagate_error (error, tmp_error);
+
+    return;
+  }
+}
+
+// FIXME static
+void
+retro_core_descriptor_check_platform_group (RetroCoreDescriptor  *self,
+                                            const gchar          *group,
+                                            GError              **error)
+{
+  gboolean has_key;
+  gchar **firmwares;
+  gchar **firmware_p;
+  gint firmware_it;
+  gchar *firmware_group;
+  GError *tmp_error = NULL;
+
+  g_return_if_fail (self != NULL);
+  g_return_if_fail (group != NULL);
+
+  retro_core_descriptor_check_has_required_key (self,
+                                                group,
+                                                RETRO_CORE_DESCRIPTOR_PLATFORM_MIME_TYPE_KEY,
+                                                &tmp_error);
+
+  has_key = g_key_file_has_key (self->key_file,
+                                group,
+                                RETRO_CORE_DESCRIPTOR_PLATFORM_FIRMWARES_KEY,
+                                &tmp_error);
+  if (G_UNLIKELY (tmp_error != NULL)) {
+    g_propagate_error (error, tmp_error);
+
+    return;
+  }
+
+  if (!has_key)
+    return;
+
+  // TODO foreach
+
+  firmwares = g_key_file_get_string_list (self->key_file,
+                                          group,
+                                          RETRO_CORE_DESCRIPTOR_PLATFORM_FIRMWARES_KEY,
+                                          NULL,
+                                          &tmp_error);
+  if (G_UNLIKELY (tmp_error != NULL)) {
+    g_propagate_error (error, tmp_error);
+
+    return;
+  }
+
+  for (firmware_p = firmwares; firmware_p != NULL; firmware_p++) {
+    firmware_group = g_strconcat (RETRO_CORE_DESCRIPTOR_FIRMWARE_GROUP_PREFIX, *firmware_p, NULL);
+    if (!g_key_file_has_group (self->key_file, firmware_group)) {
+      g_set_error (error,
+                   RETRO_CORE_DESCRIPTOR_ERROR,
+                   RETRO_CORE_DESCRIPTOR_ERROR_FIRMWARE_NOT_FOUND,
+                   "%s isn't a valid Libretro core descriptor:"
+                   "[%s] mentioned in [%s] not found.",
+                   self->filename,
+                   firmware_group,
+                   group);
+
+      g_free (firmware_group);
+      g_strfreev (firmwares);
+
+      return;
+    }
+
+    g_free (firmware_group);
+  }
+
+  g_strfreev (firmwares);
+}
+
+// FIXME static
+void
+retro_core_descriptor_check_firmware_group (RetroCoreDescriptor  *self,
+                                            const gchar          *group,
+                                            GError              **error)
+{
+  GError *tmp_error = NULL;
+
+  g_return_if_fail (self != NULL);
+  g_return_if_fail (group != NULL);
+
+  retro_core_descriptor_check_has_required_key (self,
+                                                group,
+                                                RETRO_CORE_DESCRIPTOR_FIRMWARE_PATH_KEY,
+                                                &tmp_error);
+  if (G_UNLIKELY (tmp_error != NULL)) {
+    g_propagate_error (error, tmp_error);
+
+    return;
+  }
+
+  retro_core_descriptor_check_has_required_key (self,
+                                                group,
+                                                RETRO_CORE_DESCRIPTOR_FIRMWARE_MANDATORY_KEY,
+                                                &tmp_error);
+  if (G_UNLIKELY (tmp_error != NULL)) {
+    g_propagate_error (error, tmp_error);
+
+    return;
+  }
+}
+
+// FIXME static
+void
+retro_core_descriptor_check_has_required_key (RetroCoreDescriptor  *self,
+                                              const gchar          *group,
+                                              const gchar          *key,
+                                              GError              **error)
+{
+  gboolean has_key;
+  GError *tmp_error = NULL;
+
+  g_return_if_fail (self != NULL);
+  g_return_if_fail (group != NULL);
+  g_return_if_fail (key != NULL);
+
+  has_key = g_key_file_has_key (self->key_file,
+                                RETRO_CORE_DESCRIPTOR_LIBRETRO_GROUP,
+                                RETRO_CORE_DESCRIPTOR_TYPE_KEY,
+                                &tmp_error);
+  if (G_UNLIKELY (tmp_error != NULL)) {
+    g_propagate_error (error, tmp_error);
+
+    return;
+  }
+
+  if (!has_key)
+    g_set_error (error, RETRO_CORE_DESCRIPTOR_ERROR,
+                 RETRO_CORE_DESCRIPTOR_ERROR_REQUIRED_KEY_NOT_FOUND,
+                 "%s isn't a valid Libretro core descriptor: "
+                 "required key %s not found in group [%s].",
+                 self->filename,
+                 key,
+                 group);
+}
+
+
+/* static gpointer _g_key_file_ref0 (gpointer self) { */
+/*   return self ? g_key_file_ref (self) : NULL; */
+/* } */
+
+
+/* static RetroCoreDescriptorPlatform* retro_core_descriptor_platform_construct (GType object_type, 
GKeyFile* key_file, const gchar* platform) { */
+/*   RetroCoreDescriptorPlatform * self = NULL; */
+/*   GKeyFile* _tmp0_; */
+/*   GKeyFile* _tmp1_; */
+/*   const gchar* _tmp2_; */
+/*   gchar* _tmp3_; */
+/*   g_return_val_if_fail (key_file != NULL, NULL); */
+/*   g_return_val_if_fail (platform != NULL, NULL); */
+/*   self = (RetroCoreDescriptorPlatform*) g_object_new (object_type, NULL); */
+/*   _tmp0_ = key_file; */
+/*   _tmp1_ = _g_key_file_ref0 (_tmp0_); */
+/*   _g_key_file_unref0 (self->key_file); */
+/*   self->key_file = _tmp1_; */
+/*   _tmp2_ = platform; */
+/*   _tmp3_ = g_strconcat (RETRO_CORE_DESCRIPTOR_PLATFORM_GROUP_PREFIX, _tmp2_, NULL); */
+/*   _g_free0 (self->priv->group); */
+/*   self->priv->group = _tmp3_; */
+/*   return self; */
+/* } */
+
+
+/* static RetroCoreDescriptorPlatform* retro_core_descriptor_platform_new (GKeyFile* key_file, const gchar* 
platform) { */
+/*   return retro_core_descriptor_platform_construct (RETRO_CORE_DESCRIPTOR_TYPE_PLATFORM, key_file, 
platform); */
+/* } */
+
+
+/* static void retro_core_descriptor_platform_class_init (RetroCoreDescriptorPlatformClass * klass) { */
+/*   retro_core_descriptor_platform_parent_class = g_type_class_peek_parent (klass); */
+/*   g_type_class_add_private (klass, sizeof (RetroCoreDescriptorPlatformPrivate)); */
+/*   G_OBJECT_CLASS (klass)->finalize = retro_core_descriptor_platform_finalize; */
+/* } */
+
+
+/* static void retro_core_descriptor_platform_instance_init (RetroCoreDescriptorPlatform * self) { */
+/*   self->priv = RETRO_CORE_DESCRIPTOR_PLATFORM_GET_PRIVATE (self); */
+/* } */
+
+
+/* static void retro_core_descriptor_platform_finalize (GObject * obj) { */
+/*   RetroCoreDescriptorPlatform * self; */
+/*   self = G_TYPE_CHECK_INSTANCE_CAST (obj, RETRO_CORE_DESCRIPTOR_TYPE_PLATFORM, 
RetroCoreDescriptorPlatform); */
+/*   _g_key_file_unref0 (self->key_file); */
+/*   _g_free0 (self->priv->group); */
+/*   G_OBJECT_CLASS (retro_core_descriptor_platform_parent_class)->finalize (obj); */
+/* } */
+
+
+/* GType retro_core_descriptor_platform_get_type (void) { */
+/*   static volatile gsize retro_core_descriptor_platform_type_id__volatile = 0; */
+/*   if (g_once_init_enter (&retro_core_descriptor_platform_type_id__volatile)) { */
+/*     static const GTypeInfo g_define_type_info = { sizeof (RetroCoreDescriptorPlatformClass), 
(GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) retro_core_descriptor_platform_class_init, 
(GClassFinalizeFunc) NULL, NULL, sizeof (RetroCoreDescriptorPlatform), 0, (GInstanceInitFunc) 
retro_core_descriptor_platform_instance_init, NULL }; */
+/*     GType retro_core_descriptor_platform_type_id; */
+/*     retro_core_descriptor_platform_type_id = g_type_register_static (G_TYPE_OBJECT, 
"RetroCoreDescriptorPlatform", &g_define_type_info, 0); */
+/*     g_once_init_leave (&retro_core_descriptor_platform_type_id__volatile, 
retro_core_descriptor_platform_type_id); */
+/*   } */
+/*   return retro_core_descriptor_platform_type_id__volatile; */
+/* } */
+
+
+/* static void retro_core_descriptor_class_init (RetroCoreDescriptorClass * klass) { */
+/*   retro_core_descriptor_parent_class = g_type_class_peek_parent (klass); */
+/*   g_type_class_add_private (klass, sizeof (RetroCoreDescriptorPrivate)); */
+/*   G_OBJECT_CLASS (klass)->finalize = retro_core_descriptor_finalize; */
+/* } */
+
+
+/* static void retro_core_descriptor_instance_init (RetroCoreDescriptor * self) { */
+/*   self->priv = RETRO_CORE_DESCRIPTOR_GET_PRIVATE (self); */
+/* } */
+
+
+/* static void retro_core_descriptor_finalize (GObject * obj) { */
+/*   RetroCoreDescriptor * self; */
+/*   self = G_TYPE_CHECK_INSTANCE_CAST (obj, RETRO_TYPE_CORE_DESCRIPTOR, RetroCoreDescriptor); */
+/*   _g_free0 (self->filename); */
+/*   _g_key_file_unref0 (self->key_file); */
+/*   G_OBJECT_CLASS (retro_core_descriptor_parent_class)->finalize (obj); */
+/* } */
+
+
+/* GType retro_core_descriptor_get_type (void) { */
+/*   static volatile gsize retro_core_descriptor_type_id__volatile = 0; */
+/*   if (g_once_init_enter (&retro_core_descriptor_type_id__volatile)) { */
+/*     static const GTypeInfo g_define_type_info = { sizeof (RetroCoreDescriptorClass), (GBaseInitFunc) 
NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) retro_core_descriptor_class_init, (GClassFinalizeFunc) NULL, 
NULL, sizeof (RetroCoreDescriptor), 0, (GInstanceInitFunc) retro_core_descriptor_instance_init, NULL }; */
+/*     GType retro_core_descriptor_type_id; */
+/*     retro_core_descriptor_type_id = g_type_register_static (G_TYPE_OBJECT, "RetroCoreDescriptor", 
&g_define_type_info, 0); */
+/*     g_once_init_leave (&retro_core_descriptor_type_id__volatile, retro_core_descriptor_type_id); */
+/*   } */
+/*   return retro_core_descriptor_type_id__volatile; */
+/* } */
+
+
+/* static void _vala_array_destroy (gpointer array, gint array_length, GDestroyNotify destroy_func) { */
+/*   if ((array != NULL) && (destroy_func != NULL)) { */
+/*     int i; */
+/*     for (i = 0; i < array_length; i = i + 1) { */
+/*       if (((gpointer*) array)[i] != NULL) { */
+/*         destroy_func (((gpointer*) array)[i]); */
+/*       } */
+/*     } */
+/*   } */
+/* } */
+
+
+/* static void _vala_array_free (gpointer array, gint array_length, GDestroyNotify destroy_func) { */
+/*   _vala_array_destroy (array, array_length, destroy_func); */
+/*   g_free (array); */
+/* } */
+
+
+
diff --git a/retro-gtk/retro-core-descriptor.h b/retro-gtk/retro-core-descriptor.h
new file mode 100644
index 0000000..c675b9b
--- /dev/null
+++ b/retro-gtk/retro-core-descriptor.h
@@ -0,0 +1,191 @@
+// This file is part of retro-gtk. License: GPL-3.0+.
+
+#ifndef RETRO_CORE_DESCRIPTOR_H
+#define RETRO_CORE_DESCRIPTOR_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define RETRO_TYPE_CORE_DESCRIPTOR (retro_core_descriptor_get_type())
+
+G_DECLARE_FINAL_TYPE (RetroCoreDescriptor, retro_core_descriptor, RETRO, CORE_DESCRIPTOR, GObject)
+
+RetroCoreDescriptor *retro_core_descriptor_new (void);
+
+G_END_DECLS
+
+#endif /* RETRO_CORE_DESCRIPTOR_H */
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+public class Retro.CoreDescriptor : Object {
+       public class Platform : Object {
+
+               private KeyFile key_file;
+               private string group;
+
+               private Platform (KeyFile key_file, string platform) {
+                       this.key_file = key_file;
+                       group = PLATFORM_GROUP_PREFIX + platform;
+               }
+       }
+
+       private string filename;
+       private KeyFile key_file;
+
+       public CoreDescriptor (string filename) throws Error, KeyFileError, FileError {
+               this.filename = filename;
+               key_file = new KeyFile ();
+               key_file.load_from_file (filename, KeyFileFlags.NONE);
+
+               check_libretro_group ();
+
+               foreach (var group in key_file.get_groups ()) {
+                       if (group.has_prefix (PLATFORM_GROUP_PREFIX))
+                               check_platform_group (group);
+                       else if (group.has_prefix (FIRMWARE_GROUP_PREFIX))
+                               check_firmware_group (group);
+               }
+       }
+
+       public bool has_icon () throws KeyFileError {
+               return key_file.has_key (LIBRETRO_GROUP, ICON_KEY);
+       }
+
+       public string get_uri () {
+               var file = File.new_for_path (filename);
+
+               return file.get_uri ();
+       }
+
+       public string get_id () {
+               return Path.get_basename (filename);
+       }
+
+       public bool get_is_game () throws KeyFileError {
+               return key_file.get_string (LIBRETRO_GROUP, TYPE_KEY) == TYPE_GAME;
+       }
+
+       public bool get_is_emulator () throws KeyFileError {
+               return key_file.get_string (LIBRETRO_GROUP, TYPE_KEY) == TYPE_EMULATOR;
+       }
+
+       public string get_name () throws KeyFileError {
+               return key_file.get_string (LIBRETRO_GROUP, NAME_KEY);
+       }
+
+       public GLib.Icon get_icon () throws KeyFileError {
+               var icon_name = key_file.get_string (LIBRETRO_GROUP, ICON_KEY);
+
+               return new ThemedIcon (icon_name);
+       }
+
+       public string get_module () throws KeyFileError {
+               return key_file.get_string (LIBRETRO_GROUP, MODULE_KEY);
+       }
+
+       public File? get_module_file () throws KeyFileError {
+               var file = File.new_for_path (filename);
+               var dir = file.get_parent ();
+               if (dir == null)
+                       return null;
+
+               var module = get_module ();
+               var module_file = dir.get_child (module);
+               if (!module_file.query_exists ())
+                       return null;
+
+               return module_file;
+       }
+
+       public bool has_platform (string platform) {
+               return key_file.has_group (PLATFORM_GROUP_PREFIX + platform);
+       }
+
+       public bool has_firmwares (string platform) throws KeyFileError {
+               return key_file.has_key (PLATFORM_GROUP_PREFIX + platform, PLATFORM_FIRMWARES_KEY);
+       }
+
+       public bool has_firmware_md5 (string firmware) throws KeyFileError {
+               return key_file.has_key (FIRMWARE_GROUP_PREFIX + firmware, FIRMWARE_MD5_KEY);
+       }
+
+       public bool has_firmware_sha512 (string firmware) throws KeyFileError {
+               return key_file.has_key (FIRMWARE_GROUP_PREFIX + firmware, FIRMWARE_SHA512_KEY);
+       }
+
+       public string[] get_mime_type (string platform) throws KeyFileError {
+               return key_file.get_string_list (PLATFORM_GROUP_PREFIX + platform, PLATFORM_MIME_TYPE_KEY);
+       }
+
+       public string[] get_firmwares (string platform) throws KeyFileError {
+               return key_file.get_string_list (PLATFORM_GROUP_PREFIX + platform, PLATFORM_FIRMWARES_KEY);
+       }
+
+       public string get_firmware_path (string firmware) throws KeyFileError {
+               return key_file.get_string (FIRMWARE_GROUP_PREFIX + firmware, FIRMWARE_PATH_KEY);
+       }
+
+       public string get_firmware_md5 (string firmware) throws KeyFileError {
+               return key_file.get_string (FIRMWARE_GROUP_PREFIX + firmware, FIRMWARE_MD5_KEY);
+       }
+
+       public string get_firmware_sha512 (string firmware) throws KeyFileError {
+               return key_file.get_string (FIRMWARE_GROUP_PREFIX + firmware, FIRMWARE_SHA512_KEY);
+       }
+
+       public bool get_is_firmware_mandatory (string firmware) throws KeyFileError {
+               return key_file.get_boolean (FIRMWARE_GROUP_PREFIX + firmware, FIRMWARE_MANDATORY_KEY);
+       }
+
+       public bool get_platform_supports_mime_types (string platform, string[] mime_types) throws 
KeyFileError {
+               var supported_mime_types = get_mime_type (platform);
+               foreach (var mime_type in mime_types)
+                       if (!(mime_type in supported_mime_types))
+                               return false;
+
+               return true;
+       }
+
+       private void check_libretro_group () throws CoreDescriptorError, KeyFileError {
+               check_has_required_key (LIBRETRO_GROUP, TYPE_KEY);
+               check_has_required_key (LIBRETRO_GROUP, NAME_KEY);
+               check_has_required_key (LIBRETRO_GROUP, MODULE_KEY);
+               check_has_required_key (LIBRETRO_GROUP, LIBRETRO_VERSION_KEY);
+       }
+
+       private void check_platform_group (string group) throws CoreDescriptorError, KeyFileError {
+               check_has_required_key (group, PLATFORM_MIME_TYPE_KEY);
+               if (key_file.has_key (group, PLATFORM_FIRMWARES_KEY))
+                       foreach (var firmware in key_file.get_string_list (group, PLATFORM_FIRMWARES_KEY))
+                               if (!key_file.has_group (FIRMWARE_GROUP_PREFIX + firmware))
+                                       throw new CoreDescriptorError.FIRMWARE_NOT_FOUND ("%s isn't a valid 
Libretro core descriptor: [%s] mentioned in [%s] not found.", filename, FIRMWARE_GROUP_PREFIX + firmware, 
group);
+       }
+
+       private void check_firmware_group (string group) throws CoreDescriptorError, KeyFileError {
+               check_has_required_key (group, FIRMWARE_PATH_KEY);
+               check_has_required_key (group, FIRMWARE_MANDATORY_KEY);
+       }
+
+       private void check_has_required_key (string group, string key) throws CoreDescriptorError, 
KeyFileError {
+               if (!key_file.has_key (LIBRETRO_GROUP, TYPE_KEY))
+                       throw new CoreDescriptorError.REQUIRED_KEY_NOT_FOUND ("%s isn't a valid Libretro core 
descriptor: required key %s not found in group [%s].", filename, key, group);
+       }
+}
+
diff --git a/retro-gtk/retro-core-descriptor.vala b/retro-gtk/retro-core-descriptor.vala
index a78e380..3cbed33 100644
--- a/retro-gtk/retro-core-descriptor.vala
+++ b/retro-gtk/retro-core-descriptor.vala
@@ -33,8 +33,8 @@ public class Retro.CoreDescriptor : Object {
        private const string TYPE_GAME = "Game";
        private const string TYPE_EMULATOR = "Emulator";
 
-       private string filename;
-       private KeyFile key_file;
+       internal string filename;
+       internal KeyFile key_file;
 
        public CoreDescriptor (string filename) throws Error, KeyFileError, FileError {
                this.filename = filename;
@@ -150,29 +150,9 @@ public class Retro.CoreDescriptor : Object {
                return true;
        }
 
-       private void check_libretro_group () throws CoreDescriptorError, KeyFileError {
-               check_has_required_key (LIBRETRO_GROUP, TYPE_KEY);
-               check_has_required_key (LIBRETRO_GROUP, NAME_KEY);
-               check_has_required_key (LIBRETRO_GROUP, MODULE_KEY);
-               check_has_required_key (LIBRETRO_GROUP, LIBRETRO_VERSION_KEY);
-       }
-
-       private void check_platform_group (string group) throws CoreDescriptorError, KeyFileError {
-               check_has_required_key (group, PLATFORM_MIME_TYPE_KEY);
-               if (key_file.has_key (group, PLATFORM_FIRMWARES_KEY))
-                       foreach (var firmware in key_file.get_string_list (group, PLATFORM_FIRMWARES_KEY))
-                               if (!key_file.has_group (FIRMWARE_GROUP_PREFIX + firmware))
-                                       throw new CoreDescriptorError.FIRMWARE_NOT_FOUND ("%s isn't a valid 
Libretro core descriptor: [%s] mentioned in [%s] not found.", filename, FIRMWARE_GROUP_PREFIX + firmware, 
group);
-       }
-
-       private void check_firmware_group (string group) throws CoreDescriptorError, KeyFileError {
-               check_has_required_key (group, FIRMWARE_PATH_KEY);
-               check_has_required_key (group, FIRMWARE_MANDATORY_KEY);
-       }
-
-       private void check_has_required_key (string group, string key) throws CoreDescriptorError, 
KeyFileError {
-               if (!key_file.has_key (LIBRETRO_GROUP, TYPE_KEY))
-                       throw new CoreDescriptorError.REQUIRED_KEY_NOT_FOUND ("%s isn't a valid Libretro core 
descriptor: required key %s not found in group [%s].", filename, key, group);
-       }
+       private extern void check_libretro_group () throws CoreDescriptorError, KeyFileError;
+       private extern void check_platform_group (string group) throws CoreDescriptorError, KeyFileError;
+       private extern void check_firmware_group (string group) throws CoreDescriptorError, KeyFileError;
+       private extern void check_has_required_key (string group, string key) throws CoreDescriptorError, 
KeyFileError;
 }
 
diff --git a/retro-gtk/vapi/retro-gtk-c.vapi b/retro-gtk/vapi/retro-gtk-c.vapi
index bf0ea78..a3e78a6 100644
--- a/retro-gtk/vapi/retro-gtk-c.vapi
+++ b/retro-gtk/vapi/retro-gtk-c.vapi
@@ -1,4 +1,40 @@
 // This file is part of retro-gtk. License: GPL-3.0+.
+// This file is part of retro-gtk. License: GPL-3.0+.
+
+//public class Retro.CoreDescriptor : Object {
+//     public class Platform : Object {
+
+//             private KeyFile key_file;
+//             private string group;
+
+//             private Platform (KeyFile key_file, string platform) {
+//                     this.key_file = key_file;
+//                     group = PLATFORM_GROUP_PREFIX + platform;
+//             }
+//     }
+
+//     public CoreDescriptor (string filename) throws Error, KeyFileError, FileError;
+//     public bool has_icon () throws KeyFileError {
+//     public string get_uri () {
+//     public string get_id () {
+//     public bool get_is_game () throws KeyFileError {
+//     public bool get_is_emulator () throws KeyFileError {
+//     public string get_name () throws KeyFileError {
+//     public GLib.Icon get_icon () throws KeyFileError {
+//     public string get_module () throws KeyFileError {
+//     public File? get_module_file () throws KeyFileError {
+//     public bool has_platform (string platform) {
+//     public bool has_firmwares (string platform) throws KeyFileError {
+//     public bool has_firmware_md5 (string firmware) throws KeyFileError {
+//     public bool has_firmware_sha512 (string firmware) throws KeyFileError {
+//     public string[] get_mime_type (string platform) throws KeyFileError {
+//     public string[] get_firmwares (string platform) throws KeyFileError {
+//     public string get_firmware_path (string firmware) throws KeyFileError {
+//     public string get_firmware_md5 (string firmware) throws KeyFileError {
+//     public string get_firmware_sha512 (string firmware) throws KeyFileError {
+//     public bool get_is_firmware_mandatory (string firmware) throws KeyFileError {
+//     public bool get_platform_supports_mime_types (string platform, string[] mime_types) throws 
KeyFileError {
+//}
 
 [CCode (cheader_filename = "retro-device-type.h")]
 public enum Retro.DeviceType {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]