Skip to content

Commit

Permalink
Unified batch ACB content extraction, and fixed #10
Browse files Browse the repository at this point in the history
  • Loading branch information
hozuki committed Apr 15, 2020
1 parent 2b717b3 commit 542bf64
Show file tree
Hide file tree
Showing 10 changed files with 466 additions and 344 deletions.
22 changes: 12 additions & 10 deletions cmake/project_files.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,30 @@ file(GLOB_RECURSE LIBCGSS_INS_SOURCE_FILES "src/lib/ichinose/*.h" "src/lib/ichin
set(LIBCGSS_SOURCE_FILES
${LIBCGSS_API_FILES} ${LIBCGSS_COMMON_HEADER_FILES} ${LIBCGSS_COMMON_SOURCE_FILES} ${LIBCGSS_KS_SOURCE_FILES} ${LIBCGSS_TM_SOURCE_FILES} ${LIBCGSS_INS_SOURCE_FILES})

set(CGSS_APP_SOURCE_FILES
set(CGSS_API_HEADER_FILES
src/apps/cgssh.h)

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

set(HCACC_SOURCE_FILES
src/apps/hcacc/hcacc.cpp ${CGSS_APP_SOURCE_FILES} ${APP_SOURCE_FILES} ${LIBCGSS_API_FILES})
src/apps/hcacc/hcacc.cpp ${CGSS_API_HEADER_FILES} ${APP_SOURCE_FILES} ${LIBCGSS_API_FILES})
set(HCAENC_SOURCE_FILES
src/apps/hcaenc/hcaenc.cpp ${CGSS_APP_SOURCE_FILES} ${APP_SOURCE_FILES} ${LIBCGSS_TM_API_FILES})
src/apps/hcaenc/hcaenc.cpp ${CGSS_API_HEADER_FILES} ${APP_SOURCE_FILES} ${LIBCGSS_TM_API_FILES})
set(HCA2WAV_SOURCE_FILES
src/apps/hca2wav/hca2wav.cpp ${CGSS_APP_SOURCE_FILES} ${APP_SOURCE_FILES} ${LIBCGSS_API_FILES})
src/apps/hca2wav/hca2wav.cpp ${CGSS_API_HEADER_FILES} ${APP_SOURCE_FILES} ${LIBCGSS_API_FILES})
set(HCAINFO_SOURCE_FILES
src/apps/hcainfo/hcainfo.cpp ${APP_SOURCE_FILES} ${LIBCGSS_API_FILES})
src/apps/hcainfo/hcainfo.cpp ${APP_COMMON_SOURCE_FILES} ${LIBCGSS_API_FILES})
set(UTFTABLE_SOURCE_FILES
src/apps/utftable/utftable.c ${APP_SOURCE_FILES} ${LIBCGSS_API_FILES})
src/apps/utftable/utftable.c ${APP_COMMON_SOURCE_FILES} ${LIBCGSS_API_FILES})
set(ACBUNPACK_SOURCE_FILES
src/apps/acbunpack/acbunpack.cpp ${APP_SOURCE_FILES} ${LIBCGSS_API_FILES})
src/apps/acbunpack/acbunpack.cpp ${APP_COMMON_SOURCE_FILES} ${LIBCGSS_API_FILES} ${APP_ACB_EXTRACT_COMMON_FILES})
set(ACB2WAVS_SOURCE_FILES
src/apps/acb2wavs/acb2wavs.cpp ${CGSS_APP_SOURCE_FILES} ${APP_SOURCE_FILES} ${LIBCGSS_API_FILES})
src/apps/acb2wavs/acb2wavs.cpp ${CGSS_API_HEADER_FILES} ${APP_COMMON_SOURCE_FILES} ${LIBCGSS_API_FILES} ${APP_ACB_EXTRACT_COMMON_FILES})
set(ACB2HCAS_SOURCE_FILES
src/apps/acb2hcas/acb2hcas.cpp ${APP_SOURCE_FILES} ${LIBCGSS_API_FILES})
src/apps/acb2hcas/acb2hcas.cpp ${APP_COMMON_SOURCE_FILES} ${LIBCGSS_API_FILES} ${APP_ACB_EXTRACT_COMMON_FILES})

set(LIBCGSS_DEF_FILE src/cgss.def)
set(LIBCGSS_SOURCE_FILES ${LIBCGSS_SOURCE_FILES} ${LIBCGSS_DEF_FILE})
148 changes: 27 additions & 121 deletions src/apps/acb2hcas/acb2hcas.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

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

using namespace std;
using namespace cgss;
Expand All @@ -27,8 +28,7 @@ static int ParseArgs(int argc, const char *argv[], const char **input, Acb2HcasO

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

static int
ProcessAllBinaries(CAcbFile *acb, uint32_t formatVersion, const Acb2HcasOptions &options, const string &extractDir, CAfs2Archive *archive, IStream *dataStream, bool_t isInternal);
static int ProcessHca(AcbWalkCallbackParams *params);

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

Expand Down Expand Up @@ -100,139 +100,45 @@ static int ParseArgs(int argc, const char *argv[], const char **input, Acb2HcasO
}

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

CFileStream fileStream(inputFile.c_str(), FileMode::OpenExisting, FileAccess::Read);
CAcbFile acb(&fileStream, inputFile.c_str());
o.callback = ProcessHca;
o.decoderConfig.cipherConfig.key = options.key;
o.useCueName = options.useCueName;

acb.Initialize();

CAfs2Archive *archive = nullptr;
uint32_t formatVersion = acb.GetFormatVersion();
int r;

try {
archive = acb.GetInternalAwb();
} catch (CException &ex) {
fprintf(stderr, "%s (%d)\n", ex.GetExceptionMessage().c_str(), ex.GetOpResult());
archive = nullptr;
}

if (archive) {
const auto extractDir = CPath::Combine(baseExtractDirPath, "internal");

try {
r = ProcessAllBinaries(&acb, formatVersion, options, extractDir, archive, acb.GetStream(), TRUE);
} catch (CException &ex) {
fprintf(stderr, "%s (%d)\n", ex.GetExceptionMessage().c_str(), ex.GetOpResult());
r = -1;
}

delete archive;

if (r != 0) {
return r;
}
}

try {
archive = acb.GetExternalAwb();
} catch (CException &ex) {
fprintf(stderr, "%s (%d)\n", ex.GetExceptionMessage().c_str(), ex.GetOpResult());
archive = nullptr;
}

if (archive) {
const auto extractDir = CPath::Combine(baseExtractDirPath, "external");

try {
CFileStream fs(archive->GetFileName(), FileMode::OpenExisting, FileAccess::Read);

r = ProcessAllBinaries(&acb, formatVersion, options, extractDir, archive, &fs, FALSE);
} catch (CException &ex) {
fprintf(stderr, "%s (%d)\n", ex.GetExceptionMessage().c_str(), ex.GetOpResult());
r = -1;
}

delete archive;

if (r != 0) {
return r;
}
}

return 0;
return AcbWalk(inputFile, &o);
}

static int
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());
return -1;
}
}
static int ProcessHca(AcbWalkCallbackParams *params) {
const auto afsSourceDesc = params->isInternal ? "internal" : "external";
const auto isHca = CHcaFormatReader::IsPossibleHcaStream(params->entryDataStream);

const auto afsSource = isInternal ? "internal" : "external";
fprintf(stdout, "Processing %s AFS: #%" PRIu32 " (offset=%" PRIu32 ", size=%" PRIu32 ")",
afsSourceDesc, (uint32_t)params->cueInfo.id, (uint32_t)params->cueInfo.offset, (uint32_t)params->cueInfo.size);

uint16_t keyModifier;
if (isHca) {
std::string extractFilePath = common_utils::ReplaceAnyExtension(params->extractPathHint, ".hca");
std::string hcaKeyFilePath = common_utils::ReplaceAnyExtension(params->extractPathHint, ".hcakey");

if (formatVersion >= CAcbFile::KEY_MODIFIER_ENABLED_VERSION) {
keyModifier = archive->GetHcaKeyModifier();
} else {
keyModifier = 0;
}

const auto &fileList = archive->GetFiles();

for (auto &entry : fileList) {
auto &record = entry.second;
fprintf(stdout, " to %s...\n", extractFilePath.c_str());

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

const auto isHca = CHcaFormatReader::IsPossibleHcaStream(fileData);
try {
CFileStream hcaFile(extractFilePath.c_str(), FileMode::Create, FileAccess::Write);

fprintf(stdout, "Processing %s AFS: #%" PRIu32 " (offset=%" PRIu32 ", size=%" PRIu32 ")",
afsSource, (uint32_t)record.cueId, (uint32_t)record.fileOffsetAligned, (uint32_t)record.fileSize);
common_utils::CopyStream(params->entryDataStream, &hcaFile);

if (isHca) {
std::string extractFileName;
std::string hcaKeyFileName;
WriteHcaKeyFile(hcaKeyFilePath, params->walkOptions->decoderConfig.cipherConfig.key, params->walkOptions->decoderConfig.cipherConfig.keyModifier);

if (options.useCueName) {
extractFileName = acb->GetCueNameFromCueId(record.cueId);
} else {
extractFileName = CAcbFile::GetSymbolicFileNameFromCueId(record.cueId);
fprintf(stdout, "exported\n");
} catch (CException &ex) {
if (CFileSystem::FileExists(extractFilePath)) {
CFileSystem::RmFile(extractFilePath);
}

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);

common_utils::CopyStream(fileData, &hcaFile);

WriteHcaKeyFile(hcaKeyFilePath, options.key, keyModifier);

fprintf(stdout, "exported\n");
} catch (CException &ex) {
if (CFileSystem::FileExists(extractFilePath)) {
CFileSystem::RmFile(extractFilePath);
}

fprintf(stdout, "errored: %s (%d)\n", ex.GetExceptionMessage().c_str(), ex.GetOpResult());
}
} else {
fprintf(stdout, "... skipped (not HCA)\n");
fprintf(stdout, "errored: %s (%d)\n", ex.GetExceptionMessage().c_str(), ex.GetOpResult());
}

delete fileData;
} else {
fprintf(stdout, "... skipped (not HCA)\n");
}

return 0;
Expand Down
Loading

0 comments on commit 542bf64

Please sign in to comment.