mirror of
https://github.com/lindbergh-loader/lindbergh-loader.git
synced 2026-10-14 18:09:34 +03:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
988a9ee6e3 | ||
|
|
ea19a688cc |
@@ -1,6 +1,11 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
All notable changes to this project will be documented in this file.
|
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]
|
## [2.0.9]
|
||||||
- lindbergh elf mostly redone to make the loader work as a stand alone mode (read guide.md).
|
- 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
|
# Define the path to the eeprom.bin file
|
||||||
# EEPROM_PATH eeprom.bin
|
# 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)
|
# Set the GPU vendor (0 = Autodetect / 1 = NVidia / 2 = AMD / 3 = ATI(AMD-PRO) / 4 = Intel / 5 = Unknown)
|
||||||
# GPU_VENDOR 0
|
# GPU_VENDOR 0
|
||||||
|
|
||||||
|
|||||||
@@ -1113,6 +1113,9 @@ int readConfig(FILE *configFile, EmulatorConfig *config)
|
|||||||
else if (strcmp(command, "SRAM_PATH") == 0)
|
else if (strcmp(command, "SRAM_PATH") == 0)
|
||||||
strcpy(config->sramPath, getNextToken(NULL, " ", &saveptr));
|
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) {
|
else if (strcmp(command, "EMULATE_RIDEBOARD") == 0) {
|
||||||
int defaultValue = config->emulateRideboard;
|
int defaultValue = config->emulateRideboard;
|
||||||
config->emulateRideboard = getNextIntOrAuto(saveptr, defaultValue);
|
config->emulateRideboard = getNextIntOrAuto(saveptr, defaultValue);
|
||||||
@@ -1529,6 +1532,7 @@ int initConfig(const char* configFilePath)
|
|||||||
config.lindberghColour = YELLOW;
|
config.lindberghColour = YELLOW;
|
||||||
strcpy(config.eepromPath, "eeprom.bin");
|
strcpy(config.eepromPath, "eeprom.bin");
|
||||||
strcpy(config.sramPath, "sram.bin");
|
strcpy(config.sramPath, "sram.bin");
|
||||||
|
strcpy(config.libCgPath, "");
|
||||||
strcpy(config.jvsPath, "/dev/ttyUSB0");
|
strcpy(config.jvsPath, "/dev/ttyUSB0");
|
||||||
strcpy(config.serial1Path, "/dev/ttyS0");
|
strcpy(config.serial1Path, "/dev/ttyS0");
|
||||||
strcpy(config.serial2Path, "/dev/ttyS1");
|
strcpy(config.serial2Path, "/dev/ttyS1");
|
||||||
|
|||||||
@@ -232,6 +232,7 @@ typedef struct
|
|||||||
int fullscreen;
|
int fullscreen;
|
||||||
char eepromPath[MAX_PATH_LENGTH];
|
char eepromPath[MAX_PATH_LENGTH];
|
||||||
char sramPath[MAX_PATH_LENGTH];
|
char sramPath[MAX_PATH_LENGTH];
|
||||||
|
char libCgPath[MAX_PATH_LENGTH];
|
||||||
char jvsPath[MAX_PATH_LENGTH];
|
char jvsPath[MAX_PATH_LENGTH];
|
||||||
char serial1Path[MAX_PATH_LENGTH];
|
char serial1Path[MAX_PATH_LENGTH];
|
||||||
char serial2Path[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;
|
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.
|
* Signal handler for the SIGSEGV signal, which is triggered when a process tries to access an illegal memory location.
|
||||||
* @param signal
|
* @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)
|
char *trimOS_ID(char *str)
|
||||||
{
|
{
|
||||||
if (!str)
|
if (!str)
|
||||||
@@ -198,6 +211,12 @@ char *trimOS_ID(char *str)
|
|||||||
return 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()
|
bool checkOS_ID()
|
||||||
{
|
{
|
||||||
FILE *fp = fopen("/etc/os-release", "r");
|
FILE *fp = fopen("/etc/os-release", "r");
|
||||||
@@ -249,6 +268,12 @@ bool checkOS_ID()
|
|||||||
return found;
|
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()
|
void __attribute__((constructor)) hook_init()
|
||||||
{
|
{
|
||||||
// Get offsets of the Game's ELF and calculate CRC32.
|
// Get offsets of the Game's ELF and calculate CRC32.
|
||||||
@@ -277,7 +302,6 @@ void __attribute__((constructor)) hook_init()
|
|||||||
}
|
}
|
||||||
|
|
||||||
getGPUVendor();
|
getGPUVendor();
|
||||||
|
|
||||||
if (initPatch() != 0)
|
if (initPatch() != 0)
|
||||||
exit(1);
|
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)
|
||||||
{
|
{
|
||||||
DIR *(*_opendir)(const char *dirname) = dlsym(RTLD_NEXT, "opendir");
|
DIR *(*_opendir)(const char *dirname) = dlsym(RTLD_NEXT, "opendir");
|
||||||
@@ -395,6 +426,13 @@ DIR *opendir(const char *dirname)
|
|||||||
return _opendir(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)
|
||||||
{
|
{
|
||||||
int (*_remove)(const char *path) = dlsym(RTLD_NEXT, "remove");
|
int (*_remove)(const char *path) = dlsym(RTLD_NEXT, "remove");
|
||||||
@@ -416,6 +454,13 @@ int remove(const char *path)
|
|||||||
return _remove(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)
|
||||||
{
|
{
|
||||||
int (*_mkdir)(const char *path, mode_t mode) = dlsym(RTLD_NEXT, "mkdir");
|
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);
|
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)
|
||||||
{
|
{
|
||||||
int (*___xstat64)(int ver, const char *path, struct stat64 *stat_buf) = dlsym(RTLD_NEXT, "__xstat64");
|
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);
|
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, ...)
|
int open(const char *pathname, int flags, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
@@ -534,6 +593,13 @@ int open(const char *pathname, int flags, ...)
|
|||||||
return _open(pathname, flags, mode);
|
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, ...)
|
int open64(const char *pathname, int flags, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
@@ -544,6 +610,13 @@ int open64(const char *pathname, int flags, ...)
|
|||||||
return open(pathname, flags, mode);
|
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)
|
||||||
{
|
{
|
||||||
FILE *(*_fopen)(const char *restrict pathname, const char *restrict mode) = dlsym(RTLD_NEXT, "fopen");
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cachedShaderFilesLoaded)
|
if (cachedShaderFilesLoaded)
|
||||||
{
|
{
|
||||||
void *addr = __builtin_return_address(0);
|
void *addr = __builtin_return_address(0);
|
||||||
@@ -757,6 +829,13 @@ FILE *fopen(const char *restrict pathname, const char *restrict mode)
|
|||||||
return _fopen(pathname, 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 *pathname, const char *mode)
|
||||||
{
|
{
|
||||||
FILE *(*_fopen64)(const char *restrict pathname, const char *restrict mode) = dlsym(RTLD_NEXT, "fopen64");
|
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);
|
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)
|
||||||
{
|
{
|
||||||
int (*_fclose)(FILE *stream) = dlsym(RTLD_NEXT, "fclose");
|
int (*_fclose)(FILE *stream) = dlsym(RTLD_NEXT, "fclose");
|
||||||
@@ -878,6 +964,14 @@ int fclose(FILE *stream)
|
|||||||
}
|
}
|
||||||
return _fclose(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, ...)
|
||||||
{
|
{
|
||||||
int (*_openat)(int dirfd, const char *pathname, int flags) = dlsym(RTLD_NEXT, "openat");
|
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);
|
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)
|
||||||
{
|
{
|
||||||
int (*_close)(int fd) = dlsym(RTLD_NEXT, "close");
|
int (*_close)(int fd) = dlsym(RTLD_NEXT, "close");
|
||||||
@@ -908,6 +1009,13 @@ int close(int fd)
|
|||||||
return _close(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)
|
||||||
{
|
{
|
||||||
char *(*_fgets)(char *str, int n, FILE *stream) = dlsym(RTLD_NEXT, "fgets");
|
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);
|
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)
|
ssize_t read(int fd, void *buf, size_t count)
|
||||||
{
|
{
|
||||||
int (*_read)(int fd, void *buf, size_t count) = dlsym(RTLD_NEXT, "read");
|
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);
|
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)
|
||||||
{
|
{
|
||||||
size_t (*_fread)(void *buf, size_t size, size_t count, FILE *stream) = dlsym(RTLD_NEXT, "fread");
|
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);
|
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)
|
||||||
{
|
{
|
||||||
long int (*_ftell)(FILE *stream) = dlsym(RTLD_NEXT, "ftell");
|
long int (*_ftell)(FILE *stream) = dlsym(RTLD_NEXT, "ftell");
|
||||||
@@ -1067,6 +1196,13 @@ long int ftell(FILE *stream)
|
|||||||
return _ftell(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)
|
||||||
{
|
{
|
||||||
int (*_fseek)(FILE *stream, long int offset, int whence) = dlsym(RTLD_NEXT, "fseek");
|
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);
|
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)
|
||||||
{
|
{
|
||||||
void (*_rewind)(FILE *stream) = dlsym(RTLD_NEXT, "rewind");
|
void (*_rewind)(FILE *stream) = dlsym(RTLD_NEXT, "rewind");
|
||||||
@@ -1103,6 +1246,13 @@ void rewind(FILE *stream)
|
|||||||
_rewind(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)
|
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");
|
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);
|
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, unsigned int request, void *data)
|
||||||
{
|
{
|
||||||
int (*_ioctl)(int fd, int request, void *data) = dlsym(RTLD_NEXT, "ioctl");
|
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);
|
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)
|
||||||
{
|
{
|
||||||
int (*_tcgetattr)(int fd, struct termios *termios_p) = dlsym(RTLD_NEXT, "tcgetattr");
|
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);
|
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)
|
||||||
{
|
{
|
||||||
int (*_tcsetattr)(int fd, int optional_actions, const struct termios *termios_p) = dlsym(RTLD_NEXT, "tcsetattr");
|
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);
|
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)
|
||||||
{
|
{
|
||||||
speed_t (*_cfgetispeed)(const struct termios *termios_p) = dlsym(RTLD_NEXT, "cfgetispeed");
|
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);
|
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)
|
||||||
{
|
{
|
||||||
speed_t (*_cfgetospeed)(const struct termios *termios_p) = dlsym(RTLD_NEXT, "cfgetospeed");
|
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);
|
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)
|
||||||
{
|
{
|
||||||
int (*_cfsetispeed)(struct termios *termios_p, speed_t speed) = dlsym(RTLD_NEXT, "cfsetispeed");
|
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);
|
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)
|
||||||
{
|
{
|
||||||
int (*_cfsetospeed)(struct termios *termios_p, speed_t speed) = dlsym(RTLD_NEXT, "cfsetospeed");
|
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);
|
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,
|
int select(int nfds, fd_set *restrict readfds, fd_set *restrict writefds, fd_set *restrict exceptfds,
|
||||||
struct timeval *restrict timeout)
|
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);
|
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)
|
||||||
{
|
{
|
||||||
int (*_system)(const char *command) = dlsym(RTLD_NEXT, "system");
|
int (*_system)(const char *command) = dlsym(RTLD_NEXT, "system");
|
||||||
@@ -1291,6 +1505,36 @@ int system(const char *command)
|
|||||||
return _system(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)
|
int iopl(int level)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1306,10 +1550,11 @@ void kswap_collect(void *p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hook for function used by Primevil
|
* @brief Hook for the powf function.
|
||||||
* @param base The number to raise to the exponent
|
*
|
||||||
* @param exp The exponent to raise the number to
|
* This function intercepts calls to powf and redirects them to pow.
|
||||||
* @return The result of raising the number to the exponent
|
* @param base The base number.
|
||||||
|
* @param exponent The exponent.
|
||||||
*/
|
*/
|
||||||
float powf(float base, float 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)
|
int get_machine_ip(struct sockaddr_in *addr)
|
||||||
{
|
{
|
||||||
struct ifaddrs *ifaddr, *ifa;
|
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)
|
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)
|
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)
|
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)
|
int unsetenv(const char *name)
|
||||||
{
|
{
|
||||||
@@ -1497,6 +1764,13 @@ char *__strdup(const char *string)
|
|||||||
return ___strdup(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 *timep, struct tm *result)
|
||||||
{
|
{
|
||||||
struct tm *(*_localtime_r)(const time_t *, struct tm *) =
|
struct tm *(*_localtime_r)(const time_t *, struct tm *) =
|
||||||
|
|||||||
+31
-15
@@ -19,6 +19,7 @@
|
|||||||
#define PRELOAD_FILE_NAME "lindbergh.so"
|
#define PRELOAD_FILE_NAME "lindbergh.so"
|
||||||
#define TEAM "bobbydilley, retrofan, dkeruza-neo, doozer, francesco, rolel, caviar-x"
|
#define TEAM "bobbydilley, retrofan, dkeruza-neo, doozer, francesco, rolel, caviar-x"
|
||||||
#define LINDBERGH_CONFIG_PATH "LINDBERGH_CONFIG_PATH"
|
#define LINDBERGH_CONFIG_PATH "LINDBERGH_CONFIG_PATH"
|
||||||
|
#define LINDBERGH_LOADER_CURRENT_DIR "LINDBERGH_LOADER_CURRENT_DIR"
|
||||||
#define MAX_PATH_LEN 1024
|
#define MAX_PATH_LEN 1024
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -230,6 +231,19 @@ int calculateFileCRC32(const char *filename, uint32_t *crc)
|
|||||||
return 0;
|
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.
|
* @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.
|
* against a list of known clean ELF CRC32 values.
|
||||||
* @param command The command line string containing the path to the ELF file.
|
* @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, ' ');
|
char *last_space = strrchr(command, ' ');
|
||||||
size_t length;
|
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("__GLX_VENDOR_LIBRARY_NAME", "nvidia", 1);
|
||||||
setenv("__NV_PRIME_RENDER_OFFLOAD", "1", 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;
|
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 command[PATH_MAX] = {0};
|
||||||
char *forcedGameDir;
|
char *forcedGameDir;
|
||||||
char *forcedGameElf;
|
char *forcedGameElf;
|
||||||
@@ -796,26 +817,16 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
char *ldPreloadLibrary = findLDPreloadLibrary();
|
char *ldPreloadLibrary = findLDPreloadLibrary();
|
||||||
|
|
||||||
if (strcmp(ldPreloadLibrary, PRELOAD_FILE_NAME) == 0)
|
if (strcmp(curDir, gameDir) == 0)
|
||||||
{
|
ldPreloadLibrary = PRELOAD_FILE_NAME;
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure environment variables are set correctly
|
// Ensure environment variables are set correctly
|
||||||
setEnvironmentVariables(ldPreloadLibrary, curDir, gameDir, zink, nvidia);
|
setEnvironmentVariables(ldPreloadLibrary, curDir, gameDir, zink, nvidia);
|
||||||
|
|
||||||
if (testMode)
|
if (testMode)
|
||||||
testModePath(command);
|
testModePath(command);
|
||||||
isCleanElf(command);
|
|
||||||
|
checkIfElfisClean(command);
|
||||||
|
|
||||||
if (gdb)
|
if (gdb)
|
||||||
{
|
{
|
||||||
@@ -827,6 +838,11 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
if (extConfigPath != NULL && extConfigPath[0] != '\0')
|
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);
|
setenv(LINDBERGH_CONFIG_PATH, extConfigPath, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-11
@@ -628,11 +628,9 @@ int initPatch()
|
|||||||
|
|
||||||
if (GPUVendor != NVIDIA_GPU)
|
if (GPUVendor != NVIDIA_GPU)
|
||||||
{
|
{
|
||||||
cacheModedShaderFiles();
|
|
||||||
loadLibCg();
|
loadLibCg();
|
||||||
|
cacheModedShaderFiles();
|
||||||
cacheNnstdshader();
|
cacheNnstdshader();
|
||||||
patchMemory(0x082d4437, "9090909090"); // Stop the folder rename
|
|
||||||
patchMemory(0x088a6127, "66732f636f6d70696c65646d657361"); // Change folder to compiledshdmesa
|
|
||||||
patchMemory(0x082646b3, "01"); // Compile using CGC
|
patchMemory(0x082646b3, "01"); // Compile using CGC
|
||||||
replaceCallAtAddress(0x082d48ac, compileWithCGC);
|
replaceCallAtAddress(0x082d48ac, compileWithCGC);
|
||||||
replaceCallAtAddress(0x082d4b3b, compileWithCGC);
|
replaceCallAtAddress(0x082d4b3b, compileWithCGC);
|
||||||
@@ -2059,12 +2057,9 @@ int initPatch()
|
|||||||
{
|
{
|
||||||
loadLibCg();
|
loadLibCg();
|
||||||
cacheNnstdshader();
|
cacheNnstdshader();
|
||||||
patchMemory(0x08200c17, "9090909090"); // Stop the folder rename
|
|
||||||
patchMemory(0x084173e7, "66732f636f6d70696c65646d657361"); // Change folder to compiledshdmesa
|
|
||||||
patchMemory(0x080b3d71, "01"); // Compile using CGC
|
patchMemory(0x080b3d71, "01"); // Compile using CGC
|
||||||
replaceCallAtAddress(0x082015bf, compileWithCGC);
|
replaceCallAtAddress(0x082015bf, compileWithCGC);
|
||||||
replaceCallAtAddress(0x082012c1, compileWithCGC);
|
replaceCallAtAddress(0x082012c1, compileWithCGC);
|
||||||
// patchMemory(0x080b3d65, "00"); // Force recompile shaders
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -2487,9 +2482,8 @@ int initPatch()
|
|||||||
// Mesa Patches
|
// Mesa Patches
|
||||||
if (GPUVendor != NVIDIA_GPU)
|
if (GPUVendor != NVIDIA_GPU)
|
||||||
{
|
{
|
||||||
patchMemory(0x08503bfa, "6d657361"); // Rename compile folder to compmesa
|
|
||||||
cacheModedShaderFiles();
|
|
||||||
loadLibCg();
|
loadLibCg();
|
||||||
|
cacheModedShaderFiles();
|
||||||
cacheNnstdshader();
|
cacheNnstdshader();
|
||||||
replaceCallAtAddress(0x08370aa7, compileWithCGC);
|
replaceCallAtAddress(0x08370aa7, compileWithCGC);
|
||||||
replaceCallAtAddress(0x08370bb6, compileWithCGC);
|
replaceCallAtAddress(0x08370bb6, compileWithCGC);
|
||||||
@@ -2550,10 +2544,9 @@ int initPatch()
|
|||||||
if (GPUVendor != NVIDIA_GPU)
|
if (GPUVendor != NVIDIA_GPU)
|
||||||
{
|
{
|
||||||
loadLibCg();
|
loadLibCg();
|
||||||
cacheNnstdshader();
|
|
||||||
patchMemory(0x081ef9d8, "01"); // Force the game to recompile the shaders using cgc
|
|
||||||
patchMemory(0x08413f04, "646d657361"); // Changes compiledshader folder to compiledshdmesa
|
|
||||||
cacheModedShaderFiles();
|
cacheModedShaderFiles();
|
||||||
|
cacheNnstdshader();
|
||||||
|
patchMemory(0x081ef9d8, "01"); // Force the game to recompile the shaders using cgc
|
||||||
replaceCallAtAddress(0x08259fe5, compileWithCGC);
|
replaceCallAtAddress(0x08259fe5, compileWithCGC);
|
||||||
replaceCallAtAddress(0x0825a089, compileWithCGC);
|
replaceCallAtAddress(0x0825a089, compileWithCGC);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#ifndef __i386__
|
#ifndef __i386__
|
||||||
#define __i386__
|
#define __i386__
|
||||||
|
|
||||||
|
#include "log.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#endif
|
#endif
|
||||||
#undef __x86_64__
|
#undef __x86_64__
|
||||||
@@ -22,6 +23,7 @@
|
|||||||
#include "../libxdiff/xdiff/xdiff.h"
|
#include "../libxdiff/xdiff/xdiff.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "patch.h"
|
#include "patch.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
#include "shader_work/2spicy.h"
|
#include "shader_work/2spicy.h"
|
||||||
#include "shader_work/abc.h"
|
#include "shader_work/abc.h"
|
||||||
@@ -1541,41 +1543,99 @@ int parseCgcArgs(const char *input, const char ***compilerArgs, const char **out
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadLibCg()
|
char *findLibCg()
|
||||||
{
|
{
|
||||||
int isFlatpak = 0;
|
const char *foundPath = NULL;
|
||||||
void *handle = dlopen("./libCg.so", RTLD_NOW);
|
FILE *libCgF = NULL;
|
||||||
if (!handle)
|
|
||||||
|
char *pathsToCheck[] = {NULL, "/app/lib32/libCg2.so", "./libCg.so", NULL};
|
||||||
|
|
||||||
|
if (strcmp(getConfig()->libCgPath, "") != 0)
|
||||||
{
|
{
|
||||||
handle = dlopen("/app/lib32/libCg2.so", RTLD_NOW);
|
pathsToCheck[0] = getConfig()->libCgPath;
|
||||||
if (!handle)
|
}
|
||||||
|
|
||||||
|
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());
|
snprintf(pathsToCheck[3], pathLen, "%s/%s", currentDir, "libCg.so");
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char libCgVersion[9];
|
for (int i = 0; i < 4; ++i)
|
||||||
FILE *libF;
|
{
|
||||||
if (isFlatpak)
|
if (pathsToCheck[i] == NULL)
|
||||||
libF = fopen("/app/lib32/libCg2.so", "r");
|
continue;
|
||||||
else
|
|
||||||
libF = fopen("./libCg.so", "r");
|
|
||||||
|
|
||||||
fseek(libF, 0x226d84, SEEK_SET);
|
if (access(pathsToCheck[i], F_OK) == 0)
|
||||||
fread(libCgVersion, 9, 1, libF);
|
{
|
||||||
fclose(libF);
|
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)
|
if (strcmp(libCgVersion, "2.0.0.12") != 0)
|
||||||
{
|
{
|
||||||
printf("ERROR: Wrong libCg.so, version 2.0.0.12 is needed.\n");
|
log_error("ERROR: Wrong libCg.so version '%s', version 2.0.0.12 is needed.\n", libCgVersion);
|
||||||
exit(1);
|
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();
|
dlerror();
|
||||||
|
|
||||||
char *error;
|
char *error;
|
||||||
|
|||||||
Reference in New Issue
Block a user