VideoOut event cleanup (#2849)

* Readable VideoOutEvent data packing

Inspired by the work of former shadPS4 devs and mostly based on red_prig's current code.

* Apply DceData struct to sceVideoOutGetEventCount

Makes the code easier to read

* Update equeue.h

* Update main.cpp

* Update equeue.h

* Proper struct names

* Fix hint mask

Thanks to red_prig for catching my mistake here.

* Clang

* Fix header discrepancy
This commit is contained in:
Stephen Miller 2025-04-27 01:04:17 -05:00 committed by GitHub
parent e816bc4b99
commit c09fff2da6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 34 additions and 16 deletions

View file

@ -61,6 +61,18 @@ struct SceKernelEvent {
void* udata = nullptr; /* opaque user data identifier */ void* udata = nullptr; /* opaque user data identifier */
}; };
struct OrbisVideoOutEventHint {
u64 event_id : 8;
u64 video_id : 8;
u64 flip_arg : 48;
};
struct OrbisVideoOutEventData {
u64 time : 12;
u64 count : 4;
u64 flip_arg : 48;
};
struct EqueueEvent { struct EqueueEvent {
SceKernelEvent event; SceKernelEvent event;
void* data = nullptr; void* data = nullptr;
@ -84,19 +96,18 @@ struct EqueueEvent {
void TriggerDisplay(void* data) { void TriggerDisplay(void* data) {
is_triggered = true; is_triggered = true;
auto hint = reinterpret_cast<u64>(data); if (data != nullptr) {
if (hint != 0) { auto event_data = static_cast<OrbisVideoOutEventData>(event.data);
auto hint_h = static_cast<u32>(hint >> 8) & 0xFFFFFF; auto event_hint_raw = reinterpret_cast<u64>(data);
auto ident_h = static_cast<u32>(event.ident >> 40); auto event_hint = static_cast<OrbisVideoOutEventHint>(event_hint_raw);
if ((static_cast<u32>(hint) & 0xFF) == event.ident && event.ident != 0xFE && if (event_hint.event_id == event.ident && event.ident != 0xfe) {
((hint_h ^ ident_h) & 0xFF) == 0) {
auto time = Common::FencedRDTSC(); auto time = Common::FencedRDTSC();
auto mask = 0xF000; auto counter = event_data.count;
if ((static_cast<u32>(event.data) & 0xF000) != 0xF000) { if (counter != 0xf) {
mask = (static_cast<u32>(event.data) + 0x1000) & 0xF000; counter++;
} }
event.data = (mask | static_cast<u64>(static_cast<u32>(time) & 0xFFF) | event.data =
(hint & 0xFFFFFFFFFFFF0000)); (time & 0xfff) | (counter << 0xc) | (event_hint_raw & 0xffffffffffff0000);
} }
} }
} }

View file

@ -220,7 +220,7 @@ s32 PS4_SYSV_ABI sceVideoOutGetEventData(const Kernel::SceKernelEvent* ev, s64*
if (ev->ident != static_cast<s32>(OrbisVideoOutInternalEventId::Flip) || ev->data == 0) { if (ev->ident != static_cast<s32>(OrbisVideoOutInternalEventId::Flip) || ev->data == 0) {
*data = event_data; *data = event_data;
} else { } else {
*data = event_data | 0xFFFF000000000000; *data = event_data | 0xffff000000000000;
} }
return ORBIS_OK; return ORBIS_OK;
} }
@ -233,7 +233,8 @@ s32 PS4_SYSV_ABI sceVideoOutGetEventCount(const Kernel::SceKernelEvent* ev) {
return ORBIS_VIDEO_OUT_ERROR_INVALID_EVENT; return ORBIS_VIDEO_OUT_ERROR_INVALID_EVENT;
} }
return (ev->data >> 0xc) & 0xf; auto event_data = static_cast<OrbisVideoOutEventData>(ev->data);
return event_data.count;
} }
s32 PS4_SYSV_ABI sceVideoOutGetFlipStatus(s32 handle, FlipStatus* status) { s32 PS4_SYSV_ABI sceVideoOutGetFlipStatus(s32 handle, FlipStatus* status) {

View file

@ -111,6 +111,12 @@ struct SceVideoOutColorSettings {
u32 reserved[3]; u32 reserved[3];
}; };
struct OrbisVideoOutEventData {
u64 time : 12;
u64 count : 4;
u64 flip_arg : 48;
};
void PS4_SYSV_ABI sceVideoOutSetBufferAttribute(BufferAttribute* attribute, PixelFormat pixelFormat, void PS4_SYSV_ABI sceVideoOutSetBufferAttribute(BufferAttribute* attribute, PixelFormat pixelFormat,
u32 tilingMode, u32 aspectRatio, u32 width, u32 tilingMode, u32 aspectRatio, u32 width,
u32 height, u32 pitchInPixel); u32 height, u32 pitchInPixel);
@ -128,8 +134,8 @@ s32 PS4_SYSV_ABI sceVideoOutGetResolutionStatus(s32 handle, SceVideoOutResolutio
s32 PS4_SYSV_ABI sceVideoOutOpen(SceUserServiceUserId userId, s32 busType, s32 index, s32 PS4_SYSV_ABI sceVideoOutOpen(SceUserServiceUserId userId, s32 busType, s32 index,
const void* param); const void* param);
s32 PS4_SYSV_ABI sceVideoOutClose(s32 handle); s32 PS4_SYSV_ABI sceVideoOutClose(s32 handle);
int PS4_SYSV_ABI sceVideoOutGetEventId(const Kernel::SceKernelEvent* ev); s32 PS4_SYSV_ABI sceVideoOutGetEventId(const Kernel::SceKernelEvent* ev);
int PS4_SYSV_ABI sceVideoOutGetEventData(const Kernel::SceKernelEvent* ev, int64_t* data); s32 PS4_SYSV_ABI sceVideoOutGetEventData(const Kernel::SceKernelEvent* ev, s64* data);
s32 PS4_SYSV_ABI sceVideoOutColorSettingsSetGamma(SceVideoOutColorSettings* settings, float gamma); s32 PS4_SYSV_ABI sceVideoOutColorSettingsSetGamma(SceVideoOutColorSettings* settings, float gamma);
s32 PS4_SYSV_ABI sceVideoOutAdjustColor(s32 handle, const SceVideoOutColorSettings* settings); s32 PS4_SYSV_ABI sceVideoOutAdjustColor(s32 handle, const SceVideoOutColorSettings* settings);

View file

@ -154,7 +154,7 @@ int main(int argc, char* argv[]) {
// If no game directory is set and no command line argument, prompt for it // If no game directory is set and no command line argument, prompt for it
if (Config::getGameInstallDirs().empty()) { if (Config::getGameInstallDirs().empty()) {
std::cout << "Warning: No game folder set, please set it by calling shadps4" std::cout << "Warning: No game folder set, please set it by calling shadps4"
" with the --add-game-folder <folder_name> argument"; " with the --add-game-folder <folder_name> argument\n";
} }
if (!has_game_argument) { if (!has_game_argument) {