libextractor

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

sid_extractor.c (5650B)


      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 void
    173 EXTRACTOR_sid_extract_method (struct EXTRACTOR_ExtractContext *ec)
    174 {
    175   unsigned int flags;
    176   int version;
    177   char album[33];
    178   char artist[33];
    179   char copyright[33];
    180   char songs[32];
    181   char startingsong[32];
    182   char sidversion[32];
    183   const struct header *head;
    184   void *data;
    185 
    186   if ((ssize_t) sizeof (struct header) >
    187       ec->read (ec->cls,
    188                 &data,
    189                 sizeof (struct header)))
    190     return;
    191   head = data;
    192 
    193   /* Check "magic" id bytes */
    194   if ( (0 != memcmp (head->magicid, "PSID", 4)) &&
    195        (0 != memcmp (head->magicid, "RSID", 4)) )
    196     return;
    197 
    198   /* Mime-type */
    199   ADD ("audio/prs.sid", EXTRACTOR_METATYPE_MIMETYPE);
    200 
    201   /* Version of SID format */
    202   version = sidword (head->sidversion);
    203   snprintf (sidversion,
    204             sizeof (sidversion),
    205             "%d",
    206             version);
    207   ADD (sidversion, EXTRACTOR_METATYPE_FORMAT_VERSION);
    208 
    209   /* Get song count */
    210   snprintf (songs,
    211             sizeof (songs),
    212             "%d", sidword (head->songs));
    213   ADD (songs, EXTRACTOR_METATYPE_SONG_COUNT);
    214 
    215   /* Get number of the first song to be played */
    216   snprintf (startingsong,
    217             sizeof (startingsong),
    218             "%d",
    219             sidword (head->firstsong));
    220   ADD (startingsong, EXTRACTOR_METATYPE_STARTING_SONG);
    221 
    222   /* name, artist, copyright fields */
    223   memcpy (&album, head->title, 32);
    224   album[32] = '\0';
    225   ADD (album, EXTRACTOR_METATYPE_ALBUM);
    226 
    227   memcpy (&artist, head->artist, 32);
    228   artist[32] = '\0';
    229   ADD (artist, EXTRACTOR_METATYPE_ARTIST);
    230 
    231   memcpy (&copyright, head->copyright, 32);
    232   copyright[32] = '\0';
    233   ADD (copyright, EXTRACTOR_METATYPE_COPYRIGHT);
    234 
    235   if (version < 2)
    236     return;
    237 
    238   /* Version 2 specific options follow
    239    *
    240    * Note: Had some troubles understanding specification
    241    * on the flags in version 2. I hope this is correct.
    242    */flags = sidword (head->flags);
    243   /* MUS data */
    244   if (0 != (flags & MUSPLAYER_FLAG))
    245     ADD ("Compute!'s Sidplayer", EXTRACTOR_METATYPE_CREATED_BY_SOFTWARE);
    246 
    247   /* PlaySID data */
    248   if (0 != (flags & PLAYSID_FLAG))
    249     ADD ("PlaySID", EXTRACTOR_METATYPE_CREATED_BY_SOFTWARE);
    250 
    251 
    252   /* PAL or NTSC */
    253   if (0 != (flags & NTSC_FLAG))
    254     ADD ("PAL/NTSC", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM);
    255   else if (0 != (flags & PAL_FLAG))
    256     ADD ("PAL", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM);
    257 
    258   /* Detect SID Chips suitable for play the files */
    259   if (0 != (flags & MOS8580_FLAG))
    260     ADD ("MOS6581/MOS8580", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE);
    261   else if (0 != (flags & MOS6581_FLAG))
    262     ADD ("MOS6581", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE);
    263 }
    264 
    265 
    266 /* end of sid_extractor.c */