mirror of
https://github.com/yquake2/yquake2remaster.git
synced 2025-03-22 02:42:11 +00:00
Merge remote-tracking branch 'yquake2/master'
This commit is contained in:
commit
3f74954db6
16 changed files with 1060 additions and 379 deletions
63
.github/workflows/linux.yml
vendored
63
.github/workflows/linux.yml
vendored
|
@ -1,63 +0,0 @@
|
|||
name: Testbuild for Linux
|
||||
run-name: testbuild_linux
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
pull_request:
|
||||
types:
|
||||
- edited
|
||||
- opened
|
||||
- synchronize
|
||||
concurrency:
|
||||
# Cancel concurrent workflows for the same PR or commit hash.
|
||||
group: ${{github.workflow}}-${{github.event_name == 'pull_request' && github.head_ref || github.sha}}
|
||||
cancel-in-progress: true
|
||||
jobs:
|
||||
build_ubuntu_x86_64:
|
||||
runs-on: ubuntu-22.04
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- env: ubuntu
|
||||
steps:
|
||||
- name: Install build dependencies
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt install libgl1-mesa-dev libsdl2-dev libopenal-dev libcurl4-openssl-dev \
|
||||
libavformat-dev libswscale-dev libvulkan-dev build-essential
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v4
|
||||
- name: Build
|
||||
run: |
|
||||
sed -i 's|WITH_AVCODEC:=yes|WITH_AVCODEC:=no|g' Makefile
|
||||
# Public runners come with 2 CPUs.
|
||||
make -j2
|
||||
make -j2 ref_gles1
|
||||
- name: Create testbuild package
|
||||
run: |
|
||||
# Create release directory tree
|
||||
mkdir -p publish/quake2-linux-${{github.sha}}/misc/docs
|
||||
# Copy release assets
|
||||
cp -r release/* publish/quake2-linux-${{github.sha}}/
|
||||
# Copy misc assets
|
||||
cp -r stuff/yq2.cfg publish/quake2-linux-${{github.sha}}/misc/yq2.cfg
|
||||
cp -r stuff/mapfixes publish/quake2-linux-${{github.sha}}/misc
|
||||
cp LICENSE publish/quake2-linux-${{github.sha}}/misc/docs/LICENSE.txt
|
||||
cp README.md publish/quake2-linux-${{github.sha}}/misc/docs/README.txt
|
||||
cp doc/010_index.md publish/quake2-linux-${{github.sha}}/misc/docs/010_index.txt
|
||||
cp doc/020_installation.md publish/quake2-linux-${{github.sha}}/misc/docs/020_installation.txt
|
||||
cp doc/030_configuration.md publish/quake2-linux-${{github.sha}}/misc/docs/030_configuration.txt
|
||||
cp doc/040_cvarlist.md publish/quake2-linux-${{github.sha}}/misc/docs/040_cvarlist.txt
|
||||
cp doc/050_commands.md publish/quake2-linux-${{github.sha}}/misc/docs/050_commands.txt
|
||||
cp doc/060_multiplayer.md publish/quake2-linux-${{github.sha}}/misc/docs/060_multiplayer.txt
|
||||
cp doc/070_packaging.md publish/quake2-linux-${{github.sha}}/misc/docs/070_packaging.txt
|
||||
cp doc/080_contributing.md publish/quake2-linux-${{github.sha}}/misc/docs/080_contributing.txt
|
||||
cp doc/090_filelists.md publish/quake2-linux-${{github.sha}}/misc/docs/090_filelists.md
|
||||
- name: Upload testbuild package
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: quake2-linux-${{github.sha}}
|
||||
path: publish/
|
||||
if-no-files-found: error
|
63
.github/workflows/linux_aarch64.yml
vendored
Normal file
63
.github/workflows/linux_aarch64.yml
vendored
Normal file
|
@ -0,0 +1,63 @@
|
|||
name: Testbuild for Linux (aarch64)
|
||||
run-name: testbuild_linux_aarch64
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
pull_request:
|
||||
types:
|
||||
- edited
|
||||
- opened
|
||||
- synchronize
|
||||
concurrency:
|
||||
# Cancel concurrent workflows for the same PR or commit hash.
|
||||
group: ${{github.workflow}}-${{github.event_name == 'pull_request' && github.head_ref || github.sha}}
|
||||
cancel-in-progress: true
|
||||
jobs:
|
||||
build_ubuntu_aarch64:
|
||||
runs-on: ubuntu-22.04-arm
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- env: ubuntu
|
||||
steps:
|
||||
- name: Install build dependencies
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt install libgl1-mesa-dev libsdl2-dev libopenal-dev libcurl4-openssl-dev \
|
||||
libavformat-dev libswscale-dev libvulkan-dev build-essential
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v4
|
||||
- name: Build
|
||||
run: |
|
||||
sed -i 's|WITH_AVCODEC:=yes|WITH_AVCODEC:=no|g' Makefile
|
||||
# Public runners come with 4 CPUs.
|
||||
make -j4
|
||||
make -j4 ref_gles1
|
||||
- name: Create testbuild package
|
||||
run: |
|
||||
# Create release directory tree
|
||||
mkdir -p publish/quake2-linux_aarch64-${{github.sha}}/misc/docs
|
||||
# Copy release assets
|
||||
cp -r release/* publish/quake2-linux_aarch64-${{github.sha}}/
|
||||
# Copy misc assets
|
||||
cp -r stuff/yq2.cfg publish/quake2-linux_aarch64-${{github.sha}}/misc/yq2.cfg
|
||||
cp -r stuff/mapfixes publish/quake2-linux_aarch64-${{github.sha}}/misc
|
||||
cp LICENSE publish/quake2-linux_aarch64-${{github.sha}}/misc/docs/LICENSE.txt
|
||||
cp README.md publish/quake2-linux_aarch64-${{github.sha}}/misc/docs/README.txt
|
||||
cp doc/010_index.md publish/quake2-linux_aarch64-${{github.sha}}/misc/docs/010_index.txt
|
||||
cp doc/020_installation.md publish/quake2-linux_aarch64-${{github.sha}}/misc/docs/020_installation.txt
|
||||
cp doc/030_configuration.md publish/quake2-linux_aarch64-${{github.sha}}/misc/docs/030_configuration.txt
|
||||
cp doc/040_cvarlist.md publish/quake2-linux_aarch64-${{github.sha}}/misc/docs/040_cvarlist.txt
|
||||
cp doc/050_commands.md publish/quake2-linux_aarch64-${{github.sha}}/misc/docs/050_commands.txt
|
||||
cp doc/060_multiplayer.md publish/quake2-linux_aarch64-${{github.sha}}/misc/docs/060_multiplayer.txt
|
||||
cp doc/070_packaging.md publish/quake2-linux_aarch64-${{github.sha}}/misc/docs/070_packaging.txt
|
||||
cp doc/080_contributing.md publish/quake2-linux_aarch64-${{github.sha}}/misc/docs/080_contributing.txt
|
||||
cp doc/090_filelists.md publish/quake2-linux_aarch64-${{github.sha}}/misc/docs/090_filelists.md
|
||||
- name: Upload testbuild package
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: quake2-linux_aarch64-${{github.sha}}
|
||||
path: publish/
|
||||
if-no-files-found: error
|
63
.github/workflows/linux_x86_64.yml
vendored
Normal file
63
.github/workflows/linux_x86_64.yml
vendored
Normal file
|
@ -0,0 +1,63 @@
|
|||
name: Testbuild for Linux (x86_64)
|
||||
run-name: testbuild_linux_x86_64
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
pull_request:
|
||||
types:
|
||||
- edited
|
||||
- opened
|
||||
- synchronize
|
||||
concurrency:
|
||||
# Cancel concurrent workflows for the same PR or commit hash.
|
||||
group: ${{github.workflow}}-${{github.event_name == 'pull_request' && github.head_ref || github.sha}}
|
||||
cancel-in-progress: true
|
||||
jobs:
|
||||
build_ubuntu_x86_64:
|
||||
runs-on: ubuntu-22.04
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- env: ubuntu
|
||||
steps:
|
||||
- name: Install build dependencies
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt install libgl1-mesa-dev libsdl2-dev libopenal-dev libcurl4-openssl-dev \
|
||||
libavformat-dev libswscale-dev libvulkan-dev build-essential
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v4
|
||||
- name: Build
|
||||
run: |
|
||||
sed -i 's|WITH_AVCODEC:=yes|WITH_AVCODEC:=no|g' Makefile
|
||||
# Public runners come with 4 CPUs.
|
||||
make -j4
|
||||
make -j4 ref_gles1
|
||||
- name: Create testbuild package
|
||||
run: |
|
||||
# Create release directory tree
|
||||
mkdir -p publish/quake2-linux_x86_64-${{github.sha}}/misc/docs
|
||||
# Copy release assets
|
||||
cp -r release/* publish/quake2-linux_x86_64-${{github.sha}}/
|
||||
# Copy misc assets
|
||||
cp -r stuff/yq2.cfg publish/quake2-linux_x86_64-${{github.sha}}/misc/yq2.cfg
|
||||
cp -r stuff/mapfixes publish/quake2-linux_x86_64-${{github.sha}}/misc
|
||||
cp LICENSE publish/quake2-linux_x86_64-${{github.sha}}/misc/docs/LICENSE.txt
|
||||
cp README.md publish/quake2-linux_x86_64-${{github.sha}}/misc/docs/README.txt
|
||||
cp doc/010_index.md publish/quake2-linux_x86_64-${{github.sha}}/misc/docs/010_index.txt
|
||||
cp doc/020_installation.md publish/quake2-linux_x86_64-${{github.sha}}/misc/docs/020_installation.txt
|
||||
cp doc/030_configuration.md publish/quake2-linux_x86_64-${{github.sha}}/misc/docs/030_configuration.txt
|
||||
cp doc/040_cvarlist.md publish/quake2-linux_x86_64-${{github.sha}}/misc/docs/040_cvarlist.txt
|
||||
cp doc/050_commands.md publish/quake2-linux_x86_64-${{github.sha}}/misc/docs/050_commands.txt
|
||||
cp doc/060_multiplayer.md publish/quake2-linux_x86_64-${{github.sha}}/misc/docs/060_multiplayer.txt
|
||||
cp doc/070_packaging.md publish/quake2-linux_x86_64-${{github.sha}}/misc/docs/070_packaging.txt
|
||||
cp doc/080_contributing.md publish/quake2-linux_x86_64-${{github.sha}}/misc/docs/080_contributing.txt
|
||||
cp doc/090_filelists.md publish/quake2-linux_x86_64-${{github.sha}}/misc/docs/090_filelists.md
|
||||
- name: Upload testbuild package
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: quake2-linux_x86_64-${{github.sha}}
|
||||
path: publish/
|
||||
if-no-files-found: error
|
8
.github/workflows/win32.yml
vendored
8
.github/workflows/win32.yml
vendored
|
@ -46,8 +46,8 @@ jobs:
|
|||
shell: msys2 {0}
|
||||
run: |
|
||||
sed -i 's|WITH_AVCODEC:=yes|WITH_AVCODEC:=no|g' Makefile
|
||||
# Public runners come with 2 CPUs.
|
||||
make -j2
|
||||
# Public runners come with 4 CPUs.
|
||||
make -j4
|
||||
- name: Create testbuild package
|
||||
shell: msys2 {0}
|
||||
run: |
|
||||
|
@ -70,8 +70,8 @@ jobs:
|
|||
cp doc/080_contributing.md publish/quake2-win32-${{github.sha}}/misc/docs/080_contributing.txt
|
||||
cp doc/090_filelists.md publish/quake2-win32-${{github.sha}}/misc/docs/090_filelists.md
|
||||
# SDL2
|
||||
wget -c https://github.com/libsdl-org/SDL/releases/download/release-2.30.11/SDL2-2.30.11-win32-x86.zip
|
||||
unzip -o SDL2-2.30.11-win32-x86.zip
|
||||
wget -c https://github.com/libsdl-org/SDL/releases/download/release-2.32.0/SDL2-2.32.0-win32-x86.zip
|
||||
unzip -o SDL2-2.32.0-win32-x86.zip
|
||||
cp SDL2.dll publish/quake2-win32-${{github.sha}}/
|
||||
# openal-soft
|
||||
wget -c https://github.com/kcat/openal-soft/releases/download/1.23.1/openal-soft-1.23.1-bin.zip
|
||||
|
|
29
.github/workflows/win64.yml
vendored
29
.github/workflows/win64.yml
vendored
|
@ -1,4 +1,4 @@
|
|||
name: Testbuild for Win64
|
||||
name: Testbuild for Win64 (SDL3)
|
||||
run-name: testbuild_win64
|
||||
on:
|
||||
push:
|
||||
|
@ -8,8 +8,9 @@ on:
|
|||
- "*"
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
- edited
|
||||
- opened
|
||||
- synchronize
|
||||
concurrency:
|
||||
# Cancel concurrent workflows for the same PR or commit hash.
|
||||
group: ${{github.workflow}}-${{github.event_name == 'pull_request' && github.head_ref || github.sha}}
|
||||
|
@ -37,17 +38,19 @@ jobs:
|
|||
mingw-w64-${{matrix.env}}-gcc
|
||||
mingw-w64-${{matrix.env}}-make
|
||||
mingw-w64-${{matrix.env}}-openal
|
||||
mingw-w64-${{matrix.env}}-SDL2
|
||||
mingw-w64-${{matrix.env}}-sdl3
|
||||
mingw-w64-${{matrix.env}}-vulkan-headers
|
||||
mingw-w64-${{matrix.env}}-wget
|
||||
mingw-w64-${{matrix.env}}-pkgconf
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v4
|
||||
- name: Build
|
||||
shell: msys2 {0}
|
||||
run: |
|
||||
# Public runners come with 2 CPUs.
|
||||
make -j2
|
||||
make -j2 ref_gles1
|
||||
sed -i 's|WITH_SDL3:=no|WITH_SDL3:=yes|g' Makefile
|
||||
# Public runners come with 4 CPUs.
|
||||
make -j4
|
||||
make -j4 ref_gles1
|
||||
- name: Create testbuild package
|
||||
shell: msys2 {0}
|
||||
run: |
|
||||
|
@ -69,10 +72,10 @@ jobs:
|
|||
cp doc/070_packaging.md publish/quake2-win64-${{github.sha}}/misc/docs/070_packaging.txt
|
||||
cp doc/080_contributing.md publish/quake2-win64-${{github.sha}}/misc/docs/080_contributing.txt
|
||||
cp doc/090_filelists.md publish/quake2-win64-${{github.sha}}/misc/docs/090_filelists.md
|
||||
# SDL2
|
||||
wget -c https://github.com/libsdl-org/SDL/releases/download/release-2.30.11/SDL2-2.30.11-win32-x64.zip
|
||||
unzip -o SDL2-2.30.11-win32-x64.zip
|
||||
cp SDL2.dll publish/quake2-win64-${{github.sha}}/
|
||||
# SDL3
|
||||
wget -c https://github.com/libsdl-org/SDL/releases/download/release-3.2.4/SDL3-3.2.4-win32-x64.zip
|
||||
unzip -o SDL3-3.2.4-win32-x64.zip
|
||||
cp SDL3.dll publish/quake2-win64-${{github.sha}}/
|
||||
# static ffmpeg
|
||||
wget -c https://github.com/BtbN/FFmpeg-Builds/releases/download/autobuild-2024-08-31-12-50/ffmpeg-n7.0.2-6-g7e69129d2f-win64-lgpl-shared-7.0.zip
|
||||
unzip -o ffmpeg-n7.0.2-6-g7e69129d2f-win64-lgpl-shared-7.0.zip
|
||||
|
@ -84,9 +87,9 @@ jobs:
|
|||
unzip -o openal-soft-1.23.1-bin.zip
|
||||
cp openal-soft-1.23.1-bin/bin/Win64/soft_oal.dll publish/quake2-win64-${{github.sha}}/openal32.dll
|
||||
# curl (releases use a custom build curl.dll)
|
||||
wget -c https://curl.se/windows/dl-8.9.1_1/curl-8.9.1_1-win64-mingw.zip
|
||||
unzip -o curl-8.9.1_1-win64-mingw.zip
|
||||
cp curl-8.9.1_1-win64-mingw/bin/libcurl-x64.dll publish/quake2-win64-${{github.sha}}/curl.dll
|
||||
wget -c -O curl-mingw-latest.zip "https://curl.se/windows/latest.cgi?p=win64-mingw.zip"
|
||||
unzip -o curl-mingw-latest.zip
|
||||
cp curl-*-win64-mingw/bin/libcurl-x64.dll publish/quake2-win64-${{github.sha}}/curl.dll
|
||||
- name: Upload testbuild package
|
||||
uses: actions/upload-artifact@v4
|
||||
if: ${{ ! startsWith(github.ref, 'refs/tags/') }}
|
||||
|
|
|
@ -617,18 +617,33 @@ it's `+set busywait 0` (setting the `busywait` cvar) and `-portable`
|
|||
* **sw_colorlight**: enable experimental color lighting.
|
||||
|
||||
|
||||
## Game Controller
|
||||
## Gamepad
|
||||
|
||||
* **in_initjoy**: Toggles initialization of game controller. Default is
|
||||
`1`, which enables gamepad usage; `0` disables its detection at
|
||||
startup. Can only be set from command line.
|
||||
|
||||
* **in_sdlbackbutton**: Defines which button is used in the gamepad as
|
||||
* **joy_escbutton**: Defines which button is used in the gamepad as
|
||||
the `Esc` key, to pull the main menu and 'cancel' / 'go back' on its
|
||||
options. Valid values are `0` = Back / Select / Minus, `1` = Start /
|
||||
Menu / Plus (default), or `2` = Guide / Home / PS. Requires a game
|
||||
options. Valid values are `0` = Start / Menu / Plus (default), `1` =
|
||||
Back / Select / Minus, or `2` = Guide / Home / PS. Requires a game
|
||||
restart, or gamepad replug, when changed.
|
||||
|
||||
* **joy_labels**: Defines style of button labels in binding menus. Note
|
||||
that binding through console only uses the SDL nomenclature (`0`).
|
||||
Default is `-1`, which requires at least SDL 2.0.12 to work.
|
||||
- `-1`: *Autodetect*, sets to `0` if gamepad type isn't detected
|
||||
- `0`: *SDL*, face buttons appear as cardinal points
|
||||
- `1`: *Xbox*, with One / Series X / S labels
|
||||
- `2`: *Playstation*, 4 & 5 format
|
||||
- `3`: *Switch*, traditional Nintendo button format
|
||||
|
||||
* **joy_confirm**: Style of *confirm* and *cancel* buttons in menus. As
|
||||
with the previous one, SDL 2.0.12 is required for `-1` to work.
|
||||
- `-1`: *Autodetect*, sets to `1` if Nintendo, `0` otherwise
|
||||
- `0`: SOUTH to confirm, EAST to cancel (standard style)
|
||||
- `1`: EAST to confirm, SOUTH to cancel (Japanese style)
|
||||
|
||||
* **joy_layout**: Allows to select the stick layout of the gamepad.
|
||||
- `0`: *Default*, left stick moves, right aims
|
||||
- `1`: *Southpaw*, same as previous one with inverted sticks
|
||||
|
|
|
@ -139,62 +139,6 @@ keyname_t keynames[] = {
|
|||
{"MWHEELUP", K_MWHEELUP},
|
||||
{"MWHEELDOWN", K_MWHEELDOWN},
|
||||
|
||||
{"BTN_A", K_BTN_A},
|
||||
{"BTN_B", K_BTN_B},
|
||||
{"BTN_X", K_BTN_X},
|
||||
{"BTN_Y", K_BTN_Y},
|
||||
{"STICK_LEFT", K_STICK_LEFT},
|
||||
{"STICK_RIGHT", K_STICK_RIGHT},
|
||||
{"SHOULDR_LEFT", K_SHOULDER_LEFT},
|
||||
{"SHOULDR_RIGHT", K_SHOULDER_RIGHT},
|
||||
{"TRIG_LEFT", K_TRIG_LEFT},
|
||||
{"TRIG_RIGHT", K_TRIG_RIGHT},
|
||||
|
||||
{"DP_UP", K_DPAD_UP},
|
||||
{"DP_DOWN", K_DPAD_DOWN},
|
||||
{"DP_LEFT", K_DPAD_LEFT},
|
||||
{"DP_RIGHT", K_DPAD_RIGHT},
|
||||
|
||||
{"PADDLE_1", K_PADDLE_1},
|
||||
{"PADDLE_2", K_PADDLE_2},
|
||||
{"PADDLE_3", K_PADDLE_3},
|
||||
{"PADDLE_4", K_PADDLE_4},
|
||||
{"BTN_MISC1", K_BTN_MISC1},
|
||||
{"TOUCHPAD", K_TOUCHPAD},
|
||||
{"BTN_BACK", K_BTN_BACK},
|
||||
{"BTN_GUIDE", K_BTN_GUIDE},
|
||||
{"BTN_START", K_BTN_START},
|
||||
|
||||
// virtual keys you get by pressing the corresponding normal joy key
|
||||
// and the altselector key
|
||||
{"BTN_A_ALT", K_BTN_A_ALT},
|
||||
{"BTN_B_ALT", K_BTN_B_ALT},
|
||||
{"BTN_X_ALT", K_BTN_X_ALT},
|
||||
{"BTN_Y_ALT", K_BTN_Y_ALT},
|
||||
{"STICK_LEFT_ALT", K_STICK_LEFT_ALT},
|
||||
{"STICK_RIGHT_ALT", K_STICK_RIGHT_ALT},
|
||||
{"SHOULDR_LEFT_ALT", K_SHOULDER_LEFT_ALT},
|
||||
{"SHOULDR_RIGHT_ALT", K_SHOULDER_RIGHT_ALT},
|
||||
{"TRIG_LEFT_ALT", K_TRIG_LEFT_ALT},
|
||||
{"TRIG_RIGHT_ALT", K_TRIG_RIGHT_ALT},
|
||||
|
||||
{"DP_UP_ALT", K_DPAD_UP_ALT},
|
||||
{"DP_DOWN_ALT", K_DPAD_DOWN_ALT},
|
||||
{"DP_LEFT_ALT", K_DPAD_LEFT_ALT},
|
||||
{"DP_RIGHT_ALT", K_DPAD_RIGHT_ALT},
|
||||
|
||||
{"PADDLE_1_ALT", K_PADDLE_1_ALT},
|
||||
{"PADDLE_2_ALT", K_PADDLE_2_ALT},
|
||||
{"PADDLE_3_ALT", K_PADDLE_3_ALT},
|
||||
{"PADDLE_4_ALT", K_PADDLE_4_ALT},
|
||||
{"BTN_MISC1_ALT", K_BTN_MISC1_ALT},
|
||||
{"TOUCHPAD_ALT", K_TOUCHPAD_ALT},
|
||||
{"BTN_BACK_ALT", K_BTN_BACK_ALT},
|
||||
{"BTN_GUIDE_ALT", K_BTN_GUIDE_ALT},
|
||||
{"BTN_START_ALT", K_BTN_START_ALT},
|
||||
|
||||
{"JOY_BACK", K_JOY_BACK},
|
||||
|
||||
{"SUPER", K_SUPER},
|
||||
{"COMPOSE", K_COMPOSE},
|
||||
{"MODE", K_MODE},
|
||||
|
@ -267,6 +211,147 @@ keyname_t keynames[] = {
|
|||
{NULL, 0}
|
||||
};
|
||||
|
||||
static char *gamepadbtns[] =
|
||||
{
|
||||
// It is imperative that this list of buttons follow EXACTLY the order they
|
||||
// appear in QKEYS enum in keyboard.h, which in turn is the same order as
|
||||
// they appear in SDL_GamepadButton / SDL_GameControllerButton enum.
|
||||
"BTN_SOUTH",
|
||||
"BTN_EAST",
|
||||
"BTN_WEST",
|
||||
"BTN_NORTH",
|
||||
"BTN_BACK",
|
||||
"BTN_GUIDE",
|
||||
"BTN_START",
|
||||
"STICK_LEFT",
|
||||
"STICK_RIGHT",
|
||||
"SHOULDR_LEFT",
|
||||
"SHOULDR_RIGHT",
|
||||
"DP_UP",
|
||||
"DP_DOWN",
|
||||
"DP_LEFT",
|
||||
"DP_RIGHT",
|
||||
"BTN_MISC1",
|
||||
"PADDL_RIGHT1",
|
||||
"PADDL_LEFT1",
|
||||
"PADDL_RIGHT2",
|
||||
"PADDL_LEFT2",
|
||||
"TOUCHPAD",
|
||||
"BTN_MISC2",
|
||||
"BTN_MISC3",
|
||||
"BTN_MISC4",
|
||||
"BTN_MISC5",
|
||||
"BTN_MISC6",
|
||||
"TRIG_LEFT",
|
||||
"TRIG_RIGHT",
|
||||
// Same with _ALT buttons ( button + 'alt modifier' pressed )
|
||||
"BTN_SOUTH_ALT",
|
||||
"BTN_EAST_ALT",
|
||||
"BTN_WEST_ALT",
|
||||
"BTN_NORTH_ALT",
|
||||
"BTN_BACK_ALT",
|
||||
"BTN_GUIDE_ALT",
|
||||
"BTN_START_ALT",
|
||||
"STICK_LEFT_ALT",
|
||||
"STICK_RIGHT_ALT",
|
||||
"SHOULDR_LEFT_ALT",
|
||||
"SHOULDR_RIGHT_ALT",
|
||||
"DP_UP_ALT",
|
||||
"DP_DOWN_ALT",
|
||||
"DP_LEFT_ALT",
|
||||
"DP_RIGHT_ALT",
|
||||
"BTN_MISC1_ALT",
|
||||
"PADDL_RIGHT1_ALT",
|
||||
"PADDL_LEFT1_ALT",
|
||||
"PADDL_RIGHT2_ALT",
|
||||
"PADDL_LEFT2_ALT",
|
||||
"TOUCHPAD_ALT",
|
||||
"BTN_MISC2_ALT",
|
||||
"BTN_MISC3_ALT",
|
||||
"BTN_MISC4_ALT",
|
||||
"BTN_MISC5_ALT",
|
||||
"BTN_MISC6_ALT",
|
||||
"TRIG_LEFT_ALT",
|
||||
"TRIG_RIGHT_ALT"
|
||||
};
|
||||
|
||||
#define NUM_GAMEPAD_BTNS (sizeof gamepadbtns / sizeof gamepadbtns[0])
|
||||
|
||||
static char *gpbtns_face[] =
|
||||
{
|
||||
// Xbox
|
||||
"A",
|
||||
"B",
|
||||
"X",
|
||||
"Y",
|
||||
"VIEW",
|
||||
"XBOX",
|
||||
"MENU",
|
||||
"LS",
|
||||
"RS",
|
||||
"LB",
|
||||
"RB",
|
||||
// Playstation
|
||||
"CROSS",
|
||||
"CIRCLE",
|
||||
"SQUARE",
|
||||
"TRIANGLE",
|
||||
"CREATE",
|
||||
"PS",
|
||||
"OPTIONS",
|
||||
"L3",
|
||||
"R3",
|
||||
"L1",
|
||||
"R1",
|
||||
// Nintendo Switch
|
||||
"B",
|
||||
"A",
|
||||
"Y",
|
||||
"X",
|
||||
"-",
|
||||
"HOME",
|
||||
"+",
|
||||
"L stick",
|
||||
"R stick",
|
||||
"L btn",
|
||||
"R btn",
|
||||
};
|
||||
|
||||
static char *gpbtns_paddles[] =
|
||||
{
|
||||
// Xbox
|
||||
"SHARE",
|
||||
"P1",
|
||||
"P3",
|
||||
"P2",
|
||||
"P4",
|
||||
// Playstation
|
||||
"MIC",
|
||||
"RB",
|
||||
"LB",
|
||||
"Right Fn",
|
||||
"Left Fn",
|
||||
// Switch
|
||||
"CAPTURE",
|
||||
"Right SR",
|
||||
"Left SL",
|
||||
"Right SL",
|
||||
"Left SR" // JoyCon btn positions suck
|
||||
};
|
||||
|
||||
static char *gpbtns_triggers[] =
|
||||
{
|
||||
// Xbox
|
||||
"LT",
|
||||
"RT",
|
||||
// Playstation
|
||||
"L2",
|
||||
"R2",
|
||||
// Switch
|
||||
"ZL",
|
||||
"ZR"
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
static void
|
||||
|
@ -738,6 +823,7 @@ static int
|
|||
Key_StringToKeynum(char *str)
|
||||
{
|
||||
keyname_t *kn;
|
||||
int i;
|
||||
|
||||
if (!str || !str[0])
|
||||
{
|
||||
|
@ -757,6 +843,14 @@ Key_StringToKeynum(char *str)
|
|||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < NUM_GAMEPAD_BTNS; i++)
|
||||
{
|
||||
if (!Q_stricmp(str, gamepadbtns[i]))
|
||||
{
|
||||
return K_JOY_FIRST_BTN + i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -784,6 +878,11 @@ Key_KeynumToString(int keynum)
|
|||
return tinystr;
|
||||
}
|
||||
|
||||
if (keynum >= K_JOY_FIRST_BTN) // gamepad button
|
||||
{
|
||||
return gamepadbtns[keynum - K_JOY_FIRST_BTN];
|
||||
}
|
||||
|
||||
for (kn = keynames; kn->name; kn++)
|
||||
{
|
||||
if (keynum == kn->keynum)
|
||||
|
@ -795,6 +894,49 @@ Key_KeynumToString(int keynum)
|
|||
return "<UNKNOWN KEYNUM>";
|
||||
}
|
||||
|
||||
/*
|
||||
* Same as Key_KeynumToString(), but for joystick/gamepad buttons.
|
||||
*/
|
||||
char *
|
||||
Key_KeynumToString_Joy(int key)
|
||||
{
|
||||
extern gamepad_labels_t joy_current_lbls;
|
||||
const int lbl_style = (int)joy_current_lbls - 1;
|
||||
|
||||
if (key < K_JOY_FIRST_BTN)
|
||||
{
|
||||
return Key_KeynumToString(key);
|
||||
}
|
||||
|
||||
// Don't print the _ALT buttons (buttons with the alt modifier pressed)
|
||||
if (key >= K_JOY_FIRST_BTN_ALT)
|
||||
{
|
||||
key -= K_JOY_FIRST_BTN_ALT - K_JOY_FIRST_BTN;
|
||||
}
|
||||
|
||||
if (lbl_style < 0) // was SDL
|
||||
{
|
||||
goto exit_sdl;
|
||||
}
|
||||
|
||||
// Alter this logic if new gamepad buttons are added in SDL
|
||||
if (key < K_DPAD_UP) // face & shoulder buttons
|
||||
{
|
||||
return gpbtns_face[lbl_style * (K_DPAD_UP - K_BTN_SOUTH) + key - K_BTN_SOUTH];
|
||||
}
|
||||
else if (key >= K_TRIG_LEFT) // triggers
|
||||
{
|
||||
return gpbtns_triggers[lbl_style * (K_JOY_FIRST_BTN_ALT - K_TRIG_LEFT) + key - K_TRIG_LEFT];
|
||||
}
|
||||
else if (key > K_DPAD_RIGHT && key < K_TOUCHPAD) // paddles & misc1
|
||||
{
|
||||
return gpbtns_paddles[lbl_style * (K_TOUCHPAD - K_BTN_MISC1) + key - K_BTN_MISC1];
|
||||
}
|
||||
|
||||
exit_sdl:
|
||||
return gamepadbtns[key - K_JOY_FIRST_BTN];
|
||||
}
|
||||
|
||||
void
|
||||
Key_SetBinding(int keynum, char *binding)
|
||||
{
|
||||
|
@ -884,7 +1026,7 @@ Key_Bind_f(void)
|
|||
}
|
||||
|
||||
/* don't allow binding escape or the special console keys */
|
||||
if(b == K_ESCAPE || b == '^' || b == '`' || b == '~' || b == K_JOY_BACK)
|
||||
if(b == K_ESCAPE || b == '^' || b == '`' || b == '~')
|
||||
{
|
||||
if(doneWithDefaultCfg)
|
||||
{
|
||||
|
@ -1202,12 +1344,12 @@ Key_Event(int key, qboolean down, qboolean special)
|
|||
unsigned int time = Sys_Milliseconds();
|
||||
|
||||
// evil hack for the joystick key altselector, which turns K_BTN_x into K_BTN_x_ALT
|
||||
if(joy_altselector_pressed && key >= K_JOY_FIRST_REGULAR && key <= K_JOY_LAST_REGULAR)
|
||||
if(joy_altselector_pressed && key >= K_JOY_FIRST_BTN && key < K_JOY_FIRST_BTN_ALT)
|
||||
{
|
||||
// make sure key is not the altselector itself (which we won't turn into *_ALT)
|
||||
if(keybindings[key] == NULL || strcmp(keybindings[key], "+joyaltselector") != 0)
|
||||
{
|
||||
int altkey = key + (K_JOY_FIRST_REGULAR_ALT - K_JOY_FIRST_REGULAR);
|
||||
int altkey = key + (K_JOY_FIRST_BTN_ALT - K_JOY_FIRST_BTN);
|
||||
// allow fallback to binding with non-alt key
|
||||
if(keybindings[altkey] != NULL || keybindings[key] == NULL)
|
||||
key = altkey;
|
||||
|
@ -1274,7 +1416,7 @@ Key_Event(int key, qboolean down, qboolean special)
|
|||
}
|
||||
|
||||
/* Key is unbound */
|
||||
if ((key >= K_MOUSE1 && key != K_JOY_BACK) && !keybindings[key] && (cls.key_dest != key_console) &&
|
||||
if ((key >= K_MOUSE1) && !keybindings[key] && (cls.key_dest != key_console) &&
|
||||
(cls.state == ca_active))
|
||||
{
|
||||
Com_Printf("%s (%d) is unbound, hit F4 to set.\n", Key_KeynumToString(key), key);
|
||||
|
@ -1295,47 +1437,43 @@ Key_Event(int key, qboolean down, qboolean special)
|
|||
- moves one menu level up
|
||||
- closes the menu
|
||||
- closes the help computer
|
||||
- closes the chat window
|
||||
Fully same logic for K_JOY_BACK */
|
||||
if (!cls.disable_screen)
|
||||
- closes the chat window */
|
||||
if (key == K_ESCAPE && !cls.disable_screen)
|
||||
{
|
||||
if (key == K_ESCAPE || key == K_JOY_BACK)
|
||||
if (!down)
|
||||
{
|
||||
if (!down)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Close the help computer */
|
||||
if (cl.frame.playerstate.stats[STAT_LAYOUTS] &&
|
||||
(cls.key_dest == key_game))
|
||||
{
|
||||
Cbuf_AddText("cmd putaway\n");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (cls.key_dest)
|
||||
{
|
||||
/* Close chat window */
|
||||
case key_message:
|
||||
Key_Message(key);
|
||||
break;
|
||||
|
||||
/* Close menu or one layer up */
|
||||
case key_menu:
|
||||
M_Keydown(key);
|
||||
break;
|
||||
|
||||
/* Pause game and / or leave console,
|
||||
break into the menu. */
|
||||
case key_game:
|
||||
case key_console:
|
||||
M_Menu_Main_f();
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Close the help computer */
|
||||
if (cl.frame.playerstate.stats[STAT_LAYOUTS] &&
|
||||
(cls.key_dest == key_game))
|
||||
{
|
||||
Cbuf_AddText("cmd putaway\n");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (cls.key_dest)
|
||||
{
|
||||
/* Close chat window */
|
||||
case key_message:
|
||||
Key_Message(key);
|
||||
break;
|
||||
|
||||
/* Close menu or one layer up */
|
||||
case key_menu:
|
||||
M_Keydown(key);
|
||||
break;
|
||||
|
||||
/* Pause game and / or leave console,
|
||||
break into the menu. */
|
||||
case key_game:
|
||||
case key_console:
|
||||
M_Menu_Main_f();
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* This is one of the most ugly constructs I've
|
||||
|
|
|
@ -491,8 +491,18 @@ void CL_BaseMove (usercmd_t *cmd);
|
|||
|
||||
void IN_CenterView (void);
|
||||
|
||||
typedef enum
|
||||
{
|
||||
LBL_SDL = 0,
|
||||
LBL_XBOX,
|
||||
LBL_PLAYSTATION,
|
||||
LBL_SWITCH,
|
||||
LBL_MAX_COUNT
|
||||
} gamepad_labels_t;
|
||||
|
||||
float CL_KeyState (kbutton_t *key);
|
||||
char *Key_KeynumToString (int keynum);
|
||||
char *Key_KeynumToString_Joy (int key);
|
||||
|
||||
void CL_WriteDemoMessage (void);
|
||||
void CL_Stop_f (void);
|
||||
|
|
|
@ -208,11 +208,11 @@ enum QKEYS {
|
|||
// From here on, only gamepad controls must be allowed.
|
||||
// Otherwise, separate bindings (keyboard / controller) menu options will not work.
|
||||
|
||||
K_BTN_A,
|
||||
K_JOY_FIRST_REGULAR = K_BTN_A,
|
||||
K_BTN_B,
|
||||
K_BTN_X,
|
||||
K_BTN_Y,
|
||||
K_BTN_SOUTH,
|
||||
K_JOY_FIRST_BTN = K_BTN_SOUTH,
|
||||
K_BTN_EAST,
|
||||
K_BTN_WEST,
|
||||
K_BTN_NORTH,
|
||||
K_BTN_BACK,
|
||||
K_BTN_GUIDE,
|
||||
K_BTN_START,
|
||||
|
@ -225,26 +225,28 @@ enum QKEYS {
|
|||
K_DPAD_LEFT,
|
||||
K_DPAD_RIGHT,
|
||||
K_BTN_MISC1,
|
||||
K_PADDLE_1,
|
||||
K_PADDLE_2,
|
||||
K_PADDLE_3,
|
||||
K_PADDLE_4,
|
||||
K_TOUCHPAD, // SDL_CONTROLLER_BUTTON_MAX - 1
|
||||
K_PADDLE_RIGHT_1,
|
||||
K_PADDLE_LEFT_1,
|
||||
K_PADDLE_RIGHT_2,
|
||||
K_PADDLE_LEFT_2,
|
||||
K_TOUCHPAD, // SDL_CONTROLLER_BUTTON_MAX - 1, SDL2 limit
|
||||
K_BTN_MISC2,
|
||||
K_BTN_MISC3,
|
||||
K_BTN_MISC4,
|
||||
K_BTN_MISC5,
|
||||
K_BTN_MISC6, // SDL_GAMEPAD_BUTTON_COUNT - 1, current SDL3 count
|
||||
K_TRIG_LEFT, // buttons for triggers (axes)
|
||||
K_TRIG_RIGHT,
|
||||
|
||||
// add other joystick/controller keys before this one
|
||||
// and adjust it accordingly, also remember to add corresponding _ALT key below!
|
||||
K_JOY_LAST_REGULAR = K_TRIG_RIGHT,
|
||||
// Add other gamepad keys before this one, adjust from SDL 2/3 definitions, and
|
||||
// add the corresponding _ALT key below! Respect the order, must be the same as above.
|
||||
// Also, verify if cl_keyboard.c needs a refactor on its arrays.
|
||||
|
||||
/* Can't be mapped to any action (=> not regular) */
|
||||
K_JOY_BACK,
|
||||
|
||||
K_BTN_A_ALT,
|
||||
K_JOY_FIRST_REGULAR_ALT = K_BTN_A_ALT,
|
||||
K_BTN_B_ALT,
|
||||
K_BTN_X_ALT,
|
||||
K_BTN_Y_ALT,
|
||||
K_BTN_SOUTH_ALT,
|
||||
K_JOY_FIRST_BTN_ALT = K_BTN_SOUTH_ALT,
|
||||
K_BTN_EAST_ALT,
|
||||
K_BTN_WEST_ALT,
|
||||
K_BTN_NORTH_ALT,
|
||||
K_BTN_BACK_ALT,
|
||||
K_BTN_GUIDE_ALT,
|
||||
K_BTN_START_ALT,
|
||||
|
@ -257,11 +259,16 @@ enum QKEYS {
|
|||
K_DPAD_LEFT_ALT,
|
||||
K_DPAD_RIGHT_ALT,
|
||||
K_BTN_MISC1_ALT,
|
||||
K_PADDLE_1_ALT,
|
||||
K_PADDLE_2_ALT,
|
||||
K_PADDLE_3_ALT,
|
||||
K_PADDLE_4_ALT,
|
||||
K_PADDLE_RIGHT_1_ALT,
|
||||
K_PADDLE_LEFT_1_ALT,
|
||||
K_PADDLE_RIGHT_2_ALT,
|
||||
K_PADDLE_LEFT_2_ALT,
|
||||
K_TOUCHPAD_ALT,
|
||||
K_BTN_MISC2_ALT,
|
||||
K_BTN_MISC3_ALT,
|
||||
K_BTN_MISC4_ALT,
|
||||
K_BTN_MISC5_ALT,
|
||||
K_BTN_MISC6_ALT,
|
||||
K_TRIG_LEFT_ALT,
|
||||
K_TRIG_RIGHT_ALT,
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@ typedef enum
|
|||
// IN_Update() called at the beginning of a frame to the
|
||||
// actual movement functions called at a later time.
|
||||
static float mouse_x, mouse_y;
|
||||
static unsigned char sdl_back_button = SDL_CONTROLLER_BUTTON_START;
|
||||
static unsigned char joy_escbutton = SDL_CONTROLLER_BUTTON_START;
|
||||
static int joystick_left_x, joystick_left_y, joystick_right_x, joystick_right_y;
|
||||
static float gyro_yaw, gyro_pitch;
|
||||
static qboolean mlooking;
|
||||
|
@ -91,6 +91,12 @@ int sys_frame_time;
|
|||
// is pressed
|
||||
qboolean joy_altselector_pressed = false;
|
||||
|
||||
// Gamepad labels' style (Xbox, Playstation, etc.) in use, normally set after detection
|
||||
gamepad_labels_t joy_current_lbls = LBL_SDL;
|
||||
|
||||
// Using japanese style for confirm & cancel buttons on gamepad
|
||||
qboolean japanese_confirm = false;
|
||||
|
||||
// Console Variables
|
||||
cvar_t *freelook;
|
||||
cvar_t *lookstrafe;
|
||||
|
@ -134,6 +140,12 @@ static int last_haptic_effect_size = HAPTIC_EFFECT_LIST_SIZE;
|
|||
static int last_haptic_effect_pos = 0;
|
||||
static haptic_effects_cache_t last_haptic_effect[HAPTIC_EFFECT_LIST_SIZE];
|
||||
|
||||
// Gamepad labels' style (Xbox, Playstation, etc.) requested by user
|
||||
static cvar_t *joy_labels;
|
||||
|
||||
// Gamepad style for confirm and cancel buttons (traditional or japanese)
|
||||
static cvar_t *joy_confirm;
|
||||
|
||||
// Joystick sensitivity
|
||||
static cvar_t *joy_yawsensitivity;
|
||||
static cvar_t *joy_pitchsensitivity;
|
||||
|
@ -506,6 +518,110 @@ IN_TranslateScancodeToQ2Key(SDL_Scancode sc)
|
|||
static void IN_Controller_Init(qboolean notify_user);
|
||||
static void IN_Controller_Shutdown(qboolean notify_user);
|
||||
|
||||
/*
|
||||
* Sets the gamepad buttons' style of labels (SDL, Xbox, PS, Switch).
|
||||
* They are only visible in the gamepad binding options.
|
||||
* Traditional binding uses SDL style, no matter the gamepad.
|
||||
*/
|
||||
static void
|
||||
IN_GamepadLabels_Changed(void)
|
||||
{
|
||||
const int requested = (int)joy_labels->value;
|
||||
joy_labels->modified = false;
|
||||
joy_current_lbls = LBL_SDL;
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 12)
|
||||
if (requested < 0 && controller) // try to autodetect...
|
||||
{
|
||||
switch (SDL_GameControllerGetType(controller))
|
||||
{
|
||||
case SDL_CONTROLLER_TYPE_XBOX360:
|
||||
case SDL_CONTROLLER_TYPE_XBOXONE:
|
||||
joy_current_lbls = LBL_XBOX;
|
||||
return;
|
||||
|
||||
case SDL_CONTROLLER_TYPE_PS3:
|
||||
case SDL_CONTROLLER_TYPE_PS4:
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 14)
|
||||
case SDL_CONTROLLER_TYPE_PS5:
|
||||
#endif // SDL_VERSION_ATLEAST(2, 0, 14)
|
||||
joy_current_lbls = LBL_PLAYSTATION;
|
||||
return;
|
||||
|
||||
case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO:
|
||||
#if SDL_VERSION_ATLEAST(2, 24, 0)
|
||||
case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_PAIR:
|
||||
#endif // SDL_VERSION_ATLEAST(2, 24, 0)
|
||||
joy_current_lbls = LBL_SWITCH;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif // SDL_VERSION_ATLEAST(2, 0, 12)
|
||||
if (requested >= LBL_SDL && requested < LBL_MAX_COUNT)
|
||||
{
|
||||
joy_current_lbls = (gamepad_labels_t)requested;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets which gamepad button works as "confirm", and which
|
||||
* works as "cancel", in menus.
|
||||
*/
|
||||
static void
|
||||
IN_GamepadConfirm_Changed(void)
|
||||
{
|
||||
const int requested = (int)joy_confirm->value;
|
||||
japanese_confirm = false;
|
||||
joy_confirm->modified = false;
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 12)
|
||||
if (requested < 0 && controller) // try to autodetect...
|
||||
{
|
||||
switch (SDL_GameControllerGetType(controller))
|
||||
{
|
||||
case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO:
|
||||
#if SDL_VERSION_ATLEAST(2, 24, 0)
|
||||
case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_PAIR:
|
||||
#endif // SDL_VERSION_ATLEAST(2, 24, 0)
|
||||
japanese_confirm = true;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif // SDL_VERSION_ATLEAST(2, 0, 12)
|
||||
if (requested == 1)
|
||||
{
|
||||
japanese_confirm = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
IN_GyroMode_Changed(void)
|
||||
{
|
||||
if (gyro_mode->value < 2)
|
||||
{
|
||||
gyro_active = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
gyro_active = true;
|
||||
}
|
||||
gyro_mode->modified = false;
|
||||
}
|
||||
|
||||
static void
|
||||
IN_VirtualKeyEvent(int keynum, qboolean *state_store, qboolean new_state)
|
||||
{
|
||||
if (new_state != *state_store)
|
||||
{
|
||||
*state_store = new_state;
|
||||
Key_Event(keynum, *state_store, true);
|
||||
}
|
||||
}
|
||||
|
||||
qboolean IN_NumpadIsOn()
|
||||
{
|
||||
SDL_Keymod mod = SDL_GetModState();
|
||||
|
@ -534,6 +650,7 @@ IN_Update(void)
|
|||
|
||||
static qboolean left_trigger = false;
|
||||
static qboolean right_trigger = false;
|
||||
static qboolean left_stick[4] = {false, false, false, false}; // left, right, up, down virtual keys
|
||||
|
||||
static int consoleKeyCode = 0;
|
||||
|
||||
|
@ -734,8 +851,8 @@ IN_Update(void)
|
|||
qboolean down = (event.type == SDL_CONTROLLERBUTTONDOWN);
|
||||
unsigned char btn = event.cbutton.button;
|
||||
|
||||
// Handle Back Button, to override its original key
|
||||
Key_Event( (btn == sdl_back_button)? K_JOY_BACK : K_BTN_A + btn,
|
||||
// Handle Esc button first, to override its original key
|
||||
Key_Event( (btn == joy_escbutton)? K_ESCAPE : K_JOY_FIRST_BTN + btn,
|
||||
down, true );
|
||||
break;
|
||||
}
|
||||
|
@ -747,26 +864,12 @@ IN_Update(void)
|
|||
switch (event.caxis.axis)
|
||||
{
|
||||
case SDL_CONTROLLER_AXIS_TRIGGERLEFT:
|
||||
{
|
||||
qboolean new_left_trigger = axis_value > 8192;
|
||||
if (new_left_trigger != left_trigger)
|
||||
{
|
||||
left_trigger = new_left_trigger;
|
||||
Key_Event(K_TRIG_LEFT, left_trigger, true);
|
||||
}
|
||||
IN_VirtualKeyEvent(K_TRIG_LEFT, &left_trigger, axis_value > 8192);
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_CONTROLLER_AXIS_TRIGGERRIGHT:
|
||||
{
|
||||
qboolean new_right_trigger = axis_value > 8192;
|
||||
if (new_right_trigger != right_trigger)
|
||||
{
|
||||
right_trigger = new_right_trigger;
|
||||
Key_Event(K_TRIG_RIGHT, right_trigger, true);
|
||||
}
|
||||
IN_VirtualKeyEvent(K_TRIG_RIGHT, &right_trigger, axis_value > 8192);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!cl_paused->value && cls.key_dest == key_game)
|
||||
|
@ -786,6 +889,24 @@ IN_Update(void)
|
|||
joystick_right_y = axis_value;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Virtual keys to navigate menus with left stick
|
||||
if (cls.key_dest == key_menu)
|
||||
{
|
||||
switch (event.caxis.axis)
|
||||
{
|
||||
case SDL_CONTROLLER_AXIS_LEFTX:
|
||||
IN_VirtualKeyEvent(K_LEFTARROW, &left_stick[0], axis_value < -16896);
|
||||
IN_VirtualKeyEvent(K_RIGHTARROW, &left_stick[1], axis_value > 16896);
|
||||
break;
|
||||
|
||||
case SDL_CONTROLLER_AXIS_LEFTY:
|
||||
IN_VirtualKeyEvent(K_UPARROW, &left_stick[2], axis_value < -16896);
|
||||
IN_VirtualKeyEvent(K_DOWNARROW, &left_stick[3], axis_value > 16896);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -834,8 +955,7 @@ IN_Update(void)
|
|||
|
||||
#endif // !NO_SDL_GYRO
|
||||
|
||||
if (gyro_active && gyro_mode->value &&
|
||||
!cl_paused->value && cls.key_dest == key_game)
|
||||
if (gyro_active && !cl_paused->value && cls.key_dest == key_game)
|
||||
{
|
||||
#ifndef NO_SDL_GYRO
|
||||
if (!gyro_turning_axis->value)
|
||||
|
@ -986,6 +1106,19 @@ IN_Update(void)
|
|||
countdown_reason = REASON_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
if (joy_labels->modified)
|
||||
{
|
||||
IN_GamepadLabels_Changed();
|
||||
}
|
||||
if (joy_confirm->modified)
|
||||
{
|
||||
IN_GamepadConfirm_Changed();
|
||||
}
|
||||
if (gyro_mode->modified)
|
||||
{
|
||||
IN_GyroMode_Changed();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1960,19 +2093,19 @@ IN_Controller_Init(qboolean notify_user)
|
|||
SDL_Joystick *joystick = NULL;
|
||||
SDL_bool is_controller = SDL_FALSE;
|
||||
|
||||
cvar = Cvar_Get("in_sdlbackbutton", "1", CVAR_ARCHIVE);
|
||||
cvar = Cvar_Get("joy_escbutton", "0", CVAR_ARCHIVE);
|
||||
if (cvar)
|
||||
{
|
||||
switch ((int)cvar->value)
|
||||
{
|
||||
case 0:
|
||||
sdl_back_button = SDL_CONTROLLER_BUTTON_BACK;
|
||||
case 1:
|
||||
joy_escbutton = SDL_CONTROLLER_BUTTON_BACK;
|
||||
break;
|
||||
case 2:
|
||||
sdl_back_button = SDL_CONTROLLER_BUTTON_GUIDE;
|
||||
joy_escbutton = SDL_CONTROLLER_BUTTON_GUIDE;
|
||||
break;
|
||||
default:
|
||||
sdl_back_button = SDL_CONTROLLER_BUTTON_START;
|
||||
joy_escbutton = SDL_CONTROLLER_BUTTON_START;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1996,6 +2129,9 @@ IN_Controller_Init(qboolean notify_user)
|
|||
#ifdef SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE
|
||||
SDL_SetHint( SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE, "1" );
|
||||
#endif
|
||||
#ifdef SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS // use button positions instead of labels, like SDL3
|
||||
SDL_SetHint( SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS, "0" );
|
||||
#endif
|
||||
|
||||
if (SDL_Init(SDL_INIT_GAMECONTROLLER | SDL_INIT_HAPTIC) == -1)
|
||||
{
|
||||
|
@ -2181,6 +2317,10 @@ IN_Controller_Init(qboolean notify_user)
|
|||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
IN_GamepadLabels_Changed();
|
||||
IN_GamepadConfirm_Changed();
|
||||
IN_GyroMode_Changed();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2216,6 +2356,8 @@ IN_Init(void)
|
|||
joy_forwardsensitivity = Cvar_Get("joy_forwardsensitivity", "1.0", CVAR_ARCHIVE);
|
||||
joy_sidesensitivity = Cvar_Get("joy_sidesensitivity", "1.0", CVAR_ARCHIVE);
|
||||
|
||||
joy_labels = Cvar_Get("joy_labels", "-1", CVAR_ARCHIVE);
|
||||
joy_confirm = Cvar_Get("joy_confirm", "-1", CVAR_ARCHIVE);
|
||||
joy_layout = Cvar_Get("joy_layout", "0", CVAR_ARCHIVE);
|
||||
joy_left_expo = Cvar_Get("joy_left_expo", "2.0", CVAR_ARCHIVE);
|
||||
joy_left_snapaxis = Cvar_Get("joy_left_snapaxis", "0.15", CVAR_ARCHIVE);
|
||||
|
@ -2230,16 +2372,11 @@ IN_Init(void)
|
|||
gyro_calibration_y = Cvar_Get("gyro_calibration_y", "0.0", CVAR_ARCHIVE);
|
||||
gyro_calibration_z = Cvar_Get("gyro_calibration_z", "0.0", CVAR_ARCHIVE);
|
||||
|
||||
gyro_yawsensitivity = Cvar_Get("gyro_yawsensitivity", "1.0", CVAR_ARCHIVE);
|
||||
gyro_pitchsensitivity = Cvar_Get("gyro_pitchsensitivity", "1.0", CVAR_ARCHIVE);
|
||||
gyro_yawsensitivity = Cvar_Get("gyro_yawsensitivity", "2.5", CVAR_ARCHIVE);
|
||||
gyro_pitchsensitivity = Cvar_Get("gyro_pitchsensitivity", "2.5", CVAR_ARCHIVE);
|
||||
gyro_tightening = Cvar_Get("gyro_tightening", "3.5", CVAR_ARCHIVE);
|
||||
gyro_turning_axis = Cvar_Get("gyro_turning_axis", "0", CVAR_ARCHIVE);
|
||||
|
||||
gyro_mode = Cvar_Get("gyro_mode", "2", CVAR_ARCHIVE);
|
||||
if ((int)gyro_mode->value == 2)
|
||||
{
|
||||
gyro_active = true;
|
||||
}
|
||||
|
||||
windowed_pauseonfocuslost = Cvar_Get("vid_pauseonfocuslost", "0", CVAR_USERINFO | CVAR_ARCHIVE);
|
||||
windowed_mouse = Cvar_Get("windowed_mouse", "1", CVAR_USERINFO | CVAR_ARCHIVE);
|
||||
|
|
|
@ -81,7 +81,7 @@ typedef enum
|
|||
// IN_Update() called at the beginning of a frame to the
|
||||
// actual movement functions called at a later time.
|
||||
static float mouse_x, mouse_y;
|
||||
static unsigned char sdl_back_button = SDL_GAMEPAD_BUTTON_START;
|
||||
static unsigned char joy_escbutton = SDL_GAMEPAD_BUTTON_START;
|
||||
static int joystick_left_x, joystick_left_y, joystick_right_x, joystick_right_y;
|
||||
static float gyro_yaw, gyro_pitch;
|
||||
static qboolean mlooking;
|
||||
|
@ -94,6 +94,12 @@ int sys_frame_time;
|
|||
// is pressed
|
||||
qboolean joy_altselector_pressed = false;
|
||||
|
||||
// Gamepad labels' style (Xbox, Playstation, etc.) in use, normally set after detection
|
||||
gamepad_labels_t joy_current_lbls = LBL_SDL;
|
||||
|
||||
// Using japanese style for confirm & cancel buttons on gamepad
|
||||
qboolean japanese_confirm = false;
|
||||
|
||||
// Console Variables
|
||||
cvar_t *freelook;
|
||||
cvar_t *lookstrafe;
|
||||
|
@ -137,6 +143,12 @@ static int last_haptic_effect_size = HAPTIC_EFFECT_LIST_SIZE;
|
|||
static int last_haptic_effect_pos = 0;
|
||||
static haptic_effects_cache_t last_haptic_effect[HAPTIC_EFFECT_LIST_SIZE];
|
||||
|
||||
// Gamepad labels' style (Xbox, Playstation, etc.) requested by user
|
||||
static cvar_t *joy_labels;
|
||||
|
||||
// Gamepad style for confirm and cancel buttons (traditional or japanese)
|
||||
static cvar_t *joy_confirm;
|
||||
|
||||
// Joystick sensitivity
|
||||
static cvar_t *joy_yawsensitivity;
|
||||
static cvar_t *joy_pitchsensitivity;
|
||||
|
@ -504,6 +516,98 @@ IN_TranslateScancodeToQ2Key(SDL_Scancode sc)
|
|||
static void IN_Controller_Init(qboolean notify_user);
|
||||
static void IN_Controller_Shutdown(qboolean notify_user);
|
||||
|
||||
/*
|
||||
* Sets the gamepad buttons' style of labels (SDL, Xbox, PS, Switch).
|
||||
* They are only visible in the gamepad binding options.
|
||||
* Traditional binding uses SDL style, no matter the gamepad.
|
||||
*/
|
||||
static void
|
||||
IN_GamepadLabels_Changed(void)
|
||||
{
|
||||
const int requested = (int)joy_labels->value;
|
||||
joy_labels->modified = false;
|
||||
joy_current_lbls = LBL_SDL;
|
||||
|
||||
if (requested < 0 && controller) // try to autodetect...
|
||||
{
|
||||
switch (SDL_GetGamepadType(controller))
|
||||
{
|
||||
case SDL_GAMEPAD_TYPE_XBOX360:
|
||||
case SDL_GAMEPAD_TYPE_XBOXONE:
|
||||
joy_current_lbls = LBL_XBOX;
|
||||
return;
|
||||
|
||||
case SDL_GAMEPAD_TYPE_PS3:
|
||||
case SDL_GAMEPAD_TYPE_PS4:
|
||||
case SDL_GAMEPAD_TYPE_PS5:
|
||||
joy_current_lbls = LBL_PLAYSTATION;
|
||||
return;
|
||||
|
||||
case SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO:
|
||||
case SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_PAIR:
|
||||
joy_current_lbls = LBL_SWITCH;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (requested >= LBL_SDL && requested < LBL_MAX_COUNT)
|
||||
{
|
||||
joy_current_lbls = (gamepad_labels_t)requested;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets which gamepad button works as "confirm", and which
|
||||
* works as "cancel", in menus.
|
||||
*/
|
||||
static void
|
||||
IN_GamepadConfirm_Changed(void)
|
||||
{
|
||||
const int requested = (int)joy_confirm->value;
|
||||
japanese_confirm = false;
|
||||
joy_confirm->modified = false;
|
||||
|
||||
if (requested < 0 && controller) // try to autodetect...
|
||||
{
|
||||
switch (SDL_GetGamepadType(controller))
|
||||
{
|
||||
case SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO:
|
||||
case SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_PAIR:
|
||||
japanese_confirm = true;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (requested == 1)
|
||||
{
|
||||
japanese_confirm = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
IN_GyroMode_Changed(void)
|
||||
{
|
||||
if (gyro_mode->value < 2)
|
||||
{
|
||||
gyro_active = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
gyro_active = true;
|
||||
}
|
||||
gyro_mode->modified = false;
|
||||
}
|
||||
|
||||
static void
|
||||
IN_VirtualKeyEvent(int keynum, qboolean *state_store, qboolean new_state)
|
||||
{
|
||||
if (new_state != *state_store)
|
||||
{
|
||||
*state_store = new_state;
|
||||
Key_Event(keynum, *state_store, true);
|
||||
}
|
||||
}
|
||||
|
||||
qboolean IN_NumpadIsOn()
|
||||
{
|
||||
SDL_Keymod mod = SDL_GetModState();
|
||||
|
@ -532,6 +636,7 @@ IN_Update(void)
|
|||
|
||||
static qboolean left_trigger = false;
|
||||
static qboolean right_trigger = false;
|
||||
static qboolean left_stick[4] = {false, false, false, false}; // left, right, up, down virtual keys
|
||||
|
||||
static int consoleKeyCode = 0;
|
||||
|
||||
|
@ -733,8 +838,8 @@ IN_Update(void)
|
|||
qboolean down = (event.type == SDL_EVENT_GAMEPAD_BUTTON_DOWN);
|
||||
unsigned char btn = event.gbutton.button;
|
||||
|
||||
// Handle Back Button, to override its original key
|
||||
Key_Event( (btn == sdl_back_button)? K_JOY_BACK : K_BTN_A + btn,
|
||||
// Handle Esc button first, to override its original key
|
||||
Key_Event( (btn == joy_escbutton)? K_ESCAPE : K_JOY_FIRST_BTN + btn,
|
||||
down, true );
|
||||
break;
|
||||
}
|
||||
|
@ -746,26 +851,12 @@ IN_Update(void)
|
|||
switch (event.gaxis.axis)
|
||||
{
|
||||
case SDL_GAMEPAD_AXIS_LEFT_TRIGGER :
|
||||
{
|
||||
qboolean new_left_trigger = axis_value > 8192;
|
||||
if (new_left_trigger != left_trigger)
|
||||
{
|
||||
left_trigger = new_left_trigger;
|
||||
Key_Event(K_TRIG_LEFT, left_trigger, true);
|
||||
}
|
||||
IN_VirtualKeyEvent(K_TRIG_LEFT, &left_trigger, axis_value > 8192);
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_GAMEPAD_AXIS_RIGHT_TRIGGER :
|
||||
{
|
||||
qboolean new_right_trigger = axis_value > 8192;
|
||||
if (new_right_trigger != right_trigger)
|
||||
{
|
||||
right_trigger = new_right_trigger;
|
||||
Key_Event(K_TRIG_RIGHT, right_trigger, true);
|
||||
}
|
||||
IN_VirtualKeyEvent(K_TRIG_RIGHT, &right_trigger, axis_value > 8192);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!cl_paused->value && cls.key_dest == key_game)
|
||||
|
@ -785,6 +876,24 @@ IN_Update(void)
|
|||
joystick_right_y = axis_value;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Virtual keys to navigate menus with left stick
|
||||
if (cls.key_dest == key_menu)
|
||||
{
|
||||
switch (event.gaxis.axis)
|
||||
{
|
||||
case SDL_GAMEPAD_AXIS_LEFTX :
|
||||
IN_VirtualKeyEvent(K_LEFTARROW, &left_stick[0], axis_value < -16896);
|
||||
IN_VirtualKeyEvent(K_RIGHTARROW, &left_stick[1], axis_value > 16896);
|
||||
break;
|
||||
|
||||
case SDL_GAMEPAD_AXIS_LEFTY :
|
||||
IN_VirtualKeyEvent(K_UPARROW, &left_stick[2], axis_value < -16896);
|
||||
IN_VirtualKeyEvent(K_DOWNARROW, &left_stick[3], axis_value > 16896);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -833,8 +942,7 @@ IN_Update(void)
|
|||
|
||||
#endif // !NO_SDL_GYRO
|
||||
|
||||
if (gyro_active && gyro_mode->value &&
|
||||
!cl_paused->value && cls.key_dest == key_game)
|
||||
if (gyro_active && !cl_paused->value && cls.key_dest == key_game)
|
||||
{
|
||||
#ifndef NO_SDL_GYRO
|
||||
if (!gyro_turning_axis->value)
|
||||
|
@ -983,6 +1091,20 @@ IN_Update(void)
|
|||
countdown_reason = REASON_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
// Gamepad labels' type and "confirm & cancel style" change handling
|
||||
if (joy_labels->modified)
|
||||
{
|
||||
IN_GamepadLabels_Changed();
|
||||
}
|
||||
if (joy_confirm->modified)
|
||||
{
|
||||
IN_GamepadConfirm_Changed();
|
||||
}
|
||||
if (gyro_mode->modified)
|
||||
{
|
||||
IN_GyroMode_Changed();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2068,19 +2190,19 @@ IN_Controller_Init(qboolean notify_user)
|
|||
SDL_Joystick *joystick = NULL;
|
||||
bool is_controller = false;
|
||||
|
||||
cvar = Cvar_Get("in_sdlbackbutton", "1", CVAR_ARCHIVE);
|
||||
cvar = Cvar_Get("joy_escbutton", "0", CVAR_ARCHIVE);
|
||||
if (cvar)
|
||||
{
|
||||
switch ((int)cvar->value)
|
||||
{
|
||||
case 0:
|
||||
sdl_back_button = SDL_GAMEPAD_BUTTON_BACK;
|
||||
case 1:
|
||||
joy_escbutton = SDL_GAMEPAD_BUTTON_BACK;
|
||||
break;
|
||||
case 2:
|
||||
sdl_back_button = SDL_GAMEPAD_BUTTON_GUIDE;
|
||||
joy_escbutton = SDL_GAMEPAD_BUTTON_GUIDE;
|
||||
break;
|
||||
default:
|
||||
sdl_back_button = SDL_GAMEPAD_BUTTON_START;
|
||||
joy_escbutton = SDL_GAMEPAD_BUTTON_START;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2131,6 +2253,8 @@ IN_Controller_Init(qboolean notify_user)
|
|||
show_haptic = true;
|
||||
}
|
||||
|
||||
SDL_free((void *)joysticks);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2280,6 +2404,9 @@ IN_Controller_Init(qboolean notify_user)
|
|||
}
|
||||
|
||||
SDL_free((void *)joysticks);
|
||||
IN_GamepadLabels_Changed();
|
||||
IN_GamepadConfirm_Changed();
|
||||
IN_GyroMode_Changed();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2315,6 +2442,8 @@ IN_Init(void)
|
|||
joy_forwardsensitivity = Cvar_Get("joy_forwardsensitivity", "1.0", CVAR_ARCHIVE);
|
||||
joy_sidesensitivity = Cvar_Get("joy_sidesensitivity", "1.0", CVAR_ARCHIVE);
|
||||
|
||||
joy_labels = Cvar_Get("joy_labels", "-1", CVAR_ARCHIVE);
|
||||
joy_confirm = Cvar_Get("joy_confirm", "-1", CVAR_ARCHIVE);
|
||||
joy_layout = Cvar_Get("joy_layout", "0", CVAR_ARCHIVE);
|
||||
joy_left_expo = Cvar_Get("joy_left_expo", "2.0", CVAR_ARCHIVE);
|
||||
joy_left_snapaxis = Cvar_Get("joy_left_snapaxis", "0.15", CVAR_ARCHIVE);
|
||||
|
@ -2329,16 +2458,11 @@ IN_Init(void)
|
|||
gyro_calibration_y = Cvar_Get("gyro_calibration_y", "0.0", CVAR_ARCHIVE);
|
||||
gyro_calibration_z = Cvar_Get("gyro_calibration_z", "0.0", CVAR_ARCHIVE);
|
||||
|
||||
gyro_yawsensitivity = Cvar_Get("gyro_yawsensitivity", "1.0", CVAR_ARCHIVE);
|
||||
gyro_pitchsensitivity = Cvar_Get("gyro_pitchsensitivity", "1.0", CVAR_ARCHIVE);
|
||||
gyro_yawsensitivity = Cvar_Get("gyro_yawsensitivity", "2.5", CVAR_ARCHIVE);
|
||||
gyro_pitchsensitivity = Cvar_Get("gyro_pitchsensitivity", "2.5", CVAR_ARCHIVE);
|
||||
gyro_tightening = Cvar_Get("gyro_tightening", "3.5", CVAR_ARCHIVE);
|
||||
gyro_turning_axis = Cvar_Get("gyro_turning_axis", "0", CVAR_ARCHIVE);
|
||||
|
||||
gyro_mode = Cvar_Get("gyro_mode", "2", CVAR_ARCHIVE);
|
||||
if ((int)gyro_mode->value == 2)
|
||||
{
|
||||
gyro_active = true;
|
||||
}
|
||||
|
||||
windowed_pauseonfocuslost = Cvar_Get("vid_pauseonfocuslost", "0", CVAR_USERINFO | CVAR_ARCHIVE);
|
||||
windowed_mouse = Cvar_Get("windowed_mouse", "1", CVAR_USERINFO | CVAR_ARCHIVE);
|
||||
|
|
|
@ -257,6 +257,8 @@ M_PushMenu(menuframework_s* menu)
|
|||
cls.key_dest = key_menu;
|
||||
}
|
||||
|
||||
extern qboolean japanese_confirm;
|
||||
|
||||
int
|
||||
Key_GetMenuKey(int key)
|
||||
{
|
||||
|
@ -297,24 +299,27 @@ Key_GetMenuKey(int key)
|
|||
|
||||
case K_KP_ENTER:
|
||||
case K_ENTER:
|
||||
case K_BTN_A:
|
||||
return K_ENTER;
|
||||
|
||||
case K_ESCAPE:
|
||||
case K_JOY_BACK:
|
||||
case K_BTN_B:
|
||||
return K_ESCAPE;
|
||||
|
||||
case K_BACKSPACE:
|
||||
case K_DEL:
|
||||
case K_KP_DEL:
|
||||
if (IN_NumpadIsOn() == true) { break; }
|
||||
case K_BTN_Y:
|
||||
case K_BACKSPACE:
|
||||
case K_DEL:
|
||||
case K_BTN_NORTH:
|
||||
return K_BACKSPACE;
|
||||
|
||||
case K_KP_INS:
|
||||
if (IN_NumpadIsOn() == true) { break; }
|
||||
case K_INS:
|
||||
return K_INS;
|
||||
|
||||
case K_BTN_SOUTH:
|
||||
if (japanese_confirm) return K_ESCAPE;
|
||||
else return K_ENTER;
|
||||
|
||||
case K_BTN_EAST:
|
||||
if (japanese_confirm) return K_ENTER;
|
||||
else return K_ESCAPE;
|
||||
}
|
||||
|
||||
return key;
|
||||
|
@ -954,14 +959,14 @@ M_UnbindCommand(char *command, int scope)
|
|||
switch (scope)
|
||||
{
|
||||
case KEYS_KEYBOARD_MOUSE:
|
||||
end = K_JOY_FIRST_REGULAR;
|
||||
end = K_JOY_FIRST_BTN;
|
||||
break;
|
||||
case KEYS_CONTROLLER:
|
||||
begin = K_JOY_FIRST_REGULAR;
|
||||
end = K_JOY_LAST_REGULAR + 1;
|
||||
begin = K_JOY_FIRST_BTN;
|
||||
end = K_JOY_FIRST_BTN_ALT;
|
||||
break;
|
||||
case KEYS_CONTROLLER_ALT:
|
||||
begin = K_JOY_FIRST_REGULAR_ALT;
|
||||
begin = K_JOY_FIRST_BTN_ALT;
|
||||
}
|
||||
|
||||
for (j = begin; j < end; j++)
|
||||
|
@ -990,14 +995,14 @@ M_FindKeysForCommand(char *command, int *twokeys, int scope)
|
|||
switch (scope)
|
||||
{
|
||||
case KEYS_KEYBOARD_MOUSE:
|
||||
end = K_JOY_FIRST_REGULAR;
|
||||
end = K_JOY_FIRST_BTN;
|
||||
break;
|
||||
case KEYS_CONTROLLER:
|
||||
begin = K_JOY_FIRST_REGULAR;
|
||||
end = K_JOY_LAST_REGULAR + 1;
|
||||
begin = K_JOY_FIRST_BTN;
|
||||
end = K_JOY_FIRST_BTN_ALT;
|
||||
break;
|
||||
case KEYS_CONTROLLER_ALT:
|
||||
begin = K_JOY_FIRST_REGULAR_ALT;
|
||||
begin = K_JOY_FIRST_BTN_ALT;
|
||||
}
|
||||
|
||||
twokeys[0] = twokeys[1] = -1;
|
||||
|
@ -1138,7 +1143,7 @@ Keys_MenuKey(int key)
|
|||
if (menukeyitem_bind)
|
||||
{
|
||||
// Any key/button except from the game controller and escape keys
|
||||
if ((key != K_ESCAPE) && (key != '`') && (key < K_JOY_FIRST_REGULAR))
|
||||
if ((key != K_ESCAPE) && (key != '`') && (key < K_JOY_FIRST_BTN))
|
||||
{
|
||||
char cmd[1024];
|
||||
|
||||
|
@ -1291,7 +1296,7 @@ MultiplayerKeys_MenuKey(int key)
|
|||
if (menukeyitem_bind)
|
||||
{
|
||||
// Any key/button but the escape ones
|
||||
if ((key != K_ESCAPE) && (key != '`') && (key != K_JOY_BACK))
|
||||
if ((key != K_ESCAPE) && (key != '`'))
|
||||
{
|
||||
char cmd[1024];
|
||||
|
||||
|
@ -1333,6 +1338,30 @@ M_Menu_Multiplayer_Keys_f(void)
|
|||
* GAME CONTROLLER ( GAMEPAD / JOYSTICK ) BUTTONS MENU
|
||||
*/
|
||||
|
||||
static void
|
||||
GamepadMenu_StatusPrompt(menuframework_s *m)
|
||||
{
|
||||
static char m_gamepadbind_statusbar[64];
|
||||
int btn_confirm, btn_cancel;
|
||||
|
||||
if (japanese_confirm)
|
||||
{
|
||||
btn_confirm = K_BTN_EAST;
|
||||
btn_cancel = K_BTN_SOUTH;
|
||||
}
|
||||
else
|
||||
{
|
||||
btn_confirm = K_BTN_SOUTH;
|
||||
btn_cancel = K_BTN_EAST;
|
||||
}
|
||||
|
||||
snprintf(m_gamepadbind_statusbar, 64, "%s assigns, %s clears, %s exits",
|
||||
Key_KeynumToString_Joy(btn_confirm), Key_KeynumToString_Joy(K_BTN_NORTH),
|
||||
Key_KeynumToString_Joy(btn_cancel));
|
||||
|
||||
Menu_SetStatusBar(m, m_gamepadbind_statusbar);
|
||||
}
|
||||
|
||||
char *controller_bindnames[][2] =
|
||||
{
|
||||
{"+attack", "attack"},
|
||||
|
@ -1388,7 +1417,7 @@ DrawControllerButtonBindingFunc(void *self)
|
|||
int x;
|
||||
const char *name;
|
||||
|
||||
name = Key_KeynumToString(keys[0]);
|
||||
name = Key_KeynumToString_Joy(keys[0]);
|
||||
|
||||
Menu_DrawString(a->generic.x + a->generic.parent->x + RCOLUMN_OFFSET * scale,
|
||||
a->generic.y + a->generic.parent->y, name);
|
||||
|
@ -1401,7 +1430,7 @@ DrawControllerButtonBindingFunc(void *self)
|
|||
a->generic.y + a->generic.parent->y, "or");
|
||||
Menu_DrawString(a->generic.x + a->generic.parent->x + 48 * scale + (x * scale),
|
||||
a->generic.y + a->generic.parent->y,
|
||||
Key_KeynumToString(keys[1]));
|
||||
Key_KeynumToString_Joy(keys[1]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1446,7 +1475,7 @@ ControllerButtons_MenuInit(void)
|
|||
Menu_AddItem(&s_controller_buttons_menu, (void *)&s_controller_buttons_actions[i]);
|
||||
}
|
||||
|
||||
Menu_SetStatusBar(&s_controller_buttons_menu, "BTN_A assigns, BTN_Y clears, BTN_B exits");
|
||||
GamepadMenu_StatusPrompt(&s_controller_buttons_menu);
|
||||
Menu_Center(&s_controller_buttons_menu);
|
||||
}
|
||||
|
||||
|
@ -1465,7 +1494,7 @@ ControllerButtons_MenuKey(int key)
|
|||
if (menukeyitem_bind)
|
||||
{
|
||||
// Only controller buttons allowed
|
||||
if (key >= K_JOY_FIRST_REGULAR && key != K_JOY_BACK)
|
||||
if (key >= K_JOY_FIRST_BTN)
|
||||
{
|
||||
char cmd[1024];
|
||||
|
||||
|
@ -1474,7 +1503,7 @@ ControllerButtons_MenuKey(int key)
|
|||
Cbuf_InsertText(cmd);
|
||||
}
|
||||
|
||||
Menu_SetStatusBar(&s_controller_buttons_menu, "BTN_A assigns, BTN_Y clears, BTN_B exits");
|
||||
GamepadMenu_StatusPrompt(&s_controller_buttons_menu);
|
||||
menukeyitem_bind = false;
|
||||
return menu_out_sound;
|
||||
}
|
||||
|
@ -1562,7 +1591,7 @@ DrawControllerAltButtonBindingFunc(void *self)
|
|||
size_t x;
|
||||
const char *name;
|
||||
|
||||
name = Key_KeynumToString(keys[0]);
|
||||
name = Key_KeynumToString_Joy(keys[0]);
|
||||
|
||||
Menu_DrawString(a->generic.x + a->generic.parent->x + RCOLUMN_OFFSET * scale,
|
||||
a->generic.y + a->generic.parent->y, name);
|
||||
|
@ -1575,7 +1604,7 @@ DrawControllerAltButtonBindingFunc(void *self)
|
|||
a->generic.y + a->generic.parent->y, "or");
|
||||
Menu_DrawString(a->generic.x + a->generic.parent->x + 48 * scale + (x * scale),
|
||||
a->generic.y + a->generic.parent->y,
|
||||
Key_KeynumToString(keys[1]));
|
||||
Key_KeynumToString_Joy(keys[1]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1620,7 +1649,7 @@ ControllerAltButtons_MenuInit(void)
|
|||
Menu_AddItem(&s_controller_alt_buttons_menu, (void *)&s_controller_alt_buttons_actions[i]);
|
||||
}
|
||||
|
||||
Menu_SetStatusBar(&s_controller_alt_buttons_menu, "BTN_A assigns, BTN_Y clears, BTN_B exits");
|
||||
GamepadMenu_StatusPrompt(&s_controller_alt_buttons_menu);
|
||||
Menu_Center(&s_controller_alt_buttons_menu);
|
||||
}
|
||||
|
||||
|
@ -1639,17 +1668,17 @@ ControllerAltButtons_MenuKey(int key)
|
|||
if (menukeyitem_bind)
|
||||
{
|
||||
// Only controller buttons allowed, different from the alt buttons modifier
|
||||
if (key >= K_JOY_FIRST_REGULAR && key != K_JOY_BACK && (keybindings[key] == NULL || strcmp(keybindings[key], "+joyaltselector") != 0))
|
||||
if (key >= K_JOY_FIRST_BTN && (keybindings[key] == NULL || strcmp(keybindings[key], "+joyaltselector") != 0))
|
||||
{
|
||||
char cmd[1024];
|
||||
key = key + (K_JOY_FIRST_REGULAR_ALT - K_JOY_FIRST_REGULAR); // change input to its ALT mode
|
||||
key = key + (K_JOY_FIRST_BTN_ALT - K_JOY_FIRST_BTN); // change input to its ALT mode
|
||||
|
||||
Com_sprintf(cmd, sizeof(cmd), "bind \"%s\" \"%s\"\n",
|
||||
Key_KeynumToString(key), controller_alt_bindnames[item->generic.localdata[0]][0]);
|
||||
Cbuf_InsertText(cmd);
|
||||
}
|
||||
|
||||
Menu_SetStatusBar(&s_controller_alt_buttons_menu, "BTN_A assigns, BTN_Y clears, BTN_B exits");
|
||||
GamepadMenu_StatusPrompt(&s_controller_alt_buttons_menu);
|
||||
menukeyitem_bind = false;
|
||||
return menu_out_sound;
|
||||
}
|
||||
|
|
|
@ -100,7 +100,7 @@ RECENT REVISION HISTORY:
|
|||
Bug & warning fixes
|
||||
Marc LeBlanc David Woo Guillaume George Martins Mozeiko
|
||||
Christpher Lloyd Jerry Jansson Joseph Thomson Blazej Dariusz Roszkowski
|
||||
Phil Jordan Dave Moore Roy Eltham
|
||||
Phil Jordan Henner Zeller Dave Moore Roy Eltham
|
||||
Hayaki Saito Nathan Reed Won Chun
|
||||
Luke Graham Johan Duparc Nick Verigakis the Horde3D community
|
||||
Thomas Ruf Ronny Chevalier github:rlyeh
|
||||
|
@ -111,7 +111,7 @@ RECENT REVISION HISTORY:
|
|||
Cass Everitt Ryamond Barbiero github:grim210
|
||||
Paul Du Bois Engin Manap Aldo Culquicondor github:sammyhw
|
||||
Philipp Wiesemann Dale Weiler Oriol Ferrer Mesia github:phprus
|
||||
Josh Tobin Neil Bickford Matthew Gregan github:poppolopoppo
|
||||
Josh Tobin Nia Bickford Matthew Gregan github:poppolopoppo
|
||||
Julian Raschke Gregory Mullen Christian Floisand github:darealshinji
|
||||
Baldur Karlsson Kevin Schmidt JR Smith github:Michaelangel007
|
||||
Brad Weinberger Matvey Cherevko github:mosra
|
||||
|
@ -373,6 +373,15 @@ RECENT REVISION HISTORY:
|
|||
|
||||
#define STBI_VERSION 1
|
||||
|
||||
#if defined(__has_attribute)
|
||||
# if __has_attribute(fallthrough)
|
||||
# define STBI_FALLTHROUGH __attribute__((fallthrough));
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(STBI_FALLTHROUGH)
|
||||
# define STBI_FALLTHROUGH
|
||||
#endif
|
||||
|
||||
enum
|
||||
{
|
||||
STBI_default = 0, // only used for desired_channels
|
||||
|
@ -1209,7 +1218,7 @@ static stbi__uint16 *stbi__convert_8_to_16(stbi_uc *orig, int w, int h, int chan
|
|||
int img_len = w * h * channels;
|
||||
stbi__uint16 *enlarged;
|
||||
|
||||
enlarged = (stbi__uint16 *) stbi__malloc(img_len*2);
|
||||
enlarged = (stbi__uint16 *) stbi__malloc(((size_t)img_len)*2);
|
||||
if (enlarged == NULL) return (stbi__uint16 *) stbi__errpuc("outofmem", "Out of memory");
|
||||
|
||||
for (i = 0; i < img_len; ++i)
|
||||
|
@ -1269,7 +1278,12 @@ static unsigned char *stbi__load_and_postprocess_8bit(stbi__context *s, int *x,
|
|||
STBI_ASSERT(ri.bits_per_channel == 8 || ri.bits_per_channel == 16);
|
||||
|
||||
if (ri.bits_per_channel != 8) {
|
||||
result = stbi__convert_16_to_8((stbi__uint16 *) result, *x, *y, req_comp == 0 ? *comp : req_comp);
|
||||
stbi_uc *converted = stbi__convert_16_to_8((stbi__uint16 *) result, *x, *y, req_comp == 0 ? *comp : req_comp);
|
||||
if (converted == NULL) {
|
||||
STBI_FREE(result);
|
||||
return NULL;
|
||||
}
|
||||
result = converted;
|
||||
ri.bits_per_channel = 8;
|
||||
}
|
||||
|
||||
|
@ -1295,7 +1309,12 @@ static stbi__uint16 *stbi__load_and_postprocess_16bit(stbi__context *s, int *x,
|
|||
STBI_ASSERT(ri.bits_per_channel == 8 || ri.bits_per_channel == 16);
|
||||
|
||||
if (ri.bits_per_channel != 16) {
|
||||
result = stbi__convert_8_to_16((stbi_uc *) result, *x, *y, req_comp == 0 ? *comp : req_comp);
|
||||
stbi__uint16 * converted = stbi__convert_8_to_16((stbi_uc *) result, *x, *y, req_comp == 0 ? *comp : req_comp);
|
||||
if (converted == NULL) {
|
||||
STBI_FREE(result);
|
||||
return NULL;
|
||||
}
|
||||
result = converted;
|
||||
ri.bits_per_channel = 16;
|
||||
}
|
||||
|
||||
|
@ -1381,7 +1400,12 @@ STBIDEF stbi_uc *stbi_load_from_file(FILE *f, int *x, int *y, int *comp, int req
|
|||
result = stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp);
|
||||
if (result) {
|
||||
// need to 'unget' all the characters in the IO buffer
|
||||
fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR);
|
||||
if (fseek(f, -(int)(s.img_buffer_end - s.img_buffer), SEEK_CUR) != 0) {
|
||||
// fseek() failed; we can no longer maintain the file cursor position
|
||||
// guarantee of this function, so return null.
|
||||
STBI_FREE(result);
|
||||
return stbi__errpuc("bad file", "fseek() failed; seek position unreliable");
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -1394,7 +1418,12 @@ STBIDEF stbi__uint16 *stbi_load_from_file_16(FILE *f, int *x, int *y, int *comp,
|
|||
result = stbi__load_and_postprocess_16bit(&s,x,y,comp,req_comp);
|
||||
if (result) {
|
||||
// need to 'unget' all the characters in the IO buffer
|
||||
fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR);
|
||||
if (fseek(f, -(int)(s.img_buffer_end - s.img_buffer), SEEK_CUR) != 0) {
|
||||
// fseek() failed; we can no longer maintain the file cursor position
|
||||
// guarantee of this function, so return null.
|
||||
STBI_FREE(result);
|
||||
return (stbi__uint16 *) stbi__errpuc("bad file", "fseek() failed; seek position unreliable");
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -1448,8 +1477,9 @@ STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int *
|
|||
stbi__start_mem(&s,buffer,len);
|
||||
|
||||
result = (unsigned char*) stbi__load_gif_main(&s, delays, x, y, z, comp, req_comp);
|
||||
if (stbi__vertically_flip_on_load) {
|
||||
stbi__vertical_flip_slices( result, *x, *y, *z, *comp );
|
||||
if (stbi__vertically_flip_on_load && result) {
|
||||
int channels = req_comp ? req_comp : *comp;
|
||||
stbi__vertical_flip_slices( result, *x, *y, *z, channels );
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -1542,12 +1572,13 @@ STBIDEF int stbi_is_hdr (char const *filename)
|
|||
STBIDEF int stbi_is_hdr_from_file(FILE *f)
|
||||
{
|
||||
#ifndef STBI_NO_HDR
|
||||
long pos = ftell(f);
|
||||
int res;
|
||||
long pos = ftell(f);
|
||||
if (pos < 0) return stbi__err("bad file", "ftell() failed");
|
||||
stbi__context s;
|
||||
stbi__start_file(&s,f);
|
||||
res = stbi__hdr_test(&s);
|
||||
fseek(f, pos, SEEK_SET);
|
||||
if (fseek(f, pos, SEEK_SET) != 0) return stbi__err("bad file", "fseek() failed");
|
||||
return res;
|
||||
#else
|
||||
STBI_NOTUSED(f);
|
||||
|
@ -1757,6 +1788,7 @@ static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int r
|
|||
int i,j;
|
||||
unsigned char *good;
|
||||
|
||||
if (data == NULL) return data;
|
||||
if (req_comp == img_n) return data;
|
||||
STBI_ASSERT(req_comp >= 1 && req_comp <= 4);
|
||||
|
||||
|
@ -1797,7 +1829,7 @@ static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int r
|
|||
}
|
||||
#endif
|
||||
|
||||
#if defined(STBI_NO_PNG) && defined(STBI_NO_PSD)
|
||||
#if defined(STBI_NO_PNG) && defined(STBI_NO_PSD) && defined(STBI_NO_PNM)
|
||||
// nothing
|
||||
#else
|
||||
static stbi__uint16 stbi__compute_y_16(int r, int g, int b)
|
||||
|
@ -1806,7 +1838,7 @@ static stbi__uint16 stbi__compute_y_16(int r, int g, int b)
|
|||
}
|
||||
#endif
|
||||
|
||||
#if defined(STBI_NO_PNG) && defined(STBI_NO_PSD)
|
||||
#if defined(STBI_NO_PNG) && defined(STBI_NO_PSD) && defined(STBI_NO_PNM)
|
||||
// nothing
|
||||
#else
|
||||
static stbi__uint16 *stbi__convert_format16(stbi__uint16 *data, int img_n, int req_comp, unsigned int x, unsigned int y)
|
||||
|
@ -2223,8 +2255,8 @@ static int stbi__jpeg_decode_block(stbi__jpeg *j, short data[64], stbi__huffman
|
|||
if (!stbi__addints_valid(j->img_comp[b].dc_pred, diff)) return stbi__err("bad delta","Corrupt JPEG");
|
||||
dc = j->img_comp[b].dc_pred + diff;
|
||||
j->img_comp[b].dc_pred = dc;
|
||||
if (!stbi__mul2shorts_valid(dc, dequant[0])) return stbi__err("can't merge dc and ac", "Corrupt JPEG");
|
||||
data[0] = (short) (dc * dequant[0]);
|
||||
if ((dc > SHRT_MAX) || (dequant[0] > SHRT_MAX) || !stbi__mul2shorts_valid((short) dc, (short) dequant[0])) return stbi__err("can't merge dc and ac", "Corrupt JPEG");
|
||||
data[0] = (short) ((size_t)dc * dequant[0]);
|
||||
|
||||
// decode AC components, see JPEG spec
|
||||
k = 1;
|
||||
|
@ -2280,7 +2312,7 @@ static int stbi__jpeg_decode_block_prog_dc(stbi__jpeg *j, short data[64], stbi__
|
|||
if (!stbi__addints_valid(j->img_comp[b].dc_pred, diff)) return stbi__err("bad delta", "Corrupt JPEG");
|
||||
dc = j->img_comp[b].dc_pred + diff;
|
||||
j->img_comp[b].dc_pred = dc;
|
||||
if (!stbi__mul2shorts_valid(dc, 1 << j->succ_low)) return stbi__err("can't merge dc and ac", "Corrupt JPEG");
|
||||
if ((dc > SHRT_MAX) || !stbi__mul2shorts_valid((short) dc, 1 << j->succ_low)) return stbi__err("can't merge dc and ac", "Corrupt JPEG");
|
||||
data[0] = (short) (dc * (1 << j->succ_low));
|
||||
} else {
|
||||
// refinement scan for DC coefficient
|
||||
|
@ -5556,7 +5588,7 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req
|
|||
|
||||
if (info.hsz == 12) {
|
||||
if (info.bpp < 24)
|
||||
psize = (info.offset - info.extra_read - 24) / 3;
|
||||
psize = (info.offset - info.extra_read - info.hsz) / 3;
|
||||
} else {
|
||||
if (info.bpp < 16)
|
||||
psize = (info.offset - info.extra_read - info.hsz) >> 2;
|
||||
|
@ -5743,7 +5775,7 @@ static int stbi__tga_get_comp(int bits_per_pixel, int is_grey, int* is_rgb16)
|
|||
switch(bits_per_pixel) {
|
||||
case 8: return STBI_grey;
|
||||
case 16: if(is_grey) return STBI_grey_alpha;
|
||||
// fallthrough
|
||||
STBI_FALLTHROUGH;
|
||||
case 15: if(is_rgb16) *is_rgb16 = 1;
|
||||
return STBI_rgb;
|
||||
case 24: // fallthrough
|
||||
|
@ -5934,7 +5966,10 @@ static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req
|
|||
for (i=0; i < tga_height; ++i) {
|
||||
int row = tga_inverted ? tga_height -i - 1 : i;
|
||||
stbi_uc *tga_row = tga_data + row*tga_width*tga_comp;
|
||||
stbi__getn(s, tga_row, tga_width * tga_comp);
|
||||
if(!stbi__getn(s, tga_row, tga_width * tga_comp)) {
|
||||
STBI_FREE(tga_data);
|
||||
return stbi__errpuc("bad palette", "Corrupt TGA");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// do I need to load a palette?
|
||||
|
@ -6528,7 +6563,7 @@ static void *stbi__pic_load(stbi__context *s,int *px,int *py,int *comp,int req_c
|
|||
|
||||
if (!stbi__pic_load_core(s,x,y,comp, result)) {
|
||||
STBI_FREE(result);
|
||||
result=0;
|
||||
return 0;
|
||||
}
|
||||
*px = x;
|
||||
*py = y;
|
||||
|
@ -6991,9 +7026,20 @@ static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y,
|
|||
stride = g.w * g.h * 4;
|
||||
|
||||
if (out) {
|
||||
if (stride == 0) {
|
||||
void *ret = stbi__load_gif_main_outofmem(&g, out, delays);
|
||||
return ret;
|
||||
}
|
||||
if (!stbi__mul2sizes_valid(layers, stride)) {
|
||||
void *ret = stbi__load_gif_main_outofmem(&g, out, delays);
|
||||
return ret;
|
||||
}
|
||||
void *tmp = (stbi_uc*) STBI_REALLOC_SIZED( out, out_size, layers * stride );
|
||||
if (!tmp)
|
||||
return stbi__load_gif_main_outofmem(&g, out, delays);
|
||||
if (!tmp) {
|
||||
void *ret = stbi__load_gif_main_outofmem(&g, out, delays);
|
||||
if (delays && *delays) *delays = 0;
|
||||
return ret;
|
||||
}
|
||||
else {
|
||||
out = (stbi_uc*) tmp;
|
||||
out_size = layers * stride;
|
||||
|
@ -7007,9 +7053,16 @@ static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y,
|
|||
delays_size = layers * sizeof(int);
|
||||
}
|
||||
} else {
|
||||
if (!stbi__mul2sizes_valid(layers, stride)) {
|
||||
void *ret = stbi__load_gif_main_outofmem(&g, out, delays);
|
||||
return ret;
|
||||
}
|
||||
out = (stbi_uc*)stbi__malloc( layers * stride );
|
||||
if (!out)
|
||||
return stbi__load_gif_main_outofmem(&g, out, delays);
|
||||
if (!out) {
|
||||
void *ret = stbi__load_gif_main_outofmem(&g, out, delays);
|
||||
if (delays && *delays) *delays = 0;
|
||||
return ret;
|
||||
}
|
||||
out_size = layers * stride;
|
||||
if (delays) {
|
||||
*delays = (int*) stbi__malloc( layers * sizeof(int) );
|
||||
|
@ -7020,7 +7073,7 @@ static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y,
|
|||
}
|
||||
memcpy( out + ((layers - 1) * stride), u, stride );
|
||||
if (layers >= 2) {
|
||||
two_back = out - 2 * stride;
|
||||
two_back = out + (layers - 2) * stride;
|
||||
}
|
||||
|
||||
if (delays) {
|
||||
|
@ -7145,10 +7198,10 @@ static void stbi__hdr_convert(float *output, stbi_uc *input, int req_comp)
|
|||
if (req_comp == 4) output[3] = 1;
|
||||
} else {
|
||||
switch (req_comp) {
|
||||
case 4: output[3] = 1; /* fallthrough */
|
||||
case 4: output[3] = 1; STBI_FALLTHROUGH;
|
||||
case 3: output[0] = output[1] = output[2] = 0;
|
||||
break;
|
||||
case 2: output[1] = 1; /* fallthrough */
|
||||
case 2: output[1] = 1; STBI_FALLTHROUGH;
|
||||
case 1: output[0] = 0;
|
||||
break;
|
||||
}
|
||||
|
@ -7219,7 +7272,10 @@ static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int re
|
|||
for (i=0; i < width; ++i) {
|
||||
stbi_uc rgbe[4];
|
||||
main_decode_loop:
|
||||
stbi__getn(s, rgbe, 4);
|
||||
if (!stbi__getn(s, rgbe, 4)) {
|
||||
STBI_FREE(hdr_data);
|
||||
return stbi__errpf("invalid decoded scanline length", "corrupt HDR");
|
||||
}
|
||||
stbi__hdr_convert(hdr_data + j * width * req_comp + i * req_comp, rgbe, req_comp);
|
||||
}
|
||||
}
|
||||
|
@ -7703,9 +7759,10 @@ STBIDEF int stbi_info_from_file(FILE *f, int *x, int *y, int *comp)
|
|||
int r;
|
||||
stbi__context s;
|
||||
long pos = ftell(f);
|
||||
if (pos < 0) return stbi__err("bad file", "ftell() failed");
|
||||
stbi__start_file(&s, f);
|
||||
r = stbi__info_main(&s,x,y,comp);
|
||||
fseek(f,pos,SEEK_SET);
|
||||
if (fseek(f, pos, SEEK_SET) != 0) return stbi__err("bad file", "fseek() failed");
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -7724,9 +7781,10 @@ STBIDEF int stbi_is_16_bit_from_file(FILE *f)
|
|||
int r;
|
||||
stbi__context s;
|
||||
long pos = ftell(f);
|
||||
if (pos < 0) return stbi__err("bad file", "ftell() failed");
|
||||
stbi__start_file(&s, f);
|
||||
r = stbi__is_16_main(&s);
|
||||
fseek(f,pos,SEEK_SET);
|
||||
if (fseek(f, pos, SEEK_SET) != 0) return stbi__err("bad file", "fseek() failed");
|
||||
return r;
|
||||
}
|
||||
#endif // !STBI_NO_STDIO
|
||||
|
|
|
@ -270,7 +270,7 @@ int RI_InitContext(void* win)
|
|||
#ifdef YQ2_GL1_GLES
|
||||
|
||||
// Load GL pointers through GLAD and check context.
|
||||
if( !gladLoadGLES1Loader(SDL_GL_GetProcAddress))
|
||||
if( !gladLoadGLES1Loader( (void * (*)(const char *)) SDL_GL_GetProcAddress ) )
|
||||
{
|
||||
R_Printf(PRINT_ALL, "RI_InitContext(): ERROR: loading OpenGL ES function pointers failed!\n");
|
||||
return false;
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
//
|
||||
// Feature contributors:
|
||||
// Dougall Johnson (sample-exact seeking)
|
||||
// Vitaly Novichkov (sample-accurate tell)
|
||||
//
|
||||
// Bugfix/warning contributors:
|
||||
// Terje Mathisen Niklas Frykholm Andy Hill
|
||||
|
@ -34,6 +35,7 @@
|
|||
// github:audinowho Dougall Johnson David Reid
|
||||
// github:Clownacy Pedro J. Estebanez Remi Verschelde
|
||||
// AnthoFoxo github:morlat Gabriel Ravier
|
||||
// Seb de Graffenried Alice Rowan
|
||||
//
|
||||
// Partial history:
|
||||
// 1.22 - 2021-07-11 - various small fixes
|
||||
|
@ -648,6 +650,17 @@ typedef signed short int16;
|
|||
typedef unsigned int uint32;
|
||||
typedef signed int int32;
|
||||
|
||||
#ifdef __has_feature
|
||||
#if __has_feature(undefined_behavior_sanitizer)
|
||||
#define HAS_UBSAN
|
||||
#endif
|
||||
#endif
|
||||
#ifdef HAS_UBSAN
|
||||
#define STB_NO_SANITIZE(s) __attribute__((no_sanitize(s)))
|
||||
#else
|
||||
#define STB_NO_SANITIZE(s)
|
||||
#endif
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
@ -752,11 +765,11 @@ typedef struct
|
|||
|
||||
typedef struct
|
||||
{
|
||||
uint16 coupling_steps;
|
||||
MappingChannel *chan;
|
||||
uint16 coupling_steps;
|
||||
uint8 submaps;
|
||||
uint8 submap_floor[15]; // varies
|
||||
uint8 submap_residue[15]; // varies
|
||||
uint8 submap_floor[16]; // varies
|
||||
uint8 submap_residue[16]; // varies
|
||||
} Mapping;
|
||||
|
||||
typedef struct
|
||||
|
@ -898,6 +911,12 @@ struct stb_vorbis
|
|||
// sample-access
|
||||
int channel_buffer_start;
|
||||
int channel_buffer_end;
|
||||
|
||||
// temporary buffers
|
||||
void *temp_lengths;
|
||||
void *temp_codewords;
|
||||
void *temp_values;
|
||||
void *temp_mults;
|
||||
};
|
||||
|
||||
#if defined(STB_VORBIS_NO_PUSHDATA_API)
|
||||
|
@ -949,9 +968,12 @@ static void *make_block_array(void *mem, int count, int size)
|
|||
|
||||
static void *setup_malloc(vorb *f, int sz)
|
||||
{
|
||||
if (INT_MAX - 7 < sz) return NULL;
|
||||
if (sz < 0) return NULL;
|
||||
sz = (sz+7) & ~7; // round up to nearest 8 for alignment of future allocs.
|
||||
f->setup_memory_required += sz;
|
||||
if (f->alloc.alloc_buffer) {
|
||||
if (sz == 0) return NULL;
|
||||
void *p = (char *) f->alloc.alloc_buffer + f->setup_offset;
|
||||
if (f->setup_offset + sz > f->temp_offset) return NULL;
|
||||
f->setup_offset += sz;
|
||||
|
@ -977,8 +999,10 @@ static void *setup_temp_malloc(vorb *f, int sz)
|
|||
return malloc(sz);
|
||||
}
|
||||
|
||||
static void setup_temp_free(vorb *f, void *p, int sz)
|
||||
static void setup_temp_free(vorb *f, void **_p, int sz)
|
||||
{
|
||||
void *p = *_p;
|
||||
*_p = NULL;
|
||||
if (f->alloc.alloc_buffer) {
|
||||
f->temp_offset += (sz+7)&~7;
|
||||
return;
|
||||
|
@ -1238,6 +1262,10 @@ static int vorbis_validate(uint8 *data)
|
|||
|
||||
// called from setup only, once per code book
|
||||
// (formula implied by specification)
|
||||
//
|
||||
// suppress an UBSan error caused by invalid input data.
|
||||
// upstream: https://github.com/nothings/stb/issues/1168.
|
||||
STB_NO_SANITIZE("float-cast-overflow")
|
||||
static int lookup1_values(int entries, int dim)
|
||||
{
|
||||
int r = (int) floor(exp((float) log((float) entries) / dim));
|
||||
|
@ -1583,8 +1611,8 @@ static int get32_packet(vorb *f)
|
|||
{
|
||||
uint32 x;
|
||||
x = get8_packet(f);
|
||||
x += get8_packet(f) << 8;
|
||||
x += get8_packet(f) << 16;
|
||||
x += (uint32) get8_packet(f) << 8;
|
||||
x += (uint32) get8_packet(f) << 16;
|
||||
x += (uint32) get8_packet(f) << 24;
|
||||
return x;
|
||||
}
|
||||
|
@ -1696,7 +1724,7 @@ static int codebook_decode_scalar_raw(vorb *f, Codebook *c)
|
|||
assert(!c->sparse);
|
||||
for (i=0; i < c->entries; ++i) {
|
||||
if (c->codeword_lengths[i] == NO_CODE) continue;
|
||||
if (c->codewords[i] == (f->acc & ((1 << c->codeword_lengths[i])-1))) {
|
||||
if (c->codewords[i] == (f->acc & ((1U << c->codeword_lengths[i])-1))) {
|
||||
if (f->valid_bits >= c->codeword_lengths[i]) {
|
||||
f->acc >>= c->codeword_lengths[i];
|
||||
f->valid_bits -= c->codeword_lengths[i];
|
||||
|
@ -1753,7 +1781,7 @@ static int codebook_decode_scalar(vorb *f, Codebook *c)
|
|||
|
||||
#define DECODE(var,f,c) \
|
||||
DECODE_RAW(var,f,c) \
|
||||
if (c->sparse) var = c->sorted_values[var];
|
||||
if (c->sparse && var >= 0) var = c->sorted_values[var];
|
||||
|
||||
#ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK
|
||||
#define DECODE_VQ(var,f,c) DECODE_RAW(var,f,c)
|
||||
|
@ -1888,7 +1916,7 @@ static int codebook_decode_deinterleave_repeat(vorb *f, Codebook *c, float **out
|
|||
// buffer (len*ch), our current offset within it (p_inter*ch)+(c_inter),
|
||||
// and the length we'll be using (effective)
|
||||
if (c_inter + p_inter*ch + effective > len * ch) {
|
||||
effective = len*ch - (p_inter*ch - c_inter);
|
||||
effective = len*ch - (p_inter*ch + c_inter);
|
||||
}
|
||||
|
||||
#ifdef STB_VORBIS_DIVIDES_IN_CODEBOOK
|
||||
|
@ -2067,7 +2095,7 @@ static __forceinline void draw_line(float *output, int x0, int y0, int x1, int y
|
|||
ady -= abs(base) * adx;
|
||||
if (x1 > n) x1 = n;
|
||||
if (x < x1) {
|
||||
LINE_OP(output[x], inverse_db_table[y&255]);
|
||||
LINE_OP(output[x], inverse_db_table[(uint32)y&255]);
|
||||
for (++x; x < x1; ++x) {
|
||||
err += ady;
|
||||
if (err >= adx) {
|
||||
|
@ -2075,7 +2103,7 @@ static __forceinline void draw_line(float *output, int x0, int y0, int x1, int y
|
|||
y += sy;
|
||||
} else
|
||||
y += base;
|
||||
LINE_OP(output[x], inverse_db_table[y&255]);
|
||||
LINE_OP(output[x], inverse_db_table[(uint32)y&255]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3058,7 +3086,7 @@ void inverse_mdct_naive(float *buffer, int n)
|
|||
|
||||
static float *get_window(vorb *f, int len)
|
||||
{
|
||||
len <<= 1;
|
||||
len = (unsigned int)len << 1;
|
||||
if (len == f->blocksize_0) return f->window[0];
|
||||
if (len == f->blocksize_1) return f->window[1];
|
||||
return NULL;
|
||||
|
@ -3650,7 +3678,7 @@ static int start_decoder(vorb *f)
|
|||
if (!vorbis_validate(header)) return error(f, VORBIS_invalid_setup);
|
||||
//file vendor
|
||||
len = get32_packet(f);
|
||||
f->vendor = (char*)setup_malloc(f, sizeof(char) * (len+1));
|
||||
f->vendor = (INT_MAX == len) ? NULL : (char*)setup_malloc(f, sizeof(char) * (len+1));
|
||||
if (f->vendor == NULL) return error(f, VORBIS_outofmem);
|
||||
for(i=0; i < len; ++i) {
|
||||
f->vendor[i] = get8_packet(f);
|
||||
|
@ -3661,14 +3689,25 @@ static int start_decoder(vorb *f)
|
|||
f->comment_list = NULL;
|
||||
if (f->comment_list_length > 0)
|
||||
{
|
||||
if (INT_MAX / sizeof(char*) < f->comment_list_length) {
|
||||
f->comment_list_length = 0;
|
||||
return error(f, VORBIS_outofmem);
|
||||
}
|
||||
f->comment_list = (char**) setup_malloc(f, sizeof(char*) * (f->comment_list_length));
|
||||
if (f->comment_list == NULL) return error(f, VORBIS_outofmem);
|
||||
if (f->comment_list == NULL)
|
||||
{
|
||||
f->comment_list_length = 0;
|
||||
return error(f, VORBIS_outofmem);
|
||||
}
|
||||
memset(f->comment_list, 0, sizeof(char*) * f->comment_list_length);
|
||||
}
|
||||
|
||||
for(i=0; i < f->comment_list_length; ++i) {
|
||||
len = get32_packet(f);
|
||||
f->comment_list[i] = (char*)setup_malloc(f, sizeof(char) * (len+1));
|
||||
if (f->comment_list[i] == NULL) return error(f, VORBIS_outofmem);
|
||||
f->comment_list[i] = (INT_MAX == len) ? NULL : (char*)setup_malloc(f, sizeof(char) * (len+1));
|
||||
if (f->comment_list[i] == NULL) {
|
||||
return error(f, VORBIS_outofmem);
|
||||
}
|
||||
|
||||
for(j=0; j < len; ++j) {
|
||||
f->comment_list[i][j] = get8_packet(f);
|
||||
|
@ -3713,6 +3752,7 @@ static int start_decoder(vorb *f)
|
|||
// codebooks
|
||||
|
||||
f->codebook_count = get_bits(f,8) + 1;
|
||||
if (f->valid_bits < 0) return error(f, VORBIS_unexpected_eof);
|
||||
f->codebooks = (Codebook *) setup_malloc(f, sizeof(*f->codebooks) * f->codebook_count);
|
||||
if (f->codebooks == NULL) return error(f, VORBIS_outofmem);
|
||||
memset(f->codebooks, 0, sizeof(*f->codebooks) * f->codebook_count);
|
||||
|
@ -3735,10 +3775,12 @@ static int start_decoder(vorb *f)
|
|||
c->sparse = ordered ? 0 : get_bits(f,1);
|
||||
|
||||
if (c->dimensions == 0 && c->entries != 0) return error(f, VORBIS_invalid_setup);
|
||||
if (f->valid_bits < 0) return error(f, VORBIS_unexpected_eof);
|
||||
|
||||
if (c->sparse)
|
||||
if (c->sparse) {
|
||||
lengths = (uint8 *) setup_temp_malloc(f, c->entries);
|
||||
else
|
||||
f->temp_lengths = lengths;
|
||||
} else
|
||||
lengths = c->codeword_lengths = (uint8 *) setup_malloc(f, c->entries);
|
||||
|
||||
if (!lengths) return error(f, VORBIS_outofmem);
|
||||
|
@ -3749,8 +3791,9 @@ static int start_decoder(vorb *f)
|
|||
while (current_entry < c->entries) {
|
||||
int limit = c->entries - current_entry;
|
||||
int n = get_bits(f, ilog(limit));
|
||||
if (f->valid_bits < 0) return error(f, VORBIS_unexpected_eof);
|
||||
if (current_length >= 32) return error(f, VORBIS_invalid_setup);
|
||||
if (current_entry + n > (int) c->entries) { return error(f, VORBIS_invalid_setup); }
|
||||
if (current_entry + n > (int) c->entries) return error(f, VORBIS_invalid_setup);
|
||||
memset(lengths + current_entry, current_length, n);
|
||||
current_entry += n;
|
||||
++current_length;
|
||||
|
@ -3758,11 +3801,14 @@ static int start_decoder(vorb *f)
|
|||
} else {
|
||||
for (j=0; j < c->entries; ++j) {
|
||||
int present = c->sparse ? get_bits(f,1) : 1;
|
||||
if (f->valid_bits < 0) return error(f, VORBIS_unexpected_eof);
|
||||
if (present) {
|
||||
lengths[j] = get_bits(f, 5) + 1;
|
||||
++total;
|
||||
if (lengths[j] == 32)
|
||||
return error(f, VORBIS_invalid_setup);
|
||||
if (lengths[j] == 32) {
|
||||
if (c->sparse) setup_temp_free(f, &f->temp_lengths, c->entries);
|
||||
return error(f, VORBIS_invalid_setup);
|
||||
}
|
||||
} else {
|
||||
lengths[j] = NO_CODE;
|
||||
}
|
||||
|
@ -3775,9 +3821,12 @@ static int start_decoder(vorb *f)
|
|||
f->setup_temp_memory_required = c->entries;
|
||||
|
||||
c->codeword_lengths = (uint8 *) setup_malloc(f, c->entries);
|
||||
if (c->codeword_lengths == NULL) return error(f, VORBIS_outofmem);
|
||||
if (c->codeword_lengths == NULL) {
|
||||
setup_temp_free(f, &f->temp_lengths, c->entries);
|
||||
return error(f, VORBIS_outofmem);
|
||||
}
|
||||
memcpy(c->codeword_lengths, lengths, c->entries);
|
||||
setup_temp_free(f, lengths, c->entries); // note this is only safe if there have been no intervening temp mallocs!
|
||||
setup_temp_free(f, &f->temp_lengths, c->entries); // note this is only safe if there have been no intervening temp mallocs!
|
||||
lengths = c->codeword_lengths;
|
||||
c->sparse = 0;
|
||||
}
|
||||
|
@ -3805,11 +3854,22 @@ static int start_decoder(vorb *f)
|
|||
unsigned int size;
|
||||
if (c->sorted_entries) {
|
||||
c->codeword_lengths = (uint8 *) setup_malloc(f, c->sorted_entries);
|
||||
if (!c->codeword_lengths) return error(f, VORBIS_outofmem);
|
||||
if (!c->codeword_lengths) {
|
||||
setup_temp_free(f, &f->temp_lengths, c->entries);
|
||||
return error(f, VORBIS_outofmem);
|
||||
}
|
||||
c->codewords = (uint32 *) setup_temp_malloc(f, sizeof(*c->codewords) * c->sorted_entries);
|
||||
if (!c->codewords) return error(f, VORBIS_outofmem);
|
||||
f->temp_codewords = c->codewords;
|
||||
if (!c->codewords) {
|
||||
setup_temp_free(f, &f->temp_lengths, c->entries);
|
||||
return error(f, VORBIS_outofmem);
|
||||
}
|
||||
values = (uint32 *) setup_temp_malloc(f, sizeof(*values) * c->sorted_entries);
|
||||
if (!values) return error(f, VORBIS_outofmem);
|
||||
f->temp_values = values;
|
||||
if (!values) {
|
||||
setup_temp_free(f, &f->temp_lengths, c->entries);
|
||||
return error(f, VORBIS_outofmem);
|
||||
}
|
||||
}
|
||||
size = c->entries + (sizeof(*c->codewords) + sizeof(*values)) * c->sorted_entries;
|
||||
if (size > f->setup_temp_memory_required)
|
||||
|
@ -3817,27 +3877,32 @@ static int start_decoder(vorb *f)
|
|||
}
|
||||
|
||||
if (!compute_codewords(c, lengths, c->entries, values)) {
|
||||
if (c->sparse) setup_temp_free(f, values, 0);
|
||||
return error(f, VORBIS_invalid_setup);
|
||||
}
|
||||
|
||||
if (c->sorted_entries) {
|
||||
// allocate an extra slot for sentinels
|
||||
c->sorted_codewords = (uint32 *) setup_malloc(f, sizeof(*c->sorted_codewords) * (c->sorted_entries+1));
|
||||
if (c->sorted_codewords == NULL) return error(f, VORBIS_outofmem);
|
||||
if (c->sorted_codewords == NULL) {
|
||||
if (c->sparse) setup_temp_free(f, &f->temp_lengths, c->entries);
|
||||
return error(f, VORBIS_outofmem);
|
||||
}
|
||||
// allocate an extra slot at the front so that c->sorted_values[-1] is defined
|
||||
// so that we can catch that case without an extra if
|
||||
c->sorted_values = ( int *) setup_malloc(f, sizeof(*c->sorted_values ) * (c->sorted_entries+1));
|
||||
if (c->sorted_values == NULL) return error(f, VORBIS_outofmem);
|
||||
if (c->sorted_values == NULL) {
|
||||
if (c->sparse) setup_temp_free(f, &f->temp_lengths, c->entries);
|
||||
return error(f, VORBIS_outofmem);
|
||||
}
|
||||
++c->sorted_values;
|
||||
c->sorted_values[-1] = -1;
|
||||
compute_sorted_huffman(c, lengths, values);
|
||||
}
|
||||
|
||||
if (c->sparse) {
|
||||
setup_temp_free(f, values, sizeof(*values)*c->sorted_entries);
|
||||
setup_temp_free(f, c->codewords, sizeof(*c->codewords)*c->sorted_entries);
|
||||
setup_temp_free(f, lengths, c->entries);
|
||||
setup_temp_free(f, &f->temp_values, sizeof(*values)*c->sorted_entries);
|
||||
setup_temp_free(f, &f->temp_codewords, sizeof(*c->codewords)*c->sorted_entries);
|
||||
setup_temp_free(f, &f->temp_lengths, c->entries);
|
||||
c->codewords = NULL;
|
||||
}
|
||||
|
||||
|
@ -3857,14 +3922,22 @@ static int start_decoder(vorb *f)
|
|||
if (values < 0) return error(f, VORBIS_invalid_setup);
|
||||
c->lookup_values = (uint32) values;
|
||||
} else {
|
||||
/* If this overflows, the file's not valid.
|
||||
* See https://github.com/nothings/stb/issues/1168. */
|
||||
if (c->entries != 0 && c->dimensions > INT_MAX / c->entries) return error(f, VORBIS_invalid_setup);
|
||||
c->lookup_values = c->entries * c->dimensions;
|
||||
}
|
||||
if (c->lookup_values == 0) return error(f, VORBIS_invalid_setup);
|
||||
// Before we allocate the lookup table, verify that it can be read
|
||||
// from the file. Otherwise, c->lookup_values can be arbitrarily
|
||||
// large, and we run out of memory.
|
||||
if (c->lookup_values > (8 * f->stream_len) / c->value_bits) return error(f, VORBIS_invalid_setup);
|
||||
mults = (uint16 *) setup_temp_malloc(f, sizeof(mults[0]) * c->lookup_values);
|
||||
f->temp_mults = mults;
|
||||
if (mults == NULL) return error(f, VORBIS_outofmem);
|
||||
for (j=0; j < (int) c->lookup_values; ++j) {
|
||||
int q = get_bits(f, c->value_bits);
|
||||
if (q == EOP) { setup_temp_free(f,mults,sizeof(mults[0])*c->lookup_values); return error(f, VORBIS_invalid_setup); }
|
||||
if (f->valid_bits < 0) return error(f, VORBIS_invalid_setup);
|
||||
mults[j] = q;
|
||||
}
|
||||
|
||||
|
@ -3878,7 +3951,7 @@ static int start_decoder(vorb *f)
|
|||
c->multiplicands = (codetype *) setup_malloc(f, sizeof(c->multiplicands[0]) * c->sorted_entries * c->dimensions);
|
||||
} else
|
||||
c->multiplicands = (codetype *) setup_malloc(f, sizeof(c->multiplicands[0]) * c->entries * c->dimensions);
|
||||
if (c->multiplicands == NULL) { setup_temp_free(f,mults,sizeof(mults[0])*c->lookup_values); return error(f, VORBIS_outofmem); }
|
||||
if (c->multiplicands == NULL) return error(f, VORBIS_outofmem);
|
||||
len = sparse ? c->sorted_entries : c->entries;
|
||||
for (j=0; j < len; ++j) {
|
||||
unsigned int z = sparse ? c->sorted_values[j] : j;
|
||||
|
@ -3891,7 +3964,6 @@ static int start_decoder(vorb *f)
|
|||
last = val;
|
||||
if (k+1 < c->dimensions) {
|
||||
if (div > UINT_MAX / (unsigned int) c->lookup_values) {
|
||||
setup_temp_free(f, mults,sizeof(mults[0])*c->lookup_values);
|
||||
return error(f, VORBIS_invalid_setup);
|
||||
}
|
||||
div *= c->lookup_values;
|
||||
|
@ -3906,7 +3978,7 @@ static int start_decoder(vorb *f)
|
|||
float last=0;
|
||||
CHECK(f);
|
||||
c->multiplicands = (codetype *) setup_malloc(f, sizeof(c->multiplicands[0]) * c->lookup_values);
|
||||
if (c->multiplicands == NULL) { setup_temp_free(f, mults,sizeof(mults[0])*c->lookup_values); return error(f, VORBIS_outofmem); }
|
||||
if (c->multiplicands == NULL) return error(f, VORBIS_outofmem);
|
||||
for (j=0; j < (int) c->lookup_values; ++j) {
|
||||
float val = mults[j] * c->delta_value + c->minimum_value + last;
|
||||
c->multiplicands[j] = val;
|
||||
|
@ -3917,7 +3989,7 @@ static int start_decoder(vorb *f)
|
|||
#ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK
|
||||
skip:;
|
||||
#endif
|
||||
setup_temp_free(f, mults, sizeof(mults[0])*c->lookup_values);
|
||||
setup_temp_free(f, &f->temp_mults, sizeof(mults[0])*c->lookup_values);
|
||||
|
||||
CHECK(f);
|
||||
}
|
||||
|
@ -3934,6 +4006,7 @@ static int start_decoder(vorb *f)
|
|||
|
||||
// Floors
|
||||
f->floor_count = get_bits(f, 6)+1;
|
||||
if (f->valid_bits < 0) return error(f, VORBIS_unexpected_eof);
|
||||
f->floor_config = (Floor *) setup_malloc(f, f->floor_count * sizeof(*f->floor_config));
|
||||
if (f->floor_config == NULL) return error(f, VORBIS_outofmem);
|
||||
for (i=0; i < f->floor_count; ++i) {
|
||||
|
@ -3963,6 +4036,7 @@ static int start_decoder(vorb *f)
|
|||
for (j=0; j <= max_class; ++j) {
|
||||
g->class_dimensions[j] = get_bits(f, 3)+1;
|
||||
g->class_subclasses[j] = get_bits(f, 2);
|
||||
if (f->valid_bits < 0) return error(f, VORBIS_unexpected_eof);
|
||||
if (g->class_subclasses[j]) {
|
||||
g->class_masterbooks[j] = get_bits(f, 8);
|
||||
if (g->class_masterbooks[j] >= f->codebook_count) return error(f, VORBIS_invalid_setup);
|
||||
|
@ -4010,6 +4084,7 @@ static int start_decoder(vorb *f)
|
|||
|
||||
// Residue
|
||||
f->residue_count = get_bits(f, 6)+1;
|
||||
if (f->valid_bits < 0) return error(f, VORBIS_unexpected_eof);
|
||||
f->residue_config = (Residue *) setup_malloc(f, f->residue_count * sizeof(f->residue_config[0]));
|
||||
if (f->residue_config == NULL) return error(f, VORBIS_outofmem);
|
||||
memset(f->residue_config, 0, f->residue_count * sizeof(f->residue_config[0]));
|
||||
|
@ -4024,6 +4099,7 @@ static int start_decoder(vorb *f)
|
|||
r->part_size = get_bits(f,24)+1;
|
||||
r->classifications = get_bits(f,6)+1;
|
||||
r->classbook = get_bits(f,8);
|
||||
if (f->valid_bits < 0) return error(f, VORBIS_unexpected_eof);
|
||||
if (r->classbook >= f->codebook_count) return error(f, VORBIS_invalid_setup);
|
||||
for (j=0; j < r->classifications; ++j) {
|
||||
uint8 high_bits=0;
|
||||
|
@ -4032,12 +4108,14 @@ static int start_decoder(vorb *f)
|
|||
high_bits = get_bits(f,5);
|
||||
residue_cascade[j] = high_bits*8 + low_bits;
|
||||
}
|
||||
if (f->valid_bits < 0) return error(f, VORBIS_unexpected_eof);
|
||||
r->residue_books = (short (*)[8]) setup_malloc(f, sizeof(r->residue_books[0]) * r->classifications);
|
||||
if (r->residue_books == NULL) return error(f, VORBIS_outofmem);
|
||||
for (j=0; j < r->classifications; ++j) {
|
||||
for (k=0; k < 8; ++k) {
|
||||
if (residue_cascade[j] & (1 << k)) {
|
||||
r->residue_books[j][k] = get_bits(f, 8);
|
||||
if (f->valid_bits < 0) return error(f, VORBIS_unexpected_eof);
|
||||
if (r->residue_books[j][k] >= f->codebook_count) return error(f, VORBIS_invalid_setup);
|
||||
} else {
|
||||
r->residue_books[j][k] = -1;
|
||||
|
@ -4062,6 +4140,7 @@ static int start_decoder(vorb *f)
|
|||
}
|
||||
|
||||
f->mapping_count = get_bits(f,6)+1;
|
||||
if (f->valid_bits < 0) return error(f, VORBIS_unexpected_eof);
|
||||
f->mapping = (Mapping *) setup_malloc(f, f->mapping_count * sizeof(*f->mapping));
|
||||
if (f->mapping == NULL) return error(f, VORBIS_outofmem);
|
||||
memset(f->mapping, 0, f->mapping_count * sizeof(*f->mapping));
|
||||
|
@ -4083,6 +4162,7 @@ static int start_decoder(vorb *f)
|
|||
for (k=0; k < m->coupling_steps; ++k) {
|
||||
m->chan[k].magnitude = get_bits(f, ilog(f->channels-1));
|
||||
m->chan[k].angle = get_bits(f, ilog(f->channels-1));
|
||||
if (f->valid_bits < 0) return error(f, VORBIS_unexpected_eof);
|
||||
if (m->chan[k].magnitude >= f->channels) return error(f, VORBIS_invalid_setup);
|
||||
if (m->chan[k].angle >= f->channels) return error(f, VORBIS_invalid_setup);
|
||||
if (m->chan[k].magnitude == m->chan[k].angle) return error(f, VORBIS_invalid_setup);
|
||||
|
@ -4119,6 +4199,7 @@ static int start_decoder(vorb *f)
|
|||
m->windowtype = get_bits(f,16);
|
||||
m->transformtype = get_bits(f,16);
|
||||
m->mapping = get_bits(f,8);
|
||||
if (f->valid_bits < 0) return error(f, VORBIS_unexpected_eof);
|
||||
if (m->windowtype != 0) return error(f, VORBIS_invalid_setup);
|
||||
if (m->transformtype != 0) return error(f, VORBIS_invalid_setup);
|
||||
if (m->mapping >= f->mapping_count) return error(f, VORBIS_invalid_setup);
|
||||
|
@ -4161,7 +4242,8 @@ static int start_decoder(vorb *f)
|
|||
int i,max_part_read=0;
|
||||
for (i=0; i < f->residue_count; ++i) {
|
||||
Residue *r = f->residue_config + i;
|
||||
unsigned int actual_size = f->blocksize_1 / 2;
|
||||
unsigned int rtype = f->residue_types[i];
|
||||
unsigned int actual_size = rtype == 2 ? f->blocksize_1 : f->blocksize_1 / 2;
|
||||
unsigned int limit_r_begin = r->begin < actual_size ? r->begin : actual_size;
|
||||
unsigned int limit_r_end = r->end < actual_size ? r->end : actual_size;
|
||||
int n_read = limit_r_end - limit_r_begin;
|
||||
|
@ -4233,7 +4315,8 @@ static void vorbis_deinit(stb_vorbis *p)
|
|||
Codebook *c = p->codebooks + i;
|
||||
setup_free(p, c->codeword_lengths);
|
||||
setup_free(p, c->multiplicands);
|
||||
setup_free(p, c->codewords);
|
||||
if (c->codewords != p->temp_codewords) // Might be the temporary buffer-allocated array.
|
||||
setup_free(p, c->codewords);
|
||||
setup_free(p, c->sorted_codewords);
|
||||
// c->sorted_values[-1] is the first entry in the array
|
||||
setup_free(p, c->sorted_values ? c->sorted_values-1 : NULL);
|
||||
|
@ -4263,6 +4346,12 @@ static void vorbis_deinit(stb_vorbis *p)
|
|||
setup_free(p, p->window[i]);
|
||||
setup_free(p, p->bit_reverse[i]);
|
||||
}
|
||||
if (!p->alloc.alloc_buffer) {
|
||||
setup_temp_free(p, &p->temp_lengths, 0);
|
||||
setup_temp_free(p, &p->temp_codewords, 0);
|
||||
setup_temp_free(p, &p->temp_values, 0);
|
||||
setup_temp_free(p, &p->temp_mults, 0);
|
||||
}
|
||||
#ifndef STB_VORBIS_NO_STDIO
|
||||
if (p->close_on_free) fclose(p->f);
|
||||
#endif
|
||||
|
@ -4649,10 +4738,12 @@ static int get_seek_page_info(stb_vorbis *f, ProbedPage *z)
|
|||
z->page_start = stb_vorbis_get_file_offset(f);
|
||||
|
||||
// parse the header
|
||||
getn(f, header, 27);
|
||||
if (!getn(f, header, 27))
|
||||
return 0;
|
||||
if (header[0] != 'O' || header[1] != 'g' || header[2] != 'g' || header[3] != 'S')
|
||||
return 0;
|
||||
getn(f, lacing, header[26]);
|
||||
if (!getn(f, lacing, header[26]))
|
||||
return 0;
|
||||
|
||||
// determine the length of the payload
|
||||
len = 0;
|
||||
|
@ -5147,7 +5238,9 @@ static int8 channel_position[7][6] =
|
|||
#ifndef STB_VORBIS_NO_FAST_SCALED_FLOAT
|
||||
typedef union {
|
||||
float f;
|
||||
int i;
|
||||
// changed this to unsigned to suppress an UBSan error.
|
||||
// upstream: https://github.com/nothings/stb/issues/1168.
|
||||
unsigned int i;
|
||||
} float_conv;
|
||||
typedef char stb_vorbis_float_size_test[sizeof(float)==4 && sizeof(int) == 4];
|
||||
#define FASTDEF(x) float_conv x
|
||||
|
@ -5169,7 +5262,7 @@ static void copy_samples(short *dest, float *src, int len)
|
|||
for (i=0; i < len; ++i) {
|
||||
FASTDEF(temp);
|
||||
int v = FAST_SCALED_FLOAT_TO_INT(temp, src[i],15);
|
||||
if ((unsigned int) (v + 32768) > 65535)
|
||||
if (((unsigned int)v + 32768) > 65535)
|
||||
v = v < 0 ? -32768 : 32767;
|
||||
dest[i] = v;
|
||||
}
|
||||
|
@ -5193,7 +5286,7 @@ static void compute_samples(int mask, short *output, int num_c, float **data, in
|
|||
for (i=0; i < n; ++i) {
|
||||
FASTDEF(temp);
|
||||
int v = FAST_SCALED_FLOAT_TO_INT(temp,buffer[i],15);
|
||||
if ((unsigned int) (v + 32768) > 65535)
|
||||
if (((unsigned int)v + 32768) > 65535)
|
||||
v = v < 0 ? -32768 : 32767;
|
||||
output[o+i] = v;
|
||||
}
|
||||
|
@ -5233,7 +5326,7 @@ static void compute_stereo_samples(short *output, int num_c, float **data, int d
|
|||
for (i=0; i < (n<<1); ++i) {
|
||||
FASTDEF(temp);
|
||||
int v = FAST_SCALED_FLOAT_TO_INT(temp,buffer[i],15);
|
||||
if ((unsigned int) (v + 32768) > 65535)
|
||||
if (((unsigned int)v + 32768) > 65535)
|
||||
v = v < 0 ? -32768 : 32767;
|
||||
output[o2+i] = v;
|
||||
}
|
||||
|
@ -5283,7 +5376,7 @@ static void convert_channels_short_interleaved(int buf_c, short *buffer, int dat
|
|||
FASTDEF(temp);
|
||||
float f = data[i][d_offset+j];
|
||||
int v = FAST_SCALED_FLOAT_TO_INT(temp, f,15);//data[i][d_offset+j],15);
|
||||
if ((unsigned int) (v + 32768) > 65535)
|
||||
if (((unsigned int)v + 32768) > 65535)
|
||||
v = v < 0 ? -32768 : 32767;
|
||||
*buffer++ = v;
|
||||
}
|
||||
|
|
|
@ -765,6 +765,8 @@ static int stbi_write_hdr_core(stbi__write_context *s, int x, int y, int comp, f
|
|||
else {
|
||||
// Each component is stored separately. Allocate scratch space for full output scanline.
|
||||
unsigned char *scratch = (unsigned char *) STBIW_MALLOC(x*4);
|
||||
if (NULL == scratch)
|
||||
return 0;
|
||||
int i, len;
|
||||
char buffer[128];
|
||||
char header[] = "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n";
|
||||
|
@ -772,6 +774,8 @@ static int stbi_write_hdr_core(stbi__write_context *s, int x, int y, int comp, f
|
|||
|
||||
#ifdef __STDC_LIB_EXT1__
|
||||
len = sprintf_s(buffer, sizeof(buffer), "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x);
|
||||
#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
|
||||
len = snprintf(buffer, sizeof(buffer), "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x);
|
||||
#else
|
||||
len = sprintf(buffer, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x);
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue