Compare commits

..
11 Commits
Author SHA1 Message Date
dkeruza 72f70ccda1 Merge pull request #90 from dkeruza-neo/master
2Spicy error in the scaling code.
2025-04-06 16:14:12 -04:00
dkeruza-neo 0a29307870 2Spicy error in the scaling code. 2025-04-06 16:12:48 -04:00
dkeruza-neo d202f31717 fixed changelog 2025-04-06 16:12:48 -04:00
dkeruza a68dcbbdcf Merge pull request #88 from dkeruza-neo/master
Resolution patches for 2Spicy and HOD-Ex
2025-04-06 13:28:44 -04:00
dkeruza 75642e285e Merge branch 'master' into master 2025-04-06 13:22:14 -04:00
dkeruza-neo d9d076f120 Added 2Spicy and HOD-Ex resolution patches. 2025-04-06 13:11:58 -04:00
dkeruza a5633bbf1d Fixed an indentation in the Flatpak script. 2025-04-06 12:38:17 -04:00
dkeruza d72ac379ea Fixed Flatpak script.
There was a bug in the script preventing it to launch.
2025-04-06 11:34:49 -04:00
dkeruza-neo c5c44ce395 Fixed flatpak build script. 2025-04-06 11:33:14 -04:00
dkeruza 988a9ee6e3 Merge pull request #86 from dkeruza-neo/master
libCg.so path, better folder redirection.
2025-04-06 04:31:52 -04:00
dkeruza-neo ea19a688cc Recompiled shaders redirectio, and lib path. 2025-04-06 04:30:09 -04:00
14 changed files with 884 additions and 377 deletions
+13
View File
@@ -2,6 +2,19 @@
All notable changes to this project will be documented in this file.
## [2.0.11]
### Added
- Resolution patches for 2Spicy and HOD-Ex
- Code clean up.
### Fixed
- 2Spicy error in the scaling code.
## [2.0.10]
### Added
- Config option to specify a path for the library libCg.so required for some shader compilation.
- Improved folder patching for recompiled shaders (2Spicy, Rambo, Harly and HOD-EX).
- Cleaned a bit of lindbergh elf.
## [2.0.9]
- lindbergh elf mostly redone to make the loader work as a stand alone mode (read guide.md).
+4
View File
@@ -72,6 +72,10 @@ EMULATE_CARDREADER AUTO
# Define the path to the eeprom.bin file
# EEPROM_PATH eeprom.bin
# If set, the library libCG.so needed for 2Spicy, Harley, Rambo and HOD-Ex shader recompilation
# will be loaded from the specifyied location. (include the name of file in the location)
# LIBCG_PATH /my/file/location/myLibCg.so
# Set the GPU vendor (0 = Autodetect / 1 = NVidia / 2 = AMD / 3 = ATI(AMD-PRO) / 4 = Intel / 5 = Unknown)
# GPU_VENDOR 0
+54 -103
View File
@@ -1,18 +1,17 @@
app-id: com.github.lindberghloader
runtime: org.freedesktop.Platform
runtime-version: &runtime-version '24.08' # Define runtime version alias
runtime-version: &runtime-version '24.08'
sdk: org.freedesktop.Sdk
# Define reusable aliases
x-gl-versions: &gl-versions '24.08;1.4' # Define GL versions list alias
x-gl-versions: &gl-versions '24.08;1.4'
x-gl-merge-dirs: &gl-merge-dirs vulkan/icd.d;glvnd/egl_vendor.d;egl/egl_external_platform.d;OpenCL/vendors;lib/dri;lib/d3d;lib/gbm;vulkan/explicit_layer.d;vulkan/implicit_layer.d # Define GL merge dirs alias
x-i386-build-options: &i386-build-options # Define 32-bit build options alias
libdir: /app/lib32 # Default library install dir for autotools/meson etc.
x-i386-build-options: &i386-build-options
libdir: /app/lib32
env:
CC: /usr/lib/sdk/toolchain-i386/bin/i686-unknown-linux-gnu-gcc
CXX: /usr/lib/sdk/toolchain-i386/bin/i686-unknown-linux-gnu-g++
LD: /usr/lib/sdk/toolchain-i386/bin/i686-unknown-linux-gnu-ld
LDFLAGS: "-L/app/lib32" # Add custom lib dir to linker search path during build
LDFLAGS: "-L/app/lib32"
command: lindbergh
@@ -21,41 +20,32 @@ sdk-extensions:
- org.freedesktop.Sdk.Extension.toolchain-i386
- org.freedesktop.Sdk.Compat.i386
# Runtime arguments and permissions
finish-args:
# Environment variables needed at runtime
- --env=LD_LIBRARY_PATH=/app/lib32:$LD_LIBRARY_PATH # Make custom 32-bit libs findable
- --env=LD_LIBRARY_PATH=/app/lib32:$LD_LIBRARY_PATH
- --env=PATH=/app/bin:/usr/bin
# Permissions
- --allow=multiarch # Needed for running 32-bit code
- --allow=multiarch
- --share=ipc
- --share=network
- --socket=x11
- --socket=wayland
- --socket=pulseaudio
# WARNING: --device=all grants broad hardware access. Consider using --device=dri and specific devices if possible.
- --device=all
# Filesystem access - adjust path as needed
- --socket=pulseaudio
- --filesystem=~/Games
# Runtime extensions automatically downloaded and installed with the app
# Runtime extensions automatically downloaded and installed with the app (For some reason does not work)
add-extensions:
# 32-bit compatibility libraries from the runtime
org.freedesktop.Platform.Compat.i386:
directory: lib/i386-linux-gnu
version: *runtime-version # Match the main runtime version
# no-autodownload removed (or set to false) to ensure installation
version: *runtime-version
# 32-bit graphics driver extension
org.freedesktop.Platform.GL32:
directory: lib/i386-linux-gnu/GL
versions: *gl-versions # Use defined GL versions list
versions: *gl-versions
subdirectories: true
# no-autodownload removed (or set to false) to ensure installation
autodelete: false
add-ld-path: lib
merge-dirs: *gl-merge-dirs # Use defined merge dirs list
# Conditions for downloading and enabling the GL driver extension
merge-dirs: *gl-merge-dirs
download-if: active-gl-driver
enable-if: active-gl-driver
autoprune-unless: active-gl-driver
@@ -75,12 +65,11 @@ modules:
- name: libGLU
buildsystem: autotools
config-opts:
- --host=i686-unknown-linux-gnu # Specify 32-bit target host
- --prefix=/app # Base install prefix
# --libdir=/app/lib32 should be handled by build-options->libdir
- --host=i686-unknown-linux-gnu
- --prefix=/app
build-options:
arch:
x86_64: *i386-build-options # Apply 32-bit build options on 64-bit host
x86_64: *i386-build-options
sources:
- type: archive
url: https://mesa.freedesktop.org/archive/glu/glu-9.0.2.tar.xz
@@ -91,15 +80,15 @@ modules:
buildsystem: cmake
config-opts:
- -DCMAKE_BUILD_TYPE=Release
- -DCMAKE_INSTALL_PREFIX=/app # Base install prefix
- -DCMAKE_INSTALL_LIBDIR=/app/lib32 # Explicitly set library install dir for CMake
- -DCMAKE_INSTALL_PREFIX=/app
- -DCMAKE_INSTALL_LIBDIR=/app/lib32
sources:
- type: archive
url: https://downloads.sourceforge.net/freeglut/freeglut-3.2.2.tar.gz
sha256: c5944a082df0bba96b5756dddb1f75d0cd72ce27b5395c6c1dde85c2ff297a50
build-options:
arch:
x86_64: *i386-build-options # Apply 32-bit build options
x86_64: *i386-build-options
# Build 32-bit libFAudio (dynamic)
- name: libFAudio-Dynamic
@@ -107,40 +96,37 @@ modules:
config-opts:
- -DCMAKE_BUILD_TYPE=Release
- -DCMAKE_INSTALL_PREFIX=/app
- -DBUILD_SDL3=off # Assuming SDL3 integration is not needed
- -DCMAKE_INSTALL_LIBDIR=/app/lib32 # Explicitly set library install dir
- -DBUILD_SDL3=off
- -DCMAKE_INSTALL_LIBDIR=/app/lib32
build-options:
arch:
x86_64: *i386-build-options # Apply 32-bit build options
x86_64: *i386-build-options
env:
# Specific flags needed for FAudio 32-bit build?
CFLAGS: "-m32 -mstackrealign"
CXXFLAGS: "-m32 -mstackrealign"
sources:
- type: git
url: https://github.com/FNA-XNA/FAudio.git
tag: "24.12" # Using a specific tag
tag: "24.12"
# Build 32-bit libXmu
- name: libxmu
buildsystem: autotools
config-opts:
# --libdir=/app/lib32 should be handled by build-options->libdir
- --prefix=/app
- --with-shared # Ensure shared library is built
- --with-shared
sources:
- type: archive
url: https://xorg.freedesktop.org/releases/individual/lib/libXmu-1.2.1.tar.gz
sha256: bf0902583dd1123856c11e0a5085bd3c6e9886fbbd44954464975fd7d52eb599
build-options:
arch:
x86_64: *i386-build-options # Apply 32-bit build options (Standardized)
x86_64: *i386-build-options
# Build 32-bit libmd
- name: libmd
buildsystem: autotools
config-opts:
# --libdir=/app/lib32 should be handled by build-options->libdir
- --prefix=/app
sources:
- type: archive
@@ -148,13 +134,12 @@ modules:
sha256: 1bd6aa42275313af3141c7cf2e5b964e8b1fd488025caf2f971f43b00776b332
build-options:
arch:
x86_64: *i386-build-options # Apply 32-bit build options
x86_64: *i386-build-options
# Build 32-bit libbsd
- name: libbsd
buildsystem: autotools
config-opts:
# --libdir=/app/lib32 should be handled by build-options->libdir
- --prefix=/app
sources:
- type: archive
@@ -162,14 +147,12 @@ modules:
sha256: b88cc9163d0c652aaf39a99991d974ddba1c3a9711db8f1b5838af2a14731014
build-options:
arch:
x86_64: *i386-build-options # Apply 32-bit build options
x86_64: *i386-build-options
# Build 32-bit ncurses (very old version)
- name: ncurses
# WARNING: ncurses 5.9 is very old. Consider updating if possible.
buildsystem: autotools
config-opts:
# --libdir=/app/lib32 should be handled by build-options->libdir
- --prefix=/app
- --with-shared
- --without-debug
@@ -178,24 +161,22 @@ modules:
url: https://ftp.gnu.org/pub/gnu/ncurses/ncurses-5.9.tar.gz
sha256: 9046298fb440324c9d4135ecea7879ffed8546dd1b58e59430ea07a4633f563b
- type: patch
path: ./assets/ncurses-5.9.patch # Assuming this patch is necessary
path: ./assets/ncurses-5.9.patch
build-options:
arch:
x86_64: *i386-build-options # Apply 32-bit build options
x86_64: *i386-build-options
env:
CPPFLAGS: "-P" # Often needed for ncurses builds
CXXFLAGS: "-std=c++14" # Is C++14 really needed for ncurses build? Check this.
CPPFLAGS: "-P"
CXXFLAGS: "-std=c++14"
# Install pre-built 32-bit Nvidia Cg Toolkit (old)
- name: nvidia-cg-toolkit
# WARNING: Cg Toolkit is deprecated and old.
buildsystem: simple
build-commands:
- install -Dm755 usr/lib/libCg.so /app/lib32/libCg.so
- install -Dm755 usr/lib/libCgGL.so /app/lib32/libCgGL.so
sources:
- type: archive
# Consider hosting this locally or finding a more reliable source if possible
url: http://developer.download.nvidia.com/cg/Cg_3.1/Cg-3.1_April2012_x86.tgz
sha256: cef3591e436f528852db0e8c145d3842f920e0c89bcfb219c466797cb7b18879
@@ -203,32 +184,27 @@ modules:
- name: libsndio-dynamic
buildsystem: autotools
config-opts:
# --libdir=/app/lib32 should be handled by build-options->libdir
- --prefix=/app
- --enable-dynamic # Build shared library
# - --disable-static # Don't build static library
- --enable-alsa # Enable ALSA backend
- --enable-dynamic
- --enable-alsa
sources:
- type: archive
url: https://www.sndio.org/sndio-1.10.0.tar.gz
sha256: bebd3bfd01c50c9376cf3e7814b9379bed9e17d0393b5113b7eb7a3d0d038c54
build-options:
arch:
x86_64: *i386-build-options # Apply 32-bit build options
x86_64: *i386-build-options
# Build 32-bit libopenal (old version)
- name: libopenal
# WARNING: OpenAL Soft 1.17.2 is quite old. Consider updating.
buildsystem: cmake
config-opts:
- -DCMAKE_INSTALL_PREFIX=/app
- -DCMAKE_INSTALL_LIBDIR=/app/lib32 # Explicitly set library install dir
# Backend selection
- -DCMAKE_INSTALL_LIBDIR=/app/lib32
- -DALSOFT_BACKEND_PULSEAUDIO=ON
- -DALSOFT_BACKEND_ALSA=ON
- -DALSOFT_BACKEND_JACK=OFF
- -DALSOFT_BACKEND_SNDIO=ON # Depends on libsndio-dynamic
# Point to the previously built sndio library/headers
- -DALSOFT_BACKEND_SNDIO=ON
- -DSOUNDIO_INCLUDE_DIR=/app/include
- -DSOUNDIO_LIBRARY=/app/lib32/libsndio.so
sources:
@@ -237,29 +213,20 @@ modules:
sha256: 11ea176f6cbf9763dbce0953dd77ab72d032b4ad95f07afffb91844abb174033
build-options:
arch:
x86_64: *i386-build-options # Apply 32-bit build options
x86_64: *i386-build-options
env:
# Specific flags needed for OpenAL 32-bit build?
CFLAGS: "-m32 -mstackrealign"
CXXFLAGS: "-m32 -std=c++14 -mstackrealign" # Needs C++14?
CXXFLAGS: "-m32 -std=c++14 -mstackrealign"
# Build 32-bit OpenSSL (extremely old and insecure version)
- name: openssl
# CRITICAL WARNING: OpenSSL 0.9.7 is extremely old, unsupported, and has known vulnerabilities.
# This should be updated or removed if at all possible. Using it poses a security risk.
buildsystem: simple
build-commands:
# Configure for 32-bit Linux (pentium target), shared libs, install to /app
- ./Configure --prefix=/app --openssldir=/app/etc/ssl shared 386 no-asm no-krb5 linux-pentium
# Build using the 32-bit toolchain
# - make -j$(nproc) CC=/usr/lib/sdk/toolchain-i386/bin/i686-unknown-linux-gnu-gcc RANLIB=/usr/lib/sdk/toolchain-i386/bin/i686-unknown-linux-gnu-ranlib
- make CC=/usr/lib/sdk/toolchain-i386/bin/i686-unknown-linux-gnu-gcc RANLIB=/usr/lib/sdk/toolchain-i386/bin/i686-unknown-linux-gnu-ranlib
# Manually move built libraries to the target lib32 directory
- install -d /app/lib32
- mv libcrypto.so* /app/lib32/
- mv libssl.so* /app/lib32/
# Install headers (needed by other modules?) - will be cleaned later if not
# - make install_hdrs
sources:
- type: archive
url: https://github.com/openssl/openssl/archive/refs/tags/OpenSSL_0_9_7.tar.gz
@@ -269,23 +236,16 @@ modules:
- name: libpcsclite
buildsystem: meson
config-opts:
# --libdir=/app/lib32 should be handled by build-options->libdir
# - -Dprefix=/app
- -Dpolkit=false # Disable polkit integration
- -Dlibsystemd=false # Disable systemd integration
# -Dudevrulesdir=no # Might be needed if it tries to install udev rules
- -Dpolkit=false
- -Dlibsystemd=false
build-options:
arch:
x86_64: *i386-build-options # Apply 32-bit build options
x86_64: *i386-build-options
env:
# Meson cross-compilation setup often requires explicit flags and paths
CFLAGS: "-m32"
CXXFLAGS: "-m32"
LDFLAGS: "-m32 -L/app/lib32" # Ensure LDFLAGS includes -L/app/lib32
# Point pkg-config to custom and SDK 32-bit locations
LDFLAGS: "-m32 -L/app/lib32"
PKG_CONFIG_PATH: "/app/lib32/pkgconfig:/usr/lib/i386-linux-gnu/pkgconfig:/usr/lib/sdk/toolchain-i386/lib/pkgconfig"
# LD_LIBRARY_PATH might not be needed here if LDFLAGS is sufficient for linking stage
# LD_LIBRARY_PATH: "/app/lib32:/usr/lib/i386-linux-gnu/pkgconfig:$LD_LIBRARY_PATH"
sources:
- type: archive
url: https://pcsclite.apdu.fr/files/pcsc-lite-2.3.1.tar.xz
@@ -295,59 +255,50 @@ modules:
- name: lindbergh-loader
buildsystem: simple
build-commands:
# Ensure make finds the libraries built in previous steps
- export LD_LIBRARY_PATH=/app/lib32:$LD_LIBRARY_PATH
- make -j$(nproc) # Build the application
# Install application binary and required libraries/symlinks
- make -j$(nproc)
- mkdir -p /app/lib/i386-linux-gnu
- mkdir -p /app/lib/i386-linux-gnu/GL
- install -Dm755 ./build/lindbergh /app/bin/
- install -Dm755 ./build/lindbergh.so /app/lib32/
- install -Dm755 ./build/libsegaapi.so /app/lib32/
- install -Dm755 ./build/libkswapapi.so /app/lib32/
- install -Dm755 ./build/libposixtime.so /app/lib32/
# Install bundled library? Make sure this doesn't conflict with nvidia-cg-toolkit
- install -Dm755 ./libs/libCg.so /app/lib32/libCg2.so
# Create necessary symlinks in the lib32 directory
- ln -sf libposixtime.so /app/lib32/libposixtime.so.1
- ln -sf libposixtime.so /app/lib32/libposixtime.so.2.4
- ln -sf libopenal.so.1 /app/lib32/libopenal.so.0 # Link to correct openal versioned so
- ln -sf libopenal.so.1 /app/lib32/libopenal.so.0
- ln -sf libkswapapi.so /app/lib32/libGLcore.so.1
- ln -sf libkswapapi.so /app/lib32/libnvidia-tls.so.1
- mv /app/lib/libopenal* /app/lib32/
build-options:
arch:
x86_64: *i386-build-options # Apply 32-bit build options (for env vars mainly)
x86_64: *i386-build-options
sources:
- type: dir
path: ../.. # Assumes source code is one level up from manifest directory
path: ../..
# Setup dynamic linker configuration
- name: bundle-setup
buildsystem: simple
build-commands:
# Install ld.so.conf to ensure /app/lib32 is searched by the dynamic linker
- install -Dm644 -t /app/etc ld.so.conf
sources:
- type: file
path: ./assets/ld.so.conf # Assumes this file contains "/app/lib32"
path: ./assets/ld.so.conf
# Cleanup unnecessary files to reduce final flatpak size
- name: cleanup
buildsystem: simple
build-commands:
# Remove static libraries and libtool archives
- find /app/lib32 -name '*.a' -type f -delete
- find /app/lib32 -name '*.la' -type f -delete
# Remove any executables other than the main command
#- find /app/bin -mindepth 1 ! -name "lindbergh" -exec rm -f {} \;
# Remove development/debugging/documentation files
#- rm -rf /app/lib/pkgconfig /app/lib32/pkgconfig /app/share/pkgconfig
#- rm -rf /app/lib32/cmake /app/lib/debug /app/include /app/man /app/share /app/etc/bash_completion.d
# Remove specific libraries if they are not needed at runtime
# (These were in the original, assuming they are safe to remove)
- find /app/bin -mindepth 1 ! -name "lindbergh" -exec rm -f {} \;
- rm -rf /app/lib/pkgconfig /app/lib32/pkgconfig /app/share/pkgconfig
- rm -rf /app/lib32/cmake /app/lib/debug /app/include /app/man /app/share /app/etc/bash_completion.d
- rm -f /app/lib32/libmenu.so*
- rm -f /app/lib32/libform.so*
- rm -f /app/lib32/libpanel.so*
- rm -f /app/lib32/libXmuu.so*
#- rm -f /app/lib32/libbsd.so*
# Remove ncurses terminfo db if not needed
- rm -rf /app/lib/terminfo
- rm -f /app/lib32/libbsd.so*
- rm -rf /app/lib/terminfo
+183 -182
View File
@@ -29,10 +29,10 @@
typedef struct
{
uint32_t srcAddress;
uint32_t srcSize;
uint32_t destAddress;
uint32_t destSize;
uint32_t srcAddress;
uint32_t srcSize;
uint32_t destAddress;
uint32_t destSize;
} BaseboardCommand;
BaseboardCommand jvsCommand = {0};
@@ -40,16 +40,16 @@ BaseboardCommand serialCommand = {0};
typedef struct
{
uint32_t *data;
uint32_t offset;
uint32_t size;
uint32_t *data;
uint32_t offset;
uint32_t size;
} readData_t;
typedef struct
{
uint32_t offset;
uint32_t *data;
uint32_t size;
uint32_t offset;
uint32_t *data;
uint32_t size;
} writeData_t;
FILE *sram = NULL;
@@ -63,224 +63,225 @@ int jvsPacketSize = -1;
int initBaseboard()
{
char *sramPath = getConfig()->sramPath;
char *sramPath = getConfig()->sramPath;
sram = fopen(sramPath, "a");
sram = fopen(sramPath, "a");
// Create file if it doesn't exist
if (sram == NULL)
{
printf("Error: Cannot open %s\n", sramPath);
return 1;
}
fclose(sram);
sram = fopen(sramPath, "rb+");
fseek(sram, 0, SEEK_SET);
if (getConfig()->emulateJVS == 0 && strcmp(getConfig()->jvsPath, "none") != 0)
{
jvsFileDescriptor = openJVSSerial(getConfig()->jvsPath);
if (jvsFileDescriptor < 0)
// Create file if it doesn't exist
if (sram == NULL)
{
printf("Error: Failed to open %s for JVS\n", getConfig()->jvsPath);
return -1;
printf("Error: Cannot open %s\n", sramPath);
return 1;
}
fclose(sram);
sram = fopen(sramPath, "rb+");
fseek(sram, 0, SEEK_SET);
if (getConfig()->emulateJVS == 0 && strcmp(getConfig()->jvsPath, "none") != 0)
{
jvsFileDescriptor = openJVSSerial(getConfig()->jvsPath);
if (jvsFileDescriptor < 0)
{
printf("Error: Failed to open %s for JVS\n", getConfig()->jvsPath);
return -1;
}
initJVSSerial(jvsFileDescriptor);
startJVSFrameThread(&jvsFileDescriptor);
}
initJVSSerial(jvsFileDescriptor);
startJVSFrameThread(&jvsFileDescriptor);
}
return 0;
return 0;
}
ssize_t baseboardRead(int fd, void *buf, size_t count)
{
memcpy(buf, &sharedMemory[sharedMemoryIndex], count);
return count;
memcpy(buf, &sharedMemory[sharedMemoryIndex], count);
return count;
}
ssize_t baseboardWrite(int fd, const void *buf, size_t count)
{
memcpy(&sharedMemory[sharedMemoryIndex], buf, count);
return count;
memcpy(&sharedMemory[sharedMemoryIndex], buf, count);
return count;
}
int baseboardSelect(int nfds, fd_set *restrict readfds, fd_set *restrict writefds, fd_set *restrict exceptfds, struct timeval *restrict timeout)
int baseboardSelect(int nfds, fd_set *restrict readfds, fd_set *restrict writefds, fd_set *restrict exceptfds,
struct timeval *restrict timeout)
{
return selectReply;
return selectReply;
}
int baseboardIoctl(int fd, unsigned int request, void *data)
{
switch (request)
{
case BASEBOARD_GET_VERSION:
{
uint8_t versionData[4] = {0x00, 0x19, 0x20, 0x07};
memcpy(data, versionData, 4);
return 0;
}
break;
case BASEBOARD_INIT:
{
// selectReply = -1; Considering adding this in
return 0;
}
break;
case BASEBOARD_READY: // Not sure if this is what it should be called
{
selectReply = 0;
return 0;
}
break;
case BASEBOARD_SEEK_SHM:
{
sharedMemoryIndex = (unsigned int)data;
return 0;
}
break;
case BASEBOARD_READ_SRAM:
{
readData_t *_data = data;
fseek(sram, _data->offset, SEEK_SET);
fread(_data->data, 1, _data->size, sram);
return 0;
}
break;
case BASEBOARD_WRITE_SRAM:
{
writeData_t *_data = data;
fseek(sram, _data->offset, SEEK_SET);
fwrite(_data->data, 1, _data->size, sram);
return 0;
}
break;
case BASEBOARD_REQUEST:
{
uint32_t *_data = data;
switch (_data[0])
switch (request)
{
case BASEBOARD_GET_SERIAL: // bcCmdSysInfoGetReq
case BASEBOARD_GET_VERSION:
{
serialCommand.destAddress = _data[1];
serialCommand.destSize = _data[2];
uint8_t versionData[4] = {0x00, 0x19, 0x20, 0x07};
memcpy(data, versionData, 4);
return 0;
}
break;
case BASEBOARD_WRITE_FLASH: // bcCmdSysFlashWrite
case BASEBOARD_INIT:
{
log_warn("The game attempted to write to the baseboard flash\n");
// selectReply = -1; Considering adding this in
return 0;
}
break;
case BASEBOARD_PROCESS_JVS:
case BASEBOARD_READY: // Not sure if this is what it should be called
{
jvsCommand.srcAddress = _data[1];
jvsCommand.srcSize = _data[2];
jvsCommand.destAddress = _data[3];
jvsCommand.destSize = _data[4];
memcpy(inputBuffer, &sharedMemory[jvsCommand.srcAddress], jvsCommand.srcSize);
selectReply = 0;
return 0;
}
break;
if (getConfig()->emulateJVS)
{
processPacket(&jvsPacketSize);
}
else if (jvsFileDescriptor >= 0)
{
for (int i = 0; i < jvsCommand.srcSize; i++)
case BASEBOARD_SEEK_SHM:
{
sharedMemoryIndex = (unsigned int)data;
return 0;
}
break;
case BASEBOARD_READ_SRAM:
{
readData_t *_data = data;
fseek(sram, _data->offset, SEEK_SET);
fread(_data->data, 1, _data->size, sram);
return 0;
}
break;
case BASEBOARD_WRITE_SRAM:
{
writeData_t *_data = data;
fseek(sram, _data->offset, SEEK_SET);
fwrite(_data->data, 1, _data->size, sram);
return 0;
}
break;
case BASEBOARD_REQUEST:
{
uint32_t *_data = data;
switch (_data[0])
{
write(jvsFileDescriptor, &inputBuffer[i], 1);
if (inputBuffer[i] == 0xF0)
{
setSenseLine(3);
}
else if (inputBuffer[i] == 0xF1)
{
setSenseLine(1);
}
case BASEBOARD_GET_SERIAL: // bcCmdSysInfoGetReq
{
serialCommand.destAddress = _data[1];
serialCommand.destSize = _data[2];
}
}
break;
case BASEBOARD_WRITE_FLASH: // bcCmdSysFlashWrite
{
log_warn("The game attempted to write to the baseboard flash\n");
}
break;
case BASEBOARD_PROCESS_JVS:
{
jvsCommand.srcAddress = _data[1];
jvsCommand.srcSize = _data[2];
jvsCommand.destAddress = _data[3];
jvsCommand.destSize = _data[4];
memcpy(inputBuffer, &sharedMemory[jvsCommand.srcAddress], jvsCommand.srcSize);
if (getConfig()->emulateJVS)
{
processPacket(&jvsPacketSize);
}
else if (jvsFileDescriptor >= 0)
{
for (int i = 0; i < jvsCommand.srcSize; i++)
{
write(jvsFileDescriptor, &inputBuffer[i], 1);
if (inputBuffer[i] == 0xF0)
{
setSenseLine(3);
}
else if (inputBuffer[i] == 0xF1)
{
setSenseLine(1);
}
}
}
}
break;
case BASEBOARD_GET_SENSE_LINE:
break;
default:
printf("Error: Unknown baseboard command %X\n", _data[0]);
}
// Acknowledge the command
_data[0] |= 0xF0000000;
return 0;
}
break;
case BASEBOARD_GET_SENSE_LINE:
break;
default:
printf("Error: Unknown baseboard command %X\n", _data[0]);
}
// Acknowledge the command
_data[0] |= 0xF0000000;
return 0;
}
break;
case BASEBOARD_RECEIVE:
{
uint32_t *_data = data;
switch (_data[0] & 0xFFF)
case BASEBOARD_RECEIVE:
{
uint32_t *_data = data;
case BASEBOARD_GET_SERIAL:
{
memcpy(&sharedMemory[serialCommand.destAddress + 96], SERIAL_STRING, strlen(SERIAL_STRING));
_data[1] = 1; // Set the status to success
}
break;
switch (_data[0] & 0xFFF)
{
case BASEBOARD_GET_SENSE_LINE:
{
_data[2] = getSenseLine();
_data[1] = 1; // Set the status to success
}
break;
case BASEBOARD_GET_SERIAL:
{
memcpy(&sharedMemory[serialCommand.destAddress + 96], SERIAL_STRING, strlen(SERIAL_STRING));
_data[1] = 1; // Set the status to success
}
break;
case BASEBOARD_PROCESS_JVS:
{
if (getConfig()->emulateJVS)
{
memcpy(&sharedMemory[jvsCommand.destAddress], outputBuffer, jvsPacketSize);
_data[2] = jvsCommand.destAddress;
_data[3] = jvsPacketSize;
_data[1] = 1; // Set the status to success
}
else if (jvsFileDescriptor >= 0)
{
JVSFrame frame = readJVSFrameFromThread();
memcpy(&sharedMemory[jvsCommand.destAddress], frame.buffer, frame.size);
_data[2] = jvsCommand.destAddress;
_data[3] = frame.size;
_data[1] = frame.ready;
}
case BASEBOARD_GET_SENSE_LINE:
{
_data[2] = getSenseLine();
_data[1] = 1; // Set the status to success
}
break;
case BASEBOARD_PROCESS_JVS:
{
if (getConfig()->emulateJVS)
{
memcpy(&sharedMemory[jvsCommand.destAddress], outputBuffer, jvsPacketSize);
_data[2] = jvsCommand.destAddress;
_data[3] = jvsPacketSize;
_data[1] = 1; // Set the status to success
}
else if (jvsFileDescriptor >= 0)
{
JVSFrame frame = readJVSFrameFromThread();
memcpy(&sharedMemory[jvsCommand.destAddress], frame.buffer, frame.size);
_data[2] = jvsCommand.destAddress;
_data[3] = frame.size;
_data[1] = frame.ready;
}
}
break;
default:
printf("Error: Unknown baseboard receive command %X\n", _data[0] & 0xFFF);
}
// Acknowledge the command
_data[0] |= 0xF0000000;
return 0;
}
break;
default:
printf("Error: Unknown baseboard receive command %X\n", _data[0] & 0xFFF);
printf("Error: Unknown baseboard ioctl %X\n", request);
}
// Acknowledge the command
_data[0] |= 0xF0000000;
return 0;
}
break;
default:
printf("Error: Unknown baseboard ioctl %X\n", request);
}
return 0;
}
+1 -4
View File
@@ -76,10 +76,7 @@ int initCardReader()
int carReaderGetFdIdx(int fd)
{
if (fd == serialFD[0].fd)
return 0;
return 1;
return (fd == serialFD[0].fd) ? 0 : 1;
}
uint8_t cardReaderGenChecksum(int fdIdx)
+14
View File
@@ -174,6 +174,8 @@ static int detectGame(uint32_t elf_crc)
config.gameStatus = WORKING;
config.jvsIOType = SEGA_TYPE_1;
config.gameType = ABC;
config.width = 640;
config.height = 480;
return 0;
}
break;
@@ -188,6 +190,8 @@ static int detectGame(uint32_t elf_crc)
config.gameStatus = WORKING;
config.jvsIOType = SEGA_TYPE_1;
config.gameType = ABC;
config.width = 640;
config.height = 480;
return 0;
}
break;
@@ -249,6 +253,8 @@ static int detectGame(uint32_t elf_crc)
config.gameNativeResolutions = "";
config.gameType = DRIVING;
config.gameStatus = WORKING;
config.width = 1280;
config.height = 768;
return 0;
}
break;
@@ -262,6 +268,8 @@ static int detectGame(uint32_t elf_crc)
config.gameNativeResolutions = "1280x768";
config.gameType = DRIVING;
config.gameStatus = WORKING;
config.width = 1280;
config.height = 768;
return 0;
}
break;
@@ -275,6 +283,8 @@ static int detectGame(uint32_t elf_crc)
config.gameNativeResolutions = "";
config.gameType = DRIVING;
config.gameStatus = WORKING;
config.width = 1280;
config.height = 768;
return 0;
}
break;
@@ -1113,6 +1123,9 @@ int readConfig(FILE *configFile, EmulatorConfig *config)
else if (strcmp(command, "SRAM_PATH") == 0)
strcpy(config->sramPath, getNextToken(NULL, " ", &saveptr));
else if (strcmp(command, "LIBCG_PATH") == 0)
strcpy(config->libCgPath, getNextToken(NULL, " ", &saveptr));
else if (strcmp(command, "EMULATE_RIDEBOARD") == 0) {
int defaultValue = config->emulateRideboard;
config->emulateRideboard = getNextIntOrAuto(saveptr, defaultValue);
@@ -1529,6 +1542,7 @@ int initConfig(const char* configFilePath)
config.lindberghColour = YELLOW;
strcpy(config.eepromPath, "eeprom.bin");
strcpy(config.sramPath, "sram.bin");
strcpy(config.libCgPath, "");
strcpy(config.jvsPath, "/dev/ttyUSB0");
strcpy(config.serial1Path, "/dev/ttyS0");
strcpy(config.serial2Path, "/dev/ttyS1");
+1
View File
@@ -232,6 +232,7 @@ typedef struct
int fullscreen;
char eepromPath[MAX_PATH_LENGTH];
char sramPath[MAX_PATH_LENGTH];
char libCgPath[MAX_PATH_LENGTH];
char jvsPath[MAX_PATH_LENGTH];
char serial1Path[MAX_PATH_LENGTH];
char serial2Path[MAX_PATH_LENGTH];
-1
View File
@@ -1,4 +1,3 @@
// #pragma once
int loadNewCursor(const char *cursorFileName, void **cursor, int customWidth, int customHeight);
void loadCursors();
+286 -26
View File
@@ -95,6 +95,12 @@ static int callback(struct dl_phdr_info *info, size_t size, void *data);
uint16_t basePortAddress = 0xFFFF;
/**
* @brief Signal handler for SIGSEGV.
*
* This function handles segmentation faults (SIGSEGV) and attempts to recover
* from certain types of memory access errors, particularly those related to I/O ports.
*/
/**
* Signal handler for the SIGSEGV signal, which is triggered when a process tries to access an illegal memory location.
* @param signal
@@ -177,6 +183,13 @@ static void handleSegfault(int signal, siginfo_t *info, void *ptr)
}
}
/**
* @brief Trims leading and trailing whitespace and quotes from a string.
*
* This function removes leading and trailing whitespace characters, as well as
* single and double quotes, from the input string.
* @param str The string to trim.
*/
char *trimOS_ID(char *str)
{
if (!str)
@@ -198,6 +211,12 @@ char *trimOS_ID(char *str)
return str;
}
/**
* @brief Checks if the operating system is Debian-based.
*
* This function reads the /etc/os-release file to determine if the current
* operating system is Debian or Ubuntu, or a derivative of them.
*/
bool checkOS_ID()
{
FILE *fp = fopen("/etc/os-release", "r");
@@ -249,6 +268,12 @@ bool checkOS_ID()
return found;
}
/**
* @brief Initialization function for the hook library.
*
* This function is called automatically when the library is loaded. It sets up
* signal handlers, initializes configuration, and performs other setup tasks.
*/
void __attribute__((constructor)) hook_init()
{
// Get offsets of the Game's ELF and calculate CRC32.
@@ -360,6 +385,13 @@ void __attribute__((constructor)) hook_init()
}
}
/**
* @brief Hook for the opendir function.
*
* This function intercepts calls to opendir and redirects them to different
* directories based on the game ID.
* @param dirname The name of the directory to open.
*/
DIR *opendir(const char *dirname)
{
DIR *(*_opendir)(const char *dirname) = dlsym(RTLD_NEXT, "opendir");
@@ -395,6 +427,13 @@ DIR *opendir(const char *dirname)
return _opendir(dirname);
}
/**
* @brief Hook for the remove function.
*
* This function intercepts calls to remove and redirects them to different
* paths based on the game ID.
* @param path The path to remove.
*/
int remove(const char *path)
{
int (*_remove)(const char *path) = dlsym(RTLD_NEXT, "remove");
@@ -416,6 +455,13 @@ int remove(const char *path)
return _remove(path);
}
/**
* @brief Hook for the mkdir function.
*
* This function intercepts calls to mkdir and redirects them to different
* paths based on the game ID.
* @param path The path to create.
*/
int mkdir(const char *path, mode_t mode)
{
int (*_mkdir)(const char *path, mode_t mode) = dlsym(RTLD_NEXT, "mkdir");
@@ -437,6 +483,13 @@ int mkdir(const char *path, mode_t mode)
return _mkdir(path, mode);
}
/**
* @brief Hook for the __xstat64 function.
*
* This function intercepts calls to __xstat64 and redirects them to different
* paths based on the game ID.
* @param path The path to stat.
*/
int __xstat64(int ver, const char *path, struct stat64 *stat_buf)
{
int (*___xstat64)(int ver, const char *path, struct stat64 *stat_buf) = dlsym(RTLD_NEXT, "__xstat64");
@@ -448,6 +501,13 @@ int __xstat64(int ver, const char *path, struct stat64 *stat_buf)
return ___xstat64(ver, path, stat_buf);
}
/**
* @brief Hook for the open function.
*
* This function intercepts calls to open and redirects them to different
* files or devices based on the pathname.
* @param pathname The path to open.
*/
int open(const char *pathname, int flags, ...)
{
va_list args;
@@ -534,6 +594,13 @@ int open(const char *pathname, int flags, ...)
return _open(pathname, flags, mode);
}
/**
* @brief Hook for the open64 function.
*
* This function intercepts calls to open64 and redirects them to different
* files or devices based on the pathname.
* @param pathname The path to open.
*/
int open64(const char *pathname, int flags, ...)
{
va_list args;
@@ -544,6 +611,13 @@ int open64(const char *pathname, int flags, ...)
return open(pathname, flags, mode);
}
/**
* @brief Hook for the fopen function.
*
* This function intercepts calls to fopen and redirects them to different
* files based on the pathname.
* @param pathname The path to open.
*/
FILE *fopen(const char *restrict pathname, const char *restrict mode)
{
FILE *(*_fopen)(const char *restrict pathname, const char *restrict mode) = dlsym(RTLD_NEXT, "fopen");
@@ -757,6 +831,13 @@ FILE *fopen(const char *restrict pathname, const char *restrict mode)
return _fopen(pathname, mode);
}
/**
* @brief Hook for the fopen64 function.
*
* This function intercepts calls to fopen64 and redirects them to different
* files based on the pathname.
* @param pathname The path to open.
*/
FILE *fopen64(const char *pathname, const char *mode)
{
FILE *(*_fopen64)(const char *restrict pathname, const char *restrict mode) = dlsym(RTLD_NEXT, "fopen64");
@@ -857,6 +938,13 @@ FILE *fopen64(const char *pathname, const char *mode)
return _fopen64(pathname, mode);
}
/**
* @brief Hook for the fclose function.
*
* This function intercepts calls to fclose and performs cleanup operations
* for the file hooks.
* @param stream The file stream to close.
*/
int fclose(FILE *stream)
{
int (*_fclose)(FILE *stream) = dlsym(RTLD_NEXT, "fclose");
@@ -878,6 +966,14 @@ int fclose(FILE *stream)
}
return _fclose(stream);
}
/**
* @brief Hook for the openat function.
*
* This function intercepts calls to openat and redirects them to different
* files or devices based on the pathname.
* @param pathname The path to open.
*/
int openat(int dirfd, const char *pathname, int flags, ...)
{
int (*_openat)(int dirfd, const char *pathname, int flags) = dlsym(RTLD_NEXT, "openat");
@@ -892,6 +988,13 @@ int openat(int dirfd, const char *pathname, int flags, ...)
return _openat(dirfd, pathname, flags);
}
/**
* @brief Hook for the close function.
*
* This function intercepts calls to close and performs cleanup operations
* for the file hooks.
* @param fd The file descriptor to close.
*/
int close(int fd)
{
int (*_close)(int fd) = dlsym(RTLD_NEXT, "close");
@@ -908,6 +1011,13 @@ int close(int fd)
return _close(fd);
}
/**
* @brief Hook for the fgets function.
*
* This function intercepts calls to fgets and redirects them to different
* files based on the stream.
* @param stream The file stream to read from.
*/
char *fgets(char *str, int n, FILE *stream)
{
char *(*_fgets)(char *str, int n, FILE *stream) = dlsym(RTLD_NEXT, "fgets");
@@ -945,6 +1055,13 @@ char *fgets(char *str, int n, FILE *stream)
return _fgets(str, n, stream);
}
/**
* @brief Hook for the read function.
*
* This function intercepts calls to read and redirects them to different
* files or devices based on the file descriptor.
* @param fd The file descriptor to read from.
*/
ssize_t read(int fd, void *buf, size_t count)
{
int (*_read)(int fd, void *buf, size_t count) = dlsym(RTLD_NEXT, "read");
@@ -964,17 +1081,11 @@ ssize_t read(int fd, void *buf, size_t count)
return driveboardRead(fd, buf, count);
}
if (fd == hooks[SERIAL0] && getConfig()->emulateCardreader)
if ((fd == hooks[SERIAL0] || fd == hooks[SERIAL1]) && getConfig()->emulateCardreader)
{
return cardReaderRead(fd, buf, count);
}
if (fd == hooks[SERIAL1] && getConfig()->emulateCardreader)
{
return cardReaderRead(fd, buf, count);
}
// If we don't hook the serial just reply with nothing
if (fd == hooks[SERIAL0] || fd == hooks[SERIAL1])
{
if (gId == PRIMEVAL_HUNT && getConfig()->emulateTouchscreen == 1)
@@ -994,6 +1105,13 @@ ssize_t read(int fd, void *buf, size_t count)
return _read(fd, buf, count);
}
/**
* @brief Hook for the fread function.
*
* This function intercepts calls to fread and redirects them to different
* files based on the stream.
* @param stream The file stream to read from.
*/
size_t fread(void *buf, size_t size, size_t count, FILE *stream)
{
size_t (*_fread)(void *buf, size_t size, size_t count, FILE *stream) = dlsym(RTLD_NEXT, "fread");
@@ -1014,11 +1132,6 @@ size_t fread(void *buf, size_t size, size_t count, FILE *stream)
return freadReplace(buf, size, count, fileRead[FILE_RW2]);
}
// if (stream == fileHooks[FILE_HARLEY])
// {
// return harleyFreadReplace(buf, size, count, fileHooks[FILE_HARLEY]);
// }
if (stream == fileHooks[FILE_FONT_ABC])
{
memcpy(buf, fontABC + fontABCidx, size * count);
@@ -1046,6 +1159,13 @@ size_t fread(void *buf, size_t size, size_t count, FILE *stream)
return _fread(buf, size, count, stream);
}
/**
* @brief Hook for the ftell function.
*
* This function intercepts calls to ftell and redirects them to different
* files based on the stream.
* @param stream The file stream to get the position from.
*/
long int ftell(FILE *stream)
{
long int (*_ftell)(FILE *stream) = dlsym(RTLD_NEXT, "ftell");
@@ -1067,6 +1187,13 @@ long int ftell(FILE *stream)
return _ftell(stream);
}
/**
* @brief Hook for the fseek function.
*
* This function intercepts calls to fseek and redirects them to different
* files based on the stream.
* @param stream The file stream to seek in.
*/
int fseek(FILE *stream, long int offset, int whence)
{
int (*_fseek)(FILE *stream, long int offset, int whence) = dlsym(RTLD_NEXT, "fseek");
@@ -1090,6 +1217,13 @@ int fseek(FILE *stream, long int offset, int whence)
return _fseek(stream, offset, whence);
}
/**
* @brief Hook for the rewind function.
*
* This function intercepts calls to rewind and redirects them to different
* files based on the stream.
* @param stream The file stream to rewind.
*/
void rewind(FILE *stream)
{
void (*_rewind)(FILE *stream) = dlsym(RTLD_NEXT, "rewind");
@@ -1103,6 +1237,13 @@ void rewind(FILE *stream)
_rewind(stream);
}
/**
* @brief Hook for the write function.
*
* This function intercepts calls to write and redirects them to different
* files or devices based on the file descriptor.
* @param fd The file descriptor to write to.
*/
ssize_t write(int fd, const void *buf, size_t count)
{
int (*_write)(int fd, const void *buf, size_t count) = dlsym(RTLD_NEXT, "write");
@@ -1128,12 +1269,7 @@ ssize_t write(int fd, const void *buf, size_t count)
return driveboardWrite(fd, buf, count);
}
if (fd == hooks[SERIAL0] && getConfig()->emulateCardreader)
{
return cardReaderWrite(fd, buf, count);
}
if (fd == hooks[SERIAL1] && getConfig()->emulateCardreader)
if ((fd == hooks[SERIAL0] || fd == hooks[SERIAL1]) && getConfig()->emulateCardreader)
{
return cardReaderWrite(fd, buf, count);
}
@@ -1141,6 +1277,13 @@ ssize_t write(int fd, const void *buf, size_t count)
return _write(fd, buf, count);
}
/**
* @brief Hook for the ioctl function.
*
* This function intercepts calls to ioctl and redirects them to different
* devices based on the file descriptor.
* @param fd The file descriptor to perform the ioctl on.
*/
int ioctl(int fd, unsigned int request, void *data)
{
int (*_ioctl)(int fd, int request, void *data) = dlsym(RTLD_NEXT, "ioctl");
@@ -1170,6 +1313,13 @@ int ioctl(int fd, unsigned int request, void *data)
return _ioctl(fd, request, data);
}
/**
* @brief Hook for the tcgetattr function.
*
* This function intercepts calls to tcgetattr and redirects them to different
* devices based on the file descriptor.
* @param fd The file descriptor to get the attributes from.
*/
int tcgetattr(int fd, struct termios *termios_p)
{
int (*_tcgetattr)(int fd, struct termios *termios_p) = dlsym(RTLD_NEXT, "tcgetattr");
@@ -1180,6 +1330,13 @@ int tcgetattr(int fd, struct termios *termios_p)
return _tcgetattr(fd, termios_p);
}
/**
* @brief Hook for the tcsetattr function.
*
* This function intercepts calls to tcsetattr and redirects them to different
* devices based on the file descriptor.
* @param fd The file descriptor to set the attributes on.
*/
int tcsetattr(int fd, int optional_actions, const struct termios *termios_p)
{
int (*_tcsetattr)(int fd, int optional_actions, const struct termios *termios_p) = dlsym(RTLD_NEXT, "tcsetattr");
@@ -1190,6 +1347,13 @@ int tcsetattr(int fd, int optional_actions, const struct termios *termios_p)
return _tcsetattr(fd, optional_actions, termios_p);
}
/**
* @brief Hook for the cfgetispeed function.
*
* This function intercepts calls to cfgetispeed and redirects them to different
* devices based on the file descriptor.
* @param termios_p The termios structure to get the input speed from.
*/
speed_t cfgetispeed(const struct termios *termios_p)
{
speed_t (*_cfgetispeed)(const struct termios *termios_p) = dlsym(RTLD_NEXT, "cfgetispeed");
@@ -1200,6 +1364,13 @@ speed_t cfgetispeed(const struct termios *termios_p)
return _cfgetispeed(termios_p);
}
/**
* @brief Hook for the cfgetospeed function.
*
* This function intercepts calls to cfgetospeed and redirects them to different
* devices based on the file descriptor.
* @param termios_p The termios structure to get the output speed from.
*/
speed_t cfgetospeed(const struct termios *termios_p)
{
speed_t (*_cfgetospeed)(const struct termios *termios_p) = dlsym(RTLD_NEXT, "cfgetospeed");
@@ -1210,6 +1381,13 @@ speed_t cfgetospeed(const struct termios *termios_p)
return _cfgetospeed(termios_p);
}
/**
* @brief Hook for the cfsetispeed function.
*
* This function intercepts calls to cfsetispeed and redirects them to different
* devices based on the file descriptor.
* @param termios_p The termios structure to set the input speed on.
*/
int cfsetispeed(struct termios *termios_p, speed_t speed)
{
int (*_cfsetispeed)(struct termios *termios_p, speed_t speed) = dlsym(RTLD_NEXT, "cfsetispeed");
@@ -1220,6 +1398,13 @@ int cfsetispeed(struct termios *termios_p, speed_t speed)
return _cfsetispeed(termios_p, speed);
}
/**
* @brief Hook for the cfsetospeed function.
*
* This function intercepts calls to cfsetospeed and redirects them to different
* devices based on the file descriptor.
* @param termios_p The termios structure to set the output speed on.
*/
int cfsetospeed(struct termios *termios_p, speed_t speed)
{
int (*_cfsetospeed)(struct termios *termios_p, speed_t speed) = dlsym(RTLD_NEXT, "cfsetospeed");
@@ -1230,6 +1415,14 @@ int cfsetospeed(struct termios *termios_p, speed_t speed)
return _cfsetospeed(termios_p, speed);
}
/**
* @brief Hook for the select function.
*
* This function intercepts calls to select and redirects them to different
* devices based on the file descriptor.
* @param nfds The highest file descriptor number plus one.
* @param readfds The file descriptors to check for readability.
*/
int select(int nfds, fd_set *restrict readfds, fd_set *restrict writefds, fd_set *restrict exceptfds,
struct timeval *restrict timeout)
{
@@ -1254,6 +1447,13 @@ int select(int nfds, fd_set *restrict readfds, fd_set *restrict writefds, fd_set
return _select(nfds, readfds, writefds, exceptfds, timeout);
}
/**
* @brief Hook for the system function.
*
* This function intercepts calls to system and redirects them to different
* commands based on the command string.
* @param command The command to execute.
*/
int system(const char *command)
{
int (*_system)(const char *command) = dlsym(RTLD_NEXT, "system");
@@ -1291,6 +1491,36 @@ int system(const char *command)
return _system(command);
}
/**
* @brief Hook for the strncpy function.
*
* This function intercepts calls to strncpy and redirects them to different
* strings based on the game ID.
* @param dest The destination string.
*/
char *strncpy(char *dest, const char *src, size_t n)
{
char *(*_strncpy)(char *dest, const char *src, size_t n) = dlsym(RTLD_NEXT, "strncpy");
switch (gId)
{
case HARLEY_DAVIDSON:
case RAMBO:
case THE_HOUSE_OF_THE_DEAD_EX:
case TOO_SPICY:
if (getConfig()->GPUVendor != NVIDIA_GPU && (strstr(src, "../fs/compiledshader") != NULL || strstr(src, "../fs/compiled") != NULL))
return _strncpy(dest, "../fs/compiledmesa", n);
}
return _strncpy(dest, src, n);
}
/**
* @brief Hook for the iopl function.
*
* This function intercepts calls to iopl and always returns 0.
* @param level The I/O privilege level to set.
* @return Always returns 0.
*/
int iopl(int level)
{
return 0;
@@ -1306,10 +1536,11 @@ void kswap_collect(void *p)
}
/**
* Hook for function used by Primevil
* @param base The number to raise to the exponent
* @param exp The exponent to raise the number to
* @return The result of raising the number to the exponent
* @brief Hook for the powf function.
*
* This function intercepts calls to powf and redirects them to pow.
* @param base The base number.
* @param exponent The exponent.
*/
float powf(float base, float exponent)
{
@@ -1324,6 +1555,13 @@ int sem_wait(sem_t *sem)
}
*/
/**
* @brief Gets the machine's IP address.
*
* This function retrieves the machine's IP address and stores it in the
* provided sockaddr_in structure.
* @param addr The sockaddr_in structure to store the IP address in.
*/
int get_machine_ip(struct sockaddr_in *addr)
{
struct ifaddrs *ifaddr, *ifa;
@@ -1396,7 +1634,11 @@ int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
}
/**
* Callback function to get the offset and size of the execution program in memory of the ELF we hook to.
* @brief Callback function for dl_iterate_phdr.
*
* This function is called for each program header in the loaded shared
* objects. It is used to calculate the CRC32 of the ELF file.
* @param info Information about the program header.
*/
static int callback(struct dl_phdr_info *info, size_t size, void *data)
{
@@ -1408,7 +1650,11 @@ static int callback(struct dl_phdr_info *info, size_t size, void *data)
}
/**
* Stop the game changing the DISPLAY environment variable
* @brief Hook for the setenv function.
*
* This function intercepts calls to setenv and prevents the game from
* changing the DISPLAY environment variable.
* @param name The name of the environment variable.
*/
int setenv(const char *name, const char *value, int overwrite)
{
@@ -1423,7 +1669,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 "Fakes" the TEA_DIR environment variable to games that require it to run
* @param name The name of the environment variable.
*/
char *getenv(const char *name)
{
@@ -1470,7 +1719,11 @@ char *getenv(const char *name)
}
/**
* Stop the game unsetting the DISPLAY environment variable
* @brief Hook for the unsetenv function.
*
* This function intercepts calls to unsetenv and prevents the game from
* unsetting the DISPLAY environment variable.
* @param name The name of the environment variable.
*/
int unsetenv(const char *name)
{
@@ -1497,6 +1750,13 @@ char *__strdup(const char *string)
return ___strdup(string);
}
/**
* @brief Hook for the localtime_r function.
*
* This function intercepts calls to localtime_r and redirects them to different
* times based on the game ID.
* @param timep The time to convert.
*/
struct tm *localtime_r(const time_t *timep, struct tm *result)
{
struct tm *(*_localtime_r)(const time_t *, struct tm *) =
+31 -15
View File
@@ -19,6 +19,7 @@
#define PRELOAD_FILE_NAME "lindbergh.so"
#define TEAM "bobbydilley, retrofan, dkeruza-neo, doozer, francesco, rolel, caviar-x"
#define LINDBERGH_CONFIG_PATH "LINDBERGH_CONFIG_PATH"
#define LINDBERGH_LOADER_CURRENT_DIR "LINDBERGH_LOADER_CURRENT_DIR"
#define MAX_PATH_LEN 1024
/**
@@ -230,6 +231,19 @@ int calculateFileCRC32(const char *filename, uint32_t *crc)
return 0;
}
bool hasSpaces(const char *str)
{
if (!str)
return false;
while (*str)
{
if (*str == ' ')
return true;
str++;
}
return false;
}
/**
* @brief Checks if the ELF file is clean based on its CRC32.
*
@@ -237,7 +251,7 @@ int calculateFileCRC32(const char *filename, uint32_t *crc)
* against a list of known clean ELF CRC32 values.
* @param command The command line string containing the path to the ELF file.
*/
void isCleanElf(char *command)
void checkIfElfisClean(char *command)
{
char *last_space = strrchr(command, ' ');
size_t length;
@@ -511,6 +525,7 @@ void setEnvironmentVariables(char *ldLibPath, char *curDir, char *gameDir, int z
setenv("__GLX_VENDOR_LIBRARY_NAME", "nvidia", 1);
setenv("__NV_PRIME_RENDER_OFFLOAD", "1", 1);
}
setenv("LINDBERGH_LOADER_CURRENT_DIR", curDir, 1);
}
/**
@@ -690,6 +705,12 @@ int main(int argc, char *argv[])
return EXIT_FAILURE;
}
if (hasSpaces(curDir))
{
log_warn("The current path contains spaces, this most likely will cause issues.");
log_warn("Please, make sure you don't use spaces in the path.");
}
char command[PATH_MAX] = {0};
char *forcedGameDir;
char *forcedGameElf;
@@ -796,26 +817,16 @@ int main(int argc, char *argv[])
char *ldPreloadLibrary = findLDPreloadLibrary();
if (strcmp(ldPreloadLibrary, PRELOAD_FILE_NAME) == 0)
{
char lindberghSoPath[MAX_PATH_LEN];
if (gameDir[0] != '\0')
snprintf(lindberghSoPath, strlen(gameDir) + sizeof(PRELOAD_FILE_NAME) + 1, "%s/%s", gameDir, PRELOAD_FILE_NAME);
if (access(lindberghSoPath, F_OK) != 0)
{
log_error("The preload object lindbergh.so was not found.");
return EXIT_FAILURE;
}
ldPreloadLibrary = strdup(lindberghSoPath);
}
if (strcmp(curDir, gameDir) == 0)
ldPreloadLibrary = PRELOAD_FILE_NAME;
// Ensure environment variables are set correctly
setEnvironmentVariables(ldPreloadLibrary, curDir, gameDir, zink, nvidia);
if (testMode)
testModePath(command);
isCleanElf(command);
checkIfElfisClean(command);
if (gdb)
{
@@ -827,6 +838,11 @@ int main(int argc, char *argv[])
if (extConfigPath != NULL && extConfigPath[0] != '\0')
{
if (hasSpaces(extConfigPath))
{
log_warn("The config path contains spaces, this most likely will cause issues.");
log_warn("Please, make sure you don't use spaces in the path.");
}
setenv(LINDBERGH_CONFIG_PATH, extConfigPath, 1);
}
+10 -6
View File
@@ -212,8 +212,8 @@ void *readJVSFrameThread(void * arg)
* @param fd
* @return 0|1
*/
int startJVSFrameThread(int * fd) {
int fdlocal = *((int *) fd);
int startJVSFrameThread(int *fd)
{
printf("SERIAL: starting thread.\n");
// Clean shared JVS frame buffer
@@ -236,17 +236,21 @@ int startJVSFrameThread(int * fd) {
* Return a JVSFrame structure with empty or full data, no in between
* @return
*/
JVSFrame readJVSFrameFromThread() {
JVSFrame readJVSFrameFromThread()
{
JVSFrame frame;
// Lock while reading/writing to shared frame
pthread_mutex_lock(&jvsBuffer_lock);
// Check if we have a valid frame
if (jvsFrameBuffer.ready == 1) {
if (jvsFrameBuffer.ready == 1)
{
frame = jvsFrameBuffer;
// It has been red, we disable this frame
// It has been read, we disable this frame
jvsFrameBuffer.ready = 0;
} else {
}
else
{
frame.ready = 0;
frame.size = 0;
memset(frame.buffer, 0, JVSBUFFER_SIZE);
+5 -11
View File
@@ -628,11 +628,9 @@ int initPatch()
if (GPUVendor != NVIDIA_GPU)
{
cacheModedShaderFiles();
loadLibCg();
cacheModedShaderFiles();
cacheNnstdshader();
patchMemory(0x082d4437, "9090909090"); // Stop the folder rename
patchMemory(0x088a6127, "66732f636f6d70696c65646d657361"); // Change folder to compiledshdmesa
patchMemory(0x082646b3, "01"); // Compile using CGC
replaceCallAtAddress(0x082d48ac, compileWithCGC);
replaceCallAtAddress(0x082d4b3b, compileWithCGC);
@@ -2059,12 +2057,9 @@ int initPatch()
{
loadLibCg();
cacheNnstdshader();
patchMemory(0x08200c17, "9090909090"); // Stop the folder rename
patchMemory(0x084173e7, "66732f636f6d70696c65646d657361"); // Change folder to compiledshdmesa
patchMemory(0x080b3d71, "01"); // Compile using CGC
replaceCallAtAddress(0x082015bf, compileWithCGC);
replaceCallAtAddress(0x082012c1, compileWithCGC);
// patchMemory(0x080b3d65, "00"); // Force recompile shaders
}
}
break;
@@ -2141,6 +2136,7 @@ int initPatch()
detourFunction(0x084d44fc, amDipswSetLed);
detourFunction(0x084d4485, amDipswGetData);
patchMemory(0x0804edb2, "9090909090"); //__intel_new_proc_init_P
detourFunction(0x08178e6c, stubRetOne); // _ZN7am_ctrl18SetNetworkAddrEth0Ejj.
detourFunction(0x0804e594, gl_XGetProcAddressARB);
srtvElfShaderPatcher();
@@ -2487,9 +2483,8 @@ int initPatch()
// Mesa Patches
if (GPUVendor != NVIDIA_GPU)
{
patchMemory(0x08503bfa, "6d657361"); // Rename compile folder to compmesa
cacheModedShaderFiles();
loadLibCg();
cacheModedShaderFiles();
cacheNnstdshader();
replaceCallAtAddress(0x08370aa7, compileWithCGC);
replaceCallAtAddress(0x08370bb6, compileWithCGC);
@@ -2550,10 +2545,9 @@ int initPatch()
if (GPUVendor != NVIDIA_GPU)
{
loadLibCg();
cacheNnstdshader();
patchMemory(0x081ef9d8, "01"); // Force the game to recompile the shaders using cgc
patchMemory(0x08413f04, "646d657361"); // Changes compiledshader folder to compiledshdmesa
cacheModedShaderFiles();
cacheNnstdshader();
patchMemory(0x081ef9d8, "01"); // Force the game to recompile the shaders using cgc
replaceCallAtAddress(0x08259fe5, compileWithCGC);
replaceCallAtAddress(0x0825a089, compileWithCGC);
}
+199 -5
View File
@@ -1267,6 +1267,178 @@ void glVertex3fHOD4(GLfloat x, GLfloat y, GLfloat z)
_glVertex3f(x, y, z);
}
void tooSpicySC(uint32_t param_1, uint32_t param_2)
{
myEnableScaling = true;
SDL_WarpMouseInWindow(SDLwindow, 1280 / 2, 768 / 2);
((void (*)(uint32_t, uint32_t))0x082fa77c)(param_1, param_2);
}
void tooSpicyPR(uint32_t param_1, uint32_t param_2)
{
myEnableScaling = false;
((void (*)(uint32_t, uint32_t))0x081eb4d4)(param_1, param_2);
}
int tooSpicyVsprintf(char *str, const char *format, va_list arg)
{
int (*_vsprintf)(char *str, const char *format, va_list arg) = dlsym(RTLD_NEXT, "vsprintf");
int res = _vsprintf(str, format, arg);
if (strcmp(str, "Additional 475") == 0)
{
myEnableScaling = false;
}
return res;
}
void glVertex3f2SP(GLfloat x, GLfloat y, GLfloat z)
{
int (*_glVertex3f)(GLfloat x, GLfloat y, GLfloat z) = dlsym(RTLD_NEXT, "glVertex3f");
void *returnAddress = __builtin_return_address(0);
float scaleX = gWidth / 1280.0f;
float scaleY = gHeight / 768.0f;
float TestX = ((((gWidth - 1280.0) / 2.0) * 1.1116317809) / 1280.0) * (1.5 / scaleX);
float TestY = ((((gHeight - 768.0) / 2.0) * 0.666979044) / 768.0) * (1.5 / scaleX);
float OffsetX = TestX; // test
float OffsetY = TestY;
float scaleZ = fabs(z) / 1.510000;
float AdjOffsetX = OffsetX * scaleZ;
float AdjOffsetY = OffsetY * scaleZ;
if (z == -1.000000f || z == -3.000000f)
{
// We skip 3d and videos
;
}
else if (z == -1.010000f)
{
// bd main
x += AdjOffsetX;
y -= AdjOffsetY;
x *= scaleX;
y *= scaleY;
}
else if (z == -1.510000f)
{
// logo - coin/start - 2D
if (curTextureID == 497) // right
{
x -= OffsetX;
y -= OffsetY;
x *= scaleX;
y *= scaleY;
}
else if (curTextureID != 498) // We skip deadend
{
x += OffsetX;
y -= OffsetY;
x *= scaleX;
y *= scaleY;
}
}
else if (z == -1.460000f)
{
// 2D title
x += AdjOffsetX;
y -= AdjOffsetY;
x *= scaleX;
y *= scaleY;
}
else if (z == -1.490000f)
{
// 2D title
x += AdjOffsetX;
y -= AdjOffsetY;
x *= scaleX;
y *= scaleY;
}
else if (z == -1.500000f)
{
// 2D title
x += AdjOffsetX;
y -= AdjOffsetY;
x *= scaleX;
y *= scaleY;
}
else if (z == -1.310000f)
{
// 2D
x += AdjOffsetX;
y -= AdjOffsetY;
x *= scaleX;
y *= scaleY;
}
else if (z == -1.210000f)
{
// 2D
x += AdjOffsetX;
y -= AdjOffsetY;
x *= scaleX;
y *= scaleY;
}
else if (z == -1.5109999180f)
{
// 2D
x += AdjOffsetX;
y -= AdjOffsetY;
x *= scaleX;
y *= scaleY;
}
else if (z == -1.200000f)
{
// target - select
if (curTextureID == 454 || curTextureID == 461 || curTextureID == 456)
{
// 457 X - 454 461 456 O
if (myEnableScaling)
{
x += AdjOffsetX;
y -= AdjOffsetY;
x *= scaleX;
y *= scaleY;
}
}
}
else if (z == -1.710000f)
{
// 2D
x += AdjOffsetX;
y -= AdjOffsetY;
x *= scaleX;
y *= scaleY;
}
else if (z > -1.85f)
{
// 2d
x += AdjOffsetX;
y -= AdjOffsetY;
x *= scaleX;
y *= scaleY;
}
_glVertex3f(x, y, z);
}
void glVertex3fHarley(GLfloat x, GLfloat y, GLfloat z)
{
int (*_glVertex3f)(GLfloat x, GLfloat y, GLfloat z) = dlsym(RTLD_NEXT, "glVertex3f");
@@ -1286,11 +1458,6 @@ void glVertex3fHarley(GLfloat x, GLfloat y, GLfloat z)
y *= scaleY;
}
void *addr = __builtin_return_address(0);
// printf("glVertex3f is hooked: x=%f, y=%f, z=%f\n", x, y, z);
// printf("z values: %.10f\n", z);
// if ( z == -3517.2272949219f){ //1360x768
// if ( z == -4271.795898f){ //900p
if (z == -5300.7529296875)
{ // 1080p
printf("glVertex3f hooked: x=%f, y=%f, z=%f, addr: %p\n", x, y, z, addr);
@@ -2655,6 +2822,23 @@ int initResolutionPatches()
{
break;
}
setVariable(0x08785b80, gWidth); // main
setVariable(0x08785b84, gHeight);
patchMemory(0x082a3222, "02");
setVariable(0x08785ad8, 1360); // sprite res 1280x768
setVariable(0x08785adc, 768);
setVariable(0x087859b8, 1360); // sprite res 640x480
setVariable(0x087859bc, 768);
patchMemory(0x081775d2, "b801000000"); // target
patchMemory(0x0804e5d2, "909090909090");
// detourFunction(0x0804d254, glVertex3fHODEX);
setVariable(0x087aa080, gWidth); // render res
patchMemory(0x0804e60c, "909090909090");
patchMemory(0x0828cc2f, "909090909090");
}
break;
case TOO_SPICY:
@@ -2669,6 +2853,16 @@ int initResolutionPatches()
{
break;
}
setVariable(0x08202b22, gWidth); // render res
patchMemory(0x08202b19, "74");
setVariable(0x08664410, gWidth); // 1280x768
setVariable(0x08664414, gHeight);
detourFunction(0x0804d0d0, glVertex3f2SP);
detourFunction(0x0804dda0, myGlBindTexture);
replaceCallAtAddress(0x080d96ff, tooSpicySC);
replaceCallAtAddress(0x080da026, tooSpicyPR);
detourFunction(0x0804ce10, tooSpicyVsprintf);
patchMemory(0x081f96b9, "02"); // 5
}
break;
case TOO_SPICY_TEST:
+83 -24
View File
@@ -22,6 +22,7 @@
#include "../libxdiff/xdiff/xdiff.h"
#include "config.h"
#include "patch.h"
#include "log.h"
#include "shader_work/2spicy.h"
#include "shader_work/abc.h"
@@ -1541,41 +1542,99 @@ int parseCgcArgs(const char *input, const char ***compilerArgs, const char **out
return 0;
}
void loadLibCg()
char *findLibCg()
{
int isFlatpak = 0;
void *handle = dlopen("./libCg.so", RTLD_NOW);
if (!handle)
const char *foundPath = NULL;
FILE *libCgF = NULL;
char *pathsToCheck[] = {NULL, "/app/lib32/libCg2.so", "./libCg.so", NULL};
if (strcmp(getConfig()->libCgPath, "") != 0)
{
handle = dlopen("/app/lib32/libCg2.so", RTLD_NOW);
if (!handle)
pathsToCheck[0] = getConfig()->libCgPath;
}
const char *currentDir = getenv("LINDBERGH_LOADER_CURRENT_DIR");
if (currentDir != NULL)
{
size_t pathLen = strlen(currentDir) + strlen("/libCg.so") + 1;
pathsToCheck[3] = malloc(pathLen);
if (pathsToCheck[3] != NULL)
{
fprintf(stderr, "Error: Unable to load library libCg.so %s\n", dlerror());
fprintf(stderr, "Error: libCg.so version 2.0 is needed to compile the shaders in the game's folder.\n");
exit(1);
}
else
{
isFlatpak = 1;
snprintf(pathsToCheck[3], pathLen, "%s/%s", currentDir, "libCg.so");
}
}
char libCgVersion[9];
FILE *libF;
if (isFlatpak)
libF = fopen("/app/lib32/libCg2.so", "r");
else
libF = fopen("./libCg.so", "r");
for (int i = 0; i < 4; ++i)
{
if (pathsToCheck[i] == NULL)
continue;
fseek(libF, 0x226d84, SEEK_SET);
fread(libCgVersion, 9, 1, libF);
fclose(libF);
if (access(pathsToCheck[i], F_OK) == 0)
{
foundPath = pathsToCheck[i];
break;
}
}
if (foundPath != pathsToCheck[3] && pathsToCheck[3] != NULL)
{
free(pathsToCheck[3]);
}
if (foundPath == NULL)
{
log_error("Error: Unable to find library libCg.so\n");
log_error("Error: libCg.so version 2.0 is needed to compile the shaders in the game's folder.\n");
exit(EXIT_FAILURE);
}
char libCgVersion[9] = {0};
libCgF = fopen(foundPath, "rb");
if (libCgF == NULL)
{
log_error("Failed to open: %s\n", foundPath);
exit(EXIT_FAILURE);
}
fseek(libCgF, 0x226d84L, SEEK_SET);
if (fread(libCgVersion, 1, sizeof(libCgVersion) - 1, libCgF) != sizeof(libCgVersion) - 1)
{
log_error("Failed to read version from: %s\n", foundPath);
fclose(libCgF);
exit(EXIT_FAILURE);
}
fclose(libCgF);
if (strcmp(libCgVersion, "2.0.0.12") != 0)
{
printf("ERROR: Wrong libCg.so, version 2.0.0.12 is needed.\n");
exit(1);
log_error("ERROR: Wrong libCg.so version '%s', version 2.0.0.12 is needed.\n", libCgVersion);
exit(EXIT_FAILURE);
}
char *resultPath = strdup(foundPath);
if (resultPath == NULL)
{
log_error("Error allocating memory for result path");
exit(EXIT_FAILURE);
}
return resultPath;
}
void loadLibCg()
{
void *handle;
char *libCgFilePath = findLibCg();
handle = dlopen(libCgFilePath, RTLD_NOW);
if (!handle)
{
log_error("Error: Unable to find library libCg.so\n");
log_error("Error: libCg.so version 2.0 is needed to compile the shaders in the game's folder.\n");
exit(EXIT_FAILURE);
}
free(libCgFilePath);
dlerror();
char *error;