mirror of
https://github.com/ScrelliCopter/VGM-Tools
synced 2025-02-21 04:09:25 +11:00
neotools: code fixup & vgz support
This commit is contained in:
@@ -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)
|
add_executable(adpcm adpcm.c)
|
||||||
set_property(TARGET adpcm PROPERTY C_STANDARD 99)
|
set_property(TARGET adpcm PROPERTY C_STANDARD 99)
|
||||||
target_compile_options(adpcm PRIVATE ${WARNINGS})
|
target_compile_options(adpcm PRIVATE ${WARNINGS})
|
||||||
@@ -9,4 +15,6 @@ target_link_libraries(adpcmb Common::headers)
|
|||||||
|
|
||||||
add_executable(neoadpcmextract autoextract.c neoadpcmextract.c)
|
add_executable(neoadpcmextract autoextract.c neoadpcmextract.c)
|
||||||
set_property(TARGET neoadpcmextract PROPERTY C_STANDARD 99)
|
set_property(TARGET neoadpcmextract PROPERTY C_STANDARD 99)
|
||||||
|
target_compile_definitions(neoadpcmextract PRIVATE $<$<BOOL:${USE_ZLIB}>:USE_ZLIB=1>)
|
||||||
target_compile_options(neoadpcmextract PRIVATE ${WARNINGS})
|
target_compile_options(neoadpcmextract PRIVATE ${WARNINGS})
|
||||||
|
target_link_libraries(neoadpcmextract $<$<BOOL:${USE_ZLIB}>:ZLIB::ZLIB> Common::headers)
|
||||||
|
|||||||
@@ -5,51 +5,46 @@
|
|||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
if (argc != 2)
|
if (argc != 2) return 1;
|
||||||
return 1;
|
|
||||||
|
|
||||||
// Open file.
|
nfile* file = nopen(argv[1], "rb"); // Open file
|
||||||
FILE* file = fopen(argv[1], "rb");
|
if (!file) return 1;
|
||||||
if (!file)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
// Error on VGZ's for now.
|
#if !USE_ZLIB
|
||||||
if (fgetc(file) == 0x1F && fgetc(file) == 0x8B)
|
if (ngetc(file) == 0x1F && ngetc(file) == 0x8B)
|
||||||
{
|
{
|
||||||
printf("I'm a little gzip short and stout\n");
|
printf("I'm a little gzip short and stout\n");
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
nseek(file, 0, SEEK_SET);
|
||||||
fseek(file, 0, SEEK_SET);
|
#endif
|
||||||
|
|
||||||
Buffer smpbuf = {NULL, 0, 0};
|
Buffer smpbuf = {NULL, 0, 0};
|
||||||
char name[32];
|
char name[32];
|
||||||
int smpaCount = 0, smpbCount = 0;
|
int smpaCount = 0, smpbCount = 0;
|
||||||
|
|
||||||
// Find ADCPM samples.
|
// Find ADCPM samples
|
||||||
int scanType;
|
int scanType;
|
||||||
while ((scanType = vgmScanSample(file)))
|
while ((scanType = vgmScanSample(file)))
|
||||||
{
|
{
|
||||||
if (scanType != 'A' && scanType != 'B')
|
if (scanType != 'A' && scanType != 'B')
|
||||||
continue;
|
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)
|
if (vgmReadSample(file, &smpbuf) || smpbuf.size == 0)
|
||||||
continue;
|
continue;
|
||||||
if (scanType == 'A')
|
if (scanType == 'A')
|
||||||
{
|
{
|
||||||
// decode
|
|
||||||
snprintf(name, sizeof(name), "smpa_%02x.pcm", smpaCount++);
|
snprintf(name, sizeof(name), "smpa_%02x.pcm", smpaCount++);
|
||||||
printf("./adpcm \"%s\" \"$WAVDIR/%s.wav\"\n", name, name);
|
printf("./adpcm \"%s\" \"$WAVDIR/%s.wav\"\n", name, name);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// decode
|
|
||||||
snprintf(name, sizeof(name), "smpb_%02x.pcm", smpbCount++);
|
snprintf(name, sizeof(name), "smpb_%02x.pcm", smpbCount++);
|
||||||
printf("./adpcmb -d \"%s\" \"$WAVDIR/%s.wav\"\n", name, name);
|
printf("./adpcmb -d \"%s\" \"$WAVDIR/%s.wav\"\n", name, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write adpcm sample.
|
// Write ADPCM sample
|
||||||
FILE* fout = fopen(name, "wb");
|
FILE* fout = fopen(name, "wb");
|
||||||
if (!fout)
|
if (!fout)
|
||||||
continue;
|
continue;
|
||||||
@@ -58,6 +53,6 @@ int main(int argc, char** argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
free(smpbuf.data);
|
free(smpbuf.data);
|
||||||
fclose(file);
|
nclose(file);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 "neoadpcmextract.h"
|
||||||
|
#include "endian.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
|
||||||
int vgmReadSample(FILE* fin, Buffer* buf)
|
static uint32_t read32le(nfile* fin)
|
||||||
{
|
{
|
||||||
// Get sample data length.
|
uint32_t tmp = 0;
|
||||||
uint32_t sampLen = 0;
|
nread(&tmp, sizeof(uint32_t), 1, fin);
|
||||||
fread(&sampLen, sizeof(uint32_t), 1, fin);
|
return SWAP_LE32(tmp);
|
||||||
if (sampLen < sizeof(uint64_t))
|
}
|
||||||
return 1;
|
|
||||||
sampLen -= sizeof(uint64_t);
|
|
||||||
|
|
||||||
// Resize buffer if needed.
|
bool bufferResize(Buffer* buf, size_t size)
|
||||||
buf->size = sampLen;
|
{
|
||||||
if (!buf->data || buf->reserved < sampLen)
|
if (!buf)
|
||||||
|
return false;
|
||||||
|
buf->size = size;
|
||||||
|
if (!buf->data || buf->reserved < size)
|
||||||
{
|
{
|
||||||
free(buf->data);
|
free(buf->data);
|
||||||
buf->reserved = sampLen;
|
buf->reserved = size;
|
||||||
buf->data = malloc(sampLen);
|
buf->data = malloc(size);
|
||||||
if (!buf->data)
|
if (!buf->data)
|
||||||
return 1;
|
return false;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Ignore 8 bytes.
|
int vgmReadSample(nfile* restrict fin, Buffer* restrict buf)
|
||||||
uint64_t dummy;
|
{
|
||||||
fread(&dummy, sizeof(uint64_t), 1, fin);
|
// Get sample data length
|
||||||
|
uint32_t sampLen = read32le(fin);
|
||||||
// Read adpcm data.
|
if (sampLen <= 8) return 1;
|
||||||
fread(buf->data, sizeof(uint8_t), sampLen, fin);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int vgmScanSample(FILE* file)
|
int vgmScanSample(nfile* file)
|
||||||
{
|
{
|
||||||
// Scan for pcm headers.
|
// Scan for pcm headers
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
if (feof(file) || ferror(file))
|
if (neof(file) || nerror(file)) return 0;
|
||||||
return 0;
|
if (ngetc(file) != 0x67 || ngetc(file) != 0x66) continue; // Match data block
|
||||||
|
switch (ngetc(file))
|
||||||
// Patterns to match (in hex):
|
{
|
||||||
// 67 66 82 - ADPCM-A
|
case 0x82: return 'A'; // 67 66 82 - ADPCM-A
|
||||||
// 67 66 83 - ADPCM-B
|
case 0x83: return 'B'; // 67 66 83 - ADPCM-B
|
||||||
if (fgetc(file) != 0x67 || fgetc(file) != 0x66)
|
default: return 0;
|
||||||
continue;
|
}
|
||||||
|
|
||||||
uint8_t byte = fgetc(file);
|
|
||||||
if (byte == 0x82)
|
|
||||||
return 'A';
|
|
||||||
else if (byte == 0x83)
|
|
||||||
return 'B';
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,38 @@
|
|||||||
#ifndef __NEOADPCMEXTRACT_H__
|
#ifndef NEOADPCMEXTRACT_H
|
||||||
#define __NEOADPCMEXTRACT_H__
|
#define NEOADPCMEXTRACT_H
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#if USE_ZLIB
|
||||||
|
#include <zlib.h>
|
||||||
|
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;
|
typedef struct { uint8_t* data; size_t size, reserved; } Buffer;
|
||||||
|
|
||||||
int vgmReadSample(FILE* fin, Buffer* buf);
|
bool bufferResize(Buffer* buf, size_t size);
|
||||||
int vgmScanSample(FILE* file);
|
|
||||||
|
|
||||||
#endif//__NEOADPCMEXTRACT_H__
|
int vgmReadSample(nfile* restrict fin, Buffer* restrict buf);
|
||||||
|
int vgmScanSample(nfile* file);
|
||||||
|
|
||||||
|
#endif//NEOADPCMEXTRACT_H
|
||||||
|
|||||||
Reference in New Issue
Block a user