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);
662 virtual bool HasFeature(
const std::string& controller_id,
const std::string& feature_name)
699 const std::vector<kodi::addon::GameControllerLayout>& controllers)
712 virtual bool EnableKeyboard(
bool enable,
const std::string& controller_id) {
return false; }
723 virtual bool EnableMouse(
bool enable,
const std::string& controller_id) {
return false; }
771 const std::string& port_address,
772 const std::string& controller_id)
802 return m_instanceData->toKodi->InputEvent(m_instanceData->toKodi->kodiInstance, &event);
930 unsigned int consoleID,
931 const std::string& filePath)
960 const std::string& username,
961 const std::string& token,
976 const std::string& token)
996 std::string& postData,
997 const std::string& username,
998 const std::string& token,
1000 const std::string& richPresence)
1044 const std::string& memAddrExpression)
1062 const std::function<
void(
const std::string& achievementUrl,
unsigned int cheevoId)>& callback)
1231 instance->hdl =
this;
1233 instance->game->toAddon->LoadGame = ADDON_LoadGame;
1234 instance->game->toAddon->LoadGameSpecial = ADDON_LoadGameSpecial;
1235 instance->game->toAddon->LoadStandalone = ADDON_LoadStandalone;
1236 instance->game->toAddon->UnloadGame = ADDON_UnloadGame;
1237 instance->game->toAddon->GetGameTiming = ADDON_GetGameTiming;
1238 instance->game->toAddon->GetRegion = ADDON_GetRegion;
1239 instance->game->toAddon->RequiresGameLoop = ADDON_RequiresGameLoop;
1240 instance->game->toAddon->RunFrame = ADDON_RunFrame;
1241 instance->game->toAddon->Reset = ADDON_Reset;
1243 instance->game->toAddon->HwContextReset = ADDON_HwContextReset;
1244 instance->game->toAddon->HwContextDestroy = ADDON_HwContextDestroy;
1246 instance->game->toAddon->HasFeature = ADDON_HasFeature;
1247 instance->game->toAddon->GetTopology = ADDON_GetTopology;
1248 instance->game->toAddon->FreeTopology = ADDON_FreeTopology;
1249 instance->game->toAddon->SetControllerLayouts = ADDON_SetControllerLayouts;
1250 instance->game->toAddon->EnableKeyboard = ADDON_EnableKeyboard;
1251 instance->game->toAddon->EnableMouse = ADDON_EnableMouse;
1252 instance->game->toAddon->ConnectController = ADDON_ConnectController;
1253 instance->game->toAddon->InputEvent = ADDON_InputEvent;
1255 instance->game->toAddon->SerializeSize = ADDON_SerializeSize;
1256 instance->game->toAddon->Serialize = ADDON_Serialize;
1257 instance->game->toAddon->Deserialize = ADDON_Deserialize;
1259 instance->game->toAddon->CheatReset = ADDON_CheatReset;
1260 instance->game->toAddon->GetMemory = ADDON_GetMemory;
1261 instance->game->toAddon->SetCheat = ADDON_SetCheat;
1263 instance->game->toAddon->RCGenerateHashFromFile = ADDON_RCGenerateHashFromFile;
1264 instance->game->toAddon->RCGetGameIDUrl = ADDON_RCGetGameIDUrl;
1265 instance->game->toAddon->RCGetPatchFileUrl = ADDON_RCGetPatchFileUrl;
1266 instance->game->toAddon->SetRetroAchievementsCredentials =
1267 ADDON_SetRetroAchievementsCredentials;
1268 instance->game->toAddon->RCPostRichPresenceUrl = ADDON_RCPostRichPresenceUrl;
1269 instance->game->toAddon->RCEnableRichPresence = ADDON_RCEnableRichPresence;
1270 instance->game->toAddon->RCGetRichPresenceEvaluation = ADDON_RCGetRichPresenceEvaluation;
1271 instance->game->toAddon->ActivateAchievement = ADDON_ActivateAchievement;
1272 instance->game->toAddon->GetCheevoUrlId = ADDON_GetCheevoUrlId;
1273 instance->game->toAddon->RCResetRuntime = ADDON_RCResetRuntime;
1275 instance->game->toAddon->GetEjectState = ADDON_GetEjectState;
1276 instance->game->toAddon->SetEjectState = ADDON_SetEjectState;
1277 instance->game->toAddon->GetImageIndex = ADDON_GetImageIndex;
1278 instance->game->toAddon->SetImageIndex = ADDON_SetImageIndex;
1279 instance->game->toAddon->GetImageCount = ADDON_GetImageCount;
1280 instance->game->toAddon->AddImageIndex = ADDON_AddImageIndex;
1281 instance->game->toAddon->ReplaceImageIndex = ADDON_ReplaceImageIndex;
1282 instance->game->toAddon->RemoveImageIndex = ADDON_RemoveImageIndex;
1283 instance->game->toAddon->SetInitialImage = ADDON_SetInitialImage;
1284 instance->game->toAddon->GetImagePath = ADDON_GetImagePath;
1285 instance->game->toAddon->GetImageLabel = ADDON_GetImageLabel;
1287 instance->game->toAddon->FreeString = ADDON_FreeString;
1289 m_instanceData = instance->game;
1290 m_instanceData->toAddon->addonInstance =
this;
1297 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->LoadGame(url);
1305 std::vector<std::string> urlList;
1306 for (
size_t i = 0; i < urlCount; ++i)
1308 if (urls[i] !=
nullptr)
1309 urlList.emplace_back(urls[i]);
1312 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1313 ->LoadGameSpecial(type, urlList);
1318 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->LoadStandalone();
1323 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->UnloadGame();
1329 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1330 ->GetGameTiming(*timing_info);
1335 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->
GetRegion();
1340 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->RequiresGameLoop();
1345 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->RunFrame();
1350 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->Reset();
1357 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->HwContextReset();
1362 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->HwContextDestroy();
1368 const char* controller_id,
1369 const char* feature_name)
1371 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1372 ->HasFeature(controller_id, feature_name);
1377 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->GetTopology();
1383 static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->FreeTopology(topology);
1388 unsigned int controller_count)
1390 if (controllers ==
nullptr)
1393 std::vector<GameControllerLayout> controllerList;
1394 controllerList.reserve(controller_count);
1395 for (
unsigned int i = 0; i < controller_count; ++i)
1396 controllerList.emplace_back(controllers[i]);
1398 static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1399 ->SetControllerLayouts(controllerList);
1404 const char* controller_id)
1406 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1407 ->EnableKeyboard(enable, controller_id);
1412 const char* controller_id)
1414 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1415 ->EnableMouse(enable, controller_id);
1420 const char* port_address,
1421 const char* controller_id)
1423 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1424 ->ConnectController(connect, port_address, controller_id);
1430 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->InputEvent(*event);
1437 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->SerializeSize();
1444 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->Serialize(data, size);
1448 const uint8_t* data,
1451 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->Deserialize(data, size);
1458 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->CheatReset();
1466 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1467 ->GetMemory(type, *data, *size);
1475 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1476 ->SetCheat(index, enabled, code);
1481 unsigned int consoleID,
1482 const char* filePath)
1484 if (hash ==
nullptr || filePath ==
nullptr)
1489 std::string cppHash;
1491 GAME_ERROR ret =
static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1492 ->RCGenerateHashFromFile(cppHash, consoleID, filePath);
1496 *hash =
new char[cppHash.size() + 1];
1497 std::copy(cppHash.begin(), cppHash.end(), *hash);
1498 (*hash)[cppHash.size()] =
'\0';
1508 if (url ==
nullptr || hash ==
nullptr)
1515 static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->RCGetGameIDUrl(cppUrl, hash);
1519 *url =
new char[cppUrl.size() + 1];
1520 std::copy(cppUrl.begin(), cppUrl.end(), *url);
1521 (*url)[cppUrl.size()] =
'\0';
1529 const char* username,
1531 unsigned int gameID)
1533 if (url ==
nullptr || username ==
nullptr || token ==
nullptr)
1540 GAME_ERROR ret =
static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1541 ->RCGetPatchFileUrl(cppUrl, username, token, gameID);
1545 *url =
new char[cppUrl.size() + 1];
1546 std::copy(cppUrl.begin(), cppUrl.end(), *url);
1547 (*url)[cppUrl.size()] =
'\0';
1554 const char* username,
1557 if (username ==
nullptr || token ==
nullptr)
1560 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1561 ->SetRetroAchievementsCredentials(username, token);
1567 const char* username,
1569 unsigned int gameID,
1570 const char* richPresence)
1572 if (url ==
nullptr || postData ==
nullptr || username ==
nullptr || token ==
nullptr ||
1573 richPresence ==
nullptr)
1577 *postData =
nullptr;
1580 std::string cppPostData;
1583 static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1584 ->RCPostRichPresenceUrl(cppUrl, cppPostData, username, token, gameID, richPresence);
1588 *url =
new char[cppUrl.size() + 1];
1589 std::copy(cppUrl.begin(), cppUrl.end(), *url);
1590 (*url)[cppUrl.size()] =
'\0';
1592 *postData =
new char[cppPostData.size() + 1];
1593 std::copy(cppPostData.begin(), cppPostData.end(), *postData);
1594 (*postData)[cppPostData.size()] =
'\0';
1603 if (script ==
nullptr)
1606 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1607 ->RCEnableRichPresence(script);
1612 unsigned int consoleID)
1614 if (evaluation ==
nullptr)
1617 *evaluation =
nullptr;
1619 std::string cppEvaluation;
1620 GAME_ERROR ret =
static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1621 ->RCGetRichPresenceEvaluation(cppEvaluation, consoleID);
1625 *evaluation =
new char[cppEvaluation.size() + 1];
1626 std::copy(cppEvaluation.begin(), cppEvaluation.end(), *evaluation);
1627 (*evaluation)[cppEvaluation.size()] =
'\0';
1634 unsigned int cheevoId,
1635 const char* memAddrExpression)
1637 if (memAddrExpression ==
nullptr)
1640 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1641 ->ActivateAchievement(cheevoId, memAddrExpression);
1645 void(__cdecl* callback)(
const void* context,
1646 const char* achievementUrl,
1647 unsigned int cheevoId),
1648 const void* context)
1650 if (callback ==
nullptr)
1653 const auto cppCallback =
1654 [callback, context](
const std::string& achievementUrl,
unsigned int cheevoId)
1655 { callback(context, achievementUrl.c_str(), cheevoId); };
1657 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1658 ->GetCheevoUrlId(cppCallback);
1663 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->RCResetRuntime();
1668 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->GetEjectState();
1673 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->SetEjectState(ejected);
1678 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->GetImageIndex();
1682 unsigned int imageIndex)
1684 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->SetImageIndex(imageIndex);
1689 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->GetImageCount();
1694 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->AddImageIndex();
1698 unsigned int imageIndex,
1699 const char* filePath)
1701 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1702 ->ReplaceImageIndex(imageIndex, filePath ? filePath :
"");
1706 unsigned int imageIndex)
1708 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1709 ->RemoveImageIndex(imageIndex);
1713 unsigned int imageIndex,
1714 const char* filePath)
1716 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1717 ->SetInitialImage(imageIndex, filePath ? filePath :
"");
1721 unsigned int imageIndex)
1723 std::string cppPath =
1724 static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->GetImagePath(imageIndex);
1725 if (cppPath.empty())
1728 char* path =
new char[cppPath.size() + 1];
1729 std::copy(cppPath.begin(), cppPath.end(), path);
1730 path[cppPath.size()] =
'\0';
1735 unsigned int imageIndex)
1737 std::string cppLabel =
1738 static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->GetImageLabel(imageIndex);
1739 if (cppLabel.empty())
1742 char* label =
new char[cppLabel.size() + 1];
1743 std::copy(cppLabel.begin(), cppLabel.end(), label);
1744 label[cppLabel.size()] =
'\0';