Преглед изворни кода

Merge pull request #2368 from wwylele/camera-2

CAM: build the service framework with a dummy implementation
Yuri Kunde Schlesner пре 9 година
родитељ
комит
1410aa1824

+ 15 - 0
src/citra/config.cpp

@@ -93,6 +93,21 @@ void Config::ReadValues() {
     Settings::values.region_value =
         sdl2_config->GetInteger("System", "region_value", Settings::REGION_VALUE_AUTO_SELECT);
 
+    // Camera
+    using namespace Service::CAM;
+    Settings::values.camera_name[OuterRightCamera] =
+        sdl2_config->Get("Camera", "camera_outer_right_name", "blank");
+    Settings::values.camera_config[OuterRightCamera] =
+        sdl2_config->Get("Camera", "camera_outer_right_config", "");
+    Settings::values.camera_name[InnerCamera] =
+        sdl2_config->Get("Camera", "camera_inner_name", "blank");
+    Settings::values.camera_config[InnerCamera] =
+        sdl2_config->Get("Camera", "camera_inner_config", "");
+    Settings::values.camera_name[OuterLeftCamera] =
+        sdl2_config->Get("Camera", "camera_outer_left_name", "blank");
+    Settings::values.camera_config[OuterLeftCamera] =
+        sdl2_config->Get("Camera", "camera_outer_left_config", "");
+
     // Miscellaneous
     Settings::values.log_filter = sdl2_config->Get("Miscellaneous", "log_filter", "*:Info");
 

+ 16 - 0
src/citra/default_ini.h

@@ -109,6 +109,22 @@ is_new_3ds =
 # -1: Auto-select (default), 0: Japan, 1: USA, 2: Europe, 3: Australia, 4: China, 5: Korea, 6: Taiwan
 region_value =
 
+[Camera]
+# Which camera engine to use for the right outer camera
+# blank (default): a dummy camera that always returns black image
+camera_outer_right_name =
+
+# A config string for the right outer camera. Its meaning is defined by the camera engine
+camera_outer_right_config =
+
+# ... for the left outer camera
+camera_outer_left_name =
+camera_outer_left_config =
+
+# ... for the inner camera
+camera_inner_name =
+camera_inner_config =
+
 [Miscellaneous]
 # A filter which removes logs below a certain logging level.
 # Examples: *:Debug Kernel.SVC:Trace Service.*:Critical

+ 32 - 0
src/citra_qt/config.cpp

@@ -67,6 +67,22 @@ void Config::ReadValues() {
         qt_config->value("output_device", "auto").toString().toStdString();
     qt_config->endGroup();
 
+    using namespace Service::CAM;
+    qt_config->beginGroup("Camera");
+    Settings::values.camera_name[OuterRightCamera] =
+        qt_config->value("camera_outer_right_name", "blank").toString().toStdString();
+    Settings::values.camera_config[OuterRightCamera] =
+        qt_config->value("camera_outer_right_config", "").toString().toStdString();
+    Settings::values.camera_name[InnerCamera] =
+        qt_config->value("camera_inner_name", "blank").toString().toStdString();
+    Settings::values.camera_config[InnerCamera] =
+        qt_config->value("camera_inner_config", "").toString().toStdString();
+    Settings::values.camera_name[OuterLeftCamera] =
+        qt_config->value("camera_outer_left_name", "blank").toString().toStdString();
+    Settings::values.camera_config[OuterLeftCamera] =
+        qt_config->value("camera_outer_left_config", "").toString().toStdString();
+    qt_config->endGroup();
+
     qt_config->beginGroup("Data Storage");
     Settings::values.use_virtual_sd = qt_config->value("use_virtual_sd", true).toBool();
     qt_config->endGroup();
@@ -174,6 +190,22 @@ void Config::SaveValues() {
     qt_config->setValue("output_device", QString::fromStdString(Settings::values.audio_device_id));
     qt_config->endGroup();
 
+    using namespace Service::CAM;
+    qt_config->beginGroup("Camera");
+    qt_config->setValue("camera_outer_right_name",
+                        QString::fromStdString(Settings::values.camera_name[OuterRightCamera]));
+    qt_config->setValue("camera_outer_right_config",
+                        QString::fromStdString(Settings::values.camera_config[OuterRightCamera]));
+    qt_config->setValue("camera_inner_name",
+                        QString::fromStdString(Settings::values.camera_name[InnerCamera]));
+    qt_config->setValue("camera_inner_config",
+                        QString::fromStdString(Settings::values.camera_config[InnerCamera]));
+    qt_config->setValue("camera_outer_left_name",
+                        QString::fromStdString(Settings::values.camera_name[OuterLeftCamera]));
+    qt_config->setValue("camera_outer_left_config",
+                        QString::fromStdString(Settings::values.camera_config[OuterLeftCamera]));
+    qt_config->endGroup();
+
     qt_config->beginGroup("Data Storage");
     qt_config->setValue("use_virtual_sd", Settings::values.use_virtual_sd);
     qt_config->endGroup();

+ 6 - 0
src/core/CMakeLists.txt

@@ -29,6 +29,9 @@ set(SRCS
             file_sys/ivfc_archive.cpp
             file_sys/path_parser.cpp
             file_sys/savedata_archive.cpp
+            frontend/camera/blank_camera.cpp
+            frontend/camera/factory.cpp
+            frontend/camera/interface.cpp
             frontend/emu_window.cpp
             frontend/key_map.cpp
             frontend/motion_emu.cpp
@@ -203,6 +206,9 @@ set(HEADERS
             file_sys/ivfc_archive.h
             file_sys/path_parser.h
             file_sys/savedata_archive.h
+            frontend/camera/blank_camera.h
+            frontend/camera/factory.h
+            frontend/camera/interface.h
             frontend/emu_window.h
             frontend/key_map.h
             frontend/motion_emu.h

+ 31 - 0
src/core/frontend/camera/blank_camera.cpp

@@ -0,0 +1,31 @@
+// Copyright 2016 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "core/frontend/camera/blank_camera.h"
+
+namespace Camera {
+
+void BlankCamera::StartCapture() {}
+
+void BlankCamera::StopCapture() {}
+
+void BlankCamera::SetFormat(Service::CAM::OutputFormat output_format) {
+    output_rgb = output_format == Service::CAM::OutputFormat::RGB565;
+}
+
+void BlankCamera::SetResolution(const Service::CAM::Resolution& resolution) {
+    width = resolution.width;
+    height = resolution.height;
+};
+
+void BlankCamera::SetFlip(Service::CAM::Flip) {}
+
+void BlankCamera::SetEffect(Service::CAM::Effect) {}
+
+std::vector<u16> BlankCamera::ReceiveFrame() const {
+    // Note: 0x80008000 stands for two black pixels in YUV422
+    return std::vector<u16>(width * height, output_rgb ? 0 : 0x8000);
+}
+
+} // namespace Camera

+ 28 - 0
src/core/frontend/camera/blank_camera.h

@@ -0,0 +1,28 @@
+// Copyright 2016 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/frontend/camera/factory.h"
+#include "core/frontend/camera/interface.h"
+
+namespace Camera {
+
+class BlankCamera final : public CameraInterface {
+public:
+    void StartCapture() override;
+    void StopCapture() override;
+    void SetResolution(const Service::CAM::Resolution&) override;
+    void SetFlip(Service::CAM::Flip) override;
+    void SetEffect(Service::CAM::Effect) override;
+    void SetFormat(Service::CAM::OutputFormat) override;
+    std::vector<u16> ReceiveFrame() const override;
+
+private:
+    int width = 0;
+    int height = 0;
+    bool output_rgb = false;
+};
+
+} // namespace Camera

+ 32 - 0
src/core/frontend/camera/factory.cpp

@@ -0,0 +1,32 @@
+// Copyright 2016 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <unordered_map>
+#include "common/logging/log.h"
+#include "core/frontend/camera/blank_camera.h"
+#include "core/frontend/camera/factory.h"
+
+namespace Camera {
+
+static std::unordered_map<std::string, std::unique_ptr<CameraFactory>> factories;
+
+CameraFactory::~CameraFactory() = default;
+
+void RegisterFactory(const std::string& name, std::unique_ptr<CameraFactory> factory) {
+    factories[name] = std::move(factory);
+}
+
+std::unique_ptr<CameraInterface> CreateCamera(const std::string& name, const std::string& config) {
+    auto pair = factories.find(name);
+    if (pair != factories.end()) {
+        return pair->second->Create(config);
+    }
+
+    if (name != "blank") {
+        LOG_ERROR(Service_CAM, "Unknown camera \"%s\"", name.c_str());
+    }
+    return std::make_unique<BlankCamera>();
+}
+
+} // namespace Camera

+ 41 - 0
src/core/frontend/camera/factory.h

@@ -0,0 +1,41 @@
+// Copyright 2016 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <memory>
+#include <string>
+#include "core/frontend/camera/interface.h"
+
+namespace Camera {
+
+class CameraFactory {
+public:
+    virtual ~CameraFactory();
+
+    /**
+     * Creates a camera object based on the configuration string.
+     * @params config Configuration string to create the camera. The implementation can decide the
+     *     meaning of this string.
+     * @returns a unique_ptr to the created camera object.
+     */
+    virtual std::unique_ptr<CameraInterface> Create(const std::string& config) const = 0;
+};
+
+/**
+ * Registers an external camera factory.
+ * @param name Identifier of the camera factory.
+ * @param factory Camera factory to register.
+ */
+void RegisterFactory(const std::string& name, std::unique_ptr<CameraFactory> factory);
+
+/**
+ * Creates a camera from the factory.
+ * @param name Identifier of the camera factory.
+ * @param config Configuration string to create the camera. The meaning of this string is
+ *     defined by the factory.
+ */
+std::unique_ptr<CameraInterface> CreateCamera(const std::string& name, const std::string& config);
+
+} // namespace Camera

+ 11 - 0
src/core/frontend/camera/interface.cpp

@@ -0,0 +1,11 @@
+// Copyright 2016 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "core/frontend/camera/interface.h"
+
+namespace Camera {
+
+CameraInterface::~CameraInterface() = default;
+
+} // namespace Camera

+ 61 - 0
src/core/frontend/camera/interface.h

@@ -0,0 +1,61 @@
+// Copyright 2016 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <vector>
+#include "common/common_types.h"
+#include "core/hle/service/cam/cam.h"
+
+namespace Camera {
+
+/// An abstract class standing for a camera. All camera implementations should inherit from this.
+class CameraInterface {
+public:
+    virtual ~CameraInterface();
+
+    /// Starts the camera for video capturing.
+    virtual void StartCapture() = 0;
+
+    /// Stops the camera for video capturing.
+    virtual void StopCapture() = 0;
+
+    /**
+     * Sets the video resolution from raw CAM service parameters.
+     * For the meaning of the parameters, please refer to Service::CAM::Resolution. Note that the
+     * actual camera implementation doesn't need to respect all the parameters. However, the width
+     * and the height parameters must be respected and be used to determine the size of output
+     * frames.
+     * @param resolution The resolution parameters to set
+     */
+    virtual void SetResolution(const Service::CAM::Resolution& resolution) = 0;
+
+    /**
+     * Configures how received frames should be flipped by the camera.
+     * @param flip Flip applying to the frame
+     */
+    virtual void SetFlip(Service::CAM::Flip flip) = 0;
+
+    /**
+     * Configures what effect should be applied to received frames by the camera.
+     * @param effect Effect applying to the frame
+     */
+    virtual void SetEffect(Service::CAM::Effect effect) = 0;
+
+    /**
+     * Sets the output format of the all frames received after this function is called.
+     * @param format Output format of the frame
+     */
+    virtual void SetFormat(Service::CAM::OutputFormat format) = 0;
+
+    /**
+     * Receives a frame from the camera.
+     * This function should be only called between a StartCapture call and a StopCapture call.
+     * @returns A std::vector<u16> containing pixels. The total size of the vector is width * height
+     *     where width and height are set by a call to SetResolution.
+     */
+    virtual std::vector<u16> ReceiveFrame() const = 0;
+};
+
+} // namespace Camera

Разлика између датотеке није приказан због своје велике величине
+ 810 - 84
src/core/hle/service/cam/cam.cpp


+ 304 - 54
src/core/hle/service/cam/cam.h

@@ -13,17 +13,12 @@
 namespace Service {
 namespace CAM {
 
-enum class Port : u8 { None = 0, Cam1 = 1, Cam2 = 2, Both = Cam1 | Cam2 };
+enum CameraIndex {
+    OuterRightCamera = 0,
+    InnerCamera = 1,
+    OuterLeftCamera = 2,
 
-enum class CameraSelect : u8 {
-    None = 0,
-    Out1 = 1,
-    In1 = 2,
-    Out2 = 4,
-    In1Out1 = Out1 | In1,
-    Out1Out2 = Out1 | Out2,
-    In1Out2 = In1 | Out2,
-    All = Out1 | In1 | Out2,
+    NumCameras = 3,
 };
 
 enum class Effect : u8 {
@@ -35,13 +30,6 @@ enum class Effect : u8 {
     Sepia01 = 5,
 };
 
-enum class Context : u8 {
-    None = 0,
-    A = 1,
-    B = 2,
-    Both = A | B,
-};
-
 enum class Flip : u8 {
     None = 0,
     Horizontal = 1,
@@ -160,8 +148,23 @@ struct StereoCameraCalibrationData {
 static_assert(sizeof(StereoCameraCalibrationData) == 64,
               "StereoCameraCalibrationData structure size is wrong");
 
-struct PackageParameterCameraSelect {
-    CameraSelect camera;
+/**
+ * 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;
@@ -183,14 +186,43 @@ struct PackageParameterCameraSelect {
     s16 auto_white_balance_window_height;
 };
 
-static_assert(sizeof(PackageParameterCameraSelect) == 28,
-              "PackageParameterCameraSelect structure size is wrong");
+static_assert(sizeof(PackageParameterWithoutContext) == 28,
+              "PackageParameterCameraWithoutContext structure size is wrong");
+
+struct PackageParameterWithContext {
+    u8 camera_select;
+    u8 context_select;
+    Flip flip;
+    Effect effect;
+    Size size;
+    INSERT_PADDING_BYTES(3);
+
+    Resolution GetResolution();
+};
+
+static_assert(sizeof(PackageParameterWithContext) == 8,
+              "PackageParameterWithContext structure size is wrong");
+
+struct PackageParameterWithContextDetail {
+    u8 camera_select;
+    u8 context_select;
+    Flip flip;
+    Effect effect;
+    Resolution resolution;
+
+    Resolution GetResolution() {
+        return resolution;
+    }
+};
+
+static_assert(sizeof(PackageParameterWithContextDetail) == 16,
+              "PackageParameterWithContextDetail structure size is wrong");
 
 /**
- * Unknown
+ * Starts capturing at the selected port.
  *  Inputs:
  *      0: 0x00010040
- *      1: u8 Camera port (`Port` enum)
+ *      1: u8 selected port
  *  Outputs:
  *      0: 0x00010040
  *      1: ResultCode
@@ -198,21 +230,44 @@ static_assert(sizeof(PackageParameterCameraSelect) == 28,
 void StartCapture(Service::Interface* self);
 
 /**
- * Unknown
+ * Stops capturing from the selected port.
  *  Inputs:
  *      0: 0x00020040
- *      1: u8 Camera port (`Port` enum)
+ *      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 Camera port (`Port` enum)
+ *      1: u8 selected port
  *  Outputs:
  *      0: 0x00050042
  *      1: ResultCode
@@ -225,7 +280,7 @@ void GetVsyncInterruptEvent(Service::Interface* self);
  * Unknown
  *  Inputs:
  *      0: 0x00060040
- *      1: u8 Camera port (`Port` enum)
+ *      1: u8 selected port
  *  Outputs:
  *      0: 0x00060042
  *      1: ResultCode
@@ -241,9 +296,9 @@ void GetBufferErrorInterruptEvent(Service::Interface* self);
  *  Inputs:
  *      0: 0x00070102
  *      1: Destination address in calling process
- *      2: u8 Camera port (`Port` enum)
- *      3: Image size (in bytes?)
- *      4: u16 Transfer unit size (in bytes?)
+ *      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:
@@ -255,21 +310,34 @@ void GetBufferErrorInterruptEvent(Service::Interface* self);
 void SetReceiving(Service::Interface* self);
 
 /**
- * Unknown
+ * 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 Camera port (`Port` enum)
+ *      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);
 
 /**
- * Unknown
+ * Gets the maximum number of lines that fit in the buffer
  *  Inputs:
  *      0: 0x000A0080
  *      1: u16 Width
@@ -277,27 +345,58 @@ void SetTransferLines(Service::Interface* self);
  *  Outputs:
  *      0: 0x000A0080
  *      1: ResultCode
- *      2: Maximum number of lines that fit in the buffer(?)
+ *      2: Maximum number of lines that fit in the buffer
+ * @todo figure out how the "buffer" actually works.
  */
 void GetMaxLines(Service::Interface* self);
 
 /**
- * Unknown
+ * 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 Camera port (`Port` enum)
+ *      1: u8 selected port
  *  Outputs:
  *      0: 0x000C0080
  *      1: ResultCode
- *      2: Total number of bytes for each frame with current settings(?)
+ *      2: The number of bytes the buffer contains
+ * @todo figure out how the "buffer" actually works.
  */
 void GetTransferBytes(Service::Interface* self);
 
 /**
- * Unknown
+ * 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 Camera port (`Port` enum)
+ *      1: u8 selected port
  *      2: u8 bool Enable trimming if true
  *  Outputs:
  *      0: 0x000E0040
@@ -306,14 +405,58 @@ void GetTransferBytes(Service::Interface* self);
 void SetTrimming(Service::Interface* self);
 
 /**
- * Unknown
+ * 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 Camera port (`Port` enum)
- *      2: s16 Trim width(?)
- *      3: s16 Trim height(?)
- *      4: s16 Camera width(?)
- *      5: s16 Camera height(?)
+ *      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
@@ -324,7 +467,7 @@ void SetTrimmingParamsCenter(Service::Interface* self);
  * Selects up to two physical cameras to enable.
  *  Inputs:
  *      0: 0x00130040
- *      1: u8 Cameras to activate (`CameraSelect` enum)
+ *      1: u8 selected camera
  *  Outputs:
  *      0: 0x00130040
  *      1: ResultCode
@@ -332,12 +475,24 @@ void SetTrimmingParamsCenter(Service::Interface* self);
 void Activate(Service::Interface* self);
 
 /**
- * Unknown
+ * 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 Camera select (`CameraSelect` enum)
+ *      1: u8 selected camera
  *      2: u8 Type of flipping to perform (`Flip` enum)
- *      3: u8 Context (`Context` enum)
+ *      3: u8 selected context
  *  Outputs:
  *      0: 0x001D0040
  *      1: ResultCode
@@ -345,12 +500,30 @@ void Activate(Service::Interface* self);
 void FlipImage(Service::Interface* self);
 
 /**
- * Unknown
+ * 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 Camera select (`CameraSelect` enum)
+ *      1: u8 selected camera
  *      2: u8 Camera frame resolution (`Size` enum)
- *      3: u8 Context id (`Context` enum)
+ *      3: u8 selected context
  *  Outputs:
  *      0: 0x001F0040
  *      1: ResultCode
@@ -358,10 +531,10 @@ void FlipImage(Service::Interface* self);
 void SetSize(Service::Interface* self);
 
 /**
- * Unknown
+ * Sets camera framerate.
  *  Inputs:
  *      0: 0x00200080
- *      1: u8 Camera select (`CameraSelect` enum)
+ *      1: u8 selected camera
  *      2: u8 Camera framerate (`FrameRate` enum)
  *  Outputs:
  *      0: 0x00200040
@@ -369,6 +542,44 @@ void SetSize(Service::Interface* self);
  */
 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.
  *
@@ -381,6 +592,45 @@ void SetFrameRate(Service::Interface* self);
  */
 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:

+ 16 - 16
src/core/hle/service/cam/cam_u.cpp

@@ -11,24 +11,24 @@ namespace CAM {
 const Interface::FunctionInfo FunctionTable[] = {
     {0x00010040, StartCapture, "StartCapture"},
     {0x00020040, StopCapture, "StopCapture"},
-    {0x00030040, nullptr, "IsBusy"},
-    {0x00040040, nullptr, "ClearBuffer"},
+    {0x00030040, IsBusy, "IsBusy"},
+    {0x00040040, ClearBuffer, "ClearBuffer"},
     {0x00050040, GetVsyncInterruptEvent, "GetVsyncInterruptEvent"},
     {0x00060040, GetBufferErrorInterruptEvent, "GetBufferErrorInterruptEvent"},
     {0x00070102, SetReceiving, "SetReceiving"},
-    {0x00080040, nullptr, "IsFinishedReceiving"},
+    {0x00080040, IsFinishedReceiving, "IsFinishedReceiving"},
     {0x00090100, SetTransferLines, "SetTransferLines"},
     {0x000A0080, GetMaxLines, "GetMaxLines"},
-    {0x000B0100, nullptr, "SetTransferBytes"},
+    {0x000B0100, SetTransferBytes, "SetTransferBytes"},
     {0x000C0040, GetTransferBytes, "GetTransferBytes"},
-    {0x000D0080, nullptr, "GetMaxBytes"},
+    {0x000D0080, GetMaxBytes, "GetMaxBytes"},
     {0x000E0080, SetTrimming, "SetTrimming"},
-    {0x000F0040, nullptr, "IsTrimming"},
-    {0x00100140, nullptr, "SetTrimmingParams"},
-    {0x00110040, nullptr, "GetTrimmingParams"},
+    {0x000F0040, IsTrimming, "IsTrimming"},
+    {0x00100140, SetTrimmingParams, "SetTrimmingParams"},
+    {0x00110040, GetTrimmingParams, "GetTrimmingParams"},
     {0x00120140, SetTrimmingParamsCenter, "SetTrimmingParamsCenter"},
     {0x00130040, Activate, "Activate"},
-    {0x00140080, nullptr, "SwitchContext"},
+    {0x00140080, SwitchContext, "SwitchContext"},
     {0x00150080, nullptr, "SetExposure"},
     {0x00160080, nullptr, "SetWhiteBalance"},
     {0x00170080, nullptr, "SetWhiteBalanceWithoutBaseUp"},
@@ -38,18 +38,18 @@ const Interface::FunctionInfo FunctionTable[] = {
     {0x001B0080, nullptr, "SetAutoWhiteBalance"},
     {0x001C0040, nullptr, "IsAutoWhiteBalance"},
     {0x001D00C0, FlipImage, "FlipImage"},
-    {0x001E0200, nullptr, "SetDetailSize"},
+    {0x001E0200, SetDetailSize, "SetDetailSize"},
     {0x001F00C0, SetSize, "SetSize"},
     {0x00200080, SetFrameRate, "SetFrameRate"},
     {0x00210080, nullptr, "SetPhotoMode"},
-    {0x002200C0, nullptr, "SetEffect"},
+    {0x002200C0, SetEffect, "SetEffect"},
     {0x00230080, nullptr, "SetContrast"},
     {0x00240080, nullptr, "SetLensCorrection"},
-    {0x002500C0, nullptr, "SetOutputFormat"},
+    {0x002500C0, SetOutputFormat, "SetOutputFormat"},
     {0x00260140, nullptr, "SetAutoExposureWindow"},
     {0x00270140, nullptr, "SetAutoWhiteBalanceWindow"},
     {0x00280080, nullptr, "SetNoiseFilter"},
-    {0x00290080, nullptr, "SynchronizeVsyncTiming"},
+    {0x00290080, SynchronizeVsyncTiming, "SynchronizeVsyncTiming"},
     {0x002A0080, nullptr, "GetLatestVsyncTiming"},
     {0x002B0000, GetStereoCameraCalibrationData, "GetStereoCameraCalibrationData"},
     {0x002C0400, nullptr, "SetStereoCameraCalibrationData"},
@@ -59,9 +59,9 @@ const Interface::FunctionInfo FunctionTable[] = {
     {0x00300080, nullptr, "ReadMcuVariableI2cExclusive"},
     {0x00310180, nullptr, "SetImageQualityCalibrationData"},
     {0x00320000, nullptr, "GetImageQualityCalibrationData"},
-    {0x003302C0, nullptr, "SetPackageParameterWithoutContext"},
-    {0x00340140, nullptr, "SetPackageParameterWithContext"},
-    {0x003501C0, nullptr, "SetPackageParameterWithContextDetail"},
+    {0x003302C0, SetPackageParameterWithoutContext, "SetPackageParameterWithoutContext"},
+    {0x00340140, SetPackageParameterWithContext, "SetPackageParameterWithContext"},
+    {0x003501C0, SetPackageParameterWithContextDetail, "SetPackageParameterWithContextDetail"},
     {0x00360000, GetSuitableY2rStandardCoefficient, "GetSuitableY2rStandardCoefficient"},
     {0x00370202, nullptr, "PlayShutterSoundWithWave"},
     {0x00380040, PlayShutterSound, "PlayShutterSound"},

+ 5 - 0
src/core/settings.h

@@ -7,6 +7,7 @@
 #include <array>
 #include <string>
 #include "common/common_types.h"
+#include "core/hle/service/cam/cam.h"
 
 namespace Settings {
 
@@ -106,6 +107,10 @@ struct Values {
     bool enable_audio_stretching;
     std::string audio_device_id;
 
+    // Camera
+    std::array<std::string, Service::CAM::NumCameras> camera_name;
+    std::array<std::string, Service::CAM::NumCameras> camera_config;
+
     // Debugging
     bool use_gdbstub;
     u16 gdbstub_port;

Неке датотеке нису приказане због велике количине промена