163 if (CPrivateBase::m_interface->globalSingleInstance !=
nullptr)
165 throw std::logic_error(
166 "kodi::addon::CInstanceGame: Cannot create more than one game instance!");
168 SetAddonStruct(CPrivateBase::m_interface->firstKodiInstance);
169 CPrivateBase::m_interface->globalSingleInstance =
this;
202 for (
unsigned int i = 0; i < m_instanceData->props->proxy_dll_count; ++i)
204 if (m_instanceData->props->proxy_dll_paths[i] !=
nullptr)
205 paths.emplace_back(m_instanceData->props->proxy_dll_paths[i]);
207 return !paths.empty();
226 for (
unsigned int i = 0; i < m_instanceData->props->resource_directory_count; ++i)
228 if (m_instanceData->props->resource_directories[i] !=
nullptr)
229 dirs.emplace_back(m_instanceData->props->resource_directories[i]);
231 return !dirs.empty();
258 bool SupportsVFS()
const {
return m_instanceData->props->supports_vfs; }
273 for (
unsigned int i = 0; i < m_instanceData->props->extension_count; ++i)
275 if (m_instanceData->props->extensions[i] !=
nullptr)
276 extensions.emplace_back(m_instanceData->props->extensions[i]);
278 return !extensions.empty();
407 void CloseGame(
void) { m_instanceData->toKodi->CloseGame(m_instanceData->toKodi->kodiInstance); }
442 if (!CPrivateBase::m_interface->globalSingleInstance)
452 *
static_cast<CInstanceGame*
>(CPrivateBase::m_interface->globalSingleInstance)
453 ->m_instanceData->toKodi;
454 m_handle = cb.OpenStream(cb.kodiInstance, &properties);
455 return m_handle !=
nullptr;
467 if (!m_handle || !CPrivateBase::m_interface->globalSingleInstance)
471 *
static_cast<CInstanceGame*
>(CPrivateBase::m_interface->globalSingleInstance)
472 ->m_instanceData->toKodi;
473 cb.CloseStream(cb.kodiInstance, m_handle);
494 if (!m_handle || !CPrivateBase::m_interface->globalSingleInstance)
498 *
static_cast<CInstanceGame*
>(CPrivateBase::m_interface->globalSingleInstance)
499 ->m_instanceData->toKodi;
500 return cb.GetStreamBuffer(cb.kodiInstance, m_handle, width, height, &buffer);
514 if (!m_handle || !CPrivateBase::m_interface->globalSingleInstance)
518 *
static_cast<CInstanceGame*
>(CPrivateBase::m_interface->globalSingleInstance)
519 ->m_instanceData->toKodi;
520 cb.AddStreamData(cb.kodiInstance, m_handle, &packet);
534 if (!m_handle || !CPrivateBase::m_interface->globalSingleInstance)
538 *
static_cast<CInstanceGame*
>(CPrivateBase::m_interface->globalSingleInstance)
539 ->m_instanceData->toKodi;
540 cb.ReleaseStreamBuffer(cb.kodiInstance, m_handle, &buffer);
552 bool IsOpen()
const {
return m_handle !=
nullptr; }
556 KODI_GAME_STREAM_HANDLE m_handle =
nullptr;
591 return m_instanceData->toKodi->EnableHardwareRendering(m_instanceData->toKodi->kodiInstance,
626 return m_instanceData->toKodi->HwGetProcAddress(m_instanceData->toKodi->kodiInstance, sym);
696 virtual bool HasFeature(
const std::string& controller_id,
const std::string& feature_name)
733 const std::vector<kodi::addon::GameControllerLayout>& controllers)
746 virtual bool EnableKeyboard(
bool enable,
const std::string& controller_id) {
return false; }
757 virtual bool EnableMouse(
bool enable,
const std::string& controller_id) {
return false; }
805 const std::string& port_address,
806 const std::string& controller_id)
836 return m_instanceData->toKodi->InputEvent(m_instanceData->toKodi->kodiInstance, &event);
964 unsigned int consoleID,
965 const std::string& filePath)
994 const std::string& username,
995 const std::string& token,
1010 const std::string& token)
1030 std::string& postData,
1031 const std::string& username,
1032 const std::string& token,
1033 unsigned int gameID,
1034 const std::string& richPresence)
1078 const std::string& memAddrExpression)
1096 const std::function<
void(
const std::string& achievementUrl,
unsigned int cheevoId)>& callback)
1265 instance->hdl =
this;
1267 instance->game->toAddon->LoadGame = ADDON_LoadGame;
1268 instance->game->toAddon->LoadGameSpecial = ADDON_LoadGameSpecial;
1269 instance->game->toAddon->LoadStandalone = ADDON_LoadStandalone;
1270 instance->game->toAddon->UnloadGame = ADDON_UnloadGame;
1271 instance->game->toAddon->GetGameTiming = ADDON_GetGameTiming;
1272 instance->game->toAddon->GetRegion = ADDON_GetRegion;
1273 instance->game->toAddon->RequiresGameLoop = ADDON_RequiresGameLoop;
1274 instance->game->toAddon->RunFrame = ADDON_RunFrame;
1275 instance->game->toAddon->Reset = ADDON_Reset;
1277 instance->game->toAddon->HwContextReset = ADDON_HwContextReset;
1278 instance->game->toAddon->HwContextDestroy = ADDON_HwContextDestroy;
1280 instance->game->toAddon->AudioAvailable = ADDON_AudioAvailable;
1282 instance->game->toAddon->HasFeature = ADDON_HasFeature;
1283 instance->game->toAddon->GetTopology = ADDON_GetTopology;
1284 instance->game->toAddon->FreeTopology = ADDON_FreeTopology;
1285 instance->game->toAddon->SetControllerLayouts = ADDON_SetControllerLayouts;
1286 instance->game->toAddon->EnableKeyboard = ADDON_EnableKeyboard;
1287 instance->game->toAddon->EnableMouse = ADDON_EnableMouse;
1288 instance->game->toAddon->ConnectController = ADDON_ConnectController;
1289 instance->game->toAddon->InputEvent = ADDON_InputEvent;
1291 instance->game->toAddon->SerializeSize = ADDON_SerializeSize;
1292 instance->game->toAddon->Serialize = ADDON_Serialize;
1293 instance->game->toAddon->Deserialize = ADDON_Deserialize;
1295 instance->game->toAddon->CheatReset = ADDON_CheatReset;
1296 instance->game->toAddon->GetMemory = ADDON_GetMemory;
1297 instance->game->toAddon->SetCheat = ADDON_SetCheat;
1299 instance->game->toAddon->RCGenerateHashFromFile = ADDON_RCGenerateHashFromFile;
1300 instance->game->toAddon->RCGetGameIDUrl = ADDON_RCGetGameIDUrl;
1301 instance->game->toAddon->RCGetPatchFileUrl = ADDON_RCGetPatchFileUrl;
1302 instance->game->toAddon->SetRetroAchievementsCredentials =
1303 ADDON_SetRetroAchievementsCredentials;
1304 instance->game->toAddon->RCPostRichPresenceUrl = ADDON_RCPostRichPresenceUrl;
1305 instance->game->toAddon->RCEnableRichPresence = ADDON_RCEnableRichPresence;
1306 instance->game->toAddon->RCGetRichPresenceEvaluation = ADDON_RCGetRichPresenceEvaluation;
1307 instance->game->toAddon->ActivateAchievement = ADDON_ActivateAchievement;
1308 instance->game->toAddon->GetCheevoUrlId = ADDON_GetCheevoUrlId;
1309 instance->game->toAddon->RCResetRuntime = ADDON_RCResetRuntime;
1311 instance->game->toAddon->GetEjectState = ADDON_GetEjectState;
1312 instance->game->toAddon->SetEjectState = ADDON_SetEjectState;
1313 instance->game->toAddon->GetImageIndex = ADDON_GetImageIndex;
1314 instance->game->toAddon->SetImageIndex = ADDON_SetImageIndex;
1315 instance->game->toAddon->GetImageCount = ADDON_GetImageCount;
1316 instance->game->toAddon->AddImageIndex = ADDON_AddImageIndex;
1317 instance->game->toAddon->ReplaceImageIndex = ADDON_ReplaceImageIndex;
1318 instance->game->toAddon->RemoveImageIndex = ADDON_RemoveImageIndex;
1319 instance->game->toAddon->SetInitialImage = ADDON_SetInitialImage;
1320 instance->game->toAddon->GetImagePath = ADDON_GetImagePath;
1321 instance->game->toAddon->GetImageLabel = ADDON_GetImageLabel;
1323 instance->game->toAddon->FreeString = ADDON_FreeString;
1325 m_instanceData = instance->game;
1326 m_instanceData->toAddon->addonInstance =
this;
1333 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->LoadGame(url);
1341 std::vector<std::string> urlList;
1342 for (
size_t i = 0; i < urlCount; ++i)
1344 if (urls[i] !=
nullptr)
1345 urlList.emplace_back(urls[i]);
1348 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1349 ->LoadGameSpecial(type, urlList);
1354 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->LoadStandalone();
1359 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->UnloadGame();
1365 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1366 ->GetGameTiming(*timing_info);
1371 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->
GetRegion();
1376 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->RequiresGameLoop();
1381 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->RunFrame();
1386 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->Reset();
1393 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->HwContextReset();
1398 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->HwContextDestroy();
1405 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->AudioAvailable();
1411 const char* controller_id,
1412 const char* feature_name)
1414 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1415 ->HasFeature(controller_id, feature_name);
1420 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->GetTopology();
1426 static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->FreeTopology(topology);
1431 unsigned int controller_count)
1433 if (controllers ==
nullptr)
1436 std::vector<GameControllerLayout> controllerList;
1437 controllerList.reserve(controller_count);
1438 for (
unsigned int i = 0; i < controller_count; ++i)
1439 controllerList.emplace_back(controllers[i]);
1441 static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1442 ->SetControllerLayouts(controllerList);
1447 const char* controller_id)
1449 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1450 ->EnableKeyboard(enable, controller_id);
1455 const char* controller_id)
1457 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1458 ->EnableMouse(enable, controller_id);
1463 const char* port_address,
1464 const char* controller_id)
1466 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1467 ->ConnectController(connect, port_address, controller_id);
1473 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->InputEvent(*event);
1480 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->SerializeSize();
1487 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->Serialize(data, size);
1491 const uint8_t* data,
1494 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->Deserialize(data, size);
1501 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->CheatReset();
1509 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1510 ->GetMemory(type, *data, *size);
1518 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1519 ->SetCheat(index, enabled, code);
1524 unsigned int consoleID,
1525 const char* filePath)
1527 if (hash ==
nullptr || filePath ==
nullptr)
1532 std::string cppHash;
1534 GAME_ERROR ret =
static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1535 ->RCGenerateHashFromFile(cppHash, consoleID, filePath);
1539 *hash =
new char[cppHash.size() + 1];
1540 std::copy(cppHash.begin(), cppHash.end(), *hash);
1541 (*hash)[cppHash.size()] =
'\0';
1551 if (url ==
nullptr || hash ==
nullptr)
1558 static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->RCGetGameIDUrl(cppUrl, hash);
1562 *url =
new char[cppUrl.size() + 1];
1563 std::copy(cppUrl.begin(), cppUrl.end(), *url);
1564 (*url)[cppUrl.size()] =
'\0';
1572 const char* username,
1574 unsigned int gameID)
1576 if (url ==
nullptr || username ==
nullptr || token ==
nullptr)
1583 GAME_ERROR ret =
static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1584 ->RCGetPatchFileUrl(cppUrl, username, token, gameID);
1588 *url =
new char[cppUrl.size() + 1];
1589 std::copy(cppUrl.begin(), cppUrl.end(), *url);
1590 (*url)[cppUrl.size()] =
'\0';
1597 const char* username,
1600 if (username ==
nullptr || token ==
nullptr)
1603 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1604 ->SetRetroAchievementsCredentials(username, token);
1610 const char* username,
1612 unsigned int gameID,
1613 const char* richPresence)
1615 if (url ==
nullptr || postData ==
nullptr || username ==
nullptr || token ==
nullptr ||
1616 richPresence ==
nullptr)
1620 *postData =
nullptr;
1623 std::string cppPostData;
1626 static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1627 ->RCPostRichPresenceUrl(cppUrl, cppPostData, username, token, gameID, richPresence);
1631 *url =
new char[cppUrl.size() + 1];
1632 std::copy(cppUrl.begin(), cppUrl.end(), *url);
1633 (*url)[cppUrl.size()] =
'\0';
1635 *postData =
new char[cppPostData.size() + 1];
1636 std::copy(cppPostData.begin(), cppPostData.end(), *postData);
1637 (*postData)[cppPostData.size()] =
'\0';
1646 if (script ==
nullptr)
1649 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1650 ->RCEnableRichPresence(script);
1655 unsigned int consoleID)
1657 if (evaluation ==
nullptr)
1660 *evaluation =
nullptr;
1662 std::string cppEvaluation;
1663 GAME_ERROR ret =
static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1664 ->RCGetRichPresenceEvaluation(cppEvaluation, consoleID);
1668 *evaluation =
new char[cppEvaluation.size() + 1];
1669 std::copy(cppEvaluation.begin(), cppEvaluation.end(), *evaluation);
1670 (*evaluation)[cppEvaluation.size()] =
'\0';
1677 unsigned int cheevoId,
1678 const char* memAddrExpression)
1680 if (memAddrExpression ==
nullptr)
1683 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1684 ->ActivateAchievement(cheevoId, memAddrExpression);
1688 void(__cdecl* callback)(
const void* context,
1689 const char* achievementUrl,
1690 unsigned int cheevoId),
1691 const void* context)
1693 if (callback ==
nullptr)
1696 const auto cppCallback =
1697 [callback, context](
const std::string& achievementUrl,
unsigned int cheevoId)
1698 { callback(context, achievementUrl.c_str(), cheevoId); };
1700 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1701 ->GetCheevoUrlId(cppCallback);
1706 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->RCResetRuntime();
1711 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->GetEjectState();
1716 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->SetEjectState(ejected);
1721 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->GetImageIndex();
1725 unsigned int imageIndex)
1727 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->SetImageIndex(imageIndex);
1732 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->GetImageCount();
1737 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->AddImageIndex();
1741 unsigned int imageIndex,
1742 const char* filePath)
1744 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1745 ->ReplaceImageIndex(imageIndex, filePath ? filePath :
"");
1749 unsigned int imageIndex)
1751 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1752 ->RemoveImageIndex(imageIndex);
1756 unsigned int imageIndex,
1757 const char* filePath)
1759 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1760 ->SetInitialImage(imageIndex, filePath ? filePath :
"");
1764 unsigned int imageIndex)
1766 std::string cppPath =
1767 static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->GetImagePath(imageIndex);
1768 if (cppPath.empty())
1771 char* path =
new char[cppPath.size() + 1];
1772 std::copy(cppPath.begin(), cppPath.end(), path);
1773 path[cppPath.size()] =
'\0';
1778 unsigned int imageIndex)
1780 std::string cppLabel =
1781 static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->GetImageLabel(imageIndex);
1782 if (cppLabel.empty())
1785 char* label =
new char[cppLabel.size() + 1];
1786 std::copy(cppLabel.begin(), cppLabel.end(), label);
1787 label[cppLabel.size()] =
'\0';