Closed FyiurAmron closed 1 year ago
Just an idea, having a config option to set the initial resolution of the game (or, actually, the desktop I guess, if scaling proves to be problematic due to the windowing model used) and revert to the former one after exiting the game. Obviously it's possible to do so manually before playing the game or use a 3rd-party tool for that, but IMVHO it should be really rather simple to add it here... since with the current scalings, even with "Large hex squares" in 2K on physically small-ish screens playing is somewhat problematic without prior resolution change, and on 4K+ I guess you'd be chasing ants around the screen :)
What operating system are you using ? And what DPI setting ?
Also - would it be possible to remove the limit on the size of the main game window (battlescape) so that it could be actually "maximized" (currently it's capped at 800x579 for some reason?)
I don't know where this is handled in the code, so no.
@M-HT
What operating system are you using ? And what DPI setting ?
Windows 7, standard DPI (i.e. 96).
I don't know where this is handled in the code
I'm currently trying to do a "hard" patch for it, but I thought that it should be simple enough by itself to make it possible to incorporate it into SR project.
in the code from current SR-BI3.exe
for Windows, it's
// move: SWP_NOSIZE , cx & cy === 0
.text:0040767D call ds:SetWindowPos
// resize: SWP_NOMOVE , X & Y === 0
.text:00407763 call ds:SetWindowPos
for all the main game windows (yes, they are just reskinned normal USER32 windows :D ).
Basically, the magic happens here:
.text:00466F82 call sub_47E01A ; GetWindowRect (old size)
.text:00466F87 add esp, 18h
.text:00466F8A mov eax, [ebp+oldWidth]
.text:00466F8D mov ecx, [ebp+arg_0]
.text:00466F90 mov [ecx+264h], ax
.text:00466F97 mov eax, [ebp+oldHeight]
.text:00466F9A mov ecx, [ebp+arg_0]
.text:00466F9D mov [ecx+266h], ax
.text:00466FA4 mov eax, [ebp+arg_0]
.text:00466FA7 movsx eax, word ptr [eax+0C7h] ; overwrite value at *(eax+00C7) => change maximum window height
.text:00466FAE push eax
.text:00466FAF mov eax, [ebp+arg_0]
.text:00466FB2 movsx eax, word ptr [eax+0C5h] ; overwrite value at *(eax+00C5) => change maximum window width
.text:00466FB9 push eax
.text:00466FBA mov eax, [ebp+arg_0]
.text:00466FBD push eax
.text:00466FBE call sub_41775F
My current result of hacking:
allowed manual resize above the 800x579 limit, i.e. after overwriting the default 0x0320h
x 0x0243h
limits:
maximum values higher than screen size
Windows 7, standard DPI (i.e. 96).
When using 4K (or 2K on small screen) with 96 DPI, then everything is small, not just the game. Isn't a better solution to increase DPI (which also scales the game) ?
Basically, the magic happens here: ...
There are two problems here. One, how to identify the correct window and two, what should the max size be ?
Windows 7, standard DPI (i.e. 96).
When using 4K (or 2K on small screen) with 96 DPI, then everything is small, not just the game. Isn't a better solution to increase DPI (which also scales the game) ?
Honestly, it doesn't work, at least on my machine: e.g. the cursor gets huge, but the UI/icons are still abysmally small, and the main window (battlescape) is still 800x579. (screenshot at 144 DPI)
I guess it's because I have DPI virtualization basically off: (I'm using "Classic Windows theme" etc.)
Putting that aside, I'd say that for different reason people would still want/need to keep DPI to their regular value and could want to be able to run BI3 with the "vintage" feel (i.e. with a resolution that makes icons bigger than ants on the screen :D )
I agree though, there are caveats, and for some just setting higher DPI instead of changing the monitor resolution might be a better idea.
There are two problems here. One, how to identify the correct window and two, what should the max size be ?
First one is rather trivial: there are only two windows in the entire game that can be resized, IIRC, the battlescape and the minimap. On maximize, minimap gets the values there (e.g. 0x0100 / 0x0100) with x === y (it's always square, even when resizing one border). OTOH, battlescape gets e.g. those pesky 0x0320 x 0x0243 - that alone allowed me to distinguish between those two. (.text:00466F82
etc. gets executed only on maximize - selecting it is not perfect, but it was good enough for me to do a simple injection there; I guess there might be a better place for it, though).
Also, I guess there are other methods - the hWnd is passed around also, so it could probably be used for differentiation, and I'll try to dig around and find a place that actually sets/calculates those particular values. That'll take a day or two for me, I'm not that good at hacking and debugging as I was back in the days :D
As to what the max size should be - I'd say that either using GetSystemMetrics(SM_CXSCREEN)
& GetSystemMetrics(SM_CYSCREEN)
(or anything similar), or just allowing to specify this in the config file and having some reasonable values like those 800x579 as the defaults should do the trick. Like I said, those values are strange, so I'm hoping to find if they are hardcoded based on resolution or a result of some strange calculations instead. My gut feeling is that they are assumed as 800x600 - 21 pixels vertical e.g. for the bottom UI bar, which is 48 pixels high, but even leaving 21 pixels allows to still see it... but that values are always used from 1024x768 upwards. If you run at actual 800x600, those max values are 760x560, but the initial size is bigger than that... and running at 832x624 gave me max size 792x579 :D ... So yes, those valus are really strange, and they look calculated.
almost there...
.text:0046AFBB sub_46AFBB proc near ; CODE XREF: sub_4177B1↑j
seems to be the place where the "template" values for the window sizes are read and passed to the resize/maximize handlers functions; changing stuff referenced at
.text:0046AFF3 mov ecx, dword_4C5750
.text:0046AFF9 mov ax, [ecx+eax*8+3Eh] ; [ecx+eax*8+3Eh] is where the value needs to be updated permanently
&&
.text:0046B087 mov ecx, dword_4C5750
.text:0046B08D mov ax, [ecx+eax*8+6] ; ditto
to some reasonable maximum values allowed maximizing up to actual battlescape size but not bigger than screen size. It works perfectly with minimap also.
The window left/top decoration bars are still bugged this way, so I guess tracing what sets those "template" values will be my next step.
OK, mystery solved. The 800 (width) and 579 (height) values are seemingly taken directly from the UI element pics (i.e. read from one of the e.g. DATA/UIA
files, in the INFO
sections) - the "easiest" way to mod the UI to support higher resolutions (more columns/rows) would be then to just patch the pics. I've did that in-memory, and it worked - so while this is inside my scope of fun, doing that would be completely out of the scope of SR project, obviously.
Still, the injection of e.g. 0x4000
in the two places mentioned above works as an intermediate solution well enough IMO - the window still respects the screen resolution, doesn't grow more than the actual map content, and looks "good enough" (only black bars on top and left side). It also doesn't require any manual selection of values whatsoever, since the game will cap the window size at the screen resolution anyway.
@M-HT as a dirty and simple hack as a proof of concept here: replace
.text:0046AFF9 mov ax, [ecx+eax*8+3Eh]
.text:0046AFFE and ax, FFFFh
with
.text:0046AFF9 mov byte ptr [ecx+eax*8+3Fh], 40h
.text:0046AFFE mov ax, [ecx+eax*8+3Eh]
and
.text:0046B08D mov ax, [ecx+eax*8+6]
.text:0046B092 and ax, FFFFh
with
.text:0046B08D mov byte ptr [ecx+eax*8+7], 40h
.text:0046B092 mov ax, [ecx+eax*8+6]
– you should see the results immediately. With proper code injection/replacement this can be obviously done more elegantly.
@M-HT as a dirty and simple hack as a proof of concept here: replace
.text:0046AFF9 mov ax, [ecx+eax*8+3Eh] .text:0046AFFE and ax, FFFFh
with
.text:0046AFF9 mov byte ptr [ecx+eax*8+3Fh], 40h .text:0046AFFE mov ax, [ecx+eax*8+3Eh]
and
.text:0046B08D mov ax, [ecx+eax*8+6] .text:0046B092 and ax, FFFFh
with
.text:0046B08D mov byte ptr [ecx+eax*8+7], 40h .text:0046B092 mov ax, [ecx+eax*8+6]
– you should see the results immediately. With proper code injection/replacement this can be obviously done more elegantly.
I tried this, but it doesn't work in every mission.
@M-HT on my box, it works for every campaign mission as least until Set: 1 Map: 17 (because that's how far I'm in the campaign right now :D) - can you show/tell me what doesn't work and on which mission exactly? I'm really interested how to reproduce the problem you're having. I can also send you the patched SR-BI3.exe
I'm using, you can do a diff and see if I missed mentioning something etc. (shouldn't happen, but it's always a possibility).
it has some dead code in the text string section, it's leftovers from my experiments and can be ignored completely, but the main diff should be just the code mentioned above.
Sorry, that was my mistake, it works correctly. I'll implement it, but it will be optional and disabled by default.
I created a new release which has the option to change resolution and the option to increase max window size.
Just an idea, having a config option to set the initial resolution of the game (or, actually, the desktop I guess, if scaling proves to be problematic due to the windowing model used) and revert to the former one after exiting the game. Obviously it's possible to do so manually before playing the game or use a 3rd-party tool for that, but IMVHO it should be really rather simple to add it here... since with the current scalings, even with "Large hex squares" in 2K on physically small-ish screens playing is somewhat problematic without prior resolution change, and on 4K+ I guess you'd be chasing ants around the screen :)
TBH, it feels "natural" until about 1280x1024, then it's just too small.
Also - would it be possible to remove the limit on the size of the main game window (battlescape) so that it could be actually "maximized" (currently it's capped at 800x579 for some reason?)