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
16#ifdef __cplusplus
17
18namespace kodi
19{
20namespace addon
21{
22
23//==============================================================================
32
33//==============================================================================
38
39//==============================================================================
47{
48public:
50 explicit GameControllerLayout() = default;
51 GameControllerLayout(const game_controller_layout& layout) : controller_id(layout.controller_id)
52 {
53 provides_input = layout.provides_input;
54 for (unsigned int i = 0; i < layout.digital_button_count; ++i)
55 digital_buttons.emplace_back(layout.digital_buttons[i]);
56 for (unsigned int i = 0; i < layout.analog_button_count; ++i)
57 analog_buttons.emplace_back(layout.analog_buttons[i]);
58 for (unsigned int i = 0; i < layout.analog_stick_count; ++i)
59 analog_sticks.emplace_back(layout.analog_sticks[i]);
60 for (unsigned int i = 0; i < layout.accelerometer_count; ++i)
61 accelerometers.emplace_back(layout.accelerometers[i]);
62 for (unsigned int i = 0; i < layout.key_count; ++i)
63 keys.emplace_back(layout.keys[i]);
64 for (unsigned int i = 0; i < layout.rel_pointer_count; ++i)
65 rel_pointers.emplace_back(layout.rel_pointers[i]);
66 for (unsigned int i = 0; i < layout.abs_pointer_count; ++i)
67 abs_pointers.emplace_back(layout.abs_pointers[i]);
68 for (unsigned int i = 0; i < layout.motor_count; ++i)
69 motors.emplace_back(layout.motors[i]);
70 }
74 std::string controller_id;
75
79 bool provides_input{false};
80
82 std::vector<std::string> digital_buttons;
83
85 std::vector<std::string> analog_buttons;
86
88 std::vector<std::string> analog_sticks;
89
91 std::vector<std::string> accelerometers;
92
94 std::vector<std::string> keys;
95
97 std::vector<std::string> rel_pointers;
98
100 std::vector<std::string> abs_pointers;
101
103 std::vector<std::string> motors;
104};
106//------------------------------------------------------------------------------
107
108//==============================================================================
117class ATTR_DLL_LOCAL CInstanceGame : public IAddonInstance
118{
119public:
120 //============================================================================
126
127 //============================================================================
160 CInstanceGame() : IAddonInstance(IInstanceInfo(CPrivateBase::m_interface->firstKodiInstance))
161 {
162 if (CPrivateBase::m_interface->globalSingleInstance != nullptr)
163 {
164 throw std::logic_error(
165 "kodi::addon::CInstanceGame: Cannot create more than one game instance!");
166 }
167 SetAddonStruct(CPrivateBase::m_interface->firstKodiInstance);
168 CPrivateBase::m_interface->globalSingleInstance = this;
169 }
170 //----------------------------------------------------------------------------
171
172 //============================================================================
175 ~CInstanceGame() override = default;
176 //----------------------------------------------------------------------------
177
178 //============================================================================
186 std::string GameClientDllPath() const { return m_instanceData->props->game_client_dll_path; }
187 //----------------------------------------------------------------------------
188
189 //============================================================================
199 bool ProxyDllPaths(std::vector<std::string>& paths)
200 {
201 for (unsigned int i = 0; i < m_instanceData->props->proxy_dll_count; ++i)
202 {
203 if (m_instanceData->props->proxy_dll_paths[i] != nullptr)
204 paths.emplace_back(m_instanceData->props->proxy_dll_paths[i]);
205 }
206 return !paths.empty();
207 }
208 //----------------------------------------------------------------------------
209
210 //============================================================================
223 bool ResourceDirectories(std::vector<std::string>& dirs)
224 {
225 for (unsigned int i = 0; i < m_instanceData->props->resource_directory_count; ++i)
226 {
227 if (m_instanceData->props->resource_directories[i] != nullptr)
228 dirs.emplace_back(m_instanceData->props->resource_directories[i]);
229 }
230 return !dirs.empty();
231 }
232 //----------------------------------------------------------------------------
233
234 //============================================================================
246 std::string ProfileDirectory() const { return m_instanceData->props->profile_directory; }
247 //----------------------------------------------------------------------------
248
249 //============================================================================
257 bool SupportsVFS() const { return m_instanceData->props->supports_vfs; }
258 //----------------------------------------------------------------------------
259
260 //============================================================================
270 bool Extensions(std::vector<std::string>& extensions)
271 {
272 for (unsigned int i = 0; i < m_instanceData->props->extension_count; ++i)
273 {
274 if (m_instanceData->props->extensions[i] != nullptr)
275 extensions.emplace_back(m_instanceData->props->extensions[i]);
276 }
277 return !extensions.empty();
278 }
279 //----------------------------------------------------------------------------
280
282
283 //--==----==----==----==----==----==----==----==----==----==----==----==----==--
284
285 //============================================================================
304
305 //============================================================================
312 virtual GAME_ERROR LoadGame(const std::string& url) { return GAME_ERROR_NOT_IMPLEMENTED; }
313 //----------------------------------------------------------------------------
314
315 //============================================================================
323 virtual GAME_ERROR LoadGameSpecial(SPECIAL_GAME_TYPE type, const std::vector<std::string>& urls)
324 {
326 }
327 //----------------------------------------------------------------------------
328
329 //============================================================================
340 //----------------------------------------------------------------------------
341
342 //============================================================================
350 //----------------------------------------------------------------------------
351
352 //============================================================================
360 {
362 }
363 //----------------------------------------------------------------------------
364
365 //============================================================================
371 //----------------------------------------------------------------------------
372
373 //============================================================================
381 virtual bool RequiresGameLoop() { return false; }
382 //----------------------------------------------------------------------------
383
384 //============================================================================
390 //----------------------------------------------------------------------------
391
392 //============================================================================
398 //----------------------------------------------------------------------------
399
400 //==========================================================================
406 void CloseGame(void) { m_instanceData->toKodi->CloseGame(m_instanceData->toKodi->kodiInstance); }
407 //----------------------------------------------------------------------------
408
409 //============================================================================
421 {
422 public:
423 CStream() = default;
424
425 CStream(const game_stream_properties& properties) { Open(properties); }
426
427 ~CStream() { Close(); }
428
429 //==========================================================================
439 bool Open(const game_stream_properties& properties)
440 {
441 if (!CPrivateBase::m_interface->globalSingleInstance)
442 return false;
443
444 if (m_handle)
445 {
446 kodi::Log(ADDON_LOG_INFO, "kodi::addon::CInstanceGame::CStream already reopened");
447 Close();
448 }
449
451 *static_cast<CInstanceGame*>(CPrivateBase::m_interface->globalSingleInstance)
452 ->m_instanceData->toKodi;
453 m_handle = cb.OpenStream(cb.kodiInstance, &properties);
454 return m_handle != nullptr;
455 }
456 //--------------------------------------------------------------------------
457
458 //==========================================================================
464 void Close()
465 {
466 if (!m_handle || !CPrivateBase::m_interface->globalSingleInstance)
467 return;
468
470 *static_cast<CInstanceGame*>(CPrivateBase::m_interface->globalSingleInstance)
471 ->m_instanceData->toKodi;
472 cb.CloseStream(cb.kodiInstance, m_handle);
473 m_handle = nullptr;
474 }
475 //--------------------------------------------------------------------------
476
477 //==========================================================================
491 bool GetBuffer(unsigned int width, unsigned int height, game_stream_buffer& buffer)
492 {
493 if (!m_handle || !CPrivateBase::m_interface->globalSingleInstance)
494 return false;
495
497 *static_cast<CInstanceGame*>(CPrivateBase::m_interface->globalSingleInstance)
498 ->m_instanceData->toKodi;
499 return cb.GetStreamBuffer(cb.kodiInstance, m_handle, width, height, &buffer);
500 }
501 //--------------------------------------------------------------------------
502
503 //==========================================================================
511 void AddData(const game_stream_packet& packet)
512 {
513 if (!m_handle || !CPrivateBase::m_interface->globalSingleInstance)
514 return;
515
517 *static_cast<CInstanceGame*>(CPrivateBase::m_interface->globalSingleInstance)
518 ->m_instanceData->toKodi;
519 cb.AddStreamData(cb.kodiInstance, m_handle, &packet);
520 }
521 //--------------------------------------------------------------------------
522
523 //==========================================================================
532 {
533 if (!m_handle || !CPrivateBase::m_interface->globalSingleInstance)
534 return;
535
537 *static_cast<CInstanceGame*>(CPrivateBase::m_interface->globalSingleInstance)
538 ->m_instanceData->toKodi;
539 cb.ReleaseStreamBuffer(cb.kodiInstance, m_handle, &buffer);
540 }
541 //--------------------------------------------------------------------------
542
543 //==========================================================================
551 bool IsOpen() const { return m_handle != nullptr; }
552 //--------------------------------------------------------------------------
553
554 private:
555 KODI_GAME_STREAM_HANDLE m_handle = nullptr;
556 };
558
560
561 //--==----==----==----==----==----==----==----==----==----==----==----==----==--
562
563 //============================================================================
579
580 //==========================================================================
589 {
590 return m_instanceData->toKodi->EnableHardwareRendering(m_instanceData->toKodi->kodiInstance,
591 &properties);
592 }
593 //----------------------------------------------------------------------------
594
595 //============================================================================
603 //----------------------------------------------------------------------------
604
605 //============================================================================
613
614 //============================================================================
624 {
625 return m_instanceData->toKodi->HwGetProcAddress(m_instanceData->toKodi->kodiInstance, sym);
626 }
627 //----------------------------------------------------------------------------
628
630
631 //--==----==----==----==----==----==----==----==----==----==----==----==----==--
632
633 //============================================================================
648
649 //============================================================================
661 virtual bool HasFeature(const std::string& controller_id, const std::string& feature_name)
662 {
663 return false;
664 }
665 //----------------------------------------------------------------------------
666
667 //============================================================================
678 virtual game_input_topology* GetTopology() { return nullptr; }
679 //----------------------------------------------------------------------------
680
681 //============================================================================
686 virtual void FreeTopology(game_input_topology* topology) {}
687 //----------------------------------------------------------------------------
688
689 //============================================================================
698 const std::vector<kodi::addon::GameControllerLayout>& controllers)
699 {
700 }
701 //----------------------------------------------------------------------------
702
703 //============================================================================
711 virtual bool EnableKeyboard(bool enable, const std::string& controller_id) { return false; }
712 //----------------------------------------------------------------------------
713
714 //============================================================================
722 virtual bool EnableMouse(bool enable, const std::string& controller_id) { return false; }
723 //--------------------------------------------------------------------------
724
725 //==========================================================================
769 virtual bool ConnectController(bool connect,
770 const std::string& port_address,
771 const std::string& controller_id)
772 {
773 return false;
774 }
775 //----------------------------------------------------------------------------
776
777 //============================================================================
784 virtual bool InputEvent(const game_input_event& event) { return false; }
785 //----------------------------------------------------------------------------
786
787 //============================================================================
800 {
801 return m_instanceData->toKodi->InputEvent(m_instanceData->toKodi->kodiInstance, &event);
802 }
803 //----------------------------------------------------------------------------
804
806
807 //--==----==----==----==----==----==----==----==----==----==----==----==----==--
808
809 //============================================================================
824
825 //============================================================================
830 virtual size_t SerializeSize() { return 0; }
831 //----------------------------------------------------------------------------
832
833 //============================================================================
841 virtual GAME_ERROR Serialize(uint8_t* data, size_t size) { return GAME_ERROR_NOT_IMPLEMENTED; }
842 //----------------------------------------------------------------------------
843
844 //============================================================================
852 virtual GAME_ERROR Deserialize(const uint8_t* data, size_t size)
853 {
855 }
856 //----------------------------------------------------------------------------
857
859
860 //--==----==----==----==----==----==----==----==----==----==----==----==----==--
861
862 //============================================================================
878
879 //============================================================================
885 //----------------------------------------------------------------------------
886
887 //============================================================================
896 virtual GAME_ERROR GetMemory(GAME_MEMORY type, uint8_t*& data, size_t& size)
897 {
899 }
900 //----------------------------------------------------------------------------
901
902 //============================================================================
911 virtual GAME_ERROR SetCheat(unsigned int index, bool enabled, const std::string& code)
912 {
914 }
915
916 //============================================================================
928 virtual GAME_ERROR RCGenerateHashFromFile(std::string& hash,
929 unsigned int consoleID,
930 const std::string& filePath)
931 {
933 }
934
935 //============================================================================
944 virtual GAME_ERROR RCGetGameIDUrl(std::string& url, const std::string& hash)
945 {
947 }
948
949 //============================================================================
960 virtual GAME_ERROR RCGetPatchFileUrl(std::string& url,
961 const std::string& username,
962 const std::string& token,
963 unsigned int gameID)
964 {
966 }
967
968 //============================================================================
984 virtual GAME_ERROR RCPostRichPresenceUrl(std::string& url,
985 std::string& postData,
986 const std::string& username,
987 const std::string& token,
988 unsigned int gameID,
989 const std::string& richPresence)
990 {
992 }
993
994 //============================================================================
1001 virtual GAME_ERROR RCEnableRichPresence(const std::string& script)
1002 {
1004 }
1005
1006 //============================================================================
1019 virtual GAME_ERROR RCGetRichPresenceEvaluation(std::string& evaluation, unsigned int consoleID)
1020 {
1022 }
1023
1024 //============================================================================
1032
1033 //----------------------------------------------------------------------------
1034
1036
1037 //--==----==----==----==----==----==----==----==----==----==----==----==----==--
1038
1039 //============================================================================
1054
1055 //============================================================================
1063 virtual bool GetEjectState() { return false; }
1064 //----------------------------------------------------------------------------
1065
1066 //============================================================================
1076 virtual GAME_ERROR SetEjectState(bool ejected) { return GAME_ERROR_NOT_IMPLEMENTED; }
1077 //----------------------------------------------------------------------------
1078
1079 //============================================================================
1085 virtual unsigned int GetImageIndex() { return 0; }
1086 //----------------------------------------------------------------------------
1087
1088 //============================================================================
1097 virtual GAME_ERROR SetImageIndex(unsigned int imageIndex) { return GAME_ERROR_NOT_IMPLEMENTED; }
1098 //----------------------------------------------------------------------------
1099
1100 //============================================================================
1105 virtual unsigned int GetImageCount() { return 0; }
1106 //----------------------------------------------------------------------------
1107
1108 //============================================================================
1115 //----------------------------------------------------------------------------
1116
1117 //============================================================================
1127 virtual GAME_ERROR ReplaceImageIndex(unsigned int imageIndex, const std::string& filePath)
1128 {
1130 }
1131 //----------------------------------------------------------------------------
1132
1133 //============================================================================
1142 virtual GAME_ERROR RemoveImageIndex(unsigned int imageIndex)
1143 {
1145 }
1146 //----------------------------------------------------------------------------
1147
1148 //============================================================================
1157 virtual GAME_ERROR SetInitialImage(unsigned int imageIndex, const std::string& filePath)
1158 {
1160 }
1161 //----------------------------------------------------------------------------
1162
1163 //============================================================================
1170 virtual std::string GetImagePath(unsigned int imageIndex) { return ""; }
1171 //----------------------------------------------------------------------------
1172
1173 //============================================================================
1180 virtual std::string GetImageLabel(unsigned int imageIndex) { return ""; }
1181 //----------------------------------------------------------------------------
1182
1184
1185private:
1186 void SetAddonStruct(KODI_ADDON_INSTANCE_STRUCT* instance)
1187 {
1188 instance->hdl = this;
1189
1190 instance->game->toAddon->LoadGame = ADDON_LoadGame;
1191 instance->game->toAddon->LoadGameSpecial = ADDON_LoadGameSpecial;
1192 instance->game->toAddon->LoadStandalone = ADDON_LoadStandalone;
1193 instance->game->toAddon->UnloadGame = ADDON_UnloadGame;
1194 instance->game->toAddon->GetGameTiming = ADDON_GetGameTiming;
1195 instance->game->toAddon->GetRegion = ADDON_GetRegion;
1196 instance->game->toAddon->RequiresGameLoop = ADDON_RequiresGameLoop;
1197 instance->game->toAddon->RunFrame = ADDON_RunFrame;
1198 instance->game->toAddon->Reset = ADDON_Reset;
1199
1200 instance->game->toAddon->HwContextReset = ADDON_HwContextReset;
1201 instance->game->toAddon->HwContextDestroy = ADDON_HwContextDestroy;
1202
1203 instance->game->toAddon->HasFeature = ADDON_HasFeature;
1204 instance->game->toAddon->GetTopology = ADDON_GetTopology;
1205 instance->game->toAddon->FreeTopology = ADDON_FreeTopology;
1206 instance->game->toAddon->SetControllerLayouts = ADDON_SetControllerLayouts;
1207 instance->game->toAddon->EnableKeyboard = ADDON_EnableKeyboard;
1208 instance->game->toAddon->EnableMouse = ADDON_EnableMouse;
1209 instance->game->toAddon->ConnectController = ADDON_ConnectController;
1210 instance->game->toAddon->InputEvent = ADDON_InputEvent;
1211
1212 instance->game->toAddon->SerializeSize = ADDON_SerializeSize;
1213 instance->game->toAddon->Serialize = ADDON_Serialize;
1214 instance->game->toAddon->Deserialize = ADDON_Deserialize;
1215
1216 instance->game->toAddon->CheatReset = ADDON_CheatReset;
1217 instance->game->toAddon->GetMemory = ADDON_GetMemory;
1218 instance->game->toAddon->SetCheat = ADDON_SetCheat;
1219
1220 instance->game->toAddon->RCGenerateHashFromFile = ADDON_RCGenerateHashFromFile;
1221 instance->game->toAddon->RCGetGameIDUrl = ADDON_RCGetGameIDUrl;
1222 instance->game->toAddon->RCGetPatchFileUrl = ADDON_RCGetPatchFileUrl;
1223 instance->game->toAddon->RCPostRichPresenceUrl = ADDON_RCPostRichPresenceUrl;
1224 instance->game->toAddon->RCEnableRichPresence = ADDON_RCEnableRichPresence;
1225 instance->game->toAddon->RCGetRichPresenceEvaluation = ADDON_RCGetRichPresenceEvaluation;
1226 instance->game->toAddon->RCResetRuntime = ADDON_RCResetRuntime;
1227
1228 instance->game->toAddon->GetEjectState = ADDON_GetEjectState;
1229 instance->game->toAddon->SetEjectState = ADDON_SetEjectState;
1230 instance->game->toAddon->GetImageIndex = ADDON_GetImageIndex;
1231 instance->game->toAddon->SetImageIndex = ADDON_SetImageIndex;
1232 instance->game->toAddon->GetImageCount = ADDON_GetImageCount;
1233 instance->game->toAddon->AddImageIndex = ADDON_AddImageIndex;
1234 instance->game->toAddon->ReplaceImageIndex = ADDON_ReplaceImageIndex;
1235 instance->game->toAddon->RemoveImageIndex = ADDON_RemoveImageIndex;
1236 instance->game->toAddon->SetInitialImage = ADDON_SetInitialImage;
1237 instance->game->toAddon->GetImagePath = ADDON_GetImagePath;
1238 instance->game->toAddon->GetImageLabel = ADDON_GetImageLabel;
1239
1240 instance->game->toAddon->FreeString = ADDON_FreeString;
1241
1242 m_instanceData = instance->game;
1243 m_instanceData->toAddon->addonInstance = this;
1244 }
1245
1246 // --- Game operations ---------------------------------------------------------
1247
1248 inline static GAME_ERROR ADDON_LoadGame(const AddonInstance_Game* instance, const char* url)
1249 {
1250 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->LoadGame(url);
1251 }
1252
1253 inline static GAME_ERROR ADDON_LoadGameSpecial(const AddonInstance_Game* instance,
1254 SPECIAL_GAME_TYPE type,
1255 const char** urls,
1256 size_t urlCount)
1257 {
1258 std::vector<std::string> urlList;
1259 for (size_t i = 0; i < urlCount; ++i)
1260 {
1261 if (urls[i] != nullptr)
1262 urlList.emplace_back(urls[i]);
1263 }
1264
1265 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)
1266 ->LoadGameSpecial(type, urlList);
1267 }
1268
1269 inline static GAME_ERROR ADDON_LoadStandalone(const AddonInstance_Game* instance)
1270 {
1271 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->LoadStandalone();
1272 }
1273
1274 inline static GAME_ERROR ADDON_UnloadGame(const AddonInstance_Game* instance)
1275 {
1276 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->UnloadGame();
1277 }
1278
1279 inline static GAME_ERROR ADDON_GetGameTiming(const AddonInstance_Game* instance,
1280 game_system_timing* timing_info)
1281 {
1282 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)
1283 ->GetGameTiming(*timing_info);
1284 }
1285
1286 inline static GAME_REGION ADDON_GetRegion(const AddonInstance_Game* instance)
1287 {
1288 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->GetRegion();
1289 }
1290
1291 inline static bool ADDON_RequiresGameLoop(const AddonInstance_Game* instance)
1292 {
1293 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->RequiresGameLoop();
1294 }
1295
1296 inline static GAME_ERROR ADDON_RunFrame(const AddonInstance_Game* instance)
1297 {
1298 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->RunFrame();
1299 }
1300
1301 inline static GAME_ERROR ADDON_Reset(const AddonInstance_Game* instance)
1302 {
1303 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->Reset();
1304 }
1305
1306 // --- Hardware rendering operations -------------------------------------------
1307
1308 inline static GAME_ERROR ADDON_HwContextReset(const AddonInstance_Game* instance)
1309 {
1310 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->HwContextReset();
1311 }
1312
1313 inline static GAME_ERROR ADDON_HwContextDestroy(const AddonInstance_Game* instance)
1314 {
1315 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->HwContextDestroy();
1316 }
1317
1318 // --- Input operations --------------------------------------------------------
1319
1320 inline static bool ADDON_HasFeature(const AddonInstance_Game* instance,
1321 const char* controller_id,
1322 const char* feature_name)
1323 {
1324 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)
1325 ->HasFeature(controller_id, feature_name);
1326 }
1327
1328 inline static game_input_topology* ADDON_GetTopology(const AddonInstance_Game* instance)
1329 {
1330 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->GetTopology();
1331 }
1332
1333 inline static void ADDON_FreeTopology(const AddonInstance_Game* instance,
1334 game_input_topology* topology)
1335 {
1336 static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->FreeTopology(topology);
1337 }
1338
1339 inline static void ADDON_SetControllerLayouts(const AddonInstance_Game* instance,
1340 const game_controller_layout* controllers,
1341 unsigned int controller_count)
1342 {
1343 if (controllers == nullptr)
1344 return;
1345
1346 std::vector<GameControllerLayout> controllerList;
1347 controllerList.reserve(controller_count);
1348 for (unsigned int i = 0; i < controller_count; ++i)
1349 controllerList.emplace_back(controllers[i]);
1350
1351 static_cast<CInstanceGame*>(instance->toAddon->addonInstance)
1352 ->SetControllerLayouts(controllerList);
1353 }
1354
1355 inline static bool ADDON_EnableKeyboard(const AddonInstance_Game* instance,
1356 bool enable,
1357 const char* controller_id)
1358 {
1359 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)
1360 ->EnableKeyboard(enable, controller_id);
1361 }
1362
1363 inline static bool ADDON_EnableMouse(const AddonInstance_Game* instance,
1364 bool enable,
1365 const char* controller_id)
1366 {
1367 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)
1368 ->EnableMouse(enable, controller_id);
1369 }
1370
1371 inline static bool ADDON_ConnectController(const AddonInstance_Game* instance,
1372 bool connect,
1373 const char* port_address,
1374 const char* controller_id)
1375 {
1376 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)
1377 ->ConnectController(connect, port_address, controller_id);
1378 }
1379
1380 inline static bool ADDON_InputEvent(const AddonInstance_Game* instance,
1381 const game_input_event* event)
1382 {
1383 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->InputEvent(*event);
1384 }
1385
1386 // --- Serialization operations ------------------------------------------------
1387
1388 inline static size_t ADDON_SerializeSize(const AddonInstance_Game* instance)
1389 {
1390 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->SerializeSize();
1391 }
1392
1393 inline static GAME_ERROR ADDON_Serialize(const AddonInstance_Game* instance,
1394 uint8_t* data,
1395 size_t size)
1396 {
1397 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->Serialize(data, size);
1398 }
1399
1400 inline static GAME_ERROR ADDON_Deserialize(const AddonInstance_Game* instance,
1401 const uint8_t* data,
1402 size_t size)
1403 {
1404 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->Deserialize(data, size);
1405 }
1406
1407 // --- Cheat operations --------------------------------------------------------
1408
1409 inline static GAME_ERROR ADDON_CheatReset(const AddonInstance_Game* instance)
1410 {
1411 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->CheatReset();
1412 }
1413
1414 inline static GAME_ERROR ADDON_GetMemory(const AddonInstance_Game* instance,
1415 GAME_MEMORY type,
1416 uint8_t** data,
1417 size_t* size)
1418 {
1419 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)
1420 ->GetMemory(type, *data, *size);
1421 }
1422
1423 inline static GAME_ERROR ADDON_SetCheat(const AddonInstance_Game* instance,
1424 unsigned int index,
1425 bool enabled,
1426 const char* code)
1427 {
1428 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)
1429 ->SetCheat(index, enabled, code);
1430 }
1431
1432 inline static GAME_ERROR ADDON_RCGenerateHashFromFile(const AddonInstance_Game* instance,
1433 char** hash,
1434 unsigned int consoleID,
1435 const char* filePath)
1436 {
1437 std::string cppHash;
1438
1439 GAME_ERROR ret = static_cast<CInstanceGame*>(instance->toAddon->addonInstance)
1440 ->RCGenerateHashFromFile(cppHash, consoleID, filePath);
1441 if (!cppHash.empty() && hash)
1442 {
1443 *hash = new char[cppHash.size() + 1];
1444 std::copy(cppHash.begin(), cppHash.end(), *hash);
1445 (*hash)[cppHash.size()] = '\0';
1446 }
1447 return ret;
1448 }
1449
1450 inline static GAME_ERROR ADDON_RCGetGameIDUrl(const AddonInstance_Game* instance,
1451 char** url,
1452 const char* hash)
1453 {
1454 std::string cppUrl;
1455 GAME_ERROR ret =
1456 static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->RCGetGameIDUrl(cppUrl, hash);
1457 if (!cppUrl.empty() && url)
1458 {
1459 *url = new char[cppUrl.size() + 1];
1460 std::copy(cppUrl.begin(), cppUrl.end(), *url);
1461 (*url)[cppUrl.size()] = '\0';
1462 }
1463 return ret;
1464 }
1465
1466 inline static GAME_ERROR ADDON_RCGetPatchFileUrl(const AddonInstance_Game* instance,
1467 char** url,
1468 const char* username,
1469 const char* token,
1470 unsigned int gameID)
1471 {
1472 std::string cppUrl;
1473
1474 GAME_ERROR ret = static_cast<CInstanceGame*>(instance->toAddon->addonInstance)
1475 ->RCGetPatchFileUrl(cppUrl, username, token, gameID);
1476 if (!cppUrl.empty() && url)
1477 {
1478 *url = new char[cppUrl.size() + 1];
1479 std::copy(cppUrl.begin(), cppUrl.end(), *url);
1480 (*url)[cppUrl.size()] = '\0';
1481 }
1482 return ret;
1483 }
1484
1485 inline static GAME_ERROR ADDON_RCPostRichPresenceUrl(const AddonInstance_Game* instance,
1486 char** url,
1487 char** postData,
1488 const char* username,
1489 const char* token,
1490 unsigned int gameID,
1491 const char* richPresence)
1492 {
1493 std::string cppUrl;
1494 std::string cppPostData;
1495 GAME_ERROR ret =
1496 static_cast<CInstanceGame*>(instance->toAddon->addonInstance)
1497 ->RCPostRichPresenceUrl(cppUrl, cppPostData, username, token, gameID, richPresence);
1498 if (!cppUrl.empty())
1499 {
1500 *url = new char[cppUrl.size() + 1];
1501 std::copy(cppUrl.begin(), cppUrl.end(), *url);
1502 (*url)[cppUrl.size()] = '\0';
1503 }
1504 if (!cppPostData.empty())
1505 {
1506 *postData = new char[cppPostData.size() + 1];
1507 std::copy(cppPostData.begin(), cppPostData.end(), *postData);
1508 (*postData)[cppPostData.size()] = '\0';
1509 }
1510
1511 return ret;
1512 }
1513
1514 inline static GAME_ERROR ADDON_RCEnableRichPresence(const AddonInstance_Game* instance,
1515 const char* script)
1516 {
1517 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)
1518 ->RCEnableRichPresence(script);
1519 }
1520
1521 inline static GAME_ERROR ADDON_RCGetRichPresenceEvaluation(const AddonInstance_Game* instance,
1522 char** evaluation,
1523 unsigned int consoleID)
1524 {
1525 std::string cppEvaluation;
1526 GAME_ERROR ret = static_cast<CInstanceGame*>(instance->toAddon->addonInstance)
1527 ->RCGetRichPresenceEvaluation(cppEvaluation, consoleID);
1528 if (!cppEvaluation.empty())
1529 {
1530 *evaluation = new char[cppEvaluation.size() + 1];
1531 std::copy(cppEvaluation.begin(), cppEvaluation.end(), *evaluation);
1532 (*evaluation)[cppEvaluation.size()] = '\0';
1533 }
1534
1535 return ret;
1536 }
1537
1538 inline static GAME_ERROR ADDON_RCResetRuntime(const AddonInstance_Game* instance)
1539 {
1540 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->RCResetRuntime();
1541 }
1542
1543 inline static bool ADDON_GetEjectState(const AddonInstance_Game* instance)
1544 {
1545 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->GetEjectState();
1546 }
1547
1548 inline static GAME_ERROR ADDON_SetEjectState(const AddonInstance_Game* instance, bool ejected)
1549 {
1550 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->SetEjectState(ejected);
1551 }
1552
1553 inline static unsigned int ADDON_GetImageIndex(const AddonInstance_Game* instance)
1554 {
1555 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->GetImageIndex();
1556 }
1557
1558 inline static GAME_ERROR ADDON_SetImageIndex(const AddonInstance_Game* instance,
1559 unsigned int imageIndex)
1560 {
1561 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->SetImageIndex(imageIndex);
1562 }
1563
1564 inline static unsigned int ADDON_GetImageCount(const AddonInstance_Game* instance)
1565 {
1566 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->GetImageCount();
1567 }
1568
1569 inline static GAME_ERROR ADDON_AddImageIndex(const AddonInstance_Game* instance)
1570 {
1571 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->AddImageIndex();
1572 }
1573
1574 inline static GAME_ERROR ADDON_ReplaceImageIndex(const AddonInstance_Game* instance,
1575 unsigned int imageIndex,
1576 const char* filePath)
1577 {
1578 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)
1579 ->ReplaceImageIndex(imageIndex, filePath ? filePath : "");
1580 }
1581
1582 inline static GAME_ERROR ADDON_RemoveImageIndex(const AddonInstance_Game* instance,
1583 unsigned int imageIndex)
1584 {
1585 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)
1586 ->RemoveImageIndex(imageIndex);
1587 }
1588
1589 inline static GAME_ERROR ADDON_SetInitialImage(const AddonInstance_Game* instance,
1590 unsigned int imageIndex,
1591 const char* filePath)
1592 {
1593 return static_cast<CInstanceGame*>(instance->toAddon->addonInstance)
1594 ->SetInitialImage(imageIndex, filePath ? filePath : "");
1595 }
1596
1597 inline static char* ADDON_GetImagePath(const AddonInstance_Game* instance,
1598 unsigned int imageIndex)
1599 {
1600 std::string cppPath =
1601 static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->GetImagePath(imageIndex);
1602 if (cppPath.empty())
1603 return nullptr;
1604
1605 char* path = new char[cppPath.size() + 1];
1606 std::copy(cppPath.begin(), cppPath.end(), path);
1607 path[cppPath.size()] = '\0';
1608 return path;
1609 }
1610
1611 inline static char* ADDON_GetImageLabel(const AddonInstance_Game* instance,
1612 unsigned int imageIndex)
1613 {
1614 std::string cppLabel =
1615 static_cast<CInstanceGame*>(instance->toAddon->addonInstance)->GetImageLabel(imageIndex);
1616 if (cppLabel.empty())
1617 return nullptr;
1618
1619 char* label = new char[cppLabel.size() + 1];
1620 std::copy(cppLabel.begin(), cppLabel.end(), label);
1621 label[cppLabel.size()] = '\0';
1622 return label;
1623 }
1624
1625 inline static void ADDON_FreeString(const AddonInstance_Game* instance, char* str)
1626 {
1627 delete[] str;
1628 }
1629
1630 AddonInstance_Game* m_instanceData;
1631};
1632
1633} /* namespace addon */
1634} /* namespace kodi */
1635
1636#endif /* __cplusplus */
Definition Game.h:118
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
CInstanceGame()
Game class constructor.
Definition Game.h:160
std::string GameClientDllPath() const
Callback to Kodi Function The path of the game client being loaded.
Definition Game.h:186
bool ProxyDllPaths(std::vector< std::string > &paths)
Callback to Kodi Function Paths to proxy DLLs used to load the game client.
Definition Game.h:199
bool ResourceDirectories(std::vector< std::string > &dirs)
Callback to Kodi Function The "system" directories of the frontend.
Definition Game.h:223
std::string ProfileDirectory() const
Callback to Kodi Function The writable directory of the frontend.
Definition Game.h:246
bool SupportsVFS() const
Callback to Kodi Function The value of the <supports_vfs> property from addon.xml.
Definition Game.h:257
~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:270
virtual GAME_ERROR RCGetRichPresenceEvaluation(std::string &evaluation, unsigned int consoleID)
Gets the rich presence evaluation for the current frame. Rich presence must be enabled first or this ...
Definition Game.h:1019
virtual GAME_ERROR RCGetPatchFileUrl(std::string &url, const std::string &username, const std::string &token, unsigned int gameID)
Gets a URL to the endpoint that returns the patch file.
Definition Game.h:960
virtual GAME_ERROR RCGenerateHashFromFile(std::string &hash, unsigned int consoleID, const std::string &filePath)
Generates a RetroAchievements hash for a given game that can be used to identify the game by RetroAch...
Definition Game.h:928
virtual GAME_ERROR RCPostRichPresenceUrl(std::string &url, std::string &postData, const std::string &username, const std::string &token, unsigned int gameID, const std::string &richPresence)
Gets a URL to the endpoint that updates the rich presence in the user's RetroAchievements profile.
Definition Game.h:984
virtual GAME_ERROR RCGetGameIDUrl(std::string &url, const std::string &hash)
Gets a URL to the endpoint that returns the game ID.
Definition Game.h:944
virtual GAME_ERROR RCEnableRichPresence(const std::string &script)
Enables rich presence.
Definition Game.h:1001
virtual GAME_ERROR RCResetRuntime()
Resets the runtime. Must be called each time a new rom is starting and when the savestate is changed.
Definition Game.h:1031
virtual GAME_ERROR CheatReset()
Reset the cheat system.
Definition Game.h:884
virtual GAME_ERROR GetMemory(GAME_MEMORY type, uint8_t *&data, size_t &size)
Get a region of memory.
Definition Game.h:896
virtual GAME_ERROR SetCheat(unsigned int index, bool enabled, const std::string &code)
Set a cheat code.
Definition Game.h:911
Game system timing.
Definition game.h:1140
GAME_REGION
Game region definition
Definition game.h:585
SPECIAL_GAME_TYPE
Special game types passed into game_load_game_special().
Definition game.h:603
GAME_MEMORY
Game Memory
Definition game.h:622
@ GAME_REGION_UNKNOWN
Game region unknown.
Definition game.h:587
void(* game_proc_address_t)(void)
Hardware framebuffer process function address
Definition game.h:425
Hardware rendering properties
Definition game.h:337
std::vector< std::string > analog_buttons
Analog buttons.
Definition Game.h:85
std::vector< std::string > accelerometers
Accelerometers.
Definition Game.h:91
bool provides_input
Provides input.
Definition Game.h:79
std::vector< std::string > digital_buttons
Digital buttons.
Definition Game.h:82
std::vector< std::string > abs_pointers
Absolute pointers.
Definition Game.h:100
std::vector< std::string > motors
Motors.
Definition Game.h:103
std::string controller_id
Controller identifier.
Definition Game.h:74
std::vector< std::string > rel_pointers
Relative pointers.
Definition Game.h:97
std::vector< std::string > keys
Keys.
Definition Game.h:94
std::vector< std::string > analog_sticks
Analog sticks.
Definition Game.h:88
"C" Game add-on controller layout.
Definition game.h:870
An input event.
Definition game.h:1079
The input topology is the possible ways to connect input devices.
Definition game.h:951
Stream buffers for hardware rendering and zero-copy support
Definition game.h:527
Stream packet and ephemeral metadata
Definition game.h:550
Immutable stream metadata
Definition game.h:502
GAME_ERROR
Game add-on error codes
Definition game.h:28
@ GAME_ERROR_NOT_IMPLEMENTED
The method called by the frontend is not implemented.
Definition game.h:36
virtual GAME_ERROR SetImageIndex(unsigned int imageIndex)
Inserts the disk image at the given index.
Definition Game.h:1097
virtual unsigned int GetImageCount()
Gets the number of available disk images.
Definition Game.h:1105
virtual std::string GetImageLabel(unsigned int imageIndex)
Gets a user-friendly label for a disk image.
Definition Game.h:1180
virtual GAME_ERROR ReplaceImageIndex(unsigned int imageIndex, const std::string &filePath)
Replaces the disk image at the given index.
Definition Game.h:1127
virtual GAME_ERROR RemoveImageIndex(unsigned int imageIndex)
Removes the disk image at the given index.
Definition Game.h:1142
virtual std::string GetImagePath(unsigned int imageIndex)
Gets the full path of a disk image.
Definition Game.h:1170
virtual unsigned int GetImageIndex()
Gets the index of the currently inserted disk image.
Definition Game.h:1085
virtual GAME_ERROR SetInitialImage(unsigned int imageIndex, const std::string &filePath)
Sets which image should be initially inserted on load.
Definition Game.h:1157
virtual GAME_ERROR SetEjectState(bool ejected)
Opens or closes the virtual disk tray.
Definition Game.h:1076
virtual GAME_ERROR AddImageIndex()
Adds a new disk image slot.
Definition Game.h:1114
virtual bool GetEjectState()
Returns whether the virtual disk tray is currently ejected.
Definition Game.h:1063
virtual GAME_ERROR HwContextDestroy()
Called before the context is destroyed.
Definition Game.h:612
virtual GAME_ERROR HwContextReset()
Invalidates the current HW context and reinitializes GPU resources.
Definition Game.h:602
bool EnableHardwareRendering(const game_hw_rendering_properties &properties)
Callback to Kodi Function Enable hardware rendering functionality
Definition Game.h:588
game_proc_address_t HwGetProcAddress(const char *sym)
Callback to Kodi Function Get a symbol from the hardware context
Definition Game.h:623
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:661
virtual bool InputEvent(const game_input_event &event)
Notify the add-on of an input event.
Definition Game.h:784
virtual void FreeTopology(game_input_topology *topology)
Free the topology's resources.
Definition Game.h:686
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:769
virtual void SetControllerLayouts(const std::vector< kodi::addon::GameControllerLayout > &controllers)
Set the layouts for known controllers.
Definition Game.h:697
virtual bool EnableMouse(bool enable, const std::string &controller_id)
Enable/disable mouse input using the specified controller.
Definition Game.h:722
virtual bool EnableKeyboard(bool enable, const std::string &controller_id)
Enable/disable keyboard input using the specified controller.
Definition Game.h:711
bool KodiInputEvent(const game_input_event &event)
Callback to Kodi Function Notify the port of an input event
Definition Game.h:799
virtual game_input_topology * GetTopology()
Get the input topology that specifies which controllers can be connected.
Definition Game.h:678
bool IsOpen() const
Check if the stream opened correctly, e.g. after calling the constructor.
Definition Game.h:551
void ReleaseBuffer(game_stream_buffer &buffer)
Free an allocated buffer.
Definition Game.h:531
void Close()
Free the specified stream.
Definition Game.h:464
bool GetBuffer(unsigned int width, unsigned int height, game_stream_buffer &buffer)
Get a buffer for zero-copy stream data.
Definition Game.h:491
void AddData(const game_stream_packet &packet)
Add a data packet to a stream.
Definition Game.h:511
bool Open(const game_stream_properties &properties)
Create a stream for gameplay data.
Definition Game.h:439
virtual GAME_ERROR LoadGameSpecial(SPECIAL_GAME_TYPE type, const std::vector< std::string > &urls)
Load a game that requires multiple files.
Definition Game.h:323
virtual GAME_ERROR UnloadGame()
Unload the current game.
Definition Game.h:349
virtual GAME_ERROR GetGameTiming(game_system_timing &timing_info)
Get timing information about the loaded game.
Definition Game.h:359
virtual GAME_ERROR RunFrame()
Run a single frame for add-ons that use a game loop.
Definition Game.h:389
virtual bool RequiresGameLoop()
Return true if the client requires the frontend to provide a game loop.
Definition Game.h:381
virtual GAME_ERROR Reset()
Reset the current game.
Definition Game.h:397
virtual GAME_ERROR LoadStandalone()
Begin playing without a game file.
Definition Game.h:339
void CloseGame(void)
Callback to Kodi Function Requests the frontend to stop the current game
Definition Game.h:406
virtual GAME_ERROR LoadGame(const std::string &url)
Load a game.
Definition Game.h:312
virtual GAME_REGION GetRegion()
Get region of the loaded game.
Definition Game.h:370
virtual GAME_ERROR Deserialize(const uint8_t *data, size_t size)
Deserialize the game from the given state.
Definition Game.h:852
virtual GAME_ERROR Serialize(uint8_t *data, size_t size)
Serialize the state of the game.
Definition Game.h:841
virtual size_t SerializeSize()
Get the number of bytes required to serialize the game.
Definition Game.h:830
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:1323
Game callbacks.
Definition game.h:1225
Definition addon_base.h:269
Internal used structure to have stored C API data above and available for everything below.
Definition AddonBase.h:73