Mercurial > hg > dmlib
annotate viewmod.c @ 60:f28cd66356f6
Initial work for bitmapped fonts and text drawing. Also moved TTF header
stuff to dmtext.h.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Mon, 01 Oct 2012 09:46:56 +0300 |
parents | fc097f7717df |
children | c6cdaa675801 |
rev | line source |
---|---|
0 | 1 /* |
2 * viewmod - View information about given module file | |
3 * Programmed and designed by Matti 'ccr' Hamalainen | |
4 * (C) Copyright 2006-2007 Tecnic Software productions (TNSP) | |
5 * | |
6 * Please read file 'COPYING' for information on license and distribution. | |
7 */ | |
8 #include "jss.h" | |
9 #include "jssmod.h" | |
10 #include <errno.h> | |
11 #include <string.h> | |
12 #include "dmargs.h" | |
13 | |
14 | |
15 char *optFilename = NULL; | |
16 BOOL optViewPatterns = FALSE, | |
17 optViewInstruments = FALSE, | |
18 optViewExtInstruments = FALSE, | |
19 optViewGeneralInfo = FALSE; | |
20 | |
21 | |
22 DMOptArg optList[] = | |
23 { | |
24 { 0, '?', "help", "Show this help and exit", OPT_NONE }, | |
25 { 1, 'p', "patterns", "View patterns", OPT_NONE }, | |
26 { 2, 'i', "instruments", "View instruments", OPT_NONE }, | |
27 { 5, 'e', "extinstruments", "View extended instruments", OPT_NONE }, | |
28 { 3, 'g', "general", "General information", OPT_NONE }, | |
29 { 4, 'v', "verbose", "Be more verbose", OPT_NONE }, | |
30 }; | |
31 | |
32 const int optListN = sizeof(optList) / sizeof(optList[0]); | |
33 | |
34 | |
35 void argShowHelp() | |
36 { | |
37 dmPrintBanner(stdout, dmProgName, "[options] [modfile]"); | |
38 dmArgsPrintHelp(stdout, optList, optListN); | |
39 } | |
40 | |
41 | |
42 BOOL argHandleOpt(const int optN, char *optArg, char *currArg) | |
43 { | |
44 (void) optArg; | |
45 | |
46 switch (optN) | |
47 { | |
48 case 0: | |
49 argShowHelp(); | |
50 exit(0); | |
51 break; | |
52 | |
53 case 1: | |
54 optViewPatterns = TRUE; | |
55 break; | |
56 | |
57 case 2: | |
58 optViewInstruments = TRUE; | |
59 break; | |
60 | |
61 case 3: | |
62 optViewGeneralInfo = TRUE; | |
63 break; | |
64 | |
65 case 4: | |
66 dmVerbosity++; | |
67 break; | |
68 | |
69 case 5: | |
70 optViewExtInstruments = TRUE; | |
71 break; | |
72 | |
73 default: | |
74 dmError("Unknown argument '%s'.\n", currArg); | |
75 return FALSE; | |
76 } | |
77 | |
78 return TRUE; | |
79 } | |
80 | |
81 | |
82 BOOL argHandleFile(char *currArg) | |
83 { | |
84 // Was not option argument | |
85 if (!optFilename) | |
86 optFilename = currArg; | |
87 else { | |
88 dmError("Gay error '%s'!\n", currArg); | |
89 return FALSE; | |
90 } | |
91 | |
92 return TRUE; | |
93 } | |
94 | |
95 | |
96 const char patNoteTable[12][3] = | |
97 { | |
98 "C-", "C#", "D-", | |
99 "D#", "E-", "F-", | |
100 "F#", "G-", "G#", | |
101 "A-", "A#", "B-" | |
102 }; | |
103 | |
104 #define jmpNMODEffectTable (36) | |
105 static const char jmpMODEffectTable[jmpNMODEffectTable] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; | |
106 | |
107 | |
108 /* Print a given pattern | |
109 */ | |
110 void printPattern(FILE *f, JSSPattern *p) | |
111 { | |
112 int i, j; | |
113 char c; | |
114 JSSNote *n; | |
115 | |
116 if (!p) | |
117 return; | |
118 | |
119 n = p->data; | |
120 | |
121 for (i = 0; i < p->nrows; i++) | |
122 { | |
123 fprintf(f, "%.2x: ", i); | |
124 | |
125 for (j = 0; j < p->nchannels; j++) | |
126 { | |
127 switch (n->note) | |
128 { | |
129 case jsetNotSet: | |
130 fprintf(f, "... "); | |
131 break; | |
132 case jsetNoteOff: | |
133 fprintf(f, "=== "); | |
134 break; | |
135 default: | |
136 fprintf(f, "%s%i ", patNoteTable[n->note % 12], n->note / 12); | |
137 break; | |
138 } | |
139 | |
140 if (n->instrument != jsetNotSet) | |
141 fprintf(f, "%.2x ", n->instrument + 1); // Because FT2 is 1-based and we use 0 internally | |
142 else | |
143 fprintf(f, ".. "); | |
144 | |
145 if (n->volume == jsetNotSet) | |
146 fprintf(f, ".. "); | |
147 else if (n->volume >= 0x00 && n->volume <= 0x40) | |
148 fprintf(f, "%.2x ", n->volume); | |
149 else | |
150 { | |
151 switch (n->volume & 0xf0) | |
152 { | |
153 case 0x50: c = '-'; break; | |
154 case 0x60: c = '+'; break; | |
155 case 0x70: c = '/'; break; | |
156 case 0x80: c = '\\'; break; | |
157 case 0x90: c = 'S'; break; | |
158 case 0xa0: c = 'V'; break; | |
159 case 0xb0: c = 'P'; break; | |
160 case 0xc0: c = '<'; break; | |
161 case 0xd0: c = '>'; break; | |
162 case 0xe0: c = 'M'; break; | |
163 default: c = '?'; break; | |
164 } | |
165 fprintf(f, "%c%x ", c, (n->volume & 0x0f)); | |
166 } | |
167 | |
168 if (n->effect >= 0 && n->effect < jmpNMODEffectTable) | |
169 fprintf(f, "%c", jmpMODEffectTable[n->effect]); | |
170 else if (n->effect == jsetNotSet) | |
171 fprintf(f, "."); | |
172 else | |
173 fprintf(f, "?"); | |
174 | |
175 if (n->param != jsetNotSet) | |
176 fprintf(f, "%.2x|", n->param); | |
177 else | |
178 fprintf(f, "..|"); | |
179 | |
180 n++; | |
181 } | |
182 | |
183 fprintf(f, "\n"); | |
184 } | |
185 } | |
186 | |
187 | |
188 /* | |
189 * Print given extended instrument | |
190 */ | |
191 void printEnvelope(FILE *f, JSSEnvelope *e, char *s) | |
192 { | |
193 int i; | |
194 | |
195 fprintf(f, | |
196 "\t%s-envelope:\n" | |
197 "\t - flags.....: %.4x", s, e->flags); | |
198 | |
199 if (e->flags & jenvfUsed) | |
200 fprintf(f, " [used]"); | |
201 if (e->flags & jenvfSustain) | |
202 fprintf(f, " [sust]"); | |
203 if (e->flags & jenvfLooped) | |
204 fprintf(f, " [loop]"); | |
205 | |
206 fprintf(f, "\n" | |
207 "\t - npoints...: %i\n" | |
208 "\t - sustain...: %i\n" | |
209 "\t - loopS.....: %i\n" | |
210 "\t - loopE.....: %i\n", | |
211 e->npoints, e->sustain, e->loopS, e->loopE); | |
212 | |
213 if (dmVerbosity >= 2) | |
214 { | |
215 fprintf(f, "\t - Points....:"); | |
216 for (i = 0; i < e->npoints; i++) | |
217 { | |
218 fprintf(f, " [%i:%i]", | |
219 e->points[i].frame, e->points[i].value); | |
220 } | |
221 | |
222 fprintf(f, "\n"); | |
223 } | |
224 } | |
225 | |
226 | |
227 void printExtInstrument(FILE *f, JSSExtInstrument *i) | |
228 { | |
229 if (!i) | |
230 { | |
231 fprintf(f, "\n"); | |
232 return; | |
233 } | |
234 | |
235 #ifndef JSS_LIGHT | |
236 if (i->desc) | |
237 fprintf(f, | |
238 "Description: '%s'\n", i->desc); | |
239 #endif | |
240 fprintf(f, | |
241 "nsamples.......: %i\n" | |
242 "vibratoType....: %i\n" | |
243 "vibratoSweep...: %i\n" | |
244 "vibratoDepth...: %i\n" | |
245 "vibratoRate....: %i\n" | |
246 "fadeOut........: %i\n", | |
247 i->nsamples, i->vibratoType, i->vibratoSweep, | |
248 i->vibratoDepth, i->vibratoRate, i->fadeOut); | |
249 | |
250 if (dmVerbosity >= 1) | |
251 { | |
252 printEnvelope(f, &i->volumeEnv, "Volume"); | |
253 printEnvelope(f, &i->panningEnv, "Panning"); | |
254 } | |
255 fprintf(f, "\n"); | |
256 } | |
257 | |
258 | |
259 void printInstrument(FILE *f, JSSInstrument *i) | |
260 { | |
261 if (!i) | |
262 { | |
263 fprintf(f, "\n"); | |
264 return; | |
265 } | |
266 | |
267 if (dmVerbosity >= 1) | |
268 { | |
269 #ifndef JSS_LIGHT | |
270 if (i->desc) | |
271 fprintf(f, "Description: '%s'\n", i->desc); | |
272 #endif | |
273 fprintf(f, | |
274 "size...........: %ld (0x%lx)\n" | |
275 "loopStart......: %ld (0x%lx)\n" | |
276 "loopEnd........: %ld (0x%lx)\n" | |
277 "volume.........: %d (0x%x)\n" | |
278 "flags..........: 0x%x ", | |
279 (unsigned long) i->size, (unsigned long) i->size, | |
280 (unsigned long) i->loopS, (unsigned long) i->loopE, | |
281 (unsigned long) i->loopS, (unsigned long) i->loopE, | |
282 i->volume, i->volume, | |
283 i->flags); | |
284 | |
285 if (i->flags & jsfLooped) fprintf(f, "[loop] "); | |
286 if (i->flags & jsfBiDi) fprintf(f, "[bi-di] "); | |
287 if (i->flags & jsf16bit) fprintf(f, "[16bit] "); | |
288 | |
289 fprintf(f, | |
290 "\nC4BaseSpeed....: %d (0x%x)\n" | |
291 "ERelNote.......: %d (%s%d)\n" | |
292 "EFineTune......: %d\n" | |
293 "EPanning,,,....: %d (0x%x)\n\n", | |
294 i->C4BaseSpeed, i->C4BaseSpeed, | |
295 i->ERelNote, patNoteTable[(48 + i->ERelNote) % 12], (48 + i->ERelNote) / 12, | |
296 i->EFineTune, i->EPanning, i->EPanning); | |
297 } | |
298 else | |
299 { | |
300 #ifndef JSS_LIGHT | |
301 if (i->desc) | |
302 fprintf(f, "'%s', ", i->desc); | |
303 #endif | |
304 fprintf(f, | |
305 "s=%ld (%lx), l=%ld-%ld (%lx-%lx), v=%i (%x), f=0x%x, c4=%i (%x), rn=%i (%s%i), ft=%i, pn=%i (%x)\n", | |
306 (unsigned long) i->size, (unsigned long) i->size, | |
307 (unsigned long) i->loopS, (unsigned long) i->loopE, | |
308 (unsigned long) i->loopS, (unsigned long) i->loopE, | |
309 i->volume, i->volume, i->flags, i->C4BaseSpeed, | |
310 i->C4BaseSpeed, i->ERelNote, | |
311 patNoteTable[(48 + i->ERelNote) % 12], | |
312 (48 + i->ERelNote) / 12, i->EFineTune, | |
313 i->EPanning, i->EPanning); | |
314 } | |
315 } | |
316 | |
317 | |
318 void printGeneralInfo(FILE *f, JSSModule *m) | |
319 { | |
320 int i; | |
321 | |
322 if (!m) | |
323 return; | |
324 | |
325 fprintf(f, "Module type.....: %i\n", m->moduleType); | |
326 #ifndef JSS_LIGHT | |
327 if (m->moduleName) | |
328 fprintf(f, "Module name.....: '%s'\n", m->moduleName); | |
329 if (m->trackerName) | |
330 fprintf(f, "Tracker name....: '%s'\n", m->trackerName); | |
331 #endif | |
332 fprintf(f, | |
333 "Speed...........: %d ticks\n" | |
334 "Tempo...........: %d bpm\n" | |
335 "Flags...........: %x ", | |
336 m->defSpeed, m->defTempo, m->defFlags); | |
337 | |
338 if (m->defFlags & jmdfAmigaPeriods) fprintf(f, "[Amiga periods] "); | |
339 if (m->defFlags & jmdfAmigaLimits) fprintf(f, "[Amiga limits] "); | |
340 if (m->defFlags & jmdfStereo) fprintf(f, "[stereo] "); | |
341 if (m->defFlags & jmdfFT2Replay) fprintf(f, "[FT2 replay] "); | |
342 if (m->defFlags & jmdfST300Slides) fprintf(f, "[ST300 slides] "); | |
343 if (m->defFlags & jmdfByteLStart) fprintf(f, "[ByteStart] "); | |
344 | |
345 fprintf(f, "\n" | |
346 "Restart pos.....: %d (order)\n" | |
347 "IntVersion......: %x\n" | |
348 "Channels........: %d\n" | |
349 "Instruments.....: %d\n" | |
350 "Ext.instruments.: %d\n" | |
351 "Patterns........: %d\n" | |
352 "Orders..........: %d\n", | |
353 m->defRestartPos, m->intVersion, m->nchannels, | |
354 m->ninstruments, m->nextInstruments, m->npatterns, | |
355 m->norders); | |
356 | |
357 if (dmVerbosity >= 1) | |
358 { | |
359 fprintf(f, "Orderlist: "); | |
360 for (i = 0; i < m->norders - 1; i++) | |
361 fprintf(f, "%d, ", m->orderList[i]); | |
362 if (i < m->norders) | |
363 fprintf(f, "%d", m->orderList[i]); | |
364 fprintf(f, "\n"); | |
365 } | |
366 } | |
367 | |
368 | |
369 | |
370 int main(int argc, char *argv[]) | |
371 { | |
372 int result = -1, i; | |
373 DMResource *inFile; | |
374 JSSModule *m; | |
375 | |
376 dmInitProg("viewmod", "miniJSS Module Viewer", "0.4", NULL, NULL); | |
377 dmVerbosity = 0; | |
378 | |
379 // Parse arguments | |
380 if (!dmArgsProcess(argc, argv, optList, optListN, | |
381 argHandleOpt, argHandleFile, TRUE)) | |
382 exit(1); | |
383 | |
384 // Initialize miniJSS | |
385 jssInit(); | |
386 | |
387 // Open the file | |
388 dmMsg(1, "Reading module file '%s'\n", optFilename); | |
389 if (optFilename == NULL) | |
390 inFile = dmf_create_stdio_stream(stdin); | |
391 else if ((inFile = dmf_create_stdio(optFilename)) == NULL) | |
392 { | |
393 fprintf(stderr, "Error opening input file '%s'. (%s)\n", optFilename, strerror(errno)); | |
394 return 1; | |
395 } | |
396 | |
397 // Read module file | |
398 fprintf(stderr, "Reading file: %s\n", optFilename); | |
399 #ifdef JSS_SUP_XM | |
400 fprintf(stderr, "* Trying XM...\n"); | |
401 result = jssLoadXM(inFile, &m); | |
402 #endif | |
403 #ifdef JSS_SUP_JSSMOD | |
404 if (result != 0) | |
405 { | |
8
fc097f7717df
Fix JSSMod loading in viewmod and testpl.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
406 size_t bufgot, bufsize = dmfsize(inFile); |
0 | 407 Uint8 *buf = dmMalloc(bufsize); |
8
fc097f7717df
Fix JSSMod loading in viewmod and testpl.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
408 dmfseek(inFile, 0L, SEEK_SET); |
fc097f7717df
Fix JSSMod loading in viewmod and testpl.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
409 fprintf(stderr, "* Trying JSSMOD (%d bytes, %p)...\n", bufsize, buf); |
fc097f7717df
Fix JSSMod loading in viewmod and testpl.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
410 if ((bufgot = dmfread(buf, 1, bufsize, inFile)) != bufsize) |
0 | 411 { |
8
fc097f7717df
Fix JSSMod loading in viewmod and testpl.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
412 fprintf(stderr, "Error reading file (not enough data %d), #%d: %s\n", |
fc097f7717df
Fix JSSMod loading in viewmod and testpl.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
413 bufgot, dmferror(inFile), dmErrorStr(dmferror(inFile))); |
0 | 414 return 2; |
415 } | |
416 result = jssLoadJSSMOD(buf, bufsize, &m); | |
417 dmFree(buf); | |
418 } | |
419 #endif | |
420 dmf_close(inFile); | |
8
fc097f7717df
Fix JSSMod loading in viewmod and testpl.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
421 if (result != DMERR_OK) |
0 | 422 { |
8
fc097f7717df
Fix JSSMod loading in viewmod and testpl.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
423 fprintf(stderr, "Error loading module file, %d: %s\n", |
fc097f7717df
Fix JSSMod loading in viewmod and testpl.
Matti Hamalainen <ccr@tnsp.org>
parents:
0
diff
changeset
|
424 result, dmErrorStr(result)); |
0 | 425 return 3; |
426 } | |
427 | |
428 // Print out information | |
429 if (optViewGeneralInfo) | |
430 printGeneralInfo(stdout, m); | |
431 | |
432 if (optViewPatterns) | |
433 { | |
434 for (i = 0; i < m->npatterns; i++) | |
435 { | |
436 printf("\nPattern #%03i:\n", i); | |
437 printPattern(stdout, m->patterns[i]); | |
438 } | |
439 } | |
440 | |
441 if (optViewExtInstruments) | |
442 { | |
443 printf("\n" | |
444 "ExtInstruments:\n" | |
445 "---------------\n" | |
446 ); | |
447 for (i = 0; i < m->nextInstruments; i++) | |
448 { | |
449 printf("#%03i: ", i); | |
450 printExtInstrument(stdout, m->extInstruments[i]); | |
451 } | |
452 } | |
453 | |
454 if (optViewInstruments) | |
455 { | |
456 printf("\n" | |
457 "Instruments:\n" | |
458 "------------\n" | |
459 ); | |
460 for (i = 0; i < m->ninstruments; i++) | |
461 { | |
462 printf("#%03i: ", i); | |
463 printInstrument(stdout, m->instruments[i]); | |
464 } | |
465 } | |
466 | |
467 // Free module data | |
468 jssFreeModule(m); | |
469 | |
470 exit(0); | |
471 return 0; | |
472 } |