Browse Source

Open fewer files concurrently at load time

For `MultiFileLoader` and `LoadMultipleCl2Sheet`, we now open one file
at a time.

This can help on platforms that limit the number of concurrently open
files, such as the PS2.
pull/5801/head
Gleb Mazovetskiy 3 years ago
parent
commit
e87f68b2b5
  1. 17
      Source/engine/assets.hpp
  2. 25
      Source/engine/load_cl2.hpp
  3. 23
      Source/engine/load_file.hpp

17
Source/engine/assets.hpp

@ -212,12 +212,27 @@ struct AssetHandle {
};
#endif
[[noreturn]] inline void FailedToOpenFileError(const char *path, const char *error)
{
app_fatal(StrCat("Failed to open file:\n", path, "\n\n", error));
}
inline bool ValidatAssetRef(const char *path, const AssetRef &ref)
{
if (ref.ok())
return true;
if (!HeadlessMode) {
FailedToOpenFileError(path, ref.error());
}
return false;
}
inline bool ValidateHandle(const char *path, const AssetHandle &handle)
{
if (handle.ok())
return true;
if (!HeadlessMode) {
app_fatal(StrCat("Failed to open file:\n", path, "\n\n", handle.error()));
FailedToOpenFileError(path, handle.error());
}
return false;
}

25
Source/engine/load_cl2.hpp

@ -1,12 +1,15 @@
#pragma once
#include <array>
#include <cstdint>
#include <cstring>
#include <function_ref.hpp>
#include "appfat.h"
#include "engine/clx_sprite.hpp"
#include "engine/load_file.hpp"
#include "mpq/mpq_common.hpp"
#include "utils/cl2_to_clx.hpp"
#include "utils/endian.hpp"
#include "utils/pointer_value_union.hpp"
@ -26,17 +29,23 @@ OwnedClxSpriteListOrSheet LoadCl2ListOrSheet(const char *pszName, PointerOrValue
template <size_t MaxCount>
OwnedClxSpriteSheet LoadMultipleCl2Sheet(tl::function_ref<const char *(size_t)> filenames, size_t count, uint16_t width)
{
StaticVector<AssetHandle, MaxCount> files;
StaticVector<std::array<char, MaxMpqPathSize>, MaxCount> paths;
StaticVector<AssetRef, MaxCount> files;
StaticVector<size_t, MaxCount> fileSizes;
const size_t sheetHeaderSize = 4 * count;
size_t totalSize = sheetHeaderSize;
for (size_t i = 0; i < count; ++i) {
const char *filename = filenames(i);
size_t size;
files.emplace_back(OpenAsset(filename, size));
{
const char *path = filenames(i);
paths.emplace_back();
memcpy(paths.back().data(), path, strlen(path) + 1);
}
const char *path = paths.back().data();
files.emplace_back(FindAsset(path));
if (!files.back().ok()) {
app_fatal(StrCat("Failed to open file:\n", filename, "\n\n", files.back().error()));
FailedToOpenFileError(path, files.back().error());
}
const size_t size = files.back().size();
fileSizes.emplace_back(size);
totalSize += size;
}
@ -47,8 +56,10 @@ OwnedClxSpriteSheet LoadMultipleCl2Sheet(tl::function_ref<const char *(size_t)>
size_t accumulatedSize = sheetHeaderSize;
for (size_t i = 0; i < count; ++i) {
const size_t size = fileSizes[i];
if (!files[i].read(&data[accumulatedSize], size))
app_fatal(StrCat("Read failed:\n", files[i].error()));
AssetHandle handle = OpenAsset(std::move(files[i]));
if (!handle.ok() || !handle.read(&data[accumulatedSize], size)) {
FailedToOpenFileError(paths[i].data(), handle.error());
}
WriteLE32(&data[i * 4], accumulatedSize);
#ifndef UNPACKED_MPQS
[[maybe_unused]] const uint16_t numLists = Cl2ToClx(&data[accumulatedSize], size, frameWidth);

23
Source/engine/load_file.hpp

@ -3,6 +3,7 @@
#include <array>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <memory>
#include <fmt/core.h>
@ -10,6 +11,7 @@
#include "appfat.h"
#include "diablo.h"
#include "engine/assets.hpp"
#include "mpq/mpq_common.hpp"
#include "utils/static_vector.hpp"
#include "utils/stdcompat/cstddef.hpp"
#include "utils/str_cat.hpp"
@ -99,18 +101,24 @@ struct MultiFileLoader {
[[nodiscard]] std::unique_ptr<byte[]> operator()(size_t numFiles, PathFn &&pathFn, uint32_t *outOffsets,
FilterFn filterFn = DefaultFilterFn {})
{
StaticVector<AssetHandle, MaxFiles> files;
StaticVector<std::array<char, MaxMpqPathSize>, MaxFiles> paths;
StaticVector<AssetRef, MaxFiles> files;
StaticVector<uint32_t, MaxFiles> sizes;
size_t totalSize = 0;
for (size_t i = 0, j = 0; i < numFiles; ++i) {
if (!filterFn(i))
continue;
size_t size;
const char *path = pathFn(i);
files.emplace_back(OpenAsset(path, size));
if (!ValidateHandle(path, files.back()))
{
const char *path = pathFn(i);
paths.emplace_back();
memcpy(paths.back().data(), path, strlen(path) + 1);
}
const char *path = paths.back().data();
files.emplace_back(FindAsset(path));
if (!ValidatAssetRef(path, files.back()))
return nullptr;
const size_t size = files.back().size();
sizes.emplace_back(static_cast<uint32_t>(size));
outOffsets[j] = static_cast<uint32_t>(totalSize);
totalSize += size;
@ -121,7 +129,10 @@ struct MultiFileLoader {
for (size_t i = 0, j = 0; i < numFiles; ++i) {
if (!filterFn(i))
continue;
files[j].read(&buf[outOffsets[j]], sizes[j]);
AssetHandle handle = OpenAsset(std::move(files[j]));
if (!handle.ok() || !handle.read(&buf[outOffsets[j]], sizes[j])) {
FailedToOpenFileError(paths[j].data(), handle.error());
}
++j;
}
return buf;

Loading…
Cancel
Save