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