diff options
Diffstat (limited to '')
-rw-r--r-- | src/core/hle/service/cam/cam.cpp | 1106 | ||||
-rw-r--r-- | src/core/hle/service/cam/cam.h | 686 | ||||
-rw-r--r-- | src/core/hle/service/cam/cam_c.cpp | 18 | ||||
-rw-r--r-- | src/core/hle/service/cam/cam_c.h | 22 | ||||
-rw-r--r-- | src/core/hle/service/cam/cam_q.cpp | 18 | ||||
-rw-r--r-- | src/core/hle/service/cam/cam_q.h | 22 | ||||
-rw-r--r-- | src/core/hle/service/cam/cam_s.cpp | 18 | ||||
-rw-r--r-- | src/core/hle/service/cam/cam_s.h | 22 | ||||
-rw-r--r-- | src/core/hle/service/cam/cam_u.cpp | 81 | ||||
-rw-r--r-- | src/core/hle/service/cam/cam_u.h | 22 |
10 files changed, 0 insertions, 2015 deletions
diff --git a/src/core/hle/service/cam/cam.cpp b/src/core/hle/service/cam/cam.cpp deleted file mode 100644 index 8172edae8..000000000 --- a/src/core/hle/service/cam/cam.cpp +++ /dev/null @@ -1,1106 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include <algorithm> -#include <array> -#include <future> -#include <memory> -#include <vector> -#include "common/bit_set.h" -#include "common/logging/log.h" -#include "core/core_timing.h" -#include "core/frontend/camera/factory.h" -#include "core/hle/ipc.h" -#include "core/hle/ipc_helpers.h" -#include "core/hle/kernel/event.h" -#include "core/hle/result.h" -#include "core/hle/service/cam/cam.h" -#include "core/hle/service/cam/cam_c.h" -#include "core/hle/service/cam/cam_q.h" -#include "core/hle/service/cam/cam_s.h" -#include "core/hle/service/cam/cam_u.h" -#include "core/hle/service/service.h" -#include "core/memory.h" -#include "core/settings.h" - -namespace Service { -namespace CAM { - -namespace { - -struct ContextConfig { - Flip flip; - Effect effect; - OutputFormat format; - Resolution resolution; -}; - -struct CameraConfig { - std::unique_ptr<Camera::CameraInterface> impl; - std::array<ContextConfig, 2> contexts; - int current_context; - FrameRate frame_rate; -}; - -struct PortConfig { - int camera_id; - - bool is_active; // set when the port is activated by an Activate call. - bool is_pending_receiving; // set if SetReceiving is called when is_busy = false. When - // StartCapture is called then, this will trigger a receiving - // process and reset itself. - bool is_busy; // set when StartCapture is called and reset when StopCapture is called. - bool is_receiving; // set when there is an ongoing receiving process. - - bool is_trimming; - u16 x0; // x-coordinate of starting position for trimming - u16 y0; // y-coordinate of starting position for trimming - u16 x1; // x-coordinate of ending position for trimming - u16 y1; // y-coordinate of ending position for trimming - - u16 transfer_bytes; - - Kernel::SharedPtr<Kernel::Event> completion_event; - Kernel::SharedPtr<Kernel::Event> buffer_error_interrupt_event; - Kernel::SharedPtr<Kernel::Event> vsync_interrupt_event; - - std::future<std::vector<u16>> capture_result; // will hold the received frame. - VAddr dest; // the destination address of a receiving process - u32 dest_size; // the destination size of a receiving process - - void Clear() { - completion_event->Clear(); - buffer_error_interrupt_event->Clear(); - vsync_interrupt_event->Clear(); - is_receiving = false; - is_active = false; - is_pending_receiving = false; - is_busy = false; - is_trimming = false; - x0 = 0; - y0 = 0; - x1 = 0; - y1 = 0; - transfer_bytes = 256; - } -}; - -// built-in resolution parameters -constexpr std::array<Resolution, 8> PRESET_RESOLUTION{{ - {640, 480, 0, 0, 639, 479}, // VGA - {320, 240, 0, 0, 639, 479}, // QVGA - {160, 120, 0, 0, 639, 479}, // QQVGA - {352, 288, 26, 0, 613, 479}, // CIF - {176, 144, 26, 0, 613, 479}, // QCIF - {256, 192, 0, 0, 639, 479}, // DS_LCD - {512, 384, 0, 0, 639, 479}, // DS_LCDx4 - {400, 240, 0, 48, 639, 431}, // CTR_TOP_LCD -}}; - -// latency in ms for each frame rate option -constexpr std::array<int, 13> LATENCY_BY_FRAME_RATE{{ - 67, // Rate_15 - 67, // Rate_15_To_5 - 67, // Rate_15_To_2 - 100, // Rate_10 - 118, // Rate_8_5 - 200, // Rate_5 - 50, // Rate_20 - 50, // Rate_20_To_5 - 33, // Rate_30 - 33, // Rate_30_To_5 - 67, // Rate_15_To_10 - 50, // Rate_20_To_10 - 33, // Rate_30_To_10 -}}; - -std::array<CameraConfig, NumCameras> cameras; -std::array<PortConfig, 2> ports; -int completion_event_callback; - -const ResultCode ERROR_INVALID_ENUM_VALUE(ErrorDescription::InvalidEnumValue, ErrorModule::CAM, - ErrorSummary::InvalidArgument, ErrorLevel::Usage); -const ResultCode ERROR_OUT_OF_RANGE(ErrorDescription::OutOfRange, ErrorModule::CAM, - ErrorSummary::InvalidArgument, ErrorLevel::Usage); - -void CompletionEventCallBack(u64 port_id, int) { - PortConfig& port = ports[port_id]; - const CameraConfig& camera = cameras[port.camera_id]; - const auto buffer = port.capture_result.get(); - - if (port.is_trimming) { - u32 trim_width; - u32 trim_height; - const int original_width = camera.contexts[camera.current_context].resolution.width; - const int original_height = camera.contexts[camera.current_context].resolution.height; - if (port.x1 <= port.x0 || port.y1 <= port.y0 || port.x1 > original_width || - port.y1 > original_height) { - LOG_ERROR(Service_CAM, "Invalid trimming coordinates x0=%u, y0=%u, x1=%u, y1=%u", - port.x0, port.y0, port.x1, port.y1); - trim_width = 0; - trim_height = 0; - } else { - trim_width = port.x1 - port.x0; - trim_height = port.y1 - port.y0; - } - - u32 trim_size = (port.x1 - port.x0) * (port.y1 - port.y0) * 2; - if (port.dest_size != trim_size) { - LOG_ERROR(Service_CAM, "The destination size (%u) doesn't match the source (%u)!", - port.dest_size, trim_size); - } - - const u32 src_offset = port.y0 * original_width + port.x0; - const u16* src_ptr = buffer.data() + src_offset; - // Note: src_size_left is int because it can be negative if the buffer size doesn't match. - int src_size_left = static_cast<int>((buffer.size() - src_offset) * sizeof(u16)); - VAddr dest_ptr = port.dest; - // Note: dest_size_left and line_bytes are int to match the type of src_size_left. - int dest_size_left = static_cast<int>(port.dest_size); - const int line_bytes = static_cast<int>(trim_width * sizeof(u16)); - - for (u32 y = 0; y < trim_height; ++y) { - int copy_length = std::min({line_bytes, dest_size_left, src_size_left}); - if (copy_length <= 0) { - break; - } - Memory::WriteBlock(dest_ptr, src_ptr, copy_length); - dest_ptr += copy_length; - dest_size_left -= copy_length; - src_ptr += original_width; - src_size_left -= original_width * sizeof(u16); - } - } else { - std::size_t buffer_size = buffer.size() * sizeof(u16); - if (port.dest_size != buffer_size) { - LOG_ERROR(Service_CAM, "The destination size (%u) doesn't match the source (%zu)!", - port.dest_size, buffer_size); - } - Memory::WriteBlock(port.dest, buffer.data(), std::min<size_t>(port.dest_size, buffer_size)); - } - - port.is_receiving = false; - port.completion_event->Signal(); -} - -// Starts a receiving process on the specified port. This can only be called when is_busy = true and -// is_receiving = false. -void StartReceiving(int port_id) { - PortConfig& port = ports[port_id]; - port.is_receiving = true; - - // launches a capture task asynchronously - const CameraConfig& camera = cameras[port.camera_id]; - port.capture_result = - std::async(std::launch::async, &Camera::CameraInterface::ReceiveFrame, camera.impl.get()); - - // schedules a completion event according to the frame rate. The event will block on the - // capture task if it is not finished within the expected time - CoreTiming::ScheduleEvent( - msToCycles(LATENCY_BY_FRAME_RATE[static_cast<int>(camera.frame_rate)]), - completion_event_callback, port_id); -} - -// Cancels any ongoing receiving processes at the specified port. This is used by functions that -// stop capturing. -// TODO: what is the exact behaviour on real 3DS when stopping capture during an ongoing process? -// Will the completion event still be signaled? -void CancelReceiving(int port_id) { - if (!ports[port_id].is_receiving) - return; - LOG_WARNING(Service_CAM, "tries to cancel an ongoing receiving process."); - CoreTiming::UnscheduleEvent(completion_event_callback, port_id); - ports[port_id].capture_result.wait(); - ports[port_id].is_receiving = false; -} - -// Activates the specified port with the specfied camera. -static void ActivatePort(int port_id, int camera_id) { - if (ports[port_id].is_busy && ports[port_id].camera_id != camera_id) { - CancelReceiving(port_id); - cameras[ports[port_id].camera_id].impl->StopCapture(); - ports[port_id].is_busy = false; - } - ports[port_id].is_active = true; - ports[port_id].camera_id = camera_id; -} - -template <int max_index> -class CommandParamBitSet : public BitSet8 { -public: - explicit CommandParamBitSet(u8 command_param) : BitSet8(command_param) {} - - bool IsValid() const { - return m_val < (1 << max_index); - } - - bool IsSingle() const { - return IsValid() && Count() == 1; - } -}; - -using PortSet = CommandParamBitSet<2>; -using ContextSet = CommandParamBitSet<2>; -using CameraSet = CommandParamBitSet<3>; - -} // namespace - -void StartCapture(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x01, 1, 0); - const PortSet port_select(rp.Pop<u8>()); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - - if (port_select.IsValid()) { - for (int i : port_select) { - if (!ports[i].is_busy) { - if (!ports[i].is_active) { - // This doesn't return an error, but seems to put the camera in an undefined - // state - LOG_ERROR(Service_CAM, "port %u hasn't been activated", i); - } else { - cameras[ports[i].camera_id].impl->StartCapture(); - ports[i].is_busy = true; - if (ports[i].is_pending_receiving) { - ports[i].is_pending_receiving = false; - StartReceiving(i); - } - } - } else { - LOG_WARNING(Service_CAM, "port %u already started", i); - } - } - rb.Push(RESULT_SUCCESS); - } else { - LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); - rb.Push(ERROR_INVALID_ENUM_VALUE); - } - - LOG_DEBUG(Service_CAM, "called, port_select=%u", port_select.m_val); -} - -void StopCapture(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x02, 1, 0); - const PortSet port_select(rp.Pop<u8>()); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - - if (port_select.IsValid()) { - for (int i : port_select) { - if (ports[i].is_busy) { - CancelReceiving(i); - cameras[ports[i].camera_id].impl->StopCapture(); - ports[i].is_busy = false; - } else { - LOG_WARNING(Service_CAM, "port %u already stopped", i); - } - } - rb.Push(RESULT_SUCCESS); - } else { - LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); - rb.Push(ERROR_INVALID_ENUM_VALUE); - } - - LOG_DEBUG(Service_CAM, "called, port_select=%u", port_select.m_val); -} - -void IsBusy(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x03, 1, 0); - const PortSet port_select(rp.Pop<u8>()); - - IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); - - if (port_select.IsValid()) { - bool is_busy = true; - // Note: the behaviour on no or both ports selected are verified against real 3DS. - for (int i : port_select) { - is_busy &= ports[i].is_busy; - } - rb.Push(RESULT_SUCCESS); - rb.Push(is_busy); - } else { - LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); - rb.Push(ERROR_INVALID_ENUM_VALUE); - rb.Skip(1, false); - } - - LOG_DEBUG(Service_CAM, "called, port_select=%u", port_select.m_val); -} - -void ClearBuffer(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x04, 1, 0); - const PortSet port_select(rp.Pop<u8>()); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - rb.Push(RESULT_SUCCESS); - - LOG_WARNING(Service_CAM, "(STUBBED) called, port_select=%u", port_select.m_val); -} - -void GetVsyncInterruptEvent(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x05, 1, 0); - const PortSet port_select(rp.Pop<u8>()); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); - if (port_select.IsSingle()) { - int port = *port_select.begin(); - rb.Push(RESULT_SUCCESS); - rb.PushCopyHandles( - Kernel::g_handle_table.Create(ports[port].vsync_interrupt_event).Unwrap()); - } else { - LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); - rb.Push(ERROR_INVALID_ENUM_VALUE); - rb.PushCopyHandles(0); - } - - LOG_WARNING(Service_CAM, "(STUBBED) called, port_select=%u", port_select.m_val); -} - -void GetBufferErrorInterruptEvent(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x06, 1, 0); - const PortSet port_select(rp.Pop<u8>()); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); - if (port_select.IsSingle()) { - int port = *port_select.begin(); - rb.Push(RESULT_SUCCESS); - rb.PushCopyHandles( - Kernel::g_handle_table.Create(ports[port].buffer_error_interrupt_event).Unwrap()); - } else { - LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); - rb.Push(ERROR_INVALID_ENUM_VALUE); - rb.PushCopyHandles(0); - } - - LOG_WARNING(Service_CAM, "(STUBBED) called, port_select=%u", port_select.m_val); -} - -void SetReceiving(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x07, 4, 2); - const VAddr dest = rp.Pop<u32>(); - const PortSet port_select(rp.Pop<u8>()); - const u32 image_size = rp.Pop<u32>(); - const u16 trans_unit = rp.Pop<u16>(); - rp.PopHandle(); // Handle to destination process. not used - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); - if (port_select.IsSingle()) { - int port_id = *port_select.begin(); - PortConfig& port = ports[port_id]; - CancelReceiving(port_id); - port.completion_event->Clear(); - port.dest = dest; - port.dest_size = image_size; - - if (port.is_busy) { - StartReceiving(port_id); - } else { - port.is_pending_receiving = true; - } - - rb.Push(RESULT_SUCCESS); - rb.PushCopyHandles(Kernel::g_handle_table.Create(port.completion_event).Unwrap()); - } else { - LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); - rb.Push(ERROR_INVALID_ENUM_VALUE); - rb.PushCopyHandles(0); - } - - LOG_DEBUG(Service_CAM, "called, addr=0x%X, port_select=%u, image_size=%u, trans_unit=%u", dest, - port_select.m_val, image_size, trans_unit); -} - -void IsFinishedReceiving(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x08, 1, 0); - const PortSet port_select(rp.Pop<u8>()); - - IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); - if (port_select.IsSingle()) { - int port = *port_select.begin(); - bool is_busy = ports[port].is_receiving || ports[port].is_pending_receiving; - rb.Push(RESULT_SUCCESS); - rb.Push(!is_busy); - } else { - LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); - rb.Push(ERROR_INVALID_ENUM_VALUE); - rb.Skip(1, false); - } - - LOG_DEBUG(Service_CAM, "called, port_select=%u", port_select.m_val); -} - -void SetTransferLines(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x09, 4, 0); - const PortSet port_select(rp.Pop<u8>()); - const u16 transfer_lines = rp.Pop<u16>(); - const u16 width = rp.Pop<u16>(); - const u16 height = rp.Pop<u16>(); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - if (port_select.IsValid()) { - for (int i : port_select) { - ports[i].transfer_bytes = transfer_lines * width * 2; - } - rb.Push(RESULT_SUCCESS); - } else { - LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); - rb.Push(ERROR_INVALID_ENUM_VALUE); - } - - LOG_WARNING(Service_CAM, "(STUBBED) called, port_select=%u, lines=%u, width=%u, height=%u", - port_select.m_val, transfer_lines, width, height); -} - -void GetMaxLines(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x0A, 2, 0); - const u16 width = rp.Pop<u16>(); - const u16 height = rp.Pop<u16>(); - - IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); - - // Note: the result of the algorithm below are hwtested with width < 640 and with height < 480 - constexpr u32 MIN_TRANSFER_UNIT = 256; - constexpr u32 MAX_BUFFER_SIZE = 2560; - if (width * height * 2 % MIN_TRANSFER_UNIT != 0) { - rb.Push(ERROR_OUT_OF_RANGE); - rb.Skip(1, false); - } else { - u32 lines = MAX_BUFFER_SIZE / width; - if (lines > height) { - lines = height; - } - ResultCode result = RESULT_SUCCESS; - while (height % lines != 0 || (lines * width * 2 % MIN_TRANSFER_UNIT != 0)) { - --lines; - if (lines == 0) { - result = ERROR_OUT_OF_RANGE; - break; - } - } - rb.Push(result); - rb.Push(lines); - } - - LOG_DEBUG(Service_CAM, "called, width=%u, height=%u", width, height); -} - -void SetTransferBytes(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x0B, 4, 0); - const PortSet port_select(rp.Pop<u8>()); - const u16 transfer_bytes = rp.Pop<u16>(); - const u16 width = rp.Pop<u16>(); - const u16 height = rp.Pop<u16>(); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - if (port_select.IsValid()) { - for (int i : port_select) { - ports[i].transfer_bytes = transfer_bytes; - } - rb.Push(RESULT_SUCCESS); - } else { - LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); - rb.Push(ERROR_INVALID_ENUM_VALUE); - } - - LOG_WARNING(Service_CAM, "(STUBBED)called, port_select=%u, bytes=%u, width=%u, height=%u", - port_select.m_val, transfer_bytes, width, height); -} - -void GetTransferBytes(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x0C, 1, 0); - const PortSet port_select(rp.Pop<u8>()); - - IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); - if (port_select.IsSingle()) { - int port = *port_select.begin(); - rb.Push(RESULT_SUCCESS); - rb.Push(ports[port].transfer_bytes); - } else { - LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); - rb.Push(ERROR_INVALID_ENUM_VALUE); - rb.Skip(1, false); - } - - LOG_WARNING(Service_CAM, "(STUBBED)called, port_select=%u", port_select.m_val); -} - -void GetMaxBytes(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x0D, 2, 0); - const u16 width = rp.Pop<u16>(); - const u16 height = rp.Pop<u16>(); - - IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); - - // Note: the result of the algorithm below are hwtested with width < 640 and with height < 480 - constexpr u32 MIN_TRANSFER_UNIT = 256; - constexpr u32 MAX_BUFFER_SIZE = 2560; - if (width * height * 2 % MIN_TRANSFER_UNIT != 0) { - rb.Push(ERROR_OUT_OF_RANGE); - rb.Skip(1, false); - } else { - u32 bytes = MAX_BUFFER_SIZE; - - while (width * height * 2 % bytes != 0) { - bytes -= MIN_TRANSFER_UNIT; - } - - rb.Push(RESULT_SUCCESS); - rb.Push(bytes); - } - - LOG_DEBUG(Service_CAM, "called, width=%u, height=%u", width, height); -} - -void SetTrimming(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x0E, 2, 0); - const PortSet port_select(rp.Pop<u8>()); - const bool trim = rp.Pop<bool>(); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - if (port_select.IsValid()) { - for (int i : port_select) { - ports[i].is_trimming = trim; - } - rb.Push(RESULT_SUCCESS); - } else { - LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); - rb.Push(ERROR_INVALID_ENUM_VALUE); - } - - LOG_DEBUG(Service_CAM, "called, port_select=%u, trim=%d", port_select.m_val, trim); -} - -void IsTrimming(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x0F, 1, 0); - const PortSet port_select(rp.Pop<u8>()); - - IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); - if (port_select.IsSingle()) { - int port = *port_select.begin(); - rb.Push(RESULT_SUCCESS); - rb.Push(ports[port].is_trimming); - } else { - LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); - rb.Push(ERROR_INVALID_ENUM_VALUE); - rb.Skip(1, false); - } - - LOG_DEBUG(Service_CAM, "called, port_select=%u", port_select.m_val); -} - -void SetTrimmingParams(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x10, 5, 0); - const PortSet port_select(rp.Pop<u8>()); - const u16 x0 = rp.Pop<u16>(); - const u16 y0 = rp.Pop<u16>(); - const u16 x1 = rp.Pop<u16>(); - const u16 y1 = rp.Pop<u16>(); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - if (port_select.IsValid()) { - for (int i : port_select) { - ports[i].x0 = x0; - ports[i].y0 = y0; - ports[i].x1 = x1; - ports[i].y1 = y1; - } - rb.Push(RESULT_SUCCESS); - } else { - LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); - rb.Push(ERROR_INVALID_ENUM_VALUE); - } - - LOG_DEBUG(Service_CAM, "called, port_select=%u, x0=%u, y0=%u, x1=%u, y1=%u", port_select.m_val, - x0, y0, x1, y1); -} - -void GetTrimmingParams(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x11, 1, 0); - const PortSet port_select(rp.Pop<u8>()); - - IPC::RequestBuilder rb = rp.MakeBuilder(5, 0); - if (port_select.IsSingle()) { - int port = *port_select.begin(); - rb.Push(RESULT_SUCCESS); - rb.Push(ports[port].x0); - rb.Push(ports[port].y0); - rb.Push(ports[port].x1); - rb.Push(ports[port].y1); - } else { - LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); - rb.Push(ERROR_INVALID_ENUM_VALUE); - rb.Skip(4, false); - } - - LOG_DEBUG(Service_CAM, "called, port_select=%u", port_select.m_val); -} - -void SetTrimmingParamsCenter(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x12, 5, 0); - const PortSet port_select(rp.Pop<u8>()); - const u16 trim_w = rp.Pop<u16>(); - const u16 trim_h = rp.Pop<u16>(); - const u16 cam_w = rp.Pop<u16>(); - const u16 cam_h = rp.Pop<u16>(); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - if (port_select.IsValid()) { - for (int i : port_select) { - ports[i].x0 = (cam_w - trim_w) / 2; - ports[i].y0 = (cam_h - trim_h) / 2; - ports[i].x1 = ports[i].x0 + trim_w; - ports[i].y1 = ports[i].y0 + trim_h; - } - rb.Push(RESULT_SUCCESS); - } else { - LOG_ERROR(Service_CAM, "invalid port_select=%u", port_select.m_val); - rb.Push(ERROR_INVALID_ENUM_VALUE); - } - - LOG_DEBUG(Service_CAM, "called, port_select=%u, trim_w=%u, trim_h=%u, cam_w=%u, cam_h=%u", - port_select.m_val, trim_w, trim_h, cam_w, cam_h); -} - -void Activate(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x13, 1, 0); - const CameraSet camera_select(rp.Pop<u8>()); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - if (camera_select.IsValid()) { - if (camera_select.m_val == 0) { // deactive all - for (int i = 0; i < 2; ++i) { - if (ports[i].is_busy) { - CancelReceiving(i); - cameras[ports[i].camera_id].impl->StopCapture(); - ports[i].is_busy = false; - } - ports[i].is_active = false; - } - rb.Push(RESULT_SUCCESS); - } else if (camera_select[0] && camera_select[1]) { - LOG_ERROR(Service_CAM, "camera 0 and 1 can't be both activated"); - rb.Push(ERROR_INVALID_ENUM_VALUE); - } else { - if (camera_select[0]) { - ActivatePort(0, 0); - } else if (camera_select[1]) { - ActivatePort(0, 1); - } - - if (camera_select[2]) { - ActivatePort(1, 2); - } - rb.Push(RESULT_SUCCESS); - } - } else { - LOG_ERROR(Service_CAM, "invalid camera_select=%u", camera_select.m_val); - rb.Push(ERROR_INVALID_ENUM_VALUE); - } - - LOG_DEBUG(Service_CAM, "called, camera_select=%u", camera_select.m_val); -} - -void SwitchContext(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x14, 2, 0); - const CameraSet camera_select(rp.Pop<u8>()); - const ContextSet context_select(rp.Pop<u8>()); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - if (camera_select.IsValid() && context_select.IsSingle()) { - int context = *context_select.begin(); - for (int camera : camera_select) { - cameras[camera].current_context = context; - const ContextConfig& context_config = cameras[camera].contexts[context]; - cameras[camera].impl->SetFlip(context_config.flip); - cameras[camera].impl->SetEffect(context_config.effect); - cameras[camera].impl->SetFormat(context_config.format); - cameras[camera].impl->SetResolution(context_config.resolution); - } - rb.Push(RESULT_SUCCESS); - } else { - LOG_ERROR(Service_CAM, "invalid camera_select=%u, context_select=%u", camera_select.m_val, - context_select.m_val); - rb.Push(ERROR_INVALID_ENUM_VALUE); - } - - LOG_DEBUG(Service_CAM, "called, camera_select=%u, context_select=%u", camera_select.m_val, - context_select.m_val); -} - -void FlipImage(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x1D, 3, 0); - const CameraSet camera_select(rp.Pop<u8>()); - const Flip flip = static_cast<Flip>(rp.Pop<u8>()); - const ContextSet context_select(rp.Pop<u8>()); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - if (camera_select.IsValid() && context_select.IsValid()) { - for (int camera : camera_select) { - for (int context : context_select) { - cameras[camera].contexts[context].flip = flip; - if (cameras[camera].current_context == context) { - cameras[camera].impl->SetFlip(flip); - } - } - } - rb.Push(RESULT_SUCCESS); - } else { - LOG_ERROR(Service_CAM, "invalid camera_select=%u, context_select=%u", camera_select.m_val, - context_select.m_val); - rb.Push(ERROR_INVALID_ENUM_VALUE); - } - - LOG_DEBUG(Service_CAM, "called, camera_select=%u, flip=%d, context_select=%u", - camera_select.m_val, static_cast<int>(flip), context_select.m_val); -} - -void SetDetailSize(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x1E, 8, 0); - const CameraSet camera_select(rp.Pop<u8>()); - Resolution resolution; - resolution.width = rp.Pop<u16>(); - resolution.height = rp.Pop<u16>(); - resolution.crop_x0 = rp.Pop<u16>(); - resolution.crop_y0 = rp.Pop<u16>(); - resolution.crop_x1 = rp.Pop<u16>(); - resolution.crop_y1 = rp.Pop<u16>(); - const ContextSet context_select(rp.Pop<u8>()); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - if (camera_select.IsValid() && context_select.IsValid()) { - for (int camera : camera_select) { - for (int context : context_select) { - cameras[camera].contexts[context].resolution = resolution; - if (cameras[camera].current_context == context) { - cameras[camera].impl->SetResolution(resolution); - } - } - } - rb.Push(RESULT_SUCCESS); - } else { - LOG_ERROR(Service_CAM, "invalid camera_select=%u, context_select=%u", camera_select.m_val, - context_select.m_val); - rb.Push(ERROR_INVALID_ENUM_VALUE); - } - - LOG_DEBUG(Service_CAM, "called, camera_select=%u, width=%u, height=%u, crop_x0=%u, crop_y0=%u, " - "crop_x1=%u, crop_y1=%u, context_select=%u", - camera_select.m_val, resolution.width, resolution.height, resolution.crop_x0, - resolution.crop_y0, resolution.crop_x1, resolution.crop_y1, context_select.m_val); -} - -void SetSize(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x1F, 3, 0); - const CameraSet camera_select(rp.Pop<u8>()); - const u8 size = rp.Pop<u8>(); - const ContextSet context_select(rp.Pop<u8>()); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - if (camera_select.IsValid() && context_select.IsValid()) { - for (int camera : camera_select) { - for (int context : context_select) { - cameras[camera].contexts[context].resolution = PRESET_RESOLUTION[size]; - if (cameras[camera].current_context == context) { - cameras[camera].impl->SetResolution(PRESET_RESOLUTION[size]); - } - } - } - rb.Push(RESULT_SUCCESS); - } else { - LOG_ERROR(Service_CAM, "invalid camera_select=%u, context_select=%u", camera_select.m_val, - context_select.m_val); - rb.Push(ERROR_INVALID_ENUM_VALUE); - } - - LOG_DEBUG(Service_CAM, "called, camera_select=%u, size=%u, context_select=%u", - camera_select.m_val, size, context_select.m_val); -} - -void SetFrameRate(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x20, 2, 0); - const CameraSet camera_select(rp.Pop<u8>()); - const FrameRate frame_rate = static_cast<FrameRate>(rp.Pop<u8>()); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - if (camera_select.IsValid()) { - for (int camera : camera_select) { - cameras[camera].frame_rate = frame_rate; - // TODO(wwylele): consider hinting the actual camera with the expected frame rate - } - rb.Push(RESULT_SUCCESS); - } else { - LOG_ERROR(Service_CAM, "invalid camera_select=%u", camera_select.m_val); - rb.Push(ERROR_INVALID_ENUM_VALUE); - } - - LOG_WARNING(Service_CAM, "(STUBBED) called, camera_select=%u, frame_rate=%d", - camera_select.m_val, static_cast<int>(frame_rate)); -} - -void SetEffect(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x22, 3, 0); - const CameraSet camera_select(rp.Pop<u8>()); - const Effect effect = static_cast<Effect>(rp.Pop<u8>()); - const ContextSet context_select(rp.Pop<u8>()); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - if (camera_select.IsValid() && context_select.IsValid()) { - for (int camera : camera_select) { - for (int context : context_select) { - cameras[camera].contexts[context].effect = effect; - if (cameras[camera].current_context == context) { - cameras[camera].impl->SetEffect(effect); - } - } - } - rb.Push(RESULT_SUCCESS); - } else { - LOG_ERROR(Service_CAM, "invalid camera_select=%u, context_select=%u", camera_select.m_val, - context_select.m_val); - rb.Push(ERROR_INVALID_ENUM_VALUE); - } - - LOG_DEBUG(Service_CAM, "called, camera_select=%u, effect=%d, context_select=%u", - camera_select.m_val, static_cast<int>(effect), context_select.m_val); -} - -void SetOutputFormat(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x25, 3, 0); - const CameraSet camera_select(rp.Pop<u8>()); - const OutputFormat format = static_cast<OutputFormat>(rp.Pop<u8>()); - const ContextSet context_select(rp.Pop<u8>()); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - if (camera_select.IsValid() && context_select.IsValid()) { - for (int camera : camera_select) { - for (int context : context_select) { - cameras[camera].contexts[context].format = format; - if (cameras[camera].current_context == context) { - cameras[camera].impl->SetFormat(format); - } - } - } - rb.Push(RESULT_SUCCESS); - } else { - LOG_ERROR(Service_CAM, "invalid camera_select=%u, context_select=%u", camera_select.m_val, - context_select.m_val); - rb.Push(ERROR_INVALID_ENUM_VALUE); - } - - LOG_DEBUG(Service_CAM, "called, camera_select=%u, format=%d, context_select=%u", - camera_select.m_val, static_cast<int>(format), context_select.m_val); -} - -void SynchronizeVsyncTiming(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x29, 2, 0); - const u8 camera_select1 = rp.Pop<u8>(); - const u8 camera_select2 = rp.Pop<u8>(); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - rb.Push(RESULT_SUCCESS); - - LOG_WARNING(Service_CAM, "(STUBBED) called, camera_select1=%u, camera_select2=%u", - camera_select1, camera_select2); -} - -void GetStereoCameraCalibrationData(Service::Interface* self) { - IPC::RequestBuilder rb = - IPC::RequestParser(Kernel::GetCommandBuffer(), 0x2B, 0, 0).MakeBuilder(17, 0); - - // Default values taken from yuriks' 3DS. Valid data is required here or games using the - // calibration get stuck in an infinite CPU loop. - StereoCameraCalibrationData data = {}; - data.isValidRotationXY = 0; - data.scale = 1.001776f; - data.rotationZ = 0.008322907f; - data.translationX = -87.70484f; - data.translationY = -7.640977f; - data.rotationX = 0.0f; - data.rotationY = 0.0f; - data.angleOfViewRight = 64.66875f; - data.angleOfViewLeft = 64.76067f; - data.distanceToChart = 250.0f; - data.distanceCameras = 35.0f; - data.imageWidth = 640; - data.imageHeight = 480; - - rb.Push(RESULT_SUCCESS); - rb.PushRaw(data); - - LOG_TRACE(Service_CAM, "called"); -} - -void SetPackageParameterWithoutContext(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x33, 11, 0); - - PackageParameterWithoutContext package; - rp.PopRaw(package); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - rb.Push(RESULT_SUCCESS); - - LOG_WARNING(Service_CAM, "(STUBBED) called"); -} - -template <typename PackageParameterType> -static ResultCode SetPackageParameter(const PackageParameterType& package) { - const CameraSet camera_select(package.camera_select); - const ContextSet context_select(package.context_select); - - if (camera_select.IsValid() && context_select.IsValid()) { - for (int camera_id : camera_select) { - CameraConfig& camera = cameras[camera_id]; - for (int context_id : context_select) { - ContextConfig& context = camera.contexts[context_id]; - context.effect = package.effect; - context.flip = package.flip; - context.resolution = package.GetResolution(); - if (context_id == camera.current_context) { - camera.impl->SetEffect(context.effect); - camera.impl->SetFlip(context.flip); - camera.impl->SetResolution(context.resolution); - } - } - } - return RESULT_SUCCESS; - } else { - LOG_ERROR(Service_CAM, "invalid camera_select=%u, context_select=%u", package.camera_select, - package.context_select); - return ERROR_INVALID_ENUM_VALUE; - } -} - -Resolution PackageParameterWithContext::GetResolution() const { - return PRESET_RESOLUTION[static_cast<int>(size)]; -} - -void SetPackageParameterWithContext(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x34, 5, 0); - - PackageParameterWithContext package; - rp.PopRaw(package); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - ResultCode result = SetPackageParameter(package); - rb.Push(result); - - LOG_DEBUG(Service_CAM, "called"); -} - -void SetPackageParameterWithContextDetail(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x35, 7, 0); - - PackageParameterWithContextDetail package; - rp.PopRaw(package); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - ResultCode result = SetPackageParameter(package); - rb.Push(result); - - LOG_DEBUG(Service_CAM, "called"); -} - -void GetSuitableY2rStandardCoefficient(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x36, 0, 0); - IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); - rb.Push(RESULT_SUCCESS); - rb.Push<u32>(0); - - LOG_WARNING(Service_CAM, "(STUBBED) called"); -} - -void PlayShutterSound(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x38, 1, 0); - u8 sound_id = rp.Pop<u8>(); - - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - rb.Push(RESULT_SUCCESS); - - LOG_WARNING(Service_CAM, "(STUBBED) called, sound_id=%d", sound_id); -} - -void DriverInitialize(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x39, 0, 0); - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - - for (int camera_id = 0; camera_id < NumCameras; ++camera_id) { - CameraConfig& camera = cameras[camera_id]; - camera.current_context = 0; - for (int context_id = 0; context_id < 2; ++context_id) { - // Note: the following default values are verified against real 3DS - ContextConfig& context = camera.contexts[context_id]; - context.flip = camera_id == 1 ? Flip::Horizontal : Flip::None; - context.effect = Effect::None; - context.format = OutputFormat::YUV422; - context.resolution = - context_id == 0 ? PRESET_RESOLUTION[5 /*DS_LCD*/] : PRESET_RESOLUTION[0 /*VGA*/]; - } - camera.impl = Camera::CreateCamera(Settings::values.camera_name[camera_id], - Settings::values.camera_config[camera_id]); - camera.impl->SetFlip(camera.contexts[0].flip); - camera.impl->SetEffect(camera.contexts[0].effect); - camera.impl->SetFormat(camera.contexts[0].format); - camera.impl->SetResolution(camera.contexts[0].resolution); - } - - for (PortConfig& port : ports) { - port.Clear(); - } - - rb.Push(RESULT_SUCCESS); - - LOG_DEBUG(Service_CAM, "called"); -} - -void DriverFinalize(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x3A, 0, 0); - IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); - - CancelReceiving(0); - CancelReceiving(1); - - for (CameraConfig& camera : cameras) { - camera.impl = nullptr; - } - - rb.Push(RESULT_SUCCESS); - - LOG_DEBUG(Service_CAM, "called"); -} - -void Init() { - using namespace Kernel; - - AddService(new CAM_C_Interface); - AddService(new CAM_Q_Interface); - AddService(new CAM_S_Interface); - AddService(new CAM_U_Interface); - - for (PortConfig& port : ports) { - port.completion_event = Event::Create(ResetType::Sticky, "CAM_U::completion_event"); - port.buffer_error_interrupt_event = - Event::Create(ResetType::OneShot, "CAM_U::buffer_error_interrupt_event"); - port.vsync_interrupt_event = - Event::Create(ResetType::OneShot, "CAM_U::vsync_interrupt_event"); - } - completion_event_callback = - CoreTiming::RegisterEvent("CAM_U::CompletionEventCallBack", CompletionEventCallBack); -} - -void Shutdown() { - CancelReceiving(0); - CancelReceiving(1); - for (PortConfig& port : ports) { - port.completion_event = nullptr; - port.buffer_error_interrupt_event = nullptr; - port.vsync_interrupt_event = nullptr; - } - for (CameraConfig& camera : cameras) { - camera.impl = nullptr; - } -} - -} // namespace CAM - -} // namespace Service diff --git a/src/core/hle/service/cam/cam.h b/src/core/hle/service/cam/cam.h deleted file mode 100644 index b6da721d8..000000000 --- a/src/core/hle/service/cam/cam.h +++ /dev/null @@ -1,686 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "common/common_funcs.h" -#include "common/common_types.h" -#include "common/swap.h" -#include "core/hle/kernel/kernel.h" -#include "core/hle/service/service.h" - -namespace Service { -namespace CAM { - -enum CameraIndex { - OuterRightCamera = 0, - InnerCamera = 1, - OuterLeftCamera = 2, - - NumCameras = 3, -}; - -enum class Effect : u8 { - None = 0, - Mono = 1, - Sepia = 2, - Negative = 3, - Negafilm = 4, - Sepia01 = 5, -}; - -enum class Flip : u8 { - None = 0, - Horizontal = 1, - Vertical = 2, - Reverse = 3, -}; - -enum class Size : u8 { - VGA = 0, - QVGA = 1, - QQVGA = 2, - CIF = 3, - QCIF = 4, - DS_LCD = 5, - DS_LCDx4 = 6, - CTR_TOP_LCD = 7, - CTR_BOTTOM_LCD = QVGA, -}; - -enum class FrameRate : u8 { - Rate_15 = 0, - Rate_15_To_5 = 1, - Rate_15_To_2 = 2, - Rate_10 = 3, - Rate_8_5 = 4, - Rate_5 = 5, - Rate_20 = 6, - Rate_20_To_5 = 7, - Rate_30 = 8, - Rate_30_To_5 = 9, - Rate_15_To_10 = 10, - Rate_20_To_10 = 11, - Rate_30_To_10 = 12, -}; - -enum class ShutterSoundType : u8 { - Normal = 0, - Movie = 1, - MovieEnd = 2, -}; - -enum class WhiteBalance : u8 { - BalanceAuto = 0, - Balance3200K = 1, - Balance4150K = 2, - Balance5200K = 3, - Balance6000K = 4, - Balance7000K = 5, - BalanceMax = 6, - BalanceNormal = BalanceAuto, - BalanceTungsten = Balance3200K, - BalanceWhiteFluorescentLight = Balance4150K, - BalanceDaylight = Balance5200K, - BalanceCloudy = Balance6000K, - BalanceHorizon = Balance6000K, - BalanceShade = Balance7000K, -}; - -enum class PhotoMode : u8 { - Normal = 0, - Portrait = 1, - Landscape = 2, - Nightview = 3, - Letter0 = 4, -}; - -enum class LensCorrection : u8 { - Off = 0, - On70 = 1, - On90 = 2, - Dark = Off, - Normal = On70, - Bright = On90, -}; - -enum class Contrast : u8 { - Pattern01 = 1, - Pattern02 = 2, - Pattern03 = 3, - Pattern04 = 4, - Pattern05 = 5, - Pattern06 = 6, - Pattern07 = 7, - Pattern08 = 8, - Pattern09 = 9, - Pattern10 = 10, - Pattern11 = 11, - Low = Pattern05, - Normal = Pattern06, - High = Pattern07, -}; - -enum class OutputFormat : u8 { - YUV422 = 0, - RGB565 = 1, -}; - -/// Stereo camera calibration data. -struct StereoCameraCalibrationData { - u8 isValidRotationXY; ///< Bool indicating whether the X and Y rotation data is valid. - INSERT_PADDING_BYTES(3); - float_le scale; ///< Scale to match the left camera image with the right. - float_le rotationZ; ///< Z axis rotation to match the left camera image with the right. - float_le translationX; ///< X axis translation to match the left camera image with the right. - float_le translationY; ///< Y axis translation to match the left camera image with the right. - float_le rotationX; ///< X axis rotation to match the left camera image with the right. - float_le rotationY; ///< Y axis rotation to match the left camera image with the right. - float_le angleOfViewRight; ///< Right camera angle of view. - float_le angleOfViewLeft; ///< Left camera angle of view. - float_le distanceToChart; ///< Distance between cameras and measurement chart. - float_le distanceCameras; ///< Distance between left and right cameras. - s16_le imageWidth; ///< Image width. - s16_le imageHeight; ///< Image height. - INSERT_PADDING_BYTES(16); -}; -static_assert(sizeof(StereoCameraCalibrationData) == 64, - "StereoCameraCalibrationData structure size is wrong"); - -/** - * Resolution parameters for the camera. - * The native resolution of 3DS camera is 640 * 480. The captured image will be cropped in the - * region [crop_x0, crop_x1] * [crop_y0, crop_y1], and then scaled to size width * height as the - * output image. Note that all cropping coordinates are inclusive. - */ -struct Resolution { - u16 width; - u16 height; - u16 crop_x0; - u16 crop_y0; - u16 crop_x1; - u16 crop_y1; -}; - -struct PackageParameterWithoutContext { - u8 camera_select; - s8 exposure; - WhiteBalance white_balance; - s8 sharpness; - bool auto_exposure; - bool auto_white_balance; - FrameRate frame_rate; - PhotoMode photo_mode; - Contrast contrast; - LensCorrection lens_correction; - bool noise_filter; - u8 padding; - s16 auto_exposure_window_x; - s16 auto_exposure_window_y; - s16 auto_exposure_window_width; - s16 auto_exposure_window_height; - s16 auto_white_balance_window_x; - s16 auto_white_balance_window_y; - s16 auto_white_balance_window_width; - s16 auto_white_balance_window_height; - INSERT_PADDING_WORDS(4); -}; - -static_assert(sizeof(PackageParameterWithoutContext) == 44, - "PackageParameterCameraWithoutContext structure size is wrong"); - -struct PackageParameterWithContext { - u8 camera_select; - u8 context_select; - Flip flip; - Effect effect; - Size size; - INSERT_PADDING_BYTES(3); - INSERT_PADDING_WORDS(3); - - Resolution GetResolution() const; -}; - -static_assert(sizeof(PackageParameterWithContext) == 20, - "PackageParameterWithContext structure size is wrong"); - -struct PackageParameterWithContextDetail { - u8 camera_select; - u8 context_select; - Flip flip; - Effect effect; - Resolution resolution; - INSERT_PADDING_WORDS(3); - - Resolution GetResolution() const { - return resolution; - } -}; - -static_assert(sizeof(PackageParameterWithContextDetail) == 28, - "PackageParameterWithContextDetail structure size is wrong"); - -/** - * Starts capturing at the selected port. - * Inputs: - * 0: 0x00010040 - * 1: u8 selected port - * Outputs: - * 0: 0x00010040 - * 1: ResultCode - */ -void StartCapture(Service::Interface* self); - -/** - * Stops capturing from the selected port. - * Inputs: - * 0: 0x00020040 - * 1: u8 selected port - * Outputs: - * 0: 0x00020040 - * 1: ResultCode - */ -void StopCapture(Service::Interface* self); - -/** - * Gets whether the selected port is currently capturing. - * Inputs: - * 0: 0x00030040 - * 1: u8 selected port - * Outputs: - * 0: 0x00030080 - * 1: ResultCode - * 2: 0 if not capturing, 1 if capturing - */ -void IsBusy(Service::Interface* self); - -/** - * Clears the buffer of selected ports. - * Inputs: - * 0: 0x00040040 - * 1: u8 selected port - * Outputs: - * 0: 0x00040040 - * 2: ResultCode - */ -void ClearBuffer(Service::Interface* self); - -/** - * Unknown - * Inputs: - * 0: 0x00050040 - * 1: u8 selected port - * Outputs: - * 0: 0x00050042 - * 1: ResultCode - * 2: Descriptor: Handle - * 3: Event handle - */ -void GetVsyncInterruptEvent(Service::Interface* self); - -/** - * Unknown - * Inputs: - * 0: 0x00060040 - * 1: u8 selected port - * Outputs: - * 0: 0x00060042 - * 1: ResultCode - * 2: Descriptor: Handle - * 3: Event handle - */ -void GetBufferErrorInterruptEvent(Service::Interface* self); - -/** - * Sets the target buffer to receive a frame of image data and starts the transfer. Each camera - * port has its own event to signal the end of the transfer. - * - * Inputs: - * 0: 0x00070102 - * 1: Destination address in calling process - * 2: u8 selected port - * 3: Image size (in bytes) - * 4: u16 Transfer unit size (in bytes) - * 5: Descriptor: Handle - * 6: Handle to destination process - * Outputs: - * 0: 0x00070042 - * 1: ResultCode - * 2: Descriptor: Handle - * 3: Handle to event signalled when transfer finishes - */ -void SetReceiving(Service::Interface* self); - -/** - * Gets whether the selected port finished receiving a frame. - * Inputs: - * 0: 0x00080040 - * 1: u8 selected port - * Outputs: - * 0: 0x00080080 - * 1: ResultCode - * 2: 0 if not finished, 1 if finished - */ -void IsFinishedReceiving(Service::Interface* self); - -/** - * Sets the number of lines the buffer contains. - * Inputs: - * 0: 0x00090100 - * 1: u8 selected port - * 2: u16 Number of lines to transfer - * 3: u16 Width - * 4: u16 Height - * Outputs: - * 0: 0x00090040 - * 1: ResultCode - * @todo figure out how the "buffer" actually works. - */ -void SetTransferLines(Service::Interface* self); - -/** - * Gets the maximum number of lines that fit in the buffer - * Inputs: - * 0: 0x000A0080 - * 1: u16 Width - * 2: u16 Height - * Outputs: - * 0: 0x000A0080 - * 1: ResultCode - * 2: Maximum number of lines that fit in the buffer - * @todo figure out how the "buffer" actually works. - */ -void GetMaxLines(Service::Interface* self); - -/** - * Sets the number of bytes the buffer contains. - * Inputs: - * 0: 0x000B0100 - * 1: u8 selected port - * 2: u16 Number of bytes to transfer - * 3: u16 Width - * 4: u16 Height - * Outputs: - * 0: 0x000B0040 - * 1: ResultCode - * @todo figure out how the "buffer" actually works. - */ -void SetTransferBytes(Service::Interface* self); - -/** - * Gets the number of bytes to the buffer contains. - * Inputs: - * 0: 0x000C0040 - * 1: u8 selected port - * Outputs: - * 0: 0x000C0080 - * 1: ResultCode - * 2: The number of bytes the buffer contains - * @todo figure out how the "buffer" actually works. - */ -void GetTransferBytes(Service::Interface* self); - -/** - * Gets the maximum number of bytes that fit in the buffer. - * Inputs: - * 0: 0x000D0080 - * 1: u16 Width - * 2: u16 Height - * Outputs: - * 0: 0x000D0080 - * 1: ResultCode - * 2: Maximum number of bytes that fit in the buffer - * @todo figure out how the "buffer" actually works. - */ -void GetMaxBytes(Service::Interface* self); - -/** - * Enables or disables trimming. - * Inputs: - * 0: 0x000E0080 - * 1: u8 selected port - * 2: u8 bool Enable trimming if true - * Outputs: - * 0: 0x000E0040 - * 1: ResultCode - */ -void SetTrimming(Service::Interface* self); - -/** - * Gets whether trimming is enabled. - * Inputs: - * 0: 0x000F0040 - * 1: u8 selected port - * Outputs: - * 0: 0x000F0080 - * 1: ResultCode - * 2: u8 bool Enable trimming if true - */ -void IsTrimming(Service::Interface* self); - -/** - * Sets the position to trim. - * Inputs: - * 0: 0x00100140 - * 1: u8 selected port - * 2: x start - * 3: y start - * 4: x end (exclusive) - * 5: y end (exclusive) - * Outputs: - * 0: 0x00100040 - * 1: ResultCode - */ -void SetTrimmingParams(Service::Interface* self); - -/** - * Gets the position to trim. - * Inputs: - * 0: 0x00110040 - * 1: u8 selected port - * - * Outputs: - * 0: 0x00110140 - * 1: ResultCode - * 2: x start - * 3: y start - * 4: x end (exclusive) - * 5: y end (exclusive) - */ -void GetTrimmingParams(Service::Interface* self); - -/** - * Sets the position to trim by giving the width and height. The trimming window is always at the - * center. - * Inputs: - * 0: 0x00120140 - * 1: u8 selected port - * 2: s16 Trim width - * 3: s16 Trim height - * 4: s16 Camera width - * 5: s16 Camera height - * Outputs: - * 0: 0x00120040 - * 1: ResultCode - */ -void SetTrimmingParamsCenter(Service::Interface* self); - -/** - * Selects up to two physical cameras to enable. - * Inputs: - * 0: 0x00130040 - * 1: u8 selected camera - * Outputs: - * 0: 0x00130040 - * 1: ResultCode - */ -void Activate(Service::Interface* self); - -/** - * Switches the context of camera settings. - * Inputs: - * 0: 0x00140080 - * 1: u8 selected camera - * 2: u8 selected context - * Outputs: - * 0: 0x00140040 - * 1: ResultCode - */ -void SwitchContext(Service::Interface* self); - -/** - * Sets flipping of images - * Inputs: - * 0: 0x001D00C0 - * 1: u8 selected camera - * 2: u8 Type of flipping to perform (`Flip` enum) - * 3: u8 selected context - * Outputs: - * 0: 0x001D0040 - * 1: ResultCode - */ -void FlipImage(Service::Interface* self); - -/** - * Sets camera resolution from custom parameters. For more details see the Resolution struct. - * Inputs: - * 0: 0x001E0200 - * 1: u8 selected camera - * 2: width - * 3: height - * 4: crop x0 - * 5: crop y0 - * 6: crop x1 - * 7: crop y1 - * 8: u8 selected context - * Outputs: - * 0: 0x001E0040 - * 1: ResultCode - */ -void SetDetailSize(Service::Interface* self); - -/** - * Sets camera resolution from preset resolution parameters. - * Inputs: - * 0: 0x001F00C0 - * 1: u8 selected camera - * 2: u8 Camera frame resolution (`Size` enum) - * 3: u8 selected context - * Outputs: - * 0: 0x001F0040 - * 1: ResultCode - */ -void SetSize(Service::Interface* self); - -/** - * Sets camera framerate. - * Inputs: - * 0: 0x00200080 - * 1: u8 selected camera - * 2: u8 Camera framerate (`FrameRate` enum) - * Outputs: - * 0: 0x00200040 - * 1: ResultCode - */ -void SetFrameRate(Service::Interface* self); - -/** - * Sets effect on the output image - * Inputs: - * 0: 0x002200C0 - * 1: u8 selected camera - * 2: u8 image effect (`Effect` enum) - * 3: u8 selected context - * Outputs: - * 0: 0x00220040 - * 1: ResultCode - */ -void SetEffect(Service::Interface* self); - -/** - * Sets format of the output image - * Inputs: - * 0: 0x002500C0 - * 1: u8 selected camera - * 2: u8 image format (`OutputFormat` enum) - * 3: u8 selected context - * Outputs: - * 0: 0x00250040 - * 1: ResultCode - */ -void SetOutputFormat(Service::Interface* self); - -/** - * Synchronizes the V-Sync timing of two cameras. - * Inputs: - * 0: 0x00290080 - * 1: u8 selected camera 1 - * 2: u8 selected camera 2 - * Outputs: - * 0: 0x00280040 - * 1: ResultCode - */ -void SynchronizeVsyncTiming(Service::Interface* self); - -/** - * Returns calibration data relating the outside cameras to eachother, for use in AR applications. - * - * Inputs: - * 0: 0x002B0000 - * Outputs: - * 0: 0x002B0440 - * 1: ResultCode - * 2-17: `StereoCameraCalibrationData` structure with calibration values - */ -void GetStereoCameraCalibrationData(Service::Interface* self); - -/** - * Batch-configures context-free settings. - * - * Inputs: - * 0: 0x003302C0 - * 1-7: struct PachageParameterWithoutContext - * 8-11: unused - * Outputs: - * 0: 0x00330040 - * 1: ResultCode - */ -void SetPackageParameterWithoutContext(Service::Interface* self); - -/** - * Batch-configures context-related settings with preset resolution parameters. - * - * Inputs: - * 0: 0x00340140 - * 1-2: struct PackageParameterWithContext - * 3-5: unused - * Outputs: - * 0: 0x00340040 - * 1: ResultCode - */ -void SetPackageParameterWithContext(Service::Interface* self); - -/** - * Batch-configures context-related settings with custom resolution parameters - * - * Inputs: - * 0: 0x003501C0 - * 1-4: struct PackageParameterWithContextDetail - * 5-7: unused - * Outputs: - * 0: 0x00350040 - * 1: ResultCode - */ -void SetPackageParameterWithContextDetail(Service::Interface* self); - -/** - * Unknown - * Inputs: - * 0: 0x00360000 - * Outputs: - * 0: 0x00360080 - * 1: ResultCode - * 2: ? - */ -void GetSuitableY2rStandardCoefficient(Service::Interface* self); - -/** - * Unknown - * Inputs: - * 0: 0x00380040 - * 1: u8 Sound ID - * Outputs: - * 0: 0x00380040 - * 1: ResultCode - */ -void PlayShutterSound(Service::Interface* self); - -/** - * Initializes the camera driver. Must be called before using other functions. - * Inputs: - * 0: 0x00390000 - * Outputs: - * 0: 0x00390040 - * 1: ResultCode - */ -void DriverInitialize(Service::Interface* self); - -/** - * Shuts down the camera driver. - * Inputs: - * 0: 0x003A0000 - * Outputs: - * 0: 0x003A0040 - * 1: ResultCode - */ -void DriverFinalize(Service::Interface* self); - -/// Initialize CAM service(s) -void Init(); - -/// Shutdown CAM service(s) -void Shutdown(); - -} // namespace CAM -} // namespace Service diff --git a/src/core/hle/service/cam/cam_c.cpp b/src/core/hle/service/cam/cam_c.cpp deleted file mode 100644 index 93b047c1a..000000000 --- a/src/core/hle/service/cam/cam_c.cpp +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/cam/cam_c.h" - -namespace Service { -namespace CAM { - -// Empty arrays are illegal -- commented out until an entry is added. -// const Interface::FunctionInfo FunctionTable[] = { }; - -CAM_C_Interface::CAM_C_Interface() { - // Register(FunctionTable); -} - -} // namespace CAM -} // namespace Service diff --git a/src/core/hle/service/cam/cam_c.h b/src/core/hle/service/cam/cam_c.h deleted file mode 100644 index 6b296c00d..000000000 --- a/src/core/hle/service/cam/cam_c.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included.. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace CAM { - -class CAM_C_Interface : public Service::Interface { -public: - CAM_C_Interface(); - - std::string GetPortName() const override { - return "cam:c"; - } -}; - -} // namespace CAM -} // namespace Service diff --git a/src/core/hle/service/cam/cam_q.cpp b/src/core/hle/service/cam/cam_q.cpp deleted file mode 100644 index 2ba853606..000000000 --- a/src/core/hle/service/cam/cam_q.cpp +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/cam/cam_q.h" - -namespace Service { -namespace CAM { - -// Empty arrays are illegal -- commented out until an entry is added. -// const Interface::FunctionInfo FunctionTable[] = { }; - -CAM_Q_Interface::CAM_Q_Interface() { - // Register(FunctionTable); -} - -} // namespace CAM -} // namespace Service diff --git a/src/core/hle/service/cam/cam_q.h b/src/core/hle/service/cam/cam_q.h deleted file mode 100644 index 07cc12534..000000000 --- a/src/core/hle/service/cam/cam_q.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included.. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace CAM { - -class CAM_Q_Interface : public Service::Interface { -public: - CAM_Q_Interface(); - - std::string GetPortName() const override { - return "cam:q"; - } -}; - -} // namespace CAM -} // namespace Service diff --git a/src/core/hle/service/cam/cam_s.cpp b/src/core/hle/service/cam/cam_s.cpp deleted file mode 100644 index f1c6da587..000000000 --- a/src/core/hle/service/cam/cam_s.cpp +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/cam/cam_s.h" - -namespace Service { -namespace CAM { - -// Empty arrays are illegal -- commented out until an entry is added. -// const Interface::FunctionInfo FunctionTable[] = { }; - -CAM_S_Interface::CAM_S_Interface() { - // Register(FunctionTable); -} - -} // namespace CAM -} // namespace Service diff --git a/src/core/hle/service/cam/cam_s.h b/src/core/hle/service/cam/cam_s.h deleted file mode 100644 index 0a5d6fca2..000000000 --- a/src/core/hle/service/cam/cam_s.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included.. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace CAM { - -class CAM_S_Interface : public Service::Interface { -public: - CAM_S_Interface(); - - std::string GetPortName() const override { - return "cam:s"; - } -}; - -} // namespace CAM -} // namespace Service diff --git a/src/core/hle/service/cam/cam_u.cpp b/src/core/hle/service/cam/cam_u.cpp deleted file mode 100644 index 251c1e6d4..000000000 --- a/src/core/hle/service/cam/cam_u.cpp +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include "core/hle/service/cam/cam.h" -#include "core/hle/service/cam/cam_u.h" - -namespace Service { -namespace CAM { - -const Interface::FunctionInfo FunctionTable[] = { - {0x00010040, StartCapture, "StartCapture"}, - {0x00020040, StopCapture, "StopCapture"}, - {0x00030040, IsBusy, "IsBusy"}, - {0x00040040, ClearBuffer, "ClearBuffer"}, - {0x00050040, GetVsyncInterruptEvent, "GetVsyncInterruptEvent"}, - {0x00060040, GetBufferErrorInterruptEvent, "GetBufferErrorInterruptEvent"}, - {0x00070102, SetReceiving, "SetReceiving"}, - {0x00080040, IsFinishedReceiving, "IsFinishedReceiving"}, - {0x00090100, SetTransferLines, "SetTransferLines"}, - {0x000A0080, GetMaxLines, "GetMaxLines"}, - {0x000B0100, SetTransferBytes, "SetTransferBytes"}, - {0x000C0040, GetTransferBytes, "GetTransferBytes"}, - {0x000D0080, GetMaxBytes, "GetMaxBytes"}, - {0x000E0080, SetTrimming, "SetTrimming"}, - {0x000F0040, IsTrimming, "IsTrimming"}, - {0x00100140, SetTrimmingParams, "SetTrimmingParams"}, - {0x00110040, GetTrimmingParams, "GetTrimmingParams"}, - {0x00120140, SetTrimmingParamsCenter, "SetTrimmingParamsCenter"}, - {0x00130040, Activate, "Activate"}, - {0x00140080, SwitchContext, "SwitchContext"}, - {0x00150080, nullptr, "SetExposure"}, - {0x00160080, nullptr, "SetWhiteBalance"}, - {0x00170080, nullptr, "SetWhiteBalanceWithoutBaseUp"}, - {0x00180080, nullptr, "SetSharpness"}, - {0x00190080, nullptr, "SetAutoExposure"}, - {0x001A0040, nullptr, "IsAutoExposure"}, - {0x001B0080, nullptr, "SetAutoWhiteBalance"}, - {0x001C0040, nullptr, "IsAutoWhiteBalance"}, - {0x001D00C0, FlipImage, "FlipImage"}, - {0x001E0200, SetDetailSize, "SetDetailSize"}, - {0x001F00C0, SetSize, "SetSize"}, - {0x00200080, SetFrameRate, "SetFrameRate"}, - {0x00210080, nullptr, "SetPhotoMode"}, - {0x002200C0, SetEffect, "SetEffect"}, - {0x00230080, nullptr, "SetContrast"}, - {0x00240080, nullptr, "SetLensCorrection"}, - {0x002500C0, SetOutputFormat, "SetOutputFormat"}, - {0x00260140, nullptr, "SetAutoExposureWindow"}, - {0x00270140, nullptr, "SetAutoWhiteBalanceWindow"}, - {0x00280080, nullptr, "SetNoiseFilter"}, - {0x00290080, SynchronizeVsyncTiming, "SynchronizeVsyncTiming"}, - {0x002A0080, nullptr, "GetLatestVsyncTiming"}, - {0x002B0000, GetStereoCameraCalibrationData, "GetStereoCameraCalibrationData"}, - {0x002C0400, nullptr, "SetStereoCameraCalibrationData"}, - {0x002D00C0, nullptr, "WriteRegisterI2c"}, - {0x002E00C0, nullptr, "WriteMcuVariableI2c"}, - {0x002F0080, nullptr, "ReadRegisterI2cExclusive"}, - {0x00300080, nullptr, "ReadMcuVariableI2cExclusive"}, - {0x00310180, nullptr, "SetImageQualityCalibrationData"}, - {0x00320000, nullptr, "GetImageQualityCalibrationData"}, - {0x003302C0, SetPackageParameterWithoutContext, "SetPackageParameterWithoutContext"}, - {0x00340140, SetPackageParameterWithContext, "SetPackageParameterWithContext"}, - {0x003501C0, SetPackageParameterWithContextDetail, "SetPackageParameterWithContextDetail"}, - {0x00360000, GetSuitableY2rStandardCoefficient, "GetSuitableY2rStandardCoefficient"}, - {0x00370202, nullptr, "PlayShutterSoundWithWave"}, - {0x00380040, PlayShutterSound, "PlayShutterSound"}, - {0x00390000, DriverInitialize, "DriverInitialize"}, - {0x003A0000, DriverFinalize, "DriverFinalize"}, - {0x003B0000, nullptr, "GetActivatedCamera"}, - {0x003C0000, nullptr, "GetSleepCamera"}, - {0x003D0040, nullptr, "SetSleepCamera"}, - {0x003E0040, nullptr, "SetBrightnessSynchronization"}, -}; - -CAM_U_Interface::CAM_U_Interface() { - Register(FunctionTable); -} - -} // namespace CAM -} // namespace Service diff --git a/src/core/hle/service/cam/cam_u.h b/src/core/hle/service/cam/cam_u.h deleted file mode 100644 index 369264037..000000000 --- a/src/core/hle/service/cam/cam_u.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2015 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included.. - -#pragma once - -#include "core/hle/service/service.h" - -namespace Service { -namespace CAM { - -class CAM_U_Interface : public Service::Interface { -public: - CAM_U_Interface(); - - std::string GetPortName() const override { - return "cam:u"; - } -}; - -} // namespace CAM -} // namespace Service |