Compare commits

...
Author SHA1 Message Date
Bobby Dilley ec428d26be Update README.md 2025-07-09 14:53:32 +01:00
dkeruza ba51502fdb Fixed baseboard.c 2025-05-31 21:54:27 -04:00
dkeruza aedad4dcdf resolution.c bad 2025-05-31 21:34:16 -04:00
dkeruza 374ecd6e84 Merge pull request #110 from dkeruza-neo/master
A few fixes and additions.
2025-05-31 20:49:49 -04:00
dkeruza-neo f5c8c8c0f0 A couple additions and fixes. 2025-05-31 21:45:19 -03:00
Bobby Dilley feaa6a912e Make messages more similar 2025-05-23 13:13:41 +01:00
Bobby Dilley b129220822 Add birthday checking! 2025-05-23 13:12:04 +01:00
dkeruza-neo 4d07faa251 freedesktop.org down. Changed url for libGLU. 2025-04-26 01:25:19 -03:00
dkeruza-neo 5558718f29 Various fixes, clean and window managing. 2025-04-26 01:10:23 -03:00
dkeruza-neo e9e62a3bd1 Get tag version from changelog. 2025-04-17 10:27:46 -03:00
dkeruza-neo 293b4e8c25 Test versioning. 2025-04-16 23:23:16 -03:00
dkeruza e7d8c5a80a Added libuuid.so.1 to the AppImage. 2025-04-16 10:26:08 -04:00
dkeruza-neo 92eb48691d Test Build number 2025-04-15 22:54:32 -03:00
dkeruza 55fd8955c1 Merge pull request #95 from dkeruza-neo/master
Added libs to AppImage and fixed a bug in lindbergh.c
2025-04-15 19:53:01 -04:00
dkeruza-neo ea35dcdad2 fixed build-deps 2025-04-15 20:37:12 -03:00
dkeruza-neo fb557044d7 Added libs to AppImage and fixed a bug in lindbergh.c 2025-04-15 20:22:37 -03:00
dkeruza 0e8b3b4a59 Merge pull request #92 from dkeruza-neo/master
AppImage support.
2025-04-12 00:41:08 -04:00
dkeruza-neo f17dd93778 Merge remote-tracking branch 'upstream/master' 2025-04-12 00:30:36 -04:00
dkeruza-neo e359cbb0bd Added AppImage, fixed 2Spicy Resolution, again. 2025-04-12 00:28:50 -04:00
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-neo c5c44ce395 Fixed flatpak build script. 2025-04-06 11:33:14 -04:00
27 changed files with 1103 additions and 776 deletions
+33
View File
@@ -0,0 +1,33 @@
name: 🐧 Linux AppImage
on:
workflow_call:
workflow_dispatch:
jobs:
linux-appimage:
name: "Build"
runs-on: ubuntu-22.04
timeout-minutes: 30
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install Packages
run: scripts/appimage/install-packages.sh
- name: Build Deps
run: scripts/appimage/build-deps.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"
+54 -9
View File
@@ -16,6 +16,7 @@ on:
- '**.md' - '**.md'
- '.github/ISSUE_TEMPLATE/*' - '.github/ISSUE_TEMPLATE/*'
- '.docs/changelog' - '.docs/changelog'
- '.github/workflows/*'
jobs: jobs:
linux-build: linux-build:
@@ -24,34 +25,78 @@ 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.event_name == 'push' && github.ref == 'refs/heads/master'
steps: steps:
# Step 1: Checkout the code to access Git history and tags
- name: Checkout code
uses: actions/checkout@v4
with:
# Fetch all history and tags, necessary for git tag command
fetch-depth: 0
# Step 2: Download artifacts from previous build jobs
- name: Download Artifacts - name: Download Artifacts
uses: actions/download-artifact@v4 uses: actions/download-artifact@v4
with: with:
path: ./artifacts/ path: ./artifacts/
# Optional: Display downloaded artifacts for debugging
- name: Display Downloaded Artifacts - name: Display Downloaded Artifacts
run: find ./artifacts/ run: find ./artifacts/
- name: Add 161 to github.run_number # Step 3: Extract the latest version from changelog.md
- name: Extract Version from Changelog
id: get_version
run: | run: |
NEW_RUN_NUMBER=$(( ${{ github.run_number }} + 161 )) # Define the path to the changelog file (adjust if it's not at the root)
echo "NEW_RUN_NUMBER=$NEW_RUN_NUMBER" >> $GITHUB_ENV CHANGELOG_FILE="./docs/changelog"
- name: Create Preview Release echo "Attempting to extract version from $CHANGELOG_FILE..."
if: github.ref == 'refs/heads/master'
# Check if the changelog file exists
if [[ ! -f "$CHANGELOG_FILE" ]]; then
echo "Error: Changelog file '$CHANGELOG_FILE' not found."
exit 1
fi
VERSION=$(awk '/^## \[/ { match($0, /\[([^]]+)\]/, arr); print arr[1]; exit }' "$CHANGELOG_FILE")
# Check if a version was actually extracted
if [[ -z "$VERSION" ]]; then
echo "Error: Could not find version in '$CHANGELOG_FILE'. Expected format like '## [X.Y.Z]' near the top."
exit 1
fi
echo "Found version: $VERSION"
# Set environment variables for the release step
# RELEASE_TAG often includes a 'v' prefix, RELEASE_VERSION is the plain version
echo "RELEASE_VERSION=$VERSION" >> $GITHUB_ENV
echo "RELEASE_TAG=v$VERSION" >> $GITHUB_ENV # Add 'v' prefix for the tag
echo "Using tag: v$VERSION"
# Step 4: Create the release using the calculated tag
- name: Create Release
uses: "marvinpinto/action-automatic-releases@latest" uses: "marvinpinto/action-automatic-releases@latest"
with: with:
repo_token: "${{ secrets.GITHUB_TOKEN }}" repo_token: "${{ secrets.GITHUB_TOKEN }}"
automatic_release_tag: v${{ env.NEW_RUN_NUMBER }} # Use the environment variable set in the previous step
# automatic_release_tag: ${{ env.NEXT_TAG }}
automatic_release_tag: ${{ env.RELEASE_TAG }}
# Keep prerelease as false unless you want preview releases
prerelease: false prerelease: false
title: "Build v${{ env.NEW_RUN_NUMBER }}" # Update the title to use the new tag
# title: "Build ${{ env.NEXT_TAG }}"
title: "Build ${{ env.RELEASE_TAG }}"
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
View File
@@ -1,3 +1,4 @@
.cache
bld bld
build/ build/
test/ test/
+5 -6
View File
@@ -12,9 +12,8 @@ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/build)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/build) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/build)
# Source files for various targets # Source files for various targets
file(GLOB LIND_OBJS "src/lindbergh/*.c" "src/lindbergh/*.cpp") file(GLOB LIND_OBJS "src/lindbergh/*.c")
list(FILTER LIND_OBJS EXCLUDE REGEX "src/lindbergh/lindbergh.o") list(FILTER LIND_OBJS EXCLUDE REGEX "src/lindbergh/lindbergh.c")
list(FILTER LIND_OBJS EXCLUDE REGEX "src/lindbergh/evdevinput.o")
file(GLOB XDIFF_SRCS "src/libxdiff/xdiff/*.c") file(GLOB XDIFF_SRCS "src/libxdiff/xdiff/*.c")
@@ -27,12 +26,12 @@ set(LINDBERGH_CXX_FLAGS ${LINDBERGH_C_FLAGS} -std=c++11)
set(LIBXDIFF_C_FLAGS -DHAVE_CONFIG_H -fPIC -m32) set(LIBXDIFF_C_FLAGS -DHAVE_CONFIG_H -fPIC -m32)
set(LIBSEGAAPI_CXX_FLAGS -m32 -fPIC -shared) set(LIBSEGAAPI_CXX_FLAGS -m32 -fPIC -shared)
set(LIBSEGAAPI_LINKER_FLAGS -m32 -lFAudio) set(LIBSEGAAPI_LINKER_FLAGS -m32 -lFAudio)
set(SHARED_LINKER_FLAGS -m32 -Wl,-z,defs -rdynamic -static-libstdc++ -static-libgcc -lc -ldl -lGL -lglut -lX11 -lSDL2 -lm -lpthread -shared -lstdc++ -nostdlib -lasound) set(SHARED_LINKER_FLAGS -m32 -Wl,-z,defs -rdynamic -static-libstdc++ -static-libgcc -lc -ldl -lGL -lglut -lX11 -lXcursor -lSDL2 -lm -lpthread -shared -lstdc++ -nostdlib -lasound)
# Build executable for lindbergh # Build executable for lindbergh
add_executable(lindyloader src/lindbergh/lindbergh.c src/lindbergh/evdevinput.c src/lindbergh/evdevinput.h) add_executable(lindyloader src/lindbergh/lindbergh.c src/lindbergh/evdevinput.c src/lindbergh/evdevinput.h src/lindbergh/log.c src/lindbergh/log.h src/lindbergh/jvs.c src/lindbergh/jvs.h src/lindbergh/config.h src/lindbergh/config.c)
set_target_properties(lindyloader PROPERTIES OUTPUT_NAME "lindbergh") set_target_properties(lindyloader PROPERTIES OUTPUT_NAME "lindbergh")
set_target_properties(lindyloader PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} LINK_FLAGS "-m32") set_target_properties(lindyloader PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} LINK_FLAGS "-m32 -lm")
target_compile_options(lindyloader PRIVATE ${LINDBERGH_EXE}) target_compile_options(lindyloader PRIVATE ${LINDBERGH_EXE})
# Build static library libxdiff.a with its own flags # Build static library libxdiff.a with its own flags
+1 -1
View File
@@ -1,4 +1,4 @@
[![Actions Status](https://github.com/lindbergh-loader/lindbergh-loader/actions/workflows/ci.yml/badge.svg)](https://github.com/lindbergh-loader/lindbergh-loader/actions) [![Actions Status](https://github.com/lindbergh-loader/lindbergh-loader/actions/workflows/main.yml/badge.svg)](https://github.com/lindbergh-loader/lindbergh-loader/actions)
# SEGA Lindbergh Emulator # SEGA Lindbergh Emulator
+32
View File
@@ -1,6 +1,38 @@
# 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.14]
### Added
- Bobby's birthday checking!
- FPS target to float.
### Fixed
- a bub in config.c where MJ4_ENABLED_ALL_THE_TIME was using the wrong variable.
## [2.0.13]
### Added
- Clear window when the game is loading to prevent ghosting in SDL
- Prevent the created windows to resize/maximize.
- Version in github now matches the version in the changelog.
### Fixed
- Fixed a bug in Let's Go Jungle Special Resolution Patch.
- Cleaned unnecessary global variables in resolution.c
- Fixed a bug in that prevented the loader to start when the current folder contained spaces and lindbergh.so was there.
## [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.
+30
View File
@@ -0,0 +1,30 @@
#!/usr/bin/env bash
APPIMAGEDIRNAME=lindbergh-loader.AppDir
OUTPUT_FOLDER=$(realpath "./$APPIMAGEDIRNAME")
mkdir build-deps
cd build-deps
# Build openal
wget https://github.com/kcat/openal-soft/archive/refs/tags/openal-soft-1.17.2.tar.gz
tar -xzf openal-soft-1.17.2.tar.gz
cd openal-soft-openal-soft-1.17.2/build
CFLAGS="-m32 -mstackrealign" CXXFLAGS="-m32 -std=c++14 -mstackrealign" cmake ../ -DALSOFT_BACKEND_PULSEAUDIO=ON -DALSOFT_BACKEND_ALSA=ON -DALSOFT_BACKEND_JACK=OFF -DALSOFT_BACKEND_SNDIO=ON
make -j4
sudo cp libopenal.so.1.17.2 /usr/lib/i386-linux-gnu/libopenal.so.0
cd ../../
# Build libSSL and libCrypto
wget https://github.com/openssl/openssl/archive/refs/tags/OpenSSL_0_9_7.tar.gz
tar -xzf OpenSSL_0_9_7.tar.gz
cd openssl-OpenSSL_0_9_7
cp ../../scripts/appimage/patches/openssl-0.9.7.patch .
./Configure shared 386 no-asm no-krb5 linux-pentium -m32
patch -p1 < openssl-0.9.7.patch
CFLAGS=-m32 make
sudo cp libcrypto.so.0.9.7 /usr/lib/i386-linux-gnu
sudo cp libssl.so.0.9.7 /usr/lib/i386-linux-gnu
+11
View File
@@ -0,0 +1,11 @@
#!/usr/bin/env bash
echo "Install Packages Running..."
sudo dpkg --add-architecture i386
sudo apt update
sudo apt -y install --no-install-recommends \
build-essential gcc-multilib g++-multilib cmake fuse freeglut3-dev:i386 libsdl2-dev:i386 libfaudio-dev:i386 libvdpau1:i386 \
libstdc++5:i386 libxmu6:i386 libpcsclite1:i386 libncurses5:i386 unzip libsndio-dev:i386
sudo add-apt-repository ppa:kisak/kisak-mesa -y
sudo apt update -y && sudo apt upgrade -y
+104
View File
@@ -0,0 +1,104 @@
#!/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"
"libICE.so.6"
"libSM.so.6"
"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"
"libm.so.6"
"libopenal.so.0"
"libcrypto.so.0.9.7"
"libssl.so.0.9.7"
"libuuid.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
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/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,13 @@
diff -ruN openssl-OpenSSL_0_9_7.orig/Makefile.ssl openssl-OpenSSL_0_9_7/Makefile.ssl
--- openssl-OpenSSL_0_9_7.orig/Makefile.ssl 2025-04-14 05:05:11.162340308 +0000
+++ openssl-OpenSSL_0_9_7/Makefile.ssl 2025-04-14 05:06:22.261420144 +0000
@@ -198,7 +198,7 @@
SHARED_SSL=libssl$(SHLIB_EXT)
SHARED_LIBS=$(SHARED_CRYPTO) $(SHARED_SSL)
SHARED_LIBS_LINK_EXTS=.so.$(SHLIB_MAJOR) .so
-SHARED_LDFLAGS=
+SHARED_LDFLAGS=-m32
GENERAL= Makefile
BASENAME= openssl
@@ -22,7 +22,6 @@ sdk-extensions:
finish-args: finish-args:
- --env=LD_LIBRARY_PATH=/app/lib32:$LD_LIBRARY_PATH - --env=LD_LIBRARY_PATH=/app/lib32:$LD_LIBRARY_PATH
- --env=LDFLAGS="-L/app/lib32"
- --env=PATH=/app/bin:/usr/bin - --env=PATH=/app/bin:/usr/bin
- --allow=multiarch - --allow=multiarch
- --share=ipc - --share=ipc
@@ -73,7 +72,7 @@ modules:
x86_64: *i386-build-options x86_64: *i386-build-options
sources: sources:
- type: archive - type: archive
url: https://mesa.freedesktop.org/archive/glu/glu-9.0.2.tar.xz url: https://archive.mesa3d.org/glu/glu-9.0.2.tar.xz
sha256: 6e7280ff585c6a1d9dfcdf2fca489251634b3377bfc33c29e4002466a38d02d4 sha256: 6e7280ff585c6a1d9dfcdf2fca489251634b3377bfc33c29e4002466a38d02d4
# Build 32-bit freeglut # Build 32-bit freeglut
+7
View File
@@ -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

+204 -181
View File
@@ -29,10 +29,10 @@
typedef struct typedef struct
{ {
uint32_t srcAddress; uint32_t srcAddress;
uint32_t srcSize; uint32_t srcSize;
uint32_t destAddress; uint32_t destAddress;
uint32_t destSize; uint32_t destSize;
} BaseboardCommand; } BaseboardCommand;
BaseboardCommand jvsCommand = {0}; BaseboardCommand jvsCommand = {0};
@@ -40,16 +40,16 @@ BaseboardCommand serialCommand = {0};
typedef struct typedef struct
{ {
uint32_t *data; uint32_t *data;
uint32_t offset; uint32_t offset;
uint32_t size; uint32_t size;
} readData_t; } readData_t;
typedef struct typedef struct
{ {
uint32_t offset; uint32_t offset;
uint32_t *data; uint32_t *data;
uint32_t size; uint32_t size;
} writeData_t; } writeData_t;
FILE *sram = NULL; FILE *sram = NULL;
@@ -61,226 +61,249 @@ int selectReply = -1;
int jvsFileDescriptor = -1; int jvsFileDescriptor = -1;
int jvsPacketSize = -1; int jvsPacketSize = -1;
char serialString[1024] = {0};
int initBaseboard() 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 // Create file if it doesn't exist
if (sram == NULL) 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)
{ {
printf("Error: Failed to open %s for JVS\n", getConfig()->jvsPath); printf("Error: Cannot open %s\n", sramPath);
return -1; 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); strcpy(serialString, SERIAL_STRING);
startJVSFrameThread(&jvsFileDescriptor);
}
return 0; time_t t = time(NULL); // Get current time
struct tm *tm_info = localtime(&t); // Convert to local time structure
int month = tm_info->tm_mon + 1; // tm_mon is 0-based (0 = Jan, 4 = May)
int day = tm_info->tm_mday; // tm_mday is the day of the month
if (month == 1 && day == 18) {
strcpy(serialString, "HAPPY BIRTHDAY!!");
}
if (month == 5 && day == 20) {
strcpy(serialString, "HAPPY BIRTHDAY!!");
}
if (month == 5 && day == 21) {
strcpy(serialString, "HAPPY BIRTHDAY!!");
}
return 0;
} }
ssize_t baseboardRead(int fd, void *buf, size_t count) ssize_t baseboardRead(int fd, void *buf, size_t count)
{ {
memcpy(buf, &sharedMemory[sharedMemoryIndex], count); memcpy(buf, &sharedMemory[sharedMemoryIndex], count);
return count; return count;
} }
ssize_t baseboardWrite(int fd, const void *buf, size_t count) ssize_t baseboardWrite(int fd, const void *buf, size_t count)
{ {
memcpy(&sharedMemory[sharedMemoryIndex], buf, count); memcpy(&sharedMemory[sharedMemoryIndex], buf, count);
return 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) int baseboardIoctl(int fd, unsigned int request, void *data)
{ {
switch (request) 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])
{ {
case BASEBOARD_GET_SERIAL: // bcCmdSysInfoGetReq case BASEBOARD_GET_VERSION:
{ {
serialCommand.destAddress = _data[1]; uint8_t versionData[4] = {0x00, 0x19, 0x20, 0x07};
serialCommand.destSize = _data[2]; memcpy(data, versionData, 4);
return 0;
} }
break; 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; break;
case BASEBOARD_PROCESS_JVS: case BASEBOARD_READY: // Not sure if this is what it should be called
{ {
jvsCommand.srcAddress = _data[1]; selectReply = 0;
jvsCommand.srcSize = _data[2]; return 0;
jvsCommand.destAddress = _data[3]; }
jvsCommand.destSize = _data[4]; break;
memcpy(inputBuffer, &sharedMemory[jvsCommand.srcAddress], jvsCommand.srcSize);
if (getConfig()->emulateJVS) case BASEBOARD_SEEK_SHM:
{ {
processPacket(&jvsPacketSize); sharedMemoryIndex = (unsigned int)data;
} return 0;
else if (jvsFileDescriptor >= 0) }
{ break;
for (int i = 0; i < jvsCommand.srcSize; i++)
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) case BASEBOARD_GET_SERIAL: // bcCmdSysInfoGetReq
{ {
setSenseLine(3); serialCommand.destAddress = _data[1];
} serialCommand.destSize = _data[2];
else if (inputBuffer[i] == 0xF1)
{
setSenseLine(1);
}
} }
} 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; break;
case BASEBOARD_GET_SENSE_LINE: case BASEBOARD_RECEIVE:
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)
{ {
uint32_t *_data = data;
case BASEBOARD_GET_SERIAL: switch (_data[0] & 0xFFF)
{ {
memcpy(&sharedMemory[serialCommand.destAddress + 96], SERIAL_STRING, strlen(SERIAL_STRING));
_data[1] = 1; // Set the status to success
}
break;
case BASEBOARD_GET_SENSE_LINE: case BASEBOARD_GET_SERIAL:
{ {
_data[2] = getSenseLine(); memcpy(&sharedMemory[serialCommand.destAddress + 96], serialString, strlen(serialString));
_data[1] = 1; // Set the status to success _data[1] = 1; // Set the status to success
} }
break; break;
case BASEBOARD_PROCESS_JVS: case BASEBOARD_GET_SENSE_LINE:
{ {
if (getConfig()->emulateJVS) _data[2] = getSenseLine();
{ _data[1] = 1; // Set the status to success
memcpy(&sharedMemory[jvsCommand.destAddress], outputBuffer, jvsPacketSize); }
_data[2] = jvsCommand.destAddress; break;
_data[3] = jvsPacketSize;
_data[1] = 1; // Set the status to success case BASEBOARD_PROCESS_JVS:
} {
else if (jvsFileDescriptor >= 0) if (getConfig()->emulateJVS)
{ {
JVSFrame frame = readJVSFrameFromThread(); memcpy(&sharedMemory[jvsCommand.destAddress], outputBuffer, jvsPacketSize);
memcpy(&sharedMemory[jvsCommand.destAddress], frame.buffer, frame.size); _data[2] = jvsCommand.destAddress;
_data[2] = jvsCommand.destAddress; _data[3] = jvsPacketSize;
_data[3] = frame.size; _data[1] = 1; // Set the status to success
_data[1] = frame.ready; }
} 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; break;
default: 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; 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) int carReaderGetFdIdx(int fd)
{ {
if (fd == serialFD[0].fd) return (fd == serialFD[0].fd) ? 0 : 1;
return 0;
return 1;
} }
uint8_t cardReaderGenChecksum(int fdIdx) uint8_t cardReaderGenChecksum(int fdIdx)
+1
View File
@@ -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>
+13 -3
View File
@@ -174,6 +174,8 @@ static int detectGame(uint32_t elf_crc)
config.gameStatus = WORKING; config.gameStatus = WORKING;
config.jvsIOType = SEGA_TYPE_1; config.jvsIOType = SEGA_TYPE_1;
config.gameType = ABC; config.gameType = ABC;
config.width = 640;
config.height = 480;
return 0; return 0;
} }
break; break;
@@ -188,6 +190,8 @@ static int detectGame(uint32_t elf_crc)
config.gameStatus = WORKING; config.gameStatus = WORKING;
config.jvsIOType = SEGA_TYPE_1; config.jvsIOType = SEGA_TYPE_1;
config.gameType = ABC; config.gameType = ABC;
config.width = 640;
config.height = 480;
return 0; return 0;
} }
break; break;
@@ -249,6 +253,8 @@ static int detectGame(uint32_t elf_crc)
config.gameNativeResolutions = ""; config.gameNativeResolutions = "";
config.gameType = DRIVING; config.gameType = DRIVING;
config.gameStatus = WORKING; config.gameStatus = WORKING;
config.width = 1280;
config.height = 768;
return 0; return 0;
} }
break; break;
@@ -262,6 +268,8 @@ static int detectGame(uint32_t elf_crc)
config.gameNativeResolutions = "1280x768"; config.gameNativeResolutions = "1280x768";
config.gameType = DRIVING; config.gameType = DRIVING;
config.gameStatus = WORKING; config.gameStatus = WORKING;
config.width = 1280;
config.height = 768;
return 0; return 0;
} }
break; break;
@@ -275,6 +283,8 @@ static int detectGame(uint32_t elf_crc)
config.gameNativeResolutions = ""; config.gameNativeResolutions = "";
config.gameType = DRIVING; config.gameType = DRIVING;
config.gameStatus = WORKING; config.gameStatus = WORKING;
config.width = 1280;
config.height = 768;
return 0; return 0;
} }
break; break;
@@ -1228,7 +1238,7 @@ int readConfig(FILE *configFile, EmulatorConfig *config)
config->fpsLimiter = atoi(getNextToken(NULL, " ", &saveptr)); config->fpsLimiter = atoi(getNextToken(NULL, " ", &saveptr));
else if (strcmp(command, "FPS_TARGET") == 0) else if (strcmp(command, "FPS_TARGET") == 0)
config->fpsTarget = atoi(getNextToken(NULL, " ", &saveptr)); config->fpsTarget = atof(getNextToken(NULL, " ", &saveptr));
else if (strcmp(command, "LGJ_RENDER_WITH_MESA") == 0) else if (strcmp(command, "LGJ_RENDER_WITH_MESA") == 0)
config->lgjRenderWithMesa = atoi(getNextToken(NULL, " ", &saveptr)); config->lgjRenderWithMesa = atoi(getNextToken(NULL, " ", &saveptr));
@@ -1264,7 +1274,7 @@ int readConfig(FILE *configFile, EmulatorConfig *config)
config->phTouchCursorHeight = atoi(getNextToken(NULL, " ", &saveptr)); config->phTouchCursorHeight = atoi(getNextToken(NULL, " ", &saveptr));
else if (strcmp(command, "MJ4_ENABLED_ALL_THE_TIME") == 0) else if (strcmp(command, "MJ4_ENABLED_ALL_THE_TIME") == 0)
config->phMode = atoi(getNextToken(NULL, " ", &saveptr)); config->mj4EnabledAtT = atoi(getNextToken(NULL, " ", &saveptr));
else if (strcmp(command, "OR2_IP") == 0) else if (strcmp(command, "OR2_IP") == 0)
strcpy(config->or2IP, getNextToken(NULL, " ", &saveptr)); strcpy(config->or2IP, getNextToken(NULL, " ", &saveptr));
@@ -1557,7 +1567,7 @@ int initConfig(const char* configFilePath)
config.jvsIOType = SEGA_TYPE_3; config.jvsIOType = SEGA_TYPE_3;
config.GPUVendor = AUTO_DETECT_GPU; config.GPUVendor = AUTO_DETECT_GPU;
config.fpsLimiter = 0; config.fpsLimiter = 0;
config.fpsTarget = 60; config.fpsTarget = 60.0f;
config.noSDL = 0; config.noSDL = 0;
config.phMode = 2; config.phMode = 2;
config.disableBuiltinFont = 0; config.disableBuiltinFont = 0;
+1 -1
View File
@@ -261,7 +261,7 @@ typedef struct
int hummerFlickerFix; int hummerFlickerFix;
int keepAspectRatio; int keepAspectRatio;
int fpsLimiter; int fpsLimiter;
int fpsTarget; float fpsTarget;
int lgjRenderWithMesa; int lgjRenderWithMesa;
int noSDL; int noSDL;
int phMode; int phMode;
-1
View File
@@ -1,4 +1,3 @@
// #pragma once
int loadNewCursor(const char *cursorFileName, void **cursor, int customWidth, int customHeight); int loadNewCursor(const char *cursorFileName, void **cursor, int customWidth, int customHeight);
void loadCursors(); void loadCursors();
+5 -19
View File
@@ -302,6 +302,7 @@ void __attribute__((constructor)) hook_init()
} }
getGPUVendor(); getGPUVendor();
if (initPatch() != 0) if (initPatch() != 0)
exit(1); exit(1);
@@ -763,6 +764,7 @@ FILE *fopen(const char *restrict pathname, const char *restrict mode)
{ {
return 0; return 0;
} }
if (cachedShaderFilesLoaded) if (cachedShaderFilesLoaded)
{ {
void *addr = __builtin_return_address(0); void *addr = __builtin_return_address(0);
@@ -1079,17 +1081,11 @@ ssize_t read(int fd, void *buf, size_t count)
return driveboardRead(fd, buf, 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); 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 (fd == hooks[SERIAL0] || fd == hooks[SERIAL1])
{ {
if (gId == PRIMEVAL_HUNT && getConfig()->emulateTouchscreen == 1) if (gId == PRIMEVAL_HUNT && getConfig()->emulateTouchscreen == 1)
@@ -1136,11 +1132,6 @@ size_t fread(void *buf, size_t size, size_t count, FILE *stream)
return freadReplace(buf, size, count, fileRead[FILE_RW2]); 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]) if (stream == fileHooks[FILE_FONT_ABC])
{ {
memcpy(buf, fontABC + fontABCidx, size * count); memcpy(buf, fontABC + fontABCidx, size * count);
@@ -1278,12 +1269,7 @@ ssize_t write(int fd, const void *buf, size_t count)
return driveboardWrite(fd, buf, count); return driveboardWrite(fd, buf, count);
} }
if (fd == hooks[SERIAL0] && getConfig()->emulateCardreader) if ((fd == hooks[SERIAL0] || fd == hooks[SERIAL1]) && getConfig()->emulateCardreader)
{
return cardReaderWrite(fd, buf, count);
}
if (fd == hooks[SERIAL1] && getConfig()->emulateCardreader)
{ {
return cardReaderWrite(fd, buf, count); return cardReaderWrite(fd, buf, count);
} }
@@ -1685,7 +1671,7 @@ int setenv(const char *name, const char *value, int overwrite)
/** /**
* @brief Hook for the getenv function. * @brief Hook for the getenv function.
* *
* This function iFake the TEA_DIR environment variable to games that require it to run * This function "Fakes" the TEA_DIR environment variable to games that require it to run
* @param name The name of the environment variable. * @param name The name of the environment variable.
*/ */
char *getenv(const char *name) char *getenv(const char *name)
+279 -505
View File
@@ -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,147 @@ 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]; if (fileExists(PRELOAD_FILE_NAME))
struct stat st; return PRELOAD_FILE_NAME;
char *resultPath = NULL;
for (int i = 0; i < numCandidates; ++i) for (int i = 0; i < sizeof(folderCandidates) / sizeof(folderCandidates[0]); 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;
}
} }
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 *appImgRoot = getenv("APP_IMG_ROOT");
if (appImgRoot != NULL)
{
char libglDriPath[MAX_PATH_LENGTH];
sprintf(libglDriPath, "%s/usr/lib32/dri", appImgRoot);
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 +364,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 +377,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 +394,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 +418,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 +469,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 +631,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;
+10 -6
View File
@@ -212,8 +212,8 @@ void *readJVSFrameThread(void * arg)
* @param fd * @param fd
* @return 0|1 * @return 0|1
*/ */
int startJVSFrameThread(int * fd) { int startJVSFrameThread(int *fd)
int fdlocal = *((int *) fd); {
printf("SERIAL: starting thread.\n"); printf("SERIAL: starting thread.\n");
// Clean shared JVS frame buffer // 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 a JVSFrame structure with empty or full data, no in between
* @return * @return
*/ */
JVSFrame readJVSFrameFromThread() { JVSFrame readJVSFrameFromThread()
{
JVSFrame frame; JVSFrame frame;
// Lock while reading/writing to shared frame // Lock while reading/writing to shared frame
pthread_mutex_lock(&jvsBuffer_lock); pthread_mutex_lock(&jvsBuffer_lock);
// Check if we have a valid frame // Check if we have a valid frame
if (jvsFrameBuffer.ready == 1) { if (jvsFrameBuffer.ready == 1)
{
frame = jvsFrameBuffer; frame = jvsFrameBuffer;
// It has been red, we disable this frame // It has been read, we disable this frame
jvsFrameBuffer.ready = 0; jvsFrameBuffer.ready = 0;
} else { }
else
{
frame.ready = 0; frame.ready = 0;
frame.size = 0; frame.size = 0;
memset(frame.buffer, 0, JVSBUFFER_SIZE); memset(frame.buffer, 0, JVSBUFFER_SIZE);
+1
View File
@@ -2136,6 +2136,7 @@ int initPatch()
detourFunction(0x084d44fc, amDipswSetLed); detourFunction(0x084d44fc, amDipswSetLed);
detourFunction(0x084d4485, amDipswGetData); detourFunction(0x084d4485, amDipswGetData);
patchMemory(0x0804edb2, "9090909090"); //__intel_new_proc_init_P patchMemory(0x0804edb2, "9090909090"); //__intel_new_proc_init_P
detourFunction(0x08178e6c, stubRetOne); // _ZN7am_ctrl18SetNetworkAddrEth0Ejj.
detourFunction(0x0804e594, gl_XGetProcAddressARB); detourFunction(0x0804e594, gl_XGetProcAddressARB);
srtvElfShaderPatcher(); srtvElfShaderPatcher();
+251 -30
View File
@@ -48,11 +48,6 @@ float newReducedWidthABC, newReducedHeightABC;
float newHalfWidthABC, newHalfHeightABC; float newHalfWidthABC, newHalfHeightABC;
float newWidthRangeABC, newHeightRangeABC; float newWidthRangeABC, newHeightRangeABC;
double new410ABC, new330ABC, new280ABC, new200ABC; double new410ABC, new330ABC, new280ABC, new200ABC;
uint32_t *newWidthRangePtr_CEI_ABC, *newHeightRangePtr_CEI_ABC;
uint32_t *newWidthPtrABC, *newHeightPtrABC;
uint32_t *newReducedWidthPtrABC, *newReducedHeightPtrABC;
uint32_t *newHalfWidthPtrABC, *newHalfHeightPtrABC;
uint32_t *new410PtrABC, *new330PtrABC, *new280PtrABC, *new200PtrABC;
float angleABC; float angleABC;
float newVT3, newVT3HW, newVT3HH; float newVT3, newVT3HW, newVT3HH;
@@ -68,6 +63,9 @@ int idTextShift = 0;
float id4NewCaptionY; float id4NewCaptionY;
float idShiftX = 0.0; float idShiftX = 0.0;
float isShiftY = 0.0; float isShiftY = 0.0;
float newHeightLGJ, newWidth2LGJ, newWidthHLGJ, newWidthSLGJ;
bool myEnableScaling = false; bool myEnableScaling = false;
int hummerRespatch() int hummerRespatch()
@@ -1062,15 +1060,15 @@ void patchABCMarkers(uint32_t addrCtrlEnemyInfo, uint32_t addrCtrlPlayerRivalFon
new280ABC = (gWidth / 2.0) - 40.0; // 280 new280ABC = (gWidth / 2.0) - 40.0; // 280
new200ABC = (gHeight / 2.0) - 40.0; // 200 new200ABC = (gHeight / 2.0) - 40.0; // 200
newWidthPtrABC = (uint32_t *)&newWidthABC; uint32_t *newWidthPtrABC = (uint32_t *)&newWidthABC;
newHeightPtrABC = (uint32_t *)&newHeightABC; uint32_t *newHeightPtrABC = (uint32_t *)&newHeightABC;
setVariable(addrCtrlPlayerRivalFont + 0x15b, (size_t)newWidthPtrABC); // 640 setVariable(addrCtrlPlayerRivalFont + 0x15b, (size_t)newWidthPtrABC); // 640
setVariable(addrCtrlPlayerRivalFont + 0x163, (size_t)newHeightPtrABC); // 480 setVariable(addrCtrlPlayerRivalFont + 0x163, (size_t)newHeightPtrABC); // 480
setVariable(addrCtrlEnemyPursuit2d + 0x80, (size_t)newWidthPtrABC); // 640 setVariable(addrCtrlEnemyPursuit2d + 0x80, (size_t)newWidthPtrABC); // 640
setVariable(addrCtrlEnemyPursuit2d + 0x88, (size_t)newHeightPtrABC); // 480 setVariable(addrCtrlEnemyPursuit2d + 0x88, (size_t)newHeightPtrABC); // 480
newReducedWidthPtrABC = (uint32_t *)&newReducedWidthABC; uint32_t *newReducedWidthPtrABC = (uint32_t *)&newReducedWidthABC;
newReducedHeightPtrABC = (uint32_t *)&newReducedHeightABC; uint32_t *newReducedHeightPtrABC = (uint32_t *)&newReducedHeightABC;
setVariable(addrCtrlPlayerRivalFont + 0x272, (size_t)newReducedWidthPtrABC); // 600 setVariable(addrCtrlPlayerRivalFont + 0x272, (size_t)newReducedWidthPtrABC); // 600
setVariable(addrCtrlPlayerRivalFont + 0x29f, (size_t)newReducedHeightPtrABC); // 440 setVariable(addrCtrlPlayerRivalFont + 0x29f, (size_t)newReducedHeightPtrABC); // 440
setVariable(addrCtrlPlayerRivalFont + 0x8ff, *(uint32_t *)&newReducedHeightABC); // 440 setVariable(addrCtrlPlayerRivalFont + 0x8ff, *(uint32_t *)&newReducedHeightABC); // 440
@@ -1081,8 +1079,8 @@ void patchABCMarkers(uint32_t addrCtrlEnemyInfo, uint32_t addrCtrlPlayerRivalFon
setVariable(addrCtrlEnemyPursuit2d + 0x7b3, *(uint32_t *)&newReducedHeightABC); // 440 setVariable(addrCtrlEnemyPursuit2d + 0x7b3, *(uint32_t *)&newReducedHeightABC); // 440
setVariable(addrCtrlEnemyPursuit2d + 0x812, *(uint32_t *)&newReducedHeightABC); // 440 setVariable(addrCtrlEnemyPursuit2d + 0x812, *(uint32_t *)&newReducedHeightABC); // 440
newHalfWidthPtrABC = (uint32_t *)&newHalfWidthABC; uint32_t *newHalfWidthPtrABC = (uint32_t *)&newHalfWidthABC;
newHalfHeightPtrABC = (uint32_t *)&newHalfHeightABC; uint32_t *newHalfHeightPtrABC = (uint32_t *)&newHalfHeightABC;
setVariable(addrCtrlPlayerRivalFont + 0x346, (size_t)newHalfWidthPtrABC); // 320 setVariable(addrCtrlPlayerRivalFont + 0x346, (size_t)newHalfWidthPtrABC); // 320
setVariable(addrCtrlPlayerRivalFont + 0x34e, (size_t)newHalfHeightPtrABC); // 240 setVariable(addrCtrlPlayerRivalFont + 0x34e, (size_t)newHalfHeightPtrABC); // 240
setVariable(addrCtrlPlayerRivalFont + 0x4cb, (size_t)newHalfWidthPtrABC); // 320 setVariable(addrCtrlPlayerRivalFont + 0x4cb, (size_t)newHalfWidthPtrABC); // 320
@@ -1108,10 +1106,10 @@ void patchABCMarkers(uint32_t addrCtrlEnemyInfo, uint32_t addrCtrlPlayerRivalFon
setVariable(addrCtrlEnemyPursuit2d + 0x4ea, *(uint32_t *)&newWidthRangeABC); // 730 setVariable(addrCtrlEnemyPursuit2d + 0x4ea, *(uint32_t *)&newWidthRangeABC); // 730
setVariable(addrCtrlEnemyPursuit2d + 0x77b, *(uint32_t *)&newHeightRangeABC); // 570 setVariable(addrCtrlEnemyPursuit2d + 0x77b, *(uint32_t *)&newHeightRangeABC); // 570
new410PtrABC = (uint32_t *)&new410ABC; uint32_t *new410PtrABC = (uint32_t *)&new410ABC;
new330PtrABC = (uint32_t *)&new330ABC; uint32_t *new330PtrABC = (uint32_t *)&new330ABC;
new280PtrABC = (uint32_t *)&new280ABC; uint32_t *new280PtrABC = (uint32_t *)&new280ABC;
new200PtrABC = (uint32_t *)&new200ABC; uint32_t *new200PtrABC = (uint32_t *)&new200ABC;
setVariable(addrCtrlPlayerRivalFont + 0x40e, (size_t)new410PtrABC); // 410 setVariable(addrCtrlPlayerRivalFont + 0x40e, (size_t)new410PtrABC); // 410
setVariable(addrCtrlPlayerRivalFont + 0x44a, (size_t)new330PtrABC); // 330 setVariable(addrCtrlPlayerRivalFont + 0x44a, (size_t)new330PtrABC); // 330
setVariable(addrCtrlPlayerRivalFont + 0x5de, (size_t)new280PtrABC); // 280 setVariable(addrCtrlPlayerRivalFont + 0x5de, (size_t)new280PtrABC); // 280
@@ -1267,6 +1265,182 @@ void glVertex3fHOD4(GLfloat x, GLfloat y, GLfloat z)
_glVertex3f(x, y, 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)
{ // deadend
;
}
else
{
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) void glVertex3fHarley(GLfloat x, GLfloat y, GLfloat z)
{ {
int (*_glVertex3f)(GLfloat x, GLfloat y, GLfloat z) = dlsym(RTLD_NEXT, "glVertex3f"); int (*_glVertex3f)(GLfloat x, GLfloat y, GLfloat z) = dlsym(RTLD_NEXT, "glVertex3f");
@@ -1286,11 +1460,6 @@ void glVertex3fHarley(GLfloat x, GLfloat y, GLfloat z)
y *= scaleY; y *= scaleY;
} }
void *addr = __builtin_return_address(0); 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) if (z == -5300.7529296875)
{ // 1080p { // 1080p
printf("glVertex3f hooked: x=%f, y=%f, z=%f, addr: %p\n", x, y, z, addr); printf("glVertex3f hooked: x=%f, y=%f, z=%f, addr: %p\n", x, y, z, addr);
@@ -1301,6 +1470,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;
@@ -2233,23 +2434,18 @@ int initResolutionPatches()
setVariable(0x080d6ea0, gWidth); // 800 setVariable(0x080d6ea0, gWidth); // 800
setVariable(0x080d6eaa, gHeight); // 600 setVariable(0x080d6eaa, gHeight); // 600
patchMemory(0x08303c27, "01"); // FSAA
setVariable(0x080cf6ac, gWidth); // 800 newHeightLGJ = (float)gHeight;
setVariable(0x080cf6b9, gHeight); // 600
patchMemory(0x08303c27, "01"); // FSAA
float newWidthLGJ = (float)gWidth;
float newHeightLGJ = (float)gHeight;
uint32_t *newWidthPtrLGJ = (uint32_t *)&newWidthLGJ;
uint32_t *newHeightPtrLGJ = (uint32_t *)&newHeightLGJ; uint32_t *newHeightPtrLGJ = (uint32_t *)&newHeightLGJ;
float newWidth2LGJ = (float)gWidth * 2.0; newWidth2LGJ = (float)gWidth * 2.0;
uint32_t *newWidth2PtrLGJ = (uint32_t *)&newWidth2LGJ; uint32_t *newWidth2PtrLGJ = (uint32_t *)&newWidth2LGJ;
unsigned int address = 0x080cb730; unsigned int address = 0x080cb730;
float newWidthHLGJ = (float)gWidth / 2.0; newWidthHLGJ = (float)gWidth / 2.0;
uint32_t *newWidthHPtrLGJ = (uint32_t *)&newWidthHLGJ; uint32_t *newWidthHPtrLGJ = (uint32_t *)&newWidthHLGJ;
float newWidthSLGJ = 1360.0 / (float)gWidth; newWidthSLGJ = 1360.0 / (float)gWidth;
uint32_t *newWidthSPtrLGJ = (uint32_t *)&newWidthSLGJ; uint32_t *newWidthSPtrLGJ = (uint32_t *)&newWidthSLGJ;
unsigned int addressC = 0x080cb3be; unsigned int addressC = 0x080cb3be;
@@ -2655,6 +2851,21 @@ int initResolutionPatches()
{ {
break; 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");
setVariable(0x087aa080, gWidth); // render res
patchMemory(0x0804e60c, "909090909090");
patchMemory(0x0828cc2f, "909090909090");
} }
break; break;
case TOO_SPICY: case TOO_SPICY:
@@ -2669,6 +2880,16 @@ int initResolutionPatches()
{ {
break; 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; break;
case TOO_SPICY_TEST: case TOO_SPICY_TEST:
+11 -1
View File
@@ -119,7 +119,7 @@ void initSDL(int *argcp, char **argv)
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 1); SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 1);
} }
uint32_t windowFlags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE; uint32_t windowFlags = SDL_WINDOW_OPENGL;
strcat(SDLgameTitle, getGameName()); strcat(SDLgameTitle, getGameName());
@@ -156,6 +156,16 @@ void initSDL(int *argcp, char **argv)
fprintf(stderr, "OpenGL context could not be created! SDL_Error: %s\n", SDL_GetError()); fprintf(stderr, "OpenGL context could not be created! SDL_Error: %s\n", SDL_GetError());
exit(1); exit(1);
} }
glClearColor(0.1f, 0.1f, 0.1f, 1.0f); // Your bg color
// Force initial clear
glClear(GL_COLOR_BUFFER_BIT);
SDL_GL_SwapWindow(SDLwindow);
// Now show the window
SDL_ShowWindow(SDLwindow);
printf(" SDL RESOLUTION: %dx%d\n\n", getConfig()->width, getConfig()->height); printf(" SDL RESOLUTION: %dx%d\n\n", getConfig()->width, getConfig()->height);
if (getConfig()->fullscreen) if (getConfig()->fullscreen)
+8 -7
View File
@@ -1,7 +1,6 @@
#ifndef __i386__ #ifndef __i386__
#define __i386__ #define __i386__
#include "log.h"
#include <stdint.h> #include <stdint.h>
#endif #endif
#undef __x86_64__ #undef __x86_64__
@@ -1548,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)
{ {
@@ -1560,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;
@@ -1578,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)
+26
View File
@@ -60,6 +60,20 @@ Display *XOpenDisplay(const char *display_name)
return x11Display; return x11Display;
} }
void setWindowProperties(Display *display, Window window)
{
XSizeHints *hints = XAllocSizeHints();
hints->flags = PMinSize | PMaxSize;
hints->min_width = hints->max_width = getConfig()->width;
hints->min_height = hints->max_height = getConfig()->height;
XSetWMNormalHints(display, window, hints);
XFree(hints);
Atom hintsAtom = XInternAtom(display, "_MOTIF_WM_HINTS", False);
XMapWindow(display, window);
XFlush(display);
}
Window XCreateWindow(Display *display, Window parent, int x, int y, unsigned int width, unsigned int height, unsigned int border_width, Window XCreateWindow(Display *display, Window parent, int x, int y, unsigned int width, unsigned int height, unsigned int border_width,
int depth, unsigned int class, Visual *visual, unsigned long valueMask, XSetWindowAttributes *attributes) int depth, unsigned int class, Visual *visual, unsigned long valueMask, XSetWindowAttributes *attributes)
{ {
@@ -98,9 +112,21 @@ Window XCreateWindow(Display *display, Window parent, int x, int y, unsigned int
{ {
window = x11Window; window = x11Window;
} }
// Eliminate the maximize window button and no more resizing
if (!gettingGPUVendor && !creatingWindow)
setWindowProperties(display, window);
return window; return window;
} }
// Here we prevent the games to change the window properties
void XSetWMProperties(Display *display, Window w, XTextProperty *window_name, XTextProperty *icon_name, char **argv, int argc,
XSizeHints *normal_hints, XWMHints *wm_hints, XClassHint *class_hints)
{
return;
}
int XGrabPointer(Display *display, Window grab_window, Bool owner_events, unsigned int event_mask, int pointer_mode, int XGrabPointer(Display *display, Window grab_window, Bool owner_events, unsigned int event_mask, int pointer_mode,
int keyboard_mode, Window confine_to, Cursor cursor, Time time) int keyboard_mode, Window confine_to, Cursor cursor, Time time)
{ {