1 /* $Id: modinfo.c,v 1.4 2006/09/15 13:34:06 toad32767 Exp $ */
2 /**
3  ** 2005, 2006 by Marco Trillo
4  ** This file is part of UModPlayer, and is released by
5  ** its autors to the Public Domain.
6  ** In case it's not legally possible, its autors grant
7  ** anyone the right to use, redistribute and modify
8  ** this software for any purpose, without any conditions,
9  ** unless such conditions are required by law.
10  **
11  ** THIS FILE COMES WITHOUT ANY WARRANTY. THE AUTHORS
12  ** SHALL NOT BE LIABLE FOR ANY DAMAGE RESULTING BY THE
13  ** USE OR MISUSE OF THIS SOFTWARE.
14  **/
15 
16 #include <stdlib.h>
17 #include <string.h>
18 #include <umodplayer.h>
19 #include <modinfo.h>
20 
21 
22 /* Number of instruments of a MODULE */
23 EXPORT int
24 number_instruments(MODULE * modfile)
25 {
26 	unsigned char ins = 0;
27 	char *buffer;
28 	short type;
29 	int modlen;
30 
31 	type = modfile->type;
32 	modlen = modfile->buflen;
33 
34 	switch (type) {
35 	case TYPE_SCREAM_3:
36 	case TYPE_IMPULSE:
euc_jis_2004_to_shift_jis_2004(PG_FUNCTION_ARGS)37 		if (modlen > 36) {
38 			buffer = modfile->buf + 34;
39 			ins = (unsigned char) (*buffer);
40 		}
41 		break;
42 	case TYPE_AMIGA_MOD:
43 		ins = 31;
44 		break;
45 	case TYPE_FT2:
46 		if (modlen > 74) {
47 			buffer = modfile->buf + 72;
48 			ins = (unsigned char) (*buffer);
49 		}
50 		break;
shift_jis_2004_to_euc_jis_2004(PG_FUNCTION_ARGS)51 	}
52 
53 	return ((int) ins);
54 }
55 /* Number of orders of a MODULE */
56 EXPORT int
57 number_orders(MODULE * modfile)
58 {
59 	uint16_t ord = 0;
60 	char *buffer;
61 	short type;
62 	int modlen;
63 
64 	type = modfile->type;
65 	modlen = modfile->buflen;
66 
67 	switch (type) {
euc_jis_20042shift_jis_2004(const unsigned char * euc,unsigned char * p,int len)68 	case TYPE_SCREAM_3:
69 	case TYPE_IMPULSE:
70 		if (modlen > 34) {
71 			buffer = modfile->buf + 32;
72 			ord = (uint16_t) (*(buffer++));
73 			ord <<= 8;
74 			ord |= (uint16_t) (*buffer);
75 			ord = bsLE16(ord);
76 		}
77 		break;
78 	case TYPE_AMIGA_MOD:
79 		if (modlen > 950) {
80 			buffer = modfile->buf + 950;
81 			ord = (uint16_t) (*buffer);
82 		}
83 		break;
84 	case TYPE_FT2:
85 		if (modlen > 72) {
86 			buffer = modfile->buf + 70;
87 			ord = (uint16_t) (*(buffer++));
88 			ord <<= 8;
89 			ord |= (uint16_t) (*buffer);
90 			ord = bsLE16(ord);
91 		}
92 		break;
93 
94 	}
95 
96 	return ((int) ord);
97 }
98 /* Loads & typedetects a module to a MODULE struct */
99 EXPORT int
100 load_module(MODULE * modfile, char *buffer, int buflen)
101 {
102 	char *buf;
103 	short type;
104 	uint32_t *magic;
105 	uint32_t z;
106 
107 
108 	type = TYPE_UNKNOWN;
109 
110 	/* XM`s identifier is 'Extended Module: ', starting at offset 0 */
111 	if (buflen > 17) {
112 		if (memcmp(buffer, "Extended Module: ", 17) == 0) {
113 			type = TYPE_FT2;
114 		}
115 	}
116 	/* IT`s identifier is 'IMPM', starting at offset 0 */
117 	if (buflen > 4) {
118 		magic = (uint32_t *) buffer;
119 		z = 0x494D504D;
120 		z = bsBE32(z);
121 		if (z == (*magic)) {
122 			type = TYPE_IMPULSE;
123 		}
124 	}
125 	/* S3M`s identifier is 'SCRM', starting at offset 44 (28+4+2*6) */
126 	if (buflen > 48) {
127 		buf = buffer + 44;
128 		magic = (uint32_t *) buf;
129 		z = 0x5343524D;
130 		z = bsBE32(z);
131 		if (z == (*magic)) {
132 			type = TYPE_SCREAM_3;
133 		}
134 	}
135 	/* MOD has a lot of identifiers, starting at offset 1080 */
136 	if (buflen > 1084) {
137 		buf = buffer + 1080;
138 		memcpy(&z, buf, 4);
139 		z = bsBE32(z);
140 
141 		switch (z) {
142 			/* Thanks to the Modfil11.txt for this identifiers */
143 		case 0x4d2e4b2e:
144 		case 0x46544c34:
145 		case 0x4d214b21:
146 		case 0x3443484e:
147 		case 0x3643484e:
148 		case 0x3843484e:
149 		case 0x4f435441:
150 		case 0x464c5434:
151 		case 0x43443831:
152 		case 0x464c5438:
153 			type = TYPE_AMIGA_MOD;
154 			break;
155 		}
156 	}
157 	modfile->type = type;
158 	modfile->buflen = buflen;
159 	modfile->buf = buffer;
160 
161 	if (type == TYPE_UNKNOWN)
162 		return -1;
163 
164 	return 0;
165 }
166 /* Returns the name of the "numinst" instument as a null-terminated string */
167 /* Returned value must be free()`d */
168 EXPORT char *
169 return_instrument_name(MODULE * mod, int numinst)
170 {
171 	register int i, j;
172 	char *buffer;
173 	char *insname;
174 	char *limit;
175 	int orders;
176 	int instruments;
177 	uint16_t z;
178 	uint32_t Z;
179 	int offset;
180 	int numsamples;
181 	unsigned int hlen;
182 	int G;
183 
get_ten(int b,int * ku)184 	orders = number_orders(mod);
185 	instruments = number_instruments(mod);
186 
187 	if (orders < 1)
188 		return NULL;
189 	if (instruments < (numinst + 1))
190 		return NULL;
191 
192 	insname = NULL;
193 
194 	switch (mod->type) {
195 	case TYPE_SCREAM_3:
196 		if (mod->buflen > (96 + orders + (instruments << 1))) {
197 			buffer = mod->buf + 96 + orders;
198 			buffer += (numinst << 1);
199 			z = (uint16_t) (*(buffer++));
200 			z <<= 8;
201 			z |= (uint16_t) (*buffer);
202 			z = bsLE16(z);
203 			offset = ((int) z) << 4;
204 			offset += 48;
205 
206 			if (mod->buflen <= offset)
207 				break;
208 
209 			buffer = mod->buf + offset;
210 			insname = (char *) malloc(strlen(buffer) + 1);
211 			if (insname == NULL)
212 				break;
213 			strcpy(insname, buffer);
214 		}
215 		break;
shift_jis_20042euc_jis_2004(const unsigned char * sjis,unsigned char * p,int len)216 	case TYPE_IMPULSE:
217 		if (mod->buflen > (192 + orders + (instruments << 2))) {
218 			buffer = mod->buf + 192 + orders;
219 			buffer += (numinst << 2);
220 			memcpy(&Z, buffer, 4);
221 			Z = bsLE32(Z);
222 
223 			if (mod->buflen <= ((int) Z) + 32)
224 				break;
225 
226 			buffer = mod->buf + Z + 32;
227 
228 			insname = (char *) malloc(strlen(buffer) + 1);
229 
230 			if (insname == NULL)
231 				break;
232 			strcpy(insname, buffer);
233 
234 		}
235 		break;
236 	case TYPE_AMIGA_MOD:
237 		if (mod->buflen > (50 + 30 * numinst)) {
238 			buffer = mod->buf + 20;
239 			buffer += numinst * 30;
240 			insname = (char *) malloc(23);
241 			if (insname == NULL)
242 				break;
243 			i = 22;
244 			while (i--)
245 				insname[i] = buffer[i];
246 			insname[22] = 0;
247 		}
248 		break;
249 	case TYPE_FT2:
250 		if (mod->buflen > 80 + 73 * orders) {
251 			buffer = mod->buf + 336;
252 			limit = mod->buf + mod->buflen;
253 
254 			/* Processing patterns... */
255 			for (i = 0; i < orders; ++i) {
256 				buffer += 7;
257 				if (buffer + 1 >= limit)
258 					break;
259 				z = (uint16_t) (*(buffer++));
260 				z <<= 8;
261 				z |= (uint16_t) (*(buffer++));
262 				z = bsLE16(z);
263 				buffer += z;
264 			}
265 
266 			if (buffer + 1 >= limit)
267 				break;
268 
269 			/* Processing instruments... */
270 			for (i = 0; i < numinst; ++i) {
271 				if (buffer + 29 >= limit)
272 					break;
273 				z = (uint16_t) (*(buffer + 27));
274 				z <<= 8;
275 				z |= (uint16_t) (*(buffer + 28));
276 				z = bsLE16(z);
277 				numsamples = (int) z;
278 
279 				/* Processing samples... */
280 				if (numsamples > 0) {
281 					if ((buffer + 33) >= limit)
282 						break;
283 					memcpy(&Z, buffer + 29, 4);
284 					Z = bsLE32(Z);
285 					hlen = (unsigned int) Z;
286 
287 					buffer += 0x107;
288 
289 					G = 0;
290 					for (j = 0; j < numsamples; ++j) {
291 						if (buffer + 4 >= limit)
292 							break;
293 						memcpy(&Z, buffer, 4);
294 						Z = bsLE32(Z);
295 
296 						buffer += 0x28;
297 						G += Z;
298 					}
299 
300 					buffer += G;
301 
302 					if (buffer >= limit)
303 						break;
304 
305 				} else {
306 					memcpy(&Z, buffer, 4);
307 					Z = bsLE32(Z);
308 					buffer += Z;
309 				}
310 
311 			}
312 			insname = NULL;
313 			buffer += 4;
314 
315 			if (buffer + 23 >= limit)
316 				break;
317 
318 			insname = (char *) malloc(23);
319 			i = 22;
320 			while (i--)
321 				insname[i] = buffer[i];
322 			insname[22] = 0;
323 		}
324 		break;
325 	}
326 
327 	return insname;
328 }
329 /* Fetch the module name into `buffer' */
330 EXPORT void
331 module_name(MODULE * modfile, char *buffer)
332 {
333 	int O;
334 	int i;
335 
336 	O = 0;
337 	switch (modfile->type) {
338 	case TYPE_IMPULSE:
339 		O = 4;
340 	case TYPE_SCREAM_3:
341 		strcpy(buffer, modfile->buf + O);
342 		break;
343 	case TYPE_FT2:
344 		O = 17;
345 	case TYPE_AMIGA_MOD:
346 		i = 0;
347 		memcpy(buffer, modfile->buf + O, 20);
348 		buffer[20] = 0;
349 		break;
350 	}
351 
352 	return;
353 }
354 
355 
356 EXPORT short
357 module_type(MODULE * modfile)
358 {
359 	return modfile->type;
360 }
361 
362 EXPORT char *
363 module_typestr(short type)
364 {
365 	switch (type) {
366 	case TYPE_IMPULSE:
367 		return "IT";
368 		break;
369 	case TYPE_SCREAM_3:
370 		return "S3M";
371 		break;
372 	case TYPE_FT2:
373 		return "XM";
374 		break;
375 	case TYPE_AMIGA_MOD:
376 		return "MOD";
377 		break;
378 	default:
379 		return "???";
380 	}
381 
382 	return NULL;
383 }
384 
385 #ifdef MODINFO_DEBUG
386 #include <stdio.h>
387 #include <fcntl.h>
388 #include <unistd.h>
389 #include <sys/types.h>
390 
391 char *
392 xm_retr_file(int fd, int *len)
393 {
394 	char *buffer;
395 	int buflen = 0;
396 	int bytes_out = 0;
397 
398 	buffer = (char *) malloc(1024);
399 	while ((bytes_out = read(fd, buffer + buflen, 1024)) != 0) {
400 		if (bytes_out == -1)
401 			break;
402 		buflen += bytes_out;
403 		buffer = (char *) realloc(buffer, 1024 + buflen);
404 		if (buffer == NULL)
405 			return NULL;
406 	}
407 	buffer = (char *) realloc(buffer, buflen);
408 	if (buffer == NULL)
409 		return NULL;
410 
411 	*len = buflen;
412 	return buffer;
413 }
414 
415 
416 main(argc, argv)
417 	char **argv;
418 {
419 	int i;
420 	char *buffer;
421 	static char modname[128];
422 	MODULE mod;
423 	int buflen;
424 	int fd;
425 	char *typ = NULL;
426 	int ins;
427 
428 	if (argc < 2)
429 		return 1;
430 
431 	fd = open(argv[1], O_RDONLY);
432 	if (fd < 0)
433 		return 1;
434 
435 	buffer = xm_retr_file(fd, &buflen);
436 
437 	if (buflen < 1)
438 		return 1;
439 
440 	load_module(&mod, buffer, buflen);
441 
442 	switch (module_type(&mod)) {
443 	case TYPE_IMPULSE:
444 		typ = "Impulse Tracker";
445 		break;
446 	case TYPE_SCREAM_3:
447 		typ = "Scream Tracker 3";
448 		break;
449 	case TYPE_FT2:
450 		typ = "FastTracker II";
451 		break;
452 	case TYPE_AMIGA_MOD:
453 		typ = "ProTracker/NoiseTracker";
454 		break;
455 	}
456 
457 	if (typ == NULL)
458 		return 1;
459 
460 	module_name(&mod, modname);
461 
462 	printf("Kind : [%s module]\n", typ);
463 	printf("Name : [%s]\n", modname);
464 	printf("Has:\n\t%d orders\n\t%d instruments\nInstrument names:\n",
465 	    number_orders(&mod),
466 	    (ins = number_instruments(&mod))
467 	    );
468 
469 	for (i = 0; i < ins; ++i) {
470 		typ = return_instrument_name(&mod, i);
471 		printf("\t(%d) => [%s]\n", i, typ);
472 		if (typ)
473 			free(typ);
474 	}
475 
476 	puts("");
477 	return 0;
478 }
479 #endif
480 
481 /*
482  * @EOF@ -- revised May 6 2006
483  */
484