From: Urban Wallasch Date: Sun, 17 Nov 2019 04:45:03 +0000 (+0100) Subject: * Added unriffle RIFF inspector. X-Git-Url: https://git.packet-gain.de/?a=commitdiff_plain;h=4e77d7667f110f4df2f8330559d2e9aa7740432a;p=riffx.git * Added unriffle RIFF inspector. * Amended and improved Makefile. * Updated .gitignore. --- diff --git a/.gitignore b/.gitignore index 1cdc158..34da50e 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ riffx +unriffle diff --git a/Makefile b/Makefile index 68efab7..5a4d591 100644 --- a/Makefile +++ b/Makefile @@ -1,21 +1,26 @@ +CC ?= gcc +CCX ?= g++ CFLAGS = -O2 -Wall -Wextra -Werror .PHONY: all clean -all: ww2ogg-b revorb-b riffx-b +all: ww2ogg/ww2ogg revorb-nix/revorb riffx unriffle -riffx-b: riffx +riffx: riffx.c + $(CC) $(CFLAGS) -o riffx riffx.c strip riffx -riffx: riffx.c +unriffle: unriffle.c + $(CC) $(CFLAGS) -o unriffle unriffle.c + strip unriffle -ww2ogg-b: +ww2ogg/ww2ogg: cd ww2ogg && $(MAKE) all -revorb-b: - cd revorb-nix && ./build.sh +revorb-nix/revorb: revorb-nix/revorb.cpp + $(CCX) revorb-nix/revorb.cpp -o revorb-nix/revorb -logg -lvorbis clean: - rm -f *.o riffx + rm -f *.o riffx unriffle cd ww2ogg && $(MAKE) clean cd revorb-nix && rm revorb 2>/dev/null ||: diff --git a/unriffle.c b/unriffle.c new file mode 100644 index 0000000..9134ab1 --- /dev/null +++ b/unriffle.c @@ -0,0 +1,216 @@ +#include +#include +#include +#include +#include +#include +#include + + +static struct { + FILE *dump_fp; + FILE *log_fp; + int endianess; +} cfg = { + NULL, + NULL, + 0, +}; + + +/* + * dump helper: + */ + +static const char *hdig = "0123456789abcdef"; + +static inline void xdump(const void *s, size_t n) { + const unsigned char *p = s; + char buf[68]; + char *b = buf; + char *a = buf + 51; + size_t i = 0; + + memset(buf, ' ', sizeof buf); + while (i < n) { + *b++ = hdig[p[i] / 16]; + *b++ = hdig[p[i] % 16]; + *a++ = isgraph(p[i]) ? p[i] : '.'; + ++i; + if (i % 16 == 0) { + *a++ = '\0'; + fprintf(cfg.dump_fp, "%14zu: %s\n", i - 16, buf); + memset(buf, ' ', sizeof buf); + b = buf; + a = buf + 51; + } + else { + if (i % 8 == 0) + *b++ = ' '; + *b++ = ' '; + } + } + if (b != buf) { + *a++ = '\0'; + fprintf(cfg.dump_fp, "%14zu: %s\n", (i - 1) / 16 * 16, buf); + } +} + +/* Little/Big Endian to native uint32 conversion: */ +static inline uint32_t get_ui32(const void *p) { + const uint8_t *b = p; + if (!cfg.endianess) /* Little Endian byte order (RIFF) */ + return b[0] | b[1] << 8 | b[2] << 16 | b[3] << 24; + /* Big Endian byte order (RIFX) */ + return b[3] | b[2] << 8 | b[1] << 16 | b[0] << 24; +} + +/* Little/Big Endian to native uint16 conversion: */ +static inline uint16_t get_ui16(const void *p) { + const uint8_t *b = p; + if (!cfg.endianess) /* Little Endian byte order (RIFF) */ + return b[0] | b[1] << 8; + /* Big Endian byte order (RIFX) */ + return b[1] | b[0] << 8; +} + +#define LOG(...) (fprintf(cfg.log_fp,__VA_ARGS__)) +#define DIE(...) do{LOG(__VA_ARGS__);exit(EXIT_FAILURE);}while(0) +#define DMP(...) (fprintf(cfg.dump_fp,__VA_ARGS__)) + +#define FOURCC_IS(p_,q_) (!memcmp((const void *)(p_),(const void *)(q_),4)) + +typedef uint8_t fcc_t[4]; + +typedef + struct RIFF_chunk_t { + fcc_t fcc; + uint32_t csize; + uint8_t data[]; + } + RIFF_chunk_t; + +static inline void dump4cc(const char *s, fcc_t fcc) { + fcc_t f; + for (size_t i = 0; i < sizeof f; i++) + f[i] = isprint((unsigned char)fcc[i]) ? fcc[i] : '?'; + DMP("[4] %14s: ", s); DMP("%4.4s\n", f); +} + +static inline void dump4ccEnd(const char *s, fcc_t fcc) { + fcc_t f; + for (size_t i = 0; i < sizeof f; i++) + f[i] = isprint((unsigned char)fcc[i]) ? fcc[i] : '?'; + DMP(" %14s: [%4.4s end]\n", s, f); +} + +static inline void dumpU16(const char *s, const void *u) { + DMP("[2] %14s: ", s); DMP("%"PRIu16"\n", get_ui16(u)); +} + +static inline void dumpU32(const char *s, const void *u) { + DMP("[4] %14s: ", s); DMP("%"PRIu32"\n", get_ui32(u)); +} + +static inline void dumpStr(const char *s, const void *u) { + DMP("%14s: ", s); DMP("%s\n", (const char *)u); +} + +static int rdump(void *p, size_t fsize) { + RIFF_chunk_t *r = p; + uint32_t sz = get_ui32(&r->csize); + + if (!fsize || !sz) { + return 0; + } + DMP("\n"); + dump4cc("Chunk ID", r->fcc); + dumpU32("Size", &r->csize); + if (FOURCC_IS(&r->fcc, "RIFF") || FOURCC_IS(&r->fcc, "RIFX")) { + dump4cc("RIFF Type", r->data); + rdump(r->data + sizeof(fcc_t), fsize - sizeof(fcc_t)); + } + else if (FOURCC_IS(&r->fcc, "LIST")) { + dump4cc("Form Type", r->data); + rdump(r->data + sizeof(fcc_t), sz - sizeof(fcc_t)); + } + else if (FOURCC_IS(&r->fcc, "labl")) { + dumpU32("Label ID", r->data); + dumpStr("Label Text", r->data + 4); + sz += 8; + } + else if (FOURCC_IS(&r->fcc, "cue ")) { + uint32_t cn = get_ui32(r->data); + dumpU32("# Cue points", &r->data); + for (uint32_t i = 0; i < cn; ++i) { + uint8_t *c; + c = r->data + i * 24 + 4; + dumpU32("Cue ID", c); + dumpU32("Cue Position", c+4); + dump4cc("Data Chunk ID", c + 8); + dumpU32("Chunk Start", c+12); + dumpU32("Block Start", c+16); + dumpU32("Sample Offset", c+20); + } + } + else if (FOURCC_IS(&r->fcc, "fmt ")) { + dumpU16("Compression", r->data); + dumpU16("# Channels", r->data+2); + dumpU32("Sample Rate", r->data+4); + dumpU32("Avg. Bytes/s", r->data+8); + dumpU16("Block align", r->data+12); + dumpU16("Signif. bit/s", r->data+14 ); + dumpU16("Xtra FMT bytes", r->data+16); + xdump(r->data+18, sz-18); + } + else if (sz <= fsize) { + xdump(r->data, sz); + } + else { + /* Garbage beyond expected EOF: */ + xdump(r->data, fsize); + return -1; + } + dump4ccEnd("==============", r->fcc); + return rdump(r->data + sz, fsize - sz); +} + +int main(int argc, char *argv[]) { + FILE *ifp = stdin; + size_t fsize = 0; + void *buf; + RIFF_chunk_t *r; + size_t nrd; + + cfg.dump_fp = stdout; + cfg.log_fp = stderr; + if (argc > 1) { + ifp = fopen(argv[1], "r"); + if (!ifp) + DIE("fopen %s: %s\n", argv[1], strerror(errno)); + fseek(ifp, 0, SEEK_END); + fsize = ftell(ifp); + rewind(ifp); + } + buf = malloc(fsize); + if (!buf) + DIE("malloc: %s\n", strerror(errno)); + nrd = fread(buf, 1, fsize, ifp); + if (ferror(ifp) || nrd != fsize) + DIE("read: %s\n", strerror(errno)); + r = buf; + + if (!FOURCC_IS(r->fcc, "RIFF")) { + if (!FOURCC_IS(r->fcc, "RIFX")) + DIE("%s is not a RIFF file!\n", argv[1]); + cfg.endianess = 1; + } + + DMP("File name: %s\n", argv[1]); + DMP("File size: %zu\n", fsize); + rdump(r, fsize); + free(buf); + exit(EXIT_SUCCESS); +} + +