summaryrefslogtreecommitdiffstats
path: root/xbmc/addons/kodi-dev-kit/include/kodi/addon-instance/Game.h
diff options
context:
space:
mode:
Diffstat (limited to 'xbmc/addons/kodi-dev-kit/include/kodi/addon-instance/Game.h')
-rw-r--r--xbmc/addons/kodi-dev-kit/include/kodi/addon-instance/Game.h1190
1 files changed, 1190 insertions, 0 deletions
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 @@
1/*
2 * Copyright (C) 2014-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
4 *
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
8
9#pragma once
10
11#include "../AddonBase.h"
12#include "../c-api/addon-instance/game.h"
13
14#ifdef __cplusplus
15
16namespace kodi
17{
18namespace addon
19{
20
21//==============================================================================
22/// @addtogroup cpp_kodi_addon_game
23///
24/// To use on Libretro and for stand-alone games or emulators that does not use
25/// the Libretro API.
26///
27/// Possible examples could be, Nvidia GameStream via Limelight or WINE capture
28/// could possible through the Game API.
29///
30
31//==============================================================================
32/// @defgroup cpp_kodi_addon_game_Defs Definitions, structures and enumerators
33/// @ingroup cpp_kodi_addon_game
34/// @brief **Game add-on instance definition values**
35///
36
37//==============================================================================
38/// @defgroup cpp_kodi_addon_game_Defs_InputTypes_GameControllerLayout class GameControllerLayout
39/// @ingroup cpp_kodi_addon_game_Defs_InputTypes
40/// @brief Data of layouts for known controllers.
41///
42/// Used on @ref kodi::addon::CInstanceGame::SetControllerLayouts().
43///@{
44class GameControllerLayout
45{
46public:
47 /*! @cond PRIVATE */
48 explicit GameControllerLayout() = default;
49 GameControllerLayout(const game_controller_layout& layout)
50 {
51 controller_id = layout.controller_id;
52 provides_input = layout.provides_input;
53 for (unsigned int i = 0; i < layout.digital_button_count; ++i)
54 digital_buttons.push_back(layout.digital_buttons[i]);
55 for (unsigned int i = 0; i < layout.analog_button_count; ++i)
56 analog_buttons.push_back(layout.analog_buttons[i]);
57 for (unsigned int i = 0; i < layout.analog_stick_count; ++i)
58 analog_sticks.push_back(layout.analog_sticks[i]);
59 for (unsigned int i = 0; i < layout.accelerometer_count; ++i)
60 accelerometers.push_back(layout.accelerometers[i]);
61 for (unsigned int i = 0; i < layout.key_count; ++i)
62 keys.push_back(layout.keys[i]);
63 for (unsigned int i = 0; i < layout.rel_pointer_count; ++i)
64 rel_pointers.push_back(layout.rel_pointers[i]);
65 for (unsigned int i = 0; i < layout.abs_pointer_count; ++i)
66 abs_pointers.push_back(layout.abs_pointers[i]);
67 for (unsigned int i = 0; i < layout.motor_count; ++i)
68 motors.push_back(layout.motors[i]);
69 }
70 /*! @endcond */
71
72 /// @brief Controller identifier.
73 std::string controller_id;
74
75 /// @brief Provides input.
76 ///
77 /// False for multitaps
78 bool provides_input;
79
80 /// @brief Digital buttons.
81 std::vector<std::string> digital_buttons;
82
83 /// @brief Analog buttons.
84 std::vector<std::string> analog_buttons;
85
86 /// @brief Analog sticks.
87 std::vector<std::string> analog_sticks;
88
89 /// @brief Accelerometers.
90 std::vector<std::string> accelerometers;
91
92 /// @brief Keys.
93 std::vector<std::string> keys;
94
95 /// @brief Relative pointers.
96 std::vector<std::string> rel_pointers;
97
98 /// @brief Absolute pointers.
99 std::vector<std::string> abs_pointers;
100
101 /// @brief Motors.
102 std::vector<std::string> motors;
103};
104///@}
105//------------------------------------------------------------------------------
106
107//==============================================================================
108/// @addtogroup cpp_kodi_addon_game
109/// @brief @cpp_class{ kodi::addon::CInstanceGame }
110/// **Game add-on instance**\n
111/// This class provides the basic game processing system for use as an add-on in
112/// Kodi.
113///
114/// This class is created at addon by Kodi.
115///
116class ATTRIBUTE_HIDDEN CInstanceGame : public IAddonInstance
117{
118public:
119 //============================================================================
120 /// @defgroup cpp_kodi_addon_game_Base 1. Basic functions
121 /// @ingroup cpp_kodi_addon_game
122 /// @brief **Functions to manage the addon and get basic information about it**
123 ///
124 ///@{
125
126 //============================================================================
127 /// @brief Game class constructor
128 ///
129 /// Used by an add-on that only supports only Game and only in one instance.
130 ///
131 /// This class is created at addon by Kodi.
132 ///
133 ///
134 /// --------------------------------------------------------------------------
135 ///
136 ///
137 /// **Here's example about the use of this:**
138 /// ~~~~~~~~~~~~~{.cpp}
139 /// #include <kodi/addon-instance/Game.h>
140 /// ...
141 ///
142 /// class ATTRIBUTE_HIDDEN CGameExample
143 /// : public kodi::addon::CAddonBase,
144 /// public kodi::addon::CInstanceGame
145 /// {
146 /// public:
147 /// CGameExample()
148 /// {
149 /// }
150 ///
151 /// virtual ~CGameExample();
152 /// {
153 /// }
154 ///
155 /// ...
156 /// };
157 ///
158 /// ADDONCREATOR(CGameExample)
159 /// ~~~~~~~~~~~~~
160 ///
161 CInstanceGame() : IAddonInstance(ADDON_INSTANCE_GAME, GetKodiTypeVersion(ADDON_INSTANCE_GAME))
162 {
163 if (CAddonBase::m_interface->globalSingleInstance != nullptr)
164 throw std::logic_error("kodi::addon::CInstanceGame: Creation of more as one in single "
165 "instance way is not allowed!");
166
167 SetAddonStruct(CAddonBase::m_interface->firstKodiInstance);
168 CAddonBase::m_interface->globalSingleInstance = this;
169 }
170 //----------------------------------------------------------------------------
171
172 //============================================================================
173 /// @brief Destructor
174 ///
175 ~CInstanceGame() override = default;
176 //----------------------------------------------------------------------------
177
178 //============================================================================
179 /// @brief **Callback to Kodi Function**\n
180 /// The path of the game client being loaded.
181 ///
182 /// @return the used game client Dll path
183 ///
184 /// @remarks Only called from addon itself
185 ///
186 std::string GameClientDllPath() const { return m_instanceData->props->game_client_dll_path; }
187 //----------------------------------------------------------------------------
188
189 //============================================================================
190 /// @brief **Callback to Kodi Function**\n
191 /// Paths to proxy DLLs used to load the game client.
192 ///
193 /// @param[out] paths vector list to store available dll paths
194 /// @return true if success and dll paths present
195 ///
196 /// @remarks Only called from addon itself
197 ///
198 bool ProxyDllPaths(std::vector<std::string>& paths)
199 {
200 for (unsigned int i = 0; i < m_instanceData->props->proxy_dll_count; ++i)
201 {
202 if (m_instanceData->props->proxy_dll_paths[i] != nullptr)
203 paths.push_back(m_instanceData->props->proxy_dll_paths[i]);
204 }
205 return !paths.empty();
206 }
207 //----------------------------------------------------------------------------
208
209 //============================================================================
210 /// @brief **Callback to Kodi Function**\n
211 /// The "system" directories of the frontend.
212 ///
213 /// These directories can be used to store system-specific ROMs such as
214 /// BIOSes, configuration data, etc.
215 ///
216 /// @return the used resource directory
217 ///
218 /// @remarks Only called from addon itself
219 ///
220 bool ResourceDirectories(std::vector<std::string>& dirs)
221 {
222 for (unsigned int i = 0; i < m_instanceData->props->resource_directory_count; ++i)
223 {
224 if (m_instanceData->props->resource_directories[i] != nullptr)
225 dirs.push_back(m_instanceData->props->resource_directories[i]);
226 }
227 return !dirs.empty();
228 }
229 //----------------------------------------------------------------------------
230
231 //============================================================================
232 /// @brief **Callback to Kodi Function**\n
233 /// The writable directory of the frontend.
234 ///
235 /// This directory can be used to store SRAM, memory cards, high scores,
236 /// etc, if the game client cannot use the regular memory interface,
237 /// GetMemoryData().
238 ///
239 /// @return the used profile directory
240 ///
241 /// @remarks Only called from addon itself
242 ///
243 std::string ProfileDirectory() const { return m_instanceData->props->profile_directory; }
244 //----------------------------------------------------------------------------
245
246 //============================================================================
247 /// @brief **Callback to Kodi Function**\n
248 /// The value of the <supports_vfs> property from addon.xml.
249 ///
250 /// @return true if VFS is supported
251 ///
252 /// @remarks Only called from addon itself
253 ///
254 bool SupportsVFS() const { return m_instanceData->props->supports_vfs; }
255 //----------------------------------------------------------------------------
256
257 //============================================================================
258 /// @brief **Callback to Kodi Function**\n
259 /// The extensions in the <extensions> property from addon.xml.
260 ///
261 /// @param[out] extensions vector list to store available extension
262 /// @return true if success and extensions present
263 ///
264 /// @remarks Only called from addon itself
265 ///
266 bool Extensions(std::vector<std::string>& extensions)
267 {
268 for (unsigned int i = 0; i < m_instanceData->props->extension_count; ++i)
269 {
270 if (m_instanceData->props->extensions[i] != nullptr)
271 extensions.push_back(m_instanceData->props->extensions[i]);
272 }
273 return !extensions.empty();
274 }
275 //----------------------------------------------------------------------------
276
277 ///@}
278
279//--==----==----==----==----==----==----==----==----==----==----==----==----==--
280
281 //============================================================================
282 ///
283 /// @defgroup cpp_kodi_addon_game_Operation 2. Game operations
284 /// @ingroup cpp_kodi_addon_game
285 /// @brief **Game operations**
286 ///
287 /// These are mandatory functions for using this addon to get the available
288 /// channels.
289 ///
290 ///
291 ///---------------------------------------------------------------------------
292 ///
293 /// **Game operation parts in interface:**\n
294 /// Copy this to your project and extend with your parts or leave functions
295 /// complete away where not used or supported.
296 ///
297 /// @copydetails cpp_kodi_addon_game_Operation_header_addon_auto_check
298 /// @copydetails cpp_kodi_addon_game_Operation_source_addon_auto_check
299 ///
300 ///@{
301
302 //============================================================================
303 /// @brief Load a game
304 ///
305 /// @param[in] url The URL to load
306 /// @return the error, or @ref GAME_ERROR_NO_ERROR if the game was loaded
307 ///
308 virtual GAME_ERROR LoadGame(const std::string& url)
309 {
310 return GAME_ERROR_NOT_IMPLEMENTED;
311 }
312 //----------------------------------------------------------------------------
313
314 //============================================================================
315 /// @brief Load a game that requires multiple files
316 ///
317 /// @param[in] type The game type
318 /// @param[in] urls An array of urls
319 /// @return the error, or @ref GAME_ERROR_NO_ERROR if the game was loaded
320 ///
321 virtual GAME_ERROR LoadGameSpecial(SPECIAL_GAME_TYPE type, const std::vector<std::string>& urls)
322 {
323 return GAME_ERROR_NOT_IMPLEMENTED;
324 }
325 //----------------------------------------------------------------------------
326
327 //============================================================================
328 /// @brief Begin playing without a game file
329 ///
330 /// If the add-on supports standalone mode, it must add the <supports_standalone>
331 /// tag to the extension point in addon.xml:
332 ///
333 /// <supports_no_game>false</supports_no_game>
334 ///
335 /// @return the error, or @ref GAME_ERROR_NO_ERROR if the game add-on was loaded
336 ///
337 virtual GAME_ERROR LoadStandalone()
338 {
339 return GAME_ERROR_NOT_IMPLEMENTED;
340 }
341 //----------------------------------------------------------------------------
342
343 //============================================================================
344 /// @brief Unload the current game
345 ///
346 /// Unloads a currently loaded game
347 ///
348 /// @return the error, or @ref GAME_ERROR_NO_ERROR if the game was unloaded
349 ///
350 virtual GAME_ERROR UnloadGame()
351 {
352 return GAME_ERROR_NOT_IMPLEMENTED;
353 }
354 //----------------------------------------------------------------------------
355
356 //============================================================================
357 /// @brief Get timing information about the loaded game
358 ///
359 /// @param[out] timing_info The info structure to fill
360 ///
361 /// @return the error, or @ref GAME_ERROR_NO_ERROR if info was filled
362 ///
363 virtual GAME_ERROR GetGameTiming(game_system_timing& timing_info)
364 {
365 return GAME_ERROR_NOT_IMPLEMENTED;
366 }
367 //----------------------------------------------------------------------------
368
369 //============================================================================
370 /// @brief Get region of the loaded game
371 ///
372 /// @return the region, or @ref GAME_REGION_UNKNOWN if unknown or no game is loaded
373 ///
374 virtual GAME_REGION GetRegion()
375 {
376 return GAME_REGION_UNKNOWN;
377 }
378 //----------------------------------------------------------------------------
379
380 //============================================================================
381 /// @brief Return true if the client requires the frontend to provide a game loop
382 ///
383 /// The game loop is a thread that calls RunFrame() in a loop at a rate
384 /// determined by the playback speed and the client's FPS.
385 ///
386 /// @return true if the frontend should provide a game loop, false otherwise
387 ///
388 virtual bool RequiresGameLoop()
389 {
390 return false;
391 }
392 //----------------------------------------------------------------------------
393
394 //============================================================================
395 /// @brief Run a single frame for add-ons that use a game loop
396 ///
397 /// @return the error, or @ref GAME_ERROR_NO_ERROR if there was no error
398 ///
399 virtual GAME_ERROR RunFrame()
400 {
401 return GAME_ERROR_NOT_IMPLEMENTED;
402 }
403 //----------------------------------------------------------------------------
404
405 //============================================================================
406 /// @brief Reset the current game
407 ///
408 /// @return the error, or @ref GAME_ERROR_NO_ERROR if the game was reset
409 ///
410 virtual GAME_ERROR Reset()
411 {
412 return GAME_ERROR_NOT_IMPLEMENTED;
413 }
414 //----------------------------------------------------------------------------
415
416 //==========================================================================
417 /// @brief **Callback to Kodi Function**\n
418 /// Requests the frontend to stop the current game
419 ///
420 /// @remarks Only called from addon itself
421 ///
422 void CloseGame(void) { m_instanceData->toKodi->CloseGame(m_instanceData->toKodi->kodiInstance); }
423 //----------------------------------------------------------------------------
424
425 //============================================================================
426 /// @defgroup cpp_kodi_addon_game_Operation_CStream Class: CStream
427 /// @ingroup cpp_kodi_addon_game_Operation
428 /// @brief @cpp_class{ kodi::addon::CInstanceGame::CStream }
429 /// **Game stream handler**
430 ///
431 /// This class will be integrated into the addon, which can then open it if
432 /// necessary for the processing of an audio or video stream.
433 ///
434 ///
435 /// @note Callback to Kodi class
436 ///@{
437 class CStream
438 {
439 public:
440 CStream() = default;
441
442 CStream(const game_stream_properties& properties)
443 {
444 Open(properties);
445 }
446
447 ~CStream()
448 {
449 Close();
450 }
451
452 //==========================================================================
453 /// @ingroup cpp_kodi_addon_game_Operation_CStream
454 /// @brief Create a stream for gameplay data
455 ///
456 /// @param[in] properties The stream properties
457 /// @return A stream handle, or `nullptr` on failure
458 ///
459 /// @remarks Only called from addon itself
460 ///
461 bool Open(const game_stream_properties& properties)
462 {
463 if (!CAddonBase::m_interface->globalSingleInstance)
464 return false;
465
466 if (m_handle)
467 {
468 kodi::Log(ADDON_LOG_INFO, "kodi::addon::CInstanceGame::CStream already becomes reopened");
469 Close();
470 }
471
472 AddonToKodiFuncTable_Game& cb =
473 *static_cast<CInstanceGame*>(CAddonBase::m_interface->globalSingleInstance)
474 ->m_instanceData->toKodi;
475 m_handle = cb.OpenStream(cb.kodiInstance, &properties);
476 return m_handle != nullptr;
477 }
478 //--------------------------------------------------------------------------
479
480 //==========================================================================
481 /// @ingroup cpp_kodi_addon_game_Operation_CStream
482 /// @brief Free the specified stream
483 ///
484 /// @remarks Only called from addon itself
485 ///
486 void Close()
487 {
488 if (!m_handle || !CAddonBase::m_interface->globalSingleInstance)
489 return;
490
491 AddonToKodiFuncTable_Game& cb =
492 *static_cast<CInstanceGame*>(CAddonBase::m_interface->globalSingleInstance)
493 ->m_instanceData->toKodi;
494 cb.CloseStream(cb.kodiInstance, m_handle);
495 m_handle = nullptr;
496 }
497 //--------------------------------------------------------------------------
498
499 //==========================================================================
500 /// @ingroup cpp_kodi_addon_game_Operation_CStream
501 /// @brief Get a buffer for zero-copy stream data
502 ///
503 /// @param[in] width The framebuffer width, or 0 for no width specified
504 /// @param[in] height The framebuffer height, or 0 for no height specified
505 /// @param[out] buffer The buffer, or unmodified if false is returned
506 /// @return True if buffer was set, false otherwise
507 ///
508 /// @note If this returns true, buffer must be freed using @ref ReleaseBuffer().
509 ///
510 /// @remarks Only called from addon itself
511 ///
512 bool GetBuffer(unsigned int width, unsigned int height, game_stream_buffer& buffer)
513 {
514 if (!m_handle || !CAddonBase::m_interface->globalSingleInstance)
515 return false;
516
517 AddonToKodiFuncTable_Game& cb =
518 *static_cast<CInstanceGame*>(CAddonBase::m_interface->globalSingleInstance)
519 ->m_instanceData->toKodi;
520 return cb.GetStreamBuffer(cb.kodiInstance, m_handle, width, height, &buffer);
521 }
522 //--------------------------------------------------------------------------
523
524 //==========================================================================
525 /// @ingroup cpp_kodi_addon_game_Operation_CStream
526 /// @brief Add a data packet to a stream
527 ///
528 /// @param[in] packet The data packet
529 ///
530 /// @remarks Only called from addon itself
531 ///
532 void AddData(const game_stream_packet& packet)
533 {
534 if (!m_handle || !CAddonBase::m_interface->globalSingleInstance)
535 return;
536
537 AddonToKodiFuncTable_Game& cb =
538 *static_cast<CInstanceGame*>(CAddonBase::m_interface->globalSingleInstance)
539 ->m_instanceData->toKodi;
540 cb.AddStreamData(cb.kodiInstance, m_handle, &packet);
541 }
542 //--------------------------------------------------------------------------
543
544 //==========================================================================
545 /// @ingroup cpp_kodi_addon_game_Operation_CStream
546 /// @brief Free an allocated buffer
547 ///
548 /// @param[in] buffer The buffer returned from GetStreamBuffer()
549 ///
550 /// @remarks Only called from addon itself
551 ///
552 void ReleaseBuffer(game_stream_buffer& buffer)
553 {
554 if (!m_handle || !CAddonBase::m_interface->globalSingleInstance)
555 return;
556
557 AddonToKodiFuncTable_Game& cb =
558 *static_cast<CInstanceGame*>(CAddonBase::m_interface->globalSingleInstance)
559 ->m_instanceData->toKodi;
560 cb.ReleaseStreamBuffer(cb.kodiInstance, m_handle, &buffer);
561 }
562 //--------------------------------------------------------------------------
563
564 //==========================================================================
565 /// @ingroup cpp_kodi_addon_game_Operation_CStream
566 /// @brief To check stream open was OK, e.g. after use of constructor
567 ///
568 /// @return true if stream was successfully opened
569 ///
570 /// @remarks Only called from addon itself
571 ///
572 bool IsOpen() const { return m_handle != nullptr; }
573 //--------------------------------------------------------------------------
574
575 private:
576 KODI_GAME_STREAM_HANDLE m_handle = nullptr;
577 };
578 ///@}
579
580 ///@}
581
582//--==----==----==----==----==----==----==----==----==----==----==----==----==--
583
584 //============================================================================
585 ///
586 /// @defgroup cpp_kodi_addon_game_HardwareRendering 3. Hardware rendering operations
587 /// @ingroup cpp_kodi_addon_game
588 /// @brief **Hardware rendering operations**
589 ///
590 ///
591 ///---------------------------------------------------------------------------
592 ///
593 /// **Hardware rendering operation parts in interface:**\n
594 /// Copy this to your project and extend with your parts or leave functions
595 /// complete away where not used or supported.
596 ///
597 /// @copydetails cpp_kodi_addon_game_HardwareRendering_header_addon_auto_check
598 /// @copydetails cpp_kodi_addon_game_HardwareRendering_source_addon_auto_check
599 ///
600 ///@{
601
602 //============================================================================
603 /// @brief Invalidates the current HW context and reinitializes GPU resources
604 ///
605 /// Any GL state is lost, and must not be deinitialized explicitly.
606 ///
607 /// @return the error, or @ref GAME_ERROR_NO_ERROR if the HW context was reset
608 ///
609 virtual GAME_ERROR HwContextReset()
610 {
611 return GAME_ERROR_NOT_IMPLEMENTED;
612 }
613 //----------------------------------------------------------------------------
614
615 //============================================================================
616 /// @brief Called before the context is destroyed
617 ///
618 /// Resources can be deinitialized at this step.
619 ///
620 /// @return the error, or @ref GAME_ERROR_NO_ERROR if the HW context was destroyed
621 ///
622 virtual GAME_ERROR HwContextDestroy()
623 {
624 return GAME_ERROR_NOT_IMPLEMENTED;
625 }
626
627 //============================================================================
628 /// @brief **Callback to Kodi Function**<br>Get a symbol from the hardware context
629 ///
630 /// @param[in] sym The symbol's name
631 ///
632 /// @return A function pointer for the specified symbol
633 ///
634 /// @remarks Only called from addon itself
635 ///
636 game_proc_address_t HwGetProcAddress(const char* sym)
637 {
638 return m_instanceData->toKodi->HwGetProcAddress(m_instanceData->toKodi->kodiInstance, sym);
639 }
640 //----------------------------------------------------------------------------
641
642 ///@}
643
644//--==----==----==----==----==----==----==----==----==----==----==----==----==--
645
646 //============================================================================
647 /// @defgroup cpp_kodi_addon_game_InputOperations 4. Input operations
648 /// @ingroup cpp_kodi_addon_game
649 /// @brief **Input operations**
650 ///
651 ///
652 ///---------------------------------------------------------------------------
653 ///
654 /// **Hardware rendering operation parts in interface:**\n
655 /// Copy this to your project and extend with your parts or leave functions
656 /// complete away where not used or supported.
657 ///
658 /// @copydetails cpp_kodi_addon_game_InputOperations_header_addon_auto_check
659 /// @copydetails cpp_kodi_addon_game_InputOperations_source_addon_auto_check
660 ///
661 ///@{
662
663 //============================================================================
664 /// @brief Check if input is accepted for a feature on the controller
665 ///
666 /// If only a subset of the controller profile is used, this can return false
667 /// for unsupported features to not absorb their input.
668 ///
669 /// If the entire controller profile is used, this should always return true.
670 ///
671 /// @param[in] controller_id The ID of the controller profile
672 /// @param[in] feature_name The name of a feature in that profile
673 /// @return true if input is accepted for the feature, false otherwise
674 ///
675 virtual bool HasFeature(const std::string& controller_id, const std::string& feature_name)
676 {
677 return false;
678 }
679 //----------------------------------------------------------------------------
680
681 //============================================================================
682 /// @brief Get the input topology that specifies which controllers can be connected
683 ///
684 /// @return The input topology, or null to use the default
685 ///
686 /// If this returns non-null, topology must be freed using FreeTopology().
687 ///
688 /// If this returns null, the topology will default to a single port that can
689 /// accept all controllers imported by addon.xml. The port ID is set to
690 /// the @ref DEFAULT_PORT_ID constant.
691 ///
692 virtual game_input_topology* GetTopology()
693 {
694 return nullptr;
695 }
696 //----------------------------------------------------------------------------
697
698 //============================================================================
699 /// @brief Free the topology's resources
700 ///
701 /// @param[in] topology The topology returned by GetTopology()
702 ///
703 virtual void FreeTopology(game_input_topology* topology)
704 {
705 }
706 //----------------------------------------------------------------------------
707
708 //============================================================================
709 /// @brief Set the layouts for known controllers
710 ///
711 /// @param[in] controllers The controller layouts
712 ///
713 /// After loading the input topology, the frontend will call this with
714 /// controller layouts for all controllers discovered in the topology.
715 ///
716 virtual void SetControllerLayouts(const std::vector<kodi::addon::GameControllerLayout>& controllers)
717 {
718 }
719 //----------------------------------------------------------------------------
720
721 //============================================================================
722 /// @brief Enable/disable keyboard input using the specified controller
723 ///
724 /// @param[in] enable True to enable input, false otherwise
725 /// @param[in] controller_id The controller ID if enabling, or unused if disabling
726 ///
727 /// @return True if keyboard input was enabled, false otherwise
728 ///
729 virtual bool EnableKeyboard(bool enable, const std::string& controller_id)
730 {
731 return false;
732 }
733 //----------------------------------------------------------------------------
734
735 //============================================================================
736 /// @brief Enable/disable mouse input using the specified controller
737 ///
738 /// @param[in] enable True to enable input, false otherwise
739 /// @param[in] controller_id The controller ID if enabling, or unused if disabling
740 ///
741 /// @return True if mouse input was enabled, false otherwise
742 ///
743 virtual bool EnableMouse(bool enable, const std::string& controller_id)
744 {
745 return false;
746 }
747 //--------------------------------------------------------------------------
748
749 //==========================================================================
750 /// @brief Connect/disconnect a controller to a port on the virtual game console
751 ///
752 /// @param[in] connect True to connect a controller, false to disconnect
753 /// @param[in] port_address The address of the port
754 /// @param[in] controller_id The controller ID if connecting, or unused if disconnecting
755 /// @return True if the \p controller was (dis-)connected to the port, false otherwise
756 ///
757 /// The address is a string that allows traversal of the controller topology.
758 /// It is formed by alternating port IDs and controller IDs separated by "/".
759 ///
760 /// For example, assume that the topology represented in XML for Snes9x is:
761 ///
762 /// ~~~~~~~~~~~~~{.xml}
763 /// <logicaltopology>
764 /// <port type="controller" id="1">
765 /// <accepts controller="game.controller.snes"/>
766 /// <accepts controller="game.controller.snes.multitap">
767 /// <port type="controller" id="1">
768 /// <accepts controller="game.controller.snes"/>
769 /// </port>
770 /// <port type="controller" id="2">
771 /// <accepts controller="game.controller.snes"/>
772 /// </port>
773 /// ...
774 /// </accepts>
775 /// </port>
776 /// </logicaltopology>
777 /// ~~~~~~~~~~~~~
778 ///
779 /// To connect a multitap to the console's first port, the multitap's controller
780 /// info is set using the port address:
781 ///
782 /// 1
783 ///
784 /// To connect a SNES controller to the second port of the multitap, the
785 /// controller info is next set using the address:
786 ///
787 /// 1/game.controller.multitap/2
788 ///
789 /// Any attempts to connect a controller to a port on a disconnected multitap
790 /// will return false.
791 ///
792 virtual bool ConnectController(bool connect,
793 const std::string& port_address,
794 const std::string& controller_id)
795 {
796 return false;
797 }
798 //----------------------------------------------------------------------------
799
800 //============================================================================
801 /// @brief Notify the add-on of an input event
802 ///
803 /// @param[in] event The input event
804 ///
805 /// @return true if the event was handled, false otherwise
806 ///
807 virtual bool InputEvent(const game_input_event& event)
808 {
809 return false;
810 }
811 //----------------------------------------------------------------------------
812
813 //============================================================================
814 /// @brief **Callback to Kodi Function**<br>Notify the port of an input event
815 ///
816 /// @param[in] event The input event
817 /// @return true if the event was handled, false otherwise
818 ///
819 /// @note Input events can arrive for the following sources:
820 /// - @ref GAME_INPUT_EVENT_MOTOR
821 ///
822 /// @remarks Only called from addon itself
823 ///
824 bool KodiInputEvent(const game_input_event& event)
825 {
826 return m_instanceData->toKodi->InputEvent(m_instanceData->toKodi->kodiInstance, &event);
827 }
828 //----------------------------------------------------------------------------
829
830 ///@}
831
832//--==----==----==----==----==----==----==----==----==----==----==----==----==--
833
834 //============================================================================
835 /// @defgroup cpp_kodi_addon_game_SerializationOperations 5. Serialization operations
836 /// @ingroup cpp_kodi_addon_game
837 /// @brief **Serialization operations**
838 ///
839 ///
840 ///---------------------------------------------------------------------------
841 ///
842 /// **Serialization operation parts in interface:**\n
843 /// Copy this to your project and extend with your parts or leave functions
844 /// complete away where not used or supported.
845 ///
846 /// @copydetails cpp_kodi_addon_game_SerializationOperations_header_addon_auto_check
847 /// @copydetails cpp_kodi_addon_game_SerializationOperations_source_addon_auto_check
848 ///
849 ///@{
850
851 //============================================================================
852 /// @brief Get the number of bytes required to serialize the game
853 ///
854 /// @return the number of bytes, or 0 if serialization is not supported
855 ///
856 virtual size_t SerializeSize()
857 {
858 return 0;
859 }
860 //----------------------------------------------------------------------------
861
862 //============================================================================
863 /// @brief Serialize the state of the game
864 ///
865 /// @param[in] data The buffer receiving the serialized game data
866 /// @param[in] size The size of the buffer
867 ///
868 /// @return the error, or @ref GAME_ERROR_NO_ERROR if the game was serialized into the buffer
869 ///
870 virtual GAME_ERROR Serialize(uint8_t* data, size_t size)
871 {
872 return GAME_ERROR_NOT_IMPLEMENTED;
873 }
874 //----------------------------------------------------------------------------
875
876 //============================================================================
877 /// @brief Deserialize the game from the given state
878 ///
879 /// @param[in] data A buffer containing the game's new state
880 /// @param[in] size The size of the buffer
881 ///
882 /// @return the error, or @ref GAME_ERROR_NO_ERROR if the game deserialized
883 ///
884 virtual GAME_ERROR Deserialize(const uint8_t* data, size_t size)
885 {
886 return GAME_ERROR_NOT_IMPLEMENTED;
887 }
888 //----------------------------------------------------------------------------
889
890 ///@}
891
892//--==----==----==----==----==----==----==----==----==----==----==----==----==--
893
894 //============================================================================
895 /// @defgroup cpp_kodi_addon_game_CheatOperations 6. Cheat operations
896 /// @ingroup cpp_kodi_addon_game
897 /// @brief **Cheat operations**
898 ///
899 ///
900 ///---------------------------------------------------------------------------
901 ///
902 /// **Cheat operation parts in interface:**\n
903 /// Copy this to your project and extend with your parts or leave functions
904 /// complete away where not used or supported.
905 ///
906 /// @copydetails cpp_kodi_addon_game_CheatOperations_header_addon_auto_check
907 /// @copydetails cpp_kodi_addon_game_CheatOperations_source_addon_auto_check
908 ///
909 ///@{
910
911 //============================================================================
912 /// @brief Reset the cheat system
913 ///
914 /// @return the error, or @ref GAME_ERROR_NO_ERROR if the cheat system was reset
915 ///
916 virtual GAME_ERROR CheatReset()
917 {
918 return GAME_ERROR_NOT_IMPLEMENTED;
919 }
920 //----------------------------------------------------------------------------
921
922 //============================================================================
923 /// @brief Get a region of memory
924 ///
925 /// @param[in] type The type of memory to retrieve
926 /// @param[in] data Set to the region of memory; must remain valid until UnloadGame() is called
927 /// @param[in] size Set to the size of the region of memory
928 ///
929 /// @return the error, or @ref GAME_ERROR_NO_ERROR if data was set to a valid buffer
930 ///
931 virtual GAME_ERROR GetMemory(GAME_MEMORY type, uint8_t*& data, size_t& size)
932 {
933 return GAME_ERROR_NOT_IMPLEMENTED;
934 }
935 //----------------------------------------------------------------------------
936
937 //============================================================================
938 /// @brief Set a cheat code
939 ///
940 /// @param[in] index
941 /// @param[in] enabled
942 /// @param[in] code
943 ///
944 /// @return the error, or @ref GAME_ERROR_NO_ERROR if the cheat was set
945 ///
946 virtual GAME_ERROR SetCheat(unsigned int index, bool enabled, const std::string& code)
947 {
948 return GAME_ERROR_NOT_IMPLEMENTED;
949 }
950 //----------------------------------------------------------------------------
951
952 ///@}
953
954private:
955 void SetAddonStruct(KODI_HANDLE instance)
956 {
957 if (instance == nullptr)
958 throw std::logic_error("kodi::addon::CInstanceGame: Creation with empty addon structure not"
959 "allowed, table must be given from Kodi!");
960
961 m_instanceData = static_cast<AddonInstance_Game*>(instance);
962 m_instanceData->toAddon->addonInstance = this;
963
964 m_instanceData->toAddon->LoadGame = ADDON_LoadGame;
965 m_instanceData->toAddon->LoadGameSpecial = ADDON_LoadGameSpecial;
966 m_instanceData->toAddon->LoadStandalone = ADDON_LoadStandalone;
967 m_instanceData->toAddon->UnloadGame = ADDON_UnloadGame;
968 m_instanceData->toAddon->GetGameTiming = ADDON_GetGameTiming;
969 m_instanceData->toAddon->GetRegion = ADDON_GetRegion;
970 m_instanceData->toAddon->RequiresGameLoop = ADDON_RequiresGameLoop;
971 m_instanceData->toAddon->RunFrame = ADDON_RunFrame;
972 m_instanceData->toAddon->Reset = ADDON_Reset;
973
974 m_instanceData->toAddon->HwContextReset = ADDON_HwContextReset;
975 m_instanceData->toAddon->HwContextDestroy = ADDON_HwContextDestroy;
976
977 m_instanceData->toAddon->HasFeature = ADDON_HasFeature;
978 m_instanceData->toAddon->GetTopology = ADDON_GetTopology;
979 m_instanceData->toAddon->FreeTopology = ADDON_FreeTopology;
980 m_instanceData->toAddon->SetControllerLayouts = ADDON_SetControllerLayouts;
981 m_instanceData->toAddon->EnableKeyboard = ADDON_EnableKeyboard;
982 m_instanceData->toAddon->EnableMouse = ADDON_EnableMouse;
983 m_instanceData->toAddon->ConnectController = ADDON_ConnectController;
984 m_instanceData->toAddon->InputEvent = ADDON_InputEvent;
985
986 m_instanceData->toAddon->SerializeSize = ADDON_SerializeSize;
987 m_instanceData->toAddon->Serialize = ADDON_Serialize;
988 m_instanceData->toAddon->Deserialize = ADDON_Deserialize;
989
990 m_instanceData->toAddon->CheatReset = ADDON_CheatReset;
991 m_instanceData->toAddon->GetMemory = ADDON_GetMemory;
992 m_instanceData->toAddon->SetCheat = ADDON_SetCheat;
993 }
994
995 // --- Game operations ---------------------------------------------------------
996
997 inline static GAME_ERROR ADDON_LoadGame(const AddonInstance_Game* instance, const char* url)
998 {
999 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->LoadGame(url);
1000 }
1001
1002 inline static GAME_ERROR ADDON_LoadGameSpecial(const AddonInstance_Game* instance,
1003 SPECIAL_GAME_TYPE type,
1004 const char** urls,
1005 size_t urlCount)
1006 {
1007 std::vector<std::string> urlList;
1008 for (size_t i = 0; i < urlCount; ++i)
1009 {
1010 if (urls[i] != nullptr)
1011 urlList.push_back(urls[i]);
1012 }
1013
1014 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)
1015 ->LoadGameSpecial(type, urlList);
1016 }
1017
1018 inline static GAME_ERROR ADDON_LoadStandalone(const AddonInstance_Game* instance)
1019 {
1020 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->LoadStandalone();
1021 }
1022
1023 inline static GAME_ERROR ADDON_UnloadGame(const AddonInstance_Game* instance)
1024 {
1025 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->UnloadGame();
1026 }
1027
1028 inline static GAME_ERROR ADDON_GetGameTiming(const AddonInstance_Game* instance,
1029 game_system_timing* timing_info)
1030 {
1031 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)
1032 ->GetGameTiming(*timing_info);
1033 }
1034
1035 inline static GAME_REGION ADDON_GetRegion(const AddonInstance_Game* instance)
1036 {
1037 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->GetRegion();
1038 }
1039
1040 inline static bool ADDON_RequiresGameLoop(const AddonInstance_Game* instance)
1041 {
1042 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->RequiresGameLoop();
1043 }
1044
1045 inline static GAME_ERROR ADDON_RunFrame(const AddonInstance_Game* instance)
1046 {
1047 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->RunFrame();
1048 }
1049
1050 inline static GAME_ERROR ADDON_Reset(const AddonInstance_Game* instance)
1051 {
1052 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->Reset();
1053 }
1054
1055
1056 // --- Hardware rendering operations -------------------------------------------
1057
1058 inline static GAME_ERROR ADDON_HwContextReset(const AddonInstance_Game* instance)
1059 {
1060 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->HwContextReset();
1061 }
1062
1063 inline static GAME_ERROR ADDON_HwContextDestroy(const AddonInstance_Game* instance)
1064 {
1065 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->HwContextDestroy();
1066 }
1067
1068
1069 // --- Input operations --------------------------------------------------------
1070
1071 inline static bool ADDON_HasFeature(const AddonInstance_Game* instance,
1072 const char* controller_id,
1073 const char* feature_name)
1074 {
1075 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)
1076 ->HasFeature(controller_id, feature_name);
1077 }
1078
1079 inline static game_input_topology* ADDON_GetTopology(const AddonInstance_Game* instance)
1080 {
1081 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->GetTopology();
1082 }
1083
1084 inline static void ADDON_FreeTopology(const AddonInstance_Game* instance,
1085 game_input_topology* topology)
1086 {
1087 static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->FreeTopology(topology);
1088 }
1089
1090 inline static void ADDON_SetControllerLayouts(const AddonInstance_Game* instance,
1091 const game_controller_layout* controllers,
1092 unsigned int controller_count)
1093 {
1094 if (controllers == nullptr)
1095 return;
1096
1097 std::vector<GameControllerLayout> controllerList;
1098 for (unsigned int i = 0; i < controller_count; ++i)
1099 controllerList.push_back(controllers[i]);
1100
1101 static_cast<CInstanceGame*>(instance->toAddon->addonInstance)
1102 ->SetControllerLayouts(controllerList);
1103 }
1104
1105 inline static bool ADDON_EnableKeyboard(const AddonInstance_Game* instance,
1106 bool enable,
1107 const char* controller_id)
1108 {
1109 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)
1110 ->EnableKeyboard(enable, controller_id);
1111 }
1112
1113 inline static bool ADDON_EnableMouse(const AddonInstance_Game* instance,
1114 bool enable,
1115 const char* controller_id)
1116 {
1117 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)
1118 ->EnableMouse(enable, controller_id);
1119 }
1120
1121 inline static bool ADDON_ConnectController(const AddonInstance_Game* instance,
1122 bool connect,
1123 const char* port_address,
1124 const char* controller_id)
1125 {
1126 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)
1127 ->ConnectController(connect, port_address, controller_id);
1128 }
1129
1130 inline static bool ADDON_InputEvent(const AddonInstance_Game* instance,
1131 const game_input_event* event)
1132 {
1133 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->InputEvent(*event);
1134 }
1135
1136
1137 // --- Serialization operations ------------------------------------------------
1138
1139 inline static size_t ADDON_SerializeSize(const AddonInstance_Game* instance)
1140 {
1141 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->SerializeSize();
1142 }
1143
1144 inline static GAME_ERROR ADDON_Serialize(const AddonInstance_Game* instance,
1145 uint8_t* data,
1146 size_t size)
1147 {
1148 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->Serialize(data, size);
1149 }
1150
1151 inline static GAME_ERROR ADDON_Deserialize(const AddonInstance_Game* instance,
1152 const uint8_t* data,
1153 size_t size)
1154 {
1155 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->Deserialize(data, size);
1156 }
1157
1158
1159 // --- Cheat operations --------------------------------------------------------
1160
1161 inline static GAME_ERROR ADDON_CheatReset(const AddonInstance_Game* instance)
1162 {
1163 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->CheatReset();
1164 }
1165
1166 inline static GAME_ERROR ADDON_GetMemory(const AddonInstance_Game* instance,
1167 GAME_MEMORY type,
1168 uint8_t** data,
1169 size_t* size)
1170 {
1171 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)
1172 ->GetMemory(type, *data, *size);
1173 }
1174
1175 inline static GAME_ERROR ADDON_SetCheat(const AddonInstance_Game* instance,
1176 unsigned int index,
1177 bool enabled,
1178 const char* code)
1179 {
1180 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)
1181 ->SetCheat(index, enabled, code);
1182 }
1183
1184 AddonInstance_Game* m_instanceData;
1185};
1186
1187} /* namespace addon */
1188} /* namespace kodi */
1189
1190#endif /* __cplusplus */