Merge branch 'raysan5:master' into master
This commit is contained in:
commit
a1de46c384
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -118,6 +118,7 @@ GTAGS
|
|||
# Zig programming language
|
||||
.zig-cache/
|
||||
zig-cache/
|
||||
zig-pkg/
|
||||
zig-out/
|
||||
build/
|
||||
build-*/
|
||||
|
|
|
|||
54
CHANGELOG
54
CHANGELOG
|
|
@ -21,11 +21,17 @@ KEY CHANGES:
|
|||
|
||||
Detailed changes:
|
||||
|
||||
[rcore] ADDED: `FileRename()`, by @raysan5
|
||||
[rcore] ADDED: `FileRemove()`, by @raysan5
|
||||
[rcore] ADDED: `FileCopy()`, by @raysan5
|
||||
[rcore] ADDED: `FileMove()`, by @raysan5
|
||||
[rcore] ADDED: `FileTextReplace()`, by @raysan5
|
||||
[rcore] ADDED: `FileTextFindIndex()`, by @raysan5
|
||||
[rcore] ADDED: `ComputeSHA256()` (#5264) by @iamahuman1395
|
||||
[rcore] ADDED: `GetKeyName()` (#4544) by @lecongsebastien
|
||||
[rcore] ADDED: Logging and file-system functionality from `utils` (#4551) by @raysan5 -WARNING-
|
||||
[rcore] ADDED: Flags set/clear macros: FLAG_SET, FLAG_CLEAR, FLAG_IS_SET (#5169) by @raysan5
|
||||
[rcore] ADDED: Warnings in case of no platform backend defined by @raysan5
|
||||
[rcore] ADDED: `ComputeSHA256()` (#5264) by @iamahuman1395
|
||||
[rcore] ADDED: `GetKeyName()` (#4544) by @lecongsebastien
|
||||
[rcore] REMOVED: GIF recording option, added example by @raysan5 -WARNING-
|
||||
[rcore] REMOVED: `CORE.Window.fullscreen` variable, using available flag instead by @raysan5
|
||||
[rcore] REMOVED: `SetupFramebuffer()`, most platforms do not need it any more by @raysan5
|
||||
|
|
@ -111,7 +117,7 @@ Detailed changes:
|
|||
[rcore][RGFW] ADDED: New backend option: `PLATFORM_WEB_RGFW` and update RGFW (#4480) by @colleagueRiley
|
||||
[rcore][RGFW] REVIEWED: Added missing Right Control key by @M374LX
|
||||
[rcore][RGFW] REVIEWED: Changed `RGFW_window_eventWait` timeout to -1 by @doggymangc
|
||||
[rcore][RGFW] REVIEWED: Duplicate entries reemoved from `keyMappingRGFW` (#5242) by @iamahuman1395
|
||||
[rcore][RGFW] REVIEWED: Duplicate entries removed from `keyMappingRGFW` (#5242) by @iamahuman1395
|
||||
[rcore][RGFW] REVIEWED: Fix Escape always closing the window by @M374LX
|
||||
[rcore][RGFW] REVIEWED: Forward declare the windows stuff, prevents failures in GCC (#5269) by @Jeffm2501
|
||||
[rcore][RGFW] REVIEWED: Requires RGBA8 images as window icons (#5431) by @crisserpl2
|
||||
|
|
@ -198,7 +204,7 @@ Detailed changes:
|
|||
[rlgl] REVIEWED: `rlActiveDrawBuffers`, fix for OpenGL ES 3.0 (#4605) by @Bigfoot71
|
||||
[rlgl] REVIEWED: `rlGetPixelDataSize()`, correct compressed data size calculation per blocks #5416 by @raysan5
|
||||
[rlgl] REVIEWED: `instranceTransform` shader location index #4538 (#4579) by @meadiode
|
||||
[rlgl] REVIEWED: `SetShaderValueTexture()`, updatee comments (#4703) by @pejorativefox
|
||||
[rlgl] REVIEWED: `SetShaderValueTexture()`, update comments (#4703) by @pejorativefox
|
||||
[rlgl] REDESIGNED: Avoid program crash if GPU data is tried to be loaded before `InitWindow()` #4751 by @raysan5 -WARNING-
|
||||
[rlgl] REDESIGNED: Shader loading API function names for more consistency #5631 by @raysan5 -WARNING-
|
||||
[rlsw] ADDED: `swGetColorBuffer()` for convenience by @raysan5
|
||||
|
|
@ -239,6 +245,13 @@ Detailed changes:
|
|||
[rtextures] REVIEWED: `ImageDrawLineEx(), to be able to draw even numbered thicknesses (#5042) by @Sir-Irk
|
||||
[rtextures] REVIEWED: `ImageBlurGaussian()`, fix integer overflow in cast (#5037) by @garrisonhh
|
||||
[rtext] ADDED: `LoadTextLines()`/`UnloadTextLines()` by @raysan5
|
||||
[rtext] ADDED: `TextInsertAlloc()`, returns memory allocated string by @raysan5
|
||||
[rtext] ADDED: `TextReplace()`, using static buffer by @raysan5
|
||||
[rtext] ADDED: `TextReplaceAlloc()`, returns memory allocated string by @raysan5
|
||||
[rtext] ADDED: `TextReplaceBetween()`, using static buffer by @raysan5
|
||||
[rtext] ADDED: `TextReplaceBetweenAlloc()`, returns memory allocated string by @raysan5
|
||||
[rtext] ADDED: `GetTextBetween()`, using static buffer by @raysan5
|
||||
[rtext] ADDED: `TextRemoveSpaces()`, using static buffer by @raysan5
|
||||
[rtext] ADDED: `MeasureTextCodepoints()` for direct measurement of codepoints (#5623) by @creeperblin
|
||||
[rtext] RENAMED: Variable names for consistency, `textLength` (length in bytes) vs `textSize` (measure in pixels) by @raysan5
|
||||
[rtext] REVIEWED: Support default font loading with no GPU enabled, to be used with Image API
|
||||
|
|
@ -263,11 +276,10 @@ Detailed changes:
|
|||
[rtext] REVIEWED: `GetCodepointCount()`, misuse of cast (#4741) by @sleeptightAnsiC
|
||||
[rtext] REVIEWED: `GenImageFontAtlas()`, memory corruption and invalid size calculation (#5602) by @konakona418
|
||||
[rtext] REVIEWED: `TextInsert()`, fix bug on insertion (#5644) by @CrackedPixel
|
||||
[rtext] REVIEWED: `TextInsert()`, use static buffer, easier to use by @raysan5 -WARNING-
|
||||
[rtext] REVIEWED: `TextJoin()`, convert `const char **` to `char**` by @raysan5
|
||||
[rtext] REVIEWED: `TextReplace()` and `TextLength()`, avoid using `strcpy()` by @raysan5
|
||||
[rtext] REVIEWED: `TextReplace()` by @raysan5
|
||||
[rtext] REVIEWED: `TextReplace()`, improvements (#5511) by @belan2470
|
||||
[rtext] REVIEWED: `TextReplaceBetween()` by @raysan5
|
||||
[rtext] REVIEWED: `TextReplace()` and `TextLength()`, avoid using `strcpy()` by @raysan5
|
||||
[rtext] REVIEWED: `TextSubtext(), fixes (#4759) by @veins1
|
||||
[rtext] REVIEWED: `TextToPascal()`, fix issue by @raysan5
|
||||
[rtext] REVIEWED: `TextToFloat()`, remove removed inaccurate comment (#4596) by @hexmaster111
|
||||
|
|
@ -735,7 +747,7 @@ Detailed changes:
|
|||
[rexm] REVIEWED: `ScanExampleResources()` avoid resources to be saved by the program by @raysan5
|
||||
[rexm] REVIEWED: `UpdateSourceMetadata()` and `TextReplaceBetween()` by @raysan5
|
||||
[rexm] REVIEWED: `examples.js` example addition working by @raysan5
|
||||
[rexm] REVIEWED: `add` command logic for existing examplee addition by @raysan5
|
||||
[rexm] REVIEWED: `add` command logic for existing example addition by @raysan5
|
||||
[rexm] REVIEWED: Replace example name on project file by @raysan5
|
||||
[rexm] REVIEWED: Report issues if logs can not be loaded by @raysan5
|
||||
[rexm] REVIEWED: VS project adding to solution by @raysan5
|
||||
|
|
@ -747,6 +759,7 @@ Detailed changes:
|
|||
[rexm] REVIEWED: `Makefile.Web` before trying to rebuild new example for web by @raysan5
|
||||
[rexm] REVIEWED: Using `Makefile.Web` for specific web versions generation by @raysan5
|
||||
|
||||
[external] ADDED: `cgltf_write` 1.15, to support glTF models export in the future, by @raysan5
|
||||
[external] RENAMED: `rl_gputex.h` to `rltexgpu.h`, compressed textures loading
|
||||
[external] REVIEWED: `rltexgpu.h`, make it usable standalone by @raysan5
|
||||
[external] REVIEWED: `rltexgpu.h, fix the swizzling in `rl_load_dds_from_memory()` (#5422) by @msmith-codes
|
||||
|
|
@ -755,16 +768,23 @@ Detailed changes:
|
|||
[external] REVIEWED: `sdefl` and `sinfl` issues (#5367) by @raysan5
|
||||
[external] REVIEWED: `sinfl_bsr()`, improvements by @RicoP
|
||||
[external] REVIEWED: `stb_truetype`, fix composite glyph scaling logic (#4811) by @ashishbhattarai
|
||||
[external] UPDATED: `raygui` to 5.0-dev for examples by @raysan5
|
||||
[external] UPDATED: dr_libs (#5020) by @Emil2010
|
||||
[external] UPDATED: miniaudio to v0.11.22 (#4983) by @M374LX
|
||||
[external] UPDATED: miniaudio to v0.11.23 (#5234) by @pyrokn8
|
||||
[external] UPDATED: miniaudio to v0.11.24 (#5506) by @vdemcak
|
||||
[external] UPDATED: raygui to 5.0-dev for examples by @raysan5
|
||||
[external] UPDATED: RGFW to 1.5 (#4688) by @ColleagueRiley
|
||||
[external] UPDATED: RGFW to 1.6 (#4795) by @colleagueRiley
|
||||
[external] UPDATED: RGFW to 1.7 (#4965) by @M374LX
|
||||
[external] UPDATED: RGFW to 1.7.5-dev (#4976) by @M374LX
|
||||
[external] UPDATED: RGFW to 2.0.0 (#5582) by @CrackedPixel
|
||||
[external] UPDATED: `miniaudio` to v0.11.22 (#4983) by @M374LX
|
||||
[external] UPDATED: `miniaudio` to v0.11.23 (#5234) by @pyrokn8
|
||||
[external] UPDATED: `miniaudio` to v0.11.24 (#5506) by @vdemcak
|
||||
[external] UPDATED: `RGFW` to 1.5 (#4688) by @ColleagueRiley
|
||||
[external] UPDATED: `RGFW` to 1.6 (#4795) by @colleagueRiley
|
||||
[external] UPDATED: `RGFW` to 1.7 (#4965) by @M374LX
|
||||
[external] UPDATED: `RGFW` to 1.7.5-dev (#4976) by @M374LX
|
||||
[external] UPDATED: `RGFW` to 2.0.0 (#5582) by @CrackedPixel
|
||||
[external] UPDATED: `cgltf` 1.14 to 1.15 by @raysan5
|
||||
[external] UPDATED: `dr_flac` v0.13.0 to v0.13.3 by @raysan5
|
||||
[external] UPDATED: `dr_mp3` v0.7.0 to v0.7.4 by @raysan5
|
||||
[external] UPDATED: `m3d` to latest master by @raysan5
|
||||
[external] UPDATED: `qoi` to latest master by @raysan5
|
||||
[external] UPDATED: `qoa` to latest master by @raysan5
|
||||
[external] UPDATED: `stb_image_resize2` v2.12 to v2.18 by @raysan5
|
||||
|
||||
[misc] ADDED: SECURITY.md for security reporting policies by @raysan5
|
||||
[misc] ADDED: `examples/examples_list`, to be used by `rexm` or other tools by @raysan5
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ features
|
|||
- Written in plain C code (C99) using PascalCase/camelCase notation
|
||||
- Hardware accelerated with OpenGL: **1.1, 2.1, 3.3, 4.3, ES 2.0, ES 3.0**
|
||||
- **Unique OpenGL abstraction layer** (usable as standalone module): [rlgl](https://github.com/raysan5/raylib/blob/master/src/rlgl.h)
|
||||
- **Software Renderer** backend (no OpenGL required!): [rlsw](https://github.com/raysan5/raylib/blob/master/src/external/rlsw.h)
|
||||
- Multiple **Fonts** formats supported (TTF, OTF, FNT, BDF, sprite fonts)
|
||||
- Multiple texture formats supported, including **compressed formats** (DXT, ETC, ASTC)
|
||||
- **Full 3D support**, including 3D Shapes, Models, Billboards, Heightmaps and more!
|
||||
|
|
@ -61,7 +62,7 @@ This is a basic raylib example, it creates a window and draws the text `"Congrat
|
|||
|
||||
int main(void)
|
||||
{
|
||||
InitWindow(800, 450, "raylib [core] example - basic window");
|
||||
InitWindow(800, 450, "raylib example - basic window");
|
||||
|
||||
while (!WindowShouldClose())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ Here is a wishlist with features and ideas to improve the library. Note that fea
|
|||
- [GitHub PRs](https://github.com/raysan5/raylib/pulls) open with improvements to be reviewed.
|
||||
- [raylib source code](https://github.com/raysan5/raylib/tree/master/src) has multiple *TODO* comments around code with pending things to review or improve.
|
||||
- raylib wishlists discussions are open to everyone to ask for improvements, feel free to check and comment:
|
||||
- [raylib 7.0 wishlist](https://github.com/raysan5/raylib/discussions/5710)
|
||||
- [raylib 6.0 wishlist](https://github.com/raysan5/raylib/discussions/4660)
|
||||
- [raylib 5.0 wishlist](https://github.com/raysan5/raylib/discussions/2952)
|
||||
- [raylib wishlist 2022](https://github.com/raysan5/raylib/discussions/2272)
|
||||
|
|
@ -21,7 +22,7 @@ _Current version of raylib is complete and functional but there is always room f
|
|||
- [ ] `rcore_desktop_wayland`: Create additional platform backend: Linux/Wayland
|
||||
- [ ] `rcore`: Investigate alternative embedded platforms and realtime OSs
|
||||
- [ ] `rlsw`: Software renderer optimizations: mipmaps, platform-specific SIMD
|
||||
- [ ] `rtextures`: Consider moving N-patch system to separate example
|
||||
- [ ] `rtextures`: Consider removing N-patch system, provide as separate example
|
||||
- [ ] `rtextures`: Review blending modes system, provide more options or better samples
|
||||
- [ ] `rtext`: Investigate the recently opened [`Slug`](https://sluglibrary.com/) font rendering algorithm
|
||||
- [ ] `raudio`: Support microphone input, basic API to read microphone
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ const std = @import("std");
|
|||
const builtin = @import("builtin");
|
||||
|
||||
/// Minimum supported version of Zig
|
||||
const min_ver = "0.16.0-dev.2349+204fa8959";
|
||||
const min_ver = "0.16.0-dev.3013+abd131e33";
|
||||
|
||||
const emccOutputDir = "zig-out" ++ std.fs.path.sep_str ++ "htmlout" ++ std.fs.path.sep_str;
|
||||
const emccOutputFile = "index.html";
|
||||
|
|
@ -264,7 +264,10 @@ fn compileRaylib(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.
|
|||
|
||||
setDesktopPlatform(raylib, .android);
|
||||
} else {
|
||||
try c_source_files.append(b.allocator, "src/rglfw.c");
|
||||
switch (options.platform) {
|
||||
.glfw => try c_source_files.append(b.allocator, "src/rglfw.c"),
|
||||
.rgfw, .sdl, .drm, .android => {},
|
||||
}
|
||||
|
||||
if (options.linux_display_backend == .X11 or options.linux_display_backend == .Both) {
|
||||
raylib.root_module.addCMacro("_GLFW_X11", "");
|
||||
|
|
@ -434,6 +437,7 @@ pub const OpenglVersion = enum {
|
|||
};
|
||||
|
||||
pub const LinuxDisplayBackend = enum {
|
||||
None,
|
||||
X11,
|
||||
Wayland,
|
||||
Both,
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@
|
|||
|
||||
.dependencies = .{
|
||||
.xcode_frameworks = .{
|
||||
.url = "https://pkg.machengine.org/xcode-frameworks/9a45f3ac977fd25dff77e58c6de1870b6808c4a7.tar.gz",
|
||||
.hash = "122098b9174895f9708bc824b0f9e550c401892c40a900006459acf2cbf78acd99bb",
|
||||
.url = "https://pkg.machengine.org/xcode-frameworks/8a1cfb373587ea4c9bb1468b7c986462d8d4e10e.tar.gz",
|
||||
.hash = "N-V-__8AALShqgXkvqYU6f__FrA22SMWmi2TXCJjNTO1m8XJ",
|
||||
.lazy = true,
|
||||
},
|
||||
.emsdk = .{
|
||||
|
|
|
|||
|
|
@ -1153,7 +1153,10 @@ text/text_font_filters: text/text_font_filters.c
|
|||
--preload-file text/resources/KAISG.ttf@resources/KAISG.ttf
|
||||
|
||||
text/text_font_loading: text/text_font_loading.c
|
||||
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
|
||||
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
|
||||
--preload-file text/resources/pixantiqua.fnt@resources/pixantiqua.fnt \
|
||||
--preload-file text/resources/pixantiqua.png@resources/pixantiqua.png \
|
||||
--preload-file text/resources/pixantiqua.ttf@resources/pixantiqua.ttf
|
||||
|
||||
text/text_font_sdf: text/text_font_sdf.c
|
||||
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \
|
||||
|
|
|
|||
238
examples/audio/audio_amp_envelope.c
Normal file
238
examples/audio/audio_amp_envelope.c
Normal file
|
|
@ -0,0 +1,238 @@
|
|||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [audio] example - amp envelope
|
||||
*
|
||||
* Example complexity rating: [★☆☆☆] 1/4
|
||||
*
|
||||
* Example originally created with raylib 6.0, last time updated with raylib 6.0
|
||||
*
|
||||
* Example contributed by Arbinda Rizki Muhammad (@arbipink) 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) 2026 Arbinda Rizki Muhammad (@arbipink)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
#define RAYGUI_IMPLEMENTATION
|
||||
#include "raygui.h"
|
||||
|
||||
#include <math.h> // Required for: sinf()
|
||||
|
||||
#define BUFFER_SIZE 4096
|
||||
#define SAMPLE_RATE 44100
|
||||
|
||||
// Wave state
|
||||
typedef enum {
|
||||
IDLE,
|
||||
ATTACK,
|
||||
DECAY,
|
||||
SUSTAIN,
|
||||
RELEASE
|
||||
} ADSRState;
|
||||
|
||||
// Grouping all ADSR parameters and state into a struct
|
||||
typedef struct {
|
||||
float attackTime;
|
||||
float decayTime;
|
||||
float sustainLevel;
|
||||
float releaseTime;
|
||||
float currentValue;
|
||||
ADSRState state;
|
||||
} Envelope;
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Module Functions Declaration
|
||||
//------------------------------------------------------------------------------------
|
||||
static void FillAudioBuffer(int i, float *buffer, float envelopeValue, float *audioTime);
|
||||
static void UpdateEnvelope(Envelope *env);
|
||||
static void DrawADSRGraph(Envelope *env, Rectangle bounds);
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
//------------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [audio] example - amp envelope");
|
||||
|
||||
InitAudioDevice();
|
||||
|
||||
// Set the number of samples the stream will keep in memory at a time to BUFFER_SIZE
|
||||
SetAudioStreamBufferSizeDefault(BUFFER_SIZE);
|
||||
float buffer[BUFFER_SIZE] = { 0 };
|
||||
|
||||
// Init raw audio stream (sample rate: 44100, sample size: 32bit-float, channels: 1-mono)
|
||||
AudioStream stream = LoadAudioStream(SAMPLE_RATE, 32, 1);
|
||||
|
||||
// Init Phase
|
||||
float audioTime = 0.0f;
|
||||
|
||||
// Initialize the struct
|
||||
Envelope env = {
|
||||
.attackTime = 1.0f,
|
||||
.decayTime = 1.0f,
|
||||
.sustainLevel = 0.5f,
|
||||
.releaseTime = 1.0f,
|
||||
.currentValue = 0.0f,
|
||||
.state = IDLE
|
||||
};
|
||||
|
||||
SetTargetFPS(60);
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose())
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (IsKeyPressed(KEY_SPACE)) env.state = ATTACK;
|
||||
|
||||
if (IsKeyReleased(KEY_SPACE) && (env.state != IDLE)) env.state = RELEASE;
|
||||
|
||||
if (IsAudioStreamProcessed(stream))
|
||||
{
|
||||
if ((env.state != IDLE) || (env.currentValue > 0.0f))
|
||||
{
|
||||
for (int i = 0; i < BUFFER_SIZE; i++)
|
||||
{
|
||||
UpdateEnvelope(&env);
|
||||
FillAudioBuffer(i, buffer, env.currentValue, &audioTime);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Clear buffer if silent to avoid looping noise
|
||||
for (int i = 0; i < BUFFER_SIZE; i++) buffer[i] = 0;
|
||||
audioTime = 0.0f;
|
||||
}
|
||||
|
||||
UpdateAudioStream(stream, buffer, BUFFER_SIZE);
|
||||
}
|
||||
|
||||
if (!IsAudioStreamPlaying(stream)) PlayAudioStream(stream);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
GuiSliderBar((Rectangle){ 100, 60, 400, 30 }, "Attack (s)", TextFormat("%2.2fs", env.attackTime), &env.attackTime, 0.1f, 3.0f);
|
||||
GuiSliderBar((Rectangle){ 100, 100, 400, 30 }, "Decay (s)", TextFormat("%2.2fs", env.decayTime), &env.decayTime, 0.1f, 3.0f);
|
||||
GuiSliderBar((Rectangle){ 100, 140, 400, 30 }, "Sustain", TextFormat("%2.2f", env.sustainLevel), &env.sustainLevel, 0.0f, 1.0f);
|
||||
GuiSliderBar((Rectangle){ 100, 180, 400, 30 }, "Release (s)", TextFormat("%2.2fs", env.releaseTime), &env.releaseTime, 0.1f, 3.0f);
|
||||
|
||||
DrawADSRGraph(&env, (Rectangle){ 100, 250, 400, 100 });
|
||||
|
||||
DrawCircleV((Vector2){ 520, 350 - (env.currentValue * 100) }, 5, MAROON);
|
||||
DrawText(TextFormat("Current Gain: %2.2f", env.currentValue), 535, 345 - (env.currentValue * 100), 10, MAROON);
|
||||
|
||||
DrawText("Press SPACE to PLAY the sound!", 200, 400, 20, LIGHTGRAY);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadAudioStream(stream);
|
||||
CloseAudioDevice();
|
||||
|
||||
CloseWindow();
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Module Functions Definition
|
||||
//------------------------------------------------------------------------------------
|
||||
static void FillAudioBuffer(int i, float *buffer, float envelopeValue, float *audioTime)
|
||||
{
|
||||
int frequency = 440;
|
||||
buffer[i] = envelopeValue*sinf(2.0f*PI*frequency*(*audioTime));
|
||||
*audioTime += (1.0f/SAMPLE_RATE);
|
||||
}
|
||||
|
||||
static void UpdateEnvelope(Envelope *env)
|
||||
{
|
||||
// Calculate the time delta for ONE sample (1/44100)
|
||||
float sampleTime = 1.0f/SAMPLE_RATE;
|
||||
|
||||
switch(env->state)
|
||||
{
|
||||
case ATTACK:
|
||||
{
|
||||
env->currentValue += (1.0f/env->attackTime)*sampleTime;
|
||||
if (env->currentValue >= 1.0f)
|
||||
{
|
||||
env->currentValue = 1.0f;
|
||||
env->state = DECAY;
|
||||
}
|
||||
|
||||
} break;
|
||||
case DECAY:
|
||||
{
|
||||
env->currentValue -= ((1.0f - env->sustainLevel)/env->decayTime)*sampleTime;
|
||||
if (env->currentValue <= env->sustainLevel)
|
||||
{
|
||||
env->currentValue = env->sustainLevel;
|
||||
env->state = SUSTAIN;
|
||||
}
|
||||
|
||||
} break;
|
||||
case SUSTAIN:
|
||||
{
|
||||
env->currentValue = env->sustainLevel;
|
||||
|
||||
} break;
|
||||
case RELEASE:
|
||||
{
|
||||
env->currentValue -= (env->sustainLevel/env->releaseTime)*sampleTime;
|
||||
if (env->currentValue <= 0.001f) // Use a small threshold to avoid infinite tail
|
||||
{
|
||||
env->currentValue = 0.0f;
|
||||
env->state = IDLE;
|
||||
}
|
||||
|
||||
} break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
static void DrawADSRGraph(Envelope *env, Rectangle bounds)
|
||||
{
|
||||
DrawRectangleRec(bounds, Fade(LIGHTGRAY, 0.3f));
|
||||
DrawRectangleLinesEx(bounds, 1, GRAY);
|
||||
|
||||
// Fixed visual width for sustain stage since it's an amplitude not a time value
|
||||
float sustainWidth = 1.0f;
|
||||
|
||||
// Total time to visualize (sum of A, D, R + a padding for Sustain)
|
||||
float totalTime = env->attackTime + env->decayTime + sustainWidth + env->releaseTime;
|
||||
|
||||
float scaleX = bounds.width/totalTime;
|
||||
float scaleY = bounds.height;
|
||||
|
||||
Vector2 start = { bounds.x, bounds.y + bounds.height };
|
||||
Vector2 peak = { start.x + (env->attackTime*scaleX), bounds.y };
|
||||
Vector2 sustain = { peak.x + (env->decayTime*scaleX), bounds.y + (1.0f - env->sustainLevel)*scaleY };
|
||||
Vector2 rel = { sustain.x + (sustainWidth*scaleX), sustain.y };
|
||||
Vector2 end = { rel.x + (env->releaseTime*scaleX), bounds.y + bounds.height };
|
||||
|
||||
DrawLineV(start, peak, SKYBLUE);
|
||||
DrawLineV(peak, sustain, BLUE);
|
||||
DrawLineV(sustain, rel, DARKBLUE);
|
||||
DrawLineV(rel, end, ORANGE);
|
||||
|
||||
DrawText("ADSR Visualizer", bounds.x, bounds.y - 20, 10, DARKGRAY);
|
||||
}
|
||||
BIN
examples/audio/audio_amp_envelope.png
Normal file
BIN
examples/audio/audio_amp_envelope.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
6051
examples/audio/raygui.h
Normal file
6051
examples/audio/raygui.h
Normal file
File diff suppressed because it is too large
Load Diff
|
|
@ -108,7 +108,7 @@ int main(void)
|
|||
decalMaterial.maps[MATERIAL_MAP_DIFFUSE].color = RAYWHITE;
|
||||
|
||||
bool showModel = true;
|
||||
Model decalModels[MAX_DECALS] = { 0 };
|
||||
static Model decalModels[MAX_DECALS] = { 0 };
|
||||
int decalCount = 0;
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
#include "rlgl.h"
|
||||
|
||||
#include <stdlib.h> // Required for: rand()
|
||||
#include <math.h> // Required for: cosf(), sinf()
|
||||
|
|
@ -26,8 +27,9 @@
|
|||
//------------------------------------------------------------------------------------
|
||||
// Module Functions Declaration
|
||||
//------------------------------------------------------------------------------------
|
||||
// Generate mesh using points
|
||||
static Mesh GenMeshPoints(int numPoints);
|
||||
static Mesh GenMeshPoints(int numPoints); // Generate mesh using points
|
||||
void DrawModelPoints(Model model, Vector3 position, float scale, Color tint); // Draw a model as points
|
||||
void DrawModelPointsEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model as points with extended parameters
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Program main entry point
|
||||
|
|
@ -184,3 +186,30 @@ static Mesh GenMeshPoints(int numPoints)
|
|||
|
||||
return mesh;
|
||||
}
|
||||
|
||||
|
||||
// Draw a model points
|
||||
// WARNING: OpenGL ES 2.0 does not support point mode drawing
|
||||
void DrawModelPoints(Model model, Vector3 position, float scale, Color tint)
|
||||
{
|
||||
rlEnablePointMode();
|
||||
rlDisableBackfaceCulling();
|
||||
|
||||
DrawModel(model, position, scale, tint);
|
||||
|
||||
rlEnableBackfaceCulling();
|
||||
rlDisablePointMode();
|
||||
}
|
||||
|
||||
// Draw a model points
|
||||
// WARNING: OpenGL ES 2.0 does not support point mode drawing
|
||||
void DrawModelPointsEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint)
|
||||
{
|
||||
rlEnablePointMode();
|
||||
rlDisableBackfaceCulling();
|
||||
|
||||
DrawModelEx(model, position, rotationAxis, rotationAngle, scale, tint);
|
||||
|
||||
rlEnableBackfaceCulling();
|
||||
rlDisablePointMode();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,9 +13,9 @@
|
|||
| models/vox/chr_knight.vox | ❔ | ❔ | - |
|
||||
| models/vox/chr_sword.vox | ❔ | ❔ | - |
|
||||
| models/vox/monu9.vox | ❔ | ❔ | - |
|
||||
| billboard.png | [@emegeme](https://github.com/emegeme) | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | - |
|
||||
| billboard.png | [@raysan5](https://github.com/raysan5) | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | - |
|
||||
| cubicmap.png | [@raysan5](https://github.com/raysan5) | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | - |
|
||||
| cubicmap_atlas.png | [@emegeme](https://github.com/emegeme) | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | - |
|
||||
| cubicmap_atlas.png | [@raysan5](https://github.com/raysan5) | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | - |
|
||||
| heightmap.png | [@raysan5](https://github.com/raysan5) | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | - |
|
||||
| dresden_square_1k.hdr | [HDRIHaven](https://hdrihaven.com/hdri/?h=dresden_square) | [CC0](https://hdrihaven.com/p/license.php) | - |
|
||||
| dresden_square_2k.hdr | [HDRIHaven](https://hdrihaven.com/hdri/?h=dresden_square) | [CC0](https://hdrihaven.com/p/license.php) | - |
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ void main()
|
|||
|
||||
float specCo = 0.0;
|
||||
|
||||
if (NdotL > 0.0) specCo = pow(max(0.0, dot(viewDir, reflect(-lightDir, normal))), specularExponent); // 16 refers to shine
|
||||
if (NdotL > 0.0) specCo = pow(max(0.0, dot(viewDir, reflect(-lightDir, normal))), specularExponent);
|
||||
|
||||
specular += specCo;
|
||||
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ void main()
|
|||
|
||||
float specCo = 0.0;
|
||||
|
||||
if (NdotL > 0.0) specCo = pow(max(0.0, dot(viewDir, reflect(-lightDir, normal))), specularExponent); // 16 refers to shine
|
||||
if (NdotL > 0.0) specCo = pow(max(0.0, dot(viewDir, reflect(-lightDir, normal))), specularExponent);
|
||||
|
||||
specular += specCo;
|
||||
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ void main()
|
|||
|
||||
float specCo = 0.0;
|
||||
|
||||
if (NdotL > 0.0) specCo = pow(max(0.0, dot(viewDir, reflect(-lightDir, normal))), specularExponent); // 16 refers to shine
|
||||
if (NdotL > 0.0) specCo = pow(max(0.0, dot(viewDir, reflect(-lightDir, normal))), specularExponent);
|
||||
|
||||
specular += specCo;
|
||||
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ int main(void)
|
|||
// Set the texture tiling using a shader
|
||||
float tiling[2] = { 3.0f, 3.0f };
|
||||
Shader shader = LoadShader(0, TextFormat("resources/shaders/glsl%i/tiling.fs", GLSL_VERSION));
|
||||
SetTextureWrap(texture, TEXTURE_WRAP_REPEAT);
|
||||
SetShaderValue(shader, GetShaderLocation(shader, "tiling"), tiling, SHADER_UNIFORM_VEC2);
|
||||
model.materials[0].shader = shader;
|
||||
|
||||
|
|
|
|||
|
|
@ -38,12 +38,12 @@ int main(void)
|
|||
|
||||
// Define characters to draw
|
||||
// NOTE: raylib supports UTF-8 encoding, following list is actually codified as UTF8 internally
|
||||
const char msg[256] = "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHI\nJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmn\nopqrstuvwxyz{|}~¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓ\nÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷\nøùúûüýþÿ";
|
||||
const char msg[256] = "!#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHI\nJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmn\nopqrstuvwxyz{|}~¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓ\nÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷\nøùúûüýþÿ";
|
||||
|
||||
// NOTE: Textures/Fonts MUST be loaded after Window initialization (OpenGL context is required)
|
||||
|
||||
// BMFont (AngelCode) : Font data and image atlas have been generated using external program
|
||||
Font fontBm = LoadFont("resources/pixantiqua.fnt");
|
||||
Font fontBm = LoadFont("resources/pixantiqua.fnt"); // Requires "resources/pixantiqua.png"
|
||||
|
||||
// TTF font : Font data and atlas are generated directly from TTF
|
||||
// NOTE: We define a font base size of 32 pixels tall and up-to 250 characters
|
||||
|
|
|
|||
|
|
@ -2960,24 +2960,6 @@
|
|||
<Param name="Color tint" />
|
||||
</Overload>
|
||||
</KeyWord>
|
||||
<KeyWord name="DrawModelPoints" func="yes">
|
||||
<Overload retVal="void" descr="Draw a model as points">
|
||||
<Param name="Model model" />
|
||||
<Param name="Vector3 position" />
|
||||
<Param name="float scale" />
|
||||
<Param name="Color tint" />
|
||||
</Overload>
|
||||
</KeyWord>
|
||||
<KeyWord name="DrawModelPointsEx" func="yes">
|
||||
<Overload retVal="void" descr="Draw a model as points with extended parameters">
|
||||
<Param name="Model model" />
|
||||
<Param name="Vector3 position" />
|
||||
<Param name="Vector3 rotationAxis" />
|
||||
<Param name="float rotationAngle" />
|
||||
<Param name="Vector3 scale" />
|
||||
<Param name="Color tint" />
|
||||
</Overload>
|
||||
</KeyWord>
|
||||
<KeyWord name="DrawBoundingBox" func="yes">
|
||||
<Overload retVal="void" descr="Draw bounding box (wires)">
|
||||
<Param name="BoundingBox box" />
|
||||
|
|
@ -3013,7 +2995,7 @@
|
|||
<Param name="Vector2 size" />
|
||||
<Param name="Vector2 origin" />
|
||||
<Param name="float rotation" />
|
||||
<Param name="°ñ_)% " />
|
||||
<Param name="<EFBFBD><EFBFBD>_)% " />
|
||||
</Overload>
|
||||
</KeyWord>
|
||||
|
||||
|
|
|
|||
|
|
@ -600,8 +600,6 @@ RLAPI void DrawModel(Model model, Vector3 position, float scale, Color tint);
|
|||
RLAPI void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model with extended parameters
|
||||
RLAPI void DrawModelWires(Model model, Vector3 position, float scale, Color tint); // Draw a model wires (with texture if set)
|
||||
RLAPI void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model wires (with texture if set) with extended parameters
|
||||
RLAPI void DrawModelPoints(Model model, Vector3 position, float scale, Color tint); // Draw a model as points
|
||||
RLAPI void DrawModelPointsEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model as points with extended parameters
|
||||
RLAPI void DrawBoundingBox(BoundingBox box, Color color); // Draw bounding box (wires)
|
||||
RLAPI void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float scale, Color tint); // Draw a billboard texture
|
||||
RLAPI void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector2 size, Color tint); // Draw a billboard texture defined by source
|
||||
|
|
|
|||
209
src/external/cgltf.h
vendored
209
src/external/cgltf.h
vendored
|
|
@ -1,7 +1,7 @@
|
|||
/**
|
||||
* cgltf - a single-file glTF 2.0 parser written in C99.
|
||||
*
|
||||
* Version: 1.14
|
||||
* Version: 1.15
|
||||
*
|
||||
* Website: https://github.com/jkuhlmann/cgltf
|
||||
*
|
||||
|
|
@ -141,7 +141,7 @@ typedef struct cgltf_memory_options
|
|||
typedef struct cgltf_file_options
|
||||
{
|
||||
cgltf_result(*read)(const struct cgltf_memory_options* memory_options, const struct cgltf_file_options* file_options, const char* path, cgltf_size* size, void** data);
|
||||
void (*release)(const struct cgltf_memory_options* memory_options, const struct cgltf_file_options* file_options, void* data);
|
||||
void (*release)(const struct cgltf_memory_options* memory_options, const struct cgltf_file_options* file_options, void* data, cgltf_size size);
|
||||
void* user_data;
|
||||
} cgltf_file_options;
|
||||
|
||||
|
|
@ -296,6 +296,7 @@ typedef enum cgltf_meshopt_compression_filter {
|
|||
cgltf_meshopt_compression_filter_octahedral,
|
||||
cgltf_meshopt_compression_filter_quaternion,
|
||||
cgltf_meshopt_compression_filter_exponential,
|
||||
cgltf_meshopt_compression_filter_color,
|
||||
cgltf_meshopt_compression_filter_max_enum
|
||||
} cgltf_meshopt_compression_filter;
|
||||
|
||||
|
|
@ -308,6 +309,7 @@ typedef struct cgltf_meshopt_compression
|
|||
cgltf_size count;
|
||||
cgltf_meshopt_compression_mode mode;
|
||||
cgltf_meshopt_compression_filter filter;
|
||||
cgltf_bool is_khr;
|
||||
} cgltf_meshopt_compression;
|
||||
|
||||
typedef struct cgltf_buffer_view
|
||||
|
|
@ -376,13 +378,29 @@ typedef struct cgltf_image
|
|||
cgltf_extension* extensions;
|
||||
} cgltf_image;
|
||||
|
||||
typedef enum cgltf_filter_type {
|
||||
cgltf_filter_type_undefined = 0,
|
||||
cgltf_filter_type_nearest = 9728,
|
||||
cgltf_filter_type_linear = 9729,
|
||||
cgltf_filter_type_nearest_mipmap_nearest = 9984,
|
||||
cgltf_filter_type_linear_mipmap_nearest = 9985,
|
||||
cgltf_filter_type_nearest_mipmap_linear = 9986,
|
||||
cgltf_filter_type_linear_mipmap_linear = 9987
|
||||
} cgltf_filter_type;
|
||||
|
||||
typedef enum cgltf_wrap_mode {
|
||||
cgltf_wrap_mode_clamp_to_edge = 33071,
|
||||
cgltf_wrap_mode_mirrored_repeat = 33648,
|
||||
cgltf_wrap_mode_repeat = 10497
|
||||
} cgltf_wrap_mode;
|
||||
|
||||
typedef struct cgltf_sampler
|
||||
{
|
||||
char* name;
|
||||
cgltf_int mag_filter;
|
||||
cgltf_int min_filter;
|
||||
cgltf_int wrap_s;
|
||||
cgltf_int wrap_t;
|
||||
cgltf_filter_type mag_filter;
|
||||
cgltf_filter_type min_filter;
|
||||
cgltf_wrap_mode wrap_s;
|
||||
cgltf_wrap_mode wrap_t;
|
||||
cgltf_extras extras;
|
||||
cgltf_size extensions_count;
|
||||
cgltf_extension* extensions;
|
||||
|
|
@ -500,6 +518,14 @@ typedef struct cgltf_iridescence
|
|||
cgltf_texture_view iridescence_thickness_texture;
|
||||
} cgltf_iridescence;
|
||||
|
||||
typedef struct cgltf_diffuse_transmission
|
||||
{
|
||||
cgltf_texture_view diffuse_transmission_texture;
|
||||
cgltf_float diffuse_transmission_factor;
|
||||
cgltf_float diffuse_transmission_color_factor[3];
|
||||
cgltf_texture_view diffuse_transmission_color_texture;
|
||||
} cgltf_diffuse_transmission;
|
||||
|
||||
typedef struct cgltf_anisotropy
|
||||
{
|
||||
cgltf_float anisotropy_strength;
|
||||
|
|
@ -525,6 +551,7 @@ typedef struct cgltf_material
|
|||
cgltf_bool has_sheen;
|
||||
cgltf_bool has_emissive_strength;
|
||||
cgltf_bool has_iridescence;
|
||||
cgltf_bool has_diffuse_transmission;
|
||||
cgltf_bool has_anisotropy;
|
||||
cgltf_bool has_dispersion;
|
||||
cgltf_pbr_metallic_roughness pbr_metallic_roughness;
|
||||
|
|
@ -537,6 +564,7 @@ typedef struct cgltf_material
|
|||
cgltf_volume volume;
|
||||
cgltf_emissive_strength emissive_strength;
|
||||
cgltf_iridescence iridescence;
|
||||
cgltf_diffuse_transmission diffuse_transmission;
|
||||
cgltf_anisotropy anisotropy;
|
||||
cgltf_dispersion dispersion;
|
||||
cgltf_texture_view normal_texture;
|
||||
|
|
@ -743,6 +771,7 @@ typedef struct cgltf_data
|
|||
{
|
||||
cgltf_file_type file_type;
|
||||
void* file_data;
|
||||
cgltf_size file_size;
|
||||
|
||||
cgltf_asset asset;
|
||||
|
||||
|
|
@ -844,6 +873,8 @@ void cgltf_node_transform_world(const cgltf_node* node, cgltf_float* out_matrix)
|
|||
|
||||
const uint8_t* cgltf_buffer_view_data(const cgltf_buffer_view* view);
|
||||
|
||||
const cgltf_accessor* cgltf_find_accessor(const cgltf_primitive* prim, cgltf_attribute_type type, cgltf_int index);
|
||||
|
||||
cgltf_bool cgltf_accessor_read_float(const cgltf_accessor* accessor, cgltf_size index, cgltf_float* out, cgltf_size element_size);
|
||||
cgltf_bool cgltf_accessor_read_uint(const cgltf_accessor* accessor, cgltf_size index, cgltf_uint* out, cgltf_size element_size);
|
||||
cgltf_size cgltf_accessor_read_index(const cgltf_accessor* accessor, cgltf_size index);
|
||||
|
|
@ -1071,9 +1102,10 @@ static cgltf_result cgltf_default_file_read(const struct cgltf_memory_options* m
|
|||
return cgltf_result_success;
|
||||
}
|
||||
|
||||
static void cgltf_default_file_release(const struct cgltf_memory_options* memory_options, const struct cgltf_file_options* file_options, void* data)
|
||||
static void cgltf_default_file_release(const struct cgltf_memory_options* memory_options, const struct cgltf_file_options* file_options, void* data, cgltf_size size)
|
||||
{
|
||||
(void)file_options;
|
||||
(void)size;
|
||||
void (*memfree)(void*, void*) = memory_options->free_func ? memory_options->free_func : &cgltf_default_free;
|
||||
memfree(memory_options->user_data, data);
|
||||
}
|
||||
|
|
@ -1220,7 +1252,7 @@ cgltf_result cgltf_parse_file(const cgltf_options* options, const char* path, cg
|
|||
}
|
||||
|
||||
cgltf_result (*file_read)(const struct cgltf_memory_options*, const struct cgltf_file_options*, const char*, cgltf_size*, void**) = options->file.read ? options->file.read : &cgltf_default_file_read;
|
||||
void (*file_release)(const struct cgltf_memory_options*, const struct cgltf_file_options*, void* data) = options->file.release ? options->file.release : cgltf_default_file_release;
|
||||
void (*file_release)(const struct cgltf_memory_options*, const struct cgltf_file_options*, void* data, cgltf_size size) = options->file.release ? options->file.release : cgltf_default_file_release;
|
||||
|
||||
void* file_data = NULL;
|
||||
cgltf_size file_size = 0;
|
||||
|
|
@ -1234,11 +1266,12 @@ cgltf_result cgltf_parse_file(const cgltf_options* options, const char* path, cg
|
|||
|
||||
if (result != cgltf_result_success)
|
||||
{
|
||||
file_release(&options->memory, &options->file, file_data);
|
||||
file_release(&options->memory, &options->file, file_data, file_size);
|
||||
return result;
|
||||
}
|
||||
|
||||
(*out_data)->file_data = file_data;
|
||||
(*out_data)->file_size = file_size;
|
||||
|
||||
return cgltf_result_success;
|
||||
}
|
||||
|
|
@ -1630,8 +1663,8 @@ cgltf_result cgltf_validate(cgltf_data* data)
|
|||
CGLTF_ASSERT_IF((mc->mode == cgltf_meshopt_compression_mode_triangles || mc->mode == cgltf_meshopt_compression_mode_indices) && mc->filter != cgltf_meshopt_compression_filter_none, cgltf_result_invalid_gltf);
|
||||
|
||||
CGLTF_ASSERT_IF(mc->filter == cgltf_meshopt_compression_filter_octahedral && mc->stride != 4 && mc->stride != 8, cgltf_result_invalid_gltf);
|
||||
|
||||
CGLTF_ASSERT_IF(mc->filter == cgltf_meshopt_compression_filter_quaternion && mc->stride != 8, cgltf_result_invalid_gltf);
|
||||
CGLTF_ASSERT_IF(mc->filter == cgltf_meshopt_compression_filter_color && mc->stride != 4 && mc->stride != 8, cgltf_result_invalid_gltf);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1822,7 +1855,7 @@ void cgltf_free(cgltf_data* data)
|
|||
return;
|
||||
}
|
||||
|
||||
void (*file_release)(const struct cgltf_memory_options*, const struct cgltf_file_options*, void* data) = data->file.release ? data->file.release : cgltf_default_file_release;
|
||||
void (*file_release)(const struct cgltf_memory_options*, const struct cgltf_file_options*, void* data, cgltf_size size) = data->file.release ? data->file.release : cgltf_default_file_release;
|
||||
|
||||
data->memory.free_func(data->memory.user_data, data->asset.copyright);
|
||||
data->memory.free_func(data->memory.user_data, data->asset.generator);
|
||||
|
|
@ -1857,7 +1890,7 @@ void cgltf_free(cgltf_data* data)
|
|||
|
||||
if (data->buffers[i].data_free_method == cgltf_data_free_method_file_release)
|
||||
{
|
||||
file_release(&data->memory, &data->file, data->buffers[i].data);
|
||||
file_release(&data->memory, &data->file, data->buffers[i].data, data->buffers[i].size);
|
||||
}
|
||||
else if (data->buffers[i].data_free_method == cgltf_data_free_method_memory_free)
|
||||
{
|
||||
|
|
@ -2096,7 +2129,7 @@ void cgltf_free(cgltf_data* data)
|
|||
|
||||
data->memory.free_func(data->memory.user_data, data->extensions_required);
|
||||
|
||||
file_release(&data->memory, &data->file, data->file_data);
|
||||
file_release(&data->memory, &data->file, data->file_data, data->file_size);
|
||||
|
||||
data->memory.free_func(data->memory.user_data, data);
|
||||
}
|
||||
|
|
@ -2312,11 +2345,58 @@ const uint8_t* cgltf_buffer_view_data(const cgltf_buffer_view* view)
|
|||
return result;
|
||||
}
|
||||
|
||||
const cgltf_accessor* cgltf_find_accessor(const cgltf_primitive* prim, cgltf_attribute_type type, cgltf_int index)
|
||||
{
|
||||
for (cgltf_size i = 0; i < prim->attributes_count; ++i)
|
||||
{
|
||||
const cgltf_attribute* attr = &prim->attributes[i];
|
||||
if (attr->type == type && attr->index == index)
|
||||
return attr->data;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const uint8_t* cgltf_find_sparse_index(const cgltf_accessor* accessor, cgltf_size needle)
|
||||
{
|
||||
const cgltf_accessor_sparse* sparse = &accessor->sparse;
|
||||
const uint8_t* index_data = cgltf_buffer_view_data(sparse->indices_buffer_view);
|
||||
const uint8_t* value_data = cgltf_buffer_view_data(sparse->values_buffer_view);
|
||||
|
||||
if (index_data == NULL || value_data == NULL)
|
||||
return NULL;
|
||||
|
||||
index_data += sparse->indices_byte_offset;
|
||||
value_data += sparse->values_byte_offset;
|
||||
|
||||
cgltf_size index_stride = cgltf_component_size(sparse->indices_component_type);
|
||||
|
||||
cgltf_size offset = 0;
|
||||
cgltf_size length = sparse->count;
|
||||
|
||||
while (length)
|
||||
{
|
||||
cgltf_size rem = length % 2;
|
||||
length /= 2;
|
||||
|
||||
cgltf_size index = cgltf_component_read_index(index_data + (offset + length) * index_stride, sparse->indices_component_type);
|
||||
offset += index < needle ? length + rem : 0;
|
||||
}
|
||||
|
||||
if (offset == sparse->count)
|
||||
return NULL;
|
||||
|
||||
cgltf_size index = cgltf_component_read_index(index_data + offset * index_stride, sparse->indices_component_type);
|
||||
return index == needle ? value_data + offset * accessor->stride : NULL;
|
||||
}
|
||||
|
||||
cgltf_bool cgltf_accessor_read_float(const cgltf_accessor* accessor, cgltf_size index, cgltf_float* out, cgltf_size element_size)
|
||||
{
|
||||
if (accessor->is_sparse)
|
||||
{
|
||||
return 0;
|
||||
const uint8_t* element = cgltf_find_sparse_index(accessor, index);
|
||||
if (element)
|
||||
return cgltf_element_read_float(element, accessor->type, accessor->component_type, accessor->normalized, out, element_size);
|
||||
}
|
||||
if (accessor->buffer_view == NULL)
|
||||
{
|
||||
|
|
@ -2460,7 +2540,9 @@ cgltf_bool cgltf_accessor_read_uint(const cgltf_accessor* accessor, cgltf_size i
|
|||
{
|
||||
if (accessor->is_sparse)
|
||||
{
|
||||
return 0;
|
||||
const uint8_t* element = cgltf_find_sparse_index(accessor, index);
|
||||
if (element)
|
||||
return cgltf_element_read_uint(element, accessor->type, accessor->component_type, out, element_size);
|
||||
}
|
||||
if (accessor->buffer_view == NULL)
|
||||
{
|
||||
|
|
@ -2480,7 +2562,9 @@ cgltf_size cgltf_accessor_read_index(const cgltf_accessor* accessor, cgltf_size
|
|||
{
|
||||
if (accessor->is_sparse)
|
||||
{
|
||||
return 0; // This is an error case, but we can't communicate the error with existing interface.
|
||||
const uint8_t* element = cgltf_find_sparse_index(accessor, index);
|
||||
if (element)
|
||||
return cgltf_component_read_index(element, accessor->component_type);
|
||||
}
|
||||
if (accessor->buffer_view == NULL)
|
||||
{
|
||||
|
|
@ -2598,7 +2682,10 @@ cgltf_size cgltf_accessor_unpack_indices(const cgltf_accessor* accessor, void* o
|
|||
return accessor->count;
|
||||
}
|
||||
|
||||
index_count = accessor->count < index_count ? accessor->count : index_count;
|
||||
cgltf_size numbers_per_element = cgltf_num_components(accessor->type);
|
||||
cgltf_size available_numbers = accessor->count * numbers_per_element;
|
||||
|
||||
index_count = available_numbers < index_count ? available_numbers : index_count;
|
||||
cgltf_size index_component_size = cgltf_component_size(accessor->component_type);
|
||||
|
||||
if (accessor->is_sparse)
|
||||
|
|
@ -2620,15 +2707,23 @@ cgltf_size cgltf_accessor_unpack_indices(const cgltf_accessor* accessor, void* o
|
|||
}
|
||||
element += accessor->offset;
|
||||
|
||||
if (index_component_size == out_component_size && accessor->stride == out_component_size)
|
||||
if (index_component_size == out_component_size && accessor->stride == out_component_size * numbers_per_element)
|
||||
{
|
||||
memcpy(out, element, index_count * index_component_size);
|
||||
return index_count;
|
||||
}
|
||||
|
||||
// Data couldn't be copied with memcpy due to stride being larger than the component size.
|
||||
// OR
|
||||
// The component size of the output array is larger than the component size of the index data, so index data will be padded.
|
||||
switch (out_component_size)
|
||||
{
|
||||
case 1:
|
||||
for (cgltf_size index = 0; index < index_count; index++, element += accessor->stride)
|
||||
{
|
||||
((uint8_t*)out)[index] = (uint8_t)cgltf_component_read_index(element, accessor->component_type);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
for (cgltf_size index = 0; index < index_count; index++, element += accessor->stride)
|
||||
{
|
||||
|
|
@ -2642,7 +2737,7 @@ cgltf_size cgltf_accessor_unpack_indices(const cgltf_accessor* accessor, void* o
|
|||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return index_count;
|
||||
|
|
@ -4278,6 +4373,52 @@ static int cgltf_parse_json_iridescence(cgltf_options* options, jsmntok_t const*
|
|||
return i;
|
||||
}
|
||||
|
||||
static int cgltf_parse_json_diffuse_transmission(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_diffuse_transmission* out_diff_transmission)
|
||||
{
|
||||
CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
|
||||
int size = tokens[i].size;
|
||||
++i;
|
||||
|
||||
// Defaults
|
||||
cgltf_fill_float_array(out_diff_transmission->diffuse_transmission_color_factor, 3, 1.0f);
|
||||
out_diff_transmission->diffuse_transmission_factor = 0.f;
|
||||
|
||||
for (int j = 0; j < size; ++j)
|
||||
{
|
||||
CGLTF_CHECK_KEY(tokens[i]);
|
||||
|
||||
if (cgltf_json_strcmp(tokens + i, json_chunk, "diffuseTransmissionFactor") == 0)
|
||||
{
|
||||
++i;
|
||||
out_diff_transmission->diffuse_transmission_factor = cgltf_json_to_float(tokens + i, json_chunk);
|
||||
++i;
|
||||
}
|
||||
else if (cgltf_json_strcmp(tokens + i, json_chunk, "diffuseTransmissionTexture") == 0)
|
||||
{
|
||||
i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_diff_transmission->diffuse_transmission_texture);
|
||||
}
|
||||
else if (cgltf_json_strcmp(tokens + i, json_chunk, "diffuseTransmissionColorFactor") == 0)
|
||||
{
|
||||
i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_diff_transmission->diffuse_transmission_color_factor, 3);
|
||||
}
|
||||
else if (cgltf_json_strcmp(tokens + i, json_chunk, "diffuseTransmissionColorTexture") == 0)
|
||||
{
|
||||
i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_diff_transmission->diffuse_transmission_color_texture);
|
||||
}
|
||||
else
|
||||
{
|
||||
i = cgltf_skip_json(tokens, i + 1);
|
||||
}
|
||||
|
||||
if (i < 0)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static int cgltf_parse_json_anisotropy(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_anisotropy* out_anisotropy)
|
||||
{
|
||||
CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
|
||||
|
|
@ -4406,8 +4547,8 @@ static int cgltf_parse_json_sampler(cgltf_options* options, jsmntok_t const* tok
|
|||
(void)options;
|
||||
CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
|
||||
|
||||
out_sampler->wrap_s = 10497;
|
||||
out_sampler->wrap_t = 10497;
|
||||
out_sampler->wrap_s = cgltf_wrap_mode_repeat;
|
||||
out_sampler->wrap_t = cgltf_wrap_mode_repeat;
|
||||
|
||||
int size = tokens[i].size;
|
||||
++i;
|
||||
|
|
@ -4424,28 +4565,28 @@ static int cgltf_parse_json_sampler(cgltf_options* options, jsmntok_t const* tok
|
|||
{
|
||||
++i;
|
||||
out_sampler->mag_filter
|
||||
= cgltf_json_to_int(tokens + i, json_chunk);
|
||||
= (cgltf_filter_type)cgltf_json_to_int(tokens + i, json_chunk);
|
||||
++i;
|
||||
}
|
||||
else if (cgltf_json_strcmp(tokens + i, json_chunk, "minFilter") == 0)
|
||||
{
|
||||
++i;
|
||||
out_sampler->min_filter
|
||||
= cgltf_json_to_int(tokens + i, json_chunk);
|
||||
= (cgltf_filter_type)cgltf_json_to_int(tokens + i, json_chunk);
|
||||
++i;
|
||||
}
|
||||
else if (cgltf_json_strcmp(tokens + i, json_chunk, "wrapS") == 0)
|
||||
{
|
||||
++i;
|
||||
out_sampler->wrap_s
|
||||
= cgltf_json_to_int(tokens + i, json_chunk);
|
||||
= (cgltf_wrap_mode)cgltf_json_to_int(tokens + i, json_chunk);
|
||||
++i;
|
||||
}
|
||||
else if (cgltf_json_strcmp(tokens + i, json_chunk, "wrapT") == 0)
|
||||
{
|
||||
++i;
|
||||
out_sampler->wrap_t
|
||||
= cgltf_json_to_int(tokens + i, json_chunk);
|
||||
= (cgltf_wrap_mode)cgltf_json_to_int(tokens + i, json_chunk);
|
||||
++i;
|
||||
}
|
||||
else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
|
||||
|
|
@ -4766,6 +4907,11 @@ static int cgltf_parse_json_material(cgltf_options* options, jsmntok_t const* to
|
|||
out_material->has_iridescence = 1;
|
||||
i = cgltf_parse_json_iridescence(options, tokens, i + 1, json_chunk, &out_material->iridescence);
|
||||
}
|
||||
else if (cgltf_json_strcmp(tokens + i, json_chunk, "KHR_materials_diffuse_transmission") == 0)
|
||||
{
|
||||
out_material->has_diffuse_transmission = 1;
|
||||
i = cgltf_parse_json_diffuse_transmission(options, tokens, i + 1, json_chunk, &out_material->diffuse_transmission);
|
||||
}
|
||||
else if (cgltf_json_strcmp(tokens + i, json_chunk, "KHR_materials_anisotropy") == 0)
|
||||
{
|
||||
out_material->has_anisotropy = 1;
|
||||
|
|
@ -4974,6 +5120,10 @@ static int cgltf_parse_json_meshopt_compression(cgltf_options* options, jsmntok_
|
|||
{
|
||||
out_meshopt_compression->filter = cgltf_meshopt_compression_filter_exponential;
|
||||
}
|
||||
else if (cgltf_json_strcmp(tokens+i, json_chunk, "COLOR") == 0)
|
||||
{
|
||||
out_meshopt_compression->filter = cgltf_meshopt_compression_filter_color;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
else
|
||||
|
|
@ -5084,6 +5234,12 @@ static int cgltf_parse_json_buffer_view(cgltf_options* options, jsmntok_t const*
|
|||
out_buffer_view->has_meshopt_compression = 1;
|
||||
i = cgltf_parse_json_meshopt_compression(options, tokens, i + 1, json_chunk, &out_buffer_view->meshopt_compression);
|
||||
}
|
||||
else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_meshopt_compression") == 0)
|
||||
{
|
||||
out_buffer_view->has_meshopt_compression = 1;
|
||||
out_buffer_view->meshopt_compression.is_khr = 1;
|
||||
i = cgltf_parse_json_meshopt_compression(options, tokens, i + 1, json_chunk, &out_buffer_view->meshopt_compression);
|
||||
}
|
||||
else
|
||||
{
|
||||
i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_buffer_view->extensions[out_buffer_view->extensions_count++]));
|
||||
|
|
@ -6629,6 +6785,9 @@ static int cgltf_fixup_pointers(cgltf_data* data)
|
|||
CGLTF_PTRFIXUP(data->materials[i].iridescence.iridescence_texture.texture, data->textures, data->textures_count);
|
||||
CGLTF_PTRFIXUP(data->materials[i].iridescence.iridescence_thickness_texture.texture, data->textures, data->textures_count);
|
||||
|
||||
CGLTF_PTRFIXUP(data->materials[i].diffuse_transmission.diffuse_transmission_texture.texture, data->textures, data->textures_count);
|
||||
CGLTF_PTRFIXUP(data->materials[i].diffuse_transmission.diffuse_transmission_color_texture.texture, data->textures, data->textures_count);
|
||||
|
||||
CGLTF_PTRFIXUP(data->materials[i].anisotropy.anisotropy_texture.texture, data->textures, data->textures_count);
|
||||
}
|
||||
|
||||
|
|
|
|||
1565
src/external/cgltf_write.h
vendored
Normal file
1565
src/external/cgltf_write.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
256
src/external/dr_flac.h
vendored
256
src/external/dr_flac.h
vendored
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
FLAC audio decoder. Choice of public domain or MIT-0. See license statements at the end of this file.
|
||||
dr_flac - v0.13.0 - TBD
|
||||
dr_flac - v0.13.3 - 2026-01-17
|
||||
|
||||
David Reid - mackron@gmail.com
|
||||
|
||||
|
|
@ -126,7 +126,7 @@ extern "C" {
|
|||
|
||||
#define DRFLAC_VERSION_MAJOR 0
|
||||
#define DRFLAC_VERSION_MINOR 13
|
||||
#define DRFLAC_VERSION_REVISION 0
|
||||
#define DRFLAC_VERSION_REVISION 3
|
||||
#define DRFLAC_VERSION_STRING DRFLAC_XSTRINGIFY(DRFLAC_VERSION_MAJOR) "." DRFLAC_XSTRINGIFY(DRFLAC_VERSION_MINOR) "." DRFLAC_XSTRINGIFY(DRFLAC_VERSION_REVISION)
|
||||
|
||||
#include <stddef.h> /* For size_t. */
|
||||
|
|
@ -331,6 +331,12 @@ typedef struct
|
|||
*/
|
||||
drflac_uint32 type;
|
||||
|
||||
/* The size in bytes of the block and the buffer pointed to by pRawData if it's non-NULL. */
|
||||
drflac_uint32 rawDataSize;
|
||||
|
||||
/* The offset in the stream of the raw data. */
|
||||
drflac_uint64 rawDataOffset;
|
||||
|
||||
/*
|
||||
A pointer to the raw data. This points to a temporary buffer so don't hold on to it. It's best to
|
||||
not modify the contents of this buffer. Use the structures below for more meaningful and structured
|
||||
|
|
@ -338,9 +344,6 @@ typedef struct
|
|||
*/
|
||||
const void* pRawData;
|
||||
|
||||
/* The size in bytes of the block and the buffer pointed to by pRawData if it's non-NULL. */
|
||||
drflac_uint32 rawDataSize;
|
||||
|
||||
union
|
||||
{
|
||||
drflac_streaminfo streaminfo;
|
||||
|
|
@ -392,6 +395,7 @@ typedef struct
|
|||
drflac_uint32 colorDepth;
|
||||
drflac_uint32 indexColorCount;
|
||||
drflac_uint32 pictureDataSize;
|
||||
drflac_uint64 pictureDataOffset; /* Offset from the start of the stream. */
|
||||
const drflac_uint8* pPictureData;
|
||||
} picture;
|
||||
} data;
|
||||
|
|
@ -2712,9 +2716,17 @@ static DRFLAC_INLINE drflac_uint32 drflac__clz_lzcnt(drflac_cache_t x)
|
|||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#if defined(DRFLAC_X64)
|
||||
{
|
||||
/*
|
||||
A note on lzcnt.
|
||||
|
||||
We check for the presence of the lzcnt instruction at runtime before calling this function, but we still generate this code. I have had
|
||||
a report where the assembler does not recognize the lzcnt instruction. To work around this we are going to use `rep; bsr` instead which
|
||||
has an identical byte encoding as lzcnt, and should hopefully improve compatibility with older assemblers.
|
||||
*/
|
||||
drflac_uint64 r;
|
||||
__asm__ __volatile__ (
|
||||
"lzcnt{ %1, %0| %0, %1}" : "=r"(r) : "r"(x) : "cc"
|
||||
"rep; bsr{q %1, %0| %0, %1}" : "=r"(r) : "r"(x) : "cc"
|
||||
/*"lzcnt{ %1, %0| %0, %1}" : "=r"(r) : "r"(x) : "cc"*/
|
||||
);
|
||||
|
||||
return (drflac_uint32)r;
|
||||
|
|
@ -2723,12 +2735,13 @@ static DRFLAC_INLINE drflac_uint32 drflac__clz_lzcnt(drflac_cache_t x)
|
|||
{
|
||||
drflac_uint32 r;
|
||||
__asm__ __volatile__ (
|
||||
"lzcnt{l %1, %0| %0, %1}" : "=r"(r) : "r"(x) : "cc"
|
||||
"rep; bsr{l %1, %0| %0, %1}" : "=r"(r) : "r"(x) : "cc"
|
||||
/*"lzcnt{l %1, %0| %0, %1}" : "=r"(r) : "r"(x) : "cc"*/
|
||||
);
|
||||
|
||||
return r;
|
||||
}
|
||||
#elif defined(DRFLAC_ARM) && (defined(__ARM_ARCH) && __ARM_ARCH >= 5) && !defined(__ARM_ARCH_6M__) && !defined(DRFLAC_64BIT) /* <-- I haven't tested 64-bit inline assembly, so only enabling this for the 32-bit build for now. */
|
||||
#elif defined(DRFLAC_ARM) && (defined(__ARM_ARCH) && __ARM_ARCH >= 5) && !defined(__ARM_ARCH_6M__) && !(defined(__thumb__) && !defined(__thumb2__)) && !defined(DRFLAC_64BIT) /* <-- I haven't tested 64-bit inline assembly, so only enabling this for the 32-bit build for now. */
|
||||
{
|
||||
unsigned int r;
|
||||
__asm__ __volatile__ (
|
||||
|
|
@ -6434,8 +6447,9 @@ static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, d
|
|||
runningFilePos += 4;
|
||||
|
||||
metadata.type = blockType;
|
||||
metadata.pRawData = NULL;
|
||||
metadata.rawDataSize = 0;
|
||||
metadata.rawDataOffset = runningFilePos;
|
||||
metadata.pRawData = NULL;
|
||||
|
||||
switch (blockType)
|
||||
{
|
||||
|
|
@ -6712,59 +6726,151 @@ static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, d
|
|||
}
|
||||
|
||||
if (onMeta) {
|
||||
void* pRawData;
|
||||
const char* pRunningData;
|
||||
const char* pRunningDataEnd;
|
||||
drflac_bool32 result = DRFLAC_TRUE;
|
||||
drflac_uint32 blockSizeRemaining = blockSize;
|
||||
char* pMime = NULL;
|
||||
char* pDescription = NULL;
|
||||
void* pPictureData = NULL;
|
||||
|
||||
pRawData = drflac__malloc_from_callbacks(blockSize, pAllocationCallbacks);
|
||||
if (pRawData == NULL) {
|
||||
return DRFLAC_FALSE;
|
||||
if (blockSizeRemaining < 4 || onRead(pUserData, &metadata.data.picture.type, 4) != 4) {
|
||||
result = DRFLAC_FALSE;
|
||||
goto done_flac;
|
||||
}
|
||||
blockSizeRemaining -= 4;
|
||||
metadata.data.picture.type = drflac__be2host_32(metadata.data.picture.type);
|
||||
|
||||
|
||||
if (blockSizeRemaining < 4 || onRead(pUserData, &metadata.data.picture.mimeLength, 4) != 4) {
|
||||
result = DRFLAC_FALSE;
|
||||
goto done_flac;
|
||||
}
|
||||
blockSizeRemaining -= 4;
|
||||
metadata.data.picture.mimeLength = drflac__be2host_32(metadata.data.picture.mimeLength);
|
||||
|
||||
pMime = (char*)drflac__malloc_from_callbacks(metadata.data.picture.mimeLength + 1, pAllocationCallbacks); /* +1 for null terminator. */
|
||||
if (pMime == NULL) {
|
||||
result = DRFLAC_FALSE;
|
||||
goto done_flac;
|
||||
}
|
||||
|
||||
if (onRead(pUserData, pRawData, blockSize) != blockSize) {
|
||||
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
|
||||
return DRFLAC_FALSE;
|
||||
if (blockSizeRemaining < metadata.data.picture.mimeLength || onRead(pUserData, pMime, metadata.data.picture.mimeLength) != metadata.data.picture.mimeLength) {
|
||||
result = DRFLAC_FALSE;
|
||||
goto done_flac;
|
||||
}
|
||||
blockSizeRemaining -= metadata.data.picture.mimeLength;
|
||||
pMime[metadata.data.picture.mimeLength] = '\0'; /* Null terminate for safety. */
|
||||
metadata.data.picture.mime = (const char*)pMime;
|
||||
|
||||
|
||||
if (blockSizeRemaining < 4 || onRead(pUserData, &metadata.data.picture.descriptionLength, 4) != 4) {
|
||||
result = DRFLAC_FALSE;
|
||||
goto done_flac;
|
||||
}
|
||||
blockSizeRemaining -= 4;
|
||||
metadata.data.picture.descriptionLength = drflac__be2host_32(metadata.data.picture.descriptionLength);
|
||||
|
||||
pDescription = (char*)drflac__malloc_from_callbacks(metadata.data.picture.descriptionLength + 1, pAllocationCallbacks); /* +1 for null terminator. */
|
||||
if (pDescription == NULL) {
|
||||
result = DRFLAC_FALSE;
|
||||
goto done_flac;
|
||||
}
|
||||
|
||||
metadata.pRawData = pRawData;
|
||||
metadata.rawDataSize = blockSize;
|
||||
|
||||
pRunningData = (const char*)pRawData;
|
||||
pRunningDataEnd = (const char*)pRawData + blockSize;
|
||||
|
||||
metadata.data.picture.type = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
|
||||
metadata.data.picture.mimeLength = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
|
||||
|
||||
/* Need space for the rest of the block */
|
||||
if ((pRunningDataEnd - pRunningData) - 24 < (drflac_int64)metadata.data.picture.mimeLength) { /* <-- Note the order of operations to avoid overflow to a valid value */
|
||||
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
|
||||
return DRFLAC_FALSE;
|
||||
if (blockSizeRemaining < metadata.data.picture.descriptionLength || onRead(pUserData, pDescription, metadata.data.picture.descriptionLength) != metadata.data.picture.descriptionLength) {
|
||||
result = DRFLAC_FALSE;
|
||||
goto done_flac;
|
||||
}
|
||||
metadata.data.picture.mime = pRunningData; pRunningData += metadata.data.picture.mimeLength;
|
||||
metadata.data.picture.descriptionLength = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
|
||||
blockSizeRemaining -= metadata.data.picture.descriptionLength;
|
||||
pDescription[metadata.data.picture.descriptionLength] = '\0'; /* Null terminate for safety. */
|
||||
metadata.data.picture.description = (const char*)pDescription;
|
||||
|
||||
/* Need space for the rest of the block */
|
||||
if ((pRunningDataEnd - pRunningData) - 20 < (drflac_int64)metadata.data.picture.descriptionLength) { /* <-- Note the order of operations to avoid overflow to a valid value */
|
||||
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
|
||||
return DRFLAC_FALSE;
|
||||
|
||||
if (blockSizeRemaining < 4 || onRead(pUserData, &metadata.data.picture.width, 4) != 4) {
|
||||
result = DRFLAC_FALSE;
|
||||
goto done_flac;
|
||||
}
|
||||
metadata.data.picture.description = pRunningData; pRunningData += metadata.data.picture.descriptionLength;
|
||||
metadata.data.picture.width = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
|
||||
metadata.data.picture.height = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
|
||||
metadata.data.picture.colorDepth = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
|
||||
metadata.data.picture.indexColorCount = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
|
||||
metadata.data.picture.pictureDataSize = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
|
||||
metadata.data.picture.pPictureData = (const drflac_uint8*)pRunningData;
|
||||
blockSizeRemaining -= 4;
|
||||
metadata.data.picture.width = drflac__be2host_32(metadata.data.picture.width);
|
||||
|
||||
/* Need space for the picture after the block */
|
||||
if (pRunningDataEnd - pRunningData < (drflac_int64)metadata.data.picture.pictureDataSize) { /* <-- Note the order of operations to avoid overflow to a valid value */
|
||||
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
|
||||
return DRFLAC_FALSE;
|
||||
if (blockSizeRemaining < 4 || onRead(pUserData, &metadata.data.picture.height, 4) != 4) {
|
||||
result = DRFLAC_FALSE;
|
||||
goto done_flac;
|
||||
}
|
||||
blockSizeRemaining -= 4;
|
||||
metadata.data.picture.height = drflac__be2host_32(metadata.data.picture.height);
|
||||
|
||||
if (blockSizeRemaining < 4 || onRead(pUserData, &metadata.data.picture.colorDepth, 4) != 4) {
|
||||
result = DRFLAC_FALSE;
|
||||
goto done_flac;
|
||||
}
|
||||
blockSizeRemaining -= 4;
|
||||
metadata.data.picture.colorDepth = drflac__be2host_32(metadata.data.picture.colorDepth);
|
||||
|
||||
if (blockSizeRemaining < 4 || onRead(pUserData, &metadata.data.picture.indexColorCount, 4) != 4) {
|
||||
result = DRFLAC_FALSE;
|
||||
goto done_flac;
|
||||
}
|
||||
blockSizeRemaining -= 4;
|
||||
metadata.data.picture.indexColorCount = drflac__be2host_32(metadata.data.picture.indexColorCount);
|
||||
|
||||
|
||||
/* Picture data. */
|
||||
if (blockSizeRemaining < 4 || onRead(pUserData, &metadata.data.picture.pictureDataSize, 4) != 4) {
|
||||
result = DRFLAC_FALSE;
|
||||
goto done_flac;
|
||||
}
|
||||
blockSizeRemaining -= 4;
|
||||
metadata.data.picture.pictureDataSize = drflac__be2host_32(metadata.data.picture.pictureDataSize);
|
||||
|
||||
if (blockSizeRemaining < metadata.data.picture.pictureDataSize) {
|
||||
result = DRFLAC_FALSE;
|
||||
goto done_flac;
|
||||
}
|
||||
|
||||
/* For the actual image data we want to store the offset to the start of the stream. */
|
||||
metadata.data.picture.pictureDataOffset = runningFilePos + (blockSize - blockSizeRemaining);
|
||||
|
||||
/*
|
||||
For the allocation of image data, we can allow memory allocation to fail, in which case we just leave
|
||||
the pointer as null. If it fails, we need to fall back to seeking past the image data.
|
||||
*/
|
||||
#ifndef DR_FLAC_NO_PICTURE_METADATA_MALLOC
|
||||
pPictureData = drflac__malloc_from_callbacks(metadata.data.picture.pictureDataSize, pAllocationCallbacks);
|
||||
if (pPictureData != NULL) {
|
||||
if (onRead(pUserData, pPictureData, metadata.data.picture.pictureDataSize) != metadata.data.picture.pictureDataSize) {
|
||||
result = DRFLAC_FALSE;
|
||||
goto done_flac;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
/* Allocation failed. We need to seek past the picture data. */
|
||||
if (!onSeek(pUserData, metadata.data.picture.pictureDataSize, DRFLAC_SEEK_CUR)) {
|
||||
result = DRFLAC_FALSE;
|
||||
goto done_flac;
|
||||
}
|
||||
}
|
||||
|
||||
blockSizeRemaining -= metadata.data.picture.pictureDataSize;
|
||||
(void)blockSizeRemaining;
|
||||
|
||||
metadata.data.picture.pPictureData = (const drflac_uint8*)pPictureData;
|
||||
|
||||
|
||||
/* Only fire the callback if we actually have a way to read the image data. We must have either a valid offset, or a valid data pointer. */
|
||||
if (metadata.data.picture.pictureDataOffset != 0 || metadata.data.picture.pPictureData != NULL) {
|
||||
onMeta(pUserDataMD, &metadata);
|
||||
} else {
|
||||
/* Don't have a valid offset or data pointer, so just pretend we don't have a picture metadata. */
|
||||
}
|
||||
|
||||
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
|
||||
done_flac:
|
||||
drflac__free_from_callbacks(pMime, pAllocationCallbacks);
|
||||
drflac__free_from_callbacks(pDescription, pAllocationCallbacks);
|
||||
drflac__free_from_callbacks(pPictureData, pAllocationCallbacks);
|
||||
|
||||
if (result != DRFLAC_TRUE) {
|
||||
return DRFLAC_FALSE;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
|
|
@ -6800,14 +6906,17 @@ static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, d
|
|||
*/
|
||||
if (onMeta) {
|
||||
void* pRawData = drflac__malloc_from_callbacks(blockSize, pAllocationCallbacks);
|
||||
if (pRawData == NULL) {
|
||||
return DRFLAC_FALSE;
|
||||
}
|
||||
|
||||
if (pRawData != NULL) {
|
||||
if (onRead(pUserData, pRawData, blockSize) != blockSize) {
|
||||
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
|
||||
return DRFLAC_FALSE;
|
||||
}
|
||||
} else {
|
||||
/* Allocation failed. We need to seek past the block. */
|
||||
if (!onSeek(pUserData, blockSize, DRFLAC_SEEK_CUR)) {
|
||||
return DRFLAC_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
metadata.pRawData = pRawData;
|
||||
metadata.rawDataSize = blockSize;
|
||||
|
|
@ -8699,7 +8808,7 @@ static drflac_bool32 drflac__on_tell_stdio(void* pUserData, drflac_int64* pCurso
|
|||
DRFLAC_ASSERT(pFileStdio != NULL);
|
||||
DRFLAC_ASSERT(pCursor != NULL);
|
||||
|
||||
#if defined(_WIN32)
|
||||
#if defined(_WIN32) && !defined(NXDK)
|
||||
#if defined(_MSC_VER) && _MSC_VER > 1200
|
||||
result = _ftelli64(pFileStdio);
|
||||
#else
|
||||
|
|
@ -8821,8 +8930,6 @@ static drflac_bool32 drflac__on_seek_memory(void* pUserData, int offset, drflac_
|
|||
|
||||
DRFLAC_ASSERT(memoryStream != NULL);
|
||||
|
||||
newCursor = memoryStream->currentReadPos;
|
||||
|
||||
if (origin == DRFLAC_SEEK_SET) {
|
||||
newCursor = 0;
|
||||
} else if (origin == DRFLAC_SEEK_CUR) {
|
||||
|
|
@ -11702,16 +11809,14 @@ static type* drflac__full_read_and_close_ ## extension (drflac* pFlac, unsigned
|
|||
{ \
|
||||
type* pSampleData = NULL; \
|
||||
drflac_uint64 totalPCMFrameCount; \
|
||||
\
|
||||
DRFLAC_ASSERT(pFlac != NULL); \
|
||||
\
|
||||
totalPCMFrameCount = pFlac->totalPCMFrameCount; \
|
||||
\
|
||||
if (totalPCMFrameCount == 0) { \
|
||||
type buffer[4096]; \
|
||||
drflac_uint64 pcmFramesRead; \
|
||||
size_t sampleDataBufferSize = sizeof(buffer); \
|
||||
\
|
||||
DRFLAC_ASSERT(pFlac != NULL); \
|
||||
\
|
||||
totalPCMFrameCount = 0; \
|
||||
\
|
||||
pSampleData = (type*)drflac__malloc_from_callbacks(sampleDataBufferSize, &pFlac->allocationCallbacks); \
|
||||
if (pSampleData == NULL) { \
|
||||
goto on_error; \
|
||||
|
|
@ -11740,19 +11845,6 @@ static type* drflac__full_read_and_close_ ## extension (drflac* pFlac, unsigned
|
|||
/* At this point everything should be decoded, but we just want to fill the unused part buffer with silence - need to \
|
||||
protect those ears from random noise! */ \
|
||||
DRFLAC_ZERO_MEMORY(pSampleData + (totalPCMFrameCount*pFlac->channels), (size_t)(sampleDataBufferSize - totalPCMFrameCount*pFlac->channels*sizeof(type))); \
|
||||
} else { \
|
||||
drflac_uint64 dataSize = totalPCMFrameCount*pFlac->channels*sizeof(type); \
|
||||
if (dataSize > (drflac_uint64)DRFLAC_SIZE_MAX) { \
|
||||
goto on_error; /* The decoded data is too big. */ \
|
||||
} \
|
||||
\
|
||||
pSampleData = (type*)drflac__malloc_from_callbacks((size_t)dataSize, &pFlac->allocationCallbacks); /* <-- Safe cast as per the check above. */ \
|
||||
if (pSampleData == NULL) { \
|
||||
goto on_error; \
|
||||
} \
|
||||
\
|
||||
totalPCMFrameCount = drflac_read_pcm_frames_##extension(pFlac, pFlac->totalPCMFrameCount, pSampleData); \
|
||||
} \
|
||||
\
|
||||
if (sampleRateOut) *sampleRateOut = pFlac->sampleRate; \
|
||||
if (channelsOut) *channelsOut = pFlac->channels; \
|
||||
|
|
@ -12077,7 +12169,19 @@ DRFLAC_API drflac_bool32 drflac_next_cuesheet_track(drflac_cuesheet_track_iterat
|
|||
/*
|
||||
REVISION HISTORY
|
||||
================
|
||||
v0.13.0 - TBD
|
||||
v0.13.3 - 2026-01-17
|
||||
- Fix a compiler compatibility issue with some inlined assembly.
|
||||
- Fix a compilation warning.
|
||||
|
||||
v0.13.2 - 2025-12-02
|
||||
- Improve robustness of the parsing of picture metadata to improve support for memory constrained embedded devices.
|
||||
- Fix a warning about an assigned by unused variable.
|
||||
- Improvements to drflac_open_and_read_pcm_frames_*() and family to avoid excessively large memory allocations from malformed files.
|
||||
|
||||
v0.13.1 - 2025-09-10
|
||||
- Fix an error with the NXDK build.
|
||||
|
||||
v0.13.0 - 2025-07-23
|
||||
- API CHANGE: Seek origin enums have been renamed to match the naming convention used by other dr_libs libraries:
|
||||
- drflac_seek_origin_start -> DRFLAC_SEEK_SET
|
||||
- drflac_seek_origin_current -> DRFLAC_SEEK_CUR
|
||||
|
|
|
|||
143
src/external/dr_mp3.h
vendored
143
src/external/dr_mp3.h
vendored
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
MP3 audio decoder. Choice of public domain or MIT-0. See license statements at the end of this file.
|
||||
dr_mp3 - v0.7.0 - TBD
|
||||
dr_mp3 - v0.7.4 - TBD
|
||||
|
||||
David Reid - mackron@gmail.com
|
||||
|
||||
|
|
@ -72,7 +72,7 @@ extern "C" {
|
|||
|
||||
#define DRMP3_VERSION_MAJOR 0
|
||||
#define DRMP3_VERSION_MINOR 7
|
||||
#define DRMP3_VERSION_REVISION 0
|
||||
#define DRMP3_VERSION_REVISION 4
|
||||
#define DRMP3_VERSION_STRING DRMP3_XSTRINGIFY(DRMP3_VERSION_MAJOR) "." DRMP3_XSTRINGIFY(DRMP3_VERSION_MINOR) "." DRMP3_XSTRINGIFY(DRMP3_VERSION_REVISION)
|
||||
|
||||
#include <stddef.h> /* For size_t. */
|
||||
|
|
@ -257,16 +257,45 @@ typedef struct
|
|||
Low Level Push API
|
||||
==================
|
||||
*/
|
||||
#define DRMP3_MAX_BITRESERVOIR_BYTES 511
|
||||
#define DRMP3_MAX_FREE_FORMAT_FRAME_SIZE 2304 /* more than ISO spec's */
|
||||
#define DRMP3_MAX_L3_FRAME_PAYLOAD_BYTES DRMP3_MAX_FREE_FORMAT_FRAME_SIZE /* MUST be >= 320000/8/32000*1152 = 1440 */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int frame_bytes, channels, sample_rate, layer, bitrate_kbps;
|
||||
} drmp3dec_frame_info;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const drmp3_uint8 *buf;
|
||||
int pos, limit;
|
||||
} drmp3_bs;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const drmp3_uint8 *sfbtab;
|
||||
drmp3_uint16 part_23_length, big_values, scalefac_compress;
|
||||
drmp3_uint8 global_gain, block_type, mixed_block_flag, n_long_sfb, n_short_sfb;
|
||||
drmp3_uint8 table_select[3], region_count[3], subblock_gain[3];
|
||||
drmp3_uint8 preflag, scalefac_scale, count1_table, scfsi;
|
||||
} drmp3_L3_gr_info;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
drmp3_bs bs;
|
||||
drmp3_uint8 maindata[DRMP3_MAX_BITRESERVOIR_BYTES + DRMP3_MAX_L3_FRAME_PAYLOAD_BYTES];
|
||||
drmp3_L3_gr_info gr_info[4];
|
||||
float grbuf[2][576], scf[40], syn[18 + 15][2*32];
|
||||
drmp3_uint8 ist_pos[2][39];
|
||||
} drmp3dec_scratch;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float mdct_overlap[2][9*32], qmf_state[15*2*32];
|
||||
int reserv, free_format_bytes;
|
||||
drmp3_uint8 header[4], reserv_buf[511];
|
||||
drmp3dec_scratch scratch;
|
||||
} drmp3dec;
|
||||
|
||||
/* Initializes a low level decoder. */
|
||||
|
|
@ -592,14 +621,10 @@ DRMP3_API const char* drmp3_version_string(void)
|
|||
|
||||
#define DRMP3_OFFSET_PTR(p, offset) ((void*)((drmp3_uint8*)(p) + (offset)))
|
||||
|
||||
#define DRMP3_MAX_FREE_FORMAT_FRAME_SIZE 2304 /* more than ISO spec's */
|
||||
#ifndef DRMP3_MAX_FRAME_SYNC_MATCHES
|
||||
#define DRMP3_MAX_FRAME_SYNC_MATCHES 10
|
||||
#endif
|
||||
|
||||
#define DRMP3_MAX_L3_FRAME_PAYLOAD_BYTES DRMP3_MAX_FREE_FORMAT_FRAME_SIZE /* MUST be >= 320000/8/32000*1152 = 1440 */
|
||||
|
||||
#define DRMP3_MAX_BITRESERVOIR_BYTES 511
|
||||
#define DRMP3_SHORT_BLOCK_TYPE 2
|
||||
#define DRMP3_STOP_BLOCK_TYPE 3
|
||||
#define DRMP3_MODE_MONO 3
|
||||
|
|
@ -632,8 +657,10 @@ DRMP3_API const char* drmp3_version_string(void)
|
|||
|
||||
#if !defined(DR_MP3_NO_SIMD)
|
||||
|
||||
#if !defined(DR_MP3_ONLY_SIMD) && (defined(_M_X64) || defined(__x86_64__) || defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC))
|
||||
/* x64 always have SSE2, arm64 always have neon, no need for generic code */
|
||||
#if !defined(DR_MP3_ONLY_SIMD) && ((defined(_MSC_VER) && _MSC_VER >= 1400) && defined(_M_X64)) || ((defined(__i386) || defined(_M_IX86) || defined(__i386__) || defined(__x86_64__)) && ((defined(_M_IX86_FP) && _M_IX86_FP == 2) || defined(__SSE2__)))
|
||||
#define DR_MP3_ONLY_SIMD
|
||||
#endif
|
||||
#if !defined(DR_MP3_ONLY_SIMD) && (defined(__ARM_NEON) || defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC))
|
||||
#define DR_MP3_ONLY_SIMD
|
||||
#endif
|
||||
|
||||
|
|
@ -655,7 +682,7 @@ DRMP3_API const char* drmp3_version_string(void)
|
|||
#define DRMP3_VMUL_S(x, s) _mm_mul_ps(x, _mm_set1_ps(s))
|
||||
#define DRMP3_VREV(x) _mm_shuffle_ps(x, x, _MM_SHUFFLE(0, 1, 2, 3))
|
||||
typedef __m128 drmp3_f4;
|
||||
#if defined(_MSC_VER) || defined(DR_MP3_ONLY_SIMD)
|
||||
#if (defined(_MSC_VER) || defined(DR_MP3_ONLY_SIMD)) && !defined(__clang__)
|
||||
#define drmp3_cpuid __cpuid
|
||||
#else
|
||||
static __inline__ __attribute__((always_inline)) void drmp3_cpuid(int CPUInfo[], const int InfoType)
|
||||
|
|
@ -779,11 +806,7 @@ static __inline__ __attribute__((always_inline)) drmp3_int32 drmp3_clip_int16_ar
|
|||
#define DRMP3_FREE(p) free((p))
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const drmp3_uint8 *buf;
|
||||
int pos, limit;
|
||||
} drmp3_bs;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
|
@ -796,24 +819,6 @@ typedef struct
|
|||
drmp3_uint8 tab_offset, code_tab_width, band_count;
|
||||
} drmp3_L12_subband_alloc;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const drmp3_uint8 *sfbtab;
|
||||
drmp3_uint16 part_23_length, big_values, scalefac_compress;
|
||||
drmp3_uint8 global_gain, block_type, mixed_block_flag, n_long_sfb, n_short_sfb;
|
||||
drmp3_uint8 table_select[3], region_count[3], subblock_gain[3];
|
||||
drmp3_uint8 preflag, scalefac_scale, count1_table, scfsi;
|
||||
} drmp3_L3_gr_info;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
drmp3_bs bs;
|
||||
drmp3_uint8 maindata[DRMP3_MAX_BITRESERVOIR_BYTES + DRMP3_MAX_L3_FRAME_PAYLOAD_BYTES];
|
||||
drmp3_L3_gr_info gr_info[4];
|
||||
float grbuf[2][576], scf[40], syn[18 + 15][2*32];
|
||||
drmp3_uint8 ist_pos[2][39];
|
||||
} drmp3dec_scratch;
|
||||
|
||||
static void drmp3_bs_init(drmp3_bs *bs, const drmp3_uint8 *data, int bytes)
|
||||
{
|
||||
bs->buf = data;
|
||||
|
|
@ -1227,6 +1232,14 @@ static float drmp3_L3_ldexp_q2(float y, int exp_q2)
|
|||
return y;
|
||||
}
|
||||
|
||||
/*
|
||||
I've had reports of GCC 14 throwing an incorrect -Wstringop-overflow warning here. This is an attempt
|
||||
to silence this warning.
|
||||
*/
|
||||
#if (defined(__GNUC__) && (__GNUC__ >= 13)) && !defined(__clang__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wstringop-overflow"
|
||||
#endif
|
||||
static void drmp3_L3_decode_scalefactors(const drmp3_uint8 *hdr, drmp3_uint8 *ist_pos, drmp3_bs *bs, const drmp3_L3_gr_info *gr, float *scf, int ch)
|
||||
{
|
||||
static const drmp3_uint8 g_scf_partitions[3][28] = {
|
||||
|
|
@ -1288,6 +1301,9 @@ static void drmp3_L3_decode_scalefactors(const drmp3_uint8 *hdr, drmp3_uint8 *is
|
|||
scf[i] = drmp3_L3_ldexp_q2(gain, iscf[i] << scf_shift);
|
||||
}
|
||||
}
|
||||
#if (defined(__GNUC__) && (__GNUC__ >= 13)) && !defined(__clang__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
static const float g_drmp3_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,
|
||||
|
|
@ -2299,7 +2315,6 @@ DRMP3_API int drmp3dec_decode_frame(drmp3dec *dec, const drmp3_uint8 *mp3, int m
|
|||
int i = 0, igr, frame_size = 0, success = 1;
|
||||
const drmp3_uint8 *hdr;
|
||||
drmp3_bs bs_frame[1];
|
||||
drmp3dec_scratch scratch;
|
||||
|
||||
if (mp3_bytes > 4 && dec->header[0] == 0xff && drmp3_hdr_compare(dec->header, mp3))
|
||||
{
|
||||
|
|
@ -2336,23 +2351,23 @@ DRMP3_API int drmp3dec_decode_frame(drmp3dec *dec, const drmp3_uint8 *mp3, int m
|
|||
|
||||
if (info->layer == 3)
|
||||
{
|
||||
int main_data_begin = drmp3_L3_read_side_info(bs_frame, scratch.gr_info, hdr);
|
||||
int main_data_begin = drmp3_L3_read_side_info(bs_frame, dec->scratch.gr_info, hdr);
|
||||
if (main_data_begin < 0 || bs_frame->pos > bs_frame->limit)
|
||||
{
|
||||
drmp3dec_init(dec);
|
||||
return 0;
|
||||
}
|
||||
success = drmp3_L3_restore_reservoir(dec, bs_frame, &scratch, main_data_begin);
|
||||
success = drmp3_L3_restore_reservoir(dec, bs_frame, &dec->scratch, main_data_begin);
|
||||
if (success && pcm != NULL)
|
||||
{
|
||||
for (igr = 0; igr < (DRMP3_HDR_TEST_MPEG1(hdr) ? 2 : 1); igr++, pcm = DRMP3_OFFSET_PTR(pcm, sizeof(drmp3d_sample_t)*576*info->channels))
|
||||
{
|
||||
DRMP3_ZERO_MEMORY(scratch.grbuf[0], 576*2*sizeof(float));
|
||||
drmp3_L3_decode(dec, &scratch, scratch.gr_info + igr*info->channels, info->channels);
|
||||
drmp3d_synth_granule(dec->qmf_state, scratch.grbuf[0], 18, info->channels, (drmp3d_sample_t*)pcm, scratch.syn[0]);
|
||||
DRMP3_ZERO_MEMORY(dec->scratch.grbuf[0], 576*2*sizeof(float));
|
||||
drmp3_L3_decode(dec, &dec->scratch, dec->scratch.gr_info + igr*info->channels, info->channels);
|
||||
drmp3d_synth_granule(dec->qmf_state, dec->scratch.grbuf[0], 18, info->channels, (drmp3d_sample_t*)pcm, dec->scratch.syn[0]);
|
||||
}
|
||||
}
|
||||
drmp3_L3_save_reservoir(dec, &scratch);
|
||||
drmp3_L3_save_reservoir(dec, &dec->scratch);
|
||||
} else
|
||||
{
|
||||
#ifdef DR_MP3_ONLY_MP3
|
||||
|
|
@ -2366,15 +2381,15 @@ DRMP3_API int drmp3dec_decode_frame(drmp3dec *dec, const drmp3_uint8 *mp3, int m
|
|||
|
||||
drmp3_L12_read_scale_info(hdr, bs_frame, sci);
|
||||
|
||||
DRMP3_ZERO_MEMORY(scratch.grbuf[0], 576*2*sizeof(float));
|
||||
DRMP3_ZERO_MEMORY(dec->scratch.grbuf[0], 576*2*sizeof(float));
|
||||
for (i = 0, igr = 0; igr < 3; igr++)
|
||||
{
|
||||
if (12 == (i += drmp3_L12_dequantize_granule(scratch.grbuf[0] + i, bs_frame, sci, info->layer | 1)))
|
||||
if (12 == (i += drmp3_L12_dequantize_granule(dec->scratch.grbuf[0] + i, bs_frame, sci, info->layer | 1)))
|
||||
{
|
||||
i = 0;
|
||||
drmp3_L12_apply_scf_384(sci, sci->scf + igr, scratch.grbuf[0]);
|
||||
drmp3d_synth_granule(dec->qmf_state, scratch.grbuf[0], 12, info->channels, (drmp3d_sample_t*)pcm, scratch.syn[0]);
|
||||
DRMP3_ZERO_MEMORY(scratch.grbuf[0], 576*2*sizeof(float));
|
||||
drmp3_L12_apply_scf_384(sci, sci->scf + igr, dec->scratch.grbuf[0]);
|
||||
drmp3d_synth_granule(dec->qmf_state, dec->scratch.grbuf[0], 12, info->channels, (drmp3d_sample_t*)pcm, dec->scratch.syn[0]);
|
||||
DRMP3_ZERO_MEMORY(dec->scratch.grbuf[0], 576*2*sizeof(float));
|
||||
pcm = DRMP3_OFFSET_PTR(pcm, sizeof(drmp3d_sample_t)*384*info->channels);
|
||||
}
|
||||
if (bs_frame->pos > bs_frame->limit)
|
||||
|
|
@ -3005,6 +3020,7 @@ static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drm
|
|||
((drmp3_uint32)ape[26] << 16) |
|
||||
((drmp3_uint32)ape[27] << 24);
|
||||
|
||||
if (32 + tagSize < streamLen) {
|
||||
streamEndOffset -= 32 + tagSize;
|
||||
streamLen -= 32 + tagSize;
|
||||
|
||||
|
|
@ -3023,6 +3039,9 @@ static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drm
|
|||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* The tag size is larger than the stream. Invalid APE tag. */
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
@ -3153,7 +3172,6 @@ static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drm
|
|||
{
|
||||
drmp3_bs bs;
|
||||
drmp3_L3_gr_info grInfo[4];
|
||||
const drmp3_uint8* pTagData = pFirstFrameData;
|
||||
|
||||
drmp3_bs_init(&bs, pFirstFrameData + DRMP3_HDR_SIZE, firstFrameInfo.frame_bytes - DRMP3_HDR_SIZE);
|
||||
|
||||
|
|
@ -3164,6 +3182,7 @@ static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drm
|
|||
if (drmp3_L3_read_side_info(&bs, grInfo, pFirstFrameData) >= 0) {
|
||||
drmp3_bool32 isXing = DRMP3_FALSE;
|
||||
drmp3_bool32 isInfo = DRMP3_FALSE;
|
||||
const drmp3_uint8* pTagData;
|
||||
const drmp3_uint8* pTagDataBeg;
|
||||
|
||||
pTagDataBeg = pFirstFrameData + DRMP3_HDR_SIZE + (bs.pos/8);
|
||||
|
|
@ -3246,6 +3265,13 @@ static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drm
|
|||
/* The start offset needs to be moved to the end of this frame so it's not included in any audio processing after seeking. */
|
||||
pMP3->streamStartOffset += (drmp3_uint32)(firstFrameInfo.frame_bytes);
|
||||
pMP3->streamCursor = pMP3->streamStartOffset;
|
||||
|
||||
/*
|
||||
The internal decoder needs to be reset to clear out any state. If we don't reset this state, it's possible for
|
||||
there to be inconsistencies in the number of samples read when reading to the end of the stream depending on
|
||||
whether or not the caller seeks to the start of the stream.
|
||||
*/
|
||||
drmp3dec_init(&pMP3->decoder);
|
||||
}
|
||||
} else {
|
||||
/* Failed to read the side info. */
|
||||
|
|
@ -3307,8 +3333,6 @@ static drmp3_bool32 drmp3__on_seek_memory(void* pUserData, int byteOffset, drmp3
|
|||
|
||||
DRMP3_ASSERT(pMP3 != NULL);
|
||||
|
||||
newCursor = pMP3->memory.currentReadPos;
|
||||
|
||||
if (origin == DRMP3_SEEK_SET) {
|
||||
newCursor = 0;
|
||||
} else if (origin == DRMP3_SEEK_CUR) {
|
||||
|
|
@ -3981,7 +4005,7 @@ static drmp3_bool32 drmp3__on_tell_stdio(void* pUserData, drmp3_int64* pCursor)
|
|||
DRMP3_ASSERT(pFileStdio != NULL);
|
||||
DRMP3_ASSERT(pCursor != NULL);
|
||||
|
||||
#if defined(_WIN32)
|
||||
#if defined(_WIN32) && !defined(NXDK)
|
||||
#if defined(_MSC_VER) && _MSC_VER > 1200
|
||||
result = _ftelli64(pFileStdio);
|
||||
#else
|
||||
|
|
@ -4780,6 +4804,8 @@ static float* drmp3__full_read_and_close_f32(drmp3* pMP3, drmp3_config* pConfig,
|
|||
pNewFrames = (float*)drmp3__realloc_from_callbacks(pFrames, (size_t)newFramesBufferSize, (size_t)oldFramesBufferSize, &pMP3->allocationCallbacks);
|
||||
if (pNewFrames == NULL) {
|
||||
drmp3__free_from_callbacks(pFrames, &pMP3->allocationCallbacks);
|
||||
pFrames = NULL;
|
||||
totalFramesRead = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -4847,6 +4873,8 @@ static drmp3_int16* drmp3__full_read_and_close_s16(drmp3* pMP3, drmp3_config* pC
|
|||
pNewFrames = (drmp3_int16*)drmp3__realloc_from_callbacks(pFrames, (size_t)newFramesBufferSize, (size_t)oldFramesBufferSize, &pMP3->allocationCallbacks);
|
||||
if (pNewFrames == NULL) {
|
||||
drmp3__free_from_callbacks(pFrames, &pMP3->allocationCallbacks);
|
||||
pFrames = NULL;
|
||||
totalFramesRead = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -4981,7 +5009,24 @@ DIFFERENCES BETWEEN minimp3 AND dr_mp3
|
|||
/*
|
||||
REVISION HISTORY
|
||||
================
|
||||
v0.7.0 - TBD
|
||||
v0.7.4 - TBD
|
||||
- Improvements to SIMD detection.
|
||||
|
||||
v0.7.3 - 2026-01-17
|
||||
- Fix an error in drmp3_open_and_read_pcm_frames_s16() and family when memory allocation fails.
|
||||
- Fix some compilation warnings.
|
||||
|
||||
v0.7.2 - 2025-12-02
|
||||
- Reduce stack space to improve robustness on embedded systems.
|
||||
- Fix a compilation error with MSVC Clang toolset relating to cpuid.
|
||||
- Fix an error with APE tag parsing.
|
||||
|
||||
v0.7.1 - 2025-09-10
|
||||
- Silence a warning with GCC.
|
||||
- Fix an error with the NXDK build.
|
||||
- Fix a decoding inconsistency when seeking. Prior to this change, reading to the end of the stream immediately after initializing will result in a different number of samples read than if the stream is seeked to the start and read to the end.
|
||||
|
||||
v0.7.0 - 2025-07-23
|
||||
- The old `DRMP3_IMPLEMENTATION` has been removed. Use `DR_MP3_IMPLEMENTATION` instead. The reason for this change is that in the future everything will eventually be using the underscored naming convention in the future, so `drmp3` will become `dr_mp3`.
|
||||
- API CHANGE: Seek origins have been renamed to match the naming convention used by dr_wav and my other libraries.
|
||||
- drmp3_seek_origin_start -> DRMP3_SEEK_SET
|
||||
|
|
|
|||
129
src/external/dr_wav.h
vendored
129
src/external/dr_wav.h
vendored
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
WAV audio loader and writer. Choice of public domain or MIT-0. See license statements at the end of this file.
|
||||
dr_wav - v0.14.0 - TBD
|
||||
dr_wav - v0.14.5 - 2026-03-03
|
||||
|
||||
David Reid - mackron@gmail.com
|
||||
|
||||
|
|
@ -147,7 +147,7 @@ extern "C" {
|
|||
|
||||
#define DRWAV_VERSION_MAJOR 0
|
||||
#define DRWAV_VERSION_MINOR 14
|
||||
#define DRWAV_VERSION_REVISION 0
|
||||
#define DRWAV_VERSION_REVISION 5
|
||||
#define DRWAV_VERSION_STRING DRWAV_XSTRINGIFY(DRWAV_VERSION_MAJOR) "." DRWAV_XSTRINGIFY(DRWAV_VERSION_MINOR) "." DRWAV_XSTRINGIFY(DRWAV_VERSION_REVISION)
|
||||
|
||||
#include <stddef.h> /* For size_t. */
|
||||
|
|
@ -2189,6 +2189,22 @@ DRWAV_PRIVATE drwav_uint64 drwav__read_smpl_to_metadata_obj(drwav__metadata_pars
|
|||
|
||||
if (pMetadata != NULL && bytesJustRead == sizeof(smplHeaderData)) {
|
||||
drwav_uint32 iSampleLoop;
|
||||
drwav_uint32 loopCount;
|
||||
drwav_uint32 calculatedLoopCount;
|
||||
|
||||
/*
|
||||
When we calcualted the amount of memory required for the "smpl" chunk we excluded the chunk entirely
|
||||
if the loop count in the header did not match with the calculated count based on the size of the
|
||||
chunk. When this happens, the second stage will still hit this path but the `pMetadata` will be
|
||||
non-null, but will either be pointing at the very end of the allocation or at the start of another
|
||||
chunk. We need to check the loop counts for consistency *before* dereferencing the pMetadata object
|
||||
so it's consistent with how we do it in the first stage.
|
||||
*/
|
||||
loopCount = drwav_bytes_to_u32(smplHeaderData + 28);
|
||||
calculatedLoopCount = (pChunkHeader->sizeInBytes - DRWAV_SMPL_BYTES) / DRWAV_SMPL_LOOP_BYTES;
|
||||
if (loopCount != calculatedLoopCount) {
|
||||
return totalBytesRead;
|
||||
}
|
||||
|
||||
pMetadata->type = drwav_metadata_type_smpl;
|
||||
pMetadata->data.smpl.manufacturerId = drwav_bytes_to_u32(smplHeaderData + 0);
|
||||
|
|
@ -2205,7 +2221,7 @@ DRWAV_PRIVATE drwav_uint64 drwav__read_smpl_to_metadata_obj(drwav__metadata_pars
|
|||
The loop count needs to be validated against the size of the chunk for safety so we don't
|
||||
attempt to read over the boundary of the chunk.
|
||||
*/
|
||||
if (pMetadata->data.smpl.sampleLoopCount == (pChunkHeader->sizeInBytes - DRWAV_SMPL_BYTES) / DRWAV_SMPL_LOOP_BYTES) {
|
||||
if (pMetadata->data.smpl.sampleLoopCount == calculatedLoopCount) {
|
||||
pMetadata->data.smpl.pLoops = (drwav_smpl_loop*)drwav__metadata_get_memory(pParser, sizeof(drwav_smpl_loop) * pMetadata->data.smpl.sampleLoopCount, DRWAV_METADATA_ALIGNMENT);
|
||||
|
||||
for (iSampleLoop = 0; iSampleLoop < pMetadata->data.smpl.sampleLoopCount; ++iSampleLoop) {
|
||||
|
|
@ -2230,6 +2246,15 @@ DRWAV_PRIVATE drwav_uint64 drwav__read_smpl_to_metadata_obj(drwav__metadata_pars
|
|||
|
||||
drwav__metadata_parser_read(pParser, pMetadata->data.smpl.pSamplerSpecificData, pMetadata->data.smpl.samplerSpecificDataSizeInBytes, &totalBytesRead);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
Getting here means the loop count in the header does not match up with the size of the
|
||||
chunk. Clear out the data to zero just to be safe.
|
||||
|
||||
This should never actually get hit because we check for it above, but keeping this here
|
||||
for added safety.
|
||||
*/
|
||||
DRWAV_ZERO_OBJECT(&pMetadata->data.smpl);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -5285,7 +5310,7 @@ DRWAV_PRIVATE drwav_bool32 drwav__on_tell_stdio(void* pUserData, drwav_int64* pC
|
|||
DRWAV_ASSERT(pFileStdio != NULL);
|
||||
DRWAV_ASSERT(pCursor != NULL);
|
||||
|
||||
#if defined(_WIN32)
|
||||
#if defined(_WIN32) && !defined(NXDK)
|
||||
#if defined(_MSC_VER) && _MSC_VER > 1200
|
||||
result = _ftelli64(pFileStdio);
|
||||
#else
|
||||
|
|
@ -5492,8 +5517,6 @@ DRWAV_PRIVATE drwav_bool32 drwav__on_seek_memory(void* pUserData, int offset, dr
|
|||
|
||||
DRWAV_ASSERT(pWav != NULL);
|
||||
|
||||
newCursor = pWav->memoryStream.currentReadPos;
|
||||
|
||||
if (origin == DRWAV_SEEK_SET) {
|
||||
newCursor = 0;
|
||||
} else if (origin == DRWAV_SEEK_CUR) {
|
||||
|
|
@ -5566,8 +5589,6 @@ DRWAV_PRIVATE drwav_bool32 drwav__on_seek_memory_write(void* pUserData, int offs
|
|||
|
||||
DRWAV_ASSERT(pWav != NULL);
|
||||
|
||||
newCursor = pWav->memoryStreamWrite.currentWritePos;
|
||||
|
||||
if (origin == DRWAV_SEEK_SET) {
|
||||
newCursor = 0;
|
||||
} else if (origin == DRWAV_SEEK_CUR) {
|
||||
|
|
@ -5576,7 +5597,7 @@ DRWAV_PRIVATE drwav_bool32 drwav__on_seek_memory_write(void* pUserData, int offs
|
|||
newCursor = (drwav_int64)pWav->memoryStreamWrite.dataSize;
|
||||
} else {
|
||||
DRWAV_ASSERT(!"Invalid seek origin");
|
||||
return DRWAV_INVALID_ARGS;
|
||||
return DRWAV_FALSE;
|
||||
}
|
||||
|
||||
newCursor += offset;
|
||||
|
|
@ -6258,12 +6279,12 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__msadpcm(drwav* pWav, drwav
|
|||
{
|
||||
drwav_uint64 totalFramesRead = 0;
|
||||
|
||||
static drwav_int32 adaptationTable[] = {
|
||||
static const drwav_int32 adaptationTable[] = {
|
||||
230, 230, 230, 230, 307, 409, 512, 614,
|
||||
768, 614, 512, 409, 307, 230, 230, 230
|
||||
};
|
||||
static drwav_int32 coeff1Table[] = { 256, 512, 0, 192, 240, 460, 392 };
|
||||
static drwav_int32 coeff2Table[] = { 0, -256, 0, 64, 0, -208, -232 };
|
||||
static const drwav_int32 coeff1Table[] = { 256, 512, 0, 192, 240, 460, 392 };
|
||||
static const drwav_int32 coeff2Table[] = { 0, -256, 0, 64, 0, -208, -232 };
|
||||
|
||||
DRWAV_ASSERT(pWav != NULL);
|
||||
DRWAV_ASSERT(framesToRead > 0);
|
||||
|
|
@ -6292,7 +6313,7 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__msadpcm(drwav* pWav, drwav
|
|||
pWav->msadpcm.cachedFrameCount = 2;
|
||||
|
||||
/* The predictor is used as an index into coeff1Table so we'll need to validate to ensure it never overflows. */
|
||||
if (pWav->msadpcm.predictor[0] >= drwav_countof(coeff1Table)) {
|
||||
if (pWav->msadpcm.predictor[0] >= drwav_countof(coeff1Table) || pWav->msadpcm.predictor[0] >= drwav_countof(coeff2Table)) {
|
||||
return totalFramesRead; /* Invalid file. */
|
||||
}
|
||||
} else {
|
||||
|
|
@ -6319,7 +6340,8 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__msadpcm(drwav* pWav, drwav
|
|||
pWav->msadpcm.cachedFrameCount = 2;
|
||||
|
||||
/* The predictor is used as an index into coeff1Table so we'll need to validate to ensure it never overflows. */
|
||||
if (pWav->msadpcm.predictor[0] >= drwav_countof(coeff1Table) || pWav->msadpcm.predictor[1] >= drwav_countof(coeff2Table)) {
|
||||
if (pWav->msadpcm.predictor[0] >= drwav_countof(coeff1Table) || pWav->msadpcm.predictor[0] >= drwav_countof(coeff2Table) ||
|
||||
pWav->msadpcm.predictor[1] >= drwav_countof(coeff1Table) || pWav->msadpcm.predictor[1] >= drwav_countof(coeff2Table)) {
|
||||
return totalFramesRead; /* Invalid file. */
|
||||
}
|
||||
}
|
||||
|
|
@ -6373,14 +6395,16 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__msadpcm(drwav* pWav, drwav
|
|||
drwav_int32 newSample0;
|
||||
drwav_int32 newSample1;
|
||||
|
||||
/* The predictor is read from the file and then indexed into a table. Check that it's in bounds. */
|
||||
if (pWav->msadpcm.predictor[0] >= drwav_countof(coeff1Table) || pWav->msadpcm.predictor[0] >= drwav_countof(coeff2Table)) {
|
||||
return totalFramesRead;
|
||||
}
|
||||
|
||||
newSample0 = ((pWav->msadpcm.prevFrames[0][1] * coeff1Table[pWav->msadpcm.predictor[0]]) + (pWav->msadpcm.prevFrames[0][0] * coeff2Table[pWav->msadpcm.predictor[0]])) >> 8;
|
||||
newSample0 += nibble0 * pWav->msadpcm.delta[0];
|
||||
newSample0 = drwav_clamp(newSample0, -32768, 32767);
|
||||
|
||||
pWav->msadpcm.delta[0] = (adaptationTable[((nibbles & 0xF0) >> 4)] * pWav->msadpcm.delta[0]) >> 8;
|
||||
if (pWav->msadpcm.delta[0] < 16) {
|
||||
pWav->msadpcm.delta[0] = 16;
|
||||
}
|
||||
pWav->msadpcm.delta[0] = (drwav_int32)drwav_clamp(((drwav_int64)adaptationTable[((nibbles & 0xF0) >> 4)] * pWav->msadpcm.delta[0]) >> 8, 16, 0x7FFFFFFF);
|
||||
|
||||
pWav->msadpcm.prevFrames[0][0] = pWav->msadpcm.prevFrames[0][1];
|
||||
pWav->msadpcm.prevFrames[0][1] = newSample0;
|
||||
|
|
@ -6390,15 +6414,11 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__msadpcm(drwav* pWav, drwav
|
|||
newSample1 += nibble1 * pWav->msadpcm.delta[0];
|
||||
newSample1 = drwav_clamp(newSample1, -32768, 32767);
|
||||
|
||||
pWav->msadpcm.delta[0] = (adaptationTable[((nibbles & 0x0F) >> 0)] * pWav->msadpcm.delta[0]) >> 8;
|
||||
if (pWav->msadpcm.delta[0] < 16) {
|
||||
pWav->msadpcm.delta[0] = 16;
|
||||
}
|
||||
pWav->msadpcm.delta[0] = (drwav_int32)drwav_clamp(((drwav_int64)adaptationTable[((nibbles & 0x0F) >> 0)] * pWav->msadpcm.delta[0]) >> 8, 16, 0x7FFFFFFF);
|
||||
|
||||
pWav->msadpcm.prevFrames[0][0] = pWav->msadpcm.prevFrames[0][1];
|
||||
pWav->msadpcm.prevFrames[0][1] = newSample1;
|
||||
|
||||
|
||||
pWav->msadpcm.cachedFrames[2] = newSample0;
|
||||
pWav->msadpcm.cachedFrames[3] = newSample1;
|
||||
pWav->msadpcm.cachedFrameCount = 2;
|
||||
|
|
@ -6408,28 +6428,30 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__msadpcm(drwav* pWav, drwav
|
|||
drwav_int32 newSample1;
|
||||
|
||||
/* Left. */
|
||||
if (pWav->msadpcm.predictor[0] >= drwav_countof(coeff1Table) || pWav->msadpcm.predictor[0] >= drwav_countof(coeff2Table)) {
|
||||
return totalFramesRead; /* Out of bounds. Invalid file. */
|
||||
}
|
||||
|
||||
newSample0 = ((pWav->msadpcm.prevFrames[0][1] * coeff1Table[pWav->msadpcm.predictor[0]]) + (pWav->msadpcm.prevFrames[0][0] * coeff2Table[pWav->msadpcm.predictor[0]])) >> 8;
|
||||
newSample0 += nibble0 * pWav->msadpcm.delta[0];
|
||||
newSample0 = drwav_clamp(newSample0, -32768, 32767);
|
||||
|
||||
pWav->msadpcm.delta[0] = (adaptationTable[((nibbles & 0xF0) >> 4)] * pWav->msadpcm.delta[0]) >> 8;
|
||||
if (pWav->msadpcm.delta[0] < 16) {
|
||||
pWav->msadpcm.delta[0] = 16;
|
||||
}
|
||||
pWav->msadpcm.delta[0] = (drwav_int32)drwav_clamp(((drwav_int64)adaptationTable[((nibbles & 0xF0) >> 4)] * pWav->msadpcm.delta[0]) >> 8, 16, 0x7FFFFFFF);
|
||||
|
||||
pWav->msadpcm.prevFrames[0][0] = pWav->msadpcm.prevFrames[0][1];
|
||||
pWav->msadpcm.prevFrames[0][1] = newSample0;
|
||||
|
||||
|
||||
/* Right. */
|
||||
if (pWav->msadpcm.predictor[1] >= drwav_countof(coeff1Table) || pWav->msadpcm.predictor[1] >= drwav_countof(coeff2Table)) {
|
||||
return totalFramesRead; /* Out of bounds. Invalid file. */
|
||||
}
|
||||
|
||||
newSample1 = ((pWav->msadpcm.prevFrames[1][1] * coeff1Table[pWav->msadpcm.predictor[1]]) + (pWav->msadpcm.prevFrames[1][0] * coeff2Table[pWav->msadpcm.predictor[1]])) >> 8;
|
||||
newSample1 += nibble1 * pWav->msadpcm.delta[1];
|
||||
newSample1 = drwav_clamp(newSample1, -32768, 32767);
|
||||
|
||||
pWav->msadpcm.delta[1] = (adaptationTable[((nibbles & 0x0F) >> 0)] * pWav->msadpcm.delta[1]) >> 8;
|
||||
if (pWav->msadpcm.delta[1] < 16) {
|
||||
pWav->msadpcm.delta[1] = 16;
|
||||
}
|
||||
pWav->msadpcm.delta[1] = (drwav_int32)drwav_clamp(((drwav_int64)adaptationTable[((nibbles & 0x0F) >> 0)] * pWav->msadpcm.delta[1]) >> 8, 16, 0x7FFFFFFF);
|
||||
|
||||
pWav->msadpcm.prevFrames[1][0] = pWav->msadpcm.prevFrames[1][1];
|
||||
pWav->msadpcm.prevFrames[1][1] = newSample1;
|
||||
|
|
@ -6451,12 +6473,12 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__ima(drwav* pWav, drwav_uin
|
|||
drwav_uint64 totalFramesRead = 0;
|
||||
drwav_uint32 iChannel;
|
||||
|
||||
static drwav_int32 indexTable[16] = {
|
||||
static const drwav_int32 indexTable[16] = {
|
||||
-1, -1, -1, -1, 2, 4, 6, 8,
|
||||
-1, -1, -1, -1, 2, 4, 6, 8
|
||||
};
|
||||
|
||||
static drwav_int32 stepTable[89] = {
|
||||
static const drwav_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,
|
||||
|
|
@ -6606,7 +6628,7 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__ima(drwav* pWav, drwav_uin
|
|||
|
||||
|
||||
#ifndef DR_WAV_NO_CONVERSION_API
|
||||
static unsigned short g_drwavAlawTable[256] = {
|
||||
static const unsigned short g_drwavAlawTable[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,
|
||||
|
|
@ -6625,7 +6647,7 @@ static unsigned short g_drwavAlawTable[256] = {
|
|||
0x02B0, 0x0290, 0x02F0, 0x02D0, 0x0230, 0x0210, 0x0270, 0x0250, 0x03B0, 0x0390, 0x03F0, 0x03D0, 0x0330, 0x0310, 0x0370, 0x0350
|
||||
};
|
||||
|
||||
static unsigned short g_drwavMulawTable[256] = {
|
||||
static const unsigned short g_drwavMulawTable[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,
|
||||
|
|
@ -8053,6 +8075,12 @@ DRWAV_PRIVATE drwav_int16* drwav__read_pcm_frames_and_close_s16(drwav* pWav, uns
|
|||
|
||||
DRWAV_ASSERT(pWav != NULL);
|
||||
|
||||
/* Check for overflow before multiplication. */
|
||||
if (pWav->channels == 0 || pWav->totalPCMFrameCount > DRWAV_SIZE_MAX / pWav->channels / sizeof(drwav_int16)) {
|
||||
drwav_uninit(pWav);
|
||||
return NULL; /* Overflow or invalid channels. */
|
||||
}
|
||||
|
||||
sampleDataSize = pWav->totalPCMFrameCount * pWav->channels * sizeof(drwav_int16);
|
||||
if (sampleDataSize > DRWAV_SIZE_MAX) {
|
||||
drwav_uninit(pWav);
|
||||
|
|
@ -8095,6 +8123,12 @@ DRWAV_PRIVATE float* drwav__read_pcm_frames_and_close_f32(drwav* pWav, unsigned
|
|||
|
||||
DRWAV_ASSERT(pWav != NULL);
|
||||
|
||||
/* Check for overflow before multiplication. */
|
||||
if (pWav->channels == 0 || pWav->totalPCMFrameCount > DRWAV_SIZE_MAX / pWav->channels / sizeof(float)) {
|
||||
drwav_uninit(pWav);
|
||||
return NULL; /* Overflow or invalid channels. */
|
||||
}
|
||||
|
||||
sampleDataSize = pWav->totalPCMFrameCount * pWav->channels * sizeof(float);
|
||||
if (sampleDataSize > DRWAV_SIZE_MAX) {
|
||||
drwav_uninit(pWav);
|
||||
|
|
@ -8137,6 +8171,12 @@ DRWAV_PRIVATE drwav_int32* drwav__read_pcm_frames_and_close_s32(drwav* pWav, uns
|
|||
|
||||
DRWAV_ASSERT(pWav != NULL);
|
||||
|
||||
/* Check for overflow before multiplication. */
|
||||
if (pWav->channels == 0 || pWav->totalPCMFrameCount > DRWAV_SIZE_MAX / pWav->channels / sizeof(drwav_int32)) {
|
||||
drwav_uninit(pWav);
|
||||
return NULL; /* Overflow or invalid channels. */
|
||||
}
|
||||
|
||||
sampleDataSize = pWav->totalPCMFrameCount * pWav->channels * sizeof(drwav_int32);
|
||||
if (sampleDataSize > DRWAV_SIZE_MAX) {
|
||||
drwav_uninit(pWav);
|
||||
|
|
@ -8517,7 +8557,24 @@ DRWAV_API drwav_bool32 drwav_fourcc_equal(const drwav_uint8* a, const char* b)
|
|||
/*
|
||||
REVISION HISTORY
|
||||
================
|
||||
v0.14.0 - TBD
|
||||
v0.14.5 - 2026-03-03
|
||||
- Fix a crash when loading files with a malformed "smpl" chunk.
|
||||
- Fix a signed overflow bug with the MS-ADPCM decoder.
|
||||
|
||||
v0.14.4 - 2026-01-17
|
||||
- Fix some compilation warnings.
|
||||
|
||||
v0.14.3 - 2025-12-14
|
||||
- Fix a possible out-of-bounds read when reading from MS-ADPCM encoded files.
|
||||
- Fix a possible integer overflow error.
|
||||
|
||||
v0.14.2 - 2025-12-02
|
||||
- Fix a compilation warning.
|
||||
|
||||
v0.14.1 - 2025-09-10
|
||||
- Fix an error with the NXDK build.
|
||||
|
||||
v0.14.0 - 2025-07-23
|
||||
- API CHANGE: Seek origin enums have been renamed to the following:
|
||||
- drwav_seek_origin_start -> DRWAV_SEEK_SET
|
||||
- drwav_seek_origin_current -> DRWAV_SEEK_CUR
|
||||
|
|
|
|||
53
src/external/m3d.h
vendored
53
src/external/m3d.h
vendored
|
|
@ -236,7 +236,8 @@ typedef struct {
|
|||
#ifdef M3D_ASCII
|
||||
#define M3D_PROPERTYDEF(f,i,n) { (f), (i), (char*)(n) }
|
||||
char *key;
|
||||
#else
|
||||
#endif
|
||||
#ifndef M3D_ASCII
|
||||
#define M3D_PROPERTYDEF(f,i,n) { (f), (i) }
|
||||
#endif
|
||||
} m3dpd_t;
|
||||
|
|
@ -414,7 +415,8 @@ typedef struct {
|
|||
#ifdef M3D_ASCII
|
||||
#define M3D_CMDDEF(t,n,p,a,b,c,d,e,f,g,h) { (char*)(n), (p), { (a), (b), (c), (d), (e), (f), (g), (h) } }
|
||||
char *key;
|
||||
#else
|
||||
#endif
|
||||
#ifndef M3D_ASCII
|
||||
#define M3D_CMDDEF(t,n,p,a,b,c,d,e,f,g,h) { (p), { (a), (b), (c), (d), (e), (f), (g), (h) } }
|
||||
#endif
|
||||
uint8_t p;
|
||||
|
|
@ -674,6 +676,10 @@ static m3dcd_t m3d_commandtypes[] = {
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* we'll need this with M3D_NOTEXTURE */
|
||||
char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header);
|
||||
|
||||
#ifndef M3D_NOTEXTURE
|
||||
#if !defined(M3D_NOIMPORTER) && !defined(STBI_INCLUDE_STB_IMAGE_H)
|
||||
/* PNG decompressor from
|
||||
|
||||
|
|
@ -1868,6 +1874,11 @@ static void *_m3dstbi__png_load(_m3dstbi__context *s, int *x, int *y, int *comp,
|
|||
#if !defined(M3D_NOIMPORTER) && defined(STBI_INCLUDE_STB_IMAGE_H) && !defined(STB_IMAGE_IMPLEMENTATION)
|
||||
#error "stb_image.h included without STB_IMAGE_IMPLEMENTATION. Sorry, we need some stuff defined inside the ifguard for proper integration"
|
||||
#endif
|
||||
#else
|
||||
#if !defined(STBI_INCLUDE_STB_IMAGE_H) || defined(STBI_NO_ZLIB)
|
||||
#error "stb_image.h not included or STBI_NO_ZLIB defined. Sorry, we need its zlib implementation for proper integration"
|
||||
#endif
|
||||
#endif /* M3D_NOTEXTURE */
|
||||
|
||||
#if defined(M3D_EXPORTER) && !defined(INCLUDE_STB_IMAGE_WRITE_H)
|
||||
/* zlib_compressor from
|
||||
|
|
@ -2168,9 +2179,11 @@ M3D_INDEX _m3d_gettx(m3d_t *model, m3dread_t readfilecb, m3dfree_t freecb, char
|
|||
unsigned int i, len = 0;
|
||||
unsigned char *buff = NULL;
|
||||
char *fn2;
|
||||
#ifndef M3D_NOTEXTURE
|
||||
unsigned int w, h;
|
||||
stbi__context s;
|
||||
stbi__result_info ri;
|
||||
#endif
|
||||
|
||||
/* failsafe */
|
||||
if(!fn || !*fn) return M3D_UNDEF;
|
||||
|
|
@ -2209,13 +2222,17 @@ M3D_INDEX _m3d_gettx(m3d_t *model, m3dread_t readfilecb, m3dfree_t freecb, char
|
|||
if(!model->texture) {
|
||||
if(buff && freecb) (*freecb)(buff);
|
||||
model->errcode = M3D_ERR_ALLOC;
|
||||
model->numtexture = 0;
|
||||
return M3D_UNDEF;
|
||||
}
|
||||
memset(&model->texture[i], 0, sizeof(m3dtx_t));
|
||||
model->texture[i].name = fn;
|
||||
model->texture[i].w = model->texture[i].h = 0; model->texture[i].d = NULL;
|
||||
if(buff) {
|
||||
if(buff[0] == 0x89 && buff[1] == 'P' && buff[2] == 'N' && buff[3] == 'G') {
|
||||
s.read_from_callbacks = 0;
|
||||
#ifndef M3D_NOTEXTURE
|
||||
/* return pixel buffer of the decoded texture */
|
||||
memset(&s, 0, sizeof(s));
|
||||
memset(&ri, 0, sizeof(ri));
|
||||
s.img_buffer = s.img_buffer_original = (unsigned char *) buff;
|
||||
s.img_buffer_end = s.img_buffer_original_end = (unsigned char *) buff+len;
|
||||
/* don't use model->texture[i].w directly, it's a uint16_t */
|
||||
|
|
@ -2225,6 +2242,16 @@ M3D_INDEX _m3d_gettx(m3d_t *model, m3dread_t readfilecb, m3dfree_t freecb, char
|
|||
model->texture[i].w = w;
|
||||
model->texture[i].h = h;
|
||||
model->texture[i].f = (uint8_t)len;
|
||||
#else
|
||||
/* return only the raw undecoded texture */
|
||||
if((model->texture[i].d = (uint8_t*)M3D_MALLOC(len))) {
|
||||
memcpy(model->texture[i].d, buff, len);
|
||||
model->texture[i].w = len & 0xffff;
|
||||
model->texture[i].h = (len >> 16) & 0xffff;
|
||||
model->texture[i].f = 0;
|
||||
} else
|
||||
model->errcode = M3D_ERR_ALLOC;
|
||||
#endif
|
||||
} else {
|
||||
#ifdef M3D_TX_INTERP
|
||||
if((model->errcode = M3D_TX_INTERP(fn, buff, len, &model->texture[i])) != M3D_SUCCESS) {
|
||||
|
|
@ -4280,7 +4307,7 @@ m3db_t *m3d_pose(m3d_t *model, M3D_INDEX actionid, uint32_t msec)
|
|||
if(l != msec) {
|
||||
model->vertex = (m3dv_t*)M3D_REALLOC(model->vertex, (model->numvertex + 2 * model->numbone) * sizeof(m3dv_t));
|
||||
if(!model->vertex) {
|
||||
free(ret);
|
||||
M3D_FREE(ret);
|
||||
model->errcode = M3D_ERR_ALLOC;
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -4492,7 +4519,7 @@ void m3d_free(m3d_t *model)
|
|||
if(model->label) M3D_FREE(model->label);
|
||||
if(model->inlined) M3D_FREE(model->inlined);
|
||||
if(model->extra) M3D_FREE(model->extra);
|
||||
free(model);
|
||||
M3D_FREE(model);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -4568,15 +4595,15 @@ static uint32_t _m3d_stridx(m3dstr_t *str, uint32_t numstr, char *s)
|
|||
safe = _m3d_safestr(s, 0);
|
||||
if(!safe) return 0;
|
||||
if(!*safe) {
|
||||
free(safe);
|
||||
M3D_FREE(safe);
|
||||
return 0;
|
||||
}
|
||||
for(i = 0; i < numstr; i++)
|
||||
if(!strcmp(str[i].str, s)) {
|
||||
free(safe);
|
||||
M3D_FREE(safe);
|
||||
return str[i].offs;
|
||||
}
|
||||
free(safe);
|
||||
M3D_FREE(safe);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -4889,7 +4916,7 @@ unsigned char *m3d_save(m3d_t *model, int quality, int flags, unsigned int *size
|
|||
if(cmd->type == m3dc_mesh) {
|
||||
if(numgrp + 2 < maxgrp) {
|
||||
maxgrp += 1024;
|
||||
grpidx = (uint32_t*)realloc(grpidx, maxgrp * sizeof(uint32_t));
|
||||
grpidx = (uint32_t*)M3D_REALLOC(grpidx, maxgrp * sizeof(uint32_t));
|
||||
if(!grpidx) goto memerr;
|
||||
if(!numgrp) {
|
||||
grpidx[0] = 0;
|
||||
|
|
@ -5194,7 +5221,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx);
|
|||
if(sa) M3D_FREE(sa);
|
||||
if(sd) M3D_FREE(sd);
|
||||
if(out) M3D_FREE(out);
|
||||
if(opa) free(opa);
|
||||
if(opa) M3D_FREE(opa);
|
||||
if(h) M3D_FREE(h);
|
||||
M3D_LOG("Out of memory");
|
||||
model->errcode = M3D_ERR_ALLOC;
|
||||
|
|
@ -6285,7 +6312,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx);
|
|||
if(skin) M3D_FREE(skin);
|
||||
if(str) M3D_FREE(str);
|
||||
if(vrtx) M3D_FREE(vrtx);
|
||||
if(opa) free(opa);
|
||||
if(opa) M3D_FREE(opa);
|
||||
if(h) M3D_FREE(h);
|
||||
return out;
|
||||
}
|
||||
|
|
@ -6310,7 +6337,7 @@ namespace M3D {
|
|||
|
||||
public:
|
||||
Model() {
|
||||
this->model = (m3d_t*)malloc(sizeof(m3d_t)); memset(this->model, 0, sizeof(m3d_t));
|
||||
this->model = (m3d_t*)M3D_MALLOC(sizeof(m3d_t)); memset(this->model, 0, sizeof(m3d_t));
|
||||
}
|
||||
Model(_unused const std::string &data, _unused m3dread_t ReadFileCB,
|
||||
_unused m3dfree_t FreeCB, _unused M3D::Model mtllib) {
|
||||
|
|
|
|||
10
src/external/qoa.h
vendored
10
src/external/qoa.h
vendored
|
|
@ -387,7 +387,7 @@ unsigned int qoa_encode_frame(const short *sample_data, qoa_desc *qoa, unsigned
|
|||
int slice_start = sample_index * channels + c;
|
||||
int slice_end = (sample_index + slice_len) * channels + c;
|
||||
|
||||
/* Brute for search for the best scalefactor. Just go through all
|
||||
/* Brute force search for the best scalefactor. Just go through all
|
||||
16 scalefactors, encode all samples for the current slice and
|
||||
meassure the total squared error. */
|
||||
qoa_uint64_t best_rank = -1;
|
||||
|
|
@ -402,7 +402,7 @@ unsigned int qoa_encode_frame(const short *sample_data, qoa_desc *qoa, unsigned
|
|||
/* There is a strong correlation between the scalefactors of
|
||||
neighboring slices. As an optimization, start testing
|
||||
the best scalefactor of the previous slice first. */
|
||||
int scalefactor = (sfi + prev_scalefactor[c]) % 16;
|
||||
int scalefactor = (sfi + prev_scalefactor[c]) & (16 - 1);
|
||||
|
||||
/* We have to reset the LMS state to the last known good one
|
||||
before trying each scalefactor, as each pass updates the LMS
|
||||
|
|
@ -500,7 +500,7 @@ void *qoa_encode(const short *sample_data, qoa_desc *qoa, unsigned int *out_len)
|
|||
num_frames * QOA_LMS_LEN * 4 * qoa->channels + /* 4 * 4 bytes lms state per channel */
|
||||
num_slices * 8 * qoa->channels; /* 8 byte slices */
|
||||
|
||||
unsigned char *bytes = (unsigned char *)QOA_MALLOC(encoded_size);
|
||||
unsigned char *bytes = QOA_MALLOC(encoded_size);
|
||||
|
||||
for (unsigned int c = 0; c < qoa->channels; c++) {
|
||||
/* Set the initial LMS weights to {0, 0, -1, 2}. This helps with the
|
||||
|
|
@ -657,7 +657,7 @@ short *qoa_decode(const unsigned char *bytes, int size, qoa_desc *qoa) {
|
|||
|
||||
/* Calculate the required size of the sample buffer and allocate */
|
||||
int total_samples = qoa->samples * qoa->channels;
|
||||
short *sample_data = (short *)QOA_MALLOC(total_samples * sizeof(short));
|
||||
short *sample_data = QOA_MALLOC(total_samples * sizeof(short));
|
||||
|
||||
unsigned int sample_index = 0;
|
||||
unsigned int frame_len;
|
||||
|
|
@ -733,7 +733,7 @@ void *qoa_read(const char *filename, qoa_desc *qoa) {
|
|||
bytes_read = fread(data, 1, size, f);
|
||||
fclose(f);
|
||||
|
||||
sample_data = qoa_decode((const unsigned char *)data, bytes_read, qoa);
|
||||
sample_data = qoa_decode(data, bytes_read, qoa);
|
||||
QOA_FREE(data);
|
||||
return sample_data;
|
||||
}
|
||||
|
|
|
|||
4
src/external/qoi.h
vendored
4
src/external/qoi.h
vendored
|
|
@ -427,7 +427,7 @@ void *qoi_encode(const void *data, const qoi_desc *desc, int *out_len) {
|
|||
run = 0;
|
||||
}
|
||||
|
||||
index_pos = QOI_COLOR_HASH(px) % 64;
|
||||
index_pos = QOI_COLOR_HASH(px) & (64 - 1);
|
||||
|
||||
if (index[index_pos].v == px.v) {
|
||||
bytes[p++] = QOI_OP_INDEX | index_pos;
|
||||
|
|
@ -574,7 +574,7 @@ void *qoi_decode(const void *data, int size, qoi_desc *desc, int channels) {
|
|||
run = (b1 & 0x3f);
|
||||
}
|
||||
|
||||
index[QOI_COLOR_HASH(px) % 64] = px;
|
||||
index[QOI_COLOR_HASH(px) & (64 - 1)] = px;
|
||||
}
|
||||
|
||||
pixels[px_pos + 0] = px.rgba.r;
|
||||
|
|
|
|||
654
src/external/stb_image_resize2.h
vendored
654
src/external/stb_image_resize2.h
vendored
File diff suppressed because it is too large
Load Diff
|
|
@ -821,6 +821,11 @@ void SetWindowSize(int width, int height)
|
|||
CORE.Window.screen.height = height;
|
||||
}
|
||||
|
||||
if (!CORE.Window.usingFbo)
|
||||
{
|
||||
SetupViewport(CORE.Window.screen.width, CORE.Window.screen.height);
|
||||
}
|
||||
|
||||
RGFW_window_resize(platform.window, CORE.Window.screen.width, CORE.Window.screen.height);
|
||||
}
|
||||
|
||||
|
|
|
|||
63
src/raudio.c
63
src/raudio.c
|
|
@ -963,12 +963,8 @@ Sound LoadSoundFromWave(Wave wave)
|
|||
if (frameCount == 0) TRACELOG(LOG_WARNING, "SOUND: Failed to get frame count for format conversion");
|
||||
|
||||
AudioBuffer *audioBuffer = LoadAudioBuffer(AUDIO_DEVICE_FORMAT, AUDIO_DEVICE_CHANNELS, AUDIO.System.device.sampleRate, frameCount, AUDIO_BUFFER_USAGE_STATIC);
|
||||
if (audioBuffer == NULL)
|
||||
if (audioBuffer != NULL)
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "SOUND: Failed to create buffer");
|
||||
return sound; // early return to avoid dereferencing the audioBuffer null pointer
|
||||
}
|
||||
|
||||
frameCount = (ma_uint32)ma_convert_frames(audioBuffer->data, frameCount, AUDIO_DEVICE_FORMAT, AUDIO_DEVICE_CHANNELS, AUDIO.System.device.sampleRate, wave.data, frameCountIn, formatIn, wave.channels, wave.sampleRate);
|
||||
if (frameCount == 0) TRACELOG(LOG_WARNING, "SOUND: Failed format conversion");
|
||||
|
||||
|
|
@ -978,6 +974,8 @@ Sound LoadSoundFromWave(Wave wave)
|
|||
sound.stream.channels = AUDIO_DEVICE_CHANNELS;
|
||||
sound.stream.buffer = audioBuffer;
|
||||
}
|
||||
else TRACELOG(LOG_WARNING, "SOUND: Failed to create buffer");
|
||||
}
|
||||
|
||||
return sound;
|
||||
}
|
||||
|
|
@ -992,12 +990,8 @@ Sound LoadSoundAlias(Sound source)
|
|||
{
|
||||
AudioBuffer *audioBuffer = LoadAudioBuffer(AUDIO_DEVICE_FORMAT, AUDIO_DEVICE_CHANNELS, AUDIO.System.device.sampleRate, 0, AUDIO_BUFFER_USAGE_STATIC);
|
||||
|
||||
if (audioBuffer == NULL)
|
||||
if (audioBuffer != NULL)
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "SOUND: Failed to create buffer");
|
||||
return sound; // Early return to avoid dereferencing the audioBuffer null pointer
|
||||
}
|
||||
|
||||
audioBuffer->sizeInFrames = source.stream.buffer->sizeInFrames;
|
||||
audioBuffer->data = source.stream.buffer->data;
|
||||
|
||||
|
|
@ -1012,6 +1006,8 @@ Sound LoadSoundAlias(Sound source)
|
|||
sound.stream.channels = AUDIO_DEVICE_CHANNELS;
|
||||
sound.stream.buffer = audioBuffer;
|
||||
}
|
||||
else TRACELOG(LOG_WARNING, "SOUND: Failed to create buffer");
|
||||
}
|
||||
|
||||
return sound;
|
||||
}
|
||||
|
|
@ -1071,7 +1067,7 @@ void UpdateSound(Sound sound, const void *data, int frameCount)
|
|||
// Export wave data to file
|
||||
bool ExportWave(Wave wave, const char *fileName)
|
||||
{
|
||||
bool success = false;
|
||||
bool result = false;
|
||||
|
||||
if (false) { }
|
||||
#if SUPPORT_FILEFORMAT_WAV
|
||||
|
|
@ -1088,11 +1084,11 @@ bool ExportWave(Wave wave, const char *fileName)
|
|||
|
||||
void *fileData = NULL;
|
||||
size_t fileDataSize = 0;
|
||||
success = drwav_init_memory_write(&wav, &fileData, &fileDataSize, &format, NULL);
|
||||
if (success) success = (int)drwav_write_pcm_frames(&wav, wave.frameCount, wave.data);
|
||||
result = drwav_init_memory_write(&wav, &fileData, &fileDataSize, &format, NULL);
|
||||
if (result) result = (int)drwav_write_pcm_frames(&wav, wave.frameCount, wave.data);
|
||||
drwav_result result = drwav_uninit(&wav);
|
||||
|
||||
if (result == DRWAV_SUCCESS) success = SaveFileData(fileName, (unsigned char *)fileData, (unsigned int)fileDataSize);
|
||||
if (result == DRWAV_SUCCESS) result = SaveFileData(fileName, (unsigned char *)fileData, (unsigned int)fileDataSize);
|
||||
|
||||
drwav_free(fileData, NULL);
|
||||
}
|
||||
|
|
@ -1108,7 +1104,7 @@ bool ExportWave(Wave wave, const char *fileName)
|
|||
qoa.samples = wave.frameCount;
|
||||
|
||||
int bytesWritten = qoa_write(fileName, (const short *)wave.data, &qoa);
|
||||
if (bytesWritten > 0) success = true;
|
||||
if (bytesWritten > 0) result = true;
|
||||
}
|
||||
else TRACELOG(LOG_WARNING, "AUDIO: Wave data must be 16 bit per sample for QOA format export");
|
||||
}
|
||||
|
|
@ -1117,19 +1113,19 @@ bool ExportWave(Wave wave, const char *fileName)
|
|||
{
|
||||
// Export raw sample data (without header)
|
||||
// NOTE: It's up to the user to track wave parameters
|
||||
success = SaveFileData(fileName, wave.data, wave.frameCount*wave.channels*wave.sampleSize/8);
|
||||
result = SaveFileData(fileName, wave.data, wave.frameCount*wave.channels*wave.sampleSize/8);
|
||||
}
|
||||
|
||||
if (success) TRACELOG(LOG_INFO, "FILEIO: [%s] Wave data exported successfully", fileName);
|
||||
if (result) TRACELOG(LOG_INFO, "FILEIO: [%s] Wave data exported successfully", fileName);
|
||||
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to export wave data", fileName);
|
||||
|
||||
return success;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Export wave sample data to code (.h)
|
||||
bool ExportWaveAsCode(Wave wave, const char *fileName)
|
||||
{
|
||||
bool success = false;
|
||||
bool result = false;
|
||||
|
||||
#ifndef TEXT_BYTES_PER_LINE
|
||||
#define TEXT_BYTES_PER_LINE 20
|
||||
|
|
@ -1183,14 +1179,14 @@ bool ExportWaveAsCode(Wave wave, const char *fileName)
|
|||
}
|
||||
|
||||
// NOTE: Text data length exported is determined by '\0' (NULL) character
|
||||
success = SaveFileText(fileName, txtData);
|
||||
result = SaveFileText(fileName, txtData);
|
||||
|
||||
RL_FREE(txtData);
|
||||
|
||||
if (success != 0) TRACELOG(LOG_INFO, "FILEIO: [%s] Wave as code exported successfully", fileName);
|
||||
if (result != 0) TRACELOG(LOG_INFO, "FILEIO: [%s] Wave as code exported successfully", fileName);
|
||||
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to export wave as code", fileName);
|
||||
|
||||
return success;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Play a sound
|
||||
|
|
@ -2187,12 +2183,15 @@ void UpdateAudioStream(AudioStream stream, const void *data, int frameCount)
|
|||
// Check if any audio stream buffers requires refill
|
||||
bool IsAudioStreamProcessed(AudioStream stream)
|
||||
{
|
||||
if (stream.buffer == NULL) return false;
|
||||
|
||||
bool result = false;
|
||||
|
||||
if (stream.buffer != NULL)
|
||||
{
|
||||
ma_mutex_lock(&AUDIO.System.lock);
|
||||
result = stream.buffer->isSubBufferProcessed[0] || stream.buffer->isSubBufferProcessed[1];
|
||||
ma_mutex_unlock(&AUDIO.System.lock);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -2885,6 +2884,8 @@ static unsigned char *LoadFileData(const char *fileName, int *dataSize)
|
|||
// Save data to file from buffer
|
||||
static bool SaveFileData(const char *fileName, void *data, int dataSize)
|
||||
{
|
||||
bool result = true;
|
||||
|
||||
if (fileName != NULL)
|
||||
{
|
||||
FILE *file = fopen(fileName, "wb");
|
||||
|
|
@ -2902,21 +2903,23 @@ static bool SaveFileData(const char *fileName, void *data, int dataSize)
|
|||
else
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to open file", fileName);
|
||||
return false;
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "FILEIO: File name provided is not valid");
|
||||
return false;
|
||||
result = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Save text data to file (write), string must be '\0' terminated
|
||||
static bool SaveFileText(const char *fileName, char *text)
|
||||
{
|
||||
bool result = true;
|
||||
|
||||
if (fileName != NULL)
|
||||
{
|
||||
FILE *file = fopen(fileName, "wt");
|
||||
|
|
@ -2934,16 +2937,16 @@ static bool SaveFileText(const char *fileName, char *text)
|
|||
else
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to open text file", fileName);
|
||||
return false;
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACELOG(LOG_WARNING, "FILEIO: File name provided is not valid");
|
||||
return false;
|
||||
result = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
19
src/raylib.h
19
src/raylib.h
|
|
@ -1161,8 +1161,8 @@ RLAPI int MakeDirectory(const char *dirPath); // Create di
|
|||
RLAPI bool ChangeDirectory(const char *dirPath); // Change working directory, return true on success
|
||||
RLAPI bool IsPathFile(const char *path); // Check if a given path is a file or a directory
|
||||
RLAPI bool IsFileNameValid(const char *fileName); // Check if fileName is valid for the platform/OS
|
||||
RLAPI FilePathList LoadDirectoryFiles(const char *dirPath); // Load directory filepaths
|
||||
RLAPI FilePathList LoadDirectoryFilesEx(const char *basePath, const char *filter, bool scanSubdirs); // Load directory filepaths with extension filtering and recursive directory scan. Use 'DIR' in the filter string to include directories in the result
|
||||
RLAPI FilePathList LoadDirectoryFiles(const char *dirPath); // Load directory filepaths, files and directories, no subdirs scan
|
||||
RLAPI FilePathList LoadDirectoryFilesEx(const char *basePath, const char *filter, bool scanSubdirs); // Load directory filepaths with extension filtering and subdir scan; some filters available: "*.*", "FILES*", "DIRS*"
|
||||
RLAPI void UnloadDirectoryFiles(FilePathList files); // Unload filepaths
|
||||
RLAPI bool IsFileDropped(void); // Check if a file has been dropped into window
|
||||
RLAPI FilePathList LoadDroppedFiles(void); // Load dropped filepaths
|
||||
|
|
@ -1359,7 +1359,7 @@ RLAPI Image LoadImageFromScreen(void);
|
|||
RLAPI bool IsImageValid(Image image); // Check if an image is valid (data and parameters)
|
||||
RLAPI void UnloadImage(Image image); // Unload image from CPU memory (RAM)
|
||||
RLAPI bool ExportImage(Image image, const char *fileName); // Export image data to file, returns true on success
|
||||
RLAPI unsigned char *ExportImageToMemory(Image image, const char *fileType, int *fileSize); // Export image to memory buffer
|
||||
RLAPI unsigned char *ExportImageToMemory(Image image, const char *fileType, int *fileSize); // Export image to memory buffer, memory must be MemFree()
|
||||
RLAPI bool ExportImageAsCode(Image image, const char *fileName); // Export image as code file defining an array of bytes, returns true on success
|
||||
|
||||
// Image generation functions
|
||||
|
|
@ -1528,7 +1528,7 @@ RLAPI const char *CodepointToUTF8(int codepoint, int *utf8Size);
|
|||
|
||||
// Text strings management functions (no UTF-8 strings, only byte chars)
|
||||
// WARNING 1: Most of these functions use internal static buffers[], it's recommended to store returned data on user-side for re-use
|
||||
// WARNING 2: Some strings allocate memory internally for the returned strings, those strings must be free by user using MemFree()
|
||||
// WARNING 2: Some functions allocate memory internally for the returned strings, those strings must be freed by user using MemFree()
|
||||
RLAPI char **LoadTextLines(const char *text, int *count); // Load text as separate lines ('\n')
|
||||
RLAPI void UnloadTextLines(char **text, int lineCount); // Unload text lines
|
||||
RLAPI int TextCopy(char *dst, const char *src); // Copy one string to another, returns bytes copied
|
||||
|
|
@ -1538,9 +1538,12 @@ RLAPI const char *TextFormat(const char *text, ...);
|
|||
RLAPI const char *TextSubtext(const char *text, int position, int length); // Get a piece of a text string
|
||||
RLAPI const char *TextRemoveSpaces(const char *text); // Remove text spaces, concat words
|
||||
RLAPI char *GetTextBetween(const char *text, const char *begin, const char *end); // Get text between two strings
|
||||
RLAPI char *TextReplace(const char *text, const char *search, const char *replacement); // Replace text string (WARNING: memory must be freed!)
|
||||
RLAPI char *TextReplaceBetween(const char *text, const char *begin, const char *end, const char *replacement); // Replace text between two specific strings (WARNING: memory must be freed!)
|
||||
RLAPI char *TextInsert(const char *text, const char *insert, int position); // Insert text in a position (WARNING: memory must be freed!)
|
||||
RLAPI char *TextReplace(const char *text, const char *search, const char *replacement); // Replace text string with new string
|
||||
RLAPI char *TextReplaceAlloc(const char *text, const char *search, const char *replacement); // Replace text string with new string, memory must be MemFree()
|
||||
RLAPI char *TextReplaceBetween(const char *text, const char *begin, const char *end, const char *replacement); // Replace text between two specific strings
|
||||
RLAPI char *TextReplaceBetweenAlloc(const char *text, const char *begin, const char *end, const char *replacement); // Replace text between two specific strings, memory must be MemFree()
|
||||
RLAPI char *TextInsert(const char *text, const char *insert, int position); // Insert text in a defined byte position
|
||||
RLAPI char *TextInsertAlloc(const char *text, const char *insert, int position); // Insert text in a defined byte position, memory must be MemFree()
|
||||
RLAPI char *TextJoin(char **textList, int count, const char *delimiter); // Join text strings with delimiter
|
||||
RLAPI char **TextSplit(const char *text, char delimiter, int *count); // Split text into multiple strings, using MAX_TEXTSPLIT_COUNT static strings
|
||||
RLAPI void TextAppend(char *text, const char *append, int *position); // Append text at specific position and move cursor
|
||||
|
|
@ -1596,8 +1599,6 @@ RLAPI void DrawModel(Model model, Vector3 position, float scale, Color tint);
|
|||
RLAPI void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model with extended parameters
|
||||
RLAPI void DrawModelWires(Model model, Vector3 position, float scale, Color tint); // Draw a model wires (with texture if set)
|
||||
RLAPI void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model wires (with texture if set) with extended parameters
|
||||
RLAPI void DrawModelPoints(Model model, Vector3 position, float scale, Color tint); // Draw a model as points
|
||||
RLAPI void DrawModelPointsEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model as points with extended parameters
|
||||
RLAPI void DrawBoundingBox(BoundingBox box, Color color); // Draw bounding box (wires)
|
||||
RLAPI void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float scale, Color tint); // Draw a billboard texture
|
||||
RLAPI void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector2 size, Color tint); // Draw a billboard texture defined by source
|
||||
|
|
|
|||
72
src/rcore.c
72
src/rcore.c
|
|
@ -267,15 +267,18 @@
|
|||
#define MAX_AUTOMATION_EVENTS 16384 // Maximum number of automation events to record
|
||||
#endif
|
||||
|
||||
// File and directory scan filters
|
||||
// NOTE: Used in ScanDirectoryFiles(), LoadDirectoryFilesEx() and GetDirectoryFileCountEx()
|
||||
// WARNING: Custom file filters can be specified but following raylib IsFileExtension() convention: ".png;.wav;.glb"
|
||||
#ifndef FILE_FILTER_TAG_ALL
|
||||
#define FILE_FILTER_TAG_ALL "*.*" // Filter to include all file types and directories on directory scan
|
||||
#endif // NOTE: Used in ScanDirectoryFiles(), LoadDirectoryFilesEx() and GetDirectoryFileCountEx()
|
||||
#define FILE_FILTER_TAG_ALL "*.*" // Filter to include all file types and directories on scan
|
||||
#endif
|
||||
#ifndef FILE_FILTER_TAG_FILE_ONLY
|
||||
#define FILE_FILTER_TAG_FILE_ONLY "FILES*" // Filter to include all file types on directory scan
|
||||
#endif // NOTE: Used in ScanDirectoryFiles(), LoadDirectoryFilesEx() and GetDirectoryFileCountEx()
|
||||
#define FILE_FILTER_TAG_FILE_ONLY "FILES*" // Filter to include all file types on scan (no directories)
|
||||
#endif
|
||||
#ifndef FILE_FILTER_TAG_DIR_ONLY
|
||||
#define FILE_FILTER_TAG_DIR_ONLY "DIR*" // Filter to include directories on directory scan
|
||||
#endif // NOTE: Used in ScanDirectoryFiles(), LoadDirectoryFilesEx() and GetDirectoryFileCountEx()
|
||||
#define FILE_FILTER_TAG_DIR_ONLY "DIRS*" // Filter to include only directories on scan
|
||||
#endif
|
||||
|
||||
// Flags bitwise operation macros
|
||||
#define FLAG_SET(n, f) ((n) |= (f))
|
||||
|
|
@ -821,7 +824,7 @@ int GetRenderWidth(void)
|
|||
{
|
||||
int width = 0;
|
||||
|
||||
if (CORE.Window.usingFbo) return CORE.Window.currentFbo.width;
|
||||
if (CORE.Window.usingFbo) width = CORE.Window.currentFbo.width;
|
||||
else width = CORE.Window.render.width;
|
||||
|
||||
return width;
|
||||
|
|
@ -832,7 +835,7 @@ int GetRenderHeight(void)
|
|||
{
|
||||
int height = 0;
|
||||
|
||||
if (CORE.Window.usingFbo) return CORE.Window.currentFbo.height;
|
||||
if (CORE.Window.usingFbo) height = CORE.Window.currentFbo.height;
|
||||
else height = CORE.Window.render.height;
|
||||
|
||||
return height;
|
||||
|
|
@ -1227,7 +1230,7 @@ void UnloadVrStereoConfig(VrStereoConfig config)
|
|||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Load shader from files and bind default locations
|
||||
// NOTE: If shader string is NULL, using default vertex/fragment shaders
|
||||
// NOTE: If shader filename is NULL, using default vertex/fragment shaders
|
||||
Shader LoadShader(const char *vsFileName, const char *fsFileName)
|
||||
{
|
||||
Shader shader = { 0 };
|
||||
|
|
@ -1621,8 +1624,8 @@ int GetFPS(void)
|
|||
for (int i = 0; i < FPS_CAPTURE_FRAMES_COUNT; i++) history[i] = 0;
|
||||
}
|
||||
|
||||
if (fpsFrame == 0) return 0;
|
||||
|
||||
if (fpsFrame != 0)
|
||||
{
|
||||
if ((GetTime() - last) > FPS_STEP)
|
||||
{
|
||||
last = (float)GetTime();
|
||||
|
|
@ -1633,6 +1636,8 @@ int GetFPS(void)
|
|||
}
|
||||
|
||||
fps = (int)roundf(1.0f/average);
|
||||
}
|
||||
else fps = 0;
|
||||
#endif
|
||||
|
||||
return fps;
|
||||
|
|
@ -2025,7 +2030,7 @@ void UnloadFileData(unsigned char *data)
|
|||
// Save data to file from buffer
|
||||
bool SaveFileData(const char *fileName, void *data, int dataSize)
|
||||
{
|
||||
bool success = false;
|
||||
bool result = false;
|
||||
|
||||
if (fileName != NULL)
|
||||
{
|
||||
|
|
@ -2043,20 +2048,20 @@ bool SaveFileData(const char *fileName, void *data, int dataSize)
|
|||
else if (count != dataSize) TRACELOG(LOG_WARNING, "FILEIO: [%s] File partially written", fileName);
|
||||
else TRACELOG(LOG_INFO, "FILEIO: [%s] File saved successfully", fileName);
|
||||
|
||||
int result = fclose(file);
|
||||
if (result == 0) success = true;
|
||||
int closed = fclose(file);
|
||||
if (closed == 0) result = true;
|
||||
}
|
||||
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to open file", fileName);
|
||||
}
|
||||
else TRACELOG(LOG_WARNING, "FILEIO: File name provided is not valid");
|
||||
|
||||
return success;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Export data to code (.h), returns true on success
|
||||
bool ExportDataAsCode(const unsigned char *data, int dataSize, const char *fileName)
|
||||
{
|
||||
bool success = false;
|
||||
bool result = false;
|
||||
|
||||
#ifndef TEXT_BYTES_PER_LINE
|
||||
#define TEXT_BYTES_PER_LINE 20
|
||||
|
|
@ -2096,14 +2101,14 @@ bool ExportDataAsCode(const unsigned char *data, int dataSize, const char *fileN
|
|||
byteCount += sprintf(txtData + byteCount, "0x%x };\n", data[dataSize - 1]);
|
||||
|
||||
// NOTE: Text data size exported is determined by '\0' (NULL) character
|
||||
success = SaveFileText(fileName, txtData);
|
||||
result = SaveFileText(fileName, txtData);
|
||||
|
||||
RL_FREE(txtData);
|
||||
|
||||
if (success != 0) TRACELOG(LOG_INFO, "FILEIO: [%s] Data as code exported successfully", fileName);
|
||||
if (result != 0) TRACELOG(LOG_INFO, "FILEIO: [%s] Data as code exported successfully", fileName);
|
||||
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to export data as code", fileName);
|
||||
|
||||
return success;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Load text data from file, returns a '\0' terminated string
|
||||
|
|
@ -2166,7 +2171,7 @@ void UnloadFileText(char *text)
|
|||
// Save text data to file (write), string must be '\0' terminated
|
||||
bool SaveFileText(const char *fileName, const char *text)
|
||||
{
|
||||
bool success = false;
|
||||
bool result = false;
|
||||
|
||||
if (fileName != NULL)
|
||||
{
|
||||
|
|
@ -2181,14 +2186,14 @@ bool SaveFileText(const char *fileName, const char *text)
|
|||
if (count < 0) TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to write text file", fileName);
|
||||
else TRACELOG(LOG_INFO, "FILEIO: [%s] Text file saved successfully", fileName);
|
||||
|
||||
int result = fclose(file);
|
||||
if (result == 0) success = true;
|
||||
int closed = fclose(file);
|
||||
if (closed == 0) result = true;
|
||||
}
|
||||
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to open text file", fileName);
|
||||
}
|
||||
else TRACELOG(LOG_WARNING, "FILEIO: File name provided is not valid");
|
||||
|
||||
return success;
|
||||
return result;
|
||||
}
|
||||
|
||||
// File access custom callbacks
|
||||
|
|
@ -2298,7 +2303,7 @@ int FileTextReplace(const char *fileName, const char *search, const char *replac
|
|||
if (FileExists(fileName))
|
||||
{
|
||||
fileText = LoadFileText(fileName);
|
||||
fileTextUpdated = TextReplace(fileText, search, replacement);
|
||||
fileTextUpdated = TextReplaceAlloc(fileText, search, replacement);
|
||||
result = SaveFileText(fileName, fileTextUpdated);
|
||||
MemFree(fileTextUpdated);
|
||||
UnloadFileText(fileText);
|
||||
|
|
@ -2718,17 +2723,18 @@ const char *GetApplicationDirectory(void)
|
|||
|
||||
// Load directory filepaths
|
||||
// NOTE: Base path is prepended to the scanned filepaths
|
||||
// WARNING: Directory is scanned twice, first time to get files count
|
||||
// No recursive scanning is done!
|
||||
// WARNING: Directory is scanned twice, first time to get paths count
|
||||
// Scanneed files and directories, no recursive/subdirs scanning
|
||||
FilePathList LoadDirectoryFiles(const char *dirPath)
|
||||
{
|
||||
return LoadDirectoryFilesEx(dirPath, FILE_FILTER_TAG_ALL, false);
|
||||
}
|
||||
|
||||
// Load directory filepaths with extension filtering and recursive directory scan
|
||||
// Use 'DIR*' to include directories on directory scan
|
||||
// Use '*.*' to include all file types and directories on directory scan
|
||||
// WARNING: Directory is scanned twice, first time to get files count
|
||||
// Use "*.*" to include all files and directories on scan
|
||||
// Use "FILES*" to include only files on scan
|
||||
// Use "DIRS*" to include only directories on scan
|
||||
// WARNING: Directory is scanned twice, first time to get paths count
|
||||
FilePathList LoadDirectoryFilesEx(const char *basePath, const char *filter, bool scanSubdirs)
|
||||
{
|
||||
FilePathList files = { 0 };
|
||||
|
|
@ -3628,7 +3634,7 @@ void UnloadAutomationEventList(AutomationEventList list)
|
|||
// Export automation events list as text file
|
||||
bool ExportAutomationEventList(AutomationEventList list, const char *fileName)
|
||||
{
|
||||
bool success = false;
|
||||
bool result = false;
|
||||
|
||||
#if SUPPORT_AUTOMATION_EVENTS
|
||||
// Export events as binary file
|
||||
|
|
@ -3646,7 +3652,7 @@ bool ExportAutomationEventList(AutomationEventList list, const char *fileName)
|
|||
memcpy(binBuffer + offset, list.events, sizeof(AutomationEvent)*list.count);
|
||||
offset += sizeof(AutomationEvent)*list.count;
|
||||
|
||||
success = SaveFileData(TextFormat("%s.rae",fileName), binBuffer, binarySize);
|
||||
result = SaveFileData(TextFormat("%s.rae",fileName), binBuffer, binarySize);
|
||||
RL_FREE(binBuffer);
|
||||
}
|
||||
*/
|
||||
|
|
@ -3677,12 +3683,12 @@ bool ExportAutomationEventList(AutomationEventList list, const char *fileName)
|
|||
}
|
||||
|
||||
// NOTE: Text data size exported is determined by '\0' (NULL) character
|
||||
success = SaveFileText(fileName, txtData);
|
||||
result = SaveFileText(fileName, txtData);
|
||||
|
||||
RL_FREE(txtData);
|
||||
#endif
|
||||
|
||||
return success;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Setup automation event list to record to
|
||||
|
|
|
|||
12
src/rlgl.h
12
src/rlgl.h
|
|
@ -1613,6 +1613,11 @@ void rlNormal3f(float x, float y, float z)
|
|||
normaly = RLGL.State.transform.m1*x + RLGL.State.transform.m5*y + RLGL.State.transform.m9*z;
|
||||
normalz = RLGL.State.transform.m2*x + RLGL.State.transform.m6*y + RLGL.State.transform.m10*z;
|
||||
}
|
||||
|
||||
// NOTE: Default behavior assumes the normal vector is in the correct space for what the shader expects,
|
||||
// it could be not normalized to 0.0f..1.0f, magnitud can be useed for some effects
|
||||
/*
|
||||
// WARNING: Vector normalization if required
|
||||
float length = sqrtf(normalx*normalx + normaly*normaly + normalz*normalz);
|
||||
if (length != 0.0f)
|
||||
{
|
||||
|
|
@ -1621,6 +1626,7 @@ void rlNormal3f(float x, float y, float z)
|
|||
normaly *= ilength;
|
||||
normalz *= ilength;
|
||||
}
|
||||
*/
|
||||
RLGL.State.normalx = normalx;
|
||||
RLGL.State.normaly = normaly;
|
||||
RLGL.State.normalz = normalz;
|
||||
|
|
@ -4647,14 +4653,14 @@ void rlUpdateShaderBuffer(unsigned int id, const void *data, unsigned int dataSi
|
|||
// Get SSBO buffer size
|
||||
unsigned int rlGetShaderBufferSize(unsigned int id)
|
||||
{
|
||||
unsigned int result = 0;
|
||||
#if defined(GRAPHICS_API_OPENGL_43)
|
||||
GLint64 size = 0;
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, id);
|
||||
glGetBufferParameteri64v(GL_SHADER_STORAGE_BUFFER, GL_BUFFER_SIZE, &size);
|
||||
return (size > 0)? (unsigned int)size : 0;
|
||||
#else
|
||||
return 0;
|
||||
if (size > 0) result = (unsigned int)size;
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
// Read SSBO buffer data (GPU->CPU)
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
* #define SUPPORT_FILEFORMAT_MTL
|
||||
* #define SUPPORT_FILEFORMAT_IQM
|
||||
* #define SUPPORT_FILEFORMAT_GLTF
|
||||
* #define SUPPORT_FILEFORMAT_GLTF_WRITE
|
||||
* #define SUPPORT_FILEFORMAT_VOX
|
||||
* #define SUPPORT_FILEFORMAT_M3D
|
||||
* Selected desired fileformats to be supported for model data loading
|
||||
|
|
@ -71,6 +72,11 @@
|
|||
#define CGLTF_IMPLEMENTATION
|
||||
#include "external/cgltf.h" // glTF file format loading
|
||||
#endif
|
||||
#if SUPPORT_FILEFORMAT_GLTF_WRITE
|
||||
// NOTE: No need for custom allocators, memory buffer provided
|
||||
#define CGLTF_WRITE_IMPLEMENTATION
|
||||
#include "external/cgltf_write.h" // glTF file format writing
|
||||
#endif
|
||||
|
||||
#if SUPPORT_FILEFORMAT_VOX
|
||||
#define VOX_MALLOC RL_MALLOC
|
||||
|
|
@ -1281,7 +1287,6 @@ void UploadMesh(Mesh *mesh, bool dynamic)
|
|||
|
||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||
mesh->vaoId = rlLoadVertexArray();
|
||||
if (mesh->vaoId == 0) return;
|
||||
|
||||
rlEnableVertexArray(mesh->vaoId);
|
||||
|
||||
|
|
@ -1950,7 +1955,7 @@ void UnloadMesh(Mesh mesh)
|
|||
// Export mesh data to file
|
||||
bool ExportMesh(Mesh mesh, const char *fileName)
|
||||
{
|
||||
bool success = false;
|
||||
bool result = false;
|
||||
|
||||
if (IsFileExtension(fileName, ".obj"))
|
||||
{
|
||||
|
|
@ -2014,22 +2019,35 @@ bool ExportMesh(Mesh mesh, const char *fileName)
|
|||
}
|
||||
|
||||
// NOTE: Text data length exported is determined by '\0' (NULL) character
|
||||
success = SaveFileText(fileName, txtData);
|
||||
result = SaveFileText(fileName, txtData);
|
||||
|
||||
RL_FREE(txtData);
|
||||
}
|
||||
else if (IsFileExtension(fileName, ".gltf")) // Or .glb
|
||||
{
|
||||
// TODO: Implement gltf/glb support
|
||||
/*
|
||||
cgltf_size expected = cgltf_write(options, NULL, 0, data);
|
||||
char *buffer = (char *)RL_CALLOC(expected, 0);
|
||||
cgltf_size actual = cgltf_write(options, buffer, expected, data);
|
||||
|
||||
// NOTE: cgltf_write() includes a NULL terminator that should be ommited in case of a .glb
|
||||
if (options->type == cgltf_file_type_glb) cgltf_write_glb(file, buffer, actual - 1, data->bin, data->bin_size);
|
||||
else SaveFileText(fileName, buffer); // Write a plain JSON file
|
||||
*/
|
||||
}
|
||||
else if (IsFileExtension(fileName, ".raw"))
|
||||
{
|
||||
// TODO: Support additional file formats to export mesh vertex data
|
||||
}
|
||||
|
||||
return success;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Export mesh as code file (.h) defining multiple arrays of vertex attributes
|
||||
bool ExportMeshAsCode(Mesh mesh, const char *fileName)
|
||||
{
|
||||
bool success = false;
|
||||
bool result = false;
|
||||
|
||||
#ifndef TEXT_BYTES_PER_LINE
|
||||
#define TEXT_BYTES_PER_LINE 20
|
||||
|
|
@ -2113,14 +2131,14 @@ bool ExportMeshAsCode(Mesh mesh, const char *fileName)
|
|||
//-----------------------------------------------------------------------------------------
|
||||
|
||||
// NOTE: Text data size exported is determined by '\0' (NULL) character
|
||||
success = SaveFileText(fileName, txtData);
|
||||
result = SaveFileText(fileName, txtData);
|
||||
|
||||
RL_FREE(txtData);
|
||||
|
||||
//if (success != 0) TRACELOG(LOG_INFO, "FILEIO: [%s] Image as code exported successfully", fileName);
|
||||
//if (result != 0) TRACELOG(LOG_INFO, "FILEIO: [%s] Image as code exported successfully", fileName);
|
||||
//else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to export image as code", fileName);
|
||||
|
||||
return success;
|
||||
return result;
|
||||
}
|
||||
|
||||
#if SUPPORT_FILEFORMAT_OBJ || SUPPORT_FILEFORMAT_MTL
|
||||
|
|
@ -3961,32 +3979,6 @@ void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float
|
|||
rlDisableWireMode();
|
||||
}
|
||||
|
||||
// Draw a model points
|
||||
// WARNING: OpenGL ES 2.0 does not support point mode drawing
|
||||
void DrawModelPoints(Model model, Vector3 position, float scale, Color tint)
|
||||
{
|
||||
rlEnablePointMode();
|
||||
rlDisableBackfaceCulling();
|
||||
|
||||
DrawModel(model, position, scale, tint);
|
||||
|
||||
rlEnableBackfaceCulling();
|
||||
rlDisablePointMode();
|
||||
}
|
||||
|
||||
// Draw a model points
|
||||
// WARNING: OpenGL ES 2.0 does not support point mode drawing
|
||||
void DrawModelPointsEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint)
|
||||
{
|
||||
rlEnablePointMode();
|
||||
rlDisableBackfaceCulling();
|
||||
|
||||
DrawModelEx(model, position, rotationAxis, rotationAngle, scale, tint);
|
||||
|
||||
rlEnableBackfaceCulling();
|
||||
rlDisablePointMode();
|
||||
}
|
||||
|
||||
// Draw a billboard
|
||||
void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float scale, Color tint)
|
||||
{
|
||||
|
|
@ -5292,7 +5284,7 @@ static cgltf_result LoadFileGLTFCallback(const struct cgltf_memory_options *memo
|
|||
}
|
||||
|
||||
// Release file data callback for cgltf
|
||||
static void ReleaseFileGLTFCallback(const struct cgltf_memory_options *memoryOptions, const struct cgltf_file_options *fileOptions, void *data)
|
||||
static void ReleaseFileGLTFCallback(const struct cgltf_memory_options *memoryOptions, const struct cgltf_file_options *fileOptions, void *data, cgltf_size size)
|
||||
{
|
||||
UnloadFileData((unsigned char *)data);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2348,16 +2348,18 @@ bool CheckCollisionCircleRec(Vector2 center, float radius, Rectangle rec)
|
|||
float dx = fabsf(center.x - recCenterX);
|
||||
float dy = fabsf(center.y - recCenterY);
|
||||
|
||||
if (dx > (rec.width/2.0f + radius)) { return false; }
|
||||
if (dy > (rec.height/2.0f + radius)) { return false; }
|
||||
|
||||
if (dx <= (rec.width/2.0f)) { return true; }
|
||||
if (dy <= (rec.height/2.0f)) { return true; }
|
||||
|
||||
if ((dx <= (rec.width/2.0f + radius)) && (dy <= (rec.height/2.0f + radius)))
|
||||
{
|
||||
if (dx <= (rec.width/2.0f)) collision = true;
|
||||
else if (dy <= (rec.height/2.0f)) collision = true;
|
||||
else
|
||||
{
|
||||
float cornerDistanceSq = (dx - rec.width/2.0f)*(dx - rec.width/2.0f) +
|
||||
(dy - rec.height/2.0f)*(dy - rec.height/2.0f);
|
||||
|
||||
collision = (cornerDistanceSq <= (radius*radius));
|
||||
}
|
||||
}
|
||||
|
||||
return collision;
|
||||
}
|
||||
|
|
@ -2418,14 +2420,17 @@ bool CheckCollisionPointLine(Vector2 point, Vector2 p1, Vector2 p2, int threshol
|
|||
// Check if circle collides with a line created between two points [p1] and [p2]
|
||||
bool CheckCollisionCircleLine(Vector2 center, float radius, Vector2 p1, Vector2 p2)
|
||||
{
|
||||
bool collision = false;
|
||||
|
||||
float dx = p1.x - p2.x;
|
||||
float dy = p1.y - p2.y;
|
||||
|
||||
if ((fabsf(dx) + fabsf(dy)) <= FLT_EPSILON)
|
||||
{
|
||||
return CheckCollisionCircles(p1, 0, center, radius);
|
||||
collision = CheckCollisionCircles(p1, 0, center, radius);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
float lengthSQ = ((dx*dx) + (dy*dy));
|
||||
float dotProduct = (((center.x - p1.x)*(p2.x - p1.x)) + ((center.y - p1.y)*(p2.y - p1.y)))/(lengthSQ);
|
||||
|
||||
|
|
@ -2436,7 +2441,10 @@ bool CheckCollisionCircleLine(Vector2 center, float radius, Vector2 p1, Vector2
|
|||
float dy2 = (p1.y - (dotProduct*(dy))) - center.y;
|
||||
float distanceSQ = ((dx2*dx2) + (dy2*dy2));
|
||||
|
||||
return (distanceSQ <= radius*radius);
|
||||
if (distanceSQ <= radius*radius) collision = true;
|
||||
}
|
||||
|
||||
return collision;
|
||||
}
|
||||
|
||||
// Get collision rectangle for two rectangles collision
|
||||
|
|
|
|||
155
src/rtext.c
155
src/rtext.c
|
|
@ -1017,7 +1017,7 @@ void UnloadFont(Font font)
|
|||
// Export font as code file, returns true on success
|
||||
bool ExportFontAsCode(Font font, const char *fileName)
|
||||
{
|
||||
bool success = false;
|
||||
bool result = false;
|
||||
|
||||
#ifndef TEXT_BYTES_PER_LINE
|
||||
#define TEXT_BYTES_PER_LINE 20
|
||||
|
|
@ -1159,14 +1159,14 @@ bool ExportFontAsCode(Font font, const char *fileName)
|
|||
UnloadImage(image);
|
||||
|
||||
// NOTE: Text data size exported is determined by '\0' (NULL) character
|
||||
success = SaveFileText(fileName, txtData);
|
||||
result = SaveFileText(fileName, txtData);
|
||||
|
||||
RL_FREE(txtData);
|
||||
|
||||
if (success != 0) TRACELOG(LOG_INFO, "FILEIO: [%s] Font as code exported successfully", fileName);
|
||||
if (result != 0) TRACELOG(LOG_INFO, "FILEIO: [%s] Font as code exported successfully", fileName);
|
||||
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to export font as code", fileName);
|
||||
|
||||
return success;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Draw current FPS
|
||||
|
|
@ -1395,8 +1395,7 @@ Vector2 MeasureTextCodepoints(Font font, const int *codepoints, int length, floa
|
|||
{
|
||||
Vector2 textSize = { 0 };
|
||||
|
||||
// Security check
|
||||
if ((font.texture.id == 0) || (codepoints == NULL) || (length == 0)) return textSize;
|
||||
if ((font.texture.id == 0) || (codepoints == NULL) || (length == 0)) return textSize; // Security check
|
||||
|
||||
float textWidth = 0.0f;
|
||||
// Used to count longer text line width
|
||||
|
|
@ -1699,8 +1698,8 @@ const char *TextSubtext(const char *text, int position, int length)
|
|||
{
|
||||
int textLength = TextLength(text);
|
||||
|
||||
if (position >= textLength) return buffer; // First char is already '\0' by memset
|
||||
|
||||
if (position < textLength)
|
||||
{
|
||||
int maxLength = textLength - position;
|
||||
if (length > maxLength) length = maxLength;
|
||||
if (length >= MAX_TEXT_BUFFER_LENGTH) length = MAX_TEXT_BUFFER_LENGTH - 1;
|
||||
|
|
@ -1711,6 +1710,7 @@ const char *TextSubtext(const char *text, int position, int length)
|
|||
|
||||
buffer[length] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
|
@ -1736,8 +1736,6 @@ const char *TextRemoveSpaces(const char *text)
|
|||
// Get text between two strings
|
||||
char *GetTextBetween(const char *text, const char *begin, const char *end)
|
||||
{
|
||||
#define MAX_TEXT_BETWEEN_SIZE 1024
|
||||
|
||||
static char buffer[MAX_TEXT_BUFFER_LENGTH] = { 0 };
|
||||
memset(buffer, 0, MAX_TEXT_BUFFER_LENGTH);
|
||||
|
||||
|
|
@ -1752,8 +1750,8 @@ char *GetTextBetween(const char *text, const char *begin, const char *end)
|
|||
{
|
||||
endIndex += (beginIndex + beginLen);
|
||||
int len = (endIndex - beginIndex - beginLen);
|
||||
if (len < (MAX_TEXT_BETWEEN_SIZE - 1)) strncpy(buffer, text + beginIndex + beginLen, len);
|
||||
else strncpy(buffer, text + beginIndex + beginLen, MAX_TEXT_BETWEEN_SIZE - 1);
|
||||
if (len < (MAX_TEXT_BUFFER_LENGTH - 1)) strncpy(buffer, text + beginIndex + beginLen, len);
|
||||
else strncpy(buffer, text + beginIndex + beginLen, MAX_TEXT_BUFFER_LENGTH - 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1762,8 +1760,74 @@ char *GetTextBetween(const char *text, const char *begin, const char *end)
|
|||
|
||||
// Replace text string
|
||||
// REQUIRES: strstr(), strncpy()
|
||||
// WARNING: Allocated memory must be manually freed
|
||||
// NOTE: Limited text replace functionality, using static string
|
||||
char *TextReplace(const char *text, const char *search, const char *replacement)
|
||||
{
|
||||
static char buffer[MAX_TEXT_BUFFER_LENGTH] = { 0 };
|
||||
memset(buffer, 0, MAX_TEXT_BUFFER_LENGTH);
|
||||
|
||||
if ((text != NULL) && (search != NULL) && (search[0] != '\0'))
|
||||
{
|
||||
if (replacement == NULL) replacement = "";
|
||||
|
||||
char *insertPoint = NULL; // Next insert point
|
||||
char *tempPtr = NULL; // Temp pointer
|
||||
int textLen = 0; // Text string length
|
||||
int searchLen = 0; // Search string length of (the string to remove)
|
||||
int replaceLen = 0; // Replacement length (the string to replace by)
|
||||
int lastReplacePos = 0; // Distance between next search and end of last replace
|
||||
int count = 0; // Number of replacements
|
||||
|
||||
textLen = TextLength(text);
|
||||
searchLen = TextLength(search);
|
||||
replaceLen = TextLength(replacement);
|
||||
|
||||
// Count the number of replacements needed
|
||||
insertPoint = (char *)text;
|
||||
for (count = 0; (tempPtr = strstr(insertPoint, search)); count++) insertPoint = tempPtr + searchLen;
|
||||
|
||||
if ((textLen + count*(replaceLen - searchLen)) < (MAX_TEXT_BUFFER_LENGTH - 1))
|
||||
{
|
||||
// TODO: Allow copying data replaced up to maximum buffer size and stop
|
||||
|
||||
tempPtr = buffer; // Point to result start
|
||||
|
||||
// First time through the loop, all the variable are set correctly from here on,
|
||||
// - 'temp' points to the end of the result string
|
||||
// - 'insertPoint' points to the next occurrence of replace in text
|
||||
// - 'text' points to the remainder of text after "end of replace"
|
||||
while (count > 0)
|
||||
{
|
||||
insertPoint = (char *)strstr(text, search);
|
||||
lastReplacePos = (int)(insertPoint - text);
|
||||
|
||||
memcpy(tempPtr, text, lastReplacePos);
|
||||
tempPtr += lastReplacePos;
|
||||
|
||||
if (replaceLen > 0)
|
||||
{
|
||||
memcpy(tempPtr, replacement, replaceLen);
|
||||
tempPtr += replaceLen;
|
||||
}
|
||||
|
||||
text += (lastReplacePos + searchLen); // Move to next "end of replace"
|
||||
count--;
|
||||
}
|
||||
|
||||
// Copy remaind text part after replacement to result (pointed by moving temp)
|
||||
// NOTE: Text pointer internal copy has been updated along the process
|
||||
strncpy(tempPtr, text, TextLength(text));
|
||||
}
|
||||
else TRACELOG(LOG_WARNING, "Text with replacement is longer than internal buffer, use TextReplaceAlloc()");
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
// Replace text string
|
||||
// REQUIRES: strstr(), strncpy()
|
||||
// WARNING: Allocated memory must be manually freed
|
||||
char *TextReplaceAlloc(const char *text, const char *search, const char *replacement)
|
||||
{
|
||||
char *result = NULL;
|
||||
|
||||
|
|
@ -1825,11 +1889,46 @@ char *TextReplace(const char *text, const char *search, const char *replacement)
|
|||
return result;
|
||||
}
|
||||
|
||||
// Replace text between two specific strings
|
||||
// REQUIRES: strncpy()
|
||||
// NOTE: If (replacement == NULL) removes "begin"[ ]"end" text
|
||||
char *TextReplaceBetween(const char *text, const char *begin, const char *end, const char *replacement)
|
||||
{
|
||||
static char buffer[MAX_TEXT_BUFFER_LENGTH] = { 0 };
|
||||
memset(buffer, 0, MAX_TEXT_BUFFER_LENGTH);
|
||||
|
||||
if ((text != NULL) && (begin != NULL) && (end != NULL))
|
||||
{
|
||||
int beginIndex = TextFindIndex(text, begin);
|
||||
|
||||
if (beginIndex > -1)
|
||||
{
|
||||
int beginLen = TextLength(begin);
|
||||
int endIndex = TextFindIndex(text + beginIndex + beginLen, end);
|
||||
|
||||
if (endIndex > -1)
|
||||
{
|
||||
endIndex += (beginIndex + beginLen);
|
||||
|
||||
int textLen = TextLength(text);
|
||||
int replaceLen = (replacement == NULL)? 0 : TextLength(replacement);
|
||||
//int toreplaceLen = endIndex - beginIndex - beginLen;
|
||||
|
||||
strncpy(buffer, text, beginIndex + beginLen); // Copy first text part
|
||||
if (replacement != NULL) strncpy(buffer + beginIndex + beginLen, replacement, replaceLen); // Copy replacement (if provided)
|
||||
strncpy(buffer + beginIndex + beginLen + replaceLen, text + endIndex, textLen - endIndex); // Copy end text part
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
// Replace text between two specific strings
|
||||
// REQUIRES: strncpy()
|
||||
// NOTE: If (replacement == NULL) remove "begin"[ ]"end" text
|
||||
// WARNING: Returned string must be freed by user
|
||||
char *TextReplaceBetween(const char *text, const char *begin, const char *end, const char *replacement)
|
||||
char *TextReplaceBetweenAlloc(const char *text, const char *begin, const char *end, const char *replacement)
|
||||
{
|
||||
char *result = NULL;
|
||||
|
||||
|
|
@ -1864,6 +1963,34 @@ char *TextReplaceBetween(const char *text, const char *begin, const char *end, c
|
|||
// Insert text in a specific position, moves all text forward
|
||||
// WARNING: Allocated memory must be manually freed
|
||||
char *TextInsert(const char *text, const char *insert, int position)
|
||||
{
|
||||
static char buffer[MAX_TEXT_BUFFER_LENGTH] = { 0 };
|
||||
memset(buffer, 0, MAX_TEXT_BUFFER_LENGTH);
|
||||
|
||||
if ((text != NULL) && (insert != NULL))
|
||||
{
|
||||
int textLen = TextLength(text);
|
||||
int insertLen = TextLength(insert);
|
||||
|
||||
if ((textLen + insertLen) < (MAX_TEXT_BUFFER_LENGTH - 1))
|
||||
{
|
||||
// TODO: Allow copying data inserted up to maximum buffer size and stop
|
||||
|
||||
for (int i = 0; i < position; i++) buffer[i] = text[i];
|
||||
for (int i = position; i < insertLen + position; i++) buffer[i] = insert[i - position];
|
||||
for (int i = (insertLen + position); i < (textLen + insertLen); i++) buffer[i] = text[i];
|
||||
|
||||
buffer[textLen + insertLen] = '\0'; // Add EOL
|
||||
}
|
||||
else TRACELOG(LOG_WARNING, "Text with inserted string is longer than internal buffer, use TextInserExt()");
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
// Insert text in a specific position, moves all text forward
|
||||
// WARNING: Allocated memory must be manually freed
|
||||
char *TextInsertAlloc(const char *text, const char *insert, int position)
|
||||
{
|
||||
char *result = NULL;
|
||||
|
||||
|
|
|
|||
|
|
@ -376,8 +376,7 @@ Image LoadImageAnimFromMemory(const char *fileType, const unsigned char *fileDat
|
|||
Image image = { 0 };
|
||||
int frameCount = 0;
|
||||
|
||||
// Security check for input data
|
||||
if ((fileType == NULL) || (fileData == NULL) || (dataSize == 0)) return image;
|
||||
if ((fileType == NULL) || (fileData == NULL) || (dataSize == 0)) return image; // Security check
|
||||
|
||||
#if SUPPORT_FILEFORMAT_GIF
|
||||
if ((strcmp(fileType, ".gif") == 0) || (strcmp(fileType, ".GIF") == 0))
|
||||
|
|
@ -621,8 +620,7 @@ bool ExportImage(Image image, const char *fileName)
|
|||
{
|
||||
int result = 0;
|
||||
|
||||
// Security check for input data
|
||||
if ((image.width == 0) || (image.height == 0) || (image.data == NULL)) return result;
|
||||
if ((image.width == 0) || (image.height == 0) || (image.data == NULL)) return result; // Security check
|
||||
|
||||
#if SUPPORT_IMAGE_EXPORT
|
||||
int channels = 4;
|
||||
|
|
@ -709,8 +707,7 @@ unsigned char *ExportImageToMemory(Image image, const char *fileType, int *dataS
|
|||
unsigned char *fileData = NULL;
|
||||
*dataSize = 0;
|
||||
|
||||
// Security check for input data
|
||||
if ((image.width == 0) || (image.height == 0) || (image.data == NULL)) return NULL;
|
||||
if ((image.width == 0) || (image.height == 0) || (image.data == NULL)) return fileData; // Security check
|
||||
|
||||
int channels = 4;
|
||||
|
||||
|
|
@ -734,7 +731,7 @@ unsigned char *ExportImageToMemory(Image image, const char *fileType, int *dataS
|
|||
// Export image as code file (.h) defining an array of bytes
|
||||
bool ExportImageAsCode(Image image, const char *fileName)
|
||||
{
|
||||
bool success = false;
|
||||
bool result = false;
|
||||
|
||||
#ifndef TEXT_BYTES_PER_LINE
|
||||
#define TEXT_BYTES_PER_LINE 20
|
||||
|
|
@ -774,14 +771,14 @@ bool ExportImageAsCode(Image image, const char *fileName)
|
|||
byteCount += sprintf(txtData + byteCount, "0x%x };\n", ((unsigned char *)image.data)[dataSize - 1]);
|
||||
|
||||
// NOTE: Text data size exported is determined by '\0' (NULL) character
|
||||
success = SaveFileText(fileName, txtData);
|
||||
result = SaveFileText(fileName, txtData);
|
||||
|
||||
RL_FREE(txtData);
|
||||
|
||||
if (success != 0) TRACELOG(LOG_INFO, "FILEIO: [%s] Image as code exported successfully", fileName);
|
||||
if (result != 0) TRACELOG(LOG_INFO, "FILEIO: [%s] Image as code exported successfully", fileName);
|
||||
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to export image as code", fileName);
|
||||
|
||||
return success;
|
||||
return result;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
|
|
@ -1536,8 +1533,7 @@ Image ImageFromChannel(Image image, int selectedChannel)
|
|||
{
|
||||
Image result = { 0 };
|
||||
|
||||
// Security check to avoid program crash
|
||||
if ((image.data == NULL) || (image.width == 0) || (image.height == 0)) return result;
|
||||
if ((image.data == NULL) || (image.width == 0) || (image.height == 0)) return result; // Security check
|
||||
|
||||
// Check selected channel is valid
|
||||
if (selectedChannel < 0)
|
||||
|
|
@ -2937,7 +2933,7 @@ void ImageColorReplace(Image *image, Color color, Color replace)
|
|||
// NOTE: Memory allocated should be freed using UnloadImageColors();
|
||||
Color *LoadImageColors(Image image)
|
||||
{
|
||||
if ((image.width == 0) || (image.height == 0)) return NULL;
|
||||
if ((image.width == 0) || (image.height == 0)) return NULL; // Security check
|
||||
|
||||
Color *pixels = (Color *)RL_MALLOC(image.width*image.height*sizeof(Color));
|
||||
|
||||
|
|
@ -4903,11 +4899,11 @@ Vector3 ColorToHSV(Color color)
|
|||
float max = 0.0f;
|
||||
float delta = 0.0f;
|
||||
|
||||
min = rgb.x < rgb.y? rgb.x : rgb.y;
|
||||
min = min < rgb.z? min : rgb.z;
|
||||
min = (rgb.x < rgb.y)? rgb.x : rgb.y;
|
||||
min = (min < rgb.z)? min : rgb.z;
|
||||
|
||||
max = rgb.x > rgb.y? rgb.x : rgb.y;
|
||||
max = max > rgb.z? max : rgb.z;
|
||||
max = (rgb.x > rgb.y)? rgb.x : rgb.y;
|
||||
max = (max > rgb.z)? max : rgb.z;
|
||||
|
||||
hsv.z = max; // Value
|
||||
delta = max - min;
|
||||
|
|
@ -5093,7 +5089,7 @@ Color ColorAlpha(Color color, float alpha)
|
|||
// Get src alpha-blended into dst color with tint
|
||||
Color ColorAlphaBlend(Color dst, Color src, Color tint)
|
||||
{
|
||||
Color out = WHITE;
|
||||
Color result = WHITE;
|
||||
|
||||
// Apply color tint to source color
|
||||
src.r = (unsigned char)(((unsigned int)src.r*((unsigned int)tint.r+1)) >> 8);
|
||||
|
|
@ -5104,24 +5100,24 @@ Color ColorAlphaBlend(Color dst, Color src, Color tint)
|
|||
//#define COLORALPHABLEND_FLOAT
|
||||
#define COLORALPHABLEND_INTEGERS
|
||||
#if defined(COLORALPHABLEND_INTEGERS)
|
||||
if (src.a == 0) out = dst;
|
||||
else if (src.a == 255) out = src;
|
||||
if (src.a == 0) result = dst;
|
||||
else if (src.a == 255) result = src;
|
||||
else
|
||||
{
|
||||
unsigned int alpha = (unsigned int)src.a + 1; // Shifting by 8 (dividing by 256), so need to take that excess into account
|
||||
out.a = (unsigned char)(((unsigned int)alpha*256 + (unsigned int)dst.a*(256 - alpha)) >> 8);
|
||||
result.a = (unsigned char)(((unsigned int)alpha*256 + (unsigned int)dst.a*(256 - alpha)) >> 8);
|
||||
|
||||
if (out.a > 0)
|
||||
if (result.a > 0)
|
||||
{
|
||||
out.r = (unsigned char)((((unsigned int)src.r*alpha*256 + (unsigned int)dst.r*(unsigned int)dst.a*(256 - alpha))/out.a) >> 8);
|
||||
out.g = (unsigned char)((((unsigned int)src.g*alpha*256 + (unsigned int)dst.g*(unsigned int)dst.a*(256 - alpha))/out.a) >> 8);
|
||||
out.b = (unsigned char)((((unsigned int)src.b*alpha*256 + (unsigned int)dst.b*(unsigned int)dst.a*(256 - alpha))/out.a) >> 8);
|
||||
result.r = (unsigned char)((((unsigned int)src.r*alpha*256 + (unsigned int)dst.r*(unsigned int)dst.a*(256 - alpha))/result.a) >> 8);
|
||||
result.g = (unsigned char)((((unsigned int)src.g*alpha*256 + (unsigned int)dst.g*(unsigned int)dst.a*(256 - alpha))/result.a) >> 8);
|
||||
result.b = (unsigned char)((((unsigned int)src.b*alpha*256 + (unsigned int)dst.b*(unsigned int)dst.a*(256 - alpha))/result.a) >> 8);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(COLORALPHABLEND_FLOAT)
|
||||
if (src.a == 0) out = dst;
|
||||
else if (src.a == 255) out = src;
|
||||
if (src.a == 0) result = dst;
|
||||
else if (src.a == 255) result = src;
|
||||
else
|
||||
{
|
||||
Vector4 fdst = ColorNormalize(dst);
|
||||
|
|
@ -5138,11 +5134,11 @@ Color ColorAlphaBlend(Color dst, Color src, Color tint)
|
|||
fout.z = (fsrc.z*fsrc.w + fdst.z*fdst.w*(1 - fsrc.w))/fout.w;
|
||||
}
|
||||
|
||||
out = (Color){ (unsigned char)(fout.x*255.0f), (unsigned char)(fout.y*255.0f), (unsigned char)(fout.z*255.0f), (unsigned char)(fout.w*255.0f) };
|
||||
result = (Color){ (unsigned char)(fout.x*255.0f), (unsigned char)(fout.y*255.0f), (unsigned char)(fout.z*255.0f), (unsigned char)(fout.w*255.0f) };
|
||||
}
|
||||
#endif
|
||||
|
||||
return out;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Get color lerp interpolation between two colors, factor [0.0f..1.0f]
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@
|
|||
#define REXM_MAX_BUFFER_SIZE (2*1024*1024) // 2MB
|
||||
|
||||
#define REXM_MAX_RESOURCE_PATHS 256
|
||||
#define REXM_MAX_RESOURCE_PATH_LENGTH 256
|
||||
|
||||
// Create local commit with changes on example renaming
|
||||
//#define RENAME_AUTO_COMMIT_CREATION
|
||||
|
|
@ -469,12 +470,12 @@ int main(int argc, char *argv[])
|
|||
int exIndex = TextFindIndex(exText, "/****************");
|
||||
|
||||
// Update required info with some defaults
|
||||
exTextUpdated[0] = TextReplace(exText + exIndex, "<module>", exCategory);
|
||||
exTextUpdated[1] = TextReplace(exTextUpdated[0], "<name>", exName + strlen(exCategory) + 1);
|
||||
//TextReplace(newExample, "<user_name>", "Ray");
|
||||
//TextReplace(newExample, "@<user_github>", "@raysan5");
|
||||
//TextReplace(newExample, "<year_created>", 2025);
|
||||
//TextReplace(newExample, "<year_updated>", 2025);
|
||||
exTextUpdated[0] = TextReplaceAlloc(exText + exIndex, "<module>", exCategory);
|
||||
exTextUpdated[1] = TextReplaceAlloc(exTextUpdated[0], "<name>", exName + strlen(exCategory) + 1);
|
||||
//TextReplaceAlloc(newExample, "<user_name>", "Ray");
|
||||
//TextReplaceAlloc(newExample, "@<user_github>", "@raysan5");
|
||||
//TextReplaceAlloc(newExample, "<year_created>", 2025);
|
||||
//TextReplaceAlloc(newExample, "<year_updated>", 2025);
|
||||
|
||||
SaveFileText(TextFormat("%s/%s/%s.c", exBasePath, exCategory, exName), exTextUpdated[1]);
|
||||
for (int i = 0; i < 6; i++) { MemFree(exTextUpdated[i]); exTextUpdated[i] = NULL; }
|
||||
|
|
@ -541,8 +542,6 @@ int main(int argc, char *argv[])
|
|||
else LOG("WARNING: Example resource must be placed in 'resources' directory next to .c file\n");
|
||||
}
|
||||
else LOG("WARNING: Example resource can not be found in: %s\n", TextFormat("%s/%s", GetDirectoryPath(inFileName), resPathUpdated));
|
||||
|
||||
RL_FREE(resPathUpdated);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -863,9 +862,7 @@ int main(int argc, char *argv[])
|
|||
|
||||
for (int v = 0; v < 3; v++)
|
||||
{
|
||||
char *resPathUpdated = TextReplace(resPaths[r], "glsl%i", TextFormat("glsl%i", glslVer[v]));
|
||||
FileRemove(TextFormat("%s/%s/%s", exBasePath, exCategory, resPathUpdated));
|
||||
RL_FREE(resPathUpdated);
|
||||
FileRemove(TextFormat("%s/%s/%s", exBasePath, exCategory, TextReplace(resPaths[r], "glsl%i", TextFormat("glsl%i", glslVer[v]))));
|
||||
}
|
||||
}
|
||||
else FileRemove(TextFormat("%s/%s/%s", exBasePath, exCategory, resPaths[r]));
|
||||
|
|
@ -1164,7 +1161,6 @@ int main(int argc, char *argv[])
|
|||
// Logging missing resources for convenience
|
||||
LOG("WARNING: [%s] Missing resource: %s\n", exInfo->name, resPathUpdated);
|
||||
}
|
||||
RL_FREE(resPathUpdated);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -1577,13 +1573,13 @@ int main(int argc, char *argv[])
|
|||
" SaveFileText(\"outputLogFileName\", logText);\n"
|
||||
" emscripten_run_script(\"saveFileFromMEMFSToDisk('outputLogFileName','outputLogFileName')\");\n\n"
|
||||
" return 0";
|
||||
char *returnReplaceTextUpdated = TextReplace(returnReplaceText, "outputLogFileName", TextFormat("%s.log", exName));
|
||||
char *returnReplaceTextUpdated = TextReplaceAlloc(returnReplaceText, "outputLogFileName", TextFormat("%s.log", exName));
|
||||
|
||||
char *srcTextUpdated[4] = { 0 };
|
||||
srcTextUpdated[0] = TextReplace(srcText, "int main(void)\n{", mainReplaceText);
|
||||
srcTextUpdated[1] = TextReplace(srcTextUpdated[0], "WindowShouldClose()", "WindowShouldClose() && (testFramesCount < requestedTestFrames)");
|
||||
srcTextUpdated[2] = TextReplace(srcTextUpdated[1], "EndDrawing();", "EndDrawing(); testFramesCount++;");
|
||||
srcTextUpdated[3] = TextReplace(srcTextUpdated[2], " return 0", returnReplaceTextUpdated);
|
||||
srcTextUpdated[0] = TextReplaceAlloc(srcText, "int main(void)\n{", mainReplaceText);
|
||||
srcTextUpdated[1] = TextReplaceAlloc(srcTextUpdated[0], "WindowShouldClose()", "WindowShouldClose() && (testFramesCount < requestedTestFrames)");
|
||||
srcTextUpdated[2] = TextReplaceAlloc(srcTextUpdated[1], "EndDrawing();", "EndDrawing(); testFramesCount++;");
|
||||
srcTextUpdated[3] = TextReplaceAlloc(srcTextUpdated[2], " return 0", returnReplaceTextUpdated);
|
||||
MemFree(returnReplaceTextUpdated);
|
||||
UnloadFileText(srcText);
|
||||
|
||||
|
|
@ -1633,9 +1629,9 @@ int main(int argc, char *argv[])
|
|||
" if ((argc > 1) && (argc == 3) && (strcmp(argv[1], \"--frames\") != 0)) requestedTestFrames = atoi(argv[2]);\n";
|
||||
|
||||
char *srcTextUpdated[3] = { 0 };
|
||||
srcTextUpdated[0] = TextReplace(srcText, "int main(void)\n{", mainReplaceText);
|
||||
srcTextUpdated[1] = TextReplace(srcTextUpdated[0], "WindowShouldClose()", "WindowShouldClose() && (testFramesCount < requestedTestFrames)");
|
||||
srcTextUpdated[2] = TextReplace(srcTextUpdated[1], "EndDrawing();", "EndDrawing(); testFramesCount++;");
|
||||
srcTextUpdated[0] = TextReplaceAlloc(srcText, "int main(void)\n{", mainReplaceText);
|
||||
srcTextUpdated[1] = TextReplaceAlloc(srcTextUpdated[0], "WindowShouldClose()", "WindowShouldClose() && (testFramesCount < requestedTestFrames)");
|
||||
srcTextUpdated[2] = TextReplaceAlloc(srcTextUpdated[1], "EndDrawing();", "EndDrawing(); testFramesCount++;");
|
||||
UnloadFileText(srcText);
|
||||
|
||||
SaveFileText(TextFormat("%s/%s/%s.c", exBasePath, exCategory, exName), srcTextUpdated[2]);
|
||||
|
|
@ -2042,7 +2038,7 @@ static int UpdateRequiredFiles(void)
|
|||
// In this case, we focus on web building for: glsl100
|
||||
if (TextFindIndex(resPaths[r], "glsl%i") > -1)
|
||||
{
|
||||
char *resPathUpdated = TextReplace(resPaths[r], "glsl%i", "glsl100");
|
||||
char *resPathUpdated = TextReplaceAlloc(resPaths[r], "glsl%i", "glsl100");
|
||||
memset(resPaths[r], 0, 256);
|
||||
strcpy(resPaths[r], resPathUpdated);
|
||||
RL_FREE(resPathUpdated);
|
||||
|
|
@ -2147,7 +2143,7 @@ static int UpdateRequiredFiles(void)
|
|||
{
|
||||
mdIndex += sprintf(mdTextUpdated + mdListStartIndex + mdIndex, TextFormat("\n### category: shaders [%i]\n\n", exCollectionCount));
|
||||
mdIndex += sprintf(mdTextUpdated + mdListStartIndex + mdIndex,
|
||||
"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.\n\n");
|
||||
"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.h) module.\n\n");
|
||||
}
|
||||
else if (i == 6) // "audio"
|
||||
{
|
||||
|
|
@ -2498,25 +2494,21 @@ static void SortExampleByName(rlExampleInfo *items, int count)
|
|||
qsort(items, count, sizeof(rlExampleInfo), rlExampleInfoCompare);
|
||||
}
|
||||
|
||||
// Scan resource paths in example file
|
||||
// WARNING: Supported resource file extensions is hardcoded by used file types
|
||||
// but new examples could require other file extensions to be added,
|
||||
// maybe it should look for '.xxx")' patterns instead
|
||||
// TODO: WARNING: Some resources could require linked resources: .fnt --> .png, .mtl --> .png, .gltf --> .png, ...
|
||||
static char **LoadExampleResourcePaths(const char *filePath, int *resPathCount)
|
||||
// Scan asset paths from a source code file (raylib)
|
||||
// WARNING: Supported asset file extensions are hardcoded by used file types
|
||||
// but new examples could require other file extensions to be added
|
||||
static char **LoadExampleResourcePaths(const char *srcFilePath, int *resPathCount)
|
||||
{
|
||||
#define REXM_MAX_RESOURCE_PATH_LEN 256
|
||||
|
||||
char **paths = (char **)RL_CALLOC(REXM_MAX_RESOURCE_PATHS, sizeof(char **));
|
||||
for (int i = 0; i < REXM_MAX_RESOURCE_PATHS; i++) paths[i] = (char *)RL_CALLOC(REXM_MAX_RESOURCE_PATH_LEN, sizeof(char));
|
||||
for (int i = 0; i < REXM_MAX_RESOURCE_PATHS; i++) paths[i] = (char *)RL_CALLOC(REXM_MAX_RESOURCE_PATH_LENGTH, sizeof(char));
|
||||
|
||||
int resCounter = 0;
|
||||
char *code = LoadFileText(filePath);
|
||||
char *code = LoadFileText(srcFilePath);
|
||||
|
||||
if (code != NULL)
|
||||
{
|
||||
// Resources extensions to check
|
||||
const char *exts[] = { ".png", ".bmp", ".jpg", ".qoi", ".gif", ".raw", ".hdr", ".ttf", ".fnt", ".wav", ".ogg", ".mp3", ".flac", ".mod", ".qoa", ".obj", ".iqm", ".glb", ".m3d", ".vox", ".vs", ".fs", ".txt" };
|
||||
const char *exts[] = { ".png", ".bmp", ".jpg", ".qoi", ".gif", ".raw", ".hdr", ".ttf", ".fnt", ".wav", ".ogg", ".mp3", ".flac", ".mod", ".xm", ".qoa", ".obj", ".iqm", ".glb", ".m3d", ".vox", ".vs", ".fs", ".txt" };
|
||||
const int extCount = sizeof(exts)/sizeof(char *);
|
||||
|
||||
char *ptr = code;
|
||||
|
|
@ -2542,9 +2534,9 @@ static char **LoadExampleResourcePaths(const char *filePath, int *resPathCount)
|
|||
!((functionIndex05 != -1) && (functionIndex05 < 40))) // Not found SaveFileText() before ""
|
||||
{
|
||||
int len = (int)(end - start);
|
||||
if ((len > 0) && (len < REXM_MAX_RESOURCE_PATH_LEN))
|
||||
if ((len > 0) && (len < REXM_MAX_RESOURCE_PATH_LENGTH))
|
||||
{
|
||||
char buffer[REXM_MAX_RESOURCE_PATH_LEN] = { 0 };
|
||||
char buffer[REXM_MAX_RESOURCE_PATH_LENGTH] = { 0 };
|
||||
strncpy(buffer, start, len);
|
||||
buffer[len] = '\0';
|
||||
|
||||
|
|
@ -2580,6 +2572,29 @@ static char **LoadExampleResourcePaths(const char *filePath, int *resPathCount)
|
|||
UnloadFileText(code);
|
||||
}
|
||||
|
||||
/*
|
||||
// WARNING: Some resources could require linked resources: .fnt --> .png, .mtl --> .png, .gltf --> .png
|
||||
// So doing a recursive pass to scan possible files with second resources
|
||||
int currentAssetCounter = resCounter;
|
||||
for (int i = 0; i < currentAssetCounter; i++)
|
||||
{
|
||||
if (IsFileExtension(paths[i], ".fnt;.gltf"))
|
||||
{
|
||||
int assetCount2 = 0;
|
||||
// ERROR: srcFilePath changes on rcursive call and TextFormat() static arrays are override
|
||||
char **assetPaths2 = LoadExampleResourcePaths(TextFormat("%s/%s", GetDirectoryPath(srcFilePath), paths[i]), &assetCount2);
|
||||
|
||||
for (int j = 0; j < assetCount2; j++)
|
||||
{
|
||||
strcpy(paths[resCounter], TextFormat("%s/%s", GetDirectoryPath(paths[i]) + 2, assetPaths2[j]));
|
||||
resCounter++;
|
||||
}
|
||||
|
||||
UnloadExampleResourcePaths(assetPaths2);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
*resPathCount = resCounter;
|
||||
return paths;
|
||||
}
|
||||
|
|
@ -2815,7 +2830,7 @@ static void UpdateSourceMetadata(const char *exSrcPath, const rlExampleInfo *inf
|
|||
|
||||
// Update example header title (line #3 - ALWAYS)
|
||||
// String: "* raylib [shaders] example - texture drawing"
|
||||
exTextUpdated[0] = TextReplaceBetween(exTextUpdatedPtr, "* raylib [", "\n",
|
||||
exTextUpdated[0] = TextReplaceBetweenAlloc(exTextUpdatedPtr, "* raylib [", "\n",
|
||||
TextFormat("%s] example - %s", info->category, exNameFormated));
|
||||
if (exTextUpdated[0] != NULL) exTextUpdatedPtr = exTextUpdated[0];
|
||||
|
||||
|
|
@ -2829,13 +2844,13 @@ static void UpdateSourceMetadata(const char *exSrcPath, const rlExampleInfo *inf
|
|||
if (i < info->stars) strcpy(starsText + 3*i, "★");
|
||||
else strcpy(starsText + 3*i, "☆");
|
||||
}
|
||||
exTextUpdated[1] = TextReplaceBetween(exTextUpdatedPtr, "* Example complexity rating: [", "/4\n",
|
||||
exTextUpdated[1] = TextReplaceBetweenAlloc(exTextUpdatedPtr, "* Example complexity rating: [", "/4\n",
|
||||
TextFormat("%s] %i", starsText, info->stars));
|
||||
if (exTextUpdated[1] != NULL) exTextUpdatedPtr = exTextUpdated[1];
|
||||
|
||||
// Update example creation/update raylib versions
|
||||
// String: "* Example originally created with raylib 2.0, last time updated with raylib 3.7
|
||||
exTextUpdated[2] = TextReplaceBetween(exTextUpdatedPtr, "* Example originally created with raylib ", "\n",
|
||||
exTextUpdated[2] = TextReplaceBetweenAlloc(exTextUpdatedPtr, "* Example originally created with raylib ", "\n",
|
||||
TextFormat("%s, last time updated with raylib %s", info->verCreated, info->verUpdated));
|
||||
if (exTextUpdated[2] != NULL) exTextUpdatedPtr = exTextUpdated[2];
|
||||
|
||||
|
|
@ -2843,27 +2858,27 @@ static void UpdateSourceMetadata(const char *exSrcPath, const rlExampleInfo *inf
|
|||
// String: "* Copyright (c) 2019-2026 Contributor Name (@github_user) and Ramon Santamaria (@raysan5)"
|
||||
if (info->yearCreated == info->yearReviewed)
|
||||
{
|
||||
exTextUpdated[3] = TextReplaceBetween(exTextUpdatedPtr, "Copyright (c) ", ")",
|
||||
exTextUpdated[3] = TextReplaceBetweenAlloc(exTextUpdatedPtr, "Copyright (c) ", ")",
|
||||
TextFormat("%i %s (@%s", info->yearCreated, info->author, info->authorGitHub));
|
||||
if (exTextUpdated[3] != NULL) exTextUpdatedPtr = exTextUpdated[3];
|
||||
}
|
||||
else
|
||||
{
|
||||
exTextUpdated[3] = TextReplaceBetween(exTextUpdatedPtr, "Copyright (c) ", ")",
|
||||
exTextUpdated[3] = TextReplaceBetweenAlloc(exTextUpdatedPtr, "Copyright (c) ", ")",
|
||||
TextFormat("%i-%i %s (@%s", info->yearCreated, info->yearReviewed, info->author, info->authorGitHub));
|
||||
if (exTextUpdated[3] != NULL) exTextUpdatedPtr = exTextUpdated[3];
|
||||
}
|
||||
|
||||
// Update window title
|
||||
// String: "InitWindow(screenWidth, screenHeight, "raylib [shaders] example - texture drawing");"
|
||||
exTextUpdated[4] = TextReplaceBetween(exTextUpdated[3], "InitWindow(screenWidth, screenHeight, \"", "\");",
|
||||
exTextUpdated[4] = TextReplaceBetweenAlloc(exTextUpdated[3], "InitWindow(screenWidth, screenHeight, \"", "\");",
|
||||
TextFormat("raylib [%s] example - %s", info->category, exNameFormated));
|
||||
if (exTextUpdated[4] != NULL) exTextUpdatedPtr = exTextUpdated[4];
|
||||
|
||||
// Update contributors names
|
||||
// String: "* Example contributed by Contributor Name (@github_user) and reviewed by Ramon Santamaria (@raysan5)"
|
||||
// WARNING: Not all examples are contributed by someone, so the result of this replace can be NULL (string not found)
|
||||
exTextUpdated[5] = TextReplaceBetween(exTextUpdatedPtr, "* Example contributed by ", ")",
|
||||
exTextUpdated[5] = TextReplaceBetweenAlloc(exTextUpdatedPtr, "* Example contributed by ", ")",
|
||||
TextFormat("%s (@%s", info->author, info->authorGitHub));
|
||||
if (exTextUpdated[5] != NULL) exTextUpdatedPtr = exTextUpdated[5];
|
||||
|
||||
|
|
@ -2910,14 +2925,14 @@ static void UpdateWebMetadata(const char *exHtmlPath, const char *exFilePath)
|
|||
UnloadFileText(exText);
|
||||
|
||||
// Update example.html required text
|
||||
exHtmlTextUpdated[0] = TextReplace(exHtmlText, "raylib web game", exTitle);
|
||||
exHtmlTextUpdated[1] = TextReplace(exHtmlTextUpdated[0], "New raylib web videogame, developed using raylib videogames library", exDescription);
|
||||
exHtmlTextUpdated[2] = TextReplace(exHtmlTextUpdated[1], "https://www.raylib.com/common/raylib_logo.png",
|
||||
exHtmlTextUpdated[0] = TextReplaceAlloc(exHtmlText, "raylib web game", exTitle);
|
||||
exHtmlTextUpdated[1] = TextReplaceAlloc(exHtmlTextUpdated[0], "New raylib web videogame, developed using raylib videogames library", exDescription);
|
||||
exHtmlTextUpdated[2] = TextReplaceAlloc(exHtmlTextUpdated[1], "https://www.raylib.com/common/raylib_logo.png",
|
||||
TextFormat("https://raw.githubusercontent.com/raysan5/raylib/master/examples/%s/%s.png", exCategory, exName));
|
||||
exHtmlTextUpdated[3] = TextReplace(exHtmlTextUpdated[2], "https://www.raylib.com/games.html",
|
||||
exHtmlTextUpdated[3] = TextReplaceAlloc(exHtmlTextUpdated[2], "https://www.raylib.com/games.html",
|
||||
TextFormat("https://www.raylib.com/examples/%s/%s.html", exCategory, exName));
|
||||
exHtmlTextUpdated[4] = TextReplace(exHtmlTextUpdated[3], "raylib - example", TextFormat("raylib - %s", exName)); // og:site_name
|
||||
exHtmlTextUpdated[5] = TextReplace(exHtmlTextUpdated[4], "https://github.com/raysan5/raylib",
|
||||
exHtmlTextUpdated[4] = TextReplaceAlloc(exHtmlTextUpdated[3], "raylib - example", TextFormat("raylib - %s", exName)); // og:site_name
|
||||
exHtmlTextUpdated[5] = TextReplaceAlloc(exHtmlTextUpdated[4], "https://github.com/raysan5/raylib",
|
||||
TextFormat("https://github.com/raysan5/raylib/blob/master/examples/%s/%s.c", exCategory, exName));
|
||||
|
||||
SaveFileText(exHtmlPathCopy, exHtmlTextUpdated[5]);
|
||||
|
|
|
|||
|
|
@ -4685,7 +4685,7 @@
|
|||
},
|
||||
{
|
||||
"name": "LoadDirectoryFiles",
|
||||
"description": "Load directory filepaths",
|
||||
"description": "Load directory filepaths, files and directories, no subdirs scan",
|
||||
"returnType": "FilePathList",
|
||||
"params": [
|
||||
{
|
||||
|
|
@ -4696,7 +4696,7 @@
|
|||
},
|
||||
{
|
||||
"name": "LoadDirectoryFilesEx",
|
||||
"description": "Load directory filepaths with extension filtering and recursive directory scan. Use 'DIR' in the filter string to include directories in the result",
|
||||
"description": "Load directory filepaths with extension filtering and subdir scan; some filters available: "*.*", "FILES*", "DIRS*"",
|
||||
"returnType": "FilePathList",
|
||||
"params": [
|
||||
{
|
||||
|
|
@ -7231,7 +7231,7 @@
|
|||
},
|
||||
{
|
||||
"name": "ExportImageToMemory",
|
||||
"description": "Export image to memory buffer",
|
||||
"description": "Export image to memory buffer, memory must be MemFree()",
|
||||
"returnType": "unsigned char *",
|
||||
"params": [
|
||||
{
|
||||
|
|
@ -9946,7 +9946,26 @@
|
|||
},
|
||||
{
|
||||
"name": "TextReplace",
|
||||
"description": "Replace text string (WARNING: memory must be freed!)",
|
||||
"description": "Replace text string with new string",
|
||||
"returnType": "char *",
|
||||
"params": [
|
||||
{
|
||||
"type": "const char *",
|
||||
"name": "text"
|
||||
},
|
||||
{
|
||||
"type": "const char *",
|
||||
"name": "search"
|
||||
},
|
||||
{
|
||||
"type": "const char *",
|
||||
"name": "replacement"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "TextReplaceAlloc",
|
||||
"description": "Replace text string with new string, memory must be MemFree()",
|
||||
"returnType": "char *",
|
||||
"params": [
|
||||
{
|
||||
|
|
@ -9965,7 +9984,30 @@
|
|||
},
|
||||
{
|
||||
"name": "TextReplaceBetween",
|
||||
"description": "Replace text between two specific strings (WARNING: memory must be freed!)",
|
||||
"description": "Replace text between two specific strings",
|
||||
"returnType": "char *",
|
||||
"params": [
|
||||
{
|
||||
"type": "const char *",
|
||||
"name": "text"
|
||||
},
|
||||
{
|
||||
"type": "const char *",
|
||||
"name": "begin"
|
||||
},
|
||||
{
|
||||
"type": "const char *",
|
||||
"name": "end"
|
||||
},
|
||||
{
|
||||
"type": "const char *",
|
||||
"name": "replacement"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "TextReplaceBetweenAlloc",
|
||||
"description": "Replace text between two specific strings, memory must be MemFree()",
|
||||
"returnType": "char *",
|
||||
"params": [
|
||||
{
|
||||
|
|
@ -9988,7 +10030,26 @@
|
|||
},
|
||||
{
|
||||
"name": "TextInsert",
|
||||
"description": "Insert text in a position (WARNING: memory must be freed!)",
|
||||
"description": "Insert text in a defined byte position",
|
||||
"returnType": "char *",
|
||||
"params": [
|
||||
{
|
||||
"type": "const char *",
|
||||
"name": "text"
|
||||
},
|
||||
{
|
||||
"type": "const char *",
|
||||
"name": "insert"
|
||||
},
|
||||
{
|
||||
"type": "int",
|
||||
"name": "position"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "TextInsertAlloc",
|
||||
"description": "Insert text in a defined byte position, memory must be MemFree()",
|
||||
"returnType": "char *",
|
||||
"params": [
|
||||
{
|
||||
|
|
@ -10820,60 +10881,6 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "DrawModelPoints",
|
||||
"description": "Draw a model as points",
|
||||
"returnType": "void",
|
||||
"params": [
|
||||
{
|
||||
"type": "Model",
|
||||
"name": "model"
|
||||
},
|
||||
{
|
||||
"type": "Vector3",
|
||||
"name": "position"
|
||||
},
|
||||
{
|
||||
"type": "float",
|
||||
"name": "scale"
|
||||
},
|
||||
{
|
||||
"type": "Color",
|
||||
"name": "tint"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "DrawModelPointsEx",
|
||||
"description": "Draw a model as points with extended parameters",
|
||||
"returnType": "void",
|
||||
"params": [
|
||||
{
|
||||
"type": "Model",
|
||||
"name": "model"
|
||||
},
|
||||
{
|
||||
"type": "Vector3",
|
||||
"name": "position"
|
||||
},
|
||||
{
|
||||
"type": "Vector3",
|
||||
"name": "rotationAxis"
|
||||
},
|
||||
{
|
||||
"type": "float",
|
||||
"name": "rotationAngle"
|
||||
},
|
||||
{
|
||||
"type": "Vector3",
|
||||
"name": "scale"
|
||||
},
|
||||
{
|
||||
"type": "Color",
|
||||
"name": "tint"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "DrawBoundingBox",
|
||||
"description": "Draw bounding box (wires)",
|
||||
|
|
|
|||
|
|
@ -4199,7 +4199,7 @@ return {
|
|||
},
|
||||
{
|
||||
name = "LoadDirectoryFiles",
|
||||
description = "Load directory filepaths",
|
||||
description = "Load directory filepaths, files and directories, no subdirs scan",
|
||||
returnType = "FilePathList",
|
||||
params = {
|
||||
{type = "const char *", name = "dirPath"}
|
||||
|
|
@ -4207,7 +4207,7 @@ return {
|
|||
},
|
||||
{
|
||||
name = "LoadDirectoryFilesEx",
|
||||
description = "Load directory filepaths with extension filtering and recursive directory scan. Use 'DIR' in the filter string to include directories in the result",
|
||||
description = "Load directory filepaths with extension filtering and subdir scan; some filters available: "*.*", "FILES*", "DIRS*"",
|
||||
returnType = "FilePathList",
|
||||
params = {
|
||||
{type = "const char *", name = "basePath"},
|
||||
|
|
@ -5596,7 +5596,7 @@ return {
|
|||
},
|
||||
{
|
||||
name = "ExportImageToMemory",
|
||||
description = "Export image to memory buffer",
|
||||
description = "Export image to memory buffer, memory must be MemFree()",
|
||||
returnType = "unsigned char *",
|
||||
params = {
|
||||
{type = "Image", name = "image"},
|
||||
|
|
@ -7045,7 +7045,17 @@ return {
|
|||
},
|
||||
{
|
||||
name = "TextReplace",
|
||||
description = "Replace text string (WARNING: memory must be freed!)",
|
||||
description = "Replace text string with new string",
|
||||
returnType = "char *",
|
||||
params = {
|
||||
{type = "const char *", name = "text"},
|
||||
{type = "const char *", name = "search"},
|
||||
{type = "const char *", name = "replacement"}
|
||||
}
|
||||
},
|
||||
{
|
||||
name = "TextReplaceAlloc",
|
||||
description = "Replace text string with new string, memory must be MemFree()",
|
||||
returnType = "char *",
|
||||
params = {
|
||||
{type = "const char *", name = "text"},
|
||||
|
|
@ -7055,7 +7065,18 @@ return {
|
|||
},
|
||||
{
|
||||
name = "TextReplaceBetween",
|
||||
description = "Replace text between two specific strings (WARNING: memory must be freed!)",
|
||||
description = "Replace text between two specific strings",
|
||||
returnType = "char *",
|
||||
params = {
|
||||
{type = "const char *", name = "text"},
|
||||
{type = "const char *", name = "begin"},
|
||||
{type = "const char *", name = "end"},
|
||||
{type = "const char *", name = "replacement"}
|
||||
}
|
||||
},
|
||||
{
|
||||
name = "TextReplaceBetweenAlloc",
|
||||
description = "Replace text between two specific strings, memory must be MemFree()",
|
||||
returnType = "char *",
|
||||
params = {
|
||||
{type = "const char *", name = "text"},
|
||||
|
|
@ -7066,7 +7087,17 @@ return {
|
|||
},
|
||||
{
|
||||
name = "TextInsert",
|
||||
description = "Insert text in a position (WARNING: memory must be freed!)",
|
||||
description = "Insert text in a defined byte position",
|
||||
returnType = "char *",
|
||||
params = {
|
||||
{type = "const char *", name = "text"},
|
||||
{type = "const char *", name = "insert"},
|
||||
{type = "int", name = "position"}
|
||||
}
|
||||
},
|
||||
{
|
||||
name = "TextInsertAlloc",
|
||||
description = "Insert text in a defined byte position, memory must be MemFree()",
|
||||
returnType = "char *",
|
||||
params = {
|
||||
{type = "const char *", name = "text"},
|
||||
|
|
@ -7493,30 +7524,6 @@ return {
|
|||
{type = "Color", name = "tint"}
|
||||
}
|
||||
},
|
||||
{
|
||||
name = "DrawModelPoints",
|
||||
description = "Draw a model as points",
|
||||
returnType = "void",
|
||||
params = {
|
||||
{type = "Model", name = "model"},
|
||||
{type = "Vector3", name = "position"},
|
||||
{type = "float", name = "scale"},
|
||||
{type = "Color", name = "tint"}
|
||||
}
|
||||
},
|
||||
{
|
||||
name = "DrawModelPointsEx",
|
||||
description = "Draw a model as points with extended parameters",
|
||||
returnType = "void",
|
||||
params = {
|
||||
{type = "Model", name = "model"},
|
||||
{type = "Vector3", name = "position"},
|
||||
{type = "Vector3", name = "rotationAxis"},
|
||||
{type = "float", name = "rotationAngle"},
|
||||
{type = "Vector3", name = "scale"},
|
||||
{type = "Color", name = "tint"}
|
||||
}
|
||||
},
|
||||
{
|
||||
name = "DrawBoundingBox",
|
||||
description = "Draw bounding box (wires)",
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -682,7 +682,7 @@
|
|||
<Param type="unsigned int" name="frames" desc="" />
|
||||
</Callback>
|
||||
</Callbacks>
|
||||
<Functions count="599">
|
||||
<Functions count="600">
|
||||
<Function name="InitWindow" retType="void" paramCount="3" desc="Initialize window and OpenGL context">
|
||||
<Param type="int" name="width" desc="" />
|
||||
<Param type="int" name="height" desc="" />
|
||||
|
|
@ -1122,10 +1122,10 @@
|
|||
<Function name="IsFileNameValid" retType="bool" paramCount="1" desc="Check if fileName is valid for the platform/OS">
|
||||
<Param type="const char *" name="fileName" desc="" />
|
||||
</Function>
|
||||
<Function name="LoadDirectoryFiles" retType="FilePathList" paramCount="1" desc="Load directory filepaths">
|
||||
<Function name="LoadDirectoryFiles" retType="FilePathList" paramCount="1" desc="Load directory filepaths, files and directories, no subdirs scan">
|
||||
<Param type="const char *" name="dirPath" desc="" />
|
||||
</Function>
|
||||
<Function name="LoadDirectoryFilesEx" retType="FilePathList" paramCount="3" desc="Load directory filepaths with extension filtering and recursive directory scan. Use 'DIR' in the filter string to include directories in the result">
|
||||
<Function name="LoadDirectoryFilesEx" retType="FilePathList" paramCount="3" desc="Load directory filepaths with extension filtering and subdir scan; some filters available: "*.*", "FILES*", "DIRS*"">
|
||||
<Param type="const char *" name="basePath" desc="" />
|
||||
<Param type="const char *" name="filter" desc="" />
|
||||
<Param type="bool" name="scanSubdirs" desc="" />
|
||||
|
|
@ -1809,7 +1809,7 @@
|
|||
<Param type="Image" name="image" desc="" />
|
||||
<Param type="const char *" name="fileName" desc="" />
|
||||
</Function>
|
||||
<Function name="ExportImageToMemory" retType="unsigned char *" paramCount="3" desc="Export image to memory buffer">
|
||||
<Function name="ExportImageToMemory" retType="unsigned char *" paramCount="3" desc="Export image to memory buffer, memory must be MemFree()">
|
||||
<Param type="Image" name="image" desc="" />
|
||||
<Param type="const char *" name="fileType" desc="" />
|
||||
<Param type="int *" name="fileSize" desc="" />
|
||||
|
|
@ -2525,18 +2525,34 @@
|
|||
<Param type="const char *" name="begin" desc="" />
|
||||
<Param type="const char *" name="end" desc="" />
|
||||
</Function>
|
||||
<Function name="TextReplace" retType="char *" paramCount="3" desc="Replace text string (WARNING: memory must be freed!)">
|
||||
<Function name="TextReplace" retType="char *" paramCount="3" desc="Replace text string with new string">
|
||||
<Param type="const char *" name="text" desc="" />
|
||||
<Param type="const char *" name="search" desc="" />
|
||||
<Param type="const char *" name="replacement" desc="" />
|
||||
</Function>
|
||||
<Function name="TextReplaceBetween" retType="char *" paramCount="4" desc="Replace text between two specific strings (WARNING: memory must be freed!)">
|
||||
<Function name="TextReplaceAlloc" retType="char *" paramCount="3" desc="Replace text string with new string, memory must be MemFree()">
|
||||
<Param type="const char *" name="text" desc="" />
|
||||
<Param type="const char *" name="search" desc="" />
|
||||
<Param type="const char *" name="replacement" desc="" />
|
||||
</Function>
|
||||
<Function name="TextReplaceBetween" retType="char *" paramCount="4" desc="Replace text between two specific strings">
|
||||
<Param type="const char *" name="text" desc="" />
|
||||
<Param type="const char *" name="begin" desc="" />
|
||||
<Param type="const char *" name="end" desc="" />
|
||||
<Param type="const char *" name="replacement" desc="" />
|
||||
</Function>
|
||||
<Function name="TextInsert" retType="char *" paramCount="3" desc="Insert text in a position (WARNING: memory must be freed!)">
|
||||
<Function name="TextReplaceBetweenAlloc" retType="char *" paramCount="4" desc="Replace text between two specific strings, memory must be MemFree()">
|
||||
<Param type="const char *" name="text" desc="" />
|
||||
<Param type="const char *" name="begin" desc="" />
|
||||
<Param type="const char *" name="end" desc="" />
|
||||
<Param type="const char *" name="replacement" desc="" />
|
||||
</Function>
|
||||
<Function name="TextInsert" retType="char *" paramCount="3" desc="Insert text in a defined byte position">
|
||||
<Param type="const char *" name="text" desc="" />
|
||||
<Param type="const char *" name="insert" desc="" />
|
||||
<Param type="int" name="position" desc="" />
|
||||
</Function>
|
||||
<Function name="TextInsertAlloc" retType="char *" paramCount="3" desc="Insert text in a defined byte position, memory must be MemFree()">
|
||||
<Param type="const char *" name="text" desc="" />
|
||||
<Param type="const char *" name="insert" desc="" />
|
||||
<Param type="int" name="position" desc="" />
|
||||
|
|
@ -2755,20 +2771,6 @@
|
|||
<Param type="Vector3" name="scale" desc="" />
|
||||
<Param type="Color" name="tint" desc="" />
|
||||
</Function>
|
||||
<Function name="DrawModelPoints" retType="void" paramCount="4" desc="Draw a model as points">
|
||||
<Param type="Model" name="model" desc="" />
|
||||
<Param type="Vector3" name="position" desc="" />
|
||||
<Param type="float" name="scale" desc="" />
|
||||
<Param type="Color" name="tint" desc="" />
|
||||
</Function>
|
||||
<Function name="DrawModelPointsEx" retType="void" paramCount="6" desc="Draw a model as points with extended parameters">
|
||||
<Param type="Model" name="model" desc="" />
|
||||
<Param type="Vector3" name="position" desc="" />
|
||||
<Param type="Vector3" name="rotationAxis" desc="" />
|
||||
<Param type="float" name="rotationAngle" desc="" />
|
||||
<Param type="Vector3" name="scale" desc="" />
|
||||
<Param type="Color" name="tint" desc="" />
|
||||
</Function>
|
||||
<Function name="DrawBoundingBox" retType="void" paramCount="2" desc="Draw bounding box (wires)">
|
||||
<Param type="BoundingBox" name="box" desc="" />
|
||||
<Param type="Color" name="color" desc="" />
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user