mirror of
https://github.com/elasota/Aerofoil.git
synced 2025-12-14 12:09:36 +00:00
Switch to zip archive format for resource data, prep work for moving from PICT/snd to BMP/WAV
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
#include "ResourceManager.h"
|
||||
#include "VirtualDirectory.h"
|
||||
#include "FileManager.h"
|
||||
#include "GPArchive.h"
|
||||
#include "HostFileSystem.h"
|
||||
#include "HostMemoryBuffer.h"
|
||||
#include "IOStream.h"
|
||||
@@ -13,12 +14,14 @@
|
||||
#include "ResourceFile.h"
|
||||
#include "PLPasStr.h"
|
||||
#include "PLErrorCodes.h"
|
||||
#include "ZipFileProxy.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace PortabilityLayer
|
||||
{
|
||||
struct MMHandleBlock;
|
||||
class ResourceArchive;
|
||||
|
||||
class ResourceManagerImpl final : public ResourceManager
|
||||
{
|
||||
@@ -30,7 +33,7 @@ namespace PortabilityLayer
|
||||
|
||||
void SetResLoad(bool load) override;
|
||||
|
||||
ResourceFile *LoadResFile(VirtualDirectory_t virtualDir, const PLPasStr &filename) const override;
|
||||
ResourceArchive *LoadResFile(VirtualDirectory_t virtualDir, const PLPasStr &filename) const override;
|
||||
short OpenResFork(VirtualDirectory_t virtualDir, const PLPasStr &filename) override;
|
||||
void CloseResFile(short ref) override;
|
||||
PLError_t CreateBlankResFile(VirtualDirectory_t virtualDir, const PLPasStr &filename) override;
|
||||
@@ -41,7 +44,7 @@ namespace PortabilityLayer
|
||||
void SetCurrentResFile(short ref) override;
|
||||
|
||||
void DissociateHandle(MMHandleBlock *hdl) const override;
|
||||
const ResourceCompiledRef *ResourceForHandle(MMHandleBlock *hdl) const override;
|
||||
const ResourceArchiveRef *ResourceForHandle(MMHandleBlock *hdl) const override;
|
||||
|
||||
static ResourceManagerImpl *GetInstance();
|
||||
|
||||
@@ -50,10 +53,10 @@ namespace PortabilityLayer
|
||||
{
|
||||
short m_prevFile;
|
||||
short m_nextFile;
|
||||
ResourceFile *m_resourceFile;
|
||||
ResourceArchive *m_resourceArchive;
|
||||
};
|
||||
|
||||
void UnloadAndDestroyResourceFile(ResourceFile *rf);
|
||||
void UnloadAndDestroyResourceFile(ResourceArchive *rf);
|
||||
|
||||
std::vector<ResFileSlot> m_resFiles;
|
||||
short m_firstResFile;
|
||||
@@ -81,8 +84,8 @@ namespace PortabilityLayer
|
||||
{
|
||||
for (std::vector<ResFileSlot>::iterator it = m_resFiles.begin(), itEnd = m_resFiles.end(); it != itEnd; ++it)
|
||||
{
|
||||
if (it->m_resourceFile)
|
||||
UnloadAndDestroyResourceFile(it->m_resourceFile);
|
||||
if (it->m_resourceArchive)
|
||||
UnloadAndDestroyResourceFile(it->m_resourceArchive);
|
||||
}
|
||||
|
||||
m_resFiles.clear();
|
||||
@@ -106,32 +109,13 @@ namespace PortabilityLayer
|
||||
hdl->m_rmSelfRef = nullptr;
|
||||
}
|
||||
|
||||
const ResourceCompiledRef *ResourceManagerImpl::ResourceForHandle(MMHandleBlock *hdl) const
|
||||
const ResourceArchiveRef *ResourceManagerImpl::ResourceForHandle(MMHandleBlock *hdl) const
|
||||
{
|
||||
return hdl->m_rmSelfRef;
|
||||
}
|
||||
|
||||
void ResourceManagerImpl::UnloadAndDestroyResourceFile(ResourceFile *rf)
|
||||
void ResourceManagerImpl::UnloadAndDestroyResourceFile(ResourceArchive *rf)
|
||||
{
|
||||
PortabilityLayer::MemoryManager *mm = PortabilityLayer::MemoryManager::GetInstance();
|
||||
|
||||
ResourceCompiledTypeList *rtls = nullptr;
|
||||
size_t numRTLs = 0;
|
||||
rf->GetAllResourceTypeLists(rtls, numRTLs);
|
||||
|
||||
for (size_t i = 0; i < numRTLs; i++)
|
||||
{
|
||||
const ResourceCompiledTypeList &rtl = rtls[i];
|
||||
|
||||
const size_t numRefs = rtl.m_numRefs;
|
||||
for (size_t r = 0; r < numRefs; r++)
|
||||
{
|
||||
const ResourceCompiledRef &ref = rtl.m_firstRef[r];
|
||||
if (MMHandleBlock *hdl = ref.m_handle)
|
||||
mm->ReleaseHandle(hdl);
|
||||
}
|
||||
}
|
||||
|
||||
rf->Destroy();
|
||||
}
|
||||
|
||||
@@ -145,26 +129,28 @@ namespace PortabilityLayer
|
||||
m_load = load;
|
||||
}
|
||||
|
||||
ResourceFile *ResourceManagerImpl::LoadResFile(VirtualDirectory_t virtualDir, const PLPasStr &filename) const
|
||||
ResourceArchive *ResourceManagerImpl::LoadResFile(VirtualDirectory_t virtualDir, const PLPasStr &filename) const
|
||||
{
|
||||
IOStream *fStream = nullptr;
|
||||
if (FileManager::GetInstance()->RawOpenFileResources(virtualDir, filename, EFilePermission_Read, true, GpFileCreationDispositions::kOpenExisting, fStream) != PLErrors::kNone)
|
||||
return nullptr;
|
||||
|
||||
ResourceFile *resFile = ResourceFile::Create();
|
||||
if (!resFile)
|
||||
return nullptr;
|
||||
|
||||
bool loaded = resFile->Load(fStream);
|
||||
fStream->Close();
|
||||
|
||||
if (!loaded)
|
||||
ZipFileProxy *proxy = ZipFileProxy::Create(fStream);
|
||||
if (!proxy)
|
||||
{
|
||||
resFile->Destroy();
|
||||
fStream->Close();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return resFile;
|
||||
ResourceArchive *archive = ResourceArchive::Create(proxy, fStream);
|
||||
if (!archive)
|
||||
{
|
||||
proxy->Destroy();
|
||||
fStream->Close();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return archive;
|
||||
}
|
||||
|
||||
short ResourceManagerImpl::OpenResFork(VirtualDirectory_t virtualDir, const PLPasStr &filename)
|
||||
@@ -174,7 +160,7 @@ namespace PortabilityLayer
|
||||
|
||||
for (size_t i = 0; i < numSlots; i++)
|
||||
{
|
||||
if (m_resFiles[i].m_resourceFile == nullptr)
|
||||
if (m_resFiles[i].m_resourceArchive == nullptr)
|
||||
{
|
||||
resFileIndex = i;
|
||||
break;
|
||||
@@ -185,13 +171,13 @@ namespace PortabilityLayer
|
||||
return -1;
|
||||
|
||||
|
||||
ResourceFile *resFile = LoadResFile(virtualDir, filename);
|
||||
ResourceArchive *resFile = LoadResFile(virtualDir, filename);
|
||||
|
||||
if (!resFile)
|
||||
return -1;
|
||||
|
||||
ResFileSlot slot;
|
||||
slot.m_resourceFile = resFile;
|
||||
slot.m_resourceArchive = resFile;
|
||||
slot.m_prevFile = m_lastResFile;
|
||||
slot.m_nextFile = -1;
|
||||
|
||||
@@ -218,10 +204,10 @@ namespace PortabilityLayer
|
||||
{
|
||||
ResFileSlot &slot = m_resFiles[ref];
|
||||
|
||||
assert(slot.m_resourceFile != nullptr);
|
||||
assert(slot.m_resourceArchive != nullptr);
|
||||
|
||||
slot.m_resourceFile->Destroy();
|
||||
slot.m_resourceFile = nullptr;
|
||||
slot.m_resourceArchive->Destroy();
|
||||
slot.m_resourceArchive = nullptr;
|
||||
|
||||
if (m_lastResFile == ref)
|
||||
m_lastResFile = slot.m_prevFile;
|
||||
@@ -272,9 +258,9 @@ namespace PortabilityLayer
|
||||
while (searchIndex >= 0)
|
||||
{
|
||||
const ResFileSlot& slot = m_resFiles[searchIndex];
|
||||
assert(slot.m_resourceFile);
|
||||
assert(slot.m_resourceArchive);
|
||||
|
||||
THandle<void> resHdl = slot.m_resourceFile->GetResource(resType, id, m_load);
|
||||
THandle<void> resHdl = slot.m_resourceArchive->GetResource(resType, id, m_load);
|
||||
if (resHdl != nullptr)
|
||||
return resHdl;
|
||||
|
||||
@@ -284,8 +270,122 @@ namespace PortabilityLayer
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
ResourceManagerImpl ResourceManagerImpl::ms_instance;
|
||||
|
||||
ResourceManager *ResourceManager::GetInstance() { return ResourceManagerImpl::GetInstance(); }
|
||||
|
||||
// ===========================================================================================
|
||||
|
||||
ResourceArchiveRef::ResourceArchiveRef()
|
||||
: m_handle(nullptr)
|
||||
, m_size(0)
|
||||
, m_resID(0)
|
||||
{
|
||||
}
|
||||
|
||||
ResourceArchive *ResourceArchive::Create(ZipFileProxy *zipFileProxy, IOStream *stream)
|
||||
{
|
||||
PortabilityLayer::MemoryManager *mm = PortabilityLayer::MemoryManager::GetInstance();
|
||||
|
||||
size_t numFiles = zipFileProxy->NumFiles();
|
||||
|
||||
ResourceArchiveRef *refs = static_cast<ResourceArchiveRef*>(mm->Alloc(sizeof(ResourceArchiveRef) * numFiles));
|
||||
if (!refs)
|
||||
return nullptr;
|
||||
|
||||
for (size_t i = 0; i < numFiles; i++)
|
||||
new (refs + i) ResourceArchiveRef();
|
||||
|
||||
void *storage = mm->Alloc(sizeof(ResourceArchive));
|
||||
if (!storage)
|
||||
{
|
||||
mm->Release(refs);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return new (storage) ResourceArchive(zipFileProxy, stream, refs);
|
||||
}
|
||||
|
||||
void ResourceArchive::Destroy()
|
||||
{
|
||||
this->~ResourceArchive();
|
||||
PortabilityLayer::MemoryManager::GetInstance()->Release(this);
|
||||
}
|
||||
|
||||
THandle<void> ResourceArchive::GetResource(const ResTypeID &resTypeID, int id, bool load)
|
||||
{
|
||||
const char *extension = ".bin";
|
||||
char resourceFile[64];
|
||||
|
||||
GpArcResourceTypeTag resTag = GpArcResourceTypeTag::Encode(resTypeID);
|
||||
|
||||
snprintf(resourceFile, sizeof(resourceFile) - 1, "%s/%i%s", resTag.m_id, id, extension);
|
||||
|
||||
size_t index = 0;
|
||||
if (!m_zipFileProxy->IndexFile(resourceFile, index))
|
||||
return THandle<void>();
|
||||
|
||||
ResourceArchiveRef *ref = m_resourceHandles + index;
|
||||
|
||||
MMHandleBlock *handle = nullptr;
|
||||
if (ref->m_handle != nullptr)
|
||||
handle = ref->m_handle;
|
||||
else
|
||||
{
|
||||
handle = MemoryManager::GetInstance()->AllocHandle(0);
|
||||
if (!handle)
|
||||
return THandle<void>();
|
||||
|
||||
handle->m_rmSelfRef = ref;
|
||||
ref->m_handle = handle;
|
||||
ref->m_resID = static_cast<int16_t>(id);
|
||||
ref->m_size = m_zipFileProxy->GetFileSize(index);
|
||||
}
|
||||
|
||||
if (handle->m_contents == nullptr && load)
|
||||
{
|
||||
if (ref->m_size > 0)
|
||||
{
|
||||
void *contents = MemoryManager::GetInstance()->Alloc(ref->m_size);
|
||||
handle->m_contents = contents;
|
||||
handle->m_size = ref->m_size;
|
||||
|
||||
if (!m_zipFileProxy->LoadFile(index, contents))
|
||||
{
|
||||
MemoryManager::GetInstance()->Release(contents);
|
||||
handle->m_contents = nullptr;
|
||||
handle->m_size = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return THandle<void>(handle);
|
||||
}
|
||||
|
||||
ResourceArchive::ResourceArchive(ZipFileProxy *zipFileProxy, IOStream *stream, ResourceArchiveRef *resourceHandles)
|
||||
: m_zipFileProxy(zipFileProxy)
|
||||
, m_stream(stream)
|
||||
, m_resourceHandles(resourceHandles)
|
||||
{
|
||||
}
|
||||
|
||||
ResourceArchive::~ResourceArchive()
|
||||
{
|
||||
MemoryManager *mm = MemoryManager::GetInstance();
|
||||
|
||||
const size_t numFiles = m_zipFileProxy->NumFiles();
|
||||
for (size_t i = 0; i < numFiles; i++)
|
||||
{
|
||||
ResourceArchiveRef &ref = m_resourceHandles[numFiles - 1 - i];
|
||||
if (ref.m_handle)
|
||||
mm->ReleaseHandle(ref.m_handle);
|
||||
|
||||
ref.~ResourceArchiveRef();
|
||||
}
|
||||
|
||||
mm->Release(m_resourceHandles);
|
||||
|
||||
m_zipFileProxy->Destroy();
|
||||
m_stream->Close();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user