Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 74 additions & 0 deletions common/Buffer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// SPDX-FileCopyrightText: 2002-2026 PCSX2 Dev Team
// SPDX-License-Identifier: GPL-3.0+

#pragma once
#include "Pcsx2Types.h"
#include <cstdlib>
#include <cstring>

namespace Common
{

/// Like `std::vector<u8>` but doesn't zero bytes on resize
class Buffer
{
void* ptr_;
size_t size_;
size_t cap_;
public:
constexpr Buffer(): ptr_(nullptr), size_(0), cap_(0) {}
explicit Buffer(size_t size): ptr_(malloc(size)), size_(size), cap_(size) {}
~Buffer() { if (ptr_) free(ptr_); }
Buffer(const Buffer& other): Buffer(other.size_)
{
memcpy(ptr_, other.ptr_, other.size_);
}
Buffer(Buffer&& other): ptr_(other.ptr_), size_(other.size_), cap_(other.cap_)
{
other.ptr_ = nullptr;
other.size_ = 0;
other.cap_ = 0;
}
Buffer& operator=(const Buffer& other)
{
resize(other.size_);
memcpy(ptr_, other.ptr_, other.size_);
return *this;
}
Buffer& operator=(Buffer&& other)
{
if (this != &other)
{
if (ptr_) free(ptr_);
ptr_ = other.ptr_;
size_ = other.size_;
cap_ = other.cap_;
other.ptr_ = nullptr;
other.size_ = 0;
other.cap_ = 0;
}
return *this;
}

template <typename T = void> const T* get() const { return static_cast<T*>(ptr_); }
template <typename T = void> T* get() { return static_cast<T*>(ptr_); }

size_t capacity() const { return cap_; }
size_t size() const { return size_; }

void resize(size_t size)
{
size_ = size;
reserve(size);
}

void reserve(size_t size)
{
if (cap_ >= size)
return;
cap_ = size;
ptr_ = realloc(ptr_, size);
}
};

} // namespace Common
4 changes: 4 additions & 0 deletions common/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ target_sources(common PRIVATE
Assertions.h
boost_spsc_queue.hpp
BitUtils.h
Buffer.h
ByteSwap.h
Console.h
CrashHandler.h
Expand All @@ -64,6 +65,8 @@ target_sources(common PRIVATE
MD5Digest.h
MRCHelpers.h
Path.h
Pcsx2Defs.h
Pcsx2Types.h
PrecompiledHeader.h
ProgressCallback.h
ReadbackSpinManager.h
Expand All @@ -83,6 +86,7 @@ target_sources(common PRIVATE
WindowInfo.h
WrappedMemCopy.h
YAML.h
ZipHelpers.h
)

if(ARCH_X86)
Expand Down
2 changes: 1 addition & 1 deletion common/Image.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ static const FormatHandler* GetFormatHandler(const std::string_view extension)
{
for (const FormatHandler& handler : s_format_handlers)
{
if (StringUtil::Strncasecmp(extension.data(), handler.extension, extension.size()) == 0)
if (StringUtil::compareNoCase(extension, handler.extension))
return &handler;
}

Expand Down
50 changes: 24 additions & 26 deletions pcsx2/GS/Renderers/HW/GSTextureReplacementLoaders.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ struct LoaderDefinition
GSTextureReplacements::ReplacementTextureLoader loader;
};

static bool PNGLoader(const std::string& filename, GSTextureReplacements::ReplacementTexture* tex, bool only_base_image);
static bool DDSLoader(const std::string& filename, GSTextureReplacements::ReplacementTexture* tex, bool only_base_image);
static bool PNGLoader(GSTextureReplacements::File& file, const char* filename, GSTextureReplacements::ReplacementTexture* tex, bool only_base_image);
static bool DDSLoader(GSTextureReplacements::File& file, const char* filename, GSTextureReplacements::ReplacementTexture* tex, bool only_base_image);

static constexpr LoaderDefinition s_loaders[] = {
{"png", PNGLoader},
Expand All @@ -36,7 +36,7 @@ GSTextureReplacements::ReplacementTextureLoader GSTextureReplacements::GetLoader

for (const LoaderDefinition& defn : s_loaders)
{
if (StringUtil::Strncasecmp(extension.data(), defn.extension, extension.size()) == 0)
if (StringUtil::compareNoCase(extension, defn.extension))
return defn.loader;
}

Expand Down Expand Up @@ -146,7 +146,13 @@ static void ConvertTexture_R8G8B8(u32 width, u32 height, std::vector<u8>& data,
// PNG Handlers
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

bool PNGLoader(const std::string& filename, GSTextureReplacements::ReplacementTexture* tex, bool only_base_image)
static void PNGFileReader(png_structp png, png_bytep data, size_t amt)
{
GSTextureReplacements::File* file = static_cast<GSTextureReplacements::File*>(png_get_io_ptr(png));
file->Read(data, amt);
}

bool PNGLoader(GSTextureReplacements::File& file, const char* filename, GSTextureReplacements::ReplacementTexture* tex, bool only_base_image)
{
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
if (!png_ptr)
Expand All @@ -163,14 +169,10 @@ bool PNGLoader(const std::string& filename, GSTextureReplacements::ReplacementTe
png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
});

auto fp = FileSystem::OpenManagedCFile(filename.c_str(), "rb");
if (!fp)
return false;

if (setjmp(png_jmpbuf(png_ptr)))
return false;

png_init_io(png_ptr, fp.get());
png_set_read_fn(png_ptr, &file, PNGFileReader);
png_read_info(png_ptr, info_ptr);

png_uint_32 width = 0;
Expand Down Expand Up @@ -399,15 +401,15 @@ struct DDSLoadInfo
std::function<void(u32 width, u32 height, std::vector<u8>& data, u32& pitch)> conversion_function;
};

static bool ParseDDSHeader(std::FILE* fp, DDSLoadInfo* info)
static bool ParseDDSHeader(GSTextureReplacements::File& file, DDSLoadInfo* info)
{
u32 magic;
if (std::fread(&magic, sizeof(magic), 1, fp) != 1 || magic != DDS_MAGIC)
if (!file.ReadRawStruct(&magic) || magic != DDS_MAGIC)
return false;

DDS_HEADER header;
u32 header_size = sizeof(header);
if (std::fread(&header, header_size, 1, fp) != 1 || header.dwSize < header_size)
if (!file.ReadRawStruct(&header) || header.dwSize < header_size)
return false;

// We should check for DDS_HEADER_FLAGS_TEXTURE here, but some tools don't seem
Expand Down Expand Up @@ -451,7 +453,7 @@ static bool ParseDDSHeader(std::FILE* fp, DDSLoadInfo* info)
if (header.ddspf.dwFourCC == MAKEFOURCC('D', 'X', '1', '0'))
{
DDS_HEADER_DXT10 dxt10_header;
if (std::fread(&dxt10_header, sizeof(dxt10_header), 1, fp) != 1)
if (!file.ReadRawStruct(&dxt10_header))
return false;

// Can't handle array textures here. Doesn't make sense to use them, anyway.
Expand Down Expand Up @@ -562,13 +564,13 @@ static bool ParseDDSHeader(std::FILE* fp, DDSLoadInfo* info)

// Check for truncated or corrupted files.
info->base_image_offset = sizeof(magic) + header_size;
if (info->base_image_offset >= FileSystem::FSize64(fp))
if (info->base_image_offset >= file.Size())
return false;

return true;
}

static bool ReadDDSMipLevel(std::FILE* fp, const std::string& filename, u32 mip_level, const DDSLoadInfo& info, u32 width, u32 height, std::vector<u8>& data, u32& pitch, u32 size)
static bool ReadDDSMipLevel(GSTextureReplacements::File& file, const char* filename, u32 mip_level, const DDSLoadInfo& info, u32 width, u32 height, std::vector<u8>& data, u32& pitch, u32 size)
{
// D3D11 cannot handle block compressed textures where the first mip level is
// not a multiple of the block size.
Expand All @@ -578,12 +580,12 @@ static bool ReadDDSMipLevel(std::FILE* fp, const std::string& filename, u32 mip_
Console.Error(
"Invalid dimensions for DDS texture %s. For compressed textures of this format, "
"the width/height of the first mip level must be a multiple of %u.",
filename.c_str(), info.block_size);
filename, info.block_size);
return false;
}

data.resize(size);
if (std::fread(data.data(), size, 1, fp) != 1)
if (!file.Read(data.data(), size))
return false;

// Apply conversion function for uncompressed textures.
Expand All @@ -593,25 +595,21 @@ static bool ReadDDSMipLevel(std::FILE* fp, const std::string& filename, u32 mip_
return true;
}

bool DDSLoader(const std::string& filename, GSTextureReplacements::ReplacementTexture* tex, bool only_base_image)
bool DDSLoader(GSTextureReplacements::File& file, const char* filename, GSTextureReplacements::ReplacementTexture* tex, bool only_base_image)
{
auto fp = FileSystem::OpenManagedCFile(filename.c_str(), "rb");
if (!fp)
return false;

DDSLoadInfo info;
if (!ParseDDSHeader(fp.get(), &info))
if (!ParseDDSHeader(file, &info))
return false;

// always load the base image
if (FileSystem::FSeek64(fp.get(), info.base_image_offset, SEEK_SET) != 0)
if (!file.Seek(info.base_image_offset))
return false;

tex->format = info.format;
tex->width = info.width;
tex->height = info.height;
tex->pitch = info.base_image_pitch;
if (!ReadDDSMipLevel(fp.get(), filename, 0, info, tex->width, tex->height, tex->data, tex->pitch, info.base_image_size))
if (!ReadDDSMipLevel(file, filename, 0, info, tex->width, tex->height, tex->data, tex->pitch, info.base_image_size))
return false;

// Read in any remaining mip levels in the file.
Expand All @@ -622,7 +620,7 @@ bool DDSLoader(const std::string& filename, GSTextureReplacements::ReplacementTe
GSTextureReplacements::ReplacementTexture::MipData md;
u32 mip_size;
CalcBlockMipmapSize(info.block_size, info.bytes_per_block, info.width, info.height, level, md.width, md.height, md.pitch, mip_size);
if (!ReadDDSMipLevel(fp.get(), filename, level, info, md.width, md.height, md.data, md.pitch, mip_size))
if (!ReadDDSMipLevel(file, filename, level, info, md.width, md.height, md.data, md.pitch, mip_size))
break;

tex->mips.push_back(std::move(md));
Expand Down
Loading
Loading