| 574 | } |
| 575 | |
| 576 | error_code cellCameraOpenEx(s32 dev_num, vm::ptr<CellCameraInfoEx> info) |
| 577 | { |
| 578 | cellCamera.todo("cellCameraOpenEx(dev_num=%d, info=*0x%x)", dev_num, info); |
| 579 | |
| 580 | // This function has a very weird order of checking for errors |
| 581 | |
| 582 | if (!info) |
| 583 | { |
| 584 | return CELL_CAMERA_ERROR_PARAM; |
| 585 | } |
| 586 | |
| 587 | if (g_cfg.io.camera == camera_handler::null) |
| 588 | { |
| 589 | return not_an_error(CELL_CAMERA_ERROR_DEVICE_NOT_FOUND); |
| 590 | } |
| 591 | |
| 592 | if (auto res = cellCameraSetAttribute(dev_num, CELL_CAMERA_READMODE, info->read_mode, 0)) |
| 593 | { |
| 594 | return res; |
| 595 | } |
| 596 | |
| 597 | if (info->read_mode == CELL_CAMERA_READ_DIRECT) |
| 598 | { |
| 599 | // Note: arg1 is the return value of previous SetAttribute |
| 600 | if (auto res = cellCameraSetAttribute(dev_num, CELL_CAMERA_GAMEPID, 0, 0)) |
| 601 | { |
| 602 | return res; |
| 603 | } |
| 604 | } |
| 605 | |
| 606 | if (!check_dev_num(dev_num)) |
| 607 | { |
| 608 | return CELL_CAMERA_ERROR_PARAM; |
| 609 | } |
| 610 | |
| 611 | auto& g_camera = g_fxo->get<camera_thread>(); |
| 612 | |
| 613 | if (g_camera.is_open) |
| 614 | { |
| 615 | return CELL_CAMERA_ERROR_ALREADY_OPEN; |
| 616 | } |
| 617 | |
| 618 | if (auto res = check_camera_info(*info)) |
| 619 | { |
| 620 | return res; |
| 621 | } |
| 622 | |
| 623 | // calls cellCameraGetAttribute(dev_num, CELL_CAMERA_PBUFFER) at some point |
| 624 | |
| 625 | const auto vbuf_size = get_video_buffer_size(*info); |
| 626 | |
| 627 | std::lock_guard lock(g_camera.mutex); |
| 628 | |
| 629 | // TODO: find out if the buffers are also checked for nullptr |
| 630 | if (info->read_mode == CELL_CAMERA_READ_DIRECT) |
| 631 | { |
| 632 | info->pbuf[0] = vm::cast(vm::alloc(vbuf_size, vm::main)); |
| 633 | info->pbuf[1] = vm::cast(vm::alloc(vbuf_size, vm::main)); |
nothing calls this directly
no test coverage detected