amuse/driver/amuseconv.cpp

187 lines
5.1 KiB
C++
Raw Permalink Normal View History

#include "amuse/amuse.hpp"
#include "athena/FileReader.hpp"
#include "athena/DNAYaml.hpp"
#include "logvisor/logvisor.hpp"
2017-12-29 07:57:22 +00:00
#include <cstdio>
#include <cstring>
2021-06-30 18:15:40 +00:00
#if _WIN32
#include <nowide/args.hpp>
#endif
2016-06-22 22:15:53 +00:00
static logvisor::Module Log("amuseconv");
2018-12-08 05:20:09 +00:00
enum ConvType { ConvN64, ConvGCN, ConvPC };
static void ReportConvType(ConvType tp) {
switch (tp) {
case ConvN64:
2021-06-30 18:15:40 +00:00
Log.report(logvisor::Info, FMT_STRING("using N64 format"));
2018-12-08 05:20:09 +00:00
break;
case ConvPC:
2021-06-30 18:15:40 +00:00
Log.report(logvisor::Info, FMT_STRING("using PC format"));
2018-12-08 05:20:09 +00:00
break;
case ConvGCN:
default:
2021-06-30 18:15:40 +00:00
Log.report(logvisor::Info, FMT_STRING("using GameCube format"));
2018-12-08 05:20:09 +00:00
break;
}
2016-06-22 21:43:45 +00:00
}
2021-06-30 18:15:40 +00:00
static bool BuildAudioGroup(std::string_view groupBase, std::string_view targetPath) { return true; }
2021-06-30 18:15:40 +00:00
static bool ExtractAudioGroup(std::string_view inPath, std::string_view targetPath) {
2018-12-08 05:20:09 +00:00
amuse::ContainerRegistry::Type type;
auto groups = amuse::ContainerRegistry::LoadContainer(inPath.data(), type);
2018-12-08 05:20:09 +00:00
if (groups.size()) {
2021-06-30 18:15:40 +00:00
Log.report(logvisor::Info, FMT_STRING("Found '{}'"), amuse::ContainerRegistry::TypeToName(type));
2018-12-08 05:20:09 +00:00
amuse::Mkdir(targetPath.data(), 0755);
2021-06-30 18:15:40 +00:00
Log.report(logvisor::Info, FMT_STRING("Established directory at {}"), targetPath);
2018-12-08 05:20:09 +00:00
for (auto& group : groups) {
2021-06-30 18:15:40 +00:00
Log.report(logvisor::Info, FMT_STRING("Extracting {}"), group.first);
2018-12-08 05:20:09 +00:00
}
}
auto songs = amuse::ContainerRegistry::LoadSongs(inPath.data());
2021-06-30 18:15:40 +00:00
std::string songsDir = std::string(targetPath) + "/midifiles";
2018-12-08 05:20:09 +00:00
bool madeDir = false;
for (auto& pair : songs) {
if (!madeDir) {
amuse::Mkdir(targetPath.data(), 0755);
amuse::Mkdir(songsDir.c_str(), 0755);
madeDir = true;
}
2021-06-30 18:15:40 +00:00
std::string songPath = songsDir + '/' + pair.first + ".mid";
FILE* fp = amuse::FOpen(songPath.c_str(), "wb");
2018-12-08 05:20:09 +00:00
if (fp) {
2021-06-30 18:15:40 +00:00
Log.report(logvisor::Info, FMT_STRING("Extracting {}"), pair.first);
2018-12-08 05:20:09 +00:00
int extractedVersion;
bool isBig;
std::vector<uint8_t> mid = amuse::SongConverter::SongToMIDI(pair.second.m_data.get(), extractedVersion, isBig);
fwrite(mid.data(), 1, mid.size(), fp);
fclose(fp);
}
2018-12-08 05:20:09 +00:00
}
2018-12-08 05:20:09 +00:00
return true;
}
2021-06-30 18:15:40 +00:00
static bool BuildSNG(std::string_view inPath, std::string_view targetPath, int version, bool big) {
FILE* fp = amuse::FOpen(inPath.data(), "rb");
2018-12-08 05:20:09 +00:00
if (!fp)
return false;
fseek(fp, 0, SEEK_END);
long sz = ftell(fp);
fseek(fp, 0, SEEK_SET);
std::vector<uint8_t> data(sz, 0);
fread(&data[0], 1, sz, fp);
fclose(fp);
std::vector<uint8_t> out = amuse::SongConverter::MIDIToSong(data, version, big);
if (out.empty())
return false;
2021-06-30 18:15:40 +00:00
fp = amuse::FOpen(targetPath.data(), "wb");
2018-12-08 05:20:09 +00:00
fwrite(out.data(), 1, out.size(), fp);
fclose(fp);
return true;
}
2021-06-30 18:15:40 +00:00
static bool ExtractSNG(std::string_view inPath, std::string_view targetPath) {
FILE* fp = amuse::FOpen(inPath.data(), "rb");
2018-12-08 05:20:09 +00:00
if (!fp)
return false;
fseek(fp, 0, SEEK_END);
long sz = ftell(fp);
fseek(fp, 0, SEEK_SET);
std::vector<uint8_t> data(sz, 0);
fread(&data[0], 1, sz, fp);
fclose(fp);
int extractedVersion;
bool isBig;
std::vector<uint8_t> out = amuse::SongConverter::SongToMIDI(data.data(), extractedVersion, isBig);
if (out.empty())
return false;
2021-06-30 18:15:40 +00:00
fp = amuse::FOpen(targetPath.data(), "wb");
2018-12-08 05:20:09 +00:00
fwrite(out.data(), 1, out.size(), fp);
fclose(fp);
return true;
}
2021-06-30 18:15:40 +00:00
int main(int argc, char** argv) {
#if _WIN32
2021-06-30 18:15:40 +00:00
nowide::args _(argc, argv);
#endif
2021-06-30 18:15:40 +00:00
2018-12-08 05:20:09 +00:00
logvisor::RegisterConsoleLogger();
2018-12-08 05:20:09 +00:00
if (argc < 3) {
2020-04-11 22:49:30 +00:00
fmt::print(FMT_STRING("Usage: amuseconv <in-file> <out-file> [n64|pc|gcn]\n"));
2018-12-08 05:20:09 +00:00
return 0;
}
ConvType type = ConvGCN;
if (argc >= 4) {
2021-06-30 18:15:40 +00:00
if (!amuse::CompareCaseInsensitive(argv[3], "n64"))
2018-12-08 05:20:09 +00:00
type = ConvN64;
2021-06-30 18:15:40 +00:00
else if (!amuse::CompareCaseInsensitive(argv[3], "gcn"))
2018-12-08 05:20:09 +00:00
type = ConvGCN;
2021-06-30 18:15:40 +00:00
else if (!amuse::CompareCaseInsensitive(argv[3], "pc"))
2018-12-08 05:20:09 +00:00
type = ConvPC;
else {
2021-06-30 18:15:40 +00:00
Log.report(logvisor::Error, FMT_STRING("unrecognized format: {}"), argv[3]);
2018-12-08 05:20:09 +00:00
return 1;
}
2018-12-08 05:20:09 +00:00
}
bool good = false;
2021-06-30 18:15:40 +00:00
FILE* fin = amuse::FOpen(argv[1], "rb");
2018-12-08 05:20:09 +00:00
if (fin) {
fclose(fin);
2021-06-30 18:15:40 +00:00
std::string barePath(argv[1]);
size_t dotPos = barePath.rfind('.');
const char* dot = barePath.c_str() + dotPos;
if (dotPos != std::string::npos) {
if (!amuse::CompareCaseInsensitive(dot, ".mid") ||
!amuse::CompareCaseInsensitive(dot, ".midi")) {
2018-12-08 05:20:09 +00:00
ReportConvType(type);
good = BuildSNG(barePath, argv[2], 1, true);
2021-06-30 18:15:40 +00:00
} else if (!amuse::CompareCaseInsensitive(dot, ".son") ||
!amuse::CompareCaseInsensitive(dot, ".sng")) {
2018-12-08 05:20:09 +00:00
good = ExtractSNG(argv[1], argv[2]);
} else {
good = ExtractAudioGroup(argv[1], argv[2]);
}
}
2018-12-08 05:20:09 +00:00
} else {
amuse::Sstat theStat;
if (!amuse::Stat(argv[1], &theStat) && S_ISDIR(theStat.st_mode)) {
2021-06-30 18:15:40 +00:00
std::string projectPath(argv[1]);
projectPath += "/project.yaml";
fin = amuse::FOpen(projectPath.c_str(), "rb");
2018-12-08 05:20:09 +00:00
if (fin) {
fclose(fin);
2018-12-08 05:20:09 +00:00
ReportConvType(type);
good = BuildAudioGroup(argv[1], argv[2]);
}
}
2018-12-08 05:20:09 +00:00
}
2018-12-08 05:20:09 +00:00
if (!good) {
2021-06-30 18:15:40 +00:00
Log.report(logvisor::Error, FMT_STRING("unable to convert {} to {}"), argv[1], argv[2]);
2018-12-08 05:20:09 +00:00
return 1;
}
2018-12-08 05:20:09 +00:00
return 0;
}