libextractor

GNU libextractor
Log | Files | Refs | Submodules | README | LICENSE

sid_extractor.c (5576B)


      1 /*
      2  * This file is part of libextractor.
      3  * Copyright (C) 2006, 2007, 2012 Vidyut Samanta and Christian Grothoff
      4  *
      5  * libextractor is free software; you can redistribute it and/or modify
      6  * it under the terms of the GNU General Public License as published
      7  * by the Free Software Foundation; either version 3, or (at your
      8  * option) any later version.
      9  *
     10  * libextractor is distributed in the hope that it will be useful, but
     11  * WITHOUT ANY WARRANTY; without even the implied warranty of
     12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13  * General Public License for more details.
     14  *
     15  * You should have received a copy of the GNU General Public License
     16  * along with libextractor; see the file COPYING.  If not, write to the
     17  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     18  * Boston, MA 02110-1301, USA.
     19  *
     20  */
     21 /**
     22  * @file plugins/sid_extractor.c
     23  * @brief plugin to support Scream Tracker (S3M) files
     24  * @author Toni Ruottu
     25  * @author Christian Grothoff
     26  */
     27 #include "platform.h"
     28 #include "extractor.h"
     29 
     30 
     31 /* SID flags */
     32 #define MUSPLAYER_FLAG   0x01
     33 #define PLAYSID_FLAG     0x02
     34 #define PAL_FLAG         0x04
     35 #define NTSC_FLAG        0x08
     36 #define MOS6581_FLAG     0x10
     37 #define MOS8580_FLAG     0x20
     38 
     39 /**
     40  * A "SID word".
     41  */
     42 typedef char sidwrd[2];
     43 
     44 /**
     45  * A "SID long".
     46  */
     47 typedef char sidlongwrd[4];
     48 
     49 /**
     50  * Header of a SID file.
     51  */
     52 struct header
     53 {
     54   /**
     55    * Magic string.
     56    */
     57   char magicid[4];
     58 
     59   /**
     60    * Version number.
     61    */
     62   sidwrd sidversion;
     63 
     64   /**
     65    * Unknown.
     66    */
     67   sidwrd dataoffset;
     68 
     69   /**
     70    * Unknown.
     71    */
     72   sidwrd loadaddr;
     73 
     74   /**
     75    * Unknown.
     76    */
     77   sidwrd initaddr;
     78 
     79   /**
     80    * Unknown.
     81    */
     82   sidwrd playaddr;
     83 
     84   /**
     85    * Number of songs in file.
     86    */
     87   sidwrd songs;
     88 
     89   /**
     90    * Starting song.
     91    */
     92   sidwrd firstsong;
     93 
     94   /**
     95    * Unknown.
     96    */
     97   sidlongwrd speed;
     98 
     99   /**
    100    * Title of the album.
    101    */
    102   char title[32];
    103 
    104   /**
    105    * Name of the artist.
    106    */
    107   char artist[32];
    108 
    109   /**
    110    * Copyright information.
    111    */
    112   char copyright[32];
    113 
    114   /* version 2 specific fields start */
    115 
    116   /**
    117    * Flags
    118    */
    119   sidwrd flags;
    120 
    121   /**
    122    * Unknown.
    123    */
    124   char startpage;
    125 
    126   /**
    127    * Unknown.
    128    */
    129   char pagelength;
    130 
    131   /**
    132    * Unknown.
    133    */
    134   sidwrd reserved;
    135 };
    136 
    137 
    138 /**
    139  * Convert a 'sidword' to an integer.
    140  *
    141  * @param data the sidword
    142  * @return corresponding integer value
    143  */
    144 static int
    145 sidword (const sidwrd data)
    146 {
    147   return (unsigned char) data[0] * 0x100 + (unsigned char) data[1];
    148 }
    149 
    150 
    151 /**
    152  * Give metadata to LE; return if 'proc' returns non-zero.
    153  *
    154  * @param s metadata value as UTF8
    155  * @param t metadata type to use
    156  */
    157 #define ADD(s,t) do { if (0 != ec->proc (ec->cls, "sid", t, \
    158                                          EXTRACTOR_METAFORMAT_UTF8, \
    159                                          "text/plain", s, strlen (s) \
    160                                          + 1)) return; \
    161 } while (0)
    162 
    163 
    164 /**
    165  * Extract metadata from SID files.
    166  *
    167  * @param ec extraction context
    168  */
    169 void
    170 EXTRACTOR_sid_extract_method (struct EXTRACTOR_ExtractContext *ec)
    171 {
    172   unsigned int flags;
    173   int version;
    174   char album[33];
    175   char artist[33];
    176   char copyright[33];
    177   char songs[32];
    178   char startingsong[32];
    179   char sidversion[32];
    180   const struct header *head;
    181   void *data;
    182 
    183   if ((ssize_t) sizeof (struct header) >
    184       ec->read (ec->cls,
    185                 &data,
    186                 sizeof (struct header)))
    187     return;
    188   head = data;
    189 
    190   /* Check "magic" id bytes */
    191   if ( (0 != memcmp (head->magicid, "PSID", 4)) &&
    192        (0 != memcmp (head->magicid, "RSID", 4)) )
    193     return;
    194 
    195   /* Mime-type */
    196   ADD ("audio/prs.sid", EXTRACTOR_METATYPE_MIMETYPE);
    197 
    198   /* Version of SID format */
    199   version = sidword (head->sidversion);
    200   snprintf (sidversion,
    201             sizeof (sidversion),
    202             "%d",
    203             version);
    204   ADD (sidversion, EXTRACTOR_METATYPE_FORMAT_VERSION);
    205 
    206   /* Get song count */
    207   snprintf (songs,
    208             sizeof (songs),
    209             "%d", sidword (head->songs));
    210   ADD (songs, EXTRACTOR_METATYPE_SONG_COUNT);
    211 
    212   /* Get number of the first song to be played */
    213   snprintf (startingsong,
    214             sizeof (startingsong),
    215             "%d",
    216             sidword (head->firstsong));
    217   ADD (startingsong, EXTRACTOR_METATYPE_STARTING_SONG);
    218 
    219   /* name, artist, copyright fields */
    220   memcpy (&album, head->title, 32);
    221   album[32] = '\0';
    222   ADD (album, EXTRACTOR_METATYPE_ALBUM);
    223 
    224   memcpy (&artist, head->artist, 32);
    225   artist[32] = '\0';
    226   ADD (artist, EXTRACTOR_METATYPE_ARTIST);
    227 
    228   memcpy (&copyright, head->copyright, 32);
    229   copyright[32] = '\0';
    230   ADD (copyright, EXTRACTOR_METATYPE_COPYRIGHT);
    231 
    232   if (version < 2)
    233     return;
    234 
    235   /* Version 2 specific options follow
    236    *
    237    * Note: Had some troubles understanding specification
    238    * on the flags in version 2. I hope this is correct.
    239    */flags = sidword (head->flags);
    240   /* MUS data */
    241   if (0 != (flags & MUSPLAYER_FLAG))
    242     ADD ("Compute!'s Sidplayer", EXTRACTOR_METATYPE_CREATED_BY_SOFTWARE);
    243 
    244   /* PlaySID data */
    245   if (0 != (flags & PLAYSID_FLAG))
    246     ADD ("PlaySID", EXTRACTOR_METATYPE_CREATED_BY_SOFTWARE);
    247 
    248 
    249   /* PAL or NTSC */
    250   if (0 != (flags & NTSC_FLAG))
    251     ADD ("PAL/NTSC", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM);
    252   else if (0 != (flags & PAL_FLAG))
    253     ADD ("PAL", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM);
    254 
    255   /* Detect SID Chips suitable for play the files */
    256   if (0 != (flags & MOS8580_FLAG))
    257     ADD ("MOS6581/MOS8580", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE);
    258   else if (0 != (flags & MOS6581_FLAG))
    259     ADD ("MOS6581", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE);
    260 }
    261 
    262 
    263 /* end of sid_extractor.c */