* Changes to resolution check on window creation:
1. Allow scaled rendering in window mode
2. Match closest logical rendering resolution while scaling is used
* CI: use single build action
* CMake: use imported targets
* CI: do not build boost for linux
* CMake: add FORCE_BUNDLED_MINIZIP option
* linux: use external minizip and fuzzylite
* CMake: add presets
* .gitignore: ignore cmake build dirs
* github: use cmake presets
Avoid buffer overflow caused by sws_scale():
http://trac.ffmpeg.org/ticket/9254
Currently (ffmpeg-4.4 with SSE3 enabled) sws_scale()
has a few requirements for target data buffers on rescaling:
1. buffer has to be aligned to be usable for SIMD instructions
2. buffer has to be padded to allow small overflow by SIMD instructions
Unfortunately SDL_Surface does not provide these guarantees.
This means that atempt to rescale directly into SDL surface causes
memory corruption. Usually it happens on campaign selection screen
where short video moves start spinning on mouse hover.
To fix [1.] we use av_malloc() for memory allocation.
To fix [2.] we add an `ffmpeg_pad` that provides plenty of space.
We have to use intermdiate buffer and then use memcpy() to land it
to SDL_Surface.
Without the change crash has the following backtrace:
```
(gdb) bt
(c=0x47508940, src=0x1ffeffef50, srcStride=0x1ffeffef30, srcSliceY=0, srcSliceH=116, dst=0x1ffeffef70, dstStride=0x1ffeffef40) at src/libswscale/x86/yuv2rgb_template.c:119
(c=<optimized out>, srcSlice=<optimized out>, srcStride=0x432afa20, srcSliceY=<optimized out>, srcSliceH=116, dst=<optimized out>, dstStride=0x1ffefff0a0) at src/libswscale/swscale.c:969
(this=0x1abaa330, x=90, y=72, dst=0x1a85a4c0, forceRedraw=<optimized out>, update=<optimized out>)
at ../vcmi-9999/client/CVideoHandler.cpp:332
at ../vcmi-9999/client/gui/CIntObject.cpp:83
at ../vcmi-9999/client/gui/CGuiHandler.cpp:462
```
valgrind points to corruption right in sws_scale():
```
Invalid write of size 8
at 0x6C50BD3: ??? (in /usr/lib64/libswscale.so.5.7.100)
by 0x6C4FAE6: yuv420_rgb32_ssse3 (yuv2rgb_template.c:119)
by 0x6C28DF2: sws_scale (swscale.c:969)
by 0x4566F6: CVideoPlayer::nextFrame() (CVideoHandler.cpp:293)
by 0x4573A6: CVideoPlayer::update(int, int, SDL_Surface*, bool, bool) (CVideoHandler.cpp:332)
by 0x25EC94: CIntObject::show(SDL_Surface*) [clone .part.0] (CIntObject.cpp:83)
by 0x34E855: CMainMenu::update() (CMainMenu.cpp:319)
by 0x25D589: CGuiHandler::renderFrame() (CGuiHandler.cpp:462)
by 0x1F7450: mainLoop (CMT.cpp:1387)
by 0x1F7450: main (CMT.cpp:513)
Address 0x475088a8 is 0 bytes after a block of size 92,840 alloc'd
at 0x483F7E5: malloc (vg_replace_malloc.c:380)
by 0x52B4E23: SDL_malloc_REAL (SDL_malloc.c:5387)
by 0x5266237: SDL_SIMDAlloc_REAL (SDL_cpuinfo.c:963)
by 0x52EF042: SDL_CreateRGBSurfaceWithFormat_REAL (SDL_surface.c:123)
by 0x2649AC: CSDL_Ext::newSurface(int, int, SDL_Surface*) (SDL_Extensions.cpp:42)
by 0x457B20: CVideoPlayer::open(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, bool, bool) (CVideoHandler.cpp:182)
by 0x457C60: CVideoPlayer::open(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool) (CVideoHandler.cpp:84)
by 0x35B14E: CCampaignScreen::CCampaignButton::show(SDL_Surface*) (CCampaignScreen.cpp:126)
by 0x25EC94: CIntObject::show(SDL_Surface*) [clone .part.0] (CIntObject.cpp:83)
by 0x34E855: CMainMenu::update() (CMainMenu.cpp:319)
by 0x25D589: CGuiHandler::renderFrame() (CGuiHandler.cpp:462)
by 0x1F7450: mainLoop (CMT.cpp:1387)
by 0x1F7450: main (CMT.cpp:513)
```
Signed-off-by: Sergei Trofimovich <slyfox@gentoo.org>
Before the change campaign bonus selection screen had inconsistent
overflow behaviour for difficulty selection:
```
0 1 2 3 4 | available buttons: '-' to decrease
^ | '+' to increase
```
Before the change:
1. If we click '+' 5 times we will end up on difficulty=4 (ok, saturated).
2. If we click '-' 5 times we will end up on difficulty=1 (unexpected, wrap around).
After the change:
1. If we click '+' 5 times we will end up on difficulty=4 (saturated).
2. If we click '-' 5 times we will end up on difficulty=0 (saturated).
The inconsistency happens because `difficulty` variable has `ui8` type
and server uses `difficulty = vstd::abetween(difficulty, 0, 4)` to
implement the saturation.
For large positive values saturation works as expected:
vstd::abetween(difficulty=5, 0, 4) -> 4
For small values it does not:
vstd::abetween(difficulty=-1, 0, 4) -> 4
The change makes client to avoid using negative values.
Noticed use of uninitialized value when built vcmi with -fsanitize=undefined:
```
Established connection with
VCMI 0.99 b310f2e61e (server).
UUID: bab9a90d-7416-4566-8817-e367ffcac7c1
../vcmi-9999/client/lobby/SelectionTab.cpp:138:16:
runtime error: load of value 32717, which is not a valid value for type 'ESortBy'
/usr/lib/gcc/x86_64-pc-linux-gnu/12.0.0/include/g++-v12/tuple:190:4:
runtime error: load of value 32717, which is not a valid value for type 'ESortBy'
/usr/lib/gcc/x86_64-pc-linux-gnu/12.0.0/include/g++-v12/tuple:190:4:
runtime error: load of value 32717, which is not a valid value for type 'ESortBy'
```
Here (before the change) `SelectionTab()` used `generalSortingBy` before
first use:
```
SelectionTab::SelectionTab(ESelectionScreen Type) {
...
if(tabType != ESelectionScreen::campaignList)
{
...
ESortBy criteria = (ESortBy)i;
if(criteria == _name)
criteria = generalSortingBy;
buttonsSortBy.push_back(... std::bind(&SelectionTab::sortBy, this, criteria)));
...
}
...
switch(tabType)
{
case ESelectionScreen::newGame:
generalSortingBy = ESortBy::_name;
....
```
The change moves `generalSortingBy` initialization before first use.
Signed-off-by: Sergei Trofimovich <slyfox@gentoo.org>