jooonior / SourceRes

Plugin for running Source Engine games at any resolution.
3 stars 0 forks source link

Does Not Work In Portal 2 #1

Open HarryMuscle opened 3 days ago

HarryMuscle commented 3 days ago

When trying to use this plugin with Portal 2 the plug fails to load and shows the following error message:

Unable to connect to the game engine, probably due to unupported engine interface version

I believe this error message comes from line 22 in the SourceRes.cpp file.

Any chance this plugin can be made to work with Portal 2?

jooonior commented 2 days ago

Portal 2 uses a newer branch of the engine and some of its interfaces are not backwards-compatible. Updating the plugin to support different incompatible interface versions would be a big change. I essentially wrote this project off when 64-bit TF2 got released so I don't feel like putting the effort in.

Instead, I threw together a script that does the same thing as this plugin. To use it, download the win32 lua_plugin binaries, install them as any other addon, and replace the contents of lua_plugin.lua with what's below.

lua_plugin.lua ```lua -- Add a "{, }," line for each new resolution to register. local RESOLUTIONS = { {720, 720}, {3840, 2160}, } -- In-game, use "mat_setvideomode 1" to change the resolution. -- No need to change anything below this line. -------------------------------------------------------------------------------- local ffi = require "ffi" -- Define FFI ctypes for interacting with the engine. -- Add `thiscall` calling convention to a function pointer. local function thiscall(ctype) if ffi.os == "Windows" then return "__thiscall " .. ctype else return ctype .. " __attribute__((thiscall))" end end ffi.cdef [[ // https://github.com/ValveSoftware/source-sdk-2013/blob/master/mp/src/public/modes.h typedef struct vmode_s { int width; int height; int bpp; int refreshRate; } vmode_t; ]] -- Get a virtual function pointer from the virtual table of an object. local function vfunc(this, index) local vtable = ffi.cast("void ***", this)[0] return vtable[index] end -- Append a new video mode with the specified resolution. local function add_video_mode(width, height, modes, counter) local count = counter[0] for i=0,count-1 do local mode = modes[i] if mode.width == width and mode.height == height then print(("resolution %ix%i already registered"):format(width, height)) return end end modes[count].width = width modes[count].height = height modes[count].bpp = modes[0].bpp modes[count].refreshRate = modes[0].refreshRate counter[0] = count + 1 print(("registered new resolution %ix%i"):format(width, height)) end -- Define the plugin and its functions. local Plugin = { } function Plugin:Load(create_interface) create_interface = ffi.cast( "void * (*)(const char *name, int *returnCode)", create_interface ) -- Find interfaces and their functions. local uifuncs = create_interface("VENGINE_GAMEUIFUNCS_VERSION005", nil) if uifuncs == nil then warn("IGameUIFuncs interface not found") return false end local IGameUIFuncs__GetVideoModes = ffi.cast( thiscall("void (*)(void *this, vmode_t **modes, int *count)"), vfunc(uifuncs, 3) ) -- Find the video mode array. local count_buf = ffi.new("int[1]") local modes_buf = ffi.new("vmode_t *[1]") IGameUIFuncs__GetVideoModes(uifuncs, modes_buf, count_buf) local count = count_buf[0] local modes = modes_buf[0] local counter = ffi.cast("int *", modes) counter = counter - 1 if counter[0] ~= count then warn("Can't find internal video mode counter") return false end -- Register new resolutions. print("Registering new resolutions...") for _, resolution in ipairs(RESOLUTIONS) do local width, height = unpack(resolution) add_video_mode(width, height, modes, counter) end -- Print registered resolutions. IGameUIFuncs__GetVideoModes(uifuncs, modes_buf, count_buf) count = count_buf[0] print(("----- %i resolutions registered -----"):format(count)) print("width", "height", "bpp", "refresh rate") for i=0,count-1 do print(modes[i].width, modes[i].height, modes[i].bpp, modes[i].refreshRate) end print(("-------------------------------------")) print('Use "mat_setvideomode 1" to change resolution.') return true end function Plugin:Unload() -- `Unload` is called even when `Load` fails, make sure we can handle that. end function Plugin:GetPluginDescription() return "custom resolutions" end return Plugin ```

You have to edit the script to change which resolutions it adds. In-game, use mat_setvideomode width height 1 to change to one of those resolutions (or you can put it in your autoexec.cfg).

When testing, I was not able to get above native resolution. It looks as if Portal clamped the resolution to native when switching, which is not something TF2 does. I'm not sure how to get around that.

HarryMuscle commented 2 days ago

Thanks for the quick answer. Unfortunately I'm having trouble getting the lua_plugin plugin to work with Portal 2. I created a new issue in that repo related to this:

https://github.com/jooonior/lua_plugin/issues/1

jooonior commented 2 days ago

The Lua script from the lua_plugin release archive won't work with Portal 2 because of different interface versions. Did you replace it with the snippet from https://github.com/jooonior/SourceRes/issues/1#issuecomment-2373478611?

HarryMuscle commented 2 days ago

Yes, I also tried using the following basic example:

local Plugin = {}

function Plugin:Load()
   print("Hello World!")
end

return Plugin

and I still get the same error message.

Just to make sure I have things configured correctly, I have the following 4 files

lua_plugin.dll
lua_plugin.lua
lua_plugin.vdf
lua51.dll

in the following folder

C:\Games\Steam\steamapps\common\Portal 2\portal2\addons

where C:\Games\Steam is the folder I have Steam installed in.

jooonior commented 2 days ago

That seems like it should work. Strange. Here's my addons folder: addons.zip. Can you try that?

HarryMuscle commented 2 days ago

I just tried your addon folder contents on two separate computers and both give me the exact same error (Unable to load plugin "addons/lua_plugin"). I even tried resetting all my Portal 2 configuration options on one of the computers and I still can't get the plugin to load. Are you testing this on a development PC? Is there maybe another dll that is required that exists on your PC but not on a PC without dev tools installed?

jooonior commented 2 days ago

The binaries are built with GitHub actions, not on my PC. Still, it's possible that it links to something you don't have. I'll check it out.

What happens when you delete the .lua script? If you don't see this message, that means the problem is likely with the linker.

HarryMuscle commented 2 days ago

I just tried running Portal 2 with the .lua script file deleted (but the other 3 files still in the addons folder) and I do NOT get that message (I still only get the Unable to load plugin "addons/lua_plugin" message).

jooonior commented 2 days ago

Can you check if DLL imports are resolved correctly? Not sure what's the proper way to do this on Windows, but I found this https://github.com/lucasg/Dependencies. When I open lua_plugin.dll in the GUI I get this: Capture There are some errors under kernel32, but since it works for me, those don't matter, I guess.

jooonior commented 2 days ago

From https://github.com/jooonior/lua_plugin/issues/1#issue-2548954334:

In case it helps, I also tried version 1.1.0 and it gives the following error message

ICVar interface not found
Unable to load plugin "addons/lua_plugin"

The ICVar interface not found message is from the example Lua script, so it looks like v1.1.0 works. Can you try these:

  1. Use v1.1.0 but delete the Lua script. You should get the message I talked about in https://github.com/jooonior/SourceRes/issues/1#issuecomment-2375257157.
  2. Use v1.1.0 with the Lua script from https://github.com/jooonior/SourceRes/issues/1#issuecomment-2373478611.
HarryMuscle commented 2 days ago

I think we're getting somewhere. The missing dependencies are:

MSVCP140D.dll
VCRUNTIME140D.dll
ucrtbased.dll

however, if I'm not mistaken all of these are debug dependencies and not release dependencies (the release versions of these dependencies would not have a D or d at the end of their name). I think the lua_plugin might be getting build in debug mode and not release mode maybe?

HarryMuscle commented 2 days ago

From jooonior/lua_plugin#1 (comment):

In case it helps, I also tried version 1.1.0 and it gives the following error message

ICVar interface not found
Unable to load plugin "addons/lua_plugin"

The ICVar interface not found message is from the example Lua script, so it looks like v1.1.0 works. Can you try these:

1. Use v1.1.0 but delete the Lua script. You should get the message I talked about in [Does Not Work In Portal 2 #1 (comment)](https://github.com/jooonior/SourceRes/issues/1#issuecomment-2375257157).

2. Use v1.1.0 with the Lua script from [Does Not Work In Portal 2 #1 (comment)](https://github.com/jooonior/SourceRes/issues/1#issuecomment-2373478611).

You're right, version 1.1.0 works after I change the lua script (I guess I forgot to do that when I tested it originally). So it looks like the main issue is that version 1.2.0 was compiled in debug mode and not release mode.

jooonior commented 2 days ago

however, if I'm not mistaken all of these are debug dependencies and not release dependencies (the release versions of these dependencies would not have a D or d at the end of their name). I think the lua_plugin might be getting build in debug mode and not release mode maybe?

Yeah, you're right. In 1.2.0 I switched from Visual Studio projects to CMake. I guess CMAKE_BUILD_TYPE=Release is not enough to link release libs. Oh well, I'll figure it out. TY for the help.

jooonior commented 2 days ago

Also can you go above your native resolution? It didn't work for me. I was getting:

mat_setvideomode 3840 2160 1
Changing resolutions from (1920, 1080) -> (1920, 1080)
HarryMuscle commented 2 days ago

Also can you go above your native resolution? It didn't work for me. I was getting:

mat_setvideomode 3840 2160 1
Changing resolutions from (1920, 1080) -> (1920, 1080)

That's what I've been playing around with for the last little bit. I even replaced every single registered resolution with a resolution higher than native and it still won't go above the native resolution. So frustrating.

jooonior commented 2 days ago

Not sure if it would work, but CRU lets you run resolutions that your monitor doesn't support. I use it with Looking Glass to get higher refresh rates than my dummy HDMI 1 display output allows. But you'd probably need two monitors, since the affected one won't make sense of the data its receiving.

Also I remember someone using virtual resolution or whatever it's called (render higher res and scale down, AMD drivers had that option at one time I think) to record 4k with 1080 monitor. You might be able to get something like that working too.