Repository navigation
fix: restore the retail startup resolution path (szx/szy and profile video settings) - #72
Open
AndreasLauvhjell wants to merge 2 commits into
Open
AndreasLauvhjell wants to merge 2 commits into
AndreasLauvhjell wants to merge 2 commits into
Conversation
VideoOptions::initialize ends with the scheme detection (result discarded) and applyQualityPreset(1), which selects "800x600" and "Off" (RendDX9 0x10010850 tail, 0x1000F390). VideoOptions::apply then calls the resolution change at 0x10010365 and 0x100103AE, which applies the GSWindowSizeX/Y override and posts REChangeResolution, so the SwiffHost viewport follows +szx/+szy before the login menu is built. Both pieces were skipped as [CHOSEN, not recovered] (the startup preset and the rc-login-reset-hold). Tested with a 1600x1200 window: the login and main menus fill it, and the mode change at login and on Apply survives the device reset. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
RendDX9 initializeD3DSubsystems, right after VideoOptions::initialize, fetches the host "VideoSettings" singleton and calls its applyToOptions (+0x28) with the embedded VideoOptions (RendDX9.dll 0x1000B2EE..0x1000B31B, no null test on the singleton). This pushes the pending record loaded by LocalProfileManager::init (the Default profile's Video.con) into the options, so Renderer::initialize's first apply switches to the profile resolution, antialiasing and qualities before the first frame. The rebuild had this as a frontier, so the first apply used preset 1 (800x600) and the login menu showed 4:3 with black bars until login. An apitrace D3D9 capture of retail BF2.exe shows CreateDevice 800x600@85 followed by a single Reset to 3840x2160@165 (8x MSAA) before the first Present. Tested with the x86 client fullscreen without +szx/+szy: the first apply now resets to 3840x2160@165 and the login menu opens in 16:9. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Base:
main. Two commits, which belong together:d55aae5fix: restore the retail resolution change inVideoOptions(Code/BF2/RendDX9/VideoOptions.cpp)68d921dfix: hand the profile video settings toVideoOptionsat renderer startup (Code/BF2/RendDX9/RendDX9Init.cpp)Commit 1 lets a selected resolution reach the device and the menu viewport. Commit 2 makes sure that, at startup, the selected resolution is the profile's one and not preset 1's 800x600.
What this fixes
Two symptoms, with one shared root. The rebuilt client never ran the retail resolution change at startup.
+szx/+szy. For example, with+szx 1280 +szy 720 +fullscreen 0, the window and back buffer were 1280x720, but the menu was drawn only in an 800x600 area in the top-left corner. The SwiffHost viewport starts at 800x600. OnlyREChangeResolution(category 11, id 2) updates it, and theVideoOptionspath that posts it was held back by[RETIRE-WHEN: rc-login-reset-hold].+szx/+szy. The login menu ran at 800x600 (4:3, black bars on a widescreen monitor). It switched to the profile resolution only after you logged in. Retail BF2 1.50 shows the login menu at the Default profile's resolution from the first frame. On the test machine that is 3840x2160@165 Hz with 8x AA, fromProfiles\Default\Video.con.How the startup path works (retail)
BF2Engine::initcallsLocalProfileManager::init(BF2.exe 0x409364, before the renderer exists). It loads theDefaultprofile and runs itsVideo.con.VideoSettings.setResolutionand the other setters only write the pending record (VideoSettings+0xC8).applySettings(1)at 0x4A89D3 applies audio only, so nothing is pushed to the renderer here.BF2Render::init(0x454370) creates the window and device carrier fromGSWindowSizeX/Y, which default to 800/600. The D3D device is created at 800x600.initializeD3DSubsystems(0x1000B160) runsVideoOptions::initialize(0x10010850). It readsGSWindowSizeX/Y(default 0) and ends with scheme detection (result discarded) andapplyQualityPreset(1)(0x1000F390), which selects "800x600" / AA "Off". (commit 1)VideoSettingssingleton and callsapplyToOptions(VideoOptions)(vtable +0x28, BF2.exe 0x4B2040). This pushes the pending record into the fresh options: the eight qualities, the resolution (dynamic option 1), the antialiasing (dynamic option 0, whileGSLoadLevelis empty) and the view distance scale. The singleton is not null-tested. (commit 2)Renderer::initialize's firstVideoOptions::apply(0x1002CD0E) finds a selected resolution that differs from the applied one. It calls the mode change (sub_1000F8D0, at 0x10010365 and 0x100103AE), which applies theGSWindowSizeX/Yoverride, resets the device to the selected mode and postsREChangeResolution(11,2). The SwiffHost menu viewport then follows. (commit 1)Without commit 1, step 5 never changes the mode, so the viewport stays at 800x600 whatever the window size is. Without commit 2, the selection at step 5 is still preset 1, and the first apply switches to 800x600@60.
The change
Code/BF2/RendDX9/VideoOptions.cpp(commit 1):VideoOptions::applycall the recovered mode change again. The hold and its[RETIRE-WHEN: rc-login-reset-hold]marker are removed.VideoOptions::initializeends with the shipped tail: scheme detection (slot +0x34, result discarded) andapplyQualityPreset(1).Code/BF2/RendDX9/RendDX9Init.cpp(commit 2): the line// [FRONTIER] VideoSettings still lacks the VideoOptions handoff.is replaced with the recovered call. The native plugin ABI uses the typedIVideoSettings::applyToOptions. The retail-ABI arm calls slot +0x28, the same way other host calls in RendDX9 do. No null test, as shipped.Both are retail recovery from BF2.exe and RendDX9.dll 1.50, so no issue is linked.
Note for review: upstream
fix/client-testingalso editsVideoOptions.cpp, so expect a small overlap there.Where we got stuck
Commit 1 alone fixed the windowed
+szx/+szycase, but fullscreen still showed the login menu at 800x600. Static reading alone pointed the wrong way. We first followed every path that could change the resolution before login:BF2Render::init: hard-coded 800/600 defaults.LocalProfileManager::init:applySettings(1)is audio only.VideoOptionspreset 1: "800x600".VideoSettingsglobal in BF2.exe (25 sites): apply only on login or the Options page.mainMenu.swf: the login page never callsVideoSettings.apply.All of these said "800x600 until login", which contradicted what retail visibly does. We also ruled out PE header and manifest differences (a test build with retail-like linker flags still showed black bars) and AMD per-game scaling.
The handoff was missed because it is not reached through the
VideoSettingsglobal in BF2.exe. RendDX9 calls it by singleton name from inside the DLL's own startup.How apitrace found it
We captured vanilla retail BF2.exe 1.50 (no arguments, fullscreen) with apitrace 14.0 (32-bit,
apitrace trace --api d3d9) up to the login menu, then dumped the D3D9 calls:CreateDevice: 800x600, fullscreen, 85 Hz, no MSAA (same as the rebuild)Reset: 3840x2160, fullscreen, 165 Hz, 8x MSAA, before the first Present, right after the five event queries inRenderer::initializeSo retail never shows an 800x600 frame. The reset sits between
VideoOptions::initializeand the first apply. A string search forVideoSettingsin RendDX9.dll found exactly one reference: thegetSingleton("VideoSettings")→+0x28call at 0x1000B2EE that the rebuild lacked.Testing
bf2_client) built from this branch: PASS.+szx 1600 +szy 900+fullscreen 0+szx/+szy, DefaultVideo.con= 3840x2160@165 / 8Samples (both commits):RendDX9Rebuilt.logshows the same order as the retail trace. The device is created at 800x600@85, then the firstVideoOptions::applysets presentParameters to 3840x2160 @165 fullscreen before the first frame. The quality rows come fromVideo.con(3 instead of preset 1's 2). Menu fonts are built for vp (0,0,3840,2160). The login menu fills the screen in 16:9, matching retail..github/workflows/build.yml) on 68d921d, plus the not-yet-mergedfix/x64-voip-linkthat is needed for the x64 link. All PASS: x64 python, configure,bf2_w64ded; x86 python, configure,bf2_run_checks+bf2_editor_run_checks,bf2_w32ded,bf2_aidll+bf2_client,bf2_editor. The Linux CI job was not run locally.Not exercised
+szx/+szytogether.Remaining frontiers nearby
VideoOptions::handleECCoreEvent(PE 0x100103F0) is still not registered. It only matters on level load (ECCore 5/2 and 5/3), not at startup.Logic.quitnot registered). This is unrelated to this change.