mirror of
https://github.com/OpenRCT2/OpenRCT2.git
synced 2025-01-22 18:31:59 -05:00
Merge pull request #7492 from IntelOrca/refactor/ziparchive
Improve IZipArchive so that it is more C++
This commit is contained in:
commit
0df569f0e2
9 changed files with 190 additions and 216 deletions
|
@ -1,4 +1,4 @@
|
|||
#pragma region Copyright (c) 2014-2017 OpenRCT2 Developers
|
||||
#pragma region Copyright (c) 2014-2018 OpenRCT2 Developers
|
||||
/*****************************************************************************
|
||||
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
|
||||
*
|
||||
|
@ -21,6 +21,7 @@
|
|||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#include <fstream>
|
||||
#include "File.h"
|
||||
#include "FileStream.hpp"
|
||||
#include "String.hpp"
|
||||
|
@ -50,12 +51,23 @@ namespace File
|
|||
return platform_file_move(srcPath.c_str(), dstPath.c_str());
|
||||
}
|
||||
|
||||
void * ReadAllBytes(const std::string &path, size_t * length)
|
||||
std::vector<uint8> ReadAllBytes(const std::string_view& path)
|
||||
{
|
||||
void * result = nullptr;
|
||||
std::vector<uint8> result;
|
||||
|
||||
FileStream fs = FileStream(path, FILE_MODE_OPEN);
|
||||
uint64 fsize = fs.GetLength();
|
||||
#if defined(_WIN32) && !defined(__MINGW32__)
|
||||
auto pathW = String::ToUtf16(path.data());
|
||||
std::ifstream fs(pathW, std::ios::in | std::ios::binary);
|
||||
#else
|
||||
std::ifstream fs(path.data(), std::ios::in | std::ios::binary);
|
||||
#endif
|
||||
if (!fs.is_open())
|
||||
{
|
||||
throw IOException("Unable to open " + std::string(path.data()));
|
||||
}
|
||||
|
||||
fs.seekg(0, std::ios::end);
|
||||
auto fsize = (size_t)fs.tellg();
|
||||
if (fsize > SIZE_MAX)
|
||||
{
|
||||
std::string message = String::StdFormat("'%s' exceeds maximum length of %lld bytes.", SIZE_MAX);
|
||||
|
@ -63,9 +75,11 @@ namespace File
|
|||
}
|
||||
else
|
||||
{
|
||||
result = fs.ReadArray<uint8>((size_t)fsize);
|
||||
result.resize(fsize);
|
||||
fs.seekg(0);
|
||||
fs.read((char *)result.data(), result.size());
|
||||
fs.exceptions(fs.failbit);
|
||||
}
|
||||
*length = (size_t)fsize;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -78,12 +92,11 @@ namespace File
|
|||
std::vector<std::string> ReadAllLines(const std::string &path)
|
||||
{
|
||||
std::vector<std::string> lines;
|
||||
size_t length;
|
||||
char * data = (char *)ReadAllBytes(path, &length);
|
||||
char * lineStart = data;
|
||||
char * ch = data;
|
||||
auto data = ReadAllBytes(path);
|
||||
auto lineStart = (const char *)data.data();
|
||||
auto ch = lineStart;
|
||||
char lastC = 0;
|
||||
for (size_t i = 0; i < length; i++)
|
||||
for (size_t i = 0; i < data.size(); i++)
|
||||
{
|
||||
char c = *ch;
|
||||
if (c == '\n' && lastC == '\r')
|
||||
|
@ -102,8 +115,6 @@ namespace File
|
|||
|
||||
// Last line
|
||||
lines.emplace_back(lineStart, ch - lineStart);
|
||||
|
||||
Memory::Free(data);
|
||||
return lines;
|
||||
}
|
||||
|
||||
|
@ -134,19 +145,6 @@ namespace File
|
|||
}
|
||||
} // namespace File
|
||||
|
||||
bool readentirefile(const utf8 * path, void * * outBuffer, size_t * outLength)
|
||||
{
|
||||
try
|
||||
{
|
||||
*outBuffer = File::ReadAllBytes(String::ToStd(path), outLength);
|
||||
return true;
|
||||
}
|
||||
catch (const std::exception &)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool writeentirefile(const utf8 * path, const void * buffer, size_t length)
|
||||
{
|
||||
try
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
#include "../common.h"
|
||||
|
||||
|
@ -26,7 +27,7 @@ namespace File
|
|||
bool Copy(const std::string &srcPath, const std::string &dstPath, bool overwrite);
|
||||
bool Delete(const std::string &path);
|
||||
bool Move(const std::string &srcPath, const std::string &dstPath);
|
||||
void * ReadAllBytes(const std::string &path, size_t * length);
|
||||
std::vector<uint8> ReadAllBytes(const std::string_view& path);
|
||||
void WriteAllBytes(const std::string &path, const void * buffer, size_t length);
|
||||
std::vector<std::string> ReadAllLines(const std::string &path);
|
||||
uint64 GetLastModified(const std::string &path);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#pragma region Copyright (c) 2014-2017 OpenRCT2 Developers
|
||||
#pragma region Copyright (c) 2014-2018 OpenRCT2 Developers
|
||||
/*****************************************************************************
|
||||
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
|
||||
*
|
||||
|
@ -17,26 +17,26 @@
|
|||
#ifndef __ANDROID__
|
||||
#include <zip.h>
|
||||
#include "IStream.hpp"
|
||||
#include "MemoryStream.h"
|
||||
#include "Zip.h"
|
||||
|
||||
class ZipArchive final : public IZipArchive
|
||||
{
|
||||
private:
|
||||
zip_t * _zip;
|
||||
ZIP_ACCESS _access;
|
||||
zip_t * _zip;
|
||||
ZIP_ACCESS _access;
|
||||
std::vector<std::vector<uint8>> _writeBuffers;
|
||||
|
||||
public:
|
||||
ZipArchive(const utf8 * path, ZIP_ACCESS access)
|
||||
ZipArchive(const std::string_view& path, ZIP_ACCESS access)
|
||||
{
|
||||
sint32 zipOpenMode = ZIP_RDONLY;
|
||||
if (access == ZIP_ACCESS_WRITE)
|
||||
auto zipOpenMode = ZIP_RDONLY;
|
||||
if (access == ZIP_ACCESS::WRITE)
|
||||
{
|
||||
zipOpenMode = ZIP_CREATE;
|
||||
}
|
||||
|
||||
sint32 error;
|
||||
_zip = zip_open(path, zipOpenMode, &error);
|
||||
_zip = zip_open(path.data(), zipOpenMode, &error);
|
||||
if (_zip == nullptr)
|
||||
{
|
||||
throw IOException("Unable to open zip file.");
|
||||
|
@ -55,10 +55,15 @@ public:
|
|||
return zip_get_num_files(_zip);
|
||||
}
|
||||
|
||||
const utf8 * GetFileName(size_t index) const override
|
||||
std::string GetFileName(size_t index) const override
|
||||
{
|
||||
const utf8 * name = zip_get_name(_zip, index, ZIP_FL_ENC_GUESS);
|
||||
return name;
|
||||
std::string result;
|
||||
auto name = zip_get_name(_zip, index, ZIP_FL_ENC_GUESS);
|
||||
if (name != nullptr)
|
||||
{
|
||||
result = name;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
uint64 GetFileSize(size_t index) const override
|
||||
|
@ -74,51 +79,41 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void * GetFileData(const utf8 * path, size_t * outSize) const override
|
||||
std::vector<uint8> GetFileData(const std::string_view& path) const override
|
||||
{
|
||||
void * data = nullptr;
|
||||
|
||||
size_t index = (size_t)zip_name_locate(_zip, path, 0);
|
||||
uint64 dataSize = GetFileSize(index);
|
||||
std::vector<uint8> result;
|
||||
auto index = (size_t)zip_name_locate(_zip, path.data(), 0);
|
||||
auto dataSize = GetFileSize(index);
|
||||
if (dataSize > 0 && dataSize < SIZE_MAX)
|
||||
{
|
||||
zip_file_t * zipFile = zip_fopen(_zip, path, 0);
|
||||
auto zipFile = zip_fopen(_zip, path.data(), 0);
|
||||
if (zipFile != nullptr)
|
||||
{
|
||||
data = Memory::Allocate<void>((size_t)dataSize);
|
||||
uint64 readBytes = zip_fread(zipFile, data, dataSize);
|
||||
result.resize((size_t)dataSize);
|
||||
uint64 readBytes = zip_fread(zipFile, result.data(), dataSize);
|
||||
if (readBytes != dataSize)
|
||||
{
|
||||
SafeFree(data);
|
||||
dataSize = 0;
|
||||
result.clear();
|
||||
result.shrink_to_fit();
|
||||
}
|
||||
zip_fclose(zipFile);
|
||||
}
|
||||
}
|
||||
|
||||
if (outSize != nullptr) *outSize = (size_t)dataSize;
|
||||
return data;
|
||||
return result;
|
||||
}
|
||||
|
||||
IStream * GetFileStream(const utf8 * path) const override
|
||||
void SetFileData(const std::string_view& path, std::vector<uint8>&& data) override
|
||||
{
|
||||
IStream * stream = nullptr;
|
||||
size_t dataSize;
|
||||
void * data = GetFileData(path, &dataSize);
|
||||
if (data != nullptr)
|
||||
{
|
||||
stream = new MemoryStream(data, dataSize, MEMORY_ACCESS::READ | MEMORY_ACCESS::OWNER);
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
// Push buffer to an internal list as libzip requires access to it until the zip
|
||||
// handle is closed.
|
||||
_writeBuffers.push_back(std::move(data));
|
||||
const auto& writeBuffer = *_writeBuffers.rbegin();
|
||||
|
||||
void SetFileData(const utf8 * path, void * data, size_t dataSize) override
|
||||
{
|
||||
zip_source_t * source = zip_source_buffer(_zip, data, dataSize, 0);
|
||||
sint64 index = zip_name_locate(_zip, path, 0);
|
||||
auto source = zip_source_buffer(_zip, writeBuffer.data(), writeBuffer.size(), 0);
|
||||
auto index = zip_name_locate(_zip, path.data(), 0);
|
||||
if (index == -1)
|
||||
{
|
||||
zip_add(_zip, path, source);
|
||||
zip_add(_zip, path.data(), source);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -126,34 +121,34 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void DeleteFile(const utf8 * path) override
|
||||
void DeleteFile(const std::string_view& path) override
|
||||
{
|
||||
uint64 index = zip_name_locate(_zip, path, 0);
|
||||
auto index = zip_name_locate(_zip, path.data(), 0);
|
||||
zip_delete(_zip, index);
|
||||
}
|
||||
|
||||
void RenameFile(const utf8 * path, const utf8 * newPath) override
|
||||
void RenameFile(const std::string_view& path, const std::string_view& newPath) override
|
||||
{
|
||||
uint64 index = zip_name_locate(_zip, path, 0);
|
||||
zip_file_rename(_zip, index, newPath, ZIP_FL_ENC_GUESS);
|
||||
auto index = zip_name_locate(_zip, path.data(), 0);
|
||||
zip_file_rename(_zip, index, newPath.data(), ZIP_FL_ENC_GUESS);
|
||||
}
|
||||
};
|
||||
|
||||
namespace Zip
|
||||
{
|
||||
IZipArchive * Open(const utf8 * path, ZIP_ACCESS access)
|
||||
std::unique_ptr<IZipArchive> Open(const std::string_view& path, ZIP_ACCESS access)
|
||||
{
|
||||
return new ZipArchive(path, access);
|
||||
return std::make_unique<ZipArchive>(path, access);
|
||||
}
|
||||
|
||||
IZipArchive * TryOpen(const utf8 * path, ZIP_ACCESS access)
|
||||
std::unique_ptr<IZipArchive> TryOpen(const std::string_view& path, ZIP_ACCESS access)
|
||||
{
|
||||
IZipArchive * result = nullptr;
|
||||
std::unique_ptr<IZipArchive> result;
|
||||
try
|
||||
{
|
||||
result = new ZipArchive(path, access);
|
||||
result = std::make_unique<ZipArchive>(path, access);
|
||||
}
|
||||
catch (const std::exception &)
|
||||
catch (const std::exception&)
|
||||
{
|
||||
}
|
||||
return result;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#pragma region Copyright (c) 2014-2017 OpenRCT2 Developers
|
||||
#pragma region Copyright (c) 2014-2018 OpenRCT2 Developers
|
||||
/*****************************************************************************
|
||||
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
|
||||
*
|
||||
|
@ -16,10 +16,11 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
#include "../common.h"
|
||||
|
||||
interface IStream;
|
||||
|
||||
/**
|
||||
* Represents a zip file.
|
||||
*/
|
||||
|
@ -27,33 +28,30 @@ interface IZipArchive
|
|||
{
|
||||
virtual ~IZipArchive() { }
|
||||
|
||||
virtual size_t GetNumFiles() const abstract;
|
||||
virtual const utf8 * GetFileName(size_t index) const abstract;
|
||||
virtual uint64 GetFileSize(size_t index) const abstract;
|
||||
virtual void * GetFileData(const utf8 * path, size_t * outSize) const abstract;
|
||||
virtual IStream * GetFileStream(const utf8 * path) const abstract;
|
||||
virtual size_t GetNumFiles() const abstract;
|
||||
virtual std::string GetFileName(size_t index) const abstract;
|
||||
virtual uint64 GetFileSize(size_t index) const abstract;
|
||||
virtual std::vector<uint8> GetFileData(const std::string_view& path) const abstract;
|
||||
|
||||
/**
|
||||
* Creates or overwrites a file within the zip archive to the given data buffer.
|
||||
* @param path The path of the file within the zip.
|
||||
* @param data The data to write, this buffer must not be mutated or disposed until
|
||||
* the zip archive has been disposed.
|
||||
* @param dataSize The size of the data in bytes.
|
||||
* @param data The data to write.
|
||||
*/
|
||||
virtual void SetFileData(const utf8 * path, void * data, size_t dataSize) abstract;
|
||||
virtual void SetFileData(const std::string_view& path, std::vector<uint8>&& data) abstract;
|
||||
|
||||
virtual void DeleteFile(const utf8 * path) abstract;
|
||||
virtual void RenameFile(const utf8 * path, const utf8 * newPath) abstract;
|
||||
virtual void DeleteFile(const std::string_view& path) abstract;
|
||||
virtual void RenameFile(const std::string_view& path, const std::string_view& newPath) abstract;
|
||||
};
|
||||
|
||||
enum ZIP_ACCESS
|
||||
enum class ZIP_ACCESS
|
||||
{
|
||||
ZIP_ACCESS_READ,
|
||||
ZIP_ACCESS_WRITE,
|
||||
READ,
|
||||
WRITE,
|
||||
};
|
||||
|
||||
namespace Zip
|
||||
{
|
||||
IZipArchive * Open(const utf8 * path, ZIP_ACCESS zipAccess);
|
||||
IZipArchive * TryOpen(const utf8 * path, ZIP_ACCESS zipAccess);
|
||||
std::unique_ptr<IZipArchive> Open(const std::string_view& path, ZIP_ACCESS zipAccess);
|
||||
std::unique_ptr<IZipArchive> TryOpen(const std::string_view& path, ZIP_ACCESS zipAccess);
|
||||
}
|
||||
|
|
|
@ -20,30 +20,31 @@
|
|||
#include <jni.h>
|
||||
#include "IStream.hpp"
|
||||
#include "Zip.h"
|
||||
#include "MemoryStream.h"
|
||||
|
||||
class ZipArchive final : public IZipArchive {
|
||||
class ZipArchive final : public IZipArchive
|
||||
{
|
||||
private:
|
||||
jobject _zip;
|
||||
|
||||
public:
|
||||
ZipArchive(const utf8 *path, ZIP_ACCESS access) {
|
||||
ZipArchive(const std::string_view& path, ZIP_ACCESS access)
|
||||
{
|
||||
// retrieve the JNI environment.
|
||||
JNIEnv *env = (JNIEnv *) SDL_AndroidGetJNIEnv();
|
||||
|
||||
jclass jniClass = env->FindClass("website/openrct2/ZipArchive");
|
||||
jmethodID constructor = env->GetMethodID(jniClass, "<init>", "(Ljava/lang/String;)V");
|
||||
|
||||
jstring jniPath = env->NewStringUTF(path);
|
||||
jstring jniPath = env->NewStringUTF(path.data());
|
||||
|
||||
// TODO: Catch exceptions. Should probably be done on Java side, and just return null from a static method
|
||||
jobject zip = env->NewObject(jniClass, constructor, jniPath);
|
||||
|
||||
_zip = env->NewGlobalRef(zip);
|
||||
|
||||
}
|
||||
|
||||
~ZipArchive() override {
|
||||
~ZipArchive() override
|
||||
{
|
||||
// retrieve the JNI environment.
|
||||
JNIEnv *env = (JNIEnv *) SDL_AndroidGetJNIEnv();
|
||||
|
||||
|
@ -55,7 +56,8 @@ public:
|
|||
env->DeleteGlobalRef(_zip);
|
||||
}
|
||||
|
||||
size_t GetNumFiles() const override {
|
||||
size_t GetNumFiles() const override
|
||||
{
|
||||
// retrieve the JNI environment.
|
||||
JNIEnv *env = (JNIEnv *) SDL_AndroidGetJNIEnv();
|
||||
|
||||
|
@ -65,7 +67,8 @@ public:
|
|||
return (size_t) env->CallIntMethod(_zip, fileCountMethod);
|
||||
}
|
||||
|
||||
const utf8 *GetFileName(size_t index) const override {
|
||||
std::string GetFileName(size_t index) const override
|
||||
{
|
||||
// retrieve the JNI environment.
|
||||
JNIEnv *env = (JNIEnv *) SDL_AndroidGetJNIEnv();
|
||||
|
||||
|
@ -86,8 +89,8 @@ public:
|
|||
return string;
|
||||
}
|
||||
|
||||
uint64 GetFileSize(size_t index) const override {
|
||||
|
||||
uint64 GetFileSize(size_t index) const override
|
||||
{
|
||||
// retrieve the JNI environment.
|
||||
JNIEnv *env = (JNIEnv *) SDL_AndroidGetJNIEnv();
|
||||
|
||||
|
@ -97,58 +100,57 @@ public:
|
|||
return (size_t) env->CallLongMethod(_zip, fileSizeMethod, (jint) index);
|
||||
}
|
||||
|
||||
void *GetFileData(const utf8 *path, size_t *outSize) const override {
|
||||
|
||||
std::vector<uint8> GetFileData(const std::string_view& path) const override
|
||||
{
|
||||
// retrieve the JNI environment.
|
||||
JNIEnv *env = (JNIEnv *) SDL_AndroidGetJNIEnv();
|
||||
|
||||
jclass zipClass = env->GetObjectClass(_zip);
|
||||
jstring javaPath = env->NewStringUTF(path);
|
||||
jstring javaPath = env->NewStringUTF(path.data());
|
||||
jmethodID indexMethod = env->GetMethodID(zipClass, "getFileIndex", "(Ljava/lang/String;)I");
|
||||
jint index = env->CallIntMethod(_zip, indexMethod, javaPath);
|
||||
|
||||
jmethodID fileMethod = env->GetMethodID(zipClass, "getFile", "(I)J");
|
||||
jlong ptr = env->CallLongMethod(_zip, fileMethod, index);
|
||||
|
||||
*outSize = this->GetFileSize(index);
|
||||
return reinterpret_cast<void *>(ptr);
|
||||
auto dataPtr = reinterpret_cast<uint8 *>(ptr);
|
||||
auto dataSize = this->GetFileSize(index);
|
||||
|
||||
return std::vector<uint8>(dataPtr, dataPtr + dataSize);
|
||||
}
|
||||
|
||||
IStream *GetFileStream(const utf8 *path) const override {
|
||||
IStream * stream = nullptr;
|
||||
size_t dataSize;
|
||||
void * data = GetFileData(path, &dataSize);
|
||||
if (data != nullptr)
|
||||
{
|
||||
stream = new MemoryStream(data, dataSize, MEMORY_ACCESS::READ | MEMORY_ACCESS::OWNER);
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
void SetFileData(const utf8 *path, void *data, size_t dataSize) override {
|
||||
void void SetFileData(const std::string_view& path, std::vector<uint8>&& data) override
|
||||
{
|
||||
STUB();
|
||||
}
|
||||
|
||||
void DeleteFile(const utf8 *path) override {
|
||||
void DeleteFile(const std::string_view&) override
|
||||
{
|
||||
STUB();
|
||||
}
|
||||
|
||||
void RenameFile(const utf8 *path, const utf8 *newPath) override {
|
||||
void RenameFile(const std::string_view&, const std::string_view&) override
|
||||
{
|
||||
STUB();
|
||||
}
|
||||
};
|
||||
|
||||
namespace Zip {
|
||||
IZipArchive *Open(const utf8 *path, ZIP_ACCESS access) {
|
||||
namespace Zip
|
||||
{
|
||||
std::unique_ptr<IZipArchive> Open(const std::string_view& path, ZIP_ACCESS access)
|
||||
{
|
||||
return new ZipArchive(path, access);
|
||||
}
|
||||
|
||||
IZipArchive *TryOpen(const utf8 *path, ZIP_ACCESS access) {
|
||||
IZipArchive *result = nullptr;
|
||||
try {
|
||||
std::unique_ptr<IZipArchive> TryOpen(const std::string_view path, ZIP_ACCESS access)
|
||||
{
|
||||
std::unique_ptr<IZipArchive> result;
|
||||
try
|
||||
{
|
||||
result = new ZipArchive(path, access);
|
||||
}
|
||||
catch (const std::exception &) {
|
||||
catch (const std::exception&)
|
||||
{
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#pragma region Copyright (c) 2014-2017 OpenRCT2 Developers
|
||||
#pragma region Copyright (c) 2014-2018 OpenRCT2 Developers
|
||||
/*****************************************************************************
|
||||
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
|
||||
*
|
||||
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include "../audio/audio.h"
|
||||
#include "../Cheats.h"
|
||||
#include "../core/File.h"
|
||||
#include "../core/Math.hpp"
|
||||
#include "../core/String.hpp"
|
||||
#include "../core/Util.hpp"
|
||||
|
@ -90,21 +91,18 @@ rct_track_td6 * track_design_open(const utf8 * path)
|
|||
{
|
||||
log_verbose("track_design_open(\"%s\")", path);
|
||||
|
||||
uint8 * buffer;
|
||||
size_t bufferLength;
|
||||
if (readentirefile(path, (void **) &buffer, &bufferLength))
|
||||
try
|
||||
{
|
||||
if (!sawyercoding_validate_track_checksum(buffer, bufferLength))
|
||||
auto buffer = File::ReadAllBytes(path);
|
||||
if (!sawyercoding_validate_track_checksum(buffer.data(), buffer.size()))
|
||||
{
|
||||
log_error("Track checksum failed. %s", path);
|
||||
free(buffer);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Decode the track data
|
||||
uint8 * decoded = (uint8 *) malloc(0x10000);
|
||||
size_t decodedLength = sawyercoding_decode_td6(buffer, decoded, bufferLength);
|
||||
free(buffer);
|
||||
size_t decodedLength = sawyercoding_decode_td6(buffer.data(), decoded, buffer.size());
|
||||
decoded = (uint8 *) realloc(decoded, decodedLength);
|
||||
if (decoded == nullptr)
|
||||
{
|
||||
|
@ -122,6 +120,10 @@ rct_track_td6 * track_design_open(const utf8 * path)
|
|||
}
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
log_error("Unable to load track design: %s", e.what());
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -492,17 +492,15 @@ private:
|
|||
auto directory = Path::GetDirectory(dstPath);
|
||||
platform_ensure_directory_exists(directory.c_str());
|
||||
|
||||
size_t length;
|
||||
auto mpdat = (uint8 *)(File::ReadAllBytes(srcPath, &length));
|
||||
auto mpdat = File::ReadAllBytes(srcPath);
|
||||
|
||||
// Rotate each byte of mp.dat left by 4 bits to convert
|
||||
for (size_t i = 0; i < length; i++)
|
||||
for (size_t i = 0; i < mpdat.size(); i++)
|
||||
{
|
||||
mpdat[i] = rol8(mpdat[i], 4);
|
||||
}
|
||||
|
||||
File::WriteAllBytes(dstPath, mpdat, length);
|
||||
Memory::FreeArray(mpdat, length);
|
||||
File::WriteAllBytes(dstPath, mpdat.data(), mpdat.size());
|
||||
}
|
||||
|
||||
void AddScenario(const scenario_index_entry &entry)
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
*****************************************************************************/
|
||||
#pragma endregion
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include "../common.h"
|
||||
#include "../core/Collections.hpp"
|
||||
|
@ -39,8 +40,8 @@ static std::vector<utf8 *> GetSaves(const utf8 * path);
|
|||
static std::vector<utf8 *> GetSaves(IZipArchive * zip);
|
||||
static std::vector<TitleCommand> LegacyScriptRead(utf8 * script, size_t scriptLength, std::vector<utf8 *> saves);
|
||||
static void LegacyScriptGetLine(IStream * stream, char * parts);
|
||||
static void * ReadScriptFile(const utf8 * path, size_t * outSize);
|
||||
static utf8 * LegacyScriptWrite(TitleSequence * seq);
|
||||
static std::vector<uint8> ReadScriptFile(const utf8 * path);
|
||||
static std::string LegacyScriptWrite(TitleSequence * seq);
|
||||
|
||||
TitleSequence * CreateTitleSequence()
|
||||
{
|
||||
|
@ -51,8 +52,7 @@ TitleSequence * CreateTitleSequence()
|
|||
|
||||
TitleSequence * LoadTitleSequence(const utf8 * path)
|
||||
{
|
||||
size_t scriptLength;
|
||||
utf8 * script;
|
||||
std::vector<uint8> script;
|
||||
std::vector<utf8 *> saves;
|
||||
bool isZip;
|
||||
|
||||
|
@ -61,33 +61,30 @@ TitleSequence * LoadTitleSequence(const utf8 * path)
|
|||
const utf8 * ext = Path::GetExtension(path);
|
||||
if (String::Equals(ext, TITLE_SEQUENCE_EXTENSION))
|
||||
{
|
||||
IZipArchive * zip = Zip::TryOpen(path, ZIP_ACCESS_READ);
|
||||
auto zip = std::unique_ptr<IZipArchive>(Zip::TryOpen(path, ZIP_ACCESS::READ));
|
||||
if (zip == nullptr)
|
||||
{
|
||||
Console::Error::WriteLine("Unable to open '%s'", path);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
script = (utf8 *)zip->GetFileData("script.txt", &scriptLength);
|
||||
if (script == nullptr)
|
||||
script = zip->GetFileData("script.txt");
|
||||
if (script.empty())
|
||||
{
|
||||
Console::Error::WriteLine("Unable to open script.txt in '%s'", path);
|
||||
delete zip;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
saves = GetSaves(zip);
|
||||
saves = GetSaves(zip.get());
|
||||
isZip = true;
|
||||
|
||||
delete zip;
|
||||
}
|
||||
else
|
||||
{
|
||||
utf8 scriptPath[MAX_PATH];
|
||||
String::Set(scriptPath, sizeof(scriptPath), path);
|
||||
Path::Append(scriptPath, sizeof(scriptPath), "script.txt");
|
||||
script = (utf8 *)ReadScriptFile(scriptPath, &scriptLength);
|
||||
if (script == nullptr)
|
||||
script = ReadScriptFile(scriptPath);
|
||||
if (script.empty())
|
||||
{
|
||||
Console::Error::WriteLine("Unable to open '%s'", scriptPath);
|
||||
return nullptr;
|
||||
|
@ -97,8 +94,7 @@ TitleSequence * LoadTitleSequence(const utf8 * path)
|
|||
isZip = false;
|
||||
}
|
||||
|
||||
std::vector<TitleCommand> commands = LegacyScriptRead(script, scriptLength, saves);
|
||||
Memory::Free(script);
|
||||
auto commands = LegacyScriptRead((utf8 *)script.data(), script.size(), saves);
|
||||
|
||||
TitleSequence * seq = CreateTitleSequence();
|
||||
seq->Name = Path::GetFileNameWithoutExtension(path);
|
||||
|
@ -135,13 +131,17 @@ TitleSequenceParkHandle * TitleSequenceGetParkHandle(TitleSequence * seq, size_t
|
|||
const utf8 * filename = seq->Saves[index];
|
||||
if (seq->IsZip)
|
||||
{
|
||||
IZipArchive * zip = Zip::TryOpen(seq->Path, ZIP_ACCESS_READ);
|
||||
auto zip = std::unique_ptr<IZipArchive>(Zip::TryOpen(seq->Path, ZIP_ACCESS::READ));
|
||||
if (zip != nullptr)
|
||||
{
|
||||
auto data = zip->GetFileData(filename);
|
||||
auto dataForMs = Memory::Allocate<uint8>(data.size());
|
||||
std::copy_n(data.data(), data.size(), dataForMs);
|
||||
auto ms = new MemoryStream(dataForMs, data.size(), MEMORY_ACCESS::READ | MEMORY_ACCESS::OWNER);
|
||||
|
||||
handle = Memory::Allocate<TitleSequenceParkHandle>();
|
||||
handle->Stream = zip->GetFileStream(filename);
|
||||
handle->Stream = ms;
|
||||
handle->HintPath = String::Duplicate(filename);
|
||||
delete zip;
|
||||
} else {
|
||||
Console::Error::WriteLine("Failed to open zipped path '%s' from zip '%s'", filename, seq->Path);
|
||||
}
|
||||
|
@ -185,34 +185,26 @@ void TitleSequenceCloseParkHandle(TitleSequenceParkHandle * handle)
|
|||
|
||||
bool TitleSequenceSave(TitleSequence * seq)
|
||||
{
|
||||
bool success = false;
|
||||
utf8 * script = LegacyScriptWrite(seq);
|
||||
if (seq->IsZip)
|
||||
try
|
||||
{
|
||||
IZipArchive * zip = Zip::TryOpen(seq->Path, ZIP_ACCESS_WRITE);
|
||||
zip->SetFileData("script.txt", script, String::SizeOf(script));
|
||||
delete zip;
|
||||
success = true;
|
||||
auto script = LegacyScriptWrite(seq);
|
||||
if (seq->IsZip)
|
||||
{
|
||||
auto fdata = std::vector<uint8>(script.begin(), script.end());
|
||||
auto zip = Zip::Open(seq->Path, ZIP_ACCESS::WRITE);
|
||||
zip->SetFileData("script.txt", std::move(fdata));
|
||||
}
|
||||
else
|
||||
{
|
||||
auto scriptPath = Path::Combine(seq->Path, "script.txt");
|
||||
File::WriteAllBytes(scriptPath, script.data(), script.size());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
catch (const std::exception &)
|
||||
{
|
||||
utf8 scriptPath[MAX_PATH];
|
||||
String::Set(scriptPath, sizeof(scriptPath), seq->Path);
|
||||
Path::Append(scriptPath, sizeof(scriptPath), "script.txt");
|
||||
|
||||
try
|
||||
{
|
||||
auto fs = FileStream(scriptPath, FILE_MODE_WRITE);
|
||||
fs.Write(script, String::SizeOf(script));
|
||||
success = true;
|
||||
}
|
||||
catch (const std::exception &)
|
||||
{
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Memory::Free(script);
|
||||
return success;
|
||||
}
|
||||
|
||||
bool TitleSequenceAddPark(TitleSequence * seq, const utf8 * path, const utf8 * name)
|
||||
|
@ -240,18 +232,14 @@ bool TitleSequenceAddPark(TitleSequence * seq, const utf8 * path, const utf8 * n
|
|||
{
|
||||
try
|
||||
{
|
||||
size_t fsize;
|
||||
void * fdata = File::ReadAllBytes(path, &fsize);
|
||||
|
||||
IZipArchive * zip = Zip::TryOpen(seq->Path, ZIP_ACCESS_WRITE);
|
||||
auto fdata = File::ReadAllBytes(path);
|
||||
auto zip = Zip::TryOpen(seq->Path, ZIP_ACCESS::WRITE);
|
||||
if (zip == nullptr)
|
||||
{
|
||||
Console::Error::WriteLine("Unable to open '%s'", seq->Path);
|
||||
return false;
|
||||
}
|
||||
zip->SetFileData(name, fdata, fsize);
|
||||
delete zip;
|
||||
Memory::Free(fdata);
|
||||
zip->SetFileData(name, std::move(fdata));
|
||||
}
|
||||
catch (const std::exception &ex)
|
||||
{
|
||||
|
@ -280,14 +268,13 @@ bool TitleSequenceRenamePark(TitleSequence * seq, size_t index, const utf8 * nam
|
|||
utf8 * oldRelativePath = seq->Saves[index];
|
||||
if (seq->IsZip)
|
||||
{
|
||||
IZipArchive * zip = Zip::TryOpen(seq->Path, ZIP_ACCESS_WRITE);
|
||||
auto zip = Zip::TryOpen(seq->Path, ZIP_ACCESS::WRITE);
|
||||
if (zip == nullptr)
|
||||
{
|
||||
Console::Error::WriteLine("Unable to open '%s'", seq->Path);
|
||||
return false;
|
||||
}
|
||||
zip->RenameFile(oldRelativePath, name);
|
||||
delete zip;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -317,14 +304,13 @@ bool TitleSequenceRemovePark(TitleSequence * seq, size_t index)
|
|||
utf8 * relativePath = seq->Saves[index];
|
||||
if (seq->IsZip)
|
||||
{
|
||||
IZipArchive * zip = Zip::TryOpen(seq->Path, ZIP_ACCESS_WRITE);
|
||||
auto zip = Zip::TryOpen(seq->Path, ZIP_ACCESS::WRITE);
|
||||
if (zip == nullptr)
|
||||
{
|
||||
Console::Error::WriteLine("Unable to open '%s'", seq->Path);
|
||||
return false;
|
||||
}
|
||||
zip->DeleteFile(relativePath);
|
||||
delete zip;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -391,8 +377,8 @@ static std::vector<utf8 *> GetSaves(IZipArchive * zip)
|
|||
size_t numFiles = zip->GetNumFiles();
|
||||
for (size_t i = 0; i < numFiles; i++)
|
||||
{
|
||||
const utf8 * name = zip->GetFileName(i);
|
||||
const utf8 * ext = Path::GetExtension(name);
|
||||
auto name = zip->GetFileName(i);
|
||||
auto ext = Path::GetExtension(name);
|
||||
if (String::Equals(ext, ".sv6", true) ||
|
||||
String::Equals(ext, ".sc6", true))
|
||||
{
|
||||
|
@ -566,29 +552,25 @@ static void LegacyScriptGetLine(IStream * stream, char * parts)
|
|||
}
|
||||
}
|
||||
|
||||
static void * ReadScriptFile(const utf8 * path, size_t * outSize)
|
||||
static std::vector<uint8> ReadScriptFile(const utf8 * path)
|
||||
{
|
||||
void * buffer = nullptr;
|
||||
size_t size = 0;
|
||||
std::vector<uint8> result;
|
||||
try
|
||||
{
|
||||
auto fs = FileStream(path, FILE_MODE_OPEN);
|
||||
size = (size_t)fs.GetLength();
|
||||
buffer = Memory::Allocate<void>(size);
|
||||
fs.Read(buffer, size);
|
||||
auto size = (size_t)fs.GetLength();
|
||||
result.resize(size);
|
||||
fs.Read(result.data(), size);
|
||||
}
|
||||
catch (const std::exception &)
|
||||
{
|
||||
Memory::Free(buffer);
|
||||
buffer = nullptr;
|
||||
size = 0;
|
||||
result.clear();
|
||||
result.shrink_to_fit();
|
||||
}
|
||||
|
||||
*outSize = size;
|
||||
return buffer;
|
||||
return result;
|
||||
}
|
||||
|
||||
static utf8 * LegacyScriptWrite(TitleSequence * seq)
|
||||
static std::string LegacyScriptWrite(TitleSequence * seq)
|
||||
{
|
||||
utf8 buffer[128];
|
||||
auto sb = StringBuilder(128);
|
||||
|
@ -663,8 +645,7 @@ static utf8 * LegacyScriptWrite(TitleSequence * seq)
|
|||
sb.Append("\n");
|
||||
}
|
||||
|
||||
utf8 * result = sb.StealString();
|
||||
return result;
|
||||
return sb.GetBuffer();
|
||||
}
|
||||
|
||||
bool TitleSequenceIsLoadCommand(const TitleCommand * command)
|
||||
|
|
|
@ -34,7 +34,6 @@ void path_set_extension(utf8 *path, const utf8 *newExtension, size_t size);
|
|||
void path_append_extension(utf8 *path, const utf8 *newExtension, size_t size);
|
||||
void path_remove_extension(utf8 *path);
|
||||
void path_end_with_separator(utf8 *path, size_t size);
|
||||
bool readentirefile(const utf8 *path, void **outBuffer, size_t *outLength);
|
||||
bool writeentirefile(const utf8 * path, const void * buffer, size_t length);
|
||||
|
||||
bool sse41_available();
|
||||
|
|
Loading…
Reference in a new issue