From 5f8335c1e49ce108ef3481863833c98efa00411b Mon Sep 17 00:00:00 2001 From: manuel Date: Thu, 2 Jul 2020 23:09:26 +0200 Subject: sync with upstream --- .../include/kodi/addon-instance/Game.h | 2360 ++++++++++++++++++++ 1 file changed, 2360 insertions(+) create mode 100644 xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Game.h (limited to 'xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Game.h') diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Game.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Game.h new file mode 100644 index 0000000..a53f1e7 --- /dev/null +++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Game.h @@ -0,0 +1,2360 @@ +/* + * 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" + +#ifdef BUILD_KODI_ADDON +#include "XBMC_vkeys.h" +#else +#include "input/XBMC_vkeys.h" +#endif + +//============================================================================== +/// @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. +/// + +namespace kodi +{ +namespace addon +{ +class CInstanceGame; +} +} // namespace kodi + +extern "C" +{ + +//============================================================================== +/// \defgroup cpp_kodi_addon_game_Defs Definitions, structures and enumerators +/// \ingroup cpp_kodi_addon_game +/// @brief **Game add-on instance definition values** +//------------------------------------------------------------------------------ + +//============================================================================== +/// \ingroup cpp_kodi_addon_game_Defs +/// @brief **Port ID used when topology is unknown** +#define DEFAULT_PORT_ID "1" +//------------------------------------------------------------------------------ + +//============================================================================== +/// \ingroup cpp_kodi_addon_game_Defs +/// @brief **Game add-on error codes** +/// +/// Used as return values on most Game related functions. +/// +typedef enum GAME_ERROR +{ + /// @brief no error occurred + GAME_ERROR_NO_ERROR, + + /// @brief an unknown error occurred + GAME_ERROR_UNKNOWN, + + /// @brief the method that the frontend called is not implemented + GAME_ERROR_NOT_IMPLEMENTED, + + /// @brief the command was rejected by the game client + GAME_ERROR_REJECTED, + + /// @brief the parameters of the method that was called are invalid for this operation + GAME_ERROR_INVALID_PARAMETERS, + + /// @brief the command failed + GAME_ERROR_FAILED, + + /// @brief no game is loaded + GAME_ERROR_NOT_LOADED, + + /// @brief game requires restricted resources + GAME_ERROR_RESTRICTED, +} GAME_ERROR; +//------------------------------------------------------------------------------ + +//--==----==----==----==----==----==----==----==----==----==----==----==----==-- +/// \defgroup cpp_kodi_addon_game_Defs_AudioStream 1. Audio stream +/// \ingroup cpp_kodi_addon_game_Defs +/// @brief **The for Audio stream used data system** +/// +/// Used to give Addon currently used audio stream configuration on Kodi and +/// arrays to give related data to Kodi on callbacks. +/// +//@{ + +//============================================================================== +/// @brief **Stream Format** +/// +/// From Kodi requested specified audio sample format. +/// +typedef enum GAME_PCM_FORMAT +{ + GAME_PCM_FORMAT_UNKNOWN, + + /// @brief S16NE sample format + GAME_PCM_FORMAT_S16NE, +} GAME_PCM_FORMAT; +//------------------------------------------------------------------------------ + +//============================================================================== +/// @brief **Audio channel** +/// +/// Channel identification flags. +/// +typedef enum GAME_AUDIO_CHANNEL +{ + /// @brief Channel list terminator + GAME_CH_NULL, + + /// @brief Channel front left + GAME_CH_FL, + + /// @brief Channel front right + GAME_CH_FR, + + /// @brief Channel front center + GAME_CH_FC, + + /// @brief Channel Low Frequency Effects / Subwoofer + GAME_CH_LFE, + + /// @brief Channel back left + GAME_CH_BL, + + /// @brief Channel back right + GAME_CH_BR, + + /// @brief Channel front left over center + GAME_CH_FLOC, + + /// @brief Channel front right over center + GAME_CH_FROC, + + /// @brief Channel back center + GAME_CH_BC, + + /// @brief Channel surround/side left + GAME_CH_SL, + + /// @brief Channel surround/side right + GAME_CH_SR, + + /// @brief Channel top front left + GAME_CH_TFL, + + /// @brief Channel top front right + GAME_CH_TFR, + + /// @brief Channel top front center + GAME_CH_TFC, + + /// @brief Channel top center + GAME_CH_TC, + + /// @brief Channel top back left + GAME_CH_TBL, + + /// @brief Channel top back right + GAME_CH_TBR, + + /// @brief Channel top back center + GAME_CH_TBC, + + /// @brief Channel bacl left over center + GAME_CH_BLOC, + + /// @brief Channel back right over center + GAME_CH_BROC, +} GAME_AUDIO_CHANNEL; +//------------------------------------------------------------------------------ + +//============================================================================== +/// @brief **Game audio stream properties** +/// +/// Used by Kodi to pass the currently required audio stream settings to the addon +/// +typedef struct game_stream_audio_properties +{ + GAME_PCM_FORMAT format; + const GAME_AUDIO_CHANNEL* channel_map; +} ATTRIBUTE_PACKED game_stream_audio_properties; +//------------------------------------------------------------------------------ + +//============================================================================== +/// @brief **Audio stream packet** +/// +/// This packet contains audio stream data passed to Kodi. +/// +typedef struct game_stream_audio_packet +{ + /// @brief Pointer for audio stream data given to Kodi + const uint8_t *data; + + /// @brief Size of data array + size_t size; +} ATTRIBUTE_PACKED game_stream_audio_packet; +//------------------------------------------------------------------------------ + +//@} + +//--==----==----==----==----==----==----==----==----==----==----==----==----==-- +/// \defgroup cpp_kodi_addon_game_Defs_VideoStream 2. Video stream +/// \ingroup cpp_kodi_addon_game_Defs +/// @brief **The for Video stream used data system** +/// +/// Used to give Addon currently used video stream configuration on Kodi and +/// arrays to give related data to Kodi on callbacks. +/// +//@{ + +//============================================================================== +/// @brief **Pixel format** +/// +/// From Kodi requested specified video RGB color model format. +/// +typedef enum GAME_PIXEL_FORMAT +{ + GAME_PIXEL_FORMAT_UNKNOWN, + + /// @brief 0RGB8888 Format + GAME_PIXEL_FORMAT_0RGB8888, + + /// @brief RGB565 Format + GAME_PIXEL_FORMAT_RGB565, + + /// @brief 0RGB1555 Format + GAME_PIXEL_FORMAT_0RGB1555, +} GAME_PIXEL_FORMAT; +//------------------------------------------------------------------------------ + +//============================================================================== +/// @brief **Video rotation position** +/// +/// To define position how video becomes shown. +/// +typedef enum GAME_VIDEO_ROTATION +{ + /// @brief 0° and Without rotation + GAME_VIDEO_ROTATION_0, + + /// @brief rotate 90° counterclockwise + GAME_VIDEO_ROTATION_90_CCW, + + /// @brief rotate 180° counterclockwise + GAME_VIDEO_ROTATION_180_CCW, + + /// @brief rotate 270° counterclockwise + GAME_VIDEO_ROTATION_270_CCW, +} GAME_VIDEO_ROTATION; +//------------------------------------------------------------------------------ + +//============================================================================== +/// @brief **Game video stream properties** +/// +/// Used by Kodi to pass the currently required video stream settings to the addon +/// +typedef struct game_stream_video_properties +{ + /// @brief The to used pixel format + GAME_PIXEL_FORMAT format; + + /// @brief The nominal used width + unsigned int nominal_width; + + /// @brief The nominal used height + unsigned int nominal_height; + + /// @brief The maximal used width + unsigned int max_width; + + /// @brief The maximal used height + unsigned int max_height; + + /// @brief On video stream used aspect ration + /// + /// @note If aspect_ratio is <= 0.0, an aspect ratio of nominal_width / nominal_height is assumed + float aspect_ratio; +} ATTRIBUTE_PACKED game_stream_video_properties; +//------------------------------------------------------------------------------ + +//============================================================================== +/// @brief **Video stream packet** +/// +/// This packet contains video stream data passed to Kodi. +/// +typedef struct game_stream_video_packet +{ + /// @brief Video height + unsigned int width; + + /// @brief Video width + unsigned int height; + + /// @brief Width @ref GAME_VIDEO_ROTATION defined rotation angle. + GAME_VIDEO_ROTATION rotation; + + /// @brief Pointer for video stream data given to Kodi + const uint8_t *data; + + /// @brief Size of data array + size_t size; +} ATTRIBUTE_PACKED game_stream_video_packet; +//------------------------------------------------------------------------------ + +//@} + +//--==----==----==----==----==----==----==----==----==----==----==----==----==-- +/// \defgroup cpp_kodi_addon_game_Defs_HardwareFramebuffer 3. Hardware framebuffer stream +/// \ingroup cpp_kodi_addon_game_Defs +/// @brief **Hardware framebuffer stream data** +/// +//@{ + +//============================================================================== +/// @brief **Hardware framebuffer type** +/// +typedef enum GAME_HW_CONTEXT_TYPE +{ + /// @brief None context + GAME_HW_CONTEXT_NONE, + + /// @brief OpenGL 2.x. Driver can choose to use latest compatibility context + GAME_HW_CONTEXT_OPENGL, + + /// @brief OpenGL ES 2.0 + GAME_HW_CONTEXT_OPENGLES2, + + /// @brief Modern desktop core GL context. Use major/minor fields to set GL version + GAME_HW_CONTEXT_OPENGL_CORE, + + /// @brief OpenGL ES 3.0 + GAME_HW_CONTEXT_OPENGLES3, + + /// @brief OpenGL ES 3.1+. Set major/minor fields. + GAME_HW_CONTEXT_OPENGLES_VERSION, + + /// @brief Vulkan + GAME_HW_CONTEXT_VULKAN +} GAME_HW_CONTEXT_TYPE; +//------------------------------------------------------------------------------ + +//============================================================================== +/// @brief **Hardware framebuffer properties** +/// +typedef struct game_stream_hw_framebuffer_properties +{ + /// @brief The API to use. + /// + GAME_HW_CONTEXT_TYPE context_type; + + /// @brief Set if render buffers should have depth component attached. + /// + /// @todo: Obsolete + /// + bool depth; + + /// @brief Set if stencil buffers should be attached. + /// + /// If depth and stencil are true, a packed 24/8 buffer will be added. + /// Only attaching stencil is invalid and will be ignored. + /// + /// @todo: Obsolete. + /// + bool stencil; + + /// @brief Use conventional bottom-left origin convention. + /// + /// If false, standard top-left origin semantics are used. + /// + /// @todo: Move to GL specific interface + /// + bool bottom_left_origin; + + /// @brief Major version number for core GL context or GLES 3.1+. + unsigned int version_major; + + /// @brief Minor version number for core GL context or GLES 3.1+. + unsigned int version_minor; + + /// @brief If this is true, the frontend will go very far to avoid resetting context + /// in scenarios like toggling fullscreen, etc. + /// + /// @todo: Obsolete? Maybe frontend should just always assume this... + /// + /// The reset callback might still be called in extreme situations such as if + /// the context is lost beyond recovery. + /// + /// For optimal stability, set this to false, and allow context to be reset at + /// any time. + /// + bool cache_context; + + /// @brief Creates a debug context. + bool debug_context; +} ATTRIBUTE_PACKED game_stream_hw_framebuffer_properties; +//------------------------------------------------------------------------------ + +//============================================================================== +/// @brief **Hardware framebuffer buffer** +/// +typedef struct game_stream_hw_framebuffer_buffer +{ + /// @brief + uintptr_t framebuffer; +} ATTRIBUTE_PACKED game_stream_hw_framebuffer_buffer; +//------------------------------------------------------------------------------ + +//============================================================================== +/// @brief **Hardware framebuffer packet** +/// +typedef struct game_stream_hw_framebuffer_packet +{ + /// @brief + uintptr_t framebuffer; +} ATTRIBUTE_PACKED game_stream_hw_framebuffer_packet; +//------------------------------------------------------------------------------ + +//============================================================================== +/// @brief **Hardware framebuffer process function address** +/// +typedef void (*game_proc_address_t)(void); +//------------------------------------------------------------------------------ + +//@} + +//--==----==----==----==----==----==----==----==----==----==----==----==----==-- +/// \defgroup cpp_kodi_addon_game_Defs_SoftwareFramebuffer 4. Software framebuffer stream +/// \ingroup cpp_kodi_addon_game_Defs +/// @brief **Software framebuffer stream data** +/// +//@{ + +//============================================================================== +/// @brief **Game video stream properties** +/// +/// Used by Kodi to pass the currently required video stream settings to the addon +/// +typedef game_stream_video_properties game_stream_sw_framebuffer_properties; +//------------------------------------------------------------------------------ + +//============================================================================== +/// @brief **Hardware framebuffer type** +/// +typedef struct game_stream_sw_framebuffer_buffer +{ + GAME_PIXEL_FORMAT format; + uint8_t *data; + size_t size; +} ATTRIBUTE_PACKED game_stream_sw_framebuffer_buffer; +//------------------------------------------------------------------------------ + +//============================================================================== +/// @brief **Video stream packet** +/// +/// This packet contains video stream data passed to Kodi. +/// +typedef game_stream_video_packet game_stream_sw_framebuffer_packet; +//------------------------------------------------------------------------------ + +//@} + +//--==----==----==----==----==----==----==----==----==----==----==----==----==-- +/// \defgroup cpp_kodi_addon_game_Defs_StreamTypes 5. Stream types +/// \ingroup cpp_kodi_addon_game_Defs +/// @brief **Stream types data** +/// +//@{ + +//============================================================================== +/// @brief **Game stream types** +/// +typedef enum GAME_STREAM_TYPE +{ + /// @brief Unknown + GAME_STREAM_UNKNOWN, + + /// @brief Audio stream + GAME_STREAM_AUDIO, + + /// @brief Video stream + GAME_STREAM_VIDEO, + + /// @brief Hardware framebuffer + GAME_STREAM_HW_FRAMEBUFFER, + + /// @brief Software framebuffer + GAME_STREAM_SW_FRAMEBUFFER, +} GAME_STREAM_TYPE; +//------------------------------------------------------------------------------ + +//============================================================================== +/// @brief **Immutable stream metadata** +/// +/// This metadata is provided when the stream is opened. If any stream +/// properties change, a new stream must be opened. +/// +typedef struct game_stream_properties +{ + /// @brief + GAME_STREAM_TYPE type; + union + { + /// @brief + game_stream_audio_properties audio; + + /// @brief + game_stream_video_properties video; + + /// @brief + game_stream_hw_framebuffer_properties hw_framebuffer; + + /// @brief + game_stream_sw_framebuffer_properties sw_framebuffer; + }; +} ATTRIBUTE_PACKED game_stream_properties; +//------------------------------------------------------------------------------ + +//============================================================================== +/// @brief **Stream buffers for hardware rendering and zero-copy support** +/// +typedef struct game_stream_buffer +{ + /// @brief + GAME_STREAM_TYPE type; + union + { + /// @brief + game_stream_hw_framebuffer_buffer hw_framebuffer; + + /// @brief + game_stream_sw_framebuffer_buffer sw_framebuffer; + }; +} ATTRIBUTE_PACKED game_stream_buffer; +//------------------------------------------------------------------------------ + +//============================================================================== +/// @brief **Stream packet and ephemeral metadata** +/// +/// This packet contains stream data and accompanying metadata. The metadata +/// is ephemeral, meaning it only applies to the current packet and can change +/// from packet to packet in the same stream. +/// +typedef struct game_stream_packet +{ + /// @brief + GAME_STREAM_TYPE type; + union + { + /// @brief + game_stream_audio_packet audio; + + /// @brief + game_stream_video_packet video; + + /// @brief + game_stream_hw_framebuffer_packet hw_framebuffer; + + /// @brief + game_stream_sw_framebuffer_packet sw_framebuffer; + }; +} ATTRIBUTE_PACKED game_stream_packet; +//------------------------------------------------------------------------------ + +//@} + +//--==----==----==----==----==----==----==----==----==----==----==----==----==-- +/// \defgroup cpp_kodi_addon_game_Defs_GameTypes 6. Game types +/// \ingroup cpp_kodi_addon_game_Defs +/// @brief **Game types data** +/// +//@{ + +//============================================================================== +/// @brief **Game reguin definition** +/// +/// Returned from game_get_region() +typedef enum GAME_REGION +{ + /// @brief Game region unknown + GAME_REGION_UNKNOWN, + + /// @brief Game region NTSC + GAME_REGION_NTSC, + + /// @brief Game region PAL + GAME_REGION_PAL, +} GAME_REGION; +//------------------------------------------------------------------------------ + +//============================================================================== +/// @brief **Special game types passed into game_load_game_special().** +/// +/// @remark Only used when multiple ROMs are required. +/// +typedef enum SPECIAL_GAME_TYPE +{ + /// @brief Game Type BSX + SPECIAL_GAME_TYPE_BSX, + + /// @brief Game Type BSX slotted + SPECIAL_GAME_TYPE_BSX_SLOTTED, + + /// @brief Game Type sufami turbo + SPECIAL_GAME_TYPE_SUFAMI_TURBO, + + /// @brief Game Type super game boy + SPECIAL_GAME_TYPE_SUPER_GAME_BOY, +} SPECIAL_GAME_TYPE; +//------------------------------------------------------------------------------ + +//============================================================================== +/// @brief **Game Memory** +/// +typedef enum GAME_MEMORY +{ + /// @brief Passed to game_get_memory_data/size(). If the memory type doesn't apply + /// to the implementation NULL/0 can be returned. + GAME_MEMORY_MASK = 0xff, + + /// @brief Regular save ram. + /// + /// This ram is usually found on a game cartridge, backed + /// up by a battery. If save game data is too complex for a single memory + /// buffer, the SYSTEM_DIRECTORY environment callback can be used. + GAME_MEMORY_SAVE_RAM = 0, + + /// @brief Some games have a built-in clock to keep track of time. + /// + /// This memory is usually just a couple of bytes to keep track of time. + GAME_MEMORY_RTC = 1, + + /// @brief System ram lets a frontend peek into a game systems main RAM + GAME_MEMORY_SYSTEM_RAM = 2, + + /// @brief Video ram lets a frontend peek into a game systems video RAM (VRAM) + GAME_MEMORY_VIDEO_RAM = 3, + + /// @brief Special memory type + GAME_MEMORY_SNES_BSX_RAM = ((1 << 8) | GAME_MEMORY_SAVE_RAM), + + /// @brief Special memory type + GAME_MEMORY_SNES_BSX_PRAM = ((2 << 8) | GAME_MEMORY_SAVE_RAM), + + /// @brief Special memory type + GAME_MEMORY_SNES_SUFAMI_TURBO_A_RAM = ((3 << 8) | GAME_MEMORY_SAVE_RAM), + + /// @brief Special memory type + GAME_MEMORY_SNES_SUFAMI_TURBO_B_RAM = ((4 << 8) | GAME_MEMORY_SAVE_RAM), + + /// @brief Special memory type + GAME_MEMORY_SNES_GAME_BOY_RAM = ((5 << 8) | GAME_MEMORY_SAVE_RAM), + + /// @brief Special memory type + GAME_MEMORY_SNES_GAME_BOY_RTC = ((6 << 8) | GAME_MEMORY_RTC), +} GAME_MEMORY; +//------------------------------------------------------------------------------ + +//============================================================================== +/// @brief **ID values for SIMD CPU features** +typedef enum GAME_SIMD +{ + /// @brief SIMD CPU SSE + GAME_SIMD_SSE = (1 << 0), + + /// @brief SIMD CPU SSE2 + GAME_SIMD_SSE2 = (1 << 1), + + /// @brief SIMD CPU VMX + GAME_SIMD_VMX = (1 << 2), + + /// @brief SIMD CPU VMX128 + GAME_SIMD_VMX128 = (1 << 3), + + /// @brief SIMD CPU AVX + GAME_SIMD_AVX = (1 << 4), + + /// @brief SIMD CPU NEON + GAME_SIMD_NEON = (1 << 5), + + /// @brief SIMD CPU SSE3 + GAME_SIMD_SSE3 = (1 << 6), + + /// @brief SIMD CPU SSSE3 + GAME_SIMD_SSSE3 = (1 << 7), + + /// @brief SIMD CPU MMX + GAME_SIMD_MMX = (1 << 8), + + /// @brief SIMD CPU MMXEXT + GAME_SIMD_MMXEXT = (1 << 9), + + /// @brief SIMD CPU SSE4 + GAME_SIMD_SSE4 = (1 << 10), + + /// @brief SIMD CPU SSE42 + GAME_SIMD_SSE42 = (1 << 11), + + /// @brief SIMD CPU AVX2 + GAME_SIMD_AVX2 = (1 << 12), + + /// @brief SIMD CPU VFPU + GAME_SIMD_VFPU = (1 << 13), +} GAME_SIMD; +//------------------------------------------------------------------------------ + +//@} + +//--==----==----==----==----==----==----==----==----==----==----==----==----==-- +/// \defgroup cpp_kodi_addon_game_Defs_InputTypes 7. Input types +/// \ingroup cpp_kodi_addon_game_Defs +/// @brief **Input types** +/// +//@{ + +//============================================================================== +/// @brief +typedef enum GAME_INPUT_EVENT_SOURCE +{ + /// @brief + GAME_INPUT_EVENT_DIGITAL_BUTTON, + + /// @brief + GAME_INPUT_EVENT_ANALOG_BUTTON, + + /// @brief + GAME_INPUT_EVENT_AXIS, + + /// @brief + GAME_INPUT_EVENT_ANALOG_STICK, + + /// @brief + GAME_INPUT_EVENT_ACCELEROMETER, + + /// @brief + GAME_INPUT_EVENT_KEY, + + /// @brief + GAME_INPUT_EVENT_RELATIVE_POINTER, + + /// @brief + GAME_INPUT_EVENT_ABSOLUTE_POINTER, + + /// @brief + GAME_INPUT_EVENT_MOTOR, +} GAME_INPUT_EVENT_SOURCE; +//------------------------------------------------------------------------------ + +//============================================================================== +/// @brief +typedef enum GAME_KEY_MOD +{ + /// @brief + GAME_KEY_MOD_NONE = 0x0000, + + /// @brief + GAME_KEY_MOD_SHIFT = 0x0001, + + /// @brief + GAME_KEY_MOD_CTRL = 0x0002, + + /// @brief + GAME_KEY_MOD_ALT = 0x0004, + + /// @brief + GAME_KEY_MOD_META = 0x0008, + + /// @brief + GAME_KEY_MOD_SUPER = 0x0010, + + /// @brief + GAME_KEY_MOD_NUMLOCK = 0x0100, + + /// @brief + GAME_KEY_MOD_CAPSLOCK = 0x0200, + + /// @brief + GAME_KEY_MOD_SCROLLOCK = 0x0400, +} GAME_KEY_MOD; +//------------------------------------------------------------------------------ + +//============================================================================== +/// @brief Type of port on the virtual game console +typedef enum GAME_PORT_TYPE +{ + /// @brief Game port unknown + GAME_PORT_UNKNOWN, + + /// @brief Game port Keyboard + GAME_PORT_KEYBOARD, + + /// @brief Game port mouse + GAME_PORT_MOUSE, + + /// @brief Game port controller + GAME_PORT_CONTROLLER, +} GAME_PORT_TYPE; +//------------------------------------------------------------------------------ + +/*! \cond PRIVATE */ +/*! + * @brief "C" Game add-on controller layout. + * + * Structure used to interface in "C" between Kodi and Addon. + * + * See @ref AddonGameControllerLayout for description of values. + */ +typedef struct game_controller_layout +{ + char* controller_id; + bool provides_input; // False for multitaps + char** digital_buttons; + unsigned int digital_button_count; + char** analog_buttons; + unsigned int analog_button_count; + char** analog_sticks; + unsigned int analog_stick_count; + char** accelerometers; + unsigned int accelerometer_count; + char** keys; + unsigned int key_count; + char** rel_pointers; + unsigned int rel_pointer_count; + char** abs_pointers; + unsigned int abs_pointer_count; + char** motors; + unsigned int motor_count; +} ATTRIBUTE_PACKED game_controller_layout; + /*! \endcond */ + +//============================================================================== +/// @brief +struct AddonGameControllerLayout +{ + /*! \cond PRIVATE */ + explicit AddonGameControllerLayout() = default; + AddonGameControllerLayout(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 + std::string controller_id; + + /// @brief False for multitaps + bool provides_input; + + /// @brief + std::vector digital_buttons; + + /// @brief + std::vector analog_buttons; + + /// @brief + std::vector analog_sticks; + + /// @brief + std::vector accelerometers; + + /// @brief + std::vector keys; + + /// @brief + std::vector rel_pointers; + + /// @brief + std::vector abs_pointers; + + /// @brief + std::vector motors; +}; +//------------------------------------------------------------------------------ + +struct game_input_port; + +//============================================================================== +/// @brief Device that can provide input +typedef struct game_input_device +{ + /// @brief ID used in the Kodi controller API + const char* controller_id; + + /// @brief + const char* port_address; + + /// @brief + game_input_port* available_ports; + + /// @brief + unsigned int port_count; +} ATTRIBUTE_PACKED game_input_device; +//------------------------------------------------------------------------------ + +//============================================================================== +/// @brief Port that can provide input +/// +/// Ports can accept multiple devices and devices can have multiple ports, so +/// the topology of possible configurations is a tree structure of alternating +/// port and device nodes. +/// +typedef struct game_input_port +{ + /// @brief + GAME_PORT_TYPE type; + + /// @brief Required for GAME_PORT_CONTROLLER type + const char* port_id; + + /// @brief + game_input_device* accepted_devices; + + /// @brief + unsigned int device_count; +} ATTRIBUTE_PACKED game_input_port; +//------------------------------------------------------------------------------ + +//============================================================================== +/// @brief The input topology is the possible ways to connect input devices +/// +/// This represents the logical topology, which is the possible connections that +/// the game client's logic can handle. It is strictly a subset of the physical +/// topology. Loops are not allowed. +/// +typedef struct game_input_topology +{ + /// @brief The list of ports on the virtual game console + game_input_port *ports; + + /// @brief The number of ports + unsigned int port_count; + + /// @brief A limit on the number of input-providing devices, or -1 for no limit + int player_limit; +} ATTRIBUTE_PACKED game_input_topology; +//------------------------------------------------------------------------------ + +//============================================================================== +/// @brief +typedef struct game_digital_button_event +{ + /// @brief + bool pressed; +} ATTRIBUTE_PACKED game_digital_button_event; +//------------------------------------------------------------------------------ + +//============================================================================== +/// @brief +typedef struct game_analog_button_event +{ + /// @brief + float magnitude; +} ATTRIBUTE_PACKED game_analog_button_event; +//------------------------------------------------------------------------------ + +//============================================================================== +/// @brief +typedef struct game_axis_event +{ + /// @brief + float position; +} ATTRIBUTE_PACKED game_axis_event; +//------------------------------------------------------------------------------ + +//============================================================================== +/// @brief +typedef struct game_analog_stick_event +{ + /// @brief + float x; + + /// @brief + float y; +} ATTRIBUTE_PACKED game_analog_stick_event; +//------------------------------------------------------------------------------ + +//============================================================================== +/// @brief +typedef struct game_accelerometer_event +{ + /// @brief + float x; + + /// @brief + float y; + + /// @brief + float z; +} ATTRIBUTE_PACKED game_accelerometer_event; +//------------------------------------------------------------------------------ + +//============================================================================== +/// @brief +typedef struct game_key_event +{ + /// @brief + bool pressed; + + /// @brief If the keypress generates a printing character + /// + /// The unicode value contains the character generated. If the key is a + /// non-printing character, e.g. a function or arrow key, the unicode value + /// is zero. + uint32_t unicode; + + /// @brief + GAME_KEY_MOD modifiers; +} ATTRIBUTE_PACKED game_key_event; +//------------------------------------------------------------------------------ + +//============================================================================== +/// @brief +typedef struct game_rel_pointer_event +{ + /// @brief + int x; + + /// @brief + int y; +} ATTRIBUTE_PACKED game_rel_pointer_event; +//------------------------------------------------------------------------------ + +//============================================================================== +/// @brief +typedef struct game_abs_pointer_event +{ + /// @brief + bool pressed; + + /// @brief + float x; + + /// @brief + float y; +} ATTRIBUTE_PACKED game_abs_pointer_event; +//------------------------------------------------------------------------------ + +//============================================================================== +/// @brief +typedef struct game_motor_event +{ + /// @brief + float magnitude; +} ATTRIBUTE_PACKED game_motor_event; +//------------------------------------------------------------------------------ + +//============================================================================== +/// @brief +typedef struct game_input_event +{ + /// @brief + GAME_INPUT_EVENT_SOURCE type; + + /// @brief + const char* controller_id; + + /// @brief + GAME_PORT_TYPE port_type; + + /// @brief + const char* port_address; + + /// @brief + const char* feature_name; + union { + /// @brief + struct game_digital_button_event digital_button; + + /// @brief + struct game_analog_button_event analog_button; + + /// @brief + struct game_axis_event axis; + + /// @brief + struct game_analog_stick_event analog_stick; + + /// @brief + struct game_accelerometer_event accelerometer; + + /// @brief + struct game_key_event key; + + /// @brief + struct game_rel_pointer_event rel_pointer; + + /// @brief + struct game_abs_pointer_event abs_pointer; + + /// @brief + struct game_motor_event motor; + }; +} ATTRIBUTE_PACKED game_input_event; +//------------------------------------------------------------------------------ + +//@} + +//--==----==----==----==----==----==----==----==----==----==----==----==----==-- +/// \defgroup cpp_kodi_addon_game_Defs_EnvironmentTypes 8. Environment types +/// \ingroup cpp_kodi_addon_game_Defs +/// @brief **Environment types** +/// +//@{ + +//============================================================================== +/// @brief Game system timing +/// +struct game_system_timing +{ + /// @brief FPS of video content. + double fps; + + /// @brief Sampling rate of audio. + double sample_rate; +}; +//------------------------------------------------------------------------------ + +//@} + + +//--==----==----==----==----==----==----==----==----==----==----==----==----==-- + +/*! + * @brief Game properties + * + * Not to be used outside this header. + */ +typedef struct AddonProps_Game +{ + /*! + * The path of the game client being loaded. + */ + const char* game_client_dll_path; + + /*! + * Paths to proxy DLLs used to load the game client. + */ + const char** proxy_dll_paths; + + /*! + * Number of proxy DLL paths provided. + */ + unsigned int proxy_dll_count; + + /*! + * The "system" directories of the frontend. These directories can be used to + * store system-specific ROMs such as BIOSes, configuration data, etc. + */ + const char** resource_directories; + + /*! + * Number of resource directories provided + */ + unsigned int resource_directory_count; + + /*! + * 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(). + */ + const char* profile_directory; + + /*! + * The value of the property from addon.xml + */ + bool supports_vfs; + + /*! + * The extensions in the property from addon.xml + */ + const char** extensions; + + /*! + * Number of extensions provided + */ + unsigned int extension_count; +} AddonProps_Game; + +typedef AddonProps_Game game_client_properties; + +/*! Structure to transfer the methods from kodi_game_dll.h to Kodi */ + +struct AddonInstance_Game; + +/*! + * @brief Game callbacks + * + * Not to be used outside this header. + */ +typedef struct AddonToKodiFuncTable_Game +{ + KODI_HANDLE kodiInstance; + + void (*CloseGame)(void* kodiInstance); + void* (*OpenStream)(void*, const game_stream_properties*); + bool (*GetStreamBuffer)(void*, void*, unsigned int, unsigned int, game_stream_buffer*); + void (*AddStreamData)(void*, void*, const game_stream_packet*); + void (*ReleaseStreamBuffer)(void*, void*, game_stream_buffer*); + void (*CloseStream)(void*, void*); + game_proc_address_t (*HwGetProcAddress)(void* kodiInstance, const char* symbol); + bool (*InputEvent)(void* kodiInstance, const game_input_event* event); +} AddonToKodiFuncTable_Game; + +/*! + * @brief Game function hooks + * + * Not to be used outside this header. + */ +typedef struct KodiToAddonFuncTable_Game +{ + kodi::addon::CInstanceGame* addonInstance; + + GAME_ERROR(__cdecl* LoadGame)(const AddonInstance_Game*, const char*); + GAME_ERROR(__cdecl* LoadGameSpecial) + (const AddonInstance_Game*, SPECIAL_GAME_TYPE, const char**, size_t); + GAME_ERROR(__cdecl* LoadStandalone)(const AddonInstance_Game*); + GAME_ERROR(__cdecl* UnloadGame)(const AddonInstance_Game*); + GAME_ERROR(__cdecl* GetGameTiming)(const AddonInstance_Game*, game_system_timing*); + GAME_REGION(__cdecl* GetRegion)(const AddonInstance_Game*); + bool(__cdecl* RequiresGameLoop)(const AddonInstance_Game*); + GAME_ERROR(__cdecl* RunFrame)(const AddonInstance_Game*); + GAME_ERROR(__cdecl* Reset)(const AddonInstance_Game*); + GAME_ERROR(__cdecl* HwContextReset)(const AddonInstance_Game*); + GAME_ERROR(__cdecl* HwContextDestroy)(const AddonInstance_Game*); + bool(__cdecl* HasFeature)(const AddonInstance_Game*, const char*, const char*); + game_input_topology*(__cdecl* GetTopology)(const AddonInstance_Game*); + void(__cdecl* FreeTopology)(const AddonInstance_Game*, game_input_topology*); + void(__cdecl* SetControllerLayouts)(const AddonInstance_Game*, + const game_controller_layout*, + unsigned int); + bool(__cdecl* EnableKeyboard)(const AddonInstance_Game*, bool, const char*); + bool(__cdecl* EnableMouse)(const AddonInstance_Game*, bool, const char*); + bool(__cdecl* ConnectController)(const AddonInstance_Game*, bool, const char*, const char*); + bool(__cdecl* InputEvent)(const AddonInstance_Game*, const game_input_event*); + size_t(__cdecl* SerializeSize)(const AddonInstance_Game*); + GAME_ERROR(__cdecl* Serialize)(const AddonInstance_Game*, uint8_t*, size_t); + GAME_ERROR(__cdecl* Deserialize)(const AddonInstance_Game*, const uint8_t*, size_t); + GAME_ERROR(__cdecl* CheatReset)(const AddonInstance_Game*); + GAME_ERROR(__cdecl* GetMemory)(const AddonInstance_Game*, GAME_MEMORY, uint8_t**, size_t*); + GAME_ERROR(__cdecl* SetCheat)(const AddonInstance_Game*, unsigned int, bool, const char*); +} KodiToAddonFuncTable_Game; + +/*! + * @brief Game instance + * + * Not to be used outside this header. + */ +typedef struct AddonInstance_Game +{ + AddonProps_Game props; + AddonToKodiFuncTable_Game toKodi; + KodiToAddonFuncTable_Game toAddon; +} AddonInstance_Game; + +} /* extern "C" */ + +namespace kodi +{ +namespace addon +{ + +//============================================================================== +/// +/// \addtogroup cpp_kodi_addon_game +/// @brief \cpp_class{ kodi::addon::CInstanceGame } +/// **Game add-on instance** +/// +/// 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**
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**
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**
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**
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**
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**
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. + /// + //@{ + + //============================================================================ + /// + /// @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**
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: + void* m_handle = nullptr; + }; + //@} + + //@} + +//--==----==----==----==----==----==----==----==----==----==----==----==----==-- + + //============================================================================ + /// + /// @defgroup cpp_kodi_addon_game_HardwareRendering 3. Hardware rendering operations + /// @ingroup cpp_kodi_addon_game + /// @brief **Hardware rendering operations** + /// + //@{ + + //============================================================================ + /// + /// @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** + /// + //@{ + + //============================================================================ + /// + /// @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** + /// + //@{ + + //============================================================================ + /// + /// @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** + /// + //@{ + + //============================================================================ + /// + /// @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 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 instance->toAddon.addonInstance->LoadGameSpecial(type, urlList); + } + + inline static GAME_ERROR ADDON_LoadStandalone(const AddonInstance_Game* instance) + { + return instance->toAddon.addonInstance->LoadStandalone(); + } + + inline static GAME_ERROR ADDON_UnloadGame(const AddonInstance_Game* instance) + { + return instance->toAddon.addonInstance->UnloadGame(); + } + + inline static GAME_ERROR ADDON_GetGameTiming(const AddonInstance_Game* instance, + game_system_timing* timing_info) + { + return instance->toAddon.addonInstance->GetGameTiming(*timing_info); + } + + inline static GAME_REGION ADDON_GetRegion(const AddonInstance_Game* instance) + { + return instance->toAddon.addonInstance->GetRegion(); + } + + inline static bool ADDON_RequiresGameLoop(const AddonInstance_Game* instance) + { + return instance->toAddon.addonInstance->RequiresGameLoop(); + } + + inline static GAME_ERROR ADDON_RunFrame(const AddonInstance_Game* instance) + { + return instance->toAddon.addonInstance->RunFrame(); + } + + inline static GAME_ERROR ADDON_Reset(const AddonInstance_Game* instance) + { + return instance->toAddon.addonInstance->Reset(); + } + + + // --- Hardware rendering operations ------------------------------------------- + + inline static GAME_ERROR ADDON_HwContextReset(const AddonInstance_Game* instance) + { + return instance->toAddon.addonInstance->HwContextReset(); + } + + inline static GAME_ERROR ADDON_HwContextDestroy(const AddonInstance_Game* instance) + { + return instance->toAddon.addonInstance->HwContextDestroy(); + } + + + // --- Input operations -------------------------------------------------------- + + inline static bool ADDON_HasFeature(const AddonInstance_Game* instance, + const char* controller_id, + const char* feature_name) + { + return instance->toAddon.addonInstance->HasFeature(controller_id, feature_name); + } + + inline static game_input_topology* ADDON_GetTopology(const AddonInstance_Game* instance) + { + return instance->toAddon.addonInstance->GetTopology(); + } + + inline static void ADDON_FreeTopology(const AddonInstance_Game* instance, + game_input_topology* topology) + { + 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]); + + instance->toAddon.addonInstance->SetControllerLayouts(controllerList); + } + + inline static bool ADDON_EnableKeyboard(const AddonInstance_Game* instance, + bool enable, + const char* controller_id) + { + return instance->toAddon.addonInstance->EnableKeyboard(enable, controller_id); + } + + inline static bool ADDON_EnableMouse(const AddonInstance_Game* instance, + bool enable, + const char* controller_id) + { + return 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 instance->toAddon.addonInstance->ConnectController(connect, port_address, controller_id); + } + + inline static bool ADDON_InputEvent(const AddonInstance_Game* instance, + const game_input_event* event) + { + return instance->toAddon.addonInstance->InputEvent(*event); + } + + + // --- Serialization operations ------------------------------------------------ + + inline static size_t ADDON_SerializeSize(const AddonInstance_Game* instance) + { + return instance->toAddon.addonInstance->SerializeSize(); + } + + inline static GAME_ERROR ADDON_Serialize(const AddonInstance_Game* instance, + uint8_t* data, + size_t size) + { + return instance->toAddon.addonInstance->Serialize(data, size); + } + + inline static GAME_ERROR ADDON_Deserialize(const AddonInstance_Game* instance, + const uint8_t* data, + size_t size) + { + return instance->toAddon.addonInstance->Deserialize(data, size); + } + + + // --- Cheat operations -------------------------------------------------------- + + inline static GAME_ERROR ADDON_CheatReset(const AddonInstance_Game* instance) + { + return instance->toAddon.addonInstance->CheatReset(); + } + + inline static GAME_ERROR ADDON_GetMemory(const AddonInstance_Game* instance, + GAME_MEMORY type, + uint8_t** data, + size_t* size) + { + return 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 instance->toAddon.addonInstance->SetCheat(index, enabled, code); + } + + AddonInstance_Game* m_instanceData; +}; + +} /* namespace addon */ +} /* namespace kodi */ -- cgit v1.2.3