2019-04-13 12:21:56 -04:00
/* Copyright (C) 2019 Mr Goldberg
This file is part of the Goldberg Emulator
The Goldberg Emulator is free software ; you can redistribute it and / or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation ; either
version 3 of the License , or ( at your option ) any later version .
The Goldberg Emulator is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
Lesser General Public License for more details .
You should have received a copy of the GNU Lesser General Public
License along with the Goldberg Emulator ; if not , see
< http : //www.gnu.org/licenses/>. */
2023-12-27 09:21:59 +02:00
# include "dll/steam_apps.h"
# include "sha/sha1.hpp"
2019-04-13 12:21:56 -04:00
2024-04-11 06:40:29 +02:00
Steam_Apps : : Steam_Apps ( Settings * settings , class SteamCallResults * callback_results , class SteamCallBacks * callbacks )
2019-04-13 12:21:56 -04:00
{
this - > settings = settings ;
this - > callback_results = callback_results ;
2024-04-11 06:40:29 +02:00
this - > callbacks = callbacks ;
2019-04-13 12:21:56 -04:00
}
2022-07-31 15:49:45 -04:00
// returns 0 if the key does not exist
// this may be true on first call, since the app data may not be cached locally yet
// If you expect it to exists wait for the AppDataChanged_t after the first failure and ask again
int Steam_Apps : : GetAppData ( AppId_t nAppID , const char * pchKey , char * pchValue , int cchValueMax )
{
//TODO
2024-04-06 07:55:08 +02:00
PRINT_DEBUG_TODO ( ) ;
2022-07-31 15:49:45 -04:00
return 0 ;
}
2019-04-13 12:21:56 -04:00
bool Steam_Apps : : BIsSubscribed ( )
{
2024-04-06 07:55:08 +02:00
PRINT_DEBUG_ENTRY ( ) ;
2019-04-13 12:21:56 -04:00
return true ;
}
bool Steam_Apps : : BIsLowViolence ( )
{
2024-04-06 07:55:08 +02:00
PRINT_DEBUG_ENTRY ( ) ;
2019-04-13 12:21:56 -04:00
return false ;
}
bool Steam_Apps : : BIsCybercafe ( )
{
2024-04-06 07:55:08 +02:00
PRINT_DEBUG_ENTRY ( ) ;
2019-04-13 12:21:56 -04:00
return false ;
}
bool Steam_Apps : : BIsVACBanned ( )
{
2024-04-06 07:55:08 +02:00
PRINT_DEBUG_ENTRY ( ) ;
2019-04-13 12:21:56 -04:00
return false ;
}
2024-04-06 07:55:08 +02:00
// valid list: https://partner.steamgames.com/doc/store/localization/languages
2019-04-13 12:21:56 -04:00
const char * Steam_Apps : : GetCurrentGameLanguage ( )
{
2024-04-06 07:55:08 +02:00
PRINT_DEBUG_ENTRY ( ) ;
2024-01-25 22:51:09 +02:00
std : : lock_guard < std : : recursive_mutex > lock ( global_mutex ) ;
2019-04-13 12:21:56 -04:00
return settings - > get_language ( ) ;
}
2024-04-06 07:55:08 +02:00
// Gets a comma separated list of the languages the current app supports.
// valid list: https://partner.steamgames.com/doc/store/localization/languages
2019-04-13 12:21:56 -04:00
const char * Steam_Apps : : GetAvailableGameLanguages ( )
{
2024-04-06 07:55:08 +02:00
PRINT_DEBUG_ENTRY ( ) ;
2024-01-25 22:51:09 +02:00
std : : lock_guard < std : : recursive_mutex > lock ( global_mutex ) ;
2024-04-06 07:55:08 +02:00
return settings - > get_supported_languages ( ) . c_str ( ) ;
2019-04-13 12:21:56 -04:00
}
// only use this member if you need to check ownership of another game related to yours, a demo for example
bool Steam_Apps : : BIsSubscribedApp ( AppId_t appID )
{
2024-04-06 07:55:08 +02:00
PRINT_DEBUG ( " %u " , appID ) ;
2019-04-13 12:21:56 -04:00
std : : lock_guard < std : : recursive_mutex > lock ( global_mutex ) ;
2024-06-30 05:46:47 +03:00
if ( appID = = 0 ) return false ; // steam returns false
if ( appID = = UINT32_MAX ) return true ; // steam returns true
if ( appID = = settings - > get_local_game_id ( ) . AppID ( ) ) return true ; // steam returns true
2019-04-13 12:21:56 -04:00
return settings - > hasDLC ( appID ) ;
}
// Takes AppID of DLC and checks if the user owns the DLC & if the DLC is installed
bool Steam_Apps : : BIsDlcInstalled ( AppId_t appID )
{
2024-04-06 07:55:08 +02:00
PRINT_DEBUG ( " %u " , appID ) ;
2019-04-13 12:21:56 -04:00
std : : lock_guard < std : : recursive_mutex > lock ( global_mutex ) ;
2024-06-30 05:46:47 +03:00
if ( appID = = 0 ) return false ; // steam returns false (also appid 1958220 expects false otherwise it hangs in loading screen)
if ( appID = = UINT32_MAX ) return false ; // steam returns false
2024-03-17 01:22:18 +02:00
// Age of Empires 2: Definitive Edition expects the app itself to be an owned DLC.
// otherwise it will only load the "Return of Rome" game mode, also most options are disabled
2024-06-30 05:46:47 +03:00
if ( appID = = settings - > get_local_game_id ( ) . AppID ( ) ) return true ; // steam returns true
2024-03-17 01:22:18 +02:00
2019-04-13 12:21:56 -04:00
return settings - > hasDLC ( appID ) ;
}
// returns the Unix time of the purchase of the app
uint32 Steam_Apps : : GetEarliestPurchaseUnixTime ( AppId_t nAppID )
{
2024-04-06 07:55:08 +02:00
PRINT_DEBUG_ENTRY ( ) ;
2023-12-19 04:19:16 +02:00
std : : lock_guard < std : : recursive_mutex > lock ( global_mutex ) ;
2024-06-30 05:46:47 +03:00
if ( nAppID = = 0 ) return 0 ; // steam returns 0
if ( nAppID = = UINT32_MAX ) return 0 ; // steam returns 0
2023-12-19 04:19:16 +02:00
if ( nAppID = = settings - > get_local_game_id ( ) . AppID ( ) | | settings - > hasDLC ( nAppID ) ) {
auto t =
2023-12-28 02:15:09 +02:00
// 4 days ago
startup_time
- std : : chrono : : hours ( 24 * 4 ) ;
2023-12-19 04:19:16 +02:00
auto duration = std : : chrono : : duration_cast < std : : chrono : : seconds > ( t . time_since_epoch ( ) ) ;
return ( uint32 ) duration . count ( ) ;
}
2019-04-13 12:21:56 -04:00
//TODO ?
2023-12-19 04:19:16 +02:00
return 0 ;
2019-04-13 12:21:56 -04:00
}
// Checks if the user is subscribed to the current app through a free weekend
// This function will return false for users who have a retail or other type of license
// Before using, please ask your Valve technical contact how to package and secure your free weekened
bool Steam_Apps : : BIsSubscribedFromFreeWeekend ( )
{
2024-04-06 07:55:08 +02:00
PRINT_DEBUG_ENTRY ( ) ;
2019-04-13 12:21:56 -04:00
return false ;
}
// Returns the number of DLC pieces for the running app
int Steam_Apps : : GetDLCCount ( )
{
2024-04-06 07:55:08 +02:00
PRINT_DEBUG_ENTRY ( ) ;
2019-04-13 12:21:56 -04:00
std : : lock_guard < std : : recursive_mutex > lock ( global_mutex ) ;
return settings - > DLCCount ( ) ;
}
// Returns metadata for DLC by index, of range [0, GetDLCCount()]
bool Steam_Apps : : BGetDLCDataByIndex ( int iDLC , AppId_t * pAppID , bool * pbAvailable , char * pchName , int cchNameBufferSize )
{
2024-04-06 07:55:08 +02:00
PRINT_DEBUG_ENTRY ( ) ;
2019-04-13 12:21:56 -04:00
std : : lock_guard < std : : recursive_mutex > lock ( global_mutex ) ;
2024-01-25 22:51:09 +02:00
AppId_t appid = k_uAppIdInvalid ;
bool available = false ;
std : : string name { } ;
2019-04-13 12:21:56 -04:00
if ( ! settings - > getDLC ( iDLC , appid , available , name ) ) return false ;
if ( pAppID ) * pAppID = appid ;
if ( pbAvailable ) * pbAvailable = available ;
if ( pchName & & cchNameBufferSize > 0 ) {
2024-01-25 22:51:09 +02:00
memset ( pchName , 0 , cchNameBufferSize ) ;
name . copy ( pchName , cchNameBufferSize - 1 ) ;
2019-04-13 12:21:56 -04:00
}
return true ;
}
// Install/Uninstall control for optional DLC
void Steam_Apps : : InstallDLC ( AppId_t nAppID )
{
2024-04-11 06:40:29 +02:00
PRINT_DEBUG_TODO ( ) ;
2023-12-19 22:17:29 +02:00
// we lock here because the API is supposed to modify the DLC list
std : : lock_guard < std : : recursive_mutex > lock ( global_mutex ) ;
2024-04-11 06:40:29 +02:00
if ( settings - > hasDLC ( nAppID ) ) {
DlcInstalled_t data { } ;
data . m_nAppID = nAppID ;
callbacks - > addCBResult ( data . k_iCallback , & data , sizeof ( data ) , 0.01 ) ;
}
2019-04-13 12:21:56 -04:00
}
void Steam_Apps : : UninstallDLC ( AppId_t nAppID )
{
2024-04-06 07:55:08 +02:00
PRINT_DEBUG_ENTRY ( ) ;
2023-12-19 22:17:29 +02:00
// we lock here because the API is supposed to modify the DLC list
std : : lock_guard < std : : recursive_mutex > lock ( global_mutex ) ;
2019-04-13 12:21:56 -04:00
}
2023-12-19 04:20:59 +02:00
static void FillProofOfPurchaseKey ( AppProofOfPurchaseKeyResponse_t & data , AppId_t nAppID , bool ok_result , std : : string key = " cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd " )
{
data . m_nAppID = nAppID ;
if ( ok_result ) {
// TODO maybe read this from a config file "purchased_keys.txt":
// 480=AAAAA-BBBBB-CCCCC-DDDDD
// 218620=XYZFJ-13370-98765
size_t min_len = key . size ( ) < k_cubAppProofOfPurchaseKeyMax
? key . size ( ) < k_cubAppProofOfPurchaseKeyMax
: k_cubAppProofOfPurchaseKeyMax - 1 ; // -1 because we need space for null
data . m_eResult = EResult : : k_EResultOK ;
2024-05-25 14:59:13 +02:00
data . m_cchKeyLength = static_cast < uint32 > ( min_len ) ;
2023-12-19 04:20:59 +02:00
memcpy ( data . m_rgchKey , key . c_str ( ) , min_len ) ;
data . m_rgchKey [ min_len ] = 0 ;
} else {
data . m_eResult = EResult : : k_EResultFail ;
data . m_cchKeyLength = 0 ;
data . m_rgchKey [ 0 ] = 0 ;
data . m_rgchKey [ 1 ] = 0 ;
}
}
2019-04-13 12:21:56 -04:00
// Request legacy cd-key for yourself or owned DLC. If you are interested in this
// data then make sure you provide us with a list of valid keys to be distributed
// to users when they purchase the game, before the game ships.
// You'll receive an AppProofOfPurchaseKeyResponse_t callback when
// the key is available (which may be immediately).
void Steam_Apps : : RequestAppProofOfPurchaseKey ( AppId_t nAppID )
{
2024-04-06 07:55:08 +02:00
PRINT_DEBUG_TODO ( ) ;
2023-12-19 04:20:59 +02:00
std : : lock_guard < std : : recursive_mutex > lock ( global_mutex ) ;
AppProofOfPurchaseKeyResponse_t data { } ;
data . m_nAppID = nAppID ;
// check Steam_Apps::BIsAppInstalled()
if ( nAppID = = 0 | | nAppID = = UINT32_MAX ) {
FillProofOfPurchaseKey ( data , nAppID , false ) ;
} else if ( nAppID = = settings - > get_local_game_id ( ) . AppID ( ) | | settings - > hasDLC ( nAppID ) ) {
FillProofOfPurchaseKey ( data , nAppID , true ) ;
} else {
//TODO what to do here?
FillProofOfPurchaseKey ( data , nAppID , false ) ;
}
2024-04-11 06:40:29 +02:00
callbacks - > addCBResult ( data . k_iCallback , & data , sizeof ( data ) ) ;
2019-04-13 12:21:56 -04:00
}
// returns current beta branch name, 'public' is the default branch
2023-12-18 05:21:31 +02:00
// "true if the user is on a beta branch; otherwise, false"
// https://partner.steamgames.com/doc/api/ISteamApps
2019-04-13 12:21:56 -04:00
bool Steam_Apps : : GetCurrentBetaName ( char * pchName , int cchNameBufferSize )
{
2024-04-06 07:55:08 +02:00
PRINT_DEBUG ( " %p [%i] " , pchName , cchNameBufferSize ) ;
2023-12-19 22:17:29 +02:00
std : : lock_guard < std : : recursive_mutex > lock ( global_mutex ) ;
2024-07-03 01:30:34 +03:00
const auto & current_branch_name = settings - > branches [ settings - > selected_branch_idx ] . name ;
if ( pchName & & cchNameBufferSize > 0 & & static_cast < size_t > ( cchNameBufferSize ) > current_branch_name . size ( ) ) {
2024-03-17 01:58:57 +02:00
memset ( pchName , 0 , cchNameBufferSize ) ;
2024-07-03 01:30:34 +03:00
memcpy ( pchName , current_branch_name . c_str ( ) , current_branch_name . size ( ) ) ;
2019-04-13 12:21:56 -04:00
}
2024-06-04 14:58:16 +03:00
PRINT_DEBUG ( " returned '%s' " , pchName ) ;
2023-12-18 05:21:31 +02:00
return settings - > is_beta_branch ;
2019-04-13 12:21:56 -04:00
}
// signal Steam that game files seems corrupt or missing
bool Steam_Apps : : MarkContentCorrupt ( bool bMissingFilesOnly )
{
2024-04-06 07:55:08 +02:00
PRINT_DEBUG_TODO ( ) ;
2023-12-19 22:17:29 +02:00
std : : lock_guard < std : : recursive_mutex > lock ( global_mutex ) ;
2019-04-13 12:21:56 -04:00
//TODO: warn user
return true ;
}
// return installed depots in mount order
uint32 Steam_Apps : : GetInstalledDepots ( AppId_t appID , DepotId_t * pvecDepots , uint32 cMaxDepots )
{
2024-04-06 07:55:08 +02:00
PRINT_DEBUG ( " %u, %u " , appID , cMaxDepots ) ;
2019-07-20 14:45:37 -04:00
//TODO not sure about the behavior of this function, I didn't actually test this.
std : : lock_guard < std : : recursive_mutex > lock ( global_mutex ) ;
2024-01-25 22:51:09 +02:00
unsigned int count = ( unsigned int ) settings - > depots . size ( ) ;
if ( ! pvecDepots | | ! cMaxDepots | | ! count ) return 0 ;
2020-01-31 14:31:29 -05:00
if ( cMaxDepots < count ) count = cMaxDepots ;
std : : copy ( settings - > depots . begin ( ) , settings - > depots . begin ( ) + count , pvecDepots ) ;
return count ;
}
2019-07-20 14:45:37 -04:00
2020-01-31 14:32:28 -05:00
uint32 Steam_Apps : : GetInstalledDepots ( DepotId_t * pvecDepots , uint32 cMaxDepots )
{
2024-04-06 07:55:08 +02:00
PRINT_DEBUG ( " old " ) ;
2020-01-31 14:32:28 -05:00
return GetInstalledDepots ( settings - > get_local_game_id ( ) . AppID ( ) , pvecDepots , cMaxDepots ) ;
2019-04-13 12:21:56 -04:00
}
// returns current app install folder for AppID, returns folder name length
uint32 Steam_Apps : : GetAppInstallDir ( AppId_t appID , char * pchFolder , uint32 cchFolderBufferSize )
{
2024-04-06 07:55:08 +02:00
PRINT_DEBUG ( " %u %p %u " , appID , pchFolder , cchFolderBufferSize ) ;
2021-09-19 01:07:19 -04:00
std : : lock_guard < std : : recursive_mutex > lock ( global_mutex ) ;
2019-04-13 12:21:56 -04:00
//TODO return real path instead of dll path
2019-05-09 08:10:03 -04:00
std : : string installed_path = settings - > getAppInstallPath ( appID ) ;
2024-01-25 22:51:09 +02:00
if ( installed_path . empty ( ) ) {
2019-05-09 08:10:03 -04:00
std : : string dll_path = get_full_program_path ( ) ;
std : : string current_path = get_current_path ( ) ;
2024-04-06 07:55:08 +02:00
PRINT_DEBUG ( " dll: '%s', current: '%s' " , dll_path . c_str ( ) , current_path . c_str ( ) ) ;
2019-05-09 08:10:03 -04:00
//Just pick the smallest path, it has the most chances of being the good one
if ( dll_path . size ( ) > current_path . size ( ) & & current_path . size ( ) ) {
installed_path = current_path ;
} else {
installed_path = dll_path ;
}
}
2024-04-06 07:55:08 +02:00
PRINT_DEBUG ( " final path '%s' " , installed_path . c_str ( ) ) ;
2024-01-25 22:51:09 +02:00
if ( pchFolder & & cchFolderBufferSize ) {
memset ( pchFolder , 0 , cchFolderBufferSize ) ;
installed_path . copy ( pchFolder , cchFolderBufferSize - 1 ) ;
2019-12-12 14:11:05 -05:00
}
2024-05-25 14:59:13 +02:00
return static_cast < uint32 > ( installed_path . length ( ) ) ; //Real steam always returns the actual path length, not the copied one.
2019-04-13 12:21:56 -04:00
}
// returns true if that app is installed (not necessarily owned)
2023-12-18 05:08:23 +02:00
// "This only works for base applications, not Downloadable Content (DLC). Use BIsDlcInstalled for DLC instead"
// https://partner.steamgames.com/doc/api/ISteamApps
2019-04-13 12:21:56 -04:00
bool Steam_Apps : : BIsAppInstalled ( AppId_t appID )
{
2024-04-06 07:55:08 +02:00
PRINT_DEBUG ( " %u " , appID ) ;
2023-12-18 15:03:14 +02:00
std : : lock_guard < std : : recursive_mutex > lock ( global_mutex ) ;
2024-06-30 05:46:47 +03:00
if ( appID = = 0 ) return false ; // steam returns false
2024-01-25 20:33:02 +02:00
// game LEGO 2K Drive (app id 1451810) checks for a proper steam behavior by sending uint32_max and expects false in return
2024-06-30 05:46:47 +03:00
if ( appID = = UINT32_MAX ) return false ; // steam returns false
if ( appID = = settings - > get_local_game_id ( ) . AppID ( ) ) return true ; // steam returns true
2023-12-18 05:08:23 +02:00
2024-04-20 19:30:29 +02:00
// TODO is this correct?
// the docs say that this function won't work on DLCs, but HITMAN 3 uses it on every DLC
if ( settings - > hasDLC ( appID ) ) return true ;
2023-12-18 15:03:14 +02:00
2024-04-27 23:19:10 +03:00
return settings - > isAppInstalled ( appID ) ;
2019-04-13 12:21:56 -04:00
}
// returns the SteamID of the original owner. If different from current user, it's borrowed
CSteamID Steam_Apps : : GetAppOwner ( )
{
2024-04-06 07:55:08 +02:00
PRINT_DEBUG_ENTRY ( ) ;
2023-12-19 22:17:29 +02:00
std : : lock_guard < std : : recursive_mutex > lock ( global_mutex ) ;
2019-04-13 12:21:56 -04:00
return settings - > get_local_steam_id ( ) ;
}
// Returns the associated launch param if the game is run via steam://run/<appid>//?param1=value1;param2=value2;param3=value3 etc.
// Parameter names starting with the character '@' are reserved for internal use and will always return and empty string.
// Parameter names starting with an underscore '_' are reserved for steam features -- they can be queried by the game,
// but it is advised that you not param names beginning with an underscore for your own features.
const char * Steam_Apps : : GetLaunchQueryParam ( const char * pchKey )
{
2024-04-06 07:55:08 +02:00
PRINT_DEBUG_TODO ( ) ;
std : : lock_guard < std : : recursive_mutex > lock ( global_mutex ) ;
2019-04-13 12:21:56 -04:00
return " " ;
}
// get download progress for optional DLC
bool Steam_Apps : : GetDlcDownloadProgress ( AppId_t nAppID , uint64 * punBytesDownloaded , uint64 * punBytesTotal )
{
2024-04-06 07:55:08 +02:00
PRINT_DEBUG_ENTRY ( ) ;
2023-12-19 22:17:29 +02:00
std : : lock_guard < std : : recursive_mutex > lock ( global_mutex ) ;
2019-04-13 12:21:56 -04:00
return false ;
}
// return the buildid of this app, may change at any time based on backend updates to the game
int Steam_Apps : : GetAppBuildId ( )
{
2024-04-06 07:55:08 +02:00
PRINT_DEBUG_ENTRY ( ) ;
2023-12-19 22:17:29 +02:00
std : : lock_guard < std : : recursive_mutex > lock ( global_mutex ) ;
2024-07-03 01:30:34 +03:00
return static_cast < int > ( this - > settings - > branches [ settings - > selected_branch_idx ] . build_id ) ;
2019-04-13 12:21:56 -04:00
}
// Request all proof of purchase keys for the calling appid and asociated DLC.
// A series of AppProofOfPurchaseKeyResponse_t callbacks will be sent with
// appropriate appid values, ending with a final callback where the m_nAppId
// member is k_uAppIdInvalid (zero).
void Steam_Apps : : RequestAllProofOfPurchaseKeys ( )
{
2024-04-06 07:55:08 +02:00
PRINT_DEBUG_TODO ( ) ;
2023-12-19 04:20:59 +02:00
std : : lock_guard < std : : recursive_mutex > lock ( global_mutex ) ;
// current app
{
AppProofOfPurchaseKeyResponse_t data { } ;
FillProofOfPurchaseKey ( data , settings - > get_local_game_id ( ) . AppID ( ) , true ) ;
2024-05-07 06:22:34 +03:00
callbacks - > addCBResult ( data . k_iCallback , & data , sizeof ( data ) ) ;
2023-12-19 04:20:59 +02:00
}
// DLCs
const auto count = settings - > DLCCount ( ) ;
2024-05-25 14:59:13 +02:00
for ( unsigned int i = 0 ; i < settings - > DLCCount ( ) ; i + + ) {
2023-12-19 04:20:59 +02:00
AppId_t app_id ;
bool available ;
std : : string name ;
settings - > getDLC ( i , app_id , available , name ) ;
AppProofOfPurchaseKeyResponse_t data { } ;
FillProofOfPurchaseKey ( data , app_id , true ) ;
2024-05-07 06:22:34 +03:00
callbacks - > addCBResult ( data . k_iCallback , & data , sizeof ( data ) ) ;
2023-12-19 04:20:59 +02:00
}
// termination entry
{
AppProofOfPurchaseKeyResponse_t data { } ;
FillProofOfPurchaseKey ( data , k_uAppIdInvalid , true , " " ) ;
2024-05-07 06:22:34 +03:00
callbacks - > addCBResult ( data . k_iCallback , & data , sizeof ( data ) ) ;
2023-12-19 04:20:59 +02:00
}
2019-04-13 12:21:56 -04:00
}
STEAM_CALL_RESULT ( FileDetailsResult_t )
SteamAPICall_t Steam_Apps : : GetFileDetails ( const char * pszFileName )
{
2024-04-06 07:55:08 +02:00
PRINT_DEBUG ( " %s " , pszFileName ) ;
std : : lock_guard < std : : recursive_mutex > lock ( global_mutex ) ;
2021-09-19 01:07:19 -04:00
FileDetailsResult_t data = { } ;
//TODO? this function should only return found if file is actually part of the steam depots
if ( file_exists_ ( pszFileName ) ) {
data . m_eResult = k_EResultOK ; //
2024-05-22 05:29:20 +03:00
std : : ifstream stream ( std : : filesystem : : u8path ( pszFileName ) , std : : ios : : binary ) ;
2021-09-19 01:07:19 -04:00
SHA1 checksum ;
checksum . update ( stream ) ;
checksum . final ( ) . copy ( ( char * ) data . m_FileSHA , sizeof ( data . m_FileSHA ) ) ;
data . m_ulFileSize = file_size_ ( pszFileName ) ;
//TODO data.m_unFlags; 0 is file //TODO: check if 64 is folder
} else {
data . m_eResult = k_EResultFileNotFound ;
}
2024-04-11 06:40:29 +02:00
auto ret = callback_results - > addCallResult ( data . k_iCallback , & data , sizeof ( data ) ) ;
callbacks - > addCBResult ( data . k_iCallback , & data , sizeof ( data ) ) ;
return ret ;
2019-04-13 12:21:56 -04:00
}
// Get command line if game was launched via Steam URL, e.g. steam://run/<appid>//<command line>/.
// This method of passing a connect string (used when joining via rich presence, accepting an
// invite, etc) is preferable to passing the connect string on the operating system command
// line, which is a security risk. In order for rich presence joins to go through this
// path and not be placed on the OS command line, you must set a value in your app's
// configuration on Steam. Ask Valve for help with this.
//
// If game was already running and launched again, the NewUrlLaunchParameters_t will be fired.
int Steam_Apps : : GetLaunchCommandLine ( char * pszCommandLine , int cubCommandLine )
{
2024-04-06 07:55:08 +02:00
PRINT_DEBUG_TODO ( ) ;
std : : lock_guard < std : : recursive_mutex > lock ( global_mutex ) ;
2019-04-13 12:21:56 -04:00
return 0 ;
}
// Check if user borrowed this game via Family Sharing, If true, call GetAppOwner() to get the lender SteamID
bool Steam_Apps : : BIsSubscribedFromFamilySharing ( )
{
2024-04-06 07:55:08 +02:00
PRINT_DEBUG_ENTRY ( ) ;
2023-12-19 22:17:29 +02:00
std : : lock_guard < std : : recursive_mutex > lock ( global_mutex ) ;
2019-04-13 12:21:56 -04:00
return false ;
}
2020-06-14 16:04:43 -04:00
// check if game is a timed trial with limited playtime
bool Steam_Apps : : BIsTimedTrial ( uint32 * punSecondsAllowed , uint32 * punSecondsPlayed )
{
2024-04-06 07:55:08 +02:00
PRINT_DEBUG_ENTRY ( ) ;
2023-12-19 22:17:29 +02:00
std : : lock_guard < std : : recursive_mutex > lock ( global_mutex ) ;
2020-06-14 16:04:43 -04:00
return false ;
}
2022-08-05 01:32:20 -04:00
2024-07-03 01:30:34 +03:00
// TODO no public docs
2022-08-05 01:32:20 -04:00
// set current DLC AppID being played (or 0 if none). Allows Steam to track usage of major DLC extensions
bool Steam_Apps : : SetDlcContext ( AppId_t nAppID )
{
2024-07-03 01:30:34 +03:00
PRINT_DEBUG ( " %u // TODO " , nAppID ) ;
2023-12-19 22:17:29 +02:00
std : : lock_guard < std : : recursive_mutex > lock ( global_mutex ) ;
2024-07-03 01:30:34 +03:00
2024-07-06 01:41:50 +03:00
// TODO this one is very odd, in all other functions of this interface they were returning false
// tested by `universal963` on real steam
if ( nAppID = = 0 ) return true ;
2024-07-03 01:30:34 +03:00
if ( nAppID = = UINT32_MAX ) return false ; // TODO is this correct? (see Steam_Apps::BIsDlcInstalled)
if ( nAppID = = settings - > get_local_game_id ( ) . AppID ( ) ) return true ; // TODO is this correct?
return settings - > hasDLC ( nAppID ) ;
2022-08-05 01:32:20 -04:00
}
2024-04-11 06:40:29 +02:00
2024-07-03 01:30:34 +03:00
// TODO no public docs
2024-06-30 16:17:31 +02:00
// returns total number of known app beta branches (including default "public" branch )
int Steam_Apps : : GetNumBetas ( int * pnAvailable , int * pnPrivate )
{
2024-07-01 09:03:12 +03:00
PRINT_DEBUG ( " %p, %p " , pnAvailable , pnPrivate ) ;
2024-06-30 16:17:31 +02:00
std : : lock_guard < std : : recursive_mutex > lock ( global_mutex ) ;
2024-07-01 09:03:12 +03:00
2024-07-03 01:30:34 +03:00
// I assume 'available' means installed on the user's disk and could be used
// in that case only 1 should be *available* since the user can only have 1 active and usable branch with the emu, unlike real steam
// the user can switch the active (available) branch from configs.app.ini
// right??
if ( pnAvailable ) { // TODO what is this?
* pnAvailable = 0 ;
for ( const auto & item : settings - > branches ) {
if ( item . flags & EBetaBranchFlags : : k_EBetaBranch_Available ) {
* pnAvailable + = 1 ;
}
}
PRINT_DEBUG ( " available branches = %i " , * pnAvailable ) ;
}
if ( pnPrivate ) {
* pnPrivate = 0 ;
for ( const auto & item : settings - > branches ) {
if ( item . flags & EBetaBranchFlags : : k_EBetaBranch_Private ) {
* pnPrivate + = 1 ;
}
}
PRINT_DEBUG ( " private branches = %i " , * pnPrivate ) ;
}
return static_cast < int > ( settings - > branches . size ( ) ) ; // we always return at least 1 since "public" branch
2024-06-30 16:17:31 +02:00
}
2024-07-01 09:03:12 +03:00
// TODO no public docs
2024-06-30 16:17:31 +02:00
// return beta branch details, name, description, current BuildID and state flags (EBetaBranchFlags)
bool Steam_Apps : : GetBetaInfo ( int iBetaIndex , uint32 * punFlags , uint32 * punBuildID , char * pchBetaName , int cchBetaName , char * pchDescription , int cchDescription ) // iterate through
{
2024-07-01 09:03:12 +03:00
// I assume this API is like "Steam_User_Stats::GetNextMostAchievedAchievementInfo()", it returns 'ok' until index is out of range
2024-07-03 01:30:34 +03:00
PRINT_DEBUG ( " [%i] %p %p --- %p %i --- %p %i " , iBetaIndex , punFlags , punBuildID , pchBetaName , cchBetaName , pchDescription , cchDescription ) ;
2024-06-30 16:17:31 +02:00
std : : lock_guard < std : : recursive_mutex > lock ( global_mutex ) ;
2024-07-01 09:03:12 +03:00
if ( iBetaIndex < 0 ) return false ;
2024-07-03 01:30:34 +03:00
if ( static_cast < size_t > ( iBetaIndex ) > = settings - > branches . size ( ) ) return false ;
2024-07-01 09:03:12 +03:00
2024-07-03 01:30:34 +03:00
const auto & branch = settings - > branches [ iBetaIndex ] ;
if ( punFlags ) * punFlags = branch . flags ;
if ( punBuildID ) * punBuildID = branch . build_id ;
2024-07-01 09:03:12 +03:00
2024-07-03 01:30:34 +03:00
if ( pchBetaName & & cchBetaName > 0 & & static_cast < size_t > ( cchBetaName ) > branch . name . size ( ) ) {
2024-06-30 16:17:31 +02:00
memset ( pchBetaName , 0 , cchBetaName ) ;
2024-07-03 01:30:34 +03:00
memcpy ( pchBetaName , branch . name . c_str ( ) , branch . name . size ( ) ) ;
2024-06-30 16:17:31 +02:00
}
2024-07-01 09:03:12 +03:00
2024-07-03 01:30:34 +03:00
if ( pchDescription & & cchDescription > 0 & & static_cast < size_t > ( cchDescription ) > branch . description . size ( ) ) {
2024-06-30 16:17:31 +02:00
memset ( pchDescription , 0 , cchDescription ) ;
2024-07-03 01:30:34 +03:00
memcpy ( pchDescription , branch . description . c_str ( ) , branch . description . size ( ) ) ;
2024-06-30 16:17:31 +02:00
}
2024-07-01 09:03:12 +03:00
2024-06-30 16:17:31 +02:00
return true ;
}
2024-07-03 01:30:34 +03:00
// TODO no public docs
2024-06-30 16:17:31 +02:00
// select this beta branch for this app as active, might need the game to restart so Steam can update to that branch
bool Steam_Apps : : SetActiveBeta ( const char * pchBetaName )
{
2024-07-01 09:03:12 +03:00
PRINT_DEBUG ( " '%s' " , pchBetaName ) ;
2024-06-30 16:17:31 +02:00
std : : lock_guard < std : : recursive_mutex > lock ( global_mutex ) ;
2024-07-01 09:03:12 +03:00
2024-07-03 18:29:25 +03:00
// (sdk 1.60) apparently steam always returns true if the string is null or empty, tested by 'universal963' on appid 480
if ( ! pchBetaName | | ! pchBetaName [ 0 ] ) return true ;
2024-07-01 09:03:12 +03:00
2024-07-03 18:29:25 +03:00
std : : string beta_name = pchBetaName ;
2024-07-03 01:30:34 +03:00
auto branch_it = std : : find_if ( settings - > branches . begin ( ) , settings - > branches . end ( ) , [ & beta_name ] ( const Branch_Info & item ) {
return common_helpers : : str_cmp_insensitive ( beta_name , item . name ) ;
} ) ;
2024-07-01 09:03:12 +03:00
2024-07-03 01:30:34 +03:00
if ( settings - > branches . end ( ) ! = branch_it ) {
// reset the 'active' flag for all branches
for ( auto & item : settings - > branches ) {
item . active = false ;
}
// then set the flag for this branch
branch_it - > active = true ;
PRINT_DEBUG ( " game changed active beta branch! " ) ;
return true ;
}
2024-07-03 18:29:25 +03:00
return false ;
2024-06-30 16:17:31 +02:00
}
2024-04-11 06:40:29 +02:00
# ifdef _PS3
// Result returned in a RegisterActivationCodeResponse_t callresult
SteamAPICall_t Steam_Apps : : RegisterActivationCode ( const char * pchActivationCode )
{
PRINT_DEBUG ( " %s " , pchActivationCode ) ;
std : : lock_guard < std : : recursive_mutex > lock ( global_mutex ) ;
if ( ! pchActivationCode ) return
RegisterActivationCodeResponse_t data { } ;
data . m_eResult = ERegisterActivationCodeResult : : k_ERegisterActivationCodeResultOK ;
// data.m_unPackageRegistered = 0; // TODO set this
auto ret = callback_results - > addCallResult ( data . k_iCallback , & data , sizeof ( data ) ) ;
callbacks - > addCBResult ( data . k_iCallback , & data , sizeof ( data ) ) ;
return ret ;
}
# endif