mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2026-01-17 03:53:07 +01:00
Reinstate support for title sequence folders
This commit is contained in:
@@ -124,6 +124,12 @@ public:
|
||||
return _currentPath;
|
||||
}
|
||||
|
||||
const utf8 * GetPathRelative() const override
|
||||
{
|
||||
// +1 to remove the path separator
|
||||
return _currentPath + String::SizeOf(_rootPath) + 1;
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
_started = false;
|
||||
@@ -155,6 +161,7 @@ public:
|
||||
utf8 childPath[MAX_PATH];
|
||||
String::Set(childPath, sizeof(childPath), state->Path.c_str());
|
||||
Path::Append(childPath, sizeof(childPath), child->Name.c_str());
|
||||
|
||||
PushState(childPath);
|
||||
}
|
||||
else if (PatternMatch(child->Name.c_str()))
|
||||
|
||||
@@ -31,6 +31,7 @@ interface IFileScanner
|
||||
|
||||
virtual const FileInfo * GetFileInfo() const abstract;
|
||||
virtual const utf8 * GetPath() const abstract;
|
||||
virtual const utf8 * GetPathRelative() const abstract;
|
||||
|
||||
virtual void Reset() abstract;
|
||||
virtual bool Next() abstract;
|
||||
|
||||
@@ -34,6 +34,16 @@ namespace Path
|
||||
return safe_strcat_path(buffer, src, bufferSize);
|
||||
}
|
||||
|
||||
utf8 * GetDirectory(const utf8 * path)
|
||||
{
|
||||
size_t maxSize = String::SizeOf(path) + 1;
|
||||
utf8 * result = Memory::Allocate<utf8>(maxSize);
|
||||
GetDirectory(result, maxSize, path);
|
||||
size_t reducedSize = String::SizeOf(path) + 1;
|
||||
result = Memory::Reallocate(result, reducedSize);
|
||||
return result;
|
||||
}
|
||||
|
||||
utf8 * GetDirectory(utf8 * buffer, size_t bufferSize, const utf8 * path)
|
||||
{
|
||||
size_t lastPathSepIndex = String::LastIndexOf(path, *PATH_SEPARATOR);
|
||||
|
||||
@@ -24,6 +24,7 @@ extern "C"
|
||||
namespace Path
|
||||
{
|
||||
utf8 * Append(utf8 * buffer, size_t bufferSize, const utf8 * src);
|
||||
utf8 * GetDirectory(const utf8 * path);
|
||||
utf8 * GetDirectory(utf8 * buffer, size_t bufferSize, const utf8 * path);
|
||||
const utf8 * GetFileName(const utf8 * path);
|
||||
utf8 * GetFileNameWithoutExtension(const utf8 * path);
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
#include <vector>
|
||||
#include "../core/Collections.hpp"
|
||||
#include "../core/Console.hpp"
|
||||
#include "../core/FileScanner.h"
|
||||
#include "../core/FileStream.hpp"
|
||||
#include "../core/Guard.hpp"
|
||||
#include "../core/Math.hpp"
|
||||
#include "../core/Memory.hpp"
|
||||
@@ -27,34 +29,61 @@
|
||||
#include "../core/String.hpp"
|
||||
#include "TitleSequence.h"
|
||||
|
||||
static std::vector<utf8 *> GetSaves(const utf8 * path);
|
||||
static std::vector<utf8 *> GetSaves(zip_t * zip);
|
||||
static std::vector<TitleCommand> LegacyScriptRead(utf8 * script, size_t scriptLength, std::vector<utf8 *> saves);
|
||||
static void LegacyScriptGetLine(SDL_RWops * file, char * parts);
|
||||
static void * ReadScriptFile(const utf8 * path, size_t * outSize);
|
||||
static void * GetZipFileData(zip_t * zip, const char * name, size_t * outSize);
|
||||
|
||||
extern "C"
|
||||
{
|
||||
TitleSequence * LoadTitleSequence(const utf8 * path)
|
||||
{
|
||||
int error;
|
||||
zip_t * zip = zip_open(path, ZIP_RDONLY, &error);
|
||||
if (zip == nullptr)
|
||||
{
|
||||
Console::Error::WriteLine("Unable to open '%s'", path);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
size_t scriptLength;
|
||||
char * script = (char *)GetZipFileData(zip, "script.txt", &scriptLength);
|
||||
if (script == nullptr)
|
||||
{
|
||||
Console::Error::WriteLine("Unable to open script.txt in '%s'", path);
|
||||
char * script;
|
||||
std::vector<utf8 *> saves;
|
||||
bool isZip;
|
||||
|
||||
zip_close(zip);
|
||||
return nullptr;
|
||||
const utf8 * ext = Path::GetExtension(path);
|
||||
if (String::Equals(ext, TITLE_SEQUENCE_EXTENSION))
|
||||
{
|
||||
int error;
|
||||
zip_t * zip = zip_open(path, ZIP_RDONLY, &error);
|
||||
if (zip == nullptr)
|
||||
{
|
||||
Console::Error::WriteLine("Unable to open '%s'", path);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
script = (char *)GetZipFileData(zip, "script.txt", &scriptLength);
|
||||
if (script == nullptr)
|
||||
{
|
||||
Console::Error::WriteLine("Unable to open script.txt in '%s'", path);
|
||||
|
||||
zip_close(zip);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
saves = GetSaves(zip);
|
||||
isZip = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
utf8 scriptPath[260];
|
||||
String::Set(scriptPath, sizeof(scriptPath), path);
|
||||
Path::Append(scriptPath, sizeof(scriptPath), "script.txt");
|
||||
script = (char *)ReadScriptFile(scriptPath, &scriptLength);
|
||||
if (script == nullptr)
|
||||
{
|
||||
Console::Error::WriteLine("Unable to open '%s'", scriptPath);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
saves = GetSaves(path);
|
||||
isZip = false;
|
||||
}
|
||||
|
||||
std::vector<utf8 *> saves = GetSaves(zip);
|
||||
std::vector<TitleCommand> commands = LegacyScriptRead(script, scriptLength, saves);
|
||||
|
||||
TitleSequence * seq = Memory::Allocate<TitleSequence>();
|
||||
@@ -64,6 +93,7 @@ extern "C"
|
||||
seq->Saves = Collections::ToArray(saves);
|
||||
seq->NumCommands = commands.size();
|
||||
seq->Commands = Collections::ToArray(commands);
|
||||
seq->IsZip = isZip;
|
||||
return seq;
|
||||
}
|
||||
|
||||
@@ -85,18 +115,30 @@ extern "C"
|
||||
TitleSequenceParkHandle * TitleSequenceGetParkHandle(TitleSequence * seq, size_t index)
|
||||
{
|
||||
TitleSequenceParkHandle * handle = nullptr;
|
||||
|
||||
int error;
|
||||
zip_t * zip = zip_open(seq->Path, ZIP_RDONLY, &error);
|
||||
if (zip != nullptr)
|
||||
if (index <= seq->NumSaves)
|
||||
{
|
||||
if (index <= seq->NumSaves)
|
||||
const utf8 * filename = seq->Saves[index];
|
||||
if (seq->IsZip)
|
||||
{
|
||||
utf8 * filename = seq->Saves[index];
|
||||
int error;
|
||||
zip_t * zip = zip_open(seq->Path, ZIP_RDONLY, &error);
|
||||
if (zip != nullptr)
|
||||
{
|
||||
handle = Memory::Allocate<TitleSequenceParkHandle>();
|
||||
handle->Data = GetZipFileData(zip, filename, &handle->DataSize);
|
||||
handle->RWOps = SDL_RWFromMem(handle->Data, (int)handle->DataSize);
|
||||
handle->IsScenario = String::Equals(Path::GetExtension(filename), ".sc6", true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
utf8 absolutePath[260];
|
||||
String::Set(absolutePath, sizeof(absolutePath), seq->Path);
|
||||
Path::Append(absolutePath, sizeof(absolutePath), filename);
|
||||
|
||||
handle = Memory::Allocate<TitleSequenceParkHandle>();
|
||||
handle->Data = GetZipFileData(zip, filename, &handle->DataSize);
|
||||
handle->RWOps = SDL_RWFromMem(handle->Data, (int)handle->DataSize);
|
||||
handle->Data = nullptr;
|
||||
handle->RWOps = SDL_RWFromFile(absolutePath, "rb");
|
||||
handle->IsScenario = String::Equals(Path::GetExtension(filename), ".sc6", true);
|
||||
}
|
||||
}
|
||||
@@ -105,12 +147,32 @@ extern "C"
|
||||
|
||||
void TitleSequenceCloseParkHandle(TitleSequenceParkHandle * handle)
|
||||
{
|
||||
SDL_RWclose(handle->RWOps);
|
||||
Memory::Free(handle->Data);
|
||||
Memory::Free(handle);
|
||||
if (handle != nullptr)
|
||||
{
|
||||
SDL_RWclose(handle->RWOps);
|
||||
Memory::Free(handle->Data);
|
||||
Memory::Free(handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static std::vector<utf8 *> GetSaves(const utf8 * directory)
|
||||
{
|
||||
std::vector<utf8 *> saves;
|
||||
|
||||
utf8 pattern[260];
|
||||
String::Set(pattern, sizeof(pattern), directory);
|
||||
Path::Append(pattern, sizeof(pattern), "*.sc6;*.sv6");
|
||||
|
||||
IFileScanner * scanner = Path::ScanDirectory(pattern, true);
|
||||
while (scanner->Next())
|
||||
{
|
||||
const utf8 * path = scanner->GetPathRelative();
|
||||
saves.push_back(String::Duplicate(path));
|
||||
}
|
||||
return saves;
|
||||
}
|
||||
|
||||
static std::vector<utf8 *> GetSaves(zip_t * zip)
|
||||
{
|
||||
std::vector<utf8 *> saves;
|
||||
@@ -270,6 +332,28 @@ static void LegacyScriptGetLine(SDL_RWops * file, char * parts)
|
||||
}
|
||||
}
|
||||
|
||||
static void * ReadScriptFile(const utf8 * path, size_t * outSize)
|
||||
{
|
||||
void * buffer = nullptr;
|
||||
size_t size = 0;
|
||||
try
|
||||
{
|
||||
auto fs = FileStream(path, FILE_MODE_OPEN);
|
||||
size = (size_t)fs.GetLength();
|
||||
buffer = Memory::Allocate<void>(size);
|
||||
fs.Read(buffer, size);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Memory::Free(buffer);
|
||||
buffer = nullptr;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
*outSize = size;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static void * GetZipFileData(zip_t * zip, const char * name, size_t * outSize)
|
||||
{
|
||||
void * data = nullptr;
|
||||
|
||||
@@ -47,6 +47,8 @@ typedef struct TitleSequence
|
||||
|
||||
size_t NumSaves;
|
||||
utf8 * * Saves;
|
||||
|
||||
bool IsZip;
|
||||
} TitleSequence;
|
||||
|
||||
typedef struct TitleSequenceParkHandle
|
||||
@@ -74,6 +76,10 @@ enum TITLE_SCRIPT
|
||||
TITLE_SCRIPT_LOADRCT1,
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
constexpr const utf8 * TITLE_SEQUENCE_EXTENSION = ".parkseq";
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace TitleSequenceManager
|
||||
std::vector<TitleSequenceManagerItem> _items;
|
||||
|
||||
static void Scan(const utf8 * directory);
|
||||
static std::string GetNameFromSequencePath(const utf8 * path);
|
||||
static std::string GetNameFromSequencePath(const std::string &path);
|
||||
static void GetDataSequencesPath(utf8 * buffer, size_t bufferSize);
|
||||
static void GetUserSequencesPath(utf8 * buffer, size_t bufferSize);
|
||||
|
||||
@@ -64,9 +64,9 @@ namespace TitleSequenceManager
|
||||
return &_items[i];
|
||||
}
|
||||
|
||||
static const uint16 GetPredefinedIndex(const utf8 * path)
|
||||
static const uint16 GetPredefinedIndex(const std::string &path)
|
||||
{
|
||||
const utf8 * filename = Path::GetFileName(path);
|
||||
const utf8 * filename = Path::GetFileName(path.c_str());
|
||||
for (uint16 i = 0; i < Util::CountOf(PredefinedSequences); i++)
|
||||
{
|
||||
if (String::Equals(filename, PredefinedSequences[i].Filename, true))
|
||||
@@ -111,16 +111,22 @@ namespace TitleSequenceManager
|
||||
{
|
||||
utf8 pattern[MAX_PATH];
|
||||
String::Set(pattern, sizeof(pattern), directory);
|
||||
Path::Append(pattern, sizeof(pattern), "*.parkseq");
|
||||
Path::Append(pattern, sizeof(pattern), "script.txt;*.parkseq");
|
||||
|
||||
IFileScanner * fileScanner = Path::ScanDirectory(pattern, true);
|
||||
while (fileScanner->Next())
|
||||
{
|
||||
const utf8 * path = fileScanner->GetPath();
|
||||
std::string path = std::string(fileScanner->GetPath());
|
||||
bool isZip = true;
|
||||
if (String::Equals(Path::GetExtension(path.c_str()), ".txt", true))
|
||||
{
|
||||
path = std::string(Path::GetDirectory(path.c_str()));
|
||||
isZip = false;
|
||||
}
|
||||
|
||||
TitleSequenceManagerItem item;
|
||||
item.PredefinedIndex = GetPredefinedIndex(path);
|
||||
item.Path = std::string(path);
|
||||
item.Path = path;
|
||||
if (item.PredefinedIndex != PREDEFINED_INDEX_CUSTOM)
|
||||
{
|
||||
rct_string_id stringId = PredefinedSequences[item.PredefinedIndex].StringId;
|
||||
@@ -130,14 +136,15 @@ namespace TitleSequenceManager
|
||||
{
|
||||
item.Name = GetNameFromSequencePath(path);
|
||||
}
|
||||
item.IsZip = isZip;
|
||||
_items.push_back(item);
|
||||
}
|
||||
delete fileScanner;
|
||||
}
|
||||
|
||||
static std::string GetNameFromSequencePath(const utf8 * path)
|
||||
static std::string GetNameFromSequencePath(const std::string &path)
|
||||
{
|
||||
utf8 * name = Path::GetFileNameWithoutExtension(path);
|
||||
utf8 * name = Path::GetFileNameWithoutExtension(path.c_str());
|
||||
std::string result = std::string(name);
|
||||
Memory::Free(name);
|
||||
return result;
|
||||
|
||||
@@ -27,6 +27,7 @@ struct TitleSequenceManagerItem
|
||||
std::string Name;
|
||||
std::string Path;
|
||||
uint16 PredefinedIndex;
|
||||
bool IsZip;
|
||||
};
|
||||
|
||||
namespace TitleSequenceManager
|
||||
|
||||
Reference in New Issue
Block a user