1
0
mirror of https://github.com/rwengine/openrw.git synced 2024-11-07 03:12:36 +01:00
openrw/rwcore/loaders/LoaderSDT.cpp
Daniel Evans 4fd92a1549 Rename rwlib library to "core" to fit its new role
Also move up source files into the root directory, as there's nothing else in this directory
2018-08-09 20:28:24 +01:00

128 lines
3.8 KiB
C++

#include "loaders/LoaderSDT.hpp"
#include <cstring>
#include <cstdio>
#include <string>
#include "rw/debug.hpp"
bool LoaderSDT::load(const rwfs::path& path) {
const auto sdtName = path.string() + ".SDT";
const auto rawName = path.string() + ".RAW";
FILE* fp = fopen(sdtName.c_str(), "rb");
if (fp) {
fseek(fp, 0, SEEK_END);
unsigned long fileSize = ftell(fp);
fseek(fp, 0, SEEK_SET);
m_assetCount = fileSize / 20;
m_assets.resize(m_assetCount);
if ((m_assetCount = fread(&m_assets[0], sizeof(LoaderSDTFile),
m_assetCount, fp)) != fileSize / 20) {
m_assets.resize(m_assetCount);
RW_ERROR("Error reading records in SDT archive");
}
fclose(fp);
m_archive = rawName;
return true;
} else {
RW_ERROR("Error cannot find " << path);
return false;
}
}
/// Get the information of a asset in the examining archive
bool LoaderSDT::findAssetInfo(size_t index, LoaderSDTFile& out) {
if (index < m_assets.size()) {
out = m_assets[index];
return true;
}
return false;
}
std::unique_ptr<char[]> LoaderSDT::loadToMemory(size_t index, bool asWave) {
bool found = findAssetInfo(index, assetInfo);
if (!found) {
RW_ERROR("Asset " << std::to_string(index) << " not found!");
return nullptr;
}
std::string rawName = m_archive;
FILE* fp = fopen(rawName.c_str(), "rb");
if (fp) {
std::unique_ptr<char[]> raw_data;
char* sample_data;
if (asWave) {
raw_data = std::make_unique<char[]>(sizeof(WaveHeader) + assetInfo.size);
auto header = reinterpret_cast<WaveHeader*>(raw_data.get());
memcpy(header->chunkId, "RIFF", 4);
header->chunkSize = sizeof(WaveHeader) - 8 + assetInfo.size;
memcpy(header->format, "WAVE", 4);
memcpy(header->fmt.id, "fmt ", 4);
header->fmt.size = sizeof(WaveHeader::fmt) - 8;
header->fmt.audioFormat = 1; // PCM
header->fmt.numChannels = 1; // Mono
header->fmt.sampleRate = assetInfo.sampleRate;
header->fmt.byteRate = assetInfo.sampleRate * 2;
header->fmt.blockAlign = 2;
header->fmt.bitsPerSample = 16;
memcpy(header->data.id, "data", 4);
header->data.size = assetInfo.size;
sample_data = raw_data.get() + sizeof(WaveHeader);
} else {
raw_data = std::make_unique<char[]>(assetInfo.size);
sample_data = raw_data.get();
}
fseek(fp, assetInfo.offset, SEEK_SET);
if (fread(sample_data, 1, assetInfo.size, fp) != assetInfo.size) {
RW_ERROR("Error reading asset " << std::to_string(index));
}
fclose(fp);
return raw_data;
} else
return nullptr;
}
/// Writes the contents of assetname to filename
bool LoaderSDT::saveAsset(size_t index, const std::string& filename,
bool asWave) {
auto raw_sound = loadToMemory(index, asWave);
if (!raw_sound) return false;
FILE* dumpFile = fopen(filename.c_str(), "wb");
if (dumpFile) {
if (findAssetInfo(index, assetInfo)) {
fwrite(raw_sound.get(), 1, assetInfo.size + (asWave ? sizeof(WaveHeader) : 0),
dumpFile);
printf("=> SDT: Saved %zu to disk with filename %s\n", index,
filename.c_str());
}
fclose(dumpFile);
return true;
} else {
return false;
}
}
const LoaderSDTFile& LoaderSDT::getAssetInfoByIndex(size_t index) const {
return m_assets[index];
}
uint32_t LoaderSDT::getAssetCount() const {
return m_assetCount;
}
LoaderSDT::Version LoaderSDT::getVersion() const {
return m_version;
}