M-HT / SR

A project to statically recompile following games to create Windows or Linux (x86 or arm) versions of the games - Albion, X-Com: UFO Defense (UFO: Enemy Unknown), X-Com: Terror from the Deep, Warcraft: Orcs & Humans, Septerra Core: Legacy of the Creator, Battle Isle 3: Shadow of the Emperor

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Battle Isle 3 resolution & window sizes

FyiurAmron opened this issue · comments

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?)

commented

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:
    image

  • maximum values higher than screen size
    image

commented

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)

image

I guess it's because I have DPI virtualization basically off: (I'm using "Classic Windows theme" etc.)
image

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.

commented

@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).

SR-BI3-modded.zip

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.

commented

Sorry, that was my mistake, it works correctly.
I'll implement it, but it will be optional and disabled by default.

commented

I created a new release which has the option to change resolution and the option to increase max window size.