mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2026-01-12 03:31:49 +00:00
feat: add external image loader for every supported game
This commit is contained in:
@@ -49,17 +49,20 @@ namespace
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<Texture> LoadIwi6(std::istream& stream)
|
||||
std::optional<IwiLoaderResult> LoadIwi6(std::istream& stream)
|
||||
{
|
||||
iwi6::IwiHeader header{};
|
||||
|
||||
stream.read(reinterpret_cast<char*>(&header), sizeof(header));
|
||||
if (stream.gcount() != sizeof(header))
|
||||
return nullptr;
|
||||
{
|
||||
con::error("IWI header corrupted");
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
const auto* format = GetFormat6(header.format);
|
||||
if (format == nullptr)
|
||||
return nullptr;
|
||||
return std::nullopt;
|
||||
|
||||
auto width = header.dimensions[0];
|
||||
auto height = header.dimensions[1];
|
||||
@@ -88,18 +91,30 @@ namespace
|
||||
&& currentFileSize != header.fileSizeForPicmip[currentMipLevel])
|
||||
{
|
||||
con::error("Iwi has invalid file size for picmip {}", currentMipLevel);
|
||||
return nullptr;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
stream.read(reinterpret_cast<char*>(texture->GetBufferForMipLevel(currentMipLevel)), sizeOfMipLevel);
|
||||
if (stream.gcount() != sizeOfMipLevel)
|
||||
{
|
||||
con::error("Unexpected eof of iwi in mip level {}", currentMipLevel);
|
||||
return nullptr;
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
return texture;
|
||||
CommonIwiMetaData meta{
|
||||
.m_no_picmip = (header.flags & iwi6::IwiFlags::IMG_FLAG_NOPICMIP) != 0,
|
||||
.m_streaming = (header.flags & iwi6::IwiFlags::IMG_FLAG_STREAMING) != 0,
|
||||
.m_clamp_u = (header.flags & iwi6::IwiFlags::IMG_FLAG_CLAMP_U) != 0,
|
||||
.m_clamp_v = (header.flags & iwi6::IwiFlags::IMG_FLAG_CLAMP_V) != 0,
|
||||
.m_dynamic = (header.flags & iwi6::IwiFlags::IMG_FLAG_DYNAMIC) != 0,
|
||||
};
|
||||
|
||||
return IwiLoaderResult{
|
||||
.m_version = IwiVersion::IWI_6,
|
||||
.m_meta = meta,
|
||||
.m_texture = std::move(texture),
|
||||
};
|
||||
}
|
||||
|
||||
const ImageFormat* GetFormat8(int8_t format)
|
||||
@@ -147,17 +162,20 @@ namespace
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<Texture> LoadIwi8(std::istream& stream)
|
||||
std::optional<IwiLoaderResult> LoadIwi8(std::istream& stream)
|
||||
{
|
||||
iwi8::IwiHeader header{};
|
||||
|
||||
stream.read(reinterpret_cast<char*>(&header), sizeof(header));
|
||||
if (stream.gcount() != sizeof(header))
|
||||
return nullptr;
|
||||
{
|
||||
con::error("IWI header corrupted");
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
const auto* format = GetFormat8(header.format);
|
||||
if (format == nullptr)
|
||||
return nullptr;
|
||||
return std::nullopt;
|
||||
|
||||
auto width = header.dimensions[0];
|
||||
auto height = header.dimensions[1];
|
||||
@@ -180,12 +198,12 @@ namespace
|
||||
else if ((header.flags & iwi8::IwiFlags::IMG_FLAG_MAPTYPE_MASK) == iwi8::IwiFlags::IMG_FLAG_MAPTYPE_1D)
|
||||
{
|
||||
con::error("Iwi has unsupported map type 1D");
|
||||
return nullptr;
|
||||
return std::nullopt;
|
||||
}
|
||||
else
|
||||
{
|
||||
con::error("Iwi has unsupported map type");
|
||||
return nullptr;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
texture->Allocate();
|
||||
@@ -202,18 +220,30 @@ namespace
|
||||
&& currentFileSize != header.fileSizeForPicmip[currentMipLevel])
|
||||
{
|
||||
con::error("Iwi has invalid file size for picmip {}", currentMipLevel);
|
||||
return nullptr;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
stream.read(reinterpret_cast<char*>(texture->GetBufferForMipLevel(currentMipLevel)), sizeOfMipLevel);
|
||||
if (stream.gcount() != sizeOfMipLevel)
|
||||
{
|
||||
con::error("Unexpected eof of iwi in mip level {}", currentMipLevel);
|
||||
return nullptr;
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
return texture;
|
||||
CommonIwiMetaData meta{
|
||||
.m_no_picmip = (header.flags & iwi8::IwiFlags::IMG_FLAG_NOPICMIP) != 0,
|
||||
.m_streaming = (header.flags & iwi8::IwiFlags::IMG_FLAG_STREAMING) != 0,
|
||||
.m_clamp_u = (header.flags & iwi8::IwiFlags::IMG_FLAG_CLAMP_U) != 0,
|
||||
.m_clamp_v = (header.flags & iwi8::IwiFlags::IMG_FLAG_CLAMP_V) != 0,
|
||||
.m_dynamic = (header.flags & iwi8::IwiFlags::IMG_FLAG_DYNAMIC) != 0,
|
||||
};
|
||||
|
||||
return IwiLoaderResult{
|
||||
.m_version = IwiVersion::IWI_8,
|
||||
.m_meta = meta,
|
||||
.m_texture = std::move(texture),
|
||||
};
|
||||
}
|
||||
|
||||
const ImageFormat* GetFormat13(int8_t format)
|
||||
@@ -258,17 +288,20 @@ namespace
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<Texture> LoadIwi13(std::istream& stream)
|
||||
std::optional<IwiLoaderResult> LoadIwi13(std::istream& stream)
|
||||
{
|
||||
iwi13::IwiHeader header{};
|
||||
|
||||
stream.read(reinterpret_cast<char*>(&header), sizeof(header));
|
||||
if (stream.gcount() != sizeof(header))
|
||||
return nullptr;
|
||||
{
|
||||
con::error("IWI header corrupted");
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
const auto* format = GetFormat6(header.format);
|
||||
if (format == nullptr)
|
||||
return nullptr;
|
||||
return std::nullopt;
|
||||
|
||||
auto width = header.dimensions[0];
|
||||
auto height = header.dimensions[1];
|
||||
@@ -297,18 +330,31 @@ namespace
|
||||
&& currentFileSize != header.fileSizeForPicmip[currentMipLevel])
|
||||
{
|
||||
con::error("Iwi has invalid file size for picmip {}", currentMipLevel);
|
||||
return nullptr;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
stream.read(reinterpret_cast<char*>(texture->GetBufferForMipLevel(currentMipLevel)), sizeOfMipLevel);
|
||||
if (stream.gcount() != sizeOfMipLevel)
|
||||
{
|
||||
con::error("Unexpected eof of iwi in mip level {}", currentMipLevel);
|
||||
return nullptr;
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
return texture;
|
||||
CommonIwiMetaData meta{
|
||||
.m_no_picmip = (header.flags & iwi13::IwiFlags::IMG_FLAG_NOPICMIP) != 0,
|
||||
.m_streaming = (header.flags & iwi13::IwiFlags::IMG_FLAG_STREAMING) != 0,
|
||||
.m_clamp_u = (header.flags & iwi13::IwiFlags::IMG_FLAG_CLAMP_U) != 0,
|
||||
.m_clamp_v = (header.flags & iwi13::IwiFlags::IMG_FLAG_CLAMP_V) != 0,
|
||||
.m_dynamic = (header.flags & iwi13::IwiFlags::IMG_FLAG_DYNAMIC) != 0,
|
||||
.m_gamma = header.gamma,
|
||||
};
|
||||
|
||||
return IwiLoaderResult{
|
||||
.m_version = IwiVersion::IWI_13,
|
||||
.m_meta = meta,
|
||||
.m_texture = std::move(texture),
|
||||
};
|
||||
}
|
||||
|
||||
const ImageFormat* GetFormat27(int8_t format)
|
||||
@@ -355,17 +401,20 @@ namespace
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<Texture> LoadIwi27(std::istream& stream)
|
||||
std::optional<IwiLoaderResult> LoadIwi27(std::istream& stream)
|
||||
{
|
||||
iwi27::IwiHeader header{};
|
||||
|
||||
stream.read(reinterpret_cast<char*>(&header), sizeof(header));
|
||||
if (stream.gcount() != sizeof(header))
|
||||
return nullptr;
|
||||
{
|
||||
con::error("IWI header corrupted");
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
const auto* format = GetFormat27(header.format);
|
||||
if (format == nullptr)
|
||||
return nullptr;
|
||||
return std::nullopt;
|
||||
|
||||
auto width = header.dimensions[0];
|
||||
auto height = header.dimensions[1];
|
||||
@@ -394,35 +443,51 @@ namespace
|
||||
&& currentFileSize != header.fileSizeForPicmip[currentMipLevel])
|
||||
{
|
||||
con::error("Iwi has invalid file size for picmip {}", currentMipLevel);
|
||||
return nullptr;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
stream.read(reinterpret_cast<char*>(texture->GetBufferForMipLevel(currentMipLevel)), sizeOfMipLevel);
|
||||
if (stream.gcount() != sizeOfMipLevel)
|
||||
{
|
||||
con::error("Unexpected eof of iwi in mip level {}", currentMipLevel);
|
||||
return nullptr;
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
return texture;
|
||||
CommonIwiMetaData meta{
|
||||
.m_no_picmip = (header.flags & iwi27::IwiFlags::IMG_FLAG_NOPICMIP) != 0,
|
||||
.m_streaming = (header.flags & iwi27::IwiFlags::IMG_FLAG_STREAMING) != 0,
|
||||
.m_clamp_u = (header.flags & iwi27::IwiFlags::IMG_FLAG_CLAMP_U) != 0,
|
||||
.m_clamp_v = (header.flags & iwi27::IwiFlags::IMG_FLAG_CLAMP_V) != 0,
|
||||
.m_dynamic = (header.flags & iwi27::IwiFlags::IMG_FLAG_DYNAMIC) != 0,
|
||||
.m_gamma = header.gamma,
|
||||
};
|
||||
|
||||
return IwiLoaderResult{
|
||||
.m_version = IwiVersion::IWI_27,
|
||||
.m_meta = meta,
|
||||
.m_texture = std::move(texture),
|
||||
};
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace image
|
||||
{
|
||||
std::unique_ptr<Texture> LoadIwi(std::istream& stream)
|
||||
std::optional<IwiLoaderResult> LoadIwi(std::istream& stream)
|
||||
{
|
||||
IwiVersionHeader iwiVersionHeader{};
|
||||
|
||||
stream.read(reinterpret_cast<char*>(&iwiVersionHeader), sizeof(iwiVersionHeader));
|
||||
if (stream.gcount() != sizeof(iwiVersionHeader))
|
||||
return nullptr;
|
||||
{
|
||||
con::error("IWI version header corrupted");
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
if (iwiVersionHeader.tag[0] != 'I' || iwiVersionHeader.tag[1] != 'W' || iwiVersionHeader.tag[2] != 'i')
|
||||
{
|
||||
con::error("Invalid IWI magic");
|
||||
return nullptr;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
switch (iwiVersionHeader.version)
|
||||
@@ -444,6 +509,6 @@ namespace image
|
||||
}
|
||||
|
||||
con::error("Unknown IWI version {}", iwiVersionHeader.version);
|
||||
return nullptr;
|
||||
return std::nullopt;
|
||||
}
|
||||
} // namespace image
|
||||
|
||||
@@ -1,11 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include "Image/IwiTypes.h"
|
||||
#include "Image/Texture.h"
|
||||
|
||||
#include <istream>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
namespace image
|
||||
{
|
||||
std::unique_ptr<Texture> LoadIwi(std::istream& stream);
|
||||
struct IwiLoaderResult
|
||||
{
|
||||
IwiVersion m_version;
|
||||
CommonIwiMetaData m_meta;
|
||||
std::unique_ptr<Texture> m_texture;
|
||||
};
|
||||
|
||||
std::optional<IwiLoaderResult> LoadIwi(std::istream& stream);
|
||||
}; // namespace image
|
||||
|
||||
@@ -16,6 +16,18 @@ namespace image
|
||||
IWI_27 = 27
|
||||
};
|
||||
|
||||
struct CommonIwiMetaData
|
||||
{
|
||||
// Always high resolution
|
||||
bool m_no_picmip;
|
||||
bool m_streaming;
|
||||
bool m_clamp_u;
|
||||
bool m_clamp_v;
|
||||
bool m_dynamic;
|
||||
|
||||
float m_gamma;
|
||||
};
|
||||
|
||||
struct IwiVersionHeader
|
||||
{
|
||||
char tag[3];
|
||||
|
||||
Reference in New Issue
Block a user