Minimal replacement layer for Games for Windows Live (GFWL) aka XLive.
Game | Implementation |
---|---|
Tron: Evolution | Used in TEM for offline usage and support on Linux w/Wine. |
Listeners are user-defined callbacks which are used to hook into functions. They allow to read and modify existing parameters but also overwrite the default return value.
TODO: Expose function signatures as types/macros? Or allow exports like XDead_XFriendsCreateEnumerator
?
Overview of the header file:
namespace xdead {
#define XDEAD_CALLBACK(type, name, ...) type __stdcall name##_callback(##__VA_ARGS__)
#define XDEAD_FUNCTION_NAME(name, ordinal) static constexpr auto name = ordinal
enum class ListenerStatus {
Ok = 0,
OrdinalNotFound = 1,
InvalidCallback = 2,
CallbackNotFound = 3,
};
// ...
XDEAD_FUNCTION_NAME(XFriendsCreateEnumerator, 5312);
// ...
auto __stdcall add_listener(uint32_t ordinal, void* callback, uint32_t index) -> ListenerStatus;
auto __stdcall remove_listener(uint32_t ordinal, void* callback) -> ListenerStatus;
auto __stdcall remove_all_listeners() -> ListenerStatus;
using add_listener_t = decltype(&add_listener);
using remove_listener_t = decltype(&remove_listener);
using remove_all_listeners_t = decltype(&remove_all_listeners);
}
The basic philosophy is to reimplement a small surface of the API, only to get the game working. After this step the user has the freedom for creativity to rewrite any features of XLive like account management, save files and UI etc.
TODO: could we use "context" for controlling the return-value?
// Define a callback
XDEAD_CALLBACK(signed int, XFriendsCreateEnumerator, int a1, int a2, int a3, int a4, int a5)
{
// By default XDead always returns 0 which in most functions means "success".
// If a callback returns anything else, all other callbacks of this
// functions will not run.
return 1;
}
// Get exported functions
auto xdead = GetModuleHandleA("xlive.dll");
auto xdead_add_listener = xdead::add_listener_t(
GetProcAddress(xdead, "xdead_add_listener")
);
auto xdead_remove_listener = xdead::remove_listener_t(
GetProcAddress(xdead, "xdead_remove_listener")
);
auto xdead_remove_all_listeners = xdead::remove_all_listeners_t(
GetProcAddress(xdead, "xdead_remove_all_listeners")
);
// Add callback as listener
auto status = xdead_add_listener(
xdead::XFriendsCreateEnumerator, // Provide ordinal by function name
XFriendsCreateEnumerator_callback, // Function from above
0 // Sort index
);
if (status == xdead::ListenerStatus::Ok) {
println("Added listener for XFriendsCreateEnumerator");
}
// Remove listener
xdead_remove_listener(XFriendsCreateEnumerator_callback);
// Or automatically remove all previously added listeners
// NOTE: This also remove listeners which have been added by other modules.
xdead_remove_all_listeners();
XDead can also be used to load additional modules automatically.
When the main process calls into XLiveInitialize/XLiveInitializeEx
, it will check for an existing xdead.json
definition file and then load each module sequentially.
TODO: Use YAML instead of JSON?
{
"version": "0.1.0",
"mods": [
{
"name": "tem",
"version": "0.1.0",
"author": "NeKz",
"path": "tem.dll",
}
]
}
View table
Function | Ordinal | |
---|---|---|
XWSAStartup | 1 | |
XWSACleanup | 2 | |
β | XSocketCreate | 3 |
β | XSocketClose | 4 |
XSocketShutdown | 5 | |
β | XSocketIOCTLSocket | 6 |
β | XSocketSetSockOpt | 7 |
β | XSocketGetSockOpt | 8 |
β | XSocketGetSockName | 9 |
XSocketGetPeerName | 10 | |
β | XSocketBind | 11 |
β | XSocketConnect | 12 |
β | XSocketListen | 13 |
β | XSocketAccept | 14 |
β | XSocketSelect | 15 |
XWSAGetOverlappedResult | 16 | |
XWSACancelOverlappedIO | 17 | |
β | XSocketRecv | 18 |
WSARecv | 19 | |
XSocketRecvFrom | 20 | |
XWSARecvFrom | 21 | |
β | XSocketSend | 22 |
XWSASend | 23 | |
β | XSocketSendTo | 24 |
XWSASendTo | 25 | |
XSocketInet_Addr | 26 | |
XSocketWSAGetLastError | 27 | |
XWSASetLastError | 28 | |
XWSACreateEvent | 29 | |
XWSACloseEvent | 30 | |
XWSASetEvent | 31 | |
XWSAResetEvent | 32 | |
XWSAWaitForMultipleEvents | 33 | |
XWSAFDIsSet | 34 | |
XWSAEventSelect | 35 | |
XSocketHTONL | 37 | |
β | XSocketNTOHS | 38 |
XSocketNTOHL | 39 | |
XSocketHTONS | 40 | |
β | XNetStartup | 51 |
β | XNetCleanup | 52 |
β | XNetRandom | 53 |
XNetCreateKey | 54 | |
β | XNetRegisterKey | 55 |
β | XNetUnregisterKey | 56 |
β | XNetXnAddrToInAddr | 57 |
β | XNetServerToInAddr | 58 |
XNetTsAddrToInAddr | 59 | |
XNetInAddrToXnAddr | 60 | |
XNetInAddrToServer | 61 | |
XNetInAddrToString | 62 | |
β | XNetUnregisterInAddr | 63 |
XNetXnAddrToMachineId | 64 | |
XNetConnect | 65 | |
XNetGetConnectStatus | 66 | |
β | XNetDnsLookup | 67 |
β | XNetDnsRelease | 68 |
β | XNetQosListen | 69 |
β | XNetQosLookup | 70 |
β | XNetQosServiceLookup | 71 |
β | XNetQosRelease | 72 |
β | XNetGetTitleXnAddr | 73 |
XNetGetDebugXnAddr | 74 | |
β | XNetGetEthernetLinkStatus | 75 |
XNetGetBroadcastVersionStatus | 76 | |
β | XNetQosGetListenStats | 77 |
XNetGetOpt | 78 | |
XNetSetOpt | 79 | |
XNetStartupEx | 80 | |
XNetReplaceKey | 81 | |
XNetGetXnAddrPlatform | 82 | |
XNetGetSystemLinkPort | 83 | |
β | XNetSetSystemLinkPort | 84 |
XNetSetSystemLinkPort | 84 | |
XCustomSetAction | 472 | |
XCustomGetLastActionPress | 473 | |
XCustomSetDynamicActions | 474 | |
XCustomGetLastActionPressEx | 476 | |
XCustomRegisterDynamicActions | 477 | |
XCustomUnregisterDynamicActions | 478 | |
XCustomGetCurrentGamercard | 479 | |
XNotifyGetNext | 651 | |
β | XNotifyPositionUI | 652 |
XNotifyDelayUI | 653 | |
β | XGetOverlappedExtendedError | 1082 |
XGetOverlappedResult | 1083 | |
XLiveInitialize | 5000 | |
XLiveInput | 5001 | |
XLiveRender | 5002 | |
β | XLiveUninitialize | 5003 |
XLiveOnCreateDevice | 5005 | |
β | XLiveOnDestroyDevice | 5006 |
β | XLiveOnResetDevice | 5007 |
β | XHVCreateEngine | 5008 |
XLiveRegisterDataSection | 5010 | |
XLiveUnregisterDataSection | 5011 | |
XLiveUpdateHashes | 5012 | |
β | XLivePBufferAllocate | 5016 |
β | XLivePBufferFree | 5017 |
XLivePBufferGetByte | 5018 | |
XLivePBufferSetByte | 5019 | |
XLivePBufferGetDWORD | 5020 | |
XLivePBufferSetDWORD | 5021 | |
XLiveGetUpdateInformation | 5022 | |
XNetGetCurrentAdapter | 5023 | |
XLiveUpdateSystem | 5024 | |
XLiveGetLiveIdError | 5025 | |
β | XLiveSetSponsorToken | 5026 |
XLiveUninstallTitle | 5027 | |
XLiveLoadLibraryEx | 5028 | |
XLiveFreeLibrary | 5029 | |
XLivePreTranslateMessage | 5030 | |
β | XLiveSetDebugLevel | 5031 |
XLiveVerifyArcadeLicense | 5032 | |
β | XLiveProtectData | 5034 |
β | XLiveUnprotectData | 5035 |
β | XLiveCreateProtectedDataContext | 5036 |
XLiveQueryProtectedDataInformation | 5037 | |
β | XLiveCloseProtectedDataContext | 5038 |
XLiveVerifyDataFile | 5039 | |
β | XShowMessagesUI | 5206 |
β | XShowGameInviteUI | 5208 |
β | XShowMessageComposeUI | 5209 |
β | XShowFriendRequestUI | 5210 |
β | XShowCustomPlayerListUI | 5212 |
β | XShowPlayerReviewUI | 5214 |
β | XShowGuideUI | 5215 |
β | XShowKeyboardUI | 5216 |
XShowArcadeUI | 5218 | |
XLocatorServerAdvertise | 5230 | |
XLocatorServerUnAdvertise | 5231 | |
XLocatorGetServiceProperty | 5233 | |
XLocatorCreateServerEnumerator | 5234 | |
XLocatorCreateServerEnumeratorByIDs | 5235 | |
XLocatorServiceInitialize | 5236 | |
XLocatorServiceUnInitialize | 5237 | |
XLocatorCreateKey | 5238 | |
β | XShowAchievementsUI | 5250 |
β | XCloseHandle | 5251 |
β | XShowGamerCardUI | 5252 |
XCancelOverlapped | 5254 | |
XEnumerateBack | 5255 | |
β | XEnumerate | 5256 |
XLiveManageCredentials | 5257 | |
β | XLiveSignout | 5258 |
β | XLiveSignin | 5259 |
β | XShowSigninUI | 5260 |
XUserGetXUID | 5261 | |
β | XUserGetSigninState | 5262 |
β | XUserGetName | 5263 |
β | XUserAreUsersFriends | 5264 |
β | XUserCheckPrivilege | 5265 |
XShowMessageBoxUI | 5266 | |
β | XUserGetSigninInfo | 5267 |
β | XNotifyCreateListener | 5270 |
β | XShowPlayersUI | 5271 |
XUserReadGamerPictureByKey | 5273 | |
β | XUserAwardGamerPicture | 5274 |
β | XShowFriendsUI | 5275 |
XUserSetProperty | 5276 | |
β | XUserSetContext | 5277 |
β | XUserWriteAchievements | 5278 |
β | XUserReadAchievementPicture | 5279 |
β | XUserCreateAchievementEnumerator | 5280 |
β | XUserReadStats | 5281 |
XUserReadGamerPicture | 5282 | |
β | XUserCreateStatsEnumeratorByRank | 5284 |
XUserCreateStatsEnumeratorByRating | 5285 | |
β | XUserCreateStatsEnumeratorByXuid | 5286 |
XUserResetStatsView | 5287 | |
XUserGetProperty | 5288 | |
XUserGetContext | 5289 | |
XUserGetReputationStars | 5290 | |
XUserResetStatsViewAllUsers | 5291 | |
β | XUserSetContextEx | 5292 |
β | XUserSetPropertyEx | 5293 |
β | XLivePBufferGetByteArray | 5294 |
XLivePBufferSetByteArray | 5295 | |
XLiveGetLocalOnlinePort | 5296 | |
β | XLiveInitializeEx | 5297 |
XLiveGetGuideKey | 5298 | |
XShowGuideKeyRemapUI | 5299 | |
β | XSessionCreate | 5300 |
β | XStringVerify | 5303 |
XStorageUploadFromMemoryGetProgress | 5304 | |
β | XStorageUploadFromMemory | 5305 |
β | XStorageEnumerate | 5306 |
XStorageDownloadToMemoryGetProgress | 5307 | |
XStorageDelete | 5308 | |
XStorageBuildServerPathByXuid | 5309 | |
β | XOnlineStartup | 5310 |
β | XOnlineCleanup | 5311 |
β | XFriendsCreateEnumerator | 5312 |
β | XPresenceInitialize | 5313 |
β | XUserMuteListQuery | 5314 |
β | XInviteGetAcceptedInfo | 5315 |
β | XInviteSend | 5316 |
β | XSessionWriteStats | 5317 |
β | XSessionStart | 5318 |
XSessionSearchEx | 5319 | |
β | XSessionSearchByID | 5320 |
β | XSessionSearch | 5321 |
β | XSessionModify | 5322 |
XSessionMigrateHost | 5323 | |
β | XOnlineGetNatType | 5324 |
β | XSessionJoinRemote | 5326 |
β | XSessionJoinLocal | 5327 |
β | XSessionGetDetails | 5328 |
β | XSessionFlushStats | 5329 |
β | XSessionDelete | 5330 |
β | XUserReadProfileSettings | 5331 |
β | XSessionEnd | 5332 |
β | XSessionArbitrationRegister | 5333 |
XOnlineGetServiceInfo | 5334 | |
β | XTitleServerCreateEnumerator | 5335 |
β | XSessionLeaveRemote | 5336 |
β | XUserWriteProfileSettings | 5337 |
β | XPresenceSubscribe | 5338 |
XUserReadProfileSettingsByXuid | 5339 | |
β | XPresenceCreateEnumerator | 5340 |
XPresenceUnsubscribe | 5341 | |
β | XSessionModifySkill | 5342 |
β | XSessionCalculateSkill | 5343 |
β | XStorageBuildServerPath | 5344 |
β | XStorageDownloadToMemory | 5345 |
XUserEstimateRankForRating | 5346 | |
XLiveProtectedLoadLibrary | 5347 | |
XLiveProtectedCreateFile | 5348 | |
XLiveProtectedVerifyFile | 5349 | |
β | XLiveContentCreateAccessHandle | 5350 |
XLiveContentInstallPackage | 5351 | |
XLiveContentUninstall | 5352 | |
XLiveContentVerifyInstalledPackage | 5354 | |
β | XLiveContentGetPath | 5355 |
β | XLiveContentGetDisplayName | 5356 |
XLiveContentGetThumbnail | 5357 | |
XLiveContentInstallLicense | 5358 | |
XLiveGetUPnPState | 5359 | |
β | XLiveContentCreateEnumerator | 5360 |
XLiveContentRetrieveOffersByDate | 5361 | |
XLiveMarketplaceDoesContentIdMatch | 5362 | |
XLiveContentGetLicensePath | 5363 | |
β | XShowMarketplaceUI | 5365 |
XShowMarketplaceDownloadItemsUI | 5366 | |
β | XContentGetMarketplaceCounts | 5367 |
XMarketplaceConsumeAssets | 5370 | |
XMarketplaceCreateAssetEnumerator | 5371 | |
β | XMarketplaceCreateOfferEnumerator | 5372 |
XMarketplaceGetDownloadStatus | 5374 | |
XMarketplaceGetImageUrl | 5375 | |
XMarketplaceCreateOfferEnumeratorByOffering | 5376 | |
XUserFindUsers | 5377 |
View list
- XWSAStartup
- XWSACleanup
- XSocketShutdown
- XSocketGetPeerName
- XWSAGetOverlappedResult
- XWSACancelOverlappedIO
- WSARecv
- XSocketRecvFrom
- XWSARecvFrom
- XWSASend
- XWSASendTo
- XSocketInet_Addr
- XSocketWSAGetLastError
- XWSASetLastError
- XWSACreateEvent
- XWSACloseEvent
- XWSASetEvent
- XWSAResetEvent
- XWSAWaitForMultipleEvents
- XWSAFDIsSet
- XWSAEventSelect
- XSocketHTONL
- XSocketNTOHL
- XSocketHTONS
- XNetCreateKey
- XNetTsAddrToInAddr
- XNetInAddrToXnAddr
- XNetInAddrToServer
- XNetInAddrToString
- XNetXnAddrToMachineId
- XNetConnect
- XNetGetConnectStatus
- XNetGetDebugXnAddr
- XNetGetBroadcastVersionStatus
- XNetGetOpt
- XNetSetOpt
- XNetStartupEx
- XNetReplaceKey
- XNetGetXnAddrPlatform
- XNetGetSystemLinkPort
- XNetSetSystemLinkPort
- XCustomSetAction
- XCustomGetLastActionPress
- XCustomSetDynamicActions
- XCustomGetLastActionPressEx
- XCustomRegisterDynamicActions
- XCustomUnregisterDynamicActions
- XCustomGetCurrentGamercard
- XNotifyGetNext
- XNotifyDelayUI
- XGetOverlappedResult
- XLiveInitialize
- XLiveInput
- XLiveRender
- XLiveOnCreateDevice
- XLiveRegisterDataSection
- XLiveUnregisterDataSection
- XLiveUpdateHashes
- XLivePBufferGetByte
- XLivePBufferSetByte
- XLivePBufferGetDWORD
- XLivePBufferSetDWORD
- XLiveGetUpdateInformation
- XNetGetCurrentAdapter
- XLiveUpdateSystem
- XLiveGetLiveIdError
- XLiveUninstallTitle
- XLiveLoadLibraryEx
- XLiveFreeLibrary
- XLivePreTranslateMessage
- XLiveVerifyArcadeLicense
- XLiveQueryProtectedDataInformation
- XLiveVerifyDataFile
- XShowArcadeUI
- XLocatorServerAdvertise
- XLocatorServerUnAdvertise
- XLocatorGetServiceProperty
- XLocatorCreateServerEnumerator
- XLocatorCreateServerEnumeratorByIDs
- XLocatorServiceInitialize
- XLocatorServiceUnInitialize
- XLocatorCreateKey
- XCancelOverlapped
- XEnumerateBack
- XLiveManageCredentials
- XUserGetXUID
- XShowMessageBoxUI
- XUserReadGamerPictureByKey
- XUserSetProperty
- XUserReadGamerPicture
- XUserCreateStatsEnumeratorByRating
- XUserResetStatsView
- XUserGetProperty
- XUserGetContext
- XUserGetReputationStars
- XUserResetStatsViewAllUsers
- XLivePBufferSetByteArray
- XLiveGetLocalOnlinePort
- XLiveGetGuideKey
- XShowGuideKeyRemapUI
- XStorageUploadFromMemoryGetProgress
- XStorageDownloadToMemoryGetProgress
- XStorageDelete
- XStorageBuildServerPathByXuid
- XSessionSearchEx
- XSessionMigrateHost
- XOnlineGetServiceInfo
- XUserReadProfileSettingsByXuid
- XPresenceUnsubscribe
- XUserEstimateRankForRating
- XLiveProtectedLoadLibrary
- XLiveProtectedCreateFile
- XLiveProtectedVerifyFile
- XLiveContentInstallPackage
- XLiveContentUninstall
- XLiveContentVerifyInstalledPackage
- XLiveContentGetThumbnail
- XLiveContentInstallLicense
- XLiveGetUPnPState
- XLiveContentRetrieveOffersByDate
- XLiveMarketplaceDoesContentIdMatch
- XLiveContentGetLicensePath
- XShowMarketplaceDownloadItemsUI
- XMarketplaceConsumeAssets
- XMarketplaceCreateAssetEnumerator
- XMarketplaceGetDownloadStatus
- XMarketplaceGetImageUrl
- XMarketplaceCreateOfferEnumeratorByOffering
- XUserFindUsers
XLLN is by far the most advanced FOSS project out there which aims to be a full rewrite of XLive. However, XDead only provides a minimal layer to work with and does not try to reimplement any of the original functions.
XLLN | XDead | |
---|---|---|
Goal? | Full Rewrite | Minimal Layer |
Additional API? | Yes | Yes |
Modules? | XLLN-Modules | No |
Module Loader? | XLNN or XLLN-Wrapper | Yes |
Standalone header? | No | Yes |
Local online support? | Yes | No |
Supported games? | 81 | 1 |
1 Counting only the official XLLN-Modules. However, XLLN might work for many other games.