mirror of
https://github.com/lindbergh-loader/lindbergh-loader.git
synced 2026-10-14 01:49:12 +03:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0e8b3b4a59 | ||
|
|
f17dd93778 | ||
|
|
e359cbb0bd | ||
|
|
72f70ccda1 | ||
|
|
0a29307870 | ||
|
|
d202f31717 |
@@ -0,0 +1,29 @@
|
|||||||
|
name: 🐧 Linux AppImage
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_call:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
linux-appimage:
|
||||||
|
name: "Build"
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
timeout-minutes: 120
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Install Packages
|
||||||
|
run: scripts/appimage/install-packages.sh
|
||||||
|
|
||||||
|
- name: Compile Build
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
make
|
||||||
|
scripts/appimage/make-appimage.sh
|
||||||
|
- name: Upload AppImage
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: "linux-appimage"
|
||||||
|
path: "lindbergh-loader.AppImage"
|
||||||
@@ -24,10 +24,13 @@ jobs:
|
|||||||
linux-flatpak:
|
linux-flatpak:
|
||||||
name: 📦 Linux Flatpak
|
name: 📦 Linux Flatpak
|
||||||
uses: "./.github/workflows/flatpak-build.yml"
|
uses: "./.github/workflows/flatpak-build.yml"
|
||||||
|
linux-appimage:
|
||||||
|
name: 📦 Linux AppImage
|
||||||
|
uses: "./.github/workflows/appimage-build.yml"
|
||||||
|
|
||||||
create-release:
|
create-release:
|
||||||
name: 📤 Create Release
|
name: 📤 Create Release
|
||||||
needs: [linux-build, linux-flatpak]
|
needs: [linux-build, linux-flatpak, linux-appimage]
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
if: github.ref == 'refs/heads/master'
|
if: github.ref == 'refs/heads/master'
|
||||||
steps:
|
steps:
|
||||||
@@ -55,3 +58,4 @@ jobs:
|
|||||||
files: |
|
files: |
|
||||||
./artifacts/linux-flatpak/lindbergh-loader.flatpak
|
./artifacts/linux-flatpak/lindbergh-loader.flatpak
|
||||||
./artifacts/linux-build/build.tar.gz
|
./artifacts/linux-build/build.tar.gz
|
||||||
|
./artifacts/linux-appimage/lindbergh-loader.AppImage
|
||||||
|
|||||||
@@ -1,6 +1,20 @@
|
|||||||
# 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.12]
|
||||||
|
### Added
|
||||||
|
- AppImage support.
|
||||||
|
### Fixed
|
||||||
|
- 2Spicy error in the scaling code, again.
|
||||||
|
|
||||||
|
## [2.0.11]
|
||||||
|
### Added
|
||||||
|
- Resolution patches for 2Spicy and HOD-Ex
|
||||||
|
- Code clean up.
|
||||||
|
### Fixed
|
||||||
|
- 2Spicy error in the scaling code.
|
||||||
|
|
||||||
## [2.0.10]
|
## [2.0.10]
|
||||||
### Added
|
### Added
|
||||||
- Config option to specify a path for the library libCg.so required for some shader compilation.
|
- Config option to specify a path for the library libCg.so required for some shader compilation.
|
||||||
|
|||||||
Executable
+11
@@ -0,0 +1,11 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
echo "Install Packages Running..."
|
||||||
|
sudo dpkg --add-architecture i386
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get -y install --no-install-recommends \
|
||||||
|
build-essential gcc-multilib fuse freeglut3-dev:i386 libsdl2-dev:i386 libfaudio-dev:i386 libvdpau1:i386 \
|
||||||
|
libstdc++5:i386 libxmu6:i386 libpcsclite1:i386 libncurses5:i386 unzip
|
||||||
|
|
||||||
|
sudo add-apt-repository ppa:kisak/kisak-mesa -y
|
||||||
|
sudo apt-get -y update && sudo apt -y dist-upgrade
|
||||||
Executable
+103
@@ -0,0 +1,103 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
APPIMAGENAME=lindbergh-loader
|
||||||
|
APPIMAGEDIRNAME=lindbergh-loader.AppDir
|
||||||
|
|
||||||
|
declare -a ADDED_LIBS=(
|
||||||
|
"libOpenGL.so.0"
|
||||||
|
"libGLdispatch.so.0"
|
||||||
|
"libGLX.so"
|
||||||
|
"libGLX_indirect.so.0"
|
||||||
|
"libGLX_mesa.so.0"
|
||||||
|
"libGL.so.1"
|
||||||
|
"libGLU.so.1"
|
||||||
|
"libglut.so.3"
|
||||||
|
"libglapi.so.0"
|
||||||
|
"libX11.so.6"
|
||||||
|
"libX11-xcb.so.1"
|
||||||
|
"libxcb.so.1"
|
||||||
|
"libxcb-dri2.so.0"
|
||||||
|
"libxcb-dri3.so.0"
|
||||||
|
"libxcb-glx.so.0"
|
||||||
|
"libXmu.so.6"
|
||||||
|
"libncurses.so.5"
|
||||||
|
"libpcsclite.so.1"
|
||||||
|
"libstdc++.so.5"
|
||||||
|
"libdrm.so.2"
|
||||||
|
"libexpat.so.1"
|
||||||
|
)
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
if [ ! -f "linuxdeploy-x86_64" ]; then
|
||||||
|
wget -O "linuxdeploy-x86_64" https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage
|
||||||
|
chmod +x "linuxdeploy-x86_64"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f "appimagetool-x86_64" ]; then
|
||||||
|
wget -O "appimagetool-x86_64" https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage
|
||||||
|
chmod +x "appimagetool-x86_64"
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd build
|
||||||
|
OUTPUT_FOLDER=$(realpath "./$APPIMAGEDIRNAME")
|
||||||
|
rm -fr "$OUTPUT_FOLDER"
|
||||||
|
|
||||||
|
ADDED_LIBS_ARGS=()
|
||||||
|
for lib in "${ADDED_LIBS[@]}"; do
|
||||||
|
ADDED_LIBS_ARGS+=("--library=/usr/lib/i386-linux-gnu/$lib")
|
||||||
|
done
|
||||||
|
|
||||||
|
|
||||||
|
echo "Copying files into AppDir..."
|
||||||
|
mkdir -p "$OUTPUT_FOLDER/usr/bin"
|
||||||
|
mkdir -p "$OUTPUT_FOLDER/usr/lib"
|
||||||
|
mkdir -p "$OUTPUT_FOLDER/usr/lib32"
|
||||||
|
|
||||||
|
# We create the AppRun file
|
||||||
|
cat > "$OUTPUT_FOLDER/AppRun" << 'EOF'
|
||||||
|
#!/bin/bash
|
||||||
|
APP_IMG_ROOT="$(dirname "$(readlink -f "$0")")"
|
||||||
|
export APP_IMG_ROOT=$APP_IMG_ROOT
|
||||||
|
export LD_LIBRARY_PATH="$APP_IMG_ROOT/usr/lib32:$LD_LIBRARY_PATH"
|
||||||
|
exec "$APP_IMG_ROOT/usr/bin/lindbergh" "$@"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
chmod +x "$OUTPUT_FOLDER/AppRun"
|
||||||
|
|
||||||
|
cp libkswapapi.so $OUTPUT_FOLDER/usr/lib
|
||||||
|
cp libsegaapi.so $OUTPUT_FOLDER/usr/lib
|
||||||
|
cp lindbergh.so $OUTPUT_FOLDER/usr/lib
|
||||||
|
cp libposixtime.so $OUTPUT_FOLDER/usr/lib
|
||||||
|
mv lindbergh $OUTPUT_FOLDER/usr/bin
|
||||||
|
mkdir -p $OUTPUT_FOLDER/usr/lib/dri
|
||||||
|
cp /usr/lib/i386-linux-gnu/dri/* $OUTPUT_FOLDER/usr/lib/dri
|
||||||
|
cp ../libs/libcrypto.so.0.9.7 $OUTPUT_FOLDER/usr/lib
|
||||||
|
cp ../libs/libssl.so.0.9.7 $OUTPUT_FOLDER/usr/lib
|
||||||
|
cp ../libs/libopenal.so.0 $OUTPUT_FOLDER/usr/lib
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
echo "Running linuxdeploy to create AppDir..."
|
||||||
|
./linuxdeploy-x86_64 --appimage-extract-and-run --appdir="$OUTPUT_FOLDER" ${ADDED_LIBS_ARGS[@]} \
|
||||||
|
--desktop-file="./scripts/lindbergh-loader.desktop" \
|
||||||
|
--icon-file="./scripts/lindbergh-loader.png"
|
||||||
|
|
||||||
|
mv $OUTPUT_FOLDER/usr/lib/libkswapapi.so $OUTPUT_FOLDER/usr/lib32
|
||||||
|
mv $OUTPUT_FOLDER/usr/lib/libsegaapi.so $OUTPUT_FOLDER/usr/lib32
|
||||||
|
mv $OUTPUT_FOLDER/usr/lib/lindbergh.so $OUTPUT_FOLDER/usr/lib32
|
||||||
|
mv $OUTPUT_FOLDER/usr/lib/libposixtime.so $OUTPUT_FOLDER/usr/lib32
|
||||||
|
mv $OUTPUT_FOLDER/usr/lib/libcrypto.so.0.9.7 $OUTPUT_FOLDER/usr/lib32
|
||||||
|
mv $OUTPUT_FOLDER/usr/lib/libssl.so.0.9.7 $OUTPUT_FOLDER/usr/lib32
|
||||||
|
mv $OUTPUT_FOLDER/usr/lib/libopenal.so.0 $OUTPUT_FOLDER/usr/lib32
|
||||||
|
mv $OUTPUT_FOLDER/usr/lib/dri $OUTPUT_FOLDER/usr/lib32
|
||||||
|
|
||||||
|
unzip libs/Cg-3.1.zip -d $OUTPUT_FOLDER/usr/lib32
|
||||||
|
cp libs/libCg.so $OUTPUT_FOLDER/usr/lib32/libCg2.so
|
||||||
|
ln -s -f libposixtime.so $OUTPUT_FOLDER/usr/lib32/libposixtime.so.1
|
||||||
|
ln -s -f libposixtime.so $OUTPUT_FOLDER/usr/lib32/libposixtime.so.2.4
|
||||||
|
ln -s -f libkswapapi.so $OUTPUT_FOLDER/usr/lib32/libGLcore.so.1
|
||||||
|
ln -s -f libkswapapi.so $OUTPUT_FOLDER/usr/lib32/libnvidia-tls.so.1
|
||||||
|
|
||||||
|
echo "Generating AppImage..."
|
||||||
|
rm -f "$APPIMAGENAME.AppImage"
|
||||||
|
./appimagetool-x86_64 -v "$OUTPUT_FOLDER" "$APPIMAGENAME.AppImage" --appimage-extract-and-run
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
[Desktop Entry]
|
||||||
|
Name=Lindbergh Loader
|
||||||
|
Exec=lindbergh
|
||||||
|
Icon=lindbergh-loader
|
||||||
|
Type=Application
|
||||||
|
Categories=Utility;ConsoleOnly;
|
||||||
|
Terminal=true
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 60 KiB |
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
|||||||
+275
-506
@@ -1,15 +1,14 @@
|
|||||||
#include <dirent.h>
|
|
||||||
#include <libgen.h>
|
|
||||||
#include <linux/limits.h>
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdint.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <libgen.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
#include "evdevinput.h"
|
#include "evdevinput.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
@@ -20,59 +19,14 @@
|
|||||||
#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 LINDBERGH_LOADER_CURRENT_DIR "LINDBERGH_LOADER_CURRENT_DIR"
|
||||||
#define MAX_PATH_LEN 1024
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Calculates the CRC32 of a single byte.
|
|
||||||
*
|
|
||||||
* This function calculates the CRC32 value for a given byte of data.
|
|
||||||
*
|
|
||||||
* @param crc The current CRC32 value.
|
|
||||||
* @param data The byte of data to calculate the CRC32 for.
|
|
||||||
* @return The updated CRC32 value.
|
|
||||||
*/
|
|
||||||
uint32_t calcCrc32(uint32_t crc, uint8_t data)
|
|
||||||
{
|
|
||||||
crc ^= data; // No shift needed; working in LSB-first order
|
|
||||||
for (int i = 0; i < 8; i++)
|
|
||||||
{
|
|
||||||
if (crc & 1)
|
|
||||||
{
|
|
||||||
crc = (crc >> 1) ^ 0xEDB88320;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
crc = (crc >> 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return crc;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t elf_crc = 0;
|
uint32_t elf_crc = 0;
|
||||||
|
|
||||||
// List of all lindbergh executables known, not including the test executables
|
// List of all lindbergh executables known, not including the test executables
|
||||||
char *games[] = {"main.exe",
|
char *games[] = {"a.elf", "abc", "apacheM.elf", "chopperM.elf", "drive.elf", "dsr",
|
||||||
"ramboM.elf",
|
"gsevo", "hod4M.elf", "hodexRI.elf", "hummer_Master.elf", "id4.elf", "id5.elf",
|
||||||
"vt3_Lindbergh",
|
"Jennifer", "lgj_final", "lgjsp_app", "main.exe", "mj4", "ramboM.elf",
|
||||||
"hummer_Master.elf",
|
"vf5", "vsg", "vt3", "vt3_Lindbergh", "END"};
|
||||||
"drive.elf",
|
|
||||||
"chopperM.elf",
|
|
||||||
"vsg",
|
|
||||||
"Jennifer",
|
|
||||||
"dsr",
|
|
||||||
"abc",
|
|
||||||
"hod4M.elf",
|
|
||||||
"lgj_final",
|
|
||||||
"vt3",
|
|
||||||
"id4.elf",
|
|
||||||
"id5.elf",
|
|
||||||
"lgjsp_app",
|
|
||||||
"gsevo",
|
|
||||||
"vf5",
|
|
||||||
"apacheM.elf",
|
|
||||||
"hodexRI.elf",
|
|
||||||
"a.elf",
|
|
||||||
"END"};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An array containin clean games elf's CRC32
|
* An array containin clean games elf's CRC32
|
||||||
@@ -129,6 +83,7 @@ uint32_t cleanElfCRC32[] = {
|
|||||||
0xB0A96E34, // DVP-0043 | vf5
|
0xB0A96E34, // DVP-0043 | vf5
|
||||||
0xF99E5635, // DVP-0044 | drive.elf
|
0xF99E5635, // DVP-0044 | drive.elf
|
||||||
0x4143F6B4, // DVP-0048A | main.exe
|
0x4143F6B4, // DVP-0048A | main.exe
|
||||||
|
0x65489691, // DVP-0049 | mj4
|
||||||
0x653BC83B, // DVP-0057 | a.elf
|
0x653BC83B, // DVP-0057 | a.elf
|
||||||
0x04D88552, // DVP-0057B | a.elf
|
0x04D88552, // DVP-0057B | a.elf
|
||||||
0x089D6051, // DVP-0060 | dsr
|
0x089D6051, // DVP-0060 | dsr
|
||||||
@@ -139,6 +94,7 @@ uint32_t cleanElfCRC32[] = {
|
|||||||
0x2E6732A3, // DVP-0070F | id5.elf
|
0x2E6732A3, // DVP-0070F | id5.elf
|
||||||
0xF99A3CDB, // DVP-0075 | id5.elf
|
0xF99A3CDB, // DVP-0075 | id5.elf
|
||||||
0x05647A8E, // DVP-0079 | hummer_Master.elf
|
0x05647A8E, // DVP-0079 | hummer_Master.elf
|
||||||
|
0x0AD7CF0F, // DVP-0081 | mj4
|
||||||
0x4442EA15, // DVP-0083 | hummer_Master.elf
|
0x4442EA15, // DVP-0083 | hummer_Master.elf
|
||||||
0x8DF6BBF9, // DVP-0084 | id5.elf
|
0x8DF6BBF9, // DVP-0084 | id5.elf
|
||||||
0x2AF8004E, // DVP-0084A | id5.elf
|
0x2AF8004E, // DVP-0084A | id5.elf
|
||||||
@@ -153,67 +109,30 @@ uint32_t cleanElfCRC32[] = {
|
|||||||
|
|
||||||
int cleanElfCRC32Count = sizeof(cleanElfCRC32) / sizeof(uint32_t);
|
int cleanElfCRC32Count = sizeof(cleanElfCRC32) / sizeof(uint32_t);
|
||||||
|
|
||||||
/**
|
uint32_t calcCrc32(uint32_t crc, uint8_t data)
|
||||||
* @brief Looks up a CRC value in the cleanElfCRC32 table.
|
|
||||||
*
|
|
||||||
* This function searches for a given CRC value within the cleanElfCRC32 array.
|
|
||||||
*
|
|
||||||
* @param crc The CRC value to look up.
|
|
||||||
* @return 1 if the CRC is found in the table, 0 otherwise.
|
|
||||||
*/
|
|
||||||
int lookupCrcTable(uint32_t crc)
|
|
||||||
{
|
{
|
||||||
for (int x = 0; x < cleanElfCRC32Count; x++)
|
crc ^= data;
|
||||||
|
for (int i = 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
if (cleanElfCRC32[x] == crc)
|
if (crc & 1)
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Removes double quotes from a string.
|
|
||||||
*
|
|
||||||
* This function iterates through the input string and removes any double quote characters.
|
|
||||||
* It modifies the string in place.
|
|
||||||
*
|
|
||||||
* @param str The string to remove double quotes from.
|
|
||||||
*/
|
|
||||||
void removeDoubleQuotes(char *str)
|
|
||||||
{
|
|
||||||
if (str == NULL)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int j = 0;
|
|
||||||
for (int i = 0; str[i] != '\0'; i++)
|
|
||||||
{
|
|
||||||
if (str[i] != '"')
|
|
||||||
{
|
{
|
||||||
str[j] = str[i];
|
crc = (crc >> 1) ^ 0xEDB88320;
|
||||||
j++;
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
crc = (crc >> 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
str[j] = '\0';
|
return crc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
int calculateCRC32inChunks(const char *filename, uint32_t *crc)
|
||||||
* @brief Calculates the CRC32 of a file.
|
|
||||||
*
|
|
||||||
* This function calculates the CRC32 of the specified file.
|
|
||||||
*
|
|
||||||
* @param filename The path to the file.
|
|
||||||
* @param crc The pointer to the variable that will contain the CRC32.
|
|
||||||
* @return 0 if the CRC32 was calculated successfully, -1 otherwise.
|
|
||||||
*/
|
|
||||||
int calculateFileCRC32(const char *filename, uint32_t *crc)
|
|
||||||
{
|
{
|
||||||
FILE *file = fopen(filename, "rb");
|
FILE *file = fopen(filename, "rb");
|
||||||
if (!file)
|
if (file == NULL)
|
||||||
{
|
{
|
||||||
log_error("Could not open file to calculate the CRC32.");
|
log_error("Could not open file to calculate the CRC32.");
|
||||||
return -1;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
*crc = 0xFFFFFFFF;
|
*crc = 0xFFFFFFFF;
|
||||||
@@ -231,32 +150,34 @@ int calculateFileCRC32(const char *filename, uint32_t *crc)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasSpaces(const char *str)
|
int lookupCrcTable(uint32_t crc)
|
||||||
{
|
{
|
||||||
if (!str)
|
for (int x = 0; x < cleanElfCRC32Count; x++)
|
||||||
return false;
|
|
||||||
while (*str)
|
|
||||||
{
|
{
|
||||||
if (*str == ' ')
|
if (cleanElfCRC32[x] == crc)
|
||||||
return true;
|
return 1;
|
||||||
str++;
|
|
||||||
}
|
}
|
||||||
return false;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
int fileExists(const char *path)
|
||||||
* @brief Checks if the ELF file is clean based on its CRC32.
|
|
||||||
*
|
|
||||||
* This function calculates the CRC32 of the specified ELF file and compares it
|
|
||||||
* against a list of known clean ELF CRC32 values.
|
|
||||||
* @param command The command line string containing the path to the ELF file.
|
|
||||||
*/
|
|
||||||
void checkIfElfisClean(char *command)
|
|
||||||
{
|
{
|
||||||
char *last_space = strrchr(command, ' ');
|
struct stat buffer;
|
||||||
|
return stat(path, &buffer) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dirExists(const char *path)
|
||||||
|
{
|
||||||
|
struct stat buffer;
|
||||||
|
return stat(path, &buffer) == 0 && S_ISDIR(buffer.st_mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void isCleanElf(char *command)
|
||||||
|
{
|
||||||
|
char *lastSpace = strrchr(command, ' ');
|
||||||
size_t length;
|
size_t length;
|
||||||
if (last_space != NULL && strcmp(last_space, " -t") == 0)
|
if (lastSpace != NULL && strcmp(lastSpace, " -t") == 0)
|
||||||
length = (size_t)(last_space - command);
|
length = (size_t)(lastSpace - command);
|
||||||
else
|
else
|
||||||
length = strlen(command);
|
length = strlen(command);
|
||||||
|
|
||||||
@@ -264,10 +185,14 @@ void checkIfElfisClean(char *command)
|
|||||||
strncpy(elfName, command, length);
|
strncpy(elfName, command, length);
|
||||||
elfName[length] = '\0';
|
elfName[length] = '\0';
|
||||||
|
|
||||||
removeDoubleQuotes(elfName);
|
if (dirExists(elfName))
|
||||||
|
{
|
||||||
|
log_error("There is a folder named \'%s\' in the current directory instead of a game's ELF.", elfName + 2);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t crc;
|
uint32_t crc;
|
||||||
if (calculateFileCRC32(elfName, &crc) != 0)
|
if (calculateCRC32inChunks(elfName, &crc) != 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
crc = crc ^ 0xFFFFFFFF;
|
crc = crc ^ 0xFFFFFFFF;
|
||||||
@@ -282,260 +207,142 @@ void checkIfElfisClean(char *command)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
void extractPathFromProg(const char *input, char *out_path, char *out_prog)
|
||||||
* Tests if the game uses a seperate elf for test mode
|
|
||||||
* and updates the command line to this elf.
|
|
||||||
*
|
|
||||||
* @param name The command path to run
|
|
||||||
*/
|
|
||||||
void testModePath(char *name)
|
|
||||||
{
|
{
|
||||||
printf("name: %s\n", name);
|
char tmp1[MAX_PATH_LENGTH], tmp2[MAX_PATH_LENGTH];
|
||||||
char *pos;
|
strncpy(tmp1, input, MAX_PATH_LENGTH);
|
||||||
// Check if a different testmode elf is used
|
strncpy(tmp2, input, MAX_PATH_LENGTH);
|
||||||
pos = strstr(name, "hod4M.elf");
|
strncpy(out_prog, basename(tmp1), MAX_PATH_LENGTH);
|
||||||
if (pos != NULL)
|
strncpy(out_path, dirname(tmp2), MAX_PATH_LENGTH);
|
||||||
{
|
|
||||||
strcpy(pos, "hod4testM.elf");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
pos = strstr(name, "hodexRI.elf");
|
|
||||||
if (pos != NULL)
|
|
||||||
{
|
|
||||||
strcpy(pos, "hodextestR.elf");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
pos = strstr(name, "/Jennifer/\"Jennifer");
|
|
||||||
if (pos != NULL)
|
|
||||||
{
|
|
||||||
strcpy(pos, "/Jennifer/\"../JenTest/JenTest");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
pos = strstr(name, "/Jennifer");
|
|
||||||
if (pos != NULL)
|
|
||||||
{
|
|
||||||
strcpy(pos, "/../JenTest/JenTest");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
pos = strstr(name, "apacheM.elf");
|
|
||||||
if (pos != NULL)
|
|
||||||
{
|
|
||||||
strcpy(pos, "apachetestM.elf");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
pos = strstr(name, "/vt3_Lindbergh/\"vt3_Lindbergh");
|
|
||||||
if (pos != NULL)
|
|
||||||
{
|
|
||||||
strcpy(pos, "/vt3_Lindbergh/\"vt3_testmode");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
pos = strstr(name, "/vt3_Lindbergh");
|
|
||||||
if (pos != NULL)
|
|
||||||
{
|
|
||||||
strcpy(pos, "/vt3_testmode");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise add the standard -t to the end
|
|
||||||
strcat(name, " -t");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
void testModePath(char *program)
|
||||||
* @brief Checks if a given path is a valid directory.
|
|
||||||
*
|
|
||||||
* This function uses the stat system call to determine if the provided path
|
|
||||||
* corresponds to a directory.
|
|
||||||
* @param path The path to check.
|
|
||||||
*/
|
|
||||||
bool isValidDirectory(const char *path)
|
|
||||||
{
|
{
|
||||||
struct stat statbuf;
|
if (strcmp(program, "hod4M.elf") == 0)
|
||||||
|
strcpy(program, "hod4testM.elf");
|
||||||
if (stat(path, &statbuf) != 0)
|
else if (strcmp(program, "hodexRI.elf") == 0)
|
||||||
return false;
|
strcpy(program, "hodextestR.elf");
|
||||||
|
else if (strcmp(program, "apacheM.elf") == 0)
|
||||||
return S_ISDIR(statbuf.st_mode);
|
strcpy(program, "apachetestM.elf");
|
||||||
|
else if (strcmp(program, "vt3_Lindbergh") == 0)
|
||||||
|
strcpy(program, "vt3_testmode");
|
||||||
|
else if (strcmp(program, "Jennifer") == 0)
|
||||||
|
strcpy(program, "../JenTest/JenTest");
|
||||||
|
else
|
||||||
|
strcat(program, " -t");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
char *findPreloadLibrary(const char *originalDir, const char *gameDir)
|
||||||
* @brief Finds a suitable 32-bit library folder.
|
|
||||||
*
|
|
||||||
* This function searches for a directory that is likely to contain 32-bit
|
|
||||||
* libraries, based on a predefined list of candidate paths.
|
|
||||||
* @return A dynamically allocated string containing the path to the found
|
|
||||||
* directory, or NULL if no suitable directory is found.
|
|
||||||
*/
|
|
||||||
char *find32bLibFolder(void)
|
|
||||||
{
|
{
|
||||||
const char *folderCandidates[] = {"/app/lib32", "/usr/lib/i386-linux-gnu", "/usr/lib/i686-linux-gnu", "/usr/lib32", "/usr/lib"};
|
static char result[MAX_PATH_LENGTH];
|
||||||
int numCandidates = sizeof(folderCandidates) / sizeof(folderCandidates[0]);
|
char appImageLib[MAX_PATH_LENGTH];
|
||||||
|
snprintf(appImageLib, MAX_PATH_LENGTH, "%s/usr/lib32", getenv("APP_IMG_ROOT"));
|
||||||
|
const char *folderCandidates[] = {"/app/lib32", appImageLib, originalDir, "/usr/lib/i386-linux-gnu", "/usr/lib/i686-linux-gnu",
|
||||||
|
"/usr/lib32", "/usr/lib", NULL};
|
||||||
|
|
||||||
char currentPath[PATH_MAX];
|
for (int i = 0; i < sizeof(folderCandidates) / sizeof(folderCandidates[0]); i++)
|
||||||
struct stat st;
|
|
||||||
char *resultPath = NULL;
|
|
||||||
|
|
||||||
for (int i = 0; i < numCandidates; ++i)
|
|
||||||
{
|
{
|
||||||
int written = snprintf(currentPath, sizeof(currentPath), "%s", folderCandidates[i]);
|
snprintf(result, MAX_PATH_LENGTH, "%s/%s", folderCandidates[i], PRELOAD_FILE_NAME);
|
||||||
|
if (fileExists(result))
|
||||||
if (written < 0 || (size_t)written >= sizeof(currentPath))
|
return result;
|
||||||
continue;
|
|
||||||
|
|
||||||
if (stat(currentPath, &st) == 0 && S_ISDIR(st.st_mode))
|
|
||||||
{
|
|
||||||
size_t pathLen = strlen(currentPath);
|
|
||||||
resultPath = (char *)malloc(pathLen + 1);
|
|
||||||
|
|
||||||
if (resultPath == NULL)
|
|
||||||
{
|
|
||||||
log_fatal("Failed to allocate memory for result path.");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
strcpy(resultPath, currentPath);
|
|
||||||
return resultPath;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (fileExists(PRELOAD_FILE_NAME))
|
||||||
|
return PRELOAD_FILE_NAME;
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
int pathsDiffer(const char *p1, const char *p2)
|
||||||
* @brief Finds the path to the LD_PRELOAD library.
|
|
||||||
*
|
|
||||||
* This function searches for the lindbergh.so library in various locations,
|
|
||||||
* including the current directory and system library folders.
|
|
||||||
* @return A dynamically allocated string containing the path to the library, or an empty string if not found.
|
|
||||||
*/
|
|
||||||
char *findLDPreloadLibrary()
|
|
||||||
{
|
{
|
||||||
char *foundPathPtr = NULL;
|
char real1[MAX_PATH_LENGTH], real2[MAX_PATH_LENGTH];
|
||||||
|
if (!realpath(p1, real1) || !realpath(p2, real2))
|
||||||
char *systemLibFolder = find32bLibFolder();
|
return 1;
|
||||||
|
return strcmp(real1, real2) != 0;
|
||||||
if (systemLibFolder == NULL || systemLibFolder[0] == '\0')
|
|
||||||
{
|
|
||||||
log_error("Error: library folder not found.\n");
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
char fullLibPath[PATH_MAX];
|
|
||||||
|
|
||||||
int lenWritten = snprintf(fullLibPath, sizeof(fullLibPath), "%s/%s", systemLibFolder, PRELOAD_FILE_NAME);
|
|
||||||
|
|
||||||
if (lenWritten < 0 || (size_t)lenWritten >= sizeof(fullLibPath))
|
|
||||||
{
|
|
||||||
log_error("Warning: Constructed path is too long or invalid: %s/%s\n", systemLibFolder, PRELOAD_FILE_NAME);
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (access(PRELOAD_FILE_NAME, F_OK) == 0) // lindbergh.so in current folder
|
|
||||||
{
|
|
||||||
char curDir[MAX_PATH_LEN];
|
|
||||||
if (getcwd(curDir, sizeof(curDir)) == NULL)
|
|
||||||
return "";
|
|
||||||
size_t len = strlen(curDir) + strlen(PRELOAD_FILE_NAME) + 1;
|
|
||||||
foundPathPtr = (char *)malloc(len + 1);
|
|
||||||
if (foundPathPtr == NULL)
|
|
||||||
return "";
|
|
||||||
else
|
|
||||||
snprintf(foundPathPtr, len + 1, "%s/%s", curDir, PRELOAD_FILE_NAME);
|
|
||||||
}
|
|
||||||
else if (access(fullLibPath, F_OK) == 0) // lindbergh.so in system lib folder
|
|
||||||
{
|
|
||||||
foundPathPtr = (char *)malloc(strlen(fullLibPath) + 1);
|
|
||||||
if (foundPathPtr == NULL)
|
|
||||||
return "";
|
|
||||||
else
|
|
||||||
strcpy(foundPathPtr, fullLibPath);
|
|
||||||
}
|
|
||||||
else // lindbergh.so in the ELF folder.
|
|
||||||
{
|
|
||||||
return PRELOAD_FILE_NAME;
|
|
||||||
}
|
|
||||||
return foundPathPtr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
bool hasSpaces(const char *path)
|
||||||
* Makes sure the environment variables are set correctly
|
|
||||||
*
|
|
||||||
* This function sets the LD_LIBRARY_PATH and LD_PRELOAD environment variables
|
|
||||||
* to ensure that the game can find the necessary libraries and preload the
|
|
||||||
* lindbergh.so library.
|
|
||||||
*
|
|
||||||
* @param ldLibPath The path to the LD_PRELOAD library.
|
|
||||||
* @param curDir The current working directory.
|
|
||||||
* @param gameDir The directory where the game is located.
|
|
||||||
* @param zink Flag indicating whether to use Zink.
|
|
||||||
* @param nvidia Flag indicating whether to use NVIDIA GPU.
|
|
||||||
* to run the game.
|
|
||||||
*/
|
|
||||||
void setEnvironmentVariables(char *ldLibPath, char *curDir, char *gameDir, int zink, int nvidia)
|
|
||||||
{
|
{
|
||||||
// Ensure the library path is set correctly
|
if (strchr(path, ' '))
|
||||||
char libraryPath[MAX_PATH_LEN] = {0};
|
return true;
|
||||||
|
|
||||||
const char *currentLibraryPath = getenv(LD_LIBRARY_PATH);
|
return false;
|
||||||
if (currentLibraryPath != NULL)
|
}
|
||||||
|
|
||||||
|
void setEnvironmentVariables(const char *ldLibPath, const char *originalDir, const char *gameDir, int zink, int nvidia,
|
||||||
|
const char *confFilePath)
|
||||||
|
{
|
||||||
|
setenv("LD_PRELOAD", ldLibPath, 1);
|
||||||
|
if (hasSpaces(ldLibPath))
|
||||||
{
|
{
|
||||||
strcat(libraryPath, currentLibraryPath);
|
log_error("The path \'%s\' where lindbergh.so is located cannot contain spaces.", ldLibPath);
|
||||||
strcat(libraryPath, ":");
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
strcat(libraryPath, ".:lib:../lib");
|
char *currentLibraryPath = getenv("LD_LIBRARY_PATH");
|
||||||
|
char newLdLibPath[MAX_PATH_LENGTH * 3] = "";
|
||||||
|
|
||||||
|
if (currentLibraryPath && strlen(currentLibraryPath) > 0)
|
||||||
|
snprintf(newLdLibPath, sizeof(newLdLibPath), "%s:", currentLibraryPath);
|
||||||
|
|
||||||
char *tmpLibPath = dirname(strdup(ldLibPath));
|
char *tmpLibPath = dirname(strdup(ldLibPath));
|
||||||
|
|
||||||
if (strcmp(tmpLibPath, ".") != 0)
|
if (strcmp(tmpLibPath, ".") != 0)
|
||||||
{
|
{
|
||||||
strcat(libraryPath, ":");
|
strcat(newLdLibPath, ":");
|
||||||
strcat(libraryPath, tmpLibPath);
|
strcat(newLdLibPath, tmpLibPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (curDir != NULL && curDir[0] != '\0' && strcmp(curDir, tmpLibPath) != 0)
|
if (originalDir != NULL && originalDir[0] != '\0' && pathsDiffer(originalDir, tmpLibPath) != 0)
|
||||||
{
|
{
|
||||||
strcat(libraryPath, ":");
|
strcat(newLdLibPath, ":");
|
||||||
strcat(libraryPath, curDir);
|
strcat(newLdLibPath, originalDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gameDir != NULL && gameDir[0] != '\0')
|
if (gameDir && gameDir[0] != '\0' && pathsDiffer(originalDir, gameDir) && pathsDiffer(tmpLibPath, gameDir))
|
||||||
{
|
{
|
||||||
strcat(libraryPath, ":");
|
strcat(newLdLibPath, ":");
|
||||||
strcat(libraryPath, gameDir);
|
strcat(newLdLibPath, gameDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
setenv(LD_LIBRARY_PATH, libraryPath, 1);
|
strcat(newLdLibPath, ":.:lib:../lib");
|
||||||
|
|
||||||
// Ensure the preload path is set correctly
|
if (newLdLibPath[0] == ':')
|
||||||
if (strcmp(ldLibPath, "") != 0)
|
memmove(newLdLibPath, newLdLibPath + 1, strlen(newLdLibPath));
|
||||||
setenv(LD_PRELOAD, ldLibPath, 1);
|
|
||||||
else
|
setenv("LD_LIBRARY_PATH", newLdLibPath, 1);
|
||||||
setenv(LD_PRELOAD, PRELOAD_FILE_NAME, 1); // Should not reach here
|
|
||||||
|
if (strlen(confFilePath) > 0)
|
||||||
|
{
|
||||||
|
if (hasSpaces(confFilePath))
|
||||||
|
{
|
||||||
|
log_error("The path \'%s\' for the config file cannot contain spaces.", confFilePath);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
setenv(LINDBERGH_CONFIG_PATH, confFilePath, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (zink && nvidia)
|
||||||
|
{
|
||||||
|
log_error("Cannot pass both, zink and nvidia options at the same time.");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
if (zink)
|
if (zink)
|
||||||
|
{
|
||||||
setenv("MESA_LOADER_DRIVER_OVERRIDE", "zink", 1);
|
setenv("MESA_LOADER_DRIVER_OVERRIDE", "zink", 1);
|
||||||
|
}
|
||||||
|
|
||||||
if (nvidia)
|
if (nvidia)
|
||||||
{
|
{
|
||||||
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);
|
|
||||||
|
char libglDriPath[MAX_PATH_LENGTH];
|
||||||
|
sprintf(libglDriPath, "%s/usr/lib32/dri", getenv("APP_IMG_ROOT"));
|
||||||
|
setenv("LIBGL_DRIVERS_PATH", libglDriPath, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Prints the usage information for the Lindbergh loader.
|
|
||||||
*
|
|
||||||
* This function displays the command-line options and usage instructions for
|
|
||||||
* the Lindbergh loader.
|
|
||||||
* @param argv The command-line arguments array.
|
|
||||||
* Prints the usage for the loader
|
|
||||||
*/
|
|
||||||
void printUsage(char *argv[])
|
void printUsage(char *argv[])
|
||||||
{
|
{
|
||||||
printf("%s [GAME_PATH] [OPTIONS]\n", argv[0]);
|
printf("%s [GAME_PATH] [OPTIONS]\n", argv[0]);
|
||||||
@@ -552,15 +359,12 @@ void printUsage(char *argv[])
|
|||||||
printf(" --gamepath | -g Specifies game path without ELF name\n");
|
printf(" --gamepath | -g Specifies game path without ELF name\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
void printVersion()
|
||||||
* @brief Lists available evdev controllers and their inputs.
|
{
|
||||||
*
|
printf("Lindbergh Loader v%d.%d\n", MAJOR_VERSION, MINOR_VERSION);
|
||||||
* This function initializes the controller system and then iterates through
|
printf("Created by: %s\n", TEAM);
|
||||||
* the available controllers, printing their names and the names of their
|
}
|
||||||
* inputs.
|
|
||||||
* @return EXIT_SUCCESS on success, EXIT_FAILURE on failure.
|
|
||||||
* Lists available evdev controllers and their inputs
|
|
||||||
*/
|
|
||||||
int listControllers()
|
int listControllers()
|
||||||
{
|
{
|
||||||
Controllers controllers;
|
Controllers controllers;
|
||||||
@@ -568,7 +372,7 @@ int listControllers()
|
|||||||
ControllerStatus status = initControllers(&controllers);
|
ControllerStatus status = initControllers(&controllers);
|
||||||
if (status != CONTROLLER_STATUS_SUCCESS)
|
if (status != CONTROLLER_STATUS_SUCCESS)
|
||||||
{
|
{
|
||||||
printf("Failed to list controllers\n");
|
log_error("Failed to list controllers\n");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -585,33 +389,16 @@ int listControllers()
|
|||||||
printf(" - %s\n", controller.inputs[i].inputName);
|
printf(" - %s\n", controller.inputs[i].inputName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stopControllers(&controllers);
|
stopControllers(&controllers);
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Prints the version information of the Lindbergh loader.
|
|
||||||
*
|
|
||||||
* This function displays the version number of the Lindbergh loader and the
|
|
||||||
* names of the team members.
|
|
||||||
*/
|
|
||||||
void printVersion() {
|
|
||||||
printf("Lindbergh Loader v%d.%d\n", MAJOR_VERSION, MINOR_VERSION);
|
|
||||||
printf("Created by: %s\n", TEAM);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Small utility to automatically detect the game and run it without
|
|
||||||
* having to type a long string in.
|
|
||||||
*/
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
char gameELF[128] = {0};
|
if (argc > 1 && strcmp(argv[1], "--version") == 0)
|
||||||
char gameDir[MAX_PATH_LEN] = {0};
|
{
|
||||||
|
|
||||||
if (argc > 1 && strcmp(argv[1], "--version") == 0) {
|
|
||||||
printVersion();
|
printVersion();
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
@@ -626,16 +413,18 @@ int main(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
return listControllers();
|
return listControllers();
|
||||||
}
|
}
|
||||||
// Build up the command to start the game
|
|
||||||
int testMode = false;
|
char passedGamePath[MAX_PATH_LENGTH] = "";
|
||||||
int gdb = false;
|
char forcedGamePath[MAX_PATH_LENGTH] = "";
|
||||||
int zink = false;
|
char forcedGameDir[MAX_PATH_LENGTH] = "";
|
||||||
int nvidia = false;
|
char gameELF[MAX_PATH_LENGTH] = "";
|
||||||
int forceGame = false;
|
char extConfigPath[MAX_PATH_LENGTH] = "";
|
||||||
int segaboot = false;
|
char originalDir[MAX_PATH_LENGTH] = "";
|
||||||
char *extConfigPath = NULL;
|
bool gdb = false;
|
||||||
char *passedGamePath = NULL;
|
bool testMode = false;
|
||||||
char *forcedGamePath = NULL;
|
bool segaboot = false;
|
||||||
|
bool zink = false;
|
||||||
|
bool nvidia = false;
|
||||||
|
|
||||||
for (int i = 1; i < argc; i++)
|
for (int i = 1; i < argc; i++)
|
||||||
{
|
{
|
||||||
@@ -675,158 +464,159 @@ int main(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
extConfigPath = strdup(argv[i + 1]);
|
strncpy(extConfigPath, argv[i + 1], MAX_PATH_LENGTH);
|
||||||
i += 1;
|
i += 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(argv[i], "-g") == 0 || strcmp(argv[i], "--gamepath") == 0)
|
if ((strcmp(argv[i], "-g") == 0 || strcmp(argv[i], "--gamepath") == 0) && i + 1 < argc)
|
||||||
{
|
{
|
||||||
if (i + 1 >= argc)
|
strncpy(passedGamePath, argv[i + 1], MAX_PATH_LENGTH);
|
||||||
{
|
i++;
|
||||||
break;
|
|
||||||
}
|
|
||||||
passedGamePath = strdup(argv[i + 1]);
|
|
||||||
|
|
||||||
i += 1;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Treat the argument as the game name
|
strncpy(forcedGamePath, argv[i], MAX_PATH_LENGTH);
|
||||||
forcedGamePath = strdup(argv[i]);
|
|
||||||
forceGame = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// We save the current dir to return to it later
|
if (!getcwd(originalDir, sizeof(originalDir)))
|
||||||
char curDir[MAX_PATH_LEN];
|
|
||||||
if (getcwd(curDir, sizeof(curDir)) == NULL)
|
|
||||||
{
|
{
|
||||||
log_error("Error: could not get the current directory.");
|
perror("getcwd");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasSpaces(curDir))
|
int useForceCommandPath = strlen(forcedGamePath) > 0;
|
||||||
{
|
bool commandOnlyElf = useForceCommandPath && strchr(forcedGamePath, '/') == NULL;
|
||||||
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};
|
if (useForceCommandPath && !commandOnlyElf)
|
||||||
char *forcedGameDir;
|
|
||||||
char *forcedGameElf;
|
|
||||||
if (forceGame)
|
|
||||||
{
|
{
|
||||||
if (forcedGamePath != NULL)
|
if (!fileExists(forcedGamePath))
|
||||||
{
|
{
|
||||||
forcedGameDir = dirname(strdup(forcedGamePath));
|
log_error("File does not exist: %s\n", forcedGamePath);
|
||||||
forcedGameElf = basename(strdup(forcedGamePath));
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
if (strcmp(forcedGameDir, ".") == 0) // Only the ELF file name was passed.
|
extractPathFromProg(forcedGamePath, forcedGameDir, gameELF);
|
||||||
{
|
if (hasSpaces(forcedGameDir))
|
||||||
if (passedGamePath[0] != '\0')
|
{
|
||||||
snprintf(gameDir, MAX_PATH_LEN, "%s", passedGamePath);
|
log_warn("The path contains spaces, this most likely will cause issues.");
|
||||||
else
|
log_warn("Please, make sure you don't use spaces in the path.");
|
||||||
snprintf(gameDir, MAX_PATH_LEN, "./");
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (passedGamePath != NULL) // ELF with path and also -g option pointing to a folder
|
|
||||||
log_warn("Warning: elf passed with a path, and -g option enabled. Ignoring -g option.");
|
|
||||||
|
|
||||||
snprintf(gameDir, MAX_PATH_LEN, "%s", forcedGameDir);
|
if (!dirExists(forcedGameDir))
|
||||||
}
|
{
|
||||||
|
log_error("Directory does not exist: %s\n", forcedGameDir);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
if (strcmp(forcedGameElf, ".") != 0)
|
chdir(forcedGameDir);
|
||||||
strcpy(gameELF, forcedGameElf);
|
}
|
||||||
// Check if the passed folder is valid
|
else if (strlen(passedGamePath) > 0)
|
||||||
if (!isValidDirectory(gameDir))
|
{
|
||||||
|
if (hasSpaces(passedGamePath))
|
||||||
|
{
|
||||||
|
log_warn("The path contains spaces, this most likely will cause issues.");
|
||||||
|
log_warn("Please, make sure you don't use spaces in the path.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dirExists(passedGamePath))
|
||||||
|
{
|
||||||
|
log_error("Directory does not exist: %s\n", passedGamePath);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
chdir(passedGamePath);
|
||||||
|
|
||||||
|
if (commandOnlyElf)
|
||||||
|
{
|
||||||
|
strncpy(gameELF, forcedGamePath, MAX_PATH_LENGTH);
|
||||||
|
if (!fileExists(gameELF))
|
||||||
{
|
{
|
||||||
log_error("%s is not a valid directory here.", gameDir);
|
log_error("Program '%s' not found in %s\n", gameELF, passedGamePath);
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int i = 0; games[i] && strcmp(games[i], "END") != 0; i++)
|
||||||
|
{
|
||||||
|
if (fileExists(games[i]))
|
||||||
|
{
|
||||||
|
strncpy(gameELF, games[i], MAX_PATH_LENGTH);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strlen(gameELF) == 0)
|
||||||
|
{
|
||||||
|
log_error("No known game file found in %s\n", passedGamePath);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (commandOnlyElf)
|
||||||
|
{
|
||||||
|
strncpy(gameELF, forcedGamePath, MAX_PATH_LENGTH);
|
||||||
|
if (!fileExists(gameELF))
|
||||||
|
{
|
||||||
|
log_error("'%s' not found in current directory\n", gameELF);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Look for the game ELF's
|
for (int i = 0; games[i] && strcmp(games[i], "END") != 0; i++)
|
||||||
struct dirent *ent;
|
|
||||||
DIR *dir;
|
|
||||||
|
|
||||||
if (passedGamePath != NULL && passedGamePath[0] != '\0')
|
|
||||||
{
|
{
|
||||||
snprintf(gameDir, MAX_PATH_LEN, "%s", passedGamePath);
|
if (access(games[i], F_OK) == 0)
|
||||||
|
|
||||||
// Check if the passed folder is valid
|
|
||||||
if (!isValidDirectory(gameDir))
|
|
||||||
{
|
{
|
||||||
log_error("%s is not a valid directory.", gameDir);
|
strncpy(gameELF, games[i], sizeof(gameELF) - 1);
|
||||||
return EXIT_FAILURE;
|
gameELF[sizeof(gameELF) - 1] = '\0';
|
||||||
|
printf("Auto-detected ELF: %s\n", gameELF);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
dir = opendir(gameDir);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
snprintf(gameDir, MAX_PATH_LEN, "%s", curDir);
|
|
||||||
dir = opendir(curDir);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dir == NULL)
|
if (gameELF[0] == '\0')
|
||||||
{
|
{
|
||||||
log_error("Could not list files in current directory.");
|
log_error("No game ELF found in current directory.\n");
|
||||||
|
printUsage(argv);
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool found = false;
|
|
||||||
while ((ent = readdir(dir)) != NULL)
|
|
||||||
{
|
|
||||||
if (ent->d_type != DT_REG)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
int index = 0;
|
|
||||||
while (!found)
|
|
||||||
{
|
|
||||||
if (strcmp(games[index], "END") == 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (strcmp(ent->d_name, games[index]) == 0)
|
|
||||||
{
|
|
||||||
strcpy(gameELF, games[index]);
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
closedir(dir);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (testMode)
|
||||||
|
{
|
||||||
|
testModePath(gameELF);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *targetedGameDir = strlen(forcedGameDir) ? forcedGameDir : passedGamePath;
|
||||||
|
char *lib_path = findPreloadLibrary(originalDir, targetedGameDir);
|
||||||
|
if (!lib_path)
|
||||||
|
{
|
||||||
|
log_error("Error: %s not found in known locations.\n", PRELOAD_FILE_NAME);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
setEnvironmentVariables(lib_path, originalDir, targetedGameDir, zink, nvidia, extConfigPath);
|
||||||
|
|
||||||
if (segaboot)
|
if (segaboot)
|
||||||
{
|
{
|
||||||
strcpy(gameELF, "segaboot");
|
strcpy(gameELF, "segaboot -t");
|
||||||
testMode = true;
|
// testMode = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gameELF[0] == '\0')
|
// Final command
|
||||||
|
char command[MAX_PATH_LENGTH];
|
||||||
|
if (strcmp(gameELF, "../JenTest/JenTest") == 0)
|
||||||
{
|
{
|
||||||
log_error("No lindbergh game found in this directory.");
|
snprintf(command, MAX_PATH_LENGTH, "%s", gameELF);
|
||||||
printUsage(argv);
|
}
|
||||||
return EXIT_FAILURE;
|
else
|
||||||
|
{
|
||||||
|
snprintf(command, MAX_PATH_LENGTH, "./%s", gameELF);
|
||||||
}
|
}
|
||||||
|
|
||||||
sprintf(command, "\"%s/\"%s", gameDir, gameELF);
|
isCleanElf(command);
|
||||||
|
|
||||||
char *ldPreloadLibrary = findLDPreloadLibrary();
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
checkIfElfisClean(command);
|
|
||||||
|
|
||||||
if (gdb)
|
if (gdb)
|
||||||
{
|
{
|
||||||
@@ -836,35 +626,14 @@ int main(int argc, char *argv[])
|
|||||||
strcpy(command, temp);
|
strcpy(command, temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
log_info("Starting $ %s", command);
|
log_info("Starting $ %s", command);
|
||||||
|
|
||||||
if (gameDir[0] != '\0')
|
|
||||||
{
|
|
||||||
if (chdir(gameDir) != 0)
|
|
||||||
{
|
|
||||||
log_error("Could not change to game path.");
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int sysCmd = system(command);
|
int sysCmd = system(command);
|
||||||
|
|
||||||
if (gameDir[0] != '\0')
|
if (chdir(originalDir) != 0)
|
||||||
{
|
{
|
||||||
if (chdir(curDir) != 0)
|
log_error("Could not return to the original directory.");
|
||||||
{
|
return EXIT_FAILURE;
|
||||||
log_error("Could not return to the original directory.");
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return sysCmd;
|
return sysCmd;
|
||||||
|
|||||||
+61
-21
@@ -1314,11 +1314,14 @@ void glVertex3f2SP(GLfloat x, GLfloat y, GLfloat z)
|
|||||||
float AdjOffsetX = OffsetX * scaleZ;
|
float AdjOffsetX = OffsetX * scaleZ;
|
||||||
float AdjOffsetY = OffsetY * scaleZ;
|
float AdjOffsetY = OffsetY * scaleZ;
|
||||||
|
|
||||||
if (z == -3.000000f)
|
if (z == -1.000000f || z == -3.000000f)
|
||||||
{ // videos
|
{
|
||||||
|
// We skip 3d and videos
|
||||||
|
;
|
||||||
}
|
}
|
||||||
else if (z == -1.010000f)
|
else if (z == -1.010000f)
|
||||||
{ // bd main
|
{
|
||||||
|
// bd main
|
||||||
x += AdjOffsetX;
|
x += AdjOffsetX;
|
||||||
y -= AdjOffsetY;
|
y -= AdjOffsetY;
|
||||||
|
|
||||||
@@ -1326,7 +1329,8 @@ void glVertex3f2SP(GLfloat x, GLfloat y, GLfloat z)
|
|||||||
y *= scaleY;
|
y *= scaleY;
|
||||||
}
|
}
|
||||||
else if (z == -1.510000f)
|
else if (z == -1.510000f)
|
||||||
{ // logo - coin/start - 2D
|
{
|
||||||
|
// logo - coin/start - 2D
|
||||||
if (curTextureID == 497) // right
|
if (curTextureID == 497) // right
|
||||||
{
|
{
|
||||||
x -= OffsetX;
|
x -= OffsetX;
|
||||||
@@ -1336,6 +1340,7 @@ void glVertex3f2SP(GLfloat x, GLfloat y, GLfloat z)
|
|||||||
}
|
}
|
||||||
else if (curTextureID == 498)
|
else if (curTextureID == 498)
|
||||||
{ // deadend
|
{ // deadend
|
||||||
|
;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1347,7 +1352,8 @@ void glVertex3f2SP(GLfloat x, GLfloat y, GLfloat z)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (z == -1.460000f)
|
else if (z == -1.460000f)
|
||||||
{ // 2D title
|
{
|
||||||
|
// 2D title
|
||||||
x += AdjOffsetX;
|
x += AdjOffsetX;
|
||||||
y -= AdjOffsetY;
|
y -= AdjOffsetY;
|
||||||
|
|
||||||
@@ -1355,7 +1361,8 @@ void glVertex3f2SP(GLfloat x, GLfloat y, GLfloat z)
|
|||||||
y *= scaleY;
|
y *= scaleY;
|
||||||
}
|
}
|
||||||
else if (z == -1.490000f)
|
else if (z == -1.490000f)
|
||||||
{ // 2D title
|
{
|
||||||
|
// 2D title
|
||||||
x += AdjOffsetX;
|
x += AdjOffsetX;
|
||||||
y -= AdjOffsetY;
|
y -= AdjOffsetY;
|
||||||
|
|
||||||
@@ -1363,7 +1370,8 @@ void glVertex3f2SP(GLfloat x, GLfloat y, GLfloat z)
|
|||||||
y *= scaleY;
|
y *= scaleY;
|
||||||
}
|
}
|
||||||
else if (z == -1.500000f)
|
else if (z == -1.500000f)
|
||||||
{ // 2D title
|
{
|
||||||
|
// 2D title
|
||||||
x += AdjOffsetX;
|
x += AdjOffsetX;
|
||||||
y -= AdjOffsetY;
|
y -= AdjOffsetY;
|
||||||
|
|
||||||
@@ -1371,7 +1379,8 @@ void glVertex3f2SP(GLfloat x, GLfloat y, GLfloat z)
|
|||||||
y *= scaleY;
|
y *= scaleY;
|
||||||
}
|
}
|
||||||
else if (z == -1.310000f)
|
else if (z == -1.310000f)
|
||||||
{ // 2D
|
{
|
||||||
|
// 2D
|
||||||
x += AdjOffsetX;
|
x += AdjOffsetX;
|
||||||
y -= AdjOffsetY;
|
y -= AdjOffsetY;
|
||||||
|
|
||||||
@@ -1379,7 +1388,8 @@ void glVertex3f2SP(GLfloat x, GLfloat y, GLfloat z)
|
|||||||
y *= scaleY;
|
y *= scaleY;
|
||||||
}
|
}
|
||||||
else if (z == -1.210000f)
|
else if (z == -1.210000f)
|
||||||
{ // 2D
|
{
|
||||||
|
// 2D
|
||||||
x += AdjOffsetX;
|
x += AdjOffsetX;
|
||||||
y -= AdjOffsetY;
|
y -= AdjOffsetY;
|
||||||
|
|
||||||
@@ -1387,7 +1397,8 @@ void glVertex3f2SP(GLfloat x, GLfloat y, GLfloat z)
|
|||||||
y *= scaleY;
|
y *= scaleY;
|
||||||
}
|
}
|
||||||
else if (z == -1.5109999180f)
|
else if (z == -1.5109999180f)
|
||||||
{ // 2D
|
{
|
||||||
|
// 2D
|
||||||
x += AdjOffsetX;
|
x += AdjOffsetX;
|
||||||
y -= AdjOffsetY;
|
y -= AdjOffsetY;
|
||||||
|
|
||||||
@@ -1395,11 +1406,11 @@ void glVertex3f2SP(GLfloat x, GLfloat y, GLfloat z)
|
|||||||
y *= scaleY;
|
y *= scaleY;
|
||||||
}
|
}
|
||||||
else if (z == -1.200000f)
|
else if (z == -1.200000f)
|
||||||
{ // target - select
|
{
|
||||||
|
// target - select
|
||||||
if (curTextureID == 454 || curTextureID == 461 || curTextureID == 456)
|
if (curTextureID == 454 || curTextureID == 461 || curTextureID == 456)
|
||||||
{ // 457 X - 454 461 456 O
|
{
|
||||||
|
// 457 X - 454 461 456 O
|
||||||
if (myEnableScaling)
|
if (myEnableScaling)
|
||||||
{
|
{
|
||||||
x += AdjOffsetX;
|
x += AdjOffsetX;
|
||||||
@@ -1411,7 +1422,8 @@ void glVertex3f2SP(GLfloat x, GLfloat y, GLfloat z)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (z == -1.710000f)
|
else if (z == -1.710000f)
|
||||||
{ // 2D
|
{
|
||||||
|
// 2D
|
||||||
x += AdjOffsetX;
|
x += AdjOffsetX;
|
||||||
y -= AdjOffsetY;
|
y -= AdjOffsetY;
|
||||||
|
|
||||||
@@ -1419,16 +1431,14 @@ void glVertex3f2SP(GLfloat x, GLfloat y, GLfloat z)
|
|||||||
y *= scaleY;
|
y *= scaleY;
|
||||||
}
|
}
|
||||||
else if (z > -1.85f)
|
else if (z > -1.85f)
|
||||||
{ // 2d
|
{
|
||||||
|
// 2d
|
||||||
x += AdjOffsetX;
|
x += AdjOffsetX;
|
||||||
y -= AdjOffsetY;
|
y -= AdjOffsetY;
|
||||||
|
|
||||||
x *= scaleX;
|
x *= scaleX;
|
||||||
y *= scaleY;
|
y *= scaleY;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
_glVertex3f(x, y, z);
|
_glVertex3f(x, y, z);
|
||||||
}
|
}
|
||||||
@@ -1462,6 +1472,38 @@ void glVertex3fHarley(GLfloat x, GLfloat y, GLfloat z)
|
|||||||
_glVertex3f(x, y, z);
|
_glVertex3f(x, y, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void glVertex3fHodEx(GLfloat x, GLfloat y, GLfloat z)
|
||||||
|
{
|
||||||
|
int (*_glVertex3f)(GLfloat x, GLfloat y, GLfloat z) = dlsym(RTLD_NEXT, "glVertex3f");
|
||||||
|
|
||||||
|
float scaleX = 600.0 / gWidth;
|
||||||
|
float scaleY = 240.0 / gHeight;
|
||||||
|
|
||||||
|
if (z == -1.210000f && (y == 0.0035231018f || y == -0.0152667547f || y == -0.0209428426f || // coin/start
|
||||||
|
y == -0.0397327021f || y == -0.0454087853f || y == -0.0641986430f || y == -0.0790739134f ||
|
||||||
|
y == -0.0931663215f || y == -0.0692875385f || y == -0.0833799466f ||
|
||||||
|
|
||||||
|
y == 0.0456045270f || y == 0.0268146675f || y == 0.0211385805f || y == 0.0023487248f || y == -0.0033273622f ||
|
||||||
|
y == -0.0221172161f || y == -0.0787803382f || y == -0.0934598967f ||
|
||||||
|
|
||||||
|
y == 0.0524549857f || y == 0.0336651318f || y == 0.0279890448f || y == 0.0091991890f
|
||||||
|
|
||||||
|
))
|
||||||
|
{
|
||||||
|
|
||||||
|
x += scaleX;
|
||||||
|
y -= scaleY;
|
||||||
|
}
|
||||||
|
else if (y == 0.0042380672f || y == -0.0169522688f || y == 0.0360235684f || y == 0.0148332343f)
|
||||||
|
{ // Main bd
|
||||||
|
|
||||||
|
x += scaleX;
|
||||||
|
y -= scaleY;
|
||||||
|
}
|
||||||
|
|
||||||
|
_glVertex3f(x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
int initResolutionPatches()
|
int initResolutionPatches()
|
||||||
{
|
{
|
||||||
gWidth = getConfig()->width;
|
gWidth = getConfig()->width;
|
||||||
@@ -2828,8 +2870,6 @@ int initResolutionPatches()
|
|||||||
patchMemory(0x081775d2, "b801000000"); // target
|
patchMemory(0x081775d2, "b801000000"); // target
|
||||||
patchMemory(0x0804e5d2, "909090909090");
|
patchMemory(0x0804e5d2, "909090909090");
|
||||||
|
|
||||||
// detourFunction(0x0804d254, glVertex3fHODEX);
|
|
||||||
|
|
||||||
setVariable(0x087aa080, gWidth); // render res
|
setVariable(0x087aa080, gWidth); // render res
|
||||||
patchMemory(0x0804e60c, "909090909090");
|
patchMemory(0x0804e60c, "909090909090");
|
||||||
patchMemory(0x0828cc2f, "909090909090");
|
patchMemory(0x0828cc2f, "909090909090");
|
||||||
|
|||||||
@@ -1547,7 +1547,9 @@ char *findLibCg()
|
|||||||
const char *foundPath = NULL;
|
const char *foundPath = NULL;
|
||||||
FILE *libCgF = NULL;
|
FILE *libCgF = NULL;
|
||||||
|
|
||||||
char *pathsToCheck[] = {NULL, "/app/lib32/libCg2.so", "./libCg.so", NULL};
|
char appImageLib[MAX_PATH_LENGTH];
|
||||||
|
snprintf(appImageLib, MAX_PATH_LENGTH, "%s/usr/lib32/libCg2.so", getenv("APP_IMG_ROOT"));
|
||||||
|
char *pathsToCheck[] = {NULL, "/app/lib32/libCg2.so", appImageLib, "./libCg.so", NULL};
|
||||||
|
|
||||||
if (strcmp(getConfig()->libCgPath, "") != 0)
|
if (strcmp(getConfig()->libCgPath, "") != 0)
|
||||||
{
|
{
|
||||||
@@ -1559,13 +1561,13 @@ char *findLibCg()
|
|||||||
{
|
{
|
||||||
size_t pathLen = strlen(currentDir) + strlen("/libCg.so") + 1;
|
size_t pathLen = strlen(currentDir) + strlen("/libCg.so") + 1;
|
||||||
pathsToCheck[3] = malloc(pathLen);
|
pathsToCheck[3] = malloc(pathLen);
|
||||||
if (pathsToCheck[3] != NULL)
|
if (pathsToCheck[4] != NULL)
|
||||||
{
|
{
|
||||||
snprintf(pathsToCheck[3], pathLen, "%s/%s", currentDir, "libCg.so");
|
snprintf(pathsToCheck[4], pathLen, "%s/%s", currentDir, "libCg.so");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < 4; ++i)
|
for (int i = 0; i < 5; ++i)
|
||||||
{
|
{
|
||||||
if (pathsToCheck[i] == NULL)
|
if (pathsToCheck[i] == NULL)
|
||||||
continue;
|
continue;
|
||||||
@@ -1577,9 +1579,9 @@ char *findLibCg()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (foundPath != pathsToCheck[3] && pathsToCheck[3] != NULL)
|
if (foundPath != pathsToCheck[4] && pathsToCheck[4] != NULL)
|
||||||
{
|
{
|
||||||
free(pathsToCheck[3]);
|
free(pathsToCheck[4]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (foundPath == NULL)
|
if (foundPath == NULL)
|
||||||
|
|||||||
Reference in New Issue
Block a user