diff --git a/.github/workflows/analyze_codeql.yml b/.github/workflows/analyze_codeql.yml
index 98d32a499..5fd169dd0 100644
--- a/.github/workflows/analyze_codeql.yml
+++ b/.github/workflows/analyze_codeql.yml
@@ -71,7 +71,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
- uses: github/codeql-action/init@v2
+ uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
@@ -90,7 +90,7 @@ jobs:
cmake --build . --config $BUILD_TYPE
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@v2
+ uses: github/codeql-action/analyze@v3
with:
category: "/language:${{matrix.language}}"
upload: false
diff --git a/.github/workflows/parse_api.yml b/.github/workflows/parse_api.yml
index c8665e1d4..ce7cb9f9a 100644
--- a/.github/workflows/parse_api.yml
+++ b/.github/workflows/parse_api.yml
@@ -32,6 +32,6 @@ jobs:
set -x
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
- git add tools/parser
- git commit -m "Update raylib_api.* by CI"
+ git add tools/rlparser
+ git commit -m "rlparser: update raylib_api.* by CI"
git push
diff --git a/CMakeOptions.txt b/CMakeOptions.txt
index 3c1c12742..32cfb814e 100644
--- a/CMakeOptions.txt
+++ b/CMakeOptions.txt
@@ -8,7 +8,7 @@ if(EMSCRIPTEN)
endif()
enum_option(PLATFORM "Desktop;Web;Android;Raspberry Pi;DRM;SDL" "Platform to build for.")
-enum_option(OPENGL_VERSION "OFF;4.3;3.3;2.1;1.1;ES 2.0;ES 3.0" "Force a specific OpenGL Version?")
+enum_option(OPENGL_VERSION "OFF;4.3;3.3;2.1;1.1;ES 2.0;ES 3.0;Software" "Force a specific OpenGL Version?")
# Configuration options
option(BUILD_EXAMPLES "Build the examples." ${PROJECT_IS_TOP_LEVEL})
diff --git a/build.zig b/build.zig
index a8f0df618..031a6824d 100644
--- a/build.zig
+++ b/build.zig
@@ -386,6 +386,8 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.
setDesktopPlatform(raylib, options.platform);
},
.emscripten => {
+ const activate_emsdk_step = emsdk.zemscripten.activateEmsdkStep(b);
+ raylib.step.dependOn(activate_emsdk_step);
raylib.root_module.addCMacro("PLATFORM_WEB", "");
if (options.opengl_version == .auto) {
raylib.root_module.addCMacro("GRAPHICS_API_OPENGL_ES3", "");
diff --git a/cmake/LibraryConfigurations.cmake b/cmake/LibraryConfigurations.cmake
index 98c7f2362..8f127fc23 100644
--- a/cmake/LibraryConfigurations.cmake
+++ b/cmake/LibraryConfigurations.cmake
@@ -158,6 +158,8 @@ if (NOT ${OPENGL_VERSION} MATCHES "OFF")
set(GRAPHICS "GRAPHICS_API_OPENGL_ES2")
elseif (${OPENGL_VERSION} MATCHES "ES 3.0")
set(GRAPHICS "GRAPHICS_API_OPENGL_ES3")
+ elseif (${OPENGL_VERSION} MATCHES "Software")
+ set(GRAPHICS "GRAPHICS_API_OPENGL_11_SOFTWARE")
endif ()
if (NOT "${SUGGESTED_GRAPHICS}" STREQUAL "" AND NOT "${SUGGESTED_GRAPHICS}" STREQUAL "${GRAPHICS}")
message(WARNING "You are overriding the suggested GRAPHICS=${SUGGESTED_GRAPHICS} with ${GRAPHICS}! This may fail.")
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index e63c1a7c8..b482df0fc 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -105,6 +105,10 @@ elseif ("${PLATFORM}" STREQUAL "DRM")
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/others/rlgl_standalone.c)
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/others/raylib_opengl_interop.c)
+elseif ("${OPENGL_VERSION}" STREQUAL "Software")
+ list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/others/rlgl_standalone.c)
+ list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/others/raylib_opengl_interop.c)
+
elseif (NOT SUPPORT_GESTURES_SYSTEM)
# Items requiring gestures system
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/textures/textures_mouse_painting.c)
diff --git a/examples/Makefile b/examples/Makefile
index ee17bb350..6e2853edb 100644
--- a/examples/Makefile
+++ b/examples/Makefile
@@ -355,7 +355,7 @@ ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_R
ifeq ($(BUILD_WEB_WEBGL2),TRUE)
LDFLAGS += -sMIN_WEBGL_VERSION=2 -sMAX_WEBGL_VERSION=2
endif
-
+
# Add resources building if required
ifeq ($(BUILD_WEB_RESOURCES),TRUE)
LDFLAGS += --preload-file $(BUILD_WEB_RESOURCES_PATH)
@@ -514,8 +514,10 @@ CORE = \
core/core_basic_window \
core/core_custom_frame_control \
core/core_custom_logging \
+ core/core_delta_time \
core/core_drop_files \
core/core_high_dpi \
+ core/core_input_actions \
core/core_input_gamepad \
core/core_input_gestures \
core/core_input_gestures_testbed \
@@ -524,6 +526,7 @@ CORE = \
core/core_input_mouse_wheel \
core/core_input_multitouch \
core/core_input_virtual_controls \
+ core/core_monitor_change \
core/core_random_sequence \
core/core_random_values \
core/core_render_texture \
@@ -540,24 +543,30 @@ CORE = \
SHAPES = \
shapes/shapes_basic_shapes \
shapes/shapes_bouncing_ball \
+ shapes/shapes_bullet_hell \
shapes/shapes_circle_sector_drawing \
shapes/shapes_collision_area \
shapes/shapes_colors_palette \
+ shapes/shapes_dashed_line \
shapes/shapes_digital_clock \
shapes/shapes_double_pendulum \
shapes/shapes_easings_ball \
shapes/shapes_easings_box \
shapes/shapes_easings_rectangles \
shapes/shapes_following_eyes \
+ shapes/shapes_kaleidoscope \
shapes/shapes_lines_bezier \
shapes/shapes_logo_raylib \
shapes/shapes_logo_raylib_anim \
shapes/shapes_rectangle_advanced \
shapes/shapes_rectangle_scaling \
+ shapes/shapes_recursive_tree \
shapes/shapes_ring_drawing \
shapes/shapes_rounded_rectangle_drawing \
shapes/shapes_splines_drawing \
- shapes/shapes_top_down_lights
+ shapes/shapes_top_down_lights \
+ shapes/shapes_triangle_strip \
+ shapes/shapes_vector_angle
TEXTURES = \
textures/textures_background_scrolling \
@@ -606,12 +615,14 @@ TEXT = \
MODELS = \
models/models_animation_gpu_skinning \
models/models_animation_playing \
+ models/models_basic_voxel \
models/models_billboard_rendering \
models/models_bone_socket \
models/models_box_collisions \
models/models_cubicmap_rendering \
models/models_first_person_maze \
models/models_geometric_shapes \
+ models/models_geometry_textures_cube \
models/models_heightmap_rendering \
models/models_loading \
models/models_loading_gltf \
@@ -629,6 +640,7 @@ MODELS = \
models/models_yaw_pitch_roll
SHADERS = \
+ shaders/shaders_ascii_rendering \
shaders/shaders_basic_lighting \
shaders/shaders_basic_pbr \
shaders/shaders_custom_uniform \
@@ -673,9 +685,9 @@ OTHERS = \
others/easings_testbed \
others/embedded_files_loading \
others/raylib_opengl_interop \
- others/raymath_vector_angle \
others/rlgl_compute_shader \
- others/rlgl_standalone
+ others/rlgl_standalone \
+ others/web_basic_window
#EXAMPLES_LIST_END
# Define processes to execute
diff --git a/examples/Makefile.Web b/examples/Makefile.Web
index a16d57853..f1662a301 100644
--- a/examples/Makefile.Web
+++ b/examples/Makefile.Web
@@ -355,7 +355,7 @@ ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_R
ifeq ($(BUILD_WEB_WEBGL2),TRUE)
LDFLAGS += -sMIN_WEBGL_VERSION=2 -sMAX_WEBGL_VERSION=2
endif
-
+
# Add resources building if required
ifeq ($(BUILD_WEB_RESOURCES),TRUE)
LDFLAGS += --preload-file $(BUILD_WEB_RESOURCES_PATH)
@@ -514,8 +514,10 @@ CORE = \
core/core_basic_window \
core/core_custom_frame_control \
core/core_custom_logging \
+ core/core_delta_time \
core/core_drop_files \
core/core_high_dpi \
+ core/core_input_actions \
core/core_input_gamepad \
core/core_input_gestures \
core/core_input_gestures_testbed \
@@ -524,6 +526,7 @@ CORE = \
core/core_input_mouse_wheel \
core/core_input_multitouch \
core/core_input_virtual_controls \
+ core/core_monitor_change \
core/core_random_sequence \
core/core_random_values \
core/core_render_texture \
@@ -540,24 +543,30 @@ CORE = \
SHAPES = \
shapes/shapes_basic_shapes \
shapes/shapes_bouncing_ball \
+ shapes/shapes_bullet_hell \
shapes/shapes_circle_sector_drawing \
shapes/shapes_collision_area \
shapes/shapes_colors_palette \
+ shapes/shapes_dashed_line \
shapes/shapes_digital_clock \
shapes/shapes_double_pendulum \
shapes/shapes_easings_ball \
shapes/shapes_easings_box \
shapes/shapes_easings_rectangles \
shapes/shapes_following_eyes \
+ shapes/shapes_kaleidoscope \
shapes/shapes_lines_bezier \
shapes/shapes_logo_raylib \
shapes/shapes_logo_raylib_anim \
shapes/shapes_rectangle_advanced \
shapes/shapes_rectangle_scaling \
+ shapes/shapes_recursive_tree \
shapes/shapes_ring_drawing \
shapes/shapes_rounded_rectangle_drawing \
shapes/shapes_splines_drawing \
- shapes/shapes_top_down_lights
+ shapes/shapes_top_down_lights \
+ shapes/shapes_triangle_strip \
+ shapes/shapes_vector_angle
TEXTURES = \
textures/textures_background_scrolling \
@@ -606,12 +615,14 @@ TEXT = \
MODELS = \
models/models_animation_gpu_skinning \
models/models_animation_playing \
+ models/models_basic_voxel \
models/models_billboard_rendering \
models/models_bone_socket \
models/models_box_collisions \
models/models_cubicmap_rendering \
models/models_first_person_maze \
models/models_geometric_shapes \
+ models/models_geometry_textures_cube \
models/models_heightmap_rendering \
models/models_loading \
models/models_loading_gltf \
@@ -629,6 +640,7 @@ MODELS = \
models/models_yaw_pitch_roll
SHADERS = \
+ shaders/shaders_ascii_rendering \
shaders/shaders_basic_lighting \
shaders/shaders_basic_pbr \
shaders/shaders_custom_uniform \
@@ -726,12 +738,18 @@ core/core_custom_frame_control: core/core_custom_frame_control.c
core/core_custom_logging: core/core_custom_logging.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
+core/core_delta_time: core/core_delta_time.c
+ $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
+
core/core_drop_files: core/core_drop_files.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
core/core_high_dpi: core/core_high_dpi.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
+core/core_input_actions: core/core_input_actions.c
+ $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
+
core/core_input_gamepad: core/core_input_gamepad.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
--preload-file core/resources/ps3.png@resources/ps3.png \
@@ -758,6 +776,9 @@ core/core_input_multitouch: core/core_input_multitouch.c
core/core_input_virtual_controls: core/core_input_virtual_controls.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
+core/core_monitor_change: core/core_monitor_change.c
+ $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
+
core/core_random_sequence: core/core_random_sequence.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
@@ -802,6 +823,9 @@ shapes/shapes_basic_shapes: shapes/shapes_basic_shapes.c
shapes/shapes_bouncing_ball: shapes/shapes_bouncing_ball.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
+shapes/shapes_bullet_hell: shapes/shapes_bullet_hell.c
+ $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
+
shapes/shapes_circle_sector_drawing: shapes/shapes_circle_sector_drawing.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
@@ -811,6 +835,9 @@ shapes/shapes_collision_area: shapes/shapes_collision_area.c
shapes/shapes_colors_palette: shapes/shapes_colors_palette.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
+shapes/shapes_dashed_line: shapes/shapes_dashed_line.c
+ $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
+
shapes/shapes_digital_clock: shapes/shapes_digital_clock.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
@@ -829,6 +856,9 @@ shapes/shapes_easings_rectangles: shapes/shapes_easings_rectangles.c
shapes/shapes_following_eyes: shapes/shapes_following_eyes.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
+shapes/shapes_kaleidoscope: shapes/shapes_kaleidoscope.c
+ $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
+
shapes/shapes_lines_bezier: shapes/shapes_lines_bezier.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
@@ -844,6 +874,9 @@ shapes/shapes_rectangle_advanced: shapes/shapes_rectangle_advanced.c
shapes/shapes_rectangle_scaling: shapes/shapes_rectangle_scaling.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
+shapes/shapes_recursive_tree: shapes/shapes_recursive_tree.c
+ $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
+
shapes/shapes_ring_drawing: shapes/shapes_ring_drawing.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
@@ -856,6 +889,12 @@ shapes/shapes_splines_drawing: shapes/shapes_splines_drawing.c
shapes/shapes_top_down_lights: shapes/shapes_top_down_lights.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
+shapes/shapes_triangle_strip: shapes/shapes_triangle_strip.c
+ $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
+
+shapes/shapes_vector_angle: shapes/shapes_vector_angle.c
+ $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
+
# Compile TEXTURES examples
textures/textures_background_scrolling: textures/textures_background_scrolling.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
@@ -1045,6 +1084,9 @@ models/models_animation_playing: models/models_animation_playing.c
--preload-file models/resources/models/iqm/guytex.png@resources/models/iqm/guytex.png \
--preload-file models/resources/models/iqm/guyanim.iqm@resources/models/iqm/guyanim.iqm
+models/models_basic_voxel: models/models_basic_voxel.c
+ $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
+
models/models_billboard_rendering: models/models_billboard_rendering.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
--preload-file models/resources/billboard.png@resources/billboard.png
@@ -1072,6 +1114,10 @@ models/models_first_person_maze: models/models_first_person_maze.c
models/models_geometric_shapes: models/models_geometric_shapes.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
+models/models_geometry_textures_cube: models/models_geometry_textures_cube.c
+ $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
+ --preload-file models/resources/cubicmap_atlas.png@resources/cubicmap_atlas.png
+
models/models_heightmap_rendering: models/models_heightmap_rendering.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
--preload-file models/resources/heightmap.png@resources/heightmap.png
@@ -1140,6 +1186,12 @@ models/models_yaw_pitch_roll: models/models_yaw_pitch_roll.c
--preload-file models/resources/models/obj/plane_diffuse.png@resources/models/obj/plane_diffuse.png
# Compile SHADERS examples
+shaders/shaders_ascii_rendering: shaders/shaders_ascii_rendering.c
+ $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
+ --preload-file shaders/resources/fudesumi.png@resources/fudesumi.png \
+ --preload-file shaders/resources/raysan.png@resources/raysan.png \
+ --preload-file shaders/resources/shaders/glsl100/ascii.fs@resources/shaders/glsl100/ascii.fs
+
shaders/shaders_basic_lighting: shaders/shaders_basic_lighting.c
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
--preload-file shaders/resources/shaders/glsl100/lighting.vs@resources/shaders/glsl100/lighting.vs \
diff --git a/examples/README.md b/examples/README.md
index 1753a31bc..441c5a368 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -17,15 +17,16 @@ You may find it easier to use than other toolchains, especially when it comes to
- `zig build [module]` to compile all examples for a module (e.g. `zig build core`)
- `zig build [example]` to compile _and run_ a particular example (e.g. `zig build core_basic_window`)
-## EXAMPLES COLLECTION [TOTAL: 163]
+## EXAMPLES COLLECTION [TOTAL: 175]
-### category: core [37]
+### category: core [40]
Examples using raylib[core](../src/rcore.c) platform functionality like window creation, inputs, drawing modes and system functionality.
| example | image | difficulty
level | version
created | last version
updated | original
developer |
|-----------|--------|:-------------------:|:------------------:|:-----------------------:|:----------------------|
| [core_basic_window](core/core_basic_window.c) |
| ⭐☆☆☆ | 1.0 | 1.0 | [Ramon Santamaria](https://github.com/raysan5) |
+| [core_delta_time](core/core_delta_time.c) |
| ⭐☆☆☆ | 5.5 | 5.6-dev | [Robin](https://github.com/RobinsAviary) |
| [core_input_keys](core/core_input_keys.c) |
| ⭐☆☆☆ | 1.0 | 1.0 | [Ramon Santamaria](https://github.com/raysan5) |
| [core_input_mouse](core/core_input_mouse.c) |
| ⭐☆☆☆ | 1.0 | 5.5 | [Ramon Santamaria](https://github.com/raysan5) |
| [core_input_mouse_wheel](core/core_input_mouse_wheel.c) |
| ⭐☆☆☆ | 1.1 | 1.3 | [Ramon Santamaria](https://github.com/raysan5) |
@@ -48,6 +49,7 @@ Examples using raylib[core](../src/rcore.c) platform functionality like window c
| [core_window_flags](core/core_window_flags.c) |
| ⭐⭐⭐☆ | 3.5 | 3.5 | [Ramon Santamaria](https://github.com/raysan5) |
| [core_window_letterbox](core/core_window_letterbox.c) |
| ⭐⭐☆☆ | 2.5 | 4.0 | [Anata](https://github.com/anatagawa) |
| [core_window_should_close](core/core_window_should_close.c) |
| ⭐☆☆☆ | 4.2 | 4.2 | [Ramon Santamaria](https://github.com/raysan5) |
+| [core_monitor_change](core/core_monitor_change.c) |
| ⭐☆☆☆ | 5.5 | 5.6 | [Maicon Santana](https://github.com/maiconpintoabreu) |
| [core_custom_logging](core/core_custom_logging.c) |
| ⭐⭐⭐☆ | 2.5 | 2.5 | [Pablo Marcos Oltra](https://github.com/pamarcos) |
| [core_drop_files](core/core_drop_files.c) |
| ⭐⭐☆☆ | 1.3 | 4.2 | [Ramon Santamaria](https://github.com/raysan5) |
| [core_random_values](core/core_random_values.c) |
| ⭐☆☆☆ | 1.1 | 1.1 | [Ramon Santamaria](https://github.com/raysan5) |
@@ -62,8 +64,9 @@ Examples using raylib[core](../src/rcore.c) platform functionality like window c
| [core_high_dpi](core/core_high_dpi.c) |
| ⭐⭐☆☆ | 5.0 | 5.5 | [Jonathan Marler](https://github.com/marler8997) |
| [core_render_texture](core/core_render_texture.c) |
| ⭐☆☆☆ | 5.6-dev | 5.6-dev | [Ramon Santamaria](https://github.com/raysan5) |
| [core_undo_redo](core/core_undo_redo.c) |
| ⭐⭐⭐☆ | 5.5 | 5.6 | [Ramon Santamaria](https://github.com/raysan5) |
+| [core_input_actions](core/core_input_actions.c) |
| ⭐⭐☆☆ | 5.5 | 5.6 | [Jett](https://github.com/JettMonstersGoBoom) |
-### category: shapes [20]
+### category: shapes [26]
Examples using raylib shapes drawing functionality, provided by raylib [shapes](../src/rshapes.c) module.
@@ -71,6 +74,7 @@ Examples using raylib shapes drawing functionality, provided by raylib [shapes](
|-----------|--------|:-------------------:|:------------------:|:-----------------------:|:----------------------|
| [shapes_basic_shapes](shapes/shapes_basic_shapes.c) |
| ⭐☆☆☆ | 1.0 | 4.2 | [Ramon Santamaria](https://github.com/raysan5) |
| [shapes_bouncing_ball](shapes/shapes_bouncing_ball.c) |
| ⭐☆☆☆ | 2.5 | 2.5 | [Ramon Santamaria](https://github.com/raysan5) |
+| [shapes_bullet_hell](shapes/shapes_bullet_hell.c) |
| ⭐☆☆☆ | 5.6 | 5.6 | [Zero](https://github.com/zerohorsepower) |
| [shapes_colors_palette](shapes/shapes_colors_palette.c) |
| ⭐⭐☆☆ | 1.0 | 2.5 | [Ramon Santamaria](https://github.com/raysan5) |
| [shapes_logo_raylib](shapes/shapes_logo_raylib.c) |
| ⭐☆☆☆ | 1.0 | 1.0 | [Ramon Santamaria](https://github.com/raysan5) |
| [shapes_logo_raylib_anim](shapes/shapes_logo_raylib_anim.c) |
| ⭐⭐☆☆ | 2.5 | 4.0 | [Ramon Santamaria](https://github.com/raysan5) |
@@ -81,6 +85,7 @@ Examples using raylib shapes drawing functionality, provided by raylib [shapes](
| [shapes_easings_ball](shapes/shapes_easings_ball.c) |
| ⭐⭐☆☆ | 2.5 | 2.5 | [Ramon Santamaria](https://github.com/raysan5) |
| [shapes_easings_box](shapes/shapes_easings_box.c) |
| ⭐⭐☆☆ | 2.5 | 2.5 | [Ramon Santamaria](https://github.com/raysan5) |
| [shapes_easings_rectangles](shapes/shapes_easings_rectangles.c) |
| ⭐⭐⭐☆ | 2.0 | 2.5 | [Ramon Santamaria](https://github.com/raysan5) |
+| [shapes_recursive_tree](shapes/shapes_recursive_tree.c) |
| ⭐⭐⭐☆ | 5.6-dev | 5.6-dev | [Jopestpe](https://github.com/jopestpe) |
| [shapes_ring_drawing](shapes/shapes_ring_drawing.c) |
| ⭐⭐⭐☆ | 2.5 | 2.5 | [Vlad Adrian](https://github.com/demizdor) |
| [shapes_circle_sector_drawing](shapes/shapes_circle_sector_drawing.c) |
| ⭐⭐⭐☆ | 2.5 | 2.5 | [Vlad Adrian](https://github.com/demizdor) |
| [shapes_rounded_rectangle_drawing](shapes/shapes_rounded_rectangle_drawing.c) |
| ⭐⭐⭐☆ | 2.5 | 2.5 | [Vlad Adrian](https://github.com/demizdor) |
@@ -89,6 +94,10 @@ Examples using raylib shapes drawing functionality, provided by raylib [shapes](
| [shapes_splines_drawing](shapes/shapes_splines_drawing.c) |
| ⭐⭐⭐☆ | 5.0 | 5.0 | [Ramon Santamaria](https://github.com/raysan5) |
| [shapes_digital_clock](shapes/shapes_digital_clock.c) |
| ⭐⭐⭐⭐️ | 5.5 | 5.6 | [Hamza RAHAL](https://github.com/hmz-rhl) |
| [shapes_double_pendulum](shapes/shapes_double_pendulum.c) |
| ⭐⭐☆☆ | 5.5 | 5.5 | [JoeCheong](https://github.com/Joecheong2006) |
+| [shapes_dashed_line](shapes/shapes_dashed_line.c) |
| ⭐☆☆☆ | 5.5 | 5.5 | [Luís Almeida](https://github.com/luis605) |
+| [shapes_triangle_strip](shapes/shapes_triangle_strip.c) |
| ⭐⭐☆☆ | 5.6-dev | 5.6-dev | [Jopestpe](https://github.com/jopestpe) |
+| [shapes_vector_angle](shapes/shapes_vector_angle.c) |
| ⭐⭐☆☆ | 1.0 | 5.0 | [Ramon Santamaria](https://github.com/raysan5) |
+| [shapes_kaleidoscope](shapes/shapes_kaleidoscope.c) |
| ⭐⭐☆☆ | 5.5 | 5.6 | [Hugo ARNAL](https://github.com/hugoarnal) |
### category: textures [26]
@@ -144,7 +153,7 @@ Examples using raylib text functionality, including sprite fonts loading/generat
| [text_codepoints_loading](text/text_codepoints_loading.c) |
| ⭐⭐⭐☆ | 4.2 | 4.2 | [Ramon Santamaria](https://github.com/raysan5) |
| [text_inline_styling](text/text_inline_styling.c) |
| ⭐⭐⭐☆ | 5.6-dev | 5.6-dev | [Wagner Barongello](https://github.com/SultansOfCode) |
-### category: models [23]
+### category: models [25]
Examples using raylib models functionality, including models loading/generation and drawing, provided by raylib [models](../src/rmodels.c) module.
@@ -173,13 +182,16 @@ Examples using raylib models functionality, including models loading/generation
| [models_animation_gpu_skinning](models/models_animation_gpu_skinning.c) |
| ⭐⭐⭐☆ | 4.5 | 4.5 | [Daniel Holden](https://github.com/orangeduck) |
| [models_bone_socket](models/models_bone_socket.c) |
| ⭐⭐⭐⭐️ | 4.5 | 4.5 | [iP](https://github.com/ipzaur) |
| [models_tesseract_view](models/models_tesseract_view.c) |
| ⭐⭐☆☆ | 5.6-dev | 5.6-dev | [Timothy van der Valk](https://github.com/arceryz) |
+| [models_basic_voxel](models/models_basic_voxel.c) |
| ⭐⭐☆☆ | 5.5 | 5.5 | [Tim Little](https://github.com/timlittle) |
+| [models_geometry_textures_cube](models/models_geometry_textures_cube.c) |
| ⭐☆☆☆ | 5.6-dev | 5.6-dev | [Jopestpe](https://github.com/jopestpe) |
-### category: shaders [29]
+### category: shaders [30]
Examples using raylib shaders functionality, including shaders loading, parameters configuration and drawing using them (model shaders and postprocessing shaders). This functionality is directly provided by raylib [rlgl](../src/rlgl.c) module.
| example | image | difficulty
level | version
created | last version
updated | original
developer |
|-----------|--------|:-------------------:|:------------------:|:-----------------------:|:----------------------|
+| [shaders_ascii_rendering](shaders/shaders_ascii_rendering.c) |
| ⭐⭐☆☆ | 5.5 | 5.6 | [Maicon Santana](https://github.com/maiconpintoabreu) |
| [shaders_basic_lighting](shaders/shaders_basic_lighting.c) |
| ⭐⭐⭐⭐️ | 3.0 | 4.2 | [Chris Camacho](https://github.com/chriscamacho) |
| [shaders_model_shader](shaders/shaders_model_shader.c) |
| ⭐⭐☆☆ | 1.3 | 3.7 | [Ramon Santamaria](https://github.com/raysan5) |
| [shaders_shapes_textures](shaders/shaders_shapes_textures.c) |
| ⭐⭐☆☆ | 1.7 | 3.7 | [Ramon Santamaria](https://github.com/raysan5) |
@@ -236,7 +248,7 @@ Examples showing raylib misc functionality that does not fit in other categories
| [easings_testbed](others/easings_testbed.c) |
| ⭐⭐⭐☆ | 2.5 | 3.0 | [Juan Miguel López](https://github.com/flashback-fx) |
| [raylib_opengl_interop](others/raylib_opengl_interop.c) |
| ⭐⭐⭐⭐️ | 3.8 | 4.0 | [Stephan Soller](https://github.com/arkanis) |
| [embedded_files_loading](others/embedded_files_loading.c) |
| ⭐⭐☆☆ | 3.0 | 3.5 | [Kristian Holmgren](https://github.com/defutura) |
-| [raymath_vector_angle](others/raymath_vector_angle.c) |
| ⭐⭐☆☆ | 1.0 | 5.0 | [Ramon Santamaria](https://github.com/raysan5) |
+| [web_basic_window](others/web_basic_window.c) |
| ⭐☆☆☆ | 5.6-dev | 5.6-dev | [Ramon Santamaria](https://github.com/raysan5) |
Some example missing? As always, contributions are welcome, feel free to send new examples!
Here is an[examples template](examples_template.c) with instructions to start with!
diff --git a/examples/core/core_3d_camera_free.c b/examples/core/core_3d_camera_free.c
index dde6a6c7d..448eb583e 100644
--- a/examples/core/core_3d_camera_free.c
+++ b/examples/core/core_3d_camera_free.c
@@ -49,7 +49,7 @@ int main(void)
//----------------------------------------------------------------------------------
UpdateCamera(&camera, CAMERA_FREE);
- if (IsKeyPressed('Z')) camera.target = (Vector3){ 0.0f, 0.0f, 0.0f };
+ if (IsKeyPressed(KEY_Z)) camera.target = (Vector3){ 0.0f, 0.0f, 0.0f };
//----------------------------------------------------------------------------------
// Draw
diff --git a/examples/core/core_delta_time.c b/examples/core/core_delta_time.c
new file mode 100644
index 000000000..e52c743da
--- /dev/null
+++ b/examples/core/core_delta_time.c
@@ -0,0 +1,112 @@
+/*******************************************************************************************
+*
+* raylib [core] example - delta time
+*
+* Example complexity rating: [★☆☆☆] 1/4
+*
+* Example originally created with raylib 5.5, last time updated with raylib 5.6-dev
+*
+* Example contributed by Robin (@RobinsAviary) and reviewed by Ramon Santamaria (@raysan5)
+*
+* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
+* BSD-like license that allows static linking with closed source software
+*
+* Copyright (c) 2025 Robin (@RobinsAviary)
+*
+********************************************************************************************/
+
+#include "raylib.h"
+
+//------------------------------------------------------------------------------------
+// Program main entry point
+//------------------------------------------------------------------------------------
+int main(void)
+{
+ // Initialization
+ //--------------------------------------------------------------------------------------
+ const int screenWidth = 800;
+ const int screenHeight = 450;
+
+ InitWindow(screenWidth, screenHeight, "raylib [core] example - delta time");
+
+ int currentFps = 60;
+
+ // Store the position for the both of the circles
+ Vector2 deltaCircle = { 0, (float)screenHeight/3.0f };
+ Vector2 frameCircle = { 0, (float)screenHeight*(2.0f/3.0f) };
+
+ // The speed applied to both circles
+ const float speed = 10.0f;
+ const float circleRadius = 32.0f;
+
+ SetTargetFPS(currentFps);
+ //--------------------------------------------------------------------------------------
+
+ // Main game loop
+ while (!WindowShouldClose()) // Detect window close button or ESC key
+ {
+ // Update
+ //----------------------------------------------------------------------------------
+ // Adjust the FPS target based on the mouse wheel
+ float mouseWheel = GetMouseWheelMove();
+ if (mouseWheel != 0)
+ {
+ currentFps += (int)mouseWheel;
+ if (currentFps < 0) currentFps = 0;
+ SetTargetFPS(currentFps);
+ }
+
+ // GetFrameTime() returns the time it took to draw the last frame, in seconds (usually called delta time)
+ // Uses the delta time to make the circle look like it's moving at a "consistent" speed regardless of FPS
+
+ // Multiply by 6.0 (an arbitrary value) in order to make the speed
+ // visually closer to the other circle (at 60 fps), for comparison
+ deltaCircle.x += GetFrameTime()*6.0f*speed;
+ // This circle can move faster or slower visually depending on the FPS
+ frameCircle.x += 0.1f*speed;
+
+ // If either circle is off the screen, reset it back to the start
+ if (deltaCircle.x > screenWidth) deltaCircle.x = 0;
+ if (frameCircle.x > screenWidth) frameCircle.x = 0;
+
+ // Reset both circles positions
+ if (IsKeyPressed(KEY_R))
+ {
+ deltaCircle.x = 0;
+ frameCircle.x = 0;
+ }
+ //----------------------------------------------------------------------------------
+
+ // Draw
+ //----------------------------------------------------------------------------------
+ BeginDrawing();
+ ClearBackground(RAYWHITE);
+
+ // Draw both circles to the screen
+ DrawCircleV(deltaCircle, circleRadius, RED);
+ DrawCircleV(frameCircle, circleRadius, BLUE);
+
+ // Draw the help text
+ // Determine what help text to show depending on the current FPS target
+ const char *fpsText = 0;
+ if (currentFps <= 0) fpsText = TextFormat("FPS: unlimited (%i)", GetFPS());
+ else fpsText = TextFormat("FPS: %i (target: %i)", GetFPS(), currentFps);
+ DrawText(fpsText, 10, 10, 20, DARKGRAY);
+ DrawText(TextFormat("Frame time: %02.02f ms", GetFrameTime()), 10, 30, 20, DARKGRAY);
+ DrawText("Use the scroll wheel to change the fps limit, r to reset", 10, 50, 20, DARKGRAY);
+
+ // Draw the text above the circles
+ DrawText("FUNC: x += GetFrameTime()*speed", 10, 90, 20, RED);
+ DrawText("FUNC: x += speed", 10, 240, 20, BLUE);
+
+ EndDrawing();
+ //----------------------------------------------------------------------------------
+ }
+
+ // De-Initialization
+ //--------------------------------------------------------------------------------------
+ CloseWindow(); // Close window and OpenGL context
+ //--------------------------------------------------------------------------------------
+
+ return 0;
+}
\ No newline at end of file
diff --git a/examples/core/core_delta_time.png b/examples/core/core_delta_time.png
new file mode 100644
index 000000000..cf8aa7c54
Binary files /dev/null and b/examples/core/core_delta_time.png differ
diff --git a/examples/core/core_input_actions.c b/examples/core/core_input_actions.c
new file mode 100644
index 000000000..aff356087
--- /dev/null
+++ b/examples/core/core_input_actions.c
@@ -0,0 +1,197 @@
+/*******************************************************************************************
+*
+* raylib [core] example - input actions
+*
+* Example complexity rating: [★★☆☆] 2/4
+*
+* Example originally created with raylib 5.5, last time updated with raylib 5.6
+*
+* Example contributed by Jett (@JettMonstersGoBoom) and reviewed by Ramon Santamaria (@raysan5)
+*
+* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
+* BSD-like license that allows static linking with closed source software
+*
+* Copyright (c) 2025 Jett (@JettMonstersGoBoom)
+*
+********************************************************************************************/
+
+// Simple example for decoding input as actions, allowing remapping of input to different keys or gamepad buttons
+// For example instead of using `IsKeyDown(KEY_LEFT)`, you can use `IsActionDown(ACTION_LEFT)`
+// which can be reassigned to e.g. KEY_A and also assigned to a gamepad button. the action will trigger with either gamepad or keys
+
+#include "raylib.h"
+
+//----------------------------------------------------------------------------------
+// Types and Structures Definition
+//----------------------------------------------------------------------------------
+typedef enum ActionType {
+ NO_ACTION = 0,
+ ACTION_UP,
+ ACTION_DOWN,
+ ACTION_LEFT,
+ ACTION_RIGHT,
+ ACTION_FIRE,
+ MAX_ACTION
+} ActionType;
+
+// Key and button inputs
+typedef struct ActionInput {
+ int key;
+ int button;
+} ActionInput;
+
+//----------------------------------------------------------------------------------
+// Global Variables Definition
+//----------------------------------------------------------------------------------
+static int gamepadIndex = 0; // Gamepad default index
+static ActionInput actionInputs[MAX_ACTION] = { 0 };
+
+//----------------------------------------------------------------------------------
+// Module Functions Declaration
+//----------------------------------------------------------------------------------
+static bool IsActionPressed(int action); // Check action key/button pressed
+static bool IsActionReleased(int action); // Check action key/button released
+static bool IsActionDown(int action); // Check action key/button down
+
+static void SetActionsDefault(void); // Set the "default" keyset
+static void SetActionsCursor(void); // Set the "alternate" keyset
+
+//------------------------------------------------------------------------------------
+// Program main entry point
+//------------------------------------------------------------------------------------
+int main(void)
+{
+ // Initialization
+ //--------------------------------------------------------------------------------------
+ const int screenWidth = 800;
+ const int screenHeight = 450;
+
+ InitWindow(screenWidth, screenHeight, "raylib [core] example - input actions");
+
+ // Set default actions
+ char actionSet = 0;
+ SetActionsDefault();
+
+ Vector2 position = (Vector2){ 400.0f, 200.0f };
+ Vector2 size = (Vector2){ 40.0f, 40.0f };
+
+ SetTargetFPS(60);
+ //--------------------------------------------------------------------------------------
+
+ // Main game loop
+ while (!WindowShouldClose()) // Detect window close button or ESC key
+ {
+ // Update
+ //----------------------------------------------------------------------------------
+ gamepadIndex = 0; // set this to gamepad being checked
+ if (IsActionDown(ACTION_UP)) position.y -= 2;
+ if (IsActionDown(ACTION_DOWN)) position.y += 2;
+ if (IsActionDown(ACTION_LEFT)) position.x -= 2;
+ if (IsActionDown(ACTION_RIGHT)) position.x += 2;
+ if (IsActionPressed(ACTION_FIRE))
+ {
+ position.x = (screenWidth-size.x)/2;
+ position.y = (screenHeight-size.y)/2;
+ }
+
+ // Switch control scheme by pressing TAB
+ if (IsKeyPressed(KEY_TAB))
+ {
+ actionSet = !actionSet;
+ if (actionSet == 0) SetActionsDefault();
+ else SetActionsCursor();
+ }
+ //----------------------------------------------------------------------------------
+
+ // Draw
+ //----------------------------------------------------------------------------------
+ BeginDrawing();
+
+ ClearBackground(GRAY);
+
+ DrawRectangleV(position, size, RED);
+
+ DrawText((actionSet == 0)? "Current input set: WASD (default)" : "Current input set: Cursor", 10, 10, 20, WHITE);
+ DrawText("Use TAB key to toggles Actions keyset", 10, 50, 20, GREEN);
+
+ EndDrawing();
+ //----------------------------------------------------------------------------------
+ }
+
+ // De-Initialization
+ //--------------------------------------------------------------------------------------
+ CloseWindow(); // Close window and OpenGL context
+ //--------------------------------------------------------------------------------------
+
+ return 0;
+}
+
+//----------------------------------------------------------------------------------
+// Module Functions Definition
+//----------------------------------------------------------------------------------
+// Check action key/button pressed
+// NOTE: Combines key pressed and gamepad button pressed in one action
+static bool IsActionPressed(int action)
+{
+ bool result = false;
+
+ if (action < MAX_ACTION) result = (IsKeyPressed(actionInputs[action].key) || IsGamepadButtonPressed(gamepadIndex, actionInputs[action].button));
+
+ return result;
+}
+
+// Check action key/button released
+// NOTE: Combines key released and gamepad button released in one action
+static bool IsActionReleased(int action)
+{
+ bool result = false;
+
+ if (action < MAX_ACTION) result = (IsKeyReleased(actionInputs[action].key) || IsGamepadButtonReleased(gamepadIndex, actionInputs[action].button));
+
+ return result;
+}
+
+// Check action key/button down
+// NOTE: Combines key down and gamepad button down in one action
+static bool IsActionDown(int action)
+{
+ bool result = false;
+
+ if (action < MAX_ACTION) result = (IsKeyDown(actionInputs[action].key) || IsGamepadButtonDown(gamepadIndex, actionInputs[action].button));
+
+ return result;
+}
+
+// Set the "default" keyset
+// NOTE: Here WASD and gamepad buttons on the left side for movement
+static void SetActionsDefault(void)
+{
+ actionInputs[ACTION_UP].key = KEY_W;
+ actionInputs[ACTION_DOWN].key = KEY_S;
+ actionInputs[ACTION_LEFT].key = KEY_A;
+ actionInputs[ACTION_RIGHT].key = KEY_D;
+ actionInputs[ACTION_FIRE].key = KEY_SPACE;
+
+ actionInputs[ACTION_UP].button = GAMEPAD_BUTTON_LEFT_FACE_UP;
+ actionInputs[ACTION_DOWN].button = GAMEPAD_BUTTON_LEFT_FACE_DOWN;
+ actionInputs[ACTION_LEFT].button = GAMEPAD_BUTTON_LEFT_FACE_LEFT;
+ actionInputs[ACTION_RIGHT].button = GAMEPAD_BUTTON_LEFT_FACE_RIGHT;
+ actionInputs[ACTION_FIRE].button = GAMEPAD_BUTTON_RIGHT_FACE_DOWN;
+}
+
+// Set the "alternate" keyset
+// NOTE: Here cursor keys and gamepad buttons on the right side for movement
+static void SetActionsCursor(void)
+{
+ actionInputs[ACTION_UP].key = KEY_UP;
+ actionInputs[ACTION_DOWN].key = KEY_DOWN;
+ actionInputs[ACTION_LEFT].key = KEY_LEFT;
+ actionInputs[ACTION_RIGHT].key = KEY_RIGHT;
+ actionInputs[ACTION_FIRE].key = KEY_SPACE;
+
+ actionInputs[ACTION_UP].button = GAMEPAD_BUTTON_RIGHT_FACE_UP;
+ actionInputs[ACTION_DOWN].button = GAMEPAD_BUTTON_RIGHT_FACE_DOWN;
+ actionInputs[ACTION_LEFT].button = GAMEPAD_BUTTON_RIGHT_FACE_LEFT;
+ actionInputs[ACTION_RIGHT].button = GAMEPAD_BUTTON_RIGHT_FACE_RIGHT;
+ actionInputs[ACTION_FIRE].button = GAMEPAD_BUTTON_LEFT_FACE_DOWN;
+}
diff --git a/examples/core/core_input_actions.png b/examples/core/core_input_actions.png
new file mode 100644
index 000000000..757b725f6
Binary files /dev/null and b/examples/core/core_input_actions.png differ
diff --git a/examples/core/core_input_mouse.c b/examples/core/core_input_mouse.c
index bbe519f82..f429018b0 100644
--- a/examples/core/core_input_mouse.c
+++ b/examples/core/core_input_mouse.c
@@ -72,7 +72,7 @@ int main(void)
DrawText("move ball with mouse and click mouse button to change color", 10, 10, 20, DARKGRAY);
DrawText("Press 'H' to toggle cursor visibility", 10, 30, 20, DARKGRAY);
- if (!IsCursorHidden()) DrawText("CURSOR HIDDEN", 20, 60, 20, RED);
+ if (IsCursorHidden()) DrawText("CURSOR HIDDEN", 20, 60, 20, RED);
else DrawText("CURSOR VISIBLE", 20, 60, 20, LIME);
EndDrawing();
diff --git a/examples/core/core_monitor_change.c b/examples/core/core_monitor_change.c
new file mode 100644
index 000000000..c85b3f633
--- /dev/null
+++ b/examples/core/core_monitor_change.c
@@ -0,0 +1,170 @@
+/*******************************************************************************************
+*
+* raylib [core] example - monitor change
+*
+* Example complexity rating: [★☆☆☆] 1/4
+*
+* Example originally created with raylib 5.5, last time updated with raylib 5.6
+*
+* Example contributed by Maicon Santana (@maiconpintoabreu) and reviewed by Ramon Santamaria (@raysan5)
+*
+* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
+* BSD-like license that allows static linking with closed source software
+*
+* Copyright (c) 2025 Maicon Santana (@maiconpintoabreu)
+*
+********************************************************************************************/
+
+#include "raylib.h"
+
+#define MAX_MONITORS 10
+
+// Monitor Details
+typedef struct Monitor {
+ Vector2 position;
+ char *name;
+ int width;
+ int height;
+ int physicalWidth;
+ int physicalHeight;
+ int refreshRate;
+} Monitor;
+
+//------------------------------------------------------------------------------------
+// Program main entry point
+//------------------------------------------------------------------------------------
+int main(void)
+{
+ // Initialization
+ //--------------------------------------------------------------------------------------
+ const int screenWidth = 800;
+ const int screenHeight = 450;
+
+ Monitor monitors[MAX_MONITORS] = { 0 };
+
+ InitWindow(screenWidth, screenHeight, "raylib [core] example - monitor change");
+
+ int currentMonitorIndex = GetCurrentMonitor();
+ int monitorCount = 0;
+
+ SetTargetFPS(60); // Set our game to run at 60 frames-per-second
+ //--------------------------------------------------------------------------------------
+
+ // Main game loop
+ while (!WindowShouldClose()) // Detect window close button or ESC key
+ {
+ // Update
+ //----------------------------------------------------------------------------------
+
+ // Variables to find the max x and Y to calculate the scale
+ int maxWidth = 1;
+ int maxHeight = 1;
+
+ // Monitor offset is to fix when monitor position x is negative
+ int monitorOffsetX = 0;
+
+ // Rebuild monitors array every frame
+ monitorCount = GetMonitorCount();
+ for (int i = 0; i < monitorCount; i++)
+ {
+ monitors[i] = (Monitor){
+ GetMonitorPosition(i),
+ GetMonitorName(i),
+ GetMonitorWidth(i),
+ GetMonitorHeight(i),
+ GetMonitorPhysicalWidth(i),
+ GetMonitorPhysicalHeight(i),
+ GetMonitorRefreshRate(i)
+ };
+ if (monitors[i].position.x < monitorOffsetX) monitorOffsetX = monitors[i].position.x*-1;
+
+ const int width = monitors[i].position.x + monitors[i].width;
+ const int height = monitors[i].position.y + monitors[i].height;
+
+ if (maxWidth < width) maxWidth = width;
+ if (maxHeight < height) maxHeight = height;
+ }
+
+ if (IsKeyPressed(KEY_ENTER) && monitorCount > 1)
+ {
+ currentMonitorIndex += 1;
+
+ // Set index to 0 if the last one
+ if(currentMonitorIndex == monitorCount) currentMonitorIndex = 0;
+
+ SetWindowMonitor(currentMonitorIndex); // Move window to currentMonitorIndex
+ }
+ else
+ {
+ // Get currentMonitorIndex if manually moved
+ currentMonitorIndex = GetCurrentMonitor();
+ }
+ const Monitor currentMonitor = monitors[currentMonitorIndex];
+
+ float monitorScale = 0.6;
+
+ if(maxHeight > maxWidth + monitorOffsetX) monitorScale *= ((float)screenHeight/(float)maxHeight);
+ else monitorScale *= ((float)screenWidth/(float)(maxWidth + monitorOffsetX));
+
+ // Draw
+ //----------------------------------------------------------------------------------
+ BeginDrawing();
+
+ ClearBackground(RAYWHITE);
+
+ DrawText("Press [Enter] to move window to next monitor available", 20, 20, 20, DARKGRAY);
+
+ DrawRectangleLines(20, 60, screenWidth - 40, screenHeight - 100, DARKGRAY);
+
+ // Draw Monitor Rectangles with information inside
+ for (int i = 0; i < monitorCount; i++)
+ {
+ // Calculate retangle position and size using monitorScale
+ const Rectangle rec = (Rectangle){
+ (monitors[i].position.x + monitorOffsetX) * monitorScale + 140,
+ monitors[i].position.y * monitorScale + 80,
+ monitors[i].width * monitorScale,
+ monitors[i].height * monitorScale
+ };
+
+ // Draw monitor name and information inside the rectangle
+ DrawText(TextFormat("[%i] %s", i, monitors[i].name), rec.x + 10, rec.y + (int)(100*monitorScale), (int)(120*monitorScale), BLUE);
+ DrawText(
+ TextFormat("Resolution: [%ipx x %ipx]\nRefreshRate: [%ihz]\nPhysical Size: [%imm x %imm]\nPosition: %3.0f x %3.0f",
+ monitors[i].width,
+ monitors[i].height,
+ monitors[i].refreshRate,
+ monitors[i].physicalWidth,
+ monitors[i].physicalHeight,
+ monitors[i].position.x,
+ monitors[i].position.y
+ ), rec.x + 10, rec.y + (int)(200*monitorScale), (int)(120*monitorScale), DARKGRAY);
+
+ // Highlight current monitor
+ if (i == currentMonitorIndex)
+ {
+ DrawRectangleLinesEx(rec, 5, RED);
+ Vector2 windowPosition = (Vector2){ (GetWindowPosition().x + monitorOffsetX)*monitorScale + 140, GetWindowPosition().y*monitorScale + 80 };
+
+ // Draw window position based on monitors
+ DrawRectangleV(windowPosition, (Vector2){screenWidth * monitorScale, screenHeight * monitorScale}, Fade(GREEN, 0.5));
+ }
+ else
+ {
+ DrawRectangleLinesEx(rec, 5, GRAY);
+ }
+
+ }
+
+
+ EndDrawing();
+ //----------------------------------------------------------------------------------
+ }
+
+ // De-Initialization
+ //--------------------------------------------------------------------------------------
+ CloseWindow(); // Close window and OpenGL context
+ //--------------------------------------------------------------------------------------
+
+ return 0;
+}
\ No newline at end of file
diff --git a/examples/core/core_monitor_change.png b/examples/core/core_monitor_change.png
new file mode 100644
index 000000000..81f9eed87
Binary files /dev/null and b/examples/core/core_monitor_change.png differ
diff --git a/examples/examples_list.txt b/examples/examples_list.txt
index ead1bf220..c6f2a97b3 100644
--- a/examples/examples_list.txt
+++ b/examples/examples_list.txt
@@ -8,6 +8,7 @@
# WARNING: List is not ordered by example name but by the display order on web
#
core;core_basic_window;★☆☆☆;1.0;1.0;2013;2025;"Ramon Santamaria";@raysan5
+core;core_delta_time;★☆☆☆;5.5;5.6-dev;2025;2025;"Robin";@RobinsAviary
core;core_input_keys;★☆☆☆;1.0;1.0;2014;2025;"Ramon Santamaria";@raysan5
core;core_input_mouse;★☆☆☆;1.0;5.5;2014;2025;"Ramon Santamaria";@raysan5
core;core_input_mouse_wheel;★☆☆☆;1.1;1.3;2014;2025;"Ramon Santamaria";@raysan5
@@ -30,6 +31,7 @@ core;core_world_screen;★★☆☆;1.3;1.4;2015;2025;"Ramon Santamaria";@raysan
core;core_window_flags;★★★☆;3.5;3.5;2020;2025;"Ramon Santamaria";@raysan5
core;core_window_letterbox;★★☆☆;2.5;4.0;2019;2025;"Anata";@anatagawa
core;core_window_should_close;★☆☆☆;4.2;4.2;2013;2025;"Ramon Santamaria";@raysan5
+core;core_monitor_change;★☆☆☆;5.5;5.6;2025;2025;"Maicon Santana";@maiconpintoabreu
core;core_custom_logging;★★★☆;2.5;2.5;2018;2025;"Pablo Marcos Oltra";@pamarcos
core;core_drop_files;★★☆☆;1.3;4.2;2015;2025;"Ramon Santamaria";@raysan5
core;core_random_values;★☆☆☆;1.1;1.1;2014;2025;"Ramon Santamaria";@raysan5
@@ -44,8 +46,10 @@ core;core_automation_events;★★★☆;5.0;5.0;2023;2025;"Ramon Santamaria";@r
core;core_high_dpi;★★☆☆;5.0;5.5;2025;2025;"Jonathan Marler";@marler8997
core;core_render_texture;★☆☆☆;5.6-dev;5.6-dev;2025;2025;"Ramon Santamaria";@raysan5
core;core_undo_redo;★★★☆;5.5;5.6;2025;2025;"Ramon Santamaria";@raysan5
+core;core_input_actions;★★☆☆;5.5;5.6;2025;2025;"Jett";@JettMonstersGoBoom
shapes;shapes_basic_shapes;★☆☆☆;1.0;4.2;2014;2025;"Ramon Santamaria";@raysan5
shapes;shapes_bouncing_ball;★☆☆☆;2.5;2.5;2013;2025;"Ramon Santamaria";@raysan5
+shapes;shapes_bullet_hell;★☆☆☆;5.6;5.6;2025;2025;"Zero";@zerohorsepower
shapes;shapes_colors_palette;★★☆☆;1.0;2.5;2014;2025;"Ramon Santamaria";@raysan5
shapes;shapes_logo_raylib;★☆☆☆;1.0;1.0;2014;2025;"Ramon Santamaria";@raysan5
shapes;shapes_logo_raylib_anim;★★☆☆;2.5;4.0;2014;2025;"Ramon Santamaria";@raysan5
@@ -56,6 +60,7 @@ shapes;shapes_following_eyes;★★☆☆;2.5;2.5;2013;2025;"Ramon Santamaria";@
shapes;shapes_easings_ball;★★☆☆;2.5;2.5;2014;2025;"Ramon Santamaria";@raysan5
shapes;shapes_easings_box;★★☆☆;2.5;2.5;2014;2025;"Ramon Santamaria";@raysan5
shapes;shapes_easings_rectangles;★★★☆;2.0;2.5;2014;2025;"Ramon Santamaria";@raysan5
+shapes;shapes_recursive_tree;★★★☆;5.6-dev;5.6-dev;2025;2025;"Jopestpe";@jopestpe
shapes;shapes_ring_drawing;★★★☆;2.5;2.5;2018;2025;"Vlad Adrian";@demizdor
shapes;shapes_circle_sector_drawing;★★★☆;2.5;2.5;2018;2025;"Vlad Adrian";@demizdor
shapes;shapes_rounded_rectangle_drawing;★★★☆;2.5;2.5;2018;2025;"Vlad Adrian";@demizdor
@@ -64,6 +69,9 @@ shapes;shapes_rectangle_advanced;★★★★;5.5;5.5;2024;2025;"Everton Jr.";@e
shapes;shapes_splines_drawing;★★★☆;5.0;5.0;2023;2025;"Ramon Santamaria";@raysan5
shapes;shapes_digital_clock;★★★★;5.5;5.6;2025;2025;"Hamza RAHAL";@hmz-rhl
shapes;shapes_double_pendulum;★★☆☆;5.5;5.5;2025;2025;"JoeCheong";@Joecheong2006
+shapes;shapes_dashed_line;★☆☆☆;5.5;5.5;2025;2025;"Luís Almeida";@luis605
+shapes;shapes_triangle_strip;★★☆☆;5.6-dev;5.6-dev;2025;2025;"Jopestpe";@jopestpe
+shapes;shapes_vector_angle;★★☆☆;1.0;5.0;2023;2025;"Ramon Santamaria";@raysan5
textures;textures_logo_raylib;★☆☆☆;1.0;1.0;2014;2025;"Ramon Santamaria";@raysan5
textures;textures_srcrec_dstrec;★★★☆;1.3;1.3;2015;2025;"Ramon Santamaria";@raysan5
textures;textures_image_drawing;★★☆☆;1.4;1.4;2016;2025;"Ramon Santamaria";@raysan5
@@ -127,6 +135,9 @@ models;models_textured_cube;★★☆☆;4.5;4.5;2022;2025;"Ramon Santamaria";@r
models;models_animation_gpu_skinning;★★★☆;4.5;4.5;2024;2025;"Daniel Holden";@orangeduck
models;models_bone_socket;★★★★;4.5;4.5;2024;2025;"iP";@ipzaur
models;models_tesseract_view;★★☆☆;5.6-dev;5.6-dev;2024;2025;"Timothy van der Valk";@arceryz
+models;models_basic_voxel;★★☆☆;5.5;5.5;2025;2025;"Tim Little";@timlittle
+models;models_geometry_textures_cube;★☆☆☆;5.6-dev;5.6-dev;2025;2025;"Jopestpe";@jopestpe
+shaders;shaders_ascii_rendering;★★☆☆;5.5;5.6;2025;2025;"Maicon Santana";@maiconpintoabreu
shaders;shaders_basic_lighting;★★★★;3.0;4.2;2019;2025;"Chris Camacho";@chriscamacho
shaders;shaders_model_shader;★★☆☆;1.3;3.7;2014;2025;"Ramon Santamaria";@raysan5
shaders;shaders_shapes_textures;★★☆☆;1.7;3.7;2015;2025;"Ramon Santamaria";@raysan5
@@ -169,4 +180,5 @@ others;rlgl_compute_shader;★★★★;4.0;4.0;2021;2025;"Teddy Astie";@tsnake4
others;easings_testbed;★★★☆;2.5;3.0;2019;2025;"Juan Miguel López";@flashback-fx
others;raylib_opengl_interop;★★★★;3.8;4.0;2021;2025;"Stephan Soller";@arkanis
others;embedded_files_loading;★★☆☆;3.0;3.5;2020;2025;"Kristian Holmgren";@defutura
-others;raymath_vector_angle;★★☆☆;1.0;5.0;2023;2025;"Ramon Santamaria";@raysan5
+others;web_basic_window;★☆☆☆;5.6-dev;5.6-dev;2014;2025;"Ramon Santamaria";@raysan5
+shapes;shapes_kaleidoscope;★★☆☆;5.5;5.6;2025;2025;"Hugo ARNAL";@hugoarnal
diff --git a/examples/models/models_basic_voxel.c b/examples/models/models_basic_voxel.c
new file mode 100644
index 000000000..8df15d73d
--- /dev/null
+++ b/examples/models/models_basic_voxel.c
@@ -0,0 +1,152 @@
+/*******************************************************************************************
+*
+* raylib [models] example - basic voxel
+*
+* Example complexity rating: [★★☆☆] 2/4
+*
+* Example originally created with raylib 5.5, last time updated with raylib 5.5
+*
+* Example contributed by Tim Little (@timlittle) and reviewed by Ramon Santamaria (@raysan5)
+*
+* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
+* BSD-like license that allows static linking with closed source software
+*
+* Copyright (c) 2025 Tim Little (@timlittle)
+*
+********************************************************************************************/
+
+#include "raylib.h"
+#include "raymath.h"
+
+#define WORLD_SIZE 8 // Size of our voxel world (8x8x8 cubes)
+
+//------------------------------------------------------------------------------------
+// Program main entry point
+//------------------------------------------------------------------------------------
+int main(void)
+{
+ // Initialization
+ //--------------------------------------------------------------------------------------
+ const int screenWidth = 800;
+ const int screenHeight = 450;
+
+ InitWindow(screenWidth, screenHeight, "raylib [models] example - basic voxel");
+
+ DisableCursor(); // Lock mouse to window center
+
+ // Define the camera to look into our 3d world (first person)
+ Camera3D camera = { 0 };
+ camera.position = (Vector3){ -2.0f, 0.0f, -2.0f }; // Camera position at ground level
+ camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera looking at point
+ camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector
+ camera.fovy = 45.0f; // Camera field-of-view Y
+ camera.projection = CAMERA_PERSPECTIVE; // Camera projection type
+
+ // Create a cube model
+ Mesh cubeMesh = GenMeshCube(1.0f, 1.0f, 1.0f); // Create a unit cube mesh
+ Model cubeModel = LoadModelFromMesh(cubeMesh); // Convert mesh to a model
+ cubeModel.materials[0].maps[MATERIAL_MAP_DIFFUSE].color = BEIGE;
+
+ // Initialize voxel world - fill with voxels
+ bool voxels[WORLD_SIZE][WORLD_SIZE][WORLD_SIZE] = { false };
+ for (int x = 0; x < WORLD_SIZE; x++)
+ {
+ for (int y = 0; y < WORLD_SIZE; y++)
+ {
+ for (int z = 0; z < WORLD_SIZE; z++)
+ {
+ voxels[x][y][z] = true;
+ }
+ }
+ }
+
+ SetTargetFPS(60);
+ //--------------------------------------------------------------------------------------
+
+ // Main game loop
+ while (!WindowShouldClose()) // Detect window close button or ESC key
+ {
+ // Update
+ //----------------------------------------------------------------------------------
+ UpdateCamera(&camera, CAMERA_FIRST_PERSON);
+
+ // Handle voxel removal with mouse click
+ if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
+ {
+ // Cast a ray from the screen center (where crosshair would be)
+ Vector2 screenCenter = { screenWidth/2.0f, screenHeight/2.0f };
+ Ray ray = GetMouseRay(screenCenter, camera);
+
+ // Check ray collision with all voxels
+ bool voxelRemoved = false;
+ for (int x = 0; (x < WORLD_SIZE) && !voxelRemoved; x++)
+ {
+ for (int y = 0; (y < WORLD_SIZE) && !voxelRemoved; y++)
+ {
+ for (int z = 0; (z < WORLD_SIZE) && !voxelRemoved; z++)
+ {
+ if (!voxels[x][y][z]) continue; // Skip empty voxels
+
+ // Build a bounding box for this voxel
+ Vector3 position = { x, y, z };
+ BoundingBox box = {
+ (Vector3){ position.x - 0.5f, position.y - 0.5f, position.z - 0.5f },
+ (Vector3){ position.x + 0.5f, position.y + 0.5f, position.z + 0.5f }
+ };
+
+ // Check ray-box collision
+ RayCollision collision = GetRayCollisionBox(ray, box);
+ if (collision.hit)
+ {
+ voxels[x][y][z] = false; // Remove this voxel
+ voxelRemoved = true; // Exit all loops
+ }
+ }
+ }
+ }
+ }
+ //----------------------------------------------------------------------------------
+
+ // Draw
+ //----------------------------------------------------------------------------------
+ BeginDrawing();
+
+ ClearBackground(RAYWHITE);
+
+ BeginMode3D(camera);
+
+ DrawGrid(10, 1.0f);
+
+ // Draw all voxels
+ for (int x = 0; x < WORLD_SIZE; x++)
+ {
+ for (int y = 0; y < WORLD_SIZE; y++)
+ {
+ for (int z = 0; z < WORLD_SIZE; z++)
+ {
+ if (!voxels[x][y][z]) continue;
+
+ Vector3 position = { x, y, z };
+ DrawModel(cubeModel, position, 1.0f, BEIGE);
+ DrawCubeWires(position, 1.0f, 1.0f, 1.0f, BLACK);
+ }
+ }
+ }
+
+ EndMode3D();
+
+ DrawText("Left-click a voxel to remove it!", 10, 10, 20, DARKGRAY);
+ DrawText("WASD to move, mouse to look around", 10, 35, 10, GRAY);
+
+ EndDrawing();
+ //----------------------------------------------------------------------------------
+ }
+
+ // De-Initialization
+ //--------------------------------------------------------------------------------------
+ UnloadModel(cubeModel);
+ CloseWindow();
+ //--------------------------------------------------------------------------------------
+
+ return 0;
+}
diff --git a/examples/models/models_basic_voxel.png b/examples/models/models_basic_voxel.png
new file mode 100644
index 000000000..8bbcaf8da
Binary files /dev/null and b/examples/models/models_basic_voxel.png differ
diff --git a/examples/models/models_geometry_textures_cube.c b/examples/models/models_geometry_textures_cube.c
new file mode 100644
index 000000000..f8236f36d
--- /dev/null
+++ b/examples/models/models_geometry_textures_cube.c
@@ -0,0 +1,88 @@
+/*******************************************************************************************
+*
+* raylib [models] example - geometry textures cube
+*
+* Example complexity rating: [★☆☆☆] 1/4
+*
+* Example originally created with raylib 5.6-dev, last time updated with raylib 5.6-dev
+*
+* Example contributed by Jopestpe (@jopestpe)
+*
+* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
+* BSD-like license that allows static linking with closed source software
+*
+* Copyright (c) 2025 Jopestpe (@jopestpe)
+*
+********************************************************************************************/
+
+#include "raylib.h"
+
+//------------------------------------------------------------------------------------
+// Program main entry point
+//------------------------------------------------------------------------------------
+int main(void)
+{
+ // Initialization
+ //--------------------------------------------------------------------------------------
+ const int screenWidth = 800;
+ const int screenHeight = 450;
+
+ InitWindow(screenWidth, screenHeight, "raylib [models] example - geometry textures cube");
+
+ // Define the camera to look into our 3d world
+ Camera camera = { 0 };
+ camera.position = (Vector3){ 0.0f, 0.0f, 4.0f };
+ camera.target = (Vector3){ 0.0f, 0.0f, 0.0f };
+ camera.up = (Vector3){ 0.0f, 1.0f, 0.0f };
+ camera.fovy = 45.0f;
+ camera.projection = CAMERA_PERSPECTIVE;
+
+ // Load image to create texture for the cube
+ Model model = LoadModelFromMesh(GenMeshCube(1.0f, 1.0f, 1.0f));
+ Image img = LoadImage("resources/cubicmap_atlas.png");
+ Image crop = ImageFromImage(img, (Rectangle){0, img.height/2, img.width/2, img.height/2});
+ Texture2D texture = LoadTextureFromImage(crop);
+ UnloadImage(img);
+ UnloadImage(crop);
+
+ model.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = texture;
+
+ float rotation = 0.0f;
+
+ SetTargetFPS(60); // Set our game to run at 60 frames-per-second
+ //--------------------------------------------------------------------------------------
+
+ // Main game loop
+ while (!WindowShouldClose()) // Detect window close button or ESC key
+ {
+ // Update
+ //----------------------------------------------------------------------------------
+ rotation += 1.0f;
+
+ // Draw
+ //----------------------------------------------------------------------------------
+ BeginDrawing();
+
+ ClearBackground(RAYWHITE);
+
+ BeginMode3D(camera);
+
+ DrawModelEx(model, (Vector3){0,0,0}, (Vector3){0.5f,1,0}, rotation, (Vector3){1,1,1}, WHITE);
+
+ EndMode3D();
+
+ DrawFPS(10, 10);
+
+ EndDrawing();
+ //----------------------------------------------------------------------------------
+ }
+
+ // De-Initialization
+ //--------------------------------------------------------------------------------------
+ UnloadTexture(texture); // Unload texture
+ UnloadModel(model); // Unload model
+ CloseWindow(); // Close window and OpenGL context
+ //--------------------------------------------------------------------------------------
+
+ return 0;
+}
diff --git a/examples/models/models_geometry_textures_cube.png b/examples/models/models_geometry_textures_cube.png
new file mode 100644
index 000000000..4c199bdc4
Binary files /dev/null and b/examples/models/models_geometry_textures_cube.png differ
diff --git a/examples/others/web_basic_window.c b/examples/others/web_basic_window.c
index 8aeebf414..f85c6e4f6 100644
--- a/examples/others/web_basic_window.c
+++ b/examples/others/web_basic_window.c
@@ -1,15 +1,18 @@
/*******************************************************************************************
*
-* raylib [others] example - Basic window (adapted for HTML5 platform)
+* raylib [others] example - basic window
*
-* This example is prepared to compile for PLATFORM_WEB and PLATFORM_DESKTOP
-* As you will notice, code structure is slightly different to the other examples...
-* To compile it for PLATFORM_WEB just uncomment #define PLATFORM_WEB at beginning
+* This example has been adapted to compile for PLATFORM_WEB and PLATFORM_DESKTOP
+* As you will notice, code structure is slightly different to the other examples
*
-* This example has been created using raylib 1.3 (www.raylib.com)
-* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
+* Example complexity rating: [★☆☆☆] 1/4
*
-* Copyright (c) 2015 Ramon Santamaria (@raysan5)
+* Example originally created with raylib 1.3, last time updated with raylib 5.5
+*
+* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
+* BSD-like license that allows static linking with closed source software
+*
+* Copyright (c) 2015-2025 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
diff --git a/examples/shaders/resources/shaders/glsl100/ascii.fs b/examples/shaders/resources/shaders/glsl100/ascii.fs
new file mode 100644
index 000000000..54e20bf66
--- /dev/null
+++ b/examples/shaders/resources/shaders/glsl100/ascii.fs
@@ -0,0 +1,80 @@
+#version 100
+
+precision mediump float;
+
+// Input from the vertex shader
+varying vec2 fragTexCoord;
+
+// Output color for the screen
+varying vec4 finalColor;
+
+uniform sampler2D texture0;
+uniform vec2 resolution;
+
+// Fontsize less then 9 may be not complete
+uniform float fontSize;
+
+float GreyScale(in vec3 col)
+{
+ return dot(col, vec3(0.2126, 0.7152, 0.0722));
+}
+
+float GetCharacter(float n, vec2 p)
+{
+ p = floor(p*vec2(-4.0, 4.0) + 2.5);
+
+ // Check if the calculated coordinate is inside the 5x5 grid (from 0.0 to 4.0)
+ if (clamp(p.x, 0.0, 4.0) == p.x && clamp(p.y, 0.0, 4.0) == p.y)
+ {
+ float a = floor(p.x + 0.5) + 5.0*floor(p.y + 0.5);
+
+ // This checked if the 'a'-th bit of 'n' was set
+ float shiftedN = floor(n/pow(2.0, a));
+
+ if (mod(shiftedN, 2.0) == 1.0)
+ {
+ return 1.0; // The bit is on
+ }
+ }
+
+ return 0.0; // The bit is off, or we are outside the grid
+}
+
+// -----------------------------------------------------------------------------
+// Main shader logic
+// -----------------------------------------------------------------------------
+
+void main()
+{
+ vec2 charPixelSize = vec2(fontSize, fontSize);
+ vec2 uvCellSize = charPixelSize/resolution;
+
+ // The cell size is based on the fontSize set by application
+ vec2 cellUV = floor(fragTexCoord/uvCellSize)*uvCellSize;
+
+ vec3 cellColor = texture2D(texture0, cellUV).rgb;
+
+ // Gray is used to define what character will be selected to draw
+ float gray = GreyScale(cellColor);
+
+ float n = 4096.0;
+
+ // Character set from https://www.shadertoy.com/view/lssGDj
+ // Create new bitmaps https://thrill-project.com/archiv/coding/bitmap/
+ if (gray > 0.2) n = 65600.0; // :
+ if (gray > 0.3) n = 18725316.0; // v
+ if (gray > 0.4) n = 15255086.0; // o
+ if (gray > 0.5) n = 13121101.0; // &
+ if (gray > 0.6) n = 15252014.0; // 8
+ if (gray > 0.7) n = 13195790.0; // @
+ if (gray > 0.8) n = 11512810.0; // #
+
+ vec2 localUV = (fragTexCoord - cellUV)/uvCellSize; // Range [0.0, 1.0]
+
+ vec2 p = localUV*2.0 - 1.0; // Range [-1.0, 1.0]
+
+ // cellColor and charShape will define the color of the char
+ vec3 color = cellColor*GetCharacter(n, p);
+
+ gl_FragColor = vec4(color, 1.0);
+}
\ No newline at end of file
diff --git a/examples/shaders/resources/shaders/glsl120/ascii.fs b/examples/shaders/resources/shaders/glsl120/ascii.fs
new file mode 100644
index 000000000..09c572ae5
--- /dev/null
+++ b/examples/shaders/resources/shaders/glsl120/ascii.fs
@@ -0,0 +1,78 @@
+#version 120
+
+// Input from the vertex shader
+varying vec2 fragTexCoord;
+
+// Output color for the screen
+varying vec4 finalColor;
+
+uniform sampler2D texture0;
+uniform vec2 resolution;
+
+// Fontsize less then 9 may be not complete
+uniform float fontSize;
+
+float GreyScale(in vec3 col)
+{
+ return dot(col, vec3(0.2126, 0.7152, 0.0722));
+}
+
+float GetCharacter(float n, vec2 p)
+{
+ p = floor(p*vec2(-4.0, 4.0) + 2.5);
+
+ // Check if the calculated coordinate is inside the 5x5 grid (from 0.0 to 4.0)
+ if (clamp(p.x, 0.0, 4.0) == p.x && clamp(p.y, 0.0, 4.0) == p.y)
+ {
+ float a = floor(p.x + 0.5) + 5.0*floor(p.y + 0.5);
+
+ // This checked if the 'a'-th bit of 'n' was set
+ float shiftedN = floor(n/pow(2.0, a));
+
+ if (mod(shiftedN, 2.0) == 1.0)
+ {
+ return 1.0; // The bit is on
+ }
+ }
+
+ return 0.0; // The bit is off, or we are outside the grid
+}
+
+// -----------------------------------------------------------------------------
+// Main shader logic
+// -----------------------------------------------------------------------------
+
+void main()
+{
+ vec2 charPixelSize = vec2(fontSize, fontSize);
+ vec2 uvCellSize = charPixelSize / resolution;
+
+ // The cell size is based on the fontSize set by application
+ vec2 cellUV = floor(fragTexCoord / uvCellSize)*uvCellSize;
+
+ vec3 cellColor = texture2D(texture0, cellUV).rgb;
+
+ // Gray is used to define what character will be selected to draw
+ float gray = GreyScale(cellColor);
+
+ float n = 4096.0;
+
+ // Character set from https://www.shadertoy.com/view/lssGDj
+ // Create new bitmaps https://thrill-project.com/archiv/coding/bitmap/
+ if (gray > 0.2) n = 65600.0; // :
+ if (gray > 0.3) n = 18725316.0; // v
+ if (gray > 0.4) n = 15255086.0; // o
+ if (gray > 0.5) n = 13121101.0; // &
+ if (gray > 0.6) n = 15252014.0; // 8
+ if (gray > 0.7) n = 13195790.0; // @
+ if (gray > 0.8) n = 11512810.0; // #
+
+ vec2 localUV = (fragTexCoord - cellUV)/uvCellSize; // Range [0.0, 1.0]
+
+ vec2 p = localUV*2.0 - 1.0; // Range [-1.0, 1.0]
+
+ // cellColor and charShape will define the color of the char
+ vec3 color = cellColor*GetCharacter(n, p);
+
+ gl_FragColor = vec4(color, 1.0);
+}
\ No newline at end of file
diff --git a/examples/shaders/resources/shaders/glsl330/ascii.fs b/examples/shaders/resources/shaders/glsl330/ascii.fs
new file mode 100644
index 000000000..3f73bf288
--- /dev/null
+++ b/examples/shaders/resources/shaders/glsl330/ascii.fs
@@ -0,0 +1,73 @@
+#version 330
+
+// Input from the vertex shader
+in vec2 fragTexCoord;
+
+// Output color for the screen
+out vec4 finalColor;
+
+uniform sampler2D texture0;
+uniform vec2 resolution;
+
+// Fontsize less then 9 may be not complete
+uniform float fontSize;
+
+float GreyScale(in vec3 col)
+{
+ return dot(col, vec3(0.2126, 0.7152, 0.0722));
+}
+
+float GetCharacter(int n, vec2 p)
+{
+ p = floor(p*vec2(-4.0, 4.0) + 2.5);
+
+ // Check if the coordinate is inside the 5x5 grid (0 to 4)
+ if (clamp(p.x, 0.0, 4.0) == p.x && clamp(p.y, 0.0, 4.0) == p.y)
+ {
+ int a = int(round(p.x) + 5.0*round(p.y));
+ if (((n >> a) & 1) == 1)
+ {
+ return 1.0;
+ }
+ }
+
+ return 0.0; // The bit is off, or we are outside the grid
+}
+
+// -----------------------------------------------------------------------------
+// Main shader logic
+// -----------------------------------------------------------------------------
+
+void main()
+{
+ vec2 charPixelSize = vec2(fontSize, fontSize);
+ vec2 uvCellSize = charPixelSize/resolution;
+
+ // The cell size is based on the fontSize set by application
+ vec2 cellUV = floor(fragTexCoord/uvCellSize)*uvCellSize;
+
+ vec3 cellColor = texture(texture0, cellUV).rgb;
+
+ // Gray is used to define what character will be selected to draw
+ float gray = GreyScale(cellColor);
+
+ int n = 4096;
+
+ // Character set from https://www.shadertoy.com/view/lssGDj
+ // Create new bitmaps https://thrill-project.com/archiv/coding/bitmap/
+ if (gray > 0.2) n = 65600; // :
+ if (gray > 0.3) n = 18725316; // v
+ if (gray > 0.4) n = 15255086; // o
+ if (gray > 0.5) n = 13121101; // &
+ if (gray > 0.6) n = 15252014; // 8
+ if (gray > 0.7) n = 13195790; // @
+ if (gray > 0.8) n = 11512810; // #
+
+ vec2 localUV = (fragTexCoord - cellUV)/uvCellSize; // Range [0.0, 1.0]
+
+ vec2 p = localUV*2.0 - 1.0; // Range [-1.0, 1.0]
+
+ vec3 color = cellColor*GetCharacter(n, p);
+
+ finalColor = vec4(color, 1.0);
+}
\ No newline at end of file
diff --git a/examples/shaders/shaders_ascii_rendering.c b/examples/shaders/shaders_ascii_rendering.c
new file mode 100644
index 000000000..523b381b2
--- /dev/null
+++ b/examples/shaders/shaders_ascii_rendering.c
@@ -0,0 +1,121 @@
+/*******************************************************************************************
+*
+* raylib [shaders] example - ascii rendering
+*
+* Example complexity rating: [★★☆☆] 2/4
+*
+* Example originally created with raylib 5.5, last time updated with raylib 5.6
+*
+* Example contributed by Maicon Santana (@maiconpintoabreu) and reviewed by Ramon Santamaria (@raysan5)
+*
+* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
+* BSD-like license that allows static linking with closed source software
+*
+* Copyright (c) 2025 Maicon Santana (@maiconpintoabreu)
+*
+********************************************************************************************/
+
+#include "raylib.h"
+
+#if defined(PLATFORM_DESKTOP)
+ #define GLSL_VERSION 330
+#else // PLATFORM_ANDROID, PLATFORM_WEB
+ #define GLSL_VERSION 100
+#endif
+
+//------------------------------------------------------------------------------------
+// Program main entry point
+//------------------------------------------------------------------------------------
+int main(void)
+{
+ // Initialization
+ //--------------------------------------------------------------------------------------
+ const int screenWidth = 800;
+ const int screenHeight = 450;
+
+ InitWindow(screenWidth, screenHeight, "raylib [shaders] example - ascii rendering");
+
+ // Texture to test static drawing
+ Texture2D fudesumi = LoadTexture("resources/fudesumi.png");
+ // Texture to test moving drawing
+ Texture2D raysan = LoadTexture("resources/raysan.png");
+
+ // Load shader to be used on postprocessing
+ Shader shader = LoadShader(0, TextFormat("resources/shaders/glsl%i/ascii.fs", GLSL_VERSION));
+
+ // These locations are used to send data to the GPU
+ int resolutionLoc = GetShaderLocation(shader, "resolution");
+ int fontSizeLoc = GetShaderLocation(shader, "fontSize");
+
+ // Set the character size for the ASCII effect
+ // Fontsize should be 9 or more
+ float fontSize = 9.0f;
+
+ // Send the updated values to the shader
+ float resolution[2] = { (float)screenWidth, (float)screenHeight };
+ SetShaderValue(shader, resolutionLoc, resolution, SHADER_UNIFORM_VEC2);
+
+ Vector2 circlePos = (Vector2){40.0f, (float)screenHeight*0.5f};
+ float circleSpeed = 1.0f;
+
+ // RenderTexture to apply the postprocessing later
+ RenderTexture2D target = LoadRenderTexture(screenWidth, screenHeight);
+
+ SetTargetFPS(60); // Set our game to run at 60 frames-per-second
+ //--------------------------------------------------------------------------------------
+
+ // Main game loop
+ while (!WindowShouldClose()) // Detect window close button or ESC key
+ {
+ // Update
+ //----------------------------------------------------------------------------------
+ circlePos.x += circleSpeed;
+ if ((circlePos.x > 200.0f) || (circlePos.x < 40.0f)) circleSpeed *= -1; // Revert speed
+
+ if (IsKeyPressed(KEY_LEFT) && (fontSize > 9.0)) fontSize -= 1; // Reduce fontSize
+ if (IsKeyPressed(KEY_RIGHT) && (fontSize < 15.0)) fontSize += 1; // Increase fontSize
+
+ // Set fontsize for the shader
+ SetShaderValue(shader, fontSizeLoc, &fontSize, SHADER_UNIFORM_FLOAT);
+
+ // Draw
+ //----------------------------------------------------------------------------------
+ BeginTextureMode(target);
+ ClearBackground(WHITE);
+
+ // Draw scene in our render texture
+ DrawTexture(fudesumi, 500, -30, WHITE);
+ DrawTextureV(raysan, circlePos, WHITE);
+ EndTextureMode();
+
+ BeginDrawing();
+ ClearBackground(RAYWHITE);
+
+ BeginShaderMode(shader);
+ // Draw the scene texture (that we rendered earlier) to the screen
+ // The shader will process every pixel of this texture
+ DrawTextureRec(target.texture,
+ (Rectangle){ 0, 0, (float)target.texture.width, (float)-target.texture.height },
+ (Vector2){ 0, 0 }, WHITE);
+ EndShaderMode();
+
+ DrawRectangle(0, 0, screenWidth, 40, BLACK);
+ DrawText(TextFormat("Ascii effect - FontSize:%2.0f - [Left] -1 [Right] +1 ", fontSize), 120, 10, 20, LIGHTGRAY);
+ DrawFPS(10, 10);
+ EndDrawing();
+ //----------------------------------------------------------------------------------
+ }
+
+ // De-Initialization
+ //--------------------------------------------------------------------------------------
+ UnloadRenderTexture(target); // Unload render texture
+
+ UnloadShader(shader); // Unload shader
+ UnloadTexture(fudesumi); // Unload texture
+ UnloadTexture(raysan); // Unload texture
+
+ CloseWindow(); // Close window and OpenGL context
+ //--------------------------------------------------------------------------------------
+
+ return 0;
+}
diff --git a/examples/shaders/shaders_ascii_rendering.png b/examples/shaders/shaders_ascii_rendering.png
new file mode 100644
index 000000000..59ecc8395
Binary files /dev/null and b/examples/shaders/shaders_ascii_rendering.png differ
diff --git a/examples/shapes/shapes_bouncing_ball.c b/examples/shapes/shapes_bouncing_ball.c
index 187cd41af..5ae699944 100644
--- a/examples/shapes/shapes_bouncing_ball.c
+++ b/examples/shapes/shapes_bouncing_ball.c
@@ -6,6 +6,8 @@
*
* Example originally created with raylib 2.5, last time updated with raylib 2.5
*
+* Example contributed by Ramon Santamaria (@raysan5), reviewed by Jopestpe (@jopestpe)
+*
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
* BSD-like license that allows static linking with closed source software
*
@@ -31,7 +33,9 @@ int main(void)
Vector2 ballPosition = { GetScreenWidth()/2.0f, GetScreenHeight()/2.0f };
Vector2 ballSpeed = { 5.0f, 4.0f };
int ballRadius = 20;
+ float gravity = 0.2f;
+ bool useGravity = true;
bool pause = 0;
int framesCounter = 0;
@@ -43,16 +47,19 @@ int main(void)
{
// Update
//-----------------------------------------------------
+ if (IsKeyPressed(KEY_G)) useGravity = !useGravity;
if (IsKeyPressed(KEY_SPACE)) pause = !pause;
-
+
if (!pause)
{
ballPosition.x += ballSpeed.x;
ballPosition.y += ballSpeed.y;
+ if (useGravity) ballSpeed.y += gravity;
+
// Check walls collision for bouncing
if ((ballPosition.x >= (GetScreenWidth() - ballRadius)) || (ballPosition.x <= ballRadius)) ballSpeed.x *= -1.0f;
- if ((ballPosition.y >= (GetScreenHeight() - ballRadius)) || (ballPosition.y <= ballRadius)) ballSpeed.y *= -1.0f;
+ if ((ballPosition.y >= (GetScreenHeight() - ballRadius)) || (ballPosition.y <= ballRadius)) ballSpeed.y *= -0.95f;
}
else framesCounter++;
//-----------------------------------------------------
@@ -65,12 +72,15 @@ int main(void)
DrawCircleV(ballPosition, (float)ballRadius, MAROON);
DrawText("PRESS SPACE to PAUSE BALL MOVEMENT", 10, GetScreenHeight() - 25, 20, LIGHTGRAY);
+
+ if (useGravity) DrawText("GRAVITY: ON (Press G to disable)", 10, GetScreenHeight() - 50, 20, DARKGREEN);
+ else DrawText("GRAVITY: OFF (Press G to enable)", 10, GetScreenHeight() - 50, 20, RED);
// On pause, we draw a blinking message
if (pause && ((framesCounter/30)%2)) DrawText("PAUSED", 350, 200, 30, GRAY);
DrawFPS(10, 10);
-
+
EndDrawing();
//-----------------------------------------------------
}
diff --git a/examples/shapes/shapes_bullet_hell.c b/examples/shapes/shapes_bullet_hell.c
new file mode 100644
index 000000000..8eaddfbfe
--- /dev/null
+++ b/examples/shapes/shapes_bullet_hell.c
@@ -0,0 +1,248 @@
+/*******************************************************************************************
+*
+* raylib [shapes] example - bullet hell
+*
+* Example complexity rating: [★☆☆☆] 1/4
+*
+* Example originally created with raylib 5.6, last time updated with raylib 5.6
+*
+* Example contributed by Zero (@zerohorsepower) and reviewed by Ramon Santamaria (@raysan5)
+*
+* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
+* BSD-like license that allows static linking with closed source software
+*
+* Copyright (c) 2025 Zero (@zerohorsepower)
+*
+********************************************************************************************/
+
+#include "raylib.h"
+
+#include // Required for: calloc(), free()
+#include // Required for: cosf(), sinf()
+
+#define MAX_BULLETS 500000 // Max bullets to be processed
+
+//----------------------------------------------------------------------------------
+// Types and Structures Definition
+//----------------------------------------------------------------------------------
+typedef struct Bullet {
+ Vector2 position; // Bullet position on screen
+ Vector2 acceleration; // Amount of pixels to be incremented to position every frame
+ bool disabled; // Skip processing and draw case out of screen
+ Color color; // Bullet color
+} Bullet;
+
+//------------------------------------------------------------------------------------
+// Program main entry point
+//------------------------------------------------------------------------------------
+int main(void)
+{
+ // Initialization
+ //--------------------------------------------------------------------------------------
+ const int screenWidth = 800;
+ const int screenHeight = 450;
+
+ InitWindow(screenWidth, screenHeight, "raylib [shapes] example - bullet hell");
+
+ // Bullets definition
+ Bullet *bullets = (Bullet *)RL_CALLOC(MAX_BULLETS, sizeof(Bullet)); // Bullets array
+ int bulletCount = 0;
+ int bulletDisabledCount = 0; // Used to calculate how many bullets are on screen
+ int bulletRadius = 10;
+ float bulletSpeed = 3.0f;
+ int bulletRows = 6;
+ Color bulletColor[2] = { RED, BLUE };
+
+ // Spawner variables
+ float baseDirection = 0;
+ int angleIncrement = 5; // After spawn all bullet rows, increment this value on the baseDirection for next the frame
+ float spawnCooldown = 2;
+ float spawnCooldownTimer = spawnCooldown;
+
+ // Magic circle
+ float magicCircleRotation = 0;
+
+ // Used on performance drawing
+ RenderTexture bulletTexture = LoadRenderTexture(24, 24);
+
+ // Draw circle to bullet texture, then draw bullet using DrawTexture()
+ // NOTE: This is done to improve the performance, since DrawCircle() is very slow
+ BeginTextureMode(bulletTexture);
+ DrawCircle(12, 12, bulletRadius, WHITE);
+ DrawCircleLines(12, 12, bulletRadius, BLACK);
+ EndTextureMode();
+
+ bool drawInPerformanceMode = true; // Switch between DrawCircle() and DrawTexture()
+
+ SetTargetFPS(60);
+ //--------------------------------------------------------------------------------------
+
+ // Main game loop
+ while (!WindowShouldClose()) // Detect window close button or ESC key
+ {
+ // Update
+ //----------------------------------------------------------------------------------
+ // Reset the bullet index
+ // New bullets will replace the old ones that are already disabled due to out-of-screen
+ if (bulletCount >= MAX_BULLETS)
+ {
+ bulletCount = 0;
+ bulletDisabledCount = 0;
+ }
+
+ spawnCooldownTimer--;
+ if (spawnCooldownTimer < 0)
+ {
+ spawnCooldownTimer = spawnCooldown;
+
+ // Spawn bullets
+ float degreesPerRow = 360.0f/bulletRows;
+ for (int row = 0; row < bulletRows; row++)
+ {
+ if (bulletCount < MAX_BULLETS)
+ {
+ bullets[bulletCount].position = (Vector2){(float) screenWidth/2, (float) screenHeight/2};
+ bullets[bulletCount].disabled = false;
+ bullets[bulletCount].color = bulletColor[row%2];
+
+ float bulletDirection = baseDirection + (degreesPerRow*row);
+
+ // Bullet speed * bullet direction, this will determine how much pixels will be incremented/decremented
+ // from the bullet position every frame. Since the bullets doesn't change its direction and speed,
+ // only need to calculate it at the spawning time
+ // 0 degrees = right, 90 degrees = down, 180 degrees = left and 270 degrees = up, basically clockwise
+ // Case you want it to be anti-clockwise, add "* -1" at the y acceleration
+ bullets[bulletCount].acceleration = (Vector2){
+ bulletSpeed*cosf(bulletDirection*DEG2RAD),
+ bulletSpeed*sinf(bulletDirection*DEG2RAD)
+ };
+
+ bulletCount++;
+ }
+ }
+
+ baseDirection += angleIncrement;
+ }
+
+ // Update bullets position based on its acceleration
+ for (int i = 0; i < bulletCount; i++)
+ {
+ // Only update bullet if inside the screen
+ if (!bullets[i].disabled)
+ {
+ bullets[i].position.x += bullets[i].acceleration.x;
+ bullets[i].position.y += bullets[i].acceleration.y;
+
+ // Disable bullet if out of screen
+ if ((bullets[i].position.x < -bulletRadius*2) ||
+ (bullets[i].position.x > screenWidth + bulletRadius*2) ||
+ (bullets[i].position.y < -bulletRadius*2) ||
+ (bullets[i].position.y > screenHeight + bulletRadius*2))
+ {
+ bullets[i].disabled = true;
+ bulletDisabledCount++;
+ }
+ }
+ }
+
+ // Input logic
+ if ((IsKeyPressed(KEY_RIGHT) || IsKeyPressed(KEY_D)) && (bulletRows < 359)) bulletRows++;
+ if ((IsKeyPressed(KEY_LEFT) || IsKeyPressed(KEY_A)) && (bulletRows > 1)) bulletRows--;
+ if (IsKeyPressed(KEY_UP) || IsKeyPressed(KEY_W)) bulletSpeed += 0.25f;
+ if ((IsKeyPressed(KEY_DOWN) || IsKeyPressed(KEY_S)) && (bulletSpeed > 0.50f)) bulletSpeed -= 0.25f;
+ if (IsKeyPressed(KEY_Z) && (spawnCooldown > 1)) spawnCooldown--;
+ if (IsKeyPressed(KEY_X)) spawnCooldown++;
+ if (IsKeyPressed(KEY_ENTER)) drawInPerformanceMode = !drawInPerformanceMode;
+
+ if (IsKeyDown(KEY_SPACE))
+ {
+ angleIncrement += 1;
+ angleIncrement %= 360;
+ }
+
+ if (IsKeyPressed(KEY_C))
+ {
+ bulletCount = 0;
+ bulletDisabledCount = 0;
+ }
+ //----------------------------------------------------------------------------------
+
+ // Draw
+ //----------------------------------------------------------------------------------
+ BeginDrawing();
+ ClearBackground(RAYWHITE);
+
+ // Draw magic circle
+ magicCircleRotation++;
+ DrawRectanglePro((Rectangle){ (float)screenWidth/2, (float)screenHeight/2, 120, 120 },
+ (Vector2){ 60.0f, 60.0f }, magicCircleRotation, PURPLE);
+ DrawRectanglePro((Rectangle){ (float)screenWidth/2, (float)screenHeight/2, 120, 120 },
+ (Vector2){ 60.0f, 60.0f }, magicCircleRotation + 45, PURPLE);
+ DrawCircleLines(screenWidth/2, screenHeight/2, 70, BLACK);
+ DrawCircleLines(screenWidth/2, screenHeight/2, 50, BLACK);
+ DrawCircleLines(screenWidth/2, screenHeight/2, 30, BLACK);
+
+ // Draw bullets
+ if (drawInPerformanceMode)
+ {
+ // Draw bullets using pre-rendered texture containing circle
+ for (int i = 0; i < bulletCount; i++)
+ {
+ // Do not draw disabled bullets (out of screen)
+ if (!bullets[i].disabled)
+ {
+ DrawTexture(bulletTexture.texture,
+ bullets[i].position.x - bulletTexture.texture.width*0.5f,
+ bullets[i].position.y - bulletTexture.texture.height*0.5f,
+ bullets[i].color);
+ }
+ }
+ }
+ else
+ {
+ // Draw bullets using DrawCircle(), less performant
+ for (int i = 0; i < bulletCount; i++)
+ {
+ // Do not draw disabled bullets (out of screen)
+ if (!bullets[i].disabled)
+ {
+ DrawCircleV(bullets[i].position, bulletRadius, bullets[i].color);
+ DrawCircleLinesV(bullets[i].position, bulletRadius, BLACK);
+ }
+ }
+ }
+
+ // Draw UI
+ DrawRectangle(10, 10, 280, 150, (Color){0,0, 0, 200 });
+ DrawText("Controls:", 20, 20, 10, LIGHTGRAY);
+ DrawText("- Right/Left or A/D: Change rows number", 40, 40, 10, LIGHTGRAY);
+ DrawText("- Up/Down or W/S: Change bullet speed", 40, 60, 10, LIGHTGRAY);
+ DrawText("- Z or X: Change spawn cooldown", 40, 80, 10, LIGHTGRAY);
+ DrawText("- Space (Hold): Change the angle increment", 40, 100, 10, LIGHTGRAY);
+ DrawText("- Enter: Switch draw method (Performance)", 40, 120, 10, LIGHTGRAY);
+ DrawText("- C: Clear bullets", 40, 140, 10, LIGHTGRAY);
+
+ DrawRectangle(610, 10, 170, 30, (Color){0,0, 0, 200 });
+ if (drawInPerformanceMode) DrawText("Draw method: DrawTexture(*)", 620, 20, 10, GREEN);
+ else DrawText("Draw method: DrawCircle(*)", 620, 20, 10, RED);
+
+ DrawRectangle(135, 410, 530, 30, (Color){0,0, 0, 200 });
+ DrawText(TextFormat("[ FPS: %d, Bullets: %d, Rows: %d, Bullet speed: %.2f, Angle increment per frame: %d, Cooldown: %.0f ]",
+ GetFPS(), bulletCount - bulletDisabledCount, bulletRows, bulletSpeed, angleIncrement, spawnCooldown),
+ 155, 420, 10, GREEN);
+
+ EndDrawing();
+ //----------------------------------------------------------------------------------
+ }
+
+ // De-Initialization
+ //--------------------------------------------------------------------------------------
+ UnloadRenderTexture(bulletTexture); // Unload bullet texture
+
+ RL_FREE(bullets); // Free bullets array data
+
+ CloseWindow(); // Close window and OpenGL context
+ //--------------------------------------------------------------------------------------
+
+ return 0;
+}
\ No newline at end of file
diff --git a/examples/shapes/shapes_bullet_hell.png b/examples/shapes/shapes_bullet_hell.png
new file mode 100644
index 000000000..cf8e5d8f6
Binary files /dev/null and b/examples/shapes/shapes_bullet_hell.png differ
diff --git a/examples/shapes/shapes_collision_area.c b/examples/shapes/shapes_collision_area.c
index f492cf250..426d56536 100644
--- a/examples/shapes/shapes_collision_area.c
+++ b/examples/shapes/shapes_collision_area.c
@@ -15,8 +15,6 @@
#include "raylib.h"
-#include // Required for: abs()
-
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
diff --git a/examples/shapes/shapes_dashed_line.c b/examples/shapes/shapes_dashed_line.c
new file mode 100644
index 000000000..7a6bf3eee
--- /dev/null
+++ b/examples/shapes/shapes_dashed_line.c
@@ -0,0 +1,96 @@
+/*******************************************************************************************
+*
+* raylib [shapes] example - dashed line
+*
+* Example complexity rating: [★☆☆☆] 1/4
+*
+* Example originally created with raylib 5.5, last time updated with raylib 5.5
+*
+* Example contributed by Luís Almeida (@luis605)
+*
+* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
+* BSD-like license that allows static linking with closed source software
+*
+* Copyright (c) 2025 Luís Almeida (@luis605)
+*
+********************************************************************************************/
+
+#include "raylib.h"
+
+//------------------------------------------------------------------------------------
+// Program main entry point
+//------------------------------------------------------------------------------------
+int main(void)
+{
+ // Initialization
+ //--------------------------------------------------------------------------------------
+ const int screenWidth = 800;
+ const int screenHeight = 450;
+
+ InitWindow(screenWidth, screenHeight, "raylib [shapes] example - dashed line");
+
+ // Line Properties
+ Vector2 lineStartPosition = { 20.0f, 50.0f };
+ Vector2 lineEndPosition = { 780.0f, 400.0f };
+ float dashLength = 25.0f;
+ float blankLength = 15.0f;
+
+ // Color selection
+ Color lineColors[] = { RED, ORANGE, GOLD, GREEN, BLUE, VIOLET, PINK, BLACK };
+ int colorIndex = 0;
+
+ SetTargetFPS(60); // Set our game to run at 60 frames-per-second
+ //--------------------------------------------------------------------------------------
+
+ // Main game loop
+ while (!WindowShouldClose()) // Detect window close button or ESC key
+ {
+ // Update
+ //----------------------------------------------------------------------------------
+ lineEndPosition = GetMousePosition(); // Line endpoint follows the mouse
+
+ // Change Dash Length (UP/DOWN arrows)
+ if (IsKeyDown(KEY_UP)) dashLength += 1.0f;
+ if (IsKeyDown(KEY_DOWN) && dashLength > 1.0f) dashLength -= 1.0f;
+
+ // Change Space Length (LEFT/RIGHT arrows)
+ if (IsKeyDown(KEY_RIGHT)) blankLength += 1.0f;
+ if (IsKeyDown(KEY_LEFT) && blankLength > 1.0f) blankLength -= 1.0f;
+
+ // Cycle through colors ('C' key)
+ if (IsKeyPressed(KEY_C)) colorIndex = (colorIndex + 1)%(sizeof(lineColors)/sizeof(Color));
+ //----------------------------------------------------------------------------------
+
+ // Draw
+ //----------------------------------------------------------------------------------
+ BeginDrawing();
+
+ ClearBackground(RAYWHITE);
+
+ // Draw the dashed line with the current properties
+ DrawLineDashed(lineStartPosition, lineEndPosition, dashLength, blankLength, lineColors[colorIndex]);
+
+ // Draw UI and Instructions
+ DrawRectangle(5, 5, 265, 95, Fade(SKYBLUE, 0.5f));
+ DrawRectangleLines(5, 5, 265, 95, BLUE);
+
+ DrawText("CONTROLS:", 15, 15, 10, BLACK);
+ DrawText("UP/DOWN: Change Dash Length", 15, 35, 10, BLACK);
+ DrawText("LEFT/RIGHT: Change Space Length", 15, 55, 10, BLACK);
+ DrawText("C: Cycle Color", 15, 75, 10, BLACK);
+
+ DrawText(TextFormat("Dash: %.0f | Space: %.0f", dashLength, blankLength), 15, 115, 10, DARKGRAY);
+
+ DrawFPS(screenWidth - 80, 10);
+
+ EndDrawing();
+ //----------------------------------------------------------------------------------
+ }
+
+ // De-Initialization
+ //--------------------------------------------------------------------------------------
+ CloseWindow(); // Close window and OpenGL context
+ //--------------------------------------------------------------------------------------
+
+ return 0;
+}
\ No newline at end of file
diff --git a/examples/shapes/shapes_dashed_line.png b/examples/shapes/shapes_dashed_line.png
new file mode 100644
index 000000000..5c3ce3ef3
Binary files /dev/null and b/examples/shapes/shapes_dashed_line.png differ
diff --git a/examples/shapes/shapes_kaleidoscope.c b/examples/shapes/shapes_kaleidoscope.c
new file mode 100644
index 000000000..07c96344c
--- /dev/null
+++ b/examples/shapes/shapes_kaleidoscope.c
@@ -0,0 +1,92 @@
+/*******************************************************************************************
+*
+* raylib [shapes] example - kaleidoscope
+*
+* Example complexity rating: [★★☆☆] 2/4
+*
+* Example originally created with raylib 5.5, last time updated with raylib 5.6
+*
+* Example contributed by Hugo ARNAL (@hugoarnal) and reviewed by Ramon Santamaria (@raysan5)
+*
+* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
+* BSD-like license that allows static linking with closed source software
+*
+* Copyright (c) 2025 Hugo ARNAL (@hugoarnal)
+*
+********************************************************************************************/
+
+#include "raylib.h"
+#include "raymath.h"
+
+//------------------------------------------------------------------------------------
+// Program main entry point
+//------------------------------------------------------------------------------------
+int main(void)
+{
+ // Initialization
+ //--------------------------------------------------------------------------------------
+ const int screenWidth = 800;
+ const int screenHeight = 450;
+
+ InitWindow(screenWidth, screenHeight, "raylib [shapes] example - kaleidoscope");
+
+ int symmetry = 6;
+ float angle = 360.0f/(float)symmetry;
+ float thickness = 3.0f;
+ Vector2 prevMousePos = { 0 };
+
+ SetTargetFPS(60);
+ ClearBackground(BLACK);
+
+ Vector2 offset = { (float)screenWidth/2.0f, (float)screenHeight/2.0f };
+ Camera2D camera = { 0 };
+ camera.target = (Vector2){ 0 };
+ camera.offset = offset;
+ camera.rotation = 0.0f;
+ camera.zoom = 1.0f;
+
+ Vector2 scaleVector = { 1.0f, -1.0f };
+ //--------------------------------------------------------------------------------------
+
+ // Main game loop
+ while (!WindowShouldClose()) // Detect window close button or ESC key
+ {
+ // Update
+ //----------------------------------------------------------------------------------
+ Vector2 mousePos = GetMousePosition();
+ Vector2 lineStart = Vector2Subtract(mousePos, offset);
+ Vector2 lineEnd = Vector2Subtract(prevMousePos, offset);
+ //----------------------------------------------------------------------------------
+
+ // Draw
+ //----------------------------------------------------------------------------------
+ BeginDrawing();
+ BeginMode2D(camera);
+ if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) {
+ for (int i = 0; i < symmetry; i++) {
+ lineStart = Vector2Rotate(lineStart, angle*DEG2RAD);
+ lineEnd = Vector2Rotate(lineEnd, angle*DEG2RAD);
+
+ DrawLineEx(lineStart, lineEnd, thickness, WHITE);
+
+ Vector2 reflectLineStart = Vector2Multiply(lineStart, scaleVector);
+ Vector2 reflectLineEnd = Vector2Multiply(lineEnd, scaleVector);
+
+ DrawLineEx(reflectLineStart, reflectLineEnd, thickness, WHITE);
+ }
+ }
+
+ prevMousePos = mousePos;
+ EndMode2D();
+ EndDrawing();
+ //----------------------------------------------------------------------------------
+ }
+
+ // De-Initialization
+ //--------------------------------------------------------------------------------------
+
+ CloseWindow(); // Close window and OpenGL context
+ //--------------------------------------------------------------------------------------
+
+ return 0;
+}
diff --git a/examples/shapes/shapes_kaleidoscope.png b/examples/shapes/shapes_kaleidoscope.png
new file mode 100644
index 000000000..d14571ab7
Binary files /dev/null and b/examples/shapes/shapes_kaleidoscope.png differ
diff --git a/examples/shapes/shapes_recursive_tree.c b/examples/shapes/shapes_recursive_tree.c
new file mode 100644
index 000000000..3ec46de4b
--- /dev/null
+++ b/examples/shapes/shapes_recursive_tree.c
@@ -0,0 +1,141 @@
+/*******************************************************************************************
+*
+* raylib [shapes] example - shapes recursive tree
+*
+* Example complexity rating: [★★★☆] 3/4
+*
+* Example originally created with raylib 5.6-dev, last time updated with raylib 5.6-dev
+*
+* Example contributed by Jopestpe (@jopestpe)
+*
+* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
+* BSD-like license that allows static linking with closed source software
+*
+* Copyright (c) 2018-2025 Jopestpe (@jopestpe)
+*
+********************************************************************************************/
+
+#include "raylib.h"
+#include
+
+#define RAYGUI_IMPLEMENTATION
+#include "raygui.h" // Required for GUI controls
+
+//----------------------------------------------------------------------------------
+// Types and Structures Definition
+//----------------------------------------------------------------------------------
+typedef struct {
+ Vector2 start;
+ Vector2 end;
+ float angle;
+ float length;
+} Branch;
+
+//----------------------------------------------------------------------------------
+// Module Functions Declaration
+//----------------------------------------------------------------------------------
+static Vector2 CalculateBranchEnd(Vector2 start, float angle, float length);
+
+//------------------------------------------------------------------------------------
+// Program main entry point
+//------------------------------------------------------------------------------------
+int main(void)
+{
+ // Initialization
+ //--------------------------------------------------------------------------------------
+ const int screenWidth = 800;
+ const int screenHeight = 450;
+
+ InitWindow(screenWidth, screenHeight, "raylib [shapes] example - shapes recursive tree");
+
+ Vector2 start = { (screenWidth/2.0f) - 125.0f, screenHeight };
+ float angle = 40.0f;
+ float thick = 1.0f;
+ float treeDepth = 10.0f;
+ float branchDecay = 0.66f;
+ float length = 120.0f;
+ bool bezier = false;
+
+ SetTargetFPS(60); // Set our game to run at 60 frames-per-second
+ //--------------------------------------------------------------------------------------
+
+ // Main game loop
+ while (!WindowShouldClose()) // Detect window close button or ESC key
+ {
+ // Update
+ //----------------------------------------------------------------------------------
+
+ float theta = angle*DEG2RAD;
+ int maxBranches = (int)(powf(2, (int)(treeDepth)));
+ Branch branches[1024] = { 0 };
+ int count = 0;
+
+ Vector2 initialEnd = CalculateBranchEnd(start, 0.0f, length);
+ branches[count++] = (Branch){start, initialEnd, 0.0f, length};
+
+ for (int i = 0; i < count; i++)
+ {
+ Branch branch = branches[i];
+ if (branch.length < 2) continue;
+
+ float nextLength = branch.length*branchDecay;
+
+ if (count < maxBranches && nextLength >= 2)
+ {
+ Vector2 branchStart = branch.end;
+
+ Vector2 branchEnd1 = CalculateBranchEnd(branchStart, branch.angle + theta, nextLength);
+ Vector2 branchEnd2 = CalculateBranchEnd(branchStart, branch.angle - theta, nextLength);
+
+ branches[count++] = (Branch){branchStart, branchEnd1, branch.angle + theta, nextLength};
+ branches[count++] = (Branch){branchStart, branchEnd2, branch.angle - theta, nextLength};
+ }
+ }
+
+ // Draw
+ //----------------------------------------------------------------------------------
+ BeginDrawing();
+
+ ClearBackground(RAYWHITE);
+
+ for (int i = 0; i < count; i++)
+ {
+ Branch branch = branches[i];
+ if (branch.length >= 2)
+ {
+ if (!bezier) DrawLineEx(branch.start, branch.end, thick, RED);
+ else DrawLineBezier(branch.start, branch.end, thick, RED);
+ }
+ }
+
+ DrawLine(580, 0, 580, GetScreenHeight(), (Color){ 218, 218, 218, 255 });
+ DrawRectangle(580, 0, GetScreenWidth(), GetScreenHeight(), (Color){ 232, 232, 232, 255 });
+
+ // Draw GUI controls
+ //------------------------------------------------------------------------------
+ GuiSliderBar((Rectangle){ 640, 40, 120, 20}, "Angle", TextFormat("%.0f", angle), &angle, 0, 180);
+ GuiSliderBar((Rectangle){ 640, 70, 120, 20 }, "Length", TextFormat("%.0f", length), &length, 12.0f, 240.0f);
+ GuiSliderBar((Rectangle){ 640, 100, 120, 20}, "Decay", TextFormat("%.2f", branchDecay), &branchDecay, 0.1f, 0.78f);
+ GuiSliderBar((Rectangle){ 640, 130, 120, 20 }, "Depth", TextFormat("%.0f", treeDepth), &treeDepth, 1.0f, 10.f);
+ GuiSliderBar((Rectangle){ 640, 160, 120, 20}, "Thick", TextFormat("%.0f", thick), &thick, 1, 8);
+ GuiCheckBox((Rectangle){ 640, 190, 20, 20 }, "Bezier", &bezier);
+ //------------------------------------------------------------------------------
+
+ DrawFPS(10, 10);
+
+ EndDrawing();
+ //----------------------------------------------------------------------------------
+ }
+
+ // De-Initialization
+ //--------------------------------------------------------------------------------------
+ CloseWindow(); // Close window and OpenGL context
+ //--------------------------------------------------------------------------------------
+
+ return 0;
+}
+
+static Vector2 CalculateBranchEnd(Vector2 start, float angle, float length)
+{
+ return (Vector2){ start.x + length*sinf(angle), start.y - length*cosf(angle) };
+}
\ No newline at end of file
diff --git a/examples/shapes/shapes_recursive_tree.png b/examples/shapes/shapes_recursive_tree.png
new file mode 100644
index 000000000..88932c204
Binary files /dev/null and b/examples/shapes/shapes_recursive_tree.png differ
diff --git a/examples/shapes/shapes_triangle_strip.c b/examples/shapes/shapes_triangle_strip.c
new file mode 100644
index 000000000..ee4556d25
--- /dev/null
+++ b/examples/shapes/shapes_triangle_strip.c
@@ -0,0 +1,106 @@
+/*******************************************************************************************
+*
+* raylib [shapes] example - triangle strip
+*
+* Example complexity rating: [★★☆☆] 2/4
+*
+* Example originally created with raylib 5.6-dev, last time updated with raylib 5.6-dev
+*
+* Example contributed by Jopestpe (@jopestpe)
+*
+* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
+* BSD-like license that allows static linking with closed source software
+*
+* Copyright (c) 2018-2025 Jopestpe (@jopestpe)
+*
+********************************************************************************************/
+
+#include "raylib.h"
+#include
+
+#define RAYGUI_IMPLEMENTATION
+#include "raygui.h" // Required for GUI controls
+
+//------------------------------------------------------------------------------------
+// Program main entry point
+//------------------------------------------------------------------------------------
+int main(void)
+{
+ // Initialization
+ //--------------------------------------------------------------------------------------
+ const int screenWidth = 800;
+ const int screenHeight = 450;
+
+ InitWindow(screenWidth, screenHeight, "raylib [shapes] example - triangle strip");
+
+ Vector2 points[120] = { 0 };
+ Vector2 center = { (screenWidth/2.0f) - 125.f, screenHeight/2.0f };
+ float segments = 6.0f;
+ float insideRadius = 100.0f;
+ float outsideRadius = 150.0f;
+ bool outline = true;
+
+ SetTargetFPS(60); // Set our game to run at 60 frames-per-second
+ //--------------------------------------------------------------------------------------
+
+ // Main game loop
+ while (!WindowShouldClose()) // Detect window close button or ESC key
+ {
+ // Update
+ //----------------------------------------------------------------------------------
+ int pointCount = (int)(segments);
+ float angleStep = (360.0f/pointCount)*DEG2RAD;
+
+ for (int i = 0, i2 = 0; i < pointCount; i++, i2 += 2)
+ {
+ float angle1 = i*angleStep;
+ points[i2] = (Vector2){ center.x + cosf(angle1)*insideRadius, center.y + sinf(angle1)*insideRadius };
+ float angle2 = angle1 + angleStep/2.0f;
+ points[i2 + 1] = (Vector2){ center.x + cosf(angle2)*outsideRadius, center.y + sinf(angle2)*outsideRadius };
+ }
+
+ points[pointCount*2] = points[0];
+ points[pointCount*2 + 1] = points[1];
+ //----------------------------------------------------------------------------------
+
+ // Draw
+ //----------------------------------------------------------------------------------
+ BeginDrawing();
+
+ ClearBackground(RAYWHITE);
+
+ for (int i = 0, i2 = 0; i < pointCount; i++, i2 += 2)
+ {
+ float angle1 = i*angleStep;
+ Color color = ColorFromHSV(angle1*RAD2DEG, 1.0f, 1.0f);
+ DrawTriangle(points[i2 + 2], points[i2 + 1], points[i2], color);
+ if (outline) DrawTriangleLines(points[i2], points[i2 + 1], points[i2 + 2], BLACK);
+
+ float angle2 = angle1 + angleStep/2.0f;
+ color = ColorFromHSV(angle2*RAD2DEG, 1.0f, 1.0f);
+ DrawTriangle(points[i2 + 3], points[i2 + 1], points[i2 + 2], color);
+ if (outline) DrawTriangleLines(points[i2 + 2], points[i2 + 1], points[i2 + 3], BLACK);
+ }
+
+ DrawLine(580, 0, 580, GetScreenHeight(), (Color){ 218, 218, 218, 255 });
+ DrawRectangle(580, 0, GetScreenWidth(), GetScreenHeight(), (Color){ 232, 232, 232, 255 });
+
+ // Draw GUI controls
+ //------------------------------------------------------------------------------
+ GuiSliderBar((Rectangle){ 640, 40, 120, 20}, "Segments", TextFormat("%.0f", segments), &segments, 6.0f, 60.f);
+ GuiCheckBox((Rectangle){ 640, 70, 20, 20 }, "Outline", &outline);
+ //------------------------------------------------------------------------------
+
+ DrawFPS(10, 10);
+
+ EndDrawing();
+ //----------------------------------------------------------------------------------
+ }
+
+ // De-Initialization
+ //--------------------------------------------------------------------------------------
+ CloseWindow(); // Close window and OpenGL context
+ //--------------------------------------------------------------------------------------
+
+ return 0;
+}
\ No newline at end of file
diff --git a/examples/shapes/shapes_triangle_strip.png b/examples/shapes/shapes_triangle_strip.png
new file mode 100644
index 000000000..c291a0849
Binary files /dev/null and b/examples/shapes/shapes_triangle_strip.png differ
diff --git a/examples/others/raymath_vector_angle.c b/examples/shapes/shapes_vector_angle.c
similarity index 96%
rename from examples/others/raymath_vector_angle.c
rename to examples/shapes/shapes_vector_angle.c
index cded99e8b..7de296dcb 100644
--- a/examples/others/raymath_vector_angle.c
+++ b/examples/shapes/shapes_vector_angle.c
@@ -1,6 +1,6 @@
/*******************************************************************************************
*
-* raylib [others] example - vector angle
+* raylib [shapes] example - vector angle
*
* Example complexity rating: [★★☆☆] 2/4
*
@@ -15,7 +15,7 @@
#include "raylib.h"
-#include "raymath.h"
+#include "raymath.h" // Required for: Vector2LineAngle()
//------------------------------------------------------------------------------------
// Program main entry point
@@ -25,9 +25,10 @@ int main(void)
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
+
const int screenHeight = 450;
- InitWindow(screenWidth, screenHeight, "raylib [others] example - vector angle");
+ InitWindow(screenWidth, screenHeight, "raylib [shapes] example - vector angle");
Vector2 v0 = { screenWidth/2, screenHeight/2 };
Vector2 v1 = Vector2Add(v0, (Vector2){ 100.0f, 80.0f });
diff --git a/examples/others/raymath_vector_angle.png b/examples/shapes/shapes_vector_angle.png
similarity index 100%
rename from examples/others/raymath_vector_angle.png
rename to examples/shapes/shapes_vector_angle.png
diff --git a/projects/VS2022/examples/core_delta_time.vcxproj b/projects/VS2022/examples/core_delta_time.vcxproj
new file mode 100644
index 000000000..3d31afa42
--- /dev/null
+++ b/projects/VS2022/examples/core_delta_time.vcxproj
@@ -0,0 +1,569 @@
+
+
+
+
+ Debug.DLL
+ ARM64
+
+
+ Debug.DLL
+ Win32
+
+
+ Debug.DLL
+ x64
+
+
+ Debug
+ ARM64
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release.DLL
+ ARM64
+
+
+ Release.DLL
+ Win32
+
+
+ Release.DLL
+ x64
+
+
+ Release
+ ARM64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}
+ Win32Proj
+ core_delta_time
+ 10.0
+ core_delta_time
+
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ $(SolutionDir)..\..\examples\core
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\core
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\core
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\core
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\core
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\core
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\core
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\core
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\core
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\core
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\core
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\core
+ WindowsLocalDebugger
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ /FS %(AdditionalOptions)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;shcore.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ /FS %(AdditionalOptions)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+
+
+
+
+
+
+ {e89d61ac-55de-4482-afd4-df7242ebc859}
+
+
+
+
+
+
\ No newline at end of file
diff --git a/projects/VS2022/examples/core_input_actions.vcxproj b/projects/VS2022/examples/core_input_actions.vcxproj
new file mode 100644
index 000000000..9b43826f8
--- /dev/null
+++ b/projects/VS2022/examples/core_input_actions.vcxproj
@@ -0,0 +1,569 @@
+
+
+
+
+ Debug.DLL
+ ARM64
+
+
+ Debug.DLL
+ Win32
+
+
+ Debug.DLL
+ x64
+
+
+ Debug
+ ARM64
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release.DLL
+ ARM64
+
+
+ Release.DLL
+ Win32
+
+
+ Release.DLL
+ x64
+
+
+ Release
+ ARM64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ {718FCBD0-591D-448C-B7D5-9F1CA8544E7B}
+ Win32Proj
+ core_input_actions
+ 10.0
+ core_input_actions
+
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ $(SolutionDir)..\..\examples\core
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\core
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\core
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\core
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\core
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\core
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\core
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\core
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\core
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\core
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\core
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\core
+ WindowsLocalDebugger
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ /FS %(AdditionalOptions)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;shcore.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ /FS %(AdditionalOptions)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+
+
+
+
+
+
+ {e89d61ac-55de-4482-afd4-df7242ebc859}
+
+
+
+
+
+
\ No newline at end of file
diff --git a/projects/VS2022/examples/core_monitor_change.vcxproj b/projects/VS2022/examples/core_monitor_change.vcxproj
new file mode 100644
index 000000000..e372a68d0
--- /dev/null
+++ b/projects/VS2022/examples/core_monitor_change.vcxproj
@@ -0,0 +1,569 @@
+
+
+
+
+ Debug.DLL
+ ARM64
+
+
+ Debug.DLL
+ Win32
+
+
+ Debug.DLL
+ x64
+
+
+ Debug
+ ARM64
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release.DLL
+ ARM64
+
+
+ Release.DLL
+ Win32
+
+
+ Release.DLL
+ x64
+
+
+ Release
+ ARM64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}
+ Win32Proj
+ core_monitor_change
+ 10.0
+ core_monitor_change
+
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ $(SolutionDir)..\..\examples\core
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\core
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\core
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\core
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\core
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\core
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\core
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\core
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\core
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\core
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\core
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\core
+ WindowsLocalDebugger
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ /FS %(AdditionalOptions)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;shcore.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ /FS %(AdditionalOptions)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+
+
+
+
+
+
+ {e89d61ac-55de-4482-afd4-df7242ebc859}
+
+
+
+
+
+
\ No newline at end of file
diff --git a/projects/VS2022/examples/models_basic_voxel.vcxproj b/projects/VS2022/examples/models_basic_voxel.vcxproj
new file mode 100644
index 000000000..f3e541f27
--- /dev/null
+++ b/projects/VS2022/examples/models_basic_voxel.vcxproj
@@ -0,0 +1,569 @@
+
+
+
+
+ Debug.DLL
+ ARM64
+
+
+ Debug.DLL
+ Win32
+
+
+ Debug.DLL
+ x64
+
+
+ Debug
+ ARM64
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release.DLL
+ ARM64
+
+
+ Release.DLL
+ Win32
+
+
+ Release.DLL
+ x64
+
+
+ Release
+ ARM64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}
+ Win32Proj
+ models_basic_voxel
+ 10.0
+ models_basic_voxel
+
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ $(SolutionDir)..\..\examples\models
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\models
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\models
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\models
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\models
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\models
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\models
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\models
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\models
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\models
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\models
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\models
+ WindowsLocalDebugger
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ /FS %(AdditionalOptions)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;shcore.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ /FS %(AdditionalOptions)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+
+
+
+
+
+
+ {e89d61ac-55de-4482-afd4-df7242ebc859}
+
+
+
+
+
+
\ No newline at end of file
diff --git a/projects/VS2022/examples/models_geometry_textures_cube.vcxproj b/projects/VS2022/examples/models_geometry_textures_cube.vcxproj
new file mode 100644
index 000000000..5c8452472
--- /dev/null
+++ b/projects/VS2022/examples/models_geometry_textures_cube.vcxproj
@@ -0,0 +1,569 @@
+
+
+
+
+ Debug.DLL
+ ARM64
+
+
+ Debug.DLL
+ Win32
+
+
+ Debug.DLL
+ x64
+
+
+ Debug
+ ARM64
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release.DLL
+ ARM64
+
+
+ Release.DLL
+ Win32
+
+
+ Release.DLL
+ x64
+
+
+ Release
+ ARM64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}
+ Win32Proj
+ models_geometry_textures_cube
+ 10.0
+ models_geometry_textures_cube
+
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ $(SolutionDir)..\..\examples\models
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\models
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\models
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\models
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\models
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\models
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\models
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\models
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\models
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\models
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\models
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\models
+ WindowsLocalDebugger
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ /FS %(AdditionalOptions)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;shcore.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ /FS %(AdditionalOptions)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+
+
+
+
+
+
+ {e89d61ac-55de-4482-afd4-df7242ebc859}
+
+
+
+
+
+
\ No newline at end of file
diff --git a/projects/VS2022/examples/shaders_ascii_rendering.vcxproj b/projects/VS2022/examples/shaders_ascii_rendering.vcxproj
new file mode 100644
index 000000000..49ee10790
--- /dev/null
+++ b/projects/VS2022/examples/shaders_ascii_rendering.vcxproj
@@ -0,0 +1,569 @@
+
+
+
+
+ Debug.DLL
+ ARM64
+
+
+ Debug.DLL
+ Win32
+
+
+ Debug.DLL
+ x64
+
+
+ Debug
+ ARM64
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release.DLL
+ ARM64
+
+
+ Release.DLL
+ Win32
+
+
+ Release.DLL
+ x64
+
+
+ Release
+ ARM64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ {9DB1F875-6E65-4195-B23F-ED8095C0B99C}
+ Win32Proj
+ shaders_ascii_rendering
+ 10.0
+ shaders_ascii_rendering
+
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ $(SolutionDir)..\..\examples\shaders
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shaders
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shaders
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shaders
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shaders
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shaders
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shaders
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shaders
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shaders
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shaders
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shaders
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shaders
+ WindowsLocalDebugger
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ /FS %(AdditionalOptions)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;shcore.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ /FS %(AdditionalOptions)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+
+
+
+
+
+
+ {e89d61ac-55de-4482-afd4-df7242ebc859}
+
+
+
+
+
+
\ No newline at end of file
diff --git a/projects/VS2022/examples/shapes_bullet_hell.vcxproj b/projects/VS2022/examples/shapes_bullet_hell.vcxproj
new file mode 100644
index 000000000..de74d2f79
--- /dev/null
+++ b/projects/VS2022/examples/shapes_bullet_hell.vcxproj
@@ -0,0 +1,569 @@
+
+
+
+
+ Debug.DLL
+ ARM64
+
+
+ Debug.DLL
+ Win32
+
+
+ Debug.DLL
+ x64
+
+
+ Debug
+ ARM64
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release.DLL
+ ARM64
+
+
+ Release.DLL
+ Win32
+
+
+ Release.DLL
+ x64
+
+
+ Release
+ ARM64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}
+ Win32Proj
+ shapes_bullet_hell
+ 10.0
+ shapes_bullet_hell
+
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ $(SolutionDir)..\..\examples\shapes
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shapes
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shapes
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shapes
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shapes
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shapes
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shapes
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shapes
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shapes
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shapes
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shapes
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shapes
+ WindowsLocalDebugger
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ /FS %(AdditionalOptions)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;shcore.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ /FS %(AdditionalOptions)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+
+
+
+
+
+
+ {e89d61ac-55de-4482-afd4-df7242ebc859}
+
+
+
+
+
+
\ No newline at end of file
diff --git a/projects/VS2022/examples/shapes_dashed_line.vcxproj b/projects/VS2022/examples/shapes_dashed_line.vcxproj
new file mode 100644
index 000000000..4a4b86ef3
--- /dev/null
+++ b/projects/VS2022/examples/shapes_dashed_line.vcxproj
@@ -0,0 +1,569 @@
+
+
+
+
+ Debug.DLL
+ ARM64
+
+
+ Debug.DLL
+ Win32
+
+
+ Debug.DLL
+ x64
+
+
+ Debug
+ ARM64
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release.DLL
+ ARM64
+
+
+ Release.DLL
+ Win32
+
+
+ Release.DLL
+ x64
+
+
+ Release
+ ARM64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}
+ Win32Proj
+ shapes_dashed_line
+ 10.0
+ shapes_dashed_line
+
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ $(SolutionDir)..\..\examples\shapes
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shapes
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shapes
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shapes
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shapes
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shapes
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shapes
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shapes
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shapes
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shapes
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shapes
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shapes
+ WindowsLocalDebugger
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ /FS %(AdditionalOptions)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;shcore.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ /FS %(AdditionalOptions)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+
+
+
+
+
+
+ {e89d61ac-55de-4482-afd4-df7242ebc859}
+
+
+
+
+
+
\ No newline at end of file
diff --git a/projects/VS2022/examples/shapes_kaleidoscope.vcxproj b/projects/VS2022/examples/shapes_kaleidoscope.vcxproj
new file mode 100644
index 000000000..1fe3e7a70
--- /dev/null
+++ b/projects/VS2022/examples/shapes_kaleidoscope.vcxproj
@@ -0,0 +1,569 @@
+
+
+
+
+ Debug.DLL
+ ARM64
+
+
+ Debug.DLL
+ Win32
+
+
+ Debug.DLL
+ x64
+
+
+ Debug
+ ARM64
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release.DLL
+ ARM64
+
+
+ Release.DLL
+ Win32
+
+
+ Release.DLL
+ x64
+
+
+ Release
+ ARM64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}
+ Win32Proj
+ shapes_kaleidoscope
+ 10.0
+ shapes_kaleidoscope
+
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ $(SolutionDir)..\..\examples\shapes
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shapes
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shapes
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shapes
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shapes
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shapes
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shapes
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shapes
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shapes
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shapes
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shapes
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shapes
+ WindowsLocalDebugger
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ /FS %(AdditionalOptions)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ /FS %(AdditionalOptions)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+
+
+
+
+
+
+ {e89d61ac-55de-4482-afd4-df7242ebc859}
+
+
+
+
+
+
\ No newline at end of file
diff --git a/projects/VS2022/examples/shapes_vector_angle.vcxproj b/projects/VS2022/examples/shapes_vector_angle.vcxproj
new file mode 100644
index 000000000..c2e0d9426
--- /dev/null
+++ b/projects/VS2022/examples/shapes_vector_angle.vcxproj
@@ -0,0 +1,569 @@
+
+
+
+
+ Debug.DLL
+ ARM64
+
+
+ Debug.DLL
+ Win32
+
+
+ Debug.DLL
+ x64
+
+
+ Debug
+ ARM64
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release.DLL
+ ARM64
+
+
+ Release.DLL
+ Win32
+
+
+ Release.DLL
+ x64
+
+
+ Release
+ ARM64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ {9DB1F875-6E65-4195-B23F-ED8095C0B99C}
+ Win32Proj
+ shapes_vector_angle
+ 10.0
+ shapes_vector_angle
+
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ $(SolutionDir)..\..\examples\shapes
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shapes
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shapes
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shapes
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shapes
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shapes
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shapes
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shapes
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shapes
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shapes
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shapes
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\shapes
+ WindowsLocalDebugger
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ /FS %(AdditionalOptions)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;shcore.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ /FS %(AdditionalOptions)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+
+
+
+
+
+
+ {e89d61ac-55de-4482-afd4-df7242ebc859}
+
+
+
+
+
+
\ No newline at end of file
diff --git a/projects/VS2022/examples/web_basic_window.vcxproj b/projects/VS2022/examples/web_basic_window.vcxproj
new file mode 100644
index 000000000..e36012ac6
--- /dev/null
+++ b/projects/VS2022/examples/web_basic_window.vcxproj
@@ -0,0 +1,569 @@
+
+
+
+
+ Debug.DLL
+ ARM64
+
+
+ Debug.DLL
+ Win32
+
+
+ Debug.DLL
+ x64
+
+
+ Debug
+ ARM64
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release.DLL
+ ARM64
+
+
+ Release.DLL
+ Win32
+
+
+ Release.DLL
+ x64
+
+
+ Release
+ ARM64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}
+ Win32Proj
+ web_basic_window
+ 10.0
+ web_basic_window
+
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ true
+ $(DefaultPlatformToolset)
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+ Application
+ false
+ $(DefaultPlatformToolset)
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ true
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ false
+ $(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)\
+ $(SolutionDir)\build\$(ProjectName)\obj\$(Platform)\$(Configuration)\
+
+
+ $(SolutionDir)..\..\examples\others
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\others
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\others
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\others
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\others
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\others
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\others
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\others
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\others
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\others
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\others
+ WindowsLocalDebugger
+
+
+ $(SolutionDir)..\..\examples\others
+ WindowsLocalDebugger
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ /FS %(AdditionalOptions)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;shcore.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ /FS %(AdditionalOptions)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions)
+ CompileAsC
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+ Copy Debug DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP
+ $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories)
+ CompileAsC
+ true
+
+
+ Console
+ true
+ true
+ true
+ raylib.lib;opengl32.lib;kernel32.lib;user32.lib;gdi32.lib;winmm.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ $(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\
+
+
+ xcopy /y /d "$(SolutionDir)\build\raylib\bin\$(Platform)\$(Configuration)\raylib.dll" "$(SolutionDir)\build\$(ProjectName)\bin\$(Platform)\$(Configuration)"
+
+
+ Copy Release DLL to output directory
+
+
+
+
+
+
+
+
+
+
+ {e89d61ac-55de-4482-afd4-df7242ebc859}
+
+
+
+
+
+
\ No newline at end of file
diff --git a/projects/VS2022/raylib.sln b/projects/VS2022/raylib.sln
index fe2241434..0c710a731 100644
--- a/projects/VS2022/raylib.sln
+++ b/projects/VS2022/raylib.sln
@@ -345,6 +345,32 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "text_inline_styling", "exam
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_undo_redo", "examples\core_undo_redo.vcxproj", "{3B27F358-2679-4F38-B297-17B536F580BB}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_input_actions", "examples\core_input_actions.vcxproj", "{718FCBD0-591D-448C-B7D5-9F1CA8544E7B}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_delta_time", "examples\core_delta_time.vcxproj", "{6B1A933E-71B8-4C1F-9E79-02D98830E671}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_bullet_hell", "examples\shapes_bullet_hell.vcxproj", "{2CCCD9E4-9058-4291-BD89-39C979F0CA1E}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_vector_angle", "examples\shapes_vector_angle.vcxproj", "{9DB1F875-6E65-4195-B23F-ED8095C0B99C}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "models_basic_voxel", "examples\models_basic_voxel.vcxproj", "{52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_dashed_line", "examples\shapes_dashed_line.vcxproj", "{6B1A933E-71B8-4C1F-9E79-02D98830E671}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "models_geometry_textures_cube", "examples\models_geometry_textures_cube.vcxproj", "{2CCCD9E4-9058-4291-BD89-39C979F0CA1E}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shaders_ascii_rendering", "examples\shaders_ascii_rendering.vcxproj", "{9DB1F875-6E65-4195-B23F-ED8095C0B99C}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_monitor_change", "examples\core_monitor_change.vcxproj", "{52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "web_basic_window", "examples\web_basic_window.vcxproj", "{6B1A933E-71B8-4C1F-9E79-02D98830E671}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_kaleidoscope", "examples\shapes_kaleidoscope.vcxproj", "{6B1A933E-71B8-4C1F-9E79-02D98830E671}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_recursive_tree", "examples\shapes_recursive_tree.vcxproj", "{6B1A933E-71B8-4C1F-9E79-02D98830E671}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_triangle_strip", "examples\shapes_triangle_strip.vcxproj", "{2CCCD9E4-9058-4291-BD89-39C979F0CA1E}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug.DLL|ARM64 = Debug.DLL|ARM64
@@ -4247,10 +4273,322 @@ Global
{3B27F358-2679-4F38-B297-17B536F580BB}.Release|x64.Build.0 = Release|x64
{3B27F358-2679-4F38-B297-17B536F580BB}.Release|x86.ActiveCfg = Release|Win32
{3B27F358-2679-4F38-B297-17B536F580BB}.Release|x86.Build.0 = Release|Win32
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
+ {718FCBD0-591D-448C-B7D5-9F1CA8544E7B}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64
+ {718FCBD0-591D-448C-B7D5-9F1CA8544E7B}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64
+ {718FCBD0-591D-448C-B7D5-9F1CA8544E7B}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64
+ {718FCBD0-591D-448C-B7D5-9F1CA8544E7B}.Debug.DLL|x64.Build.0 = Debug.DLL|x64
+ {718FCBD0-591D-448C-B7D5-9F1CA8544E7B}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32
+ {718FCBD0-591D-448C-B7D5-9F1CA8544E7B}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32
+ {718FCBD0-591D-448C-B7D5-9F1CA8544E7B}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {718FCBD0-591D-448C-B7D5-9F1CA8544E7B}.Debug|ARM64.Build.0 = Debug|ARM64
+ {718FCBD0-591D-448C-B7D5-9F1CA8544E7B}.Debug|x64.ActiveCfg = Debug|x64
+ {718FCBD0-591D-448C-B7D5-9F1CA8544E7B}.Debug|x64.Build.0 = Debug|x64
+ {718FCBD0-591D-448C-B7D5-9F1CA8544E7B}.Debug|x86.ActiveCfg = Debug|Win32
+ {718FCBD0-591D-448C-B7D5-9F1CA8544E7B}.Debug|x86.Build.0 = Debug|Win32
+ {718FCBD0-591D-448C-B7D5-9F1CA8544E7B}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64
+ {718FCBD0-591D-448C-B7D5-9F1CA8544E7B}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64
+ {718FCBD0-591D-448C-B7D5-9F1CA8544E7B}.Release.DLL|x64.ActiveCfg = Release.DLL|x64
+ {718FCBD0-591D-448C-B7D5-9F1CA8544E7B}.Release.DLL|x64.Build.0 = Release.DLL|x64
+ {718FCBD0-591D-448C-B7D5-9F1CA8544E7B}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32
+ {718FCBD0-591D-448C-B7D5-9F1CA8544E7B}.Release.DLL|x86.Build.0 = Release.DLL|Win32
+ {718FCBD0-591D-448C-B7D5-9F1CA8544E7B}.Release|ARM64.ActiveCfg = Release|ARM64
+ {718FCBD0-591D-448C-B7D5-9F1CA8544E7B}.Release|ARM64.Build.0 = Release|ARM64
+ {718FCBD0-591D-448C-B7D5-9F1CA8544E7B}.Release|x64.ActiveCfg = Release|x64
+ {718FCBD0-591D-448C-B7D5-9F1CA8544E7B}.Release|x64.Build.0 = Release|x64
+ {718FCBD0-591D-448C-B7D5-9F1CA8544E7B}.Release|x86.ActiveCfg = Release|Win32
+ {718FCBD0-591D-448C-B7D5-9F1CA8544E7B}.Release|x86.Build.0 = Release|Win32
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x64.Build.0 = Debug.DLL|x64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|ARM64.Build.0 = Debug|ARM64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x64.ActiveCfg = Debug|x64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x64.Build.0 = Debug|x64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x86.ActiveCfg = Debug|Win32
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x86.Build.0 = Debug|Win32
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x64.ActiveCfg = Release.DLL|x64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x64.Build.0 = Release.DLL|x64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x86.Build.0 = Release.DLL|Win32
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|ARM64.ActiveCfg = Release|ARM64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|ARM64.Build.0 = Release|ARM64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.ActiveCfg = Release|x64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.Build.0 = Release|x64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.ActiveCfg = Release|Win32
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.Build.0 = Release|Win32
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|x64.Build.0 = Debug.DLL|x64
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug|ARM64.Build.0 = Debug|ARM64
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug|x64.ActiveCfg = Debug|x64
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug|x64.Build.0 = Debug|x64
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug|x86.ActiveCfg = Debug|Win32
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug|x86.Build.0 = Debug|Win32
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release.DLL|x64.ActiveCfg = Release.DLL|x64
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release.DLL|x64.Build.0 = Release.DLL|x64
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release.DLL|x86.Build.0 = Release.DLL|Win32
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release|ARM64.ActiveCfg = Release|ARM64
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release|ARM64.Build.0 = Release|ARM64
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release|x64.ActiveCfg = Release|x64
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release|x64.Build.0 = Release|x64
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release|x86.ActiveCfg = Release|Win32
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release|x86.Build.0 = Release|Win32
+ {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64
+ {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64
+ {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64
+ {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug.DLL|x64.Build.0 = Debug.DLL|x64
+ {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32
+ {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32
+ {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug|ARM64.Build.0 = Debug|ARM64
+ {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug|x64.ActiveCfg = Debug|x64
+ {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug|x64.Build.0 = Debug|x64
+ {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug|x86.ActiveCfg = Debug|Win32
+ {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug|x86.Build.0 = Debug|Win32
+ {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64
+ {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64
+ {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release.DLL|x64.ActiveCfg = Release.DLL|x64
+ {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release.DLL|x64.Build.0 = Release.DLL|x64
+ {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32
+ {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release.DLL|x86.Build.0 = Release.DLL|Win32
+ {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release|ARM64.ActiveCfg = Release|ARM64
+ {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release|ARM64.Build.0 = Release|ARM64
+ {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release|x64.ActiveCfg = Release|x64
+ {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release|x64.Build.0 = Release|x64
+ {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release|x86.ActiveCfg = Release|Win32
+ {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release|x86.Build.0 = Release|Win32
+ {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64
+ {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64
+ {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64
+ {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug.DLL|x64.Build.0 = Debug.DLL|x64
+ {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32
+ {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32
+ {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug|ARM64.Build.0 = Debug|ARM64
+ {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug|x64.ActiveCfg = Debug|x64
+ {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug|x64.Build.0 = Debug|x64
+ {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug|x86.ActiveCfg = Debug|Win32
+ {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug|x86.Build.0 = Debug|Win32
+ {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64
+ {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64
+ {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release.DLL|x64.ActiveCfg = Release.DLL|x64
+ {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release.DLL|x64.Build.0 = Release.DLL|x64
+ {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32
+ {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release.DLL|x86.Build.0 = Release.DLL|Win32
+ {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release|ARM64.ActiveCfg = Release|ARM64
+ {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release|ARM64.Build.0 = Release|ARM64
+ {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release|x64.ActiveCfg = Release|x64
+ {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release|x64.Build.0 = Release|x64
+ {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release|x86.ActiveCfg = Release|Win32
+ {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release|x86.Build.0 = Release|Win32
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x64.Build.0 = Debug.DLL|x64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|ARM64.Build.0 = Debug|ARM64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x64.ActiveCfg = Debug|x64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x64.Build.0 = Debug|x64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x86.ActiveCfg = Debug|Win32
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x86.Build.0 = Debug|Win32
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x64.ActiveCfg = Release.DLL|x64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x64.Build.0 = Release.DLL|x64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x86.Build.0 = Release.DLL|Win32
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|ARM64.ActiveCfg = Release|ARM64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|ARM64.Build.0 = Release|ARM64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.ActiveCfg = Release|x64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.Build.0 = Release|x64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.ActiveCfg = Release|Win32
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.Build.0 = Release|Win32
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|x64.Build.0 = Debug.DLL|x64
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug|ARM64.Build.0 = Debug|ARM64
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug|x64.ActiveCfg = Debug|x64
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug|x64.Build.0 = Debug|x64
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug|x86.ActiveCfg = Debug|Win32
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug|x86.Build.0 = Debug|Win32
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release.DLL|x64.ActiveCfg = Release.DLL|x64
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release.DLL|x64.Build.0 = Release.DLL|x64
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release.DLL|x86.Build.0 = Release.DLL|Win32
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release|ARM64.ActiveCfg = Release|ARM64
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release|ARM64.Build.0 = Release|ARM64
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release|x64.ActiveCfg = Release|x64
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release|x64.Build.0 = Release|x64
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release|x86.ActiveCfg = Release|Win32
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release|x86.Build.0 = Release|Win32
+ {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64
+ {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64
+ {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64
+ {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug.DLL|x64.Build.0 = Debug.DLL|x64
+ {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32
+ {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32
+ {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug|ARM64.Build.0 = Debug|ARM64
+ {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug|x64.ActiveCfg = Debug|x64
+ {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug|x64.Build.0 = Debug|x64
+ {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug|x86.ActiveCfg = Debug|Win32
+ {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug|x86.Build.0 = Debug|Win32
+ {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64
+ {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64
+ {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release.DLL|x64.ActiveCfg = Release.DLL|x64
+ {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release.DLL|x64.Build.0 = Release.DLL|x64
+ {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32
+ {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release.DLL|x86.Build.0 = Release.DLL|Win32
+ {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release|ARM64.ActiveCfg = Release|ARM64
+ {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release|ARM64.Build.0 = Release|ARM64
+ {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release|x64.ActiveCfg = Release|x64
+ {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release|x64.Build.0 = Release|x64
+ {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release|x86.ActiveCfg = Release|Win32
+ {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release|x86.Build.0 = Release|Win32
+ {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64
+ {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64
+ {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64
+ {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug.DLL|x64.Build.0 = Debug.DLL|x64
+ {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32
+ {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32
+ {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug|ARM64.Build.0 = Debug|ARM64
+ {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug|x64.ActiveCfg = Debug|x64
+ {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug|x64.Build.0 = Debug|x64
+ {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug|x86.ActiveCfg = Debug|Win32
+ {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug|x86.Build.0 = Debug|Win32
+ {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64
+ {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64
+ {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release.DLL|x64.ActiveCfg = Release.DLL|x64
+ {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release.DLL|x64.Build.0 = Release.DLL|x64
+ {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32
+ {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release.DLL|x86.Build.0 = Release.DLL|Win32
+ {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release|ARM64.ActiveCfg = Release|ARM64
+ {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release|ARM64.Build.0 = Release|ARM64
+ {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release|x64.ActiveCfg = Release|x64
+ {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release|x64.Build.0 = Release|x64
+ {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release|x86.ActiveCfg = Release|Win32
+ {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release|x86.Build.0 = Release|Win32
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x64.Build.0 = Debug.DLL|x64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|ARM64.Build.0 = Debug|ARM64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x64.ActiveCfg = Debug|x64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x64.Build.0 = Debug|x64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x86.ActiveCfg = Debug|Win32
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x86.Build.0 = Debug|Win32
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x64.ActiveCfg = Release.DLL|x64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x64.Build.0 = Release.DLL|x64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x86.Build.0 = Release.DLL|Win32
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|ARM64.ActiveCfg = Release|ARM64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|ARM64.Build.0 = Release|ARM64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.ActiveCfg = Release|x64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.Build.0 = Release|x64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.ActiveCfg = Release|Win32
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.Build.0 = Release|Win32
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x64.Build.0 = Debug.DLL|x64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|ARM64.Build.0 = Debug|ARM64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x64.ActiveCfg = Debug|x64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x64.Build.0 = Debug|x64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x86.ActiveCfg = Debug|Win32
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x86.Build.0 = Debug|Win32
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x64.ActiveCfg = Release.DLL|x64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x64.Build.0 = Release.DLL|x64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x86.Build.0 = Release.DLL|Win32
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|ARM64.ActiveCfg = Release|ARM64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|ARM64.Build.0 = Release|ARM64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.ActiveCfg = Release|x64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.Build.0 = Release|x64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.ActiveCfg = Release|Win32
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.Build.0 = Release|Win32
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x64.Build.0 = Debug.DLL|x64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|ARM64.Build.0 = Debug|ARM64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x64.ActiveCfg = Debug|x64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x64.Build.0 = Debug|x64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x86.ActiveCfg = Debug|Win32
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x86.Build.0 = Debug|Win32
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x64.ActiveCfg = Release.DLL|x64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x64.Build.0 = Release.DLL|x64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x86.Build.0 = Release.DLL|Win32
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|ARM64.ActiveCfg = Release|ARM64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|ARM64.Build.0 = Release|ARM64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.ActiveCfg = Release|x64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.Build.0 = Release|x64
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.ActiveCfg = Release|Win32
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.Build.0 = Release|Win32
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|x64.Build.0 = Debug.DLL|x64
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug|ARM64.Build.0 = Debug|ARM64
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug|x64.ActiveCfg = Debug|x64
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug|x64.Build.0 = Debug|x64
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug|x86.ActiveCfg = Debug|Win32
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug|x86.Build.0 = Debug|Win32
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release.DLL|x64.ActiveCfg = Release.DLL|x64
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release.DLL|x64.Build.0 = Release.DLL|x64
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release.DLL|x86.Build.0 = Release.DLL|Win32
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release|ARM64.ActiveCfg = Release|ARM64
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release|ARM64.Build.0 = Release|ARM64
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release|x64.ActiveCfg = Release|x64
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release|x64.Build.0 = Release|x64
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release|x86.ActiveCfg = Release|Win32
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release|x86.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{6C82BAAE-BDDF-457D-8FA8-7E2490B07035} = {8716DC0F-4FDE-4F57-8E25-5F78DFB80FE1}
{278D8859-20B1-428F-8448-064F46E1F021} = {8716DC0F-4FDE-4F57-8E25-5F78DFB80FE1}
@@ -4421,8 +4759,20 @@ Global
{49C67F03-1A56-4F96-B278-39B66EC93678} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035}
{D496308F-3C3C-40B3-A3ED-EA327D244B3E} = {8D3C83B7-F1E0-4C2E-9E34-EE5F6AB2502A}
{3B27F358-2679-4F38-B297-17B536F580BB} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035}
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {E926C768-6307-4423-A1EC-57E95B1FAB29}
- EndGlobalSection
-EndGlobal
+ {718FCBD0-591D-448C-B7D5-9F1CA8544E7B} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035}
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035}
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E} = {278D8859-20B1-428F-8448-064F46E1F021}
+ {9DB1F875-6E65-4195-B23F-ED8095C0B99C} = {278D8859-20B1-428F-8448-064F46E1F021}
+ {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F} = {AF5BEC5C-1F2B-4DA8-B12D-D09FE569237C}
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671} = {278D8859-20B1-428F-8448-064F46E1F021}
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E} = {AF5BEC5C-1F2B-4DA8-B12D-D09FE569237C}
+ {9DB1F875-6E65-4195-B23F-ED8095C0B99C} = {5317807F-61D4-4E0F-B6DC-2D9F12621ED9}
+ {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035}
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671} = {278D8859-20B1-428F-8448-064F46E1F021}
+ {6B1A933E-71B8-4C1F-9E79-02D98830E671} = {278D8859-20B1-428F-8448-064F46E1F021}
+ {2CCCD9E4-9058-4291-BD89-39C979F0CA1E} = {278D8859-20B1-428F-8448-064F46E1F021}
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {E926C768-6307-4423-A1EC-57E95B1FAB29}
+ EndGlobalSection
+EndGlobal
diff --git a/src/Makefile b/src/Makefile
index f2bdd811e..e767d21d0 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -235,20 +235,22 @@ endif
# NOTE: By default use OpenGL 3.3 on desktop platforms
ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW)
GRAPHICS ?= GRAPHICS_API_OPENGL_33
- #GRAPHICS = GRAPHICS_API_OPENGL_11 # Uncomment to use OpenGL 1.1
- #GRAPHICS = GRAPHICS_API_OPENGL_21 # Uncomment to use OpenGL 2.1
- #GRAPHICS = GRAPHICS_API_OPENGL_43 # Uncomment to use OpenGL 4.3
- #GRAPHICS = GRAPHICS_API_OPENGL_ES2 # Uncomment to use OpenGL ES 2.0 (ANGLE)
+ #GRAPHICS = GRAPHICS_API_OPENGL_11_SOFTWARE # Uncomment to use software rendering
+ #GRAPHICS = GRAPHICS_API_OPENGL_11 # Uncomment to use OpenGL 1.1
+ #GRAPHICS = GRAPHICS_API_OPENGL_21 # Uncomment to use OpenGL 2.1
+ #GRAPHICS = GRAPHICS_API_OPENGL_43 # Uncomment to use OpenGL 4.3
+ #GRAPHICS = GRAPHICS_API_OPENGL_ES2 # Uncomment to use OpenGL ES 2.0 (ANGLE)
endif
ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_SDL)
GRAPHICS ?= GRAPHICS_API_OPENGL_33
endif
ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_RGFW)
GRAPHICS ?= GRAPHICS_API_OPENGL_33
- #GRAPHICS = GRAPHICS_API_OPENGL_11 # Uncomment to use OpenGL 1.1
- #GRAPHICS = GRAPHICS_API_OPENGL_21 # Uncomment to use OpenGL 2.1
- #GRAPHICS = GRAPHICS_API_OPENGL_43 # Uncomment to use OpenGL 4.3
- #GRAPHICS = GRAPHICS_API_OPENGL_ES2 # Uncomment to use OpenGL ES 2.0 (ANGLE)
+ #GRAPHICS = GRAPHICS_API_OPENGL_11_SOFTWARE # Uncomment to use software rendering
+ #GRAPHICS = GRAPHICS_API_OPENGL_11 # Uncomment to use OpenGL 1.1
+ #GRAPHICS = GRAPHICS_API_OPENGL_21 # Uncomment to use OpenGL 2.1
+ #GRAPHICS = GRAPHICS_API_OPENGL_43 # Uncomment to use OpenGL 4.3
+ #GRAPHICS = GRAPHICS_API_OPENGL_ES2 # Uncomment to use OpenGL ES 2.0 (ANGLE)
endif
ifeq ($(TARGET_PLATFORM),PLATFORM_DRM)
# On DRM OpenGL ES 2.0 must be used
diff --git a/src/external/miniaudio.h b/src/external/miniaudio.h
index c74bebeb3..b7e7a54dd 100644
--- a/src/external/miniaudio.h
+++ b/src/external/miniaudio.h
@@ -1,6 +1,6 @@
/*
Audio playback and capture library. Choice of public domain or MIT-0. See license statements at the end of this file.
-miniaudio - v0.11.22 - 2025-02-24
+miniaudio - v0.11.23 - 2025-09-11
David Reid - mackron@gmail.com
@@ -12,18 +12,10 @@ GitHub: https://github.com/mackron/miniaudio
/*
1. Introduction
===============
-To use miniaudio, include "miniaudio.h":
-
- ```c
- #include "miniaudio.h"
- ```
-
-The implementation is contained in "miniaudio.c". Just compile this like any other source file. You
-can include miniaudio.c if you want to compile your project as a single translation unit:
-
- ```c
- #include "miniaudio.c"
- ```
+To use miniaudio, just include "miniaudio.h" like any other header and add "miniaudio.c" to your
+source tree. If you don't want to add it to your source tree you can compile and link to it like
+any other library. Note that ABI compatibility is not guaranteed between versions, even with bug
+fix releases, so take care if compiling as a shared object.
miniaudio includes both low level and high level APIs. The low level API is good for those who want
to do all of their mixing themselves and only require a light weight interface to the underlying
@@ -303,7 +295,7 @@ The engine encapsulates both the resource manager and the node graph to create a
use high level API. The resource manager and node graph APIs are covered in more later sections of
this manual.
-The code below shows how you can initialize an engine using it's default configuration.
+The code below shows how you can initialize an engine using its default configuration.
```c
ma_result result;
@@ -391,7 +383,7 @@ Sounds are not started by default. Start a sound with `ma_sound_start()` and sto
`ma_sound_stop()`. When a sound is stopped, it is not rewound to the start. Use
`ma_sound_seek_to_pcm_frame(&sound, 0)` to seek back to the start of a sound. By default, starting
and stopping sounds happens immediately, but sometimes it might be convenient to schedule the sound
-the be started and/or stopped at a specific time. This can be done with the following functions:
+to be started and/or stopped at a specific time. This can be done with the following functions:
```c
ma_sound_set_start_time_in_pcm_frames()
@@ -463,6 +455,11 @@ is at the end, use `ma_sound_at_end()`. Looping of a sound can be controlled wit
miniaudio should work cleanly out of the box without the need to download or install any
dependencies. See below for platform-specific details.
+This library has been designed to be added directly to your source tree which is the preferred way
+of using it, but you can compile it as a normal library if that's your preference. Be careful if
+compiling as a shared object because miniaudio is not ABI compatible between any release, including
+bug fix releases. It's recommended you link statically.
+
Note that GCC and Clang require `-msse2`, `-mavx2`, etc. for SIMD optimizations.
If you get errors about undefined references to `__sync_val_compare_and_swap_8`, `__atomic_load_8`,
@@ -532,7 +529,7 @@ you'll need to disable run-time linking with `MA_NO_RUNTIME_LINKING` and link wi
The Emscripten build emits Web Audio JavaScript directly and should compile cleanly out of the box.
You cannot use `-std=c*` compiler flags, nor `-ansi`.
-You can enable the use of AudioWorkets by defining `MA_ENABLE_AUDIO_WORKLETS` and then compiling
+You can enable the use of AudioWorklets by defining `MA_ENABLE_AUDIO_WORKLETS` and then compiling
with the following options:
-sAUDIO_WORKLET=1 -sWASM_WORKERS=1 -sASYNCIFY
@@ -881,7 +878,7 @@ read data within a certain range of the underlying data. To do this you can use
This is useful if you have a sound bank where many sounds are stored in the same file and you want
the data source to only play one of those sub-sounds. Note that once the range is set, everything
-that takes a position, such as cursors and loop points, should always be relatvie to the start of
+that takes a position, such as cursors and loop points, should always be relative to the start of
the range. When the range is set, any previously defined loop point will be reset.
Custom loop points can also be used with data sources. By default, data sources will loop after
@@ -889,7 +886,7 @@ they reach the end of the data source, but if you need to loop at a specific loc
the following:
```c
- result = ma_data_set_loop_point_in_pcm_frames(pDataSource, loopBegInFrames, loopEndInFrames);
+ result = ma_data_source_set_loop_point_in_pcm_frames(pDataSource, loopBegInFrames, loopEndInFrames);
if (result != MA_SUCCESS) {
return result; // Failed to set the loop point.
}
@@ -3750,7 +3747,7 @@ extern "C" {
#define MA_VERSION_MAJOR 0
#define MA_VERSION_MINOR 11
-#define MA_VERSION_REVISION 22
+#define MA_VERSION_REVISION 23
#define MA_VERSION_STRING MA_XSTRINGIFY(MA_VERSION_MAJOR) "." MA_XSTRINGIFY(MA_VERSION_MINOR) "." MA_XSTRINGIFY(MA_VERSION_REVISION)
#if defined(_MSC_VER) && !defined(__clang__)
@@ -3857,6 +3854,8 @@ typedef ma_uint16 wchar_t;
#define MA_SIZE_MAX 0xFFFFFFFF /* When SIZE_MAX is not defined by the standard library just default to the maximum 32-bit unsigned integer. */
#endif
+#define MA_UINT64_MAX (((ma_uint64)0xFFFFFFFF << 32) | (ma_uint64)0xFFFFFFFF) /* Weird shifting syntax is for VC6 compatibility. */
+
/* Platform/backend detection. */
#if defined(_WIN32) || defined(__COSMOPOLITAN__)
@@ -3865,29 +3864,55 @@ typedef ma_uint16 wchar_t;
#define MA_WIN32_UWP
#elif defined(WINAPI_FAMILY) && (defined(WINAPI_FAMILY_GAMES) && WINAPI_FAMILY == WINAPI_FAMILY_GAMES)
#define MA_WIN32_GDK
+ #elif defined(NXDK)
+ #define MA_WIN32_NXDK
#else
#define MA_WIN32_DESKTOP
#endif
+
+ /* The original Xbox. */
+ #if defined(NXDK) /* <-- Add other Xbox compiler toolchains here, and then add a toolchain-specific define in case we need to discriminate between them later. */
+ #define MA_XBOX
+
+ #if defined(NXDK)
+ #define MA_XBOX_NXDK
+ #endif
+ #endif
#endif
-#if !defined(_WIN32) /* If it's not Win32, assume POSIX. */
+#if defined(__MSDOS__) || defined(MSDOS) || defined(_MSDOS) || defined(__DOS__)
+ #define MA_DOS
+
+ /* No threading allowed on DOS. */
+ #ifndef MA_NO_THREADING
+ #define MA_NO_THREADING
+ #endif
+
+ /* No runtime linking allowed on DOS. */
+ #ifndef MA_NO_RUNTIME_LINKING
+ #define MA_NO_RUNTIME_LINKING
+ #endif
+#endif
+#if !defined(MA_WIN32) && !defined(MA_DOS) /* If it's not Win32, assume POSIX. */
#define MA_POSIX
- /*
- Use the MA_NO_PTHREAD_IN_HEADER option at your own risk. This is intentionally undocumented.
- You can use this to avoid including pthread.h in the header section. The downside is that it
- results in some fixed sized structures being declared for the various types that are used in
- miniaudio. The risk here is that these types might be too small for a given platform. This
- risk is yours to take and no support will be offered if you enable this option.
- */
- #ifndef MA_NO_PTHREAD_IN_HEADER
- #include /* Unfortunate #include, but needed for pthread_t, pthread_mutex_t and pthread_cond_t types. */
- typedef pthread_t ma_pthread_t;
- typedef pthread_mutex_t ma_pthread_mutex_t;
- typedef pthread_cond_t ma_pthread_cond_t;
- #else
- typedef ma_uintptr ma_pthread_t;
- typedef union ma_pthread_mutex_t { char __data[40]; ma_uint64 __alignment; } ma_pthread_mutex_t;
- typedef union ma_pthread_cond_t { char __data[48]; ma_uint64 __alignment; } ma_pthread_cond_t;
+ #if !defined(MA_NO_THREADING)
+ /*
+ Use the MA_NO_PTHREAD_IN_HEADER option at your own risk. This is intentionally undocumented.
+ You can use this to avoid including pthread.h in the header section. The downside is that it
+ results in some fixed sized structures being declared for the various types that are used in
+ miniaudio. The risk here is that these types might be too small for a given platform. This
+ risk is yours to take and no support will be offered if you enable this option.
+ */
+ #ifndef MA_NO_PTHREAD_IN_HEADER
+ #include /* Unfortunate #include, but needed for pthread_t, pthread_mutex_t and pthread_cond_t types. */
+ typedef pthread_t ma_pthread_t;
+ typedef pthread_mutex_t ma_pthread_mutex_t;
+ typedef pthread_cond_t ma_pthread_cond_t;
+ #else
+ typedef ma_uintptr ma_pthread_t;
+ typedef union ma_pthread_mutex_t { char __data[40]; ma_uint64 __alignment; } ma_pthread_mutex_t;
+ typedef union ma_pthread_cond_t { char __data[48]; ma_uint64 __alignment; } ma_pthread_cond_t;
+ #endif
#endif
#if defined(__unix__)
@@ -3914,8 +3939,11 @@ typedef ma_uint16 wchar_t;
#if defined(__PROSPERO__)
#define MA_PROSPERO
#endif
- #if defined(__NX__)
- #define MA_NX
+ #if defined(__3DS__)
+ #define MA_3DS
+ #endif
+ #if defined(__SWITCH__) || defined(__NX__)
+ #define MA_SWITCH
#endif
#if defined(__BEOS__) || defined(__HAIKU__)
#define MA_BEOS
@@ -3925,12 +3953,13 @@ typedef ma_uint16 wchar_t;
#endif
#endif
-#if defined(__has_c_attribute)
- #if __has_c_attribute(fallthrough)
- #define MA_FALLTHROUGH [[fallthrough]]
- #endif
+#if !defined(MA_FALLTHROUGH) && defined(__cplusplus) && __cplusplus >= 201703L
+ #define MA_FALLTHROUGH [[fallthrough]]
#endif
-#if !defined(MA_FALLTHROUGH) && defined(__has_attribute) && (defined(__clang__) || defined(__GNUC__))
+#if !defined(MA_FALLTHROUGH) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202000L
+ #define MA_FALLTHROUGH [[fallthrough]]
+#endif
+#if !defined(MA_FALLTHROUGH) && defined(__has_attribute)
#if __has_attribute(fallthrough)
#define MA_FALLTHROUGH __attribute__((fallthrough))
#endif
@@ -3967,7 +3996,7 @@ typedef ma_uint16 wchar_t;
#define MA_NO_INLINE __attribute__((noinline))
#else
#define MA_INLINE MA_GNUC_INLINE_HINT
- #define MA_NO_INLINE __attribute__((noinline))
+ #define MA_NO_INLINE
#endif
#elif defined(__WATCOMC__)
#define MA_INLINE __inline
@@ -4350,7 +4379,7 @@ typedef struct
typedef struct
{
- ma_int32 state;
+ ma_uint32 state;
} ma_lcg;
@@ -6569,7 +6598,7 @@ This section contains the APIs for device playback and capture. Here is where yo
************************************************************************************************************************************************************/
#ifndef MA_NO_DEVICE_IO
/* Some backends are only supported on certain platforms. */
-#if defined(MA_WIN32)
+#if defined(MA_WIN32) && !defined(MA_XBOX)
#define MA_SUPPORT_WASAPI
#if defined(MA_WIN32_DESKTOP) /* DirectSound and WinMM backends are only supported on desktops. */
@@ -7426,6 +7455,7 @@ struct ma_context
ma_proc snd_pcm_hw_params_set_rate_resample;
ma_proc snd_pcm_hw_params_set_rate;
ma_proc snd_pcm_hw_params_set_rate_near;
+ ma_proc snd_pcm_hw_params_set_rate_minmax;
ma_proc snd_pcm_hw_params_set_buffer_size_near;
ma_proc snd_pcm_hw_params_set_periods_near;
ma_proc snd_pcm_hw_params_set_access;
@@ -7986,6 +8016,7 @@ struct ma_device
/*AAudioStream**/ ma_ptr pStreamPlayback;
/*AAudioStream**/ ma_ptr pStreamCapture;
ma_mutex rerouteLock;
+ ma_atomic_bool32 isTearingDown;
ma_aaudio_usage usage;
ma_aaudio_content_type contentType;
ma_aaudio_input_preset inputPreset;
@@ -11255,7 +11286,7 @@ typedef struct
ma_log* pLog; /* When set to NULL, will use the context's log. */
ma_uint32 listenerCount; /* Must be between 1 and MA_ENGINE_MAX_LISTENERS. */
ma_uint32 channels; /* The number of channels to use when mixing and spatializing. When set to 0, will use the native channel count of the device. */
- ma_uint32 sampleRate; /* The sample rate. When set to 0 will use the native channel count of the device. */
+ ma_uint32 sampleRate; /* The sample rate. When set to 0 will use the native sample rate of the device. */
ma_uint32 periodSizeInFrames; /* If set to something other than 0, updates will always be exactly this size. The underlying device may be a different size, but from the perspective of the mixer that won't matter.*/
ma_uint32 periodSizeInMilliseconds; /* Used if periodSizeInFrames is unset. */
ma_uint32 gainSmoothTimeInFrames; /* The number of frames to interpolate the gain of spatialized sounds across. If set to 0, will use gainSmoothTimeInMilliseconds. */
@@ -11419,11 +11450,11 @@ MA_API ma_bool32 ma_sound_is_looping(const ma_sound* pSound);
MA_API ma_bool32 ma_sound_at_end(const ma_sound* pSound);
MA_API ma_result ma_sound_seek_to_pcm_frame(ma_sound* pSound, ma_uint64 frameIndex); /* Just a wrapper around ma_data_source_seek_to_pcm_frame(). */
MA_API ma_result ma_sound_seek_to_second(ma_sound* pSound, float seekPointInSeconds); /* Abstraction to ma_sound_seek_to_pcm_frame() */
-MA_API ma_result ma_sound_get_data_format(ma_sound* pSound, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate, ma_channel* pChannelMap, size_t channelMapCap);
-MA_API ma_result ma_sound_get_cursor_in_pcm_frames(ma_sound* pSound, ma_uint64* pCursor);
-MA_API ma_result ma_sound_get_length_in_pcm_frames(ma_sound* pSound, ma_uint64* pLength);
-MA_API ma_result ma_sound_get_cursor_in_seconds(ma_sound* pSound, float* pCursor);
-MA_API ma_result ma_sound_get_length_in_seconds(ma_sound* pSound, float* pLength);
+MA_API ma_result ma_sound_get_data_format(const ma_sound* pSound, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate, ma_channel* pChannelMap, size_t channelMapCap);
+MA_API ma_result ma_sound_get_cursor_in_pcm_frames(const ma_sound* pSound, ma_uint64* pCursor);
+MA_API ma_result ma_sound_get_length_in_pcm_frames(const ma_sound* pSound, ma_uint64* pLength);
+MA_API ma_result ma_sound_get_cursor_in_seconds(const ma_sound* pSound, float* pCursor);
+MA_API ma_result ma_sound_get_length_in_seconds(const ma_sound* pSound, float* pLength);
MA_API ma_result ma_sound_set_end_callback(ma_sound* pSound, ma_sound_end_proc callback, void* pUserData);
MA_API ma_result ma_sound_group_init(ma_engine* pEngine, ma_uint32 flags, ma_sound_group* pParentGroup, ma_sound_group* pGroup);
@@ -11544,17 +11575,23 @@ IMPLEMENTATION
#endif
#if !defined(MA_WIN32)
-#include
-#include /* select() (used for ma_sleep()). */
-#include
+ #if !defined(MA_NO_THREADING)
+ #include
+ #include /* For pthreads. */
+ #endif
+
+ #include /* select() (used for ma_sleep()). */
+ #include /* For nanosleep() */
+ #include
#endif
-#ifdef MA_NX
-#include /* For nanosleep() */
+/* For fstat(), etc. */
+#if defined(MA_XBOX_NXDK)
+ #include /* Suggestion for NXDK: Add a sys/stat.h wrapper for compatibility. */
+#else
+ #include
#endif
-#include /* For fstat(), etc. */
-
#ifdef MA_EMSCRIPTEN
#include
#endif
@@ -11861,7 +11898,7 @@ static MA_INLINE ma_bool32 ma_has_neon(void)
#endif
#ifndef MA_RESTRICT
- #if defined(__clang__) || defined(__GNUC__) || defined(_MSC_VER)
+ #if defined(__clang__) || defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)))
#define MA_RESTRICT __restrict
#else
#define MA_RESTRICT
@@ -11955,7 +11992,7 @@ static void ma_sleep__posix(ma_uint32 milliseconds)
(void)milliseconds;
MA_ASSERT(MA_FALSE); /* The Emscripten build should never sleep. */
#else
- #if (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309L) || defined(MA_NX)
+ #if (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309L) || defined(MA_SWITCH)
struct timespec ts;
ts.tv_sec = milliseconds / 1000;
ts.tv_nsec = milliseconds % 1000 * 1000000;
@@ -11997,7 +12034,7 @@ static MA_INLINE void ma_yield(void)
#endif
#endif
#else
- __asm__ __volatile__ ("pause");
+ __asm__ __volatile__ ("rep; nop");
#endif
#elif (defined(__arm__) && defined(__ARM_ARCH) && __ARM_ARCH >= 7) || defined(_M_ARM64) || (defined(_M_ARM) && _M_ARM >= 7) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__)
/* ARM */
@@ -12020,7 +12057,7 @@ static MA_INLINE unsigned int ma_disable_denormals(void)
{
unsigned int prevState;
- #if defined(_MSC_VER)
+ #if defined(_MSC_VER) && !defined(MA_XBOX_NXDK)
{
/*
Older versions of Visual Studio don't support the "safe" versions of _controlfp_s(). I don't
@@ -12043,7 +12080,7 @@ static MA_INLINE unsigned int ma_disable_denormals(void)
}
#elif defined(MA_X86) || defined(MA_X64)
{
- #if defined(__SSE2__) && !(defined(__TINYC__) || defined(__WATCOMC__) || defined(__COSMOPOLITAN__)) /* <-- Add compilers that lack support for _mm_getcsr() and _mm_setcsr() to this list. */
+ #if defined(MA_SUPPORT_SSE2) && defined(__SSE2__) && !(defined(__TINYC__) || defined(__WATCOMC__) || defined(__COSMOPOLITAN__)) /* <-- Add compilers that lack support for _mm_getcsr() and _mm_setcsr() to this list. */
{
prevState = _mm_getcsr();
_mm_setcsr(prevState | MA_MM_DENORMALS_ZERO_MASK | MA_MM_FLUSH_ZERO_MASK);
@@ -12067,7 +12104,7 @@ static MA_INLINE unsigned int ma_disable_denormals(void)
static MA_INLINE void ma_restore_denormals(unsigned int prevState)
{
- #if defined(_MSC_VER)
+ #if defined(_MSC_VER) && !defined(MA_XBOX_NXDK)
{
/* Older versions of Visual Studio do not support _controlfp_s(). See ma_disable_denormals(). */
#if _MSC_VER <= 1200
@@ -12083,7 +12120,7 @@ static MA_INLINE void ma_restore_denormals(unsigned int prevState)
}
#elif defined(MA_X86) || defined(MA_X64)
{
- #if defined(__SSE2__) && !(defined(__TINYC__) || defined(__WATCOMC__) || defined(__COSMOPOLITAN__)) /* <-- Add compilers that lack support for _mm_getcsr() and _mm_setcsr() to this list. */
+ #if defined(MA_SUPPORT_SSE2) && defined(__SSE2__) && !(defined(__TINYC__) || defined(__WATCOMC__) || defined(__COSMOPOLITAN__)) /* <-- Add compilers that lack support for _mm_getcsr() and _mm_setcsr() to this list. */
{
_mm_setcsr(prevState);
}
@@ -12719,6 +12756,29 @@ MA_API MA_NO_INLINE int ma_strcmp(const char* str1, const char* str2)
return ((unsigned char*)str1)[0] - ((unsigned char*)str2)[0];
}
+MA_API MA_NO_INLINE int ma_wcscmp(const wchar_t* str1, const wchar_t* str2)
+{
+ if (str1 == str2) return 0;
+
+ /* These checks differ from the standard implementation. It's not important, but I prefer it just for sanity. */
+ if (str1 == NULL) return -1;
+ if (str2 == NULL) return 1;
+
+ for (;;) {
+ if (str1[0] == L'\0') {
+ break;
+ }
+ if (str1[0] != str2[0]) {
+ break;
+ }
+
+ str1 += 1;
+ str2 += 1;
+ }
+
+ return ((unsigned short*)str1)[0] - ((unsigned short*)str2)[0];
+}
+
MA_API MA_NO_INLINE int ma_strappend(char* dst, size_t dstSize, const char* srcA, const char* srcB)
{
int result;
@@ -12736,6 +12796,22 @@ MA_API MA_NO_INLINE int ma_strappend(char* dst, size_t dstSize, const char* srcA
return result;
}
+MA_API MA_NO_INLINE size_t ma_wcslen(const wchar_t* str)
+{
+ const wchar_t* end;
+
+ if (str == NULL) {
+ return 0;
+ }
+
+ end = str;
+ while (end[0] != '\0') {
+ end += 1;
+ }
+
+ return end - str;
+}
+
MA_API MA_NO_INLINE char* ma_copy_string(const char* src, const ma_allocation_callbacks* pAllocationCallbacks)
{
size_t sz;
@@ -12758,7 +12834,7 @@ MA_API MA_NO_INLINE char* ma_copy_string(const char* src, const ma_allocation_ca
MA_API MA_NO_INLINE wchar_t* ma_copy_string_w(const wchar_t* src, const ma_allocation_callbacks* pAllocationCallbacks)
{
- size_t sz = wcslen(src)+1;
+ size_t sz = ma_wcslen(src)+1;
wchar_t* dst = (wchar_t*)ma_malloc(sz * sizeof(*dst), pAllocationCallbacks);
if (dst == NULL) {
return NULL;
@@ -13189,7 +13265,7 @@ MA_API ma_result ma_fopen(FILE** ppFile, const char* pFilePath, const char* pOpe
return MA_INVALID_ARGS;
}
-#if defined(_MSC_VER) && _MSC_VER >= 1400
+#if (defined(_MSC_VER) && _MSC_VER >= 1400) && !defined(MA_XBOX_NXDK)
err = fopen_s(ppFile, pFilePath, pOpenMode);
if (err != 0) {
return ma_result_from_errno(err);
@@ -13231,7 +13307,7 @@ _wfopen() isn't always available in all compilation environments.
This can be reviewed as compatibility issues arise. The preference is to use _wfopen_s() and _wfopen() as opposed to the wcsrtombs()
fallback, so if you notice your compiler not detecting this properly I'm happy to look at adding support.
*/
-#if defined(_WIN32)
+#if defined(_WIN32) && !defined(MA_XBOX_NXDK)
#if defined(_MSC_VER) || defined(__MINGW64__) || (!defined(__STRICT_ANSI__) && !defined(_NO_EXT_KEYS))
#define MA_HAS_WFOPEN
#endif
@@ -13247,29 +13323,34 @@ MA_API ma_result ma_wfopen(FILE** ppFile, const wchar_t* pFilePath, const wchar_
return MA_INVALID_ARGS;
}
-#if defined(MA_HAS_WFOPEN)
+ #if defined(MA_HAS_WFOPEN)
{
/* Use _wfopen() on Windows. */
- #if defined(_MSC_VER) && _MSC_VER >= 1400
- errno_t err = _wfopen_s(ppFile, pFilePath, pOpenMode);
- if (err != 0) {
- return ma_result_from_errno(err);
+ #if defined(_MSC_VER) && _MSC_VER >= 1400
+ {
+ errno_t err = _wfopen_s(ppFile, pFilePath, pOpenMode);
+ if (err != 0) {
+ return ma_result_from_errno(err);
+ }
}
- #else
- *ppFile = _wfopen(pFilePath, pOpenMode);
- if (*ppFile == NULL) {
- return ma_result_from_errno(errno);
+ #else
+ {
+ *ppFile = _wfopen(pFilePath, pOpenMode);
+ if (*ppFile == NULL) {
+ return ma_result_from_errno(errno);
+ }
}
- #endif
+ #endif
+
(void)pAllocationCallbacks;
}
-#else
- /*
- Use fopen() on anything other than Windows. Requires a conversion. This is annoying because fopen() is locale specific. The only real way I can
- think of to do this is with wcsrtombs(). Note that wcstombs() is apparently not thread-safe because it uses a static global mbstate_t object for
- maintaining state. I've checked this with -std=c89 and it works, but if somebody get's a compiler error I'll look into improving compatibility.
- */
+ #elif !defined(MA_XBOX_NXDK) && !defined(MA_DOS) /* If your compiler does not support wcsrtombs(), add it here. */
{
+ /*
+ Use fopen() on anything other than Windows. Requires a conversion. This is annoying because fopen() is locale specific. The only real way I can
+ think of to do this is with wcsrtombs(). Note that wcstombs() is apparently not thread-safe because it uses a static global mbstate_t object for
+ maintaining state. I've checked this with -std=c89 and it works, but if somebody get's a compiler error I'll look into improving compatibility.
+ */
mbstate_t mbs;
size_t lenMB;
const wchar_t* pFilePathTemp = pFilePath;
@@ -13310,11 +13391,16 @@ MA_API ma_result ma_wfopen(FILE** ppFile, const wchar_t* pFilePath, const wchar_
ma_free(pFilePathMB, pAllocationCallbacks);
}
+ #else
+ {
+ /* Getting here means there is no way to open the file with a wide character string. */
+ *ppFile = NULL;
+ }
+ #endif
if (*ppFile == NULL) {
return MA_ERROR;
}
-#endif
return MA_SUCCESS;
}
@@ -13323,7 +13409,7 @@ MA_API ma_result ma_wfopen(FILE** ppFile, const wchar_t* pFilePath, const wchar_
static MA_INLINE void ma_copy_memory_64(void* dst, const void* src, ma_uint64 sizeInBytes)
{
-#if 0xFFFFFFFFFFFFFFFF <= MA_SIZE_MAX
+#if MA_SIZE_MAX > 0xFFFFFFFF
MA_COPY_MEMORY(dst, src, (size_t)sizeInBytes);
#else
while (sizeInBytes > 0) {
@@ -13343,7 +13429,7 @@ static MA_INLINE void ma_copy_memory_64(void* dst, const void* src, ma_uint64 si
static MA_INLINE void ma_zero_memory_64(void* dst, ma_uint64 sizeInBytes)
{
-#if 0xFFFFFFFFFFFFFFFF <= MA_SIZE_MAX
+#if MA_SIZE_MAX > 0xFFFFFFFF
MA_ZERO_MEMORY(dst, (size_t)sizeInBytes);
#else
while (sizeInBytes > 0) {
@@ -13472,6 +13558,18 @@ static ma_result ma_allocation_callbacks_init_copy(ma_allocation_callbacks* pDst
Logging
**************************************************************************************************************************************************************/
+#ifndef ma_va_copy
+ #if !defined(_MSC_VER) || _MSC_VER >= 1800
+ #if (defined(__GNUC__) && __GNUC__ < 3)
+ #define ma_va_copy(dst, src) ((dst) = (src)) /* This is untested. Not sure if this is correct for old GCC. */
+ #else
+ #define ma_va_copy(dst, src) va_copy((dst), (src))
+ #endif
+ #else
+ #define ma_va_copy(dst, src) ((dst) = (src))
+ #endif
+#endif
+
MA_API const char* ma_log_level_to_string(ma_uint32 logLevel)
{
switch (logLevel)
@@ -13712,9 +13810,15 @@ MA_API ma_result ma_log_postv(ma_log* pLog, ma_uint32 level, const char* pFormat
int length;
char pFormattedMessageStack[1024];
char* pFormattedMessageHeap = NULL;
+ va_list args2;
/* First try formatting into our fixed sized stack allocated buffer. If this is too small we'll fallback to a heap allocation. */
- length = vsnprintf(pFormattedMessageStack, sizeof(pFormattedMessageStack), pFormat, args);
+ ma_va_copy(args2, args);
+ {
+ length = vsnprintf(pFormattedMessageStack, sizeof(pFormattedMessageStack), pFormat, args2);
+ }
+ va_end(args2);
+
if (length < 0) {
return MA_INVALID_OPERATION; /* An error occurred when trying to convert the buffer. */
}
@@ -13755,17 +13859,10 @@ MA_API ma_result ma_log_postv(ma_log* pLog, ma_uint32 level, const char* pFormat
char* pFormattedMessage = NULL;
va_list args2;
- #if _MSC_VER >= 1800
+ ma_va_copy(args2, args);
{
- va_copy(args2, args);
+ formattedLen = ma_vscprintf(&pLog->allocationCallbacks, pFormat, args2);
}
- #else
- {
- args2 = args;
- }
- #endif
-
- formattedLen = ma_vscprintf(&pLog->allocationCallbacks, pFormat, args2);
va_end(args2);
if (formattedLen <= 0) {
@@ -13964,7 +14061,7 @@ miniaudio's purposes.
#define MA_LCG_A 48271
#define MA_LCG_C 0
-static ma_lcg g_maLCG = {MA_DEFAULT_LCG_SEED}; /* Non-zero initial seed. Use ma_seed() to use an explicit seed. */
+static ma_lcg g_maLCG = {MA_DEFAULT_LCG_SEED}; /* Non-zero initial seed. Use ma_lcg_seed() to use an explicit seed. */
static MA_INLINE void ma_lcg_seed(ma_lcg* pLCG, ma_int32 seed)
{
@@ -14013,7 +14110,7 @@ static MA_INLINE ma_int32 ma_lcg_rand_range_s32(ma_lcg* pLCG, ma_int32 lo, ma_in
}
-
+#if 0 /* Currently unused. */
static MA_INLINE void ma_seed(ma_int32 seed)
{
ma_lcg_seed(&g_maLCG, seed);
@@ -14038,6 +14135,7 @@ static MA_INLINE float ma_rand_f32(void)
{
return ma_lcg_rand_f32(&g_maLCG);
}
+#endif
static MA_INLINE float ma_rand_range_f32(float lo, float hi)
{
@@ -14097,6 +14195,7 @@ Atomics
**************************************************************************************************************************************************************/
/* c89atomic.h begin */
#ifndef ma_atomic_h
+#define ma_atomic_h
#if defined(__cplusplus)
extern "C" {
#endif
@@ -14108,11 +14207,40 @@ extern "C" {
#endif
#endif
typedef int ma_atomic_memory_order;
-#define MA_ATOMIC_HAS_8
-#define MA_ATOMIC_HAS_16
-#define MA_ATOMIC_HAS_32
-#define MA_ATOMIC_HAS_64
-#if (defined(_MSC_VER) ) || defined(__WATCOMC__) || defined(__DMC__)
+#if !defined(MA_ATOMIC_MODERN_MSVC) && \
+ !defined(MA_ATOMIC_LEGACY_MSVC) && \
+ !defined(MA_ATOMIC_LEGACY_MSVC_ASM) && \
+ !defined(MA_ATOMIC_MODERN_GCC) && \
+ !defined(MA_ATOMIC_LEGACY_GCC) && \
+ !defined(MA_ATOMIC_LEGACY_GCC_ASM)
+ #if defined(_MSC_VER) || defined(__WATCOMC__) || defined(__DMC__) || defined(__BORLANDC__)
+ #if (defined(_MSC_VER) && _MSC_VER > 1600)
+ #define MA_ATOMIC_MODERN_MSVC
+ #else
+ #if defined(MA_X64)
+ #define MA_ATOMIC_LEGACY_MSVC
+ #else
+ #define MA_ATOMIC_LEGACY_MSVC_ASM
+ #endif
+ #endif
+ #elif (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7))) || defined(__clang__)
+ #define MA_ATOMIC_MODERN_GCC
+ #else
+ #if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1))
+ #define MA_ATOMIC_LEGACY_GCC
+ #else
+ #define MA_ATOMIC_LEGACY_GCC_ASM
+ #endif
+ #endif
+#endif
+#if defined(MA_ATOMIC_MODERN_MSVC) || defined(MA_ATOMIC_LEGACY_MSVC)
+ #include
+ #define ma_atomic_memory_order_relaxed 1
+ #define ma_atomic_memory_order_consume 2
+ #define ma_atomic_memory_order_acquire 3
+ #define ma_atomic_memory_order_release 4
+ #define ma_atomic_memory_order_acq_rel 5
+ #define ma_atomic_memory_order_seq_cst 6
#define MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, intrin, ma_atomicType, msvcType) \
ma_atomicType result; \
switch (order) \
@@ -14138,720 +14266,1501 @@ typedef int ma_atomic_memory_order;
} break; \
} \
return result;
- #define MA_ATOMIC_MSVC_ARM_INTRINSIC_COMPARE_EXCHANGE(ptr, expected, desired, order, intrin, ma_atomicType, msvcType) \
+ typedef ma_uint32 ma_atomic_flag;
+ static MA_INLINE ma_atomic_flag ma_atomic_flag_test_and_set_explicit(volatile ma_atomic_flag* dst, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ARM)
+ {
+ MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, 1, order, _InterlockedExchange, ma_atomic_flag, long);
+ }
+ #else
+ {
+ (void)order;
+ return (ma_atomic_flag)_InterlockedExchange((volatile long*)dst, (long)1);
+ }
+ #endif
+ }
+ static MA_INLINE void ma_atomic_flag_clear_explicit(volatile ma_atomic_flag* dst, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ARM)
+ {
+ MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, 0, order, _InterlockedExchange, ma_atomic_flag, long);
+ }
+ #else
+ {
+ (void)order;
+ _InterlockedExchange((volatile long*)dst, (long)0);
+ }
+ #endif
+ }
+ static MA_INLINE ma_atomic_flag ma_atomic_flag_load_explicit(volatile const ma_atomic_flag* dst, ma_atomic_memory_order order)
+ {
+ (void)order;
+ return (ma_uint32)_InterlockedCompareExchange((volatile long*)dst, 0, 0);
+ }
+#endif
+#if defined(MA_ATOMIC_LEGACY_MSVC_ASM)
+ #define ma_atomic_memory_order_relaxed 1
+ #define ma_atomic_memory_order_consume 2
+ #define ma_atomic_memory_order_acquire 3
+ #define ma_atomic_memory_order_release 4
+ #define ma_atomic_memory_order_acq_rel 5
+ #define ma_atomic_memory_order_seq_cst 6
+ typedef ma_uint32 ma_atomic_flag;
+ static MA_INLINE ma_atomic_flag ma_atomic_flag_test_and_set_explicit(volatile ma_atomic_flag* dst, ma_atomic_memory_order order)
+ {
+ ma_atomic_flag result = 0;
+ (void)order;
+ __asm {
+ mov ecx, dst
+ mov eax, 1
+ xchg [ecx], eax
+ mov result, eax
+ }
+ return result;
+ }
+ static MA_INLINE void ma_atomic_flag_clear_explicit(volatile ma_atomic_flag* dst, ma_atomic_memory_order order)
+ {
+ if (order == ma_atomic_memory_order_relaxed) {
+ __asm {
+ mov esi, dst
+ mov dword ptr [esi], 0
+ }
+ } else {
+ __asm {
+ mov esi, dst
+ mov eax, 0
+ xchg [esi], eax
+ }
+ }
+ }
+ static MA_INLINE ma_atomic_flag ma_atomic_flag_load_explicit(volatile const ma_atomic_flag* dst, ma_atomic_memory_order order)
+ {
+ ma_atomic_flag result = 0;
+ if (order == ma_atomic_memory_order_relaxed) {
+ __asm {
+ mov esi, dst
+ mov eax, [esi]
+ mov result, eax
+ }
+ } else if (order <= ma_atomic_memory_order_release) {
+ __asm {
+ mov esi, dst
+ mov eax, [esi]
+ lock add dword ptr [esp], 0
+ mov result, eax
+ }
+ } else {
+ __asm {
+ lock add dword ptr [esp], 0
+ mov esi, dst
+ mov eax, [esi]
+ mov result, eax
+ lock add dword ptr [esp], 0
+ }
+ }
+ return result;
+ }
+#endif
+#if defined(MA_ATOMIC_MODERN_GCC)
+ #define ma_atomic_memory_order_relaxed __ATOMIC_RELAXED
+ #define ma_atomic_memory_order_consume __ATOMIC_CONSUME
+ #define ma_atomic_memory_order_acquire __ATOMIC_ACQUIRE
+ #define ma_atomic_memory_order_release __ATOMIC_RELEASE
+ #define ma_atomic_memory_order_acq_rel __ATOMIC_ACQ_REL
+ #define ma_atomic_memory_order_seq_cst __ATOMIC_SEQ_CST
+ typedef ma_uint32 ma_atomic_flag;
+ #define ma_atomic_flag_test_and_set_explicit(dst, order) __atomic_exchange_n(dst, 1, order)
+ #define ma_atomic_flag_clear_explicit(dst, order) __atomic_store_n(dst, 0, order)
+ #define ma_atomic_flag_load_explicit(dst, order) __atomic_load_n(dst, order)
+#endif
+#if defined(MA_ATOMIC_LEGACY_GCC)
+ #define ma_atomic_memory_order_relaxed 1
+ #define ma_atomic_memory_order_consume 2
+ #define ma_atomic_memory_order_acquire 3
+ #define ma_atomic_memory_order_release 4
+ #define ma_atomic_memory_order_acq_rel 5
+ #define ma_atomic_memory_order_seq_cst 6
+ typedef ma_uint32 ma_atomic_flag;
+ static MA_INLINE ma_atomic_flag ma_atomic_flag_test_and_set_explicit(volatile ma_atomic_flag* dst, ma_atomic_memory_order order)
+ {
+ if (order > ma_atomic_memory_order_acquire) {
+ __sync_synchronize();
+ }
+ return __sync_lock_test_and_set(dst, 1);
+ }
+ static MA_INLINE void ma_atomic_flag_clear_explicit(volatile ma_atomic_flag* dst, ma_atomic_memory_order order)
+ {
+ if (order > ma_atomic_memory_order_release) {
+ __sync_synchronize();
+ }
+ __sync_lock_release(dst);
+ }
+ static MA_INLINE ma_atomic_flag ma_atomic_flag_load_explicit(volatile const ma_atomic_flag* dst, ma_atomic_memory_order order)
+ {
+ (void)order;
+ return __sync_val_compare_and_swap((ma_atomic_flag*)dst, 0, 0);
+ }
+#endif
+#if defined(MA_ATOMIC_LEGACY_GCC_ASM)
+ #define ma_atomic_memory_order_relaxed 1
+ #define ma_atomic_memory_order_consume 2
+ #define ma_atomic_memory_order_acquire 3
+ #define ma_atomic_memory_order_release 4
+ #define ma_atomic_memory_order_acq_rel 5
+ #define ma_atomic_memory_order_seq_cst 6
+ #if defined(MA_X86)
+ #define ma_atomic_thread_fence(order) __asm__ __volatile__("lock; addl $0, (%%esp)" ::: "memory")
+ #elif defined(MA_X64)
+ #define ma_atomic_thread_fence(order) __asm__ __volatile__("lock; addq $0, (%%rsp)" ::: "memory")
+ #else
+ #error Unsupported architecture.
+ #endif
+ #define MA_ATOMIC_XCHG_GCC_X86(instructionSizeSuffix, result, dst, src) \
+ __asm__ __volatile__( \
+ "xchg"instructionSizeSuffix" %0, %1" \
+ : "=r"(result), \
+ "=m"(*dst) \
+ : "0"(src), \
+ "m"(*dst) \
+ : "memory" \
+ )
+ #define MA_ATOMIC_LOAD_RELAXED_GCC_X86(instructionSizeSuffix, result, dst) \
+ __asm__ __volatile__( \
+ "mov"instructionSizeSuffix" %1, %0" \
+ : "=r"(result) \
+ : "m"(*dst) \
+ )
+ #define MA_ATOMIC_LOAD_RELEASE_GCC_X86(instructionSizeSuffix, result, dst) \
+ ma_atomic_thread_fence(ma_atomic_memory_order_release); \
+ __asm__ __volatile__( \
+ "mov"instructionSizeSuffix" %1, %0" \
+ : "=r"(result) \
+ : "m"(*dst) \
+ : "memory" \
+ )
+ #define MA_ATOMIC_LOAD_SEQ_CST_GCC_X86(instructionSizeSuffix, result, dst) \
+ ma_atomic_thread_fence(ma_atomic_memory_order_seq_cst); \
+ __asm__ __volatile__( \
+ "mov"instructionSizeSuffix" %1, %0" \
+ : "=r"(result) \
+ : "m"(*dst) \
+ : "memory" \
+ ); \
+ ma_atomic_thread_fence(ma_atomic_memory_order_seq_cst)
+ typedef ma_uint32 ma_atomic_flag;
+ static MA_INLINE ma_atomic_flag ma_atomic_flag_test_and_set_explicit(volatile ma_atomic_flag* dst, ma_atomic_memory_order order)
+ {
+ ma_atomic_flag result;
+ #if defined(MA_X86) || defined(MA_X64)
+ {
+ (void)order;
+ MA_ATOMIC_XCHG_GCC_X86("l", result, dst, 1);
+ }
+ #else
+ {
+ #error Unsupported architecture.
+ }
+ #endif
+ return result;
+ }
+ static MA_INLINE void ma_atomic_flag_clear_explicit(volatile ma_atomic_flag* dst, ma_atomic_memory_order order)
+ {
+ #if defined(MA_X86) || defined(MA_X64)
+ {
+ if (order == ma_atomic_memory_order_relaxed) {
+ __asm__ __volatile__(
+ "movl $0, %0"
+ : "=m"(*dst)
+ );
+ } else if (order == ma_atomic_memory_order_release) {
+ __asm__ __volatile__(
+ "movl $0, %0"
+ : "=m"(*dst)
+ :
+ : "memory"
+ );
+ } else {
+ ma_atomic_flag tmp = 0;
+ __asm__ __volatile__(
+ "xchgl %0, %1"
+ : "=r"(tmp),
+ "=m"(*dst)
+ : "0"(tmp),
+ "m"(*dst)
+ : "memory"
+ );
+ }
+ }
+ #else
+ {
+ #error Unsupported architecture.
+ }
+ #endif
+ }
+ static MA_INLINE ma_atomic_flag ma_atomic_flag_load_explicit(volatile const ma_atomic_flag* dst, ma_atomic_memory_order order)
+ {
+ #if defined(MA_X86) || defined(MA_X64)
+ {
+ ma_atomic_flag result;
+ if (order == ma_atomic_memory_order_relaxed) {
+ MA_ATOMIC_LOAD_RELAXED_GCC_X86("l", result, dst);
+ } else if (order <= ma_atomic_memory_order_release) {
+ MA_ATOMIC_LOAD_RELEASE_GCC_X86("l", result, dst);
+ } else {
+ MA_ATOMIC_LOAD_SEQ_CST_GCC_X86("l", result, dst);
+ }
+ return result;
+ }
+ #else
+ {
+ #error Unsupported architecture.
+ }
+ #endif
+ }
+#endif
+#define ma_atomic_flag_test_and_set(dst) ma_atomic_flag_test_and_set_explicit(dst, ma_atomic_memory_order_acquire)
+#define ma_atomic_flag_clear(dst) ma_atomic_flag_clear_explicit(dst, ma_atomic_memory_order_release)
+typedef ma_atomic_flag ma_atomic_spinlock;
+static MA_INLINE void ma_atomic_spinlock_lock(volatile ma_atomic_spinlock* pSpinlock)
+{
+ for (;;) {
+ if (ma_atomic_flag_test_and_set_explicit(pSpinlock, ma_atomic_memory_order_acquire) == 0) {
+ break;
+ }
+ while (ma_atomic_flag_load_explicit(pSpinlock, ma_atomic_memory_order_relaxed) == 1) {
+ }
+ }
+}
+static MA_INLINE void ma_atomic_spinlock_unlock(volatile ma_atomic_spinlock* pSpinlock)
+{
+ ma_atomic_flag_clear_explicit(pSpinlock, ma_atomic_memory_order_release);
+}
+ma_atomic_spinlock ma_atomic_global_lock;
+#if defined(MA_ATOMIC_MODERN_MSVC) || defined(MA_ATOMIC_LEGACY_MSVC) || defined(MA_ATOMIC_LEGACY_MSVC_ASM) || defined(MA_ATOMIC_LEGACY_GCC) || defined(MA_ATOMIC_LEGACY_GCC_ASM)
+ #if defined(MA_X64) || (defined(MA_X86) && ((defined(__GNUC__) && defined(__i486__)) || (defined(_M_IX86) && _M_IX86 >= 400)))
+ #if defined(MA_ATOMIC_LEGACY_MSVC) && defined(MA_X64)
+ #else
+ #define MA_ATOMIC_IS_LOCK_FREE_8 1
+ #define MA_ATOMIC_IS_LOCK_FREE_16 1
+ #endif
+ #define MA_ATOMIC_IS_LOCK_FREE_32 1
+ #if defined(MA_X64) || (defined(MA_X86) && ((defined(__GNUC__) && defined(__i586__)) || (defined(_M_IX86) && _M_IX86 >= 500)))
+ #define MA_ATOMIC_IS_LOCK_FREE_64 1
+ #else
+ #endif
+ #else
+ #endif
+ #if defined(MA_ARM32) || defined(MA_ARM64)
+ #define MA_ATOMIC_IS_LOCK_FREE_8 1
+ #define MA_ATOMIC_IS_LOCK_FREE_16 1
+ #define MA_ATOMIC_IS_LOCK_FREE_32 1
+ #if defined(MA_ARM64) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__)
+ #define MA_ATOMIC_IS_LOCK_FREE_64 1
+ #endif
+ #endif
+ #if defined(MA_ATOMIC_PPC32) || defined(MA_ATOMIC_PPC64)
+ #if (defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 7))) && !defined(__clang__)
+ #else
+ #define MA_ATOMIC_IS_LOCK_FREE_8 1
+ #define MA_ATOMIC_IS_LOCK_FREE_16 1
+ #endif
+ #define MA_ATOMIC_IS_LOCK_FREE_32 1
+ #if defined(MA_ATOMIC_PPC64)
+ #define MA_ATOMIC_IS_LOCK_FREE_64 1
+ #endif
+ #endif
+ static MA_INLINE ma_bool32 ma_atomic_is_lock_free_8(volatile void* ptr)
+ {
+ (void)ptr;
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_8)
+ return 1;
+ #else
+ return 0;
+ #endif
+ }
+ static MA_INLINE ma_bool32 ma_atomic_is_lock_free_16(volatile void* ptr)
+ {
+ (void)ptr;
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_16)
+ return 1;
+ #else
+ return 0;
+ #endif
+ }
+ static MA_INLINE ma_bool32 ma_atomic_is_lock_free_32(volatile void* ptr)
+ {
+ (void)ptr;
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_32)
+ return 1;
+ #else
+ return 0;
+ #endif
+ }
+ static MA_INLINE ma_bool32 ma_atomic_is_lock_free_64(volatile void* ptr)
+ {
+ (void)ptr;
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_64)
+ return 1;
+ #else
+ return 0;
+ #endif
+ }
+#endif
+#define MA_ATOMIC_COMPARE_AND_SWAP_LOCK(sizeInBits, dst, expected, replacement) \
+ ma_uint##sizeInBits result; \
+ ma_atomic_spinlock_lock(&ma_atomic_global_lock); \
+ { \
+ result = *dst; \
+ if (result == expected) { \
+ *dst = replacement; \
+ } \
+ } \
+ ma_atomic_spinlock_unlock(&ma_atomic_global_lock); \
+ return result
+#define MA_ATOMIC_LOAD_EXPLICIT_LOCK(sizeInBits, ptr, order) \
+ ma_uint##sizeInBits result; \
+ ma_atomic_spinlock_lock(&ma_atomic_global_lock); \
+ { \
+ result = *ptr; \
+ (void)order; \
+ } \
+ ma_atomic_spinlock_unlock(&ma_atomic_global_lock); \
+ return result
+#define MA_ATOMIC_STORE_EXPLICIT_LOCK(sizeInBits, dst, src, order) \
+ ma_atomic_spinlock_lock(&ma_atomic_global_lock); \
+ { \
+ *dst = src; \
+ (void)order; \
+ } \
+ ma_atomic_spinlock_unlock(&ma_atomic_global_lock)
+#define MA_ATOMIC_STORE_EXPLICIT_CAS(sizeInBits, dst, src, order) \
+ ma_uint##sizeInBits oldValue; \
+ do { \
+ oldValue = ma_atomic_load_explicit_##sizeInBits(dst, ma_atomic_memory_order_relaxed); \
+ } while (ma_atomic_compare_and_swap_##sizeInBits(dst, oldValue, src) != oldValue); \
+ (void)order
+#define MA_ATOMIC_EXCHANGE_EXPLICIT_LOCK(sizeInBits, dst, src, order) \
+ ma_uint##sizeInBits result; \
+ ma_atomic_spinlock_lock(&ma_atomic_global_lock); \
+ { \
+ result = *dst; \
+ *dst = src; \
+ (void)order; \
+ } \
+ ma_atomic_spinlock_unlock(&ma_atomic_global_lock); \
+ return result
+#define MA_ATOMIC_EXCHANGE_EXPLICIT_CAS(sizeInBits, dst, src, order) \
+ ma_uint##sizeInBits oldValue; \
+ do { \
+ oldValue = ma_atomic_load_explicit_##sizeInBits(dst, ma_atomic_memory_order_relaxed); \
+ } while (ma_atomic_compare_and_swap_##sizeInBits(dst, oldValue, src) != oldValue); \
+ (void)order; \
+ return oldValue
+#define MA_ATOMIC_FETCH_ADD_LOCK(sizeInBits, dst, src, order) \
+ ma_uint##sizeInBits result; \
+ ma_atomic_spinlock_lock(&ma_atomic_global_lock); \
+ { \
+ result = *dst; \
+ *dst += src; \
+ (void)order; \
+ } \
+ ma_atomic_spinlock_unlock(&ma_atomic_global_lock); \
+ return result
+#define MA_ATOMIC_FETCH_ADD_CAS(sizeInBits, dst, src, order) \
+ ma_uint##sizeInBits oldValue; \
+ ma_uint##sizeInBits newValue; \
+ do { \
+ oldValue = ma_atomic_load_explicit_##sizeInBits(dst, ma_atomic_memory_order_relaxed); \
+ newValue = oldValue + src; \
+ } while (ma_atomic_compare_and_swap_##sizeInBits(dst, oldValue, newValue) != oldValue); \
+ (void)order; \
+ return oldValue
+#define MA_ATOMIC_FETCH_AND_CAS(sizeInBits, dst, src, order) \
+ ma_uint##sizeInBits oldValue; \
+ ma_uint##sizeInBits newValue; \
+ do { \
+ oldValue = ma_atomic_load_explicit_##sizeInBits(dst, ma_atomic_memory_order_relaxed); \
+ newValue = (ma_uint##sizeInBits)(oldValue & src); \
+ } while (ma_atomic_compare_and_swap_##sizeInBits(dst, oldValue, newValue) != oldValue); \
+ (void)order; \
+ return oldValue
+#define MA_ATOMIC_FETCH_OR_CAS(sizeInBits, dst, src, order) \
+ ma_uint##sizeInBits oldValue; \
+ ma_uint##sizeInBits newValue; \
+ do { \
+ oldValue = ma_atomic_load_explicit_##sizeInBits(dst, ma_atomic_memory_order_relaxed); \
+ newValue = (ma_uint##sizeInBits)(oldValue | src); \
+ } while (ma_atomic_compare_and_swap_##sizeInBits(dst, oldValue, newValue) != oldValue); \
+ (void)order; \
+ return oldValue
+#define MA_ATOMIC_FETCH_XOR_CAS(sizeInBits, dst, src, order) \
+ ma_uint##sizeInBits oldValue; \
+ ma_uint##sizeInBits newValue; \
+ do { \
+ oldValue = ma_atomic_load_explicit_##sizeInBits(dst, ma_atomic_memory_order_relaxed); \
+ newValue = (ma_uint##sizeInBits)(oldValue ^ src); \
+ } while (ma_atomic_compare_and_swap_##sizeInBits(dst, oldValue, newValue) != oldValue); \
+ (void)order; \
+ return oldValue
+#if defined(MA_ATOMIC_MODERN_MSVC) || defined(MA_ATOMIC_LEGACY_MSVC)
+ #define MA_ATOMIC_MSVC_ARM_INTRINSIC_COMPARE_EXCHANGE(ptr, expected, replacement, order, intrin, ma_atomicType, msvcType) \
ma_atomicType result; \
switch (order) \
{ \
case ma_atomic_memory_order_relaxed: \
{ \
- result = (ma_atomicType)intrin##_nf((volatile msvcType*)ptr, (msvcType)expected, (msvcType)desired); \
+ result = (ma_atomicType)intrin##_nf((volatile msvcType*)ptr, (msvcType)expected, (msvcType)replacement); \
} break; \
case ma_atomic_memory_order_consume: \
case ma_atomic_memory_order_acquire: \
{ \
- result = (ma_atomicType)intrin##_acq((volatile msvcType*)ptr, (msvcType)expected, (msvcType)desired); \
+ result = (ma_atomicType)intrin##_acq((volatile msvcType*)ptr, (msvcType)expected, (msvcType)replacement); \
} break; \
case ma_atomic_memory_order_release: \
{ \
- result = (ma_atomicType)intrin##_rel((volatile msvcType*)ptr, (msvcType)expected, (msvcType)desired); \
+ result = (ma_atomicType)intrin##_rel((volatile msvcType*)ptr, (msvcType)expected, (msvcType)replacement); \
} break; \
case ma_atomic_memory_order_acq_rel: \
case ma_atomic_memory_order_seq_cst: \
default: \
{ \
- result = (ma_atomicType)intrin((volatile msvcType*)ptr, (msvcType)expected, (msvcType)desired); \
+ result = (ma_atomicType)intrin((volatile msvcType*)ptr, (msvcType)expected, (msvcType)replacement); \
} break; \
} \
return result;
- #define ma_atomic_memory_order_relaxed 0
- #define ma_atomic_memory_order_consume 1
- #define ma_atomic_memory_order_acquire 2
- #define ma_atomic_memory_order_release 3
- #define ma_atomic_memory_order_acq_rel 4
- #define ma_atomic_memory_order_seq_cst 5
- #if _MSC_VER < 1600 && defined(MA_X86)
- #define MA_ATOMIC_MSVC_USE_INLINED_ASSEMBLY
- #endif
- #if _MSC_VER < 1600
- #undef MA_ATOMIC_HAS_8
- #undef MA_ATOMIC_HAS_16
- #endif
- #if !defined(MA_ATOMIC_MSVC_USE_INLINED_ASSEMBLY)
- #include
- #endif
- #if defined(MA_ATOMIC_MSVC_USE_INLINED_ASSEMBLY)
- #if defined(MA_ATOMIC_HAS_8)
- static MA_INLINE ma_uint8 __stdcall ma_atomic_compare_and_swap_8(volatile ma_uint8* dst, ma_uint8 expected, ma_uint8 desired)
- {
- ma_uint8 result = 0;
- __asm {
- mov ecx, dst
- mov al, expected
- mov dl, desired
- lock cmpxchg [ecx], dl
- mov result, al
- }
- return result;
- }
- #endif
- #if defined(MA_ATOMIC_HAS_16)
- static MA_INLINE ma_uint16 __stdcall ma_atomic_compare_and_swap_16(volatile ma_uint16* dst, ma_uint16 expected, ma_uint16 desired)
- {
- ma_uint16 result = 0;
- __asm {
- mov ecx, dst
- mov ax, expected
- mov dx, desired
- lock cmpxchg [ecx], dx
- mov result, ax
- }
- return result;
- }
- #endif
- #if defined(MA_ATOMIC_HAS_32)
- static MA_INLINE ma_uint32 __stdcall ma_atomic_compare_and_swap_32(volatile ma_uint32* dst, ma_uint32 expected, ma_uint32 desired)
- {
- ma_uint32 result = 0;
- __asm {
- mov ecx, dst
- mov eax, expected
- mov edx, desired
- lock cmpxchg [ecx], edx
- mov result, eax
- }
- return result;
- }
- #endif
- #if defined(MA_ATOMIC_HAS_64)
- static MA_INLINE ma_uint64 __stdcall ma_atomic_compare_and_swap_64(volatile ma_uint64* dst, ma_uint64 expected, ma_uint64 desired)
- {
- ma_uint32 resultEAX = 0;
- ma_uint32 resultEDX = 0;
- __asm {
- mov esi, dst
- mov eax, dword ptr expected
- mov edx, dword ptr expected + 4
- mov ebx, dword ptr desired
- mov ecx, dword ptr desired + 4
- lock cmpxchg8b qword ptr [esi]
- mov resultEAX, eax
- mov resultEDX, edx
- }
- return ((ma_uint64)resultEDX << 32) | resultEAX;
- }
- #endif
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_8)
+ #define ma_atomic_compare_and_swap_8( dst, expected, replacement) (ma_uint8 )_InterlockedCompareExchange8((volatile char*)dst, (char)replacement, (char)expected)
#else
- #if defined(MA_ATOMIC_HAS_8)
- #define ma_atomic_compare_and_swap_8( dst, expected, desired) (ma_uint8 )_InterlockedCompareExchange8((volatile char*)dst, (char)desired, (char)expected)
- #endif
- #if defined(MA_ATOMIC_HAS_16)
- #define ma_atomic_compare_and_swap_16(dst, expected, desired) (ma_uint16)_InterlockedCompareExchange16((volatile short*)dst, (short)desired, (short)expected)
- #endif
- #if defined(MA_ATOMIC_HAS_32)
- #define ma_atomic_compare_and_swap_32(dst, expected, desired) (ma_uint32)_InterlockedCompareExchange((volatile long*)dst, (long)desired, (long)expected)
- #endif
- #if defined(MA_ATOMIC_HAS_64)
- #define ma_atomic_compare_and_swap_64(dst, expected, desired) (ma_uint64)_InterlockedCompareExchange64((volatile ma_int64*)dst, (ma_int64)desired, (ma_int64)expected)
- #endif
+ static MA_INLINE ma_uint8 __stdcall ma_atomic_compare_and_swap_8(volatile ma_uint8* dst, ma_uint8 expected, ma_uint8 replacement)
+ {
+ MA_ATOMIC_COMPARE_AND_SWAP_LOCK(8, dst, expected, replacement);
+ }
#endif
- #if defined(MA_ATOMIC_MSVC_USE_INLINED_ASSEMBLY)
- #if defined(MA_ATOMIC_HAS_8)
- static MA_INLINE ma_uint8 __stdcall ma_atomic_exchange_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order)
- {
- ma_uint8 result = 0;
- (void)order;
- __asm {
- mov ecx, dst
- mov al, src
- lock xchg [ecx], al
- mov result, al
- }
- return result;
- }
- #endif
- #if defined(MA_ATOMIC_HAS_16)
- static MA_INLINE ma_uint16 __stdcall ma_atomic_exchange_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order)
- {
- ma_uint16 result = 0;
- (void)order;
- __asm {
- mov ecx, dst
- mov ax, src
- lock xchg [ecx], ax
- mov result, ax
- }
- return result;
- }
- #endif
- #if defined(MA_ATOMIC_HAS_32)
- static MA_INLINE ma_uint32 __stdcall ma_atomic_exchange_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order)
- {
- ma_uint32 result = 0;
- (void)order;
- __asm {
- mov ecx, dst
- mov eax, src
- lock xchg [ecx], eax
- mov result, eax
- }
- return result;
- }
- #endif
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_16)
+ #define ma_atomic_compare_and_swap_16(dst, expected, replacement) (ma_uint16)_InterlockedCompareExchange16((volatile short*)dst, (short)replacement, (short)expected)
#else
- #if defined(MA_ATOMIC_HAS_8)
- static MA_INLINE ma_uint8 __stdcall ma_atomic_exchange_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order)
- {
+ static MA_INLINE ma_uint16 __stdcall ma_atomic_compare_and_swap_16(volatile ma_uint16* dst, ma_uint16 expected, ma_uint16 replacement)
+ {
+ MA_ATOMIC_COMPARE_AND_SWAP_LOCK(16, dst, expected, replacement);
+ }
+ #endif
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_32)
+ #define ma_atomic_compare_and_swap_32(dst, expected, replacement) (ma_uint32)_InterlockedCompareExchange((volatile long*)dst, (long)replacement, (long)expected)
+ #else
+ static MA_INLINE ma_uint32 __stdcall ma_atomic_compare_and_swap_32(volatile ma_uint32* dst, ma_uint32 expected, ma_uint32 replacement)
+ {
+ MA_ATOMIC_COMPARE_AND_SWAP_LOCK(32, dst, expected, replacement);
+ }
+ #endif
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_32)
+ #define ma_atomic_compare_and_swap_64(dst, expected, replacement) (ma_uint64)_InterlockedCompareExchange64((volatile ma_int64*)dst, (ma_int64)replacement, (ma_int64)expected)
+ #else
+ static MA_INLINE ma_uint64 __stdcall ma_atomic_compare_and_swap_64(volatile ma_uint64* dst, ma_uint64 expected, ma_uint64 replacement)
+ {
+ MA_ATOMIC_COMPARE_AND_SWAP_LOCK(64, dst, expected, replacement);
+ }
+ #endif
+ static MA_INLINE ma_uint8 ma_atomic_load_explicit_8(volatile const ma_uint8* ptr, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_8)
+ {
#if defined(MA_ARM)
- MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedExchange8, ma_uint8, char);
+ {
+ MA_ATOMIC_MSVC_ARM_INTRINSIC_COMPARE_EXCHANGE(ptr, 0, 0, order, _InterlockedCompareExchange8, ma_uint8, char);
+ }
#else
+ {
+ (void)order;
+ return ma_atomic_compare_and_swap_8((volatile ma_uint8*)ptr, 0, 0);
+ }
+ #endif
+ }
+ #else
+ {
+ MA_ATOMIC_LOAD_EXPLICIT_LOCK(8, ptr, order);
+ }
+ #endif
+ }
+ static MA_INLINE ma_uint16 ma_atomic_load_explicit_16(volatile const ma_uint16* ptr, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_16)
+ {
+ #if defined(MA_ARM)
+ {
+ MA_ATOMIC_MSVC_ARM_INTRINSIC_COMPARE_EXCHANGE(ptr, 0, 0, order, _InterlockedCompareExchange16, ma_uint16, short);
+ }
+ #else
+ {
+ (void)order;
+ return ma_atomic_compare_and_swap_16((volatile ma_uint16*)ptr, 0, 0);
+ }
+ #endif
+ }
+ #else
+ {
+ MA_ATOMIC_LOAD_EXPLICIT_LOCK(16, ptr, order);
+ }
+ #endif
+ }
+ static MA_INLINE ma_uint32 ma_atomic_load_explicit_32(volatile const ma_uint32* ptr, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_32)
+ {
+ #if defined(MA_ARM)
+ {
+ MA_ATOMIC_MSVC_ARM_INTRINSIC_COMPARE_EXCHANGE(ptr, 0, 0, order, _InterlockedCompareExchange, ma_uint32, long);
+ }
+ #else
+ {
+ (void)order;
+ return ma_atomic_compare_and_swap_32((volatile ma_uint32*)ptr, 0, 0);
+ }
+ #endif
+ }
+ #else
+ {
+ MA_ATOMIC_LOAD_EXPLICIT_LOCK(32, ptr, order);
+ }
+ #endif
+ }
+ static MA_INLINE ma_uint64 ma_atomic_load_explicit_64(volatile const ma_uint64* ptr, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_32)
+ {
+ #if defined(MA_ARM)
+ {
+ MA_ATOMIC_MSVC_ARM_INTRINSIC_COMPARE_EXCHANGE(ptr, 0, 0, order, _InterlockedCompareExchange64, ma_uint64, long long);
+ }
+ #else
+ {
+ (void)order;
+ return ma_atomic_compare_and_swap_64((volatile ma_uint64*)ptr, 0, 0);
+ }
+ #endif
+ }
+ #else
+ {
+ MA_ATOMIC_LOAD_EXPLICIT_LOCK(64, ptr, order);
+ }
+ #endif
+ }
+ static MA_INLINE ma_uint8 __stdcall ma_atomic_exchange_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_8)
+ {
+ #if defined(MA_ARM)
+ {
+ MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedExchange8, ma_uint8, char);
+ }
+ #else
+ {
(void)order;
return (ma_uint8)_InterlockedExchange8((volatile char*)dst, (char)src);
- #endif
}
+ #endif
+ }
+ #else
+ {
+ MA_ATOMIC_EXCHANGE_EXPLICIT_LOCK(8, dst, src, order);
+ }
#endif
- #if defined(MA_ATOMIC_HAS_16)
- static MA_INLINE ma_uint16 __stdcall ma_atomic_exchange_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order)
- {
+ }
+ static MA_INLINE ma_uint16 __stdcall ma_atomic_exchange_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_16)
+ {
#if defined(MA_ARM)
+ {
MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedExchange16, ma_uint16, short);
+ }
#else
+ {
(void)order;
return (ma_uint16)_InterlockedExchange16((volatile short*)dst, (short)src);
- #endif
}
+ #endif
+ }
+ #else
+ {
+ MA_ATOMIC_EXCHANGE_EXPLICIT_LOCK(16, dst, src, order);
+ }
#endif
- #if defined(MA_ATOMIC_HAS_32)
- static MA_INLINE ma_uint32 __stdcall ma_atomic_exchange_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order)
- {
+ }
+ static MA_INLINE ma_uint32 __stdcall ma_atomic_exchange_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_32)
+ {
#if defined(MA_ARM)
+ {
MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedExchange, ma_uint32, long);
+ }
#else
+ {
(void)order;
return (ma_uint32)_InterlockedExchange((volatile long*)dst, (long)src);
- #endif
}
- #endif
- #if defined(MA_ATOMIC_HAS_64) && defined(MA_64BIT)
- static MA_INLINE ma_uint64 __stdcall ma_atomic_exchange_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order)
- {
- #if defined(MA_ARM)
- MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedExchange64, ma_uint64, long long);
- #else
- (void)order;
- return (ma_uint64)_InterlockedExchange64((volatile long long*)dst, (long long)src);
#endif
- }
- #else
- #endif
- #endif
- #if defined(MA_ATOMIC_HAS_64) && !defined(MA_64BIT)
- static MA_INLINE ma_uint64 __stdcall ma_atomic_exchange_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order)
- {
- ma_uint64 oldValue;
- do {
- oldValue = *dst;
- } while (ma_atomic_compare_and_swap_64(dst, oldValue, src) != oldValue);
- (void)order;
- return oldValue;
}
- #endif
- #if defined(MA_ATOMIC_MSVC_USE_INLINED_ASSEMBLY)
- #if defined(MA_ATOMIC_HAS_8)
- static MA_INLINE ma_uint8 __stdcall ma_atomic_fetch_add_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order)
- {
- ma_uint8 result = 0;
- (void)order;
- __asm {
- mov ecx, dst
- mov al, src
- lock xadd [ecx], al
- mov result, al
- }
- return result;
- }
+ #else
+ {
+ MA_ATOMIC_EXCHANGE_EXPLICIT_LOCK(32, dst, src, order);
+ }
#endif
- #if defined(MA_ATOMIC_HAS_16)
- static MA_INLINE ma_uint16 __stdcall ma_atomic_fetch_add_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order)
+ }
+ static MA_INLINE ma_uint64 __stdcall ma_atomic_exchange_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_64)
+ {
+ #if defined(MA_32BIT)
{
- ma_uint16 result = 0;
- (void)order;
- __asm {
- mov ecx, dst
- mov ax, src
- lock xadd [ecx], ax
- mov result, ax
- }
- return result;
+ MA_ATOMIC_EXCHANGE_EXPLICIT_CAS(64, dst, src, order);
}
- #endif
- #if defined(MA_ATOMIC_HAS_32)
- static MA_INLINE ma_uint32 __stdcall ma_atomic_fetch_add_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order)
- {
- ma_uint32 result = 0;
- (void)order;
- __asm {
- mov ecx, dst
- mov eax, src
- lock xadd [ecx], eax
- mov result, eax
- }
- return result;
- }
- #endif
- #else
- #if defined(MA_ATOMIC_HAS_8)
- static MA_INLINE ma_uint8 __stdcall ma_atomic_fetch_add_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order)
- {
- #if defined(MA_ARM)
- MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedExchangeAdd8, ma_uint8, char);
#else
+ {
+ #if defined(MA_ARM)
+ {
+ MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedExchange64, ma_uint64, long long);
+ }
+ #else
+ {
+ (void)order;
+ return (ma_uint64)_InterlockedExchange64((volatile long long*)dst, (long long)src);
+ }
+ #endif
+ }
+ #endif
+ }
+ #else
+ {
+ MA_ATOMIC_EXCHANGE_EXPLICIT_LOCK(64, dst, src, order);
+ }
+ #endif
+ }
+ static MA_INLINE ma_uint8 __stdcall ma_atomic_fetch_add_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_8)
+ {
+ #if defined(MA_ARM)
+ {
+ MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedExchangeAdd8, ma_uint8, char);
+ }
+ #else
+ {
(void)order;
return (ma_uint8)_InterlockedExchangeAdd8((volatile char*)dst, (char)src);
- #endif
}
+ #endif
+ }
+ #else
+ {
+ MA_ATOMIC_FETCH_ADD_LOCK(8, dst, src, order);
+ }
#endif
- #if defined(MA_ATOMIC_HAS_16)
- static MA_INLINE ma_uint16 __stdcall ma_atomic_fetch_add_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order)
- {
+ }
+ static MA_INLINE ma_uint16 __stdcall ma_atomic_fetch_add_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_16)
+ {
#if defined(MA_ARM)
+ {
MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedExchangeAdd16, ma_uint16, short);
+ }
#else
+ {
(void)order;
return (ma_uint16)_InterlockedExchangeAdd16((volatile short*)dst, (short)src);
- #endif
}
+ #endif
+ }
+ #else
+ {
+ MA_ATOMIC_FETCH_ADD_LOCK(16, dst, src, order);
+ }
#endif
- #if defined(MA_ATOMIC_HAS_32)
- static MA_INLINE ma_uint32 __stdcall ma_atomic_fetch_add_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order)
- {
+ }
+ static MA_INLINE ma_uint32 __stdcall ma_atomic_fetch_add_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_32)
+ {
#if defined(MA_ARM)
+ {
MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedExchangeAdd, ma_uint32, long);
+ }
#else
+ {
(void)order;
return (ma_uint32)_InterlockedExchangeAdd((volatile long*)dst, (long)src);
- #endif
}
- #endif
- #if defined(MA_ATOMIC_HAS_64) && defined(MA_64BIT)
- static MA_INLINE ma_uint64 __stdcall ma_atomic_fetch_add_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order)
- {
- #if defined(MA_ARM)
- MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedExchangeAdd64, ma_uint64, long long);
- #else
- (void)order;
- return (ma_uint64)_InterlockedExchangeAdd64((volatile long long*)dst, (long long)src);
#endif
- }
+ }
#else
- #endif
- #endif
- #if defined(MA_ATOMIC_HAS_64) && !defined(MA_64BIT)
- static MA_INLINE ma_uint64 __stdcall ma_atomic_fetch_add_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order)
{
- ma_uint64 oldValue;
- ma_uint64 newValue;
- do {
- oldValue = *dst;
- newValue = oldValue + src;
- } while (ma_atomic_compare_and_swap_64(dst, oldValue, newValue) != oldValue);
- (void)order;
- return oldValue;
+ MA_ATOMIC_FETCH_ADD_LOCK(32, dst, src, order);
+ }
+ #endif
+ }
+ static MA_INLINE ma_uint64 __stdcall ma_atomic_fetch_add_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_64)
+ {
+ #if defined(MA_32BIT)
+ {
+ MA_ATOMIC_FETCH_ADD_CAS(64, dst, src, order);
+ }
+ #else
+ {
+ #if defined(MA_ARM)
+ {
+ MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedExchangeAdd64, ma_uint64, long long);
+ }
+ #else
+ {
+ (void)order;
+ return (ma_uint64)_InterlockedExchangeAdd64((volatile long long*)dst, (long long)src);
+ }
+ #endif
+ }
+ #endif
+ }
+ #else
+ {
+ MA_ATOMIC_FETCH_ADD_LOCK(64, dst, src, order);
+ }
+ #endif
+ }
+ static MA_INLINE ma_uint8 __stdcall ma_atomic_fetch_sub_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order)
+ {
+ return ma_atomic_fetch_add_explicit_8(dst, (ma_uint8)(-(ma_int8)src), order);
+ }
+ static MA_INLINE ma_uint16 __stdcall ma_atomic_fetch_sub_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order)
+ {
+ return ma_atomic_fetch_add_explicit_16(dst, (ma_uint16)(-(ma_int16)src), order);
+ }
+ static MA_INLINE ma_uint32 __stdcall ma_atomic_fetch_sub_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order)
+ {
+ return ma_atomic_fetch_add_explicit_32(dst, (ma_uint32)(-(ma_int32)src), order);
+ }
+ static MA_INLINE ma_uint64 __stdcall ma_atomic_fetch_sub_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order)
+ {
+ return ma_atomic_fetch_add_explicit_64(dst, (ma_uint64)(-(ma_int64)src), order);
+ }
+ static MA_INLINE ma_uint8 __stdcall ma_atomic_fetch_and_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ARM)
+ {
+ MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedAnd8, ma_uint8, char);
+ }
+ #else
+ {
+ MA_ATOMIC_FETCH_AND_CAS(8, dst, src, order);
+ }
+ #endif
+ }
+ static MA_INLINE ma_uint16 __stdcall ma_atomic_fetch_and_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ARM)
+ {
+ MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedAnd16, ma_uint16, short);
+ }
+ #else
+ {
+ MA_ATOMIC_FETCH_AND_CAS(16, dst, src, order);
+ }
+ #endif
+ }
+ static MA_INLINE ma_uint32 __stdcall ma_atomic_fetch_and_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ARM)
+ {
+ MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedAnd, ma_uint32, long);
+ }
+ #else
+ {
+ MA_ATOMIC_FETCH_AND_CAS(32, dst, src, order);
+ }
+ #endif
+ }
+ static MA_INLINE ma_uint64 __stdcall ma_atomic_fetch_and_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ARM)
+ {
+ MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedAnd64, ma_uint64, long long);
+ }
+ #else
+ {
+ MA_ATOMIC_FETCH_AND_CAS(64, dst, src, order);
+ }
+ #endif
+ }
+ static MA_INLINE ma_uint8 __stdcall ma_atomic_fetch_or_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ARM)
+ {
+ MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedOr8, ma_uint8, char);
+ }
+ #else
+ {
+ MA_ATOMIC_FETCH_OR_CAS(8, dst, src, order);
+ }
+ #endif
+ }
+ static MA_INLINE ma_uint16 __stdcall ma_atomic_fetch_or_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ARM)
+ {
+ MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedOr16, ma_uint16, short);
+ }
+ #else
+ {
+ MA_ATOMIC_FETCH_OR_CAS(16, dst, src, order);
+ }
+ #endif
+ }
+ static MA_INLINE ma_uint32 __stdcall ma_atomic_fetch_or_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ARM)
+ {
+ MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedOr, ma_uint32, long);
+ }
+ #else
+ {
+ MA_ATOMIC_FETCH_OR_CAS(32, dst, src, order);
+ }
+ #endif
+ }
+ static MA_INLINE ma_uint64 __stdcall ma_atomic_fetch_or_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ARM)
+ {
+ MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedOr64, ma_uint64, long long);
+ }
+ #else
+ {
+ MA_ATOMIC_FETCH_OR_CAS(64, dst, src, order);
+ }
+ #endif
+ }
+ static MA_INLINE ma_uint8 __stdcall ma_atomic_fetch_xor_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ARM)
+ {
+ MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedXor8, ma_uint8, char);
+ }
+ #else
+ {
+ MA_ATOMIC_FETCH_XOR_CAS(8, dst, src, order);
+ }
+ #endif
+ }
+ static MA_INLINE ma_uint16 __stdcall ma_atomic_fetch_xor_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ARM)
+ {
+ MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedXor16, ma_uint16, short);
+ }
+ #else
+ {
+ MA_ATOMIC_FETCH_XOR_CAS(16, dst, src, order);
+ }
+ #endif
+ }
+ static MA_INLINE ma_uint32 __stdcall ma_atomic_fetch_xor_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ARM)
+ {
+ MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedXor, ma_uint32, long);
+ }
+ #else
+ {
+ MA_ATOMIC_FETCH_XOR_CAS(32, dst, src, order);
+ }
+ #endif
+ }
+ static MA_INLINE ma_uint64 __stdcall ma_atomic_fetch_xor_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ARM)
+ {
+ MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedXor64, ma_uint64, long long);
+ }
+ #else
+ {
+ MA_ATOMIC_FETCH_XOR_CAS(64, dst, src, order);
+ }
+ #endif
+ }
+ #define ma_atomic_store_explicit_8( dst, src, order) (void)ma_atomic_exchange_explicit_8 (dst, src, order)
+ #define ma_atomic_store_explicit_16(dst, src, order) (void)ma_atomic_exchange_explicit_16(dst, src, order)
+ #define ma_atomic_store_explicit_32(dst, src, order) (void)ma_atomic_exchange_explicit_32(dst, src, order)
+ #define ma_atomic_store_explicit_64(dst, src, order) (void)ma_atomic_exchange_explicit_64(dst, src, order)
+ #if defined(MA_X64)
+ #define ma_atomic_thread_fence(order) __faststorefence(), (void)order
+ #elif defined(MA_ARM64)
+ #define ma_atomic_thread_fence(order) __dmb(_ARM64_BARRIER_ISH), (void)order
+ #else
+ static MA_INLINE void ma_atomic_thread_fence(ma_atomic_memory_order order)
+ {
+ volatile ma_uint32 barrier = 0;
+ ma_atomic_fetch_add_explicit_32(&barrier, 0, order);
}
#endif
- #if defined(MA_ATOMIC_MSVC_USE_INLINED_ASSEMBLY)
- static MA_INLINE void __stdcall ma_atomic_thread_fence(ma_atomic_memory_order order)
+ #define ma_atomic_signal_fence(order) _ReadWriteBarrier(), (void)order
+#endif
+#if defined(MA_ATOMIC_LEGACY_MSVC_ASM)
+ static MA_INLINE ma_uint8 __stdcall ma_atomic_compare_and_swap_8(volatile ma_uint8* dst, ma_uint8 expected, ma_uint8 replacement)
+ {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_8)
{
+ ma_uint8 result = 0;
+ __asm {
+ mov ecx, dst
+ mov al, expected
+ mov dl, replacement
+ lock cmpxchg [ecx], dl
+ mov result, al
+ }
+ return result;
+ }
+ #else
+ {
+ MA_ATOMIC_COMPARE_AND_SWAP_LOCK(8, dst, expected, replacement);
+ }
+ #endif
+ }
+ static MA_INLINE ma_uint16 __stdcall ma_atomic_compare_and_swap_16(volatile ma_uint16* dst, ma_uint16 expected, ma_uint16 replacement)
+ {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_16)
+ {
+ ma_uint16 result = 0;
+ __asm {
+ mov ecx, dst
+ mov ax, expected
+ mov dx, replacement
+ lock cmpxchg [ecx], dx
+ mov result, ax
+ }
+ return result;
+ }
+ #else
+ {
+ MA_ATOMIC_COMPARE_AND_SWAP_LOCK(16, dst, expected, replacement);
+ }
+ #endif
+ }
+ static MA_INLINE ma_uint32 __stdcall ma_atomic_compare_and_swap_32(volatile ma_uint32* dst, ma_uint32 expected, ma_uint32 replacement)
+ {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_32)
+ {
+ ma_uint32 result = 0;
+ __asm {
+ mov ecx, dst
+ mov eax, expected
+ mov edx, replacement
+ lock cmpxchg [ecx], edx
+ mov result, eax
+ }
+ return result;
+ }
+ #else
+ {
+ MA_ATOMIC_COMPARE_AND_SWAP_LOCK(32, dst, expected, replacement);
+ }
+ #endif
+ }
+ static MA_INLINE ma_uint64 __stdcall ma_atomic_compare_and_swap_64(volatile ma_uint64* dst, ma_uint64 expected, ma_uint64 replacement)
+ {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_64)
+ {
+ ma_uint32 resultEAX = 0;
+ ma_uint32 resultEDX = 0;
+ __asm {
+ mov esi, dst
+ mov eax, dword ptr expected
+ mov edx, dword ptr expected + 4
+ mov ebx, dword ptr replacement
+ mov ecx, dword ptr replacement + 4
+ lock cmpxchg8b qword ptr [esi]
+ mov resultEAX, eax
+ mov resultEDX, edx
+ }
+ return ((ma_uint64)resultEDX << 32) | resultEAX;
+ }
+ #else
+ {
+ MA_ATOMIC_COMPARE_AND_SWAP_LOCK(64, dst, expected, replacement);
+ }
+ #endif
+ }
+ static MA_INLINE ma_uint8 ma_atomic_load_explicit_8(volatile const ma_uint8* dst, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_8)
+ {
+ ma_uint8 result = 0;
+ if (order == ma_atomic_memory_order_relaxed) {
+ __asm {
+ mov esi, dst
+ mov al, [esi]
+ mov result, al
+ }
+ } else if (order <= ma_atomic_memory_order_release) {
+ __asm {
+ mov esi, dst
+ mov al, [esi]
+ lock add dword ptr [esp], 0
+ mov result, al
+ }
+ } else {
+ __asm {
+ lock add dword ptr [esp], 0
+ mov esi, dst
+ mov al, [esi]
+ mov result, al
+ lock add dword ptr [esp], 0
+ }
+ }
+ return result;
+ }
+ #else
+ {
+ MA_ATOMIC_LOAD_EXPLICIT_LOCK(8, dst, order);
+ }
+ #endif
+ }
+ static MA_INLINE ma_uint16 ma_atomic_load_explicit_16(volatile const ma_uint16* dst, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_16)
+ {
+ ma_uint16 result = 0;
+ if (order == ma_atomic_memory_order_relaxed) {
+ __asm {
+ mov esi, dst
+ mov ax, [esi]
+ mov result, ax
+ }
+ } else if (order <= ma_atomic_memory_order_release) {
+ __asm {
+ mov esi, dst
+ mov ax, [esi]
+ lock add dword ptr [esp], 0
+ mov result, ax
+ }
+ } else {
+ __asm {
+ lock add dword ptr [esp], 0
+ mov esi, dst
+ mov ax, [esi]
+ mov result, ax
+ lock add dword ptr [esp], 0
+ }
+ }
+ return result;
+ }
+ #else
+ {
+ MA_ATOMIC_LOAD_EXPLICIT_LOCK(16, dst, order);
+ }
+ #endif
+ }
+ static MA_INLINE ma_uint32 ma_atomic_load_explicit_32(volatile const ma_uint32* dst, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_32)
+ {
+ ma_uint32 result = 0;
+ if (order == ma_atomic_memory_order_relaxed) {
+ __asm {
+ mov esi, dst
+ mov eax, [esi]
+ mov result, eax
+ }
+ } else if (order <= ma_atomic_memory_order_release) {
+ __asm {
+ mov esi, dst
+ mov eax, [esi]
+ lock add dword ptr [esp], 0
+ mov result, eax
+ }
+ } else {
+ __asm {
+ lock add dword ptr [esp], 0
+ mov esi, dst
+ mov eax, [esi]
+ mov result, eax
+ lock add dword ptr [esp], 0
+ }
+ }
+ return result;
+ }
+ #else
+ {
+ MA_ATOMIC_LOAD_EXPLICIT_LOCK(32, dst, order);
+ }
+ #endif
+ }
+ static MA_INLINE ma_uint64 ma_atomic_load_explicit_64(volatile const ma_uint64* dst, ma_atomic_memory_order order)
+ {
+ (void)order;
+ return ma_atomic_compare_and_swap_64((volatile ma_uint64*)dst, 0, 0);
+ }
+ static MA_INLINE void __stdcall ma_atomic_store_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order)
+ {
+ if (order == ma_atomic_memory_order_relaxed) {
+ __asm {
+ mov esi, dst
+ mov al, src
+ mov [esi], al
+ }
+ } else {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_8)
+ {
+ __asm {
+ mov esi, dst
+ mov al, src
+ xchg [esi], al
+ }
+ }
+ #else
+ {
+ MA_ATOMIC_STORE_EXPLICIT_LOCK(8, dst, src, order);
+ }
+ #endif
+ }
+ }
+ static MA_INLINE void __stdcall ma_atomic_store_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order)
+ {
+ if (order == ma_atomic_memory_order_relaxed) {
+ __asm {
+ mov esi, dst
+ mov ax, src
+ mov [esi], ax
+ }
+ } else {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_16)
+ {
+ __asm {
+ mov esi, dst
+ mov ax, src
+ xchg [esi], ax
+ }
+ }
+ #else
+ {
+ MA_ATOMIC_STORE_EXPLICIT_LOCK(16, dst, src, order);
+ }
+ #endif
+ }
+ }
+ static MA_INLINE void __stdcall ma_atomic_store_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order)
+ {
+ if (order == ma_atomic_memory_order_relaxed) {
+ __asm {
+ mov esi, dst
+ mov eax, src
+ mov [esi], eax
+ }
+ } else {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_32)
+ {
+ __asm {
+ mov esi, dst
+ mov eax, src
+ xchg [esi], eax
+ }
+ }
+ #else
+ {
+ MA_ATOMIC_STORE_EXPLICIT_LOCK(32, dst, src, order);
+ }
+ #endif
+ }
+ }
+ static MA_INLINE void __stdcall ma_atomic_store_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_64)
+ {
+ MA_ATOMIC_STORE_EXPLICIT_CAS(64, dst, src, order);
+ }
+ #else
+ {
+ MA_ATOMIC_STORE_EXPLICIT_LOCK(64, dst, src, order);
+ }
+ #endif
+ }
+ static MA_INLINE ma_uint8 __stdcall ma_atomic_exchange_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_8)
+ {
+ ma_uint8 result = 0;
(void)order;
__asm {
- lock add [esp], 0
+ mov ecx, dst
+ mov al, src
+ lock xchg [ecx], al
+ mov result, al
}
+ return result;
}
- #else
- #if defined(MA_X64)
- #define ma_atomic_thread_fence(order) __faststorefence(), (void)order
- #elif defined(MA_ARM64)
- #define ma_atomic_thread_fence(order) __dmb(_ARM64_BARRIER_ISH), (void)order
#else
- static MA_INLINE void ma_atomic_thread_fence(ma_atomic_memory_order order)
- {
- volatile ma_uint32 barrier = 0;
- ma_atomic_fetch_add_explicit_32(&barrier, 0, order);
+ {
+ MA_ATOMIC_EXCHANGE_EXPLICIT_LOCK(8, dst, src, order);
+ }
+ #endif
+ }
+ static MA_INLINE ma_uint16 __stdcall ma_atomic_exchange_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_16)
+ {
+ ma_uint16 result = 0;
+ (void)order;
+ __asm {
+ mov ecx, dst
+ mov ax, src
+ lock xchg [ecx], ax
+ mov result, ax
}
- #endif
- #endif
- #define ma_atomic_compiler_fence() ma_atomic_thread_fence(ma_atomic_memory_order_seq_cst)
- #define ma_atomic_signal_fence(order) ma_atomic_thread_fence(order)
- #if defined(MA_ATOMIC_HAS_8)
- static MA_INLINE ma_uint8 ma_atomic_load_explicit_8(volatile const ma_uint8* ptr, ma_atomic_memory_order order)
- {
- #if defined(MA_ARM)
- MA_ATOMIC_MSVC_ARM_INTRINSIC_COMPARE_EXCHANGE(ptr, 0, 0, order, _InterlockedCompareExchange8, ma_uint8, char);
+ return result;
+ }
#else
- (void)order;
- return ma_atomic_compare_and_swap_8((volatile ma_uint8*)ptr, 0, 0);
- #endif
- }
- #endif
- #if defined(MA_ATOMIC_HAS_16)
- static MA_INLINE ma_uint16 ma_atomic_load_explicit_16(volatile const ma_uint16* ptr, ma_atomic_memory_order order)
{
- #if defined(MA_ARM)
- MA_ATOMIC_MSVC_ARM_INTRINSIC_COMPARE_EXCHANGE(ptr, 0, 0, order, _InterlockedCompareExchange16, ma_uint16, short);
+ MA_ATOMIC_EXCHANGE_EXPLICIT_LOCK(16, dst, src, order);
+ }
+ #endif
+ }
+ static MA_INLINE ma_uint32 __stdcall ma_atomic_exchange_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_32)
+ {
+ ma_uint32 result = 0;
+ (void)order;
+ __asm {
+ mov ecx, dst
+ mov eax, src
+ xchg [ecx], eax
+ mov result, eax
+ }
+ return result;
+ }
#else
- (void)order;
- return ma_atomic_compare_and_swap_16((volatile ma_uint16*)ptr, 0, 0);
- #endif
- }
- #endif
- #if defined(MA_ATOMIC_HAS_32)
- static MA_INLINE ma_uint32 ma_atomic_load_explicit_32(volatile const ma_uint32* ptr, ma_atomic_memory_order order)
{
- #if defined(MA_ARM)
- MA_ATOMIC_MSVC_ARM_INTRINSIC_COMPARE_EXCHANGE(ptr, 0, 0, order, _InterlockedCompareExchange, ma_uint32, long);
+ MA_ATOMIC_EXCHANGE_EXPLICIT_LOCK(32, dst, src, order);
+ }
+ #endif
+ }
+ static MA_INLINE ma_uint64 __stdcall ma_atomic_exchange_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_64)
+ {
+ MA_ATOMIC_EXCHANGE_EXPLICIT_CAS(64, dst, src, order);
+ }
#else
- (void)order;
- return ma_atomic_compare_and_swap_32((volatile ma_uint32*)ptr, 0, 0);
- #endif
- }
- #endif
- #if defined(MA_ATOMIC_HAS_64)
- static MA_INLINE ma_uint64 ma_atomic_load_explicit_64(volatile const ma_uint64* ptr, ma_atomic_memory_order order)
{
- #if defined(MA_ARM)
- MA_ATOMIC_MSVC_ARM_INTRINSIC_COMPARE_EXCHANGE(ptr, 0, 0, order, _InterlockedCompareExchange64, ma_uint64, long long);
+ MA_ATOMIC_EXCHANGE_EXPLICIT_LOCK(64, dst, src, order);
+ }
+ #endif
+ }
+ static MA_INLINE ma_uint8 __stdcall ma_atomic_fetch_add_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_8)
+ {
+ ma_uint8 result = 0;
+ (void)order;
+ __asm {
+ mov ecx, dst
+ mov al, src
+ lock xadd [ecx], al
+ mov result, al
+ }
+ return result;
+ }
#else
- (void)order;
- return ma_atomic_compare_and_swap_64((volatile ma_uint64*)ptr, 0, 0);
+ {
+ MA_ATOMIC_FETCH_ADD_LOCK(8, dst, src, order);
+ }
#endif
- }
- #endif
- #if defined(MA_ATOMIC_HAS_8)
- #define ma_atomic_store_explicit_8( dst, src, order) (void)ma_atomic_exchange_explicit_8 (dst, src, order)
- #endif
- #if defined(MA_ATOMIC_HAS_16)
- #define ma_atomic_store_explicit_16(dst, src, order) (void)ma_atomic_exchange_explicit_16(dst, src, order)
- #endif
- #if defined(MA_ATOMIC_HAS_32)
- #define ma_atomic_store_explicit_32(dst, src, order) (void)ma_atomic_exchange_explicit_32(dst, src, order)
- #endif
- #if defined(MA_ATOMIC_HAS_64)
- #define ma_atomic_store_explicit_64(dst, src, order) (void)ma_atomic_exchange_explicit_64(dst, src, order)
- #endif
- #if defined(MA_ATOMIC_HAS_8)
- static MA_INLINE ma_uint8 __stdcall ma_atomic_fetch_sub_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order)
+ }
+ static MA_INLINE ma_uint16 __stdcall ma_atomic_fetch_add_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_16)
{
- ma_uint8 oldValue;
- ma_uint8 newValue;
- do {
- oldValue = *dst;
- newValue = (ma_uint8)(oldValue - src);
- } while (ma_atomic_compare_and_swap_8(dst, oldValue, newValue) != oldValue);
+ ma_uint16 result = 0;
(void)order;
- return oldValue;
+ __asm {
+ mov ecx, dst
+ mov ax, src
+ lock xadd [ecx], ax
+ mov result, ax
+ }
+ return result;
}
- #endif
- #if defined(MA_ATOMIC_HAS_16)
- static MA_INLINE ma_uint16 __stdcall ma_atomic_fetch_sub_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order)
- {
- ma_uint16 oldValue;
- ma_uint16 newValue;
- do {
- oldValue = *dst;
- newValue = (ma_uint16)(oldValue - src);
- } while (ma_atomic_compare_and_swap_16(dst, oldValue, newValue) != oldValue);
- (void)order;
- return oldValue;
- }
- #endif
- #if defined(MA_ATOMIC_HAS_32)
- static MA_INLINE ma_uint32 __stdcall ma_atomic_fetch_sub_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order)
- {
- ma_uint32 oldValue;
- ma_uint32 newValue;
- do {
- oldValue = *dst;
- newValue = oldValue - src;
- } while (ma_atomic_compare_and_swap_32(dst, oldValue, newValue) != oldValue);
- (void)order;
- return oldValue;
- }
- #endif
- #if defined(MA_ATOMIC_HAS_64)
- static MA_INLINE ma_uint64 __stdcall ma_atomic_fetch_sub_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order)
- {
- ma_uint64 oldValue;
- ma_uint64 newValue;
- do {
- oldValue = *dst;
- newValue = oldValue - src;
- } while (ma_atomic_compare_and_swap_64(dst, oldValue, newValue) != oldValue);
- (void)order;
- return oldValue;
- }
- #endif
- #if defined(MA_ATOMIC_HAS_8)
- static MA_INLINE ma_uint8 __stdcall ma_atomic_fetch_and_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order)
- {
- #if defined(MA_ARM)
- MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedAnd8, ma_uint8, char);
#else
- ma_uint8 oldValue;
- ma_uint8 newValue;
- do {
- oldValue = *dst;
- newValue = (ma_uint8)(oldValue & src);
- } while (ma_atomic_compare_and_swap_8(dst, oldValue, newValue) != oldValue);
- (void)order;
- return oldValue;
- #endif
- }
- #endif
- #if defined(MA_ATOMIC_HAS_16)
- static MA_INLINE ma_uint16 __stdcall ma_atomic_fetch_and_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order)
{
- #if defined(MA_ARM)
- MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedAnd16, ma_uint16, short);
- #else
- ma_uint16 oldValue;
- ma_uint16 newValue;
- do {
- oldValue = *dst;
- newValue = (ma_uint16)(oldValue & src);
- } while (ma_atomic_compare_and_swap_16(dst, oldValue, newValue) != oldValue);
- (void)order;
- return oldValue;
- #endif
+ MA_ATOMIC_FETCH_ADD_LOCK(16, dst, src, order);
}
- #endif
- #if defined(MA_ATOMIC_HAS_32)
- static MA_INLINE ma_uint32 __stdcall ma_atomic_fetch_and_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order)
+ #endif
+ }
+ static MA_INLINE ma_uint32 __stdcall ma_atomic_fetch_add_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_32)
{
- #if defined(MA_ARM)
- MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedAnd, ma_uint32, long);
- #else
- ma_uint32 oldValue;
- ma_uint32 newValue;
- do {
- oldValue = *dst;
- newValue = oldValue & src;
- } while (ma_atomic_compare_and_swap_32(dst, oldValue, newValue) != oldValue);
+ ma_uint32 result = 0;
(void)order;
- return oldValue;
- #endif
+ __asm {
+ mov ecx, dst
+ mov eax, src
+ lock xadd [ecx], eax
+ mov result, eax
+ }
+ return result;
}
- #endif
- #if defined(MA_ATOMIC_HAS_64)
- static MA_INLINE ma_uint64 __stdcall ma_atomic_fetch_and_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order)
+ #else
{
- #if defined(MA_ARM)
- MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedAnd64, ma_uint64, long long);
- #else
- ma_uint64 oldValue;
- ma_uint64 newValue;
- do {
- oldValue = *dst;
- newValue = oldValue & src;
- } while (ma_atomic_compare_and_swap_64(dst, oldValue, newValue) != oldValue);
- (void)order;
- return oldValue;
- #endif
+ MA_ATOMIC_FETCH_ADD_LOCK(32, dst, src, order);
}
- #endif
- #if defined(MA_ATOMIC_HAS_8)
- static MA_INLINE ma_uint8 __stdcall ma_atomic_fetch_xor_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order)
+ #endif
+ }
+ static MA_INLINE ma_uint64 __stdcall ma_atomic_fetch_add_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_64)
{
- #if defined(MA_ARM)
- MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedXor8, ma_uint8, char);
- #else
- ma_uint8 oldValue;
- ma_uint8 newValue;
- do {
- oldValue = *dst;
- newValue = (ma_uint8)(oldValue ^ src);
- } while (ma_atomic_compare_and_swap_8(dst, oldValue, newValue) != oldValue);
- (void)order;
- return oldValue;
- #endif
+ MA_ATOMIC_FETCH_ADD_CAS(64, dst, src, order);
}
- #endif
- #if defined(MA_ATOMIC_HAS_16)
- static MA_INLINE ma_uint16 __stdcall ma_atomic_fetch_xor_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order)
+ #else
{
- #if defined(MA_ARM)
- MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedXor16, ma_uint16, short);
- #else
- ma_uint16 oldValue;
- ma_uint16 newValue;
- do {
- oldValue = *dst;
- newValue = (ma_uint16)(oldValue ^ src);
- } while (ma_atomic_compare_and_swap_16(dst, oldValue, newValue) != oldValue);
- (void)order;
- return oldValue;
- #endif
+ MA_ATOMIC_FETCH_ADD_LOCK(64, dst, src, order);
}
- #endif
- #if defined(MA_ATOMIC_HAS_32)
- static MA_INLINE ma_uint32 __stdcall ma_atomic_fetch_xor_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order)
+ #endif
+ }
+ static MA_INLINE ma_uint8 __stdcall ma_atomic_fetch_sub_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_8)
{
- #if defined(MA_ARM)
- MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedXor, ma_uint32, long);
- #else
- ma_uint32 oldValue;
- ma_uint32 newValue;
- do {
- oldValue = *dst;
- newValue = oldValue ^ src;
- } while (ma_atomic_compare_and_swap_32(dst, oldValue, newValue) != oldValue);
+ ma_uint8 result = 0;
(void)order;
- return oldValue;
- #endif
+ __asm {
+ mov ecx, dst
+ mov al, src
+ neg al
+ lock xadd [ecx], al
+ mov result, al
+ }
+ return result;
}
- #endif
- #if defined(MA_ATOMIC_HAS_64)
- static MA_INLINE ma_uint64 __stdcall ma_atomic_fetch_xor_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order)
+ #else
{
- #if defined(MA_ARM)
- MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedXor64, ma_uint64, long long);
- #else
- ma_uint64 oldValue;
- ma_uint64 newValue;
- do {
- oldValue = *dst;
- newValue = oldValue ^ src;
- } while (ma_atomic_compare_and_swap_64(dst, oldValue, newValue) != oldValue);
- (void)order;
- return oldValue;
- #endif
+ MA_ATOMIC_FETCH_ADD_LOCK(8, dst, (ma_uint8)(-(ma_int8)src), order);
}
- #endif
- #if defined(MA_ATOMIC_HAS_8)
- static MA_INLINE ma_uint8 __stdcall ma_atomic_fetch_or_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order)
+ #endif
+ }
+ static MA_INLINE ma_uint16 __stdcall ma_atomic_fetch_sub_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_16)
{
- #if defined(MA_ARM)
- MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedOr8, ma_uint8, char);
- #else
- ma_uint8 oldValue;
- ma_uint8 newValue;
- do {
- oldValue = *dst;
- newValue = (ma_uint8)(oldValue | src);
- } while (ma_atomic_compare_and_swap_8(dst, oldValue, newValue) != oldValue);
+ ma_uint16 result = 0;
(void)order;
- return oldValue;
- #endif
+ __asm {
+ mov ecx, dst
+ mov ax, src
+ neg ax
+ lock xadd [ecx], ax
+ mov result, ax
+ }
+ return result;
}
- #endif
- #if defined(MA_ATOMIC_HAS_16)
- static MA_INLINE ma_uint16 __stdcall ma_atomic_fetch_or_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order)
+ #else
{
- #if defined(MA_ARM)
- MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedOr16, ma_uint16, short);
- #else
- ma_uint16 oldValue;
- ma_uint16 newValue;
- do {
- oldValue = *dst;
- newValue = (ma_uint16)(oldValue | src);
- } while (ma_atomic_compare_and_swap_16(dst, oldValue, newValue) != oldValue);
- (void)order;
- return oldValue;
- #endif
+ MA_ATOMIC_FETCH_ADD_LOCK(16, dst, (ma_uint16)(-(ma_int16)src), order);
}
- #endif
- #if defined(MA_ATOMIC_HAS_32)
- static MA_INLINE ma_uint32 __stdcall ma_atomic_fetch_or_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order)
+ #endif
+ }
+ static MA_INLINE ma_uint32 __stdcall ma_atomic_fetch_sub_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_32)
{
- #if defined(MA_ARM)
- MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedOr, ma_uint32, long);
- #else
- ma_uint32 oldValue;
- ma_uint32 newValue;
- do {
- oldValue = *dst;
- newValue = oldValue | src;
- } while (ma_atomic_compare_and_swap_32(dst, oldValue, newValue) != oldValue);
+ ma_uint32 result = 0;
(void)order;
- return oldValue;
- #endif
+ __asm {
+ mov ecx, dst
+ mov eax, src
+ neg eax
+ lock xadd [ecx], eax
+ mov result, eax
+ }
+ return result;
}
- #endif
- #if defined(MA_ATOMIC_HAS_64)
- static MA_INLINE ma_uint64 __stdcall ma_atomic_fetch_or_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order)
+ #else
{
- #if defined(MA_ARM)
- MA_ATOMIC_MSVC_ARM_INTRINSIC(dst, src, order, _InterlockedOr64, ma_uint64, long long);
- #else
- ma_uint64 oldValue;
- ma_uint64 newValue;
- do {
- oldValue = *dst;
- newValue = oldValue | src;
- } while (ma_atomic_compare_and_swap_64(dst, oldValue, newValue) != oldValue);
- (void)order;
- return oldValue;
- #endif
+ MA_ATOMIC_FETCH_ADD_LOCK(32, dst, (ma_uint32)(-(ma_int32)src), order);
}
- #endif
- #if defined(MA_ATOMIC_HAS_8)
- #define ma_atomic_test_and_set_explicit_8( dst, order) ma_atomic_exchange_explicit_8 (dst, 1, order)
- #endif
- #if defined(MA_ATOMIC_HAS_16)
- #define ma_atomic_test_and_set_explicit_16(dst, order) ma_atomic_exchange_explicit_16(dst, 1, order)
- #endif
- #if defined(MA_ATOMIC_HAS_32)
- #define ma_atomic_test_and_set_explicit_32(dst, order) ma_atomic_exchange_explicit_32(dst, 1, order)
- #endif
- #if defined(MA_ATOMIC_HAS_64)
- #define ma_atomic_test_and_set_explicit_64(dst, order) ma_atomic_exchange_explicit_64(dst, 1, order)
- #endif
- #if defined(MA_ATOMIC_HAS_8)
- #define ma_atomic_clear_explicit_8( dst, order) ma_atomic_store_explicit_8 (dst, 0, order)
- #endif
- #if defined(MA_ATOMIC_HAS_16)
- #define ma_atomic_clear_explicit_16(dst, order) ma_atomic_store_explicit_16(dst, 0, order)
- #endif
- #if defined(MA_ATOMIC_HAS_32)
- #define ma_atomic_clear_explicit_32(dst, order) ma_atomic_store_explicit_32(dst, 0, order)
- #endif
- #if defined(MA_ATOMIC_HAS_64)
- #define ma_atomic_clear_explicit_64(dst, order) ma_atomic_store_explicit_64(dst, 0, order)
- #endif
- #if defined(MA_ATOMIC_HAS_8)
- typedef ma_uint8 ma_atomic_flag;
- #define ma_atomic_flag_test_and_set_explicit(ptr, order) (ma_bool32)ma_atomic_test_and_set_explicit_8(ptr, order)
- #define ma_atomic_flag_clear_explicit(ptr, order) ma_atomic_clear_explicit_8(ptr, order)
- #define ma_atomic_flag_load_explicit(ptr, order) ma_atomic_load_explicit_8(ptr, order)
- #else
- typedef ma_uint32 ma_atomic_flag;
- #define ma_atomic_flag_test_and_set_explicit(ptr, order) (ma_bool32)ma_atomic_test_and_set_explicit_32(ptr, order)
- #define ma_atomic_flag_clear_explicit(ptr, order) ma_atomic_clear_explicit_32(ptr, order)
- #define ma_atomic_flag_load_explicit(ptr, order) ma_atomic_load_explicit_32(ptr, order)
- #endif
-#elif defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)))
+ #endif
+ }
+ static MA_INLINE ma_uint64 __stdcall ma_atomic_fetch_sub_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order)
+ {
+ MA_ATOMIC_FETCH_ADD_CAS(64, dst, (ma_uint64)(-(ma_int64)src), order);
+ }
+ static MA_INLINE ma_uint8 __stdcall ma_atomic_fetch_and_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order)
+ {
+ MA_ATOMIC_FETCH_AND_CAS(8, dst, src, order);
+ }
+ static MA_INLINE ma_uint16 __stdcall ma_atomic_fetch_and_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order)
+ {
+ MA_ATOMIC_FETCH_AND_CAS(16, dst, src, order);
+ }
+ static MA_INLINE ma_uint32 __stdcall ma_atomic_fetch_and_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order)
+ {
+ MA_ATOMIC_FETCH_AND_CAS(32, dst, src, order);
+ }
+ static MA_INLINE ma_uint64 __stdcall ma_atomic_fetch_and_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order)
+ {
+ MA_ATOMIC_FETCH_AND_CAS(64, dst, src, order);
+ }
+ static MA_INLINE ma_uint8 __stdcall ma_atomic_fetch_or_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order)
+ {
+ MA_ATOMIC_FETCH_OR_CAS(8, dst, src, order);
+ }
+ static MA_INLINE ma_uint16 __stdcall ma_atomic_fetch_or_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order)
+ {
+ MA_ATOMIC_FETCH_OR_CAS(16, dst, src, order);
+ }
+ static MA_INLINE ma_uint32 __stdcall ma_atomic_fetch_or_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order)
+ {
+ MA_ATOMIC_FETCH_OR_CAS(32, dst, src, order);
+ }
+ static MA_INLINE ma_uint64 __stdcall ma_atomic_fetch_or_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order)
+ {
+ MA_ATOMIC_FETCH_OR_CAS(64, dst, src, order);
+ }
+ static MA_INLINE ma_uint8 __stdcall ma_atomic_fetch_xor_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order)
+ {
+ MA_ATOMIC_FETCH_XOR_CAS(8, dst, src, order);
+ }
+ static MA_INLINE ma_uint16 __stdcall ma_atomic_fetch_xor_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order)
+ {
+ MA_ATOMIC_FETCH_XOR_CAS(16, dst, src, order);
+ }
+ static MA_INLINE ma_uint32 __stdcall ma_atomic_fetch_xor_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order)
+ {
+ MA_ATOMIC_FETCH_XOR_CAS(32, dst, src, order);
+ }
+ static MA_INLINE ma_uint64 __stdcall ma_atomic_fetch_xor_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order)
+ {
+ MA_ATOMIC_FETCH_XOR_CAS(64, dst, src, order);
+ }
+ static MA_INLINE void __stdcall ma_atomic_thread_fence(ma_atomic_memory_order order)
+ {
+ (void)order;
+ __asm {
+ lock add dword ptr [esp], 0
+ }
+ }
+ #define ma_atomic_signal_fence(order) __asm {}; (void)order
+#endif
+#if defined(MA_ATOMIC_MODERN_GCC)
#define MA_ATOMIC_HAS_NATIVE_COMPARE_EXCHANGE
- #define MA_ATOMIC_HAS_NATIVE_IS_LOCK_FREE
- #define ma_atomic_memory_order_relaxed __ATOMIC_RELAXED
- #define ma_atomic_memory_order_consume __ATOMIC_CONSUME
- #define ma_atomic_memory_order_acquire __ATOMIC_ACQUIRE
- #define ma_atomic_memory_order_release __ATOMIC_RELEASE
- #define ma_atomic_memory_order_acq_rel __ATOMIC_ACQ_REL
- #define ma_atomic_memory_order_seq_cst __ATOMIC_SEQ_CST
- #define ma_atomic_compiler_fence() __asm__ __volatile__("":::"memory")
#define ma_atomic_thread_fence(order) __atomic_thread_fence(order)
#define ma_atomic_signal_fence(order) __atomic_signal_fence(order)
#define ma_atomic_is_lock_free_8(ptr) __atomic_is_lock_free(1, ptr)
#define ma_atomic_is_lock_free_16(ptr) __atomic_is_lock_free(2, ptr)
#define ma_atomic_is_lock_free_32(ptr) __atomic_is_lock_free(4, ptr)
#define ma_atomic_is_lock_free_64(ptr) __atomic_is_lock_free(8, ptr)
- #define ma_atomic_test_and_set_explicit_8( dst, order) __atomic_exchange_n(dst, 1, order)
- #define ma_atomic_test_and_set_explicit_16(dst, order) __atomic_exchange_n(dst, 1, order)
- #define ma_atomic_test_and_set_explicit_32(dst, order) __atomic_exchange_n(dst, 1, order)
- #define ma_atomic_test_and_set_explicit_64(dst, order) __atomic_exchange_n(dst, 1, order)
- #define ma_atomic_clear_explicit_8( dst, order) __atomic_store_n(dst, 0, order)
- #define ma_atomic_clear_explicit_16(dst, order) __atomic_store_n(dst, 0, order)
- #define ma_atomic_clear_explicit_32(dst, order) __atomic_store_n(dst, 0, order)
- #define ma_atomic_clear_explicit_64(dst, order) __atomic_store_n(dst, 0, order)
#define ma_atomic_store_explicit_8( dst, src, order) __atomic_store_n(dst, src, order)
#define ma_atomic_store_explicit_16(dst, src, order) __atomic_store_n(dst, src, order)
#define ma_atomic_store_explicit_32(dst, src, order) __atomic_store_n(dst, src, order)
@@ -14864,14 +15773,14 @@ typedef int ma_atomic_memory_order;
#define ma_atomic_exchange_explicit_16(dst, src, order) __atomic_exchange_n(dst, src, order)
#define ma_atomic_exchange_explicit_32(dst, src, order) __atomic_exchange_n(dst, src, order)
#define ma_atomic_exchange_explicit_64(dst, src, order) __atomic_exchange_n(dst, src, order)
- #define ma_atomic_compare_exchange_strong_explicit_8( dst, expected, desired, successOrder, failureOrder) __atomic_compare_exchange_n(dst, expected, desired, 0, successOrder, failureOrder)
- #define ma_atomic_compare_exchange_strong_explicit_16(dst, expected, desired, successOrder, failureOrder) __atomic_compare_exchange_n(dst, expected, desired, 0, successOrder, failureOrder)
- #define ma_atomic_compare_exchange_strong_explicit_32(dst, expected, desired, successOrder, failureOrder) __atomic_compare_exchange_n(dst, expected, desired, 0, successOrder, failureOrder)
- #define ma_atomic_compare_exchange_strong_explicit_64(dst, expected, desired, successOrder, failureOrder) __atomic_compare_exchange_n(dst, expected, desired, 0, successOrder, failureOrder)
- #define ma_atomic_compare_exchange_weak_explicit_8( dst, expected, desired, successOrder, failureOrder) __atomic_compare_exchange_n(dst, expected, desired, 1, successOrder, failureOrder)
- #define ma_atomic_compare_exchange_weak_explicit_16(dst, expected, desired, successOrder, failureOrder) __atomic_compare_exchange_n(dst, expected, desired, 1, successOrder, failureOrder)
- #define ma_atomic_compare_exchange_weak_explicit_32(dst, expected, desired, successOrder, failureOrder) __atomic_compare_exchange_n(dst, expected, desired, 1, successOrder, failureOrder)
- #define ma_atomic_compare_exchange_weak_explicit_64(dst, expected, desired, successOrder, failureOrder) __atomic_compare_exchange_n(dst, expected, desired, 1, successOrder, failureOrder)
+ #define ma_atomic_compare_exchange_strong_explicit_8( dst, expected, replacement, successOrder, failureOrder) __atomic_compare_exchange_n(dst, expected, replacement, 0, successOrder, failureOrder)
+ #define ma_atomic_compare_exchange_strong_explicit_16(dst, expected, replacement, successOrder, failureOrder) __atomic_compare_exchange_n(dst, expected, replacement, 0, successOrder, failureOrder)
+ #define ma_atomic_compare_exchange_strong_explicit_32(dst, expected, replacement, successOrder, failureOrder) __atomic_compare_exchange_n(dst, expected, replacement, 0, successOrder, failureOrder)
+ #define ma_atomic_compare_exchange_strong_explicit_64(dst, expected, replacement, successOrder, failureOrder) __atomic_compare_exchange_n(dst, expected, replacement, 0, successOrder, failureOrder)
+ #define ma_atomic_compare_exchange_weak_explicit_8( dst, expected, replacement, successOrder, failureOrder) __atomic_compare_exchange_n(dst, expected, replacement, 1, successOrder, failureOrder)
+ #define ma_atomic_compare_exchange_weak_explicit_16(dst, expected, replacement, successOrder, failureOrder) __atomic_compare_exchange_n(dst, expected, replacement, 1, successOrder, failureOrder)
+ #define ma_atomic_compare_exchange_weak_explicit_32(dst, expected, replacement, successOrder, failureOrder) __atomic_compare_exchange_n(dst, expected, replacement, 1, successOrder, failureOrder)
+ #define ma_atomic_compare_exchange_weak_explicit_64(dst, expected, replacement, successOrder, failureOrder) __atomic_compare_exchange_n(dst, expected, replacement, 1, successOrder, failureOrder)
#define ma_atomic_fetch_add_explicit_8( dst, src, order) __atomic_fetch_add(dst, src, order)
#define ma_atomic_fetch_add_explicit_16(dst, src, order) __atomic_fetch_add(dst, src, order)
#define ma_atomic_fetch_add_explicit_32(dst, src, order) __atomic_fetch_add(dst, src, order)
@@ -14892,19 +15801,19 @@ typedef int ma_atomic_memory_order;
#define ma_atomic_fetch_and_explicit_16(dst, src, order) __atomic_fetch_and(dst, src, order)
#define ma_atomic_fetch_and_explicit_32(dst, src, order) __atomic_fetch_and(dst, src, order)
#define ma_atomic_fetch_and_explicit_64(dst, src, order) __atomic_fetch_and(dst, src, order)
- static MA_INLINE ma_uint8 ma_atomic_compare_and_swap_8(volatile ma_uint8* dst, ma_uint8 expected, ma_uint8 desired)
+ static MA_INLINE ma_uint8 ma_atomic_compare_and_swap_8(volatile ma_uint8* dst, ma_uint8 expected, ma_uint8 replacement)
{
- __atomic_compare_exchange_n(dst, &expected, desired, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
+ __atomic_compare_exchange_n(dst, &expected, replacement, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
return expected;
}
- static MA_INLINE ma_uint16 ma_atomic_compare_and_swap_16(volatile ma_uint16* dst, ma_uint16 expected, ma_uint16 desired)
+ static MA_INLINE ma_uint16 ma_atomic_compare_and_swap_16(volatile ma_uint16* dst, ma_uint16 expected, ma_uint16 replacement)
{
- __atomic_compare_exchange_n(dst, &expected, desired, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
+ __atomic_compare_exchange_n(dst, &expected, replacement, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
return expected;
}
- static MA_INLINE ma_uint32 ma_atomic_compare_and_swap_32(volatile ma_uint32* dst, ma_uint32 expected, ma_uint32 desired)
+ static MA_INLINE ma_uint32 ma_atomic_compare_and_swap_32(volatile ma_uint32* dst, ma_uint32 expected, ma_uint32 replacement)
{
- __atomic_compare_exchange_n(dst, &expected, desired, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
+ __atomic_compare_exchange_n(dst, &expected, replacement, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
return expected;
}
#if defined(__clang__)
@@ -14913,636 +15822,1134 @@ typedef int ma_atomic_memory_order;
#pragma clang diagnostic ignored "-Watomic-alignment"
#endif
#endif
- static MA_INLINE ma_uint64 ma_atomic_compare_and_swap_64(volatile ma_uint64* dst, ma_uint64 expected, ma_uint64 desired)
+ static MA_INLINE ma_uint64 ma_atomic_compare_and_swap_64(volatile ma_uint64* dst, ma_uint64 expected, ma_uint64 replacement)
{
- __atomic_compare_exchange_n(dst, &expected, desired, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
+ __atomic_compare_exchange_n(dst, &expected, replacement, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
return expected;
}
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
- typedef ma_uint8 ma_atomic_flag;
- #define ma_atomic_flag_test_and_set_explicit(dst, order) (ma_bool32)__atomic_test_and_set(dst, order)
- #define ma_atomic_flag_clear_explicit(dst, order) __atomic_clear(dst, order)
- #define ma_atomic_flag_load_explicit(ptr, order) ma_atomic_load_explicit_8(ptr, order)
-#else
- #define ma_atomic_memory_order_relaxed 1
- #define ma_atomic_memory_order_consume 2
- #define ma_atomic_memory_order_acquire 3
- #define ma_atomic_memory_order_release 4
- #define ma_atomic_memory_order_acq_rel 5
- #define ma_atomic_memory_order_seq_cst 6
- #define ma_atomic_compiler_fence() __asm__ __volatile__("":::"memory")
- #if defined(__GNUC__)
+#endif
+#if defined(MA_ATOMIC_LEGACY_GCC) || defined(MA_ATOMIC_LEGACY_GCC_ASM)
+ #define ma_atomic_signal_fence(order) __asm__ __volatile__("":::"memory")
+ #if defined(MA_ATOMIC_LEGACY_GCC)
#define ma_atomic_thread_fence(order) __sync_synchronize(), (void)order
- static MA_INLINE ma_uint8 ma_atomic_exchange_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order)
+ static MA_INLINE ma_uint8 ma_atomic_compare_and_swap_8(volatile ma_uint8* dst, ma_uint8 expected, ma_uint8 replacement)
{
- if (order > ma_atomic_memory_order_acquire) {
- __sync_synchronize();
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_8)
+ {
+ return __sync_val_compare_and_swap(dst, expected, replacement);
}
- return __sync_lock_test_and_set(dst, src);
+ #else
+ {
+ MA_ATOMIC_COMPARE_AND_SWAP_LOCK(8, dst, expected, replacement);
+ }
+ #endif
}
- static MA_INLINE ma_uint16 ma_atomic_exchange_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order)
+ static MA_INLINE ma_uint16 ma_atomic_compare_and_swap_16(volatile ma_uint16* dst, ma_uint16 expected, ma_uint16 replacement)
{
- ma_uint16 oldValue;
- do {
- oldValue = *dst;
- } while (__sync_val_compare_and_swap(dst, oldValue, src) != oldValue);
- (void)order;
- return oldValue;
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_16)
+ {
+ return __sync_val_compare_and_swap(dst, expected, replacement);
+ }
+ #else
+ {
+ MA_ATOMIC_COMPARE_AND_SWAP_LOCK(16, dst, expected, replacement);
+ }
+ #endif
}
- static MA_INLINE ma_uint32 ma_atomic_exchange_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order)
+ static MA_INLINE ma_uint32 ma_atomic_compare_and_swap_32(volatile ma_uint32* dst, ma_uint32 expected, ma_uint32 replacement)
{
- ma_uint32 oldValue;
- do {
- oldValue = *dst;
- } while (__sync_val_compare_and_swap(dst, oldValue, src) != oldValue);
- (void)order;
- return oldValue;
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_32)
+ {
+ return __sync_val_compare_and_swap(dst, expected, replacement);
+ }
+ #else
+ {
+ MA_ATOMIC_COMPARE_AND_SWAP_LOCK(32, dst, expected, replacement);
+ }
+ #endif
}
- static MA_INLINE ma_uint64 ma_atomic_exchange_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order)
+ static MA_INLINE ma_uint64 ma_atomic_compare_and_swap_64(volatile ma_uint64* dst, ma_uint64 expected, ma_uint64 replacement)
{
- ma_uint64 oldValue;
- do {
- oldValue = *dst;
- } while (__sync_val_compare_and_swap(dst, oldValue, src) != oldValue);
- (void)order;
- return oldValue;
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_64)
+ {
+ return __sync_val_compare_and_swap(dst, expected, replacement);
+ }
+ #else
+ {
+ MA_ATOMIC_COMPARE_AND_SWAP_LOCK(64, dst, expected, replacement);
+ }
+ #endif
}
- static MA_INLINE ma_uint8 ma_atomic_fetch_add_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order)
+ static MA_INLINE ma_uint8 ma_atomic_load_explicit_8(volatile const ma_uint8* ptr, ma_atomic_memory_order order)
{
- (void)order;
- return __sync_fetch_and_add(dst, src);
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_8)
+ {
+ (void)order;
+ return ma_atomic_compare_and_swap_8((ma_uint8*)ptr, 0, 0);
+ }
+ #else
+ {
+ MA_ATOMIC_LOAD_EXPLICIT_LOCK(8, ptr, order);
+ }
+ #endif
}
- static MA_INLINE ma_uint16 ma_atomic_fetch_add_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order)
+ static MA_INLINE ma_uint16 ma_atomic_load_explicit_16(volatile const ma_uint16* ptr, ma_atomic_memory_order order)
{
- (void)order;
- return __sync_fetch_and_add(dst, src);
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_16)
+ {
+ (void)order;
+ return ma_atomic_compare_and_swap_16((ma_uint16*)ptr, 0, 0);
+ }
+ #else
+ {
+ MA_ATOMIC_LOAD_EXPLICIT_LOCK(16, ptr, order);
+ }
+ #endif
}
- static MA_INLINE ma_uint32 ma_atomic_fetch_add_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order)
+ static MA_INLINE ma_uint32 ma_atomic_load_explicit_32(volatile const ma_uint32* ptr, ma_atomic_memory_order order)
{
- (void)order;
- return __sync_fetch_and_add(dst, src);
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_32)
+ {
+ (void)order;
+ return ma_atomic_compare_and_swap_32((ma_uint32*)ptr, 0, 0);
+ }
+ #else
+ {
+ MA_ATOMIC_LOAD_EXPLICIT_LOCK(32, ptr, order);
+ }
+ #endif
}
- static MA_INLINE ma_uint64 ma_atomic_fetch_add_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order)
+ static MA_INLINE ma_uint64 ma_atomic_load_explicit_64(volatile const ma_uint64* ptr, ma_atomic_memory_order order)
{
- (void)order;
- return __sync_fetch_and_add(dst, src);
- }
- static MA_INLINE ma_uint8 ma_atomic_fetch_sub_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order)
- {
- (void)order;
- return __sync_fetch_and_sub(dst, src);
- }
- static MA_INLINE ma_uint16 ma_atomic_fetch_sub_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order)
- {
- (void)order;
- return __sync_fetch_and_sub(dst, src);
- }
- static MA_INLINE ma_uint32 ma_atomic_fetch_sub_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order)
- {
- (void)order;
- return __sync_fetch_and_sub(dst, src);
- }
- static MA_INLINE ma_uint64 ma_atomic_fetch_sub_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order)
- {
- (void)order;
- return __sync_fetch_and_sub(dst, src);
- }
- static MA_INLINE ma_uint8 ma_atomic_fetch_or_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order)
- {
- (void)order;
- return __sync_fetch_and_or(dst, src);
- }
- static MA_INLINE ma_uint16 ma_atomic_fetch_or_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order)
- {
- (void)order;
- return __sync_fetch_and_or(dst, src);
- }
- static MA_INLINE ma_uint32 ma_atomic_fetch_or_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order)
- {
- (void)order;
- return __sync_fetch_and_or(dst, src);
- }
- static MA_INLINE ma_uint64 ma_atomic_fetch_or_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order)
- {
- (void)order;
- return __sync_fetch_and_or(dst, src);
- }
- static MA_INLINE ma_uint8 ma_atomic_fetch_xor_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order)
- {
- (void)order;
- return __sync_fetch_and_xor(dst, src);
- }
- static MA_INLINE ma_uint16 ma_atomic_fetch_xor_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order)
- {
- (void)order;
- return __sync_fetch_and_xor(dst, src);
- }
- static MA_INLINE ma_uint32 ma_atomic_fetch_xor_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order)
- {
- (void)order;
- return __sync_fetch_and_xor(dst, src);
- }
- static MA_INLINE ma_uint64 ma_atomic_fetch_xor_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order)
- {
- (void)order;
- return __sync_fetch_and_xor(dst, src);
- }
- static MA_INLINE ma_uint8 ma_atomic_fetch_and_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order)
- {
- (void)order;
- return __sync_fetch_and_and(dst, src);
- }
- static MA_INLINE ma_uint16 ma_atomic_fetch_and_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order)
- {
- (void)order;
- return __sync_fetch_and_and(dst, src);
- }
- static MA_INLINE ma_uint32 ma_atomic_fetch_and_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order)
- {
- (void)order;
- return __sync_fetch_and_and(dst, src);
- }
- static MA_INLINE ma_uint64 ma_atomic_fetch_and_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order)
- {
- (void)order;
- return __sync_fetch_and_and(dst, src);
- }
- #define ma_atomic_compare_and_swap_8( dst, expected, desired) __sync_val_compare_and_swap(dst, expected, desired)
- #define ma_atomic_compare_and_swap_16(dst, expected, desired) __sync_val_compare_and_swap(dst, expected, desired)
- #define ma_atomic_compare_and_swap_32(dst, expected, desired) __sync_val_compare_and_swap(dst, expected, desired)
- #define ma_atomic_compare_and_swap_64(dst, expected, desired) __sync_val_compare_and_swap(dst, expected, desired)
- #else
- #if defined(MA_X86)
- #define ma_atomic_thread_fence(order) __asm__ __volatile__("lock; addl $0, (%%esp)" ::: "memory", "cc")
- #elif defined(MA_X64)
- #define ma_atomic_thread_fence(order) __asm__ __volatile__("lock; addq $0, (%%rsp)" ::: "memory", "cc")
- #else
- #error Unsupported architecture. Please submit a feature request.
- #endif
- static MA_INLINE ma_uint8 ma_atomic_compare_and_swap_8(volatile ma_uint8* dst, ma_uint8 expected, ma_uint8 desired)
- {
- ma_uint8 result;
- #if defined(MA_X86) || defined(MA_X64)
- __asm__ __volatile__("lock; cmpxchg %3, %0" : "+m"(*dst), "=a"(result) : "a"(expected), "d"(desired) : "cc");
- #else
- #error Unsupported architecture. Please submit a feature request.
- #endif
- return result;
- }
- static MA_INLINE ma_uint16 ma_atomic_compare_and_swap_16(volatile ma_uint16* dst, ma_uint16 expected, ma_uint16 desired)
- {
- ma_uint16 result;
- #if defined(MA_X86) || defined(MA_X64)
- __asm__ __volatile__("lock; cmpxchg %3, %0" : "+m"(*dst), "=a"(result) : "a"(expected), "d"(desired) : "cc");
- #else
- #error Unsupported architecture. Please submit a feature request.
- #endif
- return result;
- }
- static MA_INLINE ma_uint32 ma_atomic_compare_and_swap_32(volatile ma_uint32* dst, ma_uint32 expected, ma_uint32 desired)
- {
- ma_uint32 result;
- #if defined(MA_X86) || defined(MA_X64)
- __asm__ __volatile__("lock; cmpxchg %3, %0" : "+m"(*dst), "=a"(result) : "a"(expected), "d"(desired) : "cc");
- #else
- #error Unsupported architecture. Please submit a feature request.
- #endif
- return result;
- }
- static MA_INLINE ma_uint64 ma_atomic_compare_and_swap_64(volatile ma_uint64* dst, ma_uint64 expected, ma_uint64 desired)
- {
- volatile ma_uint64 result;
- #if defined(MA_X86)
- ma_uint32 resultEAX;
- ma_uint32 resultEDX;
- __asm__ __volatile__("push %%ebx; xchg %5, %%ebx; lock; cmpxchg8b %0; pop %%ebx" : "+m"(*dst), "=a"(resultEAX), "=d"(resultEDX) : "a"(expected & 0xFFFFFFFF), "d"(expected >> 32), "r"(desired & 0xFFFFFFFF), "c"(desired >> 32) : "cc");
- result = ((ma_uint64)resultEDX << 32) | resultEAX;
- #elif defined(MA_X64)
- __asm__ __volatile__("lock; cmpxchg %3, %0" : "+m"(*dst), "=a"(result) : "a"(expected), "d"(desired) : "cc");
- #else
- #error Unsupported architecture. Please submit a feature request.
- #endif
- return result;
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_64)
+ {
+ (void)order;
+ return ma_atomic_compare_and_swap_64((ma_uint64*)ptr, 0, 0);
+ }
+ #else
+ {
+ MA_ATOMIC_LOAD_EXPLICIT_LOCK(64, ptr, order);
+ }
+ #endif
}
static MA_INLINE ma_uint8 ma_atomic_exchange_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order)
{
- ma_uint8 result = 0;
- (void)order;
- #if defined(MA_X86) || defined(MA_X64)
- __asm__ __volatile__("lock; xchg %1, %0" : "+m"(*dst), "=a"(result) : "a"(src));
- #else
- #error Unsupported architecture. Please submit a feature request.
- #endif
- return result;
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_8)
+ {
+ if (order > ma_atomic_memory_order_acquire) {
+ __sync_synchronize();
+ }
+ return __sync_lock_test_and_set(dst, src);
+ }
+ #else
+ {
+ MA_ATOMIC_EXCHANGE_EXPLICIT_LOCK(8, dst, src, order);
+ }
+ #endif
}
static MA_INLINE ma_uint16 ma_atomic_exchange_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order)
{
- ma_uint16 result = 0;
- (void)order;
- #if defined(MA_X86) || defined(MA_X64)
- __asm__ __volatile__("lock; xchg %1, %0" : "+m"(*dst), "=a"(result) : "a"(src));
- #else
- #error Unsupported architecture. Please submit a feature request.
- #endif
- return result;
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_16)
+ {
+ if (order > ma_atomic_memory_order_acquire) {
+ __sync_synchronize();
+ }
+ return __sync_lock_test_and_set(dst, src);
+ }
+ #else
+ {
+ MA_ATOMIC_EXCHANGE_EXPLICIT_LOCK(16, dst, src, order);
+ }
+ #endif
}
static MA_INLINE ma_uint32 ma_atomic_exchange_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order)
{
- ma_uint32 result;
- (void)order;
- #if defined(MA_X86) || defined(MA_X64)
- __asm__ __volatile__("lock; xchg %1, %0" : "+m"(*dst), "=a"(result) : "a"(src));
- #else
- #error Unsupported architecture. Please submit a feature request.
- #endif
- return result;
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_32)
+ {
+ if (order > ma_atomic_memory_order_acquire) {
+ __sync_synchronize();
+ }
+ return __sync_lock_test_and_set(dst, src);
+ }
+ #else
+ {
+ MA_ATOMIC_EXCHANGE_EXPLICIT_LOCK(32, dst, src, order);
+ }
+ #endif
}
static MA_INLINE ma_uint64 ma_atomic_exchange_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order)
{
- ma_uint64 result;
- (void)order;
- #if defined(MA_X86)
- do {
- result = *dst;
- } while (ma_atomic_compare_and_swap_64(dst, result, src) != result);
- #elif defined(MA_X64)
- __asm__ __volatile__("lock; xchg %1, %0" : "+m"(*dst), "=a"(result) : "a"(src));
- #else
- #error Unsupported architecture. Please submit a feature request.
- #endif
- return result;
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_64)
+ {
+ if (order > ma_atomic_memory_order_acquire) {
+ __sync_synchronize();
+ }
+ return __sync_lock_test_and_set(dst, src);
+ }
+ #else
+ {
+ MA_ATOMIC_EXCHANGE_EXPLICIT_LOCK(64, dst, src, order);
+ }
+ #endif
}
+ #define ma_atomic_store_explicit_8( dst, src, order) (void)ma_atomic_exchange_explicit_8 (dst, src, order)
+ #define ma_atomic_store_explicit_16(dst, src, order) (void)ma_atomic_exchange_explicit_16(dst, src, order)
+ #define ma_atomic_store_explicit_32(dst, src, order) (void)ma_atomic_exchange_explicit_32(dst, src, order)
+ #define ma_atomic_store_explicit_64(dst, src, order) (void)ma_atomic_exchange_explicit_64(dst, src, order)
static MA_INLINE ma_uint8 ma_atomic_fetch_add_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order)
{
- ma_uint8 result;
- (void)order;
- #if defined(MA_X86) || defined(MA_X64)
- __asm__ __volatile__("lock; xadd %1, %0" : "+m"(*dst), "=a"(result) : "a"(src) : "cc");
- #else
- #error Unsupported architecture. Please submit a feature request.
- #endif
- return result;
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_8)
+ {
+ (void)order;
+ return __sync_fetch_and_add(dst, src);
+ }
+ #else
+ {
+ MA_ATOMIC_FETCH_ADD_LOCK(8, dst, src, order);
+ }
+ #endif
}
static MA_INLINE ma_uint16 ma_atomic_fetch_add_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order)
{
- ma_uint16 result;
- (void)order;
- #if defined(MA_X86) || defined(MA_X64)
- __asm__ __volatile__("lock; xadd %1, %0" : "+m"(*dst), "=a"(result) : "a"(src) : "cc");
- #else
- #error Unsupported architecture. Please submit a feature request.
- #endif
- return result;
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_16)
+ {
+ (void)order;
+ return __sync_fetch_and_add(dst, src);
+ }
+ #else
+ {
+ MA_ATOMIC_FETCH_ADD_LOCK(16, dst, src, order);
+ }
+ #endif
}
static MA_INLINE ma_uint32 ma_atomic_fetch_add_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order)
{
- ma_uint32 result;
- (void)order;
- #if defined(MA_X86) || defined(MA_X64)
- __asm__ __volatile__("lock; xadd %1, %0" : "+m"(*dst), "=a"(result) : "a"(src) : "cc");
- #else
- #error Unsupported architecture. Please submit a feature request.
- #endif
- return result;
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_32)
+ {
+ (void)order;
+ return __sync_fetch_and_add(dst, src);
+ }
+ #else
+ {
+ MA_ATOMIC_FETCH_ADD_LOCK(32, dst, src, order);
+ }
+ #endif
}
static MA_INLINE ma_uint64 ma_atomic_fetch_add_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order)
{
- #if defined(MA_X86)
- ma_uint64 oldValue;
- ma_uint64 newValue;
- (void)order;
- do {
- oldValue = *dst;
- newValue = oldValue + src;
- } while (ma_atomic_compare_and_swap_64(dst, oldValue, newValue) != oldValue);
- return oldValue;
- #elif defined(MA_X64)
- ma_uint64 result;
- (void)order;
- __asm__ __volatile__("lock; xadd %1, %0" : "+m"(*dst), "=a"(result) : "a"(src) : "cc");
- return result;
- #endif
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_64)
+ {
+ (void)order;
+ return __sync_fetch_and_add(dst, src);
+ }
+ #else
+ {
+ MA_ATOMIC_FETCH_ADD_LOCK(64, dst, src, order);
+ }
+ #endif
}
static MA_INLINE ma_uint8 ma_atomic_fetch_sub_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order)
{
- ma_uint8 oldValue;
- ma_uint8 newValue;
- do {
- oldValue = *dst;
- newValue = (ma_uint8)(oldValue - src);
- } while (ma_atomic_compare_and_swap_8(dst, oldValue, newValue) != oldValue);
- (void)order;
- return oldValue;
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_8)
+ {
+ (void)order;
+ return __sync_fetch_and_sub(dst, src);
+ }
+ #else
+ {
+ MA_ATOMIC_FETCH_ADD_LOCK(8, dst, (ma_uint8)(-(ma_int8)src), order);
+ }
+ #endif
}
static MA_INLINE ma_uint16 ma_atomic_fetch_sub_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order)
{
- ma_uint16 oldValue;
- ma_uint16 newValue;
- do {
- oldValue = *dst;
- newValue = (ma_uint16)(oldValue - src);
- } while (ma_atomic_compare_and_swap_16(dst, oldValue, newValue) != oldValue);
- (void)order;
- return oldValue;
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_16)
+ {
+ (void)order;
+ return __sync_fetch_and_sub(dst, src);
+ }
+ #else
+ {
+ MA_ATOMIC_FETCH_ADD_LOCK(16, dst, (ma_uint16)(-(ma_int16)src), order);
+ }
+ #endif
}
static MA_INLINE ma_uint32 ma_atomic_fetch_sub_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order)
{
- ma_uint32 oldValue;
- ma_uint32 newValue;
- do {
- oldValue = *dst;
- newValue = oldValue - src;
- } while (ma_atomic_compare_and_swap_32(dst, oldValue, newValue) != oldValue);
- (void)order;
- return oldValue;
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_32)
+ {
+ (void)order;
+ return __sync_fetch_and_sub(dst, src);
+ }
+ #else
+ {
+ MA_ATOMIC_FETCH_ADD_LOCK(32, dst, (ma_uint32)(-(ma_int32)src), order);
+ }
+ #endif
}
static MA_INLINE ma_uint64 ma_atomic_fetch_sub_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order)
{
- ma_uint64 oldValue;
- ma_uint64 newValue;
- do {
- oldValue = *dst;
- newValue = oldValue - src;
- } while (ma_atomic_compare_and_swap_64(dst, oldValue, newValue) != oldValue);
- (void)order;
- return oldValue;
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_64)
+ {
+ (void)order;
+ return __sync_fetch_and_sub(dst, src);
+ }
+ #else
+ {
+ MA_ATOMIC_FETCH_ADD_LOCK(64, dst, (ma_uint64)(-(ma_int64)src), order);
+ }
+ #endif
}
static MA_INLINE ma_uint8 ma_atomic_fetch_and_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order)
{
- ma_uint8 oldValue;
- ma_uint8 newValue;
- do {
- oldValue = *dst;
- newValue = (ma_uint8)(oldValue & src);
- } while (ma_atomic_compare_and_swap_8(dst, oldValue, newValue) != oldValue);
- (void)order;
- return oldValue;
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_8)
+ {
+ (void)order;
+ return __sync_fetch_and_and(dst, src);
+ }
+ #else
+ {
+ MA_ATOMIC_FETCH_AND_CAS(8, dst, src, order);
+ }
+ #endif
}
static MA_INLINE ma_uint16 ma_atomic_fetch_and_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order)
{
- ma_uint16 oldValue;
- ma_uint16 newValue;
- do {
- oldValue = *dst;
- newValue = (ma_uint16)(oldValue & src);
- } while (ma_atomic_compare_and_swap_16(dst, oldValue, newValue) != oldValue);
- (void)order;
- return oldValue;
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_16)
+ {
+ (void)order;
+ return __sync_fetch_and_and(dst, src);
+ }
+ #else
+ {
+ MA_ATOMIC_FETCH_AND_CAS(16, dst, src, order);
+ }
+ #endif
}
static MA_INLINE ma_uint32 ma_atomic_fetch_and_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order)
{
- ma_uint32 oldValue;
- ma_uint32 newValue;
- do {
- oldValue = *dst;
- newValue = oldValue & src;
- } while (ma_atomic_compare_and_swap_32(dst, oldValue, newValue) != oldValue);
- (void)order;
- return oldValue;
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_32)
+ {
+ (void)order;
+ return __sync_fetch_and_and(dst, src);
+ }
+ #else
+ {
+ MA_ATOMIC_FETCH_AND_CAS(32, dst, src, order);
+ }
+ #endif
}
static MA_INLINE ma_uint64 ma_atomic_fetch_and_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order)
{
- ma_uint64 oldValue;
- ma_uint64 newValue;
- do {
- oldValue = *dst;
- newValue = oldValue & src;
- } while (ma_atomic_compare_and_swap_64(dst, oldValue, newValue) != oldValue);
- (void)order;
- return oldValue;
- }
- static MA_INLINE ma_uint8 ma_atomic_fetch_xor_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order)
- {
- ma_uint8 oldValue;
- ma_uint8 newValue;
- do {
- oldValue = *dst;
- newValue = (ma_uint8)(oldValue ^ src);
- } while (ma_atomic_compare_and_swap_8(dst, oldValue, newValue) != oldValue);
- (void)order;
- return oldValue;
- }
- static MA_INLINE ma_uint16 ma_atomic_fetch_xor_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order)
- {
- ma_uint16 oldValue;
- ma_uint16 newValue;
- do {
- oldValue = *dst;
- newValue = (ma_uint16)(oldValue ^ src);
- } while (ma_atomic_compare_and_swap_16(dst, oldValue, newValue) != oldValue);
- (void)order;
- return oldValue;
- }
- static MA_INLINE ma_uint32 ma_atomic_fetch_xor_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order)
- {
- ma_uint32 oldValue;
- ma_uint32 newValue;
- do {
- oldValue = *dst;
- newValue = oldValue ^ src;
- } while (ma_atomic_compare_and_swap_32(dst, oldValue, newValue) != oldValue);
- (void)order;
- return oldValue;
- }
- static MA_INLINE ma_uint64 ma_atomic_fetch_xor_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order)
- {
- ma_uint64 oldValue;
- ma_uint64 newValue;
- do {
- oldValue = *dst;
- newValue = oldValue ^ src;
- } while (ma_atomic_compare_and_swap_64(dst, oldValue, newValue) != oldValue);
- (void)order;
- return oldValue;
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_64)
+ {
+ (void)order;
+ return __sync_fetch_and_and(dst, src);
+ }
+ #else
+ {
+ MA_ATOMIC_FETCH_AND_CAS(64, dst, src, order);
+ }
+ #endif
}
static MA_INLINE ma_uint8 ma_atomic_fetch_or_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order)
{
- ma_uint8 oldValue;
- ma_uint8 newValue;
- do {
- oldValue = *dst;
- newValue = (ma_uint8)(oldValue | src);
- } while (ma_atomic_compare_and_swap_8(dst, oldValue, newValue) != oldValue);
- (void)order;
- return oldValue;
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_8)
+ {
+ (void)order;
+ return __sync_fetch_and_or(dst, src);
+ }
+ #else
+ {
+ MA_ATOMIC_FETCH_OR_CAS(8, dst, src, order);
+ }
+ #endif
}
static MA_INLINE ma_uint16 ma_atomic_fetch_or_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order)
{
- ma_uint16 oldValue;
- ma_uint16 newValue;
- do {
- oldValue = *dst;
- newValue = (ma_uint16)(oldValue | src);
- } while (ma_atomic_compare_and_swap_16(dst, oldValue, newValue) != oldValue);
- (void)order;
- return oldValue;
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_16)
+ {
+ (void)order;
+ return __sync_fetch_and_or(dst, src);
+ }
+ #else
+ {
+ MA_ATOMIC_FETCH_OR_CAS(16, dst, src, order);
+ }
+ #endif
}
static MA_INLINE ma_uint32 ma_atomic_fetch_or_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order)
{
- ma_uint32 oldValue;
- ma_uint32 newValue;
- do {
- oldValue = *dst;
- newValue = oldValue | src;
- } while (ma_atomic_compare_and_swap_32(dst, oldValue, newValue) != oldValue);
- (void)order;
- return oldValue;
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_32)
+ {
+ (void)order;
+ return __sync_fetch_and_or(dst, src);
+ }
+ #else
+ {
+ MA_ATOMIC_FETCH_OR_CAS(32, dst, src, order);
+ }
+ #endif
}
static MA_INLINE ma_uint64 ma_atomic_fetch_or_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order)
{
- ma_uint64 oldValue;
- ma_uint64 newValue;
- do {
- oldValue = *dst;
- newValue = oldValue | src;
- } while (ma_atomic_compare_and_swap_64(dst, oldValue, newValue) != oldValue);
- (void)order;
- return oldValue;
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_64)
+ {
+ (void)order;
+ return __sync_fetch_and_or(dst, src);
+ }
+ #else
+ {
+ MA_ATOMIC_FETCH_OR_CAS(64, dst, src, order);
+ }
+ #endif
}
+ static MA_INLINE ma_uint8 ma_atomic_fetch_xor_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_8)
+ {
+ (void)order;
+ return __sync_fetch_and_xor(dst, src);
+ }
+ #else
+ {
+ MA_ATOMIC_FETCH_XOR_CAS(8, dst, src, order);
+ }
+ #endif
+ }
+ static MA_INLINE ma_uint16 ma_atomic_fetch_xor_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_16)
+ {
+ (void)order;
+ return __sync_fetch_and_xor(dst, src);
+ }
+ #else
+ {
+ MA_ATOMIC_FETCH_XOR_CAS(16, dst, src, order);
+ }
+ #endif
+ }
+ static MA_INLINE ma_uint32 ma_atomic_fetch_xor_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_32)
+ {
+ (void)order;
+ return __sync_fetch_and_xor(dst, src);
+ }
+ #else
+ {
+ MA_ATOMIC_FETCH_XOR_CAS(32, dst, src, order);
+ }
+ #endif
+ }
+ static MA_INLINE ma_uint64 ma_atomic_fetch_xor_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_64)
+ {
+ (void)order;
+ return __sync_fetch_and_xor(dst, src);
+ }
+ #else
+ {
+ MA_ATOMIC_FETCH_XOR_CAS(64, dst, src, order);
+ }
+ #endif
+ }
+ #elif defined(MA_ATOMIC_LEGACY_GCC_ASM)
+ #define MA_ATOMIC_CMPXCHG_GCC_X86(instructionSizeSuffix, result, dst, expected, replacement) \
+ __asm__ __volatile__( \
+ "lock; cmpxchg"instructionSizeSuffix" %2, %1" \
+ : "=a"(result), \
+ "=m"(*dst) \
+ : "r"(replacement), \
+ "0"(expected), \
+ "m"(*dst) \
+ : "cc", "memory")
+ #define MA_ATOMIC_XADD_GCC_X86(instructionSizeSuffix, result, dst, src) \
+ __asm__ __volatile__( \
+ "lock; xadd"instructionSizeSuffix" %0, %1" \
+ : "=a"(result), \
+ "=m"(*dst) \
+ : "0"(src), \
+ "m"(*dst) \
+ : "cc", "memory")
+ static MA_INLINE ma_uint8 ma_atomic_compare_and_swap_8(volatile ma_uint8* dst, ma_uint8 expected, ma_uint8 replacement)
+ {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_8) && (defined(MA_X86) || defined(MA_X64))
+ {
+ ma_uint8 result;
+ #if defined(MA_X86) || defined(MA_X64)
+ {
+ MA_ATOMIC_CMPXCHG_GCC_X86("b", result, dst, expected, replacement);
+ }
+ #else
+ {
+ #error Unsupported architecture.
+ }
+ #endif
+ return result;
+ }
+ #else
+ {
+ MA_ATOMIC_COMPARE_AND_SWAP_LOCK(8, dst, expected, replacement);
+ }
+ #endif
+ }
+ static MA_INLINE ma_uint16 ma_atomic_compare_and_swap_16(volatile ma_uint16* dst, ma_uint16 expected, ma_uint16 replacement)
+ {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_16) && (defined(MA_X86) || defined(MA_X64))
+ {
+ ma_uint16 result;
+ #if defined(MA_X86) || defined(MA_X64)
+ {
+ MA_ATOMIC_CMPXCHG_GCC_X86("w", result, dst, expected, replacement);
+ }
+ #else
+ {
+ #error Unsupported architecture.
+ }
+ #endif
+ return result;
+ }
+ #else
+ {
+ MA_ATOMIC_COMPARE_AND_SWAP_LOCK(16, dst, expected, replacement);
+ }
+ #endif
+ }
+ static MA_INLINE ma_uint32 ma_atomic_compare_and_swap_32(volatile ma_uint32* dst, ma_uint32 expected, ma_uint32 replacement)
+ {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_32) && (defined(MA_X86) || defined(MA_X64))
+ {
+ ma_uint32 result;
+ #if defined(MA_X86) || defined(MA_X64)
+ {
+ MA_ATOMIC_CMPXCHG_GCC_X86("l", result, dst, expected, replacement);
+ }
+ #else
+ {
+ #error Unsupported architecture.
+ }
+ #endif
+ return result;
+ }
+ #else
+ {
+ MA_ATOMIC_COMPARE_AND_SWAP_LOCK(32, dst, expected, replacement);
+ }
+ #endif
+ }
+ static MA_INLINE ma_uint64 ma_atomic_compare_and_swap_64(volatile ma_uint64* dst, ma_uint64 expected, ma_uint64 replacement)
+ {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_64) && (defined(MA_X86) || defined(MA_X64))
+ {
+ ma_uint64 result;
+ #if defined(MA_X86)
+ {
+ ma_uint32 resultEAX;
+ ma_uint32 resultEDX;
+ __asm__ __volatile__(
+ "pushl %%ebx\n"
+ "movl %4, %%ebx\n"
+ "lock cmpxchg8b (%%edi)\n"
+ "popl %%ebx\n"
+ : "=a"(resultEAX),
+ "=d"(resultEDX)
+ : "a"((ma_uint32)(expected & 0xFFFFFFFF)),
+ "d"((ma_uint32)(expected >> 32)),
+ "r"((ma_uint32)(replacement & 0xFFFFFFFF)),
+ "c"((ma_uint32)(replacement >> 32)),
+ "D"(dst)
+ : "memory", "cc");
+ result = ((ma_uint64)resultEDX << 32) | resultEAX;
+ }
+ #elif defined(MA_X64)
+ {
+ MA_ATOMIC_CMPXCHG_GCC_X86("q", result, dst, expected, replacement);
+ }
+ #else
+ {
+ #error Unsupported architecture.
+ }
+ #endif
+ return result;
+ }
+ #else
+ {
+ MA_ATOMIC_COMPARE_AND_SWAP_LOCK(64, dst, expected, replacement);
+ }
+ #endif
+ }
+ static MA_INLINE ma_uint8 ma_atomic_load_explicit_8(volatile const ma_uint8* dst, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_8) && (defined(MA_X86) || defined(MA_X64))
+ {
+ ma_uint8 result;
+ #if defined(MA_X86) || defined(MA_X64)
+ {
+ if (order == ma_atomic_memory_order_relaxed) {
+ MA_ATOMIC_LOAD_RELAXED_GCC_X86("b", result, dst);
+ } else if (order <= ma_atomic_memory_order_release) {
+ MA_ATOMIC_LOAD_RELEASE_GCC_X86("b", result, dst);
+ } else {
+ MA_ATOMIC_LOAD_SEQ_CST_GCC_X86("b", result, dst);
+ }
+ }
+ #else
+ {
+ #error Unsupported architecture.
+ }
+ #endif
+ return result;
+ }
+ #else
+ {
+ MA_ATOMIC_LOAD_EXPLICIT_LOCK(8, dst, order);
+ }
+ #endif
+ }
+ static MA_INLINE ma_uint16 ma_atomic_load_explicit_16(volatile const ma_uint16* dst, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_16) && (defined(MA_X86) || defined(MA_X64))
+ {
+ ma_uint16 result;
+ #if defined(MA_X86) || defined(MA_X64)
+ {
+ if (order == ma_atomic_memory_order_relaxed) {
+ MA_ATOMIC_LOAD_RELAXED_GCC_X86("w", result, dst);
+ } else if (order <= ma_atomic_memory_order_release) {
+ MA_ATOMIC_LOAD_RELEASE_GCC_X86("w", result, dst);
+ } else {
+ MA_ATOMIC_LOAD_SEQ_CST_GCC_X86("w", result, dst);
+ }
+ }
+ #else
+ {
+ #error Unsupported architecture.
+ }
+ #endif
+ return result;
+ }
+ #else
+ {
+ MA_ATOMIC_LOAD_EXPLICIT_LOCK(16, dst, order);
+ }
+ #endif
+ }
+ static MA_INLINE ma_uint32 ma_atomic_load_explicit_32(volatile const ma_uint32* dst, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_32) && (defined(MA_X86) || defined(MA_X64))
+ {
+ ma_uint32 result;
+ #if defined(MA_X86) || defined(MA_X64)
+ {
+ if (order == ma_atomic_memory_order_relaxed) {
+ MA_ATOMIC_LOAD_RELAXED_GCC_X86("l", result, dst);
+ } else if (order <= ma_atomic_memory_order_release) {
+ MA_ATOMIC_LOAD_RELEASE_GCC_X86("l", result, dst);
+ } else {
+ MA_ATOMIC_LOAD_SEQ_CST_GCC_X86("l", result, dst);
+ }
+ }
+ #else
+ {
+ #error Unsupported architecture.
+ }
+ #endif
+ return result;
+ }
+ #else
+ {
+ MA_ATOMIC_LOAD_EXPLICIT_LOCK(32, dst, order);
+ }
+ #endif
+ }
+ static MA_INLINE ma_uint64 ma_atomic_load_explicit_64(volatile const ma_uint64* dst, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_64) && (defined(MA_X86) || defined(MA_X64))
+ {
+ ma_uint64 result;
+ #if defined(MA_X64)
+ {
+ if (order == ma_atomic_memory_order_relaxed) {
+ MA_ATOMIC_LOAD_RELAXED_GCC_X86("q", result, dst);
+ } else if (order <= ma_atomic_memory_order_release) {
+ MA_ATOMIC_LOAD_RELEASE_GCC_X86("q", result, dst);
+ } else {
+ MA_ATOMIC_LOAD_SEQ_CST_GCC_X86("q", result, dst);
+ }
+ }
+ #elif defined(MA_X86)
+ {
+ (void)order;
+ return ma_atomic_compare_and_swap_64((volatile ma_uint64*)dst, 0, 0);
+ }
+ #else
+ {
+ #error Unsupported architecture.
+ }
+ #endif
+ return result;
+ }
+ #else
+ {
+ MA_ATOMIC_LOAD_EXPLICIT_LOCK(64, dst, order);
+ }
+ #endif
+ }
+ static MA_INLINE ma_uint8 ma_atomic_exchange_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_8) && (defined(MA_X86) || defined(MA_X64))
+ {
+ ma_uint8 result;
+ (void)order;
+ #if defined(MA_X86) || defined(MA_X64)
+ {
+ MA_ATOMIC_XCHG_GCC_X86("b", result, dst, src);
+ }
+ #else
+ {
+ #error Unsupported architecture.
+ }
+ #endif
+ return result;
+ }
+ #else
+ {
+ MA_ATOMIC_EXCHANGE_EXPLICIT_LOCK(8, dst, src, order);
+ }
+ #endif
+ }
+ static MA_INLINE ma_uint16 ma_atomic_exchange_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_16) && (defined(MA_X86) || defined(MA_X64))
+ {
+ ma_uint16 result;
+ (void)order;
+ #if defined(MA_X86) || defined(MA_X64)
+ {
+ MA_ATOMIC_XCHG_GCC_X86("w", result, dst, src);
+ }
+ #else
+ {
+ #error Unsupported architecture.
+ }
+ #endif
+ return result;
+ }
+ #else
+ {
+ MA_ATOMIC_EXCHANGE_EXPLICIT_LOCK(16, dst, src, order);
+ }
+ #endif
+ }
+ static MA_INLINE ma_uint32 ma_atomic_exchange_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_32) && (defined(MA_X86) || defined(MA_X64))
+ {
+ ma_uint32 result;
+ (void)order;
+ #if defined(MA_X86) || defined(MA_X64)
+ {
+ MA_ATOMIC_XCHG_GCC_X86("l", result, dst, src);
+ }
+ #else
+ {
+ #error Unsupported architecture.
+ }
+ #endif
+ return result;
+ }
+ #else
+ {
+ MA_ATOMIC_EXCHANGE_EXPLICIT_LOCK(32, dst, src, order);
+ }
+ #endif
+ }
+ static MA_INLINE ma_uint64 ma_atomic_exchange_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_64) && (defined(MA_X86) || defined(MA_X64))
+ {
+ ma_uint64 result;
+ (void)order;
+ #if defined(MA_X86)
+ {
+ MA_ATOMIC_EXCHANGE_EXPLICIT_CAS(64, dst, src, order);
+ }
+ #elif defined(MA_X64)
+ {
+ MA_ATOMIC_XCHG_GCC_X86("q", result, dst, src);
+ }
+ #else
+ {
+ #error Unsupported architecture.
+ }
+ #endif
+ return result;
+ }
+ #else
+ {
+ MA_ATOMIC_EXCHANGE_EXPLICIT_LOCK(64, dst, src, order);
+ }
+ #endif
+ }
+ static MA_INLINE void ma_atomic_store_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_8) && (defined(MA_X86) || defined(MA_X64))
+ {
+ #if defined(MA_X86) || defined(MA_X64)
+ {
+ if (order == ma_atomic_memory_order_relaxed) {
+ __asm__ __volatile__ (
+ "movb %1, %0"
+ : "=m"(*dst)
+ : "r"(src)
+ );
+ } else {
+ __asm__ __volatile__ (
+ "xchgb %1, %0"
+ : "=m"(*dst)
+ : "r"(src)
+ : "memory"
+ );
+ }
+ }
+ #else
+ {
+ #error Unsupported architecture.
+ }
+ #endif
+ }
+ #else
+ {
+ MA_ATOMIC_STORE_EXPLICIT_LOCK(8, dst, src, order);
+ }
+ #endif
+ }
+ static MA_INLINE void ma_atomic_store_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_16) && (defined(MA_X86) || defined(MA_X64))
+ {
+ #if defined(MA_X86) || defined(MA_X64)
+ {
+ if (order == ma_atomic_memory_order_relaxed) {
+ __asm__ __volatile__ (
+ "movw %1, %0"
+ : "=m"(*dst)
+ : "r"(src)
+ );
+ } else {
+ __asm__ __volatile__ (
+ "xchgw %1, %0"
+ : "=m"(*dst)
+ : "r"(src)
+ : "memory"
+ );
+ }
+ }
+ #else
+ {
+ #error Unsupported architecture.
+ }
+ #endif
+ }
+ #else
+ {
+ MA_ATOMIC_STORE_EXPLICIT_LOCK(16, dst, src, order);
+ }
+ #endif
+ }
+ static MA_INLINE void ma_atomic_store_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_32) && (defined(MA_X86) || defined(MA_X64))
+ {
+ #if defined(MA_X86) || defined(MA_X64)
+ {
+ if (order == ma_atomic_memory_order_relaxed) {
+ __asm__ __volatile__ (
+ "movl %1, %0"
+ : "=m"(*dst)
+ : "r"(src)
+ );
+ } else {
+ __asm__ __volatile__ (
+ "xchgl %1, %0"
+ : "=m"(*dst)
+ : "r"(src)
+ : "memory"
+ );
+ }
+ }
+ #else
+ {
+ #error Unsupported architecture.
+ }
+ #endif
+ }
+ #else
+ {
+ MA_ATOMIC_STORE_EXPLICIT_LOCK(32, dst, src, order);
+ }
+ #endif
+ }
+ static MA_INLINE void ma_atomic_store_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_64) && (defined(MA_X86) || defined(MA_X64))
+ {
+ #if defined(MA_X64)
+ {
+ if (order == ma_atomic_memory_order_relaxed) {
+ __asm__ __volatile__ (
+ "movq %1, %0"
+ : "=m"(*dst)
+ : "r"(src)
+ );
+ } else {
+ __asm__ __volatile__ (
+ "xchgq %1, %0"
+ : "=m"(*dst)
+ : "r"(src)
+ : "memory"
+ );
+ }
+ }
+ #else
+ {
+ MA_ATOMIC_STORE_EXPLICIT_CAS(64, dst, src, order);
+ }
+ #endif
+ }
+ #else
+ {
+ MA_ATOMIC_STORE_EXPLICIT_LOCK(64, dst, src, order);
+ }
+ #endif
+ }
+ static MA_INLINE ma_uint8 ma_atomic_fetch_add_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_8) && (defined(MA_X86) || defined(MA_X64))
+ {
+ #if defined(MA_X86) || defined(MA_X64)
+ {
+ ma_uint8 result;
+ (void)order;
+ MA_ATOMIC_XADD_GCC_X86("b", result, dst, src);
+ return result;
+ }
+ #else
+ {
+ #error Unsupported architecture.
+ }
+ #endif
+ }
+ #else
+ {
+ MA_ATOMIC_FETCH_ADD_LOCK(8, dst, src, order);
+ }
+ #endif
+ }
+ static MA_INLINE ma_uint16 ma_atomic_fetch_add_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_16) && (defined(MA_X86) || defined(MA_X64))
+ {
+ #if defined(MA_X86) || defined(MA_X64)
+ {
+ ma_uint16 result;
+ (void)order;
+ MA_ATOMIC_XADD_GCC_X86("w", result, dst, src);
+ return result;
+ }
+ #else
+ {
+ #error Unsupported architecture.
+ }
+ #endif
+ }
+ #else
+ {
+ MA_ATOMIC_FETCH_ADD_LOCK(16, dst, src, order);
+ }
+ #endif
+ }
+ static MA_INLINE ma_uint32 ma_atomic_fetch_add_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_32) && (defined(MA_X86) || defined(MA_X64))
+ {
+ #if defined(MA_X86) || defined(MA_X64)
+ {
+ ma_uint32 result;
+ (void)order;
+ MA_ATOMIC_XADD_GCC_X86("l", result, dst, src);
+ return result;
+ }
+ #else
+ {
+ #error Unsupported architecture.
+ }
+ #endif
+ }
+ #else
+ {
+ MA_ATOMIC_FETCH_ADD_LOCK(32, dst, src, order);
+ }
+ #endif
+ }
+ static MA_INLINE ma_uint64 ma_atomic_fetch_add_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order)
+ {
+ #if defined(MA_ATOMIC_IS_LOCK_FREE_64) && (defined(MA_X86) || defined(MA_X64))
+ {
+ #if defined(MA_X86)
+ {
+ MA_ATOMIC_FETCH_ADD_CAS(64, dst, src, order);
+ }
+ #elif defined(MA_X64)
+ {
+ ma_uint64 result;
+ MA_ATOMIC_XADD_GCC_X86("q", result, dst, src);
+ (void)order;
+ return result;
+ }
+ #else
+ {
+ #error Unsupported architecture.
+ }
+ #endif
+ }
+ #else
+ {
+ MA_ATOMIC_FETCH_ADD_LOCK(64, dst, src, order);
+ }
+ #endif
+ }
+ static MA_INLINE ma_uint8 ma_atomic_fetch_sub_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order)
+ {
+ return ma_atomic_fetch_add_explicit_8(dst, (ma_uint8)(-(ma_int8)src), order);
+ }
+ static MA_INLINE ma_uint16 ma_atomic_fetch_sub_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order)
+ {
+ return ma_atomic_fetch_add_explicit_16(dst, (ma_uint16)(-(ma_int16)src), order);
+ }
+ static MA_INLINE ma_uint32 ma_atomic_fetch_sub_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order)
+ {
+ return ma_atomic_fetch_add_explicit_32(dst, (ma_uint32)(-(ma_int32)src), order);
+ }
+ static MA_INLINE ma_uint64 ma_atomic_fetch_sub_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order)
+ {
+ return ma_atomic_fetch_add_explicit_64(dst, (ma_uint64)(-(ma_int64)src), order);
+ }
+ static MA_INLINE ma_uint8 ma_atomic_fetch_and_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order)
+ {
+ MA_ATOMIC_FETCH_AND_CAS(8, dst, src, order);
+ }
+ static MA_INLINE ma_uint16 ma_atomic_fetch_and_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order)
+ {
+ MA_ATOMIC_FETCH_AND_CAS(16, dst, src, order);
+ }
+ static MA_INLINE ma_uint32 ma_atomic_fetch_and_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order)
+ {
+ MA_ATOMIC_FETCH_AND_CAS(32, dst, src, order);
+ }
+ static MA_INLINE ma_uint64 ma_atomic_fetch_and_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order)
+ {
+ MA_ATOMIC_FETCH_AND_CAS(64, dst, src, order);
+ }
+ static MA_INLINE ma_uint8 ma_atomic_fetch_or_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order)
+ {
+ MA_ATOMIC_FETCH_OR_CAS(8, dst, src, order);
+ }
+ static MA_INLINE ma_uint16 ma_atomic_fetch_or_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order)
+ {
+ MA_ATOMIC_FETCH_OR_CAS(16, dst, src, order);
+ }
+ static MA_INLINE ma_uint32 ma_atomic_fetch_or_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order)
+ {
+ MA_ATOMIC_FETCH_OR_CAS(32, dst, src, order);
+ }
+ static MA_INLINE ma_uint64 ma_atomic_fetch_or_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order)
+ {
+ MA_ATOMIC_FETCH_OR_CAS(64, dst, src, order);
+ }
+ static MA_INLINE ma_uint8 ma_atomic_fetch_xor_explicit_8(volatile ma_uint8* dst, ma_uint8 src, ma_atomic_memory_order order)
+ {
+ MA_ATOMIC_FETCH_XOR_CAS(8, dst, src, order);
+ }
+ static MA_INLINE ma_uint16 ma_atomic_fetch_xor_explicit_16(volatile ma_uint16* dst, ma_uint16 src, ma_atomic_memory_order order)
+ {
+ MA_ATOMIC_FETCH_XOR_CAS(16, dst, src, order);
+ }
+ static MA_INLINE ma_uint32 ma_atomic_fetch_xor_explicit_32(volatile ma_uint32* dst, ma_uint32 src, ma_atomic_memory_order order)
+ {
+ MA_ATOMIC_FETCH_XOR_CAS(32, dst, src, order);
+ }
+ static MA_INLINE ma_uint64 ma_atomic_fetch_xor_explicit_64(volatile ma_uint64* dst, ma_uint64 src, ma_atomic_memory_order order)
+ {
+ MA_ATOMIC_FETCH_XOR_CAS(64, dst, src, order);
+ }
+ #else
+ #error Unsupported compiler.
#endif
- #define ma_atomic_signal_fence(order) ma_atomic_thread_fence(order)
- static MA_INLINE ma_uint8 ma_atomic_load_explicit_8(volatile const ma_uint8* ptr, ma_atomic_memory_order order)
- {
- (void)order;
- return ma_atomic_compare_and_swap_8((ma_uint8*)ptr, 0, 0);
- }
- static MA_INLINE ma_uint16 ma_atomic_load_explicit_16(volatile const ma_uint16* ptr, ma_atomic_memory_order order)
- {
- (void)order;
- return ma_atomic_compare_and_swap_16((ma_uint16*)ptr, 0, 0);
- }
- static MA_INLINE ma_uint32 ma_atomic_load_explicit_32(volatile const ma_uint32* ptr, ma_atomic_memory_order order)
- {
- (void)order;
- return ma_atomic_compare_and_swap_32((ma_uint32*)ptr, 0, 0);
- }
- static MA_INLINE ma_uint64 ma_atomic_load_explicit_64(volatile const ma_uint64* ptr, ma_atomic_memory_order order)
- {
- (void)order;
- return ma_atomic_compare_and_swap_64((ma_uint64*)ptr, 0, 0);
- }
- #define ma_atomic_store_explicit_8( dst, src, order) (void)ma_atomic_exchange_explicit_8 (dst, src, order)
- #define ma_atomic_store_explicit_16(dst, src, order) (void)ma_atomic_exchange_explicit_16(dst, src, order)
- #define ma_atomic_store_explicit_32(dst, src, order) (void)ma_atomic_exchange_explicit_32(dst, src, order)
- #define ma_atomic_store_explicit_64(dst, src, order) (void)ma_atomic_exchange_explicit_64(dst, src, order)
- #define ma_atomic_test_and_set_explicit_8( dst, order) ma_atomic_exchange_explicit_8 (dst, 1, order)
- #define ma_atomic_test_and_set_explicit_16(dst, order) ma_atomic_exchange_explicit_16(dst, 1, order)
- #define ma_atomic_test_and_set_explicit_32(dst, order) ma_atomic_exchange_explicit_32(dst, 1, order)
- #define ma_atomic_test_and_set_explicit_64(dst, order) ma_atomic_exchange_explicit_64(dst, 1, order)
- #define ma_atomic_clear_explicit_8( dst, order) ma_atomic_store_explicit_8 (dst, 0, order)
- #define ma_atomic_clear_explicit_16(dst, order) ma_atomic_store_explicit_16(dst, 0, order)
- #define ma_atomic_clear_explicit_32(dst, order) ma_atomic_store_explicit_32(dst, 0, order)
- #define ma_atomic_clear_explicit_64(dst, order) ma_atomic_store_explicit_64(dst, 0, order)
- typedef ma_uint8 ma_atomic_flag;
- #define ma_atomic_flag_test_and_set_explicit(ptr, order) (ma_bool32)ma_atomic_test_and_set_explicit_8(ptr, order)
- #define ma_atomic_flag_clear_explicit(ptr, order) ma_atomic_clear_explicit_8(ptr, order)
- #define ma_atomic_flag_load_explicit(ptr, order) ma_atomic_load_explicit_8(ptr, order)
#endif
#if !defined(MA_ATOMIC_HAS_NATIVE_COMPARE_EXCHANGE)
- #if defined(MA_ATOMIC_HAS_8)
- static MA_INLINE ma_bool32 ma_atomic_compare_exchange_strong_explicit_8(volatile ma_uint8* dst, ma_uint8* expected, ma_uint8 desired, ma_atomic_memory_order successOrder, ma_atomic_memory_order failureOrder)
- {
- ma_uint8 expectedValue;
- ma_uint8 result;
- (void)successOrder;
- (void)failureOrder;
- expectedValue = ma_atomic_load_explicit_8(expected, ma_atomic_memory_order_seq_cst);
- result = ma_atomic_compare_and_swap_8(dst, expectedValue, desired);
- if (result == expectedValue) {
- return 1;
- } else {
- ma_atomic_store_explicit_8(expected, result, failureOrder);
- return 0;
- }
- }
- #endif
- #if defined(MA_ATOMIC_HAS_16)
- static MA_INLINE ma_bool32 ma_atomic_compare_exchange_strong_explicit_16(volatile ma_uint16* dst, ma_uint16* expected, ma_uint16 desired, ma_atomic_memory_order successOrder, ma_atomic_memory_order failureOrder)
- {
- ma_uint16 expectedValue;
- ma_uint16 result;
- (void)successOrder;
- (void)failureOrder;
- expectedValue = ma_atomic_load_explicit_16(expected, ma_atomic_memory_order_seq_cst);
- result = ma_atomic_compare_and_swap_16(dst, expectedValue, desired);
- if (result == expectedValue) {
- return 1;
- } else {
- ma_atomic_store_explicit_16(expected, result, failureOrder);
- return 0;
- }
- }
- #endif
- #if defined(MA_ATOMIC_HAS_32)
- static MA_INLINE ma_bool32 ma_atomic_compare_exchange_strong_explicit_32(volatile ma_uint32* dst, ma_uint32* expected, ma_uint32 desired, ma_atomic_memory_order successOrder, ma_atomic_memory_order failureOrder)
- {
- ma_uint32 expectedValue;
- ma_uint32 result;
- (void)successOrder;
- (void)failureOrder;
- expectedValue = ma_atomic_load_explicit_32(expected, ma_atomic_memory_order_seq_cst);
- result = ma_atomic_compare_and_swap_32(dst, expectedValue, desired);
- if (result == expectedValue) {
- return 1;
- } else {
- ma_atomic_store_explicit_32(expected, result, failureOrder);
- return 0;
- }
- }
- #endif
- #if defined(MA_ATOMIC_HAS_64)
- static MA_INLINE ma_bool32 ma_atomic_compare_exchange_strong_explicit_64(volatile ma_uint64* dst, volatile ma_uint64* expected, ma_uint64 desired, ma_atomic_memory_order successOrder, ma_atomic_memory_order failureOrder)
- {
- ma_uint64 expectedValue;
- ma_uint64 result;
- (void)successOrder;
- (void)failureOrder;
- expectedValue = ma_atomic_load_explicit_64(expected, ma_atomic_memory_order_seq_cst);
- result = ma_atomic_compare_and_swap_64(dst, expectedValue, desired);
- if (result == expectedValue) {
- return 1;
- } else {
- ma_atomic_store_explicit_64(expected, result, failureOrder);
- return 0;
- }
- }
- #endif
- #define ma_atomic_compare_exchange_weak_explicit_8( dst, expected, desired, successOrder, failureOrder) ma_atomic_compare_exchange_strong_explicit_8 (dst, expected, desired, successOrder, failureOrder)
- #define ma_atomic_compare_exchange_weak_explicit_16(dst, expected, desired, successOrder, failureOrder) ma_atomic_compare_exchange_strong_explicit_16(dst, expected, desired, successOrder, failureOrder)
- #define ma_atomic_compare_exchange_weak_explicit_32(dst, expected, desired, successOrder, failureOrder) ma_atomic_compare_exchange_strong_explicit_32(dst, expected, desired, successOrder, failureOrder)
- #define ma_atomic_compare_exchange_weak_explicit_64(dst, expected, desired, successOrder, failureOrder) ma_atomic_compare_exchange_strong_explicit_64(dst, expected, desired, successOrder, failureOrder)
-#endif
-#if !defined(MA_ATOMIC_HAS_NATIVE_IS_LOCK_FREE)
- static MA_INLINE ma_bool32 ma_atomic_is_lock_free_8(volatile void* ptr)
+ static MA_INLINE ma_bool32 ma_atomic_compare_exchange_strong_explicit_8(volatile ma_uint8* dst, ma_uint8* expected, ma_uint8 replacement, ma_atomic_memory_order successOrder, ma_atomic_memory_order failureOrder)
{
- (void)ptr;
- return 1;
- }
- static MA_INLINE ma_bool32 ma_atomic_is_lock_free_16(volatile void* ptr)
- {
- (void)ptr;
- return 1;
- }
- static MA_INLINE ma_bool32 ma_atomic_is_lock_free_32(volatile void* ptr)
- {
- (void)ptr;
- return 1;
- }
- static MA_INLINE ma_bool32 ma_atomic_is_lock_free_64(volatile void* ptr)
- {
- (void)ptr;
- #if defined(MA_64BIT)
- return 1;
- #else
- #if defined(MA_X86) || defined(MA_X64)
+ ma_uint8 result;
+ (void)successOrder;
+ (void)failureOrder;
+ result = ma_atomic_compare_and_swap_8(dst, *expected, replacement);
+ if (result == *expected) {
return 1;
- #else
+ } else {
+ *expected = result;
return 0;
- #endif
- #endif
+ }
}
+ static MA_INLINE ma_bool32 ma_atomic_compare_exchange_strong_explicit_16(volatile ma_uint16* dst, ma_uint16* expected, ma_uint16 replacement, ma_atomic_memory_order successOrder, ma_atomic_memory_order failureOrder)
+ {
+ ma_uint16 result;
+ (void)successOrder;
+ (void)failureOrder;
+ result = ma_atomic_compare_and_swap_16(dst, *expected, replacement);
+ if (result == *expected) {
+ return 1;
+ } else {
+ *expected = result;
+ return 0;
+ }
+ }
+ static MA_INLINE ma_bool32 ma_atomic_compare_exchange_strong_explicit_32(volatile ma_uint32* dst, ma_uint32* expected, ma_uint32 replacement, ma_atomic_memory_order successOrder, ma_atomic_memory_order failureOrder)
+ {
+ ma_uint32 result;
+ (void)successOrder;
+ (void)failureOrder;
+ result = ma_atomic_compare_and_swap_32(dst, *expected, replacement);
+ if (result == *expected) {
+ return 1;
+ } else {
+ *expected = result;
+ return 0;
+ }
+ }
+ static MA_INLINE ma_bool32 ma_atomic_compare_exchange_strong_explicit_64(volatile ma_uint64* dst, volatile ma_uint64* expected, ma_uint64 replacement, ma_atomic_memory_order successOrder, ma_atomic_memory_order failureOrder)
+ {
+ ma_uint64 result;
+ (void)successOrder;
+ (void)failureOrder;
+ result = ma_atomic_compare_and_swap_64(dst, *expected, replacement);
+ if (result == *expected) {
+ return 1;
+ } else {
+ *expected = result;
+ return 0;
+ }
+ }
+ #define ma_atomic_compare_exchange_weak_explicit_8( dst, expected, replacement, successOrder, failureOrder) ma_atomic_compare_exchange_strong_explicit_8 (dst, expected, replacement, successOrder, failureOrder)
+ #define ma_atomic_compare_exchange_weak_explicit_16(dst, expected, replacement, successOrder, failureOrder) ma_atomic_compare_exchange_strong_explicit_16(dst, expected, replacement, successOrder, failureOrder)
+ #define ma_atomic_compare_exchange_weak_explicit_32(dst, expected, replacement, successOrder, failureOrder) ma_atomic_compare_exchange_strong_explicit_32(dst, expected, replacement, successOrder, failureOrder)
+ #define ma_atomic_compare_exchange_weak_explicit_64(dst, expected, replacement, successOrder, failureOrder) ma_atomic_compare_exchange_strong_explicit_64(dst, expected, replacement, successOrder, failureOrder)
#endif
#if defined(MA_64BIT)
static MA_INLINE ma_bool32 ma_atomic_is_lock_free_ptr(volatile void** ptr)
@@ -15561,17 +16968,17 @@ typedef int ma_atomic_memory_order;
{
return (void*)ma_atomic_exchange_explicit_64((volatile ma_uint64*)dst, (ma_uint64)src, order);
}
- static MA_INLINE ma_bool32 ma_atomic_compare_exchange_strong_explicit_ptr(volatile void** dst, void** expected, void* desired, ma_atomic_memory_order successOrder, ma_atomic_memory_order failureOrder)
+ static MA_INLINE ma_bool32 ma_atomic_compare_exchange_strong_explicit_ptr(volatile void** dst, void** expected, void* replacement, ma_atomic_memory_order successOrder, ma_atomic_memory_order failureOrder)
{
- return ma_atomic_compare_exchange_strong_explicit_64((volatile ma_uint64*)dst, (ma_uint64*)expected, (ma_uint64)desired, successOrder, failureOrder);
+ return ma_atomic_compare_exchange_strong_explicit_64((volatile ma_uint64*)dst, (ma_uint64*)expected, (ma_uint64)replacement, successOrder, failureOrder);
}
- static MA_INLINE ma_bool32 ma_atomic_compare_exchange_weak_explicit_ptr(volatile void** dst, void** expected, void* desired, ma_atomic_memory_order successOrder, ma_atomic_memory_order failureOrder)
+ static MA_INLINE ma_bool32 ma_atomic_compare_exchange_weak_explicit_ptr(volatile void** dst, void** expected, void* replacement, ma_atomic_memory_order successOrder, ma_atomic_memory_order failureOrder)
{
- return ma_atomic_compare_exchange_weak_explicit_64((volatile ma_uint64*)dst, (ma_uint64*)expected, (ma_uint64)desired, successOrder, failureOrder);
+ return ma_atomic_compare_exchange_weak_explicit_64((volatile ma_uint64*)dst, (ma_uint64*)expected, (ma_uint64)replacement, successOrder, failureOrder);
}
- static MA_INLINE void* ma_atomic_compare_and_swap_ptr(volatile void** dst, void* expected, void* desired)
+ static MA_INLINE void* ma_atomic_compare_and_swap_ptr(volatile void** dst, void* expected, void* replacement)
{
- return (void*)ma_atomic_compare_and_swap_64((volatile ma_uint64*)dst, (ma_uint64)expected, (ma_uint64)desired);
+ return (void*)ma_atomic_compare_and_swap_64((volatile ma_uint64*)dst, (ma_uint64)expected, (ma_uint64)replacement);
}
#elif defined(MA_32BIT)
static MA_INLINE ma_bool32 ma_atomic_is_lock_free_ptr(volatile void** ptr)
@@ -15590,36 +16997,26 @@ typedef int ma_atomic_memory_order;
{
return (void*)ma_atomic_exchange_explicit_32((volatile ma_uint32*)dst, (ma_uint32)src, order);
}
- static MA_INLINE ma_bool32 ma_atomic_compare_exchange_strong_explicit_ptr(volatile void** dst, void** expected, void* desired, ma_atomic_memory_order successOrder, ma_atomic_memory_order failureOrder)
+ static MA_INLINE ma_bool32 ma_atomic_compare_exchange_strong_explicit_ptr(volatile void** dst, void** expected, void* replacement, ma_atomic_memory_order successOrder, ma_atomic_memory_order failureOrder)
{
- return ma_atomic_compare_exchange_strong_explicit_32((volatile ma_uint32*)dst, (ma_uint32*)expected, (ma_uint32)desired, successOrder, failureOrder);
+ return ma_atomic_compare_exchange_strong_explicit_32((volatile ma_uint32*)dst, (ma_uint32*)expected, (ma_uint32)replacement, successOrder, failureOrder);
}
- static MA_INLINE ma_bool32 ma_atomic_compare_exchange_weak_explicit_ptr(volatile void** dst, void** expected, void* desired, ma_atomic_memory_order successOrder, ma_atomic_memory_order failureOrder)
+ static MA_INLINE ma_bool32 ma_atomic_compare_exchange_weak_explicit_ptr(volatile void** dst, void** expected, void* replacement, ma_atomic_memory_order successOrder, ma_atomic_memory_order failureOrder)
{
- return ma_atomic_compare_exchange_weak_explicit_32((volatile ma_uint32*)dst, (ma_uint32*)expected, (ma_uint32)desired, successOrder, failureOrder);
+ return ma_atomic_compare_exchange_weak_explicit_32((volatile ma_uint32*)dst, (ma_uint32*)expected, (ma_uint32)replacement, successOrder, failureOrder);
}
- static MA_INLINE void* ma_atomic_compare_and_swap_ptr(volatile void** dst, void* expected, void* desired)
+ static MA_INLINE void* ma_atomic_compare_and_swap_ptr(volatile void** dst, void* expected, void* replacement)
{
- return (void*)ma_atomic_compare_and_swap_32((volatile ma_uint32*)dst, (ma_uint32)expected, (ma_uint32)desired);
+ return (void*)ma_atomic_compare_and_swap_32((volatile ma_uint32*)dst, (ma_uint32)expected, (ma_uint32)replacement);
}
#else
#error Unsupported architecture.
#endif
-#define ma_atomic_flag_test_and_set(ptr) ma_atomic_flag_test_and_set_explicit(ptr, ma_atomic_memory_order_seq_cst)
-#define ma_atomic_flag_clear(ptr) ma_atomic_flag_clear_explicit(ptr, ma_atomic_memory_order_seq_cst)
-#define ma_atomic_store_ptr(dst, src) ma_atomic_store_explicit_ptr((volatile void**)dst, (void*)src, ma_atomic_memory_order_seq_cst)
-#define ma_atomic_load_ptr(ptr) ma_atomic_load_explicit_ptr((volatile void**)ptr, ma_atomic_memory_order_seq_cst)
-#define ma_atomic_exchange_ptr(dst, src) ma_atomic_exchange_explicit_ptr((volatile void**)dst, (void*)src, ma_atomic_memory_order_seq_cst)
-#define ma_atomic_compare_exchange_strong_ptr(dst, expected, desired) ma_atomic_compare_exchange_strong_explicit_ptr((volatile void**)dst, (void**)expected, (void*)desired, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst)
-#define ma_atomic_compare_exchange_weak_ptr(dst, expected, desired) ma_atomic_compare_exchange_weak_explicit_ptr((volatile void**)dst, (void**)expected, (void*)desired, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst)
-#define ma_atomic_test_and_set_8( ptr) ma_atomic_test_and_set_explicit_8( ptr, ma_atomic_memory_order_seq_cst)
-#define ma_atomic_test_and_set_16(ptr) ma_atomic_test_and_set_explicit_16(ptr, ma_atomic_memory_order_seq_cst)
-#define ma_atomic_test_and_set_32(ptr) ma_atomic_test_and_set_explicit_32(ptr, ma_atomic_memory_order_seq_cst)
-#define ma_atomic_test_and_set_64(ptr) ma_atomic_test_and_set_explicit_64(ptr, ma_atomic_memory_order_seq_cst)
-#define ma_atomic_clear_8( ptr) ma_atomic_clear_explicit_8( ptr, ma_atomic_memory_order_seq_cst)
-#define ma_atomic_clear_16(ptr) ma_atomic_clear_explicit_16(ptr, ma_atomic_memory_order_seq_cst)
-#define ma_atomic_clear_32(ptr) ma_atomic_clear_explicit_32(ptr, ma_atomic_memory_order_seq_cst)
-#define ma_atomic_clear_64(ptr) ma_atomic_clear_explicit_64(ptr, ma_atomic_memory_order_seq_cst)
+#define ma_atomic_store_ptr(dst, src) ma_atomic_store_explicit_ptr((volatile void**)dst, (void*)src, ma_atomic_memory_order_seq_cst)
+#define ma_atomic_load_ptr(ptr) ma_atomic_load_explicit_ptr((volatile void**)ptr, ma_atomic_memory_order_seq_cst)
+#define ma_atomic_exchange_ptr(dst, src) ma_atomic_exchange_explicit_ptr((volatile void**)dst, (void*)src, ma_atomic_memory_order_seq_cst)
+#define ma_atomic_compare_exchange_strong_ptr(dst, expected, replacement) ma_atomic_compare_exchange_strong_explicit_ptr((volatile void**)dst, (void**)expected, (void*)replacement, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst)
+#define ma_atomic_compare_exchange_weak_ptr(dst, expected, replacement) ma_atomic_compare_exchange_weak_explicit_ptr((volatile void**)dst, (void**)expected, (void*)replacement, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst)
#define ma_atomic_store_8( dst, src) ma_atomic_store_explicit_8( dst, src, ma_atomic_memory_order_seq_cst)
#define ma_atomic_store_16(dst, src) ma_atomic_store_explicit_16(dst, src, ma_atomic_memory_order_seq_cst)
#define ma_atomic_store_32(dst, src) ma_atomic_store_explicit_32(dst, src, ma_atomic_memory_order_seq_cst)
@@ -15632,14 +17029,14 @@ typedef int ma_atomic_memory_order;
#define ma_atomic_exchange_16(dst, src) ma_atomic_exchange_explicit_16(dst, src, ma_atomic_memory_order_seq_cst)
#define ma_atomic_exchange_32(dst, src) ma_atomic_exchange_explicit_32(dst, src, ma_atomic_memory_order_seq_cst)
#define ma_atomic_exchange_64(dst, src) ma_atomic_exchange_explicit_64(dst, src, ma_atomic_memory_order_seq_cst)
-#define ma_atomic_compare_exchange_strong_8( dst, expected, desired) ma_atomic_compare_exchange_strong_explicit_8( dst, expected, desired, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst)
-#define ma_atomic_compare_exchange_strong_16(dst, expected, desired) ma_atomic_compare_exchange_strong_explicit_16(dst, expected, desired, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst)
-#define ma_atomic_compare_exchange_strong_32(dst, expected, desired) ma_atomic_compare_exchange_strong_explicit_32(dst, expected, desired, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst)
-#define ma_atomic_compare_exchange_strong_64(dst, expected, desired) ma_atomic_compare_exchange_strong_explicit_64(dst, expected, desired, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst)
-#define ma_atomic_compare_exchange_weak_8( dst, expected, desired) ma_atomic_compare_exchange_weak_explicit_8( dst, expected, desired, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst)
-#define ma_atomic_compare_exchange_weak_16( dst, expected, desired) ma_atomic_compare_exchange_weak_explicit_16(dst, expected, desired, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst)
-#define ma_atomic_compare_exchange_weak_32( dst, expected, desired) ma_atomic_compare_exchange_weak_explicit_32(dst, expected, desired, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst)
-#define ma_atomic_compare_exchange_weak_64( dst, expected, desired) ma_atomic_compare_exchange_weak_explicit_64(dst, expected, desired, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst)
+#define ma_atomic_compare_exchange_strong_8( dst, expected, replacement) ma_atomic_compare_exchange_strong_explicit_8( dst, expected, replacement, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst)
+#define ma_atomic_compare_exchange_strong_16(dst, expected, replacement) ma_atomic_compare_exchange_strong_explicit_16(dst, expected, replacement, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst)
+#define ma_atomic_compare_exchange_strong_32(dst, expected, replacement) ma_atomic_compare_exchange_strong_explicit_32(dst, expected, replacement, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst)
+#define ma_atomic_compare_exchange_strong_64(dst, expected, replacement) ma_atomic_compare_exchange_strong_explicit_64(dst, expected, replacement, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst)
+#define ma_atomic_compare_exchange_weak_8( dst, expected, replacement) ma_atomic_compare_exchange_weak_explicit_8( dst, expected, replacement, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst)
+#define ma_atomic_compare_exchange_weak_16( dst, expected, replacement) ma_atomic_compare_exchange_weak_explicit_16(dst, expected, replacement, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst)
+#define ma_atomic_compare_exchange_weak_32( dst, expected, replacement) ma_atomic_compare_exchange_weak_explicit_32(dst, expected, replacement, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst)
+#define ma_atomic_compare_exchange_weak_64( dst, expected, replacement) ma_atomic_compare_exchange_weak_explicit_64(dst, expected, replacement, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst)
#define ma_atomic_fetch_add_8( dst, src) ma_atomic_fetch_add_explicit_8( dst, src, ma_atomic_memory_order_seq_cst)
#define ma_atomic_fetch_add_16(dst, src) ma_atomic_fetch_add_explicit_16(dst, src, ma_atomic_memory_order_seq_cst)
#define ma_atomic_fetch_add_32(dst, src) ma_atomic_fetch_add_explicit_32(dst, src, ma_atomic_memory_order_seq_cst)
@@ -15660,14 +17057,6 @@ typedef int ma_atomic_memory_order;
#define ma_atomic_fetch_and_16(dst, src) ma_atomic_fetch_and_explicit_16(dst, src, ma_atomic_memory_order_seq_cst)
#define ma_atomic_fetch_and_32(dst, src) ma_atomic_fetch_and_explicit_32(dst, src, ma_atomic_memory_order_seq_cst)
#define ma_atomic_fetch_and_64(dst, src) ma_atomic_fetch_and_explicit_64(dst, src, ma_atomic_memory_order_seq_cst)
-#define ma_atomic_test_and_set_explicit_i8( ptr, order) (ma_int8 )ma_atomic_test_and_set_explicit_8( (ma_uint8* )ptr, order)
-#define ma_atomic_test_and_set_explicit_i16(ptr, order) (ma_int16)ma_atomic_test_and_set_explicit_16((ma_uint16*)ptr, order)
-#define ma_atomic_test_and_set_explicit_i32(ptr, order) (ma_int32)ma_atomic_test_and_set_explicit_32((ma_uint32*)ptr, order)
-#define ma_atomic_test_and_set_explicit_i64(ptr, order) (ma_int64)ma_atomic_test_and_set_explicit_64((ma_uint64*)ptr, order)
-#define ma_atomic_clear_explicit_i8( ptr, order) ma_atomic_clear_explicit_8( (ma_uint8* )ptr, order)
-#define ma_atomic_clear_explicit_i16(ptr, order) ma_atomic_clear_explicit_16((ma_uint16*)ptr, order)
-#define ma_atomic_clear_explicit_i32(ptr, order) ma_atomic_clear_explicit_32((ma_uint32*)ptr, order)
-#define ma_atomic_clear_explicit_i64(ptr, order) ma_atomic_clear_explicit_64((ma_uint64*)ptr, order)
#define ma_atomic_store_explicit_i8( dst, src, order) ma_atomic_store_explicit_8( (ma_uint8* )dst, (ma_uint8 )src, order)
#define ma_atomic_store_explicit_i16(dst, src, order) ma_atomic_store_explicit_16((ma_uint16*)dst, (ma_uint16)src, order)
#define ma_atomic_store_explicit_i32(dst, src, order) ma_atomic_store_explicit_32((ma_uint32*)dst, (ma_uint32)src, order)
@@ -15680,14 +17069,14 @@ typedef int ma_atomic_memory_order;
#define ma_atomic_exchange_explicit_i16(dst, src, order) (ma_int16)ma_atomic_exchange_explicit_16((ma_uint16*)dst, (ma_uint16)src, order)
#define ma_atomic_exchange_explicit_i32(dst, src, order) (ma_int32)ma_atomic_exchange_explicit_32((ma_uint32*)dst, (ma_uint32)src, order)
#define ma_atomic_exchange_explicit_i64(dst, src, order) (ma_int64)ma_atomic_exchange_explicit_64((ma_uint64*)dst, (ma_uint64)src, order)
-#define ma_atomic_compare_exchange_strong_explicit_i8( dst, expected, desired, successOrder, failureOrder) ma_atomic_compare_exchange_strong_explicit_8( (ma_uint8* )dst, (ma_uint8* )expected, (ma_uint8 )desired, successOrder, failureOrder)
-#define ma_atomic_compare_exchange_strong_explicit_i16(dst, expected, desired, successOrder, failureOrder) ma_atomic_compare_exchange_strong_explicit_16((ma_uint16*)dst, (ma_uint16*)expected, (ma_uint16)desired, successOrder, failureOrder)
-#define ma_atomic_compare_exchange_strong_explicit_i32(dst, expected, desired, successOrder, failureOrder) ma_atomic_compare_exchange_strong_explicit_32((ma_uint32*)dst, (ma_uint32*)expected, (ma_uint32)desired, successOrder, failureOrder)
-#define ma_atomic_compare_exchange_strong_explicit_i64(dst, expected, desired, successOrder, failureOrder) ma_atomic_compare_exchange_strong_explicit_64((ma_uint64*)dst, (ma_uint64*)expected, (ma_uint64)desired, successOrder, failureOrder)
-#define ma_atomic_compare_exchange_weak_explicit_i8( dst, expected, desired, successOrder, failureOrder) ma_atomic_compare_exchange_weak_explicit_8( (ma_uint8* )dst, (ma_uint8* )expected, (ma_uint8 )desired, successOrder, failureOrder)
-#define ma_atomic_compare_exchange_weak_explicit_i16(dst, expected, desired, successOrder, failureOrder) ma_atomic_compare_exchange_weak_explicit_16((ma_uint16*)dst, (ma_uint16*)expected, (ma_uint16)desired, successOrder, failureOrder)
-#define ma_atomic_compare_exchange_weak_explicit_i32(dst, expected, desired, successOrder, failureOrder) ma_atomic_compare_exchange_weak_explicit_32((ma_uint32*)dst, (ma_uint32*)expected, (ma_uint32)desired, successOrder, failureOrder)
-#define ma_atomic_compare_exchange_weak_explicit_i64(dst, expected, desired, successOrder, failureOrder) ma_atomic_compare_exchange_weak_explicit_64((ma_uint64*)dst, (ma_uint64*)expected, (ma_uint64)desired, successOrder, failureOrder)
+#define ma_atomic_compare_exchange_strong_explicit_i8( dst, expected, replacement, successOrder, failureOrder) ma_atomic_compare_exchange_strong_explicit_8( (ma_uint8* )dst, (ma_uint8* )expected, (ma_uint8 )replacement, successOrder, failureOrder)
+#define ma_atomic_compare_exchange_strong_explicit_i16(dst, expected, replacement, successOrder, failureOrder) ma_atomic_compare_exchange_strong_explicit_16((ma_uint16*)dst, (ma_uint16*)expected, (ma_uint16)replacement, successOrder, failureOrder)
+#define ma_atomic_compare_exchange_strong_explicit_i32(dst, expected, replacement, successOrder, failureOrder) ma_atomic_compare_exchange_strong_explicit_32((ma_uint32*)dst, (ma_uint32*)expected, (ma_uint32)replacement, successOrder, failureOrder)
+#define ma_atomic_compare_exchange_strong_explicit_i64(dst, expected, replacement, successOrder, failureOrder) ma_atomic_compare_exchange_strong_explicit_64((ma_uint64*)dst, (ma_uint64*)expected, (ma_uint64)replacement, successOrder, failureOrder)
+#define ma_atomic_compare_exchange_weak_explicit_i8( dst, expected, replacement, successOrder, failureOrder) ma_atomic_compare_exchange_weak_explicit_8( (ma_uint8* )dst, (ma_uint8* )expected, (ma_uint8 )replacement, successOrder, failureOrder)
+#define ma_atomic_compare_exchange_weak_explicit_i16(dst, expected, replacement, successOrder, failureOrder) ma_atomic_compare_exchange_weak_explicit_16((ma_uint16*)dst, (ma_uint16*)expected, (ma_uint16)replacement, successOrder, failureOrder)
+#define ma_atomic_compare_exchange_weak_explicit_i32(dst, expected, replacement, successOrder, failureOrder) ma_atomic_compare_exchange_weak_explicit_32((ma_uint32*)dst, (ma_uint32*)expected, (ma_uint32)replacement, successOrder, failureOrder)
+#define ma_atomic_compare_exchange_weak_explicit_i64(dst, expected, replacement, successOrder, failureOrder) ma_atomic_compare_exchange_weak_explicit_64((ma_uint64*)dst, (ma_uint64*)expected, (ma_uint64)replacement, successOrder, failureOrder)
#define ma_atomic_fetch_add_explicit_i8( dst, src, order) (ma_int8 )ma_atomic_fetch_add_explicit_8( (ma_uint8* )dst, (ma_uint8 )src, order)
#define ma_atomic_fetch_add_explicit_i16(dst, src, order) (ma_int16)ma_atomic_fetch_add_explicit_16((ma_uint16*)dst, (ma_uint16)src, order)
#define ma_atomic_fetch_add_explicit_i32(dst, src, order) (ma_int32)ma_atomic_fetch_add_explicit_32((ma_uint32*)dst, (ma_uint32)src, order)
@@ -15708,14 +17097,6 @@ typedef int ma_atomic_memory_order;
#define ma_atomic_fetch_and_explicit_i16(dst, src, order) (ma_int16)ma_atomic_fetch_and_explicit_16((ma_uint16*)dst, (ma_uint16)src, order)
#define ma_atomic_fetch_and_explicit_i32(dst, src, order) (ma_int32)ma_atomic_fetch_and_explicit_32((ma_uint32*)dst, (ma_uint32)src, order)
#define ma_atomic_fetch_and_explicit_i64(dst, src, order) (ma_int64)ma_atomic_fetch_and_explicit_64((ma_uint64*)dst, (ma_uint64)src, order)
-#define ma_atomic_test_and_set_i8( ptr) ma_atomic_test_and_set_explicit_i8( ptr, ma_atomic_memory_order_seq_cst)
-#define ma_atomic_test_and_set_i16(ptr) ma_atomic_test_and_set_explicit_i16(ptr, ma_atomic_memory_order_seq_cst)
-#define ma_atomic_test_and_set_i32(ptr) ma_atomic_test_and_set_explicit_i32(ptr, ma_atomic_memory_order_seq_cst)
-#define ma_atomic_test_and_set_i64(ptr) ma_atomic_test_and_set_explicit_i64(ptr, ma_atomic_memory_order_seq_cst)
-#define ma_atomic_clear_i8( ptr) ma_atomic_clear_explicit_i8( ptr, ma_atomic_memory_order_seq_cst)
-#define ma_atomic_clear_i16(ptr) ma_atomic_clear_explicit_i16(ptr, ma_atomic_memory_order_seq_cst)
-#define ma_atomic_clear_i32(ptr) ma_atomic_clear_explicit_i32(ptr, ma_atomic_memory_order_seq_cst)
-#define ma_atomic_clear_i64(ptr) ma_atomic_clear_explicit_i64(ptr, ma_atomic_memory_order_seq_cst)
#define ma_atomic_store_i8( dst, src) ma_atomic_store_explicit_i8( dst, src, ma_atomic_memory_order_seq_cst)
#define ma_atomic_store_i16(dst, src) ma_atomic_store_explicit_i16(dst, src, ma_atomic_memory_order_seq_cst)
#define ma_atomic_store_i32(dst, src) ma_atomic_store_explicit_i32(dst, src, ma_atomic_memory_order_seq_cst)
@@ -15728,14 +17109,14 @@ typedef int ma_atomic_memory_order;
#define ma_atomic_exchange_i16(dst, src) ma_atomic_exchange_explicit_i16(dst, src, ma_atomic_memory_order_seq_cst)
#define ma_atomic_exchange_i32(dst, src) ma_atomic_exchange_explicit_i32(dst, src, ma_atomic_memory_order_seq_cst)
#define ma_atomic_exchange_i64(dst, src) ma_atomic_exchange_explicit_i64(dst, src, ma_atomic_memory_order_seq_cst)
-#define ma_atomic_compare_exchange_strong_i8( dst, expected, desired) ma_atomic_compare_exchange_strong_explicit_i8( dst, expected, desired, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst)
-#define ma_atomic_compare_exchange_strong_i16(dst, expected, desired) ma_atomic_compare_exchange_strong_explicit_i16(dst, expected, desired, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst)
-#define ma_atomic_compare_exchange_strong_i32(dst, expected, desired) ma_atomic_compare_exchange_strong_explicit_i32(dst, expected, desired, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst)
-#define ma_atomic_compare_exchange_strong_i64(dst, expected, desired) ma_atomic_compare_exchange_strong_explicit_i64(dst, expected, desired, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst)
-#define ma_atomic_compare_exchange_weak_i8( dst, expected, desired) ma_atomic_compare_exchange_weak_explicit_i8( dst, expected, desired, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst)
-#define ma_atomic_compare_exchange_weak_i16(dst, expected, desired) ma_atomic_compare_exchange_weak_explicit_i16(dst, expected, desired, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst)
-#define ma_atomic_compare_exchange_weak_i32(dst, expected, desired) ma_atomic_compare_exchange_weak_explicit_i32(dst, expected, desired, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst)
-#define ma_atomic_compare_exchange_weak_i64(dst, expected, desired) ma_atomic_compare_exchange_weak_explicit_i64(dst, expected, desired, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst)
+#define ma_atomic_compare_exchange_strong_i8( dst, expected, replacement) ma_atomic_compare_exchange_strong_explicit_i8( dst, expected, replacement, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst)
+#define ma_atomic_compare_exchange_strong_i16(dst, expected, replacement) ma_atomic_compare_exchange_strong_explicit_i16(dst, expected, replacement, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst)
+#define ma_atomic_compare_exchange_strong_i32(dst, expected, replacement) ma_atomic_compare_exchange_strong_explicit_i32(dst, expected, replacement, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst)
+#define ma_atomic_compare_exchange_strong_i64(dst, expected, replacement) ma_atomic_compare_exchange_strong_explicit_i64(dst, expected, replacement, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst)
+#define ma_atomic_compare_exchange_weak_i8( dst, expected, replacement) ma_atomic_compare_exchange_weak_explicit_i8( dst, expected, replacement, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst)
+#define ma_atomic_compare_exchange_weak_i16(dst, expected, replacement) ma_atomic_compare_exchange_weak_explicit_i16(dst, expected, replacement, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst)
+#define ma_atomic_compare_exchange_weak_i32(dst, expected, replacement) ma_atomic_compare_exchange_weak_explicit_i32(dst, expected, replacement, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst)
+#define ma_atomic_compare_exchange_weak_i64(dst, expected, replacement) ma_atomic_compare_exchange_weak_explicit_i64(dst, expected, replacement, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst)
#define ma_atomic_fetch_add_i8( dst, src) ma_atomic_fetch_add_explicit_i8( dst, src, ma_atomic_memory_order_seq_cst)
#define ma_atomic_fetch_add_i16(dst, src) ma_atomic_fetch_add_explicit_i16(dst, src, ma_atomic_memory_order_seq_cst)
#define ma_atomic_fetch_add_i32(dst, src) ma_atomic_fetch_add_explicit_i32(dst, src, ma_atomic_memory_order_seq_cst)
@@ -15812,28 +17193,28 @@ static MA_INLINE double ma_atomic_exchange_explicit_f64(volatile double* dst, do
r.i = ma_atomic_exchange_explicit_64((volatile ma_uint64*)dst, x.i, order);
return r.f;
}
-static MA_INLINE ma_bool32 ma_atomic_compare_exchange_strong_explicit_f32(volatile float* dst, float* expected, float desired, ma_atomic_memory_order successOrder, ma_atomic_memory_order failureOrder)
+static MA_INLINE ma_bool32 ma_atomic_compare_exchange_strong_explicit_f32(volatile float* dst, float* expected, float replacement, ma_atomic_memory_order successOrder, ma_atomic_memory_order failureOrder)
{
ma_atomic_if32 d;
- d.f = desired;
+ d.f = replacement;
return ma_atomic_compare_exchange_strong_explicit_32((volatile ma_uint32*)dst, (ma_uint32*)expected, d.i, successOrder, failureOrder);
}
-static MA_INLINE ma_bool32 ma_atomic_compare_exchange_strong_explicit_f64(volatile double* dst, double* expected, double desired, ma_atomic_memory_order successOrder, ma_atomic_memory_order failureOrder)
+static MA_INLINE ma_bool32 ma_atomic_compare_exchange_strong_explicit_f64(volatile double* dst, double* expected, double replacement, ma_atomic_memory_order successOrder, ma_atomic_memory_order failureOrder)
{
ma_atomic_if64 d;
- d.f = desired;
+ d.f = replacement;
return ma_atomic_compare_exchange_strong_explicit_64((volatile ma_uint64*)dst, (ma_uint64*)expected, d.i, successOrder, failureOrder);
}
-static MA_INLINE ma_bool32 ma_atomic_compare_exchange_weak_explicit_f32(volatile float* dst, float* expected, float desired, ma_atomic_memory_order successOrder, ma_atomic_memory_order failureOrder)
+static MA_INLINE ma_bool32 ma_atomic_compare_exchange_weak_explicit_f32(volatile float* dst, float* expected, float replacement, ma_atomic_memory_order successOrder, ma_atomic_memory_order failureOrder)
{
ma_atomic_if32 d;
- d.f = desired;
+ d.f = replacement;
return ma_atomic_compare_exchange_weak_explicit_32((volatile ma_uint32*)dst, (ma_uint32*)expected, d.i, successOrder, failureOrder);
}
-static MA_INLINE ma_bool32 ma_atomic_compare_exchange_weak_explicit_f64(volatile double* dst, double* expected, double desired, ma_atomic_memory_order successOrder, ma_atomic_memory_order failureOrder)
+static MA_INLINE ma_bool32 ma_atomic_compare_exchange_weak_explicit_f64(volatile double* dst, double* expected, double replacement, ma_atomic_memory_order successOrder, ma_atomic_memory_order failureOrder)
{
ma_atomic_if64 d;
- d.f = desired;
+ d.f = replacement;
return ma_atomic_compare_exchange_weak_explicit_64((volatile ma_uint64*)dst, (ma_uint64*)expected, d.i, successOrder, failureOrder);
}
static MA_INLINE float ma_atomic_fetch_add_explicit_f32(volatile float* dst, float src, ma_atomic_memory_order order)
@@ -15924,10 +17305,10 @@ static MA_INLINE double ma_atomic_fetch_and_explicit_f64(volatile double* dst, d
#define ma_atomic_load_f64(ptr) (double)ma_atomic_load_explicit_f64(ptr, ma_atomic_memory_order_seq_cst)
#define ma_atomic_exchange_f32(dst, src) (float )ma_atomic_exchange_explicit_f32(dst, src, ma_atomic_memory_order_seq_cst)
#define ma_atomic_exchange_f64(dst, src) (double)ma_atomic_exchange_explicit_f64(dst, src, ma_atomic_memory_order_seq_cst)
-#define ma_atomic_compare_exchange_strong_f32(dst, expected, desired) ma_atomic_compare_exchange_strong_explicit_f32(dst, expected, desired, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst)
-#define ma_atomic_compare_exchange_strong_f64(dst, expected, desired) ma_atomic_compare_exchange_strong_explicit_f64(dst, expected, desired, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst)
-#define ma_atomic_compare_exchange_weak_f32(dst, expected, desired) ma_atomic_compare_exchange_weak_explicit_f32(dst, expected, desired, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst)
-#define ma_atomic_compare_exchange_weak_f64(dst, expected, desired) ma_atomic_compare_exchange_weak_explicit_f64(dst, expected, desired, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst)
+#define ma_atomic_compare_exchange_strong_f32(dst, expected, replacement) ma_atomic_compare_exchange_strong_explicit_f32(dst, expected, replacement, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst)
+#define ma_atomic_compare_exchange_strong_f64(dst, expected, replacement) ma_atomic_compare_exchange_strong_explicit_f64(dst, expected, replacement, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst)
+#define ma_atomic_compare_exchange_weak_f32(dst, expected, replacement) ma_atomic_compare_exchange_weak_explicit_f32(dst, expected, replacement, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst)
+#define ma_atomic_compare_exchange_weak_f64(dst, expected, replacement) ma_atomic_compare_exchange_weak_explicit_f64(dst, expected, replacement, ma_atomic_memory_order_seq_cst, ma_atomic_memory_order_seq_cst)
#define ma_atomic_fetch_add_f32(dst, src) ma_atomic_fetch_add_explicit_f32(dst, src, ma_atomic_memory_order_seq_cst)
#define ma_atomic_fetch_add_f64(dst, src) ma_atomic_fetch_add_explicit_f64(dst, src, ma_atomic_memory_order_seq_cst)
#define ma_atomic_fetch_sub_f32(dst, src) ma_atomic_fetch_sub_explicit_f32(dst, src, ma_atomic_memory_order_seq_cst)
@@ -15938,39 +17319,24 @@ static MA_INLINE double ma_atomic_fetch_and_explicit_f64(volatile double* dst, d
#define ma_atomic_fetch_xor_f64(dst, src) ma_atomic_fetch_xor_explicit_f64(dst, src, ma_atomic_memory_order_seq_cst)
#define ma_atomic_fetch_and_f32(dst, src) ma_atomic_fetch_and_explicit_f32(dst, src, ma_atomic_memory_order_seq_cst)
#define ma_atomic_fetch_and_f64(dst, src) ma_atomic_fetch_and_explicit_f64(dst, src, ma_atomic_memory_order_seq_cst)
-static MA_INLINE float ma_atomic_compare_and_swap_f32(volatile float* dst, float expected, float desired)
+static MA_INLINE float ma_atomic_compare_and_swap_f32(volatile float* dst, float expected, float replacement)
{
ma_atomic_if32 r;
ma_atomic_if32 e, d;
e.f = expected;
- d.f = desired;
+ d.f = replacement;
r.i = ma_atomic_compare_and_swap_32((volatile ma_uint32*)dst, e.i, d.i);
return r.f;
}
-static MA_INLINE double ma_atomic_compare_and_swap_f64(volatile double* dst, double expected, double desired)
+static MA_INLINE double ma_atomic_compare_and_swap_f64(volatile double* dst, double expected, double replacement)
{
ma_atomic_if64 r;
ma_atomic_if64 e, d;
e.f = expected;
- d.f = desired;
+ d.f = replacement;
r.i = ma_atomic_compare_and_swap_64((volatile ma_uint64*)dst, e.i, d.i);
return r.f;
}
-typedef ma_atomic_flag ma_atomic_spinlock;
-static MA_INLINE void ma_atomic_spinlock_lock(volatile ma_atomic_spinlock* pSpinlock)
-{
- for (;;) {
- if (ma_atomic_flag_test_and_set_explicit(pSpinlock, ma_atomic_memory_order_acquire) == 0) {
- break;
- }
- while (ma_atomic_flag_load_explicit(pSpinlock, ma_atomic_memory_order_relaxed) == 1) {
- }
- }
-}
-static MA_INLINE void ma_atomic_spinlock_unlock(volatile ma_atomic_spinlock* pSpinlock)
-{
- ma_atomic_flag_clear_explicit(pSpinlock, ma_atomic_memory_order_release);
-}
#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
#pragma GCC diagnostic pop
#endif
@@ -16176,7 +17542,7 @@ static ma_result ma_thread_create__posix(ma_thread* pThread, ma_thread_priority
int result;
pthread_attr_t* pAttr = NULL;
-#if !defined(__EMSCRIPTEN__) && !defined(__3DS__)
+#if !defined(MA_EMSCRIPTEN) && !defined(MA_3DS) && !defined(MA_SWITCH)
/* Try setting the thread priority. It's not critical if anything fails here. */
pthread_attr_t attr;
if (pthread_attr_init(&attr) == 0) {
@@ -16208,9 +17574,18 @@ static ma_result ma_thread_create__posix(ma_thread* pThread, ma_thread_priority
}
#endif
- if (stackSize > 0) {
- pthread_attr_setstacksize(&attr, stackSize);
+ #if defined(_POSIX_THREAD_ATTR_STACKSIZE) && _POSIX_THREAD_ATTR_STACKSIZE >= 0
+ {
+ if (stackSize > 0) {
+ pthread_attr_setstacksize(&attr, stackSize);
+ }
}
+ #else
+ {
+ (void)stackSize; /* Suppress unused parameter warning. */
+ }
+ #endif
+
if (scheduler != -1) {
int priorityMin = sched_get_priority_min(scheduler);
@@ -16267,6 +17642,21 @@ static ma_result ma_thread_create__posix(ma_thread* pThread, ma_thread_priority
}
if (result != 0) {
+ /*
+ There have been reports that attempting to create a realtime thread can sometimes fail. In this case,
+ fall back to a normal priority thread.
+
+ I'm including a compile-time option here to disable this functionality for those who have a hard
+ requirement on realtime threads and would rather an explicit failure.
+ */
+ #ifndef MA_NO_PTHREAD_REALTIME_PRIORITY_FALLBACK
+ {
+ if(result == EPERM && priority == ma_thread_priority_realtime) {
+ return ma_thread_create__posix(pThread, ma_thread_priority_normal, stackSize, entryProc, pData);
+ }
+ }
+ #endif
+
return ma_result_from_errno(result);
}
@@ -16538,7 +17928,7 @@ static ma_result ma_event_signal__win32(ma_event* pEvent)
static ma_result ma_semaphore_init__win32(int initialValue, ma_semaphore* pSemaphore)
{
- *pSemaphore = CreateSemaphoreW(NULL, (LONG)initialValue, LONG_MAX, NULL);
+ *pSemaphore = CreateSemaphore(NULL, (LONG)initialValue, LONG_MAX, NULL);
if (*pSemaphore == NULL) {
return ma_result_from_GetLastError(GetLastError());
}
@@ -17432,10 +18822,12 @@ static MA_INLINE ma_uint16 ma_job_extract_slot(ma_uint64 toc)
return (ma_uint16)(toc & 0x0000FFFF);
}
+#if 0 /* Currently unused, but might make use of this later. */
static MA_INLINE ma_uint16 ma_job_extract_code(ma_uint64 toc)
{
return (ma_uint16)((toc & 0xFFFF0000) >> 16);
}
+#endif
static MA_INLINE ma_uint64 ma_job_toc_to_allocation(ma_uint64 toc)
{
@@ -17900,6 +19292,13 @@ MA_API ma_result ma_job_queue_next(ma_job_queue* pQueue, ma_job* pJob)
Dynamic Linking
*******************************************************************************/
+/* Disable run-time linking on certain backends and platforms. */
+#ifndef MA_NO_RUNTIME_LINKING
+ #if defined(MA_EMSCRIPTEN) || defined(MA_ORBIS) || defined(MA_PROSPERO) || defined(MA_SWITCH) || defined(MA_DOS)
+ #define MA_NO_RUNTIME_LINKING
+ #endif
+#endif
+
#ifdef MA_POSIX
/* No need for dlfcn.h if we're not using runtime linking. */
#ifndef MA_NO_RUNTIME_LINKING
@@ -17909,104 +19308,124 @@ Dynamic Linking
MA_API ma_handle ma_dlopen(ma_log* pLog, const char* filename)
{
-#ifndef MA_NO_RUNTIME_LINKING
- ma_handle handle;
+ #ifndef MA_NO_RUNTIME_LINKING
+ {
+ ma_handle handle;
- ma_log_postf(pLog, MA_LOG_LEVEL_DEBUG, "Loading library: %s\n", filename);
+ ma_log_postf(pLog, MA_LOG_LEVEL_DEBUG, "Loading library: %s\n", filename);
- #ifdef MA_WIN32
- /* From MSDN: Desktop applications cannot use LoadPackagedLibrary; if a desktop application calls this function it fails with APPMODEL_ERROR_NO_PACKAGE.*/
- #if !defined(MA_WIN32_UWP) || !(defined(WINAPI_FAMILY) && ((defined(WINAPI_FAMILY_PHONE_APP) && WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)))
- handle = (ma_handle)LoadLibraryA(filename);
+ #ifdef MA_WIN32
+ /* From MSDN: Desktop applications cannot use LoadPackagedLibrary; if a desktop application calls this function it fails with APPMODEL_ERROR_NO_PACKAGE.*/
+ #if !defined(MA_WIN32_UWP) || !(defined(WINAPI_FAMILY) && ((defined(WINAPI_FAMILY_PHONE_APP) && WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)))
+ handle = (ma_handle)LoadLibraryA(filename);
+ #else
+ /* *sigh* It appears there is no ANSI version of LoadPackagedLibrary()... */
+ WCHAR filenameW[4096];
+ if (MultiByteToWideChar(CP_UTF8, 0, filename, -1, filenameW, sizeof(filenameW)) == 0) {
+ handle = NULL;
+ } else {
+ handle = (ma_handle)LoadPackagedLibrary(filenameW, 0);
+ }
+ #endif
#else
- /* *sigh* It appears there is no ANSI version of LoadPackagedLibrary()... */
- WCHAR filenameW[4096];
- if (MultiByteToWideChar(CP_UTF8, 0, filename, -1, filenameW, sizeof(filenameW)) == 0) {
- handle = NULL;
- } else {
- handle = (ma_handle)LoadPackagedLibrary(filenameW, 0);
- }
+ handle = (ma_handle)dlopen(filename, RTLD_NOW);
#endif
- #else
- handle = (ma_handle)dlopen(filename, RTLD_NOW);
- #endif
- /*
- I'm not considering failure to load a library an error nor a warning because seamlessly falling through to a lower-priority
- backend is a deliberate design choice. Instead I'm logging it as an informational message.
- */
- if (handle == NULL) {
- ma_log_postf(pLog, MA_LOG_LEVEL_INFO, "Failed to load library: %s\n", filename);
+ /*
+ I'm not considering failure to load a library an error nor a warning because seamlessly falling through to a lower-priority
+ backend is a deliberate design choice. Instead I'm logging it as an informational message.
+ */
+ if (handle == NULL) {
+ ma_log_postf(pLog, MA_LOG_LEVEL_INFO, "Failed to load library: %s\n", filename);
+ }
+
+ return handle;
}
-
- return handle;
-#else
- /* Runtime linking is disabled. */
- (void)pLog;
- (void)filename;
- return NULL;
-#endif
+ #else
+ {
+ /* Runtime linking is disabled. */
+ (void)pLog;
+ (void)filename;
+ return NULL;
+ }
+ #endif
}
MA_API void ma_dlclose(ma_log* pLog, ma_handle handle)
{
-#ifndef MA_NO_RUNTIME_LINKING
- #ifdef MA_WIN32
- FreeLibrary((HMODULE)handle);
- #else
- /* Hack for Android bug (see https://github.com/android/ndk/issues/360). Calling dlclose() pre-API 28 may segfault. */
- #if !defined(MA_ANDROID) || (defined(__ANDROID_API__) && __ANDROID_API__ >= 28)
+ #ifndef MA_NO_RUNTIME_LINKING
+ {
+ #ifdef MA_WIN32
{
- dlclose((void*)handle);
+ FreeLibrary((HMODULE)handle);
}
#else
{
- (void)handle;
+ /* Hack for Android bug (see https://github.com/android/ndk/issues/360). Calling dlclose() pre-API 28 may segfault. */
+ #if !defined(MA_ANDROID) || (defined(__ANDROID_API__) && __ANDROID_API__ >= 28)
+ {
+ dlclose((void*)handle);
+ }
+ #else
+ {
+ (void)handle;
+ }
+ #endif
}
#endif
- #endif
- (void)pLog;
-#else
- /* Runtime linking is disabled. */
- (void)pLog;
- (void)handle;
-#endif
+ (void)pLog;
+ }
+ #else
+ {
+ /* Runtime linking is disabled. */
+ (void)pLog;
+ (void)handle;
+ }
+ #endif
}
MA_API ma_proc ma_dlsym(ma_log* pLog, ma_handle handle, const char* symbol)
{
-#ifndef MA_NO_RUNTIME_LINKING
- ma_proc proc;
+ #ifndef MA_NO_RUNTIME_LINKING
+ {
+ ma_proc proc;
- ma_log_postf(pLog, MA_LOG_LEVEL_DEBUG, "Loading symbol: %s\n", symbol);
+ ma_log_postf(pLog, MA_LOG_LEVEL_DEBUG, "Loading symbol: %s\n", symbol);
-#ifdef _WIN32
- proc = (ma_proc)GetProcAddress((HMODULE)handle, symbol);
-#else
-#if (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))) || defined(__clang__)
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wpedantic"
-#endif
- proc = (ma_proc)dlsym((void*)handle, symbol);
-#if (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))) || defined(__clang__)
- #pragma GCC diagnostic pop
-#endif
-#endif
+ #ifdef _WIN32
+ {
+ proc = (ma_proc)GetProcAddress((HMODULE)handle, symbol);
+ }
+ #else
+ {
+ #if (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))) || defined(__clang__)
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wpedantic"
+ #endif
+ proc = (ma_proc)dlsym((void*)handle, symbol);
+ #if (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))) || defined(__clang__)
+ #pragma GCC diagnostic pop
+ #endif
+ }
+ #endif
- if (proc == NULL) {
- ma_log_postf(pLog, MA_LOG_LEVEL_WARNING, "Failed to load symbol: %s\n", symbol);
+ if (proc == NULL) {
+ ma_log_postf(pLog, MA_LOG_LEVEL_WARNING, "Failed to load symbol: %s\n", symbol);
+ }
+
+ (void)pLog; /* It's possible for pContext to be unused. */
+ return proc;
}
-
- (void)pLog; /* It's possible for pContext to be unused. */
- return proc;
-#else
- /* Runtime linking is disabled. */
- (void)pLog;
- (void)handle;
- (void)symbol;
- return NULL;
-#endif
+ #else
+ {
+ /* Runtime linking is disabled. */
+ (void)pLog;
+ (void)handle;
+ (void)symbol;
+ return NULL;
+ }
+ #endif
}
@@ -18020,13 +19439,6 @@ DEVICE I/O
*************************************************************************************************************************************************************
************************************************************************************************************************************************************/
-/* Disable run-time linking on certain backends and platforms. */
-#ifndef MA_NO_RUNTIME_LINKING
- #if defined(MA_EMSCRIPTEN) || defined(MA_ORBIS) || defined(MA_PROSPERO)
- #define MA_NO_RUNTIME_LINKING
- #endif
-#endif
-
#ifdef MA_APPLE
#include
#endif
@@ -18039,12 +19451,6 @@ DEVICE I/O
#ifdef MA_POSIX
#include
- #include
-
- /* No need for dlfcn.h if we're not using runtime linking. */
- #ifndef MA_NO_RUNTIME_LINKING
- #include
- #endif
#endif
/* This must be set to at least 26. */
@@ -18299,7 +19705,7 @@ MA_API ma_bool32 ma_is_loopback_supported(ma_backend backend)
-#if defined(MA_WIN32)
+#if defined(MA_WIN32) && !defined(MA_XBOX)
/* WASAPI error codes. */
#define MA_AUDCLNT_E_NOT_INITIALIZED ((HRESULT)0x88890001)
#define MA_AUDCLNT_E_ALREADY_INITIALIZED ((HRESULT)0x88890002)
@@ -18514,6 +19920,11 @@ typedef LONG (WINAPI * MA_PFN_RegCloseKey)(HKEY hKey);
typedef LONG (WINAPI * MA_PFN_RegQueryValueExA)(HKEY hKey, const char* lpValueName, DWORD* lpReserved, DWORD* lpType, BYTE* lpData, DWORD* lpcbData);
#endif /* MA_WIN32_DESKTOP */
+static GUID MA_GUID_KSDATAFORMAT_SUBTYPE_PCM = {0x00000001, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
+static GUID MA_GUID_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT = {0x00000003, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
+/*static GUID MA_GUID_KSDATAFORMAT_SUBTYPE_ALAW = {0x00000006, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};*/
+/*static GUID MA_GUID_KSDATAFORMAT_SUBTYPE_MULAW = {0x00000007, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};*/
+
MA_API size_t ma_strlen_WCHAR(const WCHAR* str)
{
size_t len = 0;
@@ -18577,7 +19988,7 @@ Timing
*******************************************************************************/
#if defined(MA_WIN32) && !defined(MA_POSIX)
static LARGE_INTEGER g_ma_TimerFrequency; /* <-- Initialized to zero since it's static. */
- static void ma_timer_init(ma_timer* pTimer)
+ static MA_INLINE void ma_timer_init(ma_timer* pTimer)
{
LARGE_INTEGER counter;
@@ -18589,7 +20000,7 @@ Timing
pTimer->counter = counter.QuadPart;
}
- static double ma_timer_get_time_in_seconds(ma_timer* pTimer)
+ static MA_INLINE double ma_timer_get_time_in_seconds(ma_timer* pTimer)
{
LARGE_INTEGER counter;
if (!QueryPerformanceCounter(&counter)) {
@@ -18600,7 +20011,7 @@ Timing
}
#elif defined(MA_APPLE) && (MAC_OS_X_VERSION_MIN_REQUIRED < 101200)
static ma_uint64 g_ma_TimerFrequency = 0;
- static void ma_timer_init(ma_timer* pTimer)
+ static MA_INLINE void ma_timer_init(ma_timer* pTimer)
{
mach_timebase_info_data_t baseTime;
mach_timebase_info(&baseTime);
@@ -18609,7 +20020,7 @@ Timing
pTimer->counter = mach_absolute_time();
}
- static double ma_timer_get_time_in_seconds(ma_timer* pTimer)
+ static MA_INLINE double ma_timer_get_time_in_seconds(ma_timer* pTimer)
{
ma_uint64 newTimeCounter = mach_absolute_time();
ma_uint64 oldTimeCounter = pTimer->counter;
@@ -18634,7 +20045,7 @@ Timing
#define MA_CLOCK_ID CLOCK_REALTIME
#endif
- static void ma_timer_init(ma_timer* pTimer)
+ static MA_INLINE void ma_timer_init(ma_timer* pTimer)
{
struct timespec newTime;
clock_gettime(MA_CLOCK_ID, &newTime);
@@ -18642,7 +20053,7 @@ Timing
pTimer->counter = (newTime.tv_sec * 1000000000) + newTime.tv_nsec;
}
- static double ma_timer_get_time_in_seconds(ma_timer* pTimer)
+ static MA_INLINE double ma_timer_get_time_in_seconds(ma_timer* pTimer)
{
ma_uint64 newTimeCounter;
ma_uint64 oldTimeCounter;
@@ -18656,7 +20067,7 @@ Timing
return (newTimeCounter - oldTimeCounter) / 1000000000.0;
}
#else
- static void ma_timer_init(ma_timer* pTimer)
+ static MA_INLINE void ma_timer_init(ma_timer* pTimer)
{
struct timeval newTime;
gettimeofday(&newTime, NULL);
@@ -18664,7 +20075,7 @@ Timing
pTimer->counter = (newTime.tv_sec * 1000000) + newTime.tv_usec;
}
- static double ma_timer_get_time_in_seconds(ma_timer* pTimer)
+ static MA_INLINE double ma_timer_get_time_in_seconds(ma_timer* pTimer)
{
ma_uint64 newTimeCounter;
ma_uint64 oldTimeCounter;
@@ -19248,14 +20659,6 @@ static MA_INLINE void ma_device__set_state(ma_device* pDevice, ma_device_state n
}
-#if defined(MA_WIN32)
- static GUID MA_GUID_KSDATAFORMAT_SUBTYPE_PCM = {0x00000001, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
- static GUID MA_GUID_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT = {0x00000003, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
- /*static GUID MA_GUID_KSDATAFORMAT_SUBTYPE_ALAW = {0x00000006, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};*/
- /*static GUID MA_GUID_KSDATAFORMAT_SUBTYPE_MULAW = {0x00000007, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};*/
-#endif
-
-
MA_API ma_uint32 ma_get_format_priority_index(ma_format format) /* Lower = better. */
{
@@ -19967,7 +21370,7 @@ static ma_result ma_context_init__null(ma_context* pContext, const ma_context_co
WIN32 COMMON
*******************************************************************************/
-#if defined(MA_WIN32)
+#if defined(MA_WIN32) && !defined(MA_XBOX)
#if defined(MA_WIN32_DESKTOP) || defined(MA_WIN32_GDK)
#define ma_CoInitializeEx(pContext, pvReserved, dwCoInit) ((pContext->win32.CoInitializeEx) ? ((MA_PFN_CoInitializeEx)pContext->win32.CoInitializeEx)(pvReserved, dwCoInit) : ((MA_PFN_CoInitialize)pContext->win32.CoInitialize)(pvReserved))
#define ma_CoUninitialize(pContext) ((MA_PFN_CoUninitialize)pContext->win32.CoUninitialize)()
@@ -19982,7 +21385,7 @@ WIN32 COMMON
#define ma_PropVariantClear(pContext, pvar) PropVariantClear(pvar)
#endif
-#if !defined(MAXULONG_PTR) && !defined(__WATCOMC__)
+#if !defined(MAXULONG_PTR) && !defined(__WATCOMC__) && !defined(MA_XBOX_NXDK)
typedef size_t DWORD_PTR;
#endif
@@ -20409,11 +21812,21 @@ typedef enum
MA_AudioCategory_Other = 0 /* <-- miniaudio is only caring about Other. */
} MA_AUDIO_STREAM_CATEGORY;
+typedef enum
+{
+ MA_AUDCLNT_STREAMOPTIONS_NONE,
+ MA_AUDCLNT_STREAMOPTIONS_RAW,
+ MA_AUDCLNT_STREAMOPTIONS_MATCH_FORMAT,
+ MA_AUDCLNT_STREAMOPTIONS_AMBISONICS,
+ MA_AUDCLNT_STREAMOPTIONS_POST_VOLUME_LOOPBACK
+} MA_AUDCLNT_STREAMOPTIONS;
+
typedef struct
{
ma_uint32 cbSize;
BOOL bIsOffload;
MA_AUDIO_STREAM_CATEGORY eCategory;
+ MA_AUDCLNT_STREAMOPTIONS Options;
} ma_AudioClientProperties;
/* IUnknown */
@@ -21588,6 +23001,7 @@ static ma_result ma_context_get_MMDevice__wasapi(ma_context* pContext, ma_device
{
ma_IMMDeviceEnumerator* pDeviceEnumerator;
HRESULT hr;
+ HRESULT CoInitializeResult;
MA_ASSERT(pContext != NULL);
MA_ASSERT(ppMMDevice != NULL);
@@ -21601,12 +23015,17 @@ static ma_result ma_context_get_MMDevice__wasapi(ma_context* pContext, ma_device
The community has reported that this seems to fix the crash. There are future plans to move all WASAPI operation
over to a single thread to make everything safer, but in the meantime while we wait for that to come online I'm
happy enough to use this hack instead.
+
+ CoUninitialize should only be called if we successfully initialized. S_OK and S_FALSE both mean that we need to
+ call CoUninitialize since the internal ref count was increased. RPC_E_CHANGED_MODE means that CoInitializeEx was
+ called with a different COINIT value, and we don't call CoUninitialize in that case. Other errors are possible,
+ so we check for S_OK and S_FALSE specifically.
*/
- ma_CoInitializeEx(pContext, NULL, MA_COINIT_VALUE);
+ CoInitializeResult = ma_CoInitializeEx(pContext, NULL, MA_COINIT_VALUE);
{
hr = ma_CoCreateInstance(pContext, &MA_CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, &MA_IID_IMMDeviceEnumerator, (void**)&pDeviceEnumerator);
- }
- ma_CoUninitialize(pContext);
+ }
+ if (CoInitializeResult == S_OK || CoInitializeResult == S_FALSE) { ma_CoUninitialize(pContext); }
if (FAILED(hr)) { /* <-- This is checking the call above to ma_CoCreateInstance(). */
ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to create IMMDeviceEnumerator.\n");
@@ -21950,7 +23369,7 @@ static ma_result ma_context_get_IAudioClient__wasapi(ma_context* pContext, ma_de
pActivationParams = &activationParams;
/* When requesting a specific device ID we need to use a special device ID. */
- MA_COPY_MEMORY(virtualDeviceID.wasapi, MA_VIRTUAL_AUDIO_DEVICE_PROCESS_LOOPBACK, (wcslen(MA_VIRTUAL_AUDIO_DEVICE_PROCESS_LOOPBACK) + 1) * sizeof(wchar_t)); /* +1 for the null terminator. */
+ MA_COPY_MEMORY(virtualDeviceID.wasapi, MA_VIRTUAL_AUDIO_DEVICE_PROCESS_LOOPBACK, (ma_wcslen(MA_VIRTUAL_AUDIO_DEVICE_PROCESS_LOOPBACK) + 1) * sizeof(wchar_t)); /* +1 for the null terminator. */
pDeviceID = &virtualDeviceID;
} else {
pActivationParams = NULL; /* No activation parameters required. */
@@ -26679,6 +28098,9 @@ typedef snd_pcm_channel_area_t ma_snd_pcm_channel_area_t;
typedef snd_pcm_chmap_t ma_snd_pcm_chmap_t;
typedef snd_pcm_state_t ma_snd_pcm_state_t;
+/* snd_pcm_state_t */
+#define MA_SND_PCM_STATE_XRUN SND_PCM_STATE_XRUN
+
/* snd_pcm_stream_t */
#define MA_SND_PCM_STREAM_PLAYBACK SND_PCM_STREAM_PLAYBACK
#define MA_SND_PCM_STREAM_CAPTURE SND_PCM_STREAM_CAPTURE
@@ -26874,6 +28296,7 @@ typedef int (* ma_snd_pcm_hw_params_set_channels_minmax_proc) (
typedef int (* ma_snd_pcm_hw_params_set_rate_resample_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_hw_params_t *params, unsigned int val);
typedef int (* ma_snd_pcm_hw_params_set_rate_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_hw_params_t *params, unsigned int val, int dir);
typedef int (* ma_snd_pcm_hw_params_set_rate_near_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_hw_params_t *params, unsigned int *val, int *dir);
+typedef int (* ma_snd_pcm_hw_params_set_rate_minmax_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_hw_params_t *params, unsigned int *min, int *mindir, unsigned int *max, int *maxdir);
typedef int (* ma_snd_pcm_hw_params_set_buffer_size_near_proc)(ma_snd_pcm_t *pcm, ma_snd_pcm_hw_params_t *params, ma_snd_pcm_uframes_t *val);
typedef int (* ma_snd_pcm_hw_params_set_periods_near_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_hw_params_t *params, unsigned int *val, int *dir);
typedef int (* ma_snd_pcm_hw_params_set_access_proc) (ma_snd_pcm_t *pcm, ma_snd_pcm_hw_params_t *params, ma_snd_pcm_access_t _access);
@@ -28640,8 +30063,9 @@ static ma_result ma_context_init__alsa(ma_context* pContext, const ma_context_co
ma_snd_pcm_hw_params_get_format_mask_proc _snd_pcm_hw_params_get_format_mask = snd_pcm_hw_params_get_format_mask;
ma_snd_pcm_hw_params_set_channels_proc _snd_pcm_hw_params_set_channels = snd_pcm_hw_params_set_channels;
ma_snd_pcm_hw_params_set_channels_near_proc _snd_pcm_hw_params_set_channels_near = snd_pcm_hw_params_set_channels_near;
+ ma_snd_pcm_hw_params_set_channels_minmax_proc _snd_pcm_hw_params_set_channels_minmax = snd_pcm_hw_params_set_channels_minmax;
ma_snd_pcm_hw_params_set_rate_resample_proc _snd_pcm_hw_params_set_rate_resample = snd_pcm_hw_params_set_rate_resample;
- ma_snd_pcm_hw_params_set_rate_near _snd_pcm_hw_params_set_rate = snd_pcm_hw_params_set_rate;
+ ma_snd_pcm_hw_params_set_rate_proc _snd_pcm_hw_params_set_rate = snd_pcm_hw_params_set_rate;
ma_snd_pcm_hw_params_set_rate_near_proc _snd_pcm_hw_params_set_rate_near = snd_pcm_hw_params_set_rate_near;
ma_snd_pcm_hw_params_set_rate_minmax_proc _snd_pcm_hw_params_set_rate_minmax = snd_pcm_hw_params_set_rate_minmax;
ma_snd_pcm_hw_params_set_buffer_size_near_proc _snd_pcm_hw_params_set_buffer_size_near = snd_pcm_hw_params_set_buffer_size_near;
@@ -28693,9 +30117,9 @@ static ma_result ma_context_init__alsa(ma_context* pContext, const ma_context_co
ma_snd_pcm_info_proc _snd_pcm_info = snd_pcm_info;
ma_snd_pcm_info_sizeof_proc _snd_pcm_info_sizeof = snd_pcm_info_sizeof;
ma_snd_pcm_info_get_name_proc _snd_pcm_info_get_name = snd_pcm_info_get_name;
- ma_snd_pcm_poll_descriptors _snd_pcm_poll_descriptors = snd_pcm_poll_descriptors;
- ma_snd_pcm_poll_descriptors_count _snd_pcm_poll_descriptors_count = snd_pcm_poll_descriptors_count;
- ma_snd_pcm_poll_descriptors_revents _snd_pcm_poll_descriptors_revents = snd_pcm_poll_descriptors_revents;
+ ma_snd_pcm_poll_descriptors_proc _snd_pcm_poll_descriptors = snd_pcm_poll_descriptors;
+ ma_snd_pcm_poll_descriptors_count_proc _snd_pcm_poll_descriptors_count = snd_pcm_poll_descriptors_count;
+ ma_snd_pcm_poll_descriptors_revents_proc _snd_pcm_poll_descriptors_revents = snd_pcm_poll_descriptors_revents;
ma_snd_config_update_free_global_proc _snd_config_update_free_global = snd_config_update_free_global;
pContext->alsa.snd_pcm_open = (ma_proc)_snd_pcm_open;
@@ -28711,6 +30135,7 @@ static ma_result ma_context_init__alsa(ma_context* pContext, const ma_context_co
pContext->alsa.snd_pcm_hw_params_set_rate_resample = (ma_proc)_snd_pcm_hw_params_set_rate_resample;
pContext->alsa.snd_pcm_hw_params_set_rate = (ma_proc)_snd_pcm_hw_params_set_rate;
pContext->alsa.snd_pcm_hw_params_set_rate_near = (ma_proc)_snd_pcm_hw_params_set_rate_near;
+ pContext->alsa.snd_pcm_hw_params_set_rate_minmax = (ma_proc)_snd_pcm_hw_params_set_rate_minmax;
pContext->alsa.snd_pcm_hw_params_set_buffer_size_near = (ma_proc)_snd_pcm_hw_params_set_buffer_size_near;
pContext->alsa.snd_pcm_hw_params_set_periods_near = (ma_proc)_snd_pcm_hw_params_set_periods_near;
pContext->alsa.snd_pcm_hw_params_set_access = (ma_proc)_snd_pcm_hw_params_set_access;
@@ -29436,7 +30861,7 @@ typedef void (* ma_pa_threaded_mainloop_unlock_proc) (
typedef void (* ma_pa_threaded_mainloop_wait_proc) (ma_pa_threaded_mainloop* m);
typedef void (* ma_pa_threaded_mainloop_signal_proc) (ma_pa_threaded_mainloop* m, int wait_for_accept);
typedef void (* ma_pa_threaded_mainloop_accept_proc) (ma_pa_threaded_mainloop* m);
-typedef int (* ma_pa_threaded_mainloop_get_retval_proc) (ma_pa_threaded_mainloop* m);
+typedef int (* ma_pa_threaded_mainloop_get_retval_proc) (const ma_pa_threaded_mainloop* m);
typedef ma_pa_mainloop_api* (* ma_pa_threaded_mainloop_get_api_proc) (ma_pa_threaded_mainloop* m);
typedef int (* ma_pa_threaded_mainloop_in_thread_proc) (ma_pa_threaded_mainloop* m);
typedef void (* ma_pa_threaded_mainloop_set_name_proc) (ma_pa_threaded_mainloop* m, const char* name);
@@ -29445,13 +30870,13 @@ typedef void (* ma_pa_context_unref_proc) (
typedef int (* ma_pa_context_connect_proc) (ma_pa_context* c, const char* server, ma_pa_context_flags_t flags, const ma_pa_spawn_api* api);
typedef void (* ma_pa_context_disconnect_proc) (ma_pa_context* c);
typedef void (* ma_pa_context_set_state_callback_proc) (ma_pa_context* c, ma_pa_context_notify_cb_t cb, void* userdata);
-typedef ma_pa_context_state_t (* ma_pa_context_get_state_proc) (ma_pa_context* c);
+typedef ma_pa_context_state_t (* ma_pa_context_get_state_proc) (const ma_pa_context* c);
typedef ma_pa_operation* (* ma_pa_context_get_sink_info_list_proc) (ma_pa_context* c, ma_pa_sink_info_cb_t cb, void* userdata);
typedef ma_pa_operation* (* ma_pa_context_get_source_info_list_proc) (ma_pa_context* c, ma_pa_source_info_cb_t cb, void* userdata);
typedef ma_pa_operation* (* ma_pa_context_get_sink_info_by_name_proc) (ma_pa_context* c, const char* name, ma_pa_sink_info_cb_t cb, void* userdata);
typedef ma_pa_operation* (* ma_pa_context_get_source_info_by_name_proc)(ma_pa_context* c, const char* name, ma_pa_source_info_cb_t cb, void* userdata);
typedef void (* ma_pa_operation_unref_proc) (ma_pa_operation* o);
-typedef ma_pa_operation_state_t (* ma_pa_operation_get_state_proc) (ma_pa_operation* o);
+typedef ma_pa_operation_state_t (* ma_pa_operation_get_state_proc) (const ma_pa_operation* o);
typedef ma_pa_channel_map* (* ma_pa_channel_map_init_extend_proc) (ma_pa_channel_map* m, unsigned channels, ma_pa_channel_map_def_t def);
typedef int (* ma_pa_channel_map_valid_proc) (const ma_pa_channel_map* m);
typedef int (* ma_pa_channel_map_compatible_proc) (const ma_pa_channel_map* m, const ma_pa_sample_spec* ss);
@@ -29460,12 +30885,12 @@ typedef void (* ma_pa_stream_unref_proc) (
typedef int (* ma_pa_stream_connect_playback_proc) (ma_pa_stream* s, const char* dev, const ma_pa_buffer_attr* attr, ma_pa_stream_flags_t flags, const ma_pa_cvolume* volume, ma_pa_stream* sync_stream);
typedef int (* ma_pa_stream_connect_record_proc) (ma_pa_stream* s, const char* dev, const ma_pa_buffer_attr* attr, ma_pa_stream_flags_t flags);
typedef int (* ma_pa_stream_disconnect_proc) (ma_pa_stream* s);
-typedef ma_pa_stream_state_t (* ma_pa_stream_get_state_proc) (ma_pa_stream* s);
+typedef ma_pa_stream_state_t (* ma_pa_stream_get_state_proc) (const ma_pa_stream* s);
typedef const ma_pa_sample_spec* (* ma_pa_stream_get_sample_spec_proc) (ma_pa_stream* s);
typedef const ma_pa_channel_map* (* ma_pa_stream_get_channel_map_proc) (ma_pa_stream* s);
typedef const ma_pa_buffer_attr* (* ma_pa_stream_get_buffer_attr_proc) (ma_pa_stream* s);
typedef ma_pa_operation* (* ma_pa_stream_set_buffer_attr_proc) (ma_pa_stream* s, const ma_pa_buffer_attr* attr, ma_pa_stream_success_cb_t cb, void* userdata);
-typedef const char* (* ma_pa_stream_get_device_name_proc) (ma_pa_stream* s);
+typedef const char* (* ma_pa_stream_get_device_name_proc) (const ma_pa_stream* s);
typedef void (* ma_pa_stream_set_write_callback_proc) (ma_pa_stream* s, ma_pa_stream_request_cb_t cb, void* userdata);
typedef void (* ma_pa_stream_set_read_callback_proc) (ma_pa_stream* s, ma_pa_stream_request_cb_t cb, void* userdata);
typedef void (* ma_pa_stream_set_suspended_callback_proc) (ma_pa_stream* s, ma_pa_stream_notify_cb_t cb, void* userdata);
@@ -29473,15 +30898,15 @@ typedef void (* ma_pa_stream_set_moved_callback_proc) (
typedef int (* ma_pa_stream_is_suspended_proc) (const ma_pa_stream* s);
typedef ma_pa_operation* (* ma_pa_stream_flush_proc) (ma_pa_stream* s, ma_pa_stream_success_cb_t cb, void* userdata);
typedef ma_pa_operation* (* ma_pa_stream_drain_proc) (ma_pa_stream* s, ma_pa_stream_success_cb_t cb, void* userdata);
-typedef int (* ma_pa_stream_is_corked_proc) (ma_pa_stream* s);
+typedef int (* ma_pa_stream_is_corked_proc) (const ma_pa_stream* s);
typedef ma_pa_operation* (* ma_pa_stream_cork_proc) (ma_pa_stream* s, int b, ma_pa_stream_success_cb_t cb, void* userdata);
typedef ma_pa_operation* (* ma_pa_stream_trigger_proc) (ma_pa_stream* s, ma_pa_stream_success_cb_t cb, void* userdata);
typedef int (* ma_pa_stream_begin_write_proc) (ma_pa_stream* s, void** data, size_t* nbytes);
typedef int (* ma_pa_stream_write_proc) (ma_pa_stream* s, const void* data, size_t nbytes, ma_pa_free_cb_t free_cb, int64_t offset, ma_pa_seek_mode_t seek);
typedef int (* ma_pa_stream_peek_proc) (ma_pa_stream* s, const void** data, size_t* nbytes);
typedef int (* ma_pa_stream_drop_proc) (ma_pa_stream* s);
-typedef size_t (* ma_pa_stream_writable_size_proc) (ma_pa_stream* s);
-typedef size_t (* ma_pa_stream_readable_size_proc) (ma_pa_stream* s);
+typedef size_t (* ma_pa_stream_writable_size_proc) (const ma_pa_stream* s);
+typedef size_t (* ma_pa_stream_readable_size_proc) (const ma_pa_stream* s);
typedef struct
{
@@ -29777,7 +31202,7 @@ static ma_result ma_init_pa_mainloop_and_pa_context__pulse(ma_context* pContext,
}
/* Now we need to connect to the context. Everything is asynchronous so we need to wait for it to connect before returning. */
- result = ma_result_from_pulse(((ma_pa_context_connect_proc)pContext->pulse.pa_context_connect)((ma_pa_context*)pPulseContext, pServerName, (tryAutoSpawn) ? 0 : MA_PA_CONTEXT_NOAUTOSPAWN, NULL));
+ result = ma_result_from_pulse(((ma_pa_context_connect_proc)pContext->pulse.pa_context_connect)((ma_pa_context*)pPulseContext, pServerName, (tryAutoSpawn) ? MA_PA_CONTEXT_NOFLAGS : MA_PA_CONTEXT_NOAUTOSPAWN, NULL));
if (result != MA_SUCCESS) {
ma_log_postf(ma_context_get_log(pContext), MA_LOG_LEVEL_ERROR, "[PulseAudio] Failed to connect PulseAudio context.");
((ma_pa_mainloop_free_proc)pContext->pulse.pa_mainloop_free)((ma_pa_mainloop*)(pMainLoop));
@@ -30510,7 +31935,7 @@ static ma_result ma_device_init__pulse(ma_device* pDevice, const ma_device_confi
const ma_pa_buffer_attr* pActualAttr = NULL;
const ma_pa_channel_map* pActualChannelMap = NULL;
ma_uint32 iChannel;
- ma_pa_stream_flags_t streamFlags;
+ int streamFlags;
MA_ASSERT(pDevice != NULL);
MA_ZERO_OBJECT(&pDevice->pulse);
@@ -30568,8 +31993,13 @@ static ma_result ma_device_init__pulse(ma_device* pDevice, const ma_device_confi
ss.channels = pDescriptorCapture->channels;
}
+ /* PulseAudio has a maximum channel count of 32. We'll get a crash if this is exceeded. */
+ if (ss.channels > 32) {
+ ss.channels = 32;
+ }
+
/* Use a default channel map. */
- ((ma_pa_channel_map_init_extend_proc)pDevice->pContext->pulse.pa_channel_map_init_extend)(&cmap, ss.channels, pConfig->pulse.channelMap);
+ ((ma_pa_channel_map_init_extend_proc)pDevice->pContext->pulse.pa_channel_map_init_extend)(&cmap, ss.channels, (ma_pa_channel_map_def_t)pConfig->pulse.channelMap);
/* Use the requested sample rate if one was specified. */
if (pDescriptorCapture->sampleRate != 0) {
@@ -30626,7 +32056,7 @@ static ma_result ma_device_init__pulse(ma_device* pDevice, const ma_device_confi
streamFlags |= MA_PA_STREAM_DONT_MOVE;
}
- error = ((ma_pa_stream_connect_record_proc)pDevice->pContext->pulse.pa_stream_connect_record)((ma_pa_stream*)pDevice->pulse.pStreamCapture, devCapture, &attr, streamFlags);
+ error = ((ma_pa_stream_connect_record_proc)pDevice->pContext->pulse.pa_stream_connect_record)((ma_pa_stream*)pDevice->pulse.pStreamCapture, devCapture, &attr, (ma_pa_stream_flags_t)streamFlags);
if (error != MA_PA_OK) {
ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[PulseAudio] Failed to connect PulseAudio capture stream.");
result = ma_result_from_pulse(error);
@@ -30720,8 +32150,13 @@ static ma_result ma_device_init__pulse(ma_device* pDevice, const ma_device_confi
ss.channels = pDescriptorPlayback->channels;
}
+ /* PulseAudio has a maximum channel count of 32. We'll get a crash if this is exceeded. */
+ if (ss.channels > 32) {
+ ss.channels = 32;
+ }
+
/* Use a default channel map. */
- ((ma_pa_channel_map_init_extend_proc)pDevice->pContext->pulse.pa_channel_map_init_extend)(&cmap, ss.channels, pConfig->pulse.channelMap);
+ ((ma_pa_channel_map_init_extend_proc)pDevice->pContext->pulse.pa_channel_map_init_extend)(&cmap, ss.channels, (ma_pa_channel_map_def_t)pConfig->pulse.channelMap);
/* Use the requested sample rate if one was specified. */
@@ -30783,7 +32218,7 @@ static ma_result ma_device_init__pulse(ma_device* pDevice, const ma_device_confi
streamFlags |= MA_PA_STREAM_DONT_MOVE;
}
- error = ((ma_pa_stream_connect_playback_proc)pDevice->pContext->pulse.pa_stream_connect_playback)((ma_pa_stream*)pDevice->pulse.pStreamPlayback, devPlayback, &attr, streamFlags, NULL, NULL);
+ error = ((ma_pa_stream_connect_playback_proc)pDevice->pContext->pulse.pa_stream_connect_playback)((ma_pa_stream*)pDevice->pulse.pStreamPlayback, devPlayback, &attr, (ma_pa_stream_flags_t)streamFlags, NULL, NULL);
if (error != MA_PA_OK) {
ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[PulseAudio] Failed to connect PulseAudio playback stream.");
result = ma_result_from_pulse(error);
@@ -31338,6 +32773,7 @@ typedef JackProcessCallback ma_JackProcessCallback;
typedef JackBufferSizeCallback ma_JackBufferSizeCallback;
typedef JackShutdownCallback ma_JackShutdownCallback;
#define MA_JACK_DEFAULT_AUDIO_TYPE JACK_DEFAULT_AUDIO_TYPE
+#define ma_JackNullOption JackNullOption
#define ma_JackNoStartServer JackNoStartServer
#define ma_JackPortIsInput JackPortIsInput
#define ma_JackPortIsOutput JackPortIsOutput
@@ -31352,6 +32788,7 @@ typedef int (* ma_JackProcessCallback) (ma_jack_nframes_t nframes, void* arg)
typedef int (* ma_JackBufferSizeCallback)(ma_jack_nframes_t nframes, void* arg);
typedef void (* ma_JackShutdownCallback) (void* arg);
#define MA_JACK_DEFAULT_AUDIO_TYPE "32 bit float mono audio"
+#define ma_JackNullOption 0
#define ma_JackNoStartServer 1
#define ma_JackPortIsInput 1
#define ma_JackPortIsOutput 2
@@ -31392,7 +32829,7 @@ static ma_result ma_context_open_client__jack(ma_context* pContext, ma_jack_clie
maxClientNameSize = ((ma_jack_client_name_size_proc)pContext->jack.jack_client_name_size)(); /* Includes null terminator. */
ma_strncpy_s(clientName, ma_min(sizeof(clientName), maxClientNameSize), (pContext->jack.pClientName != NULL) ? pContext->jack.pClientName : "miniaudio", (size_t)-1);
- pClient = ((ma_jack_client_open_proc)pContext->jack.jack_client_open)(clientName, (pContext->jack.tryStartServer) ? 0 : ma_JackNoStartServer, &status, NULL);
+ pClient = ((ma_jack_client_open_proc)pContext->jack.jack_client_open)(clientName, (pContext->jack.tryStartServer) ? ma_JackNullOption : ma_JackNoStartServer, &status, NULL);
if (pClient == NULL) {
return MA_FAILED_TO_OPEN_BACKEND_DEVICE;
}
@@ -36994,7 +38431,7 @@ OSS Backend
#define MA_OSS_DEFAULT_DEVICE_NAME "/dev/dsp"
-static int ma_open_temp_device__oss()
+static int ma_open_temp_device__oss(void)
{
/* The OSS sample code uses "/dev/mixer" as the device for getting system properties so I'm going to do the same. */
int fd = open("/dev/mixer", O_RDONLY, 0);
@@ -37834,25 +39271,30 @@ static void ma_stream_error_callback__aaudio(ma_AAudioStream* pStream, void* pUs
(void)error;
ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, "[AAudio] ERROR CALLBACK: error=%d, AAudioStream_getState()=%d\n", error, ((MA_PFN_AAudioStream_getState)pDevice->pContext->aaudio.AAudioStream_getState)(pStream));
+
/*
When we get an error, we'll assume that the stream is in an erroneous state and needs to be restarted. From the documentation,
we cannot do this from the error callback. Therefore we are going to use an event thread for the AAudio backend to do this
cleanly and safely.
*/
- job = ma_job_init(MA_JOB_TYPE_DEVICE_AAUDIO_REROUTE);
- job.data.device.aaudio.reroute.pDevice = pDevice;
-
- if (pStream == pDevice->aaudio.pStreamCapture) {
- job.data.device.aaudio.reroute.deviceType = ma_device_type_capture;
+ if (ma_atomic_bool32_get(&pDevice->aaudio.isTearingDown)) {
+ ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, "[AAudio] Device Disconnected. Tearing down device.\n");
}
else {
- job.data.device.aaudio.reroute.deviceType = ma_device_type_playback;
- }
-
- result = ma_device_job_thread_post(&pDevice->pContext->aaudio.jobThread, &job);
- if (result != MA_SUCCESS) {
- ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, "[AAudio] Device Disconnected. Failed to post job for rerouting.\n");
- return;
+ job = ma_job_init(MA_JOB_TYPE_DEVICE_AAUDIO_REROUTE);
+ job.data.device.aaudio.reroute.pDevice = pDevice;
+
+ if (pStream == pDevice->aaudio.pStreamCapture) {
+ job.data.device.aaudio.reroute.deviceType = ma_device_type_capture;
+ } else {
+ job.data.device.aaudio.reroute.deviceType = ma_device_type_playback;
+ }
+
+ result = ma_device_job_thread_post(&pDevice->pContext->aaudio.jobThread, &job);
+ if (result != MA_SUCCESS) {
+ ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, "[AAudio] Device Disconnected. Failed to post job for rerouting.\n");
+ return;
+ }
}
}
@@ -38169,7 +39611,7 @@ static ma_result ma_close_streams__aaudio(ma_device* pDevice)
{
MA_ASSERT(pDevice != NULL);
- /* When re-routing, streams may have been closed and never re-opened. Hence the extra checks below. */
+ /* When rerouting, streams may have been closed and never re-opened. Hence the extra checks below. */
if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
ma_close_stream__aaudio(pDevice->pContext, (ma_AAudioStream*)pDevice->aaudio.pStreamCapture);
pDevice->aaudio.pStreamCapture = NULL;
@@ -38186,6 +39628,12 @@ static ma_result ma_device_uninit__aaudio(ma_device* pDevice)
{
MA_ASSERT(pDevice != NULL);
+ /*
+ Note: Closing the streams may cause a timeout error, which would then trigger rerouting in our error callback.
+ We must not schedule a reroute when device is getting destroyed.
+ */
+ ma_atomic_bool32_set(&pDevice->aaudio.isTearingDown, MA_TRUE);
+
/* Wait for any rerouting to finish before attempting to close the streams. */
ma_mutex_lock(&pDevice->aaudio.rerouteLock);
{
@@ -38193,7 +39641,7 @@ static ma_result ma_device_uninit__aaudio(ma_device* pDevice)
}
ma_mutex_unlock(&pDevice->aaudio.rerouteLock);
- /* Destroy re-routing lock. */
+ /* Destroy rerouting lock. */
ma_mutex_uninit(&pDevice->aaudio.rerouteLock);
return MA_SUCCESS;
@@ -38429,17 +39877,22 @@ static ma_result ma_device_stop__aaudio(ma_device* pDevice)
static ma_result ma_device_reinit__aaudio(ma_device* pDevice, ma_device_type deviceType)
{
+ const ma_int32 maxAttempts = 4; /* Reasonable retry limit. */
+
ma_result result;
- int32_t retries = 0;
+ ma_int32 iAttempt;
MA_ASSERT(pDevice != NULL);
- /*
- TODO: Stop retrying if main thread is about to uninit device.
- */
- ma_mutex_lock(&pDevice->aaudio.rerouteLock);
- {
-error_disconnected:
+ /* We got disconnected! Retry a few times, until we find a connected device! */
+ iAttempt = 0;
+ while (iAttempt++ < maxAttempts) {
+ /* Device tearing down? No need to reroute! */
+ if (ma_atomic_bool32_get(&pDevice->aaudio.isTearingDown)) {
+ result = MA_SUCCESS; /* Caller should continue as normal. */
+ break;
+ }
+
/* The first thing to do is close the streams. */
ma_close_streams__aaudio(pDevice);
@@ -38495,14 +39948,16 @@ error_disconnected:
result = ma_device_init_streams__aaudio(pDevice, &deviceConfig, &descriptorPlayback, &descriptorCapture);
if (result != MA_SUCCESS) {
ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_WARNING, "[AAudio] Failed to create stream after route change.");
- goto done;
+ /* Reroute failed! */
+ break;
}
result = ma_device_post_init(pDevice, deviceType, &descriptorPlayback, &descriptorCapture);
if (result != MA_SUCCESS) {
ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_WARNING, "[AAudio] Failed to initialize device after route change.");
ma_close_streams__aaudio(pDevice);
- goto done;
+ /* Reroute failed! */
+ break;
}
/* We'll only ever do this in response to a reroute. */
@@ -38513,26 +39968,23 @@ error_disconnected:
if (pDevice->aaudio.noAutoStartAfterReroute == MA_FALSE) {
result = ma_device_start__aaudio(pDevice);
if (result != MA_SUCCESS) {
- /* We got disconnected! Retry a few times, until we find a connected device! */
- retries += 1;
- if (retries <= 3) {
- ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, "[AAudio] Failed to start stream after route change, retrying(%d)", retries);
- goto error_disconnected;
+ if (iAttempt < maxAttempts) {
+ ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, "[AAudio] Failed to start stream after route change, retrying(%d)", iAttempt);
+ } else {
+ ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, "[AAudio] Failed to start stream after route change, giving up.");
}
- ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, "[AAudio] Failed to start stream after route change.");
- goto done;
}
} else {
- ma_device_stop(pDevice); /* Do a full device stop so we set internal state correctly. */
+ ma_device_stop(pDevice); /* Do a full device stop so we set internal state correctly. */
}
}
-
- result = MA_SUCCESS;
- }
-done:
- /* Re-routing done */
- ma_mutex_unlock(&pDevice->aaudio.rerouteLock);
+ if (result == MA_SUCCESS) {
+ /* Reroute successful! */
+ break;
+ }
+ }
+
return result;
}
@@ -38698,7 +40150,7 @@ static ma_result ma_context_init__aaudio(ma_context* pContext, const ma_context_
static ma_result ma_job_process__device__aaudio_reroute(ma_job* pJob)
{
- ma_result result;
+ ma_result result = MA_SUCCESS;
ma_device* pDevice;
MA_ASSERT(pJob != NULL);
@@ -38706,19 +40158,22 @@ static ma_result ma_job_process__device__aaudio_reroute(ma_job* pJob)
pDevice = (ma_device*)pJob->data.device.aaudio.reroute.pDevice;
MA_ASSERT(pDevice != NULL);
- /* Here is where we need to reroute the device. To do this we need to uninitialize the stream and reinitialize it. */
- result = ma_device_reinit__aaudio(pDevice, (ma_device_type)pJob->data.device.aaudio.reroute.deviceType);
- if (result != MA_SUCCESS) {
- /*
- Getting here means we failed to reroute the device. The best thing I can think of here is to
- just stop the device.
- */
- ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[AAudio] Stopping device due to reroute failure.");
- ma_device_stop(pDevice);
- return result;
+ ma_mutex_lock(&pDevice->aaudio.rerouteLock);
+ {
+ /* Here is where we need to reroute the device. To do this we need to uninitialize the stream and reinitialize it. */
+ result = ma_device_reinit__aaudio(pDevice, (ma_device_type)pJob->data.device.aaudio.reroute.deviceType);
+ if (result != MA_SUCCESS) {
+ /*
+ Getting here means we failed to reroute the device. The best thing I can think of here is to
+ just stop the device.
+ */
+ ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[AAudio] Stopping device due to reroute failure.");
+ ma_device_stop(pDevice);
+ }
}
+ ma_mutex_unlock(&pDevice->aaudio.rerouteLock);
- return MA_SUCCESS;
+ return result;
}
#else
/* Getting here means there is no AAudio backend so we need a no-op job implementation. */
@@ -41236,13 +42691,13 @@ MA_API ma_result ma_device_post_init(ma_device* pDevice, ma_device_type deviceTy
static ma_thread_result MA_THREADCALL ma_worker_thread(void* pData)
{
ma_device* pDevice = (ma_device*)pData;
-#ifdef MA_WIN32
+#if defined(MA_WIN32) && !defined(MA_XBOX)
HRESULT CoInitializeResult;
#endif
MA_ASSERT(pDevice != NULL);
-#ifdef MA_WIN32
+#if defined(MA_WIN32) && !defined(MA_XBOX)
CoInitializeResult = ma_CoInitializeEx(pDevice->pContext, NULL, MA_COINIT_VALUE);
#endif
@@ -41333,8 +42788,8 @@ static ma_thread_result MA_THREADCALL ma_worker_thread(void* pData)
ma_event_signal(&pDevice->stopEvent);
}
-#ifdef MA_WIN32
- if (CoInitializeResult == S_OK) {
+#if defined(MA_WIN32) && !defined(MA_XBOX)
+ if (CoInitializeResult == S_OK || CoInitializeResult == S_FALSE) {
ma_CoUninitialize(pDevice->pContext);
}
#endif
@@ -41358,67 +42813,92 @@ static ma_bool32 ma_device__is_initialized(ma_device* pDevice)
static ma_result ma_context_uninit_backend_apis__win32(ma_context* pContext)
{
/* For some reason UWP complains when CoUninitialize() is called. I'm just not going to call it on UWP. */
-#if defined(MA_WIN32_DESKTOP) || defined(MA_WIN32_GDK)
- if (pContext->win32.CoInitializeResult == S_OK) {
- ma_CoUninitialize(pContext);
+ #if defined(MA_WIN32_DESKTOP) || defined(MA_WIN32_GDK)
+ {
+ /* TODO: Remove this once the new single threaded backend system is in place in 0.12. */
+ #if !defined(MA_XBOX)
+ {
+ if (pContext->win32.CoInitializeResult == S_OK || pContext->win32.CoInitializeResult == S_FALSE) {
+ ma_CoUninitialize(pContext); /* TODO: Remove this once the new single threaded backend system is in place in 0.12. */
+ }
+ }
+ #endif
+
+ #if defined(MA_WIN32_DESKTOP)
+ ma_dlclose(ma_context_get_log(pContext), pContext->win32.hUser32DLL);
+ ma_dlclose(ma_context_get_log(pContext), pContext->win32.hAdvapi32DLL);
+ #endif
+
+ ma_dlclose(ma_context_get_log(pContext), pContext->win32.hOle32DLL);
+ }
+ #else
+ {
+ (void)pContext;
}
-
- #if defined(MA_WIN32_DESKTOP)
- ma_dlclose(ma_context_get_log(pContext), pContext->win32.hUser32DLL);
- ma_dlclose(ma_context_get_log(pContext), pContext->win32.hAdvapi32DLL);
#endif
- ma_dlclose(ma_context_get_log(pContext), pContext->win32.hOle32DLL);
-#else
- (void)pContext;
-#endif
-
return MA_SUCCESS;
}
static ma_result ma_context_init_backend_apis__win32(ma_context* pContext)
{
-#if defined(MA_WIN32_DESKTOP) || defined(MA_WIN32_GDK)
- #if defined(MA_WIN32_DESKTOP)
- /* User32.dll */
- pContext->win32.hUser32DLL = ma_dlopen(ma_context_get_log(pContext), "user32.dll");
- if (pContext->win32.hUser32DLL == NULL) {
+ /*
+ TODO: Reassess all of this stuff and move everything to the relevant backends. For example, I think
+ GetForegroundWindow() and GetDesktopWindow() are only used by the DirectSound backend.
+ */
+ #if (defined(MA_WIN32_DESKTOP) || defined(MA_WIN32_GDK)) && !defined(MA_XBOX)
+ {
+ #if defined(MA_WIN32_DESKTOP)
+ {
+ /* User32.dll */
+ pContext->win32.hUser32DLL = ma_dlopen(ma_context_get_log(pContext), "user32.dll");
+ if (pContext->win32.hUser32DLL == NULL) {
+ return MA_FAILED_TO_INIT_BACKEND;
+ }
+
+ pContext->win32.GetForegroundWindow = (ma_proc)ma_dlsym(ma_context_get_log(pContext), pContext->win32.hUser32DLL, "GetForegroundWindow");
+ pContext->win32.GetDesktopWindow = (ma_proc)ma_dlsym(ma_context_get_log(pContext), pContext->win32.hUser32DLL, "GetDesktopWindow");
+
+
+ /* Advapi32.dll */
+ pContext->win32.hAdvapi32DLL = ma_dlopen(ma_context_get_log(pContext), "advapi32.dll");
+ if (pContext->win32.hAdvapi32DLL == NULL) {
+ return MA_FAILED_TO_INIT_BACKEND;
+ }
+
+ pContext->win32.RegOpenKeyExA = (ma_proc)ma_dlsym(ma_context_get_log(pContext), pContext->win32.hAdvapi32DLL, "RegOpenKeyExA");
+ pContext->win32.RegCloseKey = (ma_proc)ma_dlsym(ma_context_get_log(pContext), pContext->win32.hAdvapi32DLL, "RegCloseKey");
+ pContext->win32.RegQueryValueExA = (ma_proc)ma_dlsym(ma_context_get_log(pContext), pContext->win32.hAdvapi32DLL, "RegQueryValueExA");
+ }
+ #endif
+
+ /* Ole32.dll */
+ pContext->win32.hOle32DLL = ma_dlopen(ma_context_get_log(pContext), "ole32.dll");
+ if (pContext->win32.hOle32DLL == NULL) {
return MA_FAILED_TO_INIT_BACKEND;
}
- pContext->win32.GetForegroundWindow = (ma_proc)ma_dlsym(ma_context_get_log(pContext), pContext->win32.hUser32DLL, "GetForegroundWindow");
- pContext->win32.GetDesktopWindow = (ma_proc)ma_dlsym(ma_context_get_log(pContext), pContext->win32.hUser32DLL, "GetDesktopWindow");
-
-
- /* Advapi32.dll */
- pContext->win32.hAdvapi32DLL = ma_dlopen(ma_context_get_log(pContext), "advapi32.dll");
- if (pContext->win32.hAdvapi32DLL == NULL) {
- return MA_FAILED_TO_INIT_BACKEND;
- }
-
- pContext->win32.RegOpenKeyExA = (ma_proc)ma_dlsym(ma_context_get_log(pContext), pContext->win32.hAdvapi32DLL, "RegOpenKeyExA");
- pContext->win32.RegCloseKey = (ma_proc)ma_dlsym(ma_context_get_log(pContext), pContext->win32.hAdvapi32DLL, "RegCloseKey");
- pContext->win32.RegQueryValueExA = (ma_proc)ma_dlsym(ma_context_get_log(pContext), pContext->win32.hAdvapi32DLL, "RegQueryValueExA");
+ pContext->win32.CoInitialize = (ma_proc)ma_dlsym(ma_context_get_log(pContext), pContext->win32.hOle32DLL, "CoInitialize");
+ pContext->win32.CoInitializeEx = (ma_proc)ma_dlsym(ma_context_get_log(pContext), pContext->win32.hOle32DLL, "CoInitializeEx");
+ pContext->win32.CoUninitialize = (ma_proc)ma_dlsym(ma_context_get_log(pContext), pContext->win32.hOle32DLL, "CoUninitialize");
+ pContext->win32.CoCreateInstance = (ma_proc)ma_dlsym(ma_context_get_log(pContext), pContext->win32.hOle32DLL, "CoCreateInstance");
+ pContext->win32.CoTaskMemFree = (ma_proc)ma_dlsym(ma_context_get_log(pContext), pContext->win32.hOle32DLL, "CoTaskMemFree");
+ pContext->win32.PropVariantClear = (ma_proc)ma_dlsym(ma_context_get_log(pContext), pContext->win32.hOle32DLL, "PropVariantClear");
+ pContext->win32.StringFromGUID2 = (ma_proc)ma_dlsym(ma_context_get_log(pContext), pContext->win32.hOle32DLL, "StringFromGUID2");
+ }
+ #else
+ {
+ (void)pContext; /* Unused. */
+ }
#endif
- /* Ole32.dll */
- pContext->win32.hOle32DLL = ma_dlopen(ma_context_get_log(pContext), "ole32.dll");
- if (pContext->win32.hOle32DLL == NULL) {
- return MA_FAILED_TO_INIT_BACKEND;
+ /* TODO: Remove this once the new single threaded backend system is in place in 0.12. */
+ #if !defined(MA_XBOX)
+ {
+ pContext->win32.CoInitializeResult = ma_CoInitializeEx(pContext, NULL, MA_COINIT_VALUE);
}
+ #endif
- pContext->win32.CoInitialize = (ma_proc)ma_dlsym(ma_context_get_log(pContext), pContext->win32.hOle32DLL, "CoInitialize");
- pContext->win32.CoInitializeEx = (ma_proc)ma_dlsym(ma_context_get_log(pContext), pContext->win32.hOle32DLL, "CoInitializeEx");
- pContext->win32.CoUninitialize = (ma_proc)ma_dlsym(ma_context_get_log(pContext), pContext->win32.hOle32DLL, "CoUninitialize");
- pContext->win32.CoCreateInstance = (ma_proc)ma_dlsym(ma_context_get_log(pContext), pContext->win32.hOle32DLL, "CoCreateInstance");
- pContext->win32.CoTaskMemFree = (ma_proc)ma_dlsym(ma_context_get_log(pContext), pContext->win32.hOle32DLL, "CoTaskMemFree");
- pContext->win32.PropVariantClear = (ma_proc)ma_dlsym(ma_context_get_log(pContext), pContext->win32.hOle32DLL, "PropVariantClear");
- pContext->win32.StringFromGUID2 = (ma_proc)ma_dlsym(ma_context_get_log(pContext), pContext->win32.hOle32DLL, "StringFromGUID2");
-#else
- (void)pContext; /* Unused. */
-#endif
-
- pContext->win32.CoInitializeResult = ma_CoInitializeEx(pContext, NULL, MA_COINIT_VALUE);
return MA_SUCCESS;
}
#else
@@ -44016,7 +45496,7 @@ static MA_INLINE void ma_pcm_s16_to_s32__reference(void* dst, const void* src, m
ma_uint64 i;
for (i = 0; i < count; i += 1) {
- dst_s32[i] = src_s16[i] << 16;
+ dst_s32[i] = (ma_int32)src_s16[i] << 16;
}
(void)ditherMode;
@@ -56408,8 +57888,12 @@ MA_API size_t ma_channel_map_to_string(const ma_channel* pChannelMap, ma_uint32
}
/* Null terminate. Don't increment the length here. */
- if (pBufferOut != NULL && bufferCap > len + 1) {
- pBufferOut[len] = '\0';
+ if (pBufferOut != NULL) {
+ if (bufferCap > len) {
+ pBufferOut[len] = '\0';
+ } else if (bufferCap > 0) {
+ pBufferOut[bufferCap - 1] = '\0';
+ }
}
return len;
@@ -56620,7 +58104,7 @@ MA_API ma_result ma_rb_init_ex(size_t subbufferSizeInBytes, size_t subbufferCoun
Here is where we allocate our own buffer. We always want to align this to MA_SIMD_ALIGNMENT for future SIMD optimization opportunity. To do this
we need to make sure the stride is a multiple of MA_SIMD_ALIGNMENT.
*/
- pRB->subbufferStrideInBytes = (pRB->subbufferSizeInBytes + (MA_SIMD_ALIGNMENT-1)) & ~MA_SIMD_ALIGNMENT;
+ pRB->subbufferStrideInBytes = ma_align(pRB->subbufferSizeInBytes, MA_SIMD_ALIGNMENT);
bufferSizeInBytes = (size_t)pRB->subbufferCount*pRB->subbufferStrideInBytes;
pRB->pBuffer = ma_aligned_malloc(bufferSizeInBytes, MA_SIMD_ALIGNMENT, &pRB->allocationCallbacks);
@@ -59515,7 +60999,7 @@ MA_API ma_result ma_vfs_info(ma_vfs* pVFS, ma_vfs_file file, ma_file_info* pInfo
}
-#if !defined(MA_USE_WIN32_FILEIO) && (defined(MA_WIN32) && defined(MA_WIN32_DESKTOP) && !defined(MA_NO_WIN32_FILEIO) && !defined(MA_POSIX))
+#if !defined(MA_USE_WIN32_FILEIO) && (defined(MA_WIN32) && (defined(MA_WIN32_DESKTOP) || defined(MA_WIN32_NXDK)) && !defined(MA_NO_WIN32_FILEIO) && !defined(MA_POSIX))
#define MA_USE_WIN32_FILEIO
#endif
@@ -59592,25 +61076,34 @@ static ma_result ma_default_vfs_open__win32(ma_vfs* pVFS, const char* pFilePath,
static ma_result ma_default_vfs_open_w__win32(ma_vfs* pVFS, const wchar_t* pFilePath, ma_uint32 openMode, ma_vfs_file* pFile)
{
- HANDLE hFile;
- DWORD dwDesiredAccess;
- DWORD dwShareMode;
- DWORD dwCreationDisposition;
+ #if !defined(MA_XBOX_NXDK)
+ {
+ HANDLE hFile;
+ DWORD dwDesiredAccess;
+ DWORD dwShareMode;
+ DWORD dwCreationDisposition;
- (void)pVFS;
+ (void)pVFS;
- /* Load some Win32 symbols dynamically so we can dynamically check for the existence of SetFilePointerEx. */
- ma_win32_fileio_init();
+ /* Load some Win32 symbols dynamically so we can dynamically check for the existence of SetFilePointerEx. */
+ ma_win32_fileio_init();
- ma_default_vfs__get_open_settings_win32(openMode, &dwDesiredAccess, &dwShareMode, &dwCreationDisposition);
+ ma_default_vfs__get_open_settings_win32(openMode, &dwDesiredAccess, &dwShareMode, &dwCreationDisposition);
- hFile = CreateFileW(pFilePath, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, FILE_ATTRIBUTE_NORMAL, NULL);
- if (hFile == INVALID_HANDLE_VALUE) {
- return ma_result_from_GetLastError(GetLastError());
+ hFile = CreateFileW(pFilePath, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (hFile == INVALID_HANDLE_VALUE) {
+ return ma_result_from_GetLastError(GetLastError());
+ }
+
+ *pFile = hFile;
+ return MA_SUCCESS;
}
-
- *pFile = hFile;
- return MA_SUCCESS;
+ #else
+ {
+ /* No CreateFileW() available. */
+ return MA_NOT_IMPLEMENTED;
+ }
+ #endif
}
static ma_result ma_default_vfs_close__win32(ma_vfs* pVFS, ma_vfs_file file)
@@ -59781,19 +61274,28 @@ static ma_result ma_default_vfs_tell__win32(ma_vfs* pVFS, ma_vfs_file file, ma_i
static ma_result ma_default_vfs_info__win32(ma_vfs* pVFS, ma_vfs_file file, ma_file_info* pInfo)
{
- BY_HANDLE_FILE_INFORMATION fi;
- BOOL result;
-
(void)pVFS;
- result = GetFileInformationByHandle((HANDLE)file, &fi);
- if (result == 0) {
- return ma_result_from_GetLastError(GetLastError());
+ #if !defined(MA_XBOX_NXDK)
+ {
+ BY_HANDLE_FILE_INFORMATION fi;
+ BOOL result;
+
+ result = GetFileInformationByHandle((HANDLE)file, &fi);
+ if (result == 0) {
+ return ma_result_from_GetLastError(GetLastError());
+ }
+
+ pInfo->sizeInBytes = ((ma_uint64)fi.nFileSizeHigh << 32) | ((ma_uint64)fi.nFileSizeLow);
+
+ return MA_SUCCESS;
}
-
- pInfo->sizeInBytes = ((ma_uint64)fi.nFileSizeHigh << 32) | ((ma_uint64)fi.nFileSizeLow);
-
- return MA_SUCCESS;
+ #else
+ {
+ /* GetFileInformationByHandle() is unavailable. */
+ return MA_NOT_IMPLEMENTED;
+ }
+ #endif
}
#else
static ma_result ma_default_vfs_open__stdio(ma_vfs* pVFS, const char* pFilePath, ma_uint32 openMode, ma_vfs_file* pFile)
@@ -60131,6 +61633,8 @@ static ma_result ma_default_vfs_tell(ma_vfs* pVFS, ma_vfs_file file, ma_int64* p
static ma_result ma_default_vfs_info(ma_vfs* pVFS, ma_vfs_file file, ma_file_info* pInfo)
{
+ ma_result result;
+
if (pInfo == NULL) {
return MA_INVALID_ARGS;
}
@@ -60142,10 +61646,43 @@ static ma_result ma_default_vfs_info(ma_vfs* pVFS, ma_vfs_file file, ma_file_inf
}
#if defined(MA_USE_WIN32_FILEIO)
- return ma_default_vfs_info__win32(pVFS, file, pInfo);
+ result = ma_default_vfs_info__win32(pVFS, file, pInfo);
#else
- return ma_default_vfs_info__stdio(pVFS, file, pInfo);
+ result = ma_default_vfs_info__stdio(pVFS, file, pInfo);
#endif
+
+ if (result == MA_NOT_IMPLEMENTED) {
+ /* Not implemented. Fall back to seek/tell/seek. */
+ ma_result result;
+ ma_int64 cursor;
+ ma_int64 sizeInBytes;
+
+ result = ma_default_vfs_tell(pVFS, file, &cursor);
+ if (result != MA_SUCCESS) {
+ return result;
+ }
+
+ result = ma_default_vfs_seek(pVFS, file, 0, ma_seek_origin_end);
+ if (result != MA_SUCCESS) {
+ return result;
+ }
+
+ result = ma_default_vfs_tell(pVFS, file, &sizeInBytes);
+ if (result != MA_SUCCESS) {
+ return result;
+ }
+
+ pInfo->sizeInBytes = sizeInBytes;
+
+ result = ma_default_vfs_seek(pVFS, file, cursor, ma_seek_origin_start);
+ if (result != MA_SUCCESS) {
+ return result;
+ }
+
+ MA_ASSERT(result == MA_SUCCESS);
+ }
+
+ return result;
}
@@ -60333,8 +61870,8 @@ extern "C" {
#define MA_DR_WAV_STRINGIFY(x) #x
#define MA_DR_WAV_XSTRINGIFY(x) MA_DR_WAV_STRINGIFY(x)
#define MA_DR_WAV_VERSION_MAJOR 0
-#define MA_DR_WAV_VERSION_MINOR 13
-#define MA_DR_WAV_VERSION_REVISION 18
+#define MA_DR_WAV_VERSION_MINOR 14
+#define MA_DR_WAV_VERSION_REVISION 1
#define MA_DR_WAV_VERSION_STRING MA_DR_WAV_XSTRINGIFY(MA_DR_WAV_VERSION_MAJOR) "." MA_DR_WAV_XSTRINGIFY(MA_DR_WAV_VERSION_MINOR) "." MA_DR_WAV_XSTRINGIFY(MA_DR_WAV_VERSION_REVISION)
#include
#define MA_DR_WAVE_FORMAT_PCM 0x1
@@ -60350,8 +61887,9 @@ MA_API void ma_dr_wav_version(ma_uint32* pMajor, ma_uint32* pMinor, ma_uint32* p
MA_API const char* ma_dr_wav_version_string(void);
typedef enum
{
- ma_dr_wav_seek_origin_start,
- ma_dr_wav_seek_origin_current
+ MA_DR_WAV_SEEK_SET,
+ MA_DR_WAV_SEEK_CUR,
+ MA_DR_WAV_SEEK_END
} ma_dr_wav_seek_origin;
typedef enum
{
@@ -60388,6 +61926,7 @@ MA_API ma_uint16 ma_dr_wav_fmt_get_format(const ma_dr_wav_fmt* pFMT);
typedef size_t (* ma_dr_wav_read_proc)(void* pUserData, void* pBufferOut, size_t bytesToRead);
typedef size_t (* ma_dr_wav_write_proc)(void* pUserData, const void* pData, size_t bytesToWrite);
typedef ma_bool32 (* ma_dr_wav_seek_proc)(void* pUserData, int offset, ma_dr_wav_seek_origin origin);
+typedef ma_bool32 (* ma_dr_wav_tell_proc)(void* pUserData, ma_int64* pCursor);
typedef ma_uint64 (* ma_dr_wav_chunk_proc)(void* pChunkUserData, ma_dr_wav_read_proc onRead, ma_dr_wav_seek_proc onSeek, void* pReadSeekUserData, const ma_dr_wav_chunk_header* pChunkHeader, ma_dr_wav_container container, const ma_dr_wav_fmt* pFMT);
typedef struct
{
@@ -60432,6 +61971,11 @@ typedef enum
ma_dr_wav_metadata_type_list_info_genre = 1 << 15,
ma_dr_wav_metadata_type_list_info_album = 1 << 16,
ma_dr_wav_metadata_type_list_info_tracknumber = 1 << 17,
+ ma_dr_wav_metadata_type_list_info_location = 1 << 18,
+ ma_dr_wav_metadata_type_list_info_organization = 1 << 19,
+ ma_dr_wav_metadata_type_list_info_keywords = 1 << 20,
+ ma_dr_wav_metadata_type_list_info_medium = 1 << 21,
+ ma_dr_wav_metadata_type_list_info_description = 1 << 22,
ma_dr_wav_metadata_type_list_all_info_strings = ma_dr_wav_metadata_type_list_info_software
| ma_dr_wav_metadata_type_list_info_copyright
| ma_dr_wav_metadata_type_list_info_title
@@ -60440,7 +61984,12 @@ typedef enum
| ma_dr_wav_metadata_type_list_info_date
| ma_dr_wav_metadata_type_list_info_genre
| ma_dr_wav_metadata_type_list_info_album
- | ma_dr_wav_metadata_type_list_info_tracknumber,
+ | ma_dr_wav_metadata_type_list_info_tracknumber
+ | ma_dr_wav_metadata_type_list_info_location
+ | ma_dr_wav_metadata_type_list_info_organization
+ | ma_dr_wav_metadata_type_list_info_keywords
+ | ma_dr_wav_metadata_type_list_info_medium
+ | ma_dr_wav_metadata_type_list_info_description,
ma_dr_wav_metadata_type_list_all_adtl = ma_dr_wav_metadata_type_list_label
| ma_dr_wav_metadata_type_list_note
| ma_dr_wav_metadata_type_list_labelled_cue_region,
@@ -60457,8 +62006,8 @@ typedef struct
{
ma_uint32 cuePointId;
ma_uint32 type;
- ma_uint32 firstSampleByteOffset;
- ma_uint32 lastSampleByteOffset;
+ ma_uint32 firstSampleOffset;
+ ma_uint32 lastSampleOffset;
ma_uint32 sampleFraction;
ma_uint32 playCount;
} ma_dr_wav_smpl_loop;
@@ -60493,7 +62042,7 @@ typedef struct
ma_uint8 dataChunkId[4];
ma_uint32 chunkStart;
ma_uint32 blockStart;
- ma_uint32 sampleByteOffset;
+ ma_uint32 sampleOffset;
} ma_dr_wav_cue_point;
typedef struct
{
@@ -60595,6 +62144,7 @@ typedef struct
ma_dr_wav_read_proc onRead;
ma_dr_wav_write_proc onWrite;
ma_dr_wav_seek_proc onSeek;
+ ma_dr_wav_tell_proc onTell;
void* pUserData;
ma_allocation_callbacks allocationCallbacks;
ma_dr_wav_container container;
@@ -60637,9 +62187,9 @@ typedef struct
ma_bool8 isUnsigned;
} aiff;
} ma_dr_wav;
-MA_API ma_bool32 ma_dr_wav_init(ma_dr_wav* pWav, ma_dr_wav_read_proc onRead, ma_dr_wav_seek_proc onSeek, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks);
-MA_API ma_bool32 ma_dr_wav_init_ex(ma_dr_wav* pWav, ma_dr_wav_read_proc onRead, ma_dr_wav_seek_proc onSeek, ma_dr_wav_chunk_proc onChunk, void* pReadSeekUserData, void* pChunkUserData, ma_uint32 flags, const ma_allocation_callbacks* pAllocationCallbacks);
-MA_API ma_bool32 ma_dr_wav_init_with_metadata(ma_dr_wav* pWav, ma_dr_wav_read_proc onRead, ma_dr_wav_seek_proc onSeek, void* pUserData, ma_uint32 flags, const ma_allocation_callbacks* pAllocationCallbacks);
+MA_API ma_bool32 ma_dr_wav_init(ma_dr_wav* pWav, ma_dr_wav_read_proc onRead, ma_dr_wav_seek_proc onSeek, ma_dr_wav_tell_proc onTell, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks);
+MA_API ma_bool32 ma_dr_wav_init_ex(ma_dr_wav* pWav, ma_dr_wav_read_proc onRead, ma_dr_wav_seek_proc onSeek, ma_dr_wav_tell_proc onTell, ma_dr_wav_chunk_proc onChunk, void* pReadSeekTellUserData, void* pChunkUserData, ma_uint32 flags, const ma_allocation_callbacks* pAllocationCallbacks);
+MA_API ma_bool32 ma_dr_wav_init_with_metadata(ma_dr_wav* pWav, ma_dr_wav_read_proc onRead, ma_dr_wav_seek_proc onSeek, ma_dr_wav_tell_proc onTell, void* pUserData, ma_uint32 flags, const ma_allocation_callbacks* pAllocationCallbacks);
MA_API ma_bool32 ma_dr_wav_init_write(ma_dr_wav* pWav, const ma_dr_wav_data_format* pFormat, ma_dr_wav_write_proc onWrite, ma_dr_wav_seek_proc onSeek, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks);
MA_API ma_bool32 ma_dr_wav_init_write_sequential(ma_dr_wav* pWav, const ma_dr_wav_data_format* pFormat, ma_uint64 totalSampleCount, ma_dr_wav_write_proc onWrite, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks);
MA_API ma_bool32 ma_dr_wav_init_write_sequential_pcm_frames(ma_dr_wav* pWav, const ma_dr_wav_data_format* pFormat, ma_uint64 totalPCMFrameCount, ma_dr_wav_write_proc onWrite, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks);
@@ -60711,9 +62261,9 @@ MA_API ma_bool32 ma_dr_wav_init_memory_write(ma_dr_wav* pWav, void** ppData, siz
MA_API ma_bool32 ma_dr_wav_init_memory_write_sequential(ma_dr_wav* pWav, void** ppData, size_t* pDataSize, const ma_dr_wav_data_format* pFormat, ma_uint64 totalSampleCount, const ma_allocation_callbacks* pAllocationCallbacks);
MA_API ma_bool32 ma_dr_wav_init_memory_write_sequential_pcm_frames(ma_dr_wav* pWav, void** ppData, size_t* pDataSize, const ma_dr_wav_data_format* pFormat, ma_uint64 totalPCMFrameCount, const ma_allocation_callbacks* pAllocationCallbacks);
#ifndef MA_DR_WAV_NO_CONVERSION_API
-MA_API ma_int16* ma_dr_wav_open_and_read_pcm_frames_s16(ma_dr_wav_read_proc onRead, ma_dr_wav_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, ma_uint64* totalFrameCountOut, const ma_allocation_callbacks* pAllocationCallbacks);
-MA_API float* ma_dr_wav_open_and_read_pcm_frames_f32(ma_dr_wav_read_proc onRead, ma_dr_wav_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, ma_uint64* totalFrameCountOut, const ma_allocation_callbacks* pAllocationCallbacks);
-MA_API ma_int32* ma_dr_wav_open_and_read_pcm_frames_s32(ma_dr_wav_read_proc onRead, ma_dr_wav_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, ma_uint64* totalFrameCountOut, const ma_allocation_callbacks* pAllocationCallbacks);
+MA_API ma_int16* ma_dr_wav_open_and_read_pcm_frames_s16(ma_dr_wav_read_proc onRead, ma_dr_wav_seek_proc onSeek, ma_dr_wav_tell_proc onTell, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, ma_uint64* totalFrameCountOut, const ma_allocation_callbacks* pAllocationCallbacks);
+MA_API float* ma_dr_wav_open_and_read_pcm_frames_f32(ma_dr_wav_read_proc onRead, ma_dr_wav_seek_proc onSeek, ma_dr_wav_tell_proc onTell, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, ma_uint64* totalFrameCountOut, const ma_allocation_callbacks* pAllocationCallbacks);
+MA_API ma_int32* ma_dr_wav_open_and_read_pcm_frames_s32(ma_dr_wav_read_proc onRead, ma_dr_wav_seek_proc onSeek, ma_dr_wav_tell_proc onTell, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, ma_uint64* totalFrameCountOut, const ma_allocation_callbacks* pAllocationCallbacks);
#ifndef MA_DR_WAV_NO_STDIO
MA_API ma_int16* ma_dr_wav_open_file_and_read_pcm_frames_s16(const char* filename, unsigned int* channelsOut, unsigned int* sampleRateOut, ma_uint64* totalFrameCountOut, const ma_allocation_callbacks* pAllocationCallbacks);
MA_API float* ma_dr_wav_open_file_and_read_pcm_frames_f32(const char* filename, unsigned int* channelsOut, unsigned int* sampleRateOut, ma_uint64* totalFrameCountOut, const ma_allocation_callbacks* pAllocationCallbacks);
@@ -60753,8 +62303,8 @@ extern "C" {
#define MA_DR_FLAC_STRINGIFY(x) #x
#define MA_DR_FLAC_XSTRINGIFY(x) MA_DR_FLAC_STRINGIFY(x)
#define MA_DR_FLAC_VERSION_MAJOR 0
-#define MA_DR_FLAC_VERSION_MINOR 12
-#define MA_DR_FLAC_VERSION_REVISION 43
+#define MA_DR_FLAC_VERSION_MINOR 13
+#define MA_DR_FLAC_VERSION_REVISION 1
#define MA_DR_FLAC_VERSION_STRING MA_DR_FLAC_XSTRINGIFY(MA_DR_FLAC_VERSION_MAJOR) "." MA_DR_FLAC_XSTRINGIFY(MA_DR_FLAC_VERSION_MINOR) "." MA_DR_FLAC_XSTRINGIFY(MA_DR_FLAC_VERSION_REVISION)
#include
#if defined(_MSC_VER) && _MSC_VER >= 1700
@@ -60817,8 +62367,9 @@ typedef enum
} ma_dr_flac_container;
typedef enum
{
- ma_dr_flac_seek_origin_start,
- ma_dr_flac_seek_origin_current
+ MA_DR_FLAC_SEEK_SET,
+ MA_DR_FLAC_SEEK_CUR,
+ MA_DR_FLAC_SEEK_END
} ma_dr_flac_seek_origin;
typedef struct
{
@@ -60894,6 +62445,7 @@ typedef struct
} ma_dr_flac_metadata;
typedef size_t (* ma_dr_flac_read_proc)(void* pUserData, void* pBufferOut, size_t bytesToRead);
typedef ma_bool32 (* ma_dr_flac_seek_proc)(void* pUserData, int offset, ma_dr_flac_seek_origin origin);
+typedef ma_bool32 (* ma_dr_flac_tell_proc)(void* pUserData, ma_int64* pCursor);
typedef void (* ma_dr_flac_meta_proc)(void* pUserData, ma_dr_flac_metadata* pMetadata);
typedef struct
{
@@ -60905,6 +62457,7 @@ typedef struct
{
ma_dr_flac_read_proc onRead;
ma_dr_flac_seek_proc onSeek;
+ ma_dr_flac_tell_proc onTell;
void* pUserData;
size_t unalignedByteCount;
ma_dr_flac_cache_t unalignedCache;
@@ -60964,10 +62517,10 @@ typedef struct
ma_dr_flac_bs bs;
ma_uint8 pExtraData[1];
} ma_dr_flac;
-MA_API ma_dr_flac* ma_dr_flac_open(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks);
-MA_API ma_dr_flac* ma_dr_flac_open_relaxed(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, ma_dr_flac_container container, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks);
-MA_API ma_dr_flac* ma_dr_flac_open_with_metadata(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, ma_dr_flac_meta_proc onMeta, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks);
-MA_API ma_dr_flac* ma_dr_flac_open_with_metadata_relaxed(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, ma_dr_flac_meta_proc onMeta, ma_dr_flac_container container, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks);
+MA_API ma_dr_flac* ma_dr_flac_open(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, ma_dr_flac_tell_proc onTell, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks);
+MA_API ma_dr_flac* ma_dr_flac_open_relaxed(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, ma_dr_flac_tell_proc onTell, ma_dr_flac_container container, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks);
+MA_API ma_dr_flac* ma_dr_flac_open_with_metadata(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, ma_dr_flac_tell_proc onTell, ma_dr_flac_meta_proc onMeta, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks);
+MA_API ma_dr_flac* ma_dr_flac_open_with_metadata_relaxed(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, ma_dr_flac_tell_proc onTell, ma_dr_flac_meta_proc onMeta, ma_dr_flac_container container, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks);
MA_API void ma_dr_flac_close(ma_dr_flac* pFlac);
MA_API ma_uint64 ma_dr_flac_read_pcm_frames_s32(ma_dr_flac* pFlac, ma_uint64 framesToRead, ma_int32* pBufferOut);
MA_API ma_uint64 ma_dr_flac_read_pcm_frames_s16(ma_dr_flac* pFlac, ma_uint64 framesToRead, ma_int16* pBufferOut);
@@ -60981,9 +62534,9 @@ MA_API ma_dr_flac* ma_dr_flac_open_file_with_metadata_w(const wchar_t* pFileName
#endif
MA_API ma_dr_flac* ma_dr_flac_open_memory(const void* pData, size_t dataSize, const ma_allocation_callbacks* pAllocationCallbacks);
MA_API ma_dr_flac* ma_dr_flac_open_memory_with_metadata(const void* pData, size_t dataSize, ma_dr_flac_meta_proc onMeta, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks);
-MA_API ma_int32* ma_dr_flac_open_and_read_pcm_frames_s32(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, void* pUserData, unsigned int* channels, unsigned int* sampleRate, ma_uint64* totalPCMFrameCount, const ma_allocation_callbacks* pAllocationCallbacks);
-MA_API ma_int16* ma_dr_flac_open_and_read_pcm_frames_s16(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, void* pUserData, unsigned int* channels, unsigned int* sampleRate, ma_uint64* totalPCMFrameCount, const ma_allocation_callbacks* pAllocationCallbacks);
-MA_API float* ma_dr_flac_open_and_read_pcm_frames_f32(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, void* pUserData, unsigned int* channels, unsigned int* sampleRate, ma_uint64* totalPCMFrameCount, const ma_allocation_callbacks* pAllocationCallbacks);
+MA_API ma_int32* ma_dr_flac_open_and_read_pcm_frames_s32(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, ma_dr_flac_tell_proc onTell, void* pUserData, unsigned int* channels, unsigned int* sampleRate, ma_uint64* totalPCMFrameCount, const ma_allocation_callbacks* pAllocationCallbacks);
+MA_API ma_int16* ma_dr_flac_open_and_read_pcm_frames_s16(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, ma_dr_flac_tell_proc onTell, void* pUserData, unsigned int* channels, unsigned int* sampleRate, ma_uint64* totalPCMFrameCount, const ma_allocation_callbacks* pAllocationCallbacks);
+MA_API float* ma_dr_flac_open_and_read_pcm_frames_f32(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, ma_dr_flac_tell_proc onTell, void* pUserData, unsigned int* channels, unsigned int* sampleRate, ma_uint64* totalPCMFrameCount, const ma_allocation_callbacks* pAllocationCallbacks);
#ifndef MA_DR_FLAC_NO_STDIO
MA_API ma_int32* ma_dr_flac_open_file_and_read_pcm_frames_s32(const char* filename, unsigned int* channels, unsigned int* sampleRate, ma_uint64* totalPCMFrameCount, const ma_allocation_callbacks* pAllocationCallbacks);
MA_API ma_int16* ma_dr_flac_open_file_and_read_pcm_frames_s16(const char* filename, unsigned int* channels, unsigned int* sampleRate, ma_uint64* totalPCMFrameCount, const ma_allocation_callbacks* pAllocationCallbacks);
@@ -61031,6 +62584,12 @@ MA_API ma_bool32 ma_dr_flac_next_cuesheet_track(ma_dr_flac_cuesheet_track_iterat
#endif /* MA_NO_FLAC */
#if !defined(MA_NO_MP3) && !defined(MA_NO_DECODING)
+#ifndef MA_DR_MP3_NO_SIMD
+ #if (defined(MA_NO_NEON) && defined(MA_ARM)) || (defined(MA_NO_SSE2) && (defined(MA_X86) || defined(MA_X64)))
+ #define MA_DR_MP3_NO_SIMD
+ #endif
+#endif
+
/* dr_mp3_h begin */
#ifndef ma_dr_mp3_h
#define ma_dr_mp3_h
@@ -61040,8 +62599,8 @@ extern "C" {
#define MA_DR_MP3_STRINGIFY(x) #x
#define MA_DR_MP3_XSTRINGIFY(x) MA_DR_MP3_STRINGIFY(x)
#define MA_DR_MP3_VERSION_MAJOR 0
-#define MA_DR_MP3_VERSION_MINOR 6
-#define MA_DR_MP3_VERSION_REVISION 40
+#define MA_DR_MP3_VERSION_MINOR 7
+#define MA_DR_MP3_VERSION_REVISION 1
#define MA_DR_MP3_VERSION_STRING MA_DR_MP3_XSTRINGIFY(MA_DR_MP3_VERSION_MAJOR) "." MA_DR_MP3_XSTRINGIFY(MA_DR_MP3_VERSION_MINOR) "." MA_DR_MP3_XSTRINGIFY(MA_DR_MP3_VERSION_REVISION)
#include
#define MA_DR_MP3_MAX_PCM_FRAMES_PER_MP3_FRAME 1152
@@ -61050,7 +62609,7 @@ MA_API void ma_dr_mp3_version(ma_uint32* pMajor, ma_uint32* pMinor, ma_uint32* p
MA_API const char* ma_dr_mp3_version_string(void);
typedef struct
{
- int frame_bytes, channels, hz, layer, bitrate_kbps;
+ int frame_bytes, channels, sample_rate, layer, bitrate_kbps;
} ma_dr_mp3dec_frame_info;
typedef struct
{
@@ -61063,8 +62622,9 @@ MA_API int ma_dr_mp3dec_decode_frame(ma_dr_mp3dec *dec, const ma_uint8 *mp3, int
MA_API void ma_dr_mp3dec_f32_to_s16(const float *in, ma_int16 *out, size_t num_samples);
typedef enum
{
- ma_dr_mp3_seek_origin_start,
- ma_dr_mp3_seek_origin_current
+ MA_DR_MP3_SEEK_SET,
+ MA_DR_MP3_SEEK_CUR,
+ MA_DR_MP3_SEEK_END
} ma_dr_mp3_seek_origin;
typedef struct
{
@@ -61073,8 +62633,24 @@ typedef struct
ma_uint16 mp3FramesToDiscard;
ma_uint16 pcmFramesToDiscard;
} ma_dr_mp3_seek_point;
+typedef enum
+{
+ MA_DR_MP3_METADATA_TYPE_ID3V1,
+ MA_DR_MP3_METADATA_TYPE_ID3V2,
+ MA_DR_MP3_METADATA_TYPE_APE,
+ MA_DR_MP3_METADATA_TYPE_XING,
+ MA_DR_MP3_METADATA_TYPE_VBRI
+} ma_dr_mp3_metadata_type;
+typedef struct
+{
+ ma_dr_mp3_metadata_type type;
+ const void* pRawData;
+ size_t rawDataSize;
+} ma_dr_mp3_metadata;
typedef size_t (* ma_dr_mp3_read_proc)(void* pUserData, void* pBufferOut, size_t bytesToRead);
typedef ma_bool32 (* ma_dr_mp3_seek_proc)(void* pUserData, int offset, ma_dr_mp3_seek_origin origin);
+typedef ma_bool32 (* ma_dr_mp3_tell_proc)(void* pUserData, ma_int64* pCursor);
+typedef void (* ma_dr_mp3_meta_proc)(void* pUserData, const ma_dr_mp3_metadata* pMetadata);
typedef struct
{
ma_uint32 channels;
@@ -61087,7 +62663,9 @@ typedef struct
ma_uint32 sampleRate;
ma_dr_mp3_read_proc onRead;
ma_dr_mp3_seek_proc onSeek;
+ ma_dr_mp3_meta_proc onMeta;
void* pUserData;
+ void* pUserDataMeta;
ma_allocation_callbacks allocationCallbacks;
ma_uint32 mp3FrameChannels;
ma_uint32 mp3FrameSampleRate;
@@ -61096,13 +62674,20 @@ typedef struct
ma_uint8 pcmFrames[sizeof(float)*MA_DR_MP3_MAX_SAMPLES_PER_FRAME];
ma_uint64 currentPCMFrame;
ma_uint64 streamCursor;
+ ma_uint64 streamLength;
+ ma_uint64 streamStartOffset;
ma_dr_mp3_seek_point* pSeekPoints;
ma_uint32 seekPointCount;
+ ma_uint32 delayInPCMFrames;
+ ma_uint32 paddingInPCMFrames;
+ ma_uint64 totalPCMFrameCount;
+ ma_bool32 isVBR;
+ ma_bool32 isCBR;
size_t dataSize;
size_t dataCapacity;
size_t dataConsumed;
ma_uint8* pData;
- ma_bool32 atEnd : 1;
+ ma_bool32 atEnd;
struct
{
const ma_uint8* pData;
@@ -61110,9 +62695,12 @@ typedef struct
size_t currentReadPos;
} memory;
} ma_dr_mp3;
-MA_API ma_bool32 ma_dr_mp3_init(ma_dr_mp3* pMP3, ma_dr_mp3_read_proc onRead, ma_dr_mp3_seek_proc onSeek, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks);
+MA_API ma_bool32 ma_dr_mp3_init(ma_dr_mp3* pMP3, ma_dr_mp3_read_proc onRead, ma_dr_mp3_seek_proc onSeek, ma_dr_mp3_tell_proc onTell, ma_dr_mp3_meta_proc onMeta, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks);
+MA_API ma_bool32 ma_dr_mp3_init_memory_with_metadata(ma_dr_mp3* pMP3, const void* pData, size_t dataSize, ma_dr_mp3_meta_proc onMeta, void* pUserDataMeta, const ma_allocation_callbacks* pAllocationCallbacks);
MA_API ma_bool32 ma_dr_mp3_init_memory(ma_dr_mp3* pMP3, const void* pData, size_t dataSize, const ma_allocation_callbacks* pAllocationCallbacks);
#ifndef MA_DR_MP3_NO_STDIO
+MA_API ma_bool32 ma_dr_mp3_init_file_with_metadata(ma_dr_mp3* pMP3, const char* pFilePath, ma_dr_mp3_meta_proc onMeta, void* pUserDataMeta, const ma_allocation_callbacks* pAllocationCallbacks);
+MA_API ma_bool32 ma_dr_mp3_init_file_with_metadata_w(ma_dr_mp3* pMP3, const wchar_t* pFilePath, ma_dr_mp3_meta_proc onMeta, void* pUserDataMeta, const ma_allocation_callbacks* pAllocationCallbacks);
MA_API ma_bool32 ma_dr_mp3_init_file(ma_dr_mp3* pMP3, const char* pFilePath, const ma_allocation_callbacks* pAllocationCallbacks);
MA_API ma_bool32 ma_dr_mp3_init_file_w(ma_dr_mp3* pMP3, const wchar_t* pFilePath, const ma_allocation_callbacks* pAllocationCallbacks);
#endif
@@ -61125,8 +62713,8 @@ MA_API ma_uint64 ma_dr_mp3_get_mp3_frame_count(ma_dr_mp3* pMP3);
MA_API ma_bool32 ma_dr_mp3_get_mp3_and_pcm_frame_count(ma_dr_mp3* pMP3, ma_uint64* pMP3FrameCount, ma_uint64* pPCMFrameCount);
MA_API ma_bool32 ma_dr_mp3_calculate_seek_points(ma_dr_mp3* pMP3, ma_uint32* pSeekPointCount, ma_dr_mp3_seek_point* pSeekPoints);
MA_API ma_bool32 ma_dr_mp3_bind_seek_table(ma_dr_mp3* pMP3, ma_uint32 seekPointCount, ma_dr_mp3_seek_point* pSeekPoints);
-MA_API float* ma_dr_mp3_open_and_read_pcm_frames_f32(ma_dr_mp3_read_proc onRead, ma_dr_mp3_seek_proc onSeek, void* pUserData, ma_dr_mp3_config* pConfig, ma_uint64* pTotalFrameCount, const ma_allocation_callbacks* pAllocationCallbacks);
-MA_API ma_int16* ma_dr_mp3_open_and_read_pcm_frames_s16(ma_dr_mp3_read_proc onRead, ma_dr_mp3_seek_proc onSeek, void* pUserData, ma_dr_mp3_config* pConfig, ma_uint64* pTotalFrameCount, const ma_allocation_callbacks* pAllocationCallbacks);
+MA_API float* ma_dr_mp3_open_and_read_pcm_frames_f32(ma_dr_mp3_read_proc onRead, ma_dr_mp3_seek_proc onSeek, ma_dr_mp3_tell_proc onTell, void* pUserData, ma_dr_mp3_config* pConfig, ma_uint64* pTotalFrameCount, const ma_allocation_callbacks* pAllocationCallbacks);
+MA_API ma_int16* ma_dr_mp3_open_and_read_pcm_frames_s16(ma_dr_mp3_read_proc onRead, ma_dr_mp3_seek_proc onSeek, ma_dr_mp3_tell_proc onTell, void* pUserData, ma_dr_mp3_config* pConfig, ma_uint64* pTotalFrameCount, const ma_allocation_callbacks* pAllocationCallbacks);
MA_API float* ma_dr_mp3_open_memory_and_read_pcm_frames_f32(const void* pData, size_t dataSize, ma_dr_mp3_config* pConfig, ma_uint64* pTotalFrameCount, const ma_allocation_callbacks* pAllocationCallbacks);
MA_API ma_int16* ma_dr_mp3_open_memory_and_read_pcm_frames_s16(const void* pData, size_t dataSize, ma_dr_mp3_config* pConfig, ma_uint64* pTotalFrameCount, const ma_allocation_callbacks* pAllocationCallbacks);
#ifndef MA_DR_MP3_NO_STDIO
@@ -61679,8 +63267,10 @@ static ma_bool32 ma_wav_dr_callback__seek(void* pUserData, int offset, ma_dr_wav
MA_ASSERT(pWav != NULL);
maSeekOrigin = ma_seek_origin_start;
- if (origin == ma_dr_wav_seek_origin_current) {
- maSeekOrigin = ma_seek_origin_current;
+ if (origin == MA_DR_WAV_SEEK_CUR) {
+ maSeekOrigin = ma_seek_origin_current;
+ } else if (origin == MA_DR_WAV_SEEK_END) {
+ maSeekOrigin = ma_seek_origin_end;
}
result = pWav->onSeek(pWav->pReadSeekTellUserData, offset, maSeekOrigin);
@@ -61690,6 +63280,26 @@ static ma_bool32 ma_wav_dr_callback__seek(void* pUserData, int offset, ma_dr_wav
return MA_TRUE;
}
+
+static ma_bool32 ma_wav_dr_callback__tell(void* pUserData, ma_int64* pCursor)
+{
+ ma_wav* pWav = (ma_wav*)pUserData;
+ ma_result result;
+
+ MA_ASSERT(pWav != NULL);
+ MA_ASSERT(pCursor != NULL);
+
+ if (pWav->onTell == NULL) {
+ return MA_FALSE; /* Not implemented. */
+ }
+
+ result = pWav->onTell(pWav->pReadSeekTellUserData, pCursor);
+ if (result != MA_SUCCESS) {
+ return MA_FALSE; /* Failed to tell. */
+ }
+
+ return MA_TRUE;
+}
#endif
static ma_result ma_wav_init_internal(const ma_decoding_backend_config* pConfig, ma_wav* pWav)
@@ -61784,7 +63394,7 @@ MA_API ma_result ma_wav_init(ma_read_proc onRead, ma_seek_proc onSeek, ma_tell_p
{
ma_bool32 wavResult;
- wavResult = ma_dr_wav_init(&pWav->dr, ma_wav_dr_callback__read, ma_wav_dr_callback__seek, pWav, pAllocationCallbacks);
+ wavResult = ma_dr_wav_init(&pWav->dr, ma_wav_dr_callback__read, ma_wav_dr_callback__seek, ma_wav_dr_callback__tell, pWav, pAllocationCallbacks);
if (wavResult != MA_TRUE) {
return MA_INVALID_FILE;
}
@@ -62363,8 +63973,10 @@ static ma_bool32 ma_flac_dr_callback__seek(void* pUserData, int offset, ma_dr_fl
MA_ASSERT(pFlac != NULL);
maSeekOrigin = ma_seek_origin_start;
- if (origin == ma_dr_flac_seek_origin_current) {
- maSeekOrigin = ma_seek_origin_current;
+ if (origin == MA_DR_FLAC_SEEK_CUR) {
+ maSeekOrigin = ma_seek_origin_current;
+ } else if (origin == MA_DR_FLAC_SEEK_END) {
+ maSeekOrigin = ma_seek_origin_end;
}
result = pFlac->onSeek(pFlac->pReadSeekTellUserData, offset, maSeekOrigin);
@@ -62374,6 +63986,26 @@ static ma_bool32 ma_flac_dr_callback__seek(void* pUserData, int offset, ma_dr_fl
return MA_TRUE;
}
+
+static ma_bool32 ma_flac_dr_callback__tell(void* pUserData, ma_int64* pCursor)
+{
+ ma_flac* pFlac = (ma_flac*)pUserData;
+ ma_result result;
+
+ MA_ASSERT(pFlac != NULL);
+ MA_ASSERT(pCursor != NULL);
+
+ if (pFlac->onTell == NULL) {
+ return MA_FALSE; /* Not implemented. */
+ }
+
+ result = pFlac->onTell(pFlac->pReadSeekTellUserData, pCursor);
+ if (result != MA_SUCCESS) {
+ return MA_FALSE; /* Failed to tell. */
+ }
+
+ return MA_TRUE;
+}
#endif
static ma_result ma_flac_init_internal(const ma_decoding_backend_config* pConfig, ma_flac* pFlac)
@@ -62425,7 +64057,7 @@ MA_API ma_result ma_flac_init(ma_read_proc onRead, ma_seek_proc onSeek, ma_tell_
#if !defined(MA_NO_FLAC)
{
- pFlac->dr = ma_dr_flac_open(ma_flac_dr_callback__read, ma_flac_dr_callback__seek, pFlac, pAllocationCallbacks);
+ pFlac->dr = ma_dr_flac_open(ma_flac_dr_callback__read, ma_flac_dr_callback__seek, ma_flac_dr_callback__tell, pFlac, pAllocationCallbacks);
if (pFlac->dr == NULL) {
return MA_INVALID_FILE;
}
@@ -62986,9 +64618,12 @@ static ma_bool32 ma_mp3_dr_callback__seek(void* pUserData, int offset, ma_dr_mp3
MA_ASSERT(pMP3 != NULL);
- maSeekOrigin = ma_seek_origin_start;
- if (origin == ma_dr_mp3_seek_origin_current) {
- maSeekOrigin = ma_seek_origin_current;
+ if (origin == MA_DR_MP3_SEEK_SET) {
+ maSeekOrigin = ma_seek_origin_start;
+ } else if (origin == MA_DR_MP3_SEEK_END) {
+ maSeekOrigin = ma_seek_origin_end;
+ } else {
+ maSeekOrigin = ma_seek_origin_current;
}
result = pMP3->onSeek(pMP3->pReadSeekTellUserData, offset, maSeekOrigin);
@@ -62998,6 +64633,21 @@ static ma_bool32 ma_mp3_dr_callback__seek(void* pUserData, int offset, ma_dr_mp3
return MA_TRUE;
}
+
+static ma_bool32 ma_mp3_dr_callback__tell(void* pUserData, ma_int64* pCursor)
+{
+ ma_mp3* pMP3 = (ma_mp3*)pUserData;
+ ma_result result;
+
+ MA_ASSERT(pMP3 != NULL);
+
+ result = pMP3->onTell(pMP3->pReadSeekTellUserData, pCursor);
+ if (result != MA_SUCCESS) {
+ return MA_FALSE;
+ }
+
+ return MA_TRUE;
+}
#endif
static ma_result ma_mp3_init_internal(const ma_decoding_backend_config* pConfig, ma_mp3* pMP3)
@@ -63098,7 +64748,7 @@ MA_API ma_result ma_mp3_init(ma_read_proc onRead, ma_seek_proc onSeek, ma_tell_p
{
ma_bool32 mp3Result;
- mp3Result = ma_dr_mp3_init(&pMP3->dr, ma_mp3_dr_callback__read, ma_mp3_dr_callback__seek, pMP3, pAllocationCallbacks);
+ mp3Result = ma_dr_mp3_init(&pMP3->dr, ma_mp3_dr_callback__read, ma_mp3_dr_callback__seek, ma_mp3_dr_callback__tell, NULL, pMP3, pAllocationCallbacks);
if (mp3Result != MA_TRUE) {
return MA_INVALID_FILE;
}
@@ -64997,14 +66647,16 @@ static ma_bool32 ma_path_extension_equal_w(const wchar_t* path, const wchar_t* e
ext1 = extension;
ext2 = ma_path_extension_w(path);
-#if defined(_MSC_VER) || defined(__WATCOMC__) || defined(__DMC__)
- return _wcsicmp(ext1, ext2) == 0;
-#else
- /*
- I'm not aware of a wide character version of strcasecmp(). I'm therefore converting the extensions to multibyte strings and comparing those. This
- isn't the most efficient way to do it, but it should work OK.
- */
+ #if (defined(_MSC_VER) || defined(__WATCOMC__) || defined(__DMC__)) && !defined(MA_XBOX_NXDK)
{
+ return _wcsicmp(ext1, ext2) == 0;
+ }
+ #elif !defined(MA_XBOX_NXDK) && !defined(MA_DOS)
+ {
+ /*
+ I'm not aware of a wide character version of strcasecmp(). I'm therefore converting the extensions to multibyte strings and comparing those. This
+ isn't the most efficient way to do it, but it should work OK.
+ */
char ext1MB[4096];
char ext2MB[4096];
const wchar_t* pext1 = ext1;
@@ -65024,7 +66676,13 @@ static ma_bool32 ma_path_extension_equal_w(const wchar_t* path, const wchar_t* e
return strcasecmp(ext1MB, ext2MB) == 0;
}
-#endif
+ #else
+ {
+ /* Getting here means we don't have a way to do a case-sensitive comparison for wide strings. Fall back to a simple case-sensitive comparison. */
+ /* TODO: Implement our own wchar_t-to-char conversion routine and then use the char* version for comparing. */
+ return ma_wcscmp(ext1, ext2) == 0;
+ }
+ #endif
}
#endif /* MA_HAS_PATH_API */
@@ -66119,10 +67777,18 @@ static ma_bool32 ma_encoder__internal_on_seek_wav(void* pUserData, int offset, m
{
ma_encoder* pEncoder = (ma_encoder*)pUserData;
ma_result result;
+ ma_seek_origin maSeekOrigin;
MA_ASSERT(pEncoder != NULL);
- result = pEncoder->onSeek(pEncoder, offset, (origin == ma_dr_wav_seek_origin_start) ? ma_seek_origin_start : ma_seek_origin_current);
+ maSeekOrigin = ma_seek_origin_start;
+ if (origin == MA_DR_WAV_SEEK_CUR) {
+ maSeekOrigin = ma_seek_origin_current;
+ } else if (origin == MA_DR_WAV_SEEK_END) {
+ maSeekOrigin = ma_seek_origin_end;
+ }
+
+ result = pEncoder->onSeek(pEncoder, offset, maSeekOrigin);
if (result != MA_SUCCESS) {
return MA_FALSE;
} else {
@@ -67644,7 +69310,7 @@ static MA_INLINE ma_uint32 ma_hash_getblock(const ma_uint32* blocks, int i)
ma_uint32 block;
/* Try silencing a sanitization warning about unaligned access by doing a memcpy() instead of assignment. */
- MA_COPY_MEMORY(&block, ma_offset_ptr(blocks, i * sizeof(block)), sizeof(block));
+ MA_COPY_MEMORY(&block, ma_offset_ptr(blocks, i * (int) sizeof(block)), sizeof(block));
if (ma_is_little_endian()) {
return block;
@@ -67720,7 +69386,7 @@ static ma_uint32 ma_hash_string_32(const char* str)
static ma_uint32 ma_hash_string_w_32(const wchar_t* str)
{
- return ma_hash_32(str, (int)wcslen(str) * sizeof(*str), MA_DEFAULT_HASH_SEED);
+ return ma_hash_32(str, (int)ma_wcslen(str) * sizeof(*str), MA_DEFAULT_HASH_SEED);
}
@@ -67880,6 +69546,7 @@ static MA_INLINE ma_resource_manager_data_buffer_node* ma_resource_manager_data_
return ma_resource_manager_data_buffer_node_find_min(pDataBufferNode->pChildHi);
}
+#if 0 /* Currently unused, but might make use of this later. */
static MA_INLINE ma_resource_manager_data_buffer_node* ma_resource_manager_data_buffer_node_find_inorder_predecessor(ma_resource_manager_data_buffer_node* pDataBufferNode)
{
MA_ASSERT(pDataBufferNode != NULL);
@@ -67887,6 +69554,7 @@ static MA_INLINE ma_resource_manager_data_buffer_node* ma_resource_manager_data_
return ma_resource_manager_data_buffer_node_find_max(pDataBufferNode->pChildLo);
}
+#endif
static ma_result ma_resource_manager_data_buffer_node_remove(ma_resource_manager* pResourceManager, ma_resource_manager_data_buffer_node* pDataBufferNode)
{
@@ -69009,16 +70677,19 @@ static ma_result ma_resource_manager_data_buffer_node_acquire_critical_section(m
/* Failed to post job. Probably ran out of memory. */
ma_log_postf(ma_resource_manager_get_log(pResourceManager), MA_LOG_LEVEL_ERROR, "Failed to post MA_JOB_TYPE_RESOURCE_MANAGER_LOAD_DATA_BUFFER_NODE job. %s.\n", ma_result_description(result));
- /*
- Fences were acquired before posting the job, but since the job was not able to
- be posted, we need to make sure we release them so nothing gets stuck waiting.
- */
- if (pInitFence != NULL) { ma_fence_release(pInitFence); }
- if (pDoneFence != NULL) { ma_fence_release(pDoneFence); }
-
if ((flags & MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_WAIT_INIT) != 0) {
ma_resource_manager_inline_notification_uninit(pInitNotification);
} else {
+ /*
+ Fences were acquired before posting the job, but since the job was not able to
+ be posted, we need to make sure we release them so nothing gets stuck waiting.
+
+ In the WAIT_INIT case, these will have already been released in ma_job_process()
+ so we should only release fences in this branch.
+ */
+ if (pInitFence != NULL) { ma_fence_release(pInitFence); }
+ if (pDoneFence != NULL) { ma_fence_release(pDoneFence); }
+
/* These will have been freed by the job thread, but with WAIT_INIT they will already have happened since the job has already been handled. */
ma_free(pFilePathCopy, &pResourceManager->config.allocationCallbacks);
ma_free(pFilePathWCopy, &pResourceManager->config.allocationCallbacks);
@@ -76674,7 +78345,7 @@ static ma_result ma_sound_init_from_data_source_internal(ma_engine* pEngine, con
}
if (pConfig->loopPointBegInPCMFrames != 0 || pConfig->loopPointEndInPCMFrames != ~((ma_uint64)0)) {
- ma_data_source_set_range_in_pcm_frames(ma_sound_get_data_source(pSound), pConfig->loopPointBegInPCMFrames, pConfig->loopPointEndInPCMFrames);
+ ma_data_source_set_loop_point_in_pcm_frames(ma_sound_get_data_source(pSound), pConfig->loopPointBegInPCMFrames, pConfig->loopPointEndInPCMFrames);
}
ma_sound_set_looping(pSound, pConfig->isLooping || ((pConfig->flags & MA_SOUND_FLAG_LOOPING) != 0));
@@ -76736,6 +78407,7 @@ MA_API ma_result ma_sound_init_from_file_internal(ma_engine* pEngine, const ma_s
result = ma_resource_manager_data_source_init_ex(pEngine->pResourceManager, &resourceManagerDataSourceConfig, pSound->pResourceManagerDataSource);
if (result != MA_SUCCESS) {
+ ma_free(pSound->pResourceManagerDataSource, &pEngine->allocationCallbacks);
goto done;
}
@@ -77541,7 +79213,12 @@ MA_API ma_uint64 ma_sound_get_time_in_pcm_frames(const ma_sound* pSound)
MA_API ma_uint64 ma_sound_get_time_in_milliseconds(const ma_sound* pSound)
{
- return ma_sound_get_time_in_pcm_frames(pSound) * 1000 / ma_engine_get_sample_rate(ma_sound_get_engine(pSound));
+ ma_uint32 sampleRate = ma_engine_get_sample_rate(ma_sound_get_engine(pSound));
+ if (sampleRate == 0) {
+ return 0; /* Prevent a division by zero. */
+ }
+
+ return ma_sound_get_time_in_pcm_frames(pSound) * 1000 / sampleRate;
}
MA_API void ma_sound_set_looping(ma_sound* pSound, ma_bool32 isLooping)
@@ -77625,7 +79302,7 @@ MA_API ma_result ma_sound_seek_to_second(ma_sound* pSound, float seekPointInSeco
return ma_sound_seek_to_pcm_frame(pSound, frameIndex);
}
-MA_API ma_result ma_sound_get_data_format(ma_sound* pSound, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate, ma_channel* pChannelMap, size_t channelMapCap)
+MA_API ma_result ma_sound_get_data_format(const ma_sound* pSound, ma_format* pFormat, ma_uint32* pChannels, ma_uint32* pSampleRate, ma_channel* pChannelMap, size_t channelMapCap)
{
if (pSound == NULL) {
return MA_INVALID_ARGS;
@@ -77658,7 +79335,7 @@ MA_API ma_result ma_sound_get_data_format(ma_sound* pSound, ma_format* pFormat,
}
}
-MA_API ma_result ma_sound_get_cursor_in_pcm_frames(ma_sound* pSound, ma_uint64* pCursor)
+MA_API ma_result ma_sound_get_cursor_in_pcm_frames(const ma_sound* pSound, ma_uint64* pCursor)
{
ma_uint64 seekTarget;
@@ -77680,7 +79357,7 @@ MA_API ma_result ma_sound_get_cursor_in_pcm_frames(ma_sound* pSound, ma_uint64*
}
}
-MA_API ma_result ma_sound_get_length_in_pcm_frames(ma_sound* pSound, ma_uint64* pLength)
+MA_API ma_result ma_sound_get_length_in_pcm_frames(const ma_sound* pSound, ma_uint64* pLength)
{
if (pSound == NULL) {
return MA_INVALID_ARGS;
@@ -77694,7 +79371,7 @@ MA_API ma_result ma_sound_get_length_in_pcm_frames(ma_sound* pSound, ma_uint64*
return ma_data_source_get_length_in_pcm_frames(pSound->pDataSource, pLength);
}
-MA_API ma_result ma_sound_get_cursor_in_seconds(ma_sound* pSound, float* pCursor)
+MA_API ma_result ma_sound_get_cursor_in_seconds(const ma_sound* pSound, float* pCursor)
{
ma_result result;
ma_uint64 cursorInPCMFrames;
@@ -77720,7 +79397,7 @@ MA_API ma_result ma_sound_get_cursor_in_seconds(ma_sound* pSound, float* pCursor
return MA_SUCCESS;
}
-MA_API ma_result ma_sound_get_length_in_seconds(ma_sound* pSound, float* pLength)
+MA_API ma_result ma_sound_get_length_in_seconds(const ma_sound* pSound, float* pLength)
{
if (pSound == NULL) {
return MA_INVALID_ARGS;
@@ -78539,12 +80216,12 @@ MA_PRIVATE ma_bool32 ma_dr_wav__seek_forward(ma_dr_wav_seek_proc onSeek, ma_uint
ma_uint64 bytesRemainingToSeek = offset;
while (bytesRemainingToSeek > 0) {
if (bytesRemainingToSeek > 0x7FFFFFFF) {
- if (!onSeek(pUserData, 0x7FFFFFFF, ma_dr_wav_seek_origin_current)) {
+ if (!onSeek(pUserData, 0x7FFFFFFF, MA_DR_WAV_SEEK_CUR)) {
return MA_FALSE;
}
bytesRemainingToSeek -= 0x7FFFFFFF;
} else {
- if (!onSeek(pUserData, (int)bytesRemainingToSeek, ma_dr_wav_seek_origin_current)) {
+ if (!onSeek(pUserData, (int)bytesRemainingToSeek, MA_DR_WAV_SEEK_CUR)) {
return MA_FALSE;
}
bytesRemainingToSeek = 0;
@@ -78555,17 +80232,17 @@ MA_PRIVATE ma_bool32 ma_dr_wav__seek_forward(ma_dr_wav_seek_proc onSeek, ma_uint
MA_PRIVATE ma_bool32 ma_dr_wav__seek_from_start(ma_dr_wav_seek_proc onSeek, ma_uint64 offset, void* pUserData)
{
if (offset <= 0x7FFFFFFF) {
- return onSeek(pUserData, (int)offset, ma_dr_wav_seek_origin_start);
+ return onSeek(pUserData, (int)offset, MA_DR_WAV_SEEK_SET);
}
- if (!onSeek(pUserData, 0x7FFFFFFF, ma_dr_wav_seek_origin_start)) {
+ if (!onSeek(pUserData, 0x7FFFFFFF, MA_DR_WAV_SEEK_SET)) {
return MA_FALSE;
}
offset -= 0x7FFFFFFF;
for (;;) {
if (offset <= 0x7FFFFFFF) {
- return onSeek(pUserData, (int)offset, ma_dr_wav_seek_origin_current);
+ return onSeek(pUserData, (int)offset, MA_DR_WAV_SEEK_CUR);
}
- if (!onSeek(pUserData, 0x7FFFFFFF, ma_dr_wav_seek_origin_current)) {
+ if (!onSeek(pUserData, 0x7FFFFFFF, MA_DR_WAV_SEEK_CUR)) {
return MA_FALSE;
}
offset -= 0x7FFFFFFF;
@@ -78588,7 +80265,7 @@ MA_PRIVATE ma_bool32 ma_dr_wav__on_seek(ma_dr_wav_seek_proc onSeek, void* pUserD
if (!onSeek(pUserData, offset, origin)) {
return MA_FALSE;
}
- if (origin == ma_dr_wav_seek_origin_start) {
+ if (origin == MA_DR_WAV_SEEK_SET) {
*pCursor = offset;
} else {
*pCursor += offset;
@@ -78707,12 +80384,12 @@ MA_PRIVATE ma_uint64 ma_dr_wav__read_smpl_to_metadata_obj(ma_dr_wav__metadata_pa
ma_uint8 smplLoopData[MA_DR_WAV_SMPL_LOOP_BYTES];
bytesJustRead = ma_dr_wav__metadata_parser_read(pParser, smplLoopData, sizeof(smplLoopData), &totalBytesRead);
if (bytesJustRead == sizeof(smplLoopData)) {
- pMetadata->data.smpl.pLoops[iSampleLoop].cuePointId = ma_dr_wav_bytes_to_u32(smplLoopData + 0);
- pMetadata->data.smpl.pLoops[iSampleLoop].type = ma_dr_wav_bytes_to_u32(smplLoopData + 4);
- pMetadata->data.smpl.pLoops[iSampleLoop].firstSampleByteOffset = ma_dr_wav_bytes_to_u32(smplLoopData + 8);
- pMetadata->data.smpl.pLoops[iSampleLoop].lastSampleByteOffset = ma_dr_wav_bytes_to_u32(smplLoopData + 12);
- pMetadata->data.smpl.pLoops[iSampleLoop].sampleFraction = ma_dr_wav_bytes_to_u32(smplLoopData + 16);
- pMetadata->data.smpl.pLoops[iSampleLoop].playCount = ma_dr_wav_bytes_to_u32(smplLoopData + 20);
+ pMetadata->data.smpl.pLoops[iSampleLoop].cuePointId = ma_dr_wav_bytes_to_u32(smplLoopData + 0);
+ pMetadata->data.smpl.pLoops[iSampleLoop].type = ma_dr_wav_bytes_to_u32(smplLoopData + 4);
+ pMetadata->data.smpl.pLoops[iSampleLoop].firstSampleOffset = ma_dr_wav_bytes_to_u32(smplLoopData + 8);
+ pMetadata->data.smpl.pLoops[iSampleLoop].lastSampleOffset = ma_dr_wav_bytes_to_u32(smplLoopData + 12);
+ pMetadata->data.smpl.pLoops[iSampleLoop].sampleFraction = ma_dr_wav_bytes_to_u32(smplLoopData + 16);
+ pMetadata->data.smpl.pLoops[iSampleLoop].playCount = ma_dr_wav_bytes_to_u32(smplLoopData + 20);
} else {
break;
}
@@ -78756,7 +80433,7 @@ MA_PRIVATE ma_uint64 ma_dr_wav__read_cue_to_metadata_obj(ma_dr_wav__metadata_par
pMetadata->data.cue.pCuePoints[iCuePoint].dataChunkId[3] = cuePointData[11];
pMetadata->data.cue.pCuePoints[iCuePoint].chunkStart = ma_dr_wav_bytes_to_u32(cuePointData + 12);
pMetadata->data.cue.pCuePoints[iCuePoint].blockStart = ma_dr_wav_bytes_to_u32(cuePointData + 16);
- pMetadata->data.cue.pCuePoints[iCuePoint].sampleByteOffset = ma_dr_wav_bytes_to_u32(cuePointData + 20);
+ pMetadata->data.cue.pCuePoints[iCuePoint].sampleOffset = ma_dr_wav_bytes_to_u32(cuePointData + 20);
} else {
break;
}
@@ -79096,7 +80773,7 @@ MA_PRIVATE ma_uint64 ma_dr_wav__metadata_process_chunk(ma_dr_wav__metadata_parse
if (pParser->stage == ma_dr_wav__metadata_parser_stage_count) {
ma_uint8 buffer[4];
size_t bytesJustRead;
- if (!pParser->onSeek(pParser->pReadSeekUserData, 28, ma_dr_wav_seek_origin_current)) {
+ if (!pParser->onSeek(pParser->pReadSeekUserData, 28, MA_DR_WAV_SEEK_CUR)) {
return bytesRead;
}
bytesRead += 28;
@@ -79191,7 +80868,7 @@ MA_PRIVATE ma_uint64 ma_dr_wav__metadata_process_chunk(ma_dr_wav__metadata_parse
return bytesRead;
}
allocSizeNeeded += ma_dr_wav__strlen(buffer) + 1;
- allocSizeNeeded += (size_t)pChunkHeader->sizeInBytes - MA_DR_WAV_BEXT_BYTES;
+ allocSizeNeeded += (size_t)pChunkHeader->sizeInBytes - MA_DR_WAV_BEXT_BYTES + 1;
ma_dr_wav__metadata_request_extra_memory_for_stage_2(pParser, allocSizeNeeded, 1);
pParser->metadataCount += 1;
} else {
@@ -79274,6 +80951,16 @@ MA_PRIVATE ma_uint64 ma_dr_wav__metadata_process_chunk(ma_dr_wav__metadata_parse
subchunkBytesRead = ma_dr_wav__metadata_process_info_text_chunk(pParser, subchunkDataSize, ma_dr_wav_metadata_type_list_info_album);
} else if (ma_dr_wav__chunk_matches(allowedMetadataTypes, subchunkId, ma_dr_wav_metadata_type_list_info_tracknumber, "ITRK")) {
subchunkBytesRead = ma_dr_wav__metadata_process_info_text_chunk(pParser, subchunkDataSize, ma_dr_wav_metadata_type_list_info_tracknumber);
+ } else if (ma_dr_wav__chunk_matches(allowedMetadataTypes, subchunkId, ma_dr_wav_metadata_type_list_info_location, "IARL")) {
+ subchunkBytesRead = ma_dr_wav__metadata_process_info_text_chunk(pParser, subchunkDataSize, ma_dr_wav_metadata_type_list_info_location);
+ } else if (ma_dr_wav__chunk_matches(allowedMetadataTypes, subchunkId, ma_dr_wav_metadata_type_list_info_organization, "ICMS")) {
+ subchunkBytesRead = ma_dr_wav__metadata_process_info_text_chunk(pParser, subchunkDataSize, ma_dr_wav_metadata_type_list_info_organization);
+ } else if (ma_dr_wav__chunk_matches(allowedMetadataTypes, subchunkId, ma_dr_wav_metadata_type_list_info_keywords, "IKEY")) {
+ subchunkBytesRead = ma_dr_wav__metadata_process_info_text_chunk(pParser, subchunkDataSize, ma_dr_wav_metadata_type_list_info_keywords);
+ } else if (ma_dr_wav__chunk_matches(allowedMetadataTypes, subchunkId, ma_dr_wav_metadata_type_list_info_medium, "IMED")) {
+ subchunkBytesRead = ma_dr_wav__metadata_process_info_text_chunk(pParser, subchunkDataSize, ma_dr_wav_metadata_type_list_info_medium);
+ } else if (ma_dr_wav__chunk_matches(allowedMetadataTypes, subchunkId, ma_dr_wav_metadata_type_list_info_description, "ISBJ")) {
+ subchunkBytesRead = ma_dr_wav__metadata_process_info_text_chunk(pParser, subchunkDataSize, ma_dr_wav_metadata_type_list_info_description);
} else if ((allowedMetadataTypes & ma_dr_wav_metadata_type_unknown) != 0) {
subchunkBytesRead = ma_dr_wav__metadata_process_unknown_chunk(pParser, subchunkId, subchunkDataSize, listType);
}
@@ -79281,13 +80968,13 @@ MA_PRIVATE ma_uint64 ma_dr_wav__metadata_process_chunk(ma_dr_wav__metadata_parse
MA_DR_WAV_ASSERT(subchunkBytesRead <= subchunkDataSize);
if (subchunkBytesRead < subchunkDataSize) {
ma_uint64 bytesToSeek = subchunkDataSize - subchunkBytesRead;
- if (!pParser->onSeek(pParser->pReadSeekUserData, (int)bytesToSeek, ma_dr_wav_seek_origin_current)) {
+ if (!pParser->onSeek(pParser->pReadSeekUserData, (int)bytesToSeek, MA_DR_WAV_SEEK_CUR)) {
break;
}
bytesRead += bytesToSeek;
}
if ((subchunkDataSize % 2) == 1) {
- if (!pParser->onSeek(pParser->pReadSeekUserData, 1, ma_dr_wav_seek_origin_current)) {
+ if (!pParser->onSeek(pParser->pReadSeekUserData, 1, MA_DR_WAV_SEEK_CUR)) {
break;
}
bytesRead += 1;
@@ -79324,7 +81011,7 @@ MA_API ma_uint16 ma_dr_wav_fmt_get_format(const ma_dr_wav_fmt* pFMT)
return ma_dr_wav_bytes_to_u16(pFMT->subFormat);
}
}
-MA_PRIVATE ma_bool32 ma_dr_wav_preinit(ma_dr_wav* pWav, ma_dr_wav_read_proc onRead, ma_dr_wav_seek_proc onSeek, void* pReadSeekUserData, const ma_allocation_callbacks* pAllocationCallbacks)
+MA_PRIVATE ma_bool32 ma_dr_wav_preinit(ma_dr_wav* pWav, ma_dr_wav_read_proc onRead, ma_dr_wav_seek_proc onSeek, ma_dr_wav_tell_proc onTell, void* pReadSeekTellUserData, const ma_allocation_callbacks* pAllocationCallbacks)
{
if (pWav == NULL || onRead == NULL || onSeek == NULL) {
return MA_FALSE;
@@ -79332,7 +81019,8 @@ MA_PRIVATE ma_bool32 ma_dr_wav_preinit(ma_dr_wav* pWav, ma_dr_wav_read_proc onRe
MA_DR_WAV_ZERO_MEMORY(pWav, sizeof(*pWav));
pWav->onRead = onRead;
pWav->onSeek = onSeek;
- pWav->pUserData = pReadSeekUserData;
+ pWav->onTell = onTell;
+ pWav->pUserData = pReadSeekTellUserData;
pWav->allocationCallbacks = ma_dr_wav_copy_allocation_callbacks_or_defaults(pAllocationCallbacks);
if (pWav->allocationCallbacks.onFree == NULL || (pWav->allocationCallbacks.onMalloc == NULL && pWav->allocationCallbacks.onRealloc == NULL)) {
return MA_FALSE;
@@ -79546,14 +81234,14 @@ MA_PRIVATE ma_bool32 ma_dr_wav_init__internal(ma_dr_wav* pWav, ma_dr_wav_chunk_p
fmt.channelMask = ma_dr_wav_bytes_to_u32_ex(fmtext + 2, pWav->container);
ma_dr_wav_bytes_to_guid(fmtext + 6, fmt.subFormat);
} else {
- if (pWav->onSeek(pWav->pUserData, fmt.extendedSize, ma_dr_wav_seek_origin_current) == MA_FALSE) {
+ if (pWav->onSeek(pWav->pUserData, fmt.extendedSize, MA_DR_WAV_SEEK_CUR) == MA_FALSE) {
return MA_FALSE;
}
}
cursor += fmt.extendedSize;
bytesReadSoFar += fmt.extendedSize;
}
- if (pWav->onSeek(pWav->pUserData, (int)(header.sizeInBytes - bytesReadSoFar), ma_dr_wav_seek_origin_current) == MA_FALSE) {
+ if (pWav->onSeek(pWav->pUserData, (int)(header.sizeInBytes - bytesReadSoFar), MA_DR_WAV_SEEK_CUR) == MA_FALSE) {
return MA_FALSE;
}
cursor += (header.sizeInBytes - bytesReadSoFar);
@@ -79704,15 +81392,26 @@ MA_PRIVATE ma_bool32 ma_dr_wav_init__internal(ma_dr_wav* pWav, ma_dr_wav_chunk_p
return MA_FALSE;
}
offset = ma_dr_wav_bytes_to_u32_ex(offsetAndBlockSizeData + 0, pWav->container);
- if (ma_dr_wav__seek_forward(pWav->onSeek, offset, pWav->pUserData) == MA_FALSE) {
- return MA_FALSE;
- }
- cursor += offset;
- pWav->dataChunkDataPos = cursor;
+ pWav->dataChunkDataPos = cursor + offset;
dataChunkSize = chunkSize;
- if (sequential || !isProcessingMetadata) {
- break;
+ if (dataChunkSize > offset) {
+ dataChunkSize -= offset;
} else {
+ dataChunkSize = 0;
+ }
+ if (sequential) {
+ if (foundChunk_fmt) {
+ if (ma_dr_wav__seek_forward(pWav->onSeek, offset, pWav->pUserData) == MA_FALSE) {
+ return MA_FALSE;
+ }
+ cursor += offset;
+ break;
+ } else {
+ return MA_FALSE;
+ }
+ } else {
+ chunkSize += header.paddingSize;
+ chunkSize -= sizeof(offsetAndBlockSizeData);
if (ma_dr_wav__seek_forward(pWav->onSeek, chunkSize, pWav->pUserData) == MA_FALSE) {
break;
}
@@ -79776,6 +81475,17 @@ MA_PRIVATE ma_bool32 ma_dr_wav_init__internal(ma_dr_wav* pWav, ma_dr_wav_chunk_p
pWav->pMetadata = metadataParser.pMetadata;
pWav->metadataCount = metadataParser.metadataCount;
}
+ if (pWav->onTell != NULL && pWav->onSeek != NULL) {
+ if (pWav->onSeek(pWav->pUserData, 0, MA_DR_WAV_SEEK_END) == MA_TRUE) {
+ ma_int64 fileSize;
+ if (pWav->onTell(pWav->pUserData, &fileSize)) {
+ if (dataChunkSize + pWav->dataChunkDataPos > (ma_uint64)fileSize) {
+ dataChunkSize = (ma_uint64)fileSize - pWav->dataChunkDataPos;
+ }
+ }
+ } else {
+ }
+ }
if (dataChunkSize == 0xFFFFFFFF && (pWav->container == ma_dr_wav_container_riff || pWav->container == ma_dr_wav_container_rifx) && pWav->isSequentialWrite == MA_FALSE) {
dataChunkSize = 0;
for (;;) {
@@ -79795,8 +81505,14 @@ MA_PRIVATE ma_bool32 ma_dr_wav_init__internal(ma_dr_wav* pWav, ma_dr_wav_chunk_p
pWav->sampleRate = fmt.sampleRate;
pWav->channels = fmt.channels;
pWav->bitsPerSample = fmt.bitsPerSample;
- pWav->bytesRemaining = dataChunkSize;
pWav->translatedFormatTag = translatedFormatTag;
+ if (!ma_dr_wav__is_compressed_format_tag(translatedFormatTag)) {
+ ma_uint32 bytesPerFrame = ma_dr_wav_get_bytes_per_pcm_frame(pWav);
+ if (bytesPerFrame > 0) {
+ dataChunkSize -= (dataChunkSize % bytesPerFrame);
+ }
+ }
+ pWav->bytesRemaining = dataChunkSize;
pWav->dataChunkDataSize = dataChunkSize;
if (sampleCountFromFactChunk != 0) {
pWav->totalPCMFrameCount = sampleCountFromFactChunk;
@@ -79851,20 +81567,20 @@ MA_PRIVATE ma_bool32 ma_dr_wav_init__internal(ma_dr_wav* pWav, ma_dr_wav_chunk_p
#endif
return MA_TRUE;
}
-MA_API ma_bool32 ma_dr_wav_init(ma_dr_wav* pWav, ma_dr_wav_read_proc onRead, ma_dr_wav_seek_proc onSeek, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks)
+MA_API ma_bool32 ma_dr_wav_init(ma_dr_wav* pWav, ma_dr_wav_read_proc onRead, ma_dr_wav_seek_proc onSeek, ma_dr_wav_tell_proc onTell, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks)
{
- return ma_dr_wav_init_ex(pWav, onRead, onSeek, NULL, pUserData, NULL, 0, pAllocationCallbacks);
+ return ma_dr_wav_init_ex(pWav, onRead, onSeek, onTell, NULL, pUserData, NULL, 0, pAllocationCallbacks);
}
-MA_API ma_bool32 ma_dr_wav_init_ex(ma_dr_wav* pWav, ma_dr_wav_read_proc onRead, ma_dr_wav_seek_proc onSeek, ma_dr_wav_chunk_proc onChunk, void* pReadSeekUserData, void* pChunkUserData, ma_uint32 flags, const ma_allocation_callbacks* pAllocationCallbacks)
+MA_API ma_bool32 ma_dr_wav_init_ex(ma_dr_wav* pWav, ma_dr_wav_read_proc onRead, ma_dr_wav_seek_proc onSeek, ma_dr_wav_tell_proc onTell, ma_dr_wav_chunk_proc onChunk, void* pReadSeekTellUserData, void* pChunkUserData, ma_uint32 flags, const ma_allocation_callbacks* pAllocationCallbacks)
{
- if (!ma_dr_wav_preinit(pWav, onRead, onSeek, pReadSeekUserData, pAllocationCallbacks)) {
+ if (!ma_dr_wav_preinit(pWav, onRead, onSeek, onTell, pReadSeekTellUserData, pAllocationCallbacks)) {
return MA_FALSE;
}
return ma_dr_wav_init__internal(pWav, onChunk, pChunkUserData, flags);
}
-MA_API ma_bool32 ma_dr_wav_init_with_metadata(ma_dr_wav* pWav, ma_dr_wav_read_proc onRead, ma_dr_wav_seek_proc onSeek, void* pUserData, ma_uint32 flags, const ma_allocation_callbacks* pAllocationCallbacks)
+MA_API ma_bool32 ma_dr_wav_init_with_metadata(ma_dr_wav* pWav, ma_dr_wav_read_proc onRead, ma_dr_wav_seek_proc onSeek, ma_dr_wav_tell_proc onTell, void* pUserData, ma_uint32 flags, const ma_allocation_callbacks* pAllocationCallbacks)
{
- if (!ma_dr_wav_preinit(pWav, onRead, onSeek, pUserData, pAllocationCallbacks)) {
+ if (!ma_dr_wav_preinit(pWav, onRead, onSeek, onTell, pUserData, pAllocationCallbacks)) {
return MA_FALSE;
}
return ma_dr_wav_init__internal(pWav, NULL, NULL, flags | MA_DR_WAV_WITH_METADATA);
@@ -80026,8 +81742,8 @@ MA_PRIVATE size_t ma_dr_wav__write_or_count_metadata(ma_dr_wav* pWav, ma_dr_wav_
for (iLoop = 0; iLoop < pMetadata->data.smpl.sampleLoopCount; ++iLoop) {
bytesWritten += ma_dr_wav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].cuePointId);
bytesWritten += ma_dr_wav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].type);
- bytesWritten += ma_dr_wav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].firstSampleByteOffset);
- bytesWritten += ma_dr_wav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].lastSampleByteOffset);
+ bytesWritten += ma_dr_wav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].firstSampleOffset);
+ bytesWritten += ma_dr_wav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].lastSampleOffset);
bytesWritten += ma_dr_wav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].sampleFraction);
bytesWritten += ma_dr_wav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].playCount);
}
@@ -80061,7 +81777,7 @@ MA_PRIVATE size_t ma_dr_wav__write_or_count_metadata(ma_dr_wav* pWav, ma_dr_wav_
bytesWritten += ma_dr_wav__write_or_count(pWav, pMetadata->data.cue.pCuePoints[iCuePoint].dataChunkId, 4);
bytesWritten += ma_dr_wav__write_or_count_u32ne_to_le(pWav, pMetadata->data.cue.pCuePoints[iCuePoint].chunkStart);
bytesWritten += ma_dr_wav__write_or_count_u32ne_to_le(pWav, pMetadata->data.cue.pCuePoints[iCuePoint].blockStart);
- bytesWritten += ma_dr_wav__write_or_count_u32ne_to_le(pWav, pMetadata->data.cue.pCuePoints[iCuePoint].sampleByteOffset);
+ bytesWritten += ma_dr_wav__write_or_count_u32ne_to_le(pWav, pMetadata->data.cue.pCuePoints[iCuePoint].sampleOffset);
}
} break;
case ma_dr_wav_metadata_type_acid:
@@ -80147,15 +81863,20 @@ MA_PRIVATE size_t ma_dr_wav__write_or_count_metadata(ma_dr_wav* pWav, ma_dr_wav_
if (pMetadata->type & ma_dr_wav_metadata_type_list_all_info_strings) {
const char* pID = NULL;
switch (pMetadata->type) {
- case ma_dr_wav_metadata_type_list_info_software: pID = "ISFT"; break;
- case ma_dr_wav_metadata_type_list_info_copyright: pID = "ICOP"; break;
- case ma_dr_wav_metadata_type_list_info_title: pID = "INAM"; break;
- case ma_dr_wav_metadata_type_list_info_artist: pID = "IART"; break;
- case ma_dr_wav_metadata_type_list_info_comment: pID = "ICMT"; break;
- case ma_dr_wav_metadata_type_list_info_date: pID = "ICRD"; break;
- case ma_dr_wav_metadata_type_list_info_genre: pID = "IGNR"; break;
- case ma_dr_wav_metadata_type_list_info_album: pID = "IPRD"; break;
- case ma_dr_wav_metadata_type_list_info_tracknumber: pID = "ITRK"; break;
+ case ma_dr_wav_metadata_type_list_info_software: pID = "ISFT"; break;
+ case ma_dr_wav_metadata_type_list_info_copyright: pID = "ICOP"; break;
+ case ma_dr_wav_metadata_type_list_info_title: pID = "INAM"; break;
+ case ma_dr_wav_metadata_type_list_info_artist: pID = "IART"; break;
+ case ma_dr_wav_metadata_type_list_info_comment: pID = "ICMT"; break;
+ case ma_dr_wav_metadata_type_list_info_date: pID = "ICRD"; break;
+ case ma_dr_wav_metadata_type_list_info_genre: pID = "IGNR"; break;
+ case ma_dr_wav_metadata_type_list_info_album: pID = "IPRD"; break;
+ case ma_dr_wav_metadata_type_list_info_tracknumber: pID = "ITRK"; break;
+ case ma_dr_wav_metadata_type_list_info_location: pID = "IARL"; break;
+ case ma_dr_wav_metadata_type_list_info_organization: pID = "ICMS"; break;
+ case ma_dr_wav_metadata_type_list_info_keywords: pID = "IKEY"; break;
+ case ma_dr_wav_metadata_type_list_info_medium: pID = "IMED"; break;
+ case ma_dr_wav_metadata_type_list_info_description: pID = "ISBJ"; break;
default: break;
}
MA_DR_WAV_ASSERT(pID != NULL);
@@ -80370,7 +82091,7 @@ MA_PRIVATE ma_bool32 ma_dr_wav_init_write__internal(ma_dr_wav* pWav, const ma_dr
}
pWav->dataChunkDataSizeTargetWrite = initialDataChunkSize;
if (pFormat->container == ma_dr_wav_container_riff) {
- ma_uint32 chunkSizeRIFF = 28 + (ma_uint32)initialDataChunkSize;
+ ma_uint32 chunkSizeRIFF = 36 + (ma_uint32)initialDataChunkSize;
runningPos += ma_dr_wav__write(pWav, "RIFF", 4);
runningPos += ma_dr_wav__write_u32ne_to_le(pWav, chunkSizeRIFF);
runningPos += ma_dr_wav__write(pWav, "WAVE", 4);
@@ -80493,7 +82214,31 @@ MA_PRIVATE size_t ma_dr_wav__on_write_stdio(void* pUserData, const void* pData,
}
MA_PRIVATE ma_bool32 ma_dr_wav__on_seek_stdio(void* pUserData, int offset, ma_dr_wav_seek_origin origin)
{
- return fseek((FILE*)pUserData, offset, (origin == ma_dr_wav_seek_origin_current) ? SEEK_CUR : SEEK_SET) == 0;
+ int whence = SEEK_SET;
+ if (origin == MA_DR_WAV_SEEK_CUR) {
+ whence = SEEK_CUR;
+ } else if (origin == MA_DR_WAV_SEEK_END) {
+ whence = SEEK_END;
+ }
+ return fseek((FILE*)pUserData, offset, whence) == 0;
+}
+MA_PRIVATE ma_bool32 ma_dr_wav__on_tell_stdio(void* pUserData, ma_int64* pCursor)
+{
+ FILE* pFileStdio = (FILE*)pUserData;
+ ma_int64 result;
+ MA_DR_WAV_ASSERT(pFileStdio != NULL);
+ MA_DR_WAV_ASSERT(pCursor != NULL);
+#if defined(_WIN32) && !defined(NXDK)
+ #if defined(_MSC_VER) && _MSC_VER > 1200
+ result = _ftelli64(pFileStdio);
+ #else
+ result = ftell(pFileStdio);
+ #endif
+#else
+ result = ftell(pFileStdio);
+#endif
+ *pCursor = result;
+ return MA_TRUE;
}
MA_API ma_bool32 ma_dr_wav_init_file(ma_dr_wav* pWav, const char* filename, const ma_allocation_callbacks* pAllocationCallbacks)
{
@@ -80502,7 +82247,7 @@ MA_API ma_bool32 ma_dr_wav_init_file(ma_dr_wav* pWav, const char* filename, cons
MA_PRIVATE ma_bool32 ma_dr_wav_init_file__internal_FILE(ma_dr_wav* pWav, FILE* pFile, ma_dr_wav_chunk_proc onChunk, void* pChunkUserData, ma_uint32 flags, const ma_allocation_callbacks* pAllocationCallbacks)
{
ma_bool32 result;
- result = ma_dr_wav_preinit(pWav, ma_dr_wav__on_read_stdio, ma_dr_wav__on_seek_stdio, (void*)pFile, pAllocationCallbacks);
+ result = ma_dr_wav_preinit(pWav, ma_dr_wav__on_read_stdio, ma_dr_wav__on_seek_stdio, ma_dr_wav__on_tell_stdio, (void*)pFile, pAllocationCallbacks);
if (result != MA_TRUE) {
fclose(pFile);
return result;
@@ -80639,25 +82384,27 @@ MA_PRIVATE size_t ma_dr_wav__on_read_memory(void* pUserData, void* pBufferOut, s
MA_PRIVATE ma_bool32 ma_dr_wav__on_seek_memory(void* pUserData, int offset, ma_dr_wav_seek_origin origin)
{
ma_dr_wav* pWav = (ma_dr_wav*)pUserData;
+ ma_int64 newCursor;
MA_DR_WAV_ASSERT(pWav != NULL);
- if (origin == ma_dr_wav_seek_origin_current) {
- if (offset > 0) {
- if (pWav->memoryStream.currentReadPos + offset > pWav->memoryStream.dataSize) {
- return MA_FALSE;
- }
- } else {
- if (pWav->memoryStream.currentReadPos < (size_t)-offset) {
- return MA_FALSE;
- }
- }
- pWav->memoryStream.currentReadPos += offset;
+ newCursor = pWav->memoryStream.currentReadPos;
+ if (origin == MA_DR_WAV_SEEK_SET) {
+ newCursor = 0;
+ } else if (origin == MA_DR_WAV_SEEK_CUR) {
+ newCursor = (ma_int64)pWav->memoryStream.currentReadPos;
+ } else if (origin == MA_DR_WAV_SEEK_END) {
+ newCursor = (ma_int64)pWav->memoryStream.dataSize;
} else {
- if ((ma_uint32)offset <= pWav->memoryStream.dataSize) {
- pWav->memoryStream.currentReadPos = offset;
- } else {
- return MA_FALSE;
- }
+ MA_DR_WAV_ASSERT(!"Invalid seek origin");
+ return MA_FALSE;
}
+ newCursor += offset;
+ if (newCursor < 0) {
+ return MA_FALSE;
+ }
+ if ((size_t)newCursor > pWav->memoryStream.dataSize) {
+ return MA_FALSE;
+ }
+ pWav->memoryStream.currentReadPos = (size_t)newCursor;
return MA_TRUE;
}
MA_PRIVATE size_t ma_dr_wav__on_write_memory(void* pUserData, const void* pDataIn, size_t bytesToWrite)
@@ -80691,25 +82438,35 @@ MA_PRIVATE size_t ma_dr_wav__on_write_memory(void* pUserData, const void* pDataI
MA_PRIVATE ma_bool32 ma_dr_wav__on_seek_memory_write(void* pUserData, int offset, ma_dr_wav_seek_origin origin)
{
ma_dr_wav* pWav = (ma_dr_wav*)pUserData;
+ ma_int64 newCursor;
MA_DR_WAV_ASSERT(pWav != NULL);
- if (origin == ma_dr_wav_seek_origin_current) {
- if (offset > 0) {
- if (pWav->memoryStreamWrite.currentWritePos + offset > pWav->memoryStreamWrite.dataSize) {
- offset = (int)(pWav->memoryStreamWrite.dataSize - pWav->memoryStreamWrite.currentWritePos);
- }
- } else {
- if (pWav->memoryStreamWrite.currentWritePos < (size_t)-offset) {
- offset = -(int)pWav->memoryStreamWrite.currentWritePos;
- }
- }
- pWav->memoryStreamWrite.currentWritePos += offset;
+ newCursor = pWav->memoryStreamWrite.currentWritePos;
+ if (origin == MA_DR_WAV_SEEK_SET) {
+ newCursor = 0;
+ } else if (origin == MA_DR_WAV_SEEK_CUR) {
+ newCursor = (ma_int64)pWav->memoryStreamWrite.currentWritePos;
+ } else if (origin == MA_DR_WAV_SEEK_END) {
+ newCursor = (ma_int64)pWav->memoryStreamWrite.dataSize;
} else {
- if ((ma_uint32)offset <= pWav->memoryStreamWrite.dataSize) {
- pWav->memoryStreamWrite.currentWritePos = offset;
- } else {
- pWav->memoryStreamWrite.currentWritePos = pWav->memoryStreamWrite.dataSize;
- }
+ MA_DR_WAV_ASSERT(!"Invalid seek origin");
+ return MA_INVALID_ARGS;
}
+ newCursor += offset;
+ if (newCursor < 0) {
+ return MA_FALSE;
+ }
+ if ((size_t)newCursor > pWav->memoryStreamWrite.dataSize) {
+ return MA_FALSE;
+ }
+ pWav->memoryStreamWrite.currentWritePos = (size_t)newCursor;
+ return MA_TRUE;
+}
+MA_PRIVATE ma_bool32 ma_dr_wav__on_tell_memory(void* pUserData, ma_int64* pCursor)
+{
+ ma_dr_wav* pWav = (ma_dr_wav*)pUserData;
+ MA_DR_WAV_ASSERT(pWav != NULL);
+ MA_DR_WAV_ASSERT(pCursor != NULL);
+ *pCursor = (ma_int64)pWav->memoryStream.currentReadPos;
return MA_TRUE;
}
MA_API ma_bool32 ma_dr_wav_init_memory(ma_dr_wav* pWav, const void* data, size_t dataSize, const ma_allocation_callbacks* pAllocationCallbacks)
@@ -80721,7 +82478,7 @@ MA_API ma_bool32 ma_dr_wav_init_memory_ex(ma_dr_wav* pWav, const void* data, siz
if (data == NULL || dataSize == 0) {
return MA_FALSE;
}
- if (!ma_dr_wav_preinit(pWav, ma_dr_wav__on_read_memory, ma_dr_wav__on_seek_memory, pWav, pAllocationCallbacks)) {
+ if (!ma_dr_wav_preinit(pWav, ma_dr_wav__on_read_memory, ma_dr_wav__on_seek_memory, ma_dr_wav__on_tell_memory, pWav, pAllocationCallbacks)) {
return MA_FALSE;
}
pWav->memoryStream.data = (const ma_uint8*)data;
@@ -80734,7 +82491,7 @@ MA_API ma_bool32 ma_dr_wav_init_memory_with_metadata(ma_dr_wav* pWav, const void
if (data == NULL || dataSize == 0) {
return MA_FALSE;
}
- if (!ma_dr_wav_preinit(pWav, ma_dr_wav__on_read_memory, ma_dr_wav__on_seek_memory, pWav, pAllocationCallbacks)) {
+ if (!ma_dr_wav_preinit(pWav, ma_dr_wav__on_read_memory, ma_dr_wav__on_seek_memory, ma_dr_wav__on_tell_memory, pWav, pAllocationCallbacks)) {
return MA_FALSE;
}
pWav->memoryStream.data = (const ma_uint8*)data;
@@ -80793,30 +82550,30 @@ MA_API ma_result ma_dr_wav_uninit(ma_dr_wav* pWav)
}
if (pWav->onSeek && !pWav->isSequentialWrite) {
if (pWav->container == ma_dr_wav_container_riff) {
- if (pWav->onSeek(pWav->pUserData, 4, ma_dr_wav_seek_origin_start)) {
+ if (pWav->onSeek(pWav->pUserData, 4, MA_DR_WAV_SEEK_SET)) {
ma_uint32 riffChunkSize = ma_dr_wav__riff_chunk_size_riff(pWav->dataChunkDataSize, pWav->pMetadata, pWav->metadataCount);
ma_dr_wav__write_u32ne_to_le(pWav, riffChunkSize);
}
- if (pWav->onSeek(pWav->pUserData, (int)pWav->dataChunkDataPos - 4, ma_dr_wav_seek_origin_start)) {
+ if (pWav->onSeek(pWav->pUserData, (int)pWav->dataChunkDataPos - 4, MA_DR_WAV_SEEK_SET)) {
ma_uint32 dataChunkSize = ma_dr_wav__data_chunk_size_riff(pWav->dataChunkDataSize);
ma_dr_wav__write_u32ne_to_le(pWav, dataChunkSize);
}
} else if (pWav->container == ma_dr_wav_container_w64) {
- if (pWav->onSeek(pWav->pUserData, 16, ma_dr_wav_seek_origin_start)) {
+ if (pWav->onSeek(pWav->pUserData, 16, MA_DR_WAV_SEEK_SET)) {
ma_uint64 riffChunkSize = ma_dr_wav__riff_chunk_size_w64(pWav->dataChunkDataSize);
ma_dr_wav__write_u64ne_to_le(pWav, riffChunkSize);
}
- if (pWav->onSeek(pWav->pUserData, (int)pWav->dataChunkDataPos - 8, ma_dr_wav_seek_origin_start)) {
+ if (pWav->onSeek(pWav->pUserData, (int)pWav->dataChunkDataPos - 8, MA_DR_WAV_SEEK_SET)) {
ma_uint64 dataChunkSize = ma_dr_wav__data_chunk_size_w64(pWav->dataChunkDataSize);
ma_dr_wav__write_u64ne_to_le(pWav, dataChunkSize);
}
} else if (pWav->container == ma_dr_wav_container_rf64) {
int ds64BodyPos = 12 + 8;
- if (pWav->onSeek(pWav->pUserData, ds64BodyPos + 0, ma_dr_wav_seek_origin_start)) {
+ if (pWav->onSeek(pWav->pUserData, ds64BodyPos + 0, MA_DR_WAV_SEEK_SET)) {
ma_uint64 riffChunkSize = ma_dr_wav__riff_chunk_size_rf64(pWav->dataChunkDataSize, pWav->pMetadata, pWav->metadataCount);
ma_dr_wav__write_u64ne_to_le(pWav, riffChunkSize);
}
- if (pWav->onSeek(pWav->pUserData, ds64BodyPos + 8, ma_dr_wav_seek_origin_start)) {
+ if (pWav->onSeek(pWav->pUserData, ds64BodyPos + 8, MA_DR_WAV_SEEK_SET)) {
ma_uint64 dataChunkSize = ma_dr_wav__data_chunk_size_rf64(pWav->dataChunkDataSize);
ma_dr_wav__write_u64ne_to_le(pWav, dataChunkSize);
}
@@ -80863,7 +82620,7 @@ MA_API size_t ma_dr_wav_read_raw(ma_dr_wav* pWav, size_t bytesToRead, void* pBuf
if (bytesToSeek > 0x7FFFFFFF) {
bytesToSeek = 0x7FFFFFFF;
}
- if (pWav->onSeek(pWav->pUserData, (int)bytesToSeek, ma_dr_wav_seek_origin_current) == MA_FALSE) {
+ if (pWav->onSeek(pWav->pUserData, (int)bytesToSeek, MA_DR_WAV_SEEK_CUR) == MA_FALSE) {
break;
}
bytesRead += bytesToSeek;
@@ -80962,7 +82719,7 @@ MA_PRIVATE ma_bool32 ma_dr_wav_seek_to_first_pcm_frame(ma_dr_wav* pWav)
if (pWav->onWrite != NULL) {
return MA_FALSE;
}
- if (!pWav->onSeek(pWav->pUserData, (int)pWav->dataChunkDataPos, ma_dr_wav_seek_origin_start)) {
+ if (!pWav->onSeek(pWav->pUserData, (int)pWav->dataChunkDataPos, MA_DR_WAV_SEEK_SET)) {
return MA_FALSE;
}
if (ma_dr_wav__is_compressed_format_tag(pWav->translatedFormatTag)) {
@@ -81043,7 +82800,7 @@ MA_API ma_bool32 ma_dr_wav_seek_to_pcm_frame(ma_dr_wav* pWav, ma_uint64 targetFr
}
while (offset > 0) {
int offset32 = ((offset > INT_MAX) ? INT_MAX : (int)offset);
- if (!pWav->onSeek(pWav->pUserData, offset32, ma_dr_wav_seek_origin_current)) {
+ if (!pWav->onSeek(pWav->pUserData, offset32, MA_DR_WAV_SEEK_CUR)) {
return MA_FALSE;
}
pWav->readCursorInPCMFrames += offset32 / bytesPerFrame;
@@ -81169,12 +82926,12 @@ MA_API ma_uint64 ma_dr_wav_write_pcm_frames(ma_dr_wav* pWav, ma_uint64 framesToW
MA_PRIVATE ma_uint64 ma_dr_wav_read_pcm_frames_s16__msadpcm(ma_dr_wav* pWav, ma_uint64 framesToRead, ma_int16* pBufferOut)
{
ma_uint64 totalFramesRead = 0;
- static ma_int32 adaptationTable[] = {
+ static const ma_int32 adaptationTable[] = {
230, 230, 230, 230, 307, 409, 512, 614,
768, 614, 512, 409, 307, 230, 230, 230
};
- static ma_int32 coeff1Table[] = { 256, 512, 0, 192, 240, 460, 392 };
- static ma_int32 coeff2Table[] = { 0, -256, 0, 64, 0, -208, -232 };
+ static const ma_int32 coeff1Table[] = { 256, 512, 0, 192, 240, 460, 392 };
+ static const ma_int32 coeff2Table[] = { 0, -256, 0, 64, 0, -208, -232 };
MA_DR_WAV_ASSERT(pWav != NULL);
MA_DR_WAV_ASSERT(framesToRead > 0);
while (pWav->readCursorInPCMFrames < pWav->totalPCMFrameCount) {
@@ -81307,11 +83064,11 @@ MA_PRIVATE ma_uint64 ma_dr_wav_read_pcm_frames_s16__ima(ma_dr_wav* pWav, ma_uint
{
ma_uint64 totalFramesRead = 0;
ma_uint32 iChannel;
- static ma_int32 indexTable[16] = {
+ static const ma_int32 indexTable[16] = {
-1, -1, -1, -1, 2, 4, 6, 8,
-1, -1, -1, -1, 2, 4, 6, 8
};
- static ma_int32 stepTable[89] = {
+ static const ma_int32 stepTable[89] = {
7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
@@ -81334,7 +83091,7 @@ MA_PRIVATE ma_uint64 ma_dr_wav_read_pcm_frames_s16__ima(ma_dr_wav* pWav, ma_uint
}
pWav->ima.bytesRemainingInBlock = pWav->fmt.blockAlign - sizeof(header);
if (header[2] >= ma_dr_wav_countof(stepTable)) {
- pWav->onSeek(pWav->pUserData, pWav->ima.bytesRemainingInBlock, ma_dr_wav_seek_origin_current);
+ pWav->onSeek(pWav->pUserData, pWav->ima.bytesRemainingInBlock, MA_DR_WAV_SEEK_CUR);
pWav->ima.bytesRemainingInBlock = 0;
return totalFramesRead;
}
@@ -81349,7 +83106,7 @@ MA_PRIVATE ma_uint64 ma_dr_wav_read_pcm_frames_s16__ima(ma_dr_wav* pWav, ma_uint
}
pWav->ima.bytesRemainingInBlock = pWav->fmt.blockAlign - sizeof(header);
if (header[2] >= ma_dr_wav_countof(stepTable) || header[6] >= ma_dr_wav_countof(stepTable)) {
- pWav->onSeek(pWav->pUserData, pWav->ima.bytesRemainingInBlock, ma_dr_wav_seek_origin_current);
+ pWav->onSeek(pWav->pUserData, pWav->ima.bytesRemainingInBlock, MA_DR_WAV_SEEK_CUR);
pWav->ima.bytesRemainingInBlock = 0;
return totalFramesRead;
}
@@ -81424,7 +83181,7 @@ MA_PRIVATE ma_uint64 ma_dr_wav_read_pcm_frames_s16__ima(ma_dr_wav* pWav, ma_uint
return totalFramesRead;
}
#ifndef MA_DR_WAV_NO_CONVERSION_API
-static unsigned short g_ma_dr_wavAlawTable[256] = {
+static const unsigned short ma_dr_wav_gAlawTable[256] = {
0xEA80, 0xEB80, 0xE880, 0xE980, 0xEE80, 0xEF80, 0xEC80, 0xED80, 0xE280, 0xE380, 0xE080, 0xE180, 0xE680, 0xE780, 0xE480, 0xE580,
0xF540, 0xF5C0, 0xF440, 0xF4C0, 0xF740, 0xF7C0, 0xF640, 0xF6C0, 0xF140, 0xF1C0, 0xF040, 0xF0C0, 0xF340, 0xF3C0, 0xF240, 0xF2C0,
0xAA00, 0xAE00, 0xA200, 0xA600, 0xBA00, 0xBE00, 0xB200, 0xB600, 0x8A00, 0x8E00, 0x8200, 0x8600, 0x9A00, 0x9E00, 0x9200, 0x9600,
@@ -81442,7 +83199,7 @@ static unsigned short g_ma_dr_wavAlawTable[256] = {
0x0560, 0x0520, 0x05E0, 0x05A0, 0x0460, 0x0420, 0x04E0, 0x04A0, 0x0760, 0x0720, 0x07E0, 0x07A0, 0x0660, 0x0620, 0x06E0, 0x06A0,
0x02B0, 0x0290, 0x02F0, 0x02D0, 0x0230, 0x0210, 0x0270, 0x0250, 0x03B0, 0x0390, 0x03F0, 0x03D0, 0x0330, 0x0310, 0x0370, 0x0350
};
-static unsigned short g_ma_dr_wavMulawTable[256] = {
+static const unsigned short ma_dr_wav_gMulawTable[256] = {
0x8284, 0x8684, 0x8A84, 0x8E84, 0x9284, 0x9684, 0x9A84, 0x9E84, 0xA284, 0xA684, 0xAA84, 0xAE84, 0xB284, 0xB684, 0xBA84, 0xBE84,
0xC184, 0xC384, 0xC584, 0xC784, 0xC984, 0xCB84, 0xCD84, 0xCF84, 0xD184, 0xD384, 0xD584, 0xD784, 0xD984, 0xDB84, 0xDD84, 0xDF84,
0xE104, 0xE204, 0xE304, 0xE404, 0xE504, 0xE604, 0xE704, 0xE804, 0xE904, 0xEA04, 0xEB04, 0xEC04, 0xED04, 0xEE04, 0xEF04, 0xF004,
@@ -81462,11 +83219,11 @@ static unsigned short g_ma_dr_wavMulawTable[256] = {
};
static MA_INLINE ma_int16 ma_dr_wav__alaw_to_s16(ma_uint8 sampleIn)
{
- return (short)g_ma_dr_wavAlawTable[sampleIn];
+ return (short)ma_dr_wav_gAlawTable[sampleIn];
}
static MA_INLINE ma_int16 ma_dr_wav__mulaw_to_s16(ma_uint8 sampleIn)
{
- return (short)g_ma_dr_wavMulawTable[sampleIn];
+ return (short)ma_dr_wav_gMulawTable[sampleIn];
}
MA_PRIVATE void ma_dr_wav__pcm_to_s16(ma_int16* pOut, const ma_uint8* pIn, size_t totalSampleCount, unsigned int bytesPerSample)
{
@@ -82625,7 +84382,7 @@ MA_PRIVATE ma_int32* ma_dr_wav__read_pcm_frames_and_close_s32(ma_dr_wav* pWav, u
}
return pSampleData;
}
-MA_API ma_int16* ma_dr_wav_open_and_read_pcm_frames_s16(ma_dr_wav_read_proc onRead, ma_dr_wav_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, ma_uint64* totalFrameCountOut, const ma_allocation_callbacks* pAllocationCallbacks)
+MA_API ma_int16* ma_dr_wav_open_and_read_pcm_frames_s16(ma_dr_wav_read_proc onRead, ma_dr_wav_seek_proc onSeek, ma_dr_wav_tell_proc onTell, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, ma_uint64* totalFrameCountOut, const ma_allocation_callbacks* pAllocationCallbacks)
{
ma_dr_wav wav;
if (channelsOut) {
@@ -82637,12 +84394,12 @@ MA_API ma_int16* ma_dr_wav_open_and_read_pcm_frames_s16(ma_dr_wav_read_proc onRe
if (totalFrameCountOut) {
*totalFrameCountOut = 0;
}
- if (!ma_dr_wav_init(&wav, onRead, onSeek, pUserData, pAllocationCallbacks)) {
+ if (!ma_dr_wav_init(&wav, onRead, onSeek, onTell, pUserData, pAllocationCallbacks)) {
return NULL;
}
return ma_dr_wav__read_pcm_frames_and_close_s16(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
}
-MA_API float* ma_dr_wav_open_and_read_pcm_frames_f32(ma_dr_wav_read_proc onRead, ma_dr_wav_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, ma_uint64* totalFrameCountOut, const ma_allocation_callbacks* pAllocationCallbacks)
+MA_API float* ma_dr_wav_open_and_read_pcm_frames_f32(ma_dr_wav_read_proc onRead, ma_dr_wav_seek_proc onSeek, ma_dr_wav_tell_proc onTell, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, ma_uint64* totalFrameCountOut, const ma_allocation_callbacks* pAllocationCallbacks)
{
ma_dr_wav wav;
if (channelsOut) {
@@ -82654,12 +84411,12 @@ MA_API float* ma_dr_wav_open_and_read_pcm_frames_f32(ma_dr_wav_read_proc onRead,
if (totalFrameCountOut) {
*totalFrameCountOut = 0;
}
- if (!ma_dr_wav_init(&wav, onRead, onSeek, pUserData, pAllocationCallbacks)) {
+ if (!ma_dr_wav_init(&wav, onRead, onSeek, onTell, pUserData, pAllocationCallbacks)) {
return NULL;
}
return ma_dr_wav__read_pcm_frames_and_close_f32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
}
-MA_API ma_int32* ma_dr_wav_open_and_read_pcm_frames_s32(ma_dr_wav_read_proc onRead, ma_dr_wav_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, ma_uint64* totalFrameCountOut, const ma_allocation_callbacks* pAllocationCallbacks)
+MA_API ma_int32* ma_dr_wav_open_and_read_pcm_frames_s32(ma_dr_wav_read_proc onRead, ma_dr_wav_seek_proc onSeek, ma_dr_wav_tell_proc onTell, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, ma_uint64* totalFrameCountOut, const ma_allocation_callbacks* pAllocationCallbacks)
{
ma_dr_wav wav;
if (channelsOut) {
@@ -82671,7 +84428,7 @@ MA_API ma_int32* ma_dr_wav_open_and_read_pcm_frames_s32(ma_dr_wav_read_proc onRe
if (totalFrameCountOut) {
*totalFrameCountOut = 0;
}
- if (!ma_dr_wav_init(&wav, onRead, onSeek, pUserData, pAllocationCallbacks)) {
+ if (!ma_dr_wav_init(&wav, onRead, onSeek, onTell, pUserData, pAllocationCallbacks)) {
return NULL;
}
return ma_dr_wav__read_pcm_frames_and_close_s32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
@@ -84106,23 +85863,23 @@ static ma_bool32 ma_dr_flac__seek_to_byte(ma_dr_flac_bs* bs, ma_uint64 offsetFro
MA_DR_FLAC_ASSERT(offsetFromStart > 0);
if (offsetFromStart > 0x7FFFFFFF) {
ma_uint64 bytesRemaining = offsetFromStart;
- if (!bs->onSeek(bs->pUserData, 0x7FFFFFFF, ma_dr_flac_seek_origin_start)) {
+ if (!bs->onSeek(bs->pUserData, 0x7FFFFFFF, MA_DR_FLAC_SEEK_SET)) {
return MA_FALSE;
}
bytesRemaining -= 0x7FFFFFFF;
while (bytesRemaining > 0x7FFFFFFF) {
- if (!bs->onSeek(bs->pUserData, 0x7FFFFFFF, ma_dr_flac_seek_origin_current)) {
+ if (!bs->onSeek(bs->pUserData, 0x7FFFFFFF, MA_DR_FLAC_SEEK_CUR)) {
return MA_FALSE;
}
bytesRemaining -= 0x7FFFFFFF;
}
if (bytesRemaining > 0) {
- if (!bs->onSeek(bs->pUserData, (int)bytesRemaining, ma_dr_flac_seek_origin_current)) {
+ if (!bs->onSeek(bs->pUserData, (int)bytesRemaining, MA_DR_FLAC_SEEK_CUR)) {
return MA_FALSE;
}
}
} else {
- if (!bs->onSeek(bs->pUserData, (int)offsetFromStart, ma_dr_flac_seek_origin_start)) {
+ if (!bs->onSeek(bs->pUserData, (int)offsetFromStart, MA_DR_FLAC_SEEK_SET)) {
return MA_FALSE;
}
}
@@ -86600,6 +88357,7 @@ typedef struct
{
ma_dr_flac_read_proc onRead;
ma_dr_flac_seek_proc onSeek;
+ ma_dr_flac_tell_proc onTell;
ma_dr_flac_meta_proc onMeta;
ma_dr_flac_container container;
void* pUserData;
@@ -86728,11 +88486,12 @@ static void ma_dr_flac__free_from_callbacks(void* p, const ma_allocation_callbac
pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData);
}
}
-static ma_bool32 ma_dr_flac__read_and_decode_metadata(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, ma_dr_flac_meta_proc onMeta, void* pUserData, void* pUserDataMD, ma_uint64* pFirstFramePos, ma_uint64* pSeektablePos, ma_uint32* pSeekpointCount, ma_allocation_callbacks* pAllocationCallbacks)
+static ma_bool32 ma_dr_flac__read_and_decode_metadata(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, ma_dr_flac_tell_proc onTell, ma_dr_flac_meta_proc onMeta, void* pUserData, void* pUserDataMD, ma_uint64* pFirstFramePos, ma_uint64* pSeektablePos, ma_uint32* pSeekpointCount, ma_allocation_callbacks* pAllocationCallbacks)
{
ma_uint64 runningFilePos = 42;
ma_uint64 seektablePos = 0;
ma_uint32 seektableSize = 0;
+ (void)onTell;
for (;;) {
ma_dr_flac_metadata metadata;
ma_uint8 isLastBlock = 0;
@@ -86990,7 +88749,7 @@ static ma_bool32 ma_dr_flac__read_and_decode_metadata(ma_dr_flac_read_proc onRea
{
if (onMeta) {
metadata.data.padding.unused = 0;
- if (!onSeek(pUserData, blockSize, ma_dr_flac_seek_origin_current)) {
+ if (!onSeek(pUserData, blockSize, MA_DR_FLAC_SEEK_CUR)) {
isLastBlock = MA_TRUE;
} else {
onMeta(pUserDataMD, &metadata);
@@ -87000,7 +88759,7 @@ static ma_bool32 ma_dr_flac__read_and_decode_metadata(ma_dr_flac_read_proc onRea
case MA_DR_FLAC_METADATA_BLOCK_TYPE_INVALID:
{
if (onMeta) {
- if (!onSeek(pUserData, blockSize, ma_dr_flac_seek_origin_current)) {
+ if (!onSeek(pUserData, blockSize, MA_DR_FLAC_SEEK_CUR)) {
isLastBlock = MA_TRUE;
}
}
@@ -87024,7 +88783,7 @@ static ma_bool32 ma_dr_flac__read_and_decode_metadata(ma_dr_flac_read_proc onRea
} break;
}
if (onMeta == NULL && blockSize > 0) {
- if (!onSeek(pUserData, blockSize, ma_dr_flac_seek_origin_current)) {
+ if (!onSeek(pUserData, blockSize, MA_DR_FLAC_SEEK_CUR)) {
isLastBlock = MA_TRUE;
}
}
@@ -87288,6 +89047,7 @@ typedef struct
{
ma_dr_flac_read_proc onRead;
ma_dr_flac_seek_proc onSeek;
+ ma_dr_flac_tell_proc onTell;
void* pUserData;
ma_uint64 currentBytePos;
ma_uint64 firstBytePos;
@@ -87306,29 +89066,29 @@ static size_t ma_dr_flac_oggbs__read_physical(ma_dr_flac_oggbs* oggbs, void* buf
}
static ma_bool32 ma_dr_flac_oggbs__seek_physical(ma_dr_flac_oggbs* oggbs, ma_uint64 offset, ma_dr_flac_seek_origin origin)
{
- if (origin == ma_dr_flac_seek_origin_start) {
+ if (origin == MA_DR_FLAC_SEEK_SET) {
if (offset <= 0x7FFFFFFF) {
- if (!oggbs->onSeek(oggbs->pUserData, (int)offset, ma_dr_flac_seek_origin_start)) {
+ if (!oggbs->onSeek(oggbs->pUserData, (int)offset, MA_DR_FLAC_SEEK_SET)) {
return MA_FALSE;
}
oggbs->currentBytePos = offset;
return MA_TRUE;
} else {
- if (!oggbs->onSeek(oggbs->pUserData, 0x7FFFFFFF, ma_dr_flac_seek_origin_start)) {
+ if (!oggbs->onSeek(oggbs->pUserData, 0x7FFFFFFF, MA_DR_FLAC_SEEK_SET)) {
return MA_FALSE;
}
oggbs->currentBytePos = offset;
- return ma_dr_flac_oggbs__seek_physical(oggbs, offset - 0x7FFFFFFF, ma_dr_flac_seek_origin_current);
+ return ma_dr_flac_oggbs__seek_physical(oggbs, offset - 0x7FFFFFFF, MA_DR_FLAC_SEEK_CUR);
}
} else {
while (offset > 0x7FFFFFFF) {
- if (!oggbs->onSeek(oggbs->pUserData, 0x7FFFFFFF, ma_dr_flac_seek_origin_current)) {
+ if (!oggbs->onSeek(oggbs->pUserData, 0x7FFFFFFF, MA_DR_FLAC_SEEK_CUR)) {
return MA_FALSE;
}
oggbs->currentBytePos += 0x7FFFFFFF;
offset -= 0x7FFFFFFF;
}
- if (!oggbs->onSeek(oggbs->pUserData, (int)offset, ma_dr_flac_seek_origin_current)) {
+ if (!oggbs->onSeek(oggbs->pUserData, (int)offset, MA_DR_FLAC_SEEK_CUR)) {
return MA_FALSE;
}
oggbs->currentBytePos += offset;
@@ -87354,7 +89114,7 @@ static ma_bool32 ma_dr_flac_oggbs__goto_next_page(ma_dr_flac_oggbs* oggbs, ma_dr
continue;
}
if (header.serialNumber != oggbs->serialNumber) {
- if (pageBodySize > 0 && !ma_dr_flac_oggbs__seek_physical(oggbs, pageBodySize, ma_dr_flac_seek_origin_current)) {
+ if (pageBodySize > 0 && !ma_dr_flac_oggbs__seek_physical(oggbs, pageBodySize, MA_DR_FLAC_SEEK_CUR)) {
return MA_FALSE;
}
continue;
@@ -87416,7 +89176,7 @@ static ma_bool32 ma_dr_flac_oggbs__seek_to_next_packet(ma_dr_flac_oggbs* oggbs)
}
bytesToEndOfPacketOrPage += segmentSize;
}
- ma_dr_flac_oggbs__seek_physical(oggbs, bytesToEndOfPacketOrPage, ma_dr_flac_seek_origin_current);
+ ma_dr_flac_oggbs__seek_physical(oggbs, bytesToEndOfPacketOrPage, MA_DR_FLAC_SEEK_CUR);
oggbs->bytesRemainingInPage -= bytesToEndOfPacketOrPage;
if (atEndOfPage) {
if (!ma_dr_flac_oggbs__goto_next_page(oggbs)) {
@@ -87469,36 +89229,44 @@ static ma_bool32 ma_dr_flac__on_seek_ogg(void* pUserData, int offset, ma_dr_flac
int bytesSeeked = 0;
MA_DR_FLAC_ASSERT(oggbs != NULL);
MA_DR_FLAC_ASSERT(offset >= 0);
- if (origin == ma_dr_flac_seek_origin_start) {
- if (!ma_dr_flac_oggbs__seek_physical(oggbs, (int)oggbs->firstBytePos, ma_dr_flac_seek_origin_start)) {
+ if (origin == MA_DR_FLAC_SEEK_SET) {
+ if (!ma_dr_flac_oggbs__seek_physical(oggbs, (int)oggbs->firstBytePos, MA_DR_FLAC_SEEK_SET)) {
return MA_FALSE;
}
if (!ma_dr_flac_oggbs__goto_next_page(oggbs, ma_dr_flac_ogg_fail_on_crc_mismatch)) {
return MA_FALSE;
}
- return ma_dr_flac__on_seek_ogg(pUserData, offset, ma_dr_flac_seek_origin_current);
- }
- MA_DR_FLAC_ASSERT(origin == ma_dr_flac_seek_origin_current);
- while (bytesSeeked < offset) {
- int bytesRemainingToSeek = offset - bytesSeeked;
- MA_DR_FLAC_ASSERT(bytesRemainingToSeek >= 0);
- if (oggbs->bytesRemainingInPage >= (size_t)bytesRemainingToSeek) {
- bytesSeeked += bytesRemainingToSeek;
- (void)bytesSeeked;
- oggbs->bytesRemainingInPage -= bytesRemainingToSeek;
- break;
- }
- if (oggbs->bytesRemainingInPage > 0) {
- bytesSeeked += (int)oggbs->bytesRemainingInPage;
- oggbs->bytesRemainingInPage = 0;
- }
- MA_DR_FLAC_ASSERT(bytesRemainingToSeek > 0);
- if (!ma_dr_flac_oggbs__goto_next_page(oggbs, ma_dr_flac_ogg_fail_on_crc_mismatch)) {
- return MA_FALSE;
+ return ma_dr_flac__on_seek_ogg(pUserData, offset, MA_DR_FLAC_SEEK_CUR);
+ } else if (origin == MA_DR_FLAC_SEEK_CUR) {
+ while (bytesSeeked < offset) {
+ int bytesRemainingToSeek = offset - bytesSeeked;
+ MA_DR_FLAC_ASSERT(bytesRemainingToSeek >= 0);
+ if (oggbs->bytesRemainingInPage >= (size_t)bytesRemainingToSeek) {
+ bytesSeeked += bytesRemainingToSeek;
+ (void)bytesSeeked;
+ oggbs->bytesRemainingInPage -= bytesRemainingToSeek;
+ break;
+ }
+ if (oggbs->bytesRemainingInPage > 0) {
+ bytesSeeked += (int)oggbs->bytesRemainingInPage;
+ oggbs->bytesRemainingInPage = 0;
+ }
+ MA_DR_FLAC_ASSERT(bytesRemainingToSeek > 0);
+ if (!ma_dr_flac_oggbs__goto_next_page(oggbs, ma_dr_flac_ogg_fail_on_crc_mismatch)) {
+ return MA_FALSE;
+ }
}
+ } else if (origin == MA_DR_FLAC_SEEK_END) {
+ return MA_FALSE;
}
return MA_TRUE;
}
+static ma_bool32 ma_dr_flac__on_tell_ogg(void* pUserData, ma_int64* pCursor)
+{
+ (void)pUserData;
+ (void)pCursor;
+ return MA_FALSE;
+}
static ma_bool32 ma_dr_flac_ogg__seek_to_pcm_frame(ma_dr_flac* pFlac, ma_uint64 pcmFrameIndex)
{
ma_dr_flac_oggbs* oggbs = (ma_dr_flac_oggbs*)pFlac->_oggbs;
@@ -87515,7 +89283,7 @@ static ma_bool32 ma_dr_flac_ogg__seek_to_pcm_frame(ma_dr_flac* pFlac, ma_uint64
runningGranulePosition = 0;
for (;;) {
if (!ma_dr_flac_oggbs__goto_next_page(oggbs, ma_dr_flac_ogg_recover_on_crc_mismatch)) {
- ma_dr_flac_oggbs__seek_physical(oggbs, originalBytePos, ma_dr_flac_seek_origin_start);
+ ma_dr_flac_oggbs__seek_physical(oggbs, originalBytePos, MA_DR_FLAC_SEEK_SET);
return MA_FALSE;
}
runningFrameBytePos = oggbs->currentBytePos - ma_dr_flac_ogg__get_page_header_size(&oggbs->currentPageHeader) - oggbs->pageDataSize;
@@ -87534,7 +89302,7 @@ static ma_bool32 ma_dr_flac_ogg__seek_to_pcm_frame(ma_dr_flac* pFlac, ma_uint64
}
}
}
- if (!ma_dr_flac_oggbs__seek_physical(oggbs, runningFrameBytePos, ma_dr_flac_seek_origin_start)) {
+ if (!ma_dr_flac_oggbs__seek_physical(oggbs, runningFrameBytePos, MA_DR_FLAC_SEEK_SET)) {
return MA_FALSE;
}
if (!ma_dr_flac_oggbs__goto_next_page(oggbs, ma_dr_flac_ogg_recover_on_crc_mismatch)) {
@@ -87629,7 +89397,7 @@ static ma_bool32 ma_dr_flac__init_private__ogg(ma_dr_flac_init_info* pInit, ma_d
if (mappingVersion[0] != 1) {
return MA_FALSE;
}
- if (!onSeek(pUserData, 2, ma_dr_flac_seek_origin_current)) {
+ if (!onSeek(pUserData, 2, MA_DR_FLAC_SEEK_CUR)) {
return MA_FALSE;
}
if (onRead(pUserData, sig, 4) != 4) {
@@ -87674,17 +89442,17 @@ static ma_bool32 ma_dr_flac__init_private__ogg(ma_dr_flac_init_info* pInit, ma_d
return MA_FALSE;
}
} else {
- if (!onSeek(pUserData, bytesRemainingInPage, ma_dr_flac_seek_origin_current)) {
+ if (!onSeek(pUserData, bytesRemainingInPage, MA_DR_FLAC_SEEK_CUR)) {
return MA_FALSE;
}
}
} else {
- if (!onSeek(pUserData, bytesRemainingInPage, ma_dr_flac_seek_origin_current)) {
+ if (!onSeek(pUserData, bytesRemainingInPage, MA_DR_FLAC_SEEK_CUR)) {
return MA_FALSE;
}
}
} else {
- if (!onSeek(pUserData, pageBodySize, ma_dr_flac_seek_origin_current)) {
+ if (!onSeek(pUserData, pageBodySize, MA_DR_FLAC_SEEK_CUR)) {
return MA_FALSE;
}
}
@@ -87698,7 +89466,7 @@ static ma_bool32 ma_dr_flac__init_private__ogg(ma_dr_flac_init_info* pInit, ma_d
return MA_TRUE;
}
#endif
-static ma_bool32 ma_dr_flac__init_private(ma_dr_flac_init_info* pInit, ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, ma_dr_flac_meta_proc onMeta, ma_dr_flac_container container, void* pUserData, void* pUserDataMD)
+static ma_bool32 ma_dr_flac__init_private(ma_dr_flac_init_info* pInit, ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, ma_dr_flac_tell_proc onTell, ma_dr_flac_meta_proc onMeta, ma_dr_flac_container container, void* pUserData, void* pUserDataMD)
{
ma_bool32 relaxed;
ma_uint8 id[4];
@@ -87708,12 +89476,14 @@ static ma_bool32 ma_dr_flac__init_private(ma_dr_flac_init_info* pInit, ma_dr_fla
MA_DR_FLAC_ZERO_MEMORY(pInit, sizeof(*pInit));
pInit->onRead = onRead;
pInit->onSeek = onSeek;
+ pInit->onTell = onTell;
pInit->onMeta = onMeta;
pInit->container = container;
pInit->pUserData = pUserData;
pInit->pUserDataMD = pUserDataMD;
pInit->bs.onRead = onRead;
pInit->bs.onSeek = onSeek;
+ pInit->bs.onTell = onTell;
pInit->bs.pUserData = pUserData;
ma_dr_flac__reset_cache(&pInit->bs);
relaxed = container != ma_dr_flac_container_unknown;
@@ -87736,7 +89506,7 @@ static ma_bool32 ma_dr_flac__init_private(ma_dr_flac_init_info* pInit, ma_dr_fla
if (flags & 0x10) {
headerSize += 10;
}
- if (!onSeek(pUserData, headerSize, ma_dr_flac_seek_origin_current)) {
+ if (!onSeek(pUserData, headerSize, MA_DR_FLAC_SEEK_CUR)) {
return MA_FALSE;
}
pInit->runningFilePos += headerSize;
@@ -87779,7 +89549,7 @@ static void ma_dr_flac__init_from_info(ma_dr_flac* pFlac, const ma_dr_flac_init_
pFlac->totalPCMFrameCount = pInit->totalPCMFrameCount;
pFlac->container = pInit->container;
}
-static ma_dr_flac* ma_dr_flac_open_with_metadata_private(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, ma_dr_flac_meta_proc onMeta, ma_dr_flac_container container, void* pUserData, void* pUserDataMD, const ma_allocation_callbacks* pAllocationCallbacks)
+static ma_dr_flac* ma_dr_flac_open_with_metadata_private(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, ma_dr_flac_tell_proc onTell, ma_dr_flac_meta_proc onMeta, ma_dr_flac_container container, void* pUserData, void* pUserDataMD, const ma_allocation_callbacks* pAllocationCallbacks)
{
ma_dr_flac_init_info init;
ma_uint32 allocationSize;
@@ -87794,7 +89564,7 @@ static ma_dr_flac* ma_dr_flac_open_with_metadata_private(ma_dr_flac_read_proc on
ma_allocation_callbacks allocationCallbacks;
ma_dr_flac* pFlac;
ma_dr_flac__init_cpu_caps();
- if (!ma_dr_flac__init_private(&init, onRead, onSeek, onMeta, container, pUserData, pUserDataMD)) {
+ if (!ma_dr_flac__init_private(&init, onRead, onSeek, onTell, onMeta, container, pUserData, pUserDataMD)) {
return NULL;
}
if (pAllocationCallbacks != NULL) {
@@ -87827,6 +89597,7 @@ static ma_dr_flac* ma_dr_flac_open_with_metadata_private(ma_dr_flac_read_proc on
MA_DR_FLAC_ZERO_MEMORY(pOggbs, sizeof(*pOggbs));
pOggbs->onRead = onRead;
pOggbs->onSeek = onSeek;
+ pOggbs->onTell = onTell;
pOggbs->pUserData = pUserData;
pOggbs->currentBytePos = init.oggFirstBytePos;
pOggbs->firstBytePos = init.oggFirstBytePos;
@@ -87841,15 +89612,17 @@ static ma_dr_flac* ma_dr_flac_open_with_metadata_private(ma_dr_flac_read_proc on
if (init.hasMetadataBlocks) {
ma_dr_flac_read_proc onReadOverride = onRead;
ma_dr_flac_seek_proc onSeekOverride = onSeek;
+ ma_dr_flac_tell_proc onTellOverride = onTell;
void* pUserDataOverride = pUserData;
#ifndef MA_DR_FLAC_NO_OGG
if (init.container == ma_dr_flac_container_ogg) {
onReadOverride = ma_dr_flac__on_read_ogg;
onSeekOverride = ma_dr_flac__on_seek_ogg;
+ onTellOverride = ma_dr_flac__on_tell_ogg;
pUserDataOverride = (void*)pOggbs;
}
#endif
- if (!ma_dr_flac__read_and_decode_metadata(onReadOverride, onSeekOverride, onMeta, pUserDataOverride, pUserDataMD, &firstFramePos, &seektablePos, &seekpointCount, &allocationCallbacks)) {
+ if (!ma_dr_flac__read_and_decode_metadata(onReadOverride, onSeekOverride, onTellOverride, onMeta, pUserDataOverride, pUserDataMD, &firstFramePos, &seektablePos, &seekpointCount, &allocationCallbacks)) {
#ifndef MA_DR_FLAC_NO_OGG
ma_dr_flac__free_from_callbacks(pOggbs, &allocationCallbacks);
#endif
@@ -87875,6 +89648,7 @@ static ma_dr_flac* ma_dr_flac_open_with_metadata_private(ma_dr_flac_read_proc on
pOggbs = NULL;
pFlac->bs.onRead = ma_dr_flac__on_read_ogg;
pFlac->bs.onSeek = ma_dr_flac__on_seek_ogg;
+ pFlac->bs.onTell = ma_dr_flac__on_tell_ogg;
pFlac->bs.pUserData = (void*)pInternalOggbs;
pFlac->_oggbs = (void*)pInternalOggbs;
}
@@ -87894,7 +89668,7 @@ static ma_dr_flac* ma_dr_flac_open_with_metadata_private(ma_dr_flac_read_proc on
pFlac->pSeekpoints = (ma_dr_flac_seekpoint*)((ma_uint8*)pFlac->pDecodedSamples + decodedSamplesAllocationSize);
MA_DR_FLAC_ASSERT(pFlac->bs.onSeek != NULL);
MA_DR_FLAC_ASSERT(pFlac->bs.onRead != NULL);
- if (pFlac->bs.onSeek(pFlac->bs.pUserData, (int)seektablePos, ma_dr_flac_seek_origin_start)) {
+ if (pFlac->bs.onSeek(pFlac->bs.pUserData, (int)seektablePos, MA_DR_FLAC_SEEK_SET)) {
ma_uint32 iSeekpoint;
for (iSeekpoint = 0; iSeekpoint < seekpointCount; iSeekpoint += 1) {
if (pFlac->bs.onRead(pFlac->bs.pUserData, pFlac->pSeekpoints + iSeekpoint, MA_DR_FLAC_SEEKPOINT_SIZE_IN_BYTES) == MA_DR_FLAC_SEEKPOINT_SIZE_IN_BYTES) {
@@ -87907,7 +89681,7 @@ static ma_dr_flac* ma_dr_flac_open_with_metadata_private(ma_dr_flac_read_proc on
break;
}
}
- if (!pFlac->bs.onSeek(pFlac->bs.pUserData, (int)pFlac->firstFLACFramePosInBytes, ma_dr_flac_seek_origin_start)) {
+ if (!pFlac->bs.onSeek(pFlac->bs.pUserData, (int)pFlac->firstFLACFramePosInBytes, MA_DR_FLAC_SEEK_SET)) {
ma_dr_flac__free_from_callbacks(pFlac, &allocationCallbacks);
return NULL;
}
@@ -87950,8 +89724,31 @@ static size_t ma_dr_flac__on_read_stdio(void* pUserData, void* bufferOut, size_t
}
static ma_bool32 ma_dr_flac__on_seek_stdio(void* pUserData, int offset, ma_dr_flac_seek_origin origin)
{
- MA_DR_FLAC_ASSERT(offset >= 0);
- return fseek((FILE*)pUserData, offset, (origin == ma_dr_flac_seek_origin_current) ? SEEK_CUR : SEEK_SET) == 0;
+ int whence = SEEK_SET;
+ if (origin == MA_DR_FLAC_SEEK_CUR) {
+ whence = SEEK_CUR;
+ } else if (origin == MA_DR_FLAC_SEEK_END) {
+ whence = SEEK_END;
+ }
+ return fseek((FILE*)pUserData, offset, whence) == 0;
+}
+static ma_bool32 ma_dr_flac__on_tell_stdio(void* pUserData, ma_int64* pCursor)
+{
+ FILE* pFileStdio = (FILE*)pUserData;
+ ma_int64 result;
+ MA_DR_FLAC_ASSERT(pFileStdio != NULL);
+ MA_DR_FLAC_ASSERT(pCursor != NULL);
+#if defined(_WIN32) && !defined(NXDK)
+ #if defined(_MSC_VER) && _MSC_VER > 1200
+ result = _ftelli64(pFileStdio);
+ #else
+ result = ftell(pFileStdio);
+ #endif
+#else
+ result = ftell(pFileStdio);
+#endif
+ *pCursor = result;
+ return MA_TRUE;
}
MA_API ma_dr_flac* ma_dr_flac_open_file(const char* pFileName, const ma_allocation_callbacks* pAllocationCallbacks)
{
@@ -87960,7 +89757,7 @@ MA_API ma_dr_flac* ma_dr_flac_open_file(const char* pFileName, const ma_allocati
if (ma_fopen(&pFile, pFileName, "rb") != MA_SUCCESS) {
return NULL;
}
- pFlac = ma_dr_flac_open(ma_dr_flac__on_read_stdio, ma_dr_flac__on_seek_stdio, (void*)pFile, pAllocationCallbacks);
+ pFlac = ma_dr_flac_open(ma_dr_flac__on_read_stdio, ma_dr_flac__on_seek_stdio, ma_dr_flac__on_tell_stdio, (void*)pFile, pAllocationCallbacks);
if (pFlac == NULL) {
fclose(pFile);
return NULL;
@@ -87975,7 +89772,7 @@ MA_API ma_dr_flac* ma_dr_flac_open_file_w(const wchar_t* pFileName, const ma_all
if (ma_wfopen(&pFile, pFileName, L"rb", pAllocationCallbacks) != MA_SUCCESS) {
return NULL;
}
- pFlac = ma_dr_flac_open(ma_dr_flac__on_read_stdio, ma_dr_flac__on_seek_stdio, (void*)pFile, pAllocationCallbacks);
+ pFlac = ma_dr_flac_open(ma_dr_flac__on_read_stdio, ma_dr_flac__on_seek_stdio, ma_dr_flac__on_tell_stdio, (void*)pFile, pAllocationCallbacks);
if (pFlac == NULL) {
fclose(pFile);
return NULL;
@@ -87990,7 +89787,7 @@ MA_API ma_dr_flac* ma_dr_flac_open_file_with_metadata(const char* pFileName, ma_
if (ma_fopen(&pFile, pFileName, "rb") != MA_SUCCESS) {
return NULL;
}
- pFlac = ma_dr_flac_open_with_metadata_private(ma_dr_flac__on_read_stdio, ma_dr_flac__on_seek_stdio, onMeta, ma_dr_flac_container_unknown, (void*)pFile, pUserData, pAllocationCallbacks);
+ pFlac = ma_dr_flac_open_with_metadata_private(ma_dr_flac__on_read_stdio, ma_dr_flac__on_seek_stdio, ma_dr_flac__on_tell_stdio, onMeta, ma_dr_flac_container_unknown, (void*)pFile, pUserData, pAllocationCallbacks);
if (pFlac == NULL) {
fclose(pFile);
return pFlac;
@@ -88005,7 +89802,7 @@ MA_API ma_dr_flac* ma_dr_flac_open_file_with_metadata_w(const wchar_t* pFileName
if (ma_wfopen(&pFile, pFileName, L"rb", pAllocationCallbacks) != MA_SUCCESS) {
return NULL;
}
- pFlac = ma_dr_flac_open_with_metadata_private(ma_dr_flac__on_read_stdio, ma_dr_flac__on_seek_stdio, onMeta, ma_dr_flac_container_unknown, (void*)pFile, pUserData, pAllocationCallbacks);
+ pFlac = ma_dr_flac_open_with_metadata_private(ma_dr_flac__on_read_stdio, ma_dr_flac__on_seek_stdio, ma_dr_flac__on_tell_stdio, onMeta, ma_dr_flac_container_unknown, (void*)pFile, pUserData, pAllocationCallbacks);
if (pFlac == NULL) {
fclose(pFile);
return pFlac;
@@ -88033,24 +89830,35 @@ static size_t ma_dr_flac__on_read_memory(void* pUserData, void* bufferOut, size_
static ma_bool32 ma_dr_flac__on_seek_memory(void* pUserData, int offset, ma_dr_flac_seek_origin origin)
{
ma_dr_flac__memory_stream* memoryStream = (ma_dr_flac__memory_stream*)pUserData;
+ ma_int64 newCursor;
MA_DR_FLAC_ASSERT(memoryStream != NULL);
- MA_DR_FLAC_ASSERT(offset >= 0);
- if (offset > (ma_int64)memoryStream->dataSize) {
+ newCursor = memoryStream->currentReadPos;
+ if (origin == MA_DR_FLAC_SEEK_SET) {
+ newCursor = 0;
+ } else if (origin == MA_DR_FLAC_SEEK_CUR) {
+ newCursor = (ma_int64)memoryStream->currentReadPos;
+ } else if (origin == MA_DR_FLAC_SEEK_END) {
+ newCursor = (ma_int64)memoryStream->dataSize;
+ } else {
+ MA_DR_FLAC_ASSERT(!"Invalid seek origin");
return MA_FALSE;
}
- if (origin == ma_dr_flac_seek_origin_current) {
- if (memoryStream->currentReadPos + offset <= memoryStream->dataSize) {
- memoryStream->currentReadPos += offset;
- } else {
- return MA_FALSE;
- }
- } else {
- if ((ma_uint32)offset <= memoryStream->dataSize) {
- memoryStream->currentReadPos = offset;
- } else {
- return MA_FALSE;
- }
+ newCursor += offset;
+ if (newCursor < 0) {
+ return MA_FALSE;
}
+ if ((size_t)newCursor > memoryStream->dataSize) {
+ return MA_FALSE;
+ }
+ memoryStream->currentReadPos = (size_t)newCursor;
+ return MA_TRUE;
+}
+static ma_bool32 ma_dr_flac__on_tell_memory(void* pUserData, ma_int64* pCursor)
+{
+ ma_dr_flac__memory_stream* memoryStream = (ma_dr_flac__memory_stream*)pUserData;
+ MA_DR_FLAC_ASSERT(memoryStream != NULL);
+ MA_DR_FLAC_ASSERT(pCursor != NULL);
+ *pCursor = (ma_int64)memoryStream->currentReadPos;
return MA_TRUE;
}
MA_API ma_dr_flac* ma_dr_flac_open_memory(const void* pData, size_t dataSize, const ma_allocation_callbacks* pAllocationCallbacks)
@@ -88060,7 +89868,7 @@ MA_API ma_dr_flac* ma_dr_flac_open_memory(const void* pData, size_t dataSize, co
memoryStream.data = (const ma_uint8*)pData;
memoryStream.dataSize = dataSize;
memoryStream.currentReadPos = 0;
- pFlac = ma_dr_flac_open(ma_dr_flac__on_read_memory, ma_dr_flac__on_seek_memory, &memoryStream, pAllocationCallbacks);
+ pFlac = ma_dr_flac_open(ma_dr_flac__on_read_memory, ma_dr_flac__on_seek_memory, ma_dr_flac__on_tell_memory, &memoryStream, pAllocationCallbacks);
if (pFlac == NULL) {
return NULL;
}
@@ -88085,7 +89893,7 @@ MA_API ma_dr_flac* ma_dr_flac_open_memory_with_metadata(const void* pData, size_
memoryStream.data = (const ma_uint8*)pData;
memoryStream.dataSize = dataSize;
memoryStream.currentReadPos = 0;
- pFlac = ma_dr_flac_open_with_metadata_private(ma_dr_flac__on_read_memory, ma_dr_flac__on_seek_memory, onMeta, ma_dr_flac_container_unknown, &memoryStream, pUserData, pAllocationCallbacks);
+ pFlac = ma_dr_flac_open_with_metadata_private(ma_dr_flac__on_read_memory, ma_dr_flac__on_seek_memory, ma_dr_flac__on_tell_memory, onMeta, ma_dr_flac_container_unknown, &memoryStream, pUserData, pAllocationCallbacks);
if (pFlac == NULL) {
return NULL;
}
@@ -88103,21 +89911,21 @@ MA_API ma_dr_flac* ma_dr_flac_open_memory_with_metadata(const void* pData, size_
}
return pFlac;
}
-MA_API ma_dr_flac* ma_dr_flac_open(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks)
+MA_API ma_dr_flac* ma_dr_flac_open(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, ma_dr_flac_tell_proc onTell, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks)
{
- return ma_dr_flac_open_with_metadata_private(onRead, onSeek, NULL, ma_dr_flac_container_unknown, pUserData, pUserData, pAllocationCallbacks);
+ return ma_dr_flac_open_with_metadata_private(onRead, onSeek, onTell, NULL, ma_dr_flac_container_unknown, pUserData, pUserData, pAllocationCallbacks);
}
-MA_API ma_dr_flac* ma_dr_flac_open_relaxed(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, ma_dr_flac_container container, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks)
+MA_API ma_dr_flac* ma_dr_flac_open_relaxed(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, ma_dr_flac_tell_proc onTell, ma_dr_flac_container container, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks)
{
- return ma_dr_flac_open_with_metadata_private(onRead, onSeek, NULL, container, pUserData, pUserData, pAllocationCallbacks);
+ return ma_dr_flac_open_with_metadata_private(onRead, onSeek, onTell, NULL, container, pUserData, pUserData, pAllocationCallbacks);
}
-MA_API ma_dr_flac* ma_dr_flac_open_with_metadata(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, ma_dr_flac_meta_proc onMeta, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks)
+MA_API ma_dr_flac* ma_dr_flac_open_with_metadata(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, ma_dr_flac_tell_proc onTell, ma_dr_flac_meta_proc onMeta, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks)
{
- return ma_dr_flac_open_with_metadata_private(onRead, onSeek, onMeta, ma_dr_flac_container_unknown, pUserData, pUserData, pAllocationCallbacks);
+ return ma_dr_flac_open_with_metadata_private(onRead, onSeek, onTell, onMeta, ma_dr_flac_container_unknown, pUserData, pUserData, pAllocationCallbacks);
}
-MA_API ma_dr_flac* ma_dr_flac_open_with_metadata_relaxed(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, ma_dr_flac_meta_proc onMeta, ma_dr_flac_container container, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks)
+MA_API ma_dr_flac* ma_dr_flac_open_with_metadata_relaxed(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, ma_dr_flac_tell_proc onTell, ma_dr_flac_meta_proc onMeta, ma_dr_flac_container container, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks)
{
- return ma_dr_flac_open_with_metadata_private(onRead, onSeek, onMeta, container, pUserData, pUserData, pAllocationCallbacks);
+ return ma_dr_flac_open_with_metadata_private(onRead, onSeek, onTell, onMeta, container, pUserData, pUserData, pAllocationCallbacks);
}
MA_API void ma_dr_flac_close(ma_dr_flac* pFlac)
{
@@ -90410,7 +92218,7 @@ on_error:
MA_DR_FLAC_DEFINE_FULL_READ_AND_CLOSE(s32, ma_int32)
MA_DR_FLAC_DEFINE_FULL_READ_AND_CLOSE(s16, ma_int16)
MA_DR_FLAC_DEFINE_FULL_READ_AND_CLOSE(f32, float)
-MA_API ma_int32* ma_dr_flac_open_and_read_pcm_frames_s32(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, ma_uint64* totalPCMFrameCountOut, const ma_allocation_callbacks* pAllocationCallbacks)
+MA_API ma_int32* ma_dr_flac_open_and_read_pcm_frames_s32(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, ma_dr_flac_tell_proc onTell, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, ma_uint64* totalPCMFrameCountOut, const ma_allocation_callbacks* pAllocationCallbacks)
{
ma_dr_flac* pFlac;
if (channelsOut) {
@@ -90422,13 +92230,13 @@ MA_API ma_int32* ma_dr_flac_open_and_read_pcm_frames_s32(ma_dr_flac_read_proc on
if (totalPCMFrameCountOut) {
*totalPCMFrameCountOut = 0;
}
- pFlac = ma_dr_flac_open(onRead, onSeek, pUserData, pAllocationCallbacks);
+ pFlac = ma_dr_flac_open(onRead, onSeek, onTell, pUserData, pAllocationCallbacks);
if (pFlac == NULL) {
return NULL;
}
return ma_dr_flac__full_read_and_close_s32(pFlac, channelsOut, sampleRateOut, totalPCMFrameCountOut);
}
-MA_API ma_int16* ma_dr_flac_open_and_read_pcm_frames_s16(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, ma_uint64* totalPCMFrameCountOut, const ma_allocation_callbacks* pAllocationCallbacks)
+MA_API ma_int16* ma_dr_flac_open_and_read_pcm_frames_s16(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, ma_dr_flac_tell_proc onTell, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, ma_uint64* totalPCMFrameCountOut, const ma_allocation_callbacks* pAllocationCallbacks)
{
ma_dr_flac* pFlac;
if (channelsOut) {
@@ -90440,13 +92248,13 @@ MA_API ma_int16* ma_dr_flac_open_and_read_pcm_frames_s16(ma_dr_flac_read_proc on
if (totalPCMFrameCountOut) {
*totalPCMFrameCountOut = 0;
}
- pFlac = ma_dr_flac_open(onRead, onSeek, pUserData, pAllocationCallbacks);
+ pFlac = ma_dr_flac_open(onRead, onSeek, onTell, pUserData, pAllocationCallbacks);
if (pFlac == NULL) {
return NULL;
}
return ma_dr_flac__full_read_and_close_s16(pFlac, channelsOut, sampleRateOut, totalPCMFrameCountOut);
}
-MA_API float* ma_dr_flac_open_and_read_pcm_frames_f32(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, ma_uint64* totalPCMFrameCountOut, const ma_allocation_callbacks* pAllocationCallbacks)
+MA_API float* ma_dr_flac_open_and_read_pcm_frames_f32(ma_dr_flac_read_proc onRead, ma_dr_flac_seek_proc onSeek, ma_dr_flac_tell_proc onTell, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, ma_uint64* totalPCMFrameCountOut, const ma_allocation_callbacks* pAllocationCallbacks)
{
ma_dr_flac* pFlac;
if (channelsOut) {
@@ -90458,7 +92266,7 @@ MA_API float* ma_dr_flac_open_and_read_pcm_frames_f32(ma_dr_flac_read_proc onRea
if (totalPCMFrameCountOut) {
*totalPCMFrameCountOut = 0;
}
- pFlac = ma_dr_flac_open(onRead, onSeek, pUserData, pAllocationCallbacks);
+ pFlac = ma_dr_flac_open(onRead, onSeek, onTell, pUserData, pAllocationCallbacks);
if (pFlac == NULL) {
return NULL;
}
@@ -91262,6 +93070,10 @@ static float ma_dr_mp3_L3_ldexp_q2(float y, int exp_q2)
} while ((exp_q2 -= e) > 0);
return y;
}
+#if (defined(__GNUC__) && (__GNUC__ >= 14)) && !defined(__clang__)
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wstringop-overflow"
+#endif
static void ma_dr_mp3_L3_decode_scalefactors(const ma_uint8 *hdr, ma_uint8 *ist_pos, ma_dr_mp3_bs *bs, const ma_dr_mp3_L3_gr_info *gr, float *scf, int ch)
{
static const ma_uint8 g_scf_partitions[3][28] = {
@@ -91320,7 +93132,10 @@ static void ma_dr_mp3_L3_decode_scalefactors(const ma_uint8 *hdr, ma_uint8 *ist_
scf[i] = ma_dr_mp3_L3_ldexp_q2(gain, iscf[i] << scf_shift);
}
}
-static const float g_ma_dr_mp3_pow43[129 + 16] = {
+#if (defined(__GNUC__) && (__GNUC__ >= 14)) && !defined(__clang__)
+ #pragma GCC diagnostic pop
+#endif
+static const float ma_dr_mp3_g_pow43[129 + 16] = {
0,-1,-2.519842f,-4.326749f,-6.349604f,-8.549880f,-10.902724f,-13.390518f,-16.000000f,-18.720754f,-21.544347f,-24.463781f,-27.473142f,-30.567351f,-33.741992f,-36.993181f,
0,1,2.519842f,4.326749f,6.349604f,8.549880f,10.902724f,13.390518f,16.000000f,18.720754f,21.544347f,24.463781f,27.473142f,30.567351f,33.741992f,36.993181f,40.317474f,43.711787f,47.173345f,50.699631f,54.288352f,57.937408f,61.644865f,65.408941f,69.227979f,73.100443f,77.024898f,81.000000f,85.024491f,89.097188f,93.216975f,97.382800f,101.593667f,105.848633f,110.146801f,114.487321f,118.869381f,123.292209f,127.755065f,132.257246f,136.798076f,141.376907f,145.993119f,150.646117f,155.335327f,160.060199f,164.820202f,169.614826f,174.443577f,179.305980f,184.201575f,189.129918f,194.090580f,199.083145f,204.107210f,209.162385f,214.248292f,219.364564f,224.510845f,229.686789f,234.892058f,240.126328f,245.389280f,250.680604f,256.000000f,261.347174f,266.721841f,272.123723f,277.552547f,283.008049f,288.489971f,293.998060f,299.532071f,305.091761f,310.676898f,316.287249f,321.922592f,327.582707f,333.267377f,338.976394f,344.709550f,350.466646f,356.247482f,362.051866f,367.879608f,373.730522f,379.604427f,385.501143f,391.420496f,397.362314f,403.326427f,409.312672f,415.320884f,421.350905f,427.402579f,433.475750f,439.570269f,445.685987f,451.822757f,457.980436f,464.158883f,470.357960f,476.577530f,482.817459f,489.077615f,495.357868f,501.658090f,507.978156f,514.317941f,520.677324f,527.056184f,533.454404f,539.871867f,546.308458f,552.764065f,559.238575f,565.731879f,572.243870f,578.774440f,585.323483f,591.890898f,598.476581f,605.080431f,611.702349f,618.342238f,625.000000f,631.675540f,638.368763f,645.079578f
};
@@ -91330,7 +93145,7 @@ static float ma_dr_mp3_L3_pow_43(int x)
int sign, mult = 256;
if (x < 129)
{
- return g_ma_dr_mp3_pow43[16 + x];
+ return ma_dr_mp3_g_pow43[16 + x];
}
if (x < 1024)
{
@@ -91339,7 +93154,7 @@ static float ma_dr_mp3_L3_pow_43(int x)
}
sign = 2*x & 64;
frac = (float)((x & 63) - sign) / ((x & ~63) + sign);
- return g_ma_dr_mp3_pow43[16 + ((x + sign) >> 6)]*(1.f + frac*((4.f/3) + frac*(2.f/9)))*mult;
+ return ma_dr_mp3_g_pow43[16 + ((x + sign) >> 6)]*(1.f + frac*((4.f/3) + frac*(2.f/9)))*mult;
}
static void ma_dr_mp3_L3_huffman(float *dst, ma_dr_mp3_bs *bs, const ma_dr_mp3_L3_gr_info *gr_info, const float *scf, int layer3gr_limit)
{
@@ -91409,7 +93224,7 @@ static void ma_dr_mp3_L3_huffman(float *dst, ma_dr_mp3_bs *bs, const ma_dr_mp3_L
*dst = one*ma_dr_mp3_L3_pow_43(lsb)*((ma_int32)bs_cache < 0 ? -1: 1);
} else
{
- *dst = g_ma_dr_mp3_pow43[16 + lsb - 16*(bs_cache >> 31)]*one;
+ *dst = ma_dr_mp3_g_pow43[16 + lsb - 16*(bs_cache >> 31)]*one;
}
MA_DR_MP3_FLUSH_BITS(lsb ? 1 : 0);
}
@@ -91437,7 +93252,7 @@ static void ma_dr_mp3_L3_huffman(float *dst, ma_dr_mp3_bs *bs, const ma_dr_mp3_L
for (j = 0; j < 2; j++, dst++, leaf >>= 4)
{
int lsb = leaf & 0x0F;
- *dst = g_ma_dr_mp3_pow43[16 + lsb - 16*(bs_cache >> 31)]*one;
+ *dst = ma_dr_mp3_g_pow43[16 + lsb - 16*(bs_cache >> 31)]*one;
MA_DR_MP3_FLUSH_BITS(lsb ? 1 : 0);
}
MA_DR_MP3_CHECK_BITS;
@@ -92268,7 +94083,7 @@ MA_API int ma_dr_mp3dec_decode_frame(ma_dr_mp3dec *dec, const ma_uint8 *mp3, int
MA_DR_MP3_COPY_MEMORY(dec->header, hdr, MA_DR_MP3_HDR_SIZE);
info->frame_bytes = i + frame_size;
info->channels = MA_DR_MP3_HDR_IS_MONO(hdr) ? 1 : 2;
- info->hz = ma_dr_mp3_hdr_sample_rate_hz(hdr);
+ info->sample_rate = ma_dr_mp3_hdr_sample_rate_hz(hdr);
info->layer = 4 - MA_DR_MP3_HDR_GET_LAYER(hdr);
info->bitrate_kbps = ma_dr_mp3_hdr_bitrate_kbps(hdr);
ma_dr_mp3_bs_init(bs_frame, hdr + MA_DR_MP3_HDR_SIZE, frame_size - MA_DR_MP3_HDR_SIZE);
@@ -92491,19 +94306,41 @@ static ma_allocation_callbacks ma_dr_mp3_copy_allocation_callbacks_or_defaults(c
}
static size_t ma_dr_mp3__on_read(ma_dr_mp3* pMP3, void* pBufferOut, size_t bytesToRead)
{
- size_t bytesRead = pMP3->onRead(pMP3->pUserData, pBufferOut, bytesToRead);
+ size_t bytesRead;
+ MA_DR_MP3_ASSERT(pMP3 != NULL);
+ MA_DR_MP3_ASSERT(pMP3->onRead != NULL);
+ if (bytesToRead == 0) {
+ return 0;
+ }
+ bytesRead = pMP3->onRead(pMP3->pUserData, pBufferOut, bytesToRead);
pMP3->streamCursor += bytesRead;
return bytesRead;
}
+static size_t ma_dr_mp3__on_read_clamped(ma_dr_mp3* pMP3, void* pBufferOut, size_t bytesToRead)
+{
+ MA_DR_MP3_ASSERT(pMP3 != NULL);
+ MA_DR_MP3_ASSERT(pMP3->onRead != NULL);
+ if (pMP3->streamLength == MA_UINT64_MAX) {
+ return ma_dr_mp3__on_read(pMP3, pBufferOut, bytesToRead);
+ } else {
+ ma_uint64 bytesRemaining;
+ bytesRemaining = (pMP3->streamLength - pMP3->streamCursor);
+ if (bytesToRead > bytesRemaining) {
+ bytesToRead = (size_t)bytesRemaining;
+ }
+ return ma_dr_mp3__on_read(pMP3, pBufferOut, bytesToRead);
+ }
+}
static ma_bool32 ma_dr_mp3__on_seek(ma_dr_mp3* pMP3, int offset, ma_dr_mp3_seek_origin origin)
{
MA_DR_MP3_ASSERT(offset >= 0);
+ MA_DR_MP3_ASSERT(origin == MA_DR_MP3_SEEK_SET || origin == MA_DR_MP3_SEEK_CUR);
if (!pMP3->onSeek(pMP3->pUserData, offset, origin)) {
return MA_FALSE;
}
- if (origin == ma_dr_mp3_seek_origin_start) {
+ if (origin == MA_DR_MP3_SEEK_SET) {
pMP3->streamCursor = (ma_uint64)offset;
- } else {
+ } else{
pMP3->streamCursor += offset;
}
return MA_TRUE;
@@ -92513,18 +94350,18 @@ static ma_bool32 ma_dr_mp3__on_seek_64(ma_dr_mp3* pMP3, ma_uint64 offset, ma_dr_
if (offset <= 0x7FFFFFFF) {
return ma_dr_mp3__on_seek(pMP3, (int)offset, origin);
}
- if (!ma_dr_mp3__on_seek(pMP3, 0x7FFFFFFF, ma_dr_mp3_seek_origin_start)) {
+ if (!ma_dr_mp3__on_seek(pMP3, 0x7FFFFFFF, MA_DR_MP3_SEEK_SET)) {
return MA_FALSE;
}
offset -= 0x7FFFFFFF;
while (offset > 0) {
if (offset <= 0x7FFFFFFF) {
- if (!ma_dr_mp3__on_seek(pMP3, (int)offset, ma_dr_mp3_seek_origin_current)) {
+ if (!ma_dr_mp3__on_seek(pMP3, (int)offset, MA_DR_MP3_SEEK_CUR)) {
return MA_FALSE;
}
offset = 0;
} else {
- if (!ma_dr_mp3__on_seek(pMP3, 0x7FFFFFFF, ma_dr_mp3_seek_origin_current)) {
+ if (!ma_dr_mp3__on_seek(pMP3, 0x7FFFFFFF, MA_DR_MP3_SEEK_CUR)) {
return MA_FALSE;
}
offset -= 0x7FFFFFFF;
@@ -92532,7 +94369,18 @@ static ma_bool32 ma_dr_mp3__on_seek_64(ma_dr_mp3* pMP3, ma_uint64 offset, ma_dr_
}
return MA_TRUE;
}
-static ma_uint32 ma_dr_mp3_decode_next_frame_ex__callbacks(ma_dr_mp3* pMP3, ma_dr_mp3d_sample_t* pPCMFrames)
+static void ma_dr_mp3__on_meta(ma_dr_mp3* pMP3, ma_dr_mp3_metadata_type type, const void* pRawData, size_t rawDataSize)
+{
+ if (pMP3->onMeta) {
+ ma_dr_mp3_metadata metadata;
+ MA_DR_MP3_ZERO_OBJECT(&metadata);
+ metadata.type = type;
+ metadata.pRawData = pRawData;
+ metadata.rawDataSize = rawDataSize;
+ pMP3->onMeta(pMP3->pUserDataMeta, &metadata);
+ }
+}
+static ma_uint32 ma_dr_mp3_decode_next_frame_ex__callbacks(ma_dr_mp3* pMP3, ma_dr_mp3d_sample_t* pPCMFrames, ma_dr_mp3dec_frame_info* pMP3FrameInfo, const ma_uint8** ppMP3FrameData)
{
ma_uint32 pcmFramesRead = 0;
MA_DR_MP3_ASSERT(pMP3 != NULL);
@@ -92559,7 +94407,7 @@ static ma_uint32 ma_dr_mp3_decode_next_frame_ex__callbacks(ma_dr_mp3* pMP3, ma_d
pMP3->pData = pNewData;
pMP3->dataCapacity = newDataCap;
}
- bytesRead = ma_dr_mp3__on_read(pMP3, pMP3->pData + pMP3->dataSize, (pMP3->dataCapacity - pMP3->dataSize));
+ bytesRead = ma_dr_mp3__on_read_clamped(pMP3, pMP3->pData + pMP3->dataSize, (pMP3->dataCapacity - pMP3->dataSize));
if (bytesRead == 0) {
if (pMP3->dataSize == 0) {
pMP3->atEnd = MA_TRUE;
@@ -92578,16 +94426,20 @@ static ma_uint32 ma_dr_mp3_decode_next_frame_ex__callbacks(ma_dr_mp3* pMP3, ma_d
return 0;
}
pcmFramesRead = ma_dr_mp3dec_decode_frame(&pMP3->decoder, pMP3->pData + pMP3->dataConsumed, (int)pMP3->dataSize, pPCMFrames, &info);
- if (info.frame_bytes > 0) {
- pMP3->dataConsumed += (size_t)info.frame_bytes;
- pMP3->dataSize -= (size_t)info.frame_bytes;
- }
+ pMP3->dataConsumed += (size_t)info.frame_bytes;
+ pMP3->dataSize -= (size_t)info.frame_bytes;
if (pcmFramesRead > 0) {
pcmFramesRead = ma_dr_mp3_hdr_frame_samples(pMP3->decoder.header);
pMP3->pcmFramesConsumedInMP3Frame = 0;
pMP3->pcmFramesRemainingInMP3Frame = pcmFramesRead;
pMP3->mp3FrameChannels = info.channels;
- pMP3->mp3FrameSampleRate = info.hz;
+ pMP3->mp3FrameSampleRate = info.sample_rate;
+ if (pMP3FrameInfo != NULL) {
+ *pMP3FrameInfo = info;
+ }
+ if (ppMP3FrameData != NULL) {
+ *ppMP3FrameData = pMP3->pData + pMP3->dataConsumed - (size_t)info.frame_bytes;
+ }
break;
} else if (info.frame_bytes == 0) {
size_t bytesRead;
@@ -92604,7 +94456,7 @@ static ma_uint32 ma_dr_mp3_decode_next_frame_ex__callbacks(ma_dr_mp3* pMP3, ma_d
pMP3->pData = pNewData;
pMP3->dataCapacity = newDataCap;
}
- bytesRead = ma_dr_mp3__on_read(pMP3, pMP3->pData + pMP3->dataSize, (pMP3->dataCapacity - pMP3->dataSize));
+ bytesRead = ma_dr_mp3__on_read_clamped(pMP3, pMP3->pData + pMP3->dataSize, (pMP3->dataCapacity - pMP3->dataSize));
if (bytesRead == 0) {
pMP3->atEnd = MA_TRUE;
return 0;
@@ -92614,7 +94466,7 @@ static ma_uint32 ma_dr_mp3_decode_next_frame_ex__callbacks(ma_dr_mp3* pMP3, ma_d
};
return pcmFramesRead;
}
-static ma_uint32 ma_dr_mp3_decode_next_frame_ex__memory(ma_dr_mp3* pMP3, ma_dr_mp3d_sample_t* pPCMFrames)
+static ma_uint32 ma_dr_mp3_decode_next_frame_ex__memory(ma_dr_mp3* pMP3, ma_dr_mp3d_sample_t* pPCMFrames, ma_dr_mp3dec_frame_info* pMP3FrameInfo, const ma_uint8** ppMP3FrameData)
{
ma_uint32 pcmFramesRead = 0;
ma_dr_mp3dec_frame_info info;
@@ -92630,36 +94482,44 @@ static ma_uint32 ma_dr_mp3_decode_next_frame_ex__memory(ma_dr_mp3* pMP3, ma_dr_m
pMP3->pcmFramesConsumedInMP3Frame = 0;
pMP3->pcmFramesRemainingInMP3Frame = pcmFramesRead;
pMP3->mp3FrameChannels = info.channels;
- pMP3->mp3FrameSampleRate = info.hz;
+ pMP3->mp3FrameSampleRate = info.sample_rate;
+ if (pMP3FrameInfo != NULL) {
+ *pMP3FrameInfo = info;
+ }
+ if (ppMP3FrameData != NULL) {
+ *ppMP3FrameData = pMP3->memory.pData + pMP3->memory.currentReadPos;
+ }
break;
} else if (info.frame_bytes > 0) {
pMP3->memory.currentReadPos += (size_t)info.frame_bytes;
+ pMP3->streamCursor += (size_t)info.frame_bytes;
} else {
break;
}
}
pMP3->memory.currentReadPos += (size_t)info.frame_bytes;
+ pMP3->streamCursor += (size_t)info.frame_bytes;
return pcmFramesRead;
}
-static ma_uint32 ma_dr_mp3_decode_next_frame_ex(ma_dr_mp3* pMP3, ma_dr_mp3d_sample_t* pPCMFrames)
+static ma_uint32 ma_dr_mp3_decode_next_frame_ex(ma_dr_mp3* pMP3, ma_dr_mp3d_sample_t* pPCMFrames, ma_dr_mp3dec_frame_info* pMP3FrameInfo, const ma_uint8** ppMP3FrameData)
{
if (pMP3->memory.pData != NULL && pMP3->memory.dataSize > 0) {
- return ma_dr_mp3_decode_next_frame_ex__memory(pMP3, pPCMFrames);
+ return ma_dr_mp3_decode_next_frame_ex__memory(pMP3, pPCMFrames, pMP3FrameInfo, ppMP3FrameData);
} else {
- return ma_dr_mp3_decode_next_frame_ex__callbacks(pMP3, pPCMFrames);
+ return ma_dr_mp3_decode_next_frame_ex__callbacks(pMP3, pPCMFrames, pMP3FrameInfo, ppMP3FrameData);
}
}
static ma_uint32 ma_dr_mp3_decode_next_frame(ma_dr_mp3* pMP3)
{
MA_DR_MP3_ASSERT(pMP3 != NULL);
- return ma_dr_mp3_decode_next_frame_ex(pMP3, (ma_dr_mp3d_sample_t*)pMP3->pcmFrames);
+ return ma_dr_mp3_decode_next_frame_ex(pMP3, (ma_dr_mp3d_sample_t*)pMP3->pcmFrames, NULL, NULL);
}
#if 0
static ma_uint32 ma_dr_mp3_seek_next_frame(ma_dr_mp3* pMP3)
{
ma_uint32 pcmFrameCount;
MA_DR_MP3_ASSERT(pMP3 != NULL);
- pcmFrameCount = ma_dr_mp3_decode_next_frame_ex(pMP3, NULL);
+ pcmFrameCount = ma_dr_mp3_decode_next_frame_ex(pMP3, NULL, NULL, NULL);
if (pcmFrameCount == 0) {
return 0;
}
@@ -92669,33 +94529,249 @@ static ma_uint32 ma_dr_mp3_seek_next_frame(ma_dr_mp3* pMP3)
return pcmFrameCount;
}
#endif
-static ma_bool32 ma_dr_mp3_init_internal(ma_dr_mp3* pMP3, ma_dr_mp3_read_proc onRead, ma_dr_mp3_seek_proc onSeek, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks)
+static ma_bool32 ma_dr_mp3_init_internal(ma_dr_mp3* pMP3, ma_dr_mp3_read_proc onRead, ma_dr_mp3_seek_proc onSeek, ma_dr_mp3_tell_proc onTell, ma_dr_mp3_meta_proc onMeta, void* pUserData, void* pUserDataMeta, const ma_allocation_callbacks* pAllocationCallbacks)
{
+ ma_dr_mp3dec_frame_info firstFrameInfo;
+ const ma_uint8* pFirstFrameData;
+ ma_uint32 firstFramePCMFrameCount;
+ ma_uint32 detectedMP3FrameCount = 0xFFFFFFFF;
MA_DR_MP3_ASSERT(pMP3 != NULL);
MA_DR_MP3_ASSERT(onRead != NULL);
ma_dr_mp3dec_init(&pMP3->decoder);
pMP3->onRead = onRead;
pMP3->onSeek = onSeek;
+ pMP3->onMeta = onMeta;
pMP3->pUserData = pUserData;
+ pMP3->pUserDataMeta = pUserDataMeta;
pMP3->allocationCallbacks = ma_dr_mp3_copy_allocation_callbacks_or_defaults(pAllocationCallbacks);
if (pMP3->allocationCallbacks.onFree == NULL || (pMP3->allocationCallbacks.onMalloc == NULL && pMP3->allocationCallbacks.onRealloc == NULL)) {
return MA_FALSE;
}
- if (ma_dr_mp3_decode_next_frame(pMP3) == 0) {
+ pMP3->streamCursor = 0;
+ pMP3->streamLength = MA_UINT64_MAX;
+ pMP3->streamStartOffset = 0;
+ pMP3->delayInPCMFrames = 0;
+ pMP3->paddingInPCMFrames = 0;
+ pMP3->totalPCMFrameCount = MA_UINT64_MAX;
+ #if 1
+ if (onSeek != NULL && onTell != NULL) {
+ if (onSeek(pUserData, 0, MA_DR_MP3_SEEK_END)) {
+ ma_int64 streamLen;
+ int streamEndOffset = 0;
+ if (onTell(pUserData, &streamLen)) {
+ if (streamLen > 128) {
+ char id3[3];
+ if (onSeek(pUserData, streamEndOffset - 128, MA_DR_MP3_SEEK_END)) {
+ if (onRead(pUserData, id3, 3) == 3 && id3[0] == 'T' && id3[1] == 'A' && id3[2] == 'G') {
+ streamEndOffset -= 128;
+ streamLen -= 128;
+ if (onMeta != NULL) {
+ ma_uint8 tag[128];
+ tag[0] = 'T'; tag[1] = 'A'; tag[2] = 'G';
+ if (onRead(pUserData, tag + 3, 125) == 125) {
+ ma_dr_mp3__on_meta(pMP3, MA_DR_MP3_METADATA_TYPE_ID3V1, tag, 128);
+ }
+ }
+ } else {
+ }
+ } else {
+ }
+ } else {
+ }
+ if (streamLen > 32) {
+ char ape[32];
+ if (onSeek(pUserData, streamEndOffset - 32, MA_DR_MP3_SEEK_END)) {
+ if (onRead(pUserData, ape, 32) == 32 && ape[0] == 'A' && ape[1] == 'P' && ape[2] == 'E' && ape[3] == 'T' && ape[4] == 'A' && ape[5] == 'G' && ape[6] == 'E' && ape[7] == 'X') {
+ ma_uint32 tagSize =
+ ((ma_uint32)ape[24] << 0) |
+ ((ma_uint32)ape[25] << 8) |
+ ((ma_uint32)ape[26] << 16) |
+ ((ma_uint32)ape[27] << 24);
+ streamEndOffset -= 32 + tagSize;
+ streamLen -= 32 + tagSize;
+ if (onMeta != NULL) {
+ if (onSeek(pUserData, streamEndOffset, MA_DR_MP3_SEEK_END)) {
+ size_t apeTagSize = (size_t)tagSize + 32;
+ ma_uint8* pTagData = (ma_uint8*)ma_dr_mp3_malloc(apeTagSize, pAllocationCallbacks);
+ if (pTagData != NULL) {
+ if (onRead(pUserData, pTagData, apeTagSize) == apeTagSize) {
+ ma_dr_mp3__on_meta(pMP3, MA_DR_MP3_METADATA_TYPE_APE, pTagData, apeTagSize);
+ }
+ ma_dr_mp3_free(pTagData, pAllocationCallbacks);
+ }
+ }
+ }
+ }
+ }
+ } else {
+ }
+ if (!onSeek(pUserData, 0, MA_DR_MP3_SEEK_SET)) {
+ return MA_FALSE;
+ }
+ pMP3->streamLength = (ma_uint64)streamLen;
+ if (pMP3->memory.pData != NULL) {
+ pMP3->memory.dataSize = (size_t)pMP3->streamLength;
+ }
+ } else {
+ if (!onSeek(pUserData, 0, MA_DR_MP3_SEEK_SET)) {
+ return MA_FALSE;
+ }
+ }
+ } else {
+ }
+ } else {
+ }
+ #endif
+ #if 1
+ {
+ char header[10];
+ if (onRead(pUserData, header, 10) == 10) {
+ if (header[0] == 'I' && header[1] == 'D' && header[2] == '3') {
+ ma_uint32 tagSize =
+ (((ma_uint32)header[6] & 0x7F) << 21) |
+ (((ma_uint32)header[7] & 0x7F) << 14) |
+ (((ma_uint32)header[8] & 0x7F) << 7) |
+ (((ma_uint32)header[9] & 0x7F) << 0);
+ if (header[5] & 0x10) {
+ tagSize += 10;
+ }
+ if (onMeta != NULL) {
+ size_t tagSizeWithHeader = 10 + tagSize;
+ ma_uint8* pTagData = (ma_uint8*)ma_dr_mp3_malloc(tagSizeWithHeader, pAllocationCallbacks);
+ if (pTagData != NULL) {
+ MA_DR_MP3_COPY_MEMORY(pTagData, header, 10);
+ if (onRead(pUserData, pTagData + 10, tagSize) == tagSize) {
+ ma_dr_mp3__on_meta(pMP3, MA_DR_MP3_METADATA_TYPE_ID3V2, pTagData, tagSizeWithHeader);
+ }
+ ma_dr_mp3_free(pTagData, pAllocationCallbacks);
+ }
+ } else {
+ if (onSeek != NULL) {
+ if (!onSeek(pUserData, tagSize, MA_DR_MP3_SEEK_CUR)) {
+ return MA_FALSE;
+ }
+ } else {
+ char discard[1024];
+ while (tagSize > 0) {
+ size_t bytesToRead = tagSize;
+ if (bytesToRead > sizeof(discard)) {
+ bytesToRead = sizeof(discard);
+ }
+ if (onRead(pUserData, discard, bytesToRead) != bytesToRead) {
+ return MA_FALSE;
+ }
+ tagSize -= (ma_uint32)bytesToRead;
+ }
+ }
+ }
+ pMP3->streamStartOffset += 10 + tagSize;
+ pMP3->streamCursor = pMP3->streamStartOffset;
+ } else {
+ if (onSeek != NULL) {
+ if (!onSeek(pUserData, 0, MA_DR_MP3_SEEK_SET)) {
+ return MA_FALSE;
+ }
+ } else {
+ }
+ }
+ } else {
+ return MA_FALSE;
+ }
+ }
+ #endif
+ firstFramePCMFrameCount = ma_dr_mp3_decode_next_frame_ex(pMP3, (ma_dr_mp3d_sample_t*)pMP3->pcmFrames, &firstFrameInfo, &pFirstFrameData);
+ if (firstFramePCMFrameCount > 0) {
+ MA_DR_MP3_ASSERT(pFirstFrameData != NULL);
+ #if 1
+ MA_DR_MP3_ASSERT(firstFrameInfo.frame_bytes > 0);
+ {
+ ma_dr_mp3_bs bs;
+ ma_dr_mp3_L3_gr_info grInfo[4];
+ const ma_uint8* pTagData = pFirstFrameData;
+ ma_dr_mp3_bs_init(&bs, pFirstFrameData + MA_DR_MP3_HDR_SIZE, firstFrameInfo.frame_bytes - MA_DR_MP3_HDR_SIZE);
+ if (MA_DR_MP3_HDR_IS_CRC(pFirstFrameData)) {
+ ma_dr_mp3_bs_get_bits(&bs, 16);
+ }
+ if (ma_dr_mp3_L3_read_side_info(&bs, grInfo, pFirstFrameData) >= 0) {
+ ma_bool32 isXing = MA_FALSE;
+ ma_bool32 isInfo = MA_FALSE;
+ const ma_uint8* pTagDataBeg;
+ pTagDataBeg = pFirstFrameData + MA_DR_MP3_HDR_SIZE + (bs.pos/8);
+ pTagData = pTagDataBeg;
+ isXing = (pTagData[0] == 'X' && pTagData[1] == 'i' && pTagData[2] == 'n' && pTagData[3] == 'g');
+ isInfo = (pTagData[0] == 'I' && pTagData[1] == 'n' && pTagData[2] == 'f' && pTagData[3] == 'o');
+ if (isXing || isInfo) {
+ ma_uint32 bytes = 0;
+ ma_uint32 flags = pTagData[7];
+ pTagData += 8;
+ if (flags & 0x01) {
+ detectedMP3FrameCount = (ma_uint32)pTagData[0] << 24 | (ma_uint32)pTagData[1] << 16 | (ma_uint32)pTagData[2] << 8 | (ma_uint32)pTagData[3];
+ pTagData += 4;
+ }
+ if (flags & 0x02) {
+ bytes = (ma_uint32)pTagData[0] << 24 | (ma_uint32)pTagData[1] << 16 | (ma_uint32)pTagData[2] << 8 | (ma_uint32)pTagData[3];
+ (void)bytes;
+ pTagData += 4;
+ }
+ if (flags & 0x04) {
+ pTagData += 100;
+ }
+ if (flags & 0x08) {
+ pTagData += 4;
+ }
+ if (pTagData[0]) {
+ pTagData += 21;
+ if (pTagData - pFirstFrameData + 14 < firstFrameInfo.frame_bytes) {
+ int delayInPCMFrames;
+ int paddingInPCMFrames;
+ delayInPCMFrames = (( (ma_uint32)pTagData[0] << 4) | ((ma_uint32)pTagData[1] >> 4)) + (528 + 1);
+ paddingInPCMFrames = ((((ma_uint32)pTagData[1] & 0xF) << 8) | ((ma_uint32)pTagData[2] )) - (528 + 1);
+ if (paddingInPCMFrames < 0) {
+ paddingInPCMFrames = 0;
+ }
+ pMP3->delayInPCMFrames = (ma_uint32)delayInPCMFrames;
+ pMP3->paddingInPCMFrames = (ma_uint32)paddingInPCMFrames;
+ }
+ }
+ if (isXing) {
+ pMP3->isVBR = MA_TRUE;
+ } else if (isInfo) {
+ pMP3->isCBR = MA_TRUE;
+ }
+ if (onMeta != NULL) {
+ ma_dr_mp3_metadata_type metadataType = isXing ? MA_DR_MP3_METADATA_TYPE_XING : MA_DR_MP3_METADATA_TYPE_VBRI;
+ size_t tagDataSize;
+ tagDataSize = (size_t)firstFrameInfo.frame_bytes;
+ tagDataSize -= (size_t)(pTagDataBeg - pFirstFrameData);
+ ma_dr_mp3__on_meta(pMP3, metadataType, pTagDataBeg, tagDataSize);
+ }
+ pMP3->pcmFramesRemainingInMP3Frame = 0;
+ pMP3->streamStartOffset += (ma_uint32)(firstFrameInfo.frame_bytes);
+ pMP3->streamCursor = pMP3->streamStartOffset;
+ ma_dr_mp3dec_init(&pMP3->decoder);
+ }
+ } else {
+ }
+ }
+ #endif
+ } else {
ma_dr_mp3__free_from_callbacks(pMP3->pData, &pMP3->allocationCallbacks);
return MA_FALSE;
}
+ if (detectedMP3FrameCount != 0xFFFFFFFF) {
+ pMP3->totalPCMFrameCount = detectedMP3FrameCount * firstFramePCMFrameCount;
+ }
pMP3->channels = pMP3->mp3FrameChannels;
pMP3->sampleRate = pMP3->mp3FrameSampleRate;
return MA_TRUE;
}
-MA_API ma_bool32 ma_dr_mp3_init(ma_dr_mp3* pMP3, ma_dr_mp3_read_proc onRead, ma_dr_mp3_seek_proc onSeek, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks)
+MA_API ma_bool32 ma_dr_mp3_init(ma_dr_mp3* pMP3, ma_dr_mp3_read_proc onRead, ma_dr_mp3_seek_proc onSeek, ma_dr_mp3_tell_proc onTell, ma_dr_mp3_meta_proc onMeta, void* pUserData, const ma_allocation_callbacks* pAllocationCallbacks)
{
if (pMP3 == NULL || onRead == NULL) {
return MA_FALSE;
}
MA_DR_MP3_ZERO_OBJECT(pMP3);
- return ma_dr_mp3_init_internal(pMP3, onRead, onSeek, pUserData, pAllocationCallbacks);
+ return ma_dr_mp3_init_internal(pMP3, onRead, onSeek, onTell, onMeta, pUserData, pUserData, pAllocationCallbacks);
}
static size_t ma_dr_mp3__on_read_memory(void* pUserData, void* pBufferOut, size_t bytesToRead)
{
@@ -92716,29 +94792,40 @@ static size_t ma_dr_mp3__on_read_memory(void* pUserData, void* pBufferOut, size_
static ma_bool32 ma_dr_mp3__on_seek_memory(void* pUserData, int byteOffset, ma_dr_mp3_seek_origin origin)
{
ma_dr_mp3* pMP3 = (ma_dr_mp3*)pUserData;
+ ma_int64 newCursor;
MA_DR_MP3_ASSERT(pMP3 != NULL);
- if (origin == ma_dr_mp3_seek_origin_current) {
- if (byteOffset > 0) {
- if (pMP3->memory.currentReadPos + byteOffset > pMP3->memory.dataSize) {
- byteOffset = (int)(pMP3->memory.dataSize - pMP3->memory.currentReadPos);
- }
- } else {
- if (pMP3->memory.currentReadPos < (size_t)-byteOffset) {
- byteOffset = -(int)pMP3->memory.currentReadPos;
- }
- }
- pMP3->memory.currentReadPos += byteOffset;
+ newCursor = pMP3->memory.currentReadPos;
+ if (origin == MA_DR_MP3_SEEK_SET) {
+ newCursor = 0;
+ } else if (origin == MA_DR_MP3_SEEK_CUR) {
+ newCursor = (ma_int64)pMP3->memory.currentReadPos;
+ } else if (origin == MA_DR_MP3_SEEK_END) {
+ newCursor = (ma_int64)pMP3->memory.dataSize;
} else {
- if ((ma_uint32)byteOffset <= pMP3->memory.dataSize) {
- pMP3->memory.currentReadPos = byteOffset;
- } else {
- pMP3->memory.currentReadPos = pMP3->memory.dataSize;
- }
+ MA_DR_MP3_ASSERT(!"Invalid seek origin");
+ return MA_FALSE;
}
+ newCursor += byteOffset;
+ if (newCursor < 0) {
+ return MA_FALSE;
+ }
+ if ((size_t)newCursor > pMP3->memory.dataSize) {
+ return MA_FALSE;
+ }
+ pMP3->memory.currentReadPos = (size_t)newCursor;
return MA_TRUE;
}
-MA_API ma_bool32 ma_dr_mp3_init_memory(ma_dr_mp3* pMP3, const void* pData, size_t dataSize, const ma_allocation_callbacks* pAllocationCallbacks)
+static ma_bool32 ma_dr_mp3__on_tell_memory(void* pUserData, ma_int64* pCursor)
{
+ ma_dr_mp3* pMP3 = (ma_dr_mp3*)pUserData;
+ MA_DR_MP3_ASSERT(pMP3 != NULL);
+ MA_DR_MP3_ASSERT(pCursor != NULL);
+ *pCursor = (ma_int64)pMP3->memory.currentReadPos;
+ return MA_TRUE;
+}
+MA_API ma_bool32 ma_dr_mp3_init_memory_with_metadata(ma_dr_mp3* pMP3, const void* pData, size_t dataSize, ma_dr_mp3_meta_proc onMeta, void* pUserDataMeta, const ma_allocation_callbacks* pAllocationCallbacks)
+{
+ ma_bool32 result;
if (pMP3 == NULL) {
return MA_FALSE;
}
@@ -92749,7 +94836,21 @@ MA_API ma_bool32 ma_dr_mp3_init_memory(ma_dr_mp3* pMP3, const void* pData, size_
pMP3->memory.pData = (const ma_uint8*)pData;
pMP3->memory.dataSize = dataSize;
pMP3->memory.currentReadPos = 0;
- return ma_dr_mp3_init_internal(pMP3, ma_dr_mp3__on_read_memory, ma_dr_mp3__on_seek_memory, pMP3, pAllocationCallbacks);
+ result = ma_dr_mp3_init_internal(pMP3, ma_dr_mp3__on_read_memory, ma_dr_mp3__on_seek_memory, ma_dr_mp3__on_tell_memory, onMeta, pMP3, pUserDataMeta, pAllocationCallbacks);
+ if (result == MA_FALSE) {
+ return MA_FALSE;
+ }
+ if (pMP3->streamLength <= (ma_uint64)MA_SIZE_MAX) {
+ pMP3->memory.dataSize = (size_t)pMP3->streamLength;
+ }
+ if (pMP3->streamStartOffset > (ma_uint64)MA_SIZE_MAX) {
+ return MA_FALSE;
+ }
+ return MA_TRUE;
+}
+MA_API ma_bool32 ma_dr_mp3_init_memory(ma_dr_mp3* pMP3, const void* pData, size_t dataSize, const ma_allocation_callbacks* pAllocationCallbacks)
+{
+ return ma_dr_mp3_init_memory_with_metadata(pMP3, pData, dataSize, NULL, NULL, pAllocationCallbacks);
}
#ifndef MA_DR_MP3_NO_STDIO
#include
@@ -92760,36 +94861,76 @@ static size_t ma_dr_mp3__on_read_stdio(void* pUserData, void* pBufferOut, size_t
}
static ma_bool32 ma_dr_mp3__on_seek_stdio(void* pUserData, int offset, ma_dr_mp3_seek_origin origin)
{
- return fseek((FILE*)pUserData, offset, (origin == ma_dr_mp3_seek_origin_current) ? SEEK_CUR : SEEK_SET) == 0;
+ int whence = SEEK_SET;
+ if (origin == MA_DR_MP3_SEEK_CUR) {
+ whence = SEEK_CUR;
+ } else if (origin == MA_DR_MP3_SEEK_END) {
+ whence = SEEK_END;
+ }
+ return fseek((FILE*)pUserData, offset, whence) == 0;
}
-MA_API ma_bool32 ma_dr_mp3_init_file(ma_dr_mp3* pMP3, const char* pFilePath, const ma_allocation_callbacks* pAllocationCallbacks)
+static ma_bool32 ma_dr_mp3__on_tell_stdio(void* pUserData, ma_int64* pCursor)
+{
+ FILE* pFileStdio = (FILE*)pUserData;
+ ma_int64 result;
+ MA_DR_MP3_ASSERT(pFileStdio != NULL);
+ MA_DR_MP3_ASSERT(pCursor != NULL);
+#if defined(_WIN32) && !defined(NXDK)
+ #if defined(_MSC_VER) && _MSC_VER > 1200
+ result = _ftelli64(pFileStdio);
+ #else
+ result = ftell(pFileStdio);
+ #endif
+#else
+ result = ftell(pFileStdio);
+#endif
+ *pCursor = result;
+ return MA_TRUE;
+}
+MA_API ma_bool32 ma_dr_mp3_init_file_with_metadata(ma_dr_mp3* pMP3, const char* pFilePath, ma_dr_mp3_meta_proc onMeta, void* pUserDataMeta, const ma_allocation_callbacks* pAllocationCallbacks)
{
ma_bool32 result;
FILE* pFile;
+ if (pMP3 == NULL) {
+ return MA_FALSE;
+ }
+ MA_DR_MP3_ZERO_OBJECT(pMP3);
if (ma_fopen(&pFile, pFilePath, "rb") != MA_SUCCESS) {
return MA_FALSE;
}
- result = ma_dr_mp3_init(pMP3, ma_dr_mp3__on_read_stdio, ma_dr_mp3__on_seek_stdio, (void*)pFile, pAllocationCallbacks);
+ result = ma_dr_mp3_init_internal(pMP3, ma_dr_mp3__on_read_stdio, ma_dr_mp3__on_seek_stdio, ma_dr_mp3__on_tell_stdio, onMeta, (void*)pFile, pUserDataMeta, pAllocationCallbacks);
if (result != MA_TRUE) {
fclose(pFile);
return result;
}
return MA_TRUE;
}
-MA_API ma_bool32 ma_dr_mp3_init_file_w(ma_dr_mp3* pMP3, const wchar_t* pFilePath, const ma_allocation_callbacks* pAllocationCallbacks)
+MA_API ma_bool32 ma_dr_mp3_init_file_with_metadata_w(ma_dr_mp3* pMP3, const wchar_t* pFilePath, ma_dr_mp3_meta_proc onMeta, void* pUserDataMeta, const ma_allocation_callbacks* pAllocationCallbacks)
{
ma_bool32 result;
FILE* pFile;
+ if (pMP3 == NULL) {
+ return MA_FALSE;
+ }
+ MA_DR_MP3_ZERO_OBJECT(pMP3);
if (ma_wfopen(&pFile, pFilePath, L"rb", pAllocationCallbacks) != MA_SUCCESS) {
return MA_FALSE;
}
- result = ma_dr_mp3_init(pMP3, ma_dr_mp3__on_read_stdio, ma_dr_mp3__on_seek_stdio, (void*)pFile, pAllocationCallbacks);
+ result = ma_dr_mp3_init_internal(pMP3, ma_dr_mp3__on_read_stdio, ma_dr_mp3__on_seek_stdio, ma_dr_mp3__on_tell_stdio, onMeta, (void*)pFile, pUserDataMeta, pAllocationCallbacks);
if (result != MA_TRUE) {
fclose(pFile);
return result;
}
return MA_TRUE;
}
+MA_API ma_bool32 ma_dr_mp3_init_file(ma_dr_mp3* pMP3, const char* pFilePath, const ma_allocation_callbacks* pAllocationCallbacks)
+{
+ return ma_dr_mp3_init_file_with_metadata(pMP3, pFilePath, NULL, NULL, pAllocationCallbacks);
+}
+MA_API ma_bool32 ma_dr_mp3_init_file_w(ma_dr_mp3* pMP3, const wchar_t* pFilePath, const ma_allocation_callbacks* pAllocationCallbacks)
+{
+ return ma_dr_mp3_init_file_with_metadata_w(pMP3, pFilePath, NULL, NULL, pAllocationCallbacks);
+}
#endif
MA_API void ma_dr_mp3_uninit(ma_dr_mp3* pMP3)
{
@@ -92859,17 +95000,38 @@ static ma_uint64 ma_dr_mp3_read_pcm_frames_raw(ma_dr_mp3* pMP3, ma_uint64 frames
MA_DR_MP3_ASSERT(pMP3 != NULL);
MA_DR_MP3_ASSERT(pMP3->onRead != NULL);
while (framesToRead > 0) {
- ma_uint32 framesToConsume = (ma_uint32)MA_DR_MP3_MIN(pMP3->pcmFramesRemainingInMP3Frame, framesToRead);
+ ma_uint32 framesToConsume;
+ if (pMP3->currentPCMFrame < pMP3->delayInPCMFrames) {
+ ma_uint32 framesToSkip = (ma_uint32)MA_DR_MP3_MIN(pMP3->pcmFramesRemainingInMP3Frame, pMP3->delayInPCMFrames - pMP3->currentPCMFrame);
+ pMP3->currentPCMFrame += framesToSkip;
+ pMP3->pcmFramesConsumedInMP3Frame += framesToSkip;
+ pMP3->pcmFramesRemainingInMP3Frame -= framesToSkip;
+ }
+ framesToConsume = (ma_uint32)MA_DR_MP3_MIN(pMP3->pcmFramesRemainingInMP3Frame, framesToRead);
+ if (pMP3->totalPCMFrameCount != MA_UINT64_MAX && pMP3->totalPCMFrameCount > pMP3->paddingInPCMFrames) {
+ if (pMP3->currentPCMFrame < (pMP3->totalPCMFrameCount - pMP3->paddingInPCMFrames)) {
+ ma_uint64 framesRemainigToPadding = (pMP3->totalPCMFrameCount - pMP3->paddingInPCMFrames) - pMP3->currentPCMFrame;
+ if (framesToConsume > framesRemainigToPadding) {
+ framesToConsume = (ma_uint32)framesRemainigToPadding;
+ }
+ } else {
+ break;
+ }
+ }
if (pBufferOut != NULL) {
- #if defined(MA_DR_MP3_FLOAT_OUTPUT)
- float* pFramesOutF32 = (float*)MA_DR_MP3_OFFSET_PTR(pBufferOut, sizeof(float) * totalFramesRead * pMP3->channels);
- float* pFramesInF32 = (float*)MA_DR_MP3_OFFSET_PTR(&pMP3->pcmFrames[0], sizeof(float) * pMP3->pcmFramesConsumedInMP3Frame * pMP3->mp3FrameChannels);
- MA_DR_MP3_COPY_MEMORY(pFramesOutF32, pFramesInF32, sizeof(float) * framesToConsume * pMP3->channels);
- #else
- ma_int16* pFramesOutS16 = (ma_int16*)MA_DR_MP3_OFFSET_PTR(pBufferOut, sizeof(ma_int16) * totalFramesRead * pMP3->channels);
- ma_int16* pFramesInS16 = (ma_int16*)MA_DR_MP3_OFFSET_PTR(&pMP3->pcmFrames[0], sizeof(ma_int16) * pMP3->pcmFramesConsumedInMP3Frame * pMP3->mp3FrameChannels);
- MA_DR_MP3_COPY_MEMORY(pFramesOutS16, pFramesInS16, sizeof(ma_int16) * framesToConsume * pMP3->channels);
- #endif
+ #if defined(MA_DR_MP3_FLOAT_OUTPUT)
+ {
+ float* pFramesOutF32 = (float*)MA_DR_MP3_OFFSET_PTR(pBufferOut, sizeof(float) * totalFramesRead * pMP3->channels);
+ float* pFramesInF32 = (float*)MA_DR_MP3_OFFSET_PTR(&pMP3->pcmFrames[0], sizeof(float) * pMP3->pcmFramesConsumedInMP3Frame * pMP3->mp3FrameChannels);
+ MA_DR_MP3_COPY_MEMORY(pFramesOutF32, pFramesInF32, sizeof(float) * framesToConsume * pMP3->channels);
+ }
+ #else
+ {
+ ma_int16* pFramesOutS16 = (ma_int16*)MA_DR_MP3_OFFSET_PTR(pBufferOut, sizeof(ma_int16) * totalFramesRead * pMP3->channels);
+ ma_int16* pFramesInS16 = (ma_int16*)MA_DR_MP3_OFFSET_PTR(&pMP3->pcmFrames[0], sizeof(ma_int16) * pMP3->pcmFramesConsumedInMP3Frame * pMP3->mp3FrameChannels);
+ MA_DR_MP3_COPY_MEMORY(pFramesOutS16, pFramesInS16, sizeof(ma_int16) * framesToConsume * pMP3->channels);
+ }
+ #endif
}
pMP3->currentPCMFrame += framesToConsume;
pMP3->pcmFramesConsumedInMP3Frame += framesToConsume;
@@ -92879,6 +95041,9 @@ static ma_uint64 ma_dr_mp3_read_pcm_frames_raw(ma_dr_mp3* pMP3, ma_uint64 frames
if (framesToRead == 0) {
break;
}
+ if (pMP3->totalPCMFrameCount != MA_UINT64_MAX && pMP3->totalPCMFrameCount > pMP3->paddingInPCMFrames && pMP3->currentPCMFrame >= (pMP3->totalPCMFrameCount - pMP3->paddingInPCMFrames)) {
+ break;
+ }
MA_DR_MP3_ASSERT(pMP3->pcmFramesRemainingInMP3Frame == 0);
if (ma_dr_mp3_decode_next_frame(pMP3) == 0) {
break;
@@ -92958,7 +95123,7 @@ static ma_bool32 ma_dr_mp3_seek_to_start_of_stream(ma_dr_mp3* pMP3)
{
MA_DR_MP3_ASSERT(pMP3 != NULL);
MA_DR_MP3_ASSERT(pMP3->onSeek != NULL);
- if (!ma_dr_mp3__on_seek(pMP3, 0, ma_dr_mp3_seek_origin_start)) {
+ if (!ma_dr_mp3__on_seek_64(pMP3, pMP3->streamStartOffset, MA_DR_MP3_SEEK_SET)) {
return MA_FALSE;
}
ma_dr_mp3_reset(pMP3);
@@ -93024,7 +95189,7 @@ static ma_bool32 ma_dr_mp3_seek_to_pcm_frame__seek_table(ma_dr_mp3* pMP3, ma_uin
seekPoint.mp3FramesToDiscard = 0;
seekPoint.pcmFramesToDiscard = 0;
}
- if (!ma_dr_mp3__on_seek_64(pMP3, seekPoint.seekPosInBytes, ma_dr_mp3_seek_origin_start)) {
+ if (!ma_dr_mp3__on_seek_64(pMP3, seekPoint.seekPosInBytes, MA_DR_MP3_SEEK_SET)) {
return MA_FALSE;
}
ma_dr_mp3_reset(pMP3);
@@ -93035,7 +95200,7 @@ static ma_bool32 ma_dr_mp3_seek_to_pcm_frame__seek_table(ma_dr_mp3* pMP3, ma_uin
if (iMP3Frame == seekPoint.mp3FramesToDiscard-1) {
pPCMFrames = (ma_dr_mp3d_sample_t*)pMP3->pcmFrames;
}
- pcmFramesRead = ma_dr_mp3_decode_next_frame_ex(pMP3, pPCMFrames);
+ pcmFramesRead = ma_dr_mp3_decode_next_frame_ex(pMP3, pPCMFrames, NULL, NULL);
if (pcmFramesRead == 0) {
return MA_FALSE;
}
@@ -93077,7 +95242,7 @@ MA_API ma_bool32 ma_dr_mp3_get_mp3_and_pcm_frame_count(ma_dr_mp3* pMP3, ma_uint6
totalMP3FrameCount = 0;
for (;;) {
ma_uint32 pcmFramesInCurrentMP3Frame;
- pcmFramesInCurrentMP3Frame = ma_dr_mp3_decode_next_frame_ex(pMP3, NULL);
+ pcmFramesInCurrentMP3Frame = ma_dr_mp3_decode_next_frame_ex(pMP3, NULL, NULL, NULL);
if (pcmFramesInCurrentMP3Frame == 0) {
break;
}
@@ -93101,10 +95266,26 @@ MA_API ma_bool32 ma_dr_mp3_get_mp3_and_pcm_frame_count(ma_dr_mp3* pMP3, ma_uint6
MA_API ma_uint64 ma_dr_mp3_get_pcm_frame_count(ma_dr_mp3* pMP3)
{
ma_uint64 totalPCMFrameCount;
- if (!ma_dr_mp3_get_mp3_and_pcm_frame_count(pMP3, NULL, &totalPCMFrameCount)) {
+ if (pMP3 == NULL) {
return 0;
}
- return totalPCMFrameCount;
+ if (pMP3->totalPCMFrameCount != MA_UINT64_MAX) {
+ totalPCMFrameCount = pMP3->totalPCMFrameCount;
+ if (totalPCMFrameCount >= pMP3->delayInPCMFrames) {
+ totalPCMFrameCount -= pMP3->delayInPCMFrames;
+ } else {
+ }
+ if (totalPCMFrameCount >= pMP3->paddingInPCMFrames) {
+ totalPCMFrameCount -= pMP3->paddingInPCMFrames;
+ } else {
+ }
+ return totalPCMFrameCount;
+ } else {
+ if (!ma_dr_mp3_get_mp3_and_pcm_frame_count(pMP3, NULL, &totalPCMFrameCount)) {
+ return 0;
+ }
+ return totalPCMFrameCount;
+ }
}
MA_API ma_uint64 ma_dr_mp3_get_mp3_frame_count(ma_dr_mp3* pMP3)
{
@@ -93174,7 +95355,7 @@ MA_API ma_bool32 ma_dr_mp3_calculate_seek_points(ma_dr_mp3* pMP3, ma_uint32* pSe
MA_DR_MP3_ASSERT(pMP3->streamCursor >= pMP3->dataSize);
mp3FrameInfo[iMP3Frame].bytePos = pMP3->streamCursor - pMP3->dataSize;
mp3FrameInfo[iMP3Frame].pcmFrameIndex = runningPCMFrameCount;
- pcmFramesInCurrentMP3FrameIn = ma_dr_mp3_decode_next_frame_ex(pMP3, NULL);
+ pcmFramesInCurrentMP3FrameIn = ma_dr_mp3_decode_next_frame_ex(pMP3, NULL, NULL, NULL);
if (pcmFramesInCurrentMP3FrameIn == 0) {
return MA_FALSE;
}
@@ -93198,7 +95379,7 @@ MA_API ma_bool32 ma_dr_mp3_calculate_seek_points(ma_dr_mp3* pMP3, ma_uint32* pSe
}
mp3FrameInfo[MA_DR_MP3_COUNTOF(mp3FrameInfo)-1].bytePos = pMP3->streamCursor - pMP3->dataSize;
mp3FrameInfo[MA_DR_MP3_COUNTOF(mp3FrameInfo)-1].pcmFrameIndex = runningPCMFrameCount;
- pcmFramesInCurrentMP3FrameIn = ma_dr_mp3_decode_next_frame_ex(pMP3, NULL);
+ pcmFramesInCurrentMP3FrameIn = ma_dr_mp3_decode_next_frame_ex(pMP3, NULL, NULL, NULL);
if (pcmFramesInCurrentMP3FrameIn == 0) {
pSeekPoints[iSeekPoint].seekPosInBytes = mp3FrameInfo[0].bytePos;
pSeekPoints[iSeekPoint].pcmFrameIndex = nextTargetPCMFrame;
@@ -93336,18 +95517,18 @@ static ma_int16* ma_dr_mp3__full_read_and_close_s16(ma_dr_mp3* pMP3, ma_dr_mp3_c
}
return pFrames;
}
-MA_API float* ma_dr_mp3_open_and_read_pcm_frames_f32(ma_dr_mp3_read_proc onRead, ma_dr_mp3_seek_proc onSeek, void* pUserData, ma_dr_mp3_config* pConfig, ma_uint64* pTotalFrameCount, const ma_allocation_callbacks* pAllocationCallbacks)
+MA_API float* ma_dr_mp3_open_and_read_pcm_frames_f32(ma_dr_mp3_read_proc onRead, ma_dr_mp3_seek_proc onSeek, ma_dr_mp3_tell_proc onTell, void* pUserData, ma_dr_mp3_config* pConfig, ma_uint64* pTotalFrameCount, const ma_allocation_callbacks* pAllocationCallbacks)
{
ma_dr_mp3 mp3;
- if (!ma_dr_mp3_init(&mp3, onRead, onSeek, pUserData, pAllocationCallbacks)) {
+ if (!ma_dr_mp3_init(&mp3, onRead, onSeek, onTell, NULL, pUserData, pAllocationCallbacks)) {
return NULL;
}
return ma_dr_mp3__full_read_and_close_f32(&mp3, pConfig, pTotalFrameCount);
}
-MA_API ma_int16* ma_dr_mp3_open_and_read_pcm_frames_s16(ma_dr_mp3_read_proc onRead, ma_dr_mp3_seek_proc onSeek, void* pUserData, ma_dr_mp3_config* pConfig, ma_uint64* pTotalFrameCount, const ma_allocation_callbacks* pAllocationCallbacks)
+MA_API ma_int16* ma_dr_mp3_open_and_read_pcm_frames_s16(ma_dr_mp3_read_proc onRead, ma_dr_mp3_seek_proc onSeek, ma_dr_mp3_tell_proc onTell, void* pUserData, ma_dr_mp3_config* pConfig, ma_uint64* pTotalFrameCount, const ma_allocation_callbacks* pAllocationCallbacks)
{
ma_dr_mp3 mp3;
- if (!ma_dr_mp3_init(&mp3, onRead, onSeek, pUserData, pAllocationCallbacks)) {
+ if (!ma_dr_mp3_init(&mp3, onRead, onSeek, onTell, NULL, pUserData, pAllocationCallbacks)) {
return NULL;
}
return ma_dr_mp3__full_read_and_close_s16(&mp3, pConfig, pTotalFrameCount);
@@ -93465,4 +95646,4 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
-*/
+*/
\ No newline at end of file
diff --git a/src/external/rlsw.h b/src/external/rlsw.h
new file mode 100644
index 000000000..49050f848
--- /dev/null
+++ b/src/external/rlsw.h
@@ -0,0 +1,4938 @@
+/**********************************************************************************************
+*
+* rlsw v1.0 - An OpenGL 1.1-style software renderer implementation
+*
+* DESCRIPTION:
+* rlsw is a custom OpenGL 1.1-style implementation on software, intended to provide all
+* functionality available on rlgl.h library used by raylib, becoming a direct software
+* rendering replacement for OpenGL 1.1 backend and allowing to run raylib on GPU-less
+* devices when required.
+*
+* FEATURES:
+* - Rendering to custom internal framebuffer with multiple color modes supported:
+* - Color buffer: RGB - 8-bit (3:3:2) | RGB - 16-bit (5:6:5) | RGB - 24-bit (8:8:8)
+* - Depth buffer: D - 8-bit (unorm) | D - 16-bit (unorm) | D - 24-bit (unorm)
+* - Rendering modes supported: POINT, LINES, TRIANGLE, QUADS
+* - Additional features: Polygon modes, Point width, Line width
+* - Clipping support for all rendering modes
+* - Texture features supported:
+* - All uncompressed texture formats supported by raylib
+* - Texture Minification/Magnification checks
+* - Point and Bilinear filtering
+* - Texture Wrap Modes with separate checks for S/T coordinates
+* - Vertex Arrays support with direct primitive drawing mode
+* - Matrix Stack support (Matrix Push/Pop)
+* - Other GL misc features:
+* - GL-style getter functions
+* - Framebuffer resizing
+* - Perspective correction
+* - Scissor clipping
+* - Depth testing
+* - Blend modes
+* - Face culling
+*
+* ADDITIONAL NOTES:
+* Check PR for more info: https://github.com/raysan5/raylib/pull/4832
+*
+* CONFIGURATION:
+* #define RLSW_IMPLEMENTATION
+* Generates the implementation of the library into the included file
+* If not defined, the library is in header only mode and can be included in other headers
+* or source files without problems. But only ONE file should hold the implementation
+*
+* rlsw capabilities could be customized just defining some internal
+* values before library inclusion (default values listed):
+*
+* #define SW_GL_FRAMEBUFFER_COPY_BGRA true
+* #define SW_GL_BINDING_COPY_TEXTURE true
+* #define SW_COLOR_BUFFER_BITS 24
+* #define SW_DEPTH_BUFFER_BITS 16
+* #define SW_MAX_PROJECTION_STACK_SIZE 2
+* #define SW_MAX_MODELVIEW_STACK_SIZE 8
+* #define SW_MAX_TEXTURE_STACK_SIZE 2
+* #define SW_MAX_TEXTURES 128
+*
+*
+* LICENSE: MIT
+*
+* Copyright (c) 2025-2026 Le Juez Victor (@Bigfoot71), reviewed by Ramon Santamaria (@raysan5)
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all
+* copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+**********************************************************************************************/
+
+#ifndef RLSW_H
+#define RLSW_H
+
+#include
+#include
+
+//----------------------------------------------------------------------------------
+// Defines and Macros
+//----------------------------------------------------------------------------------
+// Function specifiers definition
+#ifndef SWAPI
+ #define SWAPI // Functions defined as 'extern' by default (implicit specifiers)
+#endif
+
+#ifndef SW_MALLOC
+ #define SW_MALLOC(sz) malloc(sz)
+#endif
+
+#ifndef SW_REALLOC
+ #define SW_REALLOC(ptr, newSz) realloc(ptr, newSz)
+#endif
+
+#ifndef SW_FREE
+ #define SW_FREE(ptr) free(ptr)
+#endif
+
+#ifndef SW_RESTRICT
+ #ifdef _MSC_VER
+ #define SW_RESTRICT __restrict
+ #else
+ #define SW_RESTRICT restrict
+ #endif
+#endif
+
+#ifndef SW_GL_FRAMEBUFFER_COPY_BGRA
+ #define SW_GL_FRAMEBUFFER_COPY_BGRA true
+#endif
+
+#ifndef SW_GL_BINDING_COPY_TEXTURE
+ #define SW_GL_BINDING_COPY_TEXTURE true
+#endif
+
+#ifndef SW_COLOR_BUFFER_BITS
+ #define SW_COLOR_BUFFER_BITS 24
+#endif
+
+#ifndef SW_DEPTH_BUFFER_BITS
+ #define SW_DEPTH_BUFFER_BITS 16
+#endif
+
+#ifndef SW_MAX_PROJECTION_STACK_SIZE
+ #define SW_MAX_PROJECTION_STACK_SIZE 2
+#endif
+
+#ifndef SW_MAX_MODELVIEW_STACK_SIZE
+ #define SW_MAX_MODELVIEW_STACK_SIZE 8
+#endif
+
+#ifndef SW_MAX_TEXTURE_STACK_SIZE
+ #define SW_MAX_TEXTURE_STACK_SIZE 2
+#endif
+
+#ifndef SW_MAX_TEXTURES
+ #define SW_MAX_TEXTURES 128
+#endif
+
+// Under normal circumstances, clipping a polygon can add at most one vertex per clipping plane.
+// Considering the largest polygon involved is a quadrilateral (4 vertices),
+// and that clipping occurs against both the frustum (6 planes) and the scissors (4 planes),
+// the maximum number of vertices after clipping is:
+// 4 (original vertices) + 6 (frustum planes) + 4 (scissors planes) = 14
+#ifndef SW_MAX_CLIPPED_POLYGON_VERTICES
+ #define SW_MAX_CLIPPED_POLYGON_VERTICES 14
+#endif
+
+#ifndef SW_CLIP_EPSILON
+ #define SW_CLIP_EPSILON 1e-4f
+#endif
+
+//----------------------------------------------------------------------------------
+// OpenGL Compatibility Types
+//----------------------------------------------------------------------------------
+typedef unsigned int GLenum;
+typedef unsigned char GLboolean;
+typedef unsigned int GLbitfield;
+typedef void GLvoid;
+typedef signed char GLbyte;
+typedef short GLshort;
+typedef int GLint;
+typedef unsigned char GLubyte;
+typedef unsigned short GLushort;
+typedef unsigned int GLuint;
+typedef int GLsizei;
+typedef float GLfloat;
+typedef float GLclampf;
+typedef double GLdouble;
+typedef double GLclampd;
+
+//----------------------------------------------------------------------------------
+// OpenGL Definitions
+// NOTE: Not used/supported definitions are commented
+//----------------------------------------------------------------------------------
+#define GL_FALSE 0
+#define GL_TRUE 1
+
+#define GL_SCISSOR_TEST 0x0C11
+#define GL_TEXTURE_2D 0x0DE1
+#define GL_DEPTH_TEST 0x0B71
+#define GL_CULL_FACE 0x0B44
+#define GL_BLEND 0x0BE2
+
+#define GL_VENDOR 0x1F00
+#define GL_RENDERER 0x1F01
+#define GL_VERSION 0x1F02
+#define GL_EXTENSIONS 0x1F03
+
+//#define GL_ATTRIB_STACK_DEPTH 0x0BB0
+//#define GL_CLIENT_ATTRIB_STACK_DEPTH 0x0BB1
+#define GL_COLOR_CLEAR_VALUE 0x0C22
+//#define GL_COLOR_WRITEMASK 0x0C23
+//#define GL_CURRENT_INDEX 0x0B01
+#define GL_CURRENT_COLOR 0x0B00
+//#define GL_CURRENT_NORMAL 0x0B02
+//#define GL_CURRENT_RASTER_COLOR 0x0B04
+//#define GL_CURRENT_RASTER_DISTANCE 0x0B09
+//#define GL_CURRENT_RASTER_INDEX 0x0B05
+//#define GL_CURRENT_RASTER_POSITION 0x0B07
+//#define GL_CURRENT_RASTER_TEXTURE_COORDS 0x0B06
+//#define GL_CURRENT_RASTER_POSITION_VALID 0x0B08
+#define GL_CURRENT_TEXTURE_COORDS 0x0B03
+#define GL_POINT_SIZE 0x0B11
+#define GL_LINE_WIDTH 0x0B21
+//#define GL_INDEX_CLEAR_VALUE 0x0C20
+//#define GL_INDEX_MODE 0x0C30
+//#define GL_INDEX_WRITEMASK 0x0C21
+#define GL_MODELVIEW_MATRIX 0x0BA6
+#define GL_MODELVIEW_STACK_DEPTH 0x0BA3
+//#define GL_NAME_STACK_DEPTH 0x0D70
+#define GL_PROJECTION_MATRIX 0x0BA7
+#define GL_PROJECTION_STACK_DEPTH 0x0BA4
+//#define GL_RENDER_MODE 0x0C40
+//#define GL_RGBA_MODE 0x0C31
+#define GL_TEXTURE_MATRIX 0x0BA8
+#define GL_TEXTURE_STACK_DEPTH 0x0BA5
+#define GL_VIEWPORT 0x0BA2
+
+#define GL_COLOR_BUFFER_BIT 0x00004000
+#define GL_DEPTH_BUFFER_BIT 0x00000100
+
+#define GL_MODELVIEW 0x1700
+#define GL_PROJECTION 0x1701
+#define GL_TEXTURE 0x1702
+
+#define GL_VERTEX_ARRAY 0x8074
+#define GL_NORMAL_ARRAY 0x8075 // WARNING: Not implemented (defined for RLGL)
+#define GL_COLOR_ARRAY 0x8076
+//#define GL_INDEX_ARRAY 0x8077
+#define GL_TEXTURE_COORD_ARRAY 0x8078
+
+#define GL_POINTS 0x0000
+#define GL_LINES 0x0001
+//#define GL_LINE_LOOP 0x0002
+//#define GL_LINE_STRIP 0x0003
+#define GL_TRIANGLES 0x0004
+//#define GL_TRIANGLE_STRIP 0x0005
+//#define GL_TRIANGLE_FAN 0x0006
+#define GL_QUADS 0x0007
+//#define GL_QUAD_STRIP 0x0008
+//#define GL_POLYGON 0x0009
+
+#define GL_POINT 0x1B00
+#define GL_LINE 0x1B01
+#define GL_FILL 0x1B02
+
+#define GL_FRONT 0x0404
+#define GL_BACK 0x0405
+
+#define GL_ZERO 0
+#define GL_ONE 1
+#define GL_SRC_COLOR 0x0300
+#define GL_ONE_MINUS_SRC_COLOR 0x0301
+#define GL_SRC_ALPHA 0x0302
+#define GL_ONE_MINUS_SRC_ALPHA 0x0303
+#define GL_DST_ALPHA 0x0304
+#define GL_ONE_MINUS_DST_ALPHA 0x0305
+#define GL_DST_COLOR 0x0306
+#define GL_ONE_MINUS_DST_COLOR 0x0307
+#define GL_SRC_ALPHA_SATURATE 0x0308
+
+#define GL_NEAREST 0x2600
+#define GL_LINEAR 0x2601
+
+#define GL_REPEAT 0x2901
+#define GL_CLAMP 0x2900
+
+#define GL_TEXTURE_MAG_FILTER 0x2800
+#define GL_TEXTURE_MIN_FILTER 0x2801
+
+#define GL_TEXTURE_WRAP_S 0x2802
+#define GL_TEXTURE_WRAP_T 0x2803
+
+#define GL_NO_ERROR 0
+#define GL_INVALID_ENUM 0x0500
+#define GL_INVALID_VALUE 0x0501
+#define GL_INVALID_OPERATION 0x0502
+#define GL_STACK_OVERFLOW 0x0503
+#define GL_STACK_UNDERFLOW 0x0504
+#define GL_OUT_OF_MEMORY 0x0505
+
+#define GL_ALPHA 0x1906
+#define GL_LUMINANCE 0x1909
+#define GL_LUMINANCE_ALPHA 0x190A
+#define GL_RGB 0x1907
+#define GL_RGBA 0x1908
+
+#define GL_BYTE 0x1400
+#define GL_UNSIGNED_BYTE 0x1401
+#define GL_SHORT 0x1402
+#define GL_UNSIGNED_SHORT 0x1403
+#define GL_INT 0x1404
+#define GL_UNSIGNED_INT 0x1405
+#define GL_FLOAT 0x1406
+
+// OpenGL Definitions NOT USED
+#define GL_PERSPECTIVE_CORRECTION_HINT 0x0C50
+#define GL_PACK_ALIGNMENT 0x0D05
+#define GL_UNPACK_ALIGNMENT 0x0CF5
+#define GL_LINE_SMOOTH 0x0B20
+#define GL_SMOOTH 0x1D01
+#define GL_NICEST 0x1102
+#define GL_CCW 0x0901
+#define GL_CW 0x0900
+#define GL_NEVER 0x0200
+#define GL_LESS 0x0201
+#define GL_EQUAL 0x0202
+#define GL_LEQUAL 0x0203
+#define GL_GREATER 0x0204
+#define GL_NOTEQUAL 0x0205
+#define GL_GEQUAL 0x0206
+#define GL_ALWAYS 0x0207
+
+//----------------------------------------------------------------------------------
+// OpenGL Bindings to rlsw
+//----------------------------------------------------------------------------------
+#define glReadPixels(x, y, w, h, f, t, p) swCopyFramebuffer((x), (y), (w), (h), (f), (t), (p))
+#define glEnable(state) swEnable((state))
+#define glDisable(state) swDisable((state))
+#define glGetFloatv(pname, params) swGetFloatv((pname), (params))
+#define glGetString(pname) swGetString((pname))
+#define glGetError() swGetError()
+#define glViewport(x, y, w, h) swViewport((x), (y), (w), (h))
+#define glScissor(x, y, w, h) swScissor((x), (y), (w), (h))
+#define glClearColor(r, g, b, a) swClearColor((r), (g), (b), (a))
+#define glClear(bitmask) swClear((bitmask))
+#define glBlendFunc(sfactor, dfactor) swBlendFunc((sfactor), (dfactor))
+#define glPolygonMode(face, mode) swPolygonMode((mode))
+#define glCullFace(face) swCullFace((face))
+#define glPointSize(size) swPointSize((size))
+#define glLineWidth(width) swLineWidth((width))
+#define glMatrixMode(mode) swMatrixMode((mode))
+#define glPushMatrix() swPushMatrix()
+#define glPopMatrix() swPopMatrix()
+#define glLoadIdentity() swLoadIdentity()
+#define glTranslatef(x, y, z) swTranslatef((x), (y), (z))
+#define glRotatef(a, x, y, z) swRotatef((a), (x), (y), (z))
+#define glScalef(x, y, z) swScalef((x), (y), (z))
+#define glMultMatrixf(v) swMultMatrixf((v))
+#define glFrustum(l, r, b, t, n, f) swFrustum((l), (r), (b), (t), (n), (f))
+#define glOrtho(l, r, b, t, n, f) swOrtho((l), (r), (b), (t), (n), (f))
+#define glBegin(mode) swBegin((mode))
+#define glEnd() swEnd()
+#define glVertex2i(x, y) swVertex2i((x), (y))
+#define glVertex2f(x, y) swVertex2f((x), (y))
+#define glVertex2fv(v) swVertex2fv((v))
+#define glVertex3i(x, y, z) swVertex3i((x), (y), (z))
+#define glVertex3f(x, y, z) swVertex3f((x), (y), (z))
+#define glvertex3fv(v) swVertex3fv((v))
+#define glVertex4i(x, y, z, w) swVertex4i((x), (y), (z), (w))
+#define glVertex4f(x, y, z, w) swVertex4f((x), (y), (z), (w))
+#define glVertex4fv(v) swVertex4fv((v))
+#define glColor3ub(r, g, b) swColor3ub((r), (g), (b))
+#define glColor3ubv(v) swColor3ubv((v))
+#define glColor3f(r, g, b) swColor3f((r), (g), (b))
+#define glColor3fv(v) swColor3fv((v))
+#define glColor4ub(r, g, b, a) swColor4ub((r), (g), (b), (a))
+#define glColor4ubv(v) swColor4ubv((v))
+#define glColor4f(r, g, b, a) swColor4f((r), (g), (b), (a))
+#define glColor4fv(v) swColor4fv((v))
+#define glTexCoord2f(u, v) swTexCoord2f((u), (v))
+#define glTexCoord2fv(v) swTexCoord2fv((v))
+
+#define glEnableClientState(t) ((void)(t))
+#define glDisableClientState(t) swBindArray((t), 0)
+#define glVertexPointer(sz, t, s, p) swBindArray(SW_VERTEX_ARRAY, (p))
+#define glTexCoordPointer(sz, t, s, p) swBindArray(SW_TEXTURE_COORD_ARRAY, (p))
+#define glColorPointer(sz, t, s, p) swBindArray(SW_COLOR_ARRAY, (p))
+#define glDrawArrays(m, o, c) swDrawArrays((m), (o), (c))
+#define glGenTextures(c, v) swGenTextures((c), (v))
+#define glDeleteTextures(c, v) swDeleteTextures((c), (v))
+#define glTexImage2D(tr, l, if, w, h, b, f, t, p) swTexImage2D((w), (h), (f), (t), SW_GL_BINDING_COPY_TEXTURE, (p))
+#define glTexParameteri(tr, pname, param) swTexParameteri((pname), (param))
+#define glBindTexture(tr, id) swBindTexture((id))
+
+// OpenGL functions NOT IMPLEMENTED by rlsw
+#define glClearDepth(X) ((void)(X))
+#define glDepthMask(X) ((void)(X))
+#define glColorMask(X,Y,Z,W) ((void)(X),(void)(Y),(void)(Z),(void)(W))
+#define glPixelStorei(X,Y) ((void)(X),(void)(Y))
+#define glHint(X,Y) ((void)(X),(void)(Y))
+#define glShadeModel(X) ((void)(X))
+#define glFrontFace(X) ((void)(X))
+#define glDepthFunc(X) ((void)(X))
+#define glTexSubImage2D(X,Y,Z,W,A,B,C,D,E) ((void)(X),(void)(Y),(void)(Z),(void)(W),(void)(A),(void)(B),(void)(C),(void)(D),(void)(E))
+#define glGetTexImage(X,Y,Z,W,A) ((void)(X),(void)(Y),(void)(Z),(void)(W),(void)(A))
+#define glDrawElements(X,Y,Z,W) ((void)(X),(void)(Y),(void)(Z),(void)(W))
+#define glNormal3f(X,Y,Z) ((void)(X),(void)(Y),(void)(Z))
+#define glNormal3fv(X) ((void)(X))
+#define glNormalPointer(X,Y,Z) ((void)(X),(void)(Y),(void)(Z))
+
+//----------------------------------------------------------------------------------
+// Types and Structures Definition
+//----------------------------------------------------------------------------------
+typedef enum {
+ SW_SCISSOR_TEST = GL_SCISSOR_TEST,
+ SW_TEXTURE_2D = GL_TEXTURE_2D,
+ SW_DEPTH_TEST = GL_DEPTH_TEST,
+ SW_CULL_FACE = GL_CULL_FACE,
+ SW_BLEND = GL_BLEND
+} SWstate;
+
+typedef enum {
+ SW_VENDOR = GL_VENDOR,
+ SW_RENDERER = GL_RENDERER,
+ SW_VERSION = GL_VERSION,
+ SW_EXTENSIONS = GL_EXTENSIONS,
+ SW_COLOR_CLEAR_VALUE = GL_COLOR_CLEAR_VALUE,
+ SW_CURRENT_COLOR = GL_CURRENT_COLOR,
+ SW_CURRENT_TEXTURE_COORDS = GL_CURRENT_TEXTURE_COORDS,
+ SW_POINT_SIZE = GL_POINT_SIZE,
+ SW_LINE_WIDTH = GL_LINE_WIDTH,
+ SW_MODELVIEW_MATRIX = GL_MODELVIEW_MATRIX,
+ SW_MODELVIEW_STACK_DEPTH = GL_MODELVIEW_STACK_DEPTH,
+ SW_PROJECTION_MATRIX = GL_PROJECTION_MATRIX,
+ SW_PROJECTION_STACK_DEPTH = GL_PROJECTION_STACK_DEPTH,
+ SW_TEXTURE_MATRIX = GL_TEXTURE_MATRIX,
+ SW_TEXTURE_STACK_DEPTH = GL_TEXTURE_STACK_DEPTH,
+ SW_VIEWPORT = GL_VIEWPORT
+} SWget;
+
+typedef enum {
+ SW_COLOR_BUFFER_BIT = GL_COLOR_BUFFER_BIT,
+ SW_DEPTH_BUFFER_BIT = GL_DEPTH_BUFFER_BIT
+} SWbuffer;
+
+typedef enum {
+ SW_PROJECTION = GL_PROJECTION,
+ SW_MODELVIEW = GL_MODELVIEW,
+ SW_TEXTURE = GL_TEXTURE
+} SWmatrix;
+
+typedef enum {
+ SW_VERTEX_ARRAY = GL_VERTEX_ARRAY,
+ SW_TEXTURE_COORD_ARRAY = GL_TEXTURE_COORD_ARRAY,
+ SW_COLOR_ARRAY = GL_COLOR_ARRAY
+} SWarray;
+
+typedef enum {
+ SW_POINTS = GL_POINTS,
+ SW_LINES = GL_LINES,
+ SW_TRIANGLES = GL_TRIANGLES,
+ SW_QUADS = GL_QUADS
+} SWdraw;
+
+typedef enum {
+ SW_POINT = GL_POINT,
+ SW_LINE = GL_LINE,
+ SW_FILL = GL_FILL
+} SWpoly;
+
+typedef enum {
+ SW_FRONT = GL_FRONT,
+ SW_BACK = GL_BACK,
+} SWface;
+
+typedef enum {
+ SW_ZERO = GL_ZERO,
+ SW_ONE = GL_ONE,
+ SW_SRC_COLOR = GL_SRC_COLOR,
+ SW_ONE_MINUS_SRC_COLOR = GL_ONE_MINUS_SRC_COLOR,
+ SW_SRC_ALPHA = GL_SRC_ALPHA,
+ SW_ONE_MINUS_SRC_ALPHA = GL_ONE_MINUS_SRC_ALPHA,
+ SW_DST_ALPHA = GL_DST_ALPHA,
+ SW_ONE_MINUS_DST_ALPHA = GL_ONE_MINUS_DST_ALPHA,
+ SW_DST_COLOR = GL_DST_COLOR,
+ SW_ONE_MINUS_DST_COLOR = GL_ONE_MINUS_DST_COLOR,
+ SW_SRC_ALPHA_SATURATE = GL_SRC_ALPHA_SATURATE
+} SWfactor;
+
+typedef enum {
+ SW_LUMINANCE = GL_LUMINANCE,
+ SW_LUMINANCE_ALPHA = GL_LUMINANCE_ALPHA,
+ SW_RGB = GL_RGB,
+ SW_RGBA = GL_RGBA,
+} SWformat;
+
+typedef enum {
+ SW_UNSIGNED_BYTE = GL_UNSIGNED_BYTE,
+ SW_BYTE = GL_BYTE,
+ SW_UNSIGNED_SHORT = GL_UNSIGNED_SHORT,
+ SW_SHORT = GL_SHORT,
+ SW_UNSIGNED_INT = GL_UNSIGNED_INT,
+ SW_INT = GL_INT,
+ SW_FLOAT = GL_FLOAT
+} SWtype;
+
+typedef enum {
+ SW_NEAREST = GL_NEAREST,
+ SW_LINEAR = GL_LINEAR
+} SWfilter;
+
+typedef enum {
+ SW_REPEAT = GL_REPEAT,
+ SW_CLAMP = GL_CLAMP,
+} SWwrap;
+
+typedef enum {
+ SW_TEXTURE_MIN_FILTER = GL_TEXTURE_MIN_FILTER,
+ SW_TEXTURE_MAG_FILTER = GL_TEXTURE_MAG_FILTER,
+ SW_TEXTURE_WRAP_S = GL_TEXTURE_WRAP_S,
+ SW_TEXTURE_WRAP_T = GL_TEXTURE_WRAP_T
+} SWtexparam;
+
+typedef enum {
+ SW_NO_ERROR = GL_NO_ERROR,
+ SW_INVALID_ENUM = GL_INVALID_ENUM,
+ SW_INVALID_VALUE = GL_INVALID_VALUE,
+ SW_STACK_OVERFLOW = GL_STACK_OVERFLOW,
+ SW_STACK_UNDERFLOW = GL_STACK_UNDERFLOW,
+ SW_INVALID_OPERATION = GL_INVALID_OPERATION,
+} SWerrcode;
+
+//------------------------------------------------------------------------------------
+// Functions Declaration - Public API
+//------------------------------------------------------------------------------------
+SWAPI bool swInit(int w, int h);
+SWAPI void swClose(void);
+
+SWAPI bool swResizeFramebuffer(int w, int h);
+SWAPI void swCopyFramebuffer(int x, int y, int w, int h, SWformat format, SWtype type, void *pixels);
+SWAPI void swBlitFramebuffer(int xDst, int yDst, int wDst, int hDst, int xSrc, int ySrc, int wSrc, int hSrc, SWformat format, SWtype type, void *pixels);
+SWAPI void *swGetColorBuffer(int *w, int *h);
+
+SWAPI void swEnable(SWstate state);
+SWAPI void swDisable(SWstate state);
+
+SWAPI void swGetFloatv(SWget name, float *v);
+SWAPI const char *swGetString(SWget name);
+SWAPI SWerrcode swGetError(void);
+
+SWAPI void swViewport(int x, int y, int width, int height);
+SWAPI void swScissor(int x, int y, int width, int height);
+
+SWAPI void swClearColor(float r, float g, float b, float a);
+SWAPI void swClear(uint32_t bitmask);
+
+SWAPI void swBlendFunc(SWfactor sfactor, SWfactor dfactor);
+SWAPI void swPolygonMode(SWpoly mode);
+SWAPI void swCullFace(SWface face);
+
+SWAPI void swPointSize(float size);
+SWAPI void swLineWidth(float width);
+
+SWAPI void swMatrixMode(SWmatrix mode);
+SWAPI void swPushMatrix(void);
+SWAPI void swPopMatrix(void);
+SWAPI void swLoadIdentity(void);
+SWAPI void swTranslatef(float x, float y, float z);
+SWAPI void swRotatef(float angle, float x, float y, float z);
+SWAPI void swScalef(float x, float y, float z);
+SWAPI void swMultMatrixf(const float *mat);
+SWAPI void swFrustum(double left, double right, double bottom, double top, double znear, double zfar);
+SWAPI void swOrtho(double left, double right, double bottom, double top, double znear, double zfar);
+
+SWAPI void swBegin(SWdraw mode);
+SWAPI void swEnd(void);
+
+SWAPI void swVertex2i(int x, int y);
+SWAPI void swVertex2f(float x, float y);
+SWAPI void swVertex2fv(const float *v);
+SWAPI void swVertex3i(int x, int y, int z);
+SWAPI void swVertex3f(float x, float y, float z);
+SWAPI void swVertex3fv(const float *v);
+SWAPI void swVertex4i(int x, int y, int z, int w);
+SWAPI void swVertex4f(float x, float y, float z, float w);
+SWAPI void swVertex4fv(const float *v);
+
+SWAPI void swColor3ub(uint8_t r, uint8_t g, uint8_t b);
+SWAPI void swColor3ubv(const uint8_t *v);
+SWAPI void swColor3f(float r, float g, float b);
+SWAPI void swColor3fv(const float *v);
+SWAPI void swColor4ub(uint8_t r, uint8_t g, uint8_t b, uint8_t a);
+SWAPI void swColor4ubv(const uint8_t *v);
+SWAPI void swColor4f(float r, float g, float b, float a);
+SWAPI void swColor4fv(const float *v);
+
+SWAPI void swTexCoord2f(float u, float v);
+SWAPI void swTexCoord2fv(const float *v);
+
+SWAPI void swBindArray(SWarray type, void *buffer);
+SWAPI void swDrawArrays(SWdraw mode, int offset, int count);
+
+SWAPI void swGenTextures(int count, uint32_t *textures);
+SWAPI void swDeleteTextures(int count, uint32_t *textures);
+
+SWAPI void swTexImage2D(int width, int height, SWformat format, SWtype type, bool copy, const void *data);
+SWAPI void swTexParameteri(int param, int value);
+SWAPI void swBindTexture(uint32_t id);
+
+#endif // RLSW_H
+
+/***********************************************************************************
+*
+* RLSW IMPLEMENTATION
+*
+************************************************************************************/
+#define RLSW_IMPLEMENTATION
+#if defined(RLSW_IMPLEMENTATION)
+
+#include
+#include
+#include // Required for: floorf(), fabsf()
+
+//----------------------------------------------------------------------------------
+// Defines and Macros
+//----------------------------------------------------------------------------------
+#define SW_PI 3.14159265358979323846f
+#define SW_DEG2RAD (SW_PI/180.0f)
+#define SW_RAD2DEG (180.0f/SW_PI)
+
+#define SW_COLOR_PIXEL_SIZE (SW_COLOR_BUFFER_BITS/8)
+#define SW_DEPTH_PIXEL_SIZE (SW_DEPTH_BUFFER_BITS/8)
+
+#define SW_STATE_CHECK(flags) ((RLSW.stateFlags & (flags)) == (flags))
+
+#define SW_STATE_SCISSOR_TEST (1 << 0)
+#define SW_STATE_TEXTURE_2D (1 << 1)
+#define SW_STATE_DEPTH_TEST (1 << 2)
+#define SW_STATE_CULL_FACE (1 << 3)
+#define SW_STATE_BLEND (1 << 4)
+
+//----------------------------------------------------------------------------------
+// Module Types and Structures Definition
+//----------------------------------------------------------------------------------
+// Pixel data format type
+// NOTE: Enum aligned with raylib PixelFormat
+typedef enum {
+ SW_PIXELFORMAT_UNKNOWN = 0,
+ SW_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE, // 8 bit per pixel (no alpha)
+ SW_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA, // 8*2 bpp (2 channels)
+ SW_PIXELFORMAT_UNCOMPRESSED_R5G6B5, // 16 bpp
+ SW_PIXELFORMAT_UNCOMPRESSED_R8G8B8, // 24 bpp
+ SW_PIXELFORMAT_UNCOMPRESSED_R5G5B5A1, // 16 bpp (1 bit alpha)
+ SW_PIXELFORMAT_UNCOMPRESSED_R4G4B4A4, // 16 bpp (4 bit alpha)
+ SW_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, // 32 bpp
+ SW_PIXELFORMAT_UNCOMPRESSED_R32, // 32 bpp (1 channel - float)
+ SW_PIXELFORMAT_UNCOMPRESSED_R32G32B32, // 32*3 bpp (3 channels - float)
+ SW_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32, // 32*4 bpp (4 channels - float)
+ SW_PIXELFORMAT_UNCOMPRESSED_R16, // 16 bpp (1 channel - half float)
+ SW_PIXELFORMAT_UNCOMPRESSED_R16G16B16, // 16*3 bpp (3 channels - half float)
+ SW_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16, // 16*4 bpp (4 channels - half float)
+} sw_pixelformat_t;
+
+typedef void (*sw_factor_f)(
+ float *SW_RESTRICT factor,
+ const float *SW_RESTRICT src,
+ const float *SW_RESTRICT dst
+);
+
+typedef float sw_matrix_t[4*4];
+typedef uint16_t sw_half_t;
+
+typedef struct {
+ float position[4]; // Position coordinates
+ float texcoord[2]; // Texture coordinates
+ float color[4]; // Color value (RGBA)
+
+ float homogeneous[4]; // Homogeneous coordinates
+ float screen[2]; // Screen coordinates
+} sw_vertex_t;
+
+typedef struct {
+ // Dirty hack for copied data
+ // TODO: Rework copied image handling
+ union {
+ const void *cptr; // NOTE: Is used for all data reads
+ void *ptr; // WARNING: Should only be used to allocate and free data
+ } pixels;
+
+ int width, height; // Dimensions of the texture
+ int wMinus1, hMinus1; // Dimensions minus one
+ sw_pixelformat_t format; // Pixel format (internal representation)
+
+ SWfilter minFilter; // Minification filter
+ SWfilter magFilter; // Magnification filter
+
+ SWwrap sWrap; // texcoord.x wrap mode
+ SWwrap tWrap; // texcoord.y wrap mode
+
+ float tx; // Texel width
+ float ty; // Texel height
+
+ bool copy; // Flag indicating whether memory has been allocated
+
+} sw_texture_t;
+
+typedef struct {
+ void *color;
+ void *depth;
+ int width;
+ int height;
+ int allocSz;
+} sw_framebuffer_t;
+
+typedef struct {
+ sw_framebuffer_t framebuffer; // Main framebuffer
+ float clearColor[4]; // Color used to clear the screen
+ float clearDepth; // Depth value used to clear the screen
+
+ int vpCenter[2]; // Viewport center
+ int vpHalfSize[2]; // Viewport half dimensions
+ int vpSize[2]; // Viewport dimensions (minus one)
+ int vpMin[2]; // Viewport minimum renderable point (top-left)
+ int vpMax[2]; // Viewport maximum renderable point (bottom-right)
+
+ int scMin[2]; // Scissor rectangle minimum renderable point (top-left)
+ int scMax[2]; // Scissor rectangle maximum renderable point (bottom-right)
+ float scClipMin[2]; // Scissor rectangle minimum renderable point in clip space
+ float scClipMax[2]; // Scissor rectangle maximum renderable point in clip space
+
+ uint32_t currentTexture; // Current active texture id
+
+ struct {
+ float *positions;
+ float *texcoords;
+ uint8_t *colors;
+ } array;
+
+ struct {
+ float texcoord[2];
+ float color[4];
+ } current;
+
+ sw_vertex_t vertexBuffer[SW_MAX_CLIPPED_POLYGON_VERTICES]; // Buffer used for storing primitive vertices, used for processing and rendering
+ int vertexCounter; // Number of vertices in 'ctx.vertexBuffer'
+
+ SWdraw drawMode; // Current primitive mode (e.g., lines, triangles)
+ SWpoly polyMode; // Current polygon filling mode (e.g., lines, triangles)
+ int reqVertices; // Number of vertices required for the primitive being drawn
+ float pointRadius; // Rasterized point radius
+ float lineWidth; // Rasterized line width
+
+ sw_matrix_t stackProjection[SW_MAX_PROJECTION_STACK_SIZE]; // Projection matrix stack for push/pop operations
+ sw_matrix_t stackModelview[SW_MAX_MODELVIEW_STACK_SIZE]; // Modelview matrix stack for push/pop operations
+ sw_matrix_t stackTexture[SW_MAX_TEXTURE_STACK_SIZE]; // Texture matrix stack for push/pop operations
+ uint32_t stackProjectionCounter; // Counter for matrix stack operations
+ uint32_t stackModelviewCounter; // Counter for matrix stack operations
+ uint32_t stackTextureCounter; // Counter for matrix stack operations
+ SWmatrix currentMatrixMode; // Current matrix mode (e.g., sw_MODELVIEW, sw_PROJECTION)
+ sw_matrix_t *currentMatrix; // Pointer to the currently used matrix according to the mode
+ sw_matrix_t matMVP; // Model view projection matrix, calculated and used internally
+ bool isDirtyMVP; // Indicates if the MVP matrix should be rebuilt
+
+ SWfactor srcFactor;
+ SWfactor dstFactor;
+
+ sw_factor_f srcFactorFunc;
+ sw_factor_f dstFactorFunc;
+
+ SWface cullFace; // Faces to cull
+ SWerrcode errCode; // Last error code
+
+ sw_texture_t *loadedTextures;
+ int loadedTextureCount;
+
+ uint32_t *freeTextureIds;
+ int freeTextureIdCount;
+
+ uint32_t stateFlags;
+
+} sw_context_t;
+
+//----------------------------------------------------------------------------------
+// Global Variables Definition
+//----------------------------------------------------------------------------------
+static sw_context_t RLSW = { 0 };
+
+//----------------------------------------------------------------------------------
+// Module Functions Declaration
+//----------------------------------------------------------------------------------
+static inline void sw_matrix_id(sw_matrix_t dst)
+{
+ dst[0] = 1, dst[1] = 0, dst[2] = 0, dst[3] = 0;
+ dst[4] = 0, dst[5] = 1, dst[6] = 0, dst[7] = 0;
+ dst[8] = 0, dst[9] = 0, dst[10] = 1, dst[11] = 0;
+ dst[12] = 0, dst[13] = 0, dst[14] = 0, dst[15] = 1;
+}
+
+static inline void sw_matrix_mul_rst(float *SW_RESTRICT dst, const float *SW_RESTRICT left, const float *SW_RESTRICT right)
+{
+ float l00 = left[0], l01 = left[1], l02 = left[2], l03 = left[3];
+ float l10 = left[4], l11 = left[5], l12 = left[6], l13 = left[7];
+ float l20 = left[8], l21 = left[9], l22 = left[10], l23 = left[11];
+ float l30 = left[12], l31 = left[13], l32 = left[14], l33 = left[15];
+
+ dst[0] = l00*right[0] + l01*right[4] + l02*right[8] + l03*right[12];
+ dst[4] = l10*right[0] + l11*right[4] + l12*right[8] + l13*right[12];
+ dst[8] = l20*right[0] + l21*right[4] + l22*right[8] + l23*right[12];
+ dst[12] = l30*right[0] + l31*right[4] + l32*right[8] + l33*right[12];
+
+ dst[1] = l00*right[1] + l01*right[5] + l02*right[9] + l03*right[13];
+ dst[5] = l10*right[1] + l11*right[5] + l12*right[9] + l13*right[13];
+ dst[9] = l20*right[1] + l21*right[5] + l22*right[9] + l23*right[13];
+ dst[13] = l30*right[1] + l31*right[5] + l32*right[9] + l33*right[13];
+
+ dst[2] = l00*right[2] + l01*right[6] + l02*right[10] + l03*right[14];
+ dst[6] = l10*right[2] + l11*right[6] + l12*right[10] + l13*right[14];
+ dst[10] = l20*right[2] + l21*right[6] + l22*right[10] + l23*right[14];
+ dst[14] = l30*right[2] + l31*right[6] + l32*right[10] + l33*right[14];
+
+ dst[3] = l00*right[3] + l01*right[7] + l02*right[11] + l03*right[15];
+ dst[7] = l10*right[3] + l11*right[7] + l12*right[11] + l13*right[15];
+ dst[11] = l20*right[3] + l21*right[7] + l22*right[11] + l23*right[15];
+ dst[15] = l30*right[3] + l31*right[7] + l32*right[11] + l33*right[15];
+}
+
+static inline void sw_matrix_mul(sw_matrix_t dst, const sw_matrix_t left, const sw_matrix_t right)
+{
+ float result[16];
+
+ sw_matrix_mul_rst(result, left, right);
+
+ for (int i = 0; i < 16; i++) dst[i] = result[i];
+}
+
+static inline float sw_saturate(float x)
+{
+ union { float f; uint32_t u; } fb;
+ fb.f = x;
+
+ // Check if x < 0.0f
+ // If sign bit is set (MSB), x is negative
+ if ((fb.u & 0x80000000) != 0) return 0.0f;
+
+ // Check if x > 1.0f
+ // Works for positive floats: IEEE 754 ordering matches integer ordering
+ if (fb.u > 0x3F800000) return 1.0f;
+
+ // x is in [0.0f, 1.0f]
+ return x;
+}
+
+static inline float sw_fract(float x)
+{
+ return (x - floorf(x));
+}
+
+static inline int sw_clampi(int v, int min, int max)
+{
+ if (v < min) return min;
+ if (v > max) return max;
+ return v;
+}
+
+static inline void sw_lerp_vertex_PTCH(
+ sw_vertex_t *SW_RESTRICT out,
+ const sw_vertex_t *SW_RESTRICT a,
+ const sw_vertex_t *SW_RESTRICT b,
+ float t)
+{
+ const float tInv = 1.0f - t;
+
+ // Position interpolation (4 components)
+ out->position[0] = a->position[0]*tInv + b->position[0]*t;
+ out->position[1] = a->position[1]*tInv + b->position[1]*t;
+ out->position[2] = a->position[2]*tInv + b->position[2]*t;
+ out->position[3] = a->position[3]*tInv + b->position[3]*t;
+
+ // Texture coordinate interpolation (2 components)
+ out->texcoord[0] = a->texcoord[0]*tInv + b->texcoord[0]*t;
+ out->texcoord[1] = a->texcoord[1]*tInv + b->texcoord[1]*t;
+
+ // Color interpolation (4 components)
+ out->color[0] = a->color[0]*tInv + b->color[0]*t;
+ out->color[1] = a->color[1]*tInv + b->color[1]*t;
+ out->color[2] = a->color[2]*tInv + b->color[2]*t;
+ out->color[3] = a->color[3]*tInv + b->color[3]*t;
+
+ // Homogeneous coordinate interpolation (4 components)
+ out->homogeneous[0] = a->homogeneous[0]*tInv + b->homogeneous[0]*t;
+ out->homogeneous[1] = a->homogeneous[1]*tInv + b->homogeneous[1]*t;
+ out->homogeneous[2] = a->homogeneous[2]*tInv + b->homogeneous[2]*t;
+ out->homogeneous[3] = a->homogeneous[3]*tInv + b->homogeneous[3]*t;
+}
+
+static inline void sw_get_vertex_grad_PTCH(
+ sw_vertex_t *SW_RESTRICT out,
+ const sw_vertex_t *SW_RESTRICT a,
+ const sw_vertex_t *SW_RESTRICT b,
+ float scale)
+{
+ // Calculate gradients for Position
+ out->position[0] = (b->position[0] - a->position[0])*scale;
+ out->position[1] = (b->position[1] - a->position[1])*scale;
+ out->position[2] = (b->position[2] - a->position[2])*scale;
+ out->position[3] = (b->position[3] - a->position[3])*scale;
+
+ // Calculate gradients for Texture coordinates
+ out->texcoord[0] = (b->texcoord[0] - a->texcoord[0])*scale;
+ out->texcoord[1] = (b->texcoord[1] - a->texcoord[1])*scale;
+
+ // Calculate gradients for Color
+ out->color[0] = (b->color[0] - a->color[0])*scale;
+ out->color[1] = (b->color[1] - a->color[1])*scale;
+ out->color[2] = (b->color[2] - a->color[2])*scale;
+ out->color[3] = (b->color[3] - a->color[3])*scale;
+
+ // Calculate gradients for Homogeneous coordinates
+ out->homogeneous[0] = (b->homogeneous[0] - a->homogeneous[0])*scale;
+ out->homogeneous[1] = (b->homogeneous[1] - a->homogeneous[1])*scale;
+ out->homogeneous[2] = (b->homogeneous[2] - a->homogeneous[2])*scale;
+ out->homogeneous[3] = (b->homogeneous[3] - a->homogeneous[3])*scale;
+}
+
+static inline void sw_add_vertex_grad_PTCH(
+ sw_vertex_t *SW_RESTRICT out,
+ const sw_vertex_t *SW_RESTRICT gradients)
+{
+ // Add gradients to Position
+ out->position[0] += gradients->position[0];
+ out->position[1] += gradients->position[1];
+ out->position[2] += gradients->position[2];
+ out->position[3] += gradients->position[3];
+
+ // Add gradients to Texture coordinates
+ out->texcoord[0] += gradients->texcoord[0];
+ out->texcoord[1] += gradients->texcoord[1];
+
+ // Add gradients to Color
+ out->color[0] += gradients->color[0];
+ out->color[1] += gradients->color[1];
+ out->color[2] += gradients->color[2];
+ out->color[3] += gradients->color[3];
+
+ // Add gradients to Homogeneous coordinates
+ out->homogeneous[0] += gradients->homogeneous[0];
+ out->homogeneous[1] += gradients->homogeneous[1];
+ out->homogeneous[2] += gradients->homogeneous[2];
+ out->homogeneous[3] += gradients->homogeneous[3];
+}
+
+// Half floating point management functions
+static inline uint32_t sw_f16_to_f32_ui(uint16_t h)
+{
+ uint32_t s = (uint32_t)(h & 0x8000) << 16;
+ int32_t em = h & 0x7fff;
+
+ // bias exponent and pad mantissa with 0; 112 is relative exponent bias (127-15)
+ int32_t r = (em + (112 << 10)) << 13;
+
+ // denormal: flush to zero
+ r = (em < (1 << 10))? 0 : r;
+
+ // infinity/NaN; note that we preserve NaN payload as a byproduct of unifying inf/nan cases
+ // 112 is an exponent bias fixup; since we already applied it once, applying it twice converts 31 to 255
+ r += (em >= (31 << 10))? (112 << 23) : 0;
+
+ return s | r;
+}
+
+static inline float sw_f16_to_f32(sw_half_t y)
+{
+ union { float f; uint32_t i; } v = { .i = sw_f16_to_f32_ui(y) };
+
+ return v.f;
+}
+
+static inline uint16_t sw_f16_from_f32_ui(uint32_t ui)
+{
+ int32_t s = (ui >> 16) & 0x8000;
+ int32_t em = ui & 0x7fffffff;
+
+ // Bias exponent and round to nearest; 112 is relative exponent bias (127-15)
+ int32_t h = (em - (112 << 23) + (1 << 12)) >> 13;
+
+ // Underflow: flush to zero; 113 encodes exponent -14
+ h = (em < (113 << 23))? 0 : h;
+
+ // Overflow: infinity; 143 encodes exponent 16
+ h = (em >= (143 << 23))? 0x7c00 : h;
+
+ // NaN; note that we convert all types of NaN to qNaN
+ h = (em > (255 << 23))? 0x7e00 : h;
+
+ return (uint16_t)(s | h);
+}
+
+static inline sw_half_t sw_f16_from_f32(float i)
+{
+ union { float f; uint32_t i; } v;
+ v.f = i;
+ return sw_f16_from_f32_ui(v.i);
+}
+
+// Framebuffer management functions
+static inline bool sw_framebuffer_load(int w, int h)
+{
+ int size = w*h;
+
+ RLSW.framebuffer.color = SW_MALLOC(SW_COLOR_PIXEL_SIZE*size);
+ if (RLSW.framebuffer.color == NULL) return false;
+
+ RLSW.framebuffer.depth = SW_MALLOC(SW_DEPTH_PIXEL_SIZE*size);
+ if (RLSW.framebuffer.depth == NULL) return false;
+
+ RLSW.framebuffer.width = w;
+ RLSW.framebuffer.height = h;
+ RLSW.framebuffer.allocSz = size;
+
+ return true;
+}
+
+static inline bool sw_framebuffer_resize(int w, int h)
+{
+ int newSize = w*h;
+
+ if (newSize <= RLSW.framebuffer.allocSz)
+ {
+ RLSW.framebuffer.width = w;
+ RLSW.framebuffer.height = h;
+ return true;
+ }
+
+ void *newColor = SW_REALLOC(RLSW.framebuffer.color, newSize);
+ if (newColor == NULL) return false;
+
+ void *newDepth = SW_REALLOC(RLSW.framebuffer.depth, newSize);
+ if (newDepth == NULL) return false;
+
+ RLSW.framebuffer.color = newColor;
+ RLSW.framebuffer.depth = newDepth;
+
+ RLSW.framebuffer.width = w;
+ RLSW.framebuffer.height = h;
+ RLSW.framebuffer.allocSz = newSize;
+
+ return true;
+}
+
+static inline void *sw_framebuffer_get_color_addr(const void *ptr, uint32_t offset)
+{
+ return (uint8_t *)ptr + offset*SW_COLOR_PIXEL_SIZE;
+}
+
+static inline void sw_framebuffer_inc_color_addr(void **ptr)
+{
+ *ptr = (void *)(((uint8_t *)*ptr) + SW_COLOR_PIXEL_SIZE);
+}
+
+static inline void sw_framebuffer_inc_const_color_addr(const void **ptr)
+{
+ *ptr = (const void *)(((const uint8_t *)*ptr) + SW_COLOR_PIXEL_SIZE);
+}
+
+static inline void *sw_framebuffer_get_depth_addr(const void *ptr, uint32_t offset)
+{
+ return (uint8_t *)ptr + offset*SW_DEPTH_PIXEL_SIZE;
+}
+
+static inline void sw_framebuffer_inc_depth_addr(void* *ptr)
+{
+ *ptr = (void*)(((uint8_t *)*ptr) + SW_DEPTH_PIXEL_SIZE);
+}
+
+#if (SW_COLOR_BUFFER_BITS == 8) // RGB - (3:3:2)
+static inline void sw_framebuffer_read_color(float dst[4], const void *src)
+{
+ uint8_t pixel = ((uint8_t *)src)[0];
+
+ dst[0] = ((pixel >> 5) & 0x07)*(1.0f/7.0f);
+ dst[1] = ((pixel >> 2) & 0x07)*(1.0f/7.0f);
+ dst[2] = (pixel & 0x03)*(1.0f/3.0f);
+ dst[3] = 1.0f;
+}
+
+static inline void sw_framebuffer_read_color8(uint8_t dst[4], const void *src)
+{
+ uint8_t pixel = ((const uint8_t *)src)[0];
+
+ uint8_t r = (pixel >> 5) & 0x07;
+ uint8_t g = (pixel >> 2) & 0x07;
+ uint8_t b = pixel & 0x03;
+
+ dst[0] = (r*255 + 3)/7;
+ dst[1] = (g*255 + 3)/7;
+ dst[2] = (b*255 + 1)/3;
+ dst[3] = 255;
+}
+
+static inline void sw_framebuffer_write_color(void *dst, const float color[3])
+{
+ uint8_t r = ((uint8_t)(color[0]*UINT8_MAX) >> 5) & 0x07;
+ uint8_t g = ((uint8_t)(color[1]*UINT8_MAX) >> 5) & 0x07;
+ uint8_t b = ((uint8_t)(color[2]*UINT8_MAX) >> 6) & 0x03;
+
+ ((uint8_t *)dst)[0] = (r << 5) | (g << 2) | b;
+}
+
+static inline void sw_framebuffer_fill_color(void *ptr, int size, const float color[3])
+{
+ uint8_t r8 = (uint8_t)(color[0]*7.0f + 0.5f);
+ uint8_t g8 = (uint8_t)(color[1]*7.0f + 0.5f);
+ uint8_t b8 = (uint8_t)(color[2]*3.0f + 0.5f);
+
+ uint8_t packedColor = ((r8 & 0x07) << 5) | ((g8 & 0x07) << 2) | (b8 & 0x03);
+
+ uint8_t *p = (uint8_t *)ptr;
+
+ if (RLSW.stateFlags & SW_STATE_SCISSOR_TEST)
+ {
+ int wScissor = RLSW.scMax[0] - RLSW.scMin[0] + 1;
+ for (int y = RLSW.scMin[1]; y <= RLSW.scMax[1]; y++)
+ {
+ uint8_t *curPtr = p + y*RLSW.framebuffer.width + RLSW.scMin[0];
+ for (int xCount = 0; xCount < wScissor; xCount++) *curPtr++ = packedColor;
+ }
+ }
+ else
+ {
+ for (int i = 0; i < size; i++) *p++ = packedColor;
+ }
+}
+
+#elif (SW_COLOR_BUFFER_BITS == 16) // RGB - (5:6:5)
+
+static inline void sw_framebuffer_read_color(float dst[4], const void *src)
+{
+ uint16_t pixel = ((uint16_t *)src)[0];
+
+ dst[0] = ((pixel >> 11) & 0x1F)*(1.0f/31.0f);
+ dst[1] = ((pixel >> 5) & 0x3F)*(1.0f/63.0f);
+ dst[2] = (pixel & 0x1F)*(1.0f/31.0f);
+ dst[3] = 1.0f;
+}
+
+static inline void sw_framebuffer_read_color8(uint8_t dst[4], const void *src)
+{
+ uint16_t pixel = ((const uint16_t *)src)[0];
+
+ uint8_t r = (pixel >> 11) & 0x1F;
+ uint8_t g = (pixel >> 5) & 0x3F;
+ uint8_t b = pixel & 0x1F;
+
+ dst[0] = (r*255 + 15)/31;
+ dst[1] = (g*255 + 31)/63;
+ dst[2] = (b*255 + 15)/31;
+ dst[3] = 255;
+}
+
+static inline void sw_framebuffer_write_color(void *dst, const float color[3])
+{
+ uint8_t r = (uint8_t)(color[0]*31.0f + 0.5f) & 0x1F;
+ uint8_t g = (uint8_t)(color[1]*63.0f + 0.5f) & 0x3F;
+ uint8_t b = (uint8_t)(color[2]*31.0f + 0.5f) & 0x1F;
+
+ ((uint16_t *)dst)[0] = (r << 11) | (g << 5) | b;
+}
+
+static inline void sw_framebuffer_fill_color(void *ptr, int size, const float color[3])
+{
+ uint16_t r16 = (uint16_t)(color[0]*31.0f + 0.5f);
+ uint16_t g_16 = (uint16_t)(color[1]*63.0f + 0.5f);
+ uint16_t b_16 = (uint16_t)(color[2]*31.0f + 0.5f);
+
+ uint16_t packedColor = ((r16 & 0x1F) << 11) | ((g_16 & 0x3F) << 5) | (b_16 & 0x1F);
+
+ uint16_t *p = (uint16_t *)ptr;
+
+ if (RLSW.stateFlags & SW_STATE_SCISSOR_TEST)
+ {
+ int wScissor = RLSW.scMax[0] - RLSW.scMin[0] + 1;
+ for (int y = RLSW.scMin[1]; y <= RLSW.scMax[1]; y++)
+ {
+ uint16_t *curPtr = p + y*RLSW.framebuffer.width + RLSW.scMin[0];
+ for (int xCount = 0; xCount < wScissor; xCount++) *curPtr++ = packedColor;
+ }
+ }
+ else
+ {
+ for (int i = 0; i < size; i++) *p++ = packedColor;
+ }
+}
+
+#elif (SW_COLOR_BUFFER_BITS == 24) // RGB - (8:8:8)
+
+static inline void sw_framebuffer_read_color(float dst[4], const void *src)
+{
+ dst[0] = ((uint8_t *)src)[0]*(1.0f/255.0f);
+ dst[1] = ((uint8_t *)src)[1]*(1.0f/255.0f);
+ dst[2] = ((uint8_t *)src)[2]*(1.0f/255.0f);
+ dst[3] = 1.0f;
+}
+
+static inline void sw_framebuffer_read_color8(uint8_t dst[4], const void *src)
+{
+ dst[0] = ((uint8_t *)src)[0];
+ dst[1] = ((uint8_t *)src)[1];
+ dst[2] = ((uint8_t *)src)[2];
+ dst[3] = 255;
+}
+
+static inline void sw_framebuffer_write_color(void *dst, const float color[3])
+{
+ ((uint8_t *)dst)[0] = (uint8_t)(color[0]*UINT8_MAX);
+ ((uint8_t *)dst)[1] = (uint8_t)(color[1]*UINT8_MAX);
+ ((uint8_t *)dst)[2] = (uint8_t)(color[2]*UINT8_MAX);
+}
+
+static inline void sw_framebuffer_fill_color(void *ptr, int size, const float color[3])
+{
+ uint8_t r = (uint8_t)(color[0]*255.0f);
+ uint8_t g = (uint8_t)(color[1]*255.0f);
+ uint8_t b = (uint8_t)(color[2]*255.0f);
+
+ uint8_t *p = (uint8_t *)ptr;
+
+ if (RLSW.stateFlags & SW_STATE_SCISSOR_TEST)
+ {
+ int wScissor = RLSW.scMax[0] - RLSW.scMin[0] + 1;
+ for (int y = RLSW.scMin[1]; y <= RLSW.scMax[1]; y++)
+ {
+ uint8_t *curPtr = p + 3*(y*RLSW.framebuffer.width + RLSW.scMin[0]);
+ for (int xCount = 0; xCount < wScissor; xCount++)
+ {
+ *curPtr++ = r;
+ *curPtr++ = g;
+ *curPtr++ = b;
+ }
+ }
+ }
+ else
+ {
+ for (int i = 0; i < size; i++)
+ {
+ *p++ = r;
+ *p++ = g;
+ *p++ = b;
+ }
+ }
+}
+
+#endif // SW_COLOR_BUFFER_BITS
+
+#if (SW_DEPTH_BUFFER_BITS == 8)
+
+static inline float sw_framebuffer_read_depth(const void *src)
+{
+ return (float)((uint8_t *)src)[0]*(1.0f/UINT8_MAX);
+}
+
+static inline void sw_framebuffer_write_depth(void *dst, float depth)
+{
+ ((uint8_t *)dst)[0] = (uint8_t)(depth*UINT8_MAX);
+}
+
+static inline void sw_framebuffer_fill_depth(void *ptr, int size, float value)
+{
+ uint8_t d8 = (uint8_t)(value*UINT8_MAX);
+ uint8_t *p = (uint8_t *)ptr;
+
+ if (RLSW.stateFlags & SW_STATE_SCISSOR_TEST)
+ {
+ int wScissor = RLSW.scMax[0] - RLSW.scMin[0] + 1;
+ for (int y = RLSW.scMin[1]; y <= RLSW.scMax[1]; y++)
+ {
+ uint8_t *curPtr = p + y*RLSW.framebuffer.width + RLSW.scMin[0];
+ for (int xCount = 0; xCount < wScissor; xCount++) *curPtr++ = d8;
+ }
+ }
+ else
+ {
+ for (int i = 0; i < size; i++) *p++ = d8;
+ }
+}
+
+#elif (SW_DEPTH_BUFFER_BITS == 16)
+
+static inline float sw_framebuffer_read_depth(const void *src)
+{
+ return (float)((uint16_t *)src)[0]*(1.0f/UINT16_MAX);
+}
+
+static inline void sw_framebuffer_write_depth(void *dst, float depth)
+{
+ ((uint16_t *)dst)[0] = (uint16_t)(depth*UINT16_MAX);
+}
+
+static inline void sw_framebuffer_fill_depth(void *ptr, int size, float value)
+{
+ uint16_t d16 = (uint16_t)(value*UINT16_MAX);
+ uint16_t *p = (uint16_t *)ptr;
+
+ if (RLSW.stateFlags & SW_STATE_SCISSOR_TEST)
+ {
+ int wScissor = RLSW.scMax[0] - RLSW.scMin[0] + 1;
+ for (int y = RLSW.scMin[1]; y <= RLSW.scMax[1]; y++)
+ {
+ uint16_t *curPtr = p + y*RLSW.framebuffer.width + RLSW.scMin[0];
+ for (int xCount = 0; xCount < wScissor; xCount++) *curPtr++ = d16;
+ }
+ }
+ else
+ {
+ for (int i = 0; i < size; i++) *p++ = d16;
+ }
+}
+
+#elif (SW_DEPTH_BUFFER_BITS == 24)
+
+static inline float sw_framebuffer_read_depth(const void *src)
+{
+ uint32_t depth24 = (((uint8_t *)src)[0] << 16) |
+ (((uint8_t *)src)[1] << 8) |
+ ((uint8_t *)src)[2];
+
+ return depth24/(float)0xFFFFFF;
+}
+
+static inline void sw_framebuffer_write_depth(void *dst, float depth)
+{
+ uint32_t depth24 = (uint32_t)(depth*0xFFFFFF);
+
+ ((uint8_t *)dst)[0] = (depth24 >> 16) & 0xFF;
+ ((uint8_t *)dst)[1] = (depth24 >> 8) & 0xFF;
+ ((uint8_t *)dst)[2] = depth24 & 0xFF;
+}
+
+static inline void sw_framebuffer_fill_depth(void *ptr, int size, float value)
+{
+ uint32_t d32 = (uint32_t)(value*UINT32_MAX);
+ uint8_t d_byte0 = (uint8_t)((d32 >> 16) & 0xFF);
+ uint8_t d_byte1 = (uint8_t)((d32 >> 8) & 0xFF);
+ uint8_t d_byte2 = (uint8_t)(d32 & 0xFF);
+
+ uint8_t *p = (uint8_t *)ptr;
+
+ if (RLSW.stateFlags & SW_STATE_SCISSOR_TEST)
+ {
+ int wScissor = RLSW.scMax[0] - RLSW.scMin[0] + 1;
+ for (int y = RLSW.scMin[1]; y <= RLSW.scMax[1]; y++)
+ {
+ uint8_t *curPtr = p + 3*(y*RLSW.framebuffer.width + RLSW.scMin[0]);
+ for (int xCount = 0; xCount < wScissor; xCount++)
+ {
+ *curPtr++ = d_byte0;
+ *curPtr++ = d_byte1;
+ *curPtr++ = d_byte2;
+ }
+ }
+ }
+ else
+ {
+ for (int i = 0; i < size; i++)
+ {
+ *p++ = d_byte0;
+ *p++ = d_byte1;
+ *p++ = d_byte2;
+ }
+ }
+}
+
+#endif // SW_DEPTH_BUFFER_BITS
+
+static inline void sw_framebuffer_fill(void *colorPtr, void *depthPtr, int size, float color[4], float depth_value)
+{
+#if (SW_COLOR_BUFFER_BITS == 8)
+ // Calculate and pack 3:3:2 color
+ // Scale color components to the max value for each bit depth and round
+ uint8_t r8 = (uint8_t)(color[0]*7.0f + 0.5f);
+ uint8_t g8 = (uint8_t)(color[1]*7.0f + 0.5f);
+ uint8_t b8 = (uint8_t)(color[2]*3.0f + 0.5f);
+ // Pack the components into a single byte
+ uint8_t packedColor = ((r8 & 0x07) << 5) | ((g8 & 0x07) << 2) | (b8 & 0x03);
+ uint8_t *cptr = (uint8_t *)colorPtr;
+#elif (SW_COLOR_BUFFER_BITS == 16)
+ // Calculate and pack 5:6:5 color
+ // Scale color components to the max value for each bit depth and round
+ uint16_t r16 = (uint16_t)(color[0]*31.0f + 0.5f);
+ uint16_t g16 = (uint16_t)(color[1]*63.0f + 0.5f);
+ uint16_t b16 = (uint16_t)(color[2]*31.0f + 0.5f);
+ // Pack the components into a 16-bit value
+ uint16_t packedColor = ((r16 & 0x1F) << 11) | ((g16 & 0x3F) << 5) | (b16 & 0x1F);
+ uint16_t *cptr = (uint16_t *)colorPtr;
+#elif (SW_COLOR_BUFFER_BITS == 24)
+ // Calculate 8:8:8 color components
+ uint8_t r24 = (uint8_t)(color[0]*255.0f);
+ uint8_t g24 = (uint8_t)(color[1]*255.0f);
+ uint8_t b24 = (uint8_t)(color[2]*255.0f);
+ uint8_t *cptr = (uint8_t *)colorPtr;
+#endif
+
+#if (SW_DEPTH_BUFFER_BITS == 8)
+ // Calculate 8-bit depth
+ uint8_t d8 = (uint8_t)(depth_value*UINT8_MAX);
+ uint8_t *dptr = (uint8_t *)depthPtr;
+#elif (SW_DEPTH_BUFFER_BITS == 16)
+ // Calculate 16-bit depth
+ uint16_t d16 = (uint16_t)(depth_value*UINT16_MAX);
+ uint16_t *dptr = (uint16_t *)depthPtr;
+#elif (SW_DEPTH_BUFFER_BITS == 24)
+ // Calculate 24-bit depth and pre-calculate bytes
+ uint32_t d32 = (uint32_t)(depth_value*UINT32_MAX);
+ uint8_t dByte0 = (uint8_t)((d32 >> 16) & 0xFF);
+ uint8_t dByte1 = (uint8_t)((d32 >> 8) & 0xFF);
+ uint8_t dByte2 = (uint8_t)(d32 & 0xFF);
+ uint8_t *dptr = (uint8_t *)depthPtr;
+#endif
+
+ if (RLSW.stateFlags & SW_STATE_SCISSOR_TEST)
+ {
+ int wScissor = RLSW.scMax[0] - RLSW.scMin[0] + 1;
+ for (int y = RLSW.scMin[1]; y <= RLSW.scMax[1]; y++)
+ {
+ int rowStartIdx = y*RLSW.framebuffer.width + RLSW.scMin[0];
+
+ // Calculate starting pointers for the current row within the scissor rectangle
+ #if (SW_COLOR_BUFFER_BITS == 8)
+ uint8_t *curCPtr = cptr + rowStartIdx;
+ #elif (SW_COLOR_BUFFER_BITS == 16)
+ uint16_t *curCPtr = cptr + rowStartIdx;
+ #elif (SW_COLOR_BUFFER_BITS == 24)
+ uint8_t *curCPtr = cptr + 3*rowStartIdx;
+ #endif
+
+ #if (SW_DEPTH_BUFFER_BITS == 8)
+ uint8_t *curDPtr = dptr + rowStartIdx;
+ #elif (SW_DEPTH_BUFFER_BITS == 16)
+ uint16_t *curDPtr = dptr + rowStartIdx;
+ #elif (SW_DEPTH_BUFFER_BITS == 24)
+ uint8_t *curDPtr = dptr + 3*rowStartIdx;
+ #endif
+
+ // Fill the current row within the scissor rectangle
+ for (int xCount = 0; xCount < wScissor; xCount++)
+ {
+ // Write color
+ #if (SW_COLOR_BUFFER_BITS == 8)
+ *curCPtr++ = packedColor;
+ #elif (SW_COLOR_BUFFER_BITS == 16)
+ *curCPtr++ = packedColor;
+ #elif (SW_COLOR_BUFFER_BITS == 24)
+ *curCPtr++ = r24;
+ *curCPtr++ = g24;
+ *curCPtr++ = b24;
+ #endif
+
+ // Write depth
+ #if (SW_DEPTH_BUFFER_BITS == 8)
+ *curDPtr++ = d8;
+ #elif (SW_DEPTH_BUFFER_BITS == 16)
+ *curDPtr++ = d16;
+ #elif (SW_DEPTH_BUFFER_BITS == 24)
+ *curDPtr++ = dByte0;
+ *curDPtr++ = dByte1;
+ *curDPtr++ = dByte2;
+ #endif
+ }
+ }
+ return;
+ }
+
+ for (int i = 0; i < size; i++)
+ {
+ // Write color
+ #if (SW_COLOR_BUFFER_BITS == 8)
+ *cptr++ = packedColor;
+ #elif (SW_COLOR_BUFFER_BITS == 16)
+ *cptr++ = packedColor;
+ #elif (SW_COLOR_BUFFER_BITS == 24)
+ *cptr++ = r24;
+ *cptr++ = g24;
+ *cptr++ = b24;
+ #endif
+
+ // Write depth
+ #if (SW_DEPTH_BUFFER_BITS == 8)
+ *dptr++ = d8;
+ #elif (SW_DEPTH_BUFFER_BITS == 16)
+ *dptr++ = d16;
+ #elif (SW_DEPTH_BUFFER_BITS == 24)
+ *dptr++ = dByte0;
+ *dptr++ = dByte1;
+ *dptr++ = dByte2;
+ #endif
+ }
+}
+
+#define DEFINE_FRAMEBUFFER_COPY_U32_BEGIN(name, DST_PTR_T) \
+static inline void sw_framebuffer_copy_to_##name(int x, int y, int w, int h, DST_PTR_T *dst) \
+{ \
+ const void *src = RLSW.framebuffer.color; \
+ \
+ for (int iy = y; iy < h; iy++) { \
+ for (int ix = x; ix < w; ix++) { \
+ uint8_t color[4]; \
+ sw_framebuffer_read_color8(color, src); \
+
+#define DEFINE_FRAMEBUFFER_COPY_F32_BEGIN(name, DST_PTR_T) \
+static inline void sw_framebuffer_copy_to_##name(int x, int y, int w, int h, DST_PTR_T *dst) \
+{ \
+ const void *src = RLSW.framebuffer.color; \
+ \
+ for (int iy = y; iy < h; iy++) { \
+ for (int ix = x; ix < w; ix++) { \
+ float color[4]; \
+ sw_framebuffer_read_color(color, src); \
+
+#define DEFINE_FRAMEBUFFER_COPY_END() \
+ sw_framebuffer_inc_const_color_addr(&src); \
+ } \
+ } \
+}
+
+DEFINE_FRAMEBUFFER_COPY_U32_BEGIN(GRAYSCALE, uint8_t)
+{
+ // NTSC grayscale conversion: Y = 0.299R + 0.587G + 0.114B
+ uint8_t gray = (uint8_t)((color[0]*299 + color[1]*587 + color[2]*114 + 500)/1000);
+ *dst++ = gray;
+}
+DEFINE_FRAMEBUFFER_COPY_END()
+
+DEFINE_FRAMEBUFFER_COPY_U32_BEGIN(GRAYALPHA, uint8_t)
+{
+ // Convert RGB to grayscale using NTSC formula
+ uint8_t gray = (uint8_t)((color[0]*299 + color[1]*587 + color[2]*114 + 500)/1000);
+
+ dst[0] = gray;
+ dst[1] = color[3]; // alpha
+
+ dst += 2;
+}
+DEFINE_FRAMEBUFFER_COPY_END()
+
+DEFINE_FRAMEBUFFER_COPY_U32_BEGIN(R5G6B5, uint16_t)
+{
+ // Convert 8-bit RGB to 5:6:5 format
+ uint8_t r5 = (color[0]*31 + 127)/255;
+ uint8_t g6 = (color[1]*63 + 127)/255;
+ uint8_t b5 = (color[2]*31 + 127)/255;
+
+#if SW_GL_FRAMEBUFFER_COPY_BGRA
+ uint16_t rgb565 = (b5 << 11) | (g6 << 5) | r5;
+#else // RGBA
+ uint16_t rgb565 = (r5 << 11) | (g6 << 5) | b5;
+#endif
+
+ *dst++ = rgb565;
+}
+DEFINE_FRAMEBUFFER_COPY_END()
+
+DEFINE_FRAMEBUFFER_COPY_U32_BEGIN(R8G8B8, uint8_t)
+{
+#if SW_GL_FRAMEBUFFER_COPY_BGRA
+ dst[0] = color[2];
+ dst[1] = color[1];
+ dst[2] = color[0];
+#else // RGBA
+ dst[0] = color[0];
+ dst[1] = color[1];
+ dst[2] = color[2];
+#endif
+
+ dst += 3;
+}
+DEFINE_FRAMEBUFFER_COPY_END()
+
+DEFINE_FRAMEBUFFER_COPY_U32_BEGIN(R5G5B5A1, uint16_t)
+{
+ uint8_t r5 = (color[0]*31 + 127)/255;
+ uint8_t g5 = (color[1]*31 + 127)/255;
+ uint8_t b5 = (color[2]*31 + 127)/255;
+ uint8_t a1 = color[3] >= 128 ? 1 : 0;
+
+#if SW_GL_FRAMEBUFFER_COPY_BGRA
+ uint16_t pixel = (b5 << 11) | (g5 << 6) | (r5 << 1) | a1;
+#else // RGBA
+ uint16_t pixel = (r5 << 11) | (g5 << 6) | (b5 << 1) | a1;
+#endif
+
+ *dst++ = pixel;
+}
+DEFINE_FRAMEBUFFER_COPY_END()
+
+DEFINE_FRAMEBUFFER_COPY_U32_BEGIN(R4G4B4A4, uint16_t)
+{
+ uint8_t r4 = (color[0]*15 + 127)/255;
+ uint8_t g4 = (color[1]*15 + 127)/255;
+ uint8_t b4 = (color[2]*15 + 127)/255;
+ uint8_t a4 = (color[3]*15 + 127)/255;
+
+#if SW_GL_FRAMEBUFFER_COPY_BGRA
+ uint16_t pixel = (b4 << 12) | (g4 << 8) | (r4 << 4) | a4;
+#else // RGBA
+ uint16_t pixel = (r4 << 12) | (g4 << 8) | (b4 << 4) | a4;
+#endif
+
+ *dst++ = pixel;
+}
+DEFINE_FRAMEBUFFER_COPY_END()
+
+DEFINE_FRAMEBUFFER_COPY_U32_BEGIN(R8G8B8A8, uint8_t)
+{
+#if SW_GL_FRAMEBUFFER_COPY_BGRA
+ dst[0] = color[2];
+ dst[1] = color[1];
+ dst[2] = color[0];
+#else // RGBA
+ dst[0] = color[0];
+ dst[1] = color[1];
+ dst[2] = color[2];
+#endif
+ dst[3] = color[3];
+
+ dst += 4;
+}
+DEFINE_FRAMEBUFFER_COPY_END()
+
+DEFINE_FRAMEBUFFER_COPY_F32_BEGIN(R32, float)
+{
+ dst[0] = color[0];
+ dst++;
+}
+DEFINE_FRAMEBUFFER_COPY_END()
+
+DEFINE_FRAMEBUFFER_COPY_F32_BEGIN(R32G32B32, float)
+{
+#if SW_GL_FRAMEBUFFER_COPY_BGRA
+ dst[0] = color[2];
+ dst[1] = color[1];
+ dst[2] = color[0];
+#else // RGBA
+ dst[0] = color[0];
+ dst[1] = color[1];
+ dst[2] = color[2];
+#endif
+
+ dst += 3;
+}
+DEFINE_FRAMEBUFFER_COPY_END()
+
+DEFINE_FRAMEBUFFER_COPY_F32_BEGIN(R32G32B32A32, float)
+{
+#if SW_GL_FRAMEBUFFER_COPY_BGRA
+ dst[0] = color[2];
+ dst[1] = color[1];
+ dst[2] = color[0];
+#else // RGBA
+ dst[0] = color[0];
+ dst[1] = color[1];
+ dst[2] = color[2];
+#endif
+ dst[3] = color[3];
+
+ dst += 4;
+}
+DEFINE_FRAMEBUFFER_COPY_END()
+
+DEFINE_FRAMEBUFFER_COPY_F32_BEGIN(R16, sw_half_t)
+{
+ dst[0] = sw_f16_from_f32(color[0]);
+ dst++;
+}
+DEFINE_FRAMEBUFFER_COPY_END()
+
+DEFINE_FRAMEBUFFER_COPY_F32_BEGIN(R16G16B16, sw_half_t)
+{
+#if SW_GL_FRAMEBUFFER_COPY_BGRA
+ dst[0] = sw_f16_from_f32(color[2]);
+ dst[1] = sw_f16_from_f32(color[1]);
+ dst[2] = sw_f16_from_f32(color[0]);
+#else // RGBA
+ dst[0] = sw_f16_from_f32(color[0]);
+ dst[1] = sw_f16_from_f32(color[1]);
+ dst[2] = sw_f16_from_f32(color[2]);
+#endif
+
+ dst += 3;
+}
+DEFINE_FRAMEBUFFER_COPY_END()
+
+DEFINE_FRAMEBUFFER_COPY_F32_BEGIN(R16G16B16A16, sw_half_t)
+{
+#if SW_GL_FRAMEBUFFER_COPY_BGRA
+ dst[0] = sw_f16_from_f32(color[2]);
+ dst[1] = sw_f16_from_f32(color[1]);
+ dst[2] = sw_f16_from_f32(color[0]);
+#else // RGBA
+ dst[0] = sw_f16_from_f32(color[0]);
+ dst[1] = sw_f16_from_f32(color[1]);
+ dst[2] = sw_f16_from_f32(color[2]);
+#endif
+ dst[3] = sw_f16_from_f32(color[3]);
+
+ dst += 4;
+}
+DEFINE_FRAMEBUFFER_COPY_END()
+
+#define DEFINE_FRAMEBUFFER_BLIT_U32_BEGIN(name, DST_PTR_T) \
+static inline void sw_framebuffer_blit_to_##name( \
+ int xDst, int yDst, int wDst, int hDst, \
+ int xSrc, int ySrc, int wSrc, int hSrc, \
+ DST_PTR_T *dst) \
+{ \
+ const uint8_t *srcBase = RLSW.framebuffer.color; \
+ int fbWidth = RLSW.framebuffer.width; \
+ \
+ uint32_t xScale = ((uint32_t)wSrc << 16)/(uint32_t)wDst; \
+ uint32_t yScale = ((uint32_t)hSrc << 16)/(uint32_t)hDst; \
+ \
+ for (int dy = 0; dy < hDst; dy++) { \
+ uint32_t yFix = ((uint32_t)ySrc << 16) + dy*yScale; \
+ int sy = yFix >> 16; \
+ \
+ for (int dx = 0; dx < wDst; dx++) { \
+ uint32_t xFix = dx*xScale; \
+ int sx = xFix >> 16; \
+ const void *srcPtr = sw_framebuffer_get_color_addr(srcBase, sy*fbWidth + sx); \
+ uint8_t color[4]; \
+ sw_framebuffer_read_color8(color, srcPtr); \
+
+#define DEFINE_FRAMEBUFFER_BLIT_F32_BEGIN(name, DST_PTR_T) \
+static inline void sw_framebuffer_blit_to_##name( \
+ int xDst, int yDst, int wDst, int hDst, \
+ int xSrc, int ySrc, int wSrc, int hSrc, \
+ DST_PTR_T *dst) \
+{ \
+ const uint8_t *srcBase = RLSW.framebuffer.color; \
+ int fbWidth = RLSW.framebuffer.width; \
+ \
+ uint32_t xScale = ((uint32_t)wSrc << 16)/(uint32_t)wDst; \
+ uint32_t yScale = ((uint32_t)hSrc << 16)/(uint32_t)hDst; \
+ \
+ for (int dy = 0; dy < hDst; dy++) { \
+ uint32_t yFix = ((uint32_t)ySrc << 16) + dy*yScale; \
+ int sy = yFix >> 16; \
+ \
+ for (int dx = 0; dx < wDst; dx++) { \
+ uint32_t xFix = dx*xScale; \
+ int sx = xFix >> 16; \
+ const void *srcPtr = sw_framebuffer_get_color_addr(srcBase, sy*fbWidth + sx); \
+ float color[4]; \
+ sw_framebuffer_read_color(color, srcPtr); \
+
+#define DEFINE_FRAMEBUFFER_BLIT_END() \
+ } \
+ } \
+}
+
+DEFINE_FRAMEBUFFER_BLIT_U32_BEGIN(GRAYSCALE, uint8_t)
+{
+ uint8_t gray = (uint8_t)((color[0]*299 + color[1]*587 + color[2]*114 + 500)/1000);
+ *dst++ = gray;
+}
+DEFINE_FRAMEBUFFER_BLIT_END()
+
+DEFINE_FRAMEBUFFER_BLIT_U32_BEGIN(GRAYALPHA, uint8_t)
+{
+ uint8_t gray = (uint8_t)((color[0]*299 + color[1]*587 + color[2]*114 + 500)/1000);
+
+ dst[0] = gray;
+ dst[1] = color[3]; // alpha
+
+ dst += 2;
+}
+DEFINE_FRAMEBUFFER_BLIT_END()
+
+DEFINE_FRAMEBUFFER_BLIT_U32_BEGIN(R5G6B5, uint16_t)
+{
+ uint8_t r5 = (color[0]*31 + 127)/255;
+ uint8_t g6 = (color[1]*63 + 127)/255;
+ uint8_t b5 = (color[2]*31 + 127)/255;
+
+#if SW_GL_FRAMEBUFFER_COPY_BGRA
+ uint16_t rgb565 = (b5 << 11) | (g6 << 5) | r5;
+#else // RGBA
+ uint16_t rgb565 = (r5 << 11) | (g6 << 5) | b5;
+#endif
+
+ *dst++ = rgb565;
+}
+DEFINE_FRAMEBUFFER_BLIT_END()
+
+DEFINE_FRAMEBUFFER_BLIT_U32_BEGIN(R8G8B8, uint8_t)
+{
+#if SW_GL_FRAMEBUFFER_COPY_BGRA
+ dst[0] = color[2];
+ dst[1] = color[1];
+ dst[2] = color[0];
+#else // RGBA
+ dst[0] = color[0];
+ dst[1] = color[1];
+ dst[2] = color[2];
+#endif
+
+ dst += 3;
+}
+DEFINE_FRAMEBUFFER_BLIT_END()
+
+DEFINE_FRAMEBUFFER_BLIT_U32_BEGIN(R5G5B5A1, uint16_t)
+{
+ uint8_t r5 = (color[0]*31 + 127)/255;
+ uint8_t g5 = (color[1]*31 + 127)/255;
+ uint8_t b5 = (color[2]*31 + 127)/255;
+ uint8_t a1 = color[3] >= 128 ? 1 : 0;
+
+#if SW_GL_FRAMEBUFFER_COPY_BGRA
+ uint16_t pixel = (b5 << 11) | (g5 << 6) | (r5 << 1) | a1;
+#else // RGBA
+ uint16_t pixel = (r5 << 11) | (g5 << 6) | (b5 << 1) | a1;
+#endif
+
+ *dst++ = pixel;
+}
+DEFINE_FRAMEBUFFER_BLIT_END()
+
+DEFINE_FRAMEBUFFER_BLIT_U32_BEGIN(R4G4B4A4, uint16_t)
+{
+ uint8_t r4 = (color[0]*15 + 127)/255;
+ uint8_t g4 = (color[1]*15 + 127)/255;
+ uint8_t b4 = (color[2]*15 + 127)/255;
+ uint8_t a4 = (color[3]*15 + 127)/255;
+
+#if SW_GL_FRAMEBUFFER_COPY_BGRA
+ uint16_t pixel = (b4 << 12) | (g4 << 8) | (r4 << 4) | a4;
+#else // RGBA
+ uint16_t pixel = (r4 << 12) | (g4 << 8) | (b4 << 4) | a4;
+#endif
+
+ *dst++ = pixel;
+}
+DEFINE_FRAMEBUFFER_BLIT_END()
+
+DEFINE_FRAMEBUFFER_BLIT_U32_BEGIN(R8G8B8A8, uint8_t)
+{
+#if SW_GL_FRAMEBUFFER_COPY_BGRA
+ dst[0] = color[2];
+ dst[1] = color[1];
+ dst[2] = color[0];
+#else // RGBA
+ dst[0] = color[0];
+ dst[1] = color[1];
+ dst[2] = color[2];
+#endif
+ dst[3] = color[3];
+
+ dst += 4;
+}
+DEFINE_FRAMEBUFFER_BLIT_END()
+
+DEFINE_FRAMEBUFFER_BLIT_F32_BEGIN(R32, uint8_t)
+{
+ dst[0] = color[0];
+ dst++;
+}
+DEFINE_FRAMEBUFFER_BLIT_END()
+
+DEFINE_FRAMEBUFFER_BLIT_F32_BEGIN(R32G32B32, float)
+{
+#if SW_GL_FRAMEBUFFER_COPY_BGRA
+ dst[0] = color[2];
+ dst[1] = color[1];
+ dst[2] = color[0];
+#else // RGBA
+ dst[0] = color[0];
+ dst[1] = color[1];
+ dst[2] = color[2];
+#endif
+
+ dst += 3;
+}
+DEFINE_FRAMEBUFFER_BLIT_END()
+
+DEFINE_FRAMEBUFFER_BLIT_F32_BEGIN(R32G32B32A32, float)
+{
+#if SW_GL_FRAMEBUFFER_COPY_BGRA
+ dst[0] = color[2];
+ dst[1] = color[1];
+ dst[2] = color[0];
+#else // RGBA
+ dst[0] = color[0];
+ dst[1] = color[1];
+ dst[2] = color[2];
+#endif
+ dst[3] = color[3];
+
+ dst += 4;
+}
+DEFINE_FRAMEBUFFER_BLIT_END()
+
+DEFINE_FRAMEBUFFER_BLIT_F32_BEGIN(R16, sw_half_t)
+{
+ dst[0] = sw_f16_from_f32(color[0]);
+ dst++;
+}
+DEFINE_FRAMEBUFFER_BLIT_END()
+
+DEFINE_FRAMEBUFFER_BLIT_F32_BEGIN(R16G16B16, sw_half_t)
+{
+#if SW_GL_FRAMEBUFFER_COPY_BGRA
+ dst[0] = sw_f16_from_f32(color[2]);
+ dst[1] = sw_f16_from_f32(color[1]);
+ dst[2] = sw_f16_from_f32(color[0]);
+#else // RGBA
+ dst[0] = sw_f16_from_f32(color[0]);
+ dst[1] = sw_f16_from_f32(color[1]);
+ dst[2] = sw_f16_from_f32(color[2]);
+#endif
+
+ dst += 3;
+}
+DEFINE_FRAMEBUFFER_BLIT_END()
+
+DEFINE_FRAMEBUFFER_BLIT_F32_BEGIN(R16G16B16A16, sw_half_t)
+{
+#if SW_GL_FRAMEBUFFER_COPY_BGRA
+ dst[0] = sw_f16_from_f32(color[2]);
+ dst[1] = sw_f16_from_f32(color[1]);
+ dst[2] = sw_f16_from_f32(color[0]);
+#else // RGBA
+ dst[0] = sw_f16_from_f32(color[0]);
+ dst[1] = sw_f16_from_f32(color[1]);
+ dst[2] = sw_f16_from_f32(color[2]);
+#endif
+ dst[3] = sw_f16_from_f32(color[3]);
+
+ dst += 4;
+}
+DEFINE_FRAMEBUFFER_BLIT_END()
+
+// Pixel format management functions
+
+static inline int sw_get_pixel_format(SWformat format, SWtype type)
+{
+ int channels = 0;
+ int bitsPerChannel = 8; // Default: 8 bits per channel
+
+ // Determine the number of channels (format)
+ switch (format)
+ {
+ case SW_LUMINANCE: channels = 1; break;
+ case SW_LUMINANCE_ALPHA: channels = 2; break;
+ case SW_RGB: channels = 3; break;
+ case SW_RGBA: channels = 4; break;
+ default: return SW_PIXELFORMAT_UNKNOWN;
+ }
+
+ // Determine the depth of each channel (type)
+ switch (type)
+ {
+ case SW_UNSIGNED_BYTE: bitsPerChannel = 8; break;
+ case SW_BYTE: bitsPerChannel = 8; break;
+ case SW_UNSIGNED_SHORT: bitsPerChannel = 16; break;
+ case SW_SHORT: bitsPerChannel = 16; break;
+ case SW_UNSIGNED_INT: bitsPerChannel = 32; break;
+ case SW_INT: bitsPerChannel = 32; break;
+ case SW_FLOAT: bitsPerChannel = 32; break;
+ default: return SW_PIXELFORMAT_UNKNOWN;
+ }
+
+ // Map the format and type to the correct internal format
+ if (bitsPerChannel == 8)
+ {
+ if (channels == 1) return SW_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE;
+ if (channels == 2) return SW_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA;
+ if (channels == 3) return SW_PIXELFORMAT_UNCOMPRESSED_R8G8B8;
+ if (channels == 4) return SW_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
+ }
+ else if (bitsPerChannel == 16)
+ {
+ if (channels == 1) return SW_PIXELFORMAT_UNCOMPRESSED_R16;
+ if (channels == 3) return SW_PIXELFORMAT_UNCOMPRESSED_R16G16B16;
+ if (channels == 4) return SW_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16;
+ }
+ else if (bitsPerChannel == 32)
+ {
+ if (channels == 1) return SW_PIXELFORMAT_UNCOMPRESSED_R32;
+ if (channels == 3) return SW_PIXELFORMAT_UNCOMPRESSED_R32G32B32;
+ if (channels == 4) return SW_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32;
+ }
+
+ return SW_PIXELFORMAT_UNKNOWN;
+}
+
+int sw_get_pixel_bytes(sw_pixelformat_t format)
+{
+ int bpp = 0;
+
+ switch (format)
+ {
+ case SW_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: bpp = 1; break;
+ case SW_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA:
+ case SW_PIXELFORMAT_UNCOMPRESSED_R5G6B5:
+ case SW_PIXELFORMAT_UNCOMPRESSED_R5G5B5A1:
+ case SW_PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: bpp = 2; break;
+ case SW_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: bpp = 4; break;
+ case SW_PIXELFORMAT_UNCOMPRESSED_R8G8B8: bpp = 3; break;
+ case SW_PIXELFORMAT_UNCOMPRESSED_R32: bpp = 4; break;
+ case SW_PIXELFORMAT_UNCOMPRESSED_R32G32B32: bpp = 4*3; break;
+ case SW_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: bpp = 4*4; break;
+ case SW_PIXELFORMAT_UNCOMPRESSED_R16: bpp = 2; break;
+ case SW_PIXELFORMAT_UNCOMPRESSED_R16G16B16: bpp = 2*3; break;
+ case SW_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: bpp = 2*4; break;
+ default: break;
+ }
+
+ return bpp;
+}
+
+static inline void sw_get_pixel_grayscale(float *color, const void *pixels, uint32_t offset)
+{
+ float gray = (float)((uint8_t *)pixels)[offset]*(1.0f/255);
+
+ color[0] = gray;
+ color[1] = gray;
+ color[2] = gray;
+ color[3] = 1.0f;
+}
+
+static inline void sw_get_pixel_red_16(float *color, const void *pixels, uint32_t offset)
+{
+ float value = sw_f16_to_f32(((sw_half_t *)pixels)[offset]);
+
+ color[0] = value;
+ color[1] = value;
+ color[2] = value;
+ color[3] = 1.0f;
+}
+
+static inline void sw_get_pixel_red_32(float *color, const void *pixels, uint32_t offset)
+{
+ float value = ((float *)pixels)[offset];
+
+ color[0] = value;
+ color[1] = value;
+ color[2] = value;
+ color[3] = 1.0f;
+}
+
+static inline void sw_get_pixel_grayscale_alpha(float *color, const void *pixels, uint32_t offset)
+{
+ const uint8_t *pixelData = (const uint8_t *)pixels + 2*offset;
+
+ color[0] = color[1] = color[2] = (float)pixelData[0]*(1.0f/255);
+ color[3] = (float)pixelData[1]*(1.0f/255);
+}
+
+static inline void sw_get_pixel_rgb_565(float *color, const void *pixels, uint32_t offset)
+{
+ uint16_t pixel = ((uint16_t *)pixels)[offset];
+
+ color[0] = (float)((pixel & 0xF800) >> 11)/31;
+ color[1] = (float)((pixel & 0x7E0) >> 5)/63;
+ color[2] = (float)(pixel & 0x1F)/31;
+ color[3] = 1.0f;
+}
+
+static inline void sw_get_pixel_rgb_888(float *color, const void *pixels, uint32_t offset)
+{
+ const uint8_t *pixel = (const uint8_t *)pixels + 3*offset;
+
+ color[0] = (float)pixel[0]*(1.0f/255);
+ color[1] = (float)pixel[1]*(1.0f/255);
+ color[2] = (float)pixel[2]*(1.0f/255);
+ color[3] = 1.0f;
+}
+
+static inline void sw_get_pixel_rgb_161616(float *color, const void *pixels, uint32_t offset)
+{
+ const sw_half_t *pixel = (sw_half_t *)pixels + 3*offset;
+
+ color[0] = sw_f16_to_f32(pixel[0]);
+ color[1] = sw_f16_to_f32(pixel[1]);
+ color[2] = sw_f16_to_f32(pixel[2]);
+ color[3] = 1.0f;
+}
+
+static inline void sw_get_pixel_rgb_323232(float *color, const void *pixels, uint32_t offset)
+{
+ const float *pixel = (float *)pixels + 3*offset;
+
+ color[0] = pixel[0];
+ color[1] = pixel[1];
+ color[2] = pixel[2];
+ color[3] = 1.0f;
+}
+
+static inline void sw_get_pixel_rgba_5551(float *color, const void *pixels, uint32_t offset)
+{
+ uint16_t pixel = ((uint16_t *)pixels)[offset];
+
+ color[0] = (float)((pixel & 0xF800) >> 11)/31;
+ color[1] = (float)((pixel & 0x7C0) >> 6)/31;
+ color[2] = (float)((pixel & 0x3E) >> 1)/31;
+ color[3] = (float)(pixel & 0x1);
+}
+
+static inline void sw_get_pixel_rgba_4444(float *color, const void *pixels, uint32_t offset)
+{
+ uint16_t pixel = ((uint16_t *)pixels)[offset];
+
+ color[0] = (float)((pixel & 0xF000) >> 12)/15;
+ color[1] = (float)((pixel & 0xF00) >> 8)/15;
+ color[2] = (float)((pixel & 0xF0) >> 4)/15;
+ color[3] = (float)(pixel & 0xF)/15;
+}
+
+static inline void sw_get_pixel_rgba_8888(float *color, const void *pixels, uint32_t offset)
+{
+ const uint8_t *pixel = (uint8_t *)pixels + 4*offset;
+
+ color[0] = (float)pixel[0]*(1.0f/255);
+ color[1] = (float)pixel[1]*(1.0f/255);
+ color[2] = (float)pixel[2]*(1.0f/255);
+ color[3] = (float)pixel[3]*(1.0f/255);
+}
+
+static inline void sw_get_pixel_rgba_16161616(float *color, const void *pixels, uint32_t offset)
+{
+ const sw_half_t *pixel = (sw_half_t *)pixels + 4*offset;
+
+ color[0] = sw_f16_to_f32(pixel[0]);
+ color[1] = sw_f16_to_f32(pixel[1]);
+ color[2] = sw_f16_to_f32(pixel[2]);
+ color[3] = sw_f16_to_f32(pixel[3]);
+}
+
+static inline void sw_get_pixel_rgba_32323232(float *color, const void *pixels, uint32_t offset)
+{
+ const float *pixel = (float *)pixels + 4*offset;
+
+ color[0] = pixel[0];
+ color[1] = pixel[1];
+ color[2] = pixel[2];
+ color[3] = pixel[3];
+}
+
+static inline void sw_get_pixel(float *color, const void *pixels, uint32_t offset, sw_pixelformat_t format)
+{
+ switch (format)
+ {
+ case SW_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: sw_get_pixel_grayscale(color, pixels, offset); break;
+ case SW_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA: sw_get_pixel_grayscale_alpha(color, pixels, offset); break;
+ case SW_PIXELFORMAT_UNCOMPRESSED_R5G6B5: sw_get_pixel_rgb_565(color, pixels, offset); break;
+ case SW_PIXELFORMAT_UNCOMPRESSED_R8G8B8: sw_get_pixel_rgb_888(color, pixels, offset); break;
+ case SW_PIXELFORMAT_UNCOMPRESSED_R5G5B5A1: sw_get_pixel_rgba_5551(color, pixels, offset); break;
+ case SW_PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: sw_get_pixel_rgba_4444(color, pixels, offset); break;
+ case SW_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: sw_get_pixel_rgba_8888(color, pixels, offset); break;
+ case SW_PIXELFORMAT_UNCOMPRESSED_R32: sw_get_pixel_red_32(color, pixels, offset); break;
+ case SW_PIXELFORMAT_UNCOMPRESSED_R32G32B32: sw_get_pixel_rgb_323232(color, pixels, offset); break;
+ case SW_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: sw_get_pixel_rgba_32323232(color, pixels, offset); break;
+ case SW_PIXELFORMAT_UNCOMPRESSED_R16: sw_get_pixel_red_16(color, pixels, offset); break;
+ case SW_PIXELFORMAT_UNCOMPRESSED_R16G16B16: sw_get_pixel_rgb_161616(color, pixels, offset); break;
+ case SW_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: sw_get_pixel_rgba_16161616(color, pixels, offset); break;
+ case SW_PIXELFORMAT_UNKNOWN: break;
+ default: break;
+ }
+}
+
+// Texture sampling functionality
+
+static inline void sw_texture_sample_nearest(float *color, const sw_texture_t *tex, float u, float v)
+{
+ u = (tex->sWrap == SW_REPEAT)? sw_fract(u) : sw_saturate(u);
+ v = (tex->tWrap == SW_REPEAT)? sw_fract(v) : sw_saturate(v);
+
+ int x = u*tex->width, y = v*tex->height;
+
+ sw_get_pixel(color, tex->pixels.cptr, y*tex->width + x, tex->format);
+}
+
+static inline void sw_texture_sample_linear(float *color, const sw_texture_t *tex, float u, float v)
+{
+ // TODO: REVIEW: With a bit more cleverness we could clearly reduce the
+ // number of operations here, but for now it works fine.
+
+ float xf = u*tex->width - 0.5f;
+ float yf = v*tex->height - 0.5f;
+
+ int x0 = (int)floorf(xf);
+ int y0 = (int)floorf(yf);
+
+ float fx = xf - x0;
+ float fy = yf - y0;
+
+ int x1 = x0 + 1;
+ int y1 = y0 + 1;
+
+ if (tex->sWrap == SW_CLAMP)
+ {
+ x0 = (x0 > tex->wMinus1)? tex->wMinus1 : x0;
+ x1 = (x1 > tex->wMinus1)? tex->wMinus1 : x1;
+ }
+ else
+ {
+ x0 = (x0%tex->width + tex->width)%tex->width;
+ x1 = (x1%tex->width + tex->width)%tex->width;
+ }
+
+ if (tex->tWrap == SW_CLAMP)
+ {
+ y0 = (y0 > tex->hMinus1)? tex->hMinus1 : y0;
+ y1 = (y1 > tex->hMinus1)? tex->hMinus1 : y1;
+ }
+ else
+ {
+ y0 = (y0%tex->height + tex->height)%tex->height;
+ y1 = (y1%tex->height + tex->height)%tex->height;
+ }
+
+ float c00[4], c10[4], c01[4], c11[4];
+ sw_get_pixel(c00, tex->pixels.cptr, y0*tex->width + x0, tex->format);
+ sw_get_pixel(c10, tex->pixels.cptr, y0*tex->width + x1, tex->format);
+ sw_get_pixel(c01, tex->pixels.cptr, y1*tex->width + x0, tex->format);
+ sw_get_pixel(c11, tex->pixels.cptr, y1*tex->width + x1, tex->format);
+
+ for (int i = 0; i < 4; i++)
+ {
+ float t = c00[i] + fx*(c10[i] - c00[i]);
+ float b = c01[i] + fx*(c11[i] - c01[i]);
+ color[i] = t + fy*(b - t);
+ }
+}
+
+static inline void sw_texture_sample(float *color, const sw_texture_t *tex, float u, float v, float duDx, float duDy, float dvDx, float dvDy)
+{
+ // Previous method: There is no need to compute the square root
+ // because using the squared value, the comparison remains `L2 > 1.0f*1.0f`
+ //float du = sqrtf(duDx*duDx + duDy*duDy);
+ //float dv = sqrtf(dvDx*dvDx + dvDy*dvDy);
+ //float L = (du > dv)? du : dv;
+
+ // Calculate the derivatives for each axis
+ float du2 = duDx*duDx + duDy*duDy;
+ float dv2 = dvDx*dvDx + dvDy*dvDy;
+ float L2 = (du2 > dv2)? du2 : dv2;
+
+ SWfilter filter = (L2 > 1.0f)? tex->minFilter : tex->magFilter;
+
+ switch (filter)
+ {
+ case SW_NEAREST: sw_texture_sample_nearest(color, tex, u, v); break;
+ case SW_LINEAR: sw_texture_sample_linear(color, tex, u, v); break;
+ default: break;
+ }
+}
+
+// Color Blending functionality
+
+static inline void sw_factor_zero(float *SW_RESTRICT factor, const float *SW_RESTRICT src, const float *SW_RESTRICT dst)
+{
+ factor[0] = factor[1] = factor[2] = factor[3] = 0.0f;
+}
+
+static inline void sw_factor_one(float *SW_RESTRICT factor, const float *SW_RESTRICT src, const float *SW_RESTRICT dst)
+{
+ factor[0] = factor[1] = factor[2] = factor[3] = 1.0f;
+}
+
+static inline void sw_factor_src_color(float *SW_RESTRICT factor, const float *SW_RESTRICT src, const float *SW_RESTRICT dst)
+{
+ factor[0] = src[0]; factor[1] = src[1]; factor[2] = src[2]; factor[3] = src[3];
+}
+
+static inline void sw_factor_one_minus_src_color(float *SW_RESTRICT factor, const float *SW_RESTRICT src, const float *SW_RESTRICT dst)
+{
+ factor[0] = 1.0f - src[0]; factor[1] = 1.0f - src[1];
+ factor[2] = 1.0f - src[2]; factor[3] = 1.0f - src[3];
+}
+
+static inline void sw_factor_src_alpha(float *SW_RESTRICT factor, const float *SW_RESTRICT src, const float *SW_RESTRICT dst)
+{
+ factor[0] = factor[1] = factor[2] = factor[3] = src[3];
+}
+
+static inline void sw_factor_one_minus_src_alpha(float *SW_RESTRICT factor, const float *SW_RESTRICT src, const float *SW_RESTRICT dst)
+{
+ float invAlpha = 1.0f - src[3];
+ factor[0] = factor[1] = factor[2] = factor[3] = invAlpha;
+}
+
+static inline void sw_factor_dst_alpha(float *SW_RESTRICT factor, const float *SW_RESTRICT src, const float *SW_RESTRICT dst)
+{
+ factor[0] = factor[1] = factor[2] = factor[3] = dst[3];
+}
+
+static inline void sw_factor_one_minus_dst_alpha(float *SW_RESTRICT factor, const float *SW_RESTRICT src, const float *SW_RESTRICT dst)
+{
+ float invAlpha = 1.0f - dst[3];
+ factor[0] = factor[1] = factor[2] = factor[3] = invAlpha;
+}
+
+static inline void sw_factor_dst_color(float *SW_RESTRICT factor, const float *SW_RESTRICT src, const float *SW_RESTRICT dst)
+{
+ factor[0] = dst[0]; factor[1] = dst[1]; factor[2] = dst[2]; factor[3] = dst[3];
+}
+
+static inline void sw_factor_one_minus_dst_color(float *SW_RESTRICT factor, const float *SW_RESTRICT src, const float *SW_RESTRICT dst)
+{
+ factor[0] = 1.0f - dst[0]; factor[1] = 1.0f - dst[1];
+ factor[2] = 1.0f - dst[2]; factor[3] = 1.0f - dst[3];
+}
+
+static inline void sw_factor_src_alpha_saturate(float *SW_RESTRICT factor, const float *SW_RESTRICT src, const float *SW_RESTRICT dst)
+{
+ factor[0] = factor[1] = factor[2] = 1.0f;
+ factor[3] = (src[3] < 1.0f)? src[3] : 1.0f;
+}
+
+static inline void sw_blend_colors(float *SW_RESTRICT dst/*[4]*/, const float *SW_RESTRICT src/*[4]*/)
+{
+ float srcFactor[4], dstFactor[4];
+
+ RLSW.srcFactorFunc(srcFactor, src, dst);
+ RLSW.dstFactorFunc(dstFactor, src, dst);
+
+ dst[0] = srcFactor[0]*src[0] + dstFactor[0]*dst[0];
+ dst[1] = srcFactor[1]*src[1] + dstFactor[1]*dst[1];
+ dst[2] = srcFactor[2]*src[2] + dstFactor[2]*dst[2];
+ dst[3] = srcFactor[3]*src[3] + dstFactor[3]*dst[3];
+}
+
+// Projection helper functions
+
+static inline void sw_project_ndc_to_screen(float screen[2], const float ndc[4])
+{
+ screen[0] = RLSW.vpCenter[0] + ndc[0]*RLSW.vpHalfSize[0];
+ screen[1] = RLSW.vpCenter[1] - ndc[1]*RLSW.vpHalfSize[1];
+}
+
+// Polygon Clipping management
+
+#define DEFINE_CLIP_FUNC(name, FUNC_IS_INSIDE, FUNC_COMPUTE_T) \
+static inline int sw_clip_##name( \
+ sw_vertex_t output[SW_MAX_CLIPPED_POLYGON_VERTICES], \
+ const sw_vertex_t input[SW_MAX_CLIPPED_POLYGON_VERTICES], \
+ int n) \
+{ \
+ const sw_vertex_t *prev = &input[n - 1]; \
+ int prevInside = FUNC_IS_INSIDE(prev->homogeneous); \
+ int outputCount = 0; \
+ \
+ for (int i = 0; i < n; i++) { \
+ const sw_vertex_t *curr = &input[i]; \
+ int currInside = FUNC_IS_INSIDE(curr->homogeneous); \
+ \
+ /* If transition between interior/exterior, calculate intersection point */ \
+ if (prevInside != currInside) { \
+ float t = FUNC_COMPUTE_T(prev->homogeneous, curr->homogeneous); \
+ sw_lerp_vertex_PTCH(&output[outputCount++], prev, curr, t); \
+ } \
+ \
+ /* If current vertex inside, add it */ \
+ if (currInside) { \
+ output[outputCount++] = *curr; \
+ } \
+ \
+ prev = curr; \
+ prevInside = currInside; \
+ } \
+ \
+ return outputCount; \
+}
+
+// Frustum cliping functions
+
+#define IS_INSIDE_PLANE_W(h) ((h)[3] >= SW_CLIP_EPSILON)
+#define IS_INSIDE_PLANE_X_POS(h) ((h)[0] <= (h)[3])
+#define IS_INSIDE_PLANE_X_NEG(h) (-(h)[0] <= (h)[3])
+#define IS_INSIDE_PLANE_Y_POS(h) ((h)[1] <= (h)[3])
+#define IS_INSIDE_PLANE_Y_NEG(h) (-(h)[1] <= (h)[3])
+#define IS_INSIDE_PLANE_Z_POS(h) ((h)[2] <= (h)[3])
+#define IS_INSIDE_PLANE_Z_NEG(h) (-(h)[2] <= (h)[3])
+
+#define COMPUTE_T_PLANE_W(hPrev, hCurr) ((SW_CLIP_EPSILON - (hPrev)[3])/((hCurr)[3] - (hPrev)[3]))
+#define COMPUTE_T_PLANE_X_POS(hPrev, hCurr) (((hPrev)[3] - (hPrev)[0])/(((hPrev)[3] - (hPrev)[0]) - ((hCurr)[3] - (hCurr)[0])))
+#define COMPUTE_T_PLANE_X_NEG(hPrev, hCurr) (((hPrev)[3] + (hPrev)[0])/(((hPrev)[3] + (hPrev)[0]) - ((hCurr)[3] + (hCurr)[0])))
+#define COMPUTE_T_PLANE_Y_POS(hPrev, hCurr) (((hPrev)[3] - (hPrev)[1])/(((hPrev)[3] - (hPrev)[1]) - ((hCurr)[3] - (hCurr)[1])))
+#define COMPUTE_T_PLANE_Y_NEG(hPrev, hCurr) (((hPrev)[3] + (hPrev)[1])/(((hPrev)[3] + (hPrev)[1]) - ((hCurr)[3] + (hCurr)[1])))
+#define COMPUTE_T_PLANE_Z_POS(hPrev, hCurr) (((hPrev)[3] - (hPrev)[2])/(((hPrev)[3] - (hPrev)[2]) - ((hCurr)[3] - (hCurr)[2])))
+#define COMPUTE_T_PLANE_Z_NEG(hPrev, hCurr) (((hPrev)[3] + (hPrev)[2])/(((hPrev)[3] + (hPrev)[2]) - ((hCurr)[3] + (hCurr)[2])))
+
+DEFINE_CLIP_FUNC(w, IS_INSIDE_PLANE_W, COMPUTE_T_PLANE_W)
+DEFINE_CLIP_FUNC(x_pos, IS_INSIDE_PLANE_X_POS, COMPUTE_T_PLANE_X_POS)
+DEFINE_CLIP_FUNC(x_neg, IS_INSIDE_PLANE_X_NEG, COMPUTE_T_PLANE_X_NEG)
+DEFINE_CLIP_FUNC(y_pos, IS_INSIDE_PLANE_Y_POS, COMPUTE_T_PLANE_Y_POS)
+DEFINE_CLIP_FUNC(y_neg, IS_INSIDE_PLANE_Y_NEG, COMPUTE_T_PLANE_Y_NEG)
+DEFINE_CLIP_FUNC(z_pos, IS_INSIDE_PLANE_Z_POS, COMPUTE_T_PLANE_Z_POS)
+DEFINE_CLIP_FUNC(z_neg, IS_INSIDE_PLANE_Z_NEG, COMPUTE_T_PLANE_Z_NEG)
+
+// Scissor clip functions
+
+#define COMPUTE_T_SCISSOR_X_MIN(hPrev, hCurr) (((RLSW.scClipMin[0])*(hPrev)[3] - (hPrev)[0])/(((hCurr)[0] - (RLSW.scClipMin[0])*(hCurr)[3]) - ((hPrev)[0] - (RLSW.scClipMin[0])*(hPrev)[3])))
+#define COMPUTE_T_SCISSOR_X_MAX(hPrev, hCurr) (((RLSW.scClipMax[0])*(hPrev)[3] - (hPrev)[0])/(((hCurr)[0] - (RLSW.scClipMax[0])*(hCurr)[3]) - ((hPrev)[0] - (RLSW.scClipMax[0])*(hPrev)[3])))
+#define COMPUTE_T_SCISSOR_Y_MIN(hPrev, hCurr) (((RLSW.scClipMin[1])*(hPrev)[3] - (hPrev)[1])/(((hCurr)[1] - (RLSW.scClipMin[1])*(hCurr)[3]) - ((hPrev)[1] - (RLSW.scClipMin[1])*(hPrev)[3])))
+#define COMPUTE_T_SCISSOR_Y_MAX(hPrev, hCurr) (((RLSW.scClipMax[1])*(hPrev)[3] - (hPrev)[1])/(((hCurr)[1] - (RLSW.scClipMax[1])*(hCurr)[3]) - ((hPrev)[1] - (RLSW.scClipMax[1])*(hPrev)[3])))
+
+#define IS_INSIDE_SCISSOR_X_MIN(h) ((h)[0] >= (RLSW.scClipMin[0])*(h)[3])
+#define IS_INSIDE_SCISSOR_X_MAX(h) ((h)[0] <= (RLSW.scClipMax[0])*(h)[3])
+#define IS_INSIDE_SCISSOR_Y_MIN(h) ((h)[1] >= (RLSW.scClipMin[1])*(h)[3])
+#define IS_INSIDE_SCISSOR_Y_MAX(h) ((h)[1] <= (RLSW.scClipMax[1])*(h)[3])
+
+DEFINE_CLIP_FUNC(scissor_x_min, IS_INSIDE_SCISSOR_X_MIN, COMPUTE_T_SCISSOR_X_MIN)
+DEFINE_CLIP_FUNC(scissor_x_max, IS_INSIDE_SCISSOR_X_MAX, COMPUTE_T_SCISSOR_X_MAX)
+DEFINE_CLIP_FUNC(scissor_y_min, IS_INSIDE_SCISSOR_Y_MIN, COMPUTE_T_SCISSOR_Y_MIN)
+DEFINE_CLIP_FUNC(scissor_y_max, IS_INSIDE_SCISSOR_Y_MAX, COMPUTE_T_SCISSOR_Y_MAX)
+
+// Main clip function
+
+static inline bool sw_polygon_clip(sw_vertex_t polygon[SW_MAX_CLIPPED_POLYGON_VERTICES], int *vertexCounter)
+{
+ static sw_vertex_t tmp[SW_MAX_CLIPPED_POLYGON_VERTICES];
+
+ int n = *vertexCounter;
+
+ #define CLIP_AGAINST_PLANE(FUNC_CLIP) \
+ { \
+ n = FUNC_CLIP(tmp, polygon, n); \
+ if (n < 3) \
+ { \
+ *vertexCounter = 0; \
+ return false; \
+ } \
+ for (int i = 0; i < n; i++) polygon[i] = tmp[i]; \
+ }
+
+ CLIP_AGAINST_PLANE(sw_clip_w);
+ CLIP_AGAINST_PLANE(sw_clip_x_pos);
+ CLIP_AGAINST_PLANE(sw_clip_x_neg);
+ CLIP_AGAINST_PLANE(sw_clip_y_pos);
+ CLIP_AGAINST_PLANE(sw_clip_y_neg);
+ CLIP_AGAINST_PLANE(sw_clip_z_pos);
+ CLIP_AGAINST_PLANE(sw_clip_z_neg);
+
+ if (RLSW.stateFlags & SW_STATE_SCISSOR_TEST)
+ {
+ CLIP_AGAINST_PLANE(sw_clip_scissor_x_min);
+ CLIP_AGAINST_PLANE(sw_clip_scissor_x_max);
+ CLIP_AGAINST_PLANE(sw_clip_scissor_y_min);
+ CLIP_AGAINST_PLANE(sw_clip_scissor_y_max);
+ }
+
+ *vertexCounter = n;
+
+ return (n >= 3);
+}
+
+// Triangle rendering logic
+
+static inline bool sw_triangle_face_culling(void)
+{
+ // NOTE: Face culling is done before clipping to avoid unnecessary computations.
+ // To handle triangles crossing the w=0 plane correctly,
+ // we perform the winding order test in homogeneous coordinates directly,
+ // before the perspective division (division by w).
+ // This test determines the orientation of the triangle in the (x,y,w) plane,
+ // which corresponds to the projected 2D winding order sign,
+ // even with negative w values.
+
+ // Preload homogeneous coordinates into local variables
+ const float *h0 = RLSW.vertexBuffer[0].homogeneous;
+ const float *h1 = RLSW.vertexBuffer[1].homogeneous;
+ const float *h2 = RLSW.vertexBuffer[2].homogeneous;
+
+ // Compute a value proportional to the signed area in the projected 2D plane,
+ // calculated directly using homogeneous coordinates BEFORE division by w.
+ // This is the determinant of the matrix formed by the (x, y, w) components
+ // of the vertices, which correctly captures the winding order in homogeneous
+ // space and its relationship to the projected 2D winding order, even with
+ // negative w values.
+ // The determinant formula used here is:
+ // h0.x*(h1.y*h2.w - h2.y*h1.w) +
+ // h1.x*(h2.y*h0.w - h0.y*h2.w) +
+ // h2.x*(h0.y*h1.w - h1.y*h0.w)
+
+ const float hSgnArea =
+ h0[0]*(h1[1]*h2[3] - h2[1]*h1[3]) +
+ h1[0]*(h2[1]*h0[3] - h0[1]*h2[3]) +
+ h2[0]*(h0[1]*h1[3] - h1[1]*h0[3]);
+
+ // Discard the triangle if its winding order (determined by the sign
+ // of the homogeneous area/determinant) matches the culled direction.
+ // A positive hSgnArea typically corresponds to a counter-clockwise
+ // winding in the projected space when all w > 0.
+ // This test is robust for points with w > 0 or w < 0, correctly
+ // capturing the change in orientation when crossing the w=0 plane.
+
+ // The culling logic remains the same based on the signed area/determinant.
+ // A value of 0 for hSgnArea means the points are collinear in (x, y, w)
+ // space, which corresponds to a degenerate triangle projection.
+ // Such triangles are typically not culled by this test (0 < 0 is false, 0 > 0 is false)
+ // and should be handled by the clipper if necessary.
+ return (RLSW.cullFace == SW_FRONT)
+ ? (hSgnArea < 0) // Cull if winding is "clockwise" in the projected sense
+ : (hSgnArea > 0); // Cull if winding is "counter-clockwise" in the projected sense
+}
+
+static inline void sw_triangle_clip_and_project(void)
+{
+ sw_vertex_t *polygon = RLSW.vertexBuffer;
+ int *vertexCounter = &RLSW.vertexCounter;
+
+ if (sw_polygon_clip(polygon, vertexCounter))
+ {
+ // Transformation to screen space and normalization
+ for (int i = 0; i < *vertexCounter; i++)
+ {
+ sw_vertex_t *v = &polygon[i];
+
+ // Calculation of the reciprocal of W for normalization
+ // as well as perspective-correct attributes
+ const float invW = 1.0f/v->homogeneous[3];
+ v->homogeneous[3] = invW;
+
+ // Division of XYZ coordinates by weight
+ v->homogeneous[0] *= invW;
+ v->homogeneous[1] *= invW;
+ v->homogeneous[2] *= invW;
+
+ // Division of texture coordinates (perspective-correct)
+ v->texcoord[0] *= invW;
+ v->texcoord[1] *= invW;
+
+ // Division of colors (perspective-correct)
+ v->color[0] *= invW;
+ v->color[1] *= invW;
+ v->color[2] *= invW;
+ v->color[3] *= invW;
+
+ // Transformation to screen space
+ sw_project_ndc_to_screen(v->screen, v->homogeneous);
+ }
+ }
+}
+
+#define DEFINE_TRIANGLE_RASTER_SCANLINE(FUNC_NAME, ENABLE_TEXTURE, ENABLE_DEPTH_TEST, ENABLE_COLOR_BLEND) \
+static inline void FUNC_NAME(const sw_texture_t *tex, const sw_vertex_t *start, \
+ const sw_vertex_t *end, float duDy, float dvDy) \
+{ \
+ /* Convert and center the screen coordinates */ \
+ int xStart = (int)(start->screen[0] + 0.5f); \
+ int xEnd = (int)(end->screen[0] + 0.5f); \
+ int y = (int)start->screen[1]; \
+ \
+ /* Compute the inverse horizontal distance along the X axis */ \
+ float dx = end->screen[0] - start->screen[0]; \
+ if (fabsf(dx) < 1e-6f) return; \
+ float dxRcp = 1.0f/dx; \
+ \
+ /* Compute the interpolation steps along the X axis */ \
+ float dzDx = (end->homogeneous[2] - start->homogeneous[2])*dxRcp; \
+ float dwDx = (end->homogeneous[3] - start->homogeneous[3])*dxRcp; \
+ \
+ float dcDx[4] = { 0 }; \
+ dcDx[0] = (end->color[0] - start->color[0])*dxRcp; \
+ dcDx[1] = (end->color[1] - start->color[1])*dxRcp; \
+ dcDx[2] = (end->color[2] - start->color[2])*dxRcp; \
+ dcDx[3] = (end->color[3] - start->color[3])*dxRcp; \
+ \
+ float duDx = 0.0f, dvDx = 0.0f; \
+ if (ENABLE_TEXTURE) { \
+ duDx = (end->texcoord[0] - start->texcoord[0])*dxRcp; \
+ dvDx = (end->texcoord[1] - start->texcoord[1])*dxRcp; \
+ } \
+ \
+ /* Initializing the interpolation starting values */ \
+ float z = start->homogeneous[2]; \
+ float w = start->homogeneous[3]; \
+ \
+ float color[4] = { 0 }; \
+ color[0] = start->color[0]; \
+ color[1] = start->color[1]; \
+ color[2] = start->color[2]; \
+ color[3] = start->color[3]; \
+ \
+ float u = 0.0f, v = 0.0f; \
+ if (ENABLE_TEXTURE) { \
+ u = start->texcoord[0]; \
+ v = start->texcoord[1]; \
+ } \
+ \
+ /* Pre-calculate the starting pointers for the framebuffer row */ \
+ void *cptr = sw_framebuffer_get_color_addr(RLSW.framebuffer.color, y*RLSW.framebuffer.width + xStart); \
+ void *dptr = sw_framebuffer_get_depth_addr(RLSW.framebuffer.depth, y*RLSW.framebuffer.width + xStart); \
+ \
+ /* Scanline rasterization */ \
+ for (int x = xStart; x < xEnd; x++) \
+ { \
+ /* Test and write depth */ \
+ if (ENABLE_DEPTH_TEST) \
+ { \
+ /* TODO: Implement different depth funcs? */ \
+ float depth = sw_framebuffer_read_depth(dptr); \
+ if (z > depth) goto discard; \
+ } \
+ \
+ sw_framebuffer_write_depth(dptr, z); \
+ \
+ /* Pixel color computation */ \
+ float wRcp = 1.0f/w; \
+ float srcColor[4] = { \
+ color[0]*wRcp, \
+ color[1]*wRcp, \
+ color[2]*wRcp, \
+ color[3]*wRcp \
+ }; \
+ \
+ if (ENABLE_TEXTURE) \
+ { \
+ float texColor[4]; \
+ float s = u*wRcp; \
+ float t = v*wRcp; \
+ sw_texture_sample(texColor, tex, s, t, duDx, duDy, dvDx, dvDy); \
+ srcColor[0] *= texColor[0]; \
+ srcColor[1] *= texColor[1]; \
+ srcColor[2] *= texColor[2]; \
+ srcColor[3] *= texColor[3]; \
+ } \
+ \
+ if (ENABLE_COLOR_BLEND) \
+ { \
+ float dstColor[4]; \
+ sw_framebuffer_read_color(dstColor, cptr); \
+ \
+ sw_blend_colors(dstColor, srcColor); \
+ dstColor[0] = sw_saturate(dstColor[0]); \
+ dstColor[1] = sw_saturate(dstColor[1]); \
+ dstColor[2] = sw_saturate(dstColor[2]); \
+ \
+ sw_framebuffer_write_color(cptr, dstColor); \
+ } \
+ else \
+ { \
+ sw_framebuffer_write_color(cptr, srcColor); \
+ } \
+ \
+ /* Increment the interpolation parameter, UVs, and pointers */ \
+ discard: \
+ z += dzDx; \
+ w += dwDx; \
+ color[0] += dcDx[0]; \
+ color[1] += dcDx[1]; \
+ color[2] += dcDx[2]; \
+ color[3] += dcDx[3]; \
+ if (ENABLE_TEXTURE) \
+ { \
+ u += duDx; \
+ v += dvDx; \
+ } \
+ \
+ sw_framebuffer_inc_color_addr(&cptr); \
+ sw_framebuffer_inc_depth_addr(&dptr); \
+ } \
+}
+
+#define DEFINE_TRIANGLE_RASTER(FUNC_NAME, FUNC_SCANLINE, ENABLE_TEXTURE) \
+static inline void FUNC_NAME(const sw_vertex_t *v0, const sw_vertex_t *v1, \
+ const sw_vertex_t *v2, const sw_texture_t *tex) \
+{ \
+ /* Swap vertices by increasing y */ \
+ if (v0->screen[1] > v1->screen[1]) { const sw_vertex_t *tmp = v0; v0 = v1; v1 = tmp; } \
+ if (v1->screen[1] > v2->screen[1]) { const sw_vertex_t *tmp = v1; v1 = v2; v2 = tmp; } \
+ if (v0->screen[1] > v1->screen[1]) { const sw_vertex_t *tmp = v0; v0 = v1; v1 = tmp; } \
+ \
+ /* Extracting coordinates from the sorted vertices */ \
+ float x0 = v0->screen[0], y0 = v0->screen[1]; \
+ float x1 = v1->screen[0], y1 = v1->screen[1]; \
+ float x2 = v2->screen[0], y2 = v2->screen[1]; \
+ \
+ /* Compute height differences */ \
+ float h02 = y2 - y0; \
+ float h01 = y1 - y0; \
+ float h12 = y2 - y1; \
+ \
+ if (h02 < 1e-6f) return; \
+ \
+ /* Precompute the inverse values without additional checks */ \
+ float invH02 = 1.0f/h02; \
+ float invH01 = (h01 > 1e-6f)? 1.0f/h01 : 0.0f; \
+ float invH12 = (h12 > 1e-6f)? 1.0f/h12 : 0.0f; \
+ \
+ /* Pre-calculation of slopes */ \
+ float dx02 = (x2 - x0)*invH02; \
+ float dx01 = (x1 - x0)*invH01; \
+ float dx12 = (x2 - x1)*invH12; \
+ \
+ /* Y bounds (vertical clipping) */ \
+ int yTop = (int)(y0 + 0.5f); \
+ int yMiddle = (int)(y1 + 0.5f); \
+ int yBottom = (int)(y2 + 0.5f); \
+ \
+ /* Compute gradients for each side of the triangle */ \
+ sw_vertex_t vDy02, vDy01, vDy12; \
+ sw_get_vertex_grad_PTCH(&vDy02, v0, v2, invH02); \
+ sw_get_vertex_grad_PTCH(&vDy01, v0, v1, invH01); \
+ sw_get_vertex_grad_PTCH(&vDy12, v1, v2, invH12); \
+ \
+ /* Initializing scanline variables */ \
+ sw_vertex_t vLeft = *v0; \
+ vLeft.screen[0] = x0; \
+ sw_vertex_t vRight = *v0; \
+ vRight.screen[0] = x0; \
+ \
+ /* Scanline for the upper part of the triangle */ \
+ for (int y = yTop; y < yMiddle; y++) \
+ { \
+ vLeft.screen[1] = vRight.screen[1] = y; \
+ \
+ if (vLeft.screen[0] < vRight.screen[0]) FUNC_SCANLINE(tex, &vLeft, &vRight, vDy02.texcoord[0], vDy02.texcoord[1]); \
+ else FUNC_SCANLINE(tex, &vRight, &vLeft, vDy02.texcoord[0], vDy02.texcoord[1]); \
+ \
+ sw_add_vertex_grad_PTCH(&vLeft, &vDy02); \
+ vLeft.screen[0] += dx02; \
+ sw_add_vertex_grad_PTCH(&vRight, &vDy01); \
+ vRight.screen[0] += dx01; \
+ } \
+ \
+ /* Scanline for the lower part of the triangle */ \
+ vRight = *v1, vRight.screen[0] = x1; \
+ \
+ for (int y = yMiddle; y < yBottom; y++) \
+ { \
+ vLeft.screen[1] = vRight.screen[1] = y; \
+ \
+ if (vLeft.screen[0] < vRight.screen[0]) FUNC_SCANLINE(tex, &vLeft, &vRight, vDy02.texcoord[0], vDy02.texcoord[1]); \
+ else FUNC_SCANLINE(tex, &vRight, &vLeft, vDy02.texcoord[0], vDy02.texcoord[1]); \
+ \
+ sw_add_vertex_grad_PTCH(&vLeft, &vDy02); \
+ vLeft.screen[0] += dx02; \
+ sw_add_vertex_grad_PTCH(&vRight, &vDy12); \
+ vRight.screen[0] += dx12; \
+ } \
+}
+
+DEFINE_TRIANGLE_RASTER_SCANLINE(sw_triangle_raster_scanline, 0, 0, 0)
+DEFINE_TRIANGLE_RASTER_SCANLINE(sw_triangle_raster_scanline_TEX, 1, 0, 0)
+DEFINE_TRIANGLE_RASTER_SCANLINE(sw_triangle_raster_scanline_DEPTH, 0, 1, 0)
+DEFINE_TRIANGLE_RASTER_SCANLINE(sw_triangle_raster_scanline_BLEND, 0, 0, 1)
+DEFINE_TRIANGLE_RASTER_SCANLINE(sw_triangle_raster_scanline_TEX_DEPTH, 1, 1, 0)
+DEFINE_TRIANGLE_RASTER_SCANLINE(sw_triangle_raster_scanline_TEX_BLEND, 1, 0, 1)
+DEFINE_TRIANGLE_RASTER_SCANLINE(sw_triangle_raster_scanline_DEPTH_BLEND, 0, 1, 1)
+DEFINE_TRIANGLE_RASTER_SCANLINE(sw_triangle_raster_scanline_TEX_DEPTH_BLEND, 1, 1, 1)
+
+DEFINE_TRIANGLE_RASTER(sw_triangle_raster, sw_triangle_raster_scanline, false)
+DEFINE_TRIANGLE_RASTER(sw_triangle_raster_TEX, sw_triangle_raster_scanline_TEX, true)
+DEFINE_TRIANGLE_RASTER(sw_triangle_raster_DEPTH, sw_triangle_raster_scanline_DEPTH, false)
+DEFINE_TRIANGLE_RASTER(sw_triangle_raster_BLEND, sw_triangle_raster_scanline_BLEND, false)
+DEFINE_TRIANGLE_RASTER(sw_triangle_raster_TEX_DEPTH, sw_triangle_raster_scanline_TEX_DEPTH, true)
+DEFINE_TRIANGLE_RASTER(sw_triangle_raster_TEX_BLEND, sw_triangle_raster_scanline_TEX_BLEND, true)
+DEFINE_TRIANGLE_RASTER(sw_triangle_raster_DEPTH_BLEND, sw_triangle_raster_scanline_DEPTH_BLEND, false)
+DEFINE_TRIANGLE_RASTER(sw_triangle_raster_TEX_DEPTH_BLEND, sw_triangle_raster_scanline_TEX_DEPTH_BLEND, true)
+
+static inline void sw_triangle_render(void)
+{
+ if (RLSW.stateFlags & SW_STATE_CULL_FACE)
+ {
+ if (!sw_triangle_face_culling()) return;
+ }
+
+ sw_triangle_clip_and_project();
+
+ if (RLSW.vertexCounter < 3) return;
+
+ #define TRIANGLE_RASTER(RASTER_FUNC) \
+ { \
+ for (int i = 0; i < RLSW.vertexCounter - 2; i++) \
+ { \
+ RASTER_FUNC( \
+ &RLSW.vertexBuffer[0], \
+ &RLSW.vertexBuffer[i + 1], \
+ &RLSW.vertexBuffer[i + 2], \
+ &RLSW.loadedTextures[RLSW.currentTexture] \
+ ); \
+ } \
+ }
+
+ if (SW_STATE_CHECK(SW_STATE_TEXTURE_2D | SW_STATE_DEPTH_TEST | SW_STATE_BLEND)) TRIANGLE_RASTER(sw_triangle_raster_TEX_DEPTH_BLEND)
+ else if (SW_STATE_CHECK(SW_STATE_DEPTH_TEST | SW_STATE_BLEND)) TRIANGLE_RASTER(sw_triangle_raster_DEPTH_BLEND)
+ else if (SW_STATE_CHECK(SW_STATE_TEXTURE_2D | SW_STATE_BLEND)) TRIANGLE_RASTER(sw_triangle_raster_TEX_BLEND)
+ else if (SW_STATE_CHECK(SW_STATE_TEXTURE_2D | SW_STATE_DEPTH_TEST)) TRIANGLE_RASTER(sw_triangle_raster_TEX_DEPTH)
+ else if (SW_STATE_CHECK(SW_STATE_BLEND)) TRIANGLE_RASTER(sw_triangle_raster_BLEND)
+ else if (SW_STATE_CHECK(SW_STATE_DEPTH_TEST)) TRIANGLE_RASTER(sw_triangle_raster_DEPTH)
+ else if (SW_STATE_CHECK(SW_STATE_TEXTURE_2D)) TRIANGLE_RASTER(sw_triangle_raster_TEX)
+ else TRIANGLE_RASTER(sw_triangle_raster)
+
+ #undef TRIANGLE_RASTER
+}
+
+// Quad rendering logic
+
+static inline bool sw_quad_face_culling(void)
+{
+ // NOTE: Face culling is done before clipping to avoid unnecessary computations.
+ // To handle quads crossing the w=0 plane correctly,
+ // we perform the winding order test in homogeneous coordinates directly,
+ // before the perspective division (division by w).
+ // For a convex quad with vertices P0, P1, P2, P3 in sequential order,
+ // the winding order of the quad is the same as the winding order
+ // of the triangle P0 P1 P2. We use the homogeneous triangle
+ // winding test on this first triangle.
+
+ // Preload homogeneous coordinates into local variables
+ const float *h0 = RLSW.vertexBuffer[0].homogeneous;
+ const float *h1 = RLSW.vertexBuffer[1].homogeneous;
+ const float *h2 = RLSW.vertexBuffer[2].homogeneous;
+
+ // NOTE: h3 is not needed for this test
+ // const float *h3 = RLSW.vertexBuffer[3].homogeneous;
+
+ // Compute a value proportional to the signed area of the triangle P0 P1 P2
+ // in the projected 2D plane, calculated directly using homogeneous coordinates
+ // BEFORE division by w.
+ // This is the determinant of the matrix formed by the (x, y, w) components
+ // of the vertices P0, P1, and P2. Its sign correctly indicates the winding order
+ // in homogeneous space and its relationship to the projected 2D winding order,
+ // even with negative w values.
+ // The determinant formula used here is:
+ // h0.x*(h1.y*h2.w - h2.y*h1.w) +
+ // h1.x*(h2.y*h0.w - h0.y*h2.w) +
+ // h2.x*(h0.y*h1.w - h1.y*h0.w)
+
+ const float hSgnArea =
+ h0[0]*(h1[1]*h2[3] - h2[1]*h1[3]) +
+ h1[0]*(h2[1]*h0[3] - h0[1]*h2[3]) +
+ h2[0]*(h0[1]*h1[3] - h1[1]*h0[3]);
+
+ // Perform face culling based on the winding order determined by the sign
+ // of the homogeneous area/determinant of triangle P0 P1 P2.
+ // This test is robust for points with w > 0 or w < 0 within the triangle,
+ // correctly capturing the change in orientation when crossing the w=0 plane.
+
+ // A positive hSgnArea typically corresponds to a counter-clockwise
+ // winding in the projected space when all w > 0.
+ // A value of 0 for hSgnArea means P0, P1, P2 are collinear in (x, y, w)
+ // space, which corresponds to a degenerate triangle projection.
+ // Such quads might also be degenerate or non-planar. They are typically
+ // not culled by this test (0 < 0 is false, 0 > 0 is false)
+ // and should be handled by the clipper if necessary.
+
+ return (RLSW.cullFace == SW_FRONT)
+ ? (hSgnArea < 0.0f) // Cull if winding is "clockwise" in the projected sense
+ : (hSgnArea > 0.0f); // Cull if winding is "counter-clockwise" in the projected sense
+}
+
+static inline void sw_quad_clip_and_project(void)
+{
+ sw_vertex_t *polygon = RLSW.vertexBuffer;
+ int *vertexCounter = &RLSW.vertexCounter;
+
+ if (sw_polygon_clip(polygon, vertexCounter))
+ {
+ // Transformation to screen space and normalization
+ for (int i = 0; i < *vertexCounter; i++)
+ {
+ sw_vertex_t *v = &polygon[i];
+
+ // Calculation of the reciprocal of W for normalization
+ // as well as perspective-correct attributes
+ const float invW = 1.0f/v->homogeneous[3];
+ v->homogeneous[3] = invW;
+
+ // Division of XYZ coordinates by weight
+ v->homogeneous[0] *= invW;
+ v->homogeneous[1] *= invW;
+ v->homogeneous[2] *= invW;
+
+ // Division of texture coordinates (perspective-correct)
+ v->texcoord[0] *= invW;
+ v->texcoord[1] *= invW;
+
+ // Division of colors (perspective-correct)
+ v->color[0] *= invW;
+ v->color[1] *= invW;
+ v->color[2] *= invW;
+ v->color[3] *= invW;
+
+ // Transformation to screen space
+ sw_project_ndc_to_screen(v->screen, v->homogeneous);
+ }
+ }
+}
+
+static inline bool sw_quad_is_axis_aligned(void)
+{
+ int horizontal = 0;
+ int vertical = 0;
+
+ for (int i = 0; i < 4; i++)
+ {
+ if (RLSW.vertexBuffer[i].homogeneous[3] != 1.0f) return false;
+
+ const float *v0 = RLSW.vertexBuffer[i].position;
+ const float *v1 = RLSW.vertexBuffer[(i + 1)%4].position;
+
+ float dx = v1[0] - v0[0];
+ float dy = v1[1] - v0[1];
+
+ if (fabsf(dx) > 1e-6f && fabsf(dy) < 1e-6f) horizontal++;
+ else if (fabsf(dy) > 1e-6f && fabsf(dx) < 1e-6f) vertical++;
+ else return false; // Diagonal edge -> not axis-aligned
+ }
+
+ return ((horizontal == 2) && (vertical == 2));
+}
+
+static inline void sw_quad_sort_cw(const sw_vertex_t* *output)
+{
+ // Sort 4 quad vertices into clockwise order with fixed layout:
+ //
+ // v0 -- v1
+ // | |
+ // v3 -- v2
+ //
+ // The goal is:
+ // - v0: top-left (minimum Y, then minimum X)
+ // - v1: top-right (minimum Y row, maximum X)
+ // - v2: bottom-right (maximum Y, maximum X)
+ // - v3: bottom-left (maximum Y, minimum X)
+ const sw_vertex_t *input = RLSW.vertexBuffer;
+
+ // Separate vertices into top and bottom based on Y-coordinate
+ const sw_vertex_t *top[2] = {NULL, NULL};
+ const sw_vertex_t *bottom[2] = {NULL, NULL};
+ int topCount = 0, bottomCount = 0;
+
+ // Find minimum and maximum Y
+ float minY = input[0].screen[1];
+ float maxY = input[0].screen[1];
+
+ for (int i = 1; i < 4; i++)
+ {
+ if (input[i].screen[1] < minY) minY = input[i].screen[1];
+ if (input[i].screen[1] > maxY) maxY = input[i].screen[1];
+ }
+
+ // Separate vertices based on Y-coordinate
+ for (int i = 0; i < 4; i++)
+ {
+ if (input[i].screen[1] == minY && topCount < 2) top[topCount++] = &input[i];
+ else if (input[i].screen[1] == maxY && bottomCount < 2) bottom[bottomCount++] = &input[i];
+ }
+
+ // If we don't have enough top/bottom vertices (e.g., Y values are all different),
+ // classify vertices as top or bottom based on whether they're closer to minY or maxY
+ for (int i = 0; i < 4; i++)
+ {
+ if ((topCount < 2) && (&input[i] != top[0]) && (&input[i] != bottom[0]) && (&input[i] != bottom[1]))
+ {
+ if (fabsf(input[i].screen[1] - minY) <= fabsf(input[i].screen[1] - maxY)) top[topCount++] = &input[i];
+ }
+ if ((bottomCount < 2) && (&input[i] != top[0]) && (&input[i] != top[1]) && (&input[i] != bottom[0]))
+ {
+ if (fabsf(input[i].screen[1] - maxY) < fabsf(input[i].screen[1] - minY)) bottom[bottomCount++] = &input[i];
+ }
+ }
+
+ // Sort top vertices by X (left to right)
+ if ((topCount == 2) && (top[0]->screen[0] > top[1]->screen[0]))
+ {
+ const sw_vertex_t *temp = top[0];
+ top[0] = top[1];
+ top[1] = temp;
+ }
+
+ // Sort bottom vertices by X (left to right)
+ if (bottomCount == 2 && bottom[0]->screen[0] > bottom[1]->screen[0])
+ {
+ const sw_vertex_t *temp = bottom[0];
+ bottom[0] = bottom[1];
+ bottom[1] = temp;
+ }
+
+ // Assign vertices in clockwise order as per the required layout
+ output[0] = top[0]; // v0: top-left
+ output[1] = top[topCount-1]; // v1: top-right
+ output[2] = bottom[bottomCount-1]; // v2: bottom-right
+ output[3] = bottom[0]; // v3: bottom-left
+}
+
+// TODO: REVIEW: Could a perfectly aligned quad, where one of the four points has a different depth,
+// still appear perfectly aligned from a certain point of view?
+// Because in that case, we would still need to perform perspective division for textures and colors...
+#define DEFINE_QUAD_RASTER_AXIS_ALIGNED(FUNC_NAME, ENABLE_TEXTURE, ENABLE_DEPTH_TEST, ENABLE_COLOR_BLEND) \
+static inline void FUNC_NAME(void) \
+{ \
+ const sw_vertex_t *sortedVerts[4]; \
+ sw_quad_sort_cw(sortedVerts); \
+ \
+ const sw_vertex_t *v0 = sortedVerts[0]; \
+ const sw_vertex_t *v1 = sortedVerts[1]; \
+ const sw_vertex_t *v2 = sortedVerts[2]; \
+ const sw_vertex_t *v3 = sortedVerts[3]; \
+ \
+ /* Screen bounds (axis-aligned) */ \
+ int xMin = (int)(v0->screen[0] + 0.5f); \
+ int yMin = (int)(v0->screen[1] + 0.5f); \
+ int xMax = (int)(v2->screen[0] + 0.5f); \
+ int yMax = (int)(v2->screen[1] + 0.5f); \
+ \
+ int width = xMax - xMin; \
+ int height = yMax - yMin; \
+ \
+ if (width == 0 || height == 0) return; \
+ \
+ float wRcp = (width > 0.0f)? 1.0f/width : 0.0f; \
+ float hRcp = (height > 0.0f)? 1.0f/height : 0.0f; \
+ \
+ /* Calculation of vertex gradients in X and Y */ \
+ float tcDx[2], tcDy[2]; \
+ if (ENABLE_TEXTURE) { \
+ tcDx[0] = (v1->texcoord[0] - v0->texcoord[0])*wRcp; \
+ tcDx[1] = (v1->texcoord[1] - v0->texcoord[1])*wRcp; \
+ tcDy[0] = (v3->texcoord[0] - v0->texcoord[0])*hRcp; \
+ tcDy[1] = (v3->texcoord[1] - v0->texcoord[1])*hRcp; \
+ } \
+ \
+ float cDx[4], cDy[4]; \
+ cDx[0] = (v1->color[0] - v0->color[0])*wRcp; \
+ cDx[1] = (v1->color[1] - v0->color[1])*wRcp; \
+ cDx[2] = (v1->color[2] - v0->color[2])*wRcp; \
+ cDx[3] = (v1->color[3] - v0->color[3])*wRcp; \
+ cDy[0] = (v3->color[0] - v0->color[0])*hRcp; \
+ cDy[1] = (v3->color[1] - v0->color[1])*hRcp; \
+ cDy[2] = (v3->color[2] - v0->color[2])*hRcp; \
+ cDy[3] = (v3->color[3] - v0->color[3])*hRcp; \
+ \
+ float zDx, zDy; \
+ zDx = (v1->homogeneous[2] - v0->homogeneous[2])*wRcp; \
+ zDy = (v3->homogeneous[2] - v0->homogeneous[2])*hRcp; \
+ \
+ /* Start of quad rasterization */ \
+ const sw_texture_t *tex; \
+ if (ENABLE_TEXTURE) tex = &RLSW.loadedTextures[RLSW.currentTexture]; \
+ \
+ void *cDstBase = RLSW.framebuffer.color; \
+ void *dDstBase = RLSW.framebuffer.depth; \
+ int wDst = RLSW.framebuffer.width; \
+ \
+ float zScanline = v0->homogeneous[2]; \
+ float uScanline = v0->texcoord[0]; \
+ float vScanline = v0->texcoord[1]; \
+ \
+ float colorScanline[4] = { \
+ v0->color[0], \
+ v0->color[1], \
+ v0->color[2], \
+ v0->color[3] \
+ }; \
+ \
+ for (int y = yMin; y < yMax; y++) \
+ { \
+ void *cptr = sw_framebuffer_get_color_addr(cDstBase, y*wDst + xMin); \
+ void *dptr = sw_framebuffer_get_depth_addr(dDstBase, y*wDst + xMin); \
+ \
+ float z = zScanline; \
+ float u = uScanline; \
+ float v = vScanline; \
+ \
+ float color[4] = { \
+ colorScanline[0], \
+ colorScanline[1], \
+ colorScanline[2], \
+ colorScanline[3] \
+ }; \
+ \
+ /* Scanline rasterization */ \
+ for (int x = xMin; x < xMax; x++) \
+ { \
+ /* Test and write depth */ \
+ if (ENABLE_DEPTH_TEST) \
+ { \
+ /* TODO: Implement different depth funcs? */ \
+ float depth = sw_framebuffer_read_depth(dptr); \
+ if (z > depth) goto discard; \
+ } \
+ \
+ sw_framebuffer_write_depth(dptr, z); \
+ \
+ /* Pixel color computation */ \
+ float srcColor[4] = { \
+ color[0], \
+ color[1], \
+ color[2], \
+ color[3] \
+ }; \
+ \
+ if (ENABLE_TEXTURE) \
+ { \
+ float texColor[4]; \
+ sw_texture_sample(texColor, tex, u, v, tcDx[0], tcDy[0], tcDx[1], tcDy[1]); \
+ srcColor[0] *= texColor[0]; \
+ srcColor[1] *= texColor[1]; \
+ srcColor[2] *= texColor[2]; \
+ srcColor[3] *= texColor[3]; \
+ } \
+ \
+ if (ENABLE_COLOR_BLEND) \
+ { \
+ float dstColor[4]; \
+ sw_framebuffer_read_color(dstColor, cptr); \
+ \
+ sw_blend_colors(dstColor, srcColor); \
+ dstColor[0] = sw_saturate(dstColor[0]); \
+ dstColor[1] = sw_saturate(dstColor[1]); \
+ dstColor[2] = sw_saturate(dstColor[2]); \
+ dstColor[3] = sw_saturate(dstColor[3]); \
+ \
+ sw_framebuffer_write_color(cptr, dstColor); \
+ } \
+ else sw_framebuffer_write_color(cptr, srcColor); \
+ \
+ discard: \
+ z += zDx; \
+ color[0] += cDx[0]; \
+ color[1] += cDx[1]; \
+ color[2] += cDx[2]; \
+ color[3] += cDx[3]; \
+ \
+ if (ENABLE_TEXTURE) \
+ { \
+ u += tcDx[0]; \
+ v += tcDx[1]; \
+ } \
+ \
+ sw_framebuffer_inc_color_addr(&cptr); \
+ sw_framebuffer_inc_depth_addr(&dptr); \
+ } \
+ \
+ zScanline += zDy; \
+ colorScanline[0] += cDy[0]; \
+ colorScanline[1] += cDy[1]; \
+ colorScanline[2] += cDy[2]; \
+ colorScanline[3] += cDy[3]; \
+ \
+ if (ENABLE_TEXTURE) \
+ { \
+ uScanline += tcDy[0]; \
+ vScanline += tcDy[1]; \
+ } \
+ } \
+}
+
+DEFINE_QUAD_RASTER_AXIS_ALIGNED(sw_quad_raster_axis_aligned, 0, 0, 0)
+DEFINE_QUAD_RASTER_AXIS_ALIGNED(sw_quad_raster_axis_aligned_TEX, 1, 0, 0)
+DEFINE_QUAD_RASTER_AXIS_ALIGNED(sw_quad_raster_axis_aligned_DEPTH, 0, 1, 0)
+DEFINE_QUAD_RASTER_AXIS_ALIGNED(sw_quad_raster_axis_aligned_BLEND, 0, 0, 1)
+DEFINE_QUAD_RASTER_AXIS_ALIGNED(sw_quad_raster_axis_aligned_TEX_DEPTH, 1, 1, 0)
+DEFINE_QUAD_RASTER_AXIS_ALIGNED(sw_quad_raster_axis_aligned_TEX_BLEND, 1, 0, 1)
+DEFINE_QUAD_RASTER_AXIS_ALIGNED(sw_quad_raster_axis_aligned_DEPTH_BLEND, 0, 1, 1)
+DEFINE_QUAD_RASTER_AXIS_ALIGNED(sw_quad_raster_axis_aligned_TEX_DEPTH_BLEND, 1, 1, 1)
+
+static inline void sw_quad_render(void)
+{
+ if (RLSW.stateFlags & SW_STATE_CULL_FACE)
+ {
+ if (!sw_quad_face_culling()) return;
+ }
+
+ sw_quad_clip_and_project();
+
+ if (RLSW.vertexCounter < 3) return;
+
+ if (RLSW.vertexCounter == 4 && sw_quad_is_axis_aligned())
+ {
+ if (SW_STATE_CHECK(SW_STATE_TEXTURE_2D | SW_STATE_DEPTH_TEST | SW_STATE_BLEND)) sw_quad_raster_axis_aligned_TEX_DEPTH_BLEND();
+ else if (SW_STATE_CHECK(SW_STATE_DEPTH_TEST | SW_STATE_BLEND)) sw_quad_raster_axis_aligned_DEPTH_BLEND();
+ else if (SW_STATE_CHECK(SW_STATE_TEXTURE_2D | SW_STATE_BLEND)) sw_quad_raster_axis_aligned_TEX_BLEND();
+ else if (SW_STATE_CHECK(SW_STATE_TEXTURE_2D | SW_STATE_DEPTH_TEST)) sw_quad_raster_axis_aligned_TEX_DEPTH();
+ else if (SW_STATE_CHECK(SW_STATE_BLEND)) sw_quad_raster_axis_aligned_BLEND();
+ else if (SW_STATE_CHECK(SW_STATE_DEPTH_TEST)) sw_quad_raster_axis_aligned_DEPTH();
+ else if (SW_STATE_CHECK(SW_STATE_TEXTURE_2D)) sw_quad_raster_axis_aligned_TEX();
+ else sw_quad_raster_axis_aligned();
+ return;
+ }
+
+ #define TRIANGLE_RASTER(RASTER_FUNC) \
+ { \
+ for (int i = 0; i < RLSW.vertexCounter - 2; i++) \
+ { \
+ RASTER_FUNC( \
+ &RLSW.vertexBuffer[0], \
+ &RLSW.vertexBuffer[i + 1], \
+ &RLSW.vertexBuffer[i + 2], \
+ &RLSW.loadedTextures[RLSW.currentTexture] \
+ ); \
+ } \
+ }
+
+ if (SW_STATE_CHECK(SW_STATE_TEXTURE_2D | SW_STATE_DEPTH_TEST | SW_STATE_BLEND)) TRIANGLE_RASTER(sw_triangle_raster_TEX_DEPTH_BLEND)
+ else if (SW_STATE_CHECK(SW_STATE_DEPTH_TEST | SW_STATE_BLEND)) TRIANGLE_RASTER(sw_triangle_raster_DEPTH_BLEND)
+ else if (SW_STATE_CHECK(SW_STATE_TEXTURE_2D | SW_STATE_BLEND)) TRIANGLE_RASTER(sw_triangle_raster_TEX_BLEND)
+ else if (SW_STATE_CHECK(SW_STATE_TEXTURE_2D | SW_STATE_DEPTH_TEST)) TRIANGLE_RASTER(sw_triangle_raster_TEX_DEPTH)
+ else if (SW_STATE_CHECK(SW_STATE_BLEND)) TRIANGLE_RASTER(sw_triangle_raster_BLEND)
+ else if (SW_STATE_CHECK(SW_STATE_DEPTH_TEST)) TRIANGLE_RASTER(sw_triangle_raster_DEPTH)
+ else if (SW_STATE_CHECK(SW_STATE_TEXTURE_2D)) TRIANGLE_RASTER(sw_triangle_raster_TEX)
+ else TRIANGLE_RASTER(sw_triangle_raster)
+
+ #undef TRIANGLE_RASTER
+}
+
+// Line rendering logic
+
+static inline bool sw_line_clip_coord(float q, float p, float *t0, float *t1)
+{
+ if (fabsf(p) < SW_CLIP_EPSILON)
+ {
+ // Check if the line is entirely outside the window
+ if (q < -SW_CLIP_EPSILON) return 0; // Completely outside
+ return 1; // Completely inside or on the edges
+ }
+
+ const float r = q/p;
+
+ if (p < 0)
+ {
+ if (r > *t1) return 0;
+ if (r > *t0) *t0 = r;
+ }
+ else
+ {
+ if (r < *t0) return 0;
+ if (r < *t1) *t1 = r;
+ }
+
+ return 1;
+}
+
+static inline bool sw_line_clip(sw_vertex_t *v0, sw_vertex_t *v1)
+{
+ float t0 = 0.0f, t1 = 1.0f;
+ float dH[4], dC[4];
+
+ for (int i = 0; i < 4; i++)
+ {
+ dH[i] = v1->homogeneous[i] - v0->homogeneous[i];
+ dC[i] = v1->color[i] - v0->color[i];
+ }
+
+ // Clipping Liang-Barsky
+ if (!sw_line_clip_coord(v0->homogeneous[3] - v0->homogeneous[0], -dH[3] + dH[0], &t0, &t1)) return false;
+ if (!sw_line_clip_coord(v0->homogeneous[3] + v0->homogeneous[0], -dH[3] - dH[0], &t0, &t1)) return false;
+ if (!sw_line_clip_coord(v0->homogeneous[3] - v0->homogeneous[1], -dH[3] + dH[1], &t0, &t1)) return false;
+ if (!sw_line_clip_coord(v0->homogeneous[3] + v0->homogeneous[1], -dH[3] - dH[1], &t0, &t1)) return false;
+ if (!sw_line_clip_coord(v0->homogeneous[3] - v0->homogeneous[2], -dH[3] + dH[2], &t0, &t1)) return false;
+ if (!sw_line_clip_coord(v0->homogeneous[3] + v0->homogeneous[2], -dH[3] - dH[2], &t0, &t1)) return false;
+
+ // Clipping Scissor
+ if (RLSW.stateFlags & SW_STATE_SCISSOR_TEST)
+ {
+ if (!sw_line_clip_coord(v0->homogeneous[0] - RLSW.scClipMin[0]*v0->homogeneous[3], RLSW.scClipMin[0]*dH[3] - dH[0], &t0, &t1)) return false;
+ if (!sw_line_clip_coord(RLSW.scClipMax[0]*v0->homogeneous[3] - v0->homogeneous[0], dH[0] - RLSW.scClipMax[0]*dH[3], &t0, &t1)) return false;
+ if (!sw_line_clip_coord(v0->homogeneous[1] - RLSW.scClipMin[1]*v0->homogeneous[3], RLSW.scClipMin[1]*dH[3] - dH[1], &t0, &t1)) return false;
+ if (!sw_line_clip_coord(RLSW.scClipMax[1]*v0->homogeneous[3] - v0->homogeneous[1], dH[1] - RLSW.scClipMax[1]*dH[3], &t0, &t1)) return false;
+ }
+
+ // Interpolation of new coordinates
+ if (t1 < 1.0f)
+ {
+ for (int i = 0; i < 4; i++)
+ {
+ v1->homogeneous[i] = v0->homogeneous[i] + t1*dH[i];
+ v1->color[i] = v0->color[i] + t1*dC[i];
+ }
+ }
+
+ if (t0 > 0.0f)
+ {
+ for (int i = 0; i < 4; i++)
+ {
+ v0->homogeneous[i] += t0*dH[i];
+ v0->color[i] += t0*dC[i];
+ }
+ }
+
+ return true;
+}
+
+static inline bool sw_line_clip_and_project(sw_vertex_t *v0, sw_vertex_t *v1)
+{
+ if (!sw_line_clip(v0, v1)) return false;
+
+ // Convert homogeneous coordinates to NDC
+ v0->homogeneous[3] = 1.0f/v0->homogeneous[3];
+ v1->homogeneous[3] = 1.0f/v1->homogeneous[3];
+ for (int i = 0; i < 3; i++)
+ {
+ v0->homogeneous[i] *= v0->homogeneous[3];
+ v1->homogeneous[i] *= v1->homogeneous[3];
+ }
+
+ // Convert NDC coordinates to screen space
+ sw_project_ndc_to_screen(v0->screen, v0->homogeneous);
+ sw_project_ndc_to_screen(v1->screen, v1->homogeneous);
+
+ return true;
+}
+
+#define DEFINE_LINE_RASTER(FUNC_NAME, ENABLE_DEPTH_TEST, ENABLE_COLOR_BLEND) \
+static inline void FUNC_NAME(const sw_vertex_t *v0, const sw_vertex_t *v1) \
+{ \
+ int x1 = (int)(v0->screen[0] + 0.5f); \
+ int y1 = (int)(v0->screen[1] + 0.5f); \
+ int x2 = (int)(v1->screen[0] + 0.5f); \
+ int y2 = (int)(v1->screen[1] + 0.5f); \
+ \
+ int dx = x2 - x1; \
+ int dy = y2 - y1; \
+ \
+ /* Handling of lines that are more horizontal or vertical */ \
+ if (dx == 0 && dy == 0) \
+ { \
+ /* TODO: A point should be rendered here */ \
+ return; \
+ } \
+ \
+ bool yLonger = (abs(dy) > abs(dx)); \
+ int longLen, shortLen; \
+ \
+ if (yLonger) \
+ { \
+ longLen = dy; \
+ shortLen = dx; \
+ } \
+ else \
+ { \
+ longLen = dx; \
+ shortLen = dy; \
+ } \
+ \
+ /* Handling of traversal direction */ \
+ int sgnInc = (longLen < 0)? -1 : 1; \
+ int abslongLen = abs(longLen); \
+ \
+ /* Calculation of the increment step for the shorter coordinate */ \
+ int decInc = 0; \
+ if (abslongLen != 0) decInc = (shortLen << 16)/abslongLen; \
+ \
+ float longLenRcp = (abslongLen != 0)? (1.0f/abslongLen) : 0.0f; \
+ \
+ /* Calculation of interpolation steps */ \
+ const float zStep = (v1->homogeneous[2] - v0->homogeneous[2])*longLenRcp; \
+ const float rStep = (v1->color[0] - v0->color[0])*longLenRcp; \
+ const float gStep = (v1->color[1] - v0->color[1])*longLenRcp; \
+ const float bStep = (v1->color[2] - v0->color[2])*longLenRcp; \
+ const float aStep = (v1->color[3] - v0->color[3])*longLenRcp; \
+ \
+ float z = v0->homogeneous[2]; \
+ \
+ float color[4] = { \
+ v0->color[0], \
+ v0->color[1], \
+ v0->color[2], \
+ v0->color[3] \
+ }; \
+ \
+ const int fbWidth = RLSW.framebuffer.width; \
+ void *cBuffer = RLSW.framebuffer.color; \
+ void *dBuffer = RLSW.framebuffer.depth; \
+ \
+ int j = 0; \
+ if (yLonger) \
+ { \
+ for (int i = 0; i != longLen; i += sgnInc) \
+ { \
+ int offset = (y1 + i)*fbWidth + (x1 + (j >> 16)); \
+ void *dptr = sw_framebuffer_get_depth_addr(dBuffer, offset); \
+ \
+ if (ENABLE_DEPTH_TEST) \
+ { \
+ float depth = sw_framebuffer_read_depth(dptr); \
+ if (z > depth) goto discardA; \
+ } \
+ \
+ sw_framebuffer_write_depth(dptr, z); \
+ \
+ void *cptr = sw_framebuffer_get_color_addr(cBuffer, offset); \
+ \
+ if (ENABLE_COLOR_BLEND) \
+ { \
+ float dstColor[4]; \
+ sw_framebuffer_read_color(dstColor, cptr); \
+ \
+ sw_blend_colors(dstColor, color); \
+ sw_framebuffer_write_color(cptr, dstColor); \
+ } \
+ else sw_framebuffer_write_color(cptr, color); \
+ \
+ discardA: \
+ j += decInc; \
+ z += zStep; \
+ color[0] += rStep; \
+ color[1] += gStep; \
+ color[2] += bStep; \
+ color[3] += aStep; \
+ } \
+ } \
+ else \
+ { \
+ for (int i = 0; i != longLen; i += sgnInc) \
+ { \
+ int offset = (y1 + (j >> 16))*fbWidth + (x1 + i); \
+ void *dptr = sw_framebuffer_get_depth_addr(dBuffer, offset); \
+ \
+ if (ENABLE_DEPTH_TEST) \
+ { \
+ float depth = sw_framebuffer_read_depth(dptr); \
+ if (z > depth) goto discardB; \
+ } \
+ \
+ sw_framebuffer_write_depth(dptr, z); \
+ \
+ void *cptr = sw_framebuffer_get_color_addr(cBuffer, offset); \
+ \
+ if (ENABLE_COLOR_BLEND) \
+ { \
+ float dstColor[4]; \
+ sw_framebuffer_read_color(dstColor, cptr); \
+ \
+ sw_blend_colors(dstColor, color); \
+ sw_framebuffer_write_color(cptr, dstColor); \
+ } \
+ else sw_framebuffer_write_color(cptr, color); \
+ \
+ discardB: \
+ j += decInc; \
+ z += zStep; \
+ color[0] += rStep; \
+ color[1] += gStep; \
+ color[2] += bStep; \
+ color[3] += aStep; \
+ } \
+ } \
+}
+
+#define DEFINE_LINE_THICK_RASTER(FUNC_NAME, RASTER_FUNC) \
+void FUNC_NAME(const sw_vertex_t *v1, const sw_vertex_t *v2) \
+{ \
+ sw_vertex_t tv1, tv2; \
+ \
+ int x1 = (int)v1->screen[0]; \
+ int y1 = (int)v1->screen[1]; \
+ int x2 = (int)v2->screen[0]; \
+ int y2 = (int)v2->screen[1]; \
+ \
+ int dx = x2 - x1; \
+ int dy = y2 - y1; \
+ \
+ RASTER_FUNC(v1, v2); \
+ \
+ if (dx != 0 && abs(dy/dx) < 1) \
+ { \
+ int wy = (int)((RLSW.lineWidth - 1.0f)*abs(dx)/sqrtf(dx*dx + dy*dy)); \
+ wy >>= 1; \
+ for (int i = 1; i <= wy; i++) \
+ { \
+ tv1 = *v1, tv2 = *v2; \
+ tv1.screen[1] -= i; \
+ tv2.screen[1] -= i; \
+ RASTER_FUNC(&tv1, &tv2); \
+ tv1 = *v1, tv2 = *v2; \
+ tv1.screen[1] += i; \
+ tv2.screen[1] += i; \
+ RASTER_FUNC(&tv1, &tv2); \
+ } \
+ } \
+ else if (dy != 0) \
+ { \
+ int wx = (int)((RLSW.lineWidth - 1.0f)*abs(dy)/sqrtf(dx*dx + dy*dy)); \
+ wx >>= 1; \
+ for (int i = 1; i <= wx; i++) \
+ { \
+ tv1 = *v1, tv2 = *v2; \
+ tv1.screen[0] -= i; \
+ tv2.screen[0] -= i; \
+ RASTER_FUNC(&tv1, &tv2); \
+ tv1 = *v1, tv2 = *v2; \
+ tv1.screen[0] += i; \
+ tv2.screen[0] += i; \
+ RASTER_FUNC(&tv1, &tv2); \
+ } \
+ } \
+}
+
+DEFINE_LINE_RASTER(sw_line_raster, 0, 0)
+DEFINE_LINE_RASTER(sw_line_raster_DEPTH, 1, 0)
+DEFINE_LINE_RASTER(sw_line_raster_BLEND, 0, 1)
+DEFINE_LINE_RASTER(sw_line_raster_DEPTH_BLEND, 1, 1)
+
+DEFINE_LINE_THICK_RASTER(sw_line_thick_raster, sw_line_raster)
+DEFINE_LINE_THICK_RASTER(sw_line_thick_raster_DEPTH, sw_line_raster_DEPTH)
+DEFINE_LINE_THICK_RASTER(sw_line_thick_raster_BLEND, sw_line_raster_BLEND)
+DEFINE_LINE_THICK_RASTER(sw_line_thick_raster_DEPTH_BLEND, sw_line_raster_DEPTH_BLEND)
+
+static inline void sw_line_render(sw_vertex_t *vertices)
+{
+ if (!sw_line_clip_and_project(&vertices[0], &vertices[1])) return;
+
+ if (RLSW.lineWidth >= 2.0f)
+ {
+ if (SW_STATE_CHECK(SW_STATE_DEPTH_TEST | SW_STATE_BLEND)) sw_line_thick_raster_DEPTH_BLEND(&vertices[0], &vertices[1]);
+ else if (SW_STATE_CHECK(SW_STATE_BLEND)) sw_line_thick_raster_BLEND(&vertices[0], &vertices[1]);
+ else if (SW_STATE_CHECK(SW_STATE_DEPTH_TEST)) sw_line_thick_raster_DEPTH(&vertices[0], &vertices[1]);
+ else sw_line_thick_raster(&vertices[0], &vertices[1]);
+ }
+ else
+ {
+ if (SW_STATE_CHECK(SW_STATE_DEPTH_TEST | SW_STATE_BLEND)) sw_line_raster_DEPTH_BLEND(&vertices[0], &vertices[1]);
+ else if (SW_STATE_CHECK(SW_STATE_BLEND)) sw_line_raster_BLEND(&vertices[0], &vertices[1]);
+ else if (SW_STATE_CHECK(SW_STATE_DEPTH_TEST)) sw_line_raster_DEPTH(&vertices[0], &vertices[1]);
+ else sw_line_raster(&vertices[0], &vertices[1]);
+ }
+}
+
+// Point rendering logic
+
+static inline bool sw_point_clip_and_project(sw_vertex_t *v)
+{
+ if (v->homogeneous[3] != 1.0f)
+ {
+ for (int_fast8_t i = 0; i < 3; i++)
+ {
+ if ((v->homogeneous[i] < -v->homogeneous[3]) || (v->homogeneous[i] > v->homogeneous[3])) return false;
+ }
+
+ v->homogeneous[3] = 1.0f/v->homogeneous[3];
+ v->homogeneous[0] *= v->homogeneous[3];
+ v->homogeneous[1] *= v->homogeneous[3];
+ v->homogeneous[2] *= v->homogeneous[3];
+ }
+
+ sw_project_ndc_to_screen(v->screen, v->homogeneous);
+
+ const int *min = NULL, *max = NULL;
+
+ if (RLSW.stateFlags & SW_STATE_SCISSOR_TEST)
+ {
+ min = RLSW.scMin;
+ max = RLSW.scMax;
+ }
+ else
+ {
+ min = RLSW.vpMin;
+ max = RLSW.vpMax;
+ }
+
+ bool insideX = (v->screen[0] - RLSW.pointRadius < max[0]) && (v->screen[0] + RLSW.pointRadius > min[0]);
+ bool insideY = (v->screen[1] - RLSW.pointRadius < max[1]) && (v->screen[1] + RLSW.pointRadius > min[1]);
+
+ return (insideX && insideY);
+}
+
+#define DEFINE_POINT_RASTER(FUNC_NAME, ENABLE_DEPTH_TEST, ENABLE_COLOR_BLEND, CHECK_BOUNDS) \
+static inline void FUNC_NAME(int x, int y, float z, const float color[4]) \
+{ \
+ if (CHECK_BOUNDS == 1) \
+ { \
+ if (x < RLSW.vpMin[0] || x >= RLSW.vpMax[0]) return; \
+ if (y < RLSW.vpMin[1] || y >= RLSW.vpMax[1]) return; \
+ } \
+ else if (CHECK_BOUNDS == SW_SCISSOR_TEST) \
+ { \
+ if (x < RLSW.scMin[0] || x >= RLSW.scMax[0]) return; \
+ if (y < RLSW.scMin[1] || y >= RLSW.scMax[1]) return; \
+ } \
+ \
+ int offset = y*RLSW.framebuffer.width + x; \
+ \
+ void *dptr = sw_framebuffer_get_depth_addr(RLSW.framebuffer.depth, offset); \
+ \
+ if (ENABLE_DEPTH_TEST) \
+ { \
+ float depth = sw_framebuffer_read_depth(dptr); \
+ if (z > depth) return; \
+ } \
+ \
+ sw_framebuffer_write_depth(dptr, z); \
+ \
+ void *cptr = sw_framebuffer_get_color_addr(RLSW.framebuffer.color, offset); \
+ \
+ if (ENABLE_COLOR_BLEND) \
+ { \
+ float dstColor[4]; \
+ sw_framebuffer_read_color(dstColor, cptr); \
+ \
+ sw_blend_colors(dstColor, color); \
+ sw_framebuffer_write_color(cptr, dstColor); \
+ } \
+ else sw_framebuffer_write_color(cptr, color); \
+}
+
+#define DEFINE_POINT_THICK_RASTER(FUNC_NAME, RASTER_FUNC) \
+static inline void FUNC_NAME(sw_vertex_t *v) \
+{ \
+ int cx = v->screen[0]; \
+ int cy = v->screen[1]; \
+ float cz = v->homogeneous[2]; \
+ int radius = RLSW.pointRadius; \
+ const float *color = v->color; \
+ \
+ int x = 0; \
+ int y = radius; \
+ int d = 3 - 2*radius; \
+ \
+ while (x <= y) \
+ { \
+ for (int i = -x; i <= x; i++) \
+ { \
+ RASTER_FUNC(cx + i, cy + y, cz, color); \
+ RASTER_FUNC(cx + i, cy - y, cz, color); \
+ } \
+ for (int i = -y; i <= y; i++) \
+ { \
+ RASTER_FUNC(cx + i, cy + x, cz, color); \
+ RASTER_FUNC(cx + i, cy - x, cz, color); \
+ } \
+ if (d > 0) \
+ { \
+ y--; \
+ d = d + 4*(x - y) + 10; \
+ } \
+ else d = d + 4*x + 6; \
+ x++; \
+ } \
+}
+
+DEFINE_POINT_RASTER(sw_point_raster, 0, 0, 0)
+DEFINE_POINT_RASTER(sw_point_raster_DEPTH, 1, 0, 0)
+DEFINE_POINT_RASTER(sw_point_raster_BLEND, 0, 1, 0)
+DEFINE_POINT_RASTER(sw_point_raster_DEPTH_BLEND, 1, 1, 0)
+
+DEFINE_POINT_RASTER(sw_point_raster_CHECK, 0, 0, 1)
+DEFINE_POINT_RASTER(sw_point_raster_DEPTH_CHECK, 1, 0, 1)
+DEFINE_POINT_RASTER(sw_point_raster_BLEND_CHECK, 0, 1, 1)
+DEFINE_POINT_RASTER(sw_point_raster_DEPTH_BLEND_CHECK, 1, 1, 1)
+
+DEFINE_POINT_RASTER(sw_point_raster_CHECK_SCISSOR, 0, 0, SW_SCISSOR_TEST)
+DEFINE_POINT_RASTER(sw_point_raster_DEPTH_CHECK_SCISSOR, 1, 0, SW_SCISSOR_TEST)
+DEFINE_POINT_RASTER(sw_point_raster_BLEND_CHECK_SCISSOR, 0, 1, SW_SCISSOR_TEST)
+DEFINE_POINT_RASTER(sw_point_raster_DEPTH_BLEND_CHECK_SCISSOR, 1, 1, SW_SCISSOR_TEST)
+
+DEFINE_POINT_THICK_RASTER(sw_point_thick_raster, sw_point_raster_CHECK)
+DEFINE_POINT_THICK_RASTER(sw_point_thick_raster_DEPTH, sw_point_raster_DEPTH_CHECK)
+DEFINE_POINT_THICK_RASTER(sw_point_thick_raster_BLEND, sw_point_raster_BLEND_CHECK)
+DEFINE_POINT_THICK_RASTER(sw_point_thick_raster_DEPTH_BLEND, sw_point_raster_DEPTH_BLEND_CHECK)
+
+DEFINE_POINT_THICK_RASTER(sw_point_thick_raster_SCISSOR, sw_point_raster_CHECK_SCISSOR)
+DEFINE_POINT_THICK_RASTER(sw_point_thick_raster_DEPTH_SCISSOR, sw_point_raster_DEPTH_CHECK_SCISSOR)
+DEFINE_POINT_THICK_RASTER(sw_point_thick_raster_BLEND_SCISSOR, sw_point_raster_BLEND_CHECK_SCISSOR)
+DEFINE_POINT_THICK_RASTER(sw_point_thick_raster_DEPTH_BLEND_SCISSOR, sw_point_raster_DEPTH_BLEND_CHECK_SCISSOR)
+
+static inline void sw_point_render(sw_vertex_t *v)
+{
+ if (!sw_point_clip_and_project(v)) return;
+
+ if (RLSW.pointRadius >= 1.0f)
+ {
+ if (SW_STATE_CHECK(SW_STATE_SCISSOR_TEST))
+ {
+ if (SW_STATE_CHECK(SW_STATE_DEPTH_TEST | SW_STATE_BLEND)) sw_point_thick_raster_DEPTH_BLEND_SCISSOR(v);
+ else if (SW_STATE_CHECK(SW_STATE_BLEND)) sw_point_thick_raster_BLEND_SCISSOR(v);
+ else if (SW_STATE_CHECK(SW_STATE_DEPTH_TEST)) sw_point_thick_raster_DEPTH_SCISSOR(v);
+ else sw_point_thick_raster_SCISSOR(v);
+ }
+ else
+ {
+ if (SW_STATE_CHECK(SW_STATE_DEPTH_TEST | SW_STATE_BLEND)) sw_point_thick_raster_DEPTH_BLEND(v);
+ else if (SW_STATE_CHECK(SW_STATE_BLEND)) sw_point_thick_raster_BLEND(v);
+ else if (SW_STATE_CHECK(SW_STATE_DEPTH_TEST)) sw_point_thick_raster_DEPTH(v);
+ else sw_point_thick_raster(v);
+ }
+ }
+ else
+ {
+ if (SW_STATE_CHECK(SW_STATE_DEPTH_TEST | SW_STATE_BLEND)) sw_point_raster_DEPTH_BLEND(v->screen[0], v->screen[1], v->homogeneous[2], v->color);
+ else if (SW_STATE_CHECK(SW_STATE_BLEND)) sw_point_raster_BLEND(v->screen[0], v->screen[1], v->homogeneous[2], v->color);
+ else if (SW_STATE_CHECK(SW_STATE_DEPTH_TEST)) sw_point_raster_DEPTH(v->screen[0], v->screen[1], v->homogeneous[2], v->color);
+ else sw_point_raster(v->screen[0], v->screen[1], v->homogeneous[2], v->color);
+ }
+}
+
+// Polygon modes mendering logic
+
+static inline void sw_poly_point_render(void)
+{
+ for (int i = 0; i < RLSW.vertexCounter; i++) sw_point_render(&RLSW.vertexBuffer[i]);
+}
+
+static inline void sw_poly_line_render(void)
+{
+ const sw_vertex_t *vertices = RLSW.vertexBuffer;
+ int cm1 = RLSW.vertexCounter - 1;
+
+ for (int i = 0; i < cm1; i++) sw_line_render((sw_vertex_t[2]){ vertices[i], vertices[i + 1] });
+
+ sw_line_render((sw_vertex_t[2]){ vertices[cm1], vertices[0] });
+}
+
+static inline void sw_poly_fill_render(void)
+{
+ switch (RLSW.drawMode)
+ {
+ case SW_POINTS: sw_point_render(&RLSW.vertexBuffer[0]); break;
+ case SW_LINES: sw_line_render(RLSW.vertexBuffer); break;
+ case SW_TRIANGLES: sw_triangle_render(); break;
+ case SW_QUADS: sw_quad_render(); break;
+ }
+}
+
+// Validity check helper functions
+
+static inline bool sw_is_texture_valid(uint32_t id)
+{
+ bool valid = true;
+
+ if (id == 0) valid = false;
+ else if (id >= SW_MAX_TEXTURES) valid = false;
+ else if (RLSW.loadedTextures[id].pixels.cptr == 0) valid = false;
+
+ return true;
+}
+
+static inline bool sw_is_texture_filter_valid(int filter)
+{
+ return (filter == SW_NEAREST || filter == SW_LINEAR);
+}
+
+static inline bool sw_is_texture_wrap_valid(int wrap)
+{
+ return (wrap == SW_REPEAT || wrap == SW_CLAMP);
+}
+
+static inline bool sw_is_draw_mode_valid(int mode)
+{
+ bool result = false;
+
+ switch (mode)
+ {
+ case SW_POINTS:
+ case SW_LINES:
+ case SW_TRIANGLES:
+ case SW_QUADS: result = true; break;
+ default: break;
+ }
+
+ return result;
+}
+
+static inline bool sw_is_poly_mode_valid(int mode)
+{
+ bool result = false;
+
+ switch (mode)
+ {
+ case SW_POINT:
+ case SW_LINE:
+ case SW_FILL: result = true; break;
+ default: break;
+ }
+
+ return result;
+}
+
+static inline bool sw_is_face_valid(int face)
+{
+ return (face == SW_FRONT || face == SW_BACK);
+}
+
+static inline bool sw_is_blend_src_factor_valid(int blend)
+{
+ bool result = false;
+
+ switch (blend)
+ {
+ case SW_ZERO:
+ case SW_ONE:
+ case SW_SRC_COLOR:
+ case SW_ONE_MINUS_SRC_COLOR:
+ case SW_SRC_ALPHA:
+ case SW_ONE_MINUS_SRC_ALPHA:
+ case SW_DST_ALPHA:
+ case SW_ONE_MINUS_DST_ALPHA:
+ case SW_DST_COLOR:
+ case SW_ONE_MINUS_DST_COLOR:
+ case SW_SRC_ALPHA_SATURATE: result = true; break;
+ default: break;
+ }
+
+ return result;
+}
+
+static inline bool sw_is_blend_dst_factor_valid(int blend)
+{
+ bool result = false;
+
+ switch (blend)
+ {
+ case SW_ZERO:
+ case SW_ONE:
+ case SW_SRC_COLOR:
+ case SW_ONE_MINUS_SRC_COLOR:
+ case SW_SRC_ALPHA:
+ case SW_ONE_MINUS_SRC_ALPHA:
+ case SW_DST_ALPHA:
+ case SW_ONE_MINUS_DST_ALPHA:
+ case SW_DST_COLOR:
+ case SW_ONE_MINUS_DST_COLOR: result = true; break;
+ default: break;
+ }
+
+ return result;
+}
+
+//----------------------------------------------------------------------------------
+// Module Functions Definition
+//----------------------------------------------------------------------------------
+bool swInit(int w, int h)
+{
+ if (!sw_framebuffer_load(w, h)) { swClose(); return false; }
+
+ swViewport(0, 0, w, h);
+ swScissor(0, 0, w, h);
+
+ RLSW.loadedTextures = SW_MALLOC(SW_MAX_TEXTURES*sizeof(sw_texture_t));
+ if (RLSW.loadedTextures == NULL) { swClose(); return false; }
+
+ RLSW.freeTextureIds = SW_MALLOC(SW_MAX_TEXTURES*sizeof(uint32_t));
+ if (RLSW.loadedTextures == NULL) { swClose(); return false; }
+
+ RLSW.clearColor[0] = 0.0f;
+ RLSW.clearColor[1] = 0.0f;
+ RLSW.clearColor[2] = 0.0f;
+ RLSW.clearColor[3] = 1.0f;
+ RLSW.clearDepth = 1.0f;
+
+ RLSW.currentMatrixMode = SW_MODELVIEW;
+ RLSW.currentMatrix = &RLSW.stackModelview[0];
+
+ sw_matrix_id(RLSW.stackProjection[0]);
+ sw_matrix_id(RLSW.stackModelview[0]);
+ sw_matrix_id(RLSW.stackTexture[0]);
+ sw_matrix_id(RLSW.matMVP);
+
+ RLSW.stackProjectionCounter = 1;
+ RLSW.stackModelviewCounter = 1;
+ RLSW.stackTextureCounter = 1;
+ RLSW.isDirtyMVP = false;
+
+ RLSW.current.texcoord[0] = 0.0f;
+ RLSW.current.texcoord[1] = 0.0f;
+
+ RLSW.current.color[0] = 1.0f;
+ RLSW.current.color[1] = 1.0f;
+ RLSW.current.color[2] = 1.0f;
+ RLSW.current.color[3] = 1.0f;
+
+ RLSW.srcFactor = SW_SRC_ALPHA;
+ RLSW.dstFactor = SW_ONE_MINUS_SRC_ALPHA;
+
+ RLSW.srcFactorFunc = sw_factor_src_alpha;
+ RLSW.dstFactorFunc = sw_factor_one_minus_src_alpha;
+
+ RLSW.polyMode = SW_FILL;
+ RLSW.cullFace = SW_BACK;
+
+ static const float defTex[3*2*2] = {
+ 1.0f, 1.0f, 1.0f,
+ 1.0f, 1.0f, 1.0f,
+ 1.0f, 1.0f, 1.0f,
+ 1.0f, 1.0f, 1.0f,
+ };
+
+ RLSW.loadedTextures[0].pixels.cptr = defTex;
+ RLSW.loadedTextures[0].width = 2;
+ RLSW.loadedTextures[0].height = 2;
+ RLSW.loadedTextures[0].wMinus1 = 1;
+ RLSW.loadedTextures[0].hMinus1 = 1;
+ RLSW.loadedTextures[0].format = SW_PIXELFORMAT_UNCOMPRESSED_R32G32B32;
+ RLSW.loadedTextures[0].minFilter = SW_NEAREST;
+ RLSW.loadedTextures[0].magFilter = SW_NEAREST;
+ RLSW.loadedTextures[0].sWrap = SW_REPEAT;
+ RLSW.loadedTextures[0].tWrap = SW_REPEAT;
+ RLSW.loadedTextures[0].tx = 0.5f;
+ RLSW.loadedTextures[0].ty = 0.5f;
+ RLSW.loadedTextures[0].copy = false;
+
+ RLSW.loadedTextureCount = 1;
+
+ return true;
+}
+
+void swClose(void)
+{
+ for (int i = 1; i < RLSW.loadedTextureCount; i++)
+ {
+ sw_texture_t *texture = &RLSW.loadedTextures[i];
+ if (sw_is_texture_valid(i) && texture->copy) SW_FREE(texture->pixels.ptr);
+ }
+
+ SW_FREE(RLSW.framebuffer.color);
+ SW_FREE(RLSW.framebuffer.depth);
+ SW_FREE(RLSW.loadedTextures);
+ SW_FREE(RLSW.freeTextureIds);
+
+ RLSW = (sw_context_t) { 0 };
+}
+
+bool swResizeFramebuffer(int w, int h)
+{
+ return sw_framebuffer_resize(w, h);
+}
+
+void swCopyFramebuffer(int x, int y, int w, int h, SWformat format, SWtype type, void *pixels)
+{
+ sw_pixelformat_t pFormat = sw_get_pixel_format(format, type);
+
+ if (w <= 0)
+ {
+ RLSW.errCode = SW_INVALID_VALUE;
+ return;
+ }
+
+ if (h <= 0)
+ {
+ RLSW.errCode = SW_INVALID_VALUE;
+ return;
+ }
+
+ if (w > RLSW.framebuffer.width) w = RLSW.framebuffer.width;
+ if (h > RLSW.framebuffer.height) h = RLSW.framebuffer.height;
+
+ x = sw_clampi(x, 0, w);
+ y = sw_clampi(y, 0, h);
+
+ switch (pFormat)
+ {
+ case SW_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: sw_framebuffer_copy_to_GRAYALPHA(x, y, w, h, pixels); break;
+ case SW_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA: sw_framebuffer_copy_to_GRAYALPHA(x, y, w, h, pixels); break;
+ case SW_PIXELFORMAT_UNCOMPRESSED_R5G6B5: sw_framebuffer_copy_to_R5G6B5(x, y, w, h, pixels); break;
+ case SW_PIXELFORMAT_UNCOMPRESSED_R8G8B8: sw_framebuffer_copy_to_R8G8B8(x, y, w, h, pixels); break;
+ case SW_PIXELFORMAT_UNCOMPRESSED_R5G5B5A1: sw_framebuffer_copy_to_R5G5B5A1(x, y, w, h, pixels); break;
+ case SW_PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: sw_framebuffer_copy_to_R4G4B4A4(x, y, w, h, pixels); break;
+ case SW_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: sw_framebuffer_copy_to_R8G8B8A8(x, y, w, h, pixels); break;
+ case SW_PIXELFORMAT_UNCOMPRESSED_R32: sw_framebuffer_copy_to_R32(x, y, w, h, pixels); break;
+ case SW_PIXELFORMAT_UNCOMPRESSED_R32G32B32: sw_framebuffer_copy_to_R32G32B32(x, y, w, h, pixels); break;
+ case SW_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: sw_framebuffer_copy_to_R32G32B32A32(x, y, w, h, pixels); break;
+ case SW_PIXELFORMAT_UNCOMPRESSED_R16: sw_framebuffer_copy_to_R16(x, y, w, h, pixels); break;
+ case SW_PIXELFORMAT_UNCOMPRESSED_R16G16B16: sw_framebuffer_copy_to_R16G16B16(x, y, w, h, pixels); break;
+ case SW_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: sw_framebuffer_copy_to_R16G16B16A16(x, y, w, h, pixels); break;
+ default: RLSW.errCode = SW_INVALID_ENUM; break;
+ }
+}
+
+void swBlitFramebuffer(int xDst, int yDst, int wDst, int hDst, int xSrc, int ySrc, int wSrc, int hSrc, SWformat format, SWtype type, void *pixels)
+{
+ sw_pixelformat_t pFormat = sw_get_pixel_format(format, type);
+
+ if (wSrc <= 0)
+ {
+ RLSW.errCode = SW_INVALID_VALUE;
+ return;
+ }
+
+ if (hSrc <= 0)
+ {
+ RLSW.errCode = SW_INVALID_VALUE;
+ return;
+ }
+
+ if (wSrc > RLSW.framebuffer.width) wSrc = RLSW.framebuffer.width;
+ if (hSrc > RLSW.framebuffer.height) hSrc = RLSW.framebuffer.height;
+
+ xSrc = sw_clampi(xSrc, 0, wSrc);
+ ySrc = sw_clampi(ySrc, 0, hSrc);
+
+ switch (pFormat)
+ {
+ case SW_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: sw_framebuffer_blit_to_GRAYALPHA(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, pixels); break;
+ case SW_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA: sw_framebuffer_blit_to_GRAYALPHA(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, pixels); break;
+ case SW_PIXELFORMAT_UNCOMPRESSED_R5G6B5: sw_framebuffer_blit_to_R5G6B5(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, pixels); break;
+ case SW_PIXELFORMAT_UNCOMPRESSED_R8G8B8: sw_framebuffer_blit_to_R8G8B8(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, pixels); break;
+ case SW_PIXELFORMAT_UNCOMPRESSED_R5G5B5A1: sw_framebuffer_blit_to_R5G5B5A1(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, pixels); break;
+ case SW_PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: sw_framebuffer_blit_to_R4G4B4A4(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, pixels); break;
+ case SW_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: sw_framebuffer_blit_to_R8G8B8A8(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, pixels); break;
+ case SW_PIXELFORMAT_UNCOMPRESSED_R32: sw_framebuffer_blit_to_R32(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, pixels); break;
+ case SW_PIXELFORMAT_UNCOMPRESSED_R32G32B32: sw_framebuffer_blit_to_R32G32B32(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, pixels); break;
+ case SW_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: sw_framebuffer_blit_to_R32G32B32A32(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, pixels); break;
+ case SW_PIXELFORMAT_UNCOMPRESSED_R16: sw_framebuffer_blit_to_R16(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, pixels); break;
+ case SW_PIXELFORMAT_UNCOMPRESSED_R16G16B16: sw_framebuffer_blit_to_R16G16B16(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, pixels); break;
+ case SW_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: sw_framebuffer_blit_to_R16G16B16A16(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, pixels); break;
+ default: RLSW.errCode = SW_INVALID_ENUM; break;
+ }
+}
+
+void *swGetColorBuffer(int *w, int *h)
+{
+ if (w) *w = RLSW.framebuffer.width;
+ if (h) *h = RLSW.framebuffer.height;
+
+ return RLSW.framebuffer.color;
+}
+
+void swEnable(SWstate state)
+{
+ switch (state)
+ {
+ case SW_SCISSOR_TEST: RLSW.stateFlags |= SW_STATE_SCISSOR_TEST; break;
+ case SW_TEXTURE_2D: RLSW.stateFlags |= SW_STATE_TEXTURE_2D; break;
+ case SW_DEPTH_TEST: RLSW.stateFlags |= SW_STATE_DEPTH_TEST; break;
+ case SW_CULL_FACE: RLSW.stateFlags |= SW_STATE_CULL_FACE; break;
+ case SW_BLEND: RLSW.stateFlags |= SW_STATE_BLEND; break;
+ default: RLSW.errCode = SW_INVALID_ENUM; break;
+ }
+}
+
+void swDisable(SWstate state)
+{
+ switch (state)
+ {
+ case SW_SCISSOR_TEST: RLSW.stateFlags &= ~SW_STATE_SCISSOR_TEST; break;
+ case SW_TEXTURE_2D: RLSW.stateFlags &= ~SW_STATE_TEXTURE_2D; break;
+ case SW_DEPTH_TEST: RLSW.stateFlags &= ~SW_STATE_DEPTH_TEST; break;
+ case SW_CULL_FACE: RLSW.stateFlags &= ~SW_STATE_CULL_FACE; break;
+ case SW_BLEND: RLSW.stateFlags &= ~SW_STATE_BLEND; break;
+ default: RLSW.errCode = SW_INVALID_ENUM; break;
+ }
+}
+
+void swGetIntegerv(SWget name, int *v)
+{
+ switch (name)
+ {
+ case SW_MODELVIEW_STACK_DEPTH: *v = SW_MODELVIEW_STACK_DEPTH; break;
+ case SW_PROJECTION_STACK_DEPTH: *v = SW_PROJECTION_STACK_DEPTH; break;
+ case SW_TEXTURE_STACK_DEPTH: *v = SW_TEXTURE_STACK_DEPTH; break;
+ default: RLSW.errCode = SW_INVALID_ENUM; break;
+ }
+}
+
+void swGetFloatv(SWget name, float *v)
+{
+ switch (name)
+ {
+ case SW_COLOR_CLEAR_VALUE:
+ {
+ v[0] = RLSW.clearColor[0];
+ v[1] = RLSW.clearColor[1];
+ v[2] = RLSW.clearColor[2];
+ v[3] = RLSW.clearColor[3];
+ } break;
+ case SW_CURRENT_COLOR:
+ {
+ v[0] = RLSW.vertexBuffer[RLSW.vertexCounter - 1].color[0];
+ v[1] = RLSW.vertexBuffer[RLSW.vertexCounter - 1].color[1];
+ v[2] = RLSW.vertexBuffer[RLSW.vertexCounter - 1].color[2];
+ v[3] = RLSW.vertexBuffer[RLSW.vertexCounter - 1].color[3];
+ } break;
+ case SW_CURRENT_TEXTURE_COORDS:
+ {
+ v[0] = RLSW.vertexBuffer[RLSW.vertexCounter - 1].texcoord[0];
+ v[1] = RLSW.vertexBuffer[RLSW.vertexCounter - 1].texcoord[1];
+ } break;
+ case SW_POINT_SIZE:
+ {
+ v[0] = 2.0f*RLSW.pointRadius;
+ } break;
+ case SW_LINE_WIDTH:
+ {
+ v[0] = RLSW.lineWidth;
+ } break;
+ case SW_MODELVIEW_MATRIX:
+ {
+ for (int i = 0; i < 16; i++) v[i] = RLSW.stackModelview[RLSW.stackModelviewCounter - 1][i];
+
+ } break;
+ case SW_PROJECTION_MATRIX:
+ {
+ for (int i = 0; i < 16; i++) v[i] = RLSW.stackProjection[RLSW.stackProjectionCounter - 1][i];
+
+ } break;
+ case SW_TEXTURE_MATRIX:
+ {
+ for (int i = 0; i < 16; i++) v[i] = RLSW.stackTexture[RLSW.stackTextureCounter - 1][i];
+
+ } break;
+ default: RLSW.errCode = SW_INVALID_ENUM; break;
+ }
+}
+
+const char *swGetString(SWget name)
+{
+ const char *result = NULL;
+
+ switch (name)
+ {
+ case SW_VENDOR: result = "RLSW Header"; break;
+ case SW_RENDERER: result = "RLSW Software Renderer"; break;
+ case SW_VERSION: result = "RLSW 1.0"; break;
+ case SW_EXTENSIONS: result = "None"; break;
+ default: RLSW.errCode = SW_INVALID_ENUM; break;
+ }
+
+ return result;
+}
+
+SWerrcode swGetError(void)
+{
+ SWerrcode ret = RLSW.errCode;
+ RLSW.errCode = SW_NO_ERROR;
+ return ret;
+}
+
+void swViewport(int x, int y, int width, int height)
+{
+ if ((width < 0) || (height < 0))
+ {
+ RLSW.errCode = SW_INVALID_VALUE;
+ return;
+ }
+
+ RLSW.vpSize[0] = width;
+ RLSW.vpSize[1] = height;
+
+ RLSW.vpHalfSize[0] = (int)(width/2.0f + 0.5f);
+ RLSW.vpHalfSize[1] = (int)(height/2.0f + 0.5f);
+
+ RLSW.vpCenter[0] = x + RLSW.vpHalfSize[0];
+ RLSW.vpCenter[1] = y + RLSW.vpHalfSize[1];
+
+ RLSW.vpMin[0] = sw_clampi(x, 0, RLSW.framebuffer.width - 1);
+ RLSW.vpMin[1] = sw_clampi(y, 0, RLSW.framebuffer.height - 1);
+ RLSW.vpMax[0] = sw_clampi(x + width, 0, RLSW.framebuffer.width - 1);
+ RLSW.vpMax[1] = sw_clampi(y + height, 0, RLSW.framebuffer.height - 1);
+}
+
+void swScissor(int x, int y, int width, int height)
+{
+ if ((width < 0) || (height < 0))
+ {
+ RLSW.errCode = SW_INVALID_VALUE;
+ return;
+ }
+
+ RLSW.scMin[0] = sw_clampi(x, 0, RLSW.framebuffer.width - 1);
+ RLSW.scMin[1] = sw_clampi(y, 0, RLSW.framebuffer.height - 1);
+ RLSW.scMax[0] = sw_clampi(x + width, 0, RLSW.framebuffer.width - 1);
+ RLSW.scMax[1] = sw_clampi(y + height, 0, RLSW.framebuffer.height - 1);
+
+ 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]);
+}
+
+void swClearColor(float r, float g, float b, float a)
+{
+ RLSW.clearColor[0] = r;
+ RLSW.clearColor[1] = g;
+ RLSW.clearColor[2] = b;
+ RLSW.clearColor[3] = a;
+}
+
+void swClear(uint32_t bitmask)
+{
+ int size = RLSW.framebuffer.width*RLSW.framebuffer.height;
+
+ if ((bitmask & (SW_COLOR_BUFFER_BIT | SW_DEPTH_BUFFER_BIT)) == (SW_COLOR_BUFFER_BIT | SW_DEPTH_BUFFER_BIT))
+ {
+ sw_framebuffer_fill(RLSW.framebuffer.color, RLSW.framebuffer.depth,size, RLSW.clearColor, RLSW.clearDepth);
+ }
+ else if (bitmask & (SW_COLOR_BUFFER_BIT))
+ {
+ sw_framebuffer_fill_color(RLSW.framebuffer.color, size, RLSW.clearColor);
+ }
+ else if (bitmask & SW_DEPTH_BUFFER_BIT)
+ {
+ sw_framebuffer_fill_depth(RLSW.framebuffer.depth, size, RLSW.clearDepth);
+ }
+}
+
+void swBlendFunc(SWfactor sfactor, SWfactor dfactor)
+{
+ if (!sw_is_blend_src_factor_valid(sfactor) ||
+ !sw_is_blend_dst_factor_valid(dfactor))
+ {
+ RLSW.errCode = SW_INVALID_ENUM;
+ return;
+ }
+
+ RLSW.srcFactor = sfactor;
+ RLSW.dstFactor = dfactor;
+
+ switch (sfactor)
+ {
+ case SW_ZERO: RLSW.srcFactorFunc = sw_factor_zero; break;
+ case SW_ONE: RLSW.srcFactorFunc = sw_factor_one; break;
+ case SW_SRC_COLOR: RLSW.srcFactorFunc = sw_factor_src_color; break;
+ case SW_ONE_MINUS_SRC_COLOR: RLSW.srcFactorFunc = sw_factor_one_minus_src_color; break;
+ case SW_SRC_ALPHA: RLSW.srcFactorFunc = sw_factor_src_alpha; break;
+ case SW_ONE_MINUS_SRC_ALPHA: RLSW.srcFactorFunc = sw_factor_one_minus_src_alpha; break;
+ case SW_DST_ALPHA: RLSW.srcFactorFunc = sw_factor_dst_alpha; break;
+ case SW_ONE_MINUS_DST_ALPHA: RLSW.srcFactorFunc = sw_factor_one_minus_dst_alpha; break;
+ case SW_DST_COLOR: RLSW.srcFactorFunc = sw_factor_dst_color; break;
+ case SW_ONE_MINUS_DST_COLOR: RLSW.srcFactorFunc = sw_factor_one_minus_dst_color; break;
+ case SW_SRC_ALPHA_SATURATE: RLSW.srcFactorFunc = sw_factor_src_alpha_saturate; break;
+ default: break;
+ }
+
+ switch (dfactor)
+ {
+ case SW_ZERO: RLSW.dstFactorFunc = sw_factor_zero; break;
+ case SW_ONE: RLSW.dstFactorFunc = sw_factor_one; break;
+ case SW_SRC_COLOR: RLSW.dstFactorFunc = sw_factor_src_color; break;
+ case SW_ONE_MINUS_SRC_COLOR: RLSW.dstFactorFunc = sw_factor_one_minus_src_color; break;
+ case SW_SRC_ALPHA: RLSW.dstFactorFunc = sw_factor_src_alpha; break;
+ case SW_ONE_MINUS_SRC_ALPHA: RLSW.dstFactorFunc = sw_factor_one_minus_src_alpha; break;
+ case SW_DST_ALPHA: RLSW.dstFactorFunc = sw_factor_dst_alpha; break;
+ case SW_ONE_MINUS_DST_ALPHA: RLSW.dstFactorFunc = sw_factor_one_minus_dst_alpha; break;
+ case SW_DST_COLOR: RLSW.dstFactorFunc = sw_factor_dst_color; break;
+ case SW_ONE_MINUS_DST_COLOR: RLSW.dstFactorFunc = sw_factor_one_minus_dst_color; break;
+ case SW_SRC_ALPHA_SATURATE: break;
+ default: break;
+ }
+}
+
+void swPolygonMode(SWpoly mode)
+{
+ if (!sw_is_poly_mode_valid(mode))
+ {
+ RLSW.errCode = SW_INVALID_ENUM;
+ return;
+ }
+
+ RLSW.polyMode = mode;
+}
+
+void swCullFace(SWface face)
+{
+ if (!sw_is_face_valid(face))
+ {
+ RLSW.errCode = SW_INVALID_ENUM;
+ return;
+ }
+
+ RLSW.cullFace = face;
+}
+
+void swPointSize(float size)
+{
+ RLSW.pointRadius = floorf(size*0.5f);
+}
+
+void swLineWidth(float width)
+{
+ RLSW.lineWidth = roundf(width);
+}
+
+void swMatrixMode(SWmatrix mode)
+{
+ switch (mode)
+ {
+ case SW_PROJECTION: RLSW.currentMatrix = &RLSW.stackProjection[RLSW.stackProjectionCounter - 1]; break;
+ case SW_MODELVIEW: RLSW.currentMatrix = &RLSW.stackModelview[RLSW.stackModelviewCounter - 1]; break;
+ case SW_TEXTURE: RLSW.currentMatrix = &RLSW.stackTexture[RLSW.stackTextureCounter - 1]; break;
+ default: RLSW.errCode = SW_INVALID_ENUM; return;
+ }
+
+ RLSW.currentMatrixMode = mode;
+}
+
+void swPushMatrix(void)
+{
+ switch (RLSW.currentMatrixMode)
+ {
+ case SW_PROJECTION:
+ {
+ if (RLSW.stackProjectionCounter >= SW_MAX_PROJECTION_STACK_SIZE)
+ {
+ RLSW.errCode = SW_STACK_OVERFLOW;
+ return;
+ }
+
+ int iOld = RLSW.stackProjectionCounter - 1;
+ int iNew = RLSW.stackProjectionCounter++;
+
+ for (int i = 0; i < 16; i++)
+ {
+ RLSW.stackProjection[iNew][i] = RLSW.stackProjection[iOld][i];
+ }
+
+ RLSW.currentMatrix = &RLSW.stackProjection[iNew];
+ } break;
+ case SW_MODELVIEW:
+ {
+ if (RLSW.stackModelviewCounter >= SW_MAX_MODELVIEW_STACK_SIZE)
+ {
+ RLSW.errCode = SW_STACK_OVERFLOW;
+ return;
+ }
+
+ int iOld = RLSW.stackModelviewCounter - 1;
+ int iNew = RLSW.stackModelviewCounter++;
+
+ for (int i = 0; i < 16; i++)
+ {
+ RLSW.stackModelview[iNew][i] = RLSW.stackModelview[iOld][i];
+ }
+
+ RLSW.currentMatrix = &RLSW.stackModelview[iNew];
+ } break;
+ case SW_TEXTURE:
+ {
+ if (RLSW.stackTextureCounter >= SW_MAX_TEXTURE_STACK_SIZE)
+ {
+ RLSW.errCode = SW_STACK_OVERFLOW;
+ return;
+ }
+
+ int iOld = RLSW.stackTextureCounter - 1;
+ int iNew = RLSW.stackTextureCounter++;
+
+ for (int i = 0; i < 16; i++)
+ {
+ RLSW.stackTexture[iNew][i] = RLSW.stackTexture[iOld][i];
+ }
+
+ RLSW.currentMatrix = &RLSW.stackTexture[iNew];
+ } break;
+ default: break;
+ }
+}
+
+void swPopMatrix(void)
+{
+ switch (RLSW.currentMatrixMode)
+ {
+ case SW_PROJECTION:
+ {
+ if (RLSW.stackProjectionCounter <= 0)
+ {
+ RLSW.errCode = SW_STACK_UNDERFLOW;
+ return;
+ }
+
+ RLSW.currentMatrix = &RLSW.stackProjection[--RLSW.stackProjectionCounter];
+ RLSW.isDirtyMVP = true; //< The MVP is considered to have been changed
+ } break;
+ case SW_MODELVIEW:
+ {
+ if (RLSW.stackModelviewCounter <= 0)
+ {
+ RLSW.errCode = SW_STACK_UNDERFLOW;
+ return;
+ }
+
+ RLSW.currentMatrix = &RLSW.stackModelview[--RLSW.stackModelviewCounter];
+ RLSW.isDirtyMVP = true; //< The MVP is considered to have been changed
+ } break;
+ case SW_TEXTURE:
+ {
+ if (RLSW.stackTextureCounter <= 0)
+ {
+ RLSW.errCode = SW_STACK_UNDERFLOW;
+ return;
+ }
+
+ RLSW.currentMatrix = &RLSW.stackTexture[--RLSW.stackTextureCounter];
+ } break;
+ default: break;
+ }
+}
+
+void swLoadIdentity(void)
+{
+ sw_matrix_id(*RLSW.currentMatrix);
+ if (RLSW.currentMatrixMode != SW_TEXTURE) RLSW.isDirtyMVP = true;
+}
+
+void swTranslatef(float x, float y, float z)
+{
+ sw_matrix_t mat;
+ sw_matrix_id(mat);
+
+ mat[12] = x;
+ mat[13] = y;
+ mat[14] = z;
+
+ sw_matrix_mul(*RLSW.currentMatrix, mat, *RLSW.currentMatrix);
+
+ if (RLSW.currentMatrixMode != SW_TEXTURE) RLSW.isDirtyMVP = true;
+}
+
+void swRotatef(float angle, float x, float y, float z)
+{
+ angle *= SW_DEG2RAD;
+
+ float lengthSq = x*x + y*y + z*z;
+
+ if (lengthSq != 1.0f && lengthSq != 0.0f)
+ {
+ float invLength = 1.0f/sqrtf(lengthSq);
+ x *= invLength;
+ y *= invLength;
+ z *= invLength;
+ }
+
+ float sinres = sinf(angle);
+ float cosres = cosf(angle);
+ float t = 1.0f - cosres;
+
+ sw_matrix_t mat;
+
+ mat[0] = x*x*t + cosres;
+ mat[1] = y*x*t + z*sinres;
+ mat[2] = z*x*t - y*sinres;
+ mat[3] = 0.0f;
+
+ mat[4] = x*y*t - z*sinres;
+ mat[5] = y*y*t + cosres;
+ mat[6] = z*y*t + x*sinres;
+ mat[7] = 0.0f;
+
+ mat[8] = x*z*t + y*sinres;
+ mat[9] = y*z*t - x*sinres;
+ mat[10] = z*z*t + cosres;
+ mat[11] = 0.0f;
+
+ mat[12] = 0.0f;
+ mat[13] = 0.0f;
+ mat[14] = 0.0f;
+ mat[15] = 1.0f;
+
+ sw_matrix_mul(*RLSW.currentMatrix, mat, *RLSW.currentMatrix);
+
+ if (RLSW.currentMatrixMode != SW_TEXTURE) RLSW.isDirtyMVP = true;
+}
+
+void swScalef(float x, float y, float z)
+{
+ sw_matrix_t mat;
+
+ mat[0] = x, mat[1] = 0, mat[2] = 0, mat[3] = 0;
+ mat[4] = 0, mat[5] = y, mat[6] = 0, mat[7] = 0;
+ mat[8] = 0, mat[9] = 0, mat[10] = z, mat[11] = 0;
+ mat[12] = 0, mat[13] = 0, mat[14] = 0, mat[15] = 1;
+
+ sw_matrix_mul(*RLSW.currentMatrix, mat, *RLSW.currentMatrix);
+
+ if (RLSW.currentMatrixMode != SW_TEXTURE) RLSW.isDirtyMVP = true;
+}
+
+void swMultMatrixf(const float *mat)
+{
+ sw_matrix_mul(*RLSW.currentMatrix, mat, *RLSW.currentMatrix);
+
+ if (RLSW.currentMatrixMode != SW_TEXTURE) RLSW.isDirtyMVP = true;
+}
+
+void swFrustum(double left, double right, double bottom, double top, double znear, double zfar)
+{
+ sw_matrix_t mat;
+
+ double rl = right - left;
+ double tb = top - bottom;
+ double fn = zfar - znear;
+
+ mat[0] = (float)(znear*2.0)/rl;
+ mat[1] = 0.0f;
+ mat[2] = 0.0f;
+ mat[3] = 0.0f;
+
+ mat[4] = 0.0f;
+ mat[5] = (float)(znear*2.0)/tb;
+ mat[6] = 0.0f;
+ mat[7] = 0.0f;
+
+ mat[8] = (float)(right + left)/rl;
+ mat[9] = (float)(top + bottom)/tb;
+ mat[10] = -(float)(zfar + znear)/fn;
+ mat[11] = -1.0f;
+
+ mat[12] = 0.0f;
+ mat[13] = 0.0f;
+ mat[14] = -(zfar*znear*2.0)/fn;
+ mat[15] = 0.0f;
+
+ sw_matrix_mul(*RLSW.currentMatrix, *RLSW.currentMatrix, mat);
+
+ if (RLSW.currentMatrixMode != SW_TEXTURE) RLSW.isDirtyMVP = true;
+}
+
+void swOrtho(double left, double right, double bottom, double top, double znear, double zfar)
+{
+ sw_matrix_t mat;
+
+ double rl = right - left;
+ double tb = top - bottom;
+ double fn = zfar - znear;
+
+ mat[0] = 2.0f/(float)rl;
+ mat[1] = 0.0f;
+ mat[2] = 0.0f;
+ mat[3] = 0.0f;
+
+ mat[4] = 0.0f;
+ mat[5] = 2.0f/(float)tb;
+ mat[6] = 0.0f;
+ mat[7] = 0.0f;
+
+ mat[8] = 0.0f;
+ mat[9] = 0.0f;
+ mat[10] = -2.0f/(float)fn;
+ mat[11] = 0.0f;
+
+ mat[12] = -(float)(left + right)/rl;
+ mat[13] = -(float)(top + bottom)/tb;
+ mat[14] = -(float)(zfar + znear)/fn;
+ mat[15] = 1.0f;
+
+ sw_matrix_mul(*RLSW.currentMatrix, *RLSW.currentMatrix, mat);
+
+ if (RLSW.currentMatrixMode != SW_TEXTURE) RLSW.isDirtyMVP = true;
+}
+
+void swBegin(SWdraw mode)
+{
+ // Check if the draw mode is valid
+ if (!sw_is_draw_mode_valid(mode))
+ {
+ RLSW.errCode = SW_INVALID_ENUM;
+ return;
+ }
+
+ // Recalculate the MVP if this is needed
+ if (RLSW.isDirtyMVP)
+ {
+ sw_matrix_mul_rst(RLSW.matMVP,
+ RLSW.stackModelview[RLSW.stackModelviewCounter - 1],
+ RLSW.stackProjection[RLSW.stackProjectionCounter - 1]);
+
+ RLSW.isDirtyMVP = false;
+ }
+
+ // Obtain the number of vertices needed for this primitive
+ switch (mode)
+ {
+ case SW_POINTS: RLSW.reqVertices = 1; break;
+ case SW_LINES: RLSW.reqVertices = 2; break;
+ case SW_TRIANGLES: RLSW.reqVertices = 3; break;
+ case SW_QUADS: RLSW.reqVertices = 4; break;
+ }
+
+ // Initialize required values
+ RLSW.vertexCounter = 0;
+ RLSW.drawMode = mode;
+}
+
+void swEnd(void)
+{
+ RLSW.drawMode = 0;
+}
+
+void swVertex2i(int x, int y)
+{
+ const float v[4] = { (float)x, (float)y, 0.0f, 1.0f };
+ swVertex4fv(v);
+}
+
+void swVertex2f(float x, float y)
+{
+ const float v[4] = { x, y, 0.0f, 1.0f };
+ swVertex4fv(v);
+}
+
+void swVertex2fv(const float *v)
+{
+ const float v4[4] = { v[0], v[1], 0.0f, 1.0f };
+ swVertex4fv(v4);
+}
+
+void swVertex3i(int x, int y, int z)
+{
+ const float v[4] = { (float)x, (float)y, (float)z, 1.0f };
+ swVertex4fv(v);
+}
+
+void swVertex3f(float x, float y, float z)
+{
+ const float v[4] = { x, y, z, 1.0f };
+ swVertex4fv(v);
+}
+
+void swVertex3fv(const float *v)
+{
+ const float v4[4] = { v[0], v[1], v[2], 1.0f };
+ swVertex4fv(v4);
+}
+
+void swVertex4i(int x, int y, int z, int w)
+{
+ const float v[4] = { (float)x, (float)y, (float)z, (float)w };
+ swVertex4fv(v);
+}
+
+void swVertex4f(float x, float y, float z, float w)
+{
+ const float v[4] = { x, y, z, w };
+ swVertex4fv(v);
+}
+
+void swVertex4fv(const float *v)
+{
+ // Copy the position in the current vertex
+ sw_vertex_t *vertex = &RLSW.vertexBuffer[RLSW.vertexCounter++];
+ for (int i = 0; i < 4; i++) vertex->position[i] = v[i];
+
+ // Copy additonal vertex data
+ for (int i = 0; i < 2; i++) vertex->texcoord[i] = RLSW.current.texcoord[i];
+ for (int i = 0; i < 4; i++) vertex->color[i] = RLSW.current.color[i];
+
+ // Calculation of homogeneous coordinates
+ const float *m = RLSW.matMVP;
+ vertex->homogeneous[0] = m[0]*v[0] + m[4]*v[1] + m[8]*v[2] + m[12]*v[3];
+ vertex->homogeneous[1] = m[1]*v[0] + m[5]*v[1] + m[9]*v[2] + m[13]*v[3];
+ vertex->homogeneous[2] = m[2]*v[0] + m[6]*v[1] + m[10]*v[2] + m[14]*v[3];
+ vertex->homogeneous[3] = m[3]*v[0] + m[7]*v[1] + m[11]*v[2] + m[15]*v[3];
+
+ // Immediate rendering of the primitive if the required number is reached
+ if (RLSW.vertexCounter == RLSW.reqVertices)
+ {
+ switch (RLSW.polyMode)
+ {
+ case SW_FILL: sw_poly_fill_render(); break;
+ case SW_LINE: sw_poly_line_render(); break;
+ case SW_POINT: sw_poly_point_render(); break;
+ default: break;
+ }
+
+ RLSW.vertexCounter = 0;
+ }
+}
+
+void swColor3ub(uint8_t r, uint8_t g, uint8_t b)
+{
+ float cv[4];
+ cv[0] = (float)r/255;
+ cv[1] = (float)g/255;
+ cv[2] = (float)b/255;
+ cv[3] = 1.0f;
+
+ swColor4fv(cv);
+}
+
+void swColor3ubv(const uint8_t *v)
+{
+ float cv[4];
+ cv[0] = (float)v[0]/255;
+ cv[1] = (float)v[1]/255;
+ cv[2] = (float)v[2]/255;
+ cv[3] = 1.0f;
+
+ swColor4fv(cv);
+}
+
+void swColor3f(float r, float g, float b)
+{
+ float cv[4];
+ cv[0] = r;
+ cv[1] = g;
+ cv[2] = b;
+ cv[3] = 1.0f;
+
+ swColor4fv(cv);
+}
+
+void swColor3fv(const float *v)
+{
+ float cv[4];
+ cv[0] = v[0];
+ cv[1] = v[1];
+ cv[2] = v[2];
+ cv[3] = 1.0f;
+
+ swColor4fv(cv);
+}
+
+void swColor4ub(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
+{
+ float cv[4];
+ cv[0] = (float)r/255;
+ cv[1] = (float)g/255;
+ cv[2] = (float)b/255;
+ cv[3] = (float)a/255;
+
+ swColor4fv(cv);
+}
+
+void swColor4ubv(const uint8_t *v)
+{
+ float cv[4];
+ cv[0] = (float)v[0]/255;
+ cv[1] = (float)v[1]/255;
+ cv[2] = (float)v[2]/255;
+ cv[3] = (float)v[3]/255;
+
+ swColor4fv(cv);
+}
+
+void swColor4f(float r, float g, float b, float a)
+{
+ float cv[4];
+ cv[0] = r;
+ cv[1] = g;
+ cv[2] = b;
+ cv[3] = a;
+
+ swColor4fv(cv);
+}
+
+void swColor4fv(const float *v)
+{
+ for (int i = 0; i < 4; i++) RLSW.current.color[i] = v[i];
+}
+
+void swTexCoord2f(float u, float v)
+{
+ const float *m = RLSW.stackTexture[RLSW.stackTextureCounter - 1];
+
+ RLSW.current.texcoord[0] = m[0]*u + m[4]*v + m[12];
+ RLSW.current.texcoord[1] = m[1]*u + m[5]*v + m[13];
+}
+
+void swTexCoord2fv(const float *v)
+{
+ const float *m = RLSW.stackTexture[RLSW.stackTextureCounter - 1];
+
+ RLSW.current.texcoord[0] = m[0]*v[0] + m[4]*v[1] + m[12];
+ RLSW.current.texcoord[1] = m[1]*v[0] + m[5]*v[1] + m[13];
+}
+
+void swBindArray(SWarray type, void *buffer)
+{
+ switch (type)
+ {
+ case SW_VERTEX_ARRAY: RLSW.array.positions = buffer; break;
+ case SW_TEXTURE_COORD_ARRAY: RLSW.array.texcoords = buffer; break;
+ case SW_COLOR_ARRAY: RLSW.array.colors = buffer; break;
+ default: break;
+ }
+}
+
+void swDrawArrays(SWdraw mode, int offset, int count)
+{
+ if (RLSW.array.positions == 0)
+ {
+ RLSW.errCode = SW_INVALID_OPERATION;
+ return;
+ }
+
+ swBegin(mode);
+ {
+ swTexCoord2f(0.0f, 0.0f);
+ swColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+
+ for (int i = offset; i < count; i++)
+ {
+ if (RLSW.array.texcoords) swTexCoord2fv(RLSW.array.texcoords + 2*i);
+ if (RLSW.array.colors) swColor4ubv(RLSW.array.colors + 4*i);
+ swVertex3fv(RLSW.array.positions + 3*i);
+ }
+ }
+ swEnd();
+}
+
+void swGenTextures(int count, uint32_t *textures)
+{
+ if ((count == 0) || (textures == NULL)) return;
+
+ for (int i = 0; i < count; i++)
+ {
+ if (RLSW.loadedTextureCount >= SW_MAX_TEXTURES)
+ {
+ RLSW.errCode = SW_STACK_OVERFLOW; // WARNING: Out of memory, not really stack overflow
+ return;
+ }
+
+ uint32_t id = 0;
+ if (RLSW.freeTextureIdCount > 0) id = RLSW.freeTextureIds[--RLSW.freeTextureIdCount];
+ else id = RLSW.loadedTextureCount++;
+
+ RLSW.loadedTextures[id] = RLSW.loadedTextures[0];
+ textures[i] = id;
+ }
+}
+
+void swDeleteTextures(int count, uint32_t *textures)
+{
+ if ((count == 0) || (textures == NULL)) return;
+
+ for (int i = 0; i < count; i++)
+ {
+ if (!sw_is_texture_valid(textures[i]))
+ {
+ RLSW.errCode = SW_INVALID_VALUE;
+ continue;
+ }
+
+ if (RLSW.loadedTextures[textures[i]].copy)
+ {
+ SW_FREE(RLSW.loadedTextures[textures[i]].pixels.ptr);
+ }
+
+ RLSW.loadedTextures[textures[i]].pixels.cptr = NULL;
+ RLSW.freeTextureIds[RLSW.freeTextureIdCount++] = textures[i];
+ }
+}
+
+void swTexImage2D(int width, int height, SWformat format, SWtype type, bool copy, const void *data)
+{
+ uint32_t id = RLSW.currentTexture;
+
+ if (!sw_is_texture_valid(id))
+ {
+ RLSW.errCode = SW_INVALID_VALUE;
+ return;
+ }
+
+ int pixelFormat = sw_get_pixel_format(format, type);
+
+ if (pixelFormat <= SW_PIXELFORMAT_UNKNOWN)
+ {
+ RLSW.errCode = SW_INVALID_ENUM;
+ return;
+ }
+
+ sw_texture_t *texture = &RLSW.loadedTextures[id];
+
+ if (copy)
+ {
+ int bytes = sw_get_pixel_bytes(pixelFormat);
+ int size = bytes*width*height;
+ texture->pixels.ptr = SW_MALLOC(size);
+
+ if (texture->pixels.ptr == NULL)
+ {
+ RLSW.errCode = SW_STACK_OVERFLOW; // WARING: Out of memory...
+ return;
+ }
+
+ for (int i = 0; i < size; i++)
+ {
+ ((uint8_t *)texture->pixels.ptr)[i] = ((uint8_t *)data)[i];
+ }
+ }
+ else texture->pixels.cptr = data;
+
+ texture->width = width;
+ texture->height = height;
+ texture->wMinus1 = width - 1;
+ texture->hMinus1 = height - 1;
+ texture->format = pixelFormat;
+ texture->tx = 1.0f/width;
+ texture->ty = 1.0f/height;
+ texture->copy = copy;
+}
+
+void swTexParameteri(int param, int value)
+{
+ uint32_t id = RLSW.currentTexture;
+
+ if (!sw_is_texture_valid(id))
+ {
+ RLSW.errCode = SW_INVALID_VALUE;
+ return;
+ }
+
+ sw_texture_t *texture = &RLSW.loadedTextures[id];
+
+ switch (param)
+ {
+ case SW_TEXTURE_MIN_FILTER:
+ {
+ if (!sw_is_texture_filter_valid(value))
+ {
+ RLSW.errCode = SW_INVALID_ENUM;
+ return;
+ }
+
+ texture->minFilter = value;
+ } break;
+ case SW_TEXTURE_MAG_FILTER:
+ {
+ if (!sw_is_texture_filter_valid(value))
+ {
+ RLSW.errCode = SW_INVALID_ENUM;
+ return;
+ }
+
+ texture->magFilter = value;
+ } break;
+ case SW_TEXTURE_WRAP_S:
+ {
+ if (!sw_is_texture_wrap_valid(value))
+ {
+ RLSW.errCode = SW_INVALID_ENUM;
+ return;
+ }
+
+ texture->sWrap = value;
+ } break;
+ case SW_TEXTURE_WRAP_T:
+ {
+ if (!sw_is_texture_wrap_valid(value))
+ {
+ RLSW.errCode = SW_INVALID_ENUM;
+ return;
+ }
+
+ texture->tWrap = value;
+ } break;
+ default: RLSW.errCode = SW_INVALID_ENUM; break;
+ }
+}
+
+void swBindTexture(uint32_t id)
+{
+ if (id >= SW_MAX_TEXTURES)
+ {
+ RLSW.errCode = SW_INVALID_VALUE;
+ return;
+ }
+
+ if (RLSW.loadedTextures[id].pixels.cptr == NULL)
+ {
+ RLSW.errCode = SW_INVALID_OPERATION;
+ return;
+ }
+
+ RLSW.currentTexture = id;
+}
+
+#endif // RLSW_IMPLEMENTATION
diff --git a/src/platforms/rcore_desktop_glfw.c b/src/platforms/rcore_desktop_glfw.c
index f6a51a004..1beab0611 100644
--- a/src/platforms/rcore_desktop_glfw.c
+++ b/src/platforms/rcore_desktop_glfw.c
@@ -964,8 +964,11 @@ int GetMonitorRefreshRate(int monitor)
if ((monitor >= 0) && (monitor < monitorCount))
{
- const GLFWvidmode *vidmode = glfwGetVideoMode(monitors[monitor]);
- refresh = vidmode->refreshRate;
+ const GLFWvidmode *mode = glfwGetVideoMode(monitors[monitor]);
+
+ if (mode) refresh = mode->refreshRate;
+ else TRACELOG(LOG_WARNING, "GLFW: Failed to find video mode for selected monitor");
+
}
else TRACELOG(LOG_WARNING, "GLFW: Failed to find selected monitor");
diff --git a/src/platforms/rcore_desktop_sdl.c b/src/platforms/rcore_desktop_sdl.c
index ffe4f40a1..0c1d97e46 100644
--- a/src/platforms/rcore_desktop_sdl.c
+++ b/src/platforms/rcore_desktop_sdl.c
@@ -68,18 +68,20 @@
#include "SDL.h"
#endif
-#if defined(GRAPHICS_API_OPENGL_ES2)
- // It seems it does not need to be included to work
- //#include "SDL_opengles2.h"
-#else
- // SDL OpenGL functionality (if required, instead of internal renderer)
- #ifdef USING_SDL3_PROJECT
- #include "SDL3/SDL_opengl.h"
- #elif USING_SDL2_PROJECT
- #include "SDL2/SDL_opengl.h"
- #else
- #include "SDL_opengl.h"
- #endif
+#if !defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
+ #if defined(GRAPHICS_API_OPENGL_ES2)
+ // It seems it does not need to be included to work
+ //#include "SDL_opengles2.h"
+ #else
+ // SDL OpenGL functionality (if required, instead of internal renderer)
+ #ifdef USING_SDL3_PROJECT
+ #include "SDL3/SDL_opengl.h"
+ #elif USING_SDL2_PROJECT
+ #include "SDL2/SDL_opengl.h"
+ #else
+ #include "SDL_opengl.h"
+ #endif
+ #endif
#endif
//----------------------------------------------------------------------------------
@@ -1234,7 +1236,14 @@ void DisableCursor(void)
// Swap back buffer with front buffer (screen drawing)
void SwapScreenBuffer(void)
{
+#if defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
+ // NOTE: We use a preprocessor condition here because `rlCopyFramebuffer` is only declared for software rendering
+ SDL_Surface *surface = SDL_GetWindowSurface(platform.window);
+ rlCopyFramebuffer(0, 0, CORE.Window.render.width, CORE.Window.render.height, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, surface->pixels);
+ SDL_UpdateWindowSurface(platform.window);
+#else
SDL_GL_SwapWindow(platform.window);
+#endif
}
//----------------------------------------------------------------------------------
@@ -1582,13 +1591,15 @@ void PollInputEvents(void)
if (CORE.Input.Keyboard.charPressedQueueCount < MAX_CHAR_PRESSED_QUEUE)
{
// Add character (codepoint) to the queue
- #if defined(USING_VERSION_SDL3)
+
+ #if defined(USING_VERSION_SDL3)
size_t textLen = strlen(event.text.text);
unsigned int codepoint = (unsigned int)SDL_StepUTF8(&event.text.text, &textLen);
- #else
+ #else
int codepointSize = 0;
int codepoint = GetCodepointNextSDL(event.text.text, &codepointSize);
- #endif
+ #endif
+
CORE.Input.Keyboard.charPressedQueue[CORE.Input.Keyboard.charPressedQueueCount] = codepoint;
CORE.Input.Keyboard.charPressedQueueCount++;
}
@@ -1892,7 +1903,6 @@ int InitPlatform(void)
//----------------------------------------------------------------------------
unsigned int flags = 0;
flags |= SDL_WINDOW_SHOWN;
- flags |= SDL_WINDOW_OPENGL;
flags |= SDL_WINDOW_INPUT_FOCUS;
flags |= SDL_WINDOW_MOUSE_FOCUS;
flags |= SDL_WINDOW_MOUSE_CAPTURE; // Window has mouse captured
@@ -1927,44 +1937,50 @@ int InitPlatform(void)
// NOTE: Some OpenGL context attributes must be set before window creation
- // Check selection OpenGL version
- if (rlGetVersion() == RL_OPENGL_21)
+ if (rlGetVersion() != RL_OPENGL_11_SOFTWARE)
{
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
- }
- else if (rlGetVersion() == RL_OPENGL_33)
- {
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
- }
- else if (rlGetVersion() == RL_OPENGL_43)
- {
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
-#if defined(RLGL_ENABLE_OPENGL_DEBUG_CONTEXT)
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG); // Enable OpenGL Debug Context
-#endif
- }
- else if (rlGetVersion() == RL_OPENGL_ES_20) // Request OpenGL ES 2.0 context
- {
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
- }
- else if (rlGetVersion() == RL_OPENGL_ES_30) // Request OpenGL ES 3.0 context
- {
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
- }
+ // Add the flag telling the window to use an OpenGL context
+ flags |= SDL_WINDOW_OPENGL;
- if (CORE.Window.flags & FLAG_MSAA_4X_HINT)
- {
- SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
- SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4);
+ // Check selection OpenGL version
+ if (rlGetVersion() == RL_OPENGL_21)
+ {
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
+ }
+ else if (rlGetVersion() == RL_OPENGL_33)
+ {
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
+ }
+ else if (rlGetVersion() == RL_OPENGL_43)
+ {
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
+ #if defined(RLGL_ENABLE_OPENGL_DEBUG_CONTEXT)
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG); // Enable OpenGL Debug Context
+ #endif
+ }
+ else if (rlGetVersion() == RL_OPENGL_ES_20) // Request OpenGL ES 2.0 context
+ {
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
+ }
+ else if (rlGetVersion() == RL_OPENGL_ES_30) // Request OpenGL ES 3.0 context
+ {
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
+ }
+
+ if (CORE.Window.flags & FLAG_MSAA_4X_HINT)
+ {
+ SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
+ SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4);
+ }
}
// Init window
@@ -1975,10 +1991,12 @@ int InitPlatform(void)
#endif
// Init OpenGL context
- platform.glContext = SDL_GL_CreateContext(platform.window);
+ if (rlGetVersion() != RL_OPENGL_11_SOFTWARE)
+ {
+ platform.glContext = SDL_GL_CreateContext(platform.window);
+ }
- // Check window and glContext have been initialized successfully
- if ((platform.window != NULL) && (platform.glContext != NULL))
+ if ((platform.window != NULL) && ((rlGetVersion() == RL_OPENGL_11_SOFTWARE) || (platform.glContext != NULL)))
{
CORE.Window.ready = true;
@@ -1999,8 +2017,14 @@ int InitPlatform(void)
TRACELOG(LOG_INFO, " > Render size: %i x %i", CORE.Window.render.width, CORE.Window.render.height);
TRACELOG(LOG_INFO, " > Viewport offsets: %i, %i", CORE.Window.renderOffset.x, CORE.Window.renderOffset.y);
- if (CORE.Window.flags & FLAG_VSYNC_HINT) SDL_GL_SetSwapInterval(1);
- else SDL_GL_SetSwapInterval(0);
+ if (platform.glContext != NULL)
+ {
+ SDL_GL_SetSwapInterval((CORE.Window.flags & FLAG_VSYNC_HINT)? 1 : 0);
+
+ // Load OpenGL extensions
+ // NOTE: GL procedures address loader is required to load extensions
+ rlLoadExtensions(SDL_GL_GetProcAddress);
+ }
}
else
{
@@ -2008,9 +2032,6 @@ int InitPlatform(void)
return -1;
}
- // Load OpenGL extensions
- // NOTE: GL procedures address loader is required to load extensions
- rlLoadExtensions(SDL_GL_GetProcAddress);
//----------------------------------------------------------------------------
// Initialize input events system
@@ -2082,7 +2103,7 @@ int InitPlatform(void)
void ClosePlatform(void)
{
SDL_FreeCursor(platform.cursor); // Free cursor
- SDL_GL_DeleteContext(platform.glContext); // Deinitialize OpenGL context
+ if (platform.glContext != NULL) SDL_GL_DeleteContext(platform.glContext); // Deinitialize OpenGL context
SDL_DestroyWindow(platform.window);
SDL_Quit(); // Deinitialize SDL internal global state
}
diff --git a/src/platforms/rcore_desktop_win32.c b/src/platforms/rcore_desktop_win32.c
index c7740ba2e..b9acde0e8 100644
--- a/src/platforms/rcore_desktop_win32.c
+++ b/src/platforms/rcore_desktop_win32.c
@@ -76,8 +76,9 @@
#include
#include
-#include
-//#include
+#if !defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
+ #include
+#endif
//----------------------------------------------------------------------------------
// Types and Structures Definition
@@ -87,9 +88,14 @@
// the backend must keep the client area this size (after DPI scaling is applied)
// when the window isn't fullscreen/maximized/minimized
typedef struct {
- HWND hwnd;
- HDC hdc;
- HGLRC glContext;
+ HWND hwnd; // Window handler
+ HDC hdc; // Graphic context handler
+ HGLRC glContext; // OpenGL context handler
+ // Software renderer variables
+ HDC hdcmem; // Memory graphic context handler
+ HBITMAP hbitmap; // GDI bitmap handler
+ unsigned int *pixels; // Pointer to pixel data buffer (BGRA format)
+
LARGE_INTEGER timerFrequency;
unsigned int appScreenWidth;
unsigned int appScreenHeight;
@@ -251,7 +257,7 @@ static bool DecoratedFromStyle(DWORD style)
static Mized MizedFromStyle(DWORD style)
{
- // minimized takes precedence over maximized
+ // Minimized takes precedence over maximized
if (style & WS_MINIMIZE) return MIZED_MIN;
if (style & WS_MAXIMIZE) return MIZED_MAX;
return MIZED_NONE;
@@ -260,7 +266,7 @@ static Mized MizedFromStyle(DWORD style)
static Mized MizedFromFlags(unsigned flags)
{
// minimized takes precedence over maximized
- if (flags & FLAG_WINDOW_MINIMIZED) return MIZED_MIN;
+ if (FLAG_CHECK(flags, FLAG_WINDOW_MINIMIZED)) return MIZED_MIN;
if (flags & FLAG_WINDOW_MAXIMIZED) return MIZED_MAX;
return MIZED_NONE;
}
@@ -287,15 +293,6 @@ static DWORD MakeWindowStyle(unsigned flags)
return style;
}
-static bool IsMinimized2(HWND hwnd)
-{
- bool isIconic = IsIconic(hwnd);
- bool styleMinimized = !!(WS_MINIMIZE & GetWindowLongPtrW(hwnd, GWL_STYLE));
- if (isIconic != styleMinimized) TRACELOG(LOG_WARNING, "IsIconic(%d) != WS_MINIMIZED(%d)", isIconic, styleMinimized);
-
- return isIconic;
-}
-
// Enforces that the actual window/platform state is in sync with raylib's flags
static void CheckFlags(const char *context, HWND hwnd, DWORD flags, DWORD expectedStyle, DWORD styleCheckMask)
{
@@ -433,6 +430,8 @@ static bool UpdateWindowSize(UpdateWindowKind kind, HWND hwnd, int width, int he
info.cbSize = sizeof(info);
if (!GetMonitorInfoW(monitor, &info)) TRACELOG(LOG_ERROR, "%s failed, error=%lu", "GetMonitorInfo", GetLastError());
+ #define MAX(a,b) (((a)>(b))? (a):(b))
+
LONG monitorWidth = info.rcMonitor.right - info.rcMonitor.left;
LONG monitorHeight = info.rcMonitor.bottom - info.rcMonitor.top;
windowPos = (POINT){
@@ -442,10 +441,16 @@ static bool UpdateWindowSize(UpdateWindowKind kind, HWND hwnd, int width, int he
}
else swpFlags |= SWP_NOMOVE;
- if (!SetWindowPos(hwnd, NULL, windowPos.x, windowPos.y, windowSize.cx, windowSize.cy, swpFlags))
- {
- TRACELOG(LOG_ERROR, "%s failed, error=%lu", "SetWindowPos", GetLastError());
- }
+ // WARNING: This code must be called after swInit() has been called, after InitPlatform() in [rcore]
+ //RECT rc = {0, 0, desired.cx, desired.cy};
+ //AdjustWindowRectEx(&rc, WS_OVERLAPPEDWINDOW, FALSE, 0);
+ //SetWindowPos(hwnd, NULL, windowPos.x, windowPos.y, rc.right - rc.left, rc.bottom - rc.top, SWP_NOMOVE | SWP_NOZORDER);
+
+ // Old code
+ //if (!SetWindowPos(hwnd, NULL, windowPos.x, windowPos.y, windowSize.cx, windowSize.cy, swpFlags))
+ //{
+ // TRACELOG(LOG_ERROR, "%s failed, error=%lu", "SetWindowPos", GetLastError());
+ //}
return true;
}
@@ -1149,8 +1154,18 @@ void DisableCursor(void)
void SwapScreenBuffer(void)
{
if (!platform.hdc) abort();
+
+#if defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
+ // Update framebuffer
+ rlCopyFramebuffer(0, 0, CORE.Window.render.width, CORE.Window.render.height, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, platform.pixels);
+
+ // Force redraw
+ InvalidateRect(platform.hwnd, NULL, FALSE);
+ UpdateWindow(platform.hwnd);
+#else
if (!SwapBuffers(platform.hdc)) TRACELOG(LOG_ERROR, "%s failed, error=%lu", "SwapBuffers", GetLastError());
if (!ValidateRect(platform.hwnd, NULL)) TRACELOG(LOG_ERROR, "%s failed, error=%lu", "ValidateRect", GetLastError());
+#endif
}
//----------------------------------------------------------------------------------
@@ -1264,7 +1279,6 @@ void PollInputEvents(void)
MSG msg = { 0 };
while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE))
{
- if (msg.message == WM_PAINT) return;
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
@@ -1432,7 +1446,7 @@ int InitPlatform(void)
// NOTE: Title string needs to be converted to WCHAR
WCHAR *titleWide = NULL;
A_TO_W_ALLOCA(titleWide, CORE.Window.title);
-
+
// Create window and get handle
platform.hwnd = CreateWindowExW(
WINDOW_STYLE_EX,
@@ -1440,7 +1454,7 @@ int InitPlatform(void)
titleWide,
MakeWindowStyle(CORE.Window.flags), // WS_OVERLAPPEDWINDOW | WS_VISIBLE
CW_USEDEFAULT, CW_USEDEFAULT,
- 0, 0, // Window size [width, height], needs to be updated
+ platform.appScreenWidth, platform.appScreenHeight, // TODO: Window size [width, height], needs to be updated?
NULL, NULL,
GetModuleHandleW(NULL), NULL);
@@ -1454,15 +1468,40 @@ int InitPlatform(void)
// NOTE: Windows GDI object that represents a drawing surface
platform.hdc = GetDC(platform.hwnd);
- // TODO: Support software rendering (instead of hardware-accelerated OpenGL context)
+ if (rlGetVersion() == RL_OPENGL_11_SOFTWARE) // Using software renderer
+ {
+ //ShowWindow(platform.hwnd, SW_SHOWDEFAULT); //SW_SHOWNORMAL
- // Init OpenGL modern context
- platform.glContext = InitOpenGL(platform.hwnd, platform.hdc);
+ // Initialize software framebuffer
+ BITMAPINFO bmi = { 0 };
+ ZeroMemory(&bmi, sizeof(bmi));
+ bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ bmi.bmiHeader.biWidth = platform.appScreenWidth;
+ bmi.bmiHeader.biHeight = -(int)(platform.appScreenHeight); // Top-down bitmap
+ bmi.bmiHeader.biPlanes = 1;
+ bmi.bmiHeader.biBitCount = 32; // 32-bit BGRA
+ bmi.bmiHeader.biCompression = BI_RGB;
+
+ platform.hdcmem = CreateCompatibleDC(platform.hdc);
+
+ platform.hbitmap = CreateDIBSection(
+ platform.hdcmem, &bmi, DIB_RGB_COLORS,
+ (void**)&platform.pixels, NULL, 0);
+
+ SelectObject(platform.hdcmem, platform.hbitmap);
+
+ //ReleaseDC(platform.hwnd, platform.hdc); // Required?
+ }
+ else
+ {
+ // Init hardware-accelerated OpenGL modern context
+ platform.glContext = InitOpenGL(platform.hwnd, platform.hdc);
+ }
CORE.Window.ready = true;
- // TODO: Should this function be called before or after drawing context is created?
- UpdateWindowSize(UPDATE_WINDOW_FIRST, platform.hwnd, platform.appScreenWidth, platform.appScreenHeight, platform.desiredFlags);
+ // TODO: Should this function be called before or after drawing context is created? --> After swInit() called!
+ //UpdateWindowSize(UPDATE_WINDOW_FIRST, platform.hwnd, platform.appScreenWidth, platform.appScreenHeight, platform.desiredFlags);
UpdateFlags(platform.hwnd, platform.desiredFlags, platform.appScreenWidth, platform.appScreenHeight);
CORE.Window.currentFbo.width = CORE.Window.render.width;
@@ -1531,11 +1570,29 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpara
case WM_DESTROY:
{
// Clean up for window destruction
- wglMakeCurrent(platform.hdc, NULL);
- if (platform.glContext)
+ if (rlGetVersion() == RL_OPENGL_11_SOFTWARE) // Using software renderer
{
- if (!wglDeleteContext(platform.glContext)) abort();
- platform.glContext = NULL;
+ if (platform.hdcmem)
+ {
+ DeleteDC(platform.hdcmem);
+ platform.hdcmem = NULL;
+ }
+
+ if (platform.hbitmap)
+ {
+ DeleteObject(platform.hbitmap); // Clears platform.pixels data
+ platform.hbitmap = NULL;
+ platform.pixels = NULL; // NOTE: Pointer invalid after DeleteObject()
+ }
+ }
+ else // OpenGL hardware renderer
+ {
+ wglMakeCurrent(platform.hdc, NULL);
+ if (platform.glContext)
+ {
+ if (!wglDeleteContext(platform.glContext)) abort();
+ platform.glContext = NULL;
+ }
}
if (platform.hdc)
@@ -1544,6 +1601,8 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpara
platform.hdc = NULL;
}
+ PostQuitMessage(0);
+
} break;
case WM_CLOSE: CORE.Window.shouldClose = true; break; // Window close button [x], ALT+F4
//case WM_QUIT: // Application closing, not related to window
@@ -1711,10 +1770,22 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpara
result = DefWindowProc(hwnd, msg, wparam, lparam);
} break;
- //case WM_PAINT
+ case WM_PAINT:
+ {
+ if (rlGetVersion() == RL_OPENGL_11_SOFTWARE) // Using software renderer
+ {
+ PAINTSTRUCT ps = { 0 };
+ HDC hdc = BeginPaint(hwnd, &ps);
+
+ // Blit from memory DC to window DC
+ BitBlt(hdc, 0, 0, platform.appScreenWidth, platform.appScreenHeight, platform.hdcmem, 0, 0, SRCCOPY);
+
+ EndPaint(hwnd, &ps);
+ }
+ }
case WM_INPUT:
{
- HandleRawInput(lparam);
+ //HandleRawInput(lparam);
} break;
case WM_MOUSEMOVE:
{
@@ -1755,7 +1826,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpara
case WM_MOUSEHWHEEL: CORE.Input.Mouse.currentWheelMove.x = ((float)GET_WHEEL_DELTA_WPARAM(wparam))/WHEEL_DELTA; break;
case WM_APP_UPDATE_WINDOW_SIZE:
{
- UpdateWindowSize(UPDATE_WINDOW_NORMAL, hwnd, platform.appScreenWidth, platform.appScreenHeight, CORE.Window.flags);
+ //UpdateWindowSize(UPDATE_WINDOW_NORMAL, hwnd, platform.appScreenWidth, platform.appScreenHeight, CORE.Window.flags);
} break;
default: result = DefWindowProcW(hwnd, msg, wparam, lparam); // Message passed directly for execution (default behaviour)
@@ -1955,6 +2026,7 @@ static void UpdateFlags(HWND hwnd, unsigned desiredFlags, int width, int height)
else CORE.Window.flags &= ~FLAG_VSYNC_HINT;
}
+ // TODO: Review all this code...
DWORD previousStyle;
for (unsigned attempt = 1; ; attempt++)
{
diff --git a/src/platforms/rcore_drm.c b/src/platforms/rcore_drm.c
index dcef0e2ef..87ac034f2 100644
--- a/src/platforms/rcore_drm.c
+++ b/src/platforms/rcore_drm.c
@@ -70,12 +70,17 @@
// so the enum KEY_F12 from raylib is used
#undef KEY_F12
-#include // Generic Buffer Management (native platform for EGL on DRM)
#include // Direct Rendering Manager user-level library interface
#include // Direct Rendering Manager mode setting (KMS) interface
-#include "EGL/egl.h" // Native platform windowing system interface
-#include "EGL/eglext.h" // EGL extensions
+#if !defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
+ #include // Generic Buffer Management (native platform for EGL on DRM)
+ #include "EGL/egl.h" // Native platform windowing system interface
+ #include "EGL/eglext.h" // EGL extensions
+#else
+ #include // For mmap when copying to the dumb buffer
+ #include // For the conversion of certain error messages
+#endif
// NOTE: DRM cache enables triple buffered DRM caching
#if defined(SUPPORT_DRM_CACHE)
@@ -108,15 +113,19 @@ typedef struct {
drmModeConnector *connector; // Direct Rendering Manager (DRM) mode connector
drmModeCrtc *crtc; // CRT Controller
int modeIndex; // Index of the used mode of connector->modes
+ uint32_t prevFB; // Previous DRM framebufer (during frame swapping)
+
+#if !defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
struct gbm_device *gbmDevice; // GBM device
struct gbm_surface *gbmSurface; // GBM surface
struct gbm_bo *prevBO; // Previous GBM buffer object (during frame swapping)
- uint32_t prevFB; // Previous GBM framebufer (during frame swapping)
-
EGLDisplay device; // Native display device (physical screen connection)
EGLSurface surface; // Surface to draw on, framebuffers (connected to context)
EGLContext context; // Graphic context, mode in which drawing can be done
EGLConfig config; // Graphic config
+#else
+ uint32_t prevDumbHandle; // Handle to the previous dumb buffer (during frame swapping)
+#endif
// Keyboard data
int defaultKeyboardMode; // Default keyboard mode
@@ -785,6 +794,8 @@ void SwapScreenBuffer()
// Swap back buffer with front buffer (screen drawing)
void SwapScreenBuffer(void)
{
+#if !defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
+ // Hardware rendering buffer swap with EGL
eglSwapBuffers(platform.device, platform.surface);
if (!platform.gbmSurface || (-1 == platform.fd) || !platform.connector || !platform.crtc) TRACELOG(LOG_ERROR, "DISPLAY: DRM initialization failed to swap");
@@ -810,6 +821,196 @@ void SwapScreenBuffer(void)
if (platform.prevBO) gbm_surface_release_buffer(platform.gbmSurface, platform.prevBO);
platform.prevBO = bo;
+#else
+ // Software rendering buffer swap
+ if ((platform.fd == -1) || !platform.connector || (platform.modeIndex < 0))
+ {
+ TRACELOG(LOG_ERROR, "DISPLAY: DRM initialization failed to swap");
+ return;
+ }
+
+ // Get the software rendered color buffer
+ int bufferWidth = 0, bufferHeight = 0;
+ void *colorBuffer = swGetColorBuffer(&bufferWidth, &bufferHeight);
+ if (!colorBuffer)
+ {
+ TRACELOG(LOG_ERROR, "DISPLAY: Failed to get software color buffer");
+ return;
+ }
+
+ // Retrieving the dimensions of the display mode used
+ drmModeModeInfo *mode = &platform.connector->modes[platform.modeIndex];
+ uint32_t width = mode->hdisplay;
+ uint32_t height = mode->vdisplay;
+
+ // Dumb buffers use a fixed format based on bpp
+#if SW_COLOR_BUFFER_BITS == 24
+ const uint32_t bpp = 32; // 32 bits per pixel (XRGB8888 format)
+ const uint32_t depth = 24; // Color depth, here only 24 bits, alpha is not used
+#else
+ // REVIEW: Not sure how it will be interpreted (RGB or RGBA?)
+ const uint32_t bpp = SW_COLOR_BUFFER_BITS;
+ const uint32_t depth = SW_COLOR_BUFFER_BITS;
+#endif
+
+ // Create a dumb buffer for software rendering
+ struct drm_mode_create_dumb creq = { 0 };
+ creq.width = width;
+ creq.height = height;
+ creq.bpp = bpp;
+
+ int result = drmIoctl(platform.fd, DRM_IOCTL_MODE_CREATE_DUMB, &creq);
+ if (result < 0)
+ {
+ TRACELOG(LOG_ERROR, "DISPLAY: Failed to create dumb buffer: %s", strerror(errno));
+ return;
+ }
+
+ // Create framebuffer with the correct format
+ uint32_t fb = 0;
+ result = drmModeAddFB(platform.fd, width, height, depth, bpp, creq.pitch, creq.handle, &fb);
+ if (result != 0)
+ {
+ TRACELOG(LOG_ERROR, "DISPLAY: drmModeAddFB() failed with result: %d (%s)", result, strerror(errno));
+ struct drm_mode_destroy_dumb dreq = { 0 };
+ dreq.handle = creq.handle;
+ drmIoctl(platform.fd, DRM_IOCTL_MODE_DESTROY_DUMB, &dreq);
+ return;
+ }
+
+ // Map the dumb buffer to copy our software rendered buffer
+ struct drm_mode_map_dumb mreq = { 0 };
+ mreq.handle = creq.handle;
+ result = drmIoctl(platform.fd, DRM_IOCTL_MODE_MAP_DUMB, &mreq);
+ if (result != 0)
+ {
+ TRACELOG(LOG_ERROR, "DISPLAY: Failed to map dumb buffer: %s", strerror(errno));
+ drmModeRmFB(platform.fd, fb);
+ struct drm_mode_destroy_dumb dreq = { 0 };
+ dreq.handle = creq.handle;
+ drmIoctl(platform.fd, DRM_IOCTL_MODE_DESTROY_DUMB, &dreq);
+ return;
+ }
+
+ // Map the buffer into userspace
+ void *dumbBuffer = mmap(0, creq.size, PROT_READ | PROT_WRITE, MAP_SHARED, platform.fd, mreq.offset);
+ if (dumbBuffer == MAP_FAILED)
+ {
+ TRACELOG(LOG_ERROR, "DISPLAY: Failed to mmap dumb buffer: %s", strerror(errno));
+ drmModeRmFB(platform.fd, fb);
+ struct drm_mode_destroy_dumb dreq = { 0 };
+ dreq.handle = creq.handle;
+ drmIoctl(platform.fd, DRM_IOCTL_MODE_DESTROY_DUMB, &dreq);
+ return;
+ }
+
+ // Copy the software rendered buffer to the dumb buffer with scaling if needed
+ if (bufferWidth == width && bufferHeight == height)
+ {
+ // Direct copy if sizes match
+ swCopyFramebuffer(0, 0, bufferWidth, bufferHeight, SW_RGBA, SW_UNSIGNED_BYTE, dumbBuffer);
+ }
+ else
+ {
+ // Scale the software buffer to match the display mode
+ swBlitFramebuffer(0, 0, width, height, 0, 0, bufferWidth, bufferHeight, SW_RGBA, SW_UNSIGNED_BYTE, dumbBuffer);
+ }
+
+ // Unmap the buffer
+ munmap(dumbBuffer, creq.size);
+
+ // Find a CRTC compatible with the connector
+ uint32_t crtcId = 0;
+ if (platform.crtc) crtcId = platform.crtc->crtc_id;
+ else
+ {
+ // Find a CRTC that's compatible with this connector
+ drmModeRes *res = drmModeGetResources(platform.fd);
+ if (!res)
+ {
+ TRACELOG(LOG_ERROR, "DISPLAY: Failed to get DRM resources");
+ drmModeRmFB(platform.fd, fb);
+ struct drm_mode_destroy_dumb dreq = {0};
+ dreq.handle = creq.handle;
+ drmIoctl(platform.fd, DRM_IOCTL_MODE_DESTROY_DUMB, &dreq);
+ return;
+ }
+
+ // Check which CRTCs are compatible with this connector
+ drmModeEncoder *encoder = NULL;
+ if (platform.connector->encoder_id) encoder = drmModeGetEncoder(platform.fd, platform.connector->encoder_id);
+
+ if (encoder && encoder->crtc_id)
+ {
+ crtcId = encoder->crtc_id;
+ platform.crtc = drmModeGetCrtc(platform.fd, crtcId);
+ }
+ else
+ {
+ // Find a free CRTC
+ for (int i = 0; i < res->count_crtcs; i++)
+ {
+ drmModeCrtc *crtc = drmModeGetCrtc(platform.fd, res->crtcs[i]);
+ if (crtc && !crtc->buffer_id) // CRTC is free
+ {
+ crtcId = res->crtcs[i];
+ if (platform.crtc) drmModeFreeCrtc(platform.crtc);
+ platform.crtc = crtc;
+ break;
+ }
+
+ if (crtc) drmModeFreeCrtc(crtc);
+ }
+ }
+
+ if (encoder) drmModeFreeEncoder(encoder);
+ drmModeFreeResources(res);
+
+ if (!crtcId)
+ {
+ TRACELOG(LOG_ERROR, "DISPLAY: No compatible CRTC found");
+ drmModeRmFB(platform.fd, fb);
+ struct drm_mode_destroy_dumb dreq = {0};
+ dreq.handle = creq.handle;
+ drmIoctl(platform.fd, DRM_IOCTL_MODE_DESTROY_DUMB, &dreq);
+ return;
+ }
+ }
+
+ // Set CRTC with better error handling
+ result = drmModeSetCrtc(platform.fd, crtcId, fb, 0, 0, &platform.connector->connector_id, 1, mode);
+ if (result != 0)
+ {
+ TRACELOG(LOG_ERROR, "DISPLAY: drmModeSetCrtc() failed with result: %d (%s)", result, strerror(errno));
+ TRACELOG(LOG_ERROR, "DISPLAY: CRTC ID: %u, FB ID: %u, Connector ID: %u", crtcId, fb, platform.connector->connector_id);
+ TRACELOG(LOG_ERROR, "DISPLAY: Mode: %dx%d@%d", mode->hdisplay, mode->vdisplay, mode->vrefresh);
+
+ drmModeRmFB(platform.fd, fb);
+ struct drm_mode_destroy_dumb dreq = {0};
+ dreq.handle = creq.handle;
+ drmIoctl(platform.fd, DRM_IOCTL_MODE_DESTROY_DUMB, &dreq);
+ return;
+ }
+
+ // Clean up previous framebuffer
+ if (platform.prevFB)
+ {
+ result = drmModeRmFB(platform.fd, platform.prevFB);
+ if (result != 0) TRACELOG(LOG_WARNING, "DISPLAY: drmModeRmFB() failed with result: %d", result);
+ }
+
+ platform.prevFB = fb;
+
+ // Clean up previous dumb buffer
+ if (platform.prevDumbHandle)
+ {
+ struct drm_mode_destroy_dumb dreq = {0};
+ dreq.handle = platform.prevDumbHandle;
+ drmIoctl(platform.fd, DRM_IOCTL_MODE_DESTROY_DUMB, &dreq);
+ }
+
+ platform.prevDumbHandle = creq.handle;
+#endif
}
#endif // SUPPORT_DRM_CACHE
@@ -955,10 +1156,15 @@ int InitPlatform(void)
platform.connector = NULL;
platform.modeIndex = -1;
platform.crtc = NULL;
+ platform.prevFB = 0;
+
+#if !defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
platform.gbmDevice = NULL;
platform.gbmSurface = NULL;
platform.prevBO = NULL;
- platform.prevFB = 0;
+#else
+ platform.prevDumbHandle = 0;
+#endif
// Initialize graphic device: display/window and graphic context
//----------------------------------------------------------------------------
@@ -970,11 +1176,12 @@ int InitPlatform(void)
if (platform.fd != -1) TRACELOG(LOG_INFO, "DISPLAY: Default graphic device DRM opened successfully");
#else
TRACELOG(LOG_WARNING, "DISPLAY: No graphic card set, trying platform-gpu-card");
- platform.fd = open("/dev/dri/by-path/platform-gpu-card", O_RDWR); // VideoCore VI (Raspberry Pi 4)
+ platform.fd = open("/dev/dri/by-path/platform-gpu-card", O_RDWR); // VideoCore VI (Raspberry Pi 4)
if (platform.fd != -1) TRACELOG(LOG_INFO, "DISPLAY: platform-gpu-card opened successfully");
if ((platform.fd == -1) || (drmModeGetResources(platform.fd) == NULL))
{
+ if (platform.fd != -1) close(platform.fd);
TRACELOG(LOG_WARNING, "DISPLAY: Failed to open platform-gpu-card, trying card1");
platform.fd = open("/dev/dri/card1", O_RDWR); // Other Embedded
if (platform.fd != -1) TRACELOG(LOG_INFO, "DISPLAY: card1 opened successfully");
@@ -982,10 +1189,19 @@ int InitPlatform(void)
if ((platform.fd == -1) || (drmModeGetResources(platform.fd) == NULL))
{
+ if (platform.fd != -1) close(platform.fd);
TRACELOG(LOG_WARNING, "DISPLAY: Failed to open graphic card1, trying card0");
platform.fd = open("/dev/dri/card0", O_RDWR); // VideoCore IV (Raspberry Pi 1-3)
if (platform.fd != -1) TRACELOG(LOG_INFO, "DISPLAY: card0 opened successfully");
}
+
+ if ((platform.fd == -1) || (drmModeGetResources(platform.fd) == NULL))
+ {
+ if (platform.fd != -1) close(platform.fd);
+ TRACELOG(LOG_WARNING, "DISPLAY: Failed to open graphic card0, trying card2");
+ platform.fd = open("/dev/dri/card2", O_RDWR);
+ if (platform.fd != -1) TRACELOG(LOG_INFO, "DISPLAY: card2 opened successfully");
+ }
#endif
if (platform.fd == -1)
@@ -998,29 +1214,55 @@ int InitPlatform(void)
if (!res)
{
TRACELOG(LOG_WARNING, "DISPLAY: Failed get DRM resources");
+ close(platform.fd);
return -1;
}
TRACELOG(LOG_TRACE, "DISPLAY: Connectors found: %i", res->count_connectors);
+ // Connector detection
for (size_t i = 0; i < res->count_connectors; i++)
{
TRACELOG(LOG_TRACE, "DISPLAY: Connector index %i", i);
drmModeConnector *con = drmModeGetConnector(platform.fd, res->connectors[i]);
- TRACELOG(LOG_TRACE, "DISPLAY: Connector modes detected: %i", con->count_modes);
+ if (!con)
+ {
+ TRACELOG(LOG_WARNING, "DISPLAY: Failed to get connector %i", i);
+ continue;
+ }
+
+ TRACELOG(LOG_TRACE, "DISPLAY: Connector %i modes detected: %i", i, con->count_modes);
+ TRACELOG(LOG_TRACE, "DISPLAY: Connector %i status: %s", i,
+ (con->connection == DRM_MODE_CONNECTED) ? "CONNECTED" :
+ (con->connection == DRM_MODE_DISCONNECTED) ? "DISCONNECTED" :
+ (con->connection == DRM_MODE_UNKNOWNCONNECTION) ? "UNKNOWN" : "OTHER");
// In certain cases the status of the conneciton is reported as UKNOWN, but it is still connected
// This might be a hardware or software limitation like on Raspberry Pi Zero with composite output
- if (((con->connection == DRM_MODE_CONNECTED) || (con->connection == DRM_MODE_UNKNOWNCONNECTION)) && (con->encoder_id))
+ // WARNING: Accept CONNECTED, UNKNOWN and even those without encoder_id connectors for software mode
+ if (((con->connection == DRM_MODE_CONNECTED) || (con->connection == DRM_MODE_UNKNOWNCONNECTION)) && (con->count_modes > 0))
{
- TRACELOG(LOG_TRACE, "DISPLAY: DRM mode connected");
+#if !defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
+ // For hardware rendering, we need an encoder_id
+ if (con->encoder_id)
+ {
+ TRACELOG(LOG_TRACE, "DISPLAY: DRM connector %i connected with encoder", i);
+ platform.connector = con;
+ break;
+ }
+ else TRACELOG(LOG_TRACE, "DISPLAY: DRM connector %i connected but no encoder", i);
+#else
+ // For software rendering, we can accept even without encoder_id
+ TRACELOG(LOG_TRACE, "DISPLAY: DRM connector %i suitable for software rendering", i);
platform.connector = con;
break;
+#endif
}
- else
+
+ if (!platform.connector)
{
- TRACELOG(LOG_TRACE, "DISPLAY: DRM mode NOT connected (deleting)");
+ TRACELOG(LOG_TRACE, "DISPLAY: DRM connector %i NOT suitable (deleting)", i);
drmModeFreeConnector(con);
}
}
@@ -1029,14 +1271,18 @@ int InitPlatform(void)
{
TRACELOG(LOG_WARNING, "DISPLAY: No suitable DRM connector found");
drmModeFreeResources(res);
+ close(platform.fd);
return -1;
}
+#if !defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
drmModeEncoder *enc = drmModeGetEncoder(platform.fd, platform.connector->encoder_id);
if (!enc)
{
TRACELOG(LOG_WARNING, "DISPLAY: Failed to get DRM mode encoder");
+ drmModeFreeConnector(platform.connector);
drmModeFreeResources(res);
+ close(platform.fd);
return -1;
}
@@ -1045,7 +1291,9 @@ int InitPlatform(void)
{
TRACELOG(LOG_WARNING, "DISPLAY: Failed to get DRM mode crtc");
drmModeFreeEncoder(enc);
+ drmModeFreeConnector(platform.connector);
drmModeFreeResources(res);
+ close(platform.fd);
return -1;
}
@@ -1060,7 +1308,9 @@ int InitPlatform(void)
{
TRACELOG(LOG_WARNING, "DISPLAY: No matching DRM connector mode found");
drmModeFreeEncoder(enc);
+ drmModeFreeConnector(platform.connector);
drmModeFreeResources(res);
+ close(platform.fd);
return -1;
}
@@ -1069,7 +1319,7 @@ int InitPlatform(void)
}
const bool allowInterlaced = CORE.Window.flags & FLAG_INTERLACED_HINT;
- const int fps = (CORE.Time.target > 0)? (1.0/CORE.Time.target) : 60;
+ const int fps = (CORE.Time.target > 0) ? (1.0/CORE.Time.target) : 60;
// Try to find an exact matching mode
platform.modeIndex = FindExactConnectorMode(platform.connector, CORE.Window.screen.width, CORE.Window.screen.height, fps, allowInterlaced);
@@ -1088,7 +1338,9 @@ int InitPlatform(void)
{
TRACELOG(LOG_WARNING, "DISPLAY: Failed to find a suitable DRM connector mode");
drmModeFreeEncoder(enc);
+ drmModeFreeConnector(platform.connector);
drmModeFreeResources(res);
+ close(platform.fd);
return -1;
}
@@ -1097,19 +1349,45 @@ int InitPlatform(void)
TRACELOG(LOG_INFO, "DISPLAY: Selected DRM connector mode %s (%ux%u%c@%u)", platform.connector->modes[platform.modeIndex].name,
platform.connector->modes[platform.modeIndex].hdisplay, platform.connector->modes[platform.modeIndex].vdisplay,
- (platform.connector->modes[platform.modeIndex].flags & DRM_MODE_FLAG_INTERLACE)? 'i' : 'p',
+ (platform.connector->modes[platform.modeIndex].flags & DRM_MODE_FLAG_INTERLACE) ? 'i' : 'p',
platform.connector->modes[platform.modeIndex].vrefresh);
+ drmModeFreeEncoder(enc);
+ enc = NULL;
+#else
+ // For software rendering, the first available mode can be used
+ if (platform.connector->count_modes > 0)
+ {
+ platform.modeIndex = 0;
+ CORE.Window.display.width = platform.connector->modes[0].hdisplay;
+ CORE.Window.display.height = platform.connector->modes[0].vdisplay;
+
+ TRACELOG(LOG_INFO, "DISPLAY: Selected DRM connector mode %s (%ux%u%c@%u) for software rendering",
+ platform.connector->modes[0].name,
+ platform.connector->modes[0].hdisplay,
+ platform.connector->modes[0].vdisplay,
+ (platform.connector->modes[0].flags & DRM_MODE_FLAG_INTERLACE) ? 'i' : 'p',
+ platform.connector->modes[0].vrefresh);
+ }
+ else
+ {
+ TRACELOG(LOG_WARNING, "DISPLAY: No modes available for connector");
+ drmModeFreeConnector(platform.connector);
+ drmModeFreeResources(res);
+ close(platform.fd);
+ return -1;
+ }
+#endif
+
// Use the width and height of the surface for render
CORE.Window.render.width = CORE.Window.screen.width;
CORE.Window.render.height = CORE.Window.screen.height;
- drmModeFreeEncoder(enc);
- enc = NULL;
-
drmModeFreeResources(res);
res = NULL;
+#if !defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
+ // Hardware rendering initialization with EGL
platform.gbmDevice = gbm_create_device(platform.fd);
if (!platform.gbmDevice)
{
@@ -1278,6 +1556,32 @@ int InitPlatform(void)
return -1;
}
+ // Load OpenGL extensions
+ // NOTE: GL procedures address loader is required to load extensions
+ rlLoadExtensions(eglGetProcAddress);
+#else
+ // At this point we need to manage render size vs screen size
+ // NOTE: This function use and modify global module variables:
+ // -> CORE.Window.screen.width/CORE.Window.screen.height
+ // -> CORE.Window.render.width/CORE.Window.render.height
+ // -> CORE.Window.screenScale
+ SetupFramebuffer(CORE.Window.display.width, CORE.Window.display.height);
+
+ // Setup window ready state for software rendering
+ CORE.Window.ready = true;
+
+ CORE.Window.render.width = CORE.Window.screen.width;
+ CORE.Window.render.height = CORE.Window.screen.height;
+ CORE.Window.currentFbo.width = CORE.Window.render.width;
+ CORE.Window.currentFbo.height = CORE.Window.render.height;
+
+ TRACELOG(LOG_INFO, "DISPLAY: Device initialized successfully (Software Rendering)");
+ TRACELOG(LOG_INFO, " > Display size: %i x %i", CORE.Window.display.width, CORE.Window.display.height);
+ TRACELOG(LOG_INFO, " > Screen size: %i x %i", CORE.Window.screen.width, CORE.Window.screen.height);
+ TRACELOG(LOG_INFO, " > Render size: %i x %i", CORE.Window.render.width, CORE.Window.render.height);
+ TRACELOG(LOG_INFO, " > Viewport offsets: %i, %i", CORE.Window.renderOffset.x, CORE.Window.renderOffset.y);
+#endif
+
if ((CORE.Window.flags & FLAG_WINDOW_MINIMIZED) > 0) MinimizeWindow();
// If graphic device is no properly initialized, we end program
@@ -1290,12 +1594,8 @@ int InitPlatform(void)
CORE.Window.flags |= FLAG_WINDOW_MAXIMIZED; // true
CORE.Window.flags &= ~FLAG_WINDOW_UNFOCUSED; // false
- // Load OpenGL extensions
- // NOTE: GL procedures address loader is required to load extensions
- rlLoadExtensions(eglGetProcAddress);
//----------------------------------------------------------------------------
-
- // Initialize timming system
+ // Initialize timing system
//----------------------------------------------------------------------------
// NOTE: timming system must be initialized before the input events system
InitTimer();
@@ -1341,6 +1641,7 @@ void ClosePlatform(void)
platform.prevFB = 0;
}
+#if !defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
if (platform.prevBO)
{
gbm_surface_release_buffer(platform.gbmSurface, platform.prevBO);
@@ -1358,6 +1659,7 @@ void ClosePlatform(void)
gbm_device_destroy(platform.gbmDevice);
platform.gbmDevice = NULL;
}
+#endif
if (platform.crtc)
{
@@ -1379,6 +1681,7 @@ void ClosePlatform(void)
platform.fd = -1;
}
+#if !defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
// Close surface, context and display
if (platform.device != EGL_NO_DISPLAY)
{
@@ -1397,6 +1700,7 @@ void ClosePlatform(void)
eglTerminate(platform.device);
platform.device = EGL_NO_DISPLAY;
}
+#endif
CORE.Window.shouldClose = true; // Added to force threads to exit when the close window is called
diff --git a/src/raylib.h b/src/raylib.h
index 642f9318c..c57efc2e1 100644
--- a/src/raylib.h
+++ b/src/raylib.h
@@ -1262,6 +1262,7 @@ RLAPI void DrawLineV(Vector2 startPos, Vector2 endPos, Color color);
RLAPI void DrawLineEx(Vector2 startPos, Vector2 endPos, float thick, Color color); // Draw a line (using triangles/quads)
RLAPI void DrawLineStrip(const Vector2 *points, int pointCount, Color color); // Draw lines sequence (using gl lines)
RLAPI void DrawLineBezier(Vector2 startPos, Vector2 endPos, float thick, Color color); // Draw line segment cubic-bezier in-out interpolation
+RLAPI void DrawLineDashed(Vector2 startPos, Vector2 endPos, int dashSize, int spaceSize, Color color); // Draw a dashed line
RLAPI void DrawCircle(int centerX, int centerY, float radius, Color color); // Draw a color-filled circle
RLAPI void DrawCircleSector(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw a piece of a circle
RLAPI void DrawCircleSectorLines(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw circle sector outline
diff --git a/src/rcore.c b/src/rcore.c
index 7a17d7f6f..b9098db02 100644
--- a/src/rcore.c
+++ b/src/rcore.c
@@ -1332,7 +1332,7 @@ Shader LoadShader(const char *vsFileName, const char *fsFileName)
if (vsFileName != NULL) vShaderStr = LoadFileText(vsFileName);
if (fsFileName != NULL) fShaderStr = LoadFileText(fsFileName);
- if ((vShaderStr == NULL) && (fShaderStr == NULL)) TraceLog(LOG_WARNING, "SHADER: Shader files provided are not valid, using default shader");
+ if ((vShaderStr == NULL) && (fShaderStr == NULL)) TRACELOG(LOG_WARNING, "SHADER: Shader files provided are not valid, using default shader");
shader = LoadShaderFromMemory(vShaderStr, fShaderStr);
diff --git a/src/rlgl.h b/src/rlgl.h
index 7db05251d..ecd3795a9 100644
--- a/src/rlgl.h
+++ b/src/rlgl.h
@@ -149,7 +149,8 @@
#endif
// Security check in case no GRAPHICS_API_OPENGL_* defined
-#if !defined(GRAPHICS_API_OPENGL_11) && \
+#if !defined(GRAPHICS_API_OPENGL_11_SOFTWARE) && \
+ !defined(GRAPHICS_API_OPENGL_11) && \
!defined(GRAPHICS_API_OPENGL_21) && \
!defined(GRAPHICS_API_OPENGL_33) && \
!defined(GRAPHICS_API_OPENGL_43) && \
@@ -159,7 +160,7 @@
#endif
// Security check in case multiple GRAPHICS_API_OPENGL_* defined
-#if defined(GRAPHICS_API_OPENGL_11)
+#if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
#if defined(GRAPHICS_API_OPENGL_21)
#undef GRAPHICS_API_OPENGL_21
#endif
@@ -174,6 +175,11 @@
#endif
#endif
+// Software implementation uses OpenGL 1.1 functionality
+#if defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
+ #define GRAPHICS_API_OPENGL_11
+#endif
+
// OpenGL 2.1 uses most of OpenGL 3.3 Core functionality
// WARNING: Specific parts are checked with #if defines
#if defined(GRAPHICS_API_OPENGL_21)
@@ -427,7 +433,8 @@ typedef struct rlRenderBatch {
// OpenGL version
typedef enum {
- RL_OPENGL_11 = 1, // OpenGL 1.1
+ RL_OPENGL_11_SOFTWARE = 0, // Software rendering
+ RL_OPENGL_11, // OpenGL 1.1
RL_OPENGL_21, // OpenGL 2.1 (GLSL 120)
RL_OPENGL_33, // OpenGL 3.3 (GLSL 330)
RL_OPENGL_43, // OpenGL 4.3 (using GLSL 330)
@@ -644,10 +651,8 @@ RLAPI void rlEnableVertexBufferElement(unsigned int id); // Enable vertex buffer
RLAPI void rlDisableVertexBufferElement(void); // Disable vertex buffer element (VBO element)
RLAPI void rlEnableVertexAttribute(unsigned int index); // Enable vertex attribute index
RLAPI void rlDisableVertexAttribute(unsigned int index); // Disable vertex attribute index
-#if defined(GRAPHICS_API_OPENGL_11)
RLAPI void rlEnableStatePointer(int vertexAttribType, void *buffer); // Enable attribute state pointer
RLAPI void rlDisableStatePointer(int vertexAttribType); // Disable attribute state pointer
-#endif
// Textures state
RLAPI void rlActiveTextureSlot(int slot); // Select and active a texture slot
@@ -686,6 +691,8 @@ RLAPI void rlDisableScissorTest(void); // Disable scissor test
RLAPI void rlScissor(int x, int y, int width, int height); // Scissor test
RLAPI void rlEnablePointMode(void); // Enable point mode
RLAPI void rlDisablePointMode(void); // Disable point mode
+RLAPI void rlSetPointSize(float size); // Set the point drawing size
+RLAPI float rlGetPointSize(void); // Get the point drawing size
RLAPI void rlEnableWireMode(void); // Enable wire mode
RLAPI void rlDisableWireMode(void); // Disable wire mode
RLAPI void rlSetLineWidth(float width); // Set the line drawing width
@@ -768,6 +775,10 @@ RLAPI unsigned int rlLoadFramebuffer(void); // Loa
RLAPI void rlFramebufferAttach(unsigned int fboId, unsigned int texId, int attachType, int texType, int mipLevel); // Attach texture/renderbuffer to a framebuffer
RLAPI bool rlFramebufferComplete(unsigned int id); // Verify framebuffer is complete
RLAPI void rlUnloadFramebuffer(unsigned int id); // Delete framebuffer from GPU
+#if defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
+RLAPI void rlCopyFramebuffer(int x, int y, int width, int height, int format, void *pixels); // Copy framebuffer pixel data to internal buffer
+RLAPI void rlResizeFramebuffer(int width, int height); // Resize internal framebuffer
+#endif
// Shaders management
RLAPI unsigned int rlLoadShaderCode(const char *vsCode, const char *fsCode); // Load shader from code strings
@@ -834,24 +845,32 @@ RLAPI void rlLoadDrawQuad(void); // Load and draw a quad
#endif
#if defined(GRAPHICS_API_OPENGL_11)
- #if defined(__APPLE__)
- #include // OpenGL 1.1 library for OSX
- #include // OpenGL extensions library
+ #if defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
+ #define RLSW_IMPLEMENTATION
+ #define SW_MALLOC(sz) RL_MALLOC(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
#else
- // APIENTRY for OpenGL function pointer declarations is required
- #if !defined(APIENTRY)
- #if defined(_WIN32)
- #define APIENTRY __stdcall
- #else
- #define APIENTRY
+ #if defined(__APPLE__)
+ #include // OpenGL 1.1 library for OSX
+ #include // OpenGL extensions library
+ #else
+ // APIENTRY for OpenGL function pointer declarations is required
+ #if !defined(APIENTRY)
+ #if defined(_WIN32)
+ #define APIENTRY __stdcall
+ #else
+ #define APIENTRY
+ #endif
+ #endif
+ // WINGDIAPI definition. Some Windows OpenGL headers need it
+ #if !defined(WINGDIAPI) && defined(_WIN32)
+ #define WINGDIAPI __declspec(dllimport)
#endif
- #endif
- // WINGDIAPI definition. Some Windows OpenGL headers need it
- #if !defined(WINGDIAPI) && defined(_WIN32)
- #define WINGDIAPI __declspec(dllimport)
- #endif
- #include // OpenGL 1.1 library
+ #include // OpenGL 1.1 library
+ #endif
#endif
#endif
@@ -2016,6 +2035,25 @@ float rlGetLineWidth(void)
return width;
}
+// Set the point drawing size
+void rlSetPointSize(float size)
+{
+#if defined(GRAPHICS_API_OPENGL_11)
+ glPointSize(size);
+#endif
+}
+
+// Get the point drawing size
+float rlGetPointSize(void)
+{
+ float size = 1;
+#if defined(GRAPHICS_API_OPENGL_11)
+ glGetFloatv(GL_POINT_SIZE, &size);
+#endif
+ return size;
+
+}
+
// Enable line aliasing
void rlEnableSmoothLines(void)
{
@@ -2318,6 +2356,15 @@ void rlglInit(int width, int height)
glShadeModel(GL_SMOOTH); // Smooth shading between vertex (vertex colors interpolation)
#endif
+#if defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
+ int result = swInit(width, height); // Initialize software renderer backend
+ if (result == 0)
+ {
+ TRACELOG(RL_LOG_ERROR, "RLSW: Software renderer initialization failed!");
+ exit(-1);
+ }
+#endif
+
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
// Store screen size into global variables
RLGL.State.framebufferWidth = width;
@@ -2339,11 +2386,15 @@ void rlglClose(void)
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
rlUnloadRenderBatch(RLGL.defaultBatch);
- rlUnloadShaderDefault(); // Unload default shader
+ rlUnloadShaderDefault(); // Unload default shader
glDeleteTextures(1, &RLGL.State.defaultTextureId); // Unload default texture
TRACELOG(RL_LOG_INFO, "TEXTURE: [ID %i] Default texture unloaded successfully", RLGL.State.defaultTextureId);
#endif
+
+#if defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
+ swClose(); // Unload sofware renderer resources
+#endif
}
// Load OpenGL extensions
@@ -2653,7 +2704,10 @@ void *rlGetProcAddress(const char *procName)
int rlGetVersion(void)
{
int glVersion = 0;
-#if defined(GRAPHICS_API_OPENGL_11)
+
+#if defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
+ glVersion = RL_OPENGL_11_SOFTWARE;
+#elif defined(GRAPHICS_API_OPENGL_11)
glVersion = RL_OPENGL_11;
#endif
#if defined(GRAPHICS_API_OPENGL_21)
@@ -3694,6 +3748,22 @@ void *rlReadTexturePixels(unsigned int id, int width, int height, int format)
return pixels;
}
+#if defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
+// Copy framebuffer pixel data to internal buffer
+void rlCopyFramebuffer(int x, int y, int width, int height, int format, void* pixels)
+{
+ unsigned int glInternalFormat, glFormat, glType;
+ rlGetGlTextureFormats(format, &glInternalFormat, &glFormat, &glType); // Get OpenGL texture format
+ swCopyFramebuffer(x, y, width, height, glFormat, glType, pixels);
+}
+
+// Resize internal framebuffer
+void rlResizeFramebuffer(int width, int height)
+{
+ swResizeFramebuffer(width, height);
+}
+#endif
+
// Read screen pixel data (color buffer)
unsigned char *rlReadScreenPixels(int width, int height)
{
@@ -4003,10 +4073,10 @@ void rlDrawVertexArrayElementsInstanced(int offset, int count, const void *buffe
#endif
}
-#if defined(GRAPHICS_API_OPENGL_11)
// Enable vertex state pointer
void rlEnableStatePointer(int vertexAttribType, void *buffer)
{
+#if defined(GRAPHICS_API_OPENGL_11)
if (buffer != NULL) glEnableClientState(vertexAttribType);
switch (vertexAttribType)
{
@@ -4017,14 +4087,16 @@ void rlEnableStatePointer(int vertexAttribType, void *buffer)
//case GL_INDEX_ARRAY: if (buffer != NULL) glIndexPointer(GL_SHORT, 0, buffer); break; // Indexed colors
default: break;
}
+#endif
}
// Disable vertex state pointer
void rlDisableStatePointer(int vertexAttribType)
{
+#if defined(GRAPHICS_API_OPENGL_11)
glDisableClientState(vertexAttribType);
-}
#endif
+}
// Load vertex array object (VAO)
unsigned int rlLoadVertexArray(void)
@@ -5292,4 +5364,4 @@ static Matrix rlMatrixInvert(Matrix mat)
}
#endif
-#endif // RLGL_IMPLEMENTATION
+#endif // RLGL_IMPLEMENTATION
\ No newline at end of file
diff --git a/src/rmodels.c b/src/rmodels.c
index 9aca37a24..1e7599004 100644
--- a/src/rmodels.c
+++ b/src/rmodels.c
@@ -1293,10 +1293,19 @@ void UploadMesh(Mesh *mesh, bool dynamic)
rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION);
// Enable vertex attributes: texcoords (shader-location = 1)
- mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD] = rlLoadVertexBuffer(mesh->texcoords, mesh->vertexCount*2*sizeof(float), dynamic);
- rlSetVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD, 2, RL_FLOAT, 0, 0, 0);
- rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD);
+ if (mesh->texcoords != NULL)
+ {
+ mesh->vboId[RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD] = rlLoadVertexBuffer(mesh->texcoords, mesh->vertexCount*2*sizeof(float), dynamic);
+ rlSetVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD, 2, RL_FLOAT, 0, 0, 0);
+ rlEnableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD);
+ }
+ else
+ {
+ float value[2] = { 0.0f, 0.0f };
+ rlSetVertexAttributeDefault(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD, value, SHADER_ATTRIB_VEC2, 2);
+ rlDisableVertexAttribute(RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD);
+ }
// WARNING: When setting default vertex attribute values, the values for each generic vertex attribute
// is part of current state, and it is maintained even if a different program object is used
@@ -1420,7 +1429,7 @@ void UpdateMeshBuffer(Mesh mesh, int index, const void *data, int dataSize, int
// Draw a 3d mesh with material and transform
void DrawMesh(Mesh mesh, Material material, Matrix transform)
{
-#if defined(GRAPHICS_API_OPENGL_11)
+#if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_11_SOFTWARE)
#define GL_VERTEX_ARRAY 0x8074
#define GL_NORMAL_ARRAY 0x8075
#define GL_COLOR_ARRAY 0x8076
@@ -1431,12 +1440,12 @@ void DrawMesh(Mesh mesh, Material material, Matrix transform)
if (mesh.animVertices) rlEnableStatePointer(GL_VERTEX_ARRAY, mesh.animVertices);
else rlEnableStatePointer(GL_VERTEX_ARRAY, mesh.vertices);
- rlEnableStatePointer(GL_TEXTURE_COORD_ARRAY, mesh.texcoords);
+ if (mesh.texcoords) rlEnableStatePointer(GL_TEXTURE_COORD_ARRAY, mesh.texcoords);
if (mesh.animNormals) rlEnableStatePointer(GL_NORMAL_ARRAY, mesh.animNormals);
- else rlEnableStatePointer(GL_NORMAL_ARRAY, mesh.normals);
+ else if (mesh.normals) rlEnableStatePointer(GL_NORMAL_ARRAY, mesh.normals);
- rlEnableStatePointer(GL_COLOR_ARRAY, mesh.colors);
+ if (mesh.colors) rlEnableStatePointer(GL_COLOR_ARRAY, mesh.colors);
rlPushMatrix();
rlMultMatrixf(MatrixToFloat(transform));
@@ -3836,6 +3845,7 @@ void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float
// Draw a model points
// WARNING: OpenGL ES 2.0 does not support point mode drawing
+// TODO: gate these properly for non es 2.0 versions only
void DrawModelPoints(Model model, Vector3 position, float scale, Color tint)
{
rlEnablePointMode();
@@ -4420,7 +4430,11 @@ static Model LoadOBJ(const char *fileName)
model.meshes[i].vertices = (float *)MemAlloc(sizeof(float)*vertexCount*3);
model.meshes[i].normals = (float *)MemAlloc(sizeof(float)*vertexCount*3);
model.meshes[i].texcoords = (float *)MemAlloc(sizeof(float)*vertexCount*2);
+ #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
model.meshes[i].colors = (unsigned char *)MemAlloc(sizeof(unsigned char)*vertexCount*4);
+ #else
+ model.meshes[i].colors = NULL;
+ #endif
}
MemFree(localMeshVertexCounts);
@@ -4474,8 +4488,18 @@ static Model LoadOBJ(const char *fileName)
for (int i = 0; i < 3; i++) model.meshes[meshIndex].vertices[localMeshVertexCount*3 + i] = objAttributes.vertices[vertIndex*3 + i];
- for (int i = 0; i < 2; i++) model.meshes[meshIndex].texcoords[localMeshVertexCount*2 + i] = objAttributes.texcoords[texcordIndex*2 + i];
- if (objAttributes.normals != NULL && normalIndex != TINYOBJ_INVALID_INDEX && normalIndex >= 0)
+ if ((objAttributes.texcoords != NULL) && (texcordIndex != TINYOBJ_INVALID_INDEX) && (texcordIndex >= 0))
+ {
+ for (int i = 0; i < 2; i++) model.meshes[meshIndex].texcoords[localMeshVertexCount*2 + i] = objAttributes.texcoords[texcordIndex*2 + i];
+ model.meshes[meshIndex].texcoords[localMeshVertexCount*2 + 1] = 1.0f - model.meshes[meshIndex].texcoords[localMeshVertexCount*2 + 1];
+ }
+ else
+ {
+ model.meshes[meshIndex].texcoords[localMeshVertexCount*2 + 0] = 0.0f;
+ model.meshes[meshIndex].texcoords[localMeshVertexCount*2 + 1] = 0.0f;
+ }
+
+ if ((objAttributes.normals != NULL) && (normalIndex != TINYOBJ_INVALID_INDEX) && (normalIndex >= 0))
{
for (int i = 0; i < 3; i++) model.meshes[meshIndex].normals[localMeshVertexCount*3 + i] = objAttributes.normals[normalIndex*3 + i];
}
@@ -4485,11 +4509,9 @@ static Model LoadOBJ(const char *fileName)
model.meshes[meshIndex].normals[localMeshVertexCount*3 + 1] = 1.0f;
model.meshes[meshIndex].normals[localMeshVertexCount*3 + 2] = 0.0f;
}
-
- model.meshes[meshIndex].texcoords[localMeshVertexCount*2 + 1] = 1.0f - model.meshes[meshIndex].texcoords[localMeshVertexCount*2 + 1];
-
+ #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
for (int i = 0; i < 4; i++) model.meshes[meshIndex].colors[localMeshVertexCount*4 + i] = 255;
-
+ #endif
faceVertIndex++;
localMeshVertexCount++;
}
@@ -5001,7 +5023,7 @@ static ModelAnimation *LoadModelAnimationsIQM(const char *fileName, int *animCou
animations[a].bones = (BoneInfo *)RL_MALLOC(iqmHeader->num_poses*sizeof(BoneInfo));
animations[a].framePoses = (Transform **)RL_MALLOC(anim[a].num_frames*sizeof(Transform *));
memcpy(animations[a].name, fileDataPtr + iqmHeader->ofs_text + anim[a].name, 32); // I don't like this 32 here
- TraceLog(LOG_INFO, "IQM Anim %s", animations[a].name);
+ TRACELOG(LOG_INFO, "IQM Anim %s", animations[a].name);
// animations[a].framerate = anim.framerate; // TODO: Use animation framerate data?
for (unsigned int j = 0; j < iqmHeader->num_poses; j++)
diff --git a/src/rshapes.c b/src/rshapes.c
index 14e3f856a..55f7d7fb9 100644
--- a/src/rshapes.c
+++ b/src/rshapes.c
@@ -182,6 +182,28 @@ void DrawLine(int startPosX, int startPosY, int endPosX, int endPosY, Color colo
rlEnd();
}
+// Draw a line defining thickness
+void DrawLineEx(Vector2 startPos, Vector2 endPos, float thick, Color color)
+{
+ Vector2 delta = { endPos.x - startPos.x, endPos.y - startPos.y };
+ float length = sqrtf(delta.x*delta.x + delta.y*delta.y);
+
+ if ((length > 0) && (thick > 0))
+ {
+ float scale = thick/(2*length);
+
+ Vector2 radius = { -scale*delta.y, scale*delta.x };
+ Vector2 strip[4] = {
+ { startPos.x - radius.x, startPos.y - radius.y },
+ { startPos.x + radius.x, startPos.y + radius.y },
+ { endPos.x - radius.x, endPos.y - radius.y },
+ { endPos.x + radius.x, endPos.y + radius.y }
+ };
+
+ DrawTriangleStrip(strip, 4, color);
+ }
+}
+
// Draw a line (using gl lines)
void DrawLineV(Vector2 startPos, Vector2 endPos, Color color)
{
@@ -246,26 +268,50 @@ void DrawLineBezier(Vector2 startPos, Vector2 endPos, float thick, Color color)
DrawTriangleStrip(points, 2*SPLINE_SEGMENT_DIVISIONS + 2, color);
}
-// Draw a line defining thickness
-void DrawLineEx(Vector2 startPos, Vector2 endPos, float thick, Color color)
+// Draw a dashed line
+void DrawLineDashed(Vector2 startPos, Vector2 endPos, int dashSize, int spaceSize, Color color)
{
- Vector2 delta = { endPos.x - startPos.x, endPos.y - startPos.y };
- float length = sqrtf(delta.x*delta.x + delta.y*delta.y);
+ // Calculate the vector and length of the line
+ float dx = endPos.x - startPos.x;
+ float dy = endPos.y - startPos.y;
+ float lineLength = sqrtf(dx*dx + dy*dy);
- if ((length > 0) && (thick > 0))
+ // If the line is too short for dashing or dash size is invalid, draw a solid thick line
+ if ((lineLength < (dashSize + spaceSize)) || (dashSize <= 0))
{
- float scale = thick/(2*length);
-
- Vector2 radius = { -scale*delta.y, scale*delta.x };
- Vector2 strip[4] = {
- { startPos.x - radius.x, startPos.y - radius.y },
- { startPos.x + radius.x, startPos.y + radius.y },
- { endPos.x - radius.x, endPos.y - radius.y },
- { endPos.x + radius.x, endPos.y + radius.y }
- };
-
- DrawTriangleStrip(strip, 4, color);
+ DrawLineV(startPos, endPos, color);
+ return;
}
+
+ // Calculate the normalized direction vector of the line
+ float invLineLength = 1.0f/lineLength;
+ float dirX = dx*invLineLength;
+ float dirY = dy*invLineLength;
+
+ Vector2 currentPos = startPos;
+ float distanceTraveled = 0;
+
+ rlBegin(RL_LINES);
+ rlColor4ub(color.r, color.g, color.b, color.a);
+
+ while (distanceTraveled < lineLength)
+ {
+ // Calculate the end of the current dash
+ float dashEndDist = distanceTraveled + dashSize;
+ if (dashEndDist > lineLength) dashEndDist = lineLength;
+
+ Vector2 dashEndPos = { startPos.x + dashEndDist*dirX, startPos.y + dashEndDist*dirY };
+
+ // Draw the dash segment
+ rlVertex2f(currentPos.x, currentPos.y);
+ rlVertex2f(dashEndPos.x, dashEndPos.y);
+
+ // Update the distance traveled and move the current position for the next dash
+ distanceTraveled = dashEndDist + spaceSize;
+ currentPos.x = startPos.x + distanceTraveled*dirX;
+ currentPos.y = startPos.y + distanceTraveled*dirY;
+ }
+ rlEnd();
}
// Draw a color-filled circle
diff --git a/src/rtext.c b/src/rtext.c
index edfe33c8b..6a87fe3db 100644
--- a/src/rtext.c
+++ b/src/rtext.c
@@ -1452,7 +1452,7 @@ Rectangle GetGlyphAtlasRec(Font font, int codepoint)
char **LoadTextLines(const char *text, int *count)
{
int lineCount = 1;
- int textSize = strlen(text);
+ int textSize = (int)strlen(text);
// Text pass to get required line count
for (int i = 0; i < textSize; i++)
@@ -1679,7 +1679,7 @@ char *GetTextBetween(const char *text, const char *begin, const char *end)
if (beginIndex > -1)
{
- int beginLen = strlen(begin);
+ int beginLen = (int)strlen(begin);
int endIndex = TextFindIndex(text + beginIndex + beginLen, end);
if (endIndex > -1)
@@ -1758,15 +1758,15 @@ char *TextReplaceBetween(const char *text, const char *begin, const char *end, c
if (beginIndex > -1)
{
- int beginLen = strlen(begin);
+ int beginLen = (int)strlen(begin);
int endIndex = TextFindIndex(text + beginIndex + beginLen, end);
if (endIndex > -1)
{
endIndex += (beginIndex + beginLen);
- int textLen = strlen(text);
- int replaceLen = (replacement == NULL)? 0 : strlen(replacement);
+ int textLen = (int)strlen(text);
+ int replaceLen = (replacement == NULL)? 0 : (int)strlen(replacement);
int toreplaceLen = endIndex - beginIndex - beginLen;
result = (char *)RL_CALLOC(textLen + replaceLen - toreplaceLen + 1, sizeof(char));
@@ -1954,6 +1954,7 @@ char *TextToPascal(const char *text)
{
j++;
if ((text[j] >= 'a') && (text[j] <= 'z')) buffer[i] = text[j] - 32;
+ else if ((text[j] >= '0') && (text[j] <= '9')) buffer[i] = text[j];
}
}
}
diff --git a/src/rtextures.c b/src/rtextures.c
index 6366e4645..a85467d8c 100644
--- a/src/rtextures.c
+++ b/src/rtextures.c
@@ -811,8 +811,8 @@ Image GenImageColor(int width, int height, Color color)
.data = pixels,
.width = width,
.height = height,
- .format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8,
- .mipmaps = 1
+ .mipmaps = 1,
+ .format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8
};
return image;
@@ -863,8 +863,8 @@ Image GenImageGradientLinear(int width, int height, int direction, Color start,
.data = pixels,
.width = width,
.height = height,
- .format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8,
- .mipmaps = 1
+ .mipmaps = 1,
+ .format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8
};
return image;
@@ -900,8 +900,8 @@ Image GenImageGradientRadial(int width, int height, float density, Color inner,
.data = pixels,
.width = width,
.height = height,
- .format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8,
- .mipmaps = 1
+ .mipmaps = 1,
+ .format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8
};
return image;
@@ -949,8 +949,8 @@ Image GenImageGradientSquare(int width, int height, float density, Color inner,
.data = pixels,
.width = width,
.height = height,
- .format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8,
- .mipmaps = 1
+ .mipmaps = 1,
+ .format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8
};
return image;
@@ -974,8 +974,8 @@ Image GenImageChecked(int width, int height, int checksX, int checksY, Color col
.data = pixels,
.width = width,
.height = height,
- .format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8,
- .mipmaps = 1
+ .mipmaps = 1,
+ .format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8
};
return image;
@@ -997,8 +997,8 @@ Image GenImageWhiteNoise(int width, int height, float factor)
.data = pixels,
.width = width,
.height = height,
- .format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8,
- .mipmaps = 1
+ .mipmaps = 1,
+ .format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8
};
return image;
@@ -1048,8 +1048,8 @@ Image GenImagePerlinNoise(int width, int height, int offsetX, int offsetY, float
.data = pixels,
.width = width,
.height = height,
- .format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8,
- .mipmaps = 1
+ .mipmaps = 1,
+ .format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8
};
return image;
@@ -1113,8 +1113,8 @@ Image GenImageCellular(int width, int height, int tileSize)
.data = pixels,
.width = width,
.height = height,
- .format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8,
- .mipmaps = 1
+ .mipmaps = 1,
+ .format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8
};
return image;
diff --git a/tools/parser/Makefile b/tools/parser/Makefile
deleted file mode 100644
index ecfdb44ba..000000000
--- a/tools/parser/Makefile
+++ /dev/null
@@ -1,44 +0,0 @@
-EXTENSION?=txt
-FORMAT?=DEFAULT
-.PHONY: all parse clean raylib_api
-
-
-raylib_parser: raylib_parser.c
- cc raylib_parser.c -o raylib_parser
-
-raylib_api: ../../src/raylib.h raylib_parser
- FORMAT=DEFAULT EXTENSION=txt $(MAKE) raylib_api.txt
- FORMAT=JSON EXTENSION=json $(MAKE) raylib_api.json
- FORMAT=XML EXTENSION=xml $(MAKE) raylib_api.xml
- FORMAT=LUA EXTENSION=lua $(MAKE) raylib_api.lua
-
-raylib_api.$(EXTENSION): ../../src/raylib.h raylib_parser
- ./raylib_parser -i ../../src/raylib.h -o raylib_api.$(EXTENSION) -f $(FORMAT) -d RLAPI
-
-raymath_api.$(EXTENSION): ../../src/raymath.h raylib_parser
- ./raylib_parser -i ../../src/raymath.h -o raymath_api.$(EXTENSION) -f $(FORMAT) -d RMAPI
-
-rlgl_api.$(EXTENSION): ../../src/rlgl.h raylib_parser
- ./raylib_parser -i ../../src/rlgl.h -o rlgl_api.$(EXTENSION) -f $(FORMAT) -d RLAPI -t "RLGL IMPLEMENTATION"
-
-reasings_api.$(EXTENSION): ../../examples/others/reasings.h raylib_parser
- ./raylib_parser -i ../../examples/others/reasings.h -o reasings_api.$(EXTENSION) -f $(FORMAT) -d EASEDEF
-
-raygui_api.$(EXTENSION): ../raygui.h raylib_parser
- ./raylib_parser -i ../raygui.h -o raygui_api.$(EXTENSION) -f $(FORMAT) -d RAYGUIAPI -t "RAYGUI IMPLEMENTATION"
-
-parse: raylib_api.$(EXTENSION) raymath_api.$(EXTENSION) rlgl_api.$(EXTENSION) raygui_api.$(EXTENSION)
-
-
-# `make parse` (and therefore `make all) requires
-# rmem.h, physac.h and raygui.h to exist in the correct directory
-# API files for individual headers can be created likeso, provided the relevant header exists:
-# FORMAT=JSON EXTENSION=json make raygui_api.json
-all: raylib_parser
- FORMAT=DEFAULT EXTENSION=txt $(MAKE) parse
- FORMAT=JSON EXTENSION=json $(MAKE) parse
- FORMAT=XML EXTENSION=xml $(MAKE) parse
- FORMAT=LUA EXTENSION=lua $(MAKE) parse
-
-clean:
- rm -f raylib_parser *.json *.txt *.xml *.lua
diff --git a/tools/rexm/Makefile b/tools/rexm/Makefile
index f5e7d1fe4..d7d71f64f 100644
--- a/tools/rexm/Makefile
+++ b/tools/rexm/Makefile
@@ -35,7 +35,7 @@ PROJECT_BUILD_PATH ?= .
PROJECT_SOURCE_FILES ?= rexm.c
# raylib library variables
-RAYLIB_SRC_PATH ?= ..\..\src
+RAYLIB_SRC_PATH ?= ../../src
RAYLIB_INCLUDE_PATH ?= $(RAYLIB_SRC_PATH)
RAYLIB_LIB_PATH ?= $(RAYLIB_SRC_PATH)
@@ -236,7 +236,7 @@ ifeq ($(PLATFORM),PLATFORM_WEB)
# --source-map-base # allow debugging in browser with source map
# --shell-file shell.html # define a custom shell .html and output extension
LDFLAGS += -sUSE_GLFW=3 -sTOTAL_MEMORY=$(BUILD_WEB_HEAP_SIZE) -sSTACK_SIZE=$(BUILD_WEB_STACK_SIZE) -sFORCE_FILESYSTEM=1 -sMINIFY_HTML=0
-
+
# Build using asyncify
ifeq ($(BUILD_WEB_ASYNCIFY),TRUE)
LDFLAGS += -sASYNCIFY -sASYNCIFY_STACK_SIZE=$(BUILD_WEB_ASYNCIFY_STACK_SIZE)
@@ -363,4 +363,3 @@ ifeq ($(PLATFORM),PLATFORM_WEB)
del *.o *.html *.js
endif
@echo Cleaning done
-
diff --git a/tools/rexm/examples_report.md b/tools/rexm/examples_report.md
index bb37b2db7..60da00dd5 100644
--- a/tools/rexm/examples_report.md
+++ b/tools/rexm/examples_report.md
@@ -21,6 +21,7 @@ Example elements validated:
| **EXAMPLE NAME** | [C] | [CAT]| [INFO]|[PNG]|[WPNG]| [RES]| [MK] |[MKWEB]| [VCX]| [SOL]|[RDME]|[JS] | [WOUT]|[WMETA]|
|:---------------------------------|:---:|:----:|:-----:|:---:|:----:|:----:|:----:|:-----:|:----:|:----:|:----:|:---:|:-----:|:-----:|
| core_basic_window | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+| core_delta_time | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| core_input_keys | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| core_input_mouse | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| core_input_mouse_wheel | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
@@ -43,6 +44,7 @@ Example elements validated:
| core_window_flags | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| core_window_letterbox | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| core_window_should_close | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+| core_monitor_change | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| core_custom_logging | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| core_drop_files | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| core_random_values | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
@@ -57,8 +59,10 @@ Example elements validated:
| core_high_dpi | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| core_render_texture | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| core_undo_redo | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+| core_input_actions | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| shapes_basic_shapes | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| shapes_bouncing_ball | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+| shapes_bullet_hell | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| shapes_colors_palette | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| shapes_logo_raylib | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| shapes_logo_raylib_anim | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
@@ -69,6 +73,7 @@ Example elements validated:
| shapes_easings_ball | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| shapes_easings_box | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| shapes_easings_rectangles | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+| shapes_recursive_tree | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| shapes_ring_drawing | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| shapes_circle_sector_drawing | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| shapes_rounded_rectangle_drawing | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
@@ -77,6 +82,10 @@ Example elements validated:
| shapes_splines_drawing | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| shapes_digital_clock | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| shapes_double_pendulum | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+| shapes_dashed_line | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+| shapes_triangle_strip | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+| shapes_vector_angle | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+| shapes_kaleidoscope | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| textures_logo_raylib | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| textures_srcrec_dstrec | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| textures_image_drawing | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
@@ -140,6 +149,9 @@ Example elements validated:
| models_animation_gpu_skinning | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| models_bone_socket | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| models_tesseract_view | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+| models_basic_voxel | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+| models_geometry_textures_cube | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+| shaders_ascii_rendering | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| shaders_basic_lighting | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| shaders_model_shader | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| shaders_shapes_textures | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
@@ -182,4 +194,4 @@ Example elements validated:
| easings_testbed | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| raylib_opengl_interop | ✔ | ❌ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ |
| embedded_files_loading | ✔ | ❌ | ✔ | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
-| raymath_vector_angle | ✔ | ❌ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ |
+| web_basic_window | ✔ | ❌ | ✔ | ❌ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
diff --git a/tools/rexm/examples_report_issues.md b/tools/rexm/examples_report_issues.md
index 5c4df4202..5178dabdd 100644
--- a/tools/rexm/examples_report_issues.md
+++ b/tools/rexm/examples_report_issues.md
@@ -25,4 +25,4 @@ Example elements validated:
| easings_testbed | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| raylib_opengl_interop | ✔ | ❌ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ |
| embedded_files_loading | ✔ | ❌ | ✔ | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
-| raymath_vector_angle | ✔ | ❌ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ |
+| web_basic_window | ✔ | ❌ | ✔ | ❌ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
diff --git a/tools/rexm/rexm.c b/tools/rexm/rexm.c
index 7f303538c..2dc295f37 100644
--- a/tools/rexm/rexm.c
+++ b/tools/rexm/rexm.c
@@ -56,7 +56,7 @@
#define SUPPORT_LOG_INFO
#if defined(SUPPORT_LOG_INFO) && defined(_DEBUG)
- #define LOG(...) printf(__VA_ARGS__)
+ #define LOG(...) printf("REXM: "__VA_ARGS__)
#else
#define LOG(...)
#endif
@@ -76,7 +76,7 @@
//----------------------------------------------------------------------------------
// raylib example info struct
typedef struct {
- char category[16]; // Example category: core, shapes, textures, text, models, shaders, audio, others
+ char category[16]; // Example category: core, shapes, textures, text, models, shaders, audio, [others]
char name[128]; // Example name: _name_part
int stars; // Example stars count: ★☆☆☆
char verCreated[12]; // Example raylib creation version
@@ -137,13 +137,6 @@ static const char *exVSProjectSolutionFile = NULL; // Env REXM_EXAMPLES_VS2022_S
//----------------------------------------------------------------------------------
// Module Internal Functions Declaration
//----------------------------------------------------------------------------------
-//static int FileTextFind(const char *fileName, const char *find);
-//static int FileTextReplace(const char *fileName, const char *find, const char *replace);
-//static int FileCopy(const char *srcPath, const char *dstPath);
-//static int FileRename(const char *fileName, const char *fileRename);
-//static int FileMove(const char *srcPath, const char *dstPath);
-//static int FileRemove(const char *fileName);
-
// Update required files from examples collection
// UPDATES: Makefile, Makefile.Web, README.md, examples.js
static int UpdateRequiredFiles(void);
@@ -178,6 +171,7 @@ static int RemoveVSProjectFromSolution(const char *slnFile, const char *exName);
// Generate unique UUID v4 string
// Output format: {9A2F48CC-0DA8-47C0-884E-02E37F9BE6C1}
+// TODO: It seems generated UUID is not valid for VS2022
static const char *GenerateUUIDv4(void);
// Update source code header and comments metadata
@@ -185,10 +179,8 @@ static void UpdateSourceMetadata(const char *exSrcPath, const rlExampleInfo *inf
// Update generated Web example .html file metadata
static void UpdateWebMetadata(const char *exHtmlPath, const char *exFilePath);
-// Get text between two strings
-//static char *GetTextBetween(const char *text, const char *begin, const char *end);
-// Replace text between two specific strings
-//static char *TextReplaceBetween(const char *text, const char *begin, const char *end, const char *replace);
+// Check if text string is a list of strings
+static bool TextInList(const char *text, const char **list, int listCount);
//------------------------------------------------------------------------------------
// Program main entry point
@@ -205,12 +197,22 @@ int main(int argc, char *argv[])
exCollectionFilePath = getenv("REXM_EXAMPLES_COLLECTION_FILE_PATH");
exVSProjectSolutionFile = getenv("REXM_EXAMPLES_VS2022_SLN_FILE");
+#if defined(_WIN32)
if (!exBasePath) exBasePath = "C:/GitHub/raylib/examples";
if (!exWebPath) exWebPath = "C:/GitHub/raylib.com/examples";
if (!exTemplateFilePath) exTemplateFilePath = "C:/GitHub/raylib/examples/examples_template.c";
if (!exTemplateScreenshot) exTemplateScreenshot = "C:/GitHub/raylib/examples/examples_template.png";
if (!exCollectionFilePath) exCollectionFilePath = "C:/GitHub/raylib/examples/examples_list.txt";
if (!exVSProjectSolutionFile) exVSProjectSolutionFile = "C:/GitHub/raylib/projects/VS2022/raylib.sln";
+#else
+ // Cross-platform relative fallbacks (run from tools/rexm directory)
+ if (!exBasePath) exBasePath = "../../examples";
+ if (!exWebPath) exWebPath = "../../raylib.com/examples";
+ if (!exTemplateFilePath) exTemplateFilePath = "../../examples/examples_template.c";
+ if (!exTemplateScreenshot) exTemplateScreenshot = "../../examples/examples_template.png";
+ if (!exCollectionFilePath) exCollectionFilePath = "../../examples/examples_list.txt";
+ if (!exVSProjectSolutionFile) exVSProjectSolutionFile = "../../projects/VS2022/raylib.sln";
+#endif
char inFileName[1024] = { 0 }; // Example input filename (to be added)
@@ -219,27 +221,12 @@ int main(int argc, char *argv[])
char exRecategory[32] = { 0 }; // Example re-name category: shapes
char exRename[64] = { 0 }; // Example re-name, without extension
+ char exRebuildRequested[16] = { 0 }; // Example category/full rebuild request
+
int opCode = OP_NONE; // Operation code: 0-None(Help), 1-Create, 2-Add, 3-Rename, 4-Remove
+ bool verbose = false; // Flag for verbose log info
- /*
- // Testing code for UpdateSourceMetadata()
- rlExampleInfo test = { 0 };
- strcpy(test.category, "core");
- strcpy(test.name, "core_boring_window");
- test.stars = 4;
- strcpy(test.verCreated, "2.9");
- strcpy(test.verUpdated, "6.0");
- test.yearCreated = 2010;
- test.yearReviewed = 2026;
- strcpy(test.author, "John W. Smith");
- strcpy(test.authorGitHub, "littlejohnny");
-
- char exSourcePath[512] = { 0 };
- strcpy(exSourcePath, TextFormat("%s/core/core_basic_window.c", exBasePath)); // WARNING: Cache path for saving
- UpdateSourceMetadata(exSourcePath, &test);
- */
-
- // Command-line usage mode
+ // Command-line usage mode: command args processing
//--------------------------------------------------------------------------------------
if (argc > 1)
{
@@ -402,24 +389,43 @@ int main(int argc, char *argv[])
else if (argc > 3) LOG("WARNING: Too many arguments provided\n");
else
{
- // Verify example exists in collection to be removed
- char *exColInfo = LoadFileText(exCollectionFilePath);
- if (TextFindIndex(exColInfo, argv[2]) != -1) // Example in the collection
- {
- strcpy(exName, argv[2]); // Register example name for removal
- strncpy(exCategory, exName, TextFindIndex(exName, "_"));
- opCode = OP_BUILD;
+ // Support building not only individual examples but categories and "ALL"
+ if ((strcmp(argv[2], "ALL") == 0) || TextInList(argv[2], exCategories, REXM_MAX_EXAMPLE_CATEGORIES))
+ {
+ // Category/ALL rebuilt requested
+ strcpy(exRebuildRequested, argv[2]);
+ }
+ else
+ {
+ // Verify example exists in collection to be removed
+ char *exColInfo = LoadFileText(exCollectionFilePath);
+ if (TextFindIndex(exColInfo, argv[2]) != -1) // Example in the collection
+ {
+ strcpy(exName, argv[2]); // Register example name for removal
+ strncpy(exCategory, exName, TextFindIndex(exName, "_"));
+ opCode = OP_BUILD;
+ }
+ else LOG("WARNING: BUILD: Example requested not available in the collection\n");
+ UnloadFileText(exColInfo);
}
- else LOG("WARNING: BUILD: Example not available in the collection\n");
- UnloadFileText(exColInfo);
}
}
+
+ // Check for verbose log mode request
+ for (int i = 1; i < argc; i++)
+ {
+ if ((strcmp(argv[i], "-v") == 0) || (strcmp(argv[i], "--verbose") == 0)) verbose = true;
+ }
}
+ // Command-line usage mode: command execution
switch (opCode)
{
case OP_CREATE: // Create: New example from template
{
+ LOG("INFO: Command requested: CREATE\n");
+ LOG("INFO: Example to create: %s\n", exName);
+
// Create: raylib/examples//_example_name.c
char *exText = LoadFileText(exTemplateFilePath);
char *exTextUpdated[6] = { 0 };
@@ -439,6 +445,9 @@ int main(int argc, char *argv[])
}
case OP_ADD: // Add: Example from command-line input filename
{
+ if (opCode != OP_CREATE) LOG("INFO: Command requested: ADD\n");
+ LOG("INFO: Example file to be added: %s\n", inFileName);
+
// Add: raylib/examples//_example_name.c
if (opCode != OP_CREATE) FileCopy(inFileName, TextFormat("%s/%s/%s.c", exBasePath, exCategory, exName));
@@ -530,14 +539,14 @@ int main(int argc, char *argv[])
// by default add it last in the category list
// NOTE: When populating to other files, lists are sorted by name
int nextCategoryIndex = 0;
- if (strcmp(exCategory, "core") == 0) nextCategoryIndex = 1;
- else if (strcmp(exCategory, "shapes") == 0) nextCategoryIndex = 2;
- else if (strcmp(exCategory, "textures") == 0) nextCategoryIndex = 3;
- else if (strcmp(exCategory, "text") == 0) nextCategoryIndex = 4;
- else if (strcmp(exCategory, "models") == 0) nextCategoryIndex = 5;
- else if (strcmp(exCategory, "shaders") == 0) nextCategoryIndex = 6;
- else if (strcmp(exCategory, "audio") == 0) nextCategoryIndex = 7;
- else if (strcmp(exCategory, "others") == 0) nextCategoryIndex = -1; // Add to EOF
+ if (TextIsEqual(exCategory, "core")) nextCategoryIndex = 1;
+ else if (TextIsEqual(exCategory, "shapes")) nextCategoryIndex = 2;
+ else if (TextIsEqual(exCategory, "textures")) nextCategoryIndex = 3;
+ else if (TextIsEqual(exCategory, "text")) nextCategoryIndex = 4;
+ else if (TextIsEqual(exCategory, "models")) nextCategoryIndex = 5;
+ else if (TextIsEqual(exCategory, "shaders")) nextCategoryIndex = 6;
+ else if (TextIsEqual(exCategory, "audio")) nextCategoryIndex = 7;
+ else if (TextIsEqual(exCategory, "others")) nextCategoryIndex = -1; // Add to EOF
// Get required example info from example file header (if provided)
@@ -638,6 +647,9 @@ int main(int argc, char *argv[])
} break;
case OP_RENAME: // Rename
{
+ LOG("INFO: Command requested: RENAME\n");
+ LOG("INFO: Example to be renamed: %s --> %s\n", exName, exRename);
+
// NOTE: At this point provided values have been validated:
// exName, exCategory, exRename, exRecategory
if (strcmp(exCategory, exRecategory) == 0)
@@ -749,6 +761,9 @@ int main(int argc, char *argv[])
} break;
case OP_REMOVE: // Remove
{
+ LOG("INFO: Command requested: REMOVE\n");
+ LOG("INFO: Example to be removed: %s\n", exName);
+
// Remove example from collection for files update
//------------------------------------------------------------------------------------------------
char *exCollectionList = LoadFileText(exCollectionFilePath);
@@ -827,10 +842,70 @@ int main(int argc, char *argv[])
FileRemove(TextFormat("%s/%s/%s.wasm", exWebPath, exCategory, exName));
FileRemove(TextFormat("%s/%s/%s.js", exWebPath, exCategory, exName));
+ } break;
+ case OP_BUILD:
+ {
+ LOG("INFO: Command requested: BUILD\n");
+ LOG("INFO: Example to be built: %s\n", exRebuildRequested);
+
+ if ((strcmp(exRebuildRequested, "others") != 0) &&
+ (strcmp(exCategory, "others") != 0)) // Skipping "others" category for rebuild: Special needs
+ {
+ int exRebuildCount = 0;
+ rlExampleInfo *exRebuildList = LoadExamplesData(exCollectionFilePath, exRebuildRequested, false, &exRebuildCount);
+
+ // Build: raylib.com/examples//_example_name.html
+ // Build: raylib.com/examples//_example_name.data
+ // Build: raylib.com/examples//_example_name.wasm
+ // Build: raylib.com/examples//_example_name.js
+
+#if defined(_WIN32)
+ // Set required environment variables
+ //putenv(TextFormat("RAYLIB_DIR=%s\\..", exBasePath));
+ putenv("PATH=%PATH%;C:\\raylib\\w64devkit\\bin");
+ //putenv("MAKE=mingw32-make");
+ //ChangeDirectory(exBasePath);
+#endif
+ for (int i = 0; i < exRebuildCount; i++)
+ {
+ // Build example for PLATFORM_DESKTOP
+#if defined(_WIN32)
+ system(TextFormat("mingw32-make -C %s %s/%s PLATFORM=PLATFORM_DESKTOP -B", exBasePath, exRebuildList[i].category, exRebuildList[i].name));
+#else
+ system(TextFormat("make -C %s %s/%s PLATFORM=PLATFORM_DESKTOP -B", exBasePath, exRebuildList[i].category, exRebuildList[i].name));
+#endif
+
+ // Build example for PLATFORM_WEB
+#if defined(_WIN32)
+ system(TextFormat("mingw32-make -C %s -f Makefile.Web %s/%s PLATFORM=PLATFORM_WEB -B", exBasePath, exRebuildList[i].category, exRebuildList[i].name));
+#else
+ system(TextFormat("make -C %s -f Makefile.Web %s/%s PLATFORM=PLATFORM_WEB -B", exBasePath, exRebuildList[i].category, exRebuildList[i].name));
+#endif
+ // Update generated .html metadata
+ UpdateWebMetadata(TextFormat("%s/%s/%s.html", exBasePath, exRebuildList[i].category, exRebuildList[i].name),
+ TextFormat("%s/%s/%s.c", exBasePath, exRebuildList[i].category, exRebuildList[i].name));
+
+ // Copy results to web side
+ FileCopy(TextFormat("%s/%s/%s.html", exBasePath, exRebuildList[i].category, exRebuildList[i].name),
+ TextFormat("%s/%s/%s.html", exWebPath, exRebuildList[i].category, exRebuildList[i].name));
+ FileCopy(TextFormat("%s/%s/%s.data", exBasePath, exRebuildList[i].category, exRebuildList[i].name),
+ TextFormat("%s/%s/%s.data", exWebPath, exRebuildList[i].category, exRebuildList[i].name));
+ FileCopy(TextFormat("%s/%s/%s.wasm", exBasePath, exRebuildList[i].category, exRebuildList[i].name),
+ TextFormat("%s/%s/%s.wasm", exWebPath, exRebuildList[i].category, exRebuildList[i].name));
+ FileCopy(TextFormat("%s/%s/%s.js", exBasePath, exRebuildList[i].category, exRebuildList[i].name),
+ TextFormat("%s/%s/%s.js", exWebPath, exRebuildList[i].category, exRebuildList[i].name));
+ }
+
+ UnloadExamplesData(exRebuildList);
+ }
+ else LOG("WARNING: [others] category examples should be build manually, they could have specific build requirements\n");
+
} break;
case OP_VALIDATE: // Validate: report and actions
case OP_UPDATE:
{
+ LOG("INFO: Command requested: %s\n", (opCode == OP_VALIDATE)? "VALIDATE" : "UPDATE");
+ LOG("INFO: Example collection is being %s\n", (opCode == OP_VALIDATE)? "validated" : "validated and updated");
/*
// Validation flags available:
VALID_MISSING_C
@@ -852,7 +927,7 @@ int main(int argc, char *argv[])
// Scan available example .c files and add to collection missing ones
// NOTE: Source of truth is what we have in the examples directories (on validation/update)
- FilePathList list = LoadDirectoryFilesEx(exBasePath, ".c", true);
+ FilePathList clist = LoadDirectoryFilesEx(exBasePath, ".c", true);
char *exList = LoadFileText(exCollectionFilePath);
char *exListUpdated = (char *)RL_CALLOC(REXM_MAX_BUFFER_SIZE, 1);
@@ -877,32 +952,39 @@ int main(int argc, char *argv[])
UnloadTextLines(exListLines, lineCount);
- for (unsigned int i = 0; i < list.count; i++)
+ for (unsigned int i = 0; i < clist.count; i++)
{
// NOTE: Skipping "examples_template" from checks
- if ((strcmp("examples_template", GetFileNameWithoutExt(list.paths[i])) != 0) &&
- (TextFindIndex(exList, GetFileNameWithoutExt(list.paths[i])) == -1))
+ if (!TextIsEqual(GetFileNameWithoutExt(clist.paths[i]), "examples_template") &&
+ (TextFindIndex(exList, GetFileNameWithoutExt(clist.paths[i])) == -1))
{
// Add example to the examples collection list
// WARNING: Added to the end of the list, order must be set by users and
// defines placement on raylib webpage
- rlExampleInfo *exInfo = LoadExampleInfo(list.paths[i]);
+ rlExampleInfo *exInfo = LoadExampleInfo(clist.paths[i]);
- // Get example difficulty stars
- char starsText[16] = { 0 };
- for (int s = 0; s < 4; s++)
+ // Validate example category
+ // TODO: Should [others] category be considered?
+ if (TextInList(exInfo->category, exCategories, REXM_MAX_EXAMPLE_CATEGORIES))// && !TextIsEqual(exInfo->category, "others"))
{
- // NOTE: Every UTF-8 star are 3 bytes
- if (s < exInfo->stars) strcpy(starsText + 3*s, "★");
- else strcpy(starsText + 3*s, "☆");
+ // Get example difficulty stars
+ char starsText[16] = { 0 };
+ for (int s = 0; s < 4; s++)
+ {
+ // NOTE: Every UTF-8 star are 3 bytes
+ if (s < exInfo->stars) strcpy(starsText + 3*s, "★");
+ else strcpy(starsText + 3*s, "☆");
+ }
+
+ exListLen += sprintf(exListUpdated + exListLen,
+ TextFormat("%s;%s;%s;%s;%s;%i;%i;\"%s\";@%s\n",
+ exInfo->category, exInfo->name, starsText, exInfo->verCreated,
+ exInfo->verUpdated, exInfo->yearCreated, exInfo->yearReviewed,
+ exInfo->author, exInfo->authorGitHub));
+
+ listUpdated = true;
}
- exListLen += sprintf(exListUpdated + exListLen,
- TextFormat("%s;%s;%s;%s;%s;\"%s\";@%s\n",
- exInfo->category, exInfo->name, starsText, exInfo->verCreated,
- exInfo->verUpdated, exInfo->author, exInfo->authorGitHub));
-
- listUpdated = true;
UnloadExampleInfo(exInfo);
}
}
@@ -912,7 +994,7 @@ int main(int argc, char *argv[])
UnloadFileText(exList);
RL_FREE(exListUpdated);
- UnloadDirectoryFiles(list);
+ UnloadDirectoryFiles(clist);
// Check all examples in collection [examples_list.txt] -> Source of truth!
int exCollectionCount = 0;
@@ -1287,48 +1369,6 @@ int main(int argc, char *argv[])
//------------------------------------------------------------------------------------------------
} break;
- case OP_BUILD:
- {
- // Build: raylib.com/examples//_example_name.html
- // Build: raylib.com/examples//_example_name.data
- // Build: raylib.com/examples//_example_name.wasm
- // Build: raylib.com/examples//_example_name.js
- if (strcmp(exCategory, "others") != 0) // Skipping "others" category
- {
- // Build example for PLATFORM_DESKTOP
- #if defined(_WIN32)
- //putenv(TextFormat("RAYLIB_DIR=%s\\..", exBasePath));
- putenv("PATH=%PATH%;C:\\raylib\\w64devkit\\bin");
- //putenv("MAKE=mingw32-make");
- //ChangeDirectory(exBasePath);
- system(TextFormat("mingw32-make -C %s %s/%s PLATFORM=PLATFORM_DESKTOP -B", exBasePath, exCategory, exName));
- #else
- system(TextFormat("make -C %s %s/%s PLATFORM=PLATFORM_DESKTOP -B", exBasePath, exCategory, exName));
- #endif
-
- // Build example for PLATFORM_WEB
- #if defined(_WIN32)
- putenv("PATH=%PATH%;C:\\raylib\\w64devkit\\bin");
- system(TextFormat("mingw32-make -C %s -f Makefile.Web %s/%s PLATFORM=PLATFORM_WEB -B", exBasePath, exCategory, exName));
- #else
- system(TextFormat("make -C %s -f Makefile.Web %s/%s PLATFORM=PLATFORM_WEB -B", exBasePath, exCategory, exName));
- #endif
-
- // Update generated .html metadata
- UpdateWebMetadata(TextFormat("%s/%s/%s.html", exBasePath, exCategory, exName),
- TextFormat("%s/%s/%s.c", exBasePath, exCategory, exName));
-
- // Copy results to web side
- FileCopy(TextFormat("%s/%s/%s.html", exBasePath, exCategory, exName),
- TextFormat("%s/%s/%s.html", exWebPath, exCategory, exName));
- FileCopy(TextFormat("%s/%s/%s.data", exBasePath, exCategory, exName),
- TextFormat("%s/%s/%s.data", exWebPath, exCategory, exName));
- FileCopy(TextFormat("%s/%s/%s.wasm", exBasePath, exCategory, exName),
- TextFormat("%s/%s/%s.wasm", exWebPath, exCategory, exName));
- FileCopy(TextFormat("%s/%s/%s.js", exBasePath, exCategory, exName),
- TextFormat("%s/%s/%s.js", exWebPath, exCategory, exName));
- }
- } break;
default: // Help
{
// Supported commands:
@@ -1660,54 +1700,67 @@ static int UpdateRequiredFiles(void)
// NOTE: Entries format: exampleEntry('⭐️☆☆☆' , 'core' , 'basic_window'),
//------------------------------------------------------------------------------------------------
char *jsText = LoadFileText(TextFormat("%s/../common/examples.js", exWebPath));
- char *jsTextUpdated = (char *)RL_CALLOC(REXM_MAX_BUFFER_SIZE, 1); // Updated examples.js copy, 2MB
-
- int jsListStartIndex = TextFindIndex(jsText, "//EXAMPLE_DATA_LIST_START");
- int jsListEndIndex = TextFindIndex(jsText, "//EXAMPLE_DATA_LIST_END");
-
- int jsIndex = 0;
- memcpy(jsTextUpdated, jsText, jsListStartIndex);
- jsIndex = sprintf(jsTextUpdated + jsListStartIndex, "//EXAMPLE_DATA_LIST_START\n");
- jsIndex += sprintf(jsTextUpdated + jsListStartIndex + jsIndex, " var exampleData = [\n");
-
- char starsText[16] = { 0 };
-
- // NOTE: We avoid "others" category
- for (int i = 0; i < REXM_MAX_EXAMPLE_CATEGORIES - 1; i++)
+ if (!jsText)
{
- int exCollectionCount = 0;
- rlExampleInfo *exCollection = LoadExamplesData(exCollectionFilePath, exCategories[i], false, &exCollectionCount);
- for (int x = 0; x < exCollectionCount; x++)
- {
- for (int s = 0; s < 4; s++)
- {
- if (s < exCollection[x].stars) strcpy(starsText + 3*s, "⭐️"); // WARNING: Different than '★', more visual
- else strcpy(starsText + 3*s, "☆");
- }
-
- if ((i == 6) && (x == (exCollectionCount - 1)))
- {
- // NOTE: Last line to add, special case to consider
- jsIndex += sprintf(jsTextUpdated + jsListStartIndex + jsIndex,
- TextFormat(" exampleEntry('%s', '%s', '%s')];\n", starsText, exCollection[x].category, exCollection[x].name + strlen(exCollection[x].category) + 1));
- }
- else
- {
- jsIndex += sprintf(jsTextUpdated + jsListStartIndex + jsIndex,
- TextFormat(" exampleEntry('%s', '%s', '%s'),\n", starsText, exCollection[x].category, exCollection[x].name + strlen(exCollection[x].category) + 1));
- }
- }
-
- UnloadExamplesData(exCollection);
+ LOG("INFO: examples.js not found, skipping web examples list update\n");
}
+ else
+ {
+ int jsListStartIndex = TextFindIndex(jsText, "//EXAMPLE_DATA_LIST_START");
+ int jsListEndIndex = TextFindIndex(jsText, "//EXAMPLE_DATA_LIST_END");
+ if ((jsListStartIndex < 0) || (jsListEndIndex < 0))
+ {
+ LOG("WARNING: examples.js markers not found, skipping update\n");
+ UnloadFileText(jsText);
+ }
+ else
+ {
+ char *jsTextUpdated = (char *)RL_CALLOC(REXM_MAX_BUFFER_SIZE, 1); // Updated examples.js copy, 2MB
+ int jsIndex = 0;
+ memcpy(jsTextUpdated, jsText, jsListStartIndex);
+ jsIndex = sprintf(jsTextUpdated + jsListStartIndex, "//EXAMPLE_DATA_LIST_START\n");
+ jsIndex += sprintf(jsTextUpdated + jsListStartIndex + jsIndex, " var exampleData = [\n");
- // Add the remaining part of the original file
- memcpy(jsTextUpdated + jsListStartIndex + jsIndex, jsText + jsListEndIndex, strlen(jsText) - jsListEndIndex);
+ char starsText[16] = { 0 };
- // Save updated file
- SaveFileText(TextFormat("%s/../common/examples.js", exWebPath), jsTextUpdated);
- UnloadFileText(jsText);
- RL_FREE(jsTextUpdated);
+ // NOTE: We avoid "others" category
+ for (int i = 0; i < REXM_MAX_EXAMPLE_CATEGORIES - 1; i++)
+ {
+ int exCollectionCount = 0;
+ rlExampleInfo *exCollection = LoadExamplesData(exCollectionFilePath, exCategories[i], false, &exCollectionCount);
+ for (int x = 0; x < exCollectionCount; x++)
+ {
+ for (int s = 0; s < 4; s++)
+ {
+ if (s < exCollection[x].stars) strcpy(starsText + 3*s, "⭐️"); // WARNING: Different than '★', more visual
+ else strcpy(starsText + 3*s, "☆");
+ }
+
+ if ((i == 6) && (x == (exCollectionCount - 1)))
+ {
+ // NOTE: Last line to add, special case to consider
+ jsIndex += sprintf(jsTextUpdated + jsListStartIndex + jsIndex,
+ TextFormat(" exampleEntry('%s', '%s', '%s')];\n", starsText, exCollection[x].category, exCollection[x].name + strlen(exCollection[x].category) + 1));
+ }
+ else
+ {
+ jsIndex += sprintf(jsTextUpdated + jsListStartIndex + jsIndex,
+ TextFormat(" exampleEntry('%s', '%s', '%s'),\n", starsText, exCollection[x].category, exCollection[x].name + strlen(exCollection[x].category) + 1));
+ }
+ }
+
+ UnloadExamplesData(exCollection);
+ }
+
+ // Add the remaining part of the original file
+ memcpy(jsTextUpdated + jsListStartIndex + jsIndex, jsText + jsListEndIndex, strlen(jsText) - jsListEndIndex);
+
+ // Save updated file
+ SaveFileText(TextFormat("%s/../common/examples.js", exWebPath), jsTextUpdated);
+ UnloadFileText(jsText);
+ RL_FREE(jsTextUpdated);
+ }
+ }
//------------------------------------------------------------------------------------------------
return result;
@@ -1733,12 +1786,12 @@ static rlExampleInfo *LoadExamplesData(const char *fileName, const char *categor
{
// Basic validation for lines start categories
if ((lines[i][0] != '#') &&
- ((lines[i][0] == 'c') || // core
- (lines[i][0] == 's') || // shapes, shaders
- (lines[i][0] == 't') || // textures, text
- (lines[i][0] == 'm') || // models
- (lines[i][0] == 'a') || // audio
- (lines[i][0] == 'o'))) // others
+ ((lines[i][0] == 'c') || // core
+ (lines[i][0] == 's') || // shapes, shaders
+ (lines[i][0] == 't') || // textures, text
+ (lines[i][0] == 'm') || // models
+ (lines[i][0] == 'a') || // audio
+ (lines[i][0] == 'o'))) // TODO: Get others category?
{
rlExampleInfo info = { 0 };
int result = ParseExampleInfoLine(lines[i], &info);
@@ -1777,110 +1830,6 @@ static void UnloadExamplesData(rlExampleInfo *exInfo)
RL_FREE(exInfo);
}
-/*
-// Find text in existing file
-static int FileTextFind(const char *fileName, const char *find)
-{
- int result = -1;
-
- if (FileExists(fileName))
- {
- char *fileText = LoadFileText(fileName);
- result = TextFindIndex(fileText, find);
- UnloadFileText(fileText);
- }
-
- return result;
-}
-
-// Replace text in an existing file
-static int FileTextReplace(const char *fileName, const char *textLookUp, const char *textReplace)
-{
- int result = 0;
- char *fileText = NULL;
- char *fileTextUpdated = { 0 };
-
- if (FileExists(fileName))
- {
- fileText = LoadFileText(fileName);
- fileTextUpdated = TextReplace(fileText, textLookUp, textReplace);
- result = SaveFileText(fileName, fileTextUpdated);
- MemFree(fileTextUpdated);
- UnloadFileText(fileText);
- }
-
- return result;
-}
-
-// Copy file from one path to another
-// NOTE: If destination path does not exist, it is created!
-static int FileCopy(const char *srcPath, const char *dstPath)
-{
- int result = 0;
- int srcDataSize = 0;
- unsigned char *srcFileData = LoadFileData(srcPath, &srcDataSize);
-
- // Create required paths if they do not exist
- if (!DirectoryExists(GetDirectoryPath(dstPath)))
- result = MakeDirectory(GetDirectoryPath(dstPath));
-
- if (result == 0) // Directory created successfully (or already exists)
- {
- if ((srcFileData != NULL) && (srcDataSize > 0))
- result = SaveFileData(dstPath, srcFileData, srcDataSize);
- }
-
- UnloadFileData(srcFileData);
-
- return result;
-}
-
-// Rename file (if exists)
-// NOTE: Only rename file name required, not full path
-static int FileRename(const char *fileName, const char *fileRename)
-{
- int result = 0;
-
- if (FileExists(fileName))
- {
- result = rename(fileName, fileRename);
- }
- else result = -1;
-
- return result;
-}
-
-// Remove file (if exists)
-static int FileRemove(const char *fileName)
-{
- int result = 0;
-
- if (FileExists(fileName))
- {
- result = remove(fileName);
- }
- else result = -1;
-
- return result;
-}
-
-// Move file from one directory to another
-// NOTE: If dst directories do not exists they are created
-static int FileMove(const char *srcPath, const char *dstPath)
-{
- int result = 0;
-
- if (FileExists(srcPath))
- {
- FileCopy(srcPath, dstPath);
- remove(srcPath);
- }
- else result = -1;
-
- return result;
-}
-*/
-
// Get example info from example file header
// WARNING: Expecting the example to follow raylib_example_template.c
static rlExampleInfo *LoadExampleInfo(const char *exFileName)
@@ -2331,7 +2280,7 @@ static const char *GenerateUUIDv4(void)
// Update source code header and comments metadata
static void UpdateSourceMetadata(const char *exSrcPath, const rlExampleInfo *info)
{
- if (FileExists(exSrcPath) && IsFileExtension(exSrcPath, ".c"))
+ if (FileExists(exSrcPath) && IsFileExtension(exSrcPath, ".c") && (!TextIsEqual(info->category, "others")))
{
// WARNING: Cache a copy of exSrcPath to avoid modifications by TextFormat()
char exSourcePath[512] = { 0 };
@@ -2468,62 +2417,16 @@ static void UpdateWebMetadata(const char *exHtmlPath, const char *exFilePath)
}
}
-/*
-// Get text between two strings
-// NOTE: Using static string to return result, MAX: 1024 bytes
-static char *GetTextBetween(const char *text, const char *begin, const char *end)
+// Check if text string is a list of strings
+static bool TextInList(const char *text, const char **list, int listCount)
{
- #define MAX_TEXT_BETWEEN_SIZE 1024
-
- static char between[MAX_TEXT_BETWEEN_SIZE] = { 0 };
- memset(between, 0, MAX_TEXT_BETWEEN_SIZE);
-
- int beginIndex = TextFindIndex(text, begin);
-
- if (beginIndex > -1)
+ bool result = false;
+
+ for (int i = 0; i < listCount; i++)
{
- int beginLen = strlen(begin);
- int endIndex = TextFindIndex(text + beginIndex + beginLen, end);
-
- if (endIndex > -1)
- {
- endIndex += (beginIndex + beginLen);
- int len = (endIndex - beginIndex - beginLen);
- if (len < (MAX_TEXT_BETWEEN_SIZE - 1)) strncpy(between, text + beginIndex + beginLen, len);
- else strncpy(between, text + beginIndex + beginLen, MAX_TEXT_BETWEEN_SIZE - 1);
- }
- }
-
- return between;
-}
-
-// Replace text between two specific strings
-// WARNING: Returned string must be freed by user
-static char *TextReplaceBetween(const char *text, const char *begin, const char *end, const char *replace)
-{
- char *result = NULL;
- int beginIndex = TextFindIndex(text, begin);
-
- if (beginIndex > -1)
- {
- int beginLen = strlen(begin);
- int endIndex = TextFindIndex(text + beginIndex + beginLen, end);
-
- if (endIndex > -1)
- {
- endIndex += (beginIndex + beginLen);
-
- int textLen = strlen(text);
- int replaceLen = strlen(replace);
- int toreplaceLen = endIndex - beginIndex - beginLen;
- result = (char *)RL_CALLOC(textLen + replaceLen - toreplaceLen + 1, sizeof(char));
-
- strncpy(result, text, beginIndex + beginLen); // Copy first text part
- strncpy(result + beginIndex + beginLen, replace, replaceLen); // Copy replace
- strncpy(result + beginIndex + beginLen + replaceLen, text + endIndex, textLen - endIndex); // Copy end text part
- }
+ if (TextIsEqual(text, list[i])) { result = true; break; }
}
return result;
}
-*/
+
diff --git a/tools/parser/LICENSE b/tools/rlparser/LICENSE
similarity index 100%
rename from tools/parser/LICENSE
rename to tools/rlparser/LICENSE
diff --git a/tools/rlparser/Makefile b/tools/rlparser/Makefile
new file mode 100644
index 000000000..a645f7f41
--- /dev/null
+++ b/tools/rlparser/Makefile
@@ -0,0 +1,118 @@
+EXTENSION?=txt
+FORMAT?=DEFAULT
+.PHONY: all parse clean raylib_api
+
+# Determine PLATFORM_OS
+# 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
+
+# Define default C compiler: CC
+#------------------------------------------------------------------------------------------------
+CC = gcc
+ifeq ($(PLATFORM_OS),OSX)
+ # OSX default compiler
+ CC = clang
+endif
+ifeq ($(PLATFORM_OS),BSD)
+ # FreeBSD, OpenBSD, NetBSD, DragonFly default compiler
+ CC = clang
+endif
+
+# Define default make program: MAKE
+#------------------------------------------------------------------------------------------------
+MAKE ?= make
+ifeq ($(PLATFORM_OS),WINDOWS)
+ MAKE = mingw32-make
+endif
+
+# Define compiler flags: CFLAGS
+#------------------------------------------------------------------------------------------------
+CFLAGS = -Wall -std=c99
+#CFLAGS += -Wextra -Wmissing-prototypes -Wstrict-prototypes
+
+ifeq ($(BUILD_MODE),DEBUG)
+ CFLAGS += -g -D_DEBUG
+else
+ ifeq ($(PLATFORM_OS),OSX)
+ CFLAGS += -O2
+ else
+ CFLAGS += -s -O2
+ endif
+endif
+ifeq ($(PLATFORM_OS),WINDOWS)
+ # NOTE: The resource .rc file contains windows executable icon and properties
+ CFLAGS += rlparser.rc.data
+endif
+
+# Define processes to execute
+#------------------------------------------------------------------------------------------------
+# rlparser compilation
+rlparser: rlparser.c
+ $(CC) rlparser.c -o rlparser $(CFLAGS)
+
+# rlparser execution: [raylib.h] parse, generating some output files
+raylib_api: ../../src/raylib.h rlparser
+ FORMAT=DEFAULT EXTENSION=txt $(MAKE) raylib_api.txt
+ FORMAT=JSON EXTENSION=json $(MAKE) raylib_api.json
+ FORMAT=XML EXTENSION=xml $(MAKE) raylib_api.xml
+ FORMAT=LUA EXTENSION=lua $(MAKE) raylib_api.lua
+
+# rlparser execution: [raylib.h] parse, generating some output files
+raylib_api.$(EXTENSION): ../../src/raylib.h rlparser
+ ./rlparser -i ../../src/raylib.h -o raylib_api.$(EXTENSION) -f $(FORMAT) -d RLAPI
+
+# rlparser execution: [rlgl.h] parse, generating some output files
+rlgl_api.$(EXTENSION): ../../src/rlgl.h rlparser
+ ./rlparser -i ../../src/rlgl.h -o rlgl_api.$(EXTENSION) -f $(FORMAT) -d RLAPI -t "RLGL IMPLEMENTATION"
+
+# rlparser execution: [raymath.h] parse, generating some output files
+raymath_api.$(EXTENSION): ../../src/raymath.h rlparser
+ ./rlparser -i ../../src/raymath.h -o raymath_api.$(EXTENSION) -f $(FORMAT) -d RMAPI
+
+# rlparser execution: [reasings.h] parse, generating some output files
+reasings_api.$(EXTENSION): ../../examples/others/reasings.h rlparser
+ ./rlparser -i ../../examples/others/reasings.h -o reasings_api.$(EXTENSION) -f $(FORMAT) -d EASEDEF
+
+# rlparser execution: [raygui.h] parse, generating some output files
+raygui_api.$(EXTENSION): ../raygui.h rlparser
+ ./rlparser -i ../raygui.h -o raygui_api.$(EXTENSION) -f $(FORMAT) -d RAYGUIAPI -t "RAYGUI IMPLEMENTATION"
+
+# Target to generate required APIs output files
+parse: raylib_api.$(EXTENSION) raymath_api.$(EXTENSION) rlgl_api.$(EXTENSION) raygui_api.$(EXTENSION)
+
+# "make parse" (and therefore "make all") requires
+# raygui.h and reasings_api.h to exist in the correct directory
+# API files for individual headers can be created likeso, provided the relevant header exists:
+# FORMAT=JSON EXTENSION=json make raygui_api.json
+all: rlparser
+ FORMAT=DEFAULT EXTENSION=txt $(MAKE) parse
+ FORMAT=JSON EXTENSION=json $(MAKE) parse
+ FORMAT=XML EXTENSION=xml $(MAKE) parse
+ FORMAT=LUA EXTENSION=lua $(MAKE) parse
+
+# Clean rlparser and generated output files
+clean:
+ rm -f rlparser *.json *.txt *.xml *.lua
diff --git a/tools/parser/README.md b/tools/rlparser/README.md
similarity index 83%
rename from tools/parser/README.md
rename to tools/rlparser/README.md
index 86cdfdd5b..0e4f9b739 100644
--- a/tools/parser/README.md
+++ b/tools/rlparser/README.md
@@ -1,4 +1,4 @@
-# raylib parser
+# rlparser - raylib parser
This parser scans [`raylib.h`](../src/raylib.h) to get information about `defines`, `structs`, `enums` and `functions`.
All data is separated into parts, usually as strings. The following types are used for data:
@@ -8,16 +8,16 @@ All data is separated into parts, usually as strings. The following types are us
- `struct StructInfo`
- `struct EnumInfo`
-Check `raylib_parser.c` for details about those structs.
+Check `rlparser.c` for details about those structs.
## Command Line
```
//////////////////////////////////////////////////////////////////////////////////
// //
-// raylib API parser //
+// rlparser - raylib header API parser //
// //
-// more info and bugs-report: github.com/raysan5/raylib/parser //
+// more info and bugs-report: github.com/raysan5/raylib/tools/rlparser //
// //
// Copyright (c) 2021-2025 Ramon Santamaria (@raysan5) //
// //
@@ -25,7 +25,7 @@ Check `raylib_parser.c` for details about those structs.
USAGE:
- > raylib_parser [--help] [--input ] [--output ] [--format ]
+ > rlparser [--help] [--input ] [--output ] [--format ]
OPTIONS:
@@ -50,19 +50,19 @@ OPTIONS:
EXAMPLES:
- > raylib_parser --input raylib.h --output api.json
+ > rlparser --input raylib.h --output api.json
Process to generate
- > raylib_parser --output raylib_data.info --format XML
+ > rlparser --output raylib_data.info --format XML
Process to generate as XML text data
- > raylib_parser --input raymath.h --output raymath_data.info --format XML --define RMAPI
+ > rlparser --input raymath.h --output raymath_data.info --format XML --define RMAPI
Process to generate as XML text data
```
## Constraints
-This parser is specifically designed to work with raylib.h, so, it has some constraints:
+`rlparser` is specifically designed to work with `raylib.h`, so, it has some constraints:
- Functions are expected as a single line with the following structure:
```
@@ -91,7 +91,7 @@ This parser is specifically designed to work with raylib.h, so, it has some cons
```
_NOTE: For enums, multiple options are supported:_
-
+
- If value is not provided, ( + 1) is assigned
- Value description can be provided or not
@@ -103,5 +103,7 @@ This parser **does not require `` library**, all data is parsed direct
### LICENSE: zlib/libpng
-raylib-parser is licensed under an unmodified zlib/libpng license, which is an OSI-certified, BSD-like license that allows static linking with closed source software. Check [LICENSE](LICENSE) for further details.
+raylib-parser is licensed under an unmodified zlib/libpng license, which is an OSI-certified, BSD-like license that allows static linking with closed source software.
+
+Check [LICENSE](LICENSE) for further details.
diff --git a/tools/parser/output/raylib_api.json b/tools/rlparser/output/raylib_api.json
similarity index 99%
rename from tools/parser/output/raylib_api.json
rename to tools/rlparser/output/raylib_api.json
index 5c641bac3..9714d5d05 100644
--- a/tools/parser/output/raylib_api.json
+++ b/tools/rlparser/output/raylib_api.json
@@ -5592,6 +5592,33 @@
}
]
},
+ {
+ "name": "DrawLineDashed",
+ "description": "Draw a dashed line",
+ "returnType": "void",
+ "params": [
+ {
+ "type": "Vector2",
+ "name": "startPos"
+ },
+ {
+ "type": "Vector2",
+ "name": "endPos"
+ },
+ {
+ "type": "int",
+ "name": "dashSize"
+ },
+ {
+ "type": "int",
+ "name": "spaceSize"
+ },
+ {
+ "type": "Color",
+ "name": "color"
+ }
+ ]
+ },
{
"name": "DrawCircle",
"description": "Draw a color-filled circle",
diff --git a/tools/parser/output/raylib_api.lua b/tools/rlparser/output/raylib_api.lua
similarity index 99%
rename from tools/parser/output/raylib_api.lua
rename to tools/rlparser/output/raylib_api.lua
index ce3671159..75fd06373 100644
--- a/tools/parser/output/raylib_api.lua
+++ b/tools/rlparser/output/raylib_api.lua
@@ -4800,6 +4800,18 @@ return {
{type = "Color", name = "color"}
}
},
+ {
+ name = "DrawLineDashed",
+ description = "Draw a dashed line",
+ returnType = "void",
+ params = {
+ {type = "Vector2", name = "startPos"},
+ {type = "Vector2", name = "endPos"},
+ {type = "int", name = "dashSize"},
+ {type = "int", name = "spaceSize"},
+ {type = "Color", name = "color"}
+ }
+ },
{
name = "DrawCircle",
description = "Draw a color-filled circle",
diff --git a/tools/parser/output/raylib_api.txt b/tools/rlparser/output/raylib_api.txt
similarity index 88%
rename from tools/parser/output/raylib_api.txt
rename to tools/rlparser/output/raylib_api.txt
index 94568b690..849a97a56 100644
--- a/tools/parser/output/raylib_api.txt
+++ b/tools/rlparser/output/raylib_api.txt
@@ -993,7 +993,7 @@ Callback 006: AudioCallback() (2 input parameters)
Param[1]: bufferData (type: void *)
Param[2]: frames (type: unsigned int)
-Functions found: 595
+Functions found: 596
Function 001: InitWindow() (3 input parameters)
Name: InitWindow
@@ -2220,7 +2220,16 @@ Function 225: DrawLineBezier() (4 input parameters)
Param[2]: endPos (type: Vector2)
Param[3]: thick (type: float)
Param[4]: color (type: Color)
-Function 226: DrawCircle() (4 input parameters)
+Function 226: DrawLineDashed() (5 input parameters)
+ Name: DrawLineDashed
+ Return type: void
+ Description: Draw a dashed line
+ Param[1]: startPos (type: Vector2)
+ Param[2]: endPos (type: Vector2)
+ Param[3]: dashSize (type: int)
+ Param[4]: spaceSize (type: int)
+ Param[5]: color (type: Color)
+Function 227: DrawCircle() (4 input parameters)
Name: DrawCircle
Return type: void
Description: Draw a color-filled circle
@@ -2228,7 +2237,7 @@ Function 226: DrawCircle() (4 input parameters)
Param[2]: centerY (type: int)
Param[3]: radius (type: float)
Param[4]: color (type: Color)
-Function 227: DrawCircleSector() (6 input parameters)
+Function 228: DrawCircleSector() (6 input parameters)
Name: DrawCircleSector
Return type: void
Description: Draw a piece of a circle
@@ -2238,7 +2247,7 @@ Function 227: DrawCircleSector() (6 input parameters)
Param[4]: endAngle (type: float)
Param[5]: segments (type: int)
Param[6]: color (type: Color)
-Function 228: DrawCircleSectorLines() (6 input parameters)
+Function 229: DrawCircleSectorLines() (6 input parameters)
Name: DrawCircleSectorLines
Return type: void
Description: Draw circle sector outline
@@ -2248,7 +2257,7 @@ Function 228: DrawCircleSectorLines() (6 input parameters)
Param[4]: endAngle (type: float)
Param[5]: segments (type: int)
Param[6]: color (type: Color)
-Function 229: DrawCircleGradient() (5 input parameters)
+Function 230: DrawCircleGradient() (5 input parameters)
Name: DrawCircleGradient
Return type: void
Description: Draw a gradient-filled circle
@@ -2257,14 +2266,14 @@ Function 229: DrawCircleGradient() (5 input parameters)
Param[3]: radius (type: float)
Param[4]: inner (type: Color)
Param[5]: outer (type: Color)
-Function 230: DrawCircleV() (3 input parameters)
+Function 231: DrawCircleV() (3 input parameters)
Name: DrawCircleV
Return type: void
Description: Draw a color-filled circle (Vector version)
Param[1]: center (type: Vector2)
Param[2]: radius (type: float)
Param[3]: color (type: Color)
-Function 231: DrawCircleLines() (4 input parameters)
+Function 232: DrawCircleLines() (4 input parameters)
Name: DrawCircleLines
Return type: void
Description: Draw circle outline
@@ -2272,14 +2281,14 @@ Function 231: DrawCircleLines() (4 input parameters)
Param[2]: centerY (type: int)
Param[3]: radius (type: float)
Param[4]: color (type: Color)
-Function 232: DrawCircleLinesV() (3 input parameters)
+Function 233: DrawCircleLinesV() (3 input parameters)
Name: DrawCircleLinesV
Return type: void
Description: Draw circle outline (Vector version)
Param[1]: center (type: Vector2)
Param[2]: radius (type: float)
Param[3]: color (type: Color)
-Function 233: DrawEllipse() (5 input parameters)
+Function 234: DrawEllipse() (5 input parameters)
Name: DrawEllipse
Return type: void
Description: Draw ellipse
@@ -2288,7 +2297,7 @@ Function 233: DrawEllipse() (5 input parameters)
Param[3]: radiusH (type: float)
Param[4]: radiusV (type: float)
Param[5]: color (type: Color)
-Function 234: DrawEllipseV() (4 input parameters)
+Function 235: DrawEllipseV() (4 input parameters)
Name: DrawEllipseV
Return type: void
Description: Draw ellipse (Vector version)
@@ -2296,7 +2305,7 @@ Function 234: DrawEllipseV() (4 input parameters)
Param[2]: radiusH (type: float)
Param[3]: radiusV (type: float)
Param[4]: color (type: Color)
-Function 235: DrawEllipseLines() (5 input parameters)
+Function 236: DrawEllipseLines() (5 input parameters)
Name: DrawEllipseLines
Return type: void
Description: Draw ellipse outline
@@ -2305,7 +2314,7 @@ Function 235: DrawEllipseLines() (5 input parameters)
Param[3]: radiusH (type: float)
Param[4]: radiusV (type: float)
Param[5]: color (type: Color)
-Function 236: DrawEllipseLinesV() (4 input parameters)
+Function 237: DrawEllipseLinesV() (4 input parameters)
Name: DrawEllipseLinesV
Return type: void
Description: Draw ellipse outline (Vector version)
@@ -2313,7 +2322,7 @@ Function 236: DrawEllipseLinesV() (4 input parameters)
Param[2]: radiusH (type: float)
Param[3]: radiusV (type: float)
Param[4]: color (type: Color)
-Function 237: DrawRing() (7 input parameters)
+Function 238: DrawRing() (7 input parameters)
Name: DrawRing
Return type: void
Description: Draw ring
@@ -2324,7 +2333,7 @@ Function 237: DrawRing() (7 input parameters)
Param[5]: endAngle (type: float)
Param[6]: segments (type: int)
Param[7]: color (type: Color)
-Function 238: DrawRingLines() (7 input parameters)
+Function 239: DrawRingLines() (7 input parameters)
Name: DrawRingLines
Return type: void
Description: Draw ring outline
@@ -2335,7 +2344,7 @@ Function 238: DrawRingLines() (7 input parameters)
Param[5]: endAngle (type: float)
Param[6]: segments (type: int)
Param[7]: color (type: Color)
-Function 239: DrawRectangle() (5 input parameters)
+Function 240: DrawRectangle() (5 input parameters)
Name: DrawRectangle
Return type: void
Description: Draw a color-filled rectangle
@@ -2344,20 +2353,20 @@ Function 239: DrawRectangle() (5 input parameters)
Param[3]: width (type: int)
Param[4]: height (type: int)
Param[5]: color (type: Color)
-Function 240: DrawRectangleV() (3 input parameters)
+Function 241: DrawRectangleV() (3 input parameters)
Name: DrawRectangleV
Return type: void
Description: Draw a color-filled rectangle (Vector version)
Param[1]: position (type: Vector2)
Param[2]: size (type: Vector2)
Param[3]: color (type: Color)
-Function 241: DrawRectangleRec() (2 input parameters)
+Function 242: DrawRectangleRec() (2 input parameters)
Name: DrawRectangleRec
Return type: void
Description: Draw a color-filled rectangle
Param[1]: rec (type: Rectangle)
Param[2]: color (type: Color)
-Function 242: DrawRectanglePro() (4 input parameters)
+Function 243: DrawRectanglePro() (4 input parameters)
Name: DrawRectanglePro
Return type: void
Description: Draw a color-filled rectangle with pro parameters
@@ -2365,7 +2374,7 @@ Function 242: DrawRectanglePro() (4 input parameters)
Param[2]: origin (type: Vector2)
Param[3]: rotation (type: float)
Param[4]: color (type: Color)
-Function 243: DrawRectangleGradientV() (6 input parameters)
+Function 244: DrawRectangleGradientV() (6 input parameters)
Name: DrawRectangleGradientV
Return type: void
Description: Draw a vertical-gradient-filled rectangle
@@ -2375,7 +2384,7 @@ Function 243: DrawRectangleGradientV() (6 input parameters)
Param[4]: height (type: int)
Param[5]: top (type: Color)
Param[6]: bottom (type: Color)
-Function 244: DrawRectangleGradientH() (6 input parameters)
+Function 245: DrawRectangleGradientH() (6 input parameters)
Name: DrawRectangleGradientH
Return type: void
Description: Draw a horizontal-gradient-filled rectangle
@@ -2385,7 +2394,7 @@ Function 244: DrawRectangleGradientH() (6 input parameters)
Param[4]: height (type: int)
Param[5]: left (type: Color)
Param[6]: right (type: Color)
-Function 245: DrawRectangleGradientEx() (5 input parameters)
+Function 246: DrawRectangleGradientEx() (5 input parameters)
Name: DrawRectangleGradientEx
Return type: void
Description: Draw a gradient-filled rectangle with custom vertex colors
@@ -2394,7 +2403,7 @@ Function 245: DrawRectangleGradientEx() (5 input parameters)
Param[3]: bottomLeft (type: Color)
Param[4]: bottomRight (type: Color)
Param[5]: topRight (type: Color)
-Function 246: DrawRectangleLines() (5 input parameters)
+Function 247: DrawRectangleLines() (5 input parameters)
Name: DrawRectangleLines
Return type: void
Description: Draw rectangle outline
@@ -2403,14 +2412,14 @@ Function 246: DrawRectangleLines() (5 input parameters)
Param[3]: width (type: int)
Param[4]: height (type: int)
Param[5]: color (type: Color)
-Function 247: DrawRectangleLinesEx() (3 input parameters)
+Function 248: DrawRectangleLinesEx() (3 input parameters)
Name: DrawRectangleLinesEx
Return type: void
Description: Draw rectangle outline with extended parameters
Param[1]: rec (type: Rectangle)
Param[2]: lineThick (type: float)
Param[3]: color (type: Color)
-Function 248: DrawRectangleRounded() (4 input parameters)
+Function 249: DrawRectangleRounded() (4 input parameters)
Name: DrawRectangleRounded
Return type: void
Description: Draw rectangle with rounded edges
@@ -2418,7 +2427,7 @@ Function 248: DrawRectangleRounded() (4 input parameters)
Param[2]: roundness (type: float)
Param[3]: segments (type: int)
Param[4]: color (type: Color)
-Function 249: DrawRectangleRoundedLines() (4 input parameters)
+Function 250: DrawRectangleRoundedLines() (4 input parameters)
Name: DrawRectangleRoundedLines
Return type: void
Description: Draw rectangle lines with rounded edges
@@ -2426,7 +2435,7 @@ Function 249: DrawRectangleRoundedLines() (4 input parameters)
Param[2]: roundness (type: float)
Param[3]: segments (type: int)
Param[4]: color (type: Color)
-Function 250: DrawRectangleRoundedLinesEx() (5 input parameters)
+Function 251: DrawRectangleRoundedLinesEx() (5 input parameters)
Name: DrawRectangleRoundedLinesEx
Return type: void
Description: Draw rectangle with rounded edges outline
@@ -2435,7 +2444,7 @@ Function 250: DrawRectangleRoundedLinesEx() (5 input parameters)
Param[3]: segments (type: int)
Param[4]: lineThick (type: float)
Param[5]: color (type: Color)
-Function 251: DrawTriangle() (4 input parameters)
+Function 252: DrawTriangle() (4 input parameters)
Name: DrawTriangle
Return type: void
Description: Draw a color-filled triangle (vertex in counter-clockwise order!)
@@ -2443,7 +2452,7 @@ Function 251: DrawTriangle() (4 input parameters)
Param[2]: v2 (type: Vector2)
Param[3]: v3 (type: Vector2)
Param[4]: color (type: Color)
-Function 252: DrawTriangleLines() (4 input parameters)
+Function 253: DrawTriangleLines() (4 input parameters)
Name: DrawTriangleLines
Return type: void
Description: Draw triangle outline (vertex in counter-clockwise order!)
@@ -2451,21 +2460,21 @@ Function 252: DrawTriangleLines() (4 input parameters)
Param[2]: v2 (type: Vector2)
Param[3]: v3 (type: Vector2)
Param[4]: color (type: Color)
-Function 253: DrawTriangleFan() (3 input parameters)
+Function 254: DrawTriangleFan() (3 input parameters)
Name: DrawTriangleFan
Return type: void
Description: Draw a triangle fan defined by points (first vertex is the center)
Param[1]: points (type: const Vector2 *)
Param[2]: pointCount (type: int)
Param[3]: color (type: Color)
-Function 254: DrawTriangleStrip() (3 input parameters)
+Function 255: DrawTriangleStrip() (3 input parameters)
Name: DrawTriangleStrip
Return type: void
Description: Draw a triangle strip defined by points
Param[1]: points (type: const Vector2 *)
Param[2]: pointCount (type: int)
Param[3]: color (type: Color)
-Function 255: DrawPoly() (5 input parameters)
+Function 256: DrawPoly() (5 input parameters)
Name: DrawPoly
Return type: void
Description: Draw a regular polygon (Vector version)
@@ -2474,7 +2483,7 @@ Function 255: DrawPoly() (5 input parameters)
Param[3]: radius (type: float)
Param[4]: rotation (type: float)
Param[5]: color (type: Color)
-Function 256: DrawPolyLines() (5 input parameters)
+Function 257: DrawPolyLines() (5 input parameters)
Name: DrawPolyLines
Return type: void
Description: Draw a polygon outline of n sides
@@ -2483,7 +2492,7 @@ Function 256: DrawPolyLines() (5 input parameters)
Param[3]: radius (type: float)
Param[4]: rotation (type: float)
Param[5]: color (type: Color)
-Function 257: DrawPolyLinesEx() (6 input parameters)
+Function 258: DrawPolyLinesEx() (6 input parameters)
Name: DrawPolyLinesEx
Return type: void
Description: Draw a polygon outline of n sides with extended parameters
@@ -2493,7 +2502,7 @@ Function 257: DrawPolyLinesEx() (6 input parameters)
Param[4]: rotation (type: float)
Param[5]: lineThick (type: float)
Param[6]: color (type: Color)
-Function 258: DrawSplineLinear() (4 input parameters)
+Function 259: DrawSplineLinear() (4 input parameters)
Name: DrawSplineLinear
Return type: void
Description: Draw spline: Linear, minimum 2 points
@@ -2501,7 +2510,7 @@ Function 258: DrawSplineLinear() (4 input parameters)
Param[2]: pointCount (type: int)
Param[3]: thick (type: float)
Param[4]: color (type: Color)
-Function 259: DrawSplineBasis() (4 input parameters)
+Function 260: DrawSplineBasis() (4 input parameters)
Name: DrawSplineBasis
Return type: void
Description: Draw spline: B-Spline, minimum 4 points
@@ -2509,7 +2518,7 @@ Function 259: DrawSplineBasis() (4 input parameters)
Param[2]: pointCount (type: int)
Param[3]: thick (type: float)
Param[4]: color (type: Color)
-Function 260: DrawSplineCatmullRom() (4 input parameters)
+Function 261: DrawSplineCatmullRom() (4 input parameters)
Name: DrawSplineCatmullRom
Return type: void
Description: Draw spline: Catmull-Rom, minimum 4 points
@@ -2517,7 +2526,7 @@ Function 260: DrawSplineCatmullRom() (4 input parameters)
Param[2]: pointCount (type: int)
Param[3]: thick (type: float)
Param[4]: color (type: Color)
-Function 261: DrawSplineBezierQuadratic() (4 input parameters)
+Function 262: DrawSplineBezierQuadratic() (4 input parameters)
Name: DrawSplineBezierQuadratic
Return type: void
Description: Draw spline: Quadratic Bezier, minimum 3 points (1 control point): [p1, c2, p3, c4...]
@@ -2525,7 +2534,7 @@ Function 261: DrawSplineBezierQuadratic() (4 input parameters)
Param[2]: pointCount (type: int)
Param[3]: thick (type: float)
Param[4]: color (type: Color)
-Function 262: DrawSplineBezierCubic() (4 input parameters)
+Function 263: DrawSplineBezierCubic() (4 input parameters)
Name: DrawSplineBezierCubic
Return type: void
Description: Draw spline: Cubic Bezier, minimum 4 points (2 control points): [p1, c2, c3, p4, c5, c6...]
@@ -2533,7 +2542,7 @@ Function 262: DrawSplineBezierCubic() (4 input parameters)
Param[2]: pointCount (type: int)
Param[3]: thick (type: float)
Param[4]: color (type: Color)
-Function 263: DrawSplineSegmentLinear() (4 input parameters)
+Function 264: DrawSplineSegmentLinear() (4 input parameters)
Name: DrawSplineSegmentLinear
Return type: void
Description: Draw spline segment: Linear, 2 points
@@ -2541,7 +2550,7 @@ Function 263: DrawSplineSegmentLinear() (4 input parameters)
Param[2]: p2 (type: Vector2)
Param[3]: thick (type: float)
Param[4]: color (type: Color)
-Function 264: DrawSplineSegmentBasis() (6 input parameters)
+Function 265: DrawSplineSegmentBasis() (6 input parameters)
Name: DrawSplineSegmentBasis
Return type: void
Description: Draw spline segment: B-Spline, 4 points
@@ -2551,7 +2560,7 @@ Function 264: DrawSplineSegmentBasis() (6 input parameters)
Param[4]: p4 (type: Vector2)
Param[5]: thick (type: float)
Param[6]: color (type: Color)
-Function 265: DrawSplineSegmentCatmullRom() (6 input parameters)
+Function 266: DrawSplineSegmentCatmullRom() (6 input parameters)
Name: DrawSplineSegmentCatmullRom
Return type: void
Description: Draw spline segment: Catmull-Rom, 4 points
@@ -2561,7 +2570,7 @@ Function 265: DrawSplineSegmentCatmullRom() (6 input parameters)
Param[4]: p4 (type: Vector2)
Param[5]: thick (type: float)
Param[6]: color (type: Color)
-Function 266: DrawSplineSegmentBezierQuadratic() (5 input parameters)
+Function 267: DrawSplineSegmentBezierQuadratic() (5 input parameters)
Name: DrawSplineSegmentBezierQuadratic
Return type: void
Description: Draw spline segment: Quadratic Bezier, 2 points, 1 control point
@@ -2570,7 +2579,7 @@ Function 266: DrawSplineSegmentBezierQuadratic() (5 input parameters)
Param[3]: p3 (type: Vector2)
Param[4]: thick (type: float)
Param[5]: color (type: Color)
-Function 267: DrawSplineSegmentBezierCubic() (6 input parameters)
+Function 268: DrawSplineSegmentBezierCubic() (6 input parameters)
Name: DrawSplineSegmentBezierCubic
Return type: void
Description: Draw spline segment: Cubic Bezier, 2 points, 2 control points
@@ -2580,14 +2589,14 @@ Function 267: DrawSplineSegmentBezierCubic() (6 input parameters)
Param[4]: p4 (type: Vector2)
Param[5]: thick (type: float)
Param[6]: color (type: Color)
-Function 268: GetSplinePointLinear() (3 input parameters)
+Function 269: GetSplinePointLinear() (3 input parameters)
Name: GetSplinePointLinear
Return type: Vector2
Description: Get (evaluate) spline point: Linear
Param[1]: startPos (type: Vector2)
Param[2]: endPos (type: Vector2)
Param[3]: t (type: float)
-Function 269: GetSplinePointBasis() (5 input parameters)
+Function 270: GetSplinePointBasis() (5 input parameters)
Name: GetSplinePointBasis
Return type: Vector2
Description: Get (evaluate) spline point: B-Spline
@@ -2596,7 +2605,7 @@ Function 269: GetSplinePointBasis() (5 input parameters)
Param[3]: p3 (type: Vector2)
Param[4]: p4 (type: Vector2)
Param[5]: t (type: float)
-Function 270: GetSplinePointCatmullRom() (5 input parameters)
+Function 271: GetSplinePointCatmullRom() (5 input parameters)
Name: GetSplinePointCatmullRom
Return type: Vector2
Description: Get (evaluate) spline point: Catmull-Rom
@@ -2605,7 +2614,7 @@ Function 270: GetSplinePointCatmullRom() (5 input parameters)
Param[3]: p3 (type: Vector2)
Param[4]: p4 (type: Vector2)
Param[5]: t (type: float)
-Function 271: GetSplinePointBezierQuad() (4 input parameters)
+Function 272: GetSplinePointBezierQuad() (4 input parameters)
Name: GetSplinePointBezierQuad
Return type: Vector2
Description: Get (evaluate) spline point: Quadratic Bezier
@@ -2613,7 +2622,7 @@ Function 271: GetSplinePointBezierQuad() (4 input parameters)
Param[2]: c2 (type: Vector2)
Param[3]: p3 (type: Vector2)
Param[4]: t (type: float)
-Function 272: GetSplinePointBezierCubic() (5 input parameters)
+Function 273: GetSplinePointBezierCubic() (5 input parameters)
Name: GetSplinePointBezierCubic
Return type: Vector2
Description: Get (evaluate) spline point: Cubic Bezier
@@ -2622,13 +2631,13 @@ Function 272: GetSplinePointBezierCubic() (5 input parameters)
Param[3]: c3 (type: Vector2)
Param[4]: p4 (type: Vector2)
Param[5]: t (type: float)
-Function 273: CheckCollisionRecs() (2 input parameters)
+Function 274: CheckCollisionRecs() (2 input parameters)
Name: CheckCollisionRecs
Return type: bool
Description: Check collision between two rectangles
Param[1]: rec1 (type: Rectangle)
Param[2]: rec2 (type: Rectangle)
-Function 274: CheckCollisionCircles() (4 input parameters)
+Function 275: CheckCollisionCircles() (4 input parameters)
Name: CheckCollisionCircles
Return type: bool
Description: Check collision between two circles
@@ -2636,14 +2645,14 @@ Function 274: CheckCollisionCircles() (4 input parameters)
Param[2]: radius1 (type: float)
Param[3]: center2 (type: Vector2)
Param[4]: radius2 (type: float)
-Function 275: CheckCollisionCircleRec() (3 input parameters)
+Function 276: CheckCollisionCircleRec() (3 input parameters)
Name: CheckCollisionCircleRec
Return type: bool
Description: Check collision between circle and rectangle
Param[1]: center (type: Vector2)
Param[2]: radius (type: float)
Param[3]: rec (type: Rectangle)
-Function 276: CheckCollisionCircleLine() (4 input parameters)
+Function 277: CheckCollisionCircleLine() (4 input parameters)
Name: CheckCollisionCircleLine
Return type: bool
Description: Check if circle collides with a line created betweeen two points [p1] and [p2]
@@ -2651,20 +2660,20 @@ Function 276: CheckCollisionCircleLine() (4 input parameters)
Param[2]: radius (type: float)
Param[3]: p1 (type: Vector2)
Param[4]: p2 (type: Vector2)
-Function 277: CheckCollisionPointRec() (2 input parameters)
+Function 278: CheckCollisionPointRec() (2 input parameters)
Name: CheckCollisionPointRec
Return type: bool
Description: Check if point is inside rectangle
Param[1]: point (type: Vector2)
Param[2]: rec (type: Rectangle)
-Function 278: CheckCollisionPointCircle() (3 input parameters)
+Function 279: CheckCollisionPointCircle() (3 input parameters)
Name: CheckCollisionPointCircle
Return type: bool
Description: Check if point is inside circle
Param[1]: point (type: Vector2)
Param[2]: center (type: Vector2)
Param[3]: radius (type: float)
-Function 279: CheckCollisionPointTriangle() (4 input parameters)
+Function 280: CheckCollisionPointTriangle() (4 input parameters)
Name: CheckCollisionPointTriangle
Return type: bool
Description: Check if point is inside a triangle
@@ -2672,7 +2681,7 @@ Function 279: CheckCollisionPointTriangle() (4 input parameters)
Param[2]: p1 (type: Vector2)
Param[3]: p2 (type: Vector2)
Param[4]: p3 (type: Vector2)
-Function 280: CheckCollisionPointLine() (4 input parameters)
+Function 281: CheckCollisionPointLine() (4 input parameters)
Name: CheckCollisionPointLine
Return type: bool
Description: Check if point belongs to line created between two points [p1] and [p2] with defined margin in pixels [threshold]
@@ -2680,14 +2689,14 @@ Function 280: CheckCollisionPointLine() (4 input parameters)
Param[2]: p1 (type: Vector2)
Param[3]: p2 (type: Vector2)
Param[4]: threshold (type: int)
-Function 281: CheckCollisionPointPoly() (3 input parameters)
+Function 282: CheckCollisionPointPoly() (3 input parameters)
Name: CheckCollisionPointPoly
Return type: bool
Description: Check if point is within a polygon described by array of vertices
Param[1]: point (type: Vector2)
Param[2]: points (type: const Vector2 *)
Param[3]: pointCount (type: int)
-Function 282: CheckCollisionLines() (5 input parameters)
+Function 283: CheckCollisionLines() (5 input parameters)
Name: CheckCollisionLines
Return type: bool
Description: Check the collision between two lines defined by two points each, returns collision point by reference
@@ -2696,18 +2705,18 @@ Function 282: CheckCollisionLines() (5 input parameters)
Param[3]: startPos2 (type: Vector2)
Param[4]: endPos2 (type: Vector2)
Param[5]: collisionPoint (type: Vector2 *)
-Function 283: GetCollisionRec() (2 input parameters)
+Function 284: GetCollisionRec() (2 input parameters)
Name: GetCollisionRec
Return type: Rectangle
Description: Get collision rectangle for two rectangles collision
Param[1]: rec1 (type: Rectangle)
Param[2]: rec2 (type: Rectangle)
-Function 284: LoadImage() (1 input parameters)
+Function 285: LoadImage() (1 input parameters)
Name: LoadImage
Return type: Image
Description: Load image from file into CPU memory (RAM)
Param[1]: fileName (type: const char *)
-Function 285: LoadImageRaw() (5 input parameters)
+Function 286: LoadImageRaw() (5 input parameters)
Name: LoadImageRaw
Return type: Image
Description: Load image from RAW file data
@@ -2716,13 +2725,13 @@ Function 285: LoadImageRaw() (5 input parameters)
Param[3]: height (type: int)
Param[4]: format (type: int)
Param[5]: headerSize (type: int)
-Function 286: LoadImageAnim() (2 input parameters)
+Function 287: LoadImageAnim() (2 input parameters)
Name: LoadImageAnim
Return type: Image
Description: Load image sequence from file (frames appended to image.data)
Param[1]: fileName (type: const char *)
Param[2]: frames (type: int *)
-Function 287: LoadImageAnimFromMemory() (4 input parameters)
+Function 288: LoadImageAnimFromMemory() (4 input parameters)
Name: LoadImageAnimFromMemory
Return type: Image
Description: Load image sequence from memory buffer
@@ -2730,60 +2739,60 @@ Function 287: LoadImageAnimFromMemory() (4 input parameters)
Param[2]: fileData (type: const unsigned char *)
Param[3]: dataSize (type: int)
Param[4]: frames (type: int *)
-Function 288: LoadImageFromMemory() (3 input parameters)
+Function 289: LoadImageFromMemory() (3 input parameters)
Name: LoadImageFromMemory
Return type: Image
Description: Load image from memory buffer, fileType refers to extension: i.e. '.png'
Param[1]: fileType (type: const char *)
Param[2]: fileData (type: const unsigned char *)
Param[3]: dataSize (type: int)
-Function 289: LoadImageFromTexture() (1 input parameters)
+Function 290: LoadImageFromTexture() (1 input parameters)
Name: LoadImageFromTexture
Return type: Image
Description: Load image from GPU texture data
Param[1]: texture (type: Texture2D)
-Function 290: LoadImageFromScreen() (0 input parameters)
+Function 291: LoadImageFromScreen() (0 input parameters)
Name: LoadImageFromScreen
Return type: Image
Description: Load image from screen buffer and (screenshot)
No input parameters
-Function 291: IsImageValid() (1 input parameters)
+Function 292: IsImageValid() (1 input parameters)
Name: IsImageValid
Return type: bool
Description: Check if an image is valid (data and parameters)
Param[1]: image (type: Image)
-Function 292: UnloadImage() (1 input parameters)
+Function 293: UnloadImage() (1 input parameters)
Name: UnloadImage
Return type: void
Description: Unload image from CPU memory (RAM)
Param[1]: image (type: Image)
-Function 293: ExportImage() (2 input parameters)
+Function 294: ExportImage() (2 input parameters)
Name: ExportImage
Return type: bool
Description: Export image data to file, returns true on success
Param[1]: image (type: Image)
Param[2]: fileName (type: const char *)
-Function 294: ExportImageToMemory() (3 input parameters)
+Function 295: ExportImageToMemory() (3 input parameters)
Name: ExportImageToMemory
Return type: unsigned char *
Description: Export image to memory buffer
Param[1]: image (type: Image)
Param[2]: fileType (type: const char *)
Param[3]: fileSize (type: int *)
-Function 295: ExportImageAsCode() (2 input parameters)
+Function 296: ExportImageAsCode() (2 input parameters)
Name: ExportImageAsCode
Return type: bool
Description: Export image as code file defining an array of bytes, returns true on success
Param[1]: image (type: Image)
Param[2]: fileName (type: const char *)
-Function 296: GenImageColor() (3 input parameters)
+Function 297: GenImageColor() (3 input parameters)
Name: GenImageColor
Return type: Image
Description: Generate image: plain color
Param[1]: width (type: int)
Param[2]: height (type: int)
Param[3]: color (type: Color)
-Function 297: GenImageGradientLinear() (5 input parameters)
+Function 298: GenImageGradientLinear() (5 input parameters)
Name: GenImageGradientLinear
Return type: Image
Description: Generate image: linear gradient, direction in degrees [0..360], 0=Vertical gradient
@@ -2792,7 +2801,7 @@ Function 297: GenImageGradientLinear() (5 input parameters)
Param[3]: direction (type: int)
Param[4]: start (type: Color)
Param[5]: end (type: Color)
-Function 298: GenImageGradientRadial() (5 input parameters)
+Function 299: GenImageGradientRadial() (5 input parameters)
Name: GenImageGradientRadial
Return type: Image
Description: Generate image: radial gradient
@@ -2801,7 +2810,7 @@ Function 298: GenImageGradientRadial() (5 input parameters)
Param[3]: density (type: float)
Param[4]: inner (type: Color)
Param[5]: outer (type: Color)
-Function 299: GenImageGradientSquare() (5 input parameters)
+Function 300: GenImageGradientSquare() (5 input parameters)
Name: GenImageGradientSquare
Return type: Image
Description: Generate image: square gradient
@@ -2810,7 +2819,7 @@ Function 299: GenImageGradientSquare() (5 input parameters)
Param[3]: density (type: float)
Param[4]: inner (type: Color)
Param[5]: outer (type: Color)
-Function 300: GenImageChecked() (6 input parameters)
+Function 301: GenImageChecked() (6 input parameters)
Name: GenImageChecked
Return type: Image
Description: Generate image: checked
@@ -2820,14 +2829,14 @@ Function 300: GenImageChecked() (6 input parameters)
Param[4]: checksY (type: int)
Param[5]: col1 (type: Color)
Param[6]: col2 (type: Color)
-Function 301: GenImageWhiteNoise() (3 input parameters)
+Function 302: GenImageWhiteNoise() (3 input parameters)
Name: GenImageWhiteNoise
Return type: Image
Description: Generate image: white noise
Param[1]: width (type: int)
Param[2]: height (type: int)
Param[3]: factor (type: float)
-Function 302: GenImagePerlinNoise() (5 input parameters)
+Function 303: GenImagePerlinNoise() (5 input parameters)
Name: GenImagePerlinNoise
Return type: Image
Description: Generate image: perlin noise
@@ -2836,45 +2845,45 @@ Function 302: GenImagePerlinNoise() (5 input parameters)
Param[3]: offsetX (type: int)
Param[4]: offsetY (type: int)
Param[5]: scale (type: float)
-Function 303: GenImageCellular() (3 input parameters)
+Function 304: GenImageCellular() (3 input parameters)
Name: GenImageCellular
Return type: Image
Description: Generate image: cellular algorithm, bigger tileSize means bigger cells
Param[1]: width (type: int)
Param[2]: height (type: int)
Param[3]: tileSize (type: int)
-Function 304: GenImageText() (3 input parameters)
+Function 305: GenImageText() (3 input parameters)
Name: GenImageText
Return type: Image
Description: Generate image: grayscale image from text data
Param[1]: width (type: int)
Param[2]: height (type: int)
Param[3]: text (type: const char *)
-Function 305: ImageCopy() (1 input parameters)
+Function 306: ImageCopy() (1 input parameters)
Name: ImageCopy
Return type: Image
Description: Create an image duplicate (useful for transformations)
Param[1]: image (type: Image)
-Function 306: ImageFromImage() (2 input parameters)
+Function 307: ImageFromImage() (2 input parameters)
Name: ImageFromImage
Return type: Image
Description: Create an image from another image piece
Param[1]: image (type: Image)
Param[2]: rec (type: Rectangle)
-Function 307: ImageFromChannel() (2 input parameters)
+Function 308: ImageFromChannel() (2 input parameters)
Name: ImageFromChannel
Return type: Image
Description: Create an image from a selected channel of another image (GRAYSCALE)
Param[1]: image (type: Image)
Param[2]: selectedChannel (type: int)
-Function 308: ImageText() (3 input parameters)
+Function 309: ImageText() (3 input parameters)
Name: ImageText
Return type: Image
Description: Create an image from text (default font)
Param[1]: text (type: const char *)
Param[2]: fontSize (type: int)
Param[3]: color (type: Color)
-Function 309: ImageTextEx() (5 input parameters)
+Function 310: ImageTextEx() (5 input parameters)
Name: ImageTextEx
Return type: Image
Description: Create an image from text (custom sprite font)
@@ -2883,76 +2892,76 @@ Function 309: ImageTextEx() (5 input parameters)
Param[3]: fontSize (type: float)
Param[4]: spacing (type: float)
Param[5]: tint (type: Color)
-Function 310: ImageFormat() (2 input parameters)
+Function 311: ImageFormat() (2 input parameters)
Name: ImageFormat
Return type: void
Description: Convert image data to desired format
Param[1]: image (type: Image *)
Param[2]: newFormat (type: int)
-Function 311: ImageToPOT() (2 input parameters)
+Function 312: ImageToPOT() (2 input parameters)
Name: ImageToPOT
Return type: void
Description: Convert image to POT (power-of-two)
Param[1]: image (type: Image *)
Param[2]: fill (type: Color)
-Function 312: ImageCrop() (2 input parameters)
+Function 313: ImageCrop() (2 input parameters)
Name: ImageCrop
Return type: void
Description: Crop an image to a defined rectangle
Param[1]: image (type: Image *)
Param[2]: crop (type: Rectangle)
-Function 313: ImageAlphaCrop() (2 input parameters)
+Function 314: ImageAlphaCrop() (2 input parameters)
Name: ImageAlphaCrop
Return type: void
Description: Crop image depending on alpha value
Param[1]: image (type: Image *)
Param[2]: threshold (type: float)
-Function 314: ImageAlphaClear() (3 input parameters)
+Function 315: ImageAlphaClear() (3 input parameters)
Name: ImageAlphaClear
Return type: void
Description: Clear alpha channel to desired color
Param[1]: image (type: Image *)
Param[2]: color (type: Color)
Param[3]: threshold (type: float)
-Function 315: ImageAlphaMask() (2 input parameters)
+Function 316: ImageAlphaMask() (2 input parameters)
Name: ImageAlphaMask
Return type: void
Description: Apply alpha mask to image
Param[1]: image (type: Image *)
Param[2]: alphaMask (type: Image)
-Function 316: ImageAlphaPremultiply() (1 input parameters)
+Function 317: ImageAlphaPremultiply() (1 input parameters)
Name: ImageAlphaPremultiply
Return type: void
Description: Premultiply alpha channel
Param[1]: image (type: Image *)
-Function 317: ImageBlurGaussian() (2 input parameters)
+Function 318: ImageBlurGaussian() (2 input parameters)
Name: ImageBlurGaussian
Return type: void
Description: Apply Gaussian blur using a box blur approximation
Param[1]: image (type: Image *)
Param[2]: blurSize (type: int)
-Function 318: ImageKernelConvolution() (3 input parameters)
+Function 319: ImageKernelConvolution() (3 input parameters)
Name: ImageKernelConvolution
Return type: void
Description: Apply custom square convolution kernel to image
Param[1]: image (type: Image *)
Param[2]: kernel (type: const float *)
Param[3]: kernelSize (type: int)
-Function 319: ImageResize() (3 input parameters)
+Function 320: ImageResize() (3 input parameters)
Name: ImageResize
Return type: void
Description: Resize image (Bicubic scaling algorithm)
Param[1]: image (type: Image *)
Param[2]: newWidth (type: int)
Param[3]: newHeight (type: int)
-Function 320: ImageResizeNN() (3 input parameters)
+Function 321: ImageResizeNN() (3 input parameters)
Name: ImageResizeNN
Return type: void
Description: Resize image (Nearest-Neighbor scaling algorithm)
Param[1]: image (type: Image *)
Param[2]: newWidth (type: int)
Param[3]: newHeight (type: int)
-Function 321: ImageResizeCanvas() (6 input parameters)
+Function 322: ImageResizeCanvas() (6 input parameters)
Name: ImageResizeCanvas
Return type: void
Description: Resize canvas and fill with color
@@ -2962,12 +2971,12 @@ Function 321: ImageResizeCanvas() (6 input parameters)
Param[4]: offsetX (type: int)
Param[5]: offsetY (type: int)
Param[6]: fill (type: Color)
-Function 322: ImageMipmaps() (1 input parameters)
+Function 323: ImageMipmaps() (1 input parameters)
Name: ImageMipmaps
Return type: void
Description: Compute all mipmap levels for a provided image
Param[1]: image (type: Image *)
-Function 323: ImageDither() (5 input parameters)
+Function 324: ImageDither() (5 input parameters)
Name: ImageDither
Return type: void
Description: Dither image data to 16bpp or lower (Floyd-Steinberg dithering)
@@ -2976,109 +2985,109 @@ Function 323: ImageDither() (5 input parameters)
Param[3]: gBpp (type: int)
Param[4]: bBpp (type: int)
Param[5]: aBpp (type: int)
-Function 324: ImageFlipVertical() (1 input parameters)
+Function 325: ImageFlipVertical() (1 input parameters)
Name: ImageFlipVertical
Return type: void
Description: Flip image vertically
Param[1]: image (type: Image *)
-Function 325: ImageFlipHorizontal() (1 input parameters)
+Function 326: ImageFlipHorizontal() (1 input parameters)
Name: ImageFlipHorizontal
Return type: void
Description: Flip image horizontally
Param[1]: image (type: Image *)
-Function 326: ImageRotate() (2 input parameters)
+Function 327: ImageRotate() (2 input parameters)
Name: ImageRotate
Return type: void
Description: Rotate image by input angle in degrees (-359 to 359)
Param[1]: image (type: Image *)
Param[2]: degrees (type: int)
-Function 327: ImageRotateCW() (1 input parameters)
+Function 328: ImageRotateCW() (1 input parameters)
Name: ImageRotateCW
Return type: void
Description: Rotate image clockwise 90deg
Param[1]: image (type: Image *)
-Function 328: ImageRotateCCW() (1 input parameters)
+Function 329: ImageRotateCCW() (1 input parameters)
Name: ImageRotateCCW
Return type: void
Description: Rotate image counter-clockwise 90deg
Param[1]: image (type: Image *)
-Function 329: ImageColorTint() (2 input parameters)
+Function 330: ImageColorTint() (2 input parameters)
Name: ImageColorTint
Return type: void
Description: Modify image color: tint
Param[1]: image (type: Image *)
Param[2]: color (type: Color)
-Function 330: ImageColorInvert() (1 input parameters)
+Function 331: ImageColorInvert() (1 input parameters)
Name: ImageColorInvert
Return type: void
Description: Modify image color: invert
Param[1]: image (type: Image *)
-Function 331: ImageColorGrayscale() (1 input parameters)
+Function 332: ImageColorGrayscale() (1 input parameters)
Name: ImageColorGrayscale
Return type: void
Description: Modify image color: grayscale
Param[1]: image (type: Image *)
-Function 332: ImageColorContrast() (2 input parameters)
+Function 333: ImageColorContrast() (2 input parameters)
Name: ImageColorContrast
Return type: void
Description: Modify image color: contrast (-100 to 100)
Param[1]: image (type: Image *)
Param[2]: contrast (type: float)
-Function 333: ImageColorBrightness() (2 input parameters)
+Function 334: ImageColorBrightness() (2 input parameters)
Name: ImageColorBrightness
Return type: void
Description: Modify image color: brightness (-255 to 255)
Param[1]: image (type: Image *)
Param[2]: brightness (type: int)
-Function 334: ImageColorReplace() (3 input parameters)
+Function 335: ImageColorReplace() (3 input parameters)
Name: ImageColorReplace
Return type: void
Description: Modify image color: replace color
Param[1]: image (type: Image *)
Param[2]: color (type: Color)
Param[3]: replace (type: Color)
-Function 335: LoadImageColors() (1 input parameters)
+Function 336: LoadImageColors() (1 input parameters)
Name: LoadImageColors
Return type: Color *
Description: Load color data from image as a Color array (RGBA - 32bit)
Param[1]: image (type: Image)
-Function 336: LoadImagePalette() (3 input parameters)
+Function 337: LoadImagePalette() (3 input parameters)
Name: LoadImagePalette
Return type: Color *
Description: Load colors palette from image as a Color array (RGBA - 32bit)
Param[1]: image (type: Image)
Param[2]: maxPaletteSize (type: int)
Param[3]: colorCount (type: int *)
-Function 337: UnloadImageColors() (1 input parameters)
+Function 338: UnloadImageColors() (1 input parameters)
Name: UnloadImageColors
Return type: void
Description: Unload color data loaded with LoadImageColors()
Param[1]: colors (type: Color *)
-Function 338: UnloadImagePalette() (1 input parameters)
+Function 339: UnloadImagePalette() (1 input parameters)
Name: UnloadImagePalette
Return type: void
Description: Unload colors palette loaded with LoadImagePalette()
Param[1]: colors (type: Color *)
-Function 339: GetImageAlphaBorder() (2 input parameters)
+Function 340: GetImageAlphaBorder() (2 input parameters)
Name: GetImageAlphaBorder
Return type: Rectangle
Description: Get image alpha border rectangle
Param[1]: image (type: Image)
Param[2]: threshold (type: float)
-Function 340: GetImageColor() (3 input parameters)
+Function 341: GetImageColor() (3 input parameters)
Name: GetImageColor
Return type: Color
Description: Get image pixel color at (x, y) position
Param[1]: image (type: Image)
Param[2]: x (type: int)
Param[3]: y (type: int)
-Function 341: ImageClearBackground() (2 input parameters)
+Function 342: ImageClearBackground() (2 input parameters)
Name: ImageClearBackground
Return type: void
Description: Clear image background with given color
Param[1]: dst (type: Image *)
Param[2]: color (type: Color)
-Function 342: ImageDrawPixel() (4 input parameters)
+Function 343: ImageDrawPixel() (4 input parameters)
Name: ImageDrawPixel
Return type: void
Description: Draw pixel within an image
@@ -3086,14 +3095,14 @@ Function 342: ImageDrawPixel() (4 input parameters)
Param[2]: posX (type: int)
Param[3]: posY (type: int)
Param[4]: color (type: Color)
-Function 343: ImageDrawPixelV() (3 input parameters)
+Function 344: ImageDrawPixelV() (3 input parameters)
Name: ImageDrawPixelV
Return type: void
Description: Draw pixel within an image (Vector version)
Param[1]: dst (type: Image *)
Param[2]: position (type: Vector2)
Param[3]: color (type: Color)
-Function 344: ImageDrawLine() (6 input parameters)
+Function 345: ImageDrawLine() (6 input parameters)
Name: ImageDrawLine
Return type: void
Description: Draw line within an image
@@ -3103,7 +3112,7 @@ Function 344: ImageDrawLine() (6 input parameters)
Param[4]: endPosX (type: int)
Param[5]: endPosY (type: int)
Param[6]: color (type: Color)
-Function 345: ImageDrawLineV() (4 input parameters)
+Function 346: ImageDrawLineV() (4 input parameters)
Name: ImageDrawLineV
Return type: void
Description: Draw line within an image (Vector version)
@@ -3111,7 +3120,7 @@ Function 345: ImageDrawLineV() (4 input parameters)
Param[2]: start (type: Vector2)
Param[3]: end (type: Vector2)
Param[4]: color (type: Color)
-Function 346: ImageDrawLineEx() (5 input parameters)
+Function 347: ImageDrawLineEx() (5 input parameters)
Name: ImageDrawLineEx
Return type: void
Description: Draw a line defining thickness within an image
@@ -3120,7 +3129,7 @@ Function 346: ImageDrawLineEx() (5 input parameters)
Param[3]: end (type: Vector2)
Param[4]: thick (type: int)
Param[5]: color (type: Color)
-Function 347: ImageDrawCircle() (5 input parameters)
+Function 348: ImageDrawCircle() (5 input parameters)
Name: ImageDrawCircle
Return type: void
Description: Draw a filled circle within an image
@@ -3129,7 +3138,7 @@ Function 347: ImageDrawCircle() (5 input parameters)
Param[3]: centerY (type: int)
Param[4]: radius (type: int)
Param[5]: color (type: Color)
-Function 348: ImageDrawCircleV() (4 input parameters)
+Function 349: ImageDrawCircleV() (4 input parameters)
Name: ImageDrawCircleV
Return type: void
Description: Draw a filled circle within an image (Vector version)
@@ -3137,7 +3146,7 @@ Function 348: ImageDrawCircleV() (4 input parameters)
Param[2]: center (type: Vector2)
Param[3]: radius (type: int)
Param[4]: color (type: Color)
-Function 349: ImageDrawCircleLines() (5 input parameters)
+Function 350: ImageDrawCircleLines() (5 input parameters)
Name: ImageDrawCircleLines
Return type: void
Description: Draw circle outline within an image
@@ -3146,7 +3155,7 @@ Function 349: ImageDrawCircleLines() (5 input parameters)
Param[3]: centerY (type: int)
Param[4]: radius (type: int)
Param[5]: color (type: Color)
-Function 350: ImageDrawCircleLinesV() (4 input parameters)
+Function 351: ImageDrawCircleLinesV() (4 input parameters)
Name: ImageDrawCircleLinesV
Return type: void
Description: Draw circle outline within an image (Vector version)
@@ -3154,7 +3163,7 @@ Function 350: ImageDrawCircleLinesV() (4 input parameters)
Param[2]: center (type: Vector2)
Param[3]: radius (type: int)
Param[4]: color (type: Color)
-Function 351: ImageDrawRectangle() (6 input parameters)
+Function 352: ImageDrawRectangle() (6 input parameters)
Name: ImageDrawRectangle
Return type: void
Description: Draw rectangle within an image
@@ -3164,7 +3173,7 @@ Function 351: ImageDrawRectangle() (6 input parameters)
Param[4]: width (type: int)
Param[5]: height (type: int)
Param[6]: color (type: Color)
-Function 352: ImageDrawRectangleV() (4 input parameters)
+Function 353: ImageDrawRectangleV() (4 input parameters)
Name: ImageDrawRectangleV
Return type: void
Description: Draw rectangle within an image (Vector version)
@@ -3172,14 +3181,14 @@ Function 352: ImageDrawRectangleV() (4 input parameters)
Param[2]: position (type: Vector2)
Param[3]: size (type: Vector2)
Param[4]: color (type: Color)
-Function 353: ImageDrawRectangleRec() (3 input parameters)
+Function 354: ImageDrawRectangleRec() (3 input parameters)
Name: ImageDrawRectangleRec
Return type: void
Description: Draw rectangle within an image
Param[1]: dst (type: Image *)
Param[2]: rec (type: Rectangle)
Param[3]: color (type: Color)
-Function 354: ImageDrawRectangleLines() (4 input parameters)
+Function 355: ImageDrawRectangleLines() (4 input parameters)
Name: ImageDrawRectangleLines
Return type: void
Description: Draw rectangle lines within an image
@@ -3187,7 +3196,7 @@ Function 354: ImageDrawRectangleLines() (4 input parameters)
Param[2]: rec (type: Rectangle)
Param[3]: thick (type: int)
Param[4]: color (type: Color)
-Function 355: ImageDrawTriangle() (5 input parameters)
+Function 356: ImageDrawTriangle() (5 input parameters)
Name: ImageDrawTriangle
Return type: void
Description: Draw triangle within an image
@@ -3196,7 +3205,7 @@ Function 355: ImageDrawTriangle() (5 input parameters)
Param[3]: v2 (type: Vector2)
Param[4]: v3 (type: Vector2)
Param[5]: color (type: Color)
-Function 356: ImageDrawTriangleEx() (7 input parameters)
+Function 357: ImageDrawTriangleEx() (7 input parameters)
Name: ImageDrawTriangleEx
Return type: void
Description: Draw triangle with interpolated colors within an image
@@ -3207,7 +3216,7 @@ Function 356: ImageDrawTriangleEx() (7 input parameters)
Param[5]: c1 (type: Color)
Param[6]: c2 (type: Color)
Param[7]: c3 (type: Color)
-Function 357: ImageDrawTriangleLines() (5 input parameters)
+Function 358: ImageDrawTriangleLines() (5 input parameters)
Name: ImageDrawTriangleLines
Return type: void
Description: Draw triangle outline within an image
@@ -3216,7 +3225,7 @@ Function 357: ImageDrawTriangleLines() (5 input parameters)
Param[3]: v2 (type: Vector2)
Param[4]: v3 (type: Vector2)
Param[5]: color (type: Color)
-Function 358: ImageDrawTriangleFan() (4 input parameters)
+Function 359: ImageDrawTriangleFan() (4 input parameters)
Name: ImageDrawTriangleFan
Return type: void
Description: Draw a triangle fan defined by points within an image (first vertex is the center)
@@ -3224,7 +3233,7 @@ Function 358: ImageDrawTriangleFan() (4 input parameters)
Param[2]: points (type: const Vector2 *)
Param[3]: pointCount (type: int)
Param[4]: color (type: Color)
-Function 359: ImageDrawTriangleStrip() (4 input parameters)
+Function 360: ImageDrawTriangleStrip() (4 input parameters)
Name: ImageDrawTriangleStrip
Return type: void
Description: Draw a triangle strip defined by points within an image
@@ -3232,7 +3241,7 @@ Function 359: ImageDrawTriangleStrip() (4 input parameters)
Param[2]: points (type: const Vector2 *)
Param[3]: pointCount (type: int)
Param[4]: color (type: Color)
-Function 360: ImageDraw() (5 input parameters)
+Function 361: ImageDraw() (5 input parameters)
Name: ImageDraw
Return type: void
Description: Draw a source image within a destination image (tint applied to source)
@@ -3241,7 +3250,7 @@ Function 360: ImageDraw() (5 input parameters)
Param[3]: srcRec (type: Rectangle)
Param[4]: dstRec (type: Rectangle)
Param[5]: tint (type: Color)
-Function 361: ImageDrawText() (6 input parameters)
+Function 362: ImageDrawText() (6 input parameters)
Name: ImageDrawText
Return type: void
Description: Draw text (using default font) within an image (destination)
@@ -3251,7 +3260,7 @@ Function 361: ImageDrawText() (6 input parameters)
Param[4]: posY (type: int)
Param[5]: fontSize (type: int)
Param[6]: color (type: Color)
-Function 362: ImageDrawTextEx() (7 input parameters)
+Function 363: ImageDrawTextEx() (7 input parameters)
Name: ImageDrawTextEx
Return type: void
Description: Draw text (custom sprite font) within an image (destination)
@@ -3262,79 +3271,79 @@ Function 362: ImageDrawTextEx() (7 input parameters)
Param[5]: fontSize (type: float)
Param[6]: spacing (type: float)
Param[7]: tint (type: Color)
-Function 363: LoadTexture() (1 input parameters)
+Function 364: LoadTexture() (1 input parameters)
Name: LoadTexture
Return type: Texture2D
Description: Load texture from file into GPU memory (VRAM)
Param[1]: fileName (type: const char *)
-Function 364: LoadTextureFromImage() (1 input parameters)
+Function 365: LoadTextureFromImage() (1 input parameters)
Name: LoadTextureFromImage
Return type: Texture2D
Description: Load texture from image data
Param[1]: image (type: Image)
-Function 365: LoadTextureCubemap() (2 input parameters)
+Function 366: LoadTextureCubemap() (2 input parameters)
Name: LoadTextureCubemap
Return type: TextureCubemap
Description: Load cubemap from image, multiple image cubemap layouts supported
Param[1]: image (type: Image)
Param[2]: layout (type: int)
-Function 366: LoadRenderTexture() (2 input parameters)
+Function 367: LoadRenderTexture() (2 input parameters)
Name: LoadRenderTexture
Return type: RenderTexture2D
Description: Load texture for rendering (framebuffer)
Param[1]: width (type: int)
Param[2]: height (type: int)
-Function 367: IsTextureValid() (1 input parameters)
+Function 368: IsTextureValid() (1 input parameters)
Name: IsTextureValid
Return type: bool
Description: Check if a texture is valid (loaded in GPU)
Param[1]: texture (type: Texture2D)
-Function 368: UnloadTexture() (1 input parameters)
+Function 369: UnloadTexture() (1 input parameters)
Name: UnloadTexture
Return type: void
Description: Unload texture from GPU memory (VRAM)
Param[1]: texture (type: Texture2D)
-Function 369: IsRenderTextureValid() (1 input parameters)
+Function 370: IsRenderTextureValid() (1 input parameters)
Name: IsRenderTextureValid
Return type: bool
Description: Check if a render texture is valid (loaded in GPU)
Param[1]: target (type: RenderTexture2D)
-Function 370: UnloadRenderTexture() (1 input parameters)
+Function 371: UnloadRenderTexture() (1 input parameters)
Name: UnloadRenderTexture
Return type: void
Description: Unload render texture from GPU memory (VRAM)
Param[1]: target (type: RenderTexture2D)
-Function 371: UpdateTexture() (2 input parameters)
+Function 372: UpdateTexture() (2 input parameters)
Name: UpdateTexture
Return type: void
Description: Update GPU texture with new data (pixels should be able to fill texture)
Param[1]: texture (type: Texture2D)
Param[2]: pixels (type: const void *)
-Function 372: UpdateTextureRec() (3 input parameters)
+Function 373: UpdateTextureRec() (3 input parameters)
Name: UpdateTextureRec
Return type: void
Description: Update GPU texture rectangle with new data (pixels and rec should fit in texture)
Param[1]: texture (type: Texture2D)
Param[2]: rec (type: Rectangle)
Param[3]: pixels (type: const void *)
-Function 373: GenTextureMipmaps() (1 input parameters)
+Function 374: GenTextureMipmaps() (1 input parameters)
Name: GenTextureMipmaps
Return type: void
Description: Generate GPU mipmaps for a texture
Param[1]: texture (type: Texture2D *)
-Function 374: SetTextureFilter() (2 input parameters)
+Function 375: SetTextureFilter() (2 input parameters)
Name: SetTextureFilter
Return type: void
Description: Set texture scaling filter mode
Param[1]: texture (type: Texture2D)
Param[2]: filter (type: int)
-Function 375: SetTextureWrap() (2 input parameters)
+Function 376: SetTextureWrap() (2 input parameters)
Name: SetTextureWrap
Return type: void
Description: Set texture wrapping mode
Param[1]: texture (type: Texture2D)
Param[2]: wrap (type: int)
-Function 376: DrawTexture() (4 input parameters)
+Function 377: DrawTexture() (4 input parameters)
Name: DrawTexture
Return type: void
Description: Draw a Texture2D
@@ -3342,14 +3351,14 @@ Function 376: DrawTexture() (4 input parameters)
Param[2]: posX (type: int)
Param[3]: posY (type: int)
Param[4]: tint (type: Color)
-Function 377: DrawTextureV() (3 input parameters)
+Function 378: DrawTextureV() (3 input parameters)
Name: DrawTextureV
Return type: void
Description: Draw a Texture2D with position defined as Vector2
Param[1]: texture (type: Texture2D)
Param[2]: position (type: Vector2)
Param[3]: tint (type: Color)
-Function 378: DrawTextureEx() (5 input parameters)
+Function 379: DrawTextureEx() (5 input parameters)
Name: DrawTextureEx
Return type: void
Description: Draw a Texture2D with extended parameters
@@ -3358,7 +3367,7 @@ Function 378: DrawTextureEx() (5 input parameters)
Param[3]: rotation (type: float)
Param[4]: scale (type: float)
Param[5]: tint (type: Color)
-Function 379: DrawTextureRec() (4 input parameters)
+Function 380: DrawTextureRec() (4 input parameters)
Name: DrawTextureRec
Return type: void
Description: Draw a part of a texture defined by a rectangle
@@ -3366,7 +3375,7 @@ Function 379: DrawTextureRec() (4 input parameters)
Param[2]: source (type: Rectangle)
Param[3]: position (type: Vector2)
Param[4]: tint (type: Color)
-Function 380: DrawTexturePro() (6 input parameters)
+Function 381: DrawTexturePro() (6 input parameters)
Name: DrawTexturePro
Return type: void
Description: Draw a part of a texture defined by a rectangle with 'pro' parameters
@@ -3376,7 +3385,7 @@ Function 380: DrawTexturePro() (6 input parameters)
Param[4]: origin (type: Vector2)
Param[5]: rotation (type: float)
Param[6]: tint (type: Color)
-Function 381: DrawTextureNPatch() (6 input parameters)
+Function 382: DrawTextureNPatch() (6 input parameters)
Name: DrawTextureNPatch
Return type: void
Description: Draws a texture (or part of it) that stretches or shrinks nicely
@@ -3386,119 +3395,119 @@ Function 381: DrawTextureNPatch() (6 input parameters)
Param[4]: origin (type: Vector2)
Param[5]: rotation (type: float)
Param[6]: tint (type: Color)
-Function 382: ColorIsEqual() (2 input parameters)
+Function 383: ColorIsEqual() (2 input parameters)
Name: ColorIsEqual
Return type: bool
Description: Check if two colors are equal
Param[1]: col1 (type: Color)
Param[2]: col2 (type: Color)
-Function 383: Fade() (2 input parameters)
+Function 384: Fade() (2 input parameters)
Name: Fade
Return type: Color
Description: Get color with alpha applied, alpha goes from 0.0f to 1.0f
Param[1]: color (type: Color)
Param[2]: alpha (type: float)
-Function 384: ColorToInt() (1 input parameters)
+Function 385: ColorToInt() (1 input parameters)
Name: ColorToInt
Return type: int
Description: Get hexadecimal value for a Color (0xRRGGBBAA)
Param[1]: color (type: Color)
-Function 385: ColorNormalize() (1 input parameters)
+Function 386: ColorNormalize() (1 input parameters)
Name: ColorNormalize
Return type: Vector4
Description: Get Color normalized as float [0..1]
Param[1]: color (type: Color)
-Function 386: ColorFromNormalized() (1 input parameters)
+Function 387: ColorFromNormalized() (1 input parameters)
Name: ColorFromNormalized
Return type: Color
Description: Get Color from normalized values [0..1]
Param[1]: normalized (type: Vector4)
-Function 387: ColorToHSV() (1 input parameters)
+Function 388: ColorToHSV() (1 input parameters)
Name: ColorToHSV
Return type: Vector3
Description: Get HSV values for a Color, hue [0..360], saturation/value [0..1]
Param[1]: color (type: Color)
-Function 388: ColorFromHSV() (3 input parameters)
+Function 389: ColorFromHSV() (3 input parameters)
Name: ColorFromHSV
Return type: Color
Description: Get a Color from HSV values, hue [0..360], saturation/value [0..1]
Param[1]: hue (type: float)
Param[2]: saturation (type: float)
Param[3]: value (type: float)
-Function 389: ColorTint() (2 input parameters)
+Function 390: ColorTint() (2 input parameters)
Name: ColorTint
Return type: Color
Description: Get color multiplied with another color
Param[1]: color (type: Color)
Param[2]: tint (type: Color)
-Function 390: ColorBrightness() (2 input parameters)
+Function 391: ColorBrightness() (2 input parameters)
Name: ColorBrightness
Return type: Color
Description: Get color with brightness correction, brightness factor goes from -1.0f to 1.0f
Param[1]: color (type: Color)
Param[2]: factor (type: float)
-Function 391: ColorContrast() (2 input parameters)
+Function 392: ColorContrast() (2 input parameters)
Name: ColorContrast
Return type: Color
Description: Get color with contrast correction, contrast values between -1.0f and 1.0f
Param[1]: color (type: Color)
Param[2]: contrast (type: float)
-Function 392: ColorAlpha() (2 input parameters)
+Function 393: ColorAlpha() (2 input parameters)
Name: ColorAlpha
Return type: Color
Description: Get color with alpha applied, alpha goes from 0.0f to 1.0f
Param[1]: color (type: Color)
Param[2]: alpha (type: float)
-Function 393: ColorAlphaBlend() (3 input parameters)
+Function 394: ColorAlphaBlend() (3 input parameters)
Name: ColorAlphaBlend
Return type: Color
Description: Get src alpha-blended into dst color with tint
Param[1]: dst (type: Color)
Param[2]: src (type: Color)
Param[3]: tint (type: Color)
-Function 394: ColorLerp() (3 input parameters)
+Function 395: ColorLerp() (3 input parameters)
Name: ColorLerp
Return type: Color
Description: Get color lerp interpolation between two colors, factor [0.0f..1.0f]
Param[1]: color1 (type: Color)
Param[2]: color2 (type: Color)
Param[3]: factor (type: float)
-Function 395: GetColor() (1 input parameters)
+Function 396: GetColor() (1 input parameters)
Name: GetColor
Return type: Color
Description: Get Color structure from hexadecimal value
Param[1]: hexValue (type: unsigned int)
-Function 396: GetPixelColor() (2 input parameters)
+Function 397: GetPixelColor() (2 input parameters)
Name: GetPixelColor
Return type: Color
Description: Get Color from a source pixel pointer of certain format
Param[1]: srcPtr (type: void *)
Param[2]: format (type: int)
-Function 397: SetPixelColor() (3 input parameters)
+Function 398: SetPixelColor() (3 input parameters)
Name: SetPixelColor
Return type: void
Description: Set color formatted into destination pixel pointer
Param[1]: dstPtr (type: void *)
Param[2]: color (type: Color)
Param[3]: format (type: int)
-Function 398: GetPixelDataSize() (3 input parameters)
+Function 399: GetPixelDataSize() (3 input parameters)
Name: GetPixelDataSize
Return type: int
Description: Get pixel data size in bytes for certain format
Param[1]: width (type: int)
Param[2]: height (type: int)
Param[3]: format (type: int)
-Function 399: GetFontDefault() (0 input parameters)
+Function 400: GetFontDefault() (0 input parameters)
Name: GetFontDefault
Return type: Font
Description: Get the default Font
No input parameters
-Function 400: LoadFont() (1 input parameters)
+Function 401: LoadFont() (1 input parameters)
Name: LoadFont
Return type: Font
Description: Load font from file into GPU memory (VRAM)
Param[1]: fileName (type: const char *)
-Function 401: LoadFontEx() (4 input parameters)
+Function 402: LoadFontEx() (4 input parameters)
Name: LoadFontEx
Return type: Font
Description: Load font from file with extended parameters, use NULL for codepoints and 0 for codepointCount to load the default character set, font size is provided in pixels height
@@ -3506,14 +3515,14 @@ Function 401: LoadFontEx() (4 input parameters)
Param[2]: fontSize (type: int)
Param[3]: codepoints (type: const int *)
Param[4]: codepointCount (type: int)
-Function 402: LoadFontFromImage() (3 input parameters)
+Function 403: LoadFontFromImage() (3 input parameters)
Name: LoadFontFromImage
Return type: Font
Description: Load font from Image (XNA style)
Param[1]: image (type: Image)
Param[2]: key (type: Color)
Param[3]: firstChar (type: int)
-Function 403: LoadFontFromMemory() (6 input parameters)
+Function 404: LoadFontFromMemory() (6 input parameters)
Name: LoadFontFromMemory
Return type: Font
Description: Load font from memory buffer, fileType refers to extension: i.e. '.ttf'
@@ -3523,12 +3532,12 @@ Function 403: LoadFontFromMemory() (6 input parameters)
Param[4]: fontSize (type: int)
Param[5]: codepoints (type: const int *)
Param[6]: codepointCount (type: int)
-Function 404: IsFontValid() (1 input parameters)
+Function 405: IsFontValid() (1 input parameters)
Name: IsFontValid
Return type: bool
Description: Check if a font is valid (font data loaded, WARNING: GPU texture not checked)
Param[1]: font (type: Font)
-Function 405: LoadFontData() (7 input parameters)
+Function 406: LoadFontData() (7 input parameters)
Name: LoadFontData
Return type: GlyphInfo *
Description: Load font data for further use
@@ -3539,7 +3548,7 @@ Function 405: LoadFontData() (7 input parameters)
Param[5]: codepointCount (type: int)
Param[6]: type (type: int)
Param[7]: glyphCount (type: int *)
-Function 406: GenImageFontAtlas() (6 input parameters)
+Function 407: GenImageFontAtlas() (6 input parameters)
Name: GenImageFontAtlas
Return type: Image
Description: Generate image font atlas using chars info
@@ -3549,30 +3558,30 @@ Function 406: GenImageFontAtlas() (6 input parameters)
Param[4]: fontSize (type: int)
Param[5]: padding (type: int)
Param[6]: packMethod (type: int)
-Function 407: UnloadFontData() (2 input parameters)
+Function 408: UnloadFontData() (2 input parameters)
Name: UnloadFontData
Return type: void
Description: Unload font chars info data (RAM)
Param[1]: glyphs (type: GlyphInfo *)
Param[2]: glyphCount (type: int)
-Function 408: UnloadFont() (1 input parameters)
+Function 409: UnloadFont() (1 input parameters)
Name: UnloadFont
Return type: void
Description: Unload font from GPU memory (VRAM)
Param[1]: font (type: Font)
-Function 409: ExportFontAsCode() (2 input parameters)
+Function 410: ExportFontAsCode() (2 input parameters)
Name: ExportFontAsCode
Return type: bool
Description: Export font as code file, returns true on success
Param[1]: font (type: Font)
Param[2]: fileName (type: const char *)
-Function 410: DrawFPS() (2 input parameters)
+Function 411: DrawFPS() (2 input parameters)
Name: DrawFPS
Return type: void
Description: Draw current FPS
Param[1]: posX (type: int)
Param[2]: posY (type: int)
-Function 411: DrawText() (5 input parameters)
+Function 412: DrawText() (5 input parameters)
Name: DrawText
Return type: void
Description: Draw text (using default font)
@@ -3581,7 +3590,7 @@ Function 411: DrawText() (5 input parameters)
Param[3]: posY (type: int)
Param[4]: fontSize (type: int)
Param[5]: color (type: Color)
-Function 412: DrawTextEx() (6 input parameters)
+Function 413: DrawTextEx() (6 input parameters)
Name: DrawTextEx
Return type: void
Description: Draw text using font and additional parameters
@@ -3591,7 +3600,7 @@ Function 412: DrawTextEx() (6 input parameters)
Param[4]: fontSize (type: float)
Param[5]: spacing (type: float)
Param[6]: tint (type: Color)
-Function 413: DrawTextPro() (8 input parameters)
+Function 414: DrawTextPro() (8 input parameters)
Name: DrawTextPro
Return type: void
Description: Draw text using Font and pro parameters (rotation)
@@ -3603,7 +3612,7 @@ Function 413: DrawTextPro() (8 input parameters)
Param[6]: fontSize (type: float)
Param[7]: spacing (type: float)
Param[8]: tint (type: Color)
-Function 414: DrawTextCodepoint() (5 input parameters)
+Function 415: DrawTextCodepoint() (5 input parameters)
Name: DrawTextCodepoint
Return type: void
Description: Draw one character (codepoint)
@@ -3612,7 +3621,7 @@ Function 414: DrawTextCodepoint() (5 input parameters)
Param[3]: position (type: Vector2)
Param[4]: fontSize (type: float)
Param[5]: tint (type: Color)
-Function 415: DrawTextCodepoints() (7 input parameters)
+Function 416: DrawTextCodepoints() (7 input parameters)
Name: DrawTextCodepoints
Return type: void
Description: Draw multiple character (codepoint)
@@ -3623,18 +3632,18 @@ Function 415: DrawTextCodepoints() (7 input parameters)
Param[5]: fontSize (type: float)
Param[6]: spacing (type: float)
Param[7]: tint (type: Color)
-Function 416: SetTextLineSpacing() (1 input parameters)
+Function 417: SetTextLineSpacing() (1 input parameters)
Name: SetTextLineSpacing
Return type: void
Description: Set vertical line spacing when drawing with line-breaks
Param[1]: spacing (type: int)
-Function 417: MeasureText() (2 input parameters)
+Function 418: MeasureText() (2 input parameters)
Name: MeasureText
Return type: int
Description: Measure string width for default font
Param[1]: text (type: const char *)
Param[2]: fontSize (type: int)
-Function 418: MeasureTextEx() (4 input parameters)
+Function 419: MeasureTextEx() (4 input parameters)
Name: MeasureTextEx
Return type: Vector2
Description: Measure string size for Font
@@ -3642,137 +3651,137 @@ Function 418: MeasureTextEx() (4 input parameters)
Param[2]: text (type: const char *)
Param[3]: fontSize (type: float)
Param[4]: spacing (type: float)
-Function 419: GetGlyphIndex() (2 input parameters)
+Function 420: GetGlyphIndex() (2 input parameters)
Name: GetGlyphIndex
Return type: int
Description: Get glyph index position in font for a codepoint (unicode character), fallback to '?' if not found
Param[1]: font (type: Font)
Param[2]: codepoint (type: int)
-Function 420: GetGlyphInfo() (2 input parameters)
+Function 421: GetGlyphInfo() (2 input parameters)
Name: GetGlyphInfo
Return type: GlyphInfo
Description: Get glyph font info data for a codepoint (unicode character), fallback to '?' if not found
Param[1]: font (type: Font)
Param[2]: codepoint (type: int)
-Function 421: GetGlyphAtlasRec() (2 input parameters)
+Function 422: GetGlyphAtlasRec() (2 input parameters)
Name: GetGlyphAtlasRec
Return type: Rectangle
Description: Get glyph rectangle in font atlas for a codepoint (unicode character), fallback to '?' if not found
Param[1]: font (type: Font)
Param[2]: codepoint (type: int)
-Function 422: LoadUTF8() (2 input parameters)
+Function 423: LoadUTF8() (2 input parameters)
Name: LoadUTF8
Return type: char *
Description: Load UTF-8 text encoded from codepoints array
Param[1]: codepoints (type: const int *)
Param[2]: length (type: int)
-Function 423: UnloadUTF8() (1 input parameters)
+Function 424: UnloadUTF8() (1 input parameters)
Name: UnloadUTF8
Return type: void
Description: Unload UTF-8 text encoded from codepoints array
Param[1]: text (type: char *)
-Function 424: LoadCodepoints() (2 input parameters)
+Function 425: LoadCodepoints() (2 input parameters)
Name: LoadCodepoints
Return type: int *
Description: Load all codepoints from a UTF-8 text string, codepoints count returned by parameter
Param[1]: text (type: const char *)
Param[2]: count (type: int *)
-Function 425: UnloadCodepoints() (1 input parameters)
+Function 426: UnloadCodepoints() (1 input parameters)
Name: UnloadCodepoints
Return type: void
Description: Unload codepoints data from memory
Param[1]: codepoints (type: int *)
-Function 426: GetCodepointCount() (1 input parameters)
+Function 427: GetCodepointCount() (1 input parameters)
Name: GetCodepointCount
Return type: int
Description: Get total number of codepoints in a UTF-8 encoded string
Param[1]: text (type: const char *)
-Function 427: GetCodepoint() (2 input parameters)
+Function 428: GetCodepoint() (2 input parameters)
Name: GetCodepoint
Return type: int
Description: Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure
Param[1]: text (type: const char *)
Param[2]: codepointSize (type: int *)
-Function 428: GetCodepointNext() (2 input parameters)
+Function 429: GetCodepointNext() (2 input parameters)
Name: GetCodepointNext
Return type: int
Description: Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure
Param[1]: text (type: const char *)
Param[2]: codepointSize (type: int *)
-Function 429: GetCodepointPrevious() (2 input parameters)
+Function 430: GetCodepointPrevious() (2 input parameters)
Name: GetCodepointPrevious
Return type: int
Description: Get previous codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure
Param[1]: text (type: const char *)
Param[2]: codepointSize (type: int *)
-Function 430: CodepointToUTF8() (2 input parameters)
+Function 431: CodepointToUTF8() (2 input parameters)
Name: CodepointToUTF8
Return type: const char *
Description: Encode one codepoint into UTF-8 byte array (array length returned as parameter)
Param[1]: codepoint (type: int)
Param[2]: utf8Size (type: int *)
-Function 431: LoadTextLines() (2 input parameters)
+Function 432: LoadTextLines() (2 input parameters)
Name: LoadTextLines
Return type: char **
Description: Load text as separate lines ('\n')
Param[1]: text (type: const char *)
Param[2]: count (type: int *)
-Function 432: UnloadTextLines() (2 input parameters)
+Function 433: UnloadTextLines() (2 input parameters)
Name: UnloadTextLines
Return type: void
Description: Unload text lines
Param[1]: text (type: char **)
Param[2]: lineCount (type: int)
-Function 433: TextCopy() (2 input parameters)
+Function 434: TextCopy() (2 input parameters)
Name: TextCopy
Return type: int
Description: Copy one string to another, returns bytes copied
Param[1]: dst (type: char *)
Param[2]: src (type: const char *)
-Function 434: TextIsEqual() (2 input parameters)
+Function 435: TextIsEqual() (2 input parameters)
Name: TextIsEqual
Return type: bool
Description: Check if two text string are equal
Param[1]: text1 (type: const char *)
Param[2]: text2 (type: const char *)
-Function 435: TextLength() (1 input parameters)
+Function 436: TextLength() (1 input parameters)
Name: TextLength
Return type: unsigned int
Description: Get text length, checks for '\0' ending
Param[1]: text (type: const char *)
-Function 436: TextFormat() (2 input parameters)
+Function 437: TextFormat() (2 input parameters)
Name: TextFormat
Return type: const char *
Description: Text formatting with variables (sprintf() style)
Param[1]: text (type: const char *)
Param[2]: args (type: ...)
-Function 437: TextSubtext() (3 input parameters)
+Function 438: TextSubtext() (3 input parameters)
Name: TextSubtext
Return type: const char *
Description: Get a piece of a text string
Param[1]: text (type: const char *)
Param[2]: position (type: int)
Param[3]: length (type: int)
-Function 438: TextRemoveSpaces() (1 input parameters)
+Function 439: TextRemoveSpaces() (1 input parameters)
Name: TextRemoveSpaces
Return type: const char *
Description: Remove text spaces, concat words
Param[1]: text (type: const char *)
-Function 439: GetTextBetween() (3 input parameters)
+Function 440: GetTextBetween() (3 input parameters)
Name: GetTextBetween
Return type: char *
Description: Get text between two strings
Param[1]: text (type: const char *)
Param[2]: begin (type: const char *)
Param[3]: end (type: const char *)
-Function 440: TextReplace() (3 input parameters)
+Function 441: TextReplace() (3 input parameters)
Name: TextReplace
Return type: char *
Description: Replace text string (WARNING: memory must be freed!)
Param[1]: text (type: const char *)
Param[2]: search (type: const char *)
Param[3]: replacement (type: const char *)
-Function 441: TextReplaceBetween() (4 input parameters)
+Function 442: TextReplaceBetween() (4 input parameters)
Name: TextReplaceBetween
Return type: char *
Description: Replace text between two specific strings (WARNING: memory must be freed!)
@@ -3780,89 +3789,89 @@ Function 441: TextReplaceBetween() (4 input parameters)
Param[2]: begin (type: const char *)
Param[3]: end (type: const char *)
Param[4]: replacement (type: const char *)
-Function 442: TextInsert() (3 input parameters)
+Function 443: TextInsert() (3 input parameters)
Name: TextInsert
Return type: char *
Description: Insert text in a position (WARNING: memory must be freed!)
Param[1]: text (type: const char *)
Param[2]: insert (type: const char *)
Param[3]: position (type: int)
-Function 443: TextJoin() (3 input parameters)
+Function 444: TextJoin() (3 input parameters)
Name: TextJoin
Return type: char *
Description: Join text strings with delimiter
Param[1]: textList (type: char **)
Param[2]: count (type: int)
Param[3]: delimiter (type: const char *)
-Function 444: TextSplit() (3 input parameters)
+Function 445: TextSplit() (3 input parameters)
Name: TextSplit
Return type: char **
Description: Split text into multiple strings, using MAX_TEXTSPLIT_COUNT static strings
Param[1]: text (type: const char *)
Param[2]: delimiter (type: char)
Param[3]: count (type: int *)
-Function 445: TextAppend() (3 input parameters)
+Function 446: TextAppend() (3 input parameters)
Name: TextAppend
Return type: void
Description: Append text at specific position and move cursor
Param[1]: text (type: char *)
Param[2]: append (type: const char *)
Param[3]: position (type: int *)
-Function 446: TextFindIndex() (2 input parameters)
+Function 447: TextFindIndex() (2 input parameters)
Name: TextFindIndex
Return type: int
Description: Find first text occurrence within a string, -1 if not found
Param[1]: text (type: const char *)
Param[2]: search (type: const char *)
-Function 447: TextToUpper() (1 input parameters)
+Function 448: TextToUpper() (1 input parameters)
Name: TextToUpper
Return type: char *
Description: Get upper case version of provided string
Param[1]: text (type: const char *)
-Function 448: TextToLower() (1 input parameters)
+Function 449: TextToLower() (1 input parameters)
Name: TextToLower
Return type: char *
Description: Get lower case version of provided string
Param[1]: text (type: const char *)
-Function 449: TextToPascal() (1 input parameters)
+Function 450: TextToPascal() (1 input parameters)
Name: TextToPascal
Return type: char *
Description: Get Pascal case notation version of provided string
Param[1]: text (type: const char *)
-Function 450: TextToSnake() (1 input parameters)
+Function 451: TextToSnake() (1 input parameters)
Name: TextToSnake
Return type: char *
Description: Get Snake case notation version of provided string
Param[1]: text (type: const char *)
-Function 451: TextToCamel() (1 input parameters)
+Function 452: TextToCamel() (1 input parameters)
Name: TextToCamel
Return type: char *
Description: Get Camel case notation version of provided string
Param[1]: text (type: const char *)
-Function 452: TextToInteger() (1 input parameters)
+Function 453: TextToInteger() (1 input parameters)
Name: TextToInteger
Return type: int
Description: Get integer value from text
Param[1]: text (type: const char *)
-Function 453: TextToFloat() (1 input parameters)
+Function 454: TextToFloat() (1 input parameters)
Name: TextToFloat
Return type: float
Description: Get float value from text
Param[1]: text (type: const char *)
-Function 454: DrawLine3D() (3 input parameters)
+Function 455: DrawLine3D() (3 input parameters)
Name: DrawLine3D
Return type: void
Description: Draw a line in 3D world space
Param[1]: startPos (type: Vector3)
Param[2]: endPos (type: Vector3)
Param[3]: color (type: Color)
-Function 455: DrawPoint3D() (2 input parameters)
+Function 456: DrawPoint3D() (2 input parameters)
Name: DrawPoint3D
Return type: void
Description: Draw a point in 3D space, actually a small line
Param[1]: position (type: Vector3)
Param[2]: color (type: Color)
-Function 456: DrawCircle3D() (5 input parameters)
+Function 457: DrawCircle3D() (5 input parameters)
Name: DrawCircle3D
Return type: void
Description: Draw a circle in 3D world space
@@ -3871,7 +3880,7 @@ Function 456: DrawCircle3D() (5 input parameters)
Param[3]: rotationAxis (type: Vector3)
Param[4]: rotationAngle (type: float)
Param[5]: color (type: Color)
-Function 457: DrawTriangle3D() (4 input parameters)
+Function 458: DrawTriangle3D() (4 input parameters)
Name: DrawTriangle3D
Return type: void
Description: Draw a color-filled triangle (vertex in counter-clockwise order!)
@@ -3879,14 +3888,14 @@ Function 457: DrawTriangle3D() (4 input parameters)
Param[2]: v2 (type: Vector3)
Param[3]: v3 (type: Vector3)
Param[4]: color (type: Color)
-Function 458: DrawTriangleStrip3D() (3 input parameters)
+Function 459: DrawTriangleStrip3D() (3 input parameters)
Name: DrawTriangleStrip3D
Return type: void
Description: Draw a triangle strip defined by points
Param[1]: points (type: const Vector3 *)
Param[2]: pointCount (type: int)
Param[3]: color (type: Color)
-Function 459: DrawCube() (5 input parameters)
+Function 460: DrawCube() (5 input parameters)
Name: DrawCube
Return type: void
Description: Draw cube
@@ -3895,14 +3904,14 @@ Function 459: DrawCube() (5 input parameters)
Param[3]: height (type: float)
Param[4]: length (type: float)
Param[5]: color (type: Color)
-Function 460: DrawCubeV() (3 input parameters)
+Function 461: DrawCubeV() (3 input parameters)
Name: DrawCubeV
Return type: void
Description: Draw cube (Vector version)
Param[1]: position (type: Vector3)
Param[2]: size (type: Vector3)
Param[3]: color (type: Color)
-Function 461: DrawCubeWires() (5 input parameters)
+Function 462: DrawCubeWires() (5 input parameters)
Name: DrawCubeWires
Return type: void
Description: Draw cube wires
@@ -3911,21 +3920,21 @@ Function 461: DrawCubeWires() (5 input parameters)
Param[3]: height (type: float)
Param[4]: length (type: float)
Param[5]: color (type: Color)
-Function 462: DrawCubeWiresV() (3 input parameters)
+Function 463: DrawCubeWiresV() (3 input parameters)
Name: DrawCubeWiresV
Return type: void
Description: Draw cube wires (Vector version)
Param[1]: position (type: Vector3)
Param[2]: size (type: Vector3)
Param[3]: color (type: Color)
-Function 463: DrawSphere() (3 input parameters)
+Function 464: DrawSphere() (3 input parameters)
Name: DrawSphere
Return type: void
Description: Draw sphere
Param[1]: centerPos (type: Vector3)
Param[2]: radius (type: float)
Param[3]: color (type: Color)
-Function 464: DrawSphereEx() (5 input parameters)
+Function 465: DrawSphereEx() (5 input parameters)
Name: DrawSphereEx
Return type: void
Description: Draw sphere with extended parameters
@@ -3934,7 +3943,7 @@ Function 464: DrawSphereEx() (5 input parameters)
Param[3]: rings (type: int)
Param[4]: slices (type: int)
Param[5]: color (type: Color)
-Function 465: DrawSphereWires() (5 input parameters)
+Function 466: DrawSphereWires() (5 input parameters)
Name: DrawSphereWires
Return type: void
Description: Draw sphere wires
@@ -3943,7 +3952,7 @@ Function 465: DrawSphereWires() (5 input parameters)
Param[3]: rings (type: int)
Param[4]: slices (type: int)
Param[5]: color (type: Color)
-Function 466: DrawCylinder() (6 input parameters)
+Function 467: DrawCylinder() (6 input parameters)
Name: DrawCylinder
Return type: void
Description: Draw a cylinder/cone
@@ -3953,7 +3962,7 @@ Function 466: DrawCylinder() (6 input parameters)
Param[4]: height (type: float)
Param[5]: slices (type: int)
Param[6]: color (type: Color)
-Function 467: DrawCylinderEx() (6 input parameters)
+Function 468: DrawCylinderEx() (6 input parameters)
Name: DrawCylinderEx
Return type: void
Description: Draw a cylinder with base at startPos and top at endPos
@@ -3963,7 +3972,7 @@ Function 467: DrawCylinderEx() (6 input parameters)
Param[4]: endRadius (type: float)
Param[5]: sides (type: int)
Param[6]: color (type: Color)
-Function 468: DrawCylinderWires() (6 input parameters)
+Function 469: DrawCylinderWires() (6 input parameters)
Name: DrawCylinderWires
Return type: void
Description: Draw a cylinder/cone wires
@@ -3973,7 +3982,7 @@ Function 468: DrawCylinderWires() (6 input parameters)
Param[4]: height (type: float)
Param[5]: slices (type: int)
Param[6]: color (type: Color)
-Function 469: DrawCylinderWiresEx() (6 input parameters)
+Function 470: DrawCylinderWiresEx() (6 input parameters)
Name: DrawCylinderWiresEx
Return type: void
Description: Draw a cylinder wires with base at startPos and top at endPos
@@ -3983,7 +3992,7 @@ Function 469: DrawCylinderWiresEx() (6 input parameters)
Param[4]: endRadius (type: float)
Param[5]: sides (type: int)
Param[6]: color (type: Color)
-Function 470: DrawCapsule() (6 input parameters)
+Function 471: DrawCapsule() (6 input parameters)
Name: DrawCapsule
Return type: void
Description: Draw a capsule with the center of its sphere caps at startPos and endPos
@@ -3993,7 +4002,7 @@ Function 470: DrawCapsule() (6 input parameters)
Param[4]: slices (type: int)
Param[5]: rings (type: int)
Param[6]: color (type: Color)
-Function 471: DrawCapsuleWires() (6 input parameters)
+Function 472: DrawCapsuleWires() (6 input parameters)
Name: DrawCapsuleWires
Return type: void
Description: Draw capsule wireframe with the center of its sphere caps at startPos and endPos
@@ -4003,51 +4012,51 @@ Function 471: DrawCapsuleWires() (6 input parameters)
Param[4]: slices (type: int)
Param[5]: rings (type: int)
Param[6]: color (type: Color)
-Function 472: DrawPlane() (3 input parameters)
+Function 473: DrawPlane() (3 input parameters)
Name: DrawPlane
Return type: void
Description: Draw a plane XZ
Param[1]: centerPos (type: Vector3)
Param[2]: size (type: Vector2)
Param[3]: color (type: Color)
-Function 473: DrawRay() (2 input parameters)
+Function 474: DrawRay() (2 input parameters)
Name: DrawRay
Return type: void
Description: Draw a ray line
Param[1]: ray (type: Ray)
Param[2]: color (type: Color)
-Function 474: DrawGrid() (2 input parameters)
+Function 475: DrawGrid() (2 input parameters)
Name: DrawGrid
Return type: void
Description: Draw a grid (centered at (0, 0, 0))
Param[1]: slices (type: int)
Param[2]: spacing (type: float)
-Function 475: LoadModel() (1 input parameters)
+Function 476: LoadModel() (1 input parameters)
Name: LoadModel
Return type: Model
Description: Load model from files (meshes and materials)
Param[1]: fileName (type: const char *)
-Function 476: LoadModelFromMesh() (1 input parameters)
+Function 477: LoadModelFromMesh() (1 input parameters)
Name: LoadModelFromMesh
Return type: Model
Description: Load model from generated mesh (default material)
Param[1]: mesh (type: Mesh)
-Function 477: IsModelValid() (1 input parameters)
+Function 478: IsModelValid() (1 input parameters)
Name: IsModelValid
Return type: bool
Description: Check if a model is valid (loaded in GPU, VAO/VBOs)
Param[1]: model (type: Model)
-Function 478: UnloadModel() (1 input parameters)
+Function 479: UnloadModel() (1 input parameters)
Name: UnloadModel
Return type: void
Description: Unload model (including meshes) from memory (RAM and/or VRAM)
Param[1]: model (type: Model)
-Function 479: GetModelBoundingBox() (1 input parameters)
+Function 480: GetModelBoundingBox() (1 input parameters)
Name: GetModelBoundingBox
Return type: BoundingBox
Description: Compute model bounding box limits (considers all meshes)
Param[1]: model (type: Model)
-Function 480: DrawModel() (4 input parameters)
+Function 481: DrawModel() (4 input parameters)
Name: DrawModel
Return type: void
Description: Draw a model (with texture if set)
@@ -4055,7 +4064,7 @@ Function 480: DrawModel() (4 input parameters)
Param[2]: position (type: Vector3)
Param[3]: scale (type: float)
Param[4]: tint (type: Color)
-Function 481: DrawModelEx() (6 input parameters)
+Function 482: DrawModelEx() (6 input parameters)
Name: DrawModelEx
Return type: void
Description: Draw a model with extended parameters
@@ -4065,7 +4074,7 @@ Function 481: DrawModelEx() (6 input parameters)
Param[4]: rotationAngle (type: float)
Param[5]: scale (type: Vector3)
Param[6]: tint (type: Color)
-Function 482: DrawModelWires() (4 input parameters)
+Function 483: DrawModelWires() (4 input parameters)
Name: DrawModelWires
Return type: void
Description: Draw a model wires (with texture if set)
@@ -4073,7 +4082,7 @@ Function 482: DrawModelWires() (4 input parameters)
Param[2]: position (type: Vector3)
Param[3]: scale (type: float)
Param[4]: tint (type: Color)
-Function 483: DrawModelWiresEx() (6 input parameters)
+Function 484: DrawModelWiresEx() (6 input parameters)
Name: DrawModelWiresEx
Return type: void
Description: Draw a model wires (with texture if set) with extended parameters
@@ -4083,7 +4092,7 @@ Function 483: DrawModelWiresEx() (6 input parameters)
Param[4]: rotationAngle (type: float)
Param[5]: scale (type: Vector3)
Param[6]: tint (type: Color)
-Function 484: DrawModelPoints() (4 input parameters)
+Function 485: DrawModelPoints() (4 input parameters)
Name: DrawModelPoints
Return type: void
Description: Draw a model as points
@@ -4091,7 +4100,7 @@ Function 484: DrawModelPoints() (4 input parameters)
Param[2]: position (type: Vector3)
Param[3]: scale (type: float)
Param[4]: tint (type: Color)
-Function 485: DrawModelPointsEx() (6 input parameters)
+Function 486: DrawModelPointsEx() (6 input parameters)
Name: DrawModelPointsEx
Return type: void
Description: Draw a model as points with extended parameters
@@ -4101,13 +4110,13 @@ Function 485: DrawModelPointsEx() (6 input parameters)
Param[4]: rotationAngle (type: float)
Param[5]: scale (type: Vector3)
Param[6]: tint (type: Color)
-Function 486: DrawBoundingBox() (2 input parameters)
+Function 487: DrawBoundingBox() (2 input parameters)
Name: DrawBoundingBox
Return type: void
Description: Draw bounding box (wires)
Param[1]: box (type: BoundingBox)
Param[2]: color (type: Color)
-Function 487: DrawBillboard() (5 input parameters)
+Function 488: DrawBillboard() (5 input parameters)
Name: DrawBillboard
Return type: void
Description: Draw a billboard texture
@@ -4116,7 +4125,7 @@ Function 487: DrawBillboard() (5 input parameters)
Param[3]: position (type: Vector3)
Param[4]: scale (type: float)
Param[5]: tint (type: Color)
-Function 488: DrawBillboardRec() (6 input parameters)
+Function 489: DrawBillboardRec() (6 input parameters)
Name: DrawBillboardRec
Return type: void
Description: Draw a billboard texture defined by source
@@ -4126,7 +4135,7 @@ Function 488: DrawBillboardRec() (6 input parameters)
Param[4]: position (type: Vector3)
Param[5]: size (type: Vector2)
Param[6]: tint (type: Color)
-Function 489: DrawBillboardPro() (9 input parameters)
+Function 490: DrawBillboardPro() (9 input parameters)
Name: DrawBillboardPro
Return type: void
Description: Draw a billboard texture defined by source and rotation
@@ -4139,13 +4148,13 @@ Function 489: DrawBillboardPro() (9 input parameters)
Param[7]: origin (type: Vector2)
Param[8]: rotation (type: float)
Param[9]: tint (type: Color)
-Function 490: UploadMesh() (2 input parameters)
+Function 491: UploadMesh() (2 input parameters)
Name: UploadMesh
Return type: void
Description: Upload mesh vertex data in GPU and provide VAO/VBO ids
Param[1]: mesh (type: Mesh *)
Param[2]: dynamic (type: bool)
-Function 491: UpdateMeshBuffer() (5 input parameters)
+Function 492: UpdateMeshBuffer() (5 input parameters)
Name: UpdateMeshBuffer
Return type: void
Description: Update mesh vertex data in GPU for a specific buffer index
@@ -4154,19 +4163,19 @@ Function 491: UpdateMeshBuffer() (5 input parameters)
Param[3]: data (type: const void *)
Param[4]: dataSize (type: int)
Param[5]: offset (type: int)
-Function 492: UnloadMesh() (1 input parameters)
+Function 493: UnloadMesh() (1 input parameters)
Name: UnloadMesh
Return type: void
Description: Unload mesh data from CPU and GPU
Param[1]: mesh (type: Mesh)
-Function 493: DrawMesh() (3 input parameters)
+Function 494: DrawMesh() (3 input parameters)
Name: DrawMesh
Return type: void
Description: Draw a 3d mesh with material and transform
Param[1]: mesh (type: Mesh)
Param[2]: material (type: Material)
Param[3]: transform (type: Matrix)
-Function 494: DrawMeshInstanced() (4 input parameters)
+Function 495: DrawMeshInstanced() (4 input parameters)
Name: DrawMeshInstanced
Return type: void
Description: Draw multiple mesh instances with material and different transforms
@@ -4174,35 +4183,35 @@ Function 494: DrawMeshInstanced() (4 input parameters)
Param[2]: material (type: Material)
Param[3]: transforms (type: const Matrix *)
Param[4]: instances (type: int)
-Function 495: GetMeshBoundingBox() (1 input parameters)
+Function 496: GetMeshBoundingBox() (1 input parameters)
Name: GetMeshBoundingBox
Return type: BoundingBox
Description: Compute mesh bounding box limits
Param[1]: mesh (type: Mesh)
-Function 496: GenMeshTangents() (1 input parameters)
+Function 497: GenMeshTangents() (1 input parameters)
Name: GenMeshTangents
Return type: void
Description: Compute mesh tangents
Param[1]: mesh (type: Mesh *)
-Function 497: ExportMesh() (2 input parameters)
+Function 498: ExportMesh() (2 input parameters)
Name: ExportMesh
Return type: bool
Description: Export mesh data to file, returns true on success
Param[1]: mesh (type: Mesh)
Param[2]: fileName (type: const char *)
-Function 498: ExportMeshAsCode() (2 input parameters)
+Function 499: ExportMeshAsCode() (2 input parameters)
Name: ExportMeshAsCode
Return type: bool
Description: Export mesh as code file (.h) defining multiple arrays of vertex attributes
Param[1]: mesh (type: Mesh)
Param[2]: fileName (type: const char *)
-Function 499: GenMeshPoly() (2 input parameters)
+Function 500: GenMeshPoly() (2 input parameters)
Name: GenMeshPoly
Return type: Mesh
Description: Generate polygonal mesh
Param[1]: sides (type: int)
Param[2]: radius (type: float)
-Function 500: GenMeshPlane() (4 input parameters)
+Function 501: GenMeshPlane() (4 input parameters)
Name: GenMeshPlane
Return type: Mesh
Description: Generate plane mesh (with subdivisions)
@@ -4210,42 +4219,42 @@ Function 500: GenMeshPlane() (4 input parameters)
Param[2]: length (type: float)
Param[3]: resX (type: int)
Param[4]: resZ (type: int)
-Function 501: GenMeshCube() (3 input parameters)
+Function 502: GenMeshCube() (3 input parameters)
Name: GenMeshCube
Return type: Mesh
Description: Generate cuboid mesh
Param[1]: width (type: float)
Param[2]: height (type: float)
Param[3]: length (type: float)
-Function 502: GenMeshSphere() (3 input parameters)
+Function 503: GenMeshSphere() (3 input parameters)
Name: GenMeshSphere
Return type: Mesh
Description: Generate sphere mesh (standard sphere)
Param[1]: radius (type: float)
Param[2]: rings (type: int)
Param[3]: slices (type: int)
-Function 503: GenMeshHemiSphere() (3 input parameters)
+Function 504: GenMeshHemiSphere() (3 input parameters)
Name: GenMeshHemiSphere
Return type: Mesh
Description: Generate half-sphere mesh (no bottom cap)
Param[1]: radius (type: float)
Param[2]: rings (type: int)
Param[3]: slices (type: int)
-Function 504: GenMeshCylinder() (3 input parameters)
+Function 505: GenMeshCylinder() (3 input parameters)
Name: GenMeshCylinder
Return type: Mesh
Description: Generate cylinder mesh
Param[1]: radius (type: float)
Param[2]: height (type: float)
Param[3]: slices (type: int)
-Function 505: GenMeshCone() (3 input parameters)
+Function 506: GenMeshCone() (3 input parameters)
Name: GenMeshCone
Return type: Mesh
Description: Generate cone/pyramid mesh
Param[1]: radius (type: float)
Param[2]: height (type: float)
Param[3]: slices (type: int)
-Function 506: GenMeshTorus() (4 input parameters)
+Function 507: GenMeshTorus() (4 input parameters)
Name: GenMeshTorus
Return type: Mesh
Description: Generate torus mesh
@@ -4253,7 +4262,7 @@ Function 506: GenMeshTorus() (4 input parameters)
Param[2]: size (type: float)
Param[3]: radSeg (type: int)
Param[4]: sides (type: int)
-Function 507: GenMeshKnot() (4 input parameters)
+Function 508: GenMeshKnot() (4 input parameters)
Name: GenMeshKnot
Return type: Mesh
Description: Generate trefoil knot mesh
@@ -4261,91 +4270,91 @@ Function 507: GenMeshKnot() (4 input parameters)
Param[2]: size (type: float)
Param[3]: radSeg (type: int)
Param[4]: sides (type: int)
-Function 508: GenMeshHeightmap() (2 input parameters)
+Function 509: GenMeshHeightmap() (2 input parameters)
Name: GenMeshHeightmap
Return type: Mesh
Description: Generate heightmap mesh from image data
Param[1]: heightmap (type: Image)
Param[2]: size (type: Vector3)
-Function 509: GenMeshCubicmap() (2 input parameters)
+Function 510: GenMeshCubicmap() (2 input parameters)
Name: GenMeshCubicmap
Return type: Mesh
Description: Generate cubes-based map mesh from image data
Param[1]: cubicmap (type: Image)
Param[2]: cubeSize (type: Vector3)
-Function 510: LoadMaterials() (2 input parameters)
+Function 511: LoadMaterials() (2 input parameters)
Name: LoadMaterials
Return type: Material *
Description: Load materials from model file
Param[1]: fileName (type: const char *)
Param[2]: materialCount (type: int *)
-Function 511: LoadMaterialDefault() (0 input parameters)
+Function 512: LoadMaterialDefault() (0 input parameters)
Name: LoadMaterialDefault
Return type: Material
Description: Load default material (Supports: DIFFUSE, SPECULAR, NORMAL maps)
No input parameters
-Function 512: IsMaterialValid() (1 input parameters)
+Function 513: IsMaterialValid() (1 input parameters)
Name: IsMaterialValid
Return type: bool
Description: Check if a material is valid (shader assigned, map textures loaded in GPU)
Param[1]: material (type: Material)
-Function 513: UnloadMaterial() (1 input parameters)
+Function 514: UnloadMaterial() (1 input parameters)
Name: UnloadMaterial
Return type: void
Description: Unload material from GPU memory (VRAM)
Param[1]: material (type: Material)
-Function 514: SetMaterialTexture() (3 input parameters)
+Function 515: SetMaterialTexture() (3 input parameters)
Name: SetMaterialTexture
Return type: void
Description: Set texture for a material map type (MATERIAL_MAP_DIFFUSE, MATERIAL_MAP_SPECULAR...)
Param[1]: material (type: Material *)
Param[2]: mapType (type: int)
Param[3]: texture (type: Texture2D)
-Function 515: SetModelMeshMaterial() (3 input parameters)
+Function 516: SetModelMeshMaterial() (3 input parameters)
Name: SetModelMeshMaterial
Return type: void
Description: Set material for a mesh
Param[1]: model (type: Model *)
Param[2]: meshId (type: int)
Param[3]: materialId (type: int)
-Function 516: LoadModelAnimations() (2 input parameters)
+Function 517: LoadModelAnimations() (2 input parameters)
Name: LoadModelAnimations
Return type: ModelAnimation *
Description: Load model animations from file
Param[1]: fileName (type: const char *)
Param[2]: animCount (type: int *)
-Function 517: UpdateModelAnimation() (3 input parameters)
+Function 518: UpdateModelAnimation() (3 input parameters)
Name: UpdateModelAnimation
Return type: void
Description: Update model animation pose (CPU)
Param[1]: model (type: Model)
Param[2]: anim (type: ModelAnimation)
Param[3]: frame (type: int)
-Function 518: UpdateModelAnimationBones() (3 input parameters)
+Function 519: UpdateModelAnimationBones() (3 input parameters)
Name: UpdateModelAnimationBones
Return type: void
Description: Update model animation mesh bone matrices (GPU skinning)
Param[1]: model (type: Model)
Param[2]: anim (type: ModelAnimation)
Param[3]: frame (type: int)
-Function 519: UnloadModelAnimation() (1 input parameters)
+Function 520: UnloadModelAnimation() (1 input parameters)
Name: UnloadModelAnimation
Return type: void
Description: Unload animation data
Param[1]: anim (type: ModelAnimation)
-Function 520: UnloadModelAnimations() (2 input parameters)
+Function 521: UnloadModelAnimations() (2 input parameters)
Name: UnloadModelAnimations
Return type: void
Description: Unload animation array data
Param[1]: animations (type: ModelAnimation *)
Param[2]: animCount (type: int)
-Function 521: IsModelAnimationValid() (2 input parameters)
+Function 522: IsModelAnimationValid() (2 input parameters)
Name: IsModelAnimationValid
Return type: bool
Description: Check model animation skeleton match
Param[1]: model (type: Model)
Param[2]: anim (type: ModelAnimation)
-Function 522: CheckCollisionSpheres() (4 input parameters)
+Function 523: CheckCollisionSpheres() (4 input parameters)
Name: CheckCollisionSpheres
Return type: bool
Description: Check collision between two spheres
@@ -4353,40 +4362,40 @@ Function 522: CheckCollisionSpheres() (4 input parameters)
Param[2]: radius1 (type: float)
Param[3]: center2 (type: Vector3)
Param[4]: radius2 (type: float)
-Function 523: CheckCollisionBoxes() (2 input parameters)
+Function 524: CheckCollisionBoxes() (2 input parameters)
Name: CheckCollisionBoxes
Return type: bool
Description: Check collision between two bounding boxes
Param[1]: box1 (type: BoundingBox)
Param[2]: box2 (type: BoundingBox)
-Function 524: CheckCollisionBoxSphere() (3 input parameters)
+Function 525: CheckCollisionBoxSphere() (3 input parameters)
Name: CheckCollisionBoxSphere
Return type: bool
Description: Check collision between box and sphere
Param[1]: box (type: BoundingBox)
Param[2]: center (type: Vector3)
Param[3]: radius (type: float)
-Function 525: GetRayCollisionSphere() (3 input parameters)
+Function 526: GetRayCollisionSphere() (3 input parameters)
Name: GetRayCollisionSphere
Return type: RayCollision
Description: Get collision info between ray and sphere
Param[1]: ray (type: Ray)
Param[2]: center (type: Vector3)
Param[3]: radius (type: float)
-Function 526: GetRayCollisionBox() (2 input parameters)
+Function 527: GetRayCollisionBox() (2 input parameters)
Name: GetRayCollisionBox
Return type: RayCollision
Description: Get collision info between ray and box
Param[1]: ray (type: Ray)
Param[2]: box (type: BoundingBox)
-Function 527: GetRayCollisionMesh() (3 input parameters)
+Function 528: GetRayCollisionMesh() (3 input parameters)
Name: GetRayCollisionMesh
Return type: RayCollision
Description: Get collision info between ray and mesh
Param[1]: ray (type: Ray)
Param[2]: mesh (type: Mesh)
Param[3]: transform (type: Matrix)
-Function 528: GetRayCollisionTriangle() (4 input parameters)
+Function 529: GetRayCollisionTriangle() (4 input parameters)
Name: GetRayCollisionTriangle
Return type: RayCollision
Description: Get collision info between ray and triangle
@@ -4394,7 +4403,7 @@ Function 528: GetRayCollisionTriangle() (4 input parameters)
Param[2]: p1 (type: Vector3)
Param[3]: p2 (type: Vector3)
Param[4]: p3 (type: Vector3)
-Function 529: GetRayCollisionQuad() (5 input parameters)
+Function 530: GetRayCollisionQuad() (5 input parameters)
Name: GetRayCollisionQuad
Return type: RayCollision
Description: Get collision info between ray and quad
@@ -4403,158 +4412,158 @@ Function 529: GetRayCollisionQuad() (5 input parameters)
Param[3]: p2 (type: Vector3)
Param[4]: p3 (type: Vector3)
Param[5]: p4 (type: Vector3)
-Function 530: InitAudioDevice() (0 input parameters)
+Function 531: InitAudioDevice() (0 input parameters)
Name: InitAudioDevice
Return type: void
Description: Initialize audio device and context
No input parameters
-Function 531: CloseAudioDevice() (0 input parameters)
+Function 532: CloseAudioDevice() (0 input parameters)
Name: CloseAudioDevice
Return type: void
Description: Close the audio device and context
No input parameters
-Function 532: IsAudioDeviceReady() (0 input parameters)
+Function 533: IsAudioDeviceReady() (0 input parameters)
Name: IsAudioDeviceReady
Return type: bool
Description: Check if audio device has been initialized successfully
No input parameters
-Function 533: SetMasterVolume() (1 input parameters)
+Function 534: SetMasterVolume() (1 input parameters)
Name: SetMasterVolume
Return type: void
Description: Set master volume (listener)
Param[1]: volume (type: float)
-Function 534: GetMasterVolume() (0 input parameters)
+Function 535: GetMasterVolume() (0 input parameters)
Name: GetMasterVolume
Return type: float
Description: Get master volume (listener)
No input parameters
-Function 535: LoadWave() (1 input parameters)
+Function 536: LoadWave() (1 input parameters)
Name: LoadWave
Return type: Wave
Description: Load wave data from file
Param[1]: fileName (type: const char *)
-Function 536: LoadWaveFromMemory() (3 input parameters)
+Function 537: LoadWaveFromMemory() (3 input parameters)
Name: LoadWaveFromMemory
Return type: Wave
Description: Load wave from memory buffer, fileType refers to extension: i.e. '.wav'
Param[1]: fileType (type: const char *)
Param[2]: fileData (type: const unsigned char *)
Param[3]: dataSize (type: int)
-Function 537: IsWaveValid() (1 input parameters)
+Function 538: IsWaveValid() (1 input parameters)
Name: IsWaveValid
Return type: bool
Description: Checks if wave data is valid (data loaded and parameters)
Param[1]: wave (type: Wave)
-Function 538: LoadSound() (1 input parameters)
+Function 539: LoadSound() (1 input parameters)
Name: LoadSound
Return type: Sound
Description: Load sound from file
Param[1]: fileName (type: const char *)
-Function 539: LoadSoundFromWave() (1 input parameters)
+Function 540: LoadSoundFromWave() (1 input parameters)
Name: LoadSoundFromWave
Return type: Sound
Description: Load sound from wave data
Param[1]: wave (type: Wave)
-Function 540: LoadSoundAlias() (1 input parameters)
+Function 541: LoadSoundAlias() (1 input parameters)
Name: LoadSoundAlias
Return type: Sound
Description: Create a new sound that shares the same sample data as the source sound, does not own the sound data
Param[1]: source (type: Sound)
-Function 541: IsSoundValid() (1 input parameters)
+Function 542: IsSoundValid() (1 input parameters)
Name: IsSoundValid
Return type: bool
Description: Checks if a sound is valid (data loaded and buffers initialized)
Param[1]: sound (type: Sound)
-Function 542: UpdateSound() (3 input parameters)
+Function 543: UpdateSound() (3 input parameters)
Name: UpdateSound
Return type: void
Description: Update sound buffer with new data (data and frame count should fit in sound)
Param[1]: sound (type: Sound)
Param[2]: data (type: const void *)
Param[3]: sampleCount (type: int)
-Function 543: UnloadWave() (1 input parameters)
+Function 544: UnloadWave() (1 input parameters)
Name: UnloadWave
Return type: void
Description: Unload wave data
Param[1]: wave (type: Wave)
-Function 544: UnloadSound() (1 input parameters)
+Function 545: UnloadSound() (1 input parameters)
Name: UnloadSound
Return type: void
Description: Unload sound
Param[1]: sound (type: Sound)
-Function 545: UnloadSoundAlias() (1 input parameters)
+Function 546: UnloadSoundAlias() (1 input parameters)
Name: UnloadSoundAlias
Return type: void
Description: Unload a sound alias (does not deallocate sample data)
Param[1]: alias (type: Sound)
-Function 546: ExportWave() (2 input parameters)
+Function 547: ExportWave() (2 input parameters)
Name: ExportWave
Return type: bool
Description: Export wave data to file, returns true on success
Param[1]: wave (type: Wave)
Param[2]: fileName (type: const char *)
-Function 547: ExportWaveAsCode() (2 input parameters)
+Function 548: ExportWaveAsCode() (2 input parameters)
Name: ExportWaveAsCode
Return type: bool
Description: Export wave sample data to code (.h), returns true on success
Param[1]: wave (type: Wave)
Param[2]: fileName (type: const char *)
-Function 548: PlaySound() (1 input parameters)
+Function 549: PlaySound() (1 input parameters)
Name: PlaySound
Return type: void
Description: Play a sound
Param[1]: sound (type: Sound)
-Function 549: StopSound() (1 input parameters)
+Function 550: StopSound() (1 input parameters)
Name: StopSound
Return type: void
Description: Stop playing a sound
Param[1]: sound (type: Sound)
-Function 550: PauseSound() (1 input parameters)
+Function 551: PauseSound() (1 input parameters)
Name: PauseSound
Return type: void
Description: Pause a sound
Param[1]: sound (type: Sound)
-Function 551: ResumeSound() (1 input parameters)
+Function 552: ResumeSound() (1 input parameters)
Name: ResumeSound
Return type: void
Description: Resume a paused sound
Param[1]: sound (type: Sound)
-Function 552: IsSoundPlaying() (1 input parameters)
+Function 553: IsSoundPlaying() (1 input parameters)
Name: IsSoundPlaying
Return type: bool
Description: Check if a sound is currently playing
Param[1]: sound (type: Sound)
-Function 553: SetSoundVolume() (2 input parameters)
+Function 554: SetSoundVolume() (2 input parameters)
Name: SetSoundVolume
Return type: void
Description: Set volume for a sound (1.0 is max level)
Param[1]: sound (type: Sound)
Param[2]: volume (type: float)
-Function 554: SetSoundPitch() (2 input parameters)
+Function 555: SetSoundPitch() (2 input parameters)
Name: SetSoundPitch
Return type: void
Description: Set pitch for a sound (1.0 is base level)
Param[1]: sound (type: Sound)
Param[2]: pitch (type: float)
-Function 555: SetSoundPan() (2 input parameters)
+Function 556: SetSoundPan() (2 input parameters)
Name: SetSoundPan
Return type: void
Description: Set pan for a sound (0.5 is center)
Param[1]: sound (type: Sound)
Param[2]: pan (type: float)
-Function 556: WaveCopy() (1 input parameters)
+Function 557: WaveCopy() (1 input parameters)
Name: WaveCopy
Return type: Wave
Description: Copy a wave to a new wave
Param[1]: wave (type: Wave)
-Function 557: WaveCrop() (3 input parameters)
+Function 558: WaveCrop() (3 input parameters)
Name: WaveCrop
Return type: void
Description: Crop a wave to defined frames range
Param[1]: wave (type: Wave *)
Param[2]: initFrame (type: int)
Param[3]: finalFrame (type: int)
-Function 558: WaveFormat() (4 input parameters)
+Function 559: WaveFormat() (4 input parameters)
Name: WaveFormat
Return type: void
Description: Convert wave data to desired format
@@ -4562,203 +4571,203 @@ Function 558: WaveFormat() (4 input parameters)
Param[2]: sampleRate (type: int)
Param[3]: sampleSize (type: int)
Param[4]: channels (type: int)
-Function 559: LoadWaveSamples() (1 input parameters)
+Function 560: LoadWaveSamples() (1 input parameters)
Name: LoadWaveSamples
Return type: float *
Description: Load samples data from wave as a 32bit float data array
Param[1]: wave (type: Wave)
-Function 560: UnloadWaveSamples() (1 input parameters)
+Function 561: UnloadWaveSamples() (1 input parameters)
Name: UnloadWaveSamples
Return type: void
Description: Unload samples data loaded with LoadWaveSamples()
Param[1]: samples (type: float *)
-Function 561: LoadMusicStream() (1 input parameters)
+Function 562: LoadMusicStream() (1 input parameters)
Name: LoadMusicStream
Return type: Music
Description: Load music stream from file
Param[1]: fileName (type: const char *)
-Function 562: LoadMusicStreamFromMemory() (3 input parameters)
+Function 563: LoadMusicStreamFromMemory() (3 input parameters)
Name: LoadMusicStreamFromMemory
Return type: Music
Description: Load music stream from data
Param[1]: fileType (type: const char *)
Param[2]: data (type: const unsigned char *)
Param[3]: dataSize (type: int)
-Function 563: IsMusicValid() (1 input parameters)
+Function 564: IsMusicValid() (1 input parameters)
Name: IsMusicValid
Return type: bool
Description: Checks if a music stream is valid (context and buffers initialized)
Param[1]: music (type: Music)
-Function 564: UnloadMusicStream() (1 input parameters)
+Function 565: UnloadMusicStream() (1 input parameters)
Name: UnloadMusicStream
Return type: void
Description: Unload music stream
Param[1]: music (type: Music)
-Function 565: PlayMusicStream() (1 input parameters)
+Function 566: PlayMusicStream() (1 input parameters)
Name: PlayMusicStream
Return type: void
Description: Start music playing
Param[1]: music (type: Music)
-Function 566: IsMusicStreamPlaying() (1 input parameters)
+Function 567: IsMusicStreamPlaying() (1 input parameters)
Name: IsMusicStreamPlaying
Return type: bool
Description: Check if music is playing
Param[1]: music (type: Music)
-Function 567: UpdateMusicStream() (1 input parameters)
+Function 568: UpdateMusicStream() (1 input parameters)
Name: UpdateMusicStream
Return type: void
Description: Updates buffers for music streaming
Param[1]: music (type: Music)
-Function 568: StopMusicStream() (1 input parameters)
+Function 569: StopMusicStream() (1 input parameters)
Name: StopMusicStream
Return type: void
Description: Stop music playing
Param[1]: music (type: Music)
-Function 569: PauseMusicStream() (1 input parameters)
+Function 570: PauseMusicStream() (1 input parameters)
Name: PauseMusicStream
Return type: void
Description: Pause music playing
Param[1]: music (type: Music)
-Function 570: ResumeMusicStream() (1 input parameters)
+Function 571: ResumeMusicStream() (1 input parameters)
Name: ResumeMusicStream
Return type: void
Description: Resume playing paused music
Param[1]: music (type: Music)
-Function 571: SeekMusicStream() (2 input parameters)
+Function 572: SeekMusicStream() (2 input parameters)
Name: SeekMusicStream
Return type: void
Description: Seek music to a position (in seconds)
Param[1]: music (type: Music)
Param[2]: position (type: float)
-Function 572: SetMusicVolume() (2 input parameters)
+Function 573: SetMusicVolume() (2 input parameters)
Name: SetMusicVolume
Return type: void
Description: Set volume for music (1.0 is max level)
Param[1]: music (type: Music)
Param[2]: volume (type: float)
-Function 573: SetMusicPitch() (2 input parameters)
+Function 574: SetMusicPitch() (2 input parameters)
Name: SetMusicPitch
Return type: void
Description: Set pitch for a music (1.0 is base level)
Param[1]: music (type: Music)
Param[2]: pitch (type: float)
-Function 574: SetMusicPan() (2 input parameters)
+Function 575: SetMusicPan() (2 input parameters)
Name: SetMusicPan
Return type: void
Description: Set pan for a music (0.5 is center)
Param[1]: music (type: Music)
Param[2]: pan (type: float)
-Function 575: GetMusicTimeLength() (1 input parameters)
+Function 576: GetMusicTimeLength() (1 input parameters)
Name: GetMusicTimeLength
Return type: float
Description: Get music time length (in seconds)
Param[1]: music (type: Music)
-Function 576: GetMusicTimePlayed() (1 input parameters)
+Function 577: GetMusicTimePlayed() (1 input parameters)
Name: GetMusicTimePlayed
Return type: float
Description: Get current music time played (in seconds)
Param[1]: music (type: Music)
-Function 577: LoadAudioStream() (3 input parameters)
+Function 578: LoadAudioStream() (3 input parameters)
Name: LoadAudioStream
Return type: AudioStream
Description: Load audio stream (to stream raw audio pcm data)
Param[1]: sampleRate (type: unsigned int)
Param[2]: sampleSize (type: unsigned int)
Param[3]: channels (type: unsigned int)
-Function 578: IsAudioStreamValid() (1 input parameters)
+Function 579: IsAudioStreamValid() (1 input parameters)
Name: IsAudioStreamValid
Return type: bool
Description: Checks if an audio stream is valid (buffers initialized)
Param[1]: stream (type: AudioStream)
-Function 579: UnloadAudioStream() (1 input parameters)
+Function 580: UnloadAudioStream() (1 input parameters)
Name: UnloadAudioStream
Return type: void
Description: Unload audio stream and free memory
Param[1]: stream (type: AudioStream)
-Function 580: UpdateAudioStream() (3 input parameters)
+Function 581: UpdateAudioStream() (3 input parameters)
Name: UpdateAudioStream
Return type: void
Description: Update audio stream buffers with data
Param[1]: stream (type: AudioStream)
Param[2]: data (type: const void *)
Param[3]: frameCount (type: int)
-Function 581: IsAudioStreamProcessed() (1 input parameters)
+Function 582: IsAudioStreamProcessed() (1 input parameters)
Name: IsAudioStreamProcessed
Return type: bool
Description: Check if any audio stream buffers requires refill
Param[1]: stream (type: AudioStream)
-Function 582: PlayAudioStream() (1 input parameters)
+Function 583: PlayAudioStream() (1 input parameters)
Name: PlayAudioStream
Return type: void
Description: Play audio stream
Param[1]: stream (type: AudioStream)
-Function 583: PauseAudioStream() (1 input parameters)
+Function 584: PauseAudioStream() (1 input parameters)
Name: PauseAudioStream
Return type: void
Description: Pause audio stream
Param[1]: stream (type: AudioStream)
-Function 584: ResumeAudioStream() (1 input parameters)
+Function 585: ResumeAudioStream() (1 input parameters)
Name: ResumeAudioStream
Return type: void
Description: Resume audio stream
Param[1]: stream (type: AudioStream)
-Function 585: IsAudioStreamPlaying() (1 input parameters)
+Function 586: IsAudioStreamPlaying() (1 input parameters)
Name: IsAudioStreamPlaying
Return type: bool
Description: Check if audio stream is playing
Param[1]: stream (type: AudioStream)
-Function 586: StopAudioStream() (1 input parameters)
+Function 587: StopAudioStream() (1 input parameters)
Name: StopAudioStream
Return type: void
Description: Stop audio stream
Param[1]: stream (type: AudioStream)
-Function 587: SetAudioStreamVolume() (2 input parameters)
+Function 588: SetAudioStreamVolume() (2 input parameters)
Name: SetAudioStreamVolume
Return type: void
Description: Set volume for audio stream (1.0 is max level)
Param[1]: stream (type: AudioStream)
Param[2]: volume (type: float)
-Function 588: SetAudioStreamPitch() (2 input parameters)
+Function 589: SetAudioStreamPitch() (2 input parameters)
Name: SetAudioStreamPitch
Return type: void
Description: Set pitch for audio stream (1.0 is base level)
Param[1]: stream (type: AudioStream)
Param[2]: pitch (type: float)
-Function 589: SetAudioStreamPan() (2 input parameters)
+Function 590: SetAudioStreamPan() (2 input parameters)
Name: SetAudioStreamPan
Return type: void
Description: Set pan for audio stream (0.5 is centered)
Param[1]: stream (type: AudioStream)
Param[2]: pan (type: float)
-Function 590: SetAudioStreamBufferSizeDefault() (1 input parameters)
+Function 591: SetAudioStreamBufferSizeDefault() (1 input parameters)
Name: SetAudioStreamBufferSizeDefault
Return type: void
Description: Default size for new audio streams
Param[1]: size (type: int)
-Function 591: SetAudioStreamCallback() (2 input parameters)
+Function 592: SetAudioStreamCallback() (2 input parameters)
Name: SetAudioStreamCallback
Return type: void
Description: Audio thread callback to request new data
Param[1]: stream (type: AudioStream)
Param[2]: callback (type: AudioCallback)
-Function 592: AttachAudioStreamProcessor() (2 input parameters)
+Function 593: AttachAudioStreamProcessor() (2 input parameters)
Name: AttachAudioStreamProcessor
Return type: void
Description: Attach audio stream processor to stream, receives frames x 2 samples as 'float' (stereo)
Param[1]: stream (type: AudioStream)
Param[2]: processor (type: AudioCallback)
-Function 593: DetachAudioStreamProcessor() (2 input parameters)
+Function 594: DetachAudioStreamProcessor() (2 input parameters)
Name: DetachAudioStreamProcessor
Return type: void
Description: Detach audio stream processor from stream
Param[1]: stream (type: AudioStream)
Param[2]: processor (type: AudioCallback)
-Function 594: AttachAudioMixedProcessor() (1 input parameters)
+Function 595: AttachAudioMixedProcessor() (1 input parameters)
Name: AttachAudioMixedProcessor
Return type: void
Description: Attach audio stream processor to the entire audio pipeline, receives frames x 2 samples as 'float' (stereo)
Param[1]: processor (type: AudioCallback)
-Function 595: DetachAudioMixedProcessor() (1 input parameters)
+Function 596: DetachAudioMixedProcessor() (1 input parameters)
Name: DetachAudioMixedProcessor
Return type: void
Description: Detach audio stream processor from the entire audio pipeline
diff --git a/tools/parser/output/raylib_api.xml b/tools/rlparser/output/raylib_api.xml
similarity index 99%
rename from tools/parser/output/raylib_api.xml
rename to tools/rlparser/output/raylib_api.xml
index 6ea73d8dc..59f2d4a50 100644
--- a/tools/parser/output/raylib_api.xml
+++ b/tools/rlparser/output/raylib_api.xml
@@ -679,7 +679,7 @@
-
+
@@ -1381,6 +1381,13 @@
+
+
+
+
+
+
+
diff --git a/tools/parser/raylib_parser.c b/tools/rlparser/rlparser.c
similarity index 96%
rename from tools/parser/raylib_parser.c
rename to tools/rlparser/rlparser.c
index 4b5fe1625..d5b03fa01 100644
--- a/tools/parser/raylib_parser.c
+++ b/tools/rlparser/rlparser.c
@@ -1,28 +1,28 @@
/**********************************************************************************************
- raylib API parser
+ rlparser - raylib header API parser, extracts API information as separate tokens
This parser scans raylib.h to get API information about defines, structs, aliases, enums, callbacks and functions.
All data is divided into pieces, usually as strings. The following types are used for data:
-
- struct DefineInfo
- struct StructInfo
- struct AliasInfo
- struct EnumInfo
- struct FunctionInfo
+
+ WARNING: This parser is specifically designed to work with raylib.h, and has some contraints
+ in that regards. Still, it can also work with other header files that follow same file structure
+ conventions as raylib.h: rlgl.h, raymath.h, raygui.h, reasings.h
CONSTRAINTS:
-
This parser is specifically designed to work with raylib.h, so, it has some constraints:
- Functions are expected as a single line with the following structure:
-
( , );
- Be careful with functions broken into several lines, it breaks the process!
+ WARNING: Be careful with functions broken into several lines, it breaks the process!
- Structures are expected as several lines with the following form:
-
typedef struct {
;
@@ -31,7 +31,6 @@
} ;
- Enums are expected as several lines with the following form:
-
typedef enum {
= ,
@@ -45,7 +44,6 @@
- Value description can be provided or not
OTHER NOTES:
-
- This parser could work with other C header files if mentioned constraints are followed.
- This parser does not require library, all data is parsed directly from char buffers.
@@ -82,7 +80,7 @@
// Types and Structures Definition
//----------------------------------------------------------------------------------
-// Type of parsed define
+// Define value type
typedef enum {
UNKNOWN = 0,
MACRO,
@@ -103,7 +101,7 @@ typedef enum {
// Define info data
typedef struct DefineInfo {
char name[64]; // Define name
- int type; // Define type
+ int type; // Define type: enum DefineType
char value[256]; // Define value
char desc[128]; // Define description
bool isHex; // Define is hex number (for types INT, LONG)
@@ -171,7 +169,7 @@ static char apiDefine[32] = { 0 }; // Functions define (i.e. RLAPI for r
static char truncAfter[32] = { 0 }; // Truncate marker (i.e. "RLGL IMPLEMENTATION" for rlgl.h)
static int outputFormat = DEFAULT;
-// NOTE: Max length depends on OS, in Windows MAX_PATH = 256
+// NOTE: Filename max length depends on OS, in Windows MAX_PATH = 256
static char inFileName[512] = { 0 }; // Input file name (required in case of drag & drop over executable)
static char outFileName[512] = { 0 }; // Output file name (required for file save/export)
@@ -181,15 +179,17 @@ static char outFileName[512] = { 0 }; // Output file name (required for fi
static void ShowCommandLineInfo(void); // Show command line usage info
static void ProcessCommandLine(int argc, char *argv[]); // Process command line input
-static char *LoadFileText(const char *fileName, int *length);
-static char **GetTextLines(const char *buffer, int length, int *linesCount);
-static void GetDataTypeAndName(const char *typeName, int typeNameLen, char *type, char *name);
-static void GetDescription(const char *source, char *description);
+static char *LoadFileText(const char *fileName, int *length); // Load text file - UnloadFileText() required!
+static void UnloadFileText(char *text); // Unload text data
+static char **LoadTextLines(const char *buffer, int length, int *lineCount); // Load all lines from a text buffer (expecting lines ending with '\n') - UnloadTextLines() required
+static void UnloadTextLines(char **lines, int lineCount); // Unload text lines data
+static void GetDataTypeAndName(const char *typeName, int typeNameLen, char *type, char *name); // Get data type and name from a string containing both (i.e function param and struct fields)
+static void GetDescription(const char *source, char *description); // Get description comment from a line, do nothing if no comment in line
static void MoveArraySize(char *name, char *type); // Move array size from name to type
static unsigned int TextLength(const char *text); // Get text length in bytes, check for \0 character
static bool IsTextEqual(const char *text1, const char *text2, unsigned int count);
static int TextFindIndex(const char *text, const char *find); // Find first text occurrence within a string
-static void MemoryCopy(void *dest, const void *src, unsigned int count);
+static void MemoryCopy(void *dest, const void *src, unsigned int count); // Memory copy, memcpy() replacement to avoid
static char *EscapeBackslashes(char *text); // Replace '\' by "\\" when exporting to JSON and XML
static const char *StrDefineType(DefineType type); // Get string of define type
@@ -219,21 +219,21 @@ int main(int argc, char* argv[])
}
// Preprocess buffer to get separate lines
- // NOTE: GetTextLines() also removes leading spaces/tabs
- int linesCount = 0;
- char **lines = GetTextLines(buffer, length, &linesCount);
+ // NOTE: LoadTextLines() also removes leading spaces/tabs
+ int lineCount = 0;
+ char **lines = LoadTextLines(buffer, length, &lineCount);
- // Truncate lines
+ // Truncate lines (if required)
if (truncAfter[0] != '\0')
{
int newCount = -1;
- for (int i = 0; i < linesCount; i++)
+ for (int i = 0; i < lineCount; i++)
{
if (newCount > -1) free(lines[i]);
else if (TextFindIndex(lines[i], truncAfter) > -1) newCount = i;
}
- if (newCount > -1) linesCount = newCount;
- printf("Number of truncated text lines: %i\n", linesCount);
+ if (newCount > -1) lineCount = newCount;
+ printf("Number of truncated text lines: %i\n", lineCount);
}
// Defines line indices
@@ -256,9 +256,8 @@ int main(int argc, char* argv[])
// Prepare required lines for parsing
//----------------------------------------------------------------------------------
-
// Read define lines
- for (int i = 0; i < linesCount; i++)
+ for (int i = 0; i < lineCount; i++)
{
int j = 0;
while ((lines[i][j] == ' ') || (lines[i][j] == '\t')) j++; // skip spaces and tabs in the begining
@@ -273,7 +272,7 @@ int main(int argc, char* argv[])
}
// Read struct lines
- for (int i = 0; i < linesCount; i++)
+ for (int i = 0; i < lineCount; i++)
{
// Find structs
// starting with "typedef struct ... {" or "typedef struct ... ; \n struct ... {"
@@ -300,7 +299,7 @@ int main(int argc, char* argv[])
}
// Read alias lines
- for (int i = 0; i < linesCount; i++)
+ for (int i = 0; i < lineCount; i++)
{
// Find aliases (lines with "typedef ... ...;")
if (IsTextEqual(lines[i], "typedef", 7))
@@ -322,7 +321,7 @@ int main(int argc, char* argv[])
}
// Read enum lines
- for (int i = 0; i < linesCount; i++)
+ for (int i = 0; i < lineCount; i++)
{
// Read enum line
if (IsTextEqual(lines[i], "typedef enum {", 14) && (lines[i][TextLength(lines[i])-1] != ';')) // ignore inline enums
@@ -335,7 +334,7 @@ int main(int argc, char* argv[])
}
// Read callback lines
- for (int i = 0; i < linesCount; i++)
+ for (int i = 0; i < lineCount; i++)
{
// Find callbacks (lines with "typedef ... (* ... )( ... );")
if (IsTextEqual(lines[i], "typedef", 7))
@@ -361,7 +360,7 @@ int main(int argc, char* argv[])
}
// Read function lines
- for (int i = 0; i < linesCount; i++)
+ for (int i = 0; i < lineCount; i++)
{
// Read function line (starting with `define`, i.e. for raylib.h "RLAPI")
if (IsTextEqual(lines[i], apiDefine, TextLength(apiDefine)))
@@ -373,14 +372,13 @@ int main(int argc, char* argv[])
// At this point we have all raylib defines, structs, aliases, enums, callbacks, functions lines data to start parsing
- free(buffer); // Unload text buffer
+ UnloadFileText(buffer); // Unload text buffer
// Parsing raylib data
//----------------------------------------------------------------------------------
-
// Define info data
- defines = (DefineInfo *)calloc(MAX_DEFINES_TO_PARSE, sizeof(DefineInfo));
int defineIndex = 0;
+ defines = (DefineInfo *)calloc(MAX_DEFINES_TO_PARSE, sizeof(DefineInfo));
for (int i = 0; i < defineCount; i++)
{
@@ -1040,8 +1038,7 @@ int main(int argc, char* argv[])
}
free(funcLines);
- for (int i = 0; i < linesCount; i++) free(lines[i]);
- free(lines);
+ UnloadTextLines(lines, lineCount);
// At this point, all raylib data has been parsed!
//----------------------------------------------------------------------------------
@@ -1052,6 +1049,11 @@ int main(int argc, char* argv[])
// callbacks[] -> We have all the callbacks decomposed into pieces for further analysis
// funcs[] -> We have all the functions decomposed into pieces for further analysis
+ // Export data as required
+ // NOTE: We are exporting data in several common formats (JSON, XML, LUA...) for convenience
+ // but this data can be directly used to create bindings for other languages modifying this
+ // small parser for every binding need, there is no need to use (and re-parse) the
+ // generated files... despite it seems that's the usual approach...
printf("\nInput file: %s", inFileName);
printf("\nOutput file: %s", outFileName);
if (outputFormat == DEFAULT) printf("\nOutput format: DEFAULT\n\n");
@@ -1073,22 +1075,21 @@ int main(int argc, char* argv[])
//----------------------------------------------------------------------------------
// Module Functions Definition
//----------------------------------------------------------------------------------
-
// Show command line usage info
static void ShowCommandLineInfo(void)
{
printf("\n//////////////////////////////////////////////////////////////////////////////////\n");
printf("// //\n");
- printf("// raylib API parser //\n");
+ printf("// rlparser - raylib header API parser //\n");
printf("// //\n");
- printf("// more info and bugs-report: github.com/raysan5/raylib/parser //\n");
+ printf("// more info and bugs-report: github.com/raysan5/raylib/tools/rlparser //\n");
printf("// //\n");
printf("// Copyright (c) 2021-2025 Ramon Santamaria (@raysan5) //\n");
printf("// //\n");
printf("//////////////////////////////////////////////////////////////////////////////////\n\n");
printf("USAGE:\n\n");
- printf(" > raylib_parser [--help] [--input ] [--output ] [--format ]\n");
+ printf(" > rlparser [--help] [--input ] [--output ] [--format ]\n");
printf("\nOPTIONS:\n\n");
printf(" -h, --help : Show tool version and command line usage help\n\n");
@@ -1105,11 +1106,11 @@ static void ShowCommandLineInfo(void)
printf(" NOTE: If not specified, the full input file is parsed.\n\n");
printf("\nEXAMPLES:\n\n");
- printf(" > raylib_parser --input raylib.h --output api.json\n");
+ printf(" > rlparser --input raylib.h --output api.json\n");
printf(" Process to generate \n\n");
- printf(" > raylib_parser --output raylib_data.info --format XML\n");
+ printf(" > rlparser --output raylib_data.info --format XML\n");
printf(" Process to generate as XML text data\n\n");
- printf(" > raylib_parser --input raymath.h --output raymath_data.info --format XML --define RMAPI\n");
+ printf(" > rlparser --input raymath.h --output raymath_data.info --format XML --define RMAPI\n");
printf(" Process to generate as XML text data\n\n");
}
@@ -1221,8 +1222,14 @@ static char *LoadFileText(const char *fileName, int *length)
return text;
}
+// Unload text data
+static void UnloadFileText(char *text)
+{
+ free(text);
+}
+
// Get all lines from a text buffer (expecting lines ending with '\n')
-static char **GetTextLines(const char *buffer, int length, int *linesCount)
+static char **LoadTextLines(const char *buffer, int length, int *lineCount)
{
// Get the number of lines in the text
int count = 0;
@@ -1237,7 +1244,7 @@ static char **GetTextLines(const char *buffer, int length, int *linesCount)
for (int i = 0; (i < count) || (bufferPtr[0] != '\0'); i++)
{
- lines[i] = (char *)calloc(MAX_LINE_LENGTH, sizeof(char));
+ lines[i] = (char *)calloc(MAX_LINE_LENGTH, sizeof(char)); // MAX_LINE_LENGTH=1024
// Remove line leading spaces
// Find last index of space/tab character
@@ -1254,10 +1261,17 @@ static char **GetTextLines(const char *buffer, int length, int *linesCount)
bufferPtr += (index + j + 1);
}
- *linesCount = count;
+ *lineCount = count;
return lines;
}
+// Unload text lines data
+static void UnloadTextLines(char **lines, int lineCount)
+{
+ for (int i = 0; i < lineCount; i++) free(lines[i]);
+ free(lines);
+}
+
// Get data type and name from a string containing both
// NOTE: Useful to parse function parameters and struct fields
static void GetDataTypeAndName(const char *typeName, int typeNameLen, char *type, char *name)
diff --git a/tools/rlparser/rlparser.ico b/tools/rlparser/rlparser.ico
new file mode 100644
index 000000000..37f2af6b6
Binary files /dev/null and b/tools/rlparser/rlparser.ico differ
diff --git a/tools/rlparser/rlparser.rc b/tools/rlparser/rlparser.rc
new file mode 100644
index 000000000..a5bb5b7ad
--- /dev/null
+++ b/tools/rlparser/rlparser.rc
@@ -0,0 +1,24 @@
+IDI_APP_ICON ICON "rlparser.ico"
+1 VERSIONINFO
+FILEVERSION 5,5,0,0
+PRODUCTVERSION 5,5,0,0
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904E4" // English US
+ BEGIN
+ VALUE "CompanyName", "raylib technologies"
+ VALUE "FileDescription", "rlparser | raylib header API parser"
+ VALUE "FileVersion", "1.0"
+ VALUE "InternalName", "rlparser"
+ VALUE "LegalCopyright", "(c) 2025 Ramon Santamaria (@raysan5)"
+ VALUE "OriginalFilename", "rlparser"
+ VALUE "ProductName", "rlparser"
+ VALUE "ProductVersion", "1.0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1252 // English US
+ END
+END
\ No newline at end of file
diff --git a/tools/rlparser/rlparser.rc.data b/tools/rlparser/rlparser.rc.data
new file mode 100644
index 000000000..1b5cc0c02
Binary files /dev/null and b/tools/rlparser/rlparser.rc.data differ