Closed lockheed closed 6 months ago
This is not an actual bug. This is how the game works until someone could migrate to OpenGL or Vulkan and could realize a pixel shader that could simulate efficient color palette swaps.
Original M.A.X. under MS-DOS used 256 color palette mode rendering at 640x480 resolution via the VESA BIOS. The VGA HW was able to swap 256 color palettes effortlessly without the need to change the actual video memory contents, the "textures". Games of that era created fancy graphics effects via mere palette manipulation, they did so called color animations.
Games swapped some colors in a palette, downloaded the 768 bytes modified palette into the VGA palette memory and the screen updated instantly. If we need to swap the texture or the actual pixels of the whole screen at 640x480 resolution that would mean 307.200 bytes and synchronization to the monitor refresh rate... palette based effects were king.
E.g. water caustics effect in M.A.X. is not based on textures, it is a fixed image or texture that changes colors 24 times per seconds. The same way, fade effects use simple, full 768 byte palettes that are getting darker or brighter. The speed of the fade effect was controlled by the number of full palette swaps at maximum HW rate made possible by the CPU/VGA BIOS.
Now on modern systems, there is no VESA BIOS access, there is no color palette mode at all. All of these are abstracted away by the OS or they are simply things of the past.
To have color animations M.A.X. Port simulates the VESA BIOS via SDL texture/surface palette blits/swaps and then renders the updated surfaces/textures onto the screen/window at a frame rate that is limited by the screen refresh rate.
SDL2 cannot miraculously swap an SDL surface's or SDL texture's virtual 256 color palette like the VGA HW did. The SW palette handling actually needs to change every single pixel one by one every time the palette is changed in the surface/texture in any way. Even worse, the video cards do not support 256 color indexed pixel formats anymore, so the SDL surfaces/textures need to switch to a HW supported color mode again in SW and then we reach the actual HW.
SDL2 does all of these palette manipulations on the CPU. Rendering the finished surface/texture is partly done by the video card. You can imagine how inefficient it is to sweep through 2560x1440 pixels one by one changing their colors in a range of 256 colors hundreds of times to do the actual fading stuff.
The bigger the screen, the faster your CPU becomes a bottleneck and the time to render a single frame increases exponentially.
Without an efficient GPU pixel shader, the only thing I can do is something similar to what the DOSBox dos emulator does which means skipping the palette swaps as-is and accepting the graphical glitches that this will cause...
It NEVER happens when running the game inside a Windows 10 VM in resolution of 2560x1440 (different host with NVIDIA RTX GPU passed-through to Windows).
This is odd. What is your window_width and window_height in settings.ini? I assume on the VM it is 640x480 while on the other its a big value.
If it turns out that your set resolution is small, then the only thing I can think of would be a vsync issue. The game tries to access the video memory at a rate which is not supported by the OS/HW combination and soft-locks happen. This case would require a special build that could log SDL render present results (failures).
Thanks for that detailed explanation. It would be curious to find out why the difference in behaviour between Windows VM and Linux. I use the exact same copy of MAX to play on both machines (synced with Syncthing) so all the files are the same.
[GRAPHICS_SETTINGS] display_index=0 screen_mode=2 disable_ar_correction=0 scale_quality=1 window_width=640 window_height=480 dialog_center_mode=0
Could you try out the latest GitHub Actions build? In portable mode (default) it should work with the folder structure that v0.6.1 had. Since a few weeks time SDL error messages are logged into stdout.txt which is placed in the same folder where the executable is in portable mode. I am curious whether you get such messages like SDL_LockTexture failed
or SDL_RenderClear failed
on one of your systems.
If you can build the software, you could take a look into svga.cpp
and in particular on SDL_CreateRenderer(sdlWindow, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE))
. You could try to add SDL_RENDERER_PRESENTVSYNC to the options. Or you could try to change SVGA_NO_TEXTURE_UPDATE to false in that file.
The latest build also uses updated SDL2 library which may have fixed some relevant OS dependent issues...
I am very happy to help, but I am not sure what you mean "GitHub Actions build". I haven't found any updated bins. Also, if you can provide Linux executables in a non-deb format, that'd be great. Extracting them from deb is quite a pita.
I haven't found any updated bins.
Whenever I push changes to GitHub new builds are created automatically. On the top menu there is a button called actions. There you can find a big list of executed workflows or workflow runs. E.g. currently the top entry on the list opens this build: https://github.com/klei1984/max/actions/runs/8530019150
If you log into GitHub with a user, then you can scroll to the bottom of that page and for recent builds you can download the latest build artifacts per platform.
E.g. you will find there Linux-x64.zip which contains all build artifacts. E.g. currently the deb file. I will add a tar.gz package or similar to Linux.
Got it. I put all the files into MAX directory, it won't run
max: error while loading shared libraries: libfreetyped.so.6: cannot open shared object file: No such file or directory
even though the file is in the same dir.
Yes this happens because the game is built without configuring an RPATH (or changing the default RUNPATH) which would be needed for a "portable" build. The linker places all generated libraries into their respective folder locations that are not preserved by the deb isntaller. They would not be preserved by the zipped up package either for that matter... so the game currently expects custom built shared libs to be found in the folder structure that was present on the PC that built the game.
E.g. if I build the game on one of my virtual systems it generates and embeds such a RUNPATH definition into my executable:
0x0000001d (RUNPATH) Library runpath: [/home/max/git/max/Debug/_deps/freetype-build:/home/max/git/max/Debug/_deps/sdl2-build:/home/max/git/max/Debug/_deps/miniupnp-build:/home/max/git/max/Debug/_deps/iconv-build/lib:]
But this definition will be different on each machine...
The deb installer would normally move the libraries to a standard GNU folder structure where executables are allowed to search for libraries by default. As now the shared libs are not in the allowed search path, we need to tell the game where it is allowed to search for them in addition to standard locations.
E.g. you could define or expand an environment variable called LD_LIBRARY_PATH
. You can read about it on wikipedia.
E.g.: export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/max_port/
By the way, do not install the deb from the Actions build page, the deb is not working properly yet. If you installed such a deb already, do not uninstall it, unless you are prepared to potentially restore some broken system libraries that are crucial to build or run every day stuff.
Currently lintian, a debian package checker tool, still detects 14 problems with my generated deb installers and I have no clue how to fix most of them yet 😄
Hope this helps.
I am not using a debian-based distro, so I don't install debs. I convert them to tar.gz and unpack them. As I said - a bit pain in the ass. Would be great to get MAX Port into Arch's AUR.
Anyways, I overridden the path, but it did not work.
[x@y MAXr]$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/z/data/#_archive/Gry/MAXr/ [x@y MAXr]$ max /usr/lib/pk-command-not-found: libc.so.6: version
GLIBC_ABI_DT_RELR' not found (required by /usr/lib/pk-command-not-found) /usr/lib/pk-command-not-found: libc.so.6: version
GLIBC_ABI_DT_RELR' not found (required by /usr/lib/libpackagekit-glib2.so.18) /usr/lib/pk-command-not-found: libc.so.6: versionGLIBC_ABI_DT_RELR' not found (required by /usr/lib/libglib-2.0.so.0) /usr/lib/pk-command-not-found: libc.so.6: version
GLIBC_2.38' not found (required by /usr/lib/libglib-2.0.so.0) /usr/lib/pk-command-not-found: libc.so.6: versionGLIBC_ABI_DT_RELR' not found (required by /usr/lib/libgobject-2.0.so.0) /usr/lib/pk-command-not-found: libc.so.6: version
GLIBC_ABI_DT_RELR' not found (required by /usr/lib/libgio-2.0.so.0) /usr/lib/pk-command-not-found: libc.so.6: versionGLIBC_2.38' not found (required by /usr/lib/libgio-2.0.so.0) /usr/lib/pk-command-not-found: libc.so.6: version
GLIBC_ABI_DT_RELR' not found (required by /usr/lib/libpcre2-8.so.0) /usr/lib/pk-command-not-found: libc.so.6: versionGLIBC_ABI_DT_RELR' not found (required by /usr/lib/libffi.so.8) /usr/lib/pk-command-not-found: libc.so.6: version
GLIBC_ABI_DT_RELR' not found (required by /usr/lib/libgmodule-2.0.so.0) /usr/lib/pk-command-not-found: libc.so.6: versionGLIBC_ABI_DT_RELR' not found (required by /usr/lib/libmount.so.1) /usr/lib/pk-command-not-found: libc.so.6: version
GLIBC_2.36' not found (required by /usr/lib/libmount.so.1) /usr/lib/pk-command-not-found: libc.so.6: versionGLIBC_2.38' not found (required by /usr/lib/libmount.so.1) /usr/lib/pk-command-not-found: libc.so.6: version
GLIBC_ABI_DT_RELR' not found (required by /usr/lib/libblkid.so.1) /usr/lib/pk-command-not-found: libc.so.6: version `GLIBC_2.38' not found (required by /usr/lib/libblkid.so.1)
The environment variable did work, now the custom built libraries are found, they are not listed as missed anymore. But it seems the deb installer packs not only the custom libs, but also system libs. These are system libraries in the package that the deb installer would satisfy, they are not supposed to be packed into the deb or tar.gz:
Depends: libc6 (>= 2.36), libc6 (>> 2.37), libc6 (<< 2.38), libgcc-s1 (>= 7), libstdc++6 (>= 11)
.
What happens if you delete these files from the unpacked package? max-port/ld-linux.so.2 max-port/libc.so.6 max-port/libgcc_s.so.1 max-port/libm.so.6 max-port/libstdc++.so.6.0.32
? They should normally be available anyways on your system and if not, you could install them manually. Normally the deb installer would install them.
I checked out the requirements of that AUR system. Currently the port is not compatible with it, but in time we could reach a compatible state I think. I seen nothing extreme.
A step forward, but still not quite:
$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/z/data/#_archive/Gry/MAXr ; ./max ./max: error while loading shared libraries: libfreetyped.so.6: cannot open shared object file: No such file or directory
What if you try to install SDL2 from your package manager? https://archlinux.org/packages/extra/x86_64/sdl2/
That library depends on glibc which maxport depends upon. There is a chance that then all dependencies would be fulfilled.
If that does not work either, I think you are better off building the game from source code. The build instructions are on the home page in an article for Ubuntu. I assume arch linux kde could not be that much different. If it is, then maybe that is why its not working... https://klei1984.github.io/max/build/
In the mean time I will try to figure out what would happen if I build a static version of maxport for linux too (no dependencies). Normally linux people would freak out about this "blasphemy", but their shared builds are just as broken and insufferable anyways...
I had SDL2 installed already. I also built the latest bin from git and the result is exactly the same:
./max: error while loading shared libraries: libfreetyped.so.6: cannot open shared object file: No such file or directory
Some hints, hopefully one will solve your issue.
...Gry/MAXr
?game_data=
setting in the settings.ini file that you copied into the cmake build folder. If you have all original MAX files inside the cmake build folder, you do not need to change the settings.ini as it defaults to current folder game_data=.
. The original game data folder is where the MAX.RES file is.stdout.txt
file and copy its contents here.The fade effect is now based on time instead of steps. On slow computers there are less color space transitions. In worst case there is no transition at all. The users also got the ability to simply jump over the fade effect by pressing a keyboard key or clicking the mouse. This should resolve the initial issue report, but I am keeping the ticket open till you report back about the source code build topic.
I will try to confirm it. Ability to skip the transition was already there in original MAX, but it did not work in cases when the transition became slow.
I managed to create PKGBUILD, a file that builds packages for Arch: https://pastebin.com/raw/BhZeWAin
It works for the most part, but it fails at the very end: https://pastebin.com/raw/2iYcShv7
The fade effect for logo images have 3 stages. Fade in, keep image on screen, fade out. In original M.A.X. the user was only allowed to skip the logo in the second stage. Skipping during the fade in/out stages was not made possible. As the fade in/out stages cause the extreme slowdown on high resolutions due to my sloppy renderer, skipping those stages too was rational to add.
It seems the compiler has some issues with certain standard c++ library functions. Maybe the gcc/g++ compiler is out of date. Or arch linux is more strict on standard library includes.
Do you have a discord user account? If so we could continue on discord where it is faster and more convenient to debug this.
Our discord server link is this one.
If you have no discord user, please check what is your gcc version? E.g. on Ubuntu I get this:
gcc --version
gcc (Ubuntu 12.3.0-1ubuntu1~23.04) 12.3.0
C++20 support is needed. std::map
added support for the contains
method in that version.
I think I know what is the problem. The PKGBUILD script does not use any of the provided toolchain files. The toolchain file sets up standard compiler settings like the language flavor. E.g. set(CMAKE_CXX_STANDARD 20)
. But there are other issue in the script too.
I made some changes that may or may not help:
_pkgname=("max-port")
pkgname="${_pkgname}-git"
pkgver=0.6.1.r61.g51d001f3
pkgrel=1
pkgdesc="Mechanized Assault & eXploration Port - git verion"
arch=('x86_64')
url="https://github.com/klei1984/max"
depends=('libc6>=2.36' 'libc6>>2.37' 'libc6<<2.38' 'libgcc-s1>=7' 'libstdc++6>=11')
makedepends=('file' 'build-essential' 'ninja-build' 'wget' 'gettext' 'p7zip-full' 'libsdl2-dev')
source=("${_pkgname}::git+https://github.com/klei1984/max.git")
provides=("max-port")
conflicts=("max-port")
sha256sums=('SKIP')
pkgver() {
cd ${_pkgname}
git describe --long --tags --abbrev=8 --exclude='*[a-zA-Z][a-zA-Z]*' | sed -E 's/^[^0-9]*//;s/([^-]*-g)/r\1/;s/-/./g'
}
build() {
cd "${srcdir}/${_pkgname}"
cmake --no-warn-unused-cli -G "Ninja" -DCMAKE_TOOLCHAIN_FILE=./cmake/toolchain-linux-x86_64.cmake -DCMAKE_BUILD_TYPE=Debug -DBUILD_SHARED_LIBS=ON -DCMAKE_INSTALL_PREFIX=/usr -S . -B ./build
cmake --build ./build --parallel --target package
}
package() {
cd "${srcdir}/${_pkgname}"
DESTDIR="${pkgdir}" cmake --install build
install -Dm644 LICENSE -t "${pkgdir}/usr/share/licenses/${pkgname}"
}
makepkg -si ==> Making package: max-port-git 0.6.1.r61.g51d001f3-1 (Sun 07 Apr 2024 14:47:07 CEST) ==> Checking runtime dependencies... ==> Installing missing dependencies... [sudo] password for juha: error: target not found: libc6>=2.36 error: target not found: libc6>>2.37 error: target not found: libc6<<2.38 error: target not found: libgcc-s1>=7 error: target not found: libstdc++6>=11 ==> ERROR: 'pacman' failed to install missing dependencies. ==> Missing dependencies: -> libc6>=2.36 -> libc6>>2.37 -> libc6<<2.38 -> libgcc-s1>=7 -> libstdc++6>=11 ==> Checking buildtime dependencies... ==> Installing missing dependencies... error: target not found: build-essential error: target not found: ninja-build error: target not found: p7zip-full error: target not found: libsdl2-dev ==> ERROR: 'pacman' failed to install missing dependencies. ==> Missing dependencies: -> build-essential -> ninja-build -> p7zip-full -> libsdl2-dev ==> ERROR: Could not resolve all dependencies.
Most likely package names are different on Arch. For example, build-essentials = base-devel and I have it installed. I also frequently compile things from GIT, so I'd think I have most if not all needed already installed.
Will look into the install script topic as part of the linux installer work package. Will close the ticket now that fade in/out issue should be resolved.
Operating System
Linux
Source of bug?
M.A.X. Port Version
v0.6.1
M.A.X. and DOS or DOSBox Versions
1.04
What is the issue you encountered?
When starting MAX, there is the MAX-logo screen that fades in, then out. This animation should take about 1 second, but the fading in/out process is extremely slow and takes about 15-30 seconds each. The same thing happens on every fade in/out animation in game, for example when going from the Main Menu to Load Game menu.
System: Arch Linux, KDE Hardware: ThinkPad T480s i5, Intel GPU.
Circumstances: It ALWAYS happens if I connect laptop to the docking station and start the game on my external screen 2560x1440. It NEVER happens when I run it on the same laptop but on built-in screen (1920 x 1080) without using the docking station. It NEVER happens when running the game inside a Windows 10 VM in resolution of 2560x1440 (different host with NVIDIA RTX GPU passed-through to Windows).
Anything to add?
No response