From 353d4e5def18e820e48cdf87c574911563f5ff29 Mon Sep 17 00:00:00 2001 From: a dinosaur Date: Sun, 10 Dec 2023 10:37:15 +1100 Subject: [PATCH] neotools: code fixup & vgz support --- neotools/CMakeLists.txt | 8 +++++ neotools/autoextract.c | 27 ++++++-------- neotools/neoadpcmextract.c | 73 +++++++++++++++++++------------------- neotools/neoadpcmextract.h | 36 ++++++++++++++++--- 4 files changed, 87 insertions(+), 57 deletions(-) diff --git a/neotools/CMakeLists.txt b/neotools/CMakeLists.txt index 1108a33..480c2ec 100644 --- a/neotools/CMakeLists.txt +++ b/neotools/CMakeLists.txt @@ -1,3 +1,9 @@ +find_package(ZLIB) +option(USE_ZLIB "Link Zlib for VGZ support" ${ZLIB_FOUND}) +if (USE_ZLIB AND NOT ZLIB_FOUND) + message(FATAL_ERROR "USE_ZLIB specified but Zlib was not found") +endif() + add_executable(adpcm adpcm.c) set_property(TARGET adpcm PROPERTY C_STANDARD 99) target_compile_options(adpcm PRIVATE ${WARNINGS}) @@ -9,4 +15,6 @@ target_link_libraries(adpcmb Common::headers) add_executable(neoadpcmextract autoextract.c neoadpcmextract.c) set_property(TARGET neoadpcmextract PROPERTY C_STANDARD 99) +target_compile_definitions(neoadpcmextract PRIVATE $<$:USE_ZLIB=1>) target_compile_options(neoadpcmextract PRIVATE ${WARNINGS}) +target_link_libraries(neoadpcmextract $<$:ZLIB::ZLIB> Common::headers) diff --git a/neotools/autoextract.c b/neotools/autoextract.c index 190b2d2..95b9753 100644 --- a/neotools/autoextract.c +++ b/neotools/autoextract.c @@ -5,51 +5,46 @@ int main(int argc, char** argv) { - if (argc != 2) - return 1; + if (argc != 2) return 1; - // Open file. - FILE* file = fopen(argv[1], "rb"); - if (!file) - return 1; + nfile* file = nopen(argv[1], "rb"); // Open file + if (!file) return 1; - // Error on VGZ's for now. - if (fgetc(file) == 0x1F && fgetc(file) == 0x8B) +#if !USE_ZLIB + if (ngetc(file) == 0x1F && ngetc(file) == 0x8B) { printf("I'm a little gzip short and stout\n"); return 2; } - - fseek(file, 0, SEEK_SET); + nseek(file, 0, SEEK_SET); +#endif Buffer smpbuf = {NULL, 0, 0}; char name[32]; int smpaCount = 0, smpbCount = 0; - // Find ADCPM samples. + // Find ADCPM samples int scanType; while ((scanType = vgmScanSample(file))) { if (scanType != 'A' && scanType != 'B') continue; - fprintf(stderr, "ADPCM-%c data found at 0x%08lX\n", scanType, ftell(file)); + fprintf(stderr, "ADPCM-%c data found at 0x%08lX\n", scanType, ntell(file)); if (vgmReadSample(file, &smpbuf) || smpbuf.size == 0) continue; if (scanType == 'A') { - // decode snprintf(name, sizeof(name), "smpa_%02x.pcm", smpaCount++); printf("./adpcm \"%s\" \"$WAVDIR/%s.wav\"\n", name, name); } else { - // decode snprintf(name, sizeof(name), "smpb_%02x.pcm", smpbCount++); printf("./adpcmb -d \"%s\" \"$WAVDIR/%s.wav\"\n", name, name); } - // Write adpcm sample. + // Write ADPCM sample FILE* fout = fopen(name, "wb"); if (!fout) continue; @@ -58,6 +53,6 @@ int main(int argc, char** argv) } free(smpbuf.data); - fclose(file); + nclose(file); return 0; } diff --git a/neotools/neoadpcmextract.c b/neotools/neoadpcmextract.c index 93b7ffb..00b64fb 100644 --- a/neotools/neoadpcmextract.c +++ b/neotools/neoadpcmextract.c @@ -1,57 +1,58 @@ -/* neoadpcmextract.c (C) 2017, 2019, 2020 a dinosaur (zlib) */ +/* neoadpcmextract.c (C) 2017, 2019, 2020, 2023 a dinosaur (zlib) */ #include "neoadpcmextract.h" +#include "endian.h" #include -int vgmReadSample(FILE* fin, Buffer* buf) +static uint32_t read32le(nfile* fin) { - // Get sample data length. - uint32_t sampLen = 0; - fread(&sampLen, sizeof(uint32_t), 1, fin); - if (sampLen < sizeof(uint64_t)) - return 1; - sampLen -= sizeof(uint64_t); + uint32_t tmp = 0; + nread(&tmp, sizeof(uint32_t), 1, fin); + return SWAP_LE32(tmp); +} - // Resize buffer if needed. - buf->size = sampLen; - if (!buf->data || buf->reserved < sampLen) +bool bufferResize(Buffer* buf, size_t size) +{ + if (!buf) + return false; + buf->size = size; + if (!buf->data || buf->reserved < size) { free(buf->data); - buf->reserved = sampLen; - buf->data = malloc(sampLen); + buf->reserved = size; + buf->data = malloc(size); if (!buf->data) - return 1; + return false; } + return true; +} - // Ignore 8 bytes. - uint64_t dummy; - fread(&dummy, sizeof(uint64_t), 1, fin); - - // Read adpcm data. - fread(buf->data, sizeof(uint8_t), sampLen, fin); +int vgmReadSample(nfile* restrict fin, Buffer* restrict buf) +{ + // Get sample data length + uint32_t sampLen = read32le(fin); + if (sampLen <= 8) return 1; + sampLen -= 8; + if (!bufferResize(buf, sampLen)) return false; // Resize buffer if needed + nseek(fin, 8, SEEK_CUR); // Ignore 8 bytes + nread(buf->data, sizeof(uint8_t), sampLen, fin); // Read adpcm data return 0; } -int vgmScanSample(FILE* file) +int vgmScanSample(nfile* file) { - // Scan for pcm headers. + // Scan for pcm headers while (1) { - if (feof(file) || ferror(file)) - return 0; - - // Patterns to match (in hex): - // 67 66 82 - ADPCM-A - // 67 66 83 - ADPCM-B - if (fgetc(file) != 0x67 || fgetc(file) != 0x66) - continue; - - uint8_t byte = fgetc(file); - if (byte == 0x82) - return 'A'; - else if (byte == 0x83) - return 'B'; + if (neof(file) || nerror(file)) return 0; + if (ngetc(file) != 0x67 || ngetc(file) != 0x66) continue; // Match data block + switch (ngetc(file)) + { + case 0x82: return 'A'; // 67 66 82 - ADPCM-A + case 0x83: return 'B'; // 67 66 83 - ADPCM-B + default: return 0; + } } } diff --git a/neotools/neoadpcmextract.h b/neotools/neoadpcmextract.h index 5695435..2d71d8e 100644 --- a/neotools/neoadpcmextract.h +++ b/neotools/neoadpcmextract.h @@ -1,12 +1,38 @@ -#ifndef __NEOADPCMEXTRACT_H__ -#define __NEOADPCMEXTRACT_H__ +#ifndef NEOADPCMEXTRACT_H +#define NEOADPCMEXTRACT_H #include #include +#include + +#if USE_ZLIB +#include +typedef struct gzFile_s nfile; +# define nopen gzopen +# define nclose gzclose +# define nread gzfread +# define ngetc gzgetc +# define nseek gzseek +# define ntell gztell +# define neof gzeof +static inline int nerror(gzFile file) { int err; gzerror(file, &err); return err; } +#else +typedef FILE nfile; +# define nopen fopen +# define nclose fclose +# define nread fread +# define ngetc fgetc +# define nseek fseek +# define ntell ftell +# define neof feof +# define nerror ferror +#endif typedef struct { uint8_t* data; size_t size, reserved; } Buffer; -int vgmReadSample(FILE* fin, Buffer* buf); -int vgmScanSample(FILE* file); +bool bufferResize(Buffer* buf, size_t size); -#endif//__NEOADPCMEXTRACT_H__ +int vgmReadSample(nfile* restrict fin, Buffer* restrict buf); +int vgmScanSample(nfile* file); + +#endif//NEOADPCMEXTRACT_H