cellCamera: improvements

This commit is contained in:
Megamouse 2018-06-25 00:31:39 +02:00
parent 456aa4ab8d
commit 69af607491
2 changed files with 428 additions and 95 deletions

View file

@ -16,6 +16,7 @@ logs::channel cellCamera("cellCamera");
// **************
s32 cellCameraSetAttribute(s32 dev_num, s32 attrib, u32 arg1, u32 arg2);
s32 cellCameraReadEx(s32 dev_num, vm::ptr<CellCameraReadEx> read);
// ************************
// * HLE helper functions *
@ -116,6 +117,136 @@ static bool check_dev_num(s32 dev_num)
return dev_num == 0;
}
static s32 check_camera_info(const CellCameraInfoEx& info)
{
// TODO: I managed to get 0x80990004 once. :thonkang:
if (info.format == CELL_CAMERA_FORMAT_UNKNOWN)
{
return CELL_CAMERA_ERROR_FORMAT_UNKNOWN;
}
if (info.resolution == CELL_CAMERA_RESOLUTION_UNKNOWN)
{
return CELL_CAMERA_ERROR_RESOLUTION_UNKNOWN;
}
if (info.framerate <= 24)
{
return CELL_CAMERA_ERROR_BAD_FRAMERATE;
}
auto check_fps = [fps = info.framerate](const std::vector<s32>& range)
{
return std::find(range.begin(), range.end(), fps) != range.end();
};
switch (g_cfg.io.camera_type)
{
case fake_camera_type::eyetoy:
switch (info.format)
{
case CELL_CAMERA_JPG:
switch (info.resolution)
{
case CELL_CAMERA_VGA:
case CELL_CAMERA_WGA:
if (!check_fps({ 25, 30 }))
return CELL_CAMERA_ERROR_FORMAT_UNKNOWN;
break;
case CELL_CAMERA_QVGA:
if (!check_fps({ 25, 30, 50, 60 }))
return CELL_CAMERA_ERROR_FORMAT_UNKNOWN;
break;
case CELL_CAMERA_SPECIFIED_WIDTH_HEIGHT:
default:
// TODO
return CELL_CAMERA_ERROR_FORMAT_UNKNOWN;
}
break;
case CELL_CAMERA_RAW8:
case CELL_CAMERA_YUV422:
case CELL_CAMERA_RAW10:
case CELL_CAMERA_RGBA:
case CELL_CAMERA_YUV420:
case CELL_CAMERA_V_Y1_U_Y0:
default:
// TODO (also check those other formats)
return CELL_CAMERA_ERROR_FORMAT_UNKNOWN;
}
break;
case fake_camera_type::eyetoy2:
switch (info.format)
{
case CELL_CAMERA_JPG:
case CELL_CAMERA_RAW10:
return CELL_CAMERA_ERROR_FORMAT_UNKNOWN;
case CELL_CAMERA_RAW8:
switch (info.resolution)
{
case CELL_CAMERA_VGA:
case CELL_CAMERA_WGA:
if (!check_fps({ 25, 30, 50, 60 }))
return CELL_CAMERA_ERROR_FORMAT_UNKNOWN;
break;
case CELL_CAMERA_QVGA:
if (!check_fps({ 25, 30, 50, 60, 100, 120 }))
return CELL_CAMERA_ERROR_FORMAT_UNKNOWN;
break;
case CELL_CAMERA_SPECIFIED_WIDTH_HEIGHT:
default:
// TODO
return CELL_CAMERA_ERROR_FORMAT_UNKNOWN;
}
break;
case CELL_CAMERA_YUV422:
case CELL_CAMERA_RGBA: // < TODO check: they all seem to pass the same resolutions as in CELL_CAMERA_YUV422
case CELL_CAMERA_YUV420: // <
case CELL_CAMERA_V_Y1_U_Y0: // <
default: // <
switch (info.resolution)
{
case CELL_CAMERA_VGA:
case CELL_CAMERA_WGA:
if (!check_fps({ 25, 30 }))
return CELL_CAMERA_ERROR_FORMAT_UNKNOWN;
break;
case CELL_CAMERA_QVGA:
if (!check_fps({ 25, 30, 50, 60 }))
return CELL_CAMERA_ERROR_FORMAT_UNKNOWN;
break;
case CELL_CAMERA_SPECIFIED_WIDTH_HEIGHT:
default:
// TODO
return CELL_CAMERA_ERROR_FORMAT_UNKNOWN;
}
break;
}
break;
case fake_camera_type::uvc1_1:
switch (info.format)
{
case CELL_CAMERA_JPG:
case CELL_CAMERA_YUV422:
break;
case CELL_CAMERA_RAW8:
case CELL_CAMERA_RAW10:
case CELL_CAMERA_RGBA:
case CELL_CAMERA_YUV420:
case CELL_CAMERA_V_Y1_U_Y0:
default:
// TODO
return CELL_CAMERA_ERROR_FORMAT_UNKNOWN;
}
break;
case fake_camera_type::unknown:
default:
// TODO
break;
}
return CELL_OK;
};
/**
* \brief Sets up notify event queue supplied and immediately sends an ATTACH event to it
* \param key Event queue key to add
@ -169,33 +300,15 @@ bool remove_queue(u64 key)
/**
* \brief Sets read mode attribute (used for deciding how image data is passed to games)
* Also sends it to the camera thread
* NOTE: thread-safe (uses camera_thread::mutex)
* Also sends it to the camera thread
* NOTE: thread-safe (uses camera_thread::mutex)
* \param dev_num Device number (always 0)
* \param read_mode Either CELL_CAMERA_READ_FUNCCALL or CELL_CAMERA_READ_DIRECT
* \param read_mode is CELL_CAMERA_READ_DIRECT or else CELL_CAMERA_READ_FUNCCALL
* \return CELL error code or CELL_OK
*/
u32 set_and_send_read_mode(s32 dev_num, const s32 read_mode)
s32 set_and_send_read_mode(s32 dev_num, const s32 read_mode)
{
if (read_mode == CELL_CAMERA_READ_FUNCCALL ||
read_mode == CELL_CAMERA_READ_DIRECT)
{
if (const auto status = cellCameraSetAttribute(dev_num, CELL_CAMERA_READMODE, read_mode, 0))
{
return status;
}
}
else
{
cellCamera.error("Unknown read mode set: %d", read_mode);
}
// Send read mode to camera thread
const auto g_camera = fxm::get<camera_thread>();
g_camera->read_mode.exchange(read_mode);
return CELL_OK;
return cellCameraSetAttribute(dev_num, CELL_CAMERA_READMODE, read_mode, 0);
}
std::pair<u32, u32> get_video_resolution(const CellCameraInfoEx& info)
@ -302,6 +415,13 @@ s32 cellCameraEnd()
return CELL_OK;
}
// TODO: My tests hinted to this behavior, but I'm not sure, so I'll leave this commented
//s32 res = cellCameraClose(0);
//if (res != CELL_OK)
//{
// return res;
//}
if (!fxm::remove<camera_thread>())
{
return CELL_CAMERA_ERROR_NOT_INIT;
@ -320,6 +440,13 @@ s32 cellCameraOpenEx(s32 dev_num, vm::ptr<CellCameraInfoEx> info)
{
cellCamera.todo("cellCameraOpenEx(dev_num=%d, type=*0x%x)", dev_num, info);
// This function has a very weird order of checking for errors
if (!info)
{
return CELL_CAMERA_ERROR_PARAM;
}
if (g_cfg.io.camera == camera_handler::null)
{
return CELL_CAMERA_ERROR_DEVICE_NOT_FOUND;
@ -332,20 +459,38 @@ s32 cellCameraOpenEx(s32 dev_num, vm::ptr<CellCameraInfoEx> info)
return CELL_CAMERA_ERROR_NOT_INIT;
}
s32 read_mode = info->read_mode;
u32 status = set_and_send_read_mode(dev_num, read_mode);
s32 status = set_and_send_read_mode(dev_num, info->read_mode);
if (status != CELL_OK)
{
return status;
}
status = cellCameraSetAttribute(dev_num, CELL_CAMERA_GAMEPID, status, 0); // yup, that's what libGem does
status = cellCameraSetAttribute(dev_num, CELL_CAMERA_GAMEPID, 0, 0); // yup, that's what libGem does
if (status != CELL_OK)
{
return status;
}
if (!check_dev_num)
{
return CELL_CAMERA_ERROR_PARAM;
}
semaphore_lock lock(g_camera->mutex);
if (g_camera->is_open)
{
return CELL_CAMERA_ERROR_ALREADY_OPEN;
}
status = check_camera_info(*info);
if (status < 0)
{
return status;
}
// calls cellCameraGetAttribute(dev_num, CELL_CAMERA_PBUFFER) at some point
const auto vbuf_size = get_video_buffer_size(*info);
if (info->read_mode == CELL_CAMERA_READ_FUNCCALL && !info->buffer)
@ -356,8 +501,6 @@ s32 cellCameraOpenEx(s32 dev_num, vm::ptr<CellCameraInfoEx> info)
std::tie(info->width, info->height) = get_video_resolution(*info);
semaphore_lock lock(g_camera->mutex);
g_camera->is_open = true;
g_camera->info = *info;
@ -368,6 +511,11 @@ s32 cellCameraClose(s32 dev_num)
{
cellCamera.todo("cellCameraClose(dev_num=%d)", dev_num);
if (!check_dev_num(dev_num))
{
return CELL_CAMERA_ERROR_PARAM;
}
if (g_cfg.io.camera == camera_handler::null)
{
return CELL_CAMERA_ERROR_NOT_OPEN;
@ -382,6 +530,11 @@ s32 cellCameraClose(s32 dev_num)
semaphore_lock lock(g_camera->mutex);
if (!g_camera->is_open)
{
return CELL_CAMERA_ERROR_NOT_OPEN;
}
vm::dealloc(g_camera->info.buffer.addr(), vm::memory_location_t::main);
g_camera->is_open = false;
@ -390,7 +543,19 @@ s32 cellCameraClose(s32 dev_num)
s32 cellCameraGetDeviceGUID(s32 dev_num, vm::ptr<u32> guid)
{
UNIMPLEMENTED_FUNC(cellCamera);
cellCamera.todo("cellCameraGetDeviceGUID(dev_num=%d, guid=*0x%x)", dev_num, guid);
const auto g_camera = fxm::get<camera_thread>();
if (!g_camera)
{
return CELL_CAMERA_ERROR_NOT_INIT;
}
// Does not check params or is_open (maybe attached?)
*guid = 0; // apparently always 0
return CELL_OK;
}
@ -415,6 +580,11 @@ s32 cellCameraGetType(s32 dev_num, vm::ptr<s32> type)
return CELL_CAMERA_ERROR_PARAM;
}
if (!g_camera->is_attached)
{
return CELL_CAMERA_ERROR_DEVICE_NOT_FOUND;
}
switch (g_cfg.io.camera_type)
{
case fake_camera_type::unknown: *type = CELL_CAMERA_TYPE_UNKNOWN; break;
@ -456,7 +626,7 @@ s32 cellCameraIsAttached(s32 dev_num)
const auto g_camera = fxm::get<camera_thread>();
if (!g_camera)
if (!g_camera || !check_dev_num(dev_num))
{
return false;
}
@ -487,6 +657,11 @@ s32 cellCameraIsOpen(s32 dev_num)
const auto g_camera = fxm::get<camera_thread>();
if (!g_camera || !check_dev_num(dev_num))
{
return false;
}
semaphore_lock lock(g_camera->mutex);
return g_camera->is_open;
@ -503,13 +678,20 @@ s32 cellCameraIsStarted(s32 dev_num)
const auto g_camera = fxm::get<camera_thread>();
if (!g_camera || !check_dev_num(dev_num))
{
return false;
}
semaphore_lock lock(g_camera->mutex);
return g_camera->is_streaming;
}
s32 cellCameraGetAttribute(s32 dev_num, s32 attrib, vm::ptr<u32> arg1, vm::ptr<u32> arg2)
{
const auto attr_name = get_camera_attr_name(attrib);
cellCamera.todo("cellCameraGetAttribute: get attrib %s to: 0x%x - 0x%x)", attr_name ? attr_name : "(invalid)", arg1, arg2);
cellCamera.todo("cellCameraGetAttribute(dev_num=%d, attrib=%d=%s, arg1=*0x%x, arg2=*0x%x)", dev_num, attrib, attr_name, arg1, arg2);
if (g_cfg.io.camera == camera_handler::null)
{
@ -523,15 +705,18 @@ s32 cellCameraGetAttribute(s32 dev_num, s32 attrib, vm::ptr<u32> arg1, vm::ptr<u
return CELL_CAMERA_ERROR_NOT_INIT;
}
if (!attr_name) // invalid attributes don't have a name
if (!check_dev_num(dev_num) || !attr_name || !arg1) // invalid attributes don't have a name and at least arg1 should not be NULL
{
return CELL_CAMERA_ERROR_PARAM;
}
cellCamera.todo("cellCameraGetAttribute: get attrib %s arg1: %d arg2: %d", attr_name, arg1, arg2);
semaphore_lock lock(g_camera->mutex);
if (!g_camera->is_attached)
{
return CELL_CAMERA_ERROR_DEVICE_NOT_FOUND;
}
if (arg1)
{
*arg1 = g_camera->attr[attrib].v1;
@ -547,7 +732,7 @@ s32 cellCameraGetAttribute(s32 dev_num, s32 attrib, vm::ptr<u32> arg1, vm::ptr<u
s32 cellCameraSetAttribute(s32 dev_num, s32 attrib, u32 arg1, u32 arg2)
{
const auto attr_name = get_camera_attr_name(attrib);
cellCamera.todo("cellCameraSetAttribute: set attrib %s to: %d - %d)", attr_name ? attr_name : "(invalid)", arg1, arg2);
cellCamera.todo("cellCameraSetAttribute(dev_num=%d, attrib=%d=%s, arg1=%d, arg2=%d)", dev_num, attrib, attr_name, arg1, arg2);
if (g_cfg.io.camera == camera_handler::null)
{
@ -561,12 +746,28 @@ s32 cellCameraSetAttribute(s32 dev_num, s32 attrib, u32 arg1, u32 arg2)
return CELL_CAMERA_ERROR_NOT_INIT;
}
if (!attr_name) // invalid attributes don't have a name
if (!check_dev_num(dev_num) || !attr_name) // invalid attributes don't have a name
{
return CELL_CAMERA_ERROR_PARAM;
}
semaphore_lock lock(g_camera->mutex);
if (!g_camera->is_open)
{
return CELL_CAMERA_ERROR_NOT_OPEN;
}
if (attrib == CELL_CAMERA_READMODE)
{
if (arg1 != CELL_CAMERA_READ_FUNCCALL && arg1 != CELL_CAMERA_READ_DIRECT)
{
LOG_WARNING(HLE, "Unknown read mode set: %d", arg1);
arg1 = CELL_CAMERA_READ_FUNCCALL;
}
g_camera->read_mode.exchange(arg1);
}
g_camera->attr[attrib] = { arg1, arg2 };
return CELL_OK;
@ -588,15 +789,35 @@ s32 cellCameraGetBufferSize(s32 dev_num, vm::ptr<CellCameraInfoEx> info)
return CELL_CAMERA_ERROR_NOT_INIT;
}
// TODO: a bunch of arg checks. here's one
// the next few checks have a strange order, if I can trust the tests
if (!check_dev_num(dev_num))
{
return CELL_CAMERA_ERROR_PARAM;
}
if (g_camera->is_open)
{
return CELL_CAMERA_ERROR_ALREADY_OPEN;
}
if (!info)
{
return CELL_CAMERA_ERROR_PARAM;
}
s32 res = check_camera_info(*info);
if (res < 0)
{
return res;
}
if (!cellCameraIsAttached(dev_num))
{
return CELL_CAMERA_ERROR_DEVICE_NOT_FOUND;
}
const auto read_mode = info->read_mode;
u32 status = set_and_send_read_mode(dev_num, read_mode);
u32 status = set_and_send_read_mode(dev_num, info->read_mode);
if (status != CELL_OK)
{
return status;
@ -614,6 +835,9 @@ s32 cellCameraGetBufferSize(s32 dev_num, vm::ptr<CellCameraInfoEx> info)
s32 cellCameraGetBufferInfo()
{
UNIMPLEMENTED_FUNC(cellCamera);
// called by cellCameraGetBufferInfoEx
return CELL_OK;
}
@ -621,6 +845,8 @@ s32 cellCameraGetBufferInfoEx(s32 dev_num, vm::ptr<CellCameraInfoEx> info)
{
cellCamera.todo("cellCameraGetBufferInfoEx(dev_num=%d, read=0x%x)", dev_num, info);
// the following should be moved to cellCameraGetBufferInfo
if (g_cfg.io.camera == camera_handler::null)
{
return CELL_CAMERA_ERROR_NOT_OPEN;
@ -633,13 +859,23 @@ s32 cellCameraGetBufferInfoEx(s32 dev_num, vm::ptr<CellCameraInfoEx> info)
return CELL_CAMERA_ERROR_NOT_INIT;
}
if (!info)
if (!check_dev_num(dev_num))
{
return CELL_CAMERA_ERROR_PARAM;
}
semaphore_lock lock(g_camera->mutex);
if (!g_camera->is_open)
{
return CELL_CAMERA_ERROR_NOT_OPEN;
}
if (!info)
{
return CELL_CAMERA_ERROR_PARAM;
}
*info = g_camera->info;
return CELL_OK;
@ -659,32 +895,27 @@ s32 cellCameraCtrlExtensionUnit(s32 dev_num, u8 request, u16 value, u16 length,
s32 cellCameraGetExtensionUnit(s32 dev_num, u16 value, u16 length, vm::ptr<u8> data)
{
UNIMPLEMENTED_FUNC(cellCamera);
return CELL_OK;
cellCamera.todo("cellCameraGetExtensionUnit(dev_num=%d, value=%d, length=%d, data=*0x%x)", dev_num, value, length, data);
return cellCameraCtrlExtensionUnit(dev_num, GET_CUR, value, length, data);
}
s32 cellCameraSetExtensionUnit(s32 dev_num, u16 value, u16 length, vm::ptr<u8> data)
{
UNIMPLEMENTED_FUNC(cellCamera);
return CELL_OK;
cellCamera.todo("cellCameraSetExtensionUnit(dev_num=%d, value=%d, length=%d, data=*0x%x)", dev_num, value, length, data);
return cellCameraCtrlExtensionUnit(dev_num, SET_CUR, value, length, data);
}
s32 cellCameraReset(s32 dev_num)
{
cellCamera.todo("cellCameraReset(dev_num=%d)", dev_num);
if (g_cfg.io.camera == camera_handler::null)
if (!check_dev_num(dev_num))
{
return CELL_CAMERA_ERROR_NOT_OPEN;
return CELL_CAMERA_ERROR_PARAM;
}
return CELL_OK;
}
s32 cellCameraStart(s32 dev_num)
{
cellCamera.todo("cellCameraStart(dev_num=%d)", dev_num);
if (g_cfg.io.camera == camera_handler::null)
{
return CELL_CAMERA_ERROR_NOT_OPEN;
@ -699,6 +930,54 @@ s32 cellCameraStart(s32 dev_num)
semaphore_lock lock(g_camera->mutex);
if (!g_camera->is_open)
{
return CELL_CAMERA_ERROR_NOT_OPEN;
}
if (!g_camera->is_attached)
{
return CELL_CAMERA_ERROR_DEVICE_NOT_FOUND;
}
// TODO reset camera
return CELL_OK;
}
s32 cellCameraStart(s32 dev_num)
{
cellCamera.todo("cellCameraStart(dev_num=%d)", dev_num);
if (!check_dev_num(dev_num))
{
return CELL_CAMERA_ERROR_PARAM;
}
if (g_cfg.io.camera == camera_handler::null)
{
return CELL_CAMERA_ERROR_NOT_OPEN;
}
const auto g_camera = fxm::get<camera_thread>();
if (!g_camera)
{
return CELL_CAMERA_ERROR_NOT_INIT;
}
semaphore_lock lock(g_camera->mutex);
if (!g_camera->is_open)
{
return CELL_CAMERA_ERROR_NOT_OPEN;
}
if (!g_camera->is_attached)
{
return CELL_CAMERA_ERROR_DEVICE_NOT_FOUND;
}
g_camera->timer.Start();
g_camera->is_streaming = true;
@ -709,9 +988,23 @@ s32 cellCameraRead(s32 dev_num, vm::ptr<u32> frame_num, vm::ptr<u32> bytes_read)
{
cellCamera.todo("cellCameraRead(dev_num=%d, frame_num=*0x%x, bytes_read=*0x%x)", dev_num, frame_num, bytes_read);
if (g_cfg.io.camera == camera_handler::null)
vm::ptr<CellCameraReadEx> read_ex = vm::make_var<CellCameraReadEx>({});
s32 res = cellCameraReadEx(dev_num, read_ex);
if (res != CELL_OK)
{
return CELL_CAMERA_ERROR_NOT_OPEN;
return res;
}
if (frame_num)
{
*frame_num = read_ex->frame;
}
if (bytes_read)
{
*bytes_read = read_ex->bytesread;
}
return CELL_OK;
@ -733,16 +1026,40 @@ s32 cellCameraReadEx(s32 dev_num, vm::ptr<CellCameraReadEx> read)
return CELL_CAMERA_ERROR_NOT_INIT;
}
if (!check_dev_num(dev_num))
{
return CELL_CAMERA_ERROR_PARAM;
}
semaphore_lock lock(g_camera->mutex);
read->timestamp = g_camera->timer.GetElapsedTimeInMicroSec();
read->frame = g_camera->frame_num;
read->bytesread = g_camera->is_streaming ?
get_video_buffer_size(g_camera->info) : 0;
if (!g_camera->is_open)
{
return CELL_CAMERA_ERROR_NOT_OPEN;
}
auto shared_data = fxm::get_always<gem_camera_shared>();
if (!g_camera->is_attached)
{
return CELL_CAMERA_ERROR_DEVICE_NOT_FOUND;
}
shared_data->frame_timestamp.exchange(read->timestamp);
if (!g_camera->is_streaming)
{
return CELL_CAMERA_ERROR_NOT_STARTED;
}
// can call cellCameraReset() and cellCameraStop() in some cases
if (read) // NULL returns CELL_OK
{
read->timestamp = g_camera->timer.GetElapsedTimeInMicroSec();
read->frame = g_camera->frame_num;
read->bytesread = g_camera->is_streaming ? get_video_buffer_size(g_camera->info) : 0;
auto shared_data = fxm::get_always<gem_camera_shared>();
shared_data->frame_timestamp.exchange(read->timestamp);
}
return CELL_OK;
}
@ -751,13 +1068,6 @@ s32 cellCameraReadComplete(s32 dev_num, u32 bufnum, u32 arg2)
{
cellCamera.todo("cellCameraReadComplete(dev_num=%d, bufnum=%d, arg2=%d)", dev_num, bufnum, arg2);
const auto g_camera = fxm::get<camera_thread>();
if (!g_camera)
{
return CELL_CAMERA_ERROR_NOT_INIT;
}
return cellCameraSetAttribute(dev_num, CELL_CAMERA_READFINISH, bufnum, arg2);
}
@ -765,6 +1075,11 @@ s32 cellCameraStop(s32 dev_num)
{
cellCamera.todo("cellCameraStop(dev_num=%d)", dev_num);
if (!check_dev_num(dev_num))
{
return CELL_CAMERA_ERROR_PARAM;
}
if (g_cfg.io.camera == camera_handler::null)
{
return CELL_CAMERA_ERROR_NOT_OPEN;
@ -779,6 +1094,21 @@ s32 cellCameraStop(s32 dev_num)
semaphore_lock lock(g_camera->mutex);
if (!g_camera->is_open)
{
return CELL_CAMERA_ERROR_NOT_OPEN;
}
if (!g_camera->is_attached)
{
return CELL_CAMERA_ERROR_DEVICE_NOT_FOUND;
}
if (!g_camera->is_streaming)
{
return CELL_CAMERA_ERROR_NOT_STARTED;
}
g_camera->is_streaming = false;
g_camera->timer.Stop();
@ -789,6 +1119,11 @@ s32 cellCameraSetNotifyEventQueue(u64 key)
{
cellCamera.todo("cellCameraSetNotifyEventQueue(key=0x%x)", key);
if (g_cfg.io.camera == camera_handler::null)
{
return CELL_OK;
}
if (!add_queue_and_send_attach(key, 0, 0))
{
return CELL_CAMERA_ERROR_NOT_INIT;
@ -801,6 +1136,11 @@ s32 cellCameraRemoveNotifyEventQueue(u64 key)
{
cellCamera.todo("cellCameraRemoveNotifyEventQueue(key=0x%x)", key);
if (g_cfg.io.camera == camera_handler::null)
{
return CELL_OK;
}
if (!remove_queue(key))
{
return CELL_CAMERA_ERROR_NOT_INIT;
@ -830,17 +1170,7 @@ s32 cellCameraRemoveNotifyEventQueue2(u64 key)
{
cellCamera.todo("cellCameraRemoveNotifyEventQueue2(key=0x%x)", key);
if (g_cfg.io.camera == camera_handler::null)
{
return CELL_OK;
}
if (!remove_queue(key))
{
return CELL_CAMERA_ERROR_NOT_INIT;
}
return CELL_OK;
return cellCameraRemoveNotifyEventQueue(key);
}
DECLARE(ppu_module_manager::cellCamera)("cellCamera", []()
@ -910,15 +1240,7 @@ void camera_thread::on_task()
u64 data2{ 0 };
u64 data3{ 0 };
switch (read_mode.load())
{
case CELL_CAMERA_READ_FUNCCALL:
{
data2 = 0; // device id (always 0)
data3 = 0; // unused
break;
}
case CELL_CAMERA_READ_DIRECT:
if (read_mode.load() == CELL_CAMERA_READ_DIRECT)
{
const u64 image_data_size = static_cast<u64>(info.bytesize);
const u64 buffer_number = 0;
@ -926,13 +1248,11 @@ void camera_thread::on_task()
data2 = image_data_size << 32 | buffer_number << 16 | camera_id;
data3 = timer.GetElapsedTimeInMicroSec(); // timestamp
break;
}
default:
else // CELL_CAMERA_READ_FUNCCALL, also default
{
cellCamera.error("Unknown read mode set: %d. This should never happen.", read_mode.load());
return;
}
data2 = 0; // device id (always 0)
data3 = 0; // unused
}
const auto send_status = queue->send(evt_data.source, CELL_CAMERA_FRAME_UPDATE, data2, data3);

View file

@ -310,6 +310,19 @@ enum CellCameraAttribute : s32
CELL_CAMERA_ATTRIBUTE_UNKNOWN = 500,
};
// Request codes
enum
{
SET_CUR = 0x01,
GET_CUR = 0x81,
GET_MIN = 0x82,
GET_MAX = 0x83,
GET_RES = 0x84,
GET_LEN = 0x85,
GET_INFO = 0x86,
GET_DEF = 0x87,
};
struct CellCameraInfoEx
{
be_t<s32> format; // CellCameraFormat