mirror of
https://github.com/ZDoom/ZDRay.git
synced 2024-11-24 21:01:15 +00:00
Forgot to add the filesystem files
This commit is contained in:
parent
973512ba06
commit
02c2cf7c78
2 changed files with 315 additions and 0 deletions
273
src/framework/filesystem.cpp
Normal file
273
src/framework/filesystem.cpp
Normal file
|
@ -0,0 +1,273 @@
|
||||||
|
|
||||||
|
#include "filesystem.h"
|
||||||
|
#include "zipreader.h"
|
||||||
|
#include "file.h"
|
||||||
|
#include <map>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
FFileSystem fileSystem;
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class ZipFileSystemSource : public IFileSystemSource
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ZipFileSystemSource(const FString& filename)
|
||||||
|
{
|
||||||
|
zip = ZipReader::open(filename.GetChars());
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetLumpCount() override
|
||||||
|
{
|
||||||
|
return zip->get_num_files();
|
||||||
|
}
|
||||||
|
|
||||||
|
int CheckNumForFullName(const FString& fullname) override
|
||||||
|
{
|
||||||
|
return zip->locate_file(fullname.GetChars());
|
||||||
|
}
|
||||||
|
|
||||||
|
int FileLength(int lump) override
|
||||||
|
{
|
||||||
|
uint64_t size = zip->get_uncompressed_size(lump);
|
||||||
|
// For safety. The filesystem API clearly wasn't designed to handle large files.
|
||||||
|
if (size >= 0x7fffffff) throw std::runtime_error("File is too big");
|
||||||
|
return (int)size;
|
||||||
|
}
|
||||||
|
|
||||||
|
FileData ReadFile(int lump) override
|
||||||
|
{
|
||||||
|
FileData data;
|
||||||
|
data.Buffer = zip->read_all_bytes(lump);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* GetFileFullName(int lump, bool returnshort) override
|
||||||
|
{
|
||||||
|
static std::string tempstring;
|
||||||
|
tempstring = zip->get_filename(lump);
|
||||||
|
return tempstring.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<ZipReader> zip;
|
||||||
|
};
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class FolderFileSystemSource : public IFileSystemSource
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FolderFileSystemSource(const FString& foldername)
|
||||||
|
{
|
||||||
|
ScanFolder(foldername.GetChars());
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetLumpCount() override
|
||||||
|
{
|
||||||
|
return (int)Filenames.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
int CheckNumForFullName(const FString& fullname) override
|
||||||
|
{
|
||||||
|
auto it = FilenameKeyToIndex.find(fullname.GetChars());
|
||||||
|
if (it == FilenameKeyToIndex.end())
|
||||||
|
return -1;
|
||||||
|
return (int)it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
int FileLength(int lump) override
|
||||||
|
{
|
||||||
|
int64_t size = File::open_existing(Filenames[lump])->size();
|
||||||
|
// For safety. The filesystem API clearly wasn't designed to handle large files.
|
||||||
|
if (size >= 0x7fffffff) throw std::runtime_error("File is too big");
|
||||||
|
return (int)size;
|
||||||
|
}
|
||||||
|
|
||||||
|
FileData ReadFile(int lump) override
|
||||||
|
{
|
||||||
|
FileData data;
|
||||||
|
data.Buffer = File::read_all_bytes(Filenames[lump]);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* GetFileFullName(int lump, bool returnshort) override
|
||||||
|
{
|
||||||
|
return Filenames[lump].c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScanFolder(const std::string& foldername, int depth = 0)
|
||||||
|
{
|
||||||
|
for (const std::string& filename : Directory::files(foldername))
|
||||||
|
{
|
||||||
|
std::string fullname = FilePath::combine(foldername, filename);
|
||||||
|
FilenameKeyToIndex[fullname] = Filenames.size();
|
||||||
|
Filenames.push_back(fullname);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (depth < 16)
|
||||||
|
{
|
||||||
|
for (const std::string& subfolder : Directory::folders(foldername))
|
||||||
|
{
|
||||||
|
ScanFolder(FilePath::combine(foldername, subfolder), depth + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> Filenames;
|
||||||
|
std::map<std::string, size_t> FilenameKeyToIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class WadFileEntry
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
uint32_t offset = 0;
|
||||||
|
uint32_t size = 0;
|
||||||
|
std::string name;
|
||||||
|
void *data = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
class WadFileSystemSource : public IFileSystemSource
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
WadFileSystemSource(const FString& filename)
|
||||||
|
{
|
||||||
|
file = File::open_existing(filename.GetChars());
|
||||||
|
|
||||||
|
char magic[4];
|
||||||
|
file->read(magic, 4);
|
||||||
|
pwad = memcmp(magic, "PWAD", 4) == 0;
|
||||||
|
iwad = memcmp(magic, "IWAD", 4) == 0;
|
||||||
|
if (!pwad && !iwad)
|
||||||
|
throw std::runtime_error("Not a valid WAD file");
|
||||||
|
|
||||||
|
uint32_t num_entries = file->read_uint32();
|
||||||
|
uint32_t directory_offset = file->read_uint32();
|
||||||
|
file->seek(directory_offset);
|
||||||
|
for (uint32_t i = 0; i < num_entries; i++)
|
||||||
|
{
|
||||||
|
WadFileEntry entry;
|
||||||
|
entry.offset = file->read_uint32();
|
||||||
|
entry.size = file->read_uint32();
|
||||||
|
|
||||||
|
char name[9];
|
||||||
|
name[8] = 0;
|
||||||
|
file->read(name, 8);
|
||||||
|
entry.name = name;
|
||||||
|
|
||||||
|
FilenameKeyToIndex[entry.name] = entries.size();
|
||||||
|
entries.push_back(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetLumpCount() override
|
||||||
|
{
|
||||||
|
return (int)entries.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
int CheckNumForFullName(const FString& fullname) override
|
||||||
|
{
|
||||||
|
auto it = FilenameKeyToIndex.find(fullname.GetChars());
|
||||||
|
if (it == FilenameKeyToIndex.end())
|
||||||
|
return -1;
|
||||||
|
return (int)it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
int FileLength(int lump) override
|
||||||
|
{
|
||||||
|
return entries[lump].size;
|
||||||
|
}
|
||||||
|
|
||||||
|
FileData ReadFile(int lump) override
|
||||||
|
{
|
||||||
|
FileData data;
|
||||||
|
data.Buffer.resize(entries[lump].size);
|
||||||
|
file->seek(entries[lump].offset);
|
||||||
|
file->read(data.Buffer.data(), data.Buffer.size());
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* GetFileFullName(int lump, bool returnshort) override
|
||||||
|
{
|
||||||
|
return entries[lump].name.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<File> file;
|
||||||
|
bool pwad = false;
|
||||||
|
bool iwad = false;
|
||||||
|
std::vector<WadFileEntry> entries;
|
||||||
|
std::map<std::string, size_t> FilenameKeyToIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void FFileSystem::AddZipSource(const FString& filename)
|
||||||
|
{
|
||||||
|
Sources.push_back(std::make_unique<ZipFileSystemSource>(filename));
|
||||||
|
}
|
||||||
|
|
||||||
|
void FFileSystem::AddFolderSource(const FString& foldername)
|
||||||
|
{
|
||||||
|
Sources.push_back(std::make_unique<FolderFileSystemSource>(foldername));
|
||||||
|
}
|
||||||
|
|
||||||
|
void FFileSystem::AddWadSource(const FString& filename)
|
||||||
|
{
|
||||||
|
Sources.push_back(std::make_unique<WadFileSystemSource>(filename));
|
||||||
|
}
|
||||||
|
|
||||||
|
int FFileSystem::CheckNumForFullName(const FString& fullname)
|
||||||
|
{
|
||||||
|
int pos = 0;
|
||||||
|
for (auto& source : Sources)
|
||||||
|
{
|
||||||
|
int index = source->CheckNumForFullName(fullname);
|
||||||
|
if (index != -1)
|
||||||
|
return pos + index;
|
||||||
|
pos += source->GetLumpCount();
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int FFileSystem::FileLength(int lump)
|
||||||
|
{
|
||||||
|
int pos = 0;
|
||||||
|
for (auto& source : Sources)
|
||||||
|
{
|
||||||
|
if (lump - pos < source->GetLumpCount())
|
||||||
|
{
|
||||||
|
return source->FileLength(lump - pos);
|
||||||
|
}
|
||||||
|
pos += source->GetLumpCount();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
FileData FFileSystem::ReadFile(int lump)
|
||||||
|
{
|
||||||
|
int pos = 0;
|
||||||
|
for (auto& source : Sources)
|
||||||
|
{
|
||||||
|
if (lump - pos < source->GetLumpCount())
|
||||||
|
{
|
||||||
|
return source->ReadFile(lump - pos);
|
||||||
|
}
|
||||||
|
pos += source->GetLumpCount();
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* FFileSystem::GetFileFullName(int lump, bool returnshort) const
|
||||||
|
{
|
||||||
|
int pos = 0;
|
||||||
|
for (auto& source : Sources)
|
||||||
|
{
|
||||||
|
if (lump - pos < source->GetLumpCount())
|
||||||
|
{
|
||||||
|
return source->GetFileFullName(lump - pos, returnshort);
|
||||||
|
}
|
||||||
|
pos += source->GetLumpCount();
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
42
src/framework/filesystem.h
Normal file
42
src/framework/filesystem.h
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "framework/tarray.h"
|
||||||
|
#include "framework/templates.h"
|
||||||
|
#include "framework/zstring.h"
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
struct FileData
|
||||||
|
{
|
||||||
|
char* GetMem() { return (char*)Buffer.data(); }
|
||||||
|
std::vector<uint8_t> Buffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
class IFileSystemSource
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~IFileSystemSource() = default;
|
||||||
|
virtual int GetLumpCount() = 0;
|
||||||
|
virtual int CheckNumForFullName(const FString& fullname) = 0;
|
||||||
|
virtual int FileLength(int lump) = 0;
|
||||||
|
virtual FileData ReadFile(int lump) = 0;
|
||||||
|
virtual const char* GetFileFullName(int lump, bool returnshort) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class FFileSystem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void AddZipSource(const FString& filename);
|
||||||
|
void AddFolderSource(const FString& foldername);
|
||||||
|
void AddWadSource(const FString& filename);
|
||||||
|
|
||||||
|
int CheckNumForFullName(const FString& fullname);
|
||||||
|
int FileLength(int lump);
|
||||||
|
FileData ReadFile(int lump);
|
||||||
|
const char* GetFileFullName(int lump, bool returnshort = true) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<std::unique_ptr<IFileSystemSource>> Sources;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern FFileSystem fileSystem;
|
Loading…
Reference in a new issue