Compare commits

...

2 Commits

Author SHA1 Message Date
TheLastRar
c8e1dc5328 ChdFileReader: Use core_file instead of modifing chd_open_file 2024-12-16 09:39:46 -05:00
lightningterror
c2ee5a0234 GS/HW: Get the proper context for the next draw if it's a split texture shuffle.
Draw might switch the context so make sure we get the correct one.
2024-12-16 08:37:39 +01:00
4 changed files with 81 additions and 13 deletions

View File

@@ -259,7 +259,6 @@ extern "C" {
/* CHD open values */
#define CHD_OPEN_READ 1
#define CHD_OPEN_READWRITE 2
#define CHD_OPEN_TRANSFER_FILE 4 /* Freeing of the FILE* is now libchdr's responsibility if open was successful */
/* error types */
enum _chd_error

View File

@@ -1737,13 +1737,7 @@ CHD_EXPORT chd_error chd_open_file(FILE *file, int mode, chd_file *parent, chd_f
stream->fclose = core_stdio_fclose_nonowner;
stream->fseek = core_stdio_fseek;
chd_error err = chd_open_core_file(stream, mode, parent, chd);
if (err != CHDERR_NONE)
return err;
// swap out the fclose so that we close it on chd clost
stream->fclose = core_stdio_fclose;
return CHDERR_NONE;
return chd_open_core_file(stream, mode, parent, chd);
}
/*-------------------------------------------------

View File

@@ -20,6 +20,74 @@ static constexpr u32 MAX_PARENTS = 32; // Surely someone wouldn't be insane enou
static std::vector<std::pair<std::string, chd_header>> s_chd_hash_cache; // <filename, header>
static std::recursive_mutex s_chd_hash_cache_mutex;
// Provides an implementation of core_file which allows us to control if the underlying FILE handle is freed.
// The lifetime of ChdCoreFileWrapper will be equal to that of the relevant chd_file,
// ChdCoreFileWrapper will also get destroyed if chd_open_core_file fails.
class ChdCoreFileWrapper
{
DeclareNoncopyableObject(ChdCoreFileWrapper);
private:
core_file m_core;
std::FILE* m_file;
bool m_free_file = false;
public:
ChdCoreFileWrapper(std::FILE* file)
: m_file{file}
{
m_core.argp = this;
m_core.fsize = FSize;
m_core.fread = FRead;
m_core.fclose = FClose;
m_core.fseek = FSeek;
}
~ChdCoreFileWrapper()
{
if (m_free_file)
std::fclose(m_file);
}
core_file* GetCoreFile()
{
return &m_core;
}
static ChdCoreFileWrapper* FromCoreFile(core_file* file)
{
return reinterpret_cast<ChdCoreFileWrapper*>(file->argp);
}
void SetFileOwner(bool isOwner)
{
m_free_file = isOwner;
}
private:
static u64 FSize(core_file* file)
{
return static_cast<u64>(FileSystem::FSize64(FromCoreFile(file)->m_file));
}
static size_t FRead(void* buffer, size_t elmSize, size_t elmCount, core_file* file)
{
return std::fread(buffer, elmSize, elmCount, FromCoreFile(file)->m_file);
}
static int FClose(core_file* file)
{
// Destructor handles freeing the FILE handle.
delete FromCoreFile(file);
return 0;
}
static int FSeek(core_file* file, int64_t offset, int whence)
{
return FileSystem::FSeek64(FromCoreFile(file)->m_file, offset, whence);
}
};
ChdFileReader::ChdFileReader() = default;
ChdFileReader::~ChdFileReader()
@@ -30,10 +98,13 @@ ChdFileReader::~ChdFileReader()
static chd_file* OpenCHD(const std::string& filename, FileSystem::ManagedCFilePtr fp, Error* error, u32 recursion_level)
{
chd_file* chd;
chd_error err = chd_open_file(fp.get(), CHD_OPEN_READ | CHD_OPEN_TRANSFER_FILE, nullptr, &chd);
ChdCoreFileWrapper* core_wrapper = new ChdCoreFileWrapper(fp.get());
// libchdr will take ownership of core_wrapper, and will close/free it on failure.
chd_error err = chd_open_core_file(core_wrapper->GetCoreFile(), CHD_OPEN_READ, nullptr, &chd);
if (err == CHDERR_NONE)
{
// fp is now managed by libchdr
// core_wrapper should manage fp.
core_wrapper->SetFileOwner(true);
fp.release();
return chd;
}
@@ -140,8 +211,10 @@ static chd_file* OpenCHD(const std::string& filename, FileSystem::ManagedCFilePt
return nullptr;
}
// Our last core file wrapper got freed, so make a new one.
core_wrapper = new ChdCoreFileWrapper(fp.get());
// Now try re-opening with the parent.
err = chd_open_file(fp.get(), CHD_OPEN_READ | CHD_OPEN_TRANSFER_FILE, parent_chd, &chd);
err = chd_open_core_file(core_wrapper->GetCoreFile(), CHD_OPEN_READ, parent_chd, &chd);
if (err != CHDERR_NONE)
{
Console.Error(fmt::format("Failed to open CHD '{}': {}", filename, chd_error_string(err)));
@@ -149,7 +222,8 @@ static chd_file* OpenCHD(const std::string& filename, FileSystem::ManagedCFilePt
return nullptr;
}
// fp now owned by libchdr
// core_wrapper should manage fp.
core_wrapper->SetFileOwner(true);
fp.release();
return chd;
}

View File

@@ -1012,7 +1012,8 @@ bool GSRendererHW::NextDrawMatchesShuffle() const
{
// Make sure nothing unexpected has changed.
// Twinsanity seems to screw with ZBUF here despite it being irrelevant.
const GSDrawingContext& next_ctx = m_env.CTXT[m_backed_up_ctx];
const int get_next_ctx = (m_state_flush_reason == CONTEXTCHANGE) ? m_env.PRIM.CTXT : m_backed_up_ctx;
const GSDrawingContext& next_ctx = m_env.CTXT[get_next_ctx];
if (((m_context->TEX0.U64 ^ next_ctx.TEX0.U64) & (~0x3FFF)) != 0 ||
m_context->TEX1.U64 != next_ctx.TEX1.U64 ||
m_context->CLAMP.U64 != next_ctx.CLAMP.U64 ||