diff --git a/.github/workflows/analyze_codeql.yml b/.github/workflows/analyze_codeql.yml index 5fd169dd0..6598aa063 100644 --- a/.github/workflows/analyze_codeql.yml +++ b/.github/workflows/analyze_codeql.yml @@ -44,7 +44,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@master with: submodules: recursive @@ -128,7 +128,7 @@ jobs: - name: Upload CodeQL results as an artifact if: success() || failure() - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: codeql-results path: ${{ steps.step1.outputs.sarif-output }} diff --git a/.github/workflows/build_android.yml b/.github/workflows/build_android.yml index c87807847..b4efab67c 100644 --- a/.github/workflows/build_android.yml +++ b/.github/workflows/build_android.yml @@ -21,7 +21,7 @@ permissions: jobs: build: permissions: - contents: write # for actions/upload-release-asset to upload release asset + contents: write # Required for actions/upload-release-asset to upload release asset runs-on: windows-latest strategy: fail-fast: false @@ -82,7 +82,7 @@ jobs: tar -czvf ${{ env.RELEASE_NAME }}.tar.gz ${{ env.RELEASE_NAME }} - name: Upload Artifacts - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: ${{ env.RELEASE_NAME }} path: | @@ -90,7 +90,7 @@ jobs: !./build/${{ env.RELEASE_NAME }}.tar.gz - name: Upload Artifact to Release - uses: softprops/action-gh-release@v1 + uses: softprops/action-gh-release@v3 with: files: ./build/${{ env.RELEASE_NAME }}.tar.gz env: diff --git a/.github/workflows/build_cmake.yml b/.github/workflows/build_cmake.yml index 0158fb510..da1993026 100644 --- a/.github/workflows/build_cmake.yml +++ b/.github/workflows/build_cmake.yml @@ -36,7 +36,7 @@ jobs: runs-on: windows-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@master - name: Create Build Environment # Some projects don't allow in-source building, so create a separate build directory @@ -75,7 +75,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@master - name: Create Build Environment # Some projects don't allow in-source building, so create a separate build directory diff --git a/.github/workflows/build_examples_linux.yml b/.github/workflows/build_examples_linux.yml index c293efd1d..ca15acd81 100644 --- a/.github/workflows/build_examples_linux.yml +++ b/.github/workflows/build_examples_linux.yml @@ -22,7 +22,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@master - name: Setup Environment run: | diff --git a/.github/workflows/build_examples_windows.yml b/.github/workflows/build_examples_windows.yml index 4cc2e84b9..186242c24 100644 --- a/.github/workflows/build_examples_windows.yml +++ b/.github/workflows/build_examples_windows.yml @@ -22,7 +22,7 @@ jobs: runs-on: windows-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@master - name: Add MSBuild to PATH uses: microsoft/setup-msbuild@v1 diff --git a/.github/workflows/build_linux.yml b/.github/workflows/build_linux.yml index 0fc32d374..fa1c0b82c 100644 --- a/.github/workflows/build_linux.yml +++ b/.github/workflows/build_linux.yml @@ -21,7 +21,7 @@ permissions: jobs: build: permissions: - contents: write # for actions/upload-release-asset to upload release asset + contents: write # Required for actions/upload-release-asset to upload release asset strategy: fail-fast: false max-parallel: 1 @@ -112,7 +112,7 @@ jobs: tar -czvf ${{ env.RELEASE_NAME }}.tar.gz ${{ env.RELEASE_NAME }} - name: Upload Artifacts - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: ${{ env.RELEASE_NAME }} path: | @@ -120,7 +120,7 @@ jobs: !./build/${{ env.RELEASE_NAME }}.tar.gz - name: Upload Artifact to Release - uses: softprops/action-gh-release@v1 + uses: softprops/action-gh-release@v3 with: files: ./build/${{ env.RELEASE_NAME }}.tar.gz env: diff --git a/.github/workflows/build_macos.yml b/.github/workflows/build_macos.yml index 08ea0188a..9da31412e 100644 --- a/.github/workflows/build_macos.yml +++ b/.github/workflows/build_macos.yml @@ -21,7 +21,7 @@ permissions: jobs: build: permissions: - contents: write # for actions/upload-release-asset to upload release asset + contents: write # Required for actions/upload-release-asset to upload release asset runs-on: macos-latest env: @@ -99,7 +99,7 @@ jobs: tar -czvf ${{ env.RELEASE_NAME }}.tar.gz ${{ env.RELEASE_NAME }} - name: Upload Artifacts - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: ${{ env.RELEASE_NAME }} path: | @@ -107,7 +107,7 @@ jobs: !./build/${{ env.RELEASE_NAME }}.tar.gz - name: Upload Artifact to Release - uses: softprops/action-gh-release@v1 + uses: softprops/action-gh-release@v3 with: files: ./build/${{ env.RELEASE_NAME }}.tar.gz env: diff --git a/.github/workflows/build_webassembly.yml b/.github/workflows/build_webassembly.yml index 1e4066c26..ae4b37087 100644 --- a/.github/workflows/build_webassembly.yml +++ b/.github/workflows/build_webassembly.yml @@ -27,7 +27,7 @@ jobs: uses: actions/checkout@master - name: Setup emsdk - uses: mymindstorm/setup-emsdk@v14 + uses: emscripten-core/setup-emsdk@v15 with: version: 5.0.3 actions-cache-folder: 'emsdk-cache' @@ -69,7 +69,7 @@ jobs: shell: cmd - name: Upload Artifacts - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: ${{ env.RELEASE_NAME }} path: | @@ -77,7 +77,7 @@ jobs: !./build/${{ env.RELEASE_NAME }}.zip - name: Upload Artifact to Release - uses: softprops/action-gh-release@v1 + uses: softprops/action-gh-release@v3 with: files: ./build/${{ env.RELEASE_NAME }}.zip env: diff --git a/.github/workflows/build_windows.yml b/.github/workflows/build_windows.yml index 988428403..10b7ca91b 100644 --- a/.github/workflows/build_windows.yml +++ b/.github/workflows/build_windows.yml @@ -21,7 +21,7 @@ permissions: jobs: build: permissions: - contents: write # for actions/upload-release-asset to upload release asset + contents: write # Required for actions/upload-release-asset to upload release asset runs-on: windows-latest strategy: fail-fast: false @@ -81,7 +81,7 @@ jobs: # Setup MSBuild.exe path if required - name: Setup MSBuild - uses: microsoft/setup-msbuild@v2 + uses: microsoft/setup-msbuild@v3 if: matrix.compiler == 'msvc16' - name: Build Library (MinGW-w64 32bit) @@ -140,7 +140,7 @@ jobs: shell: cmd - name: Upload Artifacts - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: ${{ env.RELEASE_NAME }} path: | @@ -148,7 +148,7 @@ jobs: !./build/${{ env.RELEASE_NAME }}.zip - name: Upload Artifact to Release - uses: softprops/action-gh-release@v1 + uses: softprops/action-gh-release@v3 with: files: ./build/${{ env.RELEASE_NAME }}.zip env: diff --git a/.github/workflows/parse_api.yml b/.github/workflows/parse_api.yml index e25cde18b..36f7fb5db 100644 --- a/.github/workflows/parse_api.yml +++ b/.github/workflows/parse_api.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@master - name: Update parse files working-directory: tools/rlparser diff --git a/.github/workflows/update_examples.yml b/.github/workflows/update_examples.yml index fe8e4c48f..1d1edc524 100644 --- a/.github/workflows/update_examples.yml +++ b/.github/workflows/update_examples.yml @@ -15,10 +15,10 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@master - name: Setup emsdk - uses: mymindstorm/setup-emsdk@v14 + uses: emscripten-core/setup-emsdk@v15 with: version: 'latest' actions-cache-folder: 'emsdk-cache' diff --git a/BINDINGS.md b/BINDINGS.md index f528c892a..624ec8155 100644 --- a/BINDINGS.md +++ b/BINDINGS.md @@ -52,7 +52,7 @@ Some people ported raylib to other languages in the form of bindings or wrappers | [KaylibKit](https://codeberg.org/Kenta/KaylibKit) | 4.5 | [Kotlin/native](https://kotlinlang.org) | Zlib | | [raylib-lua](https://github.com/TSnake41/raylib-lua) | 5.5 | [Lua](http://www.lua.org) | ISC | | [raylib-lua-bindings (WIP)](https://github.com/legendaryredfox/raylib-lua-bindings) | 5.5 | [Lua](http://www.lua.org) | ISC | -| [ReiLua](https://github.com/nullstare/ReiLua) | 5.5 | [Lua](http://www.lua.org) | MIT | +| [ReiLua](https://github.com/nullstare/ReiLua) | 6.0 | [Lua](http://www.lua.org) | MIT | | [raylib-lua-sol](https://github.com/RobLoach/raylib-lua-sol) | 5.5 | [Lua](http://www.lua.org) | Zlib | | [raylib-luajit](https://github.com/homma/raylib-luajit) | 5.5 | [Lua](http://www.lua.org) | MIT | | [raylib-luajit-generated](https://github.com/james2doyle/raylib-luajit-generated) | 5.5 | [Lua](http://www.lua.org) | MIT | diff --git a/SECURITY.md b/SECURITY.md index 48a825e37..7a52e4359 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -11,8 +11,4 @@ Most considerations of errors and defects can be handled using the project Issue ## Reporting a Vulnerability -Discovered vulnerability can be directly reported using the project Issues and/or Discussions. - -_TODO: Tell them where to go, how often they can expect to get an update on a -reported vulnerability, what to expect if the vulnerability is accepted or -declined, etc._ +Discovered vulnerability can be directly reported using the project Issues and/or Discussions. They will be reviewed as soon as possible. diff --git a/examples/shaders/resources/shaders/glsl100/pbr.fs b/examples/shaders/resources/shaders/glsl100/pbr.fs index 28212bf63..f29cb0e59 100644 --- a/examples/shaders/resources/shaders/glsl100/pbr.fs +++ b/examples/shaders/resources/shaders/glsl100/pbr.fs @@ -99,7 +99,7 @@ vec3 ComputePBR() vec3 N = normalize(fragNormal); if (useTexNormal == 1) { - N = texture2D(normalMap, vec2(fragTexCoord.x*tiling.x + offset.y, fragTexCoord.y*tiling.y + offset.y)).rgb; + N = texture2D(normalMap, vec2(fragTexCoord.x*tiling.x + offset.x, fragTexCoord.y*tiling.y + offset.y)).rgb; N = normalize(N*2.0 - 1.0); N = normalize(N*TBN); } diff --git a/examples/shaders/resources/shaders/glsl120/pbr.fs b/examples/shaders/resources/shaders/glsl120/pbr.fs index b36b76bee..450986f1b 100644 --- a/examples/shaders/resources/shaders/glsl120/pbr.fs +++ b/examples/shaders/resources/shaders/glsl120/pbr.fs @@ -97,7 +97,7 @@ vec3 ComputePBR() vec3 N = normalize(fragNormal); if (useTexNormal == 1) { - N = texture2D(normalMap, vec2(fragTexCoord.x*tiling.x + offset.y, fragTexCoord.y*tiling.y + offset.y)).rgb; + N = texture2D(normalMap, vec2(fragTexCoord.x*tiling.x + offset.x, fragTexCoord.y*tiling.y + offset.y)).rgb; N = normalize(N*2.0 - 1.0); N = normalize(N*TBN); } diff --git a/examples/shaders/resources/shaders/glsl330/pbr.fs b/examples/shaders/resources/shaders/glsl330/pbr.fs index ceaead308..67254851c 100644 --- a/examples/shaders/resources/shaders/glsl330/pbr.fs +++ b/examples/shaders/resources/shaders/glsl330/pbr.fs @@ -100,7 +100,7 @@ vec3 ComputePBR() vec3 N = normalize(fragNormal); if (useTexNormal == 1) { - N = texture(normalMap, vec2(fragTexCoord.x*tiling.x + offset.y, fragTexCoord.y*tiling.y + offset.y)).rgb; + N = texture(normalMap, vec2(fragTexCoord.x*tiling.x + offset.x, fragTexCoord.y*tiling.y + offset.y)).rgb; N = normalize(N*2.0 - 1.0); N = normalize(N*TBN); } diff --git a/projects/4coder/Makefile b/projects/4coder/Makefile deleted file mode 100644 index ec0977aaf..000000000 --- a/projects/4coder/Makefile +++ /dev/null @@ -1,401 +0,0 @@ -#************************************************************************************************** -# -# raylib makefile for Desktop platforms, Raspberry Pi, Android and HTML5 -# -# Copyright (c) 2013-2026 Ramon Santamaria (@raysan5) -# -# This software is provided "as-is", without any express or implied warranty. In no event -# will the authors be held liable for any damages arising from the use of this software. -# -# Permission is granted to anyone to use this software for any purpose, including commercial -# applications, and to alter it and redistribute it freely, subject to the following restrictions: -# -# 1. The origin of this software must not be misrepresented; you must not claim that you -# wrote the original software. If you use this software in a product, an acknowledgment -# in the product documentation would be appreciated but is not required. -# -# 2. Altered source versions must be plainly marked as such, and must not be misrepresented -# as being the original software. -# -# 3. This notice may not be removed or altered from any source distribution. -# -#************************************************************************************************** - -.PHONY: all clean - -# Define required raylib variables -PROJECT_NAME ?= game -RAYLIB_VERSION ?= 4.2.0 -RAYLIB_PATH ?= ..\.. - -# Define default options - -# One of PLATFORM_DESKTOP, PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB -PLATFORM ?= PLATFORM_DESKTOP - -# Locations of your newly installed library and associated headers. See ../src/Makefile -# On Linux, if you have installed raylib but cannot compile the examples, check that -# the *_INSTALL_PATH values here are the same as those in src/Makefile or point to known locations. -# To enable system-wide compile-time and runtime linking to libraylib.so, run ../src/$ sudo make install RAYLIB_LIBTYPE_SHARED. -# To enable compile-time linking to a special version of libraylib.so, change these variables here. -# To enable runtime linking to a special version of libraylib.so, see EXAMPLE_RUNTIME_PATH below. -# If there is a libraylib in both EXAMPLE_RUNTIME_PATH and RAYLIB_INSTALL_PATH, at runtime, -# the library at EXAMPLE_RUNTIME_PATH, if present, will take precedence over the one at RAYLIB_INSTALL_PATH. -# RAYLIB_INSTALL_PATH should be the desired full path to libraylib. No relative paths. -DESTDIR ?= /usr/local -RAYLIB_INSTALL_PATH ?= $(DESTDIR)/lib -# RAYLIB_H_INSTALL_PATH locates the installed raylib header and associated source files. -RAYLIB_H_INSTALL_PATH ?= $(DESTDIR)/include - -# Library type used for raylib: STATIC (.a) or SHARED (.so/.dll) -RAYLIB_LIBTYPE ?= STATIC - -# Build mode for project: DEBUG or RELEASE -BUILD_MODE ?= RELEASE - -# Use external GLFW library instead of rglfw module -# TODO: Review usage on Linux. Target version of choice. Switch on -lglfw or -lglfw3 -USE_EXTERNAL_GLFW ?= FALSE - -# Use Wayland display server protocol on Linux desktop -# by default it uses X11 windowing system -USE_WAYLAND_DISPLAY ?= FALSE - -# Determine PLATFORM_OS in case PLATFORM_DESKTOP selected -ifeq ($(PLATFORM),PLATFORM_DESKTOP) - # No uname.exe on MinGW!, but OS=Windows_NT on Windows! - # ifeq ($(UNAME),Msys) -> Windows - ifeq ($(OS),Windows_NT) - PLATFORM_OS=WINDOWS - else - UNAMEOS=$(shell uname) - ifeq ($(UNAMEOS),Linux) - PLATFORM_OS=LINUX - endif - ifeq ($(UNAMEOS),FreeBSD) - PLATFORM_OS=BSD - endif - ifeq ($(UNAMEOS),OpenBSD) - PLATFORM_OS=BSD - endif - ifeq ($(UNAMEOS),NetBSD) - PLATFORM_OS=BSD - endif - ifeq ($(UNAMEOS),DragonFly) - PLATFORM_OS=BSD - endif - ifeq ($(UNAMEOS),Darwin) - PLATFORM_OS=OSX - endif - endif -endif -ifeq ($(PLATFORM),PLATFORM_RPI) - UNAMEOS=$(shell uname) - ifeq ($(UNAMEOS),Linux) - PLATFORM_OS=LINUX - endif -endif - -# RAYLIB_PATH adjustment for different platforms. -# If using GNU make, we can get the full path to the top of the tree. Windows? BSD? -# Required for ldconfig or other tools that do not perform path expansion. -ifeq ($(PLATFORM),PLATFORM_DESKTOP) - ifeq ($(PLATFORM_OS),LINUX) - RAYLIB_PREFIX ?= .. - RAYLIB_PATH = $(realpath $(RAYLIB_PREFIX)) - endif -endif -# Default path for raylib on Raspberry Pi, if installed in different path, update it! -# This is not currently used by src/Makefile. Not sure of its origin or usage. Refer to wiki. -# TODO: update install: target in src/Makefile for RPI, consider relation to LINUX. -ifeq ($(PLATFORM),PLATFORM_RPI) - RAYLIB_PATH ?= /home/pi/raylib -endif - -ifeq ($(PLATFORM),PLATFORM_WEB) - # Emscripten required variables - EMSDK_PATH ?= C:/raylib/emsdk - EMSCRIPTEN_PATH ?= $(EMSDK_PATH)/upstream/emscripten - CLANG_PATH = $(EMSDK_PATH)/upstream/bin - PYTHON_PATH = $(EMSDK_PATH)/python/3.13.3_64bit - NODE_PATH = $(EMSDK_PATH)/node/22.16.0_64bit/bin - export PATH = $(EMSDK_PATH);$(EMSCRIPTEN_PATH);$(CLANG_PATH);$(NODE_PATH);$(PYTHON_PATH);C:\raylib\MinGW\bin:$$(PATH) -endif - -# Define raylib release directory for compiled library. -# RAYLIB_RELEASE_PATH points to provided binaries or your freshly built version -RAYLIB_RELEASE_PATH ?= $(RAYLIB_PATH)/src - -# EXAMPLE_RUNTIME_PATH embeds a custom runtime location of libraylib.so or other desired libraries -# into each example binary compiled with RAYLIB_LIBTYPE=SHARED. It defaults to RAYLIB_RELEASE_PATH -# so that these examples link at runtime with your version of libraylib.so in ../release/libs/linux -# without formal installation from ../src/Makefile. It aids portability and is useful if you have -# multiple versions of raylib, have raylib installed to a non-standard location, or want to -# bundle libraylib.so with your game. Change it to your liking. -# NOTE: If, at runtime, there is a libraylib.so at both EXAMPLE_RUNTIME_PATH and RAYLIB_INSTALL_PATH, -# The library at EXAMPLE_RUNTIME_PATH, if present, will take precedence over RAYLIB_INSTALL_PATH, -# Implemented for LINUX below with CFLAGS += -Wl,-rpath,$(EXAMPLE_RUNTIME_PATH) -# To see the result, run readelf -d core/core_basic_window; looking at the RPATH or RUNPATH attribute. -# To see which libraries a built example is linking to, ldd core/core_basic_window; -# Look for libraylib.so.1 => $(RAYLIB_INSTALL_PATH)/libraylib.so.1 or similar listing. -EXAMPLE_RUNTIME_PATH ?= $(RAYLIB_RELEASE_PATH) - -# Define default C compiler: gcc -# NOTE: define g++ compiler if using C++ -CC = gcc - -ifeq ($(PLATFORM),PLATFORM_DESKTOP) - ifeq ($(PLATFORM_OS),OSX) - # OSX default compiler - CC = clang - endif - ifeq ($(PLATFORM_OS),BSD) - # FreeBSD, OpenBSD, NetBSD, DragonFly default compiler - CC = clang - endif -endif -ifeq ($(PLATFORM),PLATFORM_RPI) - ifeq ($(USE_RPI_CROSS_COMPILER),TRUE) - # Define RPI cross-compiler - #CC = armv6j-hardfloat-linux-gnueabi-gcc - CC = $(RPI_TOOLCHAIN)/bin/arm-linux-gnueabihf-gcc - endif -endif -ifeq ($(PLATFORM),PLATFORM_WEB) - # HTML5 emscripten compiler - # WARNING: To compile to HTML5, code must be redesigned - # to use emscripten.h and emscripten_set_main_loop() - CC = emcc -endif - -# Define default make program: Mingw32-make -MAKE = mingw32-make - -ifeq ($(PLATFORM),PLATFORM_DESKTOP) - ifeq ($(PLATFORM_OS),LINUX) - MAKE = make - endif - ifeq ($(PLATFORM_OS),OSX) - MAKE = make - endif -endif - -# Define compiler flags: -# -O1 defines optimization level -# -g include debug information on compilation -# -s strip unnecessary data from build -# -Wall turns on most, but not all, compiler warnings -# -std=c99 defines C language mode (standard C from 1999 revision) -# -std=gnu99 defines C language mode (GNU C from 1999 revision) -# -Wno-missing-braces ignore invalid warning (GCC bug 53119) -# -D_DEFAULT_SOURCE use with -std=c99 on Linux and PLATFORM_WEB, required for timespec -CFLAGS += -O1 -s -Wall -std=c99 -D_DEFAULT_SOURCE -Wno-missing-braces - -ifeq ($(BUILD_MODE),DEBUG) - CFLAGS += -g -endif - -# Additional flags for compiler (if desired) -#CFLAGS += -Wextra -Wmissing-prototypes -Wstrict-prototypes -ifeq ($(PLATFORM),PLATFORM_DESKTOP) - ifeq ($(PLATFORM_OS),WINDOWS) - # resource file contains windows executable icon and properties - # -Wl,--subsystem,windows hides the console window - CFLAGS += $(RAYLIB_PATH)/src/raylib.rc.data -Wl,--subsystem,windows - endif - ifeq ($(PLATFORM_OS),LINUX) - ifeq ($(RAYLIB_LIBTYPE),STATIC) - CFLAGS += -D_DEFAULT_SOURCE - endif - ifeq ($(RAYLIB_LIBTYPE),SHARED) - # Explicitly enable runtime link to libraylib.so - CFLAGS += -Wl,-rpath,$(EXAMPLE_RUNTIME_PATH) - endif - endif -endif -ifeq ($(PLATFORM),PLATFORM_RPI) - CFLAGS += -std=gnu99 -endif -ifeq ($(PLATFORM),PLATFORM_WEB) - # -Os # size optimization - # -O2 # optimization level 2, if used, also set --memory-init-file 0 - # -sUSE_GLFW=3 # Use glfw3 library (context/input management) - # -sALLOW_MEMORY_GROWTH=1 # to allow memory resizing -> WARNING: Audio buffers could FAIL! - # -sTOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB) (67108864 = 64MB) - # -sUSE_PTHREADS=1 # multithreading support - # -sWASM=0 # disable Web Assembly, emitted by default - # -sASYNCIFY # lets synchronous C/C++ code interact with asynchronous JS - # -sFORCE_FILESYSTEM=1 # force filesystem to load/save files data - # -sASSERTIONS=1 # enable runtime checks for common memory allocation errors (-O1 and above turn it off) - # -sMINIFY_HTML=0 # minify generated html from shell.html - # --profiling # include information for code profiling - # --memory-init-file 0 # to avoid an external memory initialization code file (.mem) - # --preload-file resources # specify a resources folder for data compilation - # --source-map-base # allow debugging in browser with source map - # --shell-file shell.html # define a custom shell .html and output extension - CFLAGS += -Os -sUSE_GLFW=3 -sTOTAL_MEMORY=16777216 --preload-file resources -sMINIFY_HTML=0 - ifeq ($(BUILD_MODE), DEBUG) - CFLAGS += -sASSERTIONS=1 --profiling - endif - - # Define a custom shell .html and output extension - CFLAGS += --shell-file $(RAYLIB_PATH)/src/shell.html - EXT = .html -endif - -# Define include paths for required headers -# NOTE: Several external required libraries (stb and others) -INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/src -I$(RAYLIB_PATH)/src/external - -# Define additional directories containing required header files -ifeq ($(PLATFORM),PLATFORM_RPI) - # RPI required libraries - INCLUDE_PATHS += -I/opt/vc/include - INCLUDE_PATHS += -I/opt/vc/include/interface/vmcs_host/linux - INCLUDE_PATHS += -I/opt/vc/include/interface/vcos/pthreads -endif -ifeq ($(PLATFORM),PLATFORM_DESKTOP) - ifeq ($(PLATFORM_OS),BSD) - # Consider -L$(RAYLIB_H_INSTALL_PATH) - INCLUDE_PATHS += -I/usr/local/include - endif - ifeq ($(PLATFORM_OS),LINUX) - # Reset everything. - # Precedence: immediately local, installed version, raysan5 provided libs -I$(RAYLIB_H_INSTALL_PATH) -I$(RAYLIB_PATH)/release/include - INCLUDE_PATHS = -I$(RAYLIB_H_INSTALL_PATH) -isystem. -isystem$(RAYLIB_PATH)/src -isystem$(RAYLIB_PATH)/release/include -isystem$(RAYLIB_PATH)/src/external - endif -endif - -# Define library paths containing required libs. -LDFLAGS = -L. -L$(RAYLIB_RELEASE_PATH) -L$(RAYLIB_PATH)/src - -ifeq ($(PLATFORM),PLATFORM_DESKTOP) - ifeq ($(PLATFORM_OS),BSD) - # Consider -L$(RAYLIB_INSTALL_PATH) - LDFLAGS += -L. -Lsrc -L/usr/local/lib - endif - ifeq ($(PLATFORM_OS),LINUX) - # Reset everything. - # Precedence: immediately local, installed version, raysan5 provided libs - LDFLAGS = -L. -L$(RAYLIB_INSTALL_PATH) -L$(RAYLIB_RELEASE_PATH) - endif -endif - -ifeq ($(PLATFORM),PLATFORM_RPI) - LDFLAGS += -L/opt/vc/lib -endif - -# Define any libraries required on linking -# if you want to link libraries (libname.so or libname.a), use the -lname -ifeq ($(PLATFORM),PLATFORM_DESKTOP) - ifeq ($(PLATFORM_OS),WINDOWS) - # Libraries for Windows desktop compilation - # NOTE: WinMM library required to set high-res timer resolution - LDLIBS = -lraylib -lopengl32 -lgdi32 -lwinmm - endif - ifeq ($(PLATFORM_OS),LINUX) - # Libraries for Debian GNU/Linux desktop compiling - # NOTE: Required packages: libegl1-mesa-dev - LDLIBS = -lraylib -lGL -lm -lpthread -ldl -lrt - - # On X11 requires also below libraries - LDLIBS += -lX11 - # NOTE: It seems additional libraries are not required any more, latest GLFW just dlopen them - #LDLIBS += -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor - - # On Wayland windowing system, additional libraries requires - ifeq ($(USE_WAYLAND_DISPLAY),TRUE) - LDLIBS += -lwayland-client -lwayland-cursor -lwayland-egl -lxkbcommon - endif - # Explicit link to libc - ifeq ($(RAYLIB_LIBTYPE),SHARED) - LDLIBS += -lc - endif - endif - ifeq ($(PLATFORM_OS),OSX) - # Libraries for OSX 10.9 desktop compiling - # NOTE: Required packages: libopenal-dev libegl1-mesa-dev - LDLIBS = -lraylib -framework OpenGL -framework OpenAL -framework Cocoa - endif - ifeq ($(PLATFORM_OS),BSD) - # Libraries for FreeBSD, OpenBSD, NetBSD, DragonFly desktop compiling - # NOTE: Required packages: mesa-libs - LDLIBS = -lraylib -lGL -lpthread -lm - - # On XWindow requires also below libraries - LDLIBS += -lX11 -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor - endif - ifeq ($(USE_EXTERNAL_GLFW),TRUE) - # NOTE: It could require additional packages installed: libglfw3-dev - LDLIBS += -lglfw - endif -endif -ifeq ($(PLATFORM),PLATFORM_RPI) - # Libraries for Raspberry Pi compiling - # NOTE: Required packages: libasound2-dev (ALSA) - LDLIBS = -lraylib -lbrcmGLESv2 -lbrcmEGL -lpthread -lrt -lm -lbcm_host -ldl -endif -ifeq ($(PLATFORM),PLATFORM_WEB) - # Libraries for web (HTML5) compiling - LDLIBS = $(RAYLIB_RELEASE_PATH)/libraylib.bc -endif - -# Define a recursive wildcard function -rwildcard=$(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2) $(filter $(subst *,%,$2),$d)) - -# Define all source files required -SRC_DIR = src -OBJ_DIR = obj - -# Define all object files from source files -SRC = $(call rwildcard, *.c, *.h) -#OBJS = $(SRC:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o) -OBJS = main.c - -# For Android platform we call a custom Makefile.Android -ifeq ($(PLATFORM),PLATFORM_ANDROID) - MAKEFILE_PARAMS = -f Makefile.Android - export PROJECT_NAME - export SRC_DIR -else - MAKEFILE_PARAMS = $(PROJECT_NAME) -endif - -# Default target entry -# NOTE: We call this Makefile target or Makefile.Android target -all: - $(MAKE) $(MAKEFILE_PARAMS) - -# Project target defined by PROJECT_NAME -$(PROJECT_NAME): $(OBJS) - $(CC) -o $(PROJECT_NAME)$(EXT) $(OBJS) $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) - -# Compile source files -# NOTE: This pattern will compile every module defined on $(OBJS) -#%.o: %.c -$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c - $(CC) -c $< -o $@ $(CFLAGS) $(INCLUDE_PATHS) -D$(PLATFORM) - -# Clean everything -clean: -ifeq ($(PLATFORM),PLATFORM_DESKTOP) - ifeq ($(PLATFORM_OS),WINDOWS) - del *.o *.exe /s - endif - ifeq ($(PLATFORM_OS),LINUX) - find -type f -executable | xargs file -i | grep -E 'x-object|x-archive|x-sharedlib|x-executable' | rev | cut -d ':' -f 2- | rev | xargs rm -fv - endif - ifeq ($(PLATFORM_OS),OSX) - find . -type f -perm +ugo+x -delete - rm -f *.o - endif -endif -ifeq ($(PLATFORM),PLATFORM_RPI) - find . -type f -executable -delete - rm -fv *.o -endif -ifeq ($(PLATFORM),PLATFORM_WEB) - del *.o *.html *.js -endif - @echo Cleaning done - diff --git a/projects/4coder/Makefile.Android b/projects/4coder/Makefile.Android deleted file mode 100644 index 9e6773651..000000000 --- a/projects/4coder/Makefile.Android +++ /dev/null @@ -1,300 +0,0 @@ -#************************************************************************************************** -# -# raylib makefile for Android project (APK building) -# -# Copyright (c) 2017 Ramon Santamaria (@raysan5) -# -# This software is provided "as-is", without any express or implied warranty. In no event -# will the authors be held liable for any damages arising from the use of this software. -# -# Permission is granted to anyone to use this software for any purpose, including commercial -# applications, and to alter it and redistribute it freely, subject to the following restrictions: -# -# 1. The origin of this software must not be misrepresented; you must not claim that you -# wrote the original software. If you use this software in a product, an acknowledgment -# in the product documentation would be appreciated but is not required. -# -# 2. Altered source versions must be plainly marked as such, and must not be misrepresented -# as being the original software. -# -# 3. This notice may not be removed or altered from any source distribution. -# -#************************************************************************************************** - -# Define required raylib variables -PLATFORM ?= PLATFORM_ANDROID -RAYLIB_PATH ?= ..\.. - -# Define Android architecture (armeabi-v7a, arm64-v8a, x86, x86-64) and API version -ANDROID_ARCH ?= ARM -ANDROID_API_VERSION = 21 -ifeq ($(ANDROID_ARCH),ARM) - ANDROID_ARCH_NAME = armeabi-v7a -endif -ifeq ($(ANDROID_ARCH),ARM64) - ANDROID_ARCH_NAME = arm64-v8a -endif - -# Required path variables -# NOTE: JAVA_HOME must be set to JDK -JAVA_HOME ?= C:/JavaJDK -ANDROID_HOME = C:/android-sdk -ANDROID_TOOLCHAIN = C:/android_toolchain_$(ANDROID_ARCH)_API$(ANDROID_API_VERSION) -ANDROID_BUILD_TOOLS = $(ANDROID_HOME)/build-tools/28.0.1 -ANDROID_PLATFORM_TOOLS = $(ANDROID_HOME)/platform-tools - -# Android project configuration variables -PROJECT_NAME ?= raylib_game -PROJECT_LIBRARY_NAME ?= main -PROJECT_BUILD_PATH ?= android.$(PROJECT_NAME) -PROJECT_RESOURCES_PATH ?= resources -PROJECT_SOURCE_FILES ?= raylib_game.c - -# Some source files are placed in directories, when compiling to some -# output directory other than source, that directory must pre-exist. -# Here we get a list of required folders that need to be created on -# code output folder $(PROJECT_BUILD_PATH)\obj to avoid GCC errors. -PROJECT_SOURCE_DIRS = $(sort $(dir $(PROJECT_SOURCE_FILES))) - -# Android app configuration variables -APP_LABEL_NAME ?= rGame -APP_COMPANY_NAME ?= raylib -APP_PRODUCT_NAME ?= rgame -APP_VERSION_CODE ?= 1 -APP_VERSION_NAME ?= 1.0 -APP_ICON_LDPI ?= $(RAYLIB_PATH)\logo\raylib_36x36.png -APP_ICON_MDPI ?= $(RAYLIB_PATH)\logo\raylib_48x48.png -APP_ICON_HDPI ?= $(RAYLIB_PATH)\logo\raylib_72x72.png -APP_SCREEN_ORIENTATION ?= landscape -APP_KEYSTORE_PASS ?= raylib - -# Library type used for raylib: STATIC (.a) or SHARED (.so/.dll) -RAYLIB_LIBTYPE ?= STATIC - -# Library path for libraylib.a/libraylib.so -RAYLIB_LIB_PATH = $(RAYLIB_PATH)\src - -# Shared libs must be added to APK if required -# NOTE: Generated NativeLoader.java automatically load those libraries -ifeq ($(RAYLIB_LIBTYPE),SHARED) - PROJECT_SHARED_LIBS = lib/$(ANDROID_ARCH_NAME)/libraylib.so -endif - -# Compiler and archiver -# NOTE: GCC is being deprecated in Android NDK r16 -ifeq ($(ANDROID_ARCH),ARM) - CC = $(ANDROID_TOOLCHAIN)/bin/arm-linux-androideabi-clang - AR = $(ANDROID_TOOLCHAIN)/bin/arm-linux-androideabi-ar -endif -ifeq ($(ANDROID_ARCH),ARM64) - CC = $(ANDROID_TOOLCHAIN)/bin/aarch64-linux-android-clang - AR = $(ANDROID_TOOLCHAIN)/bin/aarch64-linux-android-ar -endif - -# Compiler flags for arquitecture -ifeq ($(ANDROID_ARCH),ARM) - CFLAGS = -std=c99 -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -endif -ifeq ($(ANDROID_ARCH),ARM64) - CFLAGS = -std=c99 -mfix-cortex-a53-835769 -endif -# Compilation functions attributes options -CFLAGS += -ffunction-sections -funwind-tables -fstack-protector-strong -fPIC -# Compiler options for the linker -CFLAGS += -Wall -Wa,--noexecstack -Wformat -Werror=format-security -no-canonical-prefixes -# Preprocessor macro definitions -CFLAGS += -DANDROID -DPLATFORM_ANDROID -D__ANDROID_API__=$(ANDROID_API_VERSION) - -# Paths containing required header files -INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/src -I$(RAYLIB_PATH)/src/external/android/native_app_glue - -# Linker options -LDFLAGS = -Wl,-soname,lib$(PROJECT_LIBRARY_NAME).so -Wl,--exclude-libs,libatomic.a -LDFLAGS += -Wl,--build-id -Wl,--no-undefined -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now -Wl,--warn-shared-textrel -Wl,--fatal-warnings -# Force linking of library module to define symbol -LDFLAGS += -u ANativeActivity_onCreate -# Library paths containing required libs -LDFLAGS += -L. -L$(PROJECT_BUILD_PATH)/obj -L$(PROJECT_BUILD_PATH)/lib/$(ANDROID_ARCH_NAME) -L$(ANDROID_TOOLCHAIN)\sysroot\usr\lib - -# Define any libraries to link into executable -# if you want to link libraries (libname.so or libname.a), use the -lname -LDLIBS = -lm -lc -lraylib -llog -landroid -lEGL -lGLESv2 -lOpenSLES -ldl - -# Generate target objects list from PROJECT_SOURCE_FILES -OBJS = $(patsubst %.c, $(PROJECT_BUILD_PATH)/obj/%.o, $(PROJECT_SOURCE_FILES)) - -# Android APK building process... some steps required... -# NOTE: typing 'make' will invoke the default target entry called 'all', -all: create_temp_project_dirs \ - copy_project_required_libs \ - copy_project_resources \ - generate_loader_script \ - generate_android_manifest \ - generate_apk_keystore \ - config_project_package \ - compile_project_code \ - compile_project_class \ - compile_project_class_dex \ - create_project_apk_package \ - sign_project_apk_package \ - zipalign_project_apk_package - -# Create required temp directories for APK building -create_temp_project_dirs: - if not exist $(PROJECT_BUILD_PATH) mkdir $(PROJECT_BUILD_PATH) - if not exist $(PROJECT_BUILD_PATH)\obj mkdir $(PROJECT_BUILD_PATH)\obj - if not exist $(PROJECT_BUILD_PATH)\src mkdir $(PROJECT_BUILD_PATH)\src - if not exist $(PROJECT_BUILD_PATH)\src\com mkdir $(PROJECT_BUILD_PATH)\src\com - if not exist $(PROJECT_BUILD_PATH)\src\com\$(APP_COMPANY_NAME) mkdir $(PROJECT_BUILD_PATH)\src\com\$(APP_COMPANY_NAME) - if not exist $(PROJECT_BUILD_PATH)\src\com\$(APP_COMPANY_NAME)\$(APP_PRODUCT_NAME) mkdir $(PROJECT_BUILD_PATH)\src\com\$(APP_COMPANY_NAME)\$(APP_PRODUCT_NAME) - if not exist $(PROJECT_BUILD_PATH)\lib mkdir $(PROJECT_BUILD_PATH)\lib - if not exist $(PROJECT_BUILD_PATH)\lib\$(ANDROID_ARCH_NAME) mkdir $(PROJECT_BUILD_PATH)\lib\$(ANDROID_ARCH_NAME) - if not exist $(PROJECT_BUILD_PATH)\bin mkdir $(PROJECT_BUILD_PATH)\bin - if not exist $(PROJECT_BUILD_PATH)\res mkdir $(PROJECT_BUILD_PATH)\res - if not exist $(PROJECT_BUILD_PATH)\res\drawable-ldpi mkdir $(PROJECT_BUILD_PATH)\res\drawable-ldpi - if not exist $(PROJECT_BUILD_PATH)\res\drawable-mdpi mkdir $(PROJECT_BUILD_PATH)\res\drawable-mdpi - if not exist $(PROJECT_BUILD_PATH)\res\drawable-hdpi mkdir $(PROJECT_BUILD_PATH)\res\drawable-hdpi - if not exist $(PROJECT_BUILD_PATH)\res\values mkdir $(PROJECT_BUILD_PATH)\res\values - if not exist $(PROJECT_BUILD_PATH)\assets mkdir $(PROJECT_BUILD_PATH)\assets - if not exist $(PROJECT_BUILD_PATH)\assets\$(PROJECT_RESOURCES_PATH) mkdir $(PROJECT_BUILD_PATH)\assets\$(PROJECT_RESOURCES_PATH) - if not exist $(PROJECT_BUILD_PATH)\obj\screens mkdir $(PROJECT_BUILD_PATH)\obj\screens - $(foreach dir, $(PROJECT_SOURCE_DIRS), $(call create_dir, $(dir))) - -define create_dir - if not exist $(PROJECT_BUILD_PATH)\obj\$(1) mkdir $(PROJECT_BUILD_PATH)\obj\$(1) -endef - -# Copy required shared libs for integration into APK -# NOTE: If using shared libs they are loaded by generated NativeLoader.java -copy_project_required_libs: -ifeq ($(RAYLIB_LIBTYPE),SHARED) - copy /Y $(RAYLIB_LIB_PATH)\libraylib.so $(PROJECT_BUILD_PATH)\lib\$(ANDROID_ARCH_NAME)\libraylib.so -endif -ifeq ($(RAYLIB_LIBTYPE),STATIC) - copy /Y $(RAYLIB_LIB_PATH)\libraylib.a $(PROJECT_BUILD_PATH)\lib\$(ANDROID_ARCH_NAME)\libraylib.a -endif - -# Copy project required resources: strings.xml, icon.png, assets -# NOTE: Required strings.xml is generated and game resources are copied to assets folder -# TODO: Review xcopy usage, it can not be found in some systems! -copy_project_resources: - copy $(APP_ICON_LDPI) $(PROJECT_BUILD_PATH)\res\drawable-ldpi\icon.png /Y - copy $(APP_ICON_MDPI) $(PROJECT_BUILD_PATH)\res\drawable-mdpi\icon.png /Y - copy $(APP_ICON_HDPI) $(PROJECT_BUILD_PATH)\res\drawable-hdpi\icon.png /Y - @echo ^ > $(PROJECT_BUILD_PATH)/res/values/strings.xml - @echo ^^$(APP_LABEL_NAME)^^ >> $(PROJECT_BUILD_PATH)/res/values/strings.xml - if exist $(PROJECT_RESOURCES_PATH) C:\Windows\System32\xcopy $(PROJECT_RESOURCES_PATH) $(PROJECT_BUILD_PATH)\assets\$(PROJECT_RESOURCES_PATH) /Y /E /F - -# Generate NativeLoader.java to load required shared libraries -# NOTE: Probably not the bet way to generate this file... but it works. -generate_loader_script: - @echo package com.$(APP_COMPANY_NAME).$(APP_PRODUCT_NAME); > $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java - @echo. >> $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java - @echo public class NativeLoader extends android.app.NativeActivity { >> $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java - @echo static { >> $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java -ifeq ($(RAYLIB_LIBTYPE),SHARED) - @echo System.loadLibrary("raylib"); >> $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java -endif - @echo System.loadLibrary("$(PROJECT_LIBRARY_NAME)"); >> $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java - @echo } >> $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java - @echo } >> $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java - -# Generate AndroidManifest.xml with all the required options -# NOTE: Probably not the bet way to generate this file... but it works. -generate_android_manifest: - @echo ^ > $(PROJECT_BUILD_PATH)/AndroidManifest.xml - @echo ^> $(PROJECT_BUILD_PATH)/AndroidManifest.xml - @echo package="com.$(APP_COMPANY_NAME).$(APP_PRODUCT_NAME)" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml - @echo android:versionCode="$(APP_VERSION_CODE)" android:versionName="$(APP_VERSION_NAME)" ^> >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml - @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml - @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml - @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml - @echo ^> $(PROJECT_BUILD_PATH)/AndroidManifest.xml - @echo android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml - @echo android:configChanges="orientation|keyboardHidden|screenSize" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml - @echo android:screenOrientation="$(APP_SCREEN_ORIENTATION)" android:launchMode="singleTask" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml - @echo android:clearTaskOnLaunch="true"^> >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml - @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml - @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml - @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml - @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml - @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml - @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml - @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml - @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml - -# Generate storekey for APK signing: $(PROJECT_NAME).keystore -# NOTE: Configure here your Distinguished Names (-dname) if required! -generate_apk_keystore: - if not exist $(PROJECT_BUILD_PATH)/$(PROJECT_NAME).keystore $(JAVA_HOME)/bin/keytool -genkeypair -validity 1000 -dname "CN=$(APP_COMPANY_NAME),O=Android,C=ES" -keystore $(PROJECT_BUILD_PATH)/$(PROJECT_NAME).keystore -storepass $(APP_KEYSTORE_PASS) -keypass $(APP_KEYSTORE_PASS) -alias $(PROJECT_NAME)Key -keyalg RSA - -# Config project package and resource using AndroidManifest.xml and res/values/strings.xml -# NOTE: Generates resources file: src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/R.java -config_project_package: - $(ANDROID_BUILD_TOOLS)/aapt package -f -m -S $(PROJECT_BUILD_PATH)/res -J $(PROJECT_BUILD_PATH)/src -M $(PROJECT_BUILD_PATH)/AndroidManifest.xml -I $(ANDROID_HOME)/platforms/android-$(ANDROID_API_VERSION)/android.jar - -# Compile native_app_glue code as static library: obj/libnative_app_glue.a -compile_native_app_glue: - $(CC) -c $(RAYLIB_PATH)/src/external/android/native_app_glue/android_native_app_glue.c -o $(PROJECT_BUILD_PATH)/obj/native_app_glue.o $(CFLAGS) - $(AR) rcs $(PROJECT_BUILD_PATH)/obj/libnative_app_glue.a $(PROJECT_BUILD_PATH)/obj/native_app_glue.o - -# Compile project code into a shared library: lib/lib$(PROJECT_LIBRARY_NAME).so -compile_project_code: $(OBJS) - $(CC) -o $(PROJECT_BUILD_PATH)/lib/$(ANDROID_ARCH_NAME)/lib$(PROJECT_LIBRARY_NAME).so $(OBJS) -shared $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) - -# Compile all .c files required into object (.o) files -# NOTE: Those files will be linked into a shared library -$(PROJECT_BUILD_PATH)/obj/%.o:%.c - $(CC) -c $^ -o $@ $(INCLUDE_PATHS) $(CFLAGS) --sysroot=$(ANDROID_TOOLCHAIN)/sysroot - -# Compile project .java code into .class (Java bytecode) -compile_project_class: - $(JAVA_HOME)/bin/javac -verbose -source 1.7 -target 1.7 -d $(PROJECT_BUILD_PATH)/obj -bootclasspath $(JAVA_HOME)/jre/lib/rt.jar -classpath $(ANDROID_HOME)/platforms/android-$(ANDROID_API_VERSION)/android.jar;$(PROJECT_BUILD_PATH)/obj -sourcepath $(PROJECT_BUILD_PATH)/src $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/R.java $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java - -# Compile .class files into Dalvik executable bytecode (.dex) -# NOTE: Since Android 5.0, Dalvik interpreter (JIT) has been replaced by ART (AOT) -compile_project_class_dex: - $(ANDROID_BUILD_TOOLS)/dx --verbose --dex --output=$(PROJECT_BUILD_PATH)/bin/classes.dex $(PROJECT_BUILD_PATH)/obj - -# Create Android APK package: bin/$(PROJECT_NAME).unsigned.apk -# NOTE: Requires compiled classes.dex and lib$(PROJECT_LIBRARY_NAME).so -# NOTE: Use -A resources to define additional directory in which to find raw asset files -create_project_apk_package: - $(ANDROID_BUILD_TOOLS)/aapt package -f -M $(PROJECT_BUILD_PATH)/AndroidManifest.xml -S $(PROJECT_BUILD_PATH)/res -A $(PROJECT_BUILD_PATH)/assets -I $(ANDROID_HOME)/platforms/android-$(ANDROID_API_VERSION)/android.jar -F $(PROJECT_BUILD_PATH)/bin/$(PROJECT_NAME).unsigned.apk $(PROJECT_BUILD_PATH)/bin - cd $(PROJECT_BUILD_PATH) && $(ANDROID_BUILD_TOOLS)/aapt add bin/$(PROJECT_NAME).unsigned.apk lib/$(ANDROID_ARCH_NAME)/lib$(PROJECT_LIBRARY_NAME).so $(PROJECT_SHARED_LIBS) - -# Create signed APK package using generated Key: bin/$(PROJECT_NAME).signed.apk -sign_project_apk_package: - $(JAVA_HOME)/bin/jarsigner -keystore $(PROJECT_BUILD_PATH)/$(PROJECT_NAME).keystore -storepass $(APP_KEYSTORE_PASS) -keypass $(APP_KEYSTORE_PASS) -signedjar $(PROJECT_BUILD_PATH)/bin/$(PROJECT_NAME).signed.apk $(PROJECT_BUILD_PATH)/bin/$(PROJECT_NAME).unsigned.apk $(PROJECT_NAME)Key - -# Create zip-aligned APK package: $(PROJECT_NAME).apk -zipalign_project_apk_package: - $(ANDROID_BUILD_TOOLS)/zipalign -f 4 $(PROJECT_BUILD_PATH)/bin/$(PROJECT_NAME).signed.apk $(PROJECT_NAME).apk - -# Install $(PROJECT_NAME).apk to default emulator/device -# NOTE: Use -e (emulator) or -d (device) parameters if required -install: - $(ANDROID_PLATFORM_TOOLS)/adb install --abi $(ANDROID_ARCH_NAME) -rds $(PROJECT_NAME).apk - -# Check supported ABI for the device (armeabi-v7a, arm64-v8a, x86, x86_64) -check_device_abi: - $(ANDROID_PLATFORM_TOOLS)/adb shell getprop ro.product.cpu.abi - -# Monitorize output log coming from device, only raylib tag -logcat: - $(ANDROID_PLATFORM_TOOLS)/adb logcat -c - $(ANDROID_PLATFORM_TOOLS)/adb logcat raylib:V *:S - -# Install and monitorize $(PROJECT_NAME).apk to default emulator/device -deploy: - $(ANDROID_PLATFORM_TOOLS)/adb install -r $(PROJECT_NAME).apk - $(ANDROID_PLATFORM_TOOLS)/adb logcat -c - $(ANDROID_PLATFORM_TOOLS)/adb logcat raylib:V *:S - -#$(ANDROID_PLATFORM_TOOLS)/adb logcat *:W - -# Clean everything -clean: - del $(PROJECT_BUILD_PATH)\* /f /s /q - rmdir $(PROJECT_BUILD_PATH) /s /q - @echo Cleaning done diff --git a/projects/4coder/main.c b/projects/4coder/main.c deleted file mode 100644 index 78e1519cb..000000000 --- a/projects/4coder/main.c +++ /dev/null @@ -1,40 +0,0 @@ -#include -#include "raylib.h" - -int main() -{ - int screenWidth = 800; - int screenHeight = 450; - - InitWindow(screenWidth, screenHeight, "raylib"); - - Camera cam; - cam.position = (Vector3){ 0.0f, 10.0f, 8.f }; - cam.target = (Vector3){ 0.0f, 0.0f, 0.0f }; - cam.up = (Vector3){ 0.0f, 1.f, 0.0f }; - cam.fovy = 60.0f; - - Vector3 cubePos = { 0.0f, 0.0f, 0.0f }; - - SetTargetFPS(60); - - while (!WindowShouldClose()) - { - cam.position.x = sin(GetTime())*10.0f; - cam.position.z = cos(GetTime())*10.0f; - - BeginDrawing(); - ClearBackground(RAYWHITE); - BeginMode3D(cam); - DrawCube(cubePos, 2.f, 2.f, 2.f, RED); - DrawCubeWires(cubePos, 2.f, 2.f, 2.f, MAROON); - DrawGrid(10, 1.f); - EndMode3D(); - DrawText("This is a raylib example", 10, 40, 20, DARKGRAY); - DrawFPS(10, 10); - EndDrawing(); - } - - CloseWindow(); - return 0; -} diff --git a/projects/4coder/project.4coder b/projects/4coder/project.4coder deleted file mode 100644 index 568de79bd..000000000 --- a/projects/4coder/project.4coder +++ /dev/null @@ -1,54 +0,0 @@ -version(1); - -project_name = "raylib-example"; - -patterns = { -"*.cpp", -"*.c", -"*.h", -"*.bat", -"*.sh", -"*.4coder", -"Makefile", -}; - -blacklist_patterns = { -".*", -}; - -load_paths = { - { { {".", .relative = true, .recursive = true, } }, .os = "win" }, - { { {".", .relative = true, .recursive = true, } }, .os = "linux" }, - { { {".", .relative = true, .recursive = true, } }, .os = "mac" }, -}; - -command_list = { - { .name = "clean", - .out = "*clean*", .footer_panel = true, .save_dirty_files = false, .cursor_at_end = true, - .cmd = { - {"mingw32-make clean", .os = "win"}, - {"make clean", .os = "linux"}, - {"make clean", .os = "mac"}, - }, - }, - { .name = "build", - .out = "*compile*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, - .cmd = { - {"mingw32-make", .os = "win"}, - {"make", .os = "linux"}, - {"make", .os = "mac"}, - }, - }, - { .name = "run", - .out = "*run*", .footer_panel = true, .save_dirty_files = false, .cursor_at_end = true, - .cmd = { - {".\game.exe", .os = "win"}, - {"./game", .os = "linux"}, - {"./game", .os = "mac"}, - }, - }, -}; - -fkey_command[3] = "clean"; -fkey_command[4] = "build"; -fkey_command[5] = "run"; diff --git a/projects/README.md b/projects/README.md index 2758cb86e..b1f48cdf2 100644 --- a/projects/README.md +++ b/projects/README.md @@ -4,15 +4,14 @@ This folder contains raylib templates for some common IDEs. IDE | Platform(s) | Source | Example(s) ----| ------------| :-------: | :-----: -[4coder](http://4coder.net/) | Windows | ❌ | ✔️ [Builder](https://wiki.gnome.org/Apps/Builder) | Linux | ❌ | ✔️ [CMake](https://cmake.org/) | Windows, Linux, macOS, Web | ✔️ | ✔️ [CodeBlocks](http://www.codeblocks.org/) | Windows, Linux, macOS | ❌ | ✔️ [Geany](https://www.geany.org/) | Windows, Linux | ✔️ | ✔️ -[Notepad++](https://notepad-plus-plus.org/) | Windows | ✔️ | ✔️ +[Notepad++](https://notepad-plus-plus.org/) | Windows, Web | ✔️ | ✔️ [SublimeText](https://www.sublimetext.com/) | Windows, Linux, macOS | ✔️ | ✔️ -[VS2019](https://www.visualstudio.com) | Windows | ✔️ | ✔️ -[VSCode](https://code.visualstudio.com/) | Windows, macOS | ❌ | ✔️ +[VS2022](https://www.visualstudio.com) | Windows | ✔️ | ✔️ +[VSCode](https://code.visualstudio.com/) | Windows, Linux, macOS | ❌ | ✔️ [Zig](https://ziglang.org) | Windows, Linux, macOS, Web | ✔️ | ✔️ scripts | Windows, Linux, macOS | ✔️ | ✔️ diff --git a/projects/VS2019-Android/raylib_android.sln b/projects/VS2019-Android/raylib_android.sln deleted file mode 100644 index ec1880c0e..000000000 --- a/projects/VS2019-Android/raylib_android.sln +++ /dev/null @@ -1,75 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.31702.278 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "raylib_android", "raylib_android", "{5C24BC76-8848-40EA-9BBB-A544648D8D5B}" -EndProject -Project("{39E2626F-3545-4960-A6E8-258AD8476CE5}") = "raylib_android.Packaging", "raylib_android\raylib_android.Packaging\raylib_android.Packaging.androidproj", "{B2231F0D-52DA-4C55-8998-5886F766553C}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "raylib_android.NativeActivity", "raylib_android\raylib_android.NativeActivity\raylib_android.NativeActivity.vcxproj", "{BFB31759-4FCA-4503-BC7C-A97F705EFDB2}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|ARM = Debug|ARM - Debug|ARM64 = Debug|ARM64 - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|ARM = Release|ARM - Release|ARM64 = Release|ARM64 - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {B2231F0D-52DA-4C55-8998-5886F766553C}.Debug|ARM.ActiveCfg = Debug|ARM - {B2231F0D-52DA-4C55-8998-5886F766553C}.Debug|ARM.Build.0 = Debug|ARM - {B2231F0D-52DA-4C55-8998-5886F766553C}.Debug|ARM.Deploy.0 = Debug|ARM - {B2231F0D-52DA-4C55-8998-5886F766553C}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {B2231F0D-52DA-4C55-8998-5886F766553C}.Debug|ARM64.Build.0 = Debug|ARM64 - {B2231F0D-52DA-4C55-8998-5886F766553C}.Debug|ARM64.Deploy.0 = Debug|ARM64 - {B2231F0D-52DA-4C55-8998-5886F766553C}.Debug|x64.ActiveCfg = Debug|x64 - {B2231F0D-52DA-4C55-8998-5886F766553C}.Debug|x64.Build.0 = Debug|x64 - {B2231F0D-52DA-4C55-8998-5886F766553C}.Debug|x64.Deploy.0 = Debug|x64 - {B2231F0D-52DA-4C55-8998-5886F766553C}.Debug|x86.ActiveCfg = Debug|x86 - {B2231F0D-52DA-4C55-8998-5886F766553C}.Debug|x86.Build.0 = Debug|x86 - {B2231F0D-52DA-4C55-8998-5886F766553C}.Debug|x86.Deploy.0 = Debug|x86 - {B2231F0D-52DA-4C55-8998-5886F766553C}.Release|ARM.ActiveCfg = Release|ARM - {B2231F0D-52DA-4C55-8998-5886F766553C}.Release|ARM.Build.0 = Release|ARM - {B2231F0D-52DA-4C55-8998-5886F766553C}.Release|ARM.Deploy.0 = Release|ARM - {B2231F0D-52DA-4C55-8998-5886F766553C}.Release|ARM64.ActiveCfg = Release|ARM64 - {B2231F0D-52DA-4C55-8998-5886F766553C}.Release|ARM64.Build.0 = Release|ARM64 - {B2231F0D-52DA-4C55-8998-5886F766553C}.Release|ARM64.Deploy.0 = Release|ARM64 - {B2231F0D-52DA-4C55-8998-5886F766553C}.Release|x64.ActiveCfg = Release|x64 - {B2231F0D-52DA-4C55-8998-5886F766553C}.Release|x64.Build.0 = Release|x64 - {B2231F0D-52DA-4C55-8998-5886F766553C}.Release|x64.Deploy.0 = Release|x64 - {B2231F0D-52DA-4C55-8998-5886F766553C}.Release|x86.ActiveCfg = Release|x86 - {B2231F0D-52DA-4C55-8998-5886F766553C}.Release|x86.Build.0 = Release|x86 - {B2231F0D-52DA-4C55-8998-5886F766553C}.Release|x86.Deploy.0 = Release|x86 - {BFB31759-4FCA-4503-BC7C-A97F705EFDB2}.Debug|ARM.ActiveCfg = Debug|ARM - {BFB31759-4FCA-4503-BC7C-A97F705EFDB2}.Debug|ARM.Build.0 = Debug|ARM - {BFB31759-4FCA-4503-BC7C-A97F705EFDB2}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {BFB31759-4FCA-4503-BC7C-A97F705EFDB2}.Debug|ARM64.Build.0 = Debug|ARM64 - {BFB31759-4FCA-4503-BC7C-A97F705EFDB2}.Debug|x64.ActiveCfg = Debug|x64 - {BFB31759-4FCA-4503-BC7C-A97F705EFDB2}.Debug|x64.Build.0 = Debug|x64 - {BFB31759-4FCA-4503-BC7C-A97F705EFDB2}.Debug|x86.ActiveCfg = Debug|x86 - {BFB31759-4FCA-4503-BC7C-A97F705EFDB2}.Debug|x86.Build.0 = Debug|x86 - {BFB31759-4FCA-4503-BC7C-A97F705EFDB2}.Release|ARM.ActiveCfg = Release|ARM - {BFB31759-4FCA-4503-BC7C-A97F705EFDB2}.Release|ARM.Build.0 = Release|ARM - {BFB31759-4FCA-4503-BC7C-A97F705EFDB2}.Release|ARM64.ActiveCfg = Release|ARM64 - {BFB31759-4FCA-4503-BC7C-A97F705EFDB2}.Release|ARM64.Build.0 = Release|ARM64 - {BFB31759-4FCA-4503-BC7C-A97F705EFDB2}.Release|x64.ActiveCfg = Release|x64 - {BFB31759-4FCA-4503-BC7C-A97F705EFDB2}.Release|x64.Build.0 = Release|x64 - {BFB31759-4FCA-4503-BC7C-A97F705EFDB2}.Release|x86.ActiveCfg = Release|x86 - {BFB31759-4FCA-4503-BC7C-A97F705EFDB2}.Release|x86.Build.0 = Release|x86 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {B2231F0D-52DA-4C55-8998-5886F766553C} = {5C24BC76-8848-40EA-9BBB-A544648D8D5B} - {BFB31759-4FCA-4503-BC7C-A97F705EFDB2} = {5C24BC76-8848-40EA-9BBB-A544648D8D5B} - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {B7ED0AA6-6B00-40AC-BF71-526D5BEEFC78} - EndGlobalSection -EndGlobal diff --git a/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/android_native_app_glue.c b/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/android_native_app_glue.c deleted file mode 100644 index 0b8379423..000000000 --- a/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/android_native_app_glue.c +++ /dev/null @@ -1,437 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * лицензировано по лицензии Apache License, версия 2.0 ( "Лицензия"); - *этот файл можно использовать только в соответствии с лицензией. - *Копию лицензии можно получить на веб-сайте - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - *Если только не требуется в соответствии с применимым законодательством или согласовано в письменном виде, программное обеспечение - * распространяется в рамках лицензии на УСЛОВИЯХ "КАК ЕСТЬ", - * БЕЗ ГАРАНТИЙ И УСЛОВИЙ ЛЮБОГО РОДА, явно выраженных и подразумеваемых. - * См. лицензию для получения информации об определенных разрешениях по использованию языка и - * ограничениях в рамках лицензии. - * - */ - -#include - -#include -#include -#include -#include -#include - -#include "android_native_app_glue.h" -#include - -#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "threaded_app", __VA_ARGS__)) -#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, "threaded_app", __VA_ARGS__)) - -/* Для отладочных построений необходимо всегда включать трассировку отладки в этой библиотеке*/ -#ifndef NDEBUG -# define LOGV(...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, "threaded_app", __VA_ARGS__)) -#else -# define LOGV(...) ((void)0) -#endif - -static void free_saved_state(struct android_app* android_app) { - pthread_mutex_lock(&android_app->mutex); - if (android_app->savedState != NULL) { - free(android_app->savedState); - android_app->savedState = NULL; - android_app->savedStateSize = 0; - } - pthread_mutex_unlock(&android_app->mutex); -} - -int8_t android_app_read_cmd(struct android_app* android_app) { - int8_t cmd; - if (read(android_app->msgread, &cmd, sizeof(cmd)) == sizeof(cmd)) { - switch (cmd) { - case APP_CMD_SAVE_STATE: - free_saved_state(android_app); - break; - } - return cmd; - } else { - LOGE("No data on command pipe!"); - } - return -1; -} - -static void print_cur_config(struct android_app* android_app) { - char lang[2], country[2]; - AConfiguration_getLanguage(android_app->config, lang); - AConfiguration_getCountry(android_app->config, country); - - LOGV("Config: mcc=%d mnc=%d lang=%c%c cnt=%c%c orien=%d touch=%d dens=%d " - "keys=%d nav=%d keysHid=%d navHid=%d sdk=%d size=%d long=%d " - "modetype=%d modenight=%d", - AConfiguration_getMcc(android_app->config), - AConfiguration_getMnc(android_app->config), - lang[0], lang[1], country[0], country[1], - AConfiguration_getOrientation(android_app->config), - AConfiguration_getTouchscreen(android_app->config), - AConfiguration_getDensity(android_app->config), - AConfiguration_getKeyboard(android_app->config), - AConfiguration_getNavigation(android_app->config), - AConfiguration_getKeysHidden(android_app->config), - AConfiguration_getNavHidden(android_app->config), - AConfiguration_getSdkVersion(android_app->config), - AConfiguration_getScreenSize(android_app->config), - AConfiguration_getScreenLong(android_app->config), - AConfiguration_getUiModeType(android_app->config), - AConfiguration_getUiModeNight(android_app->config)); -} - -void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd) { - switch (cmd) { - case APP_CMD_INPUT_CHANGED: - LOGV("APP_CMD_INPUT_CHANGED\n"); - pthread_mutex_lock(&android_app->mutex); - if (android_app->inputQueue != NULL) { - AInputQueue_detachLooper(android_app->inputQueue); - } - android_app->inputQueue = android_app->pendingInputQueue; - if (android_app->inputQueue != NULL) { - LOGV("Attaching input queue to looper"); - AInputQueue_attachLooper(android_app->inputQueue, - android_app->looper, LOOPER_ID_INPUT, NULL, - &android_app->inputPollSource); - } - pthread_cond_broadcast(&android_app->cond); - pthread_mutex_unlock(&android_app->mutex); - break; - - case APP_CMD_INIT_WINDOW: - LOGV("APP_CMD_INIT_WINDOW\n"); - pthread_mutex_lock(&android_app->mutex); - android_app->window = android_app->pendingWindow; - pthread_cond_broadcast(&android_app->cond); - pthread_mutex_unlock(&android_app->mutex); - break; - - case APP_CMD_TERM_WINDOW: - LOGV("APP_CMD_TERM_WINDOW\n"); - pthread_cond_broadcast(&android_app->cond); - break; - - case APP_CMD_RESUME: - case APP_CMD_START: - case APP_CMD_PAUSE: - case APP_CMD_STOP: - LOGV("activityState=%d\n", cmd); - pthread_mutex_lock(&android_app->mutex); - android_app->activityState = cmd; - pthread_cond_broadcast(&android_app->cond); - pthread_mutex_unlock(&android_app->mutex); - break; - - case APP_CMD_CONFIG_CHANGED: - LOGV("APP_CMD_CONFIG_CHANGED\n"); - AConfiguration_fromAssetManager(android_app->config, - android_app->activity->assetManager); - print_cur_config(android_app); - break; - - case APP_CMD_DESTROY: - LOGV("APP_CMD_DESTROY\n"); - android_app->destroyRequested = 1; - break; - } -} - -void android_app_post_exec_cmd(struct android_app* android_app, int8_t cmd) { - switch (cmd) { - case APP_CMD_TERM_WINDOW: - LOGV("APP_CMD_TERM_WINDOW\n"); - pthread_mutex_lock(&android_app->mutex); - android_app->window = NULL; - pthread_cond_broadcast(&android_app->cond); - pthread_mutex_unlock(&android_app->mutex); - break; - - case APP_CMD_SAVE_STATE: - LOGV("APP_CMD_SAVE_STATE\n"); - pthread_mutex_lock(&android_app->mutex); - android_app->stateSaved = 1; - pthread_cond_broadcast(&android_app->cond); - pthread_mutex_unlock(&android_app->mutex); - break; - - case APP_CMD_RESUME: - free_saved_state(android_app); - break; - } -} - -static void android_app_destroy(struct android_app* android_app) { - LOGV("android_app_destroy!"); - free_saved_state(android_app); - pthread_mutex_lock(&android_app->mutex); - if (android_app->inputQueue != NULL) { - AInputQueue_detachLooper(android_app->inputQueue); - } - AConfiguration_delete(android_app->config); - android_app->destroyed = 1; - pthread_cond_broadcast(&android_app->cond); - pthread_mutex_unlock(&android_app->mutex); - // После этого нельзя изменять объект android_app. -} - -static void process_input(struct android_app* app, struct android_poll_source* source) { - AInputEvent* event = NULL; - while (AInputQueue_getEvent(app->inputQueue, &event) >= 0) { - LOGV("New input event: type=%d\n", AInputEvent_getType(event)); - if (AInputQueue_preDispatchEvent(app->inputQueue, event)) { - continue; - } - int32_t handled = 0; - if (app->onInputEvent != NULL) handled = app->onInputEvent(app, event); - AInputQueue_finishEvent(app->inputQueue, event, handled); - } -} - -static void process_cmd(struct android_app* app, struct android_poll_source* source) { - int8_t cmd = android_app_read_cmd(app); - android_app_pre_exec_cmd(app, cmd); - if (app->onAppCmd != NULL) app->onAppCmd(app, cmd); - android_app_post_exec_cmd(app, cmd); -} - -static void* android_app_entry(void* param) { - struct android_app* android_app = (struct android_app*)param; - - android_app->config = AConfiguration_new(); - AConfiguration_fromAssetManager(android_app->config, android_app->activity->assetManager); - - print_cur_config(android_app); - - android_app->cmdPollSource.id = LOOPER_ID_MAIN; - android_app->cmdPollSource.app = android_app; - android_app->cmdPollSource.process = process_cmd; - android_app->inputPollSource.id = LOOPER_ID_INPUT; - android_app->inputPollSource.app = android_app; - android_app->inputPollSource.process = process_input; - - ALooper* looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS); - ALooper_addFd(looper, android_app->msgread, LOOPER_ID_MAIN, ALOOPER_EVENT_INPUT, NULL, - &android_app->cmdPollSource); - android_app->looper = looper; - - pthread_mutex_lock(&android_app->mutex); - android_app->running = 1; - pthread_cond_broadcast(&android_app->cond); - pthread_mutex_unlock(&android_app->mutex); - - android_main(android_app); - - android_app_destroy(android_app); - return NULL; -} - -// -------------------------------------------------------------------- -// Взаимодействие NativeАctivity (вызванное из основного потока) -// -------------------------------------------------------------------- - -static struct android_app* android_app_create(ANativeActivity* activity, - void* savedState, size_t savedStateSize) { - struct android_app* android_app = (struct android_app*)malloc(sizeof(struct android_app)); - memset(android_app, 0, sizeof(struct android_app)); - android_app->activity = activity; - - pthread_mutex_init(&android_app->mutex, NULL); - pthread_cond_init(&android_app->cond, NULL); - - if (savedState != NULL) { - android_app->savedState = malloc(savedStateSize); - android_app->savedStateSize = savedStateSize; - memcpy(android_app->savedState, savedState, savedStateSize); - } - - int msgpipe[2]; - if (pipe(msgpipe)) { - LOGE("could not create pipe: %s", strerror(errno)); - return NULL; - } - android_app->msgread = msgpipe[0]; - android_app->msgwrite = msgpipe[1]; - - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - pthread_create(&android_app->thread, &attr, android_app_entry, android_app); - - // Дождитесь запуска потока. - pthread_mutex_lock(&android_app->mutex); - while (!android_app->running) { - pthread_cond_wait(&android_app->cond, &android_app->mutex); - } - pthread_mutex_unlock(&android_app->mutex); - - return android_app; -} - -static void android_app_write_cmd(struct android_app* android_app, int8_t cmd) { - if (write(android_app->msgwrite, &cmd, sizeof(cmd)) != sizeof(cmd)) { - LOGE("Failure writing android_app cmd: %s\n", strerror(errno)); - } -} - -static void android_app_set_input(struct android_app* android_app, AInputQueue* inputQueue) { - pthread_mutex_lock(&android_app->mutex); - android_app->pendingInputQueue = inputQueue; - android_app_write_cmd(android_app, APP_CMD_INPUT_CHANGED); - while (android_app->inputQueue != android_app->pendingInputQueue) { - pthread_cond_wait(&android_app->cond, &android_app->mutex); - } - pthread_mutex_unlock(&android_app->mutex); -} - -static void android_app_set_window(struct android_app* android_app, ANativeWindow* window) { - pthread_mutex_lock(&android_app->mutex); - if (android_app->pendingWindow != NULL) { - android_app_write_cmd(android_app, APP_CMD_TERM_WINDOW); - } - android_app->pendingWindow = window; - if (window != NULL) { - android_app_write_cmd(android_app, APP_CMD_INIT_WINDOW); - } - while (android_app->window != android_app->pendingWindow) { - pthread_cond_wait(&android_app->cond, &android_app->mutex); - } - pthread_mutex_unlock(&android_app->mutex); -} - -static void android_app_set_activity_state(struct android_app* android_app, int8_t cmd) { - pthread_mutex_lock(&android_app->mutex); - android_app_write_cmd(android_app, cmd); - while (android_app->activityState != cmd) { - pthread_cond_wait(&android_app->cond, &android_app->mutex); - } - pthread_mutex_unlock(&android_app->mutex); -} - -static void android_app_free(struct android_app* android_app) { - pthread_mutex_lock(&android_app->mutex); - android_app_write_cmd(android_app, APP_CMD_DESTROY); - while (!android_app->destroyed) { - pthread_cond_wait(&android_app->cond, &android_app->mutex); - } - pthread_mutex_unlock(&android_app->mutex); - - close(android_app->msgread); - close(android_app->msgwrite); - pthread_cond_destroy(&android_app->cond); - pthread_mutex_destroy(&android_app->mutex); - free(android_app); -} - -static void onDestroy(ANativeActivity* activity) { - LOGV("Destroy: %p\n", activity); - android_app_free((struct android_app*)activity->instance); -} - -static void onStart(ANativeActivity* activity) { - LOGV("Start: %p\n", activity); - android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_START); -} - -static void onResume(ANativeActivity* activity) { - LOGV("Resume: %p\n", activity); - android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_RESUME); -} - -static void* onSaveInstanceState(ANativeActivity* activity, size_t* outLen) { - struct android_app* android_app = (struct android_app*)activity->instance; - void* savedState = NULL; - - LOGV("SaveInstanceState: %p\n", activity); - pthread_mutex_lock(&android_app->mutex); - android_app->stateSaved = 0; - android_app_write_cmd(android_app, APP_CMD_SAVE_STATE); - while (!android_app->stateSaved) { - pthread_cond_wait(&android_app->cond, &android_app->mutex); - } - - if (android_app->savedState != NULL) { - savedState = android_app->savedState; - *outLen = android_app->savedStateSize; - android_app->savedState = NULL; - android_app->savedStateSize = 0; - } - - pthread_mutex_unlock(&android_app->mutex); - - return savedState; -} - -static void onPause(ANativeActivity* activity) { - LOGV("Pause: %p\n", activity); - android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_PAUSE); -} - -static void onStop(ANativeActivity* activity) { - LOGV("Stop: %p\n", activity); - android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_STOP); -} - -static void onConfigurationChanged(ANativeActivity* activity) { - struct android_app* android_app = (struct android_app*)activity->instance; - LOGV("ConfigurationChanged: %p\n", activity); - android_app_write_cmd(android_app, APP_CMD_CONFIG_CHANGED); -} - -static void onLowMemory(ANativeActivity* activity) { - struct android_app* android_app = (struct android_app*)activity->instance; - LOGV("LowMemory: %p\n", activity); - android_app_write_cmd(android_app, APP_CMD_LOW_MEMORY); -} - -static void onWindowFocusChanged(ANativeActivity* activity, int focused) { - LOGV("WindowFocusChanged: %p -- %d\n", activity, focused); - android_app_write_cmd((struct android_app*)activity->instance, - focused ? APP_CMD_GAINED_FOCUS : APP_CMD_LOST_FOCUS); -} - -static void onNativeWindowCreated(ANativeActivity* activity, ANativeWindow* window) { - LOGV("NativeWindowCreated: %p -- %p\n", activity, window); - android_app_set_window((struct android_app*)activity->instance, window); -} - -static void onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow* window) { - LOGV("NativeWindowDestroyed: %p -- %p\n", activity, window); - android_app_set_window((struct android_app*)activity->instance, NULL); -} - -static void onInputQueueCreated(ANativeActivity* activity, AInputQueue* queue) { - LOGV("InputQueueCreated: %p -- %p\n", activity, queue); - android_app_set_input((struct android_app*)activity->instance, queue); -} - -static void onInputQueueDestroyed(ANativeActivity* activity, AInputQueue* queue) { - LOGV("InputQueueDestroyed: %p -- %p\n", activity, queue); - android_app_set_input((struct android_app*)activity->instance, NULL); -} - -void ANativeActivity_onCreate(ANativeActivity* activity, - void* savedState, size_t savedStateSize) { - LOGV("Creating: %p\n", activity); - activity->callbacks->onDestroy = onDestroy; - activity->callbacks->onStart = onStart; - activity->callbacks->onResume = onResume; - activity->callbacks->onSaveInstanceState = onSaveInstanceState; - activity->callbacks->onPause = onPause; - activity->callbacks->onStop = onStop; - activity->callbacks->onConfigurationChanged = onConfigurationChanged; - activity->callbacks->onLowMemory = onLowMemory; - activity->callbacks->onWindowFocusChanged = onWindowFocusChanged; - activity->callbacks->onNativeWindowCreated = onNativeWindowCreated; - activity->callbacks->onNativeWindowDestroyed = onNativeWindowDestroyed; - activity->callbacks->onInputQueueCreated = onInputQueueCreated; - activity->callbacks->onInputQueueDestroyed = onInputQueueDestroyed; - - activity->instance = android_app_create(activity, savedState, savedStateSize); -} diff --git a/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/android_native_app_glue.h b/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/android_native_app_glue.h deleted file mode 100644 index c7269a444..000000000 --- a/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/android_native_app_glue.h +++ /dev/null @@ -1,344 +0,0 @@ -/* - * © 2010 The Android Open Source Project - * - * Лицензировано по лицензии Apache License, версия 2.0 ( "Лицензия"); - *этот файл можно использовать только в соответствии с лицензией. - *Копию лицензии можно получить на веб-сайте - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - *Если только не требуется в соответствии с применимым законодательством или согласовано в письменном виде, программное обеспечение - * распространяется в рамках лицензии на УСЛОВИЯХ "КАК ЕСТЬ", - * БЕЗ ГАРАНТИЙ И УСЛОВИЙ ЛЮБОГО РОДА, явно выраженных и подразумеваемых. - * См. лицензию для получения информации об определенных разрешениях по использованию языка и - * ограничениях в рамках лицензии. - * - */ - -#ifndef _ANDROID_NATIVE_APP_GLUE_H -#define _ANDROID_NATIVE_APP_GLUE_H - -#include -#include -#include - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Интерфейс NativeActivity, предоставленный , - * основан на наборе предоставленных приложением обратных вызовов, которые вызываются - *основным потоком действия при возникновении определенных событий. - * - * Это означает, что ни один из данных обратных вызовов _не_ _должен_ блокироваться, иначе - * существует риск принудительного закрытия приложения системой. Эта модель программирования - * прямая, простая, но имеет ограничения. - * - * Статическая библиотека threaded_native_app используется для обеспечения другой - * модели выполнения, в которой приложение может реализовать свой собственный цикл главного события - * в другом потоке вместо этого. Это работает так: - * - * 1/ Приложение должно предоставить функцию с именем android_main(), которая - * будет вызываться при создании действия в новом потоке, - * отличающемся от основного потока действия. - * - * 2/ android_main() получает указатель на допустимую структуру android_app, - * которая содержит ссылки на другие важные объекты, например экземпляр объекта - * ANativeActivity, где выполняется приложение. - * - * 3/ Объект android_app содержит экземпляр ALooper, который уже - * ожидает две важных вещи: - * - * - событий жизненного цикла действия (например, "pause", "resume"). См. объявления APP_CMD_XXX - * ниже. - * - * - входных событий, поступающих из очереди AInputQueue, присоединенной к действию. - * - * Каждое из этих событий соответствует идентификатору ALooper, возвращенному - * ALooper_pollOnce со значениями LOOPER_ID_MAIN и LOOPER_ID_INPUT, - *, соответственно. - * - * Ваше приложение может использовать тот же ALooper для прослушивания дополнительных - * дескрипторов файла. Они могут быть основаны либо на обратных вызовах, либо поступают с идентификаторами возврата, - * начинающимися с LOOPER_ID_USER. - * - * 4/ При получении события LOOPER_ID_MAIN или LOOPER_ID_INPUT - * возвращенные данные будут указывать на структуру android_poll_source. Для нее - * можно вызвать функцию process() и заполнить android_app->onAppCmd - * и android_app->onInputEvent, для того чтобы они вызывались для вашей собственной обработки - * события. - * - * Вместо этого можно вызвать функции нижнего уровня для чтения и обработки - * данных непосредственно... посмотрите на реализации process_cmd() и process_input() - * в приклеивании, чтобы выяснить, как это делается. - * - * См. пример "native-activity" в NDK с - * полной демонстрацией использования. Также посмотрите JavaDoc в NativeActivity. - */ - -struct android_app; - -/** - * Данные, связанные с ALooper fd, которые будут возвращаться как outData - * при готовности данных в этом источнике. - */ -struct android_poll_source { - // Идентификатор данного источника. Может быть LOOPER_ID_MAIN или - // LOOPER_ID_INPUT. - int32_t id; - - // android_app, с которым связан данный идентификатор. - struct android_app* app; - - // Функция, вызываемая для стандартной обработки данных из - // этого источника. - void (*process)(struct android_app* app, struct android_poll_source* source); -}; - -/** - * Это интерфейс стандартного кода приклеивания поточного - * приложения. В этой модели код приложения выполняется - * в своем собственном потоке, отдельном от основного потока процесса. - * Не требуется связь данного потока с ВМ Java - *, хотя это необходимо для выполнения вызовов JNI любых - * объектов Java. - */ -struct android_app { - // Приложение может поместить указатель на свой собственный объект состояния - // здесь, если нужно. - void* userData; - - // Введите здесь код функции для обработки основных команд приложения (APP_CMD_*) - void (*onAppCmd)(struct android_app* app, int32_t cmd); - - // Введите здесь код функции для обработки входных событий. Сейчас - // событие уже было предварительно отправлено и будет завершено при - // возврате. Верните 1, если событие обработано, 0 — для любой диспетчеризации - // по умолчанию. - int32_t (*onInputEvent)(struct android_app* app, AInputEvent* event); - - // Экземпляр объекта ANativeActivity, в котором выполняется это приложение. - ANativeActivity* activity; - - // Текущая конфигурация, в которой выполняется это приложение. - AConfiguration* config; - - // Это последнее сохраненное состояние экземпляра, предоставленное во время создания. - // Значение равно NULL, если состояния не было. Можно использовать это по мере необходимости; - // память останется доступной до вызова android_app_exec_cmd() для - // APP_CMD_RESUME, после чего она будет освобождена, а savedState получит значение NULL. - // Эти переменные необходимо изменять только при обработке APP_CMD_SAVE_STATE, - // когда их значения будут инициализироваться в NULL и можно будет выполнить malloc для - // состояния и поместить здесь информацию. В этом случае память будет - // освобождена позднее. - void* savedState; - size_t savedStateSize; - - // ALooper, связанный с потоком приложения. - ALooper* looper; - - // Если значение не равно NULL, то это входная очередь, из которой приложение будет - // получать входные события пользователя. - AInputQueue* inputQueue; - - // Если значение не равно NULL, то это поверхность окна, в котором приложение может рисовать. - ANativeWindow* window; - - // Текущий прямоугольник содержимого окна. Это область, в которой - // должно помещаться содержимое окна, чтобы его видел пользователь. - ARect contentRect; - - // Текущее состояние действия приложения. Может быть APP_CMD_START, - // APP_CMD_RESUME, APP_CMD_PAUSE или APP_CMD_STOP; см. ниже. - int activityState; - - // Значение не равно нулю, когда NativeActivity приложения - // разрушается и ожидает завершения потока приложения. - int destroyRequested; - - // ------------------------------------------------- - // Ниже показан "частная" реализация кода прилипания. - - pthread_mutex_t mutex; - pthread_cond_t cond; - - int msgread; - int msgwrite; - - pthread_t thread; - - struct android_poll_source cmdPollSource; - struct android_poll_source inputPollSource; - - int running; - int stateSaved; - int destroyed; - int redrawNeeded; - AInputQueue* pendingInputQueue; - ANativeWindow* pendingWindow; - ARect pendingContentRect; -}; - -enum { - /** - * Идентификатор данных Looper команд, поступающих из основного потока приложения, который - * возвращается как идентификатор от ALooper_pollOnce(). Данные для этого идентификатора - * являются указателем на структуру android_poll_source. - * Их можно извлечь и обработать с помощью android_app_read_cmd() - * и android_app_exec_cmd(). - */ - LOOPER_ID_MAIN = 1, - - /** - * Идентификатор данных Looper событий, поступающий из AInputQueue окна - * приложения, который возвращается как идентификатор из - * ALooper_pollOnce(). Данные этого идентификатора являются указателем на структуру - * android_poll_source. Их можно прочитать через объект inputQueue - * приложения android_app. - */ - LOOPER_ID_INPUT = 2, - - /** - * Запуск определяемых пользователем идентификаторов ALooper. - */ - LOOPER_ID_USER = 3, -}; - -enum { - /** - * Команда из основного потока: AInputQueue изменена. После обработки - * этой команды android_app->inputQueue будет обновлена в новую очередь - * (или NULL). - */ - APP_CMD_INPUT_CHANGED, - - /** - * Команда из основного потока: новое окно ANativeWindow готово к использованию. После - * получения этой команды окно android_app-> будет содержать новую поверхность - *окна. - */ - APP_CMD_INIT_WINDOW, - - /** - * Команда из основного потока: существующее окно ANativeWindow необходимо - * прекратить. После получения этой команды окно android_app->по-прежнему - * содержит существующее окно; после вызова android_app_exec_cmd - * оно получит значение NULL. - */ - APP_CMD_TERM_WINDOW, - - /** - * Команда из основного потока: текущее окно ANativeWindow изменило размер. - * Перерисуйте согласно новом размеру. - */ - APP_CMD_WINDOW_RESIZED, - - /** - * Команда из основного потока: системе необходимо, чтобы текущее окно ANativeWindow - * было перерисовано. Необходимо перерисовать окно перед ее передачей в - * android_app_exec_cmd(), чтобы избежать переходных сбоев рисования. - */ - APP_CMD_WINDOW_REDRAW_NEEDED, - - /** - * Команда из основного потока: область содержимого окна изменена - * таким образом, что из функционального ввода окно показывается или скрывается. Можно - * найти новый прямоугольник содержимого в android_app::contentRect. - */ - APP_CMD_CONTENT_RECT_CHANGED, - - /** - * Команда из основного потока: окно действия приложения получило - * фокус ввода. - */ - APP_CMD_GAINED_FOCUS, - - /** - * Команда из основного потока: окно действия приложения потеряло - * фокус ввода. - */ - APP_CMD_LOST_FOCUS, - - /** - * Команда из основного потока: изменена текущая конфигурация устройства. - */ - APP_CMD_CONFIG_CHANGED, - - /** - * Команда из основного потока: системе не хватает памяти. - * Попробуйте уменьшить использование памяти. - */ - APP_CMD_LOW_MEMORY, - - /** - * Команда из основного потока: действие приложения было запущено. - */ - APP_CMD_START, - - /** - * Команда из основного потока: действие приложения было возобновлено. - */ - APP_CMD_RESUME, - - /** - * Команда из основного потока: приложение должно создать новое сохраненное состояние - * для себя, чтобы восстанавливаться из него позднее в случае необходимости. Если вы сохранили состояние, - * выделите его с использованием malloc и поместите в android_app.savedState с - * размером android_app.savedStateSize. Память будет освобождена - * позднее. - */ - APP_CMD_SAVE_STATE, - - /** - * Команда из основного потока: пауза в действии приложения. - */ - APP_CMD_PAUSE, - - /** - * Команда из основного потока: действие приложения было остановлено. - */ - APP_CMD_STOP, - - /** - * Команда из основного потока: действие приложения уничтожается, - * и ожидает очистки потока приложения и выхода перед обработкой. - */ - APP_CMD_DESTROY, -}; - -/** - * Вызовите, когда ALooper_pollAll() возвращает LOOPER_ID_MAIN, при чтении следующего сообщения команды - *приложения. - */ -int8_t android_app_read_cmd(struct android_app* android_app); - -/** - * Вызовите с помощью команды, возвращенной android_app_read_cmd() для выполнения - * начальной предварительной обработки данной команды. Можно выполнить собственные - * действия для команды после вызова этой функции. - */ -void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd); - -/** - * Вызовите с помощью команды, возвращенной android_app_read_cmd(), для - * окончательной предварительной обработки данной команды. Необходимо завершить собственные - * действия с командой до вызова этой функции. - */ -void android_app_post_exec_cmd(struct android_app* android_app, int8_t cmd); - -/** - * Это функция, которую должен реализовать код приложения, представляет собой - * главный вход в приложение. - */ -extern void android_main(struct android_app* app); - -#ifdef __cplusplus -} -#endif - -#endif /* _ANDROID_NATIVE_APP_GLUE_H */ diff --git a/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/main.c b/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/main.c deleted file mode 100644 index dce3f503c..000000000 --- a/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/main.c +++ /dev/null @@ -1,64 +0,0 @@ -/******************************************************************************************* -* -* raylib [core] example - Basic window -* -* This example has been created using raylib 3.8 (www.raylib.com) -* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) -* -* Example contributed by (@) and reviewed by Ramon Santamaria (@raysan5) -* -* Copyright (c) 2021 (@) - -* Adapt for Visual Studio: Vadim Boev (Kronka Dev) -* -********************************************************************************************/ -#include "android_native_app_glue.h" - -#include "../../../../src/raylib.h" - -int main(void) -{ - // Initialization - //-------------------------------------------------------------------------------------- - const int screenWidth = 800; - const int screenHeight = 450; - - InitWindow(screenWidth, screenHeight, "raylib [core] example - basic window"); - - // TODO: Load resources / Initialize variables at this point - - SetTargetFPS(60); - //-------------------------------------------------------------------------------------- - - // Main game loop - while (!WindowShouldClose()) // Detect window close button or ESC key - { - // Update - //---------------------------------------------------------------------------------- - // TODO: Update variables / Implement example logic at this point - //---------------------------------------------------------------------------------- - - // Draw - //---------------------------------------------------------------------------------- - BeginDrawing(); - - ClearBackground(RAYWHITE); - - // TODO: Draw everything that requires to be drawn at this point: - - DrawText("Congrats! You created your first window!", 190, 200, 20, LIGHTGRAY); // Example - - EndDrawing(); - //---------------------------------------------------------------------------------- - } - - // De-Initialization - //-------------------------------------------------------------------------------------- - - // TODO: Unload all loaded resources at this point - - CloseWindow(); // Close window and OpenGL context - //-------------------------------------------------------------------------------------- - - return 0; -} diff --git a/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/raylib_android.NativeActivity.vcxproj b/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/raylib_android.NativeActivity.vcxproj deleted file mode 100644 index 6b7b5a085..000000000 --- a/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/raylib_android.NativeActivity.vcxproj +++ /dev/null @@ -1,226 +0,0 @@ - - - - - Debug - ARM - - - Release - ARM - - - Debug - ARM64 - - - Release - ARM64 - - - Debug - x64 - - - Release - x64 - - - Debug - x86 - - - Release - x86 - - - - {bfb31759-4fca-4503-bc7c-a97f705efdb2} - Android - raylib_android - en-US - 14.0 - Android - 3.0 - - - - DynamicLibrary - true - Clang_5_0 - - - DynamicLibrary - false - Clang_5_0 - - - DynamicLibrary - true - Clang_5_0 - - - DynamicLibrary - false - Clang_5_0 - - - DynamicLibrary - true - Clang_5_0 - android-29 - - - DynamicLibrary - false - Clang_5_0 - - - DynamicLibrary - true - Clang_5_0 - - - DynamicLibrary - false - Clang_5_0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - libmain - - - - - - - - - - - NotUsing - pch.h - CompileAsC - c99 - Default - CompileAsC - - - %(LibraryDependencies);EGL;GLESv2;log;android;c;m;raylib - ../../../../src/;%(AdditionalLibraryDirectories) - - - - - NotUsing - pch.h - CompileAsC - c99 - Default - CompileAsC - - - %(LibraryDependencies);GLESv1_CM;EGL; - .;%(AdditionalLibraryDirectories) - - - - - Use - pch.h - CompileAsCpp - - - %(LibraryDependencies);GLESv1_CM;EGL; - - - - - Use - pch.h - CompileAsCpp - - - %(LibraryDependencies);GLESv1_CM;EGL; - - - - - Use - pch.h - CompileAsCpp - - - %(LibraryDependencies);GLESv1_CM;EGL; - - - - - Use - pch.h - CompileAsCpp - - - %(LibraryDependencies);GLESv1_CM;EGL; - - - - - Use - pch.h - CompileAsCpp - - - %(LibraryDependencies);GLESv1_CM;EGL; - - - - - Use - pch.h - CompileAsCpp - - - %(LibraryDependencies);GLESv1_CM;EGL; - - - - - - - - - - - - - \ No newline at end of file diff --git a/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/raylib_android.NativeActivity.vcxproj.filters b/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/raylib_android.NativeActivity.vcxproj.filters deleted file mode 100644 index e9a26e2dd..000000000 --- a/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/raylib_android.NativeActivity.vcxproj.filters +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/raylib_android.NativeActivity.vcxproj.user b/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/raylib_android.NativeActivity.vcxproj.user deleted file mode 100644 index 0f14913f3..000000000 --- a/projects/VS2019-Android/raylib_android/raylib_android.NativeActivity/raylib_android.NativeActivity.vcxproj.user +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/projects/VS2019-Android/raylib_android/raylib_android.Packaging/AndroidManifest.xml b/projects/VS2019-Android/raylib_android/raylib_android.Packaging/AndroidManifest.xml deleted file mode 100644 index 8d58d3756..000000000 --- a/projects/VS2019-Android/raylib_android/raylib_android.Packaging/AndroidManifest.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/projects/VS2019-Android/raylib_android/raylib_android.Packaging/build.xml b/projects/VS2019-Android/raylib_android/raylib_android.Packaging/build.xml deleted file mode 100644 index 4dd78480d..000000000 --- a/projects/VS2019-Android/raylib_android/raylib_android.Packaging/build.xml +++ /dev/null @@ -1,90 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/projects/VS2019-Android/raylib_android/raylib_android.Packaging/project.properties b/projects/VS2019-Android/raylib_android/raylib_android.Packaging/project.properties deleted file mode 100644 index 3c100376c..000000000 --- a/projects/VS2019-Android/raylib_android/raylib_android.Packaging/project.properties +++ /dev/null @@ -1,3 +0,0 @@ -# Project target -target=$(androidapilevel) -# Provide path to the directory where prebuilt external jar files are by setting jar.libs.dir= diff --git a/projects/VS2019-Android/raylib_android/raylib_android.Packaging/raylib_android.Packaging.androidproj b/projects/VS2019-Android/raylib_android/raylib_android.Packaging/raylib_android.Packaging.androidproj deleted file mode 100644 index 030d71747..000000000 --- a/projects/VS2019-Android/raylib_android/raylib_android.Packaging/raylib_android.Packaging.androidproj +++ /dev/null @@ -1,134 +0,0 @@ - - - - - Debug - ARM - - - Release - ARM - - - Debug - ARM64 - - - Release - ARM64 - - - Debug - x64 - - - Release - x64 - - - Debug - x86 - - - Release - x86 - - - - raylib_android - 14.0 - 1.0 - {b2231f0d-52da-4c55-8998-5886f766553c} - - - - true - Application - - - false - Application - - - true - Application - - - false - Application - - - true - Application - - - false - Application - - - true - Application - - - false - Application - - - - - - - - - $(RootNamespace) - - - - - $(RootNamespace) - - - - - $(RootNamespace) - - - - - $(RootNamespace) - - - - - $(RootNamespace) - - - - - $(RootNamespace) - - - - - $(RootNamespace) - - - - - $(RootNamespace) - - - - - - - - - - - {bfb31759-4fca-4503-bc7c-a97f705efdb2} - - - - - \ No newline at end of file diff --git a/projects/VS2019-Android/raylib_android/raylib_android.Packaging/res/values/strings.xml b/projects/VS2019-Android/raylib_android/raylib_android.Packaging/res/values/strings.xml deleted file mode 100644 index 98afc4675..000000000 --- a/projects/VS2019-Android/raylib_android/raylib_android.Packaging/res/values/strings.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - raylib_android.Packaging - diff --git a/src/external/rlsw.h b/src/external/rlsw.h index bb6e11679..db10bf2b4 100644 --- a/src/external/rlsw.h +++ b/src/external/rlsw.h @@ -3909,7 +3909,6 @@ static void sw_immediate_set_color(const float color[4]) RLSW.primitive.color[2] = color[2]; RLSW.primitive.color[3] = color[3]; - RLSW.primitive.hasColorAlpha |= (color[3] < 1.0f); } static void sw_immediate_set_texcoord(const float texcoord[2]) @@ -3948,6 +3947,9 @@ static void sw_immediate_push_vertex(const float position[4]) for (int i = 0; i < 4; i++) vertex->color[i] = RLSW.primitive.color[i]; for (int i = 0; i < 2; i++) vertex->texcoord[i] = RLSW.primitive.texcoord[i]; + // Track whether any vertex in this primitive has alpha < 1.0 + RLSW.primitive.hasColorAlpha |= (vertex->color[3] < 1.0f); + // Immediate rendering of the primitive if the required number is reached if (RLSW.primitive.vertexCount == SW_PRIMITIVE_VERTEX_COUNT[RLSW.drawMode]) { @@ -4307,8 +4309,8 @@ void swScissor(int x, int y, int width, int height) RLSW.scClipMin[0] = (2.0f*(float)RLSW.scMin[0]/(float)RLSW.vpSize[0]) - 1.0f; RLSW.scClipMax[0] = (2.0f*(float)RLSW.scMax[0]/(float)RLSW.vpSize[0]) - 1.0f; - RLSW.scClipMax[1] = 1.0f - (2.0f*(float)RLSW.scMin[1]/(float)RLSW.vpSize[1]); - RLSW.scClipMin[1] = 1.0f - (2.0f*(float)RLSW.scMax[1]/(float)RLSW.vpSize[1]); + RLSW.scClipMin[1] = (2.0f*(float)RLSW.scMin[1]/(float)RLSW.vpSize[1]) - 1.0f; + RLSW.scClipMax[1] = (2.0f*(float)RLSW.scMax[1]/(float)RLSW.vpSize[1]) - 1.0f; } void swClearColor(float r, float g, float b, float a) diff --git a/src/external/tinyobj_loader_c.h b/src/external/tinyobj_loader_c.h index 88b2acbdc..8d077d665 100644 --- a/src/external/tinyobj_loader_c.h +++ b/src/external/tinyobj_loader_c.h @@ -1020,7 +1020,12 @@ static int parseLine(Command *command, const char *p, unsigned int p_len, int triangulate) { char linebuf[4096]; const char *token; - assert(p_len < 4095); + + // @raysan5: + // WARNING: If -DNDEBUG is set when compiling, assertions will not + // be present in the compiled binary, replacing by a runtime check + //assert(p_len < 4095); + if (p_len > 4095) return 0; memcpy(linebuf, p, p_len); linebuf[p_len] = '\0'; @@ -1102,8 +1107,12 @@ static int parseLine(Command *command, const char *p, unsigned int p_len, tinyobj_vertex_index_t i1; tinyobj_vertex_index_t i2 = f[1]; - assert(3 * num_f < TINYOBJ_MAX_FACES_PER_F_LINE); - + // @raysan5: + // WARNING: If -DNDEBUG is set when compiling, assertions will not + // be present in the compiled binary, replacing by a runtime check + //assert(3 * num_f < TINYOBJ_MAX_FACES_PER_F_LINE); + if (3*num_f > TINYOBJ_MAX_FACES_PER_F_LINE) return 0; + for (k = 2; k < num_f; k++) { i1 = i2; i2 = f[k]; @@ -1119,7 +1128,13 @@ static int parseLine(Command *command, const char *p, unsigned int p_len, } else { unsigned int k = 0; - assert(num_f < TINYOBJ_MAX_FACES_PER_F_LINE); + + // @raysan5: + // WARNING: If -DNDEBUG is set when compiling, assertions will not + // be present in the compiled binary, replacing by a runtime check + //assert(num_f < TINYOBJ_MAX_FACES_PER_F_LINE); + if (num_f > TINYOBJ_MAX_FACES_PER_F_LINE) return 0; + for (k = 0; k < num_f; k++) { command->f[k] = f[k]; } diff --git a/src/platforms/rcore_android.c b/src/platforms/rcore_android.c index 78abe9ed6..7fb080153 100644 --- a/src/platforms/rcore_android.c +++ b/src/platforms/rcore_android.c @@ -663,13 +663,22 @@ double GetTime(void) } // Open URL with default system browser (if available) -// NOTE: This function is only safe to use if the provided URL is safe -// A user could craft a malicious string performing another action -// Avoid calling this function with user input non-validated strings +// WARNING: This function is only safe to use if you control the URL given, +// a user could craft a malicious string to perform and undesired action +// NOTE: Some safety checks have been added to mitigate security issues void OpenURL(const char *url) { // Security check to (partially) avoid malicious code - if (strchr(url, '\'') != NULL) TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'] character"); + if ((strchr(url, '\'') != NULL) || (strchr(url, '\"') != NULL)) + { + // Filter characters: ' and " + TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'\"] characters"); + } + else if ((strncmp(url, "http://", 7) != 0) && (strncmp(url, "https://", 8) != 0)) + { + // Only allow URL starting with "http://" or "https://" protocols + TRACELOG(LOG_WARNING, "SYSTEM: Provided URL must start with 'http://' or 'https://' protocols"); + } else { JNIEnv *env = NULL; @@ -717,7 +726,6 @@ void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float d void SetMousePosition(int x, int y) { CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y }; - CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition; } // Set mouse cursor diff --git a/src/platforms/rcore_desktop_glfw.c b/src/platforms/rcore_desktop_glfw.c index 64596b376..934815c0f 100644 --- a/src/platforms/rcore_desktop_glfw.c +++ b/src/platforms/rcore_desktop_glfw.c @@ -1181,17 +1181,25 @@ double GetTime(void) } // Open URL with default system browser (if available) -// NOTE: This function is only safe to use if you control the URL given -// A user could craft a malicious string performing another action -// Only call this function yourself not with user input or make sure to check the string yourself -// REF: https://github.com/raysan5/raylib/issues/686 +// WARNING: This function is only safe to use if you control the URL given, +// a user could craft a malicious string to perform and undesired action +// NOTE: Some safety checks have been added to mitigate security issues void OpenURL(const char *url) { // Security check to (partially) avoid malicious code - if (strchr(url, '\'') != NULL) TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'] character"); - else + if ((strchr(url, '\'') != NULL) || (strchr(url, '\"') != NULL)) { - char *cmd = (char *)RL_CALLOC(strlen(url) + 32, sizeof(char)); + // Filter characters: ' and " + TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'\"] characters"); + } + else if ((strncmp(url, "http://", 7) != 0) && (strncmp(url, "https://", 8) != 0)) + { + // Only allow URL starting with "http://" or "https://" protocols + TRACELOG(LOG_WARNING, "SYSTEM: Provided URL must start with 'http://' or 'https://' protocols"); + } + else + { + char *cmd = (char *)RL_CALLOC(strlen(url) + 16, sizeof(char)); #if defined(_WIN32) sprintf(cmd, "explorer \"%s\"", url); #endif @@ -1201,7 +1209,9 @@ void OpenURL(const char *url) #if defined(__APPLE__) sprintf(cmd, "open '%s'", url); #endif + // TODO: Replace system() call by custom process int result = system(cmd); + if (result == -1) TRACELOG(LOG_WARNING, "OpenURL() child process could not be created"); RL_FREE(cmd); } @@ -1227,7 +1237,6 @@ void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float d void SetMousePosition(int x, int y) { CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y }; - CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition; // NOTE: emscripten not implemented glfwSetCursorPos(platform.handle, CORE.Input.Mouse.currentPosition.x, CORE.Input.Mouse.currentPosition.y); @@ -1316,7 +1325,7 @@ void PollInputEvents(void) // Register previous gamepad states for (int k = 0; k < MAX_GAMEPAD_BUTTONS; k++) CORE.Input.Gamepad.previousButtonState[i][k] = CORE.Input.Gamepad.currentButtonState[i][k]; - // Get current gamepad state + // Get current gamepad state using internal GLFW mapping, instead of the immediate joystick API // NOTE: There is no callback available, getting it manually GLFWgamepadstate state = { 0 }; int result = glfwGetGamepadState(i, &state); // This remaps all gamepads so they have their buttons mapped like an xbox controller @@ -1331,7 +1340,7 @@ void PollInputEvents(void) for (int k = 0; (buttons != NULL) && (k < MAX_GAMEPAD_BUTTONS); k++) { - int button = -1; // GamepadButton enum values assigned + int button = -1; // GamepadButton enum values assigned switch (k) { @@ -1357,7 +1366,7 @@ void PollInputEvents(void) default: break; } - if (button != -1) // Check for valid button + if (button != -1) // Check for valid button { if (buttons[k] == GLFW_PRESS) { @@ -1399,10 +1408,10 @@ void PollInputEvents(void) if ((CORE.Window.eventWaiting) || (FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_MINIMIZED) && !FLAG_IS_SET(CORE.Window.flags, FLAG_WINDOW_ALWAYS_RUN))) { - glfwWaitEvents(); // Wait for in input events before continue (drawing is paused) + glfwWaitEvents(); // Wait for in input events before continue (drawing is paused) CORE.Time.previous = GetTime(); } - else glfwPollEvents(); // Poll input events: keyboard/mouse/window events (callbacks) -> Update keys state + else glfwPollEvents(); // Poll input events: keyboard/mouse/window events (callbacks) -> Update keys state CORE.Window.shouldClose = glfwWindowShouldClose(platform.handle); @@ -1683,6 +1692,14 @@ int InitPlatform(void) return -1; } +#if defined(__APPLE__) + // AppKit can constrain the requested window size to the visible work area during creation + int windowWidth = 0; + int windowHeight = 0; + glfwGetWindowSize(platform.handle, &windowWidth, &windowHeight); + if ((windowWidth > 0) && (windowHeight > 0)) CORE.Window.screen = (Size){ windowWidth, windowHeight }; +#endif + // NOTE: Not considering scale factor now, considered below CORE.Window.render.width = CORE.Window.screen.width; CORE.Window.render.height = CORE.Window.screen.height; @@ -1829,7 +1846,7 @@ int InitPlatform(void) { CORE.Input.Gamepad.ready[i] = true; CORE.Input.Gamepad.axisCount[i] = GLFW_GAMEPAD_AXIS_LAST + 1; - strncpy(CORE.Input.Gamepad.name[i], glfwGetJoystickName(i), MAX_GAMEPAD_NAME_LENGTH - 1); + snprintf(CORE.Input.Gamepad.name[i], MAX_GAMEPAD_NAME_LENGTH, "%s", glfwGetJoystickName(i)); } } //---------------------------------------------------------------------------- @@ -2044,7 +2061,7 @@ static void WindowDropCallback(GLFWwindow *window, int count, const char **paths for (unsigned int i = 0; i < CORE.Window.dropFileCount; i++) { CORE.Window.dropFilepaths[i] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char)); - strncpy(CORE.Window.dropFilepaths[i], paths[i], MAX_FILEPATH_LENGTH - 1); + snprintf(CORE.Window.dropFilepaths[i], MAX_FILEPATH_LENGTH, "%s", paths[i]); } } } @@ -2191,7 +2208,7 @@ static void JoystickCallback(int jid, int event) // WARNING: If glfwGetJoystickName() is longer than MAX_GAMEPAD_NAME_LENGTH, // only copy up to (MAX_GAMEPAD_NAME_LENGTH -1) to destination string memset(CORE.Input.Gamepad.name[jid], 0, MAX_GAMEPAD_NAME_LENGTH); - strncpy(CORE.Input.Gamepad.name[jid], glfwGetJoystickName(jid), MAX_GAMEPAD_NAME_LENGTH - 1); + snprintf(CORE.Input.Gamepad.name[jid], MAX_GAMEPAD_NAME_LENGTH, "%s", glfwGetJoystickName(jid)); } else if (event == GLFW_DISCONNECTED) { diff --git a/src/platforms/rcore_desktop_rgfw.c b/src/platforms/rcore_desktop_rgfw.c index 211917359..9907e8a60 100644 --- a/src/platforms/rcore_desktop_rgfw.c +++ b/src/platforms/rcore_desktop_rgfw.c @@ -486,14 +486,14 @@ static void RGFW_cb_dropfunc(const RGFW_event *e) CORE.Window.dropFilepaths = (char **)RL_CALLOC(1024, sizeof(char *)); CORE.Window.dropFilepaths[CORE.Window.dropFileCount] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char)); - strcpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], e->drop.value->data); + snprintf(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], MAX_FILEPATH_LENGTH, "%s", e->drop.value->data); CORE.Window.dropFileCount++; } else if (CORE.Window.dropFileCount < 1024) { CORE.Window.dropFilepaths[CORE.Window.dropFileCount] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char)); - strcpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], e->drop.value->data); + snprintf(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], MAX_FILEPATH_LENGTH, "%s", e->drop.value->data); CORE.Window.dropFileCount++; } @@ -1471,15 +1471,25 @@ double GetTime(void) } // Open URL with default system browser (if available) -// NOTE: This function is only safe to use if you control the URL given -// A user could craft a malicious string performing another action +// WARNING: This function is only safe to use if you control the URL given, +// a user could craft a malicious string to perform and undesired action +// NOTE: Some safety checks have been added to mitigate security issues void OpenURL(const char *url) { - // Security check to (partially) avoid malicious code on target platform - if (strchr(url, '\'') != NULL) TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'] character"); - else + // Security check to (partially) avoid malicious code + if ((strchr(url, '\'') != NULL) || (strchr(url, '\"') != NULL)) { - char *cmd = (char *)RL_CALLOC(strlen(url) + 32, sizeof(char)); + // Filter characters: ' and " + TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'\"] characters"); + } + else if ((strncmp(url, "http://", 7) != 0) && (strncmp(url, "https://", 8) != 0)) + { + // Only allow URL starting with "http://" or "https://" protocols + TRACELOG(LOG_WARNING, "SYSTEM: Provided URL must start with 'http://' or 'https://' protocols"); + } + else + { + char *cmd = (char *)RL_CALLOC(strlen(url) + 16, sizeof(char)); #if defined(_WIN32) sprintf(cmd, "explorer \"%s\"", url); #endif @@ -1516,7 +1526,6 @@ void SetMousePosition(int x, int y) { RGFW_window_moveMouse(platform.window, x, y); CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y }; - CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition; } // Set mouse cursor @@ -1609,74 +1618,76 @@ void PollInputEvents(void) //----------------------------------------------------------------------------- mg_event gamepad_event; - while (mg_gamepads_check_event(&platform.minigamepad, &gamepad_event)) { + while (mg_gamepads_check_event(&platform.minigamepad, &gamepad_event)) + { int gamepadIndex = gamepad_event.gamepad->index; - switch (gamepad_event.type) { + + switch (gamepad_event.type) + { case MG_EVENT_BUTTON_PRESS: + { + int button = mg_buttonConvertTable[gamepad_event.button]; + if (button >= 0) { - int button = mg_buttonConvertTable[gamepad_event.button]; - if (button >= 0) - { - CORE.Input.Gamepad.currentButtonState[gamepadIndex][button] = 1; - CORE.Input.Gamepad.lastButtonPressed = button; - } - } break; + CORE.Input.Gamepad.currentButtonState[gamepadIndex][button] = 1; + CORE.Input.Gamepad.lastButtonPressed = button; + } + } break; case MG_EVENT_BUTTON_RELEASE: + { + int button = mg_buttonConvertTable[gamepad_event.button]; + if (button >= 0) { - int button = mg_buttonConvertTable[gamepad_event.button]; - if (button >= 0) - { - CORE.Input.Gamepad.currentButtonState[gamepadIndex][button] = 0; - if (CORE.Input.Gamepad.lastButtonPressed == button) CORE.Input.Gamepad.lastButtonPressed = 0; - } - } break; + CORE.Input.Gamepad.currentButtonState[gamepadIndex][button] = 0; + if (CORE.Input.Gamepad.lastButtonPressed == button) CORE.Input.Gamepad.lastButtonPressed = 0; + } + } break; case MG_EVENT_AXIS_MOVE: - { - int axis = mg_axisConvertTable[gamepad_event.axis]; + { + int axis = mg_axisConvertTable[gamepad_event.axis]; - switch (axis) { - case GAMEPAD_AXIS_LEFT_X: - case GAMEPAD_AXIS_LEFT_Y: - case GAMEPAD_AXIS_RIGHT_X: - case GAMEPAD_AXIS_RIGHT_Y: - CORE.Input.Gamepad.axisState[gamepadIndex][axis] = platform.minigamepad.gamepads[gamepadIndex].axes[gamepad_event.axis].value; - break; - case GAMEPAD_AXIS_LEFT_TRIGGER: - case GAMEPAD_AXIS_RIGHT_TRIGGER: - CORE.Input.Gamepad.axisState[gamepadIndex][axis] = platform.minigamepad.gamepads[gamepadIndex].axes[gamepad_event.axis].value; + switch (axis) { + case GAMEPAD_AXIS_LEFT_X: + case GAMEPAD_AXIS_LEFT_Y: + case GAMEPAD_AXIS_RIGHT_X: + case GAMEPAD_AXIS_RIGHT_Y: + { + CORE.Input.Gamepad.axisState[gamepadIndex][axis] = platform.minigamepad.gamepads[gamepadIndex].axes[gamepad_event.axis].value; + } break; + case GAMEPAD_AXIS_LEFT_TRIGGER: + case GAMEPAD_AXIS_RIGHT_TRIGGER: + { + CORE.Input.Gamepad.axisState[gamepadIndex][axis] = platform.minigamepad.gamepads[gamepadIndex].axes[gamepad_event.axis].value; - // Trigger button press when axis is all the way - int button = (axis == GAMEPAD_AXIS_LEFT_TRIGGER) ? GAMEPAD_BUTTON_LEFT_TRIGGER_2 : GAMEPAD_BUTTON_RIGHT_TRIGGER_2; - int pressed = (platform.minigamepad.gamepads[gamepadIndex].axes[gamepad_event.axis].value >= 1.0f); + // Trigger button press when axis is all the way + int button = (axis == GAMEPAD_AXIS_LEFT_TRIGGER) ? GAMEPAD_BUTTON_LEFT_TRIGGER_2 : GAMEPAD_BUTTON_RIGHT_TRIGGER_2; + int pressed = (platform.minigamepad.gamepads[gamepadIndex].axes[gamepad_event.axis].value >= 1.0f); - CORE.Input.Gamepad.currentButtonState[gamepadIndex][button] = pressed; - if (pressed) CORE.Input.Gamepad.lastButtonPressed = button; - else if (CORE.Input.Gamepad.lastButtonPressed == button) CORE.Input.Gamepad.lastButtonPressed = 0; - break; - } - } break; + CORE.Input.Gamepad.currentButtonState[gamepadIndex][button] = pressed; + if (pressed) CORE.Input.Gamepad.lastButtonPressed = button; + else if (CORE.Input.Gamepad.lastButtonPressed == button) CORE.Input.Gamepad.lastButtonPressed = 0; + } break; + default: break; + } + } break; case MG_EVENT_GAMEPAD_CONNECT: + { CORE.Input.Gamepad.ready[gamepadIndex] = true; CORE.Input.Gamepad.axisState[gamepadIndex][GAMEPAD_AXIS_LEFT_TRIGGER] = -1.0f; CORE.Input.Gamepad.axisState[gamepadIndex][GAMEPAD_AXIS_RIGHT_TRIGGER] = -1.0f; int axisCount = 0; - for (int i = 0; i < MG_AXIS_COUNT; i += 1) { - if (platform.minigamepad.gamepads[gamepadIndex].axes[i].supported) - { - axisCount += 1; - } - else - { - break; - } + for (int i = 0; i < MG_AXIS_COUNT; i += 1) + { + if (platform.minigamepad.gamepads[gamepadIndex].axes[i].supported) axisCount += 1; + else break; } + CORE.Input.Gamepad.axisCount[gamepadIndex] = axisCount; - strcpy(CORE.Input.Gamepad.name[gamepadIndex], platform.minigamepad.gamepads[gamepadIndex].name); - break; - case MG_EVENT_GAMEPAD_DISCONNECT: - CORE.Input.Gamepad.ready[gamepadIndex] = false; - break; + snprintf(CORE.Input.Gamepad.name[gamepadIndex], MAX_GAMEPAD_NAME_LENGTH, "%s", platform.minigamepad.gamepads[gamepadIndex].name); + + } break; + case MG_EVENT_GAMEPAD_DISCONNECT: CORE.Input.Gamepad.ready[gamepadIndex] = false; break; default: break; } } diff --git a/src/platforms/rcore_desktop_sdl.c b/src/platforms/rcore_desktop_sdl.c index c96820475..bca579e41 100644 --- a/src/platforms/rcore_desktop_sdl.c +++ b/src/platforms/rcore_desktop_sdl.c @@ -1255,12 +1255,14 @@ Image GetClipboardImage(void) for (int i = 0; i < SDL_arraysize(imageFormats); i++) { - // NOTE: This pointer should be free with SDL_free() at some point fileData = SDL_GetClipboardData(imageFormats[i], &dataSize); if (fileData) { image = LoadImageFromMemory(imageExtensions[i], fileData, (int)dataSize); + + SDL_free(fileData); + if (IsImageValid(image)) { TRACELOG(LOG_INFO, "Clipboard: Got image from clipboard successfully: %s", imageExtensions[i]); @@ -1341,14 +1343,22 @@ double GetTime(void) } // Open URL with default system browser (if available) -// NOTE: This function is only safe to use if the provided URL is safe -// A user could craft a malicious string performing another action -// Avoid calling this function with user input non-validated strings -// REF: https://github.com/raysan5/raylib/issues/686 +// WARNING: This function is only safe to use if you control the URL given, +// a user could craft a malicious string to perform and undesired action +// NOTE: Some safety checks have been added to mitigate security issues void OpenURL(const char *url) { // Security check to (partially) avoid malicious code - if (strchr(url, '\'') != NULL) TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'] character"); + if ((strchr(url, '\'') != NULL) || (strchr(url, '\"') != NULL)) + { + // Filter characters: ' and " + TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'\"] characters"); + } + else if ((strncmp(url, "http://", 7) != 0) && (strncmp(url, "https://", 8) != 0)) + { + // Only allow URL starting with "http://" or "https://" protocols + TRACELOG(LOG_WARNING, "SYSTEM: Provided URL must start with 'http://' or 'https://' protocols"); + } else SDL_OpenURL(url); } @@ -1401,7 +1411,6 @@ void SetMousePosition(int x, int y) SDL_WarpMouseInWindow(platform.window, x, y); CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y }; - CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition; } // Set mouse cursor @@ -1512,9 +1521,9 @@ void PollInputEvents(void) // Event memory is now managed by SDL, so it should not be freed in SDL_EVENT_DROP_FILE, // in case data needs to be hold onto the text in SDL_EVENT_TEXT_EDITING and SDL_EVENT_TEXT_INPUT events, // a copy is required, SDL_TEXTINPUTEVENT_TEXT_SIZE is no longer necessary and has been removed - strncpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], event.drop.data, MAX_FILEPATH_LENGTH - 1); + snprintf(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], MAX_FILEPATH_LENGTH, "%s", event.drop.data); #else - strncpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], event.drop.file, MAX_FILEPATH_LENGTH - 1); + snprintf(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], MAX_FILEPATH_LENGTH, "%s", event.drop.file); SDL_free(event.drop.file); #endif @@ -1525,9 +1534,9 @@ void PollInputEvents(void) CORE.Window.dropFilepaths[CORE.Window.dropFileCount] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char)); #if defined(USING_VERSION_SDL3) - strncpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], event.drop.data, MAX_FILEPATH_LENGTH - 1); + snprintf(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], MAX_FILEPATH_LENGTH, "%s", event.drop.data); #else - strncpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], event.drop.file, MAX_FILEPATH_LENGTH - 1); + snprintf(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], MAX_FILEPATH_LENGTH, "%s", event.drop.file); SDL_free(event.drop.file); #endif @@ -1812,8 +1821,8 @@ void PollInputEvents(void) CORE.Input.Gamepad.axisState[nextAvailableSlot][GAMEPAD_AXIS_RIGHT_TRIGGER] = -1.0f; memset(CORE.Input.Gamepad.name[nextAvailableSlot], 0, MAX_GAMEPAD_NAME_LENGTH); const char *controllerName = SDL_GameControllerNameForIndex(nextAvailableSlot); - if (controllerName != NULL) strncpy(CORE.Input.Gamepad.name[nextAvailableSlot], controllerName, MAX_GAMEPAD_NAME_LENGTH - 1); - else strncpy(CORE.Input.Gamepad.name[nextAvailableSlot], "noname", 6); + if (controllerName != NULL) snprintf(CORE.Input.Gamepad.name[nextAvailableSlot], MAX_GAMEPAD_NAME_LENGTH, "%s", controllerName); + else memcpy(CORE.Input.Gamepad.name[nextAvailableSlot], "noname", 6); } else TRACELOG(LOG_WARNING, "PLATFORM: Unable to open game controller [ERROR: %s]", SDL_GetError()); } @@ -2164,11 +2173,20 @@ int InitPlatform(void) platform.gamepadId[i] = -1; // Set all gamepad initial instance ids as invalid to not conflict with instance id zero } +#if defined(USING_VERSION_SDL3) + int numJoysticks; + SDL_JoystickID *joysticks = SDL_GetJoysticks(&numJoysticks); +#else int numJoysticks = SDL_NumJoysticks(); +#endif for (int i = 0; (i < numJoysticks) && (i < MAX_GAMEPADS); i++) { +#if defined(USING_VERSION_SDL3) + platform.gamepad[i] = SDL_OpenGamepad(joysticks[i]); +#else platform.gamepad[i] = SDL_GameControllerOpen(i); +#endif platform.gamepadId[i] = SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(platform.gamepad[i])); if (platform.gamepad[i]) @@ -2177,7 +2195,12 @@ int InitPlatform(void) CORE.Input.Gamepad.axisCount[i] = SDL_JoystickNumAxes(SDL_GameControllerGetJoystick(platform.gamepad[i])); CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_LEFT_TRIGGER] = -1.0f; CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_RIGHT_TRIGGER] = -1.0f; - strncpy(CORE.Input.Gamepad.name[i], SDL_GameControllerNameForIndex(i), MAX_GAMEPAD_NAME_LENGTH - 1); +#if defined(USING_VERSION_SDL3) + const char *joystickName = SDL_GetJoystickNameForID(joysticks[i]); +#else + const char *joystickName = SDL_GameControllerNameForIndex(i); +#endif + snprintf(CORE.Input.Gamepad.name[i], MAX_GAMEPAD_NAME_LENGTH, "%s", joystickName); CORE.Input.Gamepad.name[i][MAX_GAMEPAD_NAME_LENGTH - 1] = '\0'; } else TRACELOG(LOG_WARNING, "PLATFORM: Unable to open game controller [ERROR: %s]", SDL_GetError()); diff --git a/src/platforms/rcore_desktop_win32.c b/src/platforms/rcore_desktop_win32.c index 35347023d..a6e85a657 100644 --- a/src/platforms/rcore_desktop_win32.c +++ b/src/platforms/rcore_desktop_win32.c @@ -1247,19 +1247,28 @@ double GetTime(void) } // Open URL with default system browser (if available) -// NOTE: This function is only safe to use if the provided URL is safe -// A user could craft a malicious string performing another action -// Avoid calling this function with user input non-validated strings -// REF: https://github.com/raysan5/raylib/issues/686 +// WARNING: This function is only safe to use if you control the URL given, +// a user could craft a malicious string to perform and undesired action +// NOTE: Some safety checks have been added to mitigate security issues void OpenURL(const char *url) { - // Security check to (partially) avoid malicious code on target platform - if (strchr(url, '\'') != NULL) TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'] character"); - else + // Security check to (partially) avoid malicious code + if ((strchr(url, '\'') != NULL) || (strchr(url, '\"') != NULL)) { - int len = strlen(url) + 32; + // Filter characters: ' and " + TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'\"] characters"); + } + else if ((strncmp(url, "http://", 7) != 0) && (strncmp(url, "https://", 8) != 0)) + { + // Only allow URL starting with "http://" or "https://" protocols + TRACELOG(LOG_WARNING, "SYSTEM: Provided URL must start with 'http://' or 'https://' protocols"); + } + else + { + int len = strlen(url) + 16; char *cmd = (char *)RL_CALLOC(len, sizeof(char)); snprintf(cmd, len, "explorer \"%s\"", url); + int result = system(cmd); if (result == -1) TRACELOG(LOG_WARNING, "OpenURL() child process could not be created"); RL_FREE(cmd); @@ -1290,8 +1299,8 @@ void SetMousePosition(int x, int y) if (!CORE.Input.Mouse.cursorLocked) { CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y }; - CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition; - TRACELOG(LOG_WARNING, "SetMousePosition not implemented"); + + TRACELOG(LOG_WARNING, "SetMousePosition not implemented at platform level"); } else TRACELOG(LOG_WARNING, "INPUT: MOUSE: Cursor not enabled"); } diff --git a/src/platforms/rcore_drm.c b/src/platforms/rcore_drm.c index 659c80011..4d4a4d3bf 100644 --- a/src/platforms/rcore_drm.c +++ b/src/platforms/rcore_drm.c @@ -1014,9 +1014,8 @@ double GetTime(void) } // Open URL with default system browser (if available) -// NOTE: This function is only safe to use if the provided URL is safe -// A user could craft a malicious string performing another action -// Avoid calling this function with user input non-validated strings +// WARNING: This function is only safe to use if you control the URL given, +// a user could craft a malicious string to perform and undesired action void OpenURL(const char *url) { TRACELOG(LOG_WARNING, "OpenURL() not implemented on target platform"); @@ -1043,7 +1042,6 @@ void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float d void SetMousePosition(int x, int y) { CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y }; - CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition; } // Set mouse cursor @@ -1446,7 +1444,9 @@ int InitPlatform(void) return -1; } - if (!eglChooseConfig(platform.device, NULL, NULL, 0, &numConfigs)) + // WARNING: Providing framebufferAttribs is not logically necessary, + // but it may prevent segfaults on some nvidia drivers + if (!eglChooseConfig(platform.device, framebufferAttribs, NULL, 0, &numConfigs)) { TRACELOG(LOG_WARNING, "DISPLAY: Failed to get EGL config count: 0x%x", eglGetError()); return -1; @@ -2732,4 +2732,4 @@ static void SetupFramebuffer(int width, int height) } } -// EOF \ No newline at end of file +// EOF diff --git a/src/platforms/rcore_memory.c b/src/platforms/rcore_memory.c index 14c56a591..03b787da6 100644 --- a/src/platforms/rcore_memory.c +++ b/src/platforms/rcore_memory.c @@ -420,7 +420,6 @@ void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float d void SetMousePosition(int x, int y) { CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y }; - CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition; } // Set mouse cursor diff --git a/src/platforms/rcore_template.c b/src/platforms/rcore_template.c index 353d32d11..1866059e8 100644 --- a/src/platforms/rcore_template.c +++ b/src/platforms/rcore_template.c @@ -352,14 +352,22 @@ double GetTime(void) } // Open URL with default system browser (if available) -// NOTE: This function is only safe to use if you control the URL given. -// A user could craft a malicious string performing another action. -// Only call this function yourself not with user input or make sure to check the string yourself. -// Ref: https://github.com/raysan5/raylib/issues/686 +// WARNING: This function is only safe to use if you control the URL given, +// a user could craft a malicious string to perform and undesired action +// NOTE: Some safety checks have been added to mitigate security issues void OpenURL(const char *url) { - // Security check to (partially) avoid malicious code on target platform - if (strchr(url, '\'') != NULL) TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'] character"); + // Security check to (partially) avoid malicious code + if ((strchr(url, '\'') != NULL) || (strchr(url, '\"') != NULL)) + { + // Filter characters: ' and " + TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'\"] characters"); + } + else if ((strncmp(url, "http://", 7) != 0) && (strncmp(url, "https://", 8) != 0)) + { + // Only allow URL starting with "http://" or "https://" protocols + TRACELOG(LOG_WARNING, "SYSTEM: Provided URL must start with 'http://' or 'https://' protocols"); + } else { // TODO: Load url using default browser @@ -387,7 +395,6 @@ void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float d void SetMousePosition(int x, int y) { CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y }; - CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition; } // Set mouse cursor diff --git a/src/platforms/rcore_web.c b/src/platforms/rcore_web.c index 9d16c3e87..b95121d2c 100644 --- a/src/platforms/rcore_web.c +++ b/src/platforms/rcore_web.c @@ -1047,7 +1047,6 @@ void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float d void SetMousePosition(int x, int y) { CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y }; - CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition; if (CORE.Input.Mouse.cursorLocked) CORE.Input.Mouse.lockedPosition = CORE.Input.Mouse.currentPosition; @@ -1579,7 +1578,7 @@ static void WindowDropCallback(GLFWwindow *window, int count, const char **paths for (unsigned int i = 0; i < CORE.Window.dropFileCount; i++) { CORE.Window.dropFilepaths[i] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char)); - strncpy(CORE.Window.dropFilepaths[i], paths[i], MAX_FILEPATH_LENGTH - 1); + snprintf(CORE.Window.dropFilepaths[i], MAX_FILEPATH_LENGTH, "%s", paths[i]); } } } diff --git a/src/platforms/rcore_web_emscripten.c b/src/platforms/rcore_web_emscripten.c index ff78ac547..fa967057a 100644 --- a/src/platforms/rcore_web_emscripten.c +++ b/src/platforms/rcore_web_emscripten.c @@ -968,13 +968,22 @@ double GetTime(void) } // Open URL with default system browser (if available) -// NOTE: This function is only safe to use if the provided URL is safe -// A user could craft a malicious string performing another action -// Avoid calling this function with user input non-validated strings +// WARNING: This function is only safe to use if you control the URL given, +// a user could craft a malicious string to perform and undesired action +// NOTE: Some safety checks have been added to mitigate security issues void OpenURL(const char *url) { - // Security check to (partially) avoid malicious code on target platform - if (strchr(url, '\'') != NULL) TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'] character"); + // Security check to (partially) avoid malicious code + if ((strchr(url, '\'') != NULL) || (strchr(url, '\"') != NULL)) + { + // Filter characters: ' and " + TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'\"] characters"); + } + else if ((strncmp(url, "http://", 7) != 0) && (strncmp(url, "https://", 8) != 0)) + { + // Only allow URL starting with "http://" or "https://" protocols + TRACELOG(LOG_WARNING, "SYSTEM: Provided URL must start with 'http://' or 'https://' protocols"); + } else emscripten_run_script(TextFormat("window.open('%s', '_blank')", url)); } @@ -1439,7 +1448,7 @@ static void WindowDropCallback(GLFWwindow *window, int count, const char **paths for (unsigned int i = 0; i < CORE.Window.dropFileCount; i++) { CORE.Window.dropFilepaths[i] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char)); - strncpy(CORE.Window.dropFilepaths[i], paths[i], MAX_FILEPATH_LENGTH - 1); + snprintf(CORE.Window.dropFilepaths[i], MAX_FILEPATH_LENGTH, "%s", paths[i]); } } } @@ -1498,8 +1507,16 @@ static EM_BOOL EmscriptenMouseCallback(int eventType, const EmscriptenMouseEvent { switch (eventType) { - case EMSCRIPTEN_EVENT_MOUSEENTER: CORE.Input.Mouse.cursorOnScreen = true; break; - case EMSCRIPTEN_EVENT_MOUSELEAVE: CORE.Input.Mouse.cursorOnScreen = false; break; + case EMSCRIPTEN_EVENT_MOUSEENTER: { + // NOTE: Mouse position updated by EmscriptenMouseMoveCallback(), + // EmscriptenPointerlockCallback(), and EmscriptenTouchCallback() + CORE.Input.Mouse.cursorOnScreen = true; + } break; + case EMSCRIPTEN_EVENT_MOUSELEAVE: + { + CORE.Input.Mouse.cursorOnScreen = false; + CORE.Input.Mouse.currentPosition = (Vector2){ 0 }; + } break; case EMSCRIPTEN_EVENT_MOUSEDOWN: { // NOTE: Emscripten and raylib buttons indices are not aligned diff --git a/src/raudio.c b/src/raudio.c index 094ea7533..42ea410c8 100644 --- a/src/raudio.c +++ b/src/raudio.c @@ -822,7 +822,7 @@ Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int wave.sampleRate = wav.sampleRate; wave.sampleSize = 16; wave.channels = wav.channels; - wave.data = (short *)RL_MALLOC((size_t)wave.frameCount*wave.channels*sizeof(short)); + wave.data = (short *)RL_CALLOC((size_t)wave.frameCount*wave.channels, sizeof(short)); // NOTE: Forcing conversion to 16bit sample size on reading drwav_read_pcm_frames_s16(&wav, wave.frameCount, (drwav_int16 *)wave.data); @@ -845,7 +845,7 @@ Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int wave.sampleSize = 16; // By default, ogg data is 16 bit per sample (short) wave.channels = info.channels; wave.frameCount = (unsigned int)stb_vorbis_stream_length_in_samples(oggData); // NOTE: It returns frames! - wave.data = (short *)RL_MALLOC(wave.frameCount*wave.channels*sizeof(short)); + wave.data = (short *)RL_CALLOC(wave.frameCount*wave.channels, sizeof(short)); // NOTE: Get the number of samples to process (be careful! asking for number of shorts, not bytes!) stb_vorbis_get_samples_short_interleaved(oggData, info.channels, (short *)wave.data, wave.frameCount*wave.channels); @@ -1154,7 +1154,7 @@ bool ExportWaveAsCode(Wave wave, const char *fileName) // Get file name from path and convert variable name to uppercase char varFileName[256] = { 0 }; - strncpy(varFileName, GetFileNameWithoutExt(fileName), 256 - 1); + snprintf(varFileName, 256, "%s", GetFileNameWithoutExt(fileName)); // NOTE: Using function provided by [rcore] module for (int i = 0; varFileName[i] != '\0'; i++) if (varFileName[i] >= 'a' && varFileName[i] <= 'z') { varFileName[i] = varFileName[i] - 32; } // Add wave information @@ -1258,7 +1258,7 @@ void WaveFormat(Wave *wave, int sampleRate, int sampleSize, int channels) return; } - void *data = RL_MALLOC(frameCount*channels*(sampleSize/8)); + void *data = RL_CALLOC(frameCount*channels*(sampleSize/8), 1); frameCount = (ma_uint32)ma_convert_frames(data, frameCount, formatOut, channels, sampleRate, wave->data, frameCountIn, formatIn, wave->channels, wave->sampleRate); if (frameCount == 0) @@ -1772,7 +1772,7 @@ void UnloadMusicStream(Music music) { if (false) { } #if SUPPORT_FILEFORMAT_WAV - else if (music.ctxType == MUSIC_AUDIO_WAV) drwav_uninit((drwav *)music.ctxData); + else if (music.ctxType == MUSIC_AUDIO_WAV) { drwav_uninit((drwav *)music.ctxData); RL_FREE(music.ctxData); } #endif #if SUPPORT_FILEFORMAT_OGG else if (music.ctxType == MUSIC_AUDIO_OGG) stb_vorbis_close((stb_vorbis *)music.ctxData); @@ -2827,7 +2827,7 @@ static const char *GetFileNameWithoutExt(const char *filePath) static char fileName[MAX_FILENAMEWITHOUTEXT_LENGTH] = { 0 }; memset(fileName, 0, MAX_FILENAMEWITHOUTEXT_LENGTH); - if (filePath != NULL) strncpy(fileName, GetFileName(filePath), MAX_FILENAMEWITHOUTEXT_LENGTH - 1); // Get filename with extension + if (filePath != NULL) snprintf(fileName, MAX_FILENAMEWITHOUTEXT_LENGTH, "%s", GetFileName(filePath)); int fileNameLength = (int)strlen(fileName); // Get size in bytes diff --git a/src/raylib.h b/src/raylib.h index e3b4289a3..58f233483 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -409,8 +409,8 @@ typedef struct BoneInfo { // Skeleton, animation bones hierarchy typedef struct ModelSkeleton { - int boneCount; // Number of bones - BoneInfo *bones; // Bones information (skeleton) + unsigned int boneCount; // Number of bones + BoneInfo *bones; // Bones information (skeleton) ModelAnimPose bindPose; // Bones base transformation (Transform[]) } ModelSkeleton; @@ -436,8 +436,8 @@ typedef struct Model { typedef struct ModelAnimation { char name[32]; // Animation name - int boneCount; // Number of bones (per pose) - int keyframeCount; // Number of animation key frames + unsigned int boneCount; // Number of bones (per pose) + int keyframeCount; // Number of animation key frames ModelAnimPose *keyframePoses; // Animation sequence keyframe poses [keyframe][pose] } ModelAnimation; diff --git a/src/rcore.c b/src/rcore.c index d1163a515..a368cabec 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -108,7 +108,7 @@ #include // Required for: srand(), rand(), exit() #include // Required for: FILE, fopen(), fseek(), ftell(), fread(), fwrite(), fprintf(), vprintf(), fclose(), sprintf() [Used in OpenURL()] -#include // Required for: strlen(), strncpy(), strcmp(), strrchr(), memset(), strcat() +#include // Required for: strlen(), strcmp(), strrchr(), memset(), memcpy(), strcat() #include // Required for: va_list, va_start(), va_end() [Used in TraceLog()] #include // Required for: time() [Used in InitTimer()] #include // Required for: tan() [Used in BeginMode3D()], atan2f() [Used in LoadVrStereoConfig()] @@ -1819,7 +1819,7 @@ void TakeScreenshot(const char *fileName) Image image = { imgData, (int)((float)CORE.Window.render.width*scale.x), (int)((float)CORE.Window.render.height*scale.y), 1, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 }; char path[MAX_FILEPATH_LENGTH] = { 0 }; - strncpy(path, TextFormat("%s/%s", CORE.Storage.basePath, fileName), MAX_FILEPATH_LENGTH - 1); + snprintf(path, MAX_FILEPATH_LENGTH, "%s", TextFormat("%s/%s", CORE.Storage.basePath, fileName)); ExportImage(image, path); // WARNING: Module required: rtextures RL_FREE(imgData); @@ -1844,8 +1844,6 @@ void SetConfigFlags(unsigned int flags) FLAG_SET(CORE.Window.flags, flags); } -// void OpenURL(const char *url); // Defined per platform - //---------------------------------------------------------------------------------- // Module Functions Definition: Logging system //---------------------------------------------------------------------------------- @@ -1885,12 +1883,12 @@ void TraceLog(int logType, const char *text, ...) switch (logType) { - case LOG_TRACE: strncpy(buffer, "TRACE: ", 8); break; - case LOG_DEBUG: strncpy(buffer, "DEBUG: ", 8); break; - case LOG_INFO: strncpy(buffer, "INFO: ", 7); break; - case LOG_WARNING: strncpy(buffer, "WARNING: ", 10); break; - case LOG_ERROR: strncpy(buffer, "ERROR: ", 8); break; - case LOG_FATAL: strncpy(buffer, "FATAL: ", 8); break; + case LOG_TRACE: memcpy(buffer, "TRACE: ", 7); break; + case LOG_DEBUG: memcpy(buffer, "DEBUG: ", 7); break; + case LOG_INFO: memcpy(buffer, "INFO: ", 6); break; + case LOG_WARNING: memcpy(buffer, "WARNING: ", 9); break; + case LOG_ERROR: memcpy(buffer, "ERROR: ", 7); break; + case LOG_FATAL: memcpy(buffer, "FATAL: ", 7); break; default: break; } @@ -2063,7 +2061,7 @@ bool ExportDataAsCode(const unsigned char *data, int dataSize, const char *fileN // Get file name from path char varFileName[256] = { 0 }; - strncpy(varFileName, GetFileNameWithoutExt(fileName), 256 - 1); + snprintf(varFileName, 256, "%s", GetFileNameWithoutExt(fileName)); for (int i = 0; varFileName[i] != '\0'; i++) { // Convert variable name to uppercase @@ -2507,7 +2505,7 @@ const char *GetFileNameWithoutExt(const char *filePath) if (filePath != NULL) { - strncpy(fileName, GetFileName(filePath), MAX_FILENAME_LENGTH - 1); // Get filename.ext without path + snprintf(fileName, MAX_FILENAME_LENGTH, "%s", GetFileName(filePath)); // Get filename.ext without path int fileNameLength = (int)strlen(fileName); // Get size in bytes for (int i = fileNameLength; i > 0; i--) // Reverse search '.' @@ -2561,7 +2559,6 @@ const char *GetDirectoryPath(const char *filePath) } else { - // NOTE: Be careful, strncpy() is not safe, it does not care about '\0' char *dirPathPtr = dirPath; if ((filePath[1] != ':') && (filePath[0] != '\\') && (filePath[0] != '/')) dirPathPtr += 2; // Skip drive letter, "C:" memcpy(dirPathPtr, filePath, strlen(filePath) - (strlen(lastSlash) - 1)); @@ -2579,7 +2576,7 @@ const char *GetPrevDirectoryPath(const char *dirPath) memset(prevDirPath, 0, MAX_FILEPATH_LENGTH); int dirPathLength = (int)strlen(dirPath); - if (dirPathLength <= 3) strncpy(prevDirPath, dirPath, MAX_FILEPATH_LENGTH - 1); + if (dirPathLength <= 3) snprintf(prevDirPath, MAX_FILEPATH_LENGTH, "%s", dirPath); for (int i = (dirPathLength - 1); (i >= 0) && (dirPathLength > 3); i--) { @@ -2588,7 +2585,7 @@ const char *GetPrevDirectoryPath(const char *dirPath) // Check for root: "C:\" or "/" if (((i == 2) && (dirPath[1] ==':')) || (i == 0)) i++; - strncpy(prevDirPath, dirPath, i); + memcpy(prevDirPath, dirPath, i); break; } } @@ -3276,7 +3273,7 @@ unsigned int *ComputeMD5(const unsigned char *data, int dataSize) memcpy(msg + newDataSize, &bitsLen, 4); // Append the len in bits at the end of the buffer // Process the message in successive 512-bit chunks for each 512-bit chunk of message - for (int offset = 0; offset < newDataSize; offset += (512/8)) + for (int offset = 0; offset < newDataSize; offset += 64) // 512/8 { // Break chunk into sixteen 32-bit words w[j], 0 <= j <= 15 unsigned int *w = (unsigned int *)(msg + offset); @@ -3373,16 +3370,16 @@ unsigned int *ComputeSHA1(const unsigned char *data, int dataSize) msg[newDataSize - 8] = (unsigned char)(bitsLen >> 56); // Process the message in successive 512-bit chunks - for (int offset = 0; offset < newDataSize; offset += (512/8)) + for (int offset = 0; offset < newDataSize; offset += 64) // 512/8 { // Break chunk into sixteen 32-bit words w[j], 0 <= j <= 15 unsigned int w[80] = { 0 }; for (int i = 0; i < 16; i++) { - w[i] = (msg[offset + (i*4) + 0] << 24) | - (msg[offset + (i*4) + 1] << 16) | - (msg[offset + (i*4) + 2] << 8) | - (msg[offset + (i*4) + 3]); + w[i] = ((unsigned int)msg[offset + (i*4) + 0] << 24) | + ((unsigned int)msg[offset + (i*4) + 1] << 16) | + ((unsigned int)msg[offset + (i*4) + 2] << 8) | + ((unsigned int)msg[offset + (i*4) + 3]); } // Message schedule: extend the sixteen 32-bit words into eighty 32-bit words: @@ -3604,10 +3601,14 @@ AutomationEventList LoadAutomationEventList(const char *fileName) case 'c': sscanf(buffer, "c %i", &list.count); break; case 'e': { - sscanf(buffer, "e %d %d %d %d %d %d %[^\n]s", &list.events[counter].frame, &list.events[counter].type, - &list.events[counter].params[0], &list.events[counter].params[1], &list.events[counter].params[2], &list.events[counter].params[3], eventDesc); + if (counter < list.capacity) + { + sscanf(buffer, "e %d %d %d %d %d %d %63[^\n]s", &list.events[counter].frame, &list.events[counter].type, + &list.events[counter].params[0], &list.events[counter].params[1], &list.events[counter].params[2], &list.events[counter].params[3], eventDesc); - counter++; + counter++; + } + else TRACELOG(LOG_WARNING, "AUTOMATION: Event goes beyond automated list capacity (MAX: %u): %s", list.capacity, buffer); } break; default: break; } diff --git a/src/rlgl.h b/src/rlgl.h index d72469e11..68eec7fdf 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -847,11 +847,11 @@ RLAPI void rlLoadDrawQuad(void); // Load and draw a quad #define SW_CALLOC(n,sz) RL_CALLOC(n, sz) #define SW_REALLOC(ptr, newSz) RL_REALLOC(ptr, newSz) #define SW_FREE(ptr) RL_FREE(ptr) - #include "external/rlsw.h" // OpenGL 1.1 software implementation + #include "external/rlsw.h" // OpenGL 1.1 software implementation #else #if defined(__APPLE__) - #include // OpenGL 1.1 library for OSX - #include // OpenGL extensions library + #include // OpenGL 1.1 library for OSX + #include // OpenGL extensions library #else // APIENTRY for OpenGL function pointer declarations is required #if !defined(APIENTRY) @@ -866,7 +866,7 @@ RLAPI void rlLoadDrawQuad(void); // Load and draw a quad #define WINGDIAPI __declspec(dllimport) #endif - #include // OpenGL 1.1 library + #include // OpenGL 1.1 library #endif #endif #endif @@ -907,9 +907,10 @@ RLAPI void rlLoadDrawQuad(void); // Load and draw a quad #endif #endif -#include // Required for: calloc(), free() -#include // Required for: strcmp(), strlen() [Used in rlglInit(), on extensions loading] -#include // Required for: sqrtf(), sinf(), cosf(), floor(), log() +#include // Required for: calloc(), free() +#include // Required for: strcmp(), strlen() [Used in rlglInit(), on extensions loading] +#include // Required for: sqrtf(), sinf(), cosf(), floor(), log() +#include // Required for: INT_MAX //---------------------------------------------------------------------------------- // Defines and Macros @@ -2469,7 +2470,7 @@ void rlLoadExtensions(void *loader) // NOTE: String duplication rquired because glGetString() returns a const string int extensionsLength = (int)strlen(extensions); // Get extensions string size in bytes char *extensionsDup = (char *)RL_CALLOC(extensionsLength + 1, sizeof(char)); // Allocate space for copy with additional EOL byte - strncpy(extensionsDup, extensions, extensionsLength); + snprintf(extensionsDup, extensionsLength, "%s", extensions); extList[numExt] = extensionsDup; for (int i = 0; i < extensionsLength; i++) @@ -5236,7 +5237,9 @@ static int rlGetPixelDataSize(int width, int height, int format) { int blockWidth = (width + 3)/4; int blockHeight = (height + 3)/4; - dataSize = blockWidth*blockHeight*8; + unsigned long long dataSizeBytes = (unsigned long long)blockWidth*blockHeight*8; + if (dataSizeBytes < INT_MAX) dataSize = (int)dataSizeBytes; + } break; case RL_PIXELFORMAT_COMPRESSED_DXT3_RGBA: case RL_PIXELFORMAT_COMPRESSED_DXT5_RGBA: @@ -5245,13 +5248,17 @@ static int rlGetPixelDataSize(int width, int height, int format) { int blockWidth = (width + 3)/4; int blockHeight = (height + 3)/4; - dataSize = blockWidth*blockHeight*16; + unsigned long long dataSizeBytes = (unsigned long long)blockWidth*blockHeight*16; + if (dataSizeBytes < INT_MAX) dataSize = (int)dataSizeBytes; + } break; case RL_PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA: // 4 bytes per each 4x4 block { int blockWidth = (width + 3)/4; int blockHeight = (height + 3)/4; - dataSize = blockWidth*blockHeight*4; + unsigned long long dataSizeBytes = (unsigned long long)blockWidth*blockHeight*4; + if (dataSizeBytes < INT_MAX) dataSize = (int)dataSizeBytes; + } break; default: break; } @@ -5260,9 +5267,11 @@ static int rlGetPixelDataSize(int width, int height, int format) if ((format >= RL_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE) && (format <= RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16)) { - double bytesPerPixel = (double)bpp/8.0; - dataSize = (int)(bytesPerPixel*width*height); // Total data size in bytes + unsigned long long dataSizeBytes = ((unsigned long long)width*height*bpp) >> 3; // Get size in bytes (dividing by 8) + if (dataSizeBytes < INT_MAX) dataSize = (int)dataSizeBytes; } + + if (dataSize == 0) TRACELOG(LOG_WARNING, "Requested image size is larger than 2GB, it can not be allocated"); return dataSize; } diff --git a/src/rmodels.c b/src/rmodels.c index 28fb3c9ec..0325f9b1b 100644 --- a/src/rmodels.c +++ b/src/rmodels.c @@ -50,9 +50,9 @@ #include "rlgl.h" // OpenGL abstraction layer to OpenGL 1.1, 2.1, 3.3+ or ES2 #include "raymath.h" // Required for: Vector3, Quaternion and Matrix functionality -#include // Required for: sprintf() +#include // Required for: sprintf(), snprintf() #include // Required for: malloc(), calloc(), free() -#include // Required for: memcmp(), strlen(), strncpy() +#include // Required for: strlen(), memcmp() #include // Required for: sinf(), cosf(), sqrtf(), fabsf() #if SUPPORT_FILEFORMAT_OBJ || SUPPORT_FILEFORMAT_MTL @@ -2073,7 +2073,7 @@ bool ExportMeshAsCode(Mesh mesh, const char *fileName) // Get file name from path and convert variable name to uppercase char varFileName[256] = { 0 }; - strncpy(varFileName, GetFileNameWithoutExt(fileName), 256 - 1); // NOTE: Using function provided by [rcore] module + snprintf(varFileName, 256, "%s", GetFileNameWithoutExt(fileName)); // NOTE: Using function provided by [rcore] module for (int i = 0; varFileName[i] != '\0'; i++) if ((varFileName[i] >= 'a') && (varFileName[i] <= 'z')) { varFileName[i] = varFileName[i] - 32; } // Add image information @@ -2320,7 +2320,7 @@ void UpdateModelAnimation(Model model, ModelAnimation anim, float frame) Matrix currentPoseMatrix = { 0 }; // Update all bones and bone matrices of model - for (int boneIndex = 0; boneIndex < model.skeleton.boneCount; boneIndex++) + for (unsigned int boneIndex = 0; boneIndex < model.skeleton.boneCount; boneIndex++) { // Compute interpolated pose between current and next frame // NOTE: Storing animation frame data in model.currentPose @@ -2390,7 +2390,7 @@ void UpdateModelAnimationEx(Model model, ModelAnimation animA, float frameA, Mod Matrix bindPoseMatrix = { 0 }; Matrix currentPoseMatrix = { 0 }; - for (int boneIndex = 0; boneIndex < model.skeleton.boneCount; boneIndex++) + for (unsigned int boneIndex = 0; boneIndex < model.skeleton.boneCount; boneIndex++) { // Get frame-interpolation for first animation Vector3 frameATranslation = Vector3Lerp( @@ -4421,7 +4421,7 @@ static Model LoadOBJ(const char *fileName) } char currentDir[MAX_FILEPATH_LENGTH] = { 0 }; - strncpy(currentDir, GetWorkingDirectory(), MAX_FILEPATH_LENGTH - 1); // Save current working directory + snprintf(currentDir, MAX_FILEPATH_LENGTH, "%s", GetWorkingDirectory()); // Save current working directory const char *workingDir = GetDirectoryPath(fileName); // Switch to OBJ directory for material path correctness if (CHDIR(workingDir) != 0) TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to change working directory", workingDir); @@ -5013,7 +5013,7 @@ static Model LoadIQM(const char *fileName) // Initialize runtime animation data: current pose and bone matrices model.currentPose = (Transform *)RL_CALLOC(model.skeleton.boneCount, sizeof(Transform)); model.boneMatrices = (Matrix *)RL_CALLOC(model.skeleton.boneCount, sizeof(Matrix)); - for (int j = 0; j < model.skeleton.boneCount; j++) model.boneMatrices[j] = MatrixIdentity(); + for (unsigned int j = 0; j < model.skeleton.boneCount; j++) model.boneMatrices[j] = MatrixIdentity(); UnloadFileData(fileData); @@ -5241,7 +5241,7 @@ static ModelAnimation *LoadModelAnimationsIQM(const char *fileName, int *animCou // Build frameposes for (unsigned int frame = 0; frame < anim[a].num_frames; frame++) { - for (int i = 0; i < animations[a].boneCount; i++) + for (unsigned int i = 0; i < animations[a].boneCount; i++) { if (bones[i].parent >= 0) { @@ -5316,8 +5316,8 @@ static Image LoadImageFromCgltfImage(cgltf_image *cgltfImage, const char *texPat { int base64Size = (int)strlen(cgltfImage->uri + i + 1); while (cgltfImage->uri[i + base64Size] == '=') base64Size--; // Ignore optional paddings - int numberOfEncodedBits = base64Size*6 - (base64Size*6) % 8 ; // Encoded bits minus extra bits, so it becomes a multiple of 8 bits - int outSize = numberOfEncodedBits/8 ; // Actual encoded bytes + int numberOfEncodedBits = base64Size*6 - (base64Size*6)%8; // Encoded bits minus extra bits, so it becomes a multiple of 8 bits + int outSize = numberOfEncodedBits >> 3; // Actual encoded bytes void *data = NULL; cgltf_options options = { 0 }; @@ -5369,15 +5369,15 @@ static Image LoadImageFromCgltfImage(cgltf_image *cgltfImage, const char *texPat } // Load bone info from GLTF skin data -static BoneInfo *LoadBoneInfoGLTF(cgltf_skin skin, int *boneCount) +static BoneInfo *LoadBoneInfoGLTF(cgltf_skin skin, unsigned int *boneCount) { - *boneCount = (int)skin.joints_count; + *boneCount = (unsigned int)skin.joints_count; BoneInfo *bones = (BoneInfo *)RL_CALLOC(skin.joints_count, sizeof(BoneInfo)); for (unsigned int i = 0; i < skin.joints_count; i++) { cgltf_node node = *skin.joints[i]; - if (node.name != NULL) strncpy(bones[i].name, node.name, sizeof(bones[i].name) - 1); + if (node.name != NULL) snprintf(bones[i].name, sizeof(bones[i].name), "%s", node.name); // Find parent bone index by walking up the node tree past any // non-joint ancestors (intermediate transform nodes used by some @@ -6144,7 +6144,7 @@ static Model LoadGLTF(const char *fileName) model.skeleton.bones = LoadBoneInfoGLTF(skin, &model.skeleton.boneCount); model.skeleton.bindPose = (Transform *)RL_CALLOC(model.skeleton.boneCount, sizeof(Transform)); - for (int i = 0; i < model.skeleton.boneCount; i++) + for (unsigned int i = 0; i < model.skeleton.boneCount; i++) { Matrix bindMatrix = { 0 }; cgltf_float inverseBindTransform[16] = { 0 }; @@ -6309,7 +6309,7 @@ static Model LoadGLTF(const char *fileName) if ((data->skins_count > 0) && !hasJoints && (node->parent != NULL) && (node->parent->mesh == NULL)) { int parentBoneId = -1; - for (int joint = 0; joint < model.skeleton.boneCount; joint++) + for (unsigned int joint = 0; joint < model.skeleton.boneCount; joint++) { if (data->skins[0].joints[joint] == node->parent) { @@ -6347,7 +6347,7 @@ static Model LoadGLTF(const char *fileName) // Initialize runtime animation data: current pose and bone matrices model.currentPose = (Transform *)RL_CALLOC(model.skeleton.boneCount, sizeof(Transform)); model.boneMatrices = (Matrix *)RL_CALLOC(model.skeleton.boneCount, sizeof(Matrix)); - for (int j = 0; j < model.skeleton.boneCount; j++) model.boneMatrices[j] = MatrixIdentity(); + for (unsigned int j = 0; j < model.skeleton.boneCount; j++) model.boneMatrices[j] = MatrixIdentity(); //---------------------------------------------------------------------------------------------------- // Free unused allocated memory in case of no bones defined @@ -6660,7 +6660,7 @@ static ModelAnimation *LoadModelAnimationsGLTF(const char *fileName, int *animCo animDuration = (time > animDuration)? time : animDuration; } - if (animData.name != NULL) strncpy(animations[a].name, animData.name, sizeof(animations[a].name) - 1); + if (animData.name != NULL) snprintf(animations[a].name, sizeof(animations[a].name), "%s", animData.name); animations[a].keyframeCount = (int)(animDuration*GLTF_FRAMERATE) + 1; animations[a].keyframePoses = (Transform **)RL_CALLOC(animations[a].keyframeCount, sizeof(Transform *)); @@ -6670,7 +6670,7 @@ static ModelAnimation *LoadModelAnimationsGLTF(const char *fileName, int *animCo animations[a].keyframePoses[j] = (Transform *)RL_CALLOC(animations[a].boneCount, sizeof(Transform)); float time = (float)j / GLTF_FRAMERATE; - for (int k = 0; k < animations[a].boneCount; k++) + for (unsigned int k = 0; k < animations[a].boneCount; k++) { Vector3 translation = {skin.joints[k]->translation[0], skin.joints[k]->translation[1], skin.joints[k]->translation[2]}; Quaternion rotation = {skin.joints[k]->rotation[0], skin.joints[k]->rotation[1], skin.joints[k]->rotation[2], skin.joints[k]->rotation[3]}; @@ -7150,7 +7150,7 @@ static Model LoadM3D(const char *fileName) for (i = 0; i < (int)m3d->numbone; i++) { model.skeleton.bones[i].parent = m3d->bone[i].parent; - strncpy(model.skeleton.bones[i].name, m3d->bone[i].name, sizeof(model.skeleton.bones[i].name) - 1); + snprintf(model.skeleton.bones[i].name, sizeof(model.skeleton.bones[i].name), "%s", m3d->bone[i].name); model.skeleton.bindPose[i].translation.x = m3d->vertex[m3d->bone[i].pos].x*m3d->scale; model.skeleton.bindPose[i].translation.y = m3d->vertex[m3d->bone[i].pos].y*m3d->scale; model.skeleton.bindPose[i].translation.z = m3d->vertex[m3d->bone[i].pos].z*m3d->scale; @@ -7204,7 +7204,7 @@ static Model LoadM3D(const char *fileName) // Initialize runtime animation data: current pose and bone matrices model.currentPose = (Transform *)RL_CALLOC(model.skeleton.boneCount, sizeof(Transform)); model.boneMatrices = (Matrix *)RL_CALLOC(model.skeleton.boneCount, sizeof(Matrix)); - for (int j = 0; j < model.skeleton.boneCount; j++) model.boneMatrices[j] = MatrixIdentity(); + for (unsigned int j = 0; j < model.skeleton.boneCount; j++) model.boneMatrices[j] = MatrixIdentity(); } m3d_free(m3d); @@ -7258,14 +7258,14 @@ static ModelAnimation *LoadModelAnimationsM3D(const char *fileName, int *animCou animations[a].keyframeCount = m3d->action[a].durationmsec/M3D_ANIMDELAY; animations[a].keyframePoses = (Transform **)RL_CALLOC(animations[a].keyframeCount, sizeof(Transform *)); - strncpy(animations[a].name, m3d->action[a].name, sizeof(animations[a].name) - 1); + snprintf(animations[a].name, sizeof(animations[a].name), "%s", m3d->action[a].name); TRACELOG(LOG_INFO, "MODEL: [%s] Loaded animation: %s | Frames: %d | Duration: %fs", fileName, animations[a].name, animations[a].keyframeCount, m3d->action[a].durationmsec); for (i = 0; i < (int)m3d->numbone; i++) { bones[i].parent = m3d->bone[i].parent; - strncpy(bones[i].name, m3d->bone[i].name, sizeof(bones[i].name) - 1); + snprintf(bones[i].name, sizeof(bones[i].name), "%s", m3d->bone[i].name); } // A special, never transformed "no bone" bone, used for boneless vertices diff --git a/src/rshapes.c b/src/rshapes.c index 12ae6a164..def6d36b2 100644 --- a/src/rshapes.c +++ b/src/rshapes.c @@ -888,14 +888,13 @@ void DrawRectangleRounded(Rectangle rec, float roundness, int segments, Color co // Draw rectangle with rounded edges void DrawRectangleRoundedLines(Rectangle rec, float roundness, int segments, Color color) { - // NOTE: For line thicknes <=1.0f using RL_LINES, otherwise using RL_QUADS/RL_TRIANGLES DrawRectangleRoundedLinesEx(rec, roundness, segments, 1.0f, color); } // Draw rectangle with rounded edges outline with line thickness void DrawRectangleRoundedLinesEx(Rectangle rec, float roundness, int segments, float thick, Color color) { - if (thick < 0) thick = 0; + if (thick <= 0) return; // Not a rounded rectangle if (roundness <= 0.0f) @@ -966,176 +965,145 @@ void DrawRectangleRoundedLinesEx(Rectangle rec, float roundness, int segments, f const float angles[4] = { 180.0f, 270.0f, 0.0f, 90.0f }; - if (thick > 1) - { #if SUPPORT_QUADS_DRAW_MODE - rlSetTexture(GetShapesTexture().id); - Rectangle shapeRect = GetShapesTextureRectangle(); + rlSetTexture(GetShapesTexture().id); + Rectangle shapeRect = GetShapesTextureRectangle(); - rlBegin(RL_QUADS); + rlBegin(RL_QUADS); - // Draw all the 4 corners first: Upper Left Corner, Upper Right Corner, Lower Right Corner, Lower Left Corner - for (int k = 0; k < 4; ++k) // Hope the compiler is smart enough to unroll this loop - { - float angle = angles[k]; - const Vector2 center = centers[k]; - for (int i = 0; i < segments; i++) - { - rlColor4ub(color.r, color.g, color.b, color.a); - - rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height); - rlVertex2f(center.x + cosf(DEG2RAD*angle)*innerRadius, center.y + sinf(DEG2RAD*angle)*innerRadius); - - rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height); - rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*innerRadius); - - rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height); - rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*outerRadius); - - rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height); - rlVertex2f(center.x + cosf(DEG2RAD*angle)*outerRadius, center.y + sinf(DEG2RAD*angle)*outerRadius); - - angle += stepLength; - } - } - - // Upper rectangle - rlColor4ub(color.r, color.g, color.b, color.a); - rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height); - rlVertex2f(point[0].x, point[0].y); - rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height); - rlVertex2f(point[8].x, point[8].y); - rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height); - rlVertex2f(point[9].x, point[9].y); - rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height); - rlVertex2f(point[1].x, point[1].y); - - // Right rectangle - rlColor4ub(color.r, color.g, color.b, color.a); - rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height); - rlVertex2f(point[2].x, point[2].y); - rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height); - rlVertex2f(point[10].x, point[10].y); - rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height); - rlVertex2f(point[11].x, point[11].y); - rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height); - rlVertex2f(point[3].x, point[3].y); - - // Lower rectangle - rlColor4ub(color.r, color.g, color.b, color.a); - rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height); - rlVertex2f(point[13].x, point[13].y); - rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height); - rlVertex2f(point[5].x, point[5].y); - rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height); - rlVertex2f(point[4].x, point[4].y); - rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height); - rlVertex2f(point[12].x, point[12].y); - - // Left rectangle - rlColor4ub(color.r, color.g, color.b, color.a); - rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height); - rlVertex2f(point[15].x, point[15].y); - rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height); - rlVertex2f(point[7].x, point[7].y); - rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height); - rlVertex2f(point[6].x, point[6].y); - rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height); - rlVertex2f(point[14].x, point[14].y); - - rlEnd(); - rlSetTexture(0); -#else - rlBegin(RL_TRIANGLES); - - // Draw all of the 4 corners first: Upper Left Corner, Upper Right Corner, Lower Right Corner, Lower Left Corner - for (int k = 0; k < 4; ++k) // Hope the compiler is smart enough to unroll this loop - { - float angle = angles[k]; - const Vector2 center = centers[k]; - - for (int i = 0; i < segments; i++) - { - rlColor4ub(color.r, color.g, color.b, color.a); - - rlVertex2f(center.x + cosf(DEG2RAD*angle)*innerRadius, center.y + sinf(DEG2RAD*angle)*innerRadius); - rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*innerRadius); - rlVertex2f(center.x + cosf(DEG2RAD*angle)*outerRadius, center.y + sinf(DEG2RAD*angle)*outerRadius); - - rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*innerRadius); - rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*outerRadius); - rlVertex2f(center.x + cosf(DEG2RAD*angle)*outerRadius, center.y + sinf(DEG2RAD*angle)*outerRadius); - - angle += stepLength; - } - } - - // Upper rectangle - rlColor4ub(color.r, color.g, color.b, color.a); - rlVertex2f(point[0].x, point[0].y); - rlVertex2f(point[8].x, point[8].y); - rlVertex2f(point[9].x, point[9].y); - rlVertex2f(point[1].x, point[1].y); - rlVertex2f(point[0].x, point[0].y); - rlVertex2f(point[9].x, point[9].y); - - // Right rectangle - rlColor4ub(color.r, color.g, color.b, color.a); - rlVertex2f(point[10].x, point[10].y); - rlVertex2f(point[11].x, point[11].y); - rlVertex2f(point[3].x, point[3].y); - rlVertex2f(point[2].x, point[2].y); - rlVertex2f(point[10].x, point[10].y); - rlVertex2f(point[3].x, point[3].y); - - // Lower rectangle - rlColor4ub(color.r, color.g, color.b, color.a); - rlVertex2f(point[13].x, point[13].y); - rlVertex2f(point[5].x, point[5].y); - rlVertex2f(point[4].x, point[4].y); - rlVertex2f(point[12].x, point[12].y); - rlVertex2f(point[13].x, point[13].y); - rlVertex2f(point[4].x, point[4].y); - - // Left rectangle - rlColor4ub(color.r, color.g, color.b, color.a); - rlVertex2f(point[7].x, point[7].y); - rlVertex2f(point[6].x, point[6].y); - rlVertex2f(point[14].x, point[14].y); - rlVertex2f(point[15].x, point[15].y); - rlVertex2f(point[7].x, point[7].y); - rlVertex2f(point[14].x, point[14].y); - rlEnd(); -#endif - } - else - { - // Use LINES to draw the outline - rlBegin(RL_LINES); - // Draw all the 4 corners first: Upper Left Corner, Upper Right Corner, Lower Right Corner, Lower Left Corner - for (int k = 0; k < 4; ++k) // Hope the compiler is smart enough to unroll this loop - { - float angle = angles[k]; - const Vector2 center = centers[k]; - - for (int i = 0; i < segments; i++) - { - rlColor4ub(color.r, color.g, color.b, color.a); - rlVertex2f(center.x + cosf(DEG2RAD*angle)*outerRadius, center.y + sinf(DEG2RAD*angle)*outerRadius); - rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*outerRadius); - angle += stepLength; - } - } - - // And now the remaining 4 lines - for (int i = 0; i < 8; i += 2) + // Draw all the 4 corners first: Upper Left Corner, Upper Right Corner, Lower Right Corner, Lower Left Corner + for (int k = 0; k < 4; ++k) // Hope the compiler is smart enough to unroll this loop + { + float angle = angles[k]; + const Vector2 center = centers[k]; + for (int i = 0; i < segments; i++) { rlColor4ub(color.r, color.g, color.b, color.a); - rlVertex2f(point[i].x, point[i].y); - rlVertex2f(point[i + 1].x, point[i + 1].y); + + rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height); + rlVertex2f(center.x + cosf(DEG2RAD*angle)*innerRadius, center.y + sinf(DEG2RAD*angle)*innerRadius); + + rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height); + rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*innerRadius); + + rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height); + rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*outerRadius); + + rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height); + rlVertex2f(center.x + cosf(DEG2RAD*angle)*outerRadius, center.y + sinf(DEG2RAD*angle)*outerRadius); + + angle += stepLength; } - rlEnd(); - } + } + + // Upper rectangle + rlColor4ub(color.r, color.g, color.b, color.a); + rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height); + rlVertex2f(point[0].x, point[0].y); + rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height); + rlVertex2f(point[8].x, point[8].y); + rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height); + rlVertex2f(point[9].x, point[9].y); + rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height); + rlVertex2f(point[1].x, point[1].y); + + // Right rectangle + rlColor4ub(color.r, color.g, color.b, color.a); + rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height); + rlVertex2f(point[2].x, point[2].y); + rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height); + rlVertex2f(point[10].x, point[10].y); + rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height); + rlVertex2f(point[11].x, point[11].y); + rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height); + rlVertex2f(point[3].x, point[3].y); + + // Lower rectangle + rlColor4ub(color.r, color.g, color.b, color.a); + rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height); + rlVertex2f(point[13].x, point[13].y); + rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height); + rlVertex2f(point[5].x, point[5].y); + rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height); + rlVertex2f(point[4].x, point[4].y); + rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height); + rlVertex2f(point[12].x, point[12].y); + + // Left rectangle + rlColor4ub(color.r, color.g, color.b, color.a); + rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height); + rlVertex2f(point[15].x, point[15].y); + rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height); + rlVertex2f(point[7].x, point[7].y); + rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height); + rlVertex2f(point[6].x, point[6].y); + rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height); + rlVertex2f(point[14].x, point[14].y); + + rlEnd(); + rlSetTexture(0); +#else + rlBegin(RL_TRIANGLES); + + // Draw all of the 4 corners first: Upper Left Corner, Upper Right Corner, Lower Right Corner, Lower Left Corner + for (int k = 0; k < 4; ++k) // Hope the compiler is smart enough to unroll this loop + { + float angle = angles[k]; + const Vector2 center = centers[k]; + + for (int i = 0; i < segments; i++) + { + rlColor4ub(color.r, color.g, color.b, color.a); + + rlVertex2f(center.x + cosf(DEG2RAD*angle)*innerRadius, center.y + sinf(DEG2RAD*angle)*innerRadius); + rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*innerRadius); + rlVertex2f(center.x + cosf(DEG2RAD*angle)*outerRadius, center.y + sinf(DEG2RAD*angle)*outerRadius); + + rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*innerRadius); + rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*outerRadius); + rlVertex2f(center.x + cosf(DEG2RAD*angle)*outerRadius, center.y + sinf(DEG2RAD*angle)*outerRadius); + + angle += stepLength; + } + } + + // Upper rectangle + rlColor4ub(color.r, color.g, color.b, color.a); + rlVertex2f(point[0].x, point[0].y); + rlVertex2f(point[8].x, point[8].y); + rlVertex2f(point[9].x, point[9].y); + rlVertex2f(point[1].x, point[1].y); + rlVertex2f(point[0].x, point[0].y); + rlVertex2f(point[9].x, point[9].y); + + // Right rectangle + rlColor4ub(color.r, color.g, color.b, color.a); + rlVertex2f(point[10].x, point[10].y); + rlVertex2f(point[11].x, point[11].y); + rlVertex2f(point[3].x, point[3].y); + rlVertex2f(point[2].x, point[2].y); + rlVertex2f(point[10].x, point[10].y); + rlVertex2f(point[3].x, point[3].y); + + // Lower rectangle + rlColor4ub(color.r, color.g, color.b, color.a); + rlVertex2f(point[13].x, point[13].y); + rlVertex2f(point[5].x, point[5].y); + rlVertex2f(point[4].x, point[4].y); + rlVertex2f(point[12].x, point[12].y); + rlVertex2f(point[13].x, point[13].y); + rlVertex2f(point[4].x, point[4].y); + + // Left rectangle + rlColor4ub(color.r, color.g, color.b, color.a); + rlVertex2f(point[7].x, point[7].y); + rlVertex2f(point[6].x, point[6].y); + rlVertex2f(point[14].x, point[14].y); + rlVertex2f(point[15].x, point[15].y); + rlVertex2f(point[7].x, point[7].y); + rlVertex2f(point[14].x, point[14].y); + rlEnd(); +#endif } // Draw a polygon of n sides diff --git a/src/rtext.c b/src/rtext.c index df9978838..556aef95d 100644 --- a/src/rtext.c +++ b/src/rtext.c @@ -58,8 +58,8 @@ #include "rlgl.h" // OpenGL abstraction layer to OpenGL 1.1, 2.1, 3.3+ or ES2 -> Only DrawTextPro() #include // Required for: malloc(), free() -#include // Required for: vsprintf() -#include // Required for: strcmp(), strstr(), strncpy() [Used in TextReplace()], sscanf() [Used in LoadBMFont()] +#include // Required for: vsprintf(), snprintf() +#include // Required for: strcmp(), strstr(), strncpy(), sscanf() [Used in LoadBMFont()] #include // Required for: va_list, va_start(), vsprintf(), va_end() [Used in TextFormat()] #include // Required for: toupper(), tolower() [Used in TextToUpper(), TextToLower()] @@ -539,7 +539,7 @@ Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int Font font = { 0 }; char fileExtLower[16] = { 0 }; - strncpy(fileExtLower, TextToLower(fileType), 16 - 1); + snprintf(fileExtLower, 16, "%s", TextToLower(fileType)); font.baseSize = fontSize; font.glyphPadding = 0; @@ -1043,7 +1043,7 @@ bool ExportFontAsCode(Font font, const char *fileName) // Get file name from path char fileNamePascal[256] = { 0 }; - strncpy(fileNamePascal, TextToPascal(GetFileNameWithoutExt(fileName)), 256 - 1); + snprintf(fileNamePascal, 256, "%s", TextToPascal(GetFileNameWithoutExt(fileName))); // Get font atlas image and size, required to estimate code file size // NOTE: This mechanism is highly coupled to raylib @@ -1545,7 +1545,7 @@ char **LoadTextLines(const char *text, int *count) if ((text[i] == '\n') || (text[i] == '\0')) { lines[l] = (char *)RL_CALLOC(lineLen + 1, 1); - strncpy(lines[l], &text[i - lineLen], lineLen); + memcpy(lines[l], &text[i - lineLen], lineLen); lineLen = 0; l++; } @@ -1712,7 +1712,7 @@ const char *TextSubtext(const char *text, int position, int length) static char buffer[MAX_TEXT_BUFFER_LENGTH] = { 0 }; memset(buffer, 0, MAX_TEXT_BUFFER_LENGTH); - if (text != NULL) + if ((text != NULL) && (position >= 0) && (length > 0)) { int textLength = TextLength(text); @@ -1768,8 +1768,8 @@ char *GetTextBetween(const char *text, const char *begin, const char *end) { endIndex += (beginIndex + beginLen); int len = (endIndex - beginIndex - beginLen); - if (len < (MAX_TEXT_BUFFER_LENGTH - 1)) strncpy(buffer, text + beginIndex + beginLen, len); - else strncpy(buffer, text + beginIndex + beginLen, MAX_TEXT_BUFFER_LENGTH - 1); + if (len < (MAX_TEXT_BUFFER_LENGTH - 1)) memcpy(buffer, text + beginIndex + beginLen, len); + else snprintf(buffer, MAX_TEXT_BUFFER_LENGTH, "%s", text + beginIndex + beginLen); } } @@ -1777,7 +1777,7 @@ char *GetTextBetween(const char *text, const char *begin, const char *end) } // Replace text string -// REQUIRES: strstr(), strncpy() +// REQUIRES: strstr(), memcpy() // NOTE: Limited text replace functionality, using static string char *TextReplace(const char *text, const char *search, const char *replacement) { @@ -1834,7 +1834,7 @@ char *TextReplace(const char *text, const char *search, const char *replacement) // Copy remaind text part after replacement to result (pointed by moving temp) // NOTE: Text pointer internal copy has been updated along the process - strncpy(tempPtr, text, TextLength(text)); + memcpy(tempPtr, text, TextLength(text)); } else TRACELOG(LOG_WARNING, "Text with replacement is longer than internal buffer, use TextReplaceAlloc()"); } @@ -1843,7 +1843,7 @@ char *TextReplace(const char *text, const char *search, const char *replacement) } // Replace text string -// REQUIRES: strstr(), strncpy() +// REQUIRES: strstr(), memcpy() // WARNING: Allocated memory must be manually freed char *TextReplaceAlloc(const char *text, const char *search, const char *replacement) { @@ -1900,7 +1900,7 @@ char *TextReplaceAlloc(const char *text, const char *search, const char *replace // Copy remaind text part after replacement to result (pointed by moving temp) // NOTE: Text pointer internal copy has been updated along the process - strncpy(temp, text, TextLength(text)); + memcpy(temp, text, TextLength(text)); } } @@ -1988,10 +1988,11 @@ char *TextInsert(const char *text, const char *insert, int position) { static char buffer[MAX_TEXT_BUFFER_LENGTH] = { 0 }; memset(buffer, 0, MAX_TEXT_BUFFER_LENGTH); + int textLen = TextLength(text); - if ((text != NULL) && (insert != NULL)) + if ((text != NULL) && (insert != NULL) && (position >= 0)) { - int textLen = TextLength(text); + if (position > textLen) position = textLen; // End of text string int insertLen = TextLength(insert); if ((textLen + insertLen) < (MAX_TEXT_BUFFER_LENGTH - 1)) @@ -2000,7 +2001,7 @@ char *TextInsert(const char *text, const char *insert, int position) for (int i = 0; i < position; i++) buffer[i] = text[i]; for (int i = position; i < insertLen + position; i++) buffer[i] = insert[i - position]; - for (int i = (insertLen + position); i < (textLen + insertLen); i++) buffer[i] = text[i]; + for (int i = (insertLen + position); i < (textLen + insertLen); i++) buffer[i] = text[i - insertLen]; buffer[textLen + insertLen] = '\0'; // Add EOL } @@ -2015,17 +2016,18 @@ char *TextInsert(const char *text, const char *insert, int position) char *TextInsertAlloc(const char *text, const char *insert, int position) { char *result = NULL; + int textLen = TextLength(text); - if ((text != NULL) && (insert != NULL)) + if ((text != NULL) && (insert != NULL) && (position >= 0)) { - int textLen = TextLength(text); + if (position > textLen) position = textLen; // End of text string int insertLen = TextLength(insert); result = (char *)RL_MALLOC(textLen + insertLen + 1); for (int i = 0; i < position; i++) result[i] = text[i]; - for (int i = position; i < insertLen + position; i++) result[i] = insert[i - position]; - for (int i = (insertLen + position); i < (textLen + insertLen); i++) result[i] = text[i]; + for (int i = position; i < (insertLen + position); i++) result[i] = insert[i - position]; + for (int i = (insertLen + position); i < (textLen + insertLen); i++) result[i] = text[i - insertLen]; result[textLen + insertLen] = '\0'; // Add EOL } @@ -2049,7 +2051,7 @@ char *TextJoin(char **textList, int count, const char *delimiter) int textLength = TextLength(textList[i]); // Make sure joined text could fit inside MAX_TEXT_BUFFER_LENGTH - if ((totalLength + textLength) < MAX_TEXT_BUFFER_LENGTH) + if ((totalLength + textLength + delimiterLen) < MAX_TEXT_BUFFER_LENGTH) { memcpy(textPtr, textList[i], textLength); totalLength += textLength; diff --git a/src/rtextures.c b/src/rtextures.c index 6092cb57c..61e528d47 100644 --- a/src/rtextures.c +++ b/src/rtextures.c @@ -70,6 +70,7 @@ #include // Required for: strlen() [Used in ImageTextEx()], strcmp() [Used in LoadImageFromMemory()/LoadImageAnimFromMemory()/ExportImageToMemory()] #include // Required for: fabsf() [Used in DrawTextureRec()] #include // Required for: sprintf() [Used in ExportImageAsCode()] +#include // Required for: INT_MAX // Support only desired texture formats on stb_image #if !SUPPORT_FILEFORMAT_BMP @@ -813,7 +814,7 @@ bool ExportImageAsCode(Image image, const char *fileName) // Get file name from path and convert variable name to uppercase char varFileName[256] = { 0 }; - strncpy(varFileName, GetFileNameWithoutExt(fileName), 256 - 1); // NOTE: Using function provided by [rcore] module + snprintf(varFileName, 256, "%s", GetFileNameWithoutExt(fileName)); // NOTE: Using function provided by [rcore] module for (int i = 0; varFileName[i] != '\0'; i++) if ((varFileName[i] >= 'a') && (varFileName[i] <= 'z')) { varFileName[i] = varFileName[i] - 32; } // Add image information @@ -843,9 +844,10 @@ bool ExportImageAsCode(Image image, const char *fileName) // Generate image: plain color Image GenImageColor(int width, int height, Color color) { - Color *pixels = (Color *)RL_CALLOC(width*height, sizeof(Color)); + int dataSize = GetPixelDataSize(width, height, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8); + Color *pixels = (Color *)RL_CALLOC(dataSize, 1); - for (int i = 0; i < width*height; i++) pixels[i] = color; + for (int i = 0; (pixels != NULL) && (i < width*height); i++) pixels[i] = color; Image image = { .data = pixels, @@ -1228,18 +1230,25 @@ Image ImageFromImage(Image image, Rectangle rec) { Image result = { 0 }; - int bytesPerPixel = GetPixelDataSize(1, 1, image.format); - - result.width = (int)rec.width; - result.height = (int)rec.height; - result.data = RL_CALLOC((int)rec.width*(int)rec.height*bytesPerPixel, 1); - result.format = image.format; - result.mipmaps = 1; - - for (int y = 0; y < (int)rec.height; y++) + // Basic rectangle validation: size smaller than image size + if ((rec.x >= 0) && (rec.y >= 0) && (rec.width > 0) && (rec.height > 0) && + (((int)rec.x + (int)rec.width) <= image.width) && + (((int)rec.y + (int)rec.height) <= image.height)) { - memcpy(((unsigned char *)result.data) + y*(int)rec.width*bytesPerPixel, ((unsigned char *)image.data) + ((y + (int)rec.y)*image.width + (int)rec.x)*bytesPerPixel, (int)rec.width*bytesPerPixel); + int bytesPerPixel = GetPixelDataSize(1, 1, image.format); + + result.width = (int)rec.width; + result.height = (int)rec.height; + result.data = RL_CALLOC((int)rec.width*(int)rec.height*bytesPerPixel, 1); + result.format = image.format; + result.mipmaps = 1; + + for (int y = 0; y < (int)rec.height; y++) + { + memcpy(((unsigned char *)result.data) + y*(int)rec.width*bytesPerPixel, ((unsigned char *)image.data) + ((y + (int)rec.y)*image.width + (int)rec.x)*bytesPerPixel, (int)rec.width*bytesPerPixel); + } } + else TRACELOG(LOG_WARNING, "IMAGE: Rectangle provided for ImageToImage not valid"); return result; } @@ -2684,45 +2693,49 @@ void ImageRotate(Image *image, int degrees) int width = (int)(fabsf(image->width*cosRadius) + fabsf(image->height*sinRadius)); int height = (int)(fabsf(image->height*cosRadius) + fabsf(image->width*sinRadius)); + int dataSize = GetPixelDataSize(width, height, image->format); int bytesPerPixel = GetPixelDataSize(1, 1, image->format); - unsigned char *rotatedData = (unsigned char *)RL_CALLOC(width*height, bytesPerPixel); + unsigned char *rotatedData = (unsigned char *)RL_CALLOC(dataSize, 1); - for (int y = 0; y < height; y++) + if (rotatedData != NULL) { - for (int x = 0; x < width; x++) + for (int y = 0; y < height; y++) { - float oldX = ((x - width/2.0f)*cosRadius + (y - height/2.0f)*sinRadius) + image->width/2.0f; - float oldY = ((y - height/2.0f)*cosRadius - (x - width/2.0f)*sinRadius) + image->height/2.0f; - - if ((oldX >= 0) && (oldX < image->width) && (oldY >= 0) && (oldY < image->height)) + for (int x = 0; x < width; x++) { - int x1 = (int)floorf(oldX); - int y1 = (int)floorf(oldY); - int x2 = MIN(x1 + 1, image->width - 1); - int y2 = MIN(y1 + 1, image->height - 1); + float oldX = ((x - width/2.0f)*cosRadius + (y - height/2.0f)*sinRadius) + image->width/2.0f; + float oldY = ((y - height/2.0f)*cosRadius - (x - width/2.0f)*sinRadius) + image->height/2.0f; - float px = oldX - x1; - float py = oldY - y1; - - for (int i = 0; i < bytesPerPixel; i++) + if ((oldX >= 0) && (oldX < image->width) && (oldY >= 0) && (oldY < image->height)) { - float f1 = ((unsigned char *)image->data)[(y1*image->width + x1)*bytesPerPixel + i]; - float f2 = ((unsigned char *)image->data)[(y1*image->width + x2)*bytesPerPixel + i]; - float f3 = ((unsigned char *)image->data)[(y2*image->width + x1)*bytesPerPixel + i]; - float f4 = ((unsigned char *)image->data)[(y2*image->width + x2)*bytesPerPixel + i]; + int x1 = (int)floorf(oldX); + int y1 = (int)floorf(oldY); + int x2 = MIN(x1 + 1, image->width - 1); + int y2 = MIN(y1 + 1, image->height - 1); - float val = f1*(1 - px)*(1 - py) + f2*px*(1 - py) + f3*(1 - px)*py + f4*px*py; + float px = oldX - x1; + float py = oldY - y1; - rotatedData[(y*width + x)*bytesPerPixel + i] = (unsigned char)val; + for (int i = 0; i < bytesPerPixel; i++) + { + float f1 = ((unsigned char *)image->data)[(y1*image->width + x1)*bytesPerPixel + i]; + float f2 = ((unsigned char *)image->data)[(y1*image->width + x2)*bytesPerPixel + i]; + float f3 = ((unsigned char *)image->data)[(y2*image->width + x1)*bytesPerPixel + i]; + float f4 = ((unsigned char *)image->data)[(y2*image->width + x2)*bytesPerPixel + i]; + + float val = f1*(1 - px)*(1 - py) + f2*px*(1 - py) + f3*(1 - px)*py + f4*px*py; + + rotatedData[(y*width + x)*bytesPerPixel + i] = (unsigned char)val; + } } } } - } - RL_FREE(image->data); - image->data = rotatedData; - image->width = width; - image->height = height; + RL_FREE(image->data); + image->data = rotatedData; + image->width = width; + image->height = height; + } } } @@ -3927,7 +3940,7 @@ void ImageDrawRectanglePro(Image *dst, Rectangle rec, Vector2 origin, float rota // Draw rectangle lines within an image void ImageDrawRectangleLines(Image *dst, int posX, int posY, int width, int height, Color color) { - Rectangle rec = { posX, posY, width, height }; + Rectangle rec = { (float)posX, (float)posY, (float)width, (float)height }; ImageDrawRectangleLinesEx(dst, rec, 1, color); } @@ -4019,8 +4032,8 @@ void ImageDrawCircleGradient(Image *dst, Vector2 center, float radius, Color inn // Draw an image within an image void ImageDrawImage(Image *dst, Image src, int posX, int posY, Color tint) { - Rectangle srcRec = { 0, 0, src.width, src.height }; - Rectangle dstRec = { posX, posY, srcRec.width, srcRec.height }; + Rectangle srcRec = { 0.0f, 0.0f, (float)src.width, (float)src.height }; + Rectangle dstRec = { (float)posX, (float)posY, srcRec.width, srcRec.height }; ImageDrawImagePro(dst, src, srcRec, dstRec, (Vector2){ 0 }, 0.0f, tint); } @@ -5501,17 +5514,24 @@ int GetPixelDataSize(int width, int height, int format) case PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA: bpp = 2; break; default: break; } + + unsigned long long dataSizeBytes = ((unsigned long long)width*height*bpp) >> 3; // Get size in bytes (dividing by 8) - double bytesPerPixel = (double)bpp/8.0; - dataSize = (int)(bytesPerPixel*width*height); // Total data size in bytes - - // Most compressed formats works on 4x4 blocks, - // if texture is smaller, minimum dataSize is 8 or 16 - if ((width < 4) && (height < 4)) + if (dataSizeBytes < INT_MAX) { - if ((format >= PIXELFORMAT_COMPRESSED_DXT1_RGB) && (format < PIXELFORMAT_COMPRESSED_DXT3_RGBA)) dataSize = 8; - else if ((format >= PIXELFORMAT_COMPRESSED_DXT3_RGBA) && (format < PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA)) dataSize = 16; + dataSize = (int)dataSizeBytes; + + // Most compressed formats works on 4x4 blocks, + // if texture is smaller, minimum dataSize is 8 or 16 + if ((width < 4) && (height < 4)) + { + if ((format >= PIXELFORMAT_COMPRESSED_DXT1_RGB) && (format < PIXELFORMAT_COMPRESSED_DXT3_RGBA)) dataSize = 8; + else if ((format >= PIXELFORMAT_COMPRESSED_DXT3_RGBA) && (format < PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA)) dataSize = 16; + } } + + // NOTE: In case required image data larger than 2GB, no memory allocated at all (NULL) + if (dataSize == 0) TRACELOG(LOG_WARNING, "Requested image size is larger than 2GB, it can not be allocated"); return dataSize; } diff --git a/tools/rexm/rexm.c b/tools/rexm/rexm.c index f268a7d44..cb753e031 100644 --- a/tools/rexm/rexm.c +++ b/tools/rexm/rexm.c @@ -2331,7 +2331,7 @@ static rlExampleInfo *LoadExampleInfo(const char *exFileName) // Example found in collection exInfo = (rlExampleInfo *)RL_CALLOC(1, sizeof(rlExampleInfo)); - strncpy(exInfo->name, GetFileNameWithoutExt(exFileName), 128 - 1); + snprintf(exInfo->name, 128, "%s", GetFileNameWithoutExt(exFileName)); strncpy(exInfo->category, exInfo->name, TextFindIndex(exInfo->name, "_")); char *exText = LoadFileText(exFileName); @@ -2377,7 +2377,7 @@ static rlExampleInfo *LoadExampleInfo(const char *exFileName) int copyrightIndex = TextFindIndex(exText, "Copyright (c) "); int yearStartIndex = copyrightIndex + 14; char yearText[5] = { 0 }; - strncpy(yearText, exText + yearStartIndex, 4); + snprintf(yearText, 5, "%s", exText + yearStartIndex); exInfo->yearCreated = TextToInteger(yearText); // Check for review year included (or just use creation year) if (exText[yearStartIndex + 4] == '-') strncpy(yearText, exText + yearStartIndex + 5, 4); @@ -2425,7 +2425,7 @@ static int ParseExampleInfoLine(const char *line, rlExampleInfo *entry) #define MAX_EXAMPLE_INFO_LINE_LEN 512 char temp[MAX_EXAMPLE_INFO_LINE_LEN] = { 0 }; - strncpy(temp, line, MAX_EXAMPLE_INFO_LINE_LEN); + snprintf(temp, MAX_EXAMPLE_INFO_LINE_LEN, "%s", line); temp[MAX_EXAMPLE_INFO_LINE_LEN - 1] = '\0'; // Ensure null termination int tokenCount = 0; @@ -2902,7 +2902,7 @@ static void UpdateWebMetadata(const char *exHtmlPath, const char *exFilePath) char exTitle[64] = { 0 }; // Example title: fileName without extension, replacing underscores by spaces // Get example name: replace underscore by spaces - strncpy(exName, GetFileNameWithoutExt(exHtmlPathCopy), 64 - 1); + snprintf(exName, 64, "%s", GetFileNameWithoutExt(exHtmlPathCopy)); strcpy(exTitle, exName); for (int i = 0; (i < 64) && (exTitle[i] != '\0'); i++) { if (exTitle[i] == '_') exTitle[i] = ' '; } diff --git a/tools/rlparser/output/raylib_api.json b/tools/rlparser/output/raylib_api.json index de1ebc884..2e6916737 100644 --- a/tools/rlparser/output/raylib_api.json +++ b/tools/rlparser/output/raylib_api.json @@ -968,7 +968,7 @@ "description": "Skeleton, animation bones hierarchy", "fields": [ { - "type": "int", + "type": "unsigned int", "name": "boneCount", "description": "Number of bones" }, @@ -1045,7 +1045,7 @@ "description": "Animation name" }, { - "type": "int", + "type": "unsigned int", "name": "boneCount", "description": "Number of bones (per pose)" }, diff --git a/tools/rlparser/output/raylib_api.lua b/tools/rlparser/output/raylib_api.lua index 98308682d..574cfbf2d 100644 --- a/tools/rlparser/output/raylib_api.lua +++ b/tools/rlparser/output/raylib_api.lua @@ -968,7 +968,7 @@ return { description = "Skeleton, animation bones hierarchy", fields = { { - type = "int", + type = "unsigned int", name = "boneCount", description = "Number of bones" }, @@ -1045,7 +1045,7 @@ return { description = "Animation name" }, { - type = "int", + type = "unsigned int", name = "boneCount", description = "Number of bones (per pose)" }, diff --git a/tools/rlparser/output/raylib_api.sexpr b/tools/rlparser/output/raylib_api.sexpr index e4dee877c..e57c282a3 100644 --- a/tools/rlparser/output/raylib_api.sexpr +++ b/tools/rlparser/output/raylib_api.sexpr @@ -611,7 +611,7 @@ ((name "ModelSkeleton") (description "Skeleton, animation bones hierarchy") (fields - ((type "int") + ((type "unsigned int") (name "boneCount") (description "Number of bones")) ((type "BoneInfo *") @@ -658,7 +658,7 @@ ((type "char[32]") (name "name") (description "Animation name")) - ((type "int") + ((type "unsigned int") (name "boneCount") (description "Number of bones (per pose)")) ((type "int") diff --git a/tools/rlparser/output/raylib_api.txt b/tools/rlparser/output/raylib_api.txt index 77a1dba1f..d0d60463c 100644 --- a/tools/rlparser/output/raylib_api.txt +++ b/tools/rlparser/output/raylib_api.txt @@ -448,7 +448,7 @@ Struct 20: BoneInfo (2 fields) Struct 21: ModelSkeleton (3 fields) Name: ModelSkeleton Description: Skeleton, animation bones hierarchy - Field[1]: int boneCount // Number of bones + Field[1]: unsigned int boneCount // Number of bones Field[2]: BoneInfo * bones // Bones information (skeleton) Field[3]: ModelAnimPose bindPose // Bones base transformation (Transform[]) Struct 22: Model (9 fields) @@ -467,7 +467,7 @@ Struct 23: ModelAnimation (4 fields) Name: ModelAnimation Description: ModelAnimation, contains a full animation sequence Field[1]: char[32] name // Animation name - Field[2]: int boneCount // Number of bones (per pose) + Field[2]: unsigned int boneCount // Number of bones (per pose) Field[3]: int keyframeCount // Number of animation key frames Field[4]: ModelAnimPose * keyframePoses // Animation sequence keyframe poses [keyframe][pose] Struct 24: Ray (2 fields) diff --git a/tools/rlparser/output/raylib_api.xml b/tools/rlparser/output/raylib_api.xml index b86c28b7a..77eb75c73 100644 --- a/tools/rlparser/output/raylib_api.xml +++ b/tools/rlparser/output/raylib_api.xml @@ -201,7 +201,7 @@ - + @@ -218,7 +218,7 @@ - +