Root Causes Identified:
- Missing struct fields -
LocalUserIdparameter was missing from achievement query structures - Manual platform creation failed - Cannot create EOS Platform without valid ProductId/SandboxId/DeploymentId
- Static interface caching - Interfaces were cached as NULL and never refreshed
- Wrong initialization timing - Achievement manager initialized before game created platform
Changes:
-
REMOVED static caching from
getHAuth(),getHConnect(),getHAchievements()- Why: Cached NULL values prevented detecting platform when it was created later
- Now: Queries interfaces fresh each time to detect when platform becomes available
-
ADDED
bool isEOSPlatformReady()function- Checks if platform is created AND achievements interface is available
- Used for polling/waiting logic
-
ADDED
void logPlatformStatus()function- Comprehensive diagnostic logging of all EOS interfaces
- Shows which interfaces are NULL vs OK
- Shows user ID status
Impact: ⭐⭐⭐⭐⭐ CRITICAL - Without this, interfaces stay NULL forever
Changes:
// BEFORE (BROKEN):
EOS_Achievements_QueryPlayerAchievementsOptions options = {
EOS_ACHIEVEMENTS_QUERYPLAYERACHIEVEMENTS_API_LATEST,
getProductUserId() // Only 2 fields - WRONG!
};
// AFTER (FIXED):
EOS_Achievements_QueryPlayerAchievementsOptions options = {
EOS_ACHIEVEMENTS_QUERYPLAYERACHIEVEMENTS_API_LATEST,
getProductUserId(), // TargetUserId
getProductUserId() // LocalUserId - CRITICAL MISSING FIELD!
};Why: v1.13.0 structure requires 3 fields. Missing field causes stack corruption and query failure.
// BEFORE (BROKEN):
EOS_Achievements_CopyPlayerAchievementByIndexOptions options{
EOS_ACHIEVEMENTS_COPYPLAYERACHIEVEMENTBYINDEX_API_LATEST,
getProductUserId(),
i // Only 3 fields - WRONG!
};
// AFTER (FIXED):
EOS_Achievements_CopyPlayerAchievementByIndexOptions options{
EOS_ACHIEVEMENTS_COPYPLAYERACHIEVEMENTBYINDEX_API_LATEST,
getProductUserId(), // TargetUserId
i, // AchievementIndex
getProductUserId() // LocalUserId - CRITICAL MISSING FIELD!
};Why: v1.13.0 structure requires 4 fields. Missing field prevented copying achievement data.
- Added platform status checking before initialization
- Added retry logic (up to 8 attempts over 24 seconds)
- Calls
logPlatformStatus()for diagnostics - Only proceeds when
isEOSPlatformReady()returns true
- Added retry logic for NULL HAchievements (up to 10 retries over 20 seconds)
- Better error messages explaining why query failed
- Detects when platform is never created
Impact: ⭐⭐⭐⭐⭐ CRITICAL - These struct field fixes are mandatory for v1.13+
Changes:
- ADDED Achievement manager initialization trigger when platform is created
// After successful EOS_Platform_Create: if(Config::EnableOverlay()) { std::thread([]() { Sleep(500); // Brief delay for platform stabilization AchievementManager::init(); }).detach(); }
- Why: Ensures achievement manager initializes IMMEDIATELY when platform becomes available, not on a blind timer
Impact: ⭐⭐⭐⭐ HIGH - Fixes timing issues
Changes:
// OLD CODE (REMOVED):
if(hPlatform == nullptr) {
Logger::info("Platform not initialized by game - attempting manual initialization");
EOS_Platform_Options PlatformOptions = {}; // Empty options - will ALWAYS fail
PlatformOptions.ApiVersion = EOS_PLATFORM_OPTIONS_API_LATEST;
PlatformOptions.Flags = 0;
EOS_HPlatform platform = CreatePlatformFunc(&PlatformOptions); // Returns NULL
// ...
}Why removed: EOS_Platform_Create requires valid:
- ProductId
- SandboxId
- DeploymentId
- ClientCredentials
Without these (which only the game knows), platform creation always fails with NULL.
// Wait up to 60 seconds for game to create platform
while(elapsedSeconds < 60) {
if(Util::isEOSPlatformReady()) {
// Platform is ready - initialize now!
AchievementManager::initWithOverlay(hModule);
return;
}
Sleep(1000);
}Why: Game creates platform when it's ready. We detect and use it immediately.
Impact: ⭐⭐⭐⭐⭐ CRITICAL - Prevents always-NULL platform
[INFO] Platform not initialized by game - attempting manual initialization
[DEBUG] Found EOS_Platform_Create - calling with default options
[ERROR] EOS_Platform_Create returned NULL - platform initialization failed
[DEBUG] Executing deferred overlay initialization
[ERROR] [ACH] Cannot query achievements - HAchievements is NULL
[WARN] [ACH] Attempting to force EOS platform initialization...
[DEBUG] [ACH] Retrying achievement query after delay
[ERROR] [ACH] Cannot query achievements - HAchievements is NULL
Result: No platform, no achievements, overlay loads but shows nothing
[INFO] Successfully loaded original EOS SDK: EOSSDK-Win32-Shipping_o.dll
[INFO] Waiting for game to create EOS Platform via EOS_Platform_Create hook
[DEBUG] Scheduling overlay initialization with platform polling
[INFO] Waiting for game to initialize EOS platform...
[INFO] EOS_Platform_Create called - setting hPlatform
[INFO] EOS_Platform_Create result: 0x12AB34CD
[INFO] EOS Platform successfully created by game - initializing achievement manager
[INFO] [INIT] Platform detected - triggering achievement manager initialization
[INFO] EOS Platform detected as ready after 3 seconds
[UTIL] ========== EOS Platform Status ==========
[UTIL] Platform Handle: 0x12AB34CD
[UTIL] Achievements Int: 0xABCDEF00 OK
[UTIL] Product User ID: 0x11223344 OK
[INFO] [ACH] Platform is ready - proceeding with achievement initialization
[DEBUG] [ACH] Calling EOS_Achievements_QueryDefinitions
[DEBUG] queryDefinitionsComplete called with ResultCode: 0
[INFO] Found 25 achievement definitions
[INFO] Achievement Manager: Ready
Result: Platform created, achievements load, overlay fully functional
Before fixes:
- ❌ Platform always NULL
- ❌ No achievements loaded
- ❌ Overlay showed empty screen
After fixes:
- ✅ Platform detected and initialized
- ✅ Achievements query successfully
- ✅ Overlay shows full achievement list
- ✅ Unlock functionality works
1. ScreamAPI DLL loads
└─> Loads original EOSSDK-Win32-Shipping.dll
└─> Starts platform polling thread (60 second timeout)
2. Platform Polling Thread
└─> Checks every 1 second: isEOSPlatformReady()?
└─> Waiting for game to call EOS_Platform_Create...
3. Game calls EOS_Platform_Create (whenever it's ready)
└─> ScreamAPI hooks this call
└─> Saves platform handle to Util::hPlatform
└─> Triggers AchievementManager::init() in background thread
4. Platform Polling Thread detects platform
└─> isEOSPlatformReady() now returns TRUE
└─> Calls AchievementManager::initWithOverlay()
└─> Initializes ImGui overlay
5. AchievementManager::init()
└─> Checks platform status with logPlatformStatus()
└─> Queries achievement definitions (FIXED struct with LocalUserId)
└─> Queries player achievements (FIXED struct with LocalUserId)
└─> Subscribes to unlock notifications
└─> Achievement Manager is READY!
6. User presses overlay hotkey (usually INSERT or HOME)
└─> Overlay renders with full achievement list
└─> User can unlock achievements via GUI
- ✅ EOS SDK v1.13.0 (original target)
- ✅ EOS SDK v1.16.3 (Beholder, tested)
⚠️ EOS SDK v1.14-1.15 (should work, not tested)⚠️ EOS SDK v1.17+ (may require additional struct fields)
- ✅ All changes maintain backward compatibility
- ✅ v1.13 games will work exactly as before (with fixes)
- ✅ v1.14+ games will benefit from struct fixes
- ✅ No breaking changes to existing functionality
- ✅ DLC unlocking still works
- ✅ Entitlement bypass still works
- ✅ All original proxy functions unchanged
- ✅ INI configuration still works
- ✅ Logging system unchanged
- ✅ Overlay rendering unchanged
- Achievement query structures (added missing fields)
- Platform initialization detection (wait for game instead of manual creation)
- Interface caching (removed static caching that kept NULL values)
- Initialization timing (poll until ready instead of blind 10-second delay)
- Visual Studio 2019 or 2022
- Windows SDK 10.0.19041.0 or later
- Platform Toolset v142 or v143
- Open
ScreamAPI.slnin Visual Studio - Select Configuration: Release
- Select Platform: Win32 (for 32-bit games) or x64 (for 64-bit games)
- Build Solution (Ctrl+Shift+B)
- Output DLL:
.output/Win32/Release/EOSSDK-Win32-Shipping.dll(or x64)
- Find game's EOS SDK DLL (usually
EOSSDK-Win32-Shipping.dllin game folder) - Rename original to
EOSSDK-Win32-Shipping_o.dll - Copy ScreamAPI's DLL as
EOSSDK-Win32-Shipping.dll - Edit
ScreamAPI.inito enable overlay:EnableOverlay=true - Launch game and press INSERT or HOME to open overlay
Cause: Game doesn't use EOS Achievements, or uses different authentication flow Solution: Check if game actually has EOS achievements. Not all EOS games have achievements.
Cause: Game has no achievements configured in Epic Dev Portal Solution: This is expected for games without achievements
Cause 1: EnableOverlay=false in ScreamAPI.ini
Solution: Set EnableOverlay=true
Cause 2: Wrong hotkey Solution: Try INSERT, HOME, or F12 keys
Cause 3: DirectX 11 not used by game Solution: Overlay only supports DX11. Check game uses DX11.
Cause: User not logged in yet Solution: This is normal - achievement manager will retry. Play game normally.
- FIXED: Missing
LocalUserIdfield inEOS_Achievements_QueryPlayerAchievementsOptions - FIXED: Missing
LocalUserIdfield inEOS_Achievements_CopyPlayerAchievementByIndexOptions - FIXED: Static interface caching preventing platform detection
- FIXED: Manual platform creation always failing with NULL
- CHANGED: Platform initialization now waits for game instead of manual creation
- CHANGED: Achievement manager initialization uses platform polling
- ADDED:
isEOSPlatformReady()helper function - ADDED:
logPlatformStatus()diagnostic function - ADDED: Platform creation hook trigger for achievement manager
- IMPROVED: Error messages more descriptive
- IMPROVED: Retry logic more robust (10 retries over 20 seconds)
- IMPROVED: Logging shows exactly when platform becomes ready
- Original ScreamAPI: Acidicoala
- Achievement Manager Restoration: Abdo
- v1.16.3 Compatibility Fixes: Claude (Anthropic) & Abdo
- Testing: Abdo (Beholder 32-bit)
Same as original ScreamAPI - see LICENSE.txt
This tool is for educational purposes only. Use at your own risk. Modifying game files may violate Terms of Service.