162 if (CPrivateBase::m_interface->globalSingleInstance !=
nullptr)
164 throw std::logic_error(
165 "kodi::addon::CInstanceGame: Cannot create more than one game instance!");
167 SetAddonStruct(CPrivateBase::m_interface->firstKodiInstance);
168 CPrivateBase::m_interface->globalSingleInstance =
this;
201 for (
unsigned int i = 0; i < m_instanceData->props->proxy_dll_count; ++i)
203 if (m_instanceData->props->proxy_dll_paths[i] !=
nullptr)
204 paths.emplace_back(m_instanceData->props->proxy_dll_paths[i]);
206 return !paths.empty();
225 for (
unsigned int i = 0; i < m_instanceData->props->resource_directory_count; ++i)
227 if (m_instanceData->props->resource_directories[i] !=
nullptr)
228 dirs.emplace_back(m_instanceData->props->resource_directories[i]);
230 return !dirs.empty();
257 bool SupportsVFS()
const {
return m_instanceData->props->supports_vfs; }
272 for (
unsigned int i = 0; i < m_instanceData->props->extension_count; ++i)
274 if (m_instanceData->props->extensions[i] !=
nullptr)
275 extensions.emplace_back(m_instanceData->props->extensions[i]);
277 return !extensions.empty();
406 void CloseGame(
void) { m_instanceData->toKodi->CloseGame(m_instanceData->toKodi->kodiInstance); }
441 if (!CPrivateBase::m_interface->globalSingleInstance)
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;
466 if (!m_handle || !CPrivateBase::m_interface->globalSingleInstance)
470 *
static_cast<CInstanceGame*
>(CPrivateBase::m_interface->globalSingleInstance)
471 ->m_instanceData->toKodi;
472 cb.CloseStream(cb.kodiInstance, m_handle);
493 if (!m_handle || !CPrivateBase::m_interface->globalSingleInstance)
497 *
static_cast<CInstanceGame*
>(CPrivateBase::m_interface->globalSingleInstance)
498 ->m_instanceData->toKodi;
499 return cb.GetStreamBuffer(cb.kodiInstance, m_handle, width, height, &buffer);
513 if (!m_handle || !CPrivateBase::m_interface->globalSingleInstance)
517 *
static_cast<CInstanceGame*
>(CPrivateBase::m_interface->globalSingleInstance)
518 ->m_instanceData->toKodi;
519 cb.AddStreamData(cb.kodiInstance, m_handle, &packet);
533 if (!m_handle || !CPrivateBase::m_interface->globalSingleInstance)
537 *
static_cast<CInstanceGame*
>(CPrivateBase::m_interface->globalSingleInstance)
538 ->m_instanceData->toKodi;
539 cb.ReleaseStreamBuffer(cb.kodiInstance, m_handle, &buffer);
551 bool IsOpen()
const {
return m_handle !=
nullptr; }
555 KODI_GAME_STREAM_HANDLE m_handle =
nullptr;
590 return m_instanceData->toKodi->EnableHardwareRendering(m_instanceData->toKodi->kodiInstance,
625 return m_instanceData->toKodi->HwGetProcAddress(m_instanceData->toKodi->kodiInstance, sym);
661 virtual bool HasFeature(
const std::string& controller_id,
const std::string& feature_name)
698 const std::vector<kodi::addon::GameControllerLayout>& controllers)
711 virtual bool EnableKeyboard(
bool enable,
const std::string& controller_id) {
return false; }
722 virtual bool EnableMouse(
bool enable,
const std::string& controller_id) {
return false; }
770 const std::string& port_address,
771 const std::string& controller_id)
801 return m_instanceData->toKodi->InputEvent(m_instanceData->toKodi->kodiInstance, &event);
929 unsigned int consoleID,
930 const std::string& filePath)
961 const std::string& username,
962 const std::string& token,
985 std::string& postData,
986 const std::string& username,
987 const std::string& token,
989 const std::string& richPresence)
1188 instance->hdl =
this;
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;
1200 instance->game->toAddon->HwContextReset = ADDON_HwContextReset;
1201 instance->game->toAddon->HwContextDestroy = ADDON_HwContextDestroy;
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;
1212 instance->game->toAddon->SerializeSize = ADDON_SerializeSize;
1213 instance->game->toAddon->Serialize = ADDON_Serialize;
1214 instance->game->toAddon->Deserialize = ADDON_Deserialize;
1216 instance->game->toAddon->CheatReset = ADDON_CheatReset;
1217 instance->game->toAddon->GetMemory = ADDON_GetMemory;
1218 instance->game->toAddon->SetCheat = ADDON_SetCheat;
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;
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;
1240 instance->game->toAddon->FreeString = ADDON_FreeString;
1242 m_instanceData = instance->game;
1243 m_instanceData->toAddon->addonInstance =
this;
1250 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->LoadGame(url);
1258 std::vector<std::string> urlList;
1259 for (
size_t i = 0; i < urlCount; ++i)
1261 if (urls[i] !=
nullptr)
1262 urlList.emplace_back(urls[i]);
1265 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1266 ->LoadGameSpecial(type, urlList);
1271 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->LoadStandalone();
1276 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->UnloadGame();
1282 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1283 ->GetGameTiming(*timing_info);
1288 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->
GetRegion();
1293 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->RequiresGameLoop();
1298 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->RunFrame();
1303 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->Reset();
1310 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->HwContextReset();
1315 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->HwContextDestroy();
1321 const char* controller_id,
1322 const char* feature_name)
1324 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1325 ->HasFeature(controller_id, feature_name);
1330 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->GetTopology();
1336 static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->FreeTopology(topology);
1341 unsigned int controller_count)
1343 if (controllers ==
nullptr)
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]);
1351 static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1352 ->SetControllerLayouts(controllerList);
1357 const char* controller_id)
1359 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1360 ->EnableKeyboard(enable, controller_id);
1365 const char* controller_id)
1367 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1368 ->EnableMouse(enable, controller_id);
1373 const char* port_address,
1374 const char* controller_id)
1376 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1377 ->ConnectController(connect, port_address, controller_id);
1383 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->InputEvent(*event);
1390 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->SerializeSize();
1397 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->Serialize(data, size);
1401 const uint8_t* data,
1404 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->Deserialize(data, size);
1411 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->CheatReset();
1419 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1420 ->GetMemory(type, *data, *size);
1428 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1429 ->SetCheat(index, enabled, code);
1434 unsigned int consoleID,
1435 const char* filePath)
1437 std::string cppHash;
1439 GAME_ERROR ret =
static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1440 ->RCGenerateHashFromFile(cppHash, consoleID, filePath);
1441 if (!cppHash.empty() && hash)
1443 *hash =
new char[cppHash.size() + 1];
1444 std::copy(cppHash.begin(), cppHash.end(), *hash);
1445 (*hash)[cppHash.size()] =
'\0';
1456 static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->RCGetGameIDUrl(cppUrl, hash);
1457 if (!cppUrl.empty() && url)
1459 *url =
new char[cppUrl.size() + 1];
1460 std::copy(cppUrl.begin(), cppUrl.end(), *url);
1461 (*url)[cppUrl.size()] =
'\0';
1468 const char* username,
1470 unsigned int gameID)
1474 GAME_ERROR ret =
static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1475 ->RCGetPatchFileUrl(cppUrl, username, token, gameID);
1476 if (!cppUrl.empty() && url)
1478 *url =
new char[cppUrl.size() + 1];
1479 std::copy(cppUrl.begin(), cppUrl.end(), *url);
1480 (*url)[cppUrl.size()] =
'\0';
1488 const char* username,
1490 unsigned int gameID,
1491 const char* richPresence)
1494 std::string cppPostData;
1496 static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1497 ->RCPostRichPresenceUrl(cppUrl, cppPostData, username, token, gameID, richPresence);
1498 if (!cppUrl.empty())
1500 *url =
new char[cppUrl.size() + 1];
1501 std::copy(cppUrl.begin(), cppUrl.end(), *url);
1502 (*url)[cppUrl.size()] =
'\0';
1504 if (!cppPostData.empty())
1506 *postData =
new char[cppPostData.size() + 1];
1507 std::copy(cppPostData.begin(), cppPostData.end(), *postData);
1508 (*postData)[cppPostData.size()] =
'\0';
1517 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1518 ->RCEnableRichPresence(script);
1523 unsigned int consoleID)
1525 std::string cppEvaluation;
1526 GAME_ERROR ret =
static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1527 ->RCGetRichPresenceEvaluation(cppEvaluation, consoleID);
1528 if (!cppEvaluation.empty())
1530 *evaluation =
new char[cppEvaluation.size() + 1];
1531 std::copy(cppEvaluation.begin(), cppEvaluation.end(), *evaluation);
1532 (*evaluation)[cppEvaluation.size()] =
'\0';
1540 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->RCResetRuntime();
1545 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->GetEjectState();
1550 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->SetEjectState(ejected);
1555 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->GetImageIndex();
1559 unsigned int imageIndex)
1561 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->SetImageIndex(imageIndex);
1566 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->GetImageCount();
1571 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->AddImageIndex();
1575 unsigned int imageIndex,
1576 const char* filePath)
1578 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1579 ->ReplaceImageIndex(imageIndex, filePath ? filePath :
"");
1583 unsigned int imageIndex)
1585 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1586 ->RemoveImageIndex(imageIndex);
1590 unsigned int imageIndex,
1591 const char* filePath)
1593 return static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)
1594 ->SetInitialImage(imageIndex, filePath ? filePath :
"");
1598 unsigned int imageIndex)
1600 std::string cppPath =
1601 static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->GetImagePath(imageIndex);
1602 if (cppPath.empty())
1605 char* path =
new char[cppPath.size() + 1];
1606 std::copy(cppPath.begin(), cppPath.end(), path);
1607 path[cppPath.size()] =
'\0';
1612 unsigned int imageIndex)
1614 std::string cppLabel =
1615 static_cast<CInstanceGame*
>(instance->toAddon->addonInstance)->GetImageLabel(imageIndex);
1616 if (cppLabel.empty())
1619 char* label =
new char[cppLabel.size() + 1];
1620 std::copy(cppLabel.begin(), cppLabel.end(), label);
1621 label[cppLabel.size()] =
'\0';