Mercurial > hg > dmlib
view tools/dumpmod.c @ 2570:1559011d749f
Add preliminary support for "Unknown $1000 format (unpacked)" as "xx5".
Unfinished and broken.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Wed, 02 Mar 2022 00:31:27 +0200 |
parents | d56a0e86067a |
children | 9807ae37ad69 |
line wrap: on
line source
/* * dumpmod - View information about given module file * Programmed and designed by Matti 'ccr' Hamalainen * (C) Copyright 2006-2015 Tecnic Software productions (TNSP) * * Please read file 'COPYING' for information on license and distribution. */ #include "dmtool.h" #include "jss.h" #include "jssmod.h" #include "dmargs.h" #include "dmmutex.h" char *optFilename = NULL; BOOL optViewPatterns = FALSE, optViewInstruments = FALSE, optViewExtInstruments = FALSE, optViewGeneralInfo = FALSE, optDump = FALSE; static const DMOptArg optList[] = { { 0, '?', "help" , "Show this help", OPT_NONE }, { 1, 0, "license" , "Print out this program's license agreement", OPT_NONE }, { 2, 'v', "verbose" , "Be more verbose", OPT_NONE }, { 10, 'p', "patterns" , "View patterns", OPT_NONE }, { 12, 'i', "instruments" , "View instruments", OPT_NONE }, { 14, 'e', "extinstruments" , "View extended instruments", OPT_NONE }, { 16, 'g', "general" , "General information", OPT_NONE }, { 18, 'd', "dump" , "Dump mode", OPT_NONE }, { 20, 'a', "all" , "Dump all information (pat, ext, gen, inst)", OPT_NONE }, }; const int optListN = sizeof(optList) / sizeof(optList[0]); void argShowHelp() { dmPrintBanner(stdout, dmProgName, "[options] [modfile]"); dmArgsPrintHelp(stdout, optList, optListN, 0, 80 - 2); } BOOL argHandleOpt(const int optN, char *optArg, char *currArg) { (void) optArg; switch (optN) { case 0: argShowHelp(); exit(0); break; case 1: dmPrintLicense(stdout); exit(0); break; case 2: dmVerbosity++; break; case 10: optViewPatterns = TRUE; break; case 12: optViewInstruments = TRUE; break; case 14: optViewExtInstruments = TRUE; break; case 16: optViewGeneralInfo = TRUE; break; case 18: optDump = TRUE; break; case 20: optViewPatterns = TRUE; optViewInstruments = TRUE; optViewGeneralInfo = TRUE; optViewExtInstruments = TRUE; break; default: dmErrorMsg("Unimplemented option argument '%s'.\n", currArg); return FALSE; } return TRUE; } BOOL argHandleFile(char *currArg) { // Was not option argument if (!optFilename) optFilename = currArg; else { dmErrorMsg("Oh noes, we can only hand one file and '%s' looks like a second one!\n", currArg); return FALSE; } return TRUE; } const char patNoteTable[12][3] = { "C-", "C#", "D-", "D#", "E-", "F-", "F#", "G-", "G#", "A-", "A#", "B-" }; #define jmpNMODEffectTable (36) static const char jmpMODEffectTable[jmpNMODEffectTable] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; void printEscaped(FILE *f, const char *str) { while (*str) { fputc(isprint(*str) ? *str : '*', f); str++; } } const char *getNote(const int note) { static char tmp[16]; snprintf(tmp, sizeof(tmp), "%s%d", patNoteTable[note % 12], note / 12); return tmp; } /* Print a given pattern */ void printPattern(FILE *f, const JSSPattern *p) { int i, j; char c; JSSNote *n = p->data; for (i = 0; i < p->nrows; i++) { fprintf(f, "%.2x: ", i); for (j = 0; j < p->nchannels; j++) { switch (n->note) { case jsetNotSet: fprintf(f, "... "); break; case jsetNoteOff: fprintf(f, "=== "); break; default: fprintf(f, "%s ", getNote(n->note)); break; } if (n->instrument != jsetNotSet) fprintf(f, "%.2x ", n->instrument + 1); // Because FT2 is 1-based and we use 0 internally else fprintf(f, ".. "); if (n->volume == jsetNotSet) fprintf(f, ".. "); else if (n->volume >= 0x00 && n->volume <= 0x40) fprintf(f, "%.2x ", n->volume); else { switch (n->volume & 0xf0) { case 0x50: c = '-'; break; case 0x60: c = '+'; break; case 0x70: c = '/'; break; case 0x80: c = '\\'; break; case 0x90: c = 'S'; break; case 0xa0: c = 'V'; break; case 0xb0: c = 'P'; break; case 0xc0: c = '<'; break; case 0xd0: c = '>'; break; case 0xe0: c = 'M'; break; default: c = '?'; break; } fprintf(f, "%c%x ", c, (n->volume & 0x0f)); } if (n->effect >= 0 && n->effect < jmpNMODEffectTable) fprintf(f, "%c", jmpMODEffectTable[n->effect]); else if (n->effect == jsetNotSet) fprintf(f, "."); else fprintf(f, "?"); if (n->param != jsetNotSet) fprintf(f, "%.2x|", n->param); else fprintf(f, "..|"); n++; } fprintf(f, "\n"); } } /* * Print given extended instrument */ void printEnvelope(FILE *f, const JSSEnvelope *e, const char *name) { int i; fprintf(f, " %s-envelope:\n" " flags......: %.4x%s%s%s\n" " npoints....: %d\n" " sustain....: %d\n" " loop.......: %d - %d\n", name, e->flags, (e->flags & jenvfUsed) ? " [used]" : "", (e->flags & jenvfSustain) ? " [sust]" : "", (e->flags & jenvfLooped) ? " [loop]" : "", e->npoints, e->sustain, e->loopS, e->loopE); if (dmVerbosity >= 2) { fprintf(f, " Points.....:"); for (i = 0; i < e->npoints; i++) { fprintf(f, " [%i:%i]", e->points[i].frame, e->points[i].value); } fprintf(f, "\n"); } } void printExtInstrument(FILE *f, const JSSExtInstrument *inst) { #ifndef JSS_LIGHT if (inst->desc && !optDump) { fprintf(f, "'"); printEscaped(f, inst->desc); fprintf(f, "'"); } #endif fprintf(f, "\n" " nsamples.......: %i\n" " vibratoType....: %i\n" " vibratoSweep...: %i\n" " vibratoDepth...: %i\n" " vibratoRate....: %i\n" " fadeOut........: %i\n", inst->nsamples, inst->vibratoType, inst->vibratoSweep, inst->vibratoDepth, inst->vibratoRate, inst->fadeOut); if (dmVerbosity >= 1) { printEnvelope(f, &inst->volumeEnv, "Volume"); printEnvelope(f, &inst->panningEnv, "Panning"); } if (dmVerbosity >= 2) { int n; fprintf(f, " sNumForNotes: "); for (n = 0; n < jsetNNotes; n++) { int snum = inst->sNumForNotes[n]; if (snum != jsetNotSet) { fprintf(f, "%s:%d ", getNote(n), snum); } } } fprintf(f, "\n"); } void printInstrument(FILE *f, const JSSInstrument *inst) { if (dmVerbosity >= 1) { #ifndef JSS_LIGHT if (inst->desc && !optDump) { fprintf(f, "'"); printEscaped(f, inst->desc); fprintf(f, "'"); } #endif fprintf(f, "\n" " size...........: %ld (0x%lx)\n" " loop...........: %ld - %ld (0x%lx - 0x%lx)\n" " volume.........: %d (0x%x)\n" " flags..........: 0x%x %s%s%s\n" " C4BaseSpeed....: %d (0x%x)\n" " ERelNote.......: %s (%d)\n" " EFineTune......: %d\n" " EPanning.......: %d (0x%x)\n\n", (unsigned long) inst->size, (unsigned long) inst->size, (unsigned long) inst->loopS, (unsigned long) inst->loopE, (unsigned long) inst->loopS, (unsigned long) inst->loopE, inst->volume, inst->volume, inst->flags, (inst->flags & jsfLooped) ? "[loop]" : "", (inst->flags & jsfBiDi) ? "[bi-di]" : "", (inst->flags & jsf16bit) ? "[16 bit]" : "[8 bit]", inst->C4BaseSpeed, inst->C4BaseSpeed, getNote(inst->ERelNote + 48), inst->ERelNote, inst->EFineTune, inst->EPanning, inst->EPanning); } else { #ifndef JSS_LIGHT if (inst->desc && !optDump) { printEscaped(f, inst->desc); fprintf(f, "|"); } #endif fprintf(f, "%8ld|%8ld..%-8ld|%03d|%-2s %-2s %-2s|" "%4d|%s%d|%4d|%4d\n", (unsigned long) inst->size, (unsigned long) inst->loopS, (unsigned long) inst->loopE, inst->volume, (inst->flags & jsfLooped) ? "lp" : "", (inst->flags & jsfBiDi) ? "bi" : "", (inst->flags & jsf16bit) ? "16" : "8", inst->C4BaseSpeed, patNoteTable[(48 + inst->ERelNote) % 12], (48 + inst->ERelNote) / 12, inst->EFineTune, inst->EPanning); } } void printGeneralInfo(FILE *f, const JSSModule *m) { int i; if (!m) return; if (!optDump) { fprintf(f, "Module type.....: %i\n", m->moduleType); #ifndef JSS_LIGHT if (m->moduleName) fprintf(f, "Module name.....: '%s'\n", m->moduleName); if (m->trackerName) fprintf(f, "Tracker name....: '%s'\n", m->trackerName); #endif } fprintf(f, "Speed...........: %d ticks\n" "Tempo...........: %d bpm\n" "Flags...........: %x ", m->defSpeed, m->defTempo, m->defFlags); if (m->defFlags & jmdfAmigaPeriods) fprintf(f, "[Amiga periods] "); if (m->defFlags & jmdfAmigaLimits) fprintf(f, "[Amiga limits] "); if (m->defFlags & jmdfStereo) fprintf(f, "[stereo] "); if (m->defFlags & jmdfFT2Replay) fprintf(f, "[FT2 replay] "); if (m->defFlags & jmdfST300Slides) fprintf(f, "[ST300 slides] "); if (m->defFlags & jmdfByteLStart) fprintf(f, "[ByteStart] "); fprintf(f, "\n" "Restart pos.....: %d (order)\n" "IntVersion......: %x\n" "Channels........: %d\n" "Instruments.....: %d\n" "Ext.instruments.: %d\n" "Patterns........: %d\n" "Orders..........: %d\n", m->defRestartPos, m->intVersion, m->nchannels, m->ninstruments, m->nextInstruments, m->npatterns, m->norders); if (dmVerbosity >= 1) { fprintf(f, "Orderlist: "); for (i = 0; i < m->norders - 1; i++) fprintf(f, "%d, ", m->orderList[i]); if (i < m->norders) fprintf(f, "%d", m->orderList[i]); fprintf(f, "\n"); } } int main(int argc, char *argv[]) { DMResource *file = NULL; JSSModule *mod = NULL; int res = 0; dmInitProg("dumpmod", "miniJSS Module Viewer", "0.4", NULL, NULL); dmVerbosity = 0; // Parse arguments if (!dmArgsProcess(argc, argv, optList, optListN, argHandleOpt, argHandleFile, OPTH_BAILOUT)) goto out; // Initialize miniJSS jssInit(); // Open the file dmMsg(1, "Reading module file '%s'\n", optFilename); if (optFilename == NULL) res = dmf_open_stdio_stream(stdin, &file); else res = dmf_open_stdio(optFilename, "rb", &file); if (res != DMERR_OK) { res = dmError(DMERR_FOPEN, "Error opening input file '%s': %s\n", optFilename, dmErrorStr(res)); goto out; } // Read module file dmMsg(1, "Reading file: %s\n", optFilename); #ifdef JSS_SUP_XM if (mod == NULL) { dmMsg(2, "* Trying XM...\n"); dmfreset(file); if ((res = jssLoadXM(file, &mod, TRUE)) == DMERR_OK) { dmfreset(file); res = jssLoadXM(file, &mod, FALSE); } } #endif #ifdef JSS_SUP_JSSMOD if (mod == NULL) { dmMsg(1, "* Trying JSSMOD ...\n"); dmfreset(file); if ((res = jssLoadJSSMOD(file, &mod, TRUE)) == DMERR_OK) { dmfreset(file); res = jssLoadJSSMOD(file, &mod, FALSE); } } #endif dmf_close(file); // Check for errors, we still might have some data tho if (res != DMERR_OK) { dmErrorMsg("Error loading module file: %s\n", dmErrorStr(res)); } // Check if we have anything if (mod == NULL) { res = dmError(DMERR_INIT_FAIL, "Could not load module file.\n"); goto out; } // Print out information if (optViewGeneralInfo) printGeneralInfo(stdout, mod); if (optViewPatterns) { for (int i = 0; i < mod->npatterns; i++) if (mod->patterns[i] != NULL) { printf("\nPattern #%02x:\n", i); printPattern(stdout, mod->patterns[i]); } } if (optViewExtInstruments) { printf("\n" "ExtInstruments:\n" "---------------\n" ); for (int i = 0; i < mod->nextInstruments; i++) if (mod->extInstruments[i] != NULL) { printf("#%02x: ", i + 1); printExtInstrument(stdout, mod->extInstruments[i]); } } if (optViewInstruments) { printf("\n" "Instruments:\n" "------------\n" ); for (int i = 0; i < mod->ninstruments; i++) if (mod->instruments[i] != NULL) { printf("#%02x: ", i + 1); printInstrument(stdout, mod->instruments[i]); } } out: // Free module data jssFreeModule(mod); jssClose(); return res; }