Skip to content

Commit

Permalink
ACB structure with acbunpack utility.
Browse files Browse the repository at this point in the history
  • Loading branch information
hozuki committed Oct 4, 2018
1 parent 34aea22 commit 3a6c37e
Show file tree
Hide file tree
Showing 31 changed files with 1,314 additions and 66 deletions.
2 changes: 2 additions & 0 deletions cmake/project_files.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ set(HCAINFO_SOURCE_FILES
src/apps/hcainfo/hcainfo.cpp ${LIBCGSS_API_FILES})
set(UTFTABLE_SOURCE_FILES
src/apps/utftable/utftable.c ${LIBCGSS_API_FILES})
set(ACBUNPACK_SOURCE_FILES
src/apps/acbunpack/acbunpack.cpp ${LIBCGSS_API_FILES})

set(LIBCGSS_DEF_FILE src/cgss.def)
set(LIBCGSS_SOURCE_FILES ${LIBCGSS_SOURCE_FILES} ${LIBCGSS_DEF_FILE})
1 change: 1 addition & 0 deletions cmake/project_link.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ target_link_libraries(hcaenc cgss)
target_link_libraries(hca2wav cgss)
target_link_libraries(hcainfo cgss)
target_link_libraries(utftable cgss)
target_link_libraries(acbunpack cgss)
4 changes: 4 additions & 0 deletions cmake/project_postbuild.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ if (${GNU_COMPILER})
POST_BUILD
COMMAND ${CMAKE_STRIP} -s $<TARGET_FILE:utftable>
WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
add_custom_command(TARGET acbunpack
POST_BUILD
COMMAND ${CMAKE_STRIP} -s $<TARGET_FILE:acbunpack>
WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
add_custom_command(TARGET cgss
POST_BUILD
COMMAND ${CMAKE_STRIP} -s $<TARGET_FILE:cgss>
Expand Down
1 change: 1 addition & 0 deletions cmake/project_targets.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ add_executable(hcaenc ${HCAENC_SOURCE_FILES})
add_executable(hca2wav ${HCA2WAV_SOURCE_FILES})
add_executable(hcainfo ${HCAINFO_SOURCE_FILES})
add_executable(utftable ${UTFTABLE_SOURCE_FILES})
add_executable(acbunpack ${ACBUNPACK_SOURCE_FILES})
add_library(cgss SHARED ${LIBCGSS_SOURCE_FILES})

if (${BUILD_JNI_INTERFACE})
Expand Down
183 changes: 183 additions & 0 deletions src/apps/acbunpack/acbunpack.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
#include <stdio.h>
#include <inttypes.h>
#include <string.h>

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

#include <windows.h>

#else
#include <sys/stat.h>
#endif

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

using namespace cgss;

void print_help();

void MakeDirectories(const std::string &s);

std::string GetDirectoryFromPath(const std::string &s);

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

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

int main(int argc, const char *argv[]) {
if (argc == 1) {
print_help();
return 0;
}

const char *filePath = argv[1];

if (!cgssHelperFileExists(filePath)) {
fprintf(stderr, "File '%s' does not exist or cannot be opened.\n", filePath);
return -1;
}

auto *fileStream = new CFileStream(filePath, FileMode::OpenExisting, FileAccess::Read);
auto *acb = new CAcbFile(fileStream, filePath);

const std::string fileDir = GetDirectoryFromPath(filePath);
const std::string extractDir = fileDir + "/_acb_" + GetFileNameFromPath(filePath) + "/";

acb->Initialize();

MakeDirectories(extractDir);

const auto &fileNames = acb->GetFileNames();

uint32_t i = 0;
for (const auto &fileName : fileNames) {
auto s = fileName;
auto isCueNonEmpty = !s.empty();

if (!isCueNonEmpty) {
s = CAcbFile::GetSymbolicFileNameFromCueId(i);
}

auto extractPath = extractDir + s;

IStream *stream;

if (isCueNonEmpty) {
stream = acb->OpenDataStream(s.c_str());
} else {
stream = acb->OpenDataStream(i);
}

if (stream) {
CFileStream fs(extractPath.c_str(), FileMode::Create, FileAccess::Write);
CopyStream(stream, &fs);
} else {
fprintf(stderr, "Cue #%u (%s) cannot be retrieved.\n", i + 1, s.c_str());
}

delete stream;

++i;
}

delete acb;
delete fileStream;
}

void print_help() {
fprintf(stderr, "Usage:\n\n\tacbunpack <file>\n");
}

std::string GetDirectoryFromPath(const std::string &s) {
const char sep1 = '/', sep2 = '\\';

size_t i1 = s.rfind(sep1, s.length());
size_t i2 = s.rfind(sep2, s.length());

if (i1 != std::string::npos) {
if (i2 != std::string::npos) {
auto i = i1 > i2 ? i1 : i2;
return (s.substr(0, i));
} else {
return (s.substr(0, i1));
}
} else {
if (i2 != std::string::npos) {
return (s.substr(0, i2));
} else {
return std::string("");
}
}
}

std::string GetFileNameFromPath(const std::string &s) {
const char sep1 = '/', sep2 = '\\';

size_t i1 = s.rfind(sep1, s.length());
size_t i2 = s.rfind(sep2, s.length());

if (i1 != std::string::npos) {
if (i2 != std::string::npos) {
auto i = i1 > i2 ? i1 : i2;
return (s.substr(i + 1));
} else {
return (s.substr(i1 + 1));
}
} else {
if (i2 != std::string::npos) {
return (s.substr(i2 + 1));
} else {
return std::string("");
}
}
}

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)

void MakeDirectories(const std::string &s) {
CreateDirectory(s.c_str(), nullptr);
}

#else

void MakeDirectories(const std::string &s) {
char str[512] = {0};

strncpy(str, s.c_str(), 512);
auto len = strlen(str);

for (auto i = 0; i < len; i++) {
if (str[i] == '/') {
str[i] = '\0';
if (access(str, 0) != 0) {
mkdir(str, 0777);
}
str[i] = '/';
}
}

if (len > 0 && access(str, 0) != 0) {
mkdir(str, 0777);
}
}

#endif
21 changes: 21 additions & 0 deletions src/lib/cdata/ACB_CUE_RECORD.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#pragma once

#include "../cgss_env.h"

#define ACB_CUE_RECORD_NAME_MAX_LEN (256)

struct ACB_CUE_RECORD {

uint32_t cueId;
uint8_t referenceType;
uint16_t referenceIndex;

bool_t isWaveformIdentified;
uint16_t waveformIndex;
uint16_t waveformId;
uint8_t encodeType;
bool_t isStreaming;

char cueName[ACB_CUE_RECORD_NAME_MAX_LEN];

};
15 changes: 15 additions & 0 deletions src/lib/cdata/AFS2_FILE_RECORD.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#pragma once

#include <stdint.h>

#define AFS2_FILE_NAME_MAX_LEN (256)

struct AFS2_FILE_RECORD {

uint16_t cueId;
uint64_t fileOffsetRaw;
uint64_t fileOffsetAligned;
uint64_t fileSize;
char fileName[AFS2_FILE_NAME_MAX_LEN];

};
2 changes: 2 additions & 0 deletions src/lib/cgss_cdata.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@
#include "cdata/UTF_HEADER.h"
#include "cdata/UTF_ROW.h"
#include "cdata/UTF_TABLE.h"
#include "cdata/AFS2_FILE_RECORD.h"
#include "cdata/ACB_CUE_RECORD.h"
2 changes: 2 additions & 0 deletions src/lib/cgss_intf.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,5 @@
#include "ichinose/CUtfField.h"
#include "ichinose/CUtfReader.h"
#include "ichinose/CUtfTable.h"
#include "ichinose/CAfs2Archive.h"
#include "ichinose/CAcbFile.h"
Loading

0 comments on commit 3a6c37e

Please sign in to comment.