mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-01-30 12:32:43 +00:00
cellGem: hook up camera
This commit is contained in:
parent
00c87a8fc9
commit
be972f04ac
@ -36,6 +36,27 @@ void fmt_class_string<CellCameraError>::format(std::string& out, u64 arg)
|
||||
});
|
||||
}
|
||||
|
||||
template <>
|
||||
void fmt_class_string<CellCameraFormat>::format(std::string& out, u64 arg)
|
||||
{
|
||||
format_enum(out, arg, [](CellCameraFormat value)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
STR_CASE(CELL_CAMERA_FORMAT_UNKNOWN);
|
||||
STR_CASE(CELL_CAMERA_JPG);
|
||||
STR_CASE(CELL_CAMERA_RAW8);
|
||||
STR_CASE(CELL_CAMERA_YUV422);
|
||||
STR_CASE(CELL_CAMERA_RAW10);
|
||||
STR_CASE(CELL_CAMERA_RGBA);
|
||||
STR_CASE(CELL_CAMERA_YUV420);
|
||||
STR_CASE(CELL_CAMERA_V_Y1_U_Y0);
|
||||
}
|
||||
|
||||
return unknown;
|
||||
});
|
||||
}
|
||||
|
||||
// Temporarily
|
||||
#ifndef _MSC_VER
|
||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
@ -259,14 +280,10 @@ std::pair<u32, u32> get_video_resolution(const CellCameraInfoEx& info)
|
||||
}
|
||||
}
|
||||
|
||||
u32 get_video_buffer_size(const CellCameraInfoEx& info)
|
||||
u32 get_buffer_size_by_format(s32 format, s32 width, s32 height)
|
||||
{
|
||||
u32 width, height;
|
||||
std::tie(width, height) = get_video_resolution(info);
|
||||
|
||||
double bytes_per_pixel;
|
||||
|
||||
switch (info.format)
|
||||
double bytes_per_pixel = 0.0;
|
||||
switch (format)
|
||||
{
|
||||
case CELL_CAMERA_RAW8:
|
||||
bytes_per_pixel = 1.0;
|
||||
@ -292,6 +309,14 @@ u32 get_video_buffer_size(const CellCameraInfoEx& info)
|
||||
return width * height * bytes_per_pixel;
|
||||
}
|
||||
|
||||
|
||||
u32 get_video_buffer_size(const CellCameraInfoEx& info)
|
||||
{
|
||||
u32 width, height;
|
||||
std::tie(width, height) = get_video_resolution(info);
|
||||
return get_buffer_size_by_format(info.format, width, height);
|
||||
}
|
||||
|
||||
// ************************
|
||||
// * cellCamera functions *
|
||||
// ************************
|
||||
@ -563,12 +588,14 @@ error_code cellCameraOpenEx(s32 dev_num, vm::ptr<CellCameraInfoEx> info)
|
||||
g_camera.is_open = true;
|
||||
g_camera.info = *info;
|
||||
|
||||
cellCamera.notice("cellCameraOpen info: format=%d, resolution=%d, framerate=%d, bytesize=%d, width=%d, height=%d, dev_num=%d, guid=%d",
|
||||
cellCamera.notice("cellCameraOpen info: format=%s, resolution=%d, framerate=%d, bytesize=%d, width=%d, height=%d, dev_num=%d, guid=%d",
|
||||
info->format, info->resolution, info->framerate, info->bytesize, info->width, info->height, info->dev_num, info->guid);
|
||||
|
||||
auto& shared_data = g_fxo->get<gem_camera_shared>();
|
||||
shared_data.width = info->width > 0 ? +info->width : 640;
|
||||
shared_data.height = info->height > 0 ? +info->height : 480;
|
||||
shared_data.size = vbuf_size;
|
||||
shared_data.format = info->format;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
@ -1301,7 +1328,11 @@ error_code cellCameraReadEx(s32 dev_num, vm::ptr<CellCameraReadEx> read)
|
||||
|
||||
// can call cellCameraReset() and cellCameraStop() in some cases
|
||||
|
||||
const bool has_new_frame = g_camera.has_new_frame.exchange(false);
|
||||
|
||||
if (g_camera.handler)
|
||||
{
|
||||
if (has_new_frame)
|
||||
{
|
||||
u32 width{};
|
||||
u32 height{};
|
||||
@ -1313,29 +1344,31 @@ error_code cellCameraReadEx(s32 dev_num, vm::ptr<CellCameraReadEx> read)
|
||||
return CELL_CAMERA_ERROR_DEVICE_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (read)
|
||||
{
|
||||
read->frame = frame_number;
|
||||
read->bytesread = bytes_read;
|
||||
}
|
||||
g_camera.bytes_read = bytes_read;
|
||||
|
||||
cellCamera.trace("cellCameraRead: frame_number=%d, width=%d, height=%d. bytes_read=%d (passed to game: frame=%d, bytesread=%d)",
|
||||
frame_number, width, height, bytes_read, read ? read->frame.get() : 0, read ? read->bytesread.get() : 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
g_camera.bytes_read = g_camera.is_streaming ? get_video_buffer_size(g_camera.info) : 0;
|
||||
}
|
||||
|
||||
if (has_new_frame)
|
||||
{
|
||||
g_camera.frame_timestamp = (get_guest_system_time() - g_camera.start_timestamp);
|
||||
}
|
||||
|
||||
if (read) // NULL returns CELL_OK
|
||||
{
|
||||
read->timestamp = (get_guest_system_time() - g_camera.start_timestamp);
|
||||
|
||||
if (!g_camera.handler)
|
||||
{
|
||||
read->timestamp = g_camera.frame_timestamp;
|
||||
read->frame = g_camera.frame_num;
|
||||
read->bytesread = g_camera.is_streaming ? get_video_buffer_size(g_camera.info) : 0;
|
||||
}
|
||||
read->bytesread = g_camera.bytes_read;
|
||||
|
||||
auto& shared_data = g_fxo->get<gem_camera_shared>();
|
||||
|
||||
shared_data.frame_timestamp.exchange(read->timestamp);
|
||||
shared_data.frame_timestamp.store(read->timestamp);
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
@ -1627,9 +1660,9 @@ void camera_context::operator()()
|
||||
data3 = 0; // unused
|
||||
}
|
||||
|
||||
if (queue->send(evt_data.source, CELL_CAMERA_FRAME_UPDATE, data2, data3) == 0) [[likely]]
|
||||
if (queue->send(evt_data.source, CELL_CAMERA_FRAME_UPDATE, data2, data3) != 0) [[unlikely]]
|
||||
{
|
||||
++frame_num;
|
||||
cellCamera.warning("Failed to send frame update event");
|
||||
}
|
||||
|
||||
frame_update_event_sent = true;
|
||||
@ -1637,6 +1670,9 @@ void camera_context::operator()()
|
||||
}
|
||||
}
|
||||
|
||||
++frame_num;
|
||||
has_new_frame = true;
|
||||
|
||||
if (read_mode.load() == CELL_CAMERA_READ_DIRECT && frame_update_event_sent)
|
||||
{
|
||||
std::lock_guard lock(mutex);
|
||||
@ -1645,7 +1681,7 @@ void camera_context::operator()()
|
||||
|
||||
lock.unlock();
|
||||
|
||||
for (const u64 frame_target_time = 1000000u / fps;;)
|
||||
for (const u64 frame_target_time = 1000000u / fps; !Emu.IsStopped();)
|
||||
{
|
||||
const u64 time_passed = get_guest_system_time() - frame_start;
|
||||
if (time_passed >= frame_target_time)
|
||||
@ -1788,6 +1824,9 @@ void camera_context::reset_state()
|
||||
pbuf_write_index = 0;
|
||||
pbuf_locked[0] = false;
|
||||
pbuf_locked[1] = false;
|
||||
has_new_frame = false;
|
||||
frame_timestamp = 0;
|
||||
bytes_read = 0;
|
||||
|
||||
if (info.buffer)
|
||||
{
|
||||
|
@ -360,7 +360,7 @@ struct CellCameraInfo
|
||||
|
||||
struct CellCameraInfoEx
|
||||
{
|
||||
be_t<s32> format; // CellCameraFormat
|
||||
be_t<CellCameraFormat> format; // CellCameraFormat
|
||||
be_t<s32> resolution; // CellCameraResolution
|
||||
be_t<s32> framerate;
|
||||
|
||||
@ -435,7 +435,10 @@ public:
|
||||
u32 v1, v2;
|
||||
};
|
||||
attr_t attr[500]{};
|
||||
atomic_t<bool> has_new_frame = false;
|
||||
atomic_t<u32> frame_num = 0;
|
||||
atomic_t<u32> frame_timestamp = 0;
|
||||
atomic_t<u32> bytes_read = 0;
|
||||
|
||||
atomic_t<u32> init = 0;
|
||||
|
||||
@ -458,4 +461,8 @@ struct gem_camera_shared
|
||||
atomic_t<s64> frame_timestamp{}; // latest read timestamp from cellCamera (cellCameraRead(Ex))
|
||||
atomic_t<s32> width{640};
|
||||
atomic_t<s32> height{480};
|
||||
atomic_t<s32> size{0};
|
||||
atomic_t<CellCameraFormat> format{CELL_CAMERA_RAW8};
|
||||
};
|
||||
|
||||
static inline s32 get_video_buffer_size(s32 width, s32 height);
|
||||
|
@ -2,10 +2,12 @@
|
||||
#include "cellGem.h"
|
||||
#include "cellCamera.h"
|
||||
|
||||
#include "Emu/Cell/lv2/sys_event.h"
|
||||
#include "Emu/Cell/PPUModule.h"
|
||||
#include "Emu/Cell/timers.hpp"
|
||||
#include "Emu/Io/MouseHandler.h"
|
||||
#include "Emu/system_config.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/IdManager.h"
|
||||
#include "Input/pad_thread.h"
|
||||
|
||||
@ -59,12 +61,39 @@ void fmt_class_string<CellGemStatus>::format(std::string& out, u64 arg)
|
||||
});
|
||||
}
|
||||
|
||||
template <>
|
||||
void fmt_class_string<CellGemVideoConvertFormatEnum>::format(std::string& out, u64 arg)
|
||||
{
|
||||
format_enum(out, arg, [](auto format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
STR_CASE(CELL_GEM_NO_VIDEO_OUTPUT);
|
||||
STR_CASE(CELL_GEM_RGBA_640x480);
|
||||
STR_CASE(CELL_GEM_YUV_640x480);
|
||||
STR_CASE(CELL_GEM_YUV422_640x480);
|
||||
STR_CASE(CELL_GEM_YUV411_640x480);
|
||||
STR_CASE(CELL_GEM_RGBA_320x240);
|
||||
STR_CASE(CELL_GEM_BAYER_RESTORED);
|
||||
STR_CASE(CELL_GEM_BAYER_RESTORED_RGGB);
|
||||
STR_CASE(CELL_GEM_BAYER_RESTORED_RASTERIZED);
|
||||
}
|
||||
|
||||
return unknown;
|
||||
});
|
||||
}
|
||||
|
||||
// **********************
|
||||
// * HLE helper structs *
|
||||
// **********************
|
||||
|
||||
struct gem_config
|
||||
struct gem_config_data
|
||||
{
|
||||
public:
|
||||
void operator()();
|
||||
|
||||
static constexpr auto thread_name = "Gem Thread"sv;
|
||||
|
||||
atomic_t<u32> state = 0;
|
||||
|
||||
struct gem_color
|
||||
@ -106,14 +135,16 @@ struct gem_config
|
||||
|
||||
CellGemAttribute attribute = {};
|
||||
CellGemVideoConvertAttribute vc_attribute = {};
|
||||
s32 video_data_out_size = -1;
|
||||
std::vector<u8> video_data_in;
|
||||
u64 status_flags = 0;
|
||||
bool enable_pitch_correction = false;
|
||||
u32 inertial_counter = 0;
|
||||
|
||||
std::array<gem_controller, CELL_GEM_MAX_NUM> controllers;
|
||||
u32 connected_controllers = 0;
|
||||
bool video_conversion_started{};
|
||||
bool update_started{};
|
||||
atomic_t<bool> video_conversion_in_progress{false};
|
||||
atomic_t<bool> update_started{false};
|
||||
u32 camera_frame{};
|
||||
u32 memory_ptr{};
|
||||
|
||||
@ -173,6 +204,186 @@ struct gem_config
|
||||
}
|
||||
};
|
||||
|
||||
static inline int32_t cellGemGetVideoConvertSize(s32 output_format)
|
||||
{
|
||||
switch (output_format)
|
||||
{
|
||||
case CELL_GEM_RGBA_320x240: // RGBA output; 320*240*4-byte output buffer required
|
||||
return 320 * 240 * 4;
|
||||
case CELL_GEM_RGBA_640x480: // RGBA output; 640*480*4-byte output buffer required
|
||||
return 640 * 480 * 4;
|
||||
case CELL_GEM_YUV_640x480: // YUV output; 640*480+640*480+640*480-byte output buffer required (contiguous)
|
||||
return 640 * 480 + 640 * 480 + 640 * 480;
|
||||
case CELL_GEM_YUV422_640x480: // YUV output; 640*480+320*480+320*480-byte output buffer required (contiguous)
|
||||
return 640 * 480 + 320 * 480 + 320 * 480;
|
||||
case CELL_GEM_YUV411_640x480: // YUV411 output; 640*480+320*240+320*240-byte output buffer required (contiguous)
|
||||
return 640 * 480 + 320 * 240 + 320 * 240;
|
||||
case CELL_GEM_BAYER_RESTORED: // Bayer pattern output, 640x480, gamma and white balance applied, output buffer required
|
||||
case CELL_GEM_BAYER_RESTORED_RGGB: // Restored Bayer output, 2x2 pixels rearranged into 320x240 RG1G2B
|
||||
case CELL_GEM_BAYER_RESTORED_RASTERIZED: // Restored Bayer output, R,G1,G2,B rearranged into 4 contiguous 320x240 1-channel rasters
|
||||
return 640 * 480;
|
||||
case CELL_GEM_NO_VIDEO_OUTPUT: // Disable video output
|
||||
return 0;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
void gem_config_data::operator()()
|
||||
{
|
||||
cellGem.notice("Starting thread");
|
||||
|
||||
while (thread_ctrl::state() != thread_state::aborting && !Emu.IsStopped())
|
||||
{
|
||||
while (!video_conversion_in_progress && thread_ctrl::state() != thread_state::aborting && !Emu.IsStopped())
|
||||
{
|
||||
thread_ctrl::wait_for(1000);
|
||||
}
|
||||
|
||||
if (thread_ctrl::state() == thread_state::aborting || Emu.IsStopped())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CellGemVideoConvertAttribute vc;
|
||||
{
|
||||
std::scoped_lock lock(mtx);
|
||||
vc = vc_attribute;
|
||||
}
|
||||
|
||||
if (g_cfg.io.camera != camera_handler::qt)
|
||||
{
|
||||
video_conversion_in_progress = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto& shared_data = g_fxo->get<gem_camera_shared>();
|
||||
|
||||
if (vc.output_format != CELL_GEM_NO_VIDEO_OUTPUT && !vc_attribute.video_data_out)
|
||||
{
|
||||
video_conversion_in_progress = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
extern u32 get_buffer_size_by_format(s32, s32, s32);
|
||||
const u32 required_in_size = get_buffer_size_by_format(static_cast<s32>(shared_data.format), shared_data.width, shared_data.height);
|
||||
const s32 required_out_size = cellGemGetVideoConvertSize(vc.output_format);
|
||||
|
||||
if (video_data_in.size() != required_in_size)
|
||||
{
|
||||
cellGem.error("convert: in_size mismatch: required=%d, actual=%d", required_in_size, video_data_in.size());
|
||||
video_conversion_in_progress = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (required_out_size < 0 || video_data_out_size != required_out_size)
|
||||
{
|
||||
cellGem.error("convert: out_size unknown: required=%d, format %d", required_out_size, vc.output_format);
|
||||
video_conversion_in_progress = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (required_out_size == 0)
|
||||
{
|
||||
video_conversion_in_progress = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (vc.output_format)
|
||||
{
|
||||
case CELL_GEM_RGBA_640x480: // RGBA output; 640*480*4-byte output buffer required
|
||||
{
|
||||
if (shared_data.format == CELL_CAMERA_RAW8)
|
||||
{
|
||||
constexpr u32 in_pitch = 640;
|
||||
constexpr u32 out_pitch = 640 * 4;
|
||||
|
||||
for (u32 y = 0; y < 480 - 1; y += 2)
|
||||
{
|
||||
for (u32 x = 0; x < 640 - 1; x += 2)
|
||||
{
|
||||
const u32 in_offset = 1 * (y * 640 + x);
|
||||
const u32 out_offset = 4 * (y * 640 + x);
|
||||
|
||||
const u8 b = video_data_in[in_offset + 0];
|
||||
const u8 g0 = video_data_in[in_offset + 1];
|
||||
const u8 g1 = video_data_in[in_offset + in_pitch + 0];
|
||||
const u8 r = video_data_in[in_offset + in_pitch + 1];
|
||||
|
||||
// Top-Left
|
||||
vc_attribute.video_data_out[out_offset + 0] = r; // R
|
||||
vc_attribute.video_data_out[out_offset + 1] = g0; // G
|
||||
vc_attribute.video_data_out[out_offset + 2] = b; // B
|
||||
vc_attribute.video_data_out[out_offset + 3] = 255; // A
|
||||
|
||||
// Top-Right Pixel
|
||||
vc_attribute.video_data_out[out_offset + 4] = r; // R
|
||||
vc_attribute.video_data_out[out_offset + 5] = g0; // G
|
||||
vc_attribute.video_data_out[out_offset + 6] = b; // B
|
||||
vc_attribute.video_data_out[out_offset + 7] = 255; // A
|
||||
|
||||
// Bottom-Left Pixel
|
||||
vc_attribute.video_data_out[out_offset + out_pitch + 0] = r; // R
|
||||
vc_attribute.video_data_out[out_offset + out_pitch + 1] = g1; // G
|
||||
vc_attribute.video_data_out[out_offset + out_pitch + 2] = b; // B
|
||||
vc_attribute.video_data_out[out_offset + out_pitch + 3] = 255; // A
|
||||
|
||||
// Bottom-Right Pixel
|
||||
vc_attribute.video_data_out[out_offset + out_pitch + 4] = r; // R
|
||||
vc_attribute.video_data_out[out_offset + out_pitch + 5] = g1; // G
|
||||
vc_attribute.video_data_out[out_offset + out_pitch + 6] = b; // B
|
||||
vc_attribute.video_data_out[out_offset + out_pitch + 7] = 255; // A
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cellGem.error("Unimplemented: Converting %s to %s", shared_data.format.load(), vc.output_format);
|
||||
std::memcpy(vc_attribute.video_data_out.get_ptr(), video_data_in.data(), std::min<usz>(required_in_size, required_out_size));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CELL_GEM_BAYER_RESTORED: // Bayer pattern output, 640x480, gamma and white balance applied, output buffer required
|
||||
{
|
||||
if (shared_data.format == CELL_CAMERA_RAW8)
|
||||
{
|
||||
std::memcpy(vc_attribute.video_data_out.get_ptr(), video_data_in.data(), std::min<usz>(required_in_size, required_out_size));
|
||||
}
|
||||
else
|
||||
{
|
||||
cellGem.error("Unimplemented: Converting %s to %s", shared_data.format.load(), vc.output_format);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CELL_GEM_RGBA_320x240: // RGBA output; 320*240*4-byte output buffer required
|
||||
case CELL_GEM_YUV_640x480: // YUV output; 640*480+640*480+640*480-byte output buffer required (contiguous)
|
||||
case CELL_GEM_YUV422_640x480: // YUV output; 640*480+320*480+320*480-byte output buffer required (contiguous)
|
||||
case CELL_GEM_YUV411_640x480: // YUV411 output; 640*480+320*240+320*240-byte output buffer required (contiguous)
|
||||
case CELL_GEM_BAYER_RESTORED_RGGB: // Restored Bayer output, 2x2 pixels rearranged into 320x240 RG1G2B
|
||||
case CELL_GEM_BAYER_RESTORED_RASTERIZED: // Restored Bayer output, R,G1,G2,B rearranged into 4 contiguous 320x240 1-channel rasters
|
||||
{
|
||||
cellGem.error("Unimplemented: Converting %s to %s", shared_data.format.load(), vc.output_format);
|
||||
break;
|
||||
}
|
||||
case CELL_GEM_NO_VIDEO_OUTPUT: // Disable video output
|
||||
{
|
||||
cellGem.trace("Ignoring frame conversion for CELL_GEM_NO_VIDEO_OUTPUT");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
cellGem.error("Trying to convert %s to %s", shared_data.format.load(), vc.output_format);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cellGem.notice("Converted video frame of format %s to %s", shared_data.format.load(), vc.output_format.get());
|
||||
video_conversion_in_progress = false;
|
||||
}
|
||||
}
|
||||
|
||||
using gem_config = named_thread<gem_config_data>;
|
||||
|
||||
/**
|
||||
* \brief Verifies that a Move controller id is valid
|
||||
* \param gem_num Move controler ID to verify
|
||||
@ -528,12 +739,15 @@ error_code cellGemConvertVideoFinish()
|
||||
return CELL_GEM_ERROR_UNINITIALIZED;
|
||||
}
|
||||
|
||||
if (!std::exchange(gem.video_conversion_started, false))
|
||||
if (!gem.video_conversion_in_progress)
|
||||
{
|
||||
return CELL_GEM_ERROR_CONVERT_NOT_STARTED;
|
||||
}
|
||||
|
||||
// TODO: wait until image is converted
|
||||
while (gem.video_conversion_in_progress && !Emu.IsStopped())
|
||||
{
|
||||
thread_ctrl::wait_for(100);
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
@ -555,17 +769,20 @@ error_code cellGemConvertVideoStart(vm::cptr<void> video_frame)
|
||||
}
|
||||
|
||||
// TODO: The alignment checks seem to break Time Crisis Razing Storm [BLUS30528]
|
||||
//if (!video_frame.aligned(128))
|
||||
//{
|
||||
// return CELL_GEM_ERROR_INVALID_ALIGNMENT;
|
||||
//}
|
||||
if (!video_frame.aligned(128))
|
||||
{
|
||||
return CELL_GEM_ERROR_INVALID_ALIGNMENT;
|
||||
}
|
||||
|
||||
if (std::exchange(gem.video_conversion_started, true))
|
||||
if (gem.video_conversion_in_progress)
|
||||
{
|
||||
return CELL_GEM_ERROR_CONVERT_NOT_FINISHED;
|
||||
}
|
||||
|
||||
// TODO: start image conversion of video_frame async to gem.vc_attribute.video_data_out
|
||||
const auto& shared_data = g_fxo->get<gem_camera_shared>();
|
||||
gem.video_data_in.resize(shared_data.size);
|
||||
std::memcpy(gem.video_data_in.data(), video_frame.get_ptr(), gem.video_data_in.size());
|
||||
gem.video_conversion_in_progress = true;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
@ -753,11 +970,6 @@ error_code cellGemGetCameraState(vm::ptr<CellGemCameraState> camera_state)
|
||||
|
||||
auto& gem = g_fxo->get<gem_config>();
|
||||
|
||||
if (!gem.state)
|
||||
{
|
||||
return CELL_GEM_ERROR_UNINITIALIZED;
|
||||
}
|
||||
|
||||
if (!camera_state)
|
||||
{
|
||||
return CELL_GEM_ERROR_INVALID_PARAMETER;
|
||||
@ -879,7 +1091,7 @@ error_code cellGemGetInertialState(u32 gem_num, u32 state_flag, u64 timestamp, v
|
||||
return CELL_GEM_ERROR_UNINITIALIZED;
|
||||
}
|
||||
|
||||
if (!check_gem_num(gem_num) || state_flag > CELL_GEM_INERTIAL_STATE_FLAG_NEXT || !inertial_state || !gem.is_controller_ready(gem_num))
|
||||
if (!check_gem_num(gem_num) || !inertial_state || !gem.is_controller_ready(gem_num))
|
||||
{
|
||||
return CELL_GEM_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
@ -1303,12 +1515,17 @@ s32 cellGemIsTrackableHue(u32 hue)
|
||||
|
||||
auto& gem = g_fxo->get<gem_config>();
|
||||
|
||||
if (!gem.state || hue > 359)
|
||||
if (!gem.state)
|
||||
{
|
||||
return false;
|
||||
return CELL_GEM_ERROR_UNINITIALIZED;
|
||||
}
|
||||
|
||||
return true;
|
||||
if (hue > 359)
|
||||
{
|
||||
return CELL_GEM_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
error_code cellGemPrepareCamera(s32 max_exposure, f32 image_quality)
|
||||
@ -1353,27 +1570,34 @@ error_code cellGemPrepareVideoConvert(vm::cptr<CellGemVideoConvertAttribute> vc_
|
||||
|
||||
const CellGemVideoConvertAttribute vc = *vc_attribute;
|
||||
|
||||
if (!vc_attribute || vc.version != CELL_GEM_VERSION)
|
||||
if (vc.version != CELL_GEM_VERSION)
|
||||
{
|
||||
return CELL_GEM_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (vc.output_format != CELL_GEM_NO_VIDEO_OUTPUT)
|
||||
{
|
||||
if (!vc.video_data_out || ((vc.conversion_flags & CELL_GEM_COMBINE_PREVIOUS_INPUT_FRAME) && !vc.buffer_memory))
|
||||
if (!vc.video_data_out)
|
||||
{
|
||||
return CELL_GEM_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: The alignment checks seem to break Time Crisis Razing Storm [BLUS30528]
|
||||
//if (!vc.video_data_out.aligned(16) || !vc.buffer_memory.aligned(128))
|
||||
//{
|
||||
// return CELL_GEM_ERROR_INVALID_ALIGNMENT;
|
||||
//}
|
||||
if ((vc.conversion_flags & CELL_GEM_COMBINE_PREVIOUS_INPUT_FRAME) && !vc.buffer_memory)
|
||||
{
|
||||
return CELL_GEM_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (!vc.video_data_out.aligned(128) || !vc.buffer_memory.aligned(16))
|
||||
{
|
||||
return CELL_GEM_ERROR_INVALID_ALIGNMENT;
|
||||
}
|
||||
|
||||
gem.vc_attribute = vc;
|
||||
|
||||
const s32 buffer_size = cellGemGetVideoConvertSize(vc.output_format);
|
||||
gem.video_data_out_size = buffer_size;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@ -1468,7 +1692,7 @@ error_code cellGemSetYaw(u32 gem_num, vm::ptr<f32> z_direction)
|
||||
return CELL_GEM_ERROR_UNINITIALIZED;
|
||||
}
|
||||
|
||||
if (!z_direction)
|
||||
if (!z_direction || !check_gem_num(gem_num))
|
||||
{
|
||||
return CELL_GEM_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
@ -1571,7 +1795,7 @@ error_code cellGemUpdateFinish()
|
||||
|
||||
std::scoped_lock lock(gem.mtx);
|
||||
|
||||
if (!std::exchange(gem.update_started, false))
|
||||
if (!gem.update_started.exchange(false))
|
||||
{
|
||||
return CELL_GEM_ERROR_UPDATE_NOT_STARTED;
|
||||
}
|
||||
@ -1598,16 +1822,16 @@ error_code cellGemUpdateStart(vm::cptr<void> camera_frame, u64 timestamp)
|
||||
std::scoped_lock lock(gem.mtx);
|
||||
|
||||
// Update is starting even when camera_frame is null
|
||||
if (std::exchange(gem.update_started, true))
|
||||
if (gem.update_started.exchange(true))
|
||||
{
|
||||
return CELL_GEM_ERROR_UPDATE_NOT_FINISHED;
|
||||
}
|
||||
|
||||
// TODO: The alignment checks seem to break Time Crisis Razing Storm [BLUS30528]
|
||||
//if (!camera_frame.aligned(128))
|
||||
//{
|
||||
// return CELL_GEM_ERROR_INVALID_ALIGNMENT;
|
||||
//}
|
||||
if (!camera_frame.aligned(128))
|
||||
{
|
||||
return CELL_GEM_ERROR_INVALID_ALIGNMENT;
|
||||
}
|
||||
|
||||
gem.camera_frame = camera_frame.addr();
|
||||
if (!camera_frame)
|
||||
|
@ -145,7 +145,7 @@ enum
|
||||
};
|
||||
|
||||
// Video conversion output formats
|
||||
enum
|
||||
enum CellGemVideoConvertFormatEnum : s32
|
||||
{
|
||||
CELL_GEM_NO_VIDEO_OUTPUT = 1,
|
||||
CELL_GEM_RGBA_640x480 = 2,
|
||||
@ -261,13 +261,13 @@ struct CellGemState
|
||||
struct CellGemVideoConvertAttribute
|
||||
{
|
||||
be_t<s32> version;
|
||||
be_t<s32> output_format;
|
||||
be_t<CellGemVideoConvertFormatEnum> output_format;
|
||||
be_t<s32> conversion_flags;
|
||||
be_t<f32> gain;
|
||||
be_t<f32> red_gain;
|
||||
be_t<f32> green_gain;
|
||||
be_t<f32> blue_gain;
|
||||
vm::ptr<void> buffer_memory;
|
||||
vm::ptr<void> video_data_out;
|
||||
vm::bptr<u8> buffer_memory;
|
||||
vm::bptr<u8> video_data_out;
|
||||
u8 alpha;
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user