From be933ef2241d79558f91796cc5b3a161f72ebf9c Mon Sep 17 00:00:00 2001 From: manuel Date: Mon, 19 Oct 2020 00:52:24 +0200 Subject: sync with upstream --- .../include/kodi/addon-instance/Game.h | 1190 ++++++++++++++++++++ 1 file changed, 1190 insertions(+) create mode 100644 xbmc/addons/kodi-dev-kit/include/kodi/addon-instance/Game.h (limited to 'xbmc/addons/kodi-dev-kit/include/kodi/addon-instance/Game.h') diff --git a/xbmc/addons/kodi-dev-kit/include/kodi/addon-instance/Game.h b/xbmc/addons/kodi-dev-kit/include/kodi/addon-instance/Game.h new file mode 100644 index 0000000..3dca94d --- /dev/null +++ b/xbmc/addons/kodi-dev-kit/include/kodi/addon-instance/Game.h @@ -0,0 +1,1190 @@ +/* + * Copyright (C) 2014-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +#include "../AddonBase.h" +#include "../c-api/addon-instance/game.h" + +#ifdef __cplusplus + +namespace kodi +{ +namespace addon +{ + +//============================================================================== +/// @addtogroup cpp_kodi_addon_game +/// +/// To use on Libretro and for stand-alone games or emulators that does not use +/// the Libretro API. +/// +/// Possible examples could be, Nvidia GameStream via Limelight or WINE capture +/// could possible through the Game API. +/// + +//============================================================================== +/// @defgroup cpp_kodi_addon_game_Defs Definitions, structures and enumerators +/// @ingroup cpp_kodi_addon_game +/// @brief **Game add-on instance definition values** +/// + +//============================================================================== +/// @defgroup cpp_kodi_addon_game_Defs_InputTypes_GameControllerLayout class GameControllerLayout +/// @ingroup cpp_kodi_addon_game_Defs_InputTypes +/// @brief Data of layouts for known controllers. +/// +/// Used on @ref kodi::addon::CInstanceGame::SetControllerLayouts(). +///@{ +class GameControllerLayout +{ +public: + /*! @cond PRIVATE */ + explicit GameControllerLayout() = default; + GameControllerLayout(const game_controller_layout& layout) + { + controller_id = layout.controller_id; + provides_input = layout.provides_input; + for (unsigned int i = 0; i < layout.digital_button_count; ++i) + digital_buttons.push_back(layout.digital_buttons[i]); + for (unsigned int i = 0; i < layout.analog_button_count; ++i) + analog_buttons.push_back(layout.analog_buttons[i]); + for (unsigned int i = 0; i < layout.analog_stick_count; ++i) + analog_sticks.push_back(layout.analog_sticks[i]); + for (unsigned int i = 0; i < layout.accelerometer_count; ++i) + accelerometers.push_back(layout.accelerometers[i]); + for (unsigned int i = 0; i < layout.key_count; ++i) + keys.push_back(layout.keys[i]); + for (unsigned int i = 0; i < layout.rel_pointer_count; ++i) + rel_pointers.push_back(layout.rel_pointers[i]); + for (unsigned int i = 0; i < layout.abs_pointer_count; ++i) + abs_pointers.push_back(layout.abs_pointers[i]); + for (unsigned int i = 0; i < layout.motor_count; ++i) + motors.push_back(layout.motors[i]); + } + /*! @endcond */ + + /// @brief Controller identifier. + std::string controller_id; + + /// @brief Provides input. + /// + /// False for multitaps + bool provides_input; + + /// @brief Digital buttons. + std::vector digital_buttons; + + /// @brief Analog buttons. + std::vector analog_buttons; + + /// @brief Analog sticks. + std::vector analog_sticks; + + /// @brief Accelerometers. + std::vector accelerometers; + + /// @brief Keys. + std::vector keys; + + /// @brief Relative pointers. + std::vector rel_pointers; + + /// @brief Absolute pointers. + std::vector abs_pointers; + + /// @brief Motors. + std::vector motors; +}; +///@} +//------------------------------------------------------------------------------ + +//============================================================================== +/// @addtogroup cpp_kodi_addon_game +/// @brief @cpp_class{ kodi::addon::CInstanceGame } +/// **Game add-on instance**\n +/// This class provides the basic game processing system for use as an add-on in +/// Kodi. +/// +/// This class is created at addon by Kodi. +/// +class ATTRIBUTE_HIDDEN CInstanceGame : public IAddonInstance +{ +public: + //============================================================================ + /// @defgroup cpp_kodi_addon_game_Base 1. Basic functions + /// @ingroup cpp_kodi_addon_game + /// @brief **Functions to manage the addon and get basic information about it** + /// + ///@{ + + //============================================================================ + /// @brief Game class constructor + /// + /// Used by an add-on that only supports only Game and only in one instance. + /// + /// This class is created at addon by Kodi. + /// + /// + /// -------------------------------------------------------------------------- + /// + /// + /// **Here's example about the use of this:** + /// ~~~~~~~~~~~~~{.cpp} + /// #include + /// ... + /// + /// class ATTRIBUTE_HIDDEN CGameExample + /// : public kodi::addon::CAddonBase, + /// public kodi::addon::CInstanceGame + /// { + /// public: + /// CGameExample() + /// { + /// } + /// + /// virtual ~CGameExample(); + /// { + /// } + /// + /// ... + /// }; + /// + /// ADDONCREATOR(CGameExample) + /// ~~~~~~~~~~~~~ + /// + CInstanceGame() : IAddonInstance(ADDON_INSTANCE_GAME, GetKodiTypeVersion(ADDON_INSTANCE_GAME)) + { + if (CAddonBase::m_interface->globalSingleInstance != nullptr) + throw std::logic_error("kodi::addon::CInstanceGame: Creation of more as one in single " + "instance way is not allowed!"); + + SetAddonStruct(CAddonBase::m_interface->firstKodiInstance); + CAddonBase::m_interface->globalSingleInstance = this; + } + //---------------------------------------------------------------------------- + + //============================================================================ + /// @brief Destructor + /// + ~CInstanceGame() override = default; + //---------------------------------------------------------------------------- + + //============================================================================ + /// @brief **Callback to Kodi Function**\n + /// The path of the game client being loaded. + /// + /// @return the used game client Dll path + /// + /// @remarks Only called from addon itself + /// + std::string GameClientDllPath() const { return m_instanceData->props->game_client_dll_path; } + //---------------------------------------------------------------------------- + + //============================================================================ + /// @brief **Callback to Kodi Function**\n + /// Paths to proxy DLLs used to load the game client. + /// + /// @param[out] paths vector list to store available dll paths + /// @return true if success and dll paths present + /// + /// @remarks Only called from addon itself + /// + bool ProxyDllPaths(std::vector& paths) + { + for (unsigned int i = 0; i < m_instanceData->props->proxy_dll_count; ++i) + { + if (m_instanceData->props->proxy_dll_paths[i] != nullptr) + paths.push_back(m_instanceData->props->proxy_dll_paths[i]); + } + return !paths.empty(); + } + //---------------------------------------------------------------------------- + + //============================================================================ + /// @brief **Callback to Kodi Function**\n + /// The "system" directories of the frontend. + /// + /// These directories can be used to store system-specific ROMs such as + /// BIOSes, configuration data, etc. + /// + /// @return the used resource directory + /// + /// @remarks Only called from addon itself + /// + bool ResourceDirectories(std::vector& dirs) + { + for (unsigned int i = 0; i < m_instanceData->props->resource_directory_count; ++i) + { + if (m_instanceData->props->resource_directories[i] != nullptr) + dirs.push_back(m_instanceData->props->resource_directories[i]); + } + return !dirs.empty(); + } + //---------------------------------------------------------------------------- + + //============================================================================ + /// @brief **Callback to Kodi Function**\n + /// The writable directory of the frontend. + /// + /// This directory can be used to store SRAM, memory cards, high scores, + /// etc, if the game client cannot use the regular memory interface, + /// GetMemoryData(). + /// + /// @return the used profile directory + /// + /// @remarks Only called from addon itself + /// + std::string ProfileDirectory() const { return m_instanceData->props->profile_directory; } + //---------------------------------------------------------------------------- + + //============================================================================ + /// @brief **Callback to Kodi Function**\n + /// The value of the property from addon.xml. + /// + /// @return true if VFS is supported + /// + /// @remarks Only called from addon itself + /// + bool SupportsVFS() const { return m_instanceData->props->supports_vfs; } + //---------------------------------------------------------------------------- + + //============================================================================ + /// @brief **Callback to Kodi Function**\n + /// The extensions in the property from addon.xml. + /// + /// @param[out] extensions vector list to store available extension + /// @return true if success and extensions present + /// + /// @remarks Only called from addon itself + /// + bool Extensions(std::vector& extensions) + { + for (unsigned int i = 0; i < m_instanceData->props->extension_count; ++i) + { + if (m_instanceData->props->extensions[i] != nullptr) + extensions.push_back(m_instanceData->props->extensions[i]); + } + return !extensions.empty(); + } + //---------------------------------------------------------------------------- + + ///@} + +//--==----==----==----==----==----==----==----==----==----==----==----==----==-- + + //============================================================================ + /// + /// @defgroup cpp_kodi_addon_game_Operation 2. Game operations + /// @ingroup cpp_kodi_addon_game + /// @brief **Game operations** + /// + /// These are mandatory functions for using this addon to get the available + /// channels. + /// + /// + ///--------------------------------------------------------------------------- + /// + /// **Game operation parts in interface:**\n + /// Copy this to your project and extend with your parts or leave functions + /// complete away where not used or supported. + /// + /// @copydetails cpp_kodi_addon_game_Operation_header_addon_auto_check + /// @copydetails cpp_kodi_addon_game_Operation_source_addon_auto_check + /// + ///@{ + + //============================================================================ + /// @brief Load a game + /// + /// @param[in] url The URL to load + /// @return the error, or @ref GAME_ERROR_NO_ERROR if the game was loaded + /// + virtual GAME_ERROR LoadGame(const std::string& url) + { + return GAME_ERROR_NOT_IMPLEMENTED; + } + //---------------------------------------------------------------------------- + + //============================================================================ + /// @brief Load a game that requires multiple files + /// + /// @param[in] type The game type + /// @param[in] urls An array of urls + /// @return the error, or @ref GAME_ERROR_NO_ERROR if the game was loaded + /// + virtual GAME_ERROR LoadGameSpecial(SPECIAL_GAME_TYPE type, const std::vector& urls) + { + return GAME_ERROR_NOT_IMPLEMENTED; + } + //---------------------------------------------------------------------------- + + //============================================================================ + /// @brief Begin playing without a game file + /// + /// If the add-on supports standalone mode, it must add the + /// tag to the extension point in addon.xml: + /// + /// false + /// + /// @return the error, or @ref GAME_ERROR_NO_ERROR if the game add-on was loaded + /// + virtual GAME_ERROR LoadStandalone() + { + return GAME_ERROR_NOT_IMPLEMENTED; + } + //---------------------------------------------------------------------------- + + //============================================================================ + /// @brief Unload the current game + /// + /// Unloads a currently loaded game + /// + /// @return the error, or @ref GAME_ERROR_NO_ERROR if the game was unloaded + /// + virtual GAME_ERROR UnloadGame() + { + return GAME_ERROR_NOT_IMPLEMENTED; + } + //---------------------------------------------------------------------------- + + //============================================================================ + /// @brief Get timing information about the loaded game + /// + /// @param[out] timing_info The info structure to fill + /// + /// @return the error, or @ref GAME_ERROR_NO_ERROR if info was filled + /// + virtual GAME_ERROR GetGameTiming(game_system_timing& timing_info) + { + return GAME_ERROR_NOT_IMPLEMENTED; + } + //---------------------------------------------------------------------------- + + //============================================================================ + /// @brief Get region of the loaded game + /// + /// @return the region, or @ref GAME_REGION_UNKNOWN if unknown or no game is loaded + /// + virtual GAME_REGION GetRegion() + { + return GAME_REGION_UNKNOWN; + } + //---------------------------------------------------------------------------- + + //============================================================================ + /// @brief Return true if the client requires the frontend to provide a game loop + /// + /// The game loop is a thread that calls RunFrame() in a loop at a rate + /// determined by the playback speed and the client's FPS. + /// + /// @return true if the frontend should provide a game loop, false otherwise + /// + virtual bool RequiresGameLoop() + { + return false; + } + //---------------------------------------------------------------------------- + + //============================================================================ + /// @brief Run a single frame for add-ons that use a game loop + /// + /// @return the error, or @ref GAME_ERROR_NO_ERROR if there was no error + /// + virtual GAME_ERROR RunFrame() + { + return GAME_ERROR_NOT_IMPLEMENTED; + } + //---------------------------------------------------------------------------- + + //============================================================================ + /// @brief Reset the current game + /// + /// @return the error, or @ref GAME_ERROR_NO_ERROR if the game was reset + /// + virtual GAME_ERROR Reset() + { + return GAME_ERROR_NOT_IMPLEMENTED; + } + //---------------------------------------------------------------------------- + + //========================================================================== + /// @brief **Callback to Kodi Function**\n + /// Requests the frontend to stop the current game + /// + /// @remarks Only called from addon itself + /// + void CloseGame(void) { m_instanceData->toKodi->CloseGame(m_instanceData->toKodi->kodiInstance); } + //---------------------------------------------------------------------------- + + //============================================================================ + /// @defgroup cpp_kodi_addon_game_Operation_CStream Class: CStream + /// @ingroup cpp_kodi_addon_game_Operation + /// @brief @cpp_class{ kodi::addon::CInstanceGame::CStream } + /// **Game stream handler** + /// + /// This class will be integrated into the addon, which can then open it if + /// necessary for the processing of an audio or video stream. + /// + /// + /// @note Callback to Kodi class + ///@{ + class CStream + { + public: + CStream() = default; + + CStream(const game_stream_properties& properties) + { + Open(properties); + } + + ~CStream() + { + Close(); + } + + //========================================================================== + /// @ingroup cpp_kodi_addon_game_Operation_CStream + /// @brief Create a stream for gameplay data + /// + /// @param[in] properties The stream properties + /// @return A stream handle, or `nullptr` on failure + /// + /// @remarks Only called from addon itself + /// + bool Open(const game_stream_properties& properties) + { + if (!CAddonBase::m_interface->globalSingleInstance) + return false; + + if (m_handle) + { + kodi::Log(ADDON_LOG_INFO, "kodi::addon::CInstanceGame::CStream already becomes reopened"); + Close(); + } + + AddonToKodiFuncTable_Game& cb = + *static_cast(CAddonBase::m_interface->globalSingleInstance) + ->m_instanceData->toKodi; + m_handle = cb.OpenStream(cb.kodiInstance, &properties); + return m_handle != nullptr; + } + //-------------------------------------------------------------------------- + + //========================================================================== + /// @ingroup cpp_kodi_addon_game_Operation_CStream + /// @brief Free the specified stream + /// + /// @remarks Only called from addon itself + /// + void Close() + { + if (!m_handle || !CAddonBase::m_interface->globalSingleInstance) + return; + + AddonToKodiFuncTable_Game& cb = + *static_cast(CAddonBase::m_interface->globalSingleInstance) + ->m_instanceData->toKodi; + cb.CloseStream(cb.kodiInstance, m_handle); + m_handle = nullptr; + } + //-------------------------------------------------------------------------- + + //========================================================================== + /// @ingroup cpp_kodi_addon_game_Operation_CStream + /// @brief Get a buffer for zero-copy stream data + /// + /// @param[in] width The framebuffer width, or 0 for no width specified + /// @param[in] height The framebuffer height, or 0 for no height specified + /// @param[out] buffer The buffer, or unmodified if false is returned + /// @return True if buffer was set, false otherwise + /// + /// @note If this returns true, buffer must be freed using @ref ReleaseBuffer(). + /// + /// @remarks Only called from addon itself + /// + bool GetBuffer(unsigned int width, unsigned int height, game_stream_buffer& buffer) + { + if (!m_handle || !CAddonBase::m_interface->globalSingleInstance) + return false; + + AddonToKodiFuncTable_Game& cb = + *static_cast(CAddonBase::m_interface->globalSingleInstance) + ->m_instanceData->toKodi; + return cb.GetStreamBuffer(cb.kodiInstance, m_handle, width, height, &buffer); + } + //-------------------------------------------------------------------------- + + //========================================================================== + /// @ingroup cpp_kodi_addon_game_Operation_CStream + /// @brief Add a data packet to a stream + /// + /// @param[in] packet The data packet + /// + /// @remarks Only called from addon itself + /// + void AddData(const game_stream_packet& packet) + { + if (!m_handle || !CAddonBase::m_interface->globalSingleInstance) + return; + + AddonToKodiFuncTable_Game& cb = + *static_cast(CAddonBase::m_interface->globalSingleInstance) + ->m_instanceData->toKodi; + cb.AddStreamData(cb.kodiInstance, m_handle, &packet); + } + //-------------------------------------------------------------------------- + + //========================================================================== + /// @ingroup cpp_kodi_addon_game_Operation_CStream + /// @brief Free an allocated buffer + /// + /// @param[in] buffer The buffer returned from GetStreamBuffer() + /// + /// @remarks Only called from addon itself + /// + void ReleaseBuffer(game_stream_buffer& buffer) + { + if (!m_handle || !CAddonBase::m_interface->globalSingleInstance) + return; + + AddonToKodiFuncTable_Game& cb = + *static_cast(CAddonBase::m_interface->globalSingleInstance) + ->m_instanceData->toKodi; + cb.ReleaseStreamBuffer(cb.kodiInstance, m_handle, &buffer); + } + //-------------------------------------------------------------------------- + + //========================================================================== + /// @ingroup cpp_kodi_addon_game_Operation_CStream + /// @brief To check stream open was OK, e.g. after use of constructor + /// + /// @return true if stream was successfully opened + /// + /// @remarks Only called from addon itself + /// + bool IsOpen() const { return m_handle != nullptr; } + //-------------------------------------------------------------------------- + + private: + KODI_GAME_STREAM_HANDLE m_handle = nullptr; + }; + ///@} + + ///@} + +//--==----==----==----==----==----==----==----==----==----==----==----==----==-- + + //============================================================================ + /// + /// @defgroup cpp_kodi_addon_game_HardwareRendering 3. Hardware rendering operations + /// @ingroup cpp_kodi_addon_game + /// @brief **Hardware rendering operations** + /// + /// + ///--------------------------------------------------------------------------- + /// + /// **Hardware rendering operation parts in interface:**\n + /// Copy this to your project and extend with your parts or leave functions + /// complete away where not used or supported. + /// + /// @copydetails cpp_kodi_addon_game_HardwareRendering_header_addon_auto_check + /// @copydetails cpp_kodi_addon_game_HardwareRendering_source_addon_auto_check + /// + ///@{ + + //============================================================================ + /// @brief Invalidates the current HW context and reinitializes GPU resources + /// + /// Any GL state is lost, and must not be deinitialized explicitly. + /// + /// @return the error, or @ref GAME_ERROR_NO_ERROR if the HW context was reset + /// + virtual GAME_ERROR HwContextReset() + { + return GAME_ERROR_NOT_IMPLEMENTED; + } + //---------------------------------------------------------------------------- + + //============================================================================ + /// @brief Called before the context is destroyed + /// + /// Resources can be deinitialized at this step. + /// + /// @return the error, or @ref GAME_ERROR_NO_ERROR if the HW context was destroyed + /// + virtual GAME_ERROR HwContextDestroy() + { + return GAME_ERROR_NOT_IMPLEMENTED; + } + + //============================================================================ + /// @brief **Callback to Kodi Function**
Get a symbol from the hardware context + /// + /// @param[in] sym The symbol's name + /// + /// @return A function pointer for the specified symbol + /// + /// @remarks Only called from addon itself + /// + game_proc_address_t HwGetProcAddress(const char* sym) + { + return m_instanceData->toKodi->HwGetProcAddress(m_instanceData->toKodi->kodiInstance, sym); + } + //---------------------------------------------------------------------------- + + ///@} + +//--==----==----==----==----==----==----==----==----==----==----==----==----==-- + + //============================================================================ + /// @defgroup cpp_kodi_addon_game_InputOperations 4. Input operations + /// @ingroup cpp_kodi_addon_game + /// @brief **Input operations** + /// + /// + ///--------------------------------------------------------------------------- + /// + /// **Hardware rendering operation parts in interface:**\n + /// Copy this to your project and extend with your parts or leave functions + /// complete away where not used or supported. + /// + /// @copydetails cpp_kodi_addon_game_InputOperations_header_addon_auto_check + /// @copydetails cpp_kodi_addon_game_InputOperations_source_addon_auto_check + /// + ///@{ + + //============================================================================ + /// @brief Check if input is accepted for a feature on the controller + /// + /// If only a subset of the controller profile is used, this can return false + /// for unsupported features to not absorb their input. + /// + /// If the entire controller profile is used, this should always return true. + /// + /// @param[in] controller_id The ID of the controller profile + /// @param[in] feature_name The name of a feature in that profile + /// @return true if input is accepted for the feature, false otherwise + /// + virtual bool HasFeature(const std::string& controller_id, const std::string& feature_name) + { + return false; + } + //---------------------------------------------------------------------------- + + //============================================================================ + /// @brief Get the input topology that specifies which controllers can be connected + /// + /// @return The input topology, or null to use the default + /// + /// If this returns non-null, topology must be freed using FreeTopology(). + /// + /// If this returns null, the topology will default to a single port that can + /// accept all controllers imported by addon.xml. The port ID is set to + /// the @ref DEFAULT_PORT_ID constant. + /// + virtual game_input_topology* GetTopology() + { + return nullptr; + } + //---------------------------------------------------------------------------- + + //============================================================================ + /// @brief Free the topology's resources + /// + /// @param[in] topology The topology returned by GetTopology() + /// + virtual void FreeTopology(game_input_topology* topology) + { + } + //---------------------------------------------------------------------------- + + //============================================================================ + /// @brief Set the layouts for known controllers + /// + /// @param[in] controllers The controller layouts + /// + /// After loading the input topology, the frontend will call this with + /// controller layouts for all controllers discovered in the topology. + /// + virtual void SetControllerLayouts(const std::vector& controllers) + { + } + //---------------------------------------------------------------------------- + + //============================================================================ + /// @brief Enable/disable keyboard input using the specified controller + /// + /// @param[in] enable True to enable input, false otherwise + /// @param[in] controller_id The controller ID if enabling, or unused if disabling + /// + /// @return True if keyboard input was enabled, false otherwise + /// + virtual bool EnableKeyboard(bool enable, const std::string& controller_id) + { + return false; + } + //---------------------------------------------------------------------------- + + //============================================================================ + /// @brief Enable/disable mouse input using the specified controller + /// + /// @param[in] enable True to enable input, false otherwise + /// @param[in] controller_id The controller ID if enabling, or unused if disabling + /// + /// @return True if mouse input was enabled, false otherwise + /// + virtual bool EnableMouse(bool enable, const std::string& controller_id) + { + return false; + } + //-------------------------------------------------------------------------- + + //========================================================================== + /// @brief Connect/disconnect a controller to a port on the virtual game console + /// + /// @param[in] connect True to connect a controller, false to disconnect + /// @param[in] port_address The address of the port + /// @param[in] controller_id The controller ID if connecting, or unused if disconnecting + /// @return True if the \p controller was (dis-)connected to the port, false otherwise + /// + /// The address is a string that allows traversal of the controller topology. + /// It is formed by alternating port IDs and controller IDs separated by "/". + /// + /// For example, assume that the topology represented in XML for Snes9x is: + /// + /// ~~~~~~~~~~~~~{.xml} + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// ... + /// + /// + /// + /// ~~~~~~~~~~~~~ + /// + /// To connect a multitap to the console's first port, the multitap's controller + /// info is set using the port address: + /// + /// 1 + /// + /// To connect a SNES controller to the second port of the multitap, the + /// controller info is next set using the address: + /// + /// 1/game.controller.multitap/2 + /// + /// Any attempts to connect a controller to a port on a disconnected multitap + /// will return false. + /// + virtual bool ConnectController(bool connect, + const std::string& port_address, + const std::string& controller_id) + { + return false; + } + //---------------------------------------------------------------------------- + + //============================================================================ + /// @brief Notify the add-on of an input event + /// + /// @param[in] event The input event + /// + /// @return true if the event was handled, false otherwise + /// + virtual bool InputEvent(const game_input_event& event) + { + return false; + } + //---------------------------------------------------------------------------- + + //============================================================================ + /// @brief **Callback to Kodi Function**
Notify the port of an input event + /// + /// @param[in] event The input event + /// @return true if the event was handled, false otherwise + /// + /// @note Input events can arrive for the following sources: + /// - @ref GAME_INPUT_EVENT_MOTOR + /// + /// @remarks Only called from addon itself + /// + bool KodiInputEvent(const game_input_event& event) + { + return m_instanceData->toKodi->InputEvent(m_instanceData->toKodi->kodiInstance, &event); + } + //---------------------------------------------------------------------------- + + ///@} + +//--==----==----==----==----==----==----==----==----==----==----==----==----==-- + + //============================================================================ + /// @defgroup cpp_kodi_addon_game_SerializationOperations 5. Serialization operations + /// @ingroup cpp_kodi_addon_game + /// @brief **Serialization operations** + /// + /// + ///--------------------------------------------------------------------------- + /// + /// **Serialization operation parts in interface:**\n + /// Copy this to your project and extend with your parts or leave functions + /// complete away where not used or supported. + /// + /// @copydetails cpp_kodi_addon_game_SerializationOperations_header_addon_auto_check + /// @copydetails cpp_kodi_addon_game_SerializationOperations_source_addon_auto_check + /// + ///@{ + + //============================================================================ + /// @brief Get the number of bytes required to serialize the game + /// + /// @return the number of bytes, or 0 if serialization is not supported + /// + virtual size_t SerializeSize() + { + return 0; + } + //---------------------------------------------------------------------------- + + //============================================================================ + /// @brief Serialize the state of the game + /// + /// @param[in] data The buffer receiving the serialized game data + /// @param[in] size The size of the buffer + /// + /// @return the error, or @ref GAME_ERROR_NO_ERROR if the game was serialized into the buffer + /// + virtual GAME_ERROR Serialize(uint8_t* data, size_t size) + { + return GAME_ERROR_NOT_IMPLEMENTED; + } + //---------------------------------------------------------------------------- + + //============================================================================ + /// @brief Deserialize the game from the given state + /// + /// @param[in] data A buffer containing the game's new state + /// @param[in] size The size of the buffer + /// + /// @return the error, or @ref GAME_ERROR_NO_ERROR if the game deserialized + /// + virtual GAME_ERROR Deserialize(const uint8_t* data, size_t size) + { + return GAME_ERROR_NOT_IMPLEMENTED; + } + //---------------------------------------------------------------------------- + + ///@} + +//--==----==----==----==----==----==----==----==----==----==----==----==----==-- + + //============================================================================ + /// @defgroup cpp_kodi_addon_game_CheatOperations 6. Cheat operations + /// @ingroup cpp_kodi_addon_game + /// @brief **Cheat operations** + /// + /// + ///--------------------------------------------------------------------------- + /// + /// **Cheat operation parts in interface:**\n + /// Copy this to your project and extend with your parts or leave functions + /// complete away where not used or supported. + /// + /// @copydetails cpp_kodi_addon_game_CheatOperations_header_addon_auto_check + /// @copydetails cpp_kodi_addon_game_CheatOperations_source_addon_auto_check + /// + ///@{ + + //============================================================================ + /// @brief Reset the cheat system + /// + /// @return the error, or @ref GAME_ERROR_NO_ERROR if the cheat system was reset + /// + virtual GAME_ERROR CheatReset() + { + return GAME_ERROR_NOT_IMPLEMENTED; + } + //---------------------------------------------------------------------------- + + //============================================================================ + /// @brief Get a region of memory + /// + /// @param[in] type The type of memory to retrieve + /// @param[in] data Set to the region of memory; must remain valid until UnloadGame() is called + /// @param[in] size Set to the size of the region of memory + /// + /// @return the error, or @ref GAME_ERROR_NO_ERROR if data was set to a valid buffer + /// + virtual GAME_ERROR GetMemory(GAME_MEMORY type, uint8_t*& data, size_t& size) + { + return GAME_ERROR_NOT_IMPLEMENTED; + } + //---------------------------------------------------------------------------- + + //============================================================================ + /// @brief Set a cheat code + /// + /// @param[in] index + /// @param[in] enabled + /// @param[in] code + /// + /// @return the error, or @ref GAME_ERROR_NO_ERROR if the cheat was set + /// + virtual GAME_ERROR SetCheat(unsigned int index, bool enabled, const std::string& code) + { + return GAME_ERROR_NOT_IMPLEMENTED; + } + //---------------------------------------------------------------------------- + + ///@} + +private: + void SetAddonStruct(KODI_HANDLE instance) + { + if (instance == nullptr) + throw std::logic_error("kodi::addon::CInstanceGame: Creation with empty addon structure not" + "allowed, table must be given from Kodi!"); + + m_instanceData = static_cast(instance); + m_instanceData->toAddon->addonInstance = this; + + m_instanceData->toAddon->LoadGame = ADDON_LoadGame; + m_instanceData->toAddon->LoadGameSpecial = ADDON_LoadGameSpecial; + m_instanceData->toAddon->LoadStandalone = ADDON_LoadStandalone; + m_instanceData->toAddon->UnloadGame = ADDON_UnloadGame; + m_instanceData->toAddon->GetGameTiming = ADDON_GetGameTiming; + m_instanceData->toAddon->GetRegion = ADDON_GetRegion; + m_instanceData->toAddon->RequiresGameLoop = ADDON_RequiresGameLoop; + m_instanceData->toAddon->RunFrame = ADDON_RunFrame; + m_instanceData->toAddon->Reset = ADDON_Reset; + + m_instanceData->toAddon->HwContextReset = ADDON_HwContextReset; + m_instanceData->toAddon->HwContextDestroy = ADDON_HwContextDestroy; + + m_instanceData->toAddon->HasFeature = ADDON_HasFeature; + m_instanceData->toAddon->GetTopology = ADDON_GetTopology; + m_instanceData->toAddon->FreeTopology = ADDON_FreeTopology; + m_instanceData->toAddon->SetControllerLayouts = ADDON_SetControllerLayouts; + m_instanceData->toAddon->EnableKeyboard = ADDON_EnableKeyboard; + m_instanceData->toAddon->EnableMouse = ADDON_EnableMouse; + m_instanceData->toAddon->ConnectController = ADDON_ConnectController; + m_instanceData->toAddon->InputEvent = ADDON_InputEvent; + + m_instanceData->toAddon->SerializeSize = ADDON_SerializeSize; + m_instanceData->toAddon->Serialize = ADDON_Serialize; + m_instanceData->toAddon->Deserialize = ADDON_Deserialize; + + m_instanceData->toAddon->CheatReset = ADDON_CheatReset; + m_instanceData->toAddon->GetMemory = ADDON_GetMemory; + m_instanceData->toAddon->SetCheat = ADDON_SetCheat; + } + + // --- Game operations --------------------------------------------------------- + + inline static GAME_ERROR ADDON_LoadGame(const AddonInstance_Game* instance, const char* url) + { + return static_cast(instance->toAddon->addonInstance)->LoadGame(url); + } + + inline static GAME_ERROR ADDON_LoadGameSpecial(const AddonInstance_Game* instance, + SPECIAL_GAME_TYPE type, + const char** urls, + size_t urlCount) + { + std::vector urlList; + for (size_t i = 0; i < urlCount; ++i) + { + if (urls[i] != nullptr) + urlList.push_back(urls[i]); + } + + return static_cast(instance->toAddon->addonInstance) + ->LoadGameSpecial(type, urlList); + } + + inline static GAME_ERROR ADDON_LoadStandalone(const AddonInstance_Game* instance) + { + return static_cast(instance->toAddon->addonInstance)->LoadStandalone(); + } + + inline static GAME_ERROR ADDON_UnloadGame(const AddonInstance_Game* instance) + { + return static_cast(instance->toAddon->addonInstance)->UnloadGame(); + } + + inline static GAME_ERROR ADDON_GetGameTiming(const AddonInstance_Game* instance, + game_system_timing* timing_info) + { + return static_cast(instance->toAddon->addonInstance) + ->GetGameTiming(*timing_info); + } + + inline static GAME_REGION ADDON_GetRegion(const AddonInstance_Game* instance) + { + return static_cast(instance->toAddon->addonInstance)->GetRegion(); + } + + inline static bool ADDON_RequiresGameLoop(const AddonInstance_Game* instance) + { + return static_cast(instance->toAddon->addonInstance)->RequiresGameLoop(); + } + + inline static GAME_ERROR ADDON_RunFrame(const AddonInstance_Game* instance) + { + return static_cast(instance->toAddon->addonInstance)->RunFrame(); + } + + inline static GAME_ERROR ADDON_Reset(const AddonInstance_Game* instance) + { + return static_cast(instance->toAddon->addonInstance)->Reset(); + } + + + // --- Hardware rendering operations ------------------------------------------- + + inline static GAME_ERROR ADDON_HwContextReset(const AddonInstance_Game* instance) + { + return static_cast(instance->toAddon->addonInstance)->HwContextReset(); + } + + inline static GAME_ERROR ADDON_HwContextDestroy(const AddonInstance_Game* instance) + { + return static_cast(instance->toAddon->addonInstance)->HwContextDestroy(); + } + + + // --- Input operations -------------------------------------------------------- + + inline static bool ADDON_HasFeature(const AddonInstance_Game* instance, + const char* controller_id, + const char* feature_name) + { + return static_cast(instance->toAddon->addonInstance) + ->HasFeature(controller_id, feature_name); + } + + inline static game_input_topology* ADDON_GetTopology(const AddonInstance_Game* instance) + { + return static_cast(instance->toAddon->addonInstance)->GetTopology(); + } + + inline static void ADDON_FreeTopology(const AddonInstance_Game* instance, + game_input_topology* topology) + { + static_cast(instance->toAddon->addonInstance)->FreeTopology(topology); + } + + inline static void ADDON_SetControllerLayouts(const AddonInstance_Game* instance, + const game_controller_layout* controllers, + unsigned int controller_count) + { + if (controllers == nullptr) + return; + + std::vector controllerList; + for (unsigned int i = 0; i < controller_count; ++i) + controllerList.push_back(controllers[i]); + + static_cast(instance->toAddon->addonInstance) + ->SetControllerLayouts(controllerList); + } + + inline static bool ADDON_EnableKeyboard(const AddonInstance_Game* instance, + bool enable, + const char* controller_id) + { + return static_cast(instance->toAddon->addonInstance) + ->EnableKeyboard(enable, controller_id); + } + + inline static bool ADDON_EnableMouse(const AddonInstance_Game* instance, + bool enable, + const char* controller_id) + { + return static_cast(instance->toAddon->addonInstance) + ->EnableMouse(enable, controller_id); + } + + inline static bool ADDON_ConnectController(const AddonInstance_Game* instance, + bool connect, + const char* port_address, + const char* controller_id) + { + return static_cast(instance->toAddon->addonInstance) + ->ConnectController(connect, port_address, controller_id); + } + + inline static bool ADDON_InputEvent(const AddonInstance_Game* instance, + const game_input_event* event) + { + return static_cast(instance->toAddon->addonInstance)->InputEvent(*event); + } + + + // --- Serialization operations ------------------------------------------------ + + inline static size_t ADDON_SerializeSize(const AddonInstance_Game* instance) + { + return static_cast(instance->toAddon->addonInstance)->SerializeSize(); + } + + inline static GAME_ERROR ADDON_Serialize(const AddonInstance_Game* instance, + uint8_t* data, + size_t size) + { + return static_cast(instance->toAddon->addonInstance)->Serialize(data, size); + } + + inline static GAME_ERROR ADDON_Deserialize(const AddonInstance_Game* instance, + const uint8_t* data, + size_t size) + { + return static_cast(instance->toAddon->addonInstance)->Deserialize(data, size); + } + + + // --- Cheat operations -------------------------------------------------------- + + inline static GAME_ERROR ADDON_CheatReset(const AddonInstance_Game* instance) + { + return static_cast(instance->toAddon->addonInstance)->CheatReset(); + } + + inline static GAME_ERROR ADDON_GetMemory(const AddonInstance_Game* instance, + GAME_MEMORY type, + uint8_t** data, + size_t* size) + { + return static_cast(instance->toAddon->addonInstance) + ->GetMemory(type, *data, *size); + } + + inline static GAME_ERROR ADDON_SetCheat(const AddonInstance_Game* instance, + unsigned int index, + bool enabled, + const char* code) + { + return static_cast(instance->toAddon->addonInstance) + ->SetCheat(index, enabled, code); + } + + AddonInstance_Game* m_instanceData; +}; + +} /* namespace addon */ +} /* namespace kodi */ + +#endif /* __cplusplus */ -- cgit v1.2.3