[gnome-games] playstation: Add DiscImage
- From: Adrien Plazas <aplazas src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-games] playstation: Add DiscImage
- Date: Sat, 15 Jul 2017 09:49:17 +0000 (UTC)
commit 3a28c93d5ab53f7083108d78902bda40677d8bc3
Author: Adrien Plazas <kekun plazas laposte net>
Date: Sat Jul 15 11:34:34 2017 +0200
playstation: Add DiscImage
This will be used in the next commit to parse PlayStation disc images.
https://bugzilla.gnome.org/show_bug.cgi?id=775255
plugins/playstation/src/Makefile.am | 1 +
plugins/playstation/src/disc-image.c | 227 ++++++++++++++++++++++++++++++++++
plugins/playstation/src/disc-image.h | 66 ++++++++++
3 files changed, 294 insertions(+), 0 deletions(-)
---
diff --git a/plugins/playstation/src/Makefile.am b/plugins/playstation/src/Makefile.am
index 418d093..6d82754 100644
--- a/plugins/playstation/src/Makefile.am
+++ b/plugins/playstation/src/Makefile.am
@@ -37,6 +37,7 @@ libgames_playstation_plugin_la_DEPENDENCIES = \
libgames_playstation_plugin_la_SOURCES = \
$(BUILT_SOURCES) \
disc-file-info.c \
+ disc-image.c \
disc-image-time.c \
playstation-error.vala \
playstation-game-factory.vala \
diff --git a/plugins/playstation/src/disc-image.c b/plugins/playstation/src/disc-image.c
new file mode 100644
index 0000000..bb25b2d
--- /dev/null
+++ b/plugins/playstation/src/disc-image.c
@@ -0,0 +1,227 @@
+// This file is part of GNOME Games. License: GPL-3.0+.
+
+#include "disc-image.h"
+
+#include <string.h>
+#include "disc-file-info.h"
+#include "disc-image-time.h"
+
+/* Private */
+
+#define GAMES_DISC_IMAGE_FRAME_SIZE 2352
+#define GAMES_DISC_IMAGE_FRAME_HEADER_SIZE 12
+
+typedef struct {
+ const gchar *filename;
+ GamesDiscImageTime *time;
+ gboolean is_dir;
+ gboolean found;
+} GetFileData;
+
+static gboolean
+get_file_co (GamesDiscFileInfo *file_info,
+ gpointer user_data)
+{
+ GetFileData *data = (GetFileData *) user_data;
+
+ if (games_disc_file_info_is_directory (file_info)) {
+ if (g_ascii_strncasecmp (games_disc_file_info_access_name (file_info), data->filename,
file_info->name_length) == 0) {
+ if (data->filename[file_info->name_length] != '\\')
+ return TRUE;
+
+ data->filename += file_info->name_length + 1;
+
+ games_disc_image_time_set_from_time_reference (data->time, file_info->extent);
+ data->is_dir = TRUE;
+ data->found = TRUE;
+
+ return FALSE;
+ }
+ }
+ else {
+ if (g_ascii_strncasecmp (games_disc_file_info_access_name (file_info), data->filename, strlen
(data->filename)) == 0) {
+ games_disc_image_time_set_from_time_reference (data->time, file_info->extent);
+ data->is_dir = FALSE;
+ data->found = TRUE;
+
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+/* Public */
+
+void
+games_disc_image_open (GamesDiscImage *disc,
+ const char *filename,
+ GError **error)
+{
+ GFile *file;
+ GError *tmp_error = NULL;
+
+ file = g_file_new_for_path (filename);
+ g_clear_object (&disc->input_stream);
+ disc->input_stream = g_file_read (file, NULL, &tmp_error);
+ if (tmp_error != NULL) {
+ g_propagate_error (error, tmp_error);
+ g_object_unref(file);
+
+ return;
+ }
+
+ g_object_unref(file);
+}
+
+void
+games_disc_image_dispose (GamesDiscImage *disc)
+{
+ g_clear_object (&disc->input_stream);
+}
+
+gboolean
+games_disc_image_read_frame (GamesDiscImage *disc,
+ const GamesDiscImageTime *time,
+ GamesDiscFrame *frame,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gssize read;
+ gsize offset;
+ GError *tmp_error = NULL;
+
+ g_return_val_if_fail (disc != NULL, FALSE);
+ g_return_val_if_fail (time != NULL, FALSE);
+ g_return_val_if_fail (frame != NULL, FALSE);
+
+ // FIXME Check the multiplication doesn't overflow.
+ offset = games_disc_image_time_get_sector (time) * sizeof (GamesDiscFrame);
+ g_seekable_seek (G_SEEKABLE (disc->input_stream),
+ offset, G_SEEK_SET,
+ cancellable, &tmp_error);
+ if (tmp_error != NULL) {
+ g_propagate_error (error, tmp_error);
+
+ return FALSE;
+ }
+
+ read = g_input_stream_read (G_INPUT_STREAM (disc->input_stream),
+ frame, sizeof (GamesDiscFrame),
+ cancellable, &tmp_error);
+ if (tmp_error != NULL) {
+ g_propagate_error (error, tmp_error);
+
+ return FALSE;
+ }
+
+ return read == sizeof (GamesDiscFrame);
+}
+
+gboolean
+games_disc_image_read_directory (GamesDiscImage *disc,
+ GamesDiscImageTime *time,
+ guint8 *dst,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gssize read;
+ gint sector;
+ GError *tmp_error = NULL;
+
+ sector = games_disc_image_time_get_sector(time);
+ g_seekable_seek (G_SEEKABLE (disc->input_stream),
+ sector * GAMES_DISC_IMAGE_FRAME_SIZE + GAMES_DISC_IMAGE_FRAME_HEADER_SIZE + 12,
+ G_SEEK_SET, cancellable, &tmp_error);
+ if (tmp_error != NULL) {
+ g_propagate_error (error, tmp_error);
+
+ return FALSE;
+ }
+
+ read = g_input_stream_read (G_INPUT_STREAM (disc->input_stream),
+ dst, 2048,
+ cancellable, &tmp_error);
+ if (tmp_error != NULL) {
+ g_propagate_error (error, tmp_error);
+
+ return FALSE;
+ }
+
+ if (read == -1)
+ return FALSE;
+
+ games_disc_image_time_increment (time);
+
+ sector = games_disc_image_time_get_sector(time);
+ g_seekable_seek (G_SEEKABLE (disc->input_stream),
+ sector * GAMES_DISC_IMAGE_FRAME_SIZE + GAMES_DISC_IMAGE_FRAME_HEADER_SIZE + 12,
+ G_SEEK_SET, cancellable, &tmp_error);
+ if (tmp_error != NULL) {
+ g_propagate_error (error, tmp_error);
+
+ return FALSE;
+ }
+
+ read = g_input_stream_read (G_INPUT_STREAM (disc->input_stream),
+ dst + 2048, 2048,
+ cancellable, &tmp_error);
+ if (tmp_error != NULL) {
+ g_propagate_error (error, tmp_error);
+
+ return FALSE;
+ }
+
+ if (read == -1)
+ return FALSE;
+
+ return TRUE;
+}
+
+gboolean
+games_disc_image_get_file (GamesDiscImage *disc,
+ GamesDiscFileInfo *file_info,
+ const gchar *filename,
+ GamesDiscImageTime *time,
+ GCancellable *cancellable,
+ GError **error)
+{
+ guint8 ddir[4096];
+ GetFileData data = { 0 };
+ gboolean success;
+ GError *tmp_error = NULL;
+
+ g_return_val_if_fail (filename != NULL, FALSE);
+
+ data.filename = filename;
+ data.time = time;
+ data.is_dir = TRUE;
+ data.found = FALSE;
+
+ while (data.is_dir) {
+ data.filename = filename;
+ data.time = time;
+ data.is_dir = FALSE;
+ data.found = FALSE;
+
+ games_disc_file_info_foreach_file (file_info, 4096, get_file_co, &data);
+
+ if (data.found && data.is_dir) {
+ success = games_disc_image_read_directory (disc, time, ddir, cancellable, &tmp_error);
+ if (tmp_error != NULL) {
+ g_propagate_error (error, tmp_error);
+
+ return FALSE;
+ }
+
+ if (!success)
+ return FALSE;
+
+ file_info = (GamesDiscFileInfo *) ddir;
+
+ break; // Parse the sub directory.
+ }
+ }
+
+ return data.found;
+}
diff --git a/plugins/playstation/src/disc-image.h b/plugins/playstation/src/disc-image.h
new file mode 100644
index 0000000..40699a4
--- /dev/null
+++ b/plugins/playstation/src/disc-image.h
@@ -0,0 +1,66 @@
+// This file is part of GNOME Games. License: GPL-3.0+.
+
+#ifndef DISC_IMAGE_H
+#define DISC_IMAGE_H
+
+#include <gio/gio.h>
+#include <glib.h>
+
+#include "disc-file-info.h"
+#include "disc-image-time.h"
+
+G_BEGIN_DECLS
+
+typedef struct _GamesDiscFrameMode1 GamesDiscFrameMode1;
+
+struct _GamesDiscFrameMode1 {
+ guint8 synchronization[12];
+ guint8 header[12];
+ guint8 content[2048];
+ guint8 error_correction_code[280];
+};
+
+typedef struct _GamesDiscFrameMode2 GamesDiscFrameMode2;
+
+struct _GamesDiscFrameMode2 {
+ guint8 synchronization[12];
+ guint8 content[2340];
+};
+
+typedef union _GamesDiscFrame GamesDiscFrame;
+
+union _GamesDiscFrame {
+ GamesDiscFrameMode1 mode1;
+ GamesDiscFrameMode2 mode2;
+};
+
+typedef struct _GamesDiscImage GamesDiscImage;
+
+struct _GamesDiscImage {
+ GFileInputStream *input_stream;
+};
+
+void games_disc_image_open (GamesDiscImage *disc,
+ const char *filename,
+ GError **error);
+void games_disc_image_dispose (GamesDiscImage *disc);
+gboolean games_disc_image_read_frame (GamesDiscImage *disc,
+ const GamesDiscImageTime *time,
+ GamesDiscFrame *frame,
+ GCancellable *cancellable,
+ GError **error);
+gboolean games_disc_image_read_directory (GamesDiscImage *disc,
+ GamesDiscImageTime *time,
+ guint8 *dst,
+ GCancellable *cancellable,
+ GError **error);
+gboolean games_disc_image_get_file (GamesDiscImage *disc,
+ GamesDiscFileInfo *file_info,
+ const gchar *filename,
+ GamesDiscImageTime *time,
+ GCancellable *cancellable,
+ GError **error);
+
+G_END_DECLS
+
+#endif /* DISC_IMAGE_H */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]