Skip to content

Commit

Permalink
add dlc_extract
Browse files Browse the repository at this point in the history
  • Loading branch information
PredatorCZ committed Oct 9, 2024
1 parent 48736a6 commit 08ec76c
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 1 deletion.
2 changes: 1 addition & 1 deletion 3rd_party/spike
1 change: 1 addition & 0 deletions toolset/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ add_spike_subdir(udas_extract)
add_spike_subdir(obb_extract)
add_spike_subdir(lmt_to_gltf)
add_spike_subdir(sdl_conv)
add_spike_subdir(dlc_extract)

if(NOT ${CMAKE_BUILD_TYPE} STREQUAL "Release")
add_spike_subdir(dev)
Expand Down
21 changes: 21 additions & 0 deletions toolset/dlc_extract/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
project(DLCExtract)

build_target(
NAME
dlc_extract
TYPE
ESMODULE
VERSION
1
SOURCES
dlc_extract.cpp
LINKS
revil-interface
INCLUDES
${CMAKE_SOURCE_DIR}/src/
AUTHOR
"Lukas Cone"
DESCR
"DLC Archive Extractor"
START_YEAR
2024)
110 changes: 110 additions & 0 deletions toolset/dlc_extract/dlc_extract.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/* DLCExtract
Copyright(C) 2024 Lukas Cone
This program is free software : you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program.If not, see <https://www.gnu.org/licenses/>.
*/

#include "hfs.hpp"
#include "project.h"
#include "spike/app_context.hpp"
#include "spike/except.hpp"
#include "spike/io/binreader_stream.hpp"
#include "spike/io/stat.hpp"
#include "spike/master_printer.hpp"
#include "spike/reflect/reflector.hpp"
#include <charconv>
#include <sstream>

std::string_view filters[]{
".dat$",
};

static AppInfo_s appInfo{
.filteredLoad = true,
.header = DLCExtract_DESC " v" DLCExtract_VERSION ", " DLCExtract_COPYRIGHT
"Lukas Cone",
.filters = filters,
};

AppInfo_s *AppInitModule() { return &appInfo; }

void AppProcessFile(AppContext *ctx) {
std::stringstream backup;
BinReaderRef_e rd(ctx->GetStream());
uint32 id;
rd.Push();
rd.Read(id);

if (id == SFHID) {
rd.Pop();
backup = ProcessHFS(rd);
rd = BinReaderRef_e(backup);
rd.Push();
rd.Read(id);
}

if (id != CompileFourCC("DLC")) {
rd.SwapEndian(true);
rd.Pop();
rd.Read(id);
if (id != CompileFourCC("DLC")) {
throw es::InvalidHeaderError(id);
}
}

uint8 version;
rd.Read(version);

if (version != 3) {
throw es::InvalidVersionError(version);
}

std::string name;
rd.ReadString(name);

struct File {
std::string path;
uint32 offset;
};

std::vector<File> files;
rd.ReadContainerLambda(files, [](BinReaderRef_e rd, File &file) {
rd.ReadContainer<uint8>(file.path);
rd.Read(file.offset);
});

auto ectx = ctx->ExtractContext();

if (ectx->RequiresFolders()) {
for (auto &f : files) {
ectx->AddFolderPath(f.path);
}

ectx->GenerateFolders();
}

std::string buffer;
const size_t arSize = rd.GetSize();

for (size_t curFile = 1; auto &f : files) {
rd.Seek(f.offset);
const size_t fileEnd =
curFile >= files.size() ? arSize : files.at(curFile).offset;
const size_t fileSize = fileEnd - f.offset;
rd.ReadContainer(buffer, fileSize);
ectx->NewFile(f.path);
ectx->SendData(buffer);
curFile++;
}
}

0 comments on commit 08ec76c

Please sign in to comment.