Compare commits

...
54 Commits
Author SHA1 Message Date
Bobby Dilley a3e3f51003 Attempt to fix LGJ with JVS 2025-03-25 18:50:16 +00:00
dkeruza-neo a96b1fcf30 Reverted reverse axis and shake in evdev. 2025-03-13 20:07:29 -04:00
dkeruza-neo 6e751f16f0 Fixed bug in ABC res patch after cleaning up code. 2025-03-09 16:19:41 -04:00
dkeruza-neo 03ccfd3449 Forgot to uncomment code. 2025-03-09 03:42:05 -04:00
dkeruza-neo 4e82f6fdef Again 2025-03-09 01:53:29 -05:00
dkeruza-neo ccf54ab6ad Fix release number? 2025-03-09 01:50:41 -05:00
dkeruza-neo 1fb45a1e5c Fixed autobuild script. 2025-03-09 00:49:25 -05:00
dkeruza-neo 9bbc0f983e Check the changelog. 2025-03-09 00:44:55 -05:00
dkeruza cc500aa7ef Merge pull request #62 from nadenislamarre/evdev-keys
evdev: add technical input values
2025-03-08 16:00:54 -05:00
dkeruza cafd6276c3 Workaround 6 2025-02-27 16:26:25 -05:00
dkeruza a2dbf1cbda Workaround 5 2025-02-27 15:43:56 -05:00
dkeruza 74d61985ec Workaround 4 2025-02-27 15:41:17 -05:00
dkeruza 4d0996b905 Workaround 3 2025-02-27 15:29:33 -05:00
dkeruza 52cb3eaf6b Workaround 2 2025-02-27 14:42:30 -05:00
dkeruza 8b6604efc5 Workaround - Ups2 2025-02-27 00:13:27 -05:00
dkeruza 7b426f0d11 Workaround - Ups 2025-02-27 00:11:06 -05:00
dkeruza 442d03b144 Update lindbergh.cWorkaround 2025-02-26 22:14:11 -05:00
dkeruza 50a1a35f7f Workaround 2025-02-26 22:05:53 -05:00
dkeruza 728c308835 Workaround 2025-02-17 22:14:12 -05:00
dkeruza 543ebe4817 Workaround 2025-02-17 22:12:40 -05:00
dkeruza 3c3f0f5eb5 Update ci.yml 2025-02-03 16:05:21 -05:00
dkeruza-neo fe2c749bb0 Fixes. Added ELF clean checker. 2025-02-02 17:51:24 +01:00
Nicolas Adenis-Lamarre 1f20a51aba evdev: add abs to key mapping
Signed-off-by: Nicolas Adenis-Lamarre <nicolas.adenis.lamarre@gmail.com>
2025-02-01 10:24:22 +01:00
Bobby Dilley d3e6027139 Update guide.md 2025-01-28 17:42:07 +00:00
Bobby Dilley 565a9208b7 Update guide.md 2025-01-28 15:36:05 +00:00
Bobby Dilley be78a23a31 Make dkeruza happy 2025-01-28 15:24:06 +00:00
Bobby Dilley 8942c510ec Look for /dev/dsp and /dev/dsp1 2025-01-28 10:45:35 +00:00
Bobby Dilley 685d569a08 Remove not needed message 2025-01-28 10:16:06 +00:00
Bobby Dilley 5f19cdc44c Fix wrong error message 2025-01-28 10:11:55 +00:00
Bobby Dilley be1b88b92f Merge remote-tracking branch 'caviar/master' 2025-01-28 10:01:27 +00:00
Nicolas Adenis-Lamarre 8347b61468 evdev: add shake special event
Signed-off-by: Nicolas Adenis-Lamarre <nicolas.adenis.lamarre@gmail.com>
2025-01-27 21:47:52 +01:00
dkeruza-neo 93927ef8c9 Fixes and ID5 SBRY support. 2025-01-27 15:09:52 +01:00
dkeruza-neo f67f30cbcd Fixed a bug in LGJ when GPU was nVidia and Mesa was set as shader patches. 2025-01-26 03:58:41 +01:00
dkeruza-neo 7ea08b3db3 Cleaned up commented code. 2025-01-26 03:58:41 +01:00
dkeruza dde7cc7b56 Update lindbergh.conf
typo
2025-01-25 00:29:58 +01:00
Nicolas Adenis-Lamarre 3642e2392b evdev: add technical input values
Signed-off-by: Nicolas Adenis-Lamarre <nicolas.adenis.lamarre@gmail.com>
2025-01-24 22:35:38 +01:00
dkeruza 6ff5d0b590 Update lindbergh.conf
typo
2025-01-24 10:59:45 +01:00
dkeruza a4cbbdaa97 Update patch.c
typo
2025-01-24 10:58:54 +01:00
dkeruza 2810022d1d Update config.h
typo
2025-01-24 10:53:19 +01:00
dkeruza b092b79331 Update config.c
typo
2025-01-24 10:52:23 +01:00
dkeruza-neo 1068fd5a1e Too many to list here. 2025-01-23 17:04:41 +01:00
Bobby Dilley ae61839826 Merge pull request #53 from Tovarichtch/dbresgames
add native resolution to games
2025-01-23 09:29:02 +00:00
Bobby Dilley 5786cdc37d Merge pull request #58 from lindbergh-loader/bobbydilley-patch-1
Update ci.yml
2025-01-16 10:37:32 +00:00
Bobby Dilley 5f90591690 Update ci.yml 2025-01-16 10:36:59 +00:00
Tovarichtch 9ee32e1fb0 ABC SDX was 16:9
https://www.gamoover.net/Forums/index.php?topic=44545.0
2025-01-13 22:18:05 -05:00
Tovarichtch 00a8279ce7 add config width/height 2025-01-13 20:50:55 -05:00
Tovarichtch ab7fbb7d5f ABC SDX
SDX cabinets of After Burner Climax were widescreen, clearly not 640x480. Can't locate native resolution.
2025-01-12 14:54:50 -05:00
Tovarichtch 69c0156e57 add native res to games 2025-01-11 10:39:07 -05:00
Synth_Magic 51eaec106c Do changes as requested 2025-01-10 22:03:06 +08:00
Synth Magic dcae95fe03 rename linux/limits.h to limits.h 2025-01-10 20:54:24 +08:00
Synth_Magic fbc76dfe5e Add config path sepcification 2025-01-10 20:52:07 +08:00
Bobby Dilley a3d476c584 Update ci.yml 2025-01-09 11:34:34 +00:00
Bobby Dilley 6d799d7524 Update ci.yml 2025-01-09 11:30:00 +00:00
Bobby Dilley 73d0c9fb57 Update ci.yml 2025-01-09 11:26:02 +00:00
50 changed files with 22462 additions and 5015 deletions
-69
View File
@@ -1,69 +0,0 @@
name: Build and Release Lindbergh
on:
push:
branches:
- master
pull_request:
branches:
- master
permissions:
contents: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Build Docker image
run: |
docker build --target lindbergh-build -t lindbergh-loader .
- name: Extract build artifacts
run: |
docker create --name lindbergh-builder lindbergh-loader
docker cp lindbergh-builder:/output ./build
docker rm lindbergh-builder
- name: Archive build directory
uses: actions/upload-artifact@v3
with:
name: build-output
path: ./build
release:
if: github.event_name == 'push'
needs: build
runs-on: ubuntu-latest
steps:
- name: Download build artifact
uses: actions/download-artifact@v3
with:
name: build-output
path: ./build
- name: Create Release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: v${{ github.run_number }}
release_name: "Lindbergh Loader v${{ github.run_number }}"
draft: false
prerelease: false
- name: Upload Release Asset
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./build
asset_name: build.tar.gz
asset_content_type: application/gzip
+44
View File
@@ -0,0 +1,44 @@
name: 📦 Linux Flatpak
on:
workflow_call:
workflow_dispatch:
jobs:
linux-flatpak-build:
name: "Build"
runs-on: ubuntu-latest
container:
image: ghcr.io/flathub-infra/flatpak-github-actions:kde-6.8
options: --privileged
timeout-minutes: 60
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
set-safe-directory: ${{ env.GITHUB_WORKSPACE }}
# Work around container ownership issue
- name: Set Safe Directory
shell: bash
run: git config --global --add safe.directory "*"
- name: Build Flatpak
uses: flathub-infra/flatpak-github-actions/flatpak-builder@master
with:
bundle: lindbergh-loader.flatpak
upload-artifact: false
manifest-path: scripts/flatpak/com.github.lindberghloader.yml
build-bundle: true
verbose: true
branch: stable
cache: true
restore-cache: true
cache-key: flatpak-${{ hashFiles('scripts/flatpak/*.yaml') }}
- name: Upload Flatpak
uses: actions/upload-artifact@v4
with:
name: "linux-flatpak"
path: "lindbergh-loader.flatpak"
+45
View File
@@ -0,0 +1,45 @@
name: Build and Release Lindbergh
on:
workflow_call:
workflow_dispatch:
permissions:
contents: write
jobs:
build-and-release:
runs-on: ubuntu-latest
steps:
# Checkout the repository
- name: Checkout repository
uses: actions/checkout@v3
# Set up Docker Buildx
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
# Build the Docker image
- name: Build Docker image
run: |
docker build --target lindbergh-build -t lindbergh-loader .
# Extract build artifacts
- name: Extract build artifacts
run: |
docker create --name lindbergh-builder lindbergh-loader
docker cp lindbergh-builder:/output ./build
docker rm lindbergh-builder
# Compress the build directory
- name: Compress build directory
run: tar -czvf build.tar.gz -C ./build .
# Archive the build directory as an artifact for debugging
- name: Archive build directory
uses: actions/upload-artifact@v4
with:
name: linux-build
path: build.tar.gz
+56
View File
@@ -0,0 +1,56 @@
name: Automated Builds
on:
workflow_dispatch:
pull_request:
paths-ignore:
- '**.md'
- '.github/ISSUE_TEMPLATE/*'
push:
branches:
- master
paths-ignore:
- '**.md'
- '.github/ISSUE_TEMPLATE/*'
jobs:
linux-build:
name: 💻 Linux
uses: "./.github/workflows/linux-build.yml"
linux-flatpak:
name: 📦 Linux Flatpak
uses: "./.github/workflows/flatpak-build.yml"
create-release:
name: 📤 Create Release
needs: [linux-build, linux-flatpak]
runs-on: ubuntu-22.04
if: github.ref == 'refs/heads/master'
steps:
- name: Download Artifacts
uses: actions/download-artifact@v4
with:
path: ./artifacts/
- name: Display Downloaded Artifacts
run: find ./artifacts/
- name: Add 161 to github.run_number
run: |
NEW_RUN_NUMBER=$(( ${{ github.run_number }} + 161 ))
echo "NEW_RUN_NUMBER=$NEW_RUN_NUMBER" >> $GITHUB_ENV
# - name: Display Updated Number
# run: echo "Updated Run Number: ${{ env.NEW_RUN_NUMBER }}"
- name: Create Preview Release
if: github.ref == 'refs/heads/master'
uses: "marvinpinto/action-automatic-releases@latest"
with:
repo_token: "${{ secrets.GITHUB_TOKEN }}"
automatic_release_tag: v${{ env.NEW_RUN_NUMBER }}
prerelease: false
title: "Build v${{ env.NEW_RUN_NUMBER }}"
files: |
./artifacts/linux-flatpak/lindbergh-loader.flatpak
./artifacts/linux-build/build.tar.gz
+21 -9
View File
@@ -1,7 +1,8 @@
CC = gcc -m32 -pthread CC ?= gcc
CFLAGS = -g -fPIC -m32 -Wall -Werror -Wno-unused-but-set-variable -Wno-unused-variable -Wno-unused-function -D_GNU_SOURCE -Wno-char-subscripts CFLAGS = -g -fPIC -m32 -pthread -Wall -Werror -Wno-misleading-indentation -Wno-unused-but-set-variable -Wno-unused-variable -Wno-unused-function -D_GNU_SOURCE -Wno-char-subscripts
LD = gcc -m32 CXX ?= g++
LDFLAGS = -Wl,-z,defs -rdynamic -static-libgcc -lc -ldl -lGL -lglut -lX11 -lSDL2 -lm -lpthread -shared -nostdlib -lasound -L./src/libxdiff -lxdiff LD = $(CXX)
LDFLAGS = -m32 -Wl,-z,defs -rdynamic -static-libgcc -lc -ldl -lGL -lglut -lX11 -lXcursor -lSDL2 -lm -lpthread -shared -nostdlib -lasound -L./src/libxdiff -lxdiff -L/app/lib32
BUILD = build BUILD = build
@@ -17,14 +18,14 @@ all: lindbergh libxdiff.a lindbergh.so libsegaapi.so libkswapapi.so libposixtime
lindbergh: src/lindbergh/lindbergh.c src/lindbergh/log.c src/lindbergh/log.h src/lindbergh/jvs.c src/lindbergh/jvs.h src/lindbergh/config.h src/lindbergh/config.c src/lindbergh/evdevinput.h src/lindbergh/evdevinput.c lindbergh: src/lindbergh/lindbergh.c src/lindbergh/log.c src/lindbergh/log.h src/lindbergh/jvs.c src/lindbergh/jvs.h src/lindbergh/config.h src/lindbergh/config.c src/lindbergh/evdevinput.h src/lindbergh/evdevinput.c
mkdir -p $(BUILD) mkdir -p $(BUILD)
$(CC) src/lindbergh/lindbergh.c src/lindbergh/log.h src/lindbergh/log.c src/lindbergh/jvs.h src/lindbergh/jvs.c src/lindbergh/config.h src/lindbergh/config.c src/lindbergh/evdevinput.c src/lindbergh/evdevinput.h -o $(BUILD)/lindbergh -lm $(CC) -m32 src/lindbergh/lindbergh.c src/lindbergh/log.h src/lindbergh/log.c src/lindbergh/jvs.h src/lindbergh/jvs.c src/lindbergh/config.h src/lindbergh/config.c src/lindbergh/evdevinput.c src/lindbergh/evdevinput.h -o $(BUILD)/lindbergh -lm
libxdiff.a: $(XDIFF_OBJS) libxdiff.a: $(XDIFF_OBJS)
mkdir -p $(BUILD) mkdir -p $(BUILD)
ar rcs src/libxdiff/libxdiff.a $(XDIFF_OBJS) ar rcs src/libxdiff/libxdiff.a $(XDIFF_OBJS)
src/libxdiff/xdiff/%.o: src/libxdiff/xdiff/%.c src/libxdiff/xdiff/%.o: src/libxdiff/xdiff/%.c
$(CC) -DHAVE_CONFIG_H -fPIC -c $< -o $@ $(CC) -m32 -DHAVE_CONFIG_H -fPIC -c $< -o $@
lindbergh.so: $(OBJS) lindbergh.so: $(OBJS)
mkdir -p $(BUILD) mkdir -p $(BUILD)
@@ -34,18 +35,29 @@ lindbergh.so: $(OBJS)
$(CC) $(CFLAGS) -c $< -o $@ $(CC) $(CFLAGS) -c $< -o $@
libsegaapi.so: src/libsegaapi/libsegaapi.o libsegaapi.so: src/libsegaapi/libsegaapi.o
gcc -m32 -O0 -g src/libsegaapi/libsegaapi.c -lFAudio -fPIC -shared -o $(BUILD)/libsegaapi.so $(CC) -m32 -O0 -g src/libsegaapi/libsegaapi.c -lFAudio -L/app/lib32 -fPIC -shared -o $(BUILD)/libsegaapi.so
libkswapapi.so: src/libkswapapi/libkswapapi.o libkswapapi.so: src/libkswapapi/libkswapapi.o
$(CC) src/libkswapapi/libkswapapi.o -fPIC -shared -o $(BUILD)/libkswapapi.so $(CC) -m32 src/libkswapapi/libkswapapi.o -fPIC -shared -o $(BUILD)/libkswapapi.so
libposixtime.so: libposixtime.so:
$(CC) src/libposixtime/libposixtime.c src/libposixtime/libposixtime.h -m32 -shared -o $(BUILD)/libposixtime.so $(CC) -m32 src/libposixtime/libposixtime.c src/libposixtime/libposixtime.h -m32 -shared -o $(BUILD)/libposixtime.so
ln -s -f libposixtime.so $(BUILD)/libposixtime.so.1 ln -s -f libposixtime.so $(BUILD)/libposixtime.so.1
ln -s -f libposixtime.so $(BUILD)/libposixtime.so.2.4 ln -s -f libposixtime.so $(BUILD)/libposixtime.so.2.4
# Clean rule # Clean rule
clean: clean:
rm -f $(BUILD)/lindbergh.so
rm -f $(BUILD)/libsegaapi.so
rm -f $(BUILD)/lindbergh
rm -f src/lindbergh/*.o
rm -f src/libsegaapi/*.o
#clean all rule
cleanall:
rm -rf $(BUILD) rm -rf $(BUILD)
rm -f src/lindbergh/*.o rm -f src/lindbergh/*.o
rm -f src/libsegaapi/*.o rm -f src/libsegaapi/*.o
rm -f src/libkswapapi/*.o
rm -f src/libxdiff/*.a
rm -f src/libxdiff/xdiff/*.o
+60
View File
@@ -0,0 +1,60 @@
# Changelog
All notable changes to this project will be documented in this file.
## [2.0.4]
### Added
- Boost render res option for Rambo, LGJ, HOD4, HOD-EX, ID4/ID5, 2Spicy and Harley.
- Flatpak build as a bundle. (For installation, read the guide in docs folder.)
- Add COINS with evdev for player 2.
- Merged code that adds support for COINS with evdev.
- Makefile, lindbergh.c and shader_patches.c changes to support Flatpak.
- "--zink" option in lindbergh elf to run the games using Zink.
- "--nvidia" option in lindbergh elf to force the secondary nVidia GPU in laptops.
- Click and drag in PH touchscreen.
- Hide custom crosshair cursor in PH when not needed.
- Custom mouse cursors working with X11, GLX and Glut.
- Custom mouse cursor in Primeval Hunt TouchScreen.
- TouchScreen emulation fro Primeval Hunt
- Display a warning if the distro you are running is not based on Debian.
- Cleaned up most of the code changing Ifs to Switch and sorting Alphabetically.
- Let's go Jungle and Let's go Jungle Special resolution patches.
## [2.0.3] 2025-02-02
### Added
- Display a warning when loading an Elf that is not clean.
- Added to the lib folder, common libraries that are usually missing.
### Fixed
- Missing patch in HOD-EX.
- Alows to run a game that does not support Card reader if option enabled in conf file.
## [2.0.2] 2025-01-27
### Added
- InitialD 5 SBRY added.
- HOD4 SP CPU Frequency fix.
### Fixed
- Fixed a bug when a game uses GLUT and the conf was set to NO_SDL 1
- Fixed a bug in Let's go Jungle when GPU was nVidia and Mesa was set as shader patches.
- Exclude resolution patches when the resolution is the game's original resolution.
- Reload with Right mouse click for Rambo and 2Spicy with SDL.
### [2.0.1] 2025-01-23
### Added
- HOD4 Custom crosshair.
- HOD4 CPU frequency fix (Configurable via config file).
- HOD4 New resolution patch that fixes Boss battle and scales from 1280x768 instead of the lower resolution.
- Built in Logos and fonts (no more nee to use Lucida/SEGA_KakuGothic-DB-Roman_12 and logo.tga).
- Outrun 2 Easy network config from the conf file (can set your IP address in the config file and the loader will set it in the eeprom for you).
- Card Emulation for VT3 and R-tuned.
- All the now games work inside an SDL window now, unless it is disabled in the conf file.
## [2.0] - 2024-12-24
### Initial Release
- First official public release.
- Features of the loader:
- Dynamic shader modification allowing games to work on Intel, nVidia and AMD
- 5.1 Surround Sound Support
- Dynamic resolution patching allowing most games to scale properly in HD
- Original cabinet support with pass through of JVS and FFB
- Network play
- Both simple X11 and advanced evdev input system allowing for ready-to-play keyboard and mouse support or mapping of any controller
+125 -25
View File
@@ -4,31 +4,67 @@
The follow list of games are supported. It is worth noting that there are multiple releases of these games, and some specific releases may not be supported. The follow list of games are supported. It is worth noting that there are multiple releases of these games, and some specific releases may not be supported.
| Game Name | Game ID | DVP | NVidia | Intel (Mesa) | AMD (Mesa) | AMD (proprietary) | | Game Name | Game ID | DVP | NVidia | Intel (Mesa) | AMD (Mesa) | AMD (proprietary) |
|---------------------------------|---------|----------|--------|--------------|------------|-------------------| |--------------------------------------------------|---------|-----------|--------|--------------|------------|-------------------|
| 2 Spicy | SBMV | DVP-0027 | ✓ | ✓ | ✓ | ✓ | | After Burner Climax | SBLR | DVP-0009 | ✓ | ✓ | ✓ | |
| After Burner Climax | SBLR | DVP-0009 | ✓ | ✓ | ✓ | | | After Burner Climax Rev A | SBLR | DVP-0009A | ✓ | ✓ | ✓ | |
| Ghost Squad Evolution | SBNJ | DVP-0029 | ✓ | ✓ | ✓ | ✓ | | After Burner Climax Rev B | SBLR | DVP-0009B | ✓ | ✓ | ✓ | |
| Harley Davidson | SBRG | DVP-5007 | ✓ | ✓ | ✓ | ✓ | | After Burner Climax SDX | SBMN | DVP-0018 | ✓ | ✓ | ✓ | |
| Hummer Extreme | SBST | DVP-0079 | ✓ | ✓ | ✓ | ✓ | | After Burner Climax SDX Rev A | SBMN | DVP-0018A | ✓ | ✓ | ✓ | |
| Hummer | SBQN | DVP-0057 | ✓ | ✓ | ✓ | ✓ | | After Burner Climax SE | SBLR | DVP-0031 | ✓ | ✓ | ✓ | |
| Let's Go Jungle | SBLU | DVP-0011 | ✓ | ✓ | ✓ | | | After Burner Climax SE Rev A | SBLR | DVP-0031A | ✓ | ✓ | ✓ | |
| Let's Go Jungle Special | SBNR | DVP-0036 | ✓ | ✓ | ✓ | | | Ghost Squad Evolution | SBNJ | DVP-0029 | ✓ | ✓ | ✓ | ✓ |
| Outrun 2 SP SDX | SBMB | DVP-0015 | ✓ | ✓ | ✓ | ✓ | | Harley Davidson | SBRG | DVP-5007 | ✓ | ✓ | ✓ | ✓ |
| R-Tuned | SBQW | DVP-0060 | ✓ | ✓ | ✓ | ✓ | | Hummer | SBQN | DVP-0057B | ✓ | ✓ | ✓ | ✓ |
| Race TV | SBPF | DVP-0044 | ✓ | ✓ | ✓ | ✓ | | Hummer SDLX | SBST | DVP-0057 | ✓ | ✓ | ✓ | ✓ |
| Rambo | SBQL | DVP-0069 | ✓ | ✓ | ✓ | ✓ | | Hummer Extreme | SBST | DVP-0079 | ✓ | ✓ | ✓ | ✓ |
| The House of the Dead 4 | SBLC | DVP-0003 | ✓ | ✓ | ✓ | ✓ | | Hummer Extreme MDX | SBST | DVP-0083 | ✓ | ✓ | ✓ | ✓ |
| The House of the Dead 4 Special | SBLS | DVP-0010 | ✓ | ✓ | ✓ | ✓ | | Initial D Arcade Stage 4 Rev A | SBML | DVP-0019A | ✓ | ✓ | ✓ | ✓ |
| The House of the Dead Ex | SBRC | DVP-0063 | ✓ | ✓ | ✓ | ✓ | | Initial D Arcade Stage 4 Rev B | SBML | DVP-0019B | ✓ | ✓ | ✓ | ✓ |
| Virtua Fighter 5 | SBLM | DVP-0008 | ✓ | ✓ | ✓ | ✓ | | Initial D Arcade Stage 4 Rev C | SBML | DVP-0019C | ✓ | ✓ | ✓ | ✓ |
| Virtua Fighter 5 R | SBQU | DVP-5004 | ✓ | ✓ | ✓ | ✓ | | Initial D Arcade Stage 4 Rev D | SBML | DVP-0019D | ✓ | ✓ | ✓ | ✓ |
| Virtua Fighter 5 FS | SBUV | DVP-5019 | ✓ | ✓ | ✓ | ✓ | | Initial D Arcade Stage 4 Rev G | SBML | DVP-0019G | ✓ | ✓ | ✓ | ✓ |
| Initial D 4 | SBNK | DVP-0030 | ✓ | ✓ | ✓ | ✓ | | Initial D Arcade Stage 4 Export Rev B | SBNK | DVP-0030B | ✓ | ✓ | ✓ | ✓ |
| Initial D 5 | SBTS | DVP-0075 | ✓ | ✓ | ✓ | | | Initial D Arcade Stage 4 Export Rev C | SBNK | DVP-0030C | ✓ | ✓ | ✓ | ✓ |
| Virtua Tennis 3 | SBKX | DVP-0005 | ✓ | ✓ | ✓ | ✓ | | Initial D Arcade Stage 4 Export Rev D | SBNK | DVP-0030D | ✓ | ✓ | ✓ | ✓ |
| Primeval Hunt | SBPP | DVP-0048 | ✓ | ✓ | ✓ | ✓ | | Initial D 5 EXP | SBRY | DVP-0075 | ✓ | ✓ | ✓ | |
| Initial D 5 EXP 2.0 | SBTS | DVP-0084 | ✓ | ✓ | ✓ | |
| Initial D 5 EXP 2.0 Rev A | SBQN | DVP-0084A | ✓ | ✓ | ✓ | |
| Initial D Arcade Stage 5 Rev A | SBQZ | DVP-0070A | ✓ | ✓ | ✓ | |
| Initial D Arcade Stage 5 Rev F | SBQZ | DVP-0070F | ✓ | ✓ | ✓ | |
| Let's Go Jungle | SBLU | DVP-0011 | ✓ | ✓ | ✓ | |
| Let's Go Jungle! Rev A | SBLU | DVP-0011A | ✓ | ✓ | ✓ | |
| Let's Go Jungle Special | SBNR | DVP-0036 | ✓ | ✓ | ✓ | |
| SEGA Network Taisen Mahjong MJ4 | SBPN | DVP-0049G | ✓ | ✓ | ✓ | ✓ |
| SEGA Network Taisen Mahjong MJ4 Evolution | SBTA | DVP-0081 | ✓ | ✓ | ✓ | ✓ |
| Outrun 2 SP SDX | SBMB | DVP-0015 | ✓ | ✓ | ✓ | ✓ |
| Outrun 2 SP SDX Rev A | SBMB | DVP-0015A | ✓ | ✓ | ✓ | ✓ |
| Primeval Hunt | SBPP | DVP-0048 | ✓ | ✓ | ✓ | ✓ |
| Rambo | SBQL | DVP-0069 | ✓ | ✓ | ✓ | ✓ |
| R-Tuned | SBQW | DVP-0060 | ✓ | ✓ | ✓ | ✓ |
| Sega Race TV | SBPF | DVP-0044 | ✓ | ✓ | ✓ | ✓ |
| The House of the Dead 4 Rev A | SBLC | DVP-0003A | ✓ | ✓ | ✓ | ✓ |
| The House of the Dead 4 Rev B | SBLC | DVP-0003B | ✓ | ✓ | ✓ | ✓ |
| The House of the Dead 4 Rev C | SBLC | DVP-0003C | ✓ | ✓ | ✓ | ✓ |
| The House of the Dead 4 Special | SBLS | DVP-0010 | ✓ | ✓ | ✓ | ✓ |
| The House of the Dead 4 Special Rev B | SBLS | DVP-0010B | ✓ | ✓ | ✓ | ✓ |
| The House of the Dead Ex | SBRC | DVP-0063 | ✓ | ✓ | ✓ | ✓ |
| Too Spicy | SBMV | DVP-0027 | ✓ | ✓ | ✓ | ✓ |
| Virtua Fighter 5 | SBLM | DVP-0008 | ✓ | ✓ | ✓ | ✓ |
| Virtua Fighter 5 Rev A | SBLM | DVP-0008A | ✓ | ✓ | ✓ | ✓ |
| Virtua Fighter 5 Rev B | SBLM | DVP-0008B | ✓ | ✓ | ✓ | ✓ |
| Virtua Fighter 5 Rev E (Public Version C) | SBLM | DVP-0008E | ✓ | ✓ | ✓ | ✓ |
| Virtua Fighter 5 Export | SBLM | DVP-0043 | ✓ | ✓ | ✓ | ✓ |
| Virtua Fighter 5 Final Showdown REV A | SBUV | DVP-5019 | ✓ | ✓ | ✓ | ✓ |
| Virtua Fighter 5 Final Showdown REV B | SBXX | DVP-5020 | ✓ | ✓ | ✓ | ✓ |
| Virtua Fighter 5 Final Showdown REV B ver 6.0000 | SBXX | DVP-5020 | ✓ | ✓ | ✓ | ✓ |
| Virtua Fighter 5 R | SBQU | DVP-5004 | ✓ | ✓ | ✓ | ✓ |
| Virtua Fighter 5 R Rev D | SBQU | DVP-5004D | ✓ | ✓ | ✓ | ✓ |
| Virtua Fighter 5 R Rev G | SBQU | DVP-5004G | ✓ | ✓ | ✓ | ✓ |
| Virtua Tennis 3 | SBKX | DVP-0005 | ✓ | ✓ | ✓ | ✓ |
| Virtua Tennis 3 Rev A | SBKX | DVP-0005A | ✓ | ✓ | ✓ | ✓ |
| Virtua Tennis 3 Rev B | SBKX | DVP-0005B | ✓ | ✓ | ✓ | ✓ |
| Virtua Tennis 3 Rev C | SBKX | DVP-0005C | ✓ | ✓ | ✓ | ✓ |
## Game Issues & Fixes ## Game Issues & Fixes
@@ -120,3 +156,67 @@ Will cause input on analogue input 1 to be clamped as follows:
There are currently no audio options that you can set. If you have a stereo sound card installed then the audio will be downmixed to stereo. If you have a 5.1 sound card installed and the game supports surround sound, each surround channel should be passed through properly and should play sound as it was originally intended. There are currently no audio options that you can set. If you have a stereo sound card installed then the audio will be downmixed to stereo. If you have a 5.1 sound card installed and the game supports surround sound, each surround channel should be passed through properly and should play sound as it was originally intended.
## Installing and Running the Flatpak
### Prerequisites
Before installing the main package, ensure that Flatpak is set up on your system. If Flatpak is not installed, follow the official [Flatpak setup guide](https://flatpak.org/setup/).
### Installation
Once downloaded, install Lindbergh Loader by running the following command in your terminal:
```
flatpak install lindbergh-loader-dev.flatpak
```
Additionally, install the required dependencies:
```
flatpak install org.freedesktop.Platform.Compat.i386//24.08
flatpak install org.freedesktop.Platform.GL32.default//24.08
```
Intel GPU Users (VAAPI Support):
```
flatpak install org.freedesktop.Platform.VAAPI.Intel.i386//24.08
```
NVIDIA GPU Users (Driver Support):
If your system uses an NVIDIA GPU, you need to install the matching NVIDIA driver package for your system.
To check your NVIDIA driver version, run:
```
nvidia-smi
```
Then, install the corresponding Flatpak package, replacing 570-86-16 with your actual driver version:
```
flatpak install org.freedesktop.Platform.GL32.nvidia-570-86-16
```
### Running Lindbergh Loader
Once installed, launch the application with:
```
flatpak run com.github.lindberghloader.dev
```
### Managing Game Locations
By default, games should be added to:
```
~/Games
```
If you need to add more locations, install Flatseal:
```
flatpak install com.github.tchx84.Flatseal
```
Then, run Flatseal and grant Lindbergh Loader access to additional directories.
+77 -28
View File
@@ -1,5 +1,5 @@
# SEGA Lindbergh Emulator Configuration File # SEGA Lindbergh Emulator Configuration File
# By the Lindbergh Development Team # By the Lindbergh Development Team 2024-2025
# Set the requested dip switch width here # Set the requested dip switch width here
WIDTH AUTO WIDTH AUTO
@@ -7,28 +7,31 @@ WIDTH AUTO
# Set the requested dip switch height here # Set the requested dip switch height here
HEIGHT AUTO HEIGHT AUTO
# Boost render resolution in HOD4/2Spicy/Harley/Rambo/HOD-EX/ID4/ID5 and LGJ
# BOOST_RENDER_RES 1
# Set if the emulator should go full screen # Set if the emulator should go full screen
FULLSCREEN 0 # FULLSCREEN 0
# Sets the Input Mode # Sets the Input Mode
# Mode 0: will use both SDL/X11 and EVDEV inputs (default) # Mode 0: will use both SDL/X11 and EVDEV inputs (default)
# Mode 1: will use SDL/X11 inputs only # Mode 1: will use SDL/X11 inputs only
# Mode 2: will use EVDEV raw inputs only, which should be configured at the bottom of the settings file # Mode 2: will use EVDEV raw inputs only, which should be configured at the bottom of the settings file
INPUT_MODE 0 # INPUT_MODE 0
# Set to 1 if you want to disable SDL (Fixes SRTV boost bar) # Set to 1 if you want to disable SDL (Fixes SRTV boost bar)
NO_SDL 0 # NO_SDL 0
# Set the Region ( JP/US/EX ) # Set the Region ( JP/US/EX )
REGION EX # REGION EX
# Set if you want the game to be Free Play # Set if you want the game to be Free Play
FREEPLAY 1 # FREEPLAY 1
# Set if the emulator should emulate JVS and use the keyboard/mouse for controls. # Set if the emulator should emulate JVS and use the keyboard/mouse for controls.
# If this is set to 0, then the emulator will route the traffic to the serial device # If this is set to 0, then the emulator will route the traffic to the serial device
# defined in JVS_PATH if it has been defined. # defined in JVS_PATH if it has been defined.
EMULATE_JVS 1 # EMULATE_JVS 1
# Set if the emulator should emulate the rideboard used in the special games here # Set if the emulator should emulate the rideboard used in the special games here
# If this is set to 0, then the emulator will route the traffic to one of the serial ports # If this is set to 0, then the emulator will route the traffic to one of the serial ports
@@ -42,72 +45,118 @@ EMULATE_DRIVEBOARD AUTO
# If this is set to 0, then the emulator will route the traffic to one of the serial ports # If this is set to 0, then the emulator will route the traffic to one of the serial ports
EMULATE_MOTIONBOARD AUTO EMULATE_MOTIONBOARD AUTO
# Set if the loader should emulate the card reader in Virtua Tenis 3
EMULATE_CARDREADER AUTO
# Set to 1 if the loader should emulate the touchscreen with the mouse in PH.
# EMULATE_TOUCHSCREEN 1
# Card File for reader 1
# CARDFILE_01 Card_01.crd
# Card File for reader 2
# CARDFILE_02 Card_02.crd
# Define the path to pass the JVS packets to if JVS is not being emulated. # Define the path to pass the JVS packets to if JVS is not being emulated.
JVS_PATH /dev/ttyUSB0 # JVS_PATH /dev/ttyUSB0
# Define the path to pass the first serial port to if it's not being emulated. # Define the path to pass the first serial port to if it's not being emulated.
SERIAL_1_PATH /dev/ttyUSB0 # SERIAL_1_PATH /dev/ttyUSB0
# Define the path to pass the second serial port to if it's not being emulated. # Define the path to pass the second serial port to if it's not being emulated.
SERIAL_2_PATH /dev/ttyUSB0 # SERIAL_2_PATH /dev/ttyUSB0
# Define the path to the sram.bin file # Define the path to the sram.bin file
SRAM_PATH sram.bin # SRAM_PATH sram.bin
# Define the path to the eeprom.bin file # Define the path to the eeprom.bin file
EEPROM_PATH eeprom.bin # EEPROM_PATH eeprom.bin
# Set the GPU vendor (0 = Autodetect / 1 = NVidia / 2 = AMD / 3 = ATI(AMD-PRO) / 4 = Intel / 5 = Unknown) # Set the GPU vendor (0 = Autodetect / 1 = NVidia / 2 = AMD / 3 = ATI(AMD-PRO) / 4 = Intel / 5 = Unknown)
GPU_VENDOR 0 # GPU_VENDOR 0
# Set if you want to see debug messages in the console # Set if you want to see debug messages in the console
DEBUG_MSGS 0 # DEBUG_MSGS 0
# Set if you'd like to add a border for optical light gun tracking # Set if you'd like to add a border for optical light gun tracking
BORDER_ENABLED 0 # BORDER_ENABLED 0
# Set the thickness of the white border as a percentage of the width of the screen # Set the thickness of the white border as a percentage of the width of the screen
WHITE_BORDER_PERCENTAGE 2 # WHITE_BORDER_PERCENTAGE 2
# Set the thickness of the black border which sits around the # Set the thickness of the black border which sits around the
# white border as a percentage of the width of the screen # white border as a percentage of the width of the screen
BLACK_BORDER_PERCENTAGE 0 # BLACK_BORDER_PERCENTAGE 0
# Set to true if you experience flickering in hummer # Set to true if you experience flickering in hummer
HUMMER_FLICKER_FIX 0 # HUMMER_FLICKER_FIX 0
# Set to keep the aspect ratio (4:3) in games like Sega Race TV and Primeval Hunt # Set to keep the aspect ratio (4:3) in games like Sega Race TV and Primeval Hunt
KEEP_ASPECT_RATIO 0 # KEEP_ASPECT_RATIO 0
# Set to 0 if you want to disable the Glare effect in OutRun # Set to 0 if you want to disable the Glare effect in OutRun
OUTRUN_LENS_GLARE_ENABLED 1 # OUTRUN_LENS_GLARE_ENABLED 1
# Set to 1 to bypass cabinet checks including drive board and tower in Outrun 2 SP SDX # Set to 1 to bypass cabinet checks including drive board and tower in Outrun 2 SP SDX
SKIP_OUTRUN_CABINET_CHECK 0 # SKIP_OUTRUN_CABINET_CHECK 0
# Set to 1 if you want to limit the FPS in games that are not limited like OutRun2 # Set to 1 if you want to limit the FPS in games that are not limited like OutRun2
FPS_LIMITER_ENABLED 0 # FPS_LIMITER_ENABLED 0
# Set the target FPS (will only work if FPS_LIMITER_ENABLED = 1) # Set the target FPS (will only work if FPS_LIMITER_ENABLED = 1)
FPS_TARGET 60 # FPS_TARGET 60
# Set to 1 if you want to render LGJ using the mesa patches instead of nVidia (fixes some glitches) # Set to 1 if you want to render LGJ using the mesa patches instead of nVidia (fixes some glitches)
LGJ_RENDER_WITH_MESA 1 # LGJ_RENDER_WITH_MESA 1
# Set the Primeval Hunt mode # Set the Primeval Hunt mode
# Mode 0: Leaves everything as default # Mode 0: Default (Side by Side)
# Mode 1: No touch screen (Default mode) # Mode 1: No touch screen
# Mode 2: Side by Side # Mode 2: Side by Side
# Mode 3: 3ds mode 1 (Touch screen to the right) # Mode 3: 3ds mode 1 (Touch screen to the right)
# Mode 4: 3ds mode 2 (Touch screen to the bottom) # Mode 4: 3ds mode 2 (Touch screen to the bottom)
PRIMEVAL_HUNT_MODE 1 # PRIMEVAL_HUNT_MODE 1
# Disble to use the original fonts instead of the built in font in the loader
# DISABLE_BUILTIN_FONT 0
# Disble to use the original logos instead of the built in logos in the loader
# DISABLE_BUILTIN_LOGOS 0
# Set to 0 to enable the mouse pointer/Cursor
# HIDE_CURSOR 1
# Set the custom mouse pointer from a PNG file (Usefull for shooting games)
# CUSTOM_CURSOR myCustomCursor.png
# Set the width of the custom cursor
# CUSTOM_CURSOR_WIDTH 32
# Set the height of the custom cursor
# CUSTOM_CURSOR_HEIGHT 32
# Set a custom cursor for the touch screen in Primeval Hunt
# PH_TOUCH_CURSOR myCustomHandCursor.png
# Set the width of the custom cursor
# PH_TOUCH_CURSOR_WIDTH 32
# Set the height of the custom cursor
# PH_TOUCH_CURSOR_HEIGHT 32
# Hacky way to make MJ4 work at prohibited times? # Hacky way to make MJ4 work at prohibited times?
# MJ4_ENABLED_ALL_THE_TIME 1 # MJ4_ENABLED_ALL_THE_TIME 1
# Sets the IP address in the eeprom for Outrun link (you have to put your NIC ip)
# OR2_IP 192.168.1.2
# OR2_NETMASK 255.255.255.0
# House of the dead 4 speed fix set the frequency of your CPU in Ghz (The speed reported by the manufacturer)
# CPU_FREQ_GHZ 4.0
# Set the colour of the lindbergh to change the Segaboot logo # Set the colour of the lindbergh to change the Segaboot logo
# Possible colours are: YELLOW, RED, BLUE, SILVER, REDEX # Possible colours are: YELLOW, RED, BLUE, SILVER, REDEX
LINDBERGH_COLOUR YELLOW # LINDBERGH_COLOUR YELLOW
# X11 MODE (Input Mode 1) # X11 MODE (Input Mode 1)
# To find the value pairs for these run `xev` on linux # To find the value pairs for these run `xev` on linux
BIN
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+4
View File
@@ -0,0 +1,4 @@
.flatpak-builder/
build/
repo/
*.flatpak
+4
View File
@@ -0,0 +1,4 @@
# We just make any GL32 extension have higher priority
include /run/flatpak/ld.so.conf.d/app-*-org.freedesktop.Platform.GL32.*.conf
/app/lib32
/app/lib/i386-linux-gnu
Binary file not shown.
+36
View File
@@ -0,0 +1,36 @@
diff --color -ruN ncurses-5.9.orig/c++/cursesf.h ncurses-5.9/c++/cursesf.h
--- ncurses-5.9.orig/c++/cursesf.h 2005-08-13 20:08:24.000000000 +0200
+++ ncurses-5.9/c++/cursesf.h 2025-02-21 14:45:57.002814632 +0100
@@ -703,7 +703,7 @@
virtual ~NCursesUserForm() {
};
- inline T* UserData (void) const {
+ inline T* UserData (void) {
return reinterpret_cast<T*>(get_user ());
};
diff --color -ruN ncurses-5.9.orig/c++/cursesm.h ncurses-5.9/c++/cursesm.h
--- ncurses-5.9.orig/c++/cursesm.h 2005-08-13 20:10:36.000000000 +0200
+++ ncurses-5.9/c++/cursesm.h 2025-02-21 14:47:21.238076003 +0100
@@ -659,7 +659,7 @@
virtual ~NCursesUserMenu() {
};
- inline T* UserData (void) const {
+ inline T* UserData (void) {
return reinterpret_cast<T*>(get_user ());
};
diff --color -ruN ncurses-5.9.orig/c++/cursesp.h ncurses-5.9/c++/cursesp.h
--- ncurses-5.9.orig/c++/cursesp.h 2008-08-16 19:20:23.000000000 +0200
+++ ncurses-5.9/c++/cursesp.h 2025-02-21 14:45:19.718735744 +0100
@@ -251,7 +251,7 @@
virtual ~NCursesUserPanel() {};
- T* UserData (void) const
+ T* UserData (void)
{
return reinterpret_cast<T*>(get_user ());
};
@@ -0,0 +1,323 @@
app-id: com.github.lindberghloader
runtime: org.freedesktop.Platform
runtime-version: &runtime-version '24.08'
x-gl-version: &gl-version '1.4'
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
sdk: org.freedesktop.Sdk
command: lindbergh
sdk-extensions:
- org.freedesktop.Sdk.Extension.toolchain-i386
- org.freedesktop.Sdk.Compat.i386
x-arch-build-options:
i386: &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"
finish-args:
- --env=LD_LIBRARY_PATH=/app/lib32:$LD_LIBRARY_PATH
- --env=LDFLAGS="-L/app/lib32"
- --env=PATH=/app/bin:/usr/bin
- --allow=multiarch
- --share=ipc
- --share=network
- --socket=x11
- --socket=wayland
- --device=all
- --socket=pulseaudio
- --filesystem=~/Games
add-extensions:
org.freedesktop.Platform.Compat.i386:
directory: lib/i386-linux-gnu
version: *runtime-version
no-autodownload: true
org.freedesktop.Platform.Compat.i386.Debug:
directory: lib/debug/lib/i386-linux-gnu
version: *runtime-version
no-autodownload: true
org.freedesktop.Platform.GL32:
directory: lib/i386-linux-gnu/GL
version: *gl-version
versions: *gl-versions
subdirectories: true
no-autodownload: true
autodelete: false
add-ld-path: lib
merge-dirs: *gl-merge-dirs
download-if: active-gl-driver
enable-if: active-gl-driver
autoprune-unless: active-gl-driver
org.freedesktop.Platform.GL32.Debug:
directory: lib/debug/lib/i386-linux-gnu/GL
version: *gl-version
versions: *gl-versions
subdirectories: true
no-autodownload: true
merge-dirs: *gl-merge-dirs
enable-if: active-gl-driver
autoprune-unless: active-gl-driver
modules:
- name: libstdcxx5
buildsystem: simple
build-commands:
- mkdir -p /app/lib32
- install -Dm644 libstdc++.so.5 /app/lib32/libstdc++.so.5
sources:
- type: file
path: ./assets/libstdc++.so.5
- name: libGLU
buildsystem: autotools
config-opts:
- --host=i686-unknown-linux-gnu
- --prefix=/app
build-options:
arch:
x86_64: *i386-build-options
sources:
- type: archive
url: https://mesa.freedesktop.org/archive/glu/glu-9.0.2.tar.xz
sha256: 6e7280ff585c6a1d9dfcdf2fca489251634b3377bfc33c29e4002466a38d02d4
- name: freeglut
buildsystem: cmake
config-opts:
- -DCMAKE_BUILD_TYPE=Release
- -DCMAKE_INSTALL_PREFIX=/app
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
- name: libFAudio-Dynamic
buildsystem: cmake-ninja
config-opts:
- -DCMAKE_BUILD_TYPE=Release
- -DCMAKE_INSTALL_PREFIX=/app
- -DBUILD_SDL3=off
- -DCMAKE_INSTALL_LIBDIR=/app/lib32
build-options:
arch:
x86_64: *i386-build-options
env:
CFLAGS: "-m32 -mstackrealign"
CXXFLAGS: "-m32 -mstackrealign"
sources:
- type: git
url: https://github.com/FNA-XNA/FAudio.git
tag: "24.12"
- name: libxmu
buildsystem: autotools
config-opts:
- --libdir=/app/lib32
- --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
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
libdir: /app/lib32
- name: libmd
buildsystem: autotools
config-opts:
- --libdir=/app/lib32
sources:
- type: archive
url: https://archive.hadrons.org/software/libmd/libmd-1.1.0.tar.xz
sha256: 1bd6aa42275313af3141c7cf2e5b964e8b1fd488025caf2f971f43b00776b332
build-options:
arch:
x86_64: *i386-build-options
- name: libbsd
buildsystem: autotools
config-opts:
- --libdir=/app/lib32
sources:
- type: archive
url: https://libbsd.freedesktop.org/releases/libbsd-0.12.2.tar.xz
sha256: b88cc9163d0c652aaf39a99991d974ddba1c3a9711db8f1b5838af2a14731014
build-options:
arch:
x86_64: *i386-build-options
- name: ncurses
buildsystem: autotools
config-opts:
- --libdir=/app/lib32
- --with-shared
- --without-debug
sources:
- type: archive
url: https://ftp.gnu.org/pub/gnu/ncurses/ncurses-5.9.tar.gz
sha256: 9046298fb440324c9d4135ecea7879ffed8546dd1b58e59430ea07a4633f563b
- type: patch
path: ./assets/ncurses-5.9.patch
build-options:
arch:
x86_64: *i386-build-options
env:
CPPFLAGS: "-P"
CXXFLAGS: "-std=c++14"
- name: nvidia-cg-toolkit
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
url: http://developer.download.nvidia.com/cg/Cg_3.1/Cg-3.1_April2012_x86.tgz
sha256: cef3591e436f528852db0e8c145d3842f920e0c89bcfb219c466797cb7b18879
- name: libsndio-dynamic
buildsystem: autotools
config-opts:
- --libdir=/app/lib32
- --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
- name: libsndio-static
buildsystem: autotools
config-opts:
- --libdir=/app/lib32
- --enable-static
- --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
- name: libopenal
buildsystem: cmake
config-opts:
- -DCMAKE_INSTALL_LIBDIR=/app/lib32
- -DALSOFT_BACKEND_PULSEAUDIO=ON
- -DALSOFT_BACKEND_ALSA=ON
- -DALSOFT_BACKEND_JACK=OFF
- -DALSOFT_BACKEND_SNDIO=ON
- -DSOUNDIO_INCLUDE_DIR=/app/include
- -DSOUNDIO_LIBRARY=/app/lib32/libsndio.so
sources:
- type: archive
url: https://github.com/kcat/openal-soft/archive/refs/tags/openal-soft-1.17.2.tar.gz
sha256: 11ea176f6cbf9763dbce0953dd77ab72d032b4ad95f07afffb91844abb174033
build-options:
arch:
x86_64: *i386-build-options
env:
CFLAGS: "-m32 -mstackrealign"
CXXFLAGS: "-m32 -std=c++14 -mstackrealign"
- name: openssl
buildsystem: simple
build-commands:
- ./Configure --prefix=/app --openssldir=/app/etc/ssl shared 386 no-asm no-krb5 linux-pentium
- 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
- mv libcrypto.* /app/lib32
- mv libssl.* /app/lib32
sources:
- type: archive
url: https://github.com/openssl/openssl/archive/refs/tags/OpenSSL_0_9_7.tar.gz
sha256: 14e3a90f75994689e8c1bef098a97021f225a1a1623a7b8012079bd8b2eca1e8
- name: libpcsclite
buildsystem: meson
config-opts:
- --libdir=/app/lib32
- -Dpolkit=false
- -Dlibsystemd=false
build-options:
arch:
x86_64: *i386-build-options
env:
CFLAGS: "-m32"
CXXFLAGS: "-m32"
LDFLAGS: "-m32"
PKG_CONFIG_PATH: "/app/lib32/pkgconfig:/usr/lib/i386-linux-gnu/pkgconfig"
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
sha256: a641d44d57affe1edd8365dd75307afc307e7eefb4e7ad839f6f146baa41ed56
- name: lindbergh-loader
buildsystem: simple
build-commands:
- export LD_LIBRARY_PATH=/app/lib32:$LD_LIBRARY_PATH
- make
- mkdir -p /app/bin
- 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 -Dm755 ./libs/libCg.so /app/lib32/libCg2.so
- ln -s -f libposixtime.so /app/lib32/libposixtime.so.1
- ln -s -f libposixtime.so /app/lib32/libposixtime.so.2.4
- ln -s -f libopenal.so /app/lib32/libopenal.so.0
- ln -s -f libkswapapi.so /app/lib32/libGLcore.so.1
- ln -s -f libkswapapi.so /app/lib32/libnvidia-tls.so.1
- mv /app/lib/libopenal* /app/lib32/
build-options:
arch:
x86_64: *i386-build-options
sources:
- type: dir
path: ../..
- name: bundle-setup
buildsystem: simple
build-commands:
- install -Dm644 -t /app/etc ld.so.conf
sources:
- type: file
path: ./assets/ld.so.conf
- name: cleanup
buildsystem: simple
build-commands:
- find /app/lib /app/lib32 -name '*.a' -type f -delete
- find /app/lib /app/lib32 -name '*.la' -type f -delete
- find /app/bin -mindepth 1 ! -name "lindbergh*" -exec rm -f {} \;
- rm -d /app/lib/terminfo
- rm -rf /app/lib/pkgconfig /app/lib32/pkgconfig /app/share/pkgconfig /app/lib32/cmake /app/lib/debug /app/include /app/man /app/share
- rm /app/lib32/libmenu.*
- rm /app/lib32/libform.*
- rm /app/lib32/libpanel.*
- rm /app/lib32/libXmuu.*
- rm /app/lib32/libbsd.so
+250
View File
@@ -0,0 +1,250 @@
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include "config.h"
#include "card_reader.h"
#define BLOCKSIZE 8
extern uint32_t gId;
uint8_t cardHeader[] = {0x08, 0x00, 0x00, 0x00, 0x81, 0x00, 0x59, 0xda, 0x00, 0x00, 0x54, 0x4d, 0x50, 0x06, 0x03, 0x23, 0x10, 0x41, 0x62,
0xad, 0x00, 0x2b, 0x0b, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x95, 0x71, 0x52, 0x70, 0x00, 0x00,
0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfd, 0xd2};
SerialFD serialFD[2];
WriteCommand writeCmd[2];
ReadCommand readCmd[2];
void initReadCmd(int fdIdx)
{
readCmd[fdIdx].cmd = 0;
readCmd[fdIdx].cmdCompleted = false;
readCmd[fdIdx].cmdLen = 0;
readCmd[fdIdx].sentBytes = 0;
memset(&readCmd[fdIdx].sendBuffer, '\0', 256);
}
void initWriteCmd(int fdIdx)
{
writeCmd[fdIdx].cmdCompleted = false;
writeCmd[fdIdx].packetLen = 0;
writeCmd[fdIdx].recBytes = 0;
memset(&writeCmd[fdIdx].recBuffer, '\0', sizeof(uint8_t));
}
int initCardReader()
{
EmulatorConfig *config = getConfig();
switch (gId)
{
case R_TUNED:
case VIRTUA_TENNIS_3:
case VIRTUA_TENNIS_3_TEST:
case VIRTUA_TENNIS_3_REVA:
case VIRTUA_TENNIS_3_REVA_TEST:
case VIRTUA_TENNIS_3_REVB:
case VIRTUA_TENNIS_3_REVB_TEST:
case VIRTUA_TENNIS_3_REVC:
case VIRTUA_TENNIS_3_REVC_TEST:
// Code for supported games
break;
default:
printf("Warning: This Game does not support Card Reader, I will disable the card reader for you.\n");
config->emulateCardreader = 0;
return 0;
}
if (getConfig()->emulateCardreader && getConfig()->emulateDriveboard && gId != R_TUNED)
{
printf("Warning: This Game does not support Card Reader and Driver Board emulation enabled at the same time.\n");
printf("Please disable Drive Board emulations in the config file.\n");
return -1;
}
initReadCmd(0);
initReadCmd(1);
initWriteCmd(0);
initWriteCmd(1);
return 0;
}
int carReaderGetFdIdx(int fd)
{
if (fd == serialFD[0].fd)
return 0;
return 1;
}
uint8_t cardReaderGenChecksum(int fdIdx)
{
int checksum = 0;
for (int i = 0; i < readCmd[fdIdx].cmdLen - 1; i++)
{
checksum ^= readCmd[fdIdx].sendBuffer[i];
}
return checksum;
}
void buildOutputBuffer(int fdIdx, uint8_t cmd)
{
uint16_t packetLen = 0;
readCmd[fdIdx].sendBuffer[0] = 0x10;
readCmd[fdIdx].sendBuffer[1] = cmd;
switch (cmd)
{
case 0x10:
{
readCmd[fdIdx].sendBuffer[5] = 0x20;
}
case 0x11:
{
if (writeCmd[fdIdx].recBuffer[5] == 0x04)
{
initWriteCmd(fdIdx);
return;
}
}
case 0x14:
case 0x15:
case 0x20:
{
if (cmd == 0x20 && writeCmd[fdIdx].recBuffer[5] == 0x00)
readCmd[fdIdx].sendBuffer[4] = 0x80;
}
case 0x26:
case 0x27:
{
packetLen = 0x02;
readCmd[fdIdx].sendBuffer[3] = packetLen;
}
break;
case 0x21:
{
packetLen = 0x0a;
readCmd[fdIdx].sendBuffer[3] = packetLen;
readCmd[fdIdx].sendBuffer[6] = 0x81;
readCmd[fdIdx].sendBuffer[8] = 0x59;
readCmd[fdIdx].sendBuffer[9] = 0xda;
}
break;
case 0x22:
{
packetLen = 0x0a;
readCmd[fdIdx].sendBuffer[3] = packetLen;
readCmd[fdIdx].sendBuffer[7] = 0x08;
}
break;
case 0x33:
{
packetLen = 0x0a;
readCmd[fdIdx].sendBuffer[3] = packetLen;
readCmd[fdIdx].sendBuffer[6] = 0xff;
readCmd[fdIdx].sendBuffer[7] = 0xff;
}
break;
case 0x34:
{
uint16_t blockStart = (writeCmd[fdIdx].recBuffer[6] << 8) | writeCmd[fdIdx].recBuffer[7];
uint16_t blocksToRead = (writeCmd[fdIdx].recBuffer[8] << 8) | writeCmd[fdIdx].recBuffer[9];
packetLen = (BLOCKSIZE * blocksToRead) + 2;
readCmd[fdIdx].sendBuffer[3] = packetLen;
FILE *crdFile = fopen(serialFD[fdIdx].cardFilename, "rb");
fseek(crdFile, BLOCKSIZE * blockStart, SEEK_SET);
fread(readCmd[fdIdx].sendBuffer + 6, 1, packetLen - 2, crdFile);
fclose(crdFile);
}
break;
case 0x35:
{
readCmd[fdIdx].sendBuffer[3] = 0x02;
uint16_t blockStart = (writeCmd[fdIdx].recBuffer[6] << 8) | writeCmd[fdIdx].recBuffer[7];
uint16_t blocksToWrite = (writeCmd[fdIdx].recBuffer[8] << 8) | writeCmd[fdIdx].recBuffer[9];
packetLen = BLOCKSIZE * blocksToWrite;
FILE *crdFile = fopen(serialFD[fdIdx].cardFilename, "rb+");
fseek(crdFile, BLOCKSIZE * blockStart, SEEK_SET);
fwrite(writeCmd[fdIdx].recBuffer + 10, 1, packetLen, crdFile);
fclose(crdFile);
packetLen = 0x02;
}
break;
default:
{
printf("Command not supported.\n");
}
}
readCmd[fdIdx].cmdLen = packetLen + 5;
readCmd[fdIdx].sendBuffer[readCmd[fdIdx].cmdLen - 1] = cardReaderGenChecksum(fdIdx);
}
size_t cardReaderWrite(int fd, const void *buf, size_t count)
{
int fdIdx = carReaderGetFdIdx(fd);
if (writeCmd[fdIdx].cmdCompleted)
{
printf("Something went wrong, a write command was issued after the command was completed.\n");
}
if (writeCmd[fdIdx].recBytes == 4)
{
writeCmd[fdIdx].packetLen = (writeCmd[fdIdx].recBuffer[2] << 8) | writeCmd[fdIdx].recBuffer[3];
}
writeCmd[fdIdx].recBuffer[writeCmd[fdIdx].recBytes] = *((u_int8_t *)buf);
writeCmd[fdIdx].recBytes++;
if (writeCmd[fdIdx].recBytes == writeCmd[fdIdx].packetLen + 5)
{
writeCmd[fdIdx].cmdCompleted = true;
initReadCmd(fdIdx);
buildOutputBuffer(fdIdx, writeCmd[fdIdx].recBuffer[1]);
}
return count;
}
size_t cardReaderRead(int fd, void *buf, size_t count)
{
int fdIdx = carReaderGetFdIdx(fd);
if (!writeCmd[fdIdx].cmdCompleted || readCmd[fdIdx].cmdCompleted)
return -1;
if (readCmd[fdIdx].cmdLen == readCmd[fdIdx].sentBytes)
{
readCmd[fdIdx].cmdCompleted = true;
initWriteCmd(fdIdx);
return -1;
}
memcpy(buf, &readCmd[fdIdx].sendBuffer[readCmd[fdIdx].sentBytes], sizeof(uint8_t));
readCmd[fdIdx].sentBytes++;
return 1;
}
void cardReaderSetFd(int serial, int fd, char *fName)
{
serialFD[serial].fd = fd;
serialFD[serial].cardFilename = fName;
if (access(fName, F_OK) != 0)
{
FILE *crdFile = fopen(fName, "wb+");
if (getConfig()->crc32 == R_TUNED)
{
cardHeader[0x22] = 0x02;
cardHeader[0x23] = 0x60;
}
fwrite(cardHeader, 1, 56, crdFile);
uint8_t z = 0;
fseek(crdFile, 0x7c7, SEEK_CUR);
fwrite(&z, 1, 1, crdFile);
fclose(crdFile);
printf("Cardfile %s created.\n", fName);
}
}
+36
View File
@@ -0,0 +1,36 @@
#ifndef CARD_READER_H
#define CARD_READER_H
#include <stdint.h>
#include <sys/types.h>
typedef struct
{
int fd;
char *cardFilename;
} SerialFD;
typedef struct
{
bool cmdCompleted;
uint16_t packetLen;
uint8_t recBytes;
uint8_t recBuffer[256];
} WriteCommand;
typedef struct
{
uint8_t cmd;
bool cmdCompleted;
uint8_t cmdLen;
uint8_t sentBytes;
uint8_t sendBuffer[256];
} ReadCommand;
int initCardReader();
size_t cardReaderWrite(int fd, const void *buf, size_t count);
size_t cardReaderRead(int fd, void *buf, size_t count);
void cardReaderSetFd(int serial, int fd, char *fName);
#endif
+851 -652
View File
File diff suppressed because it is too large Load Diff
+26 -5
View File
@@ -2,6 +2,7 @@
#define CONFIG_H #define CONFIG_H
#include <stdint.h> #include <stdint.h>
#include <sys/types.h>
#define MAX_PATH_LENGTH 1024 #define MAX_PATH_LENGTH 1024
#define INPUT_STRING_LENGTH 256 #define INPUT_STRING_LENGTH 256
@@ -29,8 +30,9 @@
#define INITIALD_4_EXP_REVD 0x62cc73a9 // DVP-0030D #define INITIALD_4_EXP_REVD 0x62cc73a9 // DVP-0030D
#define INITIALD_5_JAP_REVA 0xb3183112 // DVP-0070A #define INITIALD_5_JAP_REVA 0xb3183112 // DVP-0070A
#define INITIALD_5_JAP_REVF 0xfc3dc85d // DVP-0070F #define INITIALD_5_JAP_REVF 0xfc3dc85d // DVP-0070F
#define INITIALD_5_EXP_30 0x77c6b58b // DVP-0075 and DVP-0084???? #define INITIALD_5_EXP 0x701b88cf // DVP-0075
#define INITIALD_5_EXP_40 0xd4910e75 // DVP-0084A #define INITIALD_5_EXP_20 0x77c6b58b // DVP-0084
#define INITIALD_5_EXP_20A 0xd4910e75 // DVP-0084A
#define LETS_GO_JUNGLE 0xb1c8c901 // DVP-0011 #define LETS_GO_JUNGLE 0xb1c8c901 // DVP-0011
#define LETS_GO_JUNGLE_REVA 0xc697c4fb // DVP-0011A #define LETS_GO_JUNGLE_REVA 0xc697c4fb // DVP-0011A
#define LETS_GO_JUNGLE_SPECIAL 0x240beedc // DVP-0036A #define LETS_GO_JUNGLE_SPECIAL 0x240beedc // DVP-0036A
@@ -70,7 +72,6 @@
#define VIRTUA_FIGHTER_5_REVB 0x8953bd52 // DVP-0008B #define VIRTUA_FIGHTER_5_REVB 0x8953bd52 // DVP-0008B
#define VIRTUA_FIGHTER_5_REVE 0x4c2edbf6 // DVP-0008E #define VIRTUA_FIGHTER_5_REVE 0x4c2edbf6 // DVP-0008E
#define VIRTUA_FIGHTER_5_EXPORT 0xec474630 // DVP-0043 #define VIRTUA_FIGHTER_5_EXPORT 0xec474630 // DVP-0043
#define VIRTUA_FIGHTER_5_FINAL_SHOWDOWN 0x48 // DVP-5019 or does not exist
#define VIRTUA_FIGHTER_5_FINAL_SHOWDOWN_REVA 0xbae2be62 // DVP-5019A #define VIRTUA_FIGHTER_5_FINAL_SHOWDOWN_REVA 0xbae2be62 // DVP-5019A
#define VIRTUA_FIGHTER_5_FINAL_SHOWDOWN_REVB 0x7cee1d81 // DVP-5020 #define VIRTUA_FIGHTER_5_FINAL_SHOWDOWN_REVB 0x7cee1d81 // DVP-5020
#define VIRTUA_FIGHTER_5_FINAL_SHOWDOWN_REVB_6000 0x34c0d02 // DVP-5020 ver 6.00 (Weird public version) #define VIRTUA_FIGHTER_5_FINAL_SHOWDOWN_REVB_6000 0x34c0d02 // DVP-5020 ver 6.00 (Weird public version)
@@ -182,6 +183,7 @@ typedef struct {
char player1_button_8[INPUT_STRING_LENGTH]; char player1_button_8[INPUT_STRING_LENGTH];
char player1_button_9[INPUT_STRING_LENGTH]; char player1_button_9[INPUT_STRING_LENGTH];
char player1_button_10[INPUT_STRING_LENGTH]; char player1_button_10[INPUT_STRING_LENGTH];
char player1_coin[INPUT_STRING_LENGTH];
// Player 2 controls // Player 2 controls
char player2_button_start[INPUT_STRING_LENGTH]; char player2_button_start[INPUT_STRING_LENGTH];
@@ -200,7 +202,8 @@ typedef struct {
char player2_button_8[INPUT_STRING_LENGTH]; char player2_button_8[INPUT_STRING_LENGTH];
char player2_button_9[INPUT_STRING_LENGTH]; char player2_button_9[INPUT_STRING_LENGTH];
char player2_button_10[INPUT_STRING_LENGTH]; char player2_button_10[INPUT_STRING_LENGTH];
char player2_coin[INPUT_STRING_LENGTH];
// Analogue inputs // Analogue inputs
char analogue_1[INPUT_STRING_LENGTH]; char analogue_1[INPUT_STRING_LENGTH];
char analogue_2[INPUT_STRING_LENGTH]; char analogue_2[INPUT_STRING_LENGTH];
@@ -222,6 +225,10 @@ typedef struct
int emulateRideboard; int emulateRideboard;
int emulateDriveboard; int emulateDriveboard;
int emulateMotionboard; int emulateMotionboard;
int emulateCardreader;
int emulateTouchscreen;
char cardFile1[MAX_PATH_LENGTH];
char cardFile2[MAX_PATH_LENGTH];
int emulateJVS; int emulateJVS;
int fullscreen; int fullscreen;
char eepromPath[MAX_PATH_LENGTH]; char eepromPath[MAX_PATH_LENGTH];
@@ -231,6 +238,7 @@ typedef struct
char serial2Path[MAX_PATH_LENGTH]; char serial2Path[MAX_PATH_LENGTH];
int width; int width;
int height; int height;
int boostRenderRes;
Colour lindberghColour; Colour lindberghColour;
GameStatus gameStatus; GameStatus gameStatus;
GameType gameType; GameType gameType;
@@ -257,7 +265,19 @@ typedef struct
int lgjRenderWithMesa; int lgjRenderWithMesa;
int noSDL; int noSDL;
int phMode; int phMode;
int disableBuiltinFont;
int disableBuiltinLogos;
int hideCursor;
char customCursor[MAX_PATH_LENGTH];
int customCursorWidth;
int customCursorHeight;
char phTouchCursor[MAX_PATH_LENGTH];
int phTouchCursorWidth;
int phTouchCursorHeight;
int mj4EnabledAtT; int mj4EnabledAtT;
char or2IP[16];
char or2Netmask[16];
float cpuFreqGhz;
ArcadeInputs arcadeInputs; ArcadeInputs arcadeInputs;
int inputMode; // 0 = both, 1 = SDL/X11 only, 2 = EVDEV only int inputMode; // 0 = both, 1 = SDL/X11 only, 2 = EVDEV only
int skipOutrunCabinetCheck; int skipOutrunCabinetCheck;
@@ -266,8 +286,9 @@ typedef struct
int borderEnabled; int borderEnabled;
} EmulatorConfig; } EmulatorConfig;
uint32_t get_crc32(const char *s, ssize_t n);
KeyMapping getDefaultKeymap(); KeyMapping getDefaultKeymap();
int initConfig(); int initConfig(const char* configFilePath);
EmulatorConfig *getConfig(); EmulatorConfig *getConfig();
char *getGameName(); char *getGameName();
char *getDVPName(); char *getDVPName();
+229
View File
@@ -0,0 +1,229 @@
#include <SDL2/SDL_events.h>
#include <SDL2/SDL_mouse.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#define STBI_ONLY_PNG
#define STBI_SUPPORT_ZLIB
#define STBI_NO_SIMD
#include <SDL2/SDL.h>
#include <X11/Xlib.h>
#include <X11/Xcursor/Xcursor.h>
#include "config.h"
extern Display *x11Display;
extern Window window;
void *customCursor;
void *phTouchCursor;
void *blankCursor;
SDL_Surface *createSurfaceFromStb(unsigned char *data, int width, int height, int channels)
{
Uint32 rmask, gmask, bmask, amask;
if (channels == 4)
{
rmask = 0x000000FF;
gmask = 0x0000FF00;
bmask = 0x00FF0000;
amask = 0xFF000000;
}
else if (channels == 3)
{
rmask = 0x000000FF;
gmask = 0x0000FF00;
bmask = 0x00FF0000;
amask = 0;
}
else
{
fprintf(stderr, "Unsupported image format with %d channels.\n", channels);
return NULL;
}
return SDL_CreateRGBSurfaceFrom(data, width, height, channels * 8, width * channels, rmask, gmask, bmask, amask);
}
int loadNewCursor(const char *cursorFileName, void **cursor, int customWidth, int customHeight)
{
int width, height, channels;
unsigned char *imageData = stbi_load(cursorFileName, &width, &height, &channels, 0);
if (!imageData)
{
fprintf(stderr, "Failed to load image: %s\n", cursorFileName);
return 0;
}
SDL_Surface *originalSurface = createSurfaceFromStb(imageData, width, height, channels);
if (!originalSurface)
{
stbi_image_free(imageData);
return 0;
}
SDL_Surface *resizedSurface =
SDL_CreateRGBSurface(0, customWidth, customHeight, originalSurface->format->BitsPerPixel, originalSurface->format->Rmask,
originalSurface->format->Gmask, originalSurface->format->Bmask, originalSurface->format->Amask);
if (!resizedSurface)
{
fprintf(stderr, "SDL_CreateRGBSurface Error: %s\n", SDL_GetError());
SDL_FreeSurface(originalSurface);
stbi_image_free(imageData);
return 0;
}
SDL_Rect srcRect = {0, 0, originalSurface->w, originalSurface->h};
SDL_Rect destRect = {0, 0, customWidth, customHeight};
if (SDL_BlitScaled(originalSurface, &srcRect, resizedSurface, &destRect) != 0)
{
fprintf(stderr, "SDL_BlitScaled Error: %s\n", SDL_GetError());
SDL_FreeSurface(resizedSurface);
SDL_FreeSurface(originalSurface);
stbi_image_free(imageData);
return 0;
}
if (getConfig()->noSDL == 0)
{
*cursor = SDL_CreateColorCursor(resizedSurface, customWidth / 2, customHeight / 2);
if (!*cursor)
{
fprintf(stderr, "SDL_CreateColorCursor Error: %s\n", SDL_GetError());
SDL_FreeSurface(resizedSurface);
SDL_FreeSurface(originalSurface);
stbi_image_free(imageData);
return 0;
}
SDL_FreeSurface(resizedSurface);
SDL_FreeSurface(originalSurface);
}
else
{
XcursorImage *xcursor = XcursorImageCreate(resizedSurface->w, resizedSurface->h);
if (!xcursor)
return None;
xcursor->xhot = customWidth / 2;
xcursor->yhot = customHeight / 2;
xcursor->width = resizedSurface->w;
xcursor->height = resizedSurface->h;
// Convert SDL surface to Xcursor format (32-bit ARGB)
for (int y = 0; y < resizedSurface->h; ++y)
{
for (int x = 0; x < resizedSurface->w; ++x)
{
Uint32 pixel = ((Uint32 *)resizedSurface->pixels)[y * resizedSurface->w + x];
Uint8 r, g, b, a;
SDL_GetRGBA(pixel, resizedSurface->format, &r, &g, &b, &a);
xcursor->pixels[y * resizedSurface->w + x] = (a << 24) | (r << 16) | (g << 8) | b;
}
}
*cursor = (void*)XcursorImageLoadCursor(x11Display, xcursor);
XcursorImageDestroy(xcursor);
}
return 1;
}
void loadCursors()
{
if (strcmp(getConfig()->customCursor, "") != 0)
{
if (!loadNewCursor(getConfig()->customCursor, (void *)&customCursor, getConfig()->customCursorWidth,
getConfig()->customCursorHeight))
{
fprintf(stderr, "Custom cursor could not be loaded!\n");
exit(1);
}
}
if (strcmp(getConfig()->phTouchCursor, "") != 0)
{
if (!loadNewCursor(getConfig()->phTouchCursor, (void *)&phTouchCursor, getConfig()->phTouchCursorWidth,
getConfig()->phTouchCursorHeight))
{
fprintf(stderr, "Custom cursor could not be loaded!\n");
exit(1);
}
}
if(getConfig()->noSDL)
{
XColor dummyColor;
Pixmap blankPixmap;
blankPixmap = XCreatePixmap(x11Display, window, 1, 1, 1);
if (!blankPixmap)
{
fprintf(stderr, "Failed to create blank pixmap\n");
}
blankCursor = (void*)XCreatePixmapCursor(x11Display, blankPixmap, blankPixmap, &dummyColor, &dummyColor, 0, 0);
if (!blankCursor)
{
fprintf(stderr, "Failed to create blank cursor\n");
XFreePixmap(x11Display, blankPixmap);
}
}
}
void setCursor(void *cursor)
{
if (getConfig()->noSDL == 0)
{
if (SDL_GetCursor() != NULL)
SDL_SetCursor(cursor);
}
else
{
XDefineCursor(x11Display, window, (Cursor)cursor);
XFlush(x11Display);
}
}
void hideCursor()
{
if (getConfig()->noSDL == 0)
{
SDL_ShowCursor(SDL_DISABLE);
}
else
{
XDefineCursor(x11Display, window, (Cursor)blankCursor);
XFlush(x11Display);
}
}
void showCursor()
{
if (getConfig()->noSDL == 0)
{
SDL_ShowCursor(SDL_ENABLE);
}
else
{
XDefineCursor(x11Display, window, (Cursor)customCursor);
XFlush(x11Display);
}
}
void showPhCursor()
{
if (getConfig()->noSDL == 0)
{
SDL_ShowCursor(SDL_ENABLE);
}
else
{
XDefineCursor(x11Display, window, (Cursor)phTouchCursor);
XFlush(x11Display);
}
}
+10
View File
@@ -0,0 +1,10 @@
#ifndef CUSTOM_CURSORS_H
#define CUSTOM_CURSORS_H
int loadNewCursor(const char *cursorFileName, void **cursor, int customWidth, int customHeight);
void loadCursors();
void setCursor(void *cursor);
void hideCursor();
void showCursor();
void showPhCursor();
#endif
+25 -8
View File
@@ -1,6 +1,7 @@
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include "config.h" #include "config.h"
#include "eeprom.h" #include "eeprom.h"
@@ -15,6 +16,8 @@
#define I2C_SEEK 2 #define I2C_SEEK 2
#define I2C_WRITE 3 #define I2C_WRITE 3
extern uint32_t gId;
union i2c_smbus_data { union i2c_smbus_data {
uint8_t byte; uint8_t byte;
uint16_t word; uint16_t word;
@@ -67,27 +70,41 @@ int initEeprom()
setFreeplay(eeprom, getConfig()->freeplay); setFreeplay(eeprom, getConfig()->freeplay);
} }
if ((getConfig()->crc32 == LETS_GO_JUNGLE_SPECIAL) || (getConfig()->crc32 == THE_HOUSE_OF_THE_DEAD_EX) || switch (gId)
(getConfig()->crc32 == THE_HOUSE_OF_THE_DEAD_4_SPECIAL) ||
(getConfig()->crc32 == THE_HOUSE_OF_THE_DEAD_4_SPECIAL_REVB))
{ {
case LETS_GO_JUNGLE_SPECIAL:
case THE_HOUSE_OF_THE_DEAD_EX:
case THE_HOUSE_OF_THE_DEAD_4_SPECIAL:
case THE_HOUSE_OF_THE_DEAD_4_SPECIAL_REVB:
if (fixCreditSection(eeprom) != 0) if (fixCreditSection(eeprom) != 0)
{ {
printf("Error initializing eeprom settings."); printf("Error initializing eeprom settings.");
fclose(eeprom); fclose(eeprom);
return 1; return 1;
} }
} break;
case HUMMER:
if (getConfig()->crc32 == HUMMER || getConfig()->crc32 == HUMMER_SDLX || getConfig()->crc32 == HUMMER_EXTREME || case HUMMER_SDLX:
getConfig()->crc32 == HUMMER_EXTREME_MDX) case HUMMER_EXTREME:
{ case HUMMER_EXTREME_MDX:
if (fixCoinAssignmentsHummer(eeprom) != 0) if (fixCoinAssignmentsHummer(eeprom) != 0)
{ {
printf("Error initializing eeprom settings."); printf("Error initializing eeprom settings.");
fclose(eeprom); fclose(eeprom);
return 1; return 1;
} }
break;
case OUTRUN_2_SP_SDX:
case OUTRUN_2_SP_SDX_REVA:
if (strcmp(getConfig()->or2IP, "") != 0)
{
if (setIP(eeprom, getConfig()->or2IP, getConfig()->or2Netmask) != 0)
{
printf("Error setting the new IP address.");
fclose(eeprom);
return 1;
}
}
} }
fseek(eeprom, 0, SEEK_SET); fseek(eeprom, 0, SEEK_SET);
+17 -1
View File
@@ -3,7 +3,6 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "config.h"
#include "eeprom_settings.h" #include "eeprom_settings.h"
uint32_t crc32_table[255]; uint32_t crc32_table[255];
@@ -226,6 +225,23 @@ int fixCoinAssignmentsHummer(FILE *eeprom)
return 0; return 0;
} }
int setIP(FILE *eeprom, char *ipAddress, char *netMask)
{
uint32_t ipHex = inet_addr(ipAddress);
uint32_t nMask = inet_addr(netMask);
uint32_t dhcp = 0;
memcpy(&eepromBuffer[eepromOffsetTable[ETH0].offset + 8], &dhcp, sizeof(uint32_t));
memcpy(&eepromBuffer[eepromOffsetTable[ETH0].offset + 12], &ipHex, sizeof(uint32_t));
memcpy(&eepromBuffer[eepromOffsetTable[ETH0].offset + 16], &nMask, sizeof(uint32_t));
addCRCtoBuffer(ETH0);
if (writeSectiontoFile(eeprom, ETH0) != 0)
{
printf("Error writing to eeprom.");
return 1;
}
return 0;
}
int eepromSettingsInit( FILE *eeprom) int eepromSettingsInit( FILE *eeprom)
{ {
build_crc32_table(); build_crc32_table();
+3 -1
View File
@@ -1,7 +1,9 @@
#include <stdio.h>
int eepromSettingsInit(FILE *eeprom); int eepromSettingsInit(FILE *eeprom);
int getRegion(); int getRegion();
int getFreeplay(); int getFreeplay();
int setRegion(FILE *eeprom, int region); int setRegion(FILE *eeprom, int region);
int setFreeplay(FILE *eeprom, int freeplay); int setFreeplay(FILE *eeprom, int freeplay);
int fixCreditSection(FILE *eeprom); int fixCreditSection(FILE *eeprom);
int fixCoinAssignmentsHummer(FILE *eeprom); int fixCoinAssignmentsHummer(FILE *eeprom);
int setIP(FILE *eeprom, char *ipAddress, char *netMask);
+24 -2
View File
@@ -41,6 +41,7 @@ ArcadeInput arcadeInputs[] = {{"TEST_BUTTON", 0, BUTTON_TEST, 1},
{"PLAYER_1_BUTTON_8", 1, BUTTON_8, 1}, {"PLAYER_1_BUTTON_8", 1, BUTTON_8, 1},
{"PLAYER_1_BUTTON_9", 1, BUTTON_9, 1}, {"PLAYER_1_BUTTON_9", 1, BUTTON_9, 1},
{"PLAYER_1_BUTTON_10", 1, BUTTON_10, 1}, {"PLAYER_1_BUTTON_10", 1, BUTTON_10, 1},
{"PLAYER_1_COIN", 1, COIN, 1},
{"PLAYER_2_BUTTON_START", 2, BUTTON_START, 1}, {"PLAYER_2_BUTTON_START", 2, BUTTON_START, 1},
{"PLAYER_2_BUTTON_SERVICE", 2, BUTTON_SERVICE, 1}, {"PLAYER_2_BUTTON_SERVICE", 2, BUTTON_SERVICE, 1},
@@ -58,6 +59,7 @@ ArcadeInput arcadeInputs[] = {{"TEST_BUTTON", 0, BUTTON_TEST, 1},
{"PLAYER_2_BUTTON_8", 2, BUTTON_8, 1}, {"PLAYER_2_BUTTON_8", 2, BUTTON_8, 1},
{"PLAYER_2_BUTTON_9", 2, BUTTON_9, 1}, {"PLAYER_2_BUTTON_9", 2, BUTTON_9, 1},
{"PLAYER_2_BUTTON_10", 2, BUTTON_10, 1}, {"PLAYER_2_BUTTON_10", 2, BUTTON_10, 1},
{"PLAYER_2_COIN", 2, COIN, 1},
{"ANALOGUE_1", 0, ANALOGUE_1, 1}, {"ANALOGUE_1", 0, ANALOGUE_1, 1},
{"ANALOGUE_2", 0, ANALOGUE_2, 1}, {"ANALOGUE_2", 0, ANALOGUE_2, 1},
@@ -1048,8 +1050,13 @@ void *controllerThread(void *_args)
continue; continue;
} }
setSwitch(args->controller->keyTriggers[event.code].player, if(args->controller->keyTriggers[event.code].isCoin == 1) {
args->controller->keyTriggers[event.code].channel, event.value == 0 ? 0 : 1); if(event.value == 1)
incrementCoin(args->controller->keyTriggers[event.code].player, 1);
} else
setSwitch(args->controller->keyTriggers[event.code].player,
args->controller->keyTriggers[event.code].channel, event.value == 0 ? 0 : 1);
} }
break; break;
@@ -1106,6 +1113,10 @@ char *getMapping(char *mapping)
// Test button // Test button
if (strcmp(mapping, config->arcadeInputs.test) == 0) if (strcmp(mapping, config->arcadeInputs.test) == 0)
return "TEST_BUTTON"; return "TEST_BUTTON";
if (strcmp(mapping, config->arcadeInputs.player1_coin) == 0)
return "PLAYER_1_COIN";
if (strcmp(mapping, config->arcadeInputs.player2_coin) == 0)
return "PLAYER_2_COIN";
// Player 1 controls // Player 1 controls
if (strcmp(mapping, config->arcadeInputs.player1_button_start) == 0) if (strcmp(mapping, config->arcadeInputs.player1_button_start) == 0)
@@ -1238,6 +1249,7 @@ ControllerStatus startControllerThreads(Controllers *controllers)
{ {
controllers->controller[i].keyTriggers[j].enabled = 0; controllers->controller[i].keyTriggers[j].enabled = 0;
controllers->controller[i].keyTriggers[j].isAnalogue = 0; controllers->controller[i].keyTriggers[j].isAnalogue = 0;
controllers->controller[i].keyTriggers[j].isCoin = 0;
} }
for (int j = 0; j < controllers->controller[i].inputCount; j++) for (int j = 0; j < controllers->controller[i].inputCount; j++)
@@ -1314,6 +1326,16 @@ ControllerStatus startControllerThreads(Controllers *controllers)
if (strstr(input.name, "ANALOGUE") != NULL) if (strstr(input.name, "ANALOGUE") != NULL)
controllers->controller[i].keyTriggers[controllers->controller[i].inputs[j].evCode].isAnalogue = 1; controllers->controller[i].keyTriggers[controllers->controller[i].inputs[j].evCode].isAnalogue = 1;
if (strcmp(input.name, "PLAYER_1_COIN") == 0)
{
controllers->controller[i].keyTriggers[controllers->controller[i].inputs[j].evCode].isCoin = 1;
}
if (strcmp(input.name, "PLAYER_2_COIN") == 0)
{
controllers->controller[i].keyTriggers[controllers->controller[i].inputs[j].evCode].isCoin = 1;
}
} }
break; break;
+1
View File
@@ -31,6 +31,7 @@ typedef struct
int maxEnabled; int maxEnabled;
int isAnalogue; int isAnalogue;
int isCoin;
} ArcadeInput; } ArcadeInput;
typedef enum typedef enum
+46 -22
View File
@@ -22,10 +22,13 @@
#include "fps_limiter.h" #include "fps_limiter.h"
#include "sdlcalls.h" #include "sdlcalls.h"
#include "border.h" #include "border.h"
#include "resolution.h"
extern uint32_t gId;
extern SDL_Window *SDLwindow; extern SDL_Window *SDLwindow;
extern char SDLgameTitle[]; extern char SDLgameTitle[];
extern fps_limit fpsLimit; extern fps_limit fpsLimit;
bool GLUTGame = false;
void *displayFunc = NULL; void *displayFunc = NULL;
void *reshapeFunc = NULL; void *reshapeFunc = NULL;
@@ -34,19 +37,26 @@ void *idleFunc = NULL;
void FGAPIENTRY glutInit(int *argcp, char **argv) void FGAPIENTRY glutInit(int *argcp, char **argv)
{ {
if (*argcp > 1 && getConfig()->crc32 == SEGA_RACE_TV) void FGAPIENTRY (*_glutInit)(int *argcp, char **argv) = dlsym(RTLD_NEXT, "glutInit");
if (*argcp > 1 && gId == SEGA_RACE_TV)
{ {
for (int x = 0; x < *argcp; x++) if (isTestMode())
{ {
if (strcmp(argv[x], "-t") == 0) EmulatorConfig *config = getConfig();
{ config->noSDL = 0;
EmulatorConfig *config = getConfig(); printf("Forced to use SDL to make Test mode render fine.\n");
config->noSDL = 0;
printf("Forced to use SDL to make Test mode render fine.");
}
} }
} }
glutInitSDL(argcp, argv);
if (getConfig()->noSDL)
{
_glutInit(argcp, argv);
return;
}
GLUTGame = true;
initSDL(argcp, argv);
} }
void FGAPIENTRY glutMainLoop(void) void FGAPIENTRY glutMainLoop(void)
@@ -101,10 +111,13 @@ void FGAPIENTRY glutSwapBuffers(void)
return; return;
} }
int gId = config->crc32; switch (gId)
if (gId == OUTRUN_2_SP_SDX || gId == OUTRUN_2_SP_SDX_REVA || gId == OUTRUN_2_SP_SDX_REVA_TEST || gId == OUTRUN_2_SP_SDX_REVA_TEST2 ||
gId == OUTRUN_2_SP_SDX_TEST)
{ {
case OUTRUN_2_SP_SDX:
case OUTRUN_2_SP_SDX_REVA:
case OUTRUN_2_SP_SDX_REVA_TEST:
case OUTRUN_2_SP_SDX_REVA_TEST2:
case OUTRUN_2_SP_SDX_TEST:
pollEvents(); pollEvents();
} }
@@ -173,11 +186,15 @@ void FGAPIENTRY glutSetCursor(int glutCursor)
if (getConfig()->noSDL) if (getConfig()->noSDL)
{ {
void FGAPIENTRY (*_glutSetCursor)(int glutCursor) = dlsym(RTLD_NEXT, "glutSetCursor"); void FGAPIENTRY (*_glutSetCursor)(int glutCursor) = dlsym(RTLD_NEXT, "glutSetCursor");
_glutSetCursor(glutCursor); if(strcmp(getConfig()->customCursor, "") == 0)
_glutSetCursor(glutCursor);
return; return;
} }
SDL_Cursor *cursor = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW); if (strcmp(getConfig()->customCursor, "") == 0)
SDL_SetCursor(cursor); {
SDL_Cursor *cursor = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW);
SDL_SetCursor(cursor);
}
} }
void FGAPIENTRY glutDisplayFunc(void (*callback)(void)) void FGAPIENTRY glutDisplayFunc(void (*callback)(void))
@@ -296,7 +313,8 @@ void FGAPIENTRY glutKeyboardFunc(void (*callback)(unsigned char, int, int))
{ {
if (getConfig()->noSDL) if (getConfig()->noSDL)
{ {
void FGAPIENTRY (*_glutKeyboardFunc)(void (*callback)(unsigned char, int, int)) = dlsym(RTLD_NEXT, "glutKeyboardFunc"); void FGAPIENTRY (*_glutKeyboardFunc)(void (*callback)(unsigned char, int, int)) =
dlsym(RTLD_NEXT, "glutKeyboardFunc");
_glutKeyboardFunc(callback); _glutKeyboardFunc(callback);
return; return;
} }
@@ -307,7 +325,8 @@ void FGAPIENTRY glutKeyboardUpFunc(void (*callback)(unsigned char, int, int))
{ {
if (getConfig()->noSDL) if (getConfig()->noSDL)
{ {
void FGAPIENTRY (*_glutKeyboardUpFunc)(void (*callback)(unsigned char, int, int)) = dlsym(RTLD_NEXT, "glutKeyboardUpFunc"); void FGAPIENTRY (*_glutKeyboardUpFunc)(void (*callback)(unsigned char, int, int)) =
dlsym(RTLD_NEXT, "glutKeyboardUpFunc");
_glutKeyboardUpFunc(callback); _glutKeyboardUpFunc(callback);
return; return;
} }
@@ -362,7 +381,8 @@ void FGAPIENTRY glutPassiveMotionFunc(void (*callback)(int, int))
{ {
if (getConfig()->noSDL) if (getConfig()->noSDL)
{ {
void FGAPIENTRY (*_glutPassiveMotionFunc)(void (*callback)(int, int)) = dlsym(RTLD_NEXT, "glutPassiveMotionFunc"); void FGAPIENTRY (*_glutPassiveMotionFunc)(void (*callback)(int, int)) =
dlsym(RTLD_NEXT, "glutPassiveMotionFunc");
_glutPassiveMotionFunc(callback); _glutPassiveMotionFunc(callback);
return; return;
} }
@@ -417,7 +437,8 @@ void FGAPIENTRY glutSolidSphere(double radius, GLint slices, GLint stacks)
{ {
if (getConfig()->noSDL) if (getConfig()->noSDL)
{ {
void FGAPIENTRY (*_glutSolidSphere)(double radius, GLint slices, GLint stacks) = dlsym(RTLD_NEXT, "glutSolidSphere"); void FGAPIENTRY (*_glutSolidSphere)(double radius, GLint slices, GLint stacks) =
dlsym(RTLD_NEXT, "glutSolidSphere");
_glutSolidSphere(radius, slices, stacks); _glutSolidSphere(radius, slices, stacks);
return; return;
} }
@@ -428,7 +449,8 @@ void FGAPIENTRY glutWireSphere(double radius, GLint slices, GLint stacks)
{ {
if (getConfig()->noSDL) if (getConfig()->noSDL)
{ {
void FGAPIENTRY (*_glutWireSphere)(double radius, GLint slices, GLint stacks) = dlsym(RTLD_NEXT, "glutWireSphere"); void FGAPIENTRY (*_glutWireSphere)(double radius, GLint slices, GLint stacks) =
dlsym(RTLD_NEXT, "glutWireSphere");
_glutWireSphere(radius, slices, stacks); _glutWireSphere(radius, slices, stacks);
return; return;
} }
@@ -439,7 +461,8 @@ void FGAPIENTRY glutWireCone(double base, double height, GLint slices, GLint sta
{ {
if (getConfig()->noSDL) if (getConfig()->noSDL)
{ {
void FGAPIENTRY (*_glutWireCone)(double base, double height, GLint slices, GLint stacks) = dlsym(RTLD_NEXT, "glutWireCone"); void FGAPIENTRY (*_glutWireCone)(double base, double height, GLint slices, GLint stacks) =
dlsym(RTLD_NEXT, "glutWireCone");
_glutWireCone(base, height, slices, stacks); _glutWireCone(base, height, slices, stacks);
return; return;
} }
@@ -450,7 +473,8 @@ void FGAPIENTRY glutSolidCone(double base, double height, GLint slices, GLint st
{ {
if (getConfig()->noSDL) if (getConfig()->noSDL)
{ {
void FGAPIENTRY (*_glutSolidCone)(double base, double height, GLint slices, GLint stacks) = dlsym(RTLD_NEXT, "glutSolidCone"); void FGAPIENTRY (*_glutSolidCone)(double base, double height, GLint slices, GLint stacks) =
dlsym(RTLD_NEXT, "glutSolidCone");
_glutSolidCone(base, height, slices, stacks); _glutSolidCone(base, height, slices, stacks);
return; return;
} }
-25
View File
@@ -1,29 +1,4 @@
#ifndef GLUTHOOKS_H #ifndef GLUTHOOKS_H
#define GLUTHOOKS_H #define GLUTHOOKS_H
#include <GL/glx.h>
int myCreateWindow(int *param1);
void hod4glXSwapBuffers(Display *dpy, GLXDrawable drawable);
#endif #endif
// #include <GL/freeglut.h>
// /* The bitmap font structure taken from freeglut*/
// typedef struct tagSFG_Font SFG_Font;
// struct tagSFG_Font
// {
// char *Name; /* The source font name */
// int Quantity; /* Number of chars in font */
// int Height; /* Height of the characters */
// const GLubyte **Characters; /* The characters mapping */
// float xorig, yorig; /* Relative origin of the character */
// };
// extern SFG_Font fgFontFixed8x13;
// extern SFG_Font fgFontFixed9x15;
// extern SFG_Font fgFontHelvetica10;
// extern SFG_Font fgFontHelvetica12;
// extern SFG_Font fgFontHelvetica18;
// extern SFG_Font fgFontTimesRoman10;
// extern SFG_Font fgFontTimesRoman24;
+125 -61
View File
@@ -19,6 +19,7 @@
#include <dlfcn.h> #include <dlfcn.h>
#include <SDL2/SDL.h> #include <SDL2/SDL.h>
#include <sys/time.h> #include <sys/time.h>
#include <stdio.h>
#include "fps_limiter.h" #include "fps_limiter.h"
#include "sdlcalls.h" #include "sdlcalls.h"
@@ -27,27 +28,66 @@
#include "border.h" #include "border.h"
bool sdlGame = false; bool sdlGame = false;
extern uint32_t gId;
extern SDL_Window *SDLwindow; extern SDL_Window *SDLwindow;
extern SDL_GLContext SDLcontext; extern SDL_GLContext SDLcontext;
extern char SDLgameTitle[]; extern char SDLgameTitle[];
extern fps_limit fpsLimit; extern fps_limit fpsLimit;
extern Window win; extern Window window;
void glXToSDLSwapBuffers(Display *dpy, GLXDrawable drawable) void glXSwapBuffers(Display *dpy, GLXDrawable drawable)
{ {
pollEvents(); void (*_glXSwapBuffers)(Display *dpy, GLXDrawable drawable) = dlsym(RTLD_NEXT, "glXSwapBuffers");
EmulatorConfig *config = getConfig(); EmulatorConfig *config = getConfig();
if (config->borderEnabled) if (config->borderEnabled)
drawGameBorder(config->width, config->height, config->whiteBorderPercentage, config->blackBorderPercentage); drawGameBorder(config->width, config->height, config->whiteBorderPercentage, config->blackBorderPercentage);
SDL_GL_SwapWindow(SDLwindow); if (getConfig()->noSDL)
{
switch (gId)
{
case OUTRUN_2_SP_SDX:
case OUTRUN_2_SP_SDX_REVA:
case OUTRUN_2_SP_SDX_REVA_TEST:
case OUTRUN_2_SP_SDX_REVA_TEST2:
case OUTRUN_2_SP_SDX_TEST:
{
XEvent event;
while (XPending(dpy))
{
XNextEvent(dpy, &event);
}
}
}
}
else
{
pollEvents();
}
if (getConfig()->noSDL)
{
_glXSwapBuffers(dpy, drawable);
}
else
{
SDL_GL_SwapWindow(SDLwindow);
}
if (getConfig()->fpsLimiter) if (getConfig()->fpsLimiter)
{ {
fpsLimit.frameStart = Clock_now(); fpsLimit.frameStart = Clock_now();
FpsLimiter(&fpsLimit); FpsLimiter(&fpsLimit);
fpsLimit.frameEnd = Clock_now(); fpsLimit.frameEnd = Clock_now();
} }
if (getConfig()->noSDL)
{
XStoreName(dpy, window, "");
return;
}
char windowTitle[512]; char windowTitle[512];
sprintf(windowTitle, "%s - FPS: %.2f", SDLgameTitle, calculateFps()); sprintf(windowTitle, "%s - FPS: %.2f", SDLgameTitle, calculateFps());
SDL_SetWindowTitle(SDLwindow, windowTitle); SDL_SetWindowTitle(SDLwindow, windowTitle);
@@ -55,7 +95,7 @@ void glXToSDLSwapBuffers(Display *dpy, GLXDrawable drawable)
int glxSDLmyCreateWindow(int *param1) int glxSDLmyCreateWindow(int *param1)
{ {
glutInitSDL(0, 0); initSDL(0, 0);
char *buf = malloc(512); char *buf = malloc(512);
memset(buf, '\0', 512); memset(buf, '\0', 512);
// param1[0x17] = (intptr_t)(void *)buf; // window; // param1[0x17] = (intptr_t)(void *)buf; // window;
@@ -63,16 +103,37 @@ int glxSDLmyCreateWindow(int *param1)
return 1; return 1;
} }
static int nVidiaAttribs[] = {GLX_RGBA,
GLX_DOUBLEBUFFER,
GLX_RED_SIZE,
8,
GLX_GREEN_SIZE,
8,
GLX_BLUE_SIZE,
8,
GLX_ALPHA_SIZE,
8,
GLX_DEPTH_SIZE,
16,
GLX_STENCIL_SIZE,
8,
None};
XVisualInfo *glXChooseVisual(Display *dpy, int screen, int *attribList) XVisualInfo *glXChooseVisual(Display *dpy, int screen, int *attribList)
{ {
XVisualInfo *(*_glXChooseVisual)(Display *dpy, int screen, int *attribList) = dlsym(RTLD_NEXT, "glXChooseVisual"); XVisualInfo *(*_glXChooseVisual)(Display *dpy, int screen, int *attribList) = dlsym(RTLD_NEXT, "glXChooseVisual");
if (sdlGame) if (sdlGame)
return 0; return 0;
if (getConfig()->GPUVendor == NVIDIA_GPU)
{
return _glXChooseVisual(dpy, screen, nVidiaAttribs);
}
return _glXChooseVisual(dpy, screen, attribList); return _glXChooseVisual(dpy, screen, attribList);
} }
void GLAPIENTRY openglDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, void GLAPIENTRY openglDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length,
const void *userParam) const GLchar *message, const void *userParam)
{ {
if (id == 1099) if (id == 1099)
return; return;
@@ -91,35 +152,6 @@ void GLAPIENTRY openglDebugCallback(GLenum source, GLenum type, GLuint id, GLenu
} }
} }
void glXSwapBuffers(Display *dpy, GLXDrawable drawable)
{
void (*_glXSwapBuffers)(Display *dpy, GLXDrawable drawable) = dlsym(RTLD_NEXT, "glXSwapBuffers");
EmulatorConfig *config = getConfig();
if (config->borderEnabled)
drawGameBorder(config->width, config->height, config->whiteBorderPercentage, config->blackBorderPercentage);
int gId = config->crc32;
if (getConfig()->noSDL && (gId == OUTRUN_2_SP_SDX || gId == OUTRUN_2_SP_SDX_REVA || gId == OUTRUN_2_SP_SDX_REVA_TEST ||
gId == OUTRUN_2_SP_SDX_REVA_TEST2 || gId == OUTRUN_2_SP_SDX_TEST))
{
XEvent event;
while (XPending(dpy))
{
XNextEvent(dpy, &event);
}
}
_glXSwapBuffers(dpy, drawable);
if (config->fpsLimiter)
{
fpsLimit.frameStart = Clock_now();
FpsLimiter(&fpsLimit);
fpsLimit.frameEnd = Clock_now();
}
XStoreName(dpy, win, "");
}
GLXContext glXCreateContext(Display *dpy, XVisualInfo *vis, GLXContext shareList, Bool direct) GLXContext glXCreateContext(Display *dpy, XVisualInfo *vis, GLXContext shareList, Bool direct)
{ {
GLXContext (*_glXCreateContext)(Display *dpy, XVisualInfo *vis, GLXContext shareList, Bool direct) = GLXContext (*_glXCreateContext)(Display *dpy, XVisualInfo *vis, GLXContext shareList, Bool direct) =
@@ -150,7 +182,8 @@ GLXContext glXGetCurrentContext()
GLXPbuffer glXCreatePbuffer(Display *dpy, GLXFBConfig config, const int *attrib_list) GLXPbuffer glXCreatePbuffer(Display *dpy, GLXFBConfig config, const int *attrib_list)
{ {
GLXPbuffer (*_glXCreatePbuffer)(Display *dpy, GLXFBConfig config, const int *attrib_list) = dlsym(RTLD_NEXT, "glXCreatePbuffer"); GLXPbuffer (*_glXCreatePbuffer)(Display *dpy, GLXFBConfig config, const int *attrib_list) =
dlsym(RTLD_NEXT, "glXCreatePbuffer");
if (sdlGame) if (sdlGame)
return 0; return 0;
return _glXCreatePbuffer(dpy, config, attrib_list); return _glXCreatePbuffer(dpy, config, attrib_list);
@@ -174,7 +207,8 @@ void glXDestroyPbuffer(Display *dpy, GLXPbuffer pbuf)
XVisualInfo *glXGetVisualFromFBConfig(Display *dpy, GLXFBConfig config) XVisualInfo *glXGetVisualFromFBConfig(Display *dpy, GLXFBConfig config)
{ {
XVisualInfo *(*_glXGetVisualFromFBConfig)(Display *dpy, GLXFBConfig config) = dlsym(RTLD_NEXT, "glXGetVisualFromFBConfig"); XVisualInfo *(*_glXGetVisualFromFBConfig)(Display *dpy, GLXFBConfig config) =
dlsym(RTLD_NEXT, "glXGetVisualFromFBConfig");
if (sdlGame) if (sdlGame)
return 0; return 0;
return _glXGetVisualFromFBConfig(dpy, config); return _glXGetVisualFromFBConfig(dpy, config);
@@ -204,35 +238,44 @@ GLXFBConfig *glXChooseFBConfig(Display *dpy, int screen, const int *attrib_list,
GLXFBConfig *(*_glXChooseFBConfig)(Display *dpy, int screen, const int *attrib_list, int *nelements) = GLXFBConfig *(*_glXChooseFBConfig)(Display *dpy, int screen, const int *attrib_list, int *nelements) =
dlsym(RTLD_NEXT, "glXChooseFBConfig"); dlsym(RTLD_NEXT, "glXChooseFBConfig");
int gId = getConfig()->crc32;
char *__GLX_VENDOR_LIBRARY_NAME = getenv("__GLX_VENDOR_LIBRARY_NAME"); char *__GLX_VENDOR_LIBRARY_NAME = getenv("__GLX_VENDOR_LIBRARY_NAME");
char *__NV_PRIME_RENDER_OFFLOAD = getenv("__NV_PRIME_RENDER_OFFLOAD"); char *__NV_PRIME_RENDER_OFFLOAD = getenv("__NV_PRIME_RENDER_OFFLOAD");
if (__GLX_VENDOR_LIBRARY_NAME == NULL) if (__GLX_VENDOR_LIBRARY_NAME == NULL)
__GLX_VENDOR_LIBRARY_NAME = " "; __GLX_VENDOR_LIBRARY_NAME = " ";
if (__NV_PRIME_RENDER_OFFLOAD == NULL) if (__NV_PRIME_RENDER_OFFLOAD == NULL)
__NV_PRIME_RENDER_OFFLOAD = " "; __NV_PRIME_RENDER_OFFLOAD = " ";
if ((strcmp(__GLX_VENDOR_LIBRARY_NAME, "nvidia") == 0) && (strcmp(__NV_PRIME_RENDER_OFFLOAD, "1") == 0) &&
((gId == THE_HOUSE_OF_THE_DEAD_4_REVA) || (gId == THE_HOUSE_OF_THE_DEAD_4_REVB) || (gId == THE_HOUSE_OF_THE_DEAD_4_REVC) || switch (gId)
(gId == THE_HOUSE_OF_THE_DEAD_4_SPECIAL) || (gId == THE_HOUSE_OF_THE_DEAD_4_SPECIAL_REVB) || (gId == THE_HOUSE_OF_THE_DEAD_EX) ||
(gId == TOO_SPICY)))
{ {
for (int i = 0; attrib_list[i] != None; i += 2) case THE_HOUSE_OF_THE_DEAD_4_REVA:
case THE_HOUSE_OF_THE_DEAD_4_REVB:
case THE_HOUSE_OF_THE_DEAD_4_REVC:
case THE_HOUSE_OF_THE_DEAD_4_SPECIAL:
case THE_HOUSE_OF_THE_DEAD_4_SPECIAL_REVB:
case THE_HOUSE_OF_THE_DEAD_EX:
case TOO_SPICY:
{
if (strcmp(__GLX_VENDOR_LIBRARY_NAME, "nvidia") == 0 && strcmp(__NV_PRIME_RENDER_OFFLOAD, "1") == 0)
{ {
if (attrib_list[i] == GLX_DOUBLEBUFFER) for (int i = 0; attrib_list[i] != None; i += 2)
{ {
int *ptr = (int *)&attrib_list[i + 1]; if (attrib_list[i] == GLX_DOUBLEBUFFER)
patchMemory((intptr_t)ptr, "01"); {
setVariable((intptr_t)ptr, GLX_DONT_CARE); int *ptr = (int *)&attrib_list[i + 1];
patchMemory((intptr_t)ptr, "01");
setVariable((intptr_t)ptr, GLX_DONT_CARE);
}
} }
} }
} }
}
return _glXChooseFBConfig(dpy, screen, attrib_list, nelements); return _glXChooseFBConfig(dpy, screen, attrib_list, nelements);
} }
GLXContext glXCreateNewContext(Display *dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct) GLXContext glXCreateNewContext(Display *dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct)
{ {
GLXContext (*_glXCreateNewContext)(Display *dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct) = GLXContext (*_glXCreateNewContext)(Display *dpy, GLXFBConfig config, int render_type, GLXContext share_list,
dlsym(RTLD_NEXT, "glXCreateNewContext"); Bool direct) = dlsym(RTLD_NEXT, "glXCreateNewContext");
GLXContext ctx = _glXCreateNewContext(dpy, config, render_type, share_list, direct); GLXContext ctx = _glXCreateNewContext(dpy, config, render_type, share_list, direct);
@@ -246,12 +289,20 @@ GLXContext glXCreateNewContext(Display *dpy, GLXFBConfig config, int render_type
return ctx; return ctx;
} }
GLXPbuffer glXCreateGLXPbufferSGIX(Display *dpy, GLXFBConfigSGIX config, unsigned int width, unsigned int height, int *attrib_list) GLXPbuffer glXCreateGLXPbufferSGIX(Display *dpy, GLXFBConfigSGIX config, unsigned int width, unsigned int height,
int *attrib_list)
{ {
if (sdlGame) if (sdlGame)
return 0; return 0;
int pbufferAttribs[] = { int pbufferAttribs[] = {GLX_PBUFFER_WIDTH,
GLX_PBUFFER_WIDTH, width, GLX_PBUFFER_HEIGHT, height, GLX_PRESERVED_CONTENTS, true, GLX_LARGEST_PBUFFER, true, None}; width,
GLX_PBUFFER_HEIGHT,
height,
GLX_PRESERVED_CONTENTS,
true,
GLX_LARGEST_PBUFFER,
true,
None};
return glXCreatePbuffer(dpy, config, pbufferAttribs); return glXCreatePbuffer(dpy, config, pbufferAttribs);
} }
@@ -273,19 +324,31 @@ GLXFBConfigSGIX *glXChooseFBConfigSGIX(Display *dpy, int screen, int *attrib_lis
__GLX_VENDOR_LIBRARY_NAME = " "; __GLX_VENDOR_LIBRARY_NAME = " ";
if (__NV_PRIME_RENDER_OFFLOAD == NULL) if (__NV_PRIME_RENDER_OFFLOAD == NULL)
__NV_PRIME_RENDER_OFFLOAD = " "; __NV_PRIME_RENDER_OFFLOAD = " ";
if ((strcmp(__GLX_VENDOR_LIBRARY_NAME, "nvidia") == 0) && (strcmp(__NV_PRIME_RENDER_OFFLOAD, "1") == 0) &&
((gId == INITIALD_4_REVA) || (gId == INITIALD_4_REVB) || (gId == INITIALD_4_REVC) || (gId == INITIALD_4_REVD) || switch (gId)
(gId == INITIALD_4_REVG) || (gId == INITIALD_4_EXP_REVB) || (gId == INITIALD_4_EXP_REVC) || gId == INITIALD_4_EXP_REVD))
{ {
for (int i = 0; attrib_list[i] != None; i += 2) case INITIALD_4_REVA:
case INITIALD_4_REVB:
case INITIALD_4_REVC:
case INITIALD_4_REVD:
case INITIALD_4_REVG:
case INITIALD_4_EXP_REVB:
case INITIALD_4_EXP_REVC:
case INITIALD_4_EXP_REVD:
{
if (strcmp(__GLX_VENDOR_LIBRARY_NAME, "nvidia") == 0 && strcmp(__NV_PRIME_RENDER_OFFLOAD, "1") == 0)
{ {
if (attrib_list[i] == GLX_DOUBLEBUFFER) for (int i = 0; attrib_list[i] != None; i += 2)
{ {
int *ptr = (int *)&attrib_list[i + 1]; if (attrib_list[i] == GLX_DOUBLEBUFFER)
patchMemory((intptr_t)ptr, "01"); {
int *ptr = (int *)&attrib_list[i + 1];
patchMemory((intptr_t)ptr, "01");
}
} }
} }
} }
}
return glXChooseFBConfig(dpy, screen, attrib_list, nelements); return glXChooseFBConfig(dpy, screen, attrib_list, nelements);
} }
@@ -296,7 +359,8 @@ int glXGetFBConfigAttribSGIX(Display *dpy, GLXFBConfigSGIX config, int attribute
return glXGetFBConfigAttrib(dpy, config, attribute, value); return glXGetFBConfigAttrib(dpy, config, attribute, value);
} }
GLXContext glXCreateContextWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, int render_type, GLXContext share_list, Bool direct) GLXContext glXCreateContextWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, int render_type, GLXContext share_list,
Bool direct)
{ {
if (sdlGame) if (sdlGame)
return 0; return 0;
+477 -128
View File
@@ -1,6 +1,7 @@
#ifndef _GNU_SOURCE #ifndef _GNU_SOURCE
#define _GNU_SOURCE #define _GNU_SOURCE
#include <libgen.h> #include <libgen.h>
#include <stdint.h>
#include <time.h> #include <time.h>
#endif #endif
@@ -11,7 +12,6 @@
#undef __x86_64__ #undef __x86_64__
#include <arpa/inet.h> #include <arpa/inet.h>
#include <dlfcn.h> #include <dlfcn.h>
#include <errno.h>
#include <link.h> #include <link.h>
#include <linux/sockios.h> #include <linux/sockios.h>
#include <math.h> #include <math.h>
@@ -30,8 +30,6 @@
#include <ifaddrs.h> #include <ifaddrs.h>
#include <dirent.h> #include <dirent.h>
#include "hook.h"
#include "baseboard.h" #include "baseboard.h"
#include "config.h" #include "config.h"
#include "driveboard.h" #include "driveboard.h"
@@ -47,7 +45,11 @@
#include "shader_patches.h" #include "shader_patches.h"
#include "fps_limiter.h" #include "fps_limiter.h"
#include "evdevinput.h" #include "evdevinput.h"
#include "card_reader.h"
#include "touchscreen.h"
#include "log.h" #include "log.h"
#include "resources/font.h"
#include "resources/logo.h"
#define HOOK_FILE_NAME "/dev/zero" #define HOOK_FILE_NAME "/dev/zero"
@@ -63,17 +65,28 @@
#define FILE_RW1 3 #define FILE_RW1 3
#define FILE_RW2 4 #define FILE_RW2 4
#define FILE_HARLEY 5 #define FILE_HARLEY 5
#define FILE_FONT_ABC 6
#define FILE_FONT_TGA 7
#define FILE_LOGO_TGA 8
#define ROUTE 9
int hooks[5] = {-1, -1, -1, -1, -1}; int hooks[5] = {-1, -1, -1, -1, -1};
FILE *fileHooks[6] = {NULL, NULL, NULL, NULL, NULL, NULL}; FILE *fileHooks[10] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
int fileRead[6] = {0, 0, 0, 0, 0, 0}; int fileRead[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
char envpath[100]; char envpath[100];
int fontABCidx = 0;
int fontTGAidx = 0;
int logoTGAidx = 0;
uint32_t elf_crc = 0; uint32_t elf_crc = 0;
uint32_t gId = 0;
extern int hummerExtremeShaderFileIndex; extern int hummerExtremeShaderFileIndex;
extern bool cachedShaderFilesLoaded; extern bool cachedShaderFilesLoaded;
extern char vf5StageNameAbbr[5]; extern char vf5StageNameAbbr[5];
bool phShowCursorInGame = false;
extern fps_limit fpsLimit; extern fps_limit fpsLimit;
Controllers controllers = {0}; Controllers controllers = {0};
@@ -93,7 +106,9 @@ static void handleSegfault(int signal, siginfo_t *info, void *ptr)
ucontext_t *ctx = ptr; ucontext_t *ctx = ptr;
// Get the address of the instruction causing the segfault // Get the address of the instruction causing the segfault
uint8_t *code = (uint8_t *)ctx->uc_mcontext.gregs[REG_EIP]; // uint8_t *code = (uint8_t *)ctx->uc_mcontext.gregs[REG_EIP];
greg_t eip_value = ctx->uc_mcontext.gregs[REG_EIP];
uint8_t *code = (uint8_t *)(uintptr_t)eip_value; // Use uintptr_t to ensure proper alignment
switch (*code) switch (*code)
{ {
@@ -162,9 +177,36 @@ static void handleSegfault(int signal, siginfo_t *info, void *ptr)
} }
} }
char *checkIDlike()
{
FILE *file = fopen("/etc/os-release", "r");
if (!file)
{
perror("Failed to open /etc/os-release");
return NULL;
}
char line[256];
char *result = NULL;
while (fgets(line, sizeof(line), file))
{
if (strncmp(line, "ID_LIKE=", 8) == 0)
{
char *id_like = strchr(line, '=');
if (id_like)
{
result = strdup(id_like);
break;
}
}
}
fclose(file);
return result;
}
void __attribute__((constructor)) hook_init() void __attribute__((constructor)) hook_init()
{ {
// Get offsets of the Game's ELF and calculate CRC32. // Get offsets of the Game's ELF and calculate CRC32.
dl_iterate_phdr(callback, NULL); dl_iterate_phdr(callback, NULL);
@@ -174,13 +216,27 @@ void __attribute__((constructor)) hook_init()
act.sa_flags = SA_SIGINFO; act.sa_flags = SA_SIGINFO;
sigaction(SIGSEGV, &act, NULL); sigaction(SIGSEGV, &act, NULL);
initConfig(); char *envPath = getenv("LINDBERGH_CONFIG_PATH");
initConfig(envPath);
gId = getConfig()->crc32;
char *id_like = checkIDlike();
if (id_like == NULL)
{
log_warn("Unable to get system info on current OS");
}
else if (strstr(id_like, "debian") == NULL)
{
log_warn("Seems like you're not in debian-like system. There might be unexpected issues.");
}
if (getConfig()->fpsLimiter == 1) if (getConfig()->fpsLimiter == 1)
{ {
fpsLimit.targetFrameTime = 1000000 / getConfig()->fpsTarget; fpsLimit.targetFrameTime = 1000000 / getConfig()->fpsTarget;
fpsLimit.frameEnd = Clock_now(); fpsLimit.frameEnd = Clock_now();
} }
getGPUVendor(); getGPUVendor();
if (initPatch() != 0) if (initPatch() != 0)
@@ -213,14 +269,18 @@ void __attribute__((constructor)) hook_init()
exit(1); exit(1);
} }
if (getConfig()->emulateCardreader)
{
if (initCardReader() != 0)
exit(1);
}
if (initInput() != 0) if (initInput() != 0)
exit(1); exit(1);
if (initControllers(&controllers) != 0) if (initControllers(&controllers) != 0)
exit(1); exit(1);
securityBoardSetDipResolution(getConfig()->width, getConfig()->height); securityBoardSetDipResolution(getConfig()->width, getConfig()->height);
printf("\nSEGA Lindbergh Emulator\nBy the Lindbergh Development Team 2025\n\n"); printf("\nSEGA Lindbergh Emulator\nBy the Lindbergh Development Team 2025\n\n");
@@ -238,21 +298,26 @@ void __attribute__((constructor)) hook_init()
} }
printf("\n"); printf("\n");
if (getConfig()->GPUVendor == ATI_GPU switch (gId)
&& ((getConfig()->crc32 == LETS_GO_JUNGLE) || (getConfig()->crc32 == LETS_GO_JUNGLE_REVA) ||
(getConfig()->crc32 == LETS_GO_JUNGLE_SPECIAL) || (getConfig()->crc32 == AFTER_BURNER_CLIMAX) ||
(getConfig()->crc32 == AFTER_BURNER_CLIMAX_REVA) || (getConfig()->crc32 == AFTER_BURNER_CLIMAX_REVB) ||
(getConfig()->crc32 == AFTER_BURNER_CLIMAX_SDX) || (getConfig()->crc32 == AFTER_BURNER_CLIMAX_SDX_REVA) ||
(getConfig()->crc32 == AFTER_BURNER_CLIMAX_SE) || (getConfig()->crc32 == AFTER_BURNER_CLIMAX_SE_REVA) ||
(getConfig()->crc32 == INITIALD_5_JAP_REVA) || (getConfig()->crc32 == INITIALD_5_JAP_REVF) ||
(getConfig()->crc32 == INITIALD_5_EXP_30) || (getConfig()->crc32 == INITIALD_5_EXP_40))) {
printf("WARNING: Game %s is unsupported in AMD GPU with ATI driver\n",getGameName());
}
if (getConfig()->lgjRenderWithMesa &&
((getConfig()->crc32 == LETS_GO_JUNGLE) || (getConfig()->crc32 == LETS_GO_JUNGLE_REVA) ||
(getConfig()->crc32 == LETS_GO_JUNGLE_SPECIAL)))
{ {
getConfig()->GPUVendor = AMD_GPU; case LETS_GO_JUNGLE:
case LETS_GO_JUNGLE_REVA:
case LETS_GO_JUNGLE_SPECIAL:
case AFTER_BURNER_CLIMAX:
case AFTER_BURNER_CLIMAX_REVA:
case AFTER_BURNER_CLIMAX_REVB:
case AFTER_BURNER_CLIMAX_SDX:
case AFTER_BURNER_CLIMAX_SDX_REVA:
case AFTER_BURNER_CLIMAX_SE:
case AFTER_BURNER_CLIMAX_SE_REVA:
case INITIALD_5_JAP_REVA:
case INITIALD_5_JAP_REVF:
case INITIALD_5_EXP_20:
case INITIALD_5_EXP_20A:
if (getConfig()->GPUVendor == ATI_GPU)
{
printf("WARNING: Game %s is unsupported in AMD GPU with ATI driver\n", getGameName());
}
} }
} }
@@ -260,10 +325,13 @@ DIR *opendir(const char *dirname)
{ {
DIR *(*_opendir)(const char *dirname) = dlsym(RTLD_NEXT, "opendir"); DIR *(*_opendir)(const char *dirname) = dlsym(RTLD_NEXT, "opendir");
int gId = getConfig()->crc32; switch (gId)
if (gId == INITIALD_5_EXP_30 || gId == INITIALD_5_EXP_40 || gId == INITIALD_5_JAP_REVA ||
gId == INITIALD_5_JAP_REVF)
{ {
case INITIALD_5_EXP:
case INITIALD_5_EXP_20:
case INITIALD_5_EXP_20A:
case INITIALD_5_JAP_REVA:
case INITIALD_5_JAP_REVF:
if (strcmp(dirname, "/tmp/") == 0) if (strcmp(dirname, "/tmp/") == 0)
{ {
return _opendir(dirname + 1); return _opendir(dirname + 1);
@@ -306,27 +374,40 @@ int open(const char *pathname, int flags, ...)
if (strcmp(pathname, "/dev/ttyS0") == 0 || strcmp(pathname, "/dev/tts/0") == 0) if (strcmp(pathname, "/dev/ttyS0") == 0 || strcmp(pathname, "/dev/tts/0") == 0)
{ {
if (getConfig()->emulateDriveboard == 0 && getConfig()->emulateRideboard == 0) if (getConfig()->emulateDriveboard == 0 && getConfig()->emulateRideboard == 0 && getConfig()->emulateCardreader == 0 &&
getConfig()->emulateTouchscreen == 0)
return _open(getConfig()->serial1Path, flags, mode); return _open(getConfig()->serial1Path, flags, mode);
if (hooks[SERIAL0] != -1) if (hooks[SERIAL0] != -1 && getConfig()->emulateCardreader && gId != R_TUNED)
return -1; {
return hooks[SERIAL0];
}
hooks[SERIAL0] = _open(HOOK_FILE_NAME, flags, mode); hooks[SERIAL0] = _open(HOOK_FILE_NAME, flags, mode);
log_warn("SERIAL0 Opened %d\n", hooks[SERIAL0]); printf("Warning: SERIAL0 Opened %d\n", hooks[SERIAL0]);
if (getConfig()->emulateCardreader == 1 && gId != R_TUNED)
cardReaderSetFd(0, hooks[SERIAL0], getConfig()->cardFile1);
return hooks[SERIAL0]; return hooks[SERIAL0];
} }
if (strcmp(pathname, "/dev/ttyS1") == 0 || strcmp(pathname, "/dev/tts/1") == 0) if (strcmp(pathname, "/dev/ttyS1") == 0 || strcmp(pathname, "/dev/tts/1") == 0)
{ {
if (getConfig()->emulateMotionboard == 0) if (getConfig()->emulateDriveboard == 0 && getConfig()->emulateMotionboard == 0 && getConfig()->emulateCardreader == 0)
return _open(getConfig()->serial2Path, flags, mode); return _open(getConfig()->serial2Path, flags, mode);
if (hooks[SERIAL1] != -1) if (hooks[SERIAL1] != -1 && getConfig()->emulateCardreader && gId != R_TUNED)
return -1; {
return hooks[SERIAL1];
}
hooks[SERIAL1] = _open(HOOK_FILE_NAME, flags, mode); hooks[SERIAL1] = _open(HOOK_FILE_NAME, flags, mode);
log_warn("SERIAL1 opened %d\n", hooks[SERIAL1]); log_warn("SERIAL1 opened %d\n", hooks[SERIAL1]);
if (getConfig()->emulateCardreader == 1)
cardReaderSetFd(1, hooks[SERIAL1], getConfig()->cardFile2);
return hooks[SERIAL1]; return hooks[SERIAL1];
} }
@@ -370,24 +451,70 @@ FILE *fopen(const char *restrict pathname, const char *restrict mode)
{ {
FILE *(*_fopen)(const char *restrict pathname, const char *restrict mode) = dlsym(RTLD_NEXT, "fopen"); FILE *(*_fopen)(const char *restrict pathname, const char *restrict mode) = dlsym(RTLD_NEXT, "fopen");
if (strcmp(pathname, "/proc/net/route") == 0)
{
return NULL;
}
if (strcmp(pathname, "/root/lindbergrc") == 0) if (strcmp(pathname, "/root/lindbergrc") == 0)
{ {
return _fopen("lindbergrc", mode); return _fopen("lindbergrc", mode);
} }
if ((strcmp(pathname, "/usr/lib/boot/logo.tga") == 0) || (strcmp(pathname, "/usr/lib/boot/logo.tga") == 0)) if ((strcmp(pathname, "/usr/lib/boot/logo.tga") == 0))
{ {
return _fopen("logo.tga", mode); if (!getConfig()->disableBuiltinLogos)
{
fileRead[FILE_LOGO_TGA] = 0;
fileHooks[FILE_LOGO_TGA] = _fopen(HOOK_FILE_NAME, mode);
return fileHooks[FILE_LOGO_TGA];
}
else
{
return _fopen("logo.tga", mode);
}
}
if (strcmp(pathname, "/usr/lib/boot/logo_red.tga") == 0)
{
if (!getConfig()->disableBuiltinLogos)
{
fileRead[FILE_LOGO_TGA] = 1;
fileHooks[FILE_LOGO_TGA] = _fopen(HOOK_FILE_NAME, mode);
return fileHooks[FILE_LOGO_TGA];
}
else
{
return _fopen("logo_red.tga", mode);
}
} }
if (strcmp(pathname, "/usr/lib/boot/LucidaConsole_12.tga") == 0) if (strcmp(pathname, "/usr/lib/boot/LucidaConsole_12.tga") == 0)
{ {
return _fopen("LucidaConsole_12.tga", mode); if (!getConfig()->disableBuiltinFont)
{
fileRead[FILE_FONT_TGA] = 0;
fileHooks[FILE_FONT_TGA] = _fopen(HOOK_FILE_NAME, mode);
return fileHooks[FILE_FONT_TGA];
}
else
{
return _fopen("LucidaConsole_12.tga", mode);
}
} }
if (strcmp(pathname, "/usr/lib/boot/LucidaConsole_12.abc") == 0) if (strcmp(pathname, "/usr/lib/boot/LucidaConsole_12.abc") == 0)
{ {
return _fopen("LucidaConsole_12.abc", mode); if (!getConfig()->disableBuiltinFont)
{
fileRead[FILE_FONT_ABC] = 0;
fileHooks[FILE_FONT_ABC] = _fopen(HOOK_FILE_NAME, mode);
return fileHooks[FILE_FONT_ABC];
}
else
{
return _fopen("LucidaConsole_12.abc", mode);
}
} }
if (strcmp(pathname, "/proc/cpuinfo") == 0) if (strcmp(pathname, "/proc/cpuinfo") == 0)
@@ -397,18 +524,32 @@ FILE *fopen(const char *restrict pathname, const char *restrict mode)
return fileHooks[CPUINFO]; return fileHooks[CPUINFO];
} }
if (strcmp(pathname, "/usr/lib/boot/logo_red.tga") == 0)
{
return _fopen("logo_red.tga", mode);
}
if (strcmp(pathname, "/usr/lib/boot/SEGA_KakuGothic-DB-Roman_12.tga") == 0) if (strcmp(pathname, "/usr/lib/boot/SEGA_KakuGothic-DB-Roman_12.tga") == 0)
{ {
return _fopen("SEGA_KakuGothic-DB-Roman_12.tga", mode); if (!getConfig()->disableBuiltinFont)
{
fileRead[FILE_FONT_TGA] = 0;
fileHooks[FILE_FONT_TGA] = _fopen(HOOK_FILE_NAME, mode);
return fileHooks[FILE_FONT_TGA];
}
else
{
return _fopen("SEGA_KakuGothic-DB-Roman_12.tga", mode);
}
} }
if (strcmp(pathname, "/usr/lib/boot/SEGA_KakuGothic-DB-Roman_12.abc") == 0) if (strcmp(pathname, "/usr/lib/boot/SEGA_KakuGothic-DB-Roman_12.abc") == 0)
{ {
return _fopen("SEGA_KakuGothic-DB-Roman_12.abc", mode); if (!getConfig()->disableBuiltinFont)
{
fileRead[FILE_FONT_ABC] = 0;
fileHooks[FILE_FONT_ABC] = _fopen(HOOK_FILE_NAME, mode);
return fileHooks[FILE_FONT_ABC];
}
else
{
return _fopen("SEGA_KakuGothic-DB-Roman_12.abc", mode);
}
} }
if (strcmp(pathname, "/proc/bus/pci/00/1f.0") == 0) if (strcmp(pathname, "/proc/bus/pci/00/1f.0") == 0)
@@ -437,13 +578,6 @@ FILE *fopen(const char *restrict pathname, const char *restrict mode)
return 0; return 0;
} }
if (strcmp("./../fs/data/cse_credit.bnk", pathname) == 0)
{
void *addr = __builtin_return_address(0);
fileHooks[FILE_HARLEY] = _fopen(pathname, mode);
return fileHooks[FILE_HARLEY];
}
if (cachedShaderFilesLoaded) if (cachedShaderFilesLoaded)
{ {
void *addr = __builtin_return_address(0); void *addr = __builtin_return_address(0);
@@ -476,16 +610,35 @@ FILE *fopen(const char *restrict pathname, const char *restrict mode)
} }
} }
int gId = getConfig()->crc32; switch (gId)
if (gId == INITIALD_5_EXP_30 || gId == INITIALD_5_EXP_40 || gId == INITIALD_5_JAP_REVA ||
gId == INITIALD_5_JAP_REVF)
{ {
case INITIALD_5_EXP:
case INITIALD_5_EXP_20:
case INITIALD_5_EXP_20A:
case INITIALD_5_JAP_REVA:
case INITIALD_5_JAP_REVF:
if (strncmp(pathname, "/tmp/", 5) == 0) if (strncmp(pathname, "/tmp/", 5) == 0)
{ {
return fopen(pathname + 1, mode); return fopen(pathname + 1, mode);
} }
} }
if (gId == PRIMEVAL_HUNT)
{
if (strstr(pathname, "/data/lua/texture/start_stage") != NULL)
phShowCursorInGame = true;
else if (strstr(pathname, "/data/texture/weapon_select/") != NULL)
phShowCursorInGame = false;
else if (strstr(pathname, "/data/texture/stage_select/") != NULL)
phShowCursorInGame = false;
else if (strstr(pathname, "/data/texture/name_entry/") != NULL)
phShowCursorInGame = false;
else if (strstr(pathname, "/data/texture/game_end/") != NULL)
phShowCursorInGame = false;
else if (strstr(pathname, "/data/lua/stage/bonus_0") != NULL)
phShowCursorInGame = true;
}
// printf("Path= %s\n", pathname); // printf("Path= %s\n", pathname);
return _fopen(pathname, mode); return _fopen(pathname, mode);
@@ -505,46 +658,85 @@ FILE *fopen64(const char *pathname, const char *mode)
if (strcmp(pathname, "/usr/lib/boot/logo_red.tga") == 0) if (strcmp(pathname, "/usr/lib/boot/logo_red.tga") == 0)
{ {
return _fopen64("logo_red.tga", mode); if (!getConfig()->disableBuiltinLogos)
{
fileRead[FILE_LOGO_TGA] = 1;
fileHooks[FILE_LOGO_TGA] = _fopen64(HOOK_FILE_NAME, mode);
return fileHooks[FILE_LOGO_TGA];
}
else
{
return _fopen64("logo_red.tga", mode);
}
} }
if (strcmp(pathname, "/usr/lib/boot/logo.tga") == 0) if (strcmp(pathname, "/usr/lib/boot/logo.tga") == 0)
{ {
return _fopen64("logo.tga", mode); if (!getConfig()->disableBuiltinLogos)
{
fileRead[FILE_LOGO_TGA] = 0;
fileHooks[FILE_LOGO_TGA] = _fopen64(HOOK_FILE_NAME, mode);
return fileHooks[FILE_LOGO_TGA];
}
else
{
return _fopen64("logo.tga", mode);
}
} }
if (strcmp(pathname, "/usr/lib/boot/SEGA_KakuGothic-DB-Roman_12.tga") == 0) if (strcmp(pathname, "/usr/lib/boot/SEGA_KakuGothic-DB-Roman_12.tga") == 0)
{ {
return _fopen64("SEGA_KakuGothic-DB-Roman_12.tga", mode); if (!getConfig()->disableBuiltinFont)
{
fileRead[FILE_FONT_TGA] = 0;
fileHooks[FILE_FONT_TGA] = _fopen64(HOOK_FILE_NAME, mode);
return fileHooks[FILE_FONT_TGA];
}
else
{
return _fopen64("SEGA_KakuGothic-DB-Roman_12.tga", mode);
}
} }
if (strcmp(pathname, "/usr/lib/boot/SEGA_KakuGothic-DB-Roman_12.abc") == 0) if (strcmp(pathname, "/usr/lib/boot/SEGA_KakuGothic-DB-Roman_12.abc") == 0)
{ {
return _fopen64("SEGA_KakuGothic-DB-Roman_12.abc", mode); if (!getConfig()->disableBuiltinFont)
{
fileRead[FILE_FONT_ABC] = 0;
fileHooks[FILE_FONT_ABC] = _fopen64(HOOK_FILE_NAME, mode);
return fileHooks[FILE_FONT_ABC];
}
else
{
return _fopen64("SEGA_KakuGothic-DB-Roman_12.abc", mode);
}
} }
if ((getConfig()->crc32 == HUMMER) || (getConfig()->crc32 == HUMMER_SDLX) || int idx;
(getConfig()->crc32 == HUMMER_EXTREME) || (getConfig()->crc32 == HUMMER_EXTREME_MDX)) switch (gId)
{ {
int idx; case HUMMER:
case HUMMER_SDLX:
case HUMMER_EXTREME:
case HUMMER_EXTREME_MDX:
if (shaderFileInList(pathname, &idx)) if (shaderFileInList(pathname, &idx))
{ {
hummerExtremeShaderFileIndex = idx; hummerExtremeShaderFileIndex = idx;
} }
} break;
case VIRTUA_FIGHTER_5_FINAL_SHOWDOWN_REVA:
if ((getConfig()->crc32 == VIRTUA_FIGHTER_5_FINAL_SHOWDOWN_REVA || getConfig()->crc32 == VIRTUA_FIGHTER_5_FINAL_SHOWDOWN_REVB || case VIRTUA_FIGHTER_5_FINAL_SHOWDOWN_REVB:
getConfig()->crc32 == VIRTUA_FIGHTER_5_FINAL_SHOWDOWN_REVB_6000) && case VIRTUA_FIGHTER_5_FINAL_SHOWDOWN_REVB_6000:
(getConfig()->GPUVendor != NVIDIA_GPU && getConfig()->GPUVendor != ATI_GPU)) if (getConfig()->GPUVendor != NVIDIA_GPU && getConfig()->GPUVendor != ATI_GPU)
{
char *filename = basename((char *)pathname);
if (strstr(filename, "light_") || strstr(filename, "glow_"))
{ {
printf("Stage: %s\n", filename); char *filename = basename((char *)pathname);
char *start = strchr(filename, '_') + 1; if (strstr(filename, "light_") || strstr(filename, "glow_"))
char *end = strstr(filename, ".txt"); {
strncpy(vf5StageNameAbbr, start, end - start); char *start = strchr(filename, '_') + 1;
vf5StageNameAbbr[end - start] = '\0'; char *end = strstr(filename, ".txt");
strncpy(vf5StageNameAbbr, start, end - start);
vf5StageNameAbbr[end - start] = '\0';
}
} }
} }
@@ -555,13 +747,19 @@ FILE *fopen64(const char *pathname, const char *mode)
int fclose(FILE *stream) int fclose(FILE *stream)
{ {
int (*_fclose)(FILE *stream) = dlsym(RTLD_NEXT, "fclose"); int (*_fclose)(FILE *stream) = dlsym(RTLD_NEXT, "fclose");
for (int i = 0; i < 7; i++) for (int i = 0; i < 9; i++)
{ {
if (fileHooks[i] == stream) if (fileHooks[i] == stream)
{ {
int r = _fclose(stream); int r = _fclose(stream);
fileHooks[i] = NULL; fileHooks[i] = NULL;
fileRead[i] = 0; fileRead[i] = 0;
if (stream == fileHooks[FILE_FONT_ABC])
fontABCidx = 0;
if (stream == fileHooks[FILE_FONT_TGA])
fontTGAidx = 0;
if (stream == fileHooks[FILE_LOGO_TGA])
logoTGAidx = 0;
return r; return r;
} }
} }
@@ -653,9 +851,24 @@ 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)
{
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 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)
{
phRead(fd, buf, count);
return 1;
}
return -1; return -1;
} }
@@ -688,9 +901,33 @@ 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]) // if (stream == fileHooks[FILE_HARLEY])
// {
// return harleyFreadReplace(buf, size, count, fileHooks[FILE_HARLEY]);
// }
if (stream == fileHooks[FILE_FONT_ABC])
{ {
return harleyFreadReplace(buf, size, count, fileHooks[FILE_HARLEY]); memcpy(buf, fontABC + fontABCidx, size * count);
fontABCidx += (size * count);
return size * count;
}
if (stream == fileHooks[FILE_FONT_TGA])
{
memcpy(buf, fontTGA + fontTGAidx, size * count);
fontTGAidx += (size * count);
return size * count;
}
if (stream == fileHooks[FILE_LOGO_TGA])
{
if (fileRead[FILE_LOGO_TGA] == 0)
memcpy(buf, logoLL + logoTGAidx, size * count);
else
memcpy(buf, logoLLRed + logoTGAidx, size * count);
logoTGAidx += (size * count);
return size * count;
} }
return _fread(buf, size, count, stream); return _fread(buf, size, count, stream);
@@ -709,9 +946,50 @@ long int ftell(FILE *stream)
return ftellGetShaderSize(fileRead[FILE_RW2]); return ftellGetShaderSize(fileRead[FILE_RW2]);
} }
if (stream == fileHooks[FILE_FONT_ABC])
{
return fontABClen;
}
return _ftell(stream); return _ftell(stream);
} }
int fseek(FILE *stream, long int offset, int whence)
{
int (*_fseek)(FILE *stream, long int offset, int whence) = dlsym(RTLD_NEXT, "fseek");
if (stream == fileHooks[FILE_FONT_ABC])
{
switch (whence)
{
case SEEK_CUR:
break;
case SEEK_SET:
fontABCidx = 0;
break;
case SEEK_END:
fontABCidx = fontABClen;
break;
}
return fontABCidx;
}
return _fseek(stream, offset, whence);
}
void rewind(FILE *stream)
{
void (*_rewind)(FILE *stream) = dlsym(RTLD_NEXT, "rewind");
if (stream == fileHooks[FILE_FONT_ABC])
{
fontABCidx = 0;
return;
}
_rewind(stream);
}
ssize_t write(int fd, const void *buf, size_t count) ssize_t write(int fd, const void *buf, size_t count)
{ {
int (*_write)(int fd, const void *buf, size_t count) = dlsym(RTLD_NEXT, "write"); int (*_write)(int fd, const void *buf, size_t count) = dlsym(RTLD_NEXT, "write");
@@ -728,9 +1006,25 @@ ssize_t write(int fd, const void *buf, size_t count)
if (fd == hooks[SERIAL0] && getConfig()->emulateDriveboard) if (fd == hooks[SERIAL0] && getConfig()->emulateDriveboard)
{ {
// printf("Write addr: %p\n", addr);
return driveboardWrite(fd, buf, count); return driveboardWrite(fd, buf, count);
} }
if (fd == hooks[SERIAL1] && getConfig()->emulateDriveboard && gId != R_TUNED)
{
return driveboardWrite(fd, buf, count);
}
if (fd == hooks[SERIAL0] && getConfig()->emulateCardreader)
{
return cardReaderWrite(fd, buf, count);
}
if (fd == hooks[SERIAL1] && getConfig()->emulateCardreader)
{
return cardReaderWrite(fd, buf, count);
}
return _write(fd, buf, count); return _write(fd, buf, count);
} }
@@ -738,15 +1032,6 @@ int ioctl(int fd, unsigned int request, void *data)
{ {
int (*_ioctl)(int fd, int request, void *data) = dlsym(RTLD_NEXT, "ioctl"); int (*_ioctl)(int fd, int request, void *data) = dlsym(RTLD_NEXT, "ioctl");
// Attempt to stop access to the ethernet ports
if ((request == SIOCSIFADDR) || (request == SIOCSIFFLAGS) || (request == SIOCSIFHWADDR) ||
(request == SIOCSIFHWBROADCAST) || (request == SIOCDELRT) || (request == SIOCADDRT) ||
(request == SIOCSIFNETMASK))
{
errno = ENXIO;
return -1;
}
if (fd == hooks[EEPROM]) if (fd == hooks[EEPROM])
{ {
if (request == 0xC04064A0) if (request == 0xC04064A0)
@@ -759,15 +1044,79 @@ int ioctl(int fd, unsigned int request, void *data)
return baseboardIoctl(fd, request, data); return baseboardIoctl(fd, request, data);
} }
// Just accept any IOCTL on serial ports and ignore it
if (fd == hooks[SERIAL0] || fd == hooks[SERIAL1]) if (fd == hooks[SERIAL0] || fd == hooks[SERIAL1])
{ {
if (request == 0x541b && gId == R_TUNED && fd == hooks[SERIAL1])
{
uint8_t d = 1;
memcpy(data, &d, sizeof(uint8_t));
}
return 0; return 0;
} }
return _ioctl(fd, request, data); return _ioctl(fd, request, data);
} }
int tcgetattr(int fd, struct termios *termios_p)
{
int (*_tcgetattr)(int fd, struct termios *termios_p) = dlsym(RTLD_NEXT, "tcgetattr");
if (fd == hooks[SERIAL0] && getConfig()->emulateDriveboard == 1)
return 0;
return _tcgetattr(fd, termios_p);
}
int tcsetattr(int fd, int optional_actions, const struct termios *termios_p)
{
int (*_tcsetattr)(int fd, int optional_actions, const struct termios *termios_p) = dlsym(RTLD_NEXT, "tcsetattr");
if (fd == hooks[SERIAL0] && getConfig()->emulateDriveboard == 1)
return 0;
return _tcsetattr(fd, optional_actions, termios_p);
}
speed_t cfgetispeed(const struct termios *termios_p)
{
speed_t (*_cfgetispeed)(const struct termios *termios_p) = dlsym(RTLD_NEXT, "cfgetispeed");
if (getConfig()->emulateDriveboard == 1)
return B9600;
return _cfgetispeed(termios_p);
}
speed_t cfgetospeed(const struct termios *termios_p)
{
speed_t (*_cfgetospeed)(const struct termios *termios_p) = dlsym(RTLD_NEXT, "cfgetospeed");
if (getConfig()->emulateDriveboard == 1)
return B9600;
return _cfgetospeed(termios_p);
}
int cfsetispeed(struct termios *termios_p, speed_t speed)
{
int (*_cfsetispeed)(struct termios *termios_p, speed_t speed) = dlsym(RTLD_NEXT, "cfsetispeed");
if (getConfig()->emulateDriveboard == 1)
return 0;
return _cfsetispeed(termios_p, speed);
}
int cfsetospeed(struct termios *termios_p, speed_t speed)
{
int (*_cfsetospeed)(struct termios *termios_p, speed_t speed) = dlsym(RTLD_NEXT, "cfsetospeed");
if (getConfig()->emulateDriveboard == 1)
return 0;
return _cfsetospeed(termios_p, speed);
}
int select(int nfds, fd_set *restrict readfds, fd_set *restrict writefds, fd_set *restrict exceptfds, int select(int nfds, fd_set *restrict readfds, fd_set *restrict writefds, fd_set *restrict exceptfds,
struct timeval *restrict timeout) struct timeval *restrict timeout)
{ {
@@ -784,6 +1133,11 @@ int select(int nfds, fd_set *restrict readfds, fd_set *restrict writefds, fd_set
return baseboardSelect(nfds, readfds, writefds, exceptfds, timeout); return baseboardSelect(nfds, readfds, writefds, exceptfds, timeout);
} }
if (getConfig()->emulateCardreader == 1 || getConfig()->emulateDriveboard == 1)
{
return 1;
}
return _select(nfds, readfds, writefds, exceptfds, timeout); return _select(nfds, readfds, writefds, exceptfds, timeout);
} }
@@ -818,6 +1172,9 @@ int system(const char *command)
if (strstr(command, "losetup") != NULL) if (strstr(command, "losetup") != NULL)
return 0; return 0;
if (strstr(command, "check_ip.sh") != NULL)
return 0;
return _system(command); return _system(command);
} }
@@ -925,28 +1282,6 @@ int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
return _connect(sockfd, addr, addrlen); return _connect(sockfd, addr, addrlen);
} }
/**
* Function to calculate CRC32 checksum in memory.
*/
uint32_t get_crc32(const char *s, size_t n)
{
uint32_t crc = 0xFFFFFFFF;
for (size_t i = 0; i < n; i++)
{
char ch = s[i];
for (size_t j = 0; j < 8; j++)
{
uint32_t b = (ch ^ crc) & 1;
crc >>= 1;
if (b)
crc = crc ^ 0xEDB88320;
ch >>= 1;
}
}
return ~crc;
}
/** /**
* Callback function to get the offset and size of the execution program in memory of the ELF we hook to. * Callback function to get the offset and size of the execution program in memory of the ELF we hook to.
*/ */
@@ -980,26 +1315,40 @@ int setenv(const char *name, const char *value, int overwrite)
char *getenv(const char *name) char *getenv(const char *name)
{ {
char *(*_getenv)(const char *name) = dlsym(RTLD_NEXT, "getenv"); char *(*_getenv)(const char *name) = dlsym(RTLD_NEXT, "getenv");
int gId = getConfig()->crc32;
if ((strcmp(name, "TEA_DIR") == 0) && if (strcmp(name, "TEA_DIR") == 0)
((gId == VIRTUA_TENNIS_3) || (gId == VIRTUA_TENNIS_3_TEST) || (gId == VIRTUA_TENNIS_3_REVA) ||
(gId == VIRTUA_TENNIS_3_REVA_TEST) || (gId == VIRTUA_TENNIS_3_REVB) || (gId == VIRTUA_TENNIS_3_REVB_TEST) ||
(gId == VIRTUA_TENNIS_3_REVC) || (gId == VIRTUA_TENNIS_3_REVC_TEST) || ((gId == RAMBO)) || (gId == TOO_SPICY)))
{ {
if (getcwd(envpath, 100) == NULL) switch (gId)
return ""; {
char *ptr = strrchr(envpath, '/'); case VIRTUA_TENNIS_3:
if (ptr == NULL) case VIRTUA_TENNIS_3_TEST:
return ""; case VIRTUA_TENNIS_3_REVA:
*ptr = '\0'; case VIRTUA_TENNIS_3_REVA_TEST:
return envpath; case VIRTUA_TENNIS_3_REVB:
} case VIRTUA_TENNIS_3_REVB_TEST:
else if (strcmp(name, "TEA_DIR") == 0) case VIRTUA_TENNIS_3_REVC:
{ case VIRTUA_TENNIS_3_REVC_TEST:
if (getcwd(envpath, 100) == NULL) case RAMBO:
return ""; case TOO_SPICY:
return envpath; {
if (getcwd(envpath, 100) == NULL)
return "";
char *ptr = strrchr(envpath, '/');
if (ptr == NULL)
return "";
*ptr = '\0';
return envpath;
}
break;
default:
{
if (getcwd(envpath, 100) == NULL)
return "";
return envpath;
}
}
} }
if (strcmp(name, "__GL_SYNC_TO_VBLANK") == 0) if (strcmp(name, "__GL_SYNC_TO_VBLANK") == 0)
{ {
return ""; return "";
@@ -1040,7 +1389,7 @@ struct tm *localtime_r(const time_t *timep, struct tm *result)
struct tm *(*_localtime_r)(const time_t *, struct tm *) = struct tm *(*_localtime_r)(const time_t *, struct tm *) =
(struct tm * (*)(const time_t *, struct tm *)) dlsym(RTLD_NEXT, "localtime_r"); (struct tm * (*)(const time_t *, struct tm *)) dlsym(RTLD_NEXT, "localtime_r");
if ((getConfig()->crc32 == MJ4_REVG || getConfig()->crc32 == MJ4_EVO) && getConfig()->mj4EnabledAtT == 1) if ((gId == MJ4_REVG || gId == MJ4_EVO) && getConfig()->mj4EnabledAtT == 1)
{ {
time_t target_time = 1735286445; time_t target_time = 1735286445;
struct tm *res = _localtime_r(&target_time, result); struct tm *res = _localtime_r(&target_time, result);
-4
View File
@@ -1,4 +0,0 @@
#include <stdint.h>
#include <stddef.h>
uint32_t get_crc32(const char *s, size_t n);
+227 -26
View File
@@ -1,11 +1,15 @@
#ifndef __i386__ #ifndef __i386__
#define __i386__ #define __i386__
#include "customcursor.h"
#endif #endif
#undef __x86_64__ #undef __x86_64__
#include <SDL2/SDL.h> #include <SDL2/SDL.h>
#include "jvs.h" #include "jvs.h"
#include "config.h" #include "config.h"
#include "customcursor.h"
#include "patch.h"
#include "touchscreen.h"
#include <GL/freeglut.h> #include <GL/freeglut.h>
#include <GL/glx.h> #include <GL/glx.h>
@@ -20,6 +24,12 @@
GameType gameType = SHOOTING; GameType gameType = SHOOTING;
int jvsAnalogueInBits = 10; int jvsAnalogueInBits = 10;
extern int phX, phY, phW, phH; extern int phX, phY, phW, phH;
extern int phX2, phY2, phW2, phH2;
int phIsDragging = 0;
extern void *customCursor;
extern void *phTouchCursor;
extern bool phShowCursorInGame;
int initInput() int initInput()
{ {
@@ -35,6 +45,105 @@ int initInput()
return 0; return 0;
} }
void phTouchScreenCursor(int mX, int mY, int *motX, int *motY)
{
if (getConfig()->emulateTouchscreen)
{
switch (getConfig()->phMode)
{
case 0:
case 2:
case 3:
if ((mX >= phX2 && mX <= (phX2 + phW2) && mY >= phY2 && mY <= (phY2 + phH2)) && getConfig()->hideCursor == 0)
{
setCursor(phTouchCursor);
showPhCursor();
}
else if (getConfig()->hideCursor == 1 || phShowCursorInGame == false)
{
hideCursor();
}
else if (phShowCursorInGame && getConfig()->hideCursor == 0)
{
setCursor(customCursor);
showCursor();
}
break;
case 4:
if ((mX >= phX2 && mX <= (phX2 + phW2) && mY >= (phY2 + phH) && mY <= (phY2 + (phH2 + phH))) && getConfig()->hideCursor == 0)
{
setCursor(phTouchCursor);
showPhCursor();
}
else if (getConfig()->hideCursor == 1 || phShowCursorInGame == false)
{
hideCursor();
}
else if (phShowCursorInGame && getConfig()->hideCursor == 0)
{
setCursor(customCursor);
showCursor();
}
}
}
if (mX < phX)
*motX = phX;
if (mX > (phW + phX))
*motX = (phW + phX) - 1;
if (mY > phH + phY)
*motY = (phH + phY) - 1;
if (mY < phY)
*motY = phY;
}
void phTouchClick(int mX, int mY, int type)
{
int x, y;
bool insideTouchScreen = false;
switch (getConfig()->phMode)
{
case 0:
case 2:
case 3:
if (mX >= phX2 && mX <= (phX2 + phW2) && mY >= phY2 && mY <= (phY2 + phH2))
{
x = mX - phW;
y = mY - phY2;
insideTouchScreen = true;
}
break;
case 4:
if (mX >= phX2 && mX <= (phX2 + phW2) && mY >= (phY2 + phH) && mY <= (phY2 + (phH2 + phH)))
{
x = mX - phX2;
y = mY - phH;
insideTouchScreen = true;
}
}
if (insideTouchScreen)
{
if (type == ButtonPress)
phCoordinates(x, y, phW2, phH2, ButtonPress);
else if (type == SDL_MOUSEBUTTONDOWN)
phCoordinates(x, y, phW2, phH2, SDL_MOUSEBUTTONDOWN);
else if (type == ButtonRelease)
phCoordinates(x, y, phW2, phH2, ButtonRelease);
else if (type == SDL_MOUSEBUTTONUP)
phCoordinates(x, y, phW2, phH2, SDL_MOUSEBUTTONUP);
else if (type == MotionNotify)
phCoordinates(x, y, phW2, phH2, MotionNotify);
else if (type == SDL_MOUSEMOTION)
phCoordinates(x, y, phW2, phH2, SDL_MOUSEMOTION);
}
else
{
if (getConfig()->noSDL)
setSwitch(PLAYER_1, BUTTON_1, type == ButtonPress);
else
setSwitch(PLAYER_1, BUTTON_1, type == SDL_MOUSEBUTTONDOWN);
}
}
/** /**
* Button mapping used for driving games * Button mapping used for driving games
*/ */
@@ -281,16 +390,15 @@ int XNextEventShooting(Display *display, XEvent *event_return, int returnValue)
{ {
int mX = event_return->xmotion.x; int mX = event_return->xmotion.x;
int mY = event_return->xmotion.y; int mY = event_return->xmotion.y;
if (mX < phX)
mX = phX; if (phIsDragging)
if (mX > (phW + phX)) phTouchClick(mX, mY, event_return->type);
mX = (phW + phX) - 1;
if (mY > phH + phY) int motX = mX, motY = mY;
mY = (phH + phY) - 1; phTouchScreenCursor(mX, mY, &motX, &motY);
if (mY < phY)
mY = phY; setAnalogue(ANALOGUE_1, ((double)(motX - phX) / (double)phW) * pow(2, jvsAnalogueInBits));
setAnalogue(ANALOGUE_1, ((double)(mX - phX) / (double)phW) * pow(2, jvsAnalogueInBits)); setAnalogue(ANALOGUE_2, ((double)(motY - phY) / (double)phH) * pow(2, jvsAnalogueInBits));
setAnalogue(ANALOGUE_2, ((double)(mY - phY) / (double)phH) * pow(2, jvsAnalogueInBits));
} }
else else
{ {
@@ -335,7 +443,17 @@ int XNextEventShooting(Display *display, XEvent *event_return, int returnValue)
{ {
if (event_return->xbutton.button == 1) // Trigger if (event_return->xbutton.button == 1) // Trigger
{ {
setSwitch(PLAYER_1, BUTTON_1, event_return->type == ButtonPress); if (getConfig()->crc32 == PRIMEVAL_HUNT && getConfig()->emulateTouchscreen)
{
int mX = event_return->xmotion.x;
int mY = event_return->xmotion.y;
phTouchClick(mX, mY, event_return->type);
phIsDragging = (event_return->type == ButtonPress ? 1 : 0);
}
else
{
setSwitch(PLAYER_1, BUTTON_1, event_return->type == ButtonPress);
}
} }
else if (event_return->xbutton.button == 3) // Reload else if (event_return->xbutton.button == 3) // Reload
{ {
@@ -451,6 +569,7 @@ void sdlEventDriving(SDL_Event *event)
break; break;
} }
} }
void sdlEventShooting(SDL_Event *event) void sdlEventShooting(SDL_Event *event)
{ {
KeyMapping keymap = getConfig()->keymap; KeyMapping keymap = getConfig()->keymap;
@@ -502,10 +621,13 @@ void sdlEventShooting(SDL_Event *event)
setSwitch(PLAYER_2, BUTTON_1, event->type == SDL_KEYDOWN); setSwitch(PLAYER_2, BUTTON_1, event->type == SDL_KEYDOWN);
else if (event->key.keysym.sym == SDLK_x) else if (event->key.keysym.sym == SDLK_x)
setSwitch(PLAYER_2, BUTTON_1, event->type == SDL_KEYDOWN); setSwitch(PLAYER_2, BUTTON_2, event->type == SDL_KEYDOWN);
else if (event->key.keysym.sym == SDLK_c) else if (event->key.keysym.sym == SDLK_c)
setSwitch(PLAYER_2, BUTTON_1, event->type == SDL_KEYDOWN); setSwitch(PLAYER_2, BUTTON_3, event->type == SDL_KEYDOWN);
else if (event->key.keysym.sym == SDLK_v)
setSwitch(PLAYER_2, BUTTON_4, event->type == SDL_KEYDOWN);
else if (event->key.keysym.sym == SDLK_u) else if (event->key.keysym.sym == SDLK_u)
setSwitch(PLAYER_2, BUTTON_UP, event->type == SDL_KEYDOWN); setSwitch(PLAYER_2, BUTTON_UP, event->type == SDL_KEYDOWN);
@@ -533,16 +655,15 @@ void sdlEventShooting(SDL_Event *event)
{ {
int mX = event->motion.x; int mX = event->motion.x;
int mY = event->motion.y; int mY = event->motion.y;
if (mX < phX)
mX = phX; if (phIsDragging)
if (mX > (phW + phX)) phTouchClick(mX, mY, event->type);
mX = (phW + phX) - 1;
if (mY > phH + phY) int motX = mX, motY = mY;
mY = (phH + phY) - 1; phTouchScreenCursor(mX, mY, &motX, &motY);
if (mY < phY)
mY = phY; setAnalogue(ANALOGUE_1, ((double)(motX - phX) / (double)phW) * pow(2, jvsAnalogueInBits));
setAnalogue(ANALOGUE_1, ((double)(mX - phX) / (double)phW) * pow(2, jvsAnalogueInBits)); setAnalogue(ANALOGUE_2, ((double)(motY - phY) / (double)phH) * pow(2, jvsAnalogueInBits));
setAnalogue(ANALOGUE_2, ((double)(mY - phY) / (double)phH) * pow(2, jvsAnalogueInBits));
} }
else else
{ {
@@ -585,13 +706,32 @@ void sdlEventShooting(SDL_Event *event)
case SDL_MOUSEBUTTONUP: case SDL_MOUSEBUTTONUP:
{ {
if (event->button.button == SDL_BUTTON_LEFT) // Trigger if (event->button.button == SDL_BUTTON_LEFT) // Trigger
setSwitch(PLAYER_1, BUTTON_1, event->type == SDL_MOUSEBUTTONDOWN); {
if (getConfig()->crc32 == PRIMEVAL_HUNT && getConfig()->emulateTouchscreen)
{
int mX = event->motion.x;
int mY = event->motion.y;
phTouchClick(mX, mY, event->type);
phIsDragging = (event->type == SDL_MOUSEBUTTONDOWN ? 1 : 0);
}
else
{
setSwitch(PLAYER_1, BUTTON_1, event->type == SDL_MOUSEBUTTONDOWN);
}
}
else if (event->button.button == SDL_BUTTON_RIGHT) // Reload else if (event->button.button == SDL_BUTTON_RIGHT) // Reload
{
if (getConfig()->crc32 == RAMBO || getConfig()->crc32 == TOO_SPICY)
{
setAnalogue(ANALOGUE_1, -1);
setAnalogue(ANALOGUE_2, -1);
}
setSwitch(PLAYER_1, BUTTON_2, event->type == SDL_MOUSEBUTTONDOWN); setSwitch(PLAYER_1, BUTTON_2, event->type == SDL_MOUSEBUTTONDOWN);
}
else if (event->button.button == SDL_BUTTON_MIDDLE) // Extra Gun Button else if (event->button.button == SDL_BUTTON_MIDDLE) // Extra Gun Button
{
setSwitch(PLAYER_1, BUTTON_3, event->type == SDL_MOUSEBUTTONDOWN); setSwitch(PLAYER_1, BUTTON_3, event->type == SDL_MOUSEBUTTONDOWN);
}
} }
break; break;
default: default:
@@ -654,6 +794,64 @@ void sdlEventABC(SDL_Event *event)
} }
} }
void sdlEventHarley(SDL_Event *event)
{
switch (event->type)
{
case SDL_KEYDOWN:
case SDL_KEYUP:
{
if (event->key.keysym.sym == SDLK_t)
setSwitch(SYSTEM, BUTTON_TEST, event->type == SDL_KEYDOWN);
else if (event->key.keysym.sym == SDLK_s)
setSwitch(PLAYER_1, BUTTON_SERVICE, event->type == SDL_KEYDOWN);
else if (event->key.keysym.sym == SDLK_5)
incrementCoin(PLAYER_1, event->type == SDL_KEYDOWN);
else if (event->key.keysym.sym == SDLK_1)
setSwitch(PLAYER_1, BUTTON_START, event->type == SDL_KEYDOWN);
else if (event->key.keysym.sym == SDLK_UP)
setAnalogue(ANALOGUE_1, event->type == SDL_KEYDOWN ? pow(2, jvsAnalogueInBits) - 1 : 0);
else if (event->key.keysym.sym == SDLK_DOWN)
setAnalogue(ANALOGUE_4, event->type == SDL_KEYDOWN ? pow(2, jvsAnalogueInBits) - 1 : 0);
else if (event->key.keysym.sym == SDLK_LEFT)
setAnalogue(ANALOGUE_2, event->type == SDL_KEYDOWN ? pow(2, jvsAnalogueInBits) * 0.2 : pow(2, jvsAnalogueInBits) * 0.5);
else if (event->key.keysym.sym == SDLK_RIGHT)
setAnalogue(ANALOGUE_2, event->type == SDL_KEYDOWN ? pow(2, jvsAnalogueInBits) * 0.8 : pow(2, jvsAnalogueInBits) * 0.5);
else if (event->key.keysym.sym == SDLK_q)
setSwitch(PLAYER_1, BUTTON_1, event->type == SDL_KEYDOWN);
else if (event->key.keysym.sym == SDLK_w)
setSwitch(PLAYER_1, BUTTON_2, event->type == SDL_KEYDOWN);
else if (event->key.keysym.sym == SDLK_e)
setSwitch(PLAYER_1, BUTTON_3, event->type == SDL_KEYDOWN);
else if (event->key.keysym.sym == SDLK_r)
setSwitch(PLAYER_1, BUTTON_4, event->type == SDL_KEYDOWN);
else if (event->key.keysym.sym == SDLK_z)
setSwitch(PLAYER_1, BUTTON_DOWN, event->type == SDL_KEYDOWN); // Hummer - SegaTV view change
else if (event->key.keysym.sym == SDLK_x)
setSwitch(PLAYER_1, BUTTON_UP, event->type == SDL_KEYDOWN);
else if (event->key.keysym.sym == SDLK_c)
setSwitch(PLAYER_1, BUTTON_LEFT, event->type == SDL_KEYDOWN);
else if (event->key.keysym.sym == SDLK_v)
setSwitch(PLAYER_1, BUTTON_RIGHT, event->type == SDL_KEYDOWN);
else if (event->key.keysym.sym == SDLK_a)
setSwitch(PLAYER_2, BUTTON_1, event->type == SDL_KEYDOWN); // SegaTV boost
else if (event->key.keysym.sym == SDLK_LCTRL)
setSwitch(PLAYER_2, BUTTON_DOWN, event->type == SDL_KEYDOWN); // Hummer boost
else if (event->key.keysym.sym == SDLK_SPACE)
setSwitch(PLAYER_2, BUTTON_UP, event->type == SDL_KEYDOWN);
}
break;
default:
break;
}
}
void sdlEventMahjong(SDL_Event *event) void sdlEventMahjong(SDL_Event *event)
{ {
switch (event->type) switch (event->type)
@@ -766,6 +964,9 @@ void handleSdlEvents(SDL_Event *event)
case ABC: case ABC:
sdlEventABC(event); sdlEventABC(event);
break; break;
case HARLEY:
sdlEventHarley(event);
break;
case MAHJONG: case MAHJONG:
sdlEventMahjong(event); sdlEventMahjong(event);
break; break;
+215 -9
View File
@@ -11,7 +11,9 @@
#define LD_LIBRARY_PATH "LD_LIBRARY_PATH" #define LD_LIBRARY_PATH "LD_LIBRARY_PATH"
#define LD_PRELOAD "LD_PRELOAD" #define LD_PRELOAD "LD_PRELOAD"
#define PRELOAD_FILE_NAME "lindbergh.so" #define PRELOAD_FILE_NAME "lindbergh.so"
#define PRELOAD_FILE_FLATPAK "/app/lib32/lindbergh.so"
#define TEAM "bobbydilley, retrofan, dkeruza-neo, doozer, francesco, rolel, caviar-x" #define TEAM "bobbydilley, retrofan, dkeruza-neo, doozer, francesco, rolel, caviar-x"
#define LINDBERGH_CONFIG_PATH "LINDBERGH_CONFIG_PATH"
uint32_t elf_crc = 0; uint32_t elf_crc = 0;
@@ -39,6 +41,153 @@ char *games[] = {"main.exe",
"a.elf", "a.elf",
"END"}; "END"};
/**
* An array containin clean games elf's CRC32
*/
uint32_t cleanElfCRC32[] = {
0x51C4D2F6, // DVP-0003A | hod4M.elf
0x1348BCA8, // DVP-0003A | hod4testM.elf
0x0AAE384E, // DVP-0003B | hod4M.elf
0x352AA797, // DVP-0003B | hod4testM.elf
0x42EED61A, // DVP-0003C | hod4M.elf
0x6DA6E511, // DVP-0003C | hod4testM.elf
0x0E4BF4B1, // DVP-0005 | vt3_Lindbergh
0x9E48AB5B, // DVP-0005 | vt3_testmode
0xE4C64D01, // DVP-0005A | vt3_Lindbergh
0x9C0E77E5, // DVP-0005A | vt3_testmode
0xA4BDB9E2, // DVP-0005B | vt3_Lindbergh
0x74E25472, // DVP-0005B | vt3_testmode
0x987AE3FF, // DVP-0005C | vt3_Lindbergh
0x1E4271A4, // DVP-0005C | vt3_testmode
0xD409B70C, // DVP-0008 | vf5
0x08EBC0DB, // DVP-0008A | vf5
0xA47FBA2D, // DVP-0008B | vf5
0x8CA46167, // DVP-0008C | vf5
0x75946796, // DVP-0008E | vf5
0x2C8F5D57, // DVP-0009 | abc
0x13D90755, // DVP-0009A | abc
0x633AD6FB, // DVP-0009B | abc
0xD39825A8, // DVP-0010 | hod4M.elf
0x0745CF0A, // DVP-0010 | hod4testM.elf
0x13E59583, // DVP-0010B | hod4M.elf
0x302FEB00, // DVP-0010B | hod4testM.elf
0x04E08C99, // DVP-0011 | lgj_final
0x0C3D3CC3, // DVP-0011A | lgj_final
0xD9660B2E, // DVP-0015 | JenTest
0x821C3404, // DVP-0015 | Jennifer
0x13AF8581, // DVP-0015A | JenTest
0xB2CE9B23, // DVP-0015A | Jennifer
0xCC32DEAE, // DVP-0018 | abc
0x17114BC1, // DVP-0018A | abc
0x22905D60, // DVP-0019A | id4.elf
0x43582D48, // DVP-0019B | id4.elf
0x2D2A18C1, // DVP-0019C | id4.elf
0x9BFD0D98, // DVP-0019D | id4.elf
0x9CF9BBCC, // DVP-0019G | id4.elf
0xFA0F6AB0, // DVP-0027A | apacheM.elf
0x5A7F315E, // DVP-0027A | apachetestM.elf
0x9D414D18, // DVP-0029A | vsg
0xC345E213, // DVP-0030B | id4.elf
0x98E6A516, // DVP-0030C | id4.elf
0xF67365C9, // DVP-0030D | id4.elf
0x8BDD31BA, // DVP-0031 | abc
0x3DF37873, // DVP-0031A | abc
0xDD8BB792, // DVP-0036A | lgjsp_app
0xB0A96E34, // DVP-0043 | vf5
0xF99E5635, // DVP-0044 | drive.elf
0x4143F6B4, // DVP-0048A | main.exe
0x653BC83B, // DVP-0057 | a.elf
0x04D88552, // DVP-0057B | a.elf
0x089D6051, // DVP-0060 | dsr
0x317F3B90, // DVP-0063 | hodexRI.elf
0x3A5EEC69, // DVP-0063 | hodextestR.elf
0x81E02850, // DVP-0069 | ramboM.elf
0xE4F202BB, // DVP-0070A | id5.elf
0x2E6732A3, // DVP-0070F | id5.elf
0xF99A3CDB, // DVP-0075 | id5.elf
0x05647A8E, // DVP-0079 | hummer_Master.elf
0x4442EA15, // DVP-0083 | hummer_Master.elf
0x8DF6BBF9, // DVP-0084 | id5.elf
0x2AF8004E, // DVP-0084A | id5.elf
0xB95528F4, // DVP-5004 | vf5
0x012E4898, // DVP-5004D | vf5
0x74465F9F, // DVP-5004G | vf5
0x75B48E22, // DVP-5007 | chopperM.elf
0xFCB9D941, // DVP-5019A | vf5
0xAB70901C, // DVP-5020 | vf5
0x6BAA510D, // DVP-5020 | vf5 | Ver 6.000
};
int cleanElfCRC32Count = sizeof(cleanElfCRC32) / sizeof(uint32_t);
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;
}
int lookupCrcTable(uint32_t crc)
{
for (int x = 0; x < cleanElfCRC32Count; x++)
{
if (cleanElfCRC32[x] == crc)
return 1;
}
return 0;
}
void isCleanElf(char *command)
{
const char *space_pos = strchr(command, ' ');
size_t length = space_pos ? (size_t)(space_pos - command) : strlen(command);
char elfName[256];
strncpy(elfName, command, length);
elfName[length] = '\0';
FILE *file = fopen(elfName, "rb");
if (!file)
{
log_error("Could not calculate the Elf CRC32.");
return;
}
uint32_t crc = 0xFFFFFFFF;
uint8_t buffer[4096];
size_t bytesRead;
while ((bytesRead = fread(buffer, 1, sizeof(buffer), file)) > 0)
{
for (size_t i = 0; i < bytesRead; i++)
{
crc = calcCrc32(crc, buffer[i]);
}
}
fclose(file);
crc = crc ^ 0xFFFFFFFF;
if (!lookupCrcTable(crc))
{
printf("\033[1;31m");
printf("Warning: The ELF you are running is not Clean and might cause unwanted behavior.\n");
printf(" Make sure you ELF and game dump are clean before reporting issues.\n");
printf(" If you are sure the ELF is clean, please report it to us.\n");
printf("\033[0m");
}
}
/** /**
* Tests if the game uses a seperate elf for test mode * Tests if the game uses a seperate elf for test mode
* and updates the command line to this elf. * and updates the command line to this elf.
@@ -68,7 +217,7 @@ void testModePath(char *name)
if (strcmp(name, "./apacheM.elf") == 0) if (strcmp(name, "./apacheM.elf") == 0)
{ {
strcpy(name, "./apacheTestM.elf"); strcpy(name, "./apachetestM.elf");
return; return;
} }
@@ -86,7 +235,7 @@ void testModePath(char *name)
* Makes sure the environment variables are set correctly * Makes sure the environment variables are set correctly
* to run the game. * to run the game.
*/ */
void setEnvironmentVariables() void setEnvironmentVariables(int isFlatpak, int zink, int nvidia)
{ {
// Ensure the library path is set correctly // Ensure the library path is set correctly
char libraryPath[128] = {0}; char libraryPath[128] = {0};
@@ -103,7 +252,19 @@ void setEnvironmentVariables()
setenv(LD_LIBRARY_PATH, libraryPath, 1); setenv(LD_LIBRARY_PATH, libraryPath, 1);
// Ensure the preload path is set correctly // Ensure the preload path is set correctly
setenv(LD_PRELOAD, PRELOAD_FILE_NAME, 1); if (!isFlatpak)
setenv(LD_PRELOAD, PRELOAD_FILE_NAME, 1);
else
setenv(LD_PRELOAD, PRELOAD_FILE_FLATPAK, 1);
if (zink)
setenv("MESA_LOADER_DRIVER_OVERRIDE", "zink", 1);
if (nvidia)
{
setenv("__GLX_VENDOR_LIBRARY_NAME", "nvidia", 1);
setenv("__NV_PRIME_RENDER_OFFLOAD", "1", 1);
}
} }
/** /**
@@ -115,10 +276,13 @@ void printUsage(char *argv[])
printf("Options:\n"); printf("Options:\n");
printf(" --test | -t Runs the test mode\n"); printf(" --test | -t Runs the test mode\n");
printf(" --segaboot | -s Runs segaboot\n"); printf(" --segaboot | -s Runs segaboot\n");
printf(" --zink | -z Runs with Zink\n");
printf(" --nvidia | -n Runs with nVidia GPU when is as a secondary GPU in a laptop\n");
printf(" --gdb Runs with GDB\n"); printf(" --gdb Runs with GDB\n");
printf(" --list-controllers Lists available controllers and inputs\n"); printf(" --list-controllers Lists available controllers and inputs\n");
printf(" --version Displays the version of the loader and team's names\n"); printf(" --version Displays the version of the loader and team's names\n");
printf(" --help Displays this usage text\n"); printf(" --help Displays this usage text\n");
printf(" --config | -c Specifies configuration path\n");
} }
/** /**
@@ -169,9 +333,6 @@ void printVersion() {
*/ */
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
// Ensure environment variables are set correctly
setEnvironmentVariables();
// Check for --version before directory operations // Check for --version before directory operations
if (argc > 1 && strcmp(argv[1], "--version") == 0) { if (argc > 1 && strcmp(argv[1], "--version") == 0) {
printVersion(); printVersion();
@@ -191,6 +352,7 @@ int main(int argc, char *argv[])
char *game = NULL; char *game = NULL;
int lindberghSharedObjectFound = 0; int lindberghSharedObjectFound = 0;
int isFlatpak = 0;
while ((ent = readdir(dir)) != NULL) while ((ent = readdir(dir)) != NULL)
{ {
@@ -238,18 +400,30 @@ int main(int argc, char *argv[])
if (!lindberghSharedObjectFound) if (!lindberghSharedObjectFound)
{ {
log_error("The preload object lindbergh.so was not found in this directory."); FILE *file = fopen(PRELOAD_FILE_FLATPAK, "r");
return EXIT_FAILURE; if (file)
{
fclose(file);
isFlatpak = 1;
}
else
{
log_error("The preload object lindbergh.so was not found in this directory.");
return EXIT_FAILURE;
}
} }
// Build up the command to start the game // Build up the command to start the game
int testMode = 0; int testMode = 0;
int gdb = 0; int gdb = 0;
int zink = 0;
int nvidia = 0;
int forceGame = 0; int forceGame = 0;
int segaboot = 0; int segaboot = 0;
char extConfigPath[PATH_MAX] = {0};
char forceGamePath[128] = {0}; char forceGamePath[128] = {0};
for (int i = 1; i < argc; i++) for (int i = 1; i < argc; i++)
{ {
if (strcmp(argv[i], "-t") == 0 || strcmp(argv[i], "--test") == 0) if (strcmp(argv[i], "-t") == 0 || strcmp(argv[i], "--test") == 0)
@@ -270,11 +444,36 @@ int main(int argc, char *argv[])
continue; continue;
} }
if (strcmp(argv[i], "-z") == 0 || strcmp(argv[i], "--zink") == 0)
{
zink = 1;
continue;
}
if (strcmp(argv[i], "-n") == 0 || strcmp(argv[i], "--nvidia") == 0)
{
nvidia = 1;
continue;
}
if (strcmp(argv[i], "-c") == 0 || strcmp(argv[i], "--config") == 0)
{
if (i + 1 >= argc)
{
break;
}
strncpy(extConfigPath, argv[i + 1], PATH_MAX);
i += 1;
continue;
}
// Treat the argument as the game name // Treat the argument as the game name
strcpy(forceGamePath, argv[i]); strcpy(forceGamePath, argv[i]);
forceGame = 1; forceGame = 1;
} }
// Ensure environment variables are set correctly
setEnvironmentVariables(isFlatpak, zink, nvidia);
char command[128] = {0}; char command[128] = {0};
strcpy(command, "./"); strcpy(command, "./");
if (forceGame) if (forceGame)
@@ -298,6 +497,8 @@ int main(int argc, char *argv[])
if (testMode) if (testMode)
testModePath(command); testModePath(command);
isCleanElf(command);
if (gdb) if (gdb)
{ {
char temp[128]; char temp[128];
@@ -306,6 +507,11 @@ int main(int argc, char *argv[])
strcpy(command, temp); strcpy(command, temp);
} }
if (extConfigPath[0] != '\0')
{
setenv(LINDBERGH_CONFIG_PATH, extConfigPath, 1);
}
log_info("Starting $ %s", command); log_info("Starting $ %s", command);
return system(command); return system(command);
-1
View File
@@ -4,7 +4,6 @@
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <time.h>
// Structure to hold the formatted message and its size // Structure to hold the formatted message and its size
+5 -2
View File
@@ -160,6 +160,10 @@ void *readJVSFrameThread(void * arg)
waitForEnd = 0; waitForEnd = 0;
do { do {
while(jvsFrameBuffer.ready == 1) {
usleep(10);
}
// printf("SERIAL thread debug: trying to read byte.\n"); // printf("SERIAL thread debug: trying to read byte.\n");
// Try to read a byte from serial, this call will be blocking if VMIN > 0 and VTIME = 0 // Try to read a byte from serial, this call will be blocking if VMIN > 0 and VTIME = 0
bytesRead = read(fd, &localBuffer[byteCount], 1); bytesRead = read(fd, &localBuffer[byteCount], 1);
@@ -237,14 +241,13 @@ int startJVSFrameThread(int * fd) {
* @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; memcpy(&frame, &jvsFrameBuffer, sizeof(JVSFrame));
// It has been red, we disable this frame // It has been red, we disable this frame
jvsFrameBuffer.ready = 0; jvsFrameBuffer.ready = 0;
} else { } else {
+2464 -2264
View File
File diff suppressed because it is too large Load Diff
+1732 -1179
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -11,6 +11,7 @@ size_t harleyFreadReplace(void *buf, size_t size, size_t count, FILE *stream);
void glTexCoord2fvABC1(const float *v); void glTexCoord2fvABC1(const float *v);
void glVertex3fABC1(float x, float y, float z); void glVertex3fABC1(float x, float y, float z);
void glVertex3fABC2(float x, float y, float z); void glVertex3fABC2(float x, float y, float z);
int isTestMode();
typedef struct typedef struct
{ {
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+90 -33
View File
@@ -1,6 +1,5 @@
#ifndef __i386__ #ifndef __i386__
#define __i386__ #define __i386__
#include <SDL2/SDL_video.h>
#endif #endif
#undef __x86_64__ #undef __x86_64__
#define GL_GLEXT_PROTOTYPES #define GL_GLEXT_PROTOTYPES
@@ -8,18 +7,30 @@
#include <stdbool.h> #include <stdbool.h>
#include <dlfcn.h> #include <dlfcn.h>
#include <SDL2/SDL.h> #include <SDL2/SDL.h>
#include <SDL2/SDL_syswm.h>
#include <X11/Xlib.h>
#include "config.h" #include "config.h"
#include "input.h" #include "input.h"
#include "sdlcalls.h" #include "sdlcalls.h"
#include "fps_limiter.h" #include "fps_limiter.h"
#include "customcursor.h"
bool SDLGame = false; extern uint32_t gId;
bool SDLWindowCreated = false;
extern bool GLUTGame;
SDL_Window *SDLwindow; SDL_Window *SDLwindow;
SDL_GLContext SDLcontext; SDL_GLContext SDLcontext;
Display *x11Display;
Window x11Window;
char SDLgameTitle[256] = {0}; char SDLgameTitle[256] = {0};
extern fps_limit fpsLimit; extern fps_limit fpsLimit;
extern void *customCursor;
extern void *phTouchCursor;
int glutInitialized = 0;
void GLAPIENTRY openglDebugCallback2(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, void GLAPIENTRY openglDebugCallback2(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length,
const GLchar *message, const void *userParam) const GLchar *message, const void *userParam)
{ {
@@ -40,31 +51,36 @@ void GLAPIENTRY openglDebugCallback2(GLenum source, GLenum type, GLuint id, GLen
} }
} }
void glutInitSDL(int *argcp, char **argv) void initSDL(int *argcp, char **argv)
{ {
int gId = getConfig()->crc32;
void FGAPIENTRY (*_glutInit)(int *argcp, char **argv) = dlsym(RTLD_NEXT, "glutInit"); void FGAPIENTRY (*_glutInit)(int *argcp, char **argv) = dlsym(RTLD_NEXT, "glutInit");
if (getConfig()->noSDL) switch (gId)
{ {
_glutInit(argcp, argv); case OUTRUN_2_SP_SDX_TEST:
return; case OUTRUN_2_SP_SDX_REVA_TEST:
} case OUTRUN_2_SP_SDX_REVA_TEST2:
// || gId == R_TUNED || gId == VIRTUA_FIGHTER_5_R || gId == VIRTUA_FIGHTER_5_R_REVD if (!glutInitialized)
if (gId == OUTRUN_2_SP_SDX_TEST || gId == OUTRUN_2_SP_SDX_REVA_TEST || gId == OUTRUN_2_SP_SDX_REVA_TEST2) {
{ glutInitialized = 1;
_glutInit(argcp, argv); _glutInit(argcp, argv);
return;
}
} }
if ((gId == AFTER_BURNER_CLIMAX) || (gId == AFTER_BURNER_CLIMAX_REVA) || (gId == AFTER_BURNER_CLIMAX_REVB) || switch (gId)
(gId == AFTER_BURNER_CLIMAX_SDX) || (gId == AFTER_BURNER_CLIMAX_SDX_REVA) || (gId == AFTER_BURNER_CLIMAX_SE) ||
(gId == AFTER_BURNER_CLIMAX_SE_REVA))
{ {
case AFTER_BURNER_CLIMAX:
case AFTER_BURNER_CLIMAX_REVA:
case AFTER_BURNER_CLIMAX_REVB:
case AFTER_BURNER_CLIMAX_SDX:
case AFTER_BURNER_CLIMAX_SDX_REVA:
case AFTER_BURNER_CLIMAX_SE:
case AFTER_BURNER_CLIMAX_SE_REVA:
setenv("SDL_VIDEODRIVER", "x11", 1); setenv("SDL_VIDEODRIVER", "x11", 1);
} }
SDLGame = true; SDLWindowCreated = true;
if (SDL_Init(SDL_INIT_VIDEO) < 0) if (SDL_Init(SDL_INIT_VIDEO) < 0)
{ {
@@ -75,14 +91,31 @@ void glutInitSDL(int *argcp, char **argv)
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); // Double buffering SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); // Double buffering
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 1); // 24-bit depth buffer SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 1); // 24-bit depth buffer
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); // Set the alpha size to 8 bits SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); // Set the alpha size to 8 bits
if (gId == AFTER_BURNER_CLIMAX || gId == AFTER_BURNER_CLIMAX_REVA || gId == AFTER_BURNER_CLIMAX_REVB || switch (gId)
gId == AFTER_BURNER_CLIMAX_SDX || gId == AFTER_BURNER_CLIMAX_SDX_REVA || gId == AFTER_BURNER_CLIMAX_SE ||
gId == AFTER_BURNER_CLIMAX_SE_REVA || gId == R_TUNED || gId == VIRTUA_FIGHTER_5 || gId == VIRTUA_FIGHTER_5_REVA ||
gId == VIRTUA_FIGHTER_5_REVB || gId == VIRTUA_FIGHTER_5_REVE || gId == VIRTUA_FIGHTER_5_EXPORT || gId == VIRTUA_FIGHTER_5_R ||
gId == VIRTUA_FIGHTER_5_R_REVD || gId == VIRTUA_FIGHTER_5_R_REVG || gId == VIRTUA_FIGHTER_5_FINAL_SHOWDOWN_REVA ||
gId == VIRTUA_FIGHTER_5_FINAL_SHOWDOWN_REVB || gId == VIRTUA_FIGHTER_5_FINAL_SHOWDOWN_REVB_6000 || gId == GHOST_SQUAD_EVOLUTION ||
gId == SEGA_RACE_TV || gId == MJ4_REVG || gId == MJ4_EVO)
{ {
case AFTER_BURNER_CLIMAX:
case AFTER_BURNER_CLIMAX_REVA:
case AFTER_BURNER_CLIMAX_REVB:
case AFTER_BURNER_CLIMAX_SDX:
case AFTER_BURNER_CLIMAX_SDX_REVA:
case AFTER_BURNER_CLIMAX_SE:
case AFTER_BURNER_CLIMAX_SE_REVA:
case R_TUNED:
case VIRTUA_FIGHTER_5:
case VIRTUA_FIGHTER_5_REVA:
case VIRTUA_FIGHTER_5_REVB:
case VIRTUA_FIGHTER_5_REVE:
case VIRTUA_FIGHTER_5_EXPORT:
case VIRTUA_FIGHTER_5_R:
case VIRTUA_FIGHTER_5_R_REVD:
case VIRTUA_FIGHTER_5_R_REVG:
case VIRTUA_FIGHTER_5_FINAL_SHOWDOWN_REVA:
case VIRTUA_FIGHTER_5_FINAL_SHOWDOWN_REVB:
case VIRTUA_FIGHTER_5_FINAL_SHOWDOWN_REVB_6000:
case GHOST_SQUAD_EVOLUTION:
case SEGA_RACE_TV:
case MJ4_REVG:
case MJ4_EVO:
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 1); SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 1);
} }
@@ -98,19 +131,43 @@ void glutInitSDL(int *argcp, char **argv)
exit(1); exit(1);
} }
SDLcontext = SDL_GL_CreateContext(SDLwindow); SDL_SysWMinfo info;
if (!SDLcontext) SDL_VERSION(&info.version);
if (SDL_GetWindowWMInfo(SDLwindow, &info))
{
if (info.subsystem == SDL_SYSWM_X11)
{ {
fprintf(stderr, "OpenGL context could not be created! SDL_Error: %s\n", SDL_GetError()); x11Display = info.info.x11.display;
exit(1); x11Window = info.info.x11.window;
} }
else
printf(" SDL RESOLUTION: %dx%d\n\n", getConfig()->width, getConfig()->height);
if (getConfig()->fullscreen)
{ {
SDL_SetWindowFullscreen(SDLwindow, SDL_WINDOW_FULLSCREEN); fprintf(stderr, "This program is not running on X11.\n");
} }
}
else
{
fprintf(stderr, "SDL_GetWindowWMInfo Error: %s\n", SDL_GetError());
}
SDLcontext = SDL_GL_CreateContext(SDLwindow);
if (!SDLcontext)
{
fprintf(stderr, "OpenGL context could not be created! SDL_Error: %s\n", SDL_GetError());
exit(1);
}
printf(" SDL RESOLUTION: %dx%d\n\n", getConfig()->width, getConfig()->height);
if (getConfig()->fullscreen)
{
SDL_SetWindowFullscreen(SDLwindow, SDL_WINDOW_FULLSCREEN);
}
loadCursors();
setCursor(customCursor);
if (getConfig()->hideCursor || gId == PRIMEVAL_HUNT)
SDL_ShowCursor(SDL_DISABLE);
} }
void sdlQuit() void sdlQuit()
+1 -1
View File
@@ -1,2 +1,2 @@
void glutInitSDL(int *argcp, char **argv); void initSDL(int *argcp, char **argv);
void pollEvents(); void pollEvents();
+5 -3
View File
@@ -1,7 +1,7 @@
#include <stdio.h> #include <stdio.h>
#include "securityboard.h"
#include "config.h" #include "config.h"
#include "securityboard.h"
#include "log.h" #include "log.h"
#define SECURITY_BOARD_FRONT_PANEL 0x38 #define SECURITY_BOARD_FRONT_PANEL 0x38
@@ -52,8 +52,10 @@ int securityBoardSetDipResolution(int width, int height)
setResolutionDips(1, 1, 0); setResolutionDips(1, 1, 0);
else if (width == 1360 && height == 768) else if (width == 1360 && height == 768)
setResolutionDips(1, 1, 1); setResolutionDips(1, 1, 1);
else else {
log_warn("Resolution not compatible, using 640 x 480\n"); if(getConfig()->showDebugMessages)
log_warn("Resolution not original, setting dips to 640 x 480.\n");
}
return 0; return 0;
} }
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+85
View File
@@ -0,0 +1,85 @@
#include <SDL2/SDL_events.h>
#include <X11/X.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <sys/types.h>
char phSendBuf[10];
bool phBufferFilled = false;
int phCommand = 1;
int phCommandByte = 0;
uint16_t coordX;
uint16_t coordY;
#define TOUCH_START 0x81
#define TOUCH_TOUCHING 0x82
#define TOUCH_END 0x84
void phCoordinates(int x, int y, int w, int h, int button)
{
coordX = (float)x / ((float)w * 0.0002441406);
coordY = (float)y / ((float)h * 0.0002441406);
memset(phSendBuf, 0, sizeof(phSendBuf));
if (button == SDL_MOUSEBUTTONDOWN || button == ButtonPress)
{
phSendBuf[2] = TOUCH_START;
phCommand = 1;
}
else if (button == SDL_MOUSEBUTTONUP || button == ButtonRelease)
{
phSendBuf[2] = TOUCH_END;
phCommand = 3;
}
else if (button == SDL_MOUSEMOTION || button == MotionNotify)
{
phSendBuf[2] = TOUCH_TOUCHING;
phCommand = 2;
}
phSendBuf[0] = 0x55;
phSendBuf[1] = 0x54;
phSendBuf[3] = (char)(coordX & 0xFF);
phSendBuf[4] = (char)((coordX >> 8) & 0xff);
phSendBuf[5] = (char)(coordY & 0xFF);
phSendBuf[6] = (char)((coordY >> 8) & 0xff);
phBufferFilled = true;
}
uint8_t phCalcChecksum()
{
int8_t checksum = -0x56;
for (int x = 0; x < 9;x++)
{
checksum += phSendBuf[x];
}
return (uint8_t)(checksum & 0xff);
}
ssize_t phRead(int fd, void *buf, size_t count)
{
if(!phBufferFilled)
return 0;
if(phCommandByte == 9)
{
switch (phCommand)
{
case 1:
phCommand = 2;
break;
case 2:
phSendBuf[2] = TOUCH_TOUCHING;
break;
case 3:
phBufferFilled = false;
}
phSendBuf[9] = phCalcChecksum();
}
memcpy(buf, &phSendBuf[phCommandByte], sizeof(char));
phCommandByte++;
if (phCommandByte == 10)
phCommandByte = 0;
return 1;
}
+9
View File
@@ -0,0 +1,9 @@
#ifndef TOUCHSCREEN_H
#define TOUCHSCREEN_H
#include <sys/types.h>
void phCoordinates(int x, int y, int w, int h, int button);
ssize_t phRead(int fd, void *buf, size_t count);
#endif
+106 -89
View File
@@ -4,7 +4,6 @@
#endif #endif
#undef __x86_64__ #undef __x86_64__
#include <GL/glx.h> #include <GL/glx.h>
#include <GL/freeglut.h>
#include <X11/Xatom.h> #include <X11/Xatom.h>
#include <X11/extensions/xf86vmode.h> #include <X11/extensions/xf86vmode.h>
#include <dlfcn.h> #include <dlfcn.h>
@@ -19,11 +18,22 @@
#include "config.h" #include "config.h"
#include "securityboard.h" #include "securityboard.h"
#include "fps_limiter.h" #include "fps_limiter.h"
#include "sdlcalls.h"
#include "customcursor.h"
extern bool SDLGame; extern bool SDLWindowCreated;
extern bool gettingGPUVendor; extern bool gettingGPUVendor;
extern bool GLUTGame;
Window win; bool creatingWindow = false;
Window window;
extern Display *x11Display;
extern Window x11Window;
extern void *customCursor;
extern void *phTouchCursor;
/** /**
* Stop the house of the dead games turning keyboard repeating off. * Stop the house of the dead games turning keyboard repeating off.
@@ -33,42 +43,61 @@ int XAutoRepeatOff(Display *display)
return 0; return 0;
} }
Window XCreateWindow(Display *display, Window parent, int x, int y, unsigned int width, unsigned int height, Display *XOpenDisplay(const char *display_name)
unsigned int border_width, int depth, unsigned int class, Visual *visual, unsigned long valueMask, {
XSetWindowAttributes *attributes) Display *(*_XOpenDisplay)(const char *display_name) = dlsym(RTLD_NEXT, "XOpenDisplay");
if (SDLWindowCreated || gettingGPUVendor || getConfig()->noSDL)
{
x11Display = _XOpenDisplay(display_name);
}
else
{
creatingWindow = true;
initSDL(0, 0);
creatingWindow = false;
}
return x11Display;
}
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)
{ {
Window (*_XCreateWindow)(Display *display, Window parent, int x, int y, unsigned int width, unsigned int height, 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 int border_width, int depth, unsigned int class, Visual *visual,
unsigned long valueMask, XSetWindowAttributes *attributes) = unsigned long valueMask, XSetWindowAttributes *attributes) =
dlsym(RTLD_NEXT, "XCreateWindow"); dlsym(RTLD_NEXT, "XCreateWindow");
if (SDLGame || gettingGPUVendor) if ((gettingGPUVendor || creatingWindow) || (GLUTGame && getConfig()->noSDL == 0))
{ {
Window window = _XCreateWindow(display, parent, x, y, width, height, border_width, depth, class, visual, window = _XCreateWindow(display, parent, x, y, width, height, border_width, depth, class, visual, valueMask, attributes);
valueMask, attributes);
return window;
} }
else if (getConfig()->noSDL)
width = getConfig()->width;
height = getConfig()->height;
// Ensure that the windows will respond with keyboard and mouse events
attributes->event_mask = attributes->event_mask | KeyPressMask | KeyReleaseMask | PointerMotionMask;
// attributes->override_redirect = False;
Window window =
_XCreateWindow(display, parent, x, y, width, height, border_width, depth, class, visual, valueMask, attributes);
printf(" X11 RESOLUTION: %dx%d\n\n", width, height);
if (getConfig()->fullscreen)
{ {
Atom wm_state = XInternAtom(display, "_NET_WM_STATE", true); width = getConfig()->width;
Atom wm_fullscreen = XInternAtom(display, "_NET_WM_STATE_FULLSCREEN", true); height = getConfig()->height;
XChangeProperty(display, window, wm_state, XA_ATOM, 32, PropModeReplace, (unsigned char *)&wm_fullscreen, 1);
attributes->event_mask = attributes->event_mask | KeyPressMask | KeyReleaseMask | PointerMotionMask;
window = _XCreateWindow(display, parent, x, y, width, height, border_width, depth, class, visual, valueMask, attributes);
printf(" X11 RESOLUTION: %dx%d\n\n", width, height);
if (getConfig()->fullscreen)
{
Atom wm_state = XInternAtom(display, "_NET_WM_STATE", true);
Atom wm_fullscreen = XInternAtom(display, "_NET_WM_STATE_FULLSCREEN", true);
XChangeProperty(display, window, wm_state, XA_ATOM, 32, PropModeReplace, (unsigned char *)&wm_fullscreen, 1);
}
x11Window = window;
loadCursors();
setCursor(customCursor);
if (getConfig()->hideCursor)
hideCursor();
}
else
{
window = x11Window;
} }
win = window;
return window; return window;
} }
@@ -78,10 +107,15 @@ int XGrabPointer(Display *display, Window grab_window, Bool owner_events, unsign
int (*_XGrabPointer)(Display *display, Window grab_window, Bool owner_events, unsigned int event_mask, 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 pointer_mode, int keyboard_mode, Window confine_to, Cursor cursor, Time time) =
dlsym(RTLD_NEXT, "XGrabPointer"); dlsym(RTLD_NEXT, "XGrabPointer");
int returnValue = _XGrabPointer(display, grab_window, owner_events, event_mask, pointer_mode, keyboard_mode,
confine_to, cursor, time); if (getConfig()->noSDL)
XUngrabPointer(display, time); {
return returnValue; int returnValue =
_XGrabPointer(display, grab_window, owner_events, event_mask, pointer_mode, keyboard_mode, confine_to, cursor, time);
XUngrabPointer(display, time);
return returnValue;
}
return _XGrabPointer(display, grab_window, owner_events, event_mask, pointer_mode, keyboard_mode, confine_to, cursor, time);
} }
int XGrabKeyboard(Display *display, Window grab_window, Bool owner_events, int pointer_mode, int keyboard_mode, int XGrabKeyboard(Display *display, Window grab_window, Bool owner_events, int pointer_mode, int keyboard_mode,
@@ -89,22 +123,27 @@ int XGrabKeyboard(Display *display, Window grab_window, Bool owner_events, int p
{ {
int (*_XGrabKeyboard)(Display *display, Window grab_window, Bool owner_events, int pointer_mode, int keyboard_mode, int (*_XGrabKeyboard)(Display *display, Window grab_window, Bool owner_events, int pointer_mode, int keyboard_mode,
Time time) = dlsym(RTLD_NEXT, "XGrabKeyboard"); Time time) = dlsym(RTLD_NEXT, "XGrabKeyboard");
int returnValue = _XGrabKeyboard(display, grab_window, owner_events, pointer_mode, keyboard_mode, time);
XUngrabKeyboard(display, time);
return returnValue;
}
int XDefineCursor(Display *display, Window w, Cursor cursor) if (getConfig()->noSDL)
{ {
return 0; int returnValue = _XGrabKeyboard(display, grab_window, owner_events, pointer_mode, keyboard_mode, time);
XUngrabKeyboard(display, time);
return returnValue;
}
return _XGrabKeyboard(display, grab_window, owner_events, pointer_mode, keyboard_mode, time);
} }
int XStoreName(Display *display, Window w, const char *window_name) int XStoreName(Display *display, Window w, const char *window_name)
{ {
int (*_XStoreName)(Display *display, Window w, const char *window_name) = dlsym(RTLD_NEXT, "XStoreName"); int (*_XStoreName)(Display *display, Window w, const char *window_name) = dlsym(RTLD_NEXT, "XStoreName");
char windowTitle[512];
sprintf(windowTitle, "%s - FPS: %.2f", getGameName(), calculateFps()); if (getConfig()->noSDL)
return _XStoreName(display, w, windowTitle); {
char windowTitle[512];
sprintf(windowTitle, "%s - FPS: %.2f", getGameName(), calculateFps());
return _XStoreName(display, w, windowTitle);
}
return _XStoreName(display, w, window_name);
} }
int XSetStandardProperties(Display *display, Window window, const char *window_name, const char *icon_name, int XSetStandardProperties(Display *display, Window window, const char *window_name, const char *icon_name,
@@ -113,9 +152,30 @@ int XSetStandardProperties(Display *display, Window window, const char *window_n
int (*_XSetStandardProperties)(Display *display, Window window, const char *window_name, const char *icon_name, int (*_XSetStandardProperties)(Display *display, Window window, const char *window_name, const char *icon_name,
Pixmap icon_pixmap, char **argv, int argc, XSizeHints *hints) = Pixmap icon_pixmap, char **argv, int argc, XSizeHints *hints) =
dlsym(RTLD_NEXT, "XSetStandardProperties"); dlsym(RTLD_NEXT, "XSetStandardProperties");
char gameTitle[256] = {0};
strcat(gameTitle, getGameName()); if (getConfig()->noSDL)
return _XSetStandardProperties(display, window, gameTitle, icon_name, icon_pixmap, argv, argc, hints); {
char gameTitle[256] = {0};
strcat(gameTitle, getGameName());
return _XSetStandardProperties(display, window, gameTitle, icon_name, icon_pixmap, argv, argc, hints);
}
return _XSetStandardProperties(display, window, window_name, icon_name, icon_pixmap, argv, argc, hints);
}
int XPending(Display *display)
{
int (*_XPending)(Display *display) = dlsym(RTLD_NEXT, "XPending");
if (SDLWindowCreated)
return 0;
return _XPending(display);
}
int XFlush(Display *display)
{
int (*_XFlush)(Display *display) = dlsym(RTLD_NEXT, "XFlush");
if (SDLWindowCreated)
return 0;
return _XFlush(display);
} }
Bool XF86VidModeSwitchToMode(Display *display, int screen, XF86VidModeModeInfo *modesinfo) Bool XF86VidModeSwitchToMode(Display *display, int screen, XF86VidModeModeInfo *modesinfo)
@@ -153,49 +213,6 @@ int XF86VidModeGetAllModeLines(Display *display, int screen, int *modecount_retu
return true; return true;
} }
int XPending(Display *display)
{
int (*_XPending)(Display *display) = dlsym(RTLD_NEXT, "XPending");
if (SDLGame)
return 0;
return _XPending(display);
}
Cursor XCreatePixmapCursor(Display *display, Pixmap source, Pixmap mask, XColor *fg, XColor *bg, unsigned int x,
unsigned int y)
{
int (*_XCreatePixmapCursor)(Display *display, Pixmap source, Pixmap mask, XColor *fg, XColor *bg, unsigned int x,
unsigned int y) = dlsym(RTLD_NEXT, "XCreatePixmapCursor");
if (SDLGame)
return 0;
return _XCreatePixmapCursor(display, source, mask, fg, bg, x, y);
}
int XFreePixmap(Display *display, Pixmap pixmap)
{
int (*_XFreePixmap)(Display *display, Pixmap pixmap) = dlsym(RTLD_NEXT, "XFreePixmap");
if (SDLGame)
return 0;
return _XFreePixmap(display, pixmap);
}
Pixmap XCreateBitmapFromData(Display *display, Drawable drawable, const char *data, unsigned int x, unsigned int y)
{
Pixmap (*_XCreateBitmapFromData)(Display *display, Drawable drawable, const char *data, unsigned int x,
unsigned int y) = dlsym(RTLD_NEXT, "XCreateBitmapFromData");
if (SDLGame)
return 0;
return _XCreateBitmapFromData(display, drawable, data, x, y);
}
int XFlush(Display *display)
{
int (*_XFlush)(Display *display) = dlsym(RTLD_NEXT, "XFlush");
if (SDLGame)
return 0;
return _XFlush(display);
}
typedef unsigned int uint; typedef unsigned int uint;
void glGenFencesNV(int n, uint *fences) void glGenFencesNV(int n, uint *fences)