Skip to content

Commit

Permalink
Cue name and extension replacement, along with other fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
hozuki committed May 27, 2019
1 parent b04e4a0 commit 3c1ae49
Show file tree
Hide file tree
Showing 9 changed files with 172 additions and 158 deletions.
2 changes: 1 addition & 1 deletion cmake/project_files.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ set(CGSS_APP_SOURCE_FILES
src/apps/cgssh.h)

set(APP_SOURCE_FILES
src/apps/common/common.h src/apps/common/atoh.hpp)
src/apps/common/common.h src/apps/common/atoh.hpp src/apps/common/utils.h src/apps/common/utils.cpp)

set(HCACC_SOURCE_FILES
src/apps/hcacc/hcacc.cpp ${CGSS_APP_SOURCE_FILES} ${APP_SOURCE_FILES} ${LIBCGSS_API_FILES})
Expand Down
108 changes: 30 additions & 78 deletions src/apps/acb2hcas/acb2hcas.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
using namespace std;
using namespace cgss;

struct Options {
struct Acb2HcasOptions {
union {
struct {
uint32_t key2;
Expand All @@ -22,15 +22,12 @@ struct Options {

static void PrintHelp();

static int ParseArgs(int argc, const char *argv[], const char **input, Options &options);
static int ParseArgs(int argc, const char *argv[], const char **input, Acb2HcasOptions &options);

static int DoWork(const string &inputFile, const Options &options);
static int DoWork(const string &inputFile, const Acb2HcasOptions &options);

int ProcessAllBinaries(CAcbFile *acb, uint32_t formatVersion, const Options &options, const string &extractDir, CAfs2Archive *archive, IStream *dataStream, bool_t isInternal);

static void CopyStream(IStream *src, IStream *dst);

static string ReplaceExtension(const std::string &s, const std::string &oldExt, const std::string &newExt);
int
ProcessAllBinaries(CAcbFile *acb, uint32_t formatVersion, const Acb2HcasOptions &options, const string &extractDir, CAfs2Archive *archive, IStream *dataStream, bool_t isInternal);

static void WriteHcaKeyFile(const string &fileName, uint64_t key, uint16_t modifier = 0);

Expand All @@ -41,7 +38,7 @@ int main(int argc, const char *argv[]) {
}

const char *inputFile;
Options options = {0};
Acb2HcasOptions options = {0};

const auto parsed = ParseArgs(argc, argv, &inputFile, options);

Expand All @@ -63,7 +60,7 @@ static void PrintHelp() {
cout << "\t-n\tUse cue names for output waveforms" << endl;
}

static int ParseArgs(int argc, const char *argv[], const char **input, Options &options) {
static int ParseArgs(int argc, const char *argv[], const char **input, Acb2HcasOptions &options) {
if (argc < 2) {
PrintHelp();
return -1;
Expand Down Expand Up @@ -101,7 +98,7 @@ static int ParseArgs(int argc, const char *argv[], const char **input, Options &
return 0;
}

static int DoWork(const string &inputFile, const Options &options) {
static int DoWork(const string &inputFile, const Acb2HcasOptions &options) {
const auto baseExtractDirPath = CPath::Combine(CPath::GetDirectoryName(inputFile), "_acb_" + CPath::GetFileName(inputFile));

CFileStream fileStream(inputFile.c_str(), FileMode::OpenExisting, FileAccess::Read);
Expand Down Expand Up @@ -167,7 +164,7 @@ static int DoWork(const string &inputFile, const Options &options) {
}

static int
ProcessAllBinaries(CAcbFile *acb, uint32_t formatVersion, const Options &options, const string &extractDir, CAfs2Archive *archive, IStream *dataStream, bool_t isInternal) {
ProcessAllBinaries(CAcbFile *acb, uint32_t formatVersion, const Acb2HcasOptions &options, const string &extractDir, CAfs2Archive *archive, IStream *dataStream, bool_t isInternal) {
if (!CFileSystem::DirectoryExists(extractDir)) {
if (!CFileSystem::MkDir(extractDir)) {
fprintf(stderr, "Failed to create directory %s.\n", extractDir.c_str());
Expand All @@ -187,31 +184,36 @@ ProcessAllBinaries(CAcbFile *acb, uint32_t formatVersion, const Options &options

for (auto &entry : archive->GetFiles()) {
auto &record = entry.second;
std::string extractFileName;
std::string hcaKeyFileName;

if (options.useCueName) {
extractFileName = acb->GetCueNameFromCueId(record.cueId);
hcaKeyFileName = ReplaceExtension(extractFileName, ".hca", ".hcakey");
} else {
extractFileName = CAcbFile::GetSymbolicFileNameFromCueId(record.cueId);
hcaKeyFileName = ReplaceExtension(extractFileName, ".bin", ".hcakey");
}

auto extractFilePath = CPath::Combine(extractDir, extractFileName);
auto hcaKeyFilePath = CPath::Combine(extractDir, hcaKeyFileName);

auto fileData = CAcbHelper::ExtractToNewStream(dataStream, record.fileOffsetAligned, (uint32_t)record.fileSize);

const auto isHca = CHcaFormatReader::IsPossibleHcaStream(fileData);

fprintf(stdout, "Processing %s AFS: #%u (offset=%u, size=%u)... ", afsSource, (uint32_t)record.cueId, (uint32_t)record.fileOffsetAligned, (uint32_t)record.fileSize);
fprintf(stdout, "Processing %s AFS: #%u (offset=%u, size=%u)",
afsSource, (uint32_t)record.cueId, (uint32_t)record.fileOffsetAligned, (uint32_t)record.fileSize);

if (isHca) {
std::string extractFileName;
std::string hcaKeyFileName;

if (options.useCueName) {
extractFileName = acb->GetCueNameFromCueId(record.cueId);
} else {
extractFileName = CAcbFile::GetSymbolicFileNameFromCueId(record.cueId);
}

extractFileName = common_utils::ReplaceAnyExtension(extractFileName, ".hca");
hcaKeyFileName = common_utils::ReplaceAnyExtension(extractFileName, ".hcakey");

auto extractFilePath = CPath::Combine(extractDir, extractFileName);
auto hcaKeyFilePath = CPath::Combine(extractDir, hcaKeyFileName);

fprintf(stdout, " to %s...\n", extractFilePath.c_str());

try {
CFileStream hcaFile(extractFilePath.c_str(), FileMode::Create, FileAccess::Write);

CopyStream(fileData, &hcaFile);
common_utils::CopyStream(fileData, &hcaFile);

WriteHcaKeyFile(hcaKeyFilePath, options.key, keyModifier);

Expand All @@ -224,7 +226,7 @@ ProcessAllBinaries(CAcbFile *acb, uint32_t formatVersion, const Options &options
fprintf(stdout, "errored: %s (%d)\n", ex.GetExceptionMessage().c_str(), ex.GetOpResult());
}
} else {
fprintf(stdout, "skipped (not HCA)\n");
fprintf(stdout, "... skipped (not HCA)\n");
}

delete fileData;
Expand All @@ -233,56 +235,6 @@ ProcessAllBinaries(CAcbFile *acb, uint32_t formatVersion, const Options &options
return 0;
}

static void CopyStream(IStream *src, IStream *dst) {
const size_t bufferSize = 10240;
uint8_t buffer[bufferSize] = {0};
uint32_t read = 1;

while (read > 0) {
read = src->Read(buffer, bufferSize, 0, bufferSize);

if (read > 0) {
dst->Write(buffer, bufferSize, 0, read);
}

if (read < bufferSize) {
break;
}
}
}

// https://stackoverflow.com/a/874160
static bool hasEnding(std::string const &fullString, std::string const &ending) {
if (fullString.length() >= ending.length()) {
return (0 == fullString.compare(fullString.length() - ending.length(), ending.length(), ending));
} else {
return false;
}
}

static string ReplaceExtension(const std::string &s, const std::string &oldExt, const std::string &newExt) {
if (s.size() < oldExt.size()) {
return s;
}

auto sl = s;
auto extl = oldExt;

// ALERT!
// Since the only usage here is replacing extensions, and we promise that the
// extensions are in ASCII, and we don't care about chars before the extension,
// we can use this method (tolower()). Otherwise, it causes trouble for non-
// ASCII encodings.
std::transform(sl.begin(), sl.end(), sl.begin(), ::tolower);
std::transform(extl.begin(), extl.end(), extl.begin(), ::tolower);

if (!hasEnding(sl, extl)) {
return s;
}

return s.substr(0, s.size() - oldExt.size()) + newExt;
}

static void WriteHcaKeyFile(const string &fileName, uint64_t key, uint16_t modifier) {
CFileStream fs(fileName.c_str(), FileMode::Create, FileAccess::Write);
CBinaryWriter writer(&fs);
Expand Down
82 changes: 27 additions & 55 deletions src/apps/acb2wavs/acb2wavs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,31 +9,30 @@
using namespace cgss;
using namespace std;

struct Options {
struct Acb2WavsOptions {
HCA_DECODER_CONFIG decoderConfig;
bool_t useCueName;
};

static void PrintHelp();

static int ParseArgs(int argc, const char *argv[], const char **input, Options &options);
static int ParseArgs(int argc, const char *argv[], const char **input, Acb2WavsOptions &options);

static int DoWork(const string &inputFile, const Options &options);
static int DoWork(const string &inputFile, const Acb2WavsOptions &options);

static int ProcessAllBinaries(CAcbFile *acb, uint32_t formatVersion, const Options &options, const string &extractDir, CAfs2Archive *archive, IStream *dataStream, bool_t isInternal);
static int
ProcessAllBinaries(CAcbFile *acb, uint32_t formatVersion, const Acb2WavsOptions &options, const string &extractDir, CAfs2Archive *archive, IStream *dataStream, bool_t isInternal);

static int DecodeHca(IStream *hcaDataStream, IStream *waveStream, const HCA_DECODER_CONFIG &dc);

static string ReplaceExtension(const std::string &s, const std::string &oldExt, const std::string &newExt);

int main(int argc, const char *argv[]) {
if (argc < 2) {
PrintHelp();
return 0;
}

const char *inputFile;
Options options = {0};
Acb2WavsOptions options = {0};

const auto parsed = ParseArgs(argc, argv, &inputFile, options);

Expand All @@ -52,7 +51,7 @@ static void PrintHelp() {
cout << "\t-n\tUse cue names for output waveforms" << endl;
}

static int ParseArgs(int argc, const char *argv[], const char **input, Options &options) {
static int ParseArgs(int argc, const char *argv[], const char **input, Acb2WavsOptions &options) {
if (argc < 2) {
PrintHelp();
return -1;
Expand Down Expand Up @@ -90,7 +89,7 @@ static int ParseArgs(int argc, const char *argv[], const char **input, Options &
return 0;
}

static int DoWork(const string &inputFile, const Options &options) {
static int DoWork(const string &inputFile, const Acb2WavsOptions &options) {
const auto baseExtractDirPath = CPath::Combine(CPath::GetDirectoryName(inputFile), "_acb_" + CPath::GetFileName(inputFile));

CFileStream fileStream(inputFile.c_str(), FileMode::OpenExisting, FileAccess::Read);
Expand Down Expand Up @@ -155,7 +154,8 @@ static int DoWork(const string &inputFile, const Options &options) {
return 0;
}

static int ProcessAllBinaries(CAcbFile *acb, uint32_t formatVersion, const Options &options, const string &extractDir, CAfs2Archive *archive, IStream *dataStream, bool_t isInternal) {
static int
ProcessAllBinaries(CAcbFile *acb, uint32_t formatVersion, const Acb2WavsOptions &options, const string &extractDir, CAfs2Archive *archive, IStream *dataStream, bool_t isInternal) {
if (!CFileSystem::DirectoryExists(extractDir)) {
if (!CFileSystem::MkDir(extractDir)) {
fprintf(stderr, "Failed to create directory %s.\n", extractDir.c_str());
Expand All @@ -174,27 +174,31 @@ static int ProcessAllBinaries(CAcbFile *acb, uint32_t formatVersion, const Optio

for (auto &entry : archive->GetFiles()) {
auto &record = entry.second;
std::string extractFileName;

if (options.useCueName) {
extractFileName = acb->GetCueNameFromCueId(record.cueId);
extractFileName = ReplaceExtension(extractFileName, ".hca", ".wav");
} else {
extractFileName = CAcbFile::GetSymbolicFileNameFromCueId(record.cueId);
extractFileName = ReplaceExtension(extractFileName, ".bin", ".wav");
}

auto extractFilePath = CPath::Combine(extractDir, extractFileName);

auto fileData = CAcbHelper::ExtractToNewStream(dataStream, record.fileOffsetAligned, (uint32_t)record.fileSize);

const auto isHca = CHcaFormatReader::IsPossibleHcaStream(fileData);

fprintf(stdout, "Processing %s AFS: #%u (offset=%u, size=%u)... ", afsSource, (uint32_t)record.cueId, (uint32_t)record.fileOffsetAligned, (uint32_t)record.fileSize);
fprintf(stdout, "Processing %s AFS: #%u (offset=%u, size=%u)",
afsSource, (uint32_t)record.cueId, (uint32_t)record.fileOffsetAligned, (uint32_t)record.fileSize);

int r;

if (isHca) {
std::string extractFileName;

if (options.useCueName) {
extractFileName = acb->GetCueNameFromCueId(record.cueId);
} else {
extractFileName = CAcbFile::GetSymbolicFileNameFromCueId(record.cueId);
}

extractFileName = common_utils::ReplaceAnyExtension(extractFileName, ".wav");

auto extractFilePath = CPath::Combine(extractDir, extractFileName);

fprintf(stdout, " to %s...\n", extractFilePath.c_str());

try {
CFileStream fs(extractFilePath.c_str(), FileMode::Create, FileAccess::Write);

Expand All @@ -213,7 +217,7 @@ static int ProcessAllBinaries(CAcbFile *acb, uint32_t formatVersion, const Optio
fprintf(stdout, "errored: %s (%d)\n", ex.GetExceptionMessage().c_str(), ex.GetOpResult());
}
} else {
fprintf(stdout, "skipped (not HCA)\n");
fprintf(stdout, "... skipped (not HCA)\n");
}

delete fileData;
Expand All @@ -238,35 +242,3 @@ static int DecodeHca(IStream *hcaDataStream, IStream *waveStream, const HCA_DECO

return 0;
}

// https://stackoverflow.com/a/874160
static bool hasEnding(std::string const &fullString, std::string const &ending) {
if (fullString.length() >= ending.length()) {
return (0 == fullString.compare(fullString.length() - ending.length(), ending.length(), ending));
} else {
return false;
}
}

static string ReplaceExtension(const std::string &s, const std::string &oldExt, const std::string &newExt) {
if (s.size() < oldExt.size()) {
return s;
}

auto sl = s;
auto extl = oldExt;

// ALERT!
// Since the only usage here is replacing extensions, and we promise that the
// extensions are in ASCII, and we don't care about chars before the extension,
// we can use this method (tolower()). Otherwise, it causes trouble for non-
// ASCII encodings.
std::transform(sl.begin(), sl.end(), sl.begin(), ::tolower);
std::transform(extl.begin(), extl.end(), extl.begin(), ::tolower);

if (!hasEnding(sl, extl)) {
return s;
}

return s.substr(0, s.size() - oldExt.size()) + newExt;
}
25 changes: 3 additions & 22 deletions src/apps/acbunpack/acbunpack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#endif

#include "../../lib/cgss_api.h"
#include "../common/common.h"

using namespace cgss;

Expand All @@ -25,8 +26,6 @@ static std::string GetDirectoryFromPath(const std::string &s);

static std::string GetFileNameFromPath(const std::string &s);

static void CopyStream(IStream *src, IStream *dst);

int main(int argc, const char *argv[]) {
if (argc == 1) {
print_help();
Expand Down Expand Up @@ -74,7 +73,8 @@ int main(int argc, const char *argv[]) {

if (stream) {
CFileStream fs(extractPath.c_str(), FileMode::Create, FileAccess::Write);
CopyStream(stream, &fs);

common_utils::CopyStream(stream, &fs);
} else {
fprintf(stderr, "Cue #%u (%s) cannot be retrieved.\n", i + 1, s.c_str());
}
Expand Down Expand Up @@ -135,25 +135,6 @@ static std::string GetFileNameFromPath(const std::string &s) {
}
}

static void CopyStream(IStream *src, IStream *dst) {
const size_t bufferSize = 10240;
uint8_t
buffer[bufferSize] = {0};
uint32_t read = 1;

while (read > 0) {
read = src->Read(buffer, bufferSize, 0, bufferSize);

if (read > 0) {
dst->Write(buffer, bufferSize, 0, read);
}

if (read < bufferSize) {
break;
}
}
}

#if defined(WIN32) || defined(_WIN32)

static void MakeDirectories(const std::string &s) {
Expand Down
Loading

0 comments on commit 3c1ae49

Please sign in to comment.