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)
|
||||
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 $<$<BOOL:${USE_ZLIB}>:USE_ZLIB=1>)
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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 <stdlib.h>
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,38 @@
|
||||
#ifndef __NEOADPCMEXTRACT_H__
|
||||
#define __NEOADPCMEXTRACT_H__
|
||||
#ifndef NEOADPCMEXTRACT_H
|
||||
#define NEOADPCMEXTRACT_H
|
||||
|
||||
#include <stdio.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;
|
||||
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user