mirror of
https://github.com/lindbergh-loader/lindbergh-loader.git
synced 2026-09-22 22:48:03 +03:00
Merge pull request #86 from dkeruza-neo/master
libCg.so path, better folder redirection.
This commit is contained in:
@@ -1,6 +1,11 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
## [2.0.10]
|
||||
### Added
|
||||
- Config option to specify a path for the library libCg.so required for some shader compilation.
|
||||
- Improved folder patching for recompiled shaders (2Spicy, Rambo, Harly and HOD-EX).
|
||||
- Cleaned a bit of lindbergh elf.
|
||||
|
||||
## [2.0.9]
|
||||
- lindbergh elf mostly redone to make the loader work as a stand alone mode (read guide.md).
|
||||
|
||||
@@ -72,6 +72,10 @@ EMULATE_CARDREADER AUTO
|
||||
# Define the path to the eeprom.bin file
|
||||
# EEPROM_PATH eeprom.bin
|
||||
|
||||
# If set, the library libCG.so needed for 2Spicy, Harley, Rambo and HOD-Ex shader recompilation
|
||||
# will be loaded from the specifyied location. (include the name of file in the location)
|
||||
# LIBCG_PATH /my/file/location/myLibCg.so
|
||||
|
||||
# Set the GPU vendor (0 = Autodetect / 1 = NVidia / 2 = AMD / 3 = ATI(AMD-PRO) / 4 = Intel / 5 = Unknown)
|
||||
# GPU_VENDOR 0
|
||||
|
||||
|
||||
@@ -1113,6 +1113,9 @@ int readConfig(FILE *configFile, EmulatorConfig *config)
|
||||
else if (strcmp(command, "SRAM_PATH") == 0)
|
||||
strcpy(config->sramPath, getNextToken(NULL, " ", &saveptr));
|
||||
|
||||
else if (strcmp(command, "LIBCG_PATH") == 0)
|
||||
strcpy(config->libCgPath, getNextToken(NULL, " ", &saveptr));
|
||||
|
||||
else if (strcmp(command, "EMULATE_RIDEBOARD") == 0) {
|
||||
int defaultValue = config->emulateRideboard;
|
||||
config->emulateRideboard = getNextIntOrAuto(saveptr, defaultValue);
|
||||
@@ -1529,6 +1532,7 @@ int initConfig(const char* configFilePath)
|
||||
config.lindberghColour = YELLOW;
|
||||
strcpy(config.eepromPath, "eeprom.bin");
|
||||
strcpy(config.sramPath, "sram.bin");
|
||||
strcpy(config.libCgPath, "");
|
||||
strcpy(config.jvsPath, "/dev/ttyUSB0");
|
||||
strcpy(config.serial1Path, "/dev/ttyS0");
|
||||
strcpy(config.serial2Path, "/dev/ttyS1");
|
||||
|
||||
@@ -232,6 +232,7 @@ typedef struct
|
||||
int fullscreen;
|
||||
char eepromPath[MAX_PATH_LENGTH];
|
||||
char sramPath[MAX_PATH_LENGTH];
|
||||
char libCgPath[MAX_PATH_LENGTH];
|
||||
char jvsPath[MAX_PATH_LENGTH];
|
||||
char serial1Path[MAX_PATH_LENGTH];
|
||||
char serial2Path[MAX_PATH_LENGTH];
|
||||
|
||||
+284
-10
@@ -95,6 +95,12 @@ static int callback(struct dl_phdr_info *info, size_t size, void *data);
|
||||
|
||||
uint16_t basePortAddress = 0xFFFF;
|
||||
|
||||
/**
|
||||
* @brief Signal handler for SIGSEGV.
|
||||
*
|
||||
* This function handles segmentation faults (SIGSEGV) and attempts to recover
|
||||
* from certain types of memory access errors, particularly those related to I/O ports.
|
||||
*/
|
||||
/**
|
||||
* Signal handler for the SIGSEGV signal, which is triggered when a process tries to access an illegal memory location.
|
||||
* @param signal
|
||||
@@ -177,6 +183,13 @@ static void handleSegfault(int signal, siginfo_t *info, void *ptr)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Trims leading and trailing whitespace and quotes from a string.
|
||||
*
|
||||
* This function removes leading and trailing whitespace characters, as well as
|
||||
* single and double quotes, from the input string.
|
||||
* @param str The string to trim.
|
||||
*/
|
||||
char *trimOS_ID(char *str)
|
||||
{
|
||||
if (!str)
|
||||
@@ -198,6 +211,12 @@ char *trimOS_ID(char *str)
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks if the operating system is Debian-based.
|
||||
*
|
||||
* This function reads the /etc/os-release file to determine if the current
|
||||
* operating system is Debian or Ubuntu, or a derivative of them.
|
||||
*/
|
||||
bool checkOS_ID()
|
||||
{
|
||||
FILE *fp = fopen("/etc/os-release", "r");
|
||||
@@ -249,6 +268,12 @@ bool checkOS_ID()
|
||||
return found;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialization function for the hook library.
|
||||
*
|
||||
* This function is called automatically when the library is loaded. It sets up
|
||||
* signal handlers, initializes configuration, and performs other setup tasks.
|
||||
*/
|
||||
void __attribute__((constructor)) hook_init()
|
||||
{
|
||||
// Get offsets of the Game's ELF and calculate CRC32.
|
||||
@@ -277,7 +302,6 @@ void __attribute__((constructor)) hook_init()
|
||||
}
|
||||
|
||||
getGPUVendor();
|
||||
|
||||
if (initPatch() != 0)
|
||||
exit(1);
|
||||
|
||||
@@ -360,6 +384,13 @@ void __attribute__((constructor)) hook_init()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Hook for the opendir function.
|
||||
*
|
||||
* This function intercepts calls to opendir and redirects them to different
|
||||
* directories based on the game ID.
|
||||
* @param dirname The name of the directory to open.
|
||||
*/
|
||||
DIR *opendir(const char *dirname)
|
||||
{
|
||||
DIR *(*_opendir)(const char *dirname) = dlsym(RTLD_NEXT, "opendir");
|
||||
@@ -395,6 +426,13 @@ DIR *opendir(const char *dirname)
|
||||
return _opendir(dirname);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Hook for the remove function.
|
||||
*
|
||||
* This function intercepts calls to remove and redirects them to different
|
||||
* paths based on the game ID.
|
||||
* @param path The path to remove.
|
||||
*/
|
||||
int remove(const char *path)
|
||||
{
|
||||
int (*_remove)(const char *path) = dlsym(RTLD_NEXT, "remove");
|
||||
@@ -416,6 +454,13 @@ int remove(const char *path)
|
||||
return _remove(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Hook for the mkdir function.
|
||||
*
|
||||
* This function intercepts calls to mkdir and redirects them to different
|
||||
* paths based on the game ID.
|
||||
* @param path The path to create.
|
||||
*/
|
||||
int mkdir(const char *path, mode_t mode)
|
||||
{
|
||||
int (*_mkdir)(const char *path, mode_t mode) = dlsym(RTLD_NEXT, "mkdir");
|
||||
@@ -437,6 +482,13 @@ int mkdir(const char *path, mode_t mode)
|
||||
return _mkdir(path, mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Hook for the __xstat64 function.
|
||||
*
|
||||
* This function intercepts calls to __xstat64 and redirects them to different
|
||||
* paths based on the game ID.
|
||||
* @param path The path to stat.
|
||||
*/
|
||||
int __xstat64(int ver, const char *path, struct stat64 *stat_buf)
|
||||
{
|
||||
int (*___xstat64)(int ver, const char *path, struct stat64 *stat_buf) = dlsym(RTLD_NEXT, "__xstat64");
|
||||
@@ -448,6 +500,13 @@ int __xstat64(int ver, const char *path, struct stat64 *stat_buf)
|
||||
return ___xstat64(ver, path, stat_buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Hook for the open function.
|
||||
*
|
||||
* This function intercepts calls to open and redirects them to different
|
||||
* files or devices based on the pathname.
|
||||
* @param pathname The path to open.
|
||||
*/
|
||||
int open(const char *pathname, int flags, ...)
|
||||
{
|
||||
va_list args;
|
||||
@@ -534,6 +593,13 @@ int open(const char *pathname, int flags, ...)
|
||||
return _open(pathname, flags, mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Hook for the open64 function.
|
||||
*
|
||||
* This function intercepts calls to open64 and redirects them to different
|
||||
* files or devices based on the pathname.
|
||||
* @param pathname The path to open.
|
||||
*/
|
||||
int open64(const char *pathname, int flags, ...)
|
||||
{
|
||||
va_list args;
|
||||
@@ -544,6 +610,13 @@ int open64(const char *pathname, int flags, ...)
|
||||
return open(pathname, flags, mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Hook for the fopen function.
|
||||
*
|
||||
* This function intercepts calls to fopen and redirects them to different
|
||||
* files based on the pathname.
|
||||
* @param pathname The path to open.
|
||||
*/
|
||||
FILE *fopen(const char *restrict pathname, const char *restrict mode)
|
||||
{
|
||||
FILE *(*_fopen)(const char *restrict pathname, const char *restrict mode) = dlsym(RTLD_NEXT, "fopen");
|
||||
@@ -690,7 +763,6 @@ FILE *fopen(const char *restrict pathname, const char *restrict mode)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (cachedShaderFilesLoaded)
|
||||
{
|
||||
void *addr = __builtin_return_address(0);
|
||||
@@ -757,6 +829,13 @@ FILE *fopen(const char *restrict pathname, const char *restrict mode)
|
||||
return _fopen(pathname, mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Hook for the fopen64 function.
|
||||
*
|
||||
* This function intercepts calls to fopen64 and redirects them to different
|
||||
* files based on the pathname.
|
||||
* @param pathname The path to open.
|
||||
*/
|
||||
FILE *fopen64(const char *pathname, const char *mode)
|
||||
{
|
||||
FILE *(*_fopen64)(const char *restrict pathname, const char *restrict mode) = dlsym(RTLD_NEXT, "fopen64");
|
||||
@@ -857,6 +936,13 @@ FILE *fopen64(const char *pathname, const char *mode)
|
||||
return _fopen64(pathname, mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Hook for the fclose function.
|
||||
*
|
||||
* This function intercepts calls to fclose and performs cleanup operations
|
||||
* for the file hooks.
|
||||
* @param stream The file stream to close.
|
||||
*/
|
||||
int fclose(FILE *stream)
|
||||
{
|
||||
int (*_fclose)(FILE *stream) = dlsym(RTLD_NEXT, "fclose");
|
||||
@@ -878,6 +964,14 @@ int fclose(FILE *stream)
|
||||
}
|
||||
return _fclose(stream);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Hook for the openat function.
|
||||
*
|
||||
* This function intercepts calls to openat and redirects them to different
|
||||
* files or devices based on the pathname.
|
||||
* @param pathname The path to open.
|
||||
*/
|
||||
int openat(int dirfd, const char *pathname, int flags, ...)
|
||||
{
|
||||
int (*_openat)(int dirfd, const char *pathname, int flags) = dlsym(RTLD_NEXT, "openat");
|
||||
@@ -892,6 +986,13 @@ int openat(int dirfd, const char *pathname, int flags, ...)
|
||||
return _openat(dirfd, pathname, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Hook for the close function.
|
||||
*
|
||||
* This function intercepts calls to close and performs cleanup operations
|
||||
* for the file hooks.
|
||||
* @param fd The file descriptor to close.
|
||||
*/
|
||||
int close(int fd)
|
||||
{
|
||||
int (*_close)(int fd) = dlsym(RTLD_NEXT, "close");
|
||||
@@ -908,6 +1009,13 @@ int close(int fd)
|
||||
return _close(fd);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Hook for the fgets function.
|
||||
*
|
||||
* This function intercepts calls to fgets and redirects them to different
|
||||
* files based on the stream.
|
||||
* @param stream The file stream to read from.
|
||||
*/
|
||||
char *fgets(char *str, int n, FILE *stream)
|
||||
{
|
||||
char *(*_fgets)(char *str, int n, FILE *stream) = dlsym(RTLD_NEXT, "fgets");
|
||||
@@ -945,6 +1053,13 @@ char *fgets(char *str, int n, FILE *stream)
|
||||
return _fgets(str, n, stream);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Hook for the read function.
|
||||
*
|
||||
* This function intercepts calls to read and redirects them to different
|
||||
* files or devices based on the file descriptor.
|
||||
* @param fd The file descriptor to read from.
|
||||
*/
|
||||
ssize_t read(int fd, void *buf, size_t count)
|
||||
{
|
||||
int (*_read)(int fd, void *buf, size_t count) = dlsym(RTLD_NEXT, "read");
|
||||
@@ -994,6 +1109,13 @@ ssize_t read(int fd, void *buf, size_t count)
|
||||
return _read(fd, buf, count);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Hook for the fread function.
|
||||
*
|
||||
* This function intercepts calls to fread and redirects them to different
|
||||
* files based on the stream.
|
||||
* @param stream The file stream to read from.
|
||||
*/
|
||||
size_t fread(void *buf, size_t size, size_t count, FILE *stream)
|
||||
{
|
||||
size_t (*_fread)(void *buf, size_t size, size_t count, FILE *stream) = dlsym(RTLD_NEXT, "fread");
|
||||
@@ -1046,6 +1168,13 @@ size_t fread(void *buf, size_t size, size_t count, FILE *stream)
|
||||
return _fread(buf, size, count, stream);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Hook for the ftell function.
|
||||
*
|
||||
* This function intercepts calls to ftell and redirects them to different
|
||||
* files based on the stream.
|
||||
* @param stream The file stream to get the position from.
|
||||
*/
|
||||
long int ftell(FILE *stream)
|
||||
{
|
||||
long int (*_ftell)(FILE *stream) = dlsym(RTLD_NEXT, "ftell");
|
||||
@@ -1067,6 +1196,13 @@ long int ftell(FILE *stream)
|
||||
return _ftell(stream);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Hook for the fseek function.
|
||||
*
|
||||
* This function intercepts calls to fseek and redirects them to different
|
||||
* files based on the stream.
|
||||
* @param stream The file stream to seek in.
|
||||
*/
|
||||
int fseek(FILE *stream, long int offset, int whence)
|
||||
{
|
||||
int (*_fseek)(FILE *stream, long int offset, int whence) = dlsym(RTLD_NEXT, "fseek");
|
||||
@@ -1090,6 +1226,13 @@ int fseek(FILE *stream, long int offset, int whence)
|
||||
return _fseek(stream, offset, whence);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Hook for the rewind function.
|
||||
*
|
||||
* This function intercepts calls to rewind and redirects them to different
|
||||
* files based on the stream.
|
||||
* @param stream The file stream to rewind.
|
||||
*/
|
||||
void rewind(FILE *stream)
|
||||
{
|
||||
void (*_rewind)(FILE *stream) = dlsym(RTLD_NEXT, "rewind");
|
||||
@@ -1103,6 +1246,13 @@ void rewind(FILE *stream)
|
||||
_rewind(stream);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Hook for the write function.
|
||||
*
|
||||
* This function intercepts calls to write and redirects them to different
|
||||
* files or devices based on the file descriptor.
|
||||
* @param fd The file descriptor to write to.
|
||||
*/
|
||||
ssize_t write(int fd, const void *buf, size_t count)
|
||||
{
|
||||
int (*_write)(int fd, const void *buf, size_t count) = dlsym(RTLD_NEXT, "write");
|
||||
@@ -1141,6 +1291,13 @@ ssize_t write(int fd, const void *buf, size_t count)
|
||||
return _write(fd, buf, count);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Hook for the ioctl function.
|
||||
*
|
||||
* This function intercepts calls to ioctl and redirects them to different
|
||||
* devices based on the file descriptor.
|
||||
* @param fd The file descriptor to perform the ioctl on.
|
||||
*/
|
||||
int ioctl(int fd, unsigned int request, void *data)
|
||||
{
|
||||
int (*_ioctl)(int fd, int request, void *data) = dlsym(RTLD_NEXT, "ioctl");
|
||||
@@ -1170,6 +1327,13 @@ int ioctl(int fd, unsigned int request, void *data)
|
||||
return _ioctl(fd, request, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Hook for the tcgetattr function.
|
||||
*
|
||||
* This function intercepts calls to tcgetattr and redirects them to different
|
||||
* devices based on the file descriptor.
|
||||
* @param fd The file descriptor to get the attributes from.
|
||||
*/
|
||||
int tcgetattr(int fd, struct termios *termios_p)
|
||||
{
|
||||
int (*_tcgetattr)(int fd, struct termios *termios_p) = dlsym(RTLD_NEXT, "tcgetattr");
|
||||
@@ -1180,6 +1344,13 @@ int tcgetattr(int fd, struct termios *termios_p)
|
||||
return _tcgetattr(fd, termios_p);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Hook for the tcsetattr function.
|
||||
*
|
||||
* This function intercepts calls to tcsetattr and redirects them to different
|
||||
* devices based on the file descriptor.
|
||||
* @param fd The file descriptor to set the attributes on.
|
||||
*/
|
||||
int tcsetattr(int fd, int optional_actions, const struct termios *termios_p)
|
||||
{
|
||||
int (*_tcsetattr)(int fd, int optional_actions, const struct termios *termios_p) = dlsym(RTLD_NEXT, "tcsetattr");
|
||||
@@ -1190,6 +1361,13 @@ int tcsetattr(int fd, int optional_actions, const struct termios *termios_p)
|
||||
return _tcsetattr(fd, optional_actions, termios_p);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Hook for the cfgetispeed function.
|
||||
*
|
||||
* This function intercepts calls to cfgetispeed and redirects them to different
|
||||
* devices based on the file descriptor.
|
||||
* @param termios_p The termios structure to get the input speed from.
|
||||
*/
|
||||
speed_t cfgetispeed(const struct termios *termios_p)
|
||||
{
|
||||
speed_t (*_cfgetispeed)(const struct termios *termios_p) = dlsym(RTLD_NEXT, "cfgetispeed");
|
||||
@@ -1200,6 +1378,13 @@ speed_t cfgetispeed(const struct termios *termios_p)
|
||||
return _cfgetispeed(termios_p);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Hook for the cfgetospeed function.
|
||||
*
|
||||
* This function intercepts calls to cfgetospeed and redirects them to different
|
||||
* devices based on the file descriptor.
|
||||
* @param termios_p The termios structure to get the output speed from.
|
||||
*/
|
||||
speed_t cfgetospeed(const struct termios *termios_p)
|
||||
{
|
||||
speed_t (*_cfgetospeed)(const struct termios *termios_p) = dlsym(RTLD_NEXT, "cfgetospeed");
|
||||
@@ -1210,6 +1395,13 @@ speed_t cfgetospeed(const struct termios *termios_p)
|
||||
return _cfgetospeed(termios_p);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Hook for the cfsetispeed function.
|
||||
*
|
||||
* This function intercepts calls to cfsetispeed and redirects them to different
|
||||
* devices based on the file descriptor.
|
||||
* @param termios_p The termios structure to set the input speed on.
|
||||
*/
|
||||
int cfsetispeed(struct termios *termios_p, speed_t speed)
|
||||
{
|
||||
int (*_cfsetispeed)(struct termios *termios_p, speed_t speed) = dlsym(RTLD_NEXT, "cfsetispeed");
|
||||
@@ -1220,6 +1412,13 @@ int cfsetispeed(struct termios *termios_p, speed_t speed)
|
||||
return _cfsetispeed(termios_p, speed);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Hook for the cfsetospeed function.
|
||||
*
|
||||
* This function intercepts calls to cfsetospeed and redirects them to different
|
||||
* devices based on the file descriptor.
|
||||
* @param termios_p The termios structure to set the output speed on.
|
||||
*/
|
||||
int cfsetospeed(struct termios *termios_p, speed_t speed)
|
||||
{
|
||||
int (*_cfsetospeed)(struct termios *termios_p, speed_t speed) = dlsym(RTLD_NEXT, "cfsetospeed");
|
||||
@@ -1230,6 +1429,14 @@ int cfsetospeed(struct termios *termios_p, speed_t speed)
|
||||
return _cfsetospeed(termios_p, speed);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Hook for the select function.
|
||||
*
|
||||
* This function intercepts calls to select and redirects them to different
|
||||
* devices based on the file descriptor.
|
||||
* @param nfds The highest file descriptor number plus one.
|
||||
* @param readfds The file descriptors to check for readability.
|
||||
*/
|
||||
int select(int nfds, fd_set *restrict readfds, fd_set *restrict writefds, fd_set *restrict exceptfds,
|
||||
struct timeval *restrict timeout)
|
||||
{
|
||||
@@ -1254,6 +1461,13 @@ int select(int nfds, fd_set *restrict readfds, fd_set *restrict writefds, fd_set
|
||||
return _select(nfds, readfds, writefds, exceptfds, timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Hook for the system function.
|
||||
*
|
||||
* This function intercepts calls to system and redirects them to different
|
||||
* commands based on the command string.
|
||||
* @param command The command to execute.
|
||||
*/
|
||||
int system(const char *command)
|
||||
{
|
||||
int (*_system)(const char *command) = dlsym(RTLD_NEXT, "system");
|
||||
@@ -1291,6 +1505,36 @@ int system(const char *command)
|
||||
return _system(command);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Hook for the strncpy function.
|
||||
*
|
||||
* This function intercepts calls to strncpy and redirects them to different
|
||||
* strings based on the game ID.
|
||||
* @param dest The destination string.
|
||||
*/
|
||||
char *strncpy(char *dest, const char *src, size_t n)
|
||||
{
|
||||
char *(*_strncpy)(char *dest, const char *src, size_t n) = dlsym(RTLD_NEXT, "strncpy");
|
||||
|
||||
switch (gId)
|
||||
{
|
||||
case HARLEY_DAVIDSON:
|
||||
case RAMBO:
|
||||
case THE_HOUSE_OF_THE_DEAD_EX:
|
||||
case TOO_SPICY:
|
||||
if (getConfig()->GPUVendor != NVIDIA_GPU && (strstr(src, "../fs/compiledshader") != NULL || strstr(src, "../fs/compiled") != NULL))
|
||||
return _strncpy(dest, "../fs/compiledmesa", n);
|
||||
}
|
||||
return _strncpy(dest, src, n);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Hook for the iopl function.
|
||||
*
|
||||
* This function intercepts calls to iopl and always returns 0.
|
||||
* @param level The I/O privilege level to set.
|
||||
* @return Always returns 0.
|
||||
*/
|
||||
int iopl(int level)
|
||||
{
|
||||
return 0;
|
||||
@@ -1306,10 +1550,11 @@ void kswap_collect(void *p)
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook for function used by Primevil
|
||||
* @param base The number to raise to the exponent
|
||||
* @param exp The exponent to raise the number to
|
||||
* @return The result of raising the number to the exponent
|
||||
* @brief Hook for the powf function.
|
||||
*
|
||||
* This function intercepts calls to powf and redirects them to pow.
|
||||
* @param base The base number.
|
||||
* @param exponent The exponent.
|
||||
*/
|
||||
float powf(float base, float exponent)
|
||||
{
|
||||
@@ -1324,6 +1569,13 @@ int sem_wait(sem_t *sem)
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Gets the machine's IP address.
|
||||
*
|
||||
* This function retrieves the machine's IP address and stores it in the
|
||||
* provided sockaddr_in structure.
|
||||
* @param addr The sockaddr_in structure to store the IP address in.
|
||||
*/
|
||||
int get_machine_ip(struct sockaddr_in *addr)
|
||||
{
|
||||
struct ifaddrs *ifaddr, *ifa;
|
||||
@@ -1396,7 +1648,11 @@ int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback function to get the offset and size of the execution program in memory of the ELF we hook to.
|
||||
* @brief Callback function for dl_iterate_phdr.
|
||||
*
|
||||
* This function is called for each program header in the loaded shared
|
||||
* objects. It is used to calculate the CRC32 of the ELF file.
|
||||
* @param info Information about the program header.
|
||||
*/
|
||||
static int callback(struct dl_phdr_info *info, size_t size, void *data)
|
||||
{
|
||||
@@ -1408,7 +1664,11 @@ static int callback(struct dl_phdr_info *info, size_t size, void *data)
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop the game changing the DISPLAY environment variable
|
||||
* @brief Hook for the setenv function.
|
||||
*
|
||||
* This function intercepts calls to setenv and prevents the game from
|
||||
* changing the DISPLAY environment variable.
|
||||
* @param name The name of the environment variable.
|
||||
*/
|
||||
int setenv(const char *name, const char *value, int overwrite)
|
||||
{
|
||||
@@ -1423,7 +1683,10 @@ int setenv(const char *name, const char *value, int overwrite)
|
||||
}
|
||||
|
||||
/**
|
||||
* Fake the TEA_DIR environment variable to games that require it to run
|
||||
* @brief Hook for the getenv function.
|
||||
*
|
||||
* This function iFake the TEA_DIR environment variable to games that require it to run
|
||||
* @param name The name of the environment variable.
|
||||
*/
|
||||
char *getenv(const char *name)
|
||||
{
|
||||
@@ -1470,7 +1733,11 @@ char *getenv(const char *name)
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop the game unsetting the DISPLAY environment variable
|
||||
* @brief Hook for the unsetenv function.
|
||||
*
|
||||
* This function intercepts calls to unsetenv and prevents the game from
|
||||
* unsetting the DISPLAY environment variable.
|
||||
* @param name The name of the environment variable.
|
||||
*/
|
||||
int unsetenv(const char *name)
|
||||
{
|
||||
@@ -1497,6 +1764,13 @@ char *__strdup(const char *string)
|
||||
return ___strdup(string);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Hook for the localtime_r function.
|
||||
*
|
||||
* This function intercepts calls to localtime_r and redirects them to different
|
||||
* times based on the game ID.
|
||||
* @param timep The time to convert.
|
||||
*/
|
||||
struct tm *localtime_r(const time_t *timep, struct tm *result)
|
||||
{
|
||||
struct tm *(*_localtime_r)(const time_t *, struct tm *) =
|
||||
|
||||
+31
-15
@@ -19,6 +19,7 @@
|
||||
#define PRELOAD_FILE_NAME "lindbergh.so"
|
||||
#define TEAM "bobbydilley, retrofan, dkeruza-neo, doozer, francesco, rolel, caviar-x"
|
||||
#define LINDBERGH_CONFIG_PATH "LINDBERGH_CONFIG_PATH"
|
||||
#define LINDBERGH_LOADER_CURRENT_DIR "LINDBERGH_LOADER_CURRENT_DIR"
|
||||
#define MAX_PATH_LEN 1024
|
||||
|
||||
/**
|
||||
@@ -230,6 +231,19 @@ int calculateFileCRC32(const char *filename, uint32_t *crc)
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool hasSpaces(const char *str)
|
||||
{
|
||||
if (!str)
|
||||
return false;
|
||||
while (*str)
|
||||
{
|
||||
if (*str == ' ')
|
||||
return true;
|
||||
str++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks if the ELF file is clean based on its CRC32.
|
||||
*
|
||||
@@ -237,7 +251,7 @@ int calculateFileCRC32(const char *filename, uint32_t *crc)
|
||||
* against a list of known clean ELF CRC32 values.
|
||||
* @param command The command line string containing the path to the ELF file.
|
||||
*/
|
||||
void isCleanElf(char *command)
|
||||
void checkIfElfisClean(char *command)
|
||||
{
|
||||
char *last_space = strrchr(command, ' ');
|
||||
size_t length;
|
||||
@@ -511,6 +525,7 @@ void setEnvironmentVariables(char *ldLibPath, char *curDir, char *gameDir, int z
|
||||
setenv("__GLX_VENDOR_LIBRARY_NAME", "nvidia", 1);
|
||||
setenv("__NV_PRIME_RENDER_OFFLOAD", "1", 1);
|
||||
}
|
||||
setenv("LINDBERGH_LOADER_CURRENT_DIR", curDir, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -690,6 +705,12 @@ int main(int argc, char *argv[])
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (hasSpaces(curDir))
|
||||
{
|
||||
log_warn("The current path contains spaces, this most likely will cause issues.");
|
||||
log_warn("Please, make sure you don't use spaces in the path.");
|
||||
}
|
||||
|
||||
char command[PATH_MAX] = {0};
|
||||
char *forcedGameDir;
|
||||
char *forcedGameElf;
|
||||
@@ -796,26 +817,16 @@ int main(int argc, char *argv[])
|
||||
|
||||
char *ldPreloadLibrary = findLDPreloadLibrary();
|
||||
|
||||
if (strcmp(ldPreloadLibrary, PRELOAD_FILE_NAME) == 0)
|
||||
{
|
||||
char lindberghSoPath[MAX_PATH_LEN];
|
||||
if (gameDir[0] != '\0')
|
||||
snprintf(lindberghSoPath, strlen(gameDir) + sizeof(PRELOAD_FILE_NAME) + 1, "%s/%s", gameDir, PRELOAD_FILE_NAME);
|
||||
|
||||
if (access(lindberghSoPath, F_OK) != 0)
|
||||
{
|
||||
log_error("The preload object lindbergh.so was not found.");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
ldPreloadLibrary = strdup(lindberghSoPath);
|
||||
}
|
||||
if (strcmp(curDir, gameDir) == 0)
|
||||
ldPreloadLibrary = PRELOAD_FILE_NAME;
|
||||
|
||||
// Ensure environment variables are set correctly
|
||||
setEnvironmentVariables(ldPreloadLibrary, curDir, gameDir, zink, nvidia);
|
||||
|
||||
if (testMode)
|
||||
testModePath(command);
|
||||
isCleanElf(command);
|
||||
|
||||
checkIfElfisClean(command);
|
||||
|
||||
if (gdb)
|
||||
{
|
||||
@@ -827,6 +838,11 @@ int main(int argc, char *argv[])
|
||||
|
||||
if (extConfigPath != NULL && extConfigPath[0] != '\0')
|
||||
{
|
||||
if (hasSpaces(extConfigPath))
|
||||
{
|
||||
log_warn("The config path contains spaces, this most likely will cause issues.");
|
||||
log_warn("Please, make sure you don't use spaces in the path.");
|
||||
}
|
||||
setenv(LINDBERGH_CONFIG_PATH, extConfigPath, 1);
|
||||
}
|
||||
|
||||
|
||||
+4
-11
@@ -628,11 +628,9 @@ int initPatch()
|
||||
|
||||
if (GPUVendor != NVIDIA_GPU)
|
||||
{
|
||||
cacheModedShaderFiles();
|
||||
loadLibCg();
|
||||
cacheModedShaderFiles();
|
||||
cacheNnstdshader();
|
||||
patchMemory(0x082d4437, "9090909090"); // Stop the folder rename
|
||||
patchMemory(0x088a6127, "66732f636f6d70696c65646d657361"); // Change folder to compiledshdmesa
|
||||
patchMemory(0x082646b3, "01"); // Compile using CGC
|
||||
replaceCallAtAddress(0x082d48ac, compileWithCGC);
|
||||
replaceCallAtAddress(0x082d4b3b, compileWithCGC);
|
||||
@@ -2059,12 +2057,9 @@ int initPatch()
|
||||
{
|
||||
loadLibCg();
|
||||
cacheNnstdshader();
|
||||
patchMemory(0x08200c17, "9090909090"); // Stop the folder rename
|
||||
patchMemory(0x084173e7, "66732f636f6d70696c65646d657361"); // Change folder to compiledshdmesa
|
||||
patchMemory(0x080b3d71, "01"); // Compile using CGC
|
||||
replaceCallAtAddress(0x082015bf, compileWithCGC);
|
||||
replaceCallAtAddress(0x082012c1, compileWithCGC);
|
||||
// patchMemory(0x080b3d65, "00"); // Force recompile shaders
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -2487,9 +2482,8 @@ int initPatch()
|
||||
// Mesa Patches
|
||||
if (GPUVendor != NVIDIA_GPU)
|
||||
{
|
||||
patchMemory(0x08503bfa, "6d657361"); // Rename compile folder to compmesa
|
||||
cacheModedShaderFiles();
|
||||
loadLibCg();
|
||||
cacheModedShaderFiles();
|
||||
cacheNnstdshader();
|
||||
replaceCallAtAddress(0x08370aa7, compileWithCGC);
|
||||
replaceCallAtAddress(0x08370bb6, compileWithCGC);
|
||||
@@ -2550,10 +2544,9 @@ int initPatch()
|
||||
if (GPUVendor != NVIDIA_GPU)
|
||||
{
|
||||
loadLibCg();
|
||||
cacheNnstdshader();
|
||||
patchMemory(0x081ef9d8, "01"); // Force the game to recompile the shaders using cgc
|
||||
patchMemory(0x08413f04, "646d657361"); // Changes compiledshader folder to compiledshdmesa
|
||||
cacheModedShaderFiles();
|
||||
cacheNnstdshader();
|
||||
patchMemory(0x081ef9d8, "01"); // Force the game to recompile the shaders using cgc
|
||||
replaceCallAtAddress(0x08259fe5, compileWithCGC);
|
||||
replaceCallAtAddress(0x0825a089, compileWithCGC);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef __i386__
|
||||
#define __i386__
|
||||
|
||||
#include "log.h"
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#undef __x86_64__
|
||||
@@ -22,6 +23,7 @@
|
||||
#include "../libxdiff/xdiff/xdiff.h"
|
||||
#include "config.h"
|
||||
#include "patch.h"
|
||||
#include "log.h"
|
||||
|
||||
#include "shader_work/2spicy.h"
|
||||
#include "shader_work/abc.h"
|
||||
@@ -1541,41 +1543,99 @@ int parseCgcArgs(const char *input, const char ***compilerArgs, const char **out
|
||||
return 0;
|
||||
}
|
||||
|
||||
void loadLibCg()
|
||||
char *findLibCg()
|
||||
{
|
||||
int isFlatpak = 0;
|
||||
void *handle = dlopen("./libCg.so", RTLD_NOW);
|
||||
if (!handle)
|
||||
const char *foundPath = NULL;
|
||||
FILE *libCgF = NULL;
|
||||
|
||||
char *pathsToCheck[] = {NULL, "/app/lib32/libCg2.so", "./libCg.so", NULL};
|
||||
|
||||
if (strcmp(getConfig()->libCgPath, "") != 0)
|
||||
{
|
||||
handle = dlopen("/app/lib32/libCg2.so", RTLD_NOW);
|
||||
if (!handle)
|
||||
pathsToCheck[0] = getConfig()->libCgPath;
|
||||
}
|
||||
|
||||
const char *currentDir = getenv("LINDBERGH_LOADER_CURRENT_DIR");
|
||||
if (currentDir != NULL)
|
||||
{
|
||||
size_t pathLen = strlen(currentDir) + strlen("/libCg.so") + 1;
|
||||
pathsToCheck[3] = malloc(pathLen);
|
||||
if (pathsToCheck[3] != NULL)
|
||||
{
|
||||
fprintf(stderr, "Error: Unable to load library libCg.so %s\n", dlerror());
|
||||
fprintf(stderr, "Error: libCg.so version 2.0 is needed to compile the shaders in the game's folder.\n");
|
||||
exit(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
isFlatpak = 1;
|
||||
snprintf(pathsToCheck[3], pathLen, "%s/%s", currentDir, "libCg.so");
|
||||
}
|
||||
}
|
||||
|
||||
char libCgVersion[9];
|
||||
FILE *libF;
|
||||
if (isFlatpak)
|
||||
libF = fopen("/app/lib32/libCg2.so", "r");
|
||||
else
|
||||
libF = fopen("./libCg.so", "r");
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
if (pathsToCheck[i] == NULL)
|
||||
continue;
|
||||
|
||||
fseek(libF, 0x226d84, SEEK_SET);
|
||||
fread(libCgVersion, 9, 1, libF);
|
||||
fclose(libF);
|
||||
if (access(pathsToCheck[i], F_OK) == 0)
|
||||
{
|
||||
foundPath = pathsToCheck[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (foundPath != pathsToCheck[3] && pathsToCheck[3] != NULL)
|
||||
{
|
||||
free(pathsToCheck[3]);
|
||||
}
|
||||
|
||||
if (foundPath == NULL)
|
||||
{
|
||||
log_error("Error: Unable to find library libCg.so\n");
|
||||
log_error("Error: libCg.so version 2.0 is needed to compile the shaders in the game's folder.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
char libCgVersion[9] = {0};
|
||||
libCgF = fopen(foundPath, "rb");
|
||||
if (libCgF == NULL)
|
||||
{
|
||||
log_error("Failed to open: %s\n", foundPath);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
fseek(libCgF, 0x226d84L, SEEK_SET);
|
||||
if (fread(libCgVersion, 1, sizeof(libCgVersion) - 1, libCgF) != sizeof(libCgVersion) - 1)
|
||||
{
|
||||
log_error("Failed to read version from: %s\n", foundPath);
|
||||
fclose(libCgF);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
fclose(libCgF);
|
||||
|
||||
if (strcmp(libCgVersion, "2.0.0.12") != 0)
|
||||
{
|
||||
printf("ERROR: Wrong libCg.so, version 2.0.0.12 is needed.\n");
|
||||
exit(1);
|
||||
log_error("ERROR: Wrong libCg.so version '%s', version 2.0.0.12 is needed.\n", libCgVersion);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
char *resultPath = strdup(foundPath);
|
||||
if (resultPath == NULL)
|
||||
{
|
||||
log_error("Error allocating memory for result path");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return resultPath;
|
||||
}
|
||||
|
||||
void loadLibCg()
|
||||
{
|
||||
void *handle;
|
||||
char *libCgFilePath = findLibCg();
|
||||
|
||||
handle = dlopen(libCgFilePath, RTLD_NOW);
|
||||
if (!handle)
|
||||
{
|
||||
log_error("Error: Unable to find library libCg.so\n");
|
||||
log_error("Error: libCg.so version 2.0 is needed to compile the shaders in the game's folder.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
free(libCgFilePath);
|
||||
dlerror();
|
||||
|
||||
char *error;
|
||||
|
||||
Reference in New Issue
Block a user