Files
PS2Recomp/ps2xRuntime/src/lib/ps2_gif_arbiter.cpp
T
Ranieri 8c8a97af65 Feature/mpeg decoder (#120)
* feat: added ffmepg as dependency

* feat: wip decoder video

* feat: some perf and cleanup

* feat:  added generic MPEG stream notification

* feat: CMakeLists.txt in ps2xStudio to configure SDL2 build options for static linking.
fix: fix ffmpeg setup for linux
fix: now MPEG decoder now identify that movie has ended and can play again anytime
feat: better audio stub to not block games

* feat: fix expansion test

* feat: foo

* a

* feat: finally added a helper to to prevent thread starvation

* feat: added basic  vu0 code execution

* feat: added yield Guest Execution After Wake to prevent deadlock

* feat: added  options  on  cmake for logs
feat: better input for keyboard pad

* feat: small corrections like top and itop vu branches etc

* feat: changes

* feat: working feature

* feat: fatal frame iop

* feat: test fix
feat: z buffer fix

* fix: gix GsPutIMR IMR

* feat: added rl imgui

* feat: added helper to get snapshot

* feat: added debug panel consuming snapshots

* feat: added pad snapshot
feat: added RCP debug events

* feat: final cleanup from old code

* feat: added EE timer counter
feat: applyed sound driver for Lotr
feat: better check for sound driver compat layout
feat: enquee and cosumed DMa cause
feat: added Pad execCMd
feat: update GS vsync signal flag
feat: custom IOPs for LotR

* feat: small cleanups

* fix: fix wrong import
2026-06-26 21:04:39 -03:00

69 lines
2.0 KiB
C++

#include "runtime/ps2_gif_arbiter.h"
#include <algorithm>
#include <cstring>
GifArbiter::GifArbiter(ProcessPacketFn processFn)
: m_processFn(std::move(processFn))
{
}
bool GifArbiter::isImagePacket(const uint8_t *data, uint32_t sizeBytes)
{
if (!data || sizeBytes < 16u)
return false;
uint64_t tagLo = 0;
std::memcpy(&tagLo, data, sizeof(tagLo));
const uint8_t flg = static_cast<uint8_t>((tagLo >> 58) & 0x3u);
return flg == 2u;
}
void GifArbiter::submit(GifPathId pathId, const uint8_t *data, uint32_t sizeBytes, bool path2DirectHl)
{
if (!data || sizeBytes < 16 || !m_processFn)
return;
GifArbiterPacket pkt;
pkt.pathId = pathId;
pkt.path2DirectHl = (pathId == GifPathId::Path2) && path2DirectHl;
pkt.path3Image = (pathId == GifPathId::Path3) && isImagePacket(data, sizeBytes);
pkt.data.resize(sizeBytes);
std::memcpy(pkt.data.data(), data, sizeBytes);
m_queue.push_back(std::move(pkt));
}
void GifArbiter::drain()
{
if (!m_processFn)
return;
std::stable_sort(m_queue.begin(), m_queue.end(),
[](const GifArbiterPacket &a, const GifArbiterPacket &b)
{
// DIRECTHL cannot preempt PATH3 IMAGE transfers.
if (a.path2DirectHl != b.path2DirectHl || a.path3Image != b.path3Image)
{
if (a.path3Image && b.path2DirectHl)
return true;
if (a.path2DirectHl && b.path3Image)
return false;
}
return pathPriority(a.pathId) < pathPriority(b.pathId);
});
for (size_t i = 0; i < m_queue.size(); ++i)
{
auto &pkt = m_queue[i];
if (!pkt.data.empty())
{
m_processFn(pkt.data.data(), static_cast<uint32_t>(pkt.data.size()));
}
}
m_queue.clear();
}
uint8_t GifArbiter::pathPriority(GifPathId id)
{
return static_cast<uint8_t>(id);
}