mirror of
https://github.com/mrxenginner/reVC.git
synced 2026-10-10 03:43:04 +08:00
Add first-class macOS build and launch support (#42)
* fix: fix GLFW video mode fallback on startup * fix: fix GLFW mouse activation on startup * feat: locate macOS game directory when launched from Finder * feat: ask the user to choose a game directory if gamefiles could not be found * feat: create an app bundle for macOS builds * feat: resolve gamefiles inside or beside the app bundle * fix: distinguish ARM64 Premake platforms * fix: use libmpg123 pkg-config metadata * feat: add Xcode support to Premake and CMake * chore: ignore .DS_Store files * fix: center mouse cursor when launching and quitting the game * fix: address a TODO comment * feat: bundle reVC gamefiles as runtime overrides * feat: use macOS user directories for saves and settings * refactor: store macOS game path in reVC.ini * fix: make Xcode recognize the archive as a macOS app archive * fix: enable Hardened Runtime for the Xcode app target * fix: support CMake’s Xcode generator on macOS * build: remove stale libsndfile linkage * build: make the app bundle self-contained * fix: prevent buffer overflow with long game directory paths * chore: add application category to Info.plist * fix: omit missing Homebrew OpenAL search paths when using MacPorts * refactor: move game path declarations to FileMgr header * build: include the LICENSE file in the app bundle
This commit is contained in:
@@ -3,6 +3,9 @@
|
||||
##
|
||||
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||
|
||||
# macOS
|
||||
.DS_Store
|
||||
|
||||
# User-specific files
|
||||
*.rsuser
|
||||
*.suo
|
||||
|
||||
+137
@@ -3,6 +3,29 @@ cmake_minimum_required(VERSION 3.14)
|
||||
set(EXECUTABLE reVC)
|
||||
set(PROJECT REVC)
|
||||
|
||||
if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin")
|
||||
if(CMAKE_GENERATOR STREQUAL "Xcode")
|
||||
set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64" CACHE STRING "macOS architectures")
|
||||
if(NOT CMAKE_OSX_DEPLOYMENT_TARGET)
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.12" CACHE STRING
|
||||
"Minimum macOS version" FORCE)
|
||||
endif()
|
||||
if(CMAKE_OSX_DEPLOYMENT_TARGET VERSION_LESS "11.0")
|
||||
set("CMAKE_XCODE_ATTRIBUTE_MACOSX_DEPLOYMENT_TARGET[arch=arm64]" "11.0")
|
||||
endif()
|
||||
elseif(NOT CMAKE_OSX_DEPLOYMENT_TARGET)
|
||||
if(CMAKE_OSX_ARCHITECTURES STREQUAL "x86_64" OR
|
||||
(NOT CMAKE_OSX_ARCHITECTURES AND
|
||||
CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "x86_64"))
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.12" CACHE STRING
|
||||
"Minimum macOS version" FORCE)
|
||||
else()
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "11.0" CACHE STRING
|
||||
"Minimum macOS version" FORCE)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
project(${EXECUTABLE} C CXX)
|
||||
set(${PROJECT}_AUTHOR "${PROJECT} Team")
|
||||
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
|
||||
@@ -11,6 +34,117 @@ include(GetGitRevisionDescription)
|
||||
get_git_head_revision(GIT_REFSPEC GIT_SHA1 "ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR")
|
||||
message(STATUS "Building ${CMAKE_PROJECT_NAME} GIT SHA1: ${GIT_SHA1}")
|
||||
|
||||
if(APPLE)
|
||||
macro(reVC_define_macos_dependency key alias formula library filename)
|
||||
list(APPEND ${PROJECT}_MACOS_DEPENDENCIES "${key}")
|
||||
set(${PROJECT}_MACOS_${key}_ALIAS "${alias}")
|
||||
set(${PROJECT}_MACOS_${key}_FORMULA "${formula}")
|
||||
set(${PROJECT}_MACOS_${key}_LIBRARY "${library}")
|
||||
set(${PROJECT}_MACOS_${key}_FILENAME "${filename}")
|
||||
endmacro()
|
||||
|
||||
reVC_define_macos_dependency(OPENAL OpenAL::OpenAL
|
||||
openal-soft openal libopenal.1.dylib)
|
||||
reVC_define_macos_dependency(MPG123 MPG123::libmpg123
|
||||
mpg123 mpg123 libmpg123.0.dylib)
|
||||
reVC_define_macos_dependency(GLFW glfw
|
||||
glfw glfw libglfw.3.dylib)
|
||||
|
||||
if(CMAKE_GENERATOR STREQUAL "Xcode")
|
||||
set(${PROJECT}_HOMEBREW_ARM64_PREFIX "/opt/homebrew" CACHE PATH "arm64 Homebrew prefix")
|
||||
set(${PROJECT}_HOMEBREW_X86_64_PREFIX "/usr/local" CACHE PATH "x86_64 Homebrew prefix")
|
||||
|
||||
function(reVC_macos_dependency target alias dylibs formula library filename)
|
||||
if(EXISTS "/opt/local/lib/${filename}")
|
||||
add_library(${target} INTERFACE)
|
||||
add_library(${alias} ALIAS ${target})
|
||||
target_include_directories(${target} INTERFACE "/opt/local/include")
|
||||
target_link_libraries(${target} INTERFACE "/opt/local/lib/${filename}")
|
||||
set(${dylibs} "/opt/local/lib/${filename}" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
set(include_prefix)
|
||||
set(link_options)
|
||||
set(dependency_dylibs)
|
||||
foreach(architecture arm64 x86_64)
|
||||
if(architecture IN_LIST CMAKE_OSX_ARCHITECTURES)
|
||||
string(TOUPPER "${architecture}" architecture_upper)
|
||||
set(prefix "${${PROJECT}_HOMEBREW_${architecture_upper}_PREFIX}")
|
||||
set(dylib "${prefix}/opt/${formula}/lib/${filename}")
|
||||
if(NOT EXISTS "${dylib}")
|
||||
message(FATAL_ERROR
|
||||
"${architecture} ${formula} was not found under ${prefix}"
|
||||
)
|
||||
endif()
|
||||
if(NOT include_prefix)
|
||||
set(include_prefix "${prefix}")
|
||||
endif()
|
||||
list(APPEND dependency_dylibs "${dylib}")
|
||||
list(APPEND link_options
|
||||
"SHELL:-Xarch_${architecture} -L${prefix}/opt/${formula}/lib"
|
||||
)
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
add_library(${target} INTERFACE)
|
||||
add_library(${alias} ALIAS ${target})
|
||||
target_include_directories(${target} INTERFACE
|
||||
"${include_prefix}/opt/${formula}/include"
|
||||
)
|
||||
target_link_options(${target} INTERFACE ${link_options} "-l${library}")
|
||||
set(${dylibs} "${dependency_dylibs}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
if("arm64" IN_LIST CMAKE_OSX_ARCHITECTURES OR
|
||||
"x86_64" IN_LIST CMAKE_OSX_ARCHITECTURES)
|
||||
foreach(dependency IN LISTS ${PROJECT}_MACOS_DEPENDENCIES)
|
||||
string(TOLOWER "${dependency}" dependency_lower)
|
||||
reVC_macos_dependency(${PROJECT}_macos_${dependency_lower}
|
||||
${${PROJECT}_MACOS_${dependency}_ALIAS}
|
||||
${PROJECT}_MACOS_${dependency}_DYLIBS
|
||||
${${PROJECT}_MACOS_${dependency}_FORMULA}
|
||||
${${PROJECT}_MACOS_${dependency}_LIBRARY}
|
||||
${${PROJECT}_MACOS_${dependency}_FILENAME})
|
||||
endforeach()
|
||||
endif()
|
||||
else()
|
||||
function(reVC_macos_dependency_dylib output formula filename)
|
||||
set(prefix "$ENV{HOMEBREW_PREFIX}")
|
||||
set(candidates "/opt/local/lib/${filename}")
|
||||
if(CMAKE_OSX_ARCHITECTURES STREQUAL "x86_64" OR
|
||||
(NOT CMAKE_OSX_ARCHITECTURES AND
|
||||
CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64"))
|
||||
list(APPEND candidates
|
||||
"/usr/local/opt/${formula}/lib/${filename}"
|
||||
)
|
||||
else()
|
||||
if(prefix)
|
||||
list(APPEND candidates "${prefix}/opt/${formula}/lib/${filename}")
|
||||
endif()
|
||||
list(APPEND candidates
|
||||
"/opt/homebrew/opt/${formula}/lib/${filename}"
|
||||
"/usr/local/opt/${formula}/lib/${filename}"
|
||||
)
|
||||
endif()
|
||||
list(REMOVE_DUPLICATES candidates)
|
||||
foreach(candidate IN LISTS candidates)
|
||||
if(EXISTS "${candidate}")
|
||||
set(${output} "${candidate}" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
foreach(dependency IN LISTS ${PROJECT}_MACOS_DEPENDENCIES)
|
||||
reVC_macos_dependency_dylib(
|
||||
${PROJECT}_MACOS_${dependency}_DYLIBS
|
||||
${${PROJECT}_MACOS_${dependency}_FORMULA}
|
||||
${${PROJECT}_MACOS_${dependency}_FILENAME})
|
||||
endforeach()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
if(NINTENDO_SWITCH)
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake/nx")
|
||||
@@ -42,6 +176,9 @@ endif()
|
||||
|
||||
option(${PROJECT}_VENDORED_LIBRW "Use vendored librw" ON)
|
||||
if(${PROJECT}_VENDORED_LIBRW)
|
||||
if(NOT DEFINED LIBRW_PLATFORM AND NOT PS2)
|
||||
set(LIBRW_PLATFORM "GL3" CACHE STRING "librw platform")
|
||||
endif()
|
||||
add_subdirectory(vendor/librw)
|
||||
else()
|
||||
find_package(librw REQUIRED)
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
find_package(PkgConfig QUIET)
|
||||
if(PKG_CONFIG_FOUND)
|
||||
pkg_search_module(PKG_MPG123 mpg123)
|
||||
pkg_search_module(PKG_MPG123 libmpg123)
|
||||
endif()
|
||||
|
||||
find_path(mpg123_INCLUDE_DIR mpg123.h
|
||||
@@ -19,7 +19,7 @@ find_path(mpg123_INCLUDE_DIR mpg123.h
|
||||
)
|
||||
|
||||
find_library(mpg123_LIBRARIES NAMES mpg123 mpg123-0 libmpg123-0
|
||||
HINTS ${PKG_MPG123_LIBRARIES}
|
||||
HINTS ${PKG_MPG123_LIBRARY_DIRS}
|
||||
PATHS "${mpg123_DIR}"
|
||||
PATH_SUFFIXES lib
|
||||
)
|
||||
|
||||
+244
-36
@@ -68,6 +68,126 @@ function getarch(a)
|
||||
return a
|
||||
end
|
||||
|
||||
local function dependencyincludedirs(paths)
|
||||
if _ACTION == "xcode4" then
|
||||
externalincludedirs(paths)
|
||||
else
|
||||
includedirs(paths)
|
||||
end
|
||||
end
|
||||
|
||||
local macosxHomebrewPrefix = os.getenv("HOMEBREW_PREFIX")
|
||||
if not macosxHomebrewPrefix or macosxHomebrewPrefix == "" then
|
||||
macosxHomebrewPrefix = os.host() == "macosx" and os.hostarch() == "ARM64" and "/opt/homebrew" or "/usr/local"
|
||||
end
|
||||
|
||||
local function resolveMacosxDependencyDylib(formula, filename, homebrewPrefix)
|
||||
local candidates = {
|
||||
path.join("/opt/local/lib", filename),
|
||||
path.join(homebrewPrefix, "opt", formula, "lib", filename),
|
||||
}
|
||||
|
||||
for _, candidate in ipairs(candidates) do
|
||||
if os.isfile(candidate) then
|
||||
return candidate
|
||||
end
|
||||
end
|
||||
return candidates[2]
|
||||
end
|
||||
|
||||
local macosxDependencies = {
|
||||
{ formula = "openal-soft", filename = "libopenal.1.dylib" },
|
||||
{ formula = "mpg123", filename = "libmpg123.0.dylib" },
|
||||
{ formula = "glfw", filename = "libglfw.3.dylib" },
|
||||
}
|
||||
|
||||
local function resolveMacosxDependencyDylibs(homebrewPrefix)
|
||||
local dylibs = {}
|
||||
for _, dependency in ipairs(macosxDependencies) do
|
||||
table.insert(dylibs, {
|
||||
filename = dependency.filename,
|
||||
path = resolveMacosxDependencyDylib(dependency.formula, dependency.filename, homebrewPrefix),
|
||||
})
|
||||
end
|
||||
return dylibs
|
||||
end
|
||||
|
||||
local macosxDependencyDylibs = resolveMacosxDependencyDylibs(macosxHomebrewPrefix)
|
||||
local macosxArm64HomebrewPrefix = os.hostarch() == "ARM64" and macosxHomebrewPrefix or "/opt/homebrew"
|
||||
local macosxAmd64HomebrewPrefix = os.hostarch() == "ARM64" and "/usr/local" or macosxHomebrewPrefix
|
||||
local macosxArm64DependencyDylibs = resolveMacosxDependencyDylibs(macosxArm64HomebrewPrefix)
|
||||
local macosxAmd64DependencyDylibs = resolveMacosxDependencyDylibs(macosxAmd64HomebrewPrefix)
|
||||
|
||||
local function existingDirectories(directories)
|
||||
local existing = {}
|
||||
for _, directory in ipairs(directories) do
|
||||
if os.isdir(directory) then
|
||||
table.insert(existing, directory)
|
||||
end
|
||||
end
|
||||
return existing
|
||||
end
|
||||
|
||||
local function existingXcodeSearchPaths(directories)
|
||||
local existing = existingDirectories(directories)
|
||||
table.insert(existing, 1, "$(inherited)")
|
||||
return existing
|
||||
end
|
||||
|
||||
local macosxXcodeArchitectures = _OPTIONS["arch"]
|
||||
if not macosxXcodeArchitectures or macosxXcodeArchitectures == "universal" then
|
||||
macosxXcodeArchitectures = "$(ARCHS_STANDARD)"
|
||||
end
|
||||
|
||||
local macosxXcodeDeploymentTarget = macosxXcodeArchitectures == "x86_64" and "10.12" or "11.0"
|
||||
local macosxXcodeBuildSettings = {
|
||||
["ARCHS"] = { macosxXcodeArchitectures },
|
||||
["MACOSX_DEPLOYMENT_TARGET"] = { macosxXcodeDeploymentTarget },
|
||||
["ONLY_ACTIVE_ARCH"] = { "YES" },
|
||||
}
|
||||
if macosxXcodeArchitectures == "$(ARCHS_STANDARD)" then
|
||||
macosxXcodeBuildSettings["MACOSX_DEPLOYMENT_TARGET[arch=x86_64]"] = { "10.12" }
|
||||
end
|
||||
|
||||
local function macosxDependencyPaths(dylibs)
|
||||
local paths = {}
|
||||
for _, dylib in ipairs(dylibs) do
|
||||
table.insert(paths, dylib.path)
|
||||
end
|
||||
return paths
|
||||
end
|
||||
|
||||
local function macosxDependencyFilenames(dylibs)
|
||||
local filenames = {}
|
||||
for _, dylib in ipairs(dylibs) do
|
||||
table.insert(filenames, dylib.filename)
|
||||
end
|
||||
return filenames
|
||||
end
|
||||
|
||||
local function macosxInstallNameCommands(dylibs, executable)
|
||||
local commands = {}
|
||||
for _, dylib in ipairs(dylibs) do
|
||||
table.insert(commands, 'install_name_tool -change "' .. dylib.path .. '" "@rpath/' .. dylib.filename .. '" "' .. executable .. '"')
|
||||
end
|
||||
return commands
|
||||
end
|
||||
|
||||
local function macosxGmakeBundleCommands(dylibs)
|
||||
local commands = {}
|
||||
for _, dylib in ipairs(dylibs) do
|
||||
table.insert(commands, '{COPYFILE} "' .. dylib.path .. '" "%{cfg.targetdir}/reVC.app/Contents/Frameworks/' .. dylib.filename .. '"')
|
||||
end
|
||||
for _, command in ipairs(macosxInstallNameCommands(dylibs, "%{cfg.targetdir}/reVC.app/Contents/MacOS/reVC")) do
|
||||
table.insert(commands, command)
|
||||
end
|
||||
for _, dylib in ipairs(dylibs) do
|
||||
table.insert(commands, 'codesign --force --sign - "%{cfg.targetdir}/reVC.app/Contents/Frameworks/' .. dylib.filename .. '"')
|
||||
end
|
||||
table.insert(commands, 'codesign --force --sign - "%{cfg.targetdir}/reVC.app"')
|
||||
return commands
|
||||
end
|
||||
|
||||
workspace "reVC"
|
||||
language "C++"
|
||||
configurations { "Debug", "Release" }
|
||||
@@ -111,10 +231,15 @@ workspace "reVC"
|
||||
}
|
||||
|
||||
filter { "system:macosx" }
|
||||
cppdialect "gnu++14"
|
||||
if _ACTION == "xcode4" then
|
||||
platforms { "macosx-librw_gl3_glfw-oal" }
|
||||
else
|
||||
platforms {
|
||||
"macosx-arm64-librw_gl3_glfw-oal",
|
||||
"macosx-amd64-librw_gl3_glfw-oal",
|
||||
}
|
||||
end
|
||||
|
||||
filter "configurations:Debug"
|
||||
defines { "DEBUG" }
|
||||
@@ -144,20 +269,22 @@ workspace "reVC"
|
||||
filter { "platforms:*amd64*" }
|
||||
architecture "amd64"
|
||||
|
||||
filter { "platforms:*arm*" }
|
||||
filter { "platforms:*arm-*" }
|
||||
architecture "ARM"
|
||||
|
||||
filter { "platforms:macosx-arm64-*", "files:**.cpp"}
|
||||
buildoptions { "-target", "arm64-apple-macos11", "-std=gnu++14" }
|
||||
filter { "platforms:*arm64*" }
|
||||
architecture "ARM64"
|
||||
|
||||
filter { "platforms:macosx-arm64-*", "files:**.c"}
|
||||
filter { "platforms:macosx-arm64-*", "action:not xcode4" }
|
||||
buildoptions { "-target", "arm64-apple-macos11" }
|
||||
linkoptions { "-target", "arm64-apple-macos11" }
|
||||
|
||||
filter { "platforms:macosx-amd64-*", "files:**.cpp"}
|
||||
buildoptions { "-target", "x86_64-apple-macos10.12", "-std=gnu++14" }
|
||||
|
||||
filter { "platforms:macosx-amd64-*", "files:**.c"}
|
||||
filter { "platforms:macosx-amd64-*", "action:not xcode4" }
|
||||
buildoptions { "-target", "x86_64-apple-macos10.12" }
|
||||
linkoptions { "-target", "x86_64-apple-macos10.12" }
|
||||
|
||||
filter { "system:macosx", "action:xcode4" }
|
||||
xcodebuildsettings(macosxXcodeBuildSettings)
|
||||
|
||||
filter { "platforms:*librw_d3d9*" }
|
||||
defines { "RW_D3D9" }
|
||||
@@ -198,7 +325,15 @@ if(_OPTIONS["with-librw"]) then
|
||||
project "librw"
|
||||
kind "StaticLib"
|
||||
targetname "rw"
|
||||
if _ACTION == "xcode4" then
|
||||
targetdir "${BUILD_DIR}/%{cfg.buildcfg}"
|
||||
xcodebuildsettings {
|
||||
["SKIP_INSTALL"] = "YES",
|
||||
}
|
||||
else
|
||||
targetdir(path.join(Librw, "lib/%{cfg.platform}/%{cfg.buildcfg}"))
|
||||
end
|
||||
|
||||
files { path.join(Librw, "src/*.*") }
|
||||
files { path.join(Librw, "src/*/*.*") }
|
||||
files { path.join(Librw, "src/gl/*/*.*") }
|
||||
@@ -220,16 +355,19 @@ project "librw"
|
||||
|
||||
-- Support MacPorts and Homebrew
|
||||
filter "platforms:macosx-arm64-*"
|
||||
includedirs { "/opt/local/include" }
|
||||
includedirs {"/opt/homebrew/include" }
|
||||
libdirs { "/opt/local/lib" }
|
||||
libdirs { "/opt/homebrew/lib" }
|
||||
dependencyincludedirs { "/opt/local/include", "/opt/homebrew/include" }
|
||||
libdirs { "/opt/local/lib", "/opt/homebrew/lib" }
|
||||
|
||||
filter "platforms:macosx-amd64-*"
|
||||
includedirs { "/opt/local/include" }
|
||||
includedirs {"/usr/local/include" }
|
||||
libdirs { "/opt/local/lib" }
|
||||
libdirs { "/usr/local/lib" }
|
||||
dependencyincludedirs { "/opt/local/include", "/usr/local/include" }
|
||||
libdirs { "/opt/local/lib", "/usr/local/lib" }
|
||||
|
||||
filter { "system:macosx", "action:xcode4" }
|
||||
dependencyincludedirs { "/opt/local/include", "/opt/homebrew/include", "/usr/local/include" }
|
||||
xcodebuildsettings {
|
||||
["LIBRARY_SEARCH_PATHS[arch=arm64]"] = { "$(inherited)", "/opt/local/lib", "/opt/homebrew/lib" },
|
||||
["LIBRARY_SEARCH_PATHS[arch=x86_64]"] = { "$(inherited)", "/opt/local/lib", "/usr/local/lib" },
|
||||
}
|
||||
|
||||
filter "platforms:*gl3_glfw*"
|
||||
staticruntime "off"
|
||||
@@ -246,7 +384,62 @@ end
|
||||
project "reVC"
|
||||
kind "WindowedApp"
|
||||
targetname "reVC"
|
||||
if _ACTION == "xcode4" then
|
||||
targetdir "${BUILD_DIR}/%{cfg.buildcfg}"
|
||||
else
|
||||
targetdir "bin/%{cfg.platform}/%{cfg.buildcfg}"
|
||||
end
|
||||
|
||||
filter { "system:macosx" }
|
||||
files { "res/images/reVC.icns", "res/macos/Info.plist", "res/macos/ThirdPartyNotices.txt" }
|
||||
|
||||
filter { "system:macosx", "action:xcode4" }
|
||||
xcodebuildresources { "res/macos/ThirdPartyNotices.txt" }
|
||||
xcodebuildsettings {
|
||||
["PRODUCT_BUNDLE_IDENTIFIER"] = "io.github.mrxenginner.reVC",
|
||||
["INSTALL_PATH"] = "$(LOCAL_APPS_DIR)",
|
||||
["CODE_SIGN_STYLE"] = "Automatic",
|
||||
["LD_RUNPATH_SEARCH_PATHS"] = "$(inherited) @executable_path/../Frameworks",
|
||||
}
|
||||
links(macosxDependencyPaths(macosxDependencyDylibs))
|
||||
links { "pthread" }
|
||||
embedAndSign(macosxDependencyFilenames(macosxDependencyDylibs))
|
||||
postbuildcommands {
|
||||
'{MKDIR} "%{cfg.targetdir}/reVC.app/Contents/Resources"',
|
||||
'{COPYFILE} "%{prj.location}/../LICENSE.md" "%{cfg.targetdir}/reVC.app/Contents/Resources/LICENSE"',
|
||||
'{RMDIR} "%{cfg.targetdir}/reVC.app/Contents/Resources/gamefiles"',
|
||||
'{COPYDIR} "%{prj.location}/../gamefiles" "%{cfg.targetdir}/reVC.app/Contents/Resources"',
|
||||
}
|
||||
postbuildcommands(macosxInstallNameCommands(macosxDependencyDylibs, "${TARGET_BUILD_DIR}/${EXECUTABLE_PATH}"))
|
||||
|
||||
filter { "system:macosx", "action:xcode4", "configurations:Release" }
|
||||
xcodebuildsettings {
|
||||
["CODE_SIGN_IDENTITY"] = "Apple Development",
|
||||
["ENABLE_HARDENED_RUNTIME"] = "YES",
|
||||
}
|
||||
|
||||
filter { "system:macosx", "action:gmake*" }
|
||||
linkoptions { "-Wl,-rpath,@executable_path/../Frameworks" }
|
||||
postbuildcommands {
|
||||
'{MKDIR} "%{cfg.targetdir}/reVC.app/Contents/MacOS"',
|
||||
'{MKDIR} "%{cfg.targetdir}/reVC.app/Contents/Frameworks"',
|
||||
'{MKDIR} "%{cfg.targetdir}/reVC.app/Contents/Resources"',
|
||||
'{COPYFILE} "%{cfg.buildtarget.abspath}" "%{cfg.targetdir}/reVC.app/Contents/MacOS/reVC"',
|
||||
'{COPYFILE} "%{prj.location}/../res/images/reVC.icns" "%{cfg.targetdir}/reVC.app/Contents/Resources/reVC.icns"',
|
||||
'{COPYFILE} "%{prj.location}/../res/macos/ThirdPartyNotices.txt" "%{cfg.targetdir}/reVC.app/Contents/Resources/ThirdPartyNotices.txt"',
|
||||
'{COPYFILE} "%{prj.location}/../LICENSE.md" "%{cfg.targetdir}/reVC.app/Contents/Resources/LICENSE"',
|
||||
'{COPYFILE} "%{prj.location}/../res/macos/Info.plist" "%{cfg.targetdir}/reVC.app/Contents/Info.plist"',
|
||||
'{RMDIR} "%{cfg.targetdir}/reVC.app/Contents/Resources/gamefiles"',
|
||||
'{COPYDIR} "%{prj.location}/../gamefiles" "%{cfg.targetdir}/reVC.app/Contents/Resources"',
|
||||
}
|
||||
|
||||
filter { "action:gmake*", "platforms:macosx-arm64-*" }
|
||||
postbuildcommands(macosxGmakeBundleCommands(macosxArm64DependencyDylibs))
|
||||
|
||||
filter { "action:gmake*", "platforms:macosx-amd64-*" }
|
||||
postbuildcommands(macosxGmakeBundleCommands(macosxAmd64DependencyDylibs))
|
||||
|
||||
filter {}
|
||||
|
||||
if(_OPTIONS["with-librw"]) then
|
||||
dependson "librw"
|
||||
@@ -305,6 +498,11 @@ project "reVC"
|
||||
includedirs { "src/weapons" }
|
||||
includedirs { "src/extras" }
|
||||
|
||||
filter "action:xcode4"
|
||||
externalincludedirs { "src/audio/eax", "src/fakerw", Librw }
|
||||
|
||||
filter {}
|
||||
|
||||
if(not _OPTIONS["no-git-hash"]) then
|
||||
defines { "USE_OUR_VERSIONING" }
|
||||
end
|
||||
@@ -396,21 +594,21 @@ project "reVC"
|
||||
libdirs { "vendor/openal-soft/libs/Win64" }
|
||||
|
||||
filter "platforms:linux*oal"
|
||||
links { "openal", "mpg123", "sndfile", "pthread" }
|
||||
links { "openal", "mpg123", "pthread" }
|
||||
|
||||
filter "platforms:bsd*oal"
|
||||
links { "openal", "mpg123", "sndfile", "pthread" }
|
||||
links { "openal", "mpg123", "pthread" }
|
||||
|
||||
filter "platforms:macosx*oal"
|
||||
links { "openal", "mpg123", "sndfile", "pthread" }
|
||||
filter { "platforms:macosx*oal", "action:not xcode4" }
|
||||
links { "openal", "mpg123", "pthread" }
|
||||
|
||||
filter "platforms:macosx-arm64-*oal"
|
||||
includedirs { "/opt/homebrew/opt/openal-soft/include" }
|
||||
libdirs { "/opt/homebrew/opt/openal-soft/lib" }
|
||||
dependencyincludedirs(existingDirectories { "/opt/homebrew/opt/openal-soft/include" })
|
||||
libdirs(existingDirectories { "/opt/homebrew/opt/openal-soft/lib" })
|
||||
|
||||
filter "platforms:macosx-amd64-*oal"
|
||||
includedirs { "/usr/local/opt/openal-soft/include" }
|
||||
libdirs { "/usr/local/opt/openal-soft/lib" }
|
||||
dependencyincludedirs(existingDirectories { "/usr/local/opt/openal-soft/include" })
|
||||
libdirs(existingDirectories { "/usr/local/opt/openal-soft/lib" })
|
||||
|
||||
if _OPTIONS["with-opus"] then
|
||||
filter {}
|
||||
@@ -431,7 +629,7 @@ project "reVC"
|
||||
files { addSrcFiles("src/fakerw") }
|
||||
includedirs { "src/fakerw" }
|
||||
includedirs { Librw }
|
||||
if(_OPTIONS["with-librw"]) then
|
||||
if(_OPTIONS["with-librw"] and _ACTION ~= "xcode4") then
|
||||
libdirs { "vendor/librw/lib/%{cfg.platform}/%{cfg.buildcfg}" }
|
||||
end
|
||||
links { "rw" }
|
||||
@@ -460,18 +658,28 @@ project "reVC"
|
||||
includedirs { "/usr/local/include" }
|
||||
libdirs { "/usr/local/lib" }
|
||||
|
||||
filter "platforms:macosx-arm64-*gl3_glfw*"
|
||||
filter { "platforms:macosx*gl3_glfw*", "action:not xcode4" }
|
||||
links { "glfw" }
|
||||
linkoptions { "-framework OpenGL" }
|
||||
includedirs { "/opt/local/include" }
|
||||
includedirs {"/opt/homebrew/include" }
|
||||
libdirs { "/opt/local/lib" }
|
||||
libdirs { "/opt/homebrew/lib" }
|
||||
|
||||
filter "platforms:macosx-arm64-*gl3_glfw*"
|
||||
dependencyincludedirs { "/opt/local/include", "/opt/homebrew/include" }
|
||||
libdirs { "/opt/local/lib", "/opt/homebrew/lib" }
|
||||
|
||||
filter "platforms:macosx-amd64-*gl3_glfw*"
|
||||
links { "glfw" }
|
||||
linkoptions { "-framework OpenGL" }
|
||||
includedirs { "/opt/local/include" }
|
||||
includedirs {"/usr/local/include" }
|
||||
libdirs { "/opt/local/lib" }
|
||||
libdirs { "/usr/local/lib" }
|
||||
dependencyincludedirs { "/opt/local/include", "/usr/local/include" }
|
||||
libdirs { "/opt/local/lib", "/usr/local/lib" }
|
||||
|
||||
filter { "system:macosx", "action:xcode4" }
|
||||
links { "OpenGL.framework" }
|
||||
dependencyincludedirs(existingDirectories {
|
||||
"/opt/local/include",
|
||||
"/opt/homebrew/include",
|
||||
"/usr/local/include",
|
||||
"/opt/homebrew/opt/openal-soft/include",
|
||||
"/usr/local/opt/openal-soft/include",
|
||||
})
|
||||
xcodebuildsettings {
|
||||
["LIBRARY_SEARCH_PATHS[arch=arm64]"] = existingXcodeSearchPaths { "/opt/local/lib", "/opt/homebrew/lib", "/opt/homebrew/opt/openal-soft/lib" },
|
||||
["LIBRARY_SEARCH_PATHS[arch=x86_64]"] = existingXcodeSearchPaths { "/opt/local/lib", "/usr/local/lib", "/usr/local/opt/openal-soft/lib" },
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>reVC</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>reVC.icns</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>io.github.mrxenginner.reVC</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>reVC</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>10.12</string>
|
||||
<key>LSMinimumSystemVersionByArchitecture</key>
|
||||
<dict>
|
||||
<key>arm64</key>
|
||||
<string>11.0</string>
|
||||
<key>x86_64</key>
|
||||
<string>10.12</string>
|
||||
</dict>
|
||||
<key>NSHighResolutionCapable</key>
|
||||
<true/>
|
||||
<key>LSApplicationCategoryType</key>
|
||||
<string>public.app-category.games</string>
|
||||
</dict>
|
||||
</plist>
|
||||
File diff suppressed because it is too large
Load Diff
+125
-1
@@ -2,6 +2,7 @@ find_package(Threads REQUIRED)
|
||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||
|
||||
file(GLOB_RECURSE ${PROJECT}_SOURCES "*.cpp" "*.h" "*.rc")
|
||||
list(REMOVE_ITEM ${PROJECT}_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/extras/GitSHA1.cpp")
|
||||
|
||||
function(header_directories RETURN_LIST)
|
||||
file(GLOB_RECURSE ALL_SRCS *.h *.cpp *.c)
|
||||
@@ -84,7 +85,18 @@ else()
|
||||
endif()
|
||||
|
||||
if(${PROJECT}_AUDIO STREQUAL "OAL")
|
||||
if(NOT TARGET OpenAL::OpenAL)
|
||||
if(APPLE)
|
||||
find_package(OpenAL CONFIG QUIET
|
||||
PATHS
|
||||
"/opt/homebrew/opt/openal-soft"
|
||||
"/usr/local/opt/openal-soft"
|
||||
)
|
||||
endif()
|
||||
if(NOT TARGET OpenAL::OpenAL)
|
||||
find_package(OpenAL REQUIRED)
|
||||
endif()
|
||||
endif()
|
||||
if(TARGET OpenAL::OpenAL)
|
||||
target_link_libraries(${EXECUTABLE} PRIVATE OpenAL::OpenAL)
|
||||
else()
|
||||
@@ -106,7 +118,9 @@ elseif(${PROJECT}_AUDIO STREQUAL "MSS")
|
||||
target_link_libraries(${EXECUTABLE} PRIVATE MilesSDK::MilesSDK)
|
||||
endif()
|
||||
|
||||
find_package(mpg123 REQUIRED)
|
||||
if(NOT TARGET MPG123::libmpg123)
|
||||
find_package(mpg123 REQUIRED)
|
||||
endif()
|
||||
target_link_libraries(${EXECUTABLE} PRIVATE
|
||||
MPG123::libmpg123
|
||||
)
|
||||
@@ -220,10 +234,120 @@ set_target_properties(${EXECUTABLE}
|
||||
CXX_STANDARD_REQUIRED ON
|
||||
)
|
||||
|
||||
if(APPLE AND NOT ANDROID)
|
||||
set(${PROJECT}_MACOS_ICON "${PROJECT_SOURCE_DIR}/res/images/reVC.icns")
|
||||
set(${PROJECT}_MACOS_NOTICES "${PROJECT_SOURCE_DIR}/res/macos/ThirdPartyNotices.txt")
|
||||
target_sources(${EXECUTABLE} PRIVATE
|
||||
"${${PROJECT}_MACOS_ICON}"
|
||||
"${${PROJECT}_MACOS_NOTICES}"
|
||||
)
|
||||
set_source_files_properties(
|
||||
"${${PROJECT}_MACOS_ICON}"
|
||||
"${${PROJECT}_MACOS_NOTICES}"
|
||||
PROPERTIES
|
||||
MACOSX_PACKAGE_LOCATION "Resources"
|
||||
)
|
||||
set_target_properties(${EXECUTABLE} PROPERTIES
|
||||
MACOSX_BUNDLE TRUE
|
||||
MACOSX_BUNDLE_INFO_PLIST "${PROJECT_SOURCE_DIR}/res/macos/Info.plist"
|
||||
BUILD_WITH_INSTALL_RPATH TRUE
|
||||
INSTALL_RPATH "@executable_path/../Frameworks"
|
||||
INSTALL_RPATH_USE_LINK_PATH FALSE
|
||||
XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "io.github.mrxenginner.reVC"
|
||||
XCODE_ATTRIBUTE_CODE_SIGN_STYLE "$<$<CONFIG:Release>:Automatic>"
|
||||
XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "$<$<CONFIG:Release>:Apple Development>"
|
||||
"XCODE_ATTRIBUTE_ENABLE_HARDENED_RUNTIME[sdk=macosx*]" "$<IF:$<CONFIG:Debug>,NO,YES>"
|
||||
"XCODE_ATTRIBUTE_INSTALL_PATH[sdk=macosx*]" "$(LOCAL_APPS_DIR)"
|
||||
XCODE_ATTRIBUTE_SKIP_INSTALL "NO"
|
||||
)
|
||||
add_custom_command(TARGET ${EXECUTABLE} POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${PROJECT_SOURCE_DIR}/LICENSE.md"
|
||||
"$<TARGET_BUNDLE_CONTENT_DIR:${EXECUTABLE}>/Resources/LICENSE"
|
||||
COMMAND ${CMAKE_COMMAND} -E remove_directory
|
||||
"$<TARGET_BUNDLE_CONTENT_DIR:${EXECUTABLE}>/Resources/gamefiles"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||
"${PROJECT_SOURCE_DIR}/gamefiles"
|
||||
"$<TARGET_BUNDLE_CONTENT_DIR:${EXECUTABLE}>/Resources/gamefiles"
|
||||
COMMENT "Copying gamefiles into the app bundle"
|
||||
)
|
||||
|
||||
set(macos_dependency_dylibs_available TRUE)
|
||||
foreach(dependency IN LISTS ${PROJECT}_MACOS_DEPENDENCIES)
|
||||
if(NOT DEFINED ${PROJECT}_MACOS_${dependency}_DYLIBS)
|
||||
set(macos_dependency_dylibs_available FALSE)
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
if(macos_dependency_dylibs_available)
|
||||
set(shell_dollar "$")
|
||||
set(codesign_command
|
||||
"identity=${shell_dollar}EXPANDED_CODE_SIGN_IDENTITY; test -n \"${shell_dollar}identity\" || identity=-; /usr/bin/codesign --force --sign \"${shell_dollar}identity\" \"${shell_dollar}1\""
|
||||
)
|
||||
set(app_codesign_command
|
||||
"identity=${shell_dollar}EXPANDED_CODE_SIGN_IDENTITY; test -n \"${shell_dollar}identity\" || identity=-; if test \"${shell_dollar}2\" = YES; then /usr/bin/codesign --force --sign \"${shell_dollar}identity\" --options runtime \"${shell_dollar}1\"; else /usr/bin/codesign --force --sign \"${shell_dollar}identity\" \"${shell_dollar}1\"; fi"
|
||||
)
|
||||
if(CMAKE_GENERATOR STREQUAL "Xcode")
|
||||
set(app_hardened "$<IF:$<CONFIG:Debug>,NO,YES>")
|
||||
else()
|
||||
set(app_hardened NO)
|
||||
endif()
|
||||
add_custom_command(TARGET ${EXECUTABLE} POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory
|
||||
"$<TARGET_BUNDLE_CONTENT_DIR:${EXECUTABLE}>/Frameworks"
|
||||
)
|
||||
|
||||
function(reVC_bundle_macos_dylib target filename)
|
||||
set(destination
|
||||
"$<TARGET_BUNDLE_CONTENT_DIR:${target}>/Frameworks/${filename}"
|
||||
)
|
||||
list(LENGTH ARGN source_count)
|
||||
if(source_count GREATER 1)
|
||||
add_custom_command(TARGET ${target} POST_BUILD
|
||||
COMMAND /usr/bin/lipo -create ${ARGN} -output "${destination}"
|
||||
)
|
||||
else()
|
||||
list(GET ARGN 0 source)
|
||||
add_custom_command(TARGET ${target} POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
"${source}" "${destination}"
|
||||
)
|
||||
endif()
|
||||
foreach(source IN LISTS ARGN)
|
||||
add_custom_command(TARGET ${target} POST_BUILD
|
||||
COMMAND install_name_tool -change
|
||||
"${source}" "@rpath/${filename}" "$<TARGET_FILE:${target}>"
|
||||
)
|
||||
endforeach()
|
||||
add_custom_command(TARGET ${target} POST_BUILD
|
||||
COMMAND /bin/sh -c
|
||||
"${codesign_command}"
|
||||
codesign "${destination}"
|
||||
VERBATIM
|
||||
)
|
||||
endfunction()
|
||||
|
||||
foreach(dependency IN LISTS ${PROJECT}_MACOS_DEPENDENCIES)
|
||||
reVC_bundle_macos_dylib(${EXECUTABLE}
|
||||
${${PROJECT}_MACOS_${dependency}_FILENAME}
|
||||
${${PROJECT}_MACOS_${dependency}_DYLIBS})
|
||||
endforeach()
|
||||
add_custom_command(TARGET ${EXECUTABLE} POST_BUILD
|
||||
COMMAND /bin/sh -c
|
||||
"${app_codesign_command}"
|
||||
codesign "$<TARGET_BUNDLE_DIR:${EXECUTABLE}>"
|
||||
"${app_hardened}"
|
||||
COMMENT "Bundling macOS dependencies"
|
||||
VERBATIM
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(${PROJECT}_INSTALL)
|
||||
install(
|
||||
TARGETS ${EXECUTABLE}
|
||||
EXPORT ${EXECUTABLE}-targets
|
||||
BUNDLE DESTINATION "."
|
||||
RUNTIME DESTINATION "."
|
||||
)
|
||||
if(MSVC)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#ifdef AUDIO_OAL
|
||||
#include <AL/al.h>
|
||||
#include "crossplatform.h"
|
||||
|
||||
#define NUM_STREAMBUFFERS 8
|
||||
|
||||
@@ -116,7 +117,7 @@ public:
|
||||
#endif
|
||||
class CStream
|
||||
{
|
||||
char m_aFilename[128];
|
||||
char m_aFilename[MAX_PATH];
|
||||
ALuint *m_pAlSources;
|
||||
ALuint (&m_alBuffers)[NUM_STREAMBUFFERS];
|
||||
|
||||
|
||||
+210
-4
@@ -3,6 +3,10 @@
|
||||
#ifdef _WIN32
|
||||
#include <direct.h>
|
||||
#endif
|
||||
#ifdef __APPLE__
|
||||
#include <mach-o/dyld.h>
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#include "common.h"
|
||||
#include "crossplatform.h"
|
||||
|
||||
@@ -61,12 +65,162 @@ void mychdir(char const *path)
|
||||
#define mychdir chdir
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
static char bundledGameFilesDir[FILEMGR_PATH_SIZE] = {'\0'};
|
||||
|
||||
static bool
|
||||
GameFileExists(const char *root, const char *name)
|
||||
{
|
||||
char path[FILEMGR_PATH_SIZE];
|
||||
int length = snprintf(path, sizeof(path), "%s%s%s", root,
|
||||
root[0] != '\0' && root[strlen(root) - 1] == '/' ? "" : "/", name);
|
||||
if(length < 0 || length >= (int)sizeof(path))
|
||||
return false;
|
||||
|
||||
FILE *file = fcaseopen(path, "rb");
|
||||
if(file == nil)
|
||||
return false;
|
||||
fclose(file);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
SetGameRoot(const char *root, char *path, size_t pathSize)
|
||||
{
|
||||
char realRoot[FILEMGR_PATH_SIZE];
|
||||
if(realpath(root, realRoot) == nil ||
|
||||
!GameFileExists(realRoot, "data/gta_vc.dat") ||
|
||||
!GameFileExists(realRoot, "models/gta3.img"))
|
||||
return false;
|
||||
|
||||
int length = snprintf(path, pathSize, "%s/", realRoot);
|
||||
return length >= 0 && length < (int)pathSize;
|
||||
}
|
||||
|
||||
static bool
|
||||
GetExecutableDir(char *path, size_t pathSize)
|
||||
{
|
||||
char executable[FILEMGR_PATH_SIZE];
|
||||
uint32 size = sizeof(executable);
|
||||
if(_NSGetExecutablePath(executable, &size) != 0)
|
||||
return false;
|
||||
|
||||
char *slash = strrchr(executable, '/');
|
||||
if(slash == nil)
|
||||
return false;
|
||||
*slash = '\0';
|
||||
|
||||
char realPath[FILEMGR_PATH_SIZE];
|
||||
const char *dir = realpath(executable, realPath) == nil ? executable : realPath;
|
||||
int length = snprintf(path, pathSize, "%s", dir);
|
||||
return length >= 0 && length < (int)pathSize;
|
||||
}
|
||||
|
||||
static bool
|
||||
FindBundledGameFiles(char *path, size_t pathSize)
|
||||
{
|
||||
char executableDir[FILEMGR_PATH_SIZE];
|
||||
if(!GetExecutableDir(executableDir, sizeof(executableDir)))
|
||||
return false;
|
||||
|
||||
char bundleDir[FILEMGR_PATH_SIZE];
|
||||
int length = snprintf(bundleDir, sizeof(bundleDir),
|
||||
"%s/../Resources/gamefiles", executableDir);
|
||||
if(length < 0 || length >= (int)sizeof(bundleDir))
|
||||
return false;
|
||||
|
||||
char realBundleDir[FILEMGR_PATH_SIZE];
|
||||
struct stat status;
|
||||
if(realpath(bundleDir, realBundleDir) == nil ||
|
||||
stat(realBundleDir, &status) != 0 || !S_ISDIR(status.st_mode))
|
||||
return false;
|
||||
|
||||
length = snprintf(path, pathSize, "%s", realBundleDir);
|
||||
return length >= 0 && length < (int)pathSize;
|
||||
}
|
||||
|
||||
static bool
|
||||
ReadGameRoot(char *path, size_t pathSize)
|
||||
{
|
||||
char root[FILEMGR_PATH_SIZE];
|
||||
if(!ReadGamePathFromINI(root, sizeof(root)))
|
||||
return false;
|
||||
return SetGameRoot(root, path, pathSize);
|
||||
}
|
||||
|
||||
static void
|
||||
WriteGameRoot(const char *root)
|
||||
{
|
||||
WriteGamePathToINI(root);
|
||||
}
|
||||
|
||||
static bool
|
||||
ChooseGameRoot(char *path, size_t pathSize)
|
||||
{
|
||||
bool retry = false;
|
||||
for(;;){
|
||||
const char *prompt = retry ?
|
||||
"That folder is not a GTA Vice City installation. Choose the folder containing the data and models folders." :
|
||||
"Choose the GTA Vice City installation folder.";
|
||||
char command[512];
|
||||
snprintf(command, sizeof(command),
|
||||
"/usr/bin/osascript -e 'POSIX path of (choose folder with prompt \"%s\")' 2>/dev/null", prompt);
|
||||
|
||||
FILE *pipe = popen(command, "r");
|
||||
if(pipe == nil)
|
||||
return false;
|
||||
|
||||
char root[FILEMGR_PATH_SIZE];
|
||||
bool found = fgets(root, sizeof(root), pipe) != nil;
|
||||
int status = pclose(pipe);
|
||||
if(!found || status != 0)
|
||||
return false;
|
||||
|
||||
root[strcspn(root, "\r\n")] = '\0';
|
||||
if(SetGameRoot(root, path, pathSize)){
|
||||
WriteGameRoot(path);
|
||||
return true;
|
||||
}
|
||||
retry = true;
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
FindGameRoot(char *path, size_t pathSize)
|
||||
{
|
||||
char executableDir[FILEMGR_PATH_SIZE];
|
||||
if(GetExecutableDir(executableDir, sizeof(executableDir))){
|
||||
if(SetGameRoot(executableDir, path, pathSize))
|
||||
return true;
|
||||
|
||||
char defaultRoot[FILEMGR_PATH_SIZE];
|
||||
int length = snprintf(defaultRoot, sizeof(defaultRoot), "%s/../../..", executableDir);
|
||||
if(length >= 0 && length < (int)sizeof(defaultRoot) &&
|
||||
SetGameRoot(defaultRoot, path, pathSize))
|
||||
return true;
|
||||
}
|
||||
|
||||
char cwd[FILEMGR_PATH_SIZE];
|
||||
if(_getcwd(cwd, sizeof(cwd)) != nil && SetGameRoot(cwd, path, pathSize))
|
||||
return true;
|
||||
|
||||
return ReadGameRoot(path, pathSize) || ChooseGameRoot(path, pathSize);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Force file to open as binary but remember if it was text mode */
|
||||
static int
|
||||
myfopen(const char *filename, const char *mode)
|
||||
{
|
||||
int fd;
|
||||
char realmode[10], *p;
|
||||
const char *openPath = filename;
|
||||
#ifdef __APPLE__
|
||||
char bundledPath[FILEMGR_PATH_SIZE];
|
||||
if(mode[0] == 'r' && strchr(mode, '+') == nil &&
|
||||
CFileMgr::ResolveBundledGameFile(filename, bundledPath, sizeof(bundledPath)))
|
||||
openPath = bundledPath;
|
||||
#endif
|
||||
|
||||
for(fd = 1; fd < NUMFILES; fd++)
|
||||
if(myfiles[fd].file == nil)
|
||||
@@ -83,7 +237,7 @@ found:
|
||||
*p++ = 'b';
|
||||
*p = '\0';
|
||||
|
||||
myfiles[fd].file = fcaseopen(filename, realmode);
|
||||
myfiles[fd].file = fcaseopen(openPath, realmode);
|
||||
if(myfiles[fd].file == nil)
|
||||
return 0;
|
||||
return fd;
|
||||
@@ -206,8 +360,8 @@ myfeof(int fd)
|
||||
}
|
||||
|
||||
|
||||
char CFileMgr::ms_rootDirName[128] = {'\0'};
|
||||
char CFileMgr::ms_dirName[128];
|
||||
char CFileMgr::ms_rootDirName[FILEMGR_PATH_SIZE] = {'\0'};
|
||||
char CFileMgr::ms_dirName[FILEMGR_PATH_SIZE];
|
||||
|
||||
void
|
||||
CFileMgr::Initialise(void)
|
||||
@@ -218,12 +372,64 @@ CFileMgr::Initialise(void)
|
||||
strcat(ms_rootDirName, "/");
|
||||
debug("Android: Root Dir: %s\n", ms_rootDirName);
|
||||
}
|
||||
#elif defined(__APPLE__)
|
||||
FindBundledGameFiles(bundledGameFilesDir, sizeof(bundledGameFilesDir));
|
||||
if(ms_rootDirName[0] == '\0' && !FindGameRoot(ms_rootDirName, sizeof(ms_rootDirName)))
|
||||
_exit(0);
|
||||
strcpy(ms_dirName, ms_rootDirName);
|
||||
mychdir(ms_rootDirName);
|
||||
#else
|
||||
_getcwd(ms_rootDirName, 128);
|
||||
_getcwd(ms_rootDirName, sizeof(ms_rootDirName));
|
||||
strcat(ms_rootDirName, "\\");
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
CFileMgr::ResolveBundledGameFile(const char *file, char *path, size_t pathSize)
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
const char *rootDir = CFileMgr::GetRootDirName();
|
||||
if(bundledGameFilesDir[0] == '\0' || rootDir[0] == '\0' ||
|
||||
file[0] == '\0' || file[0] == '/' || file[0] == '\\')
|
||||
return false;
|
||||
|
||||
char cwd[FILEMGR_PATH_SIZE];
|
||||
if(_getcwd(cwd, sizeof(cwd)) == nil)
|
||||
return false;
|
||||
|
||||
size_t rootLength = strlen(rootDir);
|
||||
while(rootLength > 0 && rootDir[rootLength - 1] == '/')
|
||||
rootLength--;
|
||||
if(strncmp(cwd, rootDir, rootLength) != 0 ||
|
||||
(cwd[rootLength] != '\0' && cwd[rootLength] != '/'))
|
||||
return false;
|
||||
|
||||
char candidate[FILEMGR_PATH_SIZE];
|
||||
int length = snprintf(candidate, sizeof(candidate), "%s%s/%s",
|
||||
bundledGameFilesDir, cwd + rootLength, file);
|
||||
if(length < 0 || length >= (int)sizeof(candidate))
|
||||
return false;
|
||||
|
||||
char *realPath = casepath(candidate);
|
||||
const char *resolvedPath = realPath == nil ? candidate : realPath;
|
||||
FILE *bundleFile = fopen(resolvedPath, "rb");
|
||||
if(bundleFile == nil){
|
||||
free(realPath);
|
||||
return false;
|
||||
}
|
||||
fclose(bundleFile);
|
||||
|
||||
length = snprintf(path, pathSize, "%s", resolvedPath);
|
||||
free(realPath);
|
||||
return length >= 0 && length < (int)pathSize;
|
||||
#else
|
||||
(void)file;
|
||||
(void)path;
|
||||
(void)pathSize;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
CFileMgr::ChangeDir(const char *dir)
|
||||
{
|
||||
|
||||
+10
-2
@@ -1,10 +1,12 @@
|
||||
#ifndef __GTA_FILEMGR_H__
|
||||
#define __GTA_FILEMGR_H__
|
||||
|
||||
#define FILEMGR_PATH_SIZE 1024
|
||||
|
||||
class CFileMgr
|
||||
{
|
||||
static char ms_rootDirName[128];
|
||||
static char ms_dirName[128];
|
||||
static char ms_rootDirName[FILEMGR_PATH_SIZE];
|
||||
static char ms_dirName[FILEMGR_PATH_SIZE];
|
||||
public:
|
||||
static void Initialise(void);
|
||||
static void ChangeDir(const char *dir);
|
||||
@@ -20,7 +22,13 @@ public:
|
||||
static bool ReadLine(int fd, char *buf, int len);
|
||||
static int CloseFile(int fd);
|
||||
static int GetErrorReadWrite(int fd);
|
||||
static bool ResolveBundledGameFile(const char *file, char *path, size_t pathSize);
|
||||
static char *GetRootDirName() { return ms_rootDirName; }
|
||||
};
|
||||
|
||||
#ifdef __APPLE__
|
||||
bool ReadGamePathFromINI(char *path, size_t pathSize);
|
||||
void WriteGamePathToINI(const char *path);
|
||||
#endif
|
||||
|
||||
#endif // __GTA_FILEMGR_H__
|
||||
|
||||
+2
-14
@@ -627,19 +627,8 @@ void
|
||||
CMenuManager::CentreMousePointer()
|
||||
{
|
||||
if (SCREEN_WIDTH * 0.5f != 0.0f && 0.0f != SCREEN_HEIGHT * 0.5f) {
|
||||
#if defined RW_D3D9 || defined RWLIBS
|
||||
tagPOINT Point;
|
||||
Point.x = SCREEN_WIDTH / 2;
|
||||
Point.y = SCREEN_HEIGHT / 2;
|
||||
ClientToScreen(PSGLOBAL(window), &Point);
|
||||
SetCursorPos(Point.x, Point.y);
|
||||
#elif defined RW_GL3 && !defined(LIBRW_SDL2)
|
||||
glfwSetCursorPos(PSGLOBAL(window), SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2);
|
||||
#elif defined(RW_GL3) && defined(LIBRW_SDL2)
|
||||
SDL_WarpMouseInWindow(PSGLOBAL(window), SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2);
|
||||
#endif
|
||||
PSGLOBAL(lastMousePos.x) = SCREEN_WIDTH / 2;
|
||||
PSGLOBAL(lastMousePos.y) = SCREEN_HEIGHT / 2;
|
||||
RwV2d pos = { SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2 };
|
||||
RsMouseSetPos(&pos);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4866,7 +4855,6 @@ CMenuManager::ProcessUserInput(uint8 goDown, uint8 goUp, uint8 optionSelected, u
|
||||
DMAudio.Service();
|
||||
CentreMousePointer();
|
||||
m_bShowMouse = true;
|
||||
m_nCurrOption = 5; // TODO(Miami): Because selected option is resetted after res. change. We'll need to revisit that.
|
||||
m_nOptionHighlightTransitionBlend = 0;
|
||||
SaveSettings();
|
||||
}
|
||||
|
||||
@@ -191,6 +191,7 @@ void ReplaceAtomicPipeCallback();
|
||||
bool
|
||||
CGame::InitialiseRenderWare(void)
|
||||
{
|
||||
CFileMgr::SetDir("");
|
||||
ValidateVersion();
|
||||
#ifdef USE_TEXTURE_POOL
|
||||
_TexturePoolsInitialise();
|
||||
|
||||
+1
-1
@@ -332,7 +332,7 @@ DoFade(void)
|
||||
bool
|
||||
RwGrabScreen(RwCamera *camera, RwChar *filename)
|
||||
{
|
||||
char temp[255];
|
||||
char temp[FILEMGR_PATH_SIZE + 255];
|
||||
RwImage *pImage = RsGrabScreen(camera);
|
||||
bool result = true;
|
||||
|
||||
|
||||
@@ -197,9 +197,47 @@ CustomFrontendOptionsPopulate(void)
|
||||
#define MINI_CASE_SENSITIVE
|
||||
#include "ini.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
static const char *
|
||||
GetINIFilePath()
|
||||
{
|
||||
static char path[PATH_MAX];
|
||||
int length = snprintf(path, sizeof(path), "%s/reVC.ini", GetMacOSUserFilesFolder());
|
||||
return length >= 0 && length < (int)sizeof(path) ? path : "reVC.ini";
|
||||
}
|
||||
|
||||
mINI::INIFile ini(GetINIFilePath());
|
||||
#else
|
||||
mINI::INIFile ini("reVC.ini");
|
||||
#endif
|
||||
mINI::INIStructure cfg;
|
||||
|
||||
#ifdef __APPLE__
|
||||
bool
|
||||
ReadGamePathFromINI(char *path, size_t pathSize)
|
||||
{
|
||||
mINI::INIStructure settings;
|
||||
if(!ini.read(settings))
|
||||
return false;
|
||||
|
||||
mINI::INIMap<std::string> general = settings.get("General");
|
||||
if(!general.has("GamePath"))
|
||||
return false;
|
||||
|
||||
int length = snprintf(path, pathSize, "%s", general.get("GamePath").c_str());
|
||||
return length >= 0 && length < (int)pathSize;
|
||||
}
|
||||
|
||||
void
|
||||
WriteGamePathToINI(const char *path)
|
||||
{
|
||||
mINI::INIStructure settings;
|
||||
ini.read(settings);
|
||||
settings["General"]["GamePath"] = path;
|
||||
ini.write(settings);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool ReadIniIfExists(const char *cat, const char *key, uint32 *out)
|
||||
{
|
||||
mINI::INIMap<std::string> section = cfg.get(cat);
|
||||
|
||||
+6
-4
@@ -1,15 +1,13 @@
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#define WITH_D3D // not WITHD3D, so it's librw define
|
||||
#include <rwcore.h>
|
||||
#include <rpworld.h>
|
||||
#include "common.h"
|
||||
#include <rpmatfx.h>
|
||||
#include <rphanim.h>
|
||||
#include <rpskin.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#ifndef _WIN32
|
||||
#include "crossplatform.h"
|
||||
#endif
|
||||
#include "FileMgr.h"
|
||||
|
||||
using namespace rw;
|
||||
|
||||
@@ -347,6 +345,7 @@ RwStream *RwStreamOpen(RwStreamType type, RwStreamAccessType accessType, const v
|
||||
StreamMemory *mem;
|
||||
RwMemory *memargs;
|
||||
const char *mode;
|
||||
char bundledPath[FILEMGR_PATH_SIZE];
|
||||
|
||||
switch(accessType){
|
||||
case rwSTREAMREAD: mode = "rb"; break;
|
||||
@@ -358,6 +357,9 @@ RwStream *RwStreamOpen(RwStreamType type, RwStreamAccessType accessType, const v
|
||||
// oh god this is horrible. librw streams really need fixing
|
||||
switch(type){
|
||||
case rwSTREAMFILENAME:{
|
||||
if(accessType == rwSTREAMREAD &&
|
||||
CFileMgr::ResolveBundledGameFile((const char*)pData, bundledPath, sizeof(bundledPath)))
|
||||
pData = bundledPath;
|
||||
StreamFile fakefile;
|
||||
file = rwNewT(StreamFile, 1, 0);
|
||||
memcpy(file, &fakefile, sizeof(StreamFile));
|
||||
|
||||
+3
-1
@@ -19,9 +19,11 @@ C_PcSave PcSaveHelper;
|
||||
void
|
||||
C_PcSave::SetSaveDirectory(const char *path)
|
||||
{
|
||||
#if defined ANDROID
|
||||
#if defined ANDROID || defined __APPLE__
|
||||
sprintf(DefaultPCSaveFileName, "%s/%s", path, "GTAVCsf");
|
||||
#if defined ANDROID
|
||||
debug("SetSaveDirectory: %s", DefaultPCSaveFileName);
|
||||
#endif
|
||||
#else
|
||||
sprintf(DefaultPCSaveFileName, "%s\\%s", path, "GTAVCsf");
|
||||
#endif
|
||||
|
||||
@@ -2,6 +2,62 @@
|
||||
#include "crossplatform.h"
|
||||
#include "FileMgr.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <errno.h>
|
||||
#include <pwd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static bool
|
||||
CreateDirectoryTree(const char *path)
|
||||
{
|
||||
char current[PATH_MAX];
|
||||
int length = snprintf(current, sizeof(current), "%s", path);
|
||||
if(length < 0 || length >= (int)sizeof(current))
|
||||
return false;
|
||||
|
||||
for(char *separator = current + 1; *separator != '\0'; separator++){
|
||||
if(*separator != '/')
|
||||
continue;
|
||||
|
||||
*separator = '\0';
|
||||
if(mkdir(current, 0755) != 0 && errno != EEXIST){
|
||||
*separator = '/';
|
||||
return false;
|
||||
}
|
||||
*separator = '/';
|
||||
}
|
||||
|
||||
return mkdir(current, 0755) == 0 || errno == EEXIST;
|
||||
}
|
||||
|
||||
const char *
|
||||
GetMacOSUserFilesFolder()
|
||||
{
|
||||
static char path[PATH_MAX];
|
||||
const char *home = getenv("HOME");
|
||||
if(home == nil || home[0] == '\0'){
|
||||
struct passwd *user = getpwuid(getuid());
|
||||
home = user == nil ? nil : user->pw_dir;
|
||||
}
|
||||
if(home == nil || home[0] == '\0')
|
||||
return "userfiles";
|
||||
|
||||
#ifdef USE_MY_DOCUMENTS
|
||||
const char *relativePath = "Library/Application Support/Grand Theft Auto - Vice City/p_drive/Documents/GTA Vice City User Files";
|
||||
#else
|
||||
const char *relativePath = "Library/Application Support/reVC";
|
||||
#endif
|
||||
int length = snprintf(path, sizeof(path), "%s/%s", home, relativePath);
|
||||
if(length < 0 || length >= (int)sizeof(path))
|
||||
return "userfiles";
|
||||
|
||||
if(!CreateDirectoryTree(path))
|
||||
debug("Couldn't create macOS user files directory: %s\n", path);
|
||||
return path;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Codes compatible with Windows and Linux
|
||||
#ifndef _WIN32
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
#ifndef __GTA_CROSSPLATFORM_H__
|
||||
#define __GTA_CROSSPLATFORM_H__
|
||||
|
||||
#ifndef GTA_PS2
|
||||
|
||||
#include <time.h>
|
||||
@@ -110,6 +113,10 @@ extern RwUInt32 gGameState;
|
||||
|
||||
RwBool IsForegroundApp();
|
||||
|
||||
#ifdef __APPLE__
|
||||
const char *GetMacOSUserFilesFolder();
|
||||
#endif
|
||||
|
||||
#ifndef MAX_PATH
|
||||
#if !defined _WIN32 || defined __MINGW32__
|
||||
#define MAX_PATH PATH_MAX
|
||||
@@ -199,3 +206,5 @@ void GetDateFormat(int, int, SYSTEMTIME*, int, char*, int);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif // __GTA_CROSSPLATFORM_H__
|
||||
|
||||
+75
-20
@@ -78,6 +78,7 @@ static RwBool RwInitialised = FALSE;
|
||||
static RwSubSystemInfo GsubSysInfo[MAX_SUBSYSTEMS];
|
||||
static RwInt32 GnumSubSystems = 0;
|
||||
static RwInt32 GcurSel = 0, GcurSelVM = 0;
|
||||
static RwInt32 desktopWidth = 0, desktopHeight = 0;
|
||||
|
||||
static RwBool useDefault;
|
||||
|
||||
@@ -167,6 +168,8 @@ const char *_psGetUserFilesFolder()
|
||||
|
||||
strcpy(szUserFiles, "data");
|
||||
return szUserFiles;
|
||||
#elif defined __APPLE__
|
||||
return GetMacOSUserFilesFolder();
|
||||
#else
|
||||
static char szUserFiles[256];
|
||||
strcpy(szUserFiles, "userfiles");
|
||||
@@ -276,7 +279,19 @@ psTimer(void)
|
||||
void
|
||||
psMouseSetPos(RwV2d *pos)
|
||||
{
|
||||
glfwSetCursorPos(PSGLOBAL(window), pos->x, pos->y);
|
||||
int winw, winh;
|
||||
glfwGetWindowSize(PSGLOBAL(window), &winw, &winh);
|
||||
glfwSetCursorPos(PSGLOBAL(window),
|
||||
pos->x * (double)winw / RsGlobal.maximumWidth,
|
||||
pos->y * (double)winh / RsGlobal.maximumHeight);
|
||||
FrontEndMenuManager.m_nMouseTempPosX = pos->x;
|
||||
FrontEndMenuManager.m_nMouseTempPosY = pos->y;
|
||||
FrontEndMenuManager.m_nMousePosX = pos->x;
|
||||
FrontEndMenuManager.m_nMousePosY = pos->y;
|
||||
FrontEndMenuManager.m_nMouseOldPosX = pos->x;
|
||||
FrontEndMenuManager.m_nMouseOldPosY = pos->y;
|
||||
if (glfwGetWindowAttrib(PSGLOBAL(window), GLFW_FOCUSED))
|
||||
PSGLOBAL(cursorIsInWindow) = true;
|
||||
|
||||
PSGLOBAL(lastMousePos.x) = (RwInt32)pos->x;
|
||||
|
||||
@@ -746,6 +761,11 @@ psSelectDevice()
|
||||
RwInt32 subSysNum;
|
||||
RwInt32 AutoRenderer = 0;
|
||||
|
||||
const GLFWvidmode *desktopMode = glfwGetVideoMode(glfwGetPrimaryMonitor());
|
||||
if (desktopMode) {
|
||||
desktopWidth = desktopMode->width;
|
||||
desktopHeight = desktopMode->height;
|
||||
}
|
||||
|
||||
RwBool modeFound = FALSE;
|
||||
|
||||
@@ -834,16 +854,16 @@ psSelectDevice()
|
||||
if(FrontEndMenuManager.m_nPrefsWidth == 0 ||
|
||||
FrontEndMenuManager.m_nPrefsHeight == 0 ||
|
||||
FrontEndMenuManager.m_nPrefsDepth == 0){
|
||||
// Defaults if nothing specified
|
||||
const GLFWvidmode *mode = glfwGetVideoMode(glfwGetPrimaryMonitor());
|
||||
FrontEndMenuManager.m_nPrefsWidth = mode->width;
|
||||
FrontEndMenuManager.m_nPrefsHeight = mode->height;
|
||||
FrontEndMenuManager.m_nPrefsDepth = 32;
|
||||
FrontEndMenuManager.m_nPrefsWindowed = 0;
|
||||
}
|
||||
|
||||
// Find the videomode that best fits what we got from the settings file
|
||||
bestWndMode = -1;
|
||||
RwInt32 bestFsMode = -1;
|
||||
RwInt32 firstFsMode = -1;
|
||||
RwInt32 bestWidth = -1;
|
||||
RwInt32 bestHeight = -1;
|
||||
RwInt32 bestDepth = -1;
|
||||
@@ -853,6 +873,8 @@ psSelectDevice()
|
||||
if (!(vm.flags & rwVIDEOMODEEXCLUSIVE)){
|
||||
bestWndMode = GcurSelVM;
|
||||
} else {
|
||||
if(firstFsMode < 0)
|
||||
firstFsMode = GcurSelVM;
|
||||
// try the largest one that isn't larger than what we wanted
|
||||
if(vm.width >= bestWidth && vm.width <= FrontEndMenuManager.m_nPrefsWidth &&
|
||||
vm.height >= bestHeight && vm.height <= FrontEndMenuManager.m_nPrefsHeight &&
|
||||
@@ -865,32 +887,46 @@ psSelectDevice()
|
||||
}
|
||||
}
|
||||
|
||||
if(bestFsMode < 0){
|
||||
RwInt32 selectedFsMode = bestFsMode >= 0 ? bestFsMode : firstFsMode;
|
||||
GcurSelVM = selectedFsMode;
|
||||
if(GcurSelVM < 0 && FrontEndMenuManager.m_nPrefsWindowed)
|
||||
GcurSelVM = bestWndMode;
|
||||
if(GcurSelVM < 0){
|
||||
printf("WARNING: Cannot find desired video mode, selecting device cancelled\n");
|
||||
return FALSE;
|
||||
}
|
||||
GcurSelVM = bestFsMode;
|
||||
|
||||
FrontEndMenuManager.m_nDisplayVideoMode = GcurSelVM;
|
||||
if(selectedFsMode >= 0){
|
||||
FrontEndMenuManager.m_nDisplayVideoMode = selectedFsMode;
|
||||
FrontEndMenuManager.m_nPrefsVideoMode = FrontEndMenuManager.m_nDisplayVideoMode;
|
||||
}
|
||||
|
||||
FrontEndMenuManager.m_nSelectedScreenMode = FrontEndMenuManager.m_nPrefsWindowed;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef IMPROVED_VIDEOMODE
|
||||
if (FrontEndMenuManager.m_nPrefsWindowed && bestWndMode < 0){
|
||||
printf("WARNING: Cannot find windowed video mode, selecting device cancelled\n");
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
RwEngineGetVideoModeInfo(&vm, GcurSelVM);
|
||||
|
||||
#ifdef IMPROVED_VIDEOMODE
|
||||
if (FrontEndMenuManager.m_nPrefsWindowed)
|
||||
GcurSelVM = bestWndMode;
|
||||
|
||||
// Now GcurSelVM is 0 but vm has sizes(and fullscreen flag) of the video mode we want, that's why we changed the rwVIDEOMODEEXCLUSIVE conditions below
|
||||
if ((!FrontEndMenuManager.m_nPrefsWindowed || (vm.flags & rwVIDEOMODEEXCLUSIVE)) &&
|
||||
vm.width > 0 && vm.height > 0 && vm.depth > 0) {
|
||||
FrontEndMenuManager.m_nPrefsWidth = vm.width;
|
||||
FrontEndMenuManager.m_nPrefsHeight = vm.height;
|
||||
FrontEndMenuManager.m_nPrefsDepth = vm.depth;
|
||||
}
|
||||
if (FrontEndMenuManager.m_nPrefsWindowed)
|
||||
GcurSelVM = bestWndMode;
|
||||
#endif
|
||||
|
||||
#ifndef PS2_MENU
|
||||
if (!useDefault)
|
||||
FrontEndMenuManager.m_nCurrOption = 0;
|
||||
#endif
|
||||
|
||||
@@ -975,8 +1011,11 @@ void _InputInitialiseJoys()
|
||||
PSGLOBAL(joy2id) = -1;
|
||||
|
||||
// Load our gamepad mappings.
|
||||
#define SDL_GAMEPAD_DB_PATH "gamecontrollerdb.txt"
|
||||
FILE *f = fopen(SDL_GAMEPAD_DB_PATH, "rb");
|
||||
char bundledPath[FILEMGR_PATH_SIZE];
|
||||
const char *gamepadDbPath = CFileMgr::ResolveBundledGameFile(
|
||||
"gamecontrollerdb.txt", bundledPath, sizeof(bundledPath)) ?
|
||||
bundledPath : "gamecontrollerdb.txt";
|
||||
FILE *f = fcaseopen(gamepadDbPath, "rb");
|
||||
if (f) {
|
||||
fseek(f, 0, SEEK_END);
|
||||
size_t fsize = ftell(f);
|
||||
@@ -987,16 +1026,14 @@ void _InputInitialiseJoys()
|
||||
db[fsize] = '\0';
|
||||
|
||||
if (glfwUpdateGamepadMappings(db) == GLFW_FALSE)
|
||||
Error("glfwUpdateGamepadMappings didn't succeed, check " SDL_GAMEPAD_DB_PATH ".\n");
|
||||
Error("glfwUpdateGamepadMappings didn't succeed, check %s.\n", gamepadDbPath);
|
||||
} else
|
||||
Error("fread on " SDL_GAMEPAD_DB_PATH " wasn't successful.\n");
|
||||
Error("fread on %s wasn't successful.\n", gamepadDbPath);
|
||||
|
||||
free(db);
|
||||
fclose(f);
|
||||
} else
|
||||
printf("You don't seem to have copied " SDL_GAMEPAD_DB_PATH " file from reVC/gamefiles to GTA: Vice City directory. Some gamepads may not be recognized.\n");
|
||||
|
||||
#undef SDL_GAMEPAD_DB_PATH
|
||||
printf("You don't seem to have copied %s file from reVC/gamefiles to GTA: Vice City directory. Some gamepads may not be recognized.\n", gamepadDbPath);
|
||||
|
||||
// But always overwrite it with the one in SDL_GAMECONTROLLERCONFIG.
|
||||
char const* EnvControlConfig = getenv("SDL_GAMECONTROLLERCONFIG");
|
||||
@@ -1031,12 +1068,22 @@ long _InputInitialiseMouse(bool exclusive)
|
||||
// Disabled = keep cursor centered and hide
|
||||
lastCursorMode = exclusive ? GLFW_CURSOR_DISABLED : GLFW_CURSOR_HIDDEN;
|
||||
glfwSetInputMode(PSGLOBAL(window), GLFW_CURSOR, lastCursorMode);
|
||||
if (exclusive && glfwGetWindowAttrib(PSGLOBAL(window), GLFW_FOCUSED))
|
||||
PSGLOBAL(cursorIsInWindow) = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void _InputShutdownMouse()
|
||||
{
|
||||
// Not needed
|
||||
lastCursorMode = GLFW_CURSOR_NORMAL;
|
||||
glfwSetInputMode(PSGLOBAL(window), GLFW_CURSOR, lastCursorMode);
|
||||
}
|
||||
|
||||
static void
|
||||
centreMouseForDesktop()
|
||||
{
|
||||
if (desktopWidth > 0 && desktopHeight > 0)
|
||||
glfwSetCursorPos(PSGLOBAL(window), desktopWidth * 0.5, desktopHeight * 0.5);
|
||||
}
|
||||
|
||||
// Not "needs exclusive" on GLFW, but more like "needs to change mode"
|
||||
@@ -1088,6 +1135,8 @@ RwBool _psSetVideoMode(RwInt32 subSystem, RwInt32 videoMode)
|
||||
{
|
||||
RwInitialised = FALSE;
|
||||
|
||||
_InputShutdownMouse();
|
||||
centreMouseForDesktop();
|
||||
RsEventHandler(rsRWTERMINATE, nil);
|
||||
|
||||
GcurSel = subSystem;
|
||||
@@ -1845,8 +1894,8 @@ cursorCB(GLFWwindow* window, double xpos, double ypos) {
|
||||
|
||||
int winw, winh;
|
||||
glfwGetWindowSize(PSGLOBAL(window), &winw, &winh);
|
||||
FrontEndMenuManager.m_nMouseTempPosX = xpos * (RsGlobal.maximumWidth / winw);
|
||||
FrontEndMenuManager.m_nMouseTempPosY = ypos * (RsGlobal.maximumHeight / winh);
|
||||
FrontEndMenuManager.m_nMouseTempPosX = xpos * ((double)RsGlobal.maximumWidth / winw);
|
||||
FrontEndMenuManager.m_nMouseTempPosY = ypos * ((double)RsGlobal.maximumHeight / winh);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1857,6 +1906,10 @@ cursorEnterCB(GLFWwindow* window, int entered) {
|
||||
void
|
||||
windowFocusCB(GLFWwindow* window, int focused) {
|
||||
WindowFocused = !!focused;
|
||||
if (!focused)
|
||||
PSGLOBAL(cursorIsInWindow) = false;
|
||||
else if (lastCursorMode == GLFW_CURSOR_DISABLED || glfwGetWindowAttrib(window, GLFW_HOVERED))
|
||||
PSGLOBAL(cursorIsInWindow) = true;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -2445,6 +2498,8 @@ main(int argc, char *argv[])
|
||||
/*
|
||||
* Tidy up the 3D (RenderWare) components of the application...
|
||||
*/
|
||||
_InputShutdownMouse();
|
||||
centreMouseForDesktop();
|
||||
RsEventHandler(rsRWTERMINATE, nil);
|
||||
|
||||
/*
|
||||
|
||||
@@ -106,10 +106,14 @@ void _psCreateFolder(const char *path)
|
||||
*/
|
||||
const char *_psGetUserFilesFolder()
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
return GetMacOSUserFilesFolder();
|
||||
#else
|
||||
static char szUserFiles[256];
|
||||
strcpy(szUserFiles, "userfiles");
|
||||
_psCreateFolder(szUserFiles);
|
||||
return szUserFiles;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -617,6 +621,7 @@ psSelectDevice()
|
||||
#endif
|
||||
|
||||
#ifndef PS2_MENU
|
||||
if (!useDefault)
|
||||
FrontEndMenuManager.m_nCurrOption = 0;
|
||||
#endif
|
||||
|
||||
@@ -703,7 +708,10 @@ void _InputInitialiseJoys()
|
||||
char SDL_GAMEPAD_DB_PATH[MAX_PATH];
|
||||
snprintf(SDL_GAMEPAD_DB_PATH, sizeof(SDL_GAMEPAD_DB_PATH), "%s%s", pathRoot, "gamecontrollerdb.txt");
|
||||
#else
|
||||
const char* SDL_GAMEPAD_DB_PATH = "gamecontrollerdb.txt";
|
||||
char bundledPath[FILEMGR_PATH_SIZE];
|
||||
const char* SDL_GAMEPAD_DB_PATH = CFileMgr::ResolveBundledGameFile(
|
||||
"gamecontrollerdb.txt", bundledPath, sizeof(bundledPath)) ?
|
||||
bundledPath : "gamecontrollerdb.txt";
|
||||
#endif
|
||||
if (SDL_GameControllerAddMappingsFromFile(SDL_GAMEPAD_DB_PATH) <= 0) {
|
||||
debug ("You don't seem to have copied %s file from reVC/gamefiles "
|
||||
|
||||
@@ -1566,6 +1566,7 @@ psSelectDevice()
|
||||
#endif
|
||||
|
||||
#ifndef PS2_MENU
|
||||
if (!useDefault)
|
||||
FrontEndMenuManager.m_nCurrOption = 0;
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user