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 (©right, 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 */