diff --git a/Makefile b/Makefile index 4013ae6..ac528ac 100644 --- a/Makefile +++ b/Makefile @@ -22,7 +22,8 @@ OBJ=\ $(BUILDDIR)/it.o \ $(BUILDDIR)/asf.o \ $(BUILDDIR)/bink.o \ - $(BUILDDIR)/au.o + $(BUILDDIR)/au.o \ + $(BUILDDIR)/smk.o CC=gcc LD=$(CC) COMMON_CFLAGS=-Wall -Werror -Wextra -std=gnu99 -O2 -g $(INCLUDE) $(LIBDIRS) -D_FILE_OFFSET_BITS=64 @@ -88,7 +89,8 @@ $(BUILDDIR)/audioextract.o: src/audioextract.c \ src/it.h \ src/asf.h \ src/bink.h \ - src/au.h + src/au.h \ + src/smk.h $(CC) $(CFLAGS) $< -o $@ -c $(LIBS) $(BUILDDIR)/audioextract_$(PLATFORM).o: src/audioextract_$(PLATFORM).c src/audioextract.h @@ -136,6 +138,9 @@ $(BUILDDIR)/bink.o: src/bink.c src/audioextract.h src/bink.h $(BUILDDIR)/au.o: src/au.c src/audioextract.h src/au.h $(CC) $(CFLAGS) $< -o $@ -c $(LIBS) +$(BUILDDIR)/smk.o: src/smk.c src/audioextract.h src/smk.h + $(CC) $(CFLAGS) $< -o $@ -c $(LIBS) + ifeq ($(PLATFORM),posix) install: $(PREFIX)/bin/$(APPNAME) diff --git a/README.md b/README.md index 85d13d8..1abcbb8 100644 --- a/README.md +++ b/README.md @@ -105,6 +105,7 @@ files. riff Resource Interchange File Format files (ANI, AVI, MMM, PAL, RDI, RMI, WAV) s3m ScreamTracker III files + smk Smaker files xm Extended Module files tracker all tracker files (MOD, S3M, IT, XM) diff --git a/src/audioextract.c b/src/audioextract.c index 233b7b3..9a6acd5 100644 --- a/src/audioextract.c +++ b/src/audioextract.c @@ -29,6 +29,7 @@ #include "asf.h" #include "bink.h" #include "au.h" +#include "smk.h" #if defined(__WINDOWS__) && !defined(__CYGWIN__) # ifdef _WIN64 @@ -60,11 +61,12 @@ enum fileformat { XM = 0x400, ASF = 0x800, BINK = 0x1000, - AU = 0x2000 + AU = 0x2000, + SMK = 0x4000 }; -#define ALL_FORMATS (OGG | RIFF | AIFF | MPG123 | MP4 | ID3v2 | MIDI | MOD | S3M | IT | XM | ASF | BINK | AU) -#define DEFAULT_FORMATS (OGG | RIFF | AIFF | MP4 | ID3v2 | MIDI | S3M | IT | XM | ASF | BINK | AU) +#define ALL_FORMATS (OGG | RIFF | AIFF | MPG123 | MP4 | ID3v2 | MIDI | MOD | S3M | IT | XM | ASF | BINK | AU | SMK) +#define DEFAULT_FORMATS (OGG | RIFF | AIFF | MP4 | ID3v2 | MIDI | S3M | IT | XM | ASF | BINK | AU | SMK) #define TRACKER_FORMATS (MOD | S3M | IT | XM) static int usage(int argc, char **argv); @@ -152,6 +154,7 @@ static int usage(int argc, char **argv) " riff Resource Interchange File Format files (ANI, AVI, MMM,\n" " PAL, RDI, RMI, WAV)\n" " s3m ScreamTracker III files\n" + " smk Smaker files\n" " xm Extended Module files\n" " tracker all tracker files (MOD, S3M, IT, XM)\n" "\n" @@ -426,6 +429,13 @@ int do_extract(const uint8_t *filedata, size_t filesize, const struct extract_op continue; } + if (formats & SMK && IS_SMK_MAGIC(magic) && smk_isfile(ptr, input_len, &length)) + { + WRITE_FILE(ptr, length, "smk"); + ptr += length; + continue; + } + if (formats & MP4 && input_len > MP4_HEADER_SIZE && MAGIC(ptr + MP4_MAGIC_OFFSET) == MP4_MAGIC && mp4_isfile(ptr, input_len, &info)) diff --git a/src/smk.c b/src/smk.c new file mode 100644 index 0000000..0a5099c --- /dev/null +++ b/src/smk.c @@ -0,0 +1,55 @@ +#include "smk.h" + +struct smk_header { + uint32_t signature; + uint32_t width; + uint32_t height; + uint32_t frames; + uint32_t framerate; + uint32_t flags; + uint32_t audiosize[7]; + uint32_t treessize; + uint32_t mmapsize; + uint32_t mclrsize; + uint32_t fullsize; + uint32_t typesize; + uint32_t audiorate[7]; + uint32_t dummy; +}; + +int smk_isfile(const uint8_t *data, size_t input_len, size_t *lengthptr) +{ + const struct smk_header *header = (const struct smk_header *)data; + + if (input_len < SMK_HEADER_SIZE || !IS_SMK_MAGIC(header->signature)) + return 0; + + size_t frames = le32toh(header->frames); + uint32_t flags = le32toh(header->flags); + size_t treessize = le32toh(header->treessize); + size_t length = SMK_HEADER_SIZE + treessize + 5 * frames; + + if (flags > 7 || input_len < length) + return 0; + + const uint32_t *end = (const uint32_t*)(data + SMK_HEADER_SIZE) + frames; + for (const uint32_t *ptr = (const uint32_t*)(data + SMK_HEADER_SIZE); + ptr < end; ++ ptr) + { + size_t framesize = *ptr; + + if (SIZE_MAX - framesize < length) + return 0; + + length += framesize; + } + + // assume now it is a smk file and if the length doesn't fit that it is truncated + if (length > input_len) + length = input_len; + + if (lengthptr) + *lengthptr = length; + + return 1; +} diff --git a/src/smk.h b/src/smk.h new file mode 100644 index 0000000..9bd60e8 --- /dev/null +++ b/src/smk.h @@ -0,0 +1,15 @@ +#ifndef AUDIOEXTRACT_SMK_H__ +#define AUDIOEXTRACT_SMK_H__ + +#include "audioextract.h" + +#define SMK2_MAGIC MAGIC("SMK2") +#define SMK4_MAGIC MAGIC("SMK4") + +#define IS_SMK_MAGIC(magic) ((magic) == SMK2_MAGIC || (magic) == SMK4_MAGIC) + +#define SMK_HEADER_SIZE 104 + +int smk_isfile(const uint8_t *data, size_t input_len, size_t *lengthptr); + +#endif /* AUDIOEXTRACT_SMK_H__ */