[gnome-games] mega-drive: Support Mega-CD games



commit 3244b7c8b42493b39ada4f84c2b6dd3deb1f1e07
Author: Adrien Plazas <kekun plazas laposte net>
Date:   Wed Aug 3 11:08:38 2016 +0200

    mega-drive: Support Mega-CD games
    
    https://bugzilla.gnome.org/show_bug.cgi?id=769474

 plugins/mega-drive/data/mega-drive.plugin     |    2 +-
 plugins/mega-drive/src/mega-drive-header.vala |    4 ++
 plugins/mega-drive/src/mega-drive-plugin.vala |   54 +++++++++++++++++++++++++
 3 files changed, 59 insertions(+), 1 deletions(-)
---
diff --git a/plugins/mega-drive/data/mega-drive.plugin b/plugins/mega-drive/data/mega-drive.plugin
index 59ae3a2..90c55b2 100644
--- a/plugins/mega-drive/data/mega-drive.plugin
+++ b/plugins/mega-drive/data/mega-drive.plugin
@@ -1,6 +1,6 @@
 [Plugin]
 Module=libgames-mega-drive-plugin
 Name=Mega Drive Plugin
-Description=Provides support for Mega Drive/Genesis games.
+Description=Provides support for Mega Drive/Genesis, Mega-CD/Sega CD and 32X games.
 Authors=Adrien Plazas <kekun plazas laposte net>
 Copyright=Copyright © 2016 Adrien Plazas
diff --git a/plugins/mega-drive/src/mega-drive-header.vala b/plugins/mega-drive/src/mega-drive-header.vala
index 3ce8082..d823a59 100644
--- a/plugins/mega-drive/src/mega-drive-header.vala
+++ b/plugins/mega-drive/src/mega-drive-header.vala
@@ -2,6 +2,8 @@
 
 // Documentation: https://en.wikibooks.org/wiki/Genesis_Programming
 private class Games.MegaDriveHeader : Object {
+       public const size_t HEADER_LENGTH = 0x200;
+
        private const size_t[] POSSIBLE_HEADER_OFFSETS = { 0x0, 0x10 };
 
        private const size_t CD_OFFSET = 0x0;
@@ -125,4 +127,6 @@ private class Games.MegaDriveHeader : Object {
 
 errordomain Games.MegaDriveError {
        INVALID_HEADER,
+       INVALID_CUE_SHEET,
+       INVALID_FILE_TYPE,
 }
diff --git a/plugins/mega-drive/src/mega-drive-plugin.vala b/plugins/mega-drive/src/mega-drive-plugin.vala
index 389937a..7311553 100644
--- a/plugins/mega-drive/src/mega-drive-plugin.vala
+++ b/plugins/mega-drive/src/mega-drive-plugin.vala
@@ -10,17 +10,24 @@ private class Games.MegaDrivePlugin : Object, Plugin {
        private const string PICO_PREFIX = "sega-pico";
        private const string PICO_MIME_TYPE = "application/x-sega-pico-rom";
 
+       private const string MEGA_CD_PREFIX = "mega-cd";
+       private const string CUE_MIME_TYPE = "application/x-cue";
+       private const string MEGA_CD_MIME_TYPE = "application/x-sega-cd-rom";
+
        private const string MODULE_BASENAME = "libretro-mega-drive.so";
        private const bool SUPPORTS_SNAPSHOTTING = true;
 
        public GameSource get_game_source () throws Error {
                var game_uri_adapter = new GenericSyncGameUriAdapter (game_for_uri);
+               var cd_game_uri_adapter = new GenericSyncGameUriAdapter (cd_game_for_uri);
                var mega_drive_query = new MimeTypeTrackerQuery (MEGA_DRIVE_MIME_TYPE, game_uri_adapter);
                var 32x_query = new MimeTypeTrackerQuery (32X_MIME_TYPE, game_uri_adapter);
+               var mega_cd_query = new MimeTypeTrackerQuery (CUE_MIME_TYPE, cd_game_uri_adapter);
                var connection = Tracker.Sparql.Connection.@get ();
                var source = new TrackerGameSource (connection);
                source.add_query (mega_drive_query);
                source.add_query (32x_query);
+               source.add_query (mega_cd_query);
 
                return source;
        }
@@ -58,6 +65,53 @@ private class Games.MegaDrivePlugin : Object, Plugin {
 
                return new GenericGame (title, icon, cover, runner);
        }
+
+       private static Game cd_game_for_uri (string uri) throws Error {
+               var file = File.new_for_uri (uri);
+               var cue = new CueSheet (file);
+               var bin_file = get_binary_file (cue);
+
+               var header = new MegaDriveHeader (bin_file);
+               header.check_validity ();
+
+               string[] mime_types;
+               if (header.is_mega_drive ())
+                       mime_types = { CUE_MIME_TYPE, MEGA_CD_MIME_TYPE };
+               else if (header.is_32x ())
+                       mime_types = { CUE_MIME_TYPE, MEGA_CD_MIME_TYPE, 32X_MIME_TYPE };
+               else
+                       assert_not_reached ();
+
+               var bin_uri = bin_file.get_uri ();
+               var header_offset = header.get_offset ();
+               var uid = new FingerprintUid.for_chunk (bin_uri, MEGA_CD_PREFIX, header_offset, 
MegaDriveHeader.HEADER_LENGTH);
+               var title = new FilenameTitle (uri);
+               var icon = new DummyIcon ();
+               var media = new GriloMedia (title, MEGA_CD_MIME_TYPE);
+               var cover = new GriloCover (media, uid);
+               var runner = new RetroRunner.with_mime_types (uri, uid, mime_types, MODULE_BASENAME, 
SUPPORTS_SNAPSHOTTING);
+
+               return new GenericGame (title, icon, cover, runner);
+       }
+
+       private static File get_binary_file (CueSheet cue) throws Error {
+               if (cue.tracks_number == 0)
+                       throw new MegaDriveError.INVALID_CUE_SHEET (_("The file '%s' doesn't have a track."), 
cue.file.get_uri ());
+
+               var track = cue.get_track (0);
+               var file = track.file;
+
+               if (file.file_format != CueSheetFileFormat.BINARY && file.file_format != 
CueSheetFileFormat.UNKNOWN)
+                       throw new MegaDriveError.INVALID_CUE_SHEET (_("The file '%s' doesn't have a valid 
binary file format."), cue.file.get_uri ());
+
+               if (!track.track_mode.is_mode1 ())
+                       throw new MegaDriveError.INVALID_CUE_SHEET (_("The file '%s' doesn't have a valid 
track mode for track %d."), cue.file.get_uri (), track.track_number);
+
+               var header = new MegaDriveHeader (file.file);
+               header.check_validity ();
+
+               return file.file;
+       }
 }
 
 [ModuleInit]


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