Kodi Development 22.0
for Binary and Script based Add-Ons
 
Loading...
Searching...
No Matches
Game.h
1/*
2 * Copyright (C) 2014-2025 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#include <algorithm>
15#include <functional>
16
17#ifdef __cplusplus
18
19namespace kodi
20{
21namespace addon
22{
23
24//==============================================================================
33
34//==============================================================================
39
40//==============================================================================
48{
49public:
51 explicit GameControllerLayout() = default;
52 GameControllerLayout(const game_controller_layout& layout) : controller_id(layout.controller_id)
53 {
54 provides_input = layout.provides_input;
55 for (unsigned int i = 0; i < layout.digital_button_count; ++i)
56 digital_buttons.emplace_back(layout.digital_buttons[i]);
57 for (unsigned int i = 0; i < layout.analog_button_count; ++i)
58 analog_buttons.emplace_back(layout.analog_buttons[i]);
59 for (unsigned int i = 0; i < layout.analog_stick_count; ++i)
60 analog_sticks.emplace_back(layout.analog_sticks[i]);
61 for (unsigned int i = 0; i < layout.accelerometer_count; ++i)
62 accelerometers.emplace_back(layout.accelerometers[i]);
63 for (unsigned int i = 0; i < layout.key_count; ++i)
64 keys.emplace_back(layout.keys[i]);
65 for (unsigned int i = 0; i < layout.rel_pointer_count; ++i)
66 rel_pointers.emplace_back(layout.rel_pointers[i]);
67 for (unsigned int i = 0; i < layout.abs_pointer_count; ++i)
68 abs_pointers.emplace_back(layout.abs_pointers[i]);
69 for (unsigned int i = 0; i < layout.motor_count; ++i)
70 motors.emplace_back(layout.motors[i]);
71 }
75 std::string controller_id;
76
80 bool provides_input{false};
81
83 std::vector<std::string> digital_buttons;
84
86 std::vector<std::string> analog_buttons;
87
89 std::vector<std::string> analog_sticks;
90
92 std::vector<std::string> accelerometers;
93
95 std::vector<std::string> keys;
96
98 std::vector<std::string> rel_pointers;
99
101 std::vector<std::string> abs_pointers;
102
104 std::vector<std::string> motors;
105};
107//------------------------------------------------------------------------------
108
109//==============================================================================
118class ATTR_DLL_LOCAL CInstanceGame : public IAddonInstance
119{
120public:
121 //============================================================================
127
128 //============================================================================
161 CInstanceGame() : IAddonInstance(IInstanceInfo(CPrivateBase::m_interface->firstKodiInstance))
162 {
163 if (CPrivateBase::m_interface->globalSingleInstance != nullptr)
164 {
165 throw std::logic_error(
166 "kodi::addon::CInstanceGame: Cannot create more than one game instance!");
167 }
168 SetAddonStruct(CPrivateBase::m_interface->firstKodiInstance);
169 CPrivateBase::m_interface->globalSingleInstance = this;
170 }
171 //----------------------------------------------------------------------------
172
173 //============================================================================
176 ~CInstanceGame() override = default;
177 //----------------------------------------------------------------------------
178
179 //============================================================================
187 std::string GameClientDllPath() const { return m_instanceData->props->game_client_dll_path; }
188 //----------------------------------------------------------------------------
189
190 //============================================================================
200 bool ProxyDllPaths(std::vector<std::string>& paths)
201 {
202 for (unsigned int i = 0; i < m_instanceData->props->proxy_dll_count; ++i)
203 {
204 if (m_instanceData->props->proxy_dll_paths[i] != nullptr)
205 paths.emplace_back(m_instanceData->props->proxy_dll_paths[i]);
206 }
207 return !paths.empty();
208 }
209 //----------------------------------------------------------------------------
210
211 //============================================================================
224 bool ResourceDirectories(std::vector<std::string>& dirs)
225 {
226 for (unsigned int i = 0; i < m_instanceData->props->resource_directory_count; ++i)
227 {
228 if (m_instanceData->props->resource_directories[i] != nullptr)
229 dirs.emplace_back(m_instanceData->props->resource_directories[i]);
230 }
231 return !dirs.empty();
232 }
233 //----------------------------------------------------------------------------
234
235 //============================================================================
247 std::string ProfileDirectory() const { return m_instanceData->props->profile_directory; }
248 //----------------------------------------------------------------------------
249
250 //============================================================================
258 bool SupportsVFS() const { return m_instanceData->props->supports_vfs; }
259 //----------------------------------------------------------------------------
260
261 //============================================================================
271 bool Extensions(std::vector<std::string>& extensions)
272 {
273 for (unsigned int i = 0; i < m_instanceData->props->extension_count; ++i)
274 {
275 if (m_instanceData->props->extensions[i] != nullptr)
276 extensions.emplace_back(m_instanceData->props->extensions[i]);
277 }
278 return !extensions.empty();
279 }
280 //----------------------------------------------------------------------------
281
283
284 //--==----==----==----==----==----==----==----==----==----==----==----==----==--
285
286 //============================================================================
305
306 //============================================================================
313 virtual GAME_ERROR LoadGame(const std::string& url) { return GAME_ERROR_NOT_IMPLEMENTED; }
314 //----------------------------------------------------------------------------
315
316 //============================================================================
324 virtual GAME_ERROR LoadGameSpecial(SPECIAL_GAME_TYPE type, const std::vector<std::string>& urls)
325 {
327 }
328 //----------------------------------------------------------------------------
329
330 //============================================================================
341 //----------------------------------------------------------------------------
342
343 //============================================================================
351 //----------------------------------------------------------------------------
352
353 //============================================================================
361 {
363 }
364 //----------------------------------------------------------------------------
365
366 //============================================================================
372 //----------------------------------------------------------------------------
373
374 //============================================================================
382 virtual bool RequiresGameLoop() { return false; }
383 //----------------------------------------------------------------------------
384
385 //============================================================================
391 //----------------------------------------------------------------------------
392
393 //============================================================================
399 //----------------------------------------------------------------------------
400
401 //==========================================================================
407 void CloseGame(void) { m_instanceData->toKodi->CloseGame(m_instanceData->toKodi->kodiInstance); }
408 //----------------------------------------------------------------------------
409
410 //============================================================================
433 {
434 return m_instanceData->toKodi->GetPlaybackSpeed(m_instanceData->toKodi->kodiInstance);
435 }
436 //----------------------------------------------------------------------------
437
438 //============================================================================
449 void SetGameTiming(const game_system_timing& timingInfo)
450 {
451 m_instanceData->toKodi->SetGameTiming(m_instanceData->toKodi->kodiInstance, &timingInfo);
452 }
453 //----------------------------------------------------------------------------
454
455 //============================================================================
467 {
468 public:
469 CStream() = default;
470
471 CStream(const game_stream_properties& properties) { Open(properties); }
472
473 ~CStream() { Close(); }
474
475 //==========================================================================
485 bool Open(const game_stream_properties& properties)
486 {
487 if (!CPrivateBase::m_interface->globalSingleInstance)
488 return false;
489
490 if (m_handle)
491 {
492 kodi::Log(ADDON_LOG_INFO, "kodi::addon::CInstanceGame::CStream already reopened");
493 Close();
494 }
495
497 *static_cast<CInstanceGame*>(CPrivateBase::m_interface->globalSingleInstance)
498 ->m_instanceData->toKodi;
499 m_handle = cb.OpenStream(cb.kodiInstance, &properties);
500 return m_handle != nullptr;
501 }
502 //--------------------------------------------------------------------------
503
504 //==========================================================================
510 void Close()
511 {
512 if (!m_handle || !CPrivateBase::m_interface->globalSingleInstance)
513 return;
514
516 *static_cast<CInstanceGame*>(CPrivateBase::m_interface->globalSingleInstance)
517 ->m_instanceData->toKodi;
518 cb.CloseStream(cb.kodiInstance, m_handle);
519 m_handle = nullptr;
520 }
521 //--------------------------------------------------------------------------
522
523 //==========================================================================
537 bool GetBuffer(unsigned int width, unsigned int height, game_stream_buffer& buffer)
538 {
539 if (!m_handle || !CPrivateBase::m_interface->globalSingleInstance)
540 return false;
541
543 *static_cast<CInstanceGame*>(CPrivateBase::m_interface->globalSingleInstance)
544 ->m_instanceData->toKodi;
545 return cb.GetStreamBuffer(cb.kodiInstance, m_handle, width, height, &buffer);
546 }
547 //--------------------------------------------------------------------------
548
549 //==========================================================================
557 void AddData(const game_stream_packet& packet)
558 {
559 if (!m_handle || !CPrivateBase::m_interface->globalSingleInstance)
560 return;
561
563 *static_cast<CInstanceGame*>(CPrivateBase::m_interface->globalSingleInstance)
564 ->m_instanceData->toKodi;
565 cb.AddStreamData(cb.kodiInstance, m_handle, &packet);
566 }
567 //--------------------------------------------------------------------------
568
569 //==========================================================================
578 {
579 if (!m_handle || !CPrivateBase::m_interface->globalSingleInstance)
580 return;
581
583 *static_cast<CInstanceGame*>(CPrivateBase::m_interface->globalSingleInstance)
584 ->m_instanceData->toKodi;
585 cb.ReleaseStreamBuffer(cb.kodiInstance, m_handle, &buffer);
586 }
587 //--------------------------------------------------------------------------
588
589 //==========================================================================
597 bool IsOpen() const { return m_handle != nullptr; }
598 //--------------------------------------------------------------------------
599
600 private:
601 KODI_GAME_STREAM_HANDLE m_handle = nullptr;
602 };
604
606
607 //--==----==----==----==----==----==----==----==----==----==----==----==----==--
608
609 //============================================================================
625
626 //==========================================================================
635 {
636 return m_instanceData->toKodi->EnableHardwareRendering(m_instanceData->toKodi->kodiInstance,
637 &properties);
638 }
639 //----------------------------------------------------------------------------
640
641 //============================================================================
649 //----------------------------------------------------------------------------
650
651 //============================================================================
659
660 //============================================================================
670 {
671 return m_instanceData->toKodi->HwGetProcAddress(m_instanceData->toKodi->kodiInstance, sym);
672 }
673 //----------------------------------------------------------------------------
674
676
677 //--==----==----==----==----==----==----==----==----==----==----==----==----==--
678
679 //============================================================================
695
696 //==========================================================================
707 //--------------------------------------------------------------------------
708
710
711 //--==----==----==----==----==----==----==----==----==----==----==----==----==--
712
713 //============================================================================
728
729 //============================================================================
741 virtual bool HasFeature(const std::string& controller_id, const std::string& feature_name)
742 {
743 return false;
744 }
745 //----------------------------------------------------------------------------
746
747 //============================================================================
758 virtual game_input_topology* GetTopology() { return nullptr; }
759 //----------------------------------------------------------------------------
760
761 //============================================================================
766 virtual void FreeTopology(game_input_topology* topology) {}
767 //----------------------------------------------------------------------------
768
769 //============================================================================
778 const std::vector<kodi::addon::GameControllerLayout>& controllers)
779 {
780 }
781 //----------------------------------------------------------------------------
782
783 //============================================================================
791 virtual bool EnableKeyboard(bool enable, const std::string& controller_id) { return false; }
792 //----------------------------------------------------------------------------
793
794 //============================================================================
802 virtual bool EnableMouse(bool enable, const std::string& controller_id) { return false; }
803 //--------------------------------------------------------------------------
804
805 //==========================================================================
849 virtual bool ConnectController(bool connect,
850 const std::string& port_address,
851 const std::string& controller_id)
852 {
853 return false;
854 }
855 //----------------------------------------------------------------------------
856
857 //============================================================================
864 virtual bool InputEvent(const game_input_event& event) { return false; }
865 //----------------------------------------------------------------------------
866
867 //============================================================================
880 {
881 return m_instanceData->toKodi->InputEvent(m_instanceData->toKodi->kodiInstance, &event);
882 }
883 //----------------------------------------------------------------------------
884
886
887 //--==----==----==----==----==----==----==----==----==----==----==----==----==--
888
889 //============================================================================
904
905 //============================================================================
910 virtual size_t SerializeSize() { return 0; }
911 //----------------------------------------------------------------------------
912
913 //============================================================================
921 virtual GAME_ERROR Serialize(uint8_t* data, size_t size) { return GAME_ERROR_NOT_IMPLEMENTED; }
922 //----------------------------------------------------------------------------
923
924 //============================================================================
932 virtual GAME_ERROR Deserialize(const uint8_t* data, size_t size)
933 {
935 }
936 //----------------------------------------------------------------------------
937
938 //============================================================================
947 virtual size_t AchievementStateSize() { return 0; }
948 //----------------------------------------------------------------------------
949
950 //============================================================================
959 virtual GAME_ERROR SerializeAchievements(uint8_t* data, size_t size)
960 {
962 }
963 //----------------------------------------------------------------------------
964
965 //============================================================================
981 virtual GAME_ERROR DeserializeAchievements(const uint8_t* data, size_t size)
982 {
984 }
985 //----------------------------------------------------------------------------
986
988
989 //--==----==----==----==----==----==----==----==----==----==----==----==----==--
990
991 //============================================================================
1007
1008 //============================================================================
1014 //----------------------------------------------------------------------------
1015
1016 //============================================================================
1025 virtual GAME_ERROR GetMemory(GAME_MEMORY type, uint8_t*& data, size_t& size)
1026 {
1028 }
1029 //----------------------------------------------------------------------------
1030
1031 //============================================================================
1040 virtual GAME_ERROR SetCheat(unsigned int index, bool enabled, const std::string& code)
1041 {
1043 }
1044 //============================================================================
1052 virtual GAME_ERROR SetRetroAchievementsCredentials(const std::string& username,
1053 const std::string& token)
1054 {
1056 }
1057 //============================================================================
1066 virtual GAME_ERROR ActivateAchievement(unsigned int cheevoId,
1067 const std::string& memAddrExpression)
1068 {
1070 }
1071
1072 //============================================================================
1085 const std::function<void(const std::string& achievementUrl, unsigned int cheevoId)>& callback)
1086 {
1088 }
1089 //============================================================================
1101 {
1102 m_instanceData->toKodi->RCOnGameLoaded(m_instanceData->toKodi->kodiInstance, &data);
1103 }
1104
1105 //============================================================================
1116 {
1117 m_instanceData->toKodi->RCOnAchievementTriggered(m_instanceData->toKodi->kodiInstance, &data);
1118 }
1119
1120 //============================================================================
1131 void RCOnGameCompleted(const std::string& title, bool hardcore)
1132 {
1133 m_instanceData->toKodi->RCOnGameCompleted(m_instanceData->toKodi->kodiInstance, title.c_str(),
1134 hardcore);
1135 }
1136
1137 //============================================================================
1147 void RCOnRichPresenceUpdated(const std::string& evaluation)
1148 {
1149 m_instanceData->toKodi->RCOnRichPresenceUpdated(m_instanceData->toKodi->kodiInstance,
1150 evaluation.c_str());
1151 }
1152
1153 //============================================================================
1164 {
1165 m_instanceData->toKodi->RCOnLoginResult(m_instanceData->toKodi->kodiInstance, &data);
1166 }
1167
1168 //============================================================================
1181 void RCOnAchievementProgress(const std::vector<game_rc_achievement_progress>& progress)
1182 {
1183 m_instanceData->toKodi->RCOnAchievementProgress(m_instanceData->toKodi->kodiInstance,
1184 progress.empty() ? nullptr : progress.data(),
1185 static_cast<unsigned int>(progress.size()));
1186 }
1187
1188 //============================================================================
1199 void RCOnServerError(const std::string& message, const std::string& api)
1200 {
1201 m_instanceData->toKodi->RCOnServerError(m_instanceData->toKodi->kodiInstance, message.c_str(),
1202 api.c_str());
1203 }
1204
1205 //============================================================================
1218 void RCOnConnectionChanged(bool connected)
1219 {
1220 m_instanceData->toKodi->RCOnConnectionChanged(m_instanceData->toKodi->kodiInstance, connected);
1221 }
1222
1223 //----------------------------------------------------------------------------
1224
1226
1227 //--==----==----==----==----==----==----==----==----==----==----==----==----==--
1228
1229 //============================================================================
1244
1245 //============================================================================
1253 virtual bool GetEjectState() { return false; }
1254 //----------------------------------------------------------------------------
1255
1256 //============================================================================
1266 virtual GAME_ERROR SetEjectState(bool ejected) { return GAME_ERROR_NOT_IMPLEMENTED; }
1267 //----------------------------------------------------------------------------
1268
1269 //============================================================================
1275 virtual unsigned int GetImageIndex() { return 0; }
1276 //----------------------------------------------------------------------------
1277
1278 //============================================================================
1287 virtual GAME_ERROR SetImageIndex(unsigned int imageIndex) { return GAME_ERROR_NOT_IMPLEMENTED; }
1288 //----------------------------------------------------------------------------
1289
1290 //============================================================================
1295 virtual unsigned int GetImageCount() { return 0; }
1296 //----------------------------------------------------------------------------
1297
1298 //============================================================================
1305 //----------------------------------------------------------------------------
1306
1307 //============================================================================
1317 virtual GAME_ERROR ReplaceImageIndex(unsigned int imageIndex, const std::string& filePath)
1318 {
1320 }
1321 //----------------------------------------------------------------------------
1322
1323 //============================================================================
1332 virtual GAME_ERROR RemoveImageIndex(unsigned int imageIndex)
1333 {
1335 }
1336 //----------------------------------------------------------------------------
1337
1338 //============================================================================
1347 virtual GAME_ERROR SetInitialImage(unsigned int imageIndex, const std::string& filePath)
1348 {
1350 }
1351 //----------------------------------------------------------------------------
1352
1353 //============================================================================
1360 virtual std::string GetImagePath(unsigned int imageIndex) { return ""; }
1361 //----------------------------------------------------------------------------
1362
1363 //============================================================================
1370 virtual std::string GetImageLabel(unsigned int imageIndex) { return ""; }
1371 //----------------------------------------------------------------------------
1372
1374
1375private:
1376 void SetAddonStruct(KODI_ADDON_INSTANCE_STRUCT* instance)
1377 {
1378 instance->hdl = this;
1379
1380 instance->game->toAddon->LoadGame = ADDON_LoadGame;
1381 instance->game->toAddon->LoadGameSpecial = ADDON_LoadGameSpecial;
1382 instance->game->toAddon->LoadStandalone = ADDON_LoadStandalone;
1383 instance->game->toAddon->UnloadGame = ADDON_UnloadGame;
1384 instance->game->toAddon->GetGameTiming = ADDON_GetGameTiming;
1385 instance->game->toAddon->GetRegion = ADDON_GetRegion;
1386 instance->game->toAddon->RequiresGameLoop = ADDON_RequiresGameLoop;
1387 instance->game->toAddon->RunFrame = ADDON_RunFrame;
1388 instance->game->toAddon->Reset = ADDON_Reset;
1389
1390 instance->game->toAddon->HwContextReset = ADDON_HwContextReset;
1391 instance->game->toAddon->HwContextDestroy = ADDON_HwContextDestroy;
1392
1393 instance->game->toAddon->AudioAvailable = ADDON_AudioAvailable;
1394
1395 instance->game->toAddon->HasFeature = ADDON_HasFeature;
1396 instance->game->toAddon->GetTopology = ADDON_GetTopology;
1397 instance->game->toAddon->FreeTopology = ADDON_FreeTopology;
1398 instance->game->toAddon->SetControllerLayouts = ADDON_SetControllerLayouts;
1399 instance->game->toAddon->EnableKeyboard = ADDON_EnableKeyboard;
1400 instance->game->toAddon->EnableMouse = ADDON_EnableMouse;
1401 instance->game->toAddon->ConnectController = ADDON_ConnectController;
1402 instance->game->toAddon->InputEvent = ADDON_InputEvent;
1403
1404 instance->game->toAddon->SerializeSize = ADDON_SerializeSize;
1405 instance->game->toAddon->Serialize = ADDON_Serialize;
1406 instance->game->toAddon->Deserialize = ADDON_Deserialize;
1407 instance->game->toAddon->AchievementStateSize = ADDON_AchievementStateSize;
1408 instance->game->toAddon->SerializeAchievements = ADDON_SerializeAchievements;
1409 instance->game->toAddon->DeserializeAchievements = ADDON_DeserializeAchievements;
1410
1411 instance->game->toAddon->CheatReset = ADDON_CheatReset;
1412 instance->game->toAddon->GetMemory = ADDON_GetMemory;
1413 instance->game->toAddon->SetCheat = ADDON_SetCheat;
1414
1415 instance->game->toAddon->SetRetroAchievementsCredentials =
1416 ADDON_SetRetroAchievementsCredentials;
1417 instance->game->toAddon->ActivateAchievement = ADDON_ActivateAchievement;
1418 instance->game->toAddon->GetCheevoUrlId = ADDON_GetCheevoUrlId;
1419
1420 instance->game->toAddon->GetEjectState = ADDON_GetEjectState;
1421 instance->game->toAddon->SetEjectState = ADDON_SetEjectState;
1422 instance->game->toAddon->GetImageIndex = ADDON_GetImageIndex;
1423 instance->game->toAddon->SetImageIndex = ADDON_SetImageIndex;
1424 instance->game->toAddon->GetImageCount = ADDON_GetImageCount;
1425 instance->game->toAddon->AddImageIndex = ADDON_AddImageIndex;
1426 instance->game->toAddon->ReplaceImageIndex = ADDON_ReplaceImageIndex;
1427 instance->game->toAddon->RemoveImageIndex = ADDON_RemoveImageIndex;
1428 instance->game->toAddon->SetInitialImage = ADDON_SetInitialImage;
1429 instance->game->toAddon->GetImagePath = ADDON_GetImagePath;
1430 instance->game->toAddon->GetImageLabel = ADDON_GetImageLabel;
1431
1432 instance->game->toAddon->FreeString = ADDON_FreeString;
1433
1434 m_instanceData = instance->game;
1435 m_instanceData->toAddon->addonInstance = this;
1436 }
1437
1438 // --- Game operations ---------------------------------------------------------
1439
1440 inline static GAME_ERROR ADDON_LoadGame(const AddonInstance_Game* instance, const char* url)
1441 {
1442 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->LoadGame(url);
1443 }
1444
1445 inline static GAME_ERROR ADDON_LoadGameSpecial(const AddonInstance_Game* instance,
1446 SPECIAL_GAME_TYPE type,
1447 const char** urls,
1448 size_t urlCount)
1449 {
1450 std::vector<std::string> urlList;
1451 for (size_t i = 0; i < urlCount; ++i)
1452 {
1453 if (urls[i] != nullptr)
1454 urlList.emplace_back(urls[i]);
1455 }
1456
1457 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)
1458 ->LoadGameSpecial(type, urlList);
1459 }
1460
1461 inline static GAME_ERROR ADDON_LoadStandalone(const AddonInstance_Game* instance)
1462 {
1463 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->LoadStandalone();
1464 }
1465
1466 inline static GAME_ERROR ADDON_UnloadGame(const AddonInstance_Game* instance)
1467 {
1468 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->UnloadGame();
1469 }
1470
1471 inline static GAME_ERROR ADDON_GetGameTiming(const AddonInstance_Game* instance,
1472 game_system_timing* timing_info)
1473 {
1474 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)
1475 ->GetGameTiming(*timing_info);
1476 }
1477
1478 inline static GAME_REGION ADDON_GetRegion(const AddonInstance_Game* instance)
1479 {
1480 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->GetRegion();
1481 }
1482
1483 inline static bool ADDON_RequiresGameLoop(const AddonInstance_Game* instance)
1484 {
1485 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->RequiresGameLoop();
1486 }
1487
1488 inline static GAME_ERROR ADDON_RunFrame(const AddonInstance_Game* instance)
1489 {
1490 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->RunFrame();
1491 }
1492
1493 inline static GAME_ERROR ADDON_Reset(const AddonInstance_Game* instance)
1494 {
1495 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->Reset();
1496 }
1497
1498 // --- Hardware rendering operations -------------------------------------------
1499
1500 inline static GAME_ERROR ADDON_HwContextReset(const AddonInstance_Game* instance)
1501 {
1502 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->HwContextReset();
1503 }
1504
1505 inline static GAME_ERROR ADDON_HwContextDestroy(const AddonInstance_Game* instance)
1506 {
1507 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->HwContextDestroy();
1508 }
1509
1510 // --- Audio operations --------------------------------------------------------
1511
1512 inline static GAME_ERROR ADDON_AudioAvailable(const AddonInstance_Game* instance)
1513 {
1514 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->AudioAvailable();
1515 }
1516
1517 // --- Input operations --------------------------------------------------------
1518
1519 inline static bool ADDON_HasFeature(const AddonInstance_Game* instance,
1520 const char* controller_id,
1521 const char* feature_name)
1522 {
1523 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)
1524 ->HasFeature(controller_id, feature_name);
1525 }
1526
1527 inline static game_input_topology* ADDON_GetTopology(const AddonInstance_Game* instance)
1528 {
1529 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->GetTopology();
1530 }
1531
1532 inline static void ADDON_FreeTopology(const AddonInstance_Game* instance,
1533 game_input_topology* topology)
1534 {
1535 static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->FreeTopology(topology);
1536 }
1537
1538 inline static void ADDON_SetControllerLayouts(const AddonInstance_Game* instance,
1539 const game_controller_layout* controllers,
1540 unsigned int controller_count)
1541 {
1542 if (controllers == nullptr)
1543 return;
1544
1545 std::vector<GameControllerLayout> controllerList;
1546 controllerList.reserve(controller_count);
1547 for (unsigned int i = 0; i < controller_count; ++i)
1548 controllerList.emplace_back(controllers[i]);
1549
1550 static_cast<CInstanceGame*>(instance->toAddon->addonInstance)
1551 ->SetControllerLayouts(controllerList);
1552 }
1553
1554 inline static bool ADDON_EnableKeyboard(const AddonInstance_Game* instance,
1555 bool enable,
1556 const char* controller_id)
1557 {
1558 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)
1559 ->EnableKeyboard(enable, controller_id);
1560 }
1561
1562 inline static bool ADDON_EnableMouse(const AddonInstance_Game* instance,
1563 bool enable,
1564 const char* controller_id)
1565 {
1566 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)
1567 ->EnableMouse(enable, controller_id);
1568 }
1569
1570 inline static bool ADDON_ConnectController(const AddonInstance_Game* instance,
1571 bool connect,
1572 const char* port_address,
1573 const char* controller_id)
1574 {
1575 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)
1576 ->ConnectController(connect, port_address, controller_id);
1577 }
1578
1579 inline static bool ADDON_InputEvent(const AddonInstance_Game* instance,
1580 const game_input_event* event)
1581 {
1582 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->InputEvent(*event);
1583 }
1584
1585 // --- Serialization operations ------------------------------------------------
1586
1587 inline static size_t ADDON_SerializeSize(const AddonInstance_Game* instance)
1588 {
1589 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->SerializeSize();
1590 }
1591
1592 inline static GAME_ERROR ADDON_Serialize(const AddonInstance_Game* instance,
1593 uint8_t* data,
1594 size_t size)
1595 {
1596 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->Serialize(data, size);
1597 }
1598
1599 inline static GAME_ERROR ADDON_Deserialize(const AddonInstance_Game* instance,
1600 const uint8_t* data,
1601 size_t size)
1602 {
1603 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->Deserialize(data, size);
1604 }
1605
1606 inline static size_t ADDON_AchievementStateSize(const AddonInstance_Game* instance)
1607 {
1608 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->AchievementStateSize();
1609 }
1610
1611 inline static GAME_ERROR ADDON_SerializeAchievements(const AddonInstance_Game* instance,
1612 uint8_t* data,
1613 size_t size)
1614 {
1615 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)
1616 ->SerializeAchievements(data, size);
1617 }
1618
1619 inline static GAME_ERROR ADDON_DeserializeAchievements(const AddonInstance_Game* instance,
1620 const uint8_t* data,
1621 size_t size)
1622 {
1623 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)
1624 ->DeserializeAchievements(data, size);
1625 }
1626
1627 // --- Cheat operations --------------------------------------------------------
1628
1629 inline static GAME_ERROR ADDON_CheatReset(const AddonInstance_Game* instance)
1630 {
1631 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->CheatReset();
1632 }
1633
1634 inline static GAME_ERROR ADDON_GetMemory(const AddonInstance_Game* instance,
1635 GAME_MEMORY type,
1636 uint8_t** data,
1637 size_t* size)
1638 {
1639 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)
1640 ->GetMemory(type, *data, *size);
1641 }
1642
1643 inline static GAME_ERROR ADDON_SetCheat(const AddonInstance_Game* instance,
1644 unsigned int index,
1645 bool enabled,
1646 const char* code)
1647 {
1648 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)
1649 ->SetCheat(index, enabled, code);
1650 }
1651
1652 inline static GAME_ERROR ADDON_SetRetroAchievementsCredentials(const AddonInstance_Game* instance,
1653 const char* username,
1654 const char* token)
1655 {
1656 if (username == nullptr || token == nullptr)
1658
1659 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)
1660 ->SetRetroAchievementsCredentials(username, token);
1661 }
1662
1663 inline static GAME_ERROR ADDON_ActivateAchievement(const AddonInstance_Game* instance,
1664 unsigned int cheevoId,
1665 const char* memAddrExpression)
1666 {
1667 if (memAddrExpression == nullptr)
1669
1670 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)
1671 ->ActivateAchievement(cheevoId, memAddrExpression);
1672 }
1673
1674 inline static GAME_ERROR ADDON_GetCheevoUrlId(const AddonInstance_Game* instance,
1675 void(__cdecl* callback)(const void* context,
1676 const char* achievementUrl,
1677 unsigned int cheevoId),
1678 const void* context)
1679 {
1680 if (callback == nullptr)
1682
1683 const auto cppCallback =
1684 [callback, context](const std::string& achievementUrl, unsigned int cheevoId)
1685 { callback(context, achievementUrl.c_str(), cheevoId); };
1686
1687 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)
1688 ->GetCheevoUrlId(cppCallback);
1689 }
1690
1691 inline static bool ADDON_GetEjectState(const AddonInstance_Game* instance)
1692 {
1693 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->GetEjectState();
1694 }
1695
1696 inline static GAME_ERROR ADDON_SetEjectState(const AddonInstance_Game* instance, bool ejected)
1697 {
1698 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->SetEjectState(ejected);
1699 }
1700
1701 inline static unsigned int ADDON_GetImageIndex(const AddonInstance_Game* instance)
1702 {
1703 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->GetImageIndex();
1704 }
1705
1706 inline static GAME_ERROR ADDON_SetImageIndex(const AddonInstance_Game* instance,
1707 unsigned int imageIndex)
1708 {
1709 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->SetImageIndex(imageIndex);
1710 }
1711
1712 inline static unsigned int ADDON_GetImageCount(const AddonInstance_Game* instance)
1713 {
1714 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->GetImageCount();
1715 }
1716
1717 inline static GAME_ERROR ADDON_AddImageIndex(const AddonInstance_Game* instance)
1718 {
1719 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->AddImageIndex();
1720 }
1721
1722 inline static GAME_ERROR ADDON_ReplaceImageIndex(const AddonInstance_Game* instance,
1723 unsigned int imageIndex,
1724 const char* filePath)
1725 {
1726 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)
1727 ->ReplaceImageIndex(imageIndex, filePath ? filePath : "");
1728 }
1729
1730 inline static GAME_ERROR ADDON_RemoveImageIndex(const AddonInstance_Game* instance,
1731 unsigned int imageIndex)
1732 {
1733 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)
1734 ->RemoveImageIndex(imageIndex);
1735 }
1736
1737 inline static GAME_ERROR ADDON_SetInitialImage(const AddonInstance_Game* instance,
1738 unsigned int imageIndex,
1739 const char* filePath)
1740 {
1741 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)
1742 ->SetInitialImage(imageIndex, filePath ? filePath : "");
1743 }
1744
1745 inline static char* ADDON_GetImagePath(const AddonInstance_Game* instance,
1746 unsigned int imageIndex)
1747 {
1748 std::string cppPath =
1749 static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->GetImagePath(imageIndex);
1750 if (cppPath.empty())
1751 return nullptr;
1752
1753 char* path = new char[cppPath.size() + 1];
1754 std::copy(cppPath.begin(), cppPath.end(), path);
1755 path[cppPath.size()] = '\0';
1756 return path;
1757 }
1758
1759 inline static char* ADDON_GetImageLabel(const AddonInstance_Game* instance,
1760 unsigned int imageIndex)
1761 {
1762 std::string cppLabel =
1763 static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->GetImageLabel(imageIndex);
1764 if (cppLabel.empty())
1765 return nullptr;
1766
1767 char* label = new char[cppLabel.size() + 1];
1768 std::copy(cppLabel.begin(), cppLabel.end(), label);
1769 label[cppLabel.size()] = '\0';
1770 return label;
1771 }
1772
1773 inline static void ADDON_FreeString(const AddonInstance_Game* instance, char* str)
1774 {
1775 delete[] str;
1776 }
1777
1778 AddonInstance_Game* m_instanceData;
1779};
1780
1781} /* namespace addon */
1782} /* namespace kodi */
1783
1784#endif /* __cplusplus */
Definition Game.h:119
Definition AddonBase.h:566
Definition AddonBase.h:502
@ ADDON_LOG_INFO
1 : To include information messages in the log file.
Definition addon_base.h:188
virtual GAME_ERROR AudioAvailable()
Tell the client the frontend is ready for audio.
Definition Game.h:706
CInstanceGame()
Game class constructor.
Definition Game.h:161
std::string GameClientDllPath() const
Callback to Kodi Function The path of the game client being loaded.
Definition Game.h:187
bool ProxyDllPaths(std::vector< std::string > &paths)
Callback to Kodi Function Paths to proxy DLLs used to load the game client.
Definition Game.h:200
bool ResourceDirectories(std::vector< std::string > &dirs)
Callback to Kodi Function The "system" directories of the frontend.
Definition Game.h:224
std::string ProfileDirectory() const
Callback to Kodi Function The writable directory of the frontend.
Definition Game.h:247
bool SupportsVFS() const
Callback to Kodi Function The value of the <supports_vfs> property from addon.xml.
Definition Game.h:258
~CInstanceGame() override=default
Destructor.
bool Extensions(std::vector< std::string > &extensions)
Callback to Kodi Function The extensions in the <extensions> property from addon.xml.
Definition Game.h:271
virtual GAME_ERROR ActivateAchievement(unsigned int cheevoId, const std::string &memAddrExpression)
Activate an achievement.
Definition Game.h:1066
void RCOnRichPresenceUpdated(const std::string &evaluation)
Callback to Kodi Function Publish the current rich presence evaluation to Kodi
Definition Game.h:1147
void RCOnServerError(const std::string &message, const std::string &api)
Callback to Kodi Function Report an error returned by the RetroAchievements server
Definition Game.h:1199
void RCOnAchievementProgress(const std::vector< game_rc_achievement_progress > &progress)
Callback to Kodi Function Publish progress towards the game's measured achievements
Definition Game.h:1181
void RCOnGameLoaded(const game_rc_game_loaded &data)
Callback to Kodi Function Notify Kodi that a game has been identified by the achievement runtime
Definition Game.h:1100
void RCOnLoginResult(const game_rc_login_result &data)
Callback to Kodi Function Notify Kodi of the outcome of a login attempt
Definition Game.h:1163
virtual GAME_ERROR SetRetroAchievementsCredentials(const std::string &username, const std::string &token)
Set the credentials of the RetroAchievements user.
Definition Game.h:1052
void RCOnConnectionChanged(bool connected)
Callback to Kodi Function Report a change in connectivity to the RetroAchievements server
Definition Game.h:1218
void RCOnGameCompleted(const std::string &title, bool hardcore)
Callback to Kodi Function Notify Kodi that every achievement of the game has been earned
Definition Game.h:1131
virtual GAME_ERROR GetCheevoUrlId(const std::function< void(const std::string &achievementUrl, unsigned int cheevoId)> &callback)
Get triggered achievement URL and ID pairs.
Definition Game.h:1084
void RCOnAchievementTriggered(const game_rc_achievement_triggered &data)
Callback to Kodi Function Notify Kodi that the player has earned an achievement
Definition Game.h:1115
virtual GAME_ERROR CheatReset()
Reset the cheat system.
Definition Game.h:1013
virtual GAME_ERROR GetMemory(GAME_MEMORY type, uint8_t *&data, size_t &size)
Get a region of memory.
Definition Game.h:1025
virtual GAME_ERROR SetCheat(unsigned int index, bool enabled, const std::string &code)
Set a cheat code.
Definition Game.h:1040
Game system timing.
Definition game.h:1141
GAME_REGION
Game region definition
Definition game.h:586
SPECIAL_GAME_TYPE
Special game types passed into game_load_game_special().
Definition game.h:604
GAME_MEMORY
Game Memory
Definition game.h:623
@ GAME_REGION_UNKNOWN
Game region unknown.
Definition game.h:588
void(* game_proc_address_t)(void)
Hardware framebuffer process function address
Definition game.h:426
Hardware rendering properties
Definition game.h:338
std::vector< std::string > analog_buttons
Analog buttons.
Definition Game.h:86
std::vector< std::string > accelerometers
Accelerometers.
Definition Game.h:92
bool provides_input
Provides input.
Definition Game.h:80
std::vector< std::string > digital_buttons
Digital buttons.
Definition Game.h:83
std::vector< std::string > abs_pointers
Absolute pointers.
Definition Game.h:101
std::vector< std::string > motors
Motors.
Definition Game.h:104
std::string controller_id
Controller identifier.
Definition Game.h:75
std::vector< std::string > rel_pointers
Relative pointers.
Definition Game.h:98
std::vector< std::string > keys
Keys.
Definition Game.h:95
std::vector< std::string > analog_sticks
Analog sticks.
Definition Game.h:89
"C" Game add-on controller layout.
Definition game.h:871
An input event.
Definition game.h:1080
The input topology is the possible ways to connect input devices.
Definition game.h:952
**Payload of AddonToKodiFuncTable_Game::RCOnAchievementTriggered**
Definition game.h:1252
**Payload of AddonToKodiFuncTable_Game::RCOnGameLoaded**
Definition game.h:1230
**Payload of AddonToKodiFuncTable_Game::RCOnLoginResult**
Definition game.h:1277
Stream buffers for hardware rendering and zero-copy support
Definition game.h:528
Stream packet and ephemeral metadata
Definition game.h:551
Immutable stream metadata
Definition game.h:503
GAME_ERROR
Game add-on error codes
Definition game.h:29
@ GAME_ERROR_INVALID_PARAMETERS
The parameters of the called method are invalid for this operation.
Definition game.h:43
@ GAME_ERROR_NOT_IMPLEMENTED
The method called by the frontend is not implemented.
Definition game.h:37
virtual GAME_ERROR SetImageIndex(unsigned int imageIndex)
Inserts the disk image at the given index.
Definition Game.h:1287
virtual unsigned int GetImageCount()
Gets the number of available disk images.
Definition Game.h:1295
virtual std::string GetImageLabel(unsigned int imageIndex)
Gets a user-friendly label for a disk image.
Definition Game.h:1370
virtual GAME_ERROR ReplaceImageIndex(unsigned int imageIndex, const std::string &filePath)
Replaces the disk image at the given index.
Definition Game.h:1317
virtual GAME_ERROR RemoveImageIndex(unsigned int imageIndex)
Removes the disk image at the given index.
Definition Game.h:1332
virtual std::string GetImagePath(unsigned int imageIndex)
Gets the full path of a disk image.
Definition Game.h:1360
virtual unsigned int GetImageIndex()
Gets the index of the currently inserted disk image.
Definition Game.h:1275
virtual GAME_ERROR SetInitialImage(unsigned int imageIndex, const std::string &filePath)
Sets which image should be initially inserted on load.
Definition Game.h:1347
virtual GAME_ERROR SetEjectState(bool ejected)
Opens or closes the virtual disk tray.
Definition Game.h:1266
virtual GAME_ERROR AddImageIndex()
Adds a new disk image slot.
Definition Game.h:1304
virtual bool GetEjectState()
Returns whether the virtual disk tray is currently ejected.
Definition Game.h:1253
virtual GAME_ERROR HwContextDestroy()
Called before the context is destroyed.
Definition Game.h:658
virtual GAME_ERROR HwContextReset()
Invalidates the current HW context and reinitializes GPU resources.
Definition Game.h:648
bool EnableHardwareRendering(const game_hw_rendering_properties &properties)
Callback to Kodi Function Enable hardware rendering functionality
Definition Game.h:634
game_proc_address_t HwGetProcAddress(const char *sym)
Callback to Kodi Function Get a symbol from the hardware context
Definition Game.h:669
virtual bool HasFeature(const std::string &controller_id, const std::string &feature_name)
Check if input is accepted for a feature on the controller.
Definition Game.h:741
virtual bool InputEvent(const game_input_event &event)
Notify the add-on of an input event.
Definition Game.h:864
virtual void FreeTopology(game_input_topology *topology)
Free the topology's resources.
Definition Game.h:766
virtual bool ConnectController(bool connect, const std::string &port_address, const std::string &controller_id)
Connect/disconnect a controller to a port on the virtual game console.
Definition Game.h:849
virtual void SetControllerLayouts(const std::vector< kodi::addon::GameControllerLayout > &controllers)
Set the layouts for known controllers.
Definition Game.h:777
virtual bool EnableMouse(bool enable, const std::string &controller_id)
Enable/disable mouse input using the specified controller.
Definition Game.h:802
virtual bool EnableKeyboard(bool enable, const std::string &controller_id)
Enable/disable keyboard input using the specified controller.
Definition Game.h:791
bool KodiInputEvent(const game_input_event &event)
Callback to Kodi Function Notify the port of an input event
Definition Game.h:879
virtual game_input_topology * GetTopology()
Get the input topology that specifies which controllers can be connected.
Definition Game.h:758
bool IsOpen() const
Check if the stream opened correctly, e.g. after calling the constructor.
Definition Game.h:597
void ReleaseBuffer(game_stream_buffer &buffer)
Free an allocated buffer.
Definition Game.h:577
void Close()
Free the specified stream.
Definition Game.h:510
bool GetBuffer(unsigned int width, unsigned int height, game_stream_buffer &buffer)
Get a buffer for zero-copy stream data.
Definition Game.h:537
void AddData(const game_stream_packet &packet)
Add a data packet to a stream.
Definition Game.h:557
bool Open(const game_stream_properties &properties)
Create a stream for gameplay data.
Definition Game.h:485
virtual GAME_ERROR LoadGameSpecial(SPECIAL_GAME_TYPE type, const std::vector< std::string > &urls)
Load a game that requires multiple files.
Definition Game.h:324
virtual GAME_ERROR UnloadGame()
Unload the current game.
Definition Game.h:350
void SetGameTiming(const game_system_timing &timingInfo)
Callback to Kodi Function Update the video and audio timing of the running game
Definition Game.h:449
virtual GAME_ERROR GetGameTiming(game_system_timing &timing_info)
Get timing information about the loaded game.
Definition Game.h:360
virtual GAME_ERROR RunFrame()
Run a single frame for add-ons that use a game loop.
Definition Game.h:390
virtual bool RequiresGameLoop()
Return true if the client requires the frontend to provide a game loop.
Definition Game.h:382
virtual GAME_ERROR Reset()
Reset the current game.
Definition Game.h:398
virtual GAME_ERROR LoadStandalone()
Begin playing without a game file.
Definition Game.h:340
double GetPlaybackSpeed()
Callback to Kodi Function Get the speed the game is being played back at
Definition Game.h:432
void CloseGame(void)
Callback to Kodi Function Requests the frontend to stop the current game
Definition Game.h:407
virtual GAME_ERROR LoadGame(const std::string &url)
Load a game.
Definition Game.h:313
virtual GAME_REGION GetRegion()
Get region of the loaded game.
Definition Game.h:371
virtual size_t AchievementStateSize()
How many bytes the achievement runtime's state needs right now.
Definition Game.h:947
virtual GAME_ERROR SerializeAchievements(uint8_t *data, size_t size)
Write the achievement runtime's state.
Definition Game.h:959
virtual GAME_ERROR DeserializeAchievements(const uint8_t *data, size_t size)
Restore achievement state written by SerializeAchievements()
Definition Game.h:981
virtual GAME_ERROR Deserialize(const uint8_t *data, size_t size)
Deserialize the game from the given state.
Definition Game.h:932
virtual GAME_ERROR Serialize(uint8_t *data, size_t size)
Serialize the state of the game.
Definition Game.h:921
virtual size_t SerializeSize()
Get the number of bytes required to serialize the game.
Definition Game.h:910
void ATTR_DLL_LOCAL Log(const ADDON_LOG loglevel, const char *format,...)
Add a message to Kodi's log.
Definition AddonBase.h:1939
std::string ATTR_DLL_LOCAL GetRegion(const std::string &id)
Returns your regions setting as a string for the specified id.
Definition General.h:331
Game instance.
Definition game.h:1514
Game callbacks.
Definition game.h:1406
Definition addon_base.h:269
Internal used structure to have stored C API data above and available for everything below.
Definition AddonBase.h:73