"Fossies" - the Fresh Open Source Software Archive 
Member "libextractor-1.11/src/plugins/nsfe_extractor.c" (30 Jan 2021, 9205 Bytes) of package /linux/privat/libextractor-1.11.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "nsfe_extractor.c" see the
Fossies "Dox" file reference documentation and the last
Fossies "Diffs" side-by-side code changes report:
1.6_vs_1.7.
1 /*
2 * This file is part of libextractor.
3 * Copyright (C) 2007, 2009, 2012 Toni Ruottu 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/nsfe_extractor.c
23 * @brief plugin to support Nes Sound Format files
24 * @author Toni Ruottu
25 * @author Christian Grothoff
26 */
27 #include "platform.h"
28 #include "extractor.h"
29 #include "convert.h"
30
31
32 /* television system flags */
33 #define PAL_FLAG 0x01
34 #define DUAL_FLAG 0x02
35
36 /* sound chip flags */
37 #define VRCVI_FLAG 0x01
38 #define VRCVII_FLAG 0x02
39 #define FDS_FLAG 0x04
40 #define MMC5_FLAG 0x08
41 #define NAMCO_FLAG 0x10
42 #define SUNSOFT_FLAG 0x20
43
44 /**
45 * "Header" of an NSFE file.
46 */
47 struct header
48 {
49 char magicid[4];
50 };
51
52
53 /**
54 * Read an unsigned integer at the current offset.
55 *
56 * @param data input data to parse
57 * @return parsed integer
58 */
59 static uint32_t
60 nsfeuint (const char *data)
61 {
62 uint32_t value = 0;
63 int i;
64
65 for (i = 3; i > 0; i--)
66 {
67 value += (unsigned char) data[i];
68 value *= 0x100;
69 }
70 value += (unsigned char) data[0];
71 return value;
72 }
73
74
75 /**
76 * Copy string starting at 'data' with at most
77 * 'size' bytes. (strndup).
78 *
79 * @param data input data to copy
80 * @param size number of bytes in 'data'
81 * @return copy of the string at data
82 */
83 static char *
84 nsfestring (const char *data,
85 size_t size)
86 {
87 char *s;
88 size_t length;
89
90 length = 0;
91 while ( (length < size) &&
92 (data[length] != '\0') )
93 length++;
94 if (NULL == (s = malloc (length + 1)))
95 return NULL;
96 memcpy (s, data, length);
97 s[length] = '\0';
98 return s;
99 }
100
101
102 /**
103 * Give metadata to LE; return if 'proc' returns non-zero.
104 *
105 * @param s metadata value as UTF8
106 * @param t metadata type to use
107 */
108 #define ADD(s,t) do { if (0 != ec->proc (ec->cls, "nsfe", t, \
109 EXTRACTOR_METAFORMAT_UTF8, \
110 "text/plain", s, strlen (s) \
111 + 1)) return 1; \
112 } while (0)
113
114
115 /**
116 * Give metadata to LE; return if 'proc' returns non-zero.
117 *
118 * @param s metadata value as UTF8, free at the end
119 * @param t metadata type to use
120 */
121 #define ADDF(s,t) do { if (0 != ec->proc (ec->cls, "nsfe", t, \
122 EXTRACTOR_METAFORMAT_UTF8, \
123 "text/plain", s, strlen (s) \
124 + 1)) { free (s); \
125 return 1; \
126 } free (s); } while (0)
127
128
129 /**
130 * Format of an 'INFO' chunk. Last two bytes are optional.
131 */
132 struct infochunk
133 {
134 /**
135 * Unknown.
136 */
137 uint16_t loadaddr;
138
139 /**
140 * Unknown.
141 */
142 uint16_t initaddr;
143
144 /**
145 * Unknown.
146 */
147 uint16_t playaddr;
148
149 /**
150 * TV encoding flags.
151 */
152 char tvflags;
153
154 /**
155 * Chipset encoding flags.
156 */
157 char chipflags;
158
159 /**
160 * Number of songs.
161 */
162 unsigned char songs;
163
164 /**
165 * Starting song.
166 */
167 unsigned char firstsong;
168 };
169
170
171 /**
172 * Extract data from the INFO chunk.
173 *
174 * @param ec extraction context
175 * @param size number of bytes in INFO chunk
176 * @return 0 to continue extrating
177 */
178 static int
179 info_extract (struct EXTRACTOR_ExtractContext *ec,
180 uint32_t size)
181 {
182 void *data;
183 const struct infochunk *ichunk;
184 char songs[32];
185
186 if (size < 8)
187 return 0;
188 if ((ssize_t) size >
189 ec->read (ec->cls,
190 &data,
191 size))
192 return 1;
193 ichunk = data;
194
195 if (0 != (ichunk->tvflags & DUAL_FLAG))
196 {
197 ADD ("PAL/NTSC", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM);
198 }
199 else
200 {
201 if (0 != (ichunk->tvflags & PAL_FLAG))
202 ADD ("PAL", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM);
203 else
204 ADD ("NTSC", EXTRACTOR_METATYPE_BROADCAST_TELEVISION_SYSTEM);
205 }
206
207 if (0 != (ichunk->chipflags & VRCVI_FLAG))
208 ADD ("VRCVI", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE);
209 if (0 != (ichunk->chipflags & VRCVII_FLAG))
210 ADD ("VRCVII", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE);
211 if (0 != (ichunk->chipflags & FDS_FLAG))
212 ADD ("FDS Sound", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE);
213 if (0 != (ichunk->chipflags & MMC5_FLAG))
214 ADD ("MMC5 audio", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE);
215 if (0 != (ichunk->chipflags & NAMCO_FLAG))
216 ADD ("Namco 106", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE);
217 if (0 != (ichunk->chipflags & SUNSOFT_FLAG))
218 ADD ("Sunsoft FME-07", EXTRACTOR_METATYPE_TARGET_ARCHITECTURE);
219
220 if (size < sizeof (struct infochunk))
221 {
222 ADD ("1", EXTRACTOR_METATYPE_SONG_COUNT);
223 return 0;
224 }
225 snprintf (songs,
226 sizeof (songs),
227 "%d",
228 ichunk->songs);
229 ADD (songs, EXTRACTOR_METATYPE_SONG_COUNT);
230 snprintf (songs,
231 sizeof (songs),
232 "%d",
233 ichunk->firstsong);
234 ADD (songs, EXTRACTOR_METATYPE_STARTING_SONG);
235 return 0;
236 }
237
238
239 /**
240 * Extract data from the TLBL chunk.
241 *
242 * @param ec extraction context
243 * @param size number of bytes in TLBL chunk
244 * @return 0 to continue extrating
245 */
246 static int
247 tlbl_extract (struct EXTRACTOR_ExtractContext *ec,
248 uint32_t size)
249 {
250 char *title;
251 ssize_t left;
252 size_t length;
253 void *data;
254 const char *cdata;
255
256 if ((ssize_t) size >
257 ec->read (ec->cls,
258 &data,
259 size))
260 return 1;
261 cdata = data;
262
263 left = size;
264 while (left > 0)
265 {
266 title = nsfestring (&cdata[size - left], left);
267 if (NULL == title)
268 return 0;
269 length = strlen (title) + 1;
270 ADDF (title, EXTRACTOR_METATYPE_TITLE);
271 left -= length;
272 }
273 return 0;
274 }
275
276
277 /**
278 * Extract data from the AUTH chunk.
279 *
280 * @param ec extraction context
281 * @param size number of bytes in AUTH chunk
282 * @return 0 to continue extrating
283 */
284 static int
285 auth_extract (struct EXTRACTOR_ExtractContext *ec,
286 uint32_t size)
287 {
288 char *album;
289 char *artist;
290 char *copyright;
291 char *ripper;
292 uint32_t left = size;
293 void *data;
294 const char *cdata;
295
296 if (left < 1)
297 return 0;
298 if ((ssize_t) size >
299 ec->read (ec->cls,
300 &data,
301 size))
302 return 1;
303 cdata = data;
304
305 album = nsfestring (&cdata[size - left], left);
306 if (NULL != album)
307 {
308 left -= (strlen (album) + 1);
309 ADDF (album, EXTRACTOR_METATYPE_ALBUM);
310 if (left < 1)
311 return 0;
312 }
313
314 artist = nsfestring (&cdata[size - left], left);
315 if (NULL != artist)
316 {
317 left -= (strlen (artist) + 1);
318 ADDF (artist, EXTRACTOR_METATYPE_ARTIST);
319 if (left < 1)
320 return 0;
321 }
322
323 copyright = nsfestring (&cdata[size - left], left);
324 if (NULL != copyright)
325 {
326 left -= (strlen (copyright) + 1);
327 ADDF (copyright, EXTRACTOR_METATYPE_COPYRIGHT);
328 if (left < 1)
329 return 0;
330 }
331 ripper = nsfestring (&cdata[size - left], left);
332 if (NULL != ripper)
333 ADDF (ripper, EXTRACTOR_METATYPE_RIPPER);
334 return 0;
335 }
336
337
338 /**
339 * "extract" meta data from an Extended Nintendo Sound Format file
340 *
341 * NSFE specification revision 2 (Sep. 3, 2003) was used, while this
342 * piece of software was originally written.
343 *
344 * @param ec extraction context
345 */
346 void
347 EXTRACTOR_nsfe_extract_method (struct EXTRACTOR_ExtractContext *ec)
348 {
349 const struct header *head;
350 void *data;
351 uint64_t off;
352 uint32_t chunksize;
353 int ret;
354
355 if ((ssize_t) sizeof (struct header) >
356 ec->read (ec->cls,
357 &data,
358 sizeof (struct header)))
359 return;
360 head = data;
361 if (0 != memcmp (head->magicid, "NSFE", 4))
362 return;
363
364 if (0 != ec->proc (ec->cls,
365 "nsfe",
366 EXTRACTOR_METATYPE_MIMETYPE,
367 EXTRACTOR_METAFORMAT_UTF8,
368 "text/plain",
369 "audio/x-nsfe",
370 strlen ("audio/x-nsfe") + 1))
371 return;
372 off = sizeof (struct header);
373 ret = 0;
374 while (0 == ret)
375 {
376 if (off != ec->seek (ec->cls,
377 off,
378 SEEK_SET))
379 break;
380 if (8 >
381 ec->read (ec->cls,
382 &data,
383 8))
384 break;
385 chunksize = nsfeuint (data);
386 if (off + chunksize + 8LLU <= off)
387 break; /* protect against looping */
388 off += 8LLU + chunksize;
389 if (0 == memcmp (data + 4, "INFO", 4))
390 ret = info_extract (ec, chunksize);
391 else if (0 == memcmp (data + 4, "auth", 4))
392 ret = auth_extract (ec, chunksize);
393 else if (0 == memcmp (data + 4, "tlbl", 4))
394 ret = tlbl_extract (ec, chunksize);
395 /* Ignored chunks: DATA, NEND, plst, time, fade, BANK */
396 }
397 }
398
399
400 /* end of nsfe_extractor.c */