forked from Ports/perfect_dark
Compare commits
138
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9625cd7d28 | ||
|
|
0e2de3b746 | ||
|
|
32417c164c | ||
|
|
1db33f278b | ||
|
|
abc6612641 | ||
|
|
57b1e37397 | ||
|
|
3f3c091289 | ||
|
|
41ddcc7822 | ||
|
|
6708bf2aa6 | ||
|
|
c16aa70a66 | ||
|
|
60c30e9b67 | ||
|
|
bc01ff558f | ||
|
|
8c844874e7 | ||
|
|
2e18ffdad9 | ||
|
|
b2ea9aa5f2 | ||
|
|
b9a51e4a62 | ||
|
|
b72d7f54e1 | ||
|
|
d8b21f78e0 | ||
|
|
0d0de5b0d4 | ||
|
|
7667d37ff0 | ||
|
|
cf7c4d4239 | ||
|
|
adcf56ed34 | ||
|
|
5e65e84210 | ||
|
|
63a9a26908 | ||
|
|
f4530633d6 | ||
|
|
94e244a236 | ||
|
|
92d3a9f564 | ||
|
|
44a67e60e8 | ||
|
|
634eecb35d | ||
|
|
a0db91a0c9 | ||
|
|
6b105d0be0 | ||
|
|
11febd7ace | ||
|
|
dface4696c | ||
|
|
0669ce5668 | ||
|
|
6d3ea5b0fd | ||
|
|
409e955883 | ||
|
|
f006f9ba7b | ||
|
|
6a03e8d9cf | ||
|
|
a1af5b655a | ||
|
|
edeafa596d | ||
|
|
b954e3ce80 | ||
|
|
bfa4035642 | ||
|
|
35be4d589e | ||
|
|
884a30f970 | ||
|
|
7288947390 | ||
|
|
c444e76ecb | ||
|
|
c4b1a8d4a2 | ||
|
|
7c8b1176c7 | ||
|
|
c5a088e7b8 | ||
|
|
8e443d4830 | ||
|
|
2cb52b749c | ||
|
|
de14f90daf | ||
|
|
9afc7e113e | ||
|
|
fbfe4b4564 | ||
|
|
4cb99506cb | ||
|
|
562e763fbd | ||
|
|
952de6e82b | ||
|
|
7ec54e6d0b | ||
|
|
e6df6014c7 | ||
|
|
e688a1c6e6 | ||
|
|
e44298d0c2 | ||
|
|
31cd8fc28a | ||
|
|
a46ce32ad4 | ||
|
|
31d8aae704 | ||
|
|
4b30f52b32 | ||
|
|
c8d42bbf20 | ||
|
|
511d6ca299 | ||
|
|
33f6d643be | ||
|
|
c2d09135f7 | ||
|
|
9f6b21e870 | ||
|
|
4eca4a1f07 | ||
|
|
4439fdf411 | ||
|
|
6ac8a1a0f6 | ||
|
|
f4ec781b8e | ||
|
|
5e256ea406 | ||
|
|
5abb0e484e | ||
|
|
16c247a24e | ||
|
|
0737c688d7 | ||
|
|
9de245eab6 | ||
|
|
a3cc54d33a | ||
|
|
a261246e64 | ||
|
|
2e195fe21a | ||
|
|
36a692991f | ||
|
|
ca0e3c3060 | ||
|
|
39474e97a7 | ||
|
|
b74cd095a1 | ||
|
|
96e1c57f61 | ||
|
|
f6ee8bbf71 | ||
|
|
188faeecf6 | ||
|
|
2c0a0a1337 | ||
|
|
7f92551d5a | ||
|
|
f54dbb596e | ||
|
|
aa3c5a85b7 | ||
|
|
f46e112c3d | ||
|
|
bcb5b3f5c1 | ||
|
|
65589e2fd2 | ||
|
|
54fbd8ba54 | ||
|
|
49129dd3e7 | ||
|
|
7bfa2b9425 | ||
|
|
53fbbb8a10 | ||
|
|
7bee9cdcfc | ||
|
|
928544ae5f | ||
|
|
312c752205 | ||
|
|
a5d1c25fea | ||
|
|
7abebe7405 | ||
|
|
ebc126f837 | ||
|
|
67bc9c4858 | ||
|
|
c4a3c18208 | ||
|
|
cf1b87a833 | ||
|
|
fb123603ca | ||
|
|
b3ab58da3b | ||
|
|
6374fc834c | ||
|
|
6df31649f5 | ||
|
|
9de6b580ba | ||
|
|
8eb6880694 | ||
|
|
fe4d86fae1 | ||
|
|
8492670bad | ||
|
|
04f95ed1d1 | ||
|
|
ee037c10ce | ||
|
|
cbf65e53b9 | ||
|
|
8c2b15d649 | ||
|
|
2134571b9a | ||
|
|
a541c79eda | ||
|
|
454086be6b | ||
|
|
6bd5997059 | ||
|
|
99911b2290 | ||
|
|
95d8b0692f | ||
|
|
e85cc3b309 | ||
|
|
2a01d562c3 | ||
|
|
51daf45c19 | ||
|
|
c9bd2bfd54 | ||
|
|
6225f62412 | ||
|
|
d2ffd73dea | ||
|
|
02329b64a1 | ||
|
|
aae0f70dd3 | ||
|
|
41d9cb4578 | ||
|
|
370047b1b0 | ||
|
|
6fc99e4c23 |
No files matched your search
@@ -1,32 +0,0 @@
|
||||
# EditorConfig is awesome: https://EditorConfig.org
|
||||
|
||||
# Top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
# Unix-style newlines with a newline ending every file
|
||||
[*]
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
|
||||
# Matches all C source files
|
||||
[*.c]
|
||||
indent_style = tab
|
||||
tab_width = 2
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
# Matches all header files
|
||||
[*.h]
|
||||
indent_style = tab
|
||||
tab_width = 2
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
# Matches Makefiles
|
||||
[Makefile]
|
||||
indent_style = tab
|
||||
|
||||
# Matches Markdown files
|
||||
[*.md]
|
||||
max_line_length = off
|
||||
trim_trailing_whitespace = false
|
||||
+14
-269
@@ -2,7 +2,7 @@ name: C/C++ CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "port" ]
|
||||
branches: [ "port", "port-net" ]
|
||||
pull_request:
|
||||
branches: [ "port" ]
|
||||
workflow_dispatch:
|
||||
@@ -25,299 +25,44 @@ jobs:
|
||||
mingw-w64-i686-toolchain
|
||||
mingw-w64-i686-SDL2
|
||||
mingw-w64-i686-zlib
|
||||
mingw-w64-i686-cmake
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
- name: Build pd.i686.exe
|
||||
run: cmake -G"Unix Makefiles" -Bbuild . && cmake --build build -j
|
||||
- name: Build pd.pal.i686.exe
|
||||
run: cmake -G"Unix Makefiles" -Bbuild_pal -DROMID=pal-final . && cmake --build build_pal -j
|
||||
- name: Build pd.jpn.i686.exe
|
||||
run: cmake -G"Unix Makefiles" -Bbuild_jpn -DROMID=jpn-final . && cmake --build build_jpn -j
|
||||
uses: actions/checkout@v3
|
||||
- name: Build pd.exe
|
||||
run: make -f Makefile.port -j
|
||||
- name: Prepare artifact for packaging
|
||||
run: |
|
||||
mkdir -p bin/data
|
||||
cp build/pd.i686.exe bin/
|
||||
cp build_pal/pd.pal.i686.exe bin/
|
||||
cp build_jpn/pd.jpn.i686.exe bin/
|
||||
cp build/ntsc-final-port/pd.exe bin/
|
||||
cp /mingw32/bin/{SDL2.dll,zlib1.dll,libgcc_s_dw2-1.dll,libwinpthread-1.dll} bin/
|
||||
touch bin/data/put_your_rom_here.txt
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: pd-i686-windows
|
||||
path: bin/
|
||||
retention-days: 0
|
||||
|
||||
build-i686-linux:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo dpkg --add-architecture i386
|
||||
sudo apt-get update
|
||||
sudo apt-get install git gcc g++ gcc-multilib g++-multilib make libsdl2-dev zlib1g-dev libsdl2-dev:i386 zlib1g-dev:i386 cmake
|
||||
sudo apt-get install git gcc g++ gcc-multilib g++-multilib make libsdl2-dev zlib1g-dev libsdl2-dev:i386 zlib1g-dev:i386
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
- name: Build pd.i686
|
||||
run: cmake -G"Unix Makefiles" -Bbuild -DCMAKE_C_FLAGS=-m32 -DCMAKE_CXX_FLAGS=-m32 . && cmake --build build -j
|
||||
- name: Build pd.pal.i686
|
||||
run: cmake -G"Unix Makefiles" -Bbuild_pal -DCMAKE_C_FLAGS=-m32 -DCMAKE_CXX_FLAGS=-m32 -DROMID=pal-final . && cmake --build build_pal -j
|
||||
- name: Build pd.jpn.i686
|
||||
run: cmake -G"Unix Makefiles" -Bbuild_jpn -DCMAKE_C_FLAGS=-m32 -DCMAKE_CXX_FLAGS=-m32 -DROMID=jpn-final . && cmake --build build_jpn -j
|
||||
uses: actions/checkout@v3
|
||||
- name: Build pd.exe
|
||||
run: make -f Makefile.port TARGET_PLATFORM=i686-linux -j2
|
||||
- name: Prepare artifact for packaging
|
||||
run: |
|
||||
mkdir -p bin/data
|
||||
cp build/pd.i686 bin/
|
||||
cp build_pal/pd.pal.i686 bin/
|
||||
cp build_jpn/pd.jpn.i686 bin/
|
||||
cp build/ntsc-final-port/pd.exe bin/pd
|
||||
touch bin/data/put_your_rom_here.txt
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: pd-i686-linux
|
||||
path: bin/
|
||||
retention-days: 0
|
||||
|
||||
build-x86_64-windows:
|
||||
runs-on: windows-latest
|
||||
defaults:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
steps:
|
||||
- name: Install MSYS2
|
||||
uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
msystem: MINGW64
|
||||
update: true
|
||||
install: >-
|
||||
git
|
||||
make
|
||||
mingw-w64-x86_64-toolchain
|
||||
mingw-w64-x86_64-python
|
||||
mingw-w64-x86_64-SDL2
|
||||
mingw-w64-x86_64-zlib
|
||||
mingw-w64-x86_64-cmake
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
- name: Build pd.x86_64.exe
|
||||
run: cmake -G"Unix Makefiles" -Bbuild . && cmake --build build -j
|
||||
- name: Build pd.pal.x86_64.exe
|
||||
run: cmake -G"Unix Makefiles" -Bbuild_pal -DROMID=pal-final . && cmake --build build_pal -j
|
||||
- name: Build pd.jpn.x86_64.exe
|
||||
run: cmake -G"Unix Makefiles" -Bbuild_jpn -DROMID=jpn-final . && cmake --build build_jpn -j
|
||||
- name: Prepare artifact for packaging
|
||||
run: |
|
||||
mkdir -p bin/data
|
||||
cp build/pd.x86_64.exe bin/
|
||||
cp build_pal/pd.pal.x86_64.exe bin/
|
||||
cp build_jpn/pd.jpn.x86_64.exe bin/
|
||||
cp /mingw64/bin/{SDL2.dll,zlib1.dll,libwinpthread-1.dll,libgcc_s_seh-1.dll} bin/
|
||||
touch bin/data/put_your_rom_here.txt
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: pd-x86_64-windows
|
||||
path: bin/
|
||||
retention-days: 0
|
||||
|
||||
build-x86_64-linux:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo dpkg --add-architecture amd64
|
||||
sudo apt-get update
|
||||
sudo apt-get install git gcc g++ gcc-multilib g++-multilib make libsdl2-dev zlib1g-dev libsdl2-2.0-0 cmake
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
- name: Build pd.x86_64
|
||||
run: cmake -G"Unix Makefiles" -Bbuild . && cmake --build build -j
|
||||
- name: Build pd.pal.x86_64
|
||||
run: cmake -G"Unix Makefiles" -Bbuild_pal -DROMID=pal-final . && cmake --build build_pal -j
|
||||
- name: Build pd.jpn.x86_64
|
||||
run: cmake -G"Unix Makefiles" -Bbuild_jpn -DROMID=jpn-final . && cmake --build build_jpn -j
|
||||
- name: Prepare artifact for packaging
|
||||
run: |
|
||||
mkdir -p bin/data
|
||||
cp build/pd.x86_64 bin/
|
||||
cp build_pal/pd.pal.x86_64 bin/
|
||||
cp build_jpn/pd.jpn.x86_64 bin/
|
||||
touch bin/data/put_your_rom_here.txt
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: pd-x86_64-linux
|
||||
path: bin/
|
||||
retention-days: 0
|
||||
|
||||
build-x86_64-osx:
|
||||
runs-on: macos-14
|
||||
steps:
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
brew install zlib
|
||||
wget http://libsdl.org/release/SDL2-2.30.9.dmg -O SDL2.dmg
|
||||
hdiutil mount SDL2.dmg
|
||||
sudo cp -vr /Volumes/SDL2/SDL2.framework /Library/Frameworks
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
- name: Build pd.x86_64
|
||||
run: |
|
||||
cmake -G"Unix Makefiles" -Bbuild -DCMAKE_OSX_ARCHITECTURES=x86_64 .
|
||||
cmake --build build --target pd -j4 --clean-first
|
||||
- name: Build pd.pal.x86_64
|
||||
run: |
|
||||
cmake -G"Unix Makefiles" -Bbuild_pal -DCMAKE_OSX_ARCHITECTURES=x86_64 -DROMID=pal-final .
|
||||
cmake --build build_pal --target pd -j4 --clean-first
|
||||
- name: Build pd.jpn.x86_64
|
||||
run: |
|
||||
cmake -G"Unix Makefiles" -Bbuild_jpn -DCMAKE_OSX_ARCHITECTURES=x86_64 -DROMID=jpn-final .
|
||||
cmake --build build_jpn --target pd -j4 --clean-first
|
||||
- name: Prepare artifact for packaging
|
||||
run: |
|
||||
mkdir -p bin/data
|
||||
cp build/pd.x86_64 bin/
|
||||
cp build_pal/pd.pal.x86_64 bin/
|
||||
cp build_jpn/pd.jpn.x86_64 bin/
|
||||
cp -vr /Library/Frameworks/SDL2.framework bin/
|
||||
touch bin/data/put_your_rom_here.txt
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: pd-x86_64-osx
|
||||
path: bin/
|
||||
retention-days: 0
|
||||
|
||||
build-arm64-osx:
|
||||
runs-on: macos-14
|
||||
steps:
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
brew install zlib
|
||||
wget http://libsdl.org/release/SDL2-2.30.9.dmg -O SDL2.dmg
|
||||
hdiutil mount SDL2.dmg
|
||||
sudo cp -vr /Volumes/SDL2/SDL2.framework /Library/Frameworks
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
- name: Build pd.arm64
|
||||
run: |
|
||||
cmake -G"Unix Makefiles" -Bbuild -DCMAKE_OSX_ARCHITECTURES=arm64 .
|
||||
cmake --build build --target pd -j4 --clean-first
|
||||
- name: Build pd.pal.arm64
|
||||
run: |
|
||||
cmake -G"Unix Makefiles" -Bbuild_pal -DCMAKE_OSX_ARCHITECTURES=arm64 -DROMID=pal-final .
|
||||
cmake --build build_pal --target pd -j4 --clean-first
|
||||
- name: Build pd.jpn.arm64
|
||||
run: |
|
||||
cmake -G"Unix Makefiles" -Bbuild_jpn -DCMAKE_OSX_ARCHITECTURES=arm64 -DROMID=jpn-final .
|
||||
cmake --build build_jpn --target pd -j4 --clean-first
|
||||
- name: Prepare artifact for packaging
|
||||
run: |
|
||||
mkdir -p bin/data
|
||||
cp build/pd.arm64 bin/
|
||||
cp build_pal/pd.pal.arm64 bin/
|
||||
cp build_jpn/pd.jpn.arm64 bin/
|
||||
cp -vr /Library/Frameworks/SDL2.framework bin/
|
||||
touch bin/data/put_your_rom_here.txt
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: pd-arm64-osx
|
||||
path: bin/
|
||||
retention-days: 0
|
||||
|
||||
build-arm64-nswitch:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.ref == 'refs/heads/port'
|
||||
steps:
|
||||
- name: Install host dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install git make cmake curl
|
||||
- name: Install devkitA64 docker image
|
||||
run: sudo docker pull devkitpro/devkita64:latest
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
- name: Build pd.arm64.nro
|
||||
run: sudo docker run --name pd --rm -v `pwd`:`pwd` -w `pwd` devkitpro/devkita64:latest bash ./tools/buildscripts/nswitch_docker.sh build
|
||||
- name: Build pd.pal.arm64.nro
|
||||
run: sudo docker run --name pd --rm -v `pwd`:`pwd` -w `pwd` devkitpro/devkita64:latest bash ./tools/buildscripts/nswitch_docker.sh build_pal -DROMID=pal-final
|
||||
- name: Build pd.jpn.arm64.nro
|
||||
run: sudo docker run --name pd --rm -v `pwd`:`pwd` -w `pwd` devkitpro/devkita64:latest bash ./tools/buildscripts/nswitch_docker.sh build_jpn -DROMID=jpn-final
|
||||
- name: Prepare artifact for packaging
|
||||
run: |
|
||||
mkdir -p bin/perfectdark/data
|
||||
mkdir -p bin/perfectdark_pal/data
|
||||
mkdir -p bin/perfectdark_jpn/data
|
||||
cp build/pd.arm64.nro bin/perfectdark/
|
||||
cp build_pal/pd.pal.arm64.nro bin/perfectdark_pal/
|
||||
cp build_jpn/pd.jpn.arm64.nro bin/perfectdark_jpn/
|
||||
touch bin/perfectdark/data/put_your_rom_here.txt
|
||||
touch bin/perfectdark_pal/data/put_your_rom_here.txt
|
||||
touch bin/perfectdark_jpn/data/put_your_rom_here.txt
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: pd-arm64-nswitch
|
||||
path: bin/
|
||||
retention-days: 0
|
||||
|
||||
build-flatpak-bundle:
|
||||
name: "Build flatpak bundle"
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build-x86_64-linux]
|
||||
container:
|
||||
image: ghcr.io/flathub-infra/flatpak-github-actions:freedesktop-25.08
|
||||
options: --privileged
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: pd-x86_64-linux
|
||||
path: dist/linux/bin/
|
||||
|
||||
- uses: flatpak/flatpak-github-actions/flatpak-builder@v6
|
||||
with:
|
||||
bundle: io.github.perfect_dark_pc_port.perfect_dark.flatpak
|
||||
manifest-path: dist/linux/io.github.perfect_dark_pc_port.perfect_dark.yaml
|
||||
cache-key: flatpak-builder-${{ github.sha }}
|
||||
upload-artifact: false
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: io.github.perfect_dark_pc_port.perfect_dark.flatpak
|
||||
path: io.github.perfect_dark_pc_port.perfect_dark.flatpak
|
||||
retention-days: 0
|
||||
|
||||
|
||||
publish-latest-build:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.ref == 'refs/heads/port'
|
||||
needs: [build-i686-windows, build-i686-linux, build-x86_64-windows, build-x86_64-linux, build-arm64-nswitch, build-x86_64-osx, build-arm64-osx, build-flatpak-bundle]
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: ci-artifacts
|
||||
- name: Publish latest dev-build
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
mkdir ci-release
|
||||
pushd ci-artifacts
|
||||
tar czf ../ci-release/pd-i686-linux.tar.gz pd-i686-linux
|
||||
tar czf ../ci-release/pd-x86_64-linux.tar.gz pd-x86_64-linux
|
||||
tar cJf ../ci-release/pd-x86_64-osx.tar.xz pd-x86_64-osx
|
||||
tar cJf ../ci-release/pd-arm64-osx.tar.xz pd-arm64-osx
|
||||
zip -r ../ci-release/pd-i686-windows.zip pd-i686-windows
|
||||
zip -r ../ci-release/pd-x86_64-windows.zip pd-x86_64-windows
|
||||
zip -r ../ci-release/pd-arm64-nswitch.zip pd-arm64-nswitch
|
||||
mv io.github.perfect_dark_pc_port.perfect_dark.flatpak/io.github.perfect_dark_pc_port.perfect_dark.flatpak ../ci-release/
|
||||
popd
|
||||
git tag --force ci-dev-build port
|
||||
git push --force origin ci-dev-build
|
||||
gh release upload --clobber ci-dev-build ci-release/*
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
*.exe
|
||||
pd.*.z64
|
||||
build
|
||||
.flatpak-builder
|
||||
extracted
|
||||
src/assets/*/*.bin
|
||||
src/assets/*/*.ctl
|
||||
@@ -23,6 +22,3 @@ src/assets/*/textures/*.bin
|
||||
src/generated
|
||||
tools/mkrom/mkrom
|
||||
/.vs
|
||||
CppProperties.json
|
||||
.idea
|
||||
cmake-build-debug
|
||||
-360
@@ -1,360 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
|
||||
|
||||
if(APPLE)
|
||||
if(CMAKE_OSX_ARCHITECTURES MATCHES "arm64")
|
||||
# ARM Macs start at OS 11.
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "11.0" CACHE STRING "Minimum OS X deployment version")
|
||||
else()
|
||||
# SDL2 requires at least this version for everything to work properly.
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.9" CACHE STRING "Minimum OS X deployment version")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
project(pd C CXX)
|
||||
|
||||
include(TargetArch)
|
||||
include(FindPkgConfig)
|
||||
include(AssetUtils)
|
||||
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_C_EXTENSIONS OFF)
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
|
||||
# On first build set the build type to RelWithDebInfo if it's not already set
|
||||
if (NOT EXISTS ${CMAKE_BINARY_DIR}/CMakeCache.txt)
|
||||
if (NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING "" FORCE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Options
|
||||
|
||||
set(ROMID "ntsc-final" CACHE STRING "Which ROM to build an executable for: ntsc-final, pal-final or jpn-final")
|
||||
option(FORCE_CROSSCOMPILE "Force cross compiling" NO)
|
||||
|
||||
# Determine target arch
|
||||
|
||||
target_architecture(TARGET_ARCH)
|
||||
if(TARGET_ARCH STREQUAL "i386")
|
||||
# for historical reasons
|
||||
set(TARGET_ARCH "i686")
|
||||
endif()
|
||||
|
||||
# TODO
|
||||
set(TARGET_IS_BIG_ENDIAN FALSE)
|
||||
|
||||
if((TARGET_ARCH MATCHES "unknown") OR (TARGET_ARCH STREQUAL ""))
|
||||
message(FATAL_ERROR "Unknown target arch")
|
||||
elseif(TARGET_ARCH MATCHES "64")
|
||||
set(TARGET_IS_64BIT TRUE)
|
||||
else()
|
||||
set(TARGET_IS_64BIT FALSE)
|
||||
endif()
|
||||
|
||||
message(STATUS "Target arch: ${TARGET_ARCH}")
|
||||
|
||||
# Determine target OS and platform identifier ($arch-$os)
|
||||
|
||||
if(WIN32)
|
||||
# Windows
|
||||
set(TARGET_OS "windows")
|
||||
elseif(APPLE)
|
||||
# OSX
|
||||
set(TARGET_OS "osx")
|
||||
elseif(NINTENDO_SWITCH)
|
||||
# Switch
|
||||
set(TARGET_OS "nswitch")
|
||||
elseif(UNIX)
|
||||
# Generic *nix; assume Linux
|
||||
set(TARGET_OS "linux")
|
||||
else()
|
||||
# ???
|
||||
message(FATAL_ERROR "Unknown target OS or compiler")
|
||||
endif()
|
||||
|
||||
set(TARGET_PLATFORM "${TARGET_ARCH}-${TARGET_OS}")
|
||||
|
||||
message(STATUS "Target platform: ${TARGET_PLATFORM}")
|
||||
|
||||
# Calculate version info and binary name
|
||||
|
||||
set(VERSION_IS_PAL 0)
|
||||
|
||||
if(ROMID STREQUAL "ntsc-final")
|
||||
set(VERSION 2)
|
||||
set(BIN_REGION "")
|
||||
elseif(ROMID STREQUAL "pal-final")
|
||||
set(VERSION 4)
|
||||
set(BIN_REGION ".pal")
|
||||
set(VERSION_IS_PAL 1)
|
||||
elseif(ROMID STREQUAL "jpn-final")
|
||||
set(VERSION 5)
|
||||
set(BIN_REGION ".jpn")
|
||||
else()
|
||||
message(FATAL_ERROR "Unknown ROM ID: ${ROMID}")
|
||||
endif()
|
||||
|
||||
# git commit hash
|
||||
execute_process(
|
||||
COMMAND git rev-parse --short HEAD
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE VERSION_HASH
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
# git branch name
|
||||
execute_process(
|
||||
COMMAND git rev-parse --abbrev-ref HEAD
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE VERSION_BRANCH
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
set(VERSION_TARGET "${TARGET_PLATFORM}")
|
||||
set(VERSION_ARCH "${TARGET_ARCH}")
|
||||
set(VERSION_ROMID "${ROMID}")
|
||||
set(VERSION_BUILD "${CMAKE_BUILD_TYPE}")
|
||||
|
||||
if((VERSION_BRANCH STREQUAL "") OR (VERSION_BRANCH STREQUAL "HEAD"))
|
||||
set(VERSION_BRANCH "port-custom")
|
||||
endif()
|
||||
|
||||
message(STATUS "Version: ${VERSION_ROMID}, hash ${VERSION_HASH}, branch ${VERSION_BRANCH}")
|
||||
|
||||
configure_file("${CMAKE_SOURCE_DIR}/port/include/versioninfo.h.in" "${CMAKE_BINARY_DIR}/port/include/versioninfo.h" @ONLY)
|
||||
|
||||
set(ASSET_DIR "src/assets/${ROMID}")
|
||||
set(GENERATED_DIR "src/generated/${ROMID}")
|
||||
|
||||
set(ENV{ROMID} ${ROMID})
|
||||
|
||||
# Build folder postfix
|
||||
|
||||
set(BUILD_ID "${VERSION_ROMID}-${VERSION_TARGET}")
|
||||
|
||||
# Compiler defs
|
||||
|
||||
add_definitions(
|
||||
-DMATCHING=0
|
||||
-DPIRACYCHECKS=0
|
||||
-DROM_SIZE=32
|
||||
-DAVOID_UB=1
|
||||
-D_LANGUAGE_C=1
|
||||
-DPAL=${VERSION_IS_PAL}
|
||||
-DVERSION=${VERSION}
|
||||
)
|
||||
|
||||
if(TARGET_IS_64BIT)
|
||||
add_definitions(-DPLATFORM_64BIT=1)
|
||||
endif()
|
||||
|
||||
# Compiler flags
|
||||
|
||||
# Include directories
|
||||
include_directories("${CMAKE_SOURCE_DIR}/include")
|
||||
include_directories("${CMAKE_SOURCE_DIR}/include/PR")
|
||||
include_directories("${CMAKE_SOURCE_DIR}/src/include")
|
||||
include_directories("${CMAKE_BINARY_DIR}/src/generated/${ROMID}")
|
||||
include_directories("${CMAKE_SOURCE_DIR}/src/lib/ultra/audio")
|
||||
include_directories("${CMAKE_SOURCE_DIR}/port/include")
|
||||
include_directories("${CMAKE_BINARY_DIR}/port/include")
|
||||
|
||||
# Set Release optimization to -Og until I fix the -O2 issues
|
||||
if(NOT (CMAKE_BUILD_TYPE STREQUAL "Debug"))
|
||||
add_compile_options(-Og)
|
||||
endif()
|
||||
|
||||
# Common CFLAGS
|
||||
add_compile_options(
|
||||
-fno-inline-functions
|
||||
-fno-strict-aliasing
|
||||
-funsigned-char
|
||||
-fwrapv
|
||||
-include "versioninfo.h"
|
||||
)
|
||||
|
||||
# Common warning flags
|
||||
add_compile_options(
|
||||
-Wall
|
||||
-Wno-address
|
||||
-Wno-int-in-bool-context
|
||||
-Wno-misleading-indentation
|
||||
-Wno-missing-braces
|
||||
-Wno-multichar
|
||||
-Wno-tautological-compare
|
||||
-Wno-unused-but-set-variable
|
||||
-Wno-unused-value
|
||||
-Wno-unused-variable
|
||||
-fdiagnostics-color=always
|
||||
)
|
||||
|
||||
# C specific flags
|
||||
add_compile_options($<$<COMPILE_LANGUAGE:C>:-Wno-pointer-sign>)
|
||||
|
||||
# C++ specific flags
|
||||
add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-Wno-unused-function>)
|
||||
|
||||
# Platform-specific flags
|
||||
if (APPLE)
|
||||
# Make it look for libs in the executable folder manually since CMake's rpath system is wack
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -rpath @executable_path")
|
||||
else()
|
||||
# This warning is not recognized by XCode/Clang for some reason.
|
||||
add_compile_options(-Wno-format-truncation)
|
||||
endif()
|
||||
|
||||
# Dependencies
|
||||
|
||||
set(LIBS )
|
||||
|
||||
# SDL2
|
||||
find_package(SDL2 REQUIRED)
|
||||
if(NINTENDO_SWITCH)
|
||||
if(NOT SDL2_LIBRARY OR NOT SDL2_INCLUDE_DIR)
|
||||
# sometimes FindSDL2 just wants us to suffer and does not set these
|
||||
set(SDL2_LIBRARY "SDL2")
|
||||
set(SDL2_INCLUDE_DIR "${DEVKITPRO}/portlibs/switch/include/SDL2")
|
||||
endif()
|
||||
endif()
|
||||
include_directories(SYSTEM "${SDL2_INCLUDE_DIR}")
|
||||
list(APPEND LIBS "${SDL2_LIBRARY}")
|
||||
|
||||
# ZLib
|
||||
find_package(ZLIB REQUIRED)
|
||||
if(ZLIB_INCLUDE_DIR)
|
||||
include_directories(SYSTEM "${ZLIB_INCLUDE_DIR}")
|
||||
endif()
|
||||
list(APPEND LIBS "${ZLIB_LIBRARY}")
|
||||
|
||||
# GL
|
||||
if(NOT GL_LIBRARY)
|
||||
if(WIN32)
|
||||
set(GL_LIBRARY opengl32)
|
||||
elseif(NINTENDO_SWITCH)
|
||||
set(GL_LIBRARY EGL glapi drm_nouveau)
|
||||
elseif(APPLE)
|
||||
set(GL_LIBRARY "-framework OpenGL")
|
||||
else()
|
||||
set(GL_LIBRARY GL)
|
||||
endif()
|
||||
endif()
|
||||
list(APPEND LIBS "${GL_LIBRARY}")
|
||||
|
||||
# Platform-specific extra libs
|
||||
if(NOT EXTRA_LIBRARIES)
|
||||
if(WIN32)
|
||||
set(EXTRA_LIBRARIES dbghelp -static-libstdc++)
|
||||
elseif(NINTENDO_SWITCH)
|
||||
set(EXTRA_LIBRARIES stdc++ pthread)
|
||||
else()
|
||||
set(EXTRA_LIBRARIES stdc++ m dl)
|
||||
endif()
|
||||
endif()
|
||||
list(APPEND LIBS "${EXTRA_LIBRARIES}")
|
||||
|
||||
# Sources
|
||||
|
||||
file(GLOB_RECURSE SRC_PORT "${CMAKE_SOURCE_DIR}/port/*.c")
|
||||
file(GLOB_RECURSE SRC_PORT_CXX "${CMAKE_SOURCE_DIR}/port/*.cpp")
|
||||
|
||||
file(GLOB_RECURSE SRC_GAME "${CMAKE_SOURCE_DIR}/src/game/*.c")
|
||||
|
||||
file(GLOB SRC_LIB_MP3 "${CMAKE_SOURCE_DIR}/src/lib/mp3/*.c")
|
||||
file(GLOB SRC_LIB_NAUDIO "${CMAKE_SOURCE_DIR}/src/lib/naudio/*.c")
|
||||
file(GLOB SRC_LIB_ULTRA_AUDIO "${CMAKE_SOURCE_DIR}/src/lib/ultra/audio/*.c")
|
||||
file(GLOB SRC_LIB_GU "${CMAKE_SOURCE_DIR}/src/lib/ultra/gu/*.c")
|
||||
set(SRC_LIB
|
||||
src/lib/ultra/io/vimodentsclan1.c
|
||||
src/lib/ultra/io/vimodepallan1.c
|
||||
src/lib/ultra/io/vimodempallan1.c
|
||||
src/lib/ultra/io/vitbl.c
|
||||
src/lib/ailist.c
|
||||
src/lib/anim.c
|
||||
src/lib/args.c
|
||||
src/lib/audiodma.c
|
||||
src/lib/audiomgr.c
|
||||
src/lib/base.c
|
||||
src/lib/collision.c
|
||||
src/lib/debughud.c
|
||||
src/lib/dma.c
|
||||
src/lib/fault.c
|
||||
src/lib/joy.c
|
||||
src/lib/lib_2f490_c.c
|
||||
src/lib/lib_2fc60.c
|
||||
src/lib/lib_3e3e0.c
|
||||
src/lib/lib_04f60nb.c
|
||||
src/lib/lib_17ce0.c
|
||||
src/lib/lib_034d0.c
|
||||
src/lib/lib_39c80.c
|
||||
src/lib/lib_15850.c
|
||||
src/lib/mema.c
|
||||
src/lib/memp.c
|
||||
src/lib/model.c
|
||||
src/lib/modelasm_c.c
|
||||
src/lib/mp3.c
|
||||
src/lib/mtx_c.c
|
||||
src/lib/mtx.c
|
||||
src/lib/music.c
|
||||
src/lib/path.c
|
||||
src/lib/profile.c
|
||||
src/lib/rdp.c
|
||||
src/lib/rmon.c
|
||||
src/lib/rng_c.c
|
||||
src/lib/rzip_c.c
|
||||
src/lib/snd.c
|
||||
src/lib/speaker.c
|
||||
src/lib/varsinit.c
|
||||
src/lib/vi.c
|
||||
src/textureconfig.c
|
||||
)
|
||||
list(PREPEND SRC_LIB "${CMAKE_SOURCE_DIR}")
|
||||
|
||||
set(SRC
|
||||
${SRC_GAME}
|
||||
${SRC_PORT}
|
||||
${SRC_PORT_CXX}
|
||||
${SRC_LIB_MP3}
|
||||
${SRC_LIB_NAUDIO}
|
||||
${SRC_LIB_ULTRA_AUDIO}
|
||||
${SRC_LIB_GU}
|
||||
${SRC_LIB}
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
list(APPEND SRC "${CMAKE_SOURCE_DIR}/dist/windows/icon.rc")
|
||||
endif()
|
||||
|
||||
# Asset files
|
||||
|
||||
generate_asset_headers("lang/" "${CMAKE_SOURCE_DIR}/tools/assetmgr/mklang" "en" JSON_HEADERS)
|
||||
generate_asset_headers("pads/" "${CMAKE_SOURCE_DIR}/tools/assetmgr/mkpads" "" JSON_HEADERS)
|
||||
generate_asset_headers("tiles/" "${CMAKE_SOURCE_DIR}/tools/assetmgr/mktiles" "" JSON_HEADERS)
|
||||
generate_asset_headers("animations.json" "${CMAKE_SOURCE_DIR}/tools/assetmgr/mkanims" "" JSON_HEADERS)
|
||||
generate_asset_headers("sequences.json" "${CMAKE_SOURCE_DIR}/tools/assetmgr/mksequences" "" JSON_HEADERS)
|
||||
generate_asset_headers("textures.json" "${CMAKE_SOURCE_DIR}/tools/assetmgr/mktextures" "" JSON_HEADERS)
|
||||
|
||||
add_custom_target(pd_headers ALL DEPENDS ${JSON_HEADERS})
|
||||
|
||||
# Game target
|
||||
|
||||
set(BIN_NAME "pd${BIN_REGION}.${TARGET_ARCH}")
|
||||
add_executable(pd ${SRC})
|
||||
add_dependencies(pd pd_headers)
|
||||
target_link_libraries(pd ${LIBS})
|
||||
set_target_properties(pd PROPERTIES OUTPUT_NAME "${BIN_NAME}")
|
||||
if(WIN32)
|
||||
set_target_properties(pd PROPERTIES WIN32_EXECUTABLE TRUE)
|
||||
endif()
|
||||
|
||||
# Additional commands for specific platforms.
|
||||
|
||||
if(NINTENDO_SWITCH)
|
||||
add_custom_command(TARGET pd POST_BUILD
|
||||
COMMAND nacptool --create "Perfect Dark" "fgsfds and contributors" "${VERSION_ROMID}/${VERSION_BRANCH}/${VERSION_HASH}" "${BIN_NAME}.nacp"
|
||||
COMMAND aarch64-none-elf-strip -o ${CMAKE_BINARY_DIR}/${BIN_NAME}.stripped.elf ${CMAKE_BINARY_DIR}/${BIN_NAME}.elf
|
||||
COMMAND elf2nro ${CMAKE_BINARY_DIR}/${BIN_NAME}.stripped.elf ${CMAKE_BINARY_DIR}/${BIN_NAME}.nro --icon=${CMAKE_SOURCE_DIR}/dist/nswitch/icon.jpg --nacp=${BIN_NAME}.nacp
|
||||
)
|
||||
endif()
|
||||
@@ -0,0 +1,812 @@
|
||||
################################################################################
|
||||
# Options
|
||||
|
||||
# ROMID - The ROM version to build.
|
||||
#
|
||||
# Can be set in your environment using
|
||||
# $ export ROMID=...
|
||||
#
|
||||
# Supported values:
|
||||
# * ntsc-beta
|
||||
# * ntsc-1.0
|
||||
# * ntsc-final
|
||||
# * pal-beta
|
||||
# * pal-final
|
||||
# * jpn-final
|
||||
|
||||
ROMID ?= ntsc-final
|
||||
|
||||
# MATCHING - Whether to build a matching ROM (1) or a custom one (0).
|
||||
#
|
||||
# Build a matching ROM to prove that the decompilation is accurate.
|
||||
#
|
||||
# If enabled, all further options are ignored and are set automatically.
|
||||
|
||||
MATCHING = 1
|
||||
|
||||
# COMPILER - Choose which compiler to use.
|
||||
#
|
||||
# A matching build uses ido. For non-matching builds, use gcc for performance.
|
||||
#
|
||||
# gcc is currently only supported when ROMID is ntsc-1.0 or ntsc-final.
|
||||
#
|
||||
# Supported values: ido, gcc
|
||||
|
||||
COMPILER = gcc
|
||||
|
||||
# GCC_OPT_LVL - the optimisation level if building with gcc.
|
||||
#
|
||||
# Supported values: -O0, -O1, -O2, -Os
|
||||
|
||||
GCC_OPT_LVL = -Os
|
||||
|
||||
# PAL - Whether to use the PAL television standard (1) or NTSC (0).
|
||||
#
|
||||
# PAL runs at 50Hz while NTSC is 60Hz, and PAL uses different screen dimensions.
|
||||
|
||||
PAL = 0
|
||||
|
||||
# ROMALLOCATION
|
||||
#
|
||||
# The lib, data and game segments are compressed in the final ROM.
|
||||
#
|
||||
# These options define how much space is allocated for the compressed segments.
|
||||
#
|
||||
# If any value is not big enough, the build system will tell you which one needs
|
||||
# to be changed and what to change it to.
|
||||
|
||||
ROMALLOCATION_DATA = 0x015000
|
||||
ROMALLOCATION_LIB = 0x038800
|
||||
ROMALLOCATION_GAME = 0x144ee0
|
||||
|
||||
# ROM_SIZE - The desired ROM size in megabytes.
|
||||
#
|
||||
# All versions of the retail ROM are 32MB.
|
||||
#
|
||||
# If this is too low you might get this error from ld:
|
||||
# "final link failed: memory exhausted"
|
||||
|
||||
ROM_SIZE := 32
|
||||
|
||||
# DEBUG - Enable (1) or disable (0) the debug menu and crash screen.
|
||||
#
|
||||
# When enabled, press C-up and C-down simultaneously to toggle the debug menu.
|
||||
# Note that some emulators have problems displaying the crash screen text.
|
||||
|
||||
DEBUG = 0
|
||||
|
||||
################################################################################
|
||||
|
||||
# The VERSION constant is used in the source to handle version-specific code.
|
||||
ifeq ($(ROMID), ntsc-beta)
|
||||
VERSION = 0
|
||||
endif
|
||||
ifeq ($(ROMID), ntsc-1.0)
|
||||
VERSION = 1
|
||||
endif
|
||||
ifeq ($(ROMID), ntsc-final)
|
||||
VERSION = 2
|
||||
endif
|
||||
ifeq ($(ROMID), pal-beta)
|
||||
VERSION = 3
|
||||
endif
|
||||
ifeq ($(ROMID), pal-final)
|
||||
VERSION = 4
|
||||
endif
|
||||
ifeq ($(ROMID), jpn-final)
|
||||
VERSION = 5
|
||||
endif
|
||||
|
||||
# Set runtime piracy checks off. We turn this on for matching builds if needed.
|
||||
PIRACYCHECKS = 0
|
||||
|
||||
# A magic value that's only used to produce a matching ROM.
|
||||
# It's required because old-school zlib was influenced by uninitialised data.
|
||||
# ZIPMAGIC is the value of the uninitialised data. We set it per version for
|
||||
# matching builds, otherwise 0 is fine.
|
||||
ZIPMAGIC = 0x0000
|
||||
|
||||
# This is also a value that's only used to produce a matching ROM.
|
||||
# The final ROM has some duplicate bytes, and there doesn't seem to be any logic
|
||||
# for determining how many bytes are duplicated.
|
||||
COPYLEN = 2
|
||||
|
||||
# If a matching build has been requested, override directives as needed.
|
||||
ifeq ($(MATCHING), 1)
|
||||
COMPILER = ido
|
||||
|
||||
ROMALLOCATION_DATA = 0x015000
|
||||
ROMALLOCATION_LIB = 0x038800
|
||||
|
||||
ROM_SIZE = 32
|
||||
DEBUG = 0
|
||||
|
||||
ifeq ($(ROMID), ntsc-beta)
|
||||
PAL = 0
|
||||
PIRACYCHECKS = 0
|
||||
ROMALLOCATION_DATA = 0x012000
|
||||
ROMALLOCATION_LIB = 0x02f800
|
||||
ROMALLOCATION_GAME = 0x105000
|
||||
DEBUG = 1
|
||||
endif
|
||||
ifeq ($(ROMID), ntsc-1.0)
|
||||
PAL = 0
|
||||
PIRACYCHECKS = 1
|
||||
ROMALLOCATION_GAME = 0x144ee0
|
||||
ZIPMAGIC = 0xffff
|
||||
endif
|
||||
ifeq ($(ROMID), ntsc-final)
|
||||
PAL = 0
|
||||
PIRACYCHECKS = 1
|
||||
ROMALLOCATION_GAME = 0x144ee0
|
||||
ZIPMAGIC = 0xffff
|
||||
endif
|
||||
ifeq ($(ROMID), pal-beta)
|
||||
PAL = 1
|
||||
PIRACYCHECKS = 1
|
||||
ROMALLOCATION_GAME = 0x1306f0
|
||||
ZIPMAGIC = 0x0c00
|
||||
COPYLEN = 6
|
||||
DEBUG = 1
|
||||
endif
|
||||
ifeq ($(ROMID), pal-final)
|
||||
PAL = 1
|
||||
PIRACYCHECKS = 1
|
||||
ROMALLOCATION_GAME = 0x1306f0
|
||||
ZIPMAGIC = 0xaf00
|
||||
endif
|
||||
ifeq ($(ROMID), jpn-final)
|
||||
PAL = 0
|
||||
PIRACYCHECKS = 1
|
||||
ROMALLOCATION_GAME = 0x1296f0
|
||||
ZIPMAGIC = 0x0002
|
||||
COPYLEN = 4
|
||||
endif
|
||||
endif
|
||||
|
||||
DEFINES := \
|
||||
VERSION=$(VERSION) \
|
||||
MATCHING=$(MATCHING) \
|
||||
PAL=$(PAL) \
|
||||
PIRACYCHECKS=$(PIRACYCHECKS) \
|
||||
ROM_SIZE=$(ROM_SIZE) \
|
||||
PLATFORM_N64=1
|
||||
|
||||
ifeq ($(DEBUG),1)
|
||||
DEFINES := $(DEFINES) DEBUG=1
|
||||
endif
|
||||
|
||||
C_DEFINES := $(foreach d,$(DEFINES),-D$(d))
|
||||
AS_DEFINES := $(foreach d,$(DEFINES),--defsym $(d)) --defsym _LANGUAGE_ASSEMBLY=1
|
||||
|
||||
A_DIR := src/assets/$(ROMID)
|
||||
B_DIR := build/$(ROMID)
|
||||
E_DIR := extracted/$(ROMID)
|
||||
|
||||
ifneq ($(strip $(MIPS_BINUTILS_PREFIX)),)
|
||||
TOOLCHAIN := $(MIPS_BINUTILS_PREFIX)
|
||||
else ifeq ($(shell type mips-elf-ld >/dev/null 2>/dev/null; echo $$?), 0)
|
||||
TOOLCHAIN := mips-elf
|
||||
else ifeq ($(shell type mips-linux-gnu-ld >/dev/null 2>/dev/null; echo $$?), 0)
|
||||
TOOLCHAIN := mips-linux-gnu
|
||||
else ifeq ($(shell type mips64-elf-ld >/dev/null 2>/dev/null; echo $$?), 0)
|
||||
TOOLCHAIN := mips64-elf
|
||||
else ifeq ($(shell type mips64-linux-gnu-ld >/dev/null 2>/dev/null; echo $$?), 0)
|
||||
TOOLCHAIN := mips64-linux-gnu
|
||||
else
|
||||
$(error You need to install a suitable MIPS binutils toolchain (eg. mips-elf-ld))
|
||||
endif
|
||||
|
||||
# Asset files are files which are included in the "files" segment of the ROM.
|
||||
# This excludes animations, fonts, SFX, MIDI and textures.
|
||||
# And because setup files are part of the files segment they are included here,
|
||||
# despite them being written in C.
|
||||
#
|
||||
# Create names such as $(B_DIR)/assets/files/PfooZ.
|
||||
# These names (with .o added) will be dependenices for ld.
|
||||
ASSET_FILES := \
|
||||
$(patsubst $(A_DIR)/files/audio/%.mp3, $(B_DIR)/assets/files/A%M, $(shell find $(A_DIR) -path '*/files/audio/*.mp3')) \
|
||||
$(patsubst $(A_DIR)/files/chrs/%.bin, $(B_DIR)/assets/files/C%Z, $(shell find $(A_DIR) -path '*/files/chrs/*.bin')) \
|
||||
$(patsubst $(A_DIR)/files/guns/%.bin, $(B_DIR)/assets/files/G%Z, $(shell find $(A_DIR) -path '*/files/guns/*.bin')) \
|
||||
$(patsubst $(A_DIR)/files/props/%.bin, $(B_DIR)/assets/files/P%Z, $(shell find $(A_DIR) -path '*/files/props/*.bin')) \
|
||||
$(patsubst src/setups/%.c, $(B_DIR)/assets/files/U%Z, $(shell find src/setups -name '*.c')) \
|
||||
$(patsubst $(A_DIR)/files/bgdata/%.seg, $(B_DIR)/assets/files/bgdata/%.seg, $(shell find $(A_DIR) -path '*/files/bgdata/*.seg')) \
|
||||
$(B_DIR)/assets/files/ob/ob_mid.seg.o
|
||||
|
||||
LANG_JSON_FILES := $(shell find $(A_DIR) -path '*/lang/*.json')
|
||||
PADS_JSON_FILES := $(shell find $(A_DIR) -path '*/pads/*.json')
|
||||
TILES_JSON_FILES := $(shell find $(A_DIR) -path '*/tiles/*.json')
|
||||
|
||||
LANG_O_FILES := \
|
||||
$(patsubst $(A_DIR)/lang/%.json, $(B_DIR)/assets/files/L%E.o, $(LANG_JSON_FILES)) \
|
||||
$(patsubst $(A_DIR)/lang/%.json, $(B_DIR)/assets/files/L%J.o, $(LANG_JSON_FILES)) \
|
||||
$(patsubst $(A_DIR)/lang/%.json, $(B_DIR)/assets/files/L%P.o, $(LANG_JSON_FILES)) \
|
||||
$(patsubst $(A_DIR)/lang/%.json, $(B_DIR)/assets/files/L%_str_f.o, $(LANG_JSON_FILES)) \
|
||||
$(patsubst $(A_DIR)/lang/%.json, $(B_DIR)/assets/files/L%_str_g.o, $(LANG_JSON_FILES)) \
|
||||
$(patsubst $(A_DIR)/lang/%.json, $(B_DIR)/assets/files/L%_str_i.o, $(LANG_JSON_FILES)) \
|
||||
$(patsubst $(A_DIR)/lang/%.json, $(B_DIR)/assets/files/L%_str_s.o, $(LANG_JSON_FILES))
|
||||
|
||||
PADS_O_FILES := $(patsubst $(A_DIR)/pads/%.json, $(B_DIR)/assets/files/bgdata/bg_%_padsZ.o, $(PADS_JSON_FILES))
|
||||
TILES_O_FILES := $(patsubst $(A_DIR)/tiles/%.json, $(B_DIR)/assets/files/bgdata/bg_%_tilesZ.o, $(TILES_JSON_FILES))
|
||||
|
||||
C_FILES := $(shell find src/lib src/game src/inflate -name '*.c')
|
||||
S_FILES := $(shell find src/lib src/game src/preamble -name '*.s')
|
||||
|
||||
C_O_FILES := $(patsubst src/%.c, $(B_DIR)/%.o, $(C_FILES))
|
||||
S_O_FILES := $(patsubst src/%.s, $(B_DIR)/%.o, $(S_FILES))
|
||||
|
||||
O_FILES := \
|
||||
$(C_O_FILES) \
|
||||
$(S_O_FILES) \
|
||||
$(patsubst %, %.o, $(ASSET_FILES)) \
|
||||
$(LANG_O_FILES) \
|
||||
$(PADS_O_FILES) \
|
||||
$(TILES_O_FILES) \
|
||||
$(B_DIR)/assets/animations.o \
|
||||
$(B_DIR)/assets/copyrightZ.o \
|
||||
$(B_DIR)/assets/files/list.o \
|
||||
$(B_DIR)/assets/fonts/bankgothic.o \
|
||||
$(B_DIR)/assets/fonts/handelgothiclg.o \
|
||||
$(B_DIR)/assets/fonts/handelgothicmd.o \
|
||||
$(B_DIR)/assets/fonts/handelgothicsm.o \
|
||||
$(B_DIR)/assets/fonts/handelgothicxs.o \
|
||||
$(B_DIR)/assets/fonts/numeric.o \
|
||||
$(B_DIR)/assets/fonts/ocralg.o \
|
||||
$(B_DIR)/assets/fonts/ocramd.o \
|
||||
$(B_DIR)/assets/fonts/tahoma.o \
|
||||
$(B_DIR)/assets/fonts/zurich.o \
|
||||
$(B_DIR)/assets/mpstrings/mpstringsE.o \
|
||||
$(B_DIR)/assets/mpstrings/mpstringsF.o \
|
||||
$(B_DIR)/assets/mpstrings/mpstringsG.o \
|
||||
$(B_DIR)/assets/mpstrings/mpstringsI.o \
|
||||
$(B_DIR)/assets/mpstrings/mpstringsJ.o \
|
||||
$(B_DIR)/assets/mpstrings/mpstringsP.o \
|
||||
$(B_DIR)/assets/mpstrings/mpstringsS.o \
|
||||
$(B_DIR)/assets/seq.ctl.o \
|
||||
$(B_DIR)/assets/seq.tbl.o \
|
||||
$(B_DIR)/assets/sequences.o \
|
||||
$(B_DIR)/assets/sfx.ctl.o \
|
||||
$(B_DIR)/assets/sfx.tbl.o \
|
||||
$(B_DIR)/assets/textureslist.o \
|
||||
$(B_DIR)/bootloader.o \
|
||||
$(B_DIR)/firingrange.o \
|
||||
$(B_DIR)/getitle.o \
|
||||
$(B_DIR)/mpconfigs.o \
|
||||
$(B_DIR)/romheader.o \
|
||||
$(B_DIR)/rsp/asp.data.o \
|
||||
$(B_DIR)/rsp/asp.text.o \
|
||||
$(B_DIR)/rsp/gsp.data.o \
|
||||
$(B_DIR)/rsp/gsp.text.o \
|
||||
$(B_DIR)/rsp/rspboot.text.o \
|
||||
$(B_DIR)/textureconfig.o
|
||||
|
||||
# ntsc-beta doesn't have this segment
|
||||
ifneq ($(ROMID), ntsc-beta)
|
||||
O_FILES := $(O_FILES) $(B_DIR)/assets/accessingpakZ.o
|
||||
endif
|
||||
|
||||
ifeq ($(ROMID), jpn-final)
|
||||
O_FILES := $(O_FILES) $(B_DIR)/assets/fonts/jpn.o
|
||||
else
|
||||
O_FILES := $(O_FILES) \
|
||||
$(B_DIR)/assets/fonts/jpnsingle.o \
|
||||
$(B_DIR)/assets/fonts/jpnmulti.o
|
||||
endif
|
||||
|
||||
INCLUDES = \
|
||||
-I include \
|
||||
-I include/PR \
|
||||
-I src/include \
|
||||
-I src/include/lib/libc \
|
||||
-I src/generated/$(ROMID) \
|
||||
-I src/lib/ultra/audio \
|
||||
|
||||
AS := $(TOOLCHAIN)-as
|
||||
ASFLAGS = -march=vr4300 -mabi=32 $(INCLUDES) $(AS_DEFINES)
|
||||
|
||||
ifeq ($(COMPILER), ido)
|
||||
RECOMP_FILES := \
|
||||
build/recomp/5.3/as1 \
|
||||
build/recomp/5.3/cc \
|
||||
build/recomp/5.3/cfe \
|
||||
build/recomp/5.3/err.english.cc \
|
||||
build/recomp/5.3/ugen \
|
||||
build/recomp/5.3/ujoin \
|
||||
build/recomp/5.3/uld \
|
||||
build/recomp/5.3/umerge \
|
||||
build/recomp/5.3/uopt \
|
||||
build/recomp/5.3/usplit \
|
||||
build/recomp/7.1/as1 \
|
||||
build/recomp/7.1/cc \
|
||||
build/recomp/7.1/cfe \
|
||||
build/recomp/7.1/err.english.cc \
|
||||
build/recomp/7.1/ugen \
|
||||
build/recomp/7.1/uopt
|
||||
|
||||
LOOPUNROLL_C_FILES := \
|
||||
src/lib/ultra/gu/frustum.c \
|
||||
src/lib/ultra/gu/mtxutil.c \
|
||||
src/lib/ultra/gu/ortho.c \
|
||||
src/lib/ultra/io/conteepread.c \
|
||||
src/lib/ultra/io/conteepwrite.c \
|
||||
src/lib/ultra/io/contpfs.c \
|
||||
src/lib/ultra/io/contramread.c \
|
||||
src/lib/ultra/io/contramwrite.c \
|
||||
src/lib/ultra/io/gbpakgetstatus.c \
|
||||
src/lib/ultra/io/gbpakreadid.c \
|
||||
src/lib/ultra/io/motor.c \
|
||||
src/lib/ultra/io/pfschecker.c \
|
||||
src/lib/ultra/io/pfsfreeblocks.c \
|
||||
src/lib/ultra/io/pfsgetstatus.c \
|
||||
src/lib/ultra/io/pfsinitpak2.c
|
||||
|
||||
MIPS3_C_FILES := \
|
||||
src/lib/rng_c.c \
|
||||
src/lib/ultra/libc/ll.c \
|
||||
src/lib/ultra/libc/llcvt.c
|
||||
|
||||
G_C_FILES := \
|
||||
$(shell find src/lib/ultra/audio -name '*.c') \
|
||||
$(shell find src/lib/naudio -name '*.c') \
|
||||
$(shell find src/lib/mp3 -name '*.c') \
|
||||
src/lib/lib_2fc60.c \
|
||||
src/lib/lib_317f0.c \
|
||||
src/lib/lib_39c80.c \
|
||||
src/lib/lib_3e3e0.c \
|
||||
src/lib/mp3.c \
|
||||
src/lib/speaker.c
|
||||
|
||||
O1_C_FILES := \
|
||||
src/lib/lib_04f60nb.c \
|
||||
src/lib/ultra/io/ai.c \
|
||||
src/lib/ultra/io/aisetnextbuf.c \
|
||||
src/lib/ultra/io/conteeplongread.c \
|
||||
src/lib/ultra/io/contquery.c \
|
||||
src/lib/ultra/io/controller.c \
|
||||
src/lib/ultra/io/dpctr.c \
|
||||
src/lib/ultra/io/pigetcmdq.c \
|
||||
src/lib/ultra/io/pidma.c \
|
||||
src/lib/ultra/io/si.c \
|
||||
src/lib/ultra/io/sp.c \
|
||||
src/lib/ultra/io/spsetpc.c \
|
||||
src/lib/ultra/io/sptaskyielded.c \
|
||||
src/lib/ultra/io/vi.c \
|
||||
src/lib/ultra/io/viblack.c \
|
||||
src/lib/ultra/io/vigetcurrframebuf.c \
|
||||
src/lib/ultra/io/vigetnextframebuf.c \
|
||||
src/lib/ultra/io/visetevent.c \
|
||||
src/lib/ultra/io/visetmode.c \
|
||||
src/lib/ultra/io/visetxscale.c \
|
||||
src/lib/ultra/io/visetyscale.c \
|
||||
src/lib/ultra/io/viswapbuf.c \
|
||||
src/lib/ultra/libc/ll.c \
|
||||
src/lib/ultra/libc/llcvt.c \
|
||||
src/lib/ultra/os/atomic.c \
|
||||
src/lib/ultra/os/createmesgqueue.c \
|
||||
src/lib/ultra/os/destroythread.c \
|
||||
src/lib/ultra/os/getmemsize.c \
|
||||
src/lib/ultra/os/gettime.c \
|
||||
src/lib/ultra/os/initialize2.c \
|
||||
src/lib/ultra/os/jammesg.c \
|
||||
src/lib/ultra/os/recvmesg.c \
|
||||
src/lib/ultra/os/resetglobalintmask.c \
|
||||
src/lib/ultra/os/sendmesg.c \
|
||||
src/lib/ultra/os/seteventmesg.c \
|
||||
src/lib/ultra/os/setglobalintmask.c \
|
||||
src/lib/ultra/os/setthreadpri.c \
|
||||
src/lib/ultra/os/settimer.c \
|
||||
src/lib/ultra/os/startthread.c \
|
||||
src/lib/ultra/os/stopthread.c \
|
||||
src/lib/ultra/os/stoptimer.c \
|
||||
src/lib/ultra/os/thread.c \
|
||||
src/lib/ultra/os/timerintr.c \
|
||||
src/lib/ultra/os/virtualtophysical.c \
|
||||
src/lib/ultra/os/yieldthread.c
|
||||
|
||||
ifeq ($(ROMID), ntsc-beta)
|
||||
O1_C_FILES := $(O1_C_FILES) src/lib/ultra/io/pfsisplug.c
|
||||
endif
|
||||
|
||||
O3_C_FILES := \
|
||||
src/lib/ultra/gu/align.c \
|
||||
src/lib/ultra/gu/frustum.c \
|
||||
src/lib/ultra/gu/ortho.c \
|
||||
src/lib/ultra/gu/scale.c \
|
||||
src/lib/ultra/libc/xprintf.c
|
||||
|
||||
IDO71_C_FILES := \
|
||||
$(shell find src/lib/ultra/audio -name '*.c') \
|
||||
$(shell find src/lib/naudio -name '*.c') \
|
||||
$(shell find src/lib/mp3 -name '*.c') \
|
||||
src/lib/lib_2fc60.c \
|
||||
src/lib/lib_39c80.c
|
||||
|
||||
LOOPUNROLL_O_FILES = $(patsubst src/%.c, $(B_DIR)/%.o, $(LOOPUNROLL_C_FILES))
|
||||
MIPS3_O_FILES = $(patsubst src/%.c, $(B_DIR)/%.o, $(MIPS3_C_FILES))
|
||||
G_O_FILES = $(patsubst src/%.c, $(B_DIR)/%.o, $(G_C_FILES))
|
||||
O1_O_FILES = $(patsubst src/%.c, $(B_DIR)/%.o, $(O1_C_FILES))
|
||||
O3_O_FILES = $(patsubst src/%.c, $(B_DIR)/%.o, $(O3_C_FILES))
|
||||
IDO71_O_FILES = $(patsubst src/%.c, $(B_DIR)/%.o, $(IDO71_C_FILES))
|
||||
|
||||
LOOPUNROLL := -Wo,-loopunroll,0
|
||||
MIPSISET := -mips2
|
||||
OPT_LVL := -O2
|
||||
CC := build/recomp/5.3/cc
|
||||
|
||||
$(LOOPUNROLL_O_FILES): LOOPUNROLL :=
|
||||
$(MIPS3_O_FILES): MIPSISET := -mips3
|
||||
$(G_O_FILES): OPT_LVL := -g
|
||||
$(O1_O_FILES): OPT_LVL := -O1
|
||||
$(O3_O_FILES): OPT_LVL := -O3
|
||||
$(IDO71_O_FILES): CC := build/recomp/7.1/cc
|
||||
|
||||
CFLAGS = $(C_DEFINES) $(INCLUDES) \
|
||||
$(LOOPUNROLL) \
|
||||
-Wab,-r4300_mul \
|
||||
-non_shared \
|
||||
-Olimit 2000 \
|
||||
-G 0 \
|
||||
-Xcpluscomm \
|
||||
-w2 \
|
||||
-Wab,-w \
|
||||
-woff 581,649,819,820,821,838,852 \
|
||||
$(MIPSISET) -32
|
||||
|
||||
# Files containing GLOBAL_ASM must be built with the asm_processor
|
||||
ifeq ($(MATCHING), 1)
|
||||
GLOBALASM_C_FILES != grep -rl 'GLOBAL_ASM(' $(C_FILES)
|
||||
GLOBALASM_O_FILES = $(patsubst src/%.c, $(B_DIR)/%.o, $(GLOBALASM_C_FILES))
|
||||
$(GLOBALASM_O_FILES): CC := /usr/bin/env python3 tools/asm_processor/build.py $(CC) -- $(TOOLCHAIN)-as $(ASFLAGS) --
|
||||
endif
|
||||
else ifeq ($(COMPILER), gcc)
|
||||
CC := $(TOOLCHAIN)-gcc
|
||||
|
||||
$(C_O_FILES): OPT_LVL := $(GCC_OPT_LVL)
|
||||
|
||||
C_DEFINES += -DAVOID_UB
|
||||
|
||||
CFLAGS := $(C_DEFINES) $(INCLUDES) \
|
||||
-EB \
|
||||
-march=vr4300 \
|
||||
-mabi=32 \
|
||||
-mfix4300 \
|
||||
-mdivide-breaks \
|
||||
-mno-abicalls \
|
||||
-ffreestanding \
|
||||
-fno-builtin \
|
||||
-fno-common \
|
||||
-fno-inline-functions \
|
||||
-fno-merge-constants \
|
||||
-fno-strict-aliasing \
|
||||
-fno-zero-initialized-in-bss \
|
||||
-funsigned-char \
|
||||
-fwrapv \
|
||||
-Wall \
|
||||
-Werror \
|
||||
-Wno-address \
|
||||
-Wno-aggressive-loop-optimizations \
|
||||
-Wno-array-bounds \
|
||||
-Wno-int-in-bool-context \
|
||||
-Wno-int-to-pointer-cast \
|
||||
-Wno-maybe-uninitialized \
|
||||
-Wno-misleading-indentation \
|
||||
-Wno-missing-braces \
|
||||
-Wno-multichar \
|
||||
-Wno-pointer-sign \
|
||||
-Wno-pointer-to-int-cast \
|
||||
-Wno-tautological-compare \
|
||||
-Wno-uninitialized \
|
||||
-Wno-unused-but-set-variable \
|
||||
-Wno-unused-value \
|
||||
-Wno-unused-variable \
|
||||
-G 0
|
||||
|
||||
$(B_DIR)/lib/ultra/libc/xldtob.o: CFLAGS += -ffast-math -fno-unsafe-math-optimizations
|
||||
else
|
||||
$(error The COMPILER option must be "ido" or "gcc")
|
||||
endif
|
||||
|
||||
# Make ROMID available as an environment variable to all tooling.
|
||||
# (We use this a lot)
|
||||
export ROMID
|
||||
|
||||
default: rom
|
||||
|
||||
################################################################################
|
||||
# Recomp
|
||||
# ------------------------------------------------------------------------------
|
||||
# The ido-static-recomp project is installed as a git submodule at tools/recomp.
|
||||
# The IRIX binaries are taken from that project and they are recompiled to
|
||||
# build/recomp/<version>/
|
||||
|
||||
tools/recomp/recomp.cpp:
|
||||
@echo "Please install ido-static-recomp by running:"
|
||||
@echo
|
||||
@echo " git submodule update --init --recursive"
|
||||
@echo
|
||||
@exit 1
|
||||
|
||||
build/recomp/recomp: tools/recomp/recomp.cpp
|
||||
@mkdir -p build/recomp/5.3
|
||||
@mkdir -p build/recomp/7.1
|
||||
g++ tools/recomp/recomp.cpp -o build/recomp/recomp -g -lcapstone
|
||||
|
||||
build/recomp/5.3/ugen:
|
||||
@mkdir -p build/recomp/5.3
|
||||
g++ tools/recomp/recomp.cpp -o build/recomp/recomp-ugen53 -g -lcapstone -Dugen53
|
||||
./build/recomp/recomp-ugen53 tools/recomp/ido/5.3/usr/lib/ugen > build/recomp/5.3/ugen.c
|
||||
gcc tools/recomp/libc_impl.c build/recomp/5.3/ugen.c -Itools/recomp -o build/recomp/5.3/ugen -O2 -fno-strict-aliasing -lm -no-pie -DIDO53
|
||||
|
||||
build/recomp/5.3/cc: build/recomp/recomp
|
||||
./build/recomp/recomp tools/recomp/ido/5.3/usr/bin/cc > build/recomp/5.3/cc.c
|
||||
gcc tools/recomp/libc_impl.c build/recomp/5.3/cc.c -Itools/recomp -o build/recomp/5.3/cc -O2 -fno-strict-aliasing -lm -no-pie -DIDO53
|
||||
|
||||
build/recomp/5.3/%: build/recomp/recomp
|
||||
./build/recomp/recomp tools/recomp/ido/5.3/usr/lib/$* > build/recomp/5.3/$*.c
|
||||
gcc tools/recomp/libc_impl.c build/recomp/5.3/$*.c -Itools/recomp -o build/recomp/5.3/$* -O2 -fno-strict-aliasing -lm -no-pie -DIDO53
|
||||
|
||||
build/recomp/7.1/cc: build/recomp/recomp
|
||||
./build/recomp/recomp tools/recomp/ido/7.1/usr/bin/cc > build/recomp/7.1/cc.c
|
||||
gcc tools/recomp/libc_impl.c build/recomp/7.1/cc.c -Itools/recomp -o build/recomp/7.1/cc -O2 -fno-strict-aliasing -lm -no-pie -DIDO71
|
||||
|
||||
build/recomp/7.1/%: build/recomp/recomp
|
||||
./build/recomp/recomp tools/recomp/ido/7.1/usr/lib/$* > build/recomp/7.1/$*.c
|
||||
gcc tools/recomp/libc_impl.c build/recomp/7.1/$*.c -Itools/recomp -o build/recomp/7.1/$* -O2 -fno-strict-aliasing -lm -no-pie -DIDO71
|
||||
|
||||
build/recomp/%/err.english.cc:
|
||||
@mkdir -p build/recomp/$?
|
||||
cp tools/err.english.cc build/recomp/$*
|
||||
|
||||
################################################################################
|
||||
# ROM Finalisation Stages
|
||||
|
||||
# Link all objects together with ld to make stage1.elf. In this stage, the game,
|
||||
# lib and data segments are uncompressed and placed past the end of the ROM.
|
||||
$(B_DIR)/stage1.elf: $(O_FILES) ld/pd.ld
|
||||
cpp -DROMID=$(ROMID) -DVERSION=$(VERSION) -DROMALLOCATION_DATA=$(ROMALLOCATION_DATA) -DROMALLOCATION_LIB=$(ROMALLOCATION_LIB) -DROMALLOCATION_GAME=$(ROMALLOCATION_GAME) -DROM_SIZE=$(ROM_SIZE) -P ld/pd.ld -o $(B_DIR)/pd.ld
|
||||
$(TOOLCHAIN)-ld --no-check-sections -z muldefs -T $(B_DIR)/pd.ld --print-map -o $@ > $(B_DIR)/pd.map
|
||||
|
||||
$(B_DIR)/stage1.bin: $(B_DIR)/stage1.elf
|
||||
$(TOOLCHAIN)-objcopy $< $@ -O binary
|
||||
|
||||
# Build the final ROM from stage1.bin using mkrom
|
||||
# mkrom handles calculating the piracy checksums, zipping segments and
|
||||
# calculating the ROM checksum.
|
||||
$(B_DIR)/pd.z64: $(B_DIR)/stage1.bin tools/mkrom/mkrom
|
||||
tools/mkrom/mkrom $(B_DIR)/stage1.bin $(B_DIR)/pd.map $(PIRACYCHECKS) $(ZIPMAGIC) $(COPYLEN) $@
|
||||
@echo -e "\033[0;32mROM written to $@\033[0m"
|
||||
|
||||
tools/mkrom/mkrom:
|
||||
$(MAKE) -C tools/mkrom
|
||||
|
||||
################################################################################
|
||||
# Testing Related
|
||||
# ---------------------
|
||||
# This works a little backwards, in that the ROM has to be built to at least
|
||||
# stage 2, then extract-segment is used to slice out the segments.
|
||||
|
||||
CHECK_FILES := $(shell awk '{print $$2}' checksums.$(ROMID).md5)
|
||||
|
||||
test: $(CHECK_FILES)
|
||||
@md5sum --quiet -c checksums.$(ROMID).md5
|
||||
|
||||
$(B_DIR)/segments/%.bin: $(B_DIR)/pd.z64
|
||||
@B_DIR=$(B_DIR) tools/extract-segment $*
|
||||
|
||||
################################################################################
|
||||
# Raw data segments
|
||||
|
||||
$(B_DIR)/assets/fonts/%.o: $(A_DIR)/fonts/%.bin
|
||||
mkdir -p $(B_DIR)/assets/fonts
|
||||
TOOLCHAIN=$(TOOLCHAIN) ROMID=$(ROMID) tools/mkrawobject $< $@
|
||||
|
||||
$(B_DIR)/getitle.o: $(E_DIR)/getitle.bin
|
||||
TOOLCHAIN=$(TOOLCHAIN) ROMID=$(ROMID) tools/mkrawobject $< $@
|
||||
|
||||
$(B_DIR)/assets/seq.ctl.o: $(A_DIR)/seq.ctl
|
||||
TOOLCHAIN=$(TOOLCHAIN) ROMID=$(ROMID) tools/mkrawobject $< $@
|
||||
|
||||
$(B_DIR)/assets/seq.tbl.o: $(A_DIR)/seq.tbl
|
||||
TOOLCHAIN=$(TOOLCHAIN) ROMID=$(ROMID) tools/mkrawobject $< $@
|
||||
|
||||
$(B_DIR)/assets/sfx.ctl.o: $(A_DIR)/sfx.ctl
|
||||
TOOLCHAIN=$(TOOLCHAIN) ROMID=$(ROMID) tools/mkrawobject $< $@
|
||||
|
||||
$(B_DIR)/assets/sfx.tbl.o: $(A_DIR)/sfx.tbl
|
||||
TOOLCHAIN=$(TOOLCHAIN) ROMID=$(ROMID) tools/mkrawobject $< $@
|
||||
|
||||
################################################################################
|
||||
# Asset Manager
|
||||
|
||||
ASSETMGR_O_FILES := \
|
||||
$(B_DIR)/assets/animations.o \
|
||||
$(LANG_O_FILES) \
|
||||
$(PADS_O_FILES) \
|
||||
$(TILES_O_FILES) \
|
||||
$(B_DIR)/assets/sequences.o \
|
||||
$(B_DIR)/assets/textureslist.o \
|
||||
|
||||
# Anims
|
||||
$(B_DIR)/assets/animations.o: $(A_DIR)/animations.json
|
||||
tools/assetmgr/mkanims
|
||||
|
||||
# Lang
|
||||
$(B_DIR)/assets/files/L%E.o: $(A_DIR)/lang/%.json
|
||||
tools/assetmgr/mklang $< en
|
||||
|
||||
$(B_DIR)/assets/files/L%J.o: $(A_DIR)/lang/%.json
|
||||
tools/assetmgr/mklang $< jp
|
||||
|
||||
$(B_DIR)/assets/files/L%P.o: $(A_DIR)/lang/%.json
|
||||
tools/assetmgr/mklang $< gb
|
||||
|
||||
$(B_DIR)/assets/files/L%_str_f.o: $(A_DIR)/lang/%.json
|
||||
tools/assetmgr/mklang $< fr
|
||||
|
||||
$(B_DIR)/assets/files/L%_str_g.o: $(A_DIR)/lang/%.json
|
||||
tools/assetmgr/mklang $< de
|
||||
|
||||
$(B_DIR)/assets/files/L%_str_i.o: $(A_DIR)/lang/%.json
|
||||
tools/assetmgr/mklang $< it
|
||||
|
||||
$(B_DIR)/assets/files/L%_str_s.o: $(A_DIR)/lang/%.json
|
||||
tools/assetmgr/mklang $< es
|
||||
|
||||
# Pads
|
||||
$(B_DIR)/assets/files/bgdata/bg_%_padsZ.o: $(A_DIR)/pads/%.json
|
||||
tools/assetmgr/mkpads $<
|
||||
|
||||
# Pads - but this is the zipped non-obj, for make test
|
||||
$(B_DIR)/assets/files/bgdata/bg_%_padsZ: $(A_DIR)/pads/%.json
|
||||
tools/assetmgr/mkpads $<
|
||||
|
||||
# Sequences
|
||||
$(B_DIR)/assets/sequences.o: $(A_DIR)/sequences.json
|
||||
tools/assetmgr/mksequences
|
||||
|
||||
# Textures
|
||||
$(B_DIR)/assets/textureslist.o: $(A_DIR)/textures.json
|
||||
tools/assetmgr/mktextures
|
||||
|
||||
# Tiles
|
||||
$(B_DIR)/assets/files/bgdata/bg_%_tilesZ.o: $(A_DIR)/tiles/%.json
|
||||
tools/assetmgr/mktiles $<
|
||||
|
||||
# Tiles - but this is the zipped non-obj, for make test
|
||||
$(B_DIR)/assets/files/bgdata/bg_%_tilesZ: $(A_DIR)/tiles/%.json
|
||||
tools/assetmgr/mktiles $<
|
||||
|
||||
################################################################################
|
||||
# Files
|
||||
|
||||
# Audio
|
||||
$(B_DIR)/assets/files/A%M: $(A_DIR)/files/audio/%.mp3
|
||||
@mkdir -p $(B_DIR)/assets/files
|
||||
cp $< $@
|
||||
|
||||
# BG segs
|
||||
$(B_DIR)/assets/files/bgdata/bg_%.seg: $(A_DIR)/files/bgdata/bg_%.seg
|
||||
@mkdir -p $(B_DIR)/assets/files/bgdata
|
||||
cp $< $@
|
||||
|
||||
# Chrs
|
||||
$(B_DIR)/assets/files/C%Z: $(A_DIR)/files/chrs/%.bin
|
||||
@mkdir -p $(B_DIR)/assets/files
|
||||
tools/rarezip $< > $@
|
||||
|
||||
# Guns
|
||||
$(B_DIR)/assets/files/G%Z: $(A_DIR)/files/guns/%.bin
|
||||
@mkdir -p $(B_DIR)/assets/files
|
||||
tools/rarezip $< > $@
|
||||
|
||||
# OB seg
|
||||
$(B_DIR)/assets/files/ob/ob_mid.seg.o: $(B_DIR)/assets/files/ob/ob_mid.seg
|
||||
TOOLCHAIN=$(TOOLCHAIN) ROMID=$(ROMID) tools/mkrawobject $< $@
|
||||
|
||||
$(B_DIR)/assets/files/ob/ob_mid.seg:
|
||||
@mkdir -p $(B_DIR)/assets/files/ob
|
||||
> $@
|
||||
|
||||
# Props
|
||||
$(B_DIR)/assets/files/P%Z: $(A_DIR)/files/props/%.bin
|
||||
tools/rarezip $< > $@
|
||||
|
||||
# Stage setups
|
||||
# $(A_DIR)/files/setup/foo.c
|
||||
# -> B_DIR/assets/files/setup/foo.o (done here)
|
||||
# -> B_DIR/assets/files/setup/foo.elf (done here)
|
||||
# -> B_DIR/assets/files/setup/foo.bin (done here)
|
||||
# -> B_DIR/assets/files/UsetupfooZ (done here)
|
||||
# -> B_DIR/assets/files/UsetupfooZ.o (done elsewhere)
|
||||
$(B_DIR)/assets/files/setup/%.o: src/setups/%.c $(ASSETMGR_O_FILES) $(RECOMP_FILES)
|
||||
@mkdir -p $(dir $@)
|
||||
$(CC) -c $(CFLAGS) -o $@ $<
|
||||
|
||||
$(B_DIR)/assets/files/setup/%.elf: $(B_DIR)/assets/files/setup/%.o
|
||||
TOOLCHAIN=$(TOOLCHAIN) tools/mksimpleelf $< $@
|
||||
|
||||
$(B_DIR)/files/setup/%.bin: $(B_DIR)/assets/files/setup/%.elf
|
||||
@mkdir -p $(dir $@)
|
||||
$(TOOLCHAIN)-objcopy $< $@ -O binary
|
||||
|
||||
$(B_DIR)/assets/files/U%Z: $(B_DIR)/files/setup/%.bin
|
||||
tools/rarezip $< > $@
|
||||
|
||||
# General target to convert any finalised file into a raw object for ld
|
||||
$(B_DIR)/assets/files/%.o: $(B_DIR)/assets/files/%
|
||||
TOOLCHAIN=$(TOOLCHAIN) ROMID=$(ROMID) tools/mkrawobject $< $@
|
||||
|
||||
$(B_DIR)/assets/files/%.bin: $(B_DIR)/assets/files/%.elf
|
||||
$(TOOLCHAIN)-objcopy $< $@ -O binary
|
||||
|
||||
################################################################################
|
||||
# Miscellaneous
|
||||
|
||||
$(B_DIR)/bootloader.o: $(E_DIR)/bootloader.bin
|
||||
@mkdir -p $(dir $@)
|
||||
TOOLCHAIN=$(TOOLCHAIN) ROMID=$(ROMID) tools/mkrawobject $< $@
|
||||
|
||||
$(B_DIR)/romheader.o: src/romheader/romheader.s
|
||||
$(TOOLCHAIN)-as --defsym VERSION=$(VERSION) -march=vr4300 -mabi=32 -I src/include -EB -o $@ $<
|
||||
|
||||
$(B_DIR)/assets/accessingpakZ: $(A_DIR)/accessingpak.bin
|
||||
tools/rarezip $< > $@
|
||||
|
||||
$(B_DIR)/assets/copyrightZ: $(A_DIR)/copyright.bin
|
||||
tools/rarezip $< > $@
|
||||
|
||||
$(B_DIR)/assets/accessingpakZ.o: $(B_DIR)/assets/accessingpakZ
|
||||
TOOLCHAIN=$(TOOLCHAIN) ROMID=$(ROMID) tools/mkrawobject $< $@
|
||||
|
||||
$(B_DIR)/assets/copyrightZ.o: $(B_DIR)/assets/copyrightZ
|
||||
TOOLCHAIN=$(TOOLCHAIN) ROMID=$(ROMID) tools/mkrawobject $< $@
|
||||
|
||||
$(B_DIR)/rsp/%.text.bin $(B_DIR)/rsp/%.data.bin: src/rsp/%.s
|
||||
@mkdir -p $(dir $@)
|
||||
armips -strequ CODE_FILE $(B_DIR)/rsp/$*.text.bin -strequ DATA_FILE $(B_DIR)/rsp/$*.data.bin $<
|
||||
|
||||
$(B_DIR)/rsp/%.o: $(B_DIR)/rsp/%.bin
|
||||
TOOLCHAIN=$(TOOLCHAIN) ROMID=$(ROMID) tools/mkrawobject $< $@
|
||||
|
||||
ifeq ($(COMPILER), ido)
|
||||
$(B_DIR)/lib/rng_c.o: src/lib/rng_c.c $(ASSETMGR_O_FILES) $(RECOMP_FILES)
|
||||
@mkdir -p $(dir $@)
|
||||
$(CC) -c $(CFLAGS) $(OPT_LVL) -o $@ $<
|
||||
tools/patchmips3 $@ || rm $@
|
||||
|
||||
$(B_DIR)/lib/ultra/libc/llcvt.o: src/lib/ultra/libc/llcvt.c $(ASSETMGR_O_FILES) $(RECOMP_FILES)
|
||||
@mkdir -p $(dir $@)
|
||||
$(CC) -c $(CFLAGS) $(OPT_LVL) -o $@ $<
|
||||
tools/patchmips3 $@ || rm $@
|
||||
|
||||
$(B_DIR)/lib/ultra/libc/ll.o: src/lib/ultra/libc/ll.c $(ASSETMGR_O_FILES) $(RECOMP_FILES)
|
||||
@mkdir -p $(dir $@)
|
||||
$(CC) -c $(CFLAGS) $(OPT_LVL) $< -o $@
|
||||
tools/patchmips3 $@ || rm $@
|
||||
endif
|
||||
|
||||
$(B_DIR)/%.o: src/%.c $(ASSETMGR_O_FILES) $(RECOMP_FILES)
|
||||
@mkdir -p $(dir $@)
|
||||
$(CC) -c $(CFLAGS) $(OPT_LVL) -o $@ $<
|
||||
|
||||
$(B_DIR)/%.o: src/%.s
|
||||
@mkdir -p $(dir $@)
|
||||
cpp -P -Wno-trigraphs -I include -I include/PR -I src/include $(C_DEFINES) -D_LANGUAGE_ASSEMBLY -D_MIPSEB $< | $(AS) $(ASFLAGS) -o $@
|
||||
|
||||
$(B_DIR)/assets/%.o: $(A_DIR)/%.c $(RECOMP_FILES)
|
||||
@mkdir -p $(dir $@)
|
||||
$(CC) -c $(CFLAGS) -o $@ $<
|
||||
|
||||
extract:
|
||||
ROMID=$(ROMID) tools/extract
|
||||
|
||||
rom: $(B_DIR)/pd.z64
|
||||
|
||||
clean:
|
||||
rm -rf build/$(ROMID) src/generated/$(ROMID)
|
||||
|
||||
allclean:
|
||||
rm -rf build/* src/generated
|
||||
|
||||
codeclean:
|
||||
find $(B_DIR)/game $(B_DIR)/inflate $(B_DIR)/lib -name '*.o' -delete
|
||||
+336
@@ -0,0 +1,336 @@
|
||||
# Options.
|
||||
|
||||
# HOST_PLATFORM - Which platform we're building on.
|
||||
#
|
||||
# Determined automatically if not specified on command line.
|
||||
#
|
||||
# Supported values:
|
||||
# * i686-windows
|
||||
# * i686-linux
|
||||
|
||||
HOST_PLATFORM ?=
|
||||
|
||||
# TARGET_PLATFORM - Which platform to build for.
|
||||
#
|
||||
# Determined from HOST_PLATFORM if not specified on command line.
|
||||
#
|
||||
# Supported values:
|
||||
# * i686-windows
|
||||
# * i686-linux
|
||||
|
||||
TARGET_PLATFORM ?=
|
||||
|
||||
# ROMID - The ROM version to use.
|
||||
#
|
||||
# Can be set in your environment using
|
||||
# $ export ROMID=...
|
||||
#
|
||||
# Supported values:
|
||||
# * ntsc-final
|
||||
# * pal-final
|
||||
# * jpn-final
|
||||
|
||||
ROMID ?= ntsc-final
|
||||
|
||||
# GCC_OPT_LVL - the optimisation level if building with gcc.
|
||||
#
|
||||
# Supported values: -O0, -O1, -O2, -O3, -Os, -Og
|
||||
|
||||
GCC_OPT_LVL = -Og
|
||||
|
||||
# ROM_SIZE - The desired ROM size in megabytes.
|
||||
#
|
||||
# All versions of the retail ROM are 32MB.
|
||||
#
|
||||
# If this is too low you might get this error from ld:
|
||||
# "final link failed: memory exhausted"
|
||||
|
||||
ROM_SIZE := 32
|
||||
|
||||
# DEBUG - Enable (1) or disable (0) the debug menu and crash screen.
|
||||
#
|
||||
# When enabled, press C-up and C-down simultaneously to toggle the debug menu.
|
||||
# Note that some emulators have problems displaying the crash screen text.
|
||||
|
||||
DEBUG = 0
|
||||
|
||||
################################################################################
|
||||
|
||||
# Detect host platform if not specified.
|
||||
ifeq ($(HOST_PLATFORM),)
|
||||
ifeq ($(OS),Windows_NT)
|
||||
# assume msys for now
|
||||
UNAME_OS := $(shell uname -s)
|
||||
ifneq (,$(findstring MINGW64,$(UNAME_OS)))
|
||||
HOST_PLATFORM := x86_64-windows
|
||||
else
|
||||
HOST_PLATFORM := i686-windows
|
||||
endif
|
||||
else # TODO
|
||||
UNAME_ARCH := $(shell uname -m)
|
||||
UNAME_OS := $(shell uname -s)
|
||||
UNAME_OS := $(shell echo $(UNAME_OS) | tr A-Z a-z)
|
||||
HOST_PLATFORM := $(UNAME_ARCH)-$(UNAME_OS)
|
||||
endif
|
||||
endif
|
||||
|
||||
# Set target platform to host platform if not specified.
|
||||
ifeq ($(TARGET_PLATFORM),)
|
||||
TARGET_PLATFORM := $(HOST_PLATFORM)
|
||||
endif
|
||||
|
||||
ifeq (,$(findstring clean,$(MAKECMDGOALS)))
|
||||
$(info Host platform: $(HOST_PLATFORM))
|
||||
$(info Target platform: $(TARGET_PLATFORM))
|
||||
endif
|
||||
|
||||
# Set whether the target arch is 64- or 32-bit.
|
||||
ifneq (,$(findstring 64,$(TARGET_PLATFORM))$(findstring armv8,$(TARGET_PLATFORM)))
|
||||
# TODO: we're not 64-bit compatible yet, error out if building the actual game
|
||||
ifeq (,$(findstring clean,$(MAKECMDGOALS)))
|
||||
$(error 64-bit target platforms are not supported yet)
|
||||
endif
|
||||
TARGET_64BIT = 1
|
||||
else # TODO
|
||||
TARGET_64BIT = 0
|
||||
endif
|
||||
|
||||
# Set whether the target is big-endian or little-endian.
|
||||
TARGET_BIG_ENDIAN = 0 # TODO
|
||||
|
||||
# The VERSION constant is used in the source to handle version-specific code.
|
||||
ifeq ($(ROMID),ntsc-final)
|
||||
BIN_NAME = pd.exe
|
||||
VERSION = 2
|
||||
IS_PAL = 0
|
||||
else ifeq ($(ROMID),pal-final)
|
||||
BIN_NAME = pd.pal.exe
|
||||
VERSION = 4
|
||||
IS_PAL = 1
|
||||
else ifeq ($(ROMID),jpn-final)
|
||||
BIN_NAME = pd.jpn.exe
|
||||
VERSION = 5
|
||||
IS_PAL = 0
|
||||
else
|
||||
$(error ROM version $(VERSION) is not supported)
|
||||
endif
|
||||
|
||||
VERSION_HASH := $(shell git rev-parse --short HEAD)
|
||||
VERSION_BRANCH := $(shell git rev-parse --abbrev-ref HEAD)
|
||||
VERSION_TARGET := $(TARGET_PLATFORM)
|
||||
VERSION_ROMID := $(ROMID)
|
||||
|
||||
ifeq ($(VERSION_BRANCH),)
|
||||
VERSION_BRANCH := port-custom
|
||||
endif
|
||||
ifeq ($(VERSION_BRANCH),HEAD)
|
||||
VERSION_BRANCH := port-custom
|
||||
endif
|
||||
|
||||
DEFINES := \
|
||||
VERSION=$(VERSION) \
|
||||
VERSION_HASH=\"$(VERSION_HASH)\" \
|
||||
VERSION_TARGET=\"$(VERSION_TARGET)\" \
|
||||
VERSION_ROMID=\"$(VERSION_ROMID)\" \
|
||||
VERSION_BRANCH=\"$(VERSION_BRANCH)\" \
|
||||
MATCHING=0 \
|
||||
PAL=$(IS_PAL) \
|
||||
PIRACYCHECKS=0 \
|
||||
ROM_SIZE=$(ROM_SIZE) \
|
||||
_LANGUAGE_C=1
|
||||
|
||||
ifeq ($(DEBUG),1)
|
||||
DEFINES := $(DEFINES) DEBUG=1
|
||||
endif
|
||||
|
||||
C_DEFINES := $(foreach d,$(DEFINES),-D$(d))
|
||||
|
||||
A_DIR := src/assets/$(ROMID)
|
||||
B_DIR := build/$(ROMID)-port
|
||||
G_DIR := src/generated/$(ROMID)
|
||||
|
||||
ifneq (,$(findstring windows,$(TARGET_PLATFORM)))
|
||||
TARGET_CFLAGS := $(shell pkg-config sdl2 --cflags-only-I)
|
||||
TARGET_LDFLAGS := $(shell pkg-config sdl2 --libs) -lz -lopengl32 -lws2_32 -lwinmm -ldbghelp
|
||||
# on windows/mingw we need this to be built with a 32-bit compiler so it finds the correct libs
|
||||
TOOLCHAIN ?= i686-w64-mingw32-
|
||||
# on GCC link libstdc++ statically
|
||||
ifeq (,$(findstring clang,$(CC))$(findstring clang,$(CXX)))
|
||||
TARGET_LDFLAGS += -static-libstdc++
|
||||
else
|
||||
TARGET_LDFLAGS += -lstdc++
|
||||
endif
|
||||
else # assume *nix
|
||||
TARGET_CFLAGS := $(shell pkg-config sdl2 --cflags-only-I)
|
||||
TARGET_LDFLAGS := $(shell pkg-config sdl2 --libs) -lGL -lz -ldl
|
||||
ifneq (,$(findstring arm,$(TARGET_PLATFORM))$(findstring aarch,$(TARGET_PLATFORM)))
|
||||
# linux on arm or aarch64
|
||||
# TODO: detect soft/hardfloat abi
|
||||
TOOLCHAIN ?= arm-linux-gnueabihf-
|
||||
endif
|
||||
endif
|
||||
|
||||
# On x86_64 gcc add -m32 to CFLAGS if building a 32-bit executable.
|
||||
ifneq (,$(findstring x86_64,$(HOST_PLATFORM))$(findstring x86_64,$(TOOLCHAIN)))
|
||||
ifneq (1,$(TARGET_64BIT))
|
||||
TARGET_CFLAGS += -m32
|
||||
endif
|
||||
endif
|
||||
|
||||
# These are still used in the port, but only to generate headers.
|
||||
JSON_FILES := $(shell find $(A_DIR) -path '*/lang/*.json')
|
||||
JSON_FILES += $(shell find $(A_DIR) -path '*/pads/*.json')
|
||||
JSON_FILES += $(shell find $(A_DIR) -path '*/tiles/*.json')
|
||||
JSON_FILES += $(wildcard $(A_DIR)/*.json)
|
||||
|
||||
JSON_HEADERS := $(patsubst $(A_DIR)/%.json, $(G_DIR)/%.h, $(JSON_FILES))
|
||||
|
||||
C_FILES := $(shell find src/game port -name '*.c')
|
||||
C_FILES := $(C_FILES) \
|
||||
$(wildcard src/lib/mp3/*.c) \
|
||||
$(wildcard src/lib/naudio/*.c) \
|
||||
$(wildcard src/lib/ultra/audio/*.c) \
|
||||
$(wildcard src/lib/ultra/gu/*.c) \
|
||||
src/lib/ultra/io/vimodentsclan1.c \
|
||||
src/lib/ultra/io/vimodepallan1.c \
|
||||
src/lib/ultra/io/vimodempallan1.c \
|
||||
src/lib/ultra/io/vitbl.c \
|
||||
$(wildcard src/lib/a*.c) \
|
||||
src/lib/base.c \
|
||||
src/lib/collision.c \
|
||||
src/lib/debughud.c \
|
||||
src/lib/dma.c \
|
||||
src/lib/fault.c \
|
||||
src/lib/joy.c \
|
||||
$(wildcard src/lib/lib_*.c) \
|
||||
src/lib/mema.c \
|
||||
src/lib/memp.c \
|
||||
src/lib/model.c \
|
||||
src/lib/modelasm_c.c \
|
||||
src/lib/mp3.c \
|
||||
src/lib/mtx_c.c \
|
||||
src/lib/mtx.c \
|
||||
src/lib/music.c \
|
||||
src/lib/path.c \
|
||||
src/lib/profile.c \
|
||||
src/lib/rdp.c \
|
||||
src/lib/rmon.c \
|
||||
src/lib/rng_c.c \
|
||||
src/lib/rzip_c.c \
|
||||
src/lib/snd.c \
|
||||
src/lib/speaker.c \
|
||||
src/lib/varsinit.c \
|
||||
src/lib/vi.c \
|
||||
src/textureconfig.c
|
||||
|
||||
CXX_FILES :=$(shell find port -name '*.cpp')
|
||||
|
||||
C_O_FILES := $(patsubst %.c, $(B_DIR)/%.o, $(C_FILES))
|
||||
CXX_O_FILES := $(patsubst %.cpp, $(B_DIR)/%.o, $(CXX_FILES))
|
||||
|
||||
O_FILES := $(C_O_FILES) $(CXX_O_FILES)
|
||||
|
||||
INCLUDES = \
|
||||
-I include \
|
||||
-I include/PR \
|
||||
-I src/include \
|
||||
-I src/generated/$(ROMID) \
|
||||
-I src/lib/ultra/audio \
|
||||
-I port/include
|
||||
|
||||
TOOLCHAIN ?=
|
||||
CC ?= $(TOOLCHAIN)gcc
|
||||
CXX ?= $(TOOLCHAIN)g++
|
||||
ifneq (,$(CXX_O_FILES))
|
||||
LD := $(CXX)
|
||||
else
|
||||
LD := $(CC)
|
||||
endif
|
||||
|
||||
$(C_O_FILES): OPT_LVL := $(GCC_OPT_LVL)
|
||||
|
||||
COMMON_CFLAGS := $(C_DEFINES) -DAVOID_UB=1 $(INCLUDES) $(TARGET_CFLAGS) -g \
|
||||
-fno-inline-functions \
|
||||
-fno-strict-aliasing \
|
||||
-funsigned-char \
|
||||
-fwrapv \
|
||||
-Wall \
|
||||
-Wno-address \
|
||||
-Wno-int-in-bool-context \
|
||||
-Wno-misleading-indentation \
|
||||
-Wno-missing-braces \
|
||||
-Wno-multichar \
|
||||
-Wno-tautological-compare \
|
||||
-Wno-unused-but-set-variable \
|
||||
-Wno-unused-value \
|
||||
-Wno-unused-variable \
|
||||
-Wno-format-truncation
|
||||
|
||||
CFLAGS := -std=c11 $(COMMON_CFLAGS) -Wno-pointer-sign
|
||||
CXXFLAGS := -std=c++20 $(COMMON_CFLAGS) -Wno-unused-function
|
||||
LDFLAGS := $(TARGET_LDFLAGS)
|
||||
|
||||
# Make ROMID available as an environment variable to all tooling.
|
||||
# (We use this a lot)
|
||||
export ROMID
|
||||
|
||||
BIN := $(B_DIR)/$(BIN_NAME)
|
||||
|
||||
default: $(BIN)
|
||||
|
||||
################################################################################
|
||||
# Asset Manager header generation
|
||||
|
||||
# Anims
|
||||
$(G_DIR)/animations.h: $(A_DIR)/animations.json
|
||||
tools/assetmgr/mkanims --headers-only
|
||||
|
||||
# Lang
|
||||
$(G_DIR)/lang/%.h: $(A_DIR)/lang/%.json
|
||||
tools/assetmgr/mklang $< en --headers-only
|
||||
|
||||
# Pads
|
||||
$(G_DIR)/pads/%.h: $(A_DIR)/pads/%.json
|
||||
tools/assetmgr/mkpads $< --headers-only
|
||||
|
||||
# Sequences
|
||||
$(G_DIR)/sequences.h: $(A_DIR)/sequences.json
|
||||
tools/assetmgr/mksequences --headers-only
|
||||
|
||||
# Textures
|
||||
$(G_DIR)/textures.h: $(A_DIR)/textures.json
|
||||
tools/assetmgr/mktextures --headers-only
|
||||
|
||||
# Tiles
|
||||
$(G_DIR)/tiles/%.h: $(A_DIR)/tiles/%.json
|
||||
tools/assetmgr/mktiles $< --headers-only
|
||||
|
||||
################################################################################
|
||||
# Generic compilation rules
|
||||
|
||||
$(BIN): $(O_FILES)
|
||||
$(LD) $(COMMON_CFLAGS) $(OPT_LVL) -o $(BIN) $^ $(LDFLAGS)
|
||||
ifneq ($(CV2PDB),)
|
||||
$(CV2PDB) $(BIN)
|
||||
endif
|
||||
|
||||
$(B_DIR)/%.o: %.c $(JSON_HEADERS)
|
||||
@mkdir -p $(dir $@)
|
||||
$(CC) -c $(CFLAGS) $(OPT_LVL) -o $@ $<
|
||||
|
||||
$(B_DIR)/%.o: %.cpp $(JSON_HEADERS)
|
||||
@mkdir -p $(dir $@)
|
||||
$(CXX) -c $(CXXFLAGS) $(OPT_LVL) -o $@ $<
|
||||
|
||||
################################################################################
|
||||
# Clean rules
|
||||
|
||||
clean:
|
||||
rm -rf build/$(ROMID)-port
|
||||
|
||||
allclean:
|
||||
rm -rf build/*
|
||||
rm -rf src/generated
|
||||
|
||||
codeclean:
|
||||
find $(B_DIR)/ -name '*.o' -delete
|
||||
@@ -1,4 +1,14 @@
|
||||
# Perfect Dark port
|
||||
# Perfect Dark port (`port-net`)
|
||||
|
||||
## Experimental netplay branch
|
||||
|
||||
This branch of the port contains an **extremely** early and experimental implementation of network play.
|
||||
**DISCLAIMER:** This is **NOT READY** for prime time. Use at your own risk if you are not a developer.
|
||||
**Do not create issues about problems in this branch until this disclaimer is gone.**
|
||||
|
||||
See [this file](https://github.com/fgsfdsfgs/perfect_dark/blob/port-net/docs/netplay.md) for more information on how this works.
|
||||
|
||||
## Original description
|
||||
|
||||
This repository contains a work-in-progress port of the [Perfect Dark decompilation](https://github.com/n64decomp/perfect_dark) to modern platforms.
|
||||
|
||||
@@ -31,24 +41,18 @@ There are minor graphics- and gameplay-related issues, and possibly occasional c
|
||||
* basic mod support, currently enough to load a few custom levels;
|
||||
* slightly expanded memory heap size;
|
||||
* experimental high framerate support (up to 240 FPS):
|
||||
* enable `Uncap Tickrate` in `Extended Video Options` to activate;
|
||||
* set `Game.TickRateDivisor` to `0` in `pd.ini` to activate;
|
||||
* in practice the game will have issues running faster than ~165 FPS, so use VSync or `Video.FramerateLimit` to cap it.
|
||||
* emulate the Transfer Pak functionality the game has on the Nintendo 64 to unlock some cheats automatically.
|
||||
|
||||
**The following platforms are officially supported and tested:**
|
||||
* Windows 7+: i686, x86_64
|
||||
* Linux: i686, x86_64
|
||||
* MacOS: x86_64 (OS 10.9+), arm64 (OS 11.0+)
|
||||
* Nintendo Switch: arm64
|
||||
Currently only 32-bit platforms are supported, namely x86 Windows and Linux.
|
||||
Note that 32-bit binaries will still work on 64-bit versions of those platforms,
|
||||
though you might have to install some additional libraries.
|
||||
|
||||
## Download
|
||||
|
||||
Latest [automatic builds](https://github.com/fgsfdsfgs/perfect_dark/releases/tag/ci-dev-build) for supported platforms:
|
||||
* [x86_64-windows](https://github.com/fgsfdsfgs/perfect_dark/releases/download/ci-dev-build/pd-x86_64-windows.zip)
|
||||
* [i686-windows](https://github.com/fgsfdsfgs/perfect_dark/releases/download/ci-dev-build/pd-i686-windows.zip)
|
||||
* [x86_64-linux](https://github.com/fgsfdsfgs/perfect_dark/releases/download/ci-dev-build/pd-x86_64-linux.tar.gz)
|
||||
* [i686-linux](https://github.com/fgsfdsfgs/perfect_dark/releases/download/ci-dev-build/pd-i686-linux.tar.gz)
|
||||
* [arm64-nswitch](https://github.com/fgsfdsfgs/perfect_dark/releases/download/ci-dev-build/pd-arm64-nswitch.zip)
|
||||
Latest [automatic builds](https://github.com/fgsfdsfgs/perfect_dark/actions) of the netplay branch for supported platforms:
|
||||
* [i686-windows (`port-net`)](https://nightly.link/fgsfdsfgs/perfect_dark/workflows/c-cpp/port-net/pd-i686-windows.zip)
|
||||
* [i686-linux (`port-net`)](https://nightly.link/fgsfdsfgs/perfect_dark/workflows/c-cpp/port-net/pd-i686-linux.zip)
|
||||
|
||||
If you are looking for netplay builds (the `port-net` branch), see [this link](https://github.com/fgsfdsfgs/perfect_dark/blob/port-net/README.md#download).
|
||||
|
||||
@@ -56,29 +60,13 @@ If you are looking for netplay builds (the `port-net` branch), see [this link](h
|
||||
|
||||
You must already have a Perfect Dark ROM to run the game, as specified above.
|
||||
|
||||
This assumes that you're using an x86_64 build. If you aren't, replace `x86_64` below with your arch (e.g. `i686`).
|
||||
|
||||
1. Create a directory named `data` next to `pd.x86_64` if it's not there.
|
||||
2. Put your Perfect Dark NTSC ROM named `pd.ntsc-final.z64` into it.
|
||||
3. Run the `pd.x86_64` executable.
|
||||
|
||||
If you want to use a PAL or JPN ROM instead, put them into the `data` directory and run the appropriate executable:
|
||||
* PAL: ROM name `pd.pal-final.z64`, executable name `pd.pal.x86_64`.
|
||||
* JPN: ROM name `pd.jpn-final.z64`, executable name `pd.jpn.x86_64`.
|
||||
|
||||
Optionally, you can also put your Perfect Dark for GameBoy Color ROM named `pd.gbc` in the `data` directory if you want to emulate having the Nintendo 64's Transfer Pak and unlock some cheats automatically.
|
||||
|
||||
Optionally, you can move the data folder to `~/.local/share/perfectdark` on Linux or `~/Library/Application Support/perfectdark` on MacOS.
|
||||
1. Create a directory named `data` next to `pd.exe`.
|
||||
2. Put your Perfect Dark ROM named `pd.ntsc-final.z64` into it.
|
||||
3. Run `pd.exe`.
|
||||
|
||||
Additional information can be found in the [wiki](https://github.com/fgsfdsfgs/perfect_dark/wiki).
|
||||
|
||||
A GPU supporting OpenGL 3.0/ES3.0 or above is required to run the port.
|
||||
|
||||
### Installing the Nintendo Switch version
|
||||
|
||||
The Nintendo Switch build ZIP comes with all 3 regions in different folders: `perfectdark`, `perfectdark_pal` and `perfectdark_jpn`.
|
||||
|
||||
Take the folder for the region you want and put it into the `/switch` folder on your SD card, then put your ROM into the `data` folder inside of the folder you extracted as described above.
|
||||
A GPU supporting OpenGL 3.0 or above is required to run the port.
|
||||
|
||||
## Controls
|
||||
|
||||
@@ -98,7 +86,7 @@ Controls can be rebound in `pd.ini`. Default control scheme is as follows:
|
||||
| Aim mode | RMB/Z | LT | R Trigger |
|
||||
| Use / Cancel | E | N/A | B |
|
||||
| Use / Accept | N/A | A | A |
|
||||
| Crouch cycle | N/A | LS Click | `0x80000000` (Extra) |
|
||||
| Crouch cycle | N/A | L3 | `0x80000000` (Extra) |
|
||||
| Half-Crouch | Shift | N/A | `0x40000000` (Extra) |
|
||||
| Full-Crouch | Control | N/A | `0x20000000` (Extra) |
|
||||
| Reload | R | X | X `(0x40)` |
|
||||
@@ -114,101 +102,43 @@ Controls can be rebound in `pd.ini`. Default control scheme is as follows:
|
||||
### Windows
|
||||
|
||||
1. Install [MSYS2](https://www.msys2.org).
|
||||
2. Open the `MINGW64` prompt if building for x86_64, or the `MINGW32` prompt if building for i686. (**NOTE:** _do not_ use the `MSYS` prompt)
|
||||
2. Open the `MINGW32` prompt. (**NOTE:** _not_ the `MSYS` prompt or the `MINGW64` prompt)
|
||||
3. Install dependencies:
|
||||
`pacman -S mingw-w64-x86_64-toolchain mingw-w64-x86_64-SDL2 mingw-w64-x86_64-zlib mingw-w64-x86_64-cmake mingw-w64-x86_64-python3 mingw-w64-i686-toolchain mingw-w64-i686-SDL2 mingw-w64-i686-zlib mingw-w64-i686-cmake mingw-w64-i686-python3 make git`
|
||||
`pacman -S mingw-w64-i686-toolchain mingw-w64-i686-SDL2 mingw-w64-i686-zlib make git`
|
||||
4. Get the source code:
|
||||
`git clone --recursive https://github.com/fgsfdsfgs/perfect_dark.git && cd perfect_dark`
|
||||
5. Run `cmake -G"Unix Makefiles" -Bbuild .`.
|
||||
* Add ` -DROMID=pal-final` or ` -DROMID=jpn-final` at the end of the command if you want to build a PAL or JPN executable respectively.\
|
||||
6. Run `cmake --build build -j4 -- -O`.
|
||||
7. The resulting executable will be at `build/pd.x86_64.exe` (or at `build/pd.i686.exe` if building for i686).
|
||||
8. If you don't know where you downloaded the source to, you can run `explorer .` to open the current directory.
|
||||
`git clone -b port-net --recursive https://github.com/fgsfdsfgs/perfect_dark.git && cd perfect_dark`
|
||||
5. Run `make -f Makefile.port`.
|
||||
* Add ` ROMID=pal-final` or ` ROMID=jpn-final` at the end of the command if you want to build a PAL or JPN executable respectively.
|
||||
6. The resulting executable will be at `build/ntsc-final-port/pd.exe`.
|
||||
7. If you don't know where you downloaded the source to, you can run `explorer .` to open the current directory.
|
||||
|
||||
### Linux
|
||||
|
||||
1. Ensure you have gcc, g++ (version 10.0+), make, cmake, git, python3 and SDL2 (version 2.0.12+), libGL and ZLib installed on your system.
|
||||
* If you wish to crosscompile, you will also need to have libraries and compilers for the target platform installed, e.g. `gcc-multilib` and `g++-multilib` for x86_64 -> i686 crosscompilation.
|
||||
1. Ensure you have gcc, g++ (version 10.0+) and 32-bit versions of SDL2 (version 2.0.12+), libGL and ZLib installed on your system.
|
||||
* On a 64-bit system you also need to have `gcc-multilib` and `g++-multilib` (or your distro's analogues) installed.
|
||||
2. Get the source code:
|
||||
`git clone --recursive https://github.com/fgsfdsfgs/perfect_dark.git && cd perfect_dark`
|
||||
`git clone -b port-net --recursive https://github.com/fgsfdsfgs/perfect_dark.git && cd perfect_dark`
|
||||
3. Run the following command:
|
||||
* ```cmake -G"Unix Makefiles" -Bbuild .```
|
||||
* Add ` -DROMID=pal-final` or ` -DROMID=jpn-final` at the end of the command if you want to build a PAL or JPN executable respectively.
|
||||
* Add ` -DCMAKE_C_FLAGS=-m32 -DCMAKE_CXX_FLAGS=-m32` at the end of the command if you want to crosscompile from x86_64 to x86.
|
||||
4. Run `cmake --build build -j4`.
|
||||
5. The resulting executable will be at `build/pd.<arch>` (for example `build/pd.x86_64`).
|
||||
* On a 64-bit system: ```make -f Makefile.port TARGET_PLATFORM=i686-linux```
|
||||
* On a 32-bit system: ```make -f Makefile.port```
|
||||
* Add ` ROMID=pal-final` or ` ROMID=jpn-final` at the end of the command if you want to build a PAL or JPN executable respectively.
|
||||
4. The resulting executable will be at `build/ntsc-final-port/pd.exe`.
|
||||
|
||||
### MacOS
|
||||
Currently only `i686-linux` and `i686-windows` are supported, using `gcc -m32` and `i686-w64-mingw32-gcc` as compilers, respectively.
|
||||
Alternate compilers can be specified by passing `TOOLCHAIN=i686-whatever-` as a command line argument.
|
||||
|
||||
1. Set up Homebrew.
|
||||
2. Install dependencies:
|
||||
* Execute command: `brew install cmake gcc python3 zlib git`
|
||||
3. Install SDL2:
|
||||
* Execute commands:
|
||||
```
|
||||
wget http://libsdl.org/release/SDL2-2.30.9.dmg -O SDL2.dmg
|
||||
hdiutil mount SDL2.dmg
|
||||
sudo cp -vr /Volumes/SDL2/SDL2.framework /Library/Frameworks
|
||||
hdiutil detach /Volumes/SDL2
|
||||
```
|
||||
* This installs SDL2 system-wide and this is how the automatic builds are done. The game will also look for it in the executable path, so you could
|
||||
download it locally instead.
|
||||
4. Get the source code:
|
||||
`git clone --recursive https://github.com/fgsfdsfgs/perfect_dark.git && cd perfect_dark`
|
||||
5. Configure:
|
||||
* Execute command: `cmake -G"Unix Makefiles" -Bbuild -DCMAKE_OSX_ARCHITECTURES=x86_64 .`
|
||||
* Replace `x86_64` with `arm64` if building for an ARM64 Mac.
|
||||
* Add ` -DROMID=pal-final` or ` -DROMID=jpn-final` at the end of the command if you want to build a PAL or JPN executable respectively.
|
||||
6. Build:
|
||||
* Execute command: `cmake --build build --target pd -j4 --clean-first`
|
||||
7. The resulting executable will be at `build/pd.<arch>` (for example `build/pd.x86_64`).
|
||||
* You might need to execute `chmod +x build/pd.x86-64` before you can run it.
|
||||
You can build an executable with PAL or JPN ROM support by adding `ROMID=pal-final` or `ROMID=jpn-final` to the `make` command.
|
||||
You will need to provide a `jpn-final` or `pal-final` ROM to run those, named `pd.jpn-final.z64` or `pd.pal-final.z64`.
|
||||
|
||||
### Nintendo Switch
|
||||
|
||||
1. Set up the [devkitA64 environment](https://devkitpro.org/wiki/Getting_Started).
|
||||
* On Windows you can do it under MSYS2 or WSL, usually MSYS2 is recommended.
|
||||
* If using MSYS2, make sure to use the **MSYS2** shell, **not** MINGW32 or MINGW64.
|
||||
2. Install host dependencies:
|
||||
* On MSYS2: execute command `pacman -Syuu && pacman -S git make cmake python3`
|
||||
* On Linux: use your package manager as normal to install the above dependencies.
|
||||
3. Install Switch toolchain and dependencies:
|
||||
* Execute commands:
|
||||
```
|
||||
dkp-pacman -Syuu
|
||||
dkp-pacman -S devkitA64 libnx switch-zlib switch-sdl2 switch-cmake dkp-toolchain-vars
|
||||
```
|
||||
* If in MSYS2 or `dkp-pacman` doesn't work, replace it with just `pacman`.
|
||||
4. Get the source code:
|
||||
`git clone --recursive https://github.com/fgsfdsfgs/perfect_dark.git && cd perfect_dark`
|
||||
5. Ensure devkitA64 environment variables are set:
|
||||
* Execute command: `source /opt/devkitpro/switchvars.sh`
|
||||
* If your `$DEVKITPRO` path is different, substitute that instead or set the variables manually.
|
||||
6. Configure:
|
||||
* Execute command: `aarch64-none-elf-cmake -G"Unix Makefiles" -Bbuild .`
|
||||
* Add ` -DROMID=pal-final` or ` -DROMID=jpn-final` at the end of the command if you want to build a PAL or JPN executable respectively.
|
||||
7. Build:
|
||||
* Execute command: `make -C build -j4`
|
||||
8. The resulting executable will be at `build/pd.arm64.nro`.
|
||||
|
||||
### Notes
|
||||
|
||||
Alternate compilers or toolchains can be specified by passing `-DCMAKE_TOOLCHAIN_FILE=whatever` as normal. The port does not build with Visual Studio.
|
||||
|
||||
You will need to provide a `jpn-final` or `pal-final` ROM to run executables built for those regions, named `pd.jpn-final.z64` or `pd.pal-final.z64`.
|
||||
|
||||
It might be possible to build and run the game on platforms that are not specified in the supported platforms list (e.g. Linux on armv7), but this has not been tested.
|
||||
It might be possible to build a 32-bit ARM executable, but this has not been tested.
|
||||
|
||||
## Credits
|
||||
|
||||
* the original [decompilation project](https://github.com/n64decomp/perfect_dark) authors;
|
||||
* Ryan Dwyer for the above, additional help, and `pd-extract`;
|
||||
* doomhack for the only other publicly available [PD porting effort](https://github.com/doomhack/perfect_dark) I could find;
|
||||
* [sm64-port](https://github.com/sm64-port/sm64-port) authors for the audio mixer and some other changes;
|
||||
* [Ship of Harkinian team](https://github.com/Kenix3/libultraship/tree/main/src/fast), Emill and MaikelChan for the libultraship version of fast3d that this port uses;
|
||||
* [Ship of Harkinian team](https://github.com/Kenix3/libultraship/tree/main/src/graphic/Fast3D), Emill and MaikelChan for the libultraship version of fast3d that this port uses;
|
||||
* lieff for [minimp3](https://github.com/lieff/minimp3);
|
||||
* Mouse Injector and 1964GEPD authors for some of the 60FPS- and mouselook-related fixes;
|
||||
* Raf for the 64-bit port;
|
||||
* NicNamSam for the icon;
|
||||
* everyone who has submitted pull requests and issues to this repository and tested the port;
|
||||
* probably more I'm forgetting.
|
||||
@@ -1,27 +0,0 @@
|
||||
# execute a header generator (execcmd) for every json file in jsonpath, collect headers in headerlist
|
||||
# note that this reads ROMID
|
||||
macro(generate_asset_headers jsonpath execcmd extraarg headerlist)
|
||||
set(TMP_JSON "")
|
||||
|
||||
if (${jsonpath} MATCHES "\.json")
|
||||
# is a json file
|
||||
list(APPEND TMP_JSON "${CMAKE_SOURCE_DIR}/${ASSET_DIR}/${jsonpath}")
|
||||
else()
|
||||
# is a directory
|
||||
file(GLOB TMP_JSON "${CMAKE_SOURCE_DIR}/${ASSET_DIR}/${jsonpath}*.json")
|
||||
endif()
|
||||
|
||||
foreach(JSON ${TMP_JSON})
|
||||
unset(HEADERNAME)
|
||||
string(REPLACE ".json" ".h" HEADERNAME ${JSON})
|
||||
string(REPLACE "${CMAKE_SOURCE_DIR}/${ASSET_DIR}" "${CMAKE_BINARY_DIR}/${GENERATED_DIR}" HEADERNAME ${HEADERNAME})
|
||||
add_custom_command(
|
||||
OUTPUT ${HEADERNAME}
|
||||
DEPENDS ${JSON}
|
||||
COMMAND ${execcmd} ${JSON} ${extraarg} --headers-only --romid=${ROMID}
|
||||
)
|
||||
list(APPEND ${headerlist} "${HEADERNAME}")
|
||||
endforeach()
|
||||
|
||||
unset(TMP_JSON)
|
||||
endmacro()
|
||||
@@ -1,172 +0,0 @@
|
||||
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
# file Copyright.txt or https://cmake.org/licensing for details.
|
||||
|
||||
# Locate SDL2 library
|
||||
# This module defines
|
||||
# SDL2_LIBRARY, the name of the library to link against
|
||||
# SDL2_FOUND, if false, do not try to link to SDL2
|
||||
# SDL2_INCLUDE_DIR, where to find SDL.h
|
||||
#
|
||||
# This module responds to the the flag:
|
||||
# SDL2_BUILDING_LIBRARY
|
||||
# If this is defined, then no SDL2_main will be linked in because
|
||||
# only applications need main().
|
||||
# Otherwise, it is assumed you are building an application and this
|
||||
# module will attempt to locate and set the the proper link flags
|
||||
# as part of the returned SDL2_LIBRARY variable.
|
||||
#
|
||||
# Don't forget to include SDL2main.h and SDL2main.m your project for the
|
||||
# OS X framework based version. (Other versions link to -lSDL2main which
|
||||
# this module will try to find on your behalf.) Also for OS X, this
|
||||
# module will automatically add the -framework Cocoa on your behalf.
|
||||
#
|
||||
#
|
||||
# Additional Note: If you see an empty SDL2_LIBRARY_TEMP in your configuration
|
||||
# and no SDL2_LIBRARY, it means CMake did not find your SDL2 library
|
||||
# (SDL2.dll, libsdl2.so, SDL2.framework, etc).
|
||||
# Set SDL2_LIBRARY_TEMP to point to your SDL2 library, and configure again.
|
||||
# Similarly, if you see an empty SDL2MAIN_LIBRARY, you should set this value
|
||||
# as appropriate. These values are used to generate the final SDL2_LIBRARY
|
||||
# variable, but when these values are unset, SDL2_LIBRARY does not get created.
|
||||
#
|
||||
#
|
||||
# $SDL2DIR is an environment variable that would
|
||||
# correspond to the ./configure --prefix=$SDL2DIR
|
||||
# used in building SDL2.
|
||||
# l.e.galup 9-20-02
|
||||
#
|
||||
# Modified by Eric Wing.
|
||||
# Added code to assist with automated building by using environmental variables
|
||||
# and providing a more controlled/consistent search behavior.
|
||||
# Added new modifications to recognize OS X frameworks and
|
||||
# additional Unix paths (FreeBSD, etc).
|
||||
# Also corrected the header search path to follow "proper" SDL2 guidelines.
|
||||
# Added a search for SDL2main which is needed by some platforms.
|
||||
# Added a search for threads which is needed by some platforms.
|
||||
# Added needed compile switches for MinGW.
|
||||
#
|
||||
# On OSX, this will prefer the Framework version (if found) over others.
|
||||
# People will have to manually change the cache values of
|
||||
# SDL2_LIBRARY to override this selection or set the CMake environment
|
||||
# CMAKE_INCLUDE_PATH to modify the search paths.
|
||||
#
|
||||
# Note that the header path has changed from SDL2/SDL.h to just SDL.h
|
||||
# This needed to change because "proper" SDL2 convention
|
||||
# is #include "SDL.h", not <SDL2/SDL.h>. This is done for portability
|
||||
# reasons because not all systems place things in SDL2/ (see FreeBSD).
|
||||
#
|
||||
# Ported by Johnny Patterson. This is a literal port for SDL2 of the FindSDL.cmake
|
||||
# module with the minor edit of changing "SDL" to "SDL2" where necessary. This
|
||||
# was not created for redistribution, and exists temporarily pending official
|
||||
# SDL2 CMake modules.
|
||||
|
||||
FIND_PATH(SDL2_INCLUDE_DIR SDL.h
|
||||
HINTS
|
||||
$ENV{SDL2DIR}
|
||||
PATH_SUFFIXES include/SDL2 include
|
||||
PATHS
|
||||
~/Library/Frameworks
|
||||
/Library/Frameworks
|
||||
/usr/local/include/SDL2
|
||||
/usr/include/SDL2
|
||||
/sw # Fink
|
||||
/opt/local # DarwinPorts
|
||||
/opt/csw # Blastwave
|
||||
/opt
|
||||
/boot/system/develop/headers/SDL2 #Hiaku OS
|
||||
)
|
||||
#MESSAGE("SDL2_INCLUDE_DIR is ${SDL2_INCLUDE_DIR}")
|
||||
|
||||
FIND_LIBRARY(SDL2_LIBRARY_TEMP
|
||||
NAMES SDL2
|
||||
HINTS
|
||||
$ENV{SDL2DIR}
|
||||
PATH_SUFFIXES lib64 lib
|
||||
PATHS
|
||||
/sw
|
||||
/opt/local
|
||||
/opt/csw
|
||||
/opt
|
||||
/system/lib #Hiaku OS
|
||||
)
|
||||
|
||||
#MESSAGE("SDL2_LIBRARY_TEMP is ${SDL2_LIBRARY_TEMP}")
|
||||
|
||||
IF(NOT SDL2_BUILDING_LIBRARY)
|
||||
IF(NOT ${SDL2_INCLUDE_DIR} MATCHES ".framework")
|
||||
# Non-OS X framework versions expect you to also dynamically link to
|
||||
# SDL2main. This is mainly for Windows and OS X. Other (Unix) platforms
|
||||
# seem to provide SDL2main for compatibility even though they don't
|
||||
# necessarily need it.
|
||||
FIND_LIBRARY(SDL2MAIN_LIBRARY
|
||||
NAMES SDL2main
|
||||
HINTS
|
||||
$ENV{SDL2DIR}
|
||||
PATH_SUFFIXES lib64 lib
|
||||
PATHS
|
||||
/sw
|
||||
/opt/local
|
||||
/opt/csw
|
||||
/opt
|
||||
)
|
||||
ENDIF(NOT ${SDL2_INCLUDE_DIR} MATCHES ".framework")
|
||||
ENDIF(NOT SDL2_BUILDING_LIBRARY)
|
||||
|
||||
# SDL2 may require threads on your system.
|
||||
# The Apple build may not need an explicit flag because one of the
|
||||
# frameworks may already provide it.
|
||||
# But for non-OSX systems, I will use the CMake Threads package.
|
||||
IF(NOT APPLE)
|
||||
FIND_PACKAGE(Threads)
|
||||
ENDIF(NOT APPLE)
|
||||
|
||||
# MinGW needs an additional library, mwindows
|
||||
# It's total link flags should look like -lmingw32 -lSDL2main -lSDL2 -lmwindows
|
||||
# (Actually on second look, I think it only needs one of the m* libraries.)
|
||||
IF(MINGW)
|
||||
SET(MINGW32_LIBRARY mingw32 CACHE STRING "mwindows for MinGW")
|
||||
ENDIF(MINGW)
|
||||
|
||||
SET(SDL2_FOUND "NO")
|
||||
IF(SDL2_LIBRARY_TEMP)
|
||||
# For SDL2main
|
||||
IF(NOT SDL2_BUILDING_LIBRARY)
|
||||
IF(SDL2MAIN_LIBRARY)
|
||||
SET(SDL2_LIBRARY_TEMP ${SDL2MAIN_LIBRARY} ${SDL2_LIBRARY_TEMP})
|
||||
ENDIF(SDL2MAIN_LIBRARY)
|
||||
ENDIF(NOT SDL2_BUILDING_LIBRARY)
|
||||
|
||||
# For OS X, SDL2 uses Cocoa as a backend so it must link to Cocoa.
|
||||
# CMake doesn't display the -framework Cocoa string in the UI even
|
||||
# though it actually is there if I modify a pre-used variable.
|
||||
# I think it has something to do with the CACHE STRING.
|
||||
# So I use a temporary variable until the end so I can set the
|
||||
# "real" variable in one-shot.
|
||||
IF(APPLE)
|
||||
SET(SDL2_LIBRARY_TEMP ${SDL2_LIBRARY_TEMP} "-framework Cocoa")
|
||||
ENDIF(APPLE)
|
||||
|
||||
# For threads, as mentioned Apple doesn't need this.
|
||||
# In fact, there seems to be a problem if I used the Threads package
|
||||
# and try using this line, so I'm just skipping it entirely for OS X.
|
||||
IF(NOT APPLE)
|
||||
SET(SDL2_LIBRARY_TEMP ${SDL2_LIBRARY_TEMP} ${CMAKE_THREAD_LIBS_INIT})
|
||||
ENDIF(NOT APPLE)
|
||||
|
||||
# For MinGW library
|
||||
IF(MINGW)
|
||||
SET(SDL2_LIBRARY_TEMP ${MINGW32_LIBRARY} ${SDL2_LIBRARY_TEMP})
|
||||
ENDIF(MINGW)
|
||||
|
||||
# Set the final string here so the GUI reflects the final state.
|
||||
SET(SDL2_LIBRARY ${SDL2_LIBRARY_TEMP} CACHE STRING "Where the SDL2 Library can be found")
|
||||
# Set the temp variable to INTERNAL so it is not seen in the CMake GUI
|
||||
SET(SDL2_LIBRARY_TEMP "${SDL2_LIBRARY_TEMP}" CACHE INTERNAL "")
|
||||
|
||||
SET(SDL2_FOUND "YES")
|
||||
ENDIF(SDL2_LIBRARY_TEMP)
|
||||
|
||||
INCLUDE(FindPackageHandleStandardArgs)
|
||||
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2
|
||||
REQUIRED_VARS SDL2_LIBRARY SDL2_INCLUDE_DIR)
|
||||
@@ -1,165 +0,0 @@
|
||||
|
||||
# Copyright (c) 2012 Petroules Corporation. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation and/or
|
||||
# other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
# IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
# OF SUCH DAMAGE.
|
||||
|
||||
# Based on the Qt 5 processor detection code, so should be very accurate
|
||||
# https://qt.gitorious.org/qt/qtbase/blobs/master/src/corelib/global/qprocessordetection.h
|
||||
# Currently handles arm (v5, v6, v7), x86 (32/64), ia64, and ppc (32/64)
|
||||
|
||||
# Regarding POWER/PowerPC, just as is noted in the Qt source,
|
||||
# "There are many more known variants/revisions that we do not handle/detect."
|
||||
|
||||
set(archdetect_c_code "
|
||||
#if defined(__arm__) || defined(__TARGET_ARCH_ARM) || defined(_M_ARM64) || defined (__aarch64__)
|
||||
#if defined(__ARM_ARCH_7__) \\
|
||||
|| defined(__ARM_ARCH_7A__) \\
|
||||
|| defined(__ARM_ARCH_7R__) \\
|
||||
|| defined(__ARM_ARCH_7M__) \\
|
||||
|| (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 7)
|
||||
#error cmake_ARCH armv7
|
||||
#elif defined(__ARM_ARCH_6__) \\
|
||||
|| defined(__ARM_ARCH_6J__) \\
|
||||
|| defined(__ARM_ARCH_6T2__) \\
|
||||
|| defined(__ARM_ARCH_6Z__) \\
|
||||
|| defined(__ARM_ARCH_6K__) \\
|
||||
|| defined(__ARM_ARCH_6ZK__) \\
|
||||
|| defined(__ARM_ARCH_6M__) \\
|
||||
|| (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 6)
|
||||
#error cmake_ARCH armv6
|
||||
#elif defined(__ARM_ARCH_5TEJ__) \\
|
||||
|| (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 5)
|
||||
#error cmake_ARCH armv5
|
||||
#elif defined(_M_ARM64) || defined (__aarch64__)
|
||||
#error cmake_ARCH arm64
|
||||
#else
|
||||
#error cmake_ARCH arm
|
||||
#endif
|
||||
#elif defined(__i386) || defined(__i386__) || defined(_M_IX86)
|
||||
#error cmake_ARCH i386
|
||||
#elif defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(_M_X64)
|
||||
#error cmake_ARCH x86_64
|
||||
#elif defined(__ia64) || defined(__ia64__) || defined(_M_IA64)
|
||||
#error cmake_ARCH ia64
|
||||
#elif defined(__ppc__) || defined(__ppc) || defined(__powerpc__) \\
|
||||
|| defined(_ARCH_COM) || defined(_ARCH_PWR) || defined(_ARCH_PPC) \\
|
||||
|| defined(_M_MPPC) || defined(_M_PPC)
|
||||
#if defined(__ppc64__) || defined(__powerpc64__) || defined(__64BIT__)
|
||||
#error cmake_ARCH ppc64
|
||||
#else
|
||||
#error cmake_ARCH ppc
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#error cmake_ARCH unknown
|
||||
")
|
||||
|
||||
# Set ppc_support to TRUE before including this file or ppc and ppc64
|
||||
# will be treated as invalid architectures since they are no longer supported by Apple
|
||||
|
||||
function(target_architecture output_var)
|
||||
if(APPLE AND CMAKE_OSX_ARCHITECTURES)
|
||||
# On OS X we use CMAKE_OSX_ARCHITECTURES *if* it was set
|
||||
# First let's normalize the order of the values
|
||||
|
||||
# Note that it's not possible to compile PowerPC applications if you are using
|
||||
# the OS X SDK version 10.6 or later - you'll need 10.4/10.5 for that, so we
|
||||
# disable it by default
|
||||
# See this page for more information:
|
||||
# http://stackoverflow.com/questions/5333490/how-can-we-restore-ppc-ppc64-as-well-as-full-10-4-10-5-sdk-support-to-xcode-4
|
||||
|
||||
# Architecture defaults to i386 or ppc on OS X 10.5 and earlier, depending on the CPU type detected at runtime.
|
||||
# On OS X 10.6+ the default is x86_64 if the CPU supports it, i386 otherwise.
|
||||
|
||||
foreach(osx_arch ${CMAKE_OSX_ARCHITECTURES})
|
||||
if("${osx_arch}" STREQUAL "ppc" AND ppc_support)
|
||||
set(osx_arch_ppc TRUE)
|
||||
elseif("${osx_arch}" STREQUAL "i386")
|
||||
set(osx_arch_i386 TRUE)
|
||||
elseif("${osx_arch}" STREQUAL "x86_64")
|
||||
set(osx_arch_x86_64 TRUE)
|
||||
elseif("${osx_arch}" STREQUAL "ppc64" AND ppc_support)
|
||||
set(osx_arch_ppc64 TRUE)
|
||||
elseif("${osx_arch}" STREQUAL "arm64")
|
||||
set(osx_arch_arm64 TRUE)
|
||||
else()
|
||||
message(FATAL_ERROR "Invalid OS X arch name: ${osx_arch}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Now add all the architectures in our normalized order
|
||||
if(osx_arch_ppc)
|
||||
list(APPEND ARCH ppc)
|
||||
endif()
|
||||
|
||||
if(osx_arch_i386)
|
||||
list(APPEND ARCH i386)
|
||||
endif()
|
||||
|
||||
if(osx_arch_x86_64)
|
||||
list(APPEND ARCH x86_64)
|
||||
endif()
|
||||
|
||||
if(osx_arch_ppc64)
|
||||
list(APPEND ARCH ppc64)
|
||||
endif()
|
||||
|
||||
if(osx_arch_arm64)
|
||||
list(APPEND ARCH arm64)
|
||||
endif()
|
||||
else()
|
||||
file(WRITE "${CMAKE_BINARY_DIR}/arch.c" "${archdetect_c_code}")
|
||||
|
||||
enable_language(C)
|
||||
|
||||
# Detect the architecture in a rather creative way...
|
||||
# This compiles a small C program which is a series of ifdefs that selects a
|
||||
# particular #error preprocessor directive whose message string contains the
|
||||
# target architecture. The program will always fail to compile (both because
|
||||
# file is not a valid C program, and obviously because of the presence of the
|
||||
# #error preprocessor directives... but by exploiting the preprocessor in this
|
||||
# way, we can detect the correct target architecture even when cross-compiling,
|
||||
# since the program itself never needs to be run (only the compiler/preprocessor)
|
||||
try_run(
|
||||
run_result_unused
|
||||
compile_result_unused
|
||||
"${CMAKE_BINARY_DIR}"
|
||||
"${CMAKE_BINARY_DIR}/arch.c"
|
||||
COMPILE_OUTPUT_VARIABLE ARCH
|
||||
CMAKE_FLAGS CMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES}
|
||||
)
|
||||
|
||||
# Parse the architecture name from the compiler output
|
||||
string(REGEX MATCH "cmake_ARCH ([a-zA-Z0-9_]+)" ARCH "${ARCH}")
|
||||
|
||||
# Get rid of the value marker leaving just the architecture name
|
||||
string(REPLACE "cmake_ARCH " "" ARCH "${ARCH}")
|
||||
|
||||
# If we are compiling with an unknown architecture this variable should
|
||||
# already be set to "unknown" but in the case that it's empty (i.e. due
|
||||
# to a typo in the code), then set it to unknown
|
||||
if (NOT ARCH)
|
||||
set(ARCH unknown)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(${output_var} "${ARCH}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
@@ -1,9 +0,0 @@
|
||||
[Desktop Entry]
|
||||
Name=Perfect Dark
|
||||
Comment=Modern source port of Perfect Dark
|
||||
Exec=io.github.perfect_dark_pc_port.perfect_dark.sh
|
||||
Icon=io.github.perfect_dark_pc_port.perfect_dark
|
||||
Terminal=false
|
||||
Type=Application
|
||||
Categories=Game;ActionGame;
|
||||
StartupNotify=false
|
||||
@@ -1,46 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<component type="desktop-application">
|
||||
<id>io.github.perfect_dark_pc_port.perfect_dark</id>
|
||||
<name>Perfect Dark</name>
|
||||
<developer id="io.github.perfect_dark_pc_port.perfect_dark">
|
||||
<name>Perfect Dark Contributors</name>
|
||||
<url>https://github.com/fgsfdsfgs/perfect_dark/graphs/contributors</url>
|
||||
</developer>
|
||||
<launchable type="desktop-id">io.github.perfect_dark_pc_port.perfect_dark.desktop</launchable>
|
||||
<summary>Modern cross-platform port of Perfect Dark</summary>
|
||||
<metadata_license>CC0-1.0</metadata_license>
|
||||
<project_license>MIT</project_license>
|
||||
<url type="homepage">https://github.com/fgsfdsfgs/perfect_dark/</url>
|
||||
<description>
|
||||
<p>This is a port of Ryan Dywer's decompilation of classic N64 shooter Perfect Dark to modern systems.</p>
|
||||
</description>
|
||||
<!--
|
||||
<screenshots>
|
||||
<screenshot type="default">
|
||||
<image type="source"></image>
|
||||
<caption>Screenshot</caption>
|
||||
</screenshot>
|
||||
<screenshots>
|
||||
-->
|
||||
<categories>
|
||||
<category>Game</category>
|
||||
<category>ActionGame</category>
|
||||
<category>Shooter</category>
|
||||
</categories>
|
||||
<keywords>
|
||||
<keyword>n64</keyword>
|
||||
<keyword>scifi</keyword>
|
||||
<keyword>cyberpunk</keyword>
|
||||
<keyword>retro</keyword>
|
||||
<keyword>sourceport</keyword>
|
||||
<keyword>port</keyword>
|
||||
</keywords>
|
||||
<releases>
|
||||
<release version="latest" date="2024-05-14"/>
|
||||
</releases>
|
||||
<content_rating type="oars-1.1">
|
||||
<content_attribute id="violence-realistic">moderate</content_attribute>
|
||||
<content_attribute id="violence-bloodshed">mild</content_attribute>
|
||||
</content_rating>
|
||||
<update_contact>https://github.com/fgsfdsfgs/perfect_dark/</update_contact>
|
||||
</component>
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 30 KiB |
@@ -1,39 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Create user data directories if necessary
|
||||
userdirs=( roms saves mods )
|
||||
for path in "${userdirs[@]}"; do
|
||||
if [ ! -d "${XDG_DATA_HOME}/${path}" ]; then
|
||||
mkdir -p "${XDG_DATA_HOME}/${path}"
|
||||
fi
|
||||
done
|
||||
|
||||
# Default to pd as executable but switch to jpn/pal if the NTSC rom
|
||||
# is missing but JPN/PAL are present.
|
||||
# TODO: Other arch
|
||||
executable="pd.x86_64"
|
||||
if [ -f ${XDG_DATA_HOME}/roms/pd.ntsc-final.z64 ] | \
|
||||
[ -f ${XDG_DATA_HOME}/roms/pd.ntsc-1.0.z64 ]; then
|
||||
executable="pd.x86_64"
|
||||
elif [ -f ${XDG_DATA_HOME}/roms/pd.jpn-final.z64 ]; then
|
||||
executable="pd.jpn.x86_64"
|
||||
elif [ -f ${XDG_DATA_HOME}/roms/pd.pal-final.z64 ]; then
|
||||
executable="pd.pal.x86_64"
|
||||
fi
|
||||
|
||||
# If first parameter passed to this script is one of the pd executables,
|
||||
# run that regardless of ROM auto-detection above and pass the remaining
|
||||
# parameters to it; otherwise pass all arguments to the executable selected
|
||||
# above
|
||||
case $1 in
|
||||
"pd."*)
|
||||
executable=$1
|
||||
params="${@:2}"
|
||||
;;
|
||||
*)
|
||||
params="$@"
|
||||
;;
|
||||
esac
|
||||
|
||||
# Run game
|
||||
$executable --basedir ${XDG_DATA_HOME}/roms --savedir ${XDG_DATA_HOME}/saves $params
|
||||
@@ -1,41 +0,0 @@
|
||||
app-id: io.github.perfect_dark_pc_port.perfect_dark
|
||||
runtime: org.freedesktop.Platform
|
||||
runtime-version: "25.08"
|
||||
sdk: org.freedesktop.Sdk
|
||||
command: io.github.perfect_dark_pc_port.perfect_dark.sh
|
||||
|
||||
finish-args:
|
||||
- --device=all
|
||||
- --share=ipc
|
||||
- --socket=x11
|
||||
# Audio
|
||||
- --socket=pulseaudio
|
||||
# Enable network for multiplayer
|
||||
- --share=network
|
||||
|
||||
modules:
|
||||
- name: perfect_dark
|
||||
buildsystem: simple
|
||||
sources:
|
||||
- type: file
|
||||
path: bin/pd.x86_64
|
||||
- type: file
|
||||
path: bin/pd.jpn.x86_64
|
||||
- type: file
|
||||
path: bin/pd.pal.x86_64
|
||||
- type: file
|
||||
path: io.github.perfect_dark_pc_port.perfect_dark.sh
|
||||
- type: file
|
||||
path: io.github.perfect_dark_pc_port.perfect_dark.png
|
||||
- type: file
|
||||
path: io.github.perfect_dark_pc_port.perfect_dark.metainfo.xml
|
||||
- type: file
|
||||
path: io.github.perfect_dark_pc_port.perfect_dark.desktop
|
||||
build-commands: []
|
||||
post-install:
|
||||
# Install the binaries
|
||||
- install -Dm 755 -t /app/bin/ pd.*
|
||||
- install -Dm 755 ${FLATPAK_ID}.sh /app/bin/${FLATPAK_ID}.sh
|
||||
- install -Dm 644 ${FLATPAK_ID}.desktop /app/share/applications/${FLATPAK_ID}.desktop
|
||||
- install -Dm 644 ${FLATPAK_ID}.metainfo.xml /app/share/metainfo/${FLATPAK_ID}.metainfo.xml
|
||||
- install -Dm 644 ${FLATPAK_ID}.png /app/share/icons/hicolor/256x256/apps/${FLATPAK_ID}.png
|
||||
Vendored
-2
@@ -1,2 +0,0 @@
|
||||
# Switch (SDL_GetPlatform is not changed in switch-sdl2)
|
||||
000038f853776974636820436f6e7400,Switch Controller,a:b0,b:b1,back:b11,dpdown:b15,dpleft:b12,dpright:b14,dpup:b13,leftshoulder:b6,leftstick:b4,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b5,righttrigger:b9,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Unknown (see SDL_platform.h),
|
||||
Vendored
BIN
Binary file not shown.
|
Before Width: | Height: | Size: 32 KiB |
Vendored
BIN
Binary file not shown.
|
Before Width: | Height: | Size: 128 KiB |
Vendored
-1
@@ -1 +0,0 @@
|
||||
id ICON icon.ico
|
||||
@@ -0,0 +1,47 @@
|
||||
## Experimental netplay branch
|
||||
|
||||
This branch contains a **highly experimental** implementation of network play.
|
||||
|
||||
Currently only Combat Sim is partially working with experimental 8 player support and really bad netcode.
|
||||
Expect nothing to work right.
|
||||
|
||||
### Hosting
|
||||
|
||||
1. Forward the server port (`27100` by default, can be changed in `pd.ini`).
|
||||
* You can also use something like ZeroTier or Hamachi if you can't port forward.
|
||||
3. Choose `Network Game` -> `Host Game`, configure the player cap, press `Start Game`.
|
||||
4. Configure Combat Sim as desired, but do not start it yet. Keep in mind:
|
||||
* You can save and load the settings as normal.
|
||||
* Your player will have the config of Combat Sim player 1.
|
||||
5. Wait for everyone to join. You can use the console (press `~`) to chat in the meantime.
|
||||
6. Hit Enter/Start. During the game no more players will be able to join.
|
||||
7. After game is over, you will be kicked back to Combat Sim settings, at which point people can join again and the process repeats from step 3.
|
||||
|
||||
### Joining
|
||||
|
||||
1. Your player will have the config of Combat Sim player 1, so set that up beforehand in the Combat Sim menu.
|
||||
2. Choose `Network Game` -> `Join Game`, enter the address (and port if it's not 27100), press `Start Game`.
|
||||
3. If the message says `Waiting for host`, wait until the host configures the game. You can use the console (press `~`) to chat in the meantime or `ESC` to disconnect.
|
||||
4. The game will start automatically.
|
||||
5. After the game is over, press Enter/Start on the stats screen and you will be kicked back to the `Waiting for host` screen, at which point the process repeats from step 3.
|
||||
|
||||
### Misc
|
||||
|
||||
* Everyone has to have the same ROM. The game only compares the file name, but different regions in one game will definitely break everything.
|
||||
* Press `~` to bring up the console, press `F9` for network stats.
|
||||
* You can chat at any time during a net game by entering messages in the console and hitting Enter.
|
||||
* Server port and other network settings can be configured in `pd.ini`.
|
||||
* For a 4+ player game I would recommend changing `Net.Server.UpdateFrames` to `2` in `pd.ini` on the server to lower the bandwidth usage.
|
||||
* You can paste stuff into the `Enter Address` prompt by hitting `CTRL+V`.
|
||||
* Expect nothing to work right.
|
||||
|
||||
### Known issues
|
||||
|
||||
* Clients can't throw laptop guns.
|
||||
* Clients see rocket rotation incorrectly.
|
||||
* Clients can't use Slayer fly-by-wire rockets and they will not correctly sync if the server uses them.
|
||||
* Clients can't use the alt fire mode on the FarSight and probably a couple other guns.
|
||||
* Cloaking device is not synced.
|
||||
* Most likely only Combat works properly.
|
||||
* Sims don't work in netgames.
|
||||
* Bandwidth consumption on the server is pretty large on the default settings, especially with 8 players.
|
||||
@@ -22,7 +22,6 @@
|
||||
#define __R4300_H__
|
||||
|
||||
#include <PR/ultratypes.h>
|
||||
#include "platform.h"
|
||||
|
||||
/*
|
||||
* Segment base addresses and sizes
|
||||
|
||||
+30
-62
@@ -22,12 +22,6 @@
|
||||
|
||||
#include <PR/ultratypes.h>
|
||||
#include "gbiex.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef PLATFORM_N64
|
||||
#include "platform.h"
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* To use the F3DEX ucodes, define F3DEX_GBI before include this file.
|
||||
@@ -600,10 +594,10 @@
|
||||
#define G_BL_0 3
|
||||
|
||||
#define GBL_c1(m1a, m1b, m2a, m2b) \
|
||||
(u32)(m1a) << 30 | (u32)(m1b) << 26 | (u32)(m2a) << 22 | (u32)(m2b) << 18
|
||||
(m1a) << 30 | (m1b) << 26 | (m2a) << 22 | (m2b) << 18
|
||||
|
||||
#define GBL_c2(m1a, m1b, m2a, m2b) \
|
||||
(u32)(m1a) << 28 | (u32)(m1b) << 24 | (u32)(m2a) << 20 | (u32)(m2b) << 16
|
||||
(m1a) << 28 | (m1b) << 24 | (m2a) << 20 | (m2b) << 16
|
||||
|
||||
#define RM_AA_ZB_OPA_SURF(clk) \
|
||||
AA_EN | Z_CMP | Z_UPD | IM_RD | CVG_DST_CLAMP | \
|
||||
@@ -1059,7 +1053,7 @@ typedef struct {
|
||||
// 4x4 float matrix
|
||||
typedef float Mtx_t[4][4];
|
||||
#else
|
||||
typedef int32_t Mtx_t[4][4];
|
||||
typedef long Mtx_t[4][4];
|
||||
#endif
|
||||
|
||||
typedef union {
|
||||
@@ -1312,14 +1306,6 @@ typedef union {
|
||||
/*
|
||||
* Graphics DMA Packet
|
||||
*/
|
||||
#ifdef PLATFORM_64BIT
|
||||
typedef struct {
|
||||
intptr_t par : 24;
|
||||
intptr_t cmd : 8;
|
||||
intptr_t len : 32;
|
||||
uintptr_t addr;
|
||||
} Gdma;
|
||||
#else
|
||||
typedef struct {
|
||||
#ifdef PLATFORM_BIG_ENDIAN
|
||||
int cmd:8;
|
||||
@@ -1333,7 +1319,6 @@ typedef struct {
|
||||
unsigned int addr;
|
||||
#endif
|
||||
} Gdma;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Graphics Immediate Mode Packet types
|
||||
@@ -1372,9 +1357,6 @@ typedef struct {
|
||||
unsigned char z4:4;
|
||||
unsigned char pad:8;
|
||||
unsigned char cmd:8;
|
||||
#ifdef PLATFORM_64BIT
|
||||
unsigned char pad2[4];
|
||||
#endif
|
||||
unsigned char x1:4;
|
||||
unsigned char y1:4;
|
||||
unsigned char x2:4;
|
||||
@@ -1383,9 +1365,6 @@ typedef struct {
|
||||
unsigned char y3:4;
|
||||
unsigned char x4:4;
|
||||
unsigned char y4:4;
|
||||
#ifdef PLATFORM_64BIT
|
||||
unsigned char pad3[4];
|
||||
#endif
|
||||
#endif
|
||||
} Gtri4;
|
||||
|
||||
@@ -1559,8 +1538,8 @@ typedef struct {
|
||||
* Generic Gfx Packet
|
||||
*/
|
||||
typedef struct {
|
||||
uintptr_t w0;
|
||||
uintptr_t w1;
|
||||
unsigned int w0;
|
||||
unsigned int w1;
|
||||
} Gwords;
|
||||
|
||||
// xxxxxxxx 11223344 44555566 66666777
|
||||
@@ -1617,11 +1596,7 @@ typedef struct {
|
||||
*/
|
||||
typedef union {
|
||||
Gwords words;
|
||||
#ifdef PLATFORM_64BIT
|
||||
u8 bytes[16];
|
||||
#else
|
||||
u8 bytes[8];
|
||||
#endif
|
||||
Gdma dma;
|
||||
Gvtx vtx;
|
||||
Gtri tri;
|
||||
@@ -1644,19 +1619,12 @@ typedef union {
|
||||
Gloadtlut loadtlut;
|
||||
#endif
|
||||
GunkC0 unkc0;
|
||||
#ifdef PLATFORM_64BIT
|
||||
long long int force_structure_alignment[2];
|
||||
#else
|
||||
long long int force_structure_alignment;
|
||||
#endif
|
||||
} Gfx;
|
||||
|
||||
#ifdef PLATFORM_BIG_ENDIAN
|
||||
#define GFX_W0_BYTE(i) (i)
|
||||
#define GFX_W1_BYTE(i) (4 + (i))
|
||||
#elif PLATFORM_64BIT
|
||||
#define GFX_W0_BYTE(i) (3 - (i))
|
||||
#define GFX_W1_BYTE(i) (11 - (i))
|
||||
#else
|
||||
#define GFX_W0_BYTE(i) (3 - (i))
|
||||
#define GFX_W1_BYTE(i) (7 - (i))
|
||||
@@ -1674,12 +1642,12 @@ typedef union {
|
||||
Gfx *_g = (Gfx *)(pkt); \
|
||||
\
|
||||
_g->words.w0 = _SHIFTL((c), 24, 8) | _SHIFTL((l), 0, 24); \
|
||||
_g->words.w1 = (uintptr_t)(s); \
|
||||
_g->words.w1 = (unsigned int)(s); \
|
||||
}
|
||||
|
||||
#define gsDma0p(c, s, l) \
|
||||
{ \
|
||||
_SHIFTL((c), 24, 8) | _SHIFTL((l), 0, 24), (uintptr_t)(s) \
|
||||
_SHIFTL((c), 24, 8) | _SHIFTL((l), 0, 24), (unsigned int)(s) \
|
||||
}
|
||||
|
||||
#define gDma1p(pkt, c, s, l, p) \
|
||||
@@ -1688,14 +1656,14 @@ typedef union {
|
||||
\
|
||||
_g->words.w0 = (_SHIFTL((c), 24, 8) | _SHIFTL((p), 16, 8) | \
|
||||
_SHIFTL((l), 0, 16)); \
|
||||
_g->words.w1 = (uintptr_t)(s); \
|
||||
_g->words.w1 = (unsigned int)(s); \
|
||||
}
|
||||
|
||||
#define gsDma1p(c, s, l, p) \
|
||||
{ \
|
||||
(_SHIFTL((c), 24, 8) | _SHIFTL((p), 16, 8) | \
|
||||
_SHIFTL((l), 0, 16)), \
|
||||
(uintptr_t)(s) \
|
||||
(unsigned int)(s) \
|
||||
}
|
||||
|
||||
#define gDma2p(pkt, c, adrs, len, idx, ofs) \
|
||||
@@ -1703,14 +1671,14 @@ typedef union {
|
||||
Gfx *_g = (Gfx *)(pkt); \
|
||||
_g->words.w0 = (_SHIFTL((c),24,8)|_SHIFTL(((len)-1)/8,19,5)| \
|
||||
_SHIFTL((ofs)/8,8,8)|_SHIFTL((idx),0,8)); \
|
||||
_g->words.w1 = (uintptr_t)(adrs); \
|
||||
_g->words.w1 = (unsigned int)(adrs); \
|
||||
}
|
||||
|
||||
#define gsDma2p(c, adrs, len, idx, ofs) \
|
||||
{ \
|
||||
(_SHIFTL((c),24,8)|_SHIFTL(((len)-1)/8,19,5)| \
|
||||
_SHIFTL((ofs)/8,8,8)|_SHIFTL((idx),0,8)), \
|
||||
(uintptr_t)(adrs) \
|
||||
(unsigned int)(adrs) \
|
||||
}
|
||||
|
||||
#define gSPNoOp(pkt) gDma0p(pkt, G_SPNOOP, 0, 0)
|
||||
@@ -1759,12 +1727,12 @@ typedef union {
|
||||
Gfx *_g = (Gfx *)(pkt); \
|
||||
\
|
||||
_g->words.w0 = _SHIFTL((c), 24, 8); \
|
||||
_g->words.w1 = (uintptr_t)(p0); \
|
||||
_g->words.w1 = (unsigned int)(p0); \
|
||||
}
|
||||
|
||||
#define gsImmp1(c, p0) \
|
||||
{ \
|
||||
_SHIFTL((c), 24, 8), (uintptr_t)(p0) \
|
||||
_SHIFTL((c), 24, 8), (unsigned int)(p0) \
|
||||
}
|
||||
|
||||
#define gImmp2(pkt, c, p0, p1) \
|
||||
@@ -1801,13 +1769,13 @@ typedef union {
|
||||
\
|
||||
_g->words.w0 = (_SHIFTL((c), 24, 8) | _SHIFTL((p0), 8, 16) | \
|
||||
_SHIFTL((p1), 0, 8)); \
|
||||
_g->words.w1 = (uintptr_t) (dat); \
|
||||
_g->words.w1 = (unsigned int) (dat); \
|
||||
}
|
||||
|
||||
#define gsImmp21(c, p0, p1, dat) \
|
||||
{ \
|
||||
_SHIFTL((c), 24, 8) | _SHIFTL((p0), 8, 16) | _SHIFTL((p1), 0, 8), \
|
||||
(uintptr_t) (dat) \
|
||||
(unsigned int) (dat) \
|
||||
}
|
||||
|
||||
#define gMoveWd(pkt, index, offset, data) \
|
||||
@@ -1950,7 +1918,7 @@ typedef union {
|
||||
\
|
||||
_g->words.w0 = _SHIFTL(G_CULLDL, 24, 8) | \
|
||||
((0x0f & (vstart))*40); \
|
||||
_g->words.w1 = (uintptr_t)((0x0f & ((vend)+1))*40); \
|
||||
_g->words.w1 = (unsigned int)((0x0f & ((vend)+1))*40); \
|
||||
}
|
||||
|
||||
// Removed in PD
|
||||
@@ -2271,12 +2239,12 @@ typedef union {
|
||||
Gfx *_g = (Gfx *)(pkt); \
|
||||
\
|
||||
_g->words.w0 = _SHIFTL(G_SETGEOMETRYMODE, 24, 8); \
|
||||
_g->words.w1 = (uintptr_t)(word); \
|
||||
_g->words.w1 = (unsigned int)(word); \
|
||||
}
|
||||
|
||||
#define gsSPSetGeometryMode(word) \
|
||||
{ \
|
||||
_SHIFTL(G_SETGEOMETRYMODE, 24, 8), (uintptr_t)(word) \
|
||||
_SHIFTL(G_SETGEOMETRYMODE, 24, 8), (unsigned int)(word) \
|
||||
}
|
||||
|
||||
#define gSPClearGeometryMode(pkt, word) \
|
||||
@@ -2284,12 +2252,12 @@ typedef union {
|
||||
Gfx *_g = (Gfx *)(pkt); \
|
||||
\
|
||||
_g->words.w0 = _SHIFTL(G_CLEARGEOMETRYMODE, 24, 8); \
|
||||
_g->words.w1 = (uintptr_t)(word); \
|
||||
_g->words.w1 = (unsigned int)(word); \
|
||||
}
|
||||
|
||||
#define gsSPClearGeometryMode(word) \
|
||||
{ \
|
||||
_SHIFTL(G_CLEARGEOMETRYMODE, 24, 8), (uintptr_t)(word) \
|
||||
_SHIFTL(G_CLEARGEOMETRYMODE, 24, 8), (unsigned int)(word) \
|
||||
}
|
||||
|
||||
#define gSPSetOtherMode(pkt, cmd, sft, len, data) \
|
||||
@@ -2298,13 +2266,13 @@ typedef union {
|
||||
\
|
||||
_g->words.w0 = (_SHIFTL(cmd, 24, 8) | _SHIFTL(sft, 8, 8) | \
|
||||
_SHIFTL(len, 0, 8)); \
|
||||
_g->words.w1 = (uintptr_t)(data); \
|
||||
_g->words.w1 = (unsigned int)(data); \
|
||||
}
|
||||
|
||||
#define gsSPSetOtherMode(cmd, sft, len, data) \
|
||||
{ \
|
||||
_SHIFTL(cmd, 24, 8) | _SHIFTL(sft, 8, 8) | _SHIFTL(len, 0, 8), \
|
||||
(uintptr_t)(data) \
|
||||
(unsigned int)(data) \
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2355,14 +2323,14 @@ typedef union {
|
||||
\
|
||||
_g->words.w0 = _SHIFTL(cmd, 24, 8) | _SHIFTL(fmt, 21, 3) | \
|
||||
_SHIFTL(siz, 19, 2) | _SHIFTL((width)-1, 0, 12); \
|
||||
_g->words.w1 = (uintptr_t)(i); \
|
||||
_g->words.w1 = (unsigned int)(i); \
|
||||
}
|
||||
|
||||
#define gsSetImage(cmd, fmt, siz, width, i) \
|
||||
{ \
|
||||
_SHIFTL(cmd, 24, 8) | _SHIFTL(fmt, 21, 3) | \
|
||||
_SHIFTL(siz, 19, 2) | _SHIFTL((width)-1, 0, 12), \
|
||||
(uintptr_t)(i) \
|
||||
(unsigned int)(i) \
|
||||
}
|
||||
|
||||
#define gDPSetColorImage(pkt, f, s, w, i) gSetImage(pkt, G_SETCIMG, f, s, w, i)
|
||||
@@ -2388,13 +2356,13 @@ typedef union {
|
||||
Gfx *_g = (Gfx *)(pkt); \
|
||||
\
|
||||
_g->words.w0 = _SHIFTL(G_SETCOMBINE, 24, 8) | _SHIFTL(muxs0, 0, 24); \
|
||||
_g->words.w1 = (uintptr_t)(muxs1); \
|
||||
_g->words.w1 = (unsigned int)(muxs1); \
|
||||
}
|
||||
|
||||
#define gsDPSetCombine(muxs0, muxs1) \
|
||||
{ \
|
||||
_SHIFTL(G_SETCOMBINE, 24, 8) | _SHIFTL(muxs0, 0, 24), \
|
||||
(uintptr_t)(muxs1) \
|
||||
(unsigned int)(muxs1) \
|
||||
}
|
||||
|
||||
#define GCCc0w0(saRGB0, mRGB0, saA0, mA0) \
|
||||
@@ -2467,12 +2435,12 @@ typedef union {
|
||||
Gfx *_g = (Gfx *)(pkt); \
|
||||
\
|
||||
_g->words.w0 = _SHIFTL(c, 24, 8); \
|
||||
_g->words.w1 = (uintptr_t)(d); \
|
||||
_g->words.w1 = (unsigned int)(d); \
|
||||
}
|
||||
|
||||
#define gsDPSetColor(c, d) \
|
||||
{ \
|
||||
_SHIFTL(c, 24, 8), (uintptr_t)(d) \
|
||||
_SHIFTL(c, 24, 8), (unsigned int)(d) \
|
||||
}
|
||||
|
||||
#define DPRGBColor(pkt, cmd, r, g, b, a) \
|
||||
@@ -2553,13 +2521,13 @@ typedef union {
|
||||
Gfx *_g = (Gfx *)(pkt); \
|
||||
\
|
||||
_g->words.w0 = _SHIFTL(G_RDPSETOTHERMODE,24,8)|_SHIFTL(mode0,0,24); \
|
||||
_g->words.w1 = (uintptr_t)(mode1); \
|
||||
_g->words.w1 = (unsigned int)(mode1); \
|
||||
}
|
||||
|
||||
#define gsDPSetOtherMode(mode0, mode1) \
|
||||
{ \
|
||||
_SHIFTL(G_RDPSETOTHERMODE,24,8)|_SHIFTL(mode0,0,24), \
|
||||
(uintptr_t)(mode1) \
|
||||
(unsigned int)(mode1) \
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@
|
||||
#define OS_M_PI 3.14159265358979323846
|
||||
#define M_DTOR (3.14159265358979323846/180.0)
|
||||
|
||||
#define FTOFIX32(x) (int)((x) * (float)0x00010000)
|
||||
#define FTOFIX32(x) (long)((x) * (float)0x00010000)
|
||||
#define FIX32TOF(x) ((float)(x) * (1.0f / (float)0x00010000))
|
||||
#define FTOFRAC8(x) ((int) MIN(((x) * (128.0f)), 127.0f) & 0xff)
|
||||
|
||||
|
||||
+1
-12
@@ -28,7 +28,6 @@ extern "C" {
|
||||
|
||||
#include <PR/ultratypes.h>
|
||||
#include <PR/mbi.h>
|
||||
#include "platform.h"
|
||||
|
||||
struct var8009c340 {
|
||||
u8 surround;
|
||||
@@ -257,7 +256,7 @@ typedef struct {
|
||||
ALOscStop stopOsc;
|
||||
ALSeqMarker *loopStart;
|
||||
ALSeqMarker *loopEnd;
|
||||
intptr_t loopCount; /* -1 = loop forever, 0 = no loop */
|
||||
s32 loopCount; /* -1 = loop forever, 0 = no loop */
|
||||
u8 unk88;
|
||||
u8 unk89;
|
||||
} N_ALSeqPlayer;
|
||||
@@ -285,19 +284,9 @@ typedef struct {
|
||||
ALOscInit initOsc;
|
||||
ALOscUpdate updateOsc;
|
||||
ALOscStop stopOsc;
|
||||
|
||||
#ifdef PLATFORM_64BIT
|
||||
s32 _pad1_;
|
||||
f32 unk7c;
|
||||
s32 _pad2_;
|
||||
f32 unk80;
|
||||
#else
|
||||
f32 unk7c;
|
||||
f32 unk80;
|
||||
#endif
|
||||
|
||||
void *queue;
|
||||
|
||||
u8 unk88;
|
||||
u8 unk89;
|
||||
} N_ALCSPlayer;
|
||||
|
||||
@@ -31,14 +31,10 @@
|
||||
#define _OS_LIBC_H_
|
||||
|
||||
#include "os_pfs.h"
|
||||
#include "platform.h"
|
||||
|
||||
#ifndef PLATFORM_N64
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
#ifdef PLATFORM_OSX
|
||||
#include <strings.h>
|
||||
#endif
|
||||
|
||||
#ifdef _LANGUAGE_C_PLUS_PLUS
|
||||
extern "C" {
|
||||
@@ -88,11 +84,9 @@ extern "C" {
|
||||
|
||||
/* byte string operations */
|
||||
|
||||
#ifndef PLATFORM_OSX
|
||||
extern void bcopy(const void *, void *, size_t);
|
||||
extern int bcmp(const void *, const void *, size_t);
|
||||
extern void bzero(void *, size_t);
|
||||
#endif
|
||||
|
||||
/* Printf */
|
||||
|
||||
|
||||
+2
-2
@@ -37,7 +37,7 @@ extern "C" {
|
||||
#include <PR/ultratypes.h>
|
||||
#include "os_thread.h"
|
||||
#include "os_message.h"
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
#if defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS)
|
||||
|
||||
@@ -198,7 +198,7 @@ extern u32 osPiGetStatus(void);
|
||||
extern s32 osPiGetDeviceType(void);
|
||||
extern s32 osPiWriteIo(u32, u32);
|
||||
extern s32 osPiReadIo(u32, u32 *);
|
||||
extern s32 osPiStartDma(OSIoMesg *, s32, s32, uintptr_t, void *, u32,
|
||||
extern s32 osPiStartDma(OSIoMesg *, s32, s32, u32, void *, u32,
|
||||
OSMesgQueue *);
|
||||
extern void osCreatePiManager(OSPri, OSMesgQueue *, OSMesg *, s32);
|
||||
|
||||
|
||||
Vendored
+10
@@ -0,0 +1,10 @@
|
||||
#ifndef _WIN32
|
||||
#ifndef _POSIX_C_SOURCE
|
||||
#define _POSIX_C_SOURCE 200809L
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define ENET_IMPLEMENTATION 1
|
||||
#define ENET_NO_PRAGMA_LINK 1
|
||||
|
||||
#include "external/enet.h"
|
||||
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
#define MINIMP3_IMPLEMENTATION
|
||||
#include "external/minimp3.h"
|
||||
@@ -44,15 +44,15 @@ void gfx_start_frame(void);
|
||||
void gfx_run(Gfx* commands);
|
||||
void gfx_end_frame(void);
|
||||
void gfx_set_target_fps(int);
|
||||
void gfx_set_texture_filter(enum FilteringMode mode);
|
||||
void gfx_set_mipmap_filter(enum MipmapFilteringMode mode);
|
||||
void gfx_set_maximum_frame_latency(int latency);
|
||||
void gfx_texture_cache_clear(void);
|
||||
void gfx_texture_cache_delete(const uint8_t *orig_addr);
|
||||
void gfx_texture_cache_delete_range(const uint8_t *start, const uint8_t *end);
|
||||
int gfx_create_framebuffer(uint32_t width, uint32_t height, int upscale, int autoresize);
|
||||
void gfx_resize_framebuffer(int fb, uint32_t width, uint32_t height, int upscale, int autoresize);
|
||||
void gfx_set_framebuffer(int fb, float noise_scale) ;
|
||||
void gfx_reset_framebuffer(void);
|
||||
void gfx_copy_framebuffer(int fb_dst, int fb_src, int left, int top, int use_back);
|
||||
void gfx_get_pixel_depth_prepare(float x, float y);
|
||||
uint16_t gfx_get_pixel_depth(float x, float y);
|
||||
|
||||
#endif
|
||||
+202
-341
@@ -32,7 +32,6 @@ struct ShaderProgram {
|
||||
uint8_t num_attribs;
|
||||
GLint frame_count_location;
|
||||
GLint noise_scale_location;
|
||||
GLint three_point_filter_locations[2];
|
||||
};
|
||||
|
||||
struct Framebuffer {
|
||||
@@ -54,15 +53,10 @@ static uint32_t frame_count;
|
||||
static std::vector<Framebuffer> framebuffers;
|
||||
static size_t current_framebuffer;
|
||||
static float current_noise_scale;
|
||||
static int current_anisotropy_level;
|
||||
static FilteringMode current_filter_mode = FILTER_LINEAR;
|
||||
static MipmapFilteringMode current_mipmap_filter_mode = MIPMAP_LINEAR;
|
||||
static bool current_textures_linear_filter[2] = {false, false};
|
||||
|
||||
static int gl_glsl_version = 130;
|
||||
static char gl_glsl_version_str[16] = "130";
|
||||
static GLenum gl_mirror_clamp = GL_MIRROR_CLAMP_TO_EDGE;
|
||||
static bool gl_es = false;
|
||||
|
||||
static bool gl_core_profile = false;
|
||||
|
||||
static int gfx_opengl_get_max_texture_size() {
|
||||
@@ -100,12 +94,6 @@ static void gfx_opengl_set_uniforms(struct ShaderProgram* prg) {
|
||||
if (prg->noise_scale_location >= 0) {
|
||||
glUniform1f(prg->noise_scale_location, current_noise_scale);
|
||||
}
|
||||
if (prg->three_point_filter_locations[0] >= 0) {
|
||||
glUniform1i(prg->three_point_filter_locations[0], current_textures_linear_filter[0]);
|
||||
}
|
||||
if (prg->three_point_filter_locations[1] >= 0) {
|
||||
glUniform1i(prg->three_point_filter_locations[1], current_textures_linear_filter[1]);
|
||||
}
|
||||
}
|
||||
|
||||
static void gfx_opengl_unload_shader(struct ShaderProgram* old_prg) {
|
||||
@@ -246,138 +234,144 @@ static struct ShaderProgram* gfx_opengl_create_and_load_new_shader(uint64_t shad
|
||||
size_t num_floats = 4;
|
||||
|
||||
// Vertex shader
|
||||
|
||||
vs_len += sprintf(vs_buf + vs_len, "#version %s\n", gl_glsl_version_str);
|
||||
|
||||
if (gl_es) {
|
||||
append_line(vs_buf, &vs_len, "precision mediump float;");
|
||||
}
|
||||
|
||||
if (gl_glsl_version >= 130) {
|
||||
append_line(vs_buf, &vs_len, "#define INPUT in");
|
||||
append_line(vs_buf, &vs_len, "#define OUTPUT out");
|
||||
} else {
|
||||
append_line(vs_buf, &vs_len, "#define INPUT attribute");
|
||||
append_line(vs_buf, &vs_len, "#define OUTPUT varying");
|
||||
}
|
||||
|
||||
append_line(vs_buf, &vs_len, "INPUT vec4 aVtxPos;");
|
||||
|
||||
#ifdef __APPLE__
|
||||
append_line(vs_buf, &vs_len, "#version 410 core");
|
||||
append_line(vs_buf, &vs_len, "in vec4 aVtxPos;");
|
||||
#else
|
||||
append_line(vs_buf, &vs_len, "#version 110");
|
||||
append_line(vs_buf, &vs_len, "attribute vec4 aVtxPos;");
|
||||
#endif
|
||||
for (int i = 0; i < 2; i++) {
|
||||
if (cc_features.used_textures[i]) {
|
||||
vs_len += sprintf(vs_buf + vs_len, "INPUT vec2 aTexCoord%d;\n", i);
|
||||
vs_len += sprintf(vs_buf + vs_len, "OUTPUT vec2 vTexCoord%d;\n", i);
|
||||
#ifdef __APPLE__
|
||||
vs_len += sprintf(vs_buf + vs_len, "in vec2 aTexCoord%d;\n", i);
|
||||
vs_len += sprintf(vs_buf + vs_len, "out vec2 vTexCoord%d;\n", i);
|
||||
#else
|
||||
vs_len += sprintf(vs_buf + vs_len, "attribute vec2 aTexCoord%d;\n", i);
|
||||
vs_len += sprintf(vs_buf + vs_len, "varying vec2 vTexCoord%d;\n", i);
|
||||
#endif
|
||||
num_floats += 2;
|
||||
for (int j = 0; j < 2; j++) {
|
||||
if (cc_features.clamp[i][j]) {
|
||||
vs_len += sprintf(vs_buf + vs_len, "INPUT float aTexClamp%s%d;\n", j == 0 ? "S" : "T", i);
|
||||
vs_len += sprintf(vs_buf + vs_len, "OUTPUT float vTexClamp%s%d;\n", j == 0 ? "S" : "T", i);
|
||||
#ifdef __APPLE__
|
||||
vs_len += sprintf(vs_buf + vs_len, "in float aTexClamp%s%d;\n", j == 0 ? "S" : "T", i);
|
||||
vs_len += sprintf(vs_buf + vs_len, "out float vTexClamp%s%d;\n", j == 0 ? "S" : "T", i);
|
||||
#else
|
||||
vs_len += sprintf(vs_buf + vs_len, "attribute float aTexClamp%s%d;\n", j == 0 ? "S" : "T", i);
|
||||
vs_len += sprintf(vs_buf + vs_len, "varying float vTexClamp%s%d;\n", j == 0 ? "S" : "T", i);
|
||||
#endif
|
||||
num_floats += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cc_features.opt_fog) {
|
||||
append_line(vs_buf, &vs_len, "INPUT vec4 aFog;");
|
||||
append_line(vs_buf, &vs_len, "OUTPUT vec4 vFog;");
|
||||
#ifdef __APPLE__
|
||||
append_line(vs_buf, &vs_len, "in vec4 aFog;");
|
||||
append_line(vs_buf, &vs_len, "out vec4 vFog;");
|
||||
#else
|
||||
append_line(vs_buf, &vs_len, "attribute vec4 aFog;");
|
||||
append_line(vs_buf, &vs_len, "varying vec4 vFog;");
|
||||
#endif
|
||||
num_floats += 4;
|
||||
}
|
||||
|
||||
if (cc_features.opt_grayscale) {
|
||||
append_line(vs_buf, &vs_len, "INPUT vec4 aGrayscaleColor;");
|
||||
append_line(vs_buf, &vs_len, "OUTPUT vec4 vGrayscaleColor;");
|
||||
#ifdef __APPLE__
|
||||
append_line(vs_buf, &vs_len, "in vec4 aGrayscaleColor;");
|
||||
append_line(vs_buf, &vs_len, "out vec4 vGrayscaleColor;");
|
||||
#else
|
||||
append_line(vs_buf, &vs_len, "attribute vec4 aGrayscaleColor;");
|
||||
append_line(vs_buf, &vs_len, "varying vec4 vGrayscaleColor;");
|
||||
#endif
|
||||
num_floats += 4;
|
||||
}
|
||||
|
||||
for (int i = 0; i < cc_features.num_inputs; i++) {
|
||||
vs_len += sprintf(vs_buf + vs_len, "INPUT vec%d aInput%d;\n", cc_features.opt_alpha ? 4 : 3, i + 1);
|
||||
vs_len += sprintf(vs_buf + vs_len, "OUTPUT vec%d vInput%d;\n", cc_features.opt_alpha ? 4 : 3, i + 1);
|
||||
#ifdef __APPLE__
|
||||
vs_len += sprintf(vs_buf + vs_len, "in vec%d aInput%d;\n", cc_features.opt_alpha ? 4 : 3, i + 1);
|
||||
vs_len += sprintf(vs_buf + vs_len, "out vec%d vInput%d;\n", cc_features.opt_alpha ? 4 : 3, i + 1);
|
||||
#else
|
||||
vs_len += sprintf(vs_buf + vs_len, "attribute vec%d aInput%d;\n", cc_features.opt_alpha ? 4 : 3, i + 1);
|
||||
vs_len += sprintf(vs_buf + vs_len, "varying vec%d vInput%d;\n", cc_features.opt_alpha ? 4 : 3, i + 1);
|
||||
#endif
|
||||
num_floats += cc_features.opt_alpha ? 4 : 3;
|
||||
}
|
||||
|
||||
append_line(vs_buf, &vs_len, "void main() {");
|
||||
for (int i = 0; i < 2; i++) {
|
||||
if (cc_features.used_textures[i]) {
|
||||
vs_len += sprintf(vs_buf + vs_len, " vTexCoord%d = aTexCoord%d;\n", i, i);
|
||||
vs_len += sprintf(vs_buf + vs_len, "vTexCoord%d = aTexCoord%d;\n", i, i);
|
||||
for (int j = 0; j < 2; j++) {
|
||||
if (cc_features.clamp[i][j]) {
|
||||
vs_len += sprintf(vs_buf + vs_len, " vTexClamp%s%d = aTexClamp%s%d;\n", j == 0 ? "S" : "T", i,
|
||||
vs_len += sprintf(vs_buf + vs_len, "vTexClamp%s%d = aTexClamp%s%d;\n", j == 0 ? "S" : "T", i,
|
||||
j == 0 ? "S" : "T", i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cc_features.opt_fog) {
|
||||
append_line(vs_buf, &vs_len, " vFog = aFog;");
|
||||
append_line(vs_buf, &vs_len, "vFog = aFog;");
|
||||
}
|
||||
if (cc_features.opt_grayscale) {
|
||||
append_line(vs_buf, &vs_len, " vGrayscaleColor = aGrayscaleColor;");
|
||||
append_line(vs_buf, &vs_len, "vGrayscaleColor = aGrayscaleColor;");
|
||||
}
|
||||
for (int i = 0; i < cc_features.num_inputs; i++) {
|
||||
vs_len += sprintf(vs_buf + vs_len, " vInput%d = aInput%d;\n", i + 1, i + 1);
|
||||
}
|
||||
|
||||
append_line(vs_buf, &vs_len, " gl_Position = aVtxPos;");
|
||||
if (!GLAD_GL_ARB_depth_clamp) {
|
||||
// HACK: workaround for no GL_DEPTH_CLAMP
|
||||
append_line(vs_buf, &vs_len, " gl_Position.z *= 0.3f;");
|
||||
vs_len += sprintf(vs_buf + vs_len, "vInput%d = aInput%d;\n", i + 1, i + 1);
|
||||
}
|
||||
append_line(vs_buf, &vs_len, "gl_Position = aVtxPos;");
|
||||
append_line(vs_buf, &vs_len, "}");
|
||||
|
||||
// Fragment shader
|
||||
|
||||
fs_len += sprintf(fs_buf + fs_len, "#version %s\n", gl_glsl_version_str);
|
||||
|
||||
if (gl_es) {
|
||||
append_line(fs_buf, &fs_len, "precision mediump float;");
|
||||
}
|
||||
|
||||
if (gl_glsl_version >= 130) {
|
||||
append_line(fs_buf, &fs_len, "#define INPUT in");
|
||||
append_line(fs_buf, &fs_len, "#define OUTPUT_COLOR outColor");
|
||||
append_line(fs_buf, &fs_len, "#define SAMPLE_TEX(tex, uv) texture(tex, uv)");
|
||||
} else {
|
||||
append_line(fs_buf, &fs_len, "#define INPUT varying");
|
||||
append_line(fs_buf, &fs_len, "#define OUTPUT_COLOR gl_FragColor");
|
||||
append_line(fs_buf, &fs_len, "#define SAMPLE_TEX(tex, uv) texture2D(tex, uv)");
|
||||
}
|
||||
|
||||
// Reference approach to color wrapping as per GLideN64
|
||||
// Return wrapped value of x in interval [low, high)
|
||||
append_line(fs_buf, &fs_len, "#define WRAP(x, low, high) mod((x)-(low), (high)-(low)) + (low)");
|
||||
|
||||
append_line(fs_buf, &fs_len, "#define TEX_OFFSET(tex, uv, texSize, off) SAMPLE_TEX(tex, uv - (off)/texSize)");
|
||||
|
||||
#ifdef __APPLE__
|
||||
append_line(fs_buf, &fs_len, "#version 410 core");
|
||||
#else
|
||||
append_line(fs_buf, &fs_len, "#version 130");
|
||||
#endif
|
||||
// append_line(fs_buf, &fs_len, "precision mediump float;");
|
||||
for (int i = 0; i < 2; i++) {
|
||||
if (cc_features.used_textures[i]) {
|
||||
fs_len += sprintf(fs_buf + fs_len, "INPUT vec2 vTexCoord%d;\n", i);
|
||||
#ifdef __APPLE__
|
||||
fs_len += sprintf(fs_buf + fs_len, "in vec2 vTexCoord%d;\n", i);
|
||||
#else
|
||||
fs_len += sprintf(fs_buf + fs_len, "varying vec2 vTexCoord%d;\n", i);
|
||||
#endif
|
||||
for (int j = 0; j < 2; j++) {
|
||||
if (cc_features.clamp[i][j]) {
|
||||
fs_len += sprintf(fs_buf + fs_len, "INPUT float vTexClamp%s%d;\n", j == 0 ? "S" : "T", i);
|
||||
#ifdef __APPLE__
|
||||
fs_len += sprintf(fs_buf + fs_len, "in float vTexClamp%s%d;\n", j == 0 ? "S" : "T", i);
|
||||
#else
|
||||
fs_len += sprintf(fs_buf + fs_len, "varying float vTexClamp%s%d;\n", j == 0 ? "S" : "T", i);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cc_features.opt_fog) {
|
||||
append_line(fs_buf, &fs_len, "INPUT vec4 vFog;");
|
||||
#ifdef __APPLE__
|
||||
append_line(fs_buf, &fs_len, "in vec4 vFog;");
|
||||
#else
|
||||
append_line(fs_buf, &fs_len, "varying vec4 vFog;");
|
||||
#endif
|
||||
}
|
||||
if (cc_features.opt_grayscale) {
|
||||
append_line(fs_buf, &fs_len, "INPUT vec4 vGrayscaleColor;");
|
||||
#ifdef __APPLE__
|
||||
append_line(fs_buf, &fs_len, "in vec4 vGrayscaleColor;");
|
||||
#else
|
||||
append_line(fs_buf, &fs_len, "varying vec4 vGrayscaleColor;");
|
||||
#endif
|
||||
}
|
||||
for (int i = 0; i < cc_features.num_inputs; i++) {
|
||||
fs_len += sprintf(fs_buf + fs_len, "INPUT vec%d vInput%d;\n", cc_features.opt_alpha ? 4 : 3, i + 1);
|
||||
#ifdef __APPLE__
|
||||
fs_len += sprintf(fs_buf + fs_len, "in vec%d vInput%d;\n", cc_features.opt_alpha ? 4 : 3, i + 1);
|
||||
#else
|
||||
fs_len += sprintf(fs_buf + fs_len, "varying vec%d vInput%d;\n", cc_features.opt_alpha ? 4 : 3, i + 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (cc_features.used_textures[0]) {
|
||||
append_line(fs_buf, &fs_len, "uniform sampler2D uTex0;");
|
||||
if (current_filter_mode == FILTER_THREE_POINT)
|
||||
append_line(fs_buf, &fs_len, "uniform int three_point_filter0;");
|
||||
}
|
||||
if (cc_features.used_textures[1]) {
|
||||
append_line(fs_buf, &fs_len, "uniform sampler2D uTex1;");
|
||||
if (current_filter_mode == FILTER_THREE_POINT)
|
||||
append_line(fs_buf, &fs_len, "uniform int three_point_filter1;");
|
||||
}
|
||||
|
||||
append_line(fs_buf, &fs_len, "uniform int frame_count;");
|
||||
@@ -388,97 +382,92 @@ static struct ShaderProgram* gfx_opengl_create_and_load_new_shader(uint64_t shad
|
||||
append_line(fs_buf, &fs_len, " return fract(sin(random) * 143758.5453);");
|
||||
append_line(fs_buf, &fs_len, "}");
|
||||
|
||||
if (current_filter_mode == FILTER_THREE_POINT) {
|
||||
append_line(fs_buf, &fs_len, "vec4 filter3point(in sampler2D tex, in vec2 texCoord, in vec2 texSize) {");
|
||||
append_line(fs_buf, &fs_len, " vec2 offset = fract(texCoord*texSize - vec2(0.5));");
|
||||
append_line(fs_buf, &fs_len, " offset -= step(1.0, offset.x + offset.y);");
|
||||
append_line(fs_buf, &fs_len, " vec4 c0 = TEX_OFFSET(tex, texCoord, texSize, offset);");
|
||||
append_line(fs_buf, &fs_len, " vec4 c1 = TEX_OFFSET(tex, texCoord, texSize, vec2(offset.x - sign(offset.x), offset.y));");
|
||||
append_line(fs_buf, &fs_len, " vec4 c2 = TEX_OFFSET(tex, texCoord, texSize, vec2(offset.x, offset.y - sign(offset.y)));");
|
||||
append_line(fs_buf, &fs_len, " return c0 + abs(offset.x)*(c1-c0) + abs(offset.y)*(c2-c0);");
|
||||
append_line(fs_buf, &fs_len, "}");
|
||||
}
|
||||
|
||||
if (cc_features.opt_blur) {
|
||||
// blur filter, used for menu backgrounds
|
||||
// used to be two for loops from 0 to 4, but apparently intel drivers crashed trying to unroll it
|
||||
// used to have a const weight array, but apparently drivers for the GT620 don't like const array initializers
|
||||
|
||||
if (current_filter_mode == FILTER_THREE_POINT)
|
||||
append_line(fs_buf, &fs_len, "lowp vec4 hookTexture2D(in sampler2D t, in vec2 uv, in vec2 texSize, in int three_point_filter) {");
|
||||
else
|
||||
append_line(fs_buf, &fs_len, "lowp vec4 hookTexture2D(in sampler2D t, in vec2 uv, in vec2 texSize) {");
|
||||
|
||||
append_line(fs_buf, &fs_len, " lowp vec4 cw = vec4(0.0);");
|
||||
append_line(fs_buf, &fs_len, " for (int i = 0; i < 16; ++i) {");
|
||||
append_line(fs_buf, &fs_len, " vec2 xy = vec2(float(i & 3), float(i >> 2));");
|
||||
append_line(fs_buf, &fs_len, " lowp float w = 0.009947 - length(xy) * 0.001;");
|
||||
append_line(fs_buf, &fs_len, " vec2 scaled_uv = uv + (vec2(-1.5) + xy) / texSize;");
|
||||
|
||||
if (current_filter_mode == FILTER_THREE_POINT)
|
||||
append_line(fs_buf, &fs_len, " lowp vec4 tex = mix(SAMPLE_TEX(t, scaled_uv), filter3point(t, scaled_uv, texSize), three_point_filter);");
|
||||
else
|
||||
append_line(fs_buf, &fs_len, " lowp vec4 tex = SAMPLE_TEX(t, scaled_uv);");
|
||||
|
||||
append_line(fs_buf, &fs_len, " cw += vec4(tex.rgb * w, w);");
|
||||
append_line(fs_buf, &fs_len, " }");
|
||||
append_line(fs_buf, &fs_len, " return vec4(cw.rgb / cw.a, 1.0);");
|
||||
append_line(fs_buf, &fs_len, R"(
|
||||
lowp vec4 hookTexture2D(in sampler2D t, in vec2 uv, in vec2 tsize) {
|
||||
lowp vec4 cw = vec4(0.0);
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
vec2 xy = vec2(float(i & 3), float(i >> 2));
|
||||
lowp float w = 0.009947 - length(xy) * 0.001;
|
||||
cw += vec4(texture2D(t, uv + (vec2(-1.5) + xy) / tsize).rgb * w, w);
|
||||
}
|
||||
return vec4(cw.rgb / cw.a, 1.0);
|
||||
})"
|
||||
);
|
||||
} else if (current_filter_mode == FILTER_THREE_POINT) {
|
||||
#if __APPLE__
|
||||
append_line(fs_buf, &fs_len, "#define TEX_OFFSET(off) texture(tex, texCoord - (off)/texSize)");
|
||||
#else
|
||||
append_line(fs_buf, &fs_len, "#define TEX_OFFSET(off) texture2D(tex, texCoord - (off)/texSize)");
|
||||
#endif
|
||||
append_line(fs_buf, &fs_len, "vec4 filter3point(in sampler2D tex, in vec2 texCoord, in vec2 texSize) {");
|
||||
append_line(fs_buf, &fs_len, " vec2 offset = fract(texCoord*texSize - vec2(0.5));");
|
||||
append_line(fs_buf, &fs_len, " offset -= step(1.0, offset.x + offset.y);");
|
||||
append_line(fs_buf, &fs_len, " vec4 c0 = TEX_OFFSET(offset);");
|
||||
append_line(fs_buf, &fs_len, " vec4 c1 = TEX_OFFSET(vec2(offset.x - sign(offset.x), offset.y));");
|
||||
append_line(fs_buf, &fs_len, " vec4 c2 = TEX_OFFSET(vec2(offset.x, offset.y - sign(offset.y)));");
|
||||
append_line(fs_buf, &fs_len, " return c0 + abs(offset.x)*(c1-c0) + abs(offset.y)*(c2-c0);");
|
||||
append_line(fs_buf, &fs_len, "}");
|
||||
append_line(fs_buf, &fs_len, "vec4 hookTexture2D(in sampler2D tex, in vec2 uv, in vec2 texSize) {");
|
||||
append_line(fs_buf, &fs_len, " return filter3point(tex, uv, texSize);");
|
||||
append_line(fs_buf, &fs_len, "}");
|
||||
} else {
|
||||
if (current_filter_mode == FILTER_THREE_POINT) {
|
||||
append_line(fs_buf, &fs_len, "vec4 hookTexture2D(in sampler2D tex, in vec2 uv, in vec2 texSize, in int three_point_filter) {");
|
||||
append_line(fs_buf, &fs_len, " return mix(SAMPLE_TEX(tex, uv), filter3point(tex, uv, texSize), three_point_filter);");
|
||||
append_line(fs_buf, &fs_len, "}");
|
||||
} else {
|
||||
append_line(fs_buf, &fs_len, "vec4 hookTexture2D(in sampler2D tex, in vec2 uv, in vec2 texSize) {");
|
||||
append_line(fs_buf, &fs_len, " return SAMPLE_TEX(tex, uv);");
|
||||
append_line(fs_buf, &fs_len, "}");
|
||||
}
|
||||
append_line(fs_buf, &fs_len, "vec4 hookTexture2D(in sampler2D tex, in vec2 uv, in vec2 texSize) {");
|
||||
#if __APPLE__
|
||||
append_line(fs_buf, &fs_len, " return texture(tex, uv);");
|
||||
#else
|
||||
append_line(fs_buf, &fs_len, " return texture2D(tex, uv);");
|
||||
#endif
|
||||
append_line(fs_buf, &fs_len, "}");
|
||||
}
|
||||
|
||||
if (gl_glsl_version >= 130) {
|
||||
append_line(fs_buf, &fs_len, "out vec4 outColor;");
|
||||
}
|
||||
#if __APPLE__
|
||||
append_line(fs_buf, &fs_len, "out vec4 outColor;");
|
||||
#endif
|
||||
|
||||
append_line(fs_buf, &fs_len, "void main() {");
|
||||
|
||||
// Reference approach to color wrapping as per GLideN64
|
||||
// Return wrapped value of x in interval [low, high)
|
||||
append_line(fs_buf, &fs_len, "#define WRAP(x, low, high) mod((x)-(low), (high)-(low)) + (low)");
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
if (cc_features.used_textures[i]) {
|
||||
bool s = cc_features.clamp[i][0], t = cc_features.clamp[i][1];
|
||||
|
||||
fs_len += sprintf(fs_buf + fs_len, " vec2 texSize%d = vec2(textureSize(uTex%d, 0));\n", i, i);
|
||||
fs_len += sprintf(fs_buf + fs_len, "vec2 texSize%d = textureSize(uTex%d, 0);\n", i, i);
|
||||
|
||||
if (!s && !t) {
|
||||
fs_len += sprintf(fs_buf + fs_len, " vec2 vTexCoordAdj%d = vTexCoord%d;\n", i, i);
|
||||
fs_len += sprintf(fs_buf + fs_len, "vec2 vTexCoordAdj%d = vTexCoord%d;\n", i, i);
|
||||
} else {
|
||||
if (s && t) {
|
||||
fs_len += sprintf(fs_buf + fs_len,
|
||||
" vec2 vTexCoordAdj%d = clamp(vTexCoord%d, 0.5 / texSize%d, "
|
||||
"vec2 vTexCoordAdj%d = clamp(vTexCoord%d, 0.5 / texSize%d, "
|
||||
"vec2(vTexClampS%d, vTexClampT%d));\n",
|
||||
i, i, i, i, i);
|
||||
} else if (s) {
|
||||
fs_len += sprintf(fs_buf + fs_len,
|
||||
" vec2 vTexCoordAdj%d = vec2(clamp(vTexCoord%d.s, 0.5 / "
|
||||
"vec2 vTexCoordAdj%d = vec2(clamp(vTexCoord%d.s, 0.5 / "
|
||||
"texSize%d.s, vTexClampS%d), vTexCoord%d.t);\n",
|
||||
i, i, i, i, i);
|
||||
} else {
|
||||
fs_len += sprintf(fs_buf + fs_len,
|
||||
" vec2 vTexCoordAdj%d = vec2(vTexCoord%d.s, clamp(vTexCoord%d.t, "
|
||||
"vec2 vTexCoordAdj%d = vec2(vTexCoord%d.s, clamp(vTexCoord%d.t, "
|
||||
"0.5 / texSize%d.t, vTexClampT%d));\n",
|
||||
i, i, i, i, i);
|
||||
}
|
||||
}
|
||||
|
||||
if (current_filter_mode == FILTER_THREE_POINT)
|
||||
fs_len += sprintf(fs_buf + fs_len, " vec4 texVal%d = hookTexture2D(uTex%d, vTexCoordAdj%d, texSize%d, three_point_filter%d);\n", i, i, i, i, i);
|
||||
else
|
||||
fs_len += sprintf(fs_buf + fs_len, " vec4 texVal%d = hookTexture2D(uTex%d, vTexCoordAdj%d, texSize%d);\n", i, i, i, i);
|
||||
fs_len += sprintf(fs_buf + fs_len, "vec4 texVal%d = hookTexture2D(uTex%d, vTexCoordAdj%d, texSize%d);\n", i, i, i, i);
|
||||
}
|
||||
}
|
||||
|
||||
append_line(fs_buf, &fs_len, cc_features.opt_alpha ? " vec4 texel;" : " vec3 texel;");
|
||||
append_line(fs_buf, &fs_len, cc_features.opt_alpha ? "vec4 texel;" : "vec3 texel;");
|
||||
for (int c = 0; c < (cc_features.opt_2cyc ? 2 : 1); c++) {
|
||||
append_str(fs_buf, &fs_len, " texel = ");
|
||||
append_str(fs_buf, &fs_len, "texel = ");
|
||||
if (!cc_features.color_alpha_same[c] && cc_features.opt_alpha) {
|
||||
append_str(fs_buf, &fs_len, "vec4(");
|
||||
append_formula(fs_buf, &fs_len, cc_features.c[c], cc_features.do_single[c][0],
|
||||
@@ -495,50 +484,56 @@ static struct ShaderProgram* gfx_opengl_create_and_load_new_shader(uint64_t shad
|
||||
append_line(fs_buf, &fs_len, ";");
|
||||
|
||||
if (c == 0) {
|
||||
append_line(fs_buf, &fs_len, " texel = WRAP(texel, -1.01, 1.01);");
|
||||
append_str(fs_buf, &fs_len, "texel = WRAP(texel, -1.01, 1.01);");
|
||||
}
|
||||
}
|
||||
|
||||
append_line(fs_buf, &fs_len, " texel = WRAP(texel, -0.51, 1.51);");
|
||||
append_line(fs_buf, &fs_len, " texel = clamp(texel, 0.0, 1.0);");
|
||||
append_str(fs_buf, &fs_len, "texel = WRAP(texel, -0.51, 1.51);");
|
||||
append_str(fs_buf, &fs_len, "texel = clamp(texel, 0.0, 1.0);");
|
||||
// TODO discard if alpha is 0?
|
||||
if (cc_features.opt_fog) {
|
||||
if (cc_features.opt_alpha) {
|
||||
append_line(fs_buf, &fs_len, " texel = vec4(mix(texel.rgb, vFog.rgb, vFog.a), texel.a);");
|
||||
append_line(fs_buf, &fs_len, "texel = vec4(mix(texel.rgb, vFog.rgb, vFog.a), texel.a);");
|
||||
} else {
|
||||
append_line(fs_buf, &fs_len, " texel = mix(texel, vFog.rgb, vFog.a);");
|
||||
append_line(fs_buf, &fs_len, "texel = mix(texel, vFog.rgb, vFog.a);");
|
||||
}
|
||||
}
|
||||
|
||||
if (cc_features.opt_texture_edge && cc_features.opt_alpha) {
|
||||
append_line(fs_buf, &fs_len, " if (texel.a > 0.19) texel.a = 1.0; else discard;");
|
||||
append_line(fs_buf, &fs_len, "if (texel.a > 0.19) texel.a = 1.0; else discard;");
|
||||
}
|
||||
|
||||
if (cc_features.opt_alpha && cc_features.opt_noise) {
|
||||
append_line(fs_buf, &fs_len,
|
||||
" texel.a *= floor(clamp(random(vec3(floor(gl_FragCoord.xy * noise_scale), float(frame_count))) + "
|
||||
"texel.a *= floor(clamp(random(vec3(floor(gl_FragCoord.xy * noise_scale), float(frame_count))) + "
|
||||
"texel.a, 0.0, 1.0));");
|
||||
}
|
||||
|
||||
if (cc_features.opt_grayscale) {
|
||||
append_line(fs_buf, &fs_len, " float intensity = (texel.r + texel.g + texel.b) / 3.0;");
|
||||
append_line(fs_buf, &fs_len, " vec3 new_texel = vGrayscaleColor.rgb * intensity;");
|
||||
append_line(fs_buf, &fs_len, " texel.rgb = mix(texel.rgb, new_texel, vGrayscaleColor.a);");
|
||||
append_line(fs_buf, &fs_len, "float intensity = (texel.r + texel.g + texel.b) / 3.0;");
|
||||
append_line(fs_buf, &fs_len, "vec3 new_texel = vGrayscaleColor.rgb * intensity;");
|
||||
append_line(fs_buf, &fs_len, "texel.rgb = mix(texel.rgb, new_texel, vGrayscaleColor.a);");
|
||||
}
|
||||
|
||||
if (cc_features.opt_alpha) {
|
||||
if (cc_features.opt_alpha_threshold) {
|
||||
append_line(fs_buf, &fs_len, " if (texel.a < 8.0 / 256.0) discard;");
|
||||
append_line(fs_buf, &fs_len, "if (texel.a < 8.0 / 256.0) discard;");
|
||||
}
|
||||
if (cc_features.opt_invisible) {
|
||||
append_line(fs_buf, &fs_len, " texel.a = 0.0;");
|
||||
append_line(fs_buf, &fs_len, "texel.a = 0.0;");
|
||||
}
|
||||
|
||||
append_line(fs_buf, &fs_len, " OUTPUT_COLOR = texel;");
|
||||
#if __APPLE__
|
||||
append_line(fs_buf, &fs_len, "outColor = texel;");
|
||||
#else
|
||||
append_line(fs_buf, &fs_len, "gl_FragColor = texel;");
|
||||
#endif
|
||||
} else {
|
||||
append_line(fs_buf, &fs_len, " OUTPUT_COLOR = vec4(texel, 1.0);");
|
||||
#if __APPLE__
|
||||
append_line(fs_buf, &fs_len, "outColor = vec4(texel, 1.0);");
|
||||
#else
|
||||
append_line(fs_buf, &fs_len, "gl_FragColor = vec4(texel, 1.0);");
|
||||
#endif
|
||||
}
|
||||
|
||||
append_line(fs_buf, &fs_len, "}");
|
||||
|
||||
vs_buf[vs_len] = '\0';
|
||||
@@ -579,11 +574,6 @@ static struct ShaderProgram* gfx_opengl_create_and_load_new_shader(uint64_t shad
|
||||
glAttachShader(shader_program, fragment_shader);
|
||||
glLinkProgram(shader_program);
|
||||
|
||||
glDetachShader(shader_program, vertex_shader);
|
||||
glDetachShader(shader_program, fragment_shader);
|
||||
glDeleteShader(vertex_shader);
|
||||
glDeleteShader(fragment_shader);
|
||||
|
||||
size_t cnt = 0;
|
||||
|
||||
struct ShaderProgram* prg = &shader_program_pool[make_pair(shader_id0, shader_id1)];
|
||||
@@ -650,8 +640,6 @@ static struct ShaderProgram* gfx_opengl_create_and_load_new_shader(uint64_t shad
|
||||
|
||||
prg->frame_count_location = glGetUniformLocation(shader_program, "frame_count");
|
||||
prg->noise_scale_location = glGetUniformLocation(shader_program, "noise_scale");
|
||||
prg->three_point_filter_locations[0] = glGetUniformLocation(shader_program, "three_point_filter0");
|
||||
prg->three_point_filter_locations[1] = glGetUniformLocation(shader_program, "three_point_filter1");
|
||||
|
||||
gfx_opengl_load_shader(prg);
|
||||
|
||||
@@ -669,14 +657,6 @@ static void gfx_opengl_shader_get_info(struct ShaderProgram* prg, uint8_t* num_i
|
||||
used_textures[1] = prg->used_textures[1];
|
||||
}
|
||||
|
||||
static void gfx_opengl_clear_shaders(void) {
|
||||
glUseProgram(0);
|
||||
for (auto& pair : shader_program_pool) {
|
||||
glDeleteProgram(pair.second.opengl_program_id);
|
||||
}
|
||||
shader_program_pool.clear();
|
||||
}
|
||||
|
||||
static GLuint gfx_opengl_new_texture(void) {
|
||||
GLuint ret;
|
||||
glGenTextures(1, &ret);
|
||||
@@ -687,18 +667,13 @@ static void gfx_opengl_delete_texture(uint32_t texID) {
|
||||
glDeleteTextures(1, &texID);
|
||||
}
|
||||
|
||||
static void gfx_opengl_select_texture(int tile, GLuint texture_id, bool linear_filter) {
|
||||
static void gfx_opengl_select_texture(int tile, GLuint texture_id) {
|
||||
glActiveTexture(GL_TEXTURE0 + tile);
|
||||
glBindTexture(GL_TEXTURE_2D, texture_id);
|
||||
|
||||
current_textures_linear_filter[tile] = linear_filter;
|
||||
}
|
||||
|
||||
static void gfx_opengl_upload_texture(const uint8_t* rgba32_buf, uint32_t width, uint32_t height, bool gen_mipmaps) {
|
||||
static void gfx_opengl_upload_texture(const uint8_t* rgba32_buf, uint32_t width, uint32_t height) {
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, rgba32_buf);
|
||||
if (gen_mipmaps || current_filter_mode == FILTER_THREE_POINT) {
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t gfx_cm_to_opengl(uint32_t val) {
|
||||
@@ -715,77 +690,37 @@ static uint32_t gfx_cm_to_opengl(uint32_t val) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void gfx_opengl_set_sampler_parameters(int tile, bool linear_filter, uint32_t cms, uint32_t cmt, bool mipmaps) {
|
||||
const GLint min_filters[3][3] = {
|
||||
// MIPMAP_DISABLED MIPMAP_NEAREST MIPMAP_LINEAR
|
||||
{ GL_NEAREST, GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR }, // FILTER_NONE
|
||||
{ GL_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR }, // FILTER_BILINEAR
|
||||
{ GL_NEAREST, GL_NEAREST, GL_NEAREST }, // FILTER_THREE_POINT
|
||||
};
|
||||
|
||||
mipmaps = mipmaps && (current_mipmap_filter_mode != MIPMAP_DISABLED);
|
||||
const int mip_idx = mipmaps ? current_mipmap_filter_mode : 0;
|
||||
const GLint min_filter = linear_filter ? min_filters[current_filter_mode][mip_idx] : GL_NEAREST;
|
||||
const GLint max_filter = linear_filter && (current_filter_mode == FILTER_LINEAR) ? GL_LINEAR : GL_NEAREST;
|
||||
|
||||
static void gfx_opengl_set_sampler_parameters(int tile, bool linear_filter, uint32_t cms, uint32_t cmt) {
|
||||
const GLint filter = linear_filter && (current_filter_mode == FILTER_LINEAR) ? GL_LINEAR : GL_NEAREST;
|
||||
glActiveTexture(GL_TEXTURE0 + tile);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, max_filter);
|
||||
|
||||
if (mipmaps) {
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY, current_anisotropy_level);
|
||||
}
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, gfx_cm_to_opengl(cms));
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, gfx_cm_to_opengl(cmt));
|
||||
}
|
||||
|
||||
static void gfx_opengl_set_depth_mode(bool depth_test, bool depth_update, bool depth_compare, bool depth_source_prim, uint16_t zmode) {
|
||||
if (depth_test) {
|
||||
static void gfx_opengl_set_depth_test_and_mask(bool depth_test, bool z_upd) {
|
||||
if (depth_test || z_upd) {
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthMask(depth_update ? GL_TRUE : GL_FALSE);
|
||||
current_depth_mask = depth_update;
|
||||
|
||||
if (depth_compare) {
|
||||
switch (zmode) {
|
||||
case ZMODE_INTER:
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
glDisable(GL_POLYGON_OFFSET_FILL);
|
||||
glPolygonOffset(0, 0);
|
||||
break;
|
||||
|
||||
case ZMODE_OPA:
|
||||
case ZMODE_XLU:
|
||||
if (depth_source_prim) {
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
} else {
|
||||
glDepthFunc(GL_LESS);
|
||||
}
|
||||
glDisable(GL_POLYGON_OFFSET_FILL);
|
||||
glPolygonOffset(0, 0);
|
||||
break;
|
||||
|
||||
case ZMODE_DEC:
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
glEnable(GL_POLYGON_OFFSET_FILL);
|
||||
glPolygonOffset(-2, -2);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
glDepthFunc(GL_ALWAYS);
|
||||
glDisable(GL_POLYGON_OFFSET_FILL);
|
||||
glPolygonOffset(0, 0);
|
||||
}
|
||||
glDepthMask(z_upd ? GL_TRUE : GL_FALSE);
|
||||
glDepthFunc(depth_test ? GL_LEQUAL : GL_ALWAYS);
|
||||
current_depth_mask = z_upd;
|
||||
} else {
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
}
|
||||
}
|
||||
|
||||
static void gfx_opengl_set_depth_range(float znear, float zfar) {
|
||||
if (glDepthRangef) {
|
||||
glDepthRangef(znear, zfar);
|
||||
glDepthRange(znear, zfar);
|
||||
}
|
||||
|
||||
static void gfx_opengl_set_zmode_decal(bool zmode_decal) {
|
||||
if (zmode_decal) {
|
||||
glPolygonOffset(-2, -2);
|
||||
glEnable(GL_POLYGON_OFFSET_FILL);
|
||||
} else {
|
||||
glDepthRange(znear, zfar);
|
||||
glPolygonOffset(0, 0);
|
||||
glDisable(GL_POLYGON_OFFSET_FILL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -856,6 +791,18 @@ static bool gfx_opengl_supports_framebuffers(void) {
|
||||
return (glad_glBlitFramebuffer && glad_glRenderbufferStorageMultisample);
|
||||
}
|
||||
if (GLAD_GL_EXT_framebuffer_object && GLAD_GL_EXT_framebuffer_blit && GLAD_GL_EXT_framebuffer_multisample) {
|
||||
// because of the way glad works we'll have to copy the pointers over
|
||||
glad_glGenFramebuffers = glad_glGenFramebuffersEXT;
|
||||
glad_glGenRenderbuffers = glad_glGenRenderbuffersEXT;
|
||||
glad_glDeleteFramebuffers = glad_glDeleteFramebuffersEXT;
|
||||
glad_glDeleteRenderbuffers = glad_glDeleteRenderbuffersEXT;
|
||||
glad_glBindFramebuffer = glad_glBindFramebufferEXT;
|
||||
glad_glBindRenderbuffer = glad_glBindRenderbufferEXT;
|
||||
glad_glFramebufferRenderbuffer = glad_glFramebufferRenderbufferEXT;
|
||||
glad_glFramebufferTexture2D = glad_glFramebufferTexture2DEXT;
|
||||
glad_glRenderbufferStorage = glad_glRenderbufferStorageEXT;
|
||||
glad_glRenderbufferStorageMultisample = glad_glRenderbufferStorageMultisampleEXT;
|
||||
glad_glBlitFramebuffer = glad_glBlitFramebufferEXT;
|
||||
// sanity check
|
||||
return (glad_glFramebufferRenderbuffer && glad_glBlitFramebuffer && glad_glRenderbufferStorageMultisample);
|
||||
}
|
||||
@@ -920,52 +867,11 @@ static void *gl_load_proc(const char *name) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void gfx_opengl_init_extensions(void) {
|
||||
// patch up some extension values and pointers
|
||||
if (!GLAD_GL_ARB_depth_clamp) {
|
||||
if (GLAD_GL_EXT_depth_clamp || GLAD_GL_NV_depth_clamp) {
|
||||
GLAD_GL_ARB_depth_clamp = 1;
|
||||
} else if (!gl_es && GLVersion.major >= 3) {
|
||||
// GL3.2+ should have depth_clamp as part of the spec, but some devices don't report it for some reason
|
||||
GLAD_GL_ARB_depth_clamp = (GLVersion.major > 3 || (GLVersion.major == 3 && GLVersion.minor >= 2));
|
||||
}
|
||||
}
|
||||
|
||||
if (!GLAD_GL_ARB_texture_mirror_clamp_to_edge) {
|
||||
GLAD_GL_ARB_texture_mirror_clamp_to_edge = GLAD_GL_EXT_texture_mirror_clamp_to_edge;
|
||||
}
|
||||
|
||||
if (GLVersion.major < 3 && !GLAD_GL_ARB_framebuffer_object) {
|
||||
if (GLAD_GL_EXT_framebuffer_object && GLAD_GL_EXT_framebuffer_blit && GLAD_GL_EXT_framebuffer_multisample) {
|
||||
// because of the way glad works we'll have to copy the pointers over
|
||||
glad_glGenFramebuffers = glad_glGenFramebuffersEXT;
|
||||
glad_glGenRenderbuffers = glad_glGenRenderbuffersEXT;
|
||||
glad_glDeleteFramebuffers = glad_glDeleteFramebuffersEXT;
|
||||
glad_glDeleteRenderbuffers = glad_glDeleteRenderbuffersEXT;
|
||||
glad_glBindFramebuffer = glad_glBindFramebufferEXT;
|
||||
glad_glBindRenderbuffer = glad_glBindRenderbufferEXT;
|
||||
glad_glFramebufferRenderbuffer = glad_glFramebufferRenderbufferEXT;
|
||||
glad_glFramebufferTexture2D = glad_glFramebufferTexture2DEXT;
|
||||
glad_glRenderbufferStorage = glad_glRenderbufferStorageEXT;
|
||||
glad_glRenderbufferStorageMultisample = glad_glRenderbufferStorageMultisampleEXT;
|
||||
glad_glBlitFramebuffer = glad_glBlitFramebufferEXT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void gfx_opengl_init(void) {
|
||||
if (!gladLoadGLLoader(gl_load_proc) || glGetString == NULL || glEnable == NULL) {
|
||||
sysFatalError("Could not load OpenGL.\nReported SDL error: %s", SDL_GetError());
|
||||
}
|
||||
|
||||
// check if we're using ES or core, which have more limited feature sets
|
||||
int val = 0;
|
||||
SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &val);
|
||||
gl_core_profile = (val == SDL_GL_CONTEXT_PROFILE_CORE);
|
||||
gl_es = (val == SDL_GL_CONTEXT_PROFILE_ES);
|
||||
|
||||
gfx_opengl_init_extensions();
|
||||
|
||||
if (sysArgCheck("--debug-gl")) {
|
||||
gfx_opengl_enable_debug();
|
||||
// dump version info as early as possible
|
||||
@@ -979,7 +885,7 @@ static void gfx_opengl_init(void) {
|
||||
}
|
||||
|
||||
if (!gfx_opengl_supports_shaders()) {
|
||||
sysLogPrintf(LOG_WARNING, "GL: GLSL 1.30 may be unsupported");
|
||||
sysLogPrintf(LOG_WARNING, "GL: GLSL 1.30 unsupported");
|
||||
// maybe replace this with sysFatalError, though the GLSL compiler will cause that later anyway
|
||||
}
|
||||
|
||||
@@ -995,35 +901,20 @@ static void gfx_opengl_init(void) {
|
||||
gl_mirror_clamp = GL_MIRRORED_REPEAT;
|
||||
}
|
||||
|
||||
// determine GLSL version
|
||||
if (gl_es) {
|
||||
// ES has its own numbering scheme, but it should support 300 even on 3.1 and 3.2
|
||||
gl_glsl_version = 300;
|
||||
snprintf(gl_glsl_version_str, sizeof(gl_glsl_version_str), "%d es", gl_glsl_version);
|
||||
} else if (!gl_core_profile) {
|
||||
// in compat profile we can just request the lowest possible
|
||||
gl_glsl_version = 130;
|
||||
snprintf(gl_glsl_version_str, sizeof(gl_glsl_version_str), "%d", gl_glsl_version);
|
||||
} else {
|
||||
// otherwise we have to pick a specific version
|
||||
if (GLVersion.major == 3 && GLVersion.minor == 2) {
|
||||
// 3.2core is the earliest core version and it follows the old numbering scheme
|
||||
gl_glsl_version = 150;
|
||||
} else {
|
||||
// 3.3+ follow the new numbering scheme
|
||||
gl_glsl_version = GLVersion.major * 100 + GLVersion.minor * 10;
|
||||
}
|
||||
snprintf(gl_glsl_version_str, sizeof(gl_glsl_version_str), "%d core", gl_glsl_version);
|
||||
if ((GLVersion.major == 3 && GLVersion.minor >= 2) || GLVersion.major > 3) {
|
||||
// check if we're using core profile, which is more strict
|
||||
int val = 0;
|
||||
SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &val);
|
||||
gl_core_profile = (val == SDL_GL_CONTEXT_PROFILE_CORE);
|
||||
}
|
||||
sysLogPrintf(LOG_NOTE, "GL: using GLSL version %s", gl_glsl_version_str);
|
||||
|
||||
glGenBuffers(1, &opengl_vbo);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, opengl_vbo);
|
||||
|
||||
if (gl_core_profile || gl_es) {
|
||||
if (gl_core_profile) {
|
||||
// warn user that funny things can happen
|
||||
sysLogPrintf(LOG_WARNING, "GL: using core profile or ES, watch out for errors");
|
||||
// core/es will explode if we don't use a VAO for our VBO
|
||||
sysLogPrintf(LOG_WARNING, "GL: using core profile, watch out for errors");
|
||||
// core will explode if we don't use a VAO for our VBO
|
||||
glGenVertexArrays(1, &opengl_vao);
|
||||
glBindVertexArray(opengl_vao);
|
||||
}
|
||||
@@ -1154,23 +1045,12 @@ bool gfx_opengl_start_draw_to_framebuffer(int fb_id, float noise_scale) {
|
||||
}
|
||||
}
|
||||
|
||||
void gfx_opengl_clear_framebuffer(bool clear_color, bool clear_depth) {
|
||||
void gfx_opengl_clear_framebuffer() {
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
|
||||
GLbitfield mask = 0;
|
||||
if (clear_color) {
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
mask |= GL_COLOR_BUFFER_BIT;
|
||||
}
|
||||
if (clear_depth) {
|
||||
glDepthMask(GL_TRUE);
|
||||
mask |= GL_DEPTH_BUFFER_BIT;
|
||||
}
|
||||
glClear(mask);
|
||||
if (clear_depth) {
|
||||
glDepthMask(current_depth_mask ? GL_TRUE : GL_FALSE);
|
||||
}
|
||||
|
||||
glDepthMask(GL_TRUE);
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
glDepthMask(current_depth_mask ? GL_TRUE : GL_FALSE);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
}
|
||||
|
||||
@@ -1198,8 +1078,6 @@ void gfx_opengl_select_texture_fb(int fb_id) {
|
||||
// glDisable(GL_DEPTH_TEST);
|
||||
glActiveTexture(GL_TEXTURE0 + 0);
|
||||
glBindTexture(GL_TEXTURE_2D, framebuffers[fb_id].clrbuf);
|
||||
|
||||
current_textures_linear_filter[0] = true;
|
||||
}
|
||||
|
||||
void gfx_opengl_copy_framebuffer(int fb_dst, int fb_src, int left, int top, bool flip_y, bool use_back) {
|
||||
@@ -1242,8 +1120,7 @@ void gfx_opengl_copy_framebuffer(int fb_dst, int fb_src, int left, int top, bool
|
||||
}
|
||||
|
||||
if (fb_src == 0) {
|
||||
// GLES does not support GL_FRONT here
|
||||
glReadBuffer((use_back || gl_es) ? GL_BACK : GL_FRONT);
|
||||
glReadBuffer(use_back ? GL_BACK : GL_FRONT);
|
||||
} else {
|
||||
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
||||
}
|
||||
@@ -1259,27 +1136,14 @@ void gfx_opengl_copy_framebuffer(int fb_dst, int fb_src, int left, int top, bool
|
||||
|
||||
void gfx_opengl_set_texture_filter(FilteringMode mode) {
|
||||
current_filter_mode = mode;
|
||||
gfx_texture_cache_clear();
|
||||
}
|
||||
|
||||
FilteringMode gfx_opengl_get_texture_filter(void) {
|
||||
return current_filter_mode;
|
||||
}
|
||||
|
||||
void gfx_opengl_set_mipmap_filter(MipmapFilteringMode mode) {
|
||||
current_mipmap_filter_mode = mode;
|
||||
}
|
||||
|
||||
static int gfx_opengl_get_max_anisotropy_level() {
|
||||
GLfloat max_aniso_level;
|
||||
glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY, &max_aniso_level);
|
||||
return (int)max_aniso_level;
|
||||
}
|
||||
|
||||
static void gfx_opengl_set_anisotropy_level(int level) {
|
||||
current_anisotropy_level = level;
|
||||
}
|
||||
|
||||
struct GfxRenderingAPI gfx_opengl_api = {
|
||||
struct GfxRenderingAPI gfx_opengl_api = {
|
||||
gfx_opengl_get_name,
|
||||
gfx_opengl_get_max_texture_size,
|
||||
gfx_opengl_get_clip_parameters,
|
||||
@@ -1288,13 +1152,13 @@ struct GfxRenderingAPI gfx_opengl_api = {
|
||||
gfx_opengl_create_and_load_new_shader,
|
||||
gfx_opengl_lookup_shader,
|
||||
gfx_opengl_shader_get_info,
|
||||
gfx_opengl_clear_shaders,
|
||||
gfx_opengl_new_texture,
|
||||
gfx_opengl_select_texture,
|
||||
gfx_opengl_upload_texture,
|
||||
gfx_opengl_set_sampler_parameters,
|
||||
gfx_opengl_set_depth_mode,
|
||||
gfx_opengl_set_depth_test_and_mask,
|
||||
gfx_opengl_set_depth_range,
|
||||
gfx_opengl_set_zmode_decal,
|
||||
gfx_opengl_set_viewport,
|
||||
gfx_opengl_set_scissor,
|
||||
gfx_opengl_set_use_alpha,
|
||||
@@ -1314,8 +1178,5 @@ struct GfxRenderingAPI gfx_opengl_api = {
|
||||
gfx_opengl_select_texture_fb,
|
||||
gfx_opengl_delete_texture,
|
||||
gfx_opengl_set_texture_filter,
|
||||
gfx_opengl_get_texture_filter,
|
||||
gfx_opengl_set_mipmap_filter,
|
||||
gfx_opengl_set_anisotropy_level,
|
||||
gfx_opengl_get_max_anisotropy_level
|
||||
gfx_opengl_get_texture_filter
|
||||
};
|
||||
+103
-143
@@ -125,6 +125,8 @@ static struct RSP {
|
||||
float aspect_ofs;
|
||||
float aspect_scale;
|
||||
|
||||
float depth_zfar;
|
||||
|
||||
struct {
|
||||
// U0.16
|
||||
uint16_t s, t;
|
||||
@@ -192,13 +194,12 @@ static struct RDP {
|
||||
bool viewport_or_scissor_changed;
|
||||
void* z_buf_address;
|
||||
void* color_image_address;
|
||||
|
||||
int16_t subpixel_ofs_x;
|
||||
int16_t subpixel_ofs_y;
|
||||
} rdp;
|
||||
|
||||
static struct RenderingState {
|
||||
uint8_t depth_mode;
|
||||
uint8_t depth_test_and_mask; // 1: depth test, 2: depth mask
|
||||
float depth_zfar;
|
||||
bool decal_mode;
|
||||
bool alpha_blend;
|
||||
bool modulate;
|
||||
struct XYWidthHeight viewport, scissor;
|
||||
@@ -522,7 +523,7 @@ static bool gfx_texture_cache_lookup(int i, const TextureCacheKey& key) {
|
||||
TextureCacheNode** n = &rendering_state.textures[i];
|
||||
|
||||
if (it != gfx_texture_cache.map.end()) {
|
||||
gfx_rapi->select_texture(i, it->second.texture_id, it->second.linear_filter);
|
||||
gfx_rapi->select_texture(i, it->second.texture_id);
|
||||
*n = &*it;
|
||||
gfx_texture_cache.lru.splice(gfx_texture_cache.lru.end(), gfx_texture_cache.lru,
|
||||
it->second.lru_location); // move to back
|
||||
@@ -550,8 +551,8 @@ static bool gfx_texture_cache_lookup(int i, const TextureCacheKey& key) {
|
||||
node->second.texture_id = texture_id;
|
||||
node->second.lru_location = gfx_texture_cache.lru.insert(gfx_texture_cache.lru.end(), { it });
|
||||
|
||||
gfx_rapi->select_texture(i, texture_id, false);
|
||||
gfx_rapi->set_sampler_parameters(i, false, 0, 0, rdp.tex_lod);
|
||||
gfx_rapi->select_texture(i, texture_id);
|
||||
gfx_rapi->set_sampler_parameters(i, false, 0, 0);
|
||||
*n = node;
|
||||
return false;
|
||||
}
|
||||
@@ -585,30 +586,8 @@ void gfx_texture_cache_delete(const uint8_t* orig_addr) {
|
||||
}
|
||||
}
|
||||
|
||||
void gfx_texture_cache_delete_range(const uint8_t* start, const uint8_t* end) {
|
||||
gfx_flush();
|
||||
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
if (rendering_state.textures[i]
|
||||
&& rendering_state.textures[i]->first.texture_addr >= start
|
||||
&& rendering_state.textures[i]->first.texture_addr < end) {
|
||||
rdp.textures_changed[i] = true;
|
||||
rendering_state.textures[i] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto it = gfx_texture_cache.map.begin(); it != gfx_texture_cache.map.end(); ) {
|
||||
if (it->first.texture_addr >= start && it->first.texture_addr < end) {
|
||||
gfx_texture_cache.lru.erase(it->second.lru_location);
|
||||
gfx_texture_cache.free_texture_ids.push_back(it->second.texture_id);
|
||||
it = gfx_texture_cache.map.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void import_texture_rgba16(int tile, const LoadedTexture& loaded_texture, bool gen_mipmaps) {
|
||||
static void import_texture_rgba16(int tile, const LoadedTexture& loaded_texture, bool importReplacement) {
|
||||
const RawTexMetadata* metadata = &loaded_texture.raw_tex_metadata;
|
||||
const uint8_t* addr = loaded_texture.addr;
|
||||
const uint32_t size_bytes = loaded_texture.size_bytes;
|
||||
const uint32_t full_image_line_size_bytes =
|
||||
@@ -634,11 +613,11 @@ static void import_texture_rgba16(int tile, const LoadedTexture& loaded_texture,
|
||||
const uint32_t width = rdp.texture_tile[tile].line_size_bytes / 2;
|
||||
const uint32_t height = size_bytes / rdp.texture_tile[tile].line_size_bytes;
|
||||
|
||||
gfx_rapi->upload_texture(tex_upload_buffer, width, height, gen_mipmaps);
|
||||
gfx_rapi->upload_texture(tex_upload_buffer, width, height);
|
||||
// DumpTexture(loaded_texture.otr_path, rgba32_buf, width, height);
|
||||
}
|
||||
|
||||
static void import_texture_rgba32(int tile, const LoadedTexture& loaded_texture, bool gen_mipmaps) {
|
||||
static void import_texture_rgba32(int tile, const LoadedTexture& loaded_texture, bool importReplacement) {
|
||||
const RawTexMetadata* metadata = &loaded_texture.raw_tex_metadata;
|
||||
const uint8_t* addr = loaded_texture.addr;
|
||||
const uint32_t size_bytes = loaded_texture.size_bytes;
|
||||
@@ -655,11 +634,11 @@ static void import_texture_rgba32(int tile, const LoadedTexture& loaded_texture,
|
||||
|
||||
const uint32_t width = rdp.texture_tile[tile].line_size_bytes / 2;
|
||||
const uint32_t height = (size_bytes / 2) / rdp.texture_tile[tile].line_size_bytes;
|
||||
gfx_rapi->upload_texture(tex_upload_buffer, width, height, gen_mipmaps);
|
||||
gfx_rapi->upload_texture(tex_upload_buffer, width, height);
|
||||
// DumpTexture(loaded_texture.otr_path, addr, width, height);
|
||||
}
|
||||
|
||||
static void import_texture_ia4(int tile, const LoadedTexture& loaded_texture, bool gen_mipmaps) {
|
||||
static void import_texture_ia4(int tile, const LoadedTexture& loaded_texture, bool importReplacement) {
|
||||
const RawTexMetadata* metadata = &loaded_texture.raw_tex_metadata;
|
||||
const uint8_t* addr = loaded_texture.addr;
|
||||
const uint32_t size_bytes = loaded_texture.size_bytes;
|
||||
@@ -684,11 +663,11 @@ static void import_texture_ia4(int tile, const LoadedTexture& loaded_texture, bo
|
||||
const uint32_t width = rdp.texture_tile[tile].line_size_bytes * 2;
|
||||
const uint32_t height = size_bytes / rdp.texture_tile[tile].line_size_bytes;
|
||||
|
||||
gfx_rapi->upload_texture(tex_upload_buffer, width, height, gen_mipmaps);
|
||||
gfx_rapi->upload_texture(tex_upload_buffer, width, height);
|
||||
// DumpTexture(loaded_texture.otr_path, rgba32_buf, width, height);
|
||||
}
|
||||
|
||||
static void import_texture_ia8(int tile, const LoadedTexture& loaded_texture, bool gen_mipmaps) {
|
||||
static void import_texture_ia8(int tile, const LoadedTexture& loaded_texture, bool importReplacement) {
|
||||
const RawTexMetadata* metadata = &loaded_texture.raw_tex_metadata;
|
||||
const uint8_t* addr = loaded_texture.addr;
|
||||
const uint32_t size_bytes = loaded_texture.size_bytes;
|
||||
@@ -710,11 +689,11 @@ static void import_texture_ia8(int tile, const LoadedTexture& loaded_texture, bo
|
||||
const uint32_t width = rdp.texture_tile[tile].line_size_bytes;
|
||||
const uint32_t height = size_bytes / rdp.texture_tile[tile].line_size_bytes;
|
||||
|
||||
gfx_rapi->upload_texture(tex_upload_buffer, width, height, gen_mipmaps);
|
||||
gfx_rapi->upload_texture(tex_upload_buffer, width, height);
|
||||
// DumpTexture(loaded_texture.otr_path, rgba32_buf, width, height);
|
||||
}
|
||||
|
||||
static void import_texture_ia16(int tile, const LoadedTexture& loaded_texture, bool gen_mipmaps) {
|
||||
static void import_texture_ia16(int tile, const LoadedTexture& loaded_texture, bool importReplacement) {
|
||||
const RawTexMetadata* metadata = &loaded_texture.raw_tex_metadata;
|
||||
const uint8_t* addr = loaded_texture.addr;
|
||||
const uint32_t size_bytes = loaded_texture.size_bytes;
|
||||
@@ -736,11 +715,11 @@ static void import_texture_ia16(int tile, const LoadedTexture& loaded_texture, b
|
||||
const uint32_t width = rdp.texture_tile[tile].line_size_bytes / 2;
|
||||
const uint32_t height = size_bytes / rdp.texture_tile[tile].line_size_bytes;
|
||||
|
||||
gfx_rapi->upload_texture(tex_upload_buffer, width, height, gen_mipmaps);
|
||||
gfx_rapi->upload_texture(tex_upload_buffer, width, height);
|
||||
// DumpTexture(loaded_texture.otr_path, rgba32_buf, width, height);
|
||||
}
|
||||
|
||||
static void import_texture_i4(int tile, const LoadedTexture& loaded_texture, bool gen_mipmaps) {
|
||||
static void import_texture_i4(int tile, const LoadedTexture& loaded_texture, bool importReplacement) {
|
||||
const RawTexMetadata* metadata = &loaded_texture.raw_tex_metadata;
|
||||
const uint8_t* addr = loaded_texture.addr;
|
||||
const uint32_t size_bytes = loaded_texture.size_bytes;
|
||||
@@ -763,11 +742,11 @@ static void import_texture_i4(int tile, const LoadedTexture& loaded_texture, boo
|
||||
const uint32_t width = rdp.texture_tile[tile].line_size_bytes * 2;
|
||||
const uint32_t height = size_bytes / rdp.texture_tile[tile].line_size_bytes;
|
||||
|
||||
gfx_rapi->upload_texture(tex_upload_buffer, width, height, gen_mipmaps);
|
||||
gfx_rapi->upload_texture(tex_upload_buffer, width, height);
|
||||
// DumpTexture(loaded_texture.otr_path, rgba32_buf, width, height);
|
||||
}
|
||||
|
||||
static void import_texture_i8(int tile, const LoadedTexture& loaded_texture, bool gen_mipmaps) {
|
||||
static void import_texture_i8(int tile, const LoadedTexture& loaded_texture, bool importReplacement) {
|
||||
const RawTexMetadata* metadata = &loaded_texture.raw_tex_metadata;
|
||||
const uint8_t* addr = loaded_texture.addr;
|
||||
const uint32_t size_bytes = loaded_texture.size_bytes;
|
||||
@@ -788,7 +767,7 @@ static void import_texture_i8(int tile, const LoadedTexture& loaded_texture, boo
|
||||
const uint32_t width = rdp.texture_tile[tile].line_size_bytes;
|
||||
const uint32_t height = size_bytes / rdp.texture_tile[tile].line_size_bytes;
|
||||
|
||||
gfx_rapi->upload_texture(tex_upload_buffer, width, height, gen_mipmaps);
|
||||
gfx_rapi->upload_texture(tex_upload_buffer, width, height);
|
||||
// DumpTexture(loaded_texture.otr_path, rgba32_buf, width, height);
|
||||
}
|
||||
|
||||
@@ -813,8 +792,8 @@ static inline void palette_to_rgba32(const uint16_t palentry, uint8_t *rgba32_bu
|
||||
}
|
||||
}
|
||||
|
||||
static void import_texture_ci4(int tile, const LoadedTexture& loaded_texture, bool gen_mipmaps) {
|
||||
const RawTexMetadata* metadata = &loaded_texture.raw_tex_metadata;
|
||||
static void import_texture_ci4(int tile, const LoadedTexture& loaded_texture, bool importReplacement) {
|
||||
const RawTexMetadata* metadata = &loaded_texture.raw_tex_metadata;
|
||||
const uint8_t* addr = loaded_texture.addr;
|
||||
const uint32_t size_bytes = loaded_texture.size_bytes;
|
||||
const uint32_t full_image_line_size_bytes =
|
||||
@@ -838,11 +817,11 @@ static void import_texture_ci4(int tile, const LoadedTexture& loaded_texture, bo
|
||||
const uint32_t width = result_line_size * 2;
|
||||
const uint32_t height = size_bytes / result_line_size;
|
||||
|
||||
gfx_rapi->upload_texture(tex_upload_buffer, width, height, gen_mipmaps);
|
||||
gfx_rapi->upload_texture(tex_upload_buffer, width, height);
|
||||
}
|
||||
|
||||
static void import_texture_ci8(int tile, const LoadedTexture& loaded_texture, bool gen_mipmaps) {
|
||||
const RawTexMetadata* metadata = &loaded_texture.raw_tex_metadata;
|
||||
static void import_texture_ci8(int tile, const LoadedTexture& loaded_texture, bool importReplacement) {
|
||||
const RawTexMetadata* metadata = &loaded_texture.raw_tex_metadata;
|
||||
const uint8_t* addr = loaded_texture.addr;
|
||||
const uint32_t size_bytes = loaded_texture.size_bytes;
|
||||
const uint32_t full_image_line_size_bytes =
|
||||
@@ -864,7 +843,8 @@ static void import_texture_ci8(int tile, const LoadedTexture& loaded_texture, bo
|
||||
const uint32_t width = result_line_size;
|
||||
const uint32_t height = size_bytes / result_line_size;
|
||||
|
||||
gfx_rapi->upload_texture(tex_upload_buffer, width, height, gen_mipmaps);
|
||||
gfx_rapi->upload_texture(tex_upload_buffer, width, height);
|
||||
// DumpTexture(loaded_texture.otr_path, rgba32_buf, width, height);
|
||||
}
|
||||
|
||||
static void import_texture(int i, int tile, bool importReplacement) {
|
||||
@@ -906,35 +886,35 @@ static void import_texture(int i, int tile, bool importReplacement) {
|
||||
|
||||
if (fmt == G_IM_FMT_RGBA) {
|
||||
if (siz == G_IM_SIZ_16b) {
|
||||
import_texture_rgba16(tile, loaded_texture, rdp.tex_lod);
|
||||
import_texture_rgba16(tile, loaded_texture, importReplacement);
|
||||
} else if (siz == G_IM_SIZ_32b) {
|
||||
import_texture_rgba32(tile, loaded_texture, rdp.tex_lod);
|
||||
import_texture_rgba32(tile, loaded_texture, importReplacement);
|
||||
} else {
|
||||
sysFatalError("Bad size for RGBA texture in tile %d: %02x", tile, siz);
|
||||
}
|
||||
} else if (fmt == G_IM_FMT_IA) {
|
||||
if (siz == G_IM_SIZ_4b) {
|
||||
import_texture_ia4(tile, loaded_texture, rdp.tex_lod);
|
||||
import_texture_ia4(tile, loaded_texture, importReplacement);
|
||||
} else if (siz == G_IM_SIZ_8b) {
|
||||
import_texture_ia8(tile, loaded_texture, rdp.tex_lod);
|
||||
import_texture_ia8(tile, loaded_texture, importReplacement);
|
||||
} else if (siz == G_IM_SIZ_16b) {
|
||||
import_texture_ia16(tile, loaded_texture, rdp.tex_lod);
|
||||
import_texture_ia16(tile, loaded_texture, importReplacement);
|
||||
} else {
|
||||
sysFatalError("Bad size for IA texture in tile %d: %02x", tile, siz);
|
||||
}
|
||||
} else if (fmt == G_IM_FMT_CI) {
|
||||
if (siz == G_IM_SIZ_4b) {
|
||||
import_texture_ci4(tile, loaded_texture, rdp.tex_lod);
|
||||
import_texture_ci4(tile, loaded_texture, importReplacement);
|
||||
} else if (siz == G_IM_SIZ_8b) {
|
||||
import_texture_ci8(tile, loaded_texture, rdp.tex_lod);
|
||||
import_texture_ci8(tile, loaded_texture, importReplacement);
|
||||
} else {
|
||||
sysFatalError("Bad size for CI texture in tile %d: %02x", tile, siz);
|
||||
}
|
||||
} else if (fmt == G_IM_FMT_I) {
|
||||
if (siz == G_IM_SIZ_4b) {
|
||||
import_texture_i4(tile, loaded_texture, rdp.tex_lod);
|
||||
import_texture_i4(tile, loaded_texture, importReplacement);
|
||||
} else if (siz == G_IM_SIZ_8b) {
|
||||
import_texture_i8(tile, loaded_texture, rdp.tex_lod);
|
||||
import_texture_i8(tile, loaded_texture, importReplacement);
|
||||
} else {
|
||||
sysFatalError("Bad size for I texture in tile %d: %02x", tile, siz);
|
||||
}
|
||||
@@ -1260,18 +1240,25 @@ static void gfx_sp_tri1(uint8_t vtx1_idx, uint8_t vtx2_idx, uint8_t vtx3_idx, bo
|
||||
}
|
||||
}
|
||||
|
||||
bool depth_test = ((rsp.geometry_mode & G_ZBUFFER) == G_ZBUFFER || (rdp.other_mode_l & G_ZS_PRIM) == G_ZS_PRIM) &&
|
||||
((rdp.other_mode_h & G_CYC_1CYCLE) == G_CYC_1CYCLE || (rdp.other_mode_h & G_CYC_2CYCLE) == G_CYC_2CYCLE);
|
||||
bool depth_update = (rdp.other_mode_l & Z_UPD) == Z_UPD;
|
||||
bool depth_compare = (rdp.other_mode_l & Z_CMP) == Z_CMP;
|
||||
bool depth_source_prim = (rdp.other_mode_l & G_ZS_PRIM) == G_ZS_PRIM /* && gDP.primDepth.z == 1.0f */;
|
||||
uint16_t zmode = rdp.other_mode_l & ZMODE_DEC;
|
||||
uint8_t depth_mode = (depth_test ? 1 : 0) | (depth_update ? 2 : 0) | (depth_compare ? 4 : 0) | (depth_source_prim ? 8 : 0) | (zmode >> 6);
|
||||
|
||||
if (depth_mode != rendering_state.depth_mode) {
|
||||
bool depth_test = (rsp.geometry_mode & G_ZBUFFER) == G_ZBUFFER;
|
||||
bool depth_mask = (rdp.other_mode_l & Z_UPD) == Z_UPD;
|
||||
uint8_t depth_test_and_mask = (depth_test ? 1 : 0) | (depth_mask ? 2 : 0);
|
||||
if (depth_test_and_mask != rendering_state.depth_test_and_mask) {
|
||||
gfx_flush();
|
||||
gfx_rapi->set_depth_mode(depth_test, depth_update, depth_compare, depth_source_prim, zmode);
|
||||
rendering_state.depth_mode = depth_mode;
|
||||
gfx_rapi->set_depth_test_and_mask(depth_test, depth_mask);
|
||||
rendering_state.depth_test_and_mask = depth_test_and_mask;
|
||||
}
|
||||
if (rsp.depth_zfar != rendering_state.depth_zfar) {
|
||||
gfx_flush();
|
||||
gfx_rapi->set_depth_range(0.0f, rsp.depth_zfar);
|
||||
rendering_state.depth_zfar = rsp.depth_zfar;
|
||||
}
|
||||
|
||||
bool zmode_decal = (rdp.other_mode_l & ZMODE_DEC) == ZMODE_DEC;
|
||||
if (zmode_decal != rendering_state.decal_mode) {
|
||||
gfx_flush();
|
||||
gfx_rapi->set_zmode_decal(zmode_decal);
|
||||
rendering_state.decal_mode = zmode_decal;
|
||||
}
|
||||
|
||||
if (rdp.viewport_or_scissor_changed) {
|
||||
@@ -1404,7 +1391,7 @@ static void gfx_sp_tri1(uint8_t vtx1_idx, uint8_t vtx2_idx, uint8_t vtx3_idx, bo
|
||||
if (linear_filter != rendering_state.textures[i]->second.linear_filter ||
|
||||
cms != rendering_state.textures[i]->second.cms || cmt != rendering_state.textures[i]->second.cmt) {
|
||||
gfx_flush();
|
||||
gfx_rapi->set_sampler_parameters(i, linear_filter, cms, cmt, rdp.tex_lod);
|
||||
gfx_rapi->set_sampler_parameters(i, linear_filter, cms, cmt);
|
||||
rendering_state.textures[i]->second.linear_filter = linear_filter;
|
||||
rendering_state.textures[i]->second.cms = cms;
|
||||
rendering_state.textures[i]->second.cmt = cmt;
|
||||
@@ -1597,7 +1584,7 @@ static inline void gfx_sp_tri4(Gfx *cmd) {
|
||||
uint8_t x = C1(0, 4);
|
||||
uint8_t y = C1(4, 4);
|
||||
uint8_t z = C0(0, 4);
|
||||
|
||||
|
||||
if(x || y || z) {
|
||||
gfx_sp_tri1(x, y, z, false);
|
||||
}
|
||||
@@ -1661,34 +1648,34 @@ static void gfx_sp_extra_geometry_mode(uint32_t clear, uint32_t set) {
|
||||
}
|
||||
|
||||
static void gfx_adjust_viewport_or_scissor(XYWidthHeight* area, bool preserve_aspect = false) {
|
||||
// HACK: assume all target framebuffers have the same aspect
|
||||
// Use floor/ceil to ensure scissor fully contains the logical region
|
||||
// and prevents sub-pixel gaps at viewport edges
|
||||
float x1 = area->x * RATIO_X;
|
||||
float y1 = (SCREEN_HEIGHT - area->y) * RATIO_Y;
|
||||
float x2 = (area->x + area->width) * RATIO_X;
|
||||
float y2 = (SCREEN_HEIGHT - area->y + area->height) * RATIO_Y;
|
||||
|
||||
area->x = std::floor(x1);
|
||||
area->y = std::floor(y1);
|
||||
area->width = std::ceil(x2) - area->x;
|
||||
area->height = std::ceil(y2) - area->y;
|
||||
|
||||
if (preserve_aspect) {
|
||||
// preserve native aspect ratio
|
||||
const float ratio = gfx_current_native_aspect / gfx_current_dimensions.aspect_ratio;
|
||||
const float midx = gfx_current_dimensions.width * 0.5f;
|
||||
area->x = midx + (area->x - midx) * ratio;
|
||||
area->x += rsp.aspect_ofs * gfx_current_dimensions.width * 0.5f;
|
||||
area->width *= ratio;
|
||||
}
|
||||
if (!fbActive) {
|
||||
area->width *= RATIO_X;
|
||||
area->x *= RATIO_X;
|
||||
area->height *= RATIO_Y;
|
||||
area->y = SCREEN_HEIGHT - area->y;
|
||||
area->y *= RATIO_Y;
|
||||
if (preserve_aspect) {
|
||||
// preserve native aspect ratio
|
||||
const float ratio = gfx_current_native_aspect / gfx_current_dimensions.aspect_ratio;
|
||||
const float midx = gfx_current_dimensions.width * 0.5f;
|
||||
area->x = midx + (area->x - midx) * ratio;
|
||||
area->x += rsp.aspect_ofs * gfx_current_dimensions.width * 0.5f;
|
||||
area->width *= ratio;
|
||||
}
|
||||
|
||||
if (!game_renders_to_framebuffer ||
|
||||
(gfx_msaa_level > 1 && gfx_current_dimensions.width == gfx_current_game_window_viewport.width &&
|
||||
gfx_current_dimensions.height == gfx_current_game_window_viewport.height)) {
|
||||
area->x += gfx_current_game_window_viewport.x;
|
||||
area->y += gfx_current_window_dimensions.height -
|
||||
(gfx_current_game_window_viewport.y + gfx_current_game_window_viewport.height);
|
||||
if (!game_renders_to_framebuffer ||
|
||||
(gfx_msaa_level > 1 && gfx_current_dimensions.width == gfx_current_game_window_viewport.width &&
|
||||
gfx_current_dimensions.height == gfx_current_game_window_viewport.height)) {
|
||||
area->x += gfx_current_game_window_viewport.x;
|
||||
area->y += gfx_current_window_dimensions.height -
|
||||
(gfx_current_game_window_viewport.y + gfx_current_game_window_viewport.height);
|
||||
}
|
||||
} else {
|
||||
area->width *= RATIO_Y;
|
||||
area->height *= RATIO_Y;
|
||||
area->x *= RATIO_Y;
|
||||
area->y = active_fb->second.orig_height - area->y;
|
||||
area->y *= RATIO_Y;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1746,6 +1733,18 @@ static void gfx_sp_moveword(uint8_t index, uint16_t offset, uintptr_t data) {
|
||||
case G_MW_SEGMENT:
|
||||
segmentPointers[(offset >> 2) & 0xff] = data;
|
||||
break;
|
||||
case G_MW_PERSPNORM:
|
||||
// the default z range is around [100, 10000]
|
||||
// data is 2 / (znear + zfar) represented as a 0.16 fixed point
|
||||
// => (znear + zfar) = (2 / (data / 65536)) = 131072 / data
|
||||
constexpr float full_range_mul = 1.f / 11000.f; // that's around the biggest value I got when testing
|
||||
if (data == 0) {
|
||||
rsp.depth_zfar = 1.f;
|
||||
} else {
|
||||
// sometimes this will overshoot 1 but GL can handle that
|
||||
rsp.depth_zfar =((131072.f * full_range_mul) / (float)data);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2000,11 +1999,6 @@ static void gfx_dp_set_fill_color(uint32_t packed_color) {
|
||||
rdp.fill_color.a = a * 255;
|
||||
}
|
||||
|
||||
static void gfx_dp_set_subpixel_offset(int16_t x, int16_t y) {
|
||||
rdp.subpixel_ofs_x = x;
|
||||
rdp.subpixel_ofs_y = y;
|
||||
}
|
||||
|
||||
static void gfx_draw_rectangle(int32_t ulx, int32_t uly, int32_t lrx, int32_t lry) {
|
||||
uint32_t saved_other_mode_h = rdp.other_mode_h;
|
||||
uint32_t cycle_type = (rdp.other_mode_h & (3U << G_MDSFT_CYCLETYPE));
|
||||
@@ -2013,11 +2007,6 @@ static void gfx_draw_rectangle(int32_t ulx, int32_t uly, int32_t lrx, int32_t lr
|
||||
rdp.other_mode_h = (rdp.other_mode_h & ~(3U << G_MDSFT_TEXTFILT)) | G_TF_POINT;
|
||||
}
|
||||
|
||||
ulx += rdp.subpixel_ofs_x;
|
||||
lrx += rdp.subpixel_ofs_x;
|
||||
uly += rdp.subpixel_ofs_y;
|
||||
lry += rdp.subpixel_ofs_y;
|
||||
|
||||
// U10.2 coordinates
|
||||
float ulxf = ulx;
|
||||
float ulyf = uly;
|
||||
@@ -2402,10 +2391,6 @@ static void gfx_run_dl(Gfx* cmd) {
|
||||
break;
|
||||
// G_SETPRIMCOLOR, G_CCMUX_PRIMITIVE, G_ACMUX_PRIMITIVE, is used by Goddard
|
||||
// G_CCMUX_TEXEL1, LOD_FRACTION is used in Bowser room 1
|
||||
case G_SETSUBPIXELOFFSET_EXT: {
|
||||
gfx_dp_set_subpixel_offset(C0(0, 16), C1(0, 16));
|
||||
break;
|
||||
}
|
||||
case G_TEXRECT:
|
||||
case G_TEXRECTFLIP: {
|
||||
int32_t lrx, lry, tile, ulx, uly;
|
||||
@@ -2519,10 +2504,6 @@ static void gfx_run_dl(Gfx* cmd) {
|
||||
case G_RDPFLUSH_EXT:
|
||||
gfx_flush();
|
||||
break;
|
||||
case G_CLEAR_DEPTH_EXT:
|
||||
gfx_flush();
|
||||
gfx_rapi->clear_framebuffer(false, true);
|
||||
break;
|
||||
case G_RDPPIPESYNC:
|
||||
case G_RDPFULLSYNC:
|
||||
case G_RDPLOADSYNC:
|
||||
@@ -2573,6 +2554,8 @@ extern "C" void gfx_init(const GfxInitSettings *settings) {
|
||||
tex_upload_buffer = (uint8_t*)malloc(max_tex_size * max_tex_size * 4);
|
||||
}
|
||||
|
||||
rsp.depth_zfar = 1.0f;
|
||||
|
||||
rsp.lookat[0].dir[0] = rsp.lookat[1].dir[1] = 0x7F;
|
||||
rsp.current_lookat_coeffs[0][0] = rsp.current_lookat_coeffs[1][1] = 1.f;
|
||||
rsp.lookat_enabled = true;
|
||||
@@ -2678,7 +2661,7 @@ extern "C" void gfx_run(Gfx* commands) {
|
||||
gfx_rapi->start_frame();
|
||||
gfx_rapi->start_draw_to_framebuffer(game_renders_to_framebuffer ? game_framebuffer : 0,
|
||||
(float)gfx_current_dimensions.height / SCREEN_HEIGHT);
|
||||
gfx_rapi->clear_framebuffer(true, false);
|
||||
gfx_rapi->clear_framebuffer();
|
||||
rdp.viewport_or_scissor_changed = true;
|
||||
rendering_state.viewport = {};
|
||||
rendering_state.scissor = {};
|
||||
@@ -2688,7 +2671,7 @@ extern "C" void gfx_run(Gfx* commands) {
|
||||
|
||||
if (game_renders_to_framebuffer) {
|
||||
gfx_rapi->start_draw_to_framebuffer(0, 1);
|
||||
gfx_rapi->clear_framebuffer(true, true);
|
||||
gfx_rapi->clear_framebuffer();
|
||||
|
||||
if (gfx_msaa_level > 1) {
|
||||
bool different_size = gfx_current_dimensions.width != gfx_current_game_window_viewport.width ||
|
||||
@@ -2720,27 +2703,6 @@ extern "C" void gfx_set_target_fps(int fps) {
|
||||
gfx_wapi->set_target_fps(fps);
|
||||
}
|
||||
|
||||
extern "C" void reset_texture_state() {
|
||||
gfx_texture_cache_clear();
|
||||
if (rendering_state.shader_program) {
|
||||
gfx_rapi->unload_shader(rendering_state.shader_program);
|
||||
rendering_state.shader_program = nullptr;
|
||||
}
|
||||
gfx_rapi->clear_shaders();
|
||||
color_combiner_pool.clear();
|
||||
prev_combiner = color_combiner_pool.end();
|
||||
}
|
||||
|
||||
extern "C" void gfx_set_texture_filter(enum FilteringMode mode) {
|
||||
reset_texture_state();
|
||||
gfx_rapi->set_texture_filter(mode);
|
||||
}
|
||||
|
||||
extern "C" void gfx_set_mipmap_filter(enum MipmapFilteringMode mode) {
|
||||
reset_texture_state();
|
||||
gfx_rapi->set_mipmap_filter(mode);
|
||||
}
|
||||
|
||||
extern "C" int gfx_create_framebuffer(uint32_t width, uint32_t height, int upscale, int autoresize) {
|
||||
int fb = gfx_rapi->create_framebuffer();
|
||||
gfx_resize_framebuffer(fb, width, height, upscale, autoresize);
|
||||
@@ -2772,8 +2734,7 @@ extern "C" void gfx_resize_framebuffer(int fb, uint32_t width, uint32_t height,
|
||||
|
||||
extern "C" void gfx_set_framebuffer(int fb, float noise_scale) {
|
||||
gfx_rapi->start_draw_to_framebuffer(fb, noise_scale);
|
||||
gfx_rapi->clear_framebuffer(true, true);
|
||||
active_fb = framebuffers.find(fb);
|
||||
gfx_rapi->clear_framebuffer();
|
||||
}
|
||||
|
||||
extern "C" void gfx_copy_framebuffer(int fb_dst, int fb_src, int left, int top, int use_back) {
|
||||
@@ -2798,5 +2759,4 @@ extern "C" void gfx_copy_framebuffer(int fb_dst, int fb_src, int left, int top,
|
||||
|
||||
extern "C" void gfx_reset_framebuffer(void) {
|
||||
gfx_rapi->start_draw_to_framebuffer(0, (float)gfx_current_dimensions.height / SCREEN_HEIGHT);
|
||||
active_fb = framebuffers.end();
|
||||
}
|
||||
@@ -13,7 +13,6 @@ struct GfxClipParameters {
|
||||
};
|
||||
|
||||
enum FilteringMode { FILTER_NONE, FILTER_LINEAR, FILTER_THREE_POINT };
|
||||
enum MipmapFilteringMode { MIPMAP_DISABLED, MIPMAP_NEAREST, MIPMAP_LINEAR };
|
||||
|
||||
struct GfxRenderingAPI {
|
||||
const char* (*get_name)(void);
|
||||
@@ -24,13 +23,13 @@ struct GfxRenderingAPI {
|
||||
struct ShaderProgram* (*create_and_load_new_shader)(uint64_t shader_id0, uint32_t shader_id1);
|
||||
struct ShaderProgram* (*lookup_shader)(uint64_t shader_id0, uint32_t shader_id1);
|
||||
void (*shader_get_info)(struct ShaderProgram* prg, uint8_t* num_inputs, bool used_textures[2]);
|
||||
void (*clear_shaders)(void);
|
||||
uint32_t (*new_texture)(void);
|
||||
void (*select_texture)(int tile, uint32_t texture_id, bool linear_filter);
|
||||
void (*upload_texture)(const uint8_t* rgba32_buf, uint32_t width, uint32_t height, bool gen_mipmaps);
|
||||
void (*set_sampler_parameters)(int sampler, bool linear_filter, uint32_t cms, uint32_t cmt, bool mipmaps);
|
||||
void (*set_depth_mode)(bool depth_test, bool depth_update, bool depth_compare, bool depth_source_prim, uint16_t zmode);
|
||||
void (*select_texture)(int tile, uint32_t texture_id);
|
||||
void (*upload_texture)(const uint8_t* rgba32_buf, uint32_t width, uint32_t height);
|
||||
void (*set_sampler_parameters)(int sampler, bool linear_filter, uint32_t cms, uint32_t cmt);
|
||||
void (*set_depth_test_and_mask)(bool depth_test, bool z_upd);
|
||||
void (*set_depth_range)(float znear, float zfar);
|
||||
void (*set_zmode_decal)(bool zmode_decal);
|
||||
void (*set_viewport)(int x, int y, int width, int height);
|
||||
void (*set_scissor)(int x, int y, int width, int height);
|
||||
void (*set_use_alpha)(bool use_alpha, bool modulate);
|
||||
@@ -46,16 +45,13 @@ struct GfxRenderingAPI {
|
||||
bool can_extract_depth);
|
||||
bool (*start_draw_to_framebuffer)(int fb_id, float noise_scale);
|
||||
void (*copy_framebuffer)(int fb_dst, int fb_src, int left, int top, bool flip_y, bool use_back);
|
||||
void (*clear_framebuffer)(bool clear_color, bool clear_depth);
|
||||
void (*clear_framebuffer)(void);
|
||||
void (*resolve_msaa_color_buffer)(int fb_id_target, int fb_id_source);
|
||||
void* (*get_framebuffer_texture_id)(int fb_id);
|
||||
void (*select_texture_fb)(int fb_id);
|
||||
void (*delete_texture)(uint32_t texID);
|
||||
void (*set_texture_filter)(enum FilteringMode mode);
|
||||
enum FilteringMode (*get_texture_filter)(void);
|
||||
void (*set_mipmap_filter)(enum MipmapFilteringMode mode);
|
||||
void (*set_anisotropy_level)(int);
|
||||
int (*get_max_anisotropy_level)(void);
|
||||
};
|
||||
|
||||
#endif
|
||||
+31
-152
@@ -30,30 +30,10 @@ static uint64_t qpc_freq;
|
||||
#define FRAME_INTERVAL_US_NUMERATOR 1000000
|
||||
#define FRAME_INTERVAL_US_DENOMINATOR (target_fps)
|
||||
|
||||
static int32_t gfx_sdl_get_maximized_state(void) {
|
||||
return (int32_t)maximized_state;
|
||||
}
|
||||
|
||||
static int32_t gfx_sdl_get_fullscreen_state(void) {
|
||||
return (int32_t)fullscreen_state;
|
||||
}
|
||||
|
||||
static int32_t gfx_sdl_get_fullscreen_flag_mode(void) {
|
||||
return fullscreen_flag == SDL_WINDOW_FULLSCREEN_DESKTOP ? 0 : 1;
|
||||
}
|
||||
|
||||
static void gfx_sdl_set_fullscreen_flag(int32_t mode) {
|
||||
switch (mode) {
|
||||
case 0: {
|
||||
fullscreen_flag = SDL_WINDOW_FULLSCREEN_DESKTOP;
|
||||
} break;
|
||||
case 1: {
|
||||
fullscreen_flag = SDL_WINDOW_FULLSCREEN;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
static void set_fullscreen(bool on, bool call_callback) {
|
||||
if (fullscreen_state == on) {
|
||||
return;
|
||||
}
|
||||
fullscreen_state = on;
|
||||
SDL_SetWindowFullscreen(wnd, on ? fullscreen_flag : 0);
|
||||
if (call_callback && on_fullscreen_changed_callback) {
|
||||
@@ -62,6 +42,9 @@ static void set_fullscreen(bool on, bool call_callback) {
|
||||
}
|
||||
|
||||
static void set_maximize_window(bool on) {
|
||||
if (maximized_state == on) {
|
||||
return;
|
||||
}
|
||||
maximized_state = on;
|
||||
if (on) {
|
||||
SDL_MaximizeWindow(wnd);
|
||||
@@ -100,6 +83,7 @@ static void gfx_sdl_init(const struct GfxWindowInitSettings *set) {
|
||||
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
|
||||
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
|
||||
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY);
|
||||
if (sysArgCheck("--debug-gl")) {
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG);
|
||||
}
|
||||
@@ -108,23 +92,15 @@ static void gfx_sdl_init(const struct GfxWindowInitSettings *set) {
|
||||
int posY = set->y;
|
||||
int display_in_use = SDL_GetWindowDisplayIndex(wnd);
|
||||
if (display_in_use < 0) { // Fallback to default if out of bounds
|
||||
posX = SDL_WINDOWPOS_UNDEFINED;
|
||||
posY = SDL_WINDOWPOS_UNDEFINED;
|
||||
}
|
||||
|
||||
if (set->centered) {
|
||||
SDL_DisplayMode mode = {};
|
||||
SDL_GetCurrentDisplayMode(0, &mode);
|
||||
posX = mode.w / 2 - window_width / 2;
|
||||
posY = mode.h / 2 - window_height / 2;
|
||||
posX = 100;
|
||||
posY = 100;
|
||||
}
|
||||
|
||||
if (set->fullscreen_is_exclusive) {
|
||||
fullscreen_flag = SDL_WINDOW_FULLSCREEN;
|
||||
}
|
||||
|
||||
// we will unhide the window once the GL context is successfully created
|
||||
Uint32 flags = SDL_WINDOW_HIDDEN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL;
|
||||
Uint32 flags = SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL;
|
||||
|
||||
// if fullscreen was requested, start the window in fullscreen right away
|
||||
if (set->fullscreen) {
|
||||
@@ -143,25 +119,28 @@ static void gfx_sdl_init(const struct GfxWindowInitSettings *set) {
|
||||
}
|
||||
#endif
|
||||
|
||||
wnd = SDL_CreateWindow(set->title, posX, posY, window_width, window_height, flags);
|
||||
if (!wnd) {
|
||||
sysFatalError("Could not open SDL window:\n%s", SDL_GetError());
|
||||
}
|
||||
|
||||
// ideally we need 3.0 compat
|
||||
// if that doesn't work, try 3.2 core in case we're on mac, 2.1 compat as a last resort
|
||||
static u32 glver[][3] = {
|
||||
{ 0, 0, 0 }, // for command line override
|
||||
{ 3, 0, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY }, // 3.0: default, has all the features required
|
||||
{ 4, 1, SDL_GL_CONTEXT_PROFILE_CORE }, // 4.1core: macs only have core profile and this is the latest
|
||||
{ 3, 2, SDL_GL_CONTEXT_PROFILE_CORE }, // 3.2core: older macs will only have this at best
|
||||
{ 3, 0, SDL_GL_CONTEXT_PROFILE_ES }, // es3: don't really support ES properly, but we can try
|
||||
{ 2, 1, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY }, // 2.1: absolute last resort, will still require GLSL130 as an extension
|
||||
{ 3, 0, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY },
|
||||
{ 3, 2, SDL_GL_CONTEXT_PROFILE_CORE },
|
||||
{ 2, 1, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY },
|
||||
};
|
||||
|
||||
u32 glcore = false;
|
||||
u32 verstart = 1;
|
||||
const u32 verend = sizeof(glver) / sizeof(*glver);
|
||||
const char *verstr = sysArgGetString("--gl-version");
|
||||
if (verstr && *verstr) {
|
||||
// user override
|
||||
glver[0][2] = strstr(verstr, "core") ? SDL_GL_CONTEXT_PROFILE_CORE :
|
||||
(strstr(verstr, "es") ? SDL_GL_CONTEXT_PROFILE_ES :
|
||||
SDL_GL_CONTEXT_PROFILE_COMPATIBILITY);
|
||||
SDL_GL_CONTEXT_PROFILE_COMPATIBILITY;
|
||||
sscanf(verstr, "%d.%d", &glver[0][0], &glver[0][1]);
|
||||
if (glver[0][0] >= 1 && glver[0][0] <= 4 && glver[0][1] < 9) {
|
||||
verstart = 0;
|
||||
@@ -169,44 +148,31 @@ static void gfx_sdl_init(const struct GfxWindowInitSettings *set) {
|
||||
}
|
||||
|
||||
ctx = NULL;
|
||||
u32 vmin = 0, vmaj = 0, vprof = SDL_GL_CONTEXT_PROFILE_COMPATIBILITY;
|
||||
const char *vprofstr = "";
|
||||
for (u32 i = verstart; i < verend && !ctx; ++i) {
|
||||
u32 vmin = 0, vmaj = 0;
|
||||
for (u32 i = verstart; i < verend; ++i) {
|
||||
vmaj = glver[i][0];
|
||||
vmin = glver[i][1];
|
||||
vprof = glver[i][2];
|
||||
vprofstr = (vprof == SDL_GL_CONTEXT_PROFILE_CORE ? "core" :
|
||||
(vprof == SDL_GL_CONTEXT_PROFILE_ES ? "es" : ""));
|
||||
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, vmaj);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, vmin);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, vprof);
|
||||
|
||||
wnd = SDL_CreateWindow(set->title, posX, posY, window_width, window_height, flags);
|
||||
if (!wnd) {
|
||||
sysLogPrintf(LOG_WARNING, "SDL: could not open SDL window for GL%d.%d%s:\n%s", vmaj, vmin, vprofstr, SDL_GetError());
|
||||
continue;
|
||||
}
|
||||
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, glver[i][2]);
|
||||
ctx = SDL_GL_CreateContext(wnd);
|
||||
if (!ctx) {
|
||||
sysLogPrintf(LOG_WARNING, "SDL: could not create GL%d.%d%s context: %s", vmaj, vmin, vprofstr, SDL_GetError());
|
||||
SDL_DestroyWindow(wnd);
|
||||
wnd = nullptr;
|
||||
sysLogPrintf(LOG_WARNING, "GL: could not create GL%d.%d context: %s", vmaj, vmin, SDL_GetError());
|
||||
} else {
|
||||
glcore = (glver[i][2] == SDL_GL_CONTEXT_PROFILE_CORE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!wnd || !ctx) {
|
||||
sysFatalError("Could not open SDL window with an OpenGL context of any supported version:\n%s", SDL_GetError());
|
||||
if (!ctx) {
|
||||
sysFatalError("Could not create an OpenGL context of any supported version.\nSDL error: %s", SDL_GetError());
|
||||
} else {
|
||||
sysLogPrintf(LOG_NOTE, "SDL: created GL%d.%d%s context", vmaj, vmin, vprofstr);
|
||||
sysLogPrintf(LOG_NOTE, "GL: created GL%d.%d%s context", vmaj, vmin, glcore ? "core" : "");
|
||||
}
|
||||
|
||||
SDL_GL_MakeCurrent(wnd, ctx);
|
||||
SDL_GL_SetSwapInterval(1);
|
||||
|
||||
SDL_ShowWindow(wnd);
|
||||
|
||||
qpc_freq = SDL_GetPerformanceFrequency();
|
||||
}
|
||||
|
||||
@@ -246,43 +212,6 @@ static void gfx_sdl_set_cursor_visibility(bool visible) {
|
||||
}
|
||||
}
|
||||
|
||||
static void get_centered_positions_native(int32_t width, int32_t height, int32_t *posX, int32_t *posY) {
|
||||
const int disp_idx = SDL_GetWindowDisplayIndex(wnd);
|
||||
SDL_DisplayMode mode = {};
|
||||
SDL_GetDesktopDisplayMode(disp_idx, &mode);
|
||||
*posX = mode.w / 2 - width / 2;
|
||||
*posY = mode.h / 2 - height / 2;
|
||||
}
|
||||
|
||||
static void gfx_sdl_get_centered_positions(int32_t width, int32_t height, int32_t *posX, int32_t *posY) {
|
||||
const int disp_idx = SDL_GetWindowDisplayIndex(wnd);
|
||||
SDL_DisplayMode mode = {};
|
||||
SDL_GetCurrentDisplayMode(disp_idx, &mode);
|
||||
*posX = mode.w / 2 - width / 2;
|
||||
*posY = mode.h / 2 - height / 2;
|
||||
}
|
||||
|
||||
static void gfx_sdl_set_closest_resolution(int32_t width, int32_t height, bool should_center) {
|
||||
const SDL_DisplayMode mode = {.w = width, .h = height};
|
||||
const int disp_idx = SDL_GetWindowDisplayIndex(wnd);
|
||||
SDL_DisplayMode closest = {};
|
||||
if (SDL_GetClosestDisplayMode(disp_idx, &mode, &closest)) {
|
||||
SDL_SetWindowDisplayMode(wnd, &closest);
|
||||
SDL_SetWindowSize(wnd, closest.w, closest.h);
|
||||
if (should_center) {
|
||||
int32_t posX = 0;
|
||||
int32_t posY = 0;
|
||||
get_centered_positions_native(closest.w, closest.h, &posX, &posY);
|
||||
SDL_SetWindowPosition(wnd, posX, posY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void gfx_sdl_set_dimensions(uint32_t width, uint32_t height, int32_t posX, int32_t posY) {
|
||||
SDL_SetWindowSize(wnd, width, height);
|
||||
SDL_SetWindowPosition(wnd, posX, posY);
|
||||
}
|
||||
|
||||
static void gfx_sdl_get_dimensions(uint32_t* width, uint32_t* height, int32_t* posX, int32_t* posY) {
|
||||
SDL_GL_GetDrawableSize(wnd, static_cast<int*>((void*)width), static_cast<int*>((void*)height));
|
||||
SDL_GetWindowPosition(wnd, static_cast<int*>(posX), static_cast<int*>(posY));
|
||||
@@ -301,9 +230,6 @@ static void gfx_sdl_handle_events(void) {
|
||||
case SDL_WINDOWEVENT:
|
||||
if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
|
||||
SDL_GL_GetDrawableSize(wnd, &window_width, &window_height);
|
||||
if (!fullscreen_state) {
|
||||
maximized_state = SDL_GetWindowFlags(wnd) & SDL_WINDOW_MAXIMIZED ? true : false;
|
||||
}
|
||||
} else if (event.window.event == SDL_WINDOWEVENT_CLOSE &&
|
||||
event.window.windowID == SDL_GetWindowID(wnd)) {
|
||||
// We listen specifically for main window close because closing main window
|
||||
@@ -368,10 +294,6 @@ static double gfx_sdl_get_time(void) {
|
||||
return SDL_GetPerformanceCounter() / (double)qpc_freq;
|
||||
}
|
||||
|
||||
static int32_t gfx_sdl_get_target_fps(void) {
|
||||
return target_fps;
|
||||
}
|
||||
|
||||
static void gfx_sdl_set_target_fps(int fps) {
|
||||
target_fps = fps;
|
||||
}
|
||||
@@ -388,10 +310,6 @@ static void gfx_sdl_set_window_title(const char *title) {
|
||||
SDL_SetWindowTitle(wnd, title);
|
||||
}
|
||||
|
||||
static int gfx_sdl_get_swap_interval(void) {
|
||||
return SDL_GL_GetSwapInterval();
|
||||
}
|
||||
|
||||
static bool gfx_sdl_set_swap_interval(int interval) {
|
||||
const bool success = SDL_GL_SetSwapInterval(interval) >= 0;
|
||||
vsync_enabled = success && (interval != 0);
|
||||
@@ -401,63 +319,24 @@ static bool gfx_sdl_set_swap_interval(int interval) {
|
||||
return success;
|
||||
}
|
||||
|
||||
int gfx_sdl_get_display_mode(int modenum, int *out_w, int *out_h) {
|
||||
const int display_in_use = SDL_GetWindowDisplayIndex(wnd);
|
||||
SDL_DisplayMode sdlmode;
|
||||
if (SDL_GetDisplayMode(display_in_use, modenum, &sdlmode) == 0) {
|
||||
*out_w = sdlmode.w;
|
||||
*out_h = sdlmode.h;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gfx_sdl_get_current_display_mode(int *out_w, int *out_h) {
|
||||
const int display_in_use = SDL_GetWindowDisplayIndex(wnd);
|
||||
SDL_DisplayMode sdlmode;
|
||||
if (SDL_GetCurrentDisplayMode(display_in_use, &sdlmode) == 0) {
|
||||
*out_w = sdlmode.w;
|
||||
*out_h = sdlmode.h;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gfx_sdl_get_num_display_modes(void) {
|
||||
const int display_in_use = SDL_GetWindowDisplayIndex(wnd);
|
||||
return SDL_GetNumDisplayModes(display_in_use);
|
||||
}
|
||||
|
||||
struct GfxWindowManagerAPI gfx_sdl = {
|
||||
struct GfxWindowManagerAPI gfx_sdl = {
|
||||
gfx_sdl_init,
|
||||
gfx_sdl_close,
|
||||
gfx_sdl_get_display_mode,
|
||||
gfx_sdl_get_current_display_mode,
|
||||
gfx_sdl_get_num_display_modes,
|
||||
gfx_sdl_get_fullscreen_state,
|
||||
gfx_sdl_set_fullscreen_changed_callback,
|
||||
gfx_sdl_set_fullscreen,
|
||||
gfx_sdl_set_fullscreen_exclusive,
|
||||
gfx_sdl_set_fullscreen_flag,
|
||||
gfx_sdl_get_fullscreen_flag_mode,
|
||||
gfx_sdl_get_maximized_state,
|
||||
gfx_sdl_set_maximize_window,
|
||||
gfx_sdl_get_active_window_refresh_rate,
|
||||
gfx_sdl_set_cursor_visibility,
|
||||
gfx_sdl_set_closest_resolution,
|
||||
gfx_sdl_set_dimensions,
|
||||
gfx_sdl_get_dimensions,
|
||||
gfx_sdl_get_centered_positions,
|
||||
gfx_sdl_handle_events,
|
||||
gfx_sdl_start_frame,
|
||||
gfx_sdl_swap_buffers_begin,
|
||||
gfx_sdl_swap_buffers_end,
|
||||
gfx_sdl_get_time,
|
||||
gfx_sdl_get_target_fps,
|
||||
gfx_sdl_set_target_fps,
|
||||
gfx_sdl_can_disable_vsync,
|
||||
gfx_sdl_get_window_handle,
|
||||
gfx_sdl_set_window_title,
|
||||
gfx_sdl_get_swap_interval,
|
||||
gfx_sdl_set_swap_interval,
|
||||
};
|
||||
@@ -13,41 +13,28 @@ struct GfxWindowInitSettings {
|
||||
bool fullscreen;
|
||||
bool fullscreen_is_exclusive;
|
||||
bool maximized;
|
||||
bool centered;
|
||||
bool allow_hidpi;
|
||||
};
|
||||
|
||||
struct GfxWindowManagerAPI {
|
||||
void (*init)(const struct GfxWindowInitSettings *settings);
|
||||
void (*close)(void);
|
||||
int (*get_display_mode)(int modenum, int *out_w, int *out_h);
|
||||
int (*get_current_display_mode)(int *out_w, int *out_h);
|
||||
int (*get_num_display_modes)(void);
|
||||
int32_t (*get_fullscreen_state)(void);
|
||||
void (*set_fullscreen_changed_callback)(void (*on_fullscreen_changed)(bool is_now_fullscreen));
|
||||
void (*set_fullscreen)(bool enable);
|
||||
void (*set_fullscreen_exclusive)(bool exc);
|
||||
void (*set_fullscreen_flag)(int32_t mode);
|
||||
int32_t (*get_fullscreen_flag_mode)(void);
|
||||
int32_t (*get_maximized_state)(void);
|
||||
void (*set_maximize)(bool enable);
|
||||
void (*get_active_window_refresh_rate)(uint32_t* refresh_rate);
|
||||
void (*set_cursor_visibility)(bool visible);
|
||||
void (*set_closest_resolution)(int32_t width, int32_t height, bool should_center);
|
||||
void (*set_dimensions)(uint32_t width, uint32_t height, int32_t posX, int32_t posY);
|
||||
void (*get_dimensions)(uint32_t* width, uint32_t* height, int32_t* posX, int32_t* posY);
|
||||
void (*get_centered_positions)(int32_t width, int32_t height, int32_t *posX, int32_t *posY);
|
||||
void (*handle_events)(void);
|
||||
bool (*start_frame)(void);
|
||||
void (*swap_buffers_begin)(void);
|
||||
void (*swap_buffers_end)(void);
|
||||
double (*get_time)(void); // For debug
|
||||
int32_t (*get_target_fps)(void);
|
||||
void (*set_target_fps)(int fps);
|
||||
bool (*can_disable_vsync)(void);
|
||||
void *(*get_window_handle)(void);
|
||||
void (*set_window_title)(const char *);
|
||||
int (*get_swap_interval)(void);
|
||||
bool (*set_swap_interval)(int);
|
||||
};
|
||||
|
||||
|
||||
+844
-773
File diff suppressed because it is too large.
Load diff
+1492
-860
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,14 @@
|
||||
#ifndef _IN_CONSOLE_H
|
||||
#define _IN_CONSOLE_H
|
||||
|
||||
#include <PR/ultratypes.h>
|
||||
#include "types.h"
|
||||
|
||||
void conInit(void);
|
||||
Gfx *conRender(Gfx *gdl);
|
||||
void conTick(void);
|
||||
void conPrint(s32 showmsg, const char *s);
|
||||
void conPrintf(s32 showmsg, const char *fmt, ...);
|
||||
void conPrintLn(s32 showmsg, const char *s);
|
||||
|
||||
#endif
|
||||
Vendored
+5098
File diff suppressed because it is too large.
Load diff
+1
-2
@@ -19,9 +19,8 @@ s32 fsFileSize(const char *name);
|
||||
|
||||
FILE *fsFileOpenWrite(const char *name);
|
||||
FILE *fsFileOpenRead(const char *name);
|
||||
void fsFileFree(FILE *f);
|
||||
void fsFileClose(FILE *f);
|
||||
|
||||
const char *fsGetModDir(void);
|
||||
s32 fsCreateDir(const char *path);
|
||||
|
||||
#endif
|
||||
+82
-118
@@ -17,108 +17,88 @@
|
||||
#define CONT_NUM_BUTTONS 32 // not including the stick axes
|
||||
|
||||
enum virtkey {
|
||||
/* same order as SDL scancodes */
|
||||
VK_KEYBOARD_BEGIN = 0,
|
||||
VK_A = 4,
|
||||
VK_Z = 29,
|
||||
VK_1 = 30,
|
||||
VK_9 = 38,
|
||||
VK_0 = 39,
|
||||
VK_RETURN = 40,
|
||||
VK_ESCAPE = 41,
|
||||
VK_BACKSPACE = 42,
|
||||
VK_SPACE = 44,
|
||||
VK_MINUS = 45,
|
||||
VK_LEFTBRACKET = 47,
|
||||
VK_RIGHTBRACKET = 48,
|
||||
VK_SEMICOLON = 51,
|
||||
VK_GRAVE = 53,
|
||||
VK_COMMA = 54,
|
||||
VK_PERIOD = 55,
|
||||
VK_F1 = 58,
|
||||
VK_F9 = 66,
|
||||
VK_DELETE = 76,
|
||||
VK_LCTRL = 224,
|
||||
VK_LSHIFT = 225,
|
||||
VK_LALT = 226,
|
||||
VK_RCTRL = 228,
|
||||
VK_RSHIFT = 229,
|
||||
/* same order as SDL scancodes */
|
||||
VK_KEYBOARD_BEGIN = 0,
|
||||
VK_A = 4,
|
||||
VK_Z = 29,
|
||||
VK_1 = 30,
|
||||
VK_9 = 38,
|
||||
VK_0 = 39,
|
||||
VK_RETURN = 40,
|
||||
VK_ESCAPE = 41,
|
||||
VK_BACKSPACE = 42,
|
||||
VK_SPACE = 44,
|
||||
VK_MINUS = 45,
|
||||
VK_LEFTBRACKET = 47,
|
||||
VK_RIGHTBRACKET = 48,
|
||||
VK_SEMICOLON = 51,
|
||||
VK_GRAVE = 53,
|
||||
VK_COMMA = 54,
|
||||
VK_PERIOD = 55,
|
||||
VK_F1 = 58,
|
||||
VK_F9 = 66,
|
||||
VK_DELETE = 76,
|
||||
VK_LCTRL = 224,
|
||||
VK_LSHIFT = 225,
|
||||
VK_RCTRL = 228,
|
||||
VK_RSHIFT = 229,
|
||||
|
||||
/* same order as SDL mouse buttons */
|
||||
VK_MOUSE_BEGIN = 512,
|
||||
VK_MOUSE_LEFT = VK_MOUSE_BEGIN,
|
||||
VK_MOUSE_MIDDLE,
|
||||
VK_MOUSE_RIGHT,
|
||||
VK_MOUSE_X1,
|
||||
VK_MOUSE_X2,
|
||||
VK_MOUSE_WHEEL_UP,
|
||||
VK_MOUSE_WHEEL_DN,
|
||||
/* same order as SDL mouse buttons */
|
||||
VK_MOUSE_BEGIN = 512,
|
||||
VK_MOUSE_LEFT = VK_MOUSE_BEGIN,
|
||||
VK_MOUSE_MIDDLE,
|
||||
VK_MOUSE_RIGHT,
|
||||
VK_MOUSE_X1,
|
||||
VK_MOUSE_X2,
|
||||
VK_MOUSE_WHEEL_UP,
|
||||
VK_MOUSE_WHEEL_DN,
|
||||
|
||||
/* same order as SDL gamecontroller buttons plus two buttons for triggers */
|
||||
VK_JOY_BEGIN,
|
||||
VK_JOY1_BEGIN = VK_JOY_BEGIN,
|
||||
VK_JOY1_LSHOULDER = VK_JOY1_BEGIN + 9,
|
||||
VK_JOY1_RSHOULDER = VK_JOY1_BEGIN + 10,
|
||||
VK_JOY1_LTRIG = VK_JOY1_BEGIN + 30,
|
||||
VK_JOY1_RTRIG = VK_JOY1_BEGIN + 31,
|
||||
VK_JOY2_BEGIN = VK_JOY1_BEGIN + INPUT_MAX_CONTROLLER_BUTTONS,
|
||||
VK_JOY3_BEGIN = VK_JOY2_BEGIN + INPUT_MAX_CONTROLLER_BUTTONS,
|
||||
VK_JOY4_BEGIN = VK_JOY3_BEGIN + INPUT_MAX_CONTROLLER_BUTTONS,
|
||||
/* same order as SDL gamecontroller buttons plus two buttons for triggers */
|
||||
VK_JOY_BEGIN,
|
||||
VK_JOY1_BEGIN = VK_JOY_BEGIN,
|
||||
VK_JOY1_LTRIG = VK_JOY1_BEGIN + 30,
|
||||
VK_JOY1_RTRIG = VK_JOY1_BEGIN + 31,
|
||||
VK_JOY2_BEGIN = VK_JOY1_BEGIN + INPUT_MAX_CONTROLLER_BUTTONS,
|
||||
VK_JOY3_BEGIN = VK_JOY2_BEGIN + INPUT_MAX_CONTROLLER_BUTTONS,
|
||||
VK_JOY4_BEGIN = VK_JOY3_BEGIN + INPUT_MAX_CONTROLLER_BUTTONS,
|
||||
|
||||
VK_TOTAL_COUNT = VK_JOY_BEGIN + INPUT_MAX_CONTROLLERS * INPUT_MAX_CONTROLLER_BUTTONS,
|
||||
};
|
||||
|
||||
enum keymod {
|
||||
/* same order as SDL keymods */
|
||||
KM_LSHIFT = 0x0001,
|
||||
KM_RSHIFT = 0x0002,
|
||||
KM_LCTRL = 0x0040,
|
||||
KM_RCTRL = 0x0080,
|
||||
KM_CAPS = 0x2000,
|
||||
KM_CTRL = KM_LCTRL | KM_RCTRL,
|
||||
KM_SHIFT = KM_LSHIFT | KM_RSHIFT
|
||||
VK_TOTAL_COUNT = VK_JOY_BEGIN + INPUT_MAX_CONTROLLERS * INPUT_MAX_CONTROLLER_BUTTONS,
|
||||
};
|
||||
|
||||
enum contkey {
|
||||
CK_C_R,
|
||||
CK_C_L,
|
||||
CK_C_D,
|
||||
CK_C_U,
|
||||
CK_RTRIG,
|
||||
CK_LTRIG,
|
||||
CK_X, // gap in CONT_
|
||||
CK_Y, // gap in CONT_
|
||||
CK_DPAD_R,
|
||||
CK_DPAD_L,
|
||||
CK_DPAD_D,
|
||||
CK_DPAD_U,
|
||||
CK_START,
|
||||
CK_ZTRIG,
|
||||
CK_B,
|
||||
CK_A,
|
||||
CK_STICK_XNEG,
|
||||
CK_STICK_XPOS,
|
||||
CK_STICK_YNEG,
|
||||
CK_STICK_YPOS,
|
||||
CK_ACCEPT,
|
||||
CK_CANCEL,
|
||||
CK_0040,
|
||||
CK_0080,
|
||||
CK_0100,
|
||||
CK_0200,
|
||||
CK_0400,
|
||||
CK_0800,
|
||||
CK_1000,
|
||||
CK_2000,
|
||||
CK_4000,
|
||||
CK_8000,
|
||||
CK_TOTAL_COUNT
|
||||
};
|
||||
|
||||
enum mouselockmode {
|
||||
MLOCK_OFF = 0,
|
||||
MLOCK_ON = 1,
|
||||
MLOCK_AUTO = 2
|
||||
CK_C_R,
|
||||
CK_C_L,
|
||||
CK_C_D,
|
||||
CK_C_U,
|
||||
CK_RTRIG,
|
||||
CK_LTRIG,
|
||||
CK_X, // gap in CONT_
|
||||
CK_Y, // gap in CONT_
|
||||
CK_DPAD_R,
|
||||
CK_DPAD_L,
|
||||
CK_DPAD_D,
|
||||
CK_DPAD_U,
|
||||
CK_START,
|
||||
CK_ZTRIG,
|
||||
CK_B,
|
||||
CK_A,
|
||||
CK_STICK_XNEG,
|
||||
CK_STICK_XPOS,
|
||||
CK_STICK_YNEG,
|
||||
CK_STICK_YPOS,
|
||||
CK_0010,
|
||||
CK_0020,
|
||||
CK_0040,
|
||||
CK_0080,
|
||||
CK_0100,
|
||||
CK_0200,
|
||||
CK_0400,
|
||||
CK_0800,
|
||||
CK_1000,
|
||||
CK_2000,
|
||||
CK_4000,
|
||||
CK_8000,
|
||||
CK_TOTAL_COUNT
|
||||
};
|
||||
|
||||
// returns bitmask of connected controllers or -1 if failed
|
||||
@@ -145,10 +125,6 @@ void inputControllerSetSticksSwapped(s32 cidx, s32 swapped);
|
||||
s32 inputControllerGetDualAnalog(s32 cidx);
|
||||
void inputControllerSetDualAnalog(s32 cidx, s32 enable);
|
||||
|
||||
// get/set Input.Player%d.CancelCButtons
|
||||
s32 inputControllerGetCancelCButtons(s32 cidx);
|
||||
void inputControllerSetCancelCButtons(s32 cidx, s32 cancel);
|
||||
|
||||
// get/set sensitivity for a given player
|
||||
f32 inputControllerGetAxisScale(s32 cidx, s32 stick, s32 axis);
|
||||
void inputControllerSetAxisScale(s32 cidx, s32 stick, s32 axis, f32 value);
|
||||
@@ -176,7 +152,6 @@ s32 inputAssignController(s32 cidx, s32 id);
|
||||
|
||||
// vk is a value from the virtkey enum above
|
||||
s32 inputKeyPressed(u32 vk);
|
||||
s32 inputKeyJustPressed(u32 vk);
|
||||
|
||||
// idx is controller index, contbtn is one of the CONT_ constants
|
||||
s32 inputButtonPressed(s32 idx, u32 contbtn);
|
||||
@@ -211,9 +186,8 @@ void inputLockMouse(s32 lock);
|
||||
// returns the current state of the above
|
||||
s32 inputMouseIsLocked(void);
|
||||
|
||||
// sets x, y to mouse position in native viewport coordinates (ie, 320x240 most of the time)
|
||||
// returns true if mouse has moved this input frame
|
||||
s32 inputMouseGetPosition(s32 *x, s32 *y);
|
||||
// returns mouse position in native viewport coordinates (ie, 320x240 most of the time)
|
||||
void inputMouseGetPosition(s32 *x, s32 *y);
|
||||
|
||||
// returns changes in mouse position since last frame, in window coordinates
|
||||
void inputMouseGetRawDelta(s32 *dx, s32 *dy);
|
||||
@@ -245,29 +219,19 @@ void inputSetDefaultKeyBinds(s32 cidx, s32 n64mode);
|
||||
void inputClearLastKey(void);
|
||||
s32 inputGetLastKey(void);
|
||||
|
||||
// get/set Input.MouseLockMode
|
||||
s32 inputGetMouseLockMode(void);
|
||||
void inputSetMouseLockMode(s32 lockmode);
|
||||
|
||||
// same as inputLockMouse but works only if mouse is enabled and lockmode == MLOCK_AUTO
|
||||
s32 inputAutoLockMouse(s32 wantlock);
|
||||
|
||||
// show/hide mouse cursor; if mouse lock is on the cursor is always hidden
|
||||
void inputMouseShowCursor(s32 show);
|
||||
|
||||
void inputStartTextInput(void);
|
||||
void inputStopTextInput(void);
|
||||
s32 inputIsTextInputActive(void);
|
||||
|
||||
void inputClearLastTextChar(void);
|
||||
char inputGetLastTextChar(void);
|
||||
|
||||
s32 inputTextHandler(char *out, const u32 outSize, s32 *curCol, s32 oskCharsOnly);
|
||||
s32 inputTextHandler(char *out, const u32 outSize, s32 *curCol);
|
||||
|
||||
void inputClearClipboard(void);
|
||||
const char *inputGetClipboard(void);
|
||||
|
||||
// returns keymod values
|
||||
u32 inputGetKeyModState(void);
|
||||
// get/set Input.MouseDefaultLocked
|
||||
s32 inputGetMouseDefaultLocked(void);
|
||||
void inputSetMouseDefaultLocked(s32 defaultLocked);
|
||||
|
||||
#endif
|
||||
@@ -1,12 +0,0 @@
|
||||
#ifndef _IN_MPSETUPS_H
|
||||
#define _IN_MPSETUPS_H
|
||||
|
||||
#include "types.h"
|
||||
|
||||
s32 mpsetupLoadCurrentFile(void);
|
||||
s32 mpsetupSaveCurrentFile(void);
|
||||
void mpsetupLoadSetup(s32 slotindex);
|
||||
s32 mpsetupSaveSetup(s32 slotindex, u8 savefile);
|
||||
void mpsetupCopyAllFromPak(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,163 @@
|
||||
#ifndef _IN_NET_H
|
||||
#define _IN_NET_H
|
||||
|
||||
#include "types.h"
|
||||
#include "constants.h"
|
||||
#include "net/netbuf.h"
|
||||
|
||||
#define NET_PROTOCOL_VER 12
|
||||
|
||||
#define NET_QUERY_MAGIC "PDQM\x01"
|
||||
|
||||
#define NET_MAX_CLIENTS MAX_PLAYERS
|
||||
#define NET_MAX_NAME MAX_PLAYERNAME
|
||||
#define NET_MAX_ADDR 256
|
||||
|
||||
#define NET_BUFSIZE 1440
|
||||
|
||||
#define NET_DEFAULT_PORT 27100
|
||||
|
||||
#define NET_NULL_CLIENT 0xFF
|
||||
#define NET_NULL_PROP 0
|
||||
|
||||
#define NETCHAN_DEFAULT 0
|
||||
#define NETCHAN_CONTROL 1
|
||||
#define NETCHAN_COUNT 2
|
||||
|
||||
#define DISCONNECT_UNKNOWN 0
|
||||
#define DISCONNECT_SHUTDOWN 1
|
||||
#define DISCONNECT_VERSION 2
|
||||
#define DISCONNECT_KICKED 3
|
||||
#define DISCONNECT_BANNED 4
|
||||
#define DISCONNECT_TIMEOUT 5
|
||||
#define DISCONNECT_FULL 6
|
||||
#define DISCONNECT_LATE 7
|
||||
#define DISCONNECT_FILES 8
|
||||
|
||||
#define CLSTATE_DISCONNECTED 0
|
||||
#define CLSTATE_CONNECTING 1
|
||||
#define CLSTATE_AUTH 2
|
||||
#define CLSTATE_LOBBY 3
|
||||
#define CLSTATE_GAME 4
|
||||
|
||||
#define UCMD_FIRE (1 << 0)
|
||||
#define UCMD_ACTIVATE (1 << 1)
|
||||
#define UCMD_RELOAD (1 << 2)
|
||||
#define UCMD_AIMMODE (1 << 3)
|
||||
#define UCMD_DUCK (1 << 4)
|
||||
#define UCMD_SQUAT (1 << 5)
|
||||
#define UCMD_ZOOMIN (1 << 6)
|
||||
#define UCMD_SELECT (1 << 7)
|
||||
#define UCMD_SELECT_DUAL (1 << 8)
|
||||
#define UCMD_EYESSHUT (1 << 9)
|
||||
#define UCMD_SECONDARY (1 << 10)
|
||||
#define UCMD_RESPAWN (1 << 27)
|
||||
#define UCMD_CHAT (1 << 28)
|
||||
#define UCMD_IMPORTANT_MASK (UCMD_FIRE | UCMD_ACTIVATE | UCMD_RELOAD | UCMD_AIMMODE | UCMD_SELECT | UCMD_SELECT_DUAL)
|
||||
#define UCMD_FL_FORCEPOS (1 << 29)
|
||||
#define UCMD_FL_FORCEANGLE (1 << 30)
|
||||
#define UCMD_FL_FORCEGROUND (1 << 31)
|
||||
#define UCMD_FL_FORCEMASK (UCMD_FL_FORCEPOS | UCMD_FL_FORCEANGLE | UCMD_FL_FORCEGROUND)
|
||||
|
||||
struct netplayermove {
|
||||
u32 tick; // g_NetTIck value when this struct was written; if 0, this struct is invalid
|
||||
u32 ucmd; // player commands (UCMD_)
|
||||
f32 leanofs; // analog lean value (-1 .. 1; equal to player->swaytarget / 75.f)
|
||||
f32 crouchofs; // analog crouch value (-90 for SQUAT, 0 for STAND; player->crouchofs)
|
||||
f32 zoomfov; // manual zoom fov for the current gun; synced only if UCMD_AIMING is set
|
||||
f32 movespeed[2]; // move inputs, [0] is forward, [1] is sideways; used mostly for animation
|
||||
f32 angles[2]; // view angles, [0] is theta, [1] is verta
|
||||
f32 crosspos[2]; // crosshair position in aiming mode; normalized to default aspect ratio
|
||||
s8 weaponnum; // switch to this weapon if UCMD_SELECT is set
|
||||
struct coord pos; // player position at g_NetTick == tick
|
||||
};
|
||||
|
||||
struct netclient {
|
||||
struct _ENetPeer *peer;
|
||||
u32 id; // remote client number, server is always 0, even on clients
|
||||
u32 state; // CLSTATE_
|
||||
u32 flags; // CLFLAG_
|
||||
|
||||
struct {
|
||||
char name[NET_MAX_NAME];
|
||||
u16 options;
|
||||
u8 headnum;
|
||||
u8 bodynum;
|
||||
u8 team;
|
||||
f32 fovy;
|
||||
f32 fovzoommult;
|
||||
} settings;
|
||||
|
||||
struct mpplayerconfig *config;
|
||||
struct player *player;
|
||||
u8 playernum;
|
||||
|
||||
struct netplayermove outmove[2]; // last 2 outgoing player inputs, newest one first
|
||||
struct netplayermove inmove[2]; // last 2 incoming player inputs, newest one first
|
||||
u32 inmovetick; // last inmove tick which was applied to the player
|
||||
u32 outmoveack; // last acked outmove tick
|
||||
u32 forcetick; // tick on which the client's position was forced, or 0 if not forcing
|
||||
u32 lerpticks; // how many ticks we've been lerping the position
|
||||
|
||||
struct netbuf out; // outbound messages are written here, except broadcasts
|
||||
struct netbuf in; // incoming packets are fed here
|
||||
|
||||
u8 out_data[NET_BUFSIZE]; // buffer for out
|
||||
};
|
||||
|
||||
extern s32 g_NetMode;
|
||||
|
||||
extern s32 g_NetJoinLatch;
|
||||
extern s32 g_NetHostLatch;
|
||||
|
||||
// net frame, ticks at 60 fps, starts at 0 when the server is started
|
||||
extern u32 g_NetTick;
|
||||
extern u32 g_NetNextSyncId;
|
||||
|
||||
extern u64 g_NetRngSeeds[2];
|
||||
extern u32 g_NetRngLatch;
|
||||
|
||||
extern u32 g_NetInterpTicks;
|
||||
extern u32 g_NetServerPort;
|
||||
extern char g_NetLastJoinAddr[NET_MAX_ADDR + 1];
|
||||
|
||||
extern s32 g_NetDebugDraw;
|
||||
|
||||
extern s32 g_NetMaxClients;
|
||||
extern s32 g_NetNumClients;
|
||||
extern struct netclient g_NetClients[NET_MAX_CLIENTS + 1]; // last is an extra temporary client
|
||||
extern struct netclient *g_NetLocalClient;
|
||||
|
||||
extern struct netbuf g_NetMsg;
|
||||
extern struct netbuf g_NetMsgRel;
|
||||
|
||||
const char *netFormatClientAddr(const struct netclient *cl);
|
||||
|
||||
void netInit(void);
|
||||
s32 netDisconnect(void);
|
||||
void netStartFrame(void);
|
||||
void netEndFrame(void);
|
||||
|
||||
s32 netStartServer(u16 port, s32 maxclients);
|
||||
s32 netStartClient(const char *addr);
|
||||
|
||||
u32 netSend(struct netclient *dstcl, struct netbuf *buf, const s32 reliable, const s32 chan);
|
||||
|
||||
void netChat(struct netclient *dst, const char *text);
|
||||
void netChatPrintf(struct netclient *dst, const char *fmt, ...);
|
||||
|
||||
void netServerStageStart(void);
|
||||
void netServerStageEnd(void);
|
||||
void netServerKick(struct netclient *cl, const u32 reason);
|
||||
|
||||
struct netclient *netClientForPlayerNum(s32 playernum);
|
||||
|
||||
void netClientSyncRng(void);
|
||||
void netClientSettingsChanged(void);
|
||||
|
||||
void netPlayersAllocate(void);
|
||||
void netSyncIdsAllocate(void);
|
||||
|
||||
Gfx *netDebugRender(Gfx *gdl);
|
||||
|
||||
#endif // _IN_NET_H
|
||||
@@ -0,0 +1,50 @@
|
||||
#ifndef _IN_NETBUF_H
|
||||
#define _IN_NETBUF_H
|
||||
|
||||
#include "types.h"
|
||||
|
||||
struct netbuf {
|
||||
u8 *data;
|
||||
u32 size;
|
||||
u32 rp;
|
||||
u32 wp;
|
||||
u32 error;
|
||||
};
|
||||
|
||||
void netbufStartRead(struct netbuf *buf);
|
||||
void netbufStartReadData(struct netbuf *buf, const void *data, u32 size);
|
||||
s32 netbufReadLeft(const struct netbuf *buf);
|
||||
u32 netbufReadData(struct netbuf *buf, void *out, u32 num);
|
||||
u8 netbufReadU8(struct netbuf *buf);
|
||||
u16 netbufReadU16(struct netbuf *buf);
|
||||
u32 netbufReadU32(struct netbuf *buf);
|
||||
u64 netbufReadU64(struct netbuf *buf);
|
||||
s8 netbufReadS8(struct netbuf *buf);
|
||||
s16 netbufReadS16(struct netbuf *buf);
|
||||
s32 netbufReadS32(struct netbuf *buf);
|
||||
s64 netbufReadS64(struct netbuf *buf);
|
||||
f32 netbufReadF32(struct netbuf *buf);
|
||||
char *netbufReadStr(struct netbuf *buf);
|
||||
u32 netbufReadCoord(struct netbuf *buf, struct coord *out);
|
||||
u32 netbufReadMtxf(struct netbuf *buf, Mtxf *out);
|
||||
u32 netbufReadSkip(struct netbuf *buf, u32 count);
|
||||
|
||||
void netbufStartWrite(struct netbuf *buf);
|
||||
s32 netbufWriteLeft(const struct netbuf *buf);
|
||||
u32 netbufWriteData(struct netbuf *buf, const void *data, u32 num);
|
||||
u32 netbufWriteU8(struct netbuf *buf, const u8 v);
|
||||
u32 netbufWriteU16(struct netbuf *buf, const u16 v);
|
||||
u32 netbufWriteU32(struct netbuf *buf, const u32 v);
|
||||
u32 netbufWriteU64(struct netbuf *buf, const u64 v);
|
||||
u32 netbufWriteS8(struct netbuf *buf, const s8 v);
|
||||
u32 netbufWriteS16(struct netbuf *buf, const s16 v);
|
||||
u32 netbufWriteS32(struct netbuf *buf, const s32 v);
|
||||
u32 netbufWriteS64(struct netbuf *buf, const s64 v);
|
||||
u32 netbufWriteF32(struct netbuf *buf, const f32 v);
|
||||
u32 netbufWriteStr(struct netbuf *buf, const char *v);
|
||||
u32 netbufWriteCoord(struct netbuf *buf, const struct coord *v);
|
||||
u32 netbufWriteMtxf(struct netbuf *buf, const Mtxf *in);
|
||||
|
||||
void netbufReset(struct netbuf *buf);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,10 @@
|
||||
#ifndef _IN_NETENET_H
|
||||
#define _IN_NETENET_H
|
||||
|
||||
#define ENET_NO_PRAGMA_LINK 1
|
||||
#include "external/enet.h"
|
||||
#undef bool
|
||||
#undef near
|
||||
#undef far
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,74 @@
|
||||
#ifndef _IN_NETMSG_H
|
||||
#define _IN_NETMSG_H
|
||||
|
||||
#include <PR/ultratypes.h>
|
||||
#include "net/net.h"
|
||||
#include "net/netbuf.h"
|
||||
|
||||
#define SVC_BAD 0x00 // trash
|
||||
#define SVC_NOP 0x01 // does nothing
|
||||
#define SVC_AUTH 0x02 // auth response, sent in response to CLC_AUTH
|
||||
#define SVC_CHAT 0x03 // chat message
|
||||
#define SVC_STAGE_START 0x10 // start level
|
||||
#define SVC_STAGE_END 0x11 // end level
|
||||
#define SVC_PLAYER_MOVE 0x20 // player movement and inputs
|
||||
#define SVC_PLAYER_GUNS 0x21 // player gun state
|
||||
#define SVC_PLAYER_STATS 0x22 // player stats (health etc)
|
||||
#define SVC_PROP_MOVE 0x30 // prop movement
|
||||
#define SVC_PROP_SPAWN 0x31 // new prop spawned
|
||||
#define SVC_PROP_DAMAGE 0x32 // prop was damaged
|
||||
#define SVC_PROP_PICKUP 0x33 // prop was picked up
|
||||
#define SVC_PROP_USE 0x34 // door/lift/etc was used
|
||||
#define SVC_PROP_DOOR 0x35 // door state changed
|
||||
#define SVC_PROP_LIFT 0x36 // lift state changed
|
||||
#define SVC_CHR_DAMAGE 0x42 // chr was damaged
|
||||
#define SVC_CHR_DISARM 0x43 // chr's weapons were dropped
|
||||
|
||||
#define CLC_BAD 0x00 // trash
|
||||
#define CLC_NOP 0x01 // does nothing
|
||||
#define CLC_AUTH 0x02 // auth request, sent immediately after connecting
|
||||
#define CLC_CHAT 0x03 // chat message
|
||||
#define CLC_MOVE 0x04 // player input
|
||||
#define CLC_SETTINGS 0x05 // player settings changed
|
||||
|
||||
u32 netmsgClcAuthWrite(struct netbuf *dst);
|
||||
u32 netmsgClcAuthRead(struct netbuf *src, struct netclient *srccl);
|
||||
u32 netmsgClcChatWrite(struct netbuf *dst, const char *str);
|
||||
u32 netmsgClcChatRead(struct netbuf *src, struct netclient *srccl);
|
||||
u32 netmsgClcMoveWrite(struct netbuf *dst);
|
||||
u32 netmsgClcMoveRead(struct netbuf *src, struct netclient *srccl);
|
||||
u32 netmsgClcSettingsWrite(struct netbuf *dst);
|
||||
u32 netmsgClcSettingsRead(struct netbuf *src, struct netclient *srccl);
|
||||
|
||||
u32 netmsgSvcAuthWrite(struct netbuf *dst, struct netclient *authcl);
|
||||
u32 netmsgSvcAuthRead(struct netbuf *src, struct netclient *srccl);
|
||||
u32 netmsgSvcChatWrite(struct netbuf *dst, const char *str);
|
||||
u32 netmsgSvcChatRead(struct netbuf *src, struct netclient *srccl);
|
||||
u32 netmsgSvcStageStartWrite(struct netbuf *dst);
|
||||
u32 netmsgSvcStageStartRead(struct netbuf *src, struct netclient *srccl);
|
||||
u32 netmsgSvcStageEndWrite(struct netbuf *dst);
|
||||
u32 netmsgSvcStageEndRead(struct netbuf *src, struct netclient *srccl);
|
||||
u32 netmsgSvcPlayerMoveWrite(struct netbuf *dst, struct netclient *movecl);
|
||||
u32 netmsgSvcPlayerMoveRead(struct netbuf *src, struct netclient *srccl);
|
||||
u32 netmsgSvcPlayerStatsWrite(struct netbuf *dst, struct netclient *actcl);
|
||||
u32 netmsgSvcPlayerStatsRead(struct netbuf *src, struct netclient *srccl);
|
||||
u32 netmsgSvcPropSpawnWrite(struct netbuf *dst, struct prop *prop);
|
||||
u32 netmsgSvcPropSpawnRead(struct netbuf *src, struct netclient *srccl);
|
||||
u32 netmsgSvcPropMoveWrite(struct netbuf *dst, struct prop *prop, struct coord *initrot);
|
||||
u32 netmsgSvcPropMoveRead(struct netbuf *src, struct netclient *srccl);
|
||||
u32 netmsgSvcPropDamageWrite(struct netbuf *dst, struct prop *prop, f32 damage, struct coord *pos, s32 weaponnum, s32 playernum);
|
||||
u32 netmsgSvcPropDamageRead(struct netbuf *src, struct netclient *srccl);
|
||||
u32 netmsgSvcPropPickupWrite(struct netbuf *dst, struct netclient *actcl, struct prop *prop, const s32 tickop);
|
||||
u32 netmsgSvcPropPickupRead(struct netbuf *src, struct netclient *srccl);
|
||||
u32 netmsgSvcPropUseWrite(struct netbuf *dst, struct prop *prop, struct netclient *usercl, const s32 tickop);
|
||||
u32 netmsgSvcPropUseRead(struct netbuf *src, struct netclient *srccl);
|
||||
u32 netmsgSvcPropDoorWrite(struct netbuf *dst, struct prop *prop, struct netclient *usercl);
|
||||
u32 netmsgSvcPropDoorRead(struct netbuf *src, struct netclient *srccl);
|
||||
u32 netmsgSvcPropLiftWrite(struct netbuf *dst, struct prop *prop);
|
||||
u32 netmsgSvcPropLiftRead(struct netbuf *src, struct netclient *srccl);
|
||||
u32 netmsgSvcChrDamageWrite(struct netbuf *dst, struct chrdata *chr, f32 damage, struct coord *vector, struct gset *gset, struct prop *aprop, s32 hitpart, bool damageshield, struct prop *prop2, s32 side, s16 *arg11, bool explosion, struct coord *explosionpos);
|
||||
u32 netmsgSvcChrDamageRead(struct netbuf *src, struct netclient *srccl);
|
||||
u32 netmsgSvcChrDisarmWrite(struct netbuf *dst, struct chrdata *chr, struct prop *attacker, u8 weaponnum, f32 wpndamage, struct coord *wpnpos);
|
||||
u32 netmsgSvcChrDisarmRead(struct netbuf *src, struct netclient *srccl);
|
||||
|
||||
#endif
|
||||
+21
-19
@@ -3,30 +3,32 @@
|
||||
|
||||
#include <PR/ultratypes.h>
|
||||
|
||||
typedef u8 *(*preprocessfunc)(u8 *data, u32 size, u32 *outSize);
|
||||
typedef void (*preprocessfunc)(u8 *data, u32 size);
|
||||
|
||||
u8* preprocessAnimations(u8 *data, u32 size, u32 *outSize);
|
||||
u8* preprocessMpConfigs(u8 *data, u32 size, u32 *outSize);
|
||||
u8* preprocessFont(u8 *data, u32 size, u32 *outSize);
|
||||
u8* preprocessJpnFont(u8 *data, u32 size, u32 *outSize);
|
||||
u8* preprocessALBankFile(u8 *data, u32 size, u32 *outSize);
|
||||
u8 *preprocessALCMidiHdr(u8 *data, u32 size, u32 *outSize);
|
||||
u8* preprocessSequences(u8 *data, u32 size, u32 *outSize);
|
||||
u8* preprocessTexturesList(u8 *data, u32 size, u32 *outSize);
|
||||
void preprocessAnimations(u8 *data, u32 size);
|
||||
void preprocessMpConfigs(u8 *data, u32 size);
|
||||
void preprocessFont(u8 *data, u32 size);
|
||||
void preprocessJpnFont(u8 *data, u32 size);
|
||||
void preprocessALBankFile(u8 *data, u32 size);
|
||||
void preprocessALCMidiHdr(u8 *data, u32 size);
|
||||
void preprocessSequences(u8 *data, u32 size);
|
||||
void preprocessFiringRange(u8 *data, u32 size);
|
||||
void preprocessTexturesList(u8 *data, u32 size);
|
||||
|
||||
void preprocessBgSection1(u8* data, u32 size, u32 ofs);
|
||||
void preprocessBgSection2(u8 *data, u32 size);
|
||||
void preprocessBgSection3(u8* data, u32 size);
|
||||
void preprocessBgSection1Header(u8 *data, u32 size);
|
||||
void preprocessBgSection1(u8 *data, u32 size);
|
||||
void preprocessBgSection2Header(u8 *data, u32 size);
|
||||
void preprocessBgSection2(u8 *data, u32 size);
|
||||
void preprocessBgSection3Header(u8 *data, u32 size);
|
||||
u32 preprocessBgRoom(u8* data, u32 size, u32 room_ofs);
|
||||
void preprocessBgSection3(u8 *data, u32 size);
|
||||
void preprocessBgRoom(u8 *data, u32 ofs);
|
||||
void preprocessBgLights(u8 *data, u32 ofs);
|
||||
|
||||
u8 *preprocessLangFile(u8 *data, u32 size, u32 *outSize);
|
||||
u8 *preprocessPadsFile(u8 *data, u32 size, u32 *outSize);
|
||||
u8 *preprocessTilesFile(u8 *data, u32 size, u32 *outSize);
|
||||
u8 *preprocessSetupFile(u8 *data, u32 size, u32 *outSize);
|
||||
u8 *preprocessModelFile(u8 *data, u32 size, u32 *outSize);
|
||||
u8 *preprocessGunFile(u8 *data, u32 size, u32 *outSize);
|
||||
void preprocessLangFile(u8 *data, u32 size);
|
||||
void preprocessPadsFile(u8 *data, u32 size);
|
||||
void preprocessTilesFile(u8 *data, u32 size);
|
||||
void preprocessSetupFile(u8 *data, u32 size);
|
||||
void preprocessModelFile(u8 *data, u32 size);
|
||||
void preprocessGunFile(u8 *data, u32 size);
|
||||
|
||||
#endif
|
||||
@@ -1,59 +0,0 @@
|
||||
#ifndef _IN_PREPROCESS_COMMON_H
|
||||
#define _IN_PREPROCESS_COMMON_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <PR/ultratypes.h>
|
||||
#include "types.h"
|
||||
#include "constants.h"
|
||||
|
||||
#include "platform.h"
|
||||
#include "system.h"
|
||||
#include "romdata.h"
|
||||
#include "preprocess.h"
|
||||
|
||||
#define MAX_PTR_MARKERS (1024 * 8)
|
||||
|
||||
#define PD_ALIGN(val, size) (((val) + ((size) - 1)) & ~((size) - 1))
|
||||
|
||||
#define PD_PTR_BASE(x, b) (void *)((u8 *)b + (uintptr_t)x)
|
||||
#define PD_PTR_BASEOFS(x, b, d) (void *)((u8 *)b - d + (uintptr_t)x)
|
||||
|
||||
static inline f32 swapF32(f32 x) { *(u32*)&x = PD_BE32(*(u32*)&x); return x; }
|
||||
static inline u32 swapU32(u32 x) { return PD_BE32(x); }
|
||||
static inline s32 swapS32(s32 x) { return PD_BE32(x); }
|
||||
static inline u16 swapU16(u16 x) { return PD_BE16(x); }
|
||||
static inline s16 swapS16(s16 x) { return PD_BE16(x); }
|
||||
static inline void* swapPtr(void** x) { return (void*)PD_BEPTR((uintptr_t)x); }
|
||||
static inline struct coord swapCrd(struct coord crd) { crd.x = swapF32(crd.x); crd.y = swapF32(crd.y); crd.z = swapF32(crd.z); return crd; }
|
||||
static inline u32 swapUnk(u32 x) { assert(0 && "unknown type"); return x; }
|
||||
|
||||
#define PD_SWAPPED_VAL(x) _Generic((x), \
|
||||
f32: swapF32, \
|
||||
u32: swapU32, \
|
||||
s32: swapS32, \
|
||||
u16: swapU16, \
|
||||
s16: swapS16, \
|
||||
struct coord: swapCrd, \
|
||||
default: swapUnk \
|
||||
)(x)
|
||||
|
||||
#define PD_SWAP_VAL(x) x = PD_SWAPPED_VAL(x)
|
||||
|
||||
#define PD_SWAP_PTR(x) x = swapPtr((void *)(x))
|
||||
|
||||
// ptr marker functions
|
||||
|
||||
struct ptrmarker {
|
||||
u32 ptr_src;
|
||||
uintptr_t ptr_host;
|
||||
};
|
||||
|
||||
void ptrAdd(u32 ptr_src, uintptr_t ptr_host);
|
||||
struct ptrmarker* ptrFind(uintptr_t ptr_src);
|
||||
void ptrReset(void);
|
||||
|
||||
#endif
|
||||
@@ -1,15 +0,0 @@
|
||||
#ifndef _IN_PREPROCESS_GBI_H
|
||||
#define _IN_PREPROCESS_GBI_H
|
||||
|
||||
#include "preprocess/common.h"
|
||||
|
||||
// gbi related functions
|
||||
void gbiReset(void);
|
||||
void gbiSetSegment(int segment, u32 offset);
|
||||
void gbiSetVtx(u32 src_offset, u32 dst_offset);
|
||||
u32 gbiConvertGdl(u8 *dst, u32 dstpos, u8 *src, u32 srcpos, int segment_cmds);
|
||||
void gbiConvertVtx(u8* dst, u32 dstpos, int count);
|
||||
void gbiGdlRewriteAddrs(u8* dst, u32 offset);
|
||||
void gbiAddTexAddr(u32 src_offset, u32 dst_offset);
|
||||
|
||||
#endif
|
||||
@@ -1,640 +0,0 @@
|
||||
#ifndef _IN_SETUP_DECL
|
||||
#define _IN_SETUP_DECL
|
||||
|
||||
#include "preprocess/common.h"
|
||||
|
||||
struct n64_stagesetup {
|
||||
u32 ptr_waypoints;
|
||||
u32 ptr_waygroups;
|
||||
u32 ptr_cover;
|
||||
u32 ptr_intro;
|
||||
u32 ptr_props;
|
||||
u32 ptr_paths;
|
||||
u32 ptr_ailists;
|
||||
u32 ptr_padfiledata;
|
||||
};
|
||||
|
||||
struct n64_coord {
|
||||
f32 x;
|
||||
f32 y;
|
||||
f32 z;
|
||||
};
|
||||
|
||||
struct n64_defaultobj {
|
||||
u16 extrascale;
|
||||
u8 hidden2;
|
||||
u8 type;
|
||||
s16 modelnum;
|
||||
s16 pad;
|
||||
u32 flags;
|
||||
u32 flags2;
|
||||
u32 flags3;
|
||||
u32 ptr_prop;
|
||||
u32 ptr_model;
|
||||
f32 realrot[3][3];
|
||||
u32 hidden;
|
||||
union {
|
||||
u32 ptr_geotilef;
|
||||
u32 ptr_geoblock;
|
||||
u32 ptr_geocyl;
|
||||
u32 ptr_unkgeo;
|
||||
};
|
||||
union {
|
||||
u32 ptr_projectile;
|
||||
u32 ptr_embedment;
|
||||
};
|
||||
s16 damage;
|
||||
s16 maxdamage;
|
||||
u8 shadecol[4];
|
||||
u8 nextcol[4];
|
||||
u16 floorcol;
|
||||
s8 geocount;
|
||||
s8 _pad_;
|
||||
};
|
||||
|
||||
struct n64_doorobj {
|
||||
struct n64_defaultobj base;
|
||||
f32 maxfrac;
|
||||
f32 perimfrac;
|
||||
f32 accel;
|
||||
f32 decel;
|
||||
f32 maxspeed;
|
||||
u16 doorflags;
|
||||
u16 doortype;
|
||||
u32 keyflags;
|
||||
s32 autoclosetime;
|
||||
f32 frac;
|
||||
f32 fracspeed;
|
||||
s8 mode;
|
||||
s8 glasshits;
|
||||
s16 fadealpha;
|
||||
s16 xludist;
|
||||
s16 opadist;
|
||||
struct n64_coord startpos;
|
||||
f32 mtx98[3][3];
|
||||
u32 ptr_sibling;
|
||||
s32 lastopen60;
|
||||
s16 portalnum;
|
||||
s8 soundtype;
|
||||
s8 fadetime60;
|
||||
s32 lastcalc60;
|
||||
u8 laserfade;
|
||||
u8 unusedmaybe[3];
|
||||
u8 shadeinfo1[4];
|
||||
u8 shadeinfo2[4];
|
||||
u8 actual1;
|
||||
u8 actual2;
|
||||
u8 extra1;
|
||||
u8 extra2;
|
||||
};
|
||||
|
||||
struct n64_doorscaleobj {
|
||||
u32 unk00;
|
||||
s32 scale;
|
||||
};
|
||||
|
||||
struct n64_keyobj {
|
||||
struct n64_defaultobj base;
|
||||
u32 keyflags;
|
||||
};
|
||||
|
||||
struct n64_alarmobj {
|
||||
struct n64_defaultobj base;
|
||||
};
|
||||
|
||||
struct n64_cctvobj {
|
||||
struct n64_defaultobj base;
|
||||
|
||||
s16 lookatpadnum;
|
||||
s16 toleft;
|
||||
//Mtxf camrotm;
|
||||
f32 m[4][4];
|
||||
f32 yzero;
|
||||
f32 yrot;
|
||||
f32 yleft;
|
||||
f32 yright;
|
||||
f32 yspeed;
|
||||
f32 ymaxspeed;
|
||||
s32 seebondtime60;
|
||||
f32 maxdist;
|
||||
f32 xzero;
|
||||
};
|
||||
|
||||
struct n64_ammocrateobj {
|
||||
struct n64_defaultobj base;
|
||||
s32 ammotype;
|
||||
};
|
||||
|
||||
struct n64_gset {
|
||||
u8 weaponnum;
|
||||
u8 unk0639;
|
||||
u8 unk063a;
|
||||
u8 weaponfunc;
|
||||
};
|
||||
|
||||
struct n64_weaponobj {
|
||||
struct n64_defaultobj base;
|
||||
|
||||
union {
|
||||
struct n64_gset gset;
|
||||
struct {
|
||||
u8 weaponnum;
|
||||
s8 unk5d;
|
||||
s8 unk5e;
|
||||
u8 gunfunc;
|
||||
};
|
||||
};
|
||||
|
||||
s8 fadeouttimer60;
|
||||
s8 dualweaponnum;
|
||||
|
||||
union {
|
||||
s16 timer240;
|
||||
s16 team;
|
||||
};
|
||||
|
||||
u32 ptr_dualweapon;
|
||||
};
|
||||
|
||||
struct n64_packedchr {
|
||||
s16 chrindex;
|
||||
s8 unk02;
|
||||
s8 typenum;
|
||||
u32 spawnflags;
|
||||
s16 chrnum;
|
||||
u16 padnum;
|
||||
u8 bodynum;
|
||||
s8 headnum;
|
||||
u16 ailistnum;
|
||||
u16 padpreset;
|
||||
u16 chrpreset;
|
||||
u16 hearscale;
|
||||
u16 viewdist;
|
||||
u32 flags;
|
||||
u32 flags2;
|
||||
u8 team;
|
||||
u8 squadron;
|
||||
s16 chair;
|
||||
u32 convtalk;
|
||||
u8 tude;
|
||||
u8 naturalanim;
|
||||
u8 yvisang;
|
||||
u8 teamscandist;
|
||||
};
|
||||
|
||||
struct n64_tvscreen {
|
||||
u32 ptr_cmdlist;
|
||||
u16 offset;
|
||||
s16 pause60;
|
||||
u32 ptr_tconfig;
|
||||
f32 rot;
|
||||
f32 xscale;
|
||||
f32 xscalefrac;
|
||||
f32 xscaleinc;
|
||||
f32 xscaleold;
|
||||
f32 xscalenew;
|
||||
f32 yscale;
|
||||
f32 yscalefrac;
|
||||
f32 yscaleinc;
|
||||
f32 yscaleold;
|
||||
f32 yscalenew;
|
||||
f32 xmid;
|
||||
f32 xmidfrac;
|
||||
f32 xmidinc;
|
||||
f32 xmidold;
|
||||
f32 xmidnew;
|
||||
f32 ymid;
|
||||
f32 ymidfrac;
|
||||
f32 ymidinc;
|
||||
f32 ymidold;
|
||||
f32 ymidnew;
|
||||
u8 red;
|
||||
u8 redold;
|
||||
u8 rednew;
|
||||
u8 green;
|
||||
u8 greenold;
|
||||
u8 greennew;
|
||||
u8 blue;
|
||||
u8 blueold;
|
||||
u8 bluenew;
|
||||
u8 alpha;
|
||||
u8 alphaold;
|
||||
u8 alphanew;
|
||||
f32 colfrac;
|
||||
f32 colinc;
|
||||
};
|
||||
|
||||
struct n64_singlemonitorobj {
|
||||
struct n64_defaultobj base;
|
||||
struct n64_tvscreen screen;
|
||||
s16 owneroffset;
|
||||
s8 ownerpart;
|
||||
u8 imagenum;
|
||||
};
|
||||
|
||||
struct n64_multimonitorobj {
|
||||
struct n64_defaultobj base;
|
||||
struct n64_tvscreen screens[4];
|
||||
u8 imagenums[4];
|
||||
};
|
||||
|
||||
struct n64_hangingmonitorsobj {
|
||||
struct n64_defaultobj base;
|
||||
};
|
||||
|
||||
struct n64_autogunobj {
|
||||
struct n64_defaultobj base;
|
||||
s16 targetpad;
|
||||
s8 firing;
|
||||
u8 firecount;
|
||||
f32 yzero;
|
||||
f32 ymaxleft;
|
||||
f32 ymaxright;
|
||||
f32 yrot;
|
||||
f32 yspeed;
|
||||
f32 xzero;
|
||||
f32 xrot;
|
||||
f32 xspeed;
|
||||
f32 maxspeed;
|
||||
f32 aimdist;
|
||||
f32 barrelspeed;
|
||||
f32 barrelrot;
|
||||
s32 lastseebond60;
|
||||
s32 lastaimbond60;
|
||||
s32 allowsoundframe;
|
||||
u32 ptr_beam;
|
||||
f32 shotbondsum;
|
||||
u32 ptr_target;
|
||||
u8 targetteam;
|
||||
u8 ammoquantity;
|
||||
s16 nextchrtest;
|
||||
};
|
||||
|
||||
struct n64_linkgunsobj {
|
||||
u32 unk00;
|
||||
s16 offset1;
|
||||
s16 offset2;
|
||||
};
|
||||
|
||||
struct n64_debrisobj {
|
||||
struct n64_defaultobj base;
|
||||
};
|
||||
|
||||
struct n64_hatobj {
|
||||
struct n64_defaultobj base;
|
||||
};
|
||||
|
||||
struct n64_grenadeprobobj { // objtype 0x12
|
||||
u32 unk00;
|
||||
s16 chrnum;
|
||||
u16 probability;
|
||||
};
|
||||
|
||||
struct n64_linkliftdoorobj {
|
||||
u32 unk00;
|
||||
u32 ptr_door;
|
||||
u32 ptr_lift;
|
||||
u32 ptr_next;
|
||||
s32 stopnum;
|
||||
};
|
||||
|
||||
struct n64_multiammocrateslot {
|
||||
u16 modelnum;
|
||||
u16 quantity;
|
||||
};
|
||||
|
||||
struct n64_multiammocrateobj {
|
||||
struct n64_defaultobj base;
|
||||
struct n64_multiammocrateslot slots[19];
|
||||
};
|
||||
|
||||
struct n64_shieldobj {
|
||||
struct n64_defaultobj base;
|
||||
f32 initialamount;
|
||||
f32 amount;
|
||||
u32 unk64;
|
||||
};
|
||||
|
||||
struct n64_tag {
|
||||
u32 identifier;
|
||||
u16 tagnum;
|
||||
s16 cmdoffset;
|
||||
u32 ptr_next;
|
||||
u32 ptr_obj;
|
||||
};
|
||||
|
||||
struct n64_objective {
|
||||
u32 unk00;
|
||||
s32 index;
|
||||
u32 text;
|
||||
u16 unk0c;
|
||||
u8 flags;
|
||||
s8 difficulties;
|
||||
};
|
||||
|
||||
struct n64_stdobjective {
|
||||
u32 cmd;
|
||||
};
|
||||
|
||||
struct n64_objectivecmd {
|
||||
u8 cmd0[4];
|
||||
u32 cmd1;
|
||||
};
|
||||
|
||||
struct n64_briefingobj {
|
||||
u32 unk00;
|
||||
u32 type;
|
||||
u32 text;
|
||||
u32 ptr_next;
|
||||
};
|
||||
|
||||
struct n64_padlockeddoorobj {
|
||||
u32 unk00;
|
||||
u32 ptr_door;
|
||||
u32 ptr_lock;
|
||||
u32 ptr_next;
|
||||
};
|
||||
|
||||
struct n64_truckobj {
|
||||
struct n64_defaultobj base;
|
||||
u32 ptr_ailist;
|
||||
u16 aioffset;
|
||||
s16 aireturnlist;
|
||||
f32 speed;
|
||||
f32 wheelxrot;
|
||||
f32 wheelyrot;
|
||||
f32 speedaim;
|
||||
f32 speedtime60;
|
||||
f32 turnrot60;
|
||||
f32 roty;
|
||||
u32 ptr_path;
|
||||
s32 nextstep;
|
||||
};
|
||||
|
||||
struct n64_tankobj {
|
||||
u8 _pad_[128];
|
||||
};
|
||||
|
||||
struct n64_heliobj {
|
||||
struct n64_defaultobj base;
|
||||
u32 ptr_ailist;
|
||||
u16 aioffset;
|
||||
s16 aireturnlist;
|
||||
f32 rotoryrot;
|
||||
f32 rotoryspeed;
|
||||
f32 rotoryspeedaim;
|
||||
f32 rotoryspeedtime;
|
||||
f32 speed;
|
||||
f32 speedaim;
|
||||
f32 speedtime60;
|
||||
f32 yrot;
|
||||
u32 ptr_path;
|
||||
s32 nextstep;
|
||||
};
|
||||
|
||||
struct n64_glassobj {
|
||||
struct n64_defaultobj base;
|
||||
s16 portalnum;
|
||||
s16 _pad_;
|
||||
};
|
||||
|
||||
struct n64_safeobj {
|
||||
struct n64_defaultobj base;
|
||||
};
|
||||
|
||||
struct n64_safeitemobj {
|
||||
u32 unk00;
|
||||
u32 ptr_item;
|
||||
u32 ptr_safe;
|
||||
u32 ptr_door;
|
||||
u32 ptr_next;
|
||||
};
|
||||
|
||||
struct n64_cameraposobj {
|
||||
s32 type;
|
||||
f32 x;
|
||||
f32 y;
|
||||
f32 z;
|
||||
f32 theta;
|
||||
f32 verta;
|
||||
s32 pad;
|
||||
};
|
||||
|
||||
struct n64_tintedglassobj {
|
||||
struct n64_defaultobj base;
|
||||
s16 xludist;
|
||||
s16 opadist;
|
||||
s16 opacity;
|
||||
s16 portalnum;
|
||||
f32 unk64;
|
||||
};
|
||||
|
||||
struct n64_liftobj {
|
||||
struct n64_defaultobj base;
|
||||
s16 pads[4];
|
||||
u32 ptr_doors[4];
|
||||
f32 dist;
|
||||
f32 speed;
|
||||
f32 accel;
|
||||
f32 maxspeed;
|
||||
s8 soundtype;
|
||||
s8 levelcur;
|
||||
s8 levelaim;
|
||||
s8 _pad_;
|
||||
struct n64_coord prevpos;
|
||||
};
|
||||
|
||||
struct n64_linksceneryobj {
|
||||
u32 unk00;
|
||||
u32 ptr_trigger;
|
||||
u32 ptr_unexp;
|
||||
u32 ptr_exp;
|
||||
u32 ptr_next;
|
||||
};
|
||||
|
||||
struct n64_blockedpathobj {
|
||||
u32 unk00;
|
||||
u32 ptr_blocker;
|
||||
s16 waypoint1;
|
||||
s16 waypoint2;
|
||||
u32 ptr_next;
|
||||
};
|
||||
|
||||
struct n64_hov {
|
||||
u8 type;
|
||||
u8 flags;
|
||||
s16 _pad_;
|
||||
f32 bobycur;
|
||||
f32 bobytarget;
|
||||
f32 bobyspeed;
|
||||
f32 yrot;
|
||||
f32 bobpitchcur;
|
||||
f32 bobpitchtarget;
|
||||
f32 bobpitchspeed;
|
||||
f32 bobrollcur;
|
||||
f32 bobrolltarget;
|
||||
f32 bobrollspeed;
|
||||
f32 groundpitch;
|
||||
f32 y;
|
||||
f32 ground;
|
||||
s32 prevframe60;
|
||||
s32 prevgroundframe60;
|
||||
};
|
||||
|
||||
struct n64_hoverbikeobj {
|
||||
struct n64_defaultobj base;
|
||||
struct n64_hov hov;
|
||||
f32 speed[2];
|
||||
f32 prevpos[2];
|
||||
f32 w;
|
||||
f32 rels[2];
|
||||
f32 exreal;
|
||||
f32 ezreal;
|
||||
f32 ezreal2;
|
||||
f32 leanspeed;
|
||||
f32 leandiff;
|
||||
s32 maxspeedtime240;
|
||||
f32 speedabs[2];
|
||||
f32 speedrel[2];
|
||||
};
|
||||
|
||||
struct n64_hoverpropobj {
|
||||
struct n64_defaultobj base;
|
||||
struct n64_hov hov;
|
||||
};
|
||||
|
||||
struct n64_fanobj {
|
||||
struct n64_defaultobj base;
|
||||
f32 yrot;
|
||||
f32 yrotprev;
|
||||
f32 ymaxspeed;
|
||||
f32 yspeed;
|
||||
f32 yaccel;
|
||||
s8 on;
|
||||
u8 _pad_[3];
|
||||
};
|
||||
|
||||
struct n64_hovercarobj {
|
||||
struct n64_defaultobj base;
|
||||
u32 ptr_ailist;
|
||||
u16 aioffset;
|
||||
s16 aireturnlist;
|
||||
f32 speed;
|
||||
f32 speedaim;
|
||||
f32 speedtime60;
|
||||
f32 turnyspeed60;
|
||||
f32 turnxspeed60;
|
||||
f32 turnrot60;
|
||||
f32 roty;
|
||||
f32 rotx;
|
||||
f32 rotz;
|
||||
u32 ptr_path;
|
||||
s32 nextstep;
|
||||
s16 status;
|
||||
s16 dead;
|
||||
s16 deadtimer60;
|
||||
s16 sparkstimer60;
|
||||
};
|
||||
|
||||
struct n64_chopperobj {
|
||||
struct n64_defaultobj base;
|
||||
u32 ptr_ailist;
|
||||
u16 aioffset;
|
||||
s16 aireturnlist;
|
||||
union {
|
||||
struct {
|
||||
f32 speed;
|
||||
f32 speedaim;
|
||||
f32 speedtime60;
|
||||
};
|
||||
struct n64_coord fall;
|
||||
};
|
||||
f32 turnyspeed60;
|
||||
f32 turnxspeed60;
|
||||
f32 turnrot60;
|
||||
f32 roty;
|
||||
f32 rotx;
|
||||
f32 rotz;
|
||||
u32 ptr_path;
|
||||
s32 nextstep;//
|
||||
s16 weaponsarmed;
|
||||
s16 ontarget;
|
||||
s16 target;
|
||||
u8 attackmode;
|
||||
u8 cw;
|
||||
f32 vx;
|
||||
f32 vy;
|
||||
f32 vz;
|
||||
f32 power;
|
||||
f32 otx;
|
||||
f32 oty;
|
||||
f32 otz;
|
||||
f32 bob;
|
||||
f32 bobstrength;
|
||||
s32 targetvisible;
|
||||
s32 timer60;
|
||||
s32 patroltimer60;
|
||||
f32 gunturnyspeed60;
|
||||
f32 gunturnxspeed60;
|
||||
f32 gunroty;
|
||||
f32 gunrotx;
|
||||
f32 barrelrotspeed;
|
||||
f32 barrelrot;
|
||||
u32 ptr_fireslotthing;
|
||||
s32 dead;
|
||||
};
|
||||
|
||||
struct n64_escalatorobj {
|
||||
struct n64_defaultobj base;
|
||||
s32 frame;
|
||||
struct n64_coord prevpos;
|
||||
};
|
||||
|
||||
struct n64_textoverride {
|
||||
u32 unk00;
|
||||
s32 objoffset;
|
||||
s32 weapon;
|
||||
u32 obtaintext;
|
||||
u32 ownertext;
|
||||
u32 inventorytext;
|
||||
u32 inventory2text;
|
||||
u32 pickuptext;
|
||||
u32 ptr_next;
|
||||
u32 ptr_obj;
|
||||
};
|
||||
|
||||
struct n64_criteria_roomentered {
|
||||
u32 unk00;
|
||||
u32 pad;
|
||||
u32 status;
|
||||
u32 ptr_next;
|
||||
};
|
||||
|
||||
struct n64_criteria_throwinroom {
|
||||
u32 unk00;
|
||||
u32 unk04;
|
||||
u32 pad;
|
||||
u32 status;
|
||||
u32 ptr_next;
|
||||
};
|
||||
|
||||
struct n64_criteria_holograph {
|
||||
u32 unk00;
|
||||
u32 obj;
|
||||
u32 status;
|
||||
u32 ptr_next;
|
||||
};
|
||||
|
||||
struct n64_ailist {
|
||||
u32 ptr_list;
|
||||
s32 id;
|
||||
};
|
||||
|
||||
struct n64_path {
|
||||
u32 ptr_pads;
|
||||
u8 id;
|
||||
u8 flags;
|
||||
u16 len;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -5,11 +5,12 @@
|
||||
|
||||
extern u8 *g_RomFile;
|
||||
extern u32 g_RomFileSize;
|
||||
extern const char *g_RomName;
|
||||
|
||||
s32 romdataInit(void);
|
||||
|
||||
u8 *romdataFileLoad(s32 fileNum, u32 *outSize);
|
||||
void romdataFilePreprocess(s32 fileNum, s32 loadType, u8 *data, u32 size, u32 *outSize);
|
||||
void romdataFilePreprocess(s32 fileNum, s32 loadType, u8 *data, u32 size);
|
||||
void romdataFileFree(s32 fileNum);
|
||||
const char *romdataFileGetName(s32 fileNum);
|
||||
|
||||
@@ -21,8 +22,5 @@ s32 romdataFileGetNumForName(const char *name);
|
||||
u8 *romdataSegGetData(const char *segName);
|
||||
u8 *romdataSegGetDataEnd(const char *segName);
|
||||
u32 romdataSegGetSize(const char *segName);
|
||||
u32 romdataFileGetEstimatedSize(const u32 size, const u32 loadtype);
|
||||
|
||||
s32 romdataCheckGbcRom(void);
|
||||
|
||||
#endif
|
||||
@@ -7,10 +7,14 @@ extern "C" {
|
||||
|
||||
#include <PR/ultratypes.h>
|
||||
|
||||
enum LogLevel {
|
||||
LOG_NOTE,
|
||||
LOG_WARNING,
|
||||
LOG_ERROR,
|
||||
#define LOGFLAG_NOCON (1 << 6)
|
||||
#define LOGFLAG_SHOWMSG (1 << 7)
|
||||
|
||||
enum loglevel {
|
||||
LOG_NOTE = 0,
|
||||
LOG_CHAT = 0 | LOGFLAG_SHOWMSG,
|
||||
LOG_WARNING = 1 | LOGFLAG_SHOWMSG,
|
||||
LOG_ERROR = 2 | LOGFLAG_SHOWMSG,
|
||||
};
|
||||
|
||||
void sysInitArgs(s32 argc, const char **argv);
|
||||
@@ -21,6 +25,7 @@ const char *sysArgGetString(const char *arg);
|
||||
s32 sysArgGetInt(const char *arg, s32 defval);
|
||||
|
||||
u64 sysGetMicroseconds(void);
|
||||
f32 sysGetSeconds(void);
|
||||
|
||||
void sysFatalError(const char *fmt, ...) __attribute__((noreturn));
|
||||
|
||||
@@ -32,7 +37,6 @@ void sysGetHomePath(char *outPath, const u32 outLen);
|
||||
|
||||
void *sysMemAlloc(const u32 size);
|
||||
void *sysMemZeroAlloc(const u32 size);
|
||||
void *sysMemRealloc(void *ptr, const u32 newSize);
|
||||
void sysMemFree(void *ptr);
|
||||
|
||||
// hns is specified in 100ns units
|
||||
|
||||
@@ -12,4 +12,18 @@ char *strParseToken(char *str, char *out, s32 *outCount);
|
||||
char *strFmt(const char *fmt, ...);
|
||||
char *strDuplicate(const char *str);
|
||||
|
||||
static inline f32 lerpf(const f32 a, const f32 b, const f32 t) {
|
||||
return a + (b - a) * t;
|
||||
}
|
||||
|
||||
static inline f32 lerpanglef(const f32 a, const f32 b, const f32 t) {
|
||||
f32 d = b - a;
|
||||
if (d > 180.f) {
|
||||
d -= 360.f;
|
||||
} else if (d < -180.f) {
|
||||
d += 360.f;
|
||||
}
|
||||
return a + d * t;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,11 +0,0 @@
|
||||
#ifndef _IN_VERSIONINFO_H
|
||||
#define _IN_VERSIONINFO_H
|
||||
|
||||
#define VERSION_TARGET "@VERSION_TARGET@"
|
||||
#define VERSION_ARCH "@VERSION_ARCH@"
|
||||
#define VERSION_ROMID "@VERSION_ROMID@"
|
||||
#define VERSION_BUILD "@VERSION_BUILD@"
|
||||
#define VERSION_HASH "@VERSION_HASH@"
|
||||
#define VERSION_BRANCH "@VERSION_BRANCH@"
|
||||
|
||||
#endif
|
||||
+1
-33
@@ -11,11 +11,6 @@
|
||||
#define VIDEO_MAX_FPS 240
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
s32 width;
|
||||
s32 height;
|
||||
} displaymode;
|
||||
|
||||
s32 videoInit(void);
|
||||
void videoStartFrame(void);
|
||||
void videoSubmitCommands(Gfx *cmds);
|
||||
@@ -32,42 +27,18 @@ s32 videoGetWidth(void);
|
||||
s32 videoGetHeight(void);
|
||||
f32 videoGetAspect(void);
|
||||
s32 videoGetFullscreen(void);
|
||||
s32 videoGetFullscreenMode(void);
|
||||
s32 videoGetMaximizeWindow(void);
|
||||
void videoSetMaximizeWindow(s32 fs);
|
||||
s32 videoGetCenterWindow(void);
|
||||
void videoSetCenterWindow(s32 center);
|
||||
u32 videoGetTextureFilter(void);
|
||||
s32 videoGetTextureFilter2D(void);
|
||||
u32 videoGetAnisotropicFilter(void);
|
||||
u32 videoGetMaxAnisotropyLevel(void);
|
||||
s32 videoGetDetailTextures(void);
|
||||
s32 videoGetDisplayModeIndex(void);
|
||||
s32 videoGetDisplayMode(displaymode *out, const s32 index);
|
||||
s32 videoGetNumDisplayModes(void);
|
||||
s32 videoGetVsync(void);
|
||||
s32 videoGetFramerateLimit(void);
|
||||
s32 videoGetDisplayFPS(void);
|
||||
s32 videoGetMSAA(void);
|
||||
f32 videoGetGlareBrightness(void);
|
||||
f32 videoGetOverexposureScale(void);
|
||||
|
||||
f32 videoGetAverageFPS(void);
|
||||
|
||||
void videoSetWindowOffset(s32 x, s32 y);
|
||||
void videoSetFullscreen(s32 fs);
|
||||
void videoSetFullscreenMode(s32 mode);
|
||||
void videoSetTextureFilter(u32 filter);
|
||||
void videoSetTextureFilter2D(s32 filter);
|
||||
void videoSetAnisotropicFilter(u32 filter);
|
||||
void videoSetDetailTextures(s32 detail);
|
||||
void videoSetDisplayMode(const s32 index);
|
||||
void videoSetVsync(const s32 vsync);
|
||||
void videoSetFramerateLimit(const s32 limit);
|
||||
void videoSetDisplayFPS(const s32 displayfps);
|
||||
void videoSetMSAA(const s32 msaa);
|
||||
void videoSetGlareBrightness(f32 bright);
|
||||
void videoSetOverexposureScale(f32 scale);
|
||||
void videoCapFramerate(s32 limit);
|
||||
|
||||
s32 videoCreateFramebuffer(u32 w, u32 h, s32 upscale, s32 autoresize);
|
||||
void videoSetFramebuffer(s32 target);
|
||||
@@ -78,8 +49,5 @@ s32 videoFramebuffersSupported(void);
|
||||
|
||||
void videoResetTextureCache(void);
|
||||
void videoFreeCachedTexture(const void *texptr);
|
||||
void videoFreeCachedTextures(const void *start, const void *end);
|
||||
|
||||
void videoShutdown(void);
|
||||
|
||||
#endif
|
||||
+4
-9
@@ -10,7 +10,7 @@
|
||||
|
||||
#define CONFIG_MAX_SECNAME 128
|
||||
#define CONFIG_MAX_KEYNAME 256
|
||||
#define CONFIG_MAX_SETTINGS 300
|
||||
#define CONFIG_MAX_SETTINGS 256
|
||||
|
||||
typedef enum {
|
||||
CFG_NONE,
|
||||
@@ -34,7 +34,6 @@ struct configentry {
|
||||
} settings[CONFIG_MAX_SETTINGS];
|
||||
|
||||
static s32 numSettings = 0;
|
||||
static u8 configMaxWarningLogged = 0;
|
||||
|
||||
static inline s32 configClampInt(s32 val, s32 min, s32 max)
|
||||
{
|
||||
@@ -65,15 +64,11 @@ static inline struct configentry *configAddEntry(const char *key)
|
||||
{
|
||||
if (numSettings < CONFIG_MAX_SETTINGS) {
|
||||
struct configentry *cfg = &settings[numSettings++];
|
||||
snprintf(cfg->key, CONFIG_MAX_KEYNAME, "%s", key);
|
||||
strncpy(cfg->key, key, CONFIG_MAX_KEYNAME);
|
||||
const char *delim = strrchr(cfg->key, '.');
|
||||
cfg->seclen = delim ? (delim - cfg->key) : 0;
|
||||
return cfg;
|
||||
}
|
||||
if (!configMaxWarningLogged) {
|
||||
sysLogPrintf(LOG_WARNING, "Maximum number of configuration entries exceeded: %d", CONFIG_MAX_SETTINGS);
|
||||
configMaxWarningLogged = 1;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -233,7 +228,7 @@ s32 configSave(const char *fname)
|
||||
configSaveEntry(cfg, f);
|
||||
}
|
||||
|
||||
fsFileFree(f);
|
||||
fsFileClose(f);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -287,7 +282,7 @@ s32 configLoad(const char *fname)
|
||||
}
|
||||
}
|
||||
|
||||
fsFileFree(f);
|
||||
fsFileClose(f);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,213 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include "platform.h"
|
||||
#include "types.h"
|
||||
#include "constants.h"
|
||||
#include "data.h"
|
||||
#include "bss.h"
|
||||
#include "config.h"
|
||||
#include "video.h"
|
||||
#include "input.h"
|
||||
#include "console.h"
|
||||
#include "system.h"
|
||||
#include "utils.h"
|
||||
#include "net/net.h"
|
||||
#include "game/hudmsg.h"
|
||||
#include "game/game_1531a0.h"
|
||||
#include "lib/vi.h"
|
||||
|
||||
#define CON_ROWS 80
|
||||
#define CON_COLS 56
|
||||
#define CON_VISROWS 10
|
||||
#define CON_MSGROWS 4
|
||||
#define CON_MSGTIMER 3.f
|
||||
|
||||
static char conBuf[CON_ROWS][CON_COLS + 1];
|
||||
static char conInput[CON_COLS + 1];
|
||||
static char *conVisRows[CON_VISROWS];
|
||||
static s32 conPrintRow = 0;
|
||||
static s32 conPrintCol = 0;
|
||||
static s32 conMsgRows = 0;
|
||||
static f32 conMsgTimer = 0.f;
|
||||
static s32 conInputCol = 0;
|
||||
static u32 conTextColour = 0x00ff00ff;
|
||||
static s32 conOpen = 0;
|
||||
static s32 conButton = 0;
|
||||
|
||||
void conInit(void)
|
||||
{
|
||||
memset(conBuf, 0, sizeof(conBuf));
|
||||
memset(conInput, 0, sizeof(conInput));
|
||||
memset(conVisRows, 0, sizeof(conVisRows));
|
||||
conPrintRow = conPrintCol = 0;
|
||||
conOpen = 0;
|
||||
conMsgRows = 0;
|
||||
conMsgTimer = 0.0f;
|
||||
conInputCol = 0;
|
||||
}
|
||||
|
||||
void conPrint(s32 showmsg, const char *str)
|
||||
{
|
||||
if (!str || !*str) {
|
||||
return;
|
||||
}
|
||||
|
||||
const s32 oldRow = conPrintRow;
|
||||
|
||||
for (const char *s = str; *s; ++s) {
|
||||
char ch = *s;
|
||||
switch (ch) {
|
||||
case '\n':
|
||||
if (conPrintCol) {
|
||||
conPrintCol = 0;
|
||||
conPrintRow = (conPrintRow + 1) % CON_ROWS;
|
||||
}
|
||||
break;
|
||||
case '\r':
|
||||
break;
|
||||
case '\t':
|
||||
ch = ' ';
|
||||
/* fallthrough */
|
||||
default:
|
||||
conBuf[conPrintRow][conPrintCol++] = ch;
|
||||
if (conPrintCol == CON_COLS) {
|
||||
conPrintCol = 0;
|
||||
conPrintRow = (conPrintRow + 1) % CON_ROWS;
|
||||
}
|
||||
break;
|
||||
}
|
||||
conBuf[conPrintRow][conPrintCol] = '\0';
|
||||
}
|
||||
|
||||
if (conPrintRow != oldRow) {
|
||||
// scroll time
|
||||
for (s32 i = 0; i < ARRAYCOUNT(conVisRows); ++i) {
|
||||
s32 row = conPrintRow - i - 1;
|
||||
if (row < 0) {
|
||||
row = CON_ROWS + row;
|
||||
}
|
||||
conVisRows[i] = &conBuf[row][0];
|
||||
}
|
||||
if (showmsg) {
|
||||
if (conMsgRows < CON_MSGROWS) {
|
||||
if (conPrintRow > oldRow) {
|
||||
conMsgRows += conPrintRow - oldRow;
|
||||
} else {
|
||||
conMsgRows += conPrintRow + (CON_ROWS - oldRow);
|
||||
}
|
||||
}
|
||||
conMsgTimer = sysGetSeconds() + CON_MSGTIMER;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void conPrintLn(s32 showmsg, const char *s)
|
||||
{
|
||||
char tmp[4096];
|
||||
snprintf(tmp, sizeof(tmp), "%s\n", s);
|
||||
conPrint(showmsg, tmp);
|
||||
}
|
||||
|
||||
void conPrintf(s32 showmsg, const char *fmt, ...)
|
||||
{
|
||||
char tmp[4096];
|
||||
tmp[sizeof(tmp) - 1] = '\0';
|
||||
tmp[0] = '\0';
|
||||
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
vsnprintf(tmp, sizeof(tmp), fmt, args);
|
||||
va_end(args);
|
||||
|
||||
conPrint(showmsg, tmp);
|
||||
}
|
||||
|
||||
static inline Gfx *conRenderMsgs(Gfx *gdl)
|
||||
{
|
||||
if (conMsgRows) {
|
||||
s32 x, y;
|
||||
const u32 c = (conTextColour & 0xffffff00) | 0xa0;
|
||||
for (s32 i = 0; i < conMsgRows; ++i) {
|
||||
char *s = conVisRows[i];
|
||||
if (s) {
|
||||
x = 4;
|
||||
y = 4 + 8 * (conMsgRows - i - 1);
|
||||
gdl = textRenderProjected(gdl, &x, &y, s, g_CharsHandelGothicXs, g_FontHandelGothicXs, c, viGetWidth(), viGetHeight(), 0, 0);
|
||||
}
|
||||
}
|
||||
const f32 t = sysGetSeconds();
|
||||
if (conMsgTimer <= t) {
|
||||
conMsgTimer = t + CON_MSGTIMER;
|
||||
--conMsgRows;
|
||||
}
|
||||
} else {
|
||||
conMsgTimer = 0;
|
||||
}
|
||||
|
||||
return gdl;
|
||||
}
|
||||
|
||||
Gfx *conRender(Gfx *gdl)
|
||||
{
|
||||
if (!g_CharsHandelGothicXs || !g_FontHandelGothicXs) {
|
||||
return gdl;
|
||||
}
|
||||
|
||||
gdl = text0f153628(gdl);
|
||||
|
||||
if (!conOpen) {
|
||||
gSPExtraGeometryModeEXT(gdl++, G_ASPECT_MODE_EXT, G_ASPECT_LEFT_EXT);
|
||||
gdl = conRenderMsgs(gdl);
|
||||
} else {
|
||||
s32 x, y;
|
||||
gSPExtraGeometryModeEXT(gdl++, G_ASPECT_MODE_EXT, G_ASPECT_CENTER_EXT);
|
||||
gdl = hudmsgRenderBox(gdl, 16, 0, SCREEN_WIDTH_LO - 16, 4 + 8 * (CON_VISROWS + 1), 1.f, conTextColour, 0.9f);
|
||||
for (s32 i = 0; i < CON_VISROWS; ++i) {
|
||||
char *s = conVisRows[i];
|
||||
if (s) {
|
||||
x = 18;
|
||||
y = 4 + 8 * (CON_VISROWS - i - 1);
|
||||
gdl = textRenderProjected(gdl, &x, &y, s, g_CharsHandelGothicXs, g_FontHandelGothicXs, conTextColour, viGetWidth(), viGetHeight(), 0, 0);
|
||||
}
|
||||
}
|
||||
char tmp[CON_COLS + 3];
|
||||
snprintf(tmp, sizeof(tmp), "> %s", conInput);
|
||||
x = 18;
|
||||
y = 4 + 8 * CON_VISROWS;
|
||||
gdl = textRenderProjected(gdl, &x, &y, tmp, g_CharsHandelGothicXs, g_FontHandelGothicXs, conTextColour, viGetWidth(), viGetHeight(), 0, 0);
|
||||
}
|
||||
|
||||
gSPClearExtraGeometryModeEXT(gdl++, G_ASPECT_MODE_EXT);
|
||||
|
||||
gdl = text0f153780(gdl);
|
||||
|
||||
return gdl;
|
||||
}
|
||||
|
||||
void conTick(void)
|
||||
{
|
||||
const s32 button = inputKeyPressed(VK_GRAVE);
|
||||
if (button && !conButton) {
|
||||
conOpen = !conOpen;
|
||||
if (conOpen) {
|
||||
inputStartTextInput();
|
||||
} else {
|
||||
inputStopTextInput();
|
||||
}
|
||||
}
|
||||
|
||||
conButton = button;
|
||||
|
||||
if (conOpen) {
|
||||
if (inputTextHandler(conInput, CON_COLS, &conInputCol)) {
|
||||
if (g_NetMode) {
|
||||
netChat(NULL, conInput);
|
||||
}
|
||||
conInput[0] = '\0';
|
||||
conInputCol = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-15
@@ -11,9 +11,6 @@
|
||||
#include "platform.h"
|
||||
#include "utils.h"
|
||||
#include "fs.h"
|
||||
#ifdef PLATFORM_WIN32
|
||||
#include <direct.h>
|
||||
#endif
|
||||
|
||||
#define DEFAULT_BASEDIR_NAME "data"
|
||||
|
||||
@@ -114,7 +111,7 @@ s32 fsInit(void)
|
||||
if (!portable) {
|
||||
if (fsFileSize("./" DEFAULT_BASEDIR_NAME) >= 0) {
|
||||
path = "./" DEFAULT_BASEDIR_NAME;
|
||||
} else if (fsFileSize("$H/" DEFAULT_BASEDIR_NAME) >= 0) {
|
||||
} else if (fsFileSize("$H/" DEFAULT_BASEDIR_NAME)) {
|
||||
path = "$H/" DEFAULT_BASEDIR_NAME;
|
||||
}
|
||||
}
|
||||
@@ -152,7 +149,7 @@ s32 fsInit(void)
|
||||
if (portable) {
|
||||
path = "$E";
|
||||
} else {
|
||||
#if defined(PLATFORM_LINUX) || defined(PLATFORM_OSX)
|
||||
#ifdef PLATFORM_LINUX
|
||||
// check if there's a config in the working directory, otherwise default to homeDir
|
||||
if (fsFileSize("./" CONFIG_FNAME) >= 0) {
|
||||
path = ".";
|
||||
@@ -279,16 +276,7 @@ FILE *fsFileOpenRead(const char *name)
|
||||
return fopen(fsFullPath(name), "rb");
|
||||
}
|
||||
|
||||
void fsFileFree(FILE *f)
|
||||
void fsFileClose(FILE *f)
|
||||
{
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
s32 fsCreateDir(const char *path)
|
||||
{
|
||||
#ifdef PLATFORM_WIN32
|
||||
return _mkdir(fsFullPath(path));
|
||||
#else
|
||||
return mkdir(fsFullPath(path), 0777);
|
||||
#endif
|
||||
}
|
||||
+52
-205
@@ -28,9 +28,6 @@
|
||||
#define WHEEL_UP_MASK SDL_BUTTON(VK_MOUSE_WHEEL_UP - VK_MOUSE_BEGIN + 1)
|
||||
#define WHEEL_DN_MASK SDL_BUTTON(VK_MOUSE_WHEEL_DN - VK_MOUSE_BEGIN + 1)
|
||||
|
||||
#define CURSOR_HIDE_THRESHOLD 1
|
||||
#define CURSOR_HIDE_TIME 3000000 // us
|
||||
|
||||
static SDL_GameController *pads[INPUT_MAX_CONTROLLERS];
|
||||
|
||||
#define CONTROLLERCFG_DEFAULT { \
|
||||
@@ -44,8 +41,7 @@ static SDL_GameController *pads[INPUT_MAX_CONTROLLERS];
|
||||
.deadzone = { DEFAULT_DEADZONE, DEFAULT_DEADZONE, DEFAULT_DEADZONE, DEFAULT_DEADZONE_RY }, \
|
||||
.stickCButtons = 0, \
|
||||
.swapSticks = 1, \
|
||||
.deviceIndex = -1, \
|
||||
.cancelCButtons = 0, \
|
||||
.deviceIndex = -1 \
|
||||
}
|
||||
|
||||
static struct controllercfg {
|
||||
@@ -57,7 +53,6 @@ static struct controllercfg {
|
||||
s32 stickCButtons;
|
||||
s32 swapSticks;
|
||||
s32 deviceIndex;
|
||||
s32 cancelCButtons;
|
||||
} padsCfg[INPUT_MAX_CONTROLLERS] = {
|
||||
CONTROLLERCFG_DEFAULT,
|
||||
CONTROLLERCFG_DEFAULT,
|
||||
@@ -74,22 +69,16 @@ static s32 connectedMask = 0;
|
||||
|
||||
static s32 numJoysticks = 0;
|
||||
|
||||
static s32 useHIDAPI = 1;
|
||||
static s32 useRawInput = 0;
|
||||
|
||||
static s32 mouseEnabled = 1;
|
||||
static s32 mouseLocked = 0;
|
||||
static s32 mouseDefaultLocked = 0;
|
||||
static s32 mouseX, mouseY;
|
||||
static s32 mouseDX, mouseDY;
|
||||
static u32 mouseButtons;
|
||||
static s32 mouseWheel = 0;
|
||||
|
||||
static s32 mouseLocked = 0;
|
||||
static s32 mouseLockMode = MLOCK_AUTO;
|
||||
static u64 mouseCursorTime = 0;
|
||||
static s32 mouseShowCursor = 1;
|
||||
|
||||
static f32 mouseSensX = 2.5f;
|
||||
static f32 mouseSensY = 2.5f;
|
||||
static f32 mouseSensX = 1.5f;
|
||||
static f32 mouseSensY = 1.5f;
|
||||
|
||||
static s32 lastKey = 0;
|
||||
static char lastChar = 0;
|
||||
@@ -118,8 +107,8 @@ static const char *ckNames[CK_TOTAL_COUNT] = {
|
||||
"STICK_XPOS",
|
||||
"STICK_YNEG",
|
||||
"STICK_YPOS",
|
||||
"ACCEPT_BUTTON",
|
||||
"CANCEL_BUTTON",
|
||||
"CK_0010",
|
||||
"CK_0020",
|
||||
"CK_0040",
|
||||
"CK_0080",
|
||||
"CK_0100",
|
||||
@@ -184,8 +173,6 @@ static const char *vkJoyNames[] = {
|
||||
|
||||
static char vkNames[VK_TOTAL_COUNT][64];
|
||||
|
||||
static s8 vkPrevState[VK_TOTAL_COUNT];
|
||||
|
||||
void inputSetDefaultKeyBinds(s32 cidx, s32 n64mode)
|
||||
{
|
||||
// TODO: make VK constants for all these
|
||||
@@ -195,7 +182,7 @@ void inputSetDefaultKeyBinds(s32 cidx, s32 n64mode)
|
||||
{ CK_RTRIG, VK_MOUSE_RIGHT, SDL_SCANCODE_Z },
|
||||
{ CK_LTRIG, SDL_SCANCODE_F, SDL_SCANCODE_X },
|
||||
{ CK_ZTRIG, VK_MOUSE_LEFT, SDL_SCANCODE_SPACE },
|
||||
{ CK_START, SDL_SCANCODE_TAB, 0 },
|
||||
{ CK_START, SDL_SCANCODE_RETURN, SDL_SCANCODE_TAB },
|
||||
{ CK_DPAD_D, SDL_SCANCODE_Q, VK_MOUSE_MIDDLE },
|
||||
{ CK_DPAD_U, 0, 0 },
|
||||
{ CK_Y, VK_MOUSE_WHEEL_DN, 0 },
|
||||
@@ -209,9 +196,7 @@ void inputSetDefaultKeyBinds(s32 cidx, s32 n64mode)
|
||||
{ CK_STICK_YNEG, SDL_SCANCODE_DOWN, 0 },
|
||||
{ CK_STICK_YPOS, SDL_SCANCODE_UP, 0 },
|
||||
{ CK_4000, SDL_SCANCODE_LSHIFT, 0 },
|
||||
{ CK_2000, SDL_SCANCODE_LCTRL, 0 },
|
||||
{ CK_ACCEPT, SDL_SCANCODE_RETURN, SDL_SCANCODE_E },
|
||||
{ CK_CANCEL, VK_MOUSE_RIGHT, 0 },
|
||||
{ CK_2000, SDL_SCANCODE_LCTRL, 0 }
|
||||
};
|
||||
|
||||
static const u32 pcjoybinds[][2] = {
|
||||
@@ -228,8 +213,6 @@ void inputSetDefaultKeyBinds(s32 cidx, s32 n64mode)
|
||||
{ CK_C_U, SDL_CONTROLLER_BUTTON_DPAD_UP },
|
||||
{ CK_C_R, SDL_CONTROLLER_BUTTON_DPAD_RIGHT },
|
||||
{ CK_C_L, SDL_CONTROLLER_BUTTON_DPAD_LEFT },
|
||||
{ CK_ACCEPT, SDL_CONTROLLER_BUTTON_A },
|
||||
{ CK_CANCEL, SDL_CONTROLLER_BUTTON_B },
|
||||
{ CK_8000, SDL_CONTROLLER_BUTTON_LEFTSTICK },
|
||||
};
|
||||
|
||||
@@ -340,14 +323,6 @@ static inline void inputInitController(const s32 cidx, const s32 jidx)
|
||||
|
||||
sysLogPrintf(LOG_NOTE, "input: assigned controller '%d: (%s)' (id %d) to player %d",
|
||||
jidx, SDL_GameControllerName(pads[cidx]), inputControllerGetId(pads[cidx]), cidx);
|
||||
|
||||
SDL_Joystick* joy = SDL_GameControllerGetJoystick(pads[cidx]);
|
||||
if (joy) {
|
||||
char guidStr[1024] = "";
|
||||
SDL_JoystickGUID guid = SDL_JoystickGetGUID(joy);
|
||||
SDL_JoystickGetGUIDString(guid, guidStr, sizeof(guidStr));
|
||||
sysLogPrintf(LOG_NOTE, "input: GUID for controller %d: %s", jidx, guidStr);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void inputCloseController(const s32 cidx)
|
||||
@@ -679,47 +654,6 @@ static inline void inputLoadBinds(void)
|
||||
|
||||
s32 inputInit(void)
|
||||
{
|
||||
// Set SDL hints before initializing the controller subsystem.
|
||||
if (useHIDAPI) {
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 12)
|
||||
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_GAMECUBE, "1");
|
||||
#endif
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 14)
|
||||
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS5, "1");
|
||||
#endif
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 22)
|
||||
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI, "1");
|
||||
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS4, "1");
|
||||
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_SWITCH, "1");
|
||||
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS, "1");
|
||||
// the two hints below enable Rumble and Motion Sensor for PS4/5 pads connected via bluetooth
|
||||
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE, "1");
|
||||
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE, "1");
|
||||
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_STEAM, "1");
|
||||
#endif
|
||||
#if SDL_VERSION_ATLEAST(2, 23, 2)
|
||||
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_COMBINE_JOY_CONS, "1");
|
||||
#endif
|
||||
#if SDL_VERSION_ATLEAST(2, 25, 1)
|
||||
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS3, "1");
|
||||
#endif
|
||||
#if SDL_VERSION_ATLEAST(2, 26, 0)
|
||||
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_WII, "1");
|
||||
#endif
|
||||
#if SDL_VERSION_ATLEAST(2, 30, 0)
|
||||
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_STEAMDECK, "1");
|
||||
#endif
|
||||
}
|
||||
if (useRawInput) {
|
||||
SDL_SetHint(SDL_HINT_JOYSTICK_RAWINPUT, "1");
|
||||
#ifdef SDL_HINT_JOYSTICK_RAWINPUT_CORRELATE_XINPUT
|
||||
SDL_SetHint(SDL_HINT_JOYSTICK_RAWINPUT_CORRELATE_XINPUT, "1");
|
||||
#elif defined(SDL_HINT_JOYSTICK_HIDAPI_CORRELATE_XINPUT)
|
||||
// old name for SDL_HINT_JOYSTICK_RAWINPUT_CORRELATE_XINPUT before SDL2.0.16
|
||||
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_CORRELATE_XINPUT, "1");
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!SDL_WasInit(SDL_INIT_GAMECONTROLLER | SDL_INIT_HAPTIC)) {
|
||||
SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER | SDL_INIT_HAPTIC);
|
||||
}
|
||||
@@ -744,9 +678,7 @@ s32 inputInit(void)
|
||||
inputSetDefaultKeyBinds(i, 0);
|
||||
}
|
||||
|
||||
if (mouseLockMode != MLOCK_AUTO) {
|
||||
inputLockMouse(mouseLockMode);
|
||||
}
|
||||
inputLockMouse(mouseDefaultLocked);
|
||||
|
||||
// update the axis maps
|
||||
// NOTE: by default sticks get swapped for 1.2: "right stick" here means left stick on your controller
|
||||
@@ -756,9 +688,6 @@ s32 inputInit(void)
|
||||
|
||||
inputLoadBinds();
|
||||
|
||||
// Explicitly stop text input to prevent key events being swallowed on certain Wayland systems
|
||||
inputStopTextInput();
|
||||
|
||||
return connectedMask;
|
||||
}
|
||||
|
||||
@@ -819,22 +748,12 @@ s32 inputReadController(s32 idx, OSContPad *npad)
|
||||
npad->stick_x = xdiff < 0 ? -0x80 : (xdiff > 0 ? 0x7F : 0);
|
||||
npad->stick_y = ydiff < 0 ? -0x80 : (ydiff > 0 ? 0x7F : 0);
|
||||
|
||||
const struct controllercfg *cfg = &padsCfg[idx];
|
||||
|
||||
if (cfg->cancelCButtons) {
|
||||
// opposite C buttons cancel each other out
|
||||
if ((npad->button & (L_CBUTTONS | R_CBUTTONS)) == (L_CBUTTONS | R_CBUTTONS)) {
|
||||
npad->button &= ~(L_CBUTTONS | R_CBUTTONS);
|
||||
}
|
||||
if ((npad->button & (U_CBUTTONS | D_CBUTTONS)) == (U_CBUTTONS | D_CBUTTONS)) {
|
||||
npad->button &= ~(U_CBUTTONS | D_CBUTTONS);
|
||||
}
|
||||
}
|
||||
|
||||
if (!pads[idx]) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct controllercfg *cfg = &padsCfg[idx];
|
||||
|
||||
s32 leftX = SDL_GameControllerGetAxis(pads[idx], cfg->axisMap[0][0]);
|
||||
s32 leftY = SDL_GameControllerGetAxis(pads[idx], cfg->axisMap[0][1]);
|
||||
s32 rightX = SDL_GameControllerGetAxis(pads[idx], cfg->axisMap[1][0]);
|
||||
@@ -889,12 +808,8 @@ static inline void inputUpdateMouse(void)
|
||||
|
||||
mouseWheel = 0;
|
||||
|
||||
s32 mdx = 0;
|
||||
s32 mdy = 0;
|
||||
SDL_GetRelativeMouseState(&mdx, &mdy);
|
||||
if (mouseLocked) {
|
||||
mouseDX = mdx;
|
||||
mouseDY = mdy;
|
||||
SDL_GetRelativeMouseState(&mouseDX, &mouseDY);
|
||||
} else {
|
||||
mouseDX = mx - mouseX;
|
||||
mouseDY = my - mouseY;
|
||||
@@ -903,18 +818,10 @@ static inline void inputUpdateMouse(void)
|
||||
mouseX = mx;
|
||||
mouseY = my;
|
||||
|
||||
// if MLOCK_AUTO is enabled, disable cursor if mouse is unlocked
|
||||
// and we haven't moved it for a few seconds
|
||||
if (mouseLockMode == MLOCK_AUTO && !mouseLocked) {
|
||||
if (abs(mouseDX) > CURSOR_HIDE_THRESHOLD || abs(mouseDY) > CURSOR_HIDE_THRESHOLD) {
|
||||
if (!mouseShowCursor) {
|
||||
inputMouseShowCursor(1);
|
||||
}
|
||||
} else if (sysGetMicroseconds() > mouseCursorTime) {
|
||||
if (mouseShowCursor) {
|
||||
inputMouseShowCursor(0);
|
||||
}
|
||||
}
|
||||
if (!mouseLocked && (mouseButtons & SDL_BUTTON_LMASK)) {
|
||||
inputLockMouse(1);
|
||||
} else if (mouseLocked && inputKeyPressed(VK_ESCAPE)) {
|
||||
inputLockMouse(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1012,16 +919,6 @@ void inputControllerSetDualAnalog(s32 cidx, s32 enable)
|
||||
padsCfg[cidx].stickCButtons = !enable;
|
||||
}
|
||||
|
||||
s32 inputControllerGetCancelCButtons(s32 cidx)
|
||||
{
|
||||
return padsCfg[cidx].cancelCButtons;
|
||||
}
|
||||
|
||||
void inputControllerSetCancelCButtons(s32 cidx, s32 cancel)
|
||||
{
|
||||
padsCfg[cidx].cancelCButtons = cancel;
|
||||
}
|
||||
|
||||
f32 inputControllerGetAxisScale(s32 cidx, s32 stick, s32 axis)
|
||||
{
|
||||
return padsCfg[cidx].sens[stick * 2 + axis];
|
||||
@@ -1091,13 +988,6 @@ const char *inputGetConnectedControllerName(s32 id)
|
||||
|
||||
snprintf(fullName, sizeof(fullName), "%d: %s", jidx, name);
|
||||
|
||||
// replace non-ascii chars with spaces
|
||||
for (char *p = fullName; *p; ++p) {
|
||||
if ((u32)*p >= 0x7f) {
|
||||
*p = ' ';
|
||||
}
|
||||
}
|
||||
|
||||
return fullName;
|
||||
}
|
||||
|
||||
@@ -1179,13 +1069,9 @@ s32 inputKeyPressed(u32 vk)
|
||||
if (vk >= VK_KEYBOARD_BEGIN && vk < VK_MOUSE_BEGIN) {
|
||||
const u8 *state = SDL_GetKeyboardState(NULL);
|
||||
return state[vk - VK_KEYBOARD_BEGIN];
|
||||
}
|
||||
|
||||
if (vk >= VK_MOUSE_BEGIN && vk < VK_JOY_BEGIN) {
|
||||
return (mouseButtons & SDL_BUTTON(vk - VK_MOUSE_BEGIN + 1)) != 0;
|
||||
}
|
||||
|
||||
if (vk >= VK_JOY_BEGIN && vk < VK_TOTAL_COUNT) {
|
||||
} else if (vk >= VK_MOUSE_BEGIN && vk < VK_JOY_BEGIN) {
|
||||
return mouseButtons & SDL_BUTTON(vk - VK_MOUSE_BEGIN + 1);
|
||||
} else if (vk >= VK_JOY_BEGIN && vk < VK_TOTAL_COUNT) {
|
||||
vk -= VK_JOY_BEGIN;
|
||||
const s32 idx = vk / INPUT_MAX_CONTROLLER_BUTTONS;
|
||||
if (idx < 0 || idx >= INPUT_MAX_CONTROLLERS || !pads[idx]) {
|
||||
@@ -1199,18 +1085,9 @@ s32 inputKeyPressed(u32 vk)
|
||||
}
|
||||
return SDL_GameControllerGetButton(pads[idx], vk);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 inputKeyJustPressed(u32 vk)
|
||||
{
|
||||
const s8 pressed = inputKeyPressed(vk);
|
||||
const s32 result = pressed && !vkPrevState[vk];
|
||||
vkPrevState[vk] = pressed;
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline u32 inputContToContKey(const u32 cont)
|
||||
{
|
||||
if (cont == 0) {
|
||||
@@ -1240,11 +1117,10 @@ s32 inputMouseIsLocked(void)
|
||||
return mouseLocked;
|
||||
}
|
||||
|
||||
s32 inputMouseGetPosition(s32 *x, s32 *y)
|
||||
void inputMouseGetPosition(s32 *x, s32 *y)
|
||||
{
|
||||
if (x) *x = mouseX * videoGetNativeWidth() / videoGetWidth();
|
||||
if (y) *y = mouseY * videoGetNativeHeight() / videoGetHeight();
|
||||
return (mouseDX != 0 || mouseDY != 0);
|
||||
}
|
||||
|
||||
void inputMouseGetRawDelta(s32 *dx, s32 *dy)
|
||||
@@ -1253,23 +1129,29 @@ void inputMouseGetRawDelta(s32 *dx, s32 *dy)
|
||||
if (dy) *dy = mouseDY;
|
||||
}
|
||||
|
||||
void inputMouseGetScaledDelta(f32* dx, f32* dy)
|
||||
void inputMouseGetScaledDelta(f32 *dx, f32 *dy)
|
||||
{
|
||||
f32 mdx = 0.f, mdy = 0.f;
|
||||
f32 mdx, mdy;
|
||||
if (mouseLocked) {
|
||||
mdx = mouseDX * (0.022f / 3.5f) * mouseSensX;
|
||||
mdy = mouseDY * (0.022f / 3.5f) * mouseSensY;
|
||||
mdx = mouseSensX * (f32)mouseDX / 100.0f;
|
||||
mdy = mouseSensY * (f32)mouseDY / 100.0f;
|
||||
} else {
|
||||
mdx = 0.f;
|
||||
mdy = 0.f;
|
||||
}
|
||||
if (dx) *dx = mdx;
|
||||
if (dy) *dy = mdy;
|
||||
}
|
||||
|
||||
void inputMouseGetAbsScaledDelta(f32* dx, f32* dy)
|
||||
void inputMouseGetAbsScaledDelta(f32 *dx, f32 *dy)
|
||||
{
|
||||
f32 mdx = 0.f, mdy = 0.f;
|
||||
f32 mdx, mdy;
|
||||
if (mouseLocked) {
|
||||
mdx = mouseDX * (0.022f / 3.5f) * fabsf(mouseSensX);
|
||||
mdy = mouseDY * (0.022f / 3.5f) * fabsf(mouseSensY);
|
||||
mdx = fabsf(mouseSensX) * (f32)mouseDX / 100.0f;
|
||||
mdy = fabsf(mouseSensY) * (f32)mouseDY / 100.0f;
|
||||
} else {
|
||||
mdx = 0.f;
|
||||
mdy = 0.f;
|
||||
}
|
||||
if (dx) *dx = mdx;
|
||||
if (dy) *dy = mdy;
|
||||
@@ -1295,41 +1177,21 @@ s32 inputMouseIsEnabled(void)
|
||||
void inputMouseEnable(s32 enabled)
|
||||
{
|
||||
mouseEnabled = !!enabled;
|
||||
if (!mouseEnabled && mouseLockMode != MLOCK_ON && mouseLocked) {
|
||||
if (!mouseEnabled && mouseLocked) {
|
||||
inputLockMouse(0);
|
||||
}
|
||||
}
|
||||
|
||||
s32 inputAutoLockMouse(s32 wantlock)
|
||||
s32 inputGetMouseDefaultLocked(void)
|
||||
{
|
||||
if (mouseEnabled && mouseLockMode == MLOCK_AUTO) {
|
||||
inputLockMouse(wantlock);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
return mouseDefaultLocked;
|
||||
}
|
||||
|
||||
void inputMouseShowCursor(s32 show)
|
||||
void inputSetMouseDefaultLocked(s32 defaultLocked)
|
||||
{
|
||||
mouseShowCursor = !!show;
|
||||
SDL_ShowCursor(mouseShowCursor);
|
||||
if (show) {
|
||||
mouseCursorTime = sysGetMicroseconds() + CURSOR_HIDE_TIME;
|
||||
}
|
||||
}
|
||||
|
||||
s32 inputGetMouseLockMode(void)
|
||||
{
|
||||
return mouseLockMode;
|
||||
}
|
||||
|
||||
void inputSetMouseLockMode(s32 lockmode)
|
||||
{
|
||||
mouseLockMode = lockmode;
|
||||
if (lockmode == MLOCK_ON) {
|
||||
inputLockMouse(1);
|
||||
} else {
|
||||
inputLockMouse(0);
|
||||
mouseDefaultLocked = !!defaultLocked;
|
||||
if (mouseEnabled) {
|
||||
inputLockMouse(mouseDefaultLocked);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1425,20 +1287,14 @@ char inputGetLastTextChar(void)
|
||||
return lastChar;
|
||||
}
|
||||
|
||||
static inline s32 filterChar(const char ch)
|
||||
s32 inputTextHandler(char *out, const u32 outSize, s32 *curCol)
|
||||
{
|
||||
return isalnum(ch) || ch == ' ' || ch == '?' || ch == '!' || ch == '.';
|
||||
}
|
||||
|
||||
s32 inputTextHandler(char *out, const u32 outSize, s32 *curCol, s32 oskCharsOnly)
|
||||
{
|
||||
const s32 ctrlHeld = inputGetKeyModState() & KM_CTRL;
|
||||
const s32 ctrlHeld = inputKeyPressed(VK_LCTRL) || inputKeyPressed(VK_RCTRL);
|
||||
|
||||
if (!ctrlHeld) {
|
||||
const char chr = inputGetLastTextChar();
|
||||
inputClearLastTextChar();
|
||||
const s32 valid = chr && (oskCharsOnly ? filterChar(chr) : isprint(chr));
|
||||
if (valid) {
|
||||
if (chr && isprint(chr)) {
|
||||
if (*curCol < outSize - 1) {
|
||||
out[(*curCol)++] = chr;
|
||||
out[*curCol] = '\0';
|
||||
@@ -1465,6 +1321,10 @@ s32 inputTextHandler(char *out, const u32 outSize, s32 *curCol, s32 oskCharsOnly
|
||||
} else {
|
||||
out[0] = '\0';
|
||||
}
|
||||
} else if (key == VK_RETURN) {
|
||||
if (out[0] && *curCol) {
|
||||
return 1;
|
||||
}
|
||||
} else if (key == VK_ESCAPE) {
|
||||
return -1;
|
||||
}
|
||||
@@ -1503,26 +1363,14 @@ void inputStopTextInput(void)
|
||||
textInput = 0;
|
||||
}
|
||||
|
||||
s32 inputIsTextInputActive(void)
|
||||
{
|
||||
return textInput;
|
||||
}
|
||||
|
||||
u32 inputGetKeyModState(void)
|
||||
{
|
||||
return SDL_GetModState();
|
||||
}
|
||||
|
||||
PD_CONSTRUCTOR static void inputConfigInit(void)
|
||||
{
|
||||
configRegisterInt("Input.MouseEnabled", &mouseEnabled, 0, 1);
|
||||
configRegisterInt("Input.MouseLockMode", &mouseLockMode, MLOCK_OFF, MLOCK_AUTO);
|
||||
configRegisterFloat("Input.MouseSpeedX", &mouseSensX, -30.f, 30.f);
|
||||
configRegisterFloat("Input.MouseSpeedY", &mouseSensY, -30.f, 30.f);
|
||||
configRegisterInt("Input.MouseDefaultLocked", &mouseDefaultLocked, 0, 1);
|
||||
configRegisterFloat("Input.MouseSpeedX", &mouseSensX, -10.f, 10.f);
|
||||
configRegisterFloat("Input.MouseSpeedY", &mouseSensY, -10.f, 10.f);
|
||||
configRegisterInt("Input.FakeGamepads", &fakeControllers, 0, 4);
|
||||
configRegisterInt("Input.FirstGamepadNum", &firstController, 0, 3);
|
||||
configRegisterInt("Input.UseHIDAPI", &useHIDAPI, 0, 1);
|
||||
configRegisterInt("Input.UseRawInput", &useRawInput, 0, 1);
|
||||
|
||||
char secname[] = "Input.Player1.Binds";
|
||||
char keyname[256] = { 0 };
|
||||
@@ -1539,7 +1387,6 @@ PD_CONSTRUCTOR static void inputConfigInit(void)
|
||||
configRegisterFloat(strFmt("%s.RStickScaleX", secname), &padsCfg[c].sens[2], -10.f, 10.f);
|
||||
configRegisterFloat(strFmt("%s.RStickScaleY", secname), &padsCfg[c].sens[3], -10.f, 10.f);
|
||||
configRegisterInt(strFmt("%s.StickCButtons", secname), &padsCfg[c].stickCButtons, 0, 1);
|
||||
configRegisterInt(strFmt("%s.CancelCButtons", secname), &padsCfg[c].cancelCButtons, 0, 1);
|
||||
configRegisterInt(strFmt("%s.SwapSticks", secname), &padsCfg[c].swapSticks, 0, 1);
|
||||
configRegisterInt(strFmt("%s.ControllerIndex", secname), &padsCfg[c].deviceIndex, -1, 0x7FFFFFFF);
|
||||
secname[13] = '.';
|
||||
|
||||
+8
-7
@@ -6,7 +6,6 @@
|
||||
#include <errno.h>
|
||||
#include <PR/os_internal.h>
|
||||
#include <PR/rcp.h>
|
||||
#include "platform.h"
|
||||
#include "system.h"
|
||||
#include "input.h"
|
||||
#include "video.h"
|
||||
@@ -278,7 +277,7 @@ static inline void osEeepromLoad(const char *fname)
|
||||
FILE *fp = fsFileOpenRead(fname);
|
||||
if (fp) {
|
||||
fread(eeprom, 1, EEPROM_SIZE, fp);
|
||||
fsFileFree(fp);
|
||||
fsFileClose(fp);
|
||||
} else {
|
||||
sysLogPrintf(LOG_NOTE, "could not read EEPROM from `%s`: %s", fsFullPath(fname), strerror(errno));
|
||||
}
|
||||
@@ -290,7 +289,7 @@ static inline void osEeepromSave(const char *fname)
|
||||
FILE* fp = fsFileOpenWrite(fname);
|
||||
if (fp) {
|
||||
fwrite(eeprom, 1, EEPROM_SIZE, fp);
|
||||
fsFileFree(fp);
|
||||
fsFileClose(fp);
|
||||
} else {
|
||||
sysLogPrintf(LOG_ERROR, "could not save EEPROM to `%s`: %s", fsFullPath(fname), strerror(errno));
|
||||
}
|
||||
@@ -434,7 +433,7 @@ void osInvalDCache(void *a, s32 b)
|
||||
|
||||
}
|
||||
|
||||
s32 osPiStartDma(OSIoMesg *mb, s32 priority, s32 direction, uintptr_t devAddr, void *vAddr, u32 nbytes, OSMesgQueue *mq)
|
||||
s32 osPiStartDma(OSIoMesg *mb, s32 priority, s32 direction, uintptr_t devAddr, void *vAddr, size_t nbytes, OSMesgQueue *mq)
|
||||
{
|
||||
memcpy(vAddr, (const void *)devAddr, nbytes);
|
||||
return 0;
|
||||
@@ -467,21 +466,23 @@ OSIntMask osSetIntMask(OSIntMask mask)
|
||||
|
||||
/* libc compatibility wrappers */
|
||||
|
||||
#ifndef PLATFORM_OSX
|
||||
|
||||
#ifndef HAVE_BZERO
|
||||
void bzero(void *ptr, size_t size)
|
||||
{
|
||||
memset(ptr, 0, size);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_BCOPY
|
||||
void bcopy(const void *src, void *dst, size_t n)
|
||||
{
|
||||
memcpy(dst, src, n);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_BCMP
|
||||
s32 bcmp(const void *s1, const void *s2, size_t n)
|
||||
{
|
||||
return memcmp(s1, s2, n);
|
||||
}
|
||||
|
||||
#endif
|
||||
+18
-10
@@ -16,7 +16,9 @@
|
||||
#include "config.h"
|
||||
#include "mod.h"
|
||||
#include "system.h"
|
||||
#include "console.h"
|
||||
#include "utils.h"
|
||||
#include "net/net.h"
|
||||
|
||||
u32 g_OsMemSize = 0;
|
||||
s32 g_OsMemSizeMb = 16;
|
||||
@@ -69,7 +71,7 @@ static void gameInit(void)
|
||||
{
|
||||
osMemSize = g_OsMemSizeMb * 1024 * 1024;
|
||||
|
||||
for (s32 i = 0; i < MAX_PLAYERS; ++i) {
|
||||
for (s32 i = 0; i < MAX_LOCAL_PLAYERS; ++i) {
|
||||
struct extplayerconfig *cfg = g_PlayerExtCfg + i;
|
||||
cfg->fovzoommult = cfg->fovzoom ? cfg->fovy / 60.0f : 1.0f;
|
||||
}
|
||||
@@ -86,9 +88,9 @@ static void gameInit(void)
|
||||
static void cleanup(void)
|
||||
{
|
||||
sysLogPrintf(LOG_NOTE, "shutdown");
|
||||
netDisconnect();
|
||||
inputSaveBinds();
|
||||
configSave(CONFIG_PATH);
|
||||
videoShutdown();
|
||||
crashShutdown();
|
||||
// TODO: actually shut down all subsystems
|
||||
}
|
||||
@@ -101,6 +103,7 @@ int main(int argc, const char **argv)
|
||||
crashInit();
|
||||
}
|
||||
|
||||
conInit();
|
||||
sysInit();
|
||||
fsInit();
|
||||
configInit();
|
||||
@@ -108,8 +111,7 @@ int main(int argc, const char **argv)
|
||||
inputInit();
|
||||
audioInit();
|
||||
romdataInit();
|
||||
|
||||
g_ValidGbcRomFound = romdataCheckGbcRom();
|
||||
netInit();
|
||||
|
||||
gameInit();
|
||||
|
||||
@@ -136,6 +138,8 @@ int main(int argc, const char **argv)
|
||||
|
||||
g_StageNum = sysArgGetInt("--boot-stage", STAGE_TITLE);
|
||||
|
||||
g_FileAutoSelect = sysArgGetInt("--profile", -1);
|
||||
|
||||
if (g_StageNum == STAGE_TITLE && (sysArgCheck("--skip-intro") || g_SkipIntro)) {
|
||||
// shorthand for --boot-stage 0x26
|
||||
g_StageNum = STAGE_CITRAINING;
|
||||
@@ -144,11 +148,19 @@ int main(int argc, const char **argv)
|
||||
g_StageNum = STAGE_TITLE;
|
||||
}
|
||||
|
||||
if (g_NetJoinLatch || g_NetHostLatch) {
|
||||
if (g_FileAutoSelect < 0) {
|
||||
// default to profile 0 if going into a net game
|
||||
g_FileAutoSelect = 0;
|
||||
}
|
||||
// skip the intro if going into a net game
|
||||
g_StageNum = STAGE_CITRAINING;
|
||||
}
|
||||
|
||||
if (g_StageNum != STAGE_TITLE) {
|
||||
sysLogPrintf(LOG_NOTE, "boot stage set to 0x%02x", g_StageNum);
|
||||
}
|
||||
|
||||
g_FileAutoSelect = sysArgGetInt("--profile", -1);
|
||||
if (g_FileAutoSelect >= 0) {
|
||||
sysLogPrintf(LOG_NOTE, "player profile set to %d", g_FileAutoSelect);
|
||||
}
|
||||
@@ -162,15 +174,13 @@ PD_CONSTRUCTOR static void gameConfigInit(void)
|
||||
{
|
||||
configRegisterInt("Game.MemorySize", &g_OsMemSizeMb, 4, 2048);
|
||||
configRegisterInt("Game.CenterHUD", &g_HudCenter, 0, 2);
|
||||
configRegisterInt("Game.MenuMouseControl", &g_MenuMouseControl, 0, 1);
|
||||
configRegisterFloat("Game.ScreenShakeIntensity", &g_ViShakeIntensityMult, 0.f, 10.f);
|
||||
configRegisterInt("Game.TickRateDivisor", &g_TickRateDiv, 0, 10);
|
||||
configRegisterInt("Game.ExtraSleep", &g_TickExtraSleep, 0, 1);
|
||||
configRegisterInt("Game.SkipIntro", &g_SkipIntro, 0, 1);
|
||||
configRegisterInt("Game.DisableMpDeathMusic", &g_MusicDisableMpDeath, 0, 1);
|
||||
configRegisterInt("Game.GEMuzzleFlashes", &g_BgunGeMuzzleFlashes, 0, 1);
|
||||
configRegisterInt("Game.MaxExplosions", &g_MaxExplosions, 6, 96);
|
||||
for (s32 j = 0; j < MAX_PLAYERS; ++j) {
|
||||
for (s32 j = 0; j < MAX_LOCAL_PLAYERS; ++j) {
|
||||
const s32 i = j + 1;
|
||||
configRegisterFloat(strFmt("Game.Player%d.FovY", i), &g_PlayerExtCfg[j].fovy, 5.f, 175.f);
|
||||
configRegisterInt(strFmt("Game.Player%d.FovAffectsZoom", i), &g_PlayerExtCfg[j].fovzoom, 0, 1);
|
||||
@@ -179,12 +189,10 @@ PD_CONSTRUCTOR static void gameConfigInit(void)
|
||||
configRegisterFloat(strFmt("Game.Player%d.MouseAimSpeedY", i), &g_PlayerExtCfg[j].mouseaimspeedy, 0.f, 10.f);
|
||||
configRegisterFloat(strFmt("Game.Player%d.RadialMenuSpeed", i), &g_PlayerExtCfg[j].radialmenuspeed, 0.f, 10.f);
|
||||
configRegisterFloat(strFmt("Game.Player%d.CrosshairSway", i), &g_PlayerExtCfg[j].crosshairsway, 0.f, 10.f);
|
||||
configRegisterFloat(strFmt("Game.Player%d.CrosshairEdgeBoundary", i), &g_PlayerExtCfg[j].crosshairedgeboundary, 0.0f, 1.0f);
|
||||
configRegisterInt(strFmt("Game.Player%d.CrouchMode", i), &g_PlayerExtCfg[j].crouchmode, 0, CROUCHMODE_TOGGLE_ANALOG);
|
||||
configRegisterInt(strFmt("Game.Player%d.ExtendedControls", i), &g_PlayerExtCfg[j].extcontrols, 0, 1);
|
||||
configRegisterUInt(strFmt("Game.Player%d.CrosshairColour", i), &g_PlayerExtCfg[j].crosshaircolour, 0, 0xFFFFFFFF);
|
||||
configRegisterUInt(strFmt("Game.Player%d.CrosshairSize", i), &g_PlayerExtCfg[j].crosshairsize, 0, 4);
|
||||
configRegisterInt(strFmt("Game.Player%d.CrosshairHealth", i), &g_PlayerExtCfg[j].crosshairhealth, 0, CROSSHAIR_HEALTH_ON_WHITE);
|
||||
configRegisterInt(strFmt("Game.Player%d.UseKeyReloads", i), &g_PlayerExtCfg[j].usereloads, 0, false);
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,6 @@
|
||||
#include "mixer.h"
|
||||
#include "platform.h"
|
||||
|
||||
#define MINIMP3_IMPLEMENTATION
|
||||
#include "external/minimp3.h"
|
||||
|
||||
#ifdef __SSE4_1__
|
||||
|
||||
+3
-3
@@ -420,7 +420,7 @@ s32 modTextureLoad(u16 num, void *dst, u32 dstSize)
|
||||
{
|
||||
static s32 dirExists = -1;
|
||||
if (dirExists < 0) {
|
||||
dirExists = (fsFileSize(MOD_TEXTURES_DIR) >= 0);
|
||||
dirExists = (fsFileSize(MOD_TEXTURES_DIR "/") >= 0);
|
||||
}
|
||||
|
||||
if (!dirExists) {
|
||||
@@ -442,7 +442,7 @@ void *modSequenceLoad(u16 num, u32 *outSize)
|
||||
{
|
||||
static s32 dirExists = -1;
|
||||
if (dirExists < 0) {
|
||||
dirExists = (fsFileSize(MOD_SEQUENCES_DIR) >= 0);
|
||||
dirExists = (fsFileSize(MOD_SEQUENCES_DIR "/") >= 0);
|
||||
}
|
||||
|
||||
if (!dirExists) {
|
||||
@@ -478,7 +478,7 @@ s32 modAnimationLoadDescriptor(u16 num, struct animtableentry *anim)
|
||||
{
|
||||
static s32 dirExists = -1;
|
||||
if (dirExists < 0) {
|
||||
dirExists = (fsFileSize(MOD_ANIMATIONS_DIR) >= 0);
|
||||
dirExists = (fsFileSize(MOD_ANIMATIONS_DIR "/") >= 0);
|
||||
}
|
||||
|
||||
if (!dirExists) {
|
||||
|
||||
@@ -1,896 +0,0 @@
|
||||
#include "types.h"
|
||||
#include "constants.h"
|
||||
#include "bss.h"
|
||||
#include "game/pak.h"
|
||||
#include "game/filelist.h"
|
||||
#include "game/menu.h"
|
||||
#include "game/savebuffer.h"
|
||||
#include "game/mplayer/mplayer.h"
|
||||
#include <string.h>
|
||||
#include "fs.h"
|
||||
#include "system.h"
|
||||
#include "mpsetups.h"
|
||||
|
||||
/*
|
||||
MP Setup File Format
|
||||
# header
|
||||
[version{1}]
|
||||
[defaultsetup{1}]
|
||||
[numsetups{1}]
|
||||
# setups
|
||||
[setup_1{80}]
|
||||
...
|
||||
[setup_n{80}]
|
||||
*/
|
||||
|
||||
#define MPSETUP_VERSION 1
|
||||
|
||||
#define MPSETUP_EXPORTDIR "$S/exported/"
|
||||
#define MPSETUP_FILENAME "mpsetups"
|
||||
#define MPSETUP_FILENAME_EXP "mpsetups-ext"
|
||||
|
||||
#define MPSETUP_OP_DEFAULT 0
|
||||
#define MPSETUP_OP_IMPORT 1
|
||||
#define MPSETUP_OP_EXPORT 2
|
||||
|
||||
#define MPSETUP_IMPORT_OVERWRITE 0
|
||||
#define MPSETUP_IMPORT_ADD 1
|
||||
|
||||
#define MPSETUP_IMPORT_CONFLICT 0x1313
|
||||
|
||||
extern struct menudialogdef g_MpSaveSetupNameMenuDialog;
|
||||
|
||||
s16 g_MpCurrentSetup = -1;
|
||||
struct mpsetupfile g_MpSetupFile;
|
||||
|
||||
static struct mpsetupfile g_ImportMpSetupFile;
|
||||
static u64 g_MpImportExportFilter[2];
|
||||
|
||||
static char g_StatusText[128];
|
||||
static char g_TitleImportExportDialog[20];
|
||||
static char g_LabelSetDefault[20] = "Set Default\n";
|
||||
|
||||
/* extended mpsetup menu definitions */
|
||||
|
||||
static MenuItemHandlerResult menuhandlerRenameSetup(s32 operation, struct menuitem *item, union handlerdata *data);
|
||||
static MenuItemHandlerResult menuhandlerDeleteSetup(s32 operation, struct menuitem *item, union handlerdata *data);
|
||||
static MenuItemHandlerResult menuhandlerImportOrExportSettings(s32 operation, struct menuitem *item, union handlerdata *data);
|
||||
static MenuItemHandlerResult menuhandlerImportAction(s32 operation, struct menuitem *item, union handlerdata *data);
|
||||
static MenuItemHandlerResult menuhandlerOpenImportExportDialog(s32 operation, struct menuitem *item, union handlerdata *data);
|
||||
static MenuItemHandlerResult menuhandlerSelectSetupHandler(s32 operation, struct menuitem *item, union handlerdata *data);
|
||||
static MenuItemHandlerResult menuhandlerSetupRename(s32 operation, struct menuitem *item, union handlerdata *data);
|
||||
static MenuItemHandlerResult menuhandlerSetupDelete(s32 operation, struct menuitem *item, union handlerdata *data);
|
||||
static MenuItemHandlerResult menuhandlerSetupSetDefault(s32 operation, struct menuitem *item, union handlerdata *data);
|
||||
|
||||
static struct menuitem g_StatusOkMenuItems[] = {
|
||||
{
|
||||
MENUITEMTYPE_LABEL,
|
||||
0,
|
||||
MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_LESSLEFTPADDING,
|
||||
(uintptr_t)g_StatusText,
|
||||
0,
|
||||
NULL,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SELECTABLE,
|
||||
0,
|
||||
MENUITEMFLAG_SELECTABLE_CLOSESDIALOG | MENUITEMFLAG_SELECTABLE_CENTRE,
|
||||
L_OPTIONS_347, // "OK"
|
||||
0,
|
||||
NULL,
|
||||
},
|
||||
{ MENUITEMTYPE_END },
|
||||
};
|
||||
|
||||
static struct menudialogdef g_StatusOkDialog = {
|
||||
MENUDIALOGTYPE_SUCCESS,
|
||||
L_OPTIONS_345, // "Cool!"
|
||||
g_StatusOkMenuItems,
|
||||
NULL,
|
||||
MENUDIALOGFLAG_DISABLEBANNER,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct menuitem g_StatusErrorMenuItems[] = {
|
||||
{
|
||||
MENUITEMTYPE_LABEL,
|
||||
0,
|
||||
MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_LESSLEFTPADDING,
|
||||
(uintptr_t)g_StatusText,
|
||||
0,
|
||||
NULL,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SELECTABLE,
|
||||
0,
|
||||
MENUITEMFLAG_SELECTABLE_CLOSESDIALOG | MENUITEMFLAG_SELECTABLE_CENTRE,
|
||||
L_OPTIONS_347, // "OK"
|
||||
0,
|
||||
NULL,
|
||||
},
|
||||
{ MENUITEMTYPE_END },
|
||||
};
|
||||
|
||||
/* public */
|
||||
struct menudialogdef g_StatusErrorDialog = {
|
||||
MENUDIALOGTYPE_DANGER,
|
||||
L_OPTIONS_277, // "Failed"
|
||||
g_StatusErrorMenuItems,
|
||||
NULL,
|
||||
MENUDIALOGFLAG_DISABLEBANNER,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct menuitem g_RenameSetupItems[] = {
|
||||
#if VERSION != VERSION_JPN_FINAL
|
||||
{
|
||||
MENUITEMTYPE_LABEL,
|
||||
0,
|
||||
MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_LESSLEFTPADDING,
|
||||
(uintptr_t)"Enter the setup name:\n",
|
||||
0,
|
||||
NULL,
|
||||
},
|
||||
#endif
|
||||
{
|
||||
MENUITEMTYPE_KEYBOARD,
|
||||
18,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
menuhandlerRenameSetup,
|
||||
},
|
||||
{ MENUITEMTYPE_END },
|
||||
};
|
||||
|
||||
static struct menudialogdef g_RenameSetupDialog = {
|
||||
MENUDIALOGTYPE_DEFAULT,
|
||||
(uintptr_t)"Setup Name:\n",
|
||||
g_RenameSetupItems,
|
||||
NULL,
|
||||
MENUDIALOGFLAG_LITERAL_TEXT,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct menuitem g_DeleteSetupItems[] = {
|
||||
{
|
||||
MENUITEMTYPE_LABEL,
|
||||
0,
|
||||
MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_LESSLEFTPADDING,
|
||||
(uintptr_t)"Delete Setup?\n",
|
||||
0,
|
||||
NULL,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SELECTABLE,
|
||||
0,
|
||||
MENUITEMFLAG_SELECTABLE_CLOSESDIALOG | MENUITEMFLAG_SELECTABLE_CENTRE,
|
||||
L_OPTIONS_385, // "No"
|
||||
0,
|
||||
NULL,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SELECTABLE,
|
||||
0,
|
||||
MENUITEMFLAG_SELECTABLE_CENTRE,
|
||||
L_OPTIONS_386, // "Yes"
|
||||
0,
|
||||
menuhandlerDeleteSetup,
|
||||
},
|
||||
{ MENUITEMTYPE_END },
|
||||
};
|
||||
|
||||
static struct menudialogdef g_DeleteSetupDialog = {
|
||||
MENUDIALOGTYPE_DANGER,
|
||||
(uintptr_t)"Delete Setup\n",
|
||||
g_DeleteSetupItems,
|
||||
NULL,
|
||||
MENUDIALOGFLAG_LITERAL_TEXT,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct menuitem g_ImportExportItems[] = {
|
||||
{
|
||||
MENUITEMTYPE_LIST,
|
||||
0,
|
||||
MENUITEMFLAG_LOCKABLEMINOR | MENUITEMFLAG_LABEL_CUSTOMCOLOUR,
|
||||
140,
|
||||
0x0000004d,
|
||||
menuhandlerImportOrExportSettings,
|
||||
},
|
||||
{ MENUITEMTYPE_END },
|
||||
};
|
||||
|
||||
static struct menudialogdef g_ImportExportDialog = {
|
||||
MENUDIALOGTYPE_DEFAULT,
|
||||
(uintptr_t) g_TitleImportExportDialog,
|
||||
g_ImportExportItems,
|
||||
NULL,
|
||||
MENUDIALOGFLAG_LITERAL_TEXT,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct menuitem g_ManageImportExportItems[] = {
|
||||
{
|
||||
MENUITEMTYPE_SELECTABLE,
|
||||
MPSETUP_OP_IMPORT,
|
||||
MENUITEMFLAG_LITERAL_TEXT,
|
||||
(uintptr_t)"Import Settings\n",
|
||||
0,
|
||||
menuhandlerOpenImportExportDialog,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SELECTABLE,
|
||||
MPSETUP_OP_EXPORT,
|
||||
MENUITEMFLAG_LITERAL_TEXT,
|
||||
(uintptr_t)"Export Settings\n",
|
||||
0,
|
||||
menuhandlerOpenImportExportDialog,
|
||||
},
|
||||
{ MENUITEMTYPE_END },
|
||||
};
|
||||
|
||||
static struct menudialogdef g_ManageImportExportDialog = {
|
||||
MENUDIALOGTYPE_DEFAULT,
|
||||
(uintptr_t) "Import/Export\n",
|
||||
g_ManageImportExportItems,
|
||||
NULL,
|
||||
MENUDIALOGFLAG_LITERAL_TEXT,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct menuitem g_MpManageSettingsListItems[] = {
|
||||
{
|
||||
MENUITEMTYPE_LIST,
|
||||
0,
|
||||
MENUITEMFLAG_LABEL_CUSTOMCOLOUR,
|
||||
160,
|
||||
0x00000042,
|
||||
menuhandlerSelectSetupHandler,
|
||||
},
|
||||
{ MENUITEMTYPE_END },
|
||||
|
||||
};
|
||||
|
||||
/* public */
|
||||
struct menudialogdef g_ManageSettingsDialog = {
|
||||
MENUDIALOGTYPE_DEFAULT,
|
||||
(uintptr_t) "Manage Settings\n",
|
||||
g_MpManageSettingsListItems,
|
||||
NULL,
|
||||
MENUDIALOGFLAG_LITERAL_TEXT,
|
||||
&g_ManageImportExportDialog,
|
||||
};
|
||||
|
||||
static struct menuitem g_ManageSetupItems[] = {
|
||||
{
|
||||
MENUITEMTYPE_SELECTABLE,
|
||||
0,
|
||||
MENUITEMFLAG_LITERAL_TEXT,
|
||||
(uintptr_t)"Rename\n",
|
||||
0,
|
||||
menuhandlerSetupRename,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SELECTABLE,
|
||||
0,
|
||||
MENUITEMFLAG_LITERAL_TEXT,
|
||||
(uintptr_t)"Delete\n",
|
||||
0,
|
||||
menuhandlerSetupDelete,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SELECTABLE,
|
||||
0,
|
||||
MENUITEMFLAG_LITERAL_TEXT,
|
||||
(uintptr_t)g_LabelSetDefault,
|
||||
0,
|
||||
menuhandlerSetupSetDefault,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SEPARATOR,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SELECTABLE,
|
||||
0,
|
||||
MENUITEMFLAG_SELECTABLE_CLOSESDIALOG,
|
||||
L_OPTIONS_213, // "Back"
|
||||
0,
|
||||
NULL,
|
||||
},
|
||||
{ MENUITEMTYPE_END },
|
||||
};
|
||||
|
||||
static struct menudialogdef g_ManageSetupDialog = {
|
||||
MENUDIALOGTYPE_DEFAULT,
|
||||
(uintptr_t)"Manage Setup",
|
||||
g_ManageSetupItems,
|
||||
NULL,
|
||||
MENUDIALOGFLAG_LITERAL_TEXT,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct menuitem g_ImportOverrideItems[] = {
|
||||
{
|
||||
MENUITEMTYPE_LABEL,
|
||||
0,
|
||||
MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_LESSLEFTPADDING,
|
||||
(uintptr_t) "How to resolve setups\nwith the same name?\n",
|
||||
0,
|
||||
NULL,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SELECTABLE,
|
||||
MPSETUP_IMPORT_ADD,
|
||||
MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SELECTABLE_CLOSESDIALOG,
|
||||
(uintptr_t) "Add\n",
|
||||
0,
|
||||
menuhandlerImportAction,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SELECTABLE,
|
||||
MPSETUP_IMPORT_OVERWRITE,
|
||||
MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SELECTABLE_CLOSESDIALOG,
|
||||
(uintptr_t) "Overwrite\n",
|
||||
0,
|
||||
menuhandlerImportAction,
|
||||
},
|
||||
{ MENUITEMTYPE_END },
|
||||
};
|
||||
|
||||
static struct menudialogdef g_ImportOverrideDialog = {
|
||||
MENUDIALOGTYPE_DEFAULT,
|
||||
(uintptr_t)"Name Conflicts\n",
|
||||
g_ImportOverrideItems,
|
||||
NULL,
|
||||
MENUDIALOGFLAG_LITERAL_TEXT,
|
||||
NULL,
|
||||
};
|
||||
|
||||
/* common utils */
|
||||
|
||||
static s32 mpsetupDeserialize(FILE *f, struct mpsetupfile *setupfile)
|
||||
{
|
||||
s32 rx = 0;
|
||||
|
||||
rx += fread(&setupfile->version, sizeof(setupfile->version), 1, f);
|
||||
rx += fread(&setupfile->defaultsetup, sizeof(setupfile->defaultsetup), 1, f);
|
||||
rx += fread(&setupfile->numsetups, sizeof(setupfile->numsetups), 1, f);
|
||||
|
||||
for (int i = 0; i < setupfile->numsetups; ++i) {
|
||||
rx += fread(setupfile->setups[i].bytes, sizeof(setupfile->setups[i].bytes), 1, f);
|
||||
}
|
||||
|
||||
return rx;
|
||||
}
|
||||
|
||||
static s32 mpsetupSerialize(FILE *f, struct mpsetupfile *setupfile)
|
||||
{
|
||||
s32 wx = 0;
|
||||
|
||||
wx += fwrite(&setupfile->version, sizeof(setupfile->version), 1, f);
|
||||
wx += fwrite(&setupfile->defaultsetup, sizeof(setupfile->defaultsetup), 1, f);
|
||||
wx += fwrite(&setupfile->numsetups, sizeof(setupfile->numsetups), 1, f);
|
||||
|
||||
for (int i = 0; i < setupfile->numsetups; ++i) {
|
||||
wx += fwrite(setupfile->setups[i].bytes, sizeof(setupfile->setups[i].bytes), 1, f);
|
||||
}
|
||||
|
||||
return wx;
|
||||
}
|
||||
|
||||
static FILE *mpsetupOpenFile(bool write, u8 op) {
|
||||
const char *filename = fsFullPath("$S/" MPSETUP_FILENAME ".bin");
|
||||
|
||||
if (op == MPSETUP_OP_EXPORT) {
|
||||
// create export directory if it doesn't exist
|
||||
if (fsFileSize(MPSETUP_EXPORTDIR) < 0) {
|
||||
if (fsCreateDir(MPSETUP_EXPORTDIR) != 0) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
filename = fsFullPath(MPSETUP_EXPORTDIR MPSETUP_FILENAME_EXP ".bin");
|
||||
} else if (op == MPSETUP_OP_IMPORT) {
|
||||
// same name as export but different folder
|
||||
filename = fsFullPath("$S/" MPSETUP_FILENAME_EXP ".bin");
|
||||
}
|
||||
|
||||
FILE *f;
|
||||
|
||||
if (fsFileSize(filename) < 0) {
|
||||
// setup file doesn't exist: create one
|
||||
f = fsFileOpenWrite(filename);
|
||||
fsFileFree(f);
|
||||
}
|
||||
|
||||
if (write) {
|
||||
f = fsFileOpenWrite(filename);
|
||||
} else {
|
||||
f = fsFileOpenRead(filename);
|
||||
}
|
||||
|
||||
if (f == NULL) {
|
||||
sysLogPrintf(LOG_ERROR, "Unable to open mp setup file");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
static s32 mpsetupSaveFile(u8 op, struct mpsetupfile *setupfile)
|
||||
{
|
||||
FILE *f = mpsetupOpenFile(true, op);
|
||||
if (f == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
s32 nwritten = mpsetupSerialize(f, setupfile);
|
||||
if (nwritten < 1) {
|
||||
fsFileFree(f);
|
||||
sysLogPrintf(LOG_ERROR, "Unable to write the MP setup file");
|
||||
snprintf(g_StatusText, sizeof(g_StatusText), "Unable to write the setup file\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
fsFileFree(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static s32 mpsetupLoadFile(struct mpsetupfile *setupfile, u8 op)
|
||||
{
|
||||
FILE *f = mpsetupOpenFile(false, op);
|
||||
if (f == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
mpsetupDeserialize(f, setupfile);
|
||||
|
||||
if (op == MPSETUP_OP_DEFAULT && setupfile->defaultsetup > 0) {
|
||||
mpsetupLoadSetup(setupfile->defaultsetup - 1);
|
||||
}
|
||||
|
||||
fsFileFree(f);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static s32 mpsetupImportFile(u8 op, u8 skipOverlap)
|
||||
{
|
||||
if (!skipOverlap) {
|
||||
// check for names overlap
|
||||
u8 overlap = false;
|
||||
for (int i = 0; i < g_ImportMpSetupFile.numsetups; ++i) {
|
||||
for (int j = 0; j < g_MpSetupFile.numsetups; ++j) {
|
||||
if (strcmp(g_ImportMpSetupFile.setups[i].bytes, g_MpSetupFile.setups[j].bytes) == 0) {
|
||||
overlap = true;
|
||||
return MPSETUP_IMPORT_CONFLICT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < g_ImportMpSetupFile.numsetups; ++i) {
|
||||
s16 overlapIdx = -1;
|
||||
for (int j = g_MpSetupFile.numsetups-1; j >= 0; --j) {
|
||||
if (strcmp(g_ImportMpSetupFile.setups[i].bytes, g_MpSetupFile.setups[j].bytes) == 0) {
|
||||
overlapIdx = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
s16 importIdx = overlapIdx;
|
||||
if (overlapIdx < 0 || op == MPSETUP_IMPORT_ADD) {
|
||||
if (g_MpSetupFile.numsetups == MPSETUP_MAXSETUPS) {
|
||||
snprintf(g_StatusText, sizeof(g_StatusText), "Number of setups exceeds %d\n", MPSETUP_MAXSETUPS);
|
||||
return -1;
|
||||
}
|
||||
importIdx = g_MpSetupFile.numsetups++;
|
||||
}
|
||||
|
||||
memcpy(g_MpSetupFile.setups[importIdx].bytes, g_ImportMpSetupFile.setups[i].bytes, MPSETUP_BLOCKSIZE);
|
||||
}
|
||||
|
||||
return mpsetupSaveCurrentFile();
|
||||
}
|
||||
|
||||
static s32 mpsetupExportFile(void)
|
||||
{
|
||||
struct mpsetupfile expMpSetupFile;
|
||||
expMpSetupFile.numsetups = 0;
|
||||
expMpSetupFile.defaultsetup = 0;
|
||||
expMpSetupFile.version = MPSETUP_VERSION;
|
||||
|
||||
u8 maxsetups = MPSETUP_MAXSETUPS;
|
||||
maxsetups = MIN(maxsetups, g_MpSetupFile.numsetups);
|
||||
for (int i = 0; i < maxsetups; ++i) {
|
||||
u8 bank = i < 64 ? 0 : 1;
|
||||
u8 bit = i - bank * 64;
|
||||
if (g_MpImportExportFilter[bank] & (1 << bit)) {
|
||||
u8 n = expMpSetupFile.numsetups;
|
||||
expMpSetupFile.numsetups++;
|
||||
char *name = g_MpSetupFile.setups[i].bytes;
|
||||
memcpy(expMpSetupFile.setups[n].bytes, g_MpSetupFile.setups[i].bytes, MPSETUP_BLOCKSIZE);
|
||||
expMpSetupFile.numsetups = n + 1;
|
||||
}
|
||||
}
|
||||
|
||||
s32 err = mpsetupSaveFile(MPSETUP_OP_EXPORT, &expMpSetupFile);
|
||||
if (err) {
|
||||
snprintf(g_StatusText, sizeof(g_StatusText), "Unable to write\nsetup file\n");
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static s32 mpsetupDelete(void)
|
||||
{
|
||||
s32 slotindex = g_Menus[g_MpPlayerNum].mpsetup.slotindex;
|
||||
for (int i = slotindex; i < g_MpSetupFile.numsetups - 1; ++i) {
|
||||
u8* dst = g_MpSetupFile.setups[i].bytes;
|
||||
u8* src = g_MpSetupFile.setups[i+1].bytes;
|
||||
memcpy(dst, src, MPSETUP_BLOCKSIZE);
|
||||
}
|
||||
|
||||
if (g_MpCurrentSetup > slotindex) {
|
||||
g_MpCurrentSetup--;
|
||||
}
|
||||
else if (g_MpCurrentSetup == slotindex) {
|
||||
g_MpCurrentSetup = -1;
|
||||
}
|
||||
|
||||
if (g_MpSetupFile.defaultsetup > slotindex + 1) {
|
||||
g_MpSetupFile.defaultsetup--;
|
||||
}
|
||||
else if (g_MpSetupFile.defaultsetup == slotindex + 1) {
|
||||
g_MpSetupFile.defaultsetup = 0;
|
||||
}
|
||||
|
||||
g_MpSetupFile.numsetups--;
|
||||
return mpsetupSaveCurrentFile();
|
||||
}
|
||||
|
||||
/* menu handlers */
|
||||
|
||||
// Rename setup dialog
|
||||
static MenuItemHandlerResult menuhandlerRenameSetup(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
char *name = data->keyboard.string;
|
||||
s32 slotindex = g_Menus[g_MpPlayerNum].mpsetup.slotindex;
|
||||
struct setupblock *setup = &g_MpSetupFile.setups[slotindex];
|
||||
s32 err;
|
||||
|
||||
switch (operation) {
|
||||
case MENUOP_GETTEXT:
|
||||
strcpy(name, setup->bytes);
|
||||
break;
|
||||
case MENUOP_SETTEXT:
|
||||
strcpy(g_MpSetup.name, name);
|
||||
break;
|
||||
case MENUOP_SET:
|
||||
strcpy(setup->bytes, name);
|
||||
err = mpsetupSaveSetup(slotindex, true);
|
||||
if (!err) {
|
||||
menuPopDialog();
|
||||
} else {
|
||||
// TODO
|
||||
// menuPushDialog(&g_FilemgrFileSavedMenuDialog);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Delete setup dialog
|
||||
static MenuItemHandlerResult menuhandlerDeleteSetup(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
if (operation == MENUOP_SET) {
|
||||
s32 err = mpsetupDelete();
|
||||
if (!err) {
|
||||
menuPopDialog();
|
||||
menuPopDialog();
|
||||
} else {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Import (or Export) settings dialog
|
||||
static MenuItemHandlerResult menuhandlerImportOrExportSettings(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
static const char *labels[] = {
|
||||
"Select All",
|
||||
"Select None",
|
||||
"Import",
|
||||
"Export",
|
||||
};
|
||||
|
||||
s32 op = g_Menus[g_MpPlayerNum].mpsetup.unke24;
|
||||
|
||||
struct mpsetupfile *setupfile = op == MPSETUP_OP_IMPORT ? &g_ImportMpSetupFile : &g_MpSetupFile;
|
||||
|
||||
u8 numsetups = setupfile->numsetups;
|
||||
u8 numitems = numsetups + 3;
|
||||
u8 bank = data->list.value < 64 ? 0 : 1;
|
||||
u8 bit = data->list.value - bank * 64;
|
||||
u8 hasselection = (g_MpImportExportFilter[0] | g_MpImportExportFilter[1]) != 0;
|
||||
u8 ofs;
|
||||
s32 err;
|
||||
u32 colour;
|
||||
s32 index;
|
||||
|
||||
switch (operation) {
|
||||
case MENUOP_GETCOLOUR:
|
||||
colour = data->list.unk04;
|
||||
if (data->list.value == numitems - 1) {
|
||||
data->list.unk04 = hasselection ? colour : (colour & 0xffffff00) | 0x66;
|
||||
}
|
||||
break;
|
||||
|
||||
case MENUOP_GETOPTIONCOUNT:
|
||||
data->list.value = numitems;
|
||||
break;
|
||||
|
||||
case MENUOP_GETOPTIONTEXT:
|
||||
if (data->list.value < numsetups) {
|
||||
return (uintptr_t) setupfile->setups[data->list.value].bytes;
|
||||
} else {
|
||||
// creates an offset to select the "Export" or "Import" label for the last item
|
||||
ofs = (data->list.value == numitems - 1) ? op - 1 : 0;
|
||||
return (intptr_t)labels[data->list.value - numsetups + ofs];
|
||||
}
|
||||
|
||||
case MENUOP_SET:
|
||||
if (data->list.value < setupfile->numsetups) {
|
||||
g_MpImportExportFilter[bank] ^= (1 << bit);
|
||||
} else {
|
||||
index = data->list.value - setupfile->numsetups;
|
||||
|
||||
switch (index) {
|
||||
// Select All
|
||||
case 0:
|
||||
g_MpImportExportFilter[0] = g_MpImportExportFilter[1] = -1;
|
||||
break;
|
||||
// Select None
|
||||
case 1:
|
||||
g_MpImportExportFilter[0] = g_MpImportExportFilter[1] = 0;
|
||||
break;
|
||||
// Export (or Import)
|
||||
case 2:
|
||||
if (hasselection) {
|
||||
err = op == MPSETUP_OP_IMPORT ? mpsetupImportFile(0, false) : mpsetupExportFile();
|
||||
if (!err) {
|
||||
menuPopDialog();
|
||||
if (op == MPSETUP_OP_IMPORT) {
|
||||
// back to the 'Manage Settings' screen
|
||||
menuPopDialog();
|
||||
menuPushDialog(&g_ManageSettingsDialog);
|
||||
} else {
|
||||
snprintf(g_StatusText, sizeof(g_StatusText), "File %s.bin\nwritten to the folder 'exported'\n", MPSETUP_FILENAME_EXP);
|
||||
menuPushDialog(&g_StatusOkDialog);
|
||||
}
|
||||
} else {
|
||||
if (err == MPSETUP_IMPORT_CONFLICT) {
|
||||
menuPopDialog();
|
||||
menuPushDialog(&g_ImportOverrideDialog);
|
||||
} else {
|
||||
menuPushDialog(&g_StatusErrorDialog);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MENUOP_GETSELECTEDINDEX:
|
||||
data->list.value = 0x000fffff;
|
||||
break;
|
||||
|
||||
case MENUOP_GETLISTITEMCHECKBOX:
|
||||
if (data->list.value < numsetups) {
|
||||
data->list.unk04 = (g_MpImportExportFilter[bank] & (1 << bit));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Import: overwrite dialog
|
||||
static MenuItemHandlerResult menuhandlerImportAction(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
if (operation == MENUOP_SET) {
|
||||
s32 err = mpsetupImportFile(item->param, true);
|
||||
if (!err) {
|
||||
menuPopDialog();
|
||||
menuPushDialog(&g_ManageSettingsDialog);
|
||||
} else {
|
||||
menuPushDialog(&g_StatusErrorDialog);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Manage Import/Export settings dialog
|
||||
static MenuItemHandlerResult menuhandlerOpenImportExportDialog(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
switch (operation) {
|
||||
case MENUOP_SET:
|
||||
if (item->param == MPSETUP_OP_IMPORT) {
|
||||
strcpy(g_TitleImportExportDialog, "Import Settings\n");
|
||||
if (fsFileSize("$S/" MPSETUP_FILENAME_EXP ".bin") < 0) {
|
||||
snprintf(
|
||||
g_StatusText, sizeof(g_StatusText),
|
||||
"No import file found.\n"
|
||||
"Place the file %s.bin\n"
|
||||
"Next to your %s.bin file\n",
|
||||
MPSETUP_FILENAME_EXP, MPSETUP_FILENAME
|
||||
);
|
||||
menuPushDialog(&g_StatusErrorDialog);
|
||||
return 0;
|
||||
}
|
||||
|
||||
mpsetupLoadFile(&g_ImportMpSetupFile, MPSETUP_OP_IMPORT);
|
||||
} else {
|
||||
strcpy(g_TitleImportExportDialog, "Export Settings\n");
|
||||
}
|
||||
g_Menus[g_MpPlayerNum].mpsetup.unke24 = item->param;
|
||||
g_MpImportExportFilter[0] = g_MpImportExportFilter[1] = -1;
|
||||
menuPushDialog(&g_ImportExportDialog);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Manage settings dialog
|
||||
static MenuItemHandlerResult menuhandlerSelectSetupHandler(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
u32 colour;
|
||||
switch (operation) {
|
||||
case MENUOP_GETCOLOUR:
|
||||
colour = data->list.unk04;
|
||||
if (data->list.value + 1 == g_MpSetupFile.defaultsetup) {
|
||||
data->list.unk04 = (colour & 0xffff0000) | 0xff;
|
||||
}
|
||||
break;
|
||||
case MENUOP_GETOPTIONCOUNT:
|
||||
data->list.value = g_MpSetupFile.numsetups;
|
||||
break;
|
||||
case MENUOP_GETOPTIONTEXT:
|
||||
return (uintptr_t) g_MpSetupFile.setups[data->list.value].bytes;
|
||||
case MENUOP_SET:
|
||||
g_Menus[g_MpPlayerNum].mpsetup.slotindex = data->list.value;
|
||||
if (data->list.value == g_MpSetupFile.defaultsetup - 1) {
|
||||
strcpy(g_LabelSetDefault, "Clear Default\n");
|
||||
} else {
|
||||
strcpy(g_LabelSetDefault, "Set Default\n");
|
||||
}
|
||||
menuPushDialog(&g_ManageSetupDialog);
|
||||
break;
|
||||
case MENUOP_GETSELECTEDINDEX:
|
||||
data->list.value = 0xfffff;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MenuItemHandlerResult menuhandlerSetupRename(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
if (operation == MENUOP_SET) {
|
||||
menuPushDialog(&g_RenameSetupDialog);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MenuItemHandlerResult menuhandlerSetupDelete(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
if (operation == MENUOP_SET) {
|
||||
menuPushDialog(&g_DeleteSetupDialog);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MenuItemHandlerResult menuhandlerSetupSetDefault(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
if (operation == MENUOP_SET) {
|
||||
s32 selected = g_Menus[g_MpPlayerNum].mpsetup.slotindex;
|
||||
// clicked on "clear default"
|
||||
if (selected == g_MpSetupFile.defaultsetup - 1) {
|
||||
g_MpSetupFile.defaultsetup = 0;
|
||||
strcpy(g_LabelSetDefault, "Set Default\n");
|
||||
} else {
|
||||
g_MpSetupFile.defaultsetup = selected + 1;
|
||||
strcpy(g_LabelSetDefault, "Clear Default\n");
|
||||
}
|
||||
|
||||
mpsetupSaveCurrentFile();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* public functions */
|
||||
|
||||
s32 mpsetupLoadCurrentFile(void)
|
||||
{
|
||||
return mpsetupLoadFile(&g_MpSetupFile, MPSETUP_OP_DEFAULT);
|
||||
}
|
||||
|
||||
s32 mpsetupSaveCurrentFile(void)
|
||||
{
|
||||
g_MpSetupFile.version = MPSETUP_VERSION;
|
||||
return mpsetupSaveFile(MPSETUP_OP_DEFAULT, &g_MpSetupFile);
|
||||
}
|
||||
|
||||
s32 mpsetupSaveSetup(s32 slotindex, u8 savefile)
|
||||
{
|
||||
struct savebuffer setup;
|
||||
|
||||
// request to add a new setup
|
||||
if (slotindex == g_MpSetupFile.numsetups) {
|
||||
g_MpCurrentSetup = g_MpSetupFile.numsetups++;
|
||||
}
|
||||
|
||||
savebufferClear(&setup);
|
||||
mpsetupfileSaveWad(&setup);
|
||||
|
||||
memcpy(g_MpSetupFile.setups[slotindex].bytes, setup.bytes, MPSETUP_BLOCKSIZE);
|
||||
|
||||
return savefile ? mpsetupSaveCurrentFile() : 0;
|
||||
}
|
||||
|
||||
void mpsetupLoadSetup(s32 index)
|
||||
{
|
||||
struct savebuffer buffer;
|
||||
savebufferClear(&buffer);
|
||||
struct setupblock *block = &g_MpSetupFile.setups[index];
|
||||
memcpy(&buffer.bytes, block->bytes, MPSETUP_BLOCKSIZE);
|
||||
mpsetupfileLoadWad(&buffer, g_MpSetupFile.version);
|
||||
g_MpCurrentSetup = index;
|
||||
}
|
||||
|
||||
void mpsetupCopyAllFromPak(void)
|
||||
{
|
||||
if (fsFileSize("$S/" MPSETUP_FILENAME ".bin") > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
filelistCreate(1, FILETYPE_MPSETUP);
|
||||
filelistsTick();
|
||||
|
||||
for (int i = 0; i < g_FileLists[1]->numfiles; ++i) {
|
||||
struct savebuffer buffer;
|
||||
savebufferClear(&buffer);
|
||||
struct filelistfile *file = &g_FileLists[1]->files[i];
|
||||
s32 device = pakFindBySerial(file->deviceserial);
|
||||
s32 err = pakReadBodyAtGuid(device, file->fileid, buffer.bytes, 0);
|
||||
|
||||
if (err != 0) {
|
||||
sysLogPrintf(LOG_ERROR, "Unable to read pak. device %d fileid %d deviceserial %d err %d",
|
||||
device, file->fileid, file->deviceserial, err);
|
||||
continue;
|
||||
}
|
||||
|
||||
mpsetupfileLoadWad(&buffer, 0);
|
||||
|
||||
// save the file when writing the last setup
|
||||
u8 savefile = i == g_FileLists[1]->numfiles - 1;
|
||||
mpsetupSaveSetup(g_MpSetupFile.numsetups, savefile);
|
||||
}
|
||||
|
||||
// to reset the mp setup
|
||||
mpInit(false);
|
||||
}
|
||||
+1127
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,305 @@
|
||||
#include <string.h>
|
||||
#include "types.h"
|
||||
#include "platform.h"
|
||||
#include "system.h"
|
||||
#include "net/netbuf.h"
|
||||
|
||||
/* read */
|
||||
|
||||
void netbufStartRead(struct netbuf *buf)
|
||||
{
|
||||
buf->error = 0;
|
||||
buf->wp = buf->size;
|
||||
buf->rp = 0;
|
||||
}
|
||||
|
||||
void netbufStartReadData(struct netbuf *buf, const void *data, u32 size)
|
||||
{
|
||||
buf->size = size;
|
||||
buf->data = (void *)data;
|
||||
netbufStartRead(buf);
|
||||
}
|
||||
|
||||
s32 netbufReadLeft(const struct netbuf *buf)
|
||||
{
|
||||
return buf->wp - buf->rp;
|
||||
}
|
||||
|
||||
static inline u32 netbufCanRead(struct netbuf *buf, const u32 num)
|
||||
{
|
||||
if (buf->error || buf->rp + num > buf->wp) {
|
||||
sysLogPrintf(LOG_ERROR, "NET: could not read %u bytes", num);
|
||||
__builtin_trap();
|
||||
buf->error = 1;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
u32 netbufReadData(struct netbuf *buf, void *out, u32 num)
|
||||
{
|
||||
if (netbufCanRead(buf, num)) {
|
||||
memcpy(out, buf->data + buf->rp, num);
|
||||
buf->rp += num;
|
||||
return num;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
u8 netbufReadU8(struct netbuf *buf)
|
||||
{
|
||||
if (netbufCanRead(buf, 1)) {
|
||||
return buf->data[buf->rp++];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
u16 netbufReadU16(struct netbuf *buf)
|
||||
{
|
||||
if (netbufCanRead(buf, 2)) {
|
||||
const u16 ret = *(u16 *)&buf->data[buf->rp];
|
||||
buf->rp += sizeof(ret);
|
||||
return PD_LE16(ret);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 netbufReadU32(struct netbuf *buf)
|
||||
{
|
||||
if (netbufCanRead(buf, 4)) {
|
||||
const u32 ret = *(u32 *)&buf->data[buf->rp];
|
||||
buf->rp += sizeof(ret);
|
||||
return PD_LE32(ret);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
u64 netbufReadU64(struct netbuf *buf)
|
||||
{
|
||||
if (netbufCanRead(buf, 8)) {
|
||||
const u64 ret = *(u64 *)&buf->data[buf->rp];
|
||||
buf->rp += sizeof(ret);
|
||||
return PD_LE64(ret);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
s8 netbufReadS8(struct netbuf *buf) {
|
||||
return (s8)netbufReadU8(buf);
|
||||
}
|
||||
|
||||
s16 netbufReadS16(struct netbuf *buf) {
|
||||
return (s16)netbufReadU16(buf);
|
||||
}
|
||||
|
||||
s32 netbufReadS32(struct netbuf *buf) {
|
||||
return (s32)netbufReadU32(buf);
|
||||
}
|
||||
|
||||
s64 netbufReadS64(struct netbuf *buf) {
|
||||
return (s64)netbufReadU64(buf);
|
||||
}
|
||||
|
||||
f32 netbufReadF32(struct netbuf *buf)
|
||||
{
|
||||
union {
|
||||
f32 f;
|
||||
u32 i;
|
||||
} hack;
|
||||
hack.i = netbufReadU32(buf);
|
||||
return hack.f;
|
||||
}
|
||||
|
||||
char *netbufReadStr(struct netbuf *buf)
|
||||
{
|
||||
const u16 len = netbufReadU16(buf);
|
||||
if (netbufCanRead(buf, len)) {
|
||||
char *ret = (char *)&buf->data[buf->rp];
|
||||
buf->rp += len;
|
||||
return ret;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
u32 netbufReadCoord(struct netbuf *buf, struct coord *out)
|
||||
{
|
||||
if (netbufCanRead(buf, sizeof(*out))) {
|
||||
out->x = netbufReadF32(buf);
|
||||
out->y = netbufReadF32(buf);
|
||||
out->z = netbufReadF32(buf);
|
||||
return sizeof(*out);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 netbufReadMtxf(struct netbuf *buf, Mtxf *out)
|
||||
{
|
||||
if (netbufCanRead(buf, sizeof(*out))) {
|
||||
for (s32 i = 0; i < 4; ++i) {
|
||||
for (s32 j = 0; j < 4; ++j) {
|
||||
out->m[i][j] = netbufReadF32(buf);
|
||||
}
|
||||
}
|
||||
return sizeof(*out);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 netbufReadSkip(struct netbuf *buf, u32 count)
|
||||
{
|
||||
if (netbufCanRead(buf, count)) {
|
||||
buf->rp += count;
|
||||
return count;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* write */
|
||||
|
||||
void netbufStartWrite(struct netbuf *buf)
|
||||
{
|
||||
buf->wp = 0;
|
||||
buf->error = 0;
|
||||
}
|
||||
|
||||
static inline u32 netbufCanWrite(struct netbuf *buf, const u32 num)
|
||||
{
|
||||
if (buf->error || buf->wp + num > buf->size) {
|
||||
buf->error = 1;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
s32 netbufWriteLeft(const struct netbuf *buf)
|
||||
{
|
||||
return buf->size - buf->wp;
|
||||
}
|
||||
|
||||
u32 netbufWriteData(struct netbuf *buf, const void *data, u32 num)
|
||||
{
|
||||
if (netbufCanWrite(buf, num)) {
|
||||
memcpy(buf->data + buf->wp, data, num);
|
||||
buf->wp += num;
|
||||
return num;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 netbufWriteU8(struct netbuf *buf, const u8 v)
|
||||
{
|
||||
if (netbufCanWrite(buf, sizeof(v))) {
|
||||
buf->data[buf->wp++] = v;
|
||||
return sizeof(v);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 netbufWriteU16(struct netbuf *buf, const u16 v)
|
||||
{
|
||||
if (netbufCanWrite(buf, sizeof(v))) {
|
||||
*(u16 *)&buf->data[buf->wp] = PD_LE16(v);
|
||||
buf->wp += sizeof(v);
|
||||
return sizeof(v);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 netbufWriteU32(struct netbuf *buf, const u32 v)
|
||||
{
|
||||
if (netbufCanWrite(buf, sizeof(v))) {
|
||||
*(u32 *)&buf->data[buf->wp] = PD_LE32(v);
|
||||
buf->wp += sizeof(v);
|
||||
return sizeof(v);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 netbufWriteU64(struct netbuf *buf, const u64 v)
|
||||
{
|
||||
if (netbufCanWrite(buf, sizeof(v))) {
|
||||
*(u64 *)&buf->data[buf->wp] = PD_LE64(v);
|
||||
buf->wp += sizeof(v);
|
||||
return sizeof(v);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 netbufWriteS8(struct netbuf *buf, const s8 v)
|
||||
{
|
||||
return netbufWriteU8(buf, (u8)v);
|
||||
}
|
||||
|
||||
u32 netbufWriteS16(struct netbuf *buf, const s16 v)
|
||||
{
|
||||
return netbufWriteU16(buf, (u16)v);
|
||||
}
|
||||
|
||||
u32 netbufWriteS32(struct netbuf *buf, const s32 v)
|
||||
{
|
||||
return netbufWriteU32(buf, (u32)v);
|
||||
}
|
||||
|
||||
u32 netbufWriteS64(struct netbuf *buf, const s64 v)
|
||||
{
|
||||
return netbufWriteU64(buf, (u64)v);
|
||||
}
|
||||
|
||||
u32 netbufWriteF32(struct netbuf *buf, const f32 v)
|
||||
{
|
||||
const union {
|
||||
f32 f;
|
||||
u32 i;
|
||||
} hack = { .f = v };
|
||||
return netbufWriteU32(buf, hack.i);
|
||||
}
|
||||
|
||||
u32 netbufWriteStr(struct netbuf *buf, const char *v)
|
||||
{
|
||||
if (!v) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 len = strlen(v) + 1;
|
||||
if (len > 0xFFFF) {
|
||||
len = 0xFFFF;
|
||||
}
|
||||
|
||||
if (netbufCanWrite(buf, len + sizeof(u16))) {
|
||||
netbufWriteU16(buf, len);
|
||||
netbufWriteData(buf, v, len);
|
||||
buf->data[buf->wp - 1] = 0;
|
||||
return sizeof(u16) + len;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 netbufWriteCoord(struct netbuf *buf, const struct coord *v)
|
||||
{
|
||||
if (netbufCanWrite(buf, sizeof(*v))) {
|
||||
netbufWriteF32(buf, v->x);
|
||||
netbufWriteF32(buf, v->y);
|
||||
netbufWriteF32(buf, v->z);
|
||||
return sizeof(*v);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 netbufWriteMtxf(struct netbuf *buf, const Mtxf *in)
|
||||
{
|
||||
if (netbufCanWrite(buf, sizeof(*in))) {
|
||||
for (s32 i = 0; i < 4; ++i) {
|
||||
for (s32 j = 0; j < 4; ++j) {
|
||||
netbufWriteF32(buf, in->m[i][j]);
|
||||
}
|
||||
}
|
||||
return sizeof(*in);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void netbufReset(struct netbuf *buf)
|
||||
{
|
||||
memset(buf, 0, sizeof(*buf));
|
||||
}
|
||||
@@ -0,0 +1,386 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <PR/ultratypes.h>
|
||||
#include "platform.h"
|
||||
#include "data.h"
|
||||
#include "types.h"
|
||||
#include "game/mainmenu.h"
|
||||
#include "game/menu.h"
|
||||
#include "game/gamefile.h"
|
||||
#include "video.h"
|
||||
#include "input.h"
|
||||
#include "config.h"
|
||||
#include "net/net.h"
|
||||
|
||||
extern MenuItemHandlerResult menuhandlerMainMenuCombatSimulator(s32 operation, struct menuitem *item, union handlerdata *data);
|
||||
extern MenuItemHandlerResult menuhandlerMpAdvancedSetup(s32 operation, struct menuitem *item, union handlerdata *data);
|
||||
|
||||
static s32 g_NetMenuMaxPlayers = NET_MAX_CLIENTS;
|
||||
static s32 g_NetMenuPort = NET_DEFAULT_PORT;
|
||||
static char g_NetJoinAddr[NET_MAX_ADDR + 1];
|
||||
static s32 g_NetJoinAddrPtr = 0;
|
||||
|
||||
/* host */
|
||||
|
||||
static MenuItemHandlerResult menuhandlerHostMaxPlayers(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
switch (operation) {
|
||||
case MENUOP_GETSLIDER:
|
||||
data->slider.value = g_NetMenuMaxPlayers;
|
||||
break;
|
||||
case MENUOP_SET:
|
||||
if (data->slider.value) {
|
||||
g_NetMenuMaxPlayers = data->slider.value;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MenuItemHandlerResult menuhandlerHostPort(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
if (operation == MENUOP_SET) {
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *menuhandlerHostPortValue(struct menuitem *item)
|
||||
{
|
||||
static char tmp[16];
|
||||
snprintf(tmp, sizeof(tmp), "%u\n", g_NetMenuPort);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
MenuItemHandlerResult menuhandlerHostStart(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
if (operation == MENUOP_SET) {
|
||||
if (netStartServer(g_NetMenuPort, g_NetMenuMaxPlayers) == 0) {
|
||||
menuhandlerMainMenuCombatSimulator(MENUOP_SET, NULL, NULL);
|
||||
menuhandlerMpAdvancedSetup(MENUOP_SET, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct menuitem g_NetHostMenuItems[] = {
|
||||
{
|
||||
MENUITEMTYPE_SLIDER,
|
||||
0,
|
||||
MENUITEMFLAG_LITERAL_TEXT,
|
||||
(uintptr_t)"Max Players",
|
||||
NET_MAX_CLIENTS,
|
||||
menuhandlerHostMaxPlayers,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SELECTABLE,
|
||||
0,
|
||||
MENUITEMFLAG_LITERAL_TEXT,
|
||||
(uintptr_t)"Port\n",
|
||||
(uintptr_t)&menuhandlerHostPortValue,
|
||||
menuhandlerHostPort,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SELECTABLE,
|
||||
0,
|
||||
0,
|
||||
L_MPMENU_036, // "Start Game"
|
||||
0,
|
||||
menuhandlerHostStart,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SEPARATOR,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SELECTABLE,
|
||||
0,
|
||||
MENUITEMFLAG_SELECTABLE_CLOSESDIALOG,
|
||||
L_OPTIONS_213, // "Back"
|
||||
0,
|
||||
NULL,
|
||||
},
|
||||
{ MENUITEMTYPE_END },
|
||||
};
|
||||
|
||||
struct menudialogdef g_NetHostMenuDialog = {
|
||||
MENUDIALOGTYPE_DEFAULT,
|
||||
(uintptr_t)"Host Network Game",
|
||||
g_NetHostMenuItems,
|
||||
NULL,
|
||||
MENUDIALOGFLAG_LITERAL_TEXT,
|
||||
NULL,
|
||||
};
|
||||
|
||||
/* join */
|
||||
|
||||
static const char *menutextJoinAddress(struct menuitem *item)
|
||||
{
|
||||
static char tmp[256 + 1];
|
||||
if (item && item->flags & MENUITEMFLAG_SELECTABLE_CENTRE) {
|
||||
// in centered dialog
|
||||
if (g_NetMode == NETMODE_NONE) {
|
||||
snprintf(tmp, sizeof(tmp), "%s_\n", g_NetJoinAddr);
|
||||
} else if (g_NetLocalClient->state == CLSTATE_CONNECTING) {
|
||||
snprintf(tmp, sizeof(tmp), "Connecting to %s...\n", g_NetJoinAddr);
|
||||
} else if (g_NetLocalClient->state == CLSTATE_AUTH) {
|
||||
snprintf(tmp, sizeof(tmp), "Authenticating with %s...\n", g_NetJoinAddr);
|
||||
} else if (g_NetLocalClient->state == CLSTATE_LOBBY) {
|
||||
snprintf(tmp, sizeof(tmp), "Waiting for host...\n");
|
||||
}
|
||||
} else {
|
||||
// label
|
||||
snprintf(tmp, sizeof(tmp), "%s\n", g_NetJoinAddr);
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static MenuItemHandlerResult menuhandlerJoining(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
if (inputKeyPressed(VK_ESCAPE)) {
|
||||
netDisconnect();
|
||||
menuPopDialog();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct menuitem g_NetJoiningMenuItems[] = {
|
||||
{
|
||||
MENUITEMTYPE_LABEL,
|
||||
0,
|
||||
MENUITEMFLAG_SELECTABLE_CENTRE,
|
||||
(uintptr_t)&menutextJoinAddress,
|
||||
0,
|
||||
NULL,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SEPARATOR,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SELECTABLE,
|
||||
0,
|
||||
MENUITEMFLAG_SELECTABLE_CENTRE | MENUITEMFLAG_LITERAL_TEXT,
|
||||
(uintptr_t)"ESC to abort\n",
|
||||
0,
|
||||
menuhandlerJoining,
|
||||
},
|
||||
{ MENUITEMTYPE_END },
|
||||
};
|
||||
|
||||
struct menudialogdef g_NetJoiningDialog = {
|
||||
MENUDIALOGTYPE_SUCCESS,
|
||||
(uintptr_t)"Joining Game...",
|
||||
g_NetJoiningMenuItems,
|
||||
NULL,
|
||||
MENUDIALOGFLAG_LITERAL_TEXT | MENUDIALOGFLAG_IGNOREBACK | MENUDIALOGFLAG_STARTSELECTS,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static MenuItemHandlerResult menuhandlerEnterJoinAddress(s32 operation, struct menuitem *item, union handlerdata *data);
|
||||
|
||||
struct menuitem g_NetJoinAddressMenuItems[] = {
|
||||
{
|
||||
MENUITEMTYPE_LABEL,
|
||||
0,
|
||||
MENUITEMFLAG_SELECTABLE_CENTRE,
|
||||
(uintptr_t)&menutextJoinAddress,
|
||||
0,
|
||||
NULL,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SEPARATOR,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SELECTABLE,
|
||||
0,
|
||||
MENUITEMFLAG_SELECTABLE_CENTRE | MENUITEMFLAG_LITERAL_TEXT,
|
||||
(uintptr_t)"ESC to return\n",
|
||||
0,
|
||||
menuhandlerEnterJoinAddress,
|
||||
},
|
||||
{ MENUITEMTYPE_END },
|
||||
};
|
||||
|
||||
struct menudialogdef g_NetJoinAddressDialog = {
|
||||
MENUDIALOGTYPE_SUCCESS,
|
||||
(uintptr_t)"Enter Address",
|
||||
g_NetJoinAddressMenuItems,
|
||||
NULL,
|
||||
MENUDIALOGFLAG_LITERAL_TEXT | MENUDIALOGFLAG_IGNOREBACK | MENUDIALOGFLAG_STARTSELECTS,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static MenuItemHandlerResult menuhandlerEnterJoinAddress(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
if (!menuIsDialogOpen(&g_NetJoinAddressDialog)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (inputTextHandler(g_NetJoinAddr, NET_MAX_ADDR, &g_NetJoinAddrPtr) < 0) {
|
||||
// escape has been pressed, stop editing
|
||||
inputStopTextInput();
|
||||
menuPopDialog();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MenuItemHandlerResult menuhandlerJoinAddress(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
if (operation == MENUOP_SET) {
|
||||
inputClearLastKey();
|
||||
inputClearLastTextChar();
|
||||
inputStartTextInput();
|
||||
g_NetJoinAddrPtr = strlen(g_NetJoinAddr);
|
||||
menuPushDialog(&g_NetJoinAddressDialog);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
MenuItemHandlerResult menuhandlerJoinStart(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
if (operation == MENUOP_SET) {
|
||||
if (netStartClient(g_NetJoinAddr) == 0) {
|
||||
menuPushDialog(&g_NetJoiningDialog);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct menuitem g_NetJoinMenuItems[] = {
|
||||
{
|
||||
MENUITEMTYPE_SELECTABLE,
|
||||
0,
|
||||
MENUITEMFLAG_LITERAL_TEXT,
|
||||
(uintptr_t)"Address: \n",
|
||||
(uintptr_t)&menutextJoinAddress,
|
||||
menuhandlerJoinAddress,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SELECTABLE,
|
||||
0,
|
||||
0,
|
||||
L_MPMENU_036, // "Start Game"
|
||||
0,
|
||||
menuhandlerJoinStart,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SEPARATOR,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SELECTABLE,
|
||||
0,
|
||||
MENUITEMFLAG_SELECTABLE_CLOSESDIALOG,
|
||||
L_OPTIONS_213, // "Back"
|
||||
0,
|
||||
NULL,
|
||||
},
|
||||
{ MENUITEMTYPE_END },
|
||||
};
|
||||
|
||||
struct menudialogdef g_NetJoinMenuDialog = {
|
||||
MENUDIALOGTYPE_DEFAULT,
|
||||
(uintptr_t)"Join Network Game",
|
||||
g_NetJoinMenuItems,
|
||||
NULL,
|
||||
MENUDIALOGFLAG_LITERAL_TEXT | MENUDIALOGFLAG_STARTSELECTS | MENUDIALOGFLAG_IGNOREBACK,
|
||||
NULL,
|
||||
};
|
||||
|
||||
/* main */
|
||||
|
||||
MenuItemHandlerResult menuhandlerHostGame(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
if (operation == MENUOP_SET) {
|
||||
g_NetMenuPort = g_NetServerPort;
|
||||
g_NetMenuMaxPlayers = g_NetMaxClients;
|
||||
menuPushDialog(&g_NetHostMenuDialog);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
MenuItemHandlerResult menuhandlerJoinGame(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
if (operation == MENUOP_SET) {
|
||||
if (g_NetJoinAddr[0] == '\0') {
|
||||
strncpy(g_NetJoinAddr, g_NetLastJoinAddr, NET_MAX_ADDR);
|
||||
g_NetJoinAddrPtr = strlen(g_NetJoinAddr);
|
||||
}
|
||||
menuPushDialog(&g_NetJoinMenuDialog);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct menuitem g_NetMenuItems[] = {
|
||||
{
|
||||
MENUITEMTYPE_SELECTABLE,
|
||||
0,
|
||||
MENUITEMFLAG_LITERAL_TEXT,
|
||||
(uintptr_t)"Host Game\n",
|
||||
0,
|
||||
menuhandlerHostGame,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SELECTABLE,
|
||||
0,
|
||||
MENUITEMFLAG_LITERAL_TEXT,
|
||||
(uintptr_t)"Join Game\n",
|
||||
0,
|
||||
menuhandlerJoinGame,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SEPARATOR,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SELECTABLE,
|
||||
0,
|
||||
MENUITEMFLAG_SELECTABLE_CLOSESDIALOG,
|
||||
L_OPTIONS_213, // "Back"
|
||||
0,
|
||||
NULL,
|
||||
},
|
||||
{ MENUITEMTYPE_END },
|
||||
};
|
||||
|
||||
struct menudialogdef g_NetMenuDialog = {
|
||||
MENUDIALOGTYPE_DEFAULT,
|
||||
(uintptr_t)"Network Game",
|
||||
g_NetMenuItems,
|
||||
NULL,
|
||||
MENUDIALOGFLAG_MPLOCKABLE | MENUDIALOGFLAG_LITERAL_TEXT,
|
||||
NULL,
|
||||
};
|
||||
File diff suppressed because it is too large.
Load diff
+40
-494
@@ -9,8 +9,6 @@
|
||||
#include "game/mainmenu.h"
|
||||
#include "game/menu.h"
|
||||
#include "game/gamefile.h"
|
||||
#include "game/player.h"
|
||||
#include "lib/joy.h"
|
||||
#include "video.h"
|
||||
#include "input.h"
|
||||
#include "config.h"
|
||||
@@ -121,40 +119,13 @@ static MenuItemHandlerResult menuhandlerMouseAimLock(s32 operation, struct menui
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MenuItemHandlerResult menuhandlerMouseLockMode(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
static const char *opts[] = {
|
||||
"Always Off",
|
||||
"Always On",
|
||||
"Auto"
|
||||
};
|
||||
|
||||
switch (operation) {
|
||||
case MENUOP_GETOPTIONCOUNT:
|
||||
data->dropdown.value = ARRAYCOUNT(opts);
|
||||
break;
|
||||
case MENUOP_GETOPTIONTEXT:
|
||||
return (intptr_t)opts[data->dropdown.value];
|
||||
case MENUOP_SET:
|
||||
inputSetMouseLockMode(data->checkbox.value);
|
||||
break;
|
||||
case MENUOP_GETSELECTEDINDEX:
|
||||
data->dropdown.value = inputGetMouseLockMode();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MenuItemHandlerResult menuhandlerMenuMouseControl(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
static MenuItemHandlerResult menuhandlerMouseDefaultLocked(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
switch (operation) {
|
||||
case MENUOP_GET:
|
||||
return g_MenuMouseControl;
|
||||
return inputGetMouseDefaultLocked();
|
||||
case MENUOP_SET:
|
||||
g_MenuMouseControl = data->checkbox.value;
|
||||
if (!g_MenuMouseControl) {
|
||||
g_MenuUsingMouse = false;
|
||||
}
|
||||
inputSetMouseDefaultLocked(data->checkbox.value);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -170,16 +141,15 @@ static MenuItemHandlerResult menuhandlerMouseSpeedX(s32 operation, struct menuit
|
||||
inputMouseGetSpeed(&x, &y);
|
||||
if (x < 0.f) {
|
||||
data->slider.value = 0;
|
||||
} else if (x > 10.f) {
|
||||
data->slider.value = 100;
|
||||
} else {
|
||||
data->slider.value = x * 100.f + 0.5f;
|
||||
data->slider.value = x * 10.f + 0.5f;
|
||||
}
|
||||
break;
|
||||
case MENUOP_SET:
|
||||
inputMouseGetSpeed(&x, &y);
|
||||
inputMouseSetSpeed((f32)data->slider.value / 100.f, y);
|
||||
break;
|
||||
case MENUOP_GETSLIDERLABEL:
|
||||
sprintf(data->slider.label, "%.2f", (f32)data->slider.value / 100.f);
|
||||
inputMouseSetSpeed((f32)data->slider.value / 10.f, y);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -195,16 +165,15 @@ static MenuItemHandlerResult menuhandlerMouseSpeedY(s32 operation, struct menuit
|
||||
inputMouseGetSpeed(&x, &y);
|
||||
if (y < 0.f) {
|
||||
data->slider.value = 0;
|
||||
} else if (y > 10.f) {
|
||||
data->slider.value = 100;
|
||||
} else {
|
||||
data->slider.value = y * 100.f + 0.5f;
|
||||
data->slider.value = y * 10.f + 0.5f;
|
||||
}
|
||||
break;
|
||||
case MENUOP_SET:
|
||||
inputMouseGetSpeed(&x, &y);
|
||||
inputMouseSetSpeed(x, (f32)data->slider.value / 100.f);
|
||||
break;
|
||||
case MENUOP_GETSLIDERLABEL:
|
||||
sprintf(data->slider.label, "%.2f", (f32)data->slider.value / 100.f);
|
||||
inputMouseSetSpeed(x, (f32)data->slider.value / 10.f);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -218,16 +187,14 @@ static MenuItemHandlerResult menuhandlerMouseAimSpeedX(s32 operation, struct men
|
||||
if (g_PlayerExtCfg[g_ExtMenuPlayer].mouseaimspeedx < 0.f) {
|
||||
data->slider.value = 0;
|
||||
} else if (g_PlayerExtCfg[g_ExtMenuPlayer].mouseaimspeedx > 10.f) {
|
||||
data->slider.value = 1000;
|
||||
data->slider.value = 100;
|
||||
} else {
|
||||
data->slider.value = g_PlayerExtCfg[g_ExtMenuPlayer].mouseaimspeedx * 100.f + 0.5f;
|
||||
data->slider.value = g_PlayerExtCfg[g_ExtMenuPlayer].mouseaimspeedx * 10.f + 0.5f;
|
||||
}
|
||||
break;
|
||||
case MENUOP_SET:
|
||||
g_PlayerExtCfg[g_ExtMenuPlayer].mouseaimspeedx = (f32)data->slider.value / 100.f;
|
||||
g_PlayerExtCfg[g_ExtMenuPlayer].mouseaimspeedx = (f32)data->slider.value / 10.f;
|
||||
break;
|
||||
case MENUOP_GETSLIDERLABEL:
|
||||
sprintf(data->slider.label, "%.2f", (f32)data->slider.value / 100.f);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -240,16 +207,14 @@ static MenuItemHandlerResult menuhandlerMouseAimSpeedY(s32 operation, struct men
|
||||
if (g_PlayerExtCfg[g_ExtMenuPlayer].mouseaimspeedy < 0.f) {
|
||||
data->slider.value = 0;
|
||||
} else if (g_PlayerExtCfg[g_ExtMenuPlayer].mouseaimspeedy > 10.f) {
|
||||
data->slider.value = 1000;
|
||||
data->slider.value = 100;
|
||||
} else {
|
||||
data->slider.value = g_PlayerExtCfg[g_ExtMenuPlayer].mouseaimspeedy * 100.f + 0.5f;
|
||||
data->slider.value = g_PlayerExtCfg[g_ExtMenuPlayer].mouseaimspeedy * 10.f + 0.5f;
|
||||
}
|
||||
break;
|
||||
case MENUOP_SET:
|
||||
g_PlayerExtCfg[g_ExtMenuPlayer].mouseaimspeedy = (f32)data->slider.value / 100.f;
|
||||
g_PlayerExtCfg[g_ExtMenuPlayer].mouseaimspeedy = (f32)data->slider.value / 10.f;
|
||||
break;
|
||||
case MENUOP_GETSLIDERLABEL:
|
||||
sprintf(data->slider.label, "%.2f", (f32)data->slider.value / 100.f);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -262,16 +227,14 @@ static MenuItemHandlerResult menuhandlerRadialMenuSpeed(s32 operation, struct me
|
||||
if (g_PlayerExtCfg[0].radialmenuspeed < 0.f) {
|
||||
data->slider.value = 0;
|
||||
} else if (g_PlayerExtCfg[0].radialmenuspeed > 10.f) {
|
||||
data->slider.value = 1000;
|
||||
data->slider.value = 100;
|
||||
} else {
|
||||
data->slider.value = g_PlayerExtCfg[0].radialmenuspeed * 100.f + 0.5f;
|
||||
data->slider.value = g_PlayerExtCfg[0].radialmenuspeed * 10.f + 0.5f;
|
||||
}
|
||||
break;
|
||||
case MENUOP_SET:
|
||||
g_PlayerExtCfg[0].radialmenuspeed = (f32)data->slider.value / 100.f;
|
||||
g_PlayerExtCfg[0].radialmenuspeed = (f32)data->slider.value / 10.f;
|
||||
break;
|
||||
case MENUOP_GETSLIDERLABEL:
|
||||
sprintf(data->slider.label, "%.2f", (f32)data->slider.value / 100.f);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -294,21 +257,13 @@ struct menuitem g_ExtendedMouseMenuItems[] = {
|
||||
0,
|
||||
menuhandlerMouseAimLock,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_DROPDOWN,
|
||||
0,
|
||||
MENUITEMFLAG_LITERAL_TEXT,
|
||||
(uintptr_t)"Mouse Lock Mode",
|
||||
0,
|
||||
menuhandlerMouseLockMode,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_CHECKBOX,
|
||||
0,
|
||||
MENUITEMFLAG_LITERAL_TEXT,
|
||||
(uintptr_t)"Mouse Menu Navigation",
|
||||
(uintptr_t)"Grab Mouse Input by Default",
|
||||
0,
|
||||
menuhandlerMenuMouseControl,
|
||||
menuhandlerMouseDefaultLocked,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SEPARATOR,
|
||||
@@ -323,7 +278,7 @@ struct menuitem g_ExtendedMouseMenuItems[] = {
|
||||
0,
|
||||
MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SLIDER_WIDE,
|
||||
(uintptr_t)"Mouse Speed X",
|
||||
3000,
|
||||
100,
|
||||
menuhandlerMouseSpeedX,
|
||||
},
|
||||
{
|
||||
@@ -331,7 +286,7 @@ struct menuitem g_ExtendedMouseMenuItems[] = {
|
||||
0,
|
||||
MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SLIDER_WIDE,
|
||||
(uintptr_t)"Mouse Speed Y",
|
||||
3000,
|
||||
100,
|
||||
menuhandlerMouseSpeedY,
|
||||
},
|
||||
{
|
||||
@@ -339,7 +294,7 @@ struct menuitem g_ExtendedMouseMenuItems[] = {
|
||||
0,
|
||||
MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SLIDER_WIDE,
|
||||
(uintptr_t)"Crosshair Speed X",
|
||||
1000,
|
||||
100,
|
||||
menuhandlerMouseAimSpeedX,
|
||||
},
|
||||
{
|
||||
@@ -347,7 +302,7 @@ struct menuitem g_ExtendedMouseMenuItems[] = {
|
||||
0,
|
||||
MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SLIDER_WIDE,
|
||||
(uintptr_t)"Crosshair Speed Y",
|
||||
1000,
|
||||
100,
|
||||
menuhandlerMouseAimSpeedY,
|
||||
},
|
||||
{
|
||||
@@ -355,7 +310,7 @@ struct menuitem g_ExtendedMouseMenuItems[] = {
|
||||
0,
|
||||
MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SLIDER_WIDE,
|
||||
(uintptr_t)"Radial Menu Speed",
|
||||
1000,
|
||||
100,
|
||||
menuhandlerRadialMenuSpeed,
|
||||
},
|
||||
{
|
||||
@@ -596,10 +551,8 @@ static MenuItemHandlerResult menuhandlerController(s32 operation, struct menuite
|
||||
if (data->dropdown.value == 0) {
|
||||
// unassign controller
|
||||
inputAssignController(g_ExtMenuPlayer, -1);
|
||||
joyReset();
|
||||
} else if (data->dropdown.value <= numCtrls) {
|
||||
inputAssignController(g_ExtMenuPlayer, ctrls[data->dropdown.value - 1]);
|
||||
joyReset();
|
||||
}
|
||||
break;
|
||||
case MENUOP_GETSELECTEDINDEX:
|
||||
@@ -699,183 +652,27 @@ static MenuItemHandlerResult menuhandlerFullScreen(s32 operation, struct menuite
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MenuItemHandlerResult menuhandlerFullScreenMode(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
static const char *opts[] = {
|
||||
"Borderless",
|
||||
"Exclusive"
|
||||
};
|
||||
|
||||
switch (operation) {
|
||||
case MENUOP_GETOPTIONCOUNT:
|
||||
data->dropdown.value = ARRAYCOUNT(opts);
|
||||
break;
|
||||
case MENUOP_GETOPTIONTEXT:
|
||||
return (intptr_t)opts[data->dropdown.value];
|
||||
case MENUOP_SET:
|
||||
videoSetFullscreenMode(data->dropdown.value);
|
||||
break;
|
||||
case MENUOP_GETSELECTEDINDEX:
|
||||
data->dropdown.value = videoGetFullscreenMode();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MenuItemHandlerResult menuhandlerCenterWindow(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
static MenuItemHandlerResult menuhandlerMaximizeWindow(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
switch (operation) {
|
||||
case MENUOP_GET:
|
||||
return videoGetCenterWindow();
|
||||
return videoGetMaximizeWindow();
|
||||
case MENUOP_SET:
|
||||
videoSetCenterWindow(data->checkbox.value);
|
||||
videoSetMaximizeWindow(data->checkbox.value);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MenuItemHandlerResult menuhandlerVsync(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
static const s32 numOpts = 10;
|
||||
static const char *constOpts[] = {
|
||||
"Adaptive",
|
||||
"Off",
|
||||
"On"
|
||||
};
|
||||
static char dynOpt[20];
|
||||
s32 vblanks;
|
||||
|
||||
switch (operation) {
|
||||
case MENUOP_GETOPTIONCOUNT:
|
||||
data->dropdown.value = numOpts;
|
||||
break;
|
||||
case MENUOP_GETOPTIONTEXT:
|
||||
if (data->dropdown.value < ARRAYCOUNT(constOpts))
|
||||
return (intptr_t)constOpts[data->dropdown.value];
|
||||
vblanks = (s32)data->dropdown.value - 1;
|
||||
snprintf(dynOpt, sizeof(dynOpt), "On (%d frames)", vblanks);
|
||||
return (intptr_t)dynOpt;
|
||||
case MENUOP_SET:
|
||||
videoSetVsync(data->dropdown.value - 1);
|
||||
case MENUOP_GETSELECTEDINDEX:
|
||||
data->dropdown.value = videoGetVsync() + 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MenuItemHandlerResult menuhandlerFramerateLimit(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
switch (operation) {
|
||||
case MENUOP_GETSLIDER:
|
||||
data->slider.value = videoGetFramerateLimit();
|
||||
break;
|
||||
case MENUOP_SET:
|
||||
videoSetFramerateLimit(data->slider.value);
|
||||
break;
|
||||
case MENUOP_GETSLIDERLABEL:
|
||||
// NOTE: data->slider.label length must not exceed 15.
|
||||
if (data->slider.value == 0) {
|
||||
strcpy(data->slider.label, "Off");
|
||||
} else {
|
||||
sprintf(data->slider.label, "%d FPS", data->slider.value);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MenuItemHandlerResult menuhandlerMSAA(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
s32 msaa;
|
||||
static const char *opts[] = {
|
||||
"Off",
|
||||
"2x (MSAA)",
|
||||
"4x (MSAA)",
|
||||
"8x (MSAA)",
|
||||
"16x (MSAA)"
|
||||
};
|
||||
|
||||
switch (operation) {
|
||||
case MENUOP_GETOPTIONCOUNT:
|
||||
data->dropdown.value = ARRAYCOUNT(opts);
|
||||
break;
|
||||
case MENUOP_GETOPTIONTEXT:
|
||||
return (intptr_t)opts[data->dropdown.value];
|
||||
case MENUOP_SET:
|
||||
videoSetMSAA(1 << data->dropdown.value);
|
||||
break;
|
||||
case MENUOP_GETSELECTEDINDEX:
|
||||
msaa = videoGetMSAA();
|
||||
if (msaa < 2) {
|
||||
data->dropdown.value = 0;
|
||||
} else if (msaa < 4) {
|
||||
data->dropdown.value = 1;
|
||||
} else if (msaa < 8) {
|
||||
data->dropdown.value = 2;
|
||||
} else if (msaa < 16) {
|
||||
data->dropdown.value = 3;
|
||||
} else {
|
||||
data->dropdown.value = 4;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MenuItemHandlerResult menuhandlerResolution(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
static char resstring[32];
|
||||
static const char *rescustom = "Custom";
|
||||
displaymode mode;
|
||||
|
||||
switch (operation) {
|
||||
case MENUOP_CHECKDISABLED:
|
||||
if (videoGetFullscreen() && videoGetFullscreenMode() == 0) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case MENUOP_GETOPTIONCOUNT:
|
||||
data->dropdown.value = videoGetNumDisplayModes();
|
||||
break;
|
||||
case MENUOP_GETOPTIONTEXT:
|
||||
videoGetDisplayMode(&mode, data->dropdown.value);
|
||||
if (mode.width == 0 && mode.height == 0) {
|
||||
return (intptr_t)rescustom;
|
||||
} else {
|
||||
snprintf(resstring, sizeof(resstring), "%dx%d", mode.width, mode.height);
|
||||
}
|
||||
return (intptr_t)resstring;
|
||||
case MENUOP_SET:
|
||||
videoSetDisplayMode(data->dropdown.value);
|
||||
break;
|
||||
case MENUOP_GETSELECTEDINDEX:
|
||||
data->dropdown.value = videoGetDisplayModeIndex();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MenuItemHandlerResult menuhandlerTexFilter(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
static const char *opts[] = {
|
||||
"Nearest",
|
||||
"Bilinear",
|
||||
"Three Point"
|
||||
};
|
||||
|
||||
switch (operation) {
|
||||
case MENUOP_GETOPTIONCOUNT:
|
||||
data->dropdown.value = ARRAYCOUNT(opts);
|
||||
break;
|
||||
case MENUOP_GETOPTIONTEXT:
|
||||
return (intptr_t)opts[data->dropdown.value];
|
||||
case MENUOP_GET:
|
||||
return (videoGetTextureFilter() != 0);
|
||||
case MENUOP_SET:
|
||||
videoSetTextureFilter(data->dropdown.value);
|
||||
videoSetTextureFilter(data->checkbox.value);
|
||||
break;
|
||||
case MENUOP_GETSELECTEDINDEX:
|
||||
data->dropdown.value = videoGetTextureFilter();
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -901,39 +698,12 @@ static MenuItemHandlerResult menuhandlerTexFilter2D(s32 operation, struct menuit
|
||||
return videoGetTextureFilter2D();
|
||||
case MENUOP_SET:
|
||||
videoSetTextureFilter2D(data->checkbox.value);
|
||||
g_TexFilter2D = videoGetTextureFilter2D() ? G_TF_BILERP : G_TF_POINT;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MenuItemHandlerResult menuhandlerAnisotropicFiltering(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
switch (operation) {
|
||||
case MENUOP_GETSLIDER:
|
||||
data->slider.value = videoGetAnisotropicFilter();
|
||||
break;
|
||||
case MENUOP_SET:
|
||||
videoSetAnisotropicFilter(data->slider.value);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MenuItemHandlerResult menuhandlerDisplayFPS(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
switch (operation) {
|
||||
case MENUOP_GET:
|
||||
return videoGetDisplayFPS();
|
||||
case MENUOP_SET:
|
||||
videoSetDisplayFPS(data->checkbox.value);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MenuItemHandlerResult menuhandlerGeMuzzleFlashes(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
switch (operation) {
|
||||
@@ -947,19 +717,6 @@ static MenuItemHandlerResult menuhandlerGeMuzzleFlashes(s32 operation, struct me
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MenuItemHandlerResult menuhandlerUncapTickrate(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
switch (operation) {
|
||||
case MENUOP_GET:
|
||||
return (g_TickRateDiv == 0);
|
||||
case MENUOP_SET:
|
||||
g_TickRateDiv = !data->checkbox.value;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MenuItemHandlerResult menuhandlerCenterHUD(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
static const char *opts[] = {
|
||||
@@ -1008,34 +765,6 @@ static MenuItemHandlerResult menuhandlerScreenShake(s32 operation, struct menuit
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MenuItemHandlerResult menuhandlerGlareBrightness(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
switch (operation) {
|
||||
case MENUOP_GETSLIDER:
|
||||
data->slider.value = videoGetGlareBrightness() * 10.f + 0.5f;
|
||||
break;
|
||||
case MENUOP_SET:
|
||||
videoSetGlareBrightness((f32)data->slider.value / 10.f);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MenuItemHandlerResult menuhandlerOverexposureScale(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
switch (operation) {
|
||||
case MENUOP_GETSLIDER:
|
||||
data->slider.value = videoGetOverexposureScale() * 10.f + 0.5f;
|
||||
break;
|
||||
case MENUOP_SET:
|
||||
videoSetOverexposureScale((f32)data->slider.value / 10.f);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct menuitem g_ExtendedVideoMenuItems[] = {
|
||||
{
|
||||
MENUITEMTYPE_CHECKBOX,
|
||||
@@ -1046,89 +775,25 @@ struct menuitem g_ExtendedVideoMenuItems[] = {
|
||||
menuhandlerFullScreen,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_DROPDOWN,
|
||||
MENUITEMTYPE_CHECKBOX,
|
||||
0,
|
||||
MENUITEMFLAG_LITERAL_TEXT,
|
||||
(uintptr_t)"Full Screen Mode",
|
||||
(uintptr_t)"Maximize Window",
|
||||
0,
|
||||
menuhandlerFullScreenMode,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_DROPDOWN,
|
||||
0,
|
||||
MENUITEMFLAG_LITERAL_TEXT,
|
||||
(uintptr_t)"Resolution",
|
||||
0,
|
||||
menuhandlerResolution,
|
||||
menuhandlerMaximizeWindow,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_CHECKBOX,
|
||||
0,
|
||||
MENUITEMFLAG_LITERAL_TEXT,
|
||||
(uintptr_t)"Center Window",
|
||||
(uintptr_t)"Detail Textures",
|
||||
0,
|
||||
menuhandlerCenterWindow,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_DROPDOWN,
|
||||
0,
|
||||
MENUITEMFLAG_LITERAL_TEXT,
|
||||
(uintptr_t)"Anti-aliasing",
|
||||
0,
|
||||
menuhandlerMSAA,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SEPARATOR,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_DROPDOWN,
|
||||
0,
|
||||
MENUITEMFLAG_LITERAL_TEXT,
|
||||
(uintptr_t)"Vsync",
|
||||
0,
|
||||
menuhandlerVsync,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SLIDER,
|
||||
0,
|
||||
MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SLIDER_WIDE | MENUITEMFLAG_SLIDER_DEFERRED,
|
||||
(uintptr_t)"Framerate Limit",
|
||||
VIDEO_MAX_FPS,
|
||||
menuhandlerFramerateLimit,
|
||||
menuhandlerTexDetail,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_CHECKBOX,
|
||||
0,
|
||||
MENUITEMFLAG_LITERAL_TEXT,
|
||||
(uintptr_t)"Uncap Tickrate",
|
||||
0,
|
||||
menuhandlerUncapTickrate,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_CHECKBOX,
|
||||
0,
|
||||
MENUITEMFLAG_LITERAL_TEXT,
|
||||
(uintptr_t)"Display FPS",
|
||||
0,
|
||||
menuhandlerDisplayFPS,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SEPARATOR,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_DROPDOWN,
|
||||
0,
|
||||
MENUITEMFLAG_LITERAL_TEXT,
|
||||
(uintptr_t)"Texture Filtering",
|
||||
0,
|
||||
menuhandlerTexFilter,
|
||||
@@ -1141,29 +806,13 @@ struct menuitem g_ExtendedVideoMenuItems[] = {
|
||||
0,
|
||||
menuhandlerTexFilter2D,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SLIDER,
|
||||
0,
|
||||
MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SLIDER_WIDE,
|
||||
(uintptr_t)"Anisotropic Filtering",
|
||||
8,
|
||||
menuhandlerAnisotropicFiltering,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_CHECKBOX,
|
||||
0,
|
||||
MENUITEMFLAG_LITERAL_TEXT,
|
||||
(uintptr_t)"Detail Textures",
|
||||
(uintptr_t)"GE64-style Muzzle Flashes",
|
||||
0,
|
||||
menuhandlerTexDetail,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SEPARATOR,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
menuhandlerGeMuzzleFlashes,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_DROPDOWN,
|
||||
@@ -1173,14 +822,6 @@ struct menuitem g_ExtendedVideoMenuItems[] = {
|
||||
0,
|
||||
menuhandlerCenterHUD,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_CHECKBOX,
|
||||
0,
|
||||
MENUITEMFLAG_LITERAL_TEXT,
|
||||
(uintptr_t)"GE64-style Muzzle Flashes",
|
||||
0,
|
||||
menuhandlerGeMuzzleFlashes,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SLIDER,
|
||||
0,
|
||||
@@ -1197,30 +838,6 @@ struct menuitem g_ExtendedVideoMenuItems[] = {
|
||||
0,
|
||||
NULL,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SLIDER,
|
||||
0,
|
||||
MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SLIDER_WIDE,
|
||||
(uintptr_t)"Glare Brightness",
|
||||
10,
|
||||
menuhandlerGlareBrightness,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SLIDER,
|
||||
0,
|
||||
MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SLIDER_WIDE,
|
||||
(uintptr_t)"Overexposure Scale",
|
||||
10,
|
||||
menuhandlerOverexposureScale,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SEPARATOR,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SELECTABLE,
|
||||
0,
|
||||
@@ -1291,21 +908,6 @@ struct menudialogdef g_ExtendedAudioMenuDialog = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
static MenuItemHandlerResult menuhandlerUseKeyReloads(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
switch (operation) {
|
||||
case MENUOP_CHECKDISABLED:
|
||||
return !g_PlayerExtCfg[g_ExtMenuPlayer].extcontrols;
|
||||
case MENUOP_GET:
|
||||
return g_PlayerExtCfg[g_ExtMenuPlayer].usereloads;
|
||||
case MENUOP_SET:
|
||||
g_PlayerExtCfg[g_ExtMenuPlayer].usereloads = data->checkbox.value;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MenuItemHandlerResult menuhandlerCrouchMode(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
static const char *opts[] = {
|
||||
@@ -1342,7 +944,6 @@ static MenuItemHandlerResult menuhandlerFieldOfView(s32 operation, struct menuit
|
||||
g_PlayerExtCfg[g_ExtMenuPlayer].fovy = data->slider.value;
|
||||
if (g_PlayerExtCfg[g_ExtMenuPlayer].fovzoom) {
|
||||
g_PlayerExtCfg[g_ExtMenuPlayer].fovzoommult = g_PlayerExtCfg[g_ExtMenuPlayer].fovy / 60.f;
|
||||
playerClampGunZoomFovY(g_ExtMenuPlayer);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1365,22 +966,6 @@ static MenuItemHandlerResult menuhandlerCrosshairSway(s32 operation, struct menu
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MenuItemHandlerResult menuhandlerCrosshairEdgeBoundary(s32 operation, struct menuitem* item, union handlerdata *data)
|
||||
{
|
||||
switch (operation) {
|
||||
case MENUOP_GETSLIDER:
|
||||
data->slider.value = (s32)(g_PlayerExtCfg[g_ExtMenuPlayer].crosshairedgeboundary * 10.f + 0.5f);
|
||||
break;
|
||||
case MENUOP_SET:
|
||||
g_PlayerExtCfg[g_ExtMenuPlayer].crosshairedgeboundary = (f32)data->slider.value / 10.f;
|
||||
break;
|
||||
case MENUOP_GETSLIDERLABEL:
|
||||
sprintf(data->slider.label, "%d", (s32)data->slider.value);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MenuItemHandlerResult menuhandlerCrosshairR(s32 operation, struct menuitem* item, union handlerdata* data)
|
||||
{
|
||||
u32 newColor;
|
||||
@@ -1602,14 +1187,6 @@ struct menuitem g_ExtendedGameMenuItems[] = {
|
||||
20,
|
||||
menuhandlerCrosshairSway,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SLIDER,
|
||||
0,
|
||||
MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SLIDER_WIDE,
|
||||
(uintptr_t)"Crosshair Edge Deadzone",
|
||||
10,
|
||||
menuhandlerCrosshairEdgeBoundary,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SLIDER,
|
||||
0,
|
||||
@@ -1634,14 +1211,6 @@ struct menuitem g_ExtendedGameMenuItems[] = {
|
||||
0,
|
||||
menuhandlerCrosshairHealth,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_CHECKBOX,
|
||||
0,
|
||||
MENUITEMFLAG_LITERAL_TEXT,
|
||||
(uintptr_t)"Use Key Reloads",
|
||||
0,
|
||||
menuhandlerUseKeyReloads,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SEPARATOR,
|
||||
0,
|
||||
@@ -1744,8 +1313,6 @@ static const struct menubind menuBinds[] = {
|
||||
{ CK_8000, "Cycle Crouch [+]\n", "N64 Ext 8000\n" },
|
||||
{ CK_4000, "Half Crouch [+]\n", "N64 Ext 4000\n" },
|
||||
{ CK_2000, "Full Crouch [+]\n", "N64 Ext 2000\n" },
|
||||
{ CK_ACCEPT, "UI Accept [+]\n", "EXT UI Accept\n" },
|
||||
{ CK_CANCEL, "UI Cancel [+]\n", "EXT UI Cancel\n" },
|
||||
};
|
||||
|
||||
static const char *menutextBind(struct menuitem *item);
|
||||
@@ -1783,8 +1350,6 @@ struct menuitem g_ExtendedBindsMenuItems[] = {
|
||||
DEFINE_MENU_BIND(),
|
||||
DEFINE_MENU_BIND(),
|
||||
DEFINE_MENU_BIND(),
|
||||
DEFINE_MENU_BIND(),
|
||||
DEFINE_MENU_BIND(),
|
||||
{
|
||||
MENUITEMTYPE_SEPARATOR,
|
||||
0,
|
||||
@@ -2021,22 +1586,3 @@ struct menudialogdef g_ExtendedMenuDialog = {
|
||||
MENUDIALOGFLAG_LITERAL_TEXT,
|
||||
NULL,
|
||||
};
|
||||
|
||||
void updateMaxAnisotropyLevel()
|
||||
{
|
||||
for (int i = 0; i < ARRAYCOUNT(g_ExtendedVideoMenuItems); ++i) {
|
||||
struct menuitem *item = &g_ExtendedVideoMenuItems[i];
|
||||
const char *text = menuResolveParam2Text(item);
|
||||
|
||||
if (text && strstr(text, "Anisotropic Filtering") != NULL) {
|
||||
item->param3 = videoGetMaxAnisotropyLevel();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void optionsMenuInit()
|
||||
{
|
||||
updateMaxAnisotropyLevel();
|
||||
}
|
||||
+25
-19
@@ -73,6 +73,9 @@
|
||||
#include "data.h"
|
||||
#include "types.h"
|
||||
#include "system.h"
|
||||
#include "console.h"
|
||||
#include "net/net.h"
|
||||
#include "net/netmsg.h"
|
||||
|
||||
extern u8 *g_MempHeap;
|
||||
extern u32 g_MempHeapSize;
|
||||
@@ -225,8 +228,6 @@ void mainInit(void)
|
||||
joyInit();
|
||||
joyReset();
|
||||
|
||||
var8005d9b0 = rmonIsDisabled();
|
||||
|
||||
g_Is4Mb = (osGetMemSize() <= 0x400000);
|
||||
g_VmShowStats = 0;
|
||||
|
||||
@@ -259,7 +260,7 @@ void mainInit(void)
|
||||
frametimeInit();
|
||||
profileInit();
|
||||
smokesInit();
|
||||
mpInit(true);
|
||||
mpInit();
|
||||
pheadInit();
|
||||
paksInit();
|
||||
pheadInit2();
|
||||
@@ -421,6 +422,9 @@ void mainLoop(void)
|
||||
|
||||
if (argFindByPrefix(1, "-ma")) {
|
||||
g_MainMemaHeapSize = strtol(argFindByPrefix(1, "-ma"), NULL, 0) * 1024;
|
||||
if (g_NetMode && g_NetMaxClients > MAX_LOCAL_PLAYERS) {
|
||||
g_MainMemaHeapSize *= MAX_PLAYERS / MAX_LOCAL_PLAYERS;
|
||||
}
|
||||
}
|
||||
|
||||
memaReset(mempAlloc(g_MainMemaHeapSize, MEMPOOL_STAGE), g_MainMemaHeapSize);
|
||||
@@ -462,10 +466,15 @@ void mainLoop(void)
|
||||
}
|
||||
|
||||
if (g_Vars.coopplayernum >= 0 || g_Vars.antiplayernum >= 0) {
|
||||
if (g_MpSetup.chrslots & 0xfff0) {
|
||||
g_MpSetup.storedbotbits = g_MpSetup.chrslots & 0xfff0;
|
||||
}
|
||||
#ifdef PLATFORM_N64
|
||||
g_MpSetup.chrslots = 0x03;
|
||||
#else
|
||||
if (g_Vars.antiplayernum < 0) {
|
||||
// Counter-Operative now uses a different approach which allows more than 2 players.
|
||||
// Co-Operative, on the other hand, is currently limited to 2 players.
|
||||
g_MpSetup.chrslots = 0x03;
|
||||
}
|
||||
#endif
|
||||
mpReset();
|
||||
} else if (g_Vars.perfectbuddynum) {
|
||||
mpReset();
|
||||
@@ -473,16 +482,8 @@ void mainLoop(void)
|
||||
&& (numplayers >= 2 || g_Vars.lvmpbotlevel || argFindByPrefix(1, "-play"))) {
|
||||
g_MpSetup.chrslots = 1;
|
||||
|
||||
if (numplayers >= 2) {
|
||||
g_MpSetup.chrslots |= 1 << 1;
|
||||
}
|
||||
|
||||
if (numplayers >= 3) {
|
||||
g_MpSetup.chrslots |= 1 << 2;
|
||||
}
|
||||
|
||||
if (numplayers >= 4) {
|
||||
g_MpSetup.chrslots |= 1 << 3;
|
||||
for (s32 i = 1; i < numplayers; ++i) {
|
||||
g_MpSetup.chrslots |= 1 << i;
|
||||
}
|
||||
|
||||
g_MpSetup.stagenum = g_StageNum;
|
||||
@@ -566,6 +567,9 @@ void mainTick(void)
|
||||
gdl = profileRender(gdl);
|
||||
}
|
||||
|
||||
gdl = conRender(gdl);
|
||||
gdl = netDebugRender(gdl);
|
||||
|
||||
gDPFullSync(gdl++);
|
||||
gSPEndDisplayList(gdl++);
|
||||
}
|
||||
@@ -575,7 +579,7 @@ void mainTick(void)
|
||||
viUpdateMode();
|
||||
}
|
||||
|
||||
rdpCreateTask(gdlstart, gdl, 0, (uintptr_t) &msg);
|
||||
rdpCreateTask(gdlstart, gdl, 0, (s32) &msg);
|
||||
memaPrint();
|
||||
profileSetMarker(PROFILE_MAINTICK_END);
|
||||
}
|
||||
@@ -593,7 +597,7 @@ void mainEndStage(void)
|
||||
s32 prevplayernum = g_Vars.currentplayernum;
|
||||
s32 i;
|
||||
|
||||
for (i = 0; i < PLAYERCOUNT(); i++) {
|
||||
for (i = 0; i < LOCALPLAYERCOUNT(); i++) {
|
||||
setCurrentPlayerNum(i);
|
||||
endscreenPushCoop();
|
||||
}
|
||||
@@ -604,7 +608,7 @@ void mainEndStage(void)
|
||||
s32 prevplayernum = g_Vars.currentplayernum;
|
||||
s32 i;
|
||||
|
||||
for (i = 0; i < PLAYERCOUNT(); i++) {
|
||||
for (i = 0; i < LOCALPLAYERCOUNT(); i++) {
|
||||
setCurrentPlayerNum(i);
|
||||
endscreenPushAnti();
|
||||
}
|
||||
@@ -617,6 +621,8 @@ void mainEndStage(void)
|
||||
endscreenPrepare();
|
||||
musicStartMenu();
|
||||
}
|
||||
|
||||
netServerStageEnd();
|
||||
}
|
||||
|
||||
g_MainIsEndscreen = true;
|
||||
|
||||
@@ -24,7 +24,9 @@
|
||||
#include "video.h"
|
||||
#include "audio.h"
|
||||
#include "input.h"
|
||||
#include "console.h"
|
||||
#include "mixer.h"
|
||||
#include "net/net.h"
|
||||
|
||||
/*
|
||||
* private typedefs and defines
|
||||
@@ -240,6 +242,14 @@ void schedSubmitTask(OSSched *sc, OSScTask *t)
|
||||
void schedStartFrame(OSSched *sc)
|
||||
{
|
||||
videoStartFrame();
|
||||
if (g_Vars.diffframe60) {
|
||||
if (g_NetMode) {
|
||||
videoCapFramerate(120);
|
||||
netStartFrame();
|
||||
} else {
|
||||
videoCapFramerate(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void schedAudioFrame(OSSched *sc)
|
||||
@@ -270,6 +280,8 @@ void schedAudioFrame(OSSched *sc)
|
||||
*/
|
||||
void schedEndFrame(OSSched *sc)
|
||||
{
|
||||
static bool netDebugKey = false;
|
||||
|
||||
sc->frameCount++;
|
||||
|
||||
#if PAL
|
||||
@@ -289,11 +301,22 @@ void schedEndFrame(OSSched *sc)
|
||||
}
|
||||
|
||||
inputUpdate();
|
||||
conTick();
|
||||
|
||||
const bool newKey = inputKeyPressed(VK_F9);
|
||||
if (!netDebugKey && newKey) {
|
||||
g_NetDebugDraw = !g_NetDebugDraw;
|
||||
}
|
||||
netDebugKey = newKey;
|
||||
|
||||
joyStartReadData(&g_PiMesgQueue);
|
||||
joyReadData();
|
||||
joy00014238();
|
||||
|
||||
if (g_Vars.diffframe60) {
|
||||
netEndFrame();
|
||||
}
|
||||
|
||||
sndHandleRetrace();
|
||||
schedAudioFrame(sc);
|
||||
schedRenderCrashPeriodically(sc->frameCount);
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,31 +0,0 @@
|
||||
#include "preprocess/common.h"
|
||||
|
||||
static struct ptrmarker ptrMarkers[MAX_PTR_MARKERS];
|
||||
static int numPtrMarkers;
|
||||
|
||||
void ptrAdd(u32 ptr_src, uintptr_t ptr_host)
|
||||
{
|
||||
if (numPtrMarkers >= ARRAYCOUNT(ptrMarkers)) {
|
||||
sysFatalError("ptrAdd(%p, %p): ptrmarker limit exceeded", (void *)(uintptr_t)ptr_src, (void *)ptr_host);
|
||||
}
|
||||
|
||||
ptrMarkers[numPtrMarkers].ptr_src = ptr_src;
|
||||
ptrMarkers[numPtrMarkers].ptr_host = ptr_host;
|
||||
numPtrMarkers++;
|
||||
}
|
||||
|
||||
struct ptrmarker *ptrFind(uintptr_t ptr_src)
|
||||
{
|
||||
for (int i = 0; i < numPtrMarkers; i++) {
|
||||
if (ptrMarkers[i].ptr_src == ptr_src) {
|
||||
return &ptrMarkers[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ptrReset(void)
|
||||
{
|
||||
numPtrMarkers = 0;
|
||||
}
|
||||
@@ -1,524 +0,0 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "data.h"
|
||||
#include "bss.h"
|
||||
|
||||
#include "preprocess/common.h"
|
||||
#include "preprocess/gbi.h"
|
||||
|
||||
/**
|
||||
* 4 bytes decompressed size of primary data
|
||||
* 4 bytes compressed size of section 1 in its entirety
|
||||
* 4 bytes compressed size of primary data
|
||||
* Section 1:
|
||||
* Primary: (zipped)
|
||||
* 4 bytes null
|
||||
* 4 bytes pointer to room table
|
||||
* 4 bytes pointer to portal table
|
||||
* 4 bytes pointer to bgcmds
|
||||
* 4 bytes pointer to lights table
|
||||
* 4 bytes null
|
||||
* (room table)
|
||||
* (portal table)
|
||||
* (bgcmds)
|
||||
* (lights table)
|
||||
* room 1 (zipped)
|
||||
* room 2 (zipped)
|
||||
* ...
|
||||
* Section 2:
|
||||
* 2 bytes decompressed size of section (mask with 0x7fff)
|
||||
* 2 bytes compressed size of section
|
||||
* Texture ID list (zipped)
|
||||
* Section 3:
|
||||
* 2 bytes decompressed size of section (mask with 0x7fff)
|
||||
* 2 bytes compressed size of section
|
||||
* Zipped:
|
||||
* (room bbox table)
|
||||
* (list of roomgfxdata sizes)
|
||||
* (list of light counts per room)
|
||||
*/
|
||||
|
||||
struct fileheader {
|
||||
u32 primary_infsize;
|
||||
u32 section1_cmpsize;
|
||||
u32 primary_cmpsize;
|
||||
};
|
||||
|
||||
struct sectionheader {
|
||||
u16 infsize;
|
||||
u16 cmpsize;
|
||||
};
|
||||
|
||||
struct n64_primaryheader {
|
||||
u32 unused1;
|
||||
u32 ptr_rooms;
|
||||
u32 ptr_portals;
|
||||
u32 ptr_bgcmds;
|
||||
u32 ptr_lights;
|
||||
u32 unused2;
|
||||
};
|
||||
|
||||
struct host_primaryheader {
|
||||
uintptr_t unused1;
|
||||
uintptr_t ptr_rooms;
|
||||
uintptr_t ptr_portals;
|
||||
uintptr_t ptr_bgcmds;
|
||||
uintptr_t ptr_lights;
|
||||
uintptr_t unused2;
|
||||
};
|
||||
|
||||
struct n64_bgroom {
|
||||
u32 ptr_gfxdata;
|
||||
struct coord pos;
|
||||
u8 br_light_min;
|
||||
u8 br_light_max;
|
||||
};
|
||||
|
||||
struct n64_roomblock {
|
||||
u8 type;
|
||||
u32 ptr_next;
|
||||
u32 ptr_gdl;
|
||||
u32 ptr_vertices;
|
||||
u32 ptr_colours;
|
||||
};
|
||||
|
||||
struct n64_roomgfxdata {
|
||||
u32 ptr_vertices;
|
||||
u32 ptr_colours;
|
||||
u32 ptr_opablocks;
|
||||
u32 ptr_xlublocks;
|
||||
s16 lightsindex;
|
||||
s16 numlights;
|
||||
s16 numvertices;
|
||||
s16 numcolours;
|
||||
// roomblocks[]
|
||||
};
|
||||
|
||||
struct vtx {
|
||||
s16 coord[3];
|
||||
u8 flag;
|
||||
u8 color;
|
||||
u16 s;
|
||||
u16 t;
|
||||
};
|
||||
|
||||
static void convertPrimaryRooms(u8 *dst, u32 *dstpos, u8 *src, u32 *srcpos)
|
||||
{
|
||||
struct n64_bgroom *n64_rooms = (struct n64_bgroom *) &src[*srcpos];
|
||||
struct bgroom *host_rooms = (struct bgroom *) &dst[*dstpos];
|
||||
|
||||
s32 numRooms = 0;
|
||||
|
||||
for (int i = 1; n64_rooms[i].ptr_gfxdata != 0; i++) {
|
||||
numRooms++;
|
||||
}
|
||||
|
||||
for (int i = 0; i < numRooms + 1; i++) {
|
||||
host_rooms[i].unk00 = PD_BE32(n64_rooms[i].ptr_gfxdata);
|
||||
host_rooms[i].pos = PD_SWAPPED_VAL(n64_rooms[i].pos);
|
||||
host_rooms[i].br_light_min = n64_rooms[i].br_light_min;
|
||||
host_rooms[i].br_light_max = n64_rooms[i].br_light_max;
|
||||
}
|
||||
|
||||
*srcpos += sizeof(*n64_rooms) * (numRooms + 2);
|
||||
*dstpos += sizeof(*host_rooms) * (numRooms +2);
|
||||
}
|
||||
|
||||
static void convertPrimaryPortals(u8 *dst, u32 *dstpos, u8 *src, u32 *srcpos, u32 *src_portalvtxs, u32 *dst_portalvtxs)
|
||||
{
|
||||
struct bgportal *n64_portals = (struct bgportal *) &src[*srcpos];
|
||||
struct bgportal *host_portals = (struct bgportal *) &dst[*dstpos];
|
||||
|
||||
// Count portals
|
||||
int numportals = 0;
|
||||
|
||||
for (int i = 0; n64_portals[i].verticesoffset != 0; i++) {
|
||||
numportals++;
|
||||
}
|
||||
|
||||
// Convert portals
|
||||
for (int i = 0; i < numportals; i++) {
|
||||
host_portals[i].verticesoffset = PD_BE16(n64_portals[i].verticesoffset);
|
||||
host_portals[i].roomnum1 = PD_BE16(n64_portals[i].roomnum1);
|
||||
host_portals[i].roomnum2 = PD_BE16(n64_portals[i].roomnum2);
|
||||
host_portals[i].flags = n64_portals[i].flags;
|
||||
}
|
||||
|
||||
*srcpos += sizeof(*n64_portals) * (numportals + 1);
|
||||
*dstpos += sizeof(*host_portals) * (numportals + 1);
|
||||
|
||||
*src_portalvtxs = *srcpos;
|
||||
*dst_portalvtxs = *dstpos;
|
||||
|
||||
while (1) {
|
||||
struct portalvertices *n64_pvertices = (struct portalvertices *)&src[*srcpos];
|
||||
struct portalvertices *host_pvertices = (struct portalvertices *)&dst[*dstpos];
|
||||
|
||||
host_pvertices->count = n64_pvertices->count;
|
||||
|
||||
for (int j = 0; j < host_pvertices->count; j++) {
|
||||
host_pvertices->vertices[j] = PD_SWAPPED_VAL(n64_pvertices->vertices[j]);
|
||||
}
|
||||
|
||||
*srcpos += 4 + host_pvertices->count * 12;
|
||||
*dstpos += 4 + host_pvertices->count * 12;
|
||||
|
||||
if (host_pvertices->count == 0) break;
|
||||
}
|
||||
}
|
||||
|
||||
static void convertPrimaryBgCmds(u8 *dst, u32 *dstpos, u8 *src, u32 dst_portalvtxs, u32 src_portalvtxs)
|
||||
{
|
||||
struct bgcmd *n64_cmds = (struct bgcmd *) src;
|
||||
struct bgcmd *host_cmds = (struct bgcmd *) &dst[*dstpos];
|
||||
int num_cmds = 0;
|
||||
|
||||
for (int i = 0; n64_cmds[i].type != 0; i++) {
|
||||
num_cmds++;
|
||||
}
|
||||
|
||||
num_cmds++;
|
||||
|
||||
for (int i = 0; i < num_cmds; i++) {
|
||||
host_cmds[i].type = n64_cmds[i].type;
|
||||
host_cmds[i].len = n64_cmds[i].len;
|
||||
host_cmds[i].param = PD_BE32(n64_cmds[i].param);
|
||||
|
||||
if (host_cmds[i].type == 0x64) {
|
||||
u32 offset = host_cmds[i].param - src_portalvtxs;
|
||||
host_cmds[i].param = dst_portalvtxs + offset;
|
||||
}
|
||||
}
|
||||
|
||||
*dstpos += sizeof(*host_cmds) * num_cmds;
|
||||
}
|
||||
|
||||
static void convertPrimaryLights(u8 *dst, u32 *dstpos, u8 *src, u32 *srcpos, u32 end)
|
||||
{
|
||||
struct light *n64_lights = (struct light *) &src[*srcpos];
|
||||
struct light *host_lights = (struct light *) &dst[*dstpos];
|
||||
int num_lights = (end - *srcpos) / sizeof(struct light);
|
||||
|
||||
for (int i = 0; i < num_lights; i++) {
|
||||
host_lights[i].roomnum = PD_BE16(n64_lights[i].roomnum);
|
||||
host_lights[i].colour = PD_BE16(n64_lights[i].colour);
|
||||
host_lights[i].brightness = n64_lights[i].brightness;
|
||||
host_lights[i].sparkable = n64_lights[i].sparkable;
|
||||
host_lights[i].healthy = n64_lights[i].healthy;
|
||||
host_lights[i].on = n64_lights[i].on;
|
||||
host_lights[i].sparking = n64_lights[i].sparking;
|
||||
host_lights[i].vulnerable = n64_lights[i].vulnerable;
|
||||
host_lights[i].brightnessmult = n64_lights[i].brightnessmult;
|
||||
host_lights[i].dirx = n64_lights[i].dirx;
|
||||
host_lights[i].diry = n64_lights[i].diry;
|
||||
host_lights[i].dirz = n64_lights[i].dirz;
|
||||
|
||||
for (int j = 0; j < 4; j++) {
|
||||
host_lights[i].bbox[j].x = PD_BE16(n64_lights[i].bbox[j].x);
|
||||
host_lights[i].bbox[j].y = PD_BE16(n64_lights[i].bbox[j].y);
|
||||
host_lights[i].bbox[j].z = PD_BE16(n64_lights[i].bbox[j].z);
|
||||
}
|
||||
}
|
||||
|
||||
*srcpos += sizeof(*n64_lights) * num_lights;
|
||||
*dstpos += ALIGN(sizeof(*host_lights) * num_lights, 4);
|
||||
}
|
||||
|
||||
#define BLOCK_LEAF 0
|
||||
#define BLOCK_PARENT 1
|
||||
|
||||
void relinkPtr(uintptr_t* ptr)
|
||||
{
|
||||
if (!*ptr) return;
|
||||
|
||||
struct ptrmarker* marker = ptrFind(*ptr);
|
||||
if (!marker) {
|
||||
sysFatalError("[BG] WARNING: Unable to relink pointer: %p\n", ptr);
|
||||
}
|
||||
|
||||
*ptr = marker->ptr_host;
|
||||
}
|
||||
|
||||
static u32 convertRoomGfxData(u8 *dst, u8 *src, u32 infsize, u32 src_ofs)
|
||||
{
|
||||
ptrReset();
|
||||
gbiReset();
|
||||
|
||||
u32 dst_roomoffset = src_ofs;
|
||||
|
||||
uintptr_t gdls_addr[64];
|
||||
int numgdls = 0;
|
||||
|
||||
struct n64_roomgfxdata *src_header = (struct n64_roomgfxdata*)src;
|
||||
struct roomgfxdata *dst_header = (struct roomgfxdata*)dst;
|
||||
|
||||
dst_header->vertices = (void *)(uintptr_t)PD_BE32(src_header->ptr_vertices);
|
||||
dst_header->colours = (void *)(uintptr_t)PD_BE32(src_header->ptr_colours);
|
||||
dst_header->opablocks = (void *)(uintptr_t)PD_BE32(src_header->ptr_opablocks);
|
||||
dst_header->xlublocks = (void *)(uintptr_t)PD_BE32(src_header->ptr_xlublocks);
|
||||
dst_header->lightsindex = PD_BE16(src_header->lightsindex);
|
||||
dst_header->numlights = PD_BE16(src_header->numlights);
|
||||
dst_header->numvertices = PD_BE16(src_header->numvertices);
|
||||
dst_header->numcolours = PD_BE16(src_header->numcolours);
|
||||
|
||||
intptr_t endpos = (uintptr_t)dst_header->vertices - src_ofs;
|
||||
uintptr_t curpos_src = sizeof(struct n64_roomgfxdata);
|
||||
uintptr_t curpos_dst = sizeof(struct roomgfxdata) - sizeof(struct roomblock); // compensate for the [1]
|
||||
|
||||
// roomblocks
|
||||
int ncoords = 0;
|
||||
|
||||
// save the ptr to roomblocks here to iterate later to fix the pointers
|
||||
struct roomblock *ptr_dst_roomblocks = (struct roomblock*)&dst[curpos_dst];
|
||||
|
||||
int numblocks = 0;
|
||||
while ((intptr_t)(curpos_src + sizeof(struct n64_roomblock)) <= endpos) {
|
||||
struct n64_roomblock *src_roomblock = (struct n64_roomblock*)&src[curpos_src];
|
||||
struct roomblock *dest_roomblock = (struct roomblock*)&dst[curpos_dst];
|
||||
|
||||
dest_roomblock->type = src_roomblock->type;
|
||||
dest_roomblock->next = (void *)(uintptr_t)PD_BE32(src_roomblock->ptr_next);
|
||||
dest_roomblock->gdl = (void *)(uintptr_t)PD_BE32(src_roomblock->ptr_gdl);
|
||||
dest_roomblock->vertices = (void *)(uintptr_t)PD_BE32(src_roomblock->ptr_vertices);
|
||||
dest_roomblock->colours = (void *)(uintptr_t)PD_BE32(src_roomblock->ptr_colours);
|
||||
|
||||
ptrAdd(curpos_src + src_ofs, curpos_dst + dst_roomoffset);
|
||||
|
||||
if (src_roomblock->type == BLOCK_PARENT) {
|
||||
ncoords++;
|
||||
uintptr_t vtx_ptr = (uintptr_t)dest_roomblock->vertices - src_ofs;
|
||||
if (vtx_ptr < endpos) endpos = vtx_ptr;
|
||||
}
|
||||
else if (src_roomblock->ptr_gdl) {
|
||||
gdls_addr[numgdls++] = PD_BE32(src_roomblock->ptr_gdl) - src_ofs;
|
||||
}
|
||||
|
||||
curpos_src += sizeof(struct n64_roomblock);
|
||||
curpos_dst += sizeof(struct roomblock);
|
||||
numblocks++;
|
||||
}
|
||||
|
||||
// block coords
|
||||
for (size_t i = 0; i < ncoords; i++) {
|
||||
u32 *src_coord = (u32*)(src + curpos_src);
|
||||
u32 *dst_coord = (u32*)(dst + curpos_dst);
|
||||
|
||||
dst_coord[0] = PD_BE32(src_coord[0]);
|
||||
dst_coord[1] = PD_BE32(src_coord[1]);
|
||||
dst_coord[2] = PD_BE32(src_coord[2]);
|
||||
|
||||
dst_coord[3] = PD_BE32(src_coord[3]);
|
||||
dst_coord[4] = PD_BE32(src_coord[4]);
|
||||
dst_coord[5] = PD_BE32(src_coord[5]);
|
||||
|
||||
ptrAdd(curpos_src + src_ofs, curpos_dst + dst_roomoffset);
|
||||
|
||||
curpos_src += 6 * sizeof(u32);
|
||||
curpos_dst += 6 * sizeof(u32);
|
||||
}
|
||||
|
||||
curpos_dst = ALIGN8(curpos_dst);
|
||||
|
||||
// vertices
|
||||
uintptr_t ptr_src_vertices = curpos_src = ALIGN8((uintptr_t)dst_header->vertices - src_ofs);
|
||||
uintptr_t ptr_dst_vertices = curpos_dst + dst_roomoffset;
|
||||
|
||||
ptrAdd(curpos_src + src_ofs, curpos_dst + dst_roomoffset);
|
||||
|
||||
uintptr_t vtx_end = (uintptr_t)dst_header->colours - src_ofs;
|
||||
|
||||
while (dst_header->colours && curpos_src < vtx_end) {
|
||||
struct vtx *src_vtx = (struct vtx*)(src + curpos_src);
|
||||
struct vtx *dst_vtx = (struct vtx*)(dst + curpos_dst);
|
||||
|
||||
dst_vtx->coord[0] = PD_BE16(src_vtx->coord[0]);
|
||||
dst_vtx->coord[1] = PD_BE16(src_vtx->coord[1]);
|
||||
dst_vtx->coord[2] = PD_BE16(src_vtx->coord[2]);
|
||||
|
||||
dst_vtx->flag = src_vtx->flag;
|
||||
dst_vtx->color = src_vtx->color;
|
||||
|
||||
dst_vtx->s = PD_BE16(src_vtx->s);
|
||||
dst_vtx->t = PD_BE16(src_vtx->t);
|
||||
|
||||
curpos_src += sizeof(struct vtx);
|
||||
curpos_dst += sizeof(struct vtx);
|
||||
}
|
||||
|
||||
curpos_dst = ALIGN8(curpos_dst);
|
||||
|
||||
// colors
|
||||
uintptr_t ptr_src_colors = 0;
|
||||
uintptr_t ptr_dst_colors = 0;
|
||||
|
||||
if (dst_header->colours) {
|
||||
ptr_src_colors = curpos_src = ALIGN8((uintptr_t)dst_header->colours - src_ofs);
|
||||
ptr_dst_colors = curpos_dst + dst_roomoffset;
|
||||
|
||||
ptrAdd(curpos_src + src_ofs, curpos_dst + dst_roomoffset);
|
||||
|
||||
uintptr_t col_end = (numgdls > 0) ? gdls_addr[0] : infsize;
|
||||
size_t col_len = col_end - curpos_src;
|
||||
|
||||
memcpy(dst + curpos_dst, src + curpos_src, col_len);
|
||||
curpos_src += col_len;
|
||||
curpos_dst += col_len;
|
||||
}
|
||||
|
||||
// gdls
|
||||
gbiSetVtx(src_header->ptr_vertices, ptr_src_vertices);
|
||||
gbiSetSegment(0x0e, (uintptr_t)dst_header->vertices);
|
||||
|
||||
uintptr_t gdlstart = curpos_dst;
|
||||
for (size_t i = 0; i < numgdls; i++) {
|
||||
ptrAdd(gdls_addr[i] + src_ofs, curpos_dst + dst_roomoffset);
|
||||
curpos_dst = gbiConvertGdl(dst, curpos_dst, src, gdls_addr[i], 1);
|
||||
}
|
||||
|
||||
// relink ptrs: roomblocks
|
||||
for (size_t i = 0; i < numblocks; i++) {
|
||||
struct roomblock *block = (struct roomblock*)&ptr_dst_roomblocks[i];
|
||||
|
||||
relinkPtr((uintptr_t*)&block->next);
|
||||
|
||||
if (block->type == BLOCK_LEAF) {
|
||||
relinkPtr((uintptr_t*)&block->gdl);
|
||||
u32 offset_vtx = (uintptr_t)block->vertices - ptr_src_vertices - src_ofs;
|
||||
u32 offset_col = (uintptr_t)block->colours - ptr_src_colors - src_ofs;
|
||||
|
||||
block->vertices = (void *)(ptr_dst_vertices + offset_vtx);
|
||||
block->colours = (void *)(ptr_dst_colors + offset_col);
|
||||
}
|
||||
else {
|
||||
relinkPtr((uintptr_t*)&block->gdl); // child
|
||||
relinkPtr((uintptr_t*)&block->vertices); // coord
|
||||
}
|
||||
}
|
||||
|
||||
// relink ptrs: header
|
||||
relinkPtr((uintptr_t*)&dst_header->vertices);
|
||||
relinkPtr((uintptr_t*)&dst_header->colours);
|
||||
relinkPtr((uintptr_t*)&dst_header->opablocks);
|
||||
relinkPtr((uintptr_t*)&dst_header->xlublocks);
|
||||
|
||||
return curpos_dst;
|
||||
}
|
||||
|
||||
static u32 convertSection1(u8 *dst, u8 *src, u32 ofs)
|
||||
{
|
||||
// Convert primary
|
||||
u32 srcpos = 0;
|
||||
u32 dstpos = 0;
|
||||
struct host_primaryheader *host_primary_header = (struct host_primaryheader *) dst;
|
||||
struct n64_primaryheader *n64_primary_header = (struct n64_primaryheader *) src;
|
||||
srcpos += sizeof(struct n64_primaryheader);
|
||||
dstpos += sizeof(*host_primary_header);
|
||||
|
||||
u32 src_bgcmds = PD_BE32(n64_primary_header->ptr_bgcmds) - ofs;
|
||||
|
||||
host_primary_header->unused1 = 0;
|
||||
host_primary_header->unused2 = 0;
|
||||
|
||||
host_primary_header->ptr_rooms = dstpos + ofs;
|
||||
convertPrimaryRooms(dst, &dstpos, src, &srcpos);
|
||||
|
||||
if (n64_primary_header->ptr_lights) {
|
||||
host_primary_header->ptr_lights = dstpos + ofs;
|
||||
srcpos = PD_BE32(n64_primary_header->ptr_lights) - ofs;
|
||||
convertPrimaryLights(dst, &dstpos, src, &srcpos, src_bgcmds);
|
||||
}
|
||||
|
||||
host_primary_header->ptr_portals = dstpos + ofs;
|
||||
srcpos = PD_BE32(n64_primary_header->ptr_portals) - ofs;
|
||||
u32 src_portalvtxs, dst_portalvtxs;
|
||||
convertPrimaryPortals(dst, &dstpos, src, &srcpos, &src_portalvtxs, &dst_portalvtxs);
|
||||
|
||||
host_primary_header->ptr_bgcmds = dstpos + ofs;
|
||||
convertPrimaryBgCmds(dst, &dstpos, &src[src_bgcmds], dst_portalvtxs, src_portalvtxs);
|
||||
|
||||
return dstpos;
|
||||
}
|
||||
|
||||
void preprocessBgSection1(u8 *data, u32 size, u32 ofs)
|
||||
{
|
||||
u8 *dst = sysMemZeroAlloc(size);
|
||||
|
||||
u32 newSize = convertSection1(dst, data, ofs);
|
||||
|
||||
if (newSize > size) {
|
||||
sysFatalError("overflow when trying to preprocess a bg file, size %d newsize %d", size, newSize);
|
||||
}
|
||||
|
||||
memcpy(data, dst, newSize);
|
||||
sysMemFree(dst);
|
||||
}
|
||||
|
||||
u32 preprocessBgRoom(u8 *data, u32 size, u32 room_ofs)
|
||||
{
|
||||
size *= 2;
|
||||
u8 *dst = sysMemZeroAlloc(size);
|
||||
u32 newSize = convertRoomGfxData(dst, data, size, room_ofs);
|
||||
|
||||
if (newSize > size) {
|
||||
sysFatalError("overflow when trying to preprocess a bg room, size %d newsize %d", size, newSize);
|
||||
}
|
||||
|
||||
memcpy(data, dst, newSize);
|
||||
sysMemFree(dst);
|
||||
|
||||
return newSize;
|
||||
}
|
||||
|
||||
void preprocessBgSection1Header(u8* data, u32 size)
|
||||
{
|
||||
u32* header = (u32*)data;
|
||||
PD_SWAP_VAL(header[0]); // inflatedsize
|
||||
PD_SWAP_VAL(header[1]); // section1size
|
||||
PD_SWAP_VAL(header[2]); // primcompsize
|
||||
}
|
||||
|
||||
void preprocessBgSection2Header(u8* data, u32 size)
|
||||
{
|
||||
u16* header = (u16*)data;
|
||||
PD_SWAP_VAL(header[0]); // inflatedsize
|
||||
PD_SWAP_VAL(header[1]); // section2compsize
|
||||
}
|
||||
|
||||
void preprocessBgSection2(u8* data, u32 size)
|
||||
{
|
||||
// section2 is a texture id list
|
||||
u16* section2 = (u16*)data;
|
||||
for (s32 i = 0; i < size; ++i) {
|
||||
PD_SWAP_VAL(section2[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void preprocessBgSection3Header(u8* data, u32 size)
|
||||
{
|
||||
u16* header = (u16*)data;
|
||||
PD_SWAP_VAL(header[0]);
|
||||
PD_SWAP_VAL(header[1]);
|
||||
}
|
||||
|
||||
void preprocessBgSection3(u8* data, u32 size)
|
||||
{
|
||||
// room bounding boxes, 6x s16 per room
|
||||
s16* bbox = (s16*)data;
|
||||
for (s32 i = 1; i < g_Vars.roomcount; ++i) {
|
||||
PD_SWAP_VAL(*bbox); ++bbox;
|
||||
PD_SWAP_VAL(*bbox); ++bbox;
|
||||
PD_SWAP_VAL(*bbox); ++bbox;
|
||||
PD_SWAP_VAL(*bbox); ++bbox;
|
||||
PD_SWAP_VAL(*bbox); ++bbox;
|
||||
PD_SWAP_VAL(*bbox); ++bbox;
|
||||
}
|
||||
|
||||
// gfxdatalen list
|
||||
u16* gfxdatalen = (u16*)bbox;
|
||||
for (s32 i = 1; i < g_Vars.roomcount; ++i) {
|
||||
PD_SWAP_VAL(*gfxdatalen); ++gfxdatalen;
|
||||
}
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "preprocess/common.h"
|
||||
|
||||
static int getNextNonZero(u8 *src, u32 offset, size_t len)
|
||||
{
|
||||
u32 *ptr = (u32 *) &src[offset];
|
||||
u32 *end = (u32 *) &src[len];
|
||||
|
||||
while (ptr < end) {
|
||||
if (*ptr != 0) {
|
||||
return PD_BE32(*ptr);
|
||||
}
|
||||
|
||||
ptr++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int getNumStrings(u8 *src, size_t len)
|
||||
{
|
||||
u32 ptr_table_len = getNextNonZero(src, 0, len);
|
||||
|
||||
if (ptr_table_len) {
|
||||
return ptr_table_len / sizeof(u32);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static u32 convertLangFile(u8 *dst, u8 *src, size_t srclen)
|
||||
{
|
||||
// Convert it
|
||||
u32 *src_offsets = (u32 *) src;
|
||||
size_t src_ptr_table_len = PD_BE32(src_offsets[0]);
|
||||
size_t src_str_table_len = srclen - src_ptr_table_len;
|
||||
int num_strings = getNumStrings(src, srclen);
|
||||
size_t dst_ptr_table_len = num_strings * sizeof(uintptr_t);
|
||||
size_t dst_str_table_len = src_str_table_len;
|
||||
|
||||
int cur_dst_offset = dst_ptr_table_len;
|
||||
|
||||
uintptr_t *dst_offsets = (uintptr_t *) dst;
|
||||
|
||||
for (int i = 0; i < num_strings; i++) {
|
||||
u32 src_offset = PD_BE32(src_offsets[i]);
|
||||
|
||||
if (src_offset) {
|
||||
// Write pointer
|
||||
dst_offsets[i] = (cur_dst_offset);
|
||||
|
||||
// Write string
|
||||
u32 end = getNextNonZero(src, (i + 1) * 4, num_strings * 4);
|
||||
|
||||
if (!end) {
|
||||
end = srclen;
|
||||
}
|
||||
|
||||
size_t len = end - src_offset;
|
||||
len = ALIGN4(len);
|
||||
memcpy(&dst[cur_dst_offset], &src[src_offset], len);
|
||||
|
||||
cur_dst_offset += len;
|
||||
} else {
|
||||
// Write pointer
|
||||
dst_offsets[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return ALIGN16(cur_dst_offset);
|
||||
}
|
||||
|
||||
u8 *preprocessLangFile(u8 *data, u32 size, u32 *outSize) {
|
||||
u32 newSizeEstimated = romdataFileGetEstimatedSize(size, LOADTYPE_LANG);
|
||||
u8 *dst = sysMemZeroAlloc(newSizeEstimated);
|
||||
|
||||
u32 newSize = convertLangFile(dst, data, size);
|
||||
|
||||
if (newSize > newSizeEstimated) {
|
||||
sysFatalError("overflow when trying to preprocess a lang file, size %d newsize %d", size, newSize);
|
||||
}
|
||||
|
||||
memcpy(data, dst, newSize);
|
||||
sysMemFree(dst);
|
||||
|
||||
*outSize = newSize;
|
||||
|
||||
return 0;
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,292 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "preprocess/common.h"
|
||||
|
||||
#include "constants.h"
|
||||
|
||||
struct n64_header {
|
||||
s32 num_pads;
|
||||
s32 num_covers;
|
||||
u32 ptr_waypoints;
|
||||
u32 ptr_waygroups;
|
||||
u32 ptr_cover;
|
||||
};
|
||||
|
||||
struct host_header {
|
||||
s32 num_pads;
|
||||
s32 num_covers;
|
||||
uintptr_t ptr_waypoints;
|
||||
uintptr_t ptr_waygroups;
|
||||
uintptr_t ptr_cover;
|
||||
};
|
||||
|
||||
struct padheader {
|
||||
u32 flags : 18;
|
||||
u32 room : 10;
|
||||
u32 liftnum : 4;
|
||||
};
|
||||
|
||||
struct n64_waypoint {
|
||||
s32 padnum;
|
||||
u32 ptr_neighbours;
|
||||
s32 groupnum;
|
||||
s32 step;
|
||||
};
|
||||
|
||||
struct n64_waygroup {
|
||||
u32 ptr_neighbours;
|
||||
u32 ptr_waypoints;
|
||||
s32 step;
|
||||
};
|
||||
|
||||
static u32 convertPads(u8 *dst, u32 dstpos, u8 *src, u32 srcpos, int num_pads)
|
||||
{
|
||||
u16 *src_offsets = (u16 *) &src[srcpos];
|
||||
u16 *dst_offsets = (u16 *) &dst[dstpos];
|
||||
|
||||
dstpos += num_pads * sizeof(u16);
|
||||
|
||||
for (int i = 0; i < num_pads; i++) {
|
||||
srcpos = PD_BE16(src_offsets[i]);
|
||||
|
||||
dst_offsets[i] = (dstpos);
|
||||
|
||||
// Header
|
||||
u32 n64_padheader = PD_BE32(*(u32 *) &src[srcpos]);
|
||||
struct padheader *host_padheader = (struct padheader *) &dst[dstpos];
|
||||
u32 flags = (n64_padheader >> 14) & 0x3ffff;
|
||||
|
||||
*(u32*)host_padheader = (n64_padheader);
|
||||
|
||||
srcpos += sizeof(struct padheader);
|
||||
dstpos += sizeof(struct padheader);
|
||||
|
||||
// Position
|
||||
if (flags & PADFLAG_INTPOS) {
|
||||
s16 *srcptr = (s16 *) &src[srcpos];
|
||||
s16 *dstptr = (s16 *) &dst[dstpos];
|
||||
|
||||
dstptr[0] = PD_BE16(srcptr[0]);
|
||||
dstptr[1] = PD_BE16(srcptr[1]);
|
||||
dstptr[2] = PD_BE16(srcptr[2]);
|
||||
|
||||
srcpos += 8;
|
||||
dstpos += 8;
|
||||
} else {
|
||||
u32 *srcptr = (u32 *) &src[srcpos];
|
||||
u32 *dstptr = (u32 *) &dst[dstpos];
|
||||
|
||||
dstptr[0] = PD_BE32(srcptr[0]);
|
||||
dstptr[1] = PD_BE32(srcptr[1]);
|
||||
dstptr[2] = PD_BE32(srcptr[2]);
|
||||
|
||||
srcpos += 12;
|
||||
dstpos += 12;
|
||||
}
|
||||
|
||||
// Up
|
||||
if ((flags & (PADFLAG_UPALIGNTOX | PADFLAG_UPALIGNTOY | PADFLAG_UPALIGNTOZ)) == 0) {
|
||||
u32 *srcptr = (u32 *) &src[srcpos];
|
||||
u32 *dstptr = (u32 *) &dst[dstpos];
|
||||
|
||||
dstptr[0] = PD_BE32(srcptr[0]);
|
||||
dstptr[1] = PD_BE32(srcptr[1]);
|
||||
dstptr[2] = PD_BE32(srcptr[2]);
|
||||
|
||||
srcpos += 12;
|
||||
dstpos += 12;
|
||||
}
|
||||
|
||||
// Look
|
||||
if ((flags & (PADFLAG_LOOKALIGNTOX | PADFLAG_LOOKALIGNTOY | PADFLAG_LOOKALIGNTOZ)) == 0) {
|
||||
u32 *srcptr = (u32 *) &src[srcpos];
|
||||
u32 *dstptr = (u32 *) &dst[dstpos];
|
||||
|
||||
dstptr[0] = PD_BE32(srcptr[0]);
|
||||
dstptr[1] = PD_BE32(srcptr[1]);
|
||||
dstptr[2] = PD_BE32(srcptr[2]);
|
||||
|
||||
srcpos += 12;
|
||||
dstpos += 12;
|
||||
}
|
||||
|
||||
// Bbox
|
||||
if (flags & PADFLAG_HASBBOXDATA) {
|
||||
u32 *srcptr = (u32 *) &src[srcpos];
|
||||
u32 *dstptr = (u32 *) &dst[dstpos];
|
||||
|
||||
dstptr[0] = PD_BE32(srcptr[0]);
|
||||
dstptr[1] = PD_BE32(srcptr[1]);
|
||||
dstptr[2] = PD_BE32(srcptr[2]);
|
||||
dstptr[3] = PD_BE32(srcptr[3]);
|
||||
dstptr[4] = PD_BE32(srcptr[4]);
|
||||
dstptr[5] = PD_BE32(srcptr[5]);
|
||||
|
||||
srcpos += 4 * 6;
|
||||
dstpos += 4 * 6;
|
||||
}
|
||||
}
|
||||
|
||||
return dstpos;
|
||||
}
|
||||
|
||||
static u32 convertWayPoints(u8 *dst, u32 dstpos, u8 *src, u32 srcpos)
|
||||
{
|
||||
struct n64_waypoint *n64_waypoints = (struct n64_waypoint *) &src[srcpos];
|
||||
struct waypoint *host_waypoints = (struct waypoint *) &dst[dstpos];
|
||||
int num_waypoints;
|
||||
|
||||
for (num_waypoints = 0; n64_waypoints[num_waypoints].padnum != -1; num_waypoints++);
|
||||
|
||||
dstpos += (num_waypoints + 1) * sizeof(struct waypoint);
|
||||
|
||||
u32 *host_neighbours = (u32 *) &dst[dstpos];
|
||||
int n = 0;
|
||||
|
||||
for (int i = 0; i < num_waypoints; i++) {
|
||||
host_waypoints[i].padnum = PD_BE32(n64_waypoints[i].padnum);
|
||||
host_waypoints[i].neighbours = (void *)(uintptr_t)dstpos;
|
||||
host_waypoints[i].groupnum = PD_BE32(n64_waypoints[i].groupnum);
|
||||
host_waypoints[i].step = 0;
|
||||
|
||||
u32 *n64_neighbours = (u32 *) &src[PD_BE32(n64_waypoints[i].ptr_neighbours)];
|
||||
|
||||
for (int j = 0; n64_neighbours[j] != 0xffffffff; j++) {
|
||||
host_neighbours[n++] = PD_BE32(n64_neighbours[j]);
|
||||
dstpos += 4;
|
||||
}
|
||||
|
||||
host_neighbours[n++] = 0xffffffff;
|
||||
dstpos += 4;
|
||||
}
|
||||
|
||||
// Terminator
|
||||
host_waypoints[num_waypoints].padnum = 0xffffffff;
|
||||
host_waypoints[num_waypoints].neighbours = NULL;
|
||||
host_waypoints[num_waypoints].groupnum = 0;
|
||||
host_waypoints[num_waypoints].step = 0;
|
||||
|
||||
return dstpos;
|
||||
}
|
||||
|
||||
static u32 convertWayGroups(u8 *dst, u32 dstpos, u8 *src, u32 srcpos)
|
||||
{
|
||||
struct n64_waygroup *n64_waygroups = (struct n64_waygroup *) &src[srcpos];
|
||||
struct waygroup *host_waygroups = (struct waygroup *) &dst[dstpos];
|
||||
int num_waygroups;
|
||||
|
||||
for (num_waygroups = 0; n64_waygroups[num_waygroups].ptr_neighbours != 0; num_waygroups++);
|
||||
|
||||
dstpos += (num_waygroups + 1) * sizeof(struct waygroup);
|
||||
|
||||
// Waygroups and child waypoints
|
||||
u32 *host_waypoints = (u32 *) &dst[dstpos];
|
||||
int n = 0;
|
||||
|
||||
for (int i = 0; i < num_waygroups; i++) {
|
||||
host_waygroups[i].waypoints = (void *)(uintptr_t)dstpos;
|
||||
host_waygroups[i].step = 0;
|
||||
|
||||
u32 *n64_waypoints = (u32 *) &src[PD_BE32(n64_waygroups[i].ptr_waypoints)];
|
||||
|
||||
for (int j = 0; n64_waypoints[j] != 0xffffffff; j++) {
|
||||
host_waypoints[n++] = PD_BE32(n64_waypoints[j]);
|
||||
dstpos += 4;
|
||||
}
|
||||
|
||||
host_waypoints[n++] = 0xffffffff;
|
||||
dstpos += 4;
|
||||
}
|
||||
|
||||
// Terminator
|
||||
host_waygroups[num_waygroups].neighbours = NULL;
|
||||
host_waygroups[num_waygroups].waypoints = NULL;
|
||||
host_waygroups[num_waygroups].step = 0;
|
||||
|
||||
// Waygroup neighbours
|
||||
u32 *host_neighbours = (u32 *) &dst[dstpos];
|
||||
n = 0;
|
||||
|
||||
for (int i = 0; i < num_waygroups; i++) {
|
||||
host_waygroups[i].neighbours = (void *)(uintptr_t)dstpos;
|
||||
|
||||
u32 *n64_neighbours = (u32 *) &src[PD_BE32(n64_waygroups[i].ptr_neighbours)];
|
||||
|
||||
for (int j = 0; n64_neighbours[j] != 0xffffffff; j++) {
|
||||
host_neighbours[n++] = PD_BE32(n64_neighbours[j]);
|
||||
dstpos += 4;
|
||||
}
|
||||
|
||||
host_neighbours[n++] = 0xffffffff;
|
||||
dstpos += 4;
|
||||
}
|
||||
|
||||
return dstpos;
|
||||
}
|
||||
|
||||
static u32 convertCover(u8 *dst, u32 dstpos, u8 *src, u32 srcpos, int num_covers)
|
||||
{
|
||||
struct coverdefinition *n64_covers = (struct coverdefinition *) &src[srcpos];
|
||||
struct coverdefinition *host_covers = (struct coverdefinition *) &dst[dstpos];
|
||||
|
||||
for (int i = 0; i < num_covers; i++) {
|
||||
host_covers[i].pos = PD_SWAPPED_VAL(n64_covers[i].pos);
|
||||
host_covers[i].look = PD_SWAPPED_VAL(n64_covers[i].look);
|
||||
host_covers[i].flags = PD_BE16(n64_covers[i].flags);
|
||||
}
|
||||
|
||||
dstpos += num_covers * sizeof(struct coverdefinition);
|
||||
|
||||
return dstpos;
|
||||
}
|
||||
|
||||
static u32 convertPadsFile(u8 *dst, u8 *src)
|
||||
{
|
||||
u32 dstpos = 0;
|
||||
struct n64_header *n64_header = (struct n64_header *) src;
|
||||
struct host_header *host_header = (struct host_header *) dst;
|
||||
|
||||
int num_pads = PD_BE32(n64_header->num_pads);
|
||||
int num_covers = PD_BE32(n64_header->num_covers);
|
||||
host_header->num_pads = (num_pads);
|
||||
host_header->num_covers = (num_covers);
|
||||
|
||||
dstpos += sizeof(struct host_header);
|
||||
|
||||
// Pads
|
||||
dstpos = convertPads(dst, dstpos, src, sizeof(struct n64_header), num_pads);
|
||||
|
||||
// Waypoints
|
||||
host_header->ptr_waypoints = (dstpos);
|
||||
dstpos = convertWayPoints(dst, dstpos, src, PD_BE32(n64_header->ptr_waypoints));
|
||||
|
||||
// Waygroups
|
||||
host_header->ptr_waygroups = (dstpos);
|
||||
dstpos = convertWayGroups(dst, dstpos, src, PD_BE32(n64_header->ptr_waygroups));
|
||||
|
||||
// Cover
|
||||
host_header->ptr_cover = (dstpos);
|
||||
dstpos = convertCover(dst, dstpos, src, PD_BE32(n64_header->ptr_cover), num_covers);
|
||||
|
||||
return dstpos;
|
||||
}
|
||||
|
||||
u8* preprocessPadsFile(u8 *data, u32 size, u32 *outSize) {
|
||||
u32 newSizeEstimated = romdataFileGetEstimatedSize(size, LOADTYPE_PADS);
|
||||
u8* dst = sysMemZeroAlloc(newSizeEstimated);
|
||||
|
||||
u32 newSize = convertPadsFile(dst, data);
|
||||
|
||||
if (newSize > newSizeEstimated) {
|
||||
sysFatalError("overflow when trying to preprocess a pads file, size %d newsize %d", size, newSize);
|
||||
}
|
||||
|
||||
memcpy(data, dst, newSize);
|
||||
sysMemFree(dst);
|
||||
|
||||
*outSize = newSize;
|
||||
|
||||
return 0;
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,103 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "preprocess/common.h"
|
||||
|
||||
struct tile {
|
||||
u8 type;
|
||||
u8 numvertices;
|
||||
u16 flags;
|
||||
u16 floortype;
|
||||
u8 xmin;
|
||||
u8 ymin;
|
||||
u8 zmin;
|
||||
u8 xmax;
|
||||
u8 ymax;
|
||||
u8 zmax;
|
||||
u16 floorcol;
|
||||
};
|
||||
|
||||
static u32 convertTiles(u8 *dst, u8 *src, size_t srclen)
|
||||
{
|
||||
int num_rooms = PD_BE32(*(u32 *) src);
|
||||
|
||||
size_t src_ptr_table_len = (num_rooms + 1) * 4;
|
||||
size_t dst_ptr_table_len = (num_rooms + 1) * sizeof(u32);
|
||||
|
||||
u32 *src_offsets = (u32 *) &src[4];
|
||||
|
||||
size_t data_len = srclen - src_ptr_table_len - 4;
|
||||
|
||||
*(u32 *) dst = (num_rooms);
|
||||
|
||||
u32 *dst_offsets = (u32 *) (dst + sizeof(u32));
|
||||
u32 cur_dst_offset = dst_ptr_table_len + sizeof(u32);
|
||||
|
||||
u32 cur_src_offset = PD_BE32(src_offsets[0]);
|
||||
u32 end_src_offset = PD_BE32(src_offsets[num_rooms]);
|
||||
int room = 0;
|
||||
|
||||
while (1) {
|
||||
// Check if this is a new room and write the pointer offset if so
|
||||
while (room < (num_rooms + 1) && PD_BE32(src_offsets[room]) == cur_src_offset) {
|
||||
dst_offsets[room] = (cur_dst_offset);
|
||||
room++;
|
||||
}
|
||||
|
||||
if (cur_src_offset >= end_src_offset) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Write tile data
|
||||
struct tile *n64tile = (struct tile *) &src[cur_src_offset];
|
||||
struct tile hosttile;
|
||||
|
||||
hosttile.type = n64tile->type;
|
||||
hosttile.numvertices = n64tile->numvertices;
|
||||
hosttile.flags = PD_BE16(n64tile->flags);
|
||||
hosttile.floortype = PD_BE16(n64tile->floortype);
|
||||
hosttile.xmin = n64tile->xmin;
|
||||
hosttile.ymin = n64tile->ymin;
|
||||
hosttile.zmin = n64tile->zmin;
|
||||
hosttile.xmax = n64tile->xmax;
|
||||
hosttile.ymax = n64tile->ymax;
|
||||
hosttile.zmax = n64tile->zmax;
|
||||
hosttile.floorcol = PD_BE16(n64tile->floorcol);
|
||||
|
||||
memcpy(&dst[cur_dst_offset], &hosttile, sizeof(struct tile));
|
||||
|
||||
cur_dst_offset += sizeof(struct tile);
|
||||
cur_src_offset += sizeof(struct tile);
|
||||
|
||||
// Write tile vertices
|
||||
for (int i = 0; i < hosttile.numvertices; i++) {
|
||||
*(s16 *) &dst[cur_dst_offset + 0] = PD_BE16(*(s16 *) &src[cur_src_offset + 0]);
|
||||
*(s16 *) &dst[cur_dst_offset + 2] = PD_BE16(*(s16 *) &src[cur_src_offset + 2]);
|
||||
*(s16 *) &dst[cur_dst_offset + 4] = PD_BE16(*(s16 *) &src[cur_src_offset + 4]);
|
||||
cur_dst_offset += 6;
|
||||
cur_src_offset += 6;
|
||||
}
|
||||
}
|
||||
|
||||
return ALIGN16(cur_dst_offset);
|
||||
}
|
||||
|
||||
u8 *preprocessTilesFile(u8 *data, u32 size, u32 *outSize)
|
||||
{
|
||||
u32 newSizeEstimated = romdataFileGetEstimatedSize(size, LOADTYPE_TILES);
|
||||
u8 *dst = sysMemZeroAlloc(newSizeEstimated);
|
||||
|
||||
u32 newSize = convertTiles(dst, data, size);
|
||||
|
||||
if (newSize > newSizeEstimated) {
|
||||
sysFatalError("overflow when trying to preprocess a tiles file, size %d newsize %d", size, newSize);
|
||||
}
|
||||
|
||||
memcpy(data, dst, newSize);
|
||||
sysMemFree(dst);
|
||||
|
||||
*outSize = newSize;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,208 +0,0 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "preprocess/common.h"
|
||||
#include "preprocess/gbi.h"
|
||||
|
||||
#if UINTPTR_MAX > 0xFFFFFFFFu
|
||||
#define HOST_DWORDS_PER_CMD 2
|
||||
#else
|
||||
#define HOST_DWORDS_PER_CMD 1
|
||||
#endif
|
||||
|
||||
struct vtx {
|
||||
s16 x;
|
||||
s16 y;
|
||||
s16 z;
|
||||
u8 flags;
|
||||
u8 colour;
|
||||
s16 s;
|
||||
s16 t;
|
||||
};
|
||||
|
||||
struct texaddr {
|
||||
u32 src;
|
||||
u32 dst;
|
||||
};
|
||||
|
||||
static u32 gbiSegments[16];
|
||||
static u32 srcVtxOffset;
|
||||
static u32 dstVtxOffset;
|
||||
|
||||
static struct texaddr texAddrs[64];
|
||||
static int numTexAddrs;
|
||||
|
||||
void gbiReset(void)
|
||||
{
|
||||
for (int i = 0; i < ARRAYCOUNT(gbiSegments); i++) {
|
||||
gbiSegments[i] = 0;
|
||||
}
|
||||
|
||||
srcVtxOffset = 0;
|
||||
dstVtxOffset = 0;
|
||||
numTexAddrs = 0;
|
||||
}
|
||||
|
||||
void gbiSetSegment(int segment, u32 offset)
|
||||
{
|
||||
gbiSegments[segment] = offset & 0x00ffffff;
|
||||
}
|
||||
|
||||
void gbiSetVtx(u32 src_offset, u32 dst_offset)
|
||||
{
|
||||
srcVtxOffset = src_offset & 0x00ffffff;
|
||||
dstVtxOffset = dst_offset & 0x00ffffff;
|
||||
}
|
||||
|
||||
void gbiAddTexAddr(u32 src_offset, u32 dst_offset)
|
||||
{
|
||||
texAddrs[numTexAddrs].src = src_offset & 0x00ffffff;
|
||||
texAddrs[numTexAddrs++].dst = dst_offset & 0x00ffffff;
|
||||
}
|
||||
|
||||
u32 gbiFindTexAddr(u32 src_offset)
|
||||
{
|
||||
for (int i = 0; i < numTexAddrs; i++) {
|
||||
if (texAddrs[i].src == src_offset)
|
||||
return texAddrs[i].dst;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void gbiConvertVtx(u8 *dst, u32 offset, int count)
|
||||
{
|
||||
if (!offset) return;
|
||||
struct vtx* vtxs = (struct vtx*)(dst + offset);
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
struct vtx* vtx = &vtxs[i];
|
||||
|
||||
vtx->x = PD_BE16(vtx->x);
|
||||
vtx->y = PD_BE16(vtx->y);
|
||||
vtx->z = PD_BE16(vtx->z);
|
||||
vtx->s = PD_BE16(vtx->s);
|
||||
vtx->t = PD_BE16(vtx->t);
|
||||
}
|
||||
}
|
||||
|
||||
#define CMD_IS_VTX(cmd) ((cmd & 0xff00000000000000) == 0x0400000000000000)
|
||||
#define CMD_IS_DL(cmd) ((cmd & 0xff00000000000000) == 0x0600000000000000)
|
||||
#define CMD_IS_COL(cmd) ((cmd & 0xff00000000000000) == 0x0700000000000000)
|
||||
#define CMD_IS_ENDDL(cmd) ((cmd & 0xff00000000000000) == 0xb800000000000000)
|
||||
#define CMD_IS_MOVEWORD(cmd) ((cmd & 0xff00000000000000) == 0xbc00000000000000)
|
||||
#define CMD_IS_MOVEMEM(cmd) ((cmd & 0xff00000000000000) == 0x0300000000000000)
|
||||
#define CMD_IS_MTX(cmd) ((cmd & 0xff00000000000000) == 0x0100000000000000)
|
||||
#define CMD_IS_SETTIMG(cmd) ((cmd & 0xff00000000000000) == 0xfd00000000000000)
|
||||
#define CMD_IS_SETZIMG(cmd) ((cmd & 0xff00000000000000) == 0xfe00000000000000)
|
||||
#define CMD_IS_SETCIMG(cmd) ((cmd & 0xff00000000000000) == 0xff00000000000000)
|
||||
|
||||
#define CMD_HAS_ADDR(cmd) CMD_IS_VTX(cmd) \
|
||||
|| CMD_IS_COL(cmd) \
|
||||
|| CMD_IS_MOVEWORD(cmd) \
|
||||
|| CMD_IS_SETTIMG(cmd)
|
||||
|
||||
|
||||
#define CMD_IS_SEGMENTED(cmd) ( CMD_IS_MOVEMEM(cmd) \
|
||||
|| CMD_IS_MTX(cmd) \
|
||||
|| CMD_IS_VTX(cmd) \
|
||||
|| CMD_IS_COL(cmd) \
|
||||
|| CMD_IS_DL(cmd) \
|
||||
|| CMD_IS_SETTIMG(cmd) \
|
||||
|| CMD_IS_SETCIMG(cmd) \
|
||||
|| CMD_IS_SETZIMG(cmd))
|
||||
|
||||
/**
|
||||
* Segment 5 is the start of the model file. The data in these files shifts
|
||||
* depending on the pointer size, so this function adjusts the offset accordingly.
|
||||
*/
|
||||
static u64 gbiRewriteAddr(u64 cmd, u8 opcode)
|
||||
{
|
||||
u8 segment = (cmd & 0x0f000000) >> 24;
|
||||
u32 offset = cmd & 0x00ffffff;
|
||||
|
||||
if (segment == 5) {
|
||||
if (opcode == 0xfd) {
|
||||
offset = gbiFindTexAddr(offset);
|
||||
}
|
||||
else {
|
||||
if (offset < srcVtxOffset) {
|
||||
sysFatalError("Tried to load data from offset 0x%x but segment starts at 0x%x\n", offset, srcVtxOffset);
|
||||
}
|
||||
|
||||
offset = offset - srcVtxOffset + dstVtxOffset;
|
||||
}
|
||||
}
|
||||
|
||||
return (cmd & 0xffffffffff000000) | offset;
|
||||
}
|
||||
|
||||
void gbiGdlRewriteAddrs(u8 *dst, u32 offset)
|
||||
{
|
||||
if (!offset) return;
|
||||
|
||||
u64 *cmds = (u64 *)(dst + (offset & 0x00ffffff));
|
||||
if (!cmds) return;
|
||||
|
||||
u64 cmd;
|
||||
|
||||
do {
|
||||
cmd = *cmds;
|
||||
Gfx* gfxcmd = (Gfx *)cmds;
|
||||
int idx = 0;
|
||||
u8 opcode = (cmd >> 24) & 0xff;
|
||||
|
||||
#if HOST_DWORDS_PER_CMD == 2
|
||||
idx = 1;
|
||||
opcode = (cmd >> 24) & 0xff;
|
||||
#endif
|
||||
cmd = (u64)opcode << 56;
|
||||
|
||||
if (CMD_HAS_ADDR(cmd)) {
|
||||
cmds[idx] = gbiRewriteAddr(cmds[idx], opcode);
|
||||
}
|
||||
|
||||
if (CMD_IS_SEGMENTED(cmd)) {
|
||||
gfxcmd->words.w1 |= 1;
|
||||
}
|
||||
|
||||
cmds += HOST_DWORDS_PER_CMD;
|
||||
} while (!CMD_IS_ENDDL(cmd));
|
||||
}
|
||||
|
||||
u32 gbiConvertGdl(u8 *dst, u32 dstpos, u8 *src, u32 srcpos, int segment_cmds)
|
||||
{
|
||||
dstpos = ALIGN8(dstpos);
|
||||
|
||||
u64 *n64_cmd = (u64*)&src[srcpos];
|
||||
u64 *host_cmd = (u64*)&dst[dstpos];
|
||||
u64 cmd;
|
||||
|
||||
do {
|
||||
cmd = PD_BE64(*n64_cmd);
|
||||
|
||||
#if HOST_DWORDS_PER_CMD == 2
|
||||
host_cmd[0] = ((cmd & 0xffffffff00000000) >> 32);
|
||||
host_cmd[1] = (cmd & 0xffffffff);
|
||||
|
||||
if (segment_cmds && CMD_IS_SEGMENTED(cmd)) {
|
||||
host_cmd[1] |= 1;
|
||||
}
|
||||
#else
|
||||
host_cmd[0] = (cmd >> 32) | ((cmd & 0xffffffff) << 32);
|
||||
|
||||
if (segment_cmds && CMD_IS_SEGMENTED(cmd)) {
|
||||
Gfx* gfxcmd = (Gfx*)host_cmd;
|
||||
gfxcmd->words.w1 |= 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
dstpos += sizeof(*host_cmd) * HOST_DWORDS_PER_CMD;
|
||||
host_cmd += HOST_DWORDS_PER_CMD;
|
||||
n64_cmd++;
|
||||
} while (!CMD_IS_ENDDL(cmd));
|
||||
|
||||
return dstpos;
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <PR/ultratypes.h>
|
||||
#include <PR/gbi.h>
|
||||
|
||||
#include "data.h"
|
||||
#include "bss.h"
|
||||
#include "game/setuputils.h"
|
||||
#include "game/texdecompress.h"
|
||||
#include "mod.h"
|
||||
|
||||
#include "preprocess/common.h"
|
||||
|
||||
u8 *preprocessAnimations(u8* data, u32 size, u32* outSize)
|
||||
{
|
||||
// set the anim table pointers as well
|
||||
extern u8 *_animationsTableRomStart;
|
||||
extern u8 *_animationsTableRomEnd;
|
||||
|
||||
// the animation table is at the end of the segment
|
||||
u32 *animtbl = (void *)(data + size - 0x38a0);
|
||||
_animationsTableRomStart = (u8 *)animtbl;
|
||||
_animationsTableRomEnd = data + size;
|
||||
|
||||
PD_SWAP_VAL(*animtbl);
|
||||
const u32 count = *animtbl++;
|
||||
|
||||
struct animtableentry *anim = (struct animtableentry *)animtbl;
|
||||
for (u32 i = 0; i < count; ++i, ++anim) {
|
||||
PD_SWAP_VAL(anim->numframes);
|
||||
PD_SWAP_VAL(anim->bytesperframe);
|
||||
PD_SWAP_VAL(anim->headerlen);
|
||||
PD_SWAP_VAL(anim->data);
|
||||
// if an external replacement exists, replace the table entry and mark the offset
|
||||
if (modAnimationLoadDescriptor(i, anim) > 0) {
|
||||
anim->data = 0xffffffff;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
u8 *preprocessMpConfigs(u8* data, u32 size, u32* outSize)
|
||||
{
|
||||
const u32 count = size / sizeof(struct mpconfig);
|
||||
struct mpconfig *cfg = (struct mpconfig *)data;
|
||||
for (u32 i = 0; i < count; ++i, ++cfg) {
|
||||
PD_SWAP_VAL(cfg->setup.options);
|
||||
PD_SWAP_VAL(cfg->setup.teamscorelimit);
|
||||
PD_SWAP_VAL(cfg->setup.chrslots);
|
||||
// TODO: are these required or are they always 0?
|
||||
PD_SWAP_VAL(cfg->setup.fileguid.deviceserial);
|
||||
PD_SWAP_VAL(cfg->setup.fileguid.fileid);
|
||||
// convert MPWEAPON_ to take classic weapons and JPN weapons into account
|
||||
for (s32 j = 0; j < ARRAYCOUNT(cfg->setup.weapons); ++j) {
|
||||
#if VERSION == VERSION_JPN_FINAL /* TODO: replace with runtime check */
|
||||
if (cfg->setup.weapons[j] >= 0x24) {
|
||||
// weapons after and including the shield need to be shifted (for classic weapons)
|
||||
cfg->setup.weapons[j] += (MPWEAPON_SHIELD - MPWEAPON_PP9I);
|
||||
}
|
||||
if (cfg->setup.weapons[j] >= 0x22) {
|
||||
// weapons after and including the cloaking device need to be shifted (for IR Scanner and Night Vision)
|
||||
cfg->setup.weapons[j] += (MPWEAPON_CLOAKINGDEVICE - MPWEAPON_NIGHTVISION);
|
||||
}
|
||||
if (cfg->setup.weapons[j] >= 0x19) {
|
||||
// weapons after the combat knife also need to be shifted up in JPN
|
||||
cfg->setup.weapons[j]++;
|
||||
}
|
||||
#else
|
||||
if (cfg->setup.weapons[j] >= 0x25) {
|
||||
// weapons after and including the shield need to be shifted (for classic weapons)
|
||||
cfg->setup.weapons[j] += (MPWEAPON_SHIELD - MPWEAPON_PP9I);
|
||||
}
|
||||
if (cfg->setup.weapons[j] >= 0x23) {
|
||||
// weapons after and including the cloaking device need to be shifted (for IR Scanner and Night Vision)
|
||||
cfg->setup.weapons[j] += (MPWEAPON_CLOAKINGDEVICE - MPWEAPON_NIGHTVISION);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
u8 *preprocessTexturesList(u8* data, u32 size, u32* outSize)
|
||||
{
|
||||
struct texture *tex = (struct texture *)data;
|
||||
const u32 count = size / sizeof(*tex);
|
||||
for (u32 i = 0; i < count; ++i, ++tex) {
|
||||
// TODO: it sure looks like none of the fields except soundsurfacetype, surfacetype and dataoffset are set
|
||||
// just swap the last 3 bytes of the first word...
|
||||
const u32 dofs = (u32)tex->dataoffset << 8;
|
||||
tex->dataoffset = PD_BE32(dofs);
|
||||
// ...and the surface types in the first byte
|
||||
const u8 tmp = tex->soundsurfacetype;
|
||||
tex->soundsurfacetype = tex->surfacetype;
|
||||
tex->surfacetype = tmp;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -1,362 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "libaudio.h"
|
||||
|
||||
#include "preprocess/common.h"
|
||||
|
||||
struct n64_adpcm_waveinfo {
|
||||
u32 loop; // ptr to ALADPCMloop
|
||||
u32 book; // ptr to ALADPCMBook
|
||||
};
|
||||
|
||||
struct n64_raw_waveinfo {
|
||||
u32 loop; // ptr to ALRawLoop
|
||||
};
|
||||
|
||||
struct n64_wavetable {
|
||||
u32 base;
|
||||
s32 len;
|
||||
u8 type;
|
||||
u8 flags;
|
||||
union {
|
||||
struct n64_adpcm_waveinfo adpcmWave;
|
||||
struct n64_raw_waveinfo rawWave;
|
||||
} waveInfo;
|
||||
};
|
||||
|
||||
struct n64_sound {
|
||||
u32 envelope; // ptr to ALEnvelope
|
||||
u32 keyMap; // ptr to ALKeyMap
|
||||
u32 wavetable; // ptr to struct n64_wavetable
|
||||
u8 samplePan;
|
||||
u8 sampleVolume;
|
||||
u8 flags;
|
||||
};
|
||||
|
||||
struct n64_instrument {
|
||||
u8 volume;
|
||||
u8 pan;
|
||||
u8 priority;
|
||||
u8 flags;
|
||||
u8 tremType;
|
||||
u8 tremRate;
|
||||
u8 tremDepth;
|
||||
u8 tremDelay;
|
||||
u8 vibType;
|
||||
u8 vibRate;
|
||||
u8 vibDepth;
|
||||
u8 vibDelay;
|
||||
s16 bendRange;
|
||||
s16 soundCount;
|
||||
u32 soundArray[1]; // ptr to struct n64_sound
|
||||
};
|
||||
|
||||
struct n64_bank {
|
||||
s16 instCount;
|
||||
u8 flags;
|
||||
u8 pad;
|
||||
s32 sampleRate;
|
||||
u32 percussion; // ptr to struct n64_instrument
|
||||
u32 instArray[1]; // ptr to struct n64_instrument
|
||||
};
|
||||
|
||||
struct n64_bankfile {
|
||||
s16 revision;
|
||||
s16 bankCount;
|
||||
u32 bankArray[1]; // ptr to struct n64_bank
|
||||
};
|
||||
|
||||
// only proceeds to convert the next item if it's not already converted
|
||||
#define AL_NEXT_ITEM(field, func) { \
|
||||
struct ptrmarker *marker = ptrFind(srcpos); \
|
||||
if (marker == NULL) { \
|
||||
field = (void *)(uintptr_t)(dstpos); \
|
||||
ptrAdd(srcpos, (uintptr_t)(field)); \
|
||||
dstpos = func(dst, dstpos, src, srcpos); \
|
||||
} else { \
|
||||
field = (void *)marker->ptr_host; } \
|
||||
}
|
||||
|
||||
static u32 convertAudioEnvelope(u8 *dst, u32 dstpos, u8 *src, u32 srcpos)
|
||||
{
|
||||
ALEnvelope *n64_envelope = (ALEnvelope *) &src[srcpos];
|
||||
ALEnvelope *host_envelope = (ALEnvelope *) &dst[dstpos];
|
||||
|
||||
dstpos += sizeof(ALEnvelope);
|
||||
|
||||
host_envelope->attackTime = PD_BE32(n64_envelope->attackTime);
|
||||
host_envelope->decayTime = PD_BE32(n64_envelope->decayTime);
|
||||
host_envelope->releaseTime = PD_BE32(n64_envelope->releaseTime);
|
||||
host_envelope->attackVolume = n64_envelope->attackVolume;
|
||||
host_envelope->decayVolume = n64_envelope->decayVolume;
|
||||
|
||||
return dstpos;
|
||||
}
|
||||
|
||||
static u32 convertAudioKeyMap(u8 *dst, u32 dstpos, u8 *src, u32 srcpos)
|
||||
{
|
||||
ALKeyMap *n64_keymap = (ALKeyMap *) &src[srcpos];
|
||||
ALKeyMap *host_keymap = (ALKeyMap *) &dst[dstpos];
|
||||
|
||||
dstpos += sizeof(ALKeyMap);
|
||||
|
||||
host_keymap->velocityMin = n64_keymap->velocityMin;
|
||||
host_keymap->velocityMax = n64_keymap->velocityMax;
|
||||
host_keymap->keyMin = n64_keymap->keyMin;
|
||||
host_keymap->keyMax = n64_keymap->keyMax;
|
||||
host_keymap->keyBase = n64_keymap->keyBase;
|
||||
host_keymap->detune = n64_keymap->detune;
|
||||
|
||||
return dstpos;
|
||||
}
|
||||
|
||||
static u32 convertAudioAdpcmLoop(u8 *dst, u32 dstpos, u8 *src, u32 srcpos)
|
||||
{
|
||||
ALADPCMloop *n64_loop = (ALADPCMloop *) &src[srcpos];
|
||||
ALADPCMloop *host_loop = (ALADPCMloop *) &dst[dstpos];
|
||||
|
||||
dstpos += sizeof(ALADPCMloop);
|
||||
|
||||
host_loop->start = PD_BE32(n64_loop->start);
|
||||
host_loop->end = PD_BE32(n64_loop->end);
|
||||
host_loop->count = PD_BE32(n64_loop->count);
|
||||
|
||||
for (int i = 0; i < ARRAYCOUNT(host_loop->state); i++) {
|
||||
host_loop->state[i] = PD_BE16(n64_loop->state[i]);
|
||||
}
|
||||
|
||||
return dstpos;
|
||||
}
|
||||
|
||||
static u32 convertAudioAdpcmBook(u8 *dst, u32 dstpos, u8 *src, u32 srcpos)
|
||||
{
|
||||
ALADPCMBook *n64_book = (ALADPCMBook *) &src[srcpos];
|
||||
ALADPCMBook *host_book = (ALADPCMBook *) &dst[dstpos];
|
||||
|
||||
dstpos += sizeof(ALADPCMBook);
|
||||
|
||||
host_book->order = PD_BE32(n64_book->order);
|
||||
host_book->npredictors = PD_BE32(n64_book->npredictors);
|
||||
|
||||
for (int i = 0; i < ARRAYCOUNT(host_book->book); i++) {
|
||||
host_book->book[i] = PD_BE16(n64_book->book[i]);
|
||||
}
|
||||
|
||||
return dstpos;
|
||||
}
|
||||
|
||||
static u32 convertAudioRawLoop(u8 *dst, u32 dstpos, u8 *src, u32 srcpos)
|
||||
{
|
||||
ALRawLoop *n64_loop = (ALRawLoop *) &src[srcpos];
|
||||
ALRawLoop *host_loop = (ALRawLoop *) &dst[dstpos];
|
||||
|
||||
dstpos += sizeof(ALRawLoop);
|
||||
|
||||
host_loop->start = PD_BE32(n64_loop->start);
|
||||
host_loop->end = PD_BE32(n64_loop->end);
|
||||
host_loop->count = PD_BE32(n64_loop->count);
|
||||
|
||||
return dstpos;
|
||||
}
|
||||
|
||||
static u32 convertAudioWaveTable(u8 *dst, u32 dstpos, u8 *src, u32 srcpos)
|
||||
{
|
||||
struct n64_wavetable *n64_wavetable = (struct n64_wavetable *) &src[srcpos];
|
||||
ALWaveTable *host_wavetable = (ALWaveTable *) &dst[dstpos];
|
||||
|
||||
dstpos += sizeof(ALWaveTable);
|
||||
|
||||
host_wavetable->base = (void *)(uintptr_t)PD_BE32(n64_wavetable->base);
|
||||
host_wavetable->len = PD_BE32(n64_wavetable->len);
|
||||
host_wavetable->type = n64_wavetable->type;
|
||||
host_wavetable->flags = n64_wavetable->flags;
|
||||
|
||||
if (host_wavetable->type == AL_ADPCM_WAVE) {
|
||||
if (n64_wavetable->waveInfo.adpcmWave.loop) {
|
||||
srcpos = PD_BE32(n64_wavetable->waveInfo.adpcmWave.loop);
|
||||
AL_NEXT_ITEM(host_wavetable->waveInfo.adpcmWave.loop, convertAudioAdpcmLoop);
|
||||
} else {
|
||||
host_wavetable->waveInfo.adpcmWave.loop = NULL;
|
||||
}
|
||||
|
||||
if (n64_wavetable->waveInfo.adpcmWave.book) {
|
||||
srcpos = PD_BE32(n64_wavetable->waveInfo.adpcmWave.book);
|
||||
AL_NEXT_ITEM(host_wavetable->waveInfo.adpcmWave.book, convertAudioAdpcmBook);
|
||||
} else {
|
||||
host_wavetable->waveInfo.adpcmWave.book = NULL;
|
||||
}
|
||||
} else if (host_wavetable->type == AL_RAW16_WAVE) {
|
||||
if (n64_wavetable->waveInfo.rawWave.loop) {
|
||||
srcpos = PD_BE32(n64_wavetable->waveInfo.rawWave.loop);
|
||||
AL_NEXT_ITEM(host_wavetable->waveInfo.rawWave.loop, convertAudioRawLoop);
|
||||
} else {
|
||||
host_wavetable->waveInfo.rawWave.loop = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return dstpos;
|
||||
}
|
||||
|
||||
static u32 convertAudioSound(u8 *dst, u32 dstpos, u8 *src, u32 srcpos)
|
||||
{
|
||||
struct n64_sound *n64_sound = (struct n64_sound *) &src[srcpos];
|
||||
ALSound *host_sound = (ALSound *) &dst[dstpos];
|
||||
|
||||
dstpos += sizeof(ALSound);
|
||||
|
||||
if (n64_sound->envelope) {
|
||||
srcpos = PD_BE32(n64_sound->envelope);
|
||||
AL_NEXT_ITEM(host_sound->envelope, convertAudioEnvelope);
|
||||
} else {
|
||||
host_sound->envelope = NULL;
|
||||
}
|
||||
|
||||
if (n64_sound->keyMap) {
|
||||
srcpos = PD_BE32(n64_sound->keyMap);
|
||||
AL_NEXT_ITEM(host_sound->keyMap, convertAudioKeyMap);
|
||||
} else {
|
||||
host_sound->keyMap = NULL;
|
||||
}
|
||||
|
||||
if (n64_sound->wavetable) {
|
||||
srcpos = PD_BE32(n64_sound->wavetable);
|
||||
AL_NEXT_ITEM(host_sound->wavetable, convertAudioWaveTable);
|
||||
} else {
|
||||
host_sound->wavetable = NULL;
|
||||
}
|
||||
|
||||
host_sound->samplePan = n64_sound->samplePan;
|
||||
host_sound->sampleVolume = n64_sound->sampleVolume;
|
||||
host_sound->flags = n64_sound->flags;
|
||||
|
||||
return dstpos;
|
||||
}
|
||||
|
||||
static u32 convertAudioInstrument(u8 *dst, u32 dstpos, u8 *src, u32 srcpos)
|
||||
{
|
||||
struct n64_instrument *n64_instrument = (struct n64_instrument *) &src[srcpos];
|
||||
ALInstrument *host_instrument = (ALInstrument *) &dst[dstpos];
|
||||
const s16 soundCount = PD_BE16(n64_instrument->soundCount);
|
||||
|
||||
host_instrument->volume = n64_instrument->volume;
|
||||
host_instrument->pan = n64_instrument->pan;
|
||||
host_instrument->priority = n64_instrument->priority;
|
||||
host_instrument->flags = n64_instrument->flags;
|
||||
host_instrument->tremType = n64_instrument->tremType;
|
||||
host_instrument->tremRate = n64_instrument->tremRate;
|
||||
host_instrument->tremDepth = n64_instrument->tremDepth;
|
||||
host_instrument->tremDelay = n64_instrument->tremDelay;
|
||||
host_instrument->vibType = n64_instrument->vibType;
|
||||
host_instrument->vibRate = n64_instrument->vibRate;
|
||||
host_instrument->vibDepth = n64_instrument->vibDepth;
|
||||
host_instrument->vibDelay = n64_instrument->vibDelay;
|
||||
host_instrument->bendRange = PD_BE16(n64_instrument->bendRange);
|
||||
host_instrument->soundCount = (soundCount);
|
||||
|
||||
dstpos = dstpos + sizeof(ALInstrument) + sizeof(uintptr_t) * (soundCount - 1);
|
||||
|
||||
for (int i = 0; i < soundCount; i++) {
|
||||
srcpos = PD_BE32(n64_instrument->soundArray[i]);
|
||||
AL_NEXT_ITEM(host_instrument->soundArray[i], convertAudioSound);
|
||||
}
|
||||
|
||||
return dstpos;
|
||||
}
|
||||
|
||||
static u32 convertAudioBank(u8 *dst, u32 dstpos, u8 *src, u32 srcpos)
|
||||
{
|
||||
struct n64_bank *n64_bank = (struct n64_bank *) &src[srcpos];
|
||||
ALBank *host_bank = (ALBank *) &dst[dstpos];
|
||||
const s16 instCount = PD_BE16(n64_bank->instCount);
|
||||
|
||||
host_bank->instCount = (instCount);
|
||||
host_bank->flags = n64_bank->flags;
|
||||
host_bank->pad = n64_bank->pad;
|
||||
host_bank->sampleRate = PD_BE32(n64_bank->sampleRate);
|
||||
|
||||
dstpos = dstpos + sizeof(ALBank) + sizeof(uintptr_t) * (instCount - 1);
|
||||
|
||||
if (n64_bank->percussion) {
|
||||
srcpos = PD_BE32(n64_bank->percussion);
|
||||
AL_NEXT_ITEM(host_bank->percussion, convertAudioInstrument);
|
||||
} else {
|
||||
host_bank->percussion = 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < instCount; i++) {
|
||||
srcpos = PD_BE32(n64_bank->instArray[i]);
|
||||
AL_NEXT_ITEM(host_bank->instArray[i], convertAudioInstrument);
|
||||
}
|
||||
|
||||
return dstpos;
|
||||
}
|
||||
|
||||
static u32 convertAudioBankFile(u8 *dst, u8 *src)
|
||||
{
|
||||
struct n64_bankfile *n64_bankfile = (struct n64_bankfile *)src;
|
||||
ALBankFile *host_bankfile = (ALBankFile *)dst;
|
||||
const s16 bankCount = PD_BE16(n64_bankfile->bankCount);
|
||||
|
||||
host_bankfile->revision = PD_BE16(n64_bankfile->revision);
|
||||
host_bankfile->bankCount = (bankCount);
|
||||
|
||||
u32 dstpos = sizeof(ALBankFile) + sizeof(uintptr_t) * (bankCount - 1);
|
||||
|
||||
for (int i = 0; i < bankCount; i++) {
|
||||
host_bankfile->bankArray[i] = (void *)(uintptr_t)(dstpos);
|
||||
u32 srcpos = PD_BE32(n64_bankfile->bankArray[i]);
|
||||
dstpos = convertAudioBank(dst, dstpos, src, srcpos);
|
||||
}
|
||||
|
||||
return dstpos;
|
||||
}
|
||||
|
||||
u8 *preprocessALBankFile(u8 *src, u32 size, u32 *outSize)
|
||||
{
|
||||
ptrReset();
|
||||
|
||||
const u32 dstlen = size * 3; // this should overshoot any possible bank size, but * 2 also works for vanilla banks
|
||||
u8 *dst = sysMemZeroAlloc(dstlen);
|
||||
|
||||
u32 reallen = convertAudioBankFile(dst, src);
|
||||
if (reallen > dstlen || ALIGN16(reallen) > dstlen) {
|
||||
sysFatalError("overflow when trying to preprocess an ALBankFile, size %u dstlen %u reallen %u", size, dstlen, reallen);
|
||||
}
|
||||
|
||||
reallen = ALIGN16(reallen);
|
||||
|
||||
if (reallen < dstlen) {
|
||||
dst = sysMemRealloc(dst, reallen);
|
||||
}
|
||||
|
||||
*outSize = reallen;
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
|
||||
u8 *preprocessALCMidiHdr(u8 *data, u32 size, u32 *outSize)
|
||||
{
|
||||
ALCMidiHdr *hdr = (ALCMidiHdr *)data;
|
||||
PD_SWAP_VAL(hdr->division);
|
||||
for (s32 i = 0; i < ARRAYCOUNT(hdr->trackOffset); ++i) {
|
||||
PD_SWAP_VAL(hdr->trackOffset[i]);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
u8 *preprocessSequences(u8* data, u32 size, u32 *outSize)
|
||||
{
|
||||
struct seqtable *seq = (struct seqtable *)data;
|
||||
PD_SWAP_VAL(seq->count);
|
||||
|
||||
for (s16 i = 0; i < seq->count; ++i) {
|
||||
PD_SWAP_VAL(seq->entries[i].binlen);
|
||||
PD_SWAP_VAL(seq->entries[i].ziplen);
|
||||
PD_SWAP_VAL(seq->entries[i].romaddr);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -1,104 +0,0 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "preprocess/common.h"
|
||||
|
||||
struct n64_fontchar {
|
||||
u8 index;
|
||||
s8 baseline;
|
||||
u8 height;
|
||||
u8 width;
|
||||
s32 kerningindex;
|
||||
u32 pixeldata;
|
||||
};
|
||||
|
||||
struct n64_fontcharjpn {
|
||||
u16 index;
|
||||
s8 baseline;
|
||||
u8 height;
|
||||
u8 width;
|
||||
s16 kerningindex;
|
||||
u32 pixeldata;
|
||||
};
|
||||
|
||||
u8 *preprocessFont(u8 *src, u32 srclen, u32 *outSize)
|
||||
{
|
||||
int num_chars = 94;
|
||||
#if VERSION == VERSION_PAL_FINAL
|
||||
// PAL has more characters in these fonts
|
||||
extern u8* _fonthandelgothicsmSegmentRomStart;
|
||||
extern u8* _fonthandelgothicxsSegmentRomStart;
|
||||
extern u8* _fonthandelgothicmdSegmentRomStart;
|
||||
if (src == _fonthandelgothicsmSegmentRomStart
|
||||
|| src == _fonthandelgothicxsSegmentRomStart
|
||||
|| src == _fonthandelgothicmdSegmentRomStart) {
|
||||
num_chars = 135;
|
||||
}
|
||||
#endif
|
||||
|
||||
size_t dstlen = srclen - (num_chars * sizeof(struct n64_fontchar)) + (num_chars * sizeof(struct fontchar)) + 0x20;
|
||||
u8* dst = sysMemZeroAlloc(dstlen);
|
||||
|
||||
// Kerning table
|
||||
s32 *src_kerning_table = (s32 *)src;
|
||||
s32 *dst_kerning_table = (s32 *)dst;
|
||||
|
||||
for (int i = 0; i < 13 * 13; i++) {
|
||||
dst_kerning_table[i] = PD_BE32(src_kerning_table[i]);
|
||||
}
|
||||
|
||||
u32 src_offset = PD_ALIGN(13 * 13 * 4, sizeof(u32));
|
||||
u32 dst_offset = PD_ALIGN(13 * 13 * 4, sizeof(uintptr_t));
|
||||
|
||||
// Character table
|
||||
#if VERSION == VERSION_JPN_FINAL
|
||||
struct n64_fontcharjpn *src_char_table = (struct n64_fontcharjpn *) &src[src_offset];
|
||||
struct fontchar *dst_char_table = (struct fontchar *) &dst[dst_offset];
|
||||
u32 diff = (dst_offset + num_chars * sizeof(struct fontchar)) - (src_offset + num_chars * sizeof(struct n64_fontcharjpn));
|
||||
|
||||
for (int i = 0; i < num_chars; i++) {
|
||||
dst_char_table[i].index = PD_BE16(src_char_table[i].index);
|
||||
dst_char_table[i].baseline = src_char_table[i].baseline;
|
||||
dst_char_table[i].height = src_char_table[i].height;
|
||||
dst_char_table[i].width = src_char_table[i].width;
|
||||
dst_char_table[i].kerningindex = PD_BE16(src_char_table[i].kerningindex);
|
||||
dst_char_table[i].pixeldata = (void *)(uintptr_t)(src_char_table[i].pixeldata ? PD_BE32(src_char_table[i].pixeldata) + diff : 0);
|
||||
}
|
||||
|
||||
src_offset += num_chars * sizeof(struct n64_fontcharjpn);
|
||||
dst_offset += num_chars * sizeof(struct fontchar);
|
||||
#else
|
||||
struct n64_fontchar *src_char_table = (struct n64_fontchar *) &src[src_offset];
|
||||
struct fontchar *dst_char_table = (struct fontchar *) &dst[dst_offset];
|
||||
u32 diff = (dst_offset + num_chars * sizeof(struct fontchar)) - (src_offset + num_chars * sizeof(struct n64_fontchar));
|
||||
|
||||
for (int i = 0; i < num_chars; i++) {
|
||||
dst_char_table[i].index = src_char_table[i].index;
|
||||
dst_char_table[i].baseline = src_char_table[i].baseline;
|
||||
dst_char_table[i].height = src_char_table[i].height;
|
||||
dst_char_table[i].width = src_char_table[i].width;
|
||||
dst_char_table[i].kerningindex = PD_BE32(src_char_table[i].kerningindex);
|
||||
dst_char_table[i].pixeldata = (void *)(uintptr_t)(src_char_table[i].pixeldata ? PD_BE32(src_char_table[i].pixeldata) + diff : 0);
|
||||
}
|
||||
|
||||
src_offset += num_chars * sizeof(struct n64_fontchar);
|
||||
dst_offset += num_chars * sizeof(struct fontchar);
|
||||
#endif
|
||||
|
||||
// Pixel data
|
||||
u32 len = srclen - src_offset;
|
||||
memcpy(&dst[dst_offset], &src[src_offset], len);
|
||||
|
||||
if (outSize) *outSize = ALIGN16(dst_offset + len);
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
u8 *preprocessJpnFont(u8* data, u32 size, u32* outSize)
|
||||
{
|
||||
// ???
|
||||
return NULL;
|
||||
}
|
||||
+18
-98
@@ -4,6 +4,7 @@
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <PR/ultratypes.h>
|
||||
#include <PR/ultratypes.h>
|
||||
#include "lib/rzip.h"
|
||||
#include "romdata.h"
|
||||
#include "fs.h"
|
||||
@@ -50,15 +51,12 @@
|
||||
|
||||
#define ROMDATA_MAX_FILES 2048
|
||||
|
||||
#define GBC_ROM_NAME "pd.gbc"
|
||||
#define GBC_ROM_SIZE 4194304
|
||||
|
||||
u8 *g_RomFile;
|
||||
u32 g_RomFileSize;
|
||||
const char *g_RomName = ROMDATA_ROM_NAME;
|
||||
|
||||
static u8 *romDataSeg;
|
||||
static u32 romDataSegSize;
|
||||
static const char *romName = ROMDATA_ROM_NAME;
|
||||
|
||||
enum loadsource {
|
||||
SRC_UNLOADED = 0,
|
||||
@@ -190,12 +188,12 @@ static inline void romdataWrongRomError(const char *fmt, ...)
|
||||
|
||||
static inline void romdataLoadRom(void)
|
||||
{
|
||||
sysLogPrintf(LOG_NOTE, "ROM file: %s", romName);
|
||||
sysLogPrintf(LOG_NOTE, "ROM file: %s", g_RomName);
|
||||
|
||||
g_RomFile = fsFileLoad(romName, &g_RomFileSize);
|
||||
g_RomFile = fsFileLoad(g_RomName, &g_RomFileSize);
|
||||
|
||||
if (!g_RomFile) {
|
||||
sysFatalError("Could not open ROM file %s.\nEnsure that it is in the %s directory.", romName, fsFullPath(""));
|
||||
sysFatalError("Could not open ROM file %s.\nEnsure that it is in the %s directory.", g_RomName, fsFullPath(""));
|
||||
}
|
||||
|
||||
// zips are not guaranteed to start with PK, but might as well at least try
|
||||
@@ -238,17 +236,6 @@ static inline void romdataLoadRom(void)
|
||||
romDataSegSize = dataSegLen;
|
||||
}
|
||||
|
||||
static inline void romdataUpdateSegStartEnd(struct romfile* seg)
|
||||
{
|
||||
if (seg->segstart) {
|
||||
*seg->segstart = seg->data;
|
||||
}
|
||||
|
||||
if (seg->segend) {
|
||||
*seg->segend = seg->data + seg->size;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void romdataInitSegment(struct romfile *seg)
|
||||
{
|
||||
if (!seg->data) {
|
||||
@@ -264,7 +251,7 @@ static inline void romdataInitSegment(struct romfile *seg)
|
||||
seg->size = seg[1].data - seg->data;
|
||||
} else {
|
||||
// this is the last segment, calculate based on rom size
|
||||
seg->size = (uintptr_t)g_RomFileSize - (uintptr_t)seg->data;
|
||||
seg->size = (u8 *)g_RomFileSize - seg->data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,7 +269,7 @@ static inline void romdataInitSegment(struct romfile *seg)
|
||||
if (g_RomFile) {
|
||||
newData = g_RomFile + (uintptr_t)seg->data;
|
||||
seg->source = SRC_ROM;
|
||||
sysLogPrintf(LOG_NOTE, "loading segment %s from ROM (offset %08x pointer %p)", seg->name, (uintptr_t)seg->data, newData);
|
||||
sysLogPrintf(LOG_NOTE, "loading segment %s from ROM (offset %08x pointer %p)", seg->name, (u32)seg->data, newData);
|
||||
} else {
|
||||
sysFatalError("No ROM or external file for segment:\n%s", seg->name);
|
||||
}
|
||||
@@ -294,19 +281,17 @@ static inline void romdataInitSegment(struct romfile *seg)
|
||||
|
||||
seg->data = newData;
|
||||
|
||||
romdataUpdateSegStartEnd(seg);
|
||||
if (seg->segstart) {
|
||||
*seg->segstart = seg->data;
|
||||
}
|
||||
|
||||
if (seg->segend) {
|
||||
*seg->segend = seg->data + seg->size;
|
||||
}
|
||||
|
||||
// call the post load function if any
|
||||
if (seg->preprocess && !seg->preprocessed) {
|
||||
newData = seg->preprocess(seg->data, seg->size, &seg->size);
|
||||
|
||||
if (newData) {
|
||||
if (seg->source == SRC_EXTERNAL)
|
||||
sysMemFree(seg->data);
|
||||
seg->data = newData;
|
||||
romdataUpdateSegStartEnd(seg);
|
||||
}
|
||||
|
||||
seg->preprocess(seg->data, seg->size);
|
||||
seg->preprocessed = 1;
|
||||
}
|
||||
}
|
||||
@@ -383,7 +368,7 @@ s32 romdataInit(void)
|
||||
{
|
||||
const char *altRomName = sysArgGetString("--rom-file");
|
||||
if (altRomName) {
|
||||
romName = altRomName;
|
||||
g_RomName = altRomName;
|
||||
}
|
||||
|
||||
romdataLoadRom();
|
||||
@@ -401,53 +386,6 @@ s32 romdataInit(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline bool romdataCheckGbcRomContents(const u8 *gbcRomFile, const u32 gbcRomSize)
|
||||
{
|
||||
if (gbcRomSize != GBC_ROM_SIZE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// ROM title
|
||||
if (memcmp(gbcRomFile + 0x134, "PerfDark VPDE", 15) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Licensee code
|
||||
if (memcmp(gbcRomFile + 0x144, "4Y", 2) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Header and global checksums
|
||||
if (gbcRomFile[0x14D] != 0xA1 || gbcRomFile[0x14E] != 0xAD || gbcRomFile[0x14F] != 0x0F) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
s32 romdataCheckGbcRom(void)
|
||||
{
|
||||
if (fsFileSize(GBC_ROM_NAME) < 0) {
|
||||
// bail early if it doesn't exist to avoid generating error messages
|
||||
return false;
|
||||
}
|
||||
|
||||
u32 gbcRomSize = 0;
|
||||
u8 *gbcRomFile = fsFileLoad(GBC_ROM_NAME, &gbcRomSize);
|
||||
if (!gbcRomFile) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool ret = romdataCheckGbcRomContents(gbcRomFile, gbcRomSize);
|
||||
sysMemFree(gbcRomFile);
|
||||
|
||||
if (ret) {
|
||||
sysLogPrintf(LOG_NOTE, "romdataCheckGbcRom: valid GBC rom found");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
s32 romdataFileGetSize(s32 fileNum)
|
||||
{
|
||||
if (fileNum < 1 || fileNum >= ROMDATA_MAX_FILES) {
|
||||
@@ -509,7 +447,7 @@ u8 *romdataFileLoad(s32 fileNum, u32 *outSize)
|
||||
return out;
|
||||
}
|
||||
|
||||
void romdataFilePreprocess(s32 fileNum, s32 loadType, u8 *data, u32 size, u32 *outSize)
|
||||
void romdataFilePreprocess(s32 fileNum, s32 loadType, u8 *data, u32 size)
|
||||
{
|
||||
if (fileNum < 1 || fileNum >= ROMDATA_MAX_FILES) {
|
||||
sysLogPrintf(LOG_ERROR, "romdataFilePreprocess: invalid file num %d", fileNum);
|
||||
@@ -527,7 +465,7 @@ void romdataFilePreprocess(s32 fileNum, s32 loadType, u8 *data, u32 size, u32 *o
|
||||
}
|
||||
}
|
||||
// then preprocess
|
||||
filePreprocFuncs[loadType](data, size, outSize);
|
||||
filePreprocFuncs[loadType](data, size);
|
||||
// fileSlots[fileNum].preprocessed = 1;
|
||||
}
|
||||
}
|
||||
@@ -586,21 +524,3 @@ u32 romdataSegGetSize(const char *segName)
|
||||
{
|
||||
return romdataGetSeg(segName)->size;
|
||||
}
|
||||
|
||||
u32 romdataFileGetEstimatedSize(const u32 size, const u32 loadtype)
|
||||
{
|
||||
#ifdef PLATFORM_64BIT
|
||||
switch (loadtype) {
|
||||
case LOADTYPE_BG: return (u32)(size * 1.1f);
|
||||
case LOADTYPE_TILES: return (u32)(size * 1.1f);
|
||||
case LOADTYPE_LANG: return (u32)(size * 1.3f);
|
||||
case LOADTYPE_SETUP: return (u32)(size * 1.5f);
|
||||
case LOADTYPE_PADS: return (u32)(size * 1.7f);
|
||||
case LOADTYPE_MODEL: return (u32)(size * 1.7f);
|
||||
case LOADTYPE_GUN: return (u32)(size * 1.7f);
|
||||
default:
|
||||
sysLogPrintf(LOG_WARNING, "romdataFileGetEstimatedSize: wrong loadtype %d", loadtype);
|
||||
}
|
||||
#endif
|
||||
return size;
|
||||
}
|
||||
+15
-8
@@ -12,6 +12,7 @@
|
||||
#include <SDL.h>
|
||||
#include <PR/ultratypes.h>
|
||||
#include "platform.h"
|
||||
#include "console.h"
|
||||
#include "system.h"
|
||||
|
||||
#ifdef PLATFORM_WIN32
|
||||
@@ -40,7 +41,7 @@ __attribute__((dllexport)) u32 AmdPowerXpressRequestHighPerformance = 1;
|
||||
// but if it doesn't we'll have to use __builtin_ia32_pause() or something
|
||||
#include <immintrin.h>
|
||||
#define DO_YIELD() _mm_pause()
|
||||
#elif defined(PLATFORM_ARM) && (defined(PLATFORM_64BIT) || PLATFORM_ARM == 7 || PLATFORM_ARM == 8)
|
||||
#elif defined(PLATFORM_ARM)
|
||||
// same as YieldProcessor() on ARM Windows
|
||||
#define DO_YIELD() __asm__ volatile("dmb ishst\n\tyield":::"memory")
|
||||
#else
|
||||
@@ -157,6 +158,12 @@ u64 sysGetMicroseconds(void)
|
||||
return ((u64)tv.tv_sec * USEC_IN_SEC + (u64)tv.tv_usec) - startTick;
|
||||
}
|
||||
|
||||
float sysGetSeconds(void)
|
||||
{
|
||||
u64 t = sysGetMicroseconds();
|
||||
return (f32)t / 1000000.f;
|
||||
}
|
||||
|
||||
s32 sysLogIsOpen(void)
|
||||
{
|
||||
return (logPath[0] != '\0');
|
||||
@@ -183,8 +190,13 @@ void sysLogPrintf(s32 level, const char *fmt, ...)
|
||||
}
|
||||
}
|
||||
|
||||
FILE *fout = (level == LOG_NOTE) ? stdout : stderr;
|
||||
fprintf(fout, "%s%s\n", prefix[level], logmsg);
|
||||
FILE *fout = ((level & 0x0f) == LOG_NOTE) ? stdout : stderr;
|
||||
fprintf(fout, "%s%s\n", prefix[level & 0x0f], logmsg);
|
||||
fflush(fout);
|
||||
|
||||
if ((level & LOGFLAG_NOCON) == 0) {
|
||||
conPrintLn((level & LOGFLAG_SHOWMSG) != 0, logmsg);
|
||||
}
|
||||
}
|
||||
|
||||
void sysFatalError(const char *fmt, ...)
|
||||
@@ -288,11 +300,6 @@ void *sysMemZeroAlloc(const u32 size)
|
||||
return calloc(1, size);
|
||||
}
|
||||
|
||||
void *sysMemRealloc(void *ptr, const u32 newSize)
|
||||
{
|
||||
return realloc(ptr, newSize);
|
||||
}
|
||||
|
||||
void sysMemFree(void *ptr)
|
||||
{
|
||||
free(ptr);
|
||||
|
||||
+30
-318
@@ -6,68 +6,36 @@
|
||||
#include <PR/gbi.h>
|
||||
#include "platform.h"
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
#include "video.h"
|
||||
|
||||
#include "../fast3d/gfx_api.h"
|
||||
#include "../fast3d/gfx_sdl.h"
|
||||
#include "../fast3d/gfx_opengl.h"
|
||||
|
||||
#ifdef PLATFORM_NSWITCH
|
||||
#define DEFAULT_VID_WIDTH 1280
|
||||
#define DEFAULT_VID_HEIGHT 720
|
||||
#define DEFAULT_VID_FULLSCREEN true
|
||||
#define DEFAULT_VID_FULLSCREEN_EXCLUSIVE true
|
||||
#else
|
||||
#define DEFAULT_VID_WIDTH 640
|
||||
#define DEFAULT_VID_HEIGHT 480
|
||||
#define DEFAULT_VID_FULLSCREEN false
|
||||
#define DEFAULT_VID_FULLSCREEN_EXCLUSIVE false
|
||||
#endif
|
||||
|
||||
static struct GfxWindowManagerAPI *wmAPI;
|
||||
static struct GfxRenderingAPI *renderingAPI;
|
||||
|
||||
static bool initDone = false;
|
||||
|
||||
static s32 vidWidth = DEFAULT_VID_WIDTH;
|
||||
static s32 vidHeight = DEFAULT_VID_HEIGHT;
|
||||
static s32 vidWidth = 640;
|
||||
static s32 vidHeight = 480;
|
||||
static s32 vidFramebuffers = true;
|
||||
static s32 vidFullscreen = DEFAULT_VID_FULLSCREEN;
|
||||
static s32 vidFullscreenExclusive = DEFAULT_VID_FULLSCREEN_EXCLUSIVE;
|
||||
static s32 vidFullscreen = false;
|
||||
static s32 vidFullscreenExclusive = false;
|
||||
static s32 vidMaximize = false;
|
||||
static s32 vidCenter = false;
|
||||
static s32 vidAllowHiDpi = false;
|
||||
static s32 vidVsync = 1;
|
||||
static s32 vidMSAA = 1;
|
||||
static s32 vidFramerateLimit = 0;
|
||||
|
||||
static s32 vidDisplayFPS = 0;
|
||||
static f32 vidDisplayFPSInterval = 1.f;
|
||||
static f32 vidAvgFPS = 0;
|
||||
|
||||
static s32 vidNumModes = 1;
|
||||
static displaymode vidModeDefault;
|
||||
static displaymode *vidModes = &vidModeDefault;
|
||||
|
||||
static f32 vidGlareBrightness = 1.f;
|
||||
static f32 vidOverexposureScale = 1.f;
|
||||
|
||||
static s32 texFilter = FILTER_LINEAR;
|
||||
static s32 texFilter2D = true;
|
||||
static s32 texDetail = false;
|
||||
static s32 texMipmapFilter = MIPMAP_LINEAR;
|
||||
static u32 texAnisotropicFilter = 4;
|
||||
static s32 texDetail = true;
|
||||
|
||||
static u32 dlcount = 0;
|
||||
static u32 frames = 0;
|
||||
static f64 startTime, endTime;
|
||||
static f64 accumDelta = 0.0;
|
||||
static f64 fpsTime = 0.0;
|
||||
static s32 fpsNumFrames = 0;
|
||||
|
||||
static s32 videoInitDisplayModes(void);
|
||||
void optionsMenuInit();
|
||||
static u32 framesPerSec = 0;
|
||||
static f64 startTime, endTime, fpsTime;
|
||||
|
||||
s32 videoInit(void)
|
||||
{
|
||||
@@ -93,21 +61,23 @@ s32 videoInit(void)
|
||||
.fullscreen = vidFullscreen,
|
||||
.fullscreen_is_exclusive = vidFullscreenExclusive,
|
||||
.maximized = vidMaximize,
|
||||
.centered = vidCenter,
|
||||
.allow_hidpi = vidAllowHiDpi
|
||||
}
|
||||
};
|
||||
|
||||
gfx_init(&set);
|
||||
|
||||
videoInitDisplayModes();
|
||||
videoSetVsync(vidVsync);
|
||||
videoSetFramerateLimit(vidFramerateLimit);
|
||||
if (!wmAPI->set_swap_interval(vidVsync)) {
|
||||
vidVsync = 0;
|
||||
}
|
||||
|
||||
gfx_set_texture_filter((enum FilteringMode)texFilter);
|
||||
gfx_set_mipmap_filter((enum MipmapFilteringMode)texMipmapFilter);
|
||||
videoSetAnisotropicFilter(texAnisotropicFilter);
|
||||
optionsMenuInit();
|
||||
if (vidVsync == 0 && vidFramerateLimit == 0) {
|
||||
// cap FPS if there's no vsync to prevent the game from exploding
|
||||
vidFramerateLimit = VIDEO_MAX_FPS;
|
||||
}
|
||||
|
||||
wmAPI->set_target_fps(vidFramerateLimit); // disabled because vsync is on
|
||||
renderingAPI->set_texture_filter((enum FilteringMode)texFilter);
|
||||
|
||||
initDone = true;
|
||||
return 0;
|
||||
@@ -119,10 +89,6 @@ void videoStartFrame(void)
|
||||
startTime = wmAPI->get_time();
|
||||
gfx_start_frame();
|
||||
}
|
||||
|
||||
// Synchronize with their backend counterparts.
|
||||
vidFullscreen = videoGetFullscreen();
|
||||
vidMaximize = videoGetMaximizeWindow();
|
||||
}
|
||||
|
||||
void videoSubmitCommands(Gfx *cmds)
|
||||
@@ -141,29 +107,20 @@ void videoEndFrame(void)
|
||||
|
||||
gfx_end_frame();
|
||||
|
||||
++frames;
|
||||
++fpsNumFrames;
|
||||
endTime = wmAPI->get_time();
|
||||
|
||||
const f64 flipTime = wmAPI->get_time();
|
||||
accumDelta += flipTime - endTime;
|
||||
endTime = flipTime;
|
||||
++frames;
|
||||
++framesPerSec;
|
||||
|
||||
if (endTime >= fpsTime) {
|
||||
char tmp[128];
|
||||
vidAvgFPS = fpsNumFrames ? ((f64)fpsNumFrames / accumDelta) : 0.f;
|
||||
fpsNumFrames = 0;
|
||||
accumDelta = 0.0;
|
||||
fpsTime = endTime + vidDisplayFPSInterval;
|
||||
snprintf(tmp, sizeof(tmp), "fps %3u frt %lf frm %u", framesPerSec, endTime - startTime, frames);
|
||||
wmAPI->set_window_title(tmp);
|
||||
framesPerSec = 0;
|
||||
fpsTime = endTime + 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
f32 videoGetAverageFPS(void)
|
||||
{
|
||||
return vidAvgFPS;
|
||||
}
|
||||
|
||||
void videoClearScreen(void)
|
||||
{
|
||||
videoStartFrame();
|
||||
@@ -208,159 +165,19 @@ s32 videoGetHeight(void)
|
||||
|
||||
s32 videoGetFullscreen(void)
|
||||
{
|
||||
vidFullscreen = wmAPI->get_fullscreen_state();
|
||||
return vidFullscreen;
|
||||
}
|
||||
|
||||
s32 videoGetFullscreenMode(void)
|
||||
{
|
||||
vidFullscreenExclusive = wmAPI->get_fullscreen_flag_mode();
|
||||
return vidFullscreenExclusive;
|
||||
}
|
||||
|
||||
s32 videoGetMaximizeWindow(void)
|
||||
{
|
||||
vidMaximize = wmAPI->get_maximized_state();
|
||||
return vidMaximize;
|
||||
}
|
||||
|
||||
s32 videoGetCenterWindow(void)
|
||||
{
|
||||
return vidCenter;
|
||||
}
|
||||
|
||||
f32 videoGetAspect(void)
|
||||
{
|
||||
return gfx_current_dimensions.aspect_ratio;
|
||||
}
|
||||
|
||||
s32 videoGetDisplayModeIndex(void)
|
||||
{
|
||||
for (s32 i = 1; i < vidNumModes; ++i) {
|
||||
if (vidModes[i].width == gfx_current_dimensions.width &&
|
||||
vidModes[i].height == gfx_current_dimensions.height) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
// Current dimensions don't match any known mode, so return index 0, "Custom".
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 videoGetMSAA(void)
|
||||
{
|
||||
vidMSAA = (s32)gfx_msaa_level;
|
||||
return vidMSAA;
|
||||
}
|
||||
|
||||
s32 videoGetVsync(void)
|
||||
{
|
||||
vidVsync = wmAPI->get_swap_interval();
|
||||
return vidVsync;
|
||||
}
|
||||
|
||||
s32 videoGetFramerateLimit(void)
|
||||
{
|
||||
vidFramerateLimit = wmAPI->get_target_fps();
|
||||
return vidFramerateLimit;
|
||||
}
|
||||
|
||||
s32 videoGetDisplayFPS(void)
|
||||
{
|
||||
return vidDisplayFPS;
|
||||
}
|
||||
|
||||
static s32 videoInitDisplayModes(void)
|
||||
{
|
||||
if (!wmAPI->get_current_display_mode(&vidModeDefault.width, &vidModeDefault.height)) {
|
||||
vidModeDefault.width = 640;
|
||||
vidModeDefault.height = 480;
|
||||
return false;
|
||||
}
|
||||
|
||||
const s32 numBaseModes = wmAPI->get_num_display_modes();
|
||||
if (!numBaseModes) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const s32 numCustomModes = 1;
|
||||
displaymode *modeList = sysMemZeroAlloc((numBaseModes + numCustomModes) * sizeof(displaymode));
|
||||
if (!modeList) {
|
||||
return false;
|
||||
}
|
||||
|
||||
modeList[0].width = 0;
|
||||
modeList[0].height = 0;
|
||||
|
||||
s32 numModes = 1;
|
||||
s32 w = -1, h = w, neww = w, newh = w;
|
||||
|
||||
// SDL modes are guaranteed to be sorted high to low
|
||||
for (s32 i = 0; i < numBaseModes; ++i) {
|
||||
wmAPI->get_display_mode(i, &neww, &newh);
|
||||
|
||||
if (neww != w || newh != h) {
|
||||
w = neww;
|
||||
h = newh;
|
||||
modeList[numModes].width = w;
|
||||
modeList[numModes].height = h;
|
||||
++numModes;
|
||||
}
|
||||
}
|
||||
|
||||
modeList = sysMemRealloc(modeList, numModes * sizeof(displaymode));
|
||||
if (!modeList) {
|
||||
return false;
|
||||
}
|
||||
|
||||
vidModes = modeList;
|
||||
vidNumModes = numModes;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
s32 videoGetDisplayMode(displaymode *out, const s32 index)
|
||||
{
|
||||
if (index >= 0 && index < vidNumModes) {
|
||||
*out = vidModes[index];
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
s32 videoGetNumDisplayModes(void)
|
||||
{
|
||||
return vidNumModes;
|
||||
}
|
||||
|
||||
void videoSetDisplayMode(const s32 index)
|
||||
{
|
||||
const displaymode dm = vidModes[index];
|
||||
|
||||
if (index == 0) {
|
||||
// "Custom" video mode.
|
||||
return;
|
||||
}
|
||||
|
||||
vidWidth = dm.width;
|
||||
vidHeight = dm.height;
|
||||
|
||||
s32 posX = 100;
|
||||
s32 posY = 100;
|
||||
if (vidCenter) {
|
||||
wmAPI->get_centered_positions(vidWidth, vidHeight, &posX, &posY);
|
||||
}
|
||||
|
||||
if (vidFullscreen) {
|
||||
wmAPI->set_closest_resolution(vidWidth, vidHeight, vidCenter);
|
||||
} else {
|
||||
if (vidMaximize) {
|
||||
videoSetMaximizeWindow(false);
|
||||
} else {
|
||||
wmAPI->set_dimensions(vidWidth, vidHeight, posX, posY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s32 videoGetTextureFilter2D(void)
|
||||
{
|
||||
return texFilter2D;
|
||||
@@ -371,31 +188,11 @@ u32 videoGetTextureFilter(void)
|
||||
return texFilter;
|
||||
}
|
||||
|
||||
u32 videoGetAnisotropicFilter()
|
||||
{
|
||||
return texAnisotropicFilter;
|
||||
}
|
||||
|
||||
u32 videoGetMaxAnisotropyLevel()
|
||||
{
|
||||
return renderingAPI->get_max_anisotropy_level();
|
||||
}
|
||||
|
||||
s32 videoGetDetailTextures(void)
|
||||
{
|
||||
return texDetail;
|
||||
}
|
||||
|
||||
f32 videoGetGlareBrightness(void)
|
||||
{
|
||||
return vidGlareBrightness;
|
||||
}
|
||||
|
||||
f32 videoGetOverexposureScale(void)
|
||||
{
|
||||
return vidOverexposureScale;
|
||||
}
|
||||
|
||||
void videoSetWindowOffset(s32 x, s32 y)
|
||||
{
|
||||
gfx_current_game_window_viewport.x = x;
|
||||
@@ -406,22 +203,7 @@ void videoSetFullscreen(s32 fs)
|
||||
{
|
||||
if (fs != vidFullscreen) {
|
||||
vidFullscreen = !!fs;
|
||||
wmAPI->set_closest_resolution(vidWidth, vidHeight, vidCenter);
|
||||
wmAPI->set_fullscreen(vidFullscreen);
|
||||
if (!vidFullscreen && vidMaximize) {
|
||||
wmAPI->set_maximize(false);
|
||||
wmAPI->set_maximize(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void videoSetFullscreenMode(s32 mode)
|
||||
{
|
||||
vidFullscreenExclusive = mode;
|
||||
wmAPI->set_fullscreen_flag(mode);
|
||||
if (vidFullscreen) {
|
||||
wmAPI->set_fullscreen(false);
|
||||
wmAPI->set_fullscreen(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -430,32 +212,14 @@ void videoSetMaximizeWindow(s32 fs)
|
||||
if (fs != vidMaximize) {
|
||||
vidMaximize = !!fs;
|
||||
wmAPI->set_maximize(vidMaximize);
|
||||
if (vidCenter && !vidMaximize) {
|
||||
s32 posX = 0;
|
||||
s32 posY = 0;
|
||||
wmAPI->get_centered_positions(vidWidth, vidHeight, &posX, &posY);
|
||||
wmAPI->set_dimensions(vidWidth, vidHeight, posX, posY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void videoSetCenterWindow(s32 center)
|
||||
{
|
||||
vidCenter = center;
|
||||
if (vidCenter && !vidMaximize) {
|
||||
s32 posX = 0;
|
||||
s32 posY = 0;
|
||||
wmAPI->get_centered_positions(vidWidth, vidHeight, &posX, &posY);
|
||||
wmAPI->set_dimensions(vidWidth, vidHeight, posX, posY);
|
||||
}
|
||||
}
|
||||
|
||||
void videoSetTextureFilter(u32 filter)
|
||||
{
|
||||
if (filter > FILTER_THREE_POINT) filter = FILTER_THREE_POINT;
|
||||
if (texFilter == filter) return;
|
||||
texFilter = filter;
|
||||
gfx_set_texture_filter((enum FilteringMode)filter);
|
||||
renderingAPI->set_texture_filter((enum FilteringMode)filter);
|
||||
}
|
||||
|
||||
void videoSetTextureFilter2D(s32 filter)
|
||||
@@ -463,26 +227,18 @@ void videoSetTextureFilter2D(s32 filter)
|
||||
texFilter2D = !!filter;
|
||||
}
|
||||
|
||||
void videoSetAnisotropicFilter(u32 level)
|
||||
{
|
||||
texAnisotropicFilter = level;
|
||||
renderingAPI->set_anisotropy_level(level);
|
||||
}
|
||||
|
||||
void videoSetDetailTextures(s32 detail)
|
||||
{
|
||||
texDetail = !!detail;
|
||||
gfx_detail_textures_enabled = (bool)texDetail;
|
||||
}
|
||||
|
||||
void videoSetGlareBrightness(f32 bright)
|
||||
void videoCapFramerate(s32 limit)
|
||||
{
|
||||
vidGlareBrightness = (bright < 0.f ? 0.f : (bright > 1.f ? 1.f : bright));
|
||||
}
|
||||
|
||||
void videoSetOverexposureScale(f32 scale)
|
||||
{
|
||||
vidOverexposureScale = (scale < 0.f ? 0.f : (scale > 1.f ? 1.f : scale));
|
||||
if (vidFramerateLimit > 0 && vidFramerateLimit < limit) {
|
||||
limit = vidFramerateLimit;
|
||||
}
|
||||
wmAPI->set_target_fps(limit ? limit : vidFramerateLimit);
|
||||
}
|
||||
|
||||
s32 videoCreateFramebuffer(u32 w, u32 h, s32 upscale, s32 autoresize)
|
||||
@@ -490,33 +246,6 @@ s32 videoCreateFramebuffer(u32 w, u32 h, s32 upscale, s32 autoresize)
|
||||
return gfx_create_framebuffer(w, h, upscale, autoresize);
|
||||
}
|
||||
|
||||
void videoSetMSAA(const s32 msaa)
|
||||
{
|
||||
vidMSAA = msaa;
|
||||
gfx_msaa_level = (u32)vidMSAA;
|
||||
}
|
||||
|
||||
void videoSetVsync(const s32 vsync)
|
||||
{
|
||||
vidVsync = wmAPI->set_swap_interval(vsync) ? vsync : 0;
|
||||
|
||||
if (vidVsync == 0 && vidFramerateLimit == 0) {
|
||||
// cap FPS if there's no vsync to prevent the game from exploding
|
||||
videoSetFramerateLimit(VIDEO_MAX_FPS);
|
||||
}
|
||||
}
|
||||
|
||||
void videoSetFramerateLimit(const s32 limit)
|
||||
{
|
||||
vidFramerateLimit = (vidVsync == 0 && limit == 0) ? VIDEO_MAX_FPS : limit;
|
||||
wmAPI->set_target_fps(vidFramerateLimit);
|
||||
}
|
||||
|
||||
void videoSetDisplayFPS(const s32 displayfps)
|
||||
{
|
||||
vidDisplayFPS = displayfps;
|
||||
}
|
||||
|
||||
void videoSetFramebuffer(s32 target)
|
||||
{
|
||||
return gfx_set_framebuffer(target, 1.f);
|
||||
@@ -553,16 +282,6 @@ void videoFreeCachedTexture(const void *texptr)
|
||||
gfx_texture_cache_delete(texptr);
|
||||
}
|
||||
|
||||
void videoFreeCachedTextures(const void *start, const void *end)
|
||||
{
|
||||
gfx_texture_cache_delete_range(start, end);
|
||||
}
|
||||
|
||||
void videoShutdown(void)
|
||||
{
|
||||
free(vidModes);
|
||||
}
|
||||
|
||||
PD_CONSTRUCTOR static void videoConfigInit(void)
|
||||
{
|
||||
configRegisterInt("Video.DefaultFullscreen", &vidFullscreen, 0, 1);
|
||||
@@ -570,19 +289,12 @@ PD_CONSTRUCTOR static void videoConfigInit(void)
|
||||
configRegisterInt("Video.DefaultWidth", &vidWidth, 0, 32767);
|
||||
configRegisterInt("Video.DefaultHeight", &vidHeight, 0, 32767);
|
||||
configRegisterInt("Video.ExclusiveFullscreen", &vidFullscreenExclusive, 0, 1);
|
||||
configRegisterInt("Video.CenterWindow", &vidCenter, 0, 1);
|
||||
configRegisterInt("Video.AllowHiDpi", &vidAllowHiDpi, 0, 1);
|
||||
configRegisterInt("Video.VSync", &vidVsync, -1, 10);
|
||||
configRegisterInt("Video.FramebufferEffects", &vidFramebuffers, 0, 1);
|
||||
configRegisterInt("Video.FramerateLimit", &vidFramerateLimit, 0, VIDEO_MAX_FPS);
|
||||
configRegisterInt("Video.DisplayFPS", &vidDisplayFPS, 0, 1);
|
||||
configRegisterFloat("Video.DisplayFPSInterval", &vidDisplayFPSInterval, 0.01f, 32.f);
|
||||
configRegisterInt("Video.MSAA", &vidMSAA, 1, 16);
|
||||
configRegisterInt("Video.TextureFilter", &texFilter, 0, 2);
|
||||
configRegisterInt("Video.TextureFilter2D", &texFilter2D, 0, 1);
|
||||
configRegisterInt("Video.DetailTextures", &texDetail, 0, 1);
|
||||
configRegisterInt("Video.MipmapFilter", &texMipmapFilter, 0, 2);
|
||||
configRegisterInt("Video.AnisotropicFilter", &texAnisotropicFilter, 0, 16);
|
||||
configRegisterFloat("Video.GlareBrightness", &vidGlareBrightness, 0.f, 1.f);
|
||||
configRegisterFloat("Video.OverexposureScale", &vidOverexposureScale, 0.f, 1.f);
|
||||
}
|
||||
+30
-30
@@ -26,7 +26,7 @@
|
||||
#include "data.h"
|
||||
#include "types.h"
|
||||
|
||||
struct activemenu g_AmMenus[MAX_PLAYERS];
|
||||
struct activemenu g_AmMenus[MAX_LOCAL_PLAYERS];
|
||||
struct fontchar *g_AmFont1;
|
||||
struct font *g_AmFont2;
|
||||
s32 g_AmIndex;
|
||||
@@ -177,7 +177,7 @@ MenuItemHandlerResult amPickTargetMenuList(s32 operation, struct menuitem *item,
|
||||
gdl = text0f153628(gdl);
|
||||
gdl = textRenderProjected(gdl, &x, &y, g_MpAllChrConfigPtrs[chrindex]->name, g_CharsHandelGothicSm, g_FontHandelGothicSm, colour, viGetWidth(), viGetHeight(), 0, 0);
|
||||
gdl = text0f153780(gdl);
|
||||
return (uintptr_t)gdl;
|
||||
return (s32)gdl;
|
||||
}
|
||||
case MENUOP_GETOPTIONHEIGHT:
|
||||
data->list.value = LINEHEIGHT;
|
||||
@@ -547,7 +547,7 @@ void amReset(void)
|
||||
g_AmFont1 = g_CharsHandelGothicSm;
|
||||
g_AmFont2 = g_FontHandelGothicSm;
|
||||
#else
|
||||
if (PLAYERCOUNT() >= 2) {
|
||||
if (LOCALPLAYERCOUNT() >= 2) {
|
||||
g_AmFont1 = g_CharsHandelGothicXs;
|
||||
g_AmFont2 = g_FontHandelGothicXs;
|
||||
} else {
|
||||
@@ -578,7 +578,7 @@ s16 amCalculateSlotWidth(void)
|
||||
}
|
||||
|
||||
#if VERSION >= VERSION_NTSC_1_0
|
||||
if (PLAYERCOUNT() > 1) {
|
||||
if (LOCALPLAYERCOUNT() > 1) {
|
||||
max += 3;
|
||||
} else {
|
||||
max += 4;
|
||||
@@ -762,32 +762,32 @@ void amClose(void)
|
||||
bool amIsCramped(void)
|
||||
{
|
||||
#if VERSION == VERSION_JPN_FINAL
|
||||
if (PLAYERCOUNT() >= 3 && g_AmMenus[g_AmIndex].screenindex != 1) {
|
||||
if (LOCALPLAYERCOUNT() >= 3 && g_AmMenus[g_AmIndex].screenindex != 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (IS4MB() && PLAYERCOUNT() == 2) {
|
||||
if (IS4MB() && LOCALPLAYERCOUNT() == 2) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (optionsGetScreenSplit() == SCREENSPLIT_VERTICAL
|
||||
&& PLAYERCOUNT() == 2
|
||||
&& LOCALPLAYERCOUNT() == 2
|
||||
&& g_AmMenus[g_AmIndex].screenindex != 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
#else
|
||||
return (g_AmMenus[g_AmIndex].screenindex == 0 && PLAYERCOUNT() >= 3)
|
||||
|| (IS4MB() && PLAYERCOUNT() == 2)
|
||||
|| (PLAYERCOUNT() == 2 && optionsGetScreenSplit() == SCREENSPLIT_VERTICAL);
|
||||
return (g_AmMenus[g_AmIndex].screenindex == 0 && LOCALPLAYERCOUNT() >= 3)
|
||||
|| (IS4MB() && LOCALPLAYERCOUNT() == 2)
|
||||
|| (LOCALPLAYERCOUNT() == 2 && optionsGetScreenSplit() == SCREENSPLIT_VERTICAL);
|
||||
#endif
|
||||
}
|
||||
|
||||
void amCalculateSlotPosition(s16 column, s16 row, s16 *x, s16 *y)
|
||||
{
|
||||
#if VERSION == VERSION_JPN_FINAL
|
||||
s32 playercount = PLAYERCOUNT();
|
||||
s32 playercount = LOCALPLAYERCOUNT();
|
||||
|
||||
*x = g_AmMenus[g_AmIndex].xradius * (column - 1);
|
||||
*y = (row - 1) * 50;
|
||||
@@ -841,7 +841,7 @@ void amCalculateSlotPosition(s16 column, s16 row, s16 *x, s16 *y)
|
||||
}
|
||||
}
|
||||
#elif VERSION >= VERSION_NTSC_1_0
|
||||
s32 playercount = PLAYERCOUNT();
|
||||
s32 playercount = LOCALPLAYERCOUNT();
|
||||
|
||||
*x = g_AmMenus[g_AmIndex].xradius * (column - 1);
|
||||
*y = (row - 1) * 50;
|
||||
@@ -893,7 +893,7 @@ void amCalculateSlotPosition(s16 column, s16 row, s16 *x, s16 *y)
|
||||
}
|
||||
}
|
||||
#else
|
||||
s32 playercount = PLAYERCOUNT();
|
||||
s32 playercount = LOCALPLAYERCOUNT();
|
||||
|
||||
*x = g_AmMenus[g_AmIndex].xradius * (column - 1);
|
||||
*y = (row - 1) * 50;
|
||||
@@ -973,15 +973,15 @@ Gfx *amRenderAibotInfo(Gfx *gdl, s32 buddynum)
|
||||
#endif
|
||||
|
||||
#if VERSION >= VERSION_NTSC_1_0
|
||||
if (PLAYERCOUNT() == 1 && optionsGetEffectiveScreenSize() != SCREENSIZE_FULL) {
|
||||
if (LOCALPLAYERCOUNT() == 1 && optionsGetEffectiveScreenSize() != SCREENSIZE_FULL) {
|
||||
wide = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if VERSION >= VERSION_NTSC_1_0
|
||||
if ((PLAYERCOUNT() == 2 && (optionsGetScreenSplit() == SCREENSPLIT_VERTICAL || IS4MB())) || PLAYERCOUNT() >= 3)
|
||||
if ((LOCALPLAYERCOUNT() == 2 && (optionsGetScreenSplit() == SCREENSPLIT_VERTICAL || IS4MB())) || LOCALPLAYERCOUNT() >= 3)
|
||||
#else
|
||||
if ((PLAYERCOUNT() == 2 && optionsGetScreenSplit() == SCREENSPLIT_VERTICAL) || PLAYERCOUNT() >= 3)
|
||||
if ((LOCALPLAYERCOUNT() == 2 && optionsGetScreenSplit() == SCREENSPLIT_VERTICAL) || LOCALPLAYERCOUNT() >= 3)
|
||||
#endif
|
||||
{
|
||||
if ((g_Vars.currentplayernum % 2) == 0) {
|
||||
@@ -1014,7 +1014,7 @@ Gfx *amRenderAibotInfo(Gfx *gdl, s32 buddynum)
|
||||
- (s32)(textwidth * 0.5f)
|
||||
+ offset;
|
||||
|
||||
if (PLAYERCOUNT() >= 2) {
|
||||
if (LOCALPLAYERCOUNT() >= 2) {
|
||||
y = viGetViewTop() + 5;
|
||||
} else {
|
||||
y = viGetViewTop() + 10;
|
||||
@@ -1030,12 +1030,12 @@ Gfx *amRenderAibotInfo(Gfx *gdl, s32 buddynum)
|
||||
gdl = func0f1574d0jf(gdl, &x, &y, aibotname, g_AmFont1, g_AmFont2, -1,
|
||||
0x000000ff, SCREEN_320, SCREEN_240, 0, 0);
|
||||
|
||||
y += (PLAYERCOUNT() >= 2) ? 0 : (s32)(textheight * 1.1f);
|
||||
y += (LOCALPLAYERCOUNT() >= 2) ? 0 : (s32)(textheight * 1.1f);
|
||||
#else
|
||||
gdl = textRender(gdl, &x, &y, aibotname, g_AmFont1, g_AmFont2, -1,
|
||||
0x000000ff, SCREEN_320, SCREEN_240, 0, 0);
|
||||
|
||||
y += (PLAYERCOUNT() >= 2) ? 0 : (s32)(textheight * 1.1f);
|
||||
y += (LOCALPLAYERCOUNT() >= 2) ? 0 : (s32)(textheight * 1.1f);
|
||||
textMeasure(&textheight, &textwidth, weaponname, g_AmFont1, g_AmFont2, 0);
|
||||
|
||||
x = viGetViewLeft() / g_ScaleX
|
||||
@@ -1064,7 +1064,7 @@ Gfx *amRenderAibotInfo(Gfx *gdl, s32 buddynum)
|
||||
- (s32)(textwidth * 0.5f)
|
||||
+ offset;
|
||||
|
||||
if (PLAYERCOUNT() >= 2) {
|
||||
if (LOCALPLAYERCOUNT() >= 2) {
|
||||
y = viGetViewTop() + 5;
|
||||
} else {
|
||||
y = viGetViewTop() + 10;
|
||||
@@ -1123,7 +1123,7 @@ Gfx *amRenderSlot(Gfx *gdl, char *text, s16 x, s16 y, s32 mode, s32 flags)
|
||||
paddingtop = 6;
|
||||
paddingbottom = 6;
|
||||
|
||||
if (PLAYERCOUNT() >= 2) {
|
||||
if (LOCALPLAYERCOUNT() >= 2) {
|
||||
paddingtop = 5;
|
||||
paddingbottom = 3;
|
||||
}
|
||||
@@ -1262,7 +1262,7 @@ Gfx *amRender(Gfx *gdl)
|
||||
#endif
|
||||
|
||||
#ifndef PLATFORM_N64
|
||||
const s32 playercount = PLAYERCOUNT();
|
||||
const s32 playercount = LOCALPLAYERCOUNT();
|
||||
if (playercount < 2 || (playercount == 2 && optionsGetScreenSplit() == SCREENSPLIT_HORIZONTAL)) {
|
||||
gSPSetExtraGeometryModeEXT(gdl++, G_ASPECT_CENTER_EXT);
|
||||
}
|
||||
@@ -1487,7 +1487,7 @@ Gfx *amRender(Gfx *gdl)
|
||||
above = 6;
|
||||
below = 6;
|
||||
|
||||
if (PLAYERCOUNT() >= 2) {
|
||||
if (LOCALPLAYERCOUNT() >= 2) {
|
||||
above = 5;
|
||||
below = 3;
|
||||
}
|
||||
@@ -1510,7 +1510,7 @@ Gfx *amRender(Gfx *gdl)
|
||||
halfwidth = 1;
|
||||
above = 2;
|
||||
below = 0;
|
||||
} else if (PLAYERCOUNT() >= 2) {
|
||||
} else if (LOCALPLAYERCOUNT() >= 2) {
|
||||
s32 textheight;
|
||||
s32 textwidth;
|
||||
char text[32];
|
||||
@@ -1592,16 +1592,16 @@ Gfx *amRender(Gfx *gdl)
|
||||
}
|
||||
#endif
|
||||
|
||||
barwidth = PLAYERCOUNT() >= 2 ? 48 : 64;
|
||||
barheight = PLAYERCOUNT() >= 2 ? 7 : 11;
|
||||
barwidth = LOCALPLAYERCOUNT() >= 2 ? 48 : 64;
|
||||
barheight = LOCALPLAYERCOUNT() >= 2 ? 7 : 11;
|
||||
xoffset = 0;
|
||||
|
||||
#if VERSION >= VERSION_NTSC_1_0
|
||||
if ((PLAYERCOUNT() == 2 && (optionsGetScreenSplit() == SCREENSPLIT_VERTICAL || IS4MB())) || PLAYERCOUNT() >= 3) {
|
||||
if ((LOCALPLAYERCOUNT() == 2 && (optionsGetScreenSplit() == SCREENSPLIT_VERTICAL || IS4MB())) || LOCALPLAYERCOUNT() >= 3) {
|
||||
xoffset = (g_Vars.currentplayernum & 1) == 0 ? 8 : -8;
|
||||
}
|
||||
|
||||
if (PLAYERCOUNT() == 1 && optionsGetEffectiveScreenSize() != SCREENSIZE_FULL) {
|
||||
if (LOCALPLAYERCOUNT() == 1 && optionsGetEffectiveScreenSize() != SCREENSIZE_FULL) {
|
||||
part1left = viGetViewLeft() / g_ScaleX + 32;
|
||||
} else {
|
||||
part1left = (s32) ((viGetViewWidth() / g_ScaleX) * 0.5f)
|
||||
@@ -1610,7 +1610,7 @@ Gfx *amRender(Gfx *gdl)
|
||||
+ xoffset;
|
||||
}
|
||||
#else
|
||||
if ((PLAYERCOUNT() == 2 && optionsGetScreenSplit() == SCREENSPLIT_VERTICAL) || PLAYERCOUNT() >= 3) {
|
||||
if ((LOCALPLAYERCOUNT() == 2 && optionsGetScreenSplit() == SCREENSPLIT_VERTICAL) || LOCALPLAYERCOUNT() >= 3) {
|
||||
xoffset = (g_Vars.currentplayernum & 1) == 0 ? 8 : -8;
|
||||
}
|
||||
|
||||
@@ -1636,7 +1636,7 @@ Gfx *amRender(Gfx *gdl)
|
||||
gDPSetRenderMode(gdl++, G_RM_XLU_SURF, G_RM_XLU_SURF2);
|
||||
gDPSetCombineMode(gdl++, G_CC_PRIMITIVE, G_CC_PRIMITIVE);
|
||||
|
||||
y = viGetViewTop() + viGetViewHeight() - (PLAYERCOUNT() >= 2 ? 19 : 34);
|
||||
y = viGetViewTop() + viGetViewHeight() - (LOCALPLAYERCOUNT() >= 2 ? 19 : 34);
|
||||
|
||||
// NTSC beta doesn't scale the health bar when hi-res is on,
|
||||
// and it only matches if part2left is an inline expression
|
||||
|
||||
@@ -22,7 +22,7 @@ void amTick(void)
|
||||
s32 prevplayernum = g_Vars.currentplayernum;
|
||||
s32 i;
|
||||
|
||||
for (i = 0; i < PLAYERCOUNT(); i++) {
|
||||
for (i = 0; i < LOCALPLAYERCOUNT(); i++) {
|
||||
setCurrentPlayerNum(i);
|
||||
g_AmIndex = g_Vars.currentplayernum;
|
||||
|
||||
|
||||
+16
-37
@@ -15,7 +15,7 @@
|
||||
#include "game/sky.h"
|
||||
#include "game/stars.h"
|
||||
#include "game/dyntex.h"
|
||||
#include "game/artifact.h"
|
||||
#include "game/game_13c510.h"
|
||||
#include "game/game_1531a0.h"
|
||||
#include "game/gfxmemory.h"
|
||||
#include "game/gfxreplace.h"
|
||||
@@ -47,7 +47,6 @@
|
||||
#include "preprocess.h"
|
||||
#include "system.h"
|
||||
#include "video.h"
|
||||
#include "platform.h"
|
||||
#endif
|
||||
|
||||
#define BGCMD_END 0x00
|
||||
@@ -98,7 +97,7 @@ u16 g_BgUnloadDelay240;
|
||||
u16 g_BgUnloadDelay240_2;
|
||||
u32 var800a4bf4;
|
||||
RoomNum g_GlareRooms[100];
|
||||
uintptr_t *g_BgPrimaryData2;
|
||||
u32 *g_BgPrimaryData2;
|
||||
struct bgroom *g_BgRooms;
|
||||
struct bgportal *g_BgPortals;
|
||||
struct portalmetric *g_PortalMetrics;
|
||||
@@ -114,7 +113,7 @@ struct portalcamcacheitem *g_PortalCameraCache;
|
||||
struct bgsnake g_BgSnake;
|
||||
|
||||
s32 g_StageIndex = 1;
|
||||
uintptr_t var8007fc04 = 0;
|
||||
u32 var8007fc04 = 0;
|
||||
u8 *var8007fc08 = NULL;
|
||||
|
||||
#if VERSION < VERSION_NTSC_1_0
|
||||
@@ -135,9 +134,6 @@ s32 g_BgMostAttemptedDrawSlots = 0;
|
||||
s32 g_BgNumRoomLoadCandidates = 0;
|
||||
u16 g_BgFrameCount = 0xfffe;
|
||||
s32 g_BgNumPortalCameraCacheItems = 0;
|
||||
#ifndef PLATFORM_N64
|
||||
bool g_BgHitXluDisabled = false;
|
||||
#endif
|
||||
|
||||
void bgUnpausePropsInRoom(u32 roomnum, bool tintedglassonly)
|
||||
{
|
||||
@@ -767,7 +763,7 @@ Gfx *bgRenderGdlInXray(Gfx *gdl, s8 *readgdl, Vtx *vertices, s16 arg3[3])
|
||||
gdl = bgProcessXrayTri(gdl, &xraydata, dmemvertices[x], dmemvertices[y], dmemvertices[z], dmemcolours[x], dmemcolours[y], dmemcolours[z], inrange[x], inrange[y], inrange[z]);
|
||||
}
|
||||
|
||||
readgdl += sizeof(Gfx);
|
||||
readgdl += 8;
|
||||
}
|
||||
|
||||
gdl = bgRenderXrayData(gdl, &xraydata);
|
||||
@@ -1472,7 +1468,7 @@ void bgReset(s32 stagenum)
|
||||
u32 section2compsize;
|
||||
u32 section2start;
|
||||
u32 section1compsize;
|
||||
uintptr_t scratch;
|
||||
u32 scratch;
|
||||
|
||||
var8007fc0c = 8;
|
||||
|
||||
@@ -1513,11 +1509,6 @@ void bgReset(s32 stagenum)
|
||||
primcompsize = *(u32 *)&header[8];
|
||||
var8007fc54 = inflatedsize - primcompsize;
|
||||
var8007fc54 -= 0xc;
|
||||
|
||||
#ifdef PLATFORM_64BIT
|
||||
inflatedsize = romdataFileGetEstimatedSize(inflatedsize, LOADTYPE_BG);
|
||||
#endif
|
||||
|
||||
inflatedsize = ALIGN16(inflatedsize);
|
||||
|
||||
// Allocate space for the primary bg data
|
||||
@@ -1538,7 +1529,7 @@ void bgReset(s32 stagenum)
|
||||
bgInflate((u8 *) scratch, g_BgPrimaryData, primcompsize);
|
||||
|
||||
#ifndef PLATFORM_N64
|
||||
preprocessBgSection1(g_BgPrimaryData, inflatedsize, 0x0f000000);
|
||||
preprocessBgSection1(g_BgPrimaryData, 0x0f000000);
|
||||
#endif
|
||||
|
||||
// Shrink the allocation (ie. free the scratch space)
|
||||
@@ -1607,7 +1598,7 @@ void bgReset(s32 stagenum)
|
||||
// Copy 0x40 bytes from a random location in ROM to a random
|
||||
// location in RAM. The write address can be anywhere in the
|
||||
// boot segment or in the lib segment up to modelRenderNodeDl.
|
||||
dmaExec((void *)(PHYS_TO_K0(0x1000) + (rngRandom() & 0x1fff8)), rngRandom() & 0x1fffe, 0x40);
|
||||
dmaExec((void *)(PHYS_TO_K0(0x1000) + (random() & 0x1fff8)), random() & 0x1fffe, 0x40);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1615,7 +1606,7 @@ void bgReset(s32 stagenum)
|
||||
var800a4920 = *(u32 *)g_BgPrimaryData;
|
||||
|
||||
if (var800a4920 == 0) {
|
||||
g_BgPrimaryData2 = (uintptr_t*)g_BgPrimaryData;
|
||||
g_BgPrimaryData2 = (u32 *)g_BgPrimaryData;
|
||||
g_BgRooms = (struct bgroom *)(g_BgPrimaryData2[1] + g_BgPrimaryData - 0x0f000000);
|
||||
goto foo; foo:;
|
||||
g_Vars.roomcount = 0;
|
||||
@@ -2007,6 +1998,10 @@ void bgBuildTables(s32 stagenum)
|
||||
numlightsptr++;
|
||||
}
|
||||
|
||||
#ifndef PLATFORM_N64
|
||||
preprocessBgLights(g_BgLightsFileData, 0);
|
||||
#endif
|
||||
|
||||
// Free the section 3 allocation
|
||||
mempRealloc(section3, 0, MEMPOOL_STAGE);
|
||||
|
||||
@@ -2825,11 +2820,6 @@ void bgLoadRoom(s32 roomnum)
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef PLATFORM_64BIT
|
||||
alloclen = alloclen * 4; // just to be safe for now, adjust properly later #TODO
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef PLATFORM_N64
|
||||
bgGarbageCollectRooms(alloclen, false);
|
||||
|
||||
@@ -2866,7 +2856,7 @@ void bgLoadRoom(s32 roomnum)
|
||||
// Inflate the data to the left side of the allocation
|
||||
inflatedlen = bgInflate(memaddr, allocation, g_BgRooms[roomnum + 1].unk00 - g_BgRooms[roomnum].unk00);
|
||||
#ifndef PLATFORM_N64
|
||||
inflatedlen = preprocessBgRoom(allocation, inflatedlen, g_BgRooms[roomnum].unk00);
|
||||
preprocessBgRoom(allocation, g_BgRooms[roomnum].unk00);
|
||||
#endif
|
||||
|
||||
g_Rooms[roomnum].gfxdata = (struct roomgfxdata *)allocation;
|
||||
@@ -2947,7 +2937,7 @@ void bgLoadRoom(s32 roomnum)
|
||||
|
||||
// Copy gdls to the right-side of the allocation
|
||||
// and build a pointer array to them
|
||||
texCopyGdls((void *) gfxblocks[0], (void *) (allocation + alloclen - (gfxblocks[numgdls] - gfxblocks[0])), (uintptr_t) (gfxblocks[numgdls] - gfxblocks[0]));
|
||||
texCopyGdls((void *) gfxblocks[0], (void *) (allocation + alloclen - (gfxblocks[numgdls] - gfxblocks[0])), (u32) (gfxblocks[numgdls] - gfxblocks[0]));
|
||||
|
||||
for (i = 0; i < numgdls + 1; i++) {
|
||||
gdlpointers[i] = gfxblocks[i] + (allocation + alloclen - gfxblocks[numgdls]);
|
||||
@@ -3650,7 +3640,7 @@ bool bgTestHitOnObj(struct coord *arg0, struct coord *arg1, struct coord *arg2,
|
||||
Gfx *imggdl = NULL;
|
||||
s32 texturenum;
|
||||
f32 lowestsqdist = MAXFLOAT;
|
||||
uintptr_t offset;
|
||||
s32 offset;
|
||||
s32 numvertices;
|
||||
Gfx *tri4gdl;
|
||||
s32 count;
|
||||
@@ -4253,7 +4243,7 @@ bool bgTestHitInVtxBatch(struct coord *arg0, struct coord *arg1, struct coord *a
|
||||
|
||||
vtx = bgFindVerticesForGdl(roomnum, gdl);
|
||||
iter = &gdl[batch->gbicmdindex];
|
||||
vtx = (Vtx *)((UNSEGADDR(iter->words.w1) & 0xffffff) + (uintptr_t)vtx);
|
||||
vtx = (Vtx *)((UNSEGADDR(iter->words.w1) & 0xffffff) + (s32)vtx);
|
||||
numvertices = (((u32) iter->bytes[GFX_W0_BYTE(1)] >> 4) & 0xf) + 1;
|
||||
ptr = var800a6470;
|
||||
|
||||
@@ -4593,10 +4583,6 @@ bool bgTestHitInRoom(struct coord *frompos, struct coord *topos, s32 roomnum, st
|
||||
numbatches = g_Rooms[roomnum].numvtxbatches;
|
||||
|
||||
for (i = 0; i < numbatches; batch++, i++) {
|
||||
#ifndef PLATFORM_N64
|
||||
if (g_BgHitXluDisabled && batch->type == VTXBATCHTYPE_XLU)
|
||||
continue;
|
||||
#endif
|
||||
j = bg0f1612e4(&batch->bbmin, &batch->bbmax, &from, &dist, &sp94, &hitthing->pos);
|
||||
|
||||
if (j == 0) {
|
||||
@@ -6424,10 +6410,6 @@ void bgCalculateGlaresForVisibleRooms(void)
|
||||
|
||||
g_NumRoomsWithGlares = 0;
|
||||
|
||||
// disable line-of-sight hits for transparent background
|
||||
// surfaces before testing for light obstructions
|
||||
g_BgHitXluDisabled = true;
|
||||
|
||||
if (!g_Vars.mplayerisrunning) {
|
||||
for (i = 1; i < g_Vars.roomcount; i++) {
|
||||
if (g_Rooms[i].flags & ROOMFLAG_ONSCREEN) {
|
||||
@@ -6438,9 +6420,6 @@ void bgCalculateGlaresForVisibleRooms(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// re-enable background hits for transparent surfaces
|
||||
g_BgHitXluDisabled = false;
|
||||
}
|
||||
|
||||
#endif
|
||||
+7
-7
@@ -299,7 +299,7 @@ struct model *bodyAllocateModel(s32 bodynum, s32 headnum, u32 spawnflags)
|
||||
if (spawnflags & SPAWNFLAG_FORCESUNGLASSES) {
|
||||
sunglasses = true;
|
||||
} else if (spawnflags & SPAWNFLAG_MAYBESUNGLASSES) {
|
||||
sunglasses = rngRandom() % 2 == 0;
|
||||
sunglasses = random() % 2 == 0;
|
||||
}
|
||||
|
||||
if (spawnflags & SPAWNFLAG_FIXEDHEIGHT) {
|
||||
@@ -325,7 +325,7 @@ s32 bodyChooseHead(s32 bodynum)
|
||||
g_ActiveMaleHeadsIndex = 0;
|
||||
}
|
||||
} else if (bodynum == BODY_FEM_GUARD) {
|
||||
head = g_FemGuardHeads[rngRandom() % 3];
|
||||
head = g_FemGuardHeads[random() % 3];
|
||||
} else {
|
||||
head = g_ActiveFemaleHeads[g_ActiveFemaleHeadsIndex++];
|
||||
|
||||
@@ -493,10 +493,10 @@ void bodyAllocateChr(s32 stagenum, struct packedchr *packed, s32 cmdindex)
|
||||
if (packed->tude != 4) {
|
||||
chr->tude = packed->tude;
|
||||
} else {
|
||||
chr->tude = rngRandom() % 4;
|
||||
chr->tude = random() % 4;
|
||||
}
|
||||
|
||||
chr->voicebox = rngRandom() % 3;
|
||||
chr->voicebox = random() % 3;
|
||||
|
||||
if (!g_HeadsAndBodies[chr->bodynum].ismale) {
|
||||
chr->voicebox = VOICEBOX_FEMALE;
|
||||
@@ -519,7 +519,7 @@ void bodyAllocateChr(s32 stagenum, struct packedchr *packed, s32 cmdindex)
|
||||
chr->flags |= CHRFLAG0_AIVSAI;
|
||||
}
|
||||
|
||||
if (rngRandom() % 5 == 0) {
|
||||
if (random() % 5 == 0) {
|
||||
// Make chr punch slower
|
||||
chr->flags2 |= CHRFLAG1_ADJUSTPUNCHSPEED;
|
||||
}
|
||||
@@ -596,8 +596,8 @@ struct prop *bodyAllocateEyespy(struct pad *pad, RoomNum room)
|
||||
chr->team = 0;
|
||||
chr->squadron = 0;
|
||||
chr->maxdamage = 2;
|
||||
chr->tude = rngRandom() & 3;
|
||||
chr->voicebox = rngRandom() % 3;
|
||||
chr->tude = random() & 3;
|
||||
chr->voicebox = random() % 3;
|
||||
chr->naturalanim = 0;
|
||||
chr->myspecial = 0;
|
||||
chr->yvisang = 0;
|
||||
|
||||
@@ -26,7 +26,7 @@ void bodiesReset(s32 stagenum)
|
||||
g_HeadsAndBodies[i].modeldef = NULL;
|
||||
}
|
||||
|
||||
var80062c80 = rngRandom() % g_NumBondBodies;
|
||||
var80062c80 = random() % g_NumBondBodies;
|
||||
var80062b14 = 0;
|
||||
var80062b18 = 0;
|
||||
|
||||
@@ -67,7 +67,7 @@ void bodiesReset(s32 stagenum)
|
||||
for (i = 0; i < g_NumActiveHeadsPerGender; i++) {
|
||||
do {
|
||||
done = true;
|
||||
g_ActiveMaleHeads[i] = headsavailablelist[rngRandom() % headsavailablelen];
|
||||
g_ActiveMaleHeads[i] = headsavailablelist[random() % headsavailablelen];
|
||||
|
||||
if (headsavailablelen > g_NumActiveHeadsPerGender) {
|
||||
for (j = 0; j < i; j++) {
|
||||
@@ -97,7 +97,7 @@ void bodiesReset(s32 stagenum)
|
||||
for (i = 0; i < g_NumActiveHeadsPerGender; i++) {
|
||||
do {
|
||||
done = true;
|
||||
g_ActiveFemaleHeads[i] = headsavailablelist[rngRandom() % headsavailablelen];
|
||||
g_ActiveFemaleHeads[i] = headsavailablelist[random() % headsavailablelen];
|
||||
|
||||
if (headsavailablelen > g_NumActiveHeadsPerGender) {
|
||||
for (j = 0; j < i; j++) {
|
||||
|
||||
@@ -1016,7 +1016,7 @@ void eyespyProcessInput(bool allowbuttons)
|
||||
// Make eyespy look horizontally
|
||||
if (domovecentre) {
|
||||
if (g_Vars.currentplayer->eyespy->verta > 0.0f && forwardspeed != 0) {
|
||||
if (controlmode != CONTROLMODE_PC) {
|
||||
if (controlmode < CONTROLMODE_PC) {
|
||||
if (g_Vars.currentplayer->eyespy->verta < 180.0f) {
|
||||
tmp = g_Vars.currentplayer->eyespy->verta;
|
||||
|
||||
|
||||
+127
-75
@@ -56,7 +56,8 @@
|
||||
#ifndef PLATFORM_N64
|
||||
#include "game/stagetable.h"
|
||||
#include "video.h"
|
||||
#include "platform.h"
|
||||
#include "net/net.h"
|
||||
#include "net/netmsg.h"
|
||||
#endif
|
||||
|
||||
#define GUNLOADSTATE_FLUX 0
|
||||
@@ -166,13 +167,8 @@ u32 fill2[1];
|
||||
|
||||
Lights1 var80070090 = gdSPDefLights1(0x96, 0x96, 0x96, 0xff, 0xff, 0xff, 0xb2, 0x4d, 0x2e);
|
||||
|
||||
#ifdef PLATFORM_64BIT
|
||||
u32 g_BgunGunMemBaseSizeDefault = 150 * 1024 * 2; // #TODO adjust these values properly
|
||||
u32 g_BgunGunMemBaseSize4Mb2P = 120 * 1024 * 2;
|
||||
#else
|
||||
u32 g_BgunGunMemBaseSizeDefault = 150 * 1024;
|
||||
u32 g_BgunGunMemBaseSize4Mb2P = 120 * 1024;
|
||||
#endif
|
||||
|
||||
u16 g_CartFileNums[] = {
|
||||
FILE_GCARTRIDGE,
|
||||
@@ -896,7 +892,7 @@ void bgunStartAnimation(struct guncmd *cmd, s32 handnum, struct hand *hand)
|
||||
if (cmd->type != GUNCMD_PLAYANIMATION) {
|
||||
struct guncmd *loopcmd = cmd;
|
||||
s32 done = false;
|
||||
u32 rand = rngRandom() % 100;
|
||||
u32 rand = random() % 100;
|
||||
|
||||
while (loopcmd->type != GUNCMD_END) {
|
||||
if (bgun0f098884(loopcmd, &hand->gset) && !done) {
|
||||
@@ -3800,17 +3796,17 @@ void bgunTickGunLoad(void)
|
||||
{
|
||||
s32 i;
|
||||
s32 numthistick;
|
||||
u64 remaining;
|
||||
u32 remaining;
|
||||
s32 padding;
|
||||
u64 allocsize;
|
||||
u64 loadsize;
|
||||
uintptr_t ptr;
|
||||
u32 allocsize;
|
||||
u32 loadsize;
|
||||
u32 ptr;
|
||||
struct player *player = g_Vars.currentplayer;
|
||||
struct modeldef *modeldef;
|
||||
struct fileinfo *fileinfo;
|
||||
struct fileinfo *gunfileinfo;
|
||||
uintptr_t newvalue;
|
||||
uintptr_t end;
|
||||
s32 newvalue;
|
||||
u32 end;
|
||||
u32 stack;
|
||||
#if VERSION >= VERSION_NTSC_1_0
|
||||
u32 stack2;
|
||||
@@ -3832,7 +3828,7 @@ void bgunTickGunLoad(void)
|
||||
*player->gunctrl.loadmemptr = ptr;
|
||||
*player->gunctrl.loadmemremaining = remaining;
|
||||
|
||||
loadsize = ALIGN64(fileGetInflatedSize(player->gunctrl.loadfilenum, LOADTYPE_MODEL)) + 0x8000;
|
||||
loadsize = ALIGN64(fileGetInflatedSize(player->gunctrl.loadfilenum)) + 0x8000;
|
||||
|
||||
osSyncPrintf("BriGun: Loading - %s, pMem 0x%08x Size %d\n");
|
||||
|
||||
@@ -3850,9 +3846,6 @@ void bgunTickGunLoad(void)
|
||||
|
||||
// Reserve some space for textures
|
||||
allocsize = fileGetLoadedSize(player->gunctrl.loadfilenum) + 0xe00;
|
||||
#ifdef PLATFORM_64BIT
|
||||
allocsize += 0xe00;
|
||||
#endif
|
||||
|
||||
osSyncPrintf("BriGun: Used size %d (Ob Size %d)\n");
|
||||
osSyncPrintf("BriGun: block len %d usedsize %d\n");
|
||||
@@ -3863,7 +3856,7 @@ void bgunTickGunLoad(void)
|
||||
|
||||
fileinfo = &g_FileInfo[player->gunctrl.loadfilenum];
|
||||
fileinfo->allocsize = allocsize;
|
||||
end = ALIGN16((uintptr_t)ptr + allocsize);
|
||||
end = ALIGN16((s32)ptr + allocsize);
|
||||
allocsize = end - ptr;
|
||||
if (1);
|
||||
remaining -= allocsize;
|
||||
@@ -3934,7 +3927,7 @@ void bgunTickGunLoad(void)
|
||||
|
||||
modeldef0f1a7560(modeldef, player->gunctrl.loadfilenum, 0x05000000, modeldef, &player->gunctrl.texpool, false);
|
||||
|
||||
fileGetInflatedSize(player->gunctrl.loadfilenum, LOADTYPE_MODEL);
|
||||
fileGetInflatedSize(player->gunctrl.loadfilenum);
|
||||
fileGetLoadedSize(player->gunctrl.loadfilenum);
|
||||
fileGetLoadedSize(player->gunctrl.loadfilenum);
|
||||
fileGetLoadedSize(player->gunctrl.loadfilenum);
|
||||
@@ -3947,7 +3940,7 @@ void bgunTickGunLoad(void)
|
||||
|
||||
newvalue = ALIGN64(texGetPoolLeftPos(&player->gunctrl.texpool));
|
||||
remaining = *player->gunctrl.loadmemremaining;
|
||||
remaining -= (intptr_t)(newvalue - *player->gunctrl.loadmemptr);
|
||||
remaining -= (s32)(newvalue - *player->gunctrl.loadmemptr);
|
||||
|
||||
*player->gunctrl.loadmemptr = newvalue;
|
||||
*player->gunctrl.loadmemremaining = remaining;
|
||||
@@ -4096,8 +4089,8 @@ void bgunTickMasterLoad(void)
|
||||
player->gunctrl.gunloadstate = GUNLOADSTATE_MODEL;
|
||||
player->gunctrl.loadfilenum = handfilenum;
|
||||
player->gunctrl.loadtomodeldef = &player->gunctrl.handmodeldef;
|
||||
player->gunctrl.loadmemptr = (uintptr_t *) &player->gunctrl.handmemloadptr;
|
||||
player->gunctrl.loadmemremaining = (uintptr_t*) &player->gunctrl.handmemloadremaining;
|
||||
player->gunctrl.loadmemptr = (u32 *) &player->gunctrl.handmemloadptr;
|
||||
player->gunctrl.loadmemremaining = (u32 *) &player->gunctrl.handmemloadremaining;
|
||||
}
|
||||
|
||||
bgunTickGunLoad();
|
||||
@@ -4124,8 +4117,8 @@ void bgunTickMasterLoad(void)
|
||||
player->gunctrl.gunloadstate = GUNLOADSTATE_MODEL;
|
||||
player->gunctrl.loadfilenum = filenum;
|
||||
player->gunctrl.loadtomodeldef = &player->gunctrl.gunmodeldef;
|
||||
player->gunctrl.loadmemptr = (uintptr_t*) &player->gunctrl.memloadptr;
|
||||
player->gunctrl.loadmemremaining = (uintptr_t*) &player->gunctrl.memloadremaining;
|
||||
player->gunctrl.loadmemptr = (u32 *) &player->gunctrl.memloadptr;
|
||||
player->gunctrl.loadmemremaining = (u32 *) &player->gunctrl.memloadremaining;
|
||||
}
|
||||
|
||||
bgunTickGunLoad();
|
||||
@@ -4166,8 +4159,8 @@ void bgunTickMasterLoad(void)
|
||||
player->gunctrl.loadfilenum = filenum;
|
||||
player->gunctrl.gunloadstate = GUNLOADSTATE_MODEL;
|
||||
player->gunctrl.loadtomodeldef = &player->gunctrl.cartmodeldef;
|
||||
player->gunctrl.loadmemptr = (uintptr_t *) &player->gunctrl.memloadptr;
|
||||
player->gunctrl.loadmemremaining = (uintptr_t*) &player->gunctrl.memloadremaining;
|
||||
player->gunctrl.loadmemptr = (u32 *) &player->gunctrl.memloadptr;
|
||||
player->gunctrl.loadmemremaining = (u32 *) &player->gunctrl.memloadremaining;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -4193,18 +4186,18 @@ void bgunTickMasterLoad(void)
|
||||
modelInit(&hand->handmodel, player->gunctrl.handmodeldef, hand->handsavedata, false);
|
||||
}
|
||||
|
||||
hand->unk0dcc = (uintptr_t *) player->gunctrl.memloadptr;
|
||||
hand->unk0dcc = (s32 *) player->gunctrl.memloadptr;
|
||||
|
||||
value = bgunCreateModelCmdList(&hand->gunmodel, player->gunctrl.gunmodeldef->rootnode, (uintptr_t *) player->gunctrl.memloadptr);
|
||||
value = bgunCreateModelCmdList(&hand->gunmodel, player->gunctrl.gunmodeldef->rootnode, (s32 *) player->gunctrl.memloadptr);
|
||||
|
||||
sum += value;
|
||||
player->gunctrl.memloadptr += value;
|
||||
player->gunctrl.memloadremaining -= value;
|
||||
|
||||
if (player->gunctrl.handmodeldef != 0) {
|
||||
hand->unk0dd0 = (uintptr_t*) player->gunctrl.memloadptr;
|
||||
hand->unk0dd0 = (s32 *) player->gunctrl.memloadptr;
|
||||
|
||||
value = bgunCreateModelCmdList(&hand->handmodel, player->gunctrl.handmodeldef->rootnode, (uintptr_t*) player->gunctrl.memloadptr);
|
||||
value = bgunCreateModelCmdList(&hand->handmodel, player->gunctrl.handmodeldef->rootnode, (s32 *) player->gunctrl.memloadptr);
|
||||
|
||||
sum += value;
|
||||
player->gunctrl.memloadptr += value;
|
||||
@@ -4481,7 +4474,7 @@ struct defaultobj *bgunCreateThrownProjectile2(struct chrdata *chr, struct gset
|
||||
* 2 = fumbling grenade from right hand (due to nbomb)
|
||||
* 3 = fumbling grenade from left hand (actually not possible)
|
||||
*/
|
||||
void bgunCreateThrownProjectile(s32 handnum, struct gset *gset)
|
||||
struct defaultobj *bgunCreateThrownProjectile(s32 handnum, struct gset *gset)
|
||||
{
|
||||
struct coord velocity = {0, 0, 0};
|
||||
Mtxf sp1f4;
|
||||
@@ -4511,6 +4504,13 @@ void bgunCreateThrownProjectile(s32 handnum, struct gset *gset)
|
||||
struct trainingdata *data;
|
||||
u32 stack;
|
||||
|
||||
#ifndef PLATFORM_N64
|
||||
// don't do anything if we're not the authority
|
||||
if (g_NetMode == NETMODE_CLIENT) {
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (handnum >= 2) {
|
||||
droppinggrenade = true;
|
||||
handnum -= 2;
|
||||
@@ -4676,7 +4676,16 @@ void bgunCreateThrownProjectile(s32 handnum, struct gset *gset)
|
||||
weapon->base.hidden |= OBJHFLAG_THROWNKNIFE;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef PLATFORM_N64
|
||||
if (obj && g_NetMode == NETMODE_SERVER) {
|
||||
netmsgSvcPropSpawnWrite(&g_NetMsgRel, obj->prop);
|
||||
netmsgSvcPropMoveWrite(&g_NetMsgRel, obj->prop, NULL);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
void bgunUpdateHeldRocket(s32 handnum)
|
||||
@@ -4780,6 +4789,12 @@ void bgunCreateFiredProjectile(s32 handnum)
|
||||
f32 spd4[4];
|
||||
f32 spc4[4];
|
||||
|
||||
#ifndef PLATFORM_N64
|
||||
if (g_NetMode == NETMODE_CLIENT) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
hand = g_Vars.currentplayer->hands + handnum;
|
||||
|
||||
playerprop = g_Vars.currentplayer->prop;
|
||||
@@ -4992,6 +5007,12 @@ void bgunCreateFiredProjectile(s32 handnum)
|
||||
weapon->base.prop = NULL;
|
||||
weapon->base.model = NULL;
|
||||
}
|
||||
#ifndef PLATFORM_N64
|
||||
else if (g_NetMode == NETMODE_SERVER) {
|
||||
netmsgSvcPropSpawnWrite(&g_NetMsgRel, weapon->base.prop);
|
||||
netmsgSvcPropMoveWrite(&g_NetMsgRel, weapon->base.prop, NULL);
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
// NTSC beta doesn't have any of the failure checks
|
||||
Mtxf sp78;
|
||||
@@ -6322,6 +6343,13 @@ void bgunDisarm(struct prop *attackerprop)
|
||||
s32 modelnum;
|
||||
s32 i;
|
||||
bool drop;
|
||||
struct defaultobj *obj;
|
||||
#ifndef PLATFORM_N64
|
||||
// don't do anything if we're not the authority
|
||||
if (g_NetMode == NETMODE_CLIENT) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!weaponHasFlag(weaponnum, WEAPONFLAG_UNDROPPABLE) && weaponnum <= WEAPON_RCP45) {
|
||||
#if VERSION >= VERSION_NTSC_1_0
|
||||
@@ -6339,6 +6367,12 @@ void bgunDisarm(struct prop *attackerprop)
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef PLATFORM_N64
|
||||
if (g_NetMode == NETMODE_SERVER) {
|
||||
netmsgSvcChrDisarmWrite(&g_NetMsgRel, player->prop->chr, attackerprop, weaponnum, 0.f, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
chr = player->prop->chr;
|
||||
drop = true;
|
||||
|
||||
@@ -6367,7 +6401,7 @@ void bgunDisarm(struct prop *attackerprop)
|
||||
&& player->hands[i].stateminor == HANDSTATEMINOR_ATTACK_THROW_0) {
|
||||
#endif
|
||||
drop = false;
|
||||
bgunCreateThrownProjectile(i + 2, &player->hands[i].gset);
|
||||
obj = bgunCreateThrownProjectile(i + 2, &player->hands[i].gset);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6391,6 +6425,13 @@ void bgunDisarm(struct prop *attackerprop)
|
||||
}
|
||||
|
||||
objDrop(prop2, true);
|
||||
|
||||
#ifndef PLATFORM_N64
|
||||
if (g_NetMode == NETMODE_SERVER) {
|
||||
netmsgSvcPropSpawnWrite(&g_NetMsgRel, prop2);
|
||||
netmsgSvcPropMoveWrite(&g_NetMsgRel, prop2, NULL);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6424,7 +6465,7 @@ void bgunDisarm(struct prop *attackerprop)
|
||||
*
|
||||
* With this function stubbed, part of the CMP150 model does not render.
|
||||
*/
|
||||
void bgunExecuteModelCmdList(uintptr_t *ptr)
|
||||
void bgunExecuteModelCmdList(s32 *ptr)
|
||||
{
|
||||
union modelrwdata *rwdata;
|
||||
struct modelnode *node;
|
||||
@@ -6481,7 +6522,7 @@ void bgunExecuteModelCmdList(uintptr_t *ptr)
|
||||
* iterate the command list to update part visibility rather than iterate the
|
||||
* full model tree.
|
||||
*/
|
||||
s32 bgunCreateModelCmdList(struct model *model, struct modelnode *nodearg, uintptr_t *ptr)
|
||||
s32 bgunCreateModelCmdList(struct model *model, struct modelnode *nodearg, s32 *ptr)
|
||||
{
|
||||
s32 len = 0;
|
||||
struct modelnode *node = nodearg;
|
||||
@@ -6498,11 +6539,11 @@ s32 bgunCreateModelCmdList(struct model *model, struct modelnode *nodearg, uintp
|
||||
rwdata->distance.visible = false;
|
||||
node->child = rodata->distance.target;
|
||||
ptr[0] = 0;
|
||||
ptr[1] = (uintptr_t)rwdata;
|
||||
ptr[2] = (uintptr_t)node;
|
||||
ptr[3] = (uintptr_t)rodata->distance.target;
|
||||
ptr[1] = (s32)rwdata;
|
||||
ptr[2] = (s32)node;
|
||||
ptr[3] = (s32)rodata->distance.target;
|
||||
ptr += 4;
|
||||
len += 4 * sizeof(uintptr_t);
|
||||
len += 16;
|
||||
break;
|
||||
case MODELNODETYPE_TOGGLE:
|
||||
rodata = node->rodata;
|
||||
@@ -6510,36 +6551,36 @@ s32 bgunCreateModelCmdList(struct model *model, struct modelnode *nodearg, uintp
|
||||
rwdata->toggle.visible = true;
|
||||
node->child = rodata->toggle.target;
|
||||
ptr[0] = 1;
|
||||
ptr[1] = (uintptr_t)rwdata;
|
||||
ptr[2] = (uintptr_t)node;
|
||||
ptr[3] = (uintptr_t)rodata->toggle.target;
|
||||
ptr[1] = (s32)rwdata;
|
||||
ptr[2] = (s32)node;
|
||||
ptr[3] = (s32)rodata->toggle.target;
|
||||
ptr += 4;
|
||||
len += 4 * sizeof(uintptr_t);
|
||||
len += 16;
|
||||
break;
|
||||
case MODELNODETYPE_HEADSPOT:
|
||||
rwdata = modelGetNodeRwData(model, node);
|
||||
rwdata->headspot.headmodeldef = NULL;
|
||||
rwdata->headspot.rwdatas = NULL;
|
||||
ptr[0] = 2;
|
||||
ptr[1] = (uintptr_t)rwdata;
|
||||
ptr[1] = (s32)rwdata;
|
||||
ptr += 2;
|
||||
len += 2 * sizeof(uintptr_t);
|
||||
len += 8;
|
||||
break;
|
||||
case MODELNODETYPE_0B:
|
||||
rwdata = modelGetNodeRwData(model, node);
|
||||
rwdata->type0b.unk00 = 0;
|
||||
ptr[0] = 3;
|
||||
ptr[1] = (uintptr_t)rwdata;
|
||||
ptr[1] = (s32)rwdata;
|
||||
ptr += 2;
|
||||
len += 2 * sizeof(uintptr_t);
|
||||
len += 8;
|
||||
break;
|
||||
case MODELNODETYPE_CHRGUNFIRE:
|
||||
rwdata = modelGetNodeRwData(model, node);
|
||||
rwdata->chrgunfire.visible = false;
|
||||
ptr[0] = 4;
|
||||
ptr[1] = (uintptr_t)rwdata;
|
||||
ptr[1] = (s32)rwdata;
|
||||
ptr += 2;
|
||||
len += 2 * sizeof(uintptr_t);
|
||||
len += 8;
|
||||
break;
|
||||
case MODELNODETYPE_DL:
|
||||
rodata = node->rodata;
|
||||
@@ -6548,12 +6589,12 @@ s32 bgunCreateModelCmdList(struct model *model, struct modelnode *nodearg, uintp
|
||||
rwdata->dl.gdl = rodata->dl.opagdl;
|
||||
rwdata->dl.colours = (void *)ALIGN8((uintptr_t)&rodata->dl.vertices[rodata->dl.numvertices]);
|
||||
ptr[0] = 5;
|
||||
ptr[1] = (uintptr_t)rwdata;
|
||||
ptr[2] = (uintptr_t)rwdata->dl.vertices;
|
||||
ptr[3] = (uintptr_t)rwdata->dl.gdl;
|
||||
ptr[4] = (uintptr_t)rwdata->dl.colours;
|
||||
ptr[1] = (s32)rwdata;
|
||||
ptr[2] = (s32)rwdata->dl.vertices;
|
||||
ptr[3] = (s32)rwdata->dl.gdl;
|
||||
ptr[4] = (s32)rwdata->dl.colours;
|
||||
ptr += 5;
|
||||
len += 5 * sizeof(uintptr_t);
|
||||
len += 20;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -6577,7 +6618,7 @@ s32 bgunCreateModelCmdList(struct model *model, struct modelnode *nodearg, uintp
|
||||
}
|
||||
|
||||
*ptr = 6;
|
||||
len += sizeof(uintptr_t);
|
||||
len += 4;
|
||||
|
||||
return len;
|
||||
}
|
||||
@@ -7170,7 +7211,7 @@ void bgunUpdateMagnum(struct hand *hand, s32 handnum, struct modeldef *modeldef,
|
||||
|
||||
if (modeldef != NULL) {
|
||||
for (i = 0; i < hand->unk0cc8_04; i++) {
|
||||
struct modelnode *node = modelGetPart(modeldef, 0x0a + rngRandom() % 6);
|
||||
struct modelnode *node = modelGetPart(modeldef, 0x0a + random() % 6);
|
||||
|
||||
if (node) {
|
||||
s32 index = modelFindNodeMtxIndex(node, 0);
|
||||
@@ -8477,7 +8518,7 @@ glabel var7f1aca90
|
||||
/* f0a71e4: 100002d5 */ b .L0f0a7d3c
|
||||
/* f0a71e8: 8fbf0034 */ lw $ra,0x34($sp)
|
||||
.L0f0a71ec:
|
||||
/* f0a71ec: 0fc5d9ad */ jal zbufSaveArtifactDepths
|
||||
/* f0a71ec: 0fc5d9ad */ jal zbufDrawArtifactsOffscreen
|
||||
/* f0a71f0: 8fa4014c */ lw $a0,0x14c($sp)
|
||||
/* f0a71f4: afa2014c */ sw $v0,0x14c($sp)
|
||||
/* f0a71f8: 0c002ca0 */ jal viPrepareZbuf
|
||||
@@ -9318,7 +9359,7 @@ glabel var7f1aca90
|
||||
/* f0a71e4: 100002d5 */ b .L0f0a7d3c
|
||||
/* f0a71e8: 8fbf0034 */ lw $ra,0x34($sp)
|
||||
.L0f0a71ec:
|
||||
/* f0a71ec: 0fc5d9ad */ jal zbufSaveArtifactDepths
|
||||
/* f0a71ec: 0fc5d9ad */ jal zbufDrawArtifactsOffscreen
|
||||
/* f0a71f0: 8fa4014c */ lw $a0,0x14c($sp)
|
||||
/* f0a71f4: afa2014c */ sw $v0,0x14c($sp)
|
||||
/* f0a71f8: 0c002ca0 */ jal viPrepareZbuf
|
||||
@@ -10159,7 +10200,7 @@ glabel var7f1aca90
|
||||
/* f0a4f30: 100002cd */ beqz $zero,.NB0f0a5a68
|
||||
/* f0a4f34: 8fbf0034 */ lw $ra,0x34($sp)
|
||||
.NB0f0a4f38:
|
||||
/* f0a4f38: 0fc5c4d5 */ jal zbufSaveArtifactDepths
|
||||
/* f0a4f38: 0fc5c4d5 */ jal zbufDrawArtifactsOffscreen
|
||||
/* f0a4f3c: 8fa40144 */ lw $a0,0x144($sp)
|
||||
/* f0a4f40: afa20144 */ sw $v0,0x144($sp)
|
||||
/* f0a4f44: 0c002d00 */ jal viPrepareZbuf
|
||||
@@ -10942,6 +10983,7 @@ void bgunRender(Gfx **gdlptr)
|
||||
struct modelrenderdata renderdata = {NULL, true, 3}; // 10c
|
||||
struct player *player;
|
||||
s32 i;
|
||||
const u32 wnorm = mtx00016dcc(0, 300);
|
||||
|
||||
static bool renderhand = true; // var800702dc
|
||||
|
||||
@@ -10957,7 +10999,7 @@ void bgunRender(Gfx **gdlptr)
|
||||
}
|
||||
|
||||
#ifdef PLATFORM_N64 // TODO
|
||||
gdl = zbufSaveArtifactDepths(gdl);
|
||||
gdl = zbufDrawArtifactsOffscreen(gdl);
|
||||
#endif
|
||||
gdl = viPrepareZbuf(gdl);
|
||||
gdl = vi0000b1d0(gdl);
|
||||
@@ -11007,7 +11049,7 @@ void bgunRender(Gfx **gdlptr)
|
||||
gSPLookAt(gdl++, camGetLookAt());
|
||||
}
|
||||
|
||||
gSPPerspNormalize(gdl++, mtx00016dcc(0, 300));
|
||||
gSPPerspNormalize(gdl++, wnorm);
|
||||
|
||||
// There is support for guns having a TV screen on them
|
||||
// but no guns have this model part so it's not used.
|
||||
@@ -11182,7 +11224,17 @@ void bgunRender(Gfx **gdlptr)
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef PLATFORM_N64
|
||||
// put the casings into the same Z range as the gun
|
||||
gSPPerspNormalize(gdl++, wnorm);
|
||||
#endif
|
||||
|
||||
casingsRender(&gdl);
|
||||
|
||||
#ifndef PLATFORM_N64
|
||||
gSPPerspNormalize(gdl++, viGetPerspScale());
|
||||
#endif
|
||||
|
||||
zbufSwap();
|
||||
|
||||
gdl = zbufConfigureRdp(gdl);
|
||||
@@ -11214,8 +11266,8 @@ struct sndstate **bgunAllocateAudioHandle(void)
|
||||
void bgunPlayPropHitSound(struct gset *gset, struct prop *prop, s32 texturenum)
|
||||
{
|
||||
#if VERSION >= VERSION_NTSC_1_0
|
||||
u32 rand1 = rngRandom();
|
||||
u32 rand2 = rngRandom();
|
||||
u32 rand1 = random();
|
||||
u32 rand2 = random();
|
||||
struct sndstate **handle;
|
||||
|
||||
if (g_Vars.lvupdate240 <= 0) {
|
||||
@@ -11294,8 +11346,8 @@ void bgunPlayPropHitSound(struct gset *gset, struct prop *prop, s32 texturenum)
|
||||
if (texturenum == 10000) {
|
||||
soundnum = SFX_SHIELD_DAMAGE;
|
||||
} else if (gset->weaponnum == WEAPON_LASER) {
|
||||
if (gset->weaponfunc == FUNC_PRIMARY || ((gset->unk063a % 4) == 0 && (rngRandom() % 2))) {
|
||||
if ((rngRandom() % 2) == 0) {
|
||||
if (gset->weaponfunc == FUNC_PRIMARY || ((gset->unk063a % 4) == 0 && (random() % 2))) {
|
||||
if ((random() % 2) == 0) {
|
||||
soundnum = SFX_CLOAK_ON;
|
||||
} else {
|
||||
soundnum = SFX_CLOAK_OFF;
|
||||
@@ -11359,8 +11411,8 @@ void bgunPlayPropHitSound(struct gset *gset, struct prop *prop, s32 texturenum)
|
||||
}
|
||||
}
|
||||
#else
|
||||
u32 rand1 = rngRandom();
|
||||
u32 rand2 = rngRandom();
|
||||
u32 rand1 = random();
|
||||
u32 rand2 = random();
|
||||
struct sndstate **handle;
|
||||
|
||||
if (g_Vars.lvupdate240 <= 0) {
|
||||
@@ -11433,7 +11485,7 @@ void bgunPlayPropHitSound(struct gset *gset, struct prop *prop, s32 texturenum)
|
||||
soundnum = SFX_SHIELD_DAMAGE;
|
||||
} else if (gset->weaponnum == WEAPON_LASER) {
|
||||
if (gset->weaponfunc == FUNC_PRIMARY || (gset->unk063a % 8) == 0) {
|
||||
if ((rngRandom() % 2) == 0) {
|
||||
if ((random() % 2) == 0) {
|
||||
soundnum = SFX_CLOAK_ON;
|
||||
} else {
|
||||
soundnum = SFX_CLOAK_OFF;
|
||||
@@ -11511,8 +11563,8 @@ void bgunPlayBgHitSound(struct gset *gset, struct coord *hitpos, s32 texturenum,
|
||||
{
|
||||
#if VERSION >= VERSION_NTSC_1_0
|
||||
struct sndstate **handle;
|
||||
u32 rand1 = rngRandom();
|
||||
u32 rand2 = rngRandom();
|
||||
u32 rand1 = random();
|
||||
u32 rand2 = random();
|
||||
bool playdefault;
|
||||
s16 soundnum;
|
||||
bool overridden;
|
||||
@@ -11535,7 +11587,7 @@ void bgunPlayBgHitSound(struct gset *gset, struct coord *hitpos, s32 texturenum,
|
||||
if (gset->weaponnum == WEAPON_LASER) {
|
||||
playdefault = false;
|
||||
|
||||
if (gset->weaponfunc == FUNC_PRIMARY || ((gset->unk063a % 4) == 0 && (rngRandom() % 2))) {
|
||||
if (gset->weaponfunc == FUNC_PRIMARY || ((gset->unk063a % 4) == 0 && (random() % 2))) {
|
||||
// Laser sounds
|
||||
s16 sounds[] = {SFX_CLOAK_ON, SFX_CLOAK_OFF};
|
||||
soundnum = sounds[rand1 % ARRAYCOUNT(sounds)];
|
||||
@@ -11610,8 +11662,8 @@ void bgunPlayBgHitSound(struct gset *gset, struct coord *hitpos, s32 texturenum,
|
||||
}
|
||||
#else
|
||||
struct sndstate **handle;
|
||||
u32 rand1 = rngRandom();
|
||||
u32 rand2 = rngRandom();
|
||||
u32 rand1 = random();
|
||||
u32 rand2 = random();
|
||||
s16 soundnum;
|
||||
bool overridden;
|
||||
|
||||
@@ -11732,7 +11784,7 @@ void bgunSetTriggerOn(s32 handnum, bool on)
|
||||
s32 bgunConsiderToggleGunFunction(s32 usedowntime, bool trigpressed, bool fromactivemenu, bool fromdedicatedbutton)
|
||||
{
|
||||
#ifndef PLATFORM_N64
|
||||
const bool extcontrols = PLAYER_EXTCFG().extcontrols;
|
||||
const bool extcontrols = PLAYER_EXTCFG().extcontrols || g_Vars.currentplayer->isremote;
|
||||
bool docontinue;
|
||||
#endif
|
||||
switch (bgunGetWeaponNum(HAND_RIGHT)) {
|
||||
@@ -11851,7 +11903,7 @@ void bgun0f0a8c50(void)
|
||||
case WEAPON_LAPTOPGUN:
|
||||
case WEAPON_DRAGON:
|
||||
case WEAPON_REMOTEMINE:
|
||||
if (PLAYER_EXTCFG().extcontrols) {
|
||||
if (PLAYER_EXTCFG().extcontrols || g_Vars.currentplayer->isremote) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
@@ -12754,7 +12806,7 @@ Gfx *bgunDrawHud(Gfx *gdl)
|
||||
{
|
||||
struct player *player = g_Vars.currentplayer;
|
||||
s32 bottom = viGetViewTop() + viGetViewHeight() - 13;
|
||||
s32 playercount = PLAYERCOUNT();
|
||||
s32 playercount = LOCALPLAYERCOUNT();
|
||||
s32 playernum = g_Vars.currentplayernum;
|
||||
struct gunctrl *ctrl;
|
||||
s32 secs60;
|
||||
|
||||
+261
-90
@@ -42,6 +42,10 @@
|
||||
#include <math.h>
|
||||
#include "input.h"
|
||||
#include "video.h"
|
||||
#include "system.h"
|
||||
#include "utils.h"
|
||||
#include "net/net.h"
|
||||
#include "net/netmsg.h"
|
||||
|
||||
static void bgunProcessQuickDetonate(struct movedata *data, u32 c1buttons, u32 c1buttonsthisframe, u32 buttons1, u32 buttons2) {
|
||||
if ((((c1buttons & (buttons1)) && (c1buttonsthisframe & (buttons2)))
|
||||
@@ -105,6 +109,159 @@ static void bgunProcessInputAltButton(struct movedata *data, s8 contpad, s32 i)
|
||||
}
|
||||
}
|
||||
|
||||
static inline void bmoveProcessRemoteInput(const bool allowc1buttons)
|
||||
{
|
||||
struct player *pl = g_Vars.currentplayer;
|
||||
if (!pl->client) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct netplayermove *inmove = &pl->client->inmove[0];
|
||||
struct netplayermove *inmoveprev = &pl->client->inmove[1];
|
||||
s32 moveticks = inmove->tick - inmoveprev->tick;
|
||||
if (moveticks > g_NetInterpTicks) {
|
||||
moveticks = g_NetInterpTicks;
|
||||
}
|
||||
|
||||
const bool handled = (pl->client->inmovetick >= inmove->tick);
|
||||
|
||||
if (!inmove->tick) {
|
||||
// no input
|
||||
inmove->pos = inmoveprev->pos = pl->prop->pos;
|
||||
inmove->angles[0] = inmoveprev->angles[0] = pl->vv_theta;
|
||||
inmove->angles[1] = inmoveprev->angles[1] = pl->vv_verta;
|
||||
inmove->ucmd = 0;
|
||||
}
|
||||
|
||||
if (inmove->ucmd & UCMD_DUCK) {
|
||||
pl->crouchpos = CROUCHPOS_DUCK;
|
||||
} else if (inmove->ucmd & UCMD_SQUAT) {
|
||||
pl->crouchpos = CROUCHPOS_SQUAT;
|
||||
} else {
|
||||
pl->crouchpos = CROUCHPOS_STAND;
|
||||
}
|
||||
|
||||
pl->bondactivateorreload = 0;
|
||||
|
||||
pl->eyesshut = (inmove->ucmd & UCMD_EYESSHUT) != 0;
|
||||
|
||||
pl->speedtheta = 0.f; // TODO: figure out if anglespeed is even required
|
||||
pl->speedverta = 0.f;
|
||||
pl->crouchoffset = inmove->crouchofs;
|
||||
|
||||
pl->oldcrosspos[0] = pl->crosspos[0];
|
||||
pl->oldcrosspos[1] = pl->crosspos[1];
|
||||
pl->crosspos[0] = inmove->crosspos[0];
|
||||
pl->crosspos[1] = inmove->crosspos[1];
|
||||
|
||||
// denormalize crosspos x
|
||||
pl->crosspos[0] -= (f32)(SCREEN_WIDTH_LO / 2);
|
||||
pl->crosspos[0] = (f32)(SCREEN_WIDTH_LO / 2) + pl->crosspos[0] / pl->aspect * SCREEN_ASPECT;
|
||||
|
||||
pl->crosspos2[0] = pl->crosspos[0];
|
||||
pl->crosspos2[1] = pl->crosspos[1];
|
||||
|
||||
pl->insightaimmode = (inmove->ucmd & UCMD_AIMMODE) != 0;
|
||||
if (pl->insightaimmode) {
|
||||
pl->gunzoomfovs[0] = pl->gunzoomfovs[1] = pl->gunzoomfovs[2] = inmove->zoomfov;
|
||||
}
|
||||
|
||||
f32 zoomfov = 0.f;
|
||||
if (pl->insightaimmode) {
|
||||
zoomfov = currentPlayerGetGunZoomFov();
|
||||
}
|
||||
if (bgunGetWeaponNum(HAND_RIGHT) == WEAPON_AR34 && pl->hands[HAND_RIGHT].gset.weaponfunc == FUNC_SECONDARY) {
|
||||
zoomfov = currentPlayerGetGunZoomFov();
|
||||
}
|
||||
if (zoomfov <= 0.f) {
|
||||
zoomfov = pl->client->settings.fovy;
|
||||
}
|
||||
playerTweenFovY(zoomfov);
|
||||
playerUpdateZoom();
|
||||
|
||||
for (s32 h = 0; h < 2; ++h) {
|
||||
pl->hands[h].crosspos[0] = pl->crosspos[0];
|
||||
pl->hands[h].crosspos[1] = pl->crosspos[1];
|
||||
}
|
||||
|
||||
if (inmove->ucmd & UCMD_SELECT) {
|
||||
pl->gunctrl.dualwielding = (inmove->ucmd & UCMD_SELECT_DUAL) != 0;
|
||||
if (inmove->weaponnum >= 0) {
|
||||
bgunEquipWeapon(inmove->weaponnum);
|
||||
}
|
||||
}
|
||||
|
||||
if ((inmove->ucmd & UCMD_SECONDARY) && !bgunIsUsingSecondaryFunction()) {
|
||||
bgunConsiderToggleGunFunction(0, false, false, true);
|
||||
} else if (!(inmove->ucmd & UCMD_SECONDARY) && bgunIsUsingSecondaryFunction()) {
|
||||
// do not switch back to primary if in the process of throwing laptop
|
||||
if (!(bgunGetWeaponNum(HAND_RIGHT) == WEAPON_LAPTOPGUN && pl->hands[HAND_RIGHT].state == HANDSTATE_ATTACK)) {
|
||||
bgunConsiderToggleGunFunction(0, false, false, true);
|
||||
}
|
||||
}
|
||||
|
||||
const bool fireguns = (inmove->ucmd & UCMD_FIRE) && !pl->waitforzrelease && allowc1buttons;
|
||||
|
||||
bgunTickGameplay(fireguns);
|
||||
|
||||
if (fireguns && g_NetMode == NETMODE_SERVER) {
|
||||
netmsgSvcPlayerStatsWrite(&g_NetMsgRel, pl->client);
|
||||
}
|
||||
|
||||
if (!handled && (inmove->ucmd & UCMD_RELOAD)) {
|
||||
pl->bondactivateorreload |= JO_ACTION_RELOAD;
|
||||
}
|
||||
|
||||
if (g_NetMode == NETMODE_SERVER) {
|
||||
if (!handled && (inmove->ucmd & UCMD_ACTIVATE)) {
|
||||
pl->bondactivateorreload |= JO_ACTION_ACTIVATE;
|
||||
}
|
||||
|
||||
if (g_Vars.bondvisible && (bgunIsFiring(HAND_RIGHT) || bgunIsFiring(HAND_LEFT))) {
|
||||
f32 noiseradius = 0.f;
|
||||
if (bgunIsFiring(HAND_RIGHT) && bgunGetNoiseRadius(HAND_RIGHT) > noiseradius) {
|
||||
noiseradius = bgunGetNoiseRadius(HAND_RIGHT);
|
||||
}
|
||||
if (bgunIsFiring(HAND_LEFT) && bgunGetNoiseRadius(HAND_LEFT) > noiseradius) {
|
||||
noiseradius = bgunGetNoiseRadius(HAND_LEFT);
|
||||
}
|
||||
chrsCheckForNoise(noiseradius);
|
||||
}
|
||||
}
|
||||
|
||||
bgunSetSightVisible(GUNSIGHTREASON_NOTAIMING, pl->insightaimmode);
|
||||
|
||||
const bool forcepos = !inmoveprev->tick || !moveticks || (inmove->ucmd & UCMD_FL_FORCEANGLE);
|
||||
|
||||
// lerp towards the current speeds and angles
|
||||
const f32 dt = (forcepos ? 1.f : (1.f / (f32)moveticks));
|
||||
f32 t = (forcepos ? 1.f : ((f32)pl->client->lerpticks / (f32)moveticks));
|
||||
if (t > 1.f) {
|
||||
t = 1.f;
|
||||
}
|
||||
pl->speedgo = pl->speedforwards = lerpf(inmoveprev->movespeed[0], inmove->movespeed[0], t);
|
||||
pl->speedstrafe = pl->speedsideways = lerpf(inmoveprev->movespeed[1], inmove->movespeed[1], t);
|
||||
pl->vv_theta = lerpanglef(pl->vv_theta, inmove->angles[0], dt);
|
||||
pl->vv_verta = lerpanglef(pl->vv_verta, inmove->angles[1], dt);
|
||||
|
||||
if (pl->bondmovemode == MOVEMODE_GRAB) {
|
||||
bgrabUpdateSpeedTheta();
|
||||
} else if (pl->bondmovemode == MOVEMODE_WALK) {
|
||||
if (bmoveGetCrouchPos() != CROUCHPOS_STAND) {
|
||||
pl->speedmaxtime60 = 0;
|
||||
}
|
||||
bwalkSetSwayTargetf(inmove->leanofs);
|
||||
} else if (pl->bondmovemode == MOVEMODE_BIKE) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
if (inmove->movespeed[0] > 0.95f) {
|
||||
pl->speedmaxtime60 += g_Vars.lvupdate60;
|
||||
} else {
|
||||
pl->speedmaxtime60 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // PLATFORM_N64
|
||||
|
||||
void bmoveSetControlDef(u32 controldef)
|
||||
@@ -313,6 +470,39 @@ void bmoveApplyMoveData(struct movedata *data)
|
||||
} else if (g_Vars.currentplayer->bondmovemode == MOVEMODE_WALK) {
|
||||
bwalkApplyMoveData(data);
|
||||
}
|
||||
|
||||
#ifndef PLATFORM_N64
|
||||
// record some inputs if this is a local player
|
||||
if (g_NetMode && !g_Vars.currentplayer->isremote) {
|
||||
g_Vars.currentplayer->ucmd = 0;
|
||||
if (g_Vars.currentplayer->isdead) {
|
||||
if (g_NetMode == NETMODE_CLIENT) {
|
||||
if (joyGetButtons(optionsGetContpadNum1(g_Vars.currentplayerstats->mpindex), 0xb000)) {
|
||||
g_Vars.currentplayer->ucmd |= UCMD_RESPAWN;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (data->triggeron) {
|
||||
g_Vars.currentplayer->ucmd |= UCMD_FIRE;
|
||||
}
|
||||
if (data->aiming) {
|
||||
g_Vars.currentplayer->ucmd |= UCMD_AIMMODE;
|
||||
}
|
||||
if (g_Vars.currentplayer->bondactivateorreload & JO_ACTION_ACTIVATE) {
|
||||
g_Vars.currentplayer->ucmd |= UCMD_ACTIVATE;
|
||||
}
|
||||
if (g_Vars.currentplayer->bondactivateorreload & JO_ACTION_RELOAD) {
|
||||
g_Vars.currentplayer->ucmd |= UCMD_RELOAD;
|
||||
}
|
||||
if (data->eyesshut) {
|
||||
g_Vars.currentplayer->ucmd |= UCMD_EYESSHUT;
|
||||
}
|
||||
if (data->weaponbackoffset || data->weaponforwardoffset) {
|
||||
g_Vars.currentplayer->ucmd |= UCMD_SELECT;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void bmoveUpdateSpeedTheta(void)
|
||||
@@ -329,11 +519,11 @@ void bmoveUpdateSpeedTheta(void)
|
||||
f32 bmoveGetSpeedVertaLimit(f32 value)
|
||||
{
|
||||
if (value > 0) {
|
||||
return (viGetFovY() * value * -0.7f) / PLAYER_DEFAULT_FOV;
|
||||
return (viGetFovY() * value * -0.7f) / 60.0f;
|
||||
}
|
||||
|
||||
if (value < 0) {
|
||||
return (viGetFovY() * -value * 0.7f) / PLAYER_DEFAULT_FOV;
|
||||
return (viGetFovY() * -value * 0.7f) / 60.0f;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -341,7 +531,7 @@ f32 bmoveGetSpeedVertaLimit(f32 value)
|
||||
|
||||
void bmoveUpdateSpeedVerta(f32 value)
|
||||
{
|
||||
f32 mult = viGetFovY() / PLAYER_DEFAULT_FOV;
|
||||
f32 mult = viGetFovY() / 60.0f;
|
||||
f32 limit = bmoveGetSpeedVertaLimit(value);
|
||||
|
||||
if (value > 0) {
|
||||
@@ -384,11 +574,11 @@ void bmoveUpdateSpeedVerta(f32 value)
|
||||
f32 bmoveGetSpeedThetaControlLimit(f32 value)
|
||||
{
|
||||
if (value > 0) {
|
||||
return (viGetFovY() * value * -0.7f) / PLAYER_DEFAULT_FOV;
|
||||
return (viGetFovY() * value * -0.7f) / 60.0f;
|
||||
}
|
||||
|
||||
if (value < 0) {
|
||||
return (viGetFovY() * -value * 0.7f) / PLAYER_DEFAULT_FOV;
|
||||
return (viGetFovY() * -value * 0.7f) / 60.0f;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -396,7 +586,7 @@ f32 bmoveGetSpeedThetaControlLimit(f32 value)
|
||||
|
||||
void bmoveUpdateSpeedThetaControl(f32 value)
|
||||
{
|
||||
f32 mult = viGetFovY() / PLAYER_DEFAULT_FOV;
|
||||
f32 mult = viGetFovY() / 60.0f;
|
||||
f32 limit = bmoveGetSpeedThetaControlLimit(value);
|
||||
|
||||
if (value > 0) {
|
||||
@@ -436,38 +626,6 @@ void bmoveUpdateSpeedThetaControl(f32 value)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply crosshair swivel based on camera movement with input detection
|
||||
*/
|
||||
static void bmoveApplyCrosshairSwivel(struct movedata *movedata, f32 mlookscale, f32 *x, f32 *y)
|
||||
{
|
||||
#ifdef PLATFORM_N64
|
||||
*x = g_Vars.currentplayer->speedtheta * 0.3f + g_Vars.currentplayer->gunextraaimx;
|
||||
*y = -g_Vars.currentplayer->speedverta * 0.1f + g_Vars.currentplayer->gunextraaimy;
|
||||
#else
|
||||
f32 xscale, yscale;
|
||||
bool mouse_active = (movedata->freelookdx || movedata->freelookdy);
|
||||
bool joystick_active = (movedata->c1stickxraw != 0 || movedata->c1stickyraw != 0);
|
||||
|
||||
if ((mouse_active) && joystick_active) {
|
||||
// Mouse + joystick sway
|
||||
xscale = PLAYER_EXTCFG().crosshairsway * 0.80f; // 80% for precision+joystick sway
|
||||
yscale = PLAYER_EXTCFG().crosshairsway * 0.80f; // 80% for precision+joystick sway
|
||||
} else if (mouse_active) {
|
||||
// Mouse sway
|
||||
xscale = PLAYER_EXTCFG().crosshairsway * 0.20f; // 20% for mouse sway
|
||||
yscale = PLAYER_EXTCFG().crosshairsway * 0.30f; // 30% for mouse sway
|
||||
} else {
|
||||
// Joystick only or no input - full sway
|
||||
xscale = yscale = PLAYER_EXTCFG().crosshairsway;
|
||||
}
|
||||
// Joystick x/y scaling
|
||||
// 0.3f for x, 0.1f for y
|
||||
*x = g_Vars.currentplayer->speedtheta * 0.3f * xscale + g_Vars.currentplayer->gunextraaimx;
|
||||
*y = -g_Vars.currentplayer->speedverta * 0.1f * yscale + g_Vars.currentplayer->gunextraaimy;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the lookahead angle.
|
||||
*
|
||||
@@ -750,6 +908,14 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i
|
||||
#endif
|
||||
|
||||
controlmode = optionsGetControlMode(g_Vars.currentplayerstats->mpindex);
|
||||
|
||||
#ifndef PLATFORM_N64
|
||||
if (g_Vars.currentplayer->isremote || controlmode == CONTROLMODE_NA) {
|
||||
bmoveProcessRemoteInput(allowc1buttons);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
weaponnum = bgunGetWeaponNum(HAND_RIGHT);
|
||||
canmanualzoom = weaponHasAimFlag(weaponnum, INVAIMFLAG_MANUALZOOM);
|
||||
contpad1 = optionsGetContpadNum1(g_Vars.currentplayerstats->mpindex);
|
||||
@@ -812,12 +978,6 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i
|
||||
movedata.freelookdy = -movedata.freelookdy;
|
||||
}
|
||||
}
|
||||
// always pause with ESC
|
||||
if (allowc1buttons && g_Vars.currentplayer->isdead == false && g_Vars.currentplayer->pausemode == PAUSEMODE_UNPAUSED) {
|
||||
if (inputKeyJustPressed(VK_ESCAPE)) {
|
||||
c1buttonsthisframe |= START_BUTTON;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Pausing
|
||||
@@ -939,9 +1099,7 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i
|
||||
aimoffhist[i] = !aimonhist[i];
|
||||
}
|
||||
|
||||
if (numsamples > 0) {
|
||||
g_Vars.currentplayer->insightaimmode = aimonhist[numsamples - 1];
|
||||
}
|
||||
g_Vars.currentplayer->insightaimmode = aimonhist[numsamples - 1];
|
||||
}
|
||||
|
||||
if (!lvIsPaused()) {
|
||||
@@ -1065,7 +1223,7 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i
|
||||
}
|
||||
|
||||
// Handle B button activation
|
||||
if (allowc1buttons && controlmode != CONTROLMODE_PC) {
|
||||
if (allowc1buttons && controlmode < CONTROLMODE_PC) {
|
||||
for (i = 0; i < numsamples; i++) {
|
||||
if (joyGetButtonsOnSample(i, contpad1, c1allowedbuttons & B_BUTTON)
|
||||
|| joyGetButtonsOnSample(i, contpad2, c2allowedbuttons & B_BUTTON)) {
|
||||
@@ -1272,9 +1430,10 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i
|
||||
aimoffhist[i] = !aimonhist[i];
|
||||
}
|
||||
|
||||
if (numsamples > 0) {
|
||||
g_Vars.currentplayer->insightaimmode = aimonhist[numsamples - 1];
|
||||
}
|
||||
#ifdef AVOID_UB
|
||||
if (numsamples)
|
||||
#endif
|
||||
g_Vars.currentplayer->insightaimmode = aimonhist[numsamples - 1];
|
||||
}
|
||||
|
||||
if (!lvIsPaused()) {
|
||||
@@ -1444,31 +1603,31 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i
|
||||
}
|
||||
|
||||
#ifndef PLATFORM_N64
|
||||
// Handle turning and looking (x/y) via mouselook when aiming
|
||||
bool allowcross = allowmcross;
|
||||
if (g_Vars.currentplayer->insightaimmode && allowcross && bgunGetWeaponNum(HAND_RIGHT) != WEAPON_HORIZONSCANNER) {
|
||||
float edge_boundary = PLAYER_EXTCFG().crosshairedgeboundary;
|
||||
if (g_Vars.currentplayer->swivelpos[0] > edge_boundary) {
|
||||
movedata.aimturnrightspeed += (g_Vars.currentplayer->swivelpos[0] - edge_boundary) / (1.0f - edge_boundary);
|
||||
} else if (g_Vars.currentplayer->swivelpos[0] < -edge_boundary) {
|
||||
movedata.aimturnleftspeed += (g_Vars.currentplayer->swivelpos[0] + edge_boundary) / -(1.0f - edge_boundary);
|
||||
// Handle turning and looking up/down via mouselook when aiming
|
||||
if (g_Vars.currentplayer->insightaimmode && allowmcross && bgunGetWeaponNum(HAND_RIGHT) != WEAPON_HORIZONSCANNER) {
|
||||
if (g_Vars.currentplayer->swivelpos[0] > 0.9f) {
|
||||
movedata.aimturnrightspeed = (g_Vars.currentplayer->swivelpos[0] - 0.9f) / 0.1f;
|
||||
movedata.aimturnleftspeed = 0.f;
|
||||
} else if (g_Vars.currentplayer->swivelpos[0] < -0.9f) {
|
||||
movedata.aimturnleftspeed = (g_Vars.currentplayer->swivelpos[0] - -0.9f) / -0.1f;
|
||||
movedata.aimturnrightspeed = 0.f;
|
||||
}
|
||||
f32 vertaup = 0.f, vertadown = 0.f;
|
||||
if (g_Vars.currentplayer->swivelpos[1] > edge_boundary) {
|
||||
vertaup = (g_Vars.currentplayer->swivelpos[1] - edge_boundary) / (1.0f - edge_boundary);
|
||||
} else if (g_Vars.currentplayer->swivelpos[1] < -edge_boundary) {
|
||||
vertadown = (g_Vars.currentplayer->swivelpos[1] + edge_boundary) / -(1.0f - edge_boundary);
|
||||
if (g_Vars.currentplayer->swivelpos[1] > 0.9f) {
|
||||
vertaup = (g_Vars.currentplayer->swivelpos[1] - 0.9f) / 0.1f;
|
||||
} else if (g_Vars.currentplayer->swivelpos[1] < -0.9f) {
|
||||
vertadown = (g_Vars.currentplayer->swivelpos[1] - -0.9f) / -0.1f;
|
||||
}
|
||||
// Uninvert pitch if needed
|
||||
if (movedata.invertpitch) {
|
||||
movedata.speedvertaup += vertadown;
|
||||
movedata.speedvertadown += vertaup;
|
||||
movedata.speedvertaup = vertadown;
|
||||
movedata.speedvertadown = vertaup;
|
||||
} else {
|
||||
movedata.speedvertaup += vertaup;
|
||||
movedata.speedvertadown += vertadown;
|
||||
movedata.speedvertaup = vertaup;
|
||||
movedata.speedvertadown = vertadown;
|
||||
}
|
||||
} else {
|
||||
// Reset mouse aim position when not aiming
|
||||
// Reset mouse aim position when not mouse aiming
|
||||
g_Vars.currentplayer->swivelpos[0] = 0.f;
|
||||
g_Vars.currentplayer->swivelpos[1] = 0.f;
|
||||
}
|
||||
@@ -1535,7 +1694,7 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i
|
||||
for (i = 0; i < numsamples; i++) {
|
||||
if (joyGetButtonsOnSample(i, contpad1, c1allowedbuttons & usemask)) {
|
||||
if (g_Vars.currentplayer->usedowntime >= -1) {
|
||||
if (controlmode != CONTROLMODE_PC) {
|
||||
if (controlmode < CONTROLMODE_PC) {
|
||||
if (joyGetButtonsPressedOnSample(i, contpad1, shootbuttons & c1allowedbuttons)
|
||||
&& g_Vars.currentplayer->usedowntime >= 0
|
||||
&& bgunConsiderToggleGunFunction(g_Vars.currentplayer->usedowntime, true, false, 0) != USETIMER_CONTINUE) {
|
||||
@@ -1560,7 +1719,7 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ((controlmode != CONTROLMODE_PC) && g_Vars.currentplayer->usedowntime >= -2) {
|
||||
if ((controlmode < CONTROLMODE_PC) && g_Vars.currentplayer->usedowntime >= -2) {
|
||||
bgunConsiderToggleGunFunction(g_Vars.currentplayer->usedowntime, false, false, 0);
|
||||
}
|
||||
}
|
||||
@@ -1615,7 +1774,6 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i
|
||||
}
|
||||
|
||||
// Handle xbla-style crouch cycling
|
||||
const s32 oldcrouchpos = g_Vars.currentplayer->crouchpos;
|
||||
for (i = 0; i < numsamples; i++) {
|
||||
// handle 1964GEPD style crouch setting
|
||||
s32 crouchsample;
|
||||
@@ -1657,10 +1815,6 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i
|
||||
}
|
||||
}
|
||||
}
|
||||
// prevent uncrouching if we don't fit
|
||||
while (g_Vars.currentplayer->crouchpos > oldcrouchpos && !bwalkCanUncrouch()) {
|
||||
g_Vars.currentplayer->crouchpos--;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1711,7 +1865,7 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i
|
||||
#ifdef PLATFORM_N64
|
||||
if (allowc1buttons) {
|
||||
#else
|
||||
if (allowc1buttons && (controlmode != CONTROLMODE_PC || (PLAYER_EXTCFG().crouchmode & CROUCHMODE_ANALOG))) {
|
||||
if (allowc1buttons && (controlmode < CONTROLMODE_PC || (PLAYER_EXTCFG().crouchmode & CROUCHMODE_ANALOG))) {
|
||||
#endif
|
||||
for (i = 0; i < numsamples; i++) {
|
||||
if (!canmanualzoom && aimonhist[i]) {
|
||||
@@ -1795,7 +1949,7 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i
|
||||
}
|
||||
|
||||
// Handle mine detonation
|
||||
if (controlmode != CONTROLMODE_PC) {
|
||||
if (controlmode < CONTROLMODE_PC) {
|
||||
if ((((c1buttons & invbuttons) && (c1buttonsthisframe & B_BUTTON))
|
||||
|| ((c1buttons & B_BUTTON) && (c1buttonsthisframe & invbuttons)))
|
||||
&& weaponnum == WEAPON_REMOTEMINE) {
|
||||
@@ -1828,7 +1982,7 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i
|
||||
movedata.triggeron = g_Vars.currentplayer->waitforzrelease == false
|
||||
&& (c1buttons & shootbuttons)
|
||||
&& g_Vars.currentplayer->pausemode == PAUSEMODE_UNPAUSED;
|
||||
if (controlmode != CONTROLMODE_PC) {
|
||||
if (controlmode < CONTROLMODE_PC) {
|
||||
movedata.triggeron = movedata.triggeron && ((c1buttons & invbuttons) == 0);
|
||||
}
|
||||
}
|
||||
@@ -1842,9 +1996,7 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i
|
||||
|
||||
g_Vars.currentplayer->bondactivateorreload = 0;
|
||||
|
||||
s32 usereloads = (controlmode != CONTROLMODE_PC);
|
||||
#ifndef PLATFORM_N64
|
||||
usereloads = usereloads || PLAYER_EXTCFG().usereloads;
|
||||
if (controlmode == CONTROLMODE_PC && movedata.alt1tapcount) {
|
||||
g_Vars.currentplayer->bondactivateorreload = g_Vars.currentplayer->bondactivateorreload | JO_ACTION_RELOAD;
|
||||
}
|
||||
@@ -1852,7 +2004,7 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i
|
||||
if (movedata.btapcount) {
|
||||
g_Vars.currentplayer->activatetimelast = g_Vars.currentplayer->activatetimethis;
|
||||
g_Vars.currentplayer->activatetimethis = g_Vars.lvframe60;
|
||||
if (!usereloads) {
|
||||
if (controlmode == CONTROLMODE_PC) {
|
||||
g_Vars.currentplayer->bondactivateorreload = g_Vars.currentplayer->bondactivateorreload | JO_ACTION_ACTIVATE;
|
||||
} else {
|
||||
g_Vars.currentplayer->bondactivateorreload = movedata.btapcount ?
|
||||
@@ -2064,7 +2216,7 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i
|
||||
}
|
||||
} else {
|
||||
if (movedata.cannaturalpitch) {
|
||||
tmp = viGetFovY() / PLAYER_DEFAULT_FOV;
|
||||
tmp = viGetFovY() / 60.0f;
|
||||
fVar25 = movedata.analogpitch / 70.0f;
|
||||
|
||||
if (fVar25 > 1) {
|
||||
@@ -2105,7 +2257,7 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i
|
||||
}
|
||||
|
||||
if (movedata.cannaturalturn) {
|
||||
tmp = viGetFovY() / PLAYER_DEFAULT_FOV;
|
||||
tmp = viGetFovY() / 60.0f;
|
||||
fVar25 = movedata.analogturn / 70.0f;
|
||||
|
||||
if (fVar25 > 1) {
|
||||
@@ -2218,8 +2370,15 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i
|
||||
x = g_Vars.currentplayer->speedtheta * 0.3f + g_Vars.currentplayer->gunextraaimx;
|
||||
y = -g_Vars.currentplayer->speedverta * 0.1f + g_Vars.currentplayer->gunextraaimy;
|
||||
#else
|
||||
// Crosshair swivel movement system
|
||||
bmoveApplyCrosshairSwivel(&movedata, mlookscale, &x, &y);
|
||||
f32 xscale, yscale;
|
||||
if (movedata.freelookdx || movedata.freelookdy) {
|
||||
xscale = PLAYER_EXTCFG().crosshairsway * 0.20f;
|
||||
yscale = PLAYER_EXTCFG().crosshairsway * 0.30f;
|
||||
} else {
|
||||
xscale = yscale = PLAYER_EXTCFG().crosshairsway;
|
||||
}
|
||||
x = g_Vars.currentplayer->speedtheta * 0.3f * xscale + g_Vars.currentplayer->gunextraaimx;
|
||||
y = -g_Vars.currentplayer->speedverta * 0.1f * yscale + g_Vars.currentplayer->gunextraaimy;
|
||||
#endif
|
||||
|
||||
bgunSwivelWithDamp(x, y, PAL ? 0.955f : 0.963f);
|
||||
@@ -2231,10 +2390,8 @@ void bmoveProcessInput(bool allowc1x, bool allowc1y, bool allowc1buttons, bool i
|
||||
#ifndef PLATFORM_N64
|
||||
if (allowmcross) {
|
||||
// joystick is inactive, move crosshair using the mouse
|
||||
const f32 xcoeff = 320.f / 1080.f;
|
||||
const f32 ycoeff = 240.f / 1080.f;
|
||||
const f32 xscale = (PLAYER_EXTCFG().mouseaimspeedx * xcoeff) / g_Vars.currentplayer->aspect;
|
||||
const f32 yscale = PLAYER_EXTCFG().mouseaimspeedy * ycoeff;
|
||||
const f32 xscale = PLAYER_EXTCFG().mouseaimspeedx * 320.f / (f32)videoGetWidth();
|
||||
const f32 yscale = PLAYER_EXTCFG().mouseaimspeedy * 240.f / (f32)videoGetHeight();
|
||||
f32 x = g_Vars.currentplayer->swivelpos[0] + movedata.freelookdx * xscale;
|
||||
f32 y = g_Vars.currentplayer->swivelpos[1] + movedata.freelookdy * yscale;
|
||||
x = (x < -1.f) ? -1.f : ((x > 1.f) ? 1.f : x);
|
||||
@@ -2415,6 +2572,14 @@ void bmoveTick(bool allowc1x, bool allowc1y, bool allowc1buttons, bool ignorec2)
|
||||
|
||||
void bmoveUpdateVerta(void)
|
||||
{
|
||||
while (g_Vars.currentplayer->vv_verta < -180) {
|
||||
g_Vars.currentplayer->vv_verta += 360;
|
||||
}
|
||||
|
||||
while (g_Vars.currentplayer->vv_verta >= 180) {
|
||||
g_Vars.currentplayer->vv_verta -= 360;
|
||||
}
|
||||
|
||||
if (g_Vars.currentplayer->vv_verta > 90) {
|
||||
g_Vars.currentplayer->vv_verta = 90;
|
||||
} else if (g_Vars.currentplayer->vv_verta < -90) {
|
||||
@@ -2519,7 +2684,7 @@ void bmoveUpdateHead(f32 arg0, f32 arg1, f32 arg2, Mtxf *arg3, f32 arg4)
|
||||
}
|
||||
} else {
|
||||
if (g_Vars.currentplayer->startnewbonddie) {
|
||||
bheadStartDeathAnimation(g_DeathAnimations[rngRandom() % g_NumDeathAnimations], rngRandom() % 2, 0, 1);
|
||||
bheadStartDeathAnimation(g_DeathAnimations[random() % g_NumDeathAnimations], random() % 2, 0, 1);
|
||||
g_Vars.currentplayer->startnewbonddie = false;
|
||||
}
|
||||
|
||||
@@ -2530,7 +2695,13 @@ void bmoveUpdateHead(f32 arg0, f32 arg1, f32 arg2, Mtxf *arg3, f32 arg4)
|
||||
bheadUpdate(sp244, arg2);
|
||||
mtx4LoadXRotation(BADDEG2RAD(360 - g_Vars.currentplayer->vv_verta360), &sp180);
|
||||
|
||||
#ifdef PLATFORM_N64
|
||||
if (optionsGetHeadRoll(g_Vars.currentplayerstats->mpindex)) {
|
||||
#else
|
||||
// in net games only allow headroll in the death animation
|
||||
// TODO: figure out how to deal with headroll in other situations
|
||||
if (optionsGetHeadRoll(g_Vars.currentplayerstats->mpindex) && (!g_NetMode || g_Vars.currentplayer->isdead)) {
|
||||
#endif
|
||||
mtx00016d58(&sp116,
|
||||
0, 0, 0,
|
||||
-g_Vars.currentplayer->headlook.x, -g_Vars.currentplayer->headlook.y, -g_Vars.currentplayer->headlook.z,
|
||||
|
||||
+13
-48
@@ -31,7 +31,7 @@ char var800a41c0[26];
|
||||
char var800a41c0[24];
|
||||
#endif
|
||||
|
||||
u8 g_IrScanlines[4][480];
|
||||
u8 g_IrScanlines[2][480];
|
||||
|
||||
#if VERSION < VERSION_NTSC_1_0
|
||||
u8 var800a8b58nb[0x1c0];
|
||||
@@ -335,7 +335,7 @@ Gfx *bviewDrawStatic(Gfx *gdl, u32 arg1, s32 arg2)
|
||||
s32 viewheight = viGetViewHeight();
|
||||
s32 viewwidth = viGetViewWidth();
|
||||
s32 viewleft = viGetViewLeft();
|
||||
u16 *fb2 = (u16 *) PHYS_TO_K0(rngRandom() & 0xfff00);
|
||||
u16 *fb2 = (u16 *) PHYS_TO_K0(random() & 0xfff00);
|
||||
s32 y;
|
||||
|
||||
gDPPipeSync(gdl++);
|
||||
@@ -344,7 +344,7 @@ Gfx *bviewDrawStatic(Gfx *gdl, u32 arg1, s32 arg2)
|
||||
|
||||
#ifdef PLATFORM_N64
|
||||
for (y = viewtop; y < viewtop + viewheight; y++) {
|
||||
gdl = bviewCopyPixels(gdl, fb2, rngRandom() % 240, 5, y, 1.0f, viewleft, viewwidth);
|
||||
gdl = bviewCopyPixels(gdl, fb2, random() % 240, 5, y, 1.0f, viewleft, viewwidth);
|
||||
}
|
||||
#else
|
||||
gDPSetCombineLERP(gdl++,
|
||||
@@ -468,8 +468,8 @@ Gfx *bviewDrawFilmInterlace(Gfx *gdl, u32 colour, u32 alpha)
|
||||
}
|
||||
}
|
||||
|
||||
if (rngRandom() % 20 == 1) {
|
||||
tmpy = rngRandom() % 200;
|
||||
if (random() % 20 == 1) {
|
||||
tmpy = random() % 200;
|
||||
}
|
||||
|
||||
gdl = bviewCopyPixels(gdl, fb, tmpy, 5, y, 1, viewleft, viewwidth);
|
||||
@@ -490,8 +490,8 @@ Gfx *bviewDrawFilmInterlace(Gfx *gdl, u32 colour, u32 alpha)
|
||||
}
|
||||
}
|
||||
|
||||
if (rngRandom() % 20 == 1) {
|
||||
tmpy += rngRandom() % 200;
|
||||
if (random() % 20 == 1) {
|
||||
tmpy += random() % 200;
|
||||
}
|
||||
|
||||
gDPFillRectangle(gdl++, viewleft, tmpy, viewleft + viewwidth, tmpy + 1);
|
||||
@@ -762,9 +762,9 @@ Gfx *bviewDrawFisheye(Gfx *gdl, u32 colour, u32 alpha, s32 shuttertime60, s8 sta
|
||||
|
||||
for (i = viewtop; i < viewtop + viewheight; i++) {
|
||||
if (hit == EYESPYHIT_DAMAGE) {
|
||||
alpha2 = (rngRandom() % 120) + 120;
|
||||
alpha2 = (random() % 120) + 120;
|
||||
colour = 0xff333300 | (alpha2 & 0xff);
|
||||
f22 = ((rngRandom() % 32) + (f32) FBALLOC_HEIGHT) * (1.0f / 256.0f);
|
||||
f22 = ((random() % 32) + (f32) FBALLOC_HEIGHT) * (1.0f / 256.0f);
|
||||
|
||||
gDPSetEnvColorViaWord(gdl++, colour);
|
||||
} else {
|
||||
@@ -1109,10 +1109,6 @@ Gfx *bviewDrawEyespyMetrics(Gfx *gdl)
|
||||
s32 x = viewleft + (viewwidth >> 1);
|
||||
s32 y = viewtop + (viewheight >> 1);
|
||||
|
||||
#ifndef PLATFORM_N64
|
||||
gDPSetSubpixelOffsetEXT(gdl++, -2, -2);
|
||||
#endif
|
||||
|
||||
gDPFillRectangle(gdl++, x + 2, y + 0, x + 7, y + 1);
|
||||
gDPFillRectangle(gdl++, x + 2, y + 0, x + 5, y + 1);
|
||||
gDPFillRectangle(gdl++, x - 6, y + 0, x - 1, y + 1);
|
||||
@@ -1121,10 +1117,6 @@ Gfx *bviewDrawEyespyMetrics(Gfx *gdl)
|
||||
gDPFillRectangle(gdl++, x + 0, y + 2, x + 1, y + 5);
|
||||
gDPFillRectangle(gdl++, x + 0, y - 6, x + 1, y - 1);
|
||||
gDPFillRectangle(gdl++, x + 0, y - 4, x + 1, y - 1);
|
||||
|
||||
#ifndef PLATFORM_N64
|
||||
gDPSetSubpixelOffsetEXT(gdl++, 0, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (g_Vars.currentplayer->eyespy->mode == EYESPYMODE_CAMSPY) {
|
||||
@@ -2171,7 +2163,7 @@ Gfx *bviewDrawNvLens(Gfx *gdl)
|
||||
u8 green;
|
||||
|
||||
if (((var8007f878 & 1) != (y & 1)) != 0) {
|
||||
u8 tmp = rngRandom() % 12;
|
||||
u8 tmp = random() % 12;
|
||||
green = 0xff - tmp;
|
||||
} else {
|
||||
green = 0x94;
|
||||
@@ -2189,7 +2181,7 @@ Gfx *bviewDrawNvLens(Gfx *gdl)
|
||||
u8 green;
|
||||
|
||||
if (((var8007f878 & 1) != (y & 1)) != 0) {
|
||||
u8 tmp = rngRandom() % 12;
|
||||
u8 tmp = random() % 12;
|
||||
green = 0xff - tmp;
|
||||
} else {
|
||||
green = 0x94;
|
||||
@@ -2356,10 +2348,6 @@ Gfx *bviewDrawIrLens(Gfx *gdl)
|
||||
gSPSetExtraGeometryModeEXT(gdl++, G_MODULATE_EXT);
|
||||
#endif
|
||||
|
||||
// fixes off by one error w/ two top players
|
||||
if (g_Vars.currentplayernum == 0 || g_Vars.currentplayernum == 1) {
|
||||
scanbottom++;
|
||||
}
|
||||
for (i = scantop; i < scanbottom; i++) {
|
||||
#if VERSION >= VERSION_NTSC_1_0
|
||||
if (i & 1) {
|
||||
@@ -2375,7 +2363,7 @@ Gfx *bviewDrawIrLens(Gfx *gdl)
|
||||
}
|
||||
#endif
|
||||
|
||||
red += rngRandom() % 8;
|
||||
red += random() % 8;
|
||||
|
||||
if (red > 255) {
|
||||
red = 255;
|
||||
@@ -2396,10 +2384,6 @@ Gfx *bviewDrawIrLens(Gfx *gdl)
|
||||
s32 semicirclewidth = sqrtf(sqinnerradius - (s32) (f0 * f0)) * (viewwidth / (f32) SCREEN_WIDTH_LO);
|
||||
s32 semicircleright = viewcentrex + semicirclewidth;
|
||||
s32 rightsidewidth = viewwidth - semicircleright;
|
||||
// if playernum is 1 or 3, shift to the right by viewwidth
|
||||
if (g_Vars.currentplayernum == 1 || g_Vars.currentplayernum == 3) {
|
||||
rightsidewidth += viewwidth;
|
||||
}
|
||||
|
||||
#ifdef PLATFORM_N64
|
||||
// Left and right of semicircle
|
||||
@@ -2413,22 +2397,14 @@ Gfx *bviewDrawIrLens(Gfx *gdl)
|
||||
gdl = bviewCopyPixels(gdl, fb, i, 5, i, 1.0f, viewleft, viewwidth);
|
||||
}
|
||||
#else
|
||||
|
||||
// Scanlines to the left and right of the semicircle
|
||||
// Left and right of semicircle
|
||||
gDPFillRectangle(gdl++, viewleft, i, viewcentrex, i + 1);
|
||||
if (PLAYERCOUNT() <= 2 && g_Vars.currentplayernum == 0 && i == viewcentrey) {
|
||||
semicircleright -= 1;
|
||||
}
|
||||
else if (PLAYERCOUNT() > 2 && (g_Vars.currentplayernum == 1 || g_Vars.currentplayernum == 3 ) && i == viewcentrey) {
|
||||
semicircleright -= 1;
|
||||
}
|
||||
gDPFillRectangle(gdl++, semicircleright, i, semicircleright + rightsidewidth, i + 1);
|
||||
|
||||
// The semicircle itself has a static colour
|
||||
gDPSetPrimColorViaWord(gdl++, 0, 0, 0xee0000ff);
|
||||
gDPFillRectangle(gdl++, viewcentrex, i, viewcentrex + semicirclewidth, i + 1);
|
||||
} else {
|
||||
// scanlines above and below the semicircle
|
||||
gDPFillRectangle(gdl++, viewleft, i, viewleft + viewwidth, i + 1);
|
||||
}
|
||||
#endif
|
||||
@@ -2797,10 +2773,6 @@ Gfx *bviewDrawIrBinoculars(Gfx *gdl)
|
||||
s32 viewleft = viGetViewLeft();
|
||||
s32 viewright = viewleft + viewwidth;
|
||||
s32 viewbottom = viewtop + viewheight;
|
||||
// fixes off by one error w/ two top players
|
||||
if (g_Vars.currentplayernum == 0 || g_Vars.currentplayernum == 1) {
|
||||
viewbottom++;
|
||||
}
|
||||
s32 leftx = viewleft + viewwidth / 3;
|
||||
s32 rightx = viewleft + (viewwidth * 2) / 3;
|
||||
s32 centrey = (viewtop + viewbottom) / 2;
|
||||
@@ -2818,13 +2790,6 @@ Gfx *bviewDrawIrBinoculars(Gfx *gdl)
|
||||
for (y = viewtop; y < viewbottom; y++) {
|
||||
s32 ytocentre = centrey - y;
|
||||
s32 sqytocentre = ytocentre * ytocentre;
|
||||
if (PLAYERCOUNT() <= 2) {
|
||||
sqytocentre += 1;
|
||||
} else if (PLAYERCOUNT() > 2) {
|
||||
if (g_Vars.currentplayernum == 1 || g_Vars.currentplayernum == 3) {
|
||||
sqytocentre += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (sqytocentre < sqradius) {
|
||||
s32 xoffset = (viewwidth / (f32) SCREEN_WIDTH_LO) * sqrtf(sqradius - sqytocentre);
|
||||
|
||||
+73
-80
@@ -27,7 +27,69 @@
|
||||
#include "data.h"
|
||||
#include "types.h"
|
||||
#ifndef PLATFORM_N64
|
||||
extern f32 fabsf(f32);
|
||||
#include "net/net.h"
|
||||
#include "system.h"
|
||||
#include "utils.h"
|
||||
|
||||
static inline void lerpcoord(struct coord *c, const struct coord *a, const struct coord *b, const f32 t) {
|
||||
c->x = lerpf(a->x, b->x, t);
|
||||
c->y = lerpf(a->y, b->y, t);
|
||||
c->z = lerpf(a->z, b->z, t);
|
||||
}
|
||||
|
||||
static void bwalkUpdateRemote(void)
|
||||
{
|
||||
struct player *pl = g_Vars.currentplayer;
|
||||
const struct netplayermove *inmove = &pl->client->inmove[0];
|
||||
const struct netplayermove *inmoveprev = &pl->client->inmove[1];
|
||||
struct coord delta;
|
||||
u16 cdtype = CDTYPE_ALL;
|
||||
s32 moveticks = inmove->tick - inmoveprev->tick;
|
||||
if (moveticks > g_NetInterpTicks) {
|
||||
moveticks = g_NetInterpTicks;
|
||||
}
|
||||
|
||||
pl->client->inmovetick = inmove->tick;
|
||||
|
||||
pl->bondshotspeed.x = 0.f;
|
||||
pl->bondshotspeed.y = 0.f;
|
||||
pl->bondshotspeed.z = 0.f;
|
||||
pl->bondbreathing = 0.f;
|
||||
|
||||
const bool forcepos = !inmoveprev->tick ||
|
||||
(inmove->ucmd & UCMD_FL_FORCEPOS) ||
|
||||
(fabsf(pl->prop->pos.x - inmove->pos.x) > 512.f) ||
|
||||
(fabsf(pl->prop->pos.y - inmove->pos.y) > 512.f) ||
|
||||
(fabsf(pl->prop->pos.z - inmove->pos.z) > 512.f);
|
||||
|
||||
delta.x = 0.f;
|
||||
delta.y = 0.f;
|
||||
delta.z = 0.f;
|
||||
|
||||
// extrapolate
|
||||
bwalk0f0c69b8();
|
||||
|
||||
if (forcepos) {
|
||||
// no interpolation, set position and lock the lad in place
|
||||
pl->prop->pos = inmove->pos;
|
||||
pl->client->lerpticks = g_NetInterpTicks + 1;
|
||||
cdtype = CDTYPE_PLAYERS; // don't get stuck in the local client
|
||||
} else if (!moveticks) {
|
||||
// duplicate move, reposition to correct coords
|
||||
delta.x = inmove->pos.x - pl->prop->pos.x;
|
||||
delta.x = inmove->pos.y - pl->prop->pos.y;
|
||||
delta.x = inmove->pos.z - pl->prop->pos.z;
|
||||
bwalk0f0c63bc(&delta, pl->swaytarget == 0.0f, cdtype);
|
||||
} else if (pl->client->lerpticks <= moveticks) {
|
||||
// lerp towards the correct position
|
||||
const f32 dt = (f32)1.f / (f32)moveticks;
|
||||
delta.x = g_Vars.lvupdate60freal * (inmove->pos.x - pl->prop->pos.x) * dt;
|
||||
delta.y = g_Vars.lvupdate60freal * (inmove->pos.y - pl->prop->pos.y) * dt;
|
||||
delta.z = g_Vars.lvupdate60freal * (inmove->pos.z - pl->prop->pos.z) * dt;
|
||||
bwalk0f0c63bc(&delta, pl->swaytarget == 0.0f, cdtype);
|
||||
pl->client->lerpticks += g_Vars.lvupdate60;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void bwalkInit(void)
|
||||
@@ -237,47 +299,6 @@ s32 bwalkTryMoveUpwards(f32 amount)
|
||||
return result;
|
||||
}
|
||||
|
||||
bool bwalkCanMoveUpwards(f32 amount)
|
||||
{
|
||||
bool result;
|
||||
struct coord newpos;
|
||||
RoomNum rooms[8];
|
||||
u32 stack;
|
||||
u32 types;
|
||||
f32 ymax;
|
||||
f32 ymin;
|
||||
f32 radius;
|
||||
|
||||
if (g_Vars.currentplayer->floorflags & GEOFLAG_SLOPE) {
|
||||
g_Vars.enableslopes = false;
|
||||
} else {
|
||||
g_Vars.enableslopes = true;
|
||||
}
|
||||
|
||||
newpos.x = g_Vars.currentplayer->prop->pos.x;
|
||||
newpos.y = g_Vars.currentplayer->prop->pos.y + amount;
|
||||
newpos.z = g_Vars.currentplayer->prop->pos.z;
|
||||
|
||||
types = g_Vars.bondcollisions ? CDTYPE_ALL : CDTYPE_BG;
|
||||
|
||||
playerGetBbox(g_Vars.currentplayer->prop, &radius, &ymax, &ymin);
|
||||
func0f065e74(&g_Vars.currentplayer->prop->pos, g_Vars.currentplayer->prop->rooms, &newpos, rooms);
|
||||
bmoveFindEnteredRoomsByPos(g_Vars.currentplayer, &newpos, rooms);
|
||||
propSetPerimEnabled(g_Vars.currentplayer->prop, false);
|
||||
|
||||
ymin -= 0.1f;
|
||||
|
||||
result = cdTestVolume(&newpos, radius, rooms, types, CHECKVERTICAL_YES,
|
||||
ymax - g_Vars.currentplayer->prop->pos.y,
|
||||
ymin - g_Vars.currentplayer->prop->pos.y);
|
||||
|
||||
propSetPerimEnabled(g_Vars.currentplayer->prop, true);
|
||||
|
||||
g_Vars.enableslopes = true;
|
||||
|
||||
return (result == CDRESULT_NOCOLLISION);
|
||||
}
|
||||
|
||||
bool bwalkCalculateNewPosition(struct coord *vel, f32 rotateamount, bool apply, f32 extrawidth, s32 checktypes)
|
||||
{
|
||||
s32 result = CDRESULT_NOCOLLISION;
|
||||
@@ -454,7 +475,7 @@ bool bwalkCalculateNewPositionWithPush(struct coord *delta, f32 rotateamount, bo
|
||||
}
|
||||
} else if (chr->chrflags & CHRCFLAG_PUSHABLE) {
|
||||
if (g_Vars.antiplayernum < 0
|
||||
|| g_Vars.currentplayer != g_Vars.anti
|
||||
|| PLAYER_IS_NOT_ANTI(g_Vars.currentplayer)
|
||||
|| (chr->hidden & CHRHFLAG_ANTINONINTERACTABLE) == 0) {
|
||||
canpush = true;
|
||||
}
|
||||
@@ -788,7 +809,7 @@ void bwalkUpdateVertical(void)
|
||||
// Maybe reset counter-op's radius - not sure why
|
||||
// Maybe it gets set to 0 when they die?
|
||||
if (g_Vars.antiplayernum >= 0
|
||||
&& g_Vars.currentplayer == g_Vars.anti
|
||||
&& PLAYER_IS_ANTI(g_Vars.currentplayer)
|
||||
&& g_Vars.currentplayer->bond2.radius != 30
|
||||
&& cdTestVolume(&g_Vars.currentplayer->prop->pos, 30, g_Vars.currentplayer->prop->rooms, CDTYPE_ALL, CHECKVERTICAL_YES, ymax - g_Vars.currentplayer->prop->pos.y, ymin - g_Vars.currentplayer->prop->pos.y)) {
|
||||
g_Vars.currentplayer->prop->chr->radius = 30;
|
||||
@@ -1111,7 +1132,7 @@ void bwalkUpdateVertical(void)
|
||||
SFX_JO_LANDING_05B7
|
||||
};
|
||||
|
||||
psCreate(NULL, g_Vars.currentplayer->prop, sounds[rngRandom() % 3],
|
||||
psCreate(NULL, g_Vars.currentplayer->prop, sounds[random() % 3],
|
||||
-1, -1, PSFLAG_0400 | PSFLAG_IGNOREROOMS, 0, PSTYPE_NONE, 0, -1, NULL, -1, -1, -1, -1);
|
||||
}
|
||||
}
|
||||
@@ -1209,41 +1230,6 @@ void bwalkUpdateCrouchOffsetReal(void)
|
||||
}
|
||||
}
|
||||
|
||||
bool bwalkCanUncrouch(void)
|
||||
{
|
||||
f32 targetoffset = 0;
|
||||
|
||||
if (g_Vars.currentplayer->crouchpos == CROUCHPOS_SQUAT) {
|
||||
targetoffset = -90;
|
||||
} else if (g_Vars.currentplayer->crouchpos == CROUCHPOS_DUCK) {
|
||||
targetoffset = -45;
|
||||
}
|
||||
|
||||
if (targetoffset != g_Vars.currentplayer->crouchoffset) {
|
||||
f32 prevcrouchoffset = g_Vars.currentplayer->crouchoffset;
|
||||
f32 prevcrouchoffsetreal = g_Vars.currentplayer->crouchoffsetreal;
|
||||
f32 prevcrouchoffsetsmall = g_Vars.currentplayer->crouchoffsetsmall;
|
||||
f32 prevcrouchoffsetrealsmall = g_Vars.currentplayer->crouchoffsetrealsmall;
|
||||
f32 prevcrouchspeed = g_Vars.currentplayer->crouchspeed;
|
||||
|
||||
g_Vars.currentplayer->crouchoffset = targetoffset;
|
||||
|
||||
bwalkUpdateCrouchOffsetReal();
|
||||
|
||||
const bool result = bwalkCanMoveUpwards(0);
|
||||
|
||||
g_Vars.currentplayer->crouchoffset = prevcrouchoffset;
|
||||
g_Vars.currentplayer->crouchoffsetreal = prevcrouchoffsetreal;
|
||||
g_Vars.currentplayer->crouchoffsetsmall = prevcrouchoffsetsmall;
|
||||
g_Vars.currentplayer->crouchoffsetrealsmall = prevcrouchoffsetrealsmall;
|
||||
g_Vars.currentplayer->crouchspeed = prevcrouchspeed;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void bwalkUpdateCrouchOffset(void)
|
||||
{
|
||||
f32 targetoffset = 0;
|
||||
@@ -1843,7 +1829,14 @@ void bwalkTick(void)
|
||||
bwalkUpdatePrevPos();
|
||||
bwalkUpdateTheta();
|
||||
bmoveUpdateVerta();
|
||||
|
||||
#ifndef PLATFORM_N64
|
||||
if (g_Vars.currentplayer->isremote) {
|
||||
bwalkUpdateRemote();
|
||||
} else
|
||||
#endif
|
||||
bwalk0f0c69b8();
|
||||
|
||||
bwalkUpdateVertical();
|
||||
|
||||
#if VERSION >= VERSION_NTSC_1_0
|
||||
|
||||
+5
-1
@@ -138,6 +138,8 @@ void bossfileLoad(void)
|
||||
g_BossFile.usingmultipletunes = savebufferReadBits(&buffer, 1);
|
||||
g_AltTitleUnlocked = savebufferReadBits(&buffer, 1);
|
||||
g_AltTitleEnabled = savebufferReadBits(&buffer, 1);
|
||||
|
||||
func0f0d54c4(&buffer);
|
||||
}
|
||||
|
||||
if (failed) {
|
||||
@@ -166,7 +168,7 @@ void bossfileSave(void)
|
||||
savebufferOr(&buffer, g_Vars.language, 4);
|
||||
|
||||
for (i = 0; i < ARRAYCOUNT(g_BossFile.teamnames); i++) {
|
||||
savebufferWriteString(&buffer, g_BossFile.teamnames[i]);
|
||||
func0f0d55a4(&buffer, g_BossFile.teamnames[i]);
|
||||
}
|
||||
|
||||
if (g_BossFile.tracknum == -1) {
|
||||
@@ -183,6 +185,8 @@ void bossfileSave(void)
|
||||
savebufferOr(&buffer, g_AltTitleUnlocked, 1);
|
||||
savebufferOr(&buffer, g_AltTitleEnabled, 1);
|
||||
|
||||
func0f0d54c4(&buffer);
|
||||
|
||||
fileid = bossfileFindFileId();
|
||||
|
||||
if (fileid == 0) {
|
||||
|
||||
+43
-52
@@ -185,13 +185,13 @@ void botReset(struct chrdata *chr, u8 respawning)
|
||||
|
||||
aibot->waypoints[0] = NULL;
|
||||
aibot->numwaystepstotarget = 0;
|
||||
aibot->random1 = rngRandom();
|
||||
aibot->random1 = random();
|
||||
aibot->random1ttl60 = 0;
|
||||
aibot->targetcloaktimer60 = 0;
|
||||
aibot->canseecloaked = 0;
|
||||
aibot->rcpcloaktimer60 = 0;
|
||||
aibot->random2ttl60 = 0;
|
||||
aibot->random2 = rngRandom();
|
||||
aibot->random2 = random();
|
||||
aibot->randomfrac = RANDOMFRAC();
|
||||
aibot->cheap = 0;
|
||||
|
||||
@@ -262,21 +262,12 @@ void botSpawn(struct chrdata *chr, u8 respawning)
|
||||
func0f02e9a0(chr, 0);
|
||||
|
||||
#ifndef PLATFORM_N64
|
||||
if (g_Vars.normmplayerisrunning
|
||||
&& (g_MpSetup.options & MPOPTION_SPAWNWITHWEAPON)
|
||||
if ((g_MpSetup.options & MPOPTION_SPAWNWITHWEAPON)
|
||||
&& g_MpSetup.weapons[0] != MPWEAPON_NONE
|
||||
&& g_MpSetup.weapons[0] != MPWEAPON_DISABLED
|
||||
&& g_MpSetup.weapons[0] != MPWEAPON_SHIELD) {
|
||||
&& g_MpSetup.weapons[0] != MPWEAPON_DISABLED) {
|
||||
struct mpweapon *mpweapon = &g_MpWeapons[g_MpSetup.weapons[0]];
|
||||
botinvGiveSingleWeapon(chr, mpweapon->weaponnum);
|
||||
const s32 ammotype = (g_MpSetup.weapons[0] == MPWEAPON_COMBATBOOST) ? AMMOTYPE_BOOST : mpweapon->priammotype;
|
||||
if (ammotype) {
|
||||
s32 startammo = mpweapon->priammoqty / 2;
|
||||
if (startammo == 0) {
|
||||
startammo = 1;
|
||||
}
|
||||
botactGiveAmmoByType(aibot, ammotype, startammo);
|
||||
}
|
||||
botactGiveAmmoByType(aibot, mpweapon->priammotype - 1, mpweapon->priammoqty / 2);
|
||||
botinvSwitchToWeapon(chr, mpweapon->weaponnum, FUNC_PRIMARY);
|
||||
}
|
||||
#endif
|
||||
@@ -1418,8 +1409,8 @@ void bot0f192a74(struct chrdata *chr)
|
||||
aibot->random3ttl60 -= g_Vars.lvupdate60;
|
||||
|
||||
if (aibot->random3ttl60 <= 0) {
|
||||
aibot->random3 = rngRandom();
|
||||
aibot->random3ttl60 = TICKS(20) + rngRandom() % TICKS(20);
|
||||
aibot->random3 = random();
|
||||
aibot->random3ttl60 = TICKS(20) + random() % TICKS(20);
|
||||
}
|
||||
|
||||
if (g_Vars.lvupdate240 > 0) {
|
||||
@@ -1560,7 +1551,7 @@ void botChooseGeneralTarget(struct chrdata *botchr)
|
||||
// However, the usage of canseecloaked appears to be botched.
|
||||
// It is implemented in botIsTargetInvisible, but that function is not
|
||||
// called here while canseecloaked is true.
|
||||
if (rngRandom() % TICKS(4 * 60 * 60) < g_MpNumChrs * g_Vars.lvupdate60) {
|
||||
if (random() % TICKS(4 * 60 * 60) < g_MpNumChrs * g_Vars.lvupdate60) {
|
||||
aibot->canseecloaked = true;
|
||||
}
|
||||
|
||||
@@ -1755,7 +1746,7 @@ s32 botFindTeammateToFollow(struct chrdata *chr, f32 range)
|
||||
|
||||
if ((g_MpSetup.options & MPOPTION_TEAMSENABLED)
|
||||
&& chr->myaction != MA_AIBOTFOLLOW
|
||||
&& (rngRandom() % 100) < chr->aibot->followchance) {
|
||||
&& (random() % 100) < chr->aibot->followchance) {
|
||||
f32 closestdistance = 0;
|
||||
s32 closestplayernum = -1;
|
||||
s32 i;
|
||||
@@ -1893,8 +1884,8 @@ struct prop *botFindPickup(struct chrdata *chr, s32 criteria)
|
||||
|
||||
for (i = 0; i < ARRAYCOUNT(weaponnums); i++) {
|
||||
if (weaponnums[i] > WEAPON_UNARMED && weaponnums[i] == weapon->weaponnum) {
|
||||
if (rngRandom() % 16) {
|
||||
if (weapproplist[i] == NULL || sqdist1 < weapdistlist[i] || rngRandom() % 16 == 0) {
|
||||
if (random() % 16) {
|
||||
if (weapproplist[i] == NULL || sqdist1 < weapdistlist[i] || random() % 16 == 0) {
|
||||
weapproplist[i] = prop;
|
||||
weapdistlist[i] = sqdist1;
|
||||
}
|
||||
@@ -1905,8 +1896,8 @@ struct prop *botFindPickup(struct chrdata *chr, s32 criteria)
|
||||
|
||||
ammotype = botactGetAmmoTypeByFunction(weapon->weaponnum, FUNC_PRIMARY);
|
||||
|
||||
if (ammotype > 0 && rngRandom() % 16) {
|
||||
if (ammoproplist[ammotype] == NULL || sqdist1 < ammodistlist[ammotype] || rngRandom() % 16 == 0) {
|
||||
if (ammotype > 0 && random() % 16) {
|
||||
if (ammoproplist[ammotype] == NULL || sqdist1 < ammodistlist[ammotype] || random() % 16 == 0) {
|
||||
ammoproplist[ammotype] = prop;
|
||||
ammodistlist[ammotype] = sqdist1;
|
||||
}
|
||||
@@ -1929,8 +1920,8 @@ struct prop *botFindPickup(struct chrdata *chr, s32 criteria)
|
||||
if (weaponnum > 0) {
|
||||
for (j = 0; j < ARRAYCOUNT(weaponnums); j++) {
|
||||
if (weaponnums[j] > WEAPON_UNARMED && weaponnum == weaponnums[j]) {
|
||||
if (rngRandom() % 16) {
|
||||
if (weapproplist[j] == NULL || sqdist2 < weapdistlist[j] || rngRandom() % 16 == 0) {
|
||||
if (random() % 16) {
|
||||
if (weapproplist[j] == NULL || sqdist2 < weapdistlist[j] || random() % 16 == 0) {
|
||||
weapproplist[j] = prop;
|
||||
weapdistlist[j] = sqdist2;
|
||||
}
|
||||
@@ -1940,8 +1931,8 @@ struct prop *botFindPickup(struct chrdata *chr, s32 criteria)
|
||||
}
|
||||
}
|
||||
|
||||
if (rngRandom() % 16) {
|
||||
if (ammoproplist[ammotype] == NULL || sqdist2 < ammodistlist[ammotype] || rngRandom() % 16 == 0) {
|
||||
if (random() % 16) {
|
||||
if (ammoproplist[ammotype] == NULL || sqdist2 < ammodistlist[ammotype] || random() % 16 == 0) {
|
||||
ammoproplist[ammotype] = prop;
|
||||
ammodistlist[ammotype] = sqdist2;
|
||||
}
|
||||
@@ -1953,11 +1944,11 @@ struct prop *botFindPickup(struct chrdata *chr, s32 criteria)
|
||||
if (weaponnums[i] == WEAPON_MPSHIELD) {
|
||||
sqdist2 = chrGetSquaredDistanceToCoord(chr, &prop->pos);
|
||||
|
||||
if (rngRandom() % 16 == 0) {
|
||||
if (random() % 16 == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (weapproplist[i] == NULL || sqdist2 < weapdistlist[i] || rngRandom() % 16 == 0) {
|
||||
if (weapproplist[i] == NULL || sqdist2 < weapdistlist[i] || random() % 16 == 0) {
|
||||
weapproplist[i] = prop;
|
||||
weapdistlist[i] = sqdist2;
|
||||
}
|
||||
@@ -2408,8 +2399,8 @@ void botTickUnpaused(struct chrdata *chr)
|
||||
aibot->random2ttl60 -= g_Vars.lvupdate60;
|
||||
|
||||
if (aibot->random2ttl60 < 0) {
|
||||
aibot->random2ttl60 = TICKS(1800) + rngRandom() % TICKS(60 * 240);
|
||||
aibot->random2 = rngRandom();
|
||||
aibot->random2ttl60 = TICKS(1800) + random() % TICKS(60 * 240);
|
||||
aibot->random2 = random();
|
||||
aibot->randomfrac = RANDOMFRAC();
|
||||
}
|
||||
|
||||
@@ -2540,7 +2531,7 @@ void botTickUnpaused(struct chrdata *chr)
|
||||
if (g_MpSetup.scenario == MPSCENARIO_HOLDTHEBRIEFCASE) {
|
||||
s32 numgetting = botGetCountInTeamDoingCommand(chr, AIBOTCMD_GETCASE2, false);
|
||||
|
||||
if (numgetting <= 0 || (numgetting < (teamsize + 1) / 2 || rngRandom() % 100 < 66)) {
|
||||
if (numgetting <= 0 || (numgetting < (teamsize + 1) / 2 || random() % 100 < 66)) {
|
||||
botApplyScenarioCommand(chr, AIBOTCMD_GETCASE2);
|
||||
} else {
|
||||
botApplyScenarioCommand(chr, AIBOTCMD_NORMAL);
|
||||
@@ -2548,7 +2539,7 @@ void botTickUnpaused(struct chrdata *chr)
|
||||
} else if (g_MpSetup.scenario == MPSCENARIO_HACKERCENTRAL) {
|
||||
s32 numbots = botGetCountInTeamDoingCommand(chr, AIBOTCMD_DOWNLOAD, false);
|
||||
|
||||
if (aibot->hasuplink || numbots <= 0 || (numbots < (teamsize + 1) / 2 || rngRandom() % 100 < 50)) {
|
||||
if (aibot->hasuplink || numbots <= 0 || (numbots < (teamsize + 1) / 2 || random() % 100 < 50)) {
|
||||
botApplyScenarioCommand(chr, AIBOTCMD_DOWNLOAD);
|
||||
} else {
|
||||
botApplyScenarioCommand(chr, AIBOTCMD_NORMAL);
|
||||
@@ -2556,7 +2547,7 @@ void botTickUnpaused(struct chrdata *chr)
|
||||
} else if (g_MpSetup.scenario == MPSCENARIO_POPACAP) {
|
||||
s32 numchasing = botGetCountInTeamDoingCommand(chr, AIBOTCMD_POPCAP, false);
|
||||
|
||||
if (numchasing <= 0 || numchasing < (teamsize + 1) / 2 || rngRandom() % 100 < 50) {
|
||||
if (numchasing <= 0 || numchasing < (teamsize + 1) / 2 || random() % 100 < 50) {
|
||||
botApplyScenarioCommand(chr, AIBOTCMD_POPCAP);
|
||||
} else {
|
||||
botApplyScenarioCommand(chr, AIBOTCMD_NORMAL);
|
||||
@@ -2572,7 +2563,7 @@ void botTickUnpaused(struct chrdata *chr)
|
||||
if (numinhill <= 0 || numinhill < teamsize / 2) {
|
||||
botApplyScenarioCommand(chr, AIBOTCMD_HOLDHILL);
|
||||
} else if (numinhill > botGetNumOpponentsInHill(chr)) {
|
||||
if (rngRandom() % 100 < 50) {
|
||||
if (random() % 100 < 50) {
|
||||
botApplyScenarioCommand(chr, AIBOTCMD_DEFHILL);
|
||||
} else {
|
||||
botApplyScenarioCommand(chr, AIBOTCMD_NORMAL);
|
||||
@@ -2588,13 +2579,13 @@ void botTickUnpaused(struct chrdata *chr)
|
||||
if (botShouldReturnCtcToken(chr)) {
|
||||
botApplyScenarioCommand(chr, AIBOTCMD_GETCASE);
|
||||
} else if (botIsChrsCtcTokenHeld(chr)) {
|
||||
if (rngRandom() % 100 < 30) {
|
||||
if (random() % 100 < 30) {
|
||||
botApplyScenarioCommand(chr, AIBOTCMD_GETCASE);
|
||||
} else {
|
||||
botApplyScenarioCommand(chr, AIBOTCMD_SAVECASE);
|
||||
}
|
||||
} else {
|
||||
if (rngRandom() % 100 < 70 || numgetting <= 0) {
|
||||
if (random() % 100 < 70 || numgetting <= 0) {
|
||||
botApplyScenarioCommand(chr, AIBOTCMD_GETCASE);
|
||||
} else {
|
||||
botApplyScenarioCommand(chr, AIBOTCMD_SAVECASE);
|
||||
@@ -2608,7 +2599,7 @@ void botTickUnpaused(struct chrdata *chr)
|
||||
if (botShouldReturnCtcToken(chr)) {
|
||||
botApplyScenarioCommand(chr, AIBOTCMD_GETCASE);
|
||||
} else if (botIsChrsCtcTokenHeld(chr)) {
|
||||
if (numsaving <= 0 || rngRandom() % 100 < 70) {
|
||||
if (numsaving <= 0 || random() % 100 < 70) {
|
||||
botApplyScenarioCommand(chr, AIBOTCMD_SAVECASE);
|
||||
} else {
|
||||
botApplyScenarioCommand(chr, AIBOTCMD_GETCASE);
|
||||
@@ -2617,9 +2608,9 @@ void botTickUnpaused(struct chrdata *chr)
|
||||
botApplyScenarioCommand(chr, AIBOTCMD_GETCASE);
|
||||
} else if (numsaving <= 0 || numsaving < teamsize / 4) {
|
||||
botApplyScenarioCommand(chr, AIBOTCMD_SAVECASE);
|
||||
} else if (rngRandom() % 100 < 30) {
|
||||
} else if (random() % 100 < 30) {
|
||||
botApplyScenarioCommand(chr, AIBOTCMD_GETCASE);
|
||||
} else if (rngRandom() % 100 < 30) {
|
||||
} else if (random() % 100 < 30) {
|
||||
botApplyScenarioCommand(chr, AIBOTCMD_SAVECASE);
|
||||
} else {
|
||||
botApplyScenarioCommand(chr, AIBOTCMD_NORMAL);
|
||||
@@ -2628,7 +2619,7 @@ void botTickUnpaused(struct chrdata *chr)
|
||||
}
|
||||
|
||||
// Consider changing command in 20 to 60 seconds
|
||||
aibot->commandtimer60 = TICKS(1200) + rngRandom() % TICKS(2400);
|
||||
aibot->commandtimer60 = TICKS(1200) + random() % TICKS(2400);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2725,7 +2716,7 @@ void botTickUnpaused(struct chrdata *chr)
|
||||
s32 index;
|
||||
s32 i;
|
||||
|
||||
index = rngRandom() % numtokens;
|
||||
index = random() % numtokens;
|
||||
|
||||
i = (index + 1) % numtokens;
|
||||
|
||||
@@ -2753,7 +2744,7 @@ void botTickUnpaused(struct chrdata *chr)
|
||||
aibot->gotoprop = tokens[index];
|
||||
} else if (botCanFollow(chr, tokens[index]->chr)) {
|
||||
newaction = MA_AIBOTFOLLOW;
|
||||
aibot->canbreakfollow = rngRandom() % 4 == 0;
|
||||
aibot->canbreakfollow = random() % 4 == 0;
|
||||
aibot->followingplayernum = mpPlayerGetIndex(tokens[index]->chr);
|
||||
}
|
||||
}
|
||||
@@ -2771,7 +2762,7 @@ void botTickUnpaused(struct chrdata *chr)
|
||||
// Held by a teammate - follow/protect them
|
||||
if (botCanFollow(chr, tokenchr)) {
|
||||
newaction = MA_AIBOTFOLLOW;
|
||||
aibot->canbreakfollow = rngRandom() % 4 == 0;
|
||||
aibot->canbreakfollow = random() % 4 == 0;
|
||||
aibot->followingplayernum = mpPlayerGetIndex(tokenchr);
|
||||
}
|
||||
} else {
|
||||
@@ -2861,7 +2852,7 @@ void botTickUnpaused(struct chrdata *chr)
|
||||
// Uplink is held by teammate - protect them
|
||||
if (botCanFollow(chr, uplinkchr)) {
|
||||
newaction = MA_AIBOTFOLLOW;
|
||||
aibot->canbreakfollow = rngRandom() % 4 == 0;
|
||||
aibot->canbreakfollow = random() % 4 == 0;
|
||||
aibot->followingplayernum = mpPlayerGetIndex(uplinkchr);
|
||||
}
|
||||
} else {
|
||||
@@ -2892,7 +2883,7 @@ void botTickUnpaused(struct chrdata *chr)
|
||||
// Briefcase is held by teammate - protect them
|
||||
if (botCanFollow(chr, tokenchr)) {
|
||||
newaction = MA_AIBOTFOLLOW;
|
||||
aibot->canbreakfollow = rngRandom() % 4 == 0;
|
||||
aibot->canbreakfollow = random() % 4 == 0;
|
||||
aibot->followingplayernum = mpPlayerGetIndex(tokenchr);
|
||||
}
|
||||
} else if (!botIsTargetInvisible(chr, tokenchr) && botPassesCowardCheck(chr, tokenchr)) {
|
||||
@@ -2920,7 +2911,7 @@ void botTickUnpaused(struct chrdata *chr)
|
||||
// Victim is a teammate - protect them
|
||||
if (botCanFollow(chr, victimchr)) {
|
||||
newaction = MA_AIBOTFOLLOW;
|
||||
aibot->canbreakfollow = rngRandom() % 4 == 0;
|
||||
aibot->canbreakfollow = random() % 4 == 0;
|
||||
aibot->followingplayernum = mpPlayerGetIndex(victimchr);
|
||||
}
|
||||
} else {
|
||||
@@ -2945,13 +2936,13 @@ void botTickUnpaused(struct chrdata *chr)
|
||||
// Current bot has the briefcase - follow a teammate for protection
|
||||
s32 playernum = -1;
|
||||
|
||||
if (rngRandom() % 100 < 66) {
|
||||
if (random() % 100 < 66) {
|
||||
playernum = botFindTeammateToFollow(chr, 100000);
|
||||
}
|
||||
|
||||
if (playernum >= 0) {
|
||||
newaction = MA_AIBOTFOLLOW;
|
||||
aibot->canbreakfollow = rngRandom() % 4 == 0;
|
||||
aibot->canbreakfollow = random() % 4 == 0;
|
||||
aibot->followingplayernum = playernum;
|
||||
}
|
||||
}
|
||||
@@ -2963,13 +2954,13 @@ void botTickUnpaused(struct chrdata *chr)
|
||||
// Current bot is the victim - follow a teammate for protection
|
||||
s32 playernum = -1;
|
||||
|
||||
if (rngRandom() % 100 < 66) {
|
||||
if (random() % 100 < 66) {
|
||||
playernum = botFindTeammateToFollow(chr, 100000);
|
||||
}
|
||||
|
||||
if (playernum >= 0) {
|
||||
newaction = MA_AIBOTFOLLOW;
|
||||
aibot->canbreakfollow = rngRandom() % 4 == 0;
|
||||
aibot->canbreakfollow = random() % 4 == 0;
|
||||
aibot->followingplayernum = playernum;
|
||||
}
|
||||
}
|
||||
@@ -3096,7 +3087,7 @@ void botTickUnpaused(struct chrdata *chr)
|
||||
|
||||
if (playernum >= 0) {
|
||||
newaction = MA_AIBOTFOLLOW;
|
||||
aibot->canbreakfollow = rngRandom() % 4 == 0;
|
||||
aibot->canbreakfollow = random() % 4 == 0;
|
||||
aibot->followingplayernum = playernum;
|
||||
}
|
||||
}
|
||||
@@ -3436,7 +3427,7 @@ void botTickUnpaused(struct chrdata *chr)
|
||||
aibot->punchtimer60[0] = TICKS(30);
|
||||
}
|
||||
|
||||
if (rngRandom() % 3 == 0) {
|
||||
if (random() % 3 == 0) {
|
||||
aibot->punchtimer60[1] = aibot->punchtimer60[0] - TICKS(20);
|
||||
}
|
||||
break;
|
||||
|
||||
+1
-1
@@ -223,7 +223,7 @@ bool botactShootFarsight(struct chrdata *chr, s32 arg1, struct coord *vector, st
|
||||
aibot = chr->aibot;
|
||||
|
||||
if (aibot->weaponnum == WEAPON_FARSIGHT) {
|
||||
rand = rngRandom() % 100;
|
||||
rand = random() % 100;
|
||||
|
||||
// 3 in 10 chance of this passing
|
||||
if (rand < 30) {
|
||||
|
||||
+1
-1
@@ -149,7 +149,7 @@ void botcmdTickDistMode(struct chrdata *chr)
|
||||
if (!insight) {
|
||||
newmode = BOTDISTMODE_ADVANCE;
|
||||
aibot->distoverrideprop = targetprop;
|
||||
aibot->distoverridetimer60 = TICKS(20) + (rngRandom() % TICKS(120));
|
||||
aibot->distoverridetimer60 = TICKS(20) + (random() % TICKS(120));
|
||||
} else if (aibot->distoverrideprop) {
|
||||
if (g_Vars.lvupdate60 < aibot->distoverridetimer60) {
|
||||
aibot->distoverridetimer60 -= g_Vars.lvupdate60;
|
||||
|
||||
+14
-14
@@ -71,14 +71,14 @@ struct aibotweaponpreference g_AibotWeaponPreferences[] = {
|
||||
/*0x22*/ { 44, 156, 0, 0, 1, 0, BOTDISTCFG_DEFAULT, BOTDISTCFG_DEFAULT, 5, 5, 2, 2, 1, 0 }, // WEAPON_REMOTEMINE
|
||||
/*0x23*/ { 8, 8, 0, 0, 0, 0, BOTDISTCFG_DEFAULT, BOTDISTCFG_DEFAULT, 0, 0, 0, 0, 1, 0 }, // WEAPON_COMBATBOOST
|
||||
#ifndef PLATFORM_N64 // add all classic weapons to multiplayer
|
||||
/*0x24*/ { 56, 60, 84, 88, 1, 0, BOTDISTCFG_PISTOL, BOTDISTCFG_CLOSE, 30, 0, 10, 0, 1, 0 }, // WEAPON_PP9I
|
||||
/*0x25*/ { 56, 60, 84, 88, 1, 0, BOTDISTCFG_PISTOL, BOTDISTCFG_CLOSE, 30, 0, 10, 0, 1, 0 }, // WEAPON_CC13
|
||||
/*0x26*/ { 56, 60, 84, 88, 1, 0, BOTDISTCFG_DEFAULT, BOTDISTCFG_CLOSE, 30, 0, 10, 0, 1, 0 }, // WEAPON_KL01313
|
||||
/*0x27*/ { 124, 148, 0, 0, 1, 0, BOTDISTCFG_DEFAULT, BOTDISTCFG_DEFAULT, 90, 0, 30, 0, 1, 0 }, // WEAPON_KF7SPECIAL
|
||||
/*0x28*/ { 116, 128, 136, 152, 1, 0, BOTDISTCFG_DEFAULT, BOTDISTCFG_DEFAULT, 100, 0, 30, 0, 1, 0 }, // WEAPON_ZZT
|
||||
/*0x29*/ { 124, 148, 0, 0, 1, 0, BOTDISTCFG_DEFAULT, BOTDISTCFG_DEFAULT, 90, 0, 30, 0, 1, 0 }, // WEAPON_DMC
|
||||
/*0x24*/ { 56, 60, 84, 88, 1, 1, BOTDISTCFG_PISTOL, BOTDISTCFG_CLOSE, 30, 0, 10, 0, 1, 0 }, // WEAPON_PP9I
|
||||
/*0x25*/ { 56, 60, 84, 88, 1, 1, BOTDISTCFG_PISTOL, BOTDISTCFG_CLOSE, 30, 0, 10, 0, 1, 0 }, // WEAPON_CC13
|
||||
/*0x26*/ { 56, 60, 84, 88, 1, 1, BOTDISTCFG_DEFAULT, BOTDISTCFG_CLOSE, 30, 0, 10, 0, 1, 0 }, // WEAPON_KL01313
|
||||
/*0x27*/ { 124, 148, 0, 0, 1, 1, BOTDISTCFG_DEFAULT, BOTDISTCFG_DEFAULT, 90, 0, 30, 0, 1, 0 }, // WEAPON_KF7SPECIAL
|
||||
/*0x28*/ { 116, 128, 136, 152, 1, 1, BOTDISTCFG_DEFAULT, BOTDISTCFG_DEFAULT, 100, 0, 30, 0, 1, 0 }, // WEAPON_ZZT
|
||||
/*0x29*/ { 124, 148, 0, 0, 1, 1, BOTDISTCFG_DEFAULT, BOTDISTCFG_DEFAULT, 90, 0, 30, 0, 1, 0 }, // WEAPON_DMC
|
||||
/*0x2a*/ { 156, 180, 0, 0, 1, 0, BOTDISTCFG_DEFAULT, BOTDISTCFG_DEFAULT, 150, 0, 30, 0, 1, 0 }, // WEAPON_AR53
|
||||
/*0x2b*/ { 164, 188, 0, 0, 1, 0, BOTDISTCFG_DEFAULT, BOTDISTCFG_DEFAULT, 200, 0, 40, 0, 1, 0 }, // WEAPON_RCP45
|
||||
/*0x2b*/ { 164, 188, 0, 0, 1, 1, BOTDISTCFG_DEFAULT, BOTDISTCFG_DEFAULT, 200, 0, 40, 0, 1, 0 }, // WEAPON_RCP45
|
||||
#else
|
||||
/*0x24*/ { 0, 0, 0, 0, 0, 0, BOTDISTCFG_DEFAULT, BOTDISTCFG_DEFAULT, 0, 0, 0, 0, 1, 0 }, // WEAPON_PP9I
|
||||
/*0x25*/ { 0, 0, 0, 0, 0, 0, BOTDISTCFG_DEFAULT, BOTDISTCFG_DEFAULT, 0, 0, 0, 0, 1, 0 }, // WEAPON_CC13
|
||||
@@ -904,7 +904,7 @@ void botinvTick(struct chrdata *chr)
|
||||
aibot->dampensuicidesttl60 -= g_Vars.lvupdate60;
|
||||
|
||||
if (aibot->dampensuicidesttl60 < 0) {
|
||||
aibot->dampensuicidesttl60 = TICKS(3600) + rngRandom() % TICKS(60);
|
||||
aibot->dampensuicidesttl60 = TICKS(3600) + random() % TICKS(60);
|
||||
|
||||
for (i = 0; i < ARRAYCOUNT(aibot->suicidesbygunfunc); i++) {
|
||||
aibot->suicidesbygunfunc[i][0] *= 0.9f;
|
||||
@@ -916,15 +916,15 @@ void botinvTick(struct chrdata *chr)
|
||||
aibot->equipextrascorestimer60 -= g_Vars.lvupdate60;
|
||||
|
||||
if (aibot->equipextrascorestimer60 < 0) {
|
||||
aibot->equipextrascorestimer60 = TICKS(600) + rngRandom() % TICKS(3000);
|
||||
aibot->equipextrascorestimer60 = TICKS(600) + random() % TICKS(3000);
|
||||
|
||||
for (i = 0; i < ARRAYCOUNT(aibot->equipextrascores); i++) {
|
||||
if (aibot->config->difficulty == BOTDIFF_MEAT) {
|
||||
aibot->equipextrascores[i] = rngRandom() % 200 - 100; // -100 to +100
|
||||
aibot->equipextrascores[i] = random() % 200 - 100; // -100 to +100
|
||||
} else if (aibot->config->difficulty == BOTDIFF_EASY) {
|
||||
aibot->equipextrascores[i] = rngRandom() % 100 - 50; // -50 to +50
|
||||
aibot->equipextrascores[i] = random() % 100 - 50; // -50 to +50
|
||||
} else {
|
||||
aibot->equipextrascores[i] = rngRandom() % 30 - 15; // -15 to +15
|
||||
aibot->equipextrascores[i] = random() % 30 - 15; // -15 to +15
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -934,8 +934,8 @@ void botinvTick(struct chrdata *chr)
|
||||
aibot->random1ttl60 -= g_Vars.lvupdate60;
|
||||
|
||||
if (aibot->random1ttl60 < 0) {
|
||||
aibot->random1ttl60 = TICKS(120) + rngRandom() % TICKS(600);
|
||||
aibot->random1 = rngRandom();
|
||||
aibot->random1ttl60 = TICKS(120) + random() % TICKS(600);
|
||||
aibot->random1 = random();
|
||||
}
|
||||
|
||||
if (aibot->cyclonedischarging[HAND_LEFT] == 0
|
||||
|
||||
Loaded 100 of 249 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user