diff --git a/raymenu/go.mod b/raymenu/go.mod
index 0d614bf..c25e674 100644
--- a/raymenu/go.mod
+++ b/raymenu/go.mod
@@ -5,11 +5,11 @@ go 1.26.2
require (
github.com/gen2brain/raylib-go/raygui v0.0.0-20260309161816-4c350487f71d
github.com/gen2brain/raylib-go/raylib v0.55.1
+ github.com/ktr0731/go-fuzzyfinder v0.9.0
)
require (
github.com/ebitengine/purego v0.10.0 // indirect
- github.com/ktr0731/go-fuzzyfinder v0.9.0 // indirect
golang.org/x/exp v0.0.0-20260508232706-74f9aab9d74a // indirect
golang.org/x/sys v0.44.0 // indirect
)
diff --git a/raymenu/vendor/github.com/ebitengine/purego/.gitignore b/raymenu/vendor/github.com/ebitengine/purego/.gitignore
new file mode 100644
index 0000000..b25c15b
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/.gitignore
@@ -0,0 +1 @@
+*~
diff --git a/raymenu/vendor/github.com/ebitengine/purego/LICENSE b/raymenu/vendor/github.com/ebitengine/purego/LICENSE
new file mode 100644
index 0000000..8dada3e
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "{}"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright {yyyy} {name of copyright owner}
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/raymenu/vendor/github.com/ebitengine/purego/README.md b/raymenu/vendor/github.com/ebitengine/purego/README.md
new file mode 100644
index 0000000..8fb85c2
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/README.md
@@ -0,0 +1,119 @@
+# purego
+[](https://pkg.go.dev/github.com/ebitengine/purego?GOOS=darwin)
+
+A library for calling C functions from Go without Cgo.
+
+> This is beta software so expect bugs and potentially API breaking changes
+> but each release will be tagged to avoid breaking people's code.
+> Bug reports are encouraged.
+
+## Motivation
+
+The [Ebitengine](https://github.com/hajimehoshi/ebiten) game engine was ported to use only Go on Windows. This enabled
+cross-compiling to Windows from any other operating system simply by setting `GOOS=windows`. The purego project was
+born to bring that same vision to the other platforms supported by Ebitengine.
+
+## Benefits
+
+- **Simple Cross-Compilation**: No C means you can build for other platforms easily without a C compiler.
+- **Faster Compilation**: Efficiently cache your entirely Go builds.
+- **Smaller Binaries**: Using Cgo generates a C wrapper function for each C function called. Purego doesn't!
+- **Dynamic Linking**: Load symbols at runtime and use it as a plugin system.
+- **Foreign Function Interface**: Call into other languages that are compiled into shared objects.
+- **Cgo Fallback**: Works even with CGO_ENABLED=1 so incremental porting is possible.
+This also means unsupported GOARCHs (freebsd/riscv64, linux/mips, etc.) will still work
+except for float arguments and return values.
+
+## Supported Platforms
+
+### Tier 1
+
+Tier 1 platforms are the primary targets officially supported by PureGo. When a new version of PureGo is released, any critical bugs found on Tier 1 platforms are treated as release blockers. The release will be postponed until such issues are resolved.
+
+- **Android**: amd641, arm641
+- **iOS**: amd641, arm641
+- **Linux**: amd64, arm64
+- **macOS**: amd64, arm64
+- **Windows**: amd64, arm64
+
+### Tier 2
+
+Tier 2 platforms are supported by PureGo on a best-effort basis. Critical bugs on Tier 2 platforms do not block new PureGo releases. However, fixes contributed by external contributors are very welcome and encouraged.
+
+- **Android**: 3861, arm1
+- **FreeBSD**: amd642, arm642
+- **Linux**: 386, arm, loong64, ppc64le, riscv64, s390x1
+- **Windows**: 3863, arm3,4
+
+#### Support Notes
+
+1. These architectures require CGO_ENABLED=1 to compile
+2. These architectures require the special flag `-gcflags="github.com/ebitengine/purego/internal/fakecgo=-std"` to compile with CGO_ENABLED=0
+3. These architectures only support `SyscallN` and `NewCallback`
+4. These architectures are no longer supported as of Go 1.26
+
+## Example
+
+The example below only showcases purego use for macOS and Linux. The other platforms require special handling which can
+be seen in the complete example at [examples/libc](https://github.com/ebitengine/purego/tree/main/examples/libc) which supports FreeBSD and Windows.
+
+```go
+package main
+
+import (
+ "fmt"
+ "runtime"
+
+ "github.com/ebitengine/purego"
+)
+
+func getSystemLibrary() string {
+ switch runtime.GOOS {
+ case "darwin":
+ return "/usr/lib/libSystem.B.dylib"
+ case "linux":
+ return "libc.so.6"
+ default:
+ panic(fmt.Errorf("GOOS=%s is not supported", runtime.GOOS))
+ }
+}
+
+func main() {
+ libc, err := purego.Dlopen(getSystemLibrary(), purego.RTLD_NOW|purego.RTLD_GLOBAL)
+ if err != nil {
+ panic(err)
+ }
+ var puts func(string)
+ purego.RegisterLibFunc(&puts, libc, "puts")
+ puts("Calling C from Go without Cgo!")
+}
+```
+
+Then to run: `CGO_ENABLED=0 go run main.go`
+
+## Questions
+
+If you have questions about how to incorporate purego in your project or want to discuss
+how it works join the [Discord](https://discord.gg/HzGZVD6BkY)!
+
+### External Code
+
+Purego uses code that originates from the Go runtime. These files are under the BSD-3
+License that can be found [in the Go Source](https://github.com/golang/go/blob/master/LICENSE).
+This is a list of the copied files:
+
+* `abi_*.h` from package `runtime/cgo`
+* `wincallback.go` from package `runtime`
+* `zcallback_darwin_*.s` from package `runtime`
+* `internal/fakecgo/abi_*.h` from package `runtime/cgo`
+* `internal/fakecgo/asm_GOARCH.s` from package `runtime/cgo`
+* `internal/fakecgo/callbacks.go` from package `runtime/cgo`
+* `internal/fakecgo/iscgo.go` from package `runtime/cgo`
+* `internal/fakecgo/setenv.go` from package `runtime/cgo`
+* `internal/fakecgo/freebsd.go` from package `runtime/cgo`
+* `internal/fakecgo/netbsd.go` from package `runtime/cgo`
+
+The `internal/fakecgo/go_GOOS.go` files were modified from `runtime/cgo/gcc_GOOS_GOARCH.go`.
+
+The files `abi_*.h` and `internal/fakecgo/abi_*.h` are the same because Bazel does not support cross-package use of
+`#include` so we need each one once per package. (cf. [issue](https://github.com/bazelbuild/rules_go/issues/3636))
diff --git a/raymenu/vendor/github.com/ebitengine/purego/abi_amd64.h b/raymenu/vendor/github.com/ebitengine/purego/abi_amd64.h
new file mode 100644
index 0000000..9949435
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/abi_amd64.h
@@ -0,0 +1,99 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Macros for transitioning from the host ABI to Go ABI0.
+//
+// These save the frame pointer, so in general, functions that use
+// these should have zero frame size to suppress the automatic frame
+// pointer, though it's harmless to not do this.
+
+#ifdef GOOS_windows
+
+// REGS_HOST_TO_ABI0_STACK is the stack bytes used by
+// PUSH_REGS_HOST_TO_ABI0.
+#define REGS_HOST_TO_ABI0_STACK (28*8 + 8)
+
+// PUSH_REGS_HOST_TO_ABI0 prepares for transitioning from
+// the host ABI to Go ABI0 code. It saves all registers that are
+// callee-save in the host ABI and caller-save in Go ABI0 and prepares
+// for entry to Go.
+//
+// Save DI SI BP BX R12 R13 R14 R15 X6-X15 registers and the DF flag.
+// Clear the DF flag for the Go ABI.
+// MXCSR matches the Go ABI, so we don't have to set that,
+// and Go doesn't modify it, so we don't have to save it.
+#define PUSH_REGS_HOST_TO_ABI0() \
+ PUSHFQ \
+ CLD \
+ ADJSP $(REGS_HOST_TO_ABI0_STACK - 8) \
+ MOVQ DI, (0*0)(SP) \
+ MOVQ SI, (1*8)(SP) \
+ MOVQ BP, (2*8)(SP) \
+ MOVQ BX, (3*8)(SP) \
+ MOVQ R12, (4*8)(SP) \
+ MOVQ R13, (5*8)(SP) \
+ MOVQ R14, (6*8)(SP) \
+ MOVQ R15, (7*8)(SP) \
+ MOVUPS X6, (8*8)(SP) \
+ MOVUPS X7, (10*8)(SP) \
+ MOVUPS X8, (12*8)(SP) \
+ MOVUPS X9, (14*8)(SP) \
+ MOVUPS X10, (16*8)(SP) \
+ MOVUPS X11, (18*8)(SP) \
+ MOVUPS X12, (20*8)(SP) \
+ MOVUPS X13, (22*8)(SP) \
+ MOVUPS X14, (24*8)(SP) \
+ MOVUPS X15, (26*8)(SP)
+
+#define POP_REGS_HOST_TO_ABI0() \
+ MOVQ (0*0)(SP), DI \
+ MOVQ (1*8)(SP), SI \
+ MOVQ (2*8)(SP), BP \
+ MOVQ (3*8)(SP), BX \
+ MOVQ (4*8)(SP), R12 \
+ MOVQ (5*8)(SP), R13 \
+ MOVQ (6*8)(SP), R14 \
+ MOVQ (7*8)(SP), R15 \
+ MOVUPS (8*8)(SP), X6 \
+ MOVUPS (10*8)(SP), X7 \
+ MOVUPS (12*8)(SP), X8 \
+ MOVUPS (14*8)(SP), X9 \
+ MOVUPS (16*8)(SP), X10 \
+ MOVUPS (18*8)(SP), X11 \
+ MOVUPS (20*8)(SP), X12 \
+ MOVUPS (22*8)(SP), X13 \
+ MOVUPS (24*8)(SP), X14 \
+ MOVUPS (26*8)(SP), X15 \
+ ADJSP $-(REGS_HOST_TO_ABI0_STACK - 8) \
+ POPFQ
+
+#else
+// SysV ABI
+
+#define REGS_HOST_TO_ABI0_STACK (6*8)
+
+// SysV MXCSR matches the Go ABI, so we don't have to set that,
+// and Go doesn't modify it, so we don't have to save it.
+// Both SysV and Go require DF to be cleared, so that's already clear.
+// The SysV and Go frame pointer conventions are compatible.
+#define PUSH_REGS_HOST_TO_ABI0() \
+ ADJSP $(REGS_HOST_TO_ABI0_STACK) \
+ MOVQ BP, (5*8)(SP) \
+ LEAQ (5*8)(SP), BP \
+ MOVQ BX, (0*8)(SP) \
+ MOVQ R12, (1*8)(SP) \
+ MOVQ R13, (2*8)(SP) \
+ MOVQ R14, (3*8)(SP) \
+ MOVQ R15, (4*8)(SP)
+
+#define POP_REGS_HOST_TO_ABI0() \
+ MOVQ (0*8)(SP), BX \
+ MOVQ (1*8)(SP), R12 \
+ MOVQ (2*8)(SP), R13 \
+ MOVQ (3*8)(SP), R14 \
+ MOVQ (4*8)(SP), R15 \
+ MOVQ (5*8)(SP), BP \
+ ADJSP $-(REGS_HOST_TO_ABI0_STACK)
+
+#endif
diff --git a/raymenu/vendor/github.com/ebitengine/purego/abi_arm64.h b/raymenu/vendor/github.com/ebitengine/purego/abi_arm64.h
new file mode 100644
index 0000000..5d5061e
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/abi_arm64.h
@@ -0,0 +1,39 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Macros for transitioning from the host ABI to Go ABI0.
+//
+// These macros save and restore the callee-saved registers
+// from the stack, but they don't adjust stack pointer, so
+// the user should prepare stack space in advance.
+// SAVE_R19_TO_R28(offset) saves R19 ~ R28 to the stack space
+// of ((offset)+0*8)(RSP) ~ ((offset)+9*8)(RSP).
+//
+// SAVE_F8_TO_F15(offset) saves F8 ~ F15 to the stack space
+// of ((offset)+0*8)(RSP) ~ ((offset)+7*8)(RSP).
+//
+// R29 is not saved because Go will save and restore it.
+
+#define SAVE_R19_TO_R28(offset) \
+ STP (R19, R20), ((offset)+0*8)(RSP) \
+ STP (R21, R22), ((offset)+2*8)(RSP) \
+ STP (R23, R24), ((offset)+4*8)(RSP) \
+ STP (R25, R26), ((offset)+6*8)(RSP) \
+ STP (R27, g), ((offset)+8*8)(RSP)
+#define RESTORE_R19_TO_R28(offset) \
+ LDP ((offset)+0*8)(RSP), (R19, R20) \
+ LDP ((offset)+2*8)(RSP), (R21, R22) \
+ LDP ((offset)+4*8)(RSP), (R23, R24) \
+ LDP ((offset)+6*8)(RSP), (R25, R26) \
+ LDP ((offset)+8*8)(RSP), (R27, g) /* R28 */
+#define SAVE_F8_TO_F15(offset) \
+ FSTPD (F8, F9), ((offset)+0*8)(RSP) \
+ FSTPD (F10, F11), ((offset)+2*8)(RSP) \
+ FSTPD (F12, F13), ((offset)+4*8)(RSP) \
+ FSTPD (F14, F15), ((offset)+6*8)(RSP)
+#define RESTORE_F8_TO_F15(offset) \
+ FLDPD ((offset)+0*8)(RSP), (F8, F9) \
+ FLDPD ((offset)+2*8)(RSP), (F10, F11) \
+ FLDPD ((offset)+4*8)(RSP), (F12, F13) \
+ FLDPD ((offset)+6*8)(RSP), (F14, F15)
diff --git a/raymenu/vendor/github.com/ebitengine/purego/abi_loong64.h b/raymenu/vendor/github.com/ebitengine/purego/abi_loong64.h
new file mode 100644
index 0000000..b10d837
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/abi_loong64.h
@@ -0,0 +1,60 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Macros for transitioning from the host ABI to Go ABI0.
+//
+// These macros save and restore the callee-saved registers
+// from the stack, but they don't adjust stack pointer, so
+// the user should prepare stack space in advance.
+// SAVE_R22_TO_R31(offset) saves R22 ~ R31 to the stack space
+// of ((offset)+0*8)(R3) ~ ((offset)+9*8)(R3).
+//
+// SAVE_F24_TO_F31(offset) saves F24 ~ F31 to the stack space
+// of ((offset)+0*8)(R3) ~ ((offset)+7*8)(R3).
+//
+// Note: g is R22
+
+#define SAVE_R22_TO_R31(offset) \
+ MOVV g, ((offset)+(0*8))(R3) \
+ MOVV R23, ((offset)+(1*8))(R3) \
+ MOVV R24, ((offset)+(2*8))(R3) \
+ MOVV R25, ((offset)+(3*8))(R3) \
+ MOVV R26, ((offset)+(4*8))(R3) \
+ MOVV R27, ((offset)+(5*8))(R3) \
+ MOVV R28, ((offset)+(6*8))(R3) \
+ MOVV R29, ((offset)+(7*8))(R3) \
+ MOVV R30, ((offset)+(8*8))(R3) \
+ MOVV R31, ((offset)+(9*8))(R3)
+
+#define SAVE_F24_TO_F31(offset) \
+ MOVD F24, ((offset)+(0*8))(R3) \
+ MOVD F25, ((offset)+(1*8))(R3) \
+ MOVD F26, ((offset)+(2*8))(R3) \
+ MOVD F27, ((offset)+(3*8))(R3) \
+ MOVD F28, ((offset)+(4*8))(R3) \
+ MOVD F29, ((offset)+(5*8))(R3) \
+ MOVD F30, ((offset)+(6*8))(R3) \
+ MOVD F31, ((offset)+(7*8))(R3)
+
+#define RESTORE_R22_TO_R31(offset) \
+ MOVV ((offset)+(0*8))(R3), g \
+ MOVV ((offset)+(1*8))(R3), R23 \
+ MOVV ((offset)+(2*8))(R3), R24 \
+ MOVV ((offset)+(3*8))(R3), R25 \
+ MOVV ((offset)+(4*8))(R3), R26 \
+ MOVV ((offset)+(5*8))(R3), R27 \
+ MOVV ((offset)+(6*8))(R3), R28 \
+ MOVV ((offset)+(7*8))(R3), R29 \
+ MOVV ((offset)+(8*8))(R3), R30 \
+ MOVV ((offset)+(9*8))(R3), R31
+
+#define RESTORE_F24_TO_F31(offset) \
+ MOVD ((offset)+(0*8))(R3), F24 \
+ MOVD ((offset)+(1*8))(R3), F25 \
+ MOVD ((offset)+(2*8))(R3), F26 \
+ MOVD ((offset)+(3*8))(R3), F27 \
+ MOVD ((offset)+(4*8))(R3), F28 \
+ MOVD ((offset)+(5*8))(R3), F29 \
+ MOVD ((offset)+(6*8))(R3), F30 \
+ MOVD ((offset)+(7*8))(R3), F31
diff --git a/raymenu/vendor/github.com/ebitengine/purego/cgo.go b/raymenu/vendor/github.com/ebitengine/purego/cgo.go
new file mode 100644
index 0000000..b6def57
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/cgo.go
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
+
+//go:build cgo && (darwin || freebsd || linux || netbsd)
+
+package purego
+
+// if CGO_ENABLED=1 import the Cgo runtime to ensure that it is set up properly.
+// This is required since some frameworks need TLS setup the C way which Go doesn't do.
+// We currently don't support ios in fakecgo mode so force Cgo or fail.
+// Even if CGO_ENABLED=1 the Cgo runtime is not imported unless `import "C"` is used,
+// which will import this package automatically. Normally this isn't an issue since it
+// usually isn't possible to call into C without using that import. However, with purego
+// it is since we don't use `import "C"`!
+import (
+ _ "runtime/cgo"
+
+ _ "github.com/ebitengine/purego/internal/cgo"
+)
diff --git a/raymenu/vendor/github.com/ebitengine/purego/dlerror.go b/raymenu/vendor/github.com/ebitengine/purego/dlerror.go
new file mode 100644
index 0000000..ad52b43
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/dlerror.go
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2023 The Ebitengine Authors
+
+//go:build darwin || freebsd || linux || netbsd
+
+package purego
+
+// Dlerror represents an error value returned from Dlopen, Dlsym, or Dlclose.
+//
+// This type is not available on Windows as there is no counterpart to it on Windows.
+type Dlerror struct {
+ s string
+}
+
+func (e Dlerror) Error() string {
+ return e.s
+}
diff --git a/raymenu/vendor/github.com/ebitengine/purego/dlfcn.go b/raymenu/vendor/github.com/ebitengine/purego/dlfcn.go
new file mode 100644
index 0000000..2730d82
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/dlfcn.go
@@ -0,0 +1,99 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
+
+//go:build (darwin || freebsd || linux || netbsd) && !android && !faketime
+
+package purego
+
+import (
+ "unsafe"
+)
+
+// Unix Specification for dlfcn.h: https://pubs.opengroup.org/onlinepubs/7908799/xsh/dlfcn.h.html
+
+var (
+ fnDlopen func(path string, mode int) uintptr
+ fnDlsym func(handle uintptr, name string) uintptr
+ fnDlerror func() string
+ fnDlclose func(handle uintptr) bool
+)
+
+func init() {
+ RegisterFunc(&fnDlopen, dlopenABI0)
+ RegisterFunc(&fnDlsym, dlsymABI0)
+ RegisterFunc(&fnDlerror, dlerrorABI0)
+ RegisterFunc(&fnDlclose, dlcloseABI0)
+}
+
+// Dlopen examines the dynamic library or bundle file specified by path. If the file is compatible
+// with the current process and has not already been loaded into the
+// current process, it is loaded and linked. After being linked, if it contains
+// any initializer functions, they are called, before Dlopen
+// returns. It returns a handle that can be used with Dlsym and Dlclose.
+// A second call to Dlopen with the same path will return the same handle, but the internal
+// reference count for the handle will be incremented. Therefore, all
+// Dlopen calls should be balanced with a Dlclose call.
+//
+// This function is not available on Windows.
+// Use [golang.org/x/sys/windows.LoadLibrary], [golang.org/x/sys/windows.LoadLibraryEx],
+// [golang.org/x/sys/windows.NewLazyDLL], or [golang.org/x/sys/windows.NewLazySystemDLL] for Windows instead.
+func Dlopen(path string, mode int) (uintptr, error) {
+ u := fnDlopen(path, mode)
+ if u == 0 {
+ return 0, Dlerror{fnDlerror()}
+ }
+ return u, nil
+}
+
+// Dlsym takes a "handle" of a dynamic library returned by Dlopen and the symbol name.
+// It returns the address where that symbol is loaded into memory. If the symbol is not found,
+// in the specified library or any of the libraries that were automatically loaded by Dlopen
+// when that library was loaded, Dlsym returns zero.
+//
+// This function is not available on Windows.
+// Use [golang.org/x/sys/windows.GetProcAddress] for Windows instead.
+func Dlsym(handle uintptr, name string) (uintptr, error) {
+ u := fnDlsym(handle, name)
+ if u == 0 {
+ return 0, Dlerror{fnDlerror()}
+ }
+ return u, nil
+}
+
+// Dlclose decrements the reference count on the dynamic library handle.
+// If the reference count drops to zero and no other loaded libraries
+// use symbols in it, then the dynamic library is unloaded.
+//
+// This function is not available on Windows.
+// Use [golang.org/x/sys/windows.FreeLibrary] for Windows instead.
+func Dlclose(handle uintptr) error {
+ if fnDlclose(handle) {
+ return Dlerror{fnDlerror()}
+ }
+ return nil
+}
+
+func loadSymbol(handle uintptr, name string) (uintptr, error) {
+ return Dlsym(handle, name)
+}
+
+// these functions exist in dlfcn_stubs.s and are calling C functions linked to in dlfcn_GOOS.go
+// the indirection is necessary because a function is actually a pointer to the pointer to the code.
+// sadly, I do not know of anyway to remove the assembly stubs entirely because //go:linkname doesn't
+// appear to work if you link directly to the C function on darwin arm64.
+
+//go:linkname dlopen dlopen
+var dlopen uint8
+var dlopenABI0 = uintptr(unsafe.Pointer(&dlopen))
+
+//go:linkname dlsym dlsym
+var dlsym uint8
+var dlsymABI0 = uintptr(unsafe.Pointer(&dlsym))
+
+//go:linkname dlclose dlclose
+var dlclose uint8
+var dlcloseABI0 = uintptr(unsafe.Pointer(&dlclose))
+
+//go:linkname dlerror dlerror
+var dlerror uint8
+var dlerrorABI0 = uintptr(unsafe.Pointer(&dlerror))
diff --git a/raymenu/vendor/github.com/ebitengine/purego/dlfcn_android.go b/raymenu/vendor/github.com/ebitengine/purego/dlfcn_android.go
new file mode 100644
index 0000000..0d53417
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/dlfcn_android.go
@@ -0,0 +1,34 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2024 The Ebitengine Authors
+
+package purego
+
+import "github.com/ebitengine/purego/internal/cgo"
+
+// Source for constants: https://android.googlesource.com/platform/bionic/+/refs/heads/main/libc/include/dlfcn.h
+
+const (
+ is64bit = 1 << (^uintptr(0) >> 63) / 2
+ is32bit = 1 - is64bit
+ RTLD_DEFAULT = is32bit * 0xffffffff
+ RTLD_LAZY = 0x00000001
+ RTLD_NOW = is64bit * 0x00000002
+ RTLD_LOCAL = 0x00000000
+ RTLD_GLOBAL = is64bit*0x00100 | is32bit*0x00000002
+)
+
+func Dlopen(path string, mode int) (uintptr, error) {
+ return cgo.Dlopen(path, mode)
+}
+
+func Dlsym(handle uintptr, name string) (uintptr, error) {
+ return cgo.Dlsym(handle, name)
+}
+
+func Dlclose(handle uintptr) error {
+ return cgo.Dlclose(handle)
+}
+
+func loadSymbol(handle uintptr, name string) (uintptr, error) {
+ return Dlsym(handle, name)
+}
diff --git a/raymenu/vendor/github.com/ebitengine/purego/dlfcn_darwin.go b/raymenu/vendor/github.com/ebitengine/purego/dlfcn_darwin.go
new file mode 100644
index 0000000..5dd4446
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/dlfcn_darwin.go
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
+
+package purego
+
+// Source for constants: https://opensource.apple.com/source/dyld/dyld-360.14/include/dlfcn.h.auto.html
+
+const (
+ RTLD_DEFAULT = 1<<64 - 2 // Pseudo-handle for dlsym so search for any loaded symbol
+ RTLD_LAZY = 0x1 // Relocations are performed at an implementation-dependent time.
+ RTLD_NOW = 0x2 // Relocations are performed when the object is loaded.
+ RTLD_LOCAL = 0x4 // All symbols are not made available for relocation processing by other modules.
+ RTLD_GLOBAL = 0x8 // All symbols are available for relocation processing of other modules.
+)
+
+//go:cgo_import_dynamic purego_dlopen dlopen "/usr/lib/libSystem.B.dylib"
+//go:cgo_import_dynamic purego_dlsym dlsym "/usr/lib/libSystem.B.dylib"
+//go:cgo_import_dynamic purego_dlerror dlerror "/usr/lib/libSystem.B.dylib"
+//go:cgo_import_dynamic purego_dlclose dlclose "/usr/lib/libSystem.B.dylib"
+//go:cgo_import_dynamic purego_error __error "/usr/lib/libSystem.B.dylib"
diff --git a/raymenu/vendor/github.com/ebitengine/purego/dlfcn_freebsd.go b/raymenu/vendor/github.com/ebitengine/purego/dlfcn_freebsd.go
new file mode 100644
index 0000000..6b37162
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/dlfcn_freebsd.go
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
+
+package purego
+
+// Constants as defined in https://github.com/freebsd/freebsd-src/blob/main/include/dlfcn.h
+const (
+ intSize = 32 << (^uint(0) >> 63) // 32 or 64
+ RTLD_DEFAULT = 1<> 63) // 32 or 64
+ RTLD_DEFAULT = 1< C)
+//
+// string <=> char*
+// bool <=> _Bool
+// uintptr <=> uintptr_t
+// uint <=> uint32_t or uint64_t
+// uint8 <=> uint8_t
+// uint16 <=> uint16_t
+// uint32 <=> uint32_t
+// uint64 <=> uint64_t
+// int <=> int32_t or int64_t
+// int8 <=> int8_t
+// int16 <=> int16_t
+// int32 <=> int32_t
+// int64 <=> int64_t
+// float32 <=> float
+// float64 <=> double
+// struct <=> struct (darwin amd64/arm64, linux amd64/arm64)
+// func <=> C function
+// unsafe.Pointer, *T <=> void*
+// []T => void*
+//
+// There is a special case when the last argument of fptr is a variadic interface (or []interface}
+// it will be expanded into a call to the C function as if it had the arguments in that slice.
+// This means that using arg ...any is like a cast to the function with the arguments inside arg.
+// This is not the same as C variadic.
+//
+// # Memory
+//
+// In general it is not possible for purego to guarantee the lifetimes of objects returned or received from
+// calling functions using RegisterFunc. For arguments to a C function it is important that the C function doesn't
+// hold onto a reference to Go memory. This is the same as the [Cgo rules].
+//
+// However, there are some special cases. When passing a string as an argument if the string does not end in a null
+// terminated byte (\x00) then the string will be copied into memory maintained by purego. The memory is only valid for
+// that specific call. Therefore, if the C code keeps a reference to that string it may become invalid at some
+// undefined time. However, if the string does already contain a null-terminated byte then no copy is done.
+// It is then the responsibility of the caller to ensure the string stays alive as long as it's needed in C memory.
+// This can be done using runtime.KeepAlive or allocating the string in C memory using malloc. When a C function
+// returns a null-terminated pointer to char a Go string can be used. Purego will allocate a new string in Go memory
+// and copy the data over. This string will be garbage collected whenever Go decides it's no longer referenced.
+// This C created string will not be freed by purego. If the pointer to char is not null-terminated or must continue
+// to point to C memory (because it's a buffer for example) then use a pointer to byte and then convert that to a slice
+// using unsafe.Slice. Doing this means that it becomes the responsibility of the caller to care about the lifetime
+// of the pointer
+//
+// # Structs
+//
+// Purego can handle the most common structs that have fields of builtin types like int8, uint16, float32, etc. However,
+// it does not support aligning fields properly. It is therefore the responsibility of the caller to ensure
+// that all padding is added to the Go struct to match the C one. See `BoolStructFn` in struct_test.go for an example.
+//
+// On Darwin ARM64, purego handles proper alignment of struct arguments when passing them on the stack,
+// following the C ABI's byte-level packing rules.
+//
+// # Example
+//
+// All functions below call this C function:
+//
+// char *foo(char *str);
+//
+// // Let purego convert types
+// var foo func(s string) string
+// goString := foo("copied")
+// // Go will garbage collect this string
+//
+// // Manually, handle allocations
+// var foo2 func(b string) *byte
+// mustFree := foo2("not copied\x00")
+// defer free(mustFree)
+//
+// [Cgo rules]: https://pkg.go.dev/cmd/cgo#hdr-Go_references_to_C
+func RegisterFunc(fptr any, cfn uintptr) {
+ const is32bit = unsafe.Sizeof(uintptr(0)) == 4
+ fn := reflect.ValueOf(fptr).Elem()
+ ty := fn.Type()
+ if ty.Kind() != reflect.Func {
+ panic("purego: fptr must be a function pointer")
+ }
+ if ty.NumOut() > 1 {
+ panic("purego: function can only return zero or one values")
+ }
+ if cfn == 0 {
+ panic("purego: cfn is nil")
+ }
+ if ty.NumOut() == 1 && (ty.Out(0).Kind() == reflect.Float32 || ty.Out(0).Kind() == reflect.Float64) &&
+ runtime.GOARCH != "arm" && runtime.GOARCH != "arm64" && runtime.GOARCH != "386" && runtime.GOARCH != "amd64" && runtime.GOARCH != "loong64" && runtime.GOARCH != "ppc64le" && runtime.GOARCH != "riscv64" && runtime.GOARCH != "s390x" {
+ panic("purego: float returns are not supported")
+ }
+ {
+ // this code checks how many registers and stack this function will use
+ // to avoid crashing with too many arguments
+ var ints int
+ var floats int
+ var stack int
+ for i := 0; i < ty.NumIn(); i++ {
+ arg := ty.In(i)
+ switch arg.Kind() {
+ case reflect.Func:
+ // This only does preliminary testing to ensure the CDecl argument
+ // is the first argument. Full testing is done when the callback is actually
+ // created in NewCallback.
+ for j := 0; j < arg.NumIn(); j++ {
+ in := arg.In(j)
+ if !in.AssignableTo(reflect.TypeOf(CDecl{})) {
+ continue
+ }
+ if j != 0 {
+ panic("purego: CDecl must be the first argument")
+ }
+ }
+ case reflect.String, reflect.Uintptr, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
+ reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Ptr, reflect.UnsafePointer,
+ reflect.Slice, reflect.Bool:
+ if ints < numOfIntegerRegisters() {
+ ints++
+ } else {
+ stack++
+ }
+ case reflect.Float32, reflect.Float64:
+ if floats < numOfFloatRegisters() {
+ floats++
+ } else {
+ stack++
+ }
+ case reflect.Struct:
+ ensureStructSupportedForRegisterFunc()
+ if arg.Size() == 0 {
+ continue
+ }
+ addInt := func(u uintptr) {
+ ints++
+ }
+ addFloat := func(u uintptr) {
+ floats++
+ }
+ addStack := func(u uintptr) {
+ stack++
+ }
+ _ = addStruct(reflect.New(arg).Elem(), &ints, &floats, &stack, addInt, addFloat, addStack, nil)
+ default:
+ panic("purego: unsupported kind " + arg.Kind().String())
+ }
+ }
+ if ty.NumOut() == 1 && ty.Out(0).Kind() == reflect.Struct {
+ ensureStructSupportedForRegisterFunc()
+ outType := ty.Out(0)
+ checkStructFieldsSupported(outType)
+ if runtime.GOARCH == "amd64" && outType.Size() > maxRegAllocStructSize {
+ // on amd64 if struct is bigger than 16 bytes allocate the return struct
+ // and pass it in as a hidden first argument.
+ ints++
+ }
+ }
+
+ sizeOfStack := maxArgs - numOfIntegerRegisters()
+ // On Darwin ARM64, use byte-based validation since arguments pack efficiently.
+ // See https://developer.apple.com/documentation/xcode/writing-arm64-code-for-apple-platforms
+ if runtime.GOOS == "darwin" && runtime.GOARCH == "arm64" {
+ stackBytes := estimateStackBytes(ty)
+ maxStackBytes := sizeOfStack * 8
+ if stackBytes > maxStackBytes {
+ panic("purego: too many stack arguments")
+ }
+ } else {
+ if stack > sizeOfStack {
+ panic("purego: too many stack arguments")
+ }
+ }
+ }
+
+ v := reflect.MakeFunc(ty, func(args []reflect.Value) (results []reflect.Value) {
+ var sysargs [maxArgs]uintptr
+ // Use maxArgs instead of numOfFloatRegisters() to keep this code path allocation-free,
+ // since numOfFloatRegisters() is a function call, not a constant.
+ // maxArgs is always greater than or equal to numOfFloatRegisters() so this is safe.
+ var floats [maxArgs]uintptr
+ var numInts int
+ var numFloats int
+ var numStack int
+ var addStack, addInt, addFloat func(x uintptr)
+ if runtime.GOARCH == "arm64" || runtime.GOOS != "windows" {
+ // Windows arm64 uses the same calling convention as macOS and Linux
+ addStack = func(x uintptr) {
+ sysargs[numOfIntegerRegisters()+numStack] = x
+ numStack++
+ }
+ addInt = func(x uintptr) {
+ if numInts >= numOfIntegerRegisters() {
+ addStack(x)
+ } else {
+ sysargs[numInts] = x
+ numInts++
+ }
+ }
+ addFloat = func(x uintptr) {
+ if numFloats < numOfFloatRegisters() {
+ floats[numFloats] = x
+ numFloats++
+ } else {
+ addStack(x)
+ }
+ }
+ } else {
+ // On Windows amd64 the arguments are passed in the numbered registered.
+ // So the first int is in the first integer register and the first float
+ // is in the second floating register if there is already a first int.
+ // This is in contrast to how macOS and Linux pass arguments which
+ // tries to use as many registers as possible in the calling convention.
+ addStack = func(x uintptr) {
+ sysargs[numStack] = x
+ numStack++
+ }
+ addInt = addStack
+ addFloat = addStack
+ }
+
+ var keepAlive []any
+ defer func() {
+ runtime.KeepAlive(keepAlive)
+ runtime.KeepAlive(args)
+ }()
+
+ var arm64_r8 uintptr
+ if ty.NumOut() == 1 && ty.Out(0).Kind() == reflect.Struct {
+ outType := ty.Out(0)
+ if (runtime.GOARCH == "amd64" || runtime.GOARCH == "loong64" || runtime.GOARCH == "ppc64le" || runtime.GOARCH == "riscv64" || runtime.GOARCH == "s390x") && outType.Size() > maxRegAllocStructSize {
+ val := reflect.New(outType)
+ keepAlive = append(keepAlive, val)
+ addInt(val.Pointer())
+ } else if runtime.GOARCH == "arm64" && outType.Size() > maxRegAllocStructSize {
+ isAllFloats, numFields := isAllSameFloat(outType)
+ if !isAllFloats || numFields > 4 {
+ val := reflect.New(outType)
+ keepAlive = append(keepAlive, val)
+ arm64_r8 = val.Pointer()
+ }
+ }
+ }
+ for i, v := range args {
+ if variadic, ok := xreflect.TypeAssert[[]any](args[i]); ok {
+ if i != len(args)-1 {
+ panic("purego: can only expand last parameter")
+ }
+ for _, x := range variadic {
+ keepAlive = addValue(reflect.ValueOf(x), keepAlive, addInt, addFloat, addStack, &numInts, &numFloats, &numStack)
+ }
+ continue
+ }
+ // Check if we need to start Darwin ARM64 C-style stack packing
+ if runtime.GOARCH == "arm64" && runtime.GOOS == "darwin" && shouldBundleStackArgs(v, numInts, numFloats) {
+ // Collect and separate remaining args into register vs stack
+ stackArgs, newKeepAlive := collectStackArgs(args, i, numInts, numFloats,
+ keepAlive, addInt, addFloat, addStack, &numInts, &numFloats, &numStack)
+ keepAlive = newKeepAlive
+
+ // Bundle stack arguments with C-style packing
+ bundleStackArgs(stackArgs, addStack)
+ break
+ }
+ keepAlive = addValue(v, keepAlive, addInt, addFloat, addStack, &numInts, &numFloats, &numStack)
+ }
+
+ syscall := thePool.Get().(*syscall15Args)
+ defer thePool.Put(syscall)
+
+ if runtime.GOARCH == "loong64" || runtime.GOARCH == "ppc64le" || runtime.GOARCH == "riscv64" || runtime.GOARCH == "s390x" {
+ syscall.Set(cfn, sysargs[:], floats[:], 0)
+ runtime_cgocall(syscall15XABI0, unsafe.Pointer(syscall))
+ } else if runtime.GOARCH == "arm64" || runtime.GOOS != "windows" {
+ // Use the normal arm64 calling convention even on Windows
+ syscall.Set(cfn, sysargs[:], floats[:], arm64_r8)
+ runtime_cgocall(syscall15XABI0, unsafe.Pointer(syscall))
+ } else {
+ *syscall = syscall15Args{}
+ // This is a fallback for Windows amd64, 386, and arm. Note this may not support floats
+ syscall.a1, syscall.a2, _ = syscall_syscall15X(cfn, sysargs[0], sysargs[1], sysargs[2], sysargs[3], sysargs[4],
+ sysargs[5], sysargs[6], sysargs[7], sysargs[8], sysargs[9], sysargs[10], sysargs[11],
+ sysargs[12], sysargs[13], sysargs[14])
+ syscall.f1 = syscall.a2 // on amd64 a2 stores the float return. On 32bit platforms floats aren't support
+ }
+ if ty.NumOut() == 0 {
+ return nil
+ }
+ outType := ty.Out(0)
+ v := reflect.New(outType).Elem()
+ switch outType.Kind() {
+ case reflect.Uintptr, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+ v.SetUint(uint64(syscall.a1))
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ v.SetInt(int64(syscall.a1))
+ case reflect.Bool:
+ v.SetBool(byte(syscall.a1) != 0)
+ case reflect.UnsafePointer:
+ // We take the address and then dereference it to trick go vet from creating a possible miss-use of unsafe.Pointer
+ v.SetPointer(*(*unsafe.Pointer)(unsafe.Pointer(&syscall.a1)))
+ case reflect.Ptr:
+ v = reflect.NewAt(outType, unsafe.Pointer(&syscall.a1)).Elem()
+ case reflect.Func:
+ // wrap this C function in a nicely typed Go function
+ v = reflect.New(outType)
+ RegisterFunc(v.Interface(), syscall.a1)
+ case reflect.String:
+ v.SetString(strings.GoString(syscall.a1))
+ case reflect.Float32:
+ // NOTE: syscall.r2 is only the floating return value on 64bit platforms.
+ // On 32bit platforms syscall.r2 is the upper part of a 64bit return.
+ // On 386, x87 FPU returns floats as float64 in ST(0), so we read as float64 and convert.
+ // On PPC64LE, C ABI converts float32 to double in FPR, so we read as float64.
+ // On S390X (big-endian), float32 is in upper 32 bits of the 64-bit FP register.
+ switch runtime.GOARCH {
+ case "386":
+ v.SetFloat(math.Float64frombits(uint64(syscall.f1) | (uint64(syscall.f2) << 32)))
+ case "ppc64le":
+ v.SetFloat(math.Float64frombits(uint64(syscall.f1)))
+ case "s390x":
+ // S390X is big-endian: float32 in upper 32 bits of 64-bit register
+ v.SetFloat(float64(math.Float32frombits(uint32(syscall.f1 >> 32))))
+ default:
+ v.SetFloat(float64(math.Float32frombits(uint32(syscall.f1))))
+ }
+ case reflect.Float64:
+ // NOTE: syscall.r2 is only the floating return value on 64bit platforms.
+ // On 32bit platforms syscall.r2 is the upper part of a 64bit return.
+ if is32bit {
+ v.SetFloat(math.Float64frombits(uint64(syscall.f1) | (uint64(syscall.f2) << 32)))
+ } else {
+ v.SetFloat(math.Float64frombits(uint64(syscall.f1)))
+ }
+ case reflect.Struct:
+ v = getStruct(outType, *syscall)
+ default:
+ panic("purego: unsupported return kind: " + outType.Kind().String())
+ }
+ if len(args) > 0 {
+ // reuse args slice instead of allocating one when possible
+ args[0] = v
+ return args[:1]
+ } else {
+ return []reflect.Value{v}
+ }
+ })
+ fn.Set(v)
+}
+
+func addValue(v reflect.Value, keepAlive []any, addInt func(x uintptr), addFloat func(x uintptr), addStack func(x uintptr), numInts *int, numFloats *int, numStack *int) []any {
+ const is32bit = unsafe.Sizeof(uintptr(0)) == 4
+ switch v.Kind() {
+ case reflect.String:
+ ptr := strings.CString(v.String())
+ keepAlive = append(keepAlive, ptr)
+ addInt(uintptr(unsafe.Pointer(ptr)))
+ case reflect.Uintptr, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+ addInt(uintptr(v.Uint()))
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ addInt(uintptr(v.Int()))
+ case reflect.Ptr, reflect.UnsafePointer, reflect.Slice:
+ // There is no need to keepAlive this pointer separately because it is kept alive in the args variable
+ addInt(v.Pointer())
+ case reflect.Func:
+ addInt(NewCallback(v.Interface()))
+ case reflect.Bool:
+ if v.Bool() {
+ addInt(1)
+ } else {
+ addInt(0)
+ }
+ case reflect.Float32:
+ // On S390X big-endian, float32 goes in upper 32 bits of 64-bit FP register
+ if runtime.GOARCH == "s390x" {
+ addFloat(uintptr(math.Float32bits(float32(v.Float()))) << 32)
+ } else {
+ addFloat(uintptr(math.Float32bits(float32(v.Float()))))
+ }
+ case reflect.Float64:
+ if is32bit {
+ bits := math.Float64bits(v.Float())
+ addFloat(uintptr(bits))
+ addFloat(uintptr(bits >> 32))
+ } else {
+ addFloat(uintptr(math.Float64bits(v.Float())))
+ }
+ case reflect.Struct:
+ keepAlive = addStruct(v, numInts, numFloats, numStack, addInt, addFloat, addStack, keepAlive)
+ default:
+ panic("purego: unsupported kind: " + v.Kind().String())
+ }
+ return keepAlive
+}
+
+// maxRegAllocStructSize is the biggest a struct can be while still fitting in registers.
+// if it is bigger than this than enough space must be allocated on the heap and then passed into
+// the function as the first parameter on amd64 or in R8 on arm64.
+//
+// If you change this make sure to update it in objc_runtime_darwin.go
+const maxRegAllocStructSize = 16
+
+func isAllSameFloat(ty reflect.Type) (allFloats bool, numFields int) {
+ allFloats = true
+ root := ty.Field(0).Type
+ for root.Kind() == reflect.Struct {
+ root = root.Field(0).Type
+ }
+ first := root.Kind()
+ if first != reflect.Float32 && first != reflect.Float64 {
+ allFloats = false
+ }
+ for i := 0; i < ty.NumField(); i++ {
+ f := ty.Field(i).Type
+ if f.Kind() == reflect.Struct {
+ var structNumFields int
+ allFloats, structNumFields = isAllSameFloat(f)
+ numFields += structNumFields
+ continue
+ }
+ numFields++
+ if f.Kind() != first {
+ allFloats = false
+ }
+ }
+ return allFloats, numFields
+}
+
+func checkStructFieldsSupported(ty reflect.Type) {
+ for i := 0; i < ty.NumField(); i++ {
+ f := ty.Field(i).Type
+ if f.Kind() == reflect.Array {
+ f = f.Elem()
+ } else if f.Kind() == reflect.Struct {
+ checkStructFieldsSupported(f)
+ continue
+ }
+ switch f.Kind() {
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
+ reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
+ reflect.Uintptr, reflect.Ptr, reflect.UnsafePointer, reflect.Float64, reflect.Float32,
+ reflect.Bool:
+ default:
+ panic(fmt.Sprintf("purego: struct field type %s is not supported", f))
+ }
+ }
+}
+
+func ensureStructSupportedForRegisterFunc() {
+ if runtime.GOARCH != "amd64" && runtime.GOARCH != "arm64" {
+ panic("purego: struct arguments are only supported on amd64 and arm64")
+ }
+ if runtime.GOOS != "darwin" && runtime.GOOS != "linux" {
+ panic("purego: struct arguments are only supported on darwin and linux")
+ }
+}
+
+func roundUpTo8(val uintptr) uintptr {
+ return (val + align8ByteMask) &^ align8ByteMask
+}
+
+func numOfFloatRegisters() int {
+ switch runtime.GOARCH {
+ case "amd64", "arm64", "loong64", "ppc64le", "riscv64":
+ return 8
+ case "s390x":
+ return 4
+ case "arm":
+ return 16
+ case "386":
+ // i386 SysV ABI passes all arguments on the stack, including floats
+ return 0
+ default:
+ // since this platform isn't supported and can therefore only access
+ // integer registers it is safest to return 8
+ return 8
+ }
+}
+
+func numOfIntegerRegisters() int {
+ switch runtime.GOARCH {
+ case "arm64", "loong64", "ppc64le", "riscv64":
+ return 8
+ case "amd64":
+ return 6
+ case "s390x":
+ // S390X uses R2-R6 for integer arguments
+ return 5
+ case "arm":
+ return 4
+ case "386":
+ // i386 SysV ABI passes all arguments on the stack
+ return 0
+ default:
+ // since this platform isn't supported and can therefore only access
+ // integer registers it is fine to return the maxArgs
+ return maxArgs
+ }
+}
+
+// estimateStackBytes estimates stack bytes needed for Darwin ARM64 validation.
+// This is a conservative estimate used only for early error detection.
+func estimateStackBytes(ty reflect.Type) int {
+ var numInts, numFloats int
+ var stackBytes int
+
+ for i := 0; i < ty.NumIn(); i++ {
+ arg := ty.In(i)
+ size := int(arg.Size())
+
+ // Check if this goes to register or stack
+ usesInt := arg.Kind() != reflect.Float32 && arg.Kind() != reflect.Float64
+ if usesInt && numInts < numOfIntegerRegisters() {
+ numInts++
+ } else if !usesInt && numFloats < numOfFloatRegisters() {
+ numFloats++
+ } else {
+ // Goes to stack - accumulate total bytes
+ stackBytes += size
+ }
+ }
+ // Round total to 8-byte boundary
+ if stackBytes > 0 && stackBytes%align8ByteSize != 0 {
+ stackBytes = int(roundUpTo8(uintptr(stackBytes)))
+ }
+ return stackBytes
+}
diff --git a/raymenu/vendor/github.com/ebitengine/purego/gen.go b/raymenu/vendor/github.com/ebitengine/purego/gen.go
new file mode 100644
index 0000000..9cb7c45
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/gen.go
@@ -0,0 +1,6 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2025 The Ebitengine Authors
+
+package purego
+
+//go:generate go run wincallback.go
diff --git a/raymenu/vendor/github.com/ebitengine/purego/go_runtime.go b/raymenu/vendor/github.com/ebitengine/purego/go_runtime.go
new file mode 100644
index 0000000..b327f78
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/go_runtime.go
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
+
+//go:build darwin || freebsd || linux || netbsd || windows
+
+package purego
+
+import (
+ "unsafe"
+)
+
+//go:linkname runtime_cgocall runtime.cgocall
+func runtime_cgocall(fn uintptr, arg unsafe.Pointer) int32 // from runtime/sys_libc.go
diff --git a/raymenu/vendor/github.com/ebitengine/purego/internal/cgo/dlfcn_cgo_unix.go b/raymenu/vendor/github.com/ebitengine/purego/internal/cgo/dlfcn_cgo_unix.go
new file mode 100644
index 0000000..6d0571a
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/internal/cgo/dlfcn_cgo_unix.go
@@ -0,0 +1,56 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2024 The Ebitengine Authors
+
+//go:build freebsd || linux || netbsd
+
+package cgo
+
+/*
+#cgo !netbsd LDFLAGS: -ldl
+
+#include
+#include
+*/
+import "C"
+
+import (
+ "errors"
+ "unsafe"
+)
+
+func Dlopen(filename string, flag int) (uintptr, error) {
+ cfilename := C.CString(filename)
+ defer C.free(unsafe.Pointer(cfilename))
+ handle := C.dlopen(cfilename, C.int(flag))
+ if handle == nil {
+ return 0, errors.New(C.GoString(C.dlerror()))
+ }
+ return uintptr(handle), nil
+}
+
+func Dlsym(handle uintptr, symbol string) (uintptr, error) {
+ csymbol := C.CString(symbol)
+ defer C.free(unsafe.Pointer(csymbol))
+ symbolAddr := C.dlsym(*(*unsafe.Pointer)(unsafe.Pointer(&handle)), csymbol)
+ if symbolAddr == nil {
+ return 0, errors.New(C.GoString(C.dlerror()))
+ }
+ return uintptr(symbolAddr), nil
+}
+
+func Dlclose(handle uintptr) error {
+ result := C.dlclose(*(*unsafe.Pointer)(unsafe.Pointer(&handle)))
+ if result != 0 {
+ return errors.New(C.GoString(C.dlerror()))
+ }
+ return nil
+}
+
+// all that is needed is to assign each dl function because then its
+// symbol will then be made available to the linker and linked to inside dlfcn.go
+var (
+ _ = C.dlopen
+ _ = C.dlsym
+ _ = C.dlerror
+ _ = C.dlclose
+)
diff --git a/raymenu/vendor/github.com/ebitengine/purego/internal/cgo/empty.go b/raymenu/vendor/github.com/ebitengine/purego/internal/cgo/empty.go
new file mode 100644
index 0000000..1d7cffe
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/internal/cgo/empty.go
@@ -0,0 +1,6 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2024 The Ebitengine Authors
+
+package cgo
+
+// Empty so that importing this package doesn't cause issue for certain platforms.
diff --git a/raymenu/vendor/github.com/ebitengine/purego/internal/cgo/syscall_cgo_unix.go b/raymenu/vendor/github.com/ebitengine/purego/internal/cgo/syscall_cgo_unix.go
new file mode 100644
index 0000000..1e39de3
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/internal/cgo/syscall_cgo_unix.go
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
+
+//go:build freebsd || (linux && !(386 || amd64 || arm || arm64 || loong64 || ppc64le || riscv64)) || netbsd
+
+package cgo
+
+// this file is placed inside internal/cgo and not package purego
+// because Cgo and assembly files can't be in the same package.
+
+/*
+#cgo !netbsd LDFLAGS: -ldl
+
+#include
+#include
+#include
+#include
+
+typedef struct syscall15Args {
+ uintptr_t fn;
+ uintptr_t a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15;
+ uintptr_t f1, f2, f3, f4, f5, f6, f7, f8;
+ uintptr_t err;
+} syscall15Args;
+
+void syscall15(struct syscall15Args *args) {
+ assert((args->f1|args->f2|args->f3|args->f4|args->f5|args->f6|args->f7|args->f8) == 0);
+ uintptr_t (*func_name)(uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6,
+ uintptr_t a7, uintptr_t a8, uintptr_t a9, uintptr_t a10, uintptr_t a11, uintptr_t a12,
+ uintptr_t a13, uintptr_t a14, uintptr_t a15);
+ *(void**)(&func_name) = (void*)(args->fn);
+ uintptr_t r1 = func_name(args->a1,args->a2,args->a3,args->a4,args->a5,args->a6,args->a7,args->a8,args->a9,
+ args->a10,args->a11,args->a12,args->a13,args->a14,args->a15);
+ args->a1 = r1;
+ args->err = errno;
+}
+
+*/
+import "C"
+import "unsafe"
+
+// assign purego.syscall15XABI0 to the C version of this function.
+var Syscall15XABI0 = unsafe.Pointer(C.syscall15)
+
+//go:nosplit
+func Syscall15X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 uintptr) (r1, r2, err uintptr) {
+ args := C.syscall15Args{
+ C.uintptr_t(fn), C.uintptr_t(a1), C.uintptr_t(a2), C.uintptr_t(a3),
+ C.uintptr_t(a4), C.uintptr_t(a5), C.uintptr_t(a6),
+ C.uintptr_t(a7), C.uintptr_t(a8), C.uintptr_t(a9), C.uintptr_t(a10), C.uintptr_t(a11), C.uintptr_t(a12),
+ C.uintptr_t(a13), C.uintptr_t(a14), C.uintptr_t(a15), 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }
+ C.syscall15(&args)
+ return uintptr(args.a1), 0, uintptr(args.err)
+}
diff --git a/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/abi_amd64.h b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/abi_amd64.h
new file mode 100644
index 0000000..9949435
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/abi_amd64.h
@@ -0,0 +1,99 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Macros for transitioning from the host ABI to Go ABI0.
+//
+// These save the frame pointer, so in general, functions that use
+// these should have zero frame size to suppress the automatic frame
+// pointer, though it's harmless to not do this.
+
+#ifdef GOOS_windows
+
+// REGS_HOST_TO_ABI0_STACK is the stack bytes used by
+// PUSH_REGS_HOST_TO_ABI0.
+#define REGS_HOST_TO_ABI0_STACK (28*8 + 8)
+
+// PUSH_REGS_HOST_TO_ABI0 prepares for transitioning from
+// the host ABI to Go ABI0 code. It saves all registers that are
+// callee-save in the host ABI and caller-save in Go ABI0 and prepares
+// for entry to Go.
+//
+// Save DI SI BP BX R12 R13 R14 R15 X6-X15 registers and the DF flag.
+// Clear the DF flag for the Go ABI.
+// MXCSR matches the Go ABI, so we don't have to set that,
+// and Go doesn't modify it, so we don't have to save it.
+#define PUSH_REGS_HOST_TO_ABI0() \
+ PUSHFQ \
+ CLD \
+ ADJSP $(REGS_HOST_TO_ABI0_STACK - 8) \
+ MOVQ DI, (0*0)(SP) \
+ MOVQ SI, (1*8)(SP) \
+ MOVQ BP, (2*8)(SP) \
+ MOVQ BX, (3*8)(SP) \
+ MOVQ R12, (4*8)(SP) \
+ MOVQ R13, (5*8)(SP) \
+ MOVQ R14, (6*8)(SP) \
+ MOVQ R15, (7*8)(SP) \
+ MOVUPS X6, (8*8)(SP) \
+ MOVUPS X7, (10*8)(SP) \
+ MOVUPS X8, (12*8)(SP) \
+ MOVUPS X9, (14*8)(SP) \
+ MOVUPS X10, (16*8)(SP) \
+ MOVUPS X11, (18*8)(SP) \
+ MOVUPS X12, (20*8)(SP) \
+ MOVUPS X13, (22*8)(SP) \
+ MOVUPS X14, (24*8)(SP) \
+ MOVUPS X15, (26*8)(SP)
+
+#define POP_REGS_HOST_TO_ABI0() \
+ MOVQ (0*0)(SP), DI \
+ MOVQ (1*8)(SP), SI \
+ MOVQ (2*8)(SP), BP \
+ MOVQ (3*8)(SP), BX \
+ MOVQ (4*8)(SP), R12 \
+ MOVQ (5*8)(SP), R13 \
+ MOVQ (6*8)(SP), R14 \
+ MOVQ (7*8)(SP), R15 \
+ MOVUPS (8*8)(SP), X6 \
+ MOVUPS (10*8)(SP), X7 \
+ MOVUPS (12*8)(SP), X8 \
+ MOVUPS (14*8)(SP), X9 \
+ MOVUPS (16*8)(SP), X10 \
+ MOVUPS (18*8)(SP), X11 \
+ MOVUPS (20*8)(SP), X12 \
+ MOVUPS (22*8)(SP), X13 \
+ MOVUPS (24*8)(SP), X14 \
+ MOVUPS (26*8)(SP), X15 \
+ ADJSP $-(REGS_HOST_TO_ABI0_STACK - 8) \
+ POPFQ
+
+#else
+// SysV ABI
+
+#define REGS_HOST_TO_ABI0_STACK (6*8)
+
+// SysV MXCSR matches the Go ABI, so we don't have to set that,
+// and Go doesn't modify it, so we don't have to save it.
+// Both SysV and Go require DF to be cleared, so that's already clear.
+// The SysV and Go frame pointer conventions are compatible.
+#define PUSH_REGS_HOST_TO_ABI0() \
+ ADJSP $(REGS_HOST_TO_ABI0_STACK) \
+ MOVQ BP, (5*8)(SP) \
+ LEAQ (5*8)(SP), BP \
+ MOVQ BX, (0*8)(SP) \
+ MOVQ R12, (1*8)(SP) \
+ MOVQ R13, (2*8)(SP) \
+ MOVQ R14, (3*8)(SP) \
+ MOVQ R15, (4*8)(SP)
+
+#define POP_REGS_HOST_TO_ABI0() \
+ MOVQ (0*8)(SP), BX \
+ MOVQ (1*8)(SP), R12 \
+ MOVQ (2*8)(SP), R13 \
+ MOVQ (3*8)(SP), R14 \
+ MOVQ (4*8)(SP), R15 \
+ MOVQ (5*8)(SP), BP \
+ ADJSP $-(REGS_HOST_TO_ABI0_STACK)
+
+#endif
diff --git a/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/abi_arm64.h b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/abi_arm64.h
new file mode 100644
index 0000000..5d5061e
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/abi_arm64.h
@@ -0,0 +1,39 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Macros for transitioning from the host ABI to Go ABI0.
+//
+// These macros save and restore the callee-saved registers
+// from the stack, but they don't adjust stack pointer, so
+// the user should prepare stack space in advance.
+// SAVE_R19_TO_R28(offset) saves R19 ~ R28 to the stack space
+// of ((offset)+0*8)(RSP) ~ ((offset)+9*8)(RSP).
+//
+// SAVE_F8_TO_F15(offset) saves F8 ~ F15 to the stack space
+// of ((offset)+0*8)(RSP) ~ ((offset)+7*8)(RSP).
+//
+// R29 is not saved because Go will save and restore it.
+
+#define SAVE_R19_TO_R28(offset) \
+ STP (R19, R20), ((offset)+0*8)(RSP) \
+ STP (R21, R22), ((offset)+2*8)(RSP) \
+ STP (R23, R24), ((offset)+4*8)(RSP) \
+ STP (R25, R26), ((offset)+6*8)(RSP) \
+ STP (R27, g), ((offset)+8*8)(RSP)
+#define RESTORE_R19_TO_R28(offset) \
+ LDP ((offset)+0*8)(RSP), (R19, R20) \
+ LDP ((offset)+2*8)(RSP), (R21, R22) \
+ LDP ((offset)+4*8)(RSP), (R23, R24) \
+ LDP ((offset)+6*8)(RSP), (R25, R26) \
+ LDP ((offset)+8*8)(RSP), (R27, g) /* R28 */
+#define SAVE_F8_TO_F15(offset) \
+ FSTPD (F8, F9), ((offset)+0*8)(RSP) \
+ FSTPD (F10, F11), ((offset)+2*8)(RSP) \
+ FSTPD (F12, F13), ((offset)+4*8)(RSP) \
+ FSTPD (F14, F15), ((offset)+6*8)(RSP)
+#define RESTORE_F8_TO_F15(offset) \
+ FLDPD ((offset)+0*8)(RSP), (F8, F9) \
+ FLDPD ((offset)+2*8)(RSP), (F10, F11) \
+ FLDPD ((offset)+4*8)(RSP), (F12, F13) \
+ FLDPD ((offset)+6*8)(RSP), (F14, F15)
diff --git a/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/abi_loong64.h b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/abi_loong64.h
new file mode 100644
index 0000000..b10d837
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/abi_loong64.h
@@ -0,0 +1,60 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Macros for transitioning from the host ABI to Go ABI0.
+//
+// These macros save and restore the callee-saved registers
+// from the stack, but they don't adjust stack pointer, so
+// the user should prepare stack space in advance.
+// SAVE_R22_TO_R31(offset) saves R22 ~ R31 to the stack space
+// of ((offset)+0*8)(R3) ~ ((offset)+9*8)(R3).
+//
+// SAVE_F24_TO_F31(offset) saves F24 ~ F31 to the stack space
+// of ((offset)+0*8)(R3) ~ ((offset)+7*8)(R3).
+//
+// Note: g is R22
+
+#define SAVE_R22_TO_R31(offset) \
+ MOVV g, ((offset)+(0*8))(R3) \
+ MOVV R23, ((offset)+(1*8))(R3) \
+ MOVV R24, ((offset)+(2*8))(R3) \
+ MOVV R25, ((offset)+(3*8))(R3) \
+ MOVV R26, ((offset)+(4*8))(R3) \
+ MOVV R27, ((offset)+(5*8))(R3) \
+ MOVV R28, ((offset)+(6*8))(R3) \
+ MOVV R29, ((offset)+(7*8))(R3) \
+ MOVV R30, ((offset)+(8*8))(R3) \
+ MOVV R31, ((offset)+(9*8))(R3)
+
+#define SAVE_F24_TO_F31(offset) \
+ MOVD F24, ((offset)+(0*8))(R3) \
+ MOVD F25, ((offset)+(1*8))(R3) \
+ MOVD F26, ((offset)+(2*8))(R3) \
+ MOVD F27, ((offset)+(3*8))(R3) \
+ MOVD F28, ((offset)+(4*8))(R3) \
+ MOVD F29, ((offset)+(5*8))(R3) \
+ MOVD F30, ((offset)+(6*8))(R3) \
+ MOVD F31, ((offset)+(7*8))(R3)
+
+#define RESTORE_R22_TO_R31(offset) \
+ MOVV ((offset)+(0*8))(R3), g \
+ MOVV ((offset)+(1*8))(R3), R23 \
+ MOVV ((offset)+(2*8))(R3), R24 \
+ MOVV ((offset)+(3*8))(R3), R25 \
+ MOVV ((offset)+(4*8))(R3), R26 \
+ MOVV ((offset)+(5*8))(R3), R27 \
+ MOVV ((offset)+(6*8))(R3), R28 \
+ MOVV ((offset)+(7*8))(R3), R29 \
+ MOVV ((offset)+(8*8))(R3), R30 \
+ MOVV ((offset)+(9*8))(R3), R31
+
+#define RESTORE_F24_TO_F31(offset) \
+ MOVD ((offset)+(0*8))(R3), F24 \
+ MOVD ((offset)+(1*8))(R3), F25 \
+ MOVD ((offset)+(2*8))(R3), F26 \
+ MOVD ((offset)+(3*8))(R3), F27 \
+ MOVD ((offset)+(4*8))(R3), F28 \
+ MOVD ((offset)+(5*8))(R3), F29 \
+ MOVD ((offset)+(6*8))(R3), F30 \
+ MOVD ((offset)+(7*8))(R3), F31
diff --git a/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/abi_ppc64x.h b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/abi_ppc64x.h
new file mode 100644
index 0000000..245a526
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/abi_ppc64x.h
@@ -0,0 +1,195 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Macros for transitioning from the host ABI to Go ABI
+//
+// On PPC64/ELFv2 targets, the following registers are callee
+// saved when called from C. They must be preserved before
+// calling into Go which does not preserve any of them.
+//
+// R14-R31
+// CR2-4
+// VR20-31
+// F14-F31
+//
+// xcoff(aix) and ELFv1 are similar, but may only require a
+// subset of these.
+//
+// These macros assume a 16 byte aligned stack pointer. This
+// is required by ELFv1, ELFv2, and AIX PPC64.
+
+#define SAVE_GPR_SIZE (18*8)
+#define SAVE_GPR(offset) \
+ MOVD R14, (offset+8*0)(R1) \
+ MOVD R15, (offset+8*1)(R1) \
+ MOVD R16, (offset+8*2)(R1) \
+ MOVD R17, (offset+8*3)(R1) \
+ MOVD R18, (offset+8*4)(R1) \
+ MOVD R19, (offset+8*5)(R1) \
+ MOVD R20, (offset+8*6)(R1) \
+ MOVD R21, (offset+8*7)(R1) \
+ MOVD R22, (offset+8*8)(R1) \
+ MOVD R23, (offset+8*9)(R1) \
+ MOVD R24, (offset+8*10)(R1) \
+ MOVD R25, (offset+8*11)(R1) \
+ MOVD R26, (offset+8*12)(R1) \
+ MOVD R27, (offset+8*13)(R1) \
+ MOVD R28, (offset+8*14)(R1) \
+ MOVD R29, (offset+8*15)(R1) \
+ MOVD g, (offset+8*16)(R1) \
+ MOVD R31, (offset+8*17)(R1)
+
+#define RESTORE_GPR(offset) \
+ MOVD (offset+8*0)(R1), R14 \
+ MOVD (offset+8*1)(R1), R15 \
+ MOVD (offset+8*2)(R1), R16 \
+ MOVD (offset+8*3)(R1), R17 \
+ MOVD (offset+8*4)(R1), R18 \
+ MOVD (offset+8*5)(R1), R19 \
+ MOVD (offset+8*6)(R1), R20 \
+ MOVD (offset+8*7)(R1), R21 \
+ MOVD (offset+8*8)(R1), R22 \
+ MOVD (offset+8*9)(R1), R23 \
+ MOVD (offset+8*10)(R1), R24 \
+ MOVD (offset+8*11)(R1), R25 \
+ MOVD (offset+8*12)(R1), R26 \
+ MOVD (offset+8*13)(R1), R27 \
+ MOVD (offset+8*14)(R1), R28 \
+ MOVD (offset+8*15)(R1), R29 \
+ MOVD (offset+8*16)(R1), g \
+ MOVD (offset+8*17)(R1), R31
+
+#define SAVE_FPR_SIZE (18*8)
+#define SAVE_FPR(offset) \
+ FMOVD F14, (offset+8*0)(R1) \
+ FMOVD F15, (offset+8*1)(R1) \
+ FMOVD F16, (offset+8*2)(R1) \
+ FMOVD F17, (offset+8*3)(R1) \
+ FMOVD F18, (offset+8*4)(R1) \
+ FMOVD F19, (offset+8*5)(R1) \
+ FMOVD F20, (offset+8*6)(R1) \
+ FMOVD F21, (offset+8*7)(R1) \
+ FMOVD F22, (offset+8*8)(R1) \
+ FMOVD F23, (offset+8*9)(R1) \
+ FMOVD F24, (offset+8*10)(R1) \
+ FMOVD F25, (offset+8*11)(R1) \
+ FMOVD F26, (offset+8*12)(R1) \
+ FMOVD F27, (offset+8*13)(R1) \
+ FMOVD F28, (offset+8*14)(R1) \
+ FMOVD F29, (offset+8*15)(R1) \
+ FMOVD F30, (offset+8*16)(R1) \
+ FMOVD F31, (offset+8*17)(R1)
+
+#define RESTORE_FPR(offset) \
+ FMOVD (offset+8*0)(R1), F14 \
+ FMOVD (offset+8*1)(R1), F15 \
+ FMOVD (offset+8*2)(R1), F16 \
+ FMOVD (offset+8*3)(R1), F17 \
+ FMOVD (offset+8*4)(R1), F18 \
+ FMOVD (offset+8*5)(R1), F19 \
+ FMOVD (offset+8*6)(R1), F20 \
+ FMOVD (offset+8*7)(R1), F21 \
+ FMOVD (offset+8*8)(R1), F22 \
+ FMOVD (offset+8*9)(R1), F23 \
+ FMOVD (offset+8*10)(R1), F24 \
+ FMOVD (offset+8*11)(R1), F25 \
+ FMOVD (offset+8*12)(R1), F26 \
+ FMOVD (offset+8*13)(R1), F27 \
+ FMOVD (offset+8*14)(R1), F28 \
+ FMOVD (offset+8*15)(R1), F29 \
+ FMOVD (offset+8*16)(R1), F30 \
+ FMOVD (offset+8*17)(R1), F31
+
+// Save and restore VR20-31 (aka VSR56-63). These
+// macros must point to a 16B aligned offset.
+#define SAVE_VR_SIZE (12*16)
+#define SAVE_VR(offset, rtmp) \
+ MOVD $(offset+16*0), rtmp \
+ STVX V20, (rtmp)(R1) \
+ MOVD $(offset+16*1), rtmp \
+ STVX V21, (rtmp)(R1) \
+ MOVD $(offset+16*2), rtmp \
+ STVX V22, (rtmp)(R1) \
+ MOVD $(offset+16*3), rtmp \
+ STVX V23, (rtmp)(R1) \
+ MOVD $(offset+16*4), rtmp \
+ STVX V24, (rtmp)(R1) \
+ MOVD $(offset+16*5), rtmp \
+ STVX V25, (rtmp)(R1) \
+ MOVD $(offset+16*6), rtmp \
+ STVX V26, (rtmp)(R1) \
+ MOVD $(offset+16*7), rtmp \
+ STVX V27, (rtmp)(R1) \
+ MOVD $(offset+16*8), rtmp \
+ STVX V28, (rtmp)(R1) \
+ MOVD $(offset+16*9), rtmp \
+ STVX V29, (rtmp)(R1) \
+ MOVD $(offset+16*10), rtmp \
+ STVX V30, (rtmp)(R1) \
+ MOVD $(offset+16*11), rtmp \
+ STVX V31, (rtmp)(R1)
+
+#define RESTORE_VR(offset, rtmp) \
+ MOVD $(offset+16*0), rtmp \
+ LVX (rtmp)(R1), V20 \
+ MOVD $(offset+16*1), rtmp \
+ LVX (rtmp)(R1), V21 \
+ MOVD $(offset+16*2), rtmp \
+ LVX (rtmp)(R1), V22 \
+ MOVD $(offset+16*3), rtmp \
+ LVX (rtmp)(R1), V23 \
+ MOVD $(offset+16*4), rtmp \
+ LVX (rtmp)(R1), V24 \
+ MOVD $(offset+16*5), rtmp \
+ LVX (rtmp)(R1), V25 \
+ MOVD $(offset+16*6), rtmp \
+ LVX (rtmp)(R1), V26 \
+ MOVD $(offset+16*7), rtmp \
+ LVX (rtmp)(R1), V27 \
+ MOVD $(offset+16*8), rtmp \
+ LVX (rtmp)(R1), V28 \
+ MOVD $(offset+16*9), rtmp \
+ LVX (rtmp)(R1), V29 \
+ MOVD $(offset+16*10), rtmp \
+ LVX (rtmp)(R1), V30 \
+ MOVD $(offset+16*11), rtmp \
+ LVX (rtmp)(R1), V31
+
+// LR and CR are saved in the caller's frame. The callee must
+// make space for all other callee-save registers.
+#define SAVE_ALL_REG_SIZE (SAVE_GPR_SIZE+SAVE_FPR_SIZE+SAVE_VR_SIZE)
+
+// Stack a frame and save all callee-save registers following the
+// host OS's ABI. Fortunately, this is identical for AIX, ELFv1, and
+// ELFv2. All host ABIs require the stack pointer to maintain 16 byte
+// alignment, and save the callee-save registers in the same places.
+//
+// To restate, R1 is assumed to be aligned when this macro is used.
+// This assumes the caller's frame is compliant with the host ABI.
+// CR and LR are saved into the caller's frame per the host ABI.
+// R0 is initialized to $0 as expected by Go.
+#define STACK_AND_SAVE_HOST_TO_GO_ABI(extra) \
+ MOVD LR, R0 \
+ MOVD R0, 16(R1) \
+ MOVW CR, R0 \
+ MOVD R0, 8(R1) \
+ MOVDU R1, -(extra)-FIXED_FRAME-SAVE_ALL_REG_SIZE(R1) \
+ SAVE_GPR(extra+FIXED_FRAME) \
+ SAVE_FPR(extra+FIXED_FRAME+SAVE_GPR_SIZE) \
+ SAVE_VR(extra+FIXED_FRAME+SAVE_GPR_SIZE+SAVE_FPR_SIZE, R0) \
+ MOVD $0, R0
+
+// This unstacks the frame, restoring all callee-save registers
+// as saved by STACK_AND_SAVE_HOST_TO_GO_ABI.
+//
+// R0 is not guaranteed to contain $0 after this macro.
+#define UNSTACK_AND_RESTORE_GO_TO_HOST_ABI(extra) \
+ RESTORE_GPR(extra+FIXED_FRAME) \
+ RESTORE_FPR(extra+FIXED_FRAME+SAVE_GPR_SIZE) \
+ RESTORE_VR(extra+FIXED_FRAME+SAVE_GPR_SIZE+SAVE_FPR_SIZE, R0) \
+ ADD $(extra+FIXED_FRAME+SAVE_ALL_REG_SIZE), R1 \
+ MOVD 16(R1), R0 \
+ MOVD R0, LR \
+ MOVD 8(R1), R0 \
+ MOVW R0, CR
diff --git a/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/asm_386.s b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/asm_386.s
new file mode 100644
index 0000000..7475ec8
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/asm_386.s
@@ -0,0 +1,29 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "textflag.h"
+
+// Called by C code generated by cmd/cgo.
+// func crosscall2(fn, a unsafe.Pointer, n int32, ctxt uintptr)
+// Saves C callee-saved registers and calls cgocallback with three arguments.
+// fn is the PC of a func(a unsafe.Pointer) function.
+TEXT crosscall2(SB), NOSPLIT, $28-16
+ MOVL BP, 24(SP)
+ MOVL BX, 20(SP)
+ MOVL SI, 16(SP)
+ MOVL DI, 12(SP)
+
+ MOVL ctxt+12(FP), AX
+ MOVL AX, 8(SP)
+ MOVL a+4(FP), AX
+ MOVL AX, 4(SP)
+ MOVL fn+0(FP), AX
+ MOVL AX, 0(SP)
+ CALL runtime·cgocallback(SB)
+
+ MOVL 12(SP), DI
+ MOVL 16(SP), SI
+ MOVL 20(SP), BX
+ MOVL 24(SP), BP
+ RET
diff --git a/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/asm_amd64.s b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/asm_amd64.s
new file mode 100644
index 0000000..2b7eb57
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/asm_amd64.s
@@ -0,0 +1,39 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "textflag.h"
+#include "abi_amd64.h"
+
+// Called by C code generated by cmd/cgo.
+// func crosscall2(fn, a unsafe.Pointer, n int32, ctxt uintptr)
+// Saves C callee-saved registers and calls cgocallback with three arguments.
+// fn is the PC of a func(a unsafe.Pointer) function.
+// This signature is known to SWIG, so we can't change it.
+TEXT crosscall2(SB), NOSPLIT, $0-0
+ PUSH_REGS_HOST_TO_ABI0()
+
+ // Make room for arguments to cgocallback.
+ ADJSP $0x18
+
+#ifndef GOOS_windows
+ MOVQ DI, 0x0(SP) // fn
+ MOVQ SI, 0x8(SP) // arg
+
+ // Skip n in DX.
+ MOVQ CX, 0x10(SP) // ctxt
+
+#else
+ MOVQ CX, 0x0(SP) // fn
+ MOVQ DX, 0x8(SP) // arg
+
+ // Skip n in R8.
+ MOVQ R9, 0x10(SP) // ctxt
+
+#endif
+
+ CALL runtime·cgocallback(SB)
+
+ ADJSP $-0x18
+ POP_REGS_HOST_TO_ABI0()
+ RET
diff --git a/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/asm_arm.s b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/asm_arm.s
new file mode 100644
index 0000000..68034e6
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/asm_arm.s
@@ -0,0 +1,52 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "textflag.h"
+
+// Called by C code generated by cmd/cgo.
+// func crosscall2(fn, a unsafe.Pointer, n int32, ctxt uintptr)
+// Saves C callee-saved registers and calls cgocallback with three arguments.
+// fn is the PC of a func(a unsafe.Pointer) function.
+TEXT crosscall2(SB), NOSPLIT|NOFRAME, $0
+ SUB $(8*9), R13 // Reserve space for the floating point registers.
+
+ // The C arguments arrive in R0, R1, R2, and R3. We want to
+ // pass R0, R1, and R3 to Go, so we push those on the stack.
+ // Also, save C callee-save registers R4-R12.
+ MOVM.WP [R0, R1, R3, R4, R5, R6, R7, R8, R9, g, R11, R12], (R13)
+
+ // Finally, save the link register R14. This also puts the
+ // arguments we pushed for cgocallback where they need to be,
+ // starting at 4(R13).
+ MOVW.W R14, -4(R13)
+
+ // Save VFP callee-saved registers D8-D15 (same as S16-S31).
+ // Note: We always save these since we target hard-float ABI.
+ MOVD F8, (13*4+8*1)(R13)
+ MOVD F9, (13*4+8*2)(R13)
+ MOVD F10, (13*4+8*3)(R13)
+ MOVD F11, (13*4+8*4)(R13)
+ MOVD F12, (13*4+8*5)(R13)
+ MOVD F13, (13*4+8*6)(R13)
+ MOVD F14, (13*4+8*7)(R13)
+ MOVD F15, (13*4+8*8)(R13)
+
+ BL runtime·load_g(SB)
+
+ // We set up the arguments to cgocallback when saving registers above.
+ BL runtime·cgocallback(SB)
+
+ MOVD (13*4+8*1)(R13), F8
+ MOVD (13*4+8*2)(R13), F9
+ MOVD (13*4+8*3)(R13), F10
+ MOVD (13*4+8*4)(R13), F11
+ MOVD (13*4+8*5)(R13), F12
+ MOVD (13*4+8*6)(R13), F13
+ MOVD (13*4+8*7)(R13), F14
+ MOVD (13*4+8*8)(R13), F15
+
+ MOVW.P 4(R13), R14
+ MOVM.IAW (R13), [R0, R1, R3, R4, R5, R6, R7, R8, R9, g, R11, R12]
+ ADD $(8*9), R13
+ MOVW R14, R15
diff --git a/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/asm_arm64.s b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/asm_arm64.s
new file mode 100644
index 0000000..50e5261
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/asm_arm64.s
@@ -0,0 +1,36 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "textflag.h"
+#include "abi_arm64.h"
+
+// Called by C code generated by cmd/cgo.
+// func crosscall2(fn, a unsafe.Pointer, n int32, ctxt uintptr)
+// Saves C callee-saved registers and calls cgocallback with three arguments.
+// fn is the PC of a func(a unsafe.Pointer) function.
+TEXT crosscall2(SB), NOSPLIT|NOFRAME, $0
+/*
+ * We still need to save all callee save register as before, and then
+ * push 3 args for fn (R0, R1, R3), skipping R2.
+ * Also note that at procedure entry in gc world, 8(RSP) will be the
+ * first arg.
+ */
+ SUB $(8*24), RSP
+ STP (R0, R1), (8*1)(RSP)
+ MOVD R3, (8*3)(RSP)
+
+ SAVE_R19_TO_R28(8*4)
+ SAVE_F8_TO_F15(8*14)
+ STP (R29, R30), (8*22)(RSP)
+
+ // Initialize Go ABI environment
+ BL runtime·load_g(SB)
+ BL runtime·cgocallback(SB)
+
+ RESTORE_R19_TO_R28(8*4)
+ RESTORE_F8_TO_F15(8*14)
+ LDP (8*22)(RSP), (R29, R30)
+
+ ADD $(8*24), RSP
+ RET
diff --git a/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/asm_loong64.s b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/asm_loong64.s
new file mode 100644
index 0000000..e81df86
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/asm_loong64.s
@@ -0,0 +1,40 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "textflag.h"
+#include "abi_loong64.h"
+
+// Called by C code generated by cmd/cgo.
+// func crosscall2(fn, a unsafe.Pointer, n int32, ctxt uintptr)
+// Saves C callee-saved registers and calls cgocallback with three arguments.
+// fn is the PC of a func(a unsafe.Pointer) function.
+TEXT crosscall2(SB), NOSPLIT|NOFRAME, $0
+/*
+ * We still need to save all callee save register as before, and then
+ * push 3 args for fn (R4, R5, R7), skipping R6.
+ * Also note that at procedure entry in gc world, 8(R29) will be the
+ * first arg.
+ */
+
+ ADDV $(-23*8), R3
+ MOVV R4, (1*8)(R3) // fn unsafe.Pointer
+ MOVV R5, (2*8)(R3) // a unsafe.Pointer
+ MOVV R7, (3*8)(R3) // ctxt uintptr
+
+ SAVE_R22_TO_R31((4*8))
+ SAVE_F24_TO_F31((14*8))
+ MOVV R1, (22*8)(R3)
+
+ // Initialize Go ABI environment
+ JAL runtime·load_g(SB)
+
+ JAL runtime·cgocallback(SB)
+
+ RESTORE_R22_TO_R31((4*8))
+ RESTORE_F24_TO_F31((14*8))
+ MOVV (22*8)(R3), R1
+
+ ADDV $(23*8), R3
+
+ RET
diff --git a/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/asm_ppc64le.s b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/asm_ppc64le.s
new file mode 100644
index 0000000..6d1938c
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/asm_ppc64le.s
@@ -0,0 +1,82 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "textflag.h"
+#include "abi_ppc64x.h"
+
+// Called by C code generated by cmd/cgo.
+// func crosscall2(fn, a unsafe.Pointer, n int32, ctxt uintptr)
+// Saves C callee-saved registers and calls cgocallback with three arguments.
+// fn is the PC of a func(a unsafe.Pointer) function.
+//
+// This is a simplified version that only saves GPR and FPR registers,
+// not vector registers. This keeps the stack frame smaller to avoid
+// exceeding the nosplit stack limit.
+//
+// On PPC64LE ELFv2, callee-save registers are:
+// R14-R31 (18 GPRs = 144 bytes)
+// F14-F31 (18 FPRs = 144 bytes)
+// CR2-CR4 (saved in CR field)
+//
+// Stack layout (must be 16-byte aligned):
+// 32 (FIXED_FRAME) + 24 (args) + 144 (GPR) + 144 (FPR) = 344
+// Rounded to 352 for 16-byte alignment.
+
+#define FIXED_FRAME 32
+#define SAVE_SIZE 352
+#define GPR_OFFSET (FIXED_FRAME+24)
+#define FPR_OFFSET (GPR_OFFSET+SAVE_GPR_SIZE)
+
+TEXT crosscall2(SB), NOSPLIT|NOFRAME, $0
+ // Save LR and CR in caller's frame per ELFv2 ABI
+ MOVD LR, R0
+ MOVD R0, 16(R1)
+ MOVW CR, R0
+ MOVD R0, 8(R1)
+
+ // Allocate our stack frame
+ MOVDU R1, -SAVE_SIZE(R1)
+
+ // Save TOC (R2) in case needed
+ MOVD R2, 24(R1)
+
+ // Save callee-save GPRs
+ SAVE_GPR(GPR_OFFSET)
+
+ // Save callee-save FPRs
+ SAVE_FPR(FPR_OFFSET)
+
+ // Initialize R0 to 0 as expected by Go
+ MOVD $0, R0
+
+ // Load the current g.
+ BL runtime·load_g(SB)
+
+ // Set up arguments for cgocallback
+ MOVD R3, FIXED_FRAME+0(R1) // fn unsafe.Pointer
+ MOVD R4, FIXED_FRAME+8(R1) // a unsafe.Pointer
+
+ // Skip R5 = n uint32
+ MOVD R6, FIXED_FRAME+16(R1) // ctxt uintptr
+ BL runtime·cgocallback(SB)
+
+ // Restore callee-save FPRs
+ RESTORE_FPR(FPR_OFFSET)
+
+ // Restore callee-save GPRs
+ RESTORE_GPR(GPR_OFFSET)
+
+ // Restore TOC
+ MOVD 24(R1), R2
+
+ // Deallocate stack frame
+ ADD $SAVE_SIZE, R1
+
+ // Restore LR and CR from caller's frame
+ MOVD 16(R1), R0
+ MOVD R0, LR
+ MOVD 8(R1), R0
+ MOVW R0, CR
+
+ RET
diff --git a/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/asm_riscv64.s b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/asm_riscv64.s
new file mode 100644
index 0000000..acf82c1
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/asm_riscv64.s
@@ -0,0 +1,78 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "textflag.h"
+
+// Called by C code generated by cmd/cgo.
+// func crosscall2(fn, a unsafe.Pointer, n int32, ctxt uintptr)
+// Saves C callee-saved registers and calls cgocallback with three arguments.
+// fn is the PC of a func(a unsafe.Pointer) function.
+TEXT crosscall2(SB), NOSPLIT|NOFRAME, $0
+/*
+ * Push arguments for fn (X10, X11, X13), along with all callee-save
+ * registers. Note that at procedure entry the first argument is at
+ * 8(X2).
+ */
+ ADD $(-8*29), X2
+ MOV X10, (8*1)(X2) // fn unsafe.Pointer
+ MOV X11, (8*2)(X2) // a unsafe.Pointer
+ MOV X13, (8*3)(X2) // ctxt uintptr
+ MOV X8, (8*4)(X2)
+ MOV X9, (8*5)(X2)
+ MOV X18, (8*6)(X2)
+ MOV X19, (8*7)(X2)
+ MOV X20, (8*8)(X2)
+ MOV X21, (8*9)(X2)
+ MOV X22, (8*10)(X2)
+ MOV X23, (8*11)(X2)
+ MOV X24, (8*12)(X2)
+ MOV X25, (8*13)(X2)
+ MOV X26, (8*14)(X2)
+ MOV g, (8*15)(X2)
+ MOV X1, (8*16)(X2)
+ MOVD F8, (8*17)(X2)
+ MOVD F9, (8*18)(X2)
+ MOVD F18, (8*19)(X2)
+ MOVD F19, (8*20)(X2)
+ MOVD F20, (8*21)(X2)
+ MOVD F21, (8*22)(X2)
+ MOVD F22, (8*23)(X2)
+ MOVD F23, (8*24)(X2)
+ MOVD F24, (8*25)(X2)
+ MOVD F25, (8*26)(X2)
+ MOVD F26, (8*27)(X2)
+ MOVD F27, (8*28)(X2)
+
+ // Initialize Go ABI environment
+ CALL runtime·load_g(SB)
+ CALL runtime·cgocallback(SB)
+
+ MOV (8*4)(X2), X8
+ MOV (8*5)(X2), X9
+ MOV (8*6)(X2), X18
+ MOV (8*7)(X2), X19
+ MOV (8*8)(X2), X20
+ MOV (8*9)(X2), X21
+ MOV (8*10)(X2), X22
+ MOV (8*11)(X2), X23
+ MOV (8*12)(X2), X24
+ MOV (8*13)(X2), X25
+ MOV (8*14)(X2), X26
+ MOV (8*15)(X2), g
+ MOV (8*16)(X2), X1
+ MOVD (8*17)(X2), F8
+ MOVD (8*18)(X2), F9
+ MOVD (8*19)(X2), F18
+ MOVD (8*20)(X2), F19
+ MOVD (8*21)(X2), F20
+ MOVD (8*22)(X2), F21
+ MOVD (8*23)(X2), F22
+ MOVD (8*24)(X2), F23
+ MOVD (8*25)(X2), F24
+ MOVD (8*26)(X2), F25
+ MOVD (8*27)(X2), F26
+ MOVD (8*28)(X2), F27
+ ADD $(8*29), X2
+
+ RET
diff --git a/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/asm_s390x.s b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/asm_s390x.s
new file mode 100644
index 0000000..b644665
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/asm_s390x.s
@@ -0,0 +1,55 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "textflag.h"
+
+// Called by C code generated by cmd/cgo.
+// func crosscall2(fn, a unsafe.Pointer, n int32, ctxt uintptr)
+// Saves C callee-saved registers and calls cgocallback with three arguments.
+// fn is the PC of a func(a unsafe.Pointer) function.
+TEXT crosscall2(SB), NOSPLIT|NOFRAME, $0
+ // Start with standard C stack frame layout and linkage.
+
+ // Save R6-R15 in the register save area of the calling function.
+ STMG R6, R15, 48(R15)
+
+ // Allocate 96 bytes on the stack.
+ MOVD $-96(R15), R15
+
+ // Save F8-F15 in our stack frame.
+ FMOVD F8, 32(R15)
+ FMOVD F9, 40(R15)
+ FMOVD F10, 48(R15)
+ FMOVD F11, 56(R15)
+ FMOVD F12, 64(R15)
+ FMOVD F13, 72(R15)
+ FMOVD F14, 80(R15)
+ FMOVD F15, 88(R15)
+
+ // Initialize Go ABI environment.
+ BL runtime·load_g(SB)
+
+ MOVD R2, 8(R15) // fn unsafe.Pointer
+ MOVD R3, 16(R15) // a unsafe.Pointer
+
+ // Skip R4 = n uint32
+ MOVD R5, 24(R15) // ctxt uintptr
+ BL runtime·cgocallback(SB)
+
+ FMOVD 32(R15), F8
+ FMOVD 40(R15), F9
+ FMOVD 48(R15), F10
+ FMOVD 56(R15), F11
+ FMOVD 64(R15), F12
+ FMOVD 72(R15), F13
+ FMOVD 80(R15), F14
+ FMOVD 88(R15), F15
+
+ // De-allocate stack frame.
+ MOVD $96(R15), R15
+
+ // Restore R6-R15.
+ LMG 48(R15), R6, R15
+
+ RET
diff --git a/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/callbacks.go b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/callbacks.go
new file mode 100644
index 0000000..27d4c98
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/callbacks.go
@@ -0,0 +1,93 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build !cgo && (darwin || freebsd || linux || netbsd)
+
+package fakecgo
+
+import (
+ _ "unsafe"
+)
+
+// TODO: decide if we need _runtime_cgo_panic_internal
+
+//go:linkname x_cgo_init_trampoline x_cgo_init_trampoline
+//go:linkname _cgo_init _cgo_init
+var x_cgo_init_trampoline byte
+var _cgo_init = &x_cgo_init_trampoline
+
+// Creates a new system thread without updating any Go state.
+//
+// This method is invoked during shared library loading to create a new OS
+// thread to perform the runtime initialization. This method is similar to
+// _cgo_sys_thread_start except that it doesn't update any Go state.
+
+//go:linkname x_cgo_thread_start_trampoline x_cgo_thread_start_trampoline
+//go:linkname _cgo_thread_start _cgo_thread_start
+var x_cgo_thread_start_trampoline byte
+var _cgo_thread_start = &x_cgo_thread_start_trampoline
+
+// Notifies that the runtime has been initialized.
+//
+// We currently block at every CGO entry point (via _cgo_wait_runtime_init_done)
+// to ensure that the runtime has been initialized before the CGO call is
+// executed. This is necessary for shared libraries where we kickoff runtime
+// initialization in a separate thread and return without waiting for this
+// thread to complete the init.
+
+//go:linkname x_cgo_notify_runtime_init_done_trampoline x_cgo_notify_runtime_init_done_trampoline
+//go:linkname _cgo_notify_runtime_init_done _cgo_notify_runtime_init_done
+var x_cgo_notify_runtime_init_done_trampoline byte
+var _cgo_notify_runtime_init_done = &x_cgo_notify_runtime_init_done_trampoline
+
+// Indicates whether a dummy thread key has been created or not.
+//
+// When calling go exported function from C, we register a destructor
+// callback, for a dummy thread key, by using pthread_key_create.
+
+//go:linkname _cgo_pthread_key_created _cgo_pthread_key_created
+var x_cgo_pthread_key_created uintptr
+var _cgo_pthread_key_created = &x_cgo_pthread_key_created
+
+// Set the x_crosscall2_ptr C function pointer variable point to crosscall2.
+// It's for the runtime package to call at init time.
+func set_crosscall2() {
+ // nothing needs to be done here for fakecgo
+ // because it's possible to just call cgocallback directly
+}
+
+//go:linkname _set_crosscall2 runtime.set_crosscall2
+var _set_crosscall2 = set_crosscall2
+
+// Store the g into the thread-specific value.
+// So that pthread_key_destructor will dropm when the thread is exiting.
+
+//go:linkname x_cgo_bindm_trampoline x_cgo_bindm_trampoline
+//go:linkname _cgo_bindm _cgo_bindm
+var x_cgo_bindm_trampoline byte
+var _cgo_bindm = &x_cgo_bindm_trampoline
+
+// TODO: decide if we need x_cgo_set_context_function
+// TODO: decide if we need _cgo_yield
+
+var (
+ // In Go 1.20 the race detector was rewritten to pure Go
+ // on darwin. This means that when CGO_ENABLED=0 is set
+ // fakecgo is built with race detector code. This is not
+ // good since this code is pretending to be C. The go:norace
+ // pragma is not enough, since it only applies to the native
+ // ABIInternal function. The ABIO wrapper (which is necessary,
+ // since all references to text symbols from assembly will use it)
+ // does not inherit the go:norace pragma, so it will still be
+ // instrumented by the race detector.
+ //
+ // To circumvent this issue, using closure calls in the
+ // assembly, which forces the compiler to use the ABIInternal
+ // native implementation (which has go:norace) instead.
+ threadentry_call = threadentry
+ x_cgo_init_call = x_cgo_init
+ x_cgo_setenv_call = x_cgo_setenv
+ x_cgo_unsetenv_call = x_cgo_unsetenv
+ x_cgo_thread_start_call = x_cgo_thread_start
+)
diff --git a/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/doc.go b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/doc.go
new file mode 100644
index 0000000..e482c12
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/doc.go
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
+
+//go:build !cgo && (darwin || freebsd || linux || netbsd)
+
+// Package fakecgo implements the Cgo runtime (runtime/cgo) entirely in Go.
+// This allows code that calls into C to function properly when CGO_ENABLED=0.
+//
+// # Goals
+//
+// fakecgo attempts to replicate the same naming structure as in the runtime.
+// For example, functions that have the prefix "gcc_*" are named "go_*".
+// This makes it easier to port other GOOSs and GOARCHs as well as to keep
+// it in sync with runtime/cgo.
+//
+// # Support
+//
+// Currently, fakecgo only supports macOS on amd64 & arm64. It also cannot
+// be used with -buildmode=c-archive because that requires special initialization
+// that fakecgo does not implement at the moment.
+//
+// # Usage
+//
+// Using fakecgo is easy just import _ "github.com/ebitengine/purego" and then
+// set the environment variable CGO_ENABLED=0.
+// The recommended usage for fakecgo is to prefer using runtime/cgo if possible
+// but if cross-compiling or fast build times are important fakecgo is available.
+// Purego will pick which ever Cgo runtime is available and prefer the one that
+// comes with Go (runtime/cgo).
+package fakecgo
+
+//go:generate go run gen.go
diff --git a/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/fakecgo.go b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/fakecgo.go
new file mode 100644
index 0000000..384dab2
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/fakecgo.go
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2025 The Ebitengine Authors
+
+//go:build !cgo && (darwin || freebsd || linux || netbsd)
+
+package fakecgo
+
+import _ "unsafe"
+
+// setg_trampoline calls setg with the G provided
+func setg_trampoline(setg uintptr, G uintptr)
+
+// call5 takes fn the C function and 5 arguments and calls the function with those arguments
+func call5(fn, a1, a2, a3, a4, a5 uintptr) uintptr
diff --git a/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/freebsd.go b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/freebsd.go
new file mode 100644
index 0000000..bb73a70
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/freebsd.go
@@ -0,0 +1,27 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build freebsd && !cgo
+
+package fakecgo
+
+import _ "unsafe" // for go:linkname
+
+// Supply environ and __progname, because we don't
+// link against the standard FreeBSD crt0.o and the
+// libc dynamic library needs them.
+
+// Note: when building with cross-compiling or CGO_ENABLED=0, add
+// the following argument to `go` so that these symbols are defined by
+// making fakecgo the Cgo.
+// -gcflags="github.com/ebitengine/purego/internal/fakecgo=-std"
+
+//go:linkname _environ environ
+//go:linkname _progname __progname
+
+//go:cgo_export_dynamic environ
+//go:cgo_export_dynamic __progname
+
+var _environ uintptr
+var _progname uintptr
diff --git a/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/go_darwin.go b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/go_darwin.go
new file mode 100644
index 0000000..d0868f0
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/go_darwin.go
@@ -0,0 +1,88 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build !cgo
+
+package fakecgo
+
+import "unsafe"
+
+//go:nosplit
+//go:norace
+func _cgo_sys_thread_start(ts *ThreadStart) {
+ var attr pthread_attr_t
+ var ign, oset sigset_t
+ var p pthread_t
+ var size size_t
+ var err int
+
+ sigfillset(&ign)
+ pthread_sigmask(SIG_SETMASK, &ign, &oset)
+
+ size = pthread_get_stacksize_np(pthread_self())
+ pthread_attr_init(&attr)
+ pthread_attr_setstacksize(&attr, size)
+ // Leave stacklo=0 and set stackhi=size; mstart will do the rest.
+ ts.g.stackhi = uintptr(size)
+
+ err = _cgo_try_pthread_create(&p, &attr, unsafe.Pointer(threadentry_trampolineABI0), ts)
+
+ pthread_sigmask(SIG_SETMASK, &oset, nil)
+
+ if err != 0 {
+ print("fakecgo: pthread_create failed: ")
+ println(err)
+ abort()
+ }
+}
+
+// threadentry_trampolineABI0 maps the C ABI to Go ABI then calls the Go function
+//
+//go:linkname x_threadentry_trampoline threadentry_trampoline
+var x_threadentry_trampoline byte
+var threadentry_trampolineABI0 = &x_threadentry_trampoline
+
+//go:nosplit
+//go:norace
+func threadentry(v unsafe.Pointer) unsafe.Pointer {
+ ts := *(*ThreadStart)(v)
+ free(v)
+
+ // TODO: support ios
+ //#if TARGET_OS_IPHONE
+ // darwin_arm_init_thread_exception_port();
+ //#endif
+ setg_trampoline(setg_func, uintptr(unsafe.Pointer(ts.g)))
+
+ // faking funcs in go is a bit a... involved - but the following works :)
+ fn := uintptr(unsafe.Pointer(&ts.fn))
+ (*(*func())(unsafe.Pointer(&fn)))()
+
+ return nil
+}
+
+// here we will store a pointer to the provided setg func
+var setg_func uintptr
+
+// x_cgo_init(G *g, void (*setg)(void*)) (runtime/cgo/gcc_linux_amd64.c)
+// This get's called during startup, adjusts stacklo, and provides a pointer to setg_gcc for us
+// Additionally, if we set _cgo_init to non-null, go won't do it's own TLS setup
+// This function can't be go:systemstack since go is not in a state where the systemcheck would work.
+//
+//go:nosplit
+//go:norace
+func x_cgo_init(g *G, setg uintptr) {
+ var size size_t
+
+ setg_func = setg
+ size = pthread_get_stacksize_np(pthread_self())
+ g.stacklo = uintptr(unsafe.Add(unsafe.Pointer(&size), -size+4096))
+
+ //TODO: support ios
+ //#if TARGET_OS_IPHONE
+ // darwin_arm_init_mach_exception_handler();
+ // darwin_arm_init_thread_exception_port();
+ // init_working_dir();
+ //#endif
+}
diff --git a/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/go_freebsd.go b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/go_freebsd.go
new file mode 100644
index 0000000..a3ba6bc
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/go_freebsd.go
@@ -0,0 +1,100 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build !cgo
+
+package fakecgo
+
+import "unsafe"
+
+//go:nosplit
+func _cgo_sys_thread_start(ts *ThreadStart) {
+ var attr pthread_attr_t
+ var ign, oset sigset_t
+ var p pthread_t
+ var size size_t
+ var err int
+
+ // fprintf(stderr, "runtime/cgo: _cgo_sys_thread_start: fn=%p, g=%p\n", ts->fn, ts->g); // debug
+ sigfillset(&ign)
+ pthread_sigmask(SIG_SETMASK, &ign, &oset)
+
+ pthread_attr_init(&attr)
+ pthread_attr_getstacksize(&attr, &size)
+ // Leave stacklo=0 and set stackhi=size; mstart will do the rest.
+ ts.g.stackhi = uintptr(size)
+
+ err = _cgo_try_pthread_create(&p, &attr, unsafe.Pointer(threadentry_trampolineABI0), ts)
+
+ pthread_sigmask(SIG_SETMASK, &oset, nil)
+
+ if err != 0 {
+ print("fakecgo: pthread_create failed: ")
+ println(err)
+ abort()
+ }
+}
+
+// threadentry_trampolineABI0 maps the C ABI to Go ABI then calls the Go function
+//
+//go:linkname x_threadentry_trampoline threadentry_trampoline
+var x_threadentry_trampoline byte
+var threadentry_trampolineABI0 = &x_threadentry_trampoline
+
+//go:nosplit
+func threadentry(v unsafe.Pointer) unsafe.Pointer {
+ ts := *(*ThreadStart)(v)
+ free(v)
+
+ setg_trampoline(setg_func, uintptr(unsafe.Pointer(ts.g)))
+
+ // faking funcs in go is a bit a... involved - but the following works :)
+ fn := uintptr(unsafe.Pointer(&ts.fn))
+ (*(*func())(unsafe.Pointer(&fn)))()
+
+ return nil
+}
+
+// here we will store a pointer to the provided setg func
+var setg_func uintptr
+
+// x_cgo_init(G *g, void (*setg)(void*)) (runtime/cgo/gcc_linux_amd64.c)
+// This get's called during startup, adjusts stacklo, and provides a pointer to setg_gcc for us
+// Additionally, if we set _cgo_init to non-null, go won't do it's own TLS setup
+// This function can't be go:systemstack since go is not in a state where the systemcheck would work.
+//
+//go:nosplit
+func x_cgo_init(g *G, setg uintptr) {
+ var size size_t
+ var attr *pthread_attr_t
+
+ /* The memory sanitizer distributed with versions of clang
+ before 3.8 has a bug: if you call mmap before malloc, mmap
+ may return an address that is later overwritten by the msan
+ library. Avoid this problem by forcing a call to malloc
+ here, before we ever call malloc.
+
+ This is only required for the memory sanitizer, so it's
+ unfortunate that we always run it. It should be possible
+ to remove this when we no longer care about versions of
+ clang before 3.8. The test for this is
+ misc/cgo/testsanitizers.
+
+ GCC works hard to eliminate a seemingly unnecessary call to
+ malloc, so we actually use the memory we allocate. */
+
+ setg_func = setg
+ attr = (*pthread_attr_t)(malloc(unsafe.Sizeof(*attr)))
+ if attr == nil {
+ println("fakecgo: malloc failed")
+ abort()
+ }
+ pthread_attr_init(attr)
+ pthread_attr_getstacksize(attr, &size)
+ // runtime/cgo uses __builtin_frame_address(0) instead of `uintptr(unsafe.Pointer(&size))`
+ // but this should be OK since we are taking the address of the first variable in this function.
+ g.stacklo = uintptr(unsafe.Pointer(&size)) - uintptr(size) + 4096
+ pthread_attr_destroy(attr)
+ free(unsafe.Pointer(attr))
+}
diff --git a/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/go_libinit.go b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/go_libinit.go
new file mode 100644
index 0000000..0c46306
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/go_libinit.go
@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
+
+//go:build !cgo && (darwin || freebsd || linux || netbsd)
+
+package fakecgo
+
+import (
+ "syscall"
+ "unsafe"
+)
+
+var (
+ pthread_g pthread_key_t
+
+ runtime_init_cond = PTHREAD_COND_INITIALIZER
+ runtime_init_mu = PTHREAD_MUTEX_INITIALIZER
+ runtime_init_done int
+)
+
+//go:nosplit
+//go:norace
+func x_cgo_notify_runtime_init_done() {
+ pthread_mutex_lock(&runtime_init_mu)
+ runtime_init_done = 1
+ pthread_cond_broadcast(&runtime_init_cond)
+ pthread_mutex_unlock(&runtime_init_mu)
+}
+
+// Store the g into a thread-specific value associated with the pthread key pthread_g.
+// And pthread_key_destructor will dropm when the thread is exiting.
+//
+//go:norace
+func x_cgo_bindm(g unsafe.Pointer) {
+ // We assume this will always succeed, otherwise, there might be extra M leaking,
+ // when a C thread exits after a cgo call.
+ // We only invoke this function once per thread in runtime.needAndBindM,
+ // and the next calls just reuse the bound m.
+ pthread_setspecific(pthread_g, g)
+}
+
+// _cgo_try_pthread_create retries pthread_create if it fails with
+// EAGAIN.
+//
+//go:nosplit
+//go:norace
+func _cgo_try_pthread_create(thread *pthread_t, attr *pthread_attr_t, pfn unsafe.Pointer, arg *ThreadStart) int {
+ var ts syscall.Timespec
+ // tries needs to be the same type as syscall.Timespec.Nsec
+ // but the fields are int32 on 32bit and int64 on 64bit.
+ // tries is assigned to syscall.Timespec.Nsec in order to match its type.
+ tries := ts.Nsec
+ var err int
+
+ for tries = 0; tries < 20; tries++ {
+ // inlined this call because it ran out of stack when inlining was disabled
+ err = int(call5(pthread_createABI0, uintptr(unsafe.Pointer(thread)), uintptr(unsafe.Pointer(attr)), uintptr(pfn), uintptr(unsafe.Pointer(arg)), 0))
+ if err == 0 {
+ // inlined this call because it ran out of stack when inlining was disabled
+ call5(pthread_detachABI0, uintptr(*thread), 0, 0, 0, 0)
+ return 0
+ }
+ if err != int(syscall.EAGAIN) {
+ return err
+ }
+ ts.Sec = 0
+ ts.Nsec = (tries + 1) * 1000 * 1000 // Milliseconds.
+ // inlined this call because it ran out of stack when inlining was disabled
+ call5(nanosleepABI0, uintptr(unsafe.Pointer(&ts)), 0, 0, 0, 0)
+ }
+ return int(syscall.EAGAIN)
+}
diff --git a/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/go_linux.go b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/go_linux.go
new file mode 100644
index 0000000..9f380c1
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/go_linux.go
@@ -0,0 +1,100 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build !cgo
+
+package fakecgo
+
+import "unsafe"
+
+//go:nosplit
+func _cgo_sys_thread_start(ts *ThreadStart) {
+ var attr pthread_attr_t
+ var ign, oset sigset_t
+ var p pthread_t
+ var size size_t
+ var err int
+
+ //fprintf(stderr, "runtime/cgo: _cgo_sys_thread_start: fn=%p, g=%p\n", ts->fn, ts->g); // debug
+ sigfillset(&ign)
+ pthread_sigmask(SIG_SETMASK, &ign, &oset)
+
+ pthread_attr_init(&attr)
+ pthread_attr_getstacksize(&attr, &size)
+ // Leave stacklo=0 and set stackhi=size; mstart will do the rest.
+ ts.g.stackhi = uintptr(size)
+
+ err = _cgo_try_pthread_create(&p, &attr, unsafe.Pointer(threadentry_trampolineABI0), ts)
+
+ pthread_sigmask(SIG_SETMASK, &oset, nil)
+
+ if err != 0 {
+ print("fakecgo: pthread_create failed: ")
+ println(err)
+ abort()
+ }
+}
+
+// threadentry_trampolineABI0 maps the C ABI to Go ABI then calls the Go function
+//
+//go:linkname x_threadentry_trampoline threadentry_trampoline
+var x_threadentry_trampoline byte
+var threadentry_trampolineABI0 = &x_threadentry_trampoline
+
+//go:nosplit
+func threadentry(v unsafe.Pointer) unsafe.Pointer {
+ ts := *(*ThreadStart)(v)
+ free(v)
+
+ setg_trampoline(setg_func, uintptr(unsafe.Pointer(ts.g)))
+
+ // faking funcs in go is a bit a... involved - but the following works :)
+ fn := uintptr(unsafe.Pointer(&ts.fn))
+ (*(*func())(unsafe.Pointer(&fn)))()
+
+ return nil
+}
+
+// here we will store a pointer to the provided setg func
+var setg_func uintptr
+
+// x_cgo_init(G *g, void (*setg)(void*)) (runtime/cgo/gcc_linux_amd64.c)
+// This get's called during startup, adjusts stacklo, and provides a pointer to setg_gcc for us
+// Additionally, if we set _cgo_init to non-null, go won't do it's own TLS setup
+// This function can't be go:systemstack since go is not in a state where the systemcheck would work.
+//
+//go:nosplit
+func x_cgo_init(g *G, setg uintptr) {
+ var size size_t
+ var attr *pthread_attr_t
+
+ /* The memory sanitizer distributed with versions of clang
+ before 3.8 has a bug: if you call mmap before malloc, mmap
+ may return an address that is later overwritten by the msan
+ library. Avoid this problem by forcing a call to malloc
+ here, before we ever call malloc.
+
+ This is only required for the memory sanitizer, so it's
+ unfortunate that we always run it. It should be possible
+ to remove this when we no longer care about versions of
+ clang before 3.8. The test for this is
+ misc/cgo/testsanitizers.
+
+ GCC works hard to eliminate a seemingly unnecessary call to
+ malloc, so we actually use the memory we allocate. */
+
+ setg_func = setg
+ attr = (*pthread_attr_t)(malloc(unsafe.Sizeof(*attr)))
+ if attr == nil {
+ println("fakecgo: malloc failed")
+ abort()
+ }
+ pthread_attr_init(attr)
+ pthread_attr_getstacksize(attr, &size)
+ // runtime/cgo uses __builtin_frame_address(0) instead of `uintptr(unsafe.Pointer(&size))`
+ // but this should be OK since we are taking the address of the first variable in this function.
+ g.stacklo = uintptr(unsafe.Pointer(&size)) - uintptr(size) + 4096
+ pthread_attr_destroy(attr)
+ free(unsafe.Pointer(attr))
+}
diff --git a/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/go_netbsd.go b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/go_netbsd.go
new file mode 100644
index 0000000..935a334
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/go_netbsd.go
@@ -0,0 +1,106 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build !cgo && (amd64 || arm64)
+
+package fakecgo
+
+import "unsafe"
+
+//go:nosplit
+func _cgo_sys_thread_start(ts *ThreadStart) {
+ var attr pthread_attr_t
+ var ign, oset sigset_t
+ var p pthread_t
+ var size size_t
+ var err int
+
+ // fprintf(stderr, "runtime/cgo: _cgo_sys_thread_start: fn=%p, g=%p\n", ts->fn, ts->g); // debug
+ sigfillset(&ign)
+ pthread_sigmask(SIG_SETMASK, &ign, &oset)
+
+ pthread_attr_init(&attr)
+ pthread_attr_getstacksize(&attr, &size)
+ // Leave stacklo=0 and set stackhi=size; mstart will do the rest.
+ ts.g.stackhi = uintptr(size)
+
+ err = _cgo_try_pthread_create(&p, &attr, unsafe.Pointer(threadentry_trampolineABI0), ts)
+
+ pthread_sigmask(SIG_SETMASK, &oset, nil)
+
+ if err != 0 {
+ print("fakecgo: pthread_create failed: ")
+ println(err)
+ abort()
+ }
+}
+
+// threadentry_trampolineABI0 maps the C ABI to Go ABI then calls the Go function
+//
+//go:linkname x_threadentry_trampoline threadentry_trampoline
+var x_threadentry_trampoline byte
+var threadentry_trampolineABI0 = &x_threadentry_trampoline
+
+//go:nosplit
+func threadentry(v unsafe.Pointer) unsafe.Pointer {
+ var ss stack_t
+ ts := *(*ThreadStart)(v)
+ free(v)
+
+ // On NetBSD, a new thread inherits the signal stack of the
+ // creating thread. That confuses minit, so we remove that
+ // signal stack here before calling the regular mstart. It's
+ // a bit baroque to remove a signal stack here only to add one
+ // in minit, but it's a simple change that keeps NetBSD
+ // working like other OS's. At this point all signals are
+ // blocked, so there is no race.
+ ss.ss_flags = SS_DISABLE
+ sigaltstack(&ss, nil)
+
+ setg_trampoline(setg_func, uintptr(unsafe.Pointer(ts.g)))
+
+ // faking funcs in go is a bit a... involved - but the following works :)
+ fn := uintptr(unsafe.Pointer(&ts.fn))
+ (*(*func())(unsafe.Pointer(&fn)))()
+
+ return nil
+}
+
+// here we will store a pointer to the provided setg func
+var setg_func uintptr
+
+//go:nosplit
+func x_cgo_init(g *G, setg uintptr) {
+ var size size_t
+ var attr *pthread_attr_t
+
+ /* The memory sanitizer distributed with versions of clang
+ before 3.8 has a bug: if you call mmap before malloc, mmap
+ may return an address that is later overwritten by the msan
+ library. Avoid this problem by forcing a call to malloc
+ here, before we ever call malloc.
+
+ This is only required for the memory sanitizer, so it's
+ unfortunate that we always run it. It should be possible
+ to remove this when we no longer care about versions of
+ clang before 3.8. The test for this is
+ misc/cgo/testsanitizers.
+
+ GCC works hard to eliminate a seemingly unnecessary call to
+ malloc, so we actually use the memory we allocate. */
+
+ setg_func = setg
+ attr = (*pthread_attr_t)(malloc(unsafe.Sizeof(*attr)))
+ if attr == nil {
+ println("fakecgo: malloc failed")
+ abort()
+ }
+ pthread_attr_init(attr)
+ pthread_attr_getstacksize(attr, &size)
+ // runtime/cgo uses __builtin_frame_address(0) instead of `uintptr(unsafe.Pointer(&size))`
+ // but this should be OK since we are taking the address of the first variable in this function.
+ g.stacklo = uintptr(unsafe.Pointer(&size)) - uintptr(size) + 4096
+ pthread_attr_destroy(attr)
+ free(unsafe.Pointer(attr))
+}
diff --git a/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/go_setenv.go b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/go_setenv.go
new file mode 100644
index 0000000..dfc6629
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/go_setenv.go
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
+
+//go:build !cgo && (darwin || freebsd || linux || netbsd)
+
+package fakecgo
+
+//go:nosplit
+//go:norace
+func x_cgo_setenv(arg *[2]*byte) {
+ setenv(arg[0], arg[1], 1)
+}
+
+//go:nosplit
+//go:norace
+func x_cgo_unsetenv(arg *[1]*byte) {
+ unsetenv(arg[0])
+}
diff --git a/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/go_util.go b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/go_util.go
new file mode 100644
index 0000000..ee993ba
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/go_util.go
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
+
+//go:build !cgo && (darwin || freebsd || linux || netbsd)
+
+package fakecgo
+
+import "unsafe"
+
+// _cgo_thread_start is split into three parts in cgo since only one part is system dependent (keep it here for easier handling)
+
+// _cgo_thread_start(ThreadStart *arg) (runtime/cgo/gcc_util.c)
+// This get's called instead of the go code for creating new threads
+// -> pthread_* stuff is used, so threads are setup correctly for C
+// If this is missing, TLS is only setup correctly on thread 1!
+// This function should be go:systemstack instead of go:nosplit (but that requires runtime)
+//
+//go:nosplit
+//go:norace
+func x_cgo_thread_start(arg *ThreadStart) {
+ var ts *ThreadStart
+ // Make our own copy that can persist after we return.
+ // _cgo_tsan_acquire();
+ ts = (*ThreadStart)(malloc(unsafe.Sizeof(*ts)))
+ // _cgo_tsan_release();
+ if ts == nil {
+ println("fakecgo: out of memory in thread_start")
+ abort()
+ }
+ // *ts = *arg would cause a writebarrier so copy using slices
+ const ptrSize = unsafe.Sizeof(uintptr(0))
+ s1 := unsafe.Slice((*uintptr)(unsafe.Pointer(ts)), unsafe.Sizeof(*ts)/ptrSize)
+ s2 := unsafe.Slice((*uintptr)(unsafe.Pointer(arg)), unsafe.Sizeof(*arg)/ptrSize)
+ for i := range s2 {
+ s1[i] = s2[i]
+ }
+ _cgo_sys_thread_start(ts) // OS-dependent half
+}
diff --git a/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/iscgo.go b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/iscgo.go
new file mode 100644
index 0000000..12e5214
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/iscgo.go
@@ -0,0 +1,19 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build !cgo && (darwin || freebsd || linux || netbsd)
+
+// The runtime package contains an uninitialized definition
+// for runtime·iscgo. Override it to tell the runtime we're here.
+// There are various function pointers that should be set too,
+// but those depend on dynamic linker magic to get initialized
+// correctly, and sometimes they break. This variable is a
+// backup: it depends only on old C style static linking rules.
+
+package fakecgo
+
+import _ "unsafe" // for go:linkname
+
+//go:linkname _iscgo runtime.iscgo
+var _iscgo bool = true
diff --git a/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo.go b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo.go
new file mode 100644
index 0000000..94fd8be
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo.go
@@ -0,0 +1,39 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
+
+//go:build !cgo && (darwin || freebsd || linux || netbsd)
+
+package fakecgo
+
+type (
+ size_t uintptr
+ // Sources:
+ // Darwin (32 bytes) - https://github.com/apple/darwin-xnu/blob/2ff845c2e033bd0ff64b5b6aa6063a1f8f65aa32/bsd/sys/_types.h#L74
+ // FreeBSD (32 bytes) - https://github.com/DoctorWkt/xv6-freebsd/blob/d2a294c2a984baed27676068b15ed9a29b06ab6f/include/signal.h#L98C9-L98C21
+ // Linux (128 bytes) - https://github.com/torvalds/linux/blob/ab75170520d4964f3acf8bb1f91d34cbc650688e/arch/x86/include/asm/signal.h#L25
+ sigset_t [128]byte
+ pthread_attr_t [64]byte
+ pthread_t int
+ pthread_key_t uint64
+)
+
+// for pthread_sigmask:
+
+type sighow int32
+
+const (
+ SIG_BLOCK sighow = 0
+ SIG_UNBLOCK sighow = 1
+ SIG_SETMASK sighow = 2
+)
+
+type G struct {
+ stacklo uintptr
+ stackhi uintptr
+}
+
+type ThreadStart struct {
+ g *G
+ tls *uintptr
+ fn uintptr
+}
diff --git a/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo_darwin.go b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo_darwin.go
new file mode 100644
index 0000000..ecdcb2e
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo_darwin.go
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
+
+//go:build !cgo
+
+package fakecgo
+
+type (
+ pthread_mutex_t struct {
+ sig int64
+ opaque [56]byte
+ }
+ pthread_cond_t struct {
+ sig int64
+ opaque [40]byte
+ }
+)
+
+var (
+ PTHREAD_COND_INITIALIZER = pthread_cond_t{sig: 0x3CB0B1BB}
+ PTHREAD_MUTEX_INITIALIZER = pthread_mutex_t{sig: 0x32AAABA7}
+)
+
+type stack_t struct {
+ /* not implemented */
+}
diff --git a/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo_freebsd.go b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo_freebsd.go
new file mode 100644
index 0000000..4bfb70c
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo_freebsd.go
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
+
+//go:build !cgo
+
+package fakecgo
+
+type (
+ pthread_cond_t uintptr
+ pthread_mutex_t uintptr
+)
+
+var (
+ PTHREAD_COND_INITIALIZER = pthread_cond_t(0)
+ PTHREAD_MUTEX_INITIALIZER = pthread_mutex_t(0)
+)
+
+type stack_t struct {
+ /* not implemented */
+}
diff --git a/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo_linux.go b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo_linux.go
new file mode 100644
index 0000000..b08a44a
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo_linux.go
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
+
+//go:build !cgo
+
+package fakecgo
+
+type (
+ pthread_cond_t [48]byte
+ pthread_mutex_t [48]byte
+)
+
+var (
+ PTHREAD_COND_INITIALIZER = pthread_cond_t{}
+ PTHREAD_MUTEX_INITIALIZER = pthread_mutex_t{}
+)
+
+type stack_t struct {
+ /* not implemented */
+}
diff --git a/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo_netbsd.go b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo_netbsd.go
new file mode 100644
index 0000000..650f695
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/libcgo_netbsd.go
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2025 The Ebitengine Authors
+
+//go:build !cgo
+
+package fakecgo
+
+type (
+ pthread_cond_t uintptr
+ pthread_mutex_t uintptr
+)
+
+var (
+ PTHREAD_COND_INITIALIZER = pthread_cond_t(0)
+ PTHREAD_MUTEX_INITIALIZER = pthread_mutex_t(0)
+)
+
+// Source: https://github.com/NetBSD/src/blob/613e27c65223fd2283b6ed679da1197e12f50e27/sys/compat/linux/arch/m68k/linux_signal.h#L133
+type stack_t struct {
+ ss_sp uintptr
+ ss_flags int32
+ ss_size uintptr
+}
+
+// Source: https://github.com/NetBSD/src/blob/613e27c65223fd2283b6ed679da1197e12f50e27/sys/sys/signal.h#L261
+const SS_DISABLE = 0x004
diff --git a/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/netbsd.go b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/netbsd.go
new file mode 100644
index 0000000..2d49981
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/netbsd.go
@@ -0,0 +1,23 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build netbsd
+
+package fakecgo
+
+import _ "unsafe" // for go:linkname
+
+// Supply environ and __progname, because we don't
+// link against the standard NetBSD crt0.o and the
+// libc dynamic library needs them.
+
+//go:linkname _environ environ
+//go:linkname _progname __progname
+//go:linkname ___ps_strings __ps_strings
+
+var (
+ _environ uintptr
+ _progname uintptr
+ ___ps_strings uintptr
+)
diff --git a/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/setenv.go b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/setenv.go
new file mode 100644
index 0000000..82308b8
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/setenv.go
@@ -0,0 +1,19 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build !cgo && (darwin || freebsd || linux || netbsd)
+
+package fakecgo
+
+import _ "unsafe" // for go:linkname
+
+//go:linkname x_cgo_setenv_trampoline x_cgo_setenv_trampoline
+//go:linkname _cgo_setenv runtime._cgo_setenv
+var x_cgo_setenv_trampoline byte
+var _cgo_setenv = &x_cgo_setenv_trampoline
+
+//go:linkname x_cgo_unsetenv_trampoline x_cgo_unsetenv_trampoline
+//go:linkname _cgo_unsetenv runtime._cgo_unsetenv
+var x_cgo_unsetenv_trampoline byte
+var _cgo_unsetenv = &x_cgo_unsetenv_trampoline
diff --git a/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_386.s b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_386.s
new file mode 100644
index 0000000..cd3492e
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_386.s
@@ -0,0 +1,107 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2026 The Ebitengine Authors
+
+//go:build !cgo && (freebsd || linux)
+
+#include "textflag.h"
+#include "go_asm.h"
+
+// These trampolines map the gcc ABI to Go ABI0 and then call into the Go equivalent functions.
+// On i386, both GCC and Go use stack-based calling conventions.
+//
+// When C calls a function, the stack looks like:
+// 0(SP) = return address
+// 4(SP) = arg1
+// 8(SP) = arg2
+// ...
+//
+// When we declare a Go function with frame size $N-0, Go's prologue
+// effectively does SUB $N, SP, so the C arguments shift up by N bytes:
+// N+0(SP) = return address
+// N+4(SP) = arg1
+// N+8(SP) = arg2
+//
+// Go ABI0 on 386 expects arguments starting at 0(FP) which equals N+4(SP)
+// after the prologue (where N is the local frame size).
+
+TEXT x_cgo_init_trampoline(SB), NOSPLIT, $8-0
+ // C args at 12(SP) and 16(SP) after frame setup (8 bytes local + 4 bytes ret addr)
+ // Go function expects args at 0(SP) and 4(SP) in local frame
+ MOVL 12(SP), AX // first C arg
+ MOVL 16(SP), BX // second C arg
+ MOVL AX, 0(SP) // Go arg 1
+ MOVL BX, 4(SP) // Go arg 2
+ MOVL ·x_cgo_init_call(SB), CX
+ MOVL (CX), CX
+ CALL CX
+ RET
+
+TEXT x_cgo_thread_start_trampoline(SB), NOSPLIT, $4-0
+ // C args at 8(SP) after frame setup (4 bytes local + 4 bytes ret addr)
+ MOVL 8(SP), AX // first C arg
+ MOVL AX, 0(SP) // Go arg 1
+ MOVL ·x_cgo_thread_start_call(SB), CX
+ MOVL (CX), CX
+ CALL CX
+ RET
+
+TEXT x_cgo_setenv_trampoline(SB), NOSPLIT, $4-0
+ MOVL 8(SP), AX // first C arg
+ MOVL AX, 0(SP) // Go arg 1
+ MOVL ·x_cgo_setenv_call(SB), CX
+ MOVL (CX), CX
+ CALL CX
+ RET
+
+TEXT x_cgo_unsetenv_trampoline(SB), NOSPLIT, $4-0
+ MOVL 8(SP), AX // first C arg
+ MOVL AX, 0(SP) // Go arg 1
+ MOVL ·x_cgo_unsetenv_call(SB), CX
+ MOVL (CX), CX
+ CALL CX
+ RET
+
+TEXT x_cgo_notify_runtime_init_done_trampoline(SB), NOSPLIT, $0-0
+ CALL ·x_cgo_notify_runtime_init_done(SB)
+ RET
+
+TEXT x_cgo_bindm_trampoline(SB), NOSPLIT, $0
+ CALL ·x_cgo_bindm(SB)
+ RET
+
+// func setg_trampoline(setg uintptr, g uintptr)
+// This is called from Go, so args are at normal FP positions
+TEXT ·setg_trampoline(SB), NOSPLIT, $4-8
+ MOVL g+4(FP), AX
+ MOVL setg+0(FP), BX
+
+ // setg expects g in 0(SP)
+ MOVL AX, 0(SP)
+ CALL BX
+ RET
+
+TEXT threadentry_trampoline(SB), NOSPLIT, $4-0
+ MOVL 8(SP), AX // first C arg
+ MOVL AX, 0(SP) // Go arg 1
+ MOVL ·threadentry_call(SB), CX
+ MOVL (CX), CX
+ CALL CX
+ RET
+
+TEXT ·call5(SB), NOSPLIT, $20-28
+ MOVL fn+0(FP), AX
+ MOVL a1+4(FP), BX
+ MOVL a2+8(FP), CX
+ MOVL a3+12(FP), DX
+ MOVL a4+16(FP), SI
+ MOVL a5+20(FP), DI
+
+ // Place arguments on local stack frame for C calling convention
+ MOVL BX, 0(SP) // a1
+ MOVL CX, 4(SP) // a2
+ MOVL DX, 8(SP) // a3
+ MOVL SI, 12(SP) // a4
+ MOVL DI, 16(SP) // a5
+ CALL AX
+ MOVL AX, r1+24(FP)
+ RET
diff --git a/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_amd64.s b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_amd64.s
new file mode 100644
index 0000000..e4e4c75
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_amd64.s
@@ -0,0 +1,107 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
+
+//go:build !cgo && (darwin || linux || freebsd)
+
+/*
+trampoline for emulating required C functions for cgo in go (see cgo.go)
+(we convert cdecl calling convention to go and vice-versa)
+
+C Calling convention cdecl used here (we only need integer args):
+1. arg: DI
+2. arg: SI
+3. arg: DX
+4. arg: CX
+5. arg: R8
+6. arg: R9
+We don't need floats with these functions -> AX=0
+return value will be in AX
+temporary register is R11
+*/
+#include "textflag.h"
+#include "go_asm.h"
+#include "abi_amd64.h"
+
+// these trampolines map the gcc ABI to Go ABI and then calls into the Go equivalent functions.
+
+TEXT x_cgo_init_trampoline(SB), NOSPLIT, $16
+ MOVQ DI, AX
+ MOVQ SI, BX
+ MOVQ ·x_cgo_init_call(SB), R11
+ MOVQ (R11), R11
+ CALL R11
+ RET
+
+TEXT x_cgo_thread_start_trampoline(SB), NOSPLIT, $8
+ MOVQ DI, AX
+ MOVQ ·x_cgo_thread_start_call(SB), R11
+ MOVQ (R11), R11
+ CALL R11
+ RET
+
+TEXT x_cgo_setenv_trampoline(SB), NOSPLIT, $8
+ MOVQ DI, AX
+ MOVQ ·x_cgo_setenv_call(SB), R11
+ MOVQ (R11), R11
+ CALL R11
+ RET
+
+TEXT x_cgo_unsetenv_trampoline(SB), NOSPLIT, $8
+ MOVQ DI, AX
+ MOVQ ·x_cgo_unsetenv_call(SB), R11
+ MOVQ (R11), R11
+ CALL R11
+ RET
+
+TEXT x_cgo_notify_runtime_init_done_trampoline(SB), NOSPLIT, $0
+ JMP ·x_cgo_notify_runtime_init_done(SB)
+
+TEXT x_cgo_bindm_trampoline(SB), NOSPLIT, $0
+ JMP ·x_cgo_bindm(SB)
+
+// func setg_trampoline(setg uintptr, g uintptr)
+TEXT ·setg_trampoline(SB), NOSPLIT, $0-16
+ MOVQ G+8(FP), DI
+ MOVQ setg+0(FP), R11
+ XORL AX, AX
+ CALL R11
+ RET
+
+TEXT threadentry_trampoline(SB), NOSPLIT, $0
+ // See crosscall2.
+ PUSH_REGS_HOST_TO_ABI0()
+
+ // X15 is designated by Go as a fixed zero register.
+ // Calling directly into ABIInternal, ensure it is zero.
+ PXOR X15, X15
+
+ MOVQ DI, AX
+ MOVQ ·threadentry_call(SB), R11
+ MOVQ (R11), R11
+ CALL R11
+
+ POP_REGS_HOST_TO_ABI0()
+ RET
+
+TEXT ·call5(SB), NOSPLIT, $0-56
+ MOVQ fn+0(FP), R11
+ MOVQ a1+8(FP), DI
+ MOVQ a2+16(FP), SI
+ MOVQ a3+24(FP), DX
+ MOVQ a4+32(FP), CX
+ MOVQ a5+40(FP), R8
+
+ XORL AX, AX // no floats
+
+ PUSHQ BP // save BP
+ MOVQ SP, BP // save SP inside BP bc BP is callee-saved
+ SUBQ $16, SP // allocate space for alignment
+ ANDQ $-16, SP // align on 16 bytes for SSE
+
+ CALL R11
+
+ MOVQ BP, SP // get SP back
+ POPQ BP // restore BP
+
+ MOVQ AX, ret+48(FP)
+ RET
diff --git a/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_arm.s b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_arm.s
new file mode 100644
index 0000000..00b3177
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_arm.s
@@ -0,0 +1,81 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2026 The Ebitengine Authors
+
+//go:build !cgo && (freebsd || linux)
+
+#include "textflag.h"
+#include "go_asm.h"
+
+// These trampolines map the gcc ABI to Go ABI0 and then call into the Go equivalent functions.
+// On ARM32, Go ABI0 uses stack-based calling convention.
+// Arguments are placed on the stack starting at 4(SP) after the prologue.
+
+TEXT x_cgo_init_trampoline(SB), NOSPLIT, $8-0
+ MOVW R0, 4(R13)
+ MOVW R1, 8(R13)
+ MOVW ·x_cgo_init_call(SB), R12
+ MOVW (R12), R12
+ CALL (R12)
+ RET
+
+TEXT x_cgo_thread_start_trampoline(SB), NOSPLIT, $8-0
+ MOVW R0, 4(R13)
+ MOVW ·x_cgo_thread_start_call(SB), R12
+ MOVW (R12), R12
+ CALL (R12)
+ RET
+
+TEXT x_cgo_setenv_trampoline(SB), NOSPLIT, $8-0
+ MOVW R0, 4(R13)
+ MOVW ·x_cgo_setenv_call(SB), R12
+ MOVW (R12), R12
+ CALL (R12)
+ RET
+
+TEXT x_cgo_unsetenv_trampoline(SB), NOSPLIT, $8-0
+ MOVW R0, 4(R13)
+ MOVW ·x_cgo_unsetenv_call(SB), R12
+ MOVW (R12), R12
+ CALL (R12)
+ RET
+
+TEXT x_cgo_notify_runtime_init_done_trampoline(SB), NOSPLIT, $0-0
+ CALL ·x_cgo_notify_runtime_init_done(SB)
+ RET
+
+TEXT x_cgo_bindm_trampoline(SB), NOSPLIT, $0
+ CALL ·x_cgo_bindm(SB)
+ RET
+
+// func setg_trampoline(setg uintptr, g uintptr)
+TEXT ·setg_trampoline(SB), NOSPLIT, $0-8
+ MOVW G+4(FP), R0
+ MOVW setg+0(FP), R12
+ BL (R12)
+ RET
+
+TEXT threadentry_trampoline(SB), NOSPLIT, $8-0
+ // See crosscall2.
+ MOVW R0, 4(R13)
+ MOVW ·threadentry_call(SB), R12
+ MOVW (R12), R12
+ CALL (R12)
+ RET
+
+TEXT ·call5(SB), NOSPLIT, $8-28
+ MOVW fn+0(FP), R12
+ MOVW a1+4(FP), R0
+ MOVW a2+8(FP), R1
+ MOVW a3+12(FP), R2
+ MOVW a4+16(FP), R3
+ MOVW a5+20(FP), R4
+
+ // Store 5th arg below SP (in local frame area)
+ MOVW R4, arg5-8(SP)
+
+ // Align SP to 8 bytes for call (required by ARM AAPCS)
+ SUB $8, R13
+ CALL (R12)
+ ADD $8, R13
+ MOVW R0, r1+24(FP)
+ RET
diff --git a/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_arm64.s b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_arm64.s
new file mode 100644
index 0000000..dceb1ca
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_arm64.s
@@ -0,0 +1,84 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
+
+//go:build !cgo && (darwin || freebsd || linux)
+
+#include "textflag.h"
+#include "go_asm.h"
+#include "abi_arm64.h"
+
+// These trampolines map the gcc ABI to Go ABIInternal and then calls into the Go equivalent functions.
+// Note that C arguments are passed in R0-R7, which matches Go ABIInternal for the first eight arguments.
+// R9 is used as a temporary register.
+
+TEXT x_cgo_init_trampoline(SB), NOSPLIT, $0-0
+ MOVD ·x_cgo_init_call(SB), R9
+ MOVD (R9), R9
+ CALL R9
+ RET
+
+TEXT x_cgo_thread_start_trampoline(SB), NOSPLIT, $0-0
+ MOVD ·x_cgo_thread_start_call(SB), R9
+ MOVD (R9), R9
+ CALL R9
+ RET
+
+TEXT x_cgo_setenv_trampoline(SB), NOSPLIT, $0-0
+ MOVD ·x_cgo_setenv_call(SB), R9
+ MOVD (R9), R9
+ CALL R9
+ RET
+
+TEXT x_cgo_unsetenv_trampoline(SB), NOSPLIT, $0-0
+ MOVD ·x_cgo_unsetenv_call(SB), R9
+ MOVD (R9), R9
+ CALL R9
+ RET
+
+TEXT x_cgo_notify_runtime_init_done_trampoline(SB), NOSPLIT, $0-0
+ CALL ·x_cgo_notify_runtime_init_done(SB)
+ RET
+
+TEXT x_cgo_bindm_trampoline(SB), NOSPLIT, $0
+ CALL ·x_cgo_bindm(SB)
+ RET
+
+// func setg_trampoline(setg uintptr, g uintptr)
+TEXT ·setg_trampoline(SB), NOSPLIT, $0-16
+ MOVD G+8(FP), R0
+ MOVD setg+0(FP), R9
+ CALL R9
+ RET
+
+TEXT threadentry_trampoline(SB), NOSPLIT, $0-0
+ // See crosscall2.
+ SUB $(8*24), RSP
+ STP (R0, R1), (8*1)(RSP)
+ MOVD R3, (8*3)(RSP)
+
+ SAVE_R19_TO_R28(8*4)
+ SAVE_F8_TO_F15(8*14)
+ STP (R29, R30), (8*22)(RSP)
+
+ MOVD ·threadentry_call(SB), R9
+ MOVD (R9), R9
+ CALL R9
+ MOVD $0, R0 // TODO: get the return value from threadentry
+
+ RESTORE_R19_TO_R28(8*4)
+ RESTORE_F8_TO_F15(8*14)
+ LDP (8*22)(RSP), (R29, R30)
+
+ ADD $(8*24), RSP
+ RET
+
+TEXT ·call5(SB), NOSPLIT, $0-0
+ MOVD fn+0(FP), R9
+ MOVD a1+8(FP), R0
+ MOVD a2+16(FP), R1
+ MOVD a3+24(FP), R2
+ MOVD a4+32(FP), R3
+ MOVD a5+40(FP), R4
+ CALL R9
+ MOVD R0, ret+48(FP)
+ RET
diff --git a/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_loong64.s b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_loong64.s
new file mode 100644
index 0000000..7596f0d
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_loong64.s
@@ -0,0 +1,88 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2025 The Ebitengine Authors
+
+//go:build !cgo && linux
+
+#include "textflag.h"
+#include "go_asm.h"
+#include "abi_loong64.h"
+
+// these trampolines map the gcc ABI to Go ABI and then calls into the Go equivalent functions.
+// R23 is used as temporary register.
+
+TEXT x_cgo_init_trampoline(SB), NOSPLIT, $16
+ MOVV R4, 8(R3)
+ MOVV R5, 16(R3)
+ MOVV ·x_cgo_init_call(SB), R23
+ MOVV (R23), R23
+ CALL (R23)
+ RET
+
+TEXT x_cgo_thread_start_trampoline(SB), NOSPLIT, $8
+ MOVV R4, 8(R3)
+ MOVV ·x_cgo_thread_start_call(SB), R23
+ MOVV (R23), R23
+ CALL (R23)
+ RET
+
+TEXT x_cgo_setenv_trampoline(SB), NOSPLIT, $8
+ MOVV R4, 8(R3)
+ MOVV ·x_cgo_setenv_call(SB), R23
+ MOVV (R23), R23
+ CALL (R23)
+ RET
+
+TEXT x_cgo_unsetenv_trampoline(SB), NOSPLIT, $8
+ MOVV R4, 8(R3)
+ MOVV ·x_cgo_unsetenv_call(SB), R23
+ MOVV (R23), R23
+ CALL (R23)
+ RET
+
+TEXT x_cgo_notify_runtime_init_done_trampoline(SB), NOSPLIT, $0
+ CALL ·x_cgo_notify_runtime_init_done(SB)
+ RET
+
+TEXT x_cgo_bindm_trampoline(SB), NOSPLIT, $0
+ CALL ·x_cgo_bindm(SB)
+ RET
+
+// func setg_trampoline(setg uintptr, g uintptr)
+TEXT ·setg_trampoline(SB), NOSPLIT, $0
+ MOVV G+8(FP), R4
+ MOVV setg+0(FP), R23
+ CALL (R23)
+ RET
+
+TEXT threadentry_trampoline(SB), NOSPLIT, $0
+ // See crosscall2.
+ ADDV $(-23*8), R3
+ MOVV R4, (1*8)(R3) // fn unsafe.Pointer
+ MOVV R5, (2*8)(R3) // a unsafe.Pointer
+ MOVV R7, (3*8)(R3) // ctxt uintptr
+
+ SAVE_R22_TO_R31((4*8))
+ SAVE_F24_TO_F31((14*8))
+ MOVV R1, (22*8)(R3)
+
+ MOVV ·threadentry_call(SB), R23
+ MOVV (R23), R23
+ CALL (R23)
+
+ RESTORE_R22_TO_R31((4*8))
+ RESTORE_F24_TO_F31((14*8))
+ MOVV (22*8)(R3), R1
+
+ ADDV $(23*8), R3
+ RET
+
+TEXT ·call5(SB), NOSPLIT, $0-0
+ MOVV fn+0(FP), R23
+ MOVV a1+8(FP), R4
+ MOVV a2+16(FP), R5
+ MOVV a3+24(FP), R6
+ MOVV a4+32(FP), R7
+ MOVV a5+40(FP), R8
+ CALL (R23)
+ MOVV R4, ret+48(FP)
+ RET
diff --git a/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_ppc64le.s b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_ppc64le.s
new file mode 100644
index 0000000..85f8955
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_ppc64le.s
@@ -0,0 +1,227 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2026 The Ebitengine Authors
+
+//go:build !cgo && linux
+
+#include "textflag.h"
+#include "go_asm.h"
+
+// These trampolines map the C ABI to Go ABI and call into the Go equivalent functions.
+//
+// PPC64LE ELFv2 ABI stack frame layout:
+// 0(R1) = backchain (pointer to caller's frame)
+// 8(R1) = CR save area
+// 16(R1) = LR save area
+// 24(R1) = reserved
+// 32(R1) = parameter save area (minimum 64 bytes for 8 args)
+//
+// Two patterns are used depending on call direction:
+//
+// C→Go trampolines: The C caller already provides a 32-byte linkage area.
+// Save LR/CR into caller's frame at 16(R1)/8(R1) BEFORE allocating,
+// then use MOVDU to allocate and set backchain atomically.
+//
+// Go→C trampolines: Go callers don't provide ELFv2 linkage area.
+// Allocate frame first with MOVDU, then save LR/CR into OUR frame.
+
+TEXT x_cgo_init_trampoline(SB), NOSPLIT|NOFRAME, $0-0
+ MOVD LR, 16(R1)
+ MOVW CR, R0
+ MOVD R0, 8(R1)
+
+ MOVDU R1, -32(R1)
+
+ // R3, R4 already have the arguments
+ MOVD ·x_cgo_init_call(SB), R12
+ MOVD (R12), R12
+ MOVD R12, CTR
+ CALL CTR
+
+ ADD $32, R1
+
+ MOVD 16(R1), LR
+ MOVD 8(R1), R0
+ MOVW R0, CR
+ RET
+
+TEXT x_cgo_thread_start_trampoline(SB), NOSPLIT|NOFRAME, $0-0
+ MOVD LR, 16(R1)
+ MOVW CR, R0
+ MOVD R0, 8(R1)
+
+ MOVDU R1, -32(R1)
+
+ MOVD ·x_cgo_thread_start_call(SB), R12
+ MOVD (R12), R12
+ MOVD R12, CTR
+ CALL CTR
+
+ ADD $32, R1
+
+ MOVD 16(R1), LR
+ MOVD 8(R1), R0
+ MOVW R0, CR
+ RET
+
+// void (*_cgo_setenv)(char**)
+// C arg: R3 = pointer to env
+// This is C→Go: caller is C ABI.
+TEXT x_cgo_setenv_trampoline(SB), NOSPLIT|NOFRAME, $0-0
+ MOVD LR, 16(R1)
+ MOVW CR, R0
+ MOVD R0, 8(R1)
+
+ MOVDU R1, -32(R1)
+
+ MOVD ·x_cgo_setenv_call(SB), R12
+ MOVD (R12), R12
+ MOVD R12, CTR
+ CALL CTR
+
+ ADD $32, R1
+
+ MOVD 16(R1), LR
+ MOVD 8(R1), R0
+ MOVW R0, CR
+ RET
+
+TEXT x_cgo_unsetenv_trampoline(SB), NOSPLIT|NOFRAME, $0-0
+ MOVD LR, 16(R1)
+ MOVW CR, R0
+ MOVD R0, 8(R1)
+
+ MOVDU R1, -32(R1)
+
+ MOVD ·x_cgo_unsetenv_call(SB), R12
+ MOVD (R12), R12
+ MOVD R12, CTR
+ CALL CTR
+
+ ADD $32, R1
+
+ MOVD 16(R1), LR
+ MOVD 8(R1), R0
+ MOVW R0, CR
+ RET
+
+TEXT x_cgo_notify_runtime_init_done_trampoline(SB), NOSPLIT|NOFRAME, $0-0
+ MOVD LR, 16(R1)
+ MOVW CR, R0
+ MOVD R0, 8(R1)
+
+ MOVDU R1, -32(R1)
+
+ CALL ·x_cgo_notify_runtime_init_done(SB)
+
+ ADD $32, R1
+
+ MOVD 16(R1), LR
+ MOVD 8(R1), R0
+ MOVW R0, CR
+ RET
+
+TEXT x_cgo_bindm_trampoline(SB), NOSPLIT|NOFRAME, $0-0
+ MOVD LR, 16(R1)
+ MOVW CR, R0
+ MOVD R0, 8(R1)
+
+ MOVDU R1, -32(R1)
+
+ CALL ·x_cgo_bindm(SB)
+
+ ADD $32, R1
+
+ MOVD 16(R1), LR
+ MOVD 8(R1), R0
+ MOVW R0, CR
+ RET
+
+TEXT ·setg_trampoline(SB), NOSPLIT|NOFRAME, $0-16
+ // Save LR, CR, and R31 to non-volatile registers (C ABI preserves R14-R31)
+ MOVD LR, R20
+ MOVW CR, R21
+ MOVD R31, R22 // save R31 because load_g clobbers it
+
+ // Load arguments from Go stack
+ MOVD 32(R1), R12 // setg function pointer
+ MOVD 40(R1), R3 // g pointer → first C arg
+
+ // Allocate ELFv2 frame for the C callee (32 bytes minimum)
+ MOVDU R1, -32(R1)
+
+ // Call setg_gcc which stores g to TLS
+ MOVD R12, CTR
+ CALL CTR
+
+ // setg_gcc stored g to TLS but restored old g in R30.
+ // Call load_g to reload g from TLS into R30.
+ // Note: load_g clobbers R31
+ CALL runtime·load_g(SB)
+
+ // Deallocate frame
+ ADD $32, R1
+
+ // Clear R0 before returning to Go code.
+ // Go uses R0 as a constant 0 for things like "std r0,X(r1)" to zero stack locations.
+ // C/assembly functions may leave garbage in R0.
+ XOR R0, R0, R0
+
+ // Restore LR, CR, and R31 from non-volatile registers
+ MOVD R22, R31 // restore R31
+ MOVD R20, LR
+ MOVW R21, CR
+ RET
+
+TEXT threadentry_trampoline(SB), NOSPLIT|NOFRAME, $0-0
+ MOVD LR, 16(R1)
+ MOVW CR, R0
+ MOVD R0, 8(R1)
+
+ MOVDU R1, -32(R1)
+
+ MOVD ·threadentry_call(SB), R12
+ MOVD (R12), R12
+ MOVD R12, CTR
+ CALL CTR
+
+ ADD $32, R1
+
+ MOVD 16(R1), LR
+ MOVD 8(R1), R0
+ MOVW R0, CR
+ RET
+
+TEXT ·call5(SB), NOSPLIT|NOFRAME, $0-56
+ MOVD LR, R20
+ MOVW CR, R21
+
+ // Load arguments from Go stack into C argument registers
+ // Go placed args at 32(R1), 40(R1), etc.
+ MOVD 32(R1), R12 // fn
+ MOVD 40(R1), R3 // a1 → first C arg
+ MOVD 48(R1), R4 // a2 → second C arg
+ MOVD 56(R1), R5 // a3 → third C arg
+ MOVD 64(R1), R6 // a4 → fourth C arg
+ MOVD 72(R1), R7 // a5 → fifth C arg
+
+ MOVDU R1, -32(R1)
+
+ MOVD R12, CTR
+ CALL CTR
+
+ // Store return value
+ // After MOVDU -32, original 80(R1) is now at 80+32=112(R1)
+ MOVD R3, (80+32)(R1)
+
+ // Deallocate frame
+ ADD $32, R1
+
+ // Clear R0 before returning to Go code.
+ // Go uses R0 as a constant 0 register for things like "std r0,X(r1)"
+ // to zero stack locations. C functions may leave garbage in R0.
+ XOR R0, R0, R0
+
+ // Restore LR/CR from non-volatile registers
+ MOVD R20, LR
+ MOVW R21, CR
+ RET
diff --git a/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_riscv64.s b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_riscv64.s
new file mode 100644
index 0000000..9298f8c
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/trampolines_riscv64.s
@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2026 The Ebitengine Authors
+
+//go:build !cgo && linux
+
+#include "textflag.h"
+#include "go_asm.h"
+
+// these trampolines map the gcc ABI to Go ABI and then calls into the Go equivalent functions.
+// X5 is used as temporary register.
+
+TEXT x_cgo_init_trampoline(SB), NOSPLIT, $16
+ MOV X10, 8(SP)
+ MOV X11, 16(SP)
+ MOV ·x_cgo_init_call(SB), X5
+ MOV (X5), X5
+ CALL X5
+ RET
+
+TEXT x_cgo_thread_start_trampoline(SB), NOSPLIT, $8
+ MOV X10, 8(SP)
+ MOV ·x_cgo_thread_start_call(SB), X5
+ MOV (X5), X5
+ CALL X5
+ RET
+
+TEXT x_cgo_setenv_trampoline(SB), NOSPLIT, $8
+ MOV X10, 8(SP)
+ MOV ·x_cgo_setenv_call(SB), X5
+ MOV (X5), X5
+ CALL X5
+ RET
+
+TEXT x_cgo_unsetenv_trampoline(SB), NOSPLIT, $8
+ MOV X10, 8(SP)
+ MOV ·x_cgo_unsetenv_call(SB), X5
+ MOV (X5), X5
+ CALL X5
+ RET
+
+TEXT x_cgo_notify_runtime_init_done_trampoline(SB), NOSPLIT, $0
+ CALL ·x_cgo_notify_runtime_init_done(SB)
+ RET
+
+TEXT x_cgo_bindm_trampoline(SB), NOSPLIT, $0
+ CALL ·x_cgo_bindm(SB)
+ RET
+
+// func setg_trampoline(setg uintptr, g uintptr)
+TEXT ·setg_trampoline(SB), NOSPLIT, $0
+ MOV gp+8(FP), X10
+ MOV setg+0(FP), X5
+ CALL X5
+ RET
+
+TEXT threadentry_trampoline(SB), NOSPLIT, $16
+ MOV X10, 8(SP)
+ MOV ·threadentry_call(SB), X5
+ MOV (X5), X5
+ CALL X5
+ RET
+
+TEXT ·call5(SB), NOSPLIT, $0-48
+ MOV fn+0(FP), X5
+ MOV a1+8(FP), X10
+ MOV a2+16(FP), X11
+ MOV a3+24(FP), X12
+ MOV a4+32(FP), X13
+ MOV a5+40(FP), X14
+ CALL X5
+ MOV X10, ret+48(FP)
+ RET
diff --git a/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/zsymbols.go b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/zsymbols.go
new file mode 100644
index 0000000..cc552e7
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/zsymbols.go
@@ -0,0 +1,165 @@
+// Code generated by 'go generate' with gen.go. DO NOT EDIT.
+
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
+
+//go:build !cgo && (darwin || freebsd || linux || netbsd)
+
+package fakecgo
+
+import (
+ "syscall"
+ "unsafe"
+)
+
+//go:nosplit
+//go:norace
+func malloc(size uintptr) unsafe.Pointer {
+ ret := call5(mallocABI0, uintptr(size), 0, 0, 0, 0)
+ // this indirection is to avoid go vet complaining about possible misuse of unsafe.Pointer
+ return *(*unsafe.Pointer)(unsafe.Pointer(&ret))
+}
+
+//go:nosplit
+//go:norace
+func free(ptr unsafe.Pointer) {
+ call5(freeABI0, uintptr(ptr), 0, 0, 0, 0)
+}
+
+//go:nosplit
+//go:norace
+func setenv(name *byte, value *byte, overwrite int32) int32 {
+ return int32(call5(setenvABI0, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(value)), uintptr(overwrite), 0, 0))
+}
+
+//go:nosplit
+//go:norace
+func unsetenv(name *byte) int32 {
+ return int32(call5(unsetenvABI0, uintptr(unsafe.Pointer(name)), 0, 0, 0, 0))
+}
+
+//go:nosplit
+//go:norace
+func sigfillset(set *sigset_t) int32 {
+ return int32(call5(sigfillsetABI0, uintptr(unsafe.Pointer(set)), 0, 0, 0, 0))
+}
+
+//go:nosplit
+//go:norace
+func nanosleep(ts *syscall.Timespec, rem *syscall.Timespec) int32 {
+ return int32(call5(nanosleepABI0, uintptr(unsafe.Pointer(ts)), uintptr(unsafe.Pointer(rem)), 0, 0, 0))
+}
+
+//go:nosplit
+//go:norace
+func abort() {
+ call5(abortABI0, 0, 0, 0, 0, 0)
+}
+
+//go:nosplit
+//go:norace
+func pthread_attr_init(attr *pthread_attr_t) int32 {
+ return int32(call5(pthread_attr_initABI0, uintptr(unsafe.Pointer(attr)), 0, 0, 0, 0))
+}
+
+//go:nosplit
+//go:norace
+func pthread_create(thread *pthread_t, attr *pthread_attr_t, start unsafe.Pointer, arg unsafe.Pointer) int32 {
+ return int32(call5(pthread_createABI0, uintptr(unsafe.Pointer(thread)), uintptr(unsafe.Pointer(attr)), uintptr(start), uintptr(arg), 0))
+}
+
+//go:nosplit
+//go:norace
+func pthread_detach(thread pthread_t) int32 {
+ return int32(call5(pthread_detachABI0, uintptr(thread), 0, 0, 0, 0))
+}
+
+//go:nosplit
+//go:norace
+func pthread_sigmask(how sighow, ign *sigset_t, oset *sigset_t) int32 {
+ return int32(call5(pthread_sigmaskABI0, uintptr(how), uintptr(unsafe.Pointer(ign)), uintptr(unsafe.Pointer(oset)), 0, 0))
+}
+
+//go:nosplit
+//go:norace
+func pthread_mutex_lock(mutex *pthread_mutex_t) int32 {
+ return int32(call5(pthread_mutex_lockABI0, uintptr(unsafe.Pointer(mutex)), 0, 0, 0, 0))
+}
+
+//go:nosplit
+//go:norace
+func pthread_mutex_unlock(mutex *pthread_mutex_t) int32 {
+ return int32(call5(pthread_mutex_unlockABI0, uintptr(unsafe.Pointer(mutex)), 0, 0, 0, 0))
+}
+
+//go:nosplit
+//go:norace
+func pthread_cond_broadcast(cond *pthread_cond_t) int32 {
+ return int32(call5(pthread_cond_broadcastABI0, uintptr(unsafe.Pointer(cond)), 0, 0, 0, 0))
+}
+
+//go:nosplit
+//go:norace
+func pthread_setspecific(key pthread_key_t, value unsafe.Pointer) int32 {
+ return int32(call5(pthread_setspecificABI0, uintptr(key), uintptr(value), 0, 0, 0))
+}
+
+//go:linkname _malloc _malloc
+var _malloc uint8
+var mallocABI0 = uintptr(unsafe.Pointer(&_malloc))
+
+//go:linkname _free _free
+var _free uint8
+var freeABI0 = uintptr(unsafe.Pointer(&_free))
+
+//go:linkname _setenv _setenv
+var _setenv uint8
+var setenvABI0 = uintptr(unsafe.Pointer(&_setenv))
+
+//go:linkname _unsetenv _unsetenv
+var _unsetenv uint8
+var unsetenvABI0 = uintptr(unsafe.Pointer(&_unsetenv))
+
+//go:linkname _sigfillset _sigfillset
+var _sigfillset uint8
+var sigfillsetABI0 = uintptr(unsafe.Pointer(&_sigfillset))
+
+//go:linkname _nanosleep _nanosleep
+var _nanosleep uint8
+var nanosleepABI0 = uintptr(unsafe.Pointer(&_nanosleep))
+
+//go:linkname _abort _abort
+var _abort uint8
+var abortABI0 = uintptr(unsafe.Pointer(&_abort))
+
+//go:linkname _pthread_attr_init _pthread_attr_init
+var _pthread_attr_init uint8
+var pthread_attr_initABI0 = uintptr(unsafe.Pointer(&_pthread_attr_init))
+
+//go:linkname _pthread_create _pthread_create
+var _pthread_create uint8
+var pthread_createABI0 = uintptr(unsafe.Pointer(&_pthread_create))
+
+//go:linkname _pthread_detach _pthread_detach
+var _pthread_detach uint8
+var pthread_detachABI0 = uintptr(unsafe.Pointer(&_pthread_detach))
+
+//go:linkname _pthread_sigmask _pthread_sigmask
+var _pthread_sigmask uint8
+var pthread_sigmaskABI0 = uintptr(unsafe.Pointer(&_pthread_sigmask))
+
+//go:linkname _pthread_mutex_lock _pthread_mutex_lock
+var _pthread_mutex_lock uint8
+var pthread_mutex_lockABI0 = uintptr(unsafe.Pointer(&_pthread_mutex_lock))
+
+//go:linkname _pthread_mutex_unlock _pthread_mutex_unlock
+var _pthread_mutex_unlock uint8
+var pthread_mutex_unlockABI0 = uintptr(unsafe.Pointer(&_pthread_mutex_unlock))
+
+//go:linkname _pthread_cond_broadcast _pthread_cond_broadcast
+var _pthread_cond_broadcast uint8
+var pthread_cond_broadcastABI0 = uintptr(unsafe.Pointer(&_pthread_cond_broadcast))
+
+//go:linkname _pthread_setspecific _pthread_setspecific
+var _pthread_setspecific uint8
+var pthread_setspecificABI0 = uintptr(unsafe.Pointer(&_pthread_setspecific))
diff --git a/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/zsymbols_darwin.go b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/zsymbols_darwin.go
new file mode 100644
index 0000000..960f816
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/zsymbols_darwin.go
@@ -0,0 +1,59 @@
+// Code generated by 'go generate' with gen.go. DO NOT EDIT.
+
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
+
+//go:build !cgo
+
+package fakecgo
+
+import "unsafe"
+
+//go:cgo_import_dynamic purego_malloc malloc "/usr/lib/libSystem.B.dylib"
+//go:cgo_import_dynamic purego_free free "/usr/lib/libSystem.B.dylib"
+//go:cgo_import_dynamic purego_setenv setenv "/usr/lib/libSystem.B.dylib"
+//go:cgo_import_dynamic purego_unsetenv unsetenv "/usr/lib/libSystem.B.dylib"
+//go:cgo_import_dynamic purego_sigfillset sigfillset "/usr/lib/libSystem.B.dylib"
+//go:cgo_import_dynamic purego_nanosleep nanosleep "/usr/lib/libSystem.B.dylib"
+//go:cgo_import_dynamic purego_abort abort "/usr/lib/libSystem.B.dylib"
+//go:cgo_import_dynamic purego_pthread_attr_init pthread_attr_init "/usr/lib/libSystem.B.dylib"
+//go:cgo_import_dynamic purego_pthread_create pthread_create "/usr/lib/libSystem.B.dylib"
+//go:cgo_import_dynamic purego_pthread_detach pthread_detach "/usr/lib/libSystem.B.dylib"
+//go:cgo_import_dynamic purego_pthread_sigmask pthread_sigmask "/usr/lib/libSystem.B.dylib"
+//go:cgo_import_dynamic purego_pthread_mutex_lock pthread_mutex_lock "/usr/lib/libSystem.B.dylib"
+//go:cgo_import_dynamic purego_pthread_mutex_unlock pthread_mutex_unlock "/usr/lib/libSystem.B.dylib"
+//go:cgo_import_dynamic purego_pthread_cond_broadcast pthread_cond_broadcast "/usr/lib/libSystem.B.dylib"
+//go:cgo_import_dynamic purego_pthread_setspecific pthread_setspecific "/usr/lib/libSystem.B.dylib"
+//go:cgo_import_dynamic purego_pthread_self pthread_self "/usr/lib/libSystem.B.dylib"
+//go:cgo_import_dynamic purego_pthread_get_stacksize_np pthread_get_stacksize_np "/usr/lib/libSystem.B.dylib"
+//go:cgo_import_dynamic purego_pthread_attr_setstacksize pthread_attr_setstacksize "/usr/lib/libSystem.B.dylib"
+
+//go:nosplit
+//go:norace
+func pthread_self() pthread_t {
+ return pthread_t(call5(pthread_selfABI0, 0, 0, 0, 0, 0))
+}
+
+//go:nosplit
+//go:norace
+func pthread_get_stacksize_np(thread pthread_t) size_t {
+ return size_t(call5(pthread_get_stacksize_npABI0, uintptr(thread), 0, 0, 0, 0))
+}
+
+//go:nosplit
+//go:norace
+func pthread_attr_setstacksize(attr *pthread_attr_t, size size_t) int32 {
+ return int32(call5(pthread_attr_setstacksizeABI0, uintptr(unsafe.Pointer(attr)), uintptr(size), 0, 0, 0))
+}
+
+//go:linkname _pthread_self _pthread_self
+var _pthread_self uint8
+var pthread_selfABI0 = uintptr(unsafe.Pointer(&_pthread_self))
+
+//go:linkname _pthread_get_stacksize_np _pthread_get_stacksize_np
+var _pthread_get_stacksize_np uint8
+var pthread_get_stacksize_npABI0 = uintptr(unsafe.Pointer(&_pthread_get_stacksize_np))
+
+//go:linkname _pthread_attr_setstacksize _pthread_attr_setstacksize
+var _pthread_attr_setstacksize uint8
+var pthread_attr_setstacksizeABI0 = uintptr(unsafe.Pointer(&_pthread_attr_setstacksize))
diff --git a/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/zsymbols_freebsd.go b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/zsymbols_freebsd.go
new file mode 100644
index 0000000..d697755
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/zsymbols_freebsd.go
@@ -0,0 +1,48 @@
+// Code generated by 'go generate' with gen.go. DO NOT EDIT.
+
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
+
+//go:build !cgo
+
+package fakecgo
+
+import "unsafe"
+
+//go:cgo_import_dynamic purego_malloc malloc "libc.so.7"
+//go:cgo_import_dynamic purego_free free "libc.so.7"
+//go:cgo_import_dynamic purego_setenv setenv "libc.so.7"
+//go:cgo_import_dynamic purego_unsetenv unsetenv "libc.so.7"
+//go:cgo_import_dynamic purego_sigfillset sigfillset "libc.so.7"
+//go:cgo_import_dynamic purego_nanosleep nanosleep "libc.so.7"
+//go:cgo_import_dynamic purego_abort abort "libc.so.7"
+//go:cgo_import_dynamic purego_pthread_attr_init pthread_attr_init "libpthread.so"
+//go:cgo_import_dynamic purego_pthread_create pthread_create "libpthread.so"
+//go:cgo_import_dynamic purego_pthread_detach pthread_detach "libpthread.so"
+//go:cgo_import_dynamic purego_pthread_sigmask pthread_sigmask "libpthread.so"
+//go:cgo_import_dynamic purego_pthread_mutex_lock pthread_mutex_lock "libpthread.so"
+//go:cgo_import_dynamic purego_pthread_mutex_unlock pthread_mutex_unlock "libpthread.so"
+//go:cgo_import_dynamic purego_pthread_cond_broadcast pthread_cond_broadcast "libpthread.so"
+//go:cgo_import_dynamic purego_pthread_setspecific pthread_setspecific "libpthread.so"
+//go:cgo_import_dynamic purego_pthread_attr_getstacksize pthread_attr_getstacksize "libpthread.so"
+//go:cgo_import_dynamic purego_pthread_attr_destroy pthread_attr_destroy "libpthread.so"
+
+//go:nosplit
+//go:norace
+func pthread_attr_getstacksize(attr *pthread_attr_t, stacksize *size_t) int32 {
+ return int32(call5(pthread_attr_getstacksizeABI0, uintptr(unsafe.Pointer(attr)), uintptr(unsafe.Pointer(stacksize)), 0, 0, 0))
+}
+
+//go:nosplit
+//go:norace
+func pthread_attr_destroy(attr *pthread_attr_t) int32 {
+ return int32(call5(pthread_attr_destroyABI0, uintptr(unsafe.Pointer(attr)), 0, 0, 0, 0))
+}
+
+//go:linkname _pthread_attr_getstacksize _pthread_attr_getstacksize
+var _pthread_attr_getstacksize uint8
+var pthread_attr_getstacksizeABI0 = uintptr(unsafe.Pointer(&_pthread_attr_getstacksize))
+
+//go:linkname _pthread_attr_destroy _pthread_attr_destroy
+var _pthread_attr_destroy uint8
+var pthread_attr_destroyABI0 = uintptr(unsafe.Pointer(&_pthread_attr_destroy))
diff --git a/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/zsymbols_linux.go b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/zsymbols_linux.go
new file mode 100644
index 0000000..f6bad22
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/zsymbols_linux.go
@@ -0,0 +1,48 @@
+// Code generated by 'go generate' with gen.go. DO NOT EDIT.
+
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
+
+//go:build !cgo
+
+package fakecgo
+
+import "unsafe"
+
+//go:cgo_import_dynamic purego_malloc malloc "libc.so.6"
+//go:cgo_import_dynamic purego_free free "libc.so.6"
+//go:cgo_import_dynamic purego_setenv setenv "libc.so.6"
+//go:cgo_import_dynamic purego_unsetenv unsetenv "libc.so.6"
+//go:cgo_import_dynamic purego_sigfillset sigfillset "libc.so.6"
+//go:cgo_import_dynamic purego_nanosleep nanosleep "libc.so.6"
+//go:cgo_import_dynamic purego_abort abort "libc.so.6"
+//go:cgo_import_dynamic purego_pthread_attr_init pthread_attr_init "libpthread.so.0"
+//go:cgo_import_dynamic purego_pthread_create pthread_create "libpthread.so.0"
+//go:cgo_import_dynamic purego_pthread_detach pthread_detach "libpthread.so.0"
+//go:cgo_import_dynamic purego_pthread_sigmask pthread_sigmask "libpthread.so.0"
+//go:cgo_import_dynamic purego_pthread_mutex_lock pthread_mutex_lock "libpthread.so.0"
+//go:cgo_import_dynamic purego_pthread_mutex_unlock pthread_mutex_unlock "libpthread.so.0"
+//go:cgo_import_dynamic purego_pthread_cond_broadcast pthread_cond_broadcast "libpthread.so.0"
+//go:cgo_import_dynamic purego_pthread_setspecific pthread_setspecific "libpthread.so.0"
+//go:cgo_import_dynamic purego_pthread_attr_getstacksize pthread_attr_getstacksize "libpthread.so.0"
+//go:cgo_import_dynamic purego_pthread_attr_destroy pthread_attr_destroy "libpthread.so.0"
+
+//go:nosplit
+//go:norace
+func pthread_attr_getstacksize(attr *pthread_attr_t, stacksize *size_t) int32 {
+ return int32(call5(pthread_attr_getstacksizeABI0, uintptr(unsafe.Pointer(attr)), uintptr(unsafe.Pointer(stacksize)), 0, 0, 0))
+}
+
+//go:nosplit
+//go:norace
+func pthread_attr_destroy(attr *pthread_attr_t) int32 {
+ return int32(call5(pthread_attr_destroyABI0, uintptr(unsafe.Pointer(attr)), 0, 0, 0, 0))
+}
+
+//go:linkname _pthread_attr_getstacksize _pthread_attr_getstacksize
+var _pthread_attr_getstacksize uint8
+var pthread_attr_getstacksizeABI0 = uintptr(unsafe.Pointer(&_pthread_attr_getstacksize))
+
+//go:linkname _pthread_attr_destroy _pthread_attr_destroy
+var _pthread_attr_destroy uint8
+var pthread_attr_destroyABI0 = uintptr(unsafe.Pointer(&_pthread_attr_destroy))
diff --git a/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/zsymbols_netbsd.go b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/zsymbols_netbsd.go
new file mode 100644
index 0000000..774402c
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/zsymbols_netbsd.go
@@ -0,0 +1,59 @@
+// Code generated by 'go generate' with gen.go. DO NOT EDIT.
+
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
+
+//go:build !cgo
+
+package fakecgo
+
+import "unsafe"
+
+//go:cgo_import_dynamic purego_malloc malloc "libc.so"
+//go:cgo_import_dynamic purego_free free "libc.so"
+//go:cgo_import_dynamic purego_setenv setenv "libc.so"
+//go:cgo_import_dynamic purego_unsetenv unsetenv "libc.so"
+//go:cgo_import_dynamic purego_sigfillset sigfillset "libc.so"
+//go:cgo_import_dynamic purego_nanosleep nanosleep "libc.so"
+//go:cgo_import_dynamic purego_abort abort "libc.so"
+//go:cgo_import_dynamic purego_sigaltstack sigaltstack "libc.so"
+//go:cgo_import_dynamic purego_pthread_attr_init pthread_attr_init "libpthread.so"
+//go:cgo_import_dynamic purego_pthread_create pthread_create "libpthread.so"
+//go:cgo_import_dynamic purego_pthread_detach pthread_detach "libpthread.so"
+//go:cgo_import_dynamic purego_pthread_sigmask pthread_sigmask "libpthread.so"
+//go:cgo_import_dynamic purego_pthread_mutex_lock pthread_mutex_lock "libpthread.so"
+//go:cgo_import_dynamic purego_pthread_mutex_unlock pthread_mutex_unlock "libpthread.so"
+//go:cgo_import_dynamic purego_pthread_cond_broadcast pthread_cond_broadcast "libpthread.so"
+//go:cgo_import_dynamic purego_pthread_setspecific pthread_setspecific "libpthread.so"
+//go:cgo_import_dynamic purego_pthread_attr_getstacksize pthread_attr_getstacksize "libpthread.so"
+//go:cgo_import_dynamic purego_pthread_attr_destroy pthread_attr_destroy "libpthread.so"
+
+//go:nosplit
+//go:norace
+func sigaltstack(ss *stack_t, old_ss *stack_t) int32 {
+ return int32(call5(sigaltstackABI0, uintptr(unsafe.Pointer(ss)), uintptr(unsafe.Pointer(old_ss)), 0, 0, 0))
+}
+
+//go:nosplit
+//go:norace
+func pthread_attr_getstacksize(attr *pthread_attr_t, stacksize *size_t) int32 {
+ return int32(call5(pthread_attr_getstacksizeABI0, uintptr(unsafe.Pointer(attr)), uintptr(unsafe.Pointer(stacksize)), 0, 0, 0))
+}
+
+//go:nosplit
+//go:norace
+func pthread_attr_destroy(attr *pthread_attr_t) int32 {
+ return int32(call5(pthread_attr_destroyABI0, uintptr(unsafe.Pointer(attr)), 0, 0, 0, 0))
+}
+
+//go:linkname _sigaltstack _sigaltstack
+var _sigaltstack uint8
+var sigaltstackABI0 = uintptr(unsafe.Pointer(&_sigaltstack))
+
+//go:linkname _pthread_attr_getstacksize _pthread_attr_getstacksize
+var _pthread_attr_getstacksize uint8
+var pthread_attr_getstacksizeABI0 = uintptr(unsafe.Pointer(&_pthread_attr_getstacksize))
+
+//go:linkname _pthread_attr_destroy _pthread_attr_destroy
+var _pthread_attr_destroy uint8
+var pthread_attr_destroyABI0 = uintptr(unsafe.Pointer(&_pthread_attr_destroy))
diff --git a/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/ztrampolines_darwin.s b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/ztrampolines_darwin.s
new file mode 100644
index 0000000..35ef7ac
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/ztrampolines_darwin.s
@@ -0,0 +1,19 @@
+// Code generated by 'go generate' with gen.go. DO NOT EDIT.
+
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
+
+//go:build !cgo
+
+#include "textflag.h"
+
+// these stubs are here because it is not possible to go:linkname directly the C functions
+
+TEXT _pthread_self(SB), NOSPLIT|NOFRAME, $0-0
+ JMP purego_pthread_self(SB)
+
+TEXT _pthread_get_stacksize_np(SB), NOSPLIT|NOFRAME, $0-0
+ JMP purego_pthread_get_stacksize_np(SB)
+
+TEXT _pthread_attr_setstacksize(SB), NOSPLIT|NOFRAME, $0-0
+ JMP purego_pthread_attr_setstacksize(SB)
diff --git a/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/ztrampolines_freebsd.s b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/ztrampolines_freebsd.s
new file mode 100644
index 0000000..da07005
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/ztrampolines_freebsd.s
@@ -0,0 +1,16 @@
+// Code generated by 'go generate' with gen.go. DO NOT EDIT.
+
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
+
+//go:build !cgo
+
+#include "textflag.h"
+
+// these stubs are here because it is not possible to go:linkname directly the C functions
+
+TEXT _pthread_attr_getstacksize(SB), NOSPLIT|NOFRAME, $0-0
+ JMP purego_pthread_attr_getstacksize(SB)
+
+TEXT _pthread_attr_destroy(SB), NOSPLIT|NOFRAME, $0-0
+ JMP purego_pthread_attr_destroy(SB)
diff --git a/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/ztrampolines_linux.s b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/ztrampolines_linux.s
new file mode 100644
index 0000000..da07005
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/ztrampolines_linux.s
@@ -0,0 +1,16 @@
+// Code generated by 'go generate' with gen.go. DO NOT EDIT.
+
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
+
+//go:build !cgo
+
+#include "textflag.h"
+
+// these stubs are here because it is not possible to go:linkname directly the C functions
+
+TEXT _pthread_attr_getstacksize(SB), NOSPLIT|NOFRAME, $0-0
+ JMP purego_pthread_attr_getstacksize(SB)
+
+TEXT _pthread_attr_destroy(SB), NOSPLIT|NOFRAME, $0-0
+ JMP purego_pthread_attr_destroy(SB)
diff --git a/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/ztrampolines_netbsd.s b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/ztrampolines_netbsd.s
new file mode 100644
index 0000000..81ef76f
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/ztrampolines_netbsd.s
@@ -0,0 +1,19 @@
+// Code generated by 'go generate' with gen.go. DO NOT EDIT.
+
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
+
+//go:build !cgo
+
+#include "textflag.h"
+
+// these stubs are here because it is not possible to go:linkname directly the C functions
+
+TEXT _sigaltstack(SB), NOSPLIT|NOFRAME, $0-0
+ JMP purego_sigaltstack(SB)
+
+TEXT _pthread_attr_getstacksize(SB), NOSPLIT|NOFRAME, $0-0
+ JMP purego_pthread_attr_getstacksize(SB)
+
+TEXT _pthread_attr_destroy(SB), NOSPLIT|NOFRAME, $0-0
+ JMP purego_pthread_attr_destroy(SB)
diff --git a/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/ztrampolines_stubs.s b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/ztrampolines_stubs.s
new file mode 100644
index 0000000..8e1afff
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/internal/fakecgo/ztrampolines_stubs.s
@@ -0,0 +1,55 @@
+// Code generated by 'go generate' with gen.go. DO NOT EDIT.
+
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
+
+//go:build !cgo && (darwin || freebsd || linux || netbsd)
+
+#include "textflag.h"
+
+// these stubs are here because it is not possible to go:linkname directly the C functions
+
+TEXT _malloc(SB), NOSPLIT|NOFRAME, $0-0
+ JMP purego_malloc(SB)
+
+TEXT _free(SB), NOSPLIT|NOFRAME, $0-0
+ JMP purego_free(SB)
+
+TEXT _setenv(SB), NOSPLIT|NOFRAME, $0-0
+ JMP purego_setenv(SB)
+
+TEXT _unsetenv(SB), NOSPLIT|NOFRAME, $0-0
+ JMP purego_unsetenv(SB)
+
+TEXT _sigfillset(SB), NOSPLIT|NOFRAME, $0-0
+ JMP purego_sigfillset(SB)
+
+TEXT _nanosleep(SB), NOSPLIT|NOFRAME, $0-0
+ JMP purego_nanosleep(SB)
+
+TEXT _abort(SB), NOSPLIT|NOFRAME, $0-0
+ JMP purego_abort(SB)
+
+TEXT _pthread_attr_init(SB), NOSPLIT|NOFRAME, $0-0
+ JMP purego_pthread_attr_init(SB)
+
+TEXT _pthread_create(SB), NOSPLIT|NOFRAME, $0-0
+ JMP purego_pthread_create(SB)
+
+TEXT _pthread_detach(SB), NOSPLIT|NOFRAME, $0-0
+ JMP purego_pthread_detach(SB)
+
+TEXT _pthread_sigmask(SB), NOSPLIT|NOFRAME, $0-0
+ JMP purego_pthread_sigmask(SB)
+
+TEXT _pthread_mutex_lock(SB), NOSPLIT|NOFRAME, $0-0
+ JMP purego_pthread_mutex_lock(SB)
+
+TEXT _pthread_mutex_unlock(SB), NOSPLIT|NOFRAME, $0-0
+ JMP purego_pthread_mutex_unlock(SB)
+
+TEXT _pthread_cond_broadcast(SB), NOSPLIT|NOFRAME, $0-0
+ JMP purego_pthread_cond_broadcast(SB)
+
+TEXT _pthread_setspecific(SB), NOSPLIT|NOFRAME, $0-0
+ JMP purego_pthread_setspecific(SB)
diff --git a/raymenu/vendor/github.com/ebitengine/purego/internal/strings/strings.go b/raymenu/vendor/github.com/ebitengine/purego/internal/strings/strings.go
new file mode 100644
index 0000000..5b0d252
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/internal/strings/strings.go
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
+
+package strings
+
+import (
+ "unsafe"
+)
+
+// hasSuffix tests whether the string s ends with suffix.
+func hasSuffix(s, suffix string) bool {
+ return len(s) >= len(suffix) && s[len(s)-len(suffix):] == suffix
+}
+
+// CString converts a go string to *byte that can be passed to C code.
+func CString(name string) *byte {
+ if hasSuffix(name, "\x00") {
+ return &(*(*[]byte)(unsafe.Pointer(&name)))[0]
+ }
+ b := make([]byte, len(name)+1)
+ copy(b, name)
+ return &b[0]
+}
+
+// GoString copies a null-terminated char* to a Go string.
+func GoString(c uintptr) string {
+ // We take the address and then dereference it to trick go vet from creating a possible misuse of unsafe.Pointer
+ ptr := *(*unsafe.Pointer)(unsafe.Pointer(&c))
+ if ptr == nil {
+ return ""
+ }
+ var length int
+ for {
+ if *(*byte)(unsafe.Add(ptr, uintptr(length))) == '\x00' {
+ break
+ }
+ length++
+ }
+ return string(unsafe.Slice((*byte)(ptr), length))
+}
diff --git a/raymenu/vendor/github.com/ebitengine/purego/internal/xreflect/reflect_go124.go b/raymenu/vendor/github.com/ebitengine/purego/internal/xreflect/reflect_go124.go
new file mode 100644
index 0000000..5eb0580
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/internal/xreflect/reflect_go124.go
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2025 The Ebitengine Authors
+
+//go:build !go1.25
+
+package xreflect
+
+import "reflect"
+
+// TODO: remove this and use Go 1.25's reflect.TypeAssert when minimum go.mod version is 1.25
+
+func TypeAssert[T any](v reflect.Value) (T, bool) {
+ v2, ok := v.Interface().(T)
+ return v2, ok
+}
diff --git a/raymenu/vendor/github.com/ebitengine/purego/internal/xreflect/reflect_go125.go b/raymenu/vendor/github.com/ebitengine/purego/internal/xreflect/reflect_go125.go
new file mode 100644
index 0000000..62ee13d
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/internal/xreflect/reflect_go125.go
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2025 The Ebitengine Authors
+
+//go:build go1.25
+
+package xreflect
+
+import "reflect"
+
+func TypeAssert[T any](v reflect.Value) (T, bool) {
+ return reflect.TypeAssert[T](v)
+}
diff --git a/raymenu/vendor/github.com/ebitengine/purego/is_ios.go b/raymenu/vendor/github.com/ebitengine/purego/is_ios.go
new file mode 100644
index 0000000..ed31da9
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/is_ios.go
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
+
+//go:build !cgo
+
+package purego
+
+// if you are getting this error it means that you have
+// CGO_ENABLED=0 while trying to build for ios.
+// purego does not support this mode yet.
+// the fix is to set CGO_ENABLED=1 which will require
+// a C compiler.
+var _ = _PUREGO_REQUIRES_CGO_ON_IOS
diff --git a/raymenu/vendor/github.com/ebitengine/purego/nocgo.go b/raymenu/vendor/github.com/ebitengine/purego/nocgo.go
new file mode 100644
index 0000000..b91b979
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/nocgo.go
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
+
+//go:build !cgo && (darwin || freebsd || linux || netbsd)
+
+package purego
+
+// if CGO_ENABLED=0 import fakecgo to setup the Cgo runtime correctly.
+// This is required since some frameworks need TLS setup the C way which Go doesn't do.
+// We currently don't support ios in fakecgo mode so force Cgo or fail
+//
+// The way that the Cgo runtime (runtime/cgo) works is by setting some variables found
+// in runtime with non-null GCC compiled functions. The variables that are replaced are
+// var (
+// iscgo bool // in runtime/cgo.go
+// _cgo_init unsafe.Pointer // in runtime/cgo.go
+// _cgo_thread_start unsafe.Pointer // in runtime/cgo.go
+// _cgo_notify_runtime_init_done unsafe.Pointer // in runtime/cgo.go
+// _cgo_setenv unsafe.Pointer // in runtime/env_posix.go
+// _cgo_unsetenv unsafe.Pointer // in runtime/env_posix.go
+// )
+// importing fakecgo will set these (using //go:linkname) with functions written
+// entirely in Go (except for some assembly trampolines to change GCC ABI to Go ABI).
+// Doing so makes it possible to build applications that call into C without CGO_ENABLED=1.
+import _ "github.com/ebitengine/purego/internal/fakecgo"
diff --git a/raymenu/vendor/github.com/ebitengine/purego/struct_386.go b/raymenu/vendor/github.com/ebitengine/purego/struct_386.go
new file mode 100644
index 0000000..02c8ac4
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/struct_386.go
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2025 The Ebitengine Authors
+
+package purego
+
+import "reflect"
+
+func addStruct(v reflect.Value, numInts, numFloats, numStack *int, addInt, addFloat, addStack func(uintptr), keepAlive []any) []any {
+ panic("purego: struct arguments are not supported")
+}
+
+func getStruct(outType reflect.Type, syscall syscall15Args) (v reflect.Value) {
+ panic("purego: struct returns are not supported")
+}
+
+func placeRegisters(v reflect.Value, addFloat func(uintptr), addInt func(uintptr)) {
+ panic("purego: placeRegisters not implemented on 386")
+}
+
+// shouldBundleStackArgs always returns false on 386
+// since C-style stack argument bundling is only needed on Darwin ARM64.
+func shouldBundleStackArgs(v reflect.Value, numInts, numFloats int) bool {
+ return false
+}
+
+// structFitsInRegisters is not used on 386.
+func structFitsInRegisters(val reflect.Value, tempNumInts, tempNumFloats int) (bool, int, int) {
+ panic("purego: structFitsInRegisters should not be called on 386")
+}
+
+// collectStackArgs is not used on 386.
+func collectStackArgs(args []reflect.Value, startIdx int, numInts, numFloats int,
+ keepAlive []any, addInt, addFloat, addStack func(uintptr),
+ pNumInts, pNumFloats, pNumStack *int) ([]reflect.Value, []any) {
+ panic("purego: collectStackArgs should not be called on 386")
+}
+
+// bundleStackArgs is not used on 386.
+func bundleStackArgs(stackArgs []reflect.Value, addStack func(uintptr)) {
+ panic("purego: bundleStackArgs should not be called on 386")
+}
diff --git a/raymenu/vendor/github.com/ebitengine/purego/struct_amd64.go b/raymenu/vendor/github.com/ebitengine/purego/struct_amd64.go
new file mode 100644
index 0000000..c56f957
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/struct_amd64.go
@@ -0,0 +1,286 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2024 The Ebitengine Authors
+
+package purego
+
+import (
+ "math"
+ "reflect"
+ "unsafe"
+)
+
+func getStruct(outType reflect.Type, syscall syscall15Args) (v reflect.Value) {
+ outSize := outType.Size()
+ switch {
+ case outSize == 0:
+ return reflect.New(outType).Elem()
+ case outSize <= 8:
+ if isAllFloats(outType) {
+ // 2 float32s or 1 float64s are return in the float register
+ return reflect.NewAt(outType, unsafe.Pointer(&struct{ a uintptr }{syscall.f1})).Elem()
+ }
+ // up to 8 bytes is returned in RAX
+ return reflect.NewAt(outType, unsafe.Pointer(&struct{ a uintptr }{syscall.a1})).Elem()
+ case outSize <= 16:
+ r1, r2 := syscall.a1, syscall.a2
+ if isAllFloats(outType) {
+ r1 = syscall.f1
+ r2 = syscall.f2
+ } else {
+ // check first 8 bytes if it's floats
+ hasFirstFloat := false
+ f1 := outType.Field(0).Type
+ if f1.Kind() == reflect.Float64 || f1.Kind() == reflect.Float32 && outType.Field(1).Type.Kind() == reflect.Float32 {
+ r1 = syscall.f1
+ hasFirstFloat = true
+ }
+
+ // find index of the field that starts the second 8 bytes
+ var i int
+ for i = 0; i < outType.NumField(); i++ {
+ if outType.Field(i).Offset == 8 {
+ break
+ }
+ }
+
+ // check last 8 bytes if they are floats
+ f1 = outType.Field(i).Type
+ if f1.Kind() == reflect.Float64 || f1.Kind() == reflect.Float32 && i+1 == outType.NumField() {
+ r2 = syscall.f1
+ } else if hasFirstFloat {
+ // if the first field was a float then that means the second integer field
+ // comes from the first integer register
+ r2 = syscall.a1
+ }
+ }
+ return reflect.NewAt(outType, unsafe.Pointer(&struct{ a, b uintptr }{r1, r2})).Elem()
+ default:
+ // create struct from the Go pointer created above
+ // weird pointer dereference to circumvent go vet
+ return reflect.NewAt(outType, *(*unsafe.Pointer)(unsafe.Pointer(&syscall.a1))).Elem()
+ }
+}
+
+func isAllFloats(ty reflect.Type) bool {
+ for i := 0; i < ty.NumField(); i++ {
+ f := ty.Field(i)
+ switch f.Type.Kind() {
+ case reflect.Float64, reflect.Float32:
+ default:
+ return false
+ }
+ }
+ return true
+}
+
+// https://refspecs.linuxbase.org/elf/x86_64-abi-0.99.pdf
+// https://gitlab.com/x86-psABIs/x86-64-ABI
+// Class determines where the 8 byte value goes.
+// Higher value classes win over lower value classes
+const (
+ _NO_CLASS = 0b0000
+ _SSE = 0b0001
+ _X87 = 0b0011 // long double not used in Go
+ _INTEGER = 0b0111
+ _MEMORY = 0b1111
+)
+
+func addStruct(v reflect.Value, numInts, numFloats, numStack *int, addInt, addFloat, addStack func(uintptr), keepAlive []any) []any {
+ if v.Type().Size() == 0 {
+ return keepAlive
+ }
+
+ // if greater than 64 bytes place on stack
+ if v.Type().Size() > 8*8 {
+ placeStack(v, addStack)
+ return keepAlive
+ }
+ var (
+ savedNumFloats = *numFloats
+ savedNumInts = *numInts
+ savedNumStack = *numStack
+ )
+ placeOnStack := postMerger(v.Type()) || !tryPlaceRegister(v, addFloat, addInt)
+ if placeOnStack {
+ // reset any values placed in registers
+ *numFloats = savedNumFloats
+ *numInts = savedNumInts
+ *numStack = savedNumStack
+ placeStack(v, addStack)
+ }
+ return keepAlive
+}
+
+func postMerger(t reflect.Type) (passInMemory bool) {
+ // (c) If the size of the aggregate exceeds two eightbytes and the first eight- byte isn’t SSE or any other
+ // eightbyte isn’t SSEUP, the whole argument is passed in memory.
+ if t.Kind() != reflect.Struct {
+ return false
+ }
+ if t.Size() <= 2*8 {
+ return false
+ }
+ return true // Go does not have an SSE/SSEUP type so this is always true
+}
+
+func tryPlaceRegister(v reflect.Value, addFloat func(uintptr), addInt func(uintptr)) (ok bool) {
+ ok = true
+ var val uint64
+ var shift byte // # of bits to shift
+ var flushed bool
+ class := _NO_CLASS
+ flushIfNeeded := func() {
+ if flushed {
+ return
+ }
+ flushed = true
+ if class == _SSE {
+ addFloat(uintptr(val))
+ } else {
+ addInt(uintptr(val))
+ }
+ val = 0
+ shift = 0
+ class = _NO_CLASS
+ }
+ var place func(v reflect.Value)
+ place = func(v reflect.Value) {
+ var numFields int
+ if v.Kind() == reflect.Struct {
+ numFields = v.Type().NumField()
+ } else {
+ numFields = v.Type().Len()
+ }
+
+ for i := 0; i < numFields; i++ {
+ flushed = false
+ var f reflect.Value
+ if v.Kind() == reflect.Struct {
+ f = v.Field(i)
+ } else {
+ f = v.Index(i)
+ }
+ switch f.Kind() {
+ case reflect.Struct:
+ place(f)
+ case reflect.Bool:
+ if f.Bool() {
+ val |= 1 << shift
+ }
+ shift += 8
+ class |= _INTEGER
+ case reflect.Pointer, reflect.UnsafePointer:
+ val = uint64(f.Pointer())
+ shift = 64
+ class = _INTEGER
+ case reflect.Int8:
+ val |= uint64(f.Int()&0xFF) << shift
+ shift += 8
+ class |= _INTEGER
+ case reflect.Int16:
+ val |= uint64(f.Int()&0xFFFF) << shift
+ shift += 16
+ class |= _INTEGER
+ case reflect.Int32:
+ val |= uint64(f.Int()&0xFFFF_FFFF) << shift
+ shift += 32
+ class |= _INTEGER
+ case reflect.Int64, reflect.Int:
+ val = uint64(f.Int())
+ shift = 64
+ class = _INTEGER
+ case reflect.Uint8:
+ val |= f.Uint() << shift
+ shift += 8
+ class |= _INTEGER
+ case reflect.Uint16:
+ val |= f.Uint() << shift
+ shift += 16
+ class |= _INTEGER
+ case reflect.Uint32:
+ val |= f.Uint() << shift
+ shift += 32
+ class |= _INTEGER
+ case reflect.Uint64, reflect.Uint, reflect.Uintptr:
+ val = f.Uint()
+ shift = 64
+ class = _INTEGER
+ case reflect.Float32:
+ val |= uint64(math.Float32bits(float32(f.Float()))) << shift
+ shift += 32
+ class |= _SSE
+ case reflect.Float64:
+ if v.Type().Size() > 16 {
+ ok = false
+ return
+ }
+ val = uint64(math.Float64bits(f.Float()))
+ shift = 64
+ class = _SSE
+ case reflect.Array:
+ place(f)
+ default:
+ panic("purego: unsupported kind " + f.Kind().String())
+ }
+
+ if shift == 64 {
+ flushIfNeeded()
+ } else if shift > 64 {
+ // Should never happen, but may if we forget to reset shift after flush (or forget to flush),
+ // better fall apart here, than corrupt arguments.
+ panic("purego: tryPlaceRegisters shift > 64")
+ }
+ }
+ }
+
+ place(v)
+ flushIfNeeded()
+ return ok
+}
+
+func placeStack(v reflect.Value, addStack func(uintptr)) {
+ // Copy the struct as a contiguous block of memory in eightbyte (8-byte)
+ // chunks. The x86-64 ABI requires structs passed on the stack to be
+ // laid out exactly as in memory, including padding and field packing
+ // within eightbytes. Decomposing field-by-field would place each field
+ // as a separate stack slot, breaking structs with mixed-type fields
+ // that share an eightbyte (e.g. int32 + float32).
+ if !v.CanAddr() {
+ tmp := reflect.New(v.Type()).Elem()
+ tmp.Set(v)
+ v = tmp
+ }
+ ptr := v.Addr().UnsafePointer()
+ size := v.Type().Size()
+ for off := uintptr(0); off < size; off += 8 {
+ chunk := *(*uintptr)(unsafe.Add(ptr, off))
+ addStack(chunk)
+ }
+}
+
+func placeRegisters(v reflect.Value, addFloat func(uintptr), addInt func(uintptr)) {
+ panic("purego: placeRegisters not implemented on amd64")
+}
+
+// shouldBundleStackArgs always returns false on non-Darwin platforms
+// since C-style stack argument bundling is only needed on Darwin ARM64.
+func shouldBundleStackArgs(v reflect.Value, numInts, numFloats int) bool {
+ return false
+}
+
+// structFitsInRegisters is not used on amd64.
+func structFitsInRegisters(val reflect.Value, tempNumInts, tempNumFloats int) (bool, int, int) {
+ panic("purego: structFitsInRegisters should not be called on amd64")
+}
+
+// collectStackArgs is not used on amd64.
+func collectStackArgs(args []reflect.Value, startIdx int, numInts, numFloats int,
+ keepAlive []any, addInt, addFloat, addStack func(uintptr),
+ pNumInts, pNumFloats, pNumStack *int) ([]reflect.Value, []any) {
+ panic("purego: collectStackArgs should not be called on amd64")
+}
+
+// bundleStackArgs is not used on amd64.
+func bundleStackArgs(stackArgs []reflect.Value, addStack func(uintptr)) {
+ panic("purego: bundleStackArgs should not be called on amd64")
+}
diff --git a/raymenu/vendor/github.com/ebitengine/purego/struct_arm.go b/raymenu/vendor/github.com/ebitengine/purego/struct_arm.go
new file mode 100644
index 0000000..1b58058
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/struct_arm.go
@@ -0,0 +1,85 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2025 The Ebitengine Authors
+
+package purego
+
+import (
+ "reflect"
+ "unsafe"
+)
+
+func addStruct(v reflect.Value, numInts, numFloats, numStack *int, addInt, addFloat, addStack func(uintptr), keepAlive []any) []any {
+ size := v.Type().Size()
+ if size == 0 {
+ return keepAlive
+ }
+
+ // TODO: ARM EABI: small structs are passed in registers or on stack
+ // For simplicity, pass by pointer for now
+ ptr := v.Addr().UnsafePointer()
+ keepAlive = append(keepAlive, ptr)
+ if *numInts < 4 {
+ addInt(uintptr(ptr))
+ *numInts++
+ } else {
+ addStack(uintptr(ptr))
+ *numStack++
+ }
+ return keepAlive
+}
+
+func getStruct(outType reflect.Type, syscall syscall15Args) (v reflect.Value) {
+ outSize := outType.Size()
+ if outSize == 0 {
+ return reflect.New(outType).Elem()
+ }
+ if outSize <= 4 {
+ // Fits in one register
+ return reflect.NewAt(outType, unsafe.Pointer(&struct{ a uintptr }{syscall.a1})).Elem()
+ }
+ if outSize <= 8 {
+ // Fits in two registers
+ return reflect.NewAt(outType, unsafe.Pointer(&struct{ a, b uintptr }{syscall.a1, syscall.a2})).Elem()
+ }
+ // Larger structs returned via pointer in a1
+ return reflect.NewAt(outType, *(*unsafe.Pointer)(unsafe.Pointer(&syscall.a1))).Elem()
+}
+
+func placeRegisters(v reflect.Value, addFloat func(uintptr), addInt func(uintptr)) {
+ // TODO: For ARM32, just pass the struct data directly
+ // This is a simplified implementation
+ size := v.Type().Size()
+ if size == 0 {
+ return
+ }
+ ptr := unsafe.Pointer(v.UnsafeAddr())
+ if size <= 4 {
+ addInt(*(*uintptr)(ptr))
+ } else if size <= 8 {
+ addInt(*(*uintptr)(ptr))
+ addInt(*(*uintptr)(unsafe.Add(ptr, 4)))
+ }
+}
+
+// shouldBundleStackArgs always returns false on arm
+// since C-style stack argument bundling is only needed on Darwin ARM64.
+func shouldBundleStackArgs(v reflect.Value, numInts, numFloats int) bool {
+ return false
+}
+
+// structFitsInRegisters is not used on arm.
+func structFitsInRegisters(val reflect.Value, tempNumInts, tempNumFloats int) (bool, int, int) {
+ panic("purego: structFitsInRegisters should not be called on arm")
+}
+
+// collectStackArgs is not used on arm.
+func collectStackArgs(args []reflect.Value, startIdx int, numInts, numFloats int,
+ keepAlive []any, addInt, addFloat, addStack func(uintptr),
+ pNumInts, pNumFloats, pNumStack *int) ([]reflect.Value, []any) {
+ panic("purego: collectStackArgs should not be called on arm")
+}
+
+// bundleStackArgs is not used on arm.
+func bundleStackArgs(stackArgs []reflect.Value, addStack func(uintptr)) {
+ panic("purego: bundleStackArgs should not be called on arm")
+}
diff --git a/raymenu/vendor/github.com/ebitengine/purego/struct_arm64.go b/raymenu/vendor/github.com/ebitengine/purego/struct_arm64.go
new file mode 100644
index 0000000..5f347c8
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/struct_arm64.go
@@ -0,0 +1,549 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2024 The Ebitengine Authors
+
+package purego
+
+import (
+ "math"
+ "reflect"
+ "runtime"
+ "strconv"
+ stdstrings "strings"
+ "unsafe"
+
+ "github.com/ebitengine/purego/internal/strings"
+)
+
+func getStruct(outType reflect.Type, syscall syscall15Args) (v reflect.Value) {
+ outSize := outType.Size()
+ switch {
+ case outSize == 0:
+ return reflect.New(outType).Elem()
+ case outSize <= 8:
+ r1 := syscall.a1
+ if isAllFloats, numFields := isAllSameFloat(outType); isAllFloats {
+ r1 = syscall.f1
+ if numFields == 2 {
+ r1 = syscall.f2<<32 | syscall.f1
+ }
+ }
+ return reflect.NewAt(outType, unsafe.Pointer(&struct{ a uintptr }{r1})).Elem()
+ case outSize <= 16:
+ r1, r2 := syscall.a1, syscall.a2
+ if isAllFloats, numFields := isAllSameFloat(outType); isAllFloats {
+ switch numFields {
+ case 4:
+ r1 = syscall.f2<<32 | syscall.f1
+ r2 = syscall.f4<<32 | syscall.f3
+ case 3:
+ r1 = syscall.f2<<32 | syscall.f1
+ r2 = syscall.f3
+ case 2:
+ r1 = syscall.f1
+ r2 = syscall.f2
+ default:
+ panic("unreachable")
+ }
+ }
+ return reflect.NewAt(outType, unsafe.Pointer(&struct{ a, b uintptr }{r1, r2})).Elem()
+ default:
+ if isAllFloats, numFields := isAllSameFloat(outType); isAllFloats && numFields <= 4 {
+ switch numFields {
+ case 4:
+ return reflect.NewAt(outType, unsafe.Pointer(&struct{ a, b, c, d uintptr }{syscall.f1, syscall.f2, syscall.f3, syscall.f4})).Elem()
+ case 3:
+ return reflect.NewAt(outType, unsafe.Pointer(&struct{ a, b, c uintptr }{syscall.f1, syscall.f2, syscall.f3})).Elem()
+ default:
+ panic("unreachable")
+ }
+ }
+ // create struct from the Go pointer created in arm64_r8
+ // weird pointer dereference to circumvent go vet
+ return reflect.NewAt(outType, *(*unsafe.Pointer)(unsafe.Pointer(&syscall.arm64_r8))).Elem()
+ }
+}
+
+// https://github.com/ARM-software/abi-aa/blob/main/sysvabi64/sysvabi64.rst
+const (
+ _NO_CLASS = 0b00
+ _FLOAT = 0b01
+ _INT = 0b11
+)
+
+func addStruct(v reflect.Value, numInts, numFloats, numStack *int, addInt, addFloat, addStack func(uintptr), keepAlive []any) []any {
+ if v.Type().Size() == 0 {
+ return keepAlive
+ }
+
+ if hva, hfa, size := isHVA(v.Type()), isHFA(v.Type()), v.Type().Size(); hva || hfa || size <= 16 {
+ // if this doesn't fit entirely in registers then
+ // each element goes onto the stack
+ if hfa && *numFloats+v.NumField() > numOfFloatRegisters() {
+ *numFloats = numOfFloatRegisters()
+ } else if hva && *numInts+v.NumField() > numOfIntegerRegisters() {
+ *numInts = numOfIntegerRegisters()
+ }
+
+ placeRegisters(v, addFloat, addInt)
+ } else {
+ keepAlive = placeStack(v, keepAlive, addInt)
+ }
+ return keepAlive // the struct was allocated so don't panic
+}
+
+func placeRegisters(v reflect.Value, addFloat func(uintptr), addInt func(uintptr)) {
+ if runtime.GOOS == "darwin" {
+ placeRegistersDarwin(v, addFloat, addInt)
+ return
+ }
+ placeRegistersArm64(v, addFloat, addInt)
+}
+
+func placeRegistersArm64(v reflect.Value, addFloat func(uintptr), addInt func(uintptr)) {
+ var val uint64
+ var shift byte
+ var flushed bool
+ class := _NO_CLASS
+ var place func(v reflect.Value)
+ place = func(v reflect.Value) {
+ var numFields int
+ if v.Kind() == reflect.Struct {
+ numFields = v.Type().NumField()
+ } else {
+ numFields = v.Type().Len()
+ }
+ for k := 0; k < numFields; k++ {
+ flushed = false
+ var f reflect.Value
+ if v.Kind() == reflect.Struct {
+ f = v.Field(k)
+ } else {
+ f = v.Index(k)
+ }
+ align := byte(f.Type().Align()*8 - 1)
+ shift = (shift + align) &^ align
+ if shift >= 64 {
+ shift = 0
+ flushed = true
+ if class == _FLOAT {
+ addFloat(uintptr(val))
+ } else {
+ addInt(uintptr(val))
+ }
+ val = 0
+ class = _NO_CLASS
+ }
+ switch f.Type().Kind() {
+ case reflect.Struct:
+ place(f)
+ case reflect.Bool:
+ if f.Bool() {
+ val |= 1 << shift
+ }
+ shift += 8
+ class |= _INT
+ case reflect.Uint8:
+ val |= f.Uint() << shift
+ shift += 8
+ class |= _INT
+ case reflect.Uint16:
+ val |= f.Uint() << shift
+ shift += 16
+ class |= _INT
+ case reflect.Uint32:
+ val |= f.Uint() << shift
+ shift += 32
+ class |= _INT
+ case reflect.Uint64, reflect.Uint, reflect.Uintptr:
+ addInt(uintptr(f.Uint()))
+ shift = 0
+ flushed = true
+ class = _NO_CLASS
+ case reflect.Int8:
+ val |= uint64(f.Int()&0xFF) << shift
+ shift += 8
+ class |= _INT
+ case reflect.Int16:
+ val |= uint64(f.Int()&0xFFFF) << shift
+ shift += 16
+ class |= _INT
+ case reflect.Int32:
+ val |= uint64(f.Int()&0xFFFF_FFFF) << shift
+ shift += 32
+ class |= _INT
+ case reflect.Int64, reflect.Int:
+ addInt(uintptr(f.Int()))
+ shift = 0
+ flushed = true
+ class = _NO_CLASS
+ case reflect.Float32:
+ if class == _FLOAT {
+ addFloat(uintptr(val))
+ val = 0
+ shift = 0
+ }
+ val |= uint64(math.Float32bits(float32(f.Float()))) << shift
+ shift += 32
+ class |= _FLOAT
+ case reflect.Float64:
+ addFloat(uintptr(math.Float64bits(float64(f.Float()))))
+ shift = 0
+ flushed = true
+ class = _NO_CLASS
+ case reflect.Ptr, reflect.UnsafePointer:
+ addInt(f.Pointer())
+ shift = 0
+ flushed = true
+ class = _NO_CLASS
+ case reflect.Array:
+ place(f)
+ default:
+ panic("purego: unsupported kind " + f.Kind().String())
+ }
+ }
+ }
+ place(v)
+ if !flushed {
+ if class == _FLOAT {
+ addFloat(uintptr(val))
+ } else {
+ addInt(uintptr(val))
+ }
+ }
+}
+
+func placeStack(v reflect.Value, keepAlive []any, addInt func(uintptr)) []any {
+ // Struct is too big to be placed in registers.
+ // Copy to heap and place the pointer in register
+ ptrStruct := reflect.New(v.Type())
+ ptrStruct.Elem().Set(v)
+ ptr := ptrStruct.Elem().Addr().UnsafePointer()
+ keepAlive = append(keepAlive, ptr)
+ addInt(uintptr(ptr))
+ return keepAlive
+}
+
+// isHFA reports a Homogeneous Floating-point Aggregate (HFA) which is a Fundamental Data Type that is a
+// Floating-Point type and at most four uniquely addressable members (5.9.5.1 in [Arm64 Calling Convention]).
+// This type of struct will be placed more compactly than the individual fields.
+//
+// [Arm64 Calling Convention]: https://github.com/ARM-software/abi-aa/blob/main/sysvabi64/sysvabi64.rst
+func isHFA(t reflect.Type) bool {
+ // round up struct size to nearest 8 see section B.4
+ structSize := roundUpTo8(t.Size())
+ if structSize == 0 || t.NumField() > 4 {
+ return false
+ }
+ first := t.Field(0)
+ switch first.Type.Kind() {
+ case reflect.Float32, reflect.Float64:
+ firstKind := first.Type.Kind()
+ for i := 0; i < t.NumField(); i++ {
+ if t.Field(i).Type.Kind() != firstKind {
+ return false
+ }
+ }
+ return true
+ case reflect.Array:
+ switch first.Type.Elem().Kind() {
+ case reflect.Float32, reflect.Float64:
+ return true
+ default:
+ return false
+ }
+ case reflect.Struct:
+ for i := 0; i < first.Type.NumField(); i++ {
+ if !isHFA(first.Type) {
+ return false
+ }
+ }
+ return true
+ default:
+ return false
+ }
+}
+
+// isHVA reports a Homogeneous Aggregate with a Fundamental Data Type that is a Short-Vector type
+// and at most four uniquely addressable members (5.9.5.2 in [Arm64 Calling Convention]).
+// A short vector is a machine type that is composed of repeated instances of one fundamental integral or
+// floating-point type. It may be 8 or 16 bytes in total size (5.4 in [Arm64 Calling Convention]).
+// This type of struct will be placed more compactly than the individual fields.
+//
+// [Arm64 Calling Convention]: https://github.com/ARM-software/abi-aa/blob/main/sysvabi64/sysvabi64.rst
+func isHVA(t reflect.Type) bool {
+ // round up struct size to nearest 8 see section B.4
+ structSize := roundUpTo8(t.Size())
+ if structSize == 0 || (structSize != 8 && structSize != 16) {
+ return false
+ }
+ first := t.Field(0)
+ switch first.Type.Kind() {
+ case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Int8, reflect.Int16, reflect.Int32:
+ firstKind := first.Type.Kind()
+ for i := 0; i < t.NumField(); i++ {
+ if t.Field(i).Type.Kind() != firstKind {
+ return false
+ }
+ }
+ return true
+ case reflect.Array:
+ switch first.Type.Elem().Kind() {
+ case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Int8, reflect.Int16, reflect.Int32:
+ return true
+ default:
+ return false
+ }
+ default:
+ return false
+ }
+}
+
+// copyStruct8ByteChunks copies struct memory in 8-byte chunks to the provided callback.
+// This is used for Darwin ARM64's byte-level packing of non-HFA/HVA structs.
+func copyStruct8ByteChunks(ptr unsafe.Pointer, size uintptr, addChunk func(uintptr)) {
+ if runtime.GOOS != "darwin" {
+ panic("purego: should only be called on darwin")
+ }
+ for offset := uintptr(0); offset < size; offset += 8 {
+ var chunk uintptr
+ remaining := size - offset
+ if remaining >= 8 {
+ chunk = *(*uintptr)(unsafe.Add(ptr, offset))
+ } else {
+ // Read byte-by-byte to avoid reading beyond allocation
+ for i := uintptr(0); i < remaining; i++ {
+ b := *(*byte)(unsafe.Add(ptr, offset+i))
+ chunk |= uintptr(b) << (i * 8)
+ }
+ }
+ addChunk(chunk)
+ }
+}
+
+// placeRegisters implements Darwin ARM64 calling convention for struct arguments.
+//
+// For HFA/HVA structs, each element must go in a separate register (or stack slot for elements
+// that don't fit in registers). We use placeRegistersArm64 for this.
+//
+// For non-HFA/HVA structs, Darwin uses byte-level packing. We copy the struct memory in
+// 8-byte chunks, which works correctly for both register and stack placement.
+func placeRegistersDarwin(v reflect.Value, addFloat func(uintptr), addInt func(uintptr)) {
+ if runtime.GOOS != "darwin" {
+ panic("purego: placeRegistersDarwin should only be called on darwin")
+ }
+ // Check if this is an HFA/HVA
+ hfa := isHFA(v.Type())
+ hva := isHVA(v.Type())
+
+ // For HFA/HVA structs, use the standard ARM64 logic which places each element separately
+ if hfa || hva {
+ placeRegistersArm64(v, addFloat, addInt)
+ return
+ }
+
+ // For non-HFA/HVA structs, use byte-level copying
+ // If the value is not addressable, create an addressable copy
+ if !v.CanAddr() {
+ addressable := reflect.New(v.Type()).Elem()
+ addressable.Set(v)
+ v = addressable
+ }
+ ptr := unsafe.Pointer(v.Addr().Pointer())
+ size := v.Type().Size()
+ copyStruct8ByteChunks(ptr, size, addInt)
+}
+
+// shouldBundleStackArgs determines if we need to start C-style packing for
+// Darwin ARM64 stack arguments. This happens when registers are exhausted.
+func shouldBundleStackArgs(v reflect.Value, numInts, numFloats int) bool {
+ if runtime.GOOS != "darwin" {
+ return false
+ }
+
+ kind := v.Kind()
+ isFloat := kind == reflect.Float32 || kind == reflect.Float64
+ isInt := !isFloat && kind != reflect.Struct
+ primitiveOnStack :=
+ (isInt && numInts >= numOfIntegerRegisters()) ||
+ (isFloat && numFloats >= numOfFloatRegisters())
+ if primitiveOnStack {
+ return true
+ }
+ if kind != reflect.Struct {
+ return false
+ }
+ hfa := isHFA(v.Type())
+ hva := isHVA(v.Type())
+ size := v.Type().Size()
+ eligible := hfa || hva || size <= 16
+ if !eligible {
+ return false
+ }
+
+ if hfa {
+ need := v.NumField()
+ return numFloats+need > numOfFloatRegisters()
+ }
+
+ if hva {
+ need := v.NumField()
+ return numInts+need > numOfIntegerRegisters()
+ }
+
+ slotsNeeded := int((size + align8ByteMask) / align8ByteSize)
+ return numInts+slotsNeeded > numOfIntegerRegisters()
+}
+
+// structFitsInRegisters determines if a struct can still fit in remaining
+// registers, used during stack argument bundling to decide if a struct
+// should go through normal register allocation or be bundled with stack args.
+func structFitsInRegisters(val reflect.Value, tempNumInts, tempNumFloats int) (bool, int, int) {
+ if runtime.GOOS != "darwin" {
+ panic("purego: structFitsInRegisters should only be called on darwin")
+ }
+ hfa := isHFA(val.Type())
+ hva := isHVA(val.Type())
+ size := val.Type().Size()
+
+ if hfa {
+ // HFA: check if elements fit in float registers
+ if tempNumFloats+val.NumField() <= numOfFloatRegisters() {
+ return true, tempNumInts, tempNumFloats + val.NumField()
+ }
+ } else if hva {
+ // HVA: check if elements fit in int registers
+ if tempNumInts+val.NumField() <= numOfIntegerRegisters() {
+ return true, tempNumInts + val.NumField(), tempNumFloats
+ }
+ } else if size <= 16 {
+ // Non-HFA/HVA small structs use int registers for byte-packing
+ slotsNeeded := int((size + align8ByteMask) / align8ByteSize)
+ if tempNumInts+slotsNeeded <= numOfIntegerRegisters() {
+ return true, tempNumInts + slotsNeeded, tempNumFloats
+ }
+ }
+
+ return false, tempNumInts, tempNumFloats
+}
+
+// collectStackArgs separates remaining arguments into those that fit in registers vs those that go on stack.
+// It returns the stack arguments and processes register arguments through addValue.
+func collectStackArgs(args []reflect.Value, startIdx int, numInts, numFloats int,
+ keepAlive []any, addInt, addFloat, addStack func(uintptr),
+ pNumInts, pNumFloats, pNumStack *int) ([]reflect.Value, []any) {
+ if runtime.GOOS != "darwin" {
+ panic("purego: collectStackArgs should only be called on darwin")
+ }
+
+ var stackArgs []reflect.Value
+ tempNumInts := numInts
+ tempNumFloats := numFloats
+
+ for j, val := range args[startIdx:] {
+ // Determine if this argument goes to register or stack
+ var fitsInRegister bool
+ var newNumInts, newNumFloats int
+
+ if val.Kind() == reflect.Struct {
+ // Check if struct still fits in remaining registers
+ fitsInRegister, newNumInts, newNumFloats = structFitsInRegisters(val, tempNumInts, tempNumFloats)
+ } else {
+ // Primitive argument
+ isFloat := val.Kind() == reflect.Float32 || val.Kind() == reflect.Float64
+ if isFloat {
+ fitsInRegister = tempNumFloats < numOfFloatRegisters()
+ newNumFloats = tempNumFloats + 1
+ newNumInts = tempNumInts
+ } else {
+ fitsInRegister = tempNumInts < numOfIntegerRegisters()
+ newNumInts = tempNumInts + 1
+ newNumFloats = tempNumFloats
+ }
+ }
+
+ if fitsInRegister {
+ // Process through normal register allocation
+ tempNumInts = newNumInts
+ tempNumFloats = newNumFloats
+ keepAlive = addValue(val, keepAlive, addInt, addFloat, addStack, pNumInts, pNumFloats, pNumStack)
+ } else {
+ // Convert strings to C strings before bundling
+ if val.Kind() == reflect.String {
+ ptr := strings.CString(val.String())
+ keepAlive = append(keepAlive, ptr)
+ val = reflect.ValueOf(ptr)
+ args[startIdx+j] = val
+ }
+ stackArgs = append(stackArgs, val)
+ }
+ }
+
+ return stackArgs, keepAlive
+}
+
+const (
+ paddingFieldPrefix = "Pad"
+)
+
+// bundleStackArgs bundles remaining arguments for Darwin ARM64 C-style stack packing.
+// It creates a packed struct with proper alignment and copies it to the stack in 8-byte chunks.
+func bundleStackArgs(stackArgs []reflect.Value, addStack func(uintptr)) {
+ if runtime.GOOS != "darwin" {
+ panic("purego: bundleStackArgs should only be called on darwin")
+ }
+ if len(stackArgs) == 0 {
+ return
+ }
+
+ // Build struct fields with proper C alignment and padding
+ var fields []reflect.StructField
+ currentOffset := uintptr(0)
+ fieldIndex := 0
+
+ for j, val := range stackArgs {
+ valSize := val.Type().Size()
+ valAlign := val.Type().Align()
+
+ // ARM64 requires 8-byte alignment for 8-byte or larger structs
+ if val.Kind() == reflect.Struct && valSize >= 8 {
+ valAlign = 8
+ }
+
+ // Add padding field if needed for alignment
+ if currentOffset%uintptr(valAlign) != 0 {
+ paddingNeeded := uintptr(valAlign) - (currentOffset % uintptr(valAlign))
+ fields = append(fields, reflect.StructField{
+ Name: paddingFieldPrefix + strconv.Itoa(fieldIndex),
+ Type: reflect.ArrayOf(int(paddingNeeded), reflect.TypeOf(byte(0))),
+ })
+ currentOffset += paddingNeeded
+ fieldIndex++
+ }
+
+ fields = append(fields, reflect.StructField{
+ Name: "X" + strconv.Itoa(j),
+ Type: val.Type(),
+ })
+ currentOffset += valSize
+ fieldIndex++
+ }
+
+ // Create and populate the packed struct
+ structType := reflect.StructOf(fields)
+ structInstance := reflect.New(structType).Elem()
+
+ // Set values (skip padding fields)
+ argIndex := 0
+ for j := 0; j < structInstance.NumField(); j++ {
+ fieldName := structType.Field(j).Name
+ if stdstrings.HasPrefix(fieldName, paddingFieldPrefix) {
+ continue
+ }
+ structInstance.Field(j).Set(stackArgs[argIndex])
+ argIndex++
+ }
+
+ ptr := unsafe.Pointer(structInstance.Addr().Pointer())
+ size := structType.Size()
+ copyStruct8ByteChunks(ptr, size, addStack)
+}
diff --git a/raymenu/vendor/github.com/ebitengine/purego/struct_loong64.go b/raymenu/vendor/github.com/ebitengine/purego/struct_loong64.go
new file mode 100644
index 0000000..e589140
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/struct_loong64.go
@@ -0,0 +1,213 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2025 The Ebitengine Authors
+
+package purego
+
+import (
+ "math"
+ "reflect"
+ "unsafe"
+)
+
+func getStruct(outType reflect.Type, syscall syscall15Args) (v reflect.Value) {
+ outSize := outType.Size()
+ switch {
+ case outSize == 0:
+ return reflect.New(outType).Elem()
+ case outSize <= 8:
+ r1 := syscall.a1
+ if isAllFloats, numFields := isAllSameFloat(outType); isAllFloats {
+ r1 = syscall.f1
+ if numFields == 2 {
+ r1 = syscall.f2<<32 | syscall.f1
+ }
+ }
+ return reflect.NewAt(outType, unsafe.Pointer(&struct{ a uintptr }{r1})).Elem()
+ case outSize <= 16:
+ r1, r2 := syscall.a1, syscall.a2
+ if isAllFloats, numFields := isAllSameFloat(outType); isAllFloats {
+ switch numFields {
+ case 4:
+ r1 = syscall.f2<<32 | syscall.f1
+ r2 = syscall.f4<<32 | syscall.f3
+ case 3:
+ r1 = syscall.f2<<32 | syscall.f1
+ r2 = syscall.f3
+ case 2:
+ r1 = syscall.f1
+ r2 = syscall.f2
+ default:
+ panic("unreachable")
+ }
+ }
+ return reflect.NewAt(outType, unsafe.Pointer(&struct{ a, b uintptr }{r1, r2})).Elem()
+ default:
+ // create struct from the Go pointer created above
+ // weird pointer dereference to circumvent go vet
+ return reflect.NewAt(outType, *(*unsafe.Pointer)(unsafe.Pointer(&syscall.a1))).Elem()
+ }
+}
+
+const (
+ _NO_CLASS = 0b00
+ _FLOAT = 0b01
+ _INT = 0b11
+)
+
+func addStruct(v reflect.Value, numInts, numFloats, numStack *int, addInt, addFloat, addStack func(uintptr), keepAlive []any) []any {
+ if v.Type().Size() == 0 {
+ return keepAlive
+ }
+
+ if size := v.Type().Size(); size <= 16 {
+ placeRegisters(v, addFloat, addInt)
+ } else {
+ keepAlive = placeStack(v, keepAlive, addInt)
+ }
+ return keepAlive // the struct was allocated so don't panic
+}
+
+func placeRegisters(v reflect.Value, addFloat func(uintptr), addInt func(uintptr)) {
+ var val uint64
+ var shift byte
+ var flushed bool
+ class := _NO_CLASS
+ var place func(v reflect.Value)
+ place = func(v reflect.Value) {
+ var numFields int
+ if v.Kind() == reflect.Struct {
+ numFields = v.Type().NumField()
+ } else {
+ numFields = v.Type().Len()
+ }
+ for k := 0; k < numFields; k++ {
+ flushed = false
+ var f reflect.Value
+ if v.Kind() == reflect.Struct {
+ f = v.Field(k)
+ } else {
+ f = v.Index(k)
+ }
+ align := byte(f.Type().Align()*8 - 1)
+ shift = (shift + align) &^ align
+ if shift >= 64 {
+ shift = 0
+ flushed = true
+ if class == _FLOAT {
+ addFloat(uintptr(val))
+ } else {
+ addInt(uintptr(val))
+ }
+ }
+ switch f.Type().Kind() {
+ case reflect.Struct:
+ place(f)
+ case reflect.Bool:
+ if f.Bool() {
+ val |= 1 << shift
+ }
+ shift += 8
+ class |= _INT
+ case reflect.Uint8:
+ val |= f.Uint() << shift
+ shift += 8
+ class |= _INT
+ case reflect.Uint16:
+ val |= f.Uint() << shift
+ shift += 16
+ class |= _INT
+ case reflect.Uint32:
+ val |= f.Uint() << shift
+ shift += 32
+ class |= _INT
+ case reflect.Uint64, reflect.Uint, reflect.Uintptr:
+ addInt(uintptr(f.Uint()))
+ shift = 0
+ flushed = true
+ class = _NO_CLASS
+ case reflect.Int8:
+ val |= uint64(f.Int()&0xFF) << shift
+ shift += 8
+ class |= _INT
+ case reflect.Int16:
+ val |= uint64(f.Int()&0xFFFF) << shift
+ shift += 16
+ class |= _INT
+ case reflect.Int32:
+ val |= uint64(f.Int()&0xFFFF_FFFF) << shift
+ shift += 32
+ class |= _INT
+ case reflect.Int64, reflect.Int:
+ addInt(uintptr(f.Int()))
+ shift = 0
+ flushed = true
+ class = _NO_CLASS
+ case reflect.Float32:
+ if class == _FLOAT {
+ addFloat(uintptr(val))
+ val = 0
+ shift = 0
+ }
+ val |= uint64(math.Float32bits(float32(f.Float()))) << shift
+ shift += 32
+ class |= _FLOAT
+ case reflect.Float64:
+ addFloat(uintptr(math.Float64bits(float64(f.Float()))))
+ shift = 0
+ flushed = true
+ class = _NO_CLASS
+ case reflect.Ptr, reflect.UnsafePointer:
+ addInt(f.Pointer())
+ shift = 0
+ flushed = true
+ class = _NO_CLASS
+ case reflect.Array:
+ place(f)
+ default:
+ panic("purego: unsupported kind " + f.Kind().String())
+ }
+ }
+ }
+ place(v)
+ if !flushed {
+ if class == _FLOAT {
+ addFloat(uintptr(val))
+ } else {
+ addInt(uintptr(val))
+ }
+ }
+}
+
+func placeStack(v reflect.Value, keepAlive []any, addInt func(uintptr)) []any {
+ // Struct is too big to be placed in registers.
+ // Copy to heap and place the pointer in register
+ ptrStruct := reflect.New(v.Type())
+ ptrStruct.Elem().Set(v)
+ ptr := ptrStruct.Elem().Addr().UnsafePointer()
+ keepAlive = append(keepAlive, ptr)
+ addInt(uintptr(ptr))
+ return keepAlive
+}
+
+// shouldBundleStackArgs always returns false on loong64
+// since C-style stack argument bundling is only needed on Darwin ARM64.
+func shouldBundleStackArgs(v reflect.Value, numInts, numFloats int) bool {
+ return false
+}
+
+// structFitsInRegisters is not used on loong64.
+func structFitsInRegisters(val reflect.Value, tempNumInts, tempNumFloats int) (bool, int, int) {
+ panic("purego: structFitsInRegisters should not be called on loong64")
+}
+
+// collectStackArgs is not used on loong64.
+func collectStackArgs(args []reflect.Value, startIdx int, numInts, numFloats int,
+ keepAlive []any, addInt, addFloat, addStack func(uintptr),
+ pNumInts, pNumFloats, pNumStack *int) ([]reflect.Value, []any) {
+ panic("purego: collectStackArgs should not be called on loong64")
+}
+
+// bundleStackArgs is not used on loong64.
+func bundleStackArgs(stackArgs []reflect.Value, addStack func(uintptr)) {
+ panic("purego: bundleStackArgs should not be called on loong64")
+}
diff --git a/raymenu/vendor/github.com/ebitengine/purego/struct_ppc64le.go b/raymenu/vendor/github.com/ebitengine/purego/struct_ppc64le.go
new file mode 100644
index 0000000..7c50dcb
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/struct_ppc64le.go
@@ -0,0 +1,143 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2026 The Ebitengine Authors
+
+package purego
+
+import (
+ "reflect"
+ "unsafe"
+)
+
+func getStruct(outType reflect.Type, syscall syscall15Args) reflect.Value {
+ outSize := outType.Size()
+
+ switch {
+ case outSize == 0:
+ return reflect.New(outType).Elem()
+
+ case outSize <= 16:
+ // Reconstruct from registers by copying raw bytes
+ var buf [16]byte
+
+ // Integer registers
+ *(*uintptr)(unsafe.Pointer(&buf[0])) = syscall.a1
+ if outSize > 8 {
+ *(*uintptr)(unsafe.Pointer(&buf[8])) = syscall.a2
+ }
+
+ // Homogeneous float aggregates override integer regs
+ if isAllFloats, numFields := isAllSameFloat(outType); isAllFloats {
+ if outType.Field(0).Type.Kind() == reflect.Float32 {
+ // float32 values in FP regs
+ f := []uintptr{syscall.f1, syscall.f2, syscall.f3, syscall.f4}
+ for i := 0; i < numFields; i++ {
+ *(*uint32)(unsafe.Pointer(&buf[i*4])) = uint32(f[i])
+ }
+ } else {
+ // float64: whole register value is valid
+ *(*uintptr)(unsafe.Pointer(&buf[0])) = syscall.f1
+ if outSize > 8 {
+ *(*uintptr)(unsafe.Pointer(&buf[8])) = syscall.f2
+ }
+ }
+ }
+
+ return reflect.NewAt(outType, unsafe.Pointer(&buf[0])).Elem()
+
+ default:
+ // Returned indirectly via pointer in a1
+ ptr := *(*unsafe.Pointer)(unsafe.Pointer(&syscall.a1))
+ return reflect.NewAt(outType, ptr).Elem()
+ }
+}
+
+func addStruct(
+ v reflect.Value,
+ numInts, numFloats, numStack *int,
+ addInt, addFloat, addStack func(uintptr),
+ keepAlive []any,
+) []any {
+ size := v.Type().Size()
+ if size == 0 {
+ return keepAlive
+ }
+
+ if size <= 16 {
+ return placeSmallAggregatePPC64LE(v, addFloat, addInt, keepAlive)
+ }
+
+ return placeStack(v, keepAlive, addInt)
+}
+
+func placeSmallAggregatePPC64LE(
+ v reflect.Value,
+ addFloat, addInt func(uintptr),
+ keepAlive []any,
+) []any {
+ size := v.Type().Size()
+
+ var ptr unsafe.Pointer
+ if v.CanAddr() {
+ ptr = v.Addr().UnsafePointer()
+ } else {
+ tmp := reflect.New(v.Type())
+ tmp.Elem().Set(v)
+ ptr = tmp.UnsafePointer()
+ keepAlive = append(keepAlive, tmp.Interface())
+ }
+
+ var buf [16]byte
+ src := unsafe.Slice((*byte)(ptr), size)
+ copy(buf[:], src)
+
+ w0 := *(*uintptr)(unsafe.Pointer(&buf[0]))
+ w1 := uintptr(0)
+ if size > 8 {
+ w1 = *(*uintptr)(unsafe.Pointer(&buf[8]))
+ }
+
+ if isFloats, _ := isAllSameFloat(v.Type()); isFloats {
+ addFloat(w0)
+ if size > 8 {
+ addFloat(w1)
+ }
+ } else {
+ addInt(w0)
+ if size > 8 {
+ addInt(w1)
+ }
+ }
+
+ return keepAlive
+}
+
+// placeStack is a fallback for structs that are too large to fit in registers
+func placeStack(v reflect.Value, keepAlive []any, addInt func(uintptr)) []any {
+ if v.CanAddr() {
+ addInt(v.Addr().Pointer())
+ return keepAlive
+ }
+ ptr := reflect.New(v.Type())
+ ptr.Elem().Set(v)
+ addInt(ptr.Pointer())
+ return append(keepAlive, ptr.Interface())
+}
+
+func shouldBundleStackArgs(v reflect.Value, numInts, numFloats int) bool {
+ // PPC64LE does not bundle stack args
+ return false
+}
+
+func collectStackArgs(
+ args []reflect.Value,
+ i, numInts, numFloats int,
+ keepAlive []any,
+ addInt, addFloat, addStack func(uintptr),
+ numIntsPtr, numFloatsPtr, numStackPtr *int,
+) ([]reflect.Value, []any) {
+ return nil, keepAlive
+}
+
+func bundleStackArgs(stackArgs []reflect.Value, addStack func(uintptr)) {
+ panic("bundleStackArgs not supported on PPC64LE")
+}
diff --git a/raymenu/vendor/github.com/ebitengine/purego/struct_riscv64.go b/raymenu/vendor/github.com/ebitengine/purego/struct_riscv64.go
new file mode 100644
index 0000000..eac0b88
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/struct_riscv64.go
@@ -0,0 +1,143 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2026 The Ebitengine Authors
+
+package purego
+
+import (
+ "reflect"
+ "unsafe"
+)
+
+func getStruct(outType reflect.Type, syscall syscall15Args) reflect.Value {
+ outSize := outType.Size()
+
+ switch {
+ case outSize == 0:
+ return reflect.New(outType).Elem()
+
+ case outSize <= 16:
+ // Reconstruct from registers by copying raw bytes
+ var buf [16]byte
+
+ // Integer registers
+ *(*uintptr)(unsafe.Pointer(&buf[0])) = syscall.a1
+ if outSize > 8 {
+ *(*uintptr)(unsafe.Pointer(&buf[8])) = syscall.a2
+ }
+
+ // Homogeneous float aggregates override integer regs
+ if isAllFloats, numFields := isAllSameFloat(outType); isAllFloats {
+ if outType.Field(0).Type.Kind() == reflect.Float32 {
+ // float32 values are NaN-boxed in FP regs; use low 32 bits only
+ f := []uintptr{syscall.f1, syscall.f2, syscall.f3, syscall.f4}
+ for i := 0; i < numFields; i++ {
+ *(*uint32)(unsafe.Pointer(&buf[i*4])) = uint32(f[i])
+ }
+ } else {
+ // float64: whole register value is valid
+ *(*uintptr)(unsafe.Pointer(&buf[0])) = syscall.f1
+ if outSize > 8 {
+ *(*uintptr)(unsafe.Pointer(&buf[8])) = syscall.f2
+ }
+ }
+ }
+
+ return reflect.NewAt(outType, unsafe.Pointer(&buf[0])).Elem()
+
+ default:
+ // Returned indirectly via pointer in a1
+ ptr := *(*unsafe.Pointer)(unsafe.Pointer(&syscall.a1))
+ return reflect.NewAt(outType, ptr).Elem()
+ }
+}
+
+func addStruct(
+ v reflect.Value,
+ numInts, numFloats, numStack *int,
+ addInt, addFloat, addStack func(uintptr),
+ keepAlive []any,
+) []any {
+ size := v.Type().Size()
+ if size == 0 {
+ return keepAlive
+ }
+
+ if size <= 16 {
+ return placeSmallAggregateRISCV64(v, addFloat, addInt, keepAlive)
+ }
+
+ return placeStack(v, keepAlive, addInt)
+}
+
+func placeSmallAggregateRISCV64(
+ v reflect.Value,
+ addFloat, addInt func(uintptr),
+ keepAlive []any,
+) []any {
+ size := v.Type().Size()
+
+ var ptr unsafe.Pointer
+ if v.CanAddr() {
+ ptr = v.Addr().UnsafePointer()
+ } else {
+ tmp := reflect.New(v.Type())
+ tmp.Elem().Set(v)
+ ptr = tmp.UnsafePointer()
+ keepAlive = append(keepAlive, tmp.Interface())
+ }
+
+ var buf [16]byte
+ src := unsafe.Slice((*byte)(ptr), size)
+ copy(buf[:], src)
+
+ w0 := *(*uintptr)(unsafe.Pointer(&buf[0]))
+ w1 := uintptr(0)
+ if size > 8 {
+ w1 = *(*uintptr)(unsafe.Pointer(&buf[8]))
+ }
+
+ if isFloats, _ := isAllSameFloat(v.Type()); isFloats {
+ addFloat(w0)
+ if size > 8 {
+ addFloat(w1)
+ }
+ } else {
+ addInt(w0)
+ if size > 8 {
+ addInt(w1)
+ }
+ }
+
+ return keepAlive
+}
+
+// placeStack is a fallback for structs that are too large to fit in registers
+func placeStack(v reflect.Value, keepAlive []any, addInt func(uintptr)) []any {
+ if v.CanAddr() {
+ addInt(v.Addr().Pointer())
+ return keepAlive
+ }
+ ptr := reflect.New(v.Type())
+ ptr.Elem().Set(v)
+ addInt(ptr.Pointer())
+ return append(keepAlive, ptr.Interface())
+}
+
+func shouldBundleStackArgs(v reflect.Value, numInts, numFloats int) bool {
+ // RISCV64 does not bundle stack args
+ return false
+}
+
+func collectStackArgs(
+ args []reflect.Value,
+ i, numInts, numFloats int,
+ keepAlive []any,
+ addInt, addFloat, addStack func(uintptr),
+ numIntsPtr, numFloatsPtr, numStackPtr *int,
+) ([]reflect.Value, []any) {
+ return nil, keepAlive
+}
+
+func bundleStackArgs(stackArgs []reflect.Value, addStack func(uintptr)) {
+ panic("bundleStackArgs not supported on RISCV64")
+}
diff --git a/raymenu/vendor/github.com/ebitengine/purego/struct_s390x.go b/raymenu/vendor/github.com/ebitengine/purego/struct_s390x.go
new file mode 100644
index 0000000..7ec5e81
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/struct_s390x.go
@@ -0,0 +1,143 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2026 The Ebitengine Authors
+
+package purego
+
+import (
+ "reflect"
+ "unsafe"
+)
+
+func getStruct(outType reflect.Type, syscall syscall15Args) reflect.Value {
+ outSize := outType.Size()
+
+ switch {
+ case outSize == 0:
+ return reflect.New(outType).Elem()
+
+ case outSize <= 16:
+ // Reconstruct from registers by copying raw bytes
+ var buf [16]byte
+
+ // Integer registers
+ *(*uintptr)(unsafe.Pointer(&buf[0])) = syscall.a1
+ if outSize > 8 {
+ *(*uintptr)(unsafe.Pointer(&buf[8])) = syscall.a2
+ }
+
+ // Homogeneous float aggregates override integer regs
+ if isAllFloats, numFields := isAllSameFloat(outType); isAllFloats {
+ if outType.Field(0).Type.Kind() == reflect.Float32 {
+ // float32 values in FP regs
+ f := []uintptr{syscall.f1, syscall.f2, syscall.f3, syscall.f4}
+ for i := 0; i < numFields; i++ {
+ *(*uint32)(unsafe.Pointer(&buf[i*4])) = uint32(f[i])
+ }
+ } else {
+ // float64: whole register value is valid
+ *(*uintptr)(unsafe.Pointer(&buf[0])) = syscall.f1
+ if outSize > 8 {
+ *(*uintptr)(unsafe.Pointer(&buf[8])) = syscall.f2
+ }
+ }
+ }
+
+ return reflect.NewAt(outType, unsafe.Pointer(&buf[0])).Elem()
+
+ default:
+ // Returned indirectly via pointer in a1
+ ptr := *(*unsafe.Pointer)(unsafe.Pointer(&syscall.a1))
+ return reflect.NewAt(outType, ptr).Elem()
+ }
+}
+
+func addStruct(
+ v reflect.Value,
+ numInts, numFloats, numStack *int,
+ addInt, addFloat, addStack func(uintptr),
+ keepAlive []any,
+) []any {
+ size := v.Type().Size()
+ if size == 0 {
+ return keepAlive
+ }
+
+ if size <= 16 {
+ return placeSmallAggregateS390X(v, addFloat, addInt, keepAlive)
+ }
+
+ return placeStack(v, keepAlive, addInt)
+}
+
+func placeSmallAggregateS390X(
+ v reflect.Value,
+ addFloat, addInt func(uintptr),
+ keepAlive []any,
+) []any {
+ size := v.Type().Size()
+
+ var ptr unsafe.Pointer
+ if v.CanAddr() {
+ ptr = v.Addr().UnsafePointer()
+ } else {
+ tmp := reflect.New(v.Type())
+ tmp.Elem().Set(v)
+ ptr = tmp.UnsafePointer()
+ keepAlive = append(keepAlive, tmp.Interface())
+ }
+
+ var buf [16]byte
+ src := unsafe.Slice((*byte)(ptr), size)
+ copy(buf[:], src)
+
+ w0 := *(*uintptr)(unsafe.Pointer(&buf[0]))
+ w1 := uintptr(0)
+ if size > 8 {
+ w1 = *(*uintptr)(unsafe.Pointer(&buf[8]))
+ }
+
+ if isFloats, _ := isAllSameFloat(v.Type()); isFloats {
+ addFloat(w0)
+ if size > 8 {
+ addFloat(w1)
+ }
+ } else {
+ addInt(w0)
+ if size > 8 {
+ addInt(w1)
+ }
+ }
+
+ return keepAlive
+}
+
+// placeStack is a fallback for structs that are too large to fit in registers
+func placeStack(v reflect.Value, keepAlive []any, addInt func(uintptr)) []any {
+ if v.CanAddr() {
+ addInt(v.Addr().Pointer())
+ return keepAlive
+ }
+ ptr := reflect.New(v.Type())
+ ptr.Elem().Set(v)
+ addInt(ptr.Pointer())
+ return append(keepAlive, ptr.Interface())
+}
+
+func shouldBundleStackArgs(v reflect.Value, numInts, numFloats int) bool {
+ // S390X does not bundle stack args
+ return false
+}
+
+func collectStackArgs(
+ args []reflect.Value,
+ i, numInts, numFloats int,
+ keepAlive []any,
+ addInt, addFloat, addStack func(uintptr),
+ numIntsPtr, numFloatsPtr, numStackPtr *int,
+) ([]reflect.Value, []any) {
+ return nil, keepAlive
+}
+
+func bundleStackArgs(stackArgs []reflect.Value, addStack func(uintptr)) {
+ panic("bundleStackArgs not supported on S390X")
+}
diff --git a/raymenu/vendor/github.com/ebitengine/purego/sys_386.s b/raymenu/vendor/github.com/ebitengine/purego/sys_386.s
new file mode 100644
index 0000000..8293141
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/sys_386.s
@@ -0,0 +1,147 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2026 The Ebitengine Authors
+
+//go:build linux
+
+#include "textflag.h"
+#include "go_asm.h"
+#include "funcdata.h"
+
+#define STACK_SIZE 160
+#define PTR_ADDRESS (STACK_SIZE - 4)
+
+// syscall15X calls a function in libc on behalf of the syscall package.
+// syscall15X takes a pointer to a struct like:
+// struct {
+// fn uintptr
+// a1 uintptr
+// ...
+// a32 uintptr
+// f1 uintptr
+// ...
+// f16 uintptr
+// arm64_r8 uintptr
+// }
+// syscall15X must be called on the g0 stack with the
+// C calling convention (use libcCall).
+//
+// On i386 System V ABI, all arguments are passed on the stack.
+// Return value is in EAX (and EDX for 64-bit values).
+GLOBL ·syscall15XABI0(SB), NOPTR|RODATA, $4
+DATA ·syscall15XABI0(SB)/4, $syscall15X(SB)
+TEXT syscall15X(SB), NOSPLIT|NOFRAME, $0-0
+ // Called via C calling convention: argument pointer at 4(SP)
+ // NOT via Go calling convention
+ // On i386, the first argument is at 4(SP) after CALL pushes return address
+ MOVL 4(SP), AX // get pointer to syscall15Args
+
+ // Save callee-saved registers
+ PUSHL BP
+ PUSHL BX
+ PUSHL SI
+ PUSHL DI
+
+ MOVL AX, BX // save args pointer in BX
+
+ // Allocate stack space for C function arguments
+ // i386 SysV: all 32 args on stack = 32 * 4 = 128 bytes
+ // Plus 16 bytes for alignment and local storage
+ SUBL $STACK_SIZE, SP
+ MOVL BX, PTR_ADDRESS(SP) // save args pointer
+
+ // Load function pointer
+ MOVL syscall15Args_fn(BX), AX
+ MOVL AX, (PTR_ADDRESS-4)(SP) // save fn pointer
+
+ // Push all integer arguments onto the stack (a1-a32)
+ // i386 SysV ABI: arguments pushed right-to-left, but we're
+ // setting up the stack from low to high addresses
+ MOVL syscall15Args_a1(BX), AX
+ MOVL AX, 0(SP)
+ MOVL syscall15Args_a2(BX), AX
+ MOVL AX, 4(SP)
+ MOVL syscall15Args_a3(BX), AX
+ MOVL AX, 8(SP)
+ MOVL syscall15Args_a4(BX), AX
+ MOVL AX, 12(SP)
+ MOVL syscall15Args_a5(BX), AX
+ MOVL AX, 16(SP)
+ MOVL syscall15Args_a6(BX), AX
+ MOVL AX, 20(SP)
+ MOVL syscall15Args_a7(BX), AX
+ MOVL AX, 24(SP)
+ MOVL syscall15Args_a8(BX), AX
+ MOVL AX, 28(SP)
+ MOVL syscall15Args_a9(BX), AX
+ MOVL AX, 32(SP)
+ MOVL syscall15Args_a10(BX), AX
+ MOVL AX, 36(SP)
+ MOVL syscall15Args_a11(BX), AX
+ MOVL AX, 40(SP)
+ MOVL syscall15Args_a12(BX), AX
+ MOVL AX, 44(SP)
+ MOVL syscall15Args_a13(BX), AX
+ MOVL AX, 48(SP)
+ MOVL syscall15Args_a14(BX), AX
+ MOVL AX, 52(SP)
+ MOVL syscall15Args_a15(BX), AX
+ MOVL AX, 56(SP)
+ MOVL syscall15Args_a16(BX), AX
+ MOVL AX, 60(SP)
+ MOVL syscall15Args_a17(BX), AX
+ MOVL AX, 64(SP)
+ MOVL syscall15Args_a18(BX), AX
+ MOVL AX, 68(SP)
+ MOVL syscall15Args_a19(BX), AX
+ MOVL AX, 72(SP)
+ MOVL syscall15Args_a20(BX), AX
+ MOVL AX, 76(SP)
+ MOVL syscall15Args_a21(BX), AX
+ MOVL AX, 80(SP)
+ MOVL syscall15Args_a22(BX), AX
+ MOVL AX, 84(SP)
+ MOVL syscall15Args_a23(BX), AX
+ MOVL AX, 88(SP)
+ MOVL syscall15Args_a24(BX), AX
+ MOVL AX, 92(SP)
+ MOVL syscall15Args_a25(BX), AX
+ MOVL AX, 96(SP)
+ MOVL syscall15Args_a26(BX), AX
+ MOVL AX, 100(SP)
+ MOVL syscall15Args_a27(BX), AX
+ MOVL AX, 104(SP)
+ MOVL syscall15Args_a28(BX), AX
+ MOVL AX, 108(SP)
+ MOVL syscall15Args_a29(BX), AX
+ MOVL AX, 112(SP)
+ MOVL syscall15Args_a30(BX), AX
+ MOVL AX, 116(SP)
+ MOVL syscall15Args_a31(BX), AX
+ MOVL AX, 120(SP)
+ MOVL syscall15Args_a32(BX), AX
+ MOVL AX, 124(SP)
+
+ // Call the C function
+ MOVL (PTR_ADDRESS-4)(SP), AX
+ CALL AX
+
+ // Get args pointer back and save results
+ MOVL PTR_ADDRESS(SP), BX
+ MOVL AX, syscall15Args_a1(BX) // return value r1
+ MOVL DX, syscall15Args_a2(BX) // return value r2 (for 64-bit returns)
+
+ // Save x87 FPU return value (ST0) to f1 field
+ // On i386 System V ABI, float/double returns are in ST(0)
+ // We save as float64 (8 bytes) to preserve precision
+ FMOVDP F0, syscall15Args_f1(BX)
+
+ // Clean up stack
+ ADDL $STACK_SIZE, SP
+
+ // Restore callee-saved registers
+ POPL DI
+ POPL SI
+ POPL BX
+ POPL BP
+
+ RET
diff --git a/raymenu/vendor/github.com/ebitengine/purego/sys_amd64.s b/raymenu/vendor/github.com/ebitengine/purego/sys_amd64.s
new file mode 100644
index 0000000..15b24dd
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/sys_amd64.s
@@ -0,0 +1,170 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
+
+//go:build darwin || freebsd || linux || netbsd
+
+#include "textflag.h"
+#include "abi_amd64.h"
+#include "go_asm.h"
+#include "funcdata.h"
+
+#define STACK_SIZE 80
+#define PTR_ADDRESS (STACK_SIZE - 8)
+
+// syscall15X calls a function in libc on behalf of the syscall package.
+// syscall15X takes a pointer to a struct like:
+// struct {
+// fn uintptr
+// a1 uintptr
+// a2 uintptr
+// a3 uintptr
+// a4 uintptr
+// a5 uintptr
+// a6 uintptr
+// a7 uintptr
+// a8 uintptr
+// a9 uintptr
+// a10 uintptr
+// a11 uintptr
+// a12 uintptr
+// a13 uintptr
+// a14 uintptr
+// a15 uintptr
+// r1 uintptr
+// r2 uintptr
+// err uintptr
+// }
+// syscall15X must be called on the g0 stack with the
+// C calling convention (use libcCall).
+GLOBL ·syscall15XABI0(SB), NOPTR|RODATA, $8
+DATA ·syscall15XABI0(SB)/8, $syscall15X(SB)
+TEXT syscall15X(SB), NOSPLIT|NOFRAME, $0
+ PUSHQ BP
+ MOVQ SP, BP
+ SUBQ $STACK_SIZE, SP
+ MOVQ DI, PTR_ADDRESS(BP) // save the pointer
+ MOVQ DI, R11
+
+ MOVQ syscall15Args_f1(R11), X0 // f1
+ MOVQ syscall15Args_f2(R11), X1 // f2
+ MOVQ syscall15Args_f3(R11), X2 // f3
+ MOVQ syscall15Args_f4(R11), X3 // f4
+ MOVQ syscall15Args_f5(R11), X4 // f5
+ MOVQ syscall15Args_f6(R11), X5 // f6
+ MOVQ syscall15Args_f7(R11), X6 // f7
+ MOVQ syscall15Args_f8(R11), X7 // f8
+
+ MOVQ syscall15Args_a1(R11), DI // a1
+ MOVQ syscall15Args_a2(R11), SI // a2
+ MOVQ syscall15Args_a3(R11), DX // a3
+ MOVQ syscall15Args_a4(R11), CX // a4
+ MOVQ syscall15Args_a5(R11), R8 // a5
+ MOVQ syscall15Args_a6(R11), R9 // a6
+
+ // push the remaining paramters onto the stack
+ MOVQ syscall15Args_a7(R11), R12
+ MOVQ R12, 0(SP) // push a7
+ MOVQ syscall15Args_a8(R11), R12
+ MOVQ R12, 8(SP) // push a8
+ MOVQ syscall15Args_a9(R11), R12
+ MOVQ R12, 16(SP) // push a9
+ MOVQ syscall15Args_a10(R11), R12
+ MOVQ R12, 24(SP) // push a10
+ MOVQ syscall15Args_a11(R11), R12
+ MOVQ R12, 32(SP) // push a11
+ MOVQ syscall15Args_a12(R11), R12
+ MOVQ R12, 40(SP) // push a12
+ MOVQ syscall15Args_a13(R11), R12
+ MOVQ R12, 48(SP) // push a13
+ MOVQ syscall15Args_a14(R11), R12
+ MOVQ R12, 56(SP) // push a14
+ MOVQ syscall15Args_a15(R11), R12
+ MOVQ R12, 64(SP) // push a15
+ XORL AX, AX // vararg: say "no float args"
+
+ MOVQ syscall15Args_fn(R11), R10 // fn
+ CALL R10
+
+ MOVQ PTR_ADDRESS(BP), DI // get the pointer back
+ MOVQ AX, syscall15Args_a1(DI) // r1
+ MOVQ DX, syscall15Args_a2(DI) // r3
+ MOVQ X0, syscall15Args_f1(DI) // f1
+ MOVQ X1, syscall15Args_f2(DI) // f2
+
+#ifdef GOOS_darwin
+ CALL purego_error(SB)
+ MOVD (AX), AX
+ MOVD AX, syscall15Args_a3(DI) // save errno
+#endif
+
+ XORL AX, AX // no error (it's ignored anyway)
+ ADDQ $STACK_SIZE, SP
+ MOVQ BP, SP
+ POPQ BP
+ RET
+
+TEXT callbackasm1(SB), NOSPLIT|NOFRAME, $0
+ MOVQ 0(SP), AX // save the return address to calculate the cb index
+ MOVQ 8(SP), R10 // get the return SP so that we can align register args with stack args
+ ADDQ $8, SP // remove return address from stack, we are not returning to callbackasm, but to its caller.
+
+ // make space for first six int and 8 float arguments below the frame
+ ADJSP $14*8, SP
+ MOVSD X0, (1*8)(SP)
+ MOVSD X1, (2*8)(SP)
+ MOVSD X2, (3*8)(SP)
+ MOVSD X3, (4*8)(SP)
+ MOVSD X4, (5*8)(SP)
+ MOVSD X5, (6*8)(SP)
+ MOVSD X6, (7*8)(SP)
+ MOVSD X7, (8*8)(SP)
+ MOVQ DI, (9*8)(SP)
+ MOVQ SI, (10*8)(SP)
+ MOVQ DX, (11*8)(SP)
+ MOVQ CX, (12*8)(SP)
+ MOVQ R8, (13*8)(SP)
+ MOVQ R9, (14*8)(SP)
+ LEAQ 8(SP), R8 // R8 = address of args vector
+
+ PUSHQ R10 // push the stack pointer below registers
+
+ // Switch from the host ABI to the Go ABI.
+ PUSH_REGS_HOST_TO_ABI0()
+
+ // determine index into runtime·cbs table
+ MOVQ $callbackasm(SB), DX
+ SUBQ DX, AX
+ MOVQ $0, DX
+ MOVQ $5, CX // divide by 5 because each call instruction in ·callbacks is 5 bytes long
+ DIVL CX
+ SUBQ $1, AX // subtract 1 because return PC is to the next slot
+
+ // Create a struct callbackArgs on our stack to be passed as
+ // the "frame" to cgocallback and on to callbackWrap.
+ // $24 to make enough room for the arguments to runtime.cgocallback
+ SUBQ $(24+callbackArgs__size), SP
+ MOVQ AX, (24+callbackArgs_index)(SP) // callback index
+ MOVQ R8, (24+callbackArgs_args)(SP) // address of args vector
+ MOVQ $0, (24+callbackArgs_result)(SP) // result
+ LEAQ 24(SP), AX // take the address of callbackArgs
+
+ // Call cgocallback, which will call callbackWrap(frame).
+ MOVQ ·callbackWrap_call(SB), DI // Get the ABIInternal function pointer
+ MOVQ (DI), DI // without by using a closure.
+ MOVQ AX, SI // frame (address of callbackArgs)
+ MOVQ $0, CX // context
+
+ CALL crosscall2(SB) // runtime.cgocallback(fn, frame, ctxt uintptr)
+
+ // Get callback result.
+ MOVQ (24+callbackArgs_result)(SP), AX
+ ADDQ $(24+callbackArgs__size), SP // remove callbackArgs struct
+
+ POP_REGS_HOST_TO_ABI0()
+
+ POPQ R10 // get the SP back
+ ADJSP $-14*8, SP // remove arguments
+
+ MOVQ R10, 0(SP)
+
+ RET
diff --git a/raymenu/vendor/github.com/ebitengine/purego/sys_arm.s b/raymenu/vendor/github.com/ebitengine/purego/sys_arm.s
new file mode 100644
index 0000000..3a8ce0d
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/sys_arm.s
@@ -0,0 +1,142 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2026 The Ebitengine Authors
+
+//go:build linux
+
+#include "textflag.h"
+#include "go_asm.h"
+#include "funcdata.h"
+
+#define STACK_SIZE 128
+#define PTR_ADDRESS (STACK_SIZE - 4)
+
+// syscall15X calls a function in libc on behalf of the syscall package.
+// syscall15X takes a pointer to a struct like:
+// struct {
+// fn uintptr
+// a1 uintptr
+// ...
+// a32 uintptr
+// f1 uintptr
+// ...
+// f16 uintptr
+// arm64_r8 uintptr
+// }
+// syscall15X must be called on the g0 stack with the
+// C calling convention (use libcCall).
+GLOBL ·syscall15XABI0(SB), NOPTR|RODATA, $4
+DATA ·syscall15XABI0(SB)/4, $syscall15X(SB)
+TEXT syscall15X(SB), NOSPLIT|NOFRAME, $0-0
+ // Called via C calling convention: R0 = pointer to syscall15Args
+ // NOT via Go calling convention
+ // Save link register and callee-saved registers first
+ MOVW.W R14, -4(R13) // save LR (decrement and store)
+ MOVM.DB.W [R4, R5, R6, R7, R8, R9, R11], (R13) // save callee-saved regs
+
+ MOVW R0, R8
+ SUB $STACK_SIZE, R13
+ MOVW R8, PTR_ADDRESS(R13)
+
+ // Load function pointer first (before anything can corrupt R8)
+ MOVW syscall15Args_fn(R8), R5
+ MOVW R5, (PTR_ADDRESS-4)(R13) // save fn at offset 56
+
+ // Load floating point arguments
+ // Each float64 spans 2 uintptr slots (8 bytes) on ARM32, so we skip by 2
+ MOVD syscall15Args_f1(R8), F0 // f1+f2 -> D0
+ MOVD syscall15Args_f3(R8), F1 // f3+f4 -> D1
+ MOVD syscall15Args_f5(R8), F2 // f5+f6 -> D2
+ MOVD syscall15Args_f7(R8), F3 // f7+f8 -> D3
+ MOVD syscall15Args_f9(R8), F4 // f9+f10 -> D4
+ MOVD syscall15Args_f11(R8), F5 // f11+f12 -> D5
+ MOVD syscall15Args_f13(R8), F6 // f13+f14 -> D6
+ MOVD syscall15Args_f15(R8), F7 // f15+f16 -> D7
+
+ // Load integer arguments into registers (R0-R3 for ARM EABI)
+ MOVW syscall15Args_a1(R8), R0 // a1
+ MOVW syscall15Args_a2(R8), R1 // a2
+ MOVW syscall15Args_a3(R8), R2 // a3
+ MOVW syscall15Args_a4(R8), R3 // a4
+
+ // push a5-a32 onto stack
+ MOVW syscall15Args_a5(R8), R4
+ MOVW R4, 0(R13)
+ MOVW syscall15Args_a6(R8), R4
+ MOVW R4, 4(R13)
+ MOVW syscall15Args_a7(R8), R4
+ MOVW R4, 8(R13)
+ MOVW syscall15Args_a8(R8), R4
+ MOVW R4, 12(R13)
+ MOVW syscall15Args_a9(R8), R4
+ MOVW R4, 16(R13)
+ MOVW syscall15Args_a10(R8), R4
+ MOVW R4, 20(R13)
+ MOVW syscall15Args_a11(R8), R4
+ MOVW R4, 24(R13)
+ MOVW syscall15Args_a12(R8), R4
+ MOVW R4, 28(R13)
+ MOVW syscall15Args_a13(R8), R4
+ MOVW R4, 32(R13)
+ MOVW syscall15Args_a14(R8), R4
+ MOVW R4, 36(R13)
+ MOVW syscall15Args_a15(R8), R4
+ MOVW R4, 40(R13)
+ MOVW syscall15Args_a16(R8), R4
+ MOVW R4, 44(R13)
+ MOVW syscall15Args_a17(R8), R4
+ MOVW R4, 48(R13)
+ MOVW syscall15Args_a18(R8), R4
+ MOVW R4, 52(R13)
+ MOVW syscall15Args_a19(R8), R4
+ MOVW R4, 56(R13)
+ MOVW syscall15Args_a20(R8), R4
+ MOVW R4, 60(R13)
+ MOVW syscall15Args_a21(R8), R4
+ MOVW R4, 64(R13)
+ MOVW syscall15Args_a22(R8), R4
+ MOVW R4, 68(R13)
+ MOVW syscall15Args_a23(R8), R4
+ MOVW R4, 72(R13)
+ MOVW syscall15Args_a24(R8), R4
+ MOVW R4, 76(R13)
+ MOVW syscall15Args_a25(R8), R4
+ MOVW R4, 80(R13)
+ MOVW syscall15Args_a26(R8), R4
+ MOVW R4, 84(R13)
+ MOVW syscall15Args_a27(R8), R4
+ MOVW R4, 88(R13)
+ MOVW syscall15Args_a28(R8), R4
+ MOVW R4, 92(R13)
+ MOVW syscall15Args_a29(R8), R4
+ MOVW R4, 96(R13)
+ MOVW syscall15Args_a30(R8), R4
+ MOVW R4, 100(R13)
+ MOVW syscall15Args_a31(R8), R4
+ MOVW R4, 104(R13)
+ MOVW syscall15Args_a32(R8), R4
+ MOVW R4, 108(R13)
+
+ // Load saved function pointer and call
+ MOVW (PTR_ADDRESS-4)(R13), R4
+
+ // Use BLX for Thumb interworking - Go assembler doesn't support BLX Rn
+ // BLX R4 = 0xE12FFF34 (ARM encoding, always condition)
+ WORD $0xE12FFF34 // blx r4
+
+ // pop structure pointer
+ MOVW PTR_ADDRESS(R13), R8
+ ADD $STACK_SIZE, R13
+
+ // save R0, R1
+ MOVW R0, syscall15Args_a1(R8)
+ MOVW R1, syscall15Args_a2(R8)
+
+ // save f0-f3 (each float64 spans 2 uintptr slots on ARM32)
+ MOVD F0, syscall15Args_f1(R8)
+ MOVD F1, syscall15Args_f3(R8)
+ MOVD F2, syscall15Args_f5(R8)
+ MOVD F3, syscall15Args_f7(R8)
+
+ // Restore callee-saved registers and return
+ MOVM.IA.W (R13), [R4, R5, R6, R7, R8, R9, R11]
+ MOVW.P 4(R13), R15 // pop LR into PC (return)
diff --git a/raymenu/vendor/github.com/ebitengine/purego/sys_arm64.s b/raymenu/vendor/github.com/ebitengine/purego/sys_arm64.s
new file mode 100644
index 0000000..40a2f4c
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/sys_arm64.s
@@ -0,0 +1,97 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
+
+//go:build darwin || freebsd || linux || netbsd || windows
+
+#include "textflag.h"
+#include "go_asm.h"
+#include "funcdata.h"
+
+#define STACK_SIZE 64
+#define PTR_ADDRESS (STACK_SIZE - 8)
+
+// syscall15X calls a function in libc on behalf of the syscall package.
+// syscall15X takes a pointer to a struct like:
+// struct {
+// fn uintptr
+// a1 uintptr
+// a2 uintptr
+// a3 uintptr
+// a4 uintptr
+// a5 uintptr
+// a6 uintptr
+// a7 uintptr
+// a8 uintptr
+// a9 uintptr
+// a10 uintptr
+// a11 uintptr
+// a12 uintptr
+// a13 uintptr
+// a14 uintptr
+// a15 uintptr
+// r1 uintptr
+// r2 uintptr
+// err uintptr
+// }
+// syscall15X must be called on the g0 stack with the
+// C calling convention (use libcCall).
+GLOBL ·syscall15XABI0(SB), NOPTR|RODATA, $8
+DATA ·syscall15XABI0(SB)/8, $syscall15X(SB)
+TEXT syscall15X(SB), NOSPLIT, $0
+ SUB $STACK_SIZE, RSP // push structure pointer
+ MOVD R0, PTR_ADDRESS(RSP)
+ MOVD R0, R9
+
+ FMOVD syscall15Args_f1(R9), F0 // f1
+ FMOVD syscall15Args_f2(R9), F1 // f2
+ FMOVD syscall15Args_f3(R9), F2 // f3
+ FMOVD syscall15Args_f4(R9), F3 // f4
+ FMOVD syscall15Args_f5(R9), F4 // f5
+ FMOVD syscall15Args_f6(R9), F5 // f6
+ FMOVD syscall15Args_f7(R9), F6 // f7
+ FMOVD syscall15Args_f8(R9), F7 // f8
+
+ MOVD syscall15Args_a1(R9), R0 // a1
+ MOVD syscall15Args_a2(R9), R1 // a2
+ MOVD syscall15Args_a3(R9), R2 // a3
+ MOVD syscall15Args_a4(R9), R3 // a4
+ MOVD syscall15Args_a5(R9), R4 // a5
+ MOVD syscall15Args_a6(R9), R5 // a6
+ MOVD syscall15Args_a7(R9), R6 // a7
+ MOVD syscall15Args_a8(R9), R7 // a8
+ MOVD syscall15Args_arm64_r8(R9), R8 // r8
+
+ MOVD syscall15Args_a9(R9), R10
+ MOVD R10, 0(RSP) // push a9 onto stack
+ MOVD syscall15Args_a10(R9), R10
+ MOVD R10, 8(RSP) // push a10 onto stack
+ MOVD syscall15Args_a11(R9), R10
+ MOVD R10, 16(RSP) // push a11 onto stack
+ MOVD syscall15Args_a12(R9), R10
+ MOVD R10, 24(RSP) // push a12 onto stack
+ MOVD syscall15Args_a13(R9), R10
+ MOVD R10, 32(RSP) // push a13 onto stack
+ MOVD syscall15Args_a14(R9), R10
+ MOVD R10, 40(RSP) // push a14 onto stack
+ MOVD syscall15Args_a15(R9), R10
+ MOVD R10, 48(RSP) // push a15 onto stack
+
+ MOVD syscall15Args_fn(R9), R10 // fn
+ BL (R10)
+
+ MOVD PTR_ADDRESS(RSP), R2 // pop structure pointer
+ ADD $STACK_SIZE, RSP
+
+ MOVD R0, syscall15Args_a1(R2) // save r1
+ MOVD R1, syscall15Args_a2(R2) // save r3
+ FMOVD F0, syscall15Args_f1(R2) // save f0
+ FMOVD F1, syscall15Args_f2(R2) // save f1
+ FMOVD F2, syscall15Args_f3(R2) // save f2
+ FMOVD F3, syscall15Args_f4(R2) // save f3
+
+#ifdef GOOS_darwin
+ BL purego_error(SB)
+ MOVD (R0), R0
+ MOVD R0, syscall15Args_a3(R2) // save errno
+#endif
+ RET
diff --git a/raymenu/vendor/github.com/ebitengine/purego/sys_loong64.s b/raymenu/vendor/github.com/ebitengine/purego/sys_loong64.s
new file mode 100644
index 0000000..420b855
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/sys_loong64.s
@@ -0,0 +1,96 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2025 The Ebitengine Authors
+
+//go:build linux
+
+#include "textflag.h"
+#include "go_asm.h"
+#include "funcdata.h"
+
+#define STACK_SIZE 64
+#define PTR_ADDRESS (STACK_SIZE - 8)
+
+// syscall15X calls a function in libc on behalf of the syscall package.
+// syscall15X takes a pointer to a struct like:
+// struct {
+// fn uintptr
+// a1 uintptr
+// a2 uintptr
+// a3 uintptr
+// a4 uintptr
+// a5 uintptr
+// a6 uintptr
+// a7 uintptr
+// a8 uintptr
+// a9 uintptr
+// a10 uintptr
+// a11 uintptr
+// a12 uintptr
+// a13 uintptr
+// a14 uintptr
+// a15 uintptr
+// r1 uintptr
+// r2 uintptr
+// err uintptr
+// }
+// syscall15X must be called on the g0 stack with the
+// C calling convention (use libcCall).
+GLOBL ·syscall15XABI0(SB), NOPTR|RODATA, $8
+DATA ·syscall15XABI0(SB)/8, $syscall15X(SB)
+TEXT syscall15X(SB), NOSPLIT, $0
+ // push structure pointer
+ SUBV $STACK_SIZE, R3
+ MOVV R4, PTR_ADDRESS(R3)
+ MOVV R4, R13
+
+ MOVD syscall15Args_f1(R13), F0 // f1
+ MOVD syscall15Args_f2(R13), F1 // f2
+ MOVD syscall15Args_f3(R13), F2 // f3
+ MOVD syscall15Args_f4(R13), F3 // f4
+ MOVD syscall15Args_f5(R13), F4 // f5
+ MOVD syscall15Args_f6(R13), F5 // f6
+ MOVD syscall15Args_f7(R13), F6 // f7
+ MOVD syscall15Args_f8(R13), F7 // f8
+
+ MOVV syscall15Args_a1(R13), R4 // a1
+ MOVV syscall15Args_a2(R13), R5 // a2
+ MOVV syscall15Args_a3(R13), R6 // a3
+ MOVV syscall15Args_a4(R13), R7 // a4
+ MOVV syscall15Args_a5(R13), R8 // a5
+ MOVV syscall15Args_a6(R13), R9 // a6
+ MOVV syscall15Args_a7(R13), R10 // a7
+ MOVV syscall15Args_a8(R13), R11 // a8
+
+ // push a9-a15 onto stack
+ MOVV syscall15Args_a9(R13), R12
+ MOVV R12, 0(R3)
+ MOVV syscall15Args_a10(R13), R12
+ MOVV R12, 8(R3)
+ MOVV syscall15Args_a11(R13), R12
+ MOVV R12, 16(R3)
+ MOVV syscall15Args_a12(R13), R12
+ MOVV R12, 24(R3)
+ MOVV syscall15Args_a13(R13), R12
+ MOVV R12, 32(R3)
+ MOVV syscall15Args_a14(R13), R12
+ MOVV R12, 40(R3)
+ MOVV syscall15Args_a15(R13), R12
+ MOVV R12, 48(R3)
+
+ MOVV syscall15Args_fn(R13), R12
+ JAL (R12)
+
+ // pop structure pointer
+ MOVV PTR_ADDRESS(R3), R13
+ ADDV $STACK_SIZE, R3
+
+ // save R4, R5
+ MOVV R4, syscall15Args_a1(R13)
+ MOVV R5, syscall15Args_a2(R13)
+
+ // save f0-f3
+ MOVD F0, syscall15Args_f1(R13)
+ MOVD F1, syscall15Args_f2(R13)
+ MOVD F2, syscall15Args_f3(R13)
+ MOVD F3, syscall15Args_f4(R13)
+ RET
diff --git a/raymenu/vendor/github.com/ebitengine/purego/sys_ppc64le.s b/raymenu/vendor/github.com/ebitengine/purego/sys_ppc64le.s
new file mode 100644
index 0000000..391b30a
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/sys_ppc64le.s
@@ -0,0 +1,120 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2026 The Ebitengine Authors
+
+//go:build linux
+
+#include "textflag.h"
+#include "go_asm.h"
+#include "funcdata.h"
+
+// PPC64LE ELFv2 ABI:
+// - Integer args: R3-R10 (8 registers)
+// - Float args: F1-F8 (8 registers)
+// - Return: R3 (integer), F1 (float)
+// - Stack pointer: R1
+// - Link register: LR (special)
+// - TOC pointer: R2 (must preserve)
+
+// Stack layout for ELFv2 ABI (aligned to 16 bytes):
+// From callee's perspective when we call BL (CTR):
+// 0(R1) - back chain (our old R1)
+// 8(R1) - CR save word (optional)
+// 16(R1) - LR save (optional, we save it)
+// 24(R1) - Reserved (compilers)
+// 32(R1) - Parameter save area start (8 * 8 = 64 bytes for R3-R10)
+// 96(R1) - First stack arg (a9) - this is where callee looks
+// 104(R1) - Second stack arg (a10)
+// 112-152 - Stack args a11-a15 (5 * 8 = 40 bytes)
+// 160(R1) - TOC save (we put it here, outside param save area)
+// 168(R1) - saved args pointer
+// 176(R1) - padding for 16-byte alignment
+// Total: 176 bytes
+
+#define STACK_SIZE 176
+#define LR_SAVE 16
+#define TOC_SAVE 160
+#define ARGP_SAVE 168
+
+GLOBL ·syscall15XABI0(SB), NOPTR|RODATA, $8
+DATA ·syscall15XABI0(SB)/8, $syscall15X(SB)
+
+TEXT syscall15X(SB), NOSPLIT, $0
+ // Prologue: create stack frame
+ // R3 contains the args pointer on entry
+ MOVD R1, R12 // save old SP
+ SUB $STACK_SIZE, R1 // allocate stack frame
+ MOVD R12, 0(R1) // save back chain
+ MOVD LR, R12
+ MOVD R12, LR_SAVE(R1) // save LR
+ MOVD R2, TOC_SAVE(R1) // save TOC
+
+ // Save args pointer (in R3)
+ MOVD R3, ARGP_SAVE(R1)
+
+ // R11 := args pointer (syscall15Args*)
+ MOVD R3, R11
+
+ // Load float args into F1-F8
+ FMOVD syscall15Args_f1(R11), F1
+ FMOVD syscall15Args_f2(R11), F2
+ FMOVD syscall15Args_f3(R11), F3
+ FMOVD syscall15Args_f4(R11), F4
+ FMOVD syscall15Args_f5(R11), F5
+ FMOVD syscall15Args_f6(R11), F6
+ FMOVD syscall15Args_f7(R11), F7
+ FMOVD syscall15Args_f8(R11), F8
+
+ // Load integer args into R3-R10
+ MOVD syscall15Args_a1(R11), R3
+ MOVD syscall15Args_a2(R11), R4
+ MOVD syscall15Args_a3(R11), R5
+ MOVD syscall15Args_a4(R11), R6
+ MOVD syscall15Args_a5(R11), R7
+ MOVD syscall15Args_a6(R11), R8
+ MOVD syscall15Args_a7(R11), R9
+ MOVD syscall15Args_a8(R11), R10
+
+ // Spill a9-a15 onto the stack (stack parameters start at 96(R1))
+ // Per ELFv2: parameter save area is 32-95, stack args start at 96
+ MOVD ARGP_SAVE(R1), R11 // reload args pointer
+ MOVD syscall15Args_a9(R11), R12
+ MOVD R12, 96(R1) // a9 at 96(R1)
+ MOVD syscall15Args_a10(R11), R12
+ MOVD R12, 104(R1) // a10 at 104(R1)
+ MOVD syscall15Args_a11(R11), R12
+ MOVD R12, 112(R1) // a11 at 112(R1)
+ MOVD syscall15Args_a12(R11), R12
+ MOVD R12, 120(R1) // a12 at 120(R1)
+ MOVD syscall15Args_a13(R11), R12
+ MOVD R12, 128(R1) // a13 at 128(R1)
+ MOVD syscall15Args_a14(R11), R12
+ MOVD R12, 136(R1) // a14 at 136(R1)
+ MOVD syscall15Args_a15(R11), R12
+ MOVD R12, 144(R1) // a15 at 144(R1)
+
+ // Call function: load fn and call
+ MOVD syscall15Args_fn(R11), R12
+ MOVD R12, CTR
+ BL (CTR)
+
+ // Restore TOC after call
+ MOVD TOC_SAVE(R1), R2
+
+ // Restore args pointer for storing results
+ MOVD ARGP_SAVE(R1), R11
+
+ // Store integer results back (R3, R4)
+ MOVD R3, syscall15Args_a1(R11)
+ MOVD R4, syscall15Args_a2(R11)
+
+ // Store float return values (F1-F4)
+ FMOVD F1, syscall15Args_f1(R11)
+ FMOVD F2, syscall15Args_f2(R11)
+ FMOVD F3, syscall15Args_f3(R11)
+ FMOVD F4, syscall15Args_f4(R11)
+
+ // Epilogue: restore and return
+ MOVD LR_SAVE(R1), R12
+ MOVD R12, LR
+ ADD $STACK_SIZE, R1
+ RET
diff --git a/raymenu/vendor/github.com/ebitengine/purego/sys_riscv64.s b/raymenu/vendor/github.com/ebitengine/purego/sys_riscv64.s
new file mode 100644
index 0000000..e7e887e
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/sys_riscv64.s
@@ -0,0 +1,101 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2026 The Ebitengine Authors
+
+//go:build linux
+
+#include "textflag.h"
+#include "go_asm.h"
+#include "funcdata.h"
+
+// Stack usage:
+// 0(SP) - 56(SP): stack args a9-a15 (7 * 8 bytes = 56)
+// 56(SP) - 64(SP): saved RA (x1)
+// 64(SP) - 72(SP): saved X9 (s1)
+// 72(SP) - 80(SP): saved X18 (s2)
+// 80(SP) - 88(SP): saved args pointer (original X10)
+// 88(SP) - 96(SP): padding
+#define STACK_SIZE 96
+#define SAVE_RA 56
+#define SAVE_X9 64
+#define SAVE_X18 72
+#define SAVE_ARGP 80
+
+GLOBL ·syscall15XABI0(SB), NOPTR|RODATA, $8
+DATA ·syscall15XABI0(SB)/8, $syscall15X(SB)
+
+TEXT syscall15X(SB), NOSPLIT, $0
+ // Allocate stack frame (keeps 16-byte alignment)
+ SUB $STACK_SIZE, SP
+
+ // Save callee-saved regs we clobber + return address
+ MOV X1, SAVE_RA(SP)
+ MOV X9, SAVE_X9(SP)
+ MOV X18, SAVE_X18(SP)
+
+ // Save original args pointer (in a0/X10)
+ MOV X10, SAVE_ARGP(SP)
+
+ // X9 := args pointer (syscall15Args*)
+ MOV X10, X9
+
+ // Load float args into fa0-fa7 (F10-F17)
+ MOVD syscall15Args_f1(X9), F10
+ MOVD syscall15Args_f2(X9), F11
+ MOVD syscall15Args_f3(X9), F12
+ MOVD syscall15Args_f4(X9), F13
+ MOVD syscall15Args_f5(X9), F14
+ MOVD syscall15Args_f6(X9), F15
+ MOVD syscall15Args_f7(X9), F16
+ MOVD syscall15Args_f8(X9), F17
+
+ // Load integer args into a0-a7 (X10-X17)
+ MOV syscall15Args_a1(X9), X10
+ MOV syscall15Args_a2(X9), X11
+ MOV syscall15Args_a3(X9), X12
+ MOV syscall15Args_a4(X9), X13
+ MOV syscall15Args_a5(X9), X14
+ MOV syscall15Args_a6(X9), X15
+ MOV syscall15Args_a7(X9), X16
+ MOV syscall15Args_a8(X9), X17
+
+ // Spill a9-a15 onto the stack (C ABI)
+ MOV syscall15Args_a9(X9), X18
+ MOV X18, 0(SP)
+ MOV syscall15Args_a10(X9), X18
+ MOV X18, 8(SP)
+ MOV syscall15Args_a11(X9), X18
+ MOV X18, 16(SP)
+ MOV syscall15Args_a12(X9), X18
+ MOV X18, 24(SP)
+ MOV syscall15Args_a13(X9), X18
+ MOV X18, 32(SP)
+ MOV syscall15Args_a14(X9), X18
+ MOV X18, 40(SP)
+ MOV syscall15Args_a15(X9), X18
+ MOV X18, 48(SP)
+
+ // Call fn
+ // IMPORTANT: preserve RA across this call (we saved it above)
+ MOV syscall15Args_fn(X9), X18
+ CALL X18
+
+ // Restore args pointer (syscall15Args*) for storing results
+ MOV SAVE_ARGP(SP), X9
+
+ // Store results back
+ MOV X10, syscall15Args_a1(X9)
+ MOV X11, syscall15Args_a2(X9)
+
+ // Store back float return regs if used by your ABI contract
+ MOVD F10, syscall15Args_f1(X9)
+ MOVD F11, syscall15Args_f2(X9)
+ MOVD F12, syscall15Args_f3(X9)
+ MOVD F13, syscall15Args_f4(X9)
+
+ // Restore callee-saved regs and return address
+ MOV SAVE_X18(SP), X18
+ MOV SAVE_X9(SP), X9
+ MOV SAVE_RA(SP), X1
+
+ ADD $STACK_SIZE, SP
+ RET
diff --git a/raymenu/vendor/github.com/ebitengine/purego/sys_s390x.s b/raymenu/vendor/github.com/ebitengine/purego/sys_s390x.s
new file mode 100644
index 0000000..a044e34
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/sys_s390x.s
@@ -0,0 +1,114 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2026 The Ebitengine Authors
+
+//go:build linux
+
+#include "textflag.h"
+#include "go_asm.h"
+#include "funcdata.h"
+
+// S390X ELF ABI:
+// - Integer args: R2-R6 (5 registers)
+// - Float args: F0, F2, F4, F6 (4 registers, even-numbered)
+// - Return: R2 (integer), F0 (float)
+// - Stack pointer: R15
+// - Link register: R14
+// - Callee-saved: R6-R13, F8-F15 (but R6 is also used for 5th param)
+//
+// Stack frame layout (aligned to 8 bytes):
+// 0(R15) - back chain
+// 8(R15) - reserved
+// 16(R15) - reserved
+// ... - register save area (R6-R15 at 48(R15))
+// 160(R15) - parameter area start (args beyond registers)
+//
+// We need space for:
+// - 160 bytes standard frame (with register save area)
+// - Stack args a6-a15 (10 * 8 = 80 bytes)
+// - Saved args pointer (8 bytes)
+// - Padding for alignment
+// Total: 264 bytes (rounded to 8-byte alignment)
+
+#define STACK_SIZE 264
+#define STACK_ARGS 160
+#define ARGP_SAVE 248
+
+GLOBL ·syscall15XABI0(SB), NOPTR|RODATA, $8
+DATA ·syscall15XABI0(SB)/8, $syscall15X(SB)
+
+TEXT syscall15X(SB), NOSPLIT, $0
+ // On entry, R2 contains the args pointer
+ // Save callee-saved registers in caller's frame (per ABI)
+ STMG R6, R15, 48(R15)
+
+ // Allocate our stack frame
+ MOVD R15, R1
+ SUB $STACK_SIZE, R15
+ MOVD R1, 0(R15) // back chain
+
+ // Save args pointer
+ MOVD R2, ARGP_SAVE(R15)
+
+ // R9 := args pointer (syscall15Args*)
+ MOVD R2, R9
+
+ // Load float args into F0, F2, F4, F6 (s390x uses even-numbered FPRs)
+ FMOVD syscall15Args_f1(R9), F0
+ FMOVD syscall15Args_f2(R9), F2
+ FMOVD syscall15Args_f3(R9), F4
+ FMOVD syscall15Args_f4(R9), F6
+
+ // Load integer args into R2-R6 (5 registers)
+ MOVD syscall15Args_a1(R9), R2
+ MOVD syscall15Args_a2(R9), R3
+ MOVD syscall15Args_a3(R9), R4
+ MOVD syscall15Args_a4(R9), R5
+ MOVD syscall15Args_a5(R9), R6
+
+ // Spill remaining args (a6-a15) onto the stack at 160(R15)
+ MOVD ARGP_SAVE(R15), R9 // reload args pointer
+ MOVD syscall15Args_a6(R9), R1
+ MOVD R1, (STACK_ARGS+0*8)(R15)
+ MOVD syscall15Args_a7(R9), R1
+ MOVD R1, (STACK_ARGS+1*8)(R15)
+ MOVD syscall15Args_a8(R9), R1
+ MOVD R1, (STACK_ARGS+2*8)(R15)
+ MOVD syscall15Args_a9(R9), R1
+ MOVD R1, (STACK_ARGS+3*8)(R15)
+ MOVD syscall15Args_a10(R9), R1
+ MOVD R1, (STACK_ARGS+4*8)(R15)
+ MOVD syscall15Args_a11(R9), R1
+ MOVD R1, (STACK_ARGS+5*8)(R15)
+ MOVD syscall15Args_a12(R9), R1
+ MOVD R1, (STACK_ARGS+6*8)(R15)
+ MOVD syscall15Args_a13(R9), R1
+ MOVD R1, (STACK_ARGS+7*8)(R15)
+ MOVD syscall15Args_a14(R9), R1
+ MOVD R1, (STACK_ARGS+8*8)(R15)
+ MOVD syscall15Args_a15(R9), R1
+ MOVD R1, (STACK_ARGS+9*8)(R15)
+
+ // Call function
+ MOVD syscall15Args_fn(R9), R1
+ BL (R1)
+
+ // Restore args pointer for storing results
+ MOVD ARGP_SAVE(R15), R9
+
+ // Store integer results back (R2, R3)
+ MOVD R2, syscall15Args_a1(R9)
+ MOVD R3, syscall15Args_a2(R9)
+
+ // Store float return values (F0, F2, F4, F6)
+ FMOVD F0, syscall15Args_f1(R9)
+ FMOVD F2, syscall15Args_f2(R9)
+ FMOVD F4, syscall15Args_f3(R9)
+ FMOVD F6, syscall15Args_f4(R9)
+
+ // Deallocate stack frame
+ ADD $STACK_SIZE, R15
+
+ // Restore callee-saved registers from caller's save area
+ LMG 48(R15), R6, R15
+
+ RET
diff --git a/raymenu/vendor/github.com/ebitengine/purego/sys_unix_386.s b/raymenu/vendor/github.com/ebitengine/purego/sys_unix_386.s
new file mode 100644
index 0000000..31aecbf
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/sys_unix_386.s
@@ -0,0 +1,226 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2026 The Ebitengine Authors
+
+//go:build linux
+
+#include "textflag.h"
+#include "go_asm.h"
+#include "funcdata.h"
+
+// callbackasm1 is the second part of the callback trampoline.
+// On entry:
+// - CX contains the callback index (set by callbackasm)
+// - 0(SP) contains the return address to C caller
+// - 4(SP), 8(SP), ... contain C arguments (cdecl convention)
+//
+// i386 cdecl calling convention:
+// - All arguments passed on stack
+// - Return value in EAX (and EDX for 64-bit)
+// - Caller cleans the stack
+// - Callee must preserve: EBX, ESI, EDI, EBP
+TEXT callbackasm1(SB), NOSPLIT|NOFRAME, $0
+ NO_LOCAL_POINTERS
+
+ // Save the return address
+ MOVL 0(SP), AX
+
+ // Allocate stack frame (must be done carefully to preserve args access)
+ // Layout:
+ // 0-15: saved callee-saved registers (BX, SI, DI, BP)
+ // 16-19: saved callback index
+ // 20-23: saved return address
+ // 24-35: callbackArgs struct (12 bytes)
+ // 36-291: copy of C arguments (256 bytes for 64 args, matching callbackMaxFrame)
+ // Total: 292 bytes, round up to 304 for alignment
+ SUBL $304, SP
+
+ // Save callee-saved registers
+ MOVL BX, 0(SP)
+ MOVL SI, 4(SP)
+ MOVL DI, 8(SP)
+ MOVL BP, 12(SP)
+
+ // Save callback index and return address
+ MOVL CX, 16(SP)
+ MOVL AX, 20(SP)
+
+ // Copy C arguments from original stack location to our frame
+ // Original args start at 304+4(SP) = 308(SP) (past our frame + original return addr)
+ // Copy to our frame at 36(SP)
+ // Copy 64 arguments (256 bytes, matching callbackMaxFrame = 64 * ptrSize)
+ MOVL 308(SP), AX
+ MOVL AX, 36(SP)
+ MOVL 312(SP), AX
+ MOVL AX, 40(SP)
+ MOVL 316(SP), AX
+ MOVL AX, 44(SP)
+ MOVL 320(SP), AX
+ MOVL AX, 48(SP)
+ MOVL 324(SP), AX
+ MOVL AX, 52(SP)
+ MOVL 328(SP), AX
+ MOVL AX, 56(SP)
+ MOVL 332(SP), AX
+ MOVL AX, 60(SP)
+ MOVL 336(SP), AX
+ MOVL AX, 64(SP)
+ MOVL 340(SP), AX
+ MOVL AX, 68(SP)
+ MOVL 344(SP), AX
+ MOVL AX, 72(SP)
+ MOVL 348(SP), AX
+ MOVL AX, 76(SP)
+ MOVL 352(SP), AX
+ MOVL AX, 80(SP)
+ MOVL 356(SP), AX
+ MOVL AX, 84(SP)
+ MOVL 360(SP), AX
+ MOVL AX, 88(SP)
+ MOVL 364(SP), AX
+ MOVL AX, 92(SP)
+ MOVL 368(SP), AX
+ MOVL AX, 96(SP)
+ MOVL 372(SP), AX
+ MOVL AX, 100(SP)
+ MOVL 376(SP), AX
+ MOVL AX, 104(SP)
+ MOVL 380(SP), AX
+ MOVL AX, 108(SP)
+ MOVL 384(SP), AX
+ MOVL AX, 112(SP)
+ MOVL 388(SP), AX
+ MOVL AX, 116(SP)
+ MOVL 392(SP), AX
+ MOVL AX, 120(SP)
+ MOVL 396(SP), AX
+ MOVL AX, 124(SP)
+ MOVL 400(SP), AX
+ MOVL AX, 128(SP)
+ MOVL 404(SP), AX
+ MOVL AX, 132(SP)
+ MOVL 408(SP), AX
+ MOVL AX, 136(SP)
+ MOVL 412(SP), AX
+ MOVL AX, 140(SP)
+ MOVL 416(SP), AX
+ MOVL AX, 144(SP)
+ MOVL 420(SP), AX
+ MOVL AX, 148(SP)
+ MOVL 424(SP), AX
+ MOVL AX, 152(SP)
+ MOVL 428(SP), AX
+ MOVL AX, 156(SP)
+ MOVL 432(SP), AX
+ MOVL AX, 160(SP)
+ MOVL 436(SP), AX
+ MOVL AX, 164(SP)
+ MOVL 440(SP), AX
+ MOVL AX, 168(SP)
+ MOVL 444(SP), AX
+ MOVL AX, 172(SP)
+ MOVL 448(SP), AX
+ MOVL AX, 176(SP)
+ MOVL 452(SP), AX
+ MOVL AX, 180(SP)
+ MOVL 456(SP), AX
+ MOVL AX, 184(SP)
+ MOVL 460(SP), AX
+ MOVL AX, 188(SP)
+ MOVL 464(SP), AX
+ MOVL AX, 192(SP)
+ MOVL 468(SP), AX
+ MOVL AX, 196(SP)
+ MOVL 472(SP), AX
+ MOVL AX, 200(SP)
+ MOVL 476(SP), AX
+ MOVL AX, 204(SP)
+ MOVL 480(SP), AX
+ MOVL AX, 208(SP)
+ MOVL 484(SP), AX
+ MOVL AX, 212(SP)
+ MOVL 488(SP), AX
+ MOVL AX, 216(SP)
+ MOVL 492(SP), AX
+ MOVL AX, 220(SP)
+ MOVL 496(SP), AX
+ MOVL AX, 224(SP)
+ MOVL 500(SP), AX
+ MOVL AX, 228(SP)
+ MOVL 504(SP), AX
+ MOVL AX, 232(SP)
+ MOVL 508(SP), AX
+ MOVL AX, 236(SP)
+ MOVL 512(SP), AX
+ MOVL AX, 240(SP)
+ MOVL 516(SP), AX
+ MOVL AX, 244(SP)
+ MOVL 520(SP), AX
+ MOVL AX, 248(SP)
+ MOVL 524(SP), AX
+ MOVL AX, 252(SP)
+ MOVL 528(SP), AX
+ MOVL AX, 256(SP)
+ MOVL 532(SP), AX
+ MOVL AX, 260(SP)
+ MOVL 536(SP), AX
+ MOVL AX, 264(SP)
+ MOVL 540(SP), AX
+ MOVL AX, 268(SP)
+ MOVL 544(SP), AX
+ MOVL AX, 272(SP)
+ MOVL 548(SP), AX
+ MOVL AX, 276(SP)
+ MOVL 552(SP), AX
+ MOVL AX, 280(SP)
+ MOVL 556(SP), AX
+ MOVL AX, 284(SP)
+ MOVL 560(SP), AX
+ MOVL AX, 288(SP)
+
+ // Set up callbackArgs struct at 24(SP)
+ // struct callbackArgs {
+ // index uintptr // offset 0
+ // args *byte // offset 4
+ // result uintptr // offset 8
+ // }
+ MOVL 16(SP), AX // callback index
+ MOVL AX, 24(SP) // callbackArgs.index
+ LEAL 36(SP), AX // pointer to copied arguments
+ MOVL AX, 28(SP) // callbackArgs.args
+ MOVL $0, 32(SP) // callbackArgs.result = 0
+
+ // Call crosscall2(fn, frame, 0, ctxt)
+ // crosscall2 expects arguments on stack:
+ // 0(SP) = fn
+ // 4(SP) = frame (pointer to callbackArgs)
+ // 8(SP) = ignored (was n)
+ // 12(SP) = ctxt
+ SUBL $16, SP
+
+ MOVL ·callbackWrap_call(SB), AX
+ MOVL (AX), AX // fn = *callbackWrap_call
+ MOVL AX, 0(SP) // fn
+ LEAL (24+16)(SP), AX // &callbackArgs (adjusted for SUB $16)
+ MOVL AX, 4(SP) // frame
+ MOVL $0, 8(SP) // 0
+ MOVL $0, 12(SP) // ctxt
+
+ CALL crosscall2(SB)
+
+ ADDL $16, SP
+
+ // Get result from callbackArgs.result
+ MOVL 32(SP), AX
+
+ // Restore callee-saved registers
+ MOVL 0(SP), BX
+ MOVL 4(SP), SI
+ MOVL 8(SP), DI
+ MOVL 12(SP), BP
+
+ // Restore return address and clean up
+ MOVL 20(SP), CX // get return address
+ ADDL $304, SP // remove our frame
+ MOVL CX, 0(SP) // put return address back
+
+ RET
diff --git a/raymenu/vendor/github.com/ebitengine/purego/sys_unix_arm.s b/raymenu/vendor/github.com/ebitengine/purego/sys_unix_arm.s
new file mode 100644
index 0000000..a97e943
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/sys_unix_arm.s
@@ -0,0 +1,89 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2026 The Ebitengine Authors
+
+//go:build linux
+
+#include "textflag.h"
+#include "go_asm.h"
+#include "funcdata.h"
+
+TEXT callbackasm1(SB), NOSPLIT|NOFRAME, $0
+ NO_LOCAL_POINTERS
+
+ // Allocate stack frame: 48 + 16 + 64 + 16 = 144 bytes
+ SUB $144, R13
+
+ // Save callee-saved registers at SP+0
+ MOVW R4, 0(R13)
+ MOVW R5, 4(R13)
+ MOVW R6, 8(R13)
+ MOVW R7, 12(R13)
+ MOVW R8, 16(R13)
+ MOVW R9, 20(R13)
+ MOVW g, 24(R13)
+ MOVW R11, 28(R13)
+ MOVW R14, 32(R13)
+
+ // Save callback index (passed in R12) at SP+36
+ MOVW R12, 36(R13)
+
+ // Save integer arguments R0-R3 at SP+128 (frame[16..19])
+ MOVW R0, 128(R13)
+ MOVW R1, 132(R13)
+ MOVW R2, 136(R13)
+ MOVW R3, 140(R13)
+
+ // Save floating point registers F0-F7 at SP+64 (frame[0..15])
+ // Note: We always save these since we target hard-float ABI.
+ MOVD F0, 64(R13)
+ MOVD F1, 72(R13)
+ MOVD F2, 80(R13)
+ MOVD F3, 88(R13)
+ MOVD F4, 96(R13)
+ MOVD F5, 104(R13)
+ MOVD F6, 112(R13)
+ MOVD F7, 120(R13)
+
+ // Set up callbackArgs at SP+48
+ MOVW 36(R13), R4
+ MOVW R4, 48(R13)
+ ADD $64, R13, R4
+ MOVW R4, 52(R13)
+ MOVW $0, R4
+ MOVW R4, 56(R13)
+
+ // Call crosscall2(fn, frame, 0, ctxt)
+ MOVW ·callbackWrap_call(SB), R0
+ MOVW (R0), R0
+ ADD $48, R13, R1
+ MOVW $0, R2
+ MOVW $0, R3
+
+ BL crosscall2(SB)
+
+ // Get result
+ MOVW 56(R13), R0
+
+ // Restore float registers
+ MOVD 64(R13), F0
+ MOVD 72(R13), F1
+ MOVD 80(R13), F2
+ MOVD 88(R13), F3
+ MOVD 96(R13), F4
+ MOVD 104(R13), F5
+ MOVD 112(R13), F6
+ MOVD 120(R13), F7
+
+ // Restore callee-saved registers
+ MOVW 0(R13), R4
+ MOVW 4(R13), R5
+ MOVW 8(R13), R6
+ MOVW 12(R13), R7
+ MOVW 16(R13), R8
+ MOVW 20(R13), R9
+ MOVW 24(R13), g
+ MOVW 28(R13), R11
+ MOVW 32(R13), R14
+
+ ADD $144, R13
+ RET
diff --git a/raymenu/vendor/github.com/ebitengine/purego/sys_unix_arm64.s b/raymenu/vendor/github.com/ebitengine/purego/sys_unix_arm64.s
new file mode 100644
index 0000000..cea803e
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/sys_unix_arm64.s
@@ -0,0 +1,70 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2023 The Ebitengine Authors
+
+//go:build darwin || freebsd || linux || netbsd
+
+#include "textflag.h"
+#include "go_asm.h"
+#include "funcdata.h"
+#include "abi_arm64.h"
+
+TEXT callbackasm1(SB), NOSPLIT|NOFRAME, $0
+ NO_LOCAL_POINTERS
+
+ // On entry, the trampoline in zcallback_darwin_arm64.s left
+ // the callback index in R12 (which is volatile in the C ABI).
+
+ // Save callback register arguments R0-R7 and F0-F7.
+ // We do this at the top of the frame so they're contiguous with stack arguments.
+ SUB $(16*8), RSP, R14
+ FSTPD (F0, F1), (0*8)(R14)
+ FSTPD (F2, F3), (2*8)(R14)
+ FSTPD (F4, F5), (4*8)(R14)
+ FSTPD (F6, F7), (6*8)(R14)
+ STP (R0, R1), (8*8)(R14)
+ STP (R2, R3), (10*8)(R14)
+ STP (R4, R5), (12*8)(R14)
+ STP (R6, R7), (14*8)(R14)
+
+ // Adjust SP by frame size.
+ SUB $(26*8), RSP
+
+ // It is important to save R27 because the go assembler
+ // uses it for move instructions for a variable.
+ // This line:
+ // MOVD ·callbackWrap_call(SB), R0
+ // Creates the instructions:
+ // ADRP 14335(PC), R27
+ // MOVD 388(27), R0
+ // R27 is a callee saved register so we are responsible
+ // for ensuring its value doesn't change. So save it and
+ // restore it at the end of this function.
+ // R30 is the link register. crosscall2 doesn't save it
+ // so it's saved here.
+ STP (R27, R30), 0(RSP)
+
+ // Create a struct callbackArgs on our stack.
+ MOVD $(callbackArgs__size)(RSP), R13
+ MOVD R12, callbackArgs_index(R13) // callback index
+ MOVD R14, callbackArgs_args(R13) // address of args vector
+ MOVD ZR, callbackArgs_result(R13) // result
+
+ // Move parameters into registers
+ // Get the ABIInternal function pointer
+ // without by using a closure.
+ MOVD ·callbackWrap_call(SB), R0
+ MOVD (R0), R0 // fn unsafe.Pointer
+ MOVD R13, R1 // frame (&callbackArgs{...})
+ MOVD $0, R3 // ctxt uintptr
+
+ BL crosscall2(SB)
+
+ // Get callback result.
+ MOVD $(callbackArgs__size)(RSP), R13
+ MOVD callbackArgs_result(R13), R0
+
+ // Restore LR and R27
+ LDP 0(RSP), (R27, R30)
+ ADD $(26*8), RSP
+
+ RET
diff --git a/raymenu/vendor/github.com/ebitengine/purego/sys_unix_loong64.s b/raymenu/vendor/github.com/ebitengine/purego/sys_unix_loong64.s
new file mode 100644
index 0000000..cd00f9c
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/sys_unix_loong64.s
@@ -0,0 +1,75 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2025 The Ebitengine Authors
+
+//go:build linux
+
+#include "textflag.h"
+#include "go_asm.h"
+#include "funcdata.h"
+#include "abi_loong64.h"
+
+TEXT callbackasm1(SB), NOSPLIT|NOFRAME, $0
+ NO_LOCAL_POINTERS
+
+ SUBV $(16*8), R3, R14
+ MOVD F0, 0(R14)
+ MOVD F1, 8(R14)
+ MOVD F2, 16(R14)
+ MOVD F3, 24(R14)
+ MOVD F4, 32(R14)
+ MOVD F5, 40(R14)
+ MOVD F6, 48(R14)
+ MOVD F7, 56(R14)
+ MOVV R4, 64(R14)
+ MOVV R5, 72(R14)
+ MOVV R6, 80(R14)
+ MOVV R7, 88(R14)
+ MOVV R8, 96(R14)
+ MOVV R9, 104(R14)
+ MOVV R10, 112(R14)
+ MOVV R11, 120(R14)
+
+ // Adjust SP by frame size.
+ SUBV $(22*8), R3
+
+ // It is important to save R30 because the go assembler
+ // uses it for move instructions for a variable.
+ // This line:
+ // MOVV ·callbackWrap_call(SB), R4
+ // Creates the instructions:
+ // PCALAU12I off1(PC), R30
+ // MOVV off2(R30), R4
+ // R30 is a callee saved register so we are responsible
+ // for ensuring its value doesn't change. So save it and
+ // restore it at the end of this function.
+ // R1 is the link register. crosscall2 doesn't save it
+ // so it's saved here.
+ MOVV R1, 0(R3)
+ MOVV R30, 8(R3)
+
+ // Create a struct callbackArgs on our stack.
+ MOVV $(callbackArgs__size)(R3), R13
+ MOVV R12, callbackArgs_index(R13) // callback index
+ MOVV R14, callbackArgs_args(R13) // address of args vector
+ MOVV $0, callbackArgs_result(R13) // result
+
+ // Move parameters into registers
+ // Get the ABIInternal function pointer
+ // without by using a closure.
+ MOVV ·callbackWrap_call(SB), R4
+ MOVV (R4), R4 // fn unsafe.Pointer
+ MOVV R13, R5 // frame (&callbackArgs{...})
+ MOVV $0, R7 // ctxt uintptr
+
+ JAL crosscall2(SB)
+
+ // Get callback result.
+ MOVV $(callbackArgs__size)(R3), R13
+ MOVV callbackArgs_result(R13), R4
+
+ // Restore LR and R30
+ MOVV 0(R3), R1
+ MOVV 8(R3), R30
+ ADDV $(22*8), R3
+
+ RET
diff --git a/raymenu/vendor/github.com/ebitengine/purego/sys_unix_ppc64le.s b/raymenu/vendor/github.com/ebitengine/purego/sys_unix_ppc64le.s
new file mode 100644
index 0000000..37f0d8d
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/sys_unix_ppc64le.s
@@ -0,0 +1,114 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2026 The Ebitengine Authors
+
+//go:build linux
+
+#include "textflag.h"
+#include "go_asm.h"
+#include "funcdata.h"
+
+// PPC64LE ELFv2 ABI callbackasm1 implementation
+// On entry, R11 contains the callback index (set by callbackasm)
+//
+// ELFv2 stack frame layout requirements:
+// 0(R1) - back chain (pointer to caller's frame)
+// 8(R1) - CR save area (optional)
+// 16(R1) - LR save area (for callee to save caller's LR)
+// 24(R1) - TOC save area (if needed)
+// 32(R1)+ - parameter save area / local variables
+//
+// Our frame (total 208 bytes, 16-byte aligned):
+// 32(R1) - saved R31 (8 bytes)
+// 40(R1) - callbackArgs struct (32 bytes: index, args, result, stackArgs)
+// 72(R1) - args array: floats (64) + ints (64) = 128 bytes, ends at 200
+// Total with alignment: 208 bytes
+//
+// Stack args are NOT copied - we pass a pointer to their location in caller's frame.
+// This keeps frame size small enough for NOSPLIT with CGO_ENABLED=1.
+// Budget: 208 + 544 (crosscall2) + 56 (cgocallback) = 808 bytes
+// This is 8 bytes over the 800 limit, but cgocallback's children (load_g, save_g)
+// reuse the same stack space, so in practice it works.
+
+#define FRAME_SIZE 200
+#define SAVE_R31 32
+#define CB_ARGS 40
+#define ARGS_ARRAY 72
+#define FLOAT_OFF 0
+#define INT_OFF 64
+
+TEXT callbackasm1(SB), NOSPLIT|NOFRAME, $0
+ NO_LOCAL_POINTERS
+
+ // On entry, the trampoline in zcallback_ppc64le.s left
+ // the callback index in R11.
+
+ // Per ELFv2 ABI, save LR to caller's frame BEFORE allocating our frame
+ MOVD LR, R0
+ MOVD R0, 16(R1)
+
+ // Allocate our stack frame (with back chain via MOVDU)
+ MOVDU R1, -FRAME_SIZE(R1)
+
+ // Save R31 - Go assembler uses it for MOVD from SB (like arm64's R27)
+ MOVD R31, SAVE_R31(R1)
+
+ // Save R11 (callback index) immediately - it's volatile and will be clobbered!
+ // Store it in the callbackArgs struct's index field now.
+ MOVD R11, (CB_ARGS+0)(R1)
+
+ // Save callback arguments to args array.
+ // Layout: floats first (F1-F8), then ints (R3-R10), then stack args
+ FMOVD F1, (ARGS_ARRAY+FLOAT_OFF+0*8)(R1)
+ FMOVD F2, (ARGS_ARRAY+FLOAT_OFF+1*8)(R1)
+ FMOVD F3, (ARGS_ARRAY+FLOAT_OFF+2*8)(R1)
+ FMOVD F4, (ARGS_ARRAY+FLOAT_OFF+3*8)(R1)
+ FMOVD F5, (ARGS_ARRAY+FLOAT_OFF+4*8)(R1)
+ FMOVD F6, (ARGS_ARRAY+FLOAT_OFF+5*8)(R1)
+ FMOVD F7, (ARGS_ARRAY+FLOAT_OFF+6*8)(R1)
+ FMOVD F8, (ARGS_ARRAY+FLOAT_OFF+7*8)(R1)
+
+ MOVD R3, (ARGS_ARRAY+INT_OFF+0*8)(R1)
+ MOVD R4, (ARGS_ARRAY+INT_OFF+1*8)(R1)
+ MOVD R5, (ARGS_ARRAY+INT_OFF+2*8)(R1)
+ MOVD R6, (ARGS_ARRAY+INT_OFF+3*8)(R1)
+ MOVD R7, (ARGS_ARRAY+INT_OFF+4*8)(R1)
+ MOVD R8, (ARGS_ARRAY+INT_OFF+5*8)(R1)
+ MOVD R9, (ARGS_ARRAY+INT_OFF+6*8)(R1)
+ MOVD R10, (ARGS_ARRAY+INT_OFF+7*8)(R1)
+
+ // Finish setting up callbackArgs struct at CB_ARGS(R1)
+ // struct { index uintptr; args unsafe.Pointer; result uintptr; stackArgs unsafe.Pointer }
+ // Note: index was already saved earlier (R11 is volatile)
+ ADD $ARGS_ARRAY, R1, R12
+ MOVD R12, (CB_ARGS+8)(R1) // args = address of register args
+ MOVD $0, (CB_ARGS+16)(R1) // result = 0
+
+ // stackArgs points to caller's stack arguments at old_R1+96 = R1+FRAME_SIZE+96
+ ADD $(FRAME_SIZE+96), R1, R12
+ MOVD R12, (CB_ARGS+24)(R1) // stackArgs = &caller_stack_args
+
+ // Call crosscall2 with arguments in registers:
+ // R3 = fn (from callbackWrap_call closure)
+ // R4 = frame (address of callbackArgs)
+ // R6 = ctxt (0)
+ MOVD ·callbackWrap_call(SB), R3
+ MOVD (R3), R3 // dereference closure to get fn
+ ADD $CB_ARGS, R1, R4 // frame = &callbackArgs
+ MOVD $0, R6 // ctxt = 0
+
+ BL crosscall2(SB)
+
+ // Get callback result into R3
+ MOVD (CB_ARGS+16)(R1), R3
+
+ // Restore R31
+ MOVD SAVE_R31(R1), R31
+
+ // Deallocate frame
+ ADD $FRAME_SIZE, R1
+
+ // Restore LR from caller's frame (per ELFv2, it was saved at 16(old_R1))
+ MOVD 16(R1), R0
+ MOVD R0, LR
+
+ RET
diff --git a/raymenu/vendor/github.com/ebitengine/purego/sys_unix_riscv64.s b/raymenu/vendor/github.com/ebitengine/purego/sys_unix_riscv64.s
new file mode 100644
index 0000000..8341d5b
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/sys_unix_riscv64.s
@@ -0,0 +1,79 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2026 The Ebitengine Authors
+
+//go:build linux
+
+#include "textflag.h"
+#include "go_asm.h"
+#include "funcdata.h"
+
+TEXT callbackasm1(SB), NOFRAME, $0
+ NO_LOCAL_POINTERS
+
+ // On entry, the trampoline in zcallback_riscv64.s left
+ // the callback index in X7.
+
+ // Save callback register arguments X10-X17 and F10-F17.
+ // Stack args (if any) are at 0(SP), 8(SP), etc.
+ // We save register args at SP-128, making them contiguous with stack args.
+ ADD $-(16*8), SP, X6
+
+ // Save float arg regs fa0-fa7 (F10-F17)
+ MOVD F10, 0(X6)
+ MOVD F11, 8(X6)
+ MOVD F12, 16(X6)
+ MOVD F13, 24(X6)
+ MOVD F14, 32(X6)
+ MOVD F15, 40(X6)
+ MOVD F16, 48(X6)
+ MOVD F17, 56(X6)
+
+ // Save integer arg regs a0-a7 (X10-X17)
+ MOV X10, 64(X6)
+ MOV X11, 72(X6)
+ MOV X12, 80(X6)
+ MOV X13, 88(X6)
+ MOV X14, 96(X6)
+ MOV X15, 104(X6)
+ MOV X16, 112(X6)
+ MOV X17, 120(X6)
+
+ // Allocate space on stack for RA, saved regs, and callbackArgs.
+ // We need: 8 (RA) + 8 (X9 callee-saved) + 24 (callbackArgs) = 40, round to 176 (22*8)
+ // to match loong64 and ensure we don't overlap with saved register args.
+ // The saved regs end at SP-8 (original), so we need new SP below SP-128.
+ ADD $-(22*8), SP
+
+ // Save link register (RA/X1) and callee-saved register X9
+ // (X9 is used by the assembler for some instructions)
+ MOV X1, 0(SP)
+ MOV X9, 8(SP)
+
+ // Create a struct callbackArgs on our stack.
+ // callbackArgs struct: index(0), args(8), result(16)
+ // Place it at 16(SP) to avoid overlap
+ ADD $16, SP, X9
+ MOV X7, 0(X9) // callback index
+ MOV X6, 8(X9) // address of args vector
+ MOV X0, 16(X9) // result = 0
+
+ // Call crosscall2 with arguments in registers
+ MOV ·callbackWrap_call(SB), X10 // Get the ABIInternal function pointer
+ MOV (X10), X10 // without by using a closure. X10 = fn
+ MOV X9, X11 // X11 = frame (address of callbackArgs)
+ MOV X0, X13 // X13 = ctxt = 0
+
+ CALL crosscall2(SB)
+
+ // Get callback result.
+ ADD $16, SP, X9
+ MOV 16(X9), X10
+
+ // Restore link register and callee-saved X9
+ MOV 8(SP), X9
+ MOV 0(SP), X1
+
+ // Restore stack pointer
+ ADD $(22*8), SP
+
+ RET
diff --git a/raymenu/vendor/github.com/ebitengine/purego/sys_unix_s390x.s b/raymenu/vendor/github.com/ebitengine/purego/sys_unix_s390x.s
new file mode 100644
index 0000000..9eed6d2
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/sys_unix_s390x.s
@@ -0,0 +1,109 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2026 The Ebitengine Authors
+
+//go:build linux
+
+#include "textflag.h"
+#include "go_asm.h"
+#include "funcdata.h"
+
+// S390X ELF ABI callbackasm1 implementation
+// On entry, R0 contains the callback index (set by callbackasm)
+// NOTE: We use R0 instead of R11 because R11 is callee-saved on S390X.
+//
+// S390X stack frame layout:
+// 0(R15) - back chain
+// 48(R15) - register save area (R6-R15)
+// 160(R15) - parameter area
+//
+// S390X uses R2-R6 for integer arguments (5 registers) and F0,F2,F4,F6 for floats (4 registers).
+//
+// Our frame layout (total 264 bytes, 8-byte aligned):
+// 0(R15) - back chain
+// 48(R15) - saved R6-R15 (done by STMG)
+// 160(R15) - callbackArgs struct (32 bytes: index, args, result, stackArgs)
+// 192(R15) - args array start
+//
+// Args array layout:
+// - floats F0,F2,F4,F6 (32 bytes)
+// - ints R2-R6 (40 bytes)
+// Total args array: 72 bytes, ends at 264
+//
+// Stack args in caller's frame start at old_R15+160
+
+#define FRAME_SIZE 264
+#define CB_ARGS 160
+#define ARGS_ARRAY 192
+#define FLOAT_OFF 0
+#define INT_OFF 32
+
+TEXT callbackasm1(SB), NOSPLIT|NOFRAME, $0
+ NO_LOCAL_POINTERS
+
+ // On entry, the trampoline in zcallback_s390x.s left
+ // the callback index in R0 (NOT R11, since R11 is callee-saved).
+ // R6 contains the 5th integer argument.
+
+ // Save R6-R15 in caller's frame (per S390X ABI) BEFORE allocating our frame
+ // STMG stores R6's current value (the 5th arg) at 48(R15)
+ STMG R6, R15, 48(R15)
+
+ // Save current stack pointer (will be back chain)
+ MOVD R15, R1
+
+ // Allocate our stack frame
+ SUB $FRAME_SIZE, R15
+ MOVD R1, 0(R15) // back chain
+
+ // Save R0 (callback index) immediately - it's volatile
+ MOVD R0, (CB_ARGS+0)(R15)
+
+ // Save callback arguments to args array.
+ // Layout: floats first (F0,F2,F4,F6), then ints (R2-R6)
+ FMOVD F0, (ARGS_ARRAY+FLOAT_OFF+0*8)(R15)
+ FMOVD F2, (ARGS_ARRAY+FLOAT_OFF+1*8)(R15)
+ FMOVD F4, (ARGS_ARRAY+FLOAT_OFF+2*8)(R15)
+ FMOVD F6, (ARGS_ARRAY+FLOAT_OFF+3*8)(R15)
+
+ MOVD R2, (ARGS_ARRAY+INT_OFF+0*8)(R15)
+ MOVD R3, (ARGS_ARRAY+INT_OFF+1*8)(R15)
+ MOVD R4, (ARGS_ARRAY+INT_OFF+2*8)(R15)
+ MOVD R5, (ARGS_ARRAY+INT_OFF+3*8)(R15)
+
+ // R6 (5th int arg) was saved at 48(old_R15) by STMG
+ // old_R15 = current R15 + FRAME_SIZE, so R6 is at 48+FRAME_SIZE(R15) = 312(R15)
+ MOVD (48+FRAME_SIZE)(R15), R1
+ MOVD R1, (ARGS_ARRAY+INT_OFF+4*8)(R15)
+
+ // Finish setting up callbackArgs struct at CB_ARGS(R15)
+ // struct { index uintptr; args unsafe.Pointer; result uintptr; stackArgs unsafe.Pointer }
+ // Note: index was already saved earlier
+ ADD $ARGS_ARRAY, R15, R1
+ MOVD R1, (CB_ARGS+8)(R15) // args = address of register args
+ MOVD $0, (CB_ARGS+16)(R15) // result = 0
+
+ // stackArgs points to caller's stack arguments at old_R15+160 = R15+FRAME_SIZE+160
+ ADD $(FRAME_SIZE+160), R15, R1
+ MOVD R1, (CB_ARGS+24)(R15) // stackArgs = &caller_stack_args
+
+ // Call crosscall2 with arguments in registers:
+ // R2 = fn (from callbackWrap_call closure)
+ // R3 = frame (address of callbackArgs)
+ // R5 = ctxt (0)
+ MOVD ·callbackWrap_call(SB), R2
+ MOVD (R2), R2 // dereference closure to get fn
+ ADD $CB_ARGS, R15, R3 // frame = &callbackArgs
+ MOVD $0, R5 // ctxt = 0
+
+ BL crosscall2(SB)
+
+ // Get callback result into R2
+ MOVD (CB_ARGS+16)(R15), R2
+
+ // Deallocate frame
+ ADD $FRAME_SIZE, R15
+
+ // Restore R6-R15 from caller's frame
+ LMG 48(R15), R6, R15
+
+ RET
diff --git a/raymenu/vendor/github.com/ebitengine/purego/syscall.go b/raymenu/vendor/github.com/ebitengine/purego/syscall.go
new file mode 100644
index 0000000..7b45383
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/syscall.go
@@ -0,0 +1,83 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
+
+//go:build !386 && !arm && (darwin || freebsd || linux || netbsd || windows)
+
+package purego
+
+// CDecl marks a function as being called using the __cdecl calling convention as defined in
+// the [MSDocs] when passed to NewCallback. It must be the first argument to the function.
+// This is only useful on 386 Windows, but it is safe to use on other platforms.
+//
+// [MSDocs]: https://learn.microsoft.com/en-us/cpp/cpp/cdecl?view=msvc-170
+type CDecl struct{}
+
+const (
+ maxArgs = 15
+)
+
+type syscall15Args struct {
+ fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 uintptr
+ f1, f2, f3, f4, f5, f6, f7, f8 uintptr
+ arm64_r8 uintptr
+}
+
+func (s *syscall15Args) Set(fn uintptr, ints []uintptr, floats []uintptr, r8 uintptr) {
+ s.fn = fn
+ s.a1 = ints[0]
+ s.a2 = ints[1]
+ s.a3 = ints[2]
+ s.a4 = ints[3]
+ s.a5 = ints[4]
+ s.a6 = ints[5]
+ s.a7 = ints[6]
+ s.a8 = ints[7]
+ s.a9 = ints[8]
+ s.a10 = ints[9]
+ s.a11 = ints[10]
+ s.a12 = ints[11]
+ s.a13 = ints[12]
+ s.a14 = ints[13]
+ s.a15 = ints[14]
+ s.f1 = floats[0]
+ s.f2 = floats[1]
+ s.f3 = floats[2]
+ s.f4 = floats[3]
+ s.f5 = floats[4]
+ s.f6 = floats[5]
+ s.f7 = floats[6]
+ s.f8 = floats[7]
+ s.arm64_r8 = r8
+}
+
+// SyscallN takes fn, a C function pointer and a list of arguments as uintptr.
+// There is an internal maximum number of arguments that SyscallN can take. It panics
+// when the maximum is exceeded. It returns the result and the libc error code if there is one.
+//
+// In order to call this function properly make sure to follow all the rules specified in [unsafe.Pointer]
+// especially point 4.
+//
+// NOTE: SyscallN does not properly call functions that have both integer and float parameters.
+// See discussion comment https://github.com/ebiten/purego/pull/1#issuecomment-1128057607
+// for an explanation of why that is.
+//
+// On amd64, if there are more than 8 floats the 9th and so on will be placed incorrectly on the
+// stack.
+//
+// The pragma go:nosplit is not needed at this function declaration because it uses go:uintptrescapes
+// which forces all the objects that the uintptrs point to onto the heap where a stack split won't affect
+// their memory location.
+//
+//go:uintptrescapes
+func SyscallN(fn uintptr, args ...uintptr) (r1, r2, err uintptr) {
+ if fn == 0 {
+ panic("purego: fn is nil")
+ }
+ if len(args) > maxArgs {
+ panic("purego: too many arguments to SyscallN")
+ }
+ // add padding so there is no out-of-bounds slicing
+ var tmp [maxArgs]uintptr
+ copy(tmp[:], args)
+ return syscall_syscall15X(fn, tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5], tmp[6], tmp[7], tmp[8], tmp[9], tmp[10], tmp[11], tmp[12], tmp[13], tmp[14])
+}
diff --git a/raymenu/vendor/github.com/ebitengine/purego/syscall_32bit.go b/raymenu/vendor/github.com/ebitengine/purego/syscall_32bit.go
new file mode 100644
index 0000000..f9f3763
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/syscall_32bit.go
@@ -0,0 +1,109 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
+
+//go:build (386 || arm) && (freebsd || linux || netbsd || windows)
+
+package purego
+
+// CDecl marks a function as being called using the __cdecl calling convention as defined in
+// the [MSDocs] when passed to NewCallback. It must be the first argument to the function.
+// This is only useful on 386 Windows, but it is safe to use on other platforms.
+//
+// [MSDocs]: https://learn.microsoft.com/en-us/cpp/cpp/cdecl?view=msvc-170
+type CDecl struct{}
+
+const (
+ maxArgs = 32
+)
+
+type syscall15Args struct {
+ fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 uintptr
+ a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32 uintptr
+ f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16 uintptr
+ arm64_r8 uintptr
+}
+
+func (s *syscall15Args) Set(fn uintptr, ints []uintptr, floats []uintptr, r8 uintptr) {
+ s.fn = fn
+ s.a1 = ints[0]
+ s.a2 = ints[1]
+ s.a3 = ints[2]
+ s.a4 = ints[3]
+ s.a5 = ints[4]
+ s.a6 = ints[5]
+ s.a7 = ints[6]
+ s.a8 = ints[7]
+ s.a9 = ints[8]
+ s.a10 = ints[9]
+ s.a11 = ints[10]
+ s.a12 = ints[11]
+ s.a13 = ints[12]
+ s.a14 = ints[13]
+ s.a15 = ints[14]
+ s.a16 = ints[15]
+ s.a17 = ints[16]
+ s.a18 = ints[17]
+ s.a19 = ints[18]
+ s.a20 = ints[19]
+ s.a21 = ints[20]
+ s.a22 = ints[21]
+ s.a23 = ints[22]
+ s.a24 = ints[23]
+ s.a25 = ints[24]
+ s.a26 = ints[25]
+ s.a27 = ints[26]
+ s.a28 = ints[27]
+ s.a29 = ints[28]
+ s.a30 = ints[29]
+ s.a31 = ints[30]
+ s.a32 = ints[31]
+ s.f1 = floats[0]
+ s.f2 = floats[1]
+ s.f3 = floats[2]
+ s.f4 = floats[3]
+ s.f5 = floats[4]
+ s.f6 = floats[5]
+ s.f7 = floats[6]
+ s.f8 = floats[7]
+ s.f9 = floats[8]
+ s.f10 = floats[9]
+ s.f11 = floats[10]
+ s.f12 = floats[11]
+ s.f13 = floats[12]
+ s.f14 = floats[13]
+ s.f15 = floats[14]
+ s.f16 = floats[15]
+ s.arm64_r8 = r8
+}
+
+// SyscallN takes fn, a C function pointer and a list of arguments as uintptr.
+// There is an internal maximum number of arguments that SyscallN can take. It panics
+// when the maximum is exceeded. It returns the result and the libc error code if there is one.
+//
+// In order to call this function properly make sure to follow all the rules specified in [unsafe.Pointer]
+// especially point 4.
+//
+// NOTE: SyscallN does not properly call functions that have both integer and float parameters.
+// See discussion comment https://github.com/ebiten/purego/pull/1#issuecomment-1128057607
+// for an explanation of why that is.
+//
+// On amd64, if there are more than 8 floats the 9th and so on will be placed incorrectly on the
+// stack.
+//
+// The pragma go:nosplit is not needed at this function declaration because it uses go:uintptrescapes
+// which forces all the objects that the uintptrs point to onto the heap where a stack split won't affect
+// their memory location.
+//
+//go:uintptrescapes
+func SyscallN(fn uintptr, args ...uintptr) (r1, r2, err uintptr) {
+ if fn == 0 {
+ panic("purego: fn is nil")
+ }
+ if len(args) > maxArgs {
+ panic("purego: too many arguments to SyscallN")
+ }
+ // add padding so there is no out-of-bounds slicing
+ var tmp [maxArgs]uintptr
+ copy(tmp[:], args)
+ return syscall_syscall15X(fn, tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5], tmp[6], tmp[7], tmp[8], tmp[9], tmp[10], tmp[11], tmp[12], tmp[13], tmp[14])
+}
diff --git a/raymenu/vendor/github.com/ebitengine/purego/syscall_cgo_linux.go b/raymenu/vendor/github.com/ebitengine/purego/syscall_cgo_linux.go
new file mode 100644
index 0000000..179167f
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/syscall_cgo_linux.go
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
+
+//go:build cgo && !(386 || amd64 || arm || arm64 || loong64 || ppc64le || riscv64 || s390x)
+
+package purego
+
+import (
+ "github.com/ebitengine/purego/internal/cgo"
+)
+
+var syscall15XABI0 = uintptr(cgo.Syscall15XABI0)
+
+//go:nosplit
+func syscall_syscall15X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 uintptr) (r1, r2, err uintptr) {
+ return cgo.Syscall15X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15)
+}
+
+func NewCallback(_ any) uintptr {
+ panic("purego: NewCallback on Linux is only supported on 386/amd64/arm64/arm/loong64/ppc64le/riscv64/s390x")
+}
diff --git a/raymenu/vendor/github.com/ebitengine/purego/syscall_sysv.go b/raymenu/vendor/github.com/ebitengine/purego/syscall_sysv.go
new file mode 100644
index 0000000..e35b32e
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/syscall_sysv.go
@@ -0,0 +1,320 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
+
+// TODO: remove s390x cgo dependency once golang/go#77449 is resolved
+//go:build darwin || freebsd || (linux && (386 || amd64 || arm || arm64 || loong64 || ppc64le || riscv64 || (cgo && s390x))) || netbsd
+
+package purego
+
+import (
+ "reflect"
+ "runtime"
+ "sync"
+ "unsafe"
+)
+
+var syscall15XABI0 uintptr
+
+func syscall_syscall15X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 uintptr) (r1, r2, err uintptr) {
+ args := thePool.Get().(*syscall15Args)
+ defer thePool.Put(args)
+
+ *args = syscall15Args{
+ fn: fn,
+ a1: a1, a2: a2, a3: a3, a4: a4, a5: a5, a6: a6, a7: a7, a8: a8,
+ a9: a9, a10: a10, a11: a11, a12: a12, a13: a13, a14: a14, a15: a15,
+ f1: a1, f2: a2, f3: a3, f4: a4, f5: a5, f6: a6, f7: a7, f8: a8,
+ }
+
+ runtime_cgocall(syscall15XABI0, unsafe.Pointer(args))
+ return args.a1, args.a2, args.a3
+}
+
+// NewCallback converts a Go function to a function pointer conforming to the C calling convention.
+// This is useful when interoperating with C code requiring callbacks. The argument is expected to be a
+// function with zero or one uintptr-sized result. The function must not have arguments with size larger than the size
+// of uintptr. Only a limited number of callbacks may be created in a single Go process, and any memory allocated
+// for these callbacks is never released. At least 2000 callbacks can always be created. Although this function
+// provides similar functionality to windows.NewCallback it is distinct.
+func NewCallback(fn any) uintptr {
+ ty := reflect.TypeOf(fn)
+ for i := 0; i < ty.NumIn(); i++ {
+ in := ty.In(i)
+ if !in.AssignableTo(reflect.TypeOf(CDecl{})) {
+ continue
+ }
+ if i != 0 {
+ panic("purego: CDecl must be the first argument")
+ }
+ }
+ return compileCallback(fn)
+}
+
+// maxCb is the maximum number of callbacks
+// only increase this if you have added more to the callbackasm function
+const maxCB = 2000
+
+var cbs struct {
+ lock sync.Mutex
+ numFn int // the number of functions currently in cbs.funcs
+ funcs [maxCB]reflect.Value // the saved callbacks
+}
+
+func compileCallback(fn any) uintptr {
+ val := reflect.ValueOf(fn)
+ if val.Kind() != reflect.Func {
+ panic("purego: the type must be a function but was not")
+ }
+ if val.IsNil() {
+ panic("purego: function must not be nil")
+ }
+ ty := val.Type()
+ for i := 0; i < ty.NumIn(); i++ {
+ in := ty.In(i)
+ switch in.Kind() {
+ case reflect.Struct:
+ if i == 0 && in.AssignableTo(reflect.TypeOf(CDecl{})) {
+ continue
+ }
+ fallthrough
+ case reflect.Interface, reflect.Func, reflect.Slice,
+ reflect.Chan, reflect.Complex64, reflect.Complex128,
+ reflect.String, reflect.Map, reflect.Invalid:
+ panic("purego: unsupported argument type: " + in.Kind().String())
+ }
+ }
+output:
+ switch {
+ case ty.NumOut() == 1:
+ switch ty.Out(0).Kind() {
+ case reflect.Pointer, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
+ reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr,
+ reflect.Bool, reflect.UnsafePointer:
+ break output
+ }
+ panic("purego: unsupported return type: " + ty.String())
+ case ty.NumOut() > 1:
+ panic("purego: callbacks can only have one return")
+ }
+ cbs.lock.Lock()
+ defer cbs.lock.Unlock()
+ if cbs.numFn >= maxCB {
+ panic("purego: the maximum number of callbacks has been reached")
+ }
+ cbs.funcs[cbs.numFn] = val
+ cbs.numFn++
+ return callbackasmAddr(cbs.numFn - 1)
+}
+
+const ptrSize = unsafe.Sizeof((*int)(nil))
+
+const callbackMaxFrame = 64 * ptrSize
+
+// callbackasm is implemented in zcallback_GOOS_GOARCH.s
+//
+//go:linkname __callbackasm callbackasm
+var __callbackasm byte
+var callbackasmABI0 = uintptr(unsafe.Pointer(&__callbackasm))
+
+// callbackWrap_call allows the calling of the ABIInternal wrapper
+// which is required for runtime.cgocallback without the
+// tag which is only allowed in the runtime.
+// This closure is used inside sys_darwin_GOARCH.s
+var callbackWrap_call = callbackWrap
+
+// callbackWrap is called by assembly code which determines which Go function to call.
+// This function takes the arguments and passes them to the Go function and returns the result.
+func callbackWrap(a *callbackArgs) {
+ cbs.lock.Lock()
+ fn := cbs.funcs[a.index]
+ cbs.lock.Unlock()
+ fnType := fn.Type()
+ args := make([]reflect.Value, fnType.NumIn())
+ frame := (*[callbackMaxFrame]uintptr)(a.args)
+ // stackFrame points to stack-passed arguments. On most architectures this is
+ // contiguous with frame (after register args), but on ppc64le it's separate.
+ var stackFrame *[callbackMaxFrame]uintptr
+ if sf := a.stackFrame(); sf != nil {
+ // Only ppc64le uses separate stackArgs pointer due to NOSPLIT constraints
+ stackFrame = (*[callbackMaxFrame]uintptr)(sf)
+ }
+ // floatsN and intsN track the number of register slots used, not argument count.
+ // This distinction matters on ARM32 where float64 uses 2 slots (32-bit registers).
+ var floatsN int
+ var intsN int
+ // stackSlot points to the index into frame (or stackFrame) of the current stack element.
+ // When stackFrame is nil, stack begins after float and integer registers in frame.
+ // When stackFrame is not nil (ppc64le), stackSlot indexes into stackFrame starting at 0.
+ stackSlot := numOfIntegerRegisters() + numOfFloatRegisters()
+ if stackFrame != nil {
+ // ppc64le: stackArgs is a separate pointer, indices start at 0
+ stackSlot = 0
+ }
+ // stackByteOffset tracks the byte offset within the stack area for Darwin ARM64
+ // tight packing. On Darwin ARM64, C passes small types packed on the stack.
+ stackByteOffset := uintptr(0)
+ for i := range args {
+ // slots is the number of pointer-sized slots the argument takes
+ var slots int
+ inType := fnType.In(i)
+ switch inType.Kind() {
+ case reflect.Float32, reflect.Float64:
+ slots = int((fnType.In(i).Size() + ptrSize - 1) / ptrSize)
+ if floatsN+slots > numOfFloatRegisters() {
+ if runtime.GOOS == "darwin" && runtime.GOARCH == "arm64" {
+ // Darwin ARM64: read from packed stack with proper alignment
+ args[i] = callbackArgFromStack(a.args, stackSlot, &stackByteOffset, inType)
+ } else if stackFrame != nil {
+ // ppc64le/s390x: stack args are in separate stackFrame
+ if runtime.GOARCH == "s390x" {
+ // s390x big-endian: sub-8-byte values are right-justified
+ args[i] = callbackArgFromSlotBigEndian(unsafe.Pointer(&stackFrame[stackSlot]), inType)
+ } else {
+ args[i] = reflect.NewAt(inType, unsafe.Pointer(&stackFrame[stackSlot])).Elem()
+ }
+ stackSlot += slots
+ } else {
+ args[i] = reflect.NewAt(inType, unsafe.Pointer(&frame[stackSlot])).Elem()
+ stackSlot += slots
+ }
+ } else {
+ if runtime.GOARCH == "s390x" {
+ // s390x big-endian: float32 is right-justified in 8-byte FPR slot
+ args[i] = callbackArgFromSlotBigEndian(unsafe.Pointer(&frame[floatsN]), inType)
+ } else {
+ args[i] = reflect.NewAt(inType, unsafe.Pointer(&frame[floatsN])).Elem()
+ }
+ }
+ floatsN += slots
+ case reflect.Struct:
+ // This is the CDecl field
+ args[i] = reflect.Zero(inType)
+ default:
+ slots = int((inType.Size() + ptrSize - 1) / ptrSize)
+ if intsN+slots > numOfIntegerRegisters() {
+ if runtime.GOOS == "darwin" && runtime.GOARCH == "arm64" {
+ // Darwin ARM64: read from packed stack with proper alignment
+ args[i] = callbackArgFromStack(a.args, stackSlot, &stackByteOffset, inType)
+ } else if stackFrame != nil {
+ // ppc64le/s390x: stack args are in separate stackFrame
+ if runtime.GOARCH == "s390x" {
+ // s390x big-endian: sub-8-byte values are right-justified
+ args[i] = callbackArgFromSlotBigEndian(unsafe.Pointer(&stackFrame[stackSlot]), inType)
+ } else {
+ args[i] = reflect.NewAt(inType, unsafe.Pointer(&stackFrame[stackSlot])).Elem()
+ }
+ stackSlot += slots
+ } else {
+ args[i] = reflect.NewAt(inType, unsafe.Pointer(&frame[stackSlot])).Elem()
+ stackSlot += slots
+ }
+ } else {
+ // the integers begin after the floats in frame
+ pos := intsN + numOfFloatRegisters()
+ if runtime.GOARCH == "s390x" {
+ // s390x big-endian: sub-8-byte values are right-justified in GPR slot
+ args[i] = callbackArgFromSlotBigEndian(unsafe.Pointer(&frame[pos]), inType)
+ } else {
+ args[i] = reflect.NewAt(inType, unsafe.Pointer(&frame[pos])).Elem()
+ }
+ }
+ intsN += slots
+ }
+ }
+ ret := fn.Call(args)
+ if len(ret) > 0 {
+ switch k := ret[0].Kind(); k {
+ case reflect.Uint, reflect.Uint64, reflect.Uint32, reflect.Uint16, reflect.Uint8, reflect.Uintptr:
+ a.result = uintptr(ret[0].Uint())
+ case reflect.Int, reflect.Int64, reflect.Int32, reflect.Int16, reflect.Int8:
+ a.result = uintptr(ret[0].Int())
+ case reflect.Bool:
+ if ret[0].Bool() {
+ a.result = 1
+ } else {
+ a.result = 0
+ }
+ case reflect.Pointer:
+ a.result = ret[0].Pointer()
+ case reflect.UnsafePointer:
+ a.result = ret[0].Pointer()
+ default:
+ panic("purego: unsupported kind: " + k.String())
+ }
+ }
+}
+
+// callbackArgFromStack reads an argument from the tightly-packed stack area on Darwin ARM64.
+// The C ABI on Darwin ARM64 packs small types on the stack without padding to 8 bytes.
+// This function handles proper alignment and advances stackByteOffset accordingly.
+func callbackArgFromStack(argsBase unsafe.Pointer, stackSlot int, stackByteOffset *uintptr, inType reflect.Type) reflect.Value {
+ // Calculate base address of stack area (after float and int registers)
+ stackBase := unsafe.Add(argsBase, stackSlot*int(ptrSize))
+
+ // Get type's natural alignment
+ align := uintptr(inType.Align())
+ size := inType.Size()
+
+ // Align the offset
+ if *stackByteOffset%align != 0 {
+ *stackByteOffset = (*stackByteOffset + align - 1) &^ (align - 1)
+ }
+
+ // Read value at aligned offset
+ ptr := unsafe.Add(stackBase, *stackByteOffset)
+ *stackByteOffset += size
+
+ return reflect.NewAt(inType, ptr).Elem()
+}
+
+// callbackArgFromSlotBigEndian reads an argument from an 8-byte slot on big-endian architectures.
+// On s390x:
+// - Integer types are right-justified in GPRs: sub-8-byte values are at offset (8 - size)
+// - Float32 in FPRs is left-justified: stored in upper 32 bits, so at offset 0
+// - Float64 occupies the full 8-byte slot
+func callbackArgFromSlotBigEndian(slotPtr unsafe.Pointer, inType reflect.Type) reflect.Value {
+ size := inType.Size()
+ if size >= 8 {
+ // 8-byte values occupy the entire slot
+ return reflect.NewAt(inType, slotPtr).Elem()
+ }
+ // Float32 is left-justified in FPRs (upper 32 bits), so offset is 0
+ if inType.Kind() == reflect.Float32 {
+ return reflect.NewAt(inType, slotPtr).Elem()
+ }
+ // Integer types are right-justified: offset = 8 - size
+ offset := 8 - size
+ ptr := unsafe.Add(slotPtr, offset)
+ return reflect.NewAt(inType, ptr).Elem()
+}
+
+// callbackasmAddr returns address of runtime.callbackasm
+// function adjusted by i.
+// On x86 and amd64, runtime.callbackasm is a series of CALL instructions,
+// and we want callback to arrive at
+// correspondent call instruction instead of start of
+// runtime.callbackasm.
+// On ARM, runtime.callbackasm is a series of mov and branch instructions.
+// R12 is loaded with the callback index. Each entry is two instructions,
+// hence 8 bytes.
+func callbackasmAddr(i int) uintptr {
+ var entrySize int
+ switch runtime.GOARCH {
+ default:
+ panic("purego: unsupported architecture")
+ case "amd64":
+ // On amd64, each callback entry is just a CALL instruction (5 bytes)
+ entrySize = 5
+ case "386":
+ // On 386, each callback entry is MOVL $imm, CX (5 bytes) + JMP (5 bytes)
+ entrySize = 10
+ case "arm", "arm64", "loong64", "ppc64le", "riscv64":
+ // On ARM, ARM64, Loong64, PPC64LE and RISCV64, each entry is a MOV instruction
+ // followed by a branch instruction
+ entrySize = 8
+ case "s390x":
+ // On S390X, each entry is LGHI (4 bytes) + JG (6 bytes)
+ entrySize = 10
+ }
+ return callbackasmABI0 + uintptr(i*entrySize)
+}
diff --git a/raymenu/vendor/github.com/ebitengine/purego/syscall_sysv_others.go b/raymenu/vendor/github.com/ebitengine/purego/syscall_sysv_others.go
new file mode 100644
index 0000000..d4f6c7b
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/syscall_sysv_others.go
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2026 The Ebitengine Authors
+
+//go:build darwin || freebsd || (linux && (386 || amd64 || arm || arm64 || loong64 || riscv64)) || netbsd
+
+package purego
+
+import "unsafe"
+
+type callbackArgs struct {
+ index uintptr
+ // args points to the argument block.
+ //
+ // The structure of the arguments goes
+ // float registers followed by the
+ // integer registers followed by the stack.
+ //
+ // This variable is treated as a continuous
+ // block of memory containing all of the arguments
+ // for this callback.
+ args unsafe.Pointer
+ // Below are out-args from callbackWrap
+ result uintptr
+}
+
+func (c *callbackArgs) stackFrame() unsafe.Pointer {
+ return nil
+}
diff --git a/raymenu/vendor/github.com/ebitengine/purego/syscall_sysv_stackargs.go b/raymenu/vendor/github.com/ebitengine/purego/syscall_sysv_stackargs.go
new file mode 100644
index 0000000..87ed981
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/syscall_sysv_stackargs.go
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2026 The Ebitengine Authors
+
+//go:build linux && (ppc64le || s390x)
+
+package purego
+
+import "unsafe"
+
+type callbackArgs struct {
+ index uintptr
+ // args points to the argument block.
+ //
+ // The structure of the arguments goes
+ // float registers followed by the
+ // integer registers followed by the stack.
+ //
+ // This variable is treated as a continuous
+ // block of memory containing all of the arguments
+ // for this callback.
+ args unsafe.Pointer
+ // Below are out-args from callbackWrap
+ result uintptr
+ // stackArgs points to stack-passed arguments for architectures where
+ // they can't be made contiguous with register args (e.g., ppc64le).
+ // On other architectures, this is nil and stack args are read from
+ // the end of the args block.
+ stackArgs unsafe.Pointer
+}
+
+func (c *callbackArgs) stackFrame() unsafe.Pointer {
+ return c.stackArgs
+}
diff --git a/raymenu/vendor/github.com/ebitengine/purego/syscall_windows.go b/raymenu/vendor/github.com/ebitengine/purego/syscall_windows.go
new file mode 100644
index 0000000..5afd8d8
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/syscall_windows.go
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: 2022 The Ebitengine Authors
+
+package purego
+
+import (
+ "reflect"
+ "syscall"
+)
+
+var syscall15XABI0 uintptr
+
+func syscall_syscall15X(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 uintptr) (r1, r2, err uintptr) {
+ r1, r2, errno := syscall.Syscall15(fn, 15, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15)
+ return r1, r2, uintptr(errno)
+}
+
+// NewCallback converts a Go function to a function pointer conforming to the stdcall calling convention.
+// This is useful when interoperating with Windows code requiring callbacks. The argument is expected to be a
+// function with one uintptr-sized result. The function must not have arguments with size larger than the
+// size of uintptr. Only a limited number of callbacks may be created in a single Go process, and any memory
+// allocated for these callbacks is never released. Between NewCallback and NewCallbackCDecl, at least 1024
+// callbacks can always be created. Although this function is similiar to the darwin version it may act
+// differently.
+func NewCallback(fn any) uintptr {
+ isCDecl := false
+ ty := reflect.TypeOf(fn)
+ for i := 0; i < ty.NumIn(); i++ {
+ in := ty.In(i)
+ if !in.AssignableTo(reflect.TypeOf(CDecl{})) {
+ continue
+ }
+ if i != 0 {
+ panic("purego: CDecl must be the first argument")
+ }
+ isCDecl = true
+ }
+ if isCDecl {
+ return syscall.NewCallbackCDecl(fn)
+ }
+ return syscall.NewCallback(fn)
+}
+
+func loadSymbol(handle uintptr, name string) (uintptr, error) {
+ return syscall.GetProcAddress(syscall.Handle(handle), name)
+}
diff --git a/raymenu/vendor/github.com/ebitengine/purego/zcallback_386.s b/raymenu/vendor/github.com/ebitengine/purego/zcallback_386.s
new file mode 100644
index 0000000..bd2d9c8
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/zcallback_386.s
@@ -0,0 +1,4014 @@
+// Code generated by wincallback.go using 'go generate'. DO NOT EDIT.
+
+//go:build linux
+
+// External code calls into callbackasm at an offset corresponding
+// to the callback index. Callbackasm is a table of MOVL and JMP instructions.
+// The MOVL instruction loads CX with the callback index, and the
+// JMP instruction branches to callbackasm1.
+// callbackasm1 takes the callback index from CX and
+// indexes into an array that stores information about each callback.
+// It then calls the Go implementation for that callback.
+#include "textflag.h"
+
+TEXT callbackasm(SB), NOSPLIT|NOFRAME, $0
+ MOVL $0, CX
+ JMP callbackasm1(SB)
+ MOVL $1, CX
+ JMP callbackasm1(SB)
+ MOVL $2, CX
+ JMP callbackasm1(SB)
+ MOVL $3, CX
+ JMP callbackasm1(SB)
+ MOVL $4, CX
+ JMP callbackasm1(SB)
+ MOVL $5, CX
+ JMP callbackasm1(SB)
+ MOVL $6, CX
+ JMP callbackasm1(SB)
+ MOVL $7, CX
+ JMP callbackasm1(SB)
+ MOVL $8, CX
+ JMP callbackasm1(SB)
+ MOVL $9, CX
+ JMP callbackasm1(SB)
+ MOVL $10, CX
+ JMP callbackasm1(SB)
+ MOVL $11, CX
+ JMP callbackasm1(SB)
+ MOVL $12, CX
+ JMP callbackasm1(SB)
+ MOVL $13, CX
+ JMP callbackasm1(SB)
+ MOVL $14, CX
+ JMP callbackasm1(SB)
+ MOVL $15, CX
+ JMP callbackasm1(SB)
+ MOVL $16, CX
+ JMP callbackasm1(SB)
+ MOVL $17, CX
+ JMP callbackasm1(SB)
+ MOVL $18, CX
+ JMP callbackasm1(SB)
+ MOVL $19, CX
+ JMP callbackasm1(SB)
+ MOVL $20, CX
+ JMP callbackasm1(SB)
+ MOVL $21, CX
+ JMP callbackasm1(SB)
+ MOVL $22, CX
+ JMP callbackasm1(SB)
+ MOVL $23, CX
+ JMP callbackasm1(SB)
+ MOVL $24, CX
+ JMP callbackasm1(SB)
+ MOVL $25, CX
+ JMP callbackasm1(SB)
+ MOVL $26, CX
+ JMP callbackasm1(SB)
+ MOVL $27, CX
+ JMP callbackasm1(SB)
+ MOVL $28, CX
+ JMP callbackasm1(SB)
+ MOVL $29, CX
+ JMP callbackasm1(SB)
+ MOVL $30, CX
+ JMP callbackasm1(SB)
+ MOVL $31, CX
+ JMP callbackasm1(SB)
+ MOVL $32, CX
+ JMP callbackasm1(SB)
+ MOVL $33, CX
+ JMP callbackasm1(SB)
+ MOVL $34, CX
+ JMP callbackasm1(SB)
+ MOVL $35, CX
+ JMP callbackasm1(SB)
+ MOVL $36, CX
+ JMP callbackasm1(SB)
+ MOVL $37, CX
+ JMP callbackasm1(SB)
+ MOVL $38, CX
+ JMP callbackasm1(SB)
+ MOVL $39, CX
+ JMP callbackasm1(SB)
+ MOVL $40, CX
+ JMP callbackasm1(SB)
+ MOVL $41, CX
+ JMP callbackasm1(SB)
+ MOVL $42, CX
+ JMP callbackasm1(SB)
+ MOVL $43, CX
+ JMP callbackasm1(SB)
+ MOVL $44, CX
+ JMP callbackasm1(SB)
+ MOVL $45, CX
+ JMP callbackasm1(SB)
+ MOVL $46, CX
+ JMP callbackasm1(SB)
+ MOVL $47, CX
+ JMP callbackasm1(SB)
+ MOVL $48, CX
+ JMP callbackasm1(SB)
+ MOVL $49, CX
+ JMP callbackasm1(SB)
+ MOVL $50, CX
+ JMP callbackasm1(SB)
+ MOVL $51, CX
+ JMP callbackasm1(SB)
+ MOVL $52, CX
+ JMP callbackasm1(SB)
+ MOVL $53, CX
+ JMP callbackasm1(SB)
+ MOVL $54, CX
+ JMP callbackasm1(SB)
+ MOVL $55, CX
+ JMP callbackasm1(SB)
+ MOVL $56, CX
+ JMP callbackasm1(SB)
+ MOVL $57, CX
+ JMP callbackasm1(SB)
+ MOVL $58, CX
+ JMP callbackasm1(SB)
+ MOVL $59, CX
+ JMP callbackasm1(SB)
+ MOVL $60, CX
+ JMP callbackasm1(SB)
+ MOVL $61, CX
+ JMP callbackasm1(SB)
+ MOVL $62, CX
+ JMP callbackasm1(SB)
+ MOVL $63, CX
+ JMP callbackasm1(SB)
+ MOVL $64, CX
+ JMP callbackasm1(SB)
+ MOVL $65, CX
+ JMP callbackasm1(SB)
+ MOVL $66, CX
+ JMP callbackasm1(SB)
+ MOVL $67, CX
+ JMP callbackasm1(SB)
+ MOVL $68, CX
+ JMP callbackasm1(SB)
+ MOVL $69, CX
+ JMP callbackasm1(SB)
+ MOVL $70, CX
+ JMP callbackasm1(SB)
+ MOVL $71, CX
+ JMP callbackasm1(SB)
+ MOVL $72, CX
+ JMP callbackasm1(SB)
+ MOVL $73, CX
+ JMP callbackasm1(SB)
+ MOVL $74, CX
+ JMP callbackasm1(SB)
+ MOVL $75, CX
+ JMP callbackasm1(SB)
+ MOVL $76, CX
+ JMP callbackasm1(SB)
+ MOVL $77, CX
+ JMP callbackasm1(SB)
+ MOVL $78, CX
+ JMP callbackasm1(SB)
+ MOVL $79, CX
+ JMP callbackasm1(SB)
+ MOVL $80, CX
+ JMP callbackasm1(SB)
+ MOVL $81, CX
+ JMP callbackasm1(SB)
+ MOVL $82, CX
+ JMP callbackasm1(SB)
+ MOVL $83, CX
+ JMP callbackasm1(SB)
+ MOVL $84, CX
+ JMP callbackasm1(SB)
+ MOVL $85, CX
+ JMP callbackasm1(SB)
+ MOVL $86, CX
+ JMP callbackasm1(SB)
+ MOVL $87, CX
+ JMP callbackasm1(SB)
+ MOVL $88, CX
+ JMP callbackasm1(SB)
+ MOVL $89, CX
+ JMP callbackasm1(SB)
+ MOVL $90, CX
+ JMP callbackasm1(SB)
+ MOVL $91, CX
+ JMP callbackasm1(SB)
+ MOVL $92, CX
+ JMP callbackasm1(SB)
+ MOVL $93, CX
+ JMP callbackasm1(SB)
+ MOVL $94, CX
+ JMP callbackasm1(SB)
+ MOVL $95, CX
+ JMP callbackasm1(SB)
+ MOVL $96, CX
+ JMP callbackasm1(SB)
+ MOVL $97, CX
+ JMP callbackasm1(SB)
+ MOVL $98, CX
+ JMP callbackasm1(SB)
+ MOVL $99, CX
+ JMP callbackasm1(SB)
+ MOVL $100, CX
+ JMP callbackasm1(SB)
+ MOVL $101, CX
+ JMP callbackasm1(SB)
+ MOVL $102, CX
+ JMP callbackasm1(SB)
+ MOVL $103, CX
+ JMP callbackasm1(SB)
+ MOVL $104, CX
+ JMP callbackasm1(SB)
+ MOVL $105, CX
+ JMP callbackasm1(SB)
+ MOVL $106, CX
+ JMP callbackasm1(SB)
+ MOVL $107, CX
+ JMP callbackasm1(SB)
+ MOVL $108, CX
+ JMP callbackasm1(SB)
+ MOVL $109, CX
+ JMP callbackasm1(SB)
+ MOVL $110, CX
+ JMP callbackasm1(SB)
+ MOVL $111, CX
+ JMP callbackasm1(SB)
+ MOVL $112, CX
+ JMP callbackasm1(SB)
+ MOVL $113, CX
+ JMP callbackasm1(SB)
+ MOVL $114, CX
+ JMP callbackasm1(SB)
+ MOVL $115, CX
+ JMP callbackasm1(SB)
+ MOVL $116, CX
+ JMP callbackasm1(SB)
+ MOVL $117, CX
+ JMP callbackasm1(SB)
+ MOVL $118, CX
+ JMP callbackasm1(SB)
+ MOVL $119, CX
+ JMP callbackasm1(SB)
+ MOVL $120, CX
+ JMP callbackasm1(SB)
+ MOVL $121, CX
+ JMP callbackasm1(SB)
+ MOVL $122, CX
+ JMP callbackasm1(SB)
+ MOVL $123, CX
+ JMP callbackasm1(SB)
+ MOVL $124, CX
+ JMP callbackasm1(SB)
+ MOVL $125, CX
+ JMP callbackasm1(SB)
+ MOVL $126, CX
+ JMP callbackasm1(SB)
+ MOVL $127, CX
+ JMP callbackasm1(SB)
+ MOVL $128, CX
+ JMP callbackasm1(SB)
+ MOVL $129, CX
+ JMP callbackasm1(SB)
+ MOVL $130, CX
+ JMP callbackasm1(SB)
+ MOVL $131, CX
+ JMP callbackasm1(SB)
+ MOVL $132, CX
+ JMP callbackasm1(SB)
+ MOVL $133, CX
+ JMP callbackasm1(SB)
+ MOVL $134, CX
+ JMP callbackasm1(SB)
+ MOVL $135, CX
+ JMP callbackasm1(SB)
+ MOVL $136, CX
+ JMP callbackasm1(SB)
+ MOVL $137, CX
+ JMP callbackasm1(SB)
+ MOVL $138, CX
+ JMP callbackasm1(SB)
+ MOVL $139, CX
+ JMP callbackasm1(SB)
+ MOVL $140, CX
+ JMP callbackasm1(SB)
+ MOVL $141, CX
+ JMP callbackasm1(SB)
+ MOVL $142, CX
+ JMP callbackasm1(SB)
+ MOVL $143, CX
+ JMP callbackasm1(SB)
+ MOVL $144, CX
+ JMP callbackasm1(SB)
+ MOVL $145, CX
+ JMP callbackasm1(SB)
+ MOVL $146, CX
+ JMP callbackasm1(SB)
+ MOVL $147, CX
+ JMP callbackasm1(SB)
+ MOVL $148, CX
+ JMP callbackasm1(SB)
+ MOVL $149, CX
+ JMP callbackasm1(SB)
+ MOVL $150, CX
+ JMP callbackasm1(SB)
+ MOVL $151, CX
+ JMP callbackasm1(SB)
+ MOVL $152, CX
+ JMP callbackasm1(SB)
+ MOVL $153, CX
+ JMP callbackasm1(SB)
+ MOVL $154, CX
+ JMP callbackasm1(SB)
+ MOVL $155, CX
+ JMP callbackasm1(SB)
+ MOVL $156, CX
+ JMP callbackasm1(SB)
+ MOVL $157, CX
+ JMP callbackasm1(SB)
+ MOVL $158, CX
+ JMP callbackasm1(SB)
+ MOVL $159, CX
+ JMP callbackasm1(SB)
+ MOVL $160, CX
+ JMP callbackasm1(SB)
+ MOVL $161, CX
+ JMP callbackasm1(SB)
+ MOVL $162, CX
+ JMP callbackasm1(SB)
+ MOVL $163, CX
+ JMP callbackasm1(SB)
+ MOVL $164, CX
+ JMP callbackasm1(SB)
+ MOVL $165, CX
+ JMP callbackasm1(SB)
+ MOVL $166, CX
+ JMP callbackasm1(SB)
+ MOVL $167, CX
+ JMP callbackasm1(SB)
+ MOVL $168, CX
+ JMP callbackasm1(SB)
+ MOVL $169, CX
+ JMP callbackasm1(SB)
+ MOVL $170, CX
+ JMP callbackasm1(SB)
+ MOVL $171, CX
+ JMP callbackasm1(SB)
+ MOVL $172, CX
+ JMP callbackasm1(SB)
+ MOVL $173, CX
+ JMP callbackasm1(SB)
+ MOVL $174, CX
+ JMP callbackasm1(SB)
+ MOVL $175, CX
+ JMP callbackasm1(SB)
+ MOVL $176, CX
+ JMP callbackasm1(SB)
+ MOVL $177, CX
+ JMP callbackasm1(SB)
+ MOVL $178, CX
+ JMP callbackasm1(SB)
+ MOVL $179, CX
+ JMP callbackasm1(SB)
+ MOVL $180, CX
+ JMP callbackasm1(SB)
+ MOVL $181, CX
+ JMP callbackasm1(SB)
+ MOVL $182, CX
+ JMP callbackasm1(SB)
+ MOVL $183, CX
+ JMP callbackasm1(SB)
+ MOVL $184, CX
+ JMP callbackasm1(SB)
+ MOVL $185, CX
+ JMP callbackasm1(SB)
+ MOVL $186, CX
+ JMP callbackasm1(SB)
+ MOVL $187, CX
+ JMP callbackasm1(SB)
+ MOVL $188, CX
+ JMP callbackasm1(SB)
+ MOVL $189, CX
+ JMP callbackasm1(SB)
+ MOVL $190, CX
+ JMP callbackasm1(SB)
+ MOVL $191, CX
+ JMP callbackasm1(SB)
+ MOVL $192, CX
+ JMP callbackasm1(SB)
+ MOVL $193, CX
+ JMP callbackasm1(SB)
+ MOVL $194, CX
+ JMP callbackasm1(SB)
+ MOVL $195, CX
+ JMP callbackasm1(SB)
+ MOVL $196, CX
+ JMP callbackasm1(SB)
+ MOVL $197, CX
+ JMP callbackasm1(SB)
+ MOVL $198, CX
+ JMP callbackasm1(SB)
+ MOVL $199, CX
+ JMP callbackasm1(SB)
+ MOVL $200, CX
+ JMP callbackasm1(SB)
+ MOVL $201, CX
+ JMP callbackasm1(SB)
+ MOVL $202, CX
+ JMP callbackasm1(SB)
+ MOVL $203, CX
+ JMP callbackasm1(SB)
+ MOVL $204, CX
+ JMP callbackasm1(SB)
+ MOVL $205, CX
+ JMP callbackasm1(SB)
+ MOVL $206, CX
+ JMP callbackasm1(SB)
+ MOVL $207, CX
+ JMP callbackasm1(SB)
+ MOVL $208, CX
+ JMP callbackasm1(SB)
+ MOVL $209, CX
+ JMP callbackasm1(SB)
+ MOVL $210, CX
+ JMP callbackasm1(SB)
+ MOVL $211, CX
+ JMP callbackasm1(SB)
+ MOVL $212, CX
+ JMP callbackasm1(SB)
+ MOVL $213, CX
+ JMP callbackasm1(SB)
+ MOVL $214, CX
+ JMP callbackasm1(SB)
+ MOVL $215, CX
+ JMP callbackasm1(SB)
+ MOVL $216, CX
+ JMP callbackasm1(SB)
+ MOVL $217, CX
+ JMP callbackasm1(SB)
+ MOVL $218, CX
+ JMP callbackasm1(SB)
+ MOVL $219, CX
+ JMP callbackasm1(SB)
+ MOVL $220, CX
+ JMP callbackasm1(SB)
+ MOVL $221, CX
+ JMP callbackasm1(SB)
+ MOVL $222, CX
+ JMP callbackasm1(SB)
+ MOVL $223, CX
+ JMP callbackasm1(SB)
+ MOVL $224, CX
+ JMP callbackasm1(SB)
+ MOVL $225, CX
+ JMP callbackasm1(SB)
+ MOVL $226, CX
+ JMP callbackasm1(SB)
+ MOVL $227, CX
+ JMP callbackasm1(SB)
+ MOVL $228, CX
+ JMP callbackasm1(SB)
+ MOVL $229, CX
+ JMP callbackasm1(SB)
+ MOVL $230, CX
+ JMP callbackasm1(SB)
+ MOVL $231, CX
+ JMP callbackasm1(SB)
+ MOVL $232, CX
+ JMP callbackasm1(SB)
+ MOVL $233, CX
+ JMP callbackasm1(SB)
+ MOVL $234, CX
+ JMP callbackasm1(SB)
+ MOVL $235, CX
+ JMP callbackasm1(SB)
+ MOVL $236, CX
+ JMP callbackasm1(SB)
+ MOVL $237, CX
+ JMP callbackasm1(SB)
+ MOVL $238, CX
+ JMP callbackasm1(SB)
+ MOVL $239, CX
+ JMP callbackasm1(SB)
+ MOVL $240, CX
+ JMP callbackasm1(SB)
+ MOVL $241, CX
+ JMP callbackasm1(SB)
+ MOVL $242, CX
+ JMP callbackasm1(SB)
+ MOVL $243, CX
+ JMP callbackasm1(SB)
+ MOVL $244, CX
+ JMP callbackasm1(SB)
+ MOVL $245, CX
+ JMP callbackasm1(SB)
+ MOVL $246, CX
+ JMP callbackasm1(SB)
+ MOVL $247, CX
+ JMP callbackasm1(SB)
+ MOVL $248, CX
+ JMP callbackasm1(SB)
+ MOVL $249, CX
+ JMP callbackasm1(SB)
+ MOVL $250, CX
+ JMP callbackasm1(SB)
+ MOVL $251, CX
+ JMP callbackasm1(SB)
+ MOVL $252, CX
+ JMP callbackasm1(SB)
+ MOVL $253, CX
+ JMP callbackasm1(SB)
+ MOVL $254, CX
+ JMP callbackasm1(SB)
+ MOVL $255, CX
+ JMP callbackasm1(SB)
+ MOVL $256, CX
+ JMP callbackasm1(SB)
+ MOVL $257, CX
+ JMP callbackasm1(SB)
+ MOVL $258, CX
+ JMP callbackasm1(SB)
+ MOVL $259, CX
+ JMP callbackasm1(SB)
+ MOVL $260, CX
+ JMP callbackasm1(SB)
+ MOVL $261, CX
+ JMP callbackasm1(SB)
+ MOVL $262, CX
+ JMP callbackasm1(SB)
+ MOVL $263, CX
+ JMP callbackasm1(SB)
+ MOVL $264, CX
+ JMP callbackasm1(SB)
+ MOVL $265, CX
+ JMP callbackasm1(SB)
+ MOVL $266, CX
+ JMP callbackasm1(SB)
+ MOVL $267, CX
+ JMP callbackasm1(SB)
+ MOVL $268, CX
+ JMP callbackasm1(SB)
+ MOVL $269, CX
+ JMP callbackasm1(SB)
+ MOVL $270, CX
+ JMP callbackasm1(SB)
+ MOVL $271, CX
+ JMP callbackasm1(SB)
+ MOVL $272, CX
+ JMP callbackasm1(SB)
+ MOVL $273, CX
+ JMP callbackasm1(SB)
+ MOVL $274, CX
+ JMP callbackasm1(SB)
+ MOVL $275, CX
+ JMP callbackasm1(SB)
+ MOVL $276, CX
+ JMP callbackasm1(SB)
+ MOVL $277, CX
+ JMP callbackasm1(SB)
+ MOVL $278, CX
+ JMP callbackasm1(SB)
+ MOVL $279, CX
+ JMP callbackasm1(SB)
+ MOVL $280, CX
+ JMP callbackasm1(SB)
+ MOVL $281, CX
+ JMP callbackasm1(SB)
+ MOVL $282, CX
+ JMP callbackasm1(SB)
+ MOVL $283, CX
+ JMP callbackasm1(SB)
+ MOVL $284, CX
+ JMP callbackasm1(SB)
+ MOVL $285, CX
+ JMP callbackasm1(SB)
+ MOVL $286, CX
+ JMP callbackasm1(SB)
+ MOVL $287, CX
+ JMP callbackasm1(SB)
+ MOVL $288, CX
+ JMP callbackasm1(SB)
+ MOVL $289, CX
+ JMP callbackasm1(SB)
+ MOVL $290, CX
+ JMP callbackasm1(SB)
+ MOVL $291, CX
+ JMP callbackasm1(SB)
+ MOVL $292, CX
+ JMP callbackasm1(SB)
+ MOVL $293, CX
+ JMP callbackasm1(SB)
+ MOVL $294, CX
+ JMP callbackasm1(SB)
+ MOVL $295, CX
+ JMP callbackasm1(SB)
+ MOVL $296, CX
+ JMP callbackasm1(SB)
+ MOVL $297, CX
+ JMP callbackasm1(SB)
+ MOVL $298, CX
+ JMP callbackasm1(SB)
+ MOVL $299, CX
+ JMP callbackasm1(SB)
+ MOVL $300, CX
+ JMP callbackasm1(SB)
+ MOVL $301, CX
+ JMP callbackasm1(SB)
+ MOVL $302, CX
+ JMP callbackasm1(SB)
+ MOVL $303, CX
+ JMP callbackasm1(SB)
+ MOVL $304, CX
+ JMP callbackasm1(SB)
+ MOVL $305, CX
+ JMP callbackasm1(SB)
+ MOVL $306, CX
+ JMP callbackasm1(SB)
+ MOVL $307, CX
+ JMP callbackasm1(SB)
+ MOVL $308, CX
+ JMP callbackasm1(SB)
+ MOVL $309, CX
+ JMP callbackasm1(SB)
+ MOVL $310, CX
+ JMP callbackasm1(SB)
+ MOVL $311, CX
+ JMP callbackasm1(SB)
+ MOVL $312, CX
+ JMP callbackasm1(SB)
+ MOVL $313, CX
+ JMP callbackasm1(SB)
+ MOVL $314, CX
+ JMP callbackasm1(SB)
+ MOVL $315, CX
+ JMP callbackasm1(SB)
+ MOVL $316, CX
+ JMP callbackasm1(SB)
+ MOVL $317, CX
+ JMP callbackasm1(SB)
+ MOVL $318, CX
+ JMP callbackasm1(SB)
+ MOVL $319, CX
+ JMP callbackasm1(SB)
+ MOVL $320, CX
+ JMP callbackasm1(SB)
+ MOVL $321, CX
+ JMP callbackasm1(SB)
+ MOVL $322, CX
+ JMP callbackasm1(SB)
+ MOVL $323, CX
+ JMP callbackasm1(SB)
+ MOVL $324, CX
+ JMP callbackasm1(SB)
+ MOVL $325, CX
+ JMP callbackasm1(SB)
+ MOVL $326, CX
+ JMP callbackasm1(SB)
+ MOVL $327, CX
+ JMP callbackasm1(SB)
+ MOVL $328, CX
+ JMP callbackasm1(SB)
+ MOVL $329, CX
+ JMP callbackasm1(SB)
+ MOVL $330, CX
+ JMP callbackasm1(SB)
+ MOVL $331, CX
+ JMP callbackasm1(SB)
+ MOVL $332, CX
+ JMP callbackasm1(SB)
+ MOVL $333, CX
+ JMP callbackasm1(SB)
+ MOVL $334, CX
+ JMP callbackasm1(SB)
+ MOVL $335, CX
+ JMP callbackasm1(SB)
+ MOVL $336, CX
+ JMP callbackasm1(SB)
+ MOVL $337, CX
+ JMP callbackasm1(SB)
+ MOVL $338, CX
+ JMP callbackasm1(SB)
+ MOVL $339, CX
+ JMP callbackasm1(SB)
+ MOVL $340, CX
+ JMP callbackasm1(SB)
+ MOVL $341, CX
+ JMP callbackasm1(SB)
+ MOVL $342, CX
+ JMP callbackasm1(SB)
+ MOVL $343, CX
+ JMP callbackasm1(SB)
+ MOVL $344, CX
+ JMP callbackasm1(SB)
+ MOVL $345, CX
+ JMP callbackasm1(SB)
+ MOVL $346, CX
+ JMP callbackasm1(SB)
+ MOVL $347, CX
+ JMP callbackasm1(SB)
+ MOVL $348, CX
+ JMP callbackasm1(SB)
+ MOVL $349, CX
+ JMP callbackasm1(SB)
+ MOVL $350, CX
+ JMP callbackasm1(SB)
+ MOVL $351, CX
+ JMP callbackasm1(SB)
+ MOVL $352, CX
+ JMP callbackasm1(SB)
+ MOVL $353, CX
+ JMP callbackasm1(SB)
+ MOVL $354, CX
+ JMP callbackasm1(SB)
+ MOVL $355, CX
+ JMP callbackasm1(SB)
+ MOVL $356, CX
+ JMP callbackasm1(SB)
+ MOVL $357, CX
+ JMP callbackasm1(SB)
+ MOVL $358, CX
+ JMP callbackasm1(SB)
+ MOVL $359, CX
+ JMP callbackasm1(SB)
+ MOVL $360, CX
+ JMP callbackasm1(SB)
+ MOVL $361, CX
+ JMP callbackasm1(SB)
+ MOVL $362, CX
+ JMP callbackasm1(SB)
+ MOVL $363, CX
+ JMP callbackasm1(SB)
+ MOVL $364, CX
+ JMP callbackasm1(SB)
+ MOVL $365, CX
+ JMP callbackasm1(SB)
+ MOVL $366, CX
+ JMP callbackasm1(SB)
+ MOVL $367, CX
+ JMP callbackasm1(SB)
+ MOVL $368, CX
+ JMP callbackasm1(SB)
+ MOVL $369, CX
+ JMP callbackasm1(SB)
+ MOVL $370, CX
+ JMP callbackasm1(SB)
+ MOVL $371, CX
+ JMP callbackasm1(SB)
+ MOVL $372, CX
+ JMP callbackasm1(SB)
+ MOVL $373, CX
+ JMP callbackasm1(SB)
+ MOVL $374, CX
+ JMP callbackasm1(SB)
+ MOVL $375, CX
+ JMP callbackasm1(SB)
+ MOVL $376, CX
+ JMP callbackasm1(SB)
+ MOVL $377, CX
+ JMP callbackasm1(SB)
+ MOVL $378, CX
+ JMP callbackasm1(SB)
+ MOVL $379, CX
+ JMP callbackasm1(SB)
+ MOVL $380, CX
+ JMP callbackasm1(SB)
+ MOVL $381, CX
+ JMP callbackasm1(SB)
+ MOVL $382, CX
+ JMP callbackasm1(SB)
+ MOVL $383, CX
+ JMP callbackasm1(SB)
+ MOVL $384, CX
+ JMP callbackasm1(SB)
+ MOVL $385, CX
+ JMP callbackasm1(SB)
+ MOVL $386, CX
+ JMP callbackasm1(SB)
+ MOVL $387, CX
+ JMP callbackasm1(SB)
+ MOVL $388, CX
+ JMP callbackasm1(SB)
+ MOVL $389, CX
+ JMP callbackasm1(SB)
+ MOVL $390, CX
+ JMP callbackasm1(SB)
+ MOVL $391, CX
+ JMP callbackasm1(SB)
+ MOVL $392, CX
+ JMP callbackasm1(SB)
+ MOVL $393, CX
+ JMP callbackasm1(SB)
+ MOVL $394, CX
+ JMP callbackasm1(SB)
+ MOVL $395, CX
+ JMP callbackasm1(SB)
+ MOVL $396, CX
+ JMP callbackasm1(SB)
+ MOVL $397, CX
+ JMP callbackasm1(SB)
+ MOVL $398, CX
+ JMP callbackasm1(SB)
+ MOVL $399, CX
+ JMP callbackasm1(SB)
+ MOVL $400, CX
+ JMP callbackasm1(SB)
+ MOVL $401, CX
+ JMP callbackasm1(SB)
+ MOVL $402, CX
+ JMP callbackasm1(SB)
+ MOVL $403, CX
+ JMP callbackasm1(SB)
+ MOVL $404, CX
+ JMP callbackasm1(SB)
+ MOVL $405, CX
+ JMP callbackasm1(SB)
+ MOVL $406, CX
+ JMP callbackasm1(SB)
+ MOVL $407, CX
+ JMP callbackasm1(SB)
+ MOVL $408, CX
+ JMP callbackasm1(SB)
+ MOVL $409, CX
+ JMP callbackasm1(SB)
+ MOVL $410, CX
+ JMP callbackasm1(SB)
+ MOVL $411, CX
+ JMP callbackasm1(SB)
+ MOVL $412, CX
+ JMP callbackasm1(SB)
+ MOVL $413, CX
+ JMP callbackasm1(SB)
+ MOVL $414, CX
+ JMP callbackasm1(SB)
+ MOVL $415, CX
+ JMP callbackasm1(SB)
+ MOVL $416, CX
+ JMP callbackasm1(SB)
+ MOVL $417, CX
+ JMP callbackasm1(SB)
+ MOVL $418, CX
+ JMP callbackasm1(SB)
+ MOVL $419, CX
+ JMP callbackasm1(SB)
+ MOVL $420, CX
+ JMP callbackasm1(SB)
+ MOVL $421, CX
+ JMP callbackasm1(SB)
+ MOVL $422, CX
+ JMP callbackasm1(SB)
+ MOVL $423, CX
+ JMP callbackasm1(SB)
+ MOVL $424, CX
+ JMP callbackasm1(SB)
+ MOVL $425, CX
+ JMP callbackasm1(SB)
+ MOVL $426, CX
+ JMP callbackasm1(SB)
+ MOVL $427, CX
+ JMP callbackasm1(SB)
+ MOVL $428, CX
+ JMP callbackasm1(SB)
+ MOVL $429, CX
+ JMP callbackasm1(SB)
+ MOVL $430, CX
+ JMP callbackasm1(SB)
+ MOVL $431, CX
+ JMP callbackasm1(SB)
+ MOVL $432, CX
+ JMP callbackasm1(SB)
+ MOVL $433, CX
+ JMP callbackasm1(SB)
+ MOVL $434, CX
+ JMP callbackasm1(SB)
+ MOVL $435, CX
+ JMP callbackasm1(SB)
+ MOVL $436, CX
+ JMP callbackasm1(SB)
+ MOVL $437, CX
+ JMP callbackasm1(SB)
+ MOVL $438, CX
+ JMP callbackasm1(SB)
+ MOVL $439, CX
+ JMP callbackasm1(SB)
+ MOVL $440, CX
+ JMP callbackasm1(SB)
+ MOVL $441, CX
+ JMP callbackasm1(SB)
+ MOVL $442, CX
+ JMP callbackasm1(SB)
+ MOVL $443, CX
+ JMP callbackasm1(SB)
+ MOVL $444, CX
+ JMP callbackasm1(SB)
+ MOVL $445, CX
+ JMP callbackasm1(SB)
+ MOVL $446, CX
+ JMP callbackasm1(SB)
+ MOVL $447, CX
+ JMP callbackasm1(SB)
+ MOVL $448, CX
+ JMP callbackasm1(SB)
+ MOVL $449, CX
+ JMP callbackasm1(SB)
+ MOVL $450, CX
+ JMP callbackasm1(SB)
+ MOVL $451, CX
+ JMP callbackasm1(SB)
+ MOVL $452, CX
+ JMP callbackasm1(SB)
+ MOVL $453, CX
+ JMP callbackasm1(SB)
+ MOVL $454, CX
+ JMP callbackasm1(SB)
+ MOVL $455, CX
+ JMP callbackasm1(SB)
+ MOVL $456, CX
+ JMP callbackasm1(SB)
+ MOVL $457, CX
+ JMP callbackasm1(SB)
+ MOVL $458, CX
+ JMP callbackasm1(SB)
+ MOVL $459, CX
+ JMP callbackasm1(SB)
+ MOVL $460, CX
+ JMP callbackasm1(SB)
+ MOVL $461, CX
+ JMP callbackasm1(SB)
+ MOVL $462, CX
+ JMP callbackasm1(SB)
+ MOVL $463, CX
+ JMP callbackasm1(SB)
+ MOVL $464, CX
+ JMP callbackasm1(SB)
+ MOVL $465, CX
+ JMP callbackasm1(SB)
+ MOVL $466, CX
+ JMP callbackasm1(SB)
+ MOVL $467, CX
+ JMP callbackasm1(SB)
+ MOVL $468, CX
+ JMP callbackasm1(SB)
+ MOVL $469, CX
+ JMP callbackasm1(SB)
+ MOVL $470, CX
+ JMP callbackasm1(SB)
+ MOVL $471, CX
+ JMP callbackasm1(SB)
+ MOVL $472, CX
+ JMP callbackasm1(SB)
+ MOVL $473, CX
+ JMP callbackasm1(SB)
+ MOVL $474, CX
+ JMP callbackasm1(SB)
+ MOVL $475, CX
+ JMP callbackasm1(SB)
+ MOVL $476, CX
+ JMP callbackasm1(SB)
+ MOVL $477, CX
+ JMP callbackasm1(SB)
+ MOVL $478, CX
+ JMP callbackasm1(SB)
+ MOVL $479, CX
+ JMP callbackasm1(SB)
+ MOVL $480, CX
+ JMP callbackasm1(SB)
+ MOVL $481, CX
+ JMP callbackasm1(SB)
+ MOVL $482, CX
+ JMP callbackasm1(SB)
+ MOVL $483, CX
+ JMP callbackasm1(SB)
+ MOVL $484, CX
+ JMP callbackasm1(SB)
+ MOVL $485, CX
+ JMP callbackasm1(SB)
+ MOVL $486, CX
+ JMP callbackasm1(SB)
+ MOVL $487, CX
+ JMP callbackasm1(SB)
+ MOVL $488, CX
+ JMP callbackasm1(SB)
+ MOVL $489, CX
+ JMP callbackasm1(SB)
+ MOVL $490, CX
+ JMP callbackasm1(SB)
+ MOVL $491, CX
+ JMP callbackasm1(SB)
+ MOVL $492, CX
+ JMP callbackasm1(SB)
+ MOVL $493, CX
+ JMP callbackasm1(SB)
+ MOVL $494, CX
+ JMP callbackasm1(SB)
+ MOVL $495, CX
+ JMP callbackasm1(SB)
+ MOVL $496, CX
+ JMP callbackasm1(SB)
+ MOVL $497, CX
+ JMP callbackasm1(SB)
+ MOVL $498, CX
+ JMP callbackasm1(SB)
+ MOVL $499, CX
+ JMP callbackasm1(SB)
+ MOVL $500, CX
+ JMP callbackasm1(SB)
+ MOVL $501, CX
+ JMP callbackasm1(SB)
+ MOVL $502, CX
+ JMP callbackasm1(SB)
+ MOVL $503, CX
+ JMP callbackasm1(SB)
+ MOVL $504, CX
+ JMP callbackasm1(SB)
+ MOVL $505, CX
+ JMP callbackasm1(SB)
+ MOVL $506, CX
+ JMP callbackasm1(SB)
+ MOVL $507, CX
+ JMP callbackasm1(SB)
+ MOVL $508, CX
+ JMP callbackasm1(SB)
+ MOVL $509, CX
+ JMP callbackasm1(SB)
+ MOVL $510, CX
+ JMP callbackasm1(SB)
+ MOVL $511, CX
+ JMP callbackasm1(SB)
+ MOVL $512, CX
+ JMP callbackasm1(SB)
+ MOVL $513, CX
+ JMP callbackasm1(SB)
+ MOVL $514, CX
+ JMP callbackasm1(SB)
+ MOVL $515, CX
+ JMP callbackasm1(SB)
+ MOVL $516, CX
+ JMP callbackasm1(SB)
+ MOVL $517, CX
+ JMP callbackasm1(SB)
+ MOVL $518, CX
+ JMP callbackasm1(SB)
+ MOVL $519, CX
+ JMP callbackasm1(SB)
+ MOVL $520, CX
+ JMP callbackasm1(SB)
+ MOVL $521, CX
+ JMP callbackasm1(SB)
+ MOVL $522, CX
+ JMP callbackasm1(SB)
+ MOVL $523, CX
+ JMP callbackasm1(SB)
+ MOVL $524, CX
+ JMP callbackasm1(SB)
+ MOVL $525, CX
+ JMP callbackasm1(SB)
+ MOVL $526, CX
+ JMP callbackasm1(SB)
+ MOVL $527, CX
+ JMP callbackasm1(SB)
+ MOVL $528, CX
+ JMP callbackasm1(SB)
+ MOVL $529, CX
+ JMP callbackasm1(SB)
+ MOVL $530, CX
+ JMP callbackasm1(SB)
+ MOVL $531, CX
+ JMP callbackasm1(SB)
+ MOVL $532, CX
+ JMP callbackasm1(SB)
+ MOVL $533, CX
+ JMP callbackasm1(SB)
+ MOVL $534, CX
+ JMP callbackasm1(SB)
+ MOVL $535, CX
+ JMP callbackasm1(SB)
+ MOVL $536, CX
+ JMP callbackasm1(SB)
+ MOVL $537, CX
+ JMP callbackasm1(SB)
+ MOVL $538, CX
+ JMP callbackasm1(SB)
+ MOVL $539, CX
+ JMP callbackasm1(SB)
+ MOVL $540, CX
+ JMP callbackasm1(SB)
+ MOVL $541, CX
+ JMP callbackasm1(SB)
+ MOVL $542, CX
+ JMP callbackasm1(SB)
+ MOVL $543, CX
+ JMP callbackasm1(SB)
+ MOVL $544, CX
+ JMP callbackasm1(SB)
+ MOVL $545, CX
+ JMP callbackasm1(SB)
+ MOVL $546, CX
+ JMP callbackasm1(SB)
+ MOVL $547, CX
+ JMP callbackasm1(SB)
+ MOVL $548, CX
+ JMP callbackasm1(SB)
+ MOVL $549, CX
+ JMP callbackasm1(SB)
+ MOVL $550, CX
+ JMP callbackasm1(SB)
+ MOVL $551, CX
+ JMP callbackasm1(SB)
+ MOVL $552, CX
+ JMP callbackasm1(SB)
+ MOVL $553, CX
+ JMP callbackasm1(SB)
+ MOVL $554, CX
+ JMP callbackasm1(SB)
+ MOVL $555, CX
+ JMP callbackasm1(SB)
+ MOVL $556, CX
+ JMP callbackasm1(SB)
+ MOVL $557, CX
+ JMP callbackasm1(SB)
+ MOVL $558, CX
+ JMP callbackasm1(SB)
+ MOVL $559, CX
+ JMP callbackasm1(SB)
+ MOVL $560, CX
+ JMP callbackasm1(SB)
+ MOVL $561, CX
+ JMP callbackasm1(SB)
+ MOVL $562, CX
+ JMP callbackasm1(SB)
+ MOVL $563, CX
+ JMP callbackasm1(SB)
+ MOVL $564, CX
+ JMP callbackasm1(SB)
+ MOVL $565, CX
+ JMP callbackasm1(SB)
+ MOVL $566, CX
+ JMP callbackasm1(SB)
+ MOVL $567, CX
+ JMP callbackasm1(SB)
+ MOVL $568, CX
+ JMP callbackasm1(SB)
+ MOVL $569, CX
+ JMP callbackasm1(SB)
+ MOVL $570, CX
+ JMP callbackasm1(SB)
+ MOVL $571, CX
+ JMP callbackasm1(SB)
+ MOVL $572, CX
+ JMP callbackasm1(SB)
+ MOVL $573, CX
+ JMP callbackasm1(SB)
+ MOVL $574, CX
+ JMP callbackasm1(SB)
+ MOVL $575, CX
+ JMP callbackasm1(SB)
+ MOVL $576, CX
+ JMP callbackasm1(SB)
+ MOVL $577, CX
+ JMP callbackasm1(SB)
+ MOVL $578, CX
+ JMP callbackasm1(SB)
+ MOVL $579, CX
+ JMP callbackasm1(SB)
+ MOVL $580, CX
+ JMP callbackasm1(SB)
+ MOVL $581, CX
+ JMP callbackasm1(SB)
+ MOVL $582, CX
+ JMP callbackasm1(SB)
+ MOVL $583, CX
+ JMP callbackasm1(SB)
+ MOVL $584, CX
+ JMP callbackasm1(SB)
+ MOVL $585, CX
+ JMP callbackasm1(SB)
+ MOVL $586, CX
+ JMP callbackasm1(SB)
+ MOVL $587, CX
+ JMP callbackasm1(SB)
+ MOVL $588, CX
+ JMP callbackasm1(SB)
+ MOVL $589, CX
+ JMP callbackasm1(SB)
+ MOVL $590, CX
+ JMP callbackasm1(SB)
+ MOVL $591, CX
+ JMP callbackasm1(SB)
+ MOVL $592, CX
+ JMP callbackasm1(SB)
+ MOVL $593, CX
+ JMP callbackasm1(SB)
+ MOVL $594, CX
+ JMP callbackasm1(SB)
+ MOVL $595, CX
+ JMP callbackasm1(SB)
+ MOVL $596, CX
+ JMP callbackasm1(SB)
+ MOVL $597, CX
+ JMP callbackasm1(SB)
+ MOVL $598, CX
+ JMP callbackasm1(SB)
+ MOVL $599, CX
+ JMP callbackasm1(SB)
+ MOVL $600, CX
+ JMP callbackasm1(SB)
+ MOVL $601, CX
+ JMP callbackasm1(SB)
+ MOVL $602, CX
+ JMP callbackasm1(SB)
+ MOVL $603, CX
+ JMP callbackasm1(SB)
+ MOVL $604, CX
+ JMP callbackasm1(SB)
+ MOVL $605, CX
+ JMP callbackasm1(SB)
+ MOVL $606, CX
+ JMP callbackasm1(SB)
+ MOVL $607, CX
+ JMP callbackasm1(SB)
+ MOVL $608, CX
+ JMP callbackasm1(SB)
+ MOVL $609, CX
+ JMP callbackasm1(SB)
+ MOVL $610, CX
+ JMP callbackasm1(SB)
+ MOVL $611, CX
+ JMP callbackasm1(SB)
+ MOVL $612, CX
+ JMP callbackasm1(SB)
+ MOVL $613, CX
+ JMP callbackasm1(SB)
+ MOVL $614, CX
+ JMP callbackasm1(SB)
+ MOVL $615, CX
+ JMP callbackasm1(SB)
+ MOVL $616, CX
+ JMP callbackasm1(SB)
+ MOVL $617, CX
+ JMP callbackasm1(SB)
+ MOVL $618, CX
+ JMP callbackasm1(SB)
+ MOVL $619, CX
+ JMP callbackasm1(SB)
+ MOVL $620, CX
+ JMP callbackasm1(SB)
+ MOVL $621, CX
+ JMP callbackasm1(SB)
+ MOVL $622, CX
+ JMP callbackasm1(SB)
+ MOVL $623, CX
+ JMP callbackasm1(SB)
+ MOVL $624, CX
+ JMP callbackasm1(SB)
+ MOVL $625, CX
+ JMP callbackasm1(SB)
+ MOVL $626, CX
+ JMP callbackasm1(SB)
+ MOVL $627, CX
+ JMP callbackasm1(SB)
+ MOVL $628, CX
+ JMP callbackasm1(SB)
+ MOVL $629, CX
+ JMP callbackasm1(SB)
+ MOVL $630, CX
+ JMP callbackasm1(SB)
+ MOVL $631, CX
+ JMP callbackasm1(SB)
+ MOVL $632, CX
+ JMP callbackasm1(SB)
+ MOVL $633, CX
+ JMP callbackasm1(SB)
+ MOVL $634, CX
+ JMP callbackasm1(SB)
+ MOVL $635, CX
+ JMP callbackasm1(SB)
+ MOVL $636, CX
+ JMP callbackasm1(SB)
+ MOVL $637, CX
+ JMP callbackasm1(SB)
+ MOVL $638, CX
+ JMP callbackasm1(SB)
+ MOVL $639, CX
+ JMP callbackasm1(SB)
+ MOVL $640, CX
+ JMP callbackasm1(SB)
+ MOVL $641, CX
+ JMP callbackasm1(SB)
+ MOVL $642, CX
+ JMP callbackasm1(SB)
+ MOVL $643, CX
+ JMP callbackasm1(SB)
+ MOVL $644, CX
+ JMP callbackasm1(SB)
+ MOVL $645, CX
+ JMP callbackasm1(SB)
+ MOVL $646, CX
+ JMP callbackasm1(SB)
+ MOVL $647, CX
+ JMP callbackasm1(SB)
+ MOVL $648, CX
+ JMP callbackasm1(SB)
+ MOVL $649, CX
+ JMP callbackasm1(SB)
+ MOVL $650, CX
+ JMP callbackasm1(SB)
+ MOVL $651, CX
+ JMP callbackasm1(SB)
+ MOVL $652, CX
+ JMP callbackasm1(SB)
+ MOVL $653, CX
+ JMP callbackasm1(SB)
+ MOVL $654, CX
+ JMP callbackasm1(SB)
+ MOVL $655, CX
+ JMP callbackasm1(SB)
+ MOVL $656, CX
+ JMP callbackasm1(SB)
+ MOVL $657, CX
+ JMP callbackasm1(SB)
+ MOVL $658, CX
+ JMP callbackasm1(SB)
+ MOVL $659, CX
+ JMP callbackasm1(SB)
+ MOVL $660, CX
+ JMP callbackasm1(SB)
+ MOVL $661, CX
+ JMP callbackasm1(SB)
+ MOVL $662, CX
+ JMP callbackasm1(SB)
+ MOVL $663, CX
+ JMP callbackasm1(SB)
+ MOVL $664, CX
+ JMP callbackasm1(SB)
+ MOVL $665, CX
+ JMP callbackasm1(SB)
+ MOVL $666, CX
+ JMP callbackasm1(SB)
+ MOVL $667, CX
+ JMP callbackasm1(SB)
+ MOVL $668, CX
+ JMP callbackasm1(SB)
+ MOVL $669, CX
+ JMP callbackasm1(SB)
+ MOVL $670, CX
+ JMP callbackasm1(SB)
+ MOVL $671, CX
+ JMP callbackasm1(SB)
+ MOVL $672, CX
+ JMP callbackasm1(SB)
+ MOVL $673, CX
+ JMP callbackasm1(SB)
+ MOVL $674, CX
+ JMP callbackasm1(SB)
+ MOVL $675, CX
+ JMP callbackasm1(SB)
+ MOVL $676, CX
+ JMP callbackasm1(SB)
+ MOVL $677, CX
+ JMP callbackasm1(SB)
+ MOVL $678, CX
+ JMP callbackasm1(SB)
+ MOVL $679, CX
+ JMP callbackasm1(SB)
+ MOVL $680, CX
+ JMP callbackasm1(SB)
+ MOVL $681, CX
+ JMP callbackasm1(SB)
+ MOVL $682, CX
+ JMP callbackasm1(SB)
+ MOVL $683, CX
+ JMP callbackasm1(SB)
+ MOVL $684, CX
+ JMP callbackasm1(SB)
+ MOVL $685, CX
+ JMP callbackasm1(SB)
+ MOVL $686, CX
+ JMP callbackasm1(SB)
+ MOVL $687, CX
+ JMP callbackasm1(SB)
+ MOVL $688, CX
+ JMP callbackasm1(SB)
+ MOVL $689, CX
+ JMP callbackasm1(SB)
+ MOVL $690, CX
+ JMP callbackasm1(SB)
+ MOVL $691, CX
+ JMP callbackasm1(SB)
+ MOVL $692, CX
+ JMP callbackasm1(SB)
+ MOVL $693, CX
+ JMP callbackasm1(SB)
+ MOVL $694, CX
+ JMP callbackasm1(SB)
+ MOVL $695, CX
+ JMP callbackasm1(SB)
+ MOVL $696, CX
+ JMP callbackasm1(SB)
+ MOVL $697, CX
+ JMP callbackasm1(SB)
+ MOVL $698, CX
+ JMP callbackasm1(SB)
+ MOVL $699, CX
+ JMP callbackasm1(SB)
+ MOVL $700, CX
+ JMP callbackasm1(SB)
+ MOVL $701, CX
+ JMP callbackasm1(SB)
+ MOVL $702, CX
+ JMP callbackasm1(SB)
+ MOVL $703, CX
+ JMP callbackasm1(SB)
+ MOVL $704, CX
+ JMP callbackasm1(SB)
+ MOVL $705, CX
+ JMP callbackasm1(SB)
+ MOVL $706, CX
+ JMP callbackasm1(SB)
+ MOVL $707, CX
+ JMP callbackasm1(SB)
+ MOVL $708, CX
+ JMP callbackasm1(SB)
+ MOVL $709, CX
+ JMP callbackasm1(SB)
+ MOVL $710, CX
+ JMP callbackasm1(SB)
+ MOVL $711, CX
+ JMP callbackasm1(SB)
+ MOVL $712, CX
+ JMP callbackasm1(SB)
+ MOVL $713, CX
+ JMP callbackasm1(SB)
+ MOVL $714, CX
+ JMP callbackasm1(SB)
+ MOVL $715, CX
+ JMP callbackasm1(SB)
+ MOVL $716, CX
+ JMP callbackasm1(SB)
+ MOVL $717, CX
+ JMP callbackasm1(SB)
+ MOVL $718, CX
+ JMP callbackasm1(SB)
+ MOVL $719, CX
+ JMP callbackasm1(SB)
+ MOVL $720, CX
+ JMP callbackasm1(SB)
+ MOVL $721, CX
+ JMP callbackasm1(SB)
+ MOVL $722, CX
+ JMP callbackasm1(SB)
+ MOVL $723, CX
+ JMP callbackasm1(SB)
+ MOVL $724, CX
+ JMP callbackasm1(SB)
+ MOVL $725, CX
+ JMP callbackasm1(SB)
+ MOVL $726, CX
+ JMP callbackasm1(SB)
+ MOVL $727, CX
+ JMP callbackasm1(SB)
+ MOVL $728, CX
+ JMP callbackasm1(SB)
+ MOVL $729, CX
+ JMP callbackasm1(SB)
+ MOVL $730, CX
+ JMP callbackasm1(SB)
+ MOVL $731, CX
+ JMP callbackasm1(SB)
+ MOVL $732, CX
+ JMP callbackasm1(SB)
+ MOVL $733, CX
+ JMP callbackasm1(SB)
+ MOVL $734, CX
+ JMP callbackasm1(SB)
+ MOVL $735, CX
+ JMP callbackasm1(SB)
+ MOVL $736, CX
+ JMP callbackasm1(SB)
+ MOVL $737, CX
+ JMP callbackasm1(SB)
+ MOVL $738, CX
+ JMP callbackasm1(SB)
+ MOVL $739, CX
+ JMP callbackasm1(SB)
+ MOVL $740, CX
+ JMP callbackasm1(SB)
+ MOVL $741, CX
+ JMP callbackasm1(SB)
+ MOVL $742, CX
+ JMP callbackasm1(SB)
+ MOVL $743, CX
+ JMP callbackasm1(SB)
+ MOVL $744, CX
+ JMP callbackasm1(SB)
+ MOVL $745, CX
+ JMP callbackasm1(SB)
+ MOVL $746, CX
+ JMP callbackasm1(SB)
+ MOVL $747, CX
+ JMP callbackasm1(SB)
+ MOVL $748, CX
+ JMP callbackasm1(SB)
+ MOVL $749, CX
+ JMP callbackasm1(SB)
+ MOVL $750, CX
+ JMP callbackasm1(SB)
+ MOVL $751, CX
+ JMP callbackasm1(SB)
+ MOVL $752, CX
+ JMP callbackasm1(SB)
+ MOVL $753, CX
+ JMP callbackasm1(SB)
+ MOVL $754, CX
+ JMP callbackasm1(SB)
+ MOVL $755, CX
+ JMP callbackasm1(SB)
+ MOVL $756, CX
+ JMP callbackasm1(SB)
+ MOVL $757, CX
+ JMP callbackasm1(SB)
+ MOVL $758, CX
+ JMP callbackasm1(SB)
+ MOVL $759, CX
+ JMP callbackasm1(SB)
+ MOVL $760, CX
+ JMP callbackasm1(SB)
+ MOVL $761, CX
+ JMP callbackasm1(SB)
+ MOVL $762, CX
+ JMP callbackasm1(SB)
+ MOVL $763, CX
+ JMP callbackasm1(SB)
+ MOVL $764, CX
+ JMP callbackasm1(SB)
+ MOVL $765, CX
+ JMP callbackasm1(SB)
+ MOVL $766, CX
+ JMP callbackasm1(SB)
+ MOVL $767, CX
+ JMP callbackasm1(SB)
+ MOVL $768, CX
+ JMP callbackasm1(SB)
+ MOVL $769, CX
+ JMP callbackasm1(SB)
+ MOVL $770, CX
+ JMP callbackasm1(SB)
+ MOVL $771, CX
+ JMP callbackasm1(SB)
+ MOVL $772, CX
+ JMP callbackasm1(SB)
+ MOVL $773, CX
+ JMP callbackasm1(SB)
+ MOVL $774, CX
+ JMP callbackasm1(SB)
+ MOVL $775, CX
+ JMP callbackasm1(SB)
+ MOVL $776, CX
+ JMP callbackasm1(SB)
+ MOVL $777, CX
+ JMP callbackasm1(SB)
+ MOVL $778, CX
+ JMP callbackasm1(SB)
+ MOVL $779, CX
+ JMP callbackasm1(SB)
+ MOVL $780, CX
+ JMP callbackasm1(SB)
+ MOVL $781, CX
+ JMP callbackasm1(SB)
+ MOVL $782, CX
+ JMP callbackasm1(SB)
+ MOVL $783, CX
+ JMP callbackasm1(SB)
+ MOVL $784, CX
+ JMP callbackasm1(SB)
+ MOVL $785, CX
+ JMP callbackasm1(SB)
+ MOVL $786, CX
+ JMP callbackasm1(SB)
+ MOVL $787, CX
+ JMP callbackasm1(SB)
+ MOVL $788, CX
+ JMP callbackasm1(SB)
+ MOVL $789, CX
+ JMP callbackasm1(SB)
+ MOVL $790, CX
+ JMP callbackasm1(SB)
+ MOVL $791, CX
+ JMP callbackasm1(SB)
+ MOVL $792, CX
+ JMP callbackasm1(SB)
+ MOVL $793, CX
+ JMP callbackasm1(SB)
+ MOVL $794, CX
+ JMP callbackasm1(SB)
+ MOVL $795, CX
+ JMP callbackasm1(SB)
+ MOVL $796, CX
+ JMP callbackasm1(SB)
+ MOVL $797, CX
+ JMP callbackasm1(SB)
+ MOVL $798, CX
+ JMP callbackasm1(SB)
+ MOVL $799, CX
+ JMP callbackasm1(SB)
+ MOVL $800, CX
+ JMP callbackasm1(SB)
+ MOVL $801, CX
+ JMP callbackasm1(SB)
+ MOVL $802, CX
+ JMP callbackasm1(SB)
+ MOVL $803, CX
+ JMP callbackasm1(SB)
+ MOVL $804, CX
+ JMP callbackasm1(SB)
+ MOVL $805, CX
+ JMP callbackasm1(SB)
+ MOVL $806, CX
+ JMP callbackasm1(SB)
+ MOVL $807, CX
+ JMP callbackasm1(SB)
+ MOVL $808, CX
+ JMP callbackasm1(SB)
+ MOVL $809, CX
+ JMP callbackasm1(SB)
+ MOVL $810, CX
+ JMP callbackasm1(SB)
+ MOVL $811, CX
+ JMP callbackasm1(SB)
+ MOVL $812, CX
+ JMP callbackasm1(SB)
+ MOVL $813, CX
+ JMP callbackasm1(SB)
+ MOVL $814, CX
+ JMP callbackasm1(SB)
+ MOVL $815, CX
+ JMP callbackasm1(SB)
+ MOVL $816, CX
+ JMP callbackasm1(SB)
+ MOVL $817, CX
+ JMP callbackasm1(SB)
+ MOVL $818, CX
+ JMP callbackasm1(SB)
+ MOVL $819, CX
+ JMP callbackasm1(SB)
+ MOVL $820, CX
+ JMP callbackasm1(SB)
+ MOVL $821, CX
+ JMP callbackasm1(SB)
+ MOVL $822, CX
+ JMP callbackasm1(SB)
+ MOVL $823, CX
+ JMP callbackasm1(SB)
+ MOVL $824, CX
+ JMP callbackasm1(SB)
+ MOVL $825, CX
+ JMP callbackasm1(SB)
+ MOVL $826, CX
+ JMP callbackasm1(SB)
+ MOVL $827, CX
+ JMP callbackasm1(SB)
+ MOVL $828, CX
+ JMP callbackasm1(SB)
+ MOVL $829, CX
+ JMP callbackasm1(SB)
+ MOVL $830, CX
+ JMP callbackasm1(SB)
+ MOVL $831, CX
+ JMP callbackasm1(SB)
+ MOVL $832, CX
+ JMP callbackasm1(SB)
+ MOVL $833, CX
+ JMP callbackasm1(SB)
+ MOVL $834, CX
+ JMP callbackasm1(SB)
+ MOVL $835, CX
+ JMP callbackasm1(SB)
+ MOVL $836, CX
+ JMP callbackasm1(SB)
+ MOVL $837, CX
+ JMP callbackasm1(SB)
+ MOVL $838, CX
+ JMP callbackasm1(SB)
+ MOVL $839, CX
+ JMP callbackasm1(SB)
+ MOVL $840, CX
+ JMP callbackasm1(SB)
+ MOVL $841, CX
+ JMP callbackasm1(SB)
+ MOVL $842, CX
+ JMP callbackasm1(SB)
+ MOVL $843, CX
+ JMP callbackasm1(SB)
+ MOVL $844, CX
+ JMP callbackasm1(SB)
+ MOVL $845, CX
+ JMP callbackasm1(SB)
+ MOVL $846, CX
+ JMP callbackasm1(SB)
+ MOVL $847, CX
+ JMP callbackasm1(SB)
+ MOVL $848, CX
+ JMP callbackasm1(SB)
+ MOVL $849, CX
+ JMP callbackasm1(SB)
+ MOVL $850, CX
+ JMP callbackasm1(SB)
+ MOVL $851, CX
+ JMP callbackasm1(SB)
+ MOVL $852, CX
+ JMP callbackasm1(SB)
+ MOVL $853, CX
+ JMP callbackasm1(SB)
+ MOVL $854, CX
+ JMP callbackasm1(SB)
+ MOVL $855, CX
+ JMP callbackasm1(SB)
+ MOVL $856, CX
+ JMP callbackasm1(SB)
+ MOVL $857, CX
+ JMP callbackasm1(SB)
+ MOVL $858, CX
+ JMP callbackasm1(SB)
+ MOVL $859, CX
+ JMP callbackasm1(SB)
+ MOVL $860, CX
+ JMP callbackasm1(SB)
+ MOVL $861, CX
+ JMP callbackasm1(SB)
+ MOVL $862, CX
+ JMP callbackasm1(SB)
+ MOVL $863, CX
+ JMP callbackasm1(SB)
+ MOVL $864, CX
+ JMP callbackasm1(SB)
+ MOVL $865, CX
+ JMP callbackasm1(SB)
+ MOVL $866, CX
+ JMP callbackasm1(SB)
+ MOVL $867, CX
+ JMP callbackasm1(SB)
+ MOVL $868, CX
+ JMP callbackasm1(SB)
+ MOVL $869, CX
+ JMP callbackasm1(SB)
+ MOVL $870, CX
+ JMP callbackasm1(SB)
+ MOVL $871, CX
+ JMP callbackasm1(SB)
+ MOVL $872, CX
+ JMP callbackasm1(SB)
+ MOVL $873, CX
+ JMP callbackasm1(SB)
+ MOVL $874, CX
+ JMP callbackasm1(SB)
+ MOVL $875, CX
+ JMP callbackasm1(SB)
+ MOVL $876, CX
+ JMP callbackasm1(SB)
+ MOVL $877, CX
+ JMP callbackasm1(SB)
+ MOVL $878, CX
+ JMP callbackasm1(SB)
+ MOVL $879, CX
+ JMP callbackasm1(SB)
+ MOVL $880, CX
+ JMP callbackasm1(SB)
+ MOVL $881, CX
+ JMP callbackasm1(SB)
+ MOVL $882, CX
+ JMP callbackasm1(SB)
+ MOVL $883, CX
+ JMP callbackasm1(SB)
+ MOVL $884, CX
+ JMP callbackasm1(SB)
+ MOVL $885, CX
+ JMP callbackasm1(SB)
+ MOVL $886, CX
+ JMP callbackasm1(SB)
+ MOVL $887, CX
+ JMP callbackasm1(SB)
+ MOVL $888, CX
+ JMP callbackasm1(SB)
+ MOVL $889, CX
+ JMP callbackasm1(SB)
+ MOVL $890, CX
+ JMP callbackasm1(SB)
+ MOVL $891, CX
+ JMP callbackasm1(SB)
+ MOVL $892, CX
+ JMP callbackasm1(SB)
+ MOVL $893, CX
+ JMP callbackasm1(SB)
+ MOVL $894, CX
+ JMP callbackasm1(SB)
+ MOVL $895, CX
+ JMP callbackasm1(SB)
+ MOVL $896, CX
+ JMP callbackasm1(SB)
+ MOVL $897, CX
+ JMP callbackasm1(SB)
+ MOVL $898, CX
+ JMP callbackasm1(SB)
+ MOVL $899, CX
+ JMP callbackasm1(SB)
+ MOVL $900, CX
+ JMP callbackasm1(SB)
+ MOVL $901, CX
+ JMP callbackasm1(SB)
+ MOVL $902, CX
+ JMP callbackasm1(SB)
+ MOVL $903, CX
+ JMP callbackasm1(SB)
+ MOVL $904, CX
+ JMP callbackasm1(SB)
+ MOVL $905, CX
+ JMP callbackasm1(SB)
+ MOVL $906, CX
+ JMP callbackasm1(SB)
+ MOVL $907, CX
+ JMP callbackasm1(SB)
+ MOVL $908, CX
+ JMP callbackasm1(SB)
+ MOVL $909, CX
+ JMP callbackasm1(SB)
+ MOVL $910, CX
+ JMP callbackasm1(SB)
+ MOVL $911, CX
+ JMP callbackasm1(SB)
+ MOVL $912, CX
+ JMP callbackasm1(SB)
+ MOVL $913, CX
+ JMP callbackasm1(SB)
+ MOVL $914, CX
+ JMP callbackasm1(SB)
+ MOVL $915, CX
+ JMP callbackasm1(SB)
+ MOVL $916, CX
+ JMP callbackasm1(SB)
+ MOVL $917, CX
+ JMP callbackasm1(SB)
+ MOVL $918, CX
+ JMP callbackasm1(SB)
+ MOVL $919, CX
+ JMP callbackasm1(SB)
+ MOVL $920, CX
+ JMP callbackasm1(SB)
+ MOVL $921, CX
+ JMP callbackasm1(SB)
+ MOVL $922, CX
+ JMP callbackasm1(SB)
+ MOVL $923, CX
+ JMP callbackasm1(SB)
+ MOVL $924, CX
+ JMP callbackasm1(SB)
+ MOVL $925, CX
+ JMP callbackasm1(SB)
+ MOVL $926, CX
+ JMP callbackasm1(SB)
+ MOVL $927, CX
+ JMP callbackasm1(SB)
+ MOVL $928, CX
+ JMP callbackasm1(SB)
+ MOVL $929, CX
+ JMP callbackasm1(SB)
+ MOVL $930, CX
+ JMP callbackasm1(SB)
+ MOVL $931, CX
+ JMP callbackasm1(SB)
+ MOVL $932, CX
+ JMP callbackasm1(SB)
+ MOVL $933, CX
+ JMP callbackasm1(SB)
+ MOVL $934, CX
+ JMP callbackasm1(SB)
+ MOVL $935, CX
+ JMP callbackasm1(SB)
+ MOVL $936, CX
+ JMP callbackasm1(SB)
+ MOVL $937, CX
+ JMP callbackasm1(SB)
+ MOVL $938, CX
+ JMP callbackasm1(SB)
+ MOVL $939, CX
+ JMP callbackasm1(SB)
+ MOVL $940, CX
+ JMP callbackasm1(SB)
+ MOVL $941, CX
+ JMP callbackasm1(SB)
+ MOVL $942, CX
+ JMP callbackasm1(SB)
+ MOVL $943, CX
+ JMP callbackasm1(SB)
+ MOVL $944, CX
+ JMP callbackasm1(SB)
+ MOVL $945, CX
+ JMP callbackasm1(SB)
+ MOVL $946, CX
+ JMP callbackasm1(SB)
+ MOVL $947, CX
+ JMP callbackasm1(SB)
+ MOVL $948, CX
+ JMP callbackasm1(SB)
+ MOVL $949, CX
+ JMP callbackasm1(SB)
+ MOVL $950, CX
+ JMP callbackasm1(SB)
+ MOVL $951, CX
+ JMP callbackasm1(SB)
+ MOVL $952, CX
+ JMP callbackasm1(SB)
+ MOVL $953, CX
+ JMP callbackasm1(SB)
+ MOVL $954, CX
+ JMP callbackasm1(SB)
+ MOVL $955, CX
+ JMP callbackasm1(SB)
+ MOVL $956, CX
+ JMP callbackasm1(SB)
+ MOVL $957, CX
+ JMP callbackasm1(SB)
+ MOVL $958, CX
+ JMP callbackasm1(SB)
+ MOVL $959, CX
+ JMP callbackasm1(SB)
+ MOVL $960, CX
+ JMP callbackasm1(SB)
+ MOVL $961, CX
+ JMP callbackasm1(SB)
+ MOVL $962, CX
+ JMP callbackasm1(SB)
+ MOVL $963, CX
+ JMP callbackasm1(SB)
+ MOVL $964, CX
+ JMP callbackasm1(SB)
+ MOVL $965, CX
+ JMP callbackasm1(SB)
+ MOVL $966, CX
+ JMP callbackasm1(SB)
+ MOVL $967, CX
+ JMP callbackasm1(SB)
+ MOVL $968, CX
+ JMP callbackasm1(SB)
+ MOVL $969, CX
+ JMP callbackasm1(SB)
+ MOVL $970, CX
+ JMP callbackasm1(SB)
+ MOVL $971, CX
+ JMP callbackasm1(SB)
+ MOVL $972, CX
+ JMP callbackasm1(SB)
+ MOVL $973, CX
+ JMP callbackasm1(SB)
+ MOVL $974, CX
+ JMP callbackasm1(SB)
+ MOVL $975, CX
+ JMP callbackasm1(SB)
+ MOVL $976, CX
+ JMP callbackasm1(SB)
+ MOVL $977, CX
+ JMP callbackasm1(SB)
+ MOVL $978, CX
+ JMP callbackasm1(SB)
+ MOVL $979, CX
+ JMP callbackasm1(SB)
+ MOVL $980, CX
+ JMP callbackasm1(SB)
+ MOVL $981, CX
+ JMP callbackasm1(SB)
+ MOVL $982, CX
+ JMP callbackasm1(SB)
+ MOVL $983, CX
+ JMP callbackasm1(SB)
+ MOVL $984, CX
+ JMP callbackasm1(SB)
+ MOVL $985, CX
+ JMP callbackasm1(SB)
+ MOVL $986, CX
+ JMP callbackasm1(SB)
+ MOVL $987, CX
+ JMP callbackasm1(SB)
+ MOVL $988, CX
+ JMP callbackasm1(SB)
+ MOVL $989, CX
+ JMP callbackasm1(SB)
+ MOVL $990, CX
+ JMP callbackasm1(SB)
+ MOVL $991, CX
+ JMP callbackasm1(SB)
+ MOVL $992, CX
+ JMP callbackasm1(SB)
+ MOVL $993, CX
+ JMP callbackasm1(SB)
+ MOVL $994, CX
+ JMP callbackasm1(SB)
+ MOVL $995, CX
+ JMP callbackasm1(SB)
+ MOVL $996, CX
+ JMP callbackasm1(SB)
+ MOVL $997, CX
+ JMP callbackasm1(SB)
+ MOVL $998, CX
+ JMP callbackasm1(SB)
+ MOVL $999, CX
+ JMP callbackasm1(SB)
+ MOVL $1000, CX
+ JMP callbackasm1(SB)
+ MOVL $1001, CX
+ JMP callbackasm1(SB)
+ MOVL $1002, CX
+ JMP callbackasm1(SB)
+ MOVL $1003, CX
+ JMP callbackasm1(SB)
+ MOVL $1004, CX
+ JMP callbackasm1(SB)
+ MOVL $1005, CX
+ JMP callbackasm1(SB)
+ MOVL $1006, CX
+ JMP callbackasm1(SB)
+ MOVL $1007, CX
+ JMP callbackasm1(SB)
+ MOVL $1008, CX
+ JMP callbackasm1(SB)
+ MOVL $1009, CX
+ JMP callbackasm1(SB)
+ MOVL $1010, CX
+ JMP callbackasm1(SB)
+ MOVL $1011, CX
+ JMP callbackasm1(SB)
+ MOVL $1012, CX
+ JMP callbackasm1(SB)
+ MOVL $1013, CX
+ JMP callbackasm1(SB)
+ MOVL $1014, CX
+ JMP callbackasm1(SB)
+ MOVL $1015, CX
+ JMP callbackasm1(SB)
+ MOVL $1016, CX
+ JMP callbackasm1(SB)
+ MOVL $1017, CX
+ JMP callbackasm1(SB)
+ MOVL $1018, CX
+ JMP callbackasm1(SB)
+ MOVL $1019, CX
+ JMP callbackasm1(SB)
+ MOVL $1020, CX
+ JMP callbackasm1(SB)
+ MOVL $1021, CX
+ JMP callbackasm1(SB)
+ MOVL $1022, CX
+ JMP callbackasm1(SB)
+ MOVL $1023, CX
+ JMP callbackasm1(SB)
+ MOVL $1024, CX
+ JMP callbackasm1(SB)
+ MOVL $1025, CX
+ JMP callbackasm1(SB)
+ MOVL $1026, CX
+ JMP callbackasm1(SB)
+ MOVL $1027, CX
+ JMP callbackasm1(SB)
+ MOVL $1028, CX
+ JMP callbackasm1(SB)
+ MOVL $1029, CX
+ JMP callbackasm1(SB)
+ MOVL $1030, CX
+ JMP callbackasm1(SB)
+ MOVL $1031, CX
+ JMP callbackasm1(SB)
+ MOVL $1032, CX
+ JMP callbackasm1(SB)
+ MOVL $1033, CX
+ JMP callbackasm1(SB)
+ MOVL $1034, CX
+ JMP callbackasm1(SB)
+ MOVL $1035, CX
+ JMP callbackasm1(SB)
+ MOVL $1036, CX
+ JMP callbackasm1(SB)
+ MOVL $1037, CX
+ JMP callbackasm1(SB)
+ MOVL $1038, CX
+ JMP callbackasm1(SB)
+ MOVL $1039, CX
+ JMP callbackasm1(SB)
+ MOVL $1040, CX
+ JMP callbackasm1(SB)
+ MOVL $1041, CX
+ JMP callbackasm1(SB)
+ MOVL $1042, CX
+ JMP callbackasm1(SB)
+ MOVL $1043, CX
+ JMP callbackasm1(SB)
+ MOVL $1044, CX
+ JMP callbackasm1(SB)
+ MOVL $1045, CX
+ JMP callbackasm1(SB)
+ MOVL $1046, CX
+ JMP callbackasm1(SB)
+ MOVL $1047, CX
+ JMP callbackasm1(SB)
+ MOVL $1048, CX
+ JMP callbackasm1(SB)
+ MOVL $1049, CX
+ JMP callbackasm1(SB)
+ MOVL $1050, CX
+ JMP callbackasm1(SB)
+ MOVL $1051, CX
+ JMP callbackasm1(SB)
+ MOVL $1052, CX
+ JMP callbackasm1(SB)
+ MOVL $1053, CX
+ JMP callbackasm1(SB)
+ MOVL $1054, CX
+ JMP callbackasm1(SB)
+ MOVL $1055, CX
+ JMP callbackasm1(SB)
+ MOVL $1056, CX
+ JMP callbackasm1(SB)
+ MOVL $1057, CX
+ JMP callbackasm1(SB)
+ MOVL $1058, CX
+ JMP callbackasm1(SB)
+ MOVL $1059, CX
+ JMP callbackasm1(SB)
+ MOVL $1060, CX
+ JMP callbackasm1(SB)
+ MOVL $1061, CX
+ JMP callbackasm1(SB)
+ MOVL $1062, CX
+ JMP callbackasm1(SB)
+ MOVL $1063, CX
+ JMP callbackasm1(SB)
+ MOVL $1064, CX
+ JMP callbackasm1(SB)
+ MOVL $1065, CX
+ JMP callbackasm1(SB)
+ MOVL $1066, CX
+ JMP callbackasm1(SB)
+ MOVL $1067, CX
+ JMP callbackasm1(SB)
+ MOVL $1068, CX
+ JMP callbackasm1(SB)
+ MOVL $1069, CX
+ JMP callbackasm1(SB)
+ MOVL $1070, CX
+ JMP callbackasm1(SB)
+ MOVL $1071, CX
+ JMP callbackasm1(SB)
+ MOVL $1072, CX
+ JMP callbackasm1(SB)
+ MOVL $1073, CX
+ JMP callbackasm1(SB)
+ MOVL $1074, CX
+ JMP callbackasm1(SB)
+ MOVL $1075, CX
+ JMP callbackasm1(SB)
+ MOVL $1076, CX
+ JMP callbackasm1(SB)
+ MOVL $1077, CX
+ JMP callbackasm1(SB)
+ MOVL $1078, CX
+ JMP callbackasm1(SB)
+ MOVL $1079, CX
+ JMP callbackasm1(SB)
+ MOVL $1080, CX
+ JMP callbackasm1(SB)
+ MOVL $1081, CX
+ JMP callbackasm1(SB)
+ MOVL $1082, CX
+ JMP callbackasm1(SB)
+ MOVL $1083, CX
+ JMP callbackasm1(SB)
+ MOVL $1084, CX
+ JMP callbackasm1(SB)
+ MOVL $1085, CX
+ JMP callbackasm1(SB)
+ MOVL $1086, CX
+ JMP callbackasm1(SB)
+ MOVL $1087, CX
+ JMP callbackasm1(SB)
+ MOVL $1088, CX
+ JMP callbackasm1(SB)
+ MOVL $1089, CX
+ JMP callbackasm1(SB)
+ MOVL $1090, CX
+ JMP callbackasm1(SB)
+ MOVL $1091, CX
+ JMP callbackasm1(SB)
+ MOVL $1092, CX
+ JMP callbackasm1(SB)
+ MOVL $1093, CX
+ JMP callbackasm1(SB)
+ MOVL $1094, CX
+ JMP callbackasm1(SB)
+ MOVL $1095, CX
+ JMP callbackasm1(SB)
+ MOVL $1096, CX
+ JMP callbackasm1(SB)
+ MOVL $1097, CX
+ JMP callbackasm1(SB)
+ MOVL $1098, CX
+ JMP callbackasm1(SB)
+ MOVL $1099, CX
+ JMP callbackasm1(SB)
+ MOVL $1100, CX
+ JMP callbackasm1(SB)
+ MOVL $1101, CX
+ JMP callbackasm1(SB)
+ MOVL $1102, CX
+ JMP callbackasm1(SB)
+ MOVL $1103, CX
+ JMP callbackasm1(SB)
+ MOVL $1104, CX
+ JMP callbackasm1(SB)
+ MOVL $1105, CX
+ JMP callbackasm1(SB)
+ MOVL $1106, CX
+ JMP callbackasm1(SB)
+ MOVL $1107, CX
+ JMP callbackasm1(SB)
+ MOVL $1108, CX
+ JMP callbackasm1(SB)
+ MOVL $1109, CX
+ JMP callbackasm1(SB)
+ MOVL $1110, CX
+ JMP callbackasm1(SB)
+ MOVL $1111, CX
+ JMP callbackasm1(SB)
+ MOVL $1112, CX
+ JMP callbackasm1(SB)
+ MOVL $1113, CX
+ JMP callbackasm1(SB)
+ MOVL $1114, CX
+ JMP callbackasm1(SB)
+ MOVL $1115, CX
+ JMP callbackasm1(SB)
+ MOVL $1116, CX
+ JMP callbackasm1(SB)
+ MOVL $1117, CX
+ JMP callbackasm1(SB)
+ MOVL $1118, CX
+ JMP callbackasm1(SB)
+ MOVL $1119, CX
+ JMP callbackasm1(SB)
+ MOVL $1120, CX
+ JMP callbackasm1(SB)
+ MOVL $1121, CX
+ JMP callbackasm1(SB)
+ MOVL $1122, CX
+ JMP callbackasm1(SB)
+ MOVL $1123, CX
+ JMP callbackasm1(SB)
+ MOVL $1124, CX
+ JMP callbackasm1(SB)
+ MOVL $1125, CX
+ JMP callbackasm1(SB)
+ MOVL $1126, CX
+ JMP callbackasm1(SB)
+ MOVL $1127, CX
+ JMP callbackasm1(SB)
+ MOVL $1128, CX
+ JMP callbackasm1(SB)
+ MOVL $1129, CX
+ JMP callbackasm1(SB)
+ MOVL $1130, CX
+ JMP callbackasm1(SB)
+ MOVL $1131, CX
+ JMP callbackasm1(SB)
+ MOVL $1132, CX
+ JMP callbackasm1(SB)
+ MOVL $1133, CX
+ JMP callbackasm1(SB)
+ MOVL $1134, CX
+ JMP callbackasm1(SB)
+ MOVL $1135, CX
+ JMP callbackasm1(SB)
+ MOVL $1136, CX
+ JMP callbackasm1(SB)
+ MOVL $1137, CX
+ JMP callbackasm1(SB)
+ MOVL $1138, CX
+ JMP callbackasm1(SB)
+ MOVL $1139, CX
+ JMP callbackasm1(SB)
+ MOVL $1140, CX
+ JMP callbackasm1(SB)
+ MOVL $1141, CX
+ JMP callbackasm1(SB)
+ MOVL $1142, CX
+ JMP callbackasm1(SB)
+ MOVL $1143, CX
+ JMP callbackasm1(SB)
+ MOVL $1144, CX
+ JMP callbackasm1(SB)
+ MOVL $1145, CX
+ JMP callbackasm1(SB)
+ MOVL $1146, CX
+ JMP callbackasm1(SB)
+ MOVL $1147, CX
+ JMP callbackasm1(SB)
+ MOVL $1148, CX
+ JMP callbackasm1(SB)
+ MOVL $1149, CX
+ JMP callbackasm1(SB)
+ MOVL $1150, CX
+ JMP callbackasm1(SB)
+ MOVL $1151, CX
+ JMP callbackasm1(SB)
+ MOVL $1152, CX
+ JMP callbackasm1(SB)
+ MOVL $1153, CX
+ JMP callbackasm1(SB)
+ MOVL $1154, CX
+ JMP callbackasm1(SB)
+ MOVL $1155, CX
+ JMP callbackasm1(SB)
+ MOVL $1156, CX
+ JMP callbackasm1(SB)
+ MOVL $1157, CX
+ JMP callbackasm1(SB)
+ MOVL $1158, CX
+ JMP callbackasm1(SB)
+ MOVL $1159, CX
+ JMP callbackasm1(SB)
+ MOVL $1160, CX
+ JMP callbackasm1(SB)
+ MOVL $1161, CX
+ JMP callbackasm1(SB)
+ MOVL $1162, CX
+ JMP callbackasm1(SB)
+ MOVL $1163, CX
+ JMP callbackasm1(SB)
+ MOVL $1164, CX
+ JMP callbackasm1(SB)
+ MOVL $1165, CX
+ JMP callbackasm1(SB)
+ MOVL $1166, CX
+ JMP callbackasm1(SB)
+ MOVL $1167, CX
+ JMP callbackasm1(SB)
+ MOVL $1168, CX
+ JMP callbackasm1(SB)
+ MOVL $1169, CX
+ JMP callbackasm1(SB)
+ MOVL $1170, CX
+ JMP callbackasm1(SB)
+ MOVL $1171, CX
+ JMP callbackasm1(SB)
+ MOVL $1172, CX
+ JMP callbackasm1(SB)
+ MOVL $1173, CX
+ JMP callbackasm1(SB)
+ MOVL $1174, CX
+ JMP callbackasm1(SB)
+ MOVL $1175, CX
+ JMP callbackasm1(SB)
+ MOVL $1176, CX
+ JMP callbackasm1(SB)
+ MOVL $1177, CX
+ JMP callbackasm1(SB)
+ MOVL $1178, CX
+ JMP callbackasm1(SB)
+ MOVL $1179, CX
+ JMP callbackasm1(SB)
+ MOVL $1180, CX
+ JMP callbackasm1(SB)
+ MOVL $1181, CX
+ JMP callbackasm1(SB)
+ MOVL $1182, CX
+ JMP callbackasm1(SB)
+ MOVL $1183, CX
+ JMP callbackasm1(SB)
+ MOVL $1184, CX
+ JMP callbackasm1(SB)
+ MOVL $1185, CX
+ JMP callbackasm1(SB)
+ MOVL $1186, CX
+ JMP callbackasm1(SB)
+ MOVL $1187, CX
+ JMP callbackasm1(SB)
+ MOVL $1188, CX
+ JMP callbackasm1(SB)
+ MOVL $1189, CX
+ JMP callbackasm1(SB)
+ MOVL $1190, CX
+ JMP callbackasm1(SB)
+ MOVL $1191, CX
+ JMP callbackasm1(SB)
+ MOVL $1192, CX
+ JMP callbackasm1(SB)
+ MOVL $1193, CX
+ JMP callbackasm1(SB)
+ MOVL $1194, CX
+ JMP callbackasm1(SB)
+ MOVL $1195, CX
+ JMP callbackasm1(SB)
+ MOVL $1196, CX
+ JMP callbackasm1(SB)
+ MOVL $1197, CX
+ JMP callbackasm1(SB)
+ MOVL $1198, CX
+ JMP callbackasm1(SB)
+ MOVL $1199, CX
+ JMP callbackasm1(SB)
+ MOVL $1200, CX
+ JMP callbackasm1(SB)
+ MOVL $1201, CX
+ JMP callbackasm1(SB)
+ MOVL $1202, CX
+ JMP callbackasm1(SB)
+ MOVL $1203, CX
+ JMP callbackasm1(SB)
+ MOVL $1204, CX
+ JMP callbackasm1(SB)
+ MOVL $1205, CX
+ JMP callbackasm1(SB)
+ MOVL $1206, CX
+ JMP callbackasm1(SB)
+ MOVL $1207, CX
+ JMP callbackasm1(SB)
+ MOVL $1208, CX
+ JMP callbackasm1(SB)
+ MOVL $1209, CX
+ JMP callbackasm1(SB)
+ MOVL $1210, CX
+ JMP callbackasm1(SB)
+ MOVL $1211, CX
+ JMP callbackasm1(SB)
+ MOVL $1212, CX
+ JMP callbackasm1(SB)
+ MOVL $1213, CX
+ JMP callbackasm1(SB)
+ MOVL $1214, CX
+ JMP callbackasm1(SB)
+ MOVL $1215, CX
+ JMP callbackasm1(SB)
+ MOVL $1216, CX
+ JMP callbackasm1(SB)
+ MOVL $1217, CX
+ JMP callbackasm1(SB)
+ MOVL $1218, CX
+ JMP callbackasm1(SB)
+ MOVL $1219, CX
+ JMP callbackasm1(SB)
+ MOVL $1220, CX
+ JMP callbackasm1(SB)
+ MOVL $1221, CX
+ JMP callbackasm1(SB)
+ MOVL $1222, CX
+ JMP callbackasm1(SB)
+ MOVL $1223, CX
+ JMP callbackasm1(SB)
+ MOVL $1224, CX
+ JMP callbackasm1(SB)
+ MOVL $1225, CX
+ JMP callbackasm1(SB)
+ MOVL $1226, CX
+ JMP callbackasm1(SB)
+ MOVL $1227, CX
+ JMP callbackasm1(SB)
+ MOVL $1228, CX
+ JMP callbackasm1(SB)
+ MOVL $1229, CX
+ JMP callbackasm1(SB)
+ MOVL $1230, CX
+ JMP callbackasm1(SB)
+ MOVL $1231, CX
+ JMP callbackasm1(SB)
+ MOVL $1232, CX
+ JMP callbackasm1(SB)
+ MOVL $1233, CX
+ JMP callbackasm1(SB)
+ MOVL $1234, CX
+ JMP callbackasm1(SB)
+ MOVL $1235, CX
+ JMP callbackasm1(SB)
+ MOVL $1236, CX
+ JMP callbackasm1(SB)
+ MOVL $1237, CX
+ JMP callbackasm1(SB)
+ MOVL $1238, CX
+ JMP callbackasm1(SB)
+ MOVL $1239, CX
+ JMP callbackasm1(SB)
+ MOVL $1240, CX
+ JMP callbackasm1(SB)
+ MOVL $1241, CX
+ JMP callbackasm1(SB)
+ MOVL $1242, CX
+ JMP callbackasm1(SB)
+ MOVL $1243, CX
+ JMP callbackasm1(SB)
+ MOVL $1244, CX
+ JMP callbackasm1(SB)
+ MOVL $1245, CX
+ JMP callbackasm1(SB)
+ MOVL $1246, CX
+ JMP callbackasm1(SB)
+ MOVL $1247, CX
+ JMP callbackasm1(SB)
+ MOVL $1248, CX
+ JMP callbackasm1(SB)
+ MOVL $1249, CX
+ JMP callbackasm1(SB)
+ MOVL $1250, CX
+ JMP callbackasm1(SB)
+ MOVL $1251, CX
+ JMP callbackasm1(SB)
+ MOVL $1252, CX
+ JMP callbackasm1(SB)
+ MOVL $1253, CX
+ JMP callbackasm1(SB)
+ MOVL $1254, CX
+ JMP callbackasm1(SB)
+ MOVL $1255, CX
+ JMP callbackasm1(SB)
+ MOVL $1256, CX
+ JMP callbackasm1(SB)
+ MOVL $1257, CX
+ JMP callbackasm1(SB)
+ MOVL $1258, CX
+ JMP callbackasm1(SB)
+ MOVL $1259, CX
+ JMP callbackasm1(SB)
+ MOVL $1260, CX
+ JMP callbackasm1(SB)
+ MOVL $1261, CX
+ JMP callbackasm1(SB)
+ MOVL $1262, CX
+ JMP callbackasm1(SB)
+ MOVL $1263, CX
+ JMP callbackasm1(SB)
+ MOVL $1264, CX
+ JMP callbackasm1(SB)
+ MOVL $1265, CX
+ JMP callbackasm1(SB)
+ MOVL $1266, CX
+ JMP callbackasm1(SB)
+ MOVL $1267, CX
+ JMP callbackasm1(SB)
+ MOVL $1268, CX
+ JMP callbackasm1(SB)
+ MOVL $1269, CX
+ JMP callbackasm1(SB)
+ MOVL $1270, CX
+ JMP callbackasm1(SB)
+ MOVL $1271, CX
+ JMP callbackasm1(SB)
+ MOVL $1272, CX
+ JMP callbackasm1(SB)
+ MOVL $1273, CX
+ JMP callbackasm1(SB)
+ MOVL $1274, CX
+ JMP callbackasm1(SB)
+ MOVL $1275, CX
+ JMP callbackasm1(SB)
+ MOVL $1276, CX
+ JMP callbackasm1(SB)
+ MOVL $1277, CX
+ JMP callbackasm1(SB)
+ MOVL $1278, CX
+ JMP callbackasm1(SB)
+ MOVL $1279, CX
+ JMP callbackasm1(SB)
+ MOVL $1280, CX
+ JMP callbackasm1(SB)
+ MOVL $1281, CX
+ JMP callbackasm1(SB)
+ MOVL $1282, CX
+ JMP callbackasm1(SB)
+ MOVL $1283, CX
+ JMP callbackasm1(SB)
+ MOVL $1284, CX
+ JMP callbackasm1(SB)
+ MOVL $1285, CX
+ JMP callbackasm1(SB)
+ MOVL $1286, CX
+ JMP callbackasm1(SB)
+ MOVL $1287, CX
+ JMP callbackasm1(SB)
+ MOVL $1288, CX
+ JMP callbackasm1(SB)
+ MOVL $1289, CX
+ JMP callbackasm1(SB)
+ MOVL $1290, CX
+ JMP callbackasm1(SB)
+ MOVL $1291, CX
+ JMP callbackasm1(SB)
+ MOVL $1292, CX
+ JMP callbackasm1(SB)
+ MOVL $1293, CX
+ JMP callbackasm1(SB)
+ MOVL $1294, CX
+ JMP callbackasm1(SB)
+ MOVL $1295, CX
+ JMP callbackasm1(SB)
+ MOVL $1296, CX
+ JMP callbackasm1(SB)
+ MOVL $1297, CX
+ JMP callbackasm1(SB)
+ MOVL $1298, CX
+ JMP callbackasm1(SB)
+ MOVL $1299, CX
+ JMP callbackasm1(SB)
+ MOVL $1300, CX
+ JMP callbackasm1(SB)
+ MOVL $1301, CX
+ JMP callbackasm1(SB)
+ MOVL $1302, CX
+ JMP callbackasm1(SB)
+ MOVL $1303, CX
+ JMP callbackasm1(SB)
+ MOVL $1304, CX
+ JMP callbackasm1(SB)
+ MOVL $1305, CX
+ JMP callbackasm1(SB)
+ MOVL $1306, CX
+ JMP callbackasm1(SB)
+ MOVL $1307, CX
+ JMP callbackasm1(SB)
+ MOVL $1308, CX
+ JMP callbackasm1(SB)
+ MOVL $1309, CX
+ JMP callbackasm1(SB)
+ MOVL $1310, CX
+ JMP callbackasm1(SB)
+ MOVL $1311, CX
+ JMP callbackasm1(SB)
+ MOVL $1312, CX
+ JMP callbackasm1(SB)
+ MOVL $1313, CX
+ JMP callbackasm1(SB)
+ MOVL $1314, CX
+ JMP callbackasm1(SB)
+ MOVL $1315, CX
+ JMP callbackasm1(SB)
+ MOVL $1316, CX
+ JMP callbackasm1(SB)
+ MOVL $1317, CX
+ JMP callbackasm1(SB)
+ MOVL $1318, CX
+ JMP callbackasm1(SB)
+ MOVL $1319, CX
+ JMP callbackasm1(SB)
+ MOVL $1320, CX
+ JMP callbackasm1(SB)
+ MOVL $1321, CX
+ JMP callbackasm1(SB)
+ MOVL $1322, CX
+ JMP callbackasm1(SB)
+ MOVL $1323, CX
+ JMP callbackasm1(SB)
+ MOVL $1324, CX
+ JMP callbackasm1(SB)
+ MOVL $1325, CX
+ JMP callbackasm1(SB)
+ MOVL $1326, CX
+ JMP callbackasm1(SB)
+ MOVL $1327, CX
+ JMP callbackasm1(SB)
+ MOVL $1328, CX
+ JMP callbackasm1(SB)
+ MOVL $1329, CX
+ JMP callbackasm1(SB)
+ MOVL $1330, CX
+ JMP callbackasm1(SB)
+ MOVL $1331, CX
+ JMP callbackasm1(SB)
+ MOVL $1332, CX
+ JMP callbackasm1(SB)
+ MOVL $1333, CX
+ JMP callbackasm1(SB)
+ MOVL $1334, CX
+ JMP callbackasm1(SB)
+ MOVL $1335, CX
+ JMP callbackasm1(SB)
+ MOVL $1336, CX
+ JMP callbackasm1(SB)
+ MOVL $1337, CX
+ JMP callbackasm1(SB)
+ MOVL $1338, CX
+ JMP callbackasm1(SB)
+ MOVL $1339, CX
+ JMP callbackasm1(SB)
+ MOVL $1340, CX
+ JMP callbackasm1(SB)
+ MOVL $1341, CX
+ JMP callbackasm1(SB)
+ MOVL $1342, CX
+ JMP callbackasm1(SB)
+ MOVL $1343, CX
+ JMP callbackasm1(SB)
+ MOVL $1344, CX
+ JMP callbackasm1(SB)
+ MOVL $1345, CX
+ JMP callbackasm1(SB)
+ MOVL $1346, CX
+ JMP callbackasm1(SB)
+ MOVL $1347, CX
+ JMP callbackasm1(SB)
+ MOVL $1348, CX
+ JMP callbackasm1(SB)
+ MOVL $1349, CX
+ JMP callbackasm1(SB)
+ MOVL $1350, CX
+ JMP callbackasm1(SB)
+ MOVL $1351, CX
+ JMP callbackasm1(SB)
+ MOVL $1352, CX
+ JMP callbackasm1(SB)
+ MOVL $1353, CX
+ JMP callbackasm1(SB)
+ MOVL $1354, CX
+ JMP callbackasm1(SB)
+ MOVL $1355, CX
+ JMP callbackasm1(SB)
+ MOVL $1356, CX
+ JMP callbackasm1(SB)
+ MOVL $1357, CX
+ JMP callbackasm1(SB)
+ MOVL $1358, CX
+ JMP callbackasm1(SB)
+ MOVL $1359, CX
+ JMP callbackasm1(SB)
+ MOVL $1360, CX
+ JMP callbackasm1(SB)
+ MOVL $1361, CX
+ JMP callbackasm1(SB)
+ MOVL $1362, CX
+ JMP callbackasm1(SB)
+ MOVL $1363, CX
+ JMP callbackasm1(SB)
+ MOVL $1364, CX
+ JMP callbackasm1(SB)
+ MOVL $1365, CX
+ JMP callbackasm1(SB)
+ MOVL $1366, CX
+ JMP callbackasm1(SB)
+ MOVL $1367, CX
+ JMP callbackasm1(SB)
+ MOVL $1368, CX
+ JMP callbackasm1(SB)
+ MOVL $1369, CX
+ JMP callbackasm1(SB)
+ MOVL $1370, CX
+ JMP callbackasm1(SB)
+ MOVL $1371, CX
+ JMP callbackasm1(SB)
+ MOVL $1372, CX
+ JMP callbackasm1(SB)
+ MOVL $1373, CX
+ JMP callbackasm1(SB)
+ MOVL $1374, CX
+ JMP callbackasm1(SB)
+ MOVL $1375, CX
+ JMP callbackasm1(SB)
+ MOVL $1376, CX
+ JMP callbackasm1(SB)
+ MOVL $1377, CX
+ JMP callbackasm1(SB)
+ MOVL $1378, CX
+ JMP callbackasm1(SB)
+ MOVL $1379, CX
+ JMP callbackasm1(SB)
+ MOVL $1380, CX
+ JMP callbackasm1(SB)
+ MOVL $1381, CX
+ JMP callbackasm1(SB)
+ MOVL $1382, CX
+ JMP callbackasm1(SB)
+ MOVL $1383, CX
+ JMP callbackasm1(SB)
+ MOVL $1384, CX
+ JMP callbackasm1(SB)
+ MOVL $1385, CX
+ JMP callbackasm1(SB)
+ MOVL $1386, CX
+ JMP callbackasm1(SB)
+ MOVL $1387, CX
+ JMP callbackasm1(SB)
+ MOVL $1388, CX
+ JMP callbackasm1(SB)
+ MOVL $1389, CX
+ JMP callbackasm1(SB)
+ MOVL $1390, CX
+ JMP callbackasm1(SB)
+ MOVL $1391, CX
+ JMP callbackasm1(SB)
+ MOVL $1392, CX
+ JMP callbackasm1(SB)
+ MOVL $1393, CX
+ JMP callbackasm1(SB)
+ MOVL $1394, CX
+ JMP callbackasm1(SB)
+ MOVL $1395, CX
+ JMP callbackasm1(SB)
+ MOVL $1396, CX
+ JMP callbackasm1(SB)
+ MOVL $1397, CX
+ JMP callbackasm1(SB)
+ MOVL $1398, CX
+ JMP callbackasm1(SB)
+ MOVL $1399, CX
+ JMP callbackasm1(SB)
+ MOVL $1400, CX
+ JMP callbackasm1(SB)
+ MOVL $1401, CX
+ JMP callbackasm1(SB)
+ MOVL $1402, CX
+ JMP callbackasm1(SB)
+ MOVL $1403, CX
+ JMP callbackasm1(SB)
+ MOVL $1404, CX
+ JMP callbackasm1(SB)
+ MOVL $1405, CX
+ JMP callbackasm1(SB)
+ MOVL $1406, CX
+ JMP callbackasm1(SB)
+ MOVL $1407, CX
+ JMP callbackasm1(SB)
+ MOVL $1408, CX
+ JMP callbackasm1(SB)
+ MOVL $1409, CX
+ JMP callbackasm1(SB)
+ MOVL $1410, CX
+ JMP callbackasm1(SB)
+ MOVL $1411, CX
+ JMP callbackasm1(SB)
+ MOVL $1412, CX
+ JMP callbackasm1(SB)
+ MOVL $1413, CX
+ JMP callbackasm1(SB)
+ MOVL $1414, CX
+ JMP callbackasm1(SB)
+ MOVL $1415, CX
+ JMP callbackasm1(SB)
+ MOVL $1416, CX
+ JMP callbackasm1(SB)
+ MOVL $1417, CX
+ JMP callbackasm1(SB)
+ MOVL $1418, CX
+ JMP callbackasm1(SB)
+ MOVL $1419, CX
+ JMP callbackasm1(SB)
+ MOVL $1420, CX
+ JMP callbackasm1(SB)
+ MOVL $1421, CX
+ JMP callbackasm1(SB)
+ MOVL $1422, CX
+ JMP callbackasm1(SB)
+ MOVL $1423, CX
+ JMP callbackasm1(SB)
+ MOVL $1424, CX
+ JMP callbackasm1(SB)
+ MOVL $1425, CX
+ JMP callbackasm1(SB)
+ MOVL $1426, CX
+ JMP callbackasm1(SB)
+ MOVL $1427, CX
+ JMP callbackasm1(SB)
+ MOVL $1428, CX
+ JMP callbackasm1(SB)
+ MOVL $1429, CX
+ JMP callbackasm1(SB)
+ MOVL $1430, CX
+ JMP callbackasm1(SB)
+ MOVL $1431, CX
+ JMP callbackasm1(SB)
+ MOVL $1432, CX
+ JMP callbackasm1(SB)
+ MOVL $1433, CX
+ JMP callbackasm1(SB)
+ MOVL $1434, CX
+ JMP callbackasm1(SB)
+ MOVL $1435, CX
+ JMP callbackasm1(SB)
+ MOVL $1436, CX
+ JMP callbackasm1(SB)
+ MOVL $1437, CX
+ JMP callbackasm1(SB)
+ MOVL $1438, CX
+ JMP callbackasm1(SB)
+ MOVL $1439, CX
+ JMP callbackasm1(SB)
+ MOVL $1440, CX
+ JMP callbackasm1(SB)
+ MOVL $1441, CX
+ JMP callbackasm1(SB)
+ MOVL $1442, CX
+ JMP callbackasm1(SB)
+ MOVL $1443, CX
+ JMP callbackasm1(SB)
+ MOVL $1444, CX
+ JMP callbackasm1(SB)
+ MOVL $1445, CX
+ JMP callbackasm1(SB)
+ MOVL $1446, CX
+ JMP callbackasm1(SB)
+ MOVL $1447, CX
+ JMP callbackasm1(SB)
+ MOVL $1448, CX
+ JMP callbackasm1(SB)
+ MOVL $1449, CX
+ JMP callbackasm1(SB)
+ MOVL $1450, CX
+ JMP callbackasm1(SB)
+ MOVL $1451, CX
+ JMP callbackasm1(SB)
+ MOVL $1452, CX
+ JMP callbackasm1(SB)
+ MOVL $1453, CX
+ JMP callbackasm1(SB)
+ MOVL $1454, CX
+ JMP callbackasm1(SB)
+ MOVL $1455, CX
+ JMP callbackasm1(SB)
+ MOVL $1456, CX
+ JMP callbackasm1(SB)
+ MOVL $1457, CX
+ JMP callbackasm1(SB)
+ MOVL $1458, CX
+ JMP callbackasm1(SB)
+ MOVL $1459, CX
+ JMP callbackasm1(SB)
+ MOVL $1460, CX
+ JMP callbackasm1(SB)
+ MOVL $1461, CX
+ JMP callbackasm1(SB)
+ MOVL $1462, CX
+ JMP callbackasm1(SB)
+ MOVL $1463, CX
+ JMP callbackasm1(SB)
+ MOVL $1464, CX
+ JMP callbackasm1(SB)
+ MOVL $1465, CX
+ JMP callbackasm1(SB)
+ MOVL $1466, CX
+ JMP callbackasm1(SB)
+ MOVL $1467, CX
+ JMP callbackasm1(SB)
+ MOVL $1468, CX
+ JMP callbackasm1(SB)
+ MOVL $1469, CX
+ JMP callbackasm1(SB)
+ MOVL $1470, CX
+ JMP callbackasm1(SB)
+ MOVL $1471, CX
+ JMP callbackasm1(SB)
+ MOVL $1472, CX
+ JMP callbackasm1(SB)
+ MOVL $1473, CX
+ JMP callbackasm1(SB)
+ MOVL $1474, CX
+ JMP callbackasm1(SB)
+ MOVL $1475, CX
+ JMP callbackasm1(SB)
+ MOVL $1476, CX
+ JMP callbackasm1(SB)
+ MOVL $1477, CX
+ JMP callbackasm1(SB)
+ MOVL $1478, CX
+ JMP callbackasm1(SB)
+ MOVL $1479, CX
+ JMP callbackasm1(SB)
+ MOVL $1480, CX
+ JMP callbackasm1(SB)
+ MOVL $1481, CX
+ JMP callbackasm1(SB)
+ MOVL $1482, CX
+ JMP callbackasm1(SB)
+ MOVL $1483, CX
+ JMP callbackasm1(SB)
+ MOVL $1484, CX
+ JMP callbackasm1(SB)
+ MOVL $1485, CX
+ JMP callbackasm1(SB)
+ MOVL $1486, CX
+ JMP callbackasm1(SB)
+ MOVL $1487, CX
+ JMP callbackasm1(SB)
+ MOVL $1488, CX
+ JMP callbackasm1(SB)
+ MOVL $1489, CX
+ JMP callbackasm1(SB)
+ MOVL $1490, CX
+ JMP callbackasm1(SB)
+ MOVL $1491, CX
+ JMP callbackasm1(SB)
+ MOVL $1492, CX
+ JMP callbackasm1(SB)
+ MOVL $1493, CX
+ JMP callbackasm1(SB)
+ MOVL $1494, CX
+ JMP callbackasm1(SB)
+ MOVL $1495, CX
+ JMP callbackasm1(SB)
+ MOVL $1496, CX
+ JMP callbackasm1(SB)
+ MOVL $1497, CX
+ JMP callbackasm1(SB)
+ MOVL $1498, CX
+ JMP callbackasm1(SB)
+ MOVL $1499, CX
+ JMP callbackasm1(SB)
+ MOVL $1500, CX
+ JMP callbackasm1(SB)
+ MOVL $1501, CX
+ JMP callbackasm1(SB)
+ MOVL $1502, CX
+ JMP callbackasm1(SB)
+ MOVL $1503, CX
+ JMP callbackasm1(SB)
+ MOVL $1504, CX
+ JMP callbackasm1(SB)
+ MOVL $1505, CX
+ JMP callbackasm1(SB)
+ MOVL $1506, CX
+ JMP callbackasm1(SB)
+ MOVL $1507, CX
+ JMP callbackasm1(SB)
+ MOVL $1508, CX
+ JMP callbackasm1(SB)
+ MOVL $1509, CX
+ JMP callbackasm1(SB)
+ MOVL $1510, CX
+ JMP callbackasm1(SB)
+ MOVL $1511, CX
+ JMP callbackasm1(SB)
+ MOVL $1512, CX
+ JMP callbackasm1(SB)
+ MOVL $1513, CX
+ JMP callbackasm1(SB)
+ MOVL $1514, CX
+ JMP callbackasm1(SB)
+ MOVL $1515, CX
+ JMP callbackasm1(SB)
+ MOVL $1516, CX
+ JMP callbackasm1(SB)
+ MOVL $1517, CX
+ JMP callbackasm1(SB)
+ MOVL $1518, CX
+ JMP callbackasm1(SB)
+ MOVL $1519, CX
+ JMP callbackasm1(SB)
+ MOVL $1520, CX
+ JMP callbackasm1(SB)
+ MOVL $1521, CX
+ JMP callbackasm1(SB)
+ MOVL $1522, CX
+ JMP callbackasm1(SB)
+ MOVL $1523, CX
+ JMP callbackasm1(SB)
+ MOVL $1524, CX
+ JMP callbackasm1(SB)
+ MOVL $1525, CX
+ JMP callbackasm1(SB)
+ MOVL $1526, CX
+ JMP callbackasm1(SB)
+ MOVL $1527, CX
+ JMP callbackasm1(SB)
+ MOVL $1528, CX
+ JMP callbackasm1(SB)
+ MOVL $1529, CX
+ JMP callbackasm1(SB)
+ MOVL $1530, CX
+ JMP callbackasm1(SB)
+ MOVL $1531, CX
+ JMP callbackasm1(SB)
+ MOVL $1532, CX
+ JMP callbackasm1(SB)
+ MOVL $1533, CX
+ JMP callbackasm1(SB)
+ MOVL $1534, CX
+ JMP callbackasm1(SB)
+ MOVL $1535, CX
+ JMP callbackasm1(SB)
+ MOVL $1536, CX
+ JMP callbackasm1(SB)
+ MOVL $1537, CX
+ JMP callbackasm1(SB)
+ MOVL $1538, CX
+ JMP callbackasm1(SB)
+ MOVL $1539, CX
+ JMP callbackasm1(SB)
+ MOVL $1540, CX
+ JMP callbackasm1(SB)
+ MOVL $1541, CX
+ JMP callbackasm1(SB)
+ MOVL $1542, CX
+ JMP callbackasm1(SB)
+ MOVL $1543, CX
+ JMP callbackasm1(SB)
+ MOVL $1544, CX
+ JMP callbackasm1(SB)
+ MOVL $1545, CX
+ JMP callbackasm1(SB)
+ MOVL $1546, CX
+ JMP callbackasm1(SB)
+ MOVL $1547, CX
+ JMP callbackasm1(SB)
+ MOVL $1548, CX
+ JMP callbackasm1(SB)
+ MOVL $1549, CX
+ JMP callbackasm1(SB)
+ MOVL $1550, CX
+ JMP callbackasm1(SB)
+ MOVL $1551, CX
+ JMP callbackasm1(SB)
+ MOVL $1552, CX
+ JMP callbackasm1(SB)
+ MOVL $1553, CX
+ JMP callbackasm1(SB)
+ MOVL $1554, CX
+ JMP callbackasm1(SB)
+ MOVL $1555, CX
+ JMP callbackasm1(SB)
+ MOVL $1556, CX
+ JMP callbackasm1(SB)
+ MOVL $1557, CX
+ JMP callbackasm1(SB)
+ MOVL $1558, CX
+ JMP callbackasm1(SB)
+ MOVL $1559, CX
+ JMP callbackasm1(SB)
+ MOVL $1560, CX
+ JMP callbackasm1(SB)
+ MOVL $1561, CX
+ JMP callbackasm1(SB)
+ MOVL $1562, CX
+ JMP callbackasm1(SB)
+ MOVL $1563, CX
+ JMP callbackasm1(SB)
+ MOVL $1564, CX
+ JMP callbackasm1(SB)
+ MOVL $1565, CX
+ JMP callbackasm1(SB)
+ MOVL $1566, CX
+ JMP callbackasm1(SB)
+ MOVL $1567, CX
+ JMP callbackasm1(SB)
+ MOVL $1568, CX
+ JMP callbackasm1(SB)
+ MOVL $1569, CX
+ JMP callbackasm1(SB)
+ MOVL $1570, CX
+ JMP callbackasm1(SB)
+ MOVL $1571, CX
+ JMP callbackasm1(SB)
+ MOVL $1572, CX
+ JMP callbackasm1(SB)
+ MOVL $1573, CX
+ JMP callbackasm1(SB)
+ MOVL $1574, CX
+ JMP callbackasm1(SB)
+ MOVL $1575, CX
+ JMP callbackasm1(SB)
+ MOVL $1576, CX
+ JMP callbackasm1(SB)
+ MOVL $1577, CX
+ JMP callbackasm1(SB)
+ MOVL $1578, CX
+ JMP callbackasm1(SB)
+ MOVL $1579, CX
+ JMP callbackasm1(SB)
+ MOVL $1580, CX
+ JMP callbackasm1(SB)
+ MOVL $1581, CX
+ JMP callbackasm1(SB)
+ MOVL $1582, CX
+ JMP callbackasm1(SB)
+ MOVL $1583, CX
+ JMP callbackasm1(SB)
+ MOVL $1584, CX
+ JMP callbackasm1(SB)
+ MOVL $1585, CX
+ JMP callbackasm1(SB)
+ MOVL $1586, CX
+ JMP callbackasm1(SB)
+ MOVL $1587, CX
+ JMP callbackasm1(SB)
+ MOVL $1588, CX
+ JMP callbackasm1(SB)
+ MOVL $1589, CX
+ JMP callbackasm1(SB)
+ MOVL $1590, CX
+ JMP callbackasm1(SB)
+ MOVL $1591, CX
+ JMP callbackasm1(SB)
+ MOVL $1592, CX
+ JMP callbackasm1(SB)
+ MOVL $1593, CX
+ JMP callbackasm1(SB)
+ MOVL $1594, CX
+ JMP callbackasm1(SB)
+ MOVL $1595, CX
+ JMP callbackasm1(SB)
+ MOVL $1596, CX
+ JMP callbackasm1(SB)
+ MOVL $1597, CX
+ JMP callbackasm1(SB)
+ MOVL $1598, CX
+ JMP callbackasm1(SB)
+ MOVL $1599, CX
+ JMP callbackasm1(SB)
+ MOVL $1600, CX
+ JMP callbackasm1(SB)
+ MOVL $1601, CX
+ JMP callbackasm1(SB)
+ MOVL $1602, CX
+ JMP callbackasm1(SB)
+ MOVL $1603, CX
+ JMP callbackasm1(SB)
+ MOVL $1604, CX
+ JMP callbackasm1(SB)
+ MOVL $1605, CX
+ JMP callbackasm1(SB)
+ MOVL $1606, CX
+ JMP callbackasm1(SB)
+ MOVL $1607, CX
+ JMP callbackasm1(SB)
+ MOVL $1608, CX
+ JMP callbackasm1(SB)
+ MOVL $1609, CX
+ JMP callbackasm1(SB)
+ MOVL $1610, CX
+ JMP callbackasm1(SB)
+ MOVL $1611, CX
+ JMP callbackasm1(SB)
+ MOVL $1612, CX
+ JMP callbackasm1(SB)
+ MOVL $1613, CX
+ JMP callbackasm1(SB)
+ MOVL $1614, CX
+ JMP callbackasm1(SB)
+ MOVL $1615, CX
+ JMP callbackasm1(SB)
+ MOVL $1616, CX
+ JMP callbackasm1(SB)
+ MOVL $1617, CX
+ JMP callbackasm1(SB)
+ MOVL $1618, CX
+ JMP callbackasm1(SB)
+ MOVL $1619, CX
+ JMP callbackasm1(SB)
+ MOVL $1620, CX
+ JMP callbackasm1(SB)
+ MOVL $1621, CX
+ JMP callbackasm1(SB)
+ MOVL $1622, CX
+ JMP callbackasm1(SB)
+ MOVL $1623, CX
+ JMP callbackasm1(SB)
+ MOVL $1624, CX
+ JMP callbackasm1(SB)
+ MOVL $1625, CX
+ JMP callbackasm1(SB)
+ MOVL $1626, CX
+ JMP callbackasm1(SB)
+ MOVL $1627, CX
+ JMP callbackasm1(SB)
+ MOVL $1628, CX
+ JMP callbackasm1(SB)
+ MOVL $1629, CX
+ JMP callbackasm1(SB)
+ MOVL $1630, CX
+ JMP callbackasm1(SB)
+ MOVL $1631, CX
+ JMP callbackasm1(SB)
+ MOVL $1632, CX
+ JMP callbackasm1(SB)
+ MOVL $1633, CX
+ JMP callbackasm1(SB)
+ MOVL $1634, CX
+ JMP callbackasm1(SB)
+ MOVL $1635, CX
+ JMP callbackasm1(SB)
+ MOVL $1636, CX
+ JMP callbackasm1(SB)
+ MOVL $1637, CX
+ JMP callbackasm1(SB)
+ MOVL $1638, CX
+ JMP callbackasm1(SB)
+ MOVL $1639, CX
+ JMP callbackasm1(SB)
+ MOVL $1640, CX
+ JMP callbackasm1(SB)
+ MOVL $1641, CX
+ JMP callbackasm1(SB)
+ MOVL $1642, CX
+ JMP callbackasm1(SB)
+ MOVL $1643, CX
+ JMP callbackasm1(SB)
+ MOVL $1644, CX
+ JMP callbackasm1(SB)
+ MOVL $1645, CX
+ JMP callbackasm1(SB)
+ MOVL $1646, CX
+ JMP callbackasm1(SB)
+ MOVL $1647, CX
+ JMP callbackasm1(SB)
+ MOVL $1648, CX
+ JMP callbackasm1(SB)
+ MOVL $1649, CX
+ JMP callbackasm1(SB)
+ MOVL $1650, CX
+ JMP callbackasm1(SB)
+ MOVL $1651, CX
+ JMP callbackasm1(SB)
+ MOVL $1652, CX
+ JMP callbackasm1(SB)
+ MOVL $1653, CX
+ JMP callbackasm1(SB)
+ MOVL $1654, CX
+ JMP callbackasm1(SB)
+ MOVL $1655, CX
+ JMP callbackasm1(SB)
+ MOVL $1656, CX
+ JMP callbackasm1(SB)
+ MOVL $1657, CX
+ JMP callbackasm1(SB)
+ MOVL $1658, CX
+ JMP callbackasm1(SB)
+ MOVL $1659, CX
+ JMP callbackasm1(SB)
+ MOVL $1660, CX
+ JMP callbackasm1(SB)
+ MOVL $1661, CX
+ JMP callbackasm1(SB)
+ MOVL $1662, CX
+ JMP callbackasm1(SB)
+ MOVL $1663, CX
+ JMP callbackasm1(SB)
+ MOVL $1664, CX
+ JMP callbackasm1(SB)
+ MOVL $1665, CX
+ JMP callbackasm1(SB)
+ MOVL $1666, CX
+ JMP callbackasm1(SB)
+ MOVL $1667, CX
+ JMP callbackasm1(SB)
+ MOVL $1668, CX
+ JMP callbackasm1(SB)
+ MOVL $1669, CX
+ JMP callbackasm1(SB)
+ MOVL $1670, CX
+ JMP callbackasm1(SB)
+ MOVL $1671, CX
+ JMP callbackasm1(SB)
+ MOVL $1672, CX
+ JMP callbackasm1(SB)
+ MOVL $1673, CX
+ JMP callbackasm1(SB)
+ MOVL $1674, CX
+ JMP callbackasm1(SB)
+ MOVL $1675, CX
+ JMP callbackasm1(SB)
+ MOVL $1676, CX
+ JMP callbackasm1(SB)
+ MOVL $1677, CX
+ JMP callbackasm1(SB)
+ MOVL $1678, CX
+ JMP callbackasm1(SB)
+ MOVL $1679, CX
+ JMP callbackasm1(SB)
+ MOVL $1680, CX
+ JMP callbackasm1(SB)
+ MOVL $1681, CX
+ JMP callbackasm1(SB)
+ MOVL $1682, CX
+ JMP callbackasm1(SB)
+ MOVL $1683, CX
+ JMP callbackasm1(SB)
+ MOVL $1684, CX
+ JMP callbackasm1(SB)
+ MOVL $1685, CX
+ JMP callbackasm1(SB)
+ MOVL $1686, CX
+ JMP callbackasm1(SB)
+ MOVL $1687, CX
+ JMP callbackasm1(SB)
+ MOVL $1688, CX
+ JMP callbackasm1(SB)
+ MOVL $1689, CX
+ JMP callbackasm1(SB)
+ MOVL $1690, CX
+ JMP callbackasm1(SB)
+ MOVL $1691, CX
+ JMP callbackasm1(SB)
+ MOVL $1692, CX
+ JMP callbackasm1(SB)
+ MOVL $1693, CX
+ JMP callbackasm1(SB)
+ MOVL $1694, CX
+ JMP callbackasm1(SB)
+ MOVL $1695, CX
+ JMP callbackasm1(SB)
+ MOVL $1696, CX
+ JMP callbackasm1(SB)
+ MOVL $1697, CX
+ JMP callbackasm1(SB)
+ MOVL $1698, CX
+ JMP callbackasm1(SB)
+ MOVL $1699, CX
+ JMP callbackasm1(SB)
+ MOVL $1700, CX
+ JMP callbackasm1(SB)
+ MOVL $1701, CX
+ JMP callbackasm1(SB)
+ MOVL $1702, CX
+ JMP callbackasm1(SB)
+ MOVL $1703, CX
+ JMP callbackasm1(SB)
+ MOVL $1704, CX
+ JMP callbackasm1(SB)
+ MOVL $1705, CX
+ JMP callbackasm1(SB)
+ MOVL $1706, CX
+ JMP callbackasm1(SB)
+ MOVL $1707, CX
+ JMP callbackasm1(SB)
+ MOVL $1708, CX
+ JMP callbackasm1(SB)
+ MOVL $1709, CX
+ JMP callbackasm1(SB)
+ MOVL $1710, CX
+ JMP callbackasm1(SB)
+ MOVL $1711, CX
+ JMP callbackasm1(SB)
+ MOVL $1712, CX
+ JMP callbackasm1(SB)
+ MOVL $1713, CX
+ JMP callbackasm1(SB)
+ MOVL $1714, CX
+ JMP callbackasm1(SB)
+ MOVL $1715, CX
+ JMP callbackasm1(SB)
+ MOVL $1716, CX
+ JMP callbackasm1(SB)
+ MOVL $1717, CX
+ JMP callbackasm1(SB)
+ MOVL $1718, CX
+ JMP callbackasm1(SB)
+ MOVL $1719, CX
+ JMP callbackasm1(SB)
+ MOVL $1720, CX
+ JMP callbackasm1(SB)
+ MOVL $1721, CX
+ JMP callbackasm1(SB)
+ MOVL $1722, CX
+ JMP callbackasm1(SB)
+ MOVL $1723, CX
+ JMP callbackasm1(SB)
+ MOVL $1724, CX
+ JMP callbackasm1(SB)
+ MOVL $1725, CX
+ JMP callbackasm1(SB)
+ MOVL $1726, CX
+ JMP callbackasm1(SB)
+ MOVL $1727, CX
+ JMP callbackasm1(SB)
+ MOVL $1728, CX
+ JMP callbackasm1(SB)
+ MOVL $1729, CX
+ JMP callbackasm1(SB)
+ MOVL $1730, CX
+ JMP callbackasm1(SB)
+ MOVL $1731, CX
+ JMP callbackasm1(SB)
+ MOVL $1732, CX
+ JMP callbackasm1(SB)
+ MOVL $1733, CX
+ JMP callbackasm1(SB)
+ MOVL $1734, CX
+ JMP callbackasm1(SB)
+ MOVL $1735, CX
+ JMP callbackasm1(SB)
+ MOVL $1736, CX
+ JMP callbackasm1(SB)
+ MOVL $1737, CX
+ JMP callbackasm1(SB)
+ MOVL $1738, CX
+ JMP callbackasm1(SB)
+ MOVL $1739, CX
+ JMP callbackasm1(SB)
+ MOVL $1740, CX
+ JMP callbackasm1(SB)
+ MOVL $1741, CX
+ JMP callbackasm1(SB)
+ MOVL $1742, CX
+ JMP callbackasm1(SB)
+ MOVL $1743, CX
+ JMP callbackasm1(SB)
+ MOVL $1744, CX
+ JMP callbackasm1(SB)
+ MOVL $1745, CX
+ JMP callbackasm1(SB)
+ MOVL $1746, CX
+ JMP callbackasm1(SB)
+ MOVL $1747, CX
+ JMP callbackasm1(SB)
+ MOVL $1748, CX
+ JMP callbackasm1(SB)
+ MOVL $1749, CX
+ JMP callbackasm1(SB)
+ MOVL $1750, CX
+ JMP callbackasm1(SB)
+ MOVL $1751, CX
+ JMP callbackasm1(SB)
+ MOVL $1752, CX
+ JMP callbackasm1(SB)
+ MOVL $1753, CX
+ JMP callbackasm1(SB)
+ MOVL $1754, CX
+ JMP callbackasm1(SB)
+ MOVL $1755, CX
+ JMP callbackasm1(SB)
+ MOVL $1756, CX
+ JMP callbackasm1(SB)
+ MOVL $1757, CX
+ JMP callbackasm1(SB)
+ MOVL $1758, CX
+ JMP callbackasm1(SB)
+ MOVL $1759, CX
+ JMP callbackasm1(SB)
+ MOVL $1760, CX
+ JMP callbackasm1(SB)
+ MOVL $1761, CX
+ JMP callbackasm1(SB)
+ MOVL $1762, CX
+ JMP callbackasm1(SB)
+ MOVL $1763, CX
+ JMP callbackasm1(SB)
+ MOVL $1764, CX
+ JMP callbackasm1(SB)
+ MOVL $1765, CX
+ JMP callbackasm1(SB)
+ MOVL $1766, CX
+ JMP callbackasm1(SB)
+ MOVL $1767, CX
+ JMP callbackasm1(SB)
+ MOVL $1768, CX
+ JMP callbackasm1(SB)
+ MOVL $1769, CX
+ JMP callbackasm1(SB)
+ MOVL $1770, CX
+ JMP callbackasm1(SB)
+ MOVL $1771, CX
+ JMP callbackasm1(SB)
+ MOVL $1772, CX
+ JMP callbackasm1(SB)
+ MOVL $1773, CX
+ JMP callbackasm1(SB)
+ MOVL $1774, CX
+ JMP callbackasm1(SB)
+ MOVL $1775, CX
+ JMP callbackasm1(SB)
+ MOVL $1776, CX
+ JMP callbackasm1(SB)
+ MOVL $1777, CX
+ JMP callbackasm1(SB)
+ MOVL $1778, CX
+ JMP callbackasm1(SB)
+ MOVL $1779, CX
+ JMP callbackasm1(SB)
+ MOVL $1780, CX
+ JMP callbackasm1(SB)
+ MOVL $1781, CX
+ JMP callbackasm1(SB)
+ MOVL $1782, CX
+ JMP callbackasm1(SB)
+ MOVL $1783, CX
+ JMP callbackasm1(SB)
+ MOVL $1784, CX
+ JMP callbackasm1(SB)
+ MOVL $1785, CX
+ JMP callbackasm1(SB)
+ MOVL $1786, CX
+ JMP callbackasm1(SB)
+ MOVL $1787, CX
+ JMP callbackasm1(SB)
+ MOVL $1788, CX
+ JMP callbackasm1(SB)
+ MOVL $1789, CX
+ JMP callbackasm1(SB)
+ MOVL $1790, CX
+ JMP callbackasm1(SB)
+ MOVL $1791, CX
+ JMP callbackasm1(SB)
+ MOVL $1792, CX
+ JMP callbackasm1(SB)
+ MOVL $1793, CX
+ JMP callbackasm1(SB)
+ MOVL $1794, CX
+ JMP callbackasm1(SB)
+ MOVL $1795, CX
+ JMP callbackasm1(SB)
+ MOVL $1796, CX
+ JMP callbackasm1(SB)
+ MOVL $1797, CX
+ JMP callbackasm1(SB)
+ MOVL $1798, CX
+ JMP callbackasm1(SB)
+ MOVL $1799, CX
+ JMP callbackasm1(SB)
+ MOVL $1800, CX
+ JMP callbackasm1(SB)
+ MOVL $1801, CX
+ JMP callbackasm1(SB)
+ MOVL $1802, CX
+ JMP callbackasm1(SB)
+ MOVL $1803, CX
+ JMP callbackasm1(SB)
+ MOVL $1804, CX
+ JMP callbackasm1(SB)
+ MOVL $1805, CX
+ JMP callbackasm1(SB)
+ MOVL $1806, CX
+ JMP callbackasm1(SB)
+ MOVL $1807, CX
+ JMP callbackasm1(SB)
+ MOVL $1808, CX
+ JMP callbackasm1(SB)
+ MOVL $1809, CX
+ JMP callbackasm1(SB)
+ MOVL $1810, CX
+ JMP callbackasm1(SB)
+ MOVL $1811, CX
+ JMP callbackasm1(SB)
+ MOVL $1812, CX
+ JMP callbackasm1(SB)
+ MOVL $1813, CX
+ JMP callbackasm1(SB)
+ MOVL $1814, CX
+ JMP callbackasm1(SB)
+ MOVL $1815, CX
+ JMP callbackasm1(SB)
+ MOVL $1816, CX
+ JMP callbackasm1(SB)
+ MOVL $1817, CX
+ JMP callbackasm1(SB)
+ MOVL $1818, CX
+ JMP callbackasm1(SB)
+ MOVL $1819, CX
+ JMP callbackasm1(SB)
+ MOVL $1820, CX
+ JMP callbackasm1(SB)
+ MOVL $1821, CX
+ JMP callbackasm1(SB)
+ MOVL $1822, CX
+ JMP callbackasm1(SB)
+ MOVL $1823, CX
+ JMP callbackasm1(SB)
+ MOVL $1824, CX
+ JMP callbackasm1(SB)
+ MOVL $1825, CX
+ JMP callbackasm1(SB)
+ MOVL $1826, CX
+ JMP callbackasm1(SB)
+ MOVL $1827, CX
+ JMP callbackasm1(SB)
+ MOVL $1828, CX
+ JMP callbackasm1(SB)
+ MOVL $1829, CX
+ JMP callbackasm1(SB)
+ MOVL $1830, CX
+ JMP callbackasm1(SB)
+ MOVL $1831, CX
+ JMP callbackasm1(SB)
+ MOVL $1832, CX
+ JMP callbackasm1(SB)
+ MOVL $1833, CX
+ JMP callbackasm1(SB)
+ MOVL $1834, CX
+ JMP callbackasm1(SB)
+ MOVL $1835, CX
+ JMP callbackasm1(SB)
+ MOVL $1836, CX
+ JMP callbackasm1(SB)
+ MOVL $1837, CX
+ JMP callbackasm1(SB)
+ MOVL $1838, CX
+ JMP callbackasm1(SB)
+ MOVL $1839, CX
+ JMP callbackasm1(SB)
+ MOVL $1840, CX
+ JMP callbackasm1(SB)
+ MOVL $1841, CX
+ JMP callbackasm1(SB)
+ MOVL $1842, CX
+ JMP callbackasm1(SB)
+ MOVL $1843, CX
+ JMP callbackasm1(SB)
+ MOVL $1844, CX
+ JMP callbackasm1(SB)
+ MOVL $1845, CX
+ JMP callbackasm1(SB)
+ MOVL $1846, CX
+ JMP callbackasm1(SB)
+ MOVL $1847, CX
+ JMP callbackasm1(SB)
+ MOVL $1848, CX
+ JMP callbackasm1(SB)
+ MOVL $1849, CX
+ JMP callbackasm1(SB)
+ MOVL $1850, CX
+ JMP callbackasm1(SB)
+ MOVL $1851, CX
+ JMP callbackasm1(SB)
+ MOVL $1852, CX
+ JMP callbackasm1(SB)
+ MOVL $1853, CX
+ JMP callbackasm1(SB)
+ MOVL $1854, CX
+ JMP callbackasm1(SB)
+ MOVL $1855, CX
+ JMP callbackasm1(SB)
+ MOVL $1856, CX
+ JMP callbackasm1(SB)
+ MOVL $1857, CX
+ JMP callbackasm1(SB)
+ MOVL $1858, CX
+ JMP callbackasm1(SB)
+ MOVL $1859, CX
+ JMP callbackasm1(SB)
+ MOVL $1860, CX
+ JMP callbackasm1(SB)
+ MOVL $1861, CX
+ JMP callbackasm1(SB)
+ MOVL $1862, CX
+ JMP callbackasm1(SB)
+ MOVL $1863, CX
+ JMP callbackasm1(SB)
+ MOVL $1864, CX
+ JMP callbackasm1(SB)
+ MOVL $1865, CX
+ JMP callbackasm1(SB)
+ MOVL $1866, CX
+ JMP callbackasm1(SB)
+ MOVL $1867, CX
+ JMP callbackasm1(SB)
+ MOVL $1868, CX
+ JMP callbackasm1(SB)
+ MOVL $1869, CX
+ JMP callbackasm1(SB)
+ MOVL $1870, CX
+ JMP callbackasm1(SB)
+ MOVL $1871, CX
+ JMP callbackasm1(SB)
+ MOVL $1872, CX
+ JMP callbackasm1(SB)
+ MOVL $1873, CX
+ JMP callbackasm1(SB)
+ MOVL $1874, CX
+ JMP callbackasm1(SB)
+ MOVL $1875, CX
+ JMP callbackasm1(SB)
+ MOVL $1876, CX
+ JMP callbackasm1(SB)
+ MOVL $1877, CX
+ JMP callbackasm1(SB)
+ MOVL $1878, CX
+ JMP callbackasm1(SB)
+ MOVL $1879, CX
+ JMP callbackasm1(SB)
+ MOVL $1880, CX
+ JMP callbackasm1(SB)
+ MOVL $1881, CX
+ JMP callbackasm1(SB)
+ MOVL $1882, CX
+ JMP callbackasm1(SB)
+ MOVL $1883, CX
+ JMP callbackasm1(SB)
+ MOVL $1884, CX
+ JMP callbackasm1(SB)
+ MOVL $1885, CX
+ JMP callbackasm1(SB)
+ MOVL $1886, CX
+ JMP callbackasm1(SB)
+ MOVL $1887, CX
+ JMP callbackasm1(SB)
+ MOVL $1888, CX
+ JMP callbackasm1(SB)
+ MOVL $1889, CX
+ JMP callbackasm1(SB)
+ MOVL $1890, CX
+ JMP callbackasm1(SB)
+ MOVL $1891, CX
+ JMP callbackasm1(SB)
+ MOVL $1892, CX
+ JMP callbackasm1(SB)
+ MOVL $1893, CX
+ JMP callbackasm1(SB)
+ MOVL $1894, CX
+ JMP callbackasm1(SB)
+ MOVL $1895, CX
+ JMP callbackasm1(SB)
+ MOVL $1896, CX
+ JMP callbackasm1(SB)
+ MOVL $1897, CX
+ JMP callbackasm1(SB)
+ MOVL $1898, CX
+ JMP callbackasm1(SB)
+ MOVL $1899, CX
+ JMP callbackasm1(SB)
+ MOVL $1900, CX
+ JMP callbackasm1(SB)
+ MOVL $1901, CX
+ JMP callbackasm1(SB)
+ MOVL $1902, CX
+ JMP callbackasm1(SB)
+ MOVL $1903, CX
+ JMP callbackasm1(SB)
+ MOVL $1904, CX
+ JMP callbackasm1(SB)
+ MOVL $1905, CX
+ JMP callbackasm1(SB)
+ MOVL $1906, CX
+ JMP callbackasm1(SB)
+ MOVL $1907, CX
+ JMP callbackasm1(SB)
+ MOVL $1908, CX
+ JMP callbackasm1(SB)
+ MOVL $1909, CX
+ JMP callbackasm1(SB)
+ MOVL $1910, CX
+ JMP callbackasm1(SB)
+ MOVL $1911, CX
+ JMP callbackasm1(SB)
+ MOVL $1912, CX
+ JMP callbackasm1(SB)
+ MOVL $1913, CX
+ JMP callbackasm1(SB)
+ MOVL $1914, CX
+ JMP callbackasm1(SB)
+ MOVL $1915, CX
+ JMP callbackasm1(SB)
+ MOVL $1916, CX
+ JMP callbackasm1(SB)
+ MOVL $1917, CX
+ JMP callbackasm1(SB)
+ MOVL $1918, CX
+ JMP callbackasm1(SB)
+ MOVL $1919, CX
+ JMP callbackasm1(SB)
+ MOVL $1920, CX
+ JMP callbackasm1(SB)
+ MOVL $1921, CX
+ JMP callbackasm1(SB)
+ MOVL $1922, CX
+ JMP callbackasm1(SB)
+ MOVL $1923, CX
+ JMP callbackasm1(SB)
+ MOVL $1924, CX
+ JMP callbackasm1(SB)
+ MOVL $1925, CX
+ JMP callbackasm1(SB)
+ MOVL $1926, CX
+ JMP callbackasm1(SB)
+ MOVL $1927, CX
+ JMP callbackasm1(SB)
+ MOVL $1928, CX
+ JMP callbackasm1(SB)
+ MOVL $1929, CX
+ JMP callbackasm1(SB)
+ MOVL $1930, CX
+ JMP callbackasm1(SB)
+ MOVL $1931, CX
+ JMP callbackasm1(SB)
+ MOVL $1932, CX
+ JMP callbackasm1(SB)
+ MOVL $1933, CX
+ JMP callbackasm1(SB)
+ MOVL $1934, CX
+ JMP callbackasm1(SB)
+ MOVL $1935, CX
+ JMP callbackasm1(SB)
+ MOVL $1936, CX
+ JMP callbackasm1(SB)
+ MOVL $1937, CX
+ JMP callbackasm1(SB)
+ MOVL $1938, CX
+ JMP callbackasm1(SB)
+ MOVL $1939, CX
+ JMP callbackasm1(SB)
+ MOVL $1940, CX
+ JMP callbackasm1(SB)
+ MOVL $1941, CX
+ JMP callbackasm1(SB)
+ MOVL $1942, CX
+ JMP callbackasm1(SB)
+ MOVL $1943, CX
+ JMP callbackasm1(SB)
+ MOVL $1944, CX
+ JMP callbackasm1(SB)
+ MOVL $1945, CX
+ JMP callbackasm1(SB)
+ MOVL $1946, CX
+ JMP callbackasm1(SB)
+ MOVL $1947, CX
+ JMP callbackasm1(SB)
+ MOVL $1948, CX
+ JMP callbackasm1(SB)
+ MOVL $1949, CX
+ JMP callbackasm1(SB)
+ MOVL $1950, CX
+ JMP callbackasm1(SB)
+ MOVL $1951, CX
+ JMP callbackasm1(SB)
+ MOVL $1952, CX
+ JMP callbackasm1(SB)
+ MOVL $1953, CX
+ JMP callbackasm1(SB)
+ MOVL $1954, CX
+ JMP callbackasm1(SB)
+ MOVL $1955, CX
+ JMP callbackasm1(SB)
+ MOVL $1956, CX
+ JMP callbackasm1(SB)
+ MOVL $1957, CX
+ JMP callbackasm1(SB)
+ MOVL $1958, CX
+ JMP callbackasm1(SB)
+ MOVL $1959, CX
+ JMP callbackasm1(SB)
+ MOVL $1960, CX
+ JMP callbackasm1(SB)
+ MOVL $1961, CX
+ JMP callbackasm1(SB)
+ MOVL $1962, CX
+ JMP callbackasm1(SB)
+ MOVL $1963, CX
+ JMP callbackasm1(SB)
+ MOVL $1964, CX
+ JMP callbackasm1(SB)
+ MOVL $1965, CX
+ JMP callbackasm1(SB)
+ MOVL $1966, CX
+ JMP callbackasm1(SB)
+ MOVL $1967, CX
+ JMP callbackasm1(SB)
+ MOVL $1968, CX
+ JMP callbackasm1(SB)
+ MOVL $1969, CX
+ JMP callbackasm1(SB)
+ MOVL $1970, CX
+ JMP callbackasm1(SB)
+ MOVL $1971, CX
+ JMP callbackasm1(SB)
+ MOVL $1972, CX
+ JMP callbackasm1(SB)
+ MOVL $1973, CX
+ JMP callbackasm1(SB)
+ MOVL $1974, CX
+ JMP callbackasm1(SB)
+ MOVL $1975, CX
+ JMP callbackasm1(SB)
+ MOVL $1976, CX
+ JMP callbackasm1(SB)
+ MOVL $1977, CX
+ JMP callbackasm1(SB)
+ MOVL $1978, CX
+ JMP callbackasm1(SB)
+ MOVL $1979, CX
+ JMP callbackasm1(SB)
+ MOVL $1980, CX
+ JMP callbackasm1(SB)
+ MOVL $1981, CX
+ JMP callbackasm1(SB)
+ MOVL $1982, CX
+ JMP callbackasm1(SB)
+ MOVL $1983, CX
+ JMP callbackasm1(SB)
+ MOVL $1984, CX
+ JMP callbackasm1(SB)
+ MOVL $1985, CX
+ JMP callbackasm1(SB)
+ MOVL $1986, CX
+ JMP callbackasm1(SB)
+ MOVL $1987, CX
+ JMP callbackasm1(SB)
+ MOVL $1988, CX
+ JMP callbackasm1(SB)
+ MOVL $1989, CX
+ JMP callbackasm1(SB)
+ MOVL $1990, CX
+ JMP callbackasm1(SB)
+ MOVL $1991, CX
+ JMP callbackasm1(SB)
+ MOVL $1992, CX
+ JMP callbackasm1(SB)
+ MOVL $1993, CX
+ JMP callbackasm1(SB)
+ MOVL $1994, CX
+ JMP callbackasm1(SB)
+ MOVL $1995, CX
+ JMP callbackasm1(SB)
+ MOVL $1996, CX
+ JMP callbackasm1(SB)
+ MOVL $1997, CX
+ JMP callbackasm1(SB)
+ MOVL $1998, CX
+ JMP callbackasm1(SB)
+ MOVL $1999, CX
+ JMP callbackasm1(SB)
diff --git a/raymenu/vendor/github.com/ebitengine/purego/zcallback_amd64.s b/raymenu/vendor/github.com/ebitengine/purego/zcallback_amd64.s
new file mode 100644
index 0000000..b2da022
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/zcallback_amd64.s
@@ -0,0 +1,2014 @@
+// Code generated by wincallback.go using 'go generate'. DO NOT EDIT.
+
+//go:build darwin || freebsd || linux || netbsd
+
+// runtime·callbackasm is called by external code to
+// execute Go implemented callback function. It is not
+// called from the start, instead runtime·compilecallback
+// always returns address into runtime·callbackasm offset
+// appropriately so different callbacks start with different
+// CALL instruction in runtime·callbackasm. This determines
+// which Go callback function is executed later on.
+#include "textflag.h"
+
+TEXT callbackasm(SB), NOSPLIT|NOFRAME, $0
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
+ CALL callbackasm1(SB)
diff --git a/raymenu/vendor/github.com/ebitengine/purego/zcallback_arm.s b/raymenu/vendor/github.com/ebitengine/purego/zcallback_arm.s
new file mode 100644
index 0000000..d969d81
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/zcallback_arm.s
@@ -0,0 +1,4014 @@
+// Code generated by wincallback.go using 'go generate'. DO NOT EDIT.
+
+//go:build linux
+
+// External code calls into callbackasm at an offset corresponding
+// to the callback index. Callbackasm is a table of MOVW and B instructions.
+// The MOVW instruction loads R12 with the callback index, and the
+// B instruction branches to callbackasm1.
+// callbackasm1 takes the callback index from R12 and
+// indexes into an array that stores information about each callback.
+// It then calls the Go implementation for that callback.
+#include "textflag.h"
+
+TEXT callbackasm(SB), NOSPLIT|NOFRAME, $0
+ MOVW $0, R12
+ B callbackasm1(SB)
+ MOVW $1, R12
+ B callbackasm1(SB)
+ MOVW $2, R12
+ B callbackasm1(SB)
+ MOVW $3, R12
+ B callbackasm1(SB)
+ MOVW $4, R12
+ B callbackasm1(SB)
+ MOVW $5, R12
+ B callbackasm1(SB)
+ MOVW $6, R12
+ B callbackasm1(SB)
+ MOVW $7, R12
+ B callbackasm1(SB)
+ MOVW $8, R12
+ B callbackasm1(SB)
+ MOVW $9, R12
+ B callbackasm1(SB)
+ MOVW $10, R12
+ B callbackasm1(SB)
+ MOVW $11, R12
+ B callbackasm1(SB)
+ MOVW $12, R12
+ B callbackasm1(SB)
+ MOVW $13, R12
+ B callbackasm1(SB)
+ MOVW $14, R12
+ B callbackasm1(SB)
+ MOVW $15, R12
+ B callbackasm1(SB)
+ MOVW $16, R12
+ B callbackasm1(SB)
+ MOVW $17, R12
+ B callbackasm1(SB)
+ MOVW $18, R12
+ B callbackasm1(SB)
+ MOVW $19, R12
+ B callbackasm1(SB)
+ MOVW $20, R12
+ B callbackasm1(SB)
+ MOVW $21, R12
+ B callbackasm1(SB)
+ MOVW $22, R12
+ B callbackasm1(SB)
+ MOVW $23, R12
+ B callbackasm1(SB)
+ MOVW $24, R12
+ B callbackasm1(SB)
+ MOVW $25, R12
+ B callbackasm1(SB)
+ MOVW $26, R12
+ B callbackasm1(SB)
+ MOVW $27, R12
+ B callbackasm1(SB)
+ MOVW $28, R12
+ B callbackasm1(SB)
+ MOVW $29, R12
+ B callbackasm1(SB)
+ MOVW $30, R12
+ B callbackasm1(SB)
+ MOVW $31, R12
+ B callbackasm1(SB)
+ MOVW $32, R12
+ B callbackasm1(SB)
+ MOVW $33, R12
+ B callbackasm1(SB)
+ MOVW $34, R12
+ B callbackasm1(SB)
+ MOVW $35, R12
+ B callbackasm1(SB)
+ MOVW $36, R12
+ B callbackasm1(SB)
+ MOVW $37, R12
+ B callbackasm1(SB)
+ MOVW $38, R12
+ B callbackasm1(SB)
+ MOVW $39, R12
+ B callbackasm1(SB)
+ MOVW $40, R12
+ B callbackasm1(SB)
+ MOVW $41, R12
+ B callbackasm1(SB)
+ MOVW $42, R12
+ B callbackasm1(SB)
+ MOVW $43, R12
+ B callbackasm1(SB)
+ MOVW $44, R12
+ B callbackasm1(SB)
+ MOVW $45, R12
+ B callbackasm1(SB)
+ MOVW $46, R12
+ B callbackasm1(SB)
+ MOVW $47, R12
+ B callbackasm1(SB)
+ MOVW $48, R12
+ B callbackasm1(SB)
+ MOVW $49, R12
+ B callbackasm1(SB)
+ MOVW $50, R12
+ B callbackasm1(SB)
+ MOVW $51, R12
+ B callbackasm1(SB)
+ MOVW $52, R12
+ B callbackasm1(SB)
+ MOVW $53, R12
+ B callbackasm1(SB)
+ MOVW $54, R12
+ B callbackasm1(SB)
+ MOVW $55, R12
+ B callbackasm1(SB)
+ MOVW $56, R12
+ B callbackasm1(SB)
+ MOVW $57, R12
+ B callbackasm1(SB)
+ MOVW $58, R12
+ B callbackasm1(SB)
+ MOVW $59, R12
+ B callbackasm1(SB)
+ MOVW $60, R12
+ B callbackasm1(SB)
+ MOVW $61, R12
+ B callbackasm1(SB)
+ MOVW $62, R12
+ B callbackasm1(SB)
+ MOVW $63, R12
+ B callbackasm1(SB)
+ MOVW $64, R12
+ B callbackasm1(SB)
+ MOVW $65, R12
+ B callbackasm1(SB)
+ MOVW $66, R12
+ B callbackasm1(SB)
+ MOVW $67, R12
+ B callbackasm1(SB)
+ MOVW $68, R12
+ B callbackasm1(SB)
+ MOVW $69, R12
+ B callbackasm1(SB)
+ MOVW $70, R12
+ B callbackasm1(SB)
+ MOVW $71, R12
+ B callbackasm1(SB)
+ MOVW $72, R12
+ B callbackasm1(SB)
+ MOVW $73, R12
+ B callbackasm1(SB)
+ MOVW $74, R12
+ B callbackasm1(SB)
+ MOVW $75, R12
+ B callbackasm1(SB)
+ MOVW $76, R12
+ B callbackasm1(SB)
+ MOVW $77, R12
+ B callbackasm1(SB)
+ MOVW $78, R12
+ B callbackasm1(SB)
+ MOVW $79, R12
+ B callbackasm1(SB)
+ MOVW $80, R12
+ B callbackasm1(SB)
+ MOVW $81, R12
+ B callbackasm1(SB)
+ MOVW $82, R12
+ B callbackasm1(SB)
+ MOVW $83, R12
+ B callbackasm1(SB)
+ MOVW $84, R12
+ B callbackasm1(SB)
+ MOVW $85, R12
+ B callbackasm1(SB)
+ MOVW $86, R12
+ B callbackasm1(SB)
+ MOVW $87, R12
+ B callbackasm1(SB)
+ MOVW $88, R12
+ B callbackasm1(SB)
+ MOVW $89, R12
+ B callbackasm1(SB)
+ MOVW $90, R12
+ B callbackasm1(SB)
+ MOVW $91, R12
+ B callbackasm1(SB)
+ MOVW $92, R12
+ B callbackasm1(SB)
+ MOVW $93, R12
+ B callbackasm1(SB)
+ MOVW $94, R12
+ B callbackasm1(SB)
+ MOVW $95, R12
+ B callbackasm1(SB)
+ MOVW $96, R12
+ B callbackasm1(SB)
+ MOVW $97, R12
+ B callbackasm1(SB)
+ MOVW $98, R12
+ B callbackasm1(SB)
+ MOVW $99, R12
+ B callbackasm1(SB)
+ MOVW $100, R12
+ B callbackasm1(SB)
+ MOVW $101, R12
+ B callbackasm1(SB)
+ MOVW $102, R12
+ B callbackasm1(SB)
+ MOVW $103, R12
+ B callbackasm1(SB)
+ MOVW $104, R12
+ B callbackasm1(SB)
+ MOVW $105, R12
+ B callbackasm1(SB)
+ MOVW $106, R12
+ B callbackasm1(SB)
+ MOVW $107, R12
+ B callbackasm1(SB)
+ MOVW $108, R12
+ B callbackasm1(SB)
+ MOVW $109, R12
+ B callbackasm1(SB)
+ MOVW $110, R12
+ B callbackasm1(SB)
+ MOVW $111, R12
+ B callbackasm1(SB)
+ MOVW $112, R12
+ B callbackasm1(SB)
+ MOVW $113, R12
+ B callbackasm1(SB)
+ MOVW $114, R12
+ B callbackasm1(SB)
+ MOVW $115, R12
+ B callbackasm1(SB)
+ MOVW $116, R12
+ B callbackasm1(SB)
+ MOVW $117, R12
+ B callbackasm1(SB)
+ MOVW $118, R12
+ B callbackasm1(SB)
+ MOVW $119, R12
+ B callbackasm1(SB)
+ MOVW $120, R12
+ B callbackasm1(SB)
+ MOVW $121, R12
+ B callbackasm1(SB)
+ MOVW $122, R12
+ B callbackasm1(SB)
+ MOVW $123, R12
+ B callbackasm1(SB)
+ MOVW $124, R12
+ B callbackasm1(SB)
+ MOVW $125, R12
+ B callbackasm1(SB)
+ MOVW $126, R12
+ B callbackasm1(SB)
+ MOVW $127, R12
+ B callbackasm1(SB)
+ MOVW $128, R12
+ B callbackasm1(SB)
+ MOVW $129, R12
+ B callbackasm1(SB)
+ MOVW $130, R12
+ B callbackasm1(SB)
+ MOVW $131, R12
+ B callbackasm1(SB)
+ MOVW $132, R12
+ B callbackasm1(SB)
+ MOVW $133, R12
+ B callbackasm1(SB)
+ MOVW $134, R12
+ B callbackasm1(SB)
+ MOVW $135, R12
+ B callbackasm1(SB)
+ MOVW $136, R12
+ B callbackasm1(SB)
+ MOVW $137, R12
+ B callbackasm1(SB)
+ MOVW $138, R12
+ B callbackasm1(SB)
+ MOVW $139, R12
+ B callbackasm1(SB)
+ MOVW $140, R12
+ B callbackasm1(SB)
+ MOVW $141, R12
+ B callbackasm1(SB)
+ MOVW $142, R12
+ B callbackasm1(SB)
+ MOVW $143, R12
+ B callbackasm1(SB)
+ MOVW $144, R12
+ B callbackasm1(SB)
+ MOVW $145, R12
+ B callbackasm1(SB)
+ MOVW $146, R12
+ B callbackasm1(SB)
+ MOVW $147, R12
+ B callbackasm1(SB)
+ MOVW $148, R12
+ B callbackasm1(SB)
+ MOVW $149, R12
+ B callbackasm1(SB)
+ MOVW $150, R12
+ B callbackasm1(SB)
+ MOVW $151, R12
+ B callbackasm1(SB)
+ MOVW $152, R12
+ B callbackasm1(SB)
+ MOVW $153, R12
+ B callbackasm1(SB)
+ MOVW $154, R12
+ B callbackasm1(SB)
+ MOVW $155, R12
+ B callbackasm1(SB)
+ MOVW $156, R12
+ B callbackasm1(SB)
+ MOVW $157, R12
+ B callbackasm1(SB)
+ MOVW $158, R12
+ B callbackasm1(SB)
+ MOVW $159, R12
+ B callbackasm1(SB)
+ MOVW $160, R12
+ B callbackasm1(SB)
+ MOVW $161, R12
+ B callbackasm1(SB)
+ MOVW $162, R12
+ B callbackasm1(SB)
+ MOVW $163, R12
+ B callbackasm1(SB)
+ MOVW $164, R12
+ B callbackasm1(SB)
+ MOVW $165, R12
+ B callbackasm1(SB)
+ MOVW $166, R12
+ B callbackasm1(SB)
+ MOVW $167, R12
+ B callbackasm1(SB)
+ MOVW $168, R12
+ B callbackasm1(SB)
+ MOVW $169, R12
+ B callbackasm1(SB)
+ MOVW $170, R12
+ B callbackasm1(SB)
+ MOVW $171, R12
+ B callbackasm1(SB)
+ MOVW $172, R12
+ B callbackasm1(SB)
+ MOVW $173, R12
+ B callbackasm1(SB)
+ MOVW $174, R12
+ B callbackasm1(SB)
+ MOVW $175, R12
+ B callbackasm1(SB)
+ MOVW $176, R12
+ B callbackasm1(SB)
+ MOVW $177, R12
+ B callbackasm1(SB)
+ MOVW $178, R12
+ B callbackasm1(SB)
+ MOVW $179, R12
+ B callbackasm1(SB)
+ MOVW $180, R12
+ B callbackasm1(SB)
+ MOVW $181, R12
+ B callbackasm1(SB)
+ MOVW $182, R12
+ B callbackasm1(SB)
+ MOVW $183, R12
+ B callbackasm1(SB)
+ MOVW $184, R12
+ B callbackasm1(SB)
+ MOVW $185, R12
+ B callbackasm1(SB)
+ MOVW $186, R12
+ B callbackasm1(SB)
+ MOVW $187, R12
+ B callbackasm1(SB)
+ MOVW $188, R12
+ B callbackasm1(SB)
+ MOVW $189, R12
+ B callbackasm1(SB)
+ MOVW $190, R12
+ B callbackasm1(SB)
+ MOVW $191, R12
+ B callbackasm1(SB)
+ MOVW $192, R12
+ B callbackasm1(SB)
+ MOVW $193, R12
+ B callbackasm1(SB)
+ MOVW $194, R12
+ B callbackasm1(SB)
+ MOVW $195, R12
+ B callbackasm1(SB)
+ MOVW $196, R12
+ B callbackasm1(SB)
+ MOVW $197, R12
+ B callbackasm1(SB)
+ MOVW $198, R12
+ B callbackasm1(SB)
+ MOVW $199, R12
+ B callbackasm1(SB)
+ MOVW $200, R12
+ B callbackasm1(SB)
+ MOVW $201, R12
+ B callbackasm1(SB)
+ MOVW $202, R12
+ B callbackasm1(SB)
+ MOVW $203, R12
+ B callbackasm1(SB)
+ MOVW $204, R12
+ B callbackasm1(SB)
+ MOVW $205, R12
+ B callbackasm1(SB)
+ MOVW $206, R12
+ B callbackasm1(SB)
+ MOVW $207, R12
+ B callbackasm1(SB)
+ MOVW $208, R12
+ B callbackasm1(SB)
+ MOVW $209, R12
+ B callbackasm1(SB)
+ MOVW $210, R12
+ B callbackasm1(SB)
+ MOVW $211, R12
+ B callbackasm1(SB)
+ MOVW $212, R12
+ B callbackasm1(SB)
+ MOVW $213, R12
+ B callbackasm1(SB)
+ MOVW $214, R12
+ B callbackasm1(SB)
+ MOVW $215, R12
+ B callbackasm1(SB)
+ MOVW $216, R12
+ B callbackasm1(SB)
+ MOVW $217, R12
+ B callbackasm1(SB)
+ MOVW $218, R12
+ B callbackasm1(SB)
+ MOVW $219, R12
+ B callbackasm1(SB)
+ MOVW $220, R12
+ B callbackasm1(SB)
+ MOVW $221, R12
+ B callbackasm1(SB)
+ MOVW $222, R12
+ B callbackasm1(SB)
+ MOVW $223, R12
+ B callbackasm1(SB)
+ MOVW $224, R12
+ B callbackasm1(SB)
+ MOVW $225, R12
+ B callbackasm1(SB)
+ MOVW $226, R12
+ B callbackasm1(SB)
+ MOVW $227, R12
+ B callbackasm1(SB)
+ MOVW $228, R12
+ B callbackasm1(SB)
+ MOVW $229, R12
+ B callbackasm1(SB)
+ MOVW $230, R12
+ B callbackasm1(SB)
+ MOVW $231, R12
+ B callbackasm1(SB)
+ MOVW $232, R12
+ B callbackasm1(SB)
+ MOVW $233, R12
+ B callbackasm1(SB)
+ MOVW $234, R12
+ B callbackasm1(SB)
+ MOVW $235, R12
+ B callbackasm1(SB)
+ MOVW $236, R12
+ B callbackasm1(SB)
+ MOVW $237, R12
+ B callbackasm1(SB)
+ MOVW $238, R12
+ B callbackasm1(SB)
+ MOVW $239, R12
+ B callbackasm1(SB)
+ MOVW $240, R12
+ B callbackasm1(SB)
+ MOVW $241, R12
+ B callbackasm1(SB)
+ MOVW $242, R12
+ B callbackasm1(SB)
+ MOVW $243, R12
+ B callbackasm1(SB)
+ MOVW $244, R12
+ B callbackasm1(SB)
+ MOVW $245, R12
+ B callbackasm1(SB)
+ MOVW $246, R12
+ B callbackasm1(SB)
+ MOVW $247, R12
+ B callbackasm1(SB)
+ MOVW $248, R12
+ B callbackasm1(SB)
+ MOVW $249, R12
+ B callbackasm1(SB)
+ MOVW $250, R12
+ B callbackasm1(SB)
+ MOVW $251, R12
+ B callbackasm1(SB)
+ MOVW $252, R12
+ B callbackasm1(SB)
+ MOVW $253, R12
+ B callbackasm1(SB)
+ MOVW $254, R12
+ B callbackasm1(SB)
+ MOVW $255, R12
+ B callbackasm1(SB)
+ MOVW $256, R12
+ B callbackasm1(SB)
+ MOVW $257, R12
+ B callbackasm1(SB)
+ MOVW $258, R12
+ B callbackasm1(SB)
+ MOVW $259, R12
+ B callbackasm1(SB)
+ MOVW $260, R12
+ B callbackasm1(SB)
+ MOVW $261, R12
+ B callbackasm1(SB)
+ MOVW $262, R12
+ B callbackasm1(SB)
+ MOVW $263, R12
+ B callbackasm1(SB)
+ MOVW $264, R12
+ B callbackasm1(SB)
+ MOVW $265, R12
+ B callbackasm1(SB)
+ MOVW $266, R12
+ B callbackasm1(SB)
+ MOVW $267, R12
+ B callbackasm1(SB)
+ MOVW $268, R12
+ B callbackasm1(SB)
+ MOVW $269, R12
+ B callbackasm1(SB)
+ MOVW $270, R12
+ B callbackasm1(SB)
+ MOVW $271, R12
+ B callbackasm1(SB)
+ MOVW $272, R12
+ B callbackasm1(SB)
+ MOVW $273, R12
+ B callbackasm1(SB)
+ MOVW $274, R12
+ B callbackasm1(SB)
+ MOVW $275, R12
+ B callbackasm1(SB)
+ MOVW $276, R12
+ B callbackasm1(SB)
+ MOVW $277, R12
+ B callbackasm1(SB)
+ MOVW $278, R12
+ B callbackasm1(SB)
+ MOVW $279, R12
+ B callbackasm1(SB)
+ MOVW $280, R12
+ B callbackasm1(SB)
+ MOVW $281, R12
+ B callbackasm1(SB)
+ MOVW $282, R12
+ B callbackasm1(SB)
+ MOVW $283, R12
+ B callbackasm1(SB)
+ MOVW $284, R12
+ B callbackasm1(SB)
+ MOVW $285, R12
+ B callbackasm1(SB)
+ MOVW $286, R12
+ B callbackasm1(SB)
+ MOVW $287, R12
+ B callbackasm1(SB)
+ MOVW $288, R12
+ B callbackasm1(SB)
+ MOVW $289, R12
+ B callbackasm1(SB)
+ MOVW $290, R12
+ B callbackasm1(SB)
+ MOVW $291, R12
+ B callbackasm1(SB)
+ MOVW $292, R12
+ B callbackasm1(SB)
+ MOVW $293, R12
+ B callbackasm1(SB)
+ MOVW $294, R12
+ B callbackasm1(SB)
+ MOVW $295, R12
+ B callbackasm1(SB)
+ MOVW $296, R12
+ B callbackasm1(SB)
+ MOVW $297, R12
+ B callbackasm1(SB)
+ MOVW $298, R12
+ B callbackasm1(SB)
+ MOVW $299, R12
+ B callbackasm1(SB)
+ MOVW $300, R12
+ B callbackasm1(SB)
+ MOVW $301, R12
+ B callbackasm1(SB)
+ MOVW $302, R12
+ B callbackasm1(SB)
+ MOVW $303, R12
+ B callbackasm1(SB)
+ MOVW $304, R12
+ B callbackasm1(SB)
+ MOVW $305, R12
+ B callbackasm1(SB)
+ MOVW $306, R12
+ B callbackasm1(SB)
+ MOVW $307, R12
+ B callbackasm1(SB)
+ MOVW $308, R12
+ B callbackasm1(SB)
+ MOVW $309, R12
+ B callbackasm1(SB)
+ MOVW $310, R12
+ B callbackasm1(SB)
+ MOVW $311, R12
+ B callbackasm1(SB)
+ MOVW $312, R12
+ B callbackasm1(SB)
+ MOVW $313, R12
+ B callbackasm1(SB)
+ MOVW $314, R12
+ B callbackasm1(SB)
+ MOVW $315, R12
+ B callbackasm1(SB)
+ MOVW $316, R12
+ B callbackasm1(SB)
+ MOVW $317, R12
+ B callbackasm1(SB)
+ MOVW $318, R12
+ B callbackasm1(SB)
+ MOVW $319, R12
+ B callbackasm1(SB)
+ MOVW $320, R12
+ B callbackasm1(SB)
+ MOVW $321, R12
+ B callbackasm1(SB)
+ MOVW $322, R12
+ B callbackasm1(SB)
+ MOVW $323, R12
+ B callbackasm1(SB)
+ MOVW $324, R12
+ B callbackasm1(SB)
+ MOVW $325, R12
+ B callbackasm1(SB)
+ MOVW $326, R12
+ B callbackasm1(SB)
+ MOVW $327, R12
+ B callbackasm1(SB)
+ MOVW $328, R12
+ B callbackasm1(SB)
+ MOVW $329, R12
+ B callbackasm1(SB)
+ MOVW $330, R12
+ B callbackasm1(SB)
+ MOVW $331, R12
+ B callbackasm1(SB)
+ MOVW $332, R12
+ B callbackasm1(SB)
+ MOVW $333, R12
+ B callbackasm1(SB)
+ MOVW $334, R12
+ B callbackasm1(SB)
+ MOVW $335, R12
+ B callbackasm1(SB)
+ MOVW $336, R12
+ B callbackasm1(SB)
+ MOVW $337, R12
+ B callbackasm1(SB)
+ MOVW $338, R12
+ B callbackasm1(SB)
+ MOVW $339, R12
+ B callbackasm1(SB)
+ MOVW $340, R12
+ B callbackasm1(SB)
+ MOVW $341, R12
+ B callbackasm1(SB)
+ MOVW $342, R12
+ B callbackasm1(SB)
+ MOVW $343, R12
+ B callbackasm1(SB)
+ MOVW $344, R12
+ B callbackasm1(SB)
+ MOVW $345, R12
+ B callbackasm1(SB)
+ MOVW $346, R12
+ B callbackasm1(SB)
+ MOVW $347, R12
+ B callbackasm1(SB)
+ MOVW $348, R12
+ B callbackasm1(SB)
+ MOVW $349, R12
+ B callbackasm1(SB)
+ MOVW $350, R12
+ B callbackasm1(SB)
+ MOVW $351, R12
+ B callbackasm1(SB)
+ MOVW $352, R12
+ B callbackasm1(SB)
+ MOVW $353, R12
+ B callbackasm1(SB)
+ MOVW $354, R12
+ B callbackasm1(SB)
+ MOVW $355, R12
+ B callbackasm1(SB)
+ MOVW $356, R12
+ B callbackasm1(SB)
+ MOVW $357, R12
+ B callbackasm1(SB)
+ MOVW $358, R12
+ B callbackasm1(SB)
+ MOVW $359, R12
+ B callbackasm1(SB)
+ MOVW $360, R12
+ B callbackasm1(SB)
+ MOVW $361, R12
+ B callbackasm1(SB)
+ MOVW $362, R12
+ B callbackasm1(SB)
+ MOVW $363, R12
+ B callbackasm1(SB)
+ MOVW $364, R12
+ B callbackasm1(SB)
+ MOVW $365, R12
+ B callbackasm1(SB)
+ MOVW $366, R12
+ B callbackasm1(SB)
+ MOVW $367, R12
+ B callbackasm1(SB)
+ MOVW $368, R12
+ B callbackasm1(SB)
+ MOVW $369, R12
+ B callbackasm1(SB)
+ MOVW $370, R12
+ B callbackasm1(SB)
+ MOVW $371, R12
+ B callbackasm1(SB)
+ MOVW $372, R12
+ B callbackasm1(SB)
+ MOVW $373, R12
+ B callbackasm1(SB)
+ MOVW $374, R12
+ B callbackasm1(SB)
+ MOVW $375, R12
+ B callbackasm1(SB)
+ MOVW $376, R12
+ B callbackasm1(SB)
+ MOVW $377, R12
+ B callbackasm1(SB)
+ MOVW $378, R12
+ B callbackasm1(SB)
+ MOVW $379, R12
+ B callbackasm1(SB)
+ MOVW $380, R12
+ B callbackasm1(SB)
+ MOVW $381, R12
+ B callbackasm1(SB)
+ MOVW $382, R12
+ B callbackasm1(SB)
+ MOVW $383, R12
+ B callbackasm1(SB)
+ MOVW $384, R12
+ B callbackasm1(SB)
+ MOVW $385, R12
+ B callbackasm1(SB)
+ MOVW $386, R12
+ B callbackasm1(SB)
+ MOVW $387, R12
+ B callbackasm1(SB)
+ MOVW $388, R12
+ B callbackasm1(SB)
+ MOVW $389, R12
+ B callbackasm1(SB)
+ MOVW $390, R12
+ B callbackasm1(SB)
+ MOVW $391, R12
+ B callbackasm1(SB)
+ MOVW $392, R12
+ B callbackasm1(SB)
+ MOVW $393, R12
+ B callbackasm1(SB)
+ MOVW $394, R12
+ B callbackasm1(SB)
+ MOVW $395, R12
+ B callbackasm1(SB)
+ MOVW $396, R12
+ B callbackasm1(SB)
+ MOVW $397, R12
+ B callbackasm1(SB)
+ MOVW $398, R12
+ B callbackasm1(SB)
+ MOVW $399, R12
+ B callbackasm1(SB)
+ MOVW $400, R12
+ B callbackasm1(SB)
+ MOVW $401, R12
+ B callbackasm1(SB)
+ MOVW $402, R12
+ B callbackasm1(SB)
+ MOVW $403, R12
+ B callbackasm1(SB)
+ MOVW $404, R12
+ B callbackasm1(SB)
+ MOVW $405, R12
+ B callbackasm1(SB)
+ MOVW $406, R12
+ B callbackasm1(SB)
+ MOVW $407, R12
+ B callbackasm1(SB)
+ MOVW $408, R12
+ B callbackasm1(SB)
+ MOVW $409, R12
+ B callbackasm1(SB)
+ MOVW $410, R12
+ B callbackasm1(SB)
+ MOVW $411, R12
+ B callbackasm1(SB)
+ MOVW $412, R12
+ B callbackasm1(SB)
+ MOVW $413, R12
+ B callbackasm1(SB)
+ MOVW $414, R12
+ B callbackasm1(SB)
+ MOVW $415, R12
+ B callbackasm1(SB)
+ MOVW $416, R12
+ B callbackasm1(SB)
+ MOVW $417, R12
+ B callbackasm1(SB)
+ MOVW $418, R12
+ B callbackasm1(SB)
+ MOVW $419, R12
+ B callbackasm1(SB)
+ MOVW $420, R12
+ B callbackasm1(SB)
+ MOVW $421, R12
+ B callbackasm1(SB)
+ MOVW $422, R12
+ B callbackasm1(SB)
+ MOVW $423, R12
+ B callbackasm1(SB)
+ MOVW $424, R12
+ B callbackasm1(SB)
+ MOVW $425, R12
+ B callbackasm1(SB)
+ MOVW $426, R12
+ B callbackasm1(SB)
+ MOVW $427, R12
+ B callbackasm1(SB)
+ MOVW $428, R12
+ B callbackasm1(SB)
+ MOVW $429, R12
+ B callbackasm1(SB)
+ MOVW $430, R12
+ B callbackasm1(SB)
+ MOVW $431, R12
+ B callbackasm1(SB)
+ MOVW $432, R12
+ B callbackasm1(SB)
+ MOVW $433, R12
+ B callbackasm1(SB)
+ MOVW $434, R12
+ B callbackasm1(SB)
+ MOVW $435, R12
+ B callbackasm1(SB)
+ MOVW $436, R12
+ B callbackasm1(SB)
+ MOVW $437, R12
+ B callbackasm1(SB)
+ MOVW $438, R12
+ B callbackasm1(SB)
+ MOVW $439, R12
+ B callbackasm1(SB)
+ MOVW $440, R12
+ B callbackasm1(SB)
+ MOVW $441, R12
+ B callbackasm1(SB)
+ MOVW $442, R12
+ B callbackasm1(SB)
+ MOVW $443, R12
+ B callbackasm1(SB)
+ MOVW $444, R12
+ B callbackasm1(SB)
+ MOVW $445, R12
+ B callbackasm1(SB)
+ MOVW $446, R12
+ B callbackasm1(SB)
+ MOVW $447, R12
+ B callbackasm1(SB)
+ MOVW $448, R12
+ B callbackasm1(SB)
+ MOVW $449, R12
+ B callbackasm1(SB)
+ MOVW $450, R12
+ B callbackasm1(SB)
+ MOVW $451, R12
+ B callbackasm1(SB)
+ MOVW $452, R12
+ B callbackasm1(SB)
+ MOVW $453, R12
+ B callbackasm1(SB)
+ MOVW $454, R12
+ B callbackasm1(SB)
+ MOVW $455, R12
+ B callbackasm1(SB)
+ MOVW $456, R12
+ B callbackasm1(SB)
+ MOVW $457, R12
+ B callbackasm1(SB)
+ MOVW $458, R12
+ B callbackasm1(SB)
+ MOVW $459, R12
+ B callbackasm1(SB)
+ MOVW $460, R12
+ B callbackasm1(SB)
+ MOVW $461, R12
+ B callbackasm1(SB)
+ MOVW $462, R12
+ B callbackasm1(SB)
+ MOVW $463, R12
+ B callbackasm1(SB)
+ MOVW $464, R12
+ B callbackasm1(SB)
+ MOVW $465, R12
+ B callbackasm1(SB)
+ MOVW $466, R12
+ B callbackasm1(SB)
+ MOVW $467, R12
+ B callbackasm1(SB)
+ MOVW $468, R12
+ B callbackasm1(SB)
+ MOVW $469, R12
+ B callbackasm1(SB)
+ MOVW $470, R12
+ B callbackasm1(SB)
+ MOVW $471, R12
+ B callbackasm1(SB)
+ MOVW $472, R12
+ B callbackasm1(SB)
+ MOVW $473, R12
+ B callbackasm1(SB)
+ MOVW $474, R12
+ B callbackasm1(SB)
+ MOVW $475, R12
+ B callbackasm1(SB)
+ MOVW $476, R12
+ B callbackasm1(SB)
+ MOVW $477, R12
+ B callbackasm1(SB)
+ MOVW $478, R12
+ B callbackasm1(SB)
+ MOVW $479, R12
+ B callbackasm1(SB)
+ MOVW $480, R12
+ B callbackasm1(SB)
+ MOVW $481, R12
+ B callbackasm1(SB)
+ MOVW $482, R12
+ B callbackasm1(SB)
+ MOVW $483, R12
+ B callbackasm1(SB)
+ MOVW $484, R12
+ B callbackasm1(SB)
+ MOVW $485, R12
+ B callbackasm1(SB)
+ MOVW $486, R12
+ B callbackasm1(SB)
+ MOVW $487, R12
+ B callbackasm1(SB)
+ MOVW $488, R12
+ B callbackasm1(SB)
+ MOVW $489, R12
+ B callbackasm1(SB)
+ MOVW $490, R12
+ B callbackasm1(SB)
+ MOVW $491, R12
+ B callbackasm1(SB)
+ MOVW $492, R12
+ B callbackasm1(SB)
+ MOVW $493, R12
+ B callbackasm1(SB)
+ MOVW $494, R12
+ B callbackasm1(SB)
+ MOVW $495, R12
+ B callbackasm1(SB)
+ MOVW $496, R12
+ B callbackasm1(SB)
+ MOVW $497, R12
+ B callbackasm1(SB)
+ MOVW $498, R12
+ B callbackasm1(SB)
+ MOVW $499, R12
+ B callbackasm1(SB)
+ MOVW $500, R12
+ B callbackasm1(SB)
+ MOVW $501, R12
+ B callbackasm1(SB)
+ MOVW $502, R12
+ B callbackasm1(SB)
+ MOVW $503, R12
+ B callbackasm1(SB)
+ MOVW $504, R12
+ B callbackasm1(SB)
+ MOVW $505, R12
+ B callbackasm1(SB)
+ MOVW $506, R12
+ B callbackasm1(SB)
+ MOVW $507, R12
+ B callbackasm1(SB)
+ MOVW $508, R12
+ B callbackasm1(SB)
+ MOVW $509, R12
+ B callbackasm1(SB)
+ MOVW $510, R12
+ B callbackasm1(SB)
+ MOVW $511, R12
+ B callbackasm1(SB)
+ MOVW $512, R12
+ B callbackasm1(SB)
+ MOVW $513, R12
+ B callbackasm1(SB)
+ MOVW $514, R12
+ B callbackasm1(SB)
+ MOVW $515, R12
+ B callbackasm1(SB)
+ MOVW $516, R12
+ B callbackasm1(SB)
+ MOVW $517, R12
+ B callbackasm1(SB)
+ MOVW $518, R12
+ B callbackasm1(SB)
+ MOVW $519, R12
+ B callbackasm1(SB)
+ MOVW $520, R12
+ B callbackasm1(SB)
+ MOVW $521, R12
+ B callbackasm1(SB)
+ MOVW $522, R12
+ B callbackasm1(SB)
+ MOVW $523, R12
+ B callbackasm1(SB)
+ MOVW $524, R12
+ B callbackasm1(SB)
+ MOVW $525, R12
+ B callbackasm1(SB)
+ MOVW $526, R12
+ B callbackasm1(SB)
+ MOVW $527, R12
+ B callbackasm1(SB)
+ MOVW $528, R12
+ B callbackasm1(SB)
+ MOVW $529, R12
+ B callbackasm1(SB)
+ MOVW $530, R12
+ B callbackasm1(SB)
+ MOVW $531, R12
+ B callbackasm1(SB)
+ MOVW $532, R12
+ B callbackasm1(SB)
+ MOVW $533, R12
+ B callbackasm1(SB)
+ MOVW $534, R12
+ B callbackasm1(SB)
+ MOVW $535, R12
+ B callbackasm1(SB)
+ MOVW $536, R12
+ B callbackasm1(SB)
+ MOVW $537, R12
+ B callbackasm1(SB)
+ MOVW $538, R12
+ B callbackasm1(SB)
+ MOVW $539, R12
+ B callbackasm1(SB)
+ MOVW $540, R12
+ B callbackasm1(SB)
+ MOVW $541, R12
+ B callbackasm1(SB)
+ MOVW $542, R12
+ B callbackasm1(SB)
+ MOVW $543, R12
+ B callbackasm1(SB)
+ MOVW $544, R12
+ B callbackasm1(SB)
+ MOVW $545, R12
+ B callbackasm1(SB)
+ MOVW $546, R12
+ B callbackasm1(SB)
+ MOVW $547, R12
+ B callbackasm1(SB)
+ MOVW $548, R12
+ B callbackasm1(SB)
+ MOVW $549, R12
+ B callbackasm1(SB)
+ MOVW $550, R12
+ B callbackasm1(SB)
+ MOVW $551, R12
+ B callbackasm1(SB)
+ MOVW $552, R12
+ B callbackasm1(SB)
+ MOVW $553, R12
+ B callbackasm1(SB)
+ MOVW $554, R12
+ B callbackasm1(SB)
+ MOVW $555, R12
+ B callbackasm1(SB)
+ MOVW $556, R12
+ B callbackasm1(SB)
+ MOVW $557, R12
+ B callbackasm1(SB)
+ MOVW $558, R12
+ B callbackasm1(SB)
+ MOVW $559, R12
+ B callbackasm1(SB)
+ MOVW $560, R12
+ B callbackasm1(SB)
+ MOVW $561, R12
+ B callbackasm1(SB)
+ MOVW $562, R12
+ B callbackasm1(SB)
+ MOVW $563, R12
+ B callbackasm1(SB)
+ MOVW $564, R12
+ B callbackasm1(SB)
+ MOVW $565, R12
+ B callbackasm1(SB)
+ MOVW $566, R12
+ B callbackasm1(SB)
+ MOVW $567, R12
+ B callbackasm1(SB)
+ MOVW $568, R12
+ B callbackasm1(SB)
+ MOVW $569, R12
+ B callbackasm1(SB)
+ MOVW $570, R12
+ B callbackasm1(SB)
+ MOVW $571, R12
+ B callbackasm1(SB)
+ MOVW $572, R12
+ B callbackasm1(SB)
+ MOVW $573, R12
+ B callbackasm1(SB)
+ MOVW $574, R12
+ B callbackasm1(SB)
+ MOVW $575, R12
+ B callbackasm1(SB)
+ MOVW $576, R12
+ B callbackasm1(SB)
+ MOVW $577, R12
+ B callbackasm1(SB)
+ MOVW $578, R12
+ B callbackasm1(SB)
+ MOVW $579, R12
+ B callbackasm1(SB)
+ MOVW $580, R12
+ B callbackasm1(SB)
+ MOVW $581, R12
+ B callbackasm1(SB)
+ MOVW $582, R12
+ B callbackasm1(SB)
+ MOVW $583, R12
+ B callbackasm1(SB)
+ MOVW $584, R12
+ B callbackasm1(SB)
+ MOVW $585, R12
+ B callbackasm1(SB)
+ MOVW $586, R12
+ B callbackasm1(SB)
+ MOVW $587, R12
+ B callbackasm1(SB)
+ MOVW $588, R12
+ B callbackasm1(SB)
+ MOVW $589, R12
+ B callbackasm1(SB)
+ MOVW $590, R12
+ B callbackasm1(SB)
+ MOVW $591, R12
+ B callbackasm1(SB)
+ MOVW $592, R12
+ B callbackasm1(SB)
+ MOVW $593, R12
+ B callbackasm1(SB)
+ MOVW $594, R12
+ B callbackasm1(SB)
+ MOVW $595, R12
+ B callbackasm1(SB)
+ MOVW $596, R12
+ B callbackasm1(SB)
+ MOVW $597, R12
+ B callbackasm1(SB)
+ MOVW $598, R12
+ B callbackasm1(SB)
+ MOVW $599, R12
+ B callbackasm1(SB)
+ MOVW $600, R12
+ B callbackasm1(SB)
+ MOVW $601, R12
+ B callbackasm1(SB)
+ MOVW $602, R12
+ B callbackasm1(SB)
+ MOVW $603, R12
+ B callbackasm1(SB)
+ MOVW $604, R12
+ B callbackasm1(SB)
+ MOVW $605, R12
+ B callbackasm1(SB)
+ MOVW $606, R12
+ B callbackasm1(SB)
+ MOVW $607, R12
+ B callbackasm1(SB)
+ MOVW $608, R12
+ B callbackasm1(SB)
+ MOVW $609, R12
+ B callbackasm1(SB)
+ MOVW $610, R12
+ B callbackasm1(SB)
+ MOVW $611, R12
+ B callbackasm1(SB)
+ MOVW $612, R12
+ B callbackasm1(SB)
+ MOVW $613, R12
+ B callbackasm1(SB)
+ MOVW $614, R12
+ B callbackasm1(SB)
+ MOVW $615, R12
+ B callbackasm1(SB)
+ MOVW $616, R12
+ B callbackasm1(SB)
+ MOVW $617, R12
+ B callbackasm1(SB)
+ MOVW $618, R12
+ B callbackasm1(SB)
+ MOVW $619, R12
+ B callbackasm1(SB)
+ MOVW $620, R12
+ B callbackasm1(SB)
+ MOVW $621, R12
+ B callbackasm1(SB)
+ MOVW $622, R12
+ B callbackasm1(SB)
+ MOVW $623, R12
+ B callbackasm1(SB)
+ MOVW $624, R12
+ B callbackasm1(SB)
+ MOVW $625, R12
+ B callbackasm1(SB)
+ MOVW $626, R12
+ B callbackasm1(SB)
+ MOVW $627, R12
+ B callbackasm1(SB)
+ MOVW $628, R12
+ B callbackasm1(SB)
+ MOVW $629, R12
+ B callbackasm1(SB)
+ MOVW $630, R12
+ B callbackasm1(SB)
+ MOVW $631, R12
+ B callbackasm1(SB)
+ MOVW $632, R12
+ B callbackasm1(SB)
+ MOVW $633, R12
+ B callbackasm1(SB)
+ MOVW $634, R12
+ B callbackasm1(SB)
+ MOVW $635, R12
+ B callbackasm1(SB)
+ MOVW $636, R12
+ B callbackasm1(SB)
+ MOVW $637, R12
+ B callbackasm1(SB)
+ MOVW $638, R12
+ B callbackasm1(SB)
+ MOVW $639, R12
+ B callbackasm1(SB)
+ MOVW $640, R12
+ B callbackasm1(SB)
+ MOVW $641, R12
+ B callbackasm1(SB)
+ MOVW $642, R12
+ B callbackasm1(SB)
+ MOVW $643, R12
+ B callbackasm1(SB)
+ MOVW $644, R12
+ B callbackasm1(SB)
+ MOVW $645, R12
+ B callbackasm1(SB)
+ MOVW $646, R12
+ B callbackasm1(SB)
+ MOVW $647, R12
+ B callbackasm1(SB)
+ MOVW $648, R12
+ B callbackasm1(SB)
+ MOVW $649, R12
+ B callbackasm1(SB)
+ MOVW $650, R12
+ B callbackasm1(SB)
+ MOVW $651, R12
+ B callbackasm1(SB)
+ MOVW $652, R12
+ B callbackasm1(SB)
+ MOVW $653, R12
+ B callbackasm1(SB)
+ MOVW $654, R12
+ B callbackasm1(SB)
+ MOVW $655, R12
+ B callbackasm1(SB)
+ MOVW $656, R12
+ B callbackasm1(SB)
+ MOVW $657, R12
+ B callbackasm1(SB)
+ MOVW $658, R12
+ B callbackasm1(SB)
+ MOVW $659, R12
+ B callbackasm1(SB)
+ MOVW $660, R12
+ B callbackasm1(SB)
+ MOVW $661, R12
+ B callbackasm1(SB)
+ MOVW $662, R12
+ B callbackasm1(SB)
+ MOVW $663, R12
+ B callbackasm1(SB)
+ MOVW $664, R12
+ B callbackasm1(SB)
+ MOVW $665, R12
+ B callbackasm1(SB)
+ MOVW $666, R12
+ B callbackasm1(SB)
+ MOVW $667, R12
+ B callbackasm1(SB)
+ MOVW $668, R12
+ B callbackasm1(SB)
+ MOVW $669, R12
+ B callbackasm1(SB)
+ MOVW $670, R12
+ B callbackasm1(SB)
+ MOVW $671, R12
+ B callbackasm1(SB)
+ MOVW $672, R12
+ B callbackasm1(SB)
+ MOVW $673, R12
+ B callbackasm1(SB)
+ MOVW $674, R12
+ B callbackasm1(SB)
+ MOVW $675, R12
+ B callbackasm1(SB)
+ MOVW $676, R12
+ B callbackasm1(SB)
+ MOVW $677, R12
+ B callbackasm1(SB)
+ MOVW $678, R12
+ B callbackasm1(SB)
+ MOVW $679, R12
+ B callbackasm1(SB)
+ MOVW $680, R12
+ B callbackasm1(SB)
+ MOVW $681, R12
+ B callbackasm1(SB)
+ MOVW $682, R12
+ B callbackasm1(SB)
+ MOVW $683, R12
+ B callbackasm1(SB)
+ MOVW $684, R12
+ B callbackasm1(SB)
+ MOVW $685, R12
+ B callbackasm1(SB)
+ MOVW $686, R12
+ B callbackasm1(SB)
+ MOVW $687, R12
+ B callbackasm1(SB)
+ MOVW $688, R12
+ B callbackasm1(SB)
+ MOVW $689, R12
+ B callbackasm1(SB)
+ MOVW $690, R12
+ B callbackasm1(SB)
+ MOVW $691, R12
+ B callbackasm1(SB)
+ MOVW $692, R12
+ B callbackasm1(SB)
+ MOVW $693, R12
+ B callbackasm1(SB)
+ MOVW $694, R12
+ B callbackasm1(SB)
+ MOVW $695, R12
+ B callbackasm1(SB)
+ MOVW $696, R12
+ B callbackasm1(SB)
+ MOVW $697, R12
+ B callbackasm1(SB)
+ MOVW $698, R12
+ B callbackasm1(SB)
+ MOVW $699, R12
+ B callbackasm1(SB)
+ MOVW $700, R12
+ B callbackasm1(SB)
+ MOVW $701, R12
+ B callbackasm1(SB)
+ MOVW $702, R12
+ B callbackasm1(SB)
+ MOVW $703, R12
+ B callbackasm1(SB)
+ MOVW $704, R12
+ B callbackasm1(SB)
+ MOVW $705, R12
+ B callbackasm1(SB)
+ MOVW $706, R12
+ B callbackasm1(SB)
+ MOVW $707, R12
+ B callbackasm1(SB)
+ MOVW $708, R12
+ B callbackasm1(SB)
+ MOVW $709, R12
+ B callbackasm1(SB)
+ MOVW $710, R12
+ B callbackasm1(SB)
+ MOVW $711, R12
+ B callbackasm1(SB)
+ MOVW $712, R12
+ B callbackasm1(SB)
+ MOVW $713, R12
+ B callbackasm1(SB)
+ MOVW $714, R12
+ B callbackasm1(SB)
+ MOVW $715, R12
+ B callbackasm1(SB)
+ MOVW $716, R12
+ B callbackasm1(SB)
+ MOVW $717, R12
+ B callbackasm1(SB)
+ MOVW $718, R12
+ B callbackasm1(SB)
+ MOVW $719, R12
+ B callbackasm1(SB)
+ MOVW $720, R12
+ B callbackasm1(SB)
+ MOVW $721, R12
+ B callbackasm1(SB)
+ MOVW $722, R12
+ B callbackasm1(SB)
+ MOVW $723, R12
+ B callbackasm1(SB)
+ MOVW $724, R12
+ B callbackasm1(SB)
+ MOVW $725, R12
+ B callbackasm1(SB)
+ MOVW $726, R12
+ B callbackasm1(SB)
+ MOVW $727, R12
+ B callbackasm1(SB)
+ MOVW $728, R12
+ B callbackasm1(SB)
+ MOVW $729, R12
+ B callbackasm1(SB)
+ MOVW $730, R12
+ B callbackasm1(SB)
+ MOVW $731, R12
+ B callbackasm1(SB)
+ MOVW $732, R12
+ B callbackasm1(SB)
+ MOVW $733, R12
+ B callbackasm1(SB)
+ MOVW $734, R12
+ B callbackasm1(SB)
+ MOVW $735, R12
+ B callbackasm1(SB)
+ MOVW $736, R12
+ B callbackasm1(SB)
+ MOVW $737, R12
+ B callbackasm1(SB)
+ MOVW $738, R12
+ B callbackasm1(SB)
+ MOVW $739, R12
+ B callbackasm1(SB)
+ MOVW $740, R12
+ B callbackasm1(SB)
+ MOVW $741, R12
+ B callbackasm1(SB)
+ MOVW $742, R12
+ B callbackasm1(SB)
+ MOVW $743, R12
+ B callbackasm1(SB)
+ MOVW $744, R12
+ B callbackasm1(SB)
+ MOVW $745, R12
+ B callbackasm1(SB)
+ MOVW $746, R12
+ B callbackasm1(SB)
+ MOVW $747, R12
+ B callbackasm1(SB)
+ MOVW $748, R12
+ B callbackasm1(SB)
+ MOVW $749, R12
+ B callbackasm1(SB)
+ MOVW $750, R12
+ B callbackasm1(SB)
+ MOVW $751, R12
+ B callbackasm1(SB)
+ MOVW $752, R12
+ B callbackasm1(SB)
+ MOVW $753, R12
+ B callbackasm1(SB)
+ MOVW $754, R12
+ B callbackasm1(SB)
+ MOVW $755, R12
+ B callbackasm1(SB)
+ MOVW $756, R12
+ B callbackasm1(SB)
+ MOVW $757, R12
+ B callbackasm1(SB)
+ MOVW $758, R12
+ B callbackasm1(SB)
+ MOVW $759, R12
+ B callbackasm1(SB)
+ MOVW $760, R12
+ B callbackasm1(SB)
+ MOVW $761, R12
+ B callbackasm1(SB)
+ MOVW $762, R12
+ B callbackasm1(SB)
+ MOVW $763, R12
+ B callbackasm1(SB)
+ MOVW $764, R12
+ B callbackasm1(SB)
+ MOVW $765, R12
+ B callbackasm1(SB)
+ MOVW $766, R12
+ B callbackasm1(SB)
+ MOVW $767, R12
+ B callbackasm1(SB)
+ MOVW $768, R12
+ B callbackasm1(SB)
+ MOVW $769, R12
+ B callbackasm1(SB)
+ MOVW $770, R12
+ B callbackasm1(SB)
+ MOVW $771, R12
+ B callbackasm1(SB)
+ MOVW $772, R12
+ B callbackasm1(SB)
+ MOVW $773, R12
+ B callbackasm1(SB)
+ MOVW $774, R12
+ B callbackasm1(SB)
+ MOVW $775, R12
+ B callbackasm1(SB)
+ MOVW $776, R12
+ B callbackasm1(SB)
+ MOVW $777, R12
+ B callbackasm1(SB)
+ MOVW $778, R12
+ B callbackasm1(SB)
+ MOVW $779, R12
+ B callbackasm1(SB)
+ MOVW $780, R12
+ B callbackasm1(SB)
+ MOVW $781, R12
+ B callbackasm1(SB)
+ MOVW $782, R12
+ B callbackasm1(SB)
+ MOVW $783, R12
+ B callbackasm1(SB)
+ MOVW $784, R12
+ B callbackasm1(SB)
+ MOVW $785, R12
+ B callbackasm1(SB)
+ MOVW $786, R12
+ B callbackasm1(SB)
+ MOVW $787, R12
+ B callbackasm1(SB)
+ MOVW $788, R12
+ B callbackasm1(SB)
+ MOVW $789, R12
+ B callbackasm1(SB)
+ MOVW $790, R12
+ B callbackasm1(SB)
+ MOVW $791, R12
+ B callbackasm1(SB)
+ MOVW $792, R12
+ B callbackasm1(SB)
+ MOVW $793, R12
+ B callbackasm1(SB)
+ MOVW $794, R12
+ B callbackasm1(SB)
+ MOVW $795, R12
+ B callbackasm1(SB)
+ MOVW $796, R12
+ B callbackasm1(SB)
+ MOVW $797, R12
+ B callbackasm1(SB)
+ MOVW $798, R12
+ B callbackasm1(SB)
+ MOVW $799, R12
+ B callbackasm1(SB)
+ MOVW $800, R12
+ B callbackasm1(SB)
+ MOVW $801, R12
+ B callbackasm1(SB)
+ MOVW $802, R12
+ B callbackasm1(SB)
+ MOVW $803, R12
+ B callbackasm1(SB)
+ MOVW $804, R12
+ B callbackasm1(SB)
+ MOVW $805, R12
+ B callbackasm1(SB)
+ MOVW $806, R12
+ B callbackasm1(SB)
+ MOVW $807, R12
+ B callbackasm1(SB)
+ MOVW $808, R12
+ B callbackasm1(SB)
+ MOVW $809, R12
+ B callbackasm1(SB)
+ MOVW $810, R12
+ B callbackasm1(SB)
+ MOVW $811, R12
+ B callbackasm1(SB)
+ MOVW $812, R12
+ B callbackasm1(SB)
+ MOVW $813, R12
+ B callbackasm1(SB)
+ MOVW $814, R12
+ B callbackasm1(SB)
+ MOVW $815, R12
+ B callbackasm1(SB)
+ MOVW $816, R12
+ B callbackasm1(SB)
+ MOVW $817, R12
+ B callbackasm1(SB)
+ MOVW $818, R12
+ B callbackasm1(SB)
+ MOVW $819, R12
+ B callbackasm1(SB)
+ MOVW $820, R12
+ B callbackasm1(SB)
+ MOVW $821, R12
+ B callbackasm1(SB)
+ MOVW $822, R12
+ B callbackasm1(SB)
+ MOVW $823, R12
+ B callbackasm1(SB)
+ MOVW $824, R12
+ B callbackasm1(SB)
+ MOVW $825, R12
+ B callbackasm1(SB)
+ MOVW $826, R12
+ B callbackasm1(SB)
+ MOVW $827, R12
+ B callbackasm1(SB)
+ MOVW $828, R12
+ B callbackasm1(SB)
+ MOVW $829, R12
+ B callbackasm1(SB)
+ MOVW $830, R12
+ B callbackasm1(SB)
+ MOVW $831, R12
+ B callbackasm1(SB)
+ MOVW $832, R12
+ B callbackasm1(SB)
+ MOVW $833, R12
+ B callbackasm1(SB)
+ MOVW $834, R12
+ B callbackasm1(SB)
+ MOVW $835, R12
+ B callbackasm1(SB)
+ MOVW $836, R12
+ B callbackasm1(SB)
+ MOVW $837, R12
+ B callbackasm1(SB)
+ MOVW $838, R12
+ B callbackasm1(SB)
+ MOVW $839, R12
+ B callbackasm1(SB)
+ MOVW $840, R12
+ B callbackasm1(SB)
+ MOVW $841, R12
+ B callbackasm1(SB)
+ MOVW $842, R12
+ B callbackasm1(SB)
+ MOVW $843, R12
+ B callbackasm1(SB)
+ MOVW $844, R12
+ B callbackasm1(SB)
+ MOVW $845, R12
+ B callbackasm1(SB)
+ MOVW $846, R12
+ B callbackasm1(SB)
+ MOVW $847, R12
+ B callbackasm1(SB)
+ MOVW $848, R12
+ B callbackasm1(SB)
+ MOVW $849, R12
+ B callbackasm1(SB)
+ MOVW $850, R12
+ B callbackasm1(SB)
+ MOVW $851, R12
+ B callbackasm1(SB)
+ MOVW $852, R12
+ B callbackasm1(SB)
+ MOVW $853, R12
+ B callbackasm1(SB)
+ MOVW $854, R12
+ B callbackasm1(SB)
+ MOVW $855, R12
+ B callbackasm1(SB)
+ MOVW $856, R12
+ B callbackasm1(SB)
+ MOVW $857, R12
+ B callbackasm1(SB)
+ MOVW $858, R12
+ B callbackasm1(SB)
+ MOVW $859, R12
+ B callbackasm1(SB)
+ MOVW $860, R12
+ B callbackasm1(SB)
+ MOVW $861, R12
+ B callbackasm1(SB)
+ MOVW $862, R12
+ B callbackasm1(SB)
+ MOVW $863, R12
+ B callbackasm1(SB)
+ MOVW $864, R12
+ B callbackasm1(SB)
+ MOVW $865, R12
+ B callbackasm1(SB)
+ MOVW $866, R12
+ B callbackasm1(SB)
+ MOVW $867, R12
+ B callbackasm1(SB)
+ MOVW $868, R12
+ B callbackasm1(SB)
+ MOVW $869, R12
+ B callbackasm1(SB)
+ MOVW $870, R12
+ B callbackasm1(SB)
+ MOVW $871, R12
+ B callbackasm1(SB)
+ MOVW $872, R12
+ B callbackasm1(SB)
+ MOVW $873, R12
+ B callbackasm1(SB)
+ MOVW $874, R12
+ B callbackasm1(SB)
+ MOVW $875, R12
+ B callbackasm1(SB)
+ MOVW $876, R12
+ B callbackasm1(SB)
+ MOVW $877, R12
+ B callbackasm1(SB)
+ MOVW $878, R12
+ B callbackasm1(SB)
+ MOVW $879, R12
+ B callbackasm1(SB)
+ MOVW $880, R12
+ B callbackasm1(SB)
+ MOVW $881, R12
+ B callbackasm1(SB)
+ MOVW $882, R12
+ B callbackasm1(SB)
+ MOVW $883, R12
+ B callbackasm1(SB)
+ MOVW $884, R12
+ B callbackasm1(SB)
+ MOVW $885, R12
+ B callbackasm1(SB)
+ MOVW $886, R12
+ B callbackasm1(SB)
+ MOVW $887, R12
+ B callbackasm1(SB)
+ MOVW $888, R12
+ B callbackasm1(SB)
+ MOVW $889, R12
+ B callbackasm1(SB)
+ MOVW $890, R12
+ B callbackasm1(SB)
+ MOVW $891, R12
+ B callbackasm1(SB)
+ MOVW $892, R12
+ B callbackasm1(SB)
+ MOVW $893, R12
+ B callbackasm1(SB)
+ MOVW $894, R12
+ B callbackasm1(SB)
+ MOVW $895, R12
+ B callbackasm1(SB)
+ MOVW $896, R12
+ B callbackasm1(SB)
+ MOVW $897, R12
+ B callbackasm1(SB)
+ MOVW $898, R12
+ B callbackasm1(SB)
+ MOVW $899, R12
+ B callbackasm1(SB)
+ MOVW $900, R12
+ B callbackasm1(SB)
+ MOVW $901, R12
+ B callbackasm1(SB)
+ MOVW $902, R12
+ B callbackasm1(SB)
+ MOVW $903, R12
+ B callbackasm1(SB)
+ MOVW $904, R12
+ B callbackasm1(SB)
+ MOVW $905, R12
+ B callbackasm1(SB)
+ MOVW $906, R12
+ B callbackasm1(SB)
+ MOVW $907, R12
+ B callbackasm1(SB)
+ MOVW $908, R12
+ B callbackasm1(SB)
+ MOVW $909, R12
+ B callbackasm1(SB)
+ MOVW $910, R12
+ B callbackasm1(SB)
+ MOVW $911, R12
+ B callbackasm1(SB)
+ MOVW $912, R12
+ B callbackasm1(SB)
+ MOVW $913, R12
+ B callbackasm1(SB)
+ MOVW $914, R12
+ B callbackasm1(SB)
+ MOVW $915, R12
+ B callbackasm1(SB)
+ MOVW $916, R12
+ B callbackasm1(SB)
+ MOVW $917, R12
+ B callbackasm1(SB)
+ MOVW $918, R12
+ B callbackasm1(SB)
+ MOVW $919, R12
+ B callbackasm1(SB)
+ MOVW $920, R12
+ B callbackasm1(SB)
+ MOVW $921, R12
+ B callbackasm1(SB)
+ MOVW $922, R12
+ B callbackasm1(SB)
+ MOVW $923, R12
+ B callbackasm1(SB)
+ MOVW $924, R12
+ B callbackasm1(SB)
+ MOVW $925, R12
+ B callbackasm1(SB)
+ MOVW $926, R12
+ B callbackasm1(SB)
+ MOVW $927, R12
+ B callbackasm1(SB)
+ MOVW $928, R12
+ B callbackasm1(SB)
+ MOVW $929, R12
+ B callbackasm1(SB)
+ MOVW $930, R12
+ B callbackasm1(SB)
+ MOVW $931, R12
+ B callbackasm1(SB)
+ MOVW $932, R12
+ B callbackasm1(SB)
+ MOVW $933, R12
+ B callbackasm1(SB)
+ MOVW $934, R12
+ B callbackasm1(SB)
+ MOVW $935, R12
+ B callbackasm1(SB)
+ MOVW $936, R12
+ B callbackasm1(SB)
+ MOVW $937, R12
+ B callbackasm1(SB)
+ MOVW $938, R12
+ B callbackasm1(SB)
+ MOVW $939, R12
+ B callbackasm1(SB)
+ MOVW $940, R12
+ B callbackasm1(SB)
+ MOVW $941, R12
+ B callbackasm1(SB)
+ MOVW $942, R12
+ B callbackasm1(SB)
+ MOVW $943, R12
+ B callbackasm1(SB)
+ MOVW $944, R12
+ B callbackasm1(SB)
+ MOVW $945, R12
+ B callbackasm1(SB)
+ MOVW $946, R12
+ B callbackasm1(SB)
+ MOVW $947, R12
+ B callbackasm1(SB)
+ MOVW $948, R12
+ B callbackasm1(SB)
+ MOVW $949, R12
+ B callbackasm1(SB)
+ MOVW $950, R12
+ B callbackasm1(SB)
+ MOVW $951, R12
+ B callbackasm1(SB)
+ MOVW $952, R12
+ B callbackasm1(SB)
+ MOVW $953, R12
+ B callbackasm1(SB)
+ MOVW $954, R12
+ B callbackasm1(SB)
+ MOVW $955, R12
+ B callbackasm1(SB)
+ MOVW $956, R12
+ B callbackasm1(SB)
+ MOVW $957, R12
+ B callbackasm1(SB)
+ MOVW $958, R12
+ B callbackasm1(SB)
+ MOVW $959, R12
+ B callbackasm1(SB)
+ MOVW $960, R12
+ B callbackasm1(SB)
+ MOVW $961, R12
+ B callbackasm1(SB)
+ MOVW $962, R12
+ B callbackasm1(SB)
+ MOVW $963, R12
+ B callbackasm1(SB)
+ MOVW $964, R12
+ B callbackasm1(SB)
+ MOVW $965, R12
+ B callbackasm1(SB)
+ MOVW $966, R12
+ B callbackasm1(SB)
+ MOVW $967, R12
+ B callbackasm1(SB)
+ MOVW $968, R12
+ B callbackasm1(SB)
+ MOVW $969, R12
+ B callbackasm1(SB)
+ MOVW $970, R12
+ B callbackasm1(SB)
+ MOVW $971, R12
+ B callbackasm1(SB)
+ MOVW $972, R12
+ B callbackasm1(SB)
+ MOVW $973, R12
+ B callbackasm1(SB)
+ MOVW $974, R12
+ B callbackasm1(SB)
+ MOVW $975, R12
+ B callbackasm1(SB)
+ MOVW $976, R12
+ B callbackasm1(SB)
+ MOVW $977, R12
+ B callbackasm1(SB)
+ MOVW $978, R12
+ B callbackasm1(SB)
+ MOVW $979, R12
+ B callbackasm1(SB)
+ MOVW $980, R12
+ B callbackasm1(SB)
+ MOVW $981, R12
+ B callbackasm1(SB)
+ MOVW $982, R12
+ B callbackasm1(SB)
+ MOVW $983, R12
+ B callbackasm1(SB)
+ MOVW $984, R12
+ B callbackasm1(SB)
+ MOVW $985, R12
+ B callbackasm1(SB)
+ MOVW $986, R12
+ B callbackasm1(SB)
+ MOVW $987, R12
+ B callbackasm1(SB)
+ MOVW $988, R12
+ B callbackasm1(SB)
+ MOVW $989, R12
+ B callbackasm1(SB)
+ MOVW $990, R12
+ B callbackasm1(SB)
+ MOVW $991, R12
+ B callbackasm1(SB)
+ MOVW $992, R12
+ B callbackasm1(SB)
+ MOVW $993, R12
+ B callbackasm1(SB)
+ MOVW $994, R12
+ B callbackasm1(SB)
+ MOVW $995, R12
+ B callbackasm1(SB)
+ MOVW $996, R12
+ B callbackasm1(SB)
+ MOVW $997, R12
+ B callbackasm1(SB)
+ MOVW $998, R12
+ B callbackasm1(SB)
+ MOVW $999, R12
+ B callbackasm1(SB)
+ MOVW $1000, R12
+ B callbackasm1(SB)
+ MOVW $1001, R12
+ B callbackasm1(SB)
+ MOVW $1002, R12
+ B callbackasm1(SB)
+ MOVW $1003, R12
+ B callbackasm1(SB)
+ MOVW $1004, R12
+ B callbackasm1(SB)
+ MOVW $1005, R12
+ B callbackasm1(SB)
+ MOVW $1006, R12
+ B callbackasm1(SB)
+ MOVW $1007, R12
+ B callbackasm1(SB)
+ MOVW $1008, R12
+ B callbackasm1(SB)
+ MOVW $1009, R12
+ B callbackasm1(SB)
+ MOVW $1010, R12
+ B callbackasm1(SB)
+ MOVW $1011, R12
+ B callbackasm1(SB)
+ MOVW $1012, R12
+ B callbackasm1(SB)
+ MOVW $1013, R12
+ B callbackasm1(SB)
+ MOVW $1014, R12
+ B callbackasm1(SB)
+ MOVW $1015, R12
+ B callbackasm1(SB)
+ MOVW $1016, R12
+ B callbackasm1(SB)
+ MOVW $1017, R12
+ B callbackasm1(SB)
+ MOVW $1018, R12
+ B callbackasm1(SB)
+ MOVW $1019, R12
+ B callbackasm1(SB)
+ MOVW $1020, R12
+ B callbackasm1(SB)
+ MOVW $1021, R12
+ B callbackasm1(SB)
+ MOVW $1022, R12
+ B callbackasm1(SB)
+ MOVW $1023, R12
+ B callbackasm1(SB)
+ MOVW $1024, R12
+ B callbackasm1(SB)
+ MOVW $1025, R12
+ B callbackasm1(SB)
+ MOVW $1026, R12
+ B callbackasm1(SB)
+ MOVW $1027, R12
+ B callbackasm1(SB)
+ MOVW $1028, R12
+ B callbackasm1(SB)
+ MOVW $1029, R12
+ B callbackasm1(SB)
+ MOVW $1030, R12
+ B callbackasm1(SB)
+ MOVW $1031, R12
+ B callbackasm1(SB)
+ MOVW $1032, R12
+ B callbackasm1(SB)
+ MOVW $1033, R12
+ B callbackasm1(SB)
+ MOVW $1034, R12
+ B callbackasm1(SB)
+ MOVW $1035, R12
+ B callbackasm1(SB)
+ MOVW $1036, R12
+ B callbackasm1(SB)
+ MOVW $1037, R12
+ B callbackasm1(SB)
+ MOVW $1038, R12
+ B callbackasm1(SB)
+ MOVW $1039, R12
+ B callbackasm1(SB)
+ MOVW $1040, R12
+ B callbackasm1(SB)
+ MOVW $1041, R12
+ B callbackasm1(SB)
+ MOVW $1042, R12
+ B callbackasm1(SB)
+ MOVW $1043, R12
+ B callbackasm1(SB)
+ MOVW $1044, R12
+ B callbackasm1(SB)
+ MOVW $1045, R12
+ B callbackasm1(SB)
+ MOVW $1046, R12
+ B callbackasm1(SB)
+ MOVW $1047, R12
+ B callbackasm1(SB)
+ MOVW $1048, R12
+ B callbackasm1(SB)
+ MOVW $1049, R12
+ B callbackasm1(SB)
+ MOVW $1050, R12
+ B callbackasm1(SB)
+ MOVW $1051, R12
+ B callbackasm1(SB)
+ MOVW $1052, R12
+ B callbackasm1(SB)
+ MOVW $1053, R12
+ B callbackasm1(SB)
+ MOVW $1054, R12
+ B callbackasm1(SB)
+ MOVW $1055, R12
+ B callbackasm1(SB)
+ MOVW $1056, R12
+ B callbackasm1(SB)
+ MOVW $1057, R12
+ B callbackasm1(SB)
+ MOVW $1058, R12
+ B callbackasm1(SB)
+ MOVW $1059, R12
+ B callbackasm1(SB)
+ MOVW $1060, R12
+ B callbackasm1(SB)
+ MOVW $1061, R12
+ B callbackasm1(SB)
+ MOVW $1062, R12
+ B callbackasm1(SB)
+ MOVW $1063, R12
+ B callbackasm1(SB)
+ MOVW $1064, R12
+ B callbackasm1(SB)
+ MOVW $1065, R12
+ B callbackasm1(SB)
+ MOVW $1066, R12
+ B callbackasm1(SB)
+ MOVW $1067, R12
+ B callbackasm1(SB)
+ MOVW $1068, R12
+ B callbackasm1(SB)
+ MOVW $1069, R12
+ B callbackasm1(SB)
+ MOVW $1070, R12
+ B callbackasm1(SB)
+ MOVW $1071, R12
+ B callbackasm1(SB)
+ MOVW $1072, R12
+ B callbackasm1(SB)
+ MOVW $1073, R12
+ B callbackasm1(SB)
+ MOVW $1074, R12
+ B callbackasm1(SB)
+ MOVW $1075, R12
+ B callbackasm1(SB)
+ MOVW $1076, R12
+ B callbackasm1(SB)
+ MOVW $1077, R12
+ B callbackasm1(SB)
+ MOVW $1078, R12
+ B callbackasm1(SB)
+ MOVW $1079, R12
+ B callbackasm1(SB)
+ MOVW $1080, R12
+ B callbackasm1(SB)
+ MOVW $1081, R12
+ B callbackasm1(SB)
+ MOVW $1082, R12
+ B callbackasm1(SB)
+ MOVW $1083, R12
+ B callbackasm1(SB)
+ MOVW $1084, R12
+ B callbackasm1(SB)
+ MOVW $1085, R12
+ B callbackasm1(SB)
+ MOVW $1086, R12
+ B callbackasm1(SB)
+ MOVW $1087, R12
+ B callbackasm1(SB)
+ MOVW $1088, R12
+ B callbackasm1(SB)
+ MOVW $1089, R12
+ B callbackasm1(SB)
+ MOVW $1090, R12
+ B callbackasm1(SB)
+ MOVW $1091, R12
+ B callbackasm1(SB)
+ MOVW $1092, R12
+ B callbackasm1(SB)
+ MOVW $1093, R12
+ B callbackasm1(SB)
+ MOVW $1094, R12
+ B callbackasm1(SB)
+ MOVW $1095, R12
+ B callbackasm1(SB)
+ MOVW $1096, R12
+ B callbackasm1(SB)
+ MOVW $1097, R12
+ B callbackasm1(SB)
+ MOVW $1098, R12
+ B callbackasm1(SB)
+ MOVW $1099, R12
+ B callbackasm1(SB)
+ MOVW $1100, R12
+ B callbackasm1(SB)
+ MOVW $1101, R12
+ B callbackasm1(SB)
+ MOVW $1102, R12
+ B callbackasm1(SB)
+ MOVW $1103, R12
+ B callbackasm1(SB)
+ MOVW $1104, R12
+ B callbackasm1(SB)
+ MOVW $1105, R12
+ B callbackasm1(SB)
+ MOVW $1106, R12
+ B callbackasm1(SB)
+ MOVW $1107, R12
+ B callbackasm1(SB)
+ MOVW $1108, R12
+ B callbackasm1(SB)
+ MOVW $1109, R12
+ B callbackasm1(SB)
+ MOVW $1110, R12
+ B callbackasm1(SB)
+ MOVW $1111, R12
+ B callbackasm1(SB)
+ MOVW $1112, R12
+ B callbackasm1(SB)
+ MOVW $1113, R12
+ B callbackasm1(SB)
+ MOVW $1114, R12
+ B callbackasm1(SB)
+ MOVW $1115, R12
+ B callbackasm1(SB)
+ MOVW $1116, R12
+ B callbackasm1(SB)
+ MOVW $1117, R12
+ B callbackasm1(SB)
+ MOVW $1118, R12
+ B callbackasm1(SB)
+ MOVW $1119, R12
+ B callbackasm1(SB)
+ MOVW $1120, R12
+ B callbackasm1(SB)
+ MOVW $1121, R12
+ B callbackasm1(SB)
+ MOVW $1122, R12
+ B callbackasm1(SB)
+ MOVW $1123, R12
+ B callbackasm1(SB)
+ MOVW $1124, R12
+ B callbackasm1(SB)
+ MOVW $1125, R12
+ B callbackasm1(SB)
+ MOVW $1126, R12
+ B callbackasm1(SB)
+ MOVW $1127, R12
+ B callbackasm1(SB)
+ MOVW $1128, R12
+ B callbackasm1(SB)
+ MOVW $1129, R12
+ B callbackasm1(SB)
+ MOVW $1130, R12
+ B callbackasm1(SB)
+ MOVW $1131, R12
+ B callbackasm1(SB)
+ MOVW $1132, R12
+ B callbackasm1(SB)
+ MOVW $1133, R12
+ B callbackasm1(SB)
+ MOVW $1134, R12
+ B callbackasm1(SB)
+ MOVW $1135, R12
+ B callbackasm1(SB)
+ MOVW $1136, R12
+ B callbackasm1(SB)
+ MOVW $1137, R12
+ B callbackasm1(SB)
+ MOVW $1138, R12
+ B callbackasm1(SB)
+ MOVW $1139, R12
+ B callbackasm1(SB)
+ MOVW $1140, R12
+ B callbackasm1(SB)
+ MOVW $1141, R12
+ B callbackasm1(SB)
+ MOVW $1142, R12
+ B callbackasm1(SB)
+ MOVW $1143, R12
+ B callbackasm1(SB)
+ MOVW $1144, R12
+ B callbackasm1(SB)
+ MOVW $1145, R12
+ B callbackasm1(SB)
+ MOVW $1146, R12
+ B callbackasm1(SB)
+ MOVW $1147, R12
+ B callbackasm1(SB)
+ MOVW $1148, R12
+ B callbackasm1(SB)
+ MOVW $1149, R12
+ B callbackasm1(SB)
+ MOVW $1150, R12
+ B callbackasm1(SB)
+ MOVW $1151, R12
+ B callbackasm1(SB)
+ MOVW $1152, R12
+ B callbackasm1(SB)
+ MOVW $1153, R12
+ B callbackasm1(SB)
+ MOVW $1154, R12
+ B callbackasm1(SB)
+ MOVW $1155, R12
+ B callbackasm1(SB)
+ MOVW $1156, R12
+ B callbackasm1(SB)
+ MOVW $1157, R12
+ B callbackasm1(SB)
+ MOVW $1158, R12
+ B callbackasm1(SB)
+ MOVW $1159, R12
+ B callbackasm1(SB)
+ MOVW $1160, R12
+ B callbackasm1(SB)
+ MOVW $1161, R12
+ B callbackasm1(SB)
+ MOVW $1162, R12
+ B callbackasm1(SB)
+ MOVW $1163, R12
+ B callbackasm1(SB)
+ MOVW $1164, R12
+ B callbackasm1(SB)
+ MOVW $1165, R12
+ B callbackasm1(SB)
+ MOVW $1166, R12
+ B callbackasm1(SB)
+ MOVW $1167, R12
+ B callbackasm1(SB)
+ MOVW $1168, R12
+ B callbackasm1(SB)
+ MOVW $1169, R12
+ B callbackasm1(SB)
+ MOVW $1170, R12
+ B callbackasm1(SB)
+ MOVW $1171, R12
+ B callbackasm1(SB)
+ MOVW $1172, R12
+ B callbackasm1(SB)
+ MOVW $1173, R12
+ B callbackasm1(SB)
+ MOVW $1174, R12
+ B callbackasm1(SB)
+ MOVW $1175, R12
+ B callbackasm1(SB)
+ MOVW $1176, R12
+ B callbackasm1(SB)
+ MOVW $1177, R12
+ B callbackasm1(SB)
+ MOVW $1178, R12
+ B callbackasm1(SB)
+ MOVW $1179, R12
+ B callbackasm1(SB)
+ MOVW $1180, R12
+ B callbackasm1(SB)
+ MOVW $1181, R12
+ B callbackasm1(SB)
+ MOVW $1182, R12
+ B callbackasm1(SB)
+ MOVW $1183, R12
+ B callbackasm1(SB)
+ MOVW $1184, R12
+ B callbackasm1(SB)
+ MOVW $1185, R12
+ B callbackasm1(SB)
+ MOVW $1186, R12
+ B callbackasm1(SB)
+ MOVW $1187, R12
+ B callbackasm1(SB)
+ MOVW $1188, R12
+ B callbackasm1(SB)
+ MOVW $1189, R12
+ B callbackasm1(SB)
+ MOVW $1190, R12
+ B callbackasm1(SB)
+ MOVW $1191, R12
+ B callbackasm1(SB)
+ MOVW $1192, R12
+ B callbackasm1(SB)
+ MOVW $1193, R12
+ B callbackasm1(SB)
+ MOVW $1194, R12
+ B callbackasm1(SB)
+ MOVW $1195, R12
+ B callbackasm1(SB)
+ MOVW $1196, R12
+ B callbackasm1(SB)
+ MOVW $1197, R12
+ B callbackasm1(SB)
+ MOVW $1198, R12
+ B callbackasm1(SB)
+ MOVW $1199, R12
+ B callbackasm1(SB)
+ MOVW $1200, R12
+ B callbackasm1(SB)
+ MOVW $1201, R12
+ B callbackasm1(SB)
+ MOVW $1202, R12
+ B callbackasm1(SB)
+ MOVW $1203, R12
+ B callbackasm1(SB)
+ MOVW $1204, R12
+ B callbackasm1(SB)
+ MOVW $1205, R12
+ B callbackasm1(SB)
+ MOVW $1206, R12
+ B callbackasm1(SB)
+ MOVW $1207, R12
+ B callbackasm1(SB)
+ MOVW $1208, R12
+ B callbackasm1(SB)
+ MOVW $1209, R12
+ B callbackasm1(SB)
+ MOVW $1210, R12
+ B callbackasm1(SB)
+ MOVW $1211, R12
+ B callbackasm1(SB)
+ MOVW $1212, R12
+ B callbackasm1(SB)
+ MOVW $1213, R12
+ B callbackasm1(SB)
+ MOVW $1214, R12
+ B callbackasm1(SB)
+ MOVW $1215, R12
+ B callbackasm1(SB)
+ MOVW $1216, R12
+ B callbackasm1(SB)
+ MOVW $1217, R12
+ B callbackasm1(SB)
+ MOVW $1218, R12
+ B callbackasm1(SB)
+ MOVW $1219, R12
+ B callbackasm1(SB)
+ MOVW $1220, R12
+ B callbackasm1(SB)
+ MOVW $1221, R12
+ B callbackasm1(SB)
+ MOVW $1222, R12
+ B callbackasm1(SB)
+ MOVW $1223, R12
+ B callbackasm1(SB)
+ MOVW $1224, R12
+ B callbackasm1(SB)
+ MOVW $1225, R12
+ B callbackasm1(SB)
+ MOVW $1226, R12
+ B callbackasm1(SB)
+ MOVW $1227, R12
+ B callbackasm1(SB)
+ MOVW $1228, R12
+ B callbackasm1(SB)
+ MOVW $1229, R12
+ B callbackasm1(SB)
+ MOVW $1230, R12
+ B callbackasm1(SB)
+ MOVW $1231, R12
+ B callbackasm1(SB)
+ MOVW $1232, R12
+ B callbackasm1(SB)
+ MOVW $1233, R12
+ B callbackasm1(SB)
+ MOVW $1234, R12
+ B callbackasm1(SB)
+ MOVW $1235, R12
+ B callbackasm1(SB)
+ MOVW $1236, R12
+ B callbackasm1(SB)
+ MOVW $1237, R12
+ B callbackasm1(SB)
+ MOVW $1238, R12
+ B callbackasm1(SB)
+ MOVW $1239, R12
+ B callbackasm1(SB)
+ MOVW $1240, R12
+ B callbackasm1(SB)
+ MOVW $1241, R12
+ B callbackasm1(SB)
+ MOVW $1242, R12
+ B callbackasm1(SB)
+ MOVW $1243, R12
+ B callbackasm1(SB)
+ MOVW $1244, R12
+ B callbackasm1(SB)
+ MOVW $1245, R12
+ B callbackasm1(SB)
+ MOVW $1246, R12
+ B callbackasm1(SB)
+ MOVW $1247, R12
+ B callbackasm1(SB)
+ MOVW $1248, R12
+ B callbackasm1(SB)
+ MOVW $1249, R12
+ B callbackasm1(SB)
+ MOVW $1250, R12
+ B callbackasm1(SB)
+ MOVW $1251, R12
+ B callbackasm1(SB)
+ MOVW $1252, R12
+ B callbackasm1(SB)
+ MOVW $1253, R12
+ B callbackasm1(SB)
+ MOVW $1254, R12
+ B callbackasm1(SB)
+ MOVW $1255, R12
+ B callbackasm1(SB)
+ MOVW $1256, R12
+ B callbackasm1(SB)
+ MOVW $1257, R12
+ B callbackasm1(SB)
+ MOVW $1258, R12
+ B callbackasm1(SB)
+ MOVW $1259, R12
+ B callbackasm1(SB)
+ MOVW $1260, R12
+ B callbackasm1(SB)
+ MOVW $1261, R12
+ B callbackasm1(SB)
+ MOVW $1262, R12
+ B callbackasm1(SB)
+ MOVW $1263, R12
+ B callbackasm1(SB)
+ MOVW $1264, R12
+ B callbackasm1(SB)
+ MOVW $1265, R12
+ B callbackasm1(SB)
+ MOVW $1266, R12
+ B callbackasm1(SB)
+ MOVW $1267, R12
+ B callbackasm1(SB)
+ MOVW $1268, R12
+ B callbackasm1(SB)
+ MOVW $1269, R12
+ B callbackasm1(SB)
+ MOVW $1270, R12
+ B callbackasm1(SB)
+ MOVW $1271, R12
+ B callbackasm1(SB)
+ MOVW $1272, R12
+ B callbackasm1(SB)
+ MOVW $1273, R12
+ B callbackasm1(SB)
+ MOVW $1274, R12
+ B callbackasm1(SB)
+ MOVW $1275, R12
+ B callbackasm1(SB)
+ MOVW $1276, R12
+ B callbackasm1(SB)
+ MOVW $1277, R12
+ B callbackasm1(SB)
+ MOVW $1278, R12
+ B callbackasm1(SB)
+ MOVW $1279, R12
+ B callbackasm1(SB)
+ MOVW $1280, R12
+ B callbackasm1(SB)
+ MOVW $1281, R12
+ B callbackasm1(SB)
+ MOVW $1282, R12
+ B callbackasm1(SB)
+ MOVW $1283, R12
+ B callbackasm1(SB)
+ MOVW $1284, R12
+ B callbackasm1(SB)
+ MOVW $1285, R12
+ B callbackasm1(SB)
+ MOVW $1286, R12
+ B callbackasm1(SB)
+ MOVW $1287, R12
+ B callbackasm1(SB)
+ MOVW $1288, R12
+ B callbackasm1(SB)
+ MOVW $1289, R12
+ B callbackasm1(SB)
+ MOVW $1290, R12
+ B callbackasm1(SB)
+ MOVW $1291, R12
+ B callbackasm1(SB)
+ MOVW $1292, R12
+ B callbackasm1(SB)
+ MOVW $1293, R12
+ B callbackasm1(SB)
+ MOVW $1294, R12
+ B callbackasm1(SB)
+ MOVW $1295, R12
+ B callbackasm1(SB)
+ MOVW $1296, R12
+ B callbackasm1(SB)
+ MOVW $1297, R12
+ B callbackasm1(SB)
+ MOVW $1298, R12
+ B callbackasm1(SB)
+ MOVW $1299, R12
+ B callbackasm1(SB)
+ MOVW $1300, R12
+ B callbackasm1(SB)
+ MOVW $1301, R12
+ B callbackasm1(SB)
+ MOVW $1302, R12
+ B callbackasm1(SB)
+ MOVW $1303, R12
+ B callbackasm1(SB)
+ MOVW $1304, R12
+ B callbackasm1(SB)
+ MOVW $1305, R12
+ B callbackasm1(SB)
+ MOVW $1306, R12
+ B callbackasm1(SB)
+ MOVW $1307, R12
+ B callbackasm1(SB)
+ MOVW $1308, R12
+ B callbackasm1(SB)
+ MOVW $1309, R12
+ B callbackasm1(SB)
+ MOVW $1310, R12
+ B callbackasm1(SB)
+ MOVW $1311, R12
+ B callbackasm1(SB)
+ MOVW $1312, R12
+ B callbackasm1(SB)
+ MOVW $1313, R12
+ B callbackasm1(SB)
+ MOVW $1314, R12
+ B callbackasm1(SB)
+ MOVW $1315, R12
+ B callbackasm1(SB)
+ MOVW $1316, R12
+ B callbackasm1(SB)
+ MOVW $1317, R12
+ B callbackasm1(SB)
+ MOVW $1318, R12
+ B callbackasm1(SB)
+ MOVW $1319, R12
+ B callbackasm1(SB)
+ MOVW $1320, R12
+ B callbackasm1(SB)
+ MOVW $1321, R12
+ B callbackasm1(SB)
+ MOVW $1322, R12
+ B callbackasm1(SB)
+ MOVW $1323, R12
+ B callbackasm1(SB)
+ MOVW $1324, R12
+ B callbackasm1(SB)
+ MOVW $1325, R12
+ B callbackasm1(SB)
+ MOVW $1326, R12
+ B callbackasm1(SB)
+ MOVW $1327, R12
+ B callbackasm1(SB)
+ MOVW $1328, R12
+ B callbackasm1(SB)
+ MOVW $1329, R12
+ B callbackasm1(SB)
+ MOVW $1330, R12
+ B callbackasm1(SB)
+ MOVW $1331, R12
+ B callbackasm1(SB)
+ MOVW $1332, R12
+ B callbackasm1(SB)
+ MOVW $1333, R12
+ B callbackasm1(SB)
+ MOVW $1334, R12
+ B callbackasm1(SB)
+ MOVW $1335, R12
+ B callbackasm1(SB)
+ MOVW $1336, R12
+ B callbackasm1(SB)
+ MOVW $1337, R12
+ B callbackasm1(SB)
+ MOVW $1338, R12
+ B callbackasm1(SB)
+ MOVW $1339, R12
+ B callbackasm1(SB)
+ MOVW $1340, R12
+ B callbackasm1(SB)
+ MOVW $1341, R12
+ B callbackasm1(SB)
+ MOVW $1342, R12
+ B callbackasm1(SB)
+ MOVW $1343, R12
+ B callbackasm1(SB)
+ MOVW $1344, R12
+ B callbackasm1(SB)
+ MOVW $1345, R12
+ B callbackasm1(SB)
+ MOVW $1346, R12
+ B callbackasm1(SB)
+ MOVW $1347, R12
+ B callbackasm1(SB)
+ MOVW $1348, R12
+ B callbackasm1(SB)
+ MOVW $1349, R12
+ B callbackasm1(SB)
+ MOVW $1350, R12
+ B callbackasm1(SB)
+ MOVW $1351, R12
+ B callbackasm1(SB)
+ MOVW $1352, R12
+ B callbackasm1(SB)
+ MOVW $1353, R12
+ B callbackasm1(SB)
+ MOVW $1354, R12
+ B callbackasm1(SB)
+ MOVW $1355, R12
+ B callbackasm1(SB)
+ MOVW $1356, R12
+ B callbackasm1(SB)
+ MOVW $1357, R12
+ B callbackasm1(SB)
+ MOVW $1358, R12
+ B callbackasm1(SB)
+ MOVW $1359, R12
+ B callbackasm1(SB)
+ MOVW $1360, R12
+ B callbackasm1(SB)
+ MOVW $1361, R12
+ B callbackasm1(SB)
+ MOVW $1362, R12
+ B callbackasm1(SB)
+ MOVW $1363, R12
+ B callbackasm1(SB)
+ MOVW $1364, R12
+ B callbackasm1(SB)
+ MOVW $1365, R12
+ B callbackasm1(SB)
+ MOVW $1366, R12
+ B callbackasm1(SB)
+ MOVW $1367, R12
+ B callbackasm1(SB)
+ MOVW $1368, R12
+ B callbackasm1(SB)
+ MOVW $1369, R12
+ B callbackasm1(SB)
+ MOVW $1370, R12
+ B callbackasm1(SB)
+ MOVW $1371, R12
+ B callbackasm1(SB)
+ MOVW $1372, R12
+ B callbackasm1(SB)
+ MOVW $1373, R12
+ B callbackasm1(SB)
+ MOVW $1374, R12
+ B callbackasm1(SB)
+ MOVW $1375, R12
+ B callbackasm1(SB)
+ MOVW $1376, R12
+ B callbackasm1(SB)
+ MOVW $1377, R12
+ B callbackasm1(SB)
+ MOVW $1378, R12
+ B callbackasm1(SB)
+ MOVW $1379, R12
+ B callbackasm1(SB)
+ MOVW $1380, R12
+ B callbackasm1(SB)
+ MOVW $1381, R12
+ B callbackasm1(SB)
+ MOVW $1382, R12
+ B callbackasm1(SB)
+ MOVW $1383, R12
+ B callbackasm1(SB)
+ MOVW $1384, R12
+ B callbackasm1(SB)
+ MOVW $1385, R12
+ B callbackasm1(SB)
+ MOVW $1386, R12
+ B callbackasm1(SB)
+ MOVW $1387, R12
+ B callbackasm1(SB)
+ MOVW $1388, R12
+ B callbackasm1(SB)
+ MOVW $1389, R12
+ B callbackasm1(SB)
+ MOVW $1390, R12
+ B callbackasm1(SB)
+ MOVW $1391, R12
+ B callbackasm1(SB)
+ MOVW $1392, R12
+ B callbackasm1(SB)
+ MOVW $1393, R12
+ B callbackasm1(SB)
+ MOVW $1394, R12
+ B callbackasm1(SB)
+ MOVW $1395, R12
+ B callbackasm1(SB)
+ MOVW $1396, R12
+ B callbackasm1(SB)
+ MOVW $1397, R12
+ B callbackasm1(SB)
+ MOVW $1398, R12
+ B callbackasm1(SB)
+ MOVW $1399, R12
+ B callbackasm1(SB)
+ MOVW $1400, R12
+ B callbackasm1(SB)
+ MOVW $1401, R12
+ B callbackasm1(SB)
+ MOVW $1402, R12
+ B callbackasm1(SB)
+ MOVW $1403, R12
+ B callbackasm1(SB)
+ MOVW $1404, R12
+ B callbackasm1(SB)
+ MOVW $1405, R12
+ B callbackasm1(SB)
+ MOVW $1406, R12
+ B callbackasm1(SB)
+ MOVW $1407, R12
+ B callbackasm1(SB)
+ MOVW $1408, R12
+ B callbackasm1(SB)
+ MOVW $1409, R12
+ B callbackasm1(SB)
+ MOVW $1410, R12
+ B callbackasm1(SB)
+ MOVW $1411, R12
+ B callbackasm1(SB)
+ MOVW $1412, R12
+ B callbackasm1(SB)
+ MOVW $1413, R12
+ B callbackasm1(SB)
+ MOVW $1414, R12
+ B callbackasm1(SB)
+ MOVW $1415, R12
+ B callbackasm1(SB)
+ MOVW $1416, R12
+ B callbackasm1(SB)
+ MOVW $1417, R12
+ B callbackasm1(SB)
+ MOVW $1418, R12
+ B callbackasm1(SB)
+ MOVW $1419, R12
+ B callbackasm1(SB)
+ MOVW $1420, R12
+ B callbackasm1(SB)
+ MOVW $1421, R12
+ B callbackasm1(SB)
+ MOVW $1422, R12
+ B callbackasm1(SB)
+ MOVW $1423, R12
+ B callbackasm1(SB)
+ MOVW $1424, R12
+ B callbackasm1(SB)
+ MOVW $1425, R12
+ B callbackasm1(SB)
+ MOVW $1426, R12
+ B callbackasm1(SB)
+ MOVW $1427, R12
+ B callbackasm1(SB)
+ MOVW $1428, R12
+ B callbackasm1(SB)
+ MOVW $1429, R12
+ B callbackasm1(SB)
+ MOVW $1430, R12
+ B callbackasm1(SB)
+ MOVW $1431, R12
+ B callbackasm1(SB)
+ MOVW $1432, R12
+ B callbackasm1(SB)
+ MOVW $1433, R12
+ B callbackasm1(SB)
+ MOVW $1434, R12
+ B callbackasm1(SB)
+ MOVW $1435, R12
+ B callbackasm1(SB)
+ MOVW $1436, R12
+ B callbackasm1(SB)
+ MOVW $1437, R12
+ B callbackasm1(SB)
+ MOVW $1438, R12
+ B callbackasm1(SB)
+ MOVW $1439, R12
+ B callbackasm1(SB)
+ MOVW $1440, R12
+ B callbackasm1(SB)
+ MOVW $1441, R12
+ B callbackasm1(SB)
+ MOVW $1442, R12
+ B callbackasm1(SB)
+ MOVW $1443, R12
+ B callbackasm1(SB)
+ MOVW $1444, R12
+ B callbackasm1(SB)
+ MOVW $1445, R12
+ B callbackasm1(SB)
+ MOVW $1446, R12
+ B callbackasm1(SB)
+ MOVW $1447, R12
+ B callbackasm1(SB)
+ MOVW $1448, R12
+ B callbackasm1(SB)
+ MOVW $1449, R12
+ B callbackasm1(SB)
+ MOVW $1450, R12
+ B callbackasm1(SB)
+ MOVW $1451, R12
+ B callbackasm1(SB)
+ MOVW $1452, R12
+ B callbackasm1(SB)
+ MOVW $1453, R12
+ B callbackasm1(SB)
+ MOVW $1454, R12
+ B callbackasm1(SB)
+ MOVW $1455, R12
+ B callbackasm1(SB)
+ MOVW $1456, R12
+ B callbackasm1(SB)
+ MOVW $1457, R12
+ B callbackasm1(SB)
+ MOVW $1458, R12
+ B callbackasm1(SB)
+ MOVW $1459, R12
+ B callbackasm1(SB)
+ MOVW $1460, R12
+ B callbackasm1(SB)
+ MOVW $1461, R12
+ B callbackasm1(SB)
+ MOVW $1462, R12
+ B callbackasm1(SB)
+ MOVW $1463, R12
+ B callbackasm1(SB)
+ MOVW $1464, R12
+ B callbackasm1(SB)
+ MOVW $1465, R12
+ B callbackasm1(SB)
+ MOVW $1466, R12
+ B callbackasm1(SB)
+ MOVW $1467, R12
+ B callbackasm1(SB)
+ MOVW $1468, R12
+ B callbackasm1(SB)
+ MOVW $1469, R12
+ B callbackasm1(SB)
+ MOVW $1470, R12
+ B callbackasm1(SB)
+ MOVW $1471, R12
+ B callbackasm1(SB)
+ MOVW $1472, R12
+ B callbackasm1(SB)
+ MOVW $1473, R12
+ B callbackasm1(SB)
+ MOVW $1474, R12
+ B callbackasm1(SB)
+ MOVW $1475, R12
+ B callbackasm1(SB)
+ MOVW $1476, R12
+ B callbackasm1(SB)
+ MOVW $1477, R12
+ B callbackasm1(SB)
+ MOVW $1478, R12
+ B callbackasm1(SB)
+ MOVW $1479, R12
+ B callbackasm1(SB)
+ MOVW $1480, R12
+ B callbackasm1(SB)
+ MOVW $1481, R12
+ B callbackasm1(SB)
+ MOVW $1482, R12
+ B callbackasm1(SB)
+ MOVW $1483, R12
+ B callbackasm1(SB)
+ MOVW $1484, R12
+ B callbackasm1(SB)
+ MOVW $1485, R12
+ B callbackasm1(SB)
+ MOVW $1486, R12
+ B callbackasm1(SB)
+ MOVW $1487, R12
+ B callbackasm1(SB)
+ MOVW $1488, R12
+ B callbackasm1(SB)
+ MOVW $1489, R12
+ B callbackasm1(SB)
+ MOVW $1490, R12
+ B callbackasm1(SB)
+ MOVW $1491, R12
+ B callbackasm1(SB)
+ MOVW $1492, R12
+ B callbackasm1(SB)
+ MOVW $1493, R12
+ B callbackasm1(SB)
+ MOVW $1494, R12
+ B callbackasm1(SB)
+ MOVW $1495, R12
+ B callbackasm1(SB)
+ MOVW $1496, R12
+ B callbackasm1(SB)
+ MOVW $1497, R12
+ B callbackasm1(SB)
+ MOVW $1498, R12
+ B callbackasm1(SB)
+ MOVW $1499, R12
+ B callbackasm1(SB)
+ MOVW $1500, R12
+ B callbackasm1(SB)
+ MOVW $1501, R12
+ B callbackasm1(SB)
+ MOVW $1502, R12
+ B callbackasm1(SB)
+ MOVW $1503, R12
+ B callbackasm1(SB)
+ MOVW $1504, R12
+ B callbackasm1(SB)
+ MOVW $1505, R12
+ B callbackasm1(SB)
+ MOVW $1506, R12
+ B callbackasm1(SB)
+ MOVW $1507, R12
+ B callbackasm1(SB)
+ MOVW $1508, R12
+ B callbackasm1(SB)
+ MOVW $1509, R12
+ B callbackasm1(SB)
+ MOVW $1510, R12
+ B callbackasm1(SB)
+ MOVW $1511, R12
+ B callbackasm1(SB)
+ MOVW $1512, R12
+ B callbackasm1(SB)
+ MOVW $1513, R12
+ B callbackasm1(SB)
+ MOVW $1514, R12
+ B callbackasm1(SB)
+ MOVW $1515, R12
+ B callbackasm1(SB)
+ MOVW $1516, R12
+ B callbackasm1(SB)
+ MOVW $1517, R12
+ B callbackasm1(SB)
+ MOVW $1518, R12
+ B callbackasm1(SB)
+ MOVW $1519, R12
+ B callbackasm1(SB)
+ MOVW $1520, R12
+ B callbackasm1(SB)
+ MOVW $1521, R12
+ B callbackasm1(SB)
+ MOVW $1522, R12
+ B callbackasm1(SB)
+ MOVW $1523, R12
+ B callbackasm1(SB)
+ MOVW $1524, R12
+ B callbackasm1(SB)
+ MOVW $1525, R12
+ B callbackasm1(SB)
+ MOVW $1526, R12
+ B callbackasm1(SB)
+ MOVW $1527, R12
+ B callbackasm1(SB)
+ MOVW $1528, R12
+ B callbackasm1(SB)
+ MOVW $1529, R12
+ B callbackasm1(SB)
+ MOVW $1530, R12
+ B callbackasm1(SB)
+ MOVW $1531, R12
+ B callbackasm1(SB)
+ MOVW $1532, R12
+ B callbackasm1(SB)
+ MOVW $1533, R12
+ B callbackasm1(SB)
+ MOVW $1534, R12
+ B callbackasm1(SB)
+ MOVW $1535, R12
+ B callbackasm1(SB)
+ MOVW $1536, R12
+ B callbackasm1(SB)
+ MOVW $1537, R12
+ B callbackasm1(SB)
+ MOVW $1538, R12
+ B callbackasm1(SB)
+ MOVW $1539, R12
+ B callbackasm1(SB)
+ MOVW $1540, R12
+ B callbackasm1(SB)
+ MOVW $1541, R12
+ B callbackasm1(SB)
+ MOVW $1542, R12
+ B callbackasm1(SB)
+ MOVW $1543, R12
+ B callbackasm1(SB)
+ MOVW $1544, R12
+ B callbackasm1(SB)
+ MOVW $1545, R12
+ B callbackasm1(SB)
+ MOVW $1546, R12
+ B callbackasm1(SB)
+ MOVW $1547, R12
+ B callbackasm1(SB)
+ MOVW $1548, R12
+ B callbackasm1(SB)
+ MOVW $1549, R12
+ B callbackasm1(SB)
+ MOVW $1550, R12
+ B callbackasm1(SB)
+ MOVW $1551, R12
+ B callbackasm1(SB)
+ MOVW $1552, R12
+ B callbackasm1(SB)
+ MOVW $1553, R12
+ B callbackasm1(SB)
+ MOVW $1554, R12
+ B callbackasm1(SB)
+ MOVW $1555, R12
+ B callbackasm1(SB)
+ MOVW $1556, R12
+ B callbackasm1(SB)
+ MOVW $1557, R12
+ B callbackasm1(SB)
+ MOVW $1558, R12
+ B callbackasm1(SB)
+ MOVW $1559, R12
+ B callbackasm1(SB)
+ MOVW $1560, R12
+ B callbackasm1(SB)
+ MOVW $1561, R12
+ B callbackasm1(SB)
+ MOVW $1562, R12
+ B callbackasm1(SB)
+ MOVW $1563, R12
+ B callbackasm1(SB)
+ MOVW $1564, R12
+ B callbackasm1(SB)
+ MOVW $1565, R12
+ B callbackasm1(SB)
+ MOVW $1566, R12
+ B callbackasm1(SB)
+ MOVW $1567, R12
+ B callbackasm1(SB)
+ MOVW $1568, R12
+ B callbackasm1(SB)
+ MOVW $1569, R12
+ B callbackasm1(SB)
+ MOVW $1570, R12
+ B callbackasm1(SB)
+ MOVW $1571, R12
+ B callbackasm1(SB)
+ MOVW $1572, R12
+ B callbackasm1(SB)
+ MOVW $1573, R12
+ B callbackasm1(SB)
+ MOVW $1574, R12
+ B callbackasm1(SB)
+ MOVW $1575, R12
+ B callbackasm1(SB)
+ MOVW $1576, R12
+ B callbackasm1(SB)
+ MOVW $1577, R12
+ B callbackasm1(SB)
+ MOVW $1578, R12
+ B callbackasm1(SB)
+ MOVW $1579, R12
+ B callbackasm1(SB)
+ MOVW $1580, R12
+ B callbackasm1(SB)
+ MOVW $1581, R12
+ B callbackasm1(SB)
+ MOVW $1582, R12
+ B callbackasm1(SB)
+ MOVW $1583, R12
+ B callbackasm1(SB)
+ MOVW $1584, R12
+ B callbackasm1(SB)
+ MOVW $1585, R12
+ B callbackasm1(SB)
+ MOVW $1586, R12
+ B callbackasm1(SB)
+ MOVW $1587, R12
+ B callbackasm1(SB)
+ MOVW $1588, R12
+ B callbackasm1(SB)
+ MOVW $1589, R12
+ B callbackasm1(SB)
+ MOVW $1590, R12
+ B callbackasm1(SB)
+ MOVW $1591, R12
+ B callbackasm1(SB)
+ MOVW $1592, R12
+ B callbackasm1(SB)
+ MOVW $1593, R12
+ B callbackasm1(SB)
+ MOVW $1594, R12
+ B callbackasm1(SB)
+ MOVW $1595, R12
+ B callbackasm1(SB)
+ MOVW $1596, R12
+ B callbackasm1(SB)
+ MOVW $1597, R12
+ B callbackasm1(SB)
+ MOVW $1598, R12
+ B callbackasm1(SB)
+ MOVW $1599, R12
+ B callbackasm1(SB)
+ MOVW $1600, R12
+ B callbackasm1(SB)
+ MOVW $1601, R12
+ B callbackasm1(SB)
+ MOVW $1602, R12
+ B callbackasm1(SB)
+ MOVW $1603, R12
+ B callbackasm1(SB)
+ MOVW $1604, R12
+ B callbackasm1(SB)
+ MOVW $1605, R12
+ B callbackasm1(SB)
+ MOVW $1606, R12
+ B callbackasm1(SB)
+ MOVW $1607, R12
+ B callbackasm1(SB)
+ MOVW $1608, R12
+ B callbackasm1(SB)
+ MOVW $1609, R12
+ B callbackasm1(SB)
+ MOVW $1610, R12
+ B callbackasm1(SB)
+ MOVW $1611, R12
+ B callbackasm1(SB)
+ MOVW $1612, R12
+ B callbackasm1(SB)
+ MOVW $1613, R12
+ B callbackasm1(SB)
+ MOVW $1614, R12
+ B callbackasm1(SB)
+ MOVW $1615, R12
+ B callbackasm1(SB)
+ MOVW $1616, R12
+ B callbackasm1(SB)
+ MOVW $1617, R12
+ B callbackasm1(SB)
+ MOVW $1618, R12
+ B callbackasm1(SB)
+ MOVW $1619, R12
+ B callbackasm1(SB)
+ MOVW $1620, R12
+ B callbackasm1(SB)
+ MOVW $1621, R12
+ B callbackasm1(SB)
+ MOVW $1622, R12
+ B callbackasm1(SB)
+ MOVW $1623, R12
+ B callbackasm1(SB)
+ MOVW $1624, R12
+ B callbackasm1(SB)
+ MOVW $1625, R12
+ B callbackasm1(SB)
+ MOVW $1626, R12
+ B callbackasm1(SB)
+ MOVW $1627, R12
+ B callbackasm1(SB)
+ MOVW $1628, R12
+ B callbackasm1(SB)
+ MOVW $1629, R12
+ B callbackasm1(SB)
+ MOVW $1630, R12
+ B callbackasm1(SB)
+ MOVW $1631, R12
+ B callbackasm1(SB)
+ MOVW $1632, R12
+ B callbackasm1(SB)
+ MOVW $1633, R12
+ B callbackasm1(SB)
+ MOVW $1634, R12
+ B callbackasm1(SB)
+ MOVW $1635, R12
+ B callbackasm1(SB)
+ MOVW $1636, R12
+ B callbackasm1(SB)
+ MOVW $1637, R12
+ B callbackasm1(SB)
+ MOVW $1638, R12
+ B callbackasm1(SB)
+ MOVW $1639, R12
+ B callbackasm1(SB)
+ MOVW $1640, R12
+ B callbackasm1(SB)
+ MOVW $1641, R12
+ B callbackasm1(SB)
+ MOVW $1642, R12
+ B callbackasm1(SB)
+ MOVW $1643, R12
+ B callbackasm1(SB)
+ MOVW $1644, R12
+ B callbackasm1(SB)
+ MOVW $1645, R12
+ B callbackasm1(SB)
+ MOVW $1646, R12
+ B callbackasm1(SB)
+ MOVW $1647, R12
+ B callbackasm1(SB)
+ MOVW $1648, R12
+ B callbackasm1(SB)
+ MOVW $1649, R12
+ B callbackasm1(SB)
+ MOVW $1650, R12
+ B callbackasm1(SB)
+ MOVW $1651, R12
+ B callbackasm1(SB)
+ MOVW $1652, R12
+ B callbackasm1(SB)
+ MOVW $1653, R12
+ B callbackasm1(SB)
+ MOVW $1654, R12
+ B callbackasm1(SB)
+ MOVW $1655, R12
+ B callbackasm1(SB)
+ MOVW $1656, R12
+ B callbackasm1(SB)
+ MOVW $1657, R12
+ B callbackasm1(SB)
+ MOVW $1658, R12
+ B callbackasm1(SB)
+ MOVW $1659, R12
+ B callbackasm1(SB)
+ MOVW $1660, R12
+ B callbackasm1(SB)
+ MOVW $1661, R12
+ B callbackasm1(SB)
+ MOVW $1662, R12
+ B callbackasm1(SB)
+ MOVW $1663, R12
+ B callbackasm1(SB)
+ MOVW $1664, R12
+ B callbackasm1(SB)
+ MOVW $1665, R12
+ B callbackasm1(SB)
+ MOVW $1666, R12
+ B callbackasm1(SB)
+ MOVW $1667, R12
+ B callbackasm1(SB)
+ MOVW $1668, R12
+ B callbackasm1(SB)
+ MOVW $1669, R12
+ B callbackasm1(SB)
+ MOVW $1670, R12
+ B callbackasm1(SB)
+ MOVW $1671, R12
+ B callbackasm1(SB)
+ MOVW $1672, R12
+ B callbackasm1(SB)
+ MOVW $1673, R12
+ B callbackasm1(SB)
+ MOVW $1674, R12
+ B callbackasm1(SB)
+ MOVW $1675, R12
+ B callbackasm1(SB)
+ MOVW $1676, R12
+ B callbackasm1(SB)
+ MOVW $1677, R12
+ B callbackasm1(SB)
+ MOVW $1678, R12
+ B callbackasm1(SB)
+ MOVW $1679, R12
+ B callbackasm1(SB)
+ MOVW $1680, R12
+ B callbackasm1(SB)
+ MOVW $1681, R12
+ B callbackasm1(SB)
+ MOVW $1682, R12
+ B callbackasm1(SB)
+ MOVW $1683, R12
+ B callbackasm1(SB)
+ MOVW $1684, R12
+ B callbackasm1(SB)
+ MOVW $1685, R12
+ B callbackasm1(SB)
+ MOVW $1686, R12
+ B callbackasm1(SB)
+ MOVW $1687, R12
+ B callbackasm1(SB)
+ MOVW $1688, R12
+ B callbackasm1(SB)
+ MOVW $1689, R12
+ B callbackasm1(SB)
+ MOVW $1690, R12
+ B callbackasm1(SB)
+ MOVW $1691, R12
+ B callbackasm1(SB)
+ MOVW $1692, R12
+ B callbackasm1(SB)
+ MOVW $1693, R12
+ B callbackasm1(SB)
+ MOVW $1694, R12
+ B callbackasm1(SB)
+ MOVW $1695, R12
+ B callbackasm1(SB)
+ MOVW $1696, R12
+ B callbackasm1(SB)
+ MOVW $1697, R12
+ B callbackasm1(SB)
+ MOVW $1698, R12
+ B callbackasm1(SB)
+ MOVW $1699, R12
+ B callbackasm1(SB)
+ MOVW $1700, R12
+ B callbackasm1(SB)
+ MOVW $1701, R12
+ B callbackasm1(SB)
+ MOVW $1702, R12
+ B callbackasm1(SB)
+ MOVW $1703, R12
+ B callbackasm1(SB)
+ MOVW $1704, R12
+ B callbackasm1(SB)
+ MOVW $1705, R12
+ B callbackasm1(SB)
+ MOVW $1706, R12
+ B callbackasm1(SB)
+ MOVW $1707, R12
+ B callbackasm1(SB)
+ MOVW $1708, R12
+ B callbackasm1(SB)
+ MOVW $1709, R12
+ B callbackasm1(SB)
+ MOVW $1710, R12
+ B callbackasm1(SB)
+ MOVW $1711, R12
+ B callbackasm1(SB)
+ MOVW $1712, R12
+ B callbackasm1(SB)
+ MOVW $1713, R12
+ B callbackasm1(SB)
+ MOVW $1714, R12
+ B callbackasm1(SB)
+ MOVW $1715, R12
+ B callbackasm1(SB)
+ MOVW $1716, R12
+ B callbackasm1(SB)
+ MOVW $1717, R12
+ B callbackasm1(SB)
+ MOVW $1718, R12
+ B callbackasm1(SB)
+ MOVW $1719, R12
+ B callbackasm1(SB)
+ MOVW $1720, R12
+ B callbackasm1(SB)
+ MOVW $1721, R12
+ B callbackasm1(SB)
+ MOVW $1722, R12
+ B callbackasm1(SB)
+ MOVW $1723, R12
+ B callbackasm1(SB)
+ MOVW $1724, R12
+ B callbackasm1(SB)
+ MOVW $1725, R12
+ B callbackasm1(SB)
+ MOVW $1726, R12
+ B callbackasm1(SB)
+ MOVW $1727, R12
+ B callbackasm1(SB)
+ MOVW $1728, R12
+ B callbackasm1(SB)
+ MOVW $1729, R12
+ B callbackasm1(SB)
+ MOVW $1730, R12
+ B callbackasm1(SB)
+ MOVW $1731, R12
+ B callbackasm1(SB)
+ MOVW $1732, R12
+ B callbackasm1(SB)
+ MOVW $1733, R12
+ B callbackasm1(SB)
+ MOVW $1734, R12
+ B callbackasm1(SB)
+ MOVW $1735, R12
+ B callbackasm1(SB)
+ MOVW $1736, R12
+ B callbackasm1(SB)
+ MOVW $1737, R12
+ B callbackasm1(SB)
+ MOVW $1738, R12
+ B callbackasm1(SB)
+ MOVW $1739, R12
+ B callbackasm1(SB)
+ MOVW $1740, R12
+ B callbackasm1(SB)
+ MOVW $1741, R12
+ B callbackasm1(SB)
+ MOVW $1742, R12
+ B callbackasm1(SB)
+ MOVW $1743, R12
+ B callbackasm1(SB)
+ MOVW $1744, R12
+ B callbackasm1(SB)
+ MOVW $1745, R12
+ B callbackasm1(SB)
+ MOVW $1746, R12
+ B callbackasm1(SB)
+ MOVW $1747, R12
+ B callbackasm1(SB)
+ MOVW $1748, R12
+ B callbackasm1(SB)
+ MOVW $1749, R12
+ B callbackasm1(SB)
+ MOVW $1750, R12
+ B callbackasm1(SB)
+ MOVW $1751, R12
+ B callbackasm1(SB)
+ MOVW $1752, R12
+ B callbackasm1(SB)
+ MOVW $1753, R12
+ B callbackasm1(SB)
+ MOVW $1754, R12
+ B callbackasm1(SB)
+ MOVW $1755, R12
+ B callbackasm1(SB)
+ MOVW $1756, R12
+ B callbackasm1(SB)
+ MOVW $1757, R12
+ B callbackasm1(SB)
+ MOVW $1758, R12
+ B callbackasm1(SB)
+ MOVW $1759, R12
+ B callbackasm1(SB)
+ MOVW $1760, R12
+ B callbackasm1(SB)
+ MOVW $1761, R12
+ B callbackasm1(SB)
+ MOVW $1762, R12
+ B callbackasm1(SB)
+ MOVW $1763, R12
+ B callbackasm1(SB)
+ MOVW $1764, R12
+ B callbackasm1(SB)
+ MOVW $1765, R12
+ B callbackasm1(SB)
+ MOVW $1766, R12
+ B callbackasm1(SB)
+ MOVW $1767, R12
+ B callbackasm1(SB)
+ MOVW $1768, R12
+ B callbackasm1(SB)
+ MOVW $1769, R12
+ B callbackasm1(SB)
+ MOVW $1770, R12
+ B callbackasm1(SB)
+ MOVW $1771, R12
+ B callbackasm1(SB)
+ MOVW $1772, R12
+ B callbackasm1(SB)
+ MOVW $1773, R12
+ B callbackasm1(SB)
+ MOVW $1774, R12
+ B callbackasm1(SB)
+ MOVW $1775, R12
+ B callbackasm1(SB)
+ MOVW $1776, R12
+ B callbackasm1(SB)
+ MOVW $1777, R12
+ B callbackasm1(SB)
+ MOVW $1778, R12
+ B callbackasm1(SB)
+ MOVW $1779, R12
+ B callbackasm1(SB)
+ MOVW $1780, R12
+ B callbackasm1(SB)
+ MOVW $1781, R12
+ B callbackasm1(SB)
+ MOVW $1782, R12
+ B callbackasm1(SB)
+ MOVW $1783, R12
+ B callbackasm1(SB)
+ MOVW $1784, R12
+ B callbackasm1(SB)
+ MOVW $1785, R12
+ B callbackasm1(SB)
+ MOVW $1786, R12
+ B callbackasm1(SB)
+ MOVW $1787, R12
+ B callbackasm1(SB)
+ MOVW $1788, R12
+ B callbackasm1(SB)
+ MOVW $1789, R12
+ B callbackasm1(SB)
+ MOVW $1790, R12
+ B callbackasm1(SB)
+ MOVW $1791, R12
+ B callbackasm1(SB)
+ MOVW $1792, R12
+ B callbackasm1(SB)
+ MOVW $1793, R12
+ B callbackasm1(SB)
+ MOVW $1794, R12
+ B callbackasm1(SB)
+ MOVW $1795, R12
+ B callbackasm1(SB)
+ MOVW $1796, R12
+ B callbackasm1(SB)
+ MOVW $1797, R12
+ B callbackasm1(SB)
+ MOVW $1798, R12
+ B callbackasm1(SB)
+ MOVW $1799, R12
+ B callbackasm1(SB)
+ MOVW $1800, R12
+ B callbackasm1(SB)
+ MOVW $1801, R12
+ B callbackasm1(SB)
+ MOVW $1802, R12
+ B callbackasm1(SB)
+ MOVW $1803, R12
+ B callbackasm1(SB)
+ MOVW $1804, R12
+ B callbackasm1(SB)
+ MOVW $1805, R12
+ B callbackasm1(SB)
+ MOVW $1806, R12
+ B callbackasm1(SB)
+ MOVW $1807, R12
+ B callbackasm1(SB)
+ MOVW $1808, R12
+ B callbackasm1(SB)
+ MOVW $1809, R12
+ B callbackasm1(SB)
+ MOVW $1810, R12
+ B callbackasm1(SB)
+ MOVW $1811, R12
+ B callbackasm1(SB)
+ MOVW $1812, R12
+ B callbackasm1(SB)
+ MOVW $1813, R12
+ B callbackasm1(SB)
+ MOVW $1814, R12
+ B callbackasm1(SB)
+ MOVW $1815, R12
+ B callbackasm1(SB)
+ MOVW $1816, R12
+ B callbackasm1(SB)
+ MOVW $1817, R12
+ B callbackasm1(SB)
+ MOVW $1818, R12
+ B callbackasm1(SB)
+ MOVW $1819, R12
+ B callbackasm1(SB)
+ MOVW $1820, R12
+ B callbackasm1(SB)
+ MOVW $1821, R12
+ B callbackasm1(SB)
+ MOVW $1822, R12
+ B callbackasm1(SB)
+ MOVW $1823, R12
+ B callbackasm1(SB)
+ MOVW $1824, R12
+ B callbackasm1(SB)
+ MOVW $1825, R12
+ B callbackasm1(SB)
+ MOVW $1826, R12
+ B callbackasm1(SB)
+ MOVW $1827, R12
+ B callbackasm1(SB)
+ MOVW $1828, R12
+ B callbackasm1(SB)
+ MOVW $1829, R12
+ B callbackasm1(SB)
+ MOVW $1830, R12
+ B callbackasm1(SB)
+ MOVW $1831, R12
+ B callbackasm1(SB)
+ MOVW $1832, R12
+ B callbackasm1(SB)
+ MOVW $1833, R12
+ B callbackasm1(SB)
+ MOVW $1834, R12
+ B callbackasm1(SB)
+ MOVW $1835, R12
+ B callbackasm1(SB)
+ MOVW $1836, R12
+ B callbackasm1(SB)
+ MOVW $1837, R12
+ B callbackasm1(SB)
+ MOVW $1838, R12
+ B callbackasm1(SB)
+ MOVW $1839, R12
+ B callbackasm1(SB)
+ MOVW $1840, R12
+ B callbackasm1(SB)
+ MOVW $1841, R12
+ B callbackasm1(SB)
+ MOVW $1842, R12
+ B callbackasm1(SB)
+ MOVW $1843, R12
+ B callbackasm1(SB)
+ MOVW $1844, R12
+ B callbackasm1(SB)
+ MOVW $1845, R12
+ B callbackasm1(SB)
+ MOVW $1846, R12
+ B callbackasm1(SB)
+ MOVW $1847, R12
+ B callbackasm1(SB)
+ MOVW $1848, R12
+ B callbackasm1(SB)
+ MOVW $1849, R12
+ B callbackasm1(SB)
+ MOVW $1850, R12
+ B callbackasm1(SB)
+ MOVW $1851, R12
+ B callbackasm1(SB)
+ MOVW $1852, R12
+ B callbackasm1(SB)
+ MOVW $1853, R12
+ B callbackasm1(SB)
+ MOVW $1854, R12
+ B callbackasm1(SB)
+ MOVW $1855, R12
+ B callbackasm1(SB)
+ MOVW $1856, R12
+ B callbackasm1(SB)
+ MOVW $1857, R12
+ B callbackasm1(SB)
+ MOVW $1858, R12
+ B callbackasm1(SB)
+ MOVW $1859, R12
+ B callbackasm1(SB)
+ MOVW $1860, R12
+ B callbackasm1(SB)
+ MOVW $1861, R12
+ B callbackasm1(SB)
+ MOVW $1862, R12
+ B callbackasm1(SB)
+ MOVW $1863, R12
+ B callbackasm1(SB)
+ MOVW $1864, R12
+ B callbackasm1(SB)
+ MOVW $1865, R12
+ B callbackasm1(SB)
+ MOVW $1866, R12
+ B callbackasm1(SB)
+ MOVW $1867, R12
+ B callbackasm1(SB)
+ MOVW $1868, R12
+ B callbackasm1(SB)
+ MOVW $1869, R12
+ B callbackasm1(SB)
+ MOVW $1870, R12
+ B callbackasm1(SB)
+ MOVW $1871, R12
+ B callbackasm1(SB)
+ MOVW $1872, R12
+ B callbackasm1(SB)
+ MOVW $1873, R12
+ B callbackasm1(SB)
+ MOVW $1874, R12
+ B callbackasm1(SB)
+ MOVW $1875, R12
+ B callbackasm1(SB)
+ MOVW $1876, R12
+ B callbackasm1(SB)
+ MOVW $1877, R12
+ B callbackasm1(SB)
+ MOVW $1878, R12
+ B callbackasm1(SB)
+ MOVW $1879, R12
+ B callbackasm1(SB)
+ MOVW $1880, R12
+ B callbackasm1(SB)
+ MOVW $1881, R12
+ B callbackasm1(SB)
+ MOVW $1882, R12
+ B callbackasm1(SB)
+ MOVW $1883, R12
+ B callbackasm1(SB)
+ MOVW $1884, R12
+ B callbackasm1(SB)
+ MOVW $1885, R12
+ B callbackasm1(SB)
+ MOVW $1886, R12
+ B callbackasm1(SB)
+ MOVW $1887, R12
+ B callbackasm1(SB)
+ MOVW $1888, R12
+ B callbackasm1(SB)
+ MOVW $1889, R12
+ B callbackasm1(SB)
+ MOVW $1890, R12
+ B callbackasm1(SB)
+ MOVW $1891, R12
+ B callbackasm1(SB)
+ MOVW $1892, R12
+ B callbackasm1(SB)
+ MOVW $1893, R12
+ B callbackasm1(SB)
+ MOVW $1894, R12
+ B callbackasm1(SB)
+ MOVW $1895, R12
+ B callbackasm1(SB)
+ MOVW $1896, R12
+ B callbackasm1(SB)
+ MOVW $1897, R12
+ B callbackasm1(SB)
+ MOVW $1898, R12
+ B callbackasm1(SB)
+ MOVW $1899, R12
+ B callbackasm1(SB)
+ MOVW $1900, R12
+ B callbackasm1(SB)
+ MOVW $1901, R12
+ B callbackasm1(SB)
+ MOVW $1902, R12
+ B callbackasm1(SB)
+ MOVW $1903, R12
+ B callbackasm1(SB)
+ MOVW $1904, R12
+ B callbackasm1(SB)
+ MOVW $1905, R12
+ B callbackasm1(SB)
+ MOVW $1906, R12
+ B callbackasm1(SB)
+ MOVW $1907, R12
+ B callbackasm1(SB)
+ MOVW $1908, R12
+ B callbackasm1(SB)
+ MOVW $1909, R12
+ B callbackasm1(SB)
+ MOVW $1910, R12
+ B callbackasm1(SB)
+ MOVW $1911, R12
+ B callbackasm1(SB)
+ MOVW $1912, R12
+ B callbackasm1(SB)
+ MOVW $1913, R12
+ B callbackasm1(SB)
+ MOVW $1914, R12
+ B callbackasm1(SB)
+ MOVW $1915, R12
+ B callbackasm1(SB)
+ MOVW $1916, R12
+ B callbackasm1(SB)
+ MOVW $1917, R12
+ B callbackasm1(SB)
+ MOVW $1918, R12
+ B callbackasm1(SB)
+ MOVW $1919, R12
+ B callbackasm1(SB)
+ MOVW $1920, R12
+ B callbackasm1(SB)
+ MOVW $1921, R12
+ B callbackasm1(SB)
+ MOVW $1922, R12
+ B callbackasm1(SB)
+ MOVW $1923, R12
+ B callbackasm1(SB)
+ MOVW $1924, R12
+ B callbackasm1(SB)
+ MOVW $1925, R12
+ B callbackasm1(SB)
+ MOVW $1926, R12
+ B callbackasm1(SB)
+ MOVW $1927, R12
+ B callbackasm1(SB)
+ MOVW $1928, R12
+ B callbackasm1(SB)
+ MOVW $1929, R12
+ B callbackasm1(SB)
+ MOVW $1930, R12
+ B callbackasm1(SB)
+ MOVW $1931, R12
+ B callbackasm1(SB)
+ MOVW $1932, R12
+ B callbackasm1(SB)
+ MOVW $1933, R12
+ B callbackasm1(SB)
+ MOVW $1934, R12
+ B callbackasm1(SB)
+ MOVW $1935, R12
+ B callbackasm1(SB)
+ MOVW $1936, R12
+ B callbackasm1(SB)
+ MOVW $1937, R12
+ B callbackasm1(SB)
+ MOVW $1938, R12
+ B callbackasm1(SB)
+ MOVW $1939, R12
+ B callbackasm1(SB)
+ MOVW $1940, R12
+ B callbackasm1(SB)
+ MOVW $1941, R12
+ B callbackasm1(SB)
+ MOVW $1942, R12
+ B callbackasm1(SB)
+ MOVW $1943, R12
+ B callbackasm1(SB)
+ MOVW $1944, R12
+ B callbackasm1(SB)
+ MOVW $1945, R12
+ B callbackasm1(SB)
+ MOVW $1946, R12
+ B callbackasm1(SB)
+ MOVW $1947, R12
+ B callbackasm1(SB)
+ MOVW $1948, R12
+ B callbackasm1(SB)
+ MOVW $1949, R12
+ B callbackasm1(SB)
+ MOVW $1950, R12
+ B callbackasm1(SB)
+ MOVW $1951, R12
+ B callbackasm1(SB)
+ MOVW $1952, R12
+ B callbackasm1(SB)
+ MOVW $1953, R12
+ B callbackasm1(SB)
+ MOVW $1954, R12
+ B callbackasm1(SB)
+ MOVW $1955, R12
+ B callbackasm1(SB)
+ MOVW $1956, R12
+ B callbackasm1(SB)
+ MOVW $1957, R12
+ B callbackasm1(SB)
+ MOVW $1958, R12
+ B callbackasm1(SB)
+ MOVW $1959, R12
+ B callbackasm1(SB)
+ MOVW $1960, R12
+ B callbackasm1(SB)
+ MOVW $1961, R12
+ B callbackasm1(SB)
+ MOVW $1962, R12
+ B callbackasm1(SB)
+ MOVW $1963, R12
+ B callbackasm1(SB)
+ MOVW $1964, R12
+ B callbackasm1(SB)
+ MOVW $1965, R12
+ B callbackasm1(SB)
+ MOVW $1966, R12
+ B callbackasm1(SB)
+ MOVW $1967, R12
+ B callbackasm1(SB)
+ MOVW $1968, R12
+ B callbackasm1(SB)
+ MOVW $1969, R12
+ B callbackasm1(SB)
+ MOVW $1970, R12
+ B callbackasm1(SB)
+ MOVW $1971, R12
+ B callbackasm1(SB)
+ MOVW $1972, R12
+ B callbackasm1(SB)
+ MOVW $1973, R12
+ B callbackasm1(SB)
+ MOVW $1974, R12
+ B callbackasm1(SB)
+ MOVW $1975, R12
+ B callbackasm1(SB)
+ MOVW $1976, R12
+ B callbackasm1(SB)
+ MOVW $1977, R12
+ B callbackasm1(SB)
+ MOVW $1978, R12
+ B callbackasm1(SB)
+ MOVW $1979, R12
+ B callbackasm1(SB)
+ MOVW $1980, R12
+ B callbackasm1(SB)
+ MOVW $1981, R12
+ B callbackasm1(SB)
+ MOVW $1982, R12
+ B callbackasm1(SB)
+ MOVW $1983, R12
+ B callbackasm1(SB)
+ MOVW $1984, R12
+ B callbackasm1(SB)
+ MOVW $1985, R12
+ B callbackasm1(SB)
+ MOVW $1986, R12
+ B callbackasm1(SB)
+ MOVW $1987, R12
+ B callbackasm1(SB)
+ MOVW $1988, R12
+ B callbackasm1(SB)
+ MOVW $1989, R12
+ B callbackasm1(SB)
+ MOVW $1990, R12
+ B callbackasm1(SB)
+ MOVW $1991, R12
+ B callbackasm1(SB)
+ MOVW $1992, R12
+ B callbackasm1(SB)
+ MOVW $1993, R12
+ B callbackasm1(SB)
+ MOVW $1994, R12
+ B callbackasm1(SB)
+ MOVW $1995, R12
+ B callbackasm1(SB)
+ MOVW $1996, R12
+ B callbackasm1(SB)
+ MOVW $1997, R12
+ B callbackasm1(SB)
+ MOVW $1998, R12
+ B callbackasm1(SB)
+ MOVW $1999, R12
+ B callbackasm1(SB)
diff --git a/raymenu/vendor/github.com/ebitengine/purego/zcallback_arm64.s b/raymenu/vendor/github.com/ebitengine/purego/zcallback_arm64.s
new file mode 100644
index 0000000..3fea4af
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/zcallback_arm64.s
@@ -0,0 +1,4014 @@
+// Code generated by wincallback.go using 'go generate'. DO NOT EDIT.
+
+//go:build darwin || freebsd || linux || netbsd
+
+// External code calls into callbackasm at an offset corresponding
+// to the callback index. Callbackasm is a table of MOV and B instructions.
+// The MOV instruction loads R12 with the callback index, and the
+// B instruction branches to callbackasm1.
+// callbackasm1 takes the callback index from R12 and
+// indexes into an array that stores information about each callback.
+// It then calls the Go implementation for that callback.
+#include "textflag.h"
+
+TEXT callbackasm(SB), NOSPLIT|NOFRAME, $0
+ MOVD $0, R12
+ B callbackasm1(SB)
+ MOVD $1, R12
+ B callbackasm1(SB)
+ MOVD $2, R12
+ B callbackasm1(SB)
+ MOVD $3, R12
+ B callbackasm1(SB)
+ MOVD $4, R12
+ B callbackasm1(SB)
+ MOVD $5, R12
+ B callbackasm1(SB)
+ MOVD $6, R12
+ B callbackasm1(SB)
+ MOVD $7, R12
+ B callbackasm1(SB)
+ MOVD $8, R12
+ B callbackasm1(SB)
+ MOVD $9, R12
+ B callbackasm1(SB)
+ MOVD $10, R12
+ B callbackasm1(SB)
+ MOVD $11, R12
+ B callbackasm1(SB)
+ MOVD $12, R12
+ B callbackasm1(SB)
+ MOVD $13, R12
+ B callbackasm1(SB)
+ MOVD $14, R12
+ B callbackasm1(SB)
+ MOVD $15, R12
+ B callbackasm1(SB)
+ MOVD $16, R12
+ B callbackasm1(SB)
+ MOVD $17, R12
+ B callbackasm1(SB)
+ MOVD $18, R12
+ B callbackasm1(SB)
+ MOVD $19, R12
+ B callbackasm1(SB)
+ MOVD $20, R12
+ B callbackasm1(SB)
+ MOVD $21, R12
+ B callbackasm1(SB)
+ MOVD $22, R12
+ B callbackasm1(SB)
+ MOVD $23, R12
+ B callbackasm1(SB)
+ MOVD $24, R12
+ B callbackasm1(SB)
+ MOVD $25, R12
+ B callbackasm1(SB)
+ MOVD $26, R12
+ B callbackasm1(SB)
+ MOVD $27, R12
+ B callbackasm1(SB)
+ MOVD $28, R12
+ B callbackasm1(SB)
+ MOVD $29, R12
+ B callbackasm1(SB)
+ MOVD $30, R12
+ B callbackasm1(SB)
+ MOVD $31, R12
+ B callbackasm1(SB)
+ MOVD $32, R12
+ B callbackasm1(SB)
+ MOVD $33, R12
+ B callbackasm1(SB)
+ MOVD $34, R12
+ B callbackasm1(SB)
+ MOVD $35, R12
+ B callbackasm1(SB)
+ MOVD $36, R12
+ B callbackasm1(SB)
+ MOVD $37, R12
+ B callbackasm1(SB)
+ MOVD $38, R12
+ B callbackasm1(SB)
+ MOVD $39, R12
+ B callbackasm1(SB)
+ MOVD $40, R12
+ B callbackasm1(SB)
+ MOVD $41, R12
+ B callbackasm1(SB)
+ MOVD $42, R12
+ B callbackasm1(SB)
+ MOVD $43, R12
+ B callbackasm1(SB)
+ MOVD $44, R12
+ B callbackasm1(SB)
+ MOVD $45, R12
+ B callbackasm1(SB)
+ MOVD $46, R12
+ B callbackasm1(SB)
+ MOVD $47, R12
+ B callbackasm1(SB)
+ MOVD $48, R12
+ B callbackasm1(SB)
+ MOVD $49, R12
+ B callbackasm1(SB)
+ MOVD $50, R12
+ B callbackasm1(SB)
+ MOVD $51, R12
+ B callbackasm1(SB)
+ MOVD $52, R12
+ B callbackasm1(SB)
+ MOVD $53, R12
+ B callbackasm1(SB)
+ MOVD $54, R12
+ B callbackasm1(SB)
+ MOVD $55, R12
+ B callbackasm1(SB)
+ MOVD $56, R12
+ B callbackasm1(SB)
+ MOVD $57, R12
+ B callbackasm1(SB)
+ MOVD $58, R12
+ B callbackasm1(SB)
+ MOVD $59, R12
+ B callbackasm1(SB)
+ MOVD $60, R12
+ B callbackasm1(SB)
+ MOVD $61, R12
+ B callbackasm1(SB)
+ MOVD $62, R12
+ B callbackasm1(SB)
+ MOVD $63, R12
+ B callbackasm1(SB)
+ MOVD $64, R12
+ B callbackasm1(SB)
+ MOVD $65, R12
+ B callbackasm1(SB)
+ MOVD $66, R12
+ B callbackasm1(SB)
+ MOVD $67, R12
+ B callbackasm1(SB)
+ MOVD $68, R12
+ B callbackasm1(SB)
+ MOVD $69, R12
+ B callbackasm1(SB)
+ MOVD $70, R12
+ B callbackasm1(SB)
+ MOVD $71, R12
+ B callbackasm1(SB)
+ MOVD $72, R12
+ B callbackasm1(SB)
+ MOVD $73, R12
+ B callbackasm1(SB)
+ MOVD $74, R12
+ B callbackasm1(SB)
+ MOVD $75, R12
+ B callbackasm1(SB)
+ MOVD $76, R12
+ B callbackasm1(SB)
+ MOVD $77, R12
+ B callbackasm1(SB)
+ MOVD $78, R12
+ B callbackasm1(SB)
+ MOVD $79, R12
+ B callbackasm1(SB)
+ MOVD $80, R12
+ B callbackasm1(SB)
+ MOVD $81, R12
+ B callbackasm1(SB)
+ MOVD $82, R12
+ B callbackasm1(SB)
+ MOVD $83, R12
+ B callbackasm1(SB)
+ MOVD $84, R12
+ B callbackasm1(SB)
+ MOVD $85, R12
+ B callbackasm1(SB)
+ MOVD $86, R12
+ B callbackasm1(SB)
+ MOVD $87, R12
+ B callbackasm1(SB)
+ MOVD $88, R12
+ B callbackasm1(SB)
+ MOVD $89, R12
+ B callbackasm1(SB)
+ MOVD $90, R12
+ B callbackasm1(SB)
+ MOVD $91, R12
+ B callbackasm1(SB)
+ MOVD $92, R12
+ B callbackasm1(SB)
+ MOVD $93, R12
+ B callbackasm1(SB)
+ MOVD $94, R12
+ B callbackasm1(SB)
+ MOVD $95, R12
+ B callbackasm1(SB)
+ MOVD $96, R12
+ B callbackasm1(SB)
+ MOVD $97, R12
+ B callbackasm1(SB)
+ MOVD $98, R12
+ B callbackasm1(SB)
+ MOVD $99, R12
+ B callbackasm1(SB)
+ MOVD $100, R12
+ B callbackasm1(SB)
+ MOVD $101, R12
+ B callbackasm1(SB)
+ MOVD $102, R12
+ B callbackasm1(SB)
+ MOVD $103, R12
+ B callbackasm1(SB)
+ MOVD $104, R12
+ B callbackasm1(SB)
+ MOVD $105, R12
+ B callbackasm1(SB)
+ MOVD $106, R12
+ B callbackasm1(SB)
+ MOVD $107, R12
+ B callbackasm1(SB)
+ MOVD $108, R12
+ B callbackasm1(SB)
+ MOVD $109, R12
+ B callbackasm1(SB)
+ MOVD $110, R12
+ B callbackasm1(SB)
+ MOVD $111, R12
+ B callbackasm1(SB)
+ MOVD $112, R12
+ B callbackasm1(SB)
+ MOVD $113, R12
+ B callbackasm1(SB)
+ MOVD $114, R12
+ B callbackasm1(SB)
+ MOVD $115, R12
+ B callbackasm1(SB)
+ MOVD $116, R12
+ B callbackasm1(SB)
+ MOVD $117, R12
+ B callbackasm1(SB)
+ MOVD $118, R12
+ B callbackasm1(SB)
+ MOVD $119, R12
+ B callbackasm1(SB)
+ MOVD $120, R12
+ B callbackasm1(SB)
+ MOVD $121, R12
+ B callbackasm1(SB)
+ MOVD $122, R12
+ B callbackasm1(SB)
+ MOVD $123, R12
+ B callbackasm1(SB)
+ MOVD $124, R12
+ B callbackasm1(SB)
+ MOVD $125, R12
+ B callbackasm1(SB)
+ MOVD $126, R12
+ B callbackasm1(SB)
+ MOVD $127, R12
+ B callbackasm1(SB)
+ MOVD $128, R12
+ B callbackasm1(SB)
+ MOVD $129, R12
+ B callbackasm1(SB)
+ MOVD $130, R12
+ B callbackasm1(SB)
+ MOVD $131, R12
+ B callbackasm1(SB)
+ MOVD $132, R12
+ B callbackasm1(SB)
+ MOVD $133, R12
+ B callbackasm1(SB)
+ MOVD $134, R12
+ B callbackasm1(SB)
+ MOVD $135, R12
+ B callbackasm1(SB)
+ MOVD $136, R12
+ B callbackasm1(SB)
+ MOVD $137, R12
+ B callbackasm1(SB)
+ MOVD $138, R12
+ B callbackasm1(SB)
+ MOVD $139, R12
+ B callbackasm1(SB)
+ MOVD $140, R12
+ B callbackasm1(SB)
+ MOVD $141, R12
+ B callbackasm1(SB)
+ MOVD $142, R12
+ B callbackasm1(SB)
+ MOVD $143, R12
+ B callbackasm1(SB)
+ MOVD $144, R12
+ B callbackasm1(SB)
+ MOVD $145, R12
+ B callbackasm1(SB)
+ MOVD $146, R12
+ B callbackasm1(SB)
+ MOVD $147, R12
+ B callbackasm1(SB)
+ MOVD $148, R12
+ B callbackasm1(SB)
+ MOVD $149, R12
+ B callbackasm1(SB)
+ MOVD $150, R12
+ B callbackasm1(SB)
+ MOVD $151, R12
+ B callbackasm1(SB)
+ MOVD $152, R12
+ B callbackasm1(SB)
+ MOVD $153, R12
+ B callbackasm1(SB)
+ MOVD $154, R12
+ B callbackasm1(SB)
+ MOVD $155, R12
+ B callbackasm1(SB)
+ MOVD $156, R12
+ B callbackasm1(SB)
+ MOVD $157, R12
+ B callbackasm1(SB)
+ MOVD $158, R12
+ B callbackasm1(SB)
+ MOVD $159, R12
+ B callbackasm1(SB)
+ MOVD $160, R12
+ B callbackasm1(SB)
+ MOVD $161, R12
+ B callbackasm1(SB)
+ MOVD $162, R12
+ B callbackasm1(SB)
+ MOVD $163, R12
+ B callbackasm1(SB)
+ MOVD $164, R12
+ B callbackasm1(SB)
+ MOVD $165, R12
+ B callbackasm1(SB)
+ MOVD $166, R12
+ B callbackasm1(SB)
+ MOVD $167, R12
+ B callbackasm1(SB)
+ MOVD $168, R12
+ B callbackasm1(SB)
+ MOVD $169, R12
+ B callbackasm1(SB)
+ MOVD $170, R12
+ B callbackasm1(SB)
+ MOVD $171, R12
+ B callbackasm1(SB)
+ MOVD $172, R12
+ B callbackasm1(SB)
+ MOVD $173, R12
+ B callbackasm1(SB)
+ MOVD $174, R12
+ B callbackasm1(SB)
+ MOVD $175, R12
+ B callbackasm1(SB)
+ MOVD $176, R12
+ B callbackasm1(SB)
+ MOVD $177, R12
+ B callbackasm1(SB)
+ MOVD $178, R12
+ B callbackasm1(SB)
+ MOVD $179, R12
+ B callbackasm1(SB)
+ MOVD $180, R12
+ B callbackasm1(SB)
+ MOVD $181, R12
+ B callbackasm1(SB)
+ MOVD $182, R12
+ B callbackasm1(SB)
+ MOVD $183, R12
+ B callbackasm1(SB)
+ MOVD $184, R12
+ B callbackasm1(SB)
+ MOVD $185, R12
+ B callbackasm1(SB)
+ MOVD $186, R12
+ B callbackasm1(SB)
+ MOVD $187, R12
+ B callbackasm1(SB)
+ MOVD $188, R12
+ B callbackasm1(SB)
+ MOVD $189, R12
+ B callbackasm1(SB)
+ MOVD $190, R12
+ B callbackasm1(SB)
+ MOVD $191, R12
+ B callbackasm1(SB)
+ MOVD $192, R12
+ B callbackasm1(SB)
+ MOVD $193, R12
+ B callbackasm1(SB)
+ MOVD $194, R12
+ B callbackasm1(SB)
+ MOVD $195, R12
+ B callbackasm1(SB)
+ MOVD $196, R12
+ B callbackasm1(SB)
+ MOVD $197, R12
+ B callbackasm1(SB)
+ MOVD $198, R12
+ B callbackasm1(SB)
+ MOVD $199, R12
+ B callbackasm1(SB)
+ MOVD $200, R12
+ B callbackasm1(SB)
+ MOVD $201, R12
+ B callbackasm1(SB)
+ MOVD $202, R12
+ B callbackasm1(SB)
+ MOVD $203, R12
+ B callbackasm1(SB)
+ MOVD $204, R12
+ B callbackasm1(SB)
+ MOVD $205, R12
+ B callbackasm1(SB)
+ MOVD $206, R12
+ B callbackasm1(SB)
+ MOVD $207, R12
+ B callbackasm1(SB)
+ MOVD $208, R12
+ B callbackasm1(SB)
+ MOVD $209, R12
+ B callbackasm1(SB)
+ MOVD $210, R12
+ B callbackasm1(SB)
+ MOVD $211, R12
+ B callbackasm1(SB)
+ MOVD $212, R12
+ B callbackasm1(SB)
+ MOVD $213, R12
+ B callbackasm1(SB)
+ MOVD $214, R12
+ B callbackasm1(SB)
+ MOVD $215, R12
+ B callbackasm1(SB)
+ MOVD $216, R12
+ B callbackasm1(SB)
+ MOVD $217, R12
+ B callbackasm1(SB)
+ MOVD $218, R12
+ B callbackasm1(SB)
+ MOVD $219, R12
+ B callbackasm1(SB)
+ MOVD $220, R12
+ B callbackasm1(SB)
+ MOVD $221, R12
+ B callbackasm1(SB)
+ MOVD $222, R12
+ B callbackasm1(SB)
+ MOVD $223, R12
+ B callbackasm1(SB)
+ MOVD $224, R12
+ B callbackasm1(SB)
+ MOVD $225, R12
+ B callbackasm1(SB)
+ MOVD $226, R12
+ B callbackasm1(SB)
+ MOVD $227, R12
+ B callbackasm1(SB)
+ MOVD $228, R12
+ B callbackasm1(SB)
+ MOVD $229, R12
+ B callbackasm1(SB)
+ MOVD $230, R12
+ B callbackasm1(SB)
+ MOVD $231, R12
+ B callbackasm1(SB)
+ MOVD $232, R12
+ B callbackasm1(SB)
+ MOVD $233, R12
+ B callbackasm1(SB)
+ MOVD $234, R12
+ B callbackasm1(SB)
+ MOVD $235, R12
+ B callbackasm1(SB)
+ MOVD $236, R12
+ B callbackasm1(SB)
+ MOVD $237, R12
+ B callbackasm1(SB)
+ MOVD $238, R12
+ B callbackasm1(SB)
+ MOVD $239, R12
+ B callbackasm1(SB)
+ MOVD $240, R12
+ B callbackasm1(SB)
+ MOVD $241, R12
+ B callbackasm1(SB)
+ MOVD $242, R12
+ B callbackasm1(SB)
+ MOVD $243, R12
+ B callbackasm1(SB)
+ MOVD $244, R12
+ B callbackasm1(SB)
+ MOVD $245, R12
+ B callbackasm1(SB)
+ MOVD $246, R12
+ B callbackasm1(SB)
+ MOVD $247, R12
+ B callbackasm1(SB)
+ MOVD $248, R12
+ B callbackasm1(SB)
+ MOVD $249, R12
+ B callbackasm1(SB)
+ MOVD $250, R12
+ B callbackasm1(SB)
+ MOVD $251, R12
+ B callbackasm1(SB)
+ MOVD $252, R12
+ B callbackasm1(SB)
+ MOVD $253, R12
+ B callbackasm1(SB)
+ MOVD $254, R12
+ B callbackasm1(SB)
+ MOVD $255, R12
+ B callbackasm1(SB)
+ MOVD $256, R12
+ B callbackasm1(SB)
+ MOVD $257, R12
+ B callbackasm1(SB)
+ MOVD $258, R12
+ B callbackasm1(SB)
+ MOVD $259, R12
+ B callbackasm1(SB)
+ MOVD $260, R12
+ B callbackasm1(SB)
+ MOVD $261, R12
+ B callbackasm1(SB)
+ MOVD $262, R12
+ B callbackasm1(SB)
+ MOVD $263, R12
+ B callbackasm1(SB)
+ MOVD $264, R12
+ B callbackasm1(SB)
+ MOVD $265, R12
+ B callbackasm1(SB)
+ MOVD $266, R12
+ B callbackasm1(SB)
+ MOVD $267, R12
+ B callbackasm1(SB)
+ MOVD $268, R12
+ B callbackasm1(SB)
+ MOVD $269, R12
+ B callbackasm1(SB)
+ MOVD $270, R12
+ B callbackasm1(SB)
+ MOVD $271, R12
+ B callbackasm1(SB)
+ MOVD $272, R12
+ B callbackasm1(SB)
+ MOVD $273, R12
+ B callbackasm1(SB)
+ MOVD $274, R12
+ B callbackasm1(SB)
+ MOVD $275, R12
+ B callbackasm1(SB)
+ MOVD $276, R12
+ B callbackasm1(SB)
+ MOVD $277, R12
+ B callbackasm1(SB)
+ MOVD $278, R12
+ B callbackasm1(SB)
+ MOVD $279, R12
+ B callbackasm1(SB)
+ MOVD $280, R12
+ B callbackasm1(SB)
+ MOVD $281, R12
+ B callbackasm1(SB)
+ MOVD $282, R12
+ B callbackasm1(SB)
+ MOVD $283, R12
+ B callbackasm1(SB)
+ MOVD $284, R12
+ B callbackasm1(SB)
+ MOVD $285, R12
+ B callbackasm1(SB)
+ MOVD $286, R12
+ B callbackasm1(SB)
+ MOVD $287, R12
+ B callbackasm1(SB)
+ MOVD $288, R12
+ B callbackasm1(SB)
+ MOVD $289, R12
+ B callbackasm1(SB)
+ MOVD $290, R12
+ B callbackasm1(SB)
+ MOVD $291, R12
+ B callbackasm1(SB)
+ MOVD $292, R12
+ B callbackasm1(SB)
+ MOVD $293, R12
+ B callbackasm1(SB)
+ MOVD $294, R12
+ B callbackasm1(SB)
+ MOVD $295, R12
+ B callbackasm1(SB)
+ MOVD $296, R12
+ B callbackasm1(SB)
+ MOVD $297, R12
+ B callbackasm1(SB)
+ MOVD $298, R12
+ B callbackasm1(SB)
+ MOVD $299, R12
+ B callbackasm1(SB)
+ MOVD $300, R12
+ B callbackasm1(SB)
+ MOVD $301, R12
+ B callbackasm1(SB)
+ MOVD $302, R12
+ B callbackasm1(SB)
+ MOVD $303, R12
+ B callbackasm1(SB)
+ MOVD $304, R12
+ B callbackasm1(SB)
+ MOVD $305, R12
+ B callbackasm1(SB)
+ MOVD $306, R12
+ B callbackasm1(SB)
+ MOVD $307, R12
+ B callbackasm1(SB)
+ MOVD $308, R12
+ B callbackasm1(SB)
+ MOVD $309, R12
+ B callbackasm1(SB)
+ MOVD $310, R12
+ B callbackasm1(SB)
+ MOVD $311, R12
+ B callbackasm1(SB)
+ MOVD $312, R12
+ B callbackasm1(SB)
+ MOVD $313, R12
+ B callbackasm1(SB)
+ MOVD $314, R12
+ B callbackasm1(SB)
+ MOVD $315, R12
+ B callbackasm1(SB)
+ MOVD $316, R12
+ B callbackasm1(SB)
+ MOVD $317, R12
+ B callbackasm1(SB)
+ MOVD $318, R12
+ B callbackasm1(SB)
+ MOVD $319, R12
+ B callbackasm1(SB)
+ MOVD $320, R12
+ B callbackasm1(SB)
+ MOVD $321, R12
+ B callbackasm1(SB)
+ MOVD $322, R12
+ B callbackasm1(SB)
+ MOVD $323, R12
+ B callbackasm1(SB)
+ MOVD $324, R12
+ B callbackasm1(SB)
+ MOVD $325, R12
+ B callbackasm1(SB)
+ MOVD $326, R12
+ B callbackasm1(SB)
+ MOVD $327, R12
+ B callbackasm1(SB)
+ MOVD $328, R12
+ B callbackasm1(SB)
+ MOVD $329, R12
+ B callbackasm1(SB)
+ MOVD $330, R12
+ B callbackasm1(SB)
+ MOVD $331, R12
+ B callbackasm1(SB)
+ MOVD $332, R12
+ B callbackasm1(SB)
+ MOVD $333, R12
+ B callbackasm1(SB)
+ MOVD $334, R12
+ B callbackasm1(SB)
+ MOVD $335, R12
+ B callbackasm1(SB)
+ MOVD $336, R12
+ B callbackasm1(SB)
+ MOVD $337, R12
+ B callbackasm1(SB)
+ MOVD $338, R12
+ B callbackasm1(SB)
+ MOVD $339, R12
+ B callbackasm1(SB)
+ MOVD $340, R12
+ B callbackasm1(SB)
+ MOVD $341, R12
+ B callbackasm1(SB)
+ MOVD $342, R12
+ B callbackasm1(SB)
+ MOVD $343, R12
+ B callbackasm1(SB)
+ MOVD $344, R12
+ B callbackasm1(SB)
+ MOVD $345, R12
+ B callbackasm1(SB)
+ MOVD $346, R12
+ B callbackasm1(SB)
+ MOVD $347, R12
+ B callbackasm1(SB)
+ MOVD $348, R12
+ B callbackasm1(SB)
+ MOVD $349, R12
+ B callbackasm1(SB)
+ MOVD $350, R12
+ B callbackasm1(SB)
+ MOVD $351, R12
+ B callbackasm1(SB)
+ MOVD $352, R12
+ B callbackasm1(SB)
+ MOVD $353, R12
+ B callbackasm1(SB)
+ MOVD $354, R12
+ B callbackasm1(SB)
+ MOVD $355, R12
+ B callbackasm1(SB)
+ MOVD $356, R12
+ B callbackasm1(SB)
+ MOVD $357, R12
+ B callbackasm1(SB)
+ MOVD $358, R12
+ B callbackasm1(SB)
+ MOVD $359, R12
+ B callbackasm1(SB)
+ MOVD $360, R12
+ B callbackasm1(SB)
+ MOVD $361, R12
+ B callbackasm1(SB)
+ MOVD $362, R12
+ B callbackasm1(SB)
+ MOVD $363, R12
+ B callbackasm1(SB)
+ MOVD $364, R12
+ B callbackasm1(SB)
+ MOVD $365, R12
+ B callbackasm1(SB)
+ MOVD $366, R12
+ B callbackasm1(SB)
+ MOVD $367, R12
+ B callbackasm1(SB)
+ MOVD $368, R12
+ B callbackasm1(SB)
+ MOVD $369, R12
+ B callbackasm1(SB)
+ MOVD $370, R12
+ B callbackasm1(SB)
+ MOVD $371, R12
+ B callbackasm1(SB)
+ MOVD $372, R12
+ B callbackasm1(SB)
+ MOVD $373, R12
+ B callbackasm1(SB)
+ MOVD $374, R12
+ B callbackasm1(SB)
+ MOVD $375, R12
+ B callbackasm1(SB)
+ MOVD $376, R12
+ B callbackasm1(SB)
+ MOVD $377, R12
+ B callbackasm1(SB)
+ MOVD $378, R12
+ B callbackasm1(SB)
+ MOVD $379, R12
+ B callbackasm1(SB)
+ MOVD $380, R12
+ B callbackasm1(SB)
+ MOVD $381, R12
+ B callbackasm1(SB)
+ MOVD $382, R12
+ B callbackasm1(SB)
+ MOVD $383, R12
+ B callbackasm1(SB)
+ MOVD $384, R12
+ B callbackasm1(SB)
+ MOVD $385, R12
+ B callbackasm1(SB)
+ MOVD $386, R12
+ B callbackasm1(SB)
+ MOVD $387, R12
+ B callbackasm1(SB)
+ MOVD $388, R12
+ B callbackasm1(SB)
+ MOVD $389, R12
+ B callbackasm1(SB)
+ MOVD $390, R12
+ B callbackasm1(SB)
+ MOVD $391, R12
+ B callbackasm1(SB)
+ MOVD $392, R12
+ B callbackasm1(SB)
+ MOVD $393, R12
+ B callbackasm1(SB)
+ MOVD $394, R12
+ B callbackasm1(SB)
+ MOVD $395, R12
+ B callbackasm1(SB)
+ MOVD $396, R12
+ B callbackasm1(SB)
+ MOVD $397, R12
+ B callbackasm1(SB)
+ MOVD $398, R12
+ B callbackasm1(SB)
+ MOVD $399, R12
+ B callbackasm1(SB)
+ MOVD $400, R12
+ B callbackasm1(SB)
+ MOVD $401, R12
+ B callbackasm1(SB)
+ MOVD $402, R12
+ B callbackasm1(SB)
+ MOVD $403, R12
+ B callbackasm1(SB)
+ MOVD $404, R12
+ B callbackasm1(SB)
+ MOVD $405, R12
+ B callbackasm1(SB)
+ MOVD $406, R12
+ B callbackasm1(SB)
+ MOVD $407, R12
+ B callbackasm1(SB)
+ MOVD $408, R12
+ B callbackasm1(SB)
+ MOVD $409, R12
+ B callbackasm1(SB)
+ MOVD $410, R12
+ B callbackasm1(SB)
+ MOVD $411, R12
+ B callbackasm1(SB)
+ MOVD $412, R12
+ B callbackasm1(SB)
+ MOVD $413, R12
+ B callbackasm1(SB)
+ MOVD $414, R12
+ B callbackasm1(SB)
+ MOVD $415, R12
+ B callbackasm1(SB)
+ MOVD $416, R12
+ B callbackasm1(SB)
+ MOVD $417, R12
+ B callbackasm1(SB)
+ MOVD $418, R12
+ B callbackasm1(SB)
+ MOVD $419, R12
+ B callbackasm1(SB)
+ MOVD $420, R12
+ B callbackasm1(SB)
+ MOVD $421, R12
+ B callbackasm1(SB)
+ MOVD $422, R12
+ B callbackasm1(SB)
+ MOVD $423, R12
+ B callbackasm1(SB)
+ MOVD $424, R12
+ B callbackasm1(SB)
+ MOVD $425, R12
+ B callbackasm1(SB)
+ MOVD $426, R12
+ B callbackasm1(SB)
+ MOVD $427, R12
+ B callbackasm1(SB)
+ MOVD $428, R12
+ B callbackasm1(SB)
+ MOVD $429, R12
+ B callbackasm1(SB)
+ MOVD $430, R12
+ B callbackasm1(SB)
+ MOVD $431, R12
+ B callbackasm1(SB)
+ MOVD $432, R12
+ B callbackasm1(SB)
+ MOVD $433, R12
+ B callbackasm1(SB)
+ MOVD $434, R12
+ B callbackasm1(SB)
+ MOVD $435, R12
+ B callbackasm1(SB)
+ MOVD $436, R12
+ B callbackasm1(SB)
+ MOVD $437, R12
+ B callbackasm1(SB)
+ MOVD $438, R12
+ B callbackasm1(SB)
+ MOVD $439, R12
+ B callbackasm1(SB)
+ MOVD $440, R12
+ B callbackasm1(SB)
+ MOVD $441, R12
+ B callbackasm1(SB)
+ MOVD $442, R12
+ B callbackasm1(SB)
+ MOVD $443, R12
+ B callbackasm1(SB)
+ MOVD $444, R12
+ B callbackasm1(SB)
+ MOVD $445, R12
+ B callbackasm1(SB)
+ MOVD $446, R12
+ B callbackasm1(SB)
+ MOVD $447, R12
+ B callbackasm1(SB)
+ MOVD $448, R12
+ B callbackasm1(SB)
+ MOVD $449, R12
+ B callbackasm1(SB)
+ MOVD $450, R12
+ B callbackasm1(SB)
+ MOVD $451, R12
+ B callbackasm1(SB)
+ MOVD $452, R12
+ B callbackasm1(SB)
+ MOVD $453, R12
+ B callbackasm1(SB)
+ MOVD $454, R12
+ B callbackasm1(SB)
+ MOVD $455, R12
+ B callbackasm1(SB)
+ MOVD $456, R12
+ B callbackasm1(SB)
+ MOVD $457, R12
+ B callbackasm1(SB)
+ MOVD $458, R12
+ B callbackasm1(SB)
+ MOVD $459, R12
+ B callbackasm1(SB)
+ MOVD $460, R12
+ B callbackasm1(SB)
+ MOVD $461, R12
+ B callbackasm1(SB)
+ MOVD $462, R12
+ B callbackasm1(SB)
+ MOVD $463, R12
+ B callbackasm1(SB)
+ MOVD $464, R12
+ B callbackasm1(SB)
+ MOVD $465, R12
+ B callbackasm1(SB)
+ MOVD $466, R12
+ B callbackasm1(SB)
+ MOVD $467, R12
+ B callbackasm1(SB)
+ MOVD $468, R12
+ B callbackasm1(SB)
+ MOVD $469, R12
+ B callbackasm1(SB)
+ MOVD $470, R12
+ B callbackasm1(SB)
+ MOVD $471, R12
+ B callbackasm1(SB)
+ MOVD $472, R12
+ B callbackasm1(SB)
+ MOVD $473, R12
+ B callbackasm1(SB)
+ MOVD $474, R12
+ B callbackasm1(SB)
+ MOVD $475, R12
+ B callbackasm1(SB)
+ MOVD $476, R12
+ B callbackasm1(SB)
+ MOVD $477, R12
+ B callbackasm1(SB)
+ MOVD $478, R12
+ B callbackasm1(SB)
+ MOVD $479, R12
+ B callbackasm1(SB)
+ MOVD $480, R12
+ B callbackasm1(SB)
+ MOVD $481, R12
+ B callbackasm1(SB)
+ MOVD $482, R12
+ B callbackasm1(SB)
+ MOVD $483, R12
+ B callbackasm1(SB)
+ MOVD $484, R12
+ B callbackasm1(SB)
+ MOVD $485, R12
+ B callbackasm1(SB)
+ MOVD $486, R12
+ B callbackasm1(SB)
+ MOVD $487, R12
+ B callbackasm1(SB)
+ MOVD $488, R12
+ B callbackasm1(SB)
+ MOVD $489, R12
+ B callbackasm1(SB)
+ MOVD $490, R12
+ B callbackasm1(SB)
+ MOVD $491, R12
+ B callbackasm1(SB)
+ MOVD $492, R12
+ B callbackasm1(SB)
+ MOVD $493, R12
+ B callbackasm1(SB)
+ MOVD $494, R12
+ B callbackasm1(SB)
+ MOVD $495, R12
+ B callbackasm1(SB)
+ MOVD $496, R12
+ B callbackasm1(SB)
+ MOVD $497, R12
+ B callbackasm1(SB)
+ MOVD $498, R12
+ B callbackasm1(SB)
+ MOVD $499, R12
+ B callbackasm1(SB)
+ MOVD $500, R12
+ B callbackasm1(SB)
+ MOVD $501, R12
+ B callbackasm1(SB)
+ MOVD $502, R12
+ B callbackasm1(SB)
+ MOVD $503, R12
+ B callbackasm1(SB)
+ MOVD $504, R12
+ B callbackasm1(SB)
+ MOVD $505, R12
+ B callbackasm1(SB)
+ MOVD $506, R12
+ B callbackasm1(SB)
+ MOVD $507, R12
+ B callbackasm1(SB)
+ MOVD $508, R12
+ B callbackasm1(SB)
+ MOVD $509, R12
+ B callbackasm1(SB)
+ MOVD $510, R12
+ B callbackasm1(SB)
+ MOVD $511, R12
+ B callbackasm1(SB)
+ MOVD $512, R12
+ B callbackasm1(SB)
+ MOVD $513, R12
+ B callbackasm1(SB)
+ MOVD $514, R12
+ B callbackasm1(SB)
+ MOVD $515, R12
+ B callbackasm1(SB)
+ MOVD $516, R12
+ B callbackasm1(SB)
+ MOVD $517, R12
+ B callbackasm1(SB)
+ MOVD $518, R12
+ B callbackasm1(SB)
+ MOVD $519, R12
+ B callbackasm1(SB)
+ MOVD $520, R12
+ B callbackasm1(SB)
+ MOVD $521, R12
+ B callbackasm1(SB)
+ MOVD $522, R12
+ B callbackasm1(SB)
+ MOVD $523, R12
+ B callbackasm1(SB)
+ MOVD $524, R12
+ B callbackasm1(SB)
+ MOVD $525, R12
+ B callbackasm1(SB)
+ MOVD $526, R12
+ B callbackasm1(SB)
+ MOVD $527, R12
+ B callbackasm1(SB)
+ MOVD $528, R12
+ B callbackasm1(SB)
+ MOVD $529, R12
+ B callbackasm1(SB)
+ MOVD $530, R12
+ B callbackasm1(SB)
+ MOVD $531, R12
+ B callbackasm1(SB)
+ MOVD $532, R12
+ B callbackasm1(SB)
+ MOVD $533, R12
+ B callbackasm1(SB)
+ MOVD $534, R12
+ B callbackasm1(SB)
+ MOVD $535, R12
+ B callbackasm1(SB)
+ MOVD $536, R12
+ B callbackasm1(SB)
+ MOVD $537, R12
+ B callbackasm1(SB)
+ MOVD $538, R12
+ B callbackasm1(SB)
+ MOVD $539, R12
+ B callbackasm1(SB)
+ MOVD $540, R12
+ B callbackasm1(SB)
+ MOVD $541, R12
+ B callbackasm1(SB)
+ MOVD $542, R12
+ B callbackasm1(SB)
+ MOVD $543, R12
+ B callbackasm1(SB)
+ MOVD $544, R12
+ B callbackasm1(SB)
+ MOVD $545, R12
+ B callbackasm1(SB)
+ MOVD $546, R12
+ B callbackasm1(SB)
+ MOVD $547, R12
+ B callbackasm1(SB)
+ MOVD $548, R12
+ B callbackasm1(SB)
+ MOVD $549, R12
+ B callbackasm1(SB)
+ MOVD $550, R12
+ B callbackasm1(SB)
+ MOVD $551, R12
+ B callbackasm1(SB)
+ MOVD $552, R12
+ B callbackasm1(SB)
+ MOVD $553, R12
+ B callbackasm1(SB)
+ MOVD $554, R12
+ B callbackasm1(SB)
+ MOVD $555, R12
+ B callbackasm1(SB)
+ MOVD $556, R12
+ B callbackasm1(SB)
+ MOVD $557, R12
+ B callbackasm1(SB)
+ MOVD $558, R12
+ B callbackasm1(SB)
+ MOVD $559, R12
+ B callbackasm1(SB)
+ MOVD $560, R12
+ B callbackasm1(SB)
+ MOVD $561, R12
+ B callbackasm1(SB)
+ MOVD $562, R12
+ B callbackasm1(SB)
+ MOVD $563, R12
+ B callbackasm1(SB)
+ MOVD $564, R12
+ B callbackasm1(SB)
+ MOVD $565, R12
+ B callbackasm1(SB)
+ MOVD $566, R12
+ B callbackasm1(SB)
+ MOVD $567, R12
+ B callbackasm1(SB)
+ MOVD $568, R12
+ B callbackasm1(SB)
+ MOVD $569, R12
+ B callbackasm1(SB)
+ MOVD $570, R12
+ B callbackasm1(SB)
+ MOVD $571, R12
+ B callbackasm1(SB)
+ MOVD $572, R12
+ B callbackasm1(SB)
+ MOVD $573, R12
+ B callbackasm1(SB)
+ MOVD $574, R12
+ B callbackasm1(SB)
+ MOVD $575, R12
+ B callbackasm1(SB)
+ MOVD $576, R12
+ B callbackasm1(SB)
+ MOVD $577, R12
+ B callbackasm1(SB)
+ MOVD $578, R12
+ B callbackasm1(SB)
+ MOVD $579, R12
+ B callbackasm1(SB)
+ MOVD $580, R12
+ B callbackasm1(SB)
+ MOVD $581, R12
+ B callbackasm1(SB)
+ MOVD $582, R12
+ B callbackasm1(SB)
+ MOVD $583, R12
+ B callbackasm1(SB)
+ MOVD $584, R12
+ B callbackasm1(SB)
+ MOVD $585, R12
+ B callbackasm1(SB)
+ MOVD $586, R12
+ B callbackasm1(SB)
+ MOVD $587, R12
+ B callbackasm1(SB)
+ MOVD $588, R12
+ B callbackasm1(SB)
+ MOVD $589, R12
+ B callbackasm1(SB)
+ MOVD $590, R12
+ B callbackasm1(SB)
+ MOVD $591, R12
+ B callbackasm1(SB)
+ MOVD $592, R12
+ B callbackasm1(SB)
+ MOVD $593, R12
+ B callbackasm1(SB)
+ MOVD $594, R12
+ B callbackasm1(SB)
+ MOVD $595, R12
+ B callbackasm1(SB)
+ MOVD $596, R12
+ B callbackasm1(SB)
+ MOVD $597, R12
+ B callbackasm1(SB)
+ MOVD $598, R12
+ B callbackasm1(SB)
+ MOVD $599, R12
+ B callbackasm1(SB)
+ MOVD $600, R12
+ B callbackasm1(SB)
+ MOVD $601, R12
+ B callbackasm1(SB)
+ MOVD $602, R12
+ B callbackasm1(SB)
+ MOVD $603, R12
+ B callbackasm1(SB)
+ MOVD $604, R12
+ B callbackasm1(SB)
+ MOVD $605, R12
+ B callbackasm1(SB)
+ MOVD $606, R12
+ B callbackasm1(SB)
+ MOVD $607, R12
+ B callbackasm1(SB)
+ MOVD $608, R12
+ B callbackasm1(SB)
+ MOVD $609, R12
+ B callbackasm1(SB)
+ MOVD $610, R12
+ B callbackasm1(SB)
+ MOVD $611, R12
+ B callbackasm1(SB)
+ MOVD $612, R12
+ B callbackasm1(SB)
+ MOVD $613, R12
+ B callbackasm1(SB)
+ MOVD $614, R12
+ B callbackasm1(SB)
+ MOVD $615, R12
+ B callbackasm1(SB)
+ MOVD $616, R12
+ B callbackasm1(SB)
+ MOVD $617, R12
+ B callbackasm1(SB)
+ MOVD $618, R12
+ B callbackasm1(SB)
+ MOVD $619, R12
+ B callbackasm1(SB)
+ MOVD $620, R12
+ B callbackasm1(SB)
+ MOVD $621, R12
+ B callbackasm1(SB)
+ MOVD $622, R12
+ B callbackasm1(SB)
+ MOVD $623, R12
+ B callbackasm1(SB)
+ MOVD $624, R12
+ B callbackasm1(SB)
+ MOVD $625, R12
+ B callbackasm1(SB)
+ MOVD $626, R12
+ B callbackasm1(SB)
+ MOVD $627, R12
+ B callbackasm1(SB)
+ MOVD $628, R12
+ B callbackasm1(SB)
+ MOVD $629, R12
+ B callbackasm1(SB)
+ MOVD $630, R12
+ B callbackasm1(SB)
+ MOVD $631, R12
+ B callbackasm1(SB)
+ MOVD $632, R12
+ B callbackasm1(SB)
+ MOVD $633, R12
+ B callbackasm1(SB)
+ MOVD $634, R12
+ B callbackasm1(SB)
+ MOVD $635, R12
+ B callbackasm1(SB)
+ MOVD $636, R12
+ B callbackasm1(SB)
+ MOVD $637, R12
+ B callbackasm1(SB)
+ MOVD $638, R12
+ B callbackasm1(SB)
+ MOVD $639, R12
+ B callbackasm1(SB)
+ MOVD $640, R12
+ B callbackasm1(SB)
+ MOVD $641, R12
+ B callbackasm1(SB)
+ MOVD $642, R12
+ B callbackasm1(SB)
+ MOVD $643, R12
+ B callbackasm1(SB)
+ MOVD $644, R12
+ B callbackasm1(SB)
+ MOVD $645, R12
+ B callbackasm1(SB)
+ MOVD $646, R12
+ B callbackasm1(SB)
+ MOVD $647, R12
+ B callbackasm1(SB)
+ MOVD $648, R12
+ B callbackasm1(SB)
+ MOVD $649, R12
+ B callbackasm1(SB)
+ MOVD $650, R12
+ B callbackasm1(SB)
+ MOVD $651, R12
+ B callbackasm1(SB)
+ MOVD $652, R12
+ B callbackasm1(SB)
+ MOVD $653, R12
+ B callbackasm1(SB)
+ MOVD $654, R12
+ B callbackasm1(SB)
+ MOVD $655, R12
+ B callbackasm1(SB)
+ MOVD $656, R12
+ B callbackasm1(SB)
+ MOVD $657, R12
+ B callbackasm1(SB)
+ MOVD $658, R12
+ B callbackasm1(SB)
+ MOVD $659, R12
+ B callbackasm1(SB)
+ MOVD $660, R12
+ B callbackasm1(SB)
+ MOVD $661, R12
+ B callbackasm1(SB)
+ MOVD $662, R12
+ B callbackasm1(SB)
+ MOVD $663, R12
+ B callbackasm1(SB)
+ MOVD $664, R12
+ B callbackasm1(SB)
+ MOVD $665, R12
+ B callbackasm1(SB)
+ MOVD $666, R12
+ B callbackasm1(SB)
+ MOVD $667, R12
+ B callbackasm1(SB)
+ MOVD $668, R12
+ B callbackasm1(SB)
+ MOVD $669, R12
+ B callbackasm1(SB)
+ MOVD $670, R12
+ B callbackasm1(SB)
+ MOVD $671, R12
+ B callbackasm1(SB)
+ MOVD $672, R12
+ B callbackasm1(SB)
+ MOVD $673, R12
+ B callbackasm1(SB)
+ MOVD $674, R12
+ B callbackasm1(SB)
+ MOVD $675, R12
+ B callbackasm1(SB)
+ MOVD $676, R12
+ B callbackasm1(SB)
+ MOVD $677, R12
+ B callbackasm1(SB)
+ MOVD $678, R12
+ B callbackasm1(SB)
+ MOVD $679, R12
+ B callbackasm1(SB)
+ MOVD $680, R12
+ B callbackasm1(SB)
+ MOVD $681, R12
+ B callbackasm1(SB)
+ MOVD $682, R12
+ B callbackasm1(SB)
+ MOVD $683, R12
+ B callbackasm1(SB)
+ MOVD $684, R12
+ B callbackasm1(SB)
+ MOVD $685, R12
+ B callbackasm1(SB)
+ MOVD $686, R12
+ B callbackasm1(SB)
+ MOVD $687, R12
+ B callbackasm1(SB)
+ MOVD $688, R12
+ B callbackasm1(SB)
+ MOVD $689, R12
+ B callbackasm1(SB)
+ MOVD $690, R12
+ B callbackasm1(SB)
+ MOVD $691, R12
+ B callbackasm1(SB)
+ MOVD $692, R12
+ B callbackasm1(SB)
+ MOVD $693, R12
+ B callbackasm1(SB)
+ MOVD $694, R12
+ B callbackasm1(SB)
+ MOVD $695, R12
+ B callbackasm1(SB)
+ MOVD $696, R12
+ B callbackasm1(SB)
+ MOVD $697, R12
+ B callbackasm1(SB)
+ MOVD $698, R12
+ B callbackasm1(SB)
+ MOVD $699, R12
+ B callbackasm1(SB)
+ MOVD $700, R12
+ B callbackasm1(SB)
+ MOVD $701, R12
+ B callbackasm1(SB)
+ MOVD $702, R12
+ B callbackasm1(SB)
+ MOVD $703, R12
+ B callbackasm1(SB)
+ MOVD $704, R12
+ B callbackasm1(SB)
+ MOVD $705, R12
+ B callbackasm1(SB)
+ MOVD $706, R12
+ B callbackasm1(SB)
+ MOVD $707, R12
+ B callbackasm1(SB)
+ MOVD $708, R12
+ B callbackasm1(SB)
+ MOVD $709, R12
+ B callbackasm1(SB)
+ MOVD $710, R12
+ B callbackasm1(SB)
+ MOVD $711, R12
+ B callbackasm1(SB)
+ MOVD $712, R12
+ B callbackasm1(SB)
+ MOVD $713, R12
+ B callbackasm1(SB)
+ MOVD $714, R12
+ B callbackasm1(SB)
+ MOVD $715, R12
+ B callbackasm1(SB)
+ MOVD $716, R12
+ B callbackasm1(SB)
+ MOVD $717, R12
+ B callbackasm1(SB)
+ MOVD $718, R12
+ B callbackasm1(SB)
+ MOVD $719, R12
+ B callbackasm1(SB)
+ MOVD $720, R12
+ B callbackasm1(SB)
+ MOVD $721, R12
+ B callbackasm1(SB)
+ MOVD $722, R12
+ B callbackasm1(SB)
+ MOVD $723, R12
+ B callbackasm1(SB)
+ MOVD $724, R12
+ B callbackasm1(SB)
+ MOVD $725, R12
+ B callbackasm1(SB)
+ MOVD $726, R12
+ B callbackasm1(SB)
+ MOVD $727, R12
+ B callbackasm1(SB)
+ MOVD $728, R12
+ B callbackasm1(SB)
+ MOVD $729, R12
+ B callbackasm1(SB)
+ MOVD $730, R12
+ B callbackasm1(SB)
+ MOVD $731, R12
+ B callbackasm1(SB)
+ MOVD $732, R12
+ B callbackasm1(SB)
+ MOVD $733, R12
+ B callbackasm1(SB)
+ MOVD $734, R12
+ B callbackasm1(SB)
+ MOVD $735, R12
+ B callbackasm1(SB)
+ MOVD $736, R12
+ B callbackasm1(SB)
+ MOVD $737, R12
+ B callbackasm1(SB)
+ MOVD $738, R12
+ B callbackasm1(SB)
+ MOVD $739, R12
+ B callbackasm1(SB)
+ MOVD $740, R12
+ B callbackasm1(SB)
+ MOVD $741, R12
+ B callbackasm1(SB)
+ MOVD $742, R12
+ B callbackasm1(SB)
+ MOVD $743, R12
+ B callbackasm1(SB)
+ MOVD $744, R12
+ B callbackasm1(SB)
+ MOVD $745, R12
+ B callbackasm1(SB)
+ MOVD $746, R12
+ B callbackasm1(SB)
+ MOVD $747, R12
+ B callbackasm1(SB)
+ MOVD $748, R12
+ B callbackasm1(SB)
+ MOVD $749, R12
+ B callbackasm1(SB)
+ MOVD $750, R12
+ B callbackasm1(SB)
+ MOVD $751, R12
+ B callbackasm1(SB)
+ MOVD $752, R12
+ B callbackasm1(SB)
+ MOVD $753, R12
+ B callbackasm1(SB)
+ MOVD $754, R12
+ B callbackasm1(SB)
+ MOVD $755, R12
+ B callbackasm1(SB)
+ MOVD $756, R12
+ B callbackasm1(SB)
+ MOVD $757, R12
+ B callbackasm1(SB)
+ MOVD $758, R12
+ B callbackasm1(SB)
+ MOVD $759, R12
+ B callbackasm1(SB)
+ MOVD $760, R12
+ B callbackasm1(SB)
+ MOVD $761, R12
+ B callbackasm1(SB)
+ MOVD $762, R12
+ B callbackasm1(SB)
+ MOVD $763, R12
+ B callbackasm1(SB)
+ MOVD $764, R12
+ B callbackasm1(SB)
+ MOVD $765, R12
+ B callbackasm1(SB)
+ MOVD $766, R12
+ B callbackasm1(SB)
+ MOVD $767, R12
+ B callbackasm1(SB)
+ MOVD $768, R12
+ B callbackasm1(SB)
+ MOVD $769, R12
+ B callbackasm1(SB)
+ MOVD $770, R12
+ B callbackasm1(SB)
+ MOVD $771, R12
+ B callbackasm1(SB)
+ MOVD $772, R12
+ B callbackasm1(SB)
+ MOVD $773, R12
+ B callbackasm1(SB)
+ MOVD $774, R12
+ B callbackasm1(SB)
+ MOVD $775, R12
+ B callbackasm1(SB)
+ MOVD $776, R12
+ B callbackasm1(SB)
+ MOVD $777, R12
+ B callbackasm1(SB)
+ MOVD $778, R12
+ B callbackasm1(SB)
+ MOVD $779, R12
+ B callbackasm1(SB)
+ MOVD $780, R12
+ B callbackasm1(SB)
+ MOVD $781, R12
+ B callbackasm1(SB)
+ MOVD $782, R12
+ B callbackasm1(SB)
+ MOVD $783, R12
+ B callbackasm1(SB)
+ MOVD $784, R12
+ B callbackasm1(SB)
+ MOVD $785, R12
+ B callbackasm1(SB)
+ MOVD $786, R12
+ B callbackasm1(SB)
+ MOVD $787, R12
+ B callbackasm1(SB)
+ MOVD $788, R12
+ B callbackasm1(SB)
+ MOVD $789, R12
+ B callbackasm1(SB)
+ MOVD $790, R12
+ B callbackasm1(SB)
+ MOVD $791, R12
+ B callbackasm1(SB)
+ MOVD $792, R12
+ B callbackasm1(SB)
+ MOVD $793, R12
+ B callbackasm1(SB)
+ MOVD $794, R12
+ B callbackasm1(SB)
+ MOVD $795, R12
+ B callbackasm1(SB)
+ MOVD $796, R12
+ B callbackasm1(SB)
+ MOVD $797, R12
+ B callbackasm1(SB)
+ MOVD $798, R12
+ B callbackasm1(SB)
+ MOVD $799, R12
+ B callbackasm1(SB)
+ MOVD $800, R12
+ B callbackasm1(SB)
+ MOVD $801, R12
+ B callbackasm1(SB)
+ MOVD $802, R12
+ B callbackasm1(SB)
+ MOVD $803, R12
+ B callbackasm1(SB)
+ MOVD $804, R12
+ B callbackasm1(SB)
+ MOVD $805, R12
+ B callbackasm1(SB)
+ MOVD $806, R12
+ B callbackasm1(SB)
+ MOVD $807, R12
+ B callbackasm1(SB)
+ MOVD $808, R12
+ B callbackasm1(SB)
+ MOVD $809, R12
+ B callbackasm1(SB)
+ MOVD $810, R12
+ B callbackasm1(SB)
+ MOVD $811, R12
+ B callbackasm1(SB)
+ MOVD $812, R12
+ B callbackasm1(SB)
+ MOVD $813, R12
+ B callbackasm1(SB)
+ MOVD $814, R12
+ B callbackasm1(SB)
+ MOVD $815, R12
+ B callbackasm1(SB)
+ MOVD $816, R12
+ B callbackasm1(SB)
+ MOVD $817, R12
+ B callbackasm1(SB)
+ MOVD $818, R12
+ B callbackasm1(SB)
+ MOVD $819, R12
+ B callbackasm1(SB)
+ MOVD $820, R12
+ B callbackasm1(SB)
+ MOVD $821, R12
+ B callbackasm1(SB)
+ MOVD $822, R12
+ B callbackasm1(SB)
+ MOVD $823, R12
+ B callbackasm1(SB)
+ MOVD $824, R12
+ B callbackasm1(SB)
+ MOVD $825, R12
+ B callbackasm1(SB)
+ MOVD $826, R12
+ B callbackasm1(SB)
+ MOVD $827, R12
+ B callbackasm1(SB)
+ MOVD $828, R12
+ B callbackasm1(SB)
+ MOVD $829, R12
+ B callbackasm1(SB)
+ MOVD $830, R12
+ B callbackasm1(SB)
+ MOVD $831, R12
+ B callbackasm1(SB)
+ MOVD $832, R12
+ B callbackasm1(SB)
+ MOVD $833, R12
+ B callbackasm1(SB)
+ MOVD $834, R12
+ B callbackasm1(SB)
+ MOVD $835, R12
+ B callbackasm1(SB)
+ MOVD $836, R12
+ B callbackasm1(SB)
+ MOVD $837, R12
+ B callbackasm1(SB)
+ MOVD $838, R12
+ B callbackasm1(SB)
+ MOVD $839, R12
+ B callbackasm1(SB)
+ MOVD $840, R12
+ B callbackasm1(SB)
+ MOVD $841, R12
+ B callbackasm1(SB)
+ MOVD $842, R12
+ B callbackasm1(SB)
+ MOVD $843, R12
+ B callbackasm1(SB)
+ MOVD $844, R12
+ B callbackasm1(SB)
+ MOVD $845, R12
+ B callbackasm1(SB)
+ MOVD $846, R12
+ B callbackasm1(SB)
+ MOVD $847, R12
+ B callbackasm1(SB)
+ MOVD $848, R12
+ B callbackasm1(SB)
+ MOVD $849, R12
+ B callbackasm1(SB)
+ MOVD $850, R12
+ B callbackasm1(SB)
+ MOVD $851, R12
+ B callbackasm1(SB)
+ MOVD $852, R12
+ B callbackasm1(SB)
+ MOVD $853, R12
+ B callbackasm1(SB)
+ MOVD $854, R12
+ B callbackasm1(SB)
+ MOVD $855, R12
+ B callbackasm1(SB)
+ MOVD $856, R12
+ B callbackasm1(SB)
+ MOVD $857, R12
+ B callbackasm1(SB)
+ MOVD $858, R12
+ B callbackasm1(SB)
+ MOVD $859, R12
+ B callbackasm1(SB)
+ MOVD $860, R12
+ B callbackasm1(SB)
+ MOVD $861, R12
+ B callbackasm1(SB)
+ MOVD $862, R12
+ B callbackasm1(SB)
+ MOVD $863, R12
+ B callbackasm1(SB)
+ MOVD $864, R12
+ B callbackasm1(SB)
+ MOVD $865, R12
+ B callbackasm1(SB)
+ MOVD $866, R12
+ B callbackasm1(SB)
+ MOVD $867, R12
+ B callbackasm1(SB)
+ MOVD $868, R12
+ B callbackasm1(SB)
+ MOVD $869, R12
+ B callbackasm1(SB)
+ MOVD $870, R12
+ B callbackasm1(SB)
+ MOVD $871, R12
+ B callbackasm1(SB)
+ MOVD $872, R12
+ B callbackasm1(SB)
+ MOVD $873, R12
+ B callbackasm1(SB)
+ MOVD $874, R12
+ B callbackasm1(SB)
+ MOVD $875, R12
+ B callbackasm1(SB)
+ MOVD $876, R12
+ B callbackasm1(SB)
+ MOVD $877, R12
+ B callbackasm1(SB)
+ MOVD $878, R12
+ B callbackasm1(SB)
+ MOVD $879, R12
+ B callbackasm1(SB)
+ MOVD $880, R12
+ B callbackasm1(SB)
+ MOVD $881, R12
+ B callbackasm1(SB)
+ MOVD $882, R12
+ B callbackasm1(SB)
+ MOVD $883, R12
+ B callbackasm1(SB)
+ MOVD $884, R12
+ B callbackasm1(SB)
+ MOVD $885, R12
+ B callbackasm1(SB)
+ MOVD $886, R12
+ B callbackasm1(SB)
+ MOVD $887, R12
+ B callbackasm1(SB)
+ MOVD $888, R12
+ B callbackasm1(SB)
+ MOVD $889, R12
+ B callbackasm1(SB)
+ MOVD $890, R12
+ B callbackasm1(SB)
+ MOVD $891, R12
+ B callbackasm1(SB)
+ MOVD $892, R12
+ B callbackasm1(SB)
+ MOVD $893, R12
+ B callbackasm1(SB)
+ MOVD $894, R12
+ B callbackasm1(SB)
+ MOVD $895, R12
+ B callbackasm1(SB)
+ MOVD $896, R12
+ B callbackasm1(SB)
+ MOVD $897, R12
+ B callbackasm1(SB)
+ MOVD $898, R12
+ B callbackasm1(SB)
+ MOVD $899, R12
+ B callbackasm1(SB)
+ MOVD $900, R12
+ B callbackasm1(SB)
+ MOVD $901, R12
+ B callbackasm1(SB)
+ MOVD $902, R12
+ B callbackasm1(SB)
+ MOVD $903, R12
+ B callbackasm1(SB)
+ MOVD $904, R12
+ B callbackasm1(SB)
+ MOVD $905, R12
+ B callbackasm1(SB)
+ MOVD $906, R12
+ B callbackasm1(SB)
+ MOVD $907, R12
+ B callbackasm1(SB)
+ MOVD $908, R12
+ B callbackasm1(SB)
+ MOVD $909, R12
+ B callbackasm1(SB)
+ MOVD $910, R12
+ B callbackasm1(SB)
+ MOVD $911, R12
+ B callbackasm1(SB)
+ MOVD $912, R12
+ B callbackasm1(SB)
+ MOVD $913, R12
+ B callbackasm1(SB)
+ MOVD $914, R12
+ B callbackasm1(SB)
+ MOVD $915, R12
+ B callbackasm1(SB)
+ MOVD $916, R12
+ B callbackasm1(SB)
+ MOVD $917, R12
+ B callbackasm1(SB)
+ MOVD $918, R12
+ B callbackasm1(SB)
+ MOVD $919, R12
+ B callbackasm1(SB)
+ MOVD $920, R12
+ B callbackasm1(SB)
+ MOVD $921, R12
+ B callbackasm1(SB)
+ MOVD $922, R12
+ B callbackasm1(SB)
+ MOVD $923, R12
+ B callbackasm1(SB)
+ MOVD $924, R12
+ B callbackasm1(SB)
+ MOVD $925, R12
+ B callbackasm1(SB)
+ MOVD $926, R12
+ B callbackasm1(SB)
+ MOVD $927, R12
+ B callbackasm1(SB)
+ MOVD $928, R12
+ B callbackasm1(SB)
+ MOVD $929, R12
+ B callbackasm1(SB)
+ MOVD $930, R12
+ B callbackasm1(SB)
+ MOVD $931, R12
+ B callbackasm1(SB)
+ MOVD $932, R12
+ B callbackasm1(SB)
+ MOVD $933, R12
+ B callbackasm1(SB)
+ MOVD $934, R12
+ B callbackasm1(SB)
+ MOVD $935, R12
+ B callbackasm1(SB)
+ MOVD $936, R12
+ B callbackasm1(SB)
+ MOVD $937, R12
+ B callbackasm1(SB)
+ MOVD $938, R12
+ B callbackasm1(SB)
+ MOVD $939, R12
+ B callbackasm1(SB)
+ MOVD $940, R12
+ B callbackasm1(SB)
+ MOVD $941, R12
+ B callbackasm1(SB)
+ MOVD $942, R12
+ B callbackasm1(SB)
+ MOVD $943, R12
+ B callbackasm1(SB)
+ MOVD $944, R12
+ B callbackasm1(SB)
+ MOVD $945, R12
+ B callbackasm1(SB)
+ MOVD $946, R12
+ B callbackasm1(SB)
+ MOVD $947, R12
+ B callbackasm1(SB)
+ MOVD $948, R12
+ B callbackasm1(SB)
+ MOVD $949, R12
+ B callbackasm1(SB)
+ MOVD $950, R12
+ B callbackasm1(SB)
+ MOVD $951, R12
+ B callbackasm1(SB)
+ MOVD $952, R12
+ B callbackasm1(SB)
+ MOVD $953, R12
+ B callbackasm1(SB)
+ MOVD $954, R12
+ B callbackasm1(SB)
+ MOVD $955, R12
+ B callbackasm1(SB)
+ MOVD $956, R12
+ B callbackasm1(SB)
+ MOVD $957, R12
+ B callbackasm1(SB)
+ MOVD $958, R12
+ B callbackasm1(SB)
+ MOVD $959, R12
+ B callbackasm1(SB)
+ MOVD $960, R12
+ B callbackasm1(SB)
+ MOVD $961, R12
+ B callbackasm1(SB)
+ MOVD $962, R12
+ B callbackasm1(SB)
+ MOVD $963, R12
+ B callbackasm1(SB)
+ MOVD $964, R12
+ B callbackasm1(SB)
+ MOVD $965, R12
+ B callbackasm1(SB)
+ MOVD $966, R12
+ B callbackasm1(SB)
+ MOVD $967, R12
+ B callbackasm1(SB)
+ MOVD $968, R12
+ B callbackasm1(SB)
+ MOVD $969, R12
+ B callbackasm1(SB)
+ MOVD $970, R12
+ B callbackasm1(SB)
+ MOVD $971, R12
+ B callbackasm1(SB)
+ MOVD $972, R12
+ B callbackasm1(SB)
+ MOVD $973, R12
+ B callbackasm1(SB)
+ MOVD $974, R12
+ B callbackasm1(SB)
+ MOVD $975, R12
+ B callbackasm1(SB)
+ MOVD $976, R12
+ B callbackasm1(SB)
+ MOVD $977, R12
+ B callbackasm1(SB)
+ MOVD $978, R12
+ B callbackasm1(SB)
+ MOVD $979, R12
+ B callbackasm1(SB)
+ MOVD $980, R12
+ B callbackasm1(SB)
+ MOVD $981, R12
+ B callbackasm1(SB)
+ MOVD $982, R12
+ B callbackasm1(SB)
+ MOVD $983, R12
+ B callbackasm1(SB)
+ MOVD $984, R12
+ B callbackasm1(SB)
+ MOVD $985, R12
+ B callbackasm1(SB)
+ MOVD $986, R12
+ B callbackasm1(SB)
+ MOVD $987, R12
+ B callbackasm1(SB)
+ MOVD $988, R12
+ B callbackasm1(SB)
+ MOVD $989, R12
+ B callbackasm1(SB)
+ MOVD $990, R12
+ B callbackasm1(SB)
+ MOVD $991, R12
+ B callbackasm1(SB)
+ MOVD $992, R12
+ B callbackasm1(SB)
+ MOVD $993, R12
+ B callbackasm1(SB)
+ MOVD $994, R12
+ B callbackasm1(SB)
+ MOVD $995, R12
+ B callbackasm1(SB)
+ MOVD $996, R12
+ B callbackasm1(SB)
+ MOVD $997, R12
+ B callbackasm1(SB)
+ MOVD $998, R12
+ B callbackasm1(SB)
+ MOVD $999, R12
+ B callbackasm1(SB)
+ MOVD $1000, R12
+ B callbackasm1(SB)
+ MOVD $1001, R12
+ B callbackasm1(SB)
+ MOVD $1002, R12
+ B callbackasm1(SB)
+ MOVD $1003, R12
+ B callbackasm1(SB)
+ MOVD $1004, R12
+ B callbackasm1(SB)
+ MOVD $1005, R12
+ B callbackasm1(SB)
+ MOVD $1006, R12
+ B callbackasm1(SB)
+ MOVD $1007, R12
+ B callbackasm1(SB)
+ MOVD $1008, R12
+ B callbackasm1(SB)
+ MOVD $1009, R12
+ B callbackasm1(SB)
+ MOVD $1010, R12
+ B callbackasm1(SB)
+ MOVD $1011, R12
+ B callbackasm1(SB)
+ MOVD $1012, R12
+ B callbackasm1(SB)
+ MOVD $1013, R12
+ B callbackasm1(SB)
+ MOVD $1014, R12
+ B callbackasm1(SB)
+ MOVD $1015, R12
+ B callbackasm1(SB)
+ MOVD $1016, R12
+ B callbackasm1(SB)
+ MOVD $1017, R12
+ B callbackasm1(SB)
+ MOVD $1018, R12
+ B callbackasm1(SB)
+ MOVD $1019, R12
+ B callbackasm1(SB)
+ MOVD $1020, R12
+ B callbackasm1(SB)
+ MOVD $1021, R12
+ B callbackasm1(SB)
+ MOVD $1022, R12
+ B callbackasm1(SB)
+ MOVD $1023, R12
+ B callbackasm1(SB)
+ MOVD $1024, R12
+ B callbackasm1(SB)
+ MOVD $1025, R12
+ B callbackasm1(SB)
+ MOVD $1026, R12
+ B callbackasm1(SB)
+ MOVD $1027, R12
+ B callbackasm1(SB)
+ MOVD $1028, R12
+ B callbackasm1(SB)
+ MOVD $1029, R12
+ B callbackasm1(SB)
+ MOVD $1030, R12
+ B callbackasm1(SB)
+ MOVD $1031, R12
+ B callbackasm1(SB)
+ MOVD $1032, R12
+ B callbackasm1(SB)
+ MOVD $1033, R12
+ B callbackasm1(SB)
+ MOVD $1034, R12
+ B callbackasm1(SB)
+ MOVD $1035, R12
+ B callbackasm1(SB)
+ MOVD $1036, R12
+ B callbackasm1(SB)
+ MOVD $1037, R12
+ B callbackasm1(SB)
+ MOVD $1038, R12
+ B callbackasm1(SB)
+ MOVD $1039, R12
+ B callbackasm1(SB)
+ MOVD $1040, R12
+ B callbackasm1(SB)
+ MOVD $1041, R12
+ B callbackasm1(SB)
+ MOVD $1042, R12
+ B callbackasm1(SB)
+ MOVD $1043, R12
+ B callbackasm1(SB)
+ MOVD $1044, R12
+ B callbackasm1(SB)
+ MOVD $1045, R12
+ B callbackasm1(SB)
+ MOVD $1046, R12
+ B callbackasm1(SB)
+ MOVD $1047, R12
+ B callbackasm1(SB)
+ MOVD $1048, R12
+ B callbackasm1(SB)
+ MOVD $1049, R12
+ B callbackasm1(SB)
+ MOVD $1050, R12
+ B callbackasm1(SB)
+ MOVD $1051, R12
+ B callbackasm1(SB)
+ MOVD $1052, R12
+ B callbackasm1(SB)
+ MOVD $1053, R12
+ B callbackasm1(SB)
+ MOVD $1054, R12
+ B callbackasm1(SB)
+ MOVD $1055, R12
+ B callbackasm1(SB)
+ MOVD $1056, R12
+ B callbackasm1(SB)
+ MOVD $1057, R12
+ B callbackasm1(SB)
+ MOVD $1058, R12
+ B callbackasm1(SB)
+ MOVD $1059, R12
+ B callbackasm1(SB)
+ MOVD $1060, R12
+ B callbackasm1(SB)
+ MOVD $1061, R12
+ B callbackasm1(SB)
+ MOVD $1062, R12
+ B callbackasm1(SB)
+ MOVD $1063, R12
+ B callbackasm1(SB)
+ MOVD $1064, R12
+ B callbackasm1(SB)
+ MOVD $1065, R12
+ B callbackasm1(SB)
+ MOVD $1066, R12
+ B callbackasm1(SB)
+ MOVD $1067, R12
+ B callbackasm1(SB)
+ MOVD $1068, R12
+ B callbackasm1(SB)
+ MOVD $1069, R12
+ B callbackasm1(SB)
+ MOVD $1070, R12
+ B callbackasm1(SB)
+ MOVD $1071, R12
+ B callbackasm1(SB)
+ MOVD $1072, R12
+ B callbackasm1(SB)
+ MOVD $1073, R12
+ B callbackasm1(SB)
+ MOVD $1074, R12
+ B callbackasm1(SB)
+ MOVD $1075, R12
+ B callbackasm1(SB)
+ MOVD $1076, R12
+ B callbackasm1(SB)
+ MOVD $1077, R12
+ B callbackasm1(SB)
+ MOVD $1078, R12
+ B callbackasm1(SB)
+ MOVD $1079, R12
+ B callbackasm1(SB)
+ MOVD $1080, R12
+ B callbackasm1(SB)
+ MOVD $1081, R12
+ B callbackasm1(SB)
+ MOVD $1082, R12
+ B callbackasm1(SB)
+ MOVD $1083, R12
+ B callbackasm1(SB)
+ MOVD $1084, R12
+ B callbackasm1(SB)
+ MOVD $1085, R12
+ B callbackasm1(SB)
+ MOVD $1086, R12
+ B callbackasm1(SB)
+ MOVD $1087, R12
+ B callbackasm1(SB)
+ MOVD $1088, R12
+ B callbackasm1(SB)
+ MOVD $1089, R12
+ B callbackasm1(SB)
+ MOVD $1090, R12
+ B callbackasm1(SB)
+ MOVD $1091, R12
+ B callbackasm1(SB)
+ MOVD $1092, R12
+ B callbackasm1(SB)
+ MOVD $1093, R12
+ B callbackasm1(SB)
+ MOVD $1094, R12
+ B callbackasm1(SB)
+ MOVD $1095, R12
+ B callbackasm1(SB)
+ MOVD $1096, R12
+ B callbackasm1(SB)
+ MOVD $1097, R12
+ B callbackasm1(SB)
+ MOVD $1098, R12
+ B callbackasm1(SB)
+ MOVD $1099, R12
+ B callbackasm1(SB)
+ MOVD $1100, R12
+ B callbackasm1(SB)
+ MOVD $1101, R12
+ B callbackasm1(SB)
+ MOVD $1102, R12
+ B callbackasm1(SB)
+ MOVD $1103, R12
+ B callbackasm1(SB)
+ MOVD $1104, R12
+ B callbackasm1(SB)
+ MOVD $1105, R12
+ B callbackasm1(SB)
+ MOVD $1106, R12
+ B callbackasm1(SB)
+ MOVD $1107, R12
+ B callbackasm1(SB)
+ MOVD $1108, R12
+ B callbackasm1(SB)
+ MOVD $1109, R12
+ B callbackasm1(SB)
+ MOVD $1110, R12
+ B callbackasm1(SB)
+ MOVD $1111, R12
+ B callbackasm1(SB)
+ MOVD $1112, R12
+ B callbackasm1(SB)
+ MOVD $1113, R12
+ B callbackasm1(SB)
+ MOVD $1114, R12
+ B callbackasm1(SB)
+ MOVD $1115, R12
+ B callbackasm1(SB)
+ MOVD $1116, R12
+ B callbackasm1(SB)
+ MOVD $1117, R12
+ B callbackasm1(SB)
+ MOVD $1118, R12
+ B callbackasm1(SB)
+ MOVD $1119, R12
+ B callbackasm1(SB)
+ MOVD $1120, R12
+ B callbackasm1(SB)
+ MOVD $1121, R12
+ B callbackasm1(SB)
+ MOVD $1122, R12
+ B callbackasm1(SB)
+ MOVD $1123, R12
+ B callbackasm1(SB)
+ MOVD $1124, R12
+ B callbackasm1(SB)
+ MOVD $1125, R12
+ B callbackasm1(SB)
+ MOVD $1126, R12
+ B callbackasm1(SB)
+ MOVD $1127, R12
+ B callbackasm1(SB)
+ MOVD $1128, R12
+ B callbackasm1(SB)
+ MOVD $1129, R12
+ B callbackasm1(SB)
+ MOVD $1130, R12
+ B callbackasm1(SB)
+ MOVD $1131, R12
+ B callbackasm1(SB)
+ MOVD $1132, R12
+ B callbackasm1(SB)
+ MOVD $1133, R12
+ B callbackasm1(SB)
+ MOVD $1134, R12
+ B callbackasm1(SB)
+ MOVD $1135, R12
+ B callbackasm1(SB)
+ MOVD $1136, R12
+ B callbackasm1(SB)
+ MOVD $1137, R12
+ B callbackasm1(SB)
+ MOVD $1138, R12
+ B callbackasm1(SB)
+ MOVD $1139, R12
+ B callbackasm1(SB)
+ MOVD $1140, R12
+ B callbackasm1(SB)
+ MOVD $1141, R12
+ B callbackasm1(SB)
+ MOVD $1142, R12
+ B callbackasm1(SB)
+ MOVD $1143, R12
+ B callbackasm1(SB)
+ MOVD $1144, R12
+ B callbackasm1(SB)
+ MOVD $1145, R12
+ B callbackasm1(SB)
+ MOVD $1146, R12
+ B callbackasm1(SB)
+ MOVD $1147, R12
+ B callbackasm1(SB)
+ MOVD $1148, R12
+ B callbackasm1(SB)
+ MOVD $1149, R12
+ B callbackasm1(SB)
+ MOVD $1150, R12
+ B callbackasm1(SB)
+ MOVD $1151, R12
+ B callbackasm1(SB)
+ MOVD $1152, R12
+ B callbackasm1(SB)
+ MOVD $1153, R12
+ B callbackasm1(SB)
+ MOVD $1154, R12
+ B callbackasm1(SB)
+ MOVD $1155, R12
+ B callbackasm1(SB)
+ MOVD $1156, R12
+ B callbackasm1(SB)
+ MOVD $1157, R12
+ B callbackasm1(SB)
+ MOVD $1158, R12
+ B callbackasm1(SB)
+ MOVD $1159, R12
+ B callbackasm1(SB)
+ MOVD $1160, R12
+ B callbackasm1(SB)
+ MOVD $1161, R12
+ B callbackasm1(SB)
+ MOVD $1162, R12
+ B callbackasm1(SB)
+ MOVD $1163, R12
+ B callbackasm1(SB)
+ MOVD $1164, R12
+ B callbackasm1(SB)
+ MOVD $1165, R12
+ B callbackasm1(SB)
+ MOVD $1166, R12
+ B callbackasm1(SB)
+ MOVD $1167, R12
+ B callbackasm1(SB)
+ MOVD $1168, R12
+ B callbackasm1(SB)
+ MOVD $1169, R12
+ B callbackasm1(SB)
+ MOVD $1170, R12
+ B callbackasm1(SB)
+ MOVD $1171, R12
+ B callbackasm1(SB)
+ MOVD $1172, R12
+ B callbackasm1(SB)
+ MOVD $1173, R12
+ B callbackasm1(SB)
+ MOVD $1174, R12
+ B callbackasm1(SB)
+ MOVD $1175, R12
+ B callbackasm1(SB)
+ MOVD $1176, R12
+ B callbackasm1(SB)
+ MOVD $1177, R12
+ B callbackasm1(SB)
+ MOVD $1178, R12
+ B callbackasm1(SB)
+ MOVD $1179, R12
+ B callbackasm1(SB)
+ MOVD $1180, R12
+ B callbackasm1(SB)
+ MOVD $1181, R12
+ B callbackasm1(SB)
+ MOVD $1182, R12
+ B callbackasm1(SB)
+ MOVD $1183, R12
+ B callbackasm1(SB)
+ MOVD $1184, R12
+ B callbackasm1(SB)
+ MOVD $1185, R12
+ B callbackasm1(SB)
+ MOVD $1186, R12
+ B callbackasm1(SB)
+ MOVD $1187, R12
+ B callbackasm1(SB)
+ MOVD $1188, R12
+ B callbackasm1(SB)
+ MOVD $1189, R12
+ B callbackasm1(SB)
+ MOVD $1190, R12
+ B callbackasm1(SB)
+ MOVD $1191, R12
+ B callbackasm1(SB)
+ MOVD $1192, R12
+ B callbackasm1(SB)
+ MOVD $1193, R12
+ B callbackasm1(SB)
+ MOVD $1194, R12
+ B callbackasm1(SB)
+ MOVD $1195, R12
+ B callbackasm1(SB)
+ MOVD $1196, R12
+ B callbackasm1(SB)
+ MOVD $1197, R12
+ B callbackasm1(SB)
+ MOVD $1198, R12
+ B callbackasm1(SB)
+ MOVD $1199, R12
+ B callbackasm1(SB)
+ MOVD $1200, R12
+ B callbackasm1(SB)
+ MOVD $1201, R12
+ B callbackasm1(SB)
+ MOVD $1202, R12
+ B callbackasm1(SB)
+ MOVD $1203, R12
+ B callbackasm1(SB)
+ MOVD $1204, R12
+ B callbackasm1(SB)
+ MOVD $1205, R12
+ B callbackasm1(SB)
+ MOVD $1206, R12
+ B callbackasm1(SB)
+ MOVD $1207, R12
+ B callbackasm1(SB)
+ MOVD $1208, R12
+ B callbackasm1(SB)
+ MOVD $1209, R12
+ B callbackasm1(SB)
+ MOVD $1210, R12
+ B callbackasm1(SB)
+ MOVD $1211, R12
+ B callbackasm1(SB)
+ MOVD $1212, R12
+ B callbackasm1(SB)
+ MOVD $1213, R12
+ B callbackasm1(SB)
+ MOVD $1214, R12
+ B callbackasm1(SB)
+ MOVD $1215, R12
+ B callbackasm1(SB)
+ MOVD $1216, R12
+ B callbackasm1(SB)
+ MOVD $1217, R12
+ B callbackasm1(SB)
+ MOVD $1218, R12
+ B callbackasm1(SB)
+ MOVD $1219, R12
+ B callbackasm1(SB)
+ MOVD $1220, R12
+ B callbackasm1(SB)
+ MOVD $1221, R12
+ B callbackasm1(SB)
+ MOVD $1222, R12
+ B callbackasm1(SB)
+ MOVD $1223, R12
+ B callbackasm1(SB)
+ MOVD $1224, R12
+ B callbackasm1(SB)
+ MOVD $1225, R12
+ B callbackasm1(SB)
+ MOVD $1226, R12
+ B callbackasm1(SB)
+ MOVD $1227, R12
+ B callbackasm1(SB)
+ MOVD $1228, R12
+ B callbackasm1(SB)
+ MOVD $1229, R12
+ B callbackasm1(SB)
+ MOVD $1230, R12
+ B callbackasm1(SB)
+ MOVD $1231, R12
+ B callbackasm1(SB)
+ MOVD $1232, R12
+ B callbackasm1(SB)
+ MOVD $1233, R12
+ B callbackasm1(SB)
+ MOVD $1234, R12
+ B callbackasm1(SB)
+ MOVD $1235, R12
+ B callbackasm1(SB)
+ MOVD $1236, R12
+ B callbackasm1(SB)
+ MOVD $1237, R12
+ B callbackasm1(SB)
+ MOVD $1238, R12
+ B callbackasm1(SB)
+ MOVD $1239, R12
+ B callbackasm1(SB)
+ MOVD $1240, R12
+ B callbackasm1(SB)
+ MOVD $1241, R12
+ B callbackasm1(SB)
+ MOVD $1242, R12
+ B callbackasm1(SB)
+ MOVD $1243, R12
+ B callbackasm1(SB)
+ MOVD $1244, R12
+ B callbackasm1(SB)
+ MOVD $1245, R12
+ B callbackasm1(SB)
+ MOVD $1246, R12
+ B callbackasm1(SB)
+ MOVD $1247, R12
+ B callbackasm1(SB)
+ MOVD $1248, R12
+ B callbackasm1(SB)
+ MOVD $1249, R12
+ B callbackasm1(SB)
+ MOVD $1250, R12
+ B callbackasm1(SB)
+ MOVD $1251, R12
+ B callbackasm1(SB)
+ MOVD $1252, R12
+ B callbackasm1(SB)
+ MOVD $1253, R12
+ B callbackasm1(SB)
+ MOVD $1254, R12
+ B callbackasm1(SB)
+ MOVD $1255, R12
+ B callbackasm1(SB)
+ MOVD $1256, R12
+ B callbackasm1(SB)
+ MOVD $1257, R12
+ B callbackasm1(SB)
+ MOVD $1258, R12
+ B callbackasm1(SB)
+ MOVD $1259, R12
+ B callbackasm1(SB)
+ MOVD $1260, R12
+ B callbackasm1(SB)
+ MOVD $1261, R12
+ B callbackasm1(SB)
+ MOVD $1262, R12
+ B callbackasm1(SB)
+ MOVD $1263, R12
+ B callbackasm1(SB)
+ MOVD $1264, R12
+ B callbackasm1(SB)
+ MOVD $1265, R12
+ B callbackasm1(SB)
+ MOVD $1266, R12
+ B callbackasm1(SB)
+ MOVD $1267, R12
+ B callbackasm1(SB)
+ MOVD $1268, R12
+ B callbackasm1(SB)
+ MOVD $1269, R12
+ B callbackasm1(SB)
+ MOVD $1270, R12
+ B callbackasm1(SB)
+ MOVD $1271, R12
+ B callbackasm1(SB)
+ MOVD $1272, R12
+ B callbackasm1(SB)
+ MOVD $1273, R12
+ B callbackasm1(SB)
+ MOVD $1274, R12
+ B callbackasm1(SB)
+ MOVD $1275, R12
+ B callbackasm1(SB)
+ MOVD $1276, R12
+ B callbackasm1(SB)
+ MOVD $1277, R12
+ B callbackasm1(SB)
+ MOVD $1278, R12
+ B callbackasm1(SB)
+ MOVD $1279, R12
+ B callbackasm1(SB)
+ MOVD $1280, R12
+ B callbackasm1(SB)
+ MOVD $1281, R12
+ B callbackasm1(SB)
+ MOVD $1282, R12
+ B callbackasm1(SB)
+ MOVD $1283, R12
+ B callbackasm1(SB)
+ MOVD $1284, R12
+ B callbackasm1(SB)
+ MOVD $1285, R12
+ B callbackasm1(SB)
+ MOVD $1286, R12
+ B callbackasm1(SB)
+ MOVD $1287, R12
+ B callbackasm1(SB)
+ MOVD $1288, R12
+ B callbackasm1(SB)
+ MOVD $1289, R12
+ B callbackasm1(SB)
+ MOVD $1290, R12
+ B callbackasm1(SB)
+ MOVD $1291, R12
+ B callbackasm1(SB)
+ MOVD $1292, R12
+ B callbackasm1(SB)
+ MOVD $1293, R12
+ B callbackasm1(SB)
+ MOVD $1294, R12
+ B callbackasm1(SB)
+ MOVD $1295, R12
+ B callbackasm1(SB)
+ MOVD $1296, R12
+ B callbackasm1(SB)
+ MOVD $1297, R12
+ B callbackasm1(SB)
+ MOVD $1298, R12
+ B callbackasm1(SB)
+ MOVD $1299, R12
+ B callbackasm1(SB)
+ MOVD $1300, R12
+ B callbackasm1(SB)
+ MOVD $1301, R12
+ B callbackasm1(SB)
+ MOVD $1302, R12
+ B callbackasm1(SB)
+ MOVD $1303, R12
+ B callbackasm1(SB)
+ MOVD $1304, R12
+ B callbackasm1(SB)
+ MOVD $1305, R12
+ B callbackasm1(SB)
+ MOVD $1306, R12
+ B callbackasm1(SB)
+ MOVD $1307, R12
+ B callbackasm1(SB)
+ MOVD $1308, R12
+ B callbackasm1(SB)
+ MOVD $1309, R12
+ B callbackasm1(SB)
+ MOVD $1310, R12
+ B callbackasm1(SB)
+ MOVD $1311, R12
+ B callbackasm1(SB)
+ MOVD $1312, R12
+ B callbackasm1(SB)
+ MOVD $1313, R12
+ B callbackasm1(SB)
+ MOVD $1314, R12
+ B callbackasm1(SB)
+ MOVD $1315, R12
+ B callbackasm1(SB)
+ MOVD $1316, R12
+ B callbackasm1(SB)
+ MOVD $1317, R12
+ B callbackasm1(SB)
+ MOVD $1318, R12
+ B callbackasm1(SB)
+ MOVD $1319, R12
+ B callbackasm1(SB)
+ MOVD $1320, R12
+ B callbackasm1(SB)
+ MOVD $1321, R12
+ B callbackasm1(SB)
+ MOVD $1322, R12
+ B callbackasm1(SB)
+ MOVD $1323, R12
+ B callbackasm1(SB)
+ MOVD $1324, R12
+ B callbackasm1(SB)
+ MOVD $1325, R12
+ B callbackasm1(SB)
+ MOVD $1326, R12
+ B callbackasm1(SB)
+ MOVD $1327, R12
+ B callbackasm1(SB)
+ MOVD $1328, R12
+ B callbackasm1(SB)
+ MOVD $1329, R12
+ B callbackasm1(SB)
+ MOVD $1330, R12
+ B callbackasm1(SB)
+ MOVD $1331, R12
+ B callbackasm1(SB)
+ MOVD $1332, R12
+ B callbackasm1(SB)
+ MOVD $1333, R12
+ B callbackasm1(SB)
+ MOVD $1334, R12
+ B callbackasm1(SB)
+ MOVD $1335, R12
+ B callbackasm1(SB)
+ MOVD $1336, R12
+ B callbackasm1(SB)
+ MOVD $1337, R12
+ B callbackasm1(SB)
+ MOVD $1338, R12
+ B callbackasm1(SB)
+ MOVD $1339, R12
+ B callbackasm1(SB)
+ MOVD $1340, R12
+ B callbackasm1(SB)
+ MOVD $1341, R12
+ B callbackasm1(SB)
+ MOVD $1342, R12
+ B callbackasm1(SB)
+ MOVD $1343, R12
+ B callbackasm1(SB)
+ MOVD $1344, R12
+ B callbackasm1(SB)
+ MOVD $1345, R12
+ B callbackasm1(SB)
+ MOVD $1346, R12
+ B callbackasm1(SB)
+ MOVD $1347, R12
+ B callbackasm1(SB)
+ MOVD $1348, R12
+ B callbackasm1(SB)
+ MOVD $1349, R12
+ B callbackasm1(SB)
+ MOVD $1350, R12
+ B callbackasm1(SB)
+ MOVD $1351, R12
+ B callbackasm1(SB)
+ MOVD $1352, R12
+ B callbackasm1(SB)
+ MOVD $1353, R12
+ B callbackasm1(SB)
+ MOVD $1354, R12
+ B callbackasm1(SB)
+ MOVD $1355, R12
+ B callbackasm1(SB)
+ MOVD $1356, R12
+ B callbackasm1(SB)
+ MOVD $1357, R12
+ B callbackasm1(SB)
+ MOVD $1358, R12
+ B callbackasm1(SB)
+ MOVD $1359, R12
+ B callbackasm1(SB)
+ MOVD $1360, R12
+ B callbackasm1(SB)
+ MOVD $1361, R12
+ B callbackasm1(SB)
+ MOVD $1362, R12
+ B callbackasm1(SB)
+ MOVD $1363, R12
+ B callbackasm1(SB)
+ MOVD $1364, R12
+ B callbackasm1(SB)
+ MOVD $1365, R12
+ B callbackasm1(SB)
+ MOVD $1366, R12
+ B callbackasm1(SB)
+ MOVD $1367, R12
+ B callbackasm1(SB)
+ MOVD $1368, R12
+ B callbackasm1(SB)
+ MOVD $1369, R12
+ B callbackasm1(SB)
+ MOVD $1370, R12
+ B callbackasm1(SB)
+ MOVD $1371, R12
+ B callbackasm1(SB)
+ MOVD $1372, R12
+ B callbackasm1(SB)
+ MOVD $1373, R12
+ B callbackasm1(SB)
+ MOVD $1374, R12
+ B callbackasm1(SB)
+ MOVD $1375, R12
+ B callbackasm1(SB)
+ MOVD $1376, R12
+ B callbackasm1(SB)
+ MOVD $1377, R12
+ B callbackasm1(SB)
+ MOVD $1378, R12
+ B callbackasm1(SB)
+ MOVD $1379, R12
+ B callbackasm1(SB)
+ MOVD $1380, R12
+ B callbackasm1(SB)
+ MOVD $1381, R12
+ B callbackasm1(SB)
+ MOVD $1382, R12
+ B callbackasm1(SB)
+ MOVD $1383, R12
+ B callbackasm1(SB)
+ MOVD $1384, R12
+ B callbackasm1(SB)
+ MOVD $1385, R12
+ B callbackasm1(SB)
+ MOVD $1386, R12
+ B callbackasm1(SB)
+ MOVD $1387, R12
+ B callbackasm1(SB)
+ MOVD $1388, R12
+ B callbackasm1(SB)
+ MOVD $1389, R12
+ B callbackasm1(SB)
+ MOVD $1390, R12
+ B callbackasm1(SB)
+ MOVD $1391, R12
+ B callbackasm1(SB)
+ MOVD $1392, R12
+ B callbackasm1(SB)
+ MOVD $1393, R12
+ B callbackasm1(SB)
+ MOVD $1394, R12
+ B callbackasm1(SB)
+ MOVD $1395, R12
+ B callbackasm1(SB)
+ MOVD $1396, R12
+ B callbackasm1(SB)
+ MOVD $1397, R12
+ B callbackasm1(SB)
+ MOVD $1398, R12
+ B callbackasm1(SB)
+ MOVD $1399, R12
+ B callbackasm1(SB)
+ MOVD $1400, R12
+ B callbackasm1(SB)
+ MOVD $1401, R12
+ B callbackasm1(SB)
+ MOVD $1402, R12
+ B callbackasm1(SB)
+ MOVD $1403, R12
+ B callbackasm1(SB)
+ MOVD $1404, R12
+ B callbackasm1(SB)
+ MOVD $1405, R12
+ B callbackasm1(SB)
+ MOVD $1406, R12
+ B callbackasm1(SB)
+ MOVD $1407, R12
+ B callbackasm1(SB)
+ MOVD $1408, R12
+ B callbackasm1(SB)
+ MOVD $1409, R12
+ B callbackasm1(SB)
+ MOVD $1410, R12
+ B callbackasm1(SB)
+ MOVD $1411, R12
+ B callbackasm1(SB)
+ MOVD $1412, R12
+ B callbackasm1(SB)
+ MOVD $1413, R12
+ B callbackasm1(SB)
+ MOVD $1414, R12
+ B callbackasm1(SB)
+ MOVD $1415, R12
+ B callbackasm1(SB)
+ MOVD $1416, R12
+ B callbackasm1(SB)
+ MOVD $1417, R12
+ B callbackasm1(SB)
+ MOVD $1418, R12
+ B callbackasm1(SB)
+ MOVD $1419, R12
+ B callbackasm1(SB)
+ MOVD $1420, R12
+ B callbackasm1(SB)
+ MOVD $1421, R12
+ B callbackasm1(SB)
+ MOVD $1422, R12
+ B callbackasm1(SB)
+ MOVD $1423, R12
+ B callbackasm1(SB)
+ MOVD $1424, R12
+ B callbackasm1(SB)
+ MOVD $1425, R12
+ B callbackasm1(SB)
+ MOVD $1426, R12
+ B callbackasm1(SB)
+ MOVD $1427, R12
+ B callbackasm1(SB)
+ MOVD $1428, R12
+ B callbackasm1(SB)
+ MOVD $1429, R12
+ B callbackasm1(SB)
+ MOVD $1430, R12
+ B callbackasm1(SB)
+ MOVD $1431, R12
+ B callbackasm1(SB)
+ MOVD $1432, R12
+ B callbackasm1(SB)
+ MOVD $1433, R12
+ B callbackasm1(SB)
+ MOVD $1434, R12
+ B callbackasm1(SB)
+ MOVD $1435, R12
+ B callbackasm1(SB)
+ MOVD $1436, R12
+ B callbackasm1(SB)
+ MOVD $1437, R12
+ B callbackasm1(SB)
+ MOVD $1438, R12
+ B callbackasm1(SB)
+ MOVD $1439, R12
+ B callbackasm1(SB)
+ MOVD $1440, R12
+ B callbackasm1(SB)
+ MOVD $1441, R12
+ B callbackasm1(SB)
+ MOVD $1442, R12
+ B callbackasm1(SB)
+ MOVD $1443, R12
+ B callbackasm1(SB)
+ MOVD $1444, R12
+ B callbackasm1(SB)
+ MOVD $1445, R12
+ B callbackasm1(SB)
+ MOVD $1446, R12
+ B callbackasm1(SB)
+ MOVD $1447, R12
+ B callbackasm1(SB)
+ MOVD $1448, R12
+ B callbackasm1(SB)
+ MOVD $1449, R12
+ B callbackasm1(SB)
+ MOVD $1450, R12
+ B callbackasm1(SB)
+ MOVD $1451, R12
+ B callbackasm1(SB)
+ MOVD $1452, R12
+ B callbackasm1(SB)
+ MOVD $1453, R12
+ B callbackasm1(SB)
+ MOVD $1454, R12
+ B callbackasm1(SB)
+ MOVD $1455, R12
+ B callbackasm1(SB)
+ MOVD $1456, R12
+ B callbackasm1(SB)
+ MOVD $1457, R12
+ B callbackasm1(SB)
+ MOVD $1458, R12
+ B callbackasm1(SB)
+ MOVD $1459, R12
+ B callbackasm1(SB)
+ MOVD $1460, R12
+ B callbackasm1(SB)
+ MOVD $1461, R12
+ B callbackasm1(SB)
+ MOVD $1462, R12
+ B callbackasm1(SB)
+ MOVD $1463, R12
+ B callbackasm1(SB)
+ MOVD $1464, R12
+ B callbackasm1(SB)
+ MOVD $1465, R12
+ B callbackasm1(SB)
+ MOVD $1466, R12
+ B callbackasm1(SB)
+ MOVD $1467, R12
+ B callbackasm1(SB)
+ MOVD $1468, R12
+ B callbackasm1(SB)
+ MOVD $1469, R12
+ B callbackasm1(SB)
+ MOVD $1470, R12
+ B callbackasm1(SB)
+ MOVD $1471, R12
+ B callbackasm1(SB)
+ MOVD $1472, R12
+ B callbackasm1(SB)
+ MOVD $1473, R12
+ B callbackasm1(SB)
+ MOVD $1474, R12
+ B callbackasm1(SB)
+ MOVD $1475, R12
+ B callbackasm1(SB)
+ MOVD $1476, R12
+ B callbackasm1(SB)
+ MOVD $1477, R12
+ B callbackasm1(SB)
+ MOVD $1478, R12
+ B callbackasm1(SB)
+ MOVD $1479, R12
+ B callbackasm1(SB)
+ MOVD $1480, R12
+ B callbackasm1(SB)
+ MOVD $1481, R12
+ B callbackasm1(SB)
+ MOVD $1482, R12
+ B callbackasm1(SB)
+ MOVD $1483, R12
+ B callbackasm1(SB)
+ MOVD $1484, R12
+ B callbackasm1(SB)
+ MOVD $1485, R12
+ B callbackasm1(SB)
+ MOVD $1486, R12
+ B callbackasm1(SB)
+ MOVD $1487, R12
+ B callbackasm1(SB)
+ MOVD $1488, R12
+ B callbackasm1(SB)
+ MOVD $1489, R12
+ B callbackasm1(SB)
+ MOVD $1490, R12
+ B callbackasm1(SB)
+ MOVD $1491, R12
+ B callbackasm1(SB)
+ MOVD $1492, R12
+ B callbackasm1(SB)
+ MOVD $1493, R12
+ B callbackasm1(SB)
+ MOVD $1494, R12
+ B callbackasm1(SB)
+ MOVD $1495, R12
+ B callbackasm1(SB)
+ MOVD $1496, R12
+ B callbackasm1(SB)
+ MOVD $1497, R12
+ B callbackasm1(SB)
+ MOVD $1498, R12
+ B callbackasm1(SB)
+ MOVD $1499, R12
+ B callbackasm1(SB)
+ MOVD $1500, R12
+ B callbackasm1(SB)
+ MOVD $1501, R12
+ B callbackasm1(SB)
+ MOVD $1502, R12
+ B callbackasm1(SB)
+ MOVD $1503, R12
+ B callbackasm1(SB)
+ MOVD $1504, R12
+ B callbackasm1(SB)
+ MOVD $1505, R12
+ B callbackasm1(SB)
+ MOVD $1506, R12
+ B callbackasm1(SB)
+ MOVD $1507, R12
+ B callbackasm1(SB)
+ MOVD $1508, R12
+ B callbackasm1(SB)
+ MOVD $1509, R12
+ B callbackasm1(SB)
+ MOVD $1510, R12
+ B callbackasm1(SB)
+ MOVD $1511, R12
+ B callbackasm1(SB)
+ MOVD $1512, R12
+ B callbackasm1(SB)
+ MOVD $1513, R12
+ B callbackasm1(SB)
+ MOVD $1514, R12
+ B callbackasm1(SB)
+ MOVD $1515, R12
+ B callbackasm1(SB)
+ MOVD $1516, R12
+ B callbackasm1(SB)
+ MOVD $1517, R12
+ B callbackasm1(SB)
+ MOVD $1518, R12
+ B callbackasm1(SB)
+ MOVD $1519, R12
+ B callbackasm1(SB)
+ MOVD $1520, R12
+ B callbackasm1(SB)
+ MOVD $1521, R12
+ B callbackasm1(SB)
+ MOVD $1522, R12
+ B callbackasm1(SB)
+ MOVD $1523, R12
+ B callbackasm1(SB)
+ MOVD $1524, R12
+ B callbackasm1(SB)
+ MOVD $1525, R12
+ B callbackasm1(SB)
+ MOVD $1526, R12
+ B callbackasm1(SB)
+ MOVD $1527, R12
+ B callbackasm1(SB)
+ MOVD $1528, R12
+ B callbackasm1(SB)
+ MOVD $1529, R12
+ B callbackasm1(SB)
+ MOVD $1530, R12
+ B callbackasm1(SB)
+ MOVD $1531, R12
+ B callbackasm1(SB)
+ MOVD $1532, R12
+ B callbackasm1(SB)
+ MOVD $1533, R12
+ B callbackasm1(SB)
+ MOVD $1534, R12
+ B callbackasm1(SB)
+ MOVD $1535, R12
+ B callbackasm1(SB)
+ MOVD $1536, R12
+ B callbackasm1(SB)
+ MOVD $1537, R12
+ B callbackasm1(SB)
+ MOVD $1538, R12
+ B callbackasm1(SB)
+ MOVD $1539, R12
+ B callbackasm1(SB)
+ MOVD $1540, R12
+ B callbackasm1(SB)
+ MOVD $1541, R12
+ B callbackasm1(SB)
+ MOVD $1542, R12
+ B callbackasm1(SB)
+ MOVD $1543, R12
+ B callbackasm1(SB)
+ MOVD $1544, R12
+ B callbackasm1(SB)
+ MOVD $1545, R12
+ B callbackasm1(SB)
+ MOVD $1546, R12
+ B callbackasm1(SB)
+ MOVD $1547, R12
+ B callbackasm1(SB)
+ MOVD $1548, R12
+ B callbackasm1(SB)
+ MOVD $1549, R12
+ B callbackasm1(SB)
+ MOVD $1550, R12
+ B callbackasm1(SB)
+ MOVD $1551, R12
+ B callbackasm1(SB)
+ MOVD $1552, R12
+ B callbackasm1(SB)
+ MOVD $1553, R12
+ B callbackasm1(SB)
+ MOVD $1554, R12
+ B callbackasm1(SB)
+ MOVD $1555, R12
+ B callbackasm1(SB)
+ MOVD $1556, R12
+ B callbackasm1(SB)
+ MOVD $1557, R12
+ B callbackasm1(SB)
+ MOVD $1558, R12
+ B callbackasm1(SB)
+ MOVD $1559, R12
+ B callbackasm1(SB)
+ MOVD $1560, R12
+ B callbackasm1(SB)
+ MOVD $1561, R12
+ B callbackasm1(SB)
+ MOVD $1562, R12
+ B callbackasm1(SB)
+ MOVD $1563, R12
+ B callbackasm1(SB)
+ MOVD $1564, R12
+ B callbackasm1(SB)
+ MOVD $1565, R12
+ B callbackasm1(SB)
+ MOVD $1566, R12
+ B callbackasm1(SB)
+ MOVD $1567, R12
+ B callbackasm1(SB)
+ MOVD $1568, R12
+ B callbackasm1(SB)
+ MOVD $1569, R12
+ B callbackasm1(SB)
+ MOVD $1570, R12
+ B callbackasm1(SB)
+ MOVD $1571, R12
+ B callbackasm1(SB)
+ MOVD $1572, R12
+ B callbackasm1(SB)
+ MOVD $1573, R12
+ B callbackasm1(SB)
+ MOVD $1574, R12
+ B callbackasm1(SB)
+ MOVD $1575, R12
+ B callbackasm1(SB)
+ MOVD $1576, R12
+ B callbackasm1(SB)
+ MOVD $1577, R12
+ B callbackasm1(SB)
+ MOVD $1578, R12
+ B callbackasm1(SB)
+ MOVD $1579, R12
+ B callbackasm1(SB)
+ MOVD $1580, R12
+ B callbackasm1(SB)
+ MOVD $1581, R12
+ B callbackasm1(SB)
+ MOVD $1582, R12
+ B callbackasm1(SB)
+ MOVD $1583, R12
+ B callbackasm1(SB)
+ MOVD $1584, R12
+ B callbackasm1(SB)
+ MOVD $1585, R12
+ B callbackasm1(SB)
+ MOVD $1586, R12
+ B callbackasm1(SB)
+ MOVD $1587, R12
+ B callbackasm1(SB)
+ MOVD $1588, R12
+ B callbackasm1(SB)
+ MOVD $1589, R12
+ B callbackasm1(SB)
+ MOVD $1590, R12
+ B callbackasm1(SB)
+ MOVD $1591, R12
+ B callbackasm1(SB)
+ MOVD $1592, R12
+ B callbackasm1(SB)
+ MOVD $1593, R12
+ B callbackasm1(SB)
+ MOVD $1594, R12
+ B callbackasm1(SB)
+ MOVD $1595, R12
+ B callbackasm1(SB)
+ MOVD $1596, R12
+ B callbackasm1(SB)
+ MOVD $1597, R12
+ B callbackasm1(SB)
+ MOVD $1598, R12
+ B callbackasm1(SB)
+ MOVD $1599, R12
+ B callbackasm1(SB)
+ MOVD $1600, R12
+ B callbackasm1(SB)
+ MOVD $1601, R12
+ B callbackasm1(SB)
+ MOVD $1602, R12
+ B callbackasm1(SB)
+ MOVD $1603, R12
+ B callbackasm1(SB)
+ MOVD $1604, R12
+ B callbackasm1(SB)
+ MOVD $1605, R12
+ B callbackasm1(SB)
+ MOVD $1606, R12
+ B callbackasm1(SB)
+ MOVD $1607, R12
+ B callbackasm1(SB)
+ MOVD $1608, R12
+ B callbackasm1(SB)
+ MOVD $1609, R12
+ B callbackasm1(SB)
+ MOVD $1610, R12
+ B callbackasm1(SB)
+ MOVD $1611, R12
+ B callbackasm1(SB)
+ MOVD $1612, R12
+ B callbackasm1(SB)
+ MOVD $1613, R12
+ B callbackasm1(SB)
+ MOVD $1614, R12
+ B callbackasm1(SB)
+ MOVD $1615, R12
+ B callbackasm1(SB)
+ MOVD $1616, R12
+ B callbackasm1(SB)
+ MOVD $1617, R12
+ B callbackasm1(SB)
+ MOVD $1618, R12
+ B callbackasm1(SB)
+ MOVD $1619, R12
+ B callbackasm1(SB)
+ MOVD $1620, R12
+ B callbackasm1(SB)
+ MOVD $1621, R12
+ B callbackasm1(SB)
+ MOVD $1622, R12
+ B callbackasm1(SB)
+ MOVD $1623, R12
+ B callbackasm1(SB)
+ MOVD $1624, R12
+ B callbackasm1(SB)
+ MOVD $1625, R12
+ B callbackasm1(SB)
+ MOVD $1626, R12
+ B callbackasm1(SB)
+ MOVD $1627, R12
+ B callbackasm1(SB)
+ MOVD $1628, R12
+ B callbackasm1(SB)
+ MOVD $1629, R12
+ B callbackasm1(SB)
+ MOVD $1630, R12
+ B callbackasm1(SB)
+ MOVD $1631, R12
+ B callbackasm1(SB)
+ MOVD $1632, R12
+ B callbackasm1(SB)
+ MOVD $1633, R12
+ B callbackasm1(SB)
+ MOVD $1634, R12
+ B callbackasm1(SB)
+ MOVD $1635, R12
+ B callbackasm1(SB)
+ MOVD $1636, R12
+ B callbackasm1(SB)
+ MOVD $1637, R12
+ B callbackasm1(SB)
+ MOVD $1638, R12
+ B callbackasm1(SB)
+ MOVD $1639, R12
+ B callbackasm1(SB)
+ MOVD $1640, R12
+ B callbackasm1(SB)
+ MOVD $1641, R12
+ B callbackasm1(SB)
+ MOVD $1642, R12
+ B callbackasm1(SB)
+ MOVD $1643, R12
+ B callbackasm1(SB)
+ MOVD $1644, R12
+ B callbackasm1(SB)
+ MOVD $1645, R12
+ B callbackasm1(SB)
+ MOVD $1646, R12
+ B callbackasm1(SB)
+ MOVD $1647, R12
+ B callbackasm1(SB)
+ MOVD $1648, R12
+ B callbackasm1(SB)
+ MOVD $1649, R12
+ B callbackasm1(SB)
+ MOVD $1650, R12
+ B callbackasm1(SB)
+ MOVD $1651, R12
+ B callbackasm1(SB)
+ MOVD $1652, R12
+ B callbackasm1(SB)
+ MOVD $1653, R12
+ B callbackasm1(SB)
+ MOVD $1654, R12
+ B callbackasm1(SB)
+ MOVD $1655, R12
+ B callbackasm1(SB)
+ MOVD $1656, R12
+ B callbackasm1(SB)
+ MOVD $1657, R12
+ B callbackasm1(SB)
+ MOVD $1658, R12
+ B callbackasm1(SB)
+ MOVD $1659, R12
+ B callbackasm1(SB)
+ MOVD $1660, R12
+ B callbackasm1(SB)
+ MOVD $1661, R12
+ B callbackasm1(SB)
+ MOVD $1662, R12
+ B callbackasm1(SB)
+ MOVD $1663, R12
+ B callbackasm1(SB)
+ MOVD $1664, R12
+ B callbackasm1(SB)
+ MOVD $1665, R12
+ B callbackasm1(SB)
+ MOVD $1666, R12
+ B callbackasm1(SB)
+ MOVD $1667, R12
+ B callbackasm1(SB)
+ MOVD $1668, R12
+ B callbackasm1(SB)
+ MOVD $1669, R12
+ B callbackasm1(SB)
+ MOVD $1670, R12
+ B callbackasm1(SB)
+ MOVD $1671, R12
+ B callbackasm1(SB)
+ MOVD $1672, R12
+ B callbackasm1(SB)
+ MOVD $1673, R12
+ B callbackasm1(SB)
+ MOVD $1674, R12
+ B callbackasm1(SB)
+ MOVD $1675, R12
+ B callbackasm1(SB)
+ MOVD $1676, R12
+ B callbackasm1(SB)
+ MOVD $1677, R12
+ B callbackasm1(SB)
+ MOVD $1678, R12
+ B callbackasm1(SB)
+ MOVD $1679, R12
+ B callbackasm1(SB)
+ MOVD $1680, R12
+ B callbackasm1(SB)
+ MOVD $1681, R12
+ B callbackasm1(SB)
+ MOVD $1682, R12
+ B callbackasm1(SB)
+ MOVD $1683, R12
+ B callbackasm1(SB)
+ MOVD $1684, R12
+ B callbackasm1(SB)
+ MOVD $1685, R12
+ B callbackasm1(SB)
+ MOVD $1686, R12
+ B callbackasm1(SB)
+ MOVD $1687, R12
+ B callbackasm1(SB)
+ MOVD $1688, R12
+ B callbackasm1(SB)
+ MOVD $1689, R12
+ B callbackasm1(SB)
+ MOVD $1690, R12
+ B callbackasm1(SB)
+ MOVD $1691, R12
+ B callbackasm1(SB)
+ MOVD $1692, R12
+ B callbackasm1(SB)
+ MOVD $1693, R12
+ B callbackasm1(SB)
+ MOVD $1694, R12
+ B callbackasm1(SB)
+ MOVD $1695, R12
+ B callbackasm1(SB)
+ MOVD $1696, R12
+ B callbackasm1(SB)
+ MOVD $1697, R12
+ B callbackasm1(SB)
+ MOVD $1698, R12
+ B callbackasm1(SB)
+ MOVD $1699, R12
+ B callbackasm1(SB)
+ MOVD $1700, R12
+ B callbackasm1(SB)
+ MOVD $1701, R12
+ B callbackasm1(SB)
+ MOVD $1702, R12
+ B callbackasm1(SB)
+ MOVD $1703, R12
+ B callbackasm1(SB)
+ MOVD $1704, R12
+ B callbackasm1(SB)
+ MOVD $1705, R12
+ B callbackasm1(SB)
+ MOVD $1706, R12
+ B callbackasm1(SB)
+ MOVD $1707, R12
+ B callbackasm1(SB)
+ MOVD $1708, R12
+ B callbackasm1(SB)
+ MOVD $1709, R12
+ B callbackasm1(SB)
+ MOVD $1710, R12
+ B callbackasm1(SB)
+ MOVD $1711, R12
+ B callbackasm1(SB)
+ MOVD $1712, R12
+ B callbackasm1(SB)
+ MOVD $1713, R12
+ B callbackasm1(SB)
+ MOVD $1714, R12
+ B callbackasm1(SB)
+ MOVD $1715, R12
+ B callbackasm1(SB)
+ MOVD $1716, R12
+ B callbackasm1(SB)
+ MOVD $1717, R12
+ B callbackasm1(SB)
+ MOVD $1718, R12
+ B callbackasm1(SB)
+ MOVD $1719, R12
+ B callbackasm1(SB)
+ MOVD $1720, R12
+ B callbackasm1(SB)
+ MOVD $1721, R12
+ B callbackasm1(SB)
+ MOVD $1722, R12
+ B callbackasm1(SB)
+ MOVD $1723, R12
+ B callbackasm1(SB)
+ MOVD $1724, R12
+ B callbackasm1(SB)
+ MOVD $1725, R12
+ B callbackasm1(SB)
+ MOVD $1726, R12
+ B callbackasm1(SB)
+ MOVD $1727, R12
+ B callbackasm1(SB)
+ MOVD $1728, R12
+ B callbackasm1(SB)
+ MOVD $1729, R12
+ B callbackasm1(SB)
+ MOVD $1730, R12
+ B callbackasm1(SB)
+ MOVD $1731, R12
+ B callbackasm1(SB)
+ MOVD $1732, R12
+ B callbackasm1(SB)
+ MOVD $1733, R12
+ B callbackasm1(SB)
+ MOVD $1734, R12
+ B callbackasm1(SB)
+ MOVD $1735, R12
+ B callbackasm1(SB)
+ MOVD $1736, R12
+ B callbackasm1(SB)
+ MOVD $1737, R12
+ B callbackasm1(SB)
+ MOVD $1738, R12
+ B callbackasm1(SB)
+ MOVD $1739, R12
+ B callbackasm1(SB)
+ MOVD $1740, R12
+ B callbackasm1(SB)
+ MOVD $1741, R12
+ B callbackasm1(SB)
+ MOVD $1742, R12
+ B callbackasm1(SB)
+ MOVD $1743, R12
+ B callbackasm1(SB)
+ MOVD $1744, R12
+ B callbackasm1(SB)
+ MOVD $1745, R12
+ B callbackasm1(SB)
+ MOVD $1746, R12
+ B callbackasm1(SB)
+ MOVD $1747, R12
+ B callbackasm1(SB)
+ MOVD $1748, R12
+ B callbackasm1(SB)
+ MOVD $1749, R12
+ B callbackasm1(SB)
+ MOVD $1750, R12
+ B callbackasm1(SB)
+ MOVD $1751, R12
+ B callbackasm1(SB)
+ MOVD $1752, R12
+ B callbackasm1(SB)
+ MOVD $1753, R12
+ B callbackasm1(SB)
+ MOVD $1754, R12
+ B callbackasm1(SB)
+ MOVD $1755, R12
+ B callbackasm1(SB)
+ MOVD $1756, R12
+ B callbackasm1(SB)
+ MOVD $1757, R12
+ B callbackasm1(SB)
+ MOVD $1758, R12
+ B callbackasm1(SB)
+ MOVD $1759, R12
+ B callbackasm1(SB)
+ MOVD $1760, R12
+ B callbackasm1(SB)
+ MOVD $1761, R12
+ B callbackasm1(SB)
+ MOVD $1762, R12
+ B callbackasm1(SB)
+ MOVD $1763, R12
+ B callbackasm1(SB)
+ MOVD $1764, R12
+ B callbackasm1(SB)
+ MOVD $1765, R12
+ B callbackasm1(SB)
+ MOVD $1766, R12
+ B callbackasm1(SB)
+ MOVD $1767, R12
+ B callbackasm1(SB)
+ MOVD $1768, R12
+ B callbackasm1(SB)
+ MOVD $1769, R12
+ B callbackasm1(SB)
+ MOVD $1770, R12
+ B callbackasm1(SB)
+ MOVD $1771, R12
+ B callbackasm1(SB)
+ MOVD $1772, R12
+ B callbackasm1(SB)
+ MOVD $1773, R12
+ B callbackasm1(SB)
+ MOVD $1774, R12
+ B callbackasm1(SB)
+ MOVD $1775, R12
+ B callbackasm1(SB)
+ MOVD $1776, R12
+ B callbackasm1(SB)
+ MOVD $1777, R12
+ B callbackasm1(SB)
+ MOVD $1778, R12
+ B callbackasm1(SB)
+ MOVD $1779, R12
+ B callbackasm1(SB)
+ MOVD $1780, R12
+ B callbackasm1(SB)
+ MOVD $1781, R12
+ B callbackasm1(SB)
+ MOVD $1782, R12
+ B callbackasm1(SB)
+ MOVD $1783, R12
+ B callbackasm1(SB)
+ MOVD $1784, R12
+ B callbackasm1(SB)
+ MOVD $1785, R12
+ B callbackasm1(SB)
+ MOVD $1786, R12
+ B callbackasm1(SB)
+ MOVD $1787, R12
+ B callbackasm1(SB)
+ MOVD $1788, R12
+ B callbackasm1(SB)
+ MOVD $1789, R12
+ B callbackasm1(SB)
+ MOVD $1790, R12
+ B callbackasm1(SB)
+ MOVD $1791, R12
+ B callbackasm1(SB)
+ MOVD $1792, R12
+ B callbackasm1(SB)
+ MOVD $1793, R12
+ B callbackasm1(SB)
+ MOVD $1794, R12
+ B callbackasm1(SB)
+ MOVD $1795, R12
+ B callbackasm1(SB)
+ MOVD $1796, R12
+ B callbackasm1(SB)
+ MOVD $1797, R12
+ B callbackasm1(SB)
+ MOVD $1798, R12
+ B callbackasm1(SB)
+ MOVD $1799, R12
+ B callbackasm1(SB)
+ MOVD $1800, R12
+ B callbackasm1(SB)
+ MOVD $1801, R12
+ B callbackasm1(SB)
+ MOVD $1802, R12
+ B callbackasm1(SB)
+ MOVD $1803, R12
+ B callbackasm1(SB)
+ MOVD $1804, R12
+ B callbackasm1(SB)
+ MOVD $1805, R12
+ B callbackasm1(SB)
+ MOVD $1806, R12
+ B callbackasm1(SB)
+ MOVD $1807, R12
+ B callbackasm1(SB)
+ MOVD $1808, R12
+ B callbackasm1(SB)
+ MOVD $1809, R12
+ B callbackasm1(SB)
+ MOVD $1810, R12
+ B callbackasm1(SB)
+ MOVD $1811, R12
+ B callbackasm1(SB)
+ MOVD $1812, R12
+ B callbackasm1(SB)
+ MOVD $1813, R12
+ B callbackasm1(SB)
+ MOVD $1814, R12
+ B callbackasm1(SB)
+ MOVD $1815, R12
+ B callbackasm1(SB)
+ MOVD $1816, R12
+ B callbackasm1(SB)
+ MOVD $1817, R12
+ B callbackasm1(SB)
+ MOVD $1818, R12
+ B callbackasm1(SB)
+ MOVD $1819, R12
+ B callbackasm1(SB)
+ MOVD $1820, R12
+ B callbackasm1(SB)
+ MOVD $1821, R12
+ B callbackasm1(SB)
+ MOVD $1822, R12
+ B callbackasm1(SB)
+ MOVD $1823, R12
+ B callbackasm1(SB)
+ MOVD $1824, R12
+ B callbackasm1(SB)
+ MOVD $1825, R12
+ B callbackasm1(SB)
+ MOVD $1826, R12
+ B callbackasm1(SB)
+ MOVD $1827, R12
+ B callbackasm1(SB)
+ MOVD $1828, R12
+ B callbackasm1(SB)
+ MOVD $1829, R12
+ B callbackasm1(SB)
+ MOVD $1830, R12
+ B callbackasm1(SB)
+ MOVD $1831, R12
+ B callbackasm1(SB)
+ MOVD $1832, R12
+ B callbackasm1(SB)
+ MOVD $1833, R12
+ B callbackasm1(SB)
+ MOVD $1834, R12
+ B callbackasm1(SB)
+ MOVD $1835, R12
+ B callbackasm1(SB)
+ MOVD $1836, R12
+ B callbackasm1(SB)
+ MOVD $1837, R12
+ B callbackasm1(SB)
+ MOVD $1838, R12
+ B callbackasm1(SB)
+ MOVD $1839, R12
+ B callbackasm1(SB)
+ MOVD $1840, R12
+ B callbackasm1(SB)
+ MOVD $1841, R12
+ B callbackasm1(SB)
+ MOVD $1842, R12
+ B callbackasm1(SB)
+ MOVD $1843, R12
+ B callbackasm1(SB)
+ MOVD $1844, R12
+ B callbackasm1(SB)
+ MOVD $1845, R12
+ B callbackasm1(SB)
+ MOVD $1846, R12
+ B callbackasm1(SB)
+ MOVD $1847, R12
+ B callbackasm1(SB)
+ MOVD $1848, R12
+ B callbackasm1(SB)
+ MOVD $1849, R12
+ B callbackasm1(SB)
+ MOVD $1850, R12
+ B callbackasm1(SB)
+ MOVD $1851, R12
+ B callbackasm1(SB)
+ MOVD $1852, R12
+ B callbackasm1(SB)
+ MOVD $1853, R12
+ B callbackasm1(SB)
+ MOVD $1854, R12
+ B callbackasm1(SB)
+ MOVD $1855, R12
+ B callbackasm1(SB)
+ MOVD $1856, R12
+ B callbackasm1(SB)
+ MOVD $1857, R12
+ B callbackasm1(SB)
+ MOVD $1858, R12
+ B callbackasm1(SB)
+ MOVD $1859, R12
+ B callbackasm1(SB)
+ MOVD $1860, R12
+ B callbackasm1(SB)
+ MOVD $1861, R12
+ B callbackasm1(SB)
+ MOVD $1862, R12
+ B callbackasm1(SB)
+ MOVD $1863, R12
+ B callbackasm1(SB)
+ MOVD $1864, R12
+ B callbackasm1(SB)
+ MOVD $1865, R12
+ B callbackasm1(SB)
+ MOVD $1866, R12
+ B callbackasm1(SB)
+ MOVD $1867, R12
+ B callbackasm1(SB)
+ MOVD $1868, R12
+ B callbackasm1(SB)
+ MOVD $1869, R12
+ B callbackasm1(SB)
+ MOVD $1870, R12
+ B callbackasm1(SB)
+ MOVD $1871, R12
+ B callbackasm1(SB)
+ MOVD $1872, R12
+ B callbackasm1(SB)
+ MOVD $1873, R12
+ B callbackasm1(SB)
+ MOVD $1874, R12
+ B callbackasm1(SB)
+ MOVD $1875, R12
+ B callbackasm1(SB)
+ MOVD $1876, R12
+ B callbackasm1(SB)
+ MOVD $1877, R12
+ B callbackasm1(SB)
+ MOVD $1878, R12
+ B callbackasm1(SB)
+ MOVD $1879, R12
+ B callbackasm1(SB)
+ MOVD $1880, R12
+ B callbackasm1(SB)
+ MOVD $1881, R12
+ B callbackasm1(SB)
+ MOVD $1882, R12
+ B callbackasm1(SB)
+ MOVD $1883, R12
+ B callbackasm1(SB)
+ MOVD $1884, R12
+ B callbackasm1(SB)
+ MOVD $1885, R12
+ B callbackasm1(SB)
+ MOVD $1886, R12
+ B callbackasm1(SB)
+ MOVD $1887, R12
+ B callbackasm1(SB)
+ MOVD $1888, R12
+ B callbackasm1(SB)
+ MOVD $1889, R12
+ B callbackasm1(SB)
+ MOVD $1890, R12
+ B callbackasm1(SB)
+ MOVD $1891, R12
+ B callbackasm1(SB)
+ MOVD $1892, R12
+ B callbackasm1(SB)
+ MOVD $1893, R12
+ B callbackasm1(SB)
+ MOVD $1894, R12
+ B callbackasm1(SB)
+ MOVD $1895, R12
+ B callbackasm1(SB)
+ MOVD $1896, R12
+ B callbackasm1(SB)
+ MOVD $1897, R12
+ B callbackasm1(SB)
+ MOVD $1898, R12
+ B callbackasm1(SB)
+ MOVD $1899, R12
+ B callbackasm1(SB)
+ MOVD $1900, R12
+ B callbackasm1(SB)
+ MOVD $1901, R12
+ B callbackasm1(SB)
+ MOVD $1902, R12
+ B callbackasm1(SB)
+ MOVD $1903, R12
+ B callbackasm1(SB)
+ MOVD $1904, R12
+ B callbackasm1(SB)
+ MOVD $1905, R12
+ B callbackasm1(SB)
+ MOVD $1906, R12
+ B callbackasm1(SB)
+ MOVD $1907, R12
+ B callbackasm1(SB)
+ MOVD $1908, R12
+ B callbackasm1(SB)
+ MOVD $1909, R12
+ B callbackasm1(SB)
+ MOVD $1910, R12
+ B callbackasm1(SB)
+ MOVD $1911, R12
+ B callbackasm1(SB)
+ MOVD $1912, R12
+ B callbackasm1(SB)
+ MOVD $1913, R12
+ B callbackasm1(SB)
+ MOVD $1914, R12
+ B callbackasm1(SB)
+ MOVD $1915, R12
+ B callbackasm1(SB)
+ MOVD $1916, R12
+ B callbackasm1(SB)
+ MOVD $1917, R12
+ B callbackasm1(SB)
+ MOVD $1918, R12
+ B callbackasm1(SB)
+ MOVD $1919, R12
+ B callbackasm1(SB)
+ MOVD $1920, R12
+ B callbackasm1(SB)
+ MOVD $1921, R12
+ B callbackasm1(SB)
+ MOVD $1922, R12
+ B callbackasm1(SB)
+ MOVD $1923, R12
+ B callbackasm1(SB)
+ MOVD $1924, R12
+ B callbackasm1(SB)
+ MOVD $1925, R12
+ B callbackasm1(SB)
+ MOVD $1926, R12
+ B callbackasm1(SB)
+ MOVD $1927, R12
+ B callbackasm1(SB)
+ MOVD $1928, R12
+ B callbackasm1(SB)
+ MOVD $1929, R12
+ B callbackasm1(SB)
+ MOVD $1930, R12
+ B callbackasm1(SB)
+ MOVD $1931, R12
+ B callbackasm1(SB)
+ MOVD $1932, R12
+ B callbackasm1(SB)
+ MOVD $1933, R12
+ B callbackasm1(SB)
+ MOVD $1934, R12
+ B callbackasm1(SB)
+ MOVD $1935, R12
+ B callbackasm1(SB)
+ MOVD $1936, R12
+ B callbackasm1(SB)
+ MOVD $1937, R12
+ B callbackasm1(SB)
+ MOVD $1938, R12
+ B callbackasm1(SB)
+ MOVD $1939, R12
+ B callbackasm1(SB)
+ MOVD $1940, R12
+ B callbackasm1(SB)
+ MOVD $1941, R12
+ B callbackasm1(SB)
+ MOVD $1942, R12
+ B callbackasm1(SB)
+ MOVD $1943, R12
+ B callbackasm1(SB)
+ MOVD $1944, R12
+ B callbackasm1(SB)
+ MOVD $1945, R12
+ B callbackasm1(SB)
+ MOVD $1946, R12
+ B callbackasm1(SB)
+ MOVD $1947, R12
+ B callbackasm1(SB)
+ MOVD $1948, R12
+ B callbackasm1(SB)
+ MOVD $1949, R12
+ B callbackasm1(SB)
+ MOVD $1950, R12
+ B callbackasm1(SB)
+ MOVD $1951, R12
+ B callbackasm1(SB)
+ MOVD $1952, R12
+ B callbackasm1(SB)
+ MOVD $1953, R12
+ B callbackasm1(SB)
+ MOVD $1954, R12
+ B callbackasm1(SB)
+ MOVD $1955, R12
+ B callbackasm1(SB)
+ MOVD $1956, R12
+ B callbackasm1(SB)
+ MOVD $1957, R12
+ B callbackasm1(SB)
+ MOVD $1958, R12
+ B callbackasm1(SB)
+ MOVD $1959, R12
+ B callbackasm1(SB)
+ MOVD $1960, R12
+ B callbackasm1(SB)
+ MOVD $1961, R12
+ B callbackasm1(SB)
+ MOVD $1962, R12
+ B callbackasm1(SB)
+ MOVD $1963, R12
+ B callbackasm1(SB)
+ MOVD $1964, R12
+ B callbackasm1(SB)
+ MOVD $1965, R12
+ B callbackasm1(SB)
+ MOVD $1966, R12
+ B callbackasm1(SB)
+ MOVD $1967, R12
+ B callbackasm1(SB)
+ MOVD $1968, R12
+ B callbackasm1(SB)
+ MOVD $1969, R12
+ B callbackasm1(SB)
+ MOVD $1970, R12
+ B callbackasm1(SB)
+ MOVD $1971, R12
+ B callbackasm1(SB)
+ MOVD $1972, R12
+ B callbackasm1(SB)
+ MOVD $1973, R12
+ B callbackasm1(SB)
+ MOVD $1974, R12
+ B callbackasm1(SB)
+ MOVD $1975, R12
+ B callbackasm1(SB)
+ MOVD $1976, R12
+ B callbackasm1(SB)
+ MOVD $1977, R12
+ B callbackasm1(SB)
+ MOVD $1978, R12
+ B callbackasm1(SB)
+ MOVD $1979, R12
+ B callbackasm1(SB)
+ MOVD $1980, R12
+ B callbackasm1(SB)
+ MOVD $1981, R12
+ B callbackasm1(SB)
+ MOVD $1982, R12
+ B callbackasm1(SB)
+ MOVD $1983, R12
+ B callbackasm1(SB)
+ MOVD $1984, R12
+ B callbackasm1(SB)
+ MOVD $1985, R12
+ B callbackasm1(SB)
+ MOVD $1986, R12
+ B callbackasm1(SB)
+ MOVD $1987, R12
+ B callbackasm1(SB)
+ MOVD $1988, R12
+ B callbackasm1(SB)
+ MOVD $1989, R12
+ B callbackasm1(SB)
+ MOVD $1990, R12
+ B callbackasm1(SB)
+ MOVD $1991, R12
+ B callbackasm1(SB)
+ MOVD $1992, R12
+ B callbackasm1(SB)
+ MOVD $1993, R12
+ B callbackasm1(SB)
+ MOVD $1994, R12
+ B callbackasm1(SB)
+ MOVD $1995, R12
+ B callbackasm1(SB)
+ MOVD $1996, R12
+ B callbackasm1(SB)
+ MOVD $1997, R12
+ B callbackasm1(SB)
+ MOVD $1998, R12
+ B callbackasm1(SB)
+ MOVD $1999, R12
+ B callbackasm1(SB)
diff --git a/raymenu/vendor/github.com/ebitengine/purego/zcallback_loong64.s b/raymenu/vendor/github.com/ebitengine/purego/zcallback_loong64.s
new file mode 100644
index 0000000..c5dcd48
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/zcallback_loong64.s
@@ -0,0 +1,4014 @@
+// Code generated by wincallback.go using 'go generate'. DO NOT EDIT.
+
+//go:build darwin || freebsd || linux || netbsd
+
+// External code calls into callbackasm at an offset corresponding
+// to the callback index. Callbackasm is a table of MOVV and JMP instructions.
+// The MOVV instruction loads R12 with the callback index, and the
+// JMP instruction branches to callbackasm1.
+// callbackasm1 takes the callback index from R12 and
+// indexes into an array that stores information about each callback.
+// It then calls the Go implementation for that callback.
+#include "textflag.h"
+
+TEXT callbackasm(SB), NOSPLIT|NOFRAME, $0
+ MOVV $0, R12
+ JMP callbackasm1(SB)
+ MOVV $1, R12
+ JMP callbackasm1(SB)
+ MOVV $2, R12
+ JMP callbackasm1(SB)
+ MOVV $3, R12
+ JMP callbackasm1(SB)
+ MOVV $4, R12
+ JMP callbackasm1(SB)
+ MOVV $5, R12
+ JMP callbackasm1(SB)
+ MOVV $6, R12
+ JMP callbackasm1(SB)
+ MOVV $7, R12
+ JMP callbackasm1(SB)
+ MOVV $8, R12
+ JMP callbackasm1(SB)
+ MOVV $9, R12
+ JMP callbackasm1(SB)
+ MOVV $10, R12
+ JMP callbackasm1(SB)
+ MOVV $11, R12
+ JMP callbackasm1(SB)
+ MOVV $12, R12
+ JMP callbackasm1(SB)
+ MOVV $13, R12
+ JMP callbackasm1(SB)
+ MOVV $14, R12
+ JMP callbackasm1(SB)
+ MOVV $15, R12
+ JMP callbackasm1(SB)
+ MOVV $16, R12
+ JMP callbackasm1(SB)
+ MOVV $17, R12
+ JMP callbackasm1(SB)
+ MOVV $18, R12
+ JMP callbackasm1(SB)
+ MOVV $19, R12
+ JMP callbackasm1(SB)
+ MOVV $20, R12
+ JMP callbackasm1(SB)
+ MOVV $21, R12
+ JMP callbackasm1(SB)
+ MOVV $22, R12
+ JMP callbackasm1(SB)
+ MOVV $23, R12
+ JMP callbackasm1(SB)
+ MOVV $24, R12
+ JMP callbackasm1(SB)
+ MOVV $25, R12
+ JMP callbackasm1(SB)
+ MOVV $26, R12
+ JMP callbackasm1(SB)
+ MOVV $27, R12
+ JMP callbackasm1(SB)
+ MOVV $28, R12
+ JMP callbackasm1(SB)
+ MOVV $29, R12
+ JMP callbackasm1(SB)
+ MOVV $30, R12
+ JMP callbackasm1(SB)
+ MOVV $31, R12
+ JMP callbackasm1(SB)
+ MOVV $32, R12
+ JMP callbackasm1(SB)
+ MOVV $33, R12
+ JMP callbackasm1(SB)
+ MOVV $34, R12
+ JMP callbackasm1(SB)
+ MOVV $35, R12
+ JMP callbackasm1(SB)
+ MOVV $36, R12
+ JMP callbackasm1(SB)
+ MOVV $37, R12
+ JMP callbackasm1(SB)
+ MOVV $38, R12
+ JMP callbackasm1(SB)
+ MOVV $39, R12
+ JMP callbackasm1(SB)
+ MOVV $40, R12
+ JMP callbackasm1(SB)
+ MOVV $41, R12
+ JMP callbackasm1(SB)
+ MOVV $42, R12
+ JMP callbackasm1(SB)
+ MOVV $43, R12
+ JMP callbackasm1(SB)
+ MOVV $44, R12
+ JMP callbackasm1(SB)
+ MOVV $45, R12
+ JMP callbackasm1(SB)
+ MOVV $46, R12
+ JMP callbackasm1(SB)
+ MOVV $47, R12
+ JMP callbackasm1(SB)
+ MOVV $48, R12
+ JMP callbackasm1(SB)
+ MOVV $49, R12
+ JMP callbackasm1(SB)
+ MOVV $50, R12
+ JMP callbackasm1(SB)
+ MOVV $51, R12
+ JMP callbackasm1(SB)
+ MOVV $52, R12
+ JMP callbackasm1(SB)
+ MOVV $53, R12
+ JMP callbackasm1(SB)
+ MOVV $54, R12
+ JMP callbackasm1(SB)
+ MOVV $55, R12
+ JMP callbackasm1(SB)
+ MOVV $56, R12
+ JMP callbackasm1(SB)
+ MOVV $57, R12
+ JMP callbackasm1(SB)
+ MOVV $58, R12
+ JMP callbackasm1(SB)
+ MOVV $59, R12
+ JMP callbackasm1(SB)
+ MOVV $60, R12
+ JMP callbackasm1(SB)
+ MOVV $61, R12
+ JMP callbackasm1(SB)
+ MOVV $62, R12
+ JMP callbackasm1(SB)
+ MOVV $63, R12
+ JMP callbackasm1(SB)
+ MOVV $64, R12
+ JMP callbackasm1(SB)
+ MOVV $65, R12
+ JMP callbackasm1(SB)
+ MOVV $66, R12
+ JMP callbackasm1(SB)
+ MOVV $67, R12
+ JMP callbackasm1(SB)
+ MOVV $68, R12
+ JMP callbackasm1(SB)
+ MOVV $69, R12
+ JMP callbackasm1(SB)
+ MOVV $70, R12
+ JMP callbackasm1(SB)
+ MOVV $71, R12
+ JMP callbackasm1(SB)
+ MOVV $72, R12
+ JMP callbackasm1(SB)
+ MOVV $73, R12
+ JMP callbackasm1(SB)
+ MOVV $74, R12
+ JMP callbackasm1(SB)
+ MOVV $75, R12
+ JMP callbackasm1(SB)
+ MOVV $76, R12
+ JMP callbackasm1(SB)
+ MOVV $77, R12
+ JMP callbackasm1(SB)
+ MOVV $78, R12
+ JMP callbackasm1(SB)
+ MOVV $79, R12
+ JMP callbackasm1(SB)
+ MOVV $80, R12
+ JMP callbackasm1(SB)
+ MOVV $81, R12
+ JMP callbackasm1(SB)
+ MOVV $82, R12
+ JMP callbackasm1(SB)
+ MOVV $83, R12
+ JMP callbackasm1(SB)
+ MOVV $84, R12
+ JMP callbackasm1(SB)
+ MOVV $85, R12
+ JMP callbackasm1(SB)
+ MOVV $86, R12
+ JMP callbackasm1(SB)
+ MOVV $87, R12
+ JMP callbackasm1(SB)
+ MOVV $88, R12
+ JMP callbackasm1(SB)
+ MOVV $89, R12
+ JMP callbackasm1(SB)
+ MOVV $90, R12
+ JMP callbackasm1(SB)
+ MOVV $91, R12
+ JMP callbackasm1(SB)
+ MOVV $92, R12
+ JMP callbackasm1(SB)
+ MOVV $93, R12
+ JMP callbackasm1(SB)
+ MOVV $94, R12
+ JMP callbackasm1(SB)
+ MOVV $95, R12
+ JMP callbackasm1(SB)
+ MOVV $96, R12
+ JMP callbackasm1(SB)
+ MOVV $97, R12
+ JMP callbackasm1(SB)
+ MOVV $98, R12
+ JMP callbackasm1(SB)
+ MOVV $99, R12
+ JMP callbackasm1(SB)
+ MOVV $100, R12
+ JMP callbackasm1(SB)
+ MOVV $101, R12
+ JMP callbackasm1(SB)
+ MOVV $102, R12
+ JMP callbackasm1(SB)
+ MOVV $103, R12
+ JMP callbackasm1(SB)
+ MOVV $104, R12
+ JMP callbackasm1(SB)
+ MOVV $105, R12
+ JMP callbackasm1(SB)
+ MOVV $106, R12
+ JMP callbackasm1(SB)
+ MOVV $107, R12
+ JMP callbackasm1(SB)
+ MOVV $108, R12
+ JMP callbackasm1(SB)
+ MOVV $109, R12
+ JMP callbackasm1(SB)
+ MOVV $110, R12
+ JMP callbackasm1(SB)
+ MOVV $111, R12
+ JMP callbackasm1(SB)
+ MOVV $112, R12
+ JMP callbackasm1(SB)
+ MOVV $113, R12
+ JMP callbackasm1(SB)
+ MOVV $114, R12
+ JMP callbackasm1(SB)
+ MOVV $115, R12
+ JMP callbackasm1(SB)
+ MOVV $116, R12
+ JMP callbackasm1(SB)
+ MOVV $117, R12
+ JMP callbackasm1(SB)
+ MOVV $118, R12
+ JMP callbackasm1(SB)
+ MOVV $119, R12
+ JMP callbackasm1(SB)
+ MOVV $120, R12
+ JMP callbackasm1(SB)
+ MOVV $121, R12
+ JMP callbackasm1(SB)
+ MOVV $122, R12
+ JMP callbackasm1(SB)
+ MOVV $123, R12
+ JMP callbackasm1(SB)
+ MOVV $124, R12
+ JMP callbackasm1(SB)
+ MOVV $125, R12
+ JMP callbackasm1(SB)
+ MOVV $126, R12
+ JMP callbackasm1(SB)
+ MOVV $127, R12
+ JMP callbackasm1(SB)
+ MOVV $128, R12
+ JMP callbackasm1(SB)
+ MOVV $129, R12
+ JMP callbackasm1(SB)
+ MOVV $130, R12
+ JMP callbackasm1(SB)
+ MOVV $131, R12
+ JMP callbackasm1(SB)
+ MOVV $132, R12
+ JMP callbackasm1(SB)
+ MOVV $133, R12
+ JMP callbackasm1(SB)
+ MOVV $134, R12
+ JMP callbackasm1(SB)
+ MOVV $135, R12
+ JMP callbackasm1(SB)
+ MOVV $136, R12
+ JMP callbackasm1(SB)
+ MOVV $137, R12
+ JMP callbackasm1(SB)
+ MOVV $138, R12
+ JMP callbackasm1(SB)
+ MOVV $139, R12
+ JMP callbackasm1(SB)
+ MOVV $140, R12
+ JMP callbackasm1(SB)
+ MOVV $141, R12
+ JMP callbackasm1(SB)
+ MOVV $142, R12
+ JMP callbackasm1(SB)
+ MOVV $143, R12
+ JMP callbackasm1(SB)
+ MOVV $144, R12
+ JMP callbackasm1(SB)
+ MOVV $145, R12
+ JMP callbackasm1(SB)
+ MOVV $146, R12
+ JMP callbackasm1(SB)
+ MOVV $147, R12
+ JMP callbackasm1(SB)
+ MOVV $148, R12
+ JMP callbackasm1(SB)
+ MOVV $149, R12
+ JMP callbackasm1(SB)
+ MOVV $150, R12
+ JMP callbackasm1(SB)
+ MOVV $151, R12
+ JMP callbackasm1(SB)
+ MOVV $152, R12
+ JMP callbackasm1(SB)
+ MOVV $153, R12
+ JMP callbackasm1(SB)
+ MOVV $154, R12
+ JMP callbackasm1(SB)
+ MOVV $155, R12
+ JMP callbackasm1(SB)
+ MOVV $156, R12
+ JMP callbackasm1(SB)
+ MOVV $157, R12
+ JMP callbackasm1(SB)
+ MOVV $158, R12
+ JMP callbackasm1(SB)
+ MOVV $159, R12
+ JMP callbackasm1(SB)
+ MOVV $160, R12
+ JMP callbackasm1(SB)
+ MOVV $161, R12
+ JMP callbackasm1(SB)
+ MOVV $162, R12
+ JMP callbackasm1(SB)
+ MOVV $163, R12
+ JMP callbackasm1(SB)
+ MOVV $164, R12
+ JMP callbackasm1(SB)
+ MOVV $165, R12
+ JMP callbackasm1(SB)
+ MOVV $166, R12
+ JMP callbackasm1(SB)
+ MOVV $167, R12
+ JMP callbackasm1(SB)
+ MOVV $168, R12
+ JMP callbackasm1(SB)
+ MOVV $169, R12
+ JMP callbackasm1(SB)
+ MOVV $170, R12
+ JMP callbackasm1(SB)
+ MOVV $171, R12
+ JMP callbackasm1(SB)
+ MOVV $172, R12
+ JMP callbackasm1(SB)
+ MOVV $173, R12
+ JMP callbackasm1(SB)
+ MOVV $174, R12
+ JMP callbackasm1(SB)
+ MOVV $175, R12
+ JMP callbackasm1(SB)
+ MOVV $176, R12
+ JMP callbackasm1(SB)
+ MOVV $177, R12
+ JMP callbackasm1(SB)
+ MOVV $178, R12
+ JMP callbackasm1(SB)
+ MOVV $179, R12
+ JMP callbackasm1(SB)
+ MOVV $180, R12
+ JMP callbackasm1(SB)
+ MOVV $181, R12
+ JMP callbackasm1(SB)
+ MOVV $182, R12
+ JMP callbackasm1(SB)
+ MOVV $183, R12
+ JMP callbackasm1(SB)
+ MOVV $184, R12
+ JMP callbackasm1(SB)
+ MOVV $185, R12
+ JMP callbackasm1(SB)
+ MOVV $186, R12
+ JMP callbackasm1(SB)
+ MOVV $187, R12
+ JMP callbackasm1(SB)
+ MOVV $188, R12
+ JMP callbackasm1(SB)
+ MOVV $189, R12
+ JMP callbackasm1(SB)
+ MOVV $190, R12
+ JMP callbackasm1(SB)
+ MOVV $191, R12
+ JMP callbackasm1(SB)
+ MOVV $192, R12
+ JMP callbackasm1(SB)
+ MOVV $193, R12
+ JMP callbackasm1(SB)
+ MOVV $194, R12
+ JMP callbackasm1(SB)
+ MOVV $195, R12
+ JMP callbackasm1(SB)
+ MOVV $196, R12
+ JMP callbackasm1(SB)
+ MOVV $197, R12
+ JMP callbackasm1(SB)
+ MOVV $198, R12
+ JMP callbackasm1(SB)
+ MOVV $199, R12
+ JMP callbackasm1(SB)
+ MOVV $200, R12
+ JMP callbackasm1(SB)
+ MOVV $201, R12
+ JMP callbackasm1(SB)
+ MOVV $202, R12
+ JMP callbackasm1(SB)
+ MOVV $203, R12
+ JMP callbackasm1(SB)
+ MOVV $204, R12
+ JMP callbackasm1(SB)
+ MOVV $205, R12
+ JMP callbackasm1(SB)
+ MOVV $206, R12
+ JMP callbackasm1(SB)
+ MOVV $207, R12
+ JMP callbackasm1(SB)
+ MOVV $208, R12
+ JMP callbackasm1(SB)
+ MOVV $209, R12
+ JMP callbackasm1(SB)
+ MOVV $210, R12
+ JMP callbackasm1(SB)
+ MOVV $211, R12
+ JMP callbackasm1(SB)
+ MOVV $212, R12
+ JMP callbackasm1(SB)
+ MOVV $213, R12
+ JMP callbackasm1(SB)
+ MOVV $214, R12
+ JMP callbackasm1(SB)
+ MOVV $215, R12
+ JMP callbackasm1(SB)
+ MOVV $216, R12
+ JMP callbackasm1(SB)
+ MOVV $217, R12
+ JMP callbackasm1(SB)
+ MOVV $218, R12
+ JMP callbackasm1(SB)
+ MOVV $219, R12
+ JMP callbackasm1(SB)
+ MOVV $220, R12
+ JMP callbackasm1(SB)
+ MOVV $221, R12
+ JMP callbackasm1(SB)
+ MOVV $222, R12
+ JMP callbackasm1(SB)
+ MOVV $223, R12
+ JMP callbackasm1(SB)
+ MOVV $224, R12
+ JMP callbackasm1(SB)
+ MOVV $225, R12
+ JMP callbackasm1(SB)
+ MOVV $226, R12
+ JMP callbackasm1(SB)
+ MOVV $227, R12
+ JMP callbackasm1(SB)
+ MOVV $228, R12
+ JMP callbackasm1(SB)
+ MOVV $229, R12
+ JMP callbackasm1(SB)
+ MOVV $230, R12
+ JMP callbackasm1(SB)
+ MOVV $231, R12
+ JMP callbackasm1(SB)
+ MOVV $232, R12
+ JMP callbackasm1(SB)
+ MOVV $233, R12
+ JMP callbackasm1(SB)
+ MOVV $234, R12
+ JMP callbackasm1(SB)
+ MOVV $235, R12
+ JMP callbackasm1(SB)
+ MOVV $236, R12
+ JMP callbackasm1(SB)
+ MOVV $237, R12
+ JMP callbackasm1(SB)
+ MOVV $238, R12
+ JMP callbackasm1(SB)
+ MOVV $239, R12
+ JMP callbackasm1(SB)
+ MOVV $240, R12
+ JMP callbackasm1(SB)
+ MOVV $241, R12
+ JMP callbackasm1(SB)
+ MOVV $242, R12
+ JMP callbackasm1(SB)
+ MOVV $243, R12
+ JMP callbackasm1(SB)
+ MOVV $244, R12
+ JMP callbackasm1(SB)
+ MOVV $245, R12
+ JMP callbackasm1(SB)
+ MOVV $246, R12
+ JMP callbackasm1(SB)
+ MOVV $247, R12
+ JMP callbackasm1(SB)
+ MOVV $248, R12
+ JMP callbackasm1(SB)
+ MOVV $249, R12
+ JMP callbackasm1(SB)
+ MOVV $250, R12
+ JMP callbackasm1(SB)
+ MOVV $251, R12
+ JMP callbackasm1(SB)
+ MOVV $252, R12
+ JMP callbackasm1(SB)
+ MOVV $253, R12
+ JMP callbackasm1(SB)
+ MOVV $254, R12
+ JMP callbackasm1(SB)
+ MOVV $255, R12
+ JMP callbackasm1(SB)
+ MOVV $256, R12
+ JMP callbackasm1(SB)
+ MOVV $257, R12
+ JMP callbackasm1(SB)
+ MOVV $258, R12
+ JMP callbackasm1(SB)
+ MOVV $259, R12
+ JMP callbackasm1(SB)
+ MOVV $260, R12
+ JMP callbackasm1(SB)
+ MOVV $261, R12
+ JMP callbackasm1(SB)
+ MOVV $262, R12
+ JMP callbackasm1(SB)
+ MOVV $263, R12
+ JMP callbackasm1(SB)
+ MOVV $264, R12
+ JMP callbackasm1(SB)
+ MOVV $265, R12
+ JMP callbackasm1(SB)
+ MOVV $266, R12
+ JMP callbackasm1(SB)
+ MOVV $267, R12
+ JMP callbackasm1(SB)
+ MOVV $268, R12
+ JMP callbackasm1(SB)
+ MOVV $269, R12
+ JMP callbackasm1(SB)
+ MOVV $270, R12
+ JMP callbackasm1(SB)
+ MOVV $271, R12
+ JMP callbackasm1(SB)
+ MOVV $272, R12
+ JMP callbackasm1(SB)
+ MOVV $273, R12
+ JMP callbackasm1(SB)
+ MOVV $274, R12
+ JMP callbackasm1(SB)
+ MOVV $275, R12
+ JMP callbackasm1(SB)
+ MOVV $276, R12
+ JMP callbackasm1(SB)
+ MOVV $277, R12
+ JMP callbackasm1(SB)
+ MOVV $278, R12
+ JMP callbackasm1(SB)
+ MOVV $279, R12
+ JMP callbackasm1(SB)
+ MOVV $280, R12
+ JMP callbackasm1(SB)
+ MOVV $281, R12
+ JMP callbackasm1(SB)
+ MOVV $282, R12
+ JMP callbackasm1(SB)
+ MOVV $283, R12
+ JMP callbackasm1(SB)
+ MOVV $284, R12
+ JMP callbackasm1(SB)
+ MOVV $285, R12
+ JMP callbackasm1(SB)
+ MOVV $286, R12
+ JMP callbackasm1(SB)
+ MOVV $287, R12
+ JMP callbackasm1(SB)
+ MOVV $288, R12
+ JMP callbackasm1(SB)
+ MOVV $289, R12
+ JMP callbackasm1(SB)
+ MOVV $290, R12
+ JMP callbackasm1(SB)
+ MOVV $291, R12
+ JMP callbackasm1(SB)
+ MOVV $292, R12
+ JMP callbackasm1(SB)
+ MOVV $293, R12
+ JMP callbackasm1(SB)
+ MOVV $294, R12
+ JMP callbackasm1(SB)
+ MOVV $295, R12
+ JMP callbackasm1(SB)
+ MOVV $296, R12
+ JMP callbackasm1(SB)
+ MOVV $297, R12
+ JMP callbackasm1(SB)
+ MOVV $298, R12
+ JMP callbackasm1(SB)
+ MOVV $299, R12
+ JMP callbackasm1(SB)
+ MOVV $300, R12
+ JMP callbackasm1(SB)
+ MOVV $301, R12
+ JMP callbackasm1(SB)
+ MOVV $302, R12
+ JMP callbackasm1(SB)
+ MOVV $303, R12
+ JMP callbackasm1(SB)
+ MOVV $304, R12
+ JMP callbackasm1(SB)
+ MOVV $305, R12
+ JMP callbackasm1(SB)
+ MOVV $306, R12
+ JMP callbackasm1(SB)
+ MOVV $307, R12
+ JMP callbackasm1(SB)
+ MOVV $308, R12
+ JMP callbackasm1(SB)
+ MOVV $309, R12
+ JMP callbackasm1(SB)
+ MOVV $310, R12
+ JMP callbackasm1(SB)
+ MOVV $311, R12
+ JMP callbackasm1(SB)
+ MOVV $312, R12
+ JMP callbackasm1(SB)
+ MOVV $313, R12
+ JMP callbackasm1(SB)
+ MOVV $314, R12
+ JMP callbackasm1(SB)
+ MOVV $315, R12
+ JMP callbackasm1(SB)
+ MOVV $316, R12
+ JMP callbackasm1(SB)
+ MOVV $317, R12
+ JMP callbackasm1(SB)
+ MOVV $318, R12
+ JMP callbackasm1(SB)
+ MOVV $319, R12
+ JMP callbackasm1(SB)
+ MOVV $320, R12
+ JMP callbackasm1(SB)
+ MOVV $321, R12
+ JMP callbackasm1(SB)
+ MOVV $322, R12
+ JMP callbackasm1(SB)
+ MOVV $323, R12
+ JMP callbackasm1(SB)
+ MOVV $324, R12
+ JMP callbackasm1(SB)
+ MOVV $325, R12
+ JMP callbackasm1(SB)
+ MOVV $326, R12
+ JMP callbackasm1(SB)
+ MOVV $327, R12
+ JMP callbackasm1(SB)
+ MOVV $328, R12
+ JMP callbackasm1(SB)
+ MOVV $329, R12
+ JMP callbackasm1(SB)
+ MOVV $330, R12
+ JMP callbackasm1(SB)
+ MOVV $331, R12
+ JMP callbackasm1(SB)
+ MOVV $332, R12
+ JMP callbackasm1(SB)
+ MOVV $333, R12
+ JMP callbackasm1(SB)
+ MOVV $334, R12
+ JMP callbackasm1(SB)
+ MOVV $335, R12
+ JMP callbackasm1(SB)
+ MOVV $336, R12
+ JMP callbackasm1(SB)
+ MOVV $337, R12
+ JMP callbackasm1(SB)
+ MOVV $338, R12
+ JMP callbackasm1(SB)
+ MOVV $339, R12
+ JMP callbackasm1(SB)
+ MOVV $340, R12
+ JMP callbackasm1(SB)
+ MOVV $341, R12
+ JMP callbackasm1(SB)
+ MOVV $342, R12
+ JMP callbackasm1(SB)
+ MOVV $343, R12
+ JMP callbackasm1(SB)
+ MOVV $344, R12
+ JMP callbackasm1(SB)
+ MOVV $345, R12
+ JMP callbackasm1(SB)
+ MOVV $346, R12
+ JMP callbackasm1(SB)
+ MOVV $347, R12
+ JMP callbackasm1(SB)
+ MOVV $348, R12
+ JMP callbackasm1(SB)
+ MOVV $349, R12
+ JMP callbackasm1(SB)
+ MOVV $350, R12
+ JMP callbackasm1(SB)
+ MOVV $351, R12
+ JMP callbackasm1(SB)
+ MOVV $352, R12
+ JMP callbackasm1(SB)
+ MOVV $353, R12
+ JMP callbackasm1(SB)
+ MOVV $354, R12
+ JMP callbackasm1(SB)
+ MOVV $355, R12
+ JMP callbackasm1(SB)
+ MOVV $356, R12
+ JMP callbackasm1(SB)
+ MOVV $357, R12
+ JMP callbackasm1(SB)
+ MOVV $358, R12
+ JMP callbackasm1(SB)
+ MOVV $359, R12
+ JMP callbackasm1(SB)
+ MOVV $360, R12
+ JMP callbackasm1(SB)
+ MOVV $361, R12
+ JMP callbackasm1(SB)
+ MOVV $362, R12
+ JMP callbackasm1(SB)
+ MOVV $363, R12
+ JMP callbackasm1(SB)
+ MOVV $364, R12
+ JMP callbackasm1(SB)
+ MOVV $365, R12
+ JMP callbackasm1(SB)
+ MOVV $366, R12
+ JMP callbackasm1(SB)
+ MOVV $367, R12
+ JMP callbackasm1(SB)
+ MOVV $368, R12
+ JMP callbackasm1(SB)
+ MOVV $369, R12
+ JMP callbackasm1(SB)
+ MOVV $370, R12
+ JMP callbackasm1(SB)
+ MOVV $371, R12
+ JMP callbackasm1(SB)
+ MOVV $372, R12
+ JMP callbackasm1(SB)
+ MOVV $373, R12
+ JMP callbackasm1(SB)
+ MOVV $374, R12
+ JMP callbackasm1(SB)
+ MOVV $375, R12
+ JMP callbackasm1(SB)
+ MOVV $376, R12
+ JMP callbackasm1(SB)
+ MOVV $377, R12
+ JMP callbackasm1(SB)
+ MOVV $378, R12
+ JMP callbackasm1(SB)
+ MOVV $379, R12
+ JMP callbackasm1(SB)
+ MOVV $380, R12
+ JMP callbackasm1(SB)
+ MOVV $381, R12
+ JMP callbackasm1(SB)
+ MOVV $382, R12
+ JMP callbackasm1(SB)
+ MOVV $383, R12
+ JMP callbackasm1(SB)
+ MOVV $384, R12
+ JMP callbackasm1(SB)
+ MOVV $385, R12
+ JMP callbackasm1(SB)
+ MOVV $386, R12
+ JMP callbackasm1(SB)
+ MOVV $387, R12
+ JMP callbackasm1(SB)
+ MOVV $388, R12
+ JMP callbackasm1(SB)
+ MOVV $389, R12
+ JMP callbackasm1(SB)
+ MOVV $390, R12
+ JMP callbackasm1(SB)
+ MOVV $391, R12
+ JMP callbackasm1(SB)
+ MOVV $392, R12
+ JMP callbackasm1(SB)
+ MOVV $393, R12
+ JMP callbackasm1(SB)
+ MOVV $394, R12
+ JMP callbackasm1(SB)
+ MOVV $395, R12
+ JMP callbackasm1(SB)
+ MOVV $396, R12
+ JMP callbackasm1(SB)
+ MOVV $397, R12
+ JMP callbackasm1(SB)
+ MOVV $398, R12
+ JMP callbackasm1(SB)
+ MOVV $399, R12
+ JMP callbackasm1(SB)
+ MOVV $400, R12
+ JMP callbackasm1(SB)
+ MOVV $401, R12
+ JMP callbackasm1(SB)
+ MOVV $402, R12
+ JMP callbackasm1(SB)
+ MOVV $403, R12
+ JMP callbackasm1(SB)
+ MOVV $404, R12
+ JMP callbackasm1(SB)
+ MOVV $405, R12
+ JMP callbackasm1(SB)
+ MOVV $406, R12
+ JMP callbackasm1(SB)
+ MOVV $407, R12
+ JMP callbackasm1(SB)
+ MOVV $408, R12
+ JMP callbackasm1(SB)
+ MOVV $409, R12
+ JMP callbackasm1(SB)
+ MOVV $410, R12
+ JMP callbackasm1(SB)
+ MOVV $411, R12
+ JMP callbackasm1(SB)
+ MOVV $412, R12
+ JMP callbackasm1(SB)
+ MOVV $413, R12
+ JMP callbackasm1(SB)
+ MOVV $414, R12
+ JMP callbackasm1(SB)
+ MOVV $415, R12
+ JMP callbackasm1(SB)
+ MOVV $416, R12
+ JMP callbackasm1(SB)
+ MOVV $417, R12
+ JMP callbackasm1(SB)
+ MOVV $418, R12
+ JMP callbackasm1(SB)
+ MOVV $419, R12
+ JMP callbackasm1(SB)
+ MOVV $420, R12
+ JMP callbackasm1(SB)
+ MOVV $421, R12
+ JMP callbackasm1(SB)
+ MOVV $422, R12
+ JMP callbackasm1(SB)
+ MOVV $423, R12
+ JMP callbackasm1(SB)
+ MOVV $424, R12
+ JMP callbackasm1(SB)
+ MOVV $425, R12
+ JMP callbackasm1(SB)
+ MOVV $426, R12
+ JMP callbackasm1(SB)
+ MOVV $427, R12
+ JMP callbackasm1(SB)
+ MOVV $428, R12
+ JMP callbackasm1(SB)
+ MOVV $429, R12
+ JMP callbackasm1(SB)
+ MOVV $430, R12
+ JMP callbackasm1(SB)
+ MOVV $431, R12
+ JMP callbackasm1(SB)
+ MOVV $432, R12
+ JMP callbackasm1(SB)
+ MOVV $433, R12
+ JMP callbackasm1(SB)
+ MOVV $434, R12
+ JMP callbackasm1(SB)
+ MOVV $435, R12
+ JMP callbackasm1(SB)
+ MOVV $436, R12
+ JMP callbackasm1(SB)
+ MOVV $437, R12
+ JMP callbackasm1(SB)
+ MOVV $438, R12
+ JMP callbackasm1(SB)
+ MOVV $439, R12
+ JMP callbackasm1(SB)
+ MOVV $440, R12
+ JMP callbackasm1(SB)
+ MOVV $441, R12
+ JMP callbackasm1(SB)
+ MOVV $442, R12
+ JMP callbackasm1(SB)
+ MOVV $443, R12
+ JMP callbackasm1(SB)
+ MOVV $444, R12
+ JMP callbackasm1(SB)
+ MOVV $445, R12
+ JMP callbackasm1(SB)
+ MOVV $446, R12
+ JMP callbackasm1(SB)
+ MOVV $447, R12
+ JMP callbackasm1(SB)
+ MOVV $448, R12
+ JMP callbackasm1(SB)
+ MOVV $449, R12
+ JMP callbackasm1(SB)
+ MOVV $450, R12
+ JMP callbackasm1(SB)
+ MOVV $451, R12
+ JMP callbackasm1(SB)
+ MOVV $452, R12
+ JMP callbackasm1(SB)
+ MOVV $453, R12
+ JMP callbackasm1(SB)
+ MOVV $454, R12
+ JMP callbackasm1(SB)
+ MOVV $455, R12
+ JMP callbackasm1(SB)
+ MOVV $456, R12
+ JMP callbackasm1(SB)
+ MOVV $457, R12
+ JMP callbackasm1(SB)
+ MOVV $458, R12
+ JMP callbackasm1(SB)
+ MOVV $459, R12
+ JMP callbackasm1(SB)
+ MOVV $460, R12
+ JMP callbackasm1(SB)
+ MOVV $461, R12
+ JMP callbackasm1(SB)
+ MOVV $462, R12
+ JMP callbackasm1(SB)
+ MOVV $463, R12
+ JMP callbackasm1(SB)
+ MOVV $464, R12
+ JMP callbackasm1(SB)
+ MOVV $465, R12
+ JMP callbackasm1(SB)
+ MOVV $466, R12
+ JMP callbackasm1(SB)
+ MOVV $467, R12
+ JMP callbackasm1(SB)
+ MOVV $468, R12
+ JMP callbackasm1(SB)
+ MOVV $469, R12
+ JMP callbackasm1(SB)
+ MOVV $470, R12
+ JMP callbackasm1(SB)
+ MOVV $471, R12
+ JMP callbackasm1(SB)
+ MOVV $472, R12
+ JMP callbackasm1(SB)
+ MOVV $473, R12
+ JMP callbackasm1(SB)
+ MOVV $474, R12
+ JMP callbackasm1(SB)
+ MOVV $475, R12
+ JMP callbackasm1(SB)
+ MOVV $476, R12
+ JMP callbackasm1(SB)
+ MOVV $477, R12
+ JMP callbackasm1(SB)
+ MOVV $478, R12
+ JMP callbackasm1(SB)
+ MOVV $479, R12
+ JMP callbackasm1(SB)
+ MOVV $480, R12
+ JMP callbackasm1(SB)
+ MOVV $481, R12
+ JMP callbackasm1(SB)
+ MOVV $482, R12
+ JMP callbackasm1(SB)
+ MOVV $483, R12
+ JMP callbackasm1(SB)
+ MOVV $484, R12
+ JMP callbackasm1(SB)
+ MOVV $485, R12
+ JMP callbackasm1(SB)
+ MOVV $486, R12
+ JMP callbackasm1(SB)
+ MOVV $487, R12
+ JMP callbackasm1(SB)
+ MOVV $488, R12
+ JMP callbackasm1(SB)
+ MOVV $489, R12
+ JMP callbackasm1(SB)
+ MOVV $490, R12
+ JMP callbackasm1(SB)
+ MOVV $491, R12
+ JMP callbackasm1(SB)
+ MOVV $492, R12
+ JMP callbackasm1(SB)
+ MOVV $493, R12
+ JMP callbackasm1(SB)
+ MOVV $494, R12
+ JMP callbackasm1(SB)
+ MOVV $495, R12
+ JMP callbackasm1(SB)
+ MOVV $496, R12
+ JMP callbackasm1(SB)
+ MOVV $497, R12
+ JMP callbackasm1(SB)
+ MOVV $498, R12
+ JMP callbackasm1(SB)
+ MOVV $499, R12
+ JMP callbackasm1(SB)
+ MOVV $500, R12
+ JMP callbackasm1(SB)
+ MOVV $501, R12
+ JMP callbackasm1(SB)
+ MOVV $502, R12
+ JMP callbackasm1(SB)
+ MOVV $503, R12
+ JMP callbackasm1(SB)
+ MOVV $504, R12
+ JMP callbackasm1(SB)
+ MOVV $505, R12
+ JMP callbackasm1(SB)
+ MOVV $506, R12
+ JMP callbackasm1(SB)
+ MOVV $507, R12
+ JMP callbackasm1(SB)
+ MOVV $508, R12
+ JMP callbackasm1(SB)
+ MOVV $509, R12
+ JMP callbackasm1(SB)
+ MOVV $510, R12
+ JMP callbackasm1(SB)
+ MOVV $511, R12
+ JMP callbackasm1(SB)
+ MOVV $512, R12
+ JMP callbackasm1(SB)
+ MOVV $513, R12
+ JMP callbackasm1(SB)
+ MOVV $514, R12
+ JMP callbackasm1(SB)
+ MOVV $515, R12
+ JMP callbackasm1(SB)
+ MOVV $516, R12
+ JMP callbackasm1(SB)
+ MOVV $517, R12
+ JMP callbackasm1(SB)
+ MOVV $518, R12
+ JMP callbackasm1(SB)
+ MOVV $519, R12
+ JMP callbackasm1(SB)
+ MOVV $520, R12
+ JMP callbackasm1(SB)
+ MOVV $521, R12
+ JMP callbackasm1(SB)
+ MOVV $522, R12
+ JMP callbackasm1(SB)
+ MOVV $523, R12
+ JMP callbackasm1(SB)
+ MOVV $524, R12
+ JMP callbackasm1(SB)
+ MOVV $525, R12
+ JMP callbackasm1(SB)
+ MOVV $526, R12
+ JMP callbackasm1(SB)
+ MOVV $527, R12
+ JMP callbackasm1(SB)
+ MOVV $528, R12
+ JMP callbackasm1(SB)
+ MOVV $529, R12
+ JMP callbackasm1(SB)
+ MOVV $530, R12
+ JMP callbackasm1(SB)
+ MOVV $531, R12
+ JMP callbackasm1(SB)
+ MOVV $532, R12
+ JMP callbackasm1(SB)
+ MOVV $533, R12
+ JMP callbackasm1(SB)
+ MOVV $534, R12
+ JMP callbackasm1(SB)
+ MOVV $535, R12
+ JMP callbackasm1(SB)
+ MOVV $536, R12
+ JMP callbackasm1(SB)
+ MOVV $537, R12
+ JMP callbackasm1(SB)
+ MOVV $538, R12
+ JMP callbackasm1(SB)
+ MOVV $539, R12
+ JMP callbackasm1(SB)
+ MOVV $540, R12
+ JMP callbackasm1(SB)
+ MOVV $541, R12
+ JMP callbackasm1(SB)
+ MOVV $542, R12
+ JMP callbackasm1(SB)
+ MOVV $543, R12
+ JMP callbackasm1(SB)
+ MOVV $544, R12
+ JMP callbackasm1(SB)
+ MOVV $545, R12
+ JMP callbackasm1(SB)
+ MOVV $546, R12
+ JMP callbackasm1(SB)
+ MOVV $547, R12
+ JMP callbackasm1(SB)
+ MOVV $548, R12
+ JMP callbackasm1(SB)
+ MOVV $549, R12
+ JMP callbackasm1(SB)
+ MOVV $550, R12
+ JMP callbackasm1(SB)
+ MOVV $551, R12
+ JMP callbackasm1(SB)
+ MOVV $552, R12
+ JMP callbackasm1(SB)
+ MOVV $553, R12
+ JMP callbackasm1(SB)
+ MOVV $554, R12
+ JMP callbackasm1(SB)
+ MOVV $555, R12
+ JMP callbackasm1(SB)
+ MOVV $556, R12
+ JMP callbackasm1(SB)
+ MOVV $557, R12
+ JMP callbackasm1(SB)
+ MOVV $558, R12
+ JMP callbackasm1(SB)
+ MOVV $559, R12
+ JMP callbackasm1(SB)
+ MOVV $560, R12
+ JMP callbackasm1(SB)
+ MOVV $561, R12
+ JMP callbackasm1(SB)
+ MOVV $562, R12
+ JMP callbackasm1(SB)
+ MOVV $563, R12
+ JMP callbackasm1(SB)
+ MOVV $564, R12
+ JMP callbackasm1(SB)
+ MOVV $565, R12
+ JMP callbackasm1(SB)
+ MOVV $566, R12
+ JMP callbackasm1(SB)
+ MOVV $567, R12
+ JMP callbackasm1(SB)
+ MOVV $568, R12
+ JMP callbackasm1(SB)
+ MOVV $569, R12
+ JMP callbackasm1(SB)
+ MOVV $570, R12
+ JMP callbackasm1(SB)
+ MOVV $571, R12
+ JMP callbackasm1(SB)
+ MOVV $572, R12
+ JMP callbackasm1(SB)
+ MOVV $573, R12
+ JMP callbackasm1(SB)
+ MOVV $574, R12
+ JMP callbackasm1(SB)
+ MOVV $575, R12
+ JMP callbackasm1(SB)
+ MOVV $576, R12
+ JMP callbackasm1(SB)
+ MOVV $577, R12
+ JMP callbackasm1(SB)
+ MOVV $578, R12
+ JMP callbackasm1(SB)
+ MOVV $579, R12
+ JMP callbackasm1(SB)
+ MOVV $580, R12
+ JMP callbackasm1(SB)
+ MOVV $581, R12
+ JMP callbackasm1(SB)
+ MOVV $582, R12
+ JMP callbackasm1(SB)
+ MOVV $583, R12
+ JMP callbackasm1(SB)
+ MOVV $584, R12
+ JMP callbackasm1(SB)
+ MOVV $585, R12
+ JMP callbackasm1(SB)
+ MOVV $586, R12
+ JMP callbackasm1(SB)
+ MOVV $587, R12
+ JMP callbackasm1(SB)
+ MOVV $588, R12
+ JMP callbackasm1(SB)
+ MOVV $589, R12
+ JMP callbackasm1(SB)
+ MOVV $590, R12
+ JMP callbackasm1(SB)
+ MOVV $591, R12
+ JMP callbackasm1(SB)
+ MOVV $592, R12
+ JMP callbackasm1(SB)
+ MOVV $593, R12
+ JMP callbackasm1(SB)
+ MOVV $594, R12
+ JMP callbackasm1(SB)
+ MOVV $595, R12
+ JMP callbackasm1(SB)
+ MOVV $596, R12
+ JMP callbackasm1(SB)
+ MOVV $597, R12
+ JMP callbackasm1(SB)
+ MOVV $598, R12
+ JMP callbackasm1(SB)
+ MOVV $599, R12
+ JMP callbackasm1(SB)
+ MOVV $600, R12
+ JMP callbackasm1(SB)
+ MOVV $601, R12
+ JMP callbackasm1(SB)
+ MOVV $602, R12
+ JMP callbackasm1(SB)
+ MOVV $603, R12
+ JMP callbackasm1(SB)
+ MOVV $604, R12
+ JMP callbackasm1(SB)
+ MOVV $605, R12
+ JMP callbackasm1(SB)
+ MOVV $606, R12
+ JMP callbackasm1(SB)
+ MOVV $607, R12
+ JMP callbackasm1(SB)
+ MOVV $608, R12
+ JMP callbackasm1(SB)
+ MOVV $609, R12
+ JMP callbackasm1(SB)
+ MOVV $610, R12
+ JMP callbackasm1(SB)
+ MOVV $611, R12
+ JMP callbackasm1(SB)
+ MOVV $612, R12
+ JMP callbackasm1(SB)
+ MOVV $613, R12
+ JMP callbackasm1(SB)
+ MOVV $614, R12
+ JMP callbackasm1(SB)
+ MOVV $615, R12
+ JMP callbackasm1(SB)
+ MOVV $616, R12
+ JMP callbackasm1(SB)
+ MOVV $617, R12
+ JMP callbackasm1(SB)
+ MOVV $618, R12
+ JMP callbackasm1(SB)
+ MOVV $619, R12
+ JMP callbackasm1(SB)
+ MOVV $620, R12
+ JMP callbackasm1(SB)
+ MOVV $621, R12
+ JMP callbackasm1(SB)
+ MOVV $622, R12
+ JMP callbackasm1(SB)
+ MOVV $623, R12
+ JMP callbackasm1(SB)
+ MOVV $624, R12
+ JMP callbackasm1(SB)
+ MOVV $625, R12
+ JMP callbackasm1(SB)
+ MOVV $626, R12
+ JMP callbackasm1(SB)
+ MOVV $627, R12
+ JMP callbackasm1(SB)
+ MOVV $628, R12
+ JMP callbackasm1(SB)
+ MOVV $629, R12
+ JMP callbackasm1(SB)
+ MOVV $630, R12
+ JMP callbackasm1(SB)
+ MOVV $631, R12
+ JMP callbackasm1(SB)
+ MOVV $632, R12
+ JMP callbackasm1(SB)
+ MOVV $633, R12
+ JMP callbackasm1(SB)
+ MOVV $634, R12
+ JMP callbackasm1(SB)
+ MOVV $635, R12
+ JMP callbackasm1(SB)
+ MOVV $636, R12
+ JMP callbackasm1(SB)
+ MOVV $637, R12
+ JMP callbackasm1(SB)
+ MOVV $638, R12
+ JMP callbackasm1(SB)
+ MOVV $639, R12
+ JMP callbackasm1(SB)
+ MOVV $640, R12
+ JMP callbackasm1(SB)
+ MOVV $641, R12
+ JMP callbackasm1(SB)
+ MOVV $642, R12
+ JMP callbackasm1(SB)
+ MOVV $643, R12
+ JMP callbackasm1(SB)
+ MOVV $644, R12
+ JMP callbackasm1(SB)
+ MOVV $645, R12
+ JMP callbackasm1(SB)
+ MOVV $646, R12
+ JMP callbackasm1(SB)
+ MOVV $647, R12
+ JMP callbackasm1(SB)
+ MOVV $648, R12
+ JMP callbackasm1(SB)
+ MOVV $649, R12
+ JMP callbackasm1(SB)
+ MOVV $650, R12
+ JMP callbackasm1(SB)
+ MOVV $651, R12
+ JMP callbackasm1(SB)
+ MOVV $652, R12
+ JMP callbackasm1(SB)
+ MOVV $653, R12
+ JMP callbackasm1(SB)
+ MOVV $654, R12
+ JMP callbackasm1(SB)
+ MOVV $655, R12
+ JMP callbackasm1(SB)
+ MOVV $656, R12
+ JMP callbackasm1(SB)
+ MOVV $657, R12
+ JMP callbackasm1(SB)
+ MOVV $658, R12
+ JMP callbackasm1(SB)
+ MOVV $659, R12
+ JMP callbackasm1(SB)
+ MOVV $660, R12
+ JMP callbackasm1(SB)
+ MOVV $661, R12
+ JMP callbackasm1(SB)
+ MOVV $662, R12
+ JMP callbackasm1(SB)
+ MOVV $663, R12
+ JMP callbackasm1(SB)
+ MOVV $664, R12
+ JMP callbackasm1(SB)
+ MOVV $665, R12
+ JMP callbackasm1(SB)
+ MOVV $666, R12
+ JMP callbackasm1(SB)
+ MOVV $667, R12
+ JMP callbackasm1(SB)
+ MOVV $668, R12
+ JMP callbackasm1(SB)
+ MOVV $669, R12
+ JMP callbackasm1(SB)
+ MOVV $670, R12
+ JMP callbackasm1(SB)
+ MOVV $671, R12
+ JMP callbackasm1(SB)
+ MOVV $672, R12
+ JMP callbackasm1(SB)
+ MOVV $673, R12
+ JMP callbackasm1(SB)
+ MOVV $674, R12
+ JMP callbackasm1(SB)
+ MOVV $675, R12
+ JMP callbackasm1(SB)
+ MOVV $676, R12
+ JMP callbackasm1(SB)
+ MOVV $677, R12
+ JMP callbackasm1(SB)
+ MOVV $678, R12
+ JMP callbackasm1(SB)
+ MOVV $679, R12
+ JMP callbackasm1(SB)
+ MOVV $680, R12
+ JMP callbackasm1(SB)
+ MOVV $681, R12
+ JMP callbackasm1(SB)
+ MOVV $682, R12
+ JMP callbackasm1(SB)
+ MOVV $683, R12
+ JMP callbackasm1(SB)
+ MOVV $684, R12
+ JMP callbackasm1(SB)
+ MOVV $685, R12
+ JMP callbackasm1(SB)
+ MOVV $686, R12
+ JMP callbackasm1(SB)
+ MOVV $687, R12
+ JMP callbackasm1(SB)
+ MOVV $688, R12
+ JMP callbackasm1(SB)
+ MOVV $689, R12
+ JMP callbackasm1(SB)
+ MOVV $690, R12
+ JMP callbackasm1(SB)
+ MOVV $691, R12
+ JMP callbackasm1(SB)
+ MOVV $692, R12
+ JMP callbackasm1(SB)
+ MOVV $693, R12
+ JMP callbackasm1(SB)
+ MOVV $694, R12
+ JMP callbackasm1(SB)
+ MOVV $695, R12
+ JMP callbackasm1(SB)
+ MOVV $696, R12
+ JMP callbackasm1(SB)
+ MOVV $697, R12
+ JMP callbackasm1(SB)
+ MOVV $698, R12
+ JMP callbackasm1(SB)
+ MOVV $699, R12
+ JMP callbackasm1(SB)
+ MOVV $700, R12
+ JMP callbackasm1(SB)
+ MOVV $701, R12
+ JMP callbackasm1(SB)
+ MOVV $702, R12
+ JMP callbackasm1(SB)
+ MOVV $703, R12
+ JMP callbackasm1(SB)
+ MOVV $704, R12
+ JMP callbackasm1(SB)
+ MOVV $705, R12
+ JMP callbackasm1(SB)
+ MOVV $706, R12
+ JMP callbackasm1(SB)
+ MOVV $707, R12
+ JMP callbackasm1(SB)
+ MOVV $708, R12
+ JMP callbackasm1(SB)
+ MOVV $709, R12
+ JMP callbackasm1(SB)
+ MOVV $710, R12
+ JMP callbackasm1(SB)
+ MOVV $711, R12
+ JMP callbackasm1(SB)
+ MOVV $712, R12
+ JMP callbackasm1(SB)
+ MOVV $713, R12
+ JMP callbackasm1(SB)
+ MOVV $714, R12
+ JMP callbackasm1(SB)
+ MOVV $715, R12
+ JMP callbackasm1(SB)
+ MOVV $716, R12
+ JMP callbackasm1(SB)
+ MOVV $717, R12
+ JMP callbackasm1(SB)
+ MOVV $718, R12
+ JMP callbackasm1(SB)
+ MOVV $719, R12
+ JMP callbackasm1(SB)
+ MOVV $720, R12
+ JMP callbackasm1(SB)
+ MOVV $721, R12
+ JMP callbackasm1(SB)
+ MOVV $722, R12
+ JMP callbackasm1(SB)
+ MOVV $723, R12
+ JMP callbackasm1(SB)
+ MOVV $724, R12
+ JMP callbackasm1(SB)
+ MOVV $725, R12
+ JMP callbackasm1(SB)
+ MOVV $726, R12
+ JMP callbackasm1(SB)
+ MOVV $727, R12
+ JMP callbackasm1(SB)
+ MOVV $728, R12
+ JMP callbackasm1(SB)
+ MOVV $729, R12
+ JMP callbackasm1(SB)
+ MOVV $730, R12
+ JMP callbackasm1(SB)
+ MOVV $731, R12
+ JMP callbackasm1(SB)
+ MOVV $732, R12
+ JMP callbackasm1(SB)
+ MOVV $733, R12
+ JMP callbackasm1(SB)
+ MOVV $734, R12
+ JMP callbackasm1(SB)
+ MOVV $735, R12
+ JMP callbackasm1(SB)
+ MOVV $736, R12
+ JMP callbackasm1(SB)
+ MOVV $737, R12
+ JMP callbackasm1(SB)
+ MOVV $738, R12
+ JMP callbackasm1(SB)
+ MOVV $739, R12
+ JMP callbackasm1(SB)
+ MOVV $740, R12
+ JMP callbackasm1(SB)
+ MOVV $741, R12
+ JMP callbackasm1(SB)
+ MOVV $742, R12
+ JMP callbackasm1(SB)
+ MOVV $743, R12
+ JMP callbackasm1(SB)
+ MOVV $744, R12
+ JMP callbackasm1(SB)
+ MOVV $745, R12
+ JMP callbackasm1(SB)
+ MOVV $746, R12
+ JMP callbackasm1(SB)
+ MOVV $747, R12
+ JMP callbackasm1(SB)
+ MOVV $748, R12
+ JMP callbackasm1(SB)
+ MOVV $749, R12
+ JMP callbackasm1(SB)
+ MOVV $750, R12
+ JMP callbackasm1(SB)
+ MOVV $751, R12
+ JMP callbackasm1(SB)
+ MOVV $752, R12
+ JMP callbackasm1(SB)
+ MOVV $753, R12
+ JMP callbackasm1(SB)
+ MOVV $754, R12
+ JMP callbackasm1(SB)
+ MOVV $755, R12
+ JMP callbackasm1(SB)
+ MOVV $756, R12
+ JMP callbackasm1(SB)
+ MOVV $757, R12
+ JMP callbackasm1(SB)
+ MOVV $758, R12
+ JMP callbackasm1(SB)
+ MOVV $759, R12
+ JMP callbackasm1(SB)
+ MOVV $760, R12
+ JMP callbackasm1(SB)
+ MOVV $761, R12
+ JMP callbackasm1(SB)
+ MOVV $762, R12
+ JMP callbackasm1(SB)
+ MOVV $763, R12
+ JMP callbackasm1(SB)
+ MOVV $764, R12
+ JMP callbackasm1(SB)
+ MOVV $765, R12
+ JMP callbackasm1(SB)
+ MOVV $766, R12
+ JMP callbackasm1(SB)
+ MOVV $767, R12
+ JMP callbackasm1(SB)
+ MOVV $768, R12
+ JMP callbackasm1(SB)
+ MOVV $769, R12
+ JMP callbackasm1(SB)
+ MOVV $770, R12
+ JMP callbackasm1(SB)
+ MOVV $771, R12
+ JMP callbackasm1(SB)
+ MOVV $772, R12
+ JMP callbackasm1(SB)
+ MOVV $773, R12
+ JMP callbackasm1(SB)
+ MOVV $774, R12
+ JMP callbackasm1(SB)
+ MOVV $775, R12
+ JMP callbackasm1(SB)
+ MOVV $776, R12
+ JMP callbackasm1(SB)
+ MOVV $777, R12
+ JMP callbackasm1(SB)
+ MOVV $778, R12
+ JMP callbackasm1(SB)
+ MOVV $779, R12
+ JMP callbackasm1(SB)
+ MOVV $780, R12
+ JMP callbackasm1(SB)
+ MOVV $781, R12
+ JMP callbackasm1(SB)
+ MOVV $782, R12
+ JMP callbackasm1(SB)
+ MOVV $783, R12
+ JMP callbackasm1(SB)
+ MOVV $784, R12
+ JMP callbackasm1(SB)
+ MOVV $785, R12
+ JMP callbackasm1(SB)
+ MOVV $786, R12
+ JMP callbackasm1(SB)
+ MOVV $787, R12
+ JMP callbackasm1(SB)
+ MOVV $788, R12
+ JMP callbackasm1(SB)
+ MOVV $789, R12
+ JMP callbackasm1(SB)
+ MOVV $790, R12
+ JMP callbackasm1(SB)
+ MOVV $791, R12
+ JMP callbackasm1(SB)
+ MOVV $792, R12
+ JMP callbackasm1(SB)
+ MOVV $793, R12
+ JMP callbackasm1(SB)
+ MOVV $794, R12
+ JMP callbackasm1(SB)
+ MOVV $795, R12
+ JMP callbackasm1(SB)
+ MOVV $796, R12
+ JMP callbackasm1(SB)
+ MOVV $797, R12
+ JMP callbackasm1(SB)
+ MOVV $798, R12
+ JMP callbackasm1(SB)
+ MOVV $799, R12
+ JMP callbackasm1(SB)
+ MOVV $800, R12
+ JMP callbackasm1(SB)
+ MOVV $801, R12
+ JMP callbackasm1(SB)
+ MOVV $802, R12
+ JMP callbackasm1(SB)
+ MOVV $803, R12
+ JMP callbackasm1(SB)
+ MOVV $804, R12
+ JMP callbackasm1(SB)
+ MOVV $805, R12
+ JMP callbackasm1(SB)
+ MOVV $806, R12
+ JMP callbackasm1(SB)
+ MOVV $807, R12
+ JMP callbackasm1(SB)
+ MOVV $808, R12
+ JMP callbackasm1(SB)
+ MOVV $809, R12
+ JMP callbackasm1(SB)
+ MOVV $810, R12
+ JMP callbackasm1(SB)
+ MOVV $811, R12
+ JMP callbackasm1(SB)
+ MOVV $812, R12
+ JMP callbackasm1(SB)
+ MOVV $813, R12
+ JMP callbackasm1(SB)
+ MOVV $814, R12
+ JMP callbackasm1(SB)
+ MOVV $815, R12
+ JMP callbackasm1(SB)
+ MOVV $816, R12
+ JMP callbackasm1(SB)
+ MOVV $817, R12
+ JMP callbackasm1(SB)
+ MOVV $818, R12
+ JMP callbackasm1(SB)
+ MOVV $819, R12
+ JMP callbackasm1(SB)
+ MOVV $820, R12
+ JMP callbackasm1(SB)
+ MOVV $821, R12
+ JMP callbackasm1(SB)
+ MOVV $822, R12
+ JMP callbackasm1(SB)
+ MOVV $823, R12
+ JMP callbackasm1(SB)
+ MOVV $824, R12
+ JMP callbackasm1(SB)
+ MOVV $825, R12
+ JMP callbackasm1(SB)
+ MOVV $826, R12
+ JMP callbackasm1(SB)
+ MOVV $827, R12
+ JMP callbackasm1(SB)
+ MOVV $828, R12
+ JMP callbackasm1(SB)
+ MOVV $829, R12
+ JMP callbackasm1(SB)
+ MOVV $830, R12
+ JMP callbackasm1(SB)
+ MOVV $831, R12
+ JMP callbackasm1(SB)
+ MOVV $832, R12
+ JMP callbackasm1(SB)
+ MOVV $833, R12
+ JMP callbackasm1(SB)
+ MOVV $834, R12
+ JMP callbackasm1(SB)
+ MOVV $835, R12
+ JMP callbackasm1(SB)
+ MOVV $836, R12
+ JMP callbackasm1(SB)
+ MOVV $837, R12
+ JMP callbackasm1(SB)
+ MOVV $838, R12
+ JMP callbackasm1(SB)
+ MOVV $839, R12
+ JMP callbackasm1(SB)
+ MOVV $840, R12
+ JMP callbackasm1(SB)
+ MOVV $841, R12
+ JMP callbackasm1(SB)
+ MOVV $842, R12
+ JMP callbackasm1(SB)
+ MOVV $843, R12
+ JMP callbackasm1(SB)
+ MOVV $844, R12
+ JMP callbackasm1(SB)
+ MOVV $845, R12
+ JMP callbackasm1(SB)
+ MOVV $846, R12
+ JMP callbackasm1(SB)
+ MOVV $847, R12
+ JMP callbackasm1(SB)
+ MOVV $848, R12
+ JMP callbackasm1(SB)
+ MOVV $849, R12
+ JMP callbackasm1(SB)
+ MOVV $850, R12
+ JMP callbackasm1(SB)
+ MOVV $851, R12
+ JMP callbackasm1(SB)
+ MOVV $852, R12
+ JMP callbackasm1(SB)
+ MOVV $853, R12
+ JMP callbackasm1(SB)
+ MOVV $854, R12
+ JMP callbackasm1(SB)
+ MOVV $855, R12
+ JMP callbackasm1(SB)
+ MOVV $856, R12
+ JMP callbackasm1(SB)
+ MOVV $857, R12
+ JMP callbackasm1(SB)
+ MOVV $858, R12
+ JMP callbackasm1(SB)
+ MOVV $859, R12
+ JMP callbackasm1(SB)
+ MOVV $860, R12
+ JMP callbackasm1(SB)
+ MOVV $861, R12
+ JMP callbackasm1(SB)
+ MOVV $862, R12
+ JMP callbackasm1(SB)
+ MOVV $863, R12
+ JMP callbackasm1(SB)
+ MOVV $864, R12
+ JMP callbackasm1(SB)
+ MOVV $865, R12
+ JMP callbackasm1(SB)
+ MOVV $866, R12
+ JMP callbackasm1(SB)
+ MOVV $867, R12
+ JMP callbackasm1(SB)
+ MOVV $868, R12
+ JMP callbackasm1(SB)
+ MOVV $869, R12
+ JMP callbackasm1(SB)
+ MOVV $870, R12
+ JMP callbackasm1(SB)
+ MOVV $871, R12
+ JMP callbackasm1(SB)
+ MOVV $872, R12
+ JMP callbackasm1(SB)
+ MOVV $873, R12
+ JMP callbackasm1(SB)
+ MOVV $874, R12
+ JMP callbackasm1(SB)
+ MOVV $875, R12
+ JMP callbackasm1(SB)
+ MOVV $876, R12
+ JMP callbackasm1(SB)
+ MOVV $877, R12
+ JMP callbackasm1(SB)
+ MOVV $878, R12
+ JMP callbackasm1(SB)
+ MOVV $879, R12
+ JMP callbackasm1(SB)
+ MOVV $880, R12
+ JMP callbackasm1(SB)
+ MOVV $881, R12
+ JMP callbackasm1(SB)
+ MOVV $882, R12
+ JMP callbackasm1(SB)
+ MOVV $883, R12
+ JMP callbackasm1(SB)
+ MOVV $884, R12
+ JMP callbackasm1(SB)
+ MOVV $885, R12
+ JMP callbackasm1(SB)
+ MOVV $886, R12
+ JMP callbackasm1(SB)
+ MOVV $887, R12
+ JMP callbackasm1(SB)
+ MOVV $888, R12
+ JMP callbackasm1(SB)
+ MOVV $889, R12
+ JMP callbackasm1(SB)
+ MOVV $890, R12
+ JMP callbackasm1(SB)
+ MOVV $891, R12
+ JMP callbackasm1(SB)
+ MOVV $892, R12
+ JMP callbackasm1(SB)
+ MOVV $893, R12
+ JMP callbackasm1(SB)
+ MOVV $894, R12
+ JMP callbackasm1(SB)
+ MOVV $895, R12
+ JMP callbackasm1(SB)
+ MOVV $896, R12
+ JMP callbackasm1(SB)
+ MOVV $897, R12
+ JMP callbackasm1(SB)
+ MOVV $898, R12
+ JMP callbackasm1(SB)
+ MOVV $899, R12
+ JMP callbackasm1(SB)
+ MOVV $900, R12
+ JMP callbackasm1(SB)
+ MOVV $901, R12
+ JMP callbackasm1(SB)
+ MOVV $902, R12
+ JMP callbackasm1(SB)
+ MOVV $903, R12
+ JMP callbackasm1(SB)
+ MOVV $904, R12
+ JMP callbackasm1(SB)
+ MOVV $905, R12
+ JMP callbackasm1(SB)
+ MOVV $906, R12
+ JMP callbackasm1(SB)
+ MOVV $907, R12
+ JMP callbackasm1(SB)
+ MOVV $908, R12
+ JMP callbackasm1(SB)
+ MOVV $909, R12
+ JMP callbackasm1(SB)
+ MOVV $910, R12
+ JMP callbackasm1(SB)
+ MOVV $911, R12
+ JMP callbackasm1(SB)
+ MOVV $912, R12
+ JMP callbackasm1(SB)
+ MOVV $913, R12
+ JMP callbackasm1(SB)
+ MOVV $914, R12
+ JMP callbackasm1(SB)
+ MOVV $915, R12
+ JMP callbackasm1(SB)
+ MOVV $916, R12
+ JMP callbackasm1(SB)
+ MOVV $917, R12
+ JMP callbackasm1(SB)
+ MOVV $918, R12
+ JMP callbackasm1(SB)
+ MOVV $919, R12
+ JMP callbackasm1(SB)
+ MOVV $920, R12
+ JMP callbackasm1(SB)
+ MOVV $921, R12
+ JMP callbackasm1(SB)
+ MOVV $922, R12
+ JMP callbackasm1(SB)
+ MOVV $923, R12
+ JMP callbackasm1(SB)
+ MOVV $924, R12
+ JMP callbackasm1(SB)
+ MOVV $925, R12
+ JMP callbackasm1(SB)
+ MOVV $926, R12
+ JMP callbackasm1(SB)
+ MOVV $927, R12
+ JMP callbackasm1(SB)
+ MOVV $928, R12
+ JMP callbackasm1(SB)
+ MOVV $929, R12
+ JMP callbackasm1(SB)
+ MOVV $930, R12
+ JMP callbackasm1(SB)
+ MOVV $931, R12
+ JMP callbackasm1(SB)
+ MOVV $932, R12
+ JMP callbackasm1(SB)
+ MOVV $933, R12
+ JMP callbackasm1(SB)
+ MOVV $934, R12
+ JMP callbackasm1(SB)
+ MOVV $935, R12
+ JMP callbackasm1(SB)
+ MOVV $936, R12
+ JMP callbackasm1(SB)
+ MOVV $937, R12
+ JMP callbackasm1(SB)
+ MOVV $938, R12
+ JMP callbackasm1(SB)
+ MOVV $939, R12
+ JMP callbackasm1(SB)
+ MOVV $940, R12
+ JMP callbackasm1(SB)
+ MOVV $941, R12
+ JMP callbackasm1(SB)
+ MOVV $942, R12
+ JMP callbackasm1(SB)
+ MOVV $943, R12
+ JMP callbackasm1(SB)
+ MOVV $944, R12
+ JMP callbackasm1(SB)
+ MOVV $945, R12
+ JMP callbackasm1(SB)
+ MOVV $946, R12
+ JMP callbackasm1(SB)
+ MOVV $947, R12
+ JMP callbackasm1(SB)
+ MOVV $948, R12
+ JMP callbackasm1(SB)
+ MOVV $949, R12
+ JMP callbackasm1(SB)
+ MOVV $950, R12
+ JMP callbackasm1(SB)
+ MOVV $951, R12
+ JMP callbackasm1(SB)
+ MOVV $952, R12
+ JMP callbackasm1(SB)
+ MOVV $953, R12
+ JMP callbackasm1(SB)
+ MOVV $954, R12
+ JMP callbackasm1(SB)
+ MOVV $955, R12
+ JMP callbackasm1(SB)
+ MOVV $956, R12
+ JMP callbackasm1(SB)
+ MOVV $957, R12
+ JMP callbackasm1(SB)
+ MOVV $958, R12
+ JMP callbackasm1(SB)
+ MOVV $959, R12
+ JMP callbackasm1(SB)
+ MOVV $960, R12
+ JMP callbackasm1(SB)
+ MOVV $961, R12
+ JMP callbackasm1(SB)
+ MOVV $962, R12
+ JMP callbackasm1(SB)
+ MOVV $963, R12
+ JMP callbackasm1(SB)
+ MOVV $964, R12
+ JMP callbackasm1(SB)
+ MOVV $965, R12
+ JMP callbackasm1(SB)
+ MOVV $966, R12
+ JMP callbackasm1(SB)
+ MOVV $967, R12
+ JMP callbackasm1(SB)
+ MOVV $968, R12
+ JMP callbackasm1(SB)
+ MOVV $969, R12
+ JMP callbackasm1(SB)
+ MOVV $970, R12
+ JMP callbackasm1(SB)
+ MOVV $971, R12
+ JMP callbackasm1(SB)
+ MOVV $972, R12
+ JMP callbackasm1(SB)
+ MOVV $973, R12
+ JMP callbackasm1(SB)
+ MOVV $974, R12
+ JMP callbackasm1(SB)
+ MOVV $975, R12
+ JMP callbackasm1(SB)
+ MOVV $976, R12
+ JMP callbackasm1(SB)
+ MOVV $977, R12
+ JMP callbackasm1(SB)
+ MOVV $978, R12
+ JMP callbackasm1(SB)
+ MOVV $979, R12
+ JMP callbackasm1(SB)
+ MOVV $980, R12
+ JMP callbackasm1(SB)
+ MOVV $981, R12
+ JMP callbackasm1(SB)
+ MOVV $982, R12
+ JMP callbackasm1(SB)
+ MOVV $983, R12
+ JMP callbackasm1(SB)
+ MOVV $984, R12
+ JMP callbackasm1(SB)
+ MOVV $985, R12
+ JMP callbackasm1(SB)
+ MOVV $986, R12
+ JMP callbackasm1(SB)
+ MOVV $987, R12
+ JMP callbackasm1(SB)
+ MOVV $988, R12
+ JMP callbackasm1(SB)
+ MOVV $989, R12
+ JMP callbackasm1(SB)
+ MOVV $990, R12
+ JMP callbackasm1(SB)
+ MOVV $991, R12
+ JMP callbackasm1(SB)
+ MOVV $992, R12
+ JMP callbackasm1(SB)
+ MOVV $993, R12
+ JMP callbackasm1(SB)
+ MOVV $994, R12
+ JMP callbackasm1(SB)
+ MOVV $995, R12
+ JMP callbackasm1(SB)
+ MOVV $996, R12
+ JMP callbackasm1(SB)
+ MOVV $997, R12
+ JMP callbackasm1(SB)
+ MOVV $998, R12
+ JMP callbackasm1(SB)
+ MOVV $999, R12
+ JMP callbackasm1(SB)
+ MOVV $1000, R12
+ JMP callbackasm1(SB)
+ MOVV $1001, R12
+ JMP callbackasm1(SB)
+ MOVV $1002, R12
+ JMP callbackasm1(SB)
+ MOVV $1003, R12
+ JMP callbackasm1(SB)
+ MOVV $1004, R12
+ JMP callbackasm1(SB)
+ MOVV $1005, R12
+ JMP callbackasm1(SB)
+ MOVV $1006, R12
+ JMP callbackasm1(SB)
+ MOVV $1007, R12
+ JMP callbackasm1(SB)
+ MOVV $1008, R12
+ JMP callbackasm1(SB)
+ MOVV $1009, R12
+ JMP callbackasm1(SB)
+ MOVV $1010, R12
+ JMP callbackasm1(SB)
+ MOVV $1011, R12
+ JMP callbackasm1(SB)
+ MOVV $1012, R12
+ JMP callbackasm1(SB)
+ MOVV $1013, R12
+ JMP callbackasm1(SB)
+ MOVV $1014, R12
+ JMP callbackasm1(SB)
+ MOVV $1015, R12
+ JMP callbackasm1(SB)
+ MOVV $1016, R12
+ JMP callbackasm1(SB)
+ MOVV $1017, R12
+ JMP callbackasm1(SB)
+ MOVV $1018, R12
+ JMP callbackasm1(SB)
+ MOVV $1019, R12
+ JMP callbackasm1(SB)
+ MOVV $1020, R12
+ JMP callbackasm1(SB)
+ MOVV $1021, R12
+ JMP callbackasm1(SB)
+ MOVV $1022, R12
+ JMP callbackasm1(SB)
+ MOVV $1023, R12
+ JMP callbackasm1(SB)
+ MOVV $1024, R12
+ JMP callbackasm1(SB)
+ MOVV $1025, R12
+ JMP callbackasm1(SB)
+ MOVV $1026, R12
+ JMP callbackasm1(SB)
+ MOVV $1027, R12
+ JMP callbackasm1(SB)
+ MOVV $1028, R12
+ JMP callbackasm1(SB)
+ MOVV $1029, R12
+ JMP callbackasm1(SB)
+ MOVV $1030, R12
+ JMP callbackasm1(SB)
+ MOVV $1031, R12
+ JMP callbackasm1(SB)
+ MOVV $1032, R12
+ JMP callbackasm1(SB)
+ MOVV $1033, R12
+ JMP callbackasm1(SB)
+ MOVV $1034, R12
+ JMP callbackasm1(SB)
+ MOVV $1035, R12
+ JMP callbackasm1(SB)
+ MOVV $1036, R12
+ JMP callbackasm1(SB)
+ MOVV $1037, R12
+ JMP callbackasm1(SB)
+ MOVV $1038, R12
+ JMP callbackasm1(SB)
+ MOVV $1039, R12
+ JMP callbackasm1(SB)
+ MOVV $1040, R12
+ JMP callbackasm1(SB)
+ MOVV $1041, R12
+ JMP callbackasm1(SB)
+ MOVV $1042, R12
+ JMP callbackasm1(SB)
+ MOVV $1043, R12
+ JMP callbackasm1(SB)
+ MOVV $1044, R12
+ JMP callbackasm1(SB)
+ MOVV $1045, R12
+ JMP callbackasm1(SB)
+ MOVV $1046, R12
+ JMP callbackasm1(SB)
+ MOVV $1047, R12
+ JMP callbackasm1(SB)
+ MOVV $1048, R12
+ JMP callbackasm1(SB)
+ MOVV $1049, R12
+ JMP callbackasm1(SB)
+ MOVV $1050, R12
+ JMP callbackasm1(SB)
+ MOVV $1051, R12
+ JMP callbackasm1(SB)
+ MOVV $1052, R12
+ JMP callbackasm1(SB)
+ MOVV $1053, R12
+ JMP callbackasm1(SB)
+ MOVV $1054, R12
+ JMP callbackasm1(SB)
+ MOVV $1055, R12
+ JMP callbackasm1(SB)
+ MOVV $1056, R12
+ JMP callbackasm1(SB)
+ MOVV $1057, R12
+ JMP callbackasm1(SB)
+ MOVV $1058, R12
+ JMP callbackasm1(SB)
+ MOVV $1059, R12
+ JMP callbackasm1(SB)
+ MOVV $1060, R12
+ JMP callbackasm1(SB)
+ MOVV $1061, R12
+ JMP callbackasm1(SB)
+ MOVV $1062, R12
+ JMP callbackasm1(SB)
+ MOVV $1063, R12
+ JMP callbackasm1(SB)
+ MOVV $1064, R12
+ JMP callbackasm1(SB)
+ MOVV $1065, R12
+ JMP callbackasm1(SB)
+ MOVV $1066, R12
+ JMP callbackasm1(SB)
+ MOVV $1067, R12
+ JMP callbackasm1(SB)
+ MOVV $1068, R12
+ JMP callbackasm1(SB)
+ MOVV $1069, R12
+ JMP callbackasm1(SB)
+ MOVV $1070, R12
+ JMP callbackasm1(SB)
+ MOVV $1071, R12
+ JMP callbackasm1(SB)
+ MOVV $1072, R12
+ JMP callbackasm1(SB)
+ MOVV $1073, R12
+ JMP callbackasm1(SB)
+ MOVV $1074, R12
+ JMP callbackasm1(SB)
+ MOVV $1075, R12
+ JMP callbackasm1(SB)
+ MOVV $1076, R12
+ JMP callbackasm1(SB)
+ MOVV $1077, R12
+ JMP callbackasm1(SB)
+ MOVV $1078, R12
+ JMP callbackasm1(SB)
+ MOVV $1079, R12
+ JMP callbackasm1(SB)
+ MOVV $1080, R12
+ JMP callbackasm1(SB)
+ MOVV $1081, R12
+ JMP callbackasm1(SB)
+ MOVV $1082, R12
+ JMP callbackasm1(SB)
+ MOVV $1083, R12
+ JMP callbackasm1(SB)
+ MOVV $1084, R12
+ JMP callbackasm1(SB)
+ MOVV $1085, R12
+ JMP callbackasm1(SB)
+ MOVV $1086, R12
+ JMP callbackasm1(SB)
+ MOVV $1087, R12
+ JMP callbackasm1(SB)
+ MOVV $1088, R12
+ JMP callbackasm1(SB)
+ MOVV $1089, R12
+ JMP callbackasm1(SB)
+ MOVV $1090, R12
+ JMP callbackasm1(SB)
+ MOVV $1091, R12
+ JMP callbackasm1(SB)
+ MOVV $1092, R12
+ JMP callbackasm1(SB)
+ MOVV $1093, R12
+ JMP callbackasm1(SB)
+ MOVV $1094, R12
+ JMP callbackasm1(SB)
+ MOVV $1095, R12
+ JMP callbackasm1(SB)
+ MOVV $1096, R12
+ JMP callbackasm1(SB)
+ MOVV $1097, R12
+ JMP callbackasm1(SB)
+ MOVV $1098, R12
+ JMP callbackasm1(SB)
+ MOVV $1099, R12
+ JMP callbackasm1(SB)
+ MOVV $1100, R12
+ JMP callbackasm1(SB)
+ MOVV $1101, R12
+ JMP callbackasm1(SB)
+ MOVV $1102, R12
+ JMP callbackasm1(SB)
+ MOVV $1103, R12
+ JMP callbackasm1(SB)
+ MOVV $1104, R12
+ JMP callbackasm1(SB)
+ MOVV $1105, R12
+ JMP callbackasm1(SB)
+ MOVV $1106, R12
+ JMP callbackasm1(SB)
+ MOVV $1107, R12
+ JMP callbackasm1(SB)
+ MOVV $1108, R12
+ JMP callbackasm1(SB)
+ MOVV $1109, R12
+ JMP callbackasm1(SB)
+ MOVV $1110, R12
+ JMP callbackasm1(SB)
+ MOVV $1111, R12
+ JMP callbackasm1(SB)
+ MOVV $1112, R12
+ JMP callbackasm1(SB)
+ MOVV $1113, R12
+ JMP callbackasm1(SB)
+ MOVV $1114, R12
+ JMP callbackasm1(SB)
+ MOVV $1115, R12
+ JMP callbackasm1(SB)
+ MOVV $1116, R12
+ JMP callbackasm1(SB)
+ MOVV $1117, R12
+ JMP callbackasm1(SB)
+ MOVV $1118, R12
+ JMP callbackasm1(SB)
+ MOVV $1119, R12
+ JMP callbackasm1(SB)
+ MOVV $1120, R12
+ JMP callbackasm1(SB)
+ MOVV $1121, R12
+ JMP callbackasm1(SB)
+ MOVV $1122, R12
+ JMP callbackasm1(SB)
+ MOVV $1123, R12
+ JMP callbackasm1(SB)
+ MOVV $1124, R12
+ JMP callbackasm1(SB)
+ MOVV $1125, R12
+ JMP callbackasm1(SB)
+ MOVV $1126, R12
+ JMP callbackasm1(SB)
+ MOVV $1127, R12
+ JMP callbackasm1(SB)
+ MOVV $1128, R12
+ JMP callbackasm1(SB)
+ MOVV $1129, R12
+ JMP callbackasm1(SB)
+ MOVV $1130, R12
+ JMP callbackasm1(SB)
+ MOVV $1131, R12
+ JMP callbackasm1(SB)
+ MOVV $1132, R12
+ JMP callbackasm1(SB)
+ MOVV $1133, R12
+ JMP callbackasm1(SB)
+ MOVV $1134, R12
+ JMP callbackasm1(SB)
+ MOVV $1135, R12
+ JMP callbackasm1(SB)
+ MOVV $1136, R12
+ JMP callbackasm1(SB)
+ MOVV $1137, R12
+ JMP callbackasm1(SB)
+ MOVV $1138, R12
+ JMP callbackasm1(SB)
+ MOVV $1139, R12
+ JMP callbackasm1(SB)
+ MOVV $1140, R12
+ JMP callbackasm1(SB)
+ MOVV $1141, R12
+ JMP callbackasm1(SB)
+ MOVV $1142, R12
+ JMP callbackasm1(SB)
+ MOVV $1143, R12
+ JMP callbackasm1(SB)
+ MOVV $1144, R12
+ JMP callbackasm1(SB)
+ MOVV $1145, R12
+ JMP callbackasm1(SB)
+ MOVV $1146, R12
+ JMP callbackasm1(SB)
+ MOVV $1147, R12
+ JMP callbackasm1(SB)
+ MOVV $1148, R12
+ JMP callbackasm1(SB)
+ MOVV $1149, R12
+ JMP callbackasm1(SB)
+ MOVV $1150, R12
+ JMP callbackasm1(SB)
+ MOVV $1151, R12
+ JMP callbackasm1(SB)
+ MOVV $1152, R12
+ JMP callbackasm1(SB)
+ MOVV $1153, R12
+ JMP callbackasm1(SB)
+ MOVV $1154, R12
+ JMP callbackasm1(SB)
+ MOVV $1155, R12
+ JMP callbackasm1(SB)
+ MOVV $1156, R12
+ JMP callbackasm1(SB)
+ MOVV $1157, R12
+ JMP callbackasm1(SB)
+ MOVV $1158, R12
+ JMP callbackasm1(SB)
+ MOVV $1159, R12
+ JMP callbackasm1(SB)
+ MOVV $1160, R12
+ JMP callbackasm1(SB)
+ MOVV $1161, R12
+ JMP callbackasm1(SB)
+ MOVV $1162, R12
+ JMP callbackasm1(SB)
+ MOVV $1163, R12
+ JMP callbackasm1(SB)
+ MOVV $1164, R12
+ JMP callbackasm1(SB)
+ MOVV $1165, R12
+ JMP callbackasm1(SB)
+ MOVV $1166, R12
+ JMP callbackasm1(SB)
+ MOVV $1167, R12
+ JMP callbackasm1(SB)
+ MOVV $1168, R12
+ JMP callbackasm1(SB)
+ MOVV $1169, R12
+ JMP callbackasm1(SB)
+ MOVV $1170, R12
+ JMP callbackasm1(SB)
+ MOVV $1171, R12
+ JMP callbackasm1(SB)
+ MOVV $1172, R12
+ JMP callbackasm1(SB)
+ MOVV $1173, R12
+ JMP callbackasm1(SB)
+ MOVV $1174, R12
+ JMP callbackasm1(SB)
+ MOVV $1175, R12
+ JMP callbackasm1(SB)
+ MOVV $1176, R12
+ JMP callbackasm1(SB)
+ MOVV $1177, R12
+ JMP callbackasm1(SB)
+ MOVV $1178, R12
+ JMP callbackasm1(SB)
+ MOVV $1179, R12
+ JMP callbackasm1(SB)
+ MOVV $1180, R12
+ JMP callbackasm1(SB)
+ MOVV $1181, R12
+ JMP callbackasm1(SB)
+ MOVV $1182, R12
+ JMP callbackasm1(SB)
+ MOVV $1183, R12
+ JMP callbackasm1(SB)
+ MOVV $1184, R12
+ JMP callbackasm1(SB)
+ MOVV $1185, R12
+ JMP callbackasm1(SB)
+ MOVV $1186, R12
+ JMP callbackasm1(SB)
+ MOVV $1187, R12
+ JMP callbackasm1(SB)
+ MOVV $1188, R12
+ JMP callbackasm1(SB)
+ MOVV $1189, R12
+ JMP callbackasm1(SB)
+ MOVV $1190, R12
+ JMP callbackasm1(SB)
+ MOVV $1191, R12
+ JMP callbackasm1(SB)
+ MOVV $1192, R12
+ JMP callbackasm1(SB)
+ MOVV $1193, R12
+ JMP callbackasm1(SB)
+ MOVV $1194, R12
+ JMP callbackasm1(SB)
+ MOVV $1195, R12
+ JMP callbackasm1(SB)
+ MOVV $1196, R12
+ JMP callbackasm1(SB)
+ MOVV $1197, R12
+ JMP callbackasm1(SB)
+ MOVV $1198, R12
+ JMP callbackasm1(SB)
+ MOVV $1199, R12
+ JMP callbackasm1(SB)
+ MOVV $1200, R12
+ JMP callbackasm1(SB)
+ MOVV $1201, R12
+ JMP callbackasm1(SB)
+ MOVV $1202, R12
+ JMP callbackasm1(SB)
+ MOVV $1203, R12
+ JMP callbackasm1(SB)
+ MOVV $1204, R12
+ JMP callbackasm1(SB)
+ MOVV $1205, R12
+ JMP callbackasm1(SB)
+ MOVV $1206, R12
+ JMP callbackasm1(SB)
+ MOVV $1207, R12
+ JMP callbackasm1(SB)
+ MOVV $1208, R12
+ JMP callbackasm1(SB)
+ MOVV $1209, R12
+ JMP callbackasm1(SB)
+ MOVV $1210, R12
+ JMP callbackasm1(SB)
+ MOVV $1211, R12
+ JMP callbackasm1(SB)
+ MOVV $1212, R12
+ JMP callbackasm1(SB)
+ MOVV $1213, R12
+ JMP callbackasm1(SB)
+ MOVV $1214, R12
+ JMP callbackasm1(SB)
+ MOVV $1215, R12
+ JMP callbackasm1(SB)
+ MOVV $1216, R12
+ JMP callbackasm1(SB)
+ MOVV $1217, R12
+ JMP callbackasm1(SB)
+ MOVV $1218, R12
+ JMP callbackasm1(SB)
+ MOVV $1219, R12
+ JMP callbackasm1(SB)
+ MOVV $1220, R12
+ JMP callbackasm1(SB)
+ MOVV $1221, R12
+ JMP callbackasm1(SB)
+ MOVV $1222, R12
+ JMP callbackasm1(SB)
+ MOVV $1223, R12
+ JMP callbackasm1(SB)
+ MOVV $1224, R12
+ JMP callbackasm1(SB)
+ MOVV $1225, R12
+ JMP callbackasm1(SB)
+ MOVV $1226, R12
+ JMP callbackasm1(SB)
+ MOVV $1227, R12
+ JMP callbackasm1(SB)
+ MOVV $1228, R12
+ JMP callbackasm1(SB)
+ MOVV $1229, R12
+ JMP callbackasm1(SB)
+ MOVV $1230, R12
+ JMP callbackasm1(SB)
+ MOVV $1231, R12
+ JMP callbackasm1(SB)
+ MOVV $1232, R12
+ JMP callbackasm1(SB)
+ MOVV $1233, R12
+ JMP callbackasm1(SB)
+ MOVV $1234, R12
+ JMP callbackasm1(SB)
+ MOVV $1235, R12
+ JMP callbackasm1(SB)
+ MOVV $1236, R12
+ JMP callbackasm1(SB)
+ MOVV $1237, R12
+ JMP callbackasm1(SB)
+ MOVV $1238, R12
+ JMP callbackasm1(SB)
+ MOVV $1239, R12
+ JMP callbackasm1(SB)
+ MOVV $1240, R12
+ JMP callbackasm1(SB)
+ MOVV $1241, R12
+ JMP callbackasm1(SB)
+ MOVV $1242, R12
+ JMP callbackasm1(SB)
+ MOVV $1243, R12
+ JMP callbackasm1(SB)
+ MOVV $1244, R12
+ JMP callbackasm1(SB)
+ MOVV $1245, R12
+ JMP callbackasm1(SB)
+ MOVV $1246, R12
+ JMP callbackasm1(SB)
+ MOVV $1247, R12
+ JMP callbackasm1(SB)
+ MOVV $1248, R12
+ JMP callbackasm1(SB)
+ MOVV $1249, R12
+ JMP callbackasm1(SB)
+ MOVV $1250, R12
+ JMP callbackasm1(SB)
+ MOVV $1251, R12
+ JMP callbackasm1(SB)
+ MOVV $1252, R12
+ JMP callbackasm1(SB)
+ MOVV $1253, R12
+ JMP callbackasm1(SB)
+ MOVV $1254, R12
+ JMP callbackasm1(SB)
+ MOVV $1255, R12
+ JMP callbackasm1(SB)
+ MOVV $1256, R12
+ JMP callbackasm1(SB)
+ MOVV $1257, R12
+ JMP callbackasm1(SB)
+ MOVV $1258, R12
+ JMP callbackasm1(SB)
+ MOVV $1259, R12
+ JMP callbackasm1(SB)
+ MOVV $1260, R12
+ JMP callbackasm1(SB)
+ MOVV $1261, R12
+ JMP callbackasm1(SB)
+ MOVV $1262, R12
+ JMP callbackasm1(SB)
+ MOVV $1263, R12
+ JMP callbackasm1(SB)
+ MOVV $1264, R12
+ JMP callbackasm1(SB)
+ MOVV $1265, R12
+ JMP callbackasm1(SB)
+ MOVV $1266, R12
+ JMP callbackasm1(SB)
+ MOVV $1267, R12
+ JMP callbackasm1(SB)
+ MOVV $1268, R12
+ JMP callbackasm1(SB)
+ MOVV $1269, R12
+ JMP callbackasm1(SB)
+ MOVV $1270, R12
+ JMP callbackasm1(SB)
+ MOVV $1271, R12
+ JMP callbackasm1(SB)
+ MOVV $1272, R12
+ JMP callbackasm1(SB)
+ MOVV $1273, R12
+ JMP callbackasm1(SB)
+ MOVV $1274, R12
+ JMP callbackasm1(SB)
+ MOVV $1275, R12
+ JMP callbackasm1(SB)
+ MOVV $1276, R12
+ JMP callbackasm1(SB)
+ MOVV $1277, R12
+ JMP callbackasm1(SB)
+ MOVV $1278, R12
+ JMP callbackasm1(SB)
+ MOVV $1279, R12
+ JMP callbackasm1(SB)
+ MOVV $1280, R12
+ JMP callbackasm1(SB)
+ MOVV $1281, R12
+ JMP callbackasm1(SB)
+ MOVV $1282, R12
+ JMP callbackasm1(SB)
+ MOVV $1283, R12
+ JMP callbackasm1(SB)
+ MOVV $1284, R12
+ JMP callbackasm1(SB)
+ MOVV $1285, R12
+ JMP callbackasm1(SB)
+ MOVV $1286, R12
+ JMP callbackasm1(SB)
+ MOVV $1287, R12
+ JMP callbackasm1(SB)
+ MOVV $1288, R12
+ JMP callbackasm1(SB)
+ MOVV $1289, R12
+ JMP callbackasm1(SB)
+ MOVV $1290, R12
+ JMP callbackasm1(SB)
+ MOVV $1291, R12
+ JMP callbackasm1(SB)
+ MOVV $1292, R12
+ JMP callbackasm1(SB)
+ MOVV $1293, R12
+ JMP callbackasm1(SB)
+ MOVV $1294, R12
+ JMP callbackasm1(SB)
+ MOVV $1295, R12
+ JMP callbackasm1(SB)
+ MOVV $1296, R12
+ JMP callbackasm1(SB)
+ MOVV $1297, R12
+ JMP callbackasm1(SB)
+ MOVV $1298, R12
+ JMP callbackasm1(SB)
+ MOVV $1299, R12
+ JMP callbackasm1(SB)
+ MOVV $1300, R12
+ JMP callbackasm1(SB)
+ MOVV $1301, R12
+ JMP callbackasm1(SB)
+ MOVV $1302, R12
+ JMP callbackasm1(SB)
+ MOVV $1303, R12
+ JMP callbackasm1(SB)
+ MOVV $1304, R12
+ JMP callbackasm1(SB)
+ MOVV $1305, R12
+ JMP callbackasm1(SB)
+ MOVV $1306, R12
+ JMP callbackasm1(SB)
+ MOVV $1307, R12
+ JMP callbackasm1(SB)
+ MOVV $1308, R12
+ JMP callbackasm1(SB)
+ MOVV $1309, R12
+ JMP callbackasm1(SB)
+ MOVV $1310, R12
+ JMP callbackasm1(SB)
+ MOVV $1311, R12
+ JMP callbackasm1(SB)
+ MOVV $1312, R12
+ JMP callbackasm1(SB)
+ MOVV $1313, R12
+ JMP callbackasm1(SB)
+ MOVV $1314, R12
+ JMP callbackasm1(SB)
+ MOVV $1315, R12
+ JMP callbackasm1(SB)
+ MOVV $1316, R12
+ JMP callbackasm1(SB)
+ MOVV $1317, R12
+ JMP callbackasm1(SB)
+ MOVV $1318, R12
+ JMP callbackasm1(SB)
+ MOVV $1319, R12
+ JMP callbackasm1(SB)
+ MOVV $1320, R12
+ JMP callbackasm1(SB)
+ MOVV $1321, R12
+ JMP callbackasm1(SB)
+ MOVV $1322, R12
+ JMP callbackasm1(SB)
+ MOVV $1323, R12
+ JMP callbackasm1(SB)
+ MOVV $1324, R12
+ JMP callbackasm1(SB)
+ MOVV $1325, R12
+ JMP callbackasm1(SB)
+ MOVV $1326, R12
+ JMP callbackasm1(SB)
+ MOVV $1327, R12
+ JMP callbackasm1(SB)
+ MOVV $1328, R12
+ JMP callbackasm1(SB)
+ MOVV $1329, R12
+ JMP callbackasm1(SB)
+ MOVV $1330, R12
+ JMP callbackasm1(SB)
+ MOVV $1331, R12
+ JMP callbackasm1(SB)
+ MOVV $1332, R12
+ JMP callbackasm1(SB)
+ MOVV $1333, R12
+ JMP callbackasm1(SB)
+ MOVV $1334, R12
+ JMP callbackasm1(SB)
+ MOVV $1335, R12
+ JMP callbackasm1(SB)
+ MOVV $1336, R12
+ JMP callbackasm1(SB)
+ MOVV $1337, R12
+ JMP callbackasm1(SB)
+ MOVV $1338, R12
+ JMP callbackasm1(SB)
+ MOVV $1339, R12
+ JMP callbackasm1(SB)
+ MOVV $1340, R12
+ JMP callbackasm1(SB)
+ MOVV $1341, R12
+ JMP callbackasm1(SB)
+ MOVV $1342, R12
+ JMP callbackasm1(SB)
+ MOVV $1343, R12
+ JMP callbackasm1(SB)
+ MOVV $1344, R12
+ JMP callbackasm1(SB)
+ MOVV $1345, R12
+ JMP callbackasm1(SB)
+ MOVV $1346, R12
+ JMP callbackasm1(SB)
+ MOVV $1347, R12
+ JMP callbackasm1(SB)
+ MOVV $1348, R12
+ JMP callbackasm1(SB)
+ MOVV $1349, R12
+ JMP callbackasm1(SB)
+ MOVV $1350, R12
+ JMP callbackasm1(SB)
+ MOVV $1351, R12
+ JMP callbackasm1(SB)
+ MOVV $1352, R12
+ JMP callbackasm1(SB)
+ MOVV $1353, R12
+ JMP callbackasm1(SB)
+ MOVV $1354, R12
+ JMP callbackasm1(SB)
+ MOVV $1355, R12
+ JMP callbackasm1(SB)
+ MOVV $1356, R12
+ JMP callbackasm1(SB)
+ MOVV $1357, R12
+ JMP callbackasm1(SB)
+ MOVV $1358, R12
+ JMP callbackasm1(SB)
+ MOVV $1359, R12
+ JMP callbackasm1(SB)
+ MOVV $1360, R12
+ JMP callbackasm1(SB)
+ MOVV $1361, R12
+ JMP callbackasm1(SB)
+ MOVV $1362, R12
+ JMP callbackasm1(SB)
+ MOVV $1363, R12
+ JMP callbackasm1(SB)
+ MOVV $1364, R12
+ JMP callbackasm1(SB)
+ MOVV $1365, R12
+ JMP callbackasm1(SB)
+ MOVV $1366, R12
+ JMP callbackasm1(SB)
+ MOVV $1367, R12
+ JMP callbackasm1(SB)
+ MOVV $1368, R12
+ JMP callbackasm1(SB)
+ MOVV $1369, R12
+ JMP callbackasm1(SB)
+ MOVV $1370, R12
+ JMP callbackasm1(SB)
+ MOVV $1371, R12
+ JMP callbackasm1(SB)
+ MOVV $1372, R12
+ JMP callbackasm1(SB)
+ MOVV $1373, R12
+ JMP callbackasm1(SB)
+ MOVV $1374, R12
+ JMP callbackasm1(SB)
+ MOVV $1375, R12
+ JMP callbackasm1(SB)
+ MOVV $1376, R12
+ JMP callbackasm1(SB)
+ MOVV $1377, R12
+ JMP callbackasm1(SB)
+ MOVV $1378, R12
+ JMP callbackasm1(SB)
+ MOVV $1379, R12
+ JMP callbackasm1(SB)
+ MOVV $1380, R12
+ JMP callbackasm1(SB)
+ MOVV $1381, R12
+ JMP callbackasm1(SB)
+ MOVV $1382, R12
+ JMP callbackasm1(SB)
+ MOVV $1383, R12
+ JMP callbackasm1(SB)
+ MOVV $1384, R12
+ JMP callbackasm1(SB)
+ MOVV $1385, R12
+ JMP callbackasm1(SB)
+ MOVV $1386, R12
+ JMP callbackasm1(SB)
+ MOVV $1387, R12
+ JMP callbackasm1(SB)
+ MOVV $1388, R12
+ JMP callbackasm1(SB)
+ MOVV $1389, R12
+ JMP callbackasm1(SB)
+ MOVV $1390, R12
+ JMP callbackasm1(SB)
+ MOVV $1391, R12
+ JMP callbackasm1(SB)
+ MOVV $1392, R12
+ JMP callbackasm1(SB)
+ MOVV $1393, R12
+ JMP callbackasm1(SB)
+ MOVV $1394, R12
+ JMP callbackasm1(SB)
+ MOVV $1395, R12
+ JMP callbackasm1(SB)
+ MOVV $1396, R12
+ JMP callbackasm1(SB)
+ MOVV $1397, R12
+ JMP callbackasm1(SB)
+ MOVV $1398, R12
+ JMP callbackasm1(SB)
+ MOVV $1399, R12
+ JMP callbackasm1(SB)
+ MOVV $1400, R12
+ JMP callbackasm1(SB)
+ MOVV $1401, R12
+ JMP callbackasm1(SB)
+ MOVV $1402, R12
+ JMP callbackasm1(SB)
+ MOVV $1403, R12
+ JMP callbackasm1(SB)
+ MOVV $1404, R12
+ JMP callbackasm1(SB)
+ MOVV $1405, R12
+ JMP callbackasm1(SB)
+ MOVV $1406, R12
+ JMP callbackasm1(SB)
+ MOVV $1407, R12
+ JMP callbackasm1(SB)
+ MOVV $1408, R12
+ JMP callbackasm1(SB)
+ MOVV $1409, R12
+ JMP callbackasm1(SB)
+ MOVV $1410, R12
+ JMP callbackasm1(SB)
+ MOVV $1411, R12
+ JMP callbackasm1(SB)
+ MOVV $1412, R12
+ JMP callbackasm1(SB)
+ MOVV $1413, R12
+ JMP callbackasm1(SB)
+ MOVV $1414, R12
+ JMP callbackasm1(SB)
+ MOVV $1415, R12
+ JMP callbackasm1(SB)
+ MOVV $1416, R12
+ JMP callbackasm1(SB)
+ MOVV $1417, R12
+ JMP callbackasm1(SB)
+ MOVV $1418, R12
+ JMP callbackasm1(SB)
+ MOVV $1419, R12
+ JMP callbackasm1(SB)
+ MOVV $1420, R12
+ JMP callbackasm1(SB)
+ MOVV $1421, R12
+ JMP callbackasm1(SB)
+ MOVV $1422, R12
+ JMP callbackasm1(SB)
+ MOVV $1423, R12
+ JMP callbackasm1(SB)
+ MOVV $1424, R12
+ JMP callbackasm1(SB)
+ MOVV $1425, R12
+ JMP callbackasm1(SB)
+ MOVV $1426, R12
+ JMP callbackasm1(SB)
+ MOVV $1427, R12
+ JMP callbackasm1(SB)
+ MOVV $1428, R12
+ JMP callbackasm1(SB)
+ MOVV $1429, R12
+ JMP callbackasm1(SB)
+ MOVV $1430, R12
+ JMP callbackasm1(SB)
+ MOVV $1431, R12
+ JMP callbackasm1(SB)
+ MOVV $1432, R12
+ JMP callbackasm1(SB)
+ MOVV $1433, R12
+ JMP callbackasm1(SB)
+ MOVV $1434, R12
+ JMP callbackasm1(SB)
+ MOVV $1435, R12
+ JMP callbackasm1(SB)
+ MOVV $1436, R12
+ JMP callbackasm1(SB)
+ MOVV $1437, R12
+ JMP callbackasm1(SB)
+ MOVV $1438, R12
+ JMP callbackasm1(SB)
+ MOVV $1439, R12
+ JMP callbackasm1(SB)
+ MOVV $1440, R12
+ JMP callbackasm1(SB)
+ MOVV $1441, R12
+ JMP callbackasm1(SB)
+ MOVV $1442, R12
+ JMP callbackasm1(SB)
+ MOVV $1443, R12
+ JMP callbackasm1(SB)
+ MOVV $1444, R12
+ JMP callbackasm1(SB)
+ MOVV $1445, R12
+ JMP callbackasm1(SB)
+ MOVV $1446, R12
+ JMP callbackasm1(SB)
+ MOVV $1447, R12
+ JMP callbackasm1(SB)
+ MOVV $1448, R12
+ JMP callbackasm1(SB)
+ MOVV $1449, R12
+ JMP callbackasm1(SB)
+ MOVV $1450, R12
+ JMP callbackasm1(SB)
+ MOVV $1451, R12
+ JMP callbackasm1(SB)
+ MOVV $1452, R12
+ JMP callbackasm1(SB)
+ MOVV $1453, R12
+ JMP callbackasm1(SB)
+ MOVV $1454, R12
+ JMP callbackasm1(SB)
+ MOVV $1455, R12
+ JMP callbackasm1(SB)
+ MOVV $1456, R12
+ JMP callbackasm1(SB)
+ MOVV $1457, R12
+ JMP callbackasm1(SB)
+ MOVV $1458, R12
+ JMP callbackasm1(SB)
+ MOVV $1459, R12
+ JMP callbackasm1(SB)
+ MOVV $1460, R12
+ JMP callbackasm1(SB)
+ MOVV $1461, R12
+ JMP callbackasm1(SB)
+ MOVV $1462, R12
+ JMP callbackasm1(SB)
+ MOVV $1463, R12
+ JMP callbackasm1(SB)
+ MOVV $1464, R12
+ JMP callbackasm1(SB)
+ MOVV $1465, R12
+ JMP callbackasm1(SB)
+ MOVV $1466, R12
+ JMP callbackasm1(SB)
+ MOVV $1467, R12
+ JMP callbackasm1(SB)
+ MOVV $1468, R12
+ JMP callbackasm1(SB)
+ MOVV $1469, R12
+ JMP callbackasm1(SB)
+ MOVV $1470, R12
+ JMP callbackasm1(SB)
+ MOVV $1471, R12
+ JMP callbackasm1(SB)
+ MOVV $1472, R12
+ JMP callbackasm1(SB)
+ MOVV $1473, R12
+ JMP callbackasm1(SB)
+ MOVV $1474, R12
+ JMP callbackasm1(SB)
+ MOVV $1475, R12
+ JMP callbackasm1(SB)
+ MOVV $1476, R12
+ JMP callbackasm1(SB)
+ MOVV $1477, R12
+ JMP callbackasm1(SB)
+ MOVV $1478, R12
+ JMP callbackasm1(SB)
+ MOVV $1479, R12
+ JMP callbackasm1(SB)
+ MOVV $1480, R12
+ JMP callbackasm1(SB)
+ MOVV $1481, R12
+ JMP callbackasm1(SB)
+ MOVV $1482, R12
+ JMP callbackasm1(SB)
+ MOVV $1483, R12
+ JMP callbackasm1(SB)
+ MOVV $1484, R12
+ JMP callbackasm1(SB)
+ MOVV $1485, R12
+ JMP callbackasm1(SB)
+ MOVV $1486, R12
+ JMP callbackasm1(SB)
+ MOVV $1487, R12
+ JMP callbackasm1(SB)
+ MOVV $1488, R12
+ JMP callbackasm1(SB)
+ MOVV $1489, R12
+ JMP callbackasm1(SB)
+ MOVV $1490, R12
+ JMP callbackasm1(SB)
+ MOVV $1491, R12
+ JMP callbackasm1(SB)
+ MOVV $1492, R12
+ JMP callbackasm1(SB)
+ MOVV $1493, R12
+ JMP callbackasm1(SB)
+ MOVV $1494, R12
+ JMP callbackasm1(SB)
+ MOVV $1495, R12
+ JMP callbackasm1(SB)
+ MOVV $1496, R12
+ JMP callbackasm1(SB)
+ MOVV $1497, R12
+ JMP callbackasm1(SB)
+ MOVV $1498, R12
+ JMP callbackasm1(SB)
+ MOVV $1499, R12
+ JMP callbackasm1(SB)
+ MOVV $1500, R12
+ JMP callbackasm1(SB)
+ MOVV $1501, R12
+ JMP callbackasm1(SB)
+ MOVV $1502, R12
+ JMP callbackasm1(SB)
+ MOVV $1503, R12
+ JMP callbackasm1(SB)
+ MOVV $1504, R12
+ JMP callbackasm1(SB)
+ MOVV $1505, R12
+ JMP callbackasm1(SB)
+ MOVV $1506, R12
+ JMP callbackasm1(SB)
+ MOVV $1507, R12
+ JMP callbackasm1(SB)
+ MOVV $1508, R12
+ JMP callbackasm1(SB)
+ MOVV $1509, R12
+ JMP callbackasm1(SB)
+ MOVV $1510, R12
+ JMP callbackasm1(SB)
+ MOVV $1511, R12
+ JMP callbackasm1(SB)
+ MOVV $1512, R12
+ JMP callbackasm1(SB)
+ MOVV $1513, R12
+ JMP callbackasm1(SB)
+ MOVV $1514, R12
+ JMP callbackasm1(SB)
+ MOVV $1515, R12
+ JMP callbackasm1(SB)
+ MOVV $1516, R12
+ JMP callbackasm1(SB)
+ MOVV $1517, R12
+ JMP callbackasm1(SB)
+ MOVV $1518, R12
+ JMP callbackasm1(SB)
+ MOVV $1519, R12
+ JMP callbackasm1(SB)
+ MOVV $1520, R12
+ JMP callbackasm1(SB)
+ MOVV $1521, R12
+ JMP callbackasm1(SB)
+ MOVV $1522, R12
+ JMP callbackasm1(SB)
+ MOVV $1523, R12
+ JMP callbackasm1(SB)
+ MOVV $1524, R12
+ JMP callbackasm1(SB)
+ MOVV $1525, R12
+ JMP callbackasm1(SB)
+ MOVV $1526, R12
+ JMP callbackasm1(SB)
+ MOVV $1527, R12
+ JMP callbackasm1(SB)
+ MOVV $1528, R12
+ JMP callbackasm1(SB)
+ MOVV $1529, R12
+ JMP callbackasm1(SB)
+ MOVV $1530, R12
+ JMP callbackasm1(SB)
+ MOVV $1531, R12
+ JMP callbackasm1(SB)
+ MOVV $1532, R12
+ JMP callbackasm1(SB)
+ MOVV $1533, R12
+ JMP callbackasm1(SB)
+ MOVV $1534, R12
+ JMP callbackasm1(SB)
+ MOVV $1535, R12
+ JMP callbackasm1(SB)
+ MOVV $1536, R12
+ JMP callbackasm1(SB)
+ MOVV $1537, R12
+ JMP callbackasm1(SB)
+ MOVV $1538, R12
+ JMP callbackasm1(SB)
+ MOVV $1539, R12
+ JMP callbackasm1(SB)
+ MOVV $1540, R12
+ JMP callbackasm1(SB)
+ MOVV $1541, R12
+ JMP callbackasm1(SB)
+ MOVV $1542, R12
+ JMP callbackasm1(SB)
+ MOVV $1543, R12
+ JMP callbackasm1(SB)
+ MOVV $1544, R12
+ JMP callbackasm1(SB)
+ MOVV $1545, R12
+ JMP callbackasm1(SB)
+ MOVV $1546, R12
+ JMP callbackasm1(SB)
+ MOVV $1547, R12
+ JMP callbackasm1(SB)
+ MOVV $1548, R12
+ JMP callbackasm1(SB)
+ MOVV $1549, R12
+ JMP callbackasm1(SB)
+ MOVV $1550, R12
+ JMP callbackasm1(SB)
+ MOVV $1551, R12
+ JMP callbackasm1(SB)
+ MOVV $1552, R12
+ JMP callbackasm1(SB)
+ MOVV $1553, R12
+ JMP callbackasm1(SB)
+ MOVV $1554, R12
+ JMP callbackasm1(SB)
+ MOVV $1555, R12
+ JMP callbackasm1(SB)
+ MOVV $1556, R12
+ JMP callbackasm1(SB)
+ MOVV $1557, R12
+ JMP callbackasm1(SB)
+ MOVV $1558, R12
+ JMP callbackasm1(SB)
+ MOVV $1559, R12
+ JMP callbackasm1(SB)
+ MOVV $1560, R12
+ JMP callbackasm1(SB)
+ MOVV $1561, R12
+ JMP callbackasm1(SB)
+ MOVV $1562, R12
+ JMP callbackasm1(SB)
+ MOVV $1563, R12
+ JMP callbackasm1(SB)
+ MOVV $1564, R12
+ JMP callbackasm1(SB)
+ MOVV $1565, R12
+ JMP callbackasm1(SB)
+ MOVV $1566, R12
+ JMP callbackasm1(SB)
+ MOVV $1567, R12
+ JMP callbackasm1(SB)
+ MOVV $1568, R12
+ JMP callbackasm1(SB)
+ MOVV $1569, R12
+ JMP callbackasm1(SB)
+ MOVV $1570, R12
+ JMP callbackasm1(SB)
+ MOVV $1571, R12
+ JMP callbackasm1(SB)
+ MOVV $1572, R12
+ JMP callbackasm1(SB)
+ MOVV $1573, R12
+ JMP callbackasm1(SB)
+ MOVV $1574, R12
+ JMP callbackasm1(SB)
+ MOVV $1575, R12
+ JMP callbackasm1(SB)
+ MOVV $1576, R12
+ JMP callbackasm1(SB)
+ MOVV $1577, R12
+ JMP callbackasm1(SB)
+ MOVV $1578, R12
+ JMP callbackasm1(SB)
+ MOVV $1579, R12
+ JMP callbackasm1(SB)
+ MOVV $1580, R12
+ JMP callbackasm1(SB)
+ MOVV $1581, R12
+ JMP callbackasm1(SB)
+ MOVV $1582, R12
+ JMP callbackasm1(SB)
+ MOVV $1583, R12
+ JMP callbackasm1(SB)
+ MOVV $1584, R12
+ JMP callbackasm1(SB)
+ MOVV $1585, R12
+ JMP callbackasm1(SB)
+ MOVV $1586, R12
+ JMP callbackasm1(SB)
+ MOVV $1587, R12
+ JMP callbackasm1(SB)
+ MOVV $1588, R12
+ JMP callbackasm1(SB)
+ MOVV $1589, R12
+ JMP callbackasm1(SB)
+ MOVV $1590, R12
+ JMP callbackasm1(SB)
+ MOVV $1591, R12
+ JMP callbackasm1(SB)
+ MOVV $1592, R12
+ JMP callbackasm1(SB)
+ MOVV $1593, R12
+ JMP callbackasm1(SB)
+ MOVV $1594, R12
+ JMP callbackasm1(SB)
+ MOVV $1595, R12
+ JMP callbackasm1(SB)
+ MOVV $1596, R12
+ JMP callbackasm1(SB)
+ MOVV $1597, R12
+ JMP callbackasm1(SB)
+ MOVV $1598, R12
+ JMP callbackasm1(SB)
+ MOVV $1599, R12
+ JMP callbackasm1(SB)
+ MOVV $1600, R12
+ JMP callbackasm1(SB)
+ MOVV $1601, R12
+ JMP callbackasm1(SB)
+ MOVV $1602, R12
+ JMP callbackasm1(SB)
+ MOVV $1603, R12
+ JMP callbackasm1(SB)
+ MOVV $1604, R12
+ JMP callbackasm1(SB)
+ MOVV $1605, R12
+ JMP callbackasm1(SB)
+ MOVV $1606, R12
+ JMP callbackasm1(SB)
+ MOVV $1607, R12
+ JMP callbackasm1(SB)
+ MOVV $1608, R12
+ JMP callbackasm1(SB)
+ MOVV $1609, R12
+ JMP callbackasm1(SB)
+ MOVV $1610, R12
+ JMP callbackasm1(SB)
+ MOVV $1611, R12
+ JMP callbackasm1(SB)
+ MOVV $1612, R12
+ JMP callbackasm1(SB)
+ MOVV $1613, R12
+ JMP callbackasm1(SB)
+ MOVV $1614, R12
+ JMP callbackasm1(SB)
+ MOVV $1615, R12
+ JMP callbackasm1(SB)
+ MOVV $1616, R12
+ JMP callbackasm1(SB)
+ MOVV $1617, R12
+ JMP callbackasm1(SB)
+ MOVV $1618, R12
+ JMP callbackasm1(SB)
+ MOVV $1619, R12
+ JMP callbackasm1(SB)
+ MOVV $1620, R12
+ JMP callbackasm1(SB)
+ MOVV $1621, R12
+ JMP callbackasm1(SB)
+ MOVV $1622, R12
+ JMP callbackasm1(SB)
+ MOVV $1623, R12
+ JMP callbackasm1(SB)
+ MOVV $1624, R12
+ JMP callbackasm1(SB)
+ MOVV $1625, R12
+ JMP callbackasm1(SB)
+ MOVV $1626, R12
+ JMP callbackasm1(SB)
+ MOVV $1627, R12
+ JMP callbackasm1(SB)
+ MOVV $1628, R12
+ JMP callbackasm1(SB)
+ MOVV $1629, R12
+ JMP callbackasm1(SB)
+ MOVV $1630, R12
+ JMP callbackasm1(SB)
+ MOVV $1631, R12
+ JMP callbackasm1(SB)
+ MOVV $1632, R12
+ JMP callbackasm1(SB)
+ MOVV $1633, R12
+ JMP callbackasm1(SB)
+ MOVV $1634, R12
+ JMP callbackasm1(SB)
+ MOVV $1635, R12
+ JMP callbackasm1(SB)
+ MOVV $1636, R12
+ JMP callbackasm1(SB)
+ MOVV $1637, R12
+ JMP callbackasm1(SB)
+ MOVV $1638, R12
+ JMP callbackasm1(SB)
+ MOVV $1639, R12
+ JMP callbackasm1(SB)
+ MOVV $1640, R12
+ JMP callbackasm1(SB)
+ MOVV $1641, R12
+ JMP callbackasm1(SB)
+ MOVV $1642, R12
+ JMP callbackasm1(SB)
+ MOVV $1643, R12
+ JMP callbackasm1(SB)
+ MOVV $1644, R12
+ JMP callbackasm1(SB)
+ MOVV $1645, R12
+ JMP callbackasm1(SB)
+ MOVV $1646, R12
+ JMP callbackasm1(SB)
+ MOVV $1647, R12
+ JMP callbackasm1(SB)
+ MOVV $1648, R12
+ JMP callbackasm1(SB)
+ MOVV $1649, R12
+ JMP callbackasm1(SB)
+ MOVV $1650, R12
+ JMP callbackasm1(SB)
+ MOVV $1651, R12
+ JMP callbackasm1(SB)
+ MOVV $1652, R12
+ JMP callbackasm1(SB)
+ MOVV $1653, R12
+ JMP callbackasm1(SB)
+ MOVV $1654, R12
+ JMP callbackasm1(SB)
+ MOVV $1655, R12
+ JMP callbackasm1(SB)
+ MOVV $1656, R12
+ JMP callbackasm1(SB)
+ MOVV $1657, R12
+ JMP callbackasm1(SB)
+ MOVV $1658, R12
+ JMP callbackasm1(SB)
+ MOVV $1659, R12
+ JMP callbackasm1(SB)
+ MOVV $1660, R12
+ JMP callbackasm1(SB)
+ MOVV $1661, R12
+ JMP callbackasm1(SB)
+ MOVV $1662, R12
+ JMP callbackasm1(SB)
+ MOVV $1663, R12
+ JMP callbackasm1(SB)
+ MOVV $1664, R12
+ JMP callbackasm1(SB)
+ MOVV $1665, R12
+ JMP callbackasm1(SB)
+ MOVV $1666, R12
+ JMP callbackasm1(SB)
+ MOVV $1667, R12
+ JMP callbackasm1(SB)
+ MOVV $1668, R12
+ JMP callbackasm1(SB)
+ MOVV $1669, R12
+ JMP callbackasm1(SB)
+ MOVV $1670, R12
+ JMP callbackasm1(SB)
+ MOVV $1671, R12
+ JMP callbackasm1(SB)
+ MOVV $1672, R12
+ JMP callbackasm1(SB)
+ MOVV $1673, R12
+ JMP callbackasm1(SB)
+ MOVV $1674, R12
+ JMP callbackasm1(SB)
+ MOVV $1675, R12
+ JMP callbackasm1(SB)
+ MOVV $1676, R12
+ JMP callbackasm1(SB)
+ MOVV $1677, R12
+ JMP callbackasm1(SB)
+ MOVV $1678, R12
+ JMP callbackasm1(SB)
+ MOVV $1679, R12
+ JMP callbackasm1(SB)
+ MOVV $1680, R12
+ JMP callbackasm1(SB)
+ MOVV $1681, R12
+ JMP callbackasm1(SB)
+ MOVV $1682, R12
+ JMP callbackasm1(SB)
+ MOVV $1683, R12
+ JMP callbackasm1(SB)
+ MOVV $1684, R12
+ JMP callbackasm1(SB)
+ MOVV $1685, R12
+ JMP callbackasm1(SB)
+ MOVV $1686, R12
+ JMP callbackasm1(SB)
+ MOVV $1687, R12
+ JMP callbackasm1(SB)
+ MOVV $1688, R12
+ JMP callbackasm1(SB)
+ MOVV $1689, R12
+ JMP callbackasm1(SB)
+ MOVV $1690, R12
+ JMP callbackasm1(SB)
+ MOVV $1691, R12
+ JMP callbackasm1(SB)
+ MOVV $1692, R12
+ JMP callbackasm1(SB)
+ MOVV $1693, R12
+ JMP callbackasm1(SB)
+ MOVV $1694, R12
+ JMP callbackasm1(SB)
+ MOVV $1695, R12
+ JMP callbackasm1(SB)
+ MOVV $1696, R12
+ JMP callbackasm1(SB)
+ MOVV $1697, R12
+ JMP callbackasm1(SB)
+ MOVV $1698, R12
+ JMP callbackasm1(SB)
+ MOVV $1699, R12
+ JMP callbackasm1(SB)
+ MOVV $1700, R12
+ JMP callbackasm1(SB)
+ MOVV $1701, R12
+ JMP callbackasm1(SB)
+ MOVV $1702, R12
+ JMP callbackasm1(SB)
+ MOVV $1703, R12
+ JMP callbackasm1(SB)
+ MOVV $1704, R12
+ JMP callbackasm1(SB)
+ MOVV $1705, R12
+ JMP callbackasm1(SB)
+ MOVV $1706, R12
+ JMP callbackasm1(SB)
+ MOVV $1707, R12
+ JMP callbackasm1(SB)
+ MOVV $1708, R12
+ JMP callbackasm1(SB)
+ MOVV $1709, R12
+ JMP callbackasm1(SB)
+ MOVV $1710, R12
+ JMP callbackasm1(SB)
+ MOVV $1711, R12
+ JMP callbackasm1(SB)
+ MOVV $1712, R12
+ JMP callbackasm1(SB)
+ MOVV $1713, R12
+ JMP callbackasm1(SB)
+ MOVV $1714, R12
+ JMP callbackasm1(SB)
+ MOVV $1715, R12
+ JMP callbackasm1(SB)
+ MOVV $1716, R12
+ JMP callbackasm1(SB)
+ MOVV $1717, R12
+ JMP callbackasm1(SB)
+ MOVV $1718, R12
+ JMP callbackasm1(SB)
+ MOVV $1719, R12
+ JMP callbackasm1(SB)
+ MOVV $1720, R12
+ JMP callbackasm1(SB)
+ MOVV $1721, R12
+ JMP callbackasm1(SB)
+ MOVV $1722, R12
+ JMP callbackasm1(SB)
+ MOVV $1723, R12
+ JMP callbackasm1(SB)
+ MOVV $1724, R12
+ JMP callbackasm1(SB)
+ MOVV $1725, R12
+ JMP callbackasm1(SB)
+ MOVV $1726, R12
+ JMP callbackasm1(SB)
+ MOVV $1727, R12
+ JMP callbackasm1(SB)
+ MOVV $1728, R12
+ JMP callbackasm1(SB)
+ MOVV $1729, R12
+ JMP callbackasm1(SB)
+ MOVV $1730, R12
+ JMP callbackasm1(SB)
+ MOVV $1731, R12
+ JMP callbackasm1(SB)
+ MOVV $1732, R12
+ JMP callbackasm1(SB)
+ MOVV $1733, R12
+ JMP callbackasm1(SB)
+ MOVV $1734, R12
+ JMP callbackasm1(SB)
+ MOVV $1735, R12
+ JMP callbackasm1(SB)
+ MOVV $1736, R12
+ JMP callbackasm1(SB)
+ MOVV $1737, R12
+ JMP callbackasm1(SB)
+ MOVV $1738, R12
+ JMP callbackasm1(SB)
+ MOVV $1739, R12
+ JMP callbackasm1(SB)
+ MOVV $1740, R12
+ JMP callbackasm1(SB)
+ MOVV $1741, R12
+ JMP callbackasm1(SB)
+ MOVV $1742, R12
+ JMP callbackasm1(SB)
+ MOVV $1743, R12
+ JMP callbackasm1(SB)
+ MOVV $1744, R12
+ JMP callbackasm1(SB)
+ MOVV $1745, R12
+ JMP callbackasm1(SB)
+ MOVV $1746, R12
+ JMP callbackasm1(SB)
+ MOVV $1747, R12
+ JMP callbackasm1(SB)
+ MOVV $1748, R12
+ JMP callbackasm1(SB)
+ MOVV $1749, R12
+ JMP callbackasm1(SB)
+ MOVV $1750, R12
+ JMP callbackasm1(SB)
+ MOVV $1751, R12
+ JMP callbackasm1(SB)
+ MOVV $1752, R12
+ JMP callbackasm1(SB)
+ MOVV $1753, R12
+ JMP callbackasm1(SB)
+ MOVV $1754, R12
+ JMP callbackasm1(SB)
+ MOVV $1755, R12
+ JMP callbackasm1(SB)
+ MOVV $1756, R12
+ JMP callbackasm1(SB)
+ MOVV $1757, R12
+ JMP callbackasm1(SB)
+ MOVV $1758, R12
+ JMP callbackasm1(SB)
+ MOVV $1759, R12
+ JMP callbackasm1(SB)
+ MOVV $1760, R12
+ JMP callbackasm1(SB)
+ MOVV $1761, R12
+ JMP callbackasm1(SB)
+ MOVV $1762, R12
+ JMP callbackasm1(SB)
+ MOVV $1763, R12
+ JMP callbackasm1(SB)
+ MOVV $1764, R12
+ JMP callbackasm1(SB)
+ MOVV $1765, R12
+ JMP callbackasm1(SB)
+ MOVV $1766, R12
+ JMP callbackasm1(SB)
+ MOVV $1767, R12
+ JMP callbackasm1(SB)
+ MOVV $1768, R12
+ JMP callbackasm1(SB)
+ MOVV $1769, R12
+ JMP callbackasm1(SB)
+ MOVV $1770, R12
+ JMP callbackasm1(SB)
+ MOVV $1771, R12
+ JMP callbackasm1(SB)
+ MOVV $1772, R12
+ JMP callbackasm1(SB)
+ MOVV $1773, R12
+ JMP callbackasm1(SB)
+ MOVV $1774, R12
+ JMP callbackasm1(SB)
+ MOVV $1775, R12
+ JMP callbackasm1(SB)
+ MOVV $1776, R12
+ JMP callbackasm1(SB)
+ MOVV $1777, R12
+ JMP callbackasm1(SB)
+ MOVV $1778, R12
+ JMP callbackasm1(SB)
+ MOVV $1779, R12
+ JMP callbackasm1(SB)
+ MOVV $1780, R12
+ JMP callbackasm1(SB)
+ MOVV $1781, R12
+ JMP callbackasm1(SB)
+ MOVV $1782, R12
+ JMP callbackasm1(SB)
+ MOVV $1783, R12
+ JMP callbackasm1(SB)
+ MOVV $1784, R12
+ JMP callbackasm1(SB)
+ MOVV $1785, R12
+ JMP callbackasm1(SB)
+ MOVV $1786, R12
+ JMP callbackasm1(SB)
+ MOVV $1787, R12
+ JMP callbackasm1(SB)
+ MOVV $1788, R12
+ JMP callbackasm1(SB)
+ MOVV $1789, R12
+ JMP callbackasm1(SB)
+ MOVV $1790, R12
+ JMP callbackasm1(SB)
+ MOVV $1791, R12
+ JMP callbackasm1(SB)
+ MOVV $1792, R12
+ JMP callbackasm1(SB)
+ MOVV $1793, R12
+ JMP callbackasm1(SB)
+ MOVV $1794, R12
+ JMP callbackasm1(SB)
+ MOVV $1795, R12
+ JMP callbackasm1(SB)
+ MOVV $1796, R12
+ JMP callbackasm1(SB)
+ MOVV $1797, R12
+ JMP callbackasm1(SB)
+ MOVV $1798, R12
+ JMP callbackasm1(SB)
+ MOVV $1799, R12
+ JMP callbackasm1(SB)
+ MOVV $1800, R12
+ JMP callbackasm1(SB)
+ MOVV $1801, R12
+ JMP callbackasm1(SB)
+ MOVV $1802, R12
+ JMP callbackasm1(SB)
+ MOVV $1803, R12
+ JMP callbackasm1(SB)
+ MOVV $1804, R12
+ JMP callbackasm1(SB)
+ MOVV $1805, R12
+ JMP callbackasm1(SB)
+ MOVV $1806, R12
+ JMP callbackasm1(SB)
+ MOVV $1807, R12
+ JMP callbackasm1(SB)
+ MOVV $1808, R12
+ JMP callbackasm1(SB)
+ MOVV $1809, R12
+ JMP callbackasm1(SB)
+ MOVV $1810, R12
+ JMP callbackasm1(SB)
+ MOVV $1811, R12
+ JMP callbackasm1(SB)
+ MOVV $1812, R12
+ JMP callbackasm1(SB)
+ MOVV $1813, R12
+ JMP callbackasm1(SB)
+ MOVV $1814, R12
+ JMP callbackasm1(SB)
+ MOVV $1815, R12
+ JMP callbackasm1(SB)
+ MOVV $1816, R12
+ JMP callbackasm1(SB)
+ MOVV $1817, R12
+ JMP callbackasm1(SB)
+ MOVV $1818, R12
+ JMP callbackasm1(SB)
+ MOVV $1819, R12
+ JMP callbackasm1(SB)
+ MOVV $1820, R12
+ JMP callbackasm1(SB)
+ MOVV $1821, R12
+ JMP callbackasm1(SB)
+ MOVV $1822, R12
+ JMP callbackasm1(SB)
+ MOVV $1823, R12
+ JMP callbackasm1(SB)
+ MOVV $1824, R12
+ JMP callbackasm1(SB)
+ MOVV $1825, R12
+ JMP callbackasm1(SB)
+ MOVV $1826, R12
+ JMP callbackasm1(SB)
+ MOVV $1827, R12
+ JMP callbackasm1(SB)
+ MOVV $1828, R12
+ JMP callbackasm1(SB)
+ MOVV $1829, R12
+ JMP callbackasm1(SB)
+ MOVV $1830, R12
+ JMP callbackasm1(SB)
+ MOVV $1831, R12
+ JMP callbackasm1(SB)
+ MOVV $1832, R12
+ JMP callbackasm1(SB)
+ MOVV $1833, R12
+ JMP callbackasm1(SB)
+ MOVV $1834, R12
+ JMP callbackasm1(SB)
+ MOVV $1835, R12
+ JMP callbackasm1(SB)
+ MOVV $1836, R12
+ JMP callbackasm1(SB)
+ MOVV $1837, R12
+ JMP callbackasm1(SB)
+ MOVV $1838, R12
+ JMP callbackasm1(SB)
+ MOVV $1839, R12
+ JMP callbackasm1(SB)
+ MOVV $1840, R12
+ JMP callbackasm1(SB)
+ MOVV $1841, R12
+ JMP callbackasm1(SB)
+ MOVV $1842, R12
+ JMP callbackasm1(SB)
+ MOVV $1843, R12
+ JMP callbackasm1(SB)
+ MOVV $1844, R12
+ JMP callbackasm1(SB)
+ MOVV $1845, R12
+ JMP callbackasm1(SB)
+ MOVV $1846, R12
+ JMP callbackasm1(SB)
+ MOVV $1847, R12
+ JMP callbackasm1(SB)
+ MOVV $1848, R12
+ JMP callbackasm1(SB)
+ MOVV $1849, R12
+ JMP callbackasm1(SB)
+ MOVV $1850, R12
+ JMP callbackasm1(SB)
+ MOVV $1851, R12
+ JMP callbackasm1(SB)
+ MOVV $1852, R12
+ JMP callbackasm1(SB)
+ MOVV $1853, R12
+ JMP callbackasm1(SB)
+ MOVV $1854, R12
+ JMP callbackasm1(SB)
+ MOVV $1855, R12
+ JMP callbackasm1(SB)
+ MOVV $1856, R12
+ JMP callbackasm1(SB)
+ MOVV $1857, R12
+ JMP callbackasm1(SB)
+ MOVV $1858, R12
+ JMP callbackasm1(SB)
+ MOVV $1859, R12
+ JMP callbackasm1(SB)
+ MOVV $1860, R12
+ JMP callbackasm1(SB)
+ MOVV $1861, R12
+ JMP callbackasm1(SB)
+ MOVV $1862, R12
+ JMP callbackasm1(SB)
+ MOVV $1863, R12
+ JMP callbackasm1(SB)
+ MOVV $1864, R12
+ JMP callbackasm1(SB)
+ MOVV $1865, R12
+ JMP callbackasm1(SB)
+ MOVV $1866, R12
+ JMP callbackasm1(SB)
+ MOVV $1867, R12
+ JMP callbackasm1(SB)
+ MOVV $1868, R12
+ JMP callbackasm1(SB)
+ MOVV $1869, R12
+ JMP callbackasm1(SB)
+ MOVV $1870, R12
+ JMP callbackasm1(SB)
+ MOVV $1871, R12
+ JMP callbackasm1(SB)
+ MOVV $1872, R12
+ JMP callbackasm1(SB)
+ MOVV $1873, R12
+ JMP callbackasm1(SB)
+ MOVV $1874, R12
+ JMP callbackasm1(SB)
+ MOVV $1875, R12
+ JMP callbackasm1(SB)
+ MOVV $1876, R12
+ JMP callbackasm1(SB)
+ MOVV $1877, R12
+ JMP callbackasm1(SB)
+ MOVV $1878, R12
+ JMP callbackasm1(SB)
+ MOVV $1879, R12
+ JMP callbackasm1(SB)
+ MOVV $1880, R12
+ JMP callbackasm1(SB)
+ MOVV $1881, R12
+ JMP callbackasm1(SB)
+ MOVV $1882, R12
+ JMP callbackasm1(SB)
+ MOVV $1883, R12
+ JMP callbackasm1(SB)
+ MOVV $1884, R12
+ JMP callbackasm1(SB)
+ MOVV $1885, R12
+ JMP callbackasm1(SB)
+ MOVV $1886, R12
+ JMP callbackasm1(SB)
+ MOVV $1887, R12
+ JMP callbackasm1(SB)
+ MOVV $1888, R12
+ JMP callbackasm1(SB)
+ MOVV $1889, R12
+ JMP callbackasm1(SB)
+ MOVV $1890, R12
+ JMP callbackasm1(SB)
+ MOVV $1891, R12
+ JMP callbackasm1(SB)
+ MOVV $1892, R12
+ JMP callbackasm1(SB)
+ MOVV $1893, R12
+ JMP callbackasm1(SB)
+ MOVV $1894, R12
+ JMP callbackasm1(SB)
+ MOVV $1895, R12
+ JMP callbackasm1(SB)
+ MOVV $1896, R12
+ JMP callbackasm1(SB)
+ MOVV $1897, R12
+ JMP callbackasm1(SB)
+ MOVV $1898, R12
+ JMP callbackasm1(SB)
+ MOVV $1899, R12
+ JMP callbackasm1(SB)
+ MOVV $1900, R12
+ JMP callbackasm1(SB)
+ MOVV $1901, R12
+ JMP callbackasm1(SB)
+ MOVV $1902, R12
+ JMP callbackasm1(SB)
+ MOVV $1903, R12
+ JMP callbackasm1(SB)
+ MOVV $1904, R12
+ JMP callbackasm1(SB)
+ MOVV $1905, R12
+ JMP callbackasm1(SB)
+ MOVV $1906, R12
+ JMP callbackasm1(SB)
+ MOVV $1907, R12
+ JMP callbackasm1(SB)
+ MOVV $1908, R12
+ JMP callbackasm1(SB)
+ MOVV $1909, R12
+ JMP callbackasm1(SB)
+ MOVV $1910, R12
+ JMP callbackasm1(SB)
+ MOVV $1911, R12
+ JMP callbackasm1(SB)
+ MOVV $1912, R12
+ JMP callbackasm1(SB)
+ MOVV $1913, R12
+ JMP callbackasm1(SB)
+ MOVV $1914, R12
+ JMP callbackasm1(SB)
+ MOVV $1915, R12
+ JMP callbackasm1(SB)
+ MOVV $1916, R12
+ JMP callbackasm1(SB)
+ MOVV $1917, R12
+ JMP callbackasm1(SB)
+ MOVV $1918, R12
+ JMP callbackasm1(SB)
+ MOVV $1919, R12
+ JMP callbackasm1(SB)
+ MOVV $1920, R12
+ JMP callbackasm1(SB)
+ MOVV $1921, R12
+ JMP callbackasm1(SB)
+ MOVV $1922, R12
+ JMP callbackasm1(SB)
+ MOVV $1923, R12
+ JMP callbackasm1(SB)
+ MOVV $1924, R12
+ JMP callbackasm1(SB)
+ MOVV $1925, R12
+ JMP callbackasm1(SB)
+ MOVV $1926, R12
+ JMP callbackasm1(SB)
+ MOVV $1927, R12
+ JMP callbackasm1(SB)
+ MOVV $1928, R12
+ JMP callbackasm1(SB)
+ MOVV $1929, R12
+ JMP callbackasm1(SB)
+ MOVV $1930, R12
+ JMP callbackasm1(SB)
+ MOVV $1931, R12
+ JMP callbackasm1(SB)
+ MOVV $1932, R12
+ JMP callbackasm1(SB)
+ MOVV $1933, R12
+ JMP callbackasm1(SB)
+ MOVV $1934, R12
+ JMP callbackasm1(SB)
+ MOVV $1935, R12
+ JMP callbackasm1(SB)
+ MOVV $1936, R12
+ JMP callbackasm1(SB)
+ MOVV $1937, R12
+ JMP callbackasm1(SB)
+ MOVV $1938, R12
+ JMP callbackasm1(SB)
+ MOVV $1939, R12
+ JMP callbackasm1(SB)
+ MOVV $1940, R12
+ JMP callbackasm1(SB)
+ MOVV $1941, R12
+ JMP callbackasm1(SB)
+ MOVV $1942, R12
+ JMP callbackasm1(SB)
+ MOVV $1943, R12
+ JMP callbackasm1(SB)
+ MOVV $1944, R12
+ JMP callbackasm1(SB)
+ MOVV $1945, R12
+ JMP callbackasm1(SB)
+ MOVV $1946, R12
+ JMP callbackasm1(SB)
+ MOVV $1947, R12
+ JMP callbackasm1(SB)
+ MOVV $1948, R12
+ JMP callbackasm1(SB)
+ MOVV $1949, R12
+ JMP callbackasm1(SB)
+ MOVV $1950, R12
+ JMP callbackasm1(SB)
+ MOVV $1951, R12
+ JMP callbackasm1(SB)
+ MOVV $1952, R12
+ JMP callbackasm1(SB)
+ MOVV $1953, R12
+ JMP callbackasm1(SB)
+ MOVV $1954, R12
+ JMP callbackasm1(SB)
+ MOVV $1955, R12
+ JMP callbackasm1(SB)
+ MOVV $1956, R12
+ JMP callbackasm1(SB)
+ MOVV $1957, R12
+ JMP callbackasm1(SB)
+ MOVV $1958, R12
+ JMP callbackasm1(SB)
+ MOVV $1959, R12
+ JMP callbackasm1(SB)
+ MOVV $1960, R12
+ JMP callbackasm1(SB)
+ MOVV $1961, R12
+ JMP callbackasm1(SB)
+ MOVV $1962, R12
+ JMP callbackasm1(SB)
+ MOVV $1963, R12
+ JMP callbackasm1(SB)
+ MOVV $1964, R12
+ JMP callbackasm1(SB)
+ MOVV $1965, R12
+ JMP callbackasm1(SB)
+ MOVV $1966, R12
+ JMP callbackasm1(SB)
+ MOVV $1967, R12
+ JMP callbackasm1(SB)
+ MOVV $1968, R12
+ JMP callbackasm1(SB)
+ MOVV $1969, R12
+ JMP callbackasm1(SB)
+ MOVV $1970, R12
+ JMP callbackasm1(SB)
+ MOVV $1971, R12
+ JMP callbackasm1(SB)
+ MOVV $1972, R12
+ JMP callbackasm1(SB)
+ MOVV $1973, R12
+ JMP callbackasm1(SB)
+ MOVV $1974, R12
+ JMP callbackasm1(SB)
+ MOVV $1975, R12
+ JMP callbackasm1(SB)
+ MOVV $1976, R12
+ JMP callbackasm1(SB)
+ MOVV $1977, R12
+ JMP callbackasm1(SB)
+ MOVV $1978, R12
+ JMP callbackasm1(SB)
+ MOVV $1979, R12
+ JMP callbackasm1(SB)
+ MOVV $1980, R12
+ JMP callbackasm1(SB)
+ MOVV $1981, R12
+ JMP callbackasm1(SB)
+ MOVV $1982, R12
+ JMP callbackasm1(SB)
+ MOVV $1983, R12
+ JMP callbackasm1(SB)
+ MOVV $1984, R12
+ JMP callbackasm1(SB)
+ MOVV $1985, R12
+ JMP callbackasm1(SB)
+ MOVV $1986, R12
+ JMP callbackasm1(SB)
+ MOVV $1987, R12
+ JMP callbackasm1(SB)
+ MOVV $1988, R12
+ JMP callbackasm1(SB)
+ MOVV $1989, R12
+ JMP callbackasm1(SB)
+ MOVV $1990, R12
+ JMP callbackasm1(SB)
+ MOVV $1991, R12
+ JMP callbackasm1(SB)
+ MOVV $1992, R12
+ JMP callbackasm1(SB)
+ MOVV $1993, R12
+ JMP callbackasm1(SB)
+ MOVV $1994, R12
+ JMP callbackasm1(SB)
+ MOVV $1995, R12
+ JMP callbackasm1(SB)
+ MOVV $1996, R12
+ JMP callbackasm1(SB)
+ MOVV $1997, R12
+ JMP callbackasm1(SB)
+ MOVV $1998, R12
+ JMP callbackasm1(SB)
+ MOVV $1999, R12
+ JMP callbackasm1(SB)
diff --git a/raymenu/vendor/github.com/ebitengine/purego/zcallback_ppc64le.s b/raymenu/vendor/github.com/ebitengine/purego/zcallback_ppc64le.s
new file mode 100644
index 0000000..702243b
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/zcallback_ppc64le.s
@@ -0,0 +1,4014 @@
+// Code generated by wincallback.go using 'go generate'. DO NOT EDIT.
+
+//go:build linux
+
+// External code calls into callbackasm at an offset corresponding
+// to the callback index. Callbackasm is a table of MOVD and BR instructions.
+// The MOVD instruction loads R11 with the callback index, and the
+// BR instruction branches to callbackasm1.
+// callbackasm1 takes the callback index from R11 and
+// indexes into an array that stores information about each callback.
+// It then calls the Go implementation for that callback.
+#include "textflag.h"
+
+TEXT callbackasm(SB), NOSPLIT|NOFRAME, $0
+ MOVD $0, R11
+ BR callbackasm1(SB)
+ MOVD $1, R11
+ BR callbackasm1(SB)
+ MOVD $2, R11
+ BR callbackasm1(SB)
+ MOVD $3, R11
+ BR callbackasm1(SB)
+ MOVD $4, R11
+ BR callbackasm1(SB)
+ MOVD $5, R11
+ BR callbackasm1(SB)
+ MOVD $6, R11
+ BR callbackasm1(SB)
+ MOVD $7, R11
+ BR callbackasm1(SB)
+ MOVD $8, R11
+ BR callbackasm1(SB)
+ MOVD $9, R11
+ BR callbackasm1(SB)
+ MOVD $10, R11
+ BR callbackasm1(SB)
+ MOVD $11, R11
+ BR callbackasm1(SB)
+ MOVD $12, R11
+ BR callbackasm1(SB)
+ MOVD $13, R11
+ BR callbackasm1(SB)
+ MOVD $14, R11
+ BR callbackasm1(SB)
+ MOVD $15, R11
+ BR callbackasm1(SB)
+ MOVD $16, R11
+ BR callbackasm1(SB)
+ MOVD $17, R11
+ BR callbackasm1(SB)
+ MOVD $18, R11
+ BR callbackasm1(SB)
+ MOVD $19, R11
+ BR callbackasm1(SB)
+ MOVD $20, R11
+ BR callbackasm1(SB)
+ MOVD $21, R11
+ BR callbackasm1(SB)
+ MOVD $22, R11
+ BR callbackasm1(SB)
+ MOVD $23, R11
+ BR callbackasm1(SB)
+ MOVD $24, R11
+ BR callbackasm1(SB)
+ MOVD $25, R11
+ BR callbackasm1(SB)
+ MOVD $26, R11
+ BR callbackasm1(SB)
+ MOVD $27, R11
+ BR callbackasm1(SB)
+ MOVD $28, R11
+ BR callbackasm1(SB)
+ MOVD $29, R11
+ BR callbackasm1(SB)
+ MOVD $30, R11
+ BR callbackasm1(SB)
+ MOVD $31, R11
+ BR callbackasm1(SB)
+ MOVD $32, R11
+ BR callbackasm1(SB)
+ MOVD $33, R11
+ BR callbackasm1(SB)
+ MOVD $34, R11
+ BR callbackasm1(SB)
+ MOVD $35, R11
+ BR callbackasm1(SB)
+ MOVD $36, R11
+ BR callbackasm1(SB)
+ MOVD $37, R11
+ BR callbackasm1(SB)
+ MOVD $38, R11
+ BR callbackasm1(SB)
+ MOVD $39, R11
+ BR callbackasm1(SB)
+ MOVD $40, R11
+ BR callbackasm1(SB)
+ MOVD $41, R11
+ BR callbackasm1(SB)
+ MOVD $42, R11
+ BR callbackasm1(SB)
+ MOVD $43, R11
+ BR callbackasm1(SB)
+ MOVD $44, R11
+ BR callbackasm1(SB)
+ MOVD $45, R11
+ BR callbackasm1(SB)
+ MOVD $46, R11
+ BR callbackasm1(SB)
+ MOVD $47, R11
+ BR callbackasm1(SB)
+ MOVD $48, R11
+ BR callbackasm1(SB)
+ MOVD $49, R11
+ BR callbackasm1(SB)
+ MOVD $50, R11
+ BR callbackasm1(SB)
+ MOVD $51, R11
+ BR callbackasm1(SB)
+ MOVD $52, R11
+ BR callbackasm1(SB)
+ MOVD $53, R11
+ BR callbackasm1(SB)
+ MOVD $54, R11
+ BR callbackasm1(SB)
+ MOVD $55, R11
+ BR callbackasm1(SB)
+ MOVD $56, R11
+ BR callbackasm1(SB)
+ MOVD $57, R11
+ BR callbackasm1(SB)
+ MOVD $58, R11
+ BR callbackasm1(SB)
+ MOVD $59, R11
+ BR callbackasm1(SB)
+ MOVD $60, R11
+ BR callbackasm1(SB)
+ MOVD $61, R11
+ BR callbackasm1(SB)
+ MOVD $62, R11
+ BR callbackasm1(SB)
+ MOVD $63, R11
+ BR callbackasm1(SB)
+ MOVD $64, R11
+ BR callbackasm1(SB)
+ MOVD $65, R11
+ BR callbackasm1(SB)
+ MOVD $66, R11
+ BR callbackasm1(SB)
+ MOVD $67, R11
+ BR callbackasm1(SB)
+ MOVD $68, R11
+ BR callbackasm1(SB)
+ MOVD $69, R11
+ BR callbackasm1(SB)
+ MOVD $70, R11
+ BR callbackasm1(SB)
+ MOVD $71, R11
+ BR callbackasm1(SB)
+ MOVD $72, R11
+ BR callbackasm1(SB)
+ MOVD $73, R11
+ BR callbackasm1(SB)
+ MOVD $74, R11
+ BR callbackasm1(SB)
+ MOVD $75, R11
+ BR callbackasm1(SB)
+ MOVD $76, R11
+ BR callbackasm1(SB)
+ MOVD $77, R11
+ BR callbackasm1(SB)
+ MOVD $78, R11
+ BR callbackasm1(SB)
+ MOVD $79, R11
+ BR callbackasm1(SB)
+ MOVD $80, R11
+ BR callbackasm1(SB)
+ MOVD $81, R11
+ BR callbackasm1(SB)
+ MOVD $82, R11
+ BR callbackasm1(SB)
+ MOVD $83, R11
+ BR callbackasm1(SB)
+ MOVD $84, R11
+ BR callbackasm1(SB)
+ MOVD $85, R11
+ BR callbackasm1(SB)
+ MOVD $86, R11
+ BR callbackasm1(SB)
+ MOVD $87, R11
+ BR callbackasm1(SB)
+ MOVD $88, R11
+ BR callbackasm1(SB)
+ MOVD $89, R11
+ BR callbackasm1(SB)
+ MOVD $90, R11
+ BR callbackasm1(SB)
+ MOVD $91, R11
+ BR callbackasm1(SB)
+ MOVD $92, R11
+ BR callbackasm1(SB)
+ MOVD $93, R11
+ BR callbackasm1(SB)
+ MOVD $94, R11
+ BR callbackasm1(SB)
+ MOVD $95, R11
+ BR callbackasm1(SB)
+ MOVD $96, R11
+ BR callbackasm1(SB)
+ MOVD $97, R11
+ BR callbackasm1(SB)
+ MOVD $98, R11
+ BR callbackasm1(SB)
+ MOVD $99, R11
+ BR callbackasm1(SB)
+ MOVD $100, R11
+ BR callbackasm1(SB)
+ MOVD $101, R11
+ BR callbackasm1(SB)
+ MOVD $102, R11
+ BR callbackasm1(SB)
+ MOVD $103, R11
+ BR callbackasm1(SB)
+ MOVD $104, R11
+ BR callbackasm1(SB)
+ MOVD $105, R11
+ BR callbackasm1(SB)
+ MOVD $106, R11
+ BR callbackasm1(SB)
+ MOVD $107, R11
+ BR callbackasm1(SB)
+ MOVD $108, R11
+ BR callbackasm1(SB)
+ MOVD $109, R11
+ BR callbackasm1(SB)
+ MOVD $110, R11
+ BR callbackasm1(SB)
+ MOVD $111, R11
+ BR callbackasm1(SB)
+ MOVD $112, R11
+ BR callbackasm1(SB)
+ MOVD $113, R11
+ BR callbackasm1(SB)
+ MOVD $114, R11
+ BR callbackasm1(SB)
+ MOVD $115, R11
+ BR callbackasm1(SB)
+ MOVD $116, R11
+ BR callbackasm1(SB)
+ MOVD $117, R11
+ BR callbackasm1(SB)
+ MOVD $118, R11
+ BR callbackasm1(SB)
+ MOVD $119, R11
+ BR callbackasm1(SB)
+ MOVD $120, R11
+ BR callbackasm1(SB)
+ MOVD $121, R11
+ BR callbackasm1(SB)
+ MOVD $122, R11
+ BR callbackasm1(SB)
+ MOVD $123, R11
+ BR callbackasm1(SB)
+ MOVD $124, R11
+ BR callbackasm1(SB)
+ MOVD $125, R11
+ BR callbackasm1(SB)
+ MOVD $126, R11
+ BR callbackasm1(SB)
+ MOVD $127, R11
+ BR callbackasm1(SB)
+ MOVD $128, R11
+ BR callbackasm1(SB)
+ MOVD $129, R11
+ BR callbackasm1(SB)
+ MOVD $130, R11
+ BR callbackasm1(SB)
+ MOVD $131, R11
+ BR callbackasm1(SB)
+ MOVD $132, R11
+ BR callbackasm1(SB)
+ MOVD $133, R11
+ BR callbackasm1(SB)
+ MOVD $134, R11
+ BR callbackasm1(SB)
+ MOVD $135, R11
+ BR callbackasm1(SB)
+ MOVD $136, R11
+ BR callbackasm1(SB)
+ MOVD $137, R11
+ BR callbackasm1(SB)
+ MOVD $138, R11
+ BR callbackasm1(SB)
+ MOVD $139, R11
+ BR callbackasm1(SB)
+ MOVD $140, R11
+ BR callbackasm1(SB)
+ MOVD $141, R11
+ BR callbackasm1(SB)
+ MOVD $142, R11
+ BR callbackasm1(SB)
+ MOVD $143, R11
+ BR callbackasm1(SB)
+ MOVD $144, R11
+ BR callbackasm1(SB)
+ MOVD $145, R11
+ BR callbackasm1(SB)
+ MOVD $146, R11
+ BR callbackasm1(SB)
+ MOVD $147, R11
+ BR callbackasm1(SB)
+ MOVD $148, R11
+ BR callbackasm1(SB)
+ MOVD $149, R11
+ BR callbackasm1(SB)
+ MOVD $150, R11
+ BR callbackasm1(SB)
+ MOVD $151, R11
+ BR callbackasm1(SB)
+ MOVD $152, R11
+ BR callbackasm1(SB)
+ MOVD $153, R11
+ BR callbackasm1(SB)
+ MOVD $154, R11
+ BR callbackasm1(SB)
+ MOVD $155, R11
+ BR callbackasm1(SB)
+ MOVD $156, R11
+ BR callbackasm1(SB)
+ MOVD $157, R11
+ BR callbackasm1(SB)
+ MOVD $158, R11
+ BR callbackasm1(SB)
+ MOVD $159, R11
+ BR callbackasm1(SB)
+ MOVD $160, R11
+ BR callbackasm1(SB)
+ MOVD $161, R11
+ BR callbackasm1(SB)
+ MOVD $162, R11
+ BR callbackasm1(SB)
+ MOVD $163, R11
+ BR callbackasm1(SB)
+ MOVD $164, R11
+ BR callbackasm1(SB)
+ MOVD $165, R11
+ BR callbackasm1(SB)
+ MOVD $166, R11
+ BR callbackasm1(SB)
+ MOVD $167, R11
+ BR callbackasm1(SB)
+ MOVD $168, R11
+ BR callbackasm1(SB)
+ MOVD $169, R11
+ BR callbackasm1(SB)
+ MOVD $170, R11
+ BR callbackasm1(SB)
+ MOVD $171, R11
+ BR callbackasm1(SB)
+ MOVD $172, R11
+ BR callbackasm1(SB)
+ MOVD $173, R11
+ BR callbackasm1(SB)
+ MOVD $174, R11
+ BR callbackasm1(SB)
+ MOVD $175, R11
+ BR callbackasm1(SB)
+ MOVD $176, R11
+ BR callbackasm1(SB)
+ MOVD $177, R11
+ BR callbackasm1(SB)
+ MOVD $178, R11
+ BR callbackasm1(SB)
+ MOVD $179, R11
+ BR callbackasm1(SB)
+ MOVD $180, R11
+ BR callbackasm1(SB)
+ MOVD $181, R11
+ BR callbackasm1(SB)
+ MOVD $182, R11
+ BR callbackasm1(SB)
+ MOVD $183, R11
+ BR callbackasm1(SB)
+ MOVD $184, R11
+ BR callbackasm1(SB)
+ MOVD $185, R11
+ BR callbackasm1(SB)
+ MOVD $186, R11
+ BR callbackasm1(SB)
+ MOVD $187, R11
+ BR callbackasm1(SB)
+ MOVD $188, R11
+ BR callbackasm1(SB)
+ MOVD $189, R11
+ BR callbackasm1(SB)
+ MOVD $190, R11
+ BR callbackasm1(SB)
+ MOVD $191, R11
+ BR callbackasm1(SB)
+ MOVD $192, R11
+ BR callbackasm1(SB)
+ MOVD $193, R11
+ BR callbackasm1(SB)
+ MOVD $194, R11
+ BR callbackasm1(SB)
+ MOVD $195, R11
+ BR callbackasm1(SB)
+ MOVD $196, R11
+ BR callbackasm1(SB)
+ MOVD $197, R11
+ BR callbackasm1(SB)
+ MOVD $198, R11
+ BR callbackasm1(SB)
+ MOVD $199, R11
+ BR callbackasm1(SB)
+ MOVD $200, R11
+ BR callbackasm1(SB)
+ MOVD $201, R11
+ BR callbackasm1(SB)
+ MOVD $202, R11
+ BR callbackasm1(SB)
+ MOVD $203, R11
+ BR callbackasm1(SB)
+ MOVD $204, R11
+ BR callbackasm1(SB)
+ MOVD $205, R11
+ BR callbackasm1(SB)
+ MOVD $206, R11
+ BR callbackasm1(SB)
+ MOVD $207, R11
+ BR callbackasm1(SB)
+ MOVD $208, R11
+ BR callbackasm1(SB)
+ MOVD $209, R11
+ BR callbackasm1(SB)
+ MOVD $210, R11
+ BR callbackasm1(SB)
+ MOVD $211, R11
+ BR callbackasm1(SB)
+ MOVD $212, R11
+ BR callbackasm1(SB)
+ MOVD $213, R11
+ BR callbackasm1(SB)
+ MOVD $214, R11
+ BR callbackasm1(SB)
+ MOVD $215, R11
+ BR callbackasm1(SB)
+ MOVD $216, R11
+ BR callbackasm1(SB)
+ MOVD $217, R11
+ BR callbackasm1(SB)
+ MOVD $218, R11
+ BR callbackasm1(SB)
+ MOVD $219, R11
+ BR callbackasm1(SB)
+ MOVD $220, R11
+ BR callbackasm1(SB)
+ MOVD $221, R11
+ BR callbackasm1(SB)
+ MOVD $222, R11
+ BR callbackasm1(SB)
+ MOVD $223, R11
+ BR callbackasm1(SB)
+ MOVD $224, R11
+ BR callbackasm1(SB)
+ MOVD $225, R11
+ BR callbackasm1(SB)
+ MOVD $226, R11
+ BR callbackasm1(SB)
+ MOVD $227, R11
+ BR callbackasm1(SB)
+ MOVD $228, R11
+ BR callbackasm1(SB)
+ MOVD $229, R11
+ BR callbackasm1(SB)
+ MOVD $230, R11
+ BR callbackasm1(SB)
+ MOVD $231, R11
+ BR callbackasm1(SB)
+ MOVD $232, R11
+ BR callbackasm1(SB)
+ MOVD $233, R11
+ BR callbackasm1(SB)
+ MOVD $234, R11
+ BR callbackasm1(SB)
+ MOVD $235, R11
+ BR callbackasm1(SB)
+ MOVD $236, R11
+ BR callbackasm1(SB)
+ MOVD $237, R11
+ BR callbackasm1(SB)
+ MOVD $238, R11
+ BR callbackasm1(SB)
+ MOVD $239, R11
+ BR callbackasm1(SB)
+ MOVD $240, R11
+ BR callbackasm1(SB)
+ MOVD $241, R11
+ BR callbackasm1(SB)
+ MOVD $242, R11
+ BR callbackasm1(SB)
+ MOVD $243, R11
+ BR callbackasm1(SB)
+ MOVD $244, R11
+ BR callbackasm1(SB)
+ MOVD $245, R11
+ BR callbackasm1(SB)
+ MOVD $246, R11
+ BR callbackasm1(SB)
+ MOVD $247, R11
+ BR callbackasm1(SB)
+ MOVD $248, R11
+ BR callbackasm1(SB)
+ MOVD $249, R11
+ BR callbackasm1(SB)
+ MOVD $250, R11
+ BR callbackasm1(SB)
+ MOVD $251, R11
+ BR callbackasm1(SB)
+ MOVD $252, R11
+ BR callbackasm1(SB)
+ MOVD $253, R11
+ BR callbackasm1(SB)
+ MOVD $254, R11
+ BR callbackasm1(SB)
+ MOVD $255, R11
+ BR callbackasm1(SB)
+ MOVD $256, R11
+ BR callbackasm1(SB)
+ MOVD $257, R11
+ BR callbackasm1(SB)
+ MOVD $258, R11
+ BR callbackasm1(SB)
+ MOVD $259, R11
+ BR callbackasm1(SB)
+ MOVD $260, R11
+ BR callbackasm1(SB)
+ MOVD $261, R11
+ BR callbackasm1(SB)
+ MOVD $262, R11
+ BR callbackasm1(SB)
+ MOVD $263, R11
+ BR callbackasm1(SB)
+ MOVD $264, R11
+ BR callbackasm1(SB)
+ MOVD $265, R11
+ BR callbackasm1(SB)
+ MOVD $266, R11
+ BR callbackasm1(SB)
+ MOVD $267, R11
+ BR callbackasm1(SB)
+ MOVD $268, R11
+ BR callbackasm1(SB)
+ MOVD $269, R11
+ BR callbackasm1(SB)
+ MOVD $270, R11
+ BR callbackasm1(SB)
+ MOVD $271, R11
+ BR callbackasm1(SB)
+ MOVD $272, R11
+ BR callbackasm1(SB)
+ MOVD $273, R11
+ BR callbackasm1(SB)
+ MOVD $274, R11
+ BR callbackasm1(SB)
+ MOVD $275, R11
+ BR callbackasm1(SB)
+ MOVD $276, R11
+ BR callbackasm1(SB)
+ MOVD $277, R11
+ BR callbackasm1(SB)
+ MOVD $278, R11
+ BR callbackasm1(SB)
+ MOVD $279, R11
+ BR callbackasm1(SB)
+ MOVD $280, R11
+ BR callbackasm1(SB)
+ MOVD $281, R11
+ BR callbackasm1(SB)
+ MOVD $282, R11
+ BR callbackasm1(SB)
+ MOVD $283, R11
+ BR callbackasm1(SB)
+ MOVD $284, R11
+ BR callbackasm1(SB)
+ MOVD $285, R11
+ BR callbackasm1(SB)
+ MOVD $286, R11
+ BR callbackasm1(SB)
+ MOVD $287, R11
+ BR callbackasm1(SB)
+ MOVD $288, R11
+ BR callbackasm1(SB)
+ MOVD $289, R11
+ BR callbackasm1(SB)
+ MOVD $290, R11
+ BR callbackasm1(SB)
+ MOVD $291, R11
+ BR callbackasm1(SB)
+ MOVD $292, R11
+ BR callbackasm1(SB)
+ MOVD $293, R11
+ BR callbackasm1(SB)
+ MOVD $294, R11
+ BR callbackasm1(SB)
+ MOVD $295, R11
+ BR callbackasm1(SB)
+ MOVD $296, R11
+ BR callbackasm1(SB)
+ MOVD $297, R11
+ BR callbackasm1(SB)
+ MOVD $298, R11
+ BR callbackasm1(SB)
+ MOVD $299, R11
+ BR callbackasm1(SB)
+ MOVD $300, R11
+ BR callbackasm1(SB)
+ MOVD $301, R11
+ BR callbackasm1(SB)
+ MOVD $302, R11
+ BR callbackasm1(SB)
+ MOVD $303, R11
+ BR callbackasm1(SB)
+ MOVD $304, R11
+ BR callbackasm1(SB)
+ MOVD $305, R11
+ BR callbackasm1(SB)
+ MOVD $306, R11
+ BR callbackasm1(SB)
+ MOVD $307, R11
+ BR callbackasm1(SB)
+ MOVD $308, R11
+ BR callbackasm1(SB)
+ MOVD $309, R11
+ BR callbackasm1(SB)
+ MOVD $310, R11
+ BR callbackasm1(SB)
+ MOVD $311, R11
+ BR callbackasm1(SB)
+ MOVD $312, R11
+ BR callbackasm1(SB)
+ MOVD $313, R11
+ BR callbackasm1(SB)
+ MOVD $314, R11
+ BR callbackasm1(SB)
+ MOVD $315, R11
+ BR callbackasm1(SB)
+ MOVD $316, R11
+ BR callbackasm1(SB)
+ MOVD $317, R11
+ BR callbackasm1(SB)
+ MOVD $318, R11
+ BR callbackasm1(SB)
+ MOVD $319, R11
+ BR callbackasm1(SB)
+ MOVD $320, R11
+ BR callbackasm1(SB)
+ MOVD $321, R11
+ BR callbackasm1(SB)
+ MOVD $322, R11
+ BR callbackasm1(SB)
+ MOVD $323, R11
+ BR callbackasm1(SB)
+ MOVD $324, R11
+ BR callbackasm1(SB)
+ MOVD $325, R11
+ BR callbackasm1(SB)
+ MOVD $326, R11
+ BR callbackasm1(SB)
+ MOVD $327, R11
+ BR callbackasm1(SB)
+ MOVD $328, R11
+ BR callbackasm1(SB)
+ MOVD $329, R11
+ BR callbackasm1(SB)
+ MOVD $330, R11
+ BR callbackasm1(SB)
+ MOVD $331, R11
+ BR callbackasm1(SB)
+ MOVD $332, R11
+ BR callbackasm1(SB)
+ MOVD $333, R11
+ BR callbackasm1(SB)
+ MOVD $334, R11
+ BR callbackasm1(SB)
+ MOVD $335, R11
+ BR callbackasm1(SB)
+ MOVD $336, R11
+ BR callbackasm1(SB)
+ MOVD $337, R11
+ BR callbackasm1(SB)
+ MOVD $338, R11
+ BR callbackasm1(SB)
+ MOVD $339, R11
+ BR callbackasm1(SB)
+ MOVD $340, R11
+ BR callbackasm1(SB)
+ MOVD $341, R11
+ BR callbackasm1(SB)
+ MOVD $342, R11
+ BR callbackasm1(SB)
+ MOVD $343, R11
+ BR callbackasm1(SB)
+ MOVD $344, R11
+ BR callbackasm1(SB)
+ MOVD $345, R11
+ BR callbackasm1(SB)
+ MOVD $346, R11
+ BR callbackasm1(SB)
+ MOVD $347, R11
+ BR callbackasm1(SB)
+ MOVD $348, R11
+ BR callbackasm1(SB)
+ MOVD $349, R11
+ BR callbackasm1(SB)
+ MOVD $350, R11
+ BR callbackasm1(SB)
+ MOVD $351, R11
+ BR callbackasm1(SB)
+ MOVD $352, R11
+ BR callbackasm1(SB)
+ MOVD $353, R11
+ BR callbackasm1(SB)
+ MOVD $354, R11
+ BR callbackasm1(SB)
+ MOVD $355, R11
+ BR callbackasm1(SB)
+ MOVD $356, R11
+ BR callbackasm1(SB)
+ MOVD $357, R11
+ BR callbackasm1(SB)
+ MOVD $358, R11
+ BR callbackasm1(SB)
+ MOVD $359, R11
+ BR callbackasm1(SB)
+ MOVD $360, R11
+ BR callbackasm1(SB)
+ MOVD $361, R11
+ BR callbackasm1(SB)
+ MOVD $362, R11
+ BR callbackasm1(SB)
+ MOVD $363, R11
+ BR callbackasm1(SB)
+ MOVD $364, R11
+ BR callbackasm1(SB)
+ MOVD $365, R11
+ BR callbackasm1(SB)
+ MOVD $366, R11
+ BR callbackasm1(SB)
+ MOVD $367, R11
+ BR callbackasm1(SB)
+ MOVD $368, R11
+ BR callbackasm1(SB)
+ MOVD $369, R11
+ BR callbackasm1(SB)
+ MOVD $370, R11
+ BR callbackasm1(SB)
+ MOVD $371, R11
+ BR callbackasm1(SB)
+ MOVD $372, R11
+ BR callbackasm1(SB)
+ MOVD $373, R11
+ BR callbackasm1(SB)
+ MOVD $374, R11
+ BR callbackasm1(SB)
+ MOVD $375, R11
+ BR callbackasm1(SB)
+ MOVD $376, R11
+ BR callbackasm1(SB)
+ MOVD $377, R11
+ BR callbackasm1(SB)
+ MOVD $378, R11
+ BR callbackasm1(SB)
+ MOVD $379, R11
+ BR callbackasm1(SB)
+ MOVD $380, R11
+ BR callbackasm1(SB)
+ MOVD $381, R11
+ BR callbackasm1(SB)
+ MOVD $382, R11
+ BR callbackasm1(SB)
+ MOVD $383, R11
+ BR callbackasm1(SB)
+ MOVD $384, R11
+ BR callbackasm1(SB)
+ MOVD $385, R11
+ BR callbackasm1(SB)
+ MOVD $386, R11
+ BR callbackasm1(SB)
+ MOVD $387, R11
+ BR callbackasm1(SB)
+ MOVD $388, R11
+ BR callbackasm1(SB)
+ MOVD $389, R11
+ BR callbackasm1(SB)
+ MOVD $390, R11
+ BR callbackasm1(SB)
+ MOVD $391, R11
+ BR callbackasm1(SB)
+ MOVD $392, R11
+ BR callbackasm1(SB)
+ MOVD $393, R11
+ BR callbackasm1(SB)
+ MOVD $394, R11
+ BR callbackasm1(SB)
+ MOVD $395, R11
+ BR callbackasm1(SB)
+ MOVD $396, R11
+ BR callbackasm1(SB)
+ MOVD $397, R11
+ BR callbackasm1(SB)
+ MOVD $398, R11
+ BR callbackasm1(SB)
+ MOVD $399, R11
+ BR callbackasm1(SB)
+ MOVD $400, R11
+ BR callbackasm1(SB)
+ MOVD $401, R11
+ BR callbackasm1(SB)
+ MOVD $402, R11
+ BR callbackasm1(SB)
+ MOVD $403, R11
+ BR callbackasm1(SB)
+ MOVD $404, R11
+ BR callbackasm1(SB)
+ MOVD $405, R11
+ BR callbackasm1(SB)
+ MOVD $406, R11
+ BR callbackasm1(SB)
+ MOVD $407, R11
+ BR callbackasm1(SB)
+ MOVD $408, R11
+ BR callbackasm1(SB)
+ MOVD $409, R11
+ BR callbackasm1(SB)
+ MOVD $410, R11
+ BR callbackasm1(SB)
+ MOVD $411, R11
+ BR callbackasm1(SB)
+ MOVD $412, R11
+ BR callbackasm1(SB)
+ MOVD $413, R11
+ BR callbackasm1(SB)
+ MOVD $414, R11
+ BR callbackasm1(SB)
+ MOVD $415, R11
+ BR callbackasm1(SB)
+ MOVD $416, R11
+ BR callbackasm1(SB)
+ MOVD $417, R11
+ BR callbackasm1(SB)
+ MOVD $418, R11
+ BR callbackasm1(SB)
+ MOVD $419, R11
+ BR callbackasm1(SB)
+ MOVD $420, R11
+ BR callbackasm1(SB)
+ MOVD $421, R11
+ BR callbackasm1(SB)
+ MOVD $422, R11
+ BR callbackasm1(SB)
+ MOVD $423, R11
+ BR callbackasm1(SB)
+ MOVD $424, R11
+ BR callbackasm1(SB)
+ MOVD $425, R11
+ BR callbackasm1(SB)
+ MOVD $426, R11
+ BR callbackasm1(SB)
+ MOVD $427, R11
+ BR callbackasm1(SB)
+ MOVD $428, R11
+ BR callbackasm1(SB)
+ MOVD $429, R11
+ BR callbackasm1(SB)
+ MOVD $430, R11
+ BR callbackasm1(SB)
+ MOVD $431, R11
+ BR callbackasm1(SB)
+ MOVD $432, R11
+ BR callbackasm1(SB)
+ MOVD $433, R11
+ BR callbackasm1(SB)
+ MOVD $434, R11
+ BR callbackasm1(SB)
+ MOVD $435, R11
+ BR callbackasm1(SB)
+ MOVD $436, R11
+ BR callbackasm1(SB)
+ MOVD $437, R11
+ BR callbackasm1(SB)
+ MOVD $438, R11
+ BR callbackasm1(SB)
+ MOVD $439, R11
+ BR callbackasm1(SB)
+ MOVD $440, R11
+ BR callbackasm1(SB)
+ MOVD $441, R11
+ BR callbackasm1(SB)
+ MOVD $442, R11
+ BR callbackasm1(SB)
+ MOVD $443, R11
+ BR callbackasm1(SB)
+ MOVD $444, R11
+ BR callbackasm1(SB)
+ MOVD $445, R11
+ BR callbackasm1(SB)
+ MOVD $446, R11
+ BR callbackasm1(SB)
+ MOVD $447, R11
+ BR callbackasm1(SB)
+ MOVD $448, R11
+ BR callbackasm1(SB)
+ MOVD $449, R11
+ BR callbackasm1(SB)
+ MOVD $450, R11
+ BR callbackasm1(SB)
+ MOVD $451, R11
+ BR callbackasm1(SB)
+ MOVD $452, R11
+ BR callbackasm1(SB)
+ MOVD $453, R11
+ BR callbackasm1(SB)
+ MOVD $454, R11
+ BR callbackasm1(SB)
+ MOVD $455, R11
+ BR callbackasm1(SB)
+ MOVD $456, R11
+ BR callbackasm1(SB)
+ MOVD $457, R11
+ BR callbackasm1(SB)
+ MOVD $458, R11
+ BR callbackasm1(SB)
+ MOVD $459, R11
+ BR callbackasm1(SB)
+ MOVD $460, R11
+ BR callbackasm1(SB)
+ MOVD $461, R11
+ BR callbackasm1(SB)
+ MOVD $462, R11
+ BR callbackasm1(SB)
+ MOVD $463, R11
+ BR callbackasm1(SB)
+ MOVD $464, R11
+ BR callbackasm1(SB)
+ MOVD $465, R11
+ BR callbackasm1(SB)
+ MOVD $466, R11
+ BR callbackasm1(SB)
+ MOVD $467, R11
+ BR callbackasm1(SB)
+ MOVD $468, R11
+ BR callbackasm1(SB)
+ MOVD $469, R11
+ BR callbackasm1(SB)
+ MOVD $470, R11
+ BR callbackasm1(SB)
+ MOVD $471, R11
+ BR callbackasm1(SB)
+ MOVD $472, R11
+ BR callbackasm1(SB)
+ MOVD $473, R11
+ BR callbackasm1(SB)
+ MOVD $474, R11
+ BR callbackasm1(SB)
+ MOVD $475, R11
+ BR callbackasm1(SB)
+ MOVD $476, R11
+ BR callbackasm1(SB)
+ MOVD $477, R11
+ BR callbackasm1(SB)
+ MOVD $478, R11
+ BR callbackasm1(SB)
+ MOVD $479, R11
+ BR callbackasm1(SB)
+ MOVD $480, R11
+ BR callbackasm1(SB)
+ MOVD $481, R11
+ BR callbackasm1(SB)
+ MOVD $482, R11
+ BR callbackasm1(SB)
+ MOVD $483, R11
+ BR callbackasm1(SB)
+ MOVD $484, R11
+ BR callbackasm1(SB)
+ MOVD $485, R11
+ BR callbackasm1(SB)
+ MOVD $486, R11
+ BR callbackasm1(SB)
+ MOVD $487, R11
+ BR callbackasm1(SB)
+ MOVD $488, R11
+ BR callbackasm1(SB)
+ MOVD $489, R11
+ BR callbackasm1(SB)
+ MOVD $490, R11
+ BR callbackasm1(SB)
+ MOVD $491, R11
+ BR callbackasm1(SB)
+ MOVD $492, R11
+ BR callbackasm1(SB)
+ MOVD $493, R11
+ BR callbackasm1(SB)
+ MOVD $494, R11
+ BR callbackasm1(SB)
+ MOVD $495, R11
+ BR callbackasm1(SB)
+ MOVD $496, R11
+ BR callbackasm1(SB)
+ MOVD $497, R11
+ BR callbackasm1(SB)
+ MOVD $498, R11
+ BR callbackasm1(SB)
+ MOVD $499, R11
+ BR callbackasm1(SB)
+ MOVD $500, R11
+ BR callbackasm1(SB)
+ MOVD $501, R11
+ BR callbackasm1(SB)
+ MOVD $502, R11
+ BR callbackasm1(SB)
+ MOVD $503, R11
+ BR callbackasm1(SB)
+ MOVD $504, R11
+ BR callbackasm1(SB)
+ MOVD $505, R11
+ BR callbackasm1(SB)
+ MOVD $506, R11
+ BR callbackasm1(SB)
+ MOVD $507, R11
+ BR callbackasm1(SB)
+ MOVD $508, R11
+ BR callbackasm1(SB)
+ MOVD $509, R11
+ BR callbackasm1(SB)
+ MOVD $510, R11
+ BR callbackasm1(SB)
+ MOVD $511, R11
+ BR callbackasm1(SB)
+ MOVD $512, R11
+ BR callbackasm1(SB)
+ MOVD $513, R11
+ BR callbackasm1(SB)
+ MOVD $514, R11
+ BR callbackasm1(SB)
+ MOVD $515, R11
+ BR callbackasm1(SB)
+ MOVD $516, R11
+ BR callbackasm1(SB)
+ MOVD $517, R11
+ BR callbackasm1(SB)
+ MOVD $518, R11
+ BR callbackasm1(SB)
+ MOVD $519, R11
+ BR callbackasm1(SB)
+ MOVD $520, R11
+ BR callbackasm1(SB)
+ MOVD $521, R11
+ BR callbackasm1(SB)
+ MOVD $522, R11
+ BR callbackasm1(SB)
+ MOVD $523, R11
+ BR callbackasm1(SB)
+ MOVD $524, R11
+ BR callbackasm1(SB)
+ MOVD $525, R11
+ BR callbackasm1(SB)
+ MOVD $526, R11
+ BR callbackasm1(SB)
+ MOVD $527, R11
+ BR callbackasm1(SB)
+ MOVD $528, R11
+ BR callbackasm1(SB)
+ MOVD $529, R11
+ BR callbackasm1(SB)
+ MOVD $530, R11
+ BR callbackasm1(SB)
+ MOVD $531, R11
+ BR callbackasm1(SB)
+ MOVD $532, R11
+ BR callbackasm1(SB)
+ MOVD $533, R11
+ BR callbackasm1(SB)
+ MOVD $534, R11
+ BR callbackasm1(SB)
+ MOVD $535, R11
+ BR callbackasm1(SB)
+ MOVD $536, R11
+ BR callbackasm1(SB)
+ MOVD $537, R11
+ BR callbackasm1(SB)
+ MOVD $538, R11
+ BR callbackasm1(SB)
+ MOVD $539, R11
+ BR callbackasm1(SB)
+ MOVD $540, R11
+ BR callbackasm1(SB)
+ MOVD $541, R11
+ BR callbackasm1(SB)
+ MOVD $542, R11
+ BR callbackasm1(SB)
+ MOVD $543, R11
+ BR callbackasm1(SB)
+ MOVD $544, R11
+ BR callbackasm1(SB)
+ MOVD $545, R11
+ BR callbackasm1(SB)
+ MOVD $546, R11
+ BR callbackasm1(SB)
+ MOVD $547, R11
+ BR callbackasm1(SB)
+ MOVD $548, R11
+ BR callbackasm1(SB)
+ MOVD $549, R11
+ BR callbackasm1(SB)
+ MOVD $550, R11
+ BR callbackasm1(SB)
+ MOVD $551, R11
+ BR callbackasm1(SB)
+ MOVD $552, R11
+ BR callbackasm1(SB)
+ MOVD $553, R11
+ BR callbackasm1(SB)
+ MOVD $554, R11
+ BR callbackasm1(SB)
+ MOVD $555, R11
+ BR callbackasm1(SB)
+ MOVD $556, R11
+ BR callbackasm1(SB)
+ MOVD $557, R11
+ BR callbackasm1(SB)
+ MOVD $558, R11
+ BR callbackasm1(SB)
+ MOVD $559, R11
+ BR callbackasm1(SB)
+ MOVD $560, R11
+ BR callbackasm1(SB)
+ MOVD $561, R11
+ BR callbackasm1(SB)
+ MOVD $562, R11
+ BR callbackasm1(SB)
+ MOVD $563, R11
+ BR callbackasm1(SB)
+ MOVD $564, R11
+ BR callbackasm1(SB)
+ MOVD $565, R11
+ BR callbackasm1(SB)
+ MOVD $566, R11
+ BR callbackasm1(SB)
+ MOVD $567, R11
+ BR callbackasm1(SB)
+ MOVD $568, R11
+ BR callbackasm1(SB)
+ MOVD $569, R11
+ BR callbackasm1(SB)
+ MOVD $570, R11
+ BR callbackasm1(SB)
+ MOVD $571, R11
+ BR callbackasm1(SB)
+ MOVD $572, R11
+ BR callbackasm1(SB)
+ MOVD $573, R11
+ BR callbackasm1(SB)
+ MOVD $574, R11
+ BR callbackasm1(SB)
+ MOVD $575, R11
+ BR callbackasm1(SB)
+ MOVD $576, R11
+ BR callbackasm1(SB)
+ MOVD $577, R11
+ BR callbackasm1(SB)
+ MOVD $578, R11
+ BR callbackasm1(SB)
+ MOVD $579, R11
+ BR callbackasm1(SB)
+ MOVD $580, R11
+ BR callbackasm1(SB)
+ MOVD $581, R11
+ BR callbackasm1(SB)
+ MOVD $582, R11
+ BR callbackasm1(SB)
+ MOVD $583, R11
+ BR callbackasm1(SB)
+ MOVD $584, R11
+ BR callbackasm1(SB)
+ MOVD $585, R11
+ BR callbackasm1(SB)
+ MOVD $586, R11
+ BR callbackasm1(SB)
+ MOVD $587, R11
+ BR callbackasm1(SB)
+ MOVD $588, R11
+ BR callbackasm1(SB)
+ MOVD $589, R11
+ BR callbackasm1(SB)
+ MOVD $590, R11
+ BR callbackasm1(SB)
+ MOVD $591, R11
+ BR callbackasm1(SB)
+ MOVD $592, R11
+ BR callbackasm1(SB)
+ MOVD $593, R11
+ BR callbackasm1(SB)
+ MOVD $594, R11
+ BR callbackasm1(SB)
+ MOVD $595, R11
+ BR callbackasm1(SB)
+ MOVD $596, R11
+ BR callbackasm1(SB)
+ MOVD $597, R11
+ BR callbackasm1(SB)
+ MOVD $598, R11
+ BR callbackasm1(SB)
+ MOVD $599, R11
+ BR callbackasm1(SB)
+ MOVD $600, R11
+ BR callbackasm1(SB)
+ MOVD $601, R11
+ BR callbackasm1(SB)
+ MOVD $602, R11
+ BR callbackasm1(SB)
+ MOVD $603, R11
+ BR callbackasm1(SB)
+ MOVD $604, R11
+ BR callbackasm1(SB)
+ MOVD $605, R11
+ BR callbackasm1(SB)
+ MOVD $606, R11
+ BR callbackasm1(SB)
+ MOVD $607, R11
+ BR callbackasm1(SB)
+ MOVD $608, R11
+ BR callbackasm1(SB)
+ MOVD $609, R11
+ BR callbackasm1(SB)
+ MOVD $610, R11
+ BR callbackasm1(SB)
+ MOVD $611, R11
+ BR callbackasm1(SB)
+ MOVD $612, R11
+ BR callbackasm1(SB)
+ MOVD $613, R11
+ BR callbackasm1(SB)
+ MOVD $614, R11
+ BR callbackasm1(SB)
+ MOVD $615, R11
+ BR callbackasm1(SB)
+ MOVD $616, R11
+ BR callbackasm1(SB)
+ MOVD $617, R11
+ BR callbackasm1(SB)
+ MOVD $618, R11
+ BR callbackasm1(SB)
+ MOVD $619, R11
+ BR callbackasm1(SB)
+ MOVD $620, R11
+ BR callbackasm1(SB)
+ MOVD $621, R11
+ BR callbackasm1(SB)
+ MOVD $622, R11
+ BR callbackasm1(SB)
+ MOVD $623, R11
+ BR callbackasm1(SB)
+ MOVD $624, R11
+ BR callbackasm1(SB)
+ MOVD $625, R11
+ BR callbackasm1(SB)
+ MOVD $626, R11
+ BR callbackasm1(SB)
+ MOVD $627, R11
+ BR callbackasm1(SB)
+ MOVD $628, R11
+ BR callbackasm1(SB)
+ MOVD $629, R11
+ BR callbackasm1(SB)
+ MOVD $630, R11
+ BR callbackasm1(SB)
+ MOVD $631, R11
+ BR callbackasm1(SB)
+ MOVD $632, R11
+ BR callbackasm1(SB)
+ MOVD $633, R11
+ BR callbackasm1(SB)
+ MOVD $634, R11
+ BR callbackasm1(SB)
+ MOVD $635, R11
+ BR callbackasm1(SB)
+ MOVD $636, R11
+ BR callbackasm1(SB)
+ MOVD $637, R11
+ BR callbackasm1(SB)
+ MOVD $638, R11
+ BR callbackasm1(SB)
+ MOVD $639, R11
+ BR callbackasm1(SB)
+ MOVD $640, R11
+ BR callbackasm1(SB)
+ MOVD $641, R11
+ BR callbackasm1(SB)
+ MOVD $642, R11
+ BR callbackasm1(SB)
+ MOVD $643, R11
+ BR callbackasm1(SB)
+ MOVD $644, R11
+ BR callbackasm1(SB)
+ MOVD $645, R11
+ BR callbackasm1(SB)
+ MOVD $646, R11
+ BR callbackasm1(SB)
+ MOVD $647, R11
+ BR callbackasm1(SB)
+ MOVD $648, R11
+ BR callbackasm1(SB)
+ MOVD $649, R11
+ BR callbackasm1(SB)
+ MOVD $650, R11
+ BR callbackasm1(SB)
+ MOVD $651, R11
+ BR callbackasm1(SB)
+ MOVD $652, R11
+ BR callbackasm1(SB)
+ MOVD $653, R11
+ BR callbackasm1(SB)
+ MOVD $654, R11
+ BR callbackasm1(SB)
+ MOVD $655, R11
+ BR callbackasm1(SB)
+ MOVD $656, R11
+ BR callbackasm1(SB)
+ MOVD $657, R11
+ BR callbackasm1(SB)
+ MOVD $658, R11
+ BR callbackasm1(SB)
+ MOVD $659, R11
+ BR callbackasm1(SB)
+ MOVD $660, R11
+ BR callbackasm1(SB)
+ MOVD $661, R11
+ BR callbackasm1(SB)
+ MOVD $662, R11
+ BR callbackasm1(SB)
+ MOVD $663, R11
+ BR callbackasm1(SB)
+ MOVD $664, R11
+ BR callbackasm1(SB)
+ MOVD $665, R11
+ BR callbackasm1(SB)
+ MOVD $666, R11
+ BR callbackasm1(SB)
+ MOVD $667, R11
+ BR callbackasm1(SB)
+ MOVD $668, R11
+ BR callbackasm1(SB)
+ MOVD $669, R11
+ BR callbackasm1(SB)
+ MOVD $670, R11
+ BR callbackasm1(SB)
+ MOVD $671, R11
+ BR callbackasm1(SB)
+ MOVD $672, R11
+ BR callbackasm1(SB)
+ MOVD $673, R11
+ BR callbackasm1(SB)
+ MOVD $674, R11
+ BR callbackasm1(SB)
+ MOVD $675, R11
+ BR callbackasm1(SB)
+ MOVD $676, R11
+ BR callbackasm1(SB)
+ MOVD $677, R11
+ BR callbackasm1(SB)
+ MOVD $678, R11
+ BR callbackasm1(SB)
+ MOVD $679, R11
+ BR callbackasm1(SB)
+ MOVD $680, R11
+ BR callbackasm1(SB)
+ MOVD $681, R11
+ BR callbackasm1(SB)
+ MOVD $682, R11
+ BR callbackasm1(SB)
+ MOVD $683, R11
+ BR callbackasm1(SB)
+ MOVD $684, R11
+ BR callbackasm1(SB)
+ MOVD $685, R11
+ BR callbackasm1(SB)
+ MOVD $686, R11
+ BR callbackasm1(SB)
+ MOVD $687, R11
+ BR callbackasm1(SB)
+ MOVD $688, R11
+ BR callbackasm1(SB)
+ MOVD $689, R11
+ BR callbackasm1(SB)
+ MOVD $690, R11
+ BR callbackasm1(SB)
+ MOVD $691, R11
+ BR callbackasm1(SB)
+ MOVD $692, R11
+ BR callbackasm1(SB)
+ MOVD $693, R11
+ BR callbackasm1(SB)
+ MOVD $694, R11
+ BR callbackasm1(SB)
+ MOVD $695, R11
+ BR callbackasm1(SB)
+ MOVD $696, R11
+ BR callbackasm1(SB)
+ MOVD $697, R11
+ BR callbackasm1(SB)
+ MOVD $698, R11
+ BR callbackasm1(SB)
+ MOVD $699, R11
+ BR callbackasm1(SB)
+ MOVD $700, R11
+ BR callbackasm1(SB)
+ MOVD $701, R11
+ BR callbackasm1(SB)
+ MOVD $702, R11
+ BR callbackasm1(SB)
+ MOVD $703, R11
+ BR callbackasm1(SB)
+ MOVD $704, R11
+ BR callbackasm1(SB)
+ MOVD $705, R11
+ BR callbackasm1(SB)
+ MOVD $706, R11
+ BR callbackasm1(SB)
+ MOVD $707, R11
+ BR callbackasm1(SB)
+ MOVD $708, R11
+ BR callbackasm1(SB)
+ MOVD $709, R11
+ BR callbackasm1(SB)
+ MOVD $710, R11
+ BR callbackasm1(SB)
+ MOVD $711, R11
+ BR callbackasm1(SB)
+ MOVD $712, R11
+ BR callbackasm1(SB)
+ MOVD $713, R11
+ BR callbackasm1(SB)
+ MOVD $714, R11
+ BR callbackasm1(SB)
+ MOVD $715, R11
+ BR callbackasm1(SB)
+ MOVD $716, R11
+ BR callbackasm1(SB)
+ MOVD $717, R11
+ BR callbackasm1(SB)
+ MOVD $718, R11
+ BR callbackasm1(SB)
+ MOVD $719, R11
+ BR callbackasm1(SB)
+ MOVD $720, R11
+ BR callbackasm1(SB)
+ MOVD $721, R11
+ BR callbackasm1(SB)
+ MOVD $722, R11
+ BR callbackasm1(SB)
+ MOVD $723, R11
+ BR callbackasm1(SB)
+ MOVD $724, R11
+ BR callbackasm1(SB)
+ MOVD $725, R11
+ BR callbackasm1(SB)
+ MOVD $726, R11
+ BR callbackasm1(SB)
+ MOVD $727, R11
+ BR callbackasm1(SB)
+ MOVD $728, R11
+ BR callbackasm1(SB)
+ MOVD $729, R11
+ BR callbackasm1(SB)
+ MOVD $730, R11
+ BR callbackasm1(SB)
+ MOVD $731, R11
+ BR callbackasm1(SB)
+ MOVD $732, R11
+ BR callbackasm1(SB)
+ MOVD $733, R11
+ BR callbackasm1(SB)
+ MOVD $734, R11
+ BR callbackasm1(SB)
+ MOVD $735, R11
+ BR callbackasm1(SB)
+ MOVD $736, R11
+ BR callbackasm1(SB)
+ MOVD $737, R11
+ BR callbackasm1(SB)
+ MOVD $738, R11
+ BR callbackasm1(SB)
+ MOVD $739, R11
+ BR callbackasm1(SB)
+ MOVD $740, R11
+ BR callbackasm1(SB)
+ MOVD $741, R11
+ BR callbackasm1(SB)
+ MOVD $742, R11
+ BR callbackasm1(SB)
+ MOVD $743, R11
+ BR callbackasm1(SB)
+ MOVD $744, R11
+ BR callbackasm1(SB)
+ MOVD $745, R11
+ BR callbackasm1(SB)
+ MOVD $746, R11
+ BR callbackasm1(SB)
+ MOVD $747, R11
+ BR callbackasm1(SB)
+ MOVD $748, R11
+ BR callbackasm1(SB)
+ MOVD $749, R11
+ BR callbackasm1(SB)
+ MOVD $750, R11
+ BR callbackasm1(SB)
+ MOVD $751, R11
+ BR callbackasm1(SB)
+ MOVD $752, R11
+ BR callbackasm1(SB)
+ MOVD $753, R11
+ BR callbackasm1(SB)
+ MOVD $754, R11
+ BR callbackasm1(SB)
+ MOVD $755, R11
+ BR callbackasm1(SB)
+ MOVD $756, R11
+ BR callbackasm1(SB)
+ MOVD $757, R11
+ BR callbackasm1(SB)
+ MOVD $758, R11
+ BR callbackasm1(SB)
+ MOVD $759, R11
+ BR callbackasm1(SB)
+ MOVD $760, R11
+ BR callbackasm1(SB)
+ MOVD $761, R11
+ BR callbackasm1(SB)
+ MOVD $762, R11
+ BR callbackasm1(SB)
+ MOVD $763, R11
+ BR callbackasm1(SB)
+ MOVD $764, R11
+ BR callbackasm1(SB)
+ MOVD $765, R11
+ BR callbackasm1(SB)
+ MOVD $766, R11
+ BR callbackasm1(SB)
+ MOVD $767, R11
+ BR callbackasm1(SB)
+ MOVD $768, R11
+ BR callbackasm1(SB)
+ MOVD $769, R11
+ BR callbackasm1(SB)
+ MOVD $770, R11
+ BR callbackasm1(SB)
+ MOVD $771, R11
+ BR callbackasm1(SB)
+ MOVD $772, R11
+ BR callbackasm1(SB)
+ MOVD $773, R11
+ BR callbackasm1(SB)
+ MOVD $774, R11
+ BR callbackasm1(SB)
+ MOVD $775, R11
+ BR callbackasm1(SB)
+ MOVD $776, R11
+ BR callbackasm1(SB)
+ MOVD $777, R11
+ BR callbackasm1(SB)
+ MOVD $778, R11
+ BR callbackasm1(SB)
+ MOVD $779, R11
+ BR callbackasm1(SB)
+ MOVD $780, R11
+ BR callbackasm1(SB)
+ MOVD $781, R11
+ BR callbackasm1(SB)
+ MOVD $782, R11
+ BR callbackasm1(SB)
+ MOVD $783, R11
+ BR callbackasm1(SB)
+ MOVD $784, R11
+ BR callbackasm1(SB)
+ MOVD $785, R11
+ BR callbackasm1(SB)
+ MOVD $786, R11
+ BR callbackasm1(SB)
+ MOVD $787, R11
+ BR callbackasm1(SB)
+ MOVD $788, R11
+ BR callbackasm1(SB)
+ MOVD $789, R11
+ BR callbackasm1(SB)
+ MOVD $790, R11
+ BR callbackasm1(SB)
+ MOVD $791, R11
+ BR callbackasm1(SB)
+ MOVD $792, R11
+ BR callbackasm1(SB)
+ MOVD $793, R11
+ BR callbackasm1(SB)
+ MOVD $794, R11
+ BR callbackasm1(SB)
+ MOVD $795, R11
+ BR callbackasm1(SB)
+ MOVD $796, R11
+ BR callbackasm1(SB)
+ MOVD $797, R11
+ BR callbackasm1(SB)
+ MOVD $798, R11
+ BR callbackasm1(SB)
+ MOVD $799, R11
+ BR callbackasm1(SB)
+ MOVD $800, R11
+ BR callbackasm1(SB)
+ MOVD $801, R11
+ BR callbackasm1(SB)
+ MOVD $802, R11
+ BR callbackasm1(SB)
+ MOVD $803, R11
+ BR callbackasm1(SB)
+ MOVD $804, R11
+ BR callbackasm1(SB)
+ MOVD $805, R11
+ BR callbackasm1(SB)
+ MOVD $806, R11
+ BR callbackasm1(SB)
+ MOVD $807, R11
+ BR callbackasm1(SB)
+ MOVD $808, R11
+ BR callbackasm1(SB)
+ MOVD $809, R11
+ BR callbackasm1(SB)
+ MOVD $810, R11
+ BR callbackasm1(SB)
+ MOVD $811, R11
+ BR callbackasm1(SB)
+ MOVD $812, R11
+ BR callbackasm1(SB)
+ MOVD $813, R11
+ BR callbackasm1(SB)
+ MOVD $814, R11
+ BR callbackasm1(SB)
+ MOVD $815, R11
+ BR callbackasm1(SB)
+ MOVD $816, R11
+ BR callbackasm1(SB)
+ MOVD $817, R11
+ BR callbackasm1(SB)
+ MOVD $818, R11
+ BR callbackasm1(SB)
+ MOVD $819, R11
+ BR callbackasm1(SB)
+ MOVD $820, R11
+ BR callbackasm1(SB)
+ MOVD $821, R11
+ BR callbackasm1(SB)
+ MOVD $822, R11
+ BR callbackasm1(SB)
+ MOVD $823, R11
+ BR callbackasm1(SB)
+ MOVD $824, R11
+ BR callbackasm1(SB)
+ MOVD $825, R11
+ BR callbackasm1(SB)
+ MOVD $826, R11
+ BR callbackasm1(SB)
+ MOVD $827, R11
+ BR callbackasm1(SB)
+ MOVD $828, R11
+ BR callbackasm1(SB)
+ MOVD $829, R11
+ BR callbackasm1(SB)
+ MOVD $830, R11
+ BR callbackasm1(SB)
+ MOVD $831, R11
+ BR callbackasm1(SB)
+ MOVD $832, R11
+ BR callbackasm1(SB)
+ MOVD $833, R11
+ BR callbackasm1(SB)
+ MOVD $834, R11
+ BR callbackasm1(SB)
+ MOVD $835, R11
+ BR callbackasm1(SB)
+ MOVD $836, R11
+ BR callbackasm1(SB)
+ MOVD $837, R11
+ BR callbackasm1(SB)
+ MOVD $838, R11
+ BR callbackasm1(SB)
+ MOVD $839, R11
+ BR callbackasm1(SB)
+ MOVD $840, R11
+ BR callbackasm1(SB)
+ MOVD $841, R11
+ BR callbackasm1(SB)
+ MOVD $842, R11
+ BR callbackasm1(SB)
+ MOVD $843, R11
+ BR callbackasm1(SB)
+ MOVD $844, R11
+ BR callbackasm1(SB)
+ MOVD $845, R11
+ BR callbackasm1(SB)
+ MOVD $846, R11
+ BR callbackasm1(SB)
+ MOVD $847, R11
+ BR callbackasm1(SB)
+ MOVD $848, R11
+ BR callbackasm1(SB)
+ MOVD $849, R11
+ BR callbackasm1(SB)
+ MOVD $850, R11
+ BR callbackasm1(SB)
+ MOVD $851, R11
+ BR callbackasm1(SB)
+ MOVD $852, R11
+ BR callbackasm1(SB)
+ MOVD $853, R11
+ BR callbackasm1(SB)
+ MOVD $854, R11
+ BR callbackasm1(SB)
+ MOVD $855, R11
+ BR callbackasm1(SB)
+ MOVD $856, R11
+ BR callbackasm1(SB)
+ MOVD $857, R11
+ BR callbackasm1(SB)
+ MOVD $858, R11
+ BR callbackasm1(SB)
+ MOVD $859, R11
+ BR callbackasm1(SB)
+ MOVD $860, R11
+ BR callbackasm1(SB)
+ MOVD $861, R11
+ BR callbackasm1(SB)
+ MOVD $862, R11
+ BR callbackasm1(SB)
+ MOVD $863, R11
+ BR callbackasm1(SB)
+ MOVD $864, R11
+ BR callbackasm1(SB)
+ MOVD $865, R11
+ BR callbackasm1(SB)
+ MOVD $866, R11
+ BR callbackasm1(SB)
+ MOVD $867, R11
+ BR callbackasm1(SB)
+ MOVD $868, R11
+ BR callbackasm1(SB)
+ MOVD $869, R11
+ BR callbackasm1(SB)
+ MOVD $870, R11
+ BR callbackasm1(SB)
+ MOVD $871, R11
+ BR callbackasm1(SB)
+ MOVD $872, R11
+ BR callbackasm1(SB)
+ MOVD $873, R11
+ BR callbackasm1(SB)
+ MOVD $874, R11
+ BR callbackasm1(SB)
+ MOVD $875, R11
+ BR callbackasm1(SB)
+ MOVD $876, R11
+ BR callbackasm1(SB)
+ MOVD $877, R11
+ BR callbackasm1(SB)
+ MOVD $878, R11
+ BR callbackasm1(SB)
+ MOVD $879, R11
+ BR callbackasm1(SB)
+ MOVD $880, R11
+ BR callbackasm1(SB)
+ MOVD $881, R11
+ BR callbackasm1(SB)
+ MOVD $882, R11
+ BR callbackasm1(SB)
+ MOVD $883, R11
+ BR callbackasm1(SB)
+ MOVD $884, R11
+ BR callbackasm1(SB)
+ MOVD $885, R11
+ BR callbackasm1(SB)
+ MOVD $886, R11
+ BR callbackasm1(SB)
+ MOVD $887, R11
+ BR callbackasm1(SB)
+ MOVD $888, R11
+ BR callbackasm1(SB)
+ MOVD $889, R11
+ BR callbackasm1(SB)
+ MOVD $890, R11
+ BR callbackasm1(SB)
+ MOVD $891, R11
+ BR callbackasm1(SB)
+ MOVD $892, R11
+ BR callbackasm1(SB)
+ MOVD $893, R11
+ BR callbackasm1(SB)
+ MOVD $894, R11
+ BR callbackasm1(SB)
+ MOVD $895, R11
+ BR callbackasm1(SB)
+ MOVD $896, R11
+ BR callbackasm1(SB)
+ MOVD $897, R11
+ BR callbackasm1(SB)
+ MOVD $898, R11
+ BR callbackasm1(SB)
+ MOVD $899, R11
+ BR callbackasm1(SB)
+ MOVD $900, R11
+ BR callbackasm1(SB)
+ MOVD $901, R11
+ BR callbackasm1(SB)
+ MOVD $902, R11
+ BR callbackasm1(SB)
+ MOVD $903, R11
+ BR callbackasm1(SB)
+ MOVD $904, R11
+ BR callbackasm1(SB)
+ MOVD $905, R11
+ BR callbackasm1(SB)
+ MOVD $906, R11
+ BR callbackasm1(SB)
+ MOVD $907, R11
+ BR callbackasm1(SB)
+ MOVD $908, R11
+ BR callbackasm1(SB)
+ MOVD $909, R11
+ BR callbackasm1(SB)
+ MOVD $910, R11
+ BR callbackasm1(SB)
+ MOVD $911, R11
+ BR callbackasm1(SB)
+ MOVD $912, R11
+ BR callbackasm1(SB)
+ MOVD $913, R11
+ BR callbackasm1(SB)
+ MOVD $914, R11
+ BR callbackasm1(SB)
+ MOVD $915, R11
+ BR callbackasm1(SB)
+ MOVD $916, R11
+ BR callbackasm1(SB)
+ MOVD $917, R11
+ BR callbackasm1(SB)
+ MOVD $918, R11
+ BR callbackasm1(SB)
+ MOVD $919, R11
+ BR callbackasm1(SB)
+ MOVD $920, R11
+ BR callbackasm1(SB)
+ MOVD $921, R11
+ BR callbackasm1(SB)
+ MOVD $922, R11
+ BR callbackasm1(SB)
+ MOVD $923, R11
+ BR callbackasm1(SB)
+ MOVD $924, R11
+ BR callbackasm1(SB)
+ MOVD $925, R11
+ BR callbackasm1(SB)
+ MOVD $926, R11
+ BR callbackasm1(SB)
+ MOVD $927, R11
+ BR callbackasm1(SB)
+ MOVD $928, R11
+ BR callbackasm1(SB)
+ MOVD $929, R11
+ BR callbackasm1(SB)
+ MOVD $930, R11
+ BR callbackasm1(SB)
+ MOVD $931, R11
+ BR callbackasm1(SB)
+ MOVD $932, R11
+ BR callbackasm1(SB)
+ MOVD $933, R11
+ BR callbackasm1(SB)
+ MOVD $934, R11
+ BR callbackasm1(SB)
+ MOVD $935, R11
+ BR callbackasm1(SB)
+ MOVD $936, R11
+ BR callbackasm1(SB)
+ MOVD $937, R11
+ BR callbackasm1(SB)
+ MOVD $938, R11
+ BR callbackasm1(SB)
+ MOVD $939, R11
+ BR callbackasm1(SB)
+ MOVD $940, R11
+ BR callbackasm1(SB)
+ MOVD $941, R11
+ BR callbackasm1(SB)
+ MOVD $942, R11
+ BR callbackasm1(SB)
+ MOVD $943, R11
+ BR callbackasm1(SB)
+ MOVD $944, R11
+ BR callbackasm1(SB)
+ MOVD $945, R11
+ BR callbackasm1(SB)
+ MOVD $946, R11
+ BR callbackasm1(SB)
+ MOVD $947, R11
+ BR callbackasm1(SB)
+ MOVD $948, R11
+ BR callbackasm1(SB)
+ MOVD $949, R11
+ BR callbackasm1(SB)
+ MOVD $950, R11
+ BR callbackasm1(SB)
+ MOVD $951, R11
+ BR callbackasm1(SB)
+ MOVD $952, R11
+ BR callbackasm1(SB)
+ MOVD $953, R11
+ BR callbackasm1(SB)
+ MOVD $954, R11
+ BR callbackasm1(SB)
+ MOVD $955, R11
+ BR callbackasm1(SB)
+ MOVD $956, R11
+ BR callbackasm1(SB)
+ MOVD $957, R11
+ BR callbackasm1(SB)
+ MOVD $958, R11
+ BR callbackasm1(SB)
+ MOVD $959, R11
+ BR callbackasm1(SB)
+ MOVD $960, R11
+ BR callbackasm1(SB)
+ MOVD $961, R11
+ BR callbackasm1(SB)
+ MOVD $962, R11
+ BR callbackasm1(SB)
+ MOVD $963, R11
+ BR callbackasm1(SB)
+ MOVD $964, R11
+ BR callbackasm1(SB)
+ MOVD $965, R11
+ BR callbackasm1(SB)
+ MOVD $966, R11
+ BR callbackasm1(SB)
+ MOVD $967, R11
+ BR callbackasm1(SB)
+ MOVD $968, R11
+ BR callbackasm1(SB)
+ MOVD $969, R11
+ BR callbackasm1(SB)
+ MOVD $970, R11
+ BR callbackasm1(SB)
+ MOVD $971, R11
+ BR callbackasm1(SB)
+ MOVD $972, R11
+ BR callbackasm1(SB)
+ MOVD $973, R11
+ BR callbackasm1(SB)
+ MOVD $974, R11
+ BR callbackasm1(SB)
+ MOVD $975, R11
+ BR callbackasm1(SB)
+ MOVD $976, R11
+ BR callbackasm1(SB)
+ MOVD $977, R11
+ BR callbackasm1(SB)
+ MOVD $978, R11
+ BR callbackasm1(SB)
+ MOVD $979, R11
+ BR callbackasm1(SB)
+ MOVD $980, R11
+ BR callbackasm1(SB)
+ MOVD $981, R11
+ BR callbackasm1(SB)
+ MOVD $982, R11
+ BR callbackasm1(SB)
+ MOVD $983, R11
+ BR callbackasm1(SB)
+ MOVD $984, R11
+ BR callbackasm1(SB)
+ MOVD $985, R11
+ BR callbackasm1(SB)
+ MOVD $986, R11
+ BR callbackasm1(SB)
+ MOVD $987, R11
+ BR callbackasm1(SB)
+ MOVD $988, R11
+ BR callbackasm1(SB)
+ MOVD $989, R11
+ BR callbackasm1(SB)
+ MOVD $990, R11
+ BR callbackasm1(SB)
+ MOVD $991, R11
+ BR callbackasm1(SB)
+ MOVD $992, R11
+ BR callbackasm1(SB)
+ MOVD $993, R11
+ BR callbackasm1(SB)
+ MOVD $994, R11
+ BR callbackasm1(SB)
+ MOVD $995, R11
+ BR callbackasm1(SB)
+ MOVD $996, R11
+ BR callbackasm1(SB)
+ MOVD $997, R11
+ BR callbackasm1(SB)
+ MOVD $998, R11
+ BR callbackasm1(SB)
+ MOVD $999, R11
+ BR callbackasm1(SB)
+ MOVD $1000, R11
+ BR callbackasm1(SB)
+ MOVD $1001, R11
+ BR callbackasm1(SB)
+ MOVD $1002, R11
+ BR callbackasm1(SB)
+ MOVD $1003, R11
+ BR callbackasm1(SB)
+ MOVD $1004, R11
+ BR callbackasm1(SB)
+ MOVD $1005, R11
+ BR callbackasm1(SB)
+ MOVD $1006, R11
+ BR callbackasm1(SB)
+ MOVD $1007, R11
+ BR callbackasm1(SB)
+ MOVD $1008, R11
+ BR callbackasm1(SB)
+ MOVD $1009, R11
+ BR callbackasm1(SB)
+ MOVD $1010, R11
+ BR callbackasm1(SB)
+ MOVD $1011, R11
+ BR callbackasm1(SB)
+ MOVD $1012, R11
+ BR callbackasm1(SB)
+ MOVD $1013, R11
+ BR callbackasm1(SB)
+ MOVD $1014, R11
+ BR callbackasm1(SB)
+ MOVD $1015, R11
+ BR callbackasm1(SB)
+ MOVD $1016, R11
+ BR callbackasm1(SB)
+ MOVD $1017, R11
+ BR callbackasm1(SB)
+ MOVD $1018, R11
+ BR callbackasm1(SB)
+ MOVD $1019, R11
+ BR callbackasm1(SB)
+ MOVD $1020, R11
+ BR callbackasm1(SB)
+ MOVD $1021, R11
+ BR callbackasm1(SB)
+ MOVD $1022, R11
+ BR callbackasm1(SB)
+ MOVD $1023, R11
+ BR callbackasm1(SB)
+ MOVD $1024, R11
+ BR callbackasm1(SB)
+ MOVD $1025, R11
+ BR callbackasm1(SB)
+ MOVD $1026, R11
+ BR callbackasm1(SB)
+ MOVD $1027, R11
+ BR callbackasm1(SB)
+ MOVD $1028, R11
+ BR callbackasm1(SB)
+ MOVD $1029, R11
+ BR callbackasm1(SB)
+ MOVD $1030, R11
+ BR callbackasm1(SB)
+ MOVD $1031, R11
+ BR callbackasm1(SB)
+ MOVD $1032, R11
+ BR callbackasm1(SB)
+ MOVD $1033, R11
+ BR callbackasm1(SB)
+ MOVD $1034, R11
+ BR callbackasm1(SB)
+ MOVD $1035, R11
+ BR callbackasm1(SB)
+ MOVD $1036, R11
+ BR callbackasm1(SB)
+ MOVD $1037, R11
+ BR callbackasm1(SB)
+ MOVD $1038, R11
+ BR callbackasm1(SB)
+ MOVD $1039, R11
+ BR callbackasm1(SB)
+ MOVD $1040, R11
+ BR callbackasm1(SB)
+ MOVD $1041, R11
+ BR callbackasm1(SB)
+ MOVD $1042, R11
+ BR callbackasm1(SB)
+ MOVD $1043, R11
+ BR callbackasm1(SB)
+ MOVD $1044, R11
+ BR callbackasm1(SB)
+ MOVD $1045, R11
+ BR callbackasm1(SB)
+ MOVD $1046, R11
+ BR callbackasm1(SB)
+ MOVD $1047, R11
+ BR callbackasm1(SB)
+ MOVD $1048, R11
+ BR callbackasm1(SB)
+ MOVD $1049, R11
+ BR callbackasm1(SB)
+ MOVD $1050, R11
+ BR callbackasm1(SB)
+ MOVD $1051, R11
+ BR callbackasm1(SB)
+ MOVD $1052, R11
+ BR callbackasm1(SB)
+ MOVD $1053, R11
+ BR callbackasm1(SB)
+ MOVD $1054, R11
+ BR callbackasm1(SB)
+ MOVD $1055, R11
+ BR callbackasm1(SB)
+ MOVD $1056, R11
+ BR callbackasm1(SB)
+ MOVD $1057, R11
+ BR callbackasm1(SB)
+ MOVD $1058, R11
+ BR callbackasm1(SB)
+ MOVD $1059, R11
+ BR callbackasm1(SB)
+ MOVD $1060, R11
+ BR callbackasm1(SB)
+ MOVD $1061, R11
+ BR callbackasm1(SB)
+ MOVD $1062, R11
+ BR callbackasm1(SB)
+ MOVD $1063, R11
+ BR callbackasm1(SB)
+ MOVD $1064, R11
+ BR callbackasm1(SB)
+ MOVD $1065, R11
+ BR callbackasm1(SB)
+ MOVD $1066, R11
+ BR callbackasm1(SB)
+ MOVD $1067, R11
+ BR callbackasm1(SB)
+ MOVD $1068, R11
+ BR callbackasm1(SB)
+ MOVD $1069, R11
+ BR callbackasm1(SB)
+ MOVD $1070, R11
+ BR callbackasm1(SB)
+ MOVD $1071, R11
+ BR callbackasm1(SB)
+ MOVD $1072, R11
+ BR callbackasm1(SB)
+ MOVD $1073, R11
+ BR callbackasm1(SB)
+ MOVD $1074, R11
+ BR callbackasm1(SB)
+ MOVD $1075, R11
+ BR callbackasm1(SB)
+ MOVD $1076, R11
+ BR callbackasm1(SB)
+ MOVD $1077, R11
+ BR callbackasm1(SB)
+ MOVD $1078, R11
+ BR callbackasm1(SB)
+ MOVD $1079, R11
+ BR callbackasm1(SB)
+ MOVD $1080, R11
+ BR callbackasm1(SB)
+ MOVD $1081, R11
+ BR callbackasm1(SB)
+ MOVD $1082, R11
+ BR callbackasm1(SB)
+ MOVD $1083, R11
+ BR callbackasm1(SB)
+ MOVD $1084, R11
+ BR callbackasm1(SB)
+ MOVD $1085, R11
+ BR callbackasm1(SB)
+ MOVD $1086, R11
+ BR callbackasm1(SB)
+ MOVD $1087, R11
+ BR callbackasm1(SB)
+ MOVD $1088, R11
+ BR callbackasm1(SB)
+ MOVD $1089, R11
+ BR callbackasm1(SB)
+ MOVD $1090, R11
+ BR callbackasm1(SB)
+ MOVD $1091, R11
+ BR callbackasm1(SB)
+ MOVD $1092, R11
+ BR callbackasm1(SB)
+ MOVD $1093, R11
+ BR callbackasm1(SB)
+ MOVD $1094, R11
+ BR callbackasm1(SB)
+ MOVD $1095, R11
+ BR callbackasm1(SB)
+ MOVD $1096, R11
+ BR callbackasm1(SB)
+ MOVD $1097, R11
+ BR callbackasm1(SB)
+ MOVD $1098, R11
+ BR callbackasm1(SB)
+ MOVD $1099, R11
+ BR callbackasm1(SB)
+ MOVD $1100, R11
+ BR callbackasm1(SB)
+ MOVD $1101, R11
+ BR callbackasm1(SB)
+ MOVD $1102, R11
+ BR callbackasm1(SB)
+ MOVD $1103, R11
+ BR callbackasm1(SB)
+ MOVD $1104, R11
+ BR callbackasm1(SB)
+ MOVD $1105, R11
+ BR callbackasm1(SB)
+ MOVD $1106, R11
+ BR callbackasm1(SB)
+ MOVD $1107, R11
+ BR callbackasm1(SB)
+ MOVD $1108, R11
+ BR callbackasm1(SB)
+ MOVD $1109, R11
+ BR callbackasm1(SB)
+ MOVD $1110, R11
+ BR callbackasm1(SB)
+ MOVD $1111, R11
+ BR callbackasm1(SB)
+ MOVD $1112, R11
+ BR callbackasm1(SB)
+ MOVD $1113, R11
+ BR callbackasm1(SB)
+ MOVD $1114, R11
+ BR callbackasm1(SB)
+ MOVD $1115, R11
+ BR callbackasm1(SB)
+ MOVD $1116, R11
+ BR callbackasm1(SB)
+ MOVD $1117, R11
+ BR callbackasm1(SB)
+ MOVD $1118, R11
+ BR callbackasm1(SB)
+ MOVD $1119, R11
+ BR callbackasm1(SB)
+ MOVD $1120, R11
+ BR callbackasm1(SB)
+ MOVD $1121, R11
+ BR callbackasm1(SB)
+ MOVD $1122, R11
+ BR callbackasm1(SB)
+ MOVD $1123, R11
+ BR callbackasm1(SB)
+ MOVD $1124, R11
+ BR callbackasm1(SB)
+ MOVD $1125, R11
+ BR callbackasm1(SB)
+ MOVD $1126, R11
+ BR callbackasm1(SB)
+ MOVD $1127, R11
+ BR callbackasm1(SB)
+ MOVD $1128, R11
+ BR callbackasm1(SB)
+ MOVD $1129, R11
+ BR callbackasm1(SB)
+ MOVD $1130, R11
+ BR callbackasm1(SB)
+ MOVD $1131, R11
+ BR callbackasm1(SB)
+ MOVD $1132, R11
+ BR callbackasm1(SB)
+ MOVD $1133, R11
+ BR callbackasm1(SB)
+ MOVD $1134, R11
+ BR callbackasm1(SB)
+ MOVD $1135, R11
+ BR callbackasm1(SB)
+ MOVD $1136, R11
+ BR callbackasm1(SB)
+ MOVD $1137, R11
+ BR callbackasm1(SB)
+ MOVD $1138, R11
+ BR callbackasm1(SB)
+ MOVD $1139, R11
+ BR callbackasm1(SB)
+ MOVD $1140, R11
+ BR callbackasm1(SB)
+ MOVD $1141, R11
+ BR callbackasm1(SB)
+ MOVD $1142, R11
+ BR callbackasm1(SB)
+ MOVD $1143, R11
+ BR callbackasm1(SB)
+ MOVD $1144, R11
+ BR callbackasm1(SB)
+ MOVD $1145, R11
+ BR callbackasm1(SB)
+ MOVD $1146, R11
+ BR callbackasm1(SB)
+ MOVD $1147, R11
+ BR callbackasm1(SB)
+ MOVD $1148, R11
+ BR callbackasm1(SB)
+ MOVD $1149, R11
+ BR callbackasm1(SB)
+ MOVD $1150, R11
+ BR callbackasm1(SB)
+ MOVD $1151, R11
+ BR callbackasm1(SB)
+ MOVD $1152, R11
+ BR callbackasm1(SB)
+ MOVD $1153, R11
+ BR callbackasm1(SB)
+ MOVD $1154, R11
+ BR callbackasm1(SB)
+ MOVD $1155, R11
+ BR callbackasm1(SB)
+ MOVD $1156, R11
+ BR callbackasm1(SB)
+ MOVD $1157, R11
+ BR callbackasm1(SB)
+ MOVD $1158, R11
+ BR callbackasm1(SB)
+ MOVD $1159, R11
+ BR callbackasm1(SB)
+ MOVD $1160, R11
+ BR callbackasm1(SB)
+ MOVD $1161, R11
+ BR callbackasm1(SB)
+ MOVD $1162, R11
+ BR callbackasm1(SB)
+ MOVD $1163, R11
+ BR callbackasm1(SB)
+ MOVD $1164, R11
+ BR callbackasm1(SB)
+ MOVD $1165, R11
+ BR callbackasm1(SB)
+ MOVD $1166, R11
+ BR callbackasm1(SB)
+ MOVD $1167, R11
+ BR callbackasm1(SB)
+ MOVD $1168, R11
+ BR callbackasm1(SB)
+ MOVD $1169, R11
+ BR callbackasm1(SB)
+ MOVD $1170, R11
+ BR callbackasm1(SB)
+ MOVD $1171, R11
+ BR callbackasm1(SB)
+ MOVD $1172, R11
+ BR callbackasm1(SB)
+ MOVD $1173, R11
+ BR callbackasm1(SB)
+ MOVD $1174, R11
+ BR callbackasm1(SB)
+ MOVD $1175, R11
+ BR callbackasm1(SB)
+ MOVD $1176, R11
+ BR callbackasm1(SB)
+ MOVD $1177, R11
+ BR callbackasm1(SB)
+ MOVD $1178, R11
+ BR callbackasm1(SB)
+ MOVD $1179, R11
+ BR callbackasm1(SB)
+ MOVD $1180, R11
+ BR callbackasm1(SB)
+ MOVD $1181, R11
+ BR callbackasm1(SB)
+ MOVD $1182, R11
+ BR callbackasm1(SB)
+ MOVD $1183, R11
+ BR callbackasm1(SB)
+ MOVD $1184, R11
+ BR callbackasm1(SB)
+ MOVD $1185, R11
+ BR callbackasm1(SB)
+ MOVD $1186, R11
+ BR callbackasm1(SB)
+ MOVD $1187, R11
+ BR callbackasm1(SB)
+ MOVD $1188, R11
+ BR callbackasm1(SB)
+ MOVD $1189, R11
+ BR callbackasm1(SB)
+ MOVD $1190, R11
+ BR callbackasm1(SB)
+ MOVD $1191, R11
+ BR callbackasm1(SB)
+ MOVD $1192, R11
+ BR callbackasm1(SB)
+ MOVD $1193, R11
+ BR callbackasm1(SB)
+ MOVD $1194, R11
+ BR callbackasm1(SB)
+ MOVD $1195, R11
+ BR callbackasm1(SB)
+ MOVD $1196, R11
+ BR callbackasm1(SB)
+ MOVD $1197, R11
+ BR callbackasm1(SB)
+ MOVD $1198, R11
+ BR callbackasm1(SB)
+ MOVD $1199, R11
+ BR callbackasm1(SB)
+ MOVD $1200, R11
+ BR callbackasm1(SB)
+ MOVD $1201, R11
+ BR callbackasm1(SB)
+ MOVD $1202, R11
+ BR callbackasm1(SB)
+ MOVD $1203, R11
+ BR callbackasm1(SB)
+ MOVD $1204, R11
+ BR callbackasm1(SB)
+ MOVD $1205, R11
+ BR callbackasm1(SB)
+ MOVD $1206, R11
+ BR callbackasm1(SB)
+ MOVD $1207, R11
+ BR callbackasm1(SB)
+ MOVD $1208, R11
+ BR callbackasm1(SB)
+ MOVD $1209, R11
+ BR callbackasm1(SB)
+ MOVD $1210, R11
+ BR callbackasm1(SB)
+ MOVD $1211, R11
+ BR callbackasm1(SB)
+ MOVD $1212, R11
+ BR callbackasm1(SB)
+ MOVD $1213, R11
+ BR callbackasm1(SB)
+ MOVD $1214, R11
+ BR callbackasm1(SB)
+ MOVD $1215, R11
+ BR callbackasm1(SB)
+ MOVD $1216, R11
+ BR callbackasm1(SB)
+ MOVD $1217, R11
+ BR callbackasm1(SB)
+ MOVD $1218, R11
+ BR callbackasm1(SB)
+ MOVD $1219, R11
+ BR callbackasm1(SB)
+ MOVD $1220, R11
+ BR callbackasm1(SB)
+ MOVD $1221, R11
+ BR callbackasm1(SB)
+ MOVD $1222, R11
+ BR callbackasm1(SB)
+ MOVD $1223, R11
+ BR callbackasm1(SB)
+ MOVD $1224, R11
+ BR callbackasm1(SB)
+ MOVD $1225, R11
+ BR callbackasm1(SB)
+ MOVD $1226, R11
+ BR callbackasm1(SB)
+ MOVD $1227, R11
+ BR callbackasm1(SB)
+ MOVD $1228, R11
+ BR callbackasm1(SB)
+ MOVD $1229, R11
+ BR callbackasm1(SB)
+ MOVD $1230, R11
+ BR callbackasm1(SB)
+ MOVD $1231, R11
+ BR callbackasm1(SB)
+ MOVD $1232, R11
+ BR callbackasm1(SB)
+ MOVD $1233, R11
+ BR callbackasm1(SB)
+ MOVD $1234, R11
+ BR callbackasm1(SB)
+ MOVD $1235, R11
+ BR callbackasm1(SB)
+ MOVD $1236, R11
+ BR callbackasm1(SB)
+ MOVD $1237, R11
+ BR callbackasm1(SB)
+ MOVD $1238, R11
+ BR callbackasm1(SB)
+ MOVD $1239, R11
+ BR callbackasm1(SB)
+ MOVD $1240, R11
+ BR callbackasm1(SB)
+ MOVD $1241, R11
+ BR callbackasm1(SB)
+ MOVD $1242, R11
+ BR callbackasm1(SB)
+ MOVD $1243, R11
+ BR callbackasm1(SB)
+ MOVD $1244, R11
+ BR callbackasm1(SB)
+ MOVD $1245, R11
+ BR callbackasm1(SB)
+ MOVD $1246, R11
+ BR callbackasm1(SB)
+ MOVD $1247, R11
+ BR callbackasm1(SB)
+ MOVD $1248, R11
+ BR callbackasm1(SB)
+ MOVD $1249, R11
+ BR callbackasm1(SB)
+ MOVD $1250, R11
+ BR callbackasm1(SB)
+ MOVD $1251, R11
+ BR callbackasm1(SB)
+ MOVD $1252, R11
+ BR callbackasm1(SB)
+ MOVD $1253, R11
+ BR callbackasm1(SB)
+ MOVD $1254, R11
+ BR callbackasm1(SB)
+ MOVD $1255, R11
+ BR callbackasm1(SB)
+ MOVD $1256, R11
+ BR callbackasm1(SB)
+ MOVD $1257, R11
+ BR callbackasm1(SB)
+ MOVD $1258, R11
+ BR callbackasm1(SB)
+ MOVD $1259, R11
+ BR callbackasm1(SB)
+ MOVD $1260, R11
+ BR callbackasm1(SB)
+ MOVD $1261, R11
+ BR callbackasm1(SB)
+ MOVD $1262, R11
+ BR callbackasm1(SB)
+ MOVD $1263, R11
+ BR callbackasm1(SB)
+ MOVD $1264, R11
+ BR callbackasm1(SB)
+ MOVD $1265, R11
+ BR callbackasm1(SB)
+ MOVD $1266, R11
+ BR callbackasm1(SB)
+ MOVD $1267, R11
+ BR callbackasm1(SB)
+ MOVD $1268, R11
+ BR callbackasm1(SB)
+ MOVD $1269, R11
+ BR callbackasm1(SB)
+ MOVD $1270, R11
+ BR callbackasm1(SB)
+ MOVD $1271, R11
+ BR callbackasm1(SB)
+ MOVD $1272, R11
+ BR callbackasm1(SB)
+ MOVD $1273, R11
+ BR callbackasm1(SB)
+ MOVD $1274, R11
+ BR callbackasm1(SB)
+ MOVD $1275, R11
+ BR callbackasm1(SB)
+ MOVD $1276, R11
+ BR callbackasm1(SB)
+ MOVD $1277, R11
+ BR callbackasm1(SB)
+ MOVD $1278, R11
+ BR callbackasm1(SB)
+ MOVD $1279, R11
+ BR callbackasm1(SB)
+ MOVD $1280, R11
+ BR callbackasm1(SB)
+ MOVD $1281, R11
+ BR callbackasm1(SB)
+ MOVD $1282, R11
+ BR callbackasm1(SB)
+ MOVD $1283, R11
+ BR callbackasm1(SB)
+ MOVD $1284, R11
+ BR callbackasm1(SB)
+ MOVD $1285, R11
+ BR callbackasm1(SB)
+ MOVD $1286, R11
+ BR callbackasm1(SB)
+ MOVD $1287, R11
+ BR callbackasm1(SB)
+ MOVD $1288, R11
+ BR callbackasm1(SB)
+ MOVD $1289, R11
+ BR callbackasm1(SB)
+ MOVD $1290, R11
+ BR callbackasm1(SB)
+ MOVD $1291, R11
+ BR callbackasm1(SB)
+ MOVD $1292, R11
+ BR callbackasm1(SB)
+ MOVD $1293, R11
+ BR callbackasm1(SB)
+ MOVD $1294, R11
+ BR callbackasm1(SB)
+ MOVD $1295, R11
+ BR callbackasm1(SB)
+ MOVD $1296, R11
+ BR callbackasm1(SB)
+ MOVD $1297, R11
+ BR callbackasm1(SB)
+ MOVD $1298, R11
+ BR callbackasm1(SB)
+ MOVD $1299, R11
+ BR callbackasm1(SB)
+ MOVD $1300, R11
+ BR callbackasm1(SB)
+ MOVD $1301, R11
+ BR callbackasm1(SB)
+ MOVD $1302, R11
+ BR callbackasm1(SB)
+ MOVD $1303, R11
+ BR callbackasm1(SB)
+ MOVD $1304, R11
+ BR callbackasm1(SB)
+ MOVD $1305, R11
+ BR callbackasm1(SB)
+ MOVD $1306, R11
+ BR callbackasm1(SB)
+ MOVD $1307, R11
+ BR callbackasm1(SB)
+ MOVD $1308, R11
+ BR callbackasm1(SB)
+ MOVD $1309, R11
+ BR callbackasm1(SB)
+ MOVD $1310, R11
+ BR callbackasm1(SB)
+ MOVD $1311, R11
+ BR callbackasm1(SB)
+ MOVD $1312, R11
+ BR callbackasm1(SB)
+ MOVD $1313, R11
+ BR callbackasm1(SB)
+ MOVD $1314, R11
+ BR callbackasm1(SB)
+ MOVD $1315, R11
+ BR callbackasm1(SB)
+ MOVD $1316, R11
+ BR callbackasm1(SB)
+ MOVD $1317, R11
+ BR callbackasm1(SB)
+ MOVD $1318, R11
+ BR callbackasm1(SB)
+ MOVD $1319, R11
+ BR callbackasm1(SB)
+ MOVD $1320, R11
+ BR callbackasm1(SB)
+ MOVD $1321, R11
+ BR callbackasm1(SB)
+ MOVD $1322, R11
+ BR callbackasm1(SB)
+ MOVD $1323, R11
+ BR callbackasm1(SB)
+ MOVD $1324, R11
+ BR callbackasm1(SB)
+ MOVD $1325, R11
+ BR callbackasm1(SB)
+ MOVD $1326, R11
+ BR callbackasm1(SB)
+ MOVD $1327, R11
+ BR callbackasm1(SB)
+ MOVD $1328, R11
+ BR callbackasm1(SB)
+ MOVD $1329, R11
+ BR callbackasm1(SB)
+ MOVD $1330, R11
+ BR callbackasm1(SB)
+ MOVD $1331, R11
+ BR callbackasm1(SB)
+ MOVD $1332, R11
+ BR callbackasm1(SB)
+ MOVD $1333, R11
+ BR callbackasm1(SB)
+ MOVD $1334, R11
+ BR callbackasm1(SB)
+ MOVD $1335, R11
+ BR callbackasm1(SB)
+ MOVD $1336, R11
+ BR callbackasm1(SB)
+ MOVD $1337, R11
+ BR callbackasm1(SB)
+ MOVD $1338, R11
+ BR callbackasm1(SB)
+ MOVD $1339, R11
+ BR callbackasm1(SB)
+ MOVD $1340, R11
+ BR callbackasm1(SB)
+ MOVD $1341, R11
+ BR callbackasm1(SB)
+ MOVD $1342, R11
+ BR callbackasm1(SB)
+ MOVD $1343, R11
+ BR callbackasm1(SB)
+ MOVD $1344, R11
+ BR callbackasm1(SB)
+ MOVD $1345, R11
+ BR callbackasm1(SB)
+ MOVD $1346, R11
+ BR callbackasm1(SB)
+ MOVD $1347, R11
+ BR callbackasm1(SB)
+ MOVD $1348, R11
+ BR callbackasm1(SB)
+ MOVD $1349, R11
+ BR callbackasm1(SB)
+ MOVD $1350, R11
+ BR callbackasm1(SB)
+ MOVD $1351, R11
+ BR callbackasm1(SB)
+ MOVD $1352, R11
+ BR callbackasm1(SB)
+ MOVD $1353, R11
+ BR callbackasm1(SB)
+ MOVD $1354, R11
+ BR callbackasm1(SB)
+ MOVD $1355, R11
+ BR callbackasm1(SB)
+ MOVD $1356, R11
+ BR callbackasm1(SB)
+ MOVD $1357, R11
+ BR callbackasm1(SB)
+ MOVD $1358, R11
+ BR callbackasm1(SB)
+ MOVD $1359, R11
+ BR callbackasm1(SB)
+ MOVD $1360, R11
+ BR callbackasm1(SB)
+ MOVD $1361, R11
+ BR callbackasm1(SB)
+ MOVD $1362, R11
+ BR callbackasm1(SB)
+ MOVD $1363, R11
+ BR callbackasm1(SB)
+ MOVD $1364, R11
+ BR callbackasm1(SB)
+ MOVD $1365, R11
+ BR callbackasm1(SB)
+ MOVD $1366, R11
+ BR callbackasm1(SB)
+ MOVD $1367, R11
+ BR callbackasm1(SB)
+ MOVD $1368, R11
+ BR callbackasm1(SB)
+ MOVD $1369, R11
+ BR callbackasm1(SB)
+ MOVD $1370, R11
+ BR callbackasm1(SB)
+ MOVD $1371, R11
+ BR callbackasm1(SB)
+ MOVD $1372, R11
+ BR callbackasm1(SB)
+ MOVD $1373, R11
+ BR callbackasm1(SB)
+ MOVD $1374, R11
+ BR callbackasm1(SB)
+ MOVD $1375, R11
+ BR callbackasm1(SB)
+ MOVD $1376, R11
+ BR callbackasm1(SB)
+ MOVD $1377, R11
+ BR callbackasm1(SB)
+ MOVD $1378, R11
+ BR callbackasm1(SB)
+ MOVD $1379, R11
+ BR callbackasm1(SB)
+ MOVD $1380, R11
+ BR callbackasm1(SB)
+ MOVD $1381, R11
+ BR callbackasm1(SB)
+ MOVD $1382, R11
+ BR callbackasm1(SB)
+ MOVD $1383, R11
+ BR callbackasm1(SB)
+ MOVD $1384, R11
+ BR callbackasm1(SB)
+ MOVD $1385, R11
+ BR callbackasm1(SB)
+ MOVD $1386, R11
+ BR callbackasm1(SB)
+ MOVD $1387, R11
+ BR callbackasm1(SB)
+ MOVD $1388, R11
+ BR callbackasm1(SB)
+ MOVD $1389, R11
+ BR callbackasm1(SB)
+ MOVD $1390, R11
+ BR callbackasm1(SB)
+ MOVD $1391, R11
+ BR callbackasm1(SB)
+ MOVD $1392, R11
+ BR callbackasm1(SB)
+ MOVD $1393, R11
+ BR callbackasm1(SB)
+ MOVD $1394, R11
+ BR callbackasm1(SB)
+ MOVD $1395, R11
+ BR callbackasm1(SB)
+ MOVD $1396, R11
+ BR callbackasm1(SB)
+ MOVD $1397, R11
+ BR callbackasm1(SB)
+ MOVD $1398, R11
+ BR callbackasm1(SB)
+ MOVD $1399, R11
+ BR callbackasm1(SB)
+ MOVD $1400, R11
+ BR callbackasm1(SB)
+ MOVD $1401, R11
+ BR callbackasm1(SB)
+ MOVD $1402, R11
+ BR callbackasm1(SB)
+ MOVD $1403, R11
+ BR callbackasm1(SB)
+ MOVD $1404, R11
+ BR callbackasm1(SB)
+ MOVD $1405, R11
+ BR callbackasm1(SB)
+ MOVD $1406, R11
+ BR callbackasm1(SB)
+ MOVD $1407, R11
+ BR callbackasm1(SB)
+ MOVD $1408, R11
+ BR callbackasm1(SB)
+ MOVD $1409, R11
+ BR callbackasm1(SB)
+ MOVD $1410, R11
+ BR callbackasm1(SB)
+ MOVD $1411, R11
+ BR callbackasm1(SB)
+ MOVD $1412, R11
+ BR callbackasm1(SB)
+ MOVD $1413, R11
+ BR callbackasm1(SB)
+ MOVD $1414, R11
+ BR callbackasm1(SB)
+ MOVD $1415, R11
+ BR callbackasm1(SB)
+ MOVD $1416, R11
+ BR callbackasm1(SB)
+ MOVD $1417, R11
+ BR callbackasm1(SB)
+ MOVD $1418, R11
+ BR callbackasm1(SB)
+ MOVD $1419, R11
+ BR callbackasm1(SB)
+ MOVD $1420, R11
+ BR callbackasm1(SB)
+ MOVD $1421, R11
+ BR callbackasm1(SB)
+ MOVD $1422, R11
+ BR callbackasm1(SB)
+ MOVD $1423, R11
+ BR callbackasm1(SB)
+ MOVD $1424, R11
+ BR callbackasm1(SB)
+ MOVD $1425, R11
+ BR callbackasm1(SB)
+ MOVD $1426, R11
+ BR callbackasm1(SB)
+ MOVD $1427, R11
+ BR callbackasm1(SB)
+ MOVD $1428, R11
+ BR callbackasm1(SB)
+ MOVD $1429, R11
+ BR callbackasm1(SB)
+ MOVD $1430, R11
+ BR callbackasm1(SB)
+ MOVD $1431, R11
+ BR callbackasm1(SB)
+ MOVD $1432, R11
+ BR callbackasm1(SB)
+ MOVD $1433, R11
+ BR callbackasm1(SB)
+ MOVD $1434, R11
+ BR callbackasm1(SB)
+ MOVD $1435, R11
+ BR callbackasm1(SB)
+ MOVD $1436, R11
+ BR callbackasm1(SB)
+ MOVD $1437, R11
+ BR callbackasm1(SB)
+ MOVD $1438, R11
+ BR callbackasm1(SB)
+ MOVD $1439, R11
+ BR callbackasm1(SB)
+ MOVD $1440, R11
+ BR callbackasm1(SB)
+ MOVD $1441, R11
+ BR callbackasm1(SB)
+ MOVD $1442, R11
+ BR callbackasm1(SB)
+ MOVD $1443, R11
+ BR callbackasm1(SB)
+ MOVD $1444, R11
+ BR callbackasm1(SB)
+ MOVD $1445, R11
+ BR callbackasm1(SB)
+ MOVD $1446, R11
+ BR callbackasm1(SB)
+ MOVD $1447, R11
+ BR callbackasm1(SB)
+ MOVD $1448, R11
+ BR callbackasm1(SB)
+ MOVD $1449, R11
+ BR callbackasm1(SB)
+ MOVD $1450, R11
+ BR callbackasm1(SB)
+ MOVD $1451, R11
+ BR callbackasm1(SB)
+ MOVD $1452, R11
+ BR callbackasm1(SB)
+ MOVD $1453, R11
+ BR callbackasm1(SB)
+ MOVD $1454, R11
+ BR callbackasm1(SB)
+ MOVD $1455, R11
+ BR callbackasm1(SB)
+ MOVD $1456, R11
+ BR callbackasm1(SB)
+ MOVD $1457, R11
+ BR callbackasm1(SB)
+ MOVD $1458, R11
+ BR callbackasm1(SB)
+ MOVD $1459, R11
+ BR callbackasm1(SB)
+ MOVD $1460, R11
+ BR callbackasm1(SB)
+ MOVD $1461, R11
+ BR callbackasm1(SB)
+ MOVD $1462, R11
+ BR callbackasm1(SB)
+ MOVD $1463, R11
+ BR callbackasm1(SB)
+ MOVD $1464, R11
+ BR callbackasm1(SB)
+ MOVD $1465, R11
+ BR callbackasm1(SB)
+ MOVD $1466, R11
+ BR callbackasm1(SB)
+ MOVD $1467, R11
+ BR callbackasm1(SB)
+ MOVD $1468, R11
+ BR callbackasm1(SB)
+ MOVD $1469, R11
+ BR callbackasm1(SB)
+ MOVD $1470, R11
+ BR callbackasm1(SB)
+ MOVD $1471, R11
+ BR callbackasm1(SB)
+ MOVD $1472, R11
+ BR callbackasm1(SB)
+ MOVD $1473, R11
+ BR callbackasm1(SB)
+ MOVD $1474, R11
+ BR callbackasm1(SB)
+ MOVD $1475, R11
+ BR callbackasm1(SB)
+ MOVD $1476, R11
+ BR callbackasm1(SB)
+ MOVD $1477, R11
+ BR callbackasm1(SB)
+ MOVD $1478, R11
+ BR callbackasm1(SB)
+ MOVD $1479, R11
+ BR callbackasm1(SB)
+ MOVD $1480, R11
+ BR callbackasm1(SB)
+ MOVD $1481, R11
+ BR callbackasm1(SB)
+ MOVD $1482, R11
+ BR callbackasm1(SB)
+ MOVD $1483, R11
+ BR callbackasm1(SB)
+ MOVD $1484, R11
+ BR callbackasm1(SB)
+ MOVD $1485, R11
+ BR callbackasm1(SB)
+ MOVD $1486, R11
+ BR callbackasm1(SB)
+ MOVD $1487, R11
+ BR callbackasm1(SB)
+ MOVD $1488, R11
+ BR callbackasm1(SB)
+ MOVD $1489, R11
+ BR callbackasm1(SB)
+ MOVD $1490, R11
+ BR callbackasm1(SB)
+ MOVD $1491, R11
+ BR callbackasm1(SB)
+ MOVD $1492, R11
+ BR callbackasm1(SB)
+ MOVD $1493, R11
+ BR callbackasm1(SB)
+ MOVD $1494, R11
+ BR callbackasm1(SB)
+ MOVD $1495, R11
+ BR callbackasm1(SB)
+ MOVD $1496, R11
+ BR callbackasm1(SB)
+ MOVD $1497, R11
+ BR callbackasm1(SB)
+ MOVD $1498, R11
+ BR callbackasm1(SB)
+ MOVD $1499, R11
+ BR callbackasm1(SB)
+ MOVD $1500, R11
+ BR callbackasm1(SB)
+ MOVD $1501, R11
+ BR callbackasm1(SB)
+ MOVD $1502, R11
+ BR callbackasm1(SB)
+ MOVD $1503, R11
+ BR callbackasm1(SB)
+ MOVD $1504, R11
+ BR callbackasm1(SB)
+ MOVD $1505, R11
+ BR callbackasm1(SB)
+ MOVD $1506, R11
+ BR callbackasm1(SB)
+ MOVD $1507, R11
+ BR callbackasm1(SB)
+ MOVD $1508, R11
+ BR callbackasm1(SB)
+ MOVD $1509, R11
+ BR callbackasm1(SB)
+ MOVD $1510, R11
+ BR callbackasm1(SB)
+ MOVD $1511, R11
+ BR callbackasm1(SB)
+ MOVD $1512, R11
+ BR callbackasm1(SB)
+ MOVD $1513, R11
+ BR callbackasm1(SB)
+ MOVD $1514, R11
+ BR callbackasm1(SB)
+ MOVD $1515, R11
+ BR callbackasm1(SB)
+ MOVD $1516, R11
+ BR callbackasm1(SB)
+ MOVD $1517, R11
+ BR callbackasm1(SB)
+ MOVD $1518, R11
+ BR callbackasm1(SB)
+ MOVD $1519, R11
+ BR callbackasm1(SB)
+ MOVD $1520, R11
+ BR callbackasm1(SB)
+ MOVD $1521, R11
+ BR callbackasm1(SB)
+ MOVD $1522, R11
+ BR callbackasm1(SB)
+ MOVD $1523, R11
+ BR callbackasm1(SB)
+ MOVD $1524, R11
+ BR callbackasm1(SB)
+ MOVD $1525, R11
+ BR callbackasm1(SB)
+ MOVD $1526, R11
+ BR callbackasm1(SB)
+ MOVD $1527, R11
+ BR callbackasm1(SB)
+ MOVD $1528, R11
+ BR callbackasm1(SB)
+ MOVD $1529, R11
+ BR callbackasm1(SB)
+ MOVD $1530, R11
+ BR callbackasm1(SB)
+ MOVD $1531, R11
+ BR callbackasm1(SB)
+ MOVD $1532, R11
+ BR callbackasm1(SB)
+ MOVD $1533, R11
+ BR callbackasm1(SB)
+ MOVD $1534, R11
+ BR callbackasm1(SB)
+ MOVD $1535, R11
+ BR callbackasm1(SB)
+ MOVD $1536, R11
+ BR callbackasm1(SB)
+ MOVD $1537, R11
+ BR callbackasm1(SB)
+ MOVD $1538, R11
+ BR callbackasm1(SB)
+ MOVD $1539, R11
+ BR callbackasm1(SB)
+ MOVD $1540, R11
+ BR callbackasm1(SB)
+ MOVD $1541, R11
+ BR callbackasm1(SB)
+ MOVD $1542, R11
+ BR callbackasm1(SB)
+ MOVD $1543, R11
+ BR callbackasm1(SB)
+ MOVD $1544, R11
+ BR callbackasm1(SB)
+ MOVD $1545, R11
+ BR callbackasm1(SB)
+ MOVD $1546, R11
+ BR callbackasm1(SB)
+ MOVD $1547, R11
+ BR callbackasm1(SB)
+ MOVD $1548, R11
+ BR callbackasm1(SB)
+ MOVD $1549, R11
+ BR callbackasm1(SB)
+ MOVD $1550, R11
+ BR callbackasm1(SB)
+ MOVD $1551, R11
+ BR callbackasm1(SB)
+ MOVD $1552, R11
+ BR callbackasm1(SB)
+ MOVD $1553, R11
+ BR callbackasm1(SB)
+ MOVD $1554, R11
+ BR callbackasm1(SB)
+ MOVD $1555, R11
+ BR callbackasm1(SB)
+ MOVD $1556, R11
+ BR callbackasm1(SB)
+ MOVD $1557, R11
+ BR callbackasm1(SB)
+ MOVD $1558, R11
+ BR callbackasm1(SB)
+ MOVD $1559, R11
+ BR callbackasm1(SB)
+ MOVD $1560, R11
+ BR callbackasm1(SB)
+ MOVD $1561, R11
+ BR callbackasm1(SB)
+ MOVD $1562, R11
+ BR callbackasm1(SB)
+ MOVD $1563, R11
+ BR callbackasm1(SB)
+ MOVD $1564, R11
+ BR callbackasm1(SB)
+ MOVD $1565, R11
+ BR callbackasm1(SB)
+ MOVD $1566, R11
+ BR callbackasm1(SB)
+ MOVD $1567, R11
+ BR callbackasm1(SB)
+ MOVD $1568, R11
+ BR callbackasm1(SB)
+ MOVD $1569, R11
+ BR callbackasm1(SB)
+ MOVD $1570, R11
+ BR callbackasm1(SB)
+ MOVD $1571, R11
+ BR callbackasm1(SB)
+ MOVD $1572, R11
+ BR callbackasm1(SB)
+ MOVD $1573, R11
+ BR callbackasm1(SB)
+ MOVD $1574, R11
+ BR callbackasm1(SB)
+ MOVD $1575, R11
+ BR callbackasm1(SB)
+ MOVD $1576, R11
+ BR callbackasm1(SB)
+ MOVD $1577, R11
+ BR callbackasm1(SB)
+ MOVD $1578, R11
+ BR callbackasm1(SB)
+ MOVD $1579, R11
+ BR callbackasm1(SB)
+ MOVD $1580, R11
+ BR callbackasm1(SB)
+ MOVD $1581, R11
+ BR callbackasm1(SB)
+ MOVD $1582, R11
+ BR callbackasm1(SB)
+ MOVD $1583, R11
+ BR callbackasm1(SB)
+ MOVD $1584, R11
+ BR callbackasm1(SB)
+ MOVD $1585, R11
+ BR callbackasm1(SB)
+ MOVD $1586, R11
+ BR callbackasm1(SB)
+ MOVD $1587, R11
+ BR callbackasm1(SB)
+ MOVD $1588, R11
+ BR callbackasm1(SB)
+ MOVD $1589, R11
+ BR callbackasm1(SB)
+ MOVD $1590, R11
+ BR callbackasm1(SB)
+ MOVD $1591, R11
+ BR callbackasm1(SB)
+ MOVD $1592, R11
+ BR callbackasm1(SB)
+ MOVD $1593, R11
+ BR callbackasm1(SB)
+ MOVD $1594, R11
+ BR callbackasm1(SB)
+ MOVD $1595, R11
+ BR callbackasm1(SB)
+ MOVD $1596, R11
+ BR callbackasm1(SB)
+ MOVD $1597, R11
+ BR callbackasm1(SB)
+ MOVD $1598, R11
+ BR callbackasm1(SB)
+ MOVD $1599, R11
+ BR callbackasm1(SB)
+ MOVD $1600, R11
+ BR callbackasm1(SB)
+ MOVD $1601, R11
+ BR callbackasm1(SB)
+ MOVD $1602, R11
+ BR callbackasm1(SB)
+ MOVD $1603, R11
+ BR callbackasm1(SB)
+ MOVD $1604, R11
+ BR callbackasm1(SB)
+ MOVD $1605, R11
+ BR callbackasm1(SB)
+ MOVD $1606, R11
+ BR callbackasm1(SB)
+ MOVD $1607, R11
+ BR callbackasm1(SB)
+ MOVD $1608, R11
+ BR callbackasm1(SB)
+ MOVD $1609, R11
+ BR callbackasm1(SB)
+ MOVD $1610, R11
+ BR callbackasm1(SB)
+ MOVD $1611, R11
+ BR callbackasm1(SB)
+ MOVD $1612, R11
+ BR callbackasm1(SB)
+ MOVD $1613, R11
+ BR callbackasm1(SB)
+ MOVD $1614, R11
+ BR callbackasm1(SB)
+ MOVD $1615, R11
+ BR callbackasm1(SB)
+ MOVD $1616, R11
+ BR callbackasm1(SB)
+ MOVD $1617, R11
+ BR callbackasm1(SB)
+ MOVD $1618, R11
+ BR callbackasm1(SB)
+ MOVD $1619, R11
+ BR callbackasm1(SB)
+ MOVD $1620, R11
+ BR callbackasm1(SB)
+ MOVD $1621, R11
+ BR callbackasm1(SB)
+ MOVD $1622, R11
+ BR callbackasm1(SB)
+ MOVD $1623, R11
+ BR callbackasm1(SB)
+ MOVD $1624, R11
+ BR callbackasm1(SB)
+ MOVD $1625, R11
+ BR callbackasm1(SB)
+ MOVD $1626, R11
+ BR callbackasm1(SB)
+ MOVD $1627, R11
+ BR callbackasm1(SB)
+ MOVD $1628, R11
+ BR callbackasm1(SB)
+ MOVD $1629, R11
+ BR callbackasm1(SB)
+ MOVD $1630, R11
+ BR callbackasm1(SB)
+ MOVD $1631, R11
+ BR callbackasm1(SB)
+ MOVD $1632, R11
+ BR callbackasm1(SB)
+ MOVD $1633, R11
+ BR callbackasm1(SB)
+ MOVD $1634, R11
+ BR callbackasm1(SB)
+ MOVD $1635, R11
+ BR callbackasm1(SB)
+ MOVD $1636, R11
+ BR callbackasm1(SB)
+ MOVD $1637, R11
+ BR callbackasm1(SB)
+ MOVD $1638, R11
+ BR callbackasm1(SB)
+ MOVD $1639, R11
+ BR callbackasm1(SB)
+ MOVD $1640, R11
+ BR callbackasm1(SB)
+ MOVD $1641, R11
+ BR callbackasm1(SB)
+ MOVD $1642, R11
+ BR callbackasm1(SB)
+ MOVD $1643, R11
+ BR callbackasm1(SB)
+ MOVD $1644, R11
+ BR callbackasm1(SB)
+ MOVD $1645, R11
+ BR callbackasm1(SB)
+ MOVD $1646, R11
+ BR callbackasm1(SB)
+ MOVD $1647, R11
+ BR callbackasm1(SB)
+ MOVD $1648, R11
+ BR callbackasm1(SB)
+ MOVD $1649, R11
+ BR callbackasm1(SB)
+ MOVD $1650, R11
+ BR callbackasm1(SB)
+ MOVD $1651, R11
+ BR callbackasm1(SB)
+ MOVD $1652, R11
+ BR callbackasm1(SB)
+ MOVD $1653, R11
+ BR callbackasm1(SB)
+ MOVD $1654, R11
+ BR callbackasm1(SB)
+ MOVD $1655, R11
+ BR callbackasm1(SB)
+ MOVD $1656, R11
+ BR callbackasm1(SB)
+ MOVD $1657, R11
+ BR callbackasm1(SB)
+ MOVD $1658, R11
+ BR callbackasm1(SB)
+ MOVD $1659, R11
+ BR callbackasm1(SB)
+ MOVD $1660, R11
+ BR callbackasm1(SB)
+ MOVD $1661, R11
+ BR callbackasm1(SB)
+ MOVD $1662, R11
+ BR callbackasm1(SB)
+ MOVD $1663, R11
+ BR callbackasm1(SB)
+ MOVD $1664, R11
+ BR callbackasm1(SB)
+ MOVD $1665, R11
+ BR callbackasm1(SB)
+ MOVD $1666, R11
+ BR callbackasm1(SB)
+ MOVD $1667, R11
+ BR callbackasm1(SB)
+ MOVD $1668, R11
+ BR callbackasm1(SB)
+ MOVD $1669, R11
+ BR callbackasm1(SB)
+ MOVD $1670, R11
+ BR callbackasm1(SB)
+ MOVD $1671, R11
+ BR callbackasm1(SB)
+ MOVD $1672, R11
+ BR callbackasm1(SB)
+ MOVD $1673, R11
+ BR callbackasm1(SB)
+ MOVD $1674, R11
+ BR callbackasm1(SB)
+ MOVD $1675, R11
+ BR callbackasm1(SB)
+ MOVD $1676, R11
+ BR callbackasm1(SB)
+ MOVD $1677, R11
+ BR callbackasm1(SB)
+ MOVD $1678, R11
+ BR callbackasm1(SB)
+ MOVD $1679, R11
+ BR callbackasm1(SB)
+ MOVD $1680, R11
+ BR callbackasm1(SB)
+ MOVD $1681, R11
+ BR callbackasm1(SB)
+ MOVD $1682, R11
+ BR callbackasm1(SB)
+ MOVD $1683, R11
+ BR callbackasm1(SB)
+ MOVD $1684, R11
+ BR callbackasm1(SB)
+ MOVD $1685, R11
+ BR callbackasm1(SB)
+ MOVD $1686, R11
+ BR callbackasm1(SB)
+ MOVD $1687, R11
+ BR callbackasm1(SB)
+ MOVD $1688, R11
+ BR callbackasm1(SB)
+ MOVD $1689, R11
+ BR callbackasm1(SB)
+ MOVD $1690, R11
+ BR callbackasm1(SB)
+ MOVD $1691, R11
+ BR callbackasm1(SB)
+ MOVD $1692, R11
+ BR callbackasm1(SB)
+ MOVD $1693, R11
+ BR callbackasm1(SB)
+ MOVD $1694, R11
+ BR callbackasm1(SB)
+ MOVD $1695, R11
+ BR callbackasm1(SB)
+ MOVD $1696, R11
+ BR callbackasm1(SB)
+ MOVD $1697, R11
+ BR callbackasm1(SB)
+ MOVD $1698, R11
+ BR callbackasm1(SB)
+ MOVD $1699, R11
+ BR callbackasm1(SB)
+ MOVD $1700, R11
+ BR callbackasm1(SB)
+ MOVD $1701, R11
+ BR callbackasm1(SB)
+ MOVD $1702, R11
+ BR callbackasm1(SB)
+ MOVD $1703, R11
+ BR callbackasm1(SB)
+ MOVD $1704, R11
+ BR callbackasm1(SB)
+ MOVD $1705, R11
+ BR callbackasm1(SB)
+ MOVD $1706, R11
+ BR callbackasm1(SB)
+ MOVD $1707, R11
+ BR callbackasm1(SB)
+ MOVD $1708, R11
+ BR callbackasm1(SB)
+ MOVD $1709, R11
+ BR callbackasm1(SB)
+ MOVD $1710, R11
+ BR callbackasm1(SB)
+ MOVD $1711, R11
+ BR callbackasm1(SB)
+ MOVD $1712, R11
+ BR callbackasm1(SB)
+ MOVD $1713, R11
+ BR callbackasm1(SB)
+ MOVD $1714, R11
+ BR callbackasm1(SB)
+ MOVD $1715, R11
+ BR callbackasm1(SB)
+ MOVD $1716, R11
+ BR callbackasm1(SB)
+ MOVD $1717, R11
+ BR callbackasm1(SB)
+ MOVD $1718, R11
+ BR callbackasm1(SB)
+ MOVD $1719, R11
+ BR callbackasm1(SB)
+ MOVD $1720, R11
+ BR callbackasm1(SB)
+ MOVD $1721, R11
+ BR callbackasm1(SB)
+ MOVD $1722, R11
+ BR callbackasm1(SB)
+ MOVD $1723, R11
+ BR callbackasm1(SB)
+ MOVD $1724, R11
+ BR callbackasm1(SB)
+ MOVD $1725, R11
+ BR callbackasm1(SB)
+ MOVD $1726, R11
+ BR callbackasm1(SB)
+ MOVD $1727, R11
+ BR callbackasm1(SB)
+ MOVD $1728, R11
+ BR callbackasm1(SB)
+ MOVD $1729, R11
+ BR callbackasm1(SB)
+ MOVD $1730, R11
+ BR callbackasm1(SB)
+ MOVD $1731, R11
+ BR callbackasm1(SB)
+ MOVD $1732, R11
+ BR callbackasm1(SB)
+ MOVD $1733, R11
+ BR callbackasm1(SB)
+ MOVD $1734, R11
+ BR callbackasm1(SB)
+ MOVD $1735, R11
+ BR callbackasm1(SB)
+ MOVD $1736, R11
+ BR callbackasm1(SB)
+ MOVD $1737, R11
+ BR callbackasm1(SB)
+ MOVD $1738, R11
+ BR callbackasm1(SB)
+ MOVD $1739, R11
+ BR callbackasm1(SB)
+ MOVD $1740, R11
+ BR callbackasm1(SB)
+ MOVD $1741, R11
+ BR callbackasm1(SB)
+ MOVD $1742, R11
+ BR callbackasm1(SB)
+ MOVD $1743, R11
+ BR callbackasm1(SB)
+ MOVD $1744, R11
+ BR callbackasm1(SB)
+ MOVD $1745, R11
+ BR callbackasm1(SB)
+ MOVD $1746, R11
+ BR callbackasm1(SB)
+ MOVD $1747, R11
+ BR callbackasm1(SB)
+ MOVD $1748, R11
+ BR callbackasm1(SB)
+ MOVD $1749, R11
+ BR callbackasm1(SB)
+ MOVD $1750, R11
+ BR callbackasm1(SB)
+ MOVD $1751, R11
+ BR callbackasm1(SB)
+ MOVD $1752, R11
+ BR callbackasm1(SB)
+ MOVD $1753, R11
+ BR callbackasm1(SB)
+ MOVD $1754, R11
+ BR callbackasm1(SB)
+ MOVD $1755, R11
+ BR callbackasm1(SB)
+ MOVD $1756, R11
+ BR callbackasm1(SB)
+ MOVD $1757, R11
+ BR callbackasm1(SB)
+ MOVD $1758, R11
+ BR callbackasm1(SB)
+ MOVD $1759, R11
+ BR callbackasm1(SB)
+ MOVD $1760, R11
+ BR callbackasm1(SB)
+ MOVD $1761, R11
+ BR callbackasm1(SB)
+ MOVD $1762, R11
+ BR callbackasm1(SB)
+ MOVD $1763, R11
+ BR callbackasm1(SB)
+ MOVD $1764, R11
+ BR callbackasm1(SB)
+ MOVD $1765, R11
+ BR callbackasm1(SB)
+ MOVD $1766, R11
+ BR callbackasm1(SB)
+ MOVD $1767, R11
+ BR callbackasm1(SB)
+ MOVD $1768, R11
+ BR callbackasm1(SB)
+ MOVD $1769, R11
+ BR callbackasm1(SB)
+ MOVD $1770, R11
+ BR callbackasm1(SB)
+ MOVD $1771, R11
+ BR callbackasm1(SB)
+ MOVD $1772, R11
+ BR callbackasm1(SB)
+ MOVD $1773, R11
+ BR callbackasm1(SB)
+ MOVD $1774, R11
+ BR callbackasm1(SB)
+ MOVD $1775, R11
+ BR callbackasm1(SB)
+ MOVD $1776, R11
+ BR callbackasm1(SB)
+ MOVD $1777, R11
+ BR callbackasm1(SB)
+ MOVD $1778, R11
+ BR callbackasm1(SB)
+ MOVD $1779, R11
+ BR callbackasm1(SB)
+ MOVD $1780, R11
+ BR callbackasm1(SB)
+ MOVD $1781, R11
+ BR callbackasm1(SB)
+ MOVD $1782, R11
+ BR callbackasm1(SB)
+ MOVD $1783, R11
+ BR callbackasm1(SB)
+ MOVD $1784, R11
+ BR callbackasm1(SB)
+ MOVD $1785, R11
+ BR callbackasm1(SB)
+ MOVD $1786, R11
+ BR callbackasm1(SB)
+ MOVD $1787, R11
+ BR callbackasm1(SB)
+ MOVD $1788, R11
+ BR callbackasm1(SB)
+ MOVD $1789, R11
+ BR callbackasm1(SB)
+ MOVD $1790, R11
+ BR callbackasm1(SB)
+ MOVD $1791, R11
+ BR callbackasm1(SB)
+ MOVD $1792, R11
+ BR callbackasm1(SB)
+ MOVD $1793, R11
+ BR callbackasm1(SB)
+ MOVD $1794, R11
+ BR callbackasm1(SB)
+ MOVD $1795, R11
+ BR callbackasm1(SB)
+ MOVD $1796, R11
+ BR callbackasm1(SB)
+ MOVD $1797, R11
+ BR callbackasm1(SB)
+ MOVD $1798, R11
+ BR callbackasm1(SB)
+ MOVD $1799, R11
+ BR callbackasm1(SB)
+ MOVD $1800, R11
+ BR callbackasm1(SB)
+ MOVD $1801, R11
+ BR callbackasm1(SB)
+ MOVD $1802, R11
+ BR callbackasm1(SB)
+ MOVD $1803, R11
+ BR callbackasm1(SB)
+ MOVD $1804, R11
+ BR callbackasm1(SB)
+ MOVD $1805, R11
+ BR callbackasm1(SB)
+ MOVD $1806, R11
+ BR callbackasm1(SB)
+ MOVD $1807, R11
+ BR callbackasm1(SB)
+ MOVD $1808, R11
+ BR callbackasm1(SB)
+ MOVD $1809, R11
+ BR callbackasm1(SB)
+ MOVD $1810, R11
+ BR callbackasm1(SB)
+ MOVD $1811, R11
+ BR callbackasm1(SB)
+ MOVD $1812, R11
+ BR callbackasm1(SB)
+ MOVD $1813, R11
+ BR callbackasm1(SB)
+ MOVD $1814, R11
+ BR callbackasm1(SB)
+ MOVD $1815, R11
+ BR callbackasm1(SB)
+ MOVD $1816, R11
+ BR callbackasm1(SB)
+ MOVD $1817, R11
+ BR callbackasm1(SB)
+ MOVD $1818, R11
+ BR callbackasm1(SB)
+ MOVD $1819, R11
+ BR callbackasm1(SB)
+ MOVD $1820, R11
+ BR callbackasm1(SB)
+ MOVD $1821, R11
+ BR callbackasm1(SB)
+ MOVD $1822, R11
+ BR callbackasm1(SB)
+ MOVD $1823, R11
+ BR callbackasm1(SB)
+ MOVD $1824, R11
+ BR callbackasm1(SB)
+ MOVD $1825, R11
+ BR callbackasm1(SB)
+ MOVD $1826, R11
+ BR callbackasm1(SB)
+ MOVD $1827, R11
+ BR callbackasm1(SB)
+ MOVD $1828, R11
+ BR callbackasm1(SB)
+ MOVD $1829, R11
+ BR callbackasm1(SB)
+ MOVD $1830, R11
+ BR callbackasm1(SB)
+ MOVD $1831, R11
+ BR callbackasm1(SB)
+ MOVD $1832, R11
+ BR callbackasm1(SB)
+ MOVD $1833, R11
+ BR callbackasm1(SB)
+ MOVD $1834, R11
+ BR callbackasm1(SB)
+ MOVD $1835, R11
+ BR callbackasm1(SB)
+ MOVD $1836, R11
+ BR callbackasm1(SB)
+ MOVD $1837, R11
+ BR callbackasm1(SB)
+ MOVD $1838, R11
+ BR callbackasm1(SB)
+ MOVD $1839, R11
+ BR callbackasm1(SB)
+ MOVD $1840, R11
+ BR callbackasm1(SB)
+ MOVD $1841, R11
+ BR callbackasm1(SB)
+ MOVD $1842, R11
+ BR callbackasm1(SB)
+ MOVD $1843, R11
+ BR callbackasm1(SB)
+ MOVD $1844, R11
+ BR callbackasm1(SB)
+ MOVD $1845, R11
+ BR callbackasm1(SB)
+ MOVD $1846, R11
+ BR callbackasm1(SB)
+ MOVD $1847, R11
+ BR callbackasm1(SB)
+ MOVD $1848, R11
+ BR callbackasm1(SB)
+ MOVD $1849, R11
+ BR callbackasm1(SB)
+ MOVD $1850, R11
+ BR callbackasm1(SB)
+ MOVD $1851, R11
+ BR callbackasm1(SB)
+ MOVD $1852, R11
+ BR callbackasm1(SB)
+ MOVD $1853, R11
+ BR callbackasm1(SB)
+ MOVD $1854, R11
+ BR callbackasm1(SB)
+ MOVD $1855, R11
+ BR callbackasm1(SB)
+ MOVD $1856, R11
+ BR callbackasm1(SB)
+ MOVD $1857, R11
+ BR callbackasm1(SB)
+ MOVD $1858, R11
+ BR callbackasm1(SB)
+ MOVD $1859, R11
+ BR callbackasm1(SB)
+ MOVD $1860, R11
+ BR callbackasm1(SB)
+ MOVD $1861, R11
+ BR callbackasm1(SB)
+ MOVD $1862, R11
+ BR callbackasm1(SB)
+ MOVD $1863, R11
+ BR callbackasm1(SB)
+ MOVD $1864, R11
+ BR callbackasm1(SB)
+ MOVD $1865, R11
+ BR callbackasm1(SB)
+ MOVD $1866, R11
+ BR callbackasm1(SB)
+ MOVD $1867, R11
+ BR callbackasm1(SB)
+ MOVD $1868, R11
+ BR callbackasm1(SB)
+ MOVD $1869, R11
+ BR callbackasm1(SB)
+ MOVD $1870, R11
+ BR callbackasm1(SB)
+ MOVD $1871, R11
+ BR callbackasm1(SB)
+ MOVD $1872, R11
+ BR callbackasm1(SB)
+ MOVD $1873, R11
+ BR callbackasm1(SB)
+ MOVD $1874, R11
+ BR callbackasm1(SB)
+ MOVD $1875, R11
+ BR callbackasm1(SB)
+ MOVD $1876, R11
+ BR callbackasm1(SB)
+ MOVD $1877, R11
+ BR callbackasm1(SB)
+ MOVD $1878, R11
+ BR callbackasm1(SB)
+ MOVD $1879, R11
+ BR callbackasm1(SB)
+ MOVD $1880, R11
+ BR callbackasm1(SB)
+ MOVD $1881, R11
+ BR callbackasm1(SB)
+ MOVD $1882, R11
+ BR callbackasm1(SB)
+ MOVD $1883, R11
+ BR callbackasm1(SB)
+ MOVD $1884, R11
+ BR callbackasm1(SB)
+ MOVD $1885, R11
+ BR callbackasm1(SB)
+ MOVD $1886, R11
+ BR callbackasm1(SB)
+ MOVD $1887, R11
+ BR callbackasm1(SB)
+ MOVD $1888, R11
+ BR callbackasm1(SB)
+ MOVD $1889, R11
+ BR callbackasm1(SB)
+ MOVD $1890, R11
+ BR callbackasm1(SB)
+ MOVD $1891, R11
+ BR callbackasm1(SB)
+ MOVD $1892, R11
+ BR callbackasm1(SB)
+ MOVD $1893, R11
+ BR callbackasm1(SB)
+ MOVD $1894, R11
+ BR callbackasm1(SB)
+ MOVD $1895, R11
+ BR callbackasm1(SB)
+ MOVD $1896, R11
+ BR callbackasm1(SB)
+ MOVD $1897, R11
+ BR callbackasm1(SB)
+ MOVD $1898, R11
+ BR callbackasm1(SB)
+ MOVD $1899, R11
+ BR callbackasm1(SB)
+ MOVD $1900, R11
+ BR callbackasm1(SB)
+ MOVD $1901, R11
+ BR callbackasm1(SB)
+ MOVD $1902, R11
+ BR callbackasm1(SB)
+ MOVD $1903, R11
+ BR callbackasm1(SB)
+ MOVD $1904, R11
+ BR callbackasm1(SB)
+ MOVD $1905, R11
+ BR callbackasm1(SB)
+ MOVD $1906, R11
+ BR callbackasm1(SB)
+ MOVD $1907, R11
+ BR callbackasm1(SB)
+ MOVD $1908, R11
+ BR callbackasm1(SB)
+ MOVD $1909, R11
+ BR callbackasm1(SB)
+ MOVD $1910, R11
+ BR callbackasm1(SB)
+ MOVD $1911, R11
+ BR callbackasm1(SB)
+ MOVD $1912, R11
+ BR callbackasm1(SB)
+ MOVD $1913, R11
+ BR callbackasm1(SB)
+ MOVD $1914, R11
+ BR callbackasm1(SB)
+ MOVD $1915, R11
+ BR callbackasm1(SB)
+ MOVD $1916, R11
+ BR callbackasm1(SB)
+ MOVD $1917, R11
+ BR callbackasm1(SB)
+ MOVD $1918, R11
+ BR callbackasm1(SB)
+ MOVD $1919, R11
+ BR callbackasm1(SB)
+ MOVD $1920, R11
+ BR callbackasm1(SB)
+ MOVD $1921, R11
+ BR callbackasm1(SB)
+ MOVD $1922, R11
+ BR callbackasm1(SB)
+ MOVD $1923, R11
+ BR callbackasm1(SB)
+ MOVD $1924, R11
+ BR callbackasm1(SB)
+ MOVD $1925, R11
+ BR callbackasm1(SB)
+ MOVD $1926, R11
+ BR callbackasm1(SB)
+ MOVD $1927, R11
+ BR callbackasm1(SB)
+ MOVD $1928, R11
+ BR callbackasm1(SB)
+ MOVD $1929, R11
+ BR callbackasm1(SB)
+ MOVD $1930, R11
+ BR callbackasm1(SB)
+ MOVD $1931, R11
+ BR callbackasm1(SB)
+ MOVD $1932, R11
+ BR callbackasm1(SB)
+ MOVD $1933, R11
+ BR callbackasm1(SB)
+ MOVD $1934, R11
+ BR callbackasm1(SB)
+ MOVD $1935, R11
+ BR callbackasm1(SB)
+ MOVD $1936, R11
+ BR callbackasm1(SB)
+ MOVD $1937, R11
+ BR callbackasm1(SB)
+ MOVD $1938, R11
+ BR callbackasm1(SB)
+ MOVD $1939, R11
+ BR callbackasm1(SB)
+ MOVD $1940, R11
+ BR callbackasm1(SB)
+ MOVD $1941, R11
+ BR callbackasm1(SB)
+ MOVD $1942, R11
+ BR callbackasm1(SB)
+ MOVD $1943, R11
+ BR callbackasm1(SB)
+ MOVD $1944, R11
+ BR callbackasm1(SB)
+ MOVD $1945, R11
+ BR callbackasm1(SB)
+ MOVD $1946, R11
+ BR callbackasm1(SB)
+ MOVD $1947, R11
+ BR callbackasm1(SB)
+ MOVD $1948, R11
+ BR callbackasm1(SB)
+ MOVD $1949, R11
+ BR callbackasm1(SB)
+ MOVD $1950, R11
+ BR callbackasm1(SB)
+ MOVD $1951, R11
+ BR callbackasm1(SB)
+ MOVD $1952, R11
+ BR callbackasm1(SB)
+ MOVD $1953, R11
+ BR callbackasm1(SB)
+ MOVD $1954, R11
+ BR callbackasm1(SB)
+ MOVD $1955, R11
+ BR callbackasm1(SB)
+ MOVD $1956, R11
+ BR callbackasm1(SB)
+ MOVD $1957, R11
+ BR callbackasm1(SB)
+ MOVD $1958, R11
+ BR callbackasm1(SB)
+ MOVD $1959, R11
+ BR callbackasm1(SB)
+ MOVD $1960, R11
+ BR callbackasm1(SB)
+ MOVD $1961, R11
+ BR callbackasm1(SB)
+ MOVD $1962, R11
+ BR callbackasm1(SB)
+ MOVD $1963, R11
+ BR callbackasm1(SB)
+ MOVD $1964, R11
+ BR callbackasm1(SB)
+ MOVD $1965, R11
+ BR callbackasm1(SB)
+ MOVD $1966, R11
+ BR callbackasm1(SB)
+ MOVD $1967, R11
+ BR callbackasm1(SB)
+ MOVD $1968, R11
+ BR callbackasm1(SB)
+ MOVD $1969, R11
+ BR callbackasm1(SB)
+ MOVD $1970, R11
+ BR callbackasm1(SB)
+ MOVD $1971, R11
+ BR callbackasm1(SB)
+ MOVD $1972, R11
+ BR callbackasm1(SB)
+ MOVD $1973, R11
+ BR callbackasm1(SB)
+ MOVD $1974, R11
+ BR callbackasm1(SB)
+ MOVD $1975, R11
+ BR callbackasm1(SB)
+ MOVD $1976, R11
+ BR callbackasm1(SB)
+ MOVD $1977, R11
+ BR callbackasm1(SB)
+ MOVD $1978, R11
+ BR callbackasm1(SB)
+ MOVD $1979, R11
+ BR callbackasm1(SB)
+ MOVD $1980, R11
+ BR callbackasm1(SB)
+ MOVD $1981, R11
+ BR callbackasm1(SB)
+ MOVD $1982, R11
+ BR callbackasm1(SB)
+ MOVD $1983, R11
+ BR callbackasm1(SB)
+ MOVD $1984, R11
+ BR callbackasm1(SB)
+ MOVD $1985, R11
+ BR callbackasm1(SB)
+ MOVD $1986, R11
+ BR callbackasm1(SB)
+ MOVD $1987, R11
+ BR callbackasm1(SB)
+ MOVD $1988, R11
+ BR callbackasm1(SB)
+ MOVD $1989, R11
+ BR callbackasm1(SB)
+ MOVD $1990, R11
+ BR callbackasm1(SB)
+ MOVD $1991, R11
+ BR callbackasm1(SB)
+ MOVD $1992, R11
+ BR callbackasm1(SB)
+ MOVD $1993, R11
+ BR callbackasm1(SB)
+ MOVD $1994, R11
+ BR callbackasm1(SB)
+ MOVD $1995, R11
+ BR callbackasm1(SB)
+ MOVD $1996, R11
+ BR callbackasm1(SB)
+ MOVD $1997, R11
+ BR callbackasm1(SB)
+ MOVD $1998, R11
+ BR callbackasm1(SB)
+ MOVD $1999, R11
+ BR callbackasm1(SB)
diff --git a/raymenu/vendor/github.com/ebitengine/purego/zcallback_riscv64.s b/raymenu/vendor/github.com/ebitengine/purego/zcallback_riscv64.s
new file mode 100644
index 0000000..f341a87
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/zcallback_riscv64.s
@@ -0,0 +1,4051 @@
+// Code generated by wincallback.go using 'go generate'. DO NOT EDIT.
+
+//go:build darwin || freebsd || linux || netbsd
+
+// External code calls into callbackasm at an offset corresponding
+// to the callback index. Callbackasm is a table of MOV and JMP instructions.
+// Since Go 1.26, MOV instructions with immediate values lower than or equal to 32
+// are encoded in 2 bytes rather than 4 bytes, which breaks the assumption that each
+// callback entry is 8 bytes long. Therefore, for callback indices less than or equal to 32,
+// add a PCALIGN directive to align the next instruction to an 8-byte boundary.
+// The MOV instruction loads X7 with the callback index, and the
+// JMP instruction branches to callbackasm1.
+// callbackasm1 takes the callback index from X7 and
+// indexes into an array that stores information about each callback.
+// It then calls the Go implementation for that callback.
+#include "textflag.h"
+
+TEXT callbackasm(SB), NOSPLIT|NOFRAME, $0
+ PCALIGN $8
+ MOV $0, X7
+ JMP callbackasm1(SB)
+ PCALIGN $8
+ MOV $1, X7
+ JMP callbackasm1(SB)
+ PCALIGN $8
+ MOV $2, X7
+ JMP callbackasm1(SB)
+ PCALIGN $8
+ MOV $3, X7
+ JMP callbackasm1(SB)
+ PCALIGN $8
+ MOV $4, X7
+ JMP callbackasm1(SB)
+ PCALIGN $8
+ MOV $5, X7
+ JMP callbackasm1(SB)
+ PCALIGN $8
+ MOV $6, X7
+ JMP callbackasm1(SB)
+ PCALIGN $8
+ MOV $7, X7
+ JMP callbackasm1(SB)
+ PCALIGN $8
+ MOV $8, X7
+ JMP callbackasm1(SB)
+ PCALIGN $8
+ MOV $9, X7
+ JMP callbackasm1(SB)
+ PCALIGN $8
+ MOV $10, X7
+ JMP callbackasm1(SB)
+ PCALIGN $8
+ MOV $11, X7
+ JMP callbackasm1(SB)
+ PCALIGN $8
+ MOV $12, X7
+ JMP callbackasm1(SB)
+ PCALIGN $8
+ MOV $13, X7
+ JMP callbackasm1(SB)
+ PCALIGN $8
+ MOV $14, X7
+ JMP callbackasm1(SB)
+ PCALIGN $8
+ MOV $15, X7
+ JMP callbackasm1(SB)
+ PCALIGN $8
+ MOV $16, X7
+ JMP callbackasm1(SB)
+ PCALIGN $8
+ MOV $17, X7
+ JMP callbackasm1(SB)
+ PCALIGN $8
+ MOV $18, X7
+ JMP callbackasm1(SB)
+ PCALIGN $8
+ MOV $19, X7
+ JMP callbackasm1(SB)
+ PCALIGN $8
+ MOV $20, X7
+ JMP callbackasm1(SB)
+ PCALIGN $8
+ MOV $21, X7
+ JMP callbackasm1(SB)
+ PCALIGN $8
+ MOV $22, X7
+ JMP callbackasm1(SB)
+ PCALIGN $8
+ MOV $23, X7
+ JMP callbackasm1(SB)
+ PCALIGN $8
+ MOV $24, X7
+ JMP callbackasm1(SB)
+ PCALIGN $8
+ MOV $25, X7
+ JMP callbackasm1(SB)
+ PCALIGN $8
+ MOV $26, X7
+ JMP callbackasm1(SB)
+ PCALIGN $8
+ MOV $27, X7
+ JMP callbackasm1(SB)
+ PCALIGN $8
+ MOV $28, X7
+ JMP callbackasm1(SB)
+ PCALIGN $8
+ MOV $29, X7
+ JMP callbackasm1(SB)
+ PCALIGN $8
+ MOV $30, X7
+ JMP callbackasm1(SB)
+ PCALIGN $8
+ MOV $31, X7
+ JMP callbackasm1(SB)
+ PCALIGN $8
+ MOV $32, X7
+ JMP callbackasm1(SB)
+ MOV $33, X7
+ JMP callbackasm1(SB)
+ MOV $34, X7
+ JMP callbackasm1(SB)
+ MOV $35, X7
+ JMP callbackasm1(SB)
+ MOV $36, X7
+ JMP callbackasm1(SB)
+ MOV $37, X7
+ JMP callbackasm1(SB)
+ MOV $38, X7
+ JMP callbackasm1(SB)
+ MOV $39, X7
+ JMP callbackasm1(SB)
+ MOV $40, X7
+ JMP callbackasm1(SB)
+ MOV $41, X7
+ JMP callbackasm1(SB)
+ MOV $42, X7
+ JMP callbackasm1(SB)
+ MOV $43, X7
+ JMP callbackasm1(SB)
+ MOV $44, X7
+ JMP callbackasm1(SB)
+ MOV $45, X7
+ JMP callbackasm1(SB)
+ MOV $46, X7
+ JMP callbackasm1(SB)
+ MOV $47, X7
+ JMP callbackasm1(SB)
+ MOV $48, X7
+ JMP callbackasm1(SB)
+ MOV $49, X7
+ JMP callbackasm1(SB)
+ MOV $50, X7
+ JMP callbackasm1(SB)
+ MOV $51, X7
+ JMP callbackasm1(SB)
+ MOV $52, X7
+ JMP callbackasm1(SB)
+ MOV $53, X7
+ JMP callbackasm1(SB)
+ MOV $54, X7
+ JMP callbackasm1(SB)
+ MOV $55, X7
+ JMP callbackasm1(SB)
+ MOV $56, X7
+ JMP callbackasm1(SB)
+ MOV $57, X7
+ JMP callbackasm1(SB)
+ MOV $58, X7
+ JMP callbackasm1(SB)
+ MOV $59, X7
+ JMP callbackasm1(SB)
+ MOV $60, X7
+ JMP callbackasm1(SB)
+ MOV $61, X7
+ JMP callbackasm1(SB)
+ MOV $62, X7
+ JMP callbackasm1(SB)
+ MOV $63, X7
+ JMP callbackasm1(SB)
+ MOV $64, X7
+ JMP callbackasm1(SB)
+ MOV $65, X7
+ JMP callbackasm1(SB)
+ MOV $66, X7
+ JMP callbackasm1(SB)
+ MOV $67, X7
+ JMP callbackasm1(SB)
+ MOV $68, X7
+ JMP callbackasm1(SB)
+ MOV $69, X7
+ JMP callbackasm1(SB)
+ MOV $70, X7
+ JMP callbackasm1(SB)
+ MOV $71, X7
+ JMP callbackasm1(SB)
+ MOV $72, X7
+ JMP callbackasm1(SB)
+ MOV $73, X7
+ JMP callbackasm1(SB)
+ MOV $74, X7
+ JMP callbackasm1(SB)
+ MOV $75, X7
+ JMP callbackasm1(SB)
+ MOV $76, X7
+ JMP callbackasm1(SB)
+ MOV $77, X7
+ JMP callbackasm1(SB)
+ MOV $78, X7
+ JMP callbackasm1(SB)
+ MOV $79, X7
+ JMP callbackasm1(SB)
+ MOV $80, X7
+ JMP callbackasm1(SB)
+ MOV $81, X7
+ JMP callbackasm1(SB)
+ MOV $82, X7
+ JMP callbackasm1(SB)
+ MOV $83, X7
+ JMP callbackasm1(SB)
+ MOV $84, X7
+ JMP callbackasm1(SB)
+ MOV $85, X7
+ JMP callbackasm1(SB)
+ MOV $86, X7
+ JMP callbackasm1(SB)
+ MOV $87, X7
+ JMP callbackasm1(SB)
+ MOV $88, X7
+ JMP callbackasm1(SB)
+ MOV $89, X7
+ JMP callbackasm1(SB)
+ MOV $90, X7
+ JMP callbackasm1(SB)
+ MOV $91, X7
+ JMP callbackasm1(SB)
+ MOV $92, X7
+ JMP callbackasm1(SB)
+ MOV $93, X7
+ JMP callbackasm1(SB)
+ MOV $94, X7
+ JMP callbackasm1(SB)
+ MOV $95, X7
+ JMP callbackasm1(SB)
+ MOV $96, X7
+ JMP callbackasm1(SB)
+ MOV $97, X7
+ JMP callbackasm1(SB)
+ MOV $98, X7
+ JMP callbackasm1(SB)
+ MOV $99, X7
+ JMP callbackasm1(SB)
+ MOV $100, X7
+ JMP callbackasm1(SB)
+ MOV $101, X7
+ JMP callbackasm1(SB)
+ MOV $102, X7
+ JMP callbackasm1(SB)
+ MOV $103, X7
+ JMP callbackasm1(SB)
+ MOV $104, X7
+ JMP callbackasm1(SB)
+ MOV $105, X7
+ JMP callbackasm1(SB)
+ MOV $106, X7
+ JMP callbackasm1(SB)
+ MOV $107, X7
+ JMP callbackasm1(SB)
+ MOV $108, X7
+ JMP callbackasm1(SB)
+ MOV $109, X7
+ JMP callbackasm1(SB)
+ MOV $110, X7
+ JMP callbackasm1(SB)
+ MOV $111, X7
+ JMP callbackasm1(SB)
+ MOV $112, X7
+ JMP callbackasm1(SB)
+ MOV $113, X7
+ JMP callbackasm1(SB)
+ MOV $114, X7
+ JMP callbackasm1(SB)
+ MOV $115, X7
+ JMP callbackasm1(SB)
+ MOV $116, X7
+ JMP callbackasm1(SB)
+ MOV $117, X7
+ JMP callbackasm1(SB)
+ MOV $118, X7
+ JMP callbackasm1(SB)
+ MOV $119, X7
+ JMP callbackasm1(SB)
+ MOV $120, X7
+ JMP callbackasm1(SB)
+ MOV $121, X7
+ JMP callbackasm1(SB)
+ MOV $122, X7
+ JMP callbackasm1(SB)
+ MOV $123, X7
+ JMP callbackasm1(SB)
+ MOV $124, X7
+ JMP callbackasm1(SB)
+ MOV $125, X7
+ JMP callbackasm1(SB)
+ MOV $126, X7
+ JMP callbackasm1(SB)
+ MOV $127, X7
+ JMP callbackasm1(SB)
+ MOV $128, X7
+ JMP callbackasm1(SB)
+ MOV $129, X7
+ JMP callbackasm1(SB)
+ MOV $130, X7
+ JMP callbackasm1(SB)
+ MOV $131, X7
+ JMP callbackasm1(SB)
+ MOV $132, X7
+ JMP callbackasm1(SB)
+ MOV $133, X7
+ JMP callbackasm1(SB)
+ MOV $134, X7
+ JMP callbackasm1(SB)
+ MOV $135, X7
+ JMP callbackasm1(SB)
+ MOV $136, X7
+ JMP callbackasm1(SB)
+ MOV $137, X7
+ JMP callbackasm1(SB)
+ MOV $138, X7
+ JMP callbackasm1(SB)
+ MOV $139, X7
+ JMP callbackasm1(SB)
+ MOV $140, X7
+ JMP callbackasm1(SB)
+ MOV $141, X7
+ JMP callbackasm1(SB)
+ MOV $142, X7
+ JMP callbackasm1(SB)
+ MOV $143, X7
+ JMP callbackasm1(SB)
+ MOV $144, X7
+ JMP callbackasm1(SB)
+ MOV $145, X7
+ JMP callbackasm1(SB)
+ MOV $146, X7
+ JMP callbackasm1(SB)
+ MOV $147, X7
+ JMP callbackasm1(SB)
+ MOV $148, X7
+ JMP callbackasm1(SB)
+ MOV $149, X7
+ JMP callbackasm1(SB)
+ MOV $150, X7
+ JMP callbackasm1(SB)
+ MOV $151, X7
+ JMP callbackasm1(SB)
+ MOV $152, X7
+ JMP callbackasm1(SB)
+ MOV $153, X7
+ JMP callbackasm1(SB)
+ MOV $154, X7
+ JMP callbackasm1(SB)
+ MOV $155, X7
+ JMP callbackasm1(SB)
+ MOV $156, X7
+ JMP callbackasm1(SB)
+ MOV $157, X7
+ JMP callbackasm1(SB)
+ MOV $158, X7
+ JMP callbackasm1(SB)
+ MOV $159, X7
+ JMP callbackasm1(SB)
+ MOV $160, X7
+ JMP callbackasm1(SB)
+ MOV $161, X7
+ JMP callbackasm1(SB)
+ MOV $162, X7
+ JMP callbackasm1(SB)
+ MOV $163, X7
+ JMP callbackasm1(SB)
+ MOV $164, X7
+ JMP callbackasm1(SB)
+ MOV $165, X7
+ JMP callbackasm1(SB)
+ MOV $166, X7
+ JMP callbackasm1(SB)
+ MOV $167, X7
+ JMP callbackasm1(SB)
+ MOV $168, X7
+ JMP callbackasm1(SB)
+ MOV $169, X7
+ JMP callbackasm1(SB)
+ MOV $170, X7
+ JMP callbackasm1(SB)
+ MOV $171, X7
+ JMP callbackasm1(SB)
+ MOV $172, X7
+ JMP callbackasm1(SB)
+ MOV $173, X7
+ JMP callbackasm1(SB)
+ MOV $174, X7
+ JMP callbackasm1(SB)
+ MOV $175, X7
+ JMP callbackasm1(SB)
+ MOV $176, X7
+ JMP callbackasm1(SB)
+ MOV $177, X7
+ JMP callbackasm1(SB)
+ MOV $178, X7
+ JMP callbackasm1(SB)
+ MOV $179, X7
+ JMP callbackasm1(SB)
+ MOV $180, X7
+ JMP callbackasm1(SB)
+ MOV $181, X7
+ JMP callbackasm1(SB)
+ MOV $182, X7
+ JMP callbackasm1(SB)
+ MOV $183, X7
+ JMP callbackasm1(SB)
+ MOV $184, X7
+ JMP callbackasm1(SB)
+ MOV $185, X7
+ JMP callbackasm1(SB)
+ MOV $186, X7
+ JMP callbackasm1(SB)
+ MOV $187, X7
+ JMP callbackasm1(SB)
+ MOV $188, X7
+ JMP callbackasm1(SB)
+ MOV $189, X7
+ JMP callbackasm1(SB)
+ MOV $190, X7
+ JMP callbackasm1(SB)
+ MOV $191, X7
+ JMP callbackasm1(SB)
+ MOV $192, X7
+ JMP callbackasm1(SB)
+ MOV $193, X7
+ JMP callbackasm1(SB)
+ MOV $194, X7
+ JMP callbackasm1(SB)
+ MOV $195, X7
+ JMP callbackasm1(SB)
+ MOV $196, X7
+ JMP callbackasm1(SB)
+ MOV $197, X7
+ JMP callbackasm1(SB)
+ MOV $198, X7
+ JMP callbackasm1(SB)
+ MOV $199, X7
+ JMP callbackasm1(SB)
+ MOV $200, X7
+ JMP callbackasm1(SB)
+ MOV $201, X7
+ JMP callbackasm1(SB)
+ MOV $202, X7
+ JMP callbackasm1(SB)
+ MOV $203, X7
+ JMP callbackasm1(SB)
+ MOV $204, X7
+ JMP callbackasm1(SB)
+ MOV $205, X7
+ JMP callbackasm1(SB)
+ MOV $206, X7
+ JMP callbackasm1(SB)
+ MOV $207, X7
+ JMP callbackasm1(SB)
+ MOV $208, X7
+ JMP callbackasm1(SB)
+ MOV $209, X7
+ JMP callbackasm1(SB)
+ MOV $210, X7
+ JMP callbackasm1(SB)
+ MOV $211, X7
+ JMP callbackasm1(SB)
+ MOV $212, X7
+ JMP callbackasm1(SB)
+ MOV $213, X7
+ JMP callbackasm1(SB)
+ MOV $214, X7
+ JMP callbackasm1(SB)
+ MOV $215, X7
+ JMP callbackasm1(SB)
+ MOV $216, X7
+ JMP callbackasm1(SB)
+ MOV $217, X7
+ JMP callbackasm1(SB)
+ MOV $218, X7
+ JMP callbackasm1(SB)
+ MOV $219, X7
+ JMP callbackasm1(SB)
+ MOV $220, X7
+ JMP callbackasm1(SB)
+ MOV $221, X7
+ JMP callbackasm1(SB)
+ MOV $222, X7
+ JMP callbackasm1(SB)
+ MOV $223, X7
+ JMP callbackasm1(SB)
+ MOV $224, X7
+ JMP callbackasm1(SB)
+ MOV $225, X7
+ JMP callbackasm1(SB)
+ MOV $226, X7
+ JMP callbackasm1(SB)
+ MOV $227, X7
+ JMP callbackasm1(SB)
+ MOV $228, X7
+ JMP callbackasm1(SB)
+ MOV $229, X7
+ JMP callbackasm1(SB)
+ MOV $230, X7
+ JMP callbackasm1(SB)
+ MOV $231, X7
+ JMP callbackasm1(SB)
+ MOV $232, X7
+ JMP callbackasm1(SB)
+ MOV $233, X7
+ JMP callbackasm1(SB)
+ MOV $234, X7
+ JMP callbackasm1(SB)
+ MOV $235, X7
+ JMP callbackasm1(SB)
+ MOV $236, X7
+ JMP callbackasm1(SB)
+ MOV $237, X7
+ JMP callbackasm1(SB)
+ MOV $238, X7
+ JMP callbackasm1(SB)
+ MOV $239, X7
+ JMP callbackasm1(SB)
+ MOV $240, X7
+ JMP callbackasm1(SB)
+ MOV $241, X7
+ JMP callbackasm1(SB)
+ MOV $242, X7
+ JMP callbackasm1(SB)
+ MOV $243, X7
+ JMP callbackasm1(SB)
+ MOV $244, X7
+ JMP callbackasm1(SB)
+ MOV $245, X7
+ JMP callbackasm1(SB)
+ MOV $246, X7
+ JMP callbackasm1(SB)
+ MOV $247, X7
+ JMP callbackasm1(SB)
+ MOV $248, X7
+ JMP callbackasm1(SB)
+ MOV $249, X7
+ JMP callbackasm1(SB)
+ MOV $250, X7
+ JMP callbackasm1(SB)
+ MOV $251, X7
+ JMP callbackasm1(SB)
+ MOV $252, X7
+ JMP callbackasm1(SB)
+ MOV $253, X7
+ JMP callbackasm1(SB)
+ MOV $254, X7
+ JMP callbackasm1(SB)
+ MOV $255, X7
+ JMP callbackasm1(SB)
+ MOV $256, X7
+ JMP callbackasm1(SB)
+ MOV $257, X7
+ JMP callbackasm1(SB)
+ MOV $258, X7
+ JMP callbackasm1(SB)
+ MOV $259, X7
+ JMP callbackasm1(SB)
+ MOV $260, X7
+ JMP callbackasm1(SB)
+ MOV $261, X7
+ JMP callbackasm1(SB)
+ MOV $262, X7
+ JMP callbackasm1(SB)
+ MOV $263, X7
+ JMP callbackasm1(SB)
+ MOV $264, X7
+ JMP callbackasm1(SB)
+ MOV $265, X7
+ JMP callbackasm1(SB)
+ MOV $266, X7
+ JMP callbackasm1(SB)
+ MOV $267, X7
+ JMP callbackasm1(SB)
+ MOV $268, X7
+ JMP callbackasm1(SB)
+ MOV $269, X7
+ JMP callbackasm1(SB)
+ MOV $270, X7
+ JMP callbackasm1(SB)
+ MOV $271, X7
+ JMP callbackasm1(SB)
+ MOV $272, X7
+ JMP callbackasm1(SB)
+ MOV $273, X7
+ JMP callbackasm1(SB)
+ MOV $274, X7
+ JMP callbackasm1(SB)
+ MOV $275, X7
+ JMP callbackasm1(SB)
+ MOV $276, X7
+ JMP callbackasm1(SB)
+ MOV $277, X7
+ JMP callbackasm1(SB)
+ MOV $278, X7
+ JMP callbackasm1(SB)
+ MOV $279, X7
+ JMP callbackasm1(SB)
+ MOV $280, X7
+ JMP callbackasm1(SB)
+ MOV $281, X7
+ JMP callbackasm1(SB)
+ MOV $282, X7
+ JMP callbackasm1(SB)
+ MOV $283, X7
+ JMP callbackasm1(SB)
+ MOV $284, X7
+ JMP callbackasm1(SB)
+ MOV $285, X7
+ JMP callbackasm1(SB)
+ MOV $286, X7
+ JMP callbackasm1(SB)
+ MOV $287, X7
+ JMP callbackasm1(SB)
+ MOV $288, X7
+ JMP callbackasm1(SB)
+ MOV $289, X7
+ JMP callbackasm1(SB)
+ MOV $290, X7
+ JMP callbackasm1(SB)
+ MOV $291, X7
+ JMP callbackasm1(SB)
+ MOV $292, X7
+ JMP callbackasm1(SB)
+ MOV $293, X7
+ JMP callbackasm1(SB)
+ MOV $294, X7
+ JMP callbackasm1(SB)
+ MOV $295, X7
+ JMP callbackasm1(SB)
+ MOV $296, X7
+ JMP callbackasm1(SB)
+ MOV $297, X7
+ JMP callbackasm1(SB)
+ MOV $298, X7
+ JMP callbackasm1(SB)
+ MOV $299, X7
+ JMP callbackasm1(SB)
+ MOV $300, X7
+ JMP callbackasm1(SB)
+ MOV $301, X7
+ JMP callbackasm1(SB)
+ MOV $302, X7
+ JMP callbackasm1(SB)
+ MOV $303, X7
+ JMP callbackasm1(SB)
+ MOV $304, X7
+ JMP callbackasm1(SB)
+ MOV $305, X7
+ JMP callbackasm1(SB)
+ MOV $306, X7
+ JMP callbackasm1(SB)
+ MOV $307, X7
+ JMP callbackasm1(SB)
+ MOV $308, X7
+ JMP callbackasm1(SB)
+ MOV $309, X7
+ JMP callbackasm1(SB)
+ MOV $310, X7
+ JMP callbackasm1(SB)
+ MOV $311, X7
+ JMP callbackasm1(SB)
+ MOV $312, X7
+ JMP callbackasm1(SB)
+ MOV $313, X7
+ JMP callbackasm1(SB)
+ MOV $314, X7
+ JMP callbackasm1(SB)
+ MOV $315, X7
+ JMP callbackasm1(SB)
+ MOV $316, X7
+ JMP callbackasm1(SB)
+ MOV $317, X7
+ JMP callbackasm1(SB)
+ MOV $318, X7
+ JMP callbackasm1(SB)
+ MOV $319, X7
+ JMP callbackasm1(SB)
+ MOV $320, X7
+ JMP callbackasm1(SB)
+ MOV $321, X7
+ JMP callbackasm1(SB)
+ MOV $322, X7
+ JMP callbackasm1(SB)
+ MOV $323, X7
+ JMP callbackasm1(SB)
+ MOV $324, X7
+ JMP callbackasm1(SB)
+ MOV $325, X7
+ JMP callbackasm1(SB)
+ MOV $326, X7
+ JMP callbackasm1(SB)
+ MOV $327, X7
+ JMP callbackasm1(SB)
+ MOV $328, X7
+ JMP callbackasm1(SB)
+ MOV $329, X7
+ JMP callbackasm1(SB)
+ MOV $330, X7
+ JMP callbackasm1(SB)
+ MOV $331, X7
+ JMP callbackasm1(SB)
+ MOV $332, X7
+ JMP callbackasm1(SB)
+ MOV $333, X7
+ JMP callbackasm1(SB)
+ MOV $334, X7
+ JMP callbackasm1(SB)
+ MOV $335, X7
+ JMP callbackasm1(SB)
+ MOV $336, X7
+ JMP callbackasm1(SB)
+ MOV $337, X7
+ JMP callbackasm1(SB)
+ MOV $338, X7
+ JMP callbackasm1(SB)
+ MOV $339, X7
+ JMP callbackasm1(SB)
+ MOV $340, X7
+ JMP callbackasm1(SB)
+ MOV $341, X7
+ JMP callbackasm1(SB)
+ MOV $342, X7
+ JMP callbackasm1(SB)
+ MOV $343, X7
+ JMP callbackasm1(SB)
+ MOV $344, X7
+ JMP callbackasm1(SB)
+ MOV $345, X7
+ JMP callbackasm1(SB)
+ MOV $346, X7
+ JMP callbackasm1(SB)
+ MOV $347, X7
+ JMP callbackasm1(SB)
+ MOV $348, X7
+ JMP callbackasm1(SB)
+ MOV $349, X7
+ JMP callbackasm1(SB)
+ MOV $350, X7
+ JMP callbackasm1(SB)
+ MOV $351, X7
+ JMP callbackasm1(SB)
+ MOV $352, X7
+ JMP callbackasm1(SB)
+ MOV $353, X7
+ JMP callbackasm1(SB)
+ MOV $354, X7
+ JMP callbackasm1(SB)
+ MOV $355, X7
+ JMP callbackasm1(SB)
+ MOV $356, X7
+ JMP callbackasm1(SB)
+ MOV $357, X7
+ JMP callbackasm1(SB)
+ MOV $358, X7
+ JMP callbackasm1(SB)
+ MOV $359, X7
+ JMP callbackasm1(SB)
+ MOV $360, X7
+ JMP callbackasm1(SB)
+ MOV $361, X7
+ JMP callbackasm1(SB)
+ MOV $362, X7
+ JMP callbackasm1(SB)
+ MOV $363, X7
+ JMP callbackasm1(SB)
+ MOV $364, X7
+ JMP callbackasm1(SB)
+ MOV $365, X7
+ JMP callbackasm1(SB)
+ MOV $366, X7
+ JMP callbackasm1(SB)
+ MOV $367, X7
+ JMP callbackasm1(SB)
+ MOV $368, X7
+ JMP callbackasm1(SB)
+ MOV $369, X7
+ JMP callbackasm1(SB)
+ MOV $370, X7
+ JMP callbackasm1(SB)
+ MOV $371, X7
+ JMP callbackasm1(SB)
+ MOV $372, X7
+ JMP callbackasm1(SB)
+ MOV $373, X7
+ JMP callbackasm1(SB)
+ MOV $374, X7
+ JMP callbackasm1(SB)
+ MOV $375, X7
+ JMP callbackasm1(SB)
+ MOV $376, X7
+ JMP callbackasm1(SB)
+ MOV $377, X7
+ JMP callbackasm1(SB)
+ MOV $378, X7
+ JMP callbackasm1(SB)
+ MOV $379, X7
+ JMP callbackasm1(SB)
+ MOV $380, X7
+ JMP callbackasm1(SB)
+ MOV $381, X7
+ JMP callbackasm1(SB)
+ MOV $382, X7
+ JMP callbackasm1(SB)
+ MOV $383, X7
+ JMP callbackasm1(SB)
+ MOV $384, X7
+ JMP callbackasm1(SB)
+ MOV $385, X7
+ JMP callbackasm1(SB)
+ MOV $386, X7
+ JMP callbackasm1(SB)
+ MOV $387, X7
+ JMP callbackasm1(SB)
+ MOV $388, X7
+ JMP callbackasm1(SB)
+ MOV $389, X7
+ JMP callbackasm1(SB)
+ MOV $390, X7
+ JMP callbackasm1(SB)
+ MOV $391, X7
+ JMP callbackasm1(SB)
+ MOV $392, X7
+ JMP callbackasm1(SB)
+ MOV $393, X7
+ JMP callbackasm1(SB)
+ MOV $394, X7
+ JMP callbackasm1(SB)
+ MOV $395, X7
+ JMP callbackasm1(SB)
+ MOV $396, X7
+ JMP callbackasm1(SB)
+ MOV $397, X7
+ JMP callbackasm1(SB)
+ MOV $398, X7
+ JMP callbackasm1(SB)
+ MOV $399, X7
+ JMP callbackasm1(SB)
+ MOV $400, X7
+ JMP callbackasm1(SB)
+ MOV $401, X7
+ JMP callbackasm1(SB)
+ MOV $402, X7
+ JMP callbackasm1(SB)
+ MOV $403, X7
+ JMP callbackasm1(SB)
+ MOV $404, X7
+ JMP callbackasm1(SB)
+ MOV $405, X7
+ JMP callbackasm1(SB)
+ MOV $406, X7
+ JMP callbackasm1(SB)
+ MOV $407, X7
+ JMP callbackasm1(SB)
+ MOV $408, X7
+ JMP callbackasm1(SB)
+ MOV $409, X7
+ JMP callbackasm1(SB)
+ MOV $410, X7
+ JMP callbackasm1(SB)
+ MOV $411, X7
+ JMP callbackasm1(SB)
+ MOV $412, X7
+ JMP callbackasm1(SB)
+ MOV $413, X7
+ JMP callbackasm1(SB)
+ MOV $414, X7
+ JMP callbackasm1(SB)
+ MOV $415, X7
+ JMP callbackasm1(SB)
+ MOV $416, X7
+ JMP callbackasm1(SB)
+ MOV $417, X7
+ JMP callbackasm1(SB)
+ MOV $418, X7
+ JMP callbackasm1(SB)
+ MOV $419, X7
+ JMP callbackasm1(SB)
+ MOV $420, X7
+ JMP callbackasm1(SB)
+ MOV $421, X7
+ JMP callbackasm1(SB)
+ MOV $422, X7
+ JMP callbackasm1(SB)
+ MOV $423, X7
+ JMP callbackasm1(SB)
+ MOV $424, X7
+ JMP callbackasm1(SB)
+ MOV $425, X7
+ JMP callbackasm1(SB)
+ MOV $426, X7
+ JMP callbackasm1(SB)
+ MOV $427, X7
+ JMP callbackasm1(SB)
+ MOV $428, X7
+ JMP callbackasm1(SB)
+ MOV $429, X7
+ JMP callbackasm1(SB)
+ MOV $430, X7
+ JMP callbackasm1(SB)
+ MOV $431, X7
+ JMP callbackasm1(SB)
+ MOV $432, X7
+ JMP callbackasm1(SB)
+ MOV $433, X7
+ JMP callbackasm1(SB)
+ MOV $434, X7
+ JMP callbackasm1(SB)
+ MOV $435, X7
+ JMP callbackasm1(SB)
+ MOV $436, X7
+ JMP callbackasm1(SB)
+ MOV $437, X7
+ JMP callbackasm1(SB)
+ MOV $438, X7
+ JMP callbackasm1(SB)
+ MOV $439, X7
+ JMP callbackasm1(SB)
+ MOV $440, X7
+ JMP callbackasm1(SB)
+ MOV $441, X7
+ JMP callbackasm1(SB)
+ MOV $442, X7
+ JMP callbackasm1(SB)
+ MOV $443, X7
+ JMP callbackasm1(SB)
+ MOV $444, X7
+ JMP callbackasm1(SB)
+ MOV $445, X7
+ JMP callbackasm1(SB)
+ MOV $446, X7
+ JMP callbackasm1(SB)
+ MOV $447, X7
+ JMP callbackasm1(SB)
+ MOV $448, X7
+ JMP callbackasm1(SB)
+ MOV $449, X7
+ JMP callbackasm1(SB)
+ MOV $450, X7
+ JMP callbackasm1(SB)
+ MOV $451, X7
+ JMP callbackasm1(SB)
+ MOV $452, X7
+ JMP callbackasm1(SB)
+ MOV $453, X7
+ JMP callbackasm1(SB)
+ MOV $454, X7
+ JMP callbackasm1(SB)
+ MOV $455, X7
+ JMP callbackasm1(SB)
+ MOV $456, X7
+ JMP callbackasm1(SB)
+ MOV $457, X7
+ JMP callbackasm1(SB)
+ MOV $458, X7
+ JMP callbackasm1(SB)
+ MOV $459, X7
+ JMP callbackasm1(SB)
+ MOV $460, X7
+ JMP callbackasm1(SB)
+ MOV $461, X7
+ JMP callbackasm1(SB)
+ MOV $462, X7
+ JMP callbackasm1(SB)
+ MOV $463, X7
+ JMP callbackasm1(SB)
+ MOV $464, X7
+ JMP callbackasm1(SB)
+ MOV $465, X7
+ JMP callbackasm1(SB)
+ MOV $466, X7
+ JMP callbackasm1(SB)
+ MOV $467, X7
+ JMP callbackasm1(SB)
+ MOV $468, X7
+ JMP callbackasm1(SB)
+ MOV $469, X7
+ JMP callbackasm1(SB)
+ MOV $470, X7
+ JMP callbackasm1(SB)
+ MOV $471, X7
+ JMP callbackasm1(SB)
+ MOV $472, X7
+ JMP callbackasm1(SB)
+ MOV $473, X7
+ JMP callbackasm1(SB)
+ MOV $474, X7
+ JMP callbackasm1(SB)
+ MOV $475, X7
+ JMP callbackasm1(SB)
+ MOV $476, X7
+ JMP callbackasm1(SB)
+ MOV $477, X7
+ JMP callbackasm1(SB)
+ MOV $478, X7
+ JMP callbackasm1(SB)
+ MOV $479, X7
+ JMP callbackasm1(SB)
+ MOV $480, X7
+ JMP callbackasm1(SB)
+ MOV $481, X7
+ JMP callbackasm1(SB)
+ MOV $482, X7
+ JMP callbackasm1(SB)
+ MOV $483, X7
+ JMP callbackasm1(SB)
+ MOV $484, X7
+ JMP callbackasm1(SB)
+ MOV $485, X7
+ JMP callbackasm1(SB)
+ MOV $486, X7
+ JMP callbackasm1(SB)
+ MOV $487, X7
+ JMP callbackasm1(SB)
+ MOV $488, X7
+ JMP callbackasm1(SB)
+ MOV $489, X7
+ JMP callbackasm1(SB)
+ MOV $490, X7
+ JMP callbackasm1(SB)
+ MOV $491, X7
+ JMP callbackasm1(SB)
+ MOV $492, X7
+ JMP callbackasm1(SB)
+ MOV $493, X7
+ JMP callbackasm1(SB)
+ MOV $494, X7
+ JMP callbackasm1(SB)
+ MOV $495, X7
+ JMP callbackasm1(SB)
+ MOV $496, X7
+ JMP callbackasm1(SB)
+ MOV $497, X7
+ JMP callbackasm1(SB)
+ MOV $498, X7
+ JMP callbackasm1(SB)
+ MOV $499, X7
+ JMP callbackasm1(SB)
+ MOV $500, X7
+ JMP callbackasm1(SB)
+ MOV $501, X7
+ JMP callbackasm1(SB)
+ MOV $502, X7
+ JMP callbackasm1(SB)
+ MOV $503, X7
+ JMP callbackasm1(SB)
+ MOV $504, X7
+ JMP callbackasm1(SB)
+ MOV $505, X7
+ JMP callbackasm1(SB)
+ MOV $506, X7
+ JMP callbackasm1(SB)
+ MOV $507, X7
+ JMP callbackasm1(SB)
+ MOV $508, X7
+ JMP callbackasm1(SB)
+ MOV $509, X7
+ JMP callbackasm1(SB)
+ MOV $510, X7
+ JMP callbackasm1(SB)
+ MOV $511, X7
+ JMP callbackasm1(SB)
+ MOV $512, X7
+ JMP callbackasm1(SB)
+ MOV $513, X7
+ JMP callbackasm1(SB)
+ MOV $514, X7
+ JMP callbackasm1(SB)
+ MOV $515, X7
+ JMP callbackasm1(SB)
+ MOV $516, X7
+ JMP callbackasm1(SB)
+ MOV $517, X7
+ JMP callbackasm1(SB)
+ MOV $518, X7
+ JMP callbackasm1(SB)
+ MOV $519, X7
+ JMP callbackasm1(SB)
+ MOV $520, X7
+ JMP callbackasm1(SB)
+ MOV $521, X7
+ JMP callbackasm1(SB)
+ MOV $522, X7
+ JMP callbackasm1(SB)
+ MOV $523, X7
+ JMP callbackasm1(SB)
+ MOV $524, X7
+ JMP callbackasm1(SB)
+ MOV $525, X7
+ JMP callbackasm1(SB)
+ MOV $526, X7
+ JMP callbackasm1(SB)
+ MOV $527, X7
+ JMP callbackasm1(SB)
+ MOV $528, X7
+ JMP callbackasm1(SB)
+ MOV $529, X7
+ JMP callbackasm1(SB)
+ MOV $530, X7
+ JMP callbackasm1(SB)
+ MOV $531, X7
+ JMP callbackasm1(SB)
+ MOV $532, X7
+ JMP callbackasm1(SB)
+ MOV $533, X7
+ JMP callbackasm1(SB)
+ MOV $534, X7
+ JMP callbackasm1(SB)
+ MOV $535, X7
+ JMP callbackasm1(SB)
+ MOV $536, X7
+ JMP callbackasm1(SB)
+ MOV $537, X7
+ JMP callbackasm1(SB)
+ MOV $538, X7
+ JMP callbackasm1(SB)
+ MOV $539, X7
+ JMP callbackasm1(SB)
+ MOV $540, X7
+ JMP callbackasm1(SB)
+ MOV $541, X7
+ JMP callbackasm1(SB)
+ MOV $542, X7
+ JMP callbackasm1(SB)
+ MOV $543, X7
+ JMP callbackasm1(SB)
+ MOV $544, X7
+ JMP callbackasm1(SB)
+ MOV $545, X7
+ JMP callbackasm1(SB)
+ MOV $546, X7
+ JMP callbackasm1(SB)
+ MOV $547, X7
+ JMP callbackasm1(SB)
+ MOV $548, X7
+ JMP callbackasm1(SB)
+ MOV $549, X7
+ JMP callbackasm1(SB)
+ MOV $550, X7
+ JMP callbackasm1(SB)
+ MOV $551, X7
+ JMP callbackasm1(SB)
+ MOV $552, X7
+ JMP callbackasm1(SB)
+ MOV $553, X7
+ JMP callbackasm1(SB)
+ MOV $554, X7
+ JMP callbackasm1(SB)
+ MOV $555, X7
+ JMP callbackasm1(SB)
+ MOV $556, X7
+ JMP callbackasm1(SB)
+ MOV $557, X7
+ JMP callbackasm1(SB)
+ MOV $558, X7
+ JMP callbackasm1(SB)
+ MOV $559, X7
+ JMP callbackasm1(SB)
+ MOV $560, X7
+ JMP callbackasm1(SB)
+ MOV $561, X7
+ JMP callbackasm1(SB)
+ MOV $562, X7
+ JMP callbackasm1(SB)
+ MOV $563, X7
+ JMP callbackasm1(SB)
+ MOV $564, X7
+ JMP callbackasm1(SB)
+ MOV $565, X7
+ JMP callbackasm1(SB)
+ MOV $566, X7
+ JMP callbackasm1(SB)
+ MOV $567, X7
+ JMP callbackasm1(SB)
+ MOV $568, X7
+ JMP callbackasm1(SB)
+ MOV $569, X7
+ JMP callbackasm1(SB)
+ MOV $570, X7
+ JMP callbackasm1(SB)
+ MOV $571, X7
+ JMP callbackasm1(SB)
+ MOV $572, X7
+ JMP callbackasm1(SB)
+ MOV $573, X7
+ JMP callbackasm1(SB)
+ MOV $574, X7
+ JMP callbackasm1(SB)
+ MOV $575, X7
+ JMP callbackasm1(SB)
+ MOV $576, X7
+ JMP callbackasm1(SB)
+ MOV $577, X7
+ JMP callbackasm1(SB)
+ MOV $578, X7
+ JMP callbackasm1(SB)
+ MOV $579, X7
+ JMP callbackasm1(SB)
+ MOV $580, X7
+ JMP callbackasm1(SB)
+ MOV $581, X7
+ JMP callbackasm1(SB)
+ MOV $582, X7
+ JMP callbackasm1(SB)
+ MOV $583, X7
+ JMP callbackasm1(SB)
+ MOV $584, X7
+ JMP callbackasm1(SB)
+ MOV $585, X7
+ JMP callbackasm1(SB)
+ MOV $586, X7
+ JMP callbackasm1(SB)
+ MOV $587, X7
+ JMP callbackasm1(SB)
+ MOV $588, X7
+ JMP callbackasm1(SB)
+ MOV $589, X7
+ JMP callbackasm1(SB)
+ MOV $590, X7
+ JMP callbackasm1(SB)
+ MOV $591, X7
+ JMP callbackasm1(SB)
+ MOV $592, X7
+ JMP callbackasm1(SB)
+ MOV $593, X7
+ JMP callbackasm1(SB)
+ MOV $594, X7
+ JMP callbackasm1(SB)
+ MOV $595, X7
+ JMP callbackasm1(SB)
+ MOV $596, X7
+ JMP callbackasm1(SB)
+ MOV $597, X7
+ JMP callbackasm1(SB)
+ MOV $598, X7
+ JMP callbackasm1(SB)
+ MOV $599, X7
+ JMP callbackasm1(SB)
+ MOV $600, X7
+ JMP callbackasm1(SB)
+ MOV $601, X7
+ JMP callbackasm1(SB)
+ MOV $602, X7
+ JMP callbackasm1(SB)
+ MOV $603, X7
+ JMP callbackasm1(SB)
+ MOV $604, X7
+ JMP callbackasm1(SB)
+ MOV $605, X7
+ JMP callbackasm1(SB)
+ MOV $606, X7
+ JMP callbackasm1(SB)
+ MOV $607, X7
+ JMP callbackasm1(SB)
+ MOV $608, X7
+ JMP callbackasm1(SB)
+ MOV $609, X7
+ JMP callbackasm1(SB)
+ MOV $610, X7
+ JMP callbackasm1(SB)
+ MOV $611, X7
+ JMP callbackasm1(SB)
+ MOV $612, X7
+ JMP callbackasm1(SB)
+ MOV $613, X7
+ JMP callbackasm1(SB)
+ MOV $614, X7
+ JMP callbackasm1(SB)
+ MOV $615, X7
+ JMP callbackasm1(SB)
+ MOV $616, X7
+ JMP callbackasm1(SB)
+ MOV $617, X7
+ JMP callbackasm1(SB)
+ MOV $618, X7
+ JMP callbackasm1(SB)
+ MOV $619, X7
+ JMP callbackasm1(SB)
+ MOV $620, X7
+ JMP callbackasm1(SB)
+ MOV $621, X7
+ JMP callbackasm1(SB)
+ MOV $622, X7
+ JMP callbackasm1(SB)
+ MOV $623, X7
+ JMP callbackasm1(SB)
+ MOV $624, X7
+ JMP callbackasm1(SB)
+ MOV $625, X7
+ JMP callbackasm1(SB)
+ MOV $626, X7
+ JMP callbackasm1(SB)
+ MOV $627, X7
+ JMP callbackasm1(SB)
+ MOV $628, X7
+ JMP callbackasm1(SB)
+ MOV $629, X7
+ JMP callbackasm1(SB)
+ MOV $630, X7
+ JMP callbackasm1(SB)
+ MOV $631, X7
+ JMP callbackasm1(SB)
+ MOV $632, X7
+ JMP callbackasm1(SB)
+ MOV $633, X7
+ JMP callbackasm1(SB)
+ MOV $634, X7
+ JMP callbackasm1(SB)
+ MOV $635, X7
+ JMP callbackasm1(SB)
+ MOV $636, X7
+ JMP callbackasm1(SB)
+ MOV $637, X7
+ JMP callbackasm1(SB)
+ MOV $638, X7
+ JMP callbackasm1(SB)
+ MOV $639, X7
+ JMP callbackasm1(SB)
+ MOV $640, X7
+ JMP callbackasm1(SB)
+ MOV $641, X7
+ JMP callbackasm1(SB)
+ MOV $642, X7
+ JMP callbackasm1(SB)
+ MOV $643, X7
+ JMP callbackasm1(SB)
+ MOV $644, X7
+ JMP callbackasm1(SB)
+ MOV $645, X7
+ JMP callbackasm1(SB)
+ MOV $646, X7
+ JMP callbackasm1(SB)
+ MOV $647, X7
+ JMP callbackasm1(SB)
+ MOV $648, X7
+ JMP callbackasm1(SB)
+ MOV $649, X7
+ JMP callbackasm1(SB)
+ MOV $650, X7
+ JMP callbackasm1(SB)
+ MOV $651, X7
+ JMP callbackasm1(SB)
+ MOV $652, X7
+ JMP callbackasm1(SB)
+ MOV $653, X7
+ JMP callbackasm1(SB)
+ MOV $654, X7
+ JMP callbackasm1(SB)
+ MOV $655, X7
+ JMP callbackasm1(SB)
+ MOV $656, X7
+ JMP callbackasm1(SB)
+ MOV $657, X7
+ JMP callbackasm1(SB)
+ MOV $658, X7
+ JMP callbackasm1(SB)
+ MOV $659, X7
+ JMP callbackasm1(SB)
+ MOV $660, X7
+ JMP callbackasm1(SB)
+ MOV $661, X7
+ JMP callbackasm1(SB)
+ MOV $662, X7
+ JMP callbackasm1(SB)
+ MOV $663, X7
+ JMP callbackasm1(SB)
+ MOV $664, X7
+ JMP callbackasm1(SB)
+ MOV $665, X7
+ JMP callbackasm1(SB)
+ MOV $666, X7
+ JMP callbackasm1(SB)
+ MOV $667, X7
+ JMP callbackasm1(SB)
+ MOV $668, X7
+ JMP callbackasm1(SB)
+ MOV $669, X7
+ JMP callbackasm1(SB)
+ MOV $670, X7
+ JMP callbackasm1(SB)
+ MOV $671, X7
+ JMP callbackasm1(SB)
+ MOV $672, X7
+ JMP callbackasm1(SB)
+ MOV $673, X7
+ JMP callbackasm1(SB)
+ MOV $674, X7
+ JMP callbackasm1(SB)
+ MOV $675, X7
+ JMP callbackasm1(SB)
+ MOV $676, X7
+ JMP callbackasm1(SB)
+ MOV $677, X7
+ JMP callbackasm1(SB)
+ MOV $678, X7
+ JMP callbackasm1(SB)
+ MOV $679, X7
+ JMP callbackasm1(SB)
+ MOV $680, X7
+ JMP callbackasm1(SB)
+ MOV $681, X7
+ JMP callbackasm1(SB)
+ MOV $682, X7
+ JMP callbackasm1(SB)
+ MOV $683, X7
+ JMP callbackasm1(SB)
+ MOV $684, X7
+ JMP callbackasm1(SB)
+ MOV $685, X7
+ JMP callbackasm1(SB)
+ MOV $686, X7
+ JMP callbackasm1(SB)
+ MOV $687, X7
+ JMP callbackasm1(SB)
+ MOV $688, X7
+ JMP callbackasm1(SB)
+ MOV $689, X7
+ JMP callbackasm1(SB)
+ MOV $690, X7
+ JMP callbackasm1(SB)
+ MOV $691, X7
+ JMP callbackasm1(SB)
+ MOV $692, X7
+ JMP callbackasm1(SB)
+ MOV $693, X7
+ JMP callbackasm1(SB)
+ MOV $694, X7
+ JMP callbackasm1(SB)
+ MOV $695, X7
+ JMP callbackasm1(SB)
+ MOV $696, X7
+ JMP callbackasm1(SB)
+ MOV $697, X7
+ JMP callbackasm1(SB)
+ MOV $698, X7
+ JMP callbackasm1(SB)
+ MOV $699, X7
+ JMP callbackasm1(SB)
+ MOV $700, X7
+ JMP callbackasm1(SB)
+ MOV $701, X7
+ JMP callbackasm1(SB)
+ MOV $702, X7
+ JMP callbackasm1(SB)
+ MOV $703, X7
+ JMP callbackasm1(SB)
+ MOV $704, X7
+ JMP callbackasm1(SB)
+ MOV $705, X7
+ JMP callbackasm1(SB)
+ MOV $706, X7
+ JMP callbackasm1(SB)
+ MOV $707, X7
+ JMP callbackasm1(SB)
+ MOV $708, X7
+ JMP callbackasm1(SB)
+ MOV $709, X7
+ JMP callbackasm1(SB)
+ MOV $710, X7
+ JMP callbackasm1(SB)
+ MOV $711, X7
+ JMP callbackasm1(SB)
+ MOV $712, X7
+ JMP callbackasm1(SB)
+ MOV $713, X7
+ JMP callbackasm1(SB)
+ MOV $714, X7
+ JMP callbackasm1(SB)
+ MOV $715, X7
+ JMP callbackasm1(SB)
+ MOV $716, X7
+ JMP callbackasm1(SB)
+ MOV $717, X7
+ JMP callbackasm1(SB)
+ MOV $718, X7
+ JMP callbackasm1(SB)
+ MOV $719, X7
+ JMP callbackasm1(SB)
+ MOV $720, X7
+ JMP callbackasm1(SB)
+ MOV $721, X7
+ JMP callbackasm1(SB)
+ MOV $722, X7
+ JMP callbackasm1(SB)
+ MOV $723, X7
+ JMP callbackasm1(SB)
+ MOV $724, X7
+ JMP callbackasm1(SB)
+ MOV $725, X7
+ JMP callbackasm1(SB)
+ MOV $726, X7
+ JMP callbackasm1(SB)
+ MOV $727, X7
+ JMP callbackasm1(SB)
+ MOV $728, X7
+ JMP callbackasm1(SB)
+ MOV $729, X7
+ JMP callbackasm1(SB)
+ MOV $730, X7
+ JMP callbackasm1(SB)
+ MOV $731, X7
+ JMP callbackasm1(SB)
+ MOV $732, X7
+ JMP callbackasm1(SB)
+ MOV $733, X7
+ JMP callbackasm1(SB)
+ MOV $734, X7
+ JMP callbackasm1(SB)
+ MOV $735, X7
+ JMP callbackasm1(SB)
+ MOV $736, X7
+ JMP callbackasm1(SB)
+ MOV $737, X7
+ JMP callbackasm1(SB)
+ MOV $738, X7
+ JMP callbackasm1(SB)
+ MOV $739, X7
+ JMP callbackasm1(SB)
+ MOV $740, X7
+ JMP callbackasm1(SB)
+ MOV $741, X7
+ JMP callbackasm1(SB)
+ MOV $742, X7
+ JMP callbackasm1(SB)
+ MOV $743, X7
+ JMP callbackasm1(SB)
+ MOV $744, X7
+ JMP callbackasm1(SB)
+ MOV $745, X7
+ JMP callbackasm1(SB)
+ MOV $746, X7
+ JMP callbackasm1(SB)
+ MOV $747, X7
+ JMP callbackasm1(SB)
+ MOV $748, X7
+ JMP callbackasm1(SB)
+ MOV $749, X7
+ JMP callbackasm1(SB)
+ MOV $750, X7
+ JMP callbackasm1(SB)
+ MOV $751, X7
+ JMP callbackasm1(SB)
+ MOV $752, X7
+ JMP callbackasm1(SB)
+ MOV $753, X7
+ JMP callbackasm1(SB)
+ MOV $754, X7
+ JMP callbackasm1(SB)
+ MOV $755, X7
+ JMP callbackasm1(SB)
+ MOV $756, X7
+ JMP callbackasm1(SB)
+ MOV $757, X7
+ JMP callbackasm1(SB)
+ MOV $758, X7
+ JMP callbackasm1(SB)
+ MOV $759, X7
+ JMP callbackasm1(SB)
+ MOV $760, X7
+ JMP callbackasm1(SB)
+ MOV $761, X7
+ JMP callbackasm1(SB)
+ MOV $762, X7
+ JMP callbackasm1(SB)
+ MOV $763, X7
+ JMP callbackasm1(SB)
+ MOV $764, X7
+ JMP callbackasm1(SB)
+ MOV $765, X7
+ JMP callbackasm1(SB)
+ MOV $766, X7
+ JMP callbackasm1(SB)
+ MOV $767, X7
+ JMP callbackasm1(SB)
+ MOV $768, X7
+ JMP callbackasm1(SB)
+ MOV $769, X7
+ JMP callbackasm1(SB)
+ MOV $770, X7
+ JMP callbackasm1(SB)
+ MOV $771, X7
+ JMP callbackasm1(SB)
+ MOV $772, X7
+ JMP callbackasm1(SB)
+ MOV $773, X7
+ JMP callbackasm1(SB)
+ MOV $774, X7
+ JMP callbackasm1(SB)
+ MOV $775, X7
+ JMP callbackasm1(SB)
+ MOV $776, X7
+ JMP callbackasm1(SB)
+ MOV $777, X7
+ JMP callbackasm1(SB)
+ MOV $778, X7
+ JMP callbackasm1(SB)
+ MOV $779, X7
+ JMP callbackasm1(SB)
+ MOV $780, X7
+ JMP callbackasm1(SB)
+ MOV $781, X7
+ JMP callbackasm1(SB)
+ MOV $782, X7
+ JMP callbackasm1(SB)
+ MOV $783, X7
+ JMP callbackasm1(SB)
+ MOV $784, X7
+ JMP callbackasm1(SB)
+ MOV $785, X7
+ JMP callbackasm1(SB)
+ MOV $786, X7
+ JMP callbackasm1(SB)
+ MOV $787, X7
+ JMP callbackasm1(SB)
+ MOV $788, X7
+ JMP callbackasm1(SB)
+ MOV $789, X7
+ JMP callbackasm1(SB)
+ MOV $790, X7
+ JMP callbackasm1(SB)
+ MOV $791, X7
+ JMP callbackasm1(SB)
+ MOV $792, X7
+ JMP callbackasm1(SB)
+ MOV $793, X7
+ JMP callbackasm1(SB)
+ MOV $794, X7
+ JMP callbackasm1(SB)
+ MOV $795, X7
+ JMP callbackasm1(SB)
+ MOV $796, X7
+ JMP callbackasm1(SB)
+ MOV $797, X7
+ JMP callbackasm1(SB)
+ MOV $798, X7
+ JMP callbackasm1(SB)
+ MOV $799, X7
+ JMP callbackasm1(SB)
+ MOV $800, X7
+ JMP callbackasm1(SB)
+ MOV $801, X7
+ JMP callbackasm1(SB)
+ MOV $802, X7
+ JMP callbackasm1(SB)
+ MOV $803, X7
+ JMP callbackasm1(SB)
+ MOV $804, X7
+ JMP callbackasm1(SB)
+ MOV $805, X7
+ JMP callbackasm1(SB)
+ MOV $806, X7
+ JMP callbackasm1(SB)
+ MOV $807, X7
+ JMP callbackasm1(SB)
+ MOV $808, X7
+ JMP callbackasm1(SB)
+ MOV $809, X7
+ JMP callbackasm1(SB)
+ MOV $810, X7
+ JMP callbackasm1(SB)
+ MOV $811, X7
+ JMP callbackasm1(SB)
+ MOV $812, X7
+ JMP callbackasm1(SB)
+ MOV $813, X7
+ JMP callbackasm1(SB)
+ MOV $814, X7
+ JMP callbackasm1(SB)
+ MOV $815, X7
+ JMP callbackasm1(SB)
+ MOV $816, X7
+ JMP callbackasm1(SB)
+ MOV $817, X7
+ JMP callbackasm1(SB)
+ MOV $818, X7
+ JMP callbackasm1(SB)
+ MOV $819, X7
+ JMP callbackasm1(SB)
+ MOV $820, X7
+ JMP callbackasm1(SB)
+ MOV $821, X7
+ JMP callbackasm1(SB)
+ MOV $822, X7
+ JMP callbackasm1(SB)
+ MOV $823, X7
+ JMP callbackasm1(SB)
+ MOV $824, X7
+ JMP callbackasm1(SB)
+ MOV $825, X7
+ JMP callbackasm1(SB)
+ MOV $826, X7
+ JMP callbackasm1(SB)
+ MOV $827, X7
+ JMP callbackasm1(SB)
+ MOV $828, X7
+ JMP callbackasm1(SB)
+ MOV $829, X7
+ JMP callbackasm1(SB)
+ MOV $830, X7
+ JMP callbackasm1(SB)
+ MOV $831, X7
+ JMP callbackasm1(SB)
+ MOV $832, X7
+ JMP callbackasm1(SB)
+ MOV $833, X7
+ JMP callbackasm1(SB)
+ MOV $834, X7
+ JMP callbackasm1(SB)
+ MOV $835, X7
+ JMP callbackasm1(SB)
+ MOV $836, X7
+ JMP callbackasm1(SB)
+ MOV $837, X7
+ JMP callbackasm1(SB)
+ MOV $838, X7
+ JMP callbackasm1(SB)
+ MOV $839, X7
+ JMP callbackasm1(SB)
+ MOV $840, X7
+ JMP callbackasm1(SB)
+ MOV $841, X7
+ JMP callbackasm1(SB)
+ MOV $842, X7
+ JMP callbackasm1(SB)
+ MOV $843, X7
+ JMP callbackasm1(SB)
+ MOV $844, X7
+ JMP callbackasm1(SB)
+ MOV $845, X7
+ JMP callbackasm1(SB)
+ MOV $846, X7
+ JMP callbackasm1(SB)
+ MOV $847, X7
+ JMP callbackasm1(SB)
+ MOV $848, X7
+ JMP callbackasm1(SB)
+ MOV $849, X7
+ JMP callbackasm1(SB)
+ MOV $850, X7
+ JMP callbackasm1(SB)
+ MOV $851, X7
+ JMP callbackasm1(SB)
+ MOV $852, X7
+ JMP callbackasm1(SB)
+ MOV $853, X7
+ JMP callbackasm1(SB)
+ MOV $854, X7
+ JMP callbackasm1(SB)
+ MOV $855, X7
+ JMP callbackasm1(SB)
+ MOV $856, X7
+ JMP callbackasm1(SB)
+ MOV $857, X7
+ JMP callbackasm1(SB)
+ MOV $858, X7
+ JMP callbackasm1(SB)
+ MOV $859, X7
+ JMP callbackasm1(SB)
+ MOV $860, X7
+ JMP callbackasm1(SB)
+ MOV $861, X7
+ JMP callbackasm1(SB)
+ MOV $862, X7
+ JMP callbackasm1(SB)
+ MOV $863, X7
+ JMP callbackasm1(SB)
+ MOV $864, X7
+ JMP callbackasm1(SB)
+ MOV $865, X7
+ JMP callbackasm1(SB)
+ MOV $866, X7
+ JMP callbackasm1(SB)
+ MOV $867, X7
+ JMP callbackasm1(SB)
+ MOV $868, X7
+ JMP callbackasm1(SB)
+ MOV $869, X7
+ JMP callbackasm1(SB)
+ MOV $870, X7
+ JMP callbackasm1(SB)
+ MOV $871, X7
+ JMP callbackasm1(SB)
+ MOV $872, X7
+ JMP callbackasm1(SB)
+ MOV $873, X7
+ JMP callbackasm1(SB)
+ MOV $874, X7
+ JMP callbackasm1(SB)
+ MOV $875, X7
+ JMP callbackasm1(SB)
+ MOV $876, X7
+ JMP callbackasm1(SB)
+ MOV $877, X7
+ JMP callbackasm1(SB)
+ MOV $878, X7
+ JMP callbackasm1(SB)
+ MOV $879, X7
+ JMP callbackasm1(SB)
+ MOV $880, X7
+ JMP callbackasm1(SB)
+ MOV $881, X7
+ JMP callbackasm1(SB)
+ MOV $882, X7
+ JMP callbackasm1(SB)
+ MOV $883, X7
+ JMP callbackasm1(SB)
+ MOV $884, X7
+ JMP callbackasm1(SB)
+ MOV $885, X7
+ JMP callbackasm1(SB)
+ MOV $886, X7
+ JMP callbackasm1(SB)
+ MOV $887, X7
+ JMP callbackasm1(SB)
+ MOV $888, X7
+ JMP callbackasm1(SB)
+ MOV $889, X7
+ JMP callbackasm1(SB)
+ MOV $890, X7
+ JMP callbackasm1(SB)
+ MOV $891, X7
+ JMP callbackasm1(SB)
+ MOV $892, X7
+ JMP callbackasm1(SB)
+ MOV $893, X7
+ JMP callbackasm1(SB)
+ MOV $894, X7
+ JMP callbackasm1(SB)
+ MOV $895, X7
+ JMP callbackasm1(SB)
+ MOV $896, X7
+ JMP callbackasm1(SB)
+ MOV $897, X7
+ JMP callbackasm1(SB)
+ MOV $898, X7
+ JMP callbackasm1(SB)
+ MOV $899, X7
+ JMP callbackasm1(SB)
+ MOV $900, X7
+ JMP callbackasm1(SB)
+ MOV $901, X7
+ JMP callbackasm1(SB)
+ MOV $902, X7
+ JMP callbackasm1(SB)
+ MOV $903, X7
+ JMP callbackasm1(SB)
+ MOV $904, X7
+ JMP callbackasm1(SB)
+ MOV $905, X7
+ JMP callbackasm1(SB)
+ MOV $906, X7
+ JMP callbackasm1(SB)
+ MOV $907, X7
+ JMP callbackasm1(SB)
+ MOV $908, X7
+ JMP callbackasm1(SB)
+ MOV $909, X7
+ JMP callbackasm1(SB)
+ MOV $910, X7
+ JMP callbackasm1(SB)
+ MOV $911, X7
+ JMP callbackasm1(SB)
+ MOV $912, X7
+ JMP callbackasm1(SB)
+ MOV $913, X7
+ JMP callbackasm1(SB)
+ MOV $914, X7
+ JMP callbackasm1(SB)
+ MOV $915, X7
+ JMP callbackasm1(SB)
+ MOV $916, X7
+ JMP callbackasm1(SB)
+ MOV $917, X7
+ JMP callbackasm1(SB)
+ MOV $918, X7
+ JMP callbackasm1(SB)
+ MOV $919, X7
+ JMP callbackasm1(SB)
+ MOV $920, X7
+ JMP callbackasm1(SB)
+ MOV $921, X7
+ JMP callbackasm1(SB)
+ MOV $922, X7
+ JMP callbackasm1(SB)
+ MOV $923, X7
+ JMP callbackasm1(SB)
+ MOV $924, X7
+ JMP callbackasm1(SB)
+ MOV $925, X7
+ JMP callbackasm1(SB)
+ MOV $926, X7
+ JMP callbackasm1(SB)
+ MOV $927, X7
+ JMP callbackasm1(SB)
+ MOV $928, X7
+ JMP callbackasm1(SB)
+ MOV $929, X7
+ JMP callbackasm1(SB)
+ MOV $930, X7
+ JMP callbackasm1(SB)
+ MOV $931, X7
+ JMP callbackasm1(SB)
+ MOV $932, X7
+ JMP callbackasm1(SB)
+ MOV $933, X7
+ JMP callbackasm1(SB)
+ MOV $934, X7
+ JMP callbackasm1(SB)
+ MOV $935, X7
+ JMP callbackasm1(SB)
+ MOV $936, X7
+ JMP callbackasm1(SB)
+ MOV $937, X7
+ JMP callbackasm1(SB)
+ MOV $938, X7
+ JMP callbackasm1(SB)
+ MOV $939, X7
+ JMP callbackasm1(SB)
+ MOV $940, X7
+ JMP callbackasm1(SB)
+ MOV $941, X7
+ JMP callbackasm1(SB)
+ MOV $942, X7
+ JMP callbackasm1(SB)
+ MOV $943, X7
+ JMP callbackasm1(SB)
+ MOV $944, X7
+ JMP callbackasm1(SB)
+ MOV $945, X7
+ JMP callbackasm1(SB)
+ MOV $946, X7
+ JMP callbackasm1(SB)
+ MOV $947, X7
+ JMP callbackasm1(SB)
+ MOV $948, X7
+ JMP callbackasm1(SB)
+ MOV $949, X7
+ JMP callbackasm1(SB)
+ MOV $950, X7
+ JMP callbackasm1(SB)
+ MOV $951, X7
+ JMP callbackasm1(SB)
+ MOV $952, X7
+ JMP callbackasm1(SB)
+ MOV $953, X7
+ JMP callbackasm1(SB)
+ MOV $954, X7
+ JMP callbackasm1(SB)
+ MOV $955, X7
+ JMP callbackasm1(SB)
+ MOV $956, X7
+ JMP callbackasm1(SB)
+ MOV $957, X7
+ JMP callbackasm1(SB)
+ MOV $958, X7
+ JMP callbackasm1(SB)
+ MOV $959, X7
+ JMP callbackasm1(SB)
+ MOV $960, X7
+ JMP callbackasm1(SB)
+ MOV $961, X7
+ JMP callbackasm1(SB)
+ MOV $962, X7
+ JMP callbackasm1(SB)
+ MOV $963, X7
+ JMP callbackasm1(SB)
+ MOV $964, X7
+ JMP callbackasm1(SB)
+ MOV $965, X7
+ JMP callbackasm1(SB)
+ MOV $966, X7
+ JMP callbackasm1(SB)
+ MOV $967, X7
+ JMP callbackasm1(SB)
+ MOV $968, X7
+ JMP callbackasm1(SB)
+ MOV $969, X7
+ JMP callbackasm1(SB)
+ MOV $970, X7
+ JMP callbackasm1(SB)
+ MOV $971, X7
+ JMP callbackasm1(SB)
+ MOV $972, X7
+ JMP callbackasm1(SB)
+ MOV $973, X7
+ JMP callbackasm1(SB)
+ MOV $974, X7
+ JMP callbackasm1(SB)
+ MOV $975, X7
+ JMP callbackasm1(SB)
+ MOV $976, X7
+ JMP callbackasm1(SB)
+ MOV $977, X7
+ JMP callbackasm1(SB)
+ MOV $978, X7
+ JMP callbackasm1(SB)
+ MOV $979, X7
+ JMP callbackasm1(SB)
+ MOV $980, X7
+ JMP callbackasm1(SB)
+ MOV $981, X7
+ JMP callbackasm1(SB)
+ MOV $982, X7
+ JMP callbackasm1(SB)
+ MOV $983, X7
+ JMP callbackasm1(SB)
+ MOV $984, X7
+ JMP callbackasm1(SB)
+ MOV $985, X7
+ JMP callbackasm1(SB)
+ MOV $986, X7
+ JMP callbackasm1(SB)
+ MOV $987, X7
+ JMP callbackasm1(SB)
+ MOV $988, X7
+ JMP callbackasm1(SB)
+ MOV $989, X7
+ JMP callbackasm1(SB)
+ MOV $990, X7
+ JMP callbackasm1(SB)
+ MOV $991, X7
+ JMP callbackasm1(SB)
+ MOV $992, X7
+ JMP callbackasm1(SB)
+ MOV $993, X7
+ JMP callbackasm1(SB)
+ MOV $994, X7
+ JMP callbackasm1(SB)
+ MOV $995, X7
+ JMP callbackasm1(SB)
+ MOV $996, X7
+ JMP callbackasm1(SB)
+ MOV $997, X7
+ JMP callbackasm1(SB)
+ MOV $998, X7
+ JMP callbackasm1(SB)
+ MOV $999, X7
+ JMP callbackasm1(SB)
+ MOV $1000, X7
+ JMP callbackasm1(SB)
+ MOV $1001, X7
+ JMP callbackasm1(SB)
+ MOV $1002, X7
+ JMP callbackasm1(SB)
+ MOV $1003, X7
+ JMP callbackasm1(SB)
+ MOV $1004, X7
+ JMP callbackasm1(SB)
+ MOV $1005, X7
+ JMP callbackasm1(SB)
+ MOV $1006, X7
+ JMP callbackasm1(SB)
+ MOV $1007, X7
+ JMP callbackasm1(SB)
+ MOV $1008, X7
+ JMP callbackasm1(SB)
+ MOV $1009, X7
+ JMP callbackasm1(SB)
+ MOV $1010, X7
+ JMP callbackasm1(SB)
+ MOV $1011, X7
+ JMP callbackasm1(SB)
+ MOV $1012, X7
+ JMP callbackasm1(SB)
+ MOV $1013, X7
+ JMP callbackasm1(SB)
+ MOV $1014, X7
+ JMP callbackasm1(SB)
+ MOV $1015, X7
+ JMP callbackasm1(SB)
+ MOV $1016, X7
+ JMP callbackasm1(SB)
+ MOV $1017, X7
+ JMP callbackasm1(SB)
+ MOV $1018, X7
+ JMP callbackasm1(SB)
+ MOV $1019, X7
+ JMP callbackasm1(SB)
+ MOV $1020, X7
+ JMP callbackasm1(SB)
+ MOV $1021, X7
+ JMP callbackasm1(SB)
+ MOV $1022, X7
+ JMP callbackasm1(SB)
+ MOV $1023, X7
+ JMP callbackasm1(SB)
+ MOV $1024, X7
+ JMP callbackasm1(SB)
+ MOV $1025, X7
+ JMP callbackasm1(SB)
+ MOV $1026, X7
+ JMP callbackasm1(SB)
+ MOV $1027, X7
+ JMP callbackasm1(SB)
+ MOV $1028, X7
+ JMP callbackasm1(SB)
+ MOV $1029, X7
+ JMP callbackasm1(SB)
+ MOV $1030, X7
+ JMP callbackasm1(SB)
+ MOV $1031, X7
+ JMP callbackasm1(SB)
+ MOV $1032, X7
+ JMP callbackasm1(SB)
+ MOV $1033, X7
+ JMP callbackasm1(SB)
+ MOV $1034, X7
+ JMP callbackasm1(SB)
+ MOV $1035, X7
+ JMP callbackasm1(SB)
+ MOV $1036, X7
+ JMP callbackasm1(SB)
+ MOV $1037, X7
+ JMP callbackasm1(SB)
+ MOV $1038, X7
+ JMP callbackasm1(SB)
+ MOV $1039, X7
+ JMP callbackasm1(SB)
+ MOV $1040, X7
+ JMP callbackasm1(SB)
+ MOV $1041, X7
+ JMP callbackasm1(SB)
+ MOV $1042, X7
+ JMP callbackasm1(SB)
+ MOV $1043, X7
+ JMP callbackasm1(SB)
+ MOV $1044, X7
+ JMP callbackasm1(SB)
+ MOV $1045, X7
+ JMP callbackasm1(SB)
+ MOV $1046, X7
+ JMP callbackasm1(SB)
+ MOV $1047, X7
+ JMP callbackasm1(SB)
+ MOV $1048, X7
+ JMP callbackasm1(SB)
+ MOV $1049, X7
+ JMP callbackasm1(SB)
+ MOV $1050, X7
+ JMP callbackasm1(SB)
+ MOV $1051, X7
+ JMP callbackasm1(SB)
+ MOV $1052, X7
+ JMP callbackasm1(SB)
+ MOV $1053, X7
+ JMP callbackasm1(SB)
+ MOV $1054, X7
+ JMP callbackasm1(SB)
+ MOV $1055, X7
+ JMP callbackasm1(SB)
+ MOV $1056, X7
+ JMP callbackasm1(SB)
+ MOV $1057, X7
+ JMP callbackasm1(SB)
+ MOV $1058, X7
+ JMP callbackasm1(SB)
+ MOV $1059, X7
+ JMP callbackasm1(SB)
+ MOV $1060, X7
+ JMP callbackasm1(SB)
+ MOV $1061, X7
+ JMP callbackasm1(SB)
+ MOV $1062, X7
+ JMP callbackasm1(SB)
+ MOV $1063, X7
+ JMP callbackasm1(SB)
+ MOV $1064, X7
+ JMP callbackasm1(SB)
+ MOV $1065, X7
+ JMP callbackasm1(SB)
+ MOV $1066, X7
+ JMP callbackasm1(SB)
+ MOV $1067, X7
+ JMP callbackasm1(SB)
+ MOV $1068, X7
+ JMP callbackasm1(SB)
+ MOV $1069, X7
+ JMP callbackasm1(SB)
+ MOV $1070, X7
+ JMP callbackasm1(SB)
+ MOV $1071, X7
+ JMP callbackasm1(SB)
+ MOV $1072, X7
+ JMP callbackasm1(SB)
+ MOV $1073, X7
+ JMP callbackasm1(SB)
+ MOV $1074, X7
+ JMP callbackasm1(SB)
+ MOV $1075, X7
+ JMP callbackasm1(SB)
+ MOV $1076, X7
+ JMP callbackasm1(SB)
+ MOV $1077, X7
+ JMP callbackasm1(SB)
+ MOV $1078, X7
+ JMP callbackasm1(SB)
+ MOV $1079, X7
+ JMP callbackasm1(SB)
+ MOV $1080, X7
+ JMP callbackasm1(SB)
+ MOV $1081, X7
+ JMP callbackasm1(SB)
+ MOV $1082, X7
+ JMP callbackasm1(SB)
+ MOV $1083, X7
+ JMP callbackasm1(SB)
+ MOV $1084, X7
+ JMP callbackasm1(SB)
+ MOV $1085, X7
+ JMP callbackasm1(SB)
+ MOV $1086, X7
+ JMP callbackasm1(SB)
+ MOV $1087, X7
+ JMP callbackasm1(SB)
+ MOV $1088, X7
+ JMP callbackasm1(SB)
+ MOV $1089, X7
+ JMP callbackasm1(SB)
+ MOV $1090, X7
+ JMP callbackasm1(SB)
+ MOV $1091, X7
+ JMP callbackasm1(SB)
+ MOV $1092, X7
+ JMP callbackasm1(SB)
+ MOV $1093, X7
+ JMP callbackasm1(SB)
+ MOV $1094, X7
+ JMP callbackasm1(SB)
+ MOV $1095, X7
+ JMP callbackasm1(SB)
+ MOV $1096, X7
+ JMP callbackasm1(SB)
+ MOV $1097, X7
+ JMP callbackasm1(SB)
+ MOV $1098, X7
+ JMP callbackasm1(SB)
+ MOV $1099, X7
+ JMP callbackasm1(SB)
+ MOV $1100, X7
+ JMP callbackasm1(SB)
+ MOV $1101, X7
+ JMP callbackasm1(SB)
+ MOV $1102, X7
+ JMP callbackasm1(SB)
+ MOV $1103, X7
+ JMP callbackasm1(SB)
+ MOV $1104, X7
+ JMP callbackasm1(SB)
+ MOV $1105, X7
+ JMP callbackasm1(SB)
+ MOV $1106, X7
+ JMP callbackasm1(SB)
+ MOV $1107, X7
+ JMP callbackasm1(SB)
+ MOV $1108, X7
+ JMP callbackasm1(SB)
+ MOV $1109, X7
+ JMP callbackasm1(SB)
+ MOV $1110, X7
+ JMP callbackasm1(SB)
+ MOV $1111, X7
+ JMP callbackasm1(SB)
+ MOV $1112, X7
+ JMP callbackasm1(SB)
+ MOV $1113, X7
+ JMP callbackasm1(SB)
+ MOV $1114, X7
+ JMP callbackasm1(SB)
+ MOV $1115, X7
+ JMP callbackasm1(SB)
+ MOV $1116, X7
+ JMP callbackasm1(SB)
+ MOV $1117, X7
+ JMP callbackasm1(SB)
+ MOV $1118, X7
+ JMP callbackasm1(SB)
+ MOV $1119, X7
+ JMP callbackasm1(SB)
+ MOV $1120, X7
+ JMP callbackasm1(SB)
+ MOV $1121, X7
+ JMP callbackasm1(SB)
+ MOV $1122, X7
+ JMP callbackasm1(SB)
+ MOV $1123, X7
+ JMP callbackasm1(SB)
+ MOV $1124, X7
+ JMP callbackasm1(SB)
+ MOV $1125, X7
+ JMP callbackasm1(SB)
+ MOV $1126, X7
+ JMP callbackasm1(SB)
+ MOV $1127, X7
+ JMP callbackasm1(SB)
+ MOV $1128, X7
+ JMP callbackasm1(SB)
+ MOV $1129, X7
+ JMP callbackasm1(SB)
+ MOV $1130, X7
+ JMP callbackasm1(SB)
+ MOV $1131, X7
+ JMP callbackasm1(SB)
+ MOV $1132, X7
+ JMP callbackasm1(SB)
+ MOV $1133, X7
+ JMP callbackasm1(SB)
+ MOV $1134, X7
+ JMP callbackasm1(SB)
+ MOV $1135, X7
+ JMP callbackasm1(SB)
+ MOV $1136, X7
+ JMP callbackasm1(SB)
+ MOV $1137, X7
+ JMP callbackasm1(SB)
+ MOV $1138, X7
+ JMP callbackasm1(SB)
+ MOV $1139, X7
+ JMP callbackasm1(SB)
+ MOV $1140, X7
+ JMP callbackasm1(SB)
+ MOV $1141, X7
+ JMP callbackasm1(SB)
+ MOV $1142, X7
+ JMP callbackasm1(SB)
+ MOV $1143, X7
+ JMP callbackasm1(SB)
+ MOV $1144, X7
+ JMP callbackasm1(SB)
+ MOV $1145, X7
+ JMP callbackasm1(SB)
+ MOV $1146, X7
+ JMP callbackasm1(SB)
+ MOV $1147, X7
+ JMP callbackasm1(SB)
+ MOV $1148, X7
+ JMP callbackasm1(SB)
+ MOV $1149, X7
+ JMP callbackasm1(SB)
+ MOV $1150, X7
+ JMP callbackasm1(SB)
+ MOV $1151, X7
+ JMP callbackasm1(SB)
+ MOV $1152, X7
+ JMP callbackasm1(SB)
+ MOV $1153, X7
+ JMP callbackasm1(SB)
+ MOV $1154, X7
+ JMP callbackasm1(SB)
+ MOV $1155, X7
+ JMP callbackasm1(SB)
+ MOV $1156, X7
+ JMP callbackasm1(SB)
+ MOV $1157, X7
+ JMP callbackasm1(SB)
+ MOV $1158, X7
+ JMP callbackasm1(SB)
+ MOV $1159, X7
+ JMP callbackasm1(SB)
+ MOV $1160, X7
+ JMP callbackasm1(SB)
+ MOV $1161, X7
+ JMP callbackasm1(SB)
+ MOV $1162, X7
+ JMP callbackasm1(SB)
+ MOV $1163, X7
+ JMP callbackasm1(SB)
+ MOV $1164, X7
+ JMP callbackasm1(SB)
+ MOV $1165, X7
+ JMP callbackasm1(SB)
+ MOV $1166, X7
+ JMP callbackasm1(SB)
+ MOV $1167, X7
+ JMP callbackasm1(SB)
+ MOV $1168, X7
+ JMP callbackasm1(SB)
+ MOV $1169, X7
+ JMP callbackasm1(SB)
+ MOV $1170, X7
+ JMP callbackasm1(SB)
+ MOV $1171, X7
+ JMP callbackasm1(SB)
+ MOV $1172, X7
+ JMP callbackasm1(SB)
+ MOV $1173, X7
+ JMP callbackasm1(SB)
+ MOV $1174, X7
+ JMP callbackasm1(SB)
+ MOV $1175, X7
+ JMP callbackasm1(SB)
+ MOV $1176, X7
+ JMP callbackasm1(SB)
+ MOV $1177, X7
+ JMP callbackasm1(SB)
+ MOV $1178, X7
+ JMP callbackasm1(SB)
+ MOV $1179, X7
+ JMP callbackasm1(SB)
+ MOV $1180, X7
+ JMP callbackasm1(SB)
+ MOV $1181, X7
+ JMP callbackasm1(SB)
+ MOV $1182, X7
+ JMP callbackasm1(SB)
+ MOV $1183, X7
+ JMP callbackasm1(SB)
+ MOV $1184, X7
+ JMP callbackasm1(SB)
+ MOV $1185, X7
+ JMP callbackasm1(SB)
+ MOV $1186, X7
+ JMP callbackasm1(SB)
+ MOV $1187, X7
+ JMP callbackasm1(SB)
+ MOV $1188, X7
+ JMP callbackasm1(SB)
+ MOV $1189, X7
+ JMP callbackasm1(SB)
+ MOV $1190, X7
+ JMP callbackasm1(SB)
+ MOV $1191, X7
+ JMP callbackasm1(SB)
+ MOV $1192, X7
+ JMP callbackasm1(SB)
+ MOV $1193, X7
+ JMP callbackasm1(SB)
+ MOV $1194, X7
+ JMP callbackasm1(SB)
+ MOV $1195, X7
+ JMP callbackasm1(SB)
+ MOV $1196, X7
+ JMP callbackasm1(SB)
+ MOV $1197, X7
+ JMP callbackasm1(SB)
+ MOV $1198, X7
+ JMP callbackasm1(SB)
+ MOV $1199, X7
+ JMP callbackasm1(SB)
+ MOV $1200, X7
+ JMP callbackasm1(SB)
+ MOV $1201, X7
+ JMP callbackasm1(SB)
+ MOV $1202, X7
+ JMP callbackasm1(SB)
+ MOV $1203, X7
+ JMP callbackasm1(SB)
+ MOV $1204, X7
+ JMP callbackasm1(SB)
+ MOV $1205, X7
+ JMP callbackasm1(SB)
+ MOV $1206, X7
+ JMP callbackasm1(SB)
+ MOV $1207, X7
+ JMP callbackasm1(SB)
+ MOV $1208, X7
+ JMP callbackasm1(SB)
+ MOV $1209, X7
+ JMP callbackasm1(SB)
+ MOV $1210, X7
+ JMP callbackasm1(SB)
+ MOV $1211, X7
+ JMP callbackasm1(SB)
+ MOV $1212, X7
+ JMP callbackasm1(SB)
+ MOV $1213, X7
+ JMP callbackasm1(SB)
+ MOV $1214, X7
+ JMP callbackasm1(SB)
+ MOV $1215, X7
+ JMP callbackasm1(SB)
+ MOV $1216, X7
+ JMP callbackasm1(SB)
+ MOV $1217, X7
+ JMP callbackasm1(SB)
+ MOV $1218, X7
+ JMP callbackasm1(SB)
+ MOV $1219, X7
+ JMP callbackasm1(SB)
+ MOV $1220, X7
+ JMP callbackasm1(SB)
+ MOV $1221, X7
+ JMP callbackasm1(SB)
+ MOV $1222, X7
+ JMP callbackasm1(SB)
+ MOV $1223, X7
+ JMP callbackasm1(SB)
+ MOV $1224, X7
+ JMP callbackasm1(SB)
+ MOV $1225, X7
+ JMP callbackasm1(SB)
+ MOV $1226, X7
+ JMP callbackasm1(SB)
+ MOV $1227, X7
+ JMP callbackasm1(SB)
+ MOV $1228, X7
+ JMP callbackasm1(SB)
+ MOV $1229, X7
+ JMP callbackasm1(SB)
+ MOV $1230, X7
+ JMP callbackasm1(SB)
+ MOV $1231, X7
+ JMP callbackasm1(SB)
+ MOV $1232, X7
+ JMP callbackasm1(SB)
+ MOV $1233, X7
+ JMP callbackasm1(SB)
+ MOV $1234, X7
+ JMP callbackasm1(SB)
+ MOV $1235, X7
+ JMP callbackasm1(SB)
+ MOV $1236, X7
+ JMP callbackasm1(SB)
+ MOV $1237, X7
+ JMP callbackasm1(SB)
+ MOV $1238, X7
+ JMP callbackasm1(SB)
+ MOV $1239, X7
+ JMP callbackasm1(SB)
+ MOV $1240, X7
+ JMP callbackasm1(SB)
+ MOV $1241, X7
+ JMP callbackasm1(SB)
+ MOV $1242, X7
+ JMP callbackasm1(SB)
+ MOV $1243, X7
+ JMP callbackasm1(SB)
+ MOV $1244, X7
+ JMP callbackasm1(SB)
+ MOV $1245, X7
+ JMP callbackasm1(SB)
+ MOV $1246, X7
+ JMP callbackasm1(SB)
+ MOV $1247, X7
+ JMP callbackasm1(SB)
+ MOV $1248, X7
+ JMP callbackasm1(SB)
+ MOV $1249, X7
+ JMP callbackasm1(SB)
+ MOV $1250, X7
+ JMP callbackasm1(SB)
+ MOV $1251, X7
+ JMP callbackasm1(SB)
+ MOV $1252, X7
+ JMP callbackasm1(SB)
+ MOV $1253, X7
+ JMP callbackasm1(SB)
+ MOV $1254, X7
+ JMP callbackasm1(SB)
+ MOV $1255, X7
+ JMP callbackasm1(SB)
+ MOV $1256, X7
+ JMP callbackasm1(SB)
+ MOV $1257, X7
+ JMP callbackasm1(SB)
+ MOV $1258, X7
+ JMP callbackasm1(SB)
+ MOV $1259, X7
+ JMP callbackasm1(SB)
+ MOV $1260, X7
+ JMP callbackasm1(SB)
+ MOV $1261, X7
+ JMP callbackasm1(SB)
+ MOV $1262, X7
+ JMP callbackasm1(SB)
+ MOV $1263, X7
+ JMP callbackasm1(SB)
+ MOV $1264, X7
+ JMP callbackasm1(SB)
+ MOV $1265, X7
+ JMP callbackasm1(SB)
+ MOV $1266, X7
+ JMP callbackasm1(SB)
+ MOV $1267, X7
+ JMP callbackasm1(SB)
+ MOV $1268, X7
+ JMP callbackasm1(SB)
+ MOV $1269, X7
+ JMP callbackasm1(SB)
+ MOV $1270, X7
+ JMP callbackasm1(SB)
+ MOV $1271, X7
+ JMP callbackasm1(SB)
+ MOV $1272, X7
+ JMP callbackasm1(SB)
+ MOV $1273, X7
+ JMP callbackasm1(SB)
+ MOV $1274, X7
+ JMP callbackasm1(SB)
+ MOV $1275, X7
+ JMP callbackasm1(SB)
+ MOV $1276, X7
+ JMP callbackasm1(SB)
+ MOV $1277, X7
+ JMP callbackasm1(SB)
+ MOV $1278, X7
+ JMP callbackasm1(SB)
+ MOV $1279, X7
+ JMP callbackasm1(SB)
+ MOV $1280, X7
+ JMP callbackasm1(SB)
+ MOV $1281, X7
+ JMP callbackasm1(SB)
+ MOV $1282, X7
+ JMP callbackasm1(SB)
+ MOV $1283, X7
+ JMP callbackasm1(SB)
+ MOV $1284, X7
+ JMP callbackasm1(SB)
+ MOV $1285, X7
+ JMP callbackasm1(SB)
+ MOV $1286, X7
+ JMP callbackasm1(SB)
+ MOV $1287, X7
+ JMP callbackasm1(SB)
+ MOV $1288, X7
+ JMP callbackasm1(SB)
+ MOV $1289, X7
+ JMP callbackasm1(SB)
+ MOV $1290, X7
+ JMP callbackasm1(SB)
+ MOV $1291, X7
+ JMP callbackasm1(SB)
+ MOV $1292, X7
+ JMP callbackasm1(SB)
+ MOV $1293, X7
+ JMP callbackasm1(SB)
+ MOV $1294, X7
+ JMP callbackasm1(SB)
+ MOV $1295, X7
+ JMP callbackasm1(SB)
+ MOV $1296, X7
+ JMP callbackasm1(SB)
+ MOV $1297, X7
+ JMP callbackasm1(SB)
+ MOV $1298, X7
+ JMP callbackasm1(SB)
+ MOV $1299, X7
+ JMP callbackasm1(SB)
+ MOV $1300, X7
+ JMP callbackasm1(SB)
+ MOV $1301, X7
+ JMP callbackasm1(SB)
+ MOV $1302, X7
+ JMP callbackasm1(SB)
+ MOV $1303, X7
+ JMP callbackasm1(SB)
+ MOV $1304, X7
+ JMP callbackasm1(SB)
+ MOV $1305, X7
+ JMP callbackasm1(SB)
+ MOV $1306, X7
+ JMP callbackasm1(SB)
+ MOV $1307, X7
+ JMP callbackasm1(SB)
+ MOV $1308, X7
+ JMP callbackasm1(SB)
+ MOV $1309, X7
+ JMP callbackasm1(SB)
+ MOV $1310, X7
+ JMP callbackasm1(SB)
+ MOV $1311, X7
+ JMP callbackasm1(SB)
+ MOV $1312, X7
+ JMP callbackasm1(SB)
+ MOV $1313, X7
+ JMP callbackasm1(SB)
+ MOV $1314, X7
+ JMP callbackasm1(SB)
+ MOV $1315, X7
+ JMP callbackasm1(SB)
+ MOV $1316, X7
+ JMP callbackasm1(SB)
+ MOV $1317, X7
+ JMP callbackasm1(SB)
+ MOV $1318, X7
+ JMP callbackasm1(SB)
+ MOV $1319, X7
+ JMP callbackasm1(SB)
+ MOV $1320, X7
+ JMP callbackasm1(SB)
+ MOV $1321, X7
+ JMP callbackasm1(SB)
+ MOV $1322, X7
+ JMP callbackasm1(SB)
+ MOV $1323, X7
+ JMP callbackasm1(SB)
+ MOV $1324, X7
+ JMP callbackasm1(SB)
+ MOV $1325, X7
+ JMP callbackasm1(SB)
+ MOV $1326, X7
+ JMP callbackasm1(SB)
+ MOV $1327, X7
+ JMP callbackasm1(SB)
+ MOV $1328, X7
+ JMP callbackasm1(SB)
+ MOV $1329, X7
+ JMP callbackasm1(SB)
+ MOV $1330, X7
+ JMP callbackasm1(SB)
+ MOV $1331, X7
+ JMP callbackasm1(SB)
+ MOV $1332, X7
+ JMP callbackasm1(SB)
+ MOV $1333, X7
+ JMP callbackasm1(SB)
+ MOV $1334, X7
+ JMP callbackasm1(SB)
+ MOV $1335, X7
+ JMP callbackasm1(SB)
+ MOV $1336, X7
+ JMP callbackasm1(SB)
+ MOV $1337, X7
+ JMP callbackasm1(SB)
+ MOV $1338, X7
+ JMP callbackasm1(SB)
+ MOV $1339, X7
+ JMP callbackasm1(SB)
+ MOV $1340, X7
+ JMP callbackasm1(SB)
+ MOV $1341, X7
+ JMP callbackasm1(SB)
+ MOV $1342, X7
+ JMP callbackasm1(SB)
+ MOV $1343, X7
+ JMP callbackasm1(SB)
+ MOV $1344, X7
+ JMP callbackasm1(SB)
+ MOV $1345, X7
+ JMP callbackasm1(SB)
+ MOV $1346, X7
+ JMP callbackasm1(SB)
+ MOV $1347, X7
+ JMP callbackasm1(SB)
+ MOV $1348, X7
+ JMP callbackasm1(SB)
+ MOV $1349, X7
+ JMP callbackasm1(SB)
+ MOV $1350, X7
+ JMP callbackasm1(SB)
+ MOV $1351, X7
+ JMP callbackasm1(SB)
+ MOV $1352, X7
+ JMP callbackasm1(SB)
+ MOV $1353, X7
+ JMP callbackasm1(SB)
+ MOV $1354, X7
+ JMP callbackasm1(SB)
+ MOV $1355, X7
+ JMP callbackasm1(SB)
+ MOV $1356, X7
+ JMP callbackasm1(SB)
+ MOV $1357, X7
+ JMP callbackasm1(SB)
+ MOV $1358, X7
+ JMP callbackasm1(SB)
+ MOV $1359, X7
+ JMP callbackasm1(SB)
+ MOV $1360, X7
+ JMP callbackasm1(SB)
+ MOV $1361, X7
+ JMP callbackasm1(SB)
+ MOV $1362, X7
+ JMP callbackasm1(SB)
+ MOV $1363, X7
+ JMP callbackasm1(SB)
+ MOV $1364, X7
+ JMP callbackasm1(SB)
+ MOV $1365, X7
+ JMP callbackasm1(SB)
+ MOV $1366, X7
+ JMP callbackasm1(SB)
+ MOV $1367, X7
+ JMP callbackasm1(SB)
+ MOV $1368, X7
+ JMP callbackasm1(SB)
+ MOV $1369, X7
+ JMP callbackasm1(SB)
+ MOV $1370, X7
+ JMP callbackasm1(SB)
+ MOV $1371, X7
+ JMP callbackasm1(SB)
+ MOV $1372, X7
+ JMP callbackasm1(SB)
+ MOV $1373, X7
+ JMP callbackasm1(SB)
+ MOV $1374, X7
+ JMP callbackasm1(SB)
+ MOV $1375, X7
+ JMP callbackasm1(SB)
+ MOV $1376, X7
+ JMP callbackasm1(SB)
+ MOV $1377, X7
+ JMP callbackasm1(SB)
+ MOV $1378, X7
+ JMP callbackasm1(SB)
+ MOV $1379, X7
+ JMP callbackasm1(SB)
+ MOV $1380, X7
+ JMP callbackasm1(SB)
+ MOV $1381, X7
+ JMP callbackasm1(SB)
+ MOV $1382, X7
+ JMP callbackasm1(SB)
+ MOV $1383, X7
+ JMP callbackasm1(SB)
+ MOV $1384, X7
+ JMP callbackasm1(SB)
+ MOV $1385, X7
+ JMP callbackasm1(SB)
+ MOV $1386, X7
+ JMP callbackasm1(SB)
+ MOV $1387, X7
+ JMP callbackasm1(SB)
+ MOV $1388, X7
+ JMP callbackasm1(SB)
+ MOV $1389, X7
+ JMP callbackasm1(SB)
+ MOV $1390, X7
+ JMP callbackasm1(SB)
+ MOV $1391, X7
+ JMP callbackasm1(SB)
+ MOV $1392, X7
+ JMP callbackasm1(SB)
+ MOV $1393, X7
+ JMP callbackasm1(SB)
+ MOV $1394, X7
+ JMP callbackasm1(SB)
+ MOV $1395, X7
+ JMP callbackasm1(SB)
+ MOV $1396, X7
+ JMP callbackasm1(SB)
+ MOV $1397, X7
+ JMP callbackasm1(SB)
+ MOV $1398, X7
+ JMP callbackasm1(SB)
+ MOV $1399, X7
+ JMP callbackasm1(SB)
+ MOV $1400, X7
+ JMP callbackasm1(SB)
+ MOV $1401, X7
+ JMP callbackasm1(SB)
+ MOV $1402, X7
+ JMP callbackasm1(SB)
+ MOV $1403, X7
+ JMP callbackasm1(SB)
+ MOV $1404, X7
+ JMP callbackasm1(SB)
+ MOV $1405, X7
+ JMP callbackasm1(SB)
+ MOV $1406, X7
+ JMP callbackasm1(SB)
+ MOV $1407, X7
+ JMP callbackasm1(SB)
+ MOV $1408, X7
+ JMP callbackasm1(SB)
+ MOV $1409, X7
+ JMP callbackasm1(SB)
+ MOV $1410, X7
+ JMP callbackasm1(SB)
+ MOV $1411, X7
+ JMP callbackasm1(SB)
+ MOV $1412, X7
+ JMP callbackasm1(SB)
+ MOV $1413, X7
+ JMP callbackasm1(SB)
+ MOV $1414, X7
+ JMP callbackasm1(SB)
+ MOV $1415, X7
+ JMP callbackasm1(SB)
+ MOV $1416, X7
+ JMP callbackasm1(SB)
+ MOV $1417, X7
+ JMP callbackasm1(SB)
+ MOV $1418, X7
+ JMP callbackasm1(SB)
+ MOV $1419, X7
+ JMP callbackasm1(SB)
+ MOV $1420, X7
+ JMP callbackasm1(SB)
+ MOV $1421, X7
+ JMP callbackasm1(SB)
+ MOV $1422, X7
+ JMP callbackasm1(SB)
+ MOV $1423, X7
+ JMP callbackasm1(SB)
+ MOV $1424, X7
+ JMP callbackasm1(SB)
+ MOV $1425, X7
+ JMP callbackasm1(SB)
+ MOV $1426, X7
+ JMP callbackasm1(SB)
+ MOV $1427, X7
+ JMP callbackasm1(SB)
+ MOV $1428, X7
+ JMP callbackasm1(SB)
+ MOV $1429, X7
+ JMP callbackasm1(SB)
+ MOV $1430, X7
+ JMP callbackasm1(SB)
+ MOV $1431, X7
+ JMP callbackasm1(SB)
+ MOV $1432, X7
+ JMP callbackasm1(SB)
+ MOV $1433, X7
+ JMP callbackasm1(SB)
+ MOV $1434, X7
+ JMP callbackasm1(SB)
+ MOV $1435, X7
+ JMP callbackasm1(SB)
+ MOV $1436, X7
+ JMP callbackasm1(SB)
+ MOV $1437, X7
+ JMP callbackasm1(SB)
+ MOV $1438, X7
+ JMP callbackasm1(SB)
+ MOV $1439, X7
+ JMP callbackasm1(SB)
+ MOV $1440, X7
+ JMP callbackasm1(SB)
+ MOV $1441, X7
+ JMP callbackasm1(SB)
+ MOV $1442, X7
+ JMP callbackasm1(SB)
+ MOV $1443, X7
+ JMP callbackasm1(SB)
+ MOV $1444, X7
+ JMP callbackasm1(SB)
+ MOV $1445, X7
+ JMP callbackasm1(SB)
+ MOV $1446, X7
+ JMP callbackasm1(SB)
+ MOV $1447, X7
+ JMP callbackasm1(SB)
+ MOV $1448, X7
+ JMP callbackasm1(SB)
+ MOV $1449, X7
+ JMP callbackasm1(SB)
+ MOV $1450, X7
+ JMP callbackasm1(SB)
+ MOV $1451, X7
+ JMP callbackasm1(SB)
+ MOV $1452, X7
+ JMP callbackasm1(SB)
+ MOV $1453, X7
+ JMP callbackasm1(SB)
+ MOV $1454, X7
+ JMP callbackasm1(SB)
+ MOV $1455, X7
+ JMP callbackasm1(SB)
+ MOV $1456, X7
+ JMP callbackasm1(SB)
+ MOV $1457, X7
+ JMP callbackasm1(SB)
+ MOV $1458, X7
+ JMP callbackasm1(SB)
+ MOV $1459, X7
+ JMP callbackasm1(SB)
+ MOV $1460, X7
+ JMP callbackasm1(SB)
+ MOV $1461, X7
+ JMP callbackasm1(SB)
+ MOV $1462, X7
+ JMP callbackasm1(SB)
+ MOV $1463, X7
+ JMP callbackasm1(SB)
+ MOV $1464, X7
+ JMP callbackasm1(SB)
+ MOV $1465, X7
+ JMP callbackasm1(SB)
+ MOV $1466, X7
+ JMP callbackasm1(SB)
+ MOV $1467, X7
+ JMP callbackasm1(SB)
+ MOV $1468, X7
+ JMP callbackasm1(SB)
+ MOV $1469, X7
+ JMP callbackasm1(SB)
+ MOV $1470, X7
+ JMP callbackasm1(SB)
+ MOV $1471, X7
+ JMP callbackasm1(SB)
+ MOV $1472, X7
+ JMP callbackasm1(SB)
+ MOV $1473, X7
+ JMP callbackasm1(SB)
+ MOV $1474, X7
+ JMP callbackasm1(SB)
+ MOV $1475, X7
+ JMP callbackasm1(SB)
+ MOV $1476, X7
+ JMP callbackasm1(SB)
+ MOV $1477, X7
+ JMP callbackasm1(SB)
+ MOV $1478, X7
+ JMP callbackasm1(SB)
+ MOV $1479, X7
+ JMP callbackasm1(SB)
+ MOV $1480, X7
+ JMP callbackasm1(SB)
+ MOV $1481, X7
+ JMP callbackasm1(SB)
+ MOV $1482, X7
+ JMP callbackasm1(SB)
+ MOV $1483, X7
+ JMP callbackasm1(SB)
+ MOV $1484, X7
+ JMP callbackasm1(SB)
+ MOV $1485, X7
+ JMP callbackasm1(SB)
+ MOV $1486, X7
+ JMP callbackasm1(SB)
+ MOV $1487, X7
+ JMP callbackasm1(SB)
+ MOV $1488, X7
+ JMP callbackasm1(SB)
+ MOV $1489, X7
+ JMP callbackasm1(SB)
+ MOV $1490, X7
+ JMP callbackasm1(SB)
+ MOV $1491, X7
+ JMP callbackasm1(SB)
+ MOV $1492, X7
+ JMP callbackasm1(SB)
+ MOV $1493, X7
+ JMP callbackasm1(SB)
+ MOV $1494, X7
+ JMP callbackasm1(SB)
+ MOV $1495, X7
+ JMP callbackasm1(SB)
+ MOV $1496, X7
+ JMP callbackasm1(SB)
+ MOV $1497, X7
+ JMP callbackasm1(SB)
+ MOV $1498, X7
+ JMP callbackasm1(SB)
+ MOV $1499, X7
+ JMP callbackasm1(SB)
+ MOV $1500, X7
+ JMP callbackasm1(SB)
+ MOV $1501, X7
+ JMP callbackasm1(SB)
+ MOV $1502, X7
+ JMP callbackasm1(SB)
+ MOV $1503, X7
+ JMP callbackasm1(SB)
+ MOV $1504, X7
+ JMP callbackasm1(SB)
+ MOV $1505, X7
+ JMP callbackasm1(SB)
+ MOV $1506, X7
+ JMP callbackasm1(SB)
+ MOV $1507, X7
+ JMP callbackasm1(SB)
+ MOV $1508, X7
+ JMP callbackasm1(SB)
+ MOV $1509, X7
+ JMP callbackasm1(SB)
+ MOV $1510, X7
+ JMP callbackasm1(SB)
+ MOV $1511, X7
+ JMP callbackasm1(SB)
+ MOV $1512, X7
+ JMP callbackasm1(SB)
+ MOV $1513, X7
+ JMP callbackasm1(SB)
+ MOV $1514, X7
+ JMP callbackasm1(SB)
+ MOV $1515, X7
+ JMP callbackasm1(SB)
+ MOV $1516, X7
+ JMP callbackasm1(SB)
+ MOV $1517, X7
+ JMP callbackasm1(SB)
+ MOV $1518, X7
+ JMP callbackasm1(SB)
+ MOV $1519, X7
+ JMP callbackasm1(SB)
+ MOV $1520, X7
+ JMP callbackasm1(SB)
+ MOV $1521, X7
+ JMP callbackasm1(SB)
+ MOV $1522, X7
+ JMP callbackasm1(SB)
+ MOV $1523, X7
+ JMP callbackasm1(SB)
+ MOV $1524, X7
+ JMP callbackasm1(SB)
+ MOV $1525, X7
+ JMP callbackasm1(SB)
+ MOV $1526, X7
+ JMP callbackasm1(SB)
+ MOV $1527, X7
+ JMP callbackasm1(SB)
+ MOV $1528, X7
+ JMP callbackasm1(SB)
+ MOV $1529, X7
+ JMP callbackasm1(SB)
+ MOV $1530, X7
+ JMP callbackasm1(SB)
+ MOV $1531, X7
+ JMP callbackasm1(SB)
+ MOV $1532, X7
+ JMP callbackasm1(SB)
+ MOV $1533, X7
+ JMP callbackasm1(SB)
+ MOV $1534, X7
+ JMP callbackasm1(SB)
+ MOV $1535, X7
+ JMP callbackasm1(SB)
+ MOV $1536, X7
+ JMP callbackasm1(SB)
+ MOV $1537, X7
+ JMP callbackasm1(SB)
+ MOV $1538, X7
+ JMP callbackasm1(SB)
+ MOV $1539, X7
+ JMP callbackasm1(SB)
+ MOV $1540, X7
+ JMP callbackasm1(SB)
+ MOV $1541, X7
+ JMP callbackasm1(SB)
+ MOV $1542, X7
+ JMP callbackasm1(SB)
+ MOV $1543, X7
+ JMP callbackasm1(SB)
+ MOV $1544, X7
+ JMP callbackasm1(SB)
+ MOV $1545, X7
+ JMP callbackasm1(SB)
+ MOV $1546, X7
+ JMP callbackasm1(SB)
+ MOV $1547, X7
+ JMP callbackasm1(SB)
+ MOV $1548, X7
+ JMP callbackasm1(SB)
+ MOV $1549, X7
+ JMP callbackasm1(SB)
+ MOV $1550, X7
+ JMP callbackasm1(SB)
+ MOV $1551, X7
+ JMP callbackasm1(SB)
+ MOV $1552, X7
+ JMP callbackasm1(SB)
+ MOV $1553, X7
+ JMP callbackasm1(SB)
+ MOV $1554, X7
+ JMP callbackasm1(SB)
+ MOV $1555, X7
+ JMP callbackasm1(SB)
+ MOV $1556, X7
+ JMP callbackasm1(SB)
+ MOV $1557, X7
+ JMP callbackasm1(SB)
+ MOV $1558, X7
+ JMP callbackasm1(SB)
+ MOV $1559, X7
+ JMP callbackasm1(SB)
+ MOV $1560, X7
+ JMP callbackasm1(SB)
+ MOV $1561, X7
+ JMP callbackasm1(SB)
+ MOV $1562, X7
+ JMP callbackasm1(SB)
+ MOV $1563, X7
+ JMP callbackasm1(SB)
+ MOV $1564, X7
+ JMP callbackasm1(SB)
+ MOV $1565, X7
+ JMP callbackasm1(SB)
+ MOV $1566, X7
+ JMP callbackasm1(SB)
+ MOV $1567, X7
+ JMP callbackasm1(SB)
+ MOV $1568, X7
+ JMP callbackasm1(SB)
+ MOV $1569, X7
+ JMP callbackasm1(SB)
+ MOV $1570, X7
+ JMP callbackasm1(SB)
+ MOV $1571, X7
+ JMP callbackasm1(SB)
+ MOV $1572, X7
+ JMP callbackasm1(SB)
+ MOV $1573, X7
+ JMP callbackasm1(SB)
+ MOV $1574, X7
+ JMP callbackasm1(SB)
+ MOV $1575, X7
+ JMP callbackasm1(SB)
+ MOV $1576, X7
+ JMP callbackasm1(SB)
+ MOV $1577, X7
+ JMP callbackasm1(SB)
+ MOV $1578, X7
+ JMP callbackasm1(SB)
+ MOV $1579, X7
+ JMP callbackasm1(SB)
+ MOV $1580, X7
+ JMP callbackasm1(SB)
+ MOV $1581, X7
+ JMP callbackasm1(SB)
+ MOV $1582, X7
+ JMP callbackasm1(SB)
+ MOV $1583, X7
+ JMP callbackasm1(SB)
+ MOV $1584, X7
+ JMP callbackasm1(SB)
+ MOV $1585, X7
+ JMP callbackasm1(SB)
+ MOV $1586, X7
+ JMP callbackasm1(SB)
+ MOV $1587, X7
+ JMP callbackasm1(SB)
+ MOV $1588, X7
+ JMP callbackasm1(SB)
+ MOV $1589, X7
+ JMP callbackasm1(SB)
+ MOV $1590, X7
+ JMP callbackasm1(SB)
+ MOV $1591, X7
+ JMP callbackasm1(SB)
+ MOV $1592, X7
+ JMP callbackasm1(SB)
+ MOV $1593, X7
+ JMP callbackasm1(SB)
+ MOV $1594, X7
+ JMP callbackasm1(SB)
+ MOV $1595, X7
+ JMP callbackasm1(SB)
+ MOV $1596, X7
+ JMP callbackasm1(SB)
+ MOV $1597, X7
+ JMP callbackasm1(SB)
+ MOV $1598, X7
+ JMP callbackasm1(SB)
+ MOV $1599, X7
+ JMP callbackasm1(SB)
+ MOV $1600, X7
+ JMP callbackasm1(SB)
+ MOV $1601, X7
+ JMP callbackasm1(SB)
+ MOV $1602, X7
+ JMP callbackasm1(SB)
+ MOV $1603, X7
+ JMP callbackasm1(SB)
+ MOV $1604, X7
+ JMP callbackasm1(SB)
+ MOV $1605, X7
+ JMP callbackasm1(SB)
+ MOV $1606, X7
+ JMP callbackasm1(SB)
+ MOV $1607, X7
+ JMP callbackasm1(SB)
+ MOV $1608, X7
+ JMP callbackasm1(SB)
+ MOV $1609, X7
+ JMP callbackasm1(SB)
+ MOV $1610, X7
+ JMP callbackasm1(SB)
+ MOV $1611, X7
+ JMP callbackasm1(SB)
+ MOV $1612, X7
+ JMP callbackasm1(SB)
+ MOV $1613, X7
+ JMP callbackasm1(SB)
+ MOV $1614, X7
+ JMP callbackasm1(SB)
+ MOV $1615, X7
+ JMP callbackasm1(SB)
+ MOV $1616, X7
+ JMP callbackasm1(SB)
+ MOV $1617, X7
+ JMP callbackasm1(SB)
+ MOV $1618, X7
+ JMP callbackasm1(SB)
+ MOV $1619, X7
+ JMP callbackasm1(SB)
+ MOV $1620, X7
+ JMP callbackasm1(SB)
+ MOV $1621, X7
+ JMP callbackasm1(SB)
+ MOV $1622, X7
+ JMP callbackasm1(SB)
+ MOV $1623, X7
+ JMP callbackasm1(SB)
+ MOV $1624, X7
+ JMP callbackasm1(SB)
+ MOV $1625, X7
+ JMP callbackasm1(SB)
+ MOV $1626, X7
+ JMP callbackasm1(SB)
+ MOV $1627, X7
+ JMP callbackasm1(SB)
+ MOV $1628, X7
+ JMP callbackasm1(SB)
+ MOV $1629, X7
+ JMP callbackasm1(SB)
+ MOV $1630, X7
+ JMP callbackasm1(SB)
+ MOV $1631, X7
+ JMP callbackasm1(SB)
+ MOV $1632, X7
+ JMP callbackasm1(SB)
+ MOV $1633, X7
+ JMP callbackasm1(SB)
+ MOV $1634, X7
+ JMP callbackasm1(SB)
+ MOV $1635, X7
+ JMP callbackasm1(SB)
+ MOV $1636, X7
+ JMP callbackasm1(SB)
+ MOV $1637, X7
+ JMP callbackasm1(SB)
+ MOV $1638, X7
+ JMP callbackasm1(SB)
+ MOV $1639, X7
+ JMP callbackasm1(SB)
+ MOV $1640, X7
+ JMP callbackasm1(SB)
+ MOV $1641, X7
+ JMP callbackasm1(SB)
+ MOV $1642, X7
+ JMP callbackasm1(SB)
+ MOV $1643, X7
+ JMP callbackasm1(SB)
+ MOV $1644, X7
+ JMP callbackasm1(SB)
+ MOV $1645, X7
+ JMP callbackasm1(SB)
+ MOV $1646, X7
+ JMP callbackasm1(SB)
+ MOV $1647, X7
+ JMP callbackasm1(SB)
+ MOV $1648, X7
+ JMP callbackasm1(SB)
+ MOV $1649, X7
+ JMP callbackasm1(SB)
+ MOV $1650, X7
+ JMP callbackasm1(SB)
+ MOV $1651, X7
+ JMP callbackasm1(SB)
+ MOV $1652, X7
+ JMP callbackasm1(SB)
+ MOV $1653, X7
+ JMP callbackasm1(SB)
+ MOV $1654, X7
+ JMP callbackasm1(SB)
+ MOV $1655, X7
+ JMP callbackasm1(SB)
+ MOV $1656, X7
+ JMP callbackasm1(SB)
+ MOV $1657, X7
+ JMP callbackasm1(SB)
+ MOV $1658, X7
+ JMP callbackasm1(SB)
+ MOV $1659, X7
+ JMP callbackasm1(SB)
+ MOV $1660, X7
+ JMP callbackasm1(SB)
+ MOV $1661, X7
+ JMP callbackasm1(SB)
+ MOV $1662, X7
+ JMP callbackasm1(SB)
+ MOV $1663, X7
+ JMP callbackasm1(SB)
+ MOV $1664, X7
+ JMP callbackasm1(SB)
+ MOV $1665, X7
+ JMP callbackasm1(SB)
+ MOV $1666, X7
+ JMP callbackasm1(SB)
+ MOV $1667, X7
+ JMP callbackasm1(SB)
+ MOV $1668, X7
+ JMP callbackasm1(SB)
+ MOV $1669, X7
+ JMP callbackasm1(SB)
+ MOV $1670, X7
+ JMP callbackasm1(SB)
+ MOV $1671, X7
+ JMP callbackasm1(SB)
+ MOV $1672, X7
+ JMP callbackasm1(SB)
+ MOV $1673, X7
+ JMP callbackasm1(SB)
+ MOV $1674, X7
+ JMP callbackasm1(SB)
+ MOV $1675, X7
+ JMP callbackasm1(SB)
+ MOV $1676, X7
+ JMP callbackasm1(SB)
+ MOV $1677, X7
+ JMP callbackasm1(SB)
+ MOV $1678, X7
+ JMP callbackasm1(SB)
+ MOV $1679, X7
+ JMP callbackasm1(SB)
+ MOV $1680, X7
+ JMP callbackasm1(SB)
+ MOV $1681, X7
+ JMP callbackasm1(SB)
+ MOV $1682, X7
+ JMP callbackasm1(SB)
+ MOV $1683, X7
+ JMP callbackasm1(SB)
+ MOV $1684, X7
+ JMP callbackasm1(SB)
+ MOV $1685, X7
+ JMP callbackasm1(SB)
+ MOV $1686, X7
+ JMP callbackasm1(SB)
+ MOV $1687, X7
+ JMP callbackasm1(SB)
+ MOV $1688, X7
+ JMP callbackasm1(SB)
+ MOV $1689, X7
+ JMP callbackasm1(SB)
+ MOV $1690, X7
+ JMP callbackasm1(SB)
+ MOV $1691, X7
+ JMP callbackasm1(SB)
+ MOV $1692, X7
+ JMP callbackasm1(SB)
+ MOV $1693, X7
+ JMP callbackasm1(SB)
+ MOV $1694, X7
+ JMP callbackasm1(SB)
+ MOV $1695, X7
+ JMP callbackasm1(SB)
+ MOV $1696, X7
+ JMP callbackasm1(SB)
+ MOV $1697, X7
+ JMP callbackasm1(SB)
+ MOV $1698, X7
+ JMP callbackasm1(SB)
+ MOV $1699, X7
+ JMP callbackasm1(SB)
+ MOV $1700, X7
+ JMP callbackasm1(SB)
+ MOV $1701, X7
+ JMP callbackasm1(SB)
+ MOV $1702, X7
+ JMP callbackasm1(SB)
+ MOV $1703, X7
+ JMP callbackasm1(SB)
+ MOV $1704, X7
+ JMP callbackasm1(SB)
+ MOV $1705, X7
+ JMP callbackasm1(SB)
+ MOV $1706, X7
+ JMP callbackasm1(SB)
+ MOV $1707, X7
+ JMP callbackasm1(SB)
+ MOV $1708, X7
+ JMP callbackasm1(SB)
+ MOV $1709, X7
+ JMP callbackasm1(SB)
+ MOV $1710, X7
+ JMP callbackasm1(SB)
+ MOV $1711, X7
+ JMP callbackasm1(SB)
+ MOV $1712, X7
+ JMP callbackasm1(SB)
+ MOV $1713, X7
+ JMP callbackasm1(SB)
+ MOV $1714, X7
+ JMP callbackasm1(SB)
+ MOV $1715, X7
+ JMP callbackasm1(SB)
+ MOV $1716, X7
+ JMP callbackasm1(SB)
+ MOV $1717, X7
+ JMP callbackasm1(SB)
+ MOV $1718, X7
+ JMP callbackasm1(SB)
+ MOV $1719, X7
+ JMP callbackasm1(SB)
+ MOV $1720, X7
+ JMP callbackasm1(SB)
+ MOV $1721, X7
+ JMP callbackasm1(SB)
+ MOV $1722, X7
+ JMP callbackasm1(SB)
+ MOV $1723, X7
+ JMP callbackasm1(SB)
+ MOV $1724, X7
+ JMP callbackasm1(SB)
+ MOV $1725, X7
+ JMP callbackasm1(SB)
+ MOV $1726, X7
+ JMP callbackasm1(SB)
+ MOV $1727, X7
+ JMP callbackasm1(SB)
+ MOV $1728, X7
+ JMP callbackasm1(SB)
+ MOV $1729, X7
+ JMP callbackasm1(SB)
+ MOV $1730, X7
+ JMP callbackasm1(SB)
+ MOV $1731, X7
+ JMP callbackasm1(SB)
+ MOV $1732, X7
+ JMP callbackasm1(SB)
+ MOV $1733, X7
+ JMP callbackasm1(SB)
+ MOV $1734, X7
+ JMP callbackasm1(SB)
+ MOV $1735, X7
+ JMP callbackasm1(SB)
+ MOV $1736, X7
+ JMP callbackasm1(SB)
+ MOV $1737, X7
+ JMP callbackasm1(SB)
+ MOV $1738, X7
+ JMP callbackasm1(SB)
+ MOV $1739, X7
+ JMP callbackasm1(SB)
+ MOV $1740, X7
+ JMP callbackasm1(SB)
+ MOV $1741, X7
+ JMP callbackasm1(SB)
+ MOV $1742, X7
+ JMP callbackasm1(SB)
+ MOV $1743, X7
+ JMP callbackasm1(SB)
+ MOV $1744, X7
+ JMP callbackasm1(SB)
+ MOV $1745, X7
+ JMP callbackasm1(SB)
+ MOV $1746, X7
+ JMP callbackasm1(SB)
+ MOV $1747, X7
+ JMP callbackasm1(SB)
+ MOV $1748, X7
+ JMP callbackasm1(SB)
+ MOV $1749, X7
+ JMP callbackasm1(SB)
+ MOV $1750, X7
+ JMP callbackasm1(SB)
+ MOV $1751, X7
+ JMP callbackasm1(SB)
+ MOV $1752, X7
+ JMP callbackasm1(SB)
+ MOV $1753, X7
+ JMP callbackasm1(SB)
+ MOV $1754, X7
+ JMP callbackasm1(SB)
+ MOV $1755, X7
+ JMP callbackasm1(SB)
+ MOV $1756, X7
+ JMP callbackasm1(SB)
+ MOV $1757, X7
+ JMP callbackasm1(SB)
+ MOV $1758, X7
+ JMP callbackasm1(SB)
+ MOV $1759, X7
+ JMP callbackasm1(SB)
+ MOV $1760, X7
+ JMP callbackasm1(SB)
+ MOV $1761, X7
+ JMP callbackasm1(SB)
+ MOV $1762, X7
+ JMP callbackasm1(SB)
+ MOV $1763, X7
+ JMP callbackasm1(SB)
+ MOV $1764, X7
+ JMP callbackasm1(SB)
+ MOV $1765, X7
+ JMP callbackasm1(SB)
+ MOV $1766, X7
+ JMP callbackasm1(SB)
+ MOV $1767, X7
+ JMP callbackasm1(SB)
+ MOV $1768, X7
+ JMP callbackasm1(SB)
+ MOV $1769, X7
+ JMP callbackasm1(SB)
+ MOV $1770, X7
+ JMP callbackasm1(SB)
+ MOV $1771, X7
+ JMP callbackasm1(SB)
+ MOV $1772, X7
+ JMP callbackasm1(SB)
+ MOV $1773, X7
+ JMP callbackasm1(SB)
+ MOV $1774, X7
+ JMP callbackasm1(SB)
+ MOV $1775, X7
+ JMP callbackasm1(SB)
+ MOV $1776, X7
+ JMP callbackasm1(SB)
+ MOV $1777, X7
+ JMP callbackasm1(SB)
+ MOV $1778, X7
+ JMP callbackasm1(SB)
+ MOV $1779, X7
+ JMP callbackasm1(SB)
+ MOV $1780, X7
+ JMP callbackasm1(SB)
+ MOV $1781, X7
+ JMP callbackasm1(SB)
+ MOV $1782, X7
+ JMP callbackasm1(SB)
+ MOV $1783, X7
+ JMP callbackasm1(SB)
+ MOV $1784, X7
+ JMP callbackasm1(SB)
+ MOV $1785, X7
+ JMP callbackasm1(SB)
+ MOV $1786, X7
+ JMP callbackasm1(SB)
+ MOV $1787, X7
+ JMP callbackasm1(SB)
+ MOV $1788, X7
+ JMP callbackasm1(SB)
+ MOV $1789, X7
+ JMP callbackasm1(SB)
+ MOV $1790, X7
+ JMP callbackasm1(SB)
+ MOV $1791, X7
+ JMP callbackasm1(SB)
+ MOV $1792, X7
+ JMP callbackasm1(SB)
+ MOV $1793, X7
+ JMP callbackasm1(SB)
+ MOV $1794, X7
+ JMP callbackasm1(SB)
+ MOV $1795, X7
+ JMP callbackasm1(SB)
+ MOV $1796, X7
+ JMP callbackasm1(SB)
+ MOV $1797, X7
+ JMP callbackasm1(SB)
+ MOV $1798, X7
+ JMP callbackasm1(SB)
+ MOV $1799, X7
+ JMP callbackasm1(SB)
+ MOV $1800, X7
+ JMP callbackasm1(SB)
+ MOV $1801, X7
+ JMP callbackasm1(SB)
+ MOV $1802, X7
+ JMP callbackasm1(SB)
+ MOV $1803, X7
+ JMP callbackasm1(SB)
+ MOV $1804, X7
+ JMP callbackasm1(SB)
+ MOV $1805, X7
+ JMP callbackasm1(SB)
+ MOV $1806, X7
+ JMP callbackasm1(SB)
+ MOV $1807, X7
+ JMP callbackasm1(SB)
+ MOV $1808, X7
+ JMP callbackasm1(SB)
+ MOV $1809, X7
+ JMP callbackasm1(SB)
+ MOV $1810, X7
+ JMP callbackasm1(SB)
+ MOV $1811, X7
+ JMP callbackasm1(SB)
+ MOV $1812, X7
+ JMP callbackasm1(SB)
+ MOV $1813, X7
+ JMP callbackasm1(SB)
+ MOV $1814, X7
+ JMP callbackasm1(SB)
+ MOV $1815, X7
+ JMP callbackasm1(SB)
+ MOV $1816, X7
+ JMP callbackasm1(SB)
+ MOV $1817, X7
+ JMP callbackasm1(SB)
+ MOV $1818, X7
+ JMP callbackasm1(SB)
+ MOV $1819, X7
+ JMP callbackasm1(SB)
+ MOV $1820, X7
+ JMP callbackasm1(SB)
+ MOV $1821, X7
+ JMP callbackasm1(SB)
+ MOV $1822, X7
+ JMP callbackasm1(SB)
+ MOV $1823, X7
+ JMP callbackasm1(SB)
+ MOV $1824, X7
+ JMP callbackasm1(SB)
+ MOV $1825, X7
+ JMP callbackasm1(SB)
+ MOV $1826, X7
+ JMP callbackasm1(SB)
+ MOV $1827, X7
+ JMP callbackasm1(SB)
+ MOV $1828, X7
+ JMP callbackasm1(SB)
+ MOV $1829, X7
+ JMP callbackasm1(SB)
+ MOV $1830, X7
+ JMP callbackasm1(SB)
+ MOV $1831, X7
+ JMP callbackasm1(SB)
+ MOV $1832, X7
+ JMP callbackasm1(SB)
+ MOV $1833, X7
+ JMP callbackasm1(SB)
+ MOV $1834, X7
+ JMP callbackasm1(SB)
+ MOV $1835, X7
+ JMP callbackasm1(SB)
+ MOV $1836, X7
+ JMP callbackasm1(SB)
+ MOV $1837, X7
+ JMP callbackasm1(SB)
+ MOV $1838, X7
+ JMP callbackasm1(SB)
+ MOV $1839, X7
+ JMP callbackasm1(SB)
+ MOV $1840, X7
+ JMP callbackasm1(SB)
+ MOV $1841, X7
+ JMP callbackasm1(SB)
+ MOV $1842, X7
+ JMP callbackasm1(SB)
+ MOV $1843, X7
+ JMP callbackasm1(SB)
+ MOV $1844, X7
+ JMP callbackasm1(SB)
+ MOV $1845, X7
+ JMP callbackasm1(SB)
+ MOV $1846, X7
+ JMP callbackasm1(SB)
+ MOV $1847, X7
+ JMP callbackasm1(SB)
+ MOV $1848, X7
+ JMP callbackasm1(SB)
+ MOV $1849, X7
+ JMP callbackasm1(SB)
+ MOV $1850, X7
+ JMP callbackasm1(SB)
+ MOV $1851, X7
+ JMP callbackasm1(SB)
+ MOV $1852, X7
+ JMP callbackasm1(SB)
+ MOV $1853, X7
+ JMP callbackasm1(SB)
+ MOV $1854, X7
+ JMP callbackasm1(SB)
+ MOV $1855, X7
+ JMP callbackasm1(SB)
+ MOV $1856, X7
+ JMP callbackasm1(SB)
+ MOV $1857, X7
+ JMP callbackasm1(SB)
+ MOV $1858, X7
+ JMP callbackasm1(SB)
+ MOV $1859, X7
+ JMP callbackasm1(SB)
+ MOV $1860, X7
+ JMP callbackasm1(SB)
+ MOV $1861, X7
+ JMP callbackasm1(SB)
+ MOV $1862, X7
+ JMP callbackasm1(SB)
+ MOV $1863, X7
+ JMP callbackasm1(SB)
+ MOV $1864, X7
+ JMP callbackasm1(SB)
+ MOV $1865, X7
+ JMP callbackasm1(SB)
+ MOV $1866, X7
+ JMP callbackasm1(SB)
+ MOV $1867, X7
+ JMP callbackasm1(SB)
+ MOV $1868, X7
+ JMP callbackasm1(SB)
+ MOV $1869, X7
+ JMP callbackasm1(SB)
+ MOV $1870, X7
+ JMP callbackasm1(SB)
+ MOV $1871, X7
+ JMP callbackasm1(SB)
+ MOV $1872, X7
+ JMP callbackasm1(SB)
+ MOV $1873, X7
+ JMP callbackasm1(SB)
+ MOV $1874, X7
+ JMP callbackasm1(SB)
+ MOV $1875, X7
+ JMP callbackasm1(SB)
+ MOV $1876, X7
+ JMP callbackasm1(SB)
+ MOV $1877, X7
+ JMP callbackasm1(SB)
+ MOV $1878, X7
+ JMP callbackasm1(SB)
+ MOV $1879, X7
+ JMP callbackasm1(SB)
+ MOV $1880, X7
+ JMP callbackasm1(SB)
+ MOV $1881, X7
+ JMP callbackasm1(SB)
+ MOV $1882, X7
+ JMP callbackasm1(SB)
+ MOV $1883, X7
+ JMP callbackasm1(SB)
+ MOV $1884, X7
+ JMP callbackasm1(SB)
+ MOV $1885, X7
+ JMP callbackasm1(SB)
+ MOV $1886, X7
+ JMP callbackasm1(SB)
+ MOV $1887, X7
+ JMP callbackasm1(SB)
+ MOV $1888, X7
+ JMP callbackasm1(SB)
+ MOV $1889, X7
+ JMP callbackasm1(SB)
+ MOV $1890, X7
+ JMP callbackasm1(SB)
+ MOV $1891, X7
+ JMP callbackasm1(SB)
+ MOV $1892, X7
+ JMP callbackasm1(SB)
+ MOV $1893, X7
+ JMP callbackasm1(SB)
+ MOV $1894, X7
+ JMP callbackasm1(SB)
+ MOV $1895, X7
+ JMP callbackasm1(SB)
+ MOV $1896, X7
+ JMP callbackasm1(SB)
+ MOV $1897, X7
+ JMP callbackasm1(SB)
+ MOV $1898, X7
+ JMP callbackasm1(SB)
+ MOV $1899, X7
+ JMP callbackasm1(SB)
+ MOV $1900, X7
+ JMP callbackasm1(SB)
+ MOV $1901, X7
+ JMP callbackasm1(SB)
+ MOV $1902, X7
+ JMP callbackasm1(SB)
+ MOV $1903, X7
+ JMP callbackasm1(SB)
+ MOV $1904, X7
+ JMP callbackasm1(SB)
+ MOV $1905, X7
+ JMP callbackasm1(SB)
+ MOV $1906, X7
+ JMP callbackasm1(SB)
+ MOV $1907, X7
+ JMP callbackasm1(SB)
+ MOV $1908, X7
+ JMP callbackasm1(SB)
+ MOV $1909, X7
+ JMP callbackasm1(SB)
+ MOV $1910, X7
+ JMP callbackasm1(SB)
+ MOV $1911, X7
+ JMP callbackasm1(SB)
+ MOV $1912, X7
+ JMP callbackasm1(SB)
+ MOV $1913, X7
+ JMP callbackasm1(SB)
+ MOV $1914, X7
+ JMP callbackasm1(SB)
+ MOV $1915, X7
+ JMP callbackasm1(SB)
+ MOV $1916, X7
+ JMP callbackasm1(SB)
+ MOV $1917, X7
+ JMP callbackasm1(SB)
+ MOV $1918, X7
+ JMP callbackasm1(SB)
+ MOV $1919, X7
+ JMP callbackasm1(SB)
+ MOV $1920, X7
+ JMP callbackasm1(SB)
+ MOV $1921, X7
+ JMP callbackasm1(SB)
+ MOV $1922, X7
+ JMP callbackasm1(SB)
+ MOV $1923, X7
+ JMP callbackasm1(SB)
+ MOV $1924, X7
+ JMP callbackasm1(SB)
+ MOV $1925, X7
+ JMP callbackasm1(SB)
+ MOV $1926, X7
+ JMP callbackasm1(SB)
+ MOV $1927, X7
+ JMP callbackasm1(SB)
+ MOV $1928, X7
+ JMP callbackasm1(SB)
+ MOV $1929, X7
+ JMP callbackasm1(SB)
+ MOV $1930, X7
+ JMP callbackasm1(SB)
+ MOV $1931, X7
+ JMP callbackasm1(SB)
+ MOV $1932, X7
+ JMP callbackasm1(SB)
+ MOV $1933, X7
+ JMP callbackasm1(SB)
+ MOV $1934, X7
+ JMP callbackasm1(SB)
+ MOV $1935, X7
+ JMP callbackasm1(SB)
+ MOV $1936, X7
+ JMP callbackasm1(SB)
+ MOV $1937, X7
+ JMP callbackasm1(SB)
+ MOV $1938, X7
+ JMP callbackasm1(SB)
+ MOV $1939, X7
+ JMP callbackasm1(SB)
+ MOV $1940, X7
+ JMP callbackasm1(SB)
+ MOV $1941, X7
+ JMP callbackasm1(SB)
+ MOV $1942, X7
+ JMP callbackasm1(SB)
+ MOV $1943, X7
+ JMP callbackasm1(SB)
+ MOV $1944, X7
+ JMP callbackasm1(SB)
+ MOV $1945, X7
+ JMP callbackasm1(SB)
+ MOV $1946, X7
+ JMP callbackasm1(SB)
+ MOV $1947, X7
+ JMP callbackasm1(SB)
+ MOV $1948, X7
+ JMP callbackasm1(SB)
+ MOV $1949, X7
+ JMP callbackasm1(SB)
+ MOV $1950, X7
+ JMP callbackasm1(SB)
+ MOV $1951, X7
+ JMP callbackasm1(SB)
+ MOV $1952, X7
+ JMP callbackasm1(SB)
+ MOV $1953, X7
+ JMP callbackasm1(SB)
+ MOV $1954, X7
+ JMP callbackasm1(SB)
+ MOV $1955, X7
+ JMP callbackasm1(SB)
+ MOV $1956, X7
+ JMP callbackasm1(SB)
+ MOV $1957, X7
+ JMP callbackasm1(SB)
+ MOV $1958, X7
+ JMP callbackasm1(SB)
+ MOV $1959, X7
+ JMP callbackasm1(SB)
+ MOV $1960, X7
+ JMP callbackasm1(SB)
+ MOV $1961, X7
+ JMP callbackasm1(SB)
+ MOV $1962, X7
+ JMP callbackasm1(SB)
+ MOV $1963, X7
+ JMP callbackasm1(SB)
+ MOV $1964, X7
+ JMP callbackasm1(SB)
+ MOV $1965, X7
+ JMP callbackasm1(SB)
+ MOV $1966, X7
+ JMP callbackasm1(SB)
+ MOV $1967, X7
+ JMP callbackasm1(SB)
+ MOV $1968, X7
+ JMP callbackasm1(SB)
+ MOV $1969, X7
+ JMP callbackasm1(SB)
+ MOV $1970, X7
+ JMP callbackasm1(SB)
+ MOV $1971, X7
+ JMP callbackasm1(SB)
+ MOV $1972, X7
+ JMP callbackasm1(SB)
+ MOV $1973, X7
+ JMP callbackasm1(SB)
+ MOV $1974, X7
+ JMP callbackasm1(SB)
+ MOV $1975, X7
+ JMP callbackasm1(SB)
+ MOV $1976, X7
+ JMP callbackasm1(SB)
+ MOV $1977, X7
+ JMP callbackasm1(SB)
+ MOV $1978, X7
+ JMP callbackasm1(SB)
+ MOV $1979, X7
+ JMP callbackasm1(SB)
+ MOV $1980, X7
+ JMP callbackasm1(SB)
+ MOV $1981, X7
+ JMP callbackasm1(SB)
+ MOV $1982, X7
+ JMP callbackasm1(SB)
+ MOV $1983, X7
+ JMP callbackasm1(SB)
+ MOV $1984, X7
+ JMP callbackasm1(SB)
+ MOV $1985, X7
+ JMP callbackasm1(SB)
+ MOV $1986, X7
+ JMP callbackasm1(SB)
+ MOV $1987, X7
+ JMP callbackasm1(SB)
+ MOV $1988, X7
+ JMP callbackasm1(SB)
+ MOV $1989, X7
+ JMP callbackasm1(SB)
+ MOV $1990, X7
+ JMP callbackasm1(SB)
+ MOV $1991, X7
+ JMP callbackasm1(SB)
+ MOV $1992, X7
+ JMP callbackasm1(SB)
+ MOV $1993, X7
+ JMP callbackasm1(SB)
+ MOV $1994, X7
+ JMP callbackasm1(SB)
+ MOV $1995, X7
+ JMP callbackasm1(SB)
+ MOV $1996, X7
+ JMP callbackasm1(SB)
+ MOV $1997, X7
+ JMP callbackasm1(SB)
+ MOV $1998, X7
+ JMP callbackasm1(SB)
+ MOV $1999, X7
+ JMP callbackasm1(SB)
diff --git a/raymenu/vendor/github.com/ebitengine/purego/zcallback_s390x.s b/raymenu/vendor/github.com/ebitengine/purego/zcallback_s390x.s
new file mode 100644
index 0000000..6b5e2b0
--- /dev/null
+++ b/raymenu/vendor/github.com/ebitengine/purego/zcallback_s390x.s
@@ -0,0 +1,4015 @@
+// Code generated by wincallback.go using 'go generate'. DO NOT EDIT.
+
+//go:build linux
+
+// External code calls into callbackasm at an offset corresponding
+// to the callback index. Callbackasm is a table of MOVD and BR instructions.
+// The MOVD instruction loads R0 with the callback index, and the
+// BR instruction branches to callbackasm1.
+// callbackasm1 takes the callback index from R0 and
+// indexes into an array that stores information about each callback.
+// It then calls the Go implementation for that callback.
+// NOTE: We use R0 instead of R11 because R11 is callee-saved on S390X.
+#include "textflag.h"
+
+TEXT callbackasm(SB), NOSPLIT|NOFRAME, $0
+ MOVD $0, R0
+ BR callbackasm1(SB)
+ MOVD $1, R0
+ BR callbackasm1(SB)
+ MOVD $2, R0
+ BR callbackasm1(SB)
+ MOVD $3, R0
+ BR callbackasm1(SB)
+ MOVD $4, R0
+ BR callbackasm1(SB)
+ MOVD $5, R0
+ BR callbackasm1(SB)
+ MOVD $6, R0
+ BR callbackasm1(SB)
+ MOVD $7, R0
+ BR callbackasm1(SB)
+ MOVD $8, R0
+ BR callbackasm1(SB)
+ MOVD $9, R0
+ BR callbackasm1(SB)
+ MOVD $10, R0
+ BR callbackasm1(SB)
+ MOVD $11, R0
+ BR callbackasm1(SB)
+ MOVD $12, R0
+ BR callbackasm1(SB)
+ MOVD $13, R0
+ BR callbackasm1(SB)
+ MOVD $14, R0
+ BR callbackasm1(SB)
+ MOVD $15, R0
+ BR callbackasm1(SB)
+ MOVD $16, R0
+ BR callbackasm1(SB)
+ MOVD $17, R0
+ BR callbackasm1(SB)
+ MOVD $18, R0
+ BR callbackasm1(SB)
+ MOVD $19, R0
+ BR callbackasm1(SB)
+ MOVD $20, R0
+ BR callbackasm1(SB)
+ MOVD $21, R0
+ BR callbackasm1(SB)
+ MOVD $22, R0
+ BR callbackasm1(SB)
+ MOVD $23, R0
+ BR callbackasm1(SB)
+ MOVD $24, R0
+ BR callbackasm1(SB)
+ MOVD $25, R0
+ BR callbackasm1(SB)
+ MOVD $26, R0
+ BR callbackasm1(SB)
+ MOVD $27, R0
+ BR callbackasm1(SB)
+ MOVD $28, R0
+ BR callbackasm1(SB)
+ MOVD $29, R0
+ BR callbackasm1(SB)
+ MOVD $30, R0
+ BR callbackasm1(SB)
+ MOVD $31, R0
+ BR callbackasm1(SB)
+ MOVD $32, R0
+ BR callbackasm1(SB)
+ MOVD $33, R0
+ BR callbackasm1(SB)
+ MOVD $34, R0
+ BR callbackasm1(SB)
+ MOVD $35, R0
+ BR callbackasm1(SB)
+ MOVD $36, R0
+ BR callbackasm1(SB)
+ MOVD $37, R0
+ BR callbackasm1(SB)
+ MOVD $38, R0
+ BR callbackasm1(SB)
+ MOVD $39, R0
+ BR callbackasm1(SB)
+ MOVD $40, R0
+ BR callbackasm1(SB)
+ MOVD $41, R0
+ BR callbackasm1(SB)
+ MOVD $42, R0
+ BR callbackasm1(SB)
+ MOVD $43, R0
+ BR callbackasm1(SB)
+ MOVD $44, R0
+ BR callbackasm1(SB)
+ MOVD $45, R0
+ BR callbackasm1(SB)
+ MOVD $46, R0
+ BR callbackasm1(SB)
+ MOVD $47, R0
+ BR callbackasm1(SB)
+ MOVD $48, R0
+ BR callbackasm1(SB)
+ MOVD $49, R0
+ BR callbackasm1(SB)
+ MOVD $50, R0
+ BR callbackasm1(SB)
+ MOVD $51, R0
+ BR callbackasm1(SB)
+ MOVD $52, R0
+ BR callbackasm1(SB)
+ MOVD $53, R0
+ BR callbackasm1(SB)
+ MOVD $54, R0
+ BR callbackasm1(SB)
+ MOVD $55, R0
+ BR callbackasm1(SB)
+ MOVD $56, R0
+ BR callbackasm1(SB)
+ MOVD $57, R0
+ BR callbackasm1(SB)
+ MOVD $58, R0
+ BR callbackasm1(SB)
+ MOVD $59, R0
+ BR callbackasm1(SB)
+ MOVD $60, R0
+ BR callbackasm1(SB)
+ MOVD $61, R0
+ BR callbackasm1(SB)
+ MOVD $62, R0
+ BR callbackasm1(SB)
+ MOVD $63, R0
+ BR callbackasm1(SB)
+ MOVD $64, R0
+ BR callbackasm1(SB)
+ MOVD $65, R0
+ BR callbackasm1(SB)
+ MOVD $66, R0
+ BR callbackasm1(SB)
+ MOVD $67, R0
+ BR callbackasm1(SB)
+ MOVD $68, R0
+ BR callbackasm1(SB)
+ MOVD $69, R0
+ BR callbackasm1(SB)
+ MOVD $70, R0
+ BR callbackasm1(SB)
+ MOVD $71, R0
+ BR callbackasm1(SB)
+ MOVD $72, R0
+ BR callbackasm1(SB)
+ MOVD $73, R0
+ BR callbackasm1(SB)
+ MOVD $74, R0
+ BR callbackasm1(SB)
+ MOVD $75, R0
+ BR callbackasm1(SB)
+ MOVD $76, R0
+ BR callbackasm1(SB)
+ MOVD $77, R0
+ BR callbackasm1(SB)
+ MOVD $78, R0
+ BR callbackasm1(SB)
+ MOVD $79, R0
+ BR callbackasm1(SB)
+ MOVD $80, R0
+ BR callbackasm1(SB)
+ MOVD $81, R0
+ BR callbackasm1(SB)
+ MOVD $82, R0
+ BR callbackasm1(SB)
+ MOVD $83, R0
+ BR callbackasm1(SB)
+ MOVD $84, R0
+ BR callbackasm1(SB)
+ MOVD $85, R0
+ BR callbackasm1(SB)
+ MOVD $86, R0
+ BR callbackasm1(SB)
+ MOVD $87, R0
+ BR callbackasm1(SB)
+ MOVD $88, R0
+ BR callbackasm1(SB)
+ MOVD $89, R0
+ BR callbackasm1(SB)
+ MOVD $90, R0
+ BR callbackasm1(SB)
+ MOVD $91, R0
+ BR callbackasm1(SB)
+ MOVD $92, R0
+ BR callbackasm1(SB)
+ MOVD $93, R0
+ BR callbackasm1(SB)
+ MOVD $94, R0
+ BR callbackasm1(SB)
+ MOVD $95, R0
+ BR callbackasm1(SB)
+ MOVD $96, R0
+ BR callbackasm1(SB)
+ MOVD $97, R0
+ BR callbackasm1(SB)
+ MOVD $98, R0
+ BR callbackasm1(SB)
+ MOVD $99, R0
+ BR callbackasm1(SB)
+ MOVD $100, R0
+ BR callbackasm1(SB)
+ MOVD $101, R0
+ BR callbackasm1(SB)
+ MOVD $102, R0
+ BR callbackasm1(SB)
+ MOVD $103, R0
+ BR callbackasm1(SB)
+ MOVD $104, R0
+ BR callbackasm1(SB)
+ MOVD $105, R0
+ BR callbackasm1(SB)
+ MOVD $106, R0
+ BR callbackasm1(SB)
+ MOVD $107, R0
+ BR callbackasm1(SB)
+ MOVD $108, R0
+ BR callbackasm1(SB)
+ MOVD $109, R0
+ BR callbackasm1(SB)
+ MOVD $110, R0
+ BR callbackasm1(SB)
+ MOVD $111, R0
+ BR callbackasm1(SB)
+ MOVD $112, R0
+ BR callbackasm1(SB)
+ MOVD $113, R0
+ BR callbackasm1(SB)
+ MOVD $114, R0
+ BR callbackasm1(SB)
+ MOVD $115, R0
+ BR callbackasm1(SB)
+ MOVD $116, R0
+ BR callbackasm1(SB)
+ MOVD $117, R0
+ BR callbackasm1(SB)
+ MOVD $118, R0
+ BR callbackasm1(SB)
+ MOVD $119, R0
+ BR callbackasm1(SB)
+ MOVD $120, R0
+ BR callbackasm1(SB)
+ MOVD $121, R0
+ BR callbackasm1(SB)
+ MOVD $122, R0
+ BR callbackasm1(SB)
+ MOVD $123, R0
+ BR callbackasm1(SB)
+ MOVD $124, R0
+ BR callbackasm1(SB)
+ MOVD $125, R0
+ BR callbackasm1(SB)
+ MOVD $126, R0
+ BR callbackasm1(SB)
+ MOVD $127, R0
+ BR callbackasm1(SB)
+ MOVD $128, R0
+ BR callbackasm1(SB)
+ MOVD $129, R0
+ BR callbackasm1(SB)
+ MOVD $130, R0
+ BR callbackasm1(SB)
+ MOVD $131, R0
+ BR callbackasm1(SB)
+ MOVD $132, R0
+ BR callbackasm1(SB)
+ MOVD $133, R0
+ BR callbackasm1(SB)
+ MOVD $134, R0
+ BR callbackasm1(SB)
+ MOVD $135, R0
+ BR callbackasm1(SB)
+ MOVD $136, R0
+ BR callbackasm1(SB)
+ MOVD $137, R0
+ BR callbackasm1(SB)
+ MOVD $138, R0
+ BR callbackasm1(SB)
+ MOVD $139, R0
+ BR callbackasm1(SB)
+ MOVD $140, R0
+ BR callbackasm1(SB)
+ MOVD $141, R0
+ BR callbackasm1(SB)
+ MOVD $142, R0
+ BR callbackasm1(SB)
+ MOVD $143, R0
+ BR callbackasm1(SB)
+ MOVD $144, R0
+ BR callbackasm1(SB)
+ MOVD $145, R0
+ BR callbackasm1(SB)
+ MOVD $146, R0
+ BR callbackasm1(SB)
+ MOVD $147, R0
+ BR callbackasm1(SB)
+ MOVD $148, R0
+ BR callbackasm1(SB)
+ MOVD $149, R0
+ BR callbackasm1(SB)
+ MOVD $150, R0
+ BR callbackasm1(SB)
+ MOVD $151, R0
+ BR callbackasm1(SB)
+ MOVD $152, R0
+ BR callbackasm1(SB)
+ MOVD $153, R0
+ BR callbackasm1(SB)
+ MOVD $154, R0
+ BR callbackasm1(SB)
+ MOVD $155, R0
+ BR callbackasm1(SB)
+ MOVD $156, R0
+ BR callbackasm1(SB)
+ MOVD $157, R0
+ BR callbackasm1(SB)
+ MOVD $158, R0
+ BR callbackasm1(SB)
+ MOVD $159, R0
+ BR callbackasm1(SB)
+ MOVD $160, R0
+ BR callbackasm1(SB)
+ MOVD $161, R0
+ BR callbackasm1(SB)
+ MOVD $162, R0
+ BR callbackasm1(SB)
+ MOVD $163, R0
+ BR callbackasm1(SB)
+ MOVD $164, R0
+ BR callbackasm1(SB)
+ MOVD $165, R0
+ BR callbackasm1(SB)
+ MOVD $166, R0
+ BR callbackasm1(SB)
+ MOVD $167, R0
+ BR callbackasm1(SB)
+ MOVD $168, R0
+ BR callbackasm1(SB)
+ MOVD $169, R0
+ BR callbackasm1(SB)
+ MOVD $170, R0
+ BR callbackasm1(SB)
+ MOVD $171, R0
+ BR callbackasm1(SB)
+ MOVD $172, R0
+ BR callbackasm1(SB)
+ MOVD $173, R0
+ BR callbackasm1(SB)
+ MOVD $174, R0
+ BR callbackasm1(SB)
+ MOVD $175, R0
+ BR callbackasm1(SB)
+ MOVD $176, R0
+ BR callbackasm1(SB)
+ MOVD $177, R0
+ BR callbackasm1(SB)
+ MOVD $178, R0
+ BR callbackasm1(SB)
+ MOVD $179, R0
+ BR callbackasm1(SB)
+ MOVD $180, R0
+ BR callbackasm1(SB)
+ MOVD $181, R0
+ BR callbackasm1(SB)
+ MOVD $182, R0
+ BR callbackasm1(SB)
+ MOVD $183, R0
+ BR callbackasm1(SB)
+ MOVD $184, R0
+ BR callbackasm1(SB)
+ MOVD $185, R0
+ BR callbackasm1(SB)
+ MOVD $186, R0
+ BR callbackasm1(SB)
+ MOVD $187, R0
+ BR callbackasm1(SB)
+ MOVD $188, R0
+ BR callbackasm1(SB)
+ MOVD $189, R0
+ BR callbackasm1(SB)
+ MOVD $190, R0
+ BR callbackasm1(SB)
+ MOVD $191, R0
+ BR callbackasm1(SB)
+ MOVD $192, R0
+ BR callbackasm1(SB)
+ MOVD $193, R0
+ BR callbackasm1(SB)
+ MOVD $194, R0
+ BR callbackasm1(SB)
+ MOVD $195, R0
+ BR callbackasm1(SB)
+ MOVD $196, R0
+ BR callbackasm1(SB)
+ MOVD $197, R0
+ BR callbackasm1(SB)
+ MOVD $198, R0
+ BR callbackasm1(SB)
+ MOVD $199, R0
+ BR callbackasm1(SB)
+ MOVD $200, R0
+ BR callbackasm1(SB)
+ MOVD $201, R0
+ BR callbackasm1(SB)
+ MOVD $202, R0
+ BR callbackasm1(SB)
+ MOVD $203, R0
+ BR callbackasm1(SB)
+ MOVD $204, R0
+ BR callbackasm1(SB)
+ MOVD $205, R0
+ BR callbackasm1(SB)
+ MOVD $206, R0
+ BR callbackasm1(SB)
+ MOVD $207, R0
+ BR callbackasm1(SB)
+ MOVD $208, R0
+ BR callbackasm1(SB)
+ MOVD $209, R0
+ BR callbackasm1(SB)
+ MOVD $210, R0
+ BR callbackasm1(SB)
+ MOVD $211, R0
+ BR callbackasm1(SB)
+ MOVD $212, R0
+ BR callbackasm1(SB)
+ MOVD $213, R0
+ BR callbackasm1(SB)
+ MOVD $214, R0
+ BR callbackasm1(SB)
+ MOVD $215, R0
+ BR callbackasm1(SB)
+ MOVD $216, R0
+ BR callbackasm1(SB)
+ MOVD $217, R0
+ BR callbackasm1(SB)
+ MOVD $218, R0
+ BR callbackasm1(SB)
+ MOVD $219, R0
+ BR callbackasm1(SB)
+ MOVD $220, R0
+ BR callbackasm1(SB)
+ MOVD $221, R0
+ BR callbackasm1(SB)
+ MOVD $222, R0
+ BR callbackasm1(SB)
+ MOVD $223, R0
+ BR callbackasm1(SB)
+ MOVD $224, R0
+ BR callbackasm1(SB)
+ MOVD $225, R0
+ BR callbackasm1(SB)
+ MOVD $226, R0
+ BR callbackasm1(SB)
+ MOVD $227, R0
+ BR callbackasm1(SB)
+ MOVD $228, R0
+ BR callbackasm1(SB)
+ MOVD $229, R0
+ BR callbackasm1(SB)
+ MOVD $230, R0
+ BR callbackasm1(SB)
+ MOVD $231, R0
+ BR callbackasm1(SB)
+ MOVD $232, R0
+ BR callbackasm1(SB)
+ MOVD $233, R0
+ BR callbackasm1(SB)
+ MOVD $234, R0
+ BR callbackasm1(SB)
+ MOVD $235, R0
+ BR callbackasm1(SB)
+ MOVD $236, R0
+ BR callbackasm1(SB)
+ MOVD $237, R0
+ BR callbackasm1(SB)
+ MOVD $238, R0
+ BR callbackasm1(SB)
+ MOVD $239, R0
+ BR callbackasm1(SB)
+ MOVD $240, R0
+ BR callbackasm1(SB)
+ MOVD $241, R0
+ BR callbackasm1(SB)
+ MOVD $242, R0
+ BR callbackasm1(SB)
+ MOVD $243, R0
+ BR callbackasm1(SB)
+ MOVD $244, R0
+ BR callbackasm1(SB)
+ MOVD $245, R0
+ BR callbackasm1(SB)
+ MOVD $246, R0
+ BR callbackasm1(SB)
+ MOVD $247, R0
+ BR callbackasm1(SB)
+ MOVD $248, R0
+ BR callbackasm1(SB)
+ MOVD $249, R0
+ BR callbackasm1(SB)
+ MOVD $250, R0
+ BR callbackasm1(SB)
+ MOVD $251, R0
+ BR callbackasm1(SB)
+ MOVD $252, R0
+ BR callbackasm1(SB)
+ MOVD $253, R0
+ BR callbackasm1(SB)
+ MOVD $254, R0
+ BR callbackasm1(SB)
+ MOVD $255, R0
+ BR callbackasm1(SB)
+ MOVD $256, R0
+ BR callbackasm1(SB)
+ MOVD $257, R0
+ BR callbackasm1(SB)
+ MOVD $258, R0
+ BR callbackasm1(SB)
+ MOVD $259, R0
+ BR callbackasm1(SB)
+ MOVD $260, R0
+ BR callbackasm1(SB)
+ MOVD $261, R0
+ BR callbackasm1(SB)
+ MOVD $262, R0
+ BR callbackasm1(SB)
+ MOVD $263, R0
+ BR callbackasm1(SB)
+ MOVD $264, R0
+ BR callbackasm1(SB)
+ MOVD $265, R0
+ BR callbackasm1(SB)
+ MOVD $266, R0
+ BR callbackasm1(SB)
+ MOVD $267, R0
+ BR callbackasm1(SB)
+ MOVD $268, R0
+ BR callbackasm1(SB)
+ MOVD $269, R0
+ BR callbackasm1(SB)
+ MOVD $270, R0
+ BR callbackasm1(SB)
+ MOVD $271, R0
+ BR callbackasm1(SB)
+ MOVD $272, R0
+ BR callbackasm1(SB)
+ MOVD $273, R0
+ BR callbackasm1(SB)
+ MOVD $274, R0
+ BR callbackasm1(SB)
+ MOVD $275, R0
+ BR callbackasm1(SB)
+ MOVD $276, R0
+ BR callbackasm1(SB)
+ MOVD $277, R0
+ BR callbackasm1(SB)
+ MOVD $278, R0
+ BR callbackasm1(SB)
+ MOVD $279, R0
+ BR callbackasm1(SB)
+ MOVD $280, R0
+ BR callbackasm1(SB)
+ MOVD $281, R0
+ BR callbackasm1(SB)
+ MOVD $282, R0
+ BR callbackasm1(SB)
+ MOVD $283, R0
+ BR callbackasm1(SB)
+ MOVD $284, R0
+ BR callbackasm1(SB)
+ MOVD $285, R0
+ BR callbackasm1(SB)
+ MOVD $286, R0
+ BR callbackasm1(SB)
+ MOVD $287, R0
+ BR callbackasm1(SB)
+ MOVD $288, R0
+ BR callbackasm1(SB)
+ MOVD $289, R0
+ BR callbackasm1(SB)
+ MOVD $290, R0
+ BR callbackasm1(SB)
+ MOVD $291, R0
+ BR callbackasm1(SB)
+ MOVD $292, R0
+ BR callbackasm1(SB)
+ MOVD $293, R0
+ BR callbackasm1(SB)
+ MOVD $294, R0
+ BR callbackasm1(SB)
+ MOVD $295, R0
+ BR callbackasm1(SB)
+ MOVD $296, R0
+ BR callbackasm1(SB)
+ MOVD $297, R0
+ BR callbackasm1(SB)
+ MOVD $298, R0
+ BR callbackasm1(SB)
+ MOVD $299, R0
+ BR callbackasm1(SB)
+ MOVD $300, R0
+ BR callbackasm1(SB)
+ MOVD $301, R0
+ BR callbackasm1(SB)
+ MOVD $302, R0
+ BR callbackasm1(SB)
+ MOVD $303, R0
+ BR callbackasm1(SB)
+ MOVD $304, R0
+ BR callbackasm1(SB)
+ MOVD $305, R0
+ BR callbackasm1(SB)
+ MOVD $306, R0
+ BR callbackasm1(SB)
+ MOVD $307, R0
+ BR callbackasm1(SB)
+ MOVD $308, R0
+ BR callbackasm1(SB)
+ MOVD $309, R0
+ BR callbackasm1(SB)
+ MOVD $310, R0
+ BR callbackasm1(SB)
+ MOVD $311, R0
+ BR callbackasm1(SB)
+ MOVD $312, R0
+ BR callbackasm1(SB)
+ MOVD $313, R0
+ BR callbackasm1(SB)
+ MOVD $314, R0
+ BR callbackasm1(SB)
+ MOVD $315, R0
+ BR callbackasm1(SB)
+ MOVD $316, R0
+ BR callbackasm1(SB)
+ MOVD $317, R0
+ BR callbackasm1(SB)
+ MOVD $318, R0
+ BR callbackasm1(SB)
+ MOVD $319, R0
+ BR callbackasm1(SB)
+ MOVD $320, R0
+ BR callbackasm1(SB)
+ MOVD $321, R0
+ BR callbackasm1(SB)
+ MOVD $322, R0
+ BR callbackasm1(SB)
+ MOVD $323, R0
+ BR callbackasm1(SB)
+ MOVD $324, R0
+ BR callbackasm1(SB)
+ MOVD $325, R0
+ BR callbackasm1(SB)
+ MOVD $326, R0
+ BR callbackasm1(SB)
+ MOVD $327, R0
+ BR callbackasm1(SB)
+ MOVD $328, R0
+ BR callbackasm1(SB)
+ MOVD $329, R0
+ BR callbackasm1(SB)
+ MOVD $330, R0
+ BR callbackasm1(SB)
+ MOVD $331, R0
+ BR callbackasm1(SB)
+ MOVD $332, R0
+ BR callbackasm1(SB)
+ MOVD $333, R0
+ BR callbackasm1(SB)
+ MOVD $334, R0
+ BR callbackasm1(SB)
+ MOVD $335, R0
+ BR callbackasm1(SB)
+ MOVD $336, R0
+ BR callbackasm1(SB)
+ MOVD $337, R0
+ BR callbackasm1(SB)
+ MOVD $338, R0
+ BR callbackasm1(SB)
+ MOVD $339, R0
+ BR callbackasm1(SB)
+ MOVD $340, R0
+ BR callbackasm1(SB)
+ MOVD $341, R0
+ BR callbackasm1(SB)
+ MOVD $342, R0
+ BR callbackasm1(SB)
+ MOVD $343, R0
+ BR callbackasm1(SB)
+ MOVD $344, R0
+ BR callbackasm1(SB)
+ MOVD $345, R0
+ BR callbackasm1(SB)
+ MOVD $346, R0
+ BR callbackasm1(SB)
+ MOVD $347, R0
+ BR callbackasm1(SB)
+ MOVD $348, R0
+ BR callbackasm1(SB)
+ MOVD $349, R0
+ BR callbackasm1(SB)
+ MOVD $350, R0
+ BR callbackasm1(SB)
+ MOVD $351, R0
+ BR callbackasm1(SB)
+ MOVD $352, R0
+ BR callbackasm1(SB)
+ MOVD $353, R0
+ BR callbackasm1(SB)
+ MOVD $354, R0
+ BR callbackasm1(SB)
+ MOVD $355, R0
+ BR callbackasm1(SB)
+ MOVD $356, R0
+ BR callbackasm1(SB)
+ MOVD $357, R0
+ BR callbackasm1(SB)
+ MOVD $358, R0
+ BR callbackasm1(SB)
+ MOVD $359, R0
+ BR callbackasm1(SB)
+ MOVD $360, R0
+ BR callbackasm1(SB)
+ MOVD $361, R0
+ BR callbackasm1(SB)
+ MOVD $362, R0
+ BR callbackasm1(SB)
+ MOVD $363, R0
+ BR callbackasm1(SB)
+ MOVD $364, R0
+ BR callbackasm1(SB)
+ MOVD $365, R0
+ BR callbackasm1(SB)
+ MOVD $366, R0
+ BR callbackasm1(SB)
+ MOVD $367, R0
+ BR callbackasm1(SB)
+ MOVD $368, R0
+ BR callbackasm1(SB)
+ MOVD $369, R0
+ BR callbackasm1(SB)
+ MOVD $370, R0
+ BR callbackasm1(SB)
+ MOVD $371, R0
+ BR callbackasm1(SB)
+ MOVD $372, R0
+ BR callbackasm1(SB)
+ MOVD $373, R0
+ BR callbackasm1(SB)
+ MOVD $374, R0
+ BR callbackasm1(SB)
+ MOVD $375, R0
+ BR callbackasm1(SB)
+ MOVD $376, R0
+ BR callbackasm1(SB)
+ MOVD $377, R0
+ BR callbackasm1(SB)
+ MOVD $378, R0
+ BR callbackasm1(SB)
+ MOVD $379, R0
+ BR callbackasm1(SB)
+ MOVD $380, R0
+ BR callbackasm1(SB)
+ MOVD $381, R0
+ BR callbackasm1(SB)
+ MOVD $382, R0
+ BR callbackasm1(SB)
+ MOVD $383, R0
+ BR callbackasm1(SB)
+ MOVD $384, R0
+ BR callbackasm1(SB)
+ MOVD $385, R0
+ BR callbackasm1(SB)
+ MOVD $386, R0
+ BR callbackasm1(SB)
+ MOVD $387, R0
+ BR callbackasm1(SB)
+ MOVD $388, R0
+ BR callbackasm1(SB)
+ MOVD $389, R0
+ BR callbackasm1(SB)
+ MOVD $390, R0
+ BR callbackasm1(SB)
+ MOVD $391, R0
+ BR callbackasm1(SB)
+ MOVD $392, R0
+ BR callbackasm1(SB)
+ MOVD $393, R0
+ BR callbackasm1(SB)
+ MOVD $394, R0
+ BR callbackasm1(SB)
+ MOVD $395, R0
+ BR callbackasm1(SB)
+ MOVD $396, R0
+ BR callbackasm1(SB)
+ MOVD $397, R0
+ BR callbackasm1(SB)
+ MOVD $398, R0
+ BR callbackasm1(SB)
+ MOVD $399, R0
+ BR callbackasm1(SB)
+ MOVD $400, R0
+ BR callbackasm1(SB)
+ MOVD $401, R0
+ BR callbackasm1(SB)
+ MOVD $402, R0
+ BR callbackasm1(SB)
+ MOVD $403, R0
+ BR callbackasm1(SB)
+ MOVD $404, R0
+ BR callbackasm1(SB)
+ MOVD $405, R0
+ BR callbackasm1(SB)
+ MOVD $406, R0
+ BR callbackasm1(SB)
+ MOVD $407, R0
+ BR callbackasm1(SB)
+ MOVD $408, R0
+ BR callbackasm1(SB)
+ MOVD $409, R0
+ BR callbackasm1(SB)
+ MOVD $410, R0
+ BR callbackasm1(SB)
+ MOVD $411, R0
+ BR callbackasm1(SB)
+ MOVD $412, R0
+ BR callbackasm1(SB)
+ MOVD $413, R0
+ BR callbackasm1(SB)
+ MOVD $414, R0
+ BR callbackasm1(SB)
+ MOVD $415, R0
+ BR callbackasm1(SB)
+ MOVD $416, R0
+ BR callbackasm1(SB)
+ MOVD $417, R0
+ BR callbackasm1(SB)
+ MOVD $418, R0
+ BR callbackasm1(SB)
+ MOVD $419, R0
+ BR callbackasm1(SB)
+ MOVD $420, R0
+ BR callbackasm1(SB)
+ MOVD $421, R0
+ BR callbackasm1(SB)
+ MOVD $422, R0
+ BR callbackasm1(SB)
+ MOVD $423, R0
+ BR callbackasm1(SB)
+ MOVD $424, R0
+ BR callbackasm1(SB)
+ MOVD $425, R0
+ BR callbackasm1(SB)
+ MOVD $426, R0
+ BR callbackasm1(SB)
+ MOVD $427, R0
+ BR callbackasm1(SB)
+ MOVD $428, R0
+ BR callbackasm1(SB)
+ MOVD $429, R0
+ BR callbackasm1(SB)
+ MOVD $430, R0
+ BR callbackasm1(SB)
+ MOVD $431, R0
+ BR callbackasm1(SB)
+ MOVD $432, R0
+ BR callbackasm1(SB)
+ MOVD $433, R0
+ BR callbackasm1(SB)
+ MOVD $434, R0
+ BR callbackasm1(SB)
+ MOVD $435, R0
+ BR callbackasm1(SB)
+ MOVD $436, R0
+ BR callbackasm1(SB)
+ MOVD $437, R0
+ BR callbackasm1(SB)
+ MOVD $438, R0
+ BR callbackasm1(SB)
+ MOVD $439, R0
+ BR callbackasm1(SB)
+ MOVD $440, R0
+ BR callbackasm1(SB)
+ MOVD $441, R0
+ BR callbackasm1(SB)
+ MOVD $442, R0
+ BR callbackasm1(SB)
+ MOVD $443, R0
+ BR callbackasm1(SB)
+ MOVD $444, R0
+ BR callbackasm1(SB)
+ MOVD $445, R0
+ BR callbackasm1(SB)
+ MOVD $446, R0
+ BR callbackasm1(SB)
+ MOVD $447, R0
+ BR callbackasm1(SB)
+ MOVD $448, R0
+ BR callbackasm1(SB)
+ MOVD $449, R0
+ BR callbackasm1(SB)
+ MOVD $450, R0
+ BR callbackasm1(SB)
+ MOVD $451, R0
+ BR callbackasm1(SB)
+ MOVD $452, R0
+ BR callbackasm1(SB)
+ MOVD $453, R0
+ BR callbackasm1(SB)
+ MOVD $454, R0
+ BR callbackasm1(SB)
+ MOVD $455, R0
+ BR callbackasm1(SB)
+ MOVD $456, R0
+ BR callbackasm1(SB)
+ MOVD $457, R0
+ BR callbackasm1(SB)
+ MOVD $458, R0
+ BR callbackasm1(SB)
+ MOVD $459, R0
+ BR callbackasm1(SB)
+ MOVD $460, R0
+ BR callbackasm1(SB)
+ MOVD $461, R0
+ BR callbackasm1(SB)
+ MOVD $462, R0
+ BR callbackasm1(SB)
+ MOVD $463, R0
+ BR callbackasm1(SB)
+ MOVD $464, R0
+ BR callbackasm1(SB)
+ MOVD $465, R0
+ BR callbackasm1(SB)
+ MOVD $466, R0
+ BR callbackasm1(SB)
+ MOVD $467, R0
+ BR callbackasm1(SB)
+ MOVD $468, R0
+ BR callbackasm1(SB)
+ MOVD $469, R0
+ BR callbackasm1(SB)
+ MOVD $470, R0
+ BR callbackasm1(SB)
+ MOVD $471, R0
+ BR callbackasm1(SB)
+ MOVD $472, R0
+ BR callbackasm1(SB)
+ MOVD $473, R0
+ BR callbackasm1(SB)
+ MOVD $474, R0
+ BR callbackasm1(SB)
+ MOVD $475, R0
+ BR callbackasm1(SB)
+ MOVD $476, R0
+ BR callbackasm1(SB)
+ MOVD $477, R0
+ BR callbackasm1(SB)
+ MOVD $478, R0
+ BR callbackasm1(SB)
+ MOVD $479, R0
+ BR callbackasm1(SB)
+ MOVD $480, R0
+ BR callbackasm1(SB)
+ MOVD $481, R0
+ BR callbackasm1(SB)
+ MOVD $482, R0
+ BR callbackasm1(SB)
+ MOVD $483, R0
+ BR callbackasm1(SB)
+ MOVD $484, R0
+ BR callbackasm1(SB)
+ MOVD $485, R0
+ BR callbackasm1(SB)
+ MOVD $486, R0
+ BR callbackasm1(SB)
+ MOVD $487, R0
+ BR callbackasm1(SB)
+ MOVD $488, R0
+ BR callbackasm1(SB)
+ MOVD $489, R0
+ BR callbackasm1(SB)
+ MOVD $490, R0
+ BR callbackasm1(SB)
+ MOVD $491, R0
+ BR callbackasm1(SB)
+ MOVD $492, R0
+ BR callbackasm1(SB)
+ MOVD $493, R0
+ BR callbackasm1(SB)
+ MOVD $494, R0
+ BR callbackasm1(SB)
+ MOVD $495, R0
+ BR callbackasm1(SB)
+ MOVD $496, R0
+ BR callbackasm1(SB)
+ MOVD $497, R0
+ BR callbackasm1(SB)
+ MOVD $498, R0
+ BR callbackasm1(SB)
+ MOVD $499, R0
+ BR callbackasm1(SB)
+ MOVD $500, R0
+ BR callbackasm1(SB)
+ MOVD $501, R0
+ BR callbackasm1(SB)
+ MOVD $502, R0
+ BR callbackasm1(SB)
+ MOVD $503, R0
+ BR callbackasm1(SB)
+ MOVD $504, R0
+ BR callbackasm1(SB)
+ MOVD $505, R0
+ BR callbackasm1(SB)
+ MOVD $506, R0
+ BR callbackasm1(SB)
+ MOVD $507, R0
+ BR callbackasm1(SB)
+ MOVD $508, R0
+ BR callbackasm1(SB)
+ MOVD $509, R0
+ BR callbackasm1(SB)
+ MOVD $510, R0
+ BR callbackasm1(SB)
+ MOVD $511, R0
+ BR callbackasm1(SB)
+ MOVD $512, R0
+ BR callbackasm1(SB)
+ MOVD $513, R0
+ BR callbackasm1(SB)
+ MOVD $514, R0
+ BR callbackasm1(SB)
+ MOVD $515, R0
+ BR callbackasm1(SB)
+ MOVD $516, R0
+ BR callbackasm1(SB)
+ MOVD $517, R0
+ BR callbackasm1(SB)
+ MOVD $518, R0
+ BR callbackasm1(SB)
+ MOVD $519, R0
+ BR callbackasm1(SB)
+ MOVD $520, R0
+ BR callbackasm1(SB)
+ MOVD $521, R0
+ BR callbackasm1(SB)
+ MOVD $522, R0
+ BR callbackasm1(SB)
+ MOVD $523, R0
+ BR callbackasm1(SB)
+ MOVD $524, R0
+ BR callbackasm1(SB)
+ MOVD $525, R0
+ BR callbackasm1(SB)
+ MOVD $526, R0
+ BR callbackasm1(SB)
+ MOVD $527, R0
+ BR callbackasm1(SB)
+ MOVD $528, R0
+ BR callbackasm1(SB)
+ MOVD $529, R0
+ BR callbackasm1(SB)
+ MOVD $530, R0
+ BR callbackasm1(SB)
+ MOVD $531, R0
+ BR callbackasm1(SB)
+ MOVD $532, R0
+ BR callbackasm1(SB)
+ MOVD $533, R0
+ BR callbackasm1(SB)
+ MOVD $534, R0
+ BR callbackasm1(SB)
+ MOVD $535, R0
+ BR callbackasm1(SB)
+ MOVD $536, R0
+ BR callbackasm1(SB)
+ MOVD $537, R0
+ BR callbackasm1(SB)
+ MOVD $538, R0
+ BR callbackasm1(SB)
+ MOVD $539, R0
+ BR callbackasm1(SB)
+ MOVD $540, R0
+ BR callbackasm1(SB)
+ MOVD $541, R0
+ BR callbackasm1(SB)
+ MOVD $542, R0
+ BR callbackasm1(SB)
+ MOVD $543, R0
+ BR callbackasm1(SB)
+ MOVD $544, R0
+ BR callbackasm1(SB)
+ MOVD $545, R0
+ BR callbackasm1(SB)
+ MOVD $546, R0
+ BR callbackasm1(SB)
+ MOVD $547, R0
+ BR callbackasm1(SB)
+ MOVD $548, R0
+ BR callbackasm1(SB)
+ MOVD $549, R0
+ BR callbackasm1(SB)
+ MOVD $550, R0
+ BR callbackasm1(SB)
+ MOVD $551, R0
+ BR callbackasm1(SB)
+ MOVD $552, R0
+ BR callbackasm1(SB)
+ MOVD $553, R0
+ BR callbackasm1(SB)
+ MOVD $554, R0
+ BR callbackasm1(SB)
+ MOVD $555, R0
+ BR callbackasm1(SB)
+ MOVD $556, R0
+ BR callbackasm1(SB)
+ MOVD $557, R0
+ BR callbackasm1(SB)
+ MOVD $558, R0
+ BR callbackasm1(SB)
+ MOVD $559, R0
+ BR callbackasm1(SB)
+ MOVD $560, R0
+ BR callbackasm1(SB)
+ MOVD $561, R0
+ BR callbackasm1(SB)
+ MOVD $562, R0
+ BR callbackasm1(SB)
+ MOVD $563, R0
+ BR callbackasm1(SB)
+ MOVD $564, R0
+ BR callbackasm1(SB)
+ MOVD $565, R0
+ BR callbackasm1(SB)
+ MOVD $566, R0
+ BR callbackasm1(SB)
+ MOVD $567, R0
+ BR callbackasm1(SB)
+ MOVD $568, R0
+ BR callbackasm1(SB)
+ MOVD $569, R0
+ BR callbackasm1(SB)
+ MOVD $570, R0
+ BR callbackasm1(SB)
+ MOVD $571, R0
+ BR callbackasm1(SB)
+ MOVD $572, R0
+ BR callbackasm1(SB)
+ MOVD $573, R0
+ BR callbackasm1(SB)
+ MOVD $574, R0
+ BR callbackasm1(SB)
+ MOVD $575, R0
+ BR callbackasm1(SB)
+ MOVD $576, R0
+ BR callbackasm1(SB)
+ MOVD $577, R0
+ BR callbackasm1(SB)
+ MOVD $578, R0
+ BR callbackasm1(SB)
+ MOVD $579, R0
+ BR callbackasm1(SB)
+ MOVD $580, R0
+ BR callbackasm1(SB)
+ MOVD $581, R0
+ BR callbackasm1(SB)
+ MOVD $582, R0
+ BR callbackasm1(SB)
+ MOVD $583, R0
+ BR callbackasm1(SB)
+ MOVD $584, R0
+ BR callbackasm1(SB)
+ MOVD $585, R0
+ BR callbackasm1(SB)
+ MOVD $586, R0
+ BR callbackasm1(SB)
+ MOVD $587, R0
+ BR callbackasm1(SB)
+ MOVD $588, R0
+ BR callbackasm1(SB)
+ MOVD $589, R0
+ BR callbackasm1(SB)
+ MOVD $590, R0
+ BR callbackasm1(SB)
+ MOVD $591, R0
+ BR callbackasm1(SB)
+ MOVD $592, R0
+ BR callbackasm1(SB)
+ MOVD $593, R0
+ BR callbackasm1(SB)
+ MOVD $594, R0
+ BR callbackasm1(SB)
+ MOVD $595, R0
+ BR callbackasm1(SB)
+ MOVD $596, R0
+ BR callbackasm1(SB)
+ MOVD $597, R0
+ BR callbackasm1(SB)
+ MOVD $598, R0
+ BR callbackasm1(SB)
+ MOVD $599, R0
+ BR callbackasm1(SB)
+ MOVD $600, R0
+ BR callbackasm1(SB)
+ MOVD $601, R0
+ BR callbackasm1(SB)
+ MOVD $602, R0
+ BR callbackasm1(SB)
+ MOVD $603, R0
+ BR callbackasm1(SB)
+ MOVD $604, R0
+ BR callbackasm1(SB)
+ MOVD $605, R0
+ BR callbackasm1(SB)
+ MOVD $606, R0
+ BR callbackasm1(SB)
+ MOVD $607, R0
+ BR callbackasm1(SB)
+ MOVD $608, R0
+ BR callbackasm1(SB)
+ MOVD $609, R0
+ BR callbackasm1(SB)
+ MOVD $610, R0
+ BR callbackasm1(SB)
+ MOVD $611, R0
+ BR callbackasm1(SB)
+ MOVD $612, R0
+ BR callbackasm1(SB)
+ MOVD $613, R0
+ BR callbackasm1(SB)
+ MOVD $614, R0
+ BR callbackasm1(SB)
+ MOVD $615, R0
+ BR callbackasm1(SB)
+ MOVD $616, R0
+ BR callbackasm1(SB)
+ MOVD $617, R0
+ BR callbackasm1(SB)
+ MOVD $618, R0
+ BR callbackasm1(SB)
+ MOVD $619, R0
+ BR callbackasm1(SB)
+ MOVD $620, R0
+ BR callbackasm1(SB)
+ MOVD $621, R0
+ BR callbackasm1(SB)
+ MOVD $622, R0
+ BR callbackasm1(SB)
+ MOVD $623, R0
+ BR callbackasm1(SB)
+ MOVD $624, R0
+ BR callbackasm1(SB)
+ MOVD $625, R0
+ BR callbackasm1(SB)
+ MOVD $626, R0
+ BR callbackasm1(SB)
+ MOVD $627, R0
+ BR callbackasm1(SB)
+ MOVD $628, R0
+ BR callbackasm1(SB)
+ MOVD $629, R0
+ BR callbackasm1(SB)
+ MOVD $630, R0
+ BR callbackasm1(SB)
+ MOVD $631, R0
+ BR callbackasm1(SB)
+ MOVD $632, R0
+ BR callbackasm1(SB)
+ MOVD $633, R0
+ BR callbackasm1(SB)
+ MOVD $634, R0
+ BR callbackasm1(SB)
+ MOVD $635, R0
+ BR callbackasm1(SB)
+ MOVD $636, R0
+ BR callbackasm1(SB)
+ MOVD $637, R0
+ BR callbackasm1(SB)
+ MOVD $638, R0
+ BR callbackasm1(SB)
+ MOVD $639, R0
+ BR callbackasm1(SB)
+ MOVD $640, R0
+ BR callbackasm1(SB)
+ MOVD $641, R0
+ BR callbackasm1(SB)
+ MOVD $642, R0
+ BR callbackasm1(SB)
+ MOVD $643, R0
+ BR callbackasm1(SB)
+ MOVD $644, R0
+ BR callbackasm1(SB)
+ MOVD $645, R0
+ BR callbackasm1(SB)
+ MOVD $646, R0
+ BR callbackasm1(SB)
+ MOVD $647, R0
+ BR callbackasm1(SB)
+ MOVD $648, R0
+ BR callbackasm1(SB)
+ MOVD $649, R0
+ BR callbackasm1(SB)
+ MOVD $650, R0
+ BR callbackasm1(SB)
+ MOVD $651, R0
+ BR callbackasm1(SB)
+ MOVD $652, R0
+ BR callbackasm1(SB)
+ MOVD $653, R0
+ BR callbackasm1(SB)
+ MOVD $654, R0
+ BR callbackasm1(SB)
+ MOVD $655, R0
+ BR callbackasm1(SB)
+ MOVD $656, R0
+ BR callbackasm1(SB)
+ MOVD $657, R0
+ BR callbackasm1(SB)
+ MOVD $658, R0
+ BR callbackasm1(SB)
+ MOVD $659, R0
+ BR callbackasm1(SB)
+ MOVD $660, R0
+ BR callbackasm1(SB)
+ MOVD $661, R0
+ BR callbackasm1(SB)
+ MOVD $662, R0
+ BR callbackasm1(SB)
+ MOVD $663, R0
+ BR callbackasm1(SB)
+ MOVD $664, R0
+ BR callbackasm1(SB)
+ MOVD $665, R0
+ BR callbackasm1(SB)
+ MOVD $666, R0
+ BR callbackasm1(SB)
+ MOVD $667, R0
+ BR callbackasm1(SB)
+ MOVD $668, R0
+ BR callbackasm1(SB)
+ MOVD $669, R0
+ BR callbackasm1(SB)
+ MOVD $670, R0
+ BR callbackasm1(SB)
+ MOVD $671, R0
+ BR callbackasm1(SB)
+ MOVD $672, R0
+ BR callbackasm1(SB)
+ MOVD $673, R0
+ BR callbackasm1(SB)
+ MOVD $674, R0
+ BR callbackasm1(SB)
+ MOVD $675, R0
+ BR callbackasm1(SB)
+ MOVD $676, R0
+ BR callbackasm1(SB)
+ MOVD $677, R0
+ BR callbackasm1(SB)
+ MOVD $678, R0
+ BR callbackasm1(SB)
+ MOVD $679, R0
+ BR callbackasm1(SB)
+ MOVD $680, R0
+ BR callbackasm1(SB)
+ MOVD $681, R0
+ BR callbackasm1(SB)
+ MOVD $682, R0
+ BR callbackasm1(SB)
+ MOVD $683, R0
+ BR callbackasm1(SB)
+ MOVD $684, R0
+ BR callbackasm1(SB)
+ MOVD $685, R0
+ BR callbackasm1(SB)
+ MOVD $686, R0
+ BR callbackasm1(SB)
+ MOVD $687, R0
+ BR callbackasm1(SB)
+ MOVD $688, R0
+ BR callbackasm1(SB)
+ MOVD $689, R0
+ BR callbackasm1(SB)
+ MOVD $690, R0
+ BR callbackasm1(SB)
+ MOVD $691, R0
+ BR callbackasm1(SB)
+ MOVD $692, R0
+ BR callbackasm1(SB)
+ MOVD $693, R0
+ BR callbackasm1(SB)
+ MOVD $694, R0
+ BR callbackasm1(SB)
+ MOVD $695, R0
+ BR callbackasm1(SB)
+ MOVD $696, R0
+ BR callbackasm1(SB)
+ MOVD $697, R0
+ BR callbackasm1(SB)
+ MOVD $698, R0
+ BR callbackasm1(SB)
+ MOVD $699, R0
+ BR callbackasm1(SB)
+ MOVD $700, R0
+ BR callbackasm1(SB)
+ MOVD $701, R0
+ BR callbackasm1(SB)
+ MOVD $702, R0
+ BR callbackasm1(SB)
+ MOVD $703, R0
+ BR callbackasm1(SB)
+ MOVD $704, R0
+ BR callbackasm1(SB)
+ MOVD $705, R0
+ BR callbackasm1(SB)
+ MOVD $706, R0
+ BR callbackasm1(SB)
+ MOVD $707, R0
+ BR callbackasm1(SB)
+ MOVD $708, R0
+ BR callbackasm1(SB)
+ MOVD $709, R0
+ BR callbackasm1(SB)
+ MOVD $710, R0
+ BR callbackasm1(SB)
+ MOVD $711, R0
+ BR callbackasm1(SB)
+ MOVD $712, R0
+ BR callbackasm1(SB)
+ MOVD $713, R0
+ BR callbackasm1(SB)
+ MOVD $714, R0
+ BR callbackasm1(SB)
+ MOVD $715, R0
+ BR callbackasm1(SB)
+ MOVD $716, R0
+ BR callbackasm1(SB)
+ MOVD $717, R0
+ BR callbackasm1(SB)
+ MOVD $718, R0
+ BR callbackasm1(SB)
+ MOVD $719, R0
+ BR callbackasm1(SB)
+ MOVD $720, R0
+ BR callbackasm1(SB)
+ MOVD $721, R0
+ BR callbackasm1(SB)
+ MOVD $722, R0
+ BR callbackasm1(SB)
+ MOVD $723, R0
+ BR callbackasm1(SB)
+ MOVD $724, R0
+ BR callbackasm1(SB)
+ MOVD $725, R0
+ BR callbackasm1(SB)
+ MOVD $726, R0
+ BR callbackasm1(SB)
+ MOVD $727, R0
+ BR callbackasm1(SB)
+ MOVD $728, R0
+ BR callbackasm1(SB)
+ MOVD $729, R0
+ BR callbackasm1(SB)
+ MOVD $730, R0
+ BR callbackasm1(SB)
+ MOVD $731, R0
+ BR callbackasm1(SB)
+ MOVD $732, R0
+ BR callbackasm1(SB)
+ MOVD $733, R0
+ BR callbackasm1(SB)
+ MOVD $734, R0
+ BR callbackasm1(SB)
+ MOVD $735, R0
+ BR callbackasm1(SB)
+ MOVD $736, R0
+ BR callbackasm1(SB)
+ MOVD $737, R0
+ BR callbackasm1(SB)
+ MOVD $738, R0
+ BR callbackasm1(SB)
+ MOVD $739, R0
+ BR callbackasm1(SB)
+ MOVD $740, R0
+ BR callbackasm1(SB)
+ MOVD $741, R0
+ BR callbackasm1(SB)
+ MOVD $742, R0
+ BR callbackasm1(SB)
+ MOVD $743, R0
+ BR callbackasm1(SB)
+ MOVD $744, R0
+ BR callbackasm1(SB)
+ MOVD $745, R0
+ BR callbackasm1(SB)
+ MOVD $746, R0
+ BR callbackasm1(SB)
+ MOVD $747, R0
+ BR callbackasm1(SB)
+ MOVD $748, R0
+ BR callbackasm1(SB)
+ MOVD $749, R0
+ BR callbackasm1(SB)
+ MOVD $750, R0
+ BR callbackasm1(SB)
+ MOVD $751, R0
+ BR callbackasm1(SB)
+ MOVD $752, R0
+ BR callbackasm1(SB)
+ MOVD $753, R0
+ BR callbackasm1(SB)
+ MOVD $754, R0
+ BR callbackasm1(SB)
+ MOVD $755, R0
+ BR callbackasm1(SB)
+ MOVD $756, R0
+ BR callbackasm1(SB)
+ MOVD $757, R0
+ BR callbackasm1(SB)
+ MOVD $758, R0
+ BR callbackasm1(SB)
+ MOVD $759, R0
+ BR callbackasm1(SB)
+ MOVD $760, R0
+ BR callbackasm1(SB)
+ MOVD $761, R0
+ BR callbackasm1(SB)
+ MOVD $762, R0
+ BR callbackasm1(SB)
+ MOVD $763, R0
+ BR callbackasm1(SB)
+ MOVD $764, R0
+ BR callbackasm1(SB)
+ MOVD $765, R0
+ BR callbackasm1(SB)
+ MOVD $766, R0
+ BR callbackasm1(SB)
+ MOVD $767, R0
+ BR callbackasm1(SB)
+ MOVD $768, R0
+ BR callbackasm1(SB)
+ MOVD $769, R0
+ BR callbackasm1(SB)
+ MOVD $770, R0
+ BR callbackasm1(SB)
+ MOVD $771, R0
+ BR callbackasm1(SB)
+ MOVD $772, R0
+ BR callbackasm1(SB)
+ MOVD $773, R0
+ BR callbackasm1(SB)
+ MOVD $774, R0
+ BR callbackasm1(SB)
+ MOVD $775, R0
+ BR callbackasm1(SB)
+ MOVD $776, R0
+ BR callbackasm1(SB)
+ MOVD $777, R0
+ BR callbackasm1(SB)
+ MOVD $778, R0
+ BR callbackasm1(SB)
+ MOVD $779, R0
+ BR callbackasm1(SB)
+ MOVD $780, R0
+ BR callbackasm1(SB)
+ MOVD $781, R0
+ BR callbackasm1(SB)
+ MOVD $782, R0
+ BR callbackasm1(SB)
+ MOVD $783, R0
+ BR callbackasm1(SB)
+ MOVD $784, R0
+ BR callbackasm1(SB)
+ MOVD $785, R0
+ BR callbackasm1(SB)
+ MOVD $786, R0
+ BR callbackasm1(SB)
+ MOVD $787, R0
+ BR callbackasm1(SB)
+ MOVD $788, R0
+ BR callbackasm1(SB)
+ MOVD $789, R0
+ BR callbackasm1(SB)
+ MOVD $790, R0
+ BR callbackasm1(SB)
+ MOVD $791, R0
+ BR callbackasm1(SB)
+ MOVD $792, R0
+ BR callbackasm1(SB)
+ MOVD $793, R0
+ BR callbackasm1(SB)
+ MOVD $794, R0
+ BR callbackasm1(SB)
+ MOVD $795, R0
+ BR callbackasm1(SB)
+ MOVD $796, R0
+ BR callbackasm1(SB)
+ MOVD $797, R0
+ BR callbackasm1(SB)
+ MOVD $798, R0
+ BR callbackasm1(SB)
+ MOVD $799, R0
+ BR callbackasm1(SB)
+ MOVD $800, R0
+ BR callbackasm1(SB)
+ MOVD $801, R0
+ BR callbackasm1(SB)
+ MOVD $802, R0
+ BR callbackasm1(SB)
+ MOVD $803, R0
+ BR callbackasm1(SB)
+ MOVD $804, R0
+ BR callbackasm1(SB)
+ MOVD $805, R0
+ BR callbackasm1(SB)
+ MOVD $806, R0
+ BR callbackasm1(SB)
+ MOVD $807, R0
+ BR callbackasm1(SB)
+ MOVD $808, R0
+ BR callbackasm1(SB)
+ MOVD $809, R0
+ BR callbackasm1(SB)
+ MOVD $810, R0
+ BR callbackasm1(SB)
+ MOVD $811, R0
+ BR callbackasm1(SB)
+ MOVD $812, R0
+ BR callbackasm1(SB)
+ MOVD $813, R0
+ BR callbackasm1(SB)
+ MOVD $814, R0
+ BR callbackasm1(SB)
+ MOVD $815, R0
+ BR callbackasm1(SB)
+ MOVD $816, R0
+ BR callbackasm1(SB)
+ MOVD $817, R0
+ BR callbackasm1(SB)
+ MOVD $818, R0
+ BR callbackasm1(SB)
+ MOVD $819, R0
+ BR callbackasm1(SB)
+ MOVD $820, R0
+ BR callbackasm1(SB)
+ MOVD $821, R0
+ BR callbackasm1(SB)
+ MOVD $822, R0
+ BR callbackasm1(SB)
+ MOVD $823, R0
+ BR callbackasm1(SB)
+ MOVD $824, R0
+ BR callbackasm1(SB)
+ MOVD $825, R0
+ BR callbackasm1(SB)
+ MOVD $826, R0
+ BR callbackasm1(SB)
+ MOVD $827, R0
+ BR callbackasm1(SB)
+ MOVD $828, R0
+ BR callbackasm1(SB)
+ MOVD $829, R0
+ BR callbackasm1(SB)
+ MOVD $830, R0
+ BR callbackasm1(SB)
+ MOVD $831, R0
+ BR callbackasm1(SB)
+ MOVD $832, R0
+ BR callbackasm1(SB)
+ MOVD $833, R0
+ BR callbackasm1(SB)
+ MOVD $834, R0
+ BR callbackasm1(SB)
+ MOVD $835, R0
+ BR callbackasm1(SB)
+ MOVD $836, R0
+ BR callbackasm1(SB)
+ MOVD $837, R0
+ BR callbackasm1(SB)
+ MOVD $838, R0
+ BR callbackasm1(SB)
+ MOVD $839, R0
+ BR callbackasm1(SB)
+ MOVD $840, R0
+ BR callbackasm1(SB)
+ MOVD $841, R0
+ BR callbackasm1(SB)
+ MOVD $842, R0
+ BR callbackasm1(SB)
+ MOVD $843, R0
+ BR callbackasm1(SB)
+ MOVD $844, R0
+ BR callbackasm1(SB)
+ MOVD $845, R0
+ BR callbackasm1(SB)
+ MOVD $846, R0
+ BR callbackasm1(SB)
+ MOVD $847, R0
+ BR callbackasm1(SB)
+ MOVD $848, R0
+ BR callbackasm1(SB)
+ MOVD $849, R0
+ BR callbackasm1(SB)
+ MOVD $850, R0
+ BR callbackasm1(SB)
+ MOVD $851, R0
+ BR callbackasm1(SB)
+ MOVD $852, R0
+ BR callbackasm1(SB)
+ MOVD $853, R0
+ BR callbackasm1(SB)
+ MOVD $854, R0
+ BR callbackasm1(SB)
+ MOVD $855, R0
+ BR callbackasm1(SB)
+ MOVD $856, R0
+ BR callbackasm1(SB)
+ MOVD $857, R0
+ BR callbackasm1(SB)
+ MOVD $858, R0
+ BR callbackasm1(SB)
+ MOVD $859, R0
+ BR callbackasm1(SB)
+ MOVD $860, R0
+ BR callbackasm1(SB)
+ MOVD $861, R0
+ BR callbackasm1(SB)
+ MOVD $862, R0
+ BR callbackasm1(SB)
+ MOVD $863, R0
+ BR callbackasm1(SB)
+ MOVD $864, R0
+ BR callbackasm1(SB)
+ MOVD $865, R0
+ BR callbackasm1(SB)
+ MOVD $866, R0
+ BR callbackasm1(SB)
+ MOVD $867, R0
+ BR callbackasm1(SB)
+ MOVD $868, R0
+ BR callbackasm1(SB)
+ MOVD $869, R0
+ BR callbackasm1(SB)
+ MOVD $870, R0
+ BR callbackasm1(SB)
+ MOVD $871, R0
+ BR callbackasm1(SB)
+ MOVD $872, R0
+ BR callbackasm1(SB)
+ MOVD $873, R0
+ BR callbackasm1(SB)
+ MOVD $874, R0
+ BR callbackasm1(SB)
+ MOVD $875, R0
+ BR callbackasm1(SB)
+ MOVD $876, R0
+ BR callbackasm1(SB)
+ MOVD $877, R0
+ BR callbackasm1(SB)
+ MOVD $878, R0
+ BR callbackasm1(SB)
+ MOVD $879, R0
+ BR callbackasm1(SB)
+ MOVD $880, R0
+ BR callbackasm1(SB)
+ MOVD $881, R0
+ BR callbackasm1(SB)
+ MOVD $882, R0
+ BR callbackasm1(SB)
+ MOVD $883, R0
+ BR callbackasm1(SB)
+ MOVD $884, R0
+ BR callbackasm1(SB)
+ MOVD $885, R0
+ BR callbackasm1(SB)
+ MOVD $886, R0
+ BR callbackasm1(SB)
+ MOVD $887, R0
+ BR callbackasm1(SB)
+ MOVD $888, R0
+ BR callbackasm1(SB)
+ MOVD $889, R0
+ BR callbackasm1(SB)
+ MOVD $890, R0
+ BR callbackasm1(SB)
+ MOVD $891, R0
+ BR callbackasm1(SB)
+ MOVD $892, R0
+ BR callbackasm1(SB)
+ MOVD $893, R0
+ BR callbackasm1(SB)
+ MOVD $894, R0
+ BR callbackasm1(SB)
+ MOVD $895, R0
+ BR callbackasm1(SB)
+ MOVD $896, R0
+ BR callbackasm1(SB)
+ MOVD $897, R0
+ BR callbackasm1(SB)
+ MOVD $898, R0
+ BR callbackasm1(SB)
+ MOVD $899, R0
+ BR callbackasm1(SB)
+ MOVD $900, R0
+ BR callbackasm1(SB)
+ MOVD $901, R0
+ BR callbackasm1(SB)
+ MOVD $902, R0
+ BR callbackasm1(SB)
+ MOVD $903, R0
+ BR callbackasm1(SB)
+ MOVD $904, R0
+ BR callbackasm1(SB)
+ MOVD $905, R0
+ BR callbackasm1(SB)
+ MOVD $906, R0
+ BR callbackasm1(SB)
+ MOVD $907, R0
+ BR callbackasm1(SB)
+ MOVD $908, R0
+ BR callbackasm1(SB)
+ MOVD $909, R0
+ BR callbackasm1(SB)
+ MOVD $910, R0
+ BR callbackasm1(SB)
+ MOVD $911, R0
+ BR callbackasm1(SB)
+ MOVD $912, R0
+ BR callbackasm1(SB)
+ MOVD $913, R0
+ BR callbackasm1(SB)
+ MOVD $914, R0
+ BR callbackasm1(SB)
+ MOVD $915, R0
+ BR callbackasm1(SB)
+ MOVD $916, R0
+ BR callbackasm1(SB)
+ MOVD $917, R0
+ BR callbackasm1(SB)
+ MOVD $918, R0
+ BR callbackasm1(SB)
+ MOVD $919, R0
+ BR callbackasm1(SB)
+ MOVD $920, R0
+ BR callbackasm1(SB)
+ MOVD $921, R0
+ BR callbackasm1(SB)
+ MOVD $922, R0
+ BR callbackasm1(SB)
+ MOVD $923, R0
+ BR callbackasm1(SB)
+ MOVD $924, R0
+ BR callbackasm1(SB)
+ MOVD $925, R0
+ BR callbackasm1(SB)
+ MOVD $926, R0
+ BR callbackasm1(SB)
+ MOVD $927, R0
+ BR callbackasm1(SB)
+ MOVD $928, R0
+ BR callbackasm1(SB)
+ MOVD $929, R0
+ BR callbackasm1(SB)
+ MOVD $930, R0
+ BR callbackasm1(SB)
+ MOVD $931, R0
+ BR callbackasm1(SB)
+ MOVD $932, R0
+ BR callbackasm1(SB)
+ MOVD $933, R0
+ BR callbackasm1(SB)
+ MOVD $934, R0
+ BR callbackasm1(SB)
+ MOVD $935, R0
+ BR callbackasm1(SB)
+ MOVD $936, R0
+ BR callbackasm1(SB)
+ MOVD $937, R0
+ BR callbackasm1(SB)
+ MOVD $938, R0
+ BR callbackasm1(SB)
+ MOVD $939, R0
+ BR callbackasm1(SB)
+ MOVD $940, R0
+ BR callbackasm1(SB)
+ MOVD $941, R0
+ BR callbackasm1(SB)
+ MOVD $942, R0
+ BR callbackasm1(SB)
+ MOVD $943, R0
+ BR callbackasm1(SB)
+ MOVD $944, R0
+ BR callbackasm1(SB)
+ MOVD $945, R0
+ BR callbackasm1(SB)
+ MOVD $946, R0
+ BR callbackasm1(SB)
+ MOVD $947, R0
+ BR callbackasm1(SB)
+ MOVD $948, R0
+ BR callbackasm1(SB)
+ MOVD $949, R0
+ BR callbackasm1(SB)
+ MOVD $950, R0
+ BR callbackasm1(SB)
+ MOVD $951, R0
+ BR callbackasm1(SB)
+ MOVD $952, R0
+ BR callbackasm1(SB)
+ MOVD $953, R0
+ BR callbackasm1(SB)
+ MOVD $954, R0
+ BR callbackasm1(SB)
+ MOVD $955, R0
+ BR callbackasm1(SB)
+ MOVD $956, R0
+ BR callbackasm1(SB)
+ MOVD $957, R0
+ BR callbackasm1(SB)
+ MOVD $958, R0
+ BR callbackasm1(SB)
+ MOVD $959, R0
+ BR callbackasm1(SB)
+ MOVD $960, R0
+ BR callbackasm1(SB)
+ MOVD $961, R0
+ BR callbackasm1(SB)
+ MOVD $962, R0
+ BR callbackasm1(SB)
+ MOVD $963, R0
+ BR callbackasm1(SB)
+ MOVD $964, R0
+ BR callbackasm1(SB)
+ MOVD $965, R0
+ BR callbackasm1(SB)
+ MOVD $966, R0
+ BR callbackasm1(SB)
+ MOVD $967, R0
+ BR callbackasm1(SB)
+ MOVD $968, R0
+ BR callbackasm1(SB)
+ MOVD $969, R0
+ BR callbackasm1(SB)
+ MOVD $970, R0
+ BR callbackasm1(SB)
+ MOVD $971, R0
+ BR callbackasm1(SB)
+ MOVD $972, R0
+ BR callbackasm1(SB)
+ MOVD $973, R0
+ BR callbackasm1(SB)
+ MOVD $974, R0
+ BR callbackasm1(SB)
+ MOVD $975, R0
+ BR callbackasm1(SB)
+ MOVD $976, R0
+ BR callbackasm1(SB)
+ MOVD $977, R0
+ BR callbackasm1(SB)
+ MOVD $978, R0
+ BR callbackasm1(SB)
+ MOVD $979, R0
+ BR callbackasm1(SB)
+ MOVD $980, R0
+ BR callbackasm1(SB)
+ MOVD $981, R0
+ BR callbackasm1(SB)
+ MOVD $982, R0
+ BR callbackasm1(SB)
+ MOVD $983, R0
+ BR callbackasm1(SB)
+ MOVD $984, R0
+ BR callbackasm1(SB)
+ MOVD $985, R0
+ BR callbackasm1(SB)
+ MOVD $986, R0
+ BR callbackasm1(SB)
+ MOVD $987, R0
+ BR callbackasm1(SB)
+ MOVD $988, R0
+ BR callbackasm1(SB)
+ MOVD $989, R0
+ BR callbackasm1(SB)
+ MOVD $990, R0
+ BR callbackasm1(SB)
+ MOVD $991, R0
+ BR callbackasm1(SB)
+ MOVD $992, R0
+ BR callbackasm1(SB)
+ MOVD $993, R0
+ BR callbackasm1(SB)
+ MOVD $994, R0
+ BR callbackasm1(SB)
+ MOVD $995, R0
+ BR callbackasm1(SB)
+ MOVD $996, R0
+ BR callbackasm1(SB)
+ MOVD $997, R0
+ BR callbackasm1(SB)
+ MOVD $998, R0
+ BR callbackasm1(SB)
+ MOVD $999, R0
+ BR callbackasm1(SB)
+ MOVD $1000, R0
+ BR callbackasm1(SB)
+ MOVD $1001, R0
+ BR callbackasm1(SB)
+ MOVD $1002, R0
+ BR callbackasm1(SB)
+ MOVD $1003, R0
+ BR callbackasm1(SB)
+ MOVD $1004, R0
+ BR callbackasm1(SB)
+ MOVD $1005, R0
+ BR callbackasm1(SB)
+ MOVD $1006, R0
+ BR callbackasm1(SB)
+ MOVD $1007, R0
+ BR callbackasm1(SB)
+ MOVD $1008, R0
+ BR callbackasm1(SB)
+ MOVD $1009, R0
+ BR callbackasm1(SB)
+ MOVD $1010, R0
+ BR callbackasm1(SB)
+ MOVD $1011, R0
+ BR callbackasm1(SB)
+ MOVD $1012, R0
+ BR callbackasm1(SB)
+ MOVD $1013, R0
+ BR callbackasm1(SB)
+ MOVD $1014, R0
+ BR callbackasm1(SB)
+ MOVD $1015, R0
+ BR callbackasm1(SB)
+ MOVD $1016, R0
+ BR callbackasm1(SB)
+ MOVD $1017, R0
+ BR callbackasm1(SB)
+ MOVD $1018, R0
+ BR callbackasm1(SB)
+ MOVD $1019, R0
+ BR callbackasm1(SB)
+ MOVD $1020, R0
+ BR callbackasm1(SB)
+ MOVD $1021, R0
+ BR callbackasm1(SB)
+ MOVD $1022, R0
+ BR callbackasm1(SB)
+ MOVD $1023, R0
+ BR callbackasm1(SB)
+ MOVD $1024, R0
+ BR callbackasm1(SB)
+ MOVD $1025, R0
+ BR callbackasm1(SB)
+ MOVD $1026, R0
+ BR callbackasm1(SB)
+ MOVD $1027, R0
+ BR callbackasm1(SB)
+ MOVD $1028, R0
+ BR callbackasm1(SB)
+ MOVD $1029, R0
+ BR callbackasm1(SB)
+ MOVD $1030, R0
+ BR callbackasm1(SB)
+ MOVD $1031, R0
+ BR callbackasm1(SB)
+ MOVD $1032, R0
+ BR callbackasm1(SB)
+ MOVD $1033, R0
+ BR callbackasm1(SB)
+ MOVD $1034, R0
+ BR callbackasm1(SB)
+ MOVD $1035, R0
+ BR callbackasm1(SB)
+ MOVD $1036, R0
+ BR callbackasm1(SB)
+ MOVD $1037, R0
+ BR callbackasm1(SB)
+ MOVD $1038, R0
+ BR callbackasm1(SB)
+ MOVD $1039, R0
+ BR callbackasm1(SB)
+ MOVD $1040, R0
+ BR callbackasm1(SB)
+ MOVD $1041, R0
+ BR callbackasm1(SB)
+ MOVD $1042, R0
+ BR callbackasm1(SB)
+ MOVD $1043, R0
+ BR callbackasm1(SB)
+ MOVD $1044, R0
+ BR callbackasm1(SB)
+ MOVD $1045, R0
+ BR callbackasm1(SB)
+ MOVD $1046, R0
+ BR callbackasm1(SB)
+ MOVD $1047, R0
+ BR callbackasm1(SB)
+ MOVD $1048, R0
+ BR callbackasm1(SB)
+ MOVD $1049, R0
+ BR callbackasm1(SB)
+ MOVD $1050, R0
+ BR callbackasm1(SB)
+ MOVD $1051, R0
+ BR callbackasm1(SB)
+ MOVD $1052, R0
+ BR callbackasm1(SB)
+ MOVD $1053, R0
+ BR callbackasm1(SB)
+ MOVD $1054, R0
+ BR callbackasm1(SB)
+ MOVD $1055, R0
+ BR callbackasm1(SB)
+ MOVD $1056, R0
+ BR callbackasm1(SB)
+ MOVD $1057, R0
+ BR callbackasm1(SB)
+ MOVD $1058, R0
+ BR callbackasm1(SB)
+ MOVD $1059, R0
+ BR callbackasm1(SB)
+ MOVD $1060, R0
+ BR callbackasm1(SB)
+ MOVD $1061, R0
+ BR callbackasm1(SB)
+ MOVD $1062, R0
+ BR callbackasm1(SB)
+ MOVD $1063, R0
+ BR callbackasm1(SB)
+ MOVD $1064, R0
+ BR callbackasm1(SB)
+ MOVD $1065, R0
+ BR callbackasm1(SB)
+ MOVD $1066, R0
+ BR callbackasm1(SB)
+ MOVD $1067, R0
+ BR callbackasm1(SB)
+ MOVD $1068, R0
+ BR callbackasm1(SB)
+ MOVD $1069, R0
+ BR callbackasm1(SB)
+ MOVD $1070, R0
+ BR callbackasm1(SB)
+ MOVD $1071, R0
+ BR callbackasm1(SB)
+ MOVD $1072, R0
+ BR callbackasm1(SB)
+ MOVD $1073, R0
+ BR callbackasm1(SB)
+ MOVD $1074, R0
+ BR callbackasm1(SB)
+ MOVD $1075, R0
+ BR callbackasm1(SB)
+ MOVD $1076, R0
+ BR callbackasm1(SB)
+ MOVD $1077, R0
+ BR callbackasm1(SB)
+ MOVD $1078, R0
+ BR callbackasm1(SB)
+ MOVD $1079, R0
+ BR callbackasm1(SB)
+ MOVD $1080, R0
+ BR callbackasm1(SB)
+ MOVD $1081, R0
+ BR callbackasm1(SB)
+ MOVD $1082, R0
+ BR callbackasm1(SB)
+ MOVD $1083, R0
+ BR callbackasm1(SB)
+ MOVD $1084, R0
+ BR callbackasm1(SB)
+ MOVD $1085, R0
+ BR callbackasm1(SB)
+ MOVD $1086, R0
+ BR callbackasm1(SB)
+ MOVD $1087, R0
+ BR callbackasm1(SB)
+ MOVD $1088, R0
+ BR callbackasm1(SB)
+ MOVD $1089, R0
+ BR callbackasm1(SB)
+ MOVD $1090, R0
+ BR callbackasm1(SB)
+ MOVD $1091, R0
+ BR callbackasm1(SB)
+ MOVD $1092, R0
+ BR callbackasm1(SB)
+ MOVD $1093, R0
+ BR callbackasm1(SB)
+ MOVD $1094, R0
+ BR callbackasm1(SB)
+ MOVD $1095, R0
+ BR callbackasm1(SB)
+ MOVD $1096, R0
+ BR callbackasm1(SB)
+ MOVD $1097, R0
+ BR callbackasm1(SB)
+ MOVD $1098, R0
+ BR callbackasm1(SB)
+ MOVD $1099, R0
+ BR callbackasm1(SB)
+ MOVD $1100, R0
+ BR callbackasm1(SB)
+ MOVD $1101, R0
+ BR callbackasm1(SB)
+ MOVD $1102, R0
+ BR callbackasm1(SB)
+ MOVD $1103, R0
+ BR callbackasm1(SB)
+ MOVD $1104, R0
+ BR callbackasm1(SB)
+ MOVD $1105, R0
+ BR callbackasm1(SB)
+ MOVD $1106, R0
+ BR callbackasm1(SB)
+ MOVD $1107, R0
+ BR callbackasm1(SB)
+ MOVD $1108, R0
+ BR callbackasm1(SB)
+ MOVD $1109, R0
+ BR callbackasm1(SB)
+ MOVD $1110, R0
+ BR callbackasm1(SB)
+ MOVD $1111, R0
+ BR callbackasm1(SB)
+ MOVD $1112, R0
+ BR callbackasm1(SB)
+ MOVD $1113, R0
+ BR callbackasm1(SB)
+ MOVD $1114, R0
+ BR callbackasm1(SB)
+ MOVD $1115, R0
+ BR callbackasm1(SB)
+ MOVD $1116, R0
+ BR callbackasm1(SB)
+ MOVD $1117, R0
+ BR callbackasm1(SB)
+ MOVD $1118, R0
+ BR callbackasm1(SB)
+ MOVD $1119, R0
+ BR callbackasm1(SB)
+ MOVD $1120, R0
+ BR callbackasm1(SB)
+ MOVD $1121, R0
+ BR callbackasm1(SB)
+ MOVD $1122, R0
+ BR callbackasm1(SB)
+ MOVD $1123, R0
+ BR callbackasm1(SB)
+ MOVD $1124, R0
+ BR callbackasm1(SB)
+ MOVD $1125, R0
+ BR callbackasm1(SB)
+ MOVD $1126, R0
+ BR callbackasm1(SB)
+ MOVD $1127, R0
+ BR callbackasm1(SB)
+ MOVD $1128, R0
+ BR callbackasm1(SB)
+ MOVD $1129, R0
+ BR callbackasm1(SB)
+ MOVD $1130, R0
+ BR callbackasm1(SB)
+ MOVD $1131, R0
+ BR callbackasm1(SB)
+ MOVD $1132, R0
+ BR callbackasm1(SB)
+ MOVD $1133, R0
+ BR callbackasm1(SB)
+ MOVD $1134, R0
+ BR callbackasm1(SB)
+ MOVD $1135, R0
+ BR callbackasm1(SB)
+ MOVD $1136, R0
+ BR callbackasm1(SB)
+ MOVD $1137, R0
+ BR callbackasm1(SB)
+ MOVD $1138, R0
+ BR callbackasm1(SB)
+ MOVD $1139, R0
+ BR callbackasm1(SB)
+ MOVD $1140, R0
+ BR callbackasm1(SB)
+ MOVD $1141, R0
+ BR callbackasm1(SB)
+ MOVD $1142, R0
+ BR callbackasm1(SB)
+ MOVD $1143, R0
+ BR callbackasm1(SB)
+ MOVD $1144, R0
+ BR callbackasm1(SB)
+ MOVD $1145, R0
+ BR callbackasm1(SB)
+ MOVD $1146, R0
+ BR callbackasm1(SB)
+ MOVD $1147, R0
+ BR callbackasm1(SB)
+ MOVD $1148, R0
+ BR callbackasm1(SB)
+ MOVD $1149, R0
+ BR callbackasm1(SB)
+ MOVD $1150, R0
+ BR callbackasm1(SB)
+ MOVD $1151, R0
+ BR callbackasm1(SB)
+ MOVD $1152, R0
+ BR callbackasm1(SB)
+ MOVD $1153, R0
+ BR callbackasm1(SB)
+ MOVD $1154, R0
+ BR callbackasm1(SB)
+ MOVD $1155, R0
+ BR callbackasm1(SB)
+ MOVD $1156, R0
+ BR callbackasm1(SB)
+ MOVD $1157, R0
+ BR callbackasm1(SB)
+ MOVD $1158, R0
+ BR callbackasm1(SB)
+ MOVD $1159, R0
+ BR callbackasm1(SB)
+ MOVD $1160, R0
+ BR callbackasm1(SB)
+ MOVD $1161, R0
+ BR callbackasm1(SB)
+ MOVD $1162, R0
+ BR callbackasm1(SB)
+ MOVD $1163, R0
+ BR callbackasm1(SB)
+ MOVD $1164, R0
+ BR callbackasm1(SB)
+ MOVD $1165, R0
+ BR callbackasm1(SB)
+ MOVD $1166, R0
+ BR callbackasm1(SB)
+ MOVD $1167, R0
+ BR callbackasm1(SB)
+ MOVD $1168, R0
+ BR callbackasm1(SB)
+ MOVD $1169, R0
+ BR callbackasm1(SB)
+ MOVD $1170, R0
+ BR callbackasm1(SB)
+ MOVD $1171, R0
+ BR callbackasm1(SB)
+ MOVD $1172, R0
+ BR callbackasm1(SB)
+ MOVD $1173, R0
+ BR callbackasm1(SB)
+ MOVD $1174, R0
+ BR callbackasm1(SB)
+ MOVD $1175, R0
+ BR callbackasm1(SB)
+ MOVD $1176, R0
+ BR callbackasm1(SB)
+ MOVD $1177, R0
+ BR callbackasm1(SB)
+ MOVD $1178, R0
+ BR callbackasm1(SB)
+ MOVD $1179, R0
+ BR callbackasm1(SB)
+ MOVD $1180, R0
+ BR callbackasm1(SB)
+ MOVD $1181, R0
+ BR callbackasm1(SB)
+ MOVD $1182, R0
+ BR callbackasm1(SB)
+ MOVD $1183, R0
+ BR callbackasm1(SB)
+ MOVD $1184, R0
+ BR callbackasm1(SB)
+ MOVD $1185, R0
+ BR callbackasm1(SB)
+ MOVD $1186, R0
+ BR callbackasm1(SB)
+ MOVD $1187, R0
+ BR callbackasm1(SB)
+ MOVD $1188, R0
+ BR callbackasm1(SB)
+ MOVD $1189, R0
+ BR callbackasm1(SB)
+ MOVD $1190, R0
+ BR callbackasm1(SB)
+ MOVD $1191, R0
+ BR callbackasm1(SB)
+ MOVD $1192, R0
+ BR callbackasm1(SB)
+ MOVD $1193, R0
+ BR callbackasm1(SB)
+ MOVD $1194, R0
+ BR callbackasm1(SB)
+ MOVD $1195, R0
+ BR callbackasm1(SB)
+ MOVD $1196, R0
+ BR callbackasm1(SB)
+ MOVD $1197, R0
+ BR callbackasm1(SB)
+ MOVD $1198, R0
+ BR callbackasm1(SB)
+ MOVD $1199, R0
+ BR callbackasm1(SB)
+ MOVD $1200, R0
+ BR callbackasm1(SB)
+ MOVD $1201, R0
+ BR callbackasm1(SB)
+ MOVD $1202, R0
+ BR callbackasm1(SB)
+ MOVD $1203, R0
+ BR callbackasm1(SB)
+ MOVD $1204, R0
+ BR callbackasm1(SB)
+ MOVD $1205, R0
+ BR callbackasm1(SB)
+ MOVD $1206, R0
+ BR callbackasm1(SB)
+ MOVD $1207, R0
+ BR callbackasm1(SB)
+ MOVD $1208, R0
+ BR callbackasm1(SB)
+ MOVD $1209, R0
+ BR callbackasm1(SB)
+ MOVD $1210, R0
+ BR callbackasm1(SB)
+ MOVD $1211, R0
+ BR callbackasm1(SB)
+ MOVD $1212, R0
+ BR callbackasm1(SB)
+ MOVD $1213, R0
+ BR callbackasm1(SB)
+ MOVD $1214, R0
+ BR callbackasm1(SB)
+ MOVD $1215, R0
+ BR callbackasm1(SB)
+ MOVD $1216, R0
+ BR callbackasm1(SB)
+ MOVD $1217, R0
+ BR callbackasm1(SB)
+ MOVD $1218, R0
+ BR callbackasm1(SB)
+ MOVD $1219, R0
+ BR callbackasm1(SB)
+ MOVD $1220, R0
+ BR callbackasm1(SB)
+ MOVD $1221, R0
+ BR callbackasm1(SB)
+ MOVD $1222, R0
+ BR callbackasm1(SB)
+ MOVD $1223, R0
+ BR callbackasm1(SB)
+ MOVD $1224, R0
+ BR callbackasm1(SB)
+ MOVD $1225, R0
+ BR callbackasm1(SB)
+ MOVD $1226, R0
+ BR callbackasm1(SB)
+ MOVD $1227, R0
+ BR callbackasm1(SB)
+ MOVD $1228, R0
+ BR callbackasm1(SB)
+ MOVD $1229, R0
+ BR callbackasm1(SB)
+ MOVD $1230, R0
+ BR callbackasm1(SB)
+ MOVD $1231, R0
+ BR callbackasm1(SB)
+ MOVD $1232, R0
+ BR callbackasm1(SB)
+ MOVD $1233, R0
+ BR callbackasm1(SB)
+ MOVD $1234, R0
+ BR callbackasm1(SB)
+ MOVD $1235, R0
+ BR callbackasm1(SB)
+ MOVD $1236, R0
+ BR callbackasm1(SB)
+ MOVD $1237, R0
+ BR callbackasm1(SB)
+ MOVD $1238, R0
+ BR callbackasm1(SB)
+ MOVD $1239, R0
+ BR callbackasm1(SB)
+ MOVD $1240, R0
+ BR callbackasm1(SB)
+ MOVD $1241, R0
+ BR callbackasm1(SB)
+ MOVD $1242, R0
+ BR callbackasm1(SB)
+ MOVD $1243, R0
+ BR callbackasm1(SB)
+ MOVD $1244, R0
+ BR callbackasm1(SB)
+ MOVD $1245, R0
+ BR callbackasm1(SB)
+ MOVD $1246, R0
+ BR callbackasm1(SB)
+ MOVD $1247, R0
+ BR callbackasm1(SB)
+ MOVD $1248, R0
+ BR callbackasm1(SB)
+ MOVD $1249, R0
+ BR callbackasm1(SB)
+ MOVD $1250, R0
+ BR callbackasm1(SB)
+ MOVD $1251, R0
+ BR callbackasm1(SB)
+ MOVD $1252, R0
+ BR callbackasm1(SB)
+ MOVD $1253, R0
+ BR callbackasm1(SB)
+ MOVD $1254, R0
+ BR callbackasm1(SB)
+ MOVD $1255, R0
+ BR callbackasm1(SB)
+ MOVD $1256, R0
+ BR callbackasm1(SB)
+ MOVD $1257, R0
+ BR callbackasm1(SB)
+ MOVD $1258, R0
+ BR callbackasm1(SB)
+ MOVD $1259, R0
+ BR callbackasm1(SB)
+ MOVD $1260, R0
+ BR callbackasm1(SB)
+ MOVD $1261, R0
+ BR callbackasm1(SB)
+ MOVD $1262, R0
+ BR callbackasm1(SB)
+ MOVD $1263, R0
+ BR callbackasm1(SB)
+ MOVD $1264, R0
+ BR callbackasm1(SB)
+ MOVD $1265, R0
+ BR callbackasm1(SB)
+ MOVD $1266, R0
+ BR callbackasm1(SB)
+ MOVD $1267, R0
+ BR callbackasm1(SB)
+ MOVD $1268, R0
+ BR callbackasm1(SB)
+ MOVD $1269, R0
+ BR callbackasm1(SB)
+ MOVD $1270, R0
+ BR callbackasm1(SB)
+ MOVD $1271, R0
+ BR callbackasm1(SB)
+ MOVD $1272, R0
+ BR callbackasm1(SB)
+ MOVD $1273, R0
+ BR callbackasm1(SB)
+ MOVD $1274, R0
+ BR callbackasm1(SB)
+ MOVD $1275, R0
+ BR callbackasm1(SB)
+ MOVD $1276, R0
+ BR callbackasm1(SB)
+ MOVD $1277, R0
+ BR callbackasm1(SB)
+ MOVD $1278, R0
+ BR callbackasm1(SB)
+ MOVD $1279, R0
+ BR callbackasm1(SB)
+ MOVD $1280, R0
+ BR callbackasm1(SB)
+ MOVD $1281, R0
+ BR callbackasm1(SB)
+ MOVD $1282, R0
+ BR callbackasm1(SB)
+ MOVD $1283, R0
+ BR callbackasm1(SB)
+ MOVD $1284, R0
+ BR callbackasm1(SB)
+ MOVD $1285, R0
+ BR callbackasm1(SB)
+ MOVD $1286, R0
+ BR callbackasm1(SB)
+ MOVD $1287, R0
+ BR callbackasm1(SB)
+ MOVD $1288, R0
+ BR callbackasm1(SB)
+ MOVD $1289, R0
+ BR callbackasm1(SB)
+ MOVD $1290, R0
+ BR callbackasm1(SB)
+ MOVD $1291, R0
+ BR callbackasm1(SB)
+ MOVD $1292, R0
+ BR callbackasm1(SB)
+ MOVD $1293, R0
+ BR callbackasm1(SB)
+ MOVD $1294, R0
+ BR callbackasm1(SB)
+ MOVD $1295, R0
+ BR callbackasm1(SB)
+ MOVD $1296, R0
+ BR callbackasm1(SB)
+ MOVD $1297, R0
+ BR callbackasm1(SB)
+ MOVD $1298, R0
+ BR callbackasm1(SB)
+ MOVD $1299, R0
+ BR callbackasm1(SB)
+ MOVD $1300, R0
+ BR callbackasm1(SB)
+ MOVD $1301, R0
+ BR callbackasm1(SB)
+ MOVD $1302, R0
+ BR callbackasm1(SB)
+ MOVD $1303, R0
+ BR callbackasm1(SB)
+ MOVD $1304, R0
+ BR callbackasm1(SB)
+ MOVD $1305, R0
+ BR callbackasm1(SB)
+ MOVD $1306, R0
+ BR callbackasm1(SB)
+ MOVD $1307, R0
+ BR callbackasm1(SB)
+ MOVD $1308, R0
+ BR callbackasm1(SB)
+ MOVD $1309, R0
+ BR callbackasm1(SB)
+ MOVD $1310, R0
+ BR callbackasm1(SB)
+ MOVD $1311, R0
+ BR callbackasm1(SB)
+ MOVD $1312, R0
+ BR callbackasm1(SB)
+ MOVD $1313, R0
+ BR callbackasm1(SB)
+ MOVD $1314, R0
+ BR callbackasm1(SB)
+ MOVD $1315, R0
+ BR callbackasm1(SB)
+ MOVD $1316, R0
+ BR callbackasm1(SB)
+ MOVD $1317, R0
+ BR callbackasm1(SB)
+ MOVD $1318, R0
+ BR callbackasm1(SB)
+ MOVD $1319, R0
+ BR callbackasm1(SB)
+ MOVD $1320, R0
+ BR callbackasm1(SB)
+ MOVD $1321, R0
+ BR callbackasm1(SB)
+ MOVD $1322, R0
+ BR callbackasm1(SB)
+ MOVD $1323, R0
+ BR callbackasm1(SB)
+ MOVD $1324, R0
+ BR callbackasm1(SB)
+ MOVD $1325, R0
+ BR callbackasm1(SB)
+ MOVD $1326, R0
+ BR callbackasm1(SB)
+ MOVD $1327, R0
+ BR callbackasm1(SB)
+ MOVD $1328, R0
+ BR callbackasm1(SB)
+ MOVD $1329, R0
+ BR callbackasm1(SB)
+ MOVD $1330, R0
+ BR callbackasm1(SB)
+ MOVD $1331, R0
+ BR callbackasm1(SB)
+ MOVD $1332, R0
+ BR callbackasm1(SB)
+ MOVD $1333, R0
+ BR callbackasm1(SB)
+ MOVD $1334, R0
+ BR callbackasm1(SB)
+ MOVD $1335, R0
+ BR callbackasm1(SB)
+ MOVD $1336, R0
+ BR callbackasm1(SB)
+ MOVD $1337, R0
+ BR callbackasm1(SB)
+ MOVD $1338, R0
+ BR callbackasm1(SB)
+ MOVD $1339, R0
+ BR callbackasm1(SB)
+ MOVD $1340, R0
+ BR callbackasm1(SB)
+ MOVD $1341, R0
+ BR callbackasm1(SB)
+ MOVD $1342, R0
+ BR callbackasm1(SB)
+ MOVD $1343, R0
+ BR callbackasm1(SB)
+ MOVD $1344, R0
+ BR callbackasm1(SB)
+ MOVD $1345, R0
+ BR callbackasm1(SB)
+ MOVD $1346, R0
+ BR callbackasm1(SB)
+ MOVD $1347, R0
+ BR callbackasm1(SB)
+ MOVD $1348, R0
+ BR callbackasm1(SB)
+ MOVD $1349, R0
+ BR callbackasm1(SB)
+ MOVD $1350, R0
+ BR callbackasm1(SB)
+ MOVD $1351, R0
+ BR callbackasm1(SB)
+ MOVD $1352, R0
+ BR callbackasm1(SB)
+ MOVD $1353, R0
+ BR callbackasm1(SB)
+ MOVD $1354, R0
+ BR callbackasm1(SB)
+ MOVD $1355, R0
+ BR callbackasm1(SB)
+ MOVD $1356, R0
+ BR callbackasm1(SB)
+ MOVD $1357, R0
+ BR callbackasm1(SB)
+ MOVD $1358, R0
+ BR callbackasm1(SB)
+ MOVD $1359, R0
+ BR callbackasm1(SB)
+ MOVD $1360, R0
+ BR callbackasm1(SB)
+ MOVD $1361, R0
+ BR callbackasm1(SB)
+ MOVD $1362, R0
+ BR callbackasm1(SB)
+ MOVD $1363, R0
+ BR callbackasm1(SB)
+ MOVD $1364, R0
+ BR callbackasm1(SB)
+ MOVD $1365, R0
+ BR callbackasm1(SB)
+ MOVD $1366, R0
+ BR callbackasm1(SB)
+ MOVD $1367, R0
+ BR callbackasm1(SB)
+ MOVD $1368, R0
+ BR callbackasm1(SB)
+ MOVD $1369, R0
+ BR callbackasm1(SB)
+ MOVD $1370, R0
+ BR callbackasm1(SB)
+ MOVD $1371, R0
+ BR callbackasm1(SB)
+ MOVD $1372, R0
+ BR callbackasm1(SB)
+ MOVD $1373, R0
+ BR callbackasm1(SB)
+ MOVD $1374, R0
+ BR callbackasm1(SB)
+ MOVD $1375, R0
+ BR callbackasm1(SB)
+ MOVD $1376, R0
+ BR callbackasm1(SB)
+ MOVD $1377, R0
+ BR callbackasm1(SB)
+ MOVD $1378, R0
+ BR callbackasm1(SB)
+ MOVD $1379, R0
+ BR callbackasm1(SB)
+ MOVD $1380, R0
+ BR callbackasm1(SB)
+ MOVD $1381, R0
+ BR callbackasm1(SB)
+ MOVD $1382, R0
+ BR callbackasm1(SB)
+ MOVD $1383, R0
+ BR callbackasm1(SB)
+ MOVD $1384, R0
+ BR callbackasm1(SB)
+ MOVD $1385, R0
+ BR callbackasm1(SB)
+ MOVD $1386, R0
+ BR callbackasm1(SB)
+ MOVD $1387, R0
+ BR callbackasm1(SB)
+ MOVD $1388, R0
+ BR callbackasm1(SB)
+ MOVD $1389, R0
+ BR callbackasm1(SB)
+ MOVD $1390, R0
+ BR callbackasm1(SB)
+ MOVD $1391, R0
+ BR callbackasm1(SB)
+ MOVD $1392, R0
+ BR callbackasm1(SB)
+ MOVD $1393, R0
+ BR callbackasm1(SB)
+ MOVD $1394, R0
+ BR callbackasm1(SB)
+ MOVD $1395, R0
+ BR callbackasm1(SB)
+ MOVD $1396, R0
+ BR callbackasm1(SB)
+ MOVD $1397, R0
+ BR callbackasm1(SB)
+ MOVD $1398, R0
+ BR callbackasm1(SB)
+ MOVD $1399, R0
+ BR callbackasm1(SB)
+ MOVD $1400, R0
+ BR callbackasm1(SB)
+ MOVD $1401, R0
+ BR callbackasm1(SB)
+ MOVD $1402, R0
+ BR callbackasm1(SB)
+ MOVD $1403, R0
+ BR callbackasm1(SB)
+ MOVD $1404, R0
+ BR callbackasm1(SB)
+ MOVD $1405, R0
+ BR callbackasm1(SB)
+ MOVD $1406, R0
+ BR callbackasm1(SB)
+ MOVD $1407, R0
+ BR callbackasm1(SB)
+ MOVD $1408, R0
+ BR callbackasm1(SB)
+ MOVD $1409, R0
+ BR callbackasm1(SB)
+ MOVD $1410, R0
+ BR callbackasm1(SB)
+ MOVD $1411, R0
+ BR callbackasm1(SB)
+ MOVD $1412, R0
+ BR callbackasm1(SB)
+ MOVD $1413, R0
+ BR callbackasm1(SB)
+ MOVD $1414, R0
+ BR callbackasm1(SB)
+ MOVD $1415, R0
+ BR callbackasm1(SB)
+ MOVD $1416, R0
+ BR callbackasm1(SB)
+ MOVD $1417, R0
+ BR callbackasm1(SB)
+ MOVD $1418, R0
+ BR callbackasm1(SB)
+ MOVD $1419, R0
+ BR callbackasm1(SB)
+ MOVD $1420, R0
+ BR callbackasm1(SB)
+ MOVD $1421, R0
+ BR callbackasm1(SB)
+ MOVD $1422, R0
+ BR callbackasm1(SB)
+ MOVD $1423, R0
+ BR callbackasm1(SB)
+ MOVD $1424, R0
+ BR callbackasm1(SB)
+ MOVD $1425, R0
+ BR callbackasm1(SB)
+ MOVD $1426, R0
+ BR callbackasm1(SB)
+ MOVD $1427, R0
+ BR callbackasm1(SB)
+ MOVD $1428, R0
+ BR callbackasm1(SB)
+ MOVD $1429, R0
+ BR callbackasm1(SB)
+ MOVD $1430, R0
+ BR callbackasm1(SB)
+ MOVD $1431, R0
+ BR callbackasm1(SB)
+ MOVD $1432, R0
+ BR callbackasm1(SB)
+ MOVD $1433, R0
+ BR callbackasm1(SB)
+ MOVD $1434, R0
+ BR callbackasm1(SB)
+ MOVD $1435, R0
+ BR callbackasm1(SB)
+ MOVD $1436, R0
+ BR callbackasm1(SB)
+ MOVD $1437, R0
+ BR callbackasm1(SB)
+ MOVD $1438, R0
+ BR callbackasm1(SB)
+ MOVD $1439, R0
+ BR callbackasm1(SB)
+ MOVD $1440, R0
+ BR callbackasm1(SB)
+ MOVD $1441, R0
+ BR callbackasm1(SB)
+ MOVD $1442, R0
+ BR callbackasm1(SB)
+ MOVD $1443, R0
+ BR callbackasm1(SB)
+ MOVD $1444, R0
+ BR callbackasm1(SB)
+ MOVD $1445, R0
+ BR callbackasm1(SB)
+ MOVD $1446, R0
+ BR callbackasm1(SB)
+ MOVD $1447, R0
+ BR callbackasm1(SB)
+ MOVD $1448, R0
+ BR callbackasm1(SB)
+ MOVD $1449, R0
+ BR callbackasm1(SB)
+ MOVD $1450, R0
+ BR callbackasm1(SB)
+ MOVD $1451, R0
+ BR callbackasm1(SB)
+ MOVD $1452, R0
+ BR callbackasm1(SB)
+ MOVD $1453, R0
+ BR callbackasm1(SB)
+ MOVD $1454, R0
+ BR callbackasm1(SB)
+ MOVD $1455, R0
+ BR callbackasm1(SB)
+ MOVD $1456, R0
+ BR callbackasm1(SB)
+ MOVD $1457, R0
+ BR callbackasm1(SB)
+ MOVD $1458, R0
+ BR callbackasm1(SB)
+ MOVD $1459, R0
+ BR callbackasm1(SB)
+ MOVD $1460, R0
+ BR callbackasm1(SB)
+ MOVD $1461, R0
+ BR callbackasm1(SB)
+ MOVD $1462, R0
+ BR callbackasm1(SB)
+ MOVD $1463, R0
+ BR callbackasm1(SB)
+ MOVD $1464, R0
+ BR callbackasm1(SB)
+ MOVD $1465, R0
+ BR callbackasm1(SB)
+ MOVD $1466, R0
+ BR callbackasm1(SB)
+ MOVD $1467, R0
+ BR callbackasm1(SB)
+ MOVD $1468, R0
+ BR callbackasm1(SB)
+ MOVD $1469, R0
+ BR callbackasm1(SB)
+ MOVD $1470, R0
+ BR callbackasm1(SB)
+ MOVD $1471, R0
+ BR callbackasm1(SB)
+ MOVD $1472, R0
+ BR callbackasm1(SB)
+ MOVD $1473, R0
+ BR callbackasm1(SB)
+ MOVD $1474, R0
+ BR callbackasm1(SB)
+ MOVD $1475, R0
+ BR callbackasm1(SB)
+ MOVD $1476, R0
+ BR callbackasm1(SB)
+ MOVD $1477, R0
+ BR callbackasm1(SB)
+ MOVD $1478, R0
+ BR callbackasm1(SB)
+ MOVD $1479, R0
+ BR callbackasm1(SB)
+ MOVD $1480, R0
+ BR callbackasm1(SB)
+ MOVD $1481, R0
+ BR callbackasm1(SB)
+ MOVD $1482, R0
+ BR callbackasm1(SB)
+ MOVD $1483, R0
+ BR callbackasm1(SB)
+ MOVD $1484, R0
+ BR callbackasm1(SB)
+ MOVD $1485, R0
+ BR callbackasm1(SB)
+ MOVD $1486, R0
+ BR callbackasm1(SB)
+ MOVD $1487, R0
+ BR callbackasm1(SB)
+ MOVD $1488, R0
+ BR callbackasm1(SB)
+ MOVD $1489, R0
+ BR callbackasm1(SB)
+ MOVD $1490, R0
+ BR callbackasm1(SB)
+ MOVD $1491, R0
+ BR callbackasm1(SB)
+ MOVD $1492, R0
+ BR callbackasm1(SB)
+ MOVD $1493, R0
+ BR callbackasm1(SB)
+ MOVD $1494, R0
+ BR callbackasm1(SB)
+ MOVD $1495, R0
+ BR callbackasm1(SB)
+ MOVD $1496, R0
+ BR callbackasm1(SB)
+ MOVD $1497, R0
+ BR callbackasm1(SB)
+ MOVD $1498, R0
+ BR callbackasm1(SB)
+ MOVD $1499, R0
+ BR callbackasm1(SB)
+ MOVD $1500, R0
+ BR callbackasm1(SB)
+ MOVD $1501, R0
+ BR callbackasm1(SB)
+ MOVD $1502, R0
+ BR callbackasm1(SB)
+ MOVD $1503, R0
+ BR callbackasm1(SB)
+ MOVD $1504, R0
+ BR callbackasm1(SB)
+ MOVD $1505, R0
+ BR callbackasm1(SB)
+ MOVD $1506, R0
+ BR callbackasm1(SB)
+ MOVD $1507, R0
+ BR callbackasm1(SB)
+ MOVD $1508, R0
+ BR callbackasm1(SB)
+ MOVD $1509, R0
+ BR callbackasm1(SB)
+ MOVD $1510, R0
+ BR callbackasm1(SB)
+ MOVD $1511, R0
+ BR callbackasm1(SB)
+ MOVD $1512, R0
+ BR callbackasm1(SB)
+ MOVD $1513, R0
+ BR callbackasm1(SB)
+ MOVD $1514, R0
+ BR callbackasm1(SB)
+ MOVD $1515, R0
+ BR callbackasm1(SB)
+ MOVD $1516, R0
+ BR callbackasm1(SB)
+ MOVD $1517, R0
+ BR callbackasm1(SB)
+ MOVD $1518, R0
+ BR callbackasm1(SB)
+ MOVD $1519, R0
+ BR callbackasm1(SB)
+ MOVD $1520, R0
+ BR callbackasm1(SB)
+ MOVD $1521, R0
+ BR callbackasm1(SB)
+ MOVD $1522, R0
+ BR callbackasm1(SB)
+ MOVD $1523, R0
+ BR callbackasm1(SB)
+ MOVD $1524, R0
+ BR callbackasm1(SB)
+ MOVD $1525, R0
+ BR callbackasm1(SB)
+ MOVD $1526, R0
+ BR callbackasm1(SB)
+ MOVD $1527, R0
+ BR callbackasm1(SB)
+ MOVD $1528, R0
+ BR callbackasm1(SB)
+ MOVD $1529, R0
+ BR callbackasm1(SB)
+ MOVD $1530, R0
+ BR callbackasm1(SB)
+ MOVD $1531, R0
+ BR callbackasm1(SB)
+ MOVD $1532, R0
+ BR callbackasm1(SB)
+ MOVD $1533, R0
+ BR callbackasm1(SB)
+ MOVD $1534, R0
+ BR callbackasm1(SB)
+ MOVD $1535, R0
+ BR callbackasm1(SB)
+ MOVD $1536, R0
+ BR callbackasm1(SB)
+ MOVD $1537, R0
+ BR callbackasm1(SB)
+ MOVD $1538, R0
+ BR callbackasm1(SB)
+ MOVD $1539, R0
+ BR callbackasm1(SB)
+ MOVD $1540, R0
+ BR callbackasm1(SB)
+ MOVD $1541, R0
+ BR callbackasm1(SB)
+ MOVD $1542, R0
+ BR callbackasm1(SB)
+ MOVD $1543, R0
+ BR callbackasm1(SB)
+ MOVD $1544, R0
+ BR callbackasm1(SB)
+ MOVD $1545, R0
+ BR callbackasm1(SB)
+ MOVD $1546, R0
+ BR callbackasm1(SB)
+ MOVD $1547, R0
+ BR callbackasm1(SB)
+ MOVD $1548, R0
+ BR callbackasm1(SB)
+ MOVD $1549, R0
+ BR callbackasm1(SB)
+ MOVD $1550, R0
+ BR callbackasm1(SB)
+ MOVD $1551, R0
+ BR callbackasm1(SB)
+ MOVD $1552, R0
+ BR callbackasm1(SB)
+ MOVD $1553, R0
+ BR callbackasm1(SB)
+ MOVD $1554, R0
+ BR callbackasm1(SB)
+ MOVD $1555, R0
+ BR callbackasm1(SB)
+ MOVD $1556, R0
+ BR callbackasm1(SB)
+ MOVD $1557, R0
+ BR callbackasm1(SB)
+ MOVD $1558, R0
+ BR callbackasm1(SB)
+ MOVD $1559, R0
+ BR callbackasm1(SB)
+ MOVD $1560, R0
+ BR callbackasm1(SB)
+ MOVD $1561, R0
+ BR callbackasm1(SB)
+ MOVD $1562, R0
+ BR callbackasm1(SB)
+ MOVD $1563, R0
+ BR callbackasm1(SB)
+ MOVD $1564, R0
+ BR callbackasm1(SB)
+ MOVD $1565, R0
+ BR callbackasm1(SB)
+ MOVD $1566, R0
+ BR callbackasm1(SB)
+ MOVD $1567, R0
+ BR callbackasm1(SB)
+ MOVD $1568, R0
+ BR callbackasm1(SB)
+ MOVD $1569, R0
+ BR callbackasm1(SB)
+ MOVD $1570, R0
+ BR callbackasm1(SB)
+ MOVD $1571, R0
+ BR callbackasm1(SB)
+ MOVD $1572, R0
+ BR callbackasm1(SB)
+ MOVD $1573, R0
+ BR callbackasm1(SB)
+ MOVD $1574, R0
+ BR callbackasm1(SB)
+ MOVD $1575, R0
+ BR callbackasm1(SB)
+ MOVD $1576, R0
+ BR callbackasm1(SB)
+ MOVD $1577, R0
+ BR callbackasm1(SB)
+ MOVD $1578, R0
+ BR callbackasm1(SB)
+ MOVD $1579, R0
+ BR callbackasm1(SB)
+ MOVD $1580, R0
+ BR callbackasm1(SB)
+ MOVD $1581, R0
+ BR callbackasm1(SB)
+ MOVD $1582, R0
+ BR callbackasm1(SB)
+ MOVD $1583, R0
+ BR callbackasm1(SB)
+ MOVD $1584, R0
+ BR callbackasm1(SB)
+ MOVD $1585, R0
+ BR callbackasm1(SB)
+ MOVD $1586, R0
+ BR callbackasm1(SB)
+ MOVD $1587, R0
+ BR callbackasm1(SB)
+ MOVD $1588, R0
+ BR callbackasm1(SB)
+ MOVD $1589, R0
+ BR callbackasm1(SB)
+ MOVD $1590, R0
+ BR callbackasm1(SB)
+ MOVD $1591, R0
+ BR callbackasm1(SB)
+ MOVD $1592, R0
+ BR callbackasm1(SB)
+ MOVD $1593, R0
+ BR callbackasm1(SB)
+ MOVD $1594, R0
+ BR callbackasm1(SB)
+ MOVD $1595, R0
+ BR callbackasm1(SB)
+ MOVD $1596, R0
+ BR callbackasm1(SB)
+ MOVD $1597, R0
+ BR callbackasm1(SB)
+ MOVD $1598, R0
+ BR callbackasm1(SB)
+ MOVD $1599, R0
+ BR callbackasm1(SB)
+ MOVD $1600, R0
+ BR callbackasm1(SB)
+ MOVD $1601, R0
+ BR callbackasm1(SB)
+ MOVD $1602, R0
+ BR callbackasm1(SB)
+ MOVD $1603, R0
+ BR callbackasm1(SB)
+ MOVD $1604, R0
+ BR callbackasm1(SB)
+ MOVD $1605, R0
+ BR callbackasm1(SB)
+ MOVD $1606, R0
+ BR callbackasm1(SB)
+ MOVD $1607, R0
+ BR callbackasm1(SB)
+ MOVD $1608, R0
+ BR callbackasm1(SB)
+ MOVD $1609, R0
+ BR callbackasm1(SB)
+ MOVD $1610, R0
+ BR callbackasm1(SB)
+ MOVD $1611, R0
+ BR callbackasm1(SB)
+ MOVD $1612, R0
+ BR callbackasm1(SB)
+ MOVD $1613, R0
+ BR callbackasm1(SB)
+ MOVD $1614, R0
+ BR callbackasm1(SB)
+ MOVD $1615, R0
+ BR callbackasm1(SB)
+ MOVD $1616, R0
+ BR callbackasm1(SB)
+ MOVD $1617, R0
+ BR callbackasm1(SB)
+ MOVD $1618, R0
+ BR callbackasm1(SB)
+ MOVD $1619, R0
+ BR callbackasm1(SB)
+ MOVD $1620, R0
+ BR callbackasm1(SB)
+ MOVD $1621, R0
+ BR callbackasm1(SB)
+ MOVD $1622, R0
+ BR callbackasm1(SB)
+ MOVD $1623, R0
+ BR callbackasm1(SB)
+ MOVD $1624, R0
+ BR callbackasm1(SB)
+ MOVD $1625, R0
+ BR callbackasm1(SB)
+ MOVD $1626, R0
+ BR callbackasm1(SB)
+ MOVD $1627, R0
+ BR callbackasm1(SB)
+ MOVD $1628, R0
+ BR callbackasm1(SB)
+ MOVD $1629, R0
+ BR callbackasm1(SB)
+ MOVD $1630, R0
+ BR callbackasm1(SB)
+ MOVD $1631, R0
+ BR callbackasm1(SB)
+ MOVD $1632, R0
+ BR callbackasm1(SB)
+ MOVD $1633, R0
+ BR callbackasm1(SB)
+ MOVD $1634, R0
+ BR callbackasm1(SB)
+ MOVD $1635, R0
+ BR callbackasm1(SB)
+ MOVD $1636, R0
+ BR callbackasm1(SB)
+ MOVD $1637, R0
+ BR callbackasm1(SB)
+ MOVD $1638, R0
+ BR callbackasm1(SB)
+ MOVD $1639, R0
+ BR callbackasm1(SB)
+ MOVD $1640, R0
+ BR callbackasm1(SB)
+ MOVD $1641, R0
+ BR callbackasm1(SB)
+ MOVD $1642, R0
+ BR callbackasm1(SB)
+ MOVD $1643, R0
+ BR callbackasm1(SB)
+ MOVD $1644, R0
+ BR callbackasm1(SB)
+ MOVD $1645, R0
+ BR callbackasm1(SB)
+ MOVD $1646, R0
+ BR callbackasm1(SB)
+ MOVD $1647, R0
+ BR callbackasm1(SB)
+ MOVD $1648, R0
+ BR callbackasm1(SB)
+ MOVD $1649, R0
+ BR callbackasm1(SB)
+ MOVD $1650, R0
+ BR callbackasm1(SB)
+ MOVD $1651, R0
+ BR callbackasm1(SB)
+ MOVD $1652, R0
+ BR callbackasm1(SB)
+ MOVD $1653, R0
+ BR callbackasm1(SB)
+ MOVD $1654, R0
+ BR callbackasm1(SB)
+ MOVD $1655, R0
+ BR callbackasm1(SB)
+ MOVD $1656, R0
+ BR callbackasm1(SB)
+ MOVD $1657, R0
+ BR callbackasm1(SB)
+ MOVD $1658, R0
+ BR callbackasm1(SB)
+ MOVD $1659, R0
+ BR callbackasm1(SB)
+ MOVD $1660, R0
+ BR callbackasm1(SB)
+ MOVD $1661, R0
+ BR callbackasm1(SB)
+ MOVD $1662, R0
+ BR callbackasm1(SB)
+ MOVD $1663, R0
+ BR callbackasm1(SB)
+ MOVD $1664, R0
+ BR callbackasm1(SB)
+ MOVD $1665, R0
+ BR callbackasm1(SB)
+ MOVD $1666, R0
+ BR callbackasm1(SB)
+ MOVD $1667, R0
+ BR callbackasm1(SB)
+ MOVD $1668, R0
+ BR callbackasm1(SB)
+ MOVD $1669, R0
+ BR callbackasm1(SB)
+ MOVD $1670, R0
+ BR callbackasm1(SB)
+ MOVD $1671, R0
+ BR callbackasm1(SB)
+ MOVD $1672, R0
+ BR callbackasm1(SB)
+ MOVD $1673, R0
+ BR callbackasm1(SB)
+ MOVD $1674, R0
+ BR callbackasm1(SB)
+ MOVD $1675, R0
+ BR callbackasm1(SB)
+ MOVD $1676, R0
+ BR callbackasm1(SB)
+ MOVD $1677, R0
+ BR callbackasm1(SB)
+ MOVD $1678, R0
+ BR callbackasm1(SB)
+ MOVD $1679, R0
+ BR callbackasm1(SB)
+ MOVD $1680, R0
+ BR callbackasm1(SB)
+ MOVD $1681, R0
+ BR callbackasm1(SB)
+ MOVD $1682, R0
+ BR callbackasm1(SB)
+ MOVD $1683, R0
+ BR callbackasm1(SB)
+ MOVD $1684, R0
+ BR callbackasm1(SB)
+ MOVD $1685, R0
+ BR callbackasm1(SB)
+ MOVD $1686, R0
+ BR callbackasm1(SB)
+ MOVD $1687, R0
+ BR callbackasm1(SB)
+ MOVD $1688, R0
+ BR callbackasm1(SB)
+ MOVD $1689, R0
+ BR callbackasm1(SB)
+ MOVD $1690, R0
+ BR callbackasm1(SB)
+ MOVD $1691, R0
+ BR callbackasm1(SB)
+ MOVD $1692, R0
+ BR callbackasm1(SB)
+ MOVD $1693, R0
+ BR callbackasm1(SB)
+ MOVD $1694, R0
+ BR callbackasm1(SB)
+ MOVD $1695, R0
+ BR callbackasm1(SB)
+ MOVD $1696, R0
+ BR callbackasm1(SB)
+ MOVD $1697, R0
+ BR callbackasm1(SB)
+ MOVD $1698, R0
+ BR callbackasm1(SB)
+ MOVD $1699, R0
+ BR callbackasm1(SB)
+ MOVD $1700, R0
+ BR callbackasm1(SB)
+ MOVD $1701, R0
+ BR callbackasm1(SB)
+ MOVD $1702, R0
+ BR callbackasm1(SB)
+ MOVD $1703, R0
+ BR callbackasm1(SB)
+ MOVD $1704, R0
+ BR callbackasm1(SB)
+ MOVD $1705, R0
+ BR callbackasm1(SB)
+ MOVD $1706, R0
+ BR callbackasm1(SB)
+ MOVD $1707, R0
+ BR callbackasm1(SB)
+ MOVD $1708, R0
+ BR callbackasm1(SB)
+ MOVD $1709, R0
+ BR callbackasm1(SB)
+ MOVD $1710, R0
+ BR callbackasm1(SB)
+ MOVD $1711, R0
+ BR callbackasm1(SB)
+ MOVD $1712, R0
+ BR callbackasm1(SB)
+ MOVD $1713, R0
+ BR callbackasm1(SB)
+ MOVD $1714, R0
+ BR callbackasm1(SB)
+ MOVD $1715, R0
+ BR callbackasm1(SB)
+ MOVD $1716, R0
+ BR callbackasm1(SB)
+ MOVD $1717, R0
+ BR callbackasm1(SB)
+ MOVD $1718, R0
+ BR callbackasm1(SB)
+ MOVD $1719, R0
+ BR callbackasm1(SB)
+ MOVD $1720, R0
+ BR callbackasm1(SB)
+ MOVD $1721, R0
+ BR callbackasm1(SB)
+ MOVD $1722, R0
+ BR callbackasm1(SB)
+ MOVD $1723, R0
+ BR callbackasm1(SB)
+ MOVD $1724, R0
+ BR callbackasm1(SB)
+ MOVD $1725, R0
+ BR callbackasm1(SB)
+ MOVD $1726, R0
+ BR callbackasm1(SB)
+ MOVD $1727, R0
+ BR callbackasm1(SB)
+ MOVD $1728, R0
+ BR callbackasm1(SB)
+ MOVD $1729, R0
+ BR callbackasm1(SB)
+ MOVD $1730, R0
+ BR callbackasm1(SB)
+ MOVD $1731, R0
+ BR callbackasm1(SB)
+ MOVD $1732, R0
+ BR callbackasm1(SB)
+ MOVD $1733, R0
+ BR callbackasm1(SB)
+ MOVD $1734, R0
+ BR callbackasm1(SB)
+ MOVD $1735, R0
+ BR callbackasm1(SB)
+ MOVD $1736, R0
+ BR callbackasm1(SB)
+ MOVD $1737, R0
+ BR callbackasm1(SB)
+ MOVD $1738, R0
+ BR callbackasm1(SB)
+ MOVD $1739, R0
+ BR callbackasm1(SB)
+ MOVD $1740, R0
+ BR callbackasm1(SB)
+ MOVD $1741, R0
+ BR callbackasm1(SB)
+ MOVD $1742, R0
+ BR callbackasm1(SB)
+ MOVD $1743, R0
+ BR callbackasm1(SB)
+ MOVD $1744, R0
+ BR callbackasm1(SB)
+ MOVD $1745, R0
+ BR callbackasm1(SB)
+ MOVD $1746, R0
+ BR callbackasm1(SB)
+ MOVD $1747, R0
+ BR callbackasm1(SB)
+ MOVD $1748, R0
+ BR callbackasm1(SB)
+ MOVD $1749, R0
+ BR callbackasm1(SB)
+ MOVD $1750, R0
+ BR callbackasm1(SB)
+ MOVD $1751, R0
+ BR callbackasm1(SB)
+ MOVD $1752, R0
+ BR callbackasm1(SB)
+ MOVD $1753, R0
+ BR callbackasm1(SB)
+ MOVD $1754, R0
+ BR callbackasm1(SB)
+ MOVD $1755, R0
+ BR callbackasm1(SB)
+ MOVD $1756, R0
+ BR callbackasm1(SB)
+ MOVD $1757, R0
+ BR callbackasm1(SB)
+ MOVD $1758, R0
+ BR callbackasm1(SB)
+ MOVD $1759, R0
+ BR callbackasm1(SB)
+ MOVD $1760, R0
+ BR callbackasm1(SB)
+ MOVD $1761, R0
+ BR callbackasm1(SB)
+ MOVD $1762, R0
+ BR callbackasm1(SB)
+ MOVD $1763, R0
+ BR callbackasm1(SB)
+ MOVD $1764, R0
+ BR callbackasm1(SB)
+ MOVD $1765, R0
+ BR callbackasm1(SB)
+ MOVD $1766, R0
+ BR callbackasm1(SB)
+ MOVD $1767, R0
+ BR callbackasm1(SB)
+ MOVD $1768, R0
+ BR callbackasm1(SB)
+ MOVD $1769, R0
+ BR callbackasm1(SB)
+ MOVD $1770, R0
+ BR callbackasm1(SB)
+ MOVD $1771, R0
+ BR callbackasm1(SB)
+ MOVD $1772, R0
+ BR callbackasm1(SB)
+ MOVD $1773, R0
+ BR callbackasm1(SB)
+ MOVD $1774, R0
+ BR callbackasm1(SB)
+ MOVD $1775, R0
+ BR callbackasm1(SB)
+ MOVD $1776, R0
+ BR callbackasm1(SB)
+ MOVD $1777, R0
+ BR callbackasm1(SB)
+ MOVD $1778, R0
+ BR callbackasm1(SB)
+ MOVD $1779, R0
+ BR callbackasm1(SB)
+ MOVD $1780, R0
+ BR callbackasm1(SB)
+ MOVD $1781, R0
+ BR callbackasm1(SB)
+ MOVD $1782, R0
+ BR callbackasm1(SB)
+ MOVD $1783, R0
+ BR callbackasm1(SB)
+ MOVD $1784, R0
+ BR callbackasm1(SB)
+ MOVD $1785, R0
+ BR callbackasm1(SB)
+ MOVD $1786, R0
+ BR callbackasm1(SB)
+ MOVD $1787, R0
+ BR callbackasm1(SB)
+ MOVD $1788, R0
+ BR callbackasm1(SB)
+ MOVD $1789, R0
+ BR callbackasm1(SB)
+ MOVD $1790, R0
+ BR callbackasm1(SB)
+ MOVD $1791, R0
+ BR callbackasm1(SB)
+ MOVD $1792, R0
+ BR callbackasm1(SB)
+ MOVD $1793, R0
+ BR callbackasm1(SB)
+ MOVD $1794, R0
+ BR callbackasm1(SB)
+ MOVD $1795, R0
+ BR callbackasm1(SB)
+ MOVD $1796, R0
+ BR callbackasm1(SB)
+ MOVD $1797, R0
+ BR callbackasm1(SB)
+ MOVD $1798, R0
+ BR callbackasm1(SB)
+ MOVD $1799, R0
+ BR callbackasm1(SB)
+ MOVD $1800, R0
+ BR callbackasm1(SB)
+ MOVD $1801, R0
+ BR callbackasm1(SB)
+ MOVD $1802, R0
+ BR callbackasm1(SB)
+ MOVD $1803, R0
+ BR callbackasm1(SB)
+ MOVD $1804, R0
+ BR callbackasm1(SB)
+ MOVD $1805, R0
+ BR callbackasm1(SB)
+ MOVD $1806, R0
+ BR callbackasm1(SB)
+ MOVD $1807, R0
+ BR callbackasm1(SB)
+ MOVD $1808, R0
+ BR callbackasm1(SB)
+ MOVD $1809, R0
+ BR callbackasm1(SB)
+ MOVD $1810, R0
+ BR callbackasm1(SB)
+ MOVD $1811, R0
+ BR callbackasm1(SB)
+ MOVD $1812, R0
+ BR callbackasm1(SB)
+ MOVD $1813, R0
+ BR callbackasm1(SB)
+ MOVD $1814, R0
+ BR callbackasm1(SB)
+ MOVD $1815, R0
+ BR callbackasm1(SB)
+ MOVD $1816, R0
+ BR callbackasm1(SB)
+ MOVD $1817, R0
+ BR callbackasm1(SB)
+ MOVD $1818, R0
+ BR callbackasm1(SB)
+ MOVD $1819, R0
+ BR callbackasm1(SB)
+ MOVD $1820, R0
+ BR callbackasm1(SB)
+ MOVD $1821, R0
+ BR callbackasm1(SB)
+ MOVD $1822, R0
+ BR callbackasm1(SB)
+ MOVD $1823, R0
+ BR callbackasm1(SB)
+ MOVD $1824, R0
+ BR callbackasm1(SB)
+ MOVD $1825, R0
+ BR callbackasm1(SB)
+ MOVD $1826, R0
+ BR callbackasm1(SB)
+ MOVD $1827, R0
+ BR callbackasm1(SB)
+ MOVD $1828, R0
+ BR callbackasm1(SB)
+ MOVD $1829, R0
+ BR callbackasm1(SB)
+ MOVD $1830, R0
+ BR callbackasm1(SB)
+ MOVD $1831, R0
+ BR callbackasm1(SB)
+ MOVD $1832, R0
+ BR callbackasm1(SB)
+ MOVD $1833, R0
+ BR callbackasm1(SB)
+ MOVD $1834, R0
+ BR callbackasm1(SB)
+ MOVD $1835, R0
+ BR callbackasm1(SB)
+ MOVD $1836, R0
+ BR callbackasm1(SB)
+ MOVD $1837, R0
+ BR callbackasm1(SB)
+ MOVD $1838, R0
+ BR callbackasm1(SB)
+ MOVD $1839, R0
+ BR callbackasm1(SB)
+ MOVD $1840, R0
+ BR callbackasm1(SB)
+ MOVD $1841, R0
+ BR callbackasm1(SB)
+ MOVD $1842, R0
+ BR callbackasm1(SB)
+ MOVD $1843, R0
+ BR callbackasm1(SB)
+ MOVD $1844, R0
+ BR callbackasm1(SB)
+ MOVD $1845, R0
+ BR callbackasm1(SB)
+ MOVD $1846, R0
+ BR callbackasm1(SB)
+ MOVD $1847, R0
+ BR callbackasm1(SB)
+ MOVD $1848, R0
+ BR callbackasm1(SB)
+ MOVD $1849, R0
+ BR callbackasm1(SB)
+ MOVD $1850, R0
+ BR callbackasm1(SB)
+ MOVD $1851, R0
+ BR callbackasm1(SB)
+ MOVD $1852, R0
+ BR callbackasm1(SB)
+ MOVD $1853, R0
+ BR callbackasm1(SB)
+ MOVD $1854, R0
+ BR callbackasm1(SB)
+ MOVD $1855, R0
+ BR callbackasm1(SB)
+ MOVD $1856, R0
+ BR callbackasm1(SB)
+ MOVD $1857, R0
+ BR callbackasm1(SB)
+ MOVD $1858, R0
+ BR callbackasm1(SB)
+ MOVD $1859, R0
+ BR callbackasm1(SB)
+ MOVD $1860, R0
+ BR callbackasm1(SB)
+ MOVD $1861, R0
+ BR callbackasm1(SB)
+ MOVD $1862, R0
+ BR callbackasm1(SB)
+ MOVD $1863, R0
+ BR callbackasm1(SB)
+ MOVD $1864, R0
+ BR callbackasm1(SB)
+ MOVD $1865, R0
+ BR callbackasm1(SB)
+ MOVD $1866, R0
+ BR callbackasm1(SB)
+ MOVD $1867, R0
+ BR callbackasm1(SB)
+ MOVD $1868, R0
+ BR callbackasm1(SB)
+ MOVD $1869, R0
+ BR callbackasm1(SB)
+ MOVD $1870, R0
+ BR callbackasm1(SB)
+ MOVD $1871, R0
+ BR callbackasm1(SB)
+ MOVD $1872, R0
+ BR callbackasm1(SB)
+ MOVD $1873, R0
+ BR callbackasm1(SB)
+ MOVD $1874, R0
+ BR callbackasm1(SB)
+ MOVD $1875, R0
+ BR callbackasm1(SB)
+ MOVD $1876, R0
+ BR callbackasm1(SB)
+ MOVD $1877, R0
+ BR callbackasm1(SB)
+ MOVD $1878, R0
+ BR callbackasm1(SB)
+ MOVD $1879, R0
+ BR callbackasm1(SB)
+ MOVD $1880, R0
+ BR callbackasm1(SB)
+ MOVD $1881, R0
+ BR callbackasm1(SB)
+ MOVD $1882, R0
+ BR callbackasm1(SB)
+ MOVD $1883, R0
+ BR callbackasm1(SB)
+ MOVD $1884, R0
+ BR callbackasm1(SB)
+ MOVD $1885, R0
+ BR callbackasm1(SB)
+ MOVD $1886, R0
+ BR callbackasm1(SB)
+ MOVD $1887, R0
+ BR callbackasm1(SB)
+ MOVD $1888, R0
+ BR callbackasm1(SB)
+ MOVD $1889, R0
+ BR callbackasm1(SB)
+ MOVD $1890, R0
+ BR callbackasm1(SB)
+ MOVD $1891, R0
+ BR callbackasm1(SB)
+ MOVD $1892, R0
+ BR callbackasm1(SB)
+ MOVD $1893, R0
+ BR callbackasm1(SB)
+ MOVD $1894, R0
+ BR callbackasm1(SB)
+ MOVD $1895, R0
+ BR callbackasm1(SB)
+ MOVD $1896, R0
+ BR callbackasm1(SB)
+ MOVD $1897, R0
+ BR callbackasm1(SB)
+ MOVD $1898, R0
+ BR callbackasm1(SB)
+ MOVD $1899, R0
+ BR callbackasm1(SB)
+ MOVD $1900, R0
+ BR callbackasm1(SB)
+ MOVD $1901, R0
+ BR callbackasm1(SB)
+ MOVD $1902, R0
+ BR callbackasm1(SB)
+ MOVD $1903, R0
+ BR callbackasm1(SB)
+ MOVD $1904, R0
+ BR callbackasm1(SB)
+ MOVD $1905, R0
+ BR callbackasm1(SB)
+ MOVD $1906, R0
+ BR callbackasm1(SB)
+ MOVD $1907, R0
+ BR callbackasm1(SB)
+ MOVD $1908, R0
+ BR callbackasm1(SB)
+ MOVD $1909, R0
+ BR callbackasm1(SB)
+ MOVD $1910, R0
+ BR callbackasm1(SB)
+ MOVD $1911, R0
+ BR callbackasm1(SB)
+ MOVD $1912, R0
+ BR callbackasm1(SB)
+ MOVD $1913, R0
+ BR callbackasm1(SB)
+ MOVD $1914, R0
+ BR callbackasm1(SB)
+ MOVD $1915, R0
+ BR callbackasm1(SB)
+ MOVD $1916, R0
+ BR callbackasm1(SB)
+ MOVD $1917, R0
+ BR callbackasm1(SB)
+ MOVD $1918, R0
+ BR callbackasm1(SB)
+ MOVD $1919, R0
+ BR callbackasm1(SB)
+ MOVD $1920, R0
+ BR callbackasm1(SB)
+ MOVD $1921, R0
+ BR callbackasm1(SB)
+ MOVD $1922, R0
+ BR callbackasm1(SB)
+ MOVD $1923, R0
+ BR callbackasm1(SB)
+ MOVD $1924, R0
+ BR callbackasm1(SB)
+ MOVD $1925, R0
+ BR callbackasm1(SB)
+ MOVD $1926, R0
+ BR callbackasm1(SB)
+ MOVD $1927, R0
+ BR callbackasm1(SB)
+ MOVD $1928, R0
+ BR callbackasm1(SB)
+ MOVD $1929, R0
+ BR callbackasm1(SB)
+ MOVD $1930, R0
+ BR callbackasm1(SB)
+ MOVD $1931, R0
+ BR callbackasm1(SB)
+ MOVD $1932, R0
+ BR callbackasm1(SB)
+ MOVD $1933, R0
+ BR callbackasm1(SB)
+ MOVD $1934, R0
+ BR callbackasm1(SB)
+ MOVD $1935, R0
+ BR callbackasm1(SB)
+ MOVD $1936, R0
+ BR callbackasm1(SB)
+ MOVD $1937, R0
+ BR callbackasm1(SB)
+ MOVD $1938, R0
+ BR callbackasm1(SB)
+ MOVD $1939, R0
+ BR callbackasm1(SB)
+ MOVD $1940, R0
+ BR callbackasm1(SB)
+ MOVD $1941, R0
+ BR callbackasm1(SB)
+ MOVD $1942, R0
+ BR callbackasm1(SB)
+ MOVD $1943, R0
+ BR callbackasm1(SB)
+ MOVD $1944, R0
+ BR callbackasm1(SB)
+ MOVD $1945, R0
+ BR callbackasm1(SB)
+ MOVD $1946, R0
+ BR callbackasm1(SB)
+ MOVD $1947, R0
+ BR callbackasm1(SB)
+ MOVD $1948, R0
+ BR callbackasm1(SB)
+ MOVD $1949, R0
+ BR callbackasm1(SB)
+ MOVD $1950, R0
+ BR callbackasm1(SB)
+ MOVD $1951, R0
+ BR callbackasm1(SB)
+ MOVD $1952, R0
+ BR callbackasm1(SB)
+ MOVD $1953, R0
+ BR callbackasm1(SB)
+ MOVD $1954, R0
+ BR callbackasm1(SB)
+ MOVD $1955, R0
+ BR callbackasm1(SB)
+ MOVD $1956, R0
+ BR callbackasm1(SB)
+ MOVD $1957, R0
+ BR callbackasm1(SB)
+ MOVD $1958, R0
+ BR callbackasm1(SB)
+ MOVD $1959, R0
+ BR callbackasm1(SB)
+ MOVD $1960, R0
+ BR callbackasm1(SB)
+ MOVD $1961, R0
+ BR callbackasm1(SB)
+ MOVD $1962, R0
+ BR callbackasm1(SB)
+ MOVD $1963, R0
+ BR callbackasm1(SB)
+ MOVD $1964, R0
+ BR callbackasm1(SB)
+ MOVD $1965, R0
+ BR callbackasm1(SB)
+ MOVD $1966, R0
+ BR callbackasm1(SB)
+ MOVD $1967, R0
+ BR callbackasm1(SB)
+ MOVD $1968, R0
+ BR callbackasm1(SB)
+ MOVD $1969, R0
+ BR callbackasm1(SB)
+ MOVD $1970, R0
+ BR callbackasm1(SB)
+ MOVD $1971, R0
+ BR callbackasm1(SB)
+ MOVD $1972, R0
+ BR callbackasm1(SB)
+ MOVD $1973, R0
+ BR callbackasm1(SB)
+ MOVD $1974, R0
+ BR callbackasm1(SB)
+ MOVD $1975, R0
+ BR callbackasm1(SB)
+ MOVD $1976, R0
+ BR callbackasm1(SB)
+ MOVD $1977, R0
+ BR callbackasm1(SB)
+ MOVD $1978, R0
+ BR callbackasm1(SB)
+ MOVD $1979, R0
+ BR callbackasm1(SB)
+ MOVD $1980, R0
+ BR callbackasm1(SB)
+ MOVD $1981, R0
+ BR callbackasm1(SB)
+ MOVD $1982, R0
+ BR callbackasm1(SB)
+ MOVD $1983, R0
+ BR callbackasm1(SB)
+ MOVD $1984, R0
+ BR callbackasm1(SB)
+ MOVD $1985, R0
+ BR callbackasm1(SB)
+ MOVD $1986, R0
+ BR callbackasm1(SB)
+ MOVD $1987, R0
+ BR callbackasm1(SB)
+ MOVD $1988, R0
+ BR callbackasm1(SB)
+ MOVD $1989, R0
+ BR callbackasm1(SB)
+ MOVD $1990, R0
+ BR callbackasm1(SB)
+ MOVD $1991, R0
+ BR callbackasm1(SB)
+ MOVD $1992, R0
+ BR callbackasm1(SB)
+ MOVD $1993, R0
+ BR callbackasm1(SB)
+ MOVD $1994, R0
+ BR callbackasm1(SB)
+ MOVD $1995, R0
+ BR callbackasm1(SB)
+ MOVD $1996, R0
+ BR callbackasm1(SB)
+ MOVD $1997, R0
+ BR callbackasm1(SB)
+ MOVD $1998, R0
+ BR callbackasm1(SB)
+ MOVD $1999, R0
+ BR callbackasm1(SB)
diff --git a/raymenu/vendor/github.com/gen2brain/raylib-go/raygui/LICENSE b/raymenu/vendor/github.com/gen2brain/raylib-go/raygui/LICENSE
new file mode 100644
index 0000000..2329060
--- /dev/null
+++ b/raymenu/vendor/github.com/gen2brain/raylib-go/raygui/LICENSE
@@ -0,0 +1,17 @@
+ Copyright (C) 2016 Milan Nikolic (gen2brain)
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
diff --git a/raymenu/vendor/github.com/gen2brain/raylib-go/raygui/README.md b/raymenu/vendor/github.com/gen2brain/raylib-go/raygui/README.md
new file mode 100644
index 0000000..42c543c
--- /dev/null
+++ b/raymenu/vendor/github.com/gen2brain/raylib-go/raygui/README.md
@@ -0,0 +1,13 @@
+## raygui [](https://godoc.org/github.com/gen2brain/raylib-go/raygui)
+
+raygui is simple and easy-to-use IMGUI (immediate mode GUI API) library.
+
+
+### controls_test_suite
+
+
+
+
+### scroll_panel
+
+
diff --git a/raymenu/vendor/github.com/gen2brain/raylib-go/raygui/cgo.go b/raymenu/vendor/github.com/gen2brain/raylib-go/raygui/cgo.go
new file mode 100644
index 0000000..4198945
--- /dev/null
+++ b/raymenu/vendor/github.com/gen2brain/raylib-go/raygui/cgo.go
@@ -0,0 +1,6 @@
+package raygui
+
+/*
+#cgo CFLAGS: -std=gnu99 -Wno-unused-result
+*/
+import "C"
diff --git a/raymenu/vendor/github.com/gen2brain/raylib-go/raygui/cstring.go b/raymenu/vendor/github.com/gen2brain/raylib-go/raygui/cstring.go
new file mode 100644
index 0000000..023bfd4
--- /dev/null
+++ b/raymenu/vendor/github.com/gen2brain/raylib-go/raygui/cstring.go
@@ -0,0 +1,102 @@
+package raygui
+
+/*
+#include
+// Code from https://blog.pytool.com/language/golang/cgo/go-cgo-string/
+
+static char** make_str_array(int size) {
+ return calloc(sizeof(char*), size);
+}
+
+static int len_str_array(char **arr) {
+ int i = 0;
+ while (arr[i] != NULL) i++;
+ return i+1; // NULL does count
+}
+
+static void set_str_array(char **arr, int idx, char *s) {
+ arr[idx] = s;
+}
+
+static void free_str_array(char **arr, int size) {
+ int i;
+ for (i = 0; i < size; i++) {
+ free(arr[i]);
+ }
+ free(arr);
+}
+*/
+import "C"
+
+import (
+ "unsafe"
+)
+
+// CStringArray represents an array of pointers to NULL terminated C strings,
+// the array itself is terminated with a NULL
+type CStringArray struct {
+ Pointer unsafe.Pointer
+ Length int
+}
+
+// NewCStringArray returns an instance of CStringArray
+func NewCStringArray() *CStringArray {
+ return &CStringArray{}
+}
+
+// NewCStringArrayFromSlice makes an instance of CStringArray then copy the
+// input slice to it.
+func NewCStringArrayFromSlice(ss []string) *CStringArray {
+ var arr CStringArray
+ arr.Copy(ss)
+ return &arr
+}
+
+func NewCStringArrayFromPointer(p unsafe.Pointer) *CStringArray {
+ return &CStringArray{
+ Length: int(C.len_str_array((**C.char)(p))),
+ Pointer: p,
+ }
+}
+
+// ToSlice converts CStringArray to Go slice of strings
+func (arr *CStringArray) ToSlice() []string {
+ if arr.Length == 0 || arr.Pointer == nil {
+ return []string{}
+ }
+
+ var ss []string
+ var cs **C.char
+ defer C.free(unsafe.Pointer(cs))
+ p := uintptr(arr.Pointer)
+ for {
+ cs = *(***C.char)(unsafe.Pointer(&p))
+ if *cs == nil { // skip NULL - the last element
+ break
+ }
+ ss = append(ss, C.GoString(*cs))
+ p += unsafe.Sizeof(p)
+ }
+
+ return ss
+}
+
+// Copy converts Go slice of strings to C underlying struct of CStringArray
+func (arr *CStringArray) Copy(ss []string) {
+ arr.Length = len(ss) + 1 // one more element for NULL at the end
+ arr.Pointer = unsafe.Pointer(C.make_str_array(C.int(arr.Length)))
+
+ for i, s := range ss {
+ cs := C.CString(s) // will be free by Free() method
+ C.set_str_array((**C.char)(arr.Pointer), C.int(i), cs)
+ }
+}
+
+// Free frees C underlying struct of CStringArray
+// MUST call this method after using CStringArray
+// Exception: If you use NewCStringArrayFromPointer() to create CStringArray object
+// and you use other way to free C underlying structure pointed by the pointer,
+// then don't need to call Free()
+func (arr *CStringArray) Free() {
+ C.free_str_array((**C.char)(arr.Pointer), C.int(arr.Length))
+}
diff --git a/raymenu/vendor/github.com/gen2brain/raylib-go/raygui/raygui.go b/raymenu/vendor/github.com/gen2brain/raylib-go/raygui/raygui.go
new file mode 100644
index 0000000..fd0d3a8
--- /dev/null
+++ b/raymenu/vendor/github.com/gen2brain/raylib-go/raygui/raygui.go
@@ -0,0 +1,1538 @@
+package raygui
+
+/*
+#define RAYGUI_IMPLEMENTATION
+#include "raygui.h"
+#include
+*/
+import "C"
+
+import (
+ "image/color"
+ "strings"
+ "unsafe"
+
+ rl "github.com/gen2brain/raylib-go/raylib"
+)
+
+type (
+ ControlID uint16
+ PropertyID uint16
+ PropertyValue uint32
+
+ IconID uint32
+)
+
+func (p PropertyID) IsExtended() bool {
+ return p >= 16
+}
+
+func (v PropertyValue) AsColor() rl.Color {
+ return rl.Color{uint8(v >> 24), uint8(v >> 16), uint8(v >> 8), uint8(v)}
+}
+
+func NewColorPropertyValue(color rl.Color) PropertyValue {
+ return PropertyValue(uint32(color.R)<<24 + uint32(color.G)<<16 + uint32(color.B)<<8 + uint32(color.A))
+}
+
+// Gui control state
+const (
+ STATE_NORMAL PropertyValue = iota
+ STATE_FOCUSED
+ STATE_PRESSED
+ STATE_DISABLED
+)
+
+// Gui control text alignment
+const (
+ TEXT_ALIGN_LEFT PropertyValue = iota
+ TEXT_ALIGN_CENTER
+ TEXT_ALIGN_RIGHT
+)
+
+// Gui control text alignment vertical
+// NOTE: Text vertical position inside the text bounds
+const (
+ TEXT_ALIGN_TOP PropertyValue = iota
+ TEXT_ALIGN_MIDDLE
+ TEXT_ALIGN_BOTTOM
+)
+
+// Gui control text wrap mode
+// NOTE: Useful for multiline text
+const (
+ TEXT_WRAP_NONE PropertyValue = iota
+ TEXT_WRAP_CHAR
+ TEXT_WRAP_WORD
+)
+
+const (
+ SCROLLBAR_LEFT_SIDE PropertyValue = iota
+ SCROLLBAR_RIGHT_SIDE
+)
+
+// Gui controls
+const (
+ // Default -> populates to all controls when set
+ DEFAULT ControlID = iota
+
+ // Basic controls
+ LABEL // Used also for: LABELBUTTON
+ BUTTON
+ TOGGLE // Used also for: TOGGLEGROUP
+ SLIDER // Used also for: SLIDERBAR, TOGGLESLIDER
+ PROGRESSBAR
+ CHECKBOX
+ COMBOBOX
+ DROPDOWNBOX
+ TEXTBOX // Used also for: TEXTBOXMULTI
+ VALUEBOX
+ CONTROL11
+ LISTVIEW
+ COLORPICKER
+ SCROLLBAR
+ STATUSBAR
+)
+
+// ----------------------------------------------------------------------------------
+// Module Types and Structures Definition
+// ----------------------------------------------------------------------------------
+// Gui control property style color element
+const (
+ BORDER PropertyID = iota
+ BASE
+ TEXT
+ OTHER
+)
+
+// Gui base properties for every control
+// NOTE: RAYGUI_MAX_PROPS_BASE properties (by default 16 properties)
+const (
+ BORDER_COLOR_NORMAL PropertyID = iota // Control border color in STATE_NORMAL
+ BASE_COLOR_NORMAL // Control base color in STATE_NORMAL
+ TEXT_COLOR_NORMAL // Control text color in STATE_NORMAL
+ BORDER_COLOR_FOCUSED // Control border color in STATE_FOCUSED
+ BASE_COLOR_FOCUSED // Control base color in STATE_FOCUSED
+ TEXT_COLOR_FOCUSED // Control text color in STATE_FOCUSED
+ BORDER_COLOR_PRESSED // Control border color in STATE_PRESSED
+ BASE_COLOR_PRESSED // Control base color in STATE_PRESSED
+ TEXT_COLOR_PRESSED // Control text color in STATE_PRESSED
+ BORDER_COLOR_DISABLED // Control border color in STATE_DISABLED
+ BASE_COLOR_DISABLED // Control base color in STATE_DISABLED
+ TEXT_COLOR_DISABLED // Control text color in STATE_DISABLED
+ BORDER_WIDTH // Control border size, 0 for no border
+ TEXT_PADDING // Control text padding, not considering border
+ TEXT_ALIGNMENT // Control text horizontal alignment inside control text bound (after border and padding)
+)
+
+// Gui extended properties depend on control
+// NOTE: RAYGUI_MAX_PROPS_EXTENDED properties (by default, max 8 properties)
+// ----------------------------------------------------------------------------------
+// DEFAULT extended properties
+// NOTE: Those properties are common to all controls or global
+// WARNING: We only have 8 slots for those properties by default!!! -> New global control: TEXT?
+const (
+ TEXT_SIZE PropertyID = 16 + iota // Text size (glyphs max height)
+ TEXT_SPACING // Text spacing between glyphs
+ LINE_COLOR // Line control color
+ BACKGROUND_COLOR // Background color
+ TEXT_LINE_SPACING // Text spacing between lines
+ TEXT_ALIGNMENT_VERTICAL // Text vertical alignment inside text bounds (after border and padding)
+ TEXT_WRAP_MODE // Text wrap-mode inside text bounds
+)
+
+// Toggle/ToggleGroup
+const (
+ GROUP_PADDING PropertyID = 16 + iota // ToggleGroup separation between toggles
+)
+
+// Slider/SliderBar
+const (
+ SLIDER_WIDTH PropertyID = 16 + iota // Slider size of internal bar
+ SLIDER_PADDING // Slider/SliderBar internal bar padding
+)
+
+// ProgressBar
+const (
+ PROGRESS_PADDING PropertyID = 16 + iota // ProgressBar internal padding
+)
+
+// ScrollBar
+const (
+ ARROWS_SIZE PropertyID = 16 + iota // ScrollBar arrows size
+ ARROWS_VISIBLE // ScrollBar arrows visible
+ SCROLL_SLIDER_PADDING // ScrollBar slider internal padding
+ SCROLL_SLIDER_SIZE // ScrollBar slider size
+ SCROLL_PADDING // ScrollBar scroll padding from arrows
+ SCROLL_SPEED // ScrollBar scrolling speed
+)
+
+// CheckBox
+const (
+ CHECK_PADDING PropertyID = 16 + iota // CheckBox internal check padding
+)
+
+// ComboBox
+const (
+ COMBO_BUTTON_WIDTH PropertyID = 16 + iota // ComboBox right button width
+ COMBO_BUTTON_SPACING // ComboBox button separation
+)
+
+// DropdownBox
+const (
+ ARROW_PADDING PropertyID = 16 + iota // DropdownBox arrow separation from border and items
+ DROPDOWN_ITEMS_SPACING // DropdownBox items separation
+ DROPDOWN_ARROW_HIDDEN // DropdownBox arrow hidden
+ DROPDOWN_ROLL_UP // DropdownBox roll up flag (default rolls down)
+)
+
+// TextBox/TextBoxMulti/ValueBox/Spinner
+const (
+ TEXT_READONLY PropertyID = 16 + iota // TextBox in read-only mode: 0-text editable, 1-text no-editable
+)
+
+// ValueBox/Spinner
+const (
+ SPINNER_BUTTON_WIDTH PropertyID = 16 // Spinner left/right buttons width
+ SPINNER_BUTTON_SPACING // Spinner buttons separation
+)
+
+// ListView
+const (
+ LIST_ITEMS_HEIGHT PropertyID = 16 + iota // ListView items height
+ LIST_ITEMS_SPACING // ListView items separation
+ SCROLLBAR_WIDTH // ListView scrollbar size (usually width)
+ SCROLLBAR_SIDE // ListView scrollbar side (0-SCROLLBAR_LEFT_SIDE, 1-SCROLLBAR_RIGHT_SIDE)
+ LIST_ITEMS_BORDER_NORMAL // ListView items border enabled in normal state
+ LIST_ITEMS_BORDER_WIDTH // ListView items border width
+)
+
+// ColorPicker
+const (
+ COLOR_SELECTOR_SIZE PropertyID = 16 + iota
+ HUEBAR_WIDTH // ColorPicker right hue bar width
+ HUEBAR_PADDING // ColorPicker right hue bar separation from panel
+ HUEBAR_SELECTOR_HEIGHT // ColorPicker right hue bar selector height
+ HUEBAR_SELECTOR_OVERFLOW // ColorPicker right hue bar selector overflow
+)
+
+// Icons enumeration
+const (
+ ICON_NONE IconID = 0
+ ICON_FOLDER_FILE_OPEN IconID = 1
+ ICON_FILE_SAVE_CLASSIC IconID = 2
+ ICON_FOLDER_OPEN IconID = 3
+ ICON_FOLDER_SAVE IconID = 4
+ ICON_FILE_OPEN IconID = 5
+ ICON_FILE_SAVE IconID = 6
+ ICON_FILE_EXPORT IconID = 7
+ ICON_FILE_ADD IconID = 8
+ ICON_FILE_DELETE IconID = 9
+ ICON_FILETYPE_TEXT IconID = 10
+ ICON_FILETYPE_AUDIO IconID = 11
+ ICON_FILETYPE_IMAGE IconID = 12
+ ICON_FILETYPE_PLAY IconID = 13
+ ICON_FILETYPE_VIDEO IconID = 14
+ ICON_FILETYPE_INFO IconID = 15
+ ICON_FILE_COPY IconID = 16
+ ICON_FILE_CUT IconID = 17
+ ICON_FILE_PASTE IconID = 18
+ ICON_CURSOR_HAND IconID = 19
+ ICON_CURSOR_POINTER IconID = 20
+ ICON_CURSOR_CLASSIC IconID = 21
+ ICON_PENCIL IconID = 22
+ ICON_PENCIL_BIG IconID = 23
+ ICON_BRUSH_CLASSIC IconID = 24
+ ICON_BRUSH_PAINTER IconID = 25
+ ICON_WATER_DROP IconID = 26
+ ICON_COLOR_PICKER IconID = 27
+ ICON_RUBBER IconID = 28
+ ICON_COLOR_BUCKET IconID = 29
+ ICON_TEXT_T IconID = 30
+ ICON_TEXT_A IconID = 31
+ ICON_SCALE IconID = 32
+ ICON_RESIZE IconID = 33
+ ICON_FILTER_POINT IconID = 34
+ ICON_FILTER_BILINEAR IconID = 35
+ ICON_CROP IconID = 36
+ ICON_CROP_ALPHA IconID = 37
+ ICON_SQUARE_TOGGLE IconID = 38
+ ICON_SYMMETRY IconID = 39
+ ICON_SYMMETRY_HORIZONTAL IconID = 40
+ ICON_SYMMETRY_VERTICAL IconID = 41
+ ICON_LENS IconID = 42
+ ICON_LENS_BIG IconID = 43
+ ICON_EYE_ON IconID = 44
+ ICON_EYE_OFF IconID = 45
+ ICON_FILTER_TOP IconID = 46
+ ICON_FILTER IconID = 47
+ ICON_TARGET_POINT IconID = 48
+ ICON_TARGET_SMALL IconID = 49
+ ICON_TARGET_BIG IconID = 50
+ ICON_TARGET_MOVE IconID = 51
+ ICON_CURSOR_MOVE IconID = 52
+ ICON_CURSOR_SCALE IconID = 53
+ ICON_CURSOR_SCALE_RIGHT IconID = 54
+ ICON_CURSOR_SCALE_LEFT IconID = 55
+ ICON_UNDO IconID = 56
+ ICON_REDO IconID = 57
+ ICON_REREDO IconID = 58
+ ICON_MUTATE IconID = 59
+ ICON_ROTATE IconID = 60
+ ICON_REPEAT IconID = 61
+ ICON_SHUFFLE IconID = 62
+ ICON_EMPTYBOX IconID = 63
+ ICON_TARGET IconID = 64
+ ICON_TARGET_SMALL_FILL IconID = 65
+ ICON_TARGET_BIG_FILL IconID = 66
+ ICON_TARGET_MOVE_FILL IconID = 67
+ ICON_CURSOR_MOVE_FILL IconID = 68
+ ICON_CURSOR_SCALE_FILL IconID = 69
+ ICON_CURSOR_SCALE_RIGHT_FILL IconID = 70
+ ICON_CURSOR_SCALE_LEFT_FILL IconID = 71
+ ICON_UNDO_FILL IconID = 72
+ ICON_REDO_FILL IconID = 73
+ ICON_REREDO_FILL IconID = 74
+ ICON_MUTATE_FILL IconID = 75
+ ICON_ROTATE_FILL IconID = 76
+ ICON_REPEAT_FILL IconID = 77
+ ICON_SHUFFLE_FILL IconID = 78
+ ICON_EMPTYBOX_SMALL IconID = 79
+ ICON_BOX IconID = 80
+ ICON_BOX_TOP IconID = 81
+ ICON_BOX_TOP_RIGHT IconID = 82
+ ICON_BOX_RIGHT IconID = 83
+ ICON_BOX_BOTTOM_RIGHT IconID = 84
+ ICON_BOX_BOTTOM IconID = 85
+ ICON_BOX_BOTTOM_LEFT IconID = 86
+ ICON_BOX_LEFT IconID = 87
+ ICON_BOX_TOP_LEFT IconID = 88
+ ICON_BOX_CENTER IconID = 89
+ ICON_BOX_CIRCLE_MASK IconID = 90
+ ICON_POT IconID = 91
+ ICON_ALPHA_MULTIPLY IconID = 92
+ ICON_ALPHA_CLEAR IconID = 93
+ ICON_DITHERING IconID = 94
+ ICON_MIPMAPS IconID = 95
+ ICON_BOX_GRID IconID = 96
+ ICON_GRID IconID = 97
+ ICON_BOX_CORNERS_SMALL IconID = 98
+ ICON_BOX_CORNERS_BIG IconID = 99
+ ICON_FOUR_BOXES IconID = 100
+ ICON_GRID_FILL IconID = 101
+ ICON_BOX_MULTISIZE IconID = 102
+ ICON_ZOOM_SMALL IconID = 103
+ ICON_ZOOM_MEDIUM IconID = 104
+ ICON_ZOOM_BIG IconID = 105
+ ICON_ZOOM_ALL IconID = 106
+ ICON_ZOOM_CENTER IconID = 107
+ ICON_BOX_DOTS_SMALL IconID = 108
+ ICON_BOX_DOTS_BIG IconID = 109
+ ICON_BOX_CONCENTRIC IconID = 110
+ ICON_BOX_GRID_BIG IconID = 111
+ ICON_OK_TICK IconID = 112
+ ICON_CROSS IconID = 113
+ ICON_ARROW_LEFT IconID = 114
+ ICON_ARROW_RIGHT IconID = 115
+ ICON_ARROW_DOWN IconID = 116
+ ICON_ARROW_UP IconID = 117
+ ICON_ARROW_LEFT_FILL IconID = 118
+ ICON_ARROW_RIGHT_FILL IconID = 119
+ ICON_ARROW_DOWN_FILL IconID = 120
+ ICON_ARROW_UP_FILL IconID = 121
+ ICON_AUDIO IconID = 122
+ ICON_FX IconID = 123
+ ICON_WAVE IconID = 124
+ ICON_WAVE_SINUS IconID = 125
+ ICON_WAVE_SQUARE IconID = 126
+ ICON_WAVE_TRIANGULAR IconID = 127
+ ICON_CROSS_SMALL IconID = 128
+ ICON_PLAYER_PREVIOUS IconID = 129
+ ICON_PLAYER_PLAY_BACK IconID = 130
+ ICON_PLAYER_PLAY IconID = 131
+ ICON_PLAYER_PAUSE IconID = 132
+ ICON_PLAYER_STOP IconID = 133
+ ICON_PLAYER_NEXT IconID = 134
+ ICON_PLAYER_RECORD IconID = 135
+ ICON_MAGNET IconID = 136
+ ICON_LOCK_CLOSE IconID = 137
+ ICON_LOCK_OPEN IconID = 138
+ ICON_CLOCK IconID = 139
+ ICON_TOOLS IconID = 140
+ ICON_GEAR IconID = 141
+ ICON_GEAR_BIG IconID = 142
+ ICON_BIN IconID = 143
+ ICON_HAND_POINTER IconID = 144
+ ICON_LASER IconID = 145
+ ICON_COIN IconID = 146
+ ICON_EXPLOSION IconID = 147
+ ICON_1UP IconID = 148
+ ICON_PLAYER IconID = 149
+ ICON_PLAYER_JUMP IconID = 150
+ ICON_KEY IconID = 151
+ ICON_DEMON IconID = 152
+ ICON_TEXT_POPUP IconID = 153
+ ICON_GEAR_EX IconID = 154
+ ICON_CRACK IconID = 155
+ ICON_CRACK_POINTS IconID = 156
+ ICON_STAR IconID = 157
+ ICON_DOOR IconID = 158
+ ICON_EXIT IconID = 159
+ ICON_MODE_2D IconID = 160
+ ICON_MODE_3D IconID = 161
+ ICON_CUBE IconID = 162
+ ICON_CUBE_FACE_TOP IconID = 163
+ ICON_CUBE_FACE_LEFT IconID = 164
+ ICON_CUBE_FACE_FRONT IconID = 165
+ ICON_CUBE_FACE_BOTTOM IconID = 166
+ ICON_CUBE_FACE_RIGHT IconID = 167
+ ICON_CUBE_FACE_BACK IconID = 168
+ ICON_CAMERA IconID = 169
+ ICON_SPECIAL IconID = 170
+ ICON_LINK_NET IconID = 171
+ ICON_LINK_BOXES IconID = 172
+ ICON_LINK_MULTI IconID = 173
+ ICON_LINK IconID = 174
+ ICON_LINK_BROKE IconID = 175
+ ICON_TEXT_NOTES IconID = 176
+ ICON_NOTEBOOK IconID = 177
+ ICON_SUITCASE IconID = 178
+ ICON_SUITCASE_ZIP IconID = 179
+ ICON_MAILBOX IconID = 180
+ ICON_MONITOR IconID = 181
+ ICON_PRINTER IconID = 182
+ ICON_PHOTO_CAMERA IconID = 183
+ ICON_PHOTO_CAMERA_FLASH IconID = 184
+ ICON_HOUSE IconID = 185
+ ICON_HEART IconID = 186
+ ICON_CORNER IconID = 187
+ ICON_VERTICAL_BARS IconID = 188
+ ICON_VERTICAL_BARS_FILL IconID = 189
+ ICON_LIFE_BARS IconID = 190
+ ICON_INFO IconID = 191
+ ICON_CROSSLINE IconID = 192
+ ICON_HELP IconID = 193
+ ICON_FILETYPE_ALPHA IconID = 194
+ ICON_FILETYPE_HOME IconID = 195
+ ICON_LAYERS_VISIBLE IconID = 196
+ ICON_LAYERS IconID = 197
+ ICON_WINDOW IconID = 198
+ ICON_HIDPI IconID = 199
+ ICON_FILETYPE_BINARY IconID = 200
+ ICON_HEX IconID = 201
+ ICON_SHIELD IconID = 202
+ ICON_FILE_NEW IconID = 203
+ ICON_FOLDER_ADD IconID = 204
+ ICON_ALARM IconID = 205
+ ICON_CPU IconID = 206
+ ICON_ROM IconID = 207
+ ICON_STEP_OVER IconID = 208
+ ICON_STEP_INTO IconID = 209
+ ICON_STEP_OUT IconID = 210
+ ICON_RESTART IconID = 211
+ ICON_BREAKPOINT_ON IconID = 212
+ ICON_BREAKPOINT_OFF IconID = 213
+ ICON_BURGER_MENU IconID = 214
+ ICON_CASE_SENSITIVE IconID = 215
+ ICON_REG_EXP IconID = 216
+ ICON_FOLDER IconID = 217
+ ICON_FILE IconID = 218
+ ICON_SAND_TIMER IconID = 219
+ ICON_WARNING IconID = 220
+ ICON_HELP_BOX IconID = 221
+ ICON_INFO_BOX IconID = 222
+ ICON_PRIORITY IconID = 223
+ ICON_LAYERS_ISO IconID = 224
+ ICON_LAYERS2 IconID = 225
+ ICON_MLAYERS IconID = 226
+ ICON_MAPS IconID = 227
+ ICON_HOT IconID = 228
+ ICON_LABEL IconID = 229
+ ICON_NAME_ID IconID = 230
+ ICON_SLICING IconID = 231
+ ICON_MANUAL_CONTROL IconID = 232
+ ICON_COLLISION IconID = 233
+ ICON_CIRCLE_ADD IconID = 234
+ ICON_CIRCLE_ADD_FILL IconID = 235
+ ICON_CIRCLE_WARNING IconID = 236
+ ICON_CIRCLE_WARNING_FILL IconID = 237
+ ICON_BOX_MORE IconID = 238
+ ICON_BOX_MORE_FILL IconID = 239
+ ICON_BOX_MINUS IconID = 240
+ ICON_BOX_MINUS_FILL IconID = 241
+ ICON_UNION IconID = 242
+ ICON_INTERSECTION IconID = 243
+ ICON_DIFFERENCE IconID = 244
+ ICON_SPHERE IconID = 245
+ ICON_CYLINDER IconID = 246
+ ICON_CONE IconID = 247
+ ICON_ELLIPSOID IconID = 248
+ ICON_CAPSULE IconID = 249
+ ICON_250 IconID = 250
+ ICON_251 IconID = 251
+ ICON_252 IconID = 252
+ ICON_253 IconID = 253
+ ICON_254 IconID = 254
+ ICON_255 IconID = 255
+)
+
+//----------------------------------------------------------------------------------
+// Gui Setup Functions Definition
+//----------------------------------------------------------------------------------
+
+// Enable gui global state
+func Enable() {
+ C.GuiEnable()
+}
+
+// Disable gui global state
+func Disable() {
+ C.GuiDisable()
+}
+
+// Lock gui global state
+func Lock() {
+ C.GuiLock()
+}
+
+// Unlock gui global state
+func Unlock() {
+ C.GuiUnlock()
+}
+
+// Check if gui is locked (global state)
+func IsLocked() bool {
+ return bool(C.GuiIsLocked())
+}
+
+// Set gui controls alpha global state
+func SetAlpha(alpha float32) {
+ calpha := C.float(alpha)
+ C.GuiSetAlpha(calpha)
+}
+
+// Set gui state (global state)
+func SetState(state PropertyValue) {
+ cstate := C.int(state)
+ C.GuiSetState(cstate)
+}
+
+// Get gui state (global state)
+func GetState() PropertyValue {
+ return PropertyValue(C.GuiGetState())
+}
+
+// Set custom gui font
+func SetFont(font rl.Font) {
+ cfont := (*C.Font)(unsafe.Pointer(&font))
+ C.GuiSetFont(*cfont)
+}
+
+// Get custom gui font
+func GetFont() rl.Font {
+ ret := C.GuiGetFont()
+ ptr := unsafe.Pointer(&ret)
+ return *(*rl.Font)(ptr)
+}
+
+// Set control style property value
+func SetStyle(control ControlID, property PropertyID, value PropertyValue) {
+ ccontrol := C.int(control)
+ cproperty := C.int(property)
+ cvalue := C.int(value)
+ C.GuiSetStyle(ccontrol, cproperty, cvalue)
+}
+
+// Get control style property value
+func GetStyle(control ControlID, property PropertyID) PropertyValue {
+ ccontrol := C.int(control)
+ cproperty := C.int(property)
+ return PropertyValue(C.GuiGetStyle(ccontrol, cproperty))
+}
+
+func GetColor(control ControlID, property PropertyID) rl.Color {
+ color := C.GuiGetStyle(C.int(control), C.int(property))
+ return rl.Color{R: uint8(color >> 24), G: uint8(color >> 16), B: uint8(color >> 8), A: uint8(color)}
+}
+
+//----------------------------------------------------------------------------------
+// Gui Controls Functions Definition
+//----------------------------------------------------------------------------------
+
+// Window Box control
+func WindowBox(bounds rl.Rectangle, title string) bool {
+ var cbounds C.struct_Rectangle
+ cbounds.height = C.float(bounds.Height)
+ cbounds.x = C.float(bounds.X)
+ cbounds.y = C.float(bounds.Y)
+ cbounds.width = C.float(bounds.Width)
+ var ctitle *C.char
+ if len(title) > 0 {
+ ctitle = C.CString(title)
+ defer C.free(unsafe.Pointer(ctitle))
+ }
+ return C.GuiWindowBox(cbounds, ctitle) != 0
+}
+
+// Group Box control with text name
+func GroupBox(bounds rl.Rectangle, text string) {
+ var cbounds C.struct_Rectangle
+ cbounds.height = C.float(bounds.Height)
+ cbounds.x = C.float(bounds.X)
+ cbounds.y = C.float(bounds.Y)
+ cbounds.width = C.float(bounds.Width)
+ var ctext *C.char
+ if len(text) > 0 {
+ ctext = C.CString(text)
+ defer C.free(unsafe.Pointer(ctext))
+ }
+ C.GuiGroupBox(cbounds, ctext)
+}
+
+// Line control
+func Line(bounds rl.Rectangle, text string) {
+ var cbounds C.struct_Rectangle
+ cbounds.x = C.float(bounds.X)
+ cbounds.y = C.float(bounds.Y)
+ cbounds.width = C.float(bounds.Width)
+ cbounds.height = C.float(bounds.Height)
+ var ctext *C.char
+ if len(text) > 0 {
+ ctext = C.CString(text)
+ defer C.free(unsafe.Pointer(ctext))
+ }
+ C.GuiLine(cbounds, ctext)
+}
+
+// Panel control
+func Panel(bounds rl.Rectangle, text string) {
+ var cbounds C.struct_Rectangle
+ cbounds.width = C.float(bounds.Width)
+ cbounds.height = C.float(bounds.Height)
+ cbounds.x = C.float(bounds.X)
+ cbounds.y = C.float(bounds.Y)
+ var ctext *C.char
+ if len(text) > 0 {
+ ctext = C.CString(text)
+ defer C.free(unsafe.Pointer(ctext))
+ }
+ C.GuiPanel(cbounds, ctext)
+}
+
+// Tab Bar control, returns the current TAB closing requested, -1 otherwise
+func TabBar(bounds rl.Rectangle, text []string, active *int32) int32 {
+ var cbounds C.struct_Rectangle
+ cbounds.x = C.float(bounds.X)
+ cbounds.y = C.float(bounds.Y)
+ cbounds.width = C.float(bounds.Width)
+ cbounds.height = C.float(bounds.Height)
+
+ ctext := NewCStringArrayFromSlice(text)
+ defer ctext.Free()
+
+ count := C.int(len(text))
+
+ if active == nil {
+ active = new(int32)
+ }
+ cactive := C.int(*active)
+ defer func() {
+ *active = int32(cactive)
+ }()
+ return int32(C.GuiTabBar(cbounds, (**C.char)(ctext.Pointer), count, &cactive))
+}
+
+// Scroll Panel control
+func ScrollPanel(bounds rl.Rectangle, text string, content rl.Rectangle, scroll *rl.Vector2, view *rl.Rectangle) {
+ var cbounds C.struct_Rectangle
+ cbounds.x = C.float(bounds.X)
+ cbounds.y = C.float(bounds.Y)
+ cbounds.width = C.float(bounds.Width)
+ cbounds.height = C.float(bounds.Height)
+ var ctext *C.char
+ if len(text) > 0 {
+ ctext = C.CString(text)
+ defer C.free(unsafe.Pointer(ctext))
+ }
+ var ccontent C.struct_Rectangle
+ ccontent.x = C.float(content.X)
+ ccontent.y = C.float(content.Y)
+ ccontent.width = C.float(content.Width)
+ ccontent.height = C.float(content.Height)
+ var cscroll C.struct_Vector2
+ cscroll.x = C.float(scroll.X)
+ cscroll.y = C.float(scroll.Y)
+ defer func() {
+ scroll.X = float32(cscroll.x)
+ scroll.Y = float32(cscroll.y)
+ }()
+ var cview C.struct_Rectangle
+ cview.x = C.float(view.X)
+ cview.y = C.float(view.Y)
+ cview.width = C.float(view.Width)
+ cview.height = C.float(view.Height)
+ defer func() {
+ view.X = float32(cview.x)
+ view.Y = float32(cview.y)
+ view.Width = float32(cview.width)
+ view.Height = float32(cview.height)
+ }()
+
+ C.GuiScrollPanel(cbounds, ctext, ccontent, &cscroll, &cview)
+}
+
+// Label control
+func Label(bounds rl.Rectangle, text string) {
+ var cbounds C.struct_Rectangle
+ cbounds.x = C.float(bounds.X)
+ cbounds.y = C.float(bounds.Y)
+ cbounds.width = C.float(bounds.Width)
+ cbounds.height = C.float(bounds.Height)
+ var ctext *C.char
+ if len(text) > 0 {
+ ctext = C.CString(text)
+ defer C.free(unsafe.Pointer(ctext))
+ }
+ C.GuiLabel(cbounds, ctext)
+}
+
+// Button control, returns true when clicked
+func Button(bounds rl.Rectangle, text string) bool {
+ var cbounds C.struct_Rectangle
+ cbounds.x = C.float(bounds.X)
+ cbounds.y = C.float(bounds.Y)
+ cbounds.width = C.float(bounds.Width)
+ cbounds.height = C.float(bounds.Height)
+ var ctext *C.char
+ if len(text) > 0 {
+ ctext = C.CString(text)
+ defer C.free(unsafe.Pointer(ctext))
+ }
+ return C.GuiButton(cbounds, ctext) != 0
+}
+
+// LabelButton control, returns true when clicked
+func LabelButton(bounds rl.Rectangle, text string) bool {
+ var cbounds C.struct_Rectangle
+ cbounds.x = C.float(bounds.X)
+ cbounds.y = C.float(bounds.Y)
+ cbounds.width = C.float(bounds.Width)
+ cbounds.height = C.float(bounds.Height)
+ var ctext *C.char
+ if len(text) > 0 {
+ ctext = C.CString(text)
+ defer C.free(unsafe.Pointer(ctext))
+ }
+ return C.GuiLabelButton(cbounds, ctext) != 0
+}
+
+// Toggle control, returns true when active
+func Toggle(bounds rl.Rectangle, text string, active bool) bool {
+ var cbounds C.struct_Rectangle
+ cbounds.x = C.float(bounds.X)
+ cbounds.y = C.float(bounds.Y)
+ cbounds.width = C.float(bounds.Width)
+ cbounds.height = C.float(bounds.Height)
+ var ctext *C.char
+ if len(text) > 0 {
+ ctext = C.CString(text)
+ defer C.free(unsafe.Pointer(ctext))
+ }
+ cactive := C.bool(active)
+ C.GuiToggle(cbounds, ctext, &cactive)
+ return bool(cactive)
+}
+
+// ToggleGroup control, returns active toggle index
+func ToggleGroup(bounds rl.Rectangle, text string, active int32) int32 {
+ var cbounds C.struct_Rectangle
+ cbounds.x = C.float(bounds.X)
+ cbounds.y = C.float(bounds.Y)
+ cbounds.width = C.float(bounds.Width)
+ cbounds.height = C.float(bounds.Height)
+ var ctext *C.char
+ if len(text) > 0 {
+ ctext = C.CString(text)
+ defer C.free(unsafe.Pointer(ctext))
+ }
+ cactive := C.int(active)
+ C.GuiToggleGroup(cbounds, ctext, &cactive)
+ return int32(cactive)
+}
+
+// ToggleSlider control, returns true when clicked
+func ToggleSlider(bounds rl.Rectangle, text string, active int32) int32 {
+ var cbounds C.struct_Rectangle
+ cbounds.x = C.float(bounds.X)
+ cbounds.y = C.float(bounds.Y)
+ cbounds.width = C.float(bounds.Width)
+ cbounds.height = C.float(bounds.Height)
+ var ctext *C.char
+ if len(text) > 0 {
+ ctext = C.CString(text)
+ defer C.free(unsafe.Pointer(ctext))
+ }
+ cactive := C.int(active)
+ C.GuiToggleSlider(cbounds, ctext, &cactive)
+ return int32(cactive)
+}
+
+// CheckBox control, returns true when active
+func CheckBox(bounds rl.Rectangle, text string, checked bool) bool {
+ var cbounds C.struct_Rectangle
+ cbounds.x = C.float(bounds.X)
+ cbounds.y = C.float(bounds.Y)
+ cbounds.width = C.float(bounds.Width)
+ cbounds.height = C.float(bounds.Height)
+ var ctext *C.char
+ if len(text) > 0 {
+ ctext = C.CString(text)
+ defer C.free(unsafe.Pointer(ctext))
+ }
+ cchecked := C.bool(checked)
+ C.GuiCheckBox(cbounds, ctext, &cchecked)
+ return bool(cchecked)
+}
+
+// ComboBox control, returns selected item index
+func ComboBox(bounds rl.Rectangle, text string, active int32) int32 {
+ var cbounds C.struct_Rectangle
+ cbounds.x = C.float(bounds.X)
+ cbounds.y = C.float(bounds.Y)
+ cbounds.width = C.float(bounds.Width)
+ cbounds.height = C.float(bounds.Height)
+ var ctext *C.char
+ if len(text) > 0 {
+ ctext = C.CString(text)
+ defer C.free(unsafe.Pointer(ctext))
+ }
+ cactive := C.int(active)
+ C.GuiComboBox(cbounds, ctext, &cactive)
+ return int32(cactive)
+}
+
+// DropdownBox control, returns true when clicked
+func DropdownBox(bounds rl.Rectangle, text string, active *int32, editMode bool) bool {
+ var cbounds C.struct_Rectangle
+ cbounds.x = C.float(bounds.X)
+ cbounds.y = C.float(bounds.Y)
+ cbounds.width = C.float(bounds.Width)
+ cbounds.height = C.float(bounds.Height)
+ var ctext *C.char
+ if len(text) > 0 {
+ ctext = C.CString(text)
+ defer C.free(unsafe.Pointer(ctext))
+ }
+
+ if active == nil {
+ active = new(int32)
+ }
+ cactive := C.int(*active)
+ defer func() {
+ *active = int32(cactive)
+ }()
+
+ ceditMode := C.bool(editMode)
+
+ return C.GuiDropdownBox(cbounds, ctext, &cactive, ceditMode) != 0
+}
+
+// TextBox control, updates input text, returns true on ENTER pressed or defocused
+func TextBox(bounds rl.Rectangle, text *string, textSize int, editMode bool) bool {
+ var cbounds C.struct_Rectangle
+ cbounds.x = C.float(bounds.X)
+ cbounds.y = C.float(bounds.Y)
+ cbounds.width = C.float(bounds.Width)
+ cbounds.height = C.float(bounds.Height)
+
+ bs := []byte(*text)
+ if len(bs) == 0 {
+ bs = []byte{byte(0)}
+ }
+ if 0 < len(bs) && bs[len(bs)-1] != byte(0) { // minimalize allocation
+ bs = append(bs, byte(0)) // for next input symbols
+ }
+ ctext := (*C.char)(unsafe.Pointer(&bs[0]))
+ defer func() {
+ *text = strings.Trim(string(bs), "\x00")
+ // no need : C.free(unsafe.Pointer(ctext))
+ }()
+
+ ctextSize := C.int(textSize)
+ ceditMode := C.bool(editMode)
+
+ return C.GuiTextBox(cbounds, ctext, ctextSize, ceditMode) != 0
+}
+
+// Spinner control, sets value to the selected number and returns true when clicked.
+func Spinner(bounds rl.Rectangle, text string, value *int32, minValue, maxValue int, editMode bool) bool {
+ var cbounds C.struct_Rectangle
+ cbounds.x = C.float(bounds.X)
+ cbounds.y = C.float(bounds.Y)
+ cbounds.width = C.float(bounds.Width)
+ cbounds.height = C.float(bounds.Height)
+ var ctext *C.char
+ if len(text) > 0 {
+ ctext = C.CString(text)
+ defer C.free(unsafe.Pointer(ctext))
+ }
+
+ if value == nil {
+ value = new(int32)
+ }
+ cvalue := C.int(*value)
+ defer func() {
+ *value = int32(cvalue)
+ }()
+
+ cminValue := C.int(minValue)
+ cmaxValue := C.int(maxValue)
+ ceditMode := C.bool(editMode)
+
+ return C.GuiSpinner(cbounds, ctext, &cvalue, cminValue, cmaxValue, ceditMode) != 0
+}
+
+// ValueBox control, updates input text with numbers
+func ValueBox(bounds rl.Rectangle, text string, value *int32, minValue, maxValue int, editMode bool) bool {
+ var cbounds C.struct_Rectangle
+ cbounds.x = C.float(bounds.X)
+ cbounds.y = C.float(bounds.Y)
+ cbounds.width = C.float(bounds.Width)
+ cbounds.height = C.float(bounds.Height)
+ var ctext *C.char
+ if len(text) > 0 {
+ ctext = C.CString(text)
+ defer C.free(unsafe.Pointer(ctext))
+ }
+
+ if value == nil {
+ value = new(int32)
+ }
+ cvalue := C.int(*value)
+ defer func() {
+ *value = int32(cvalue)
+ }()
+
+ cminValue := C.int(minValue)
+ cmaxValue := C.int(maxValue)
+ ceditMode := C.bool(editMode)
+
+ return C.GuiValueBox(cbounds, ctext, &cvalue, cminValue, cmaxValue, ceditMode) != 0
+}
+
+// Floating point Value Box control, updates input val_str with numbers
+func ValueBoxFloat(bounds rl.Rectangle, text string, textValue *string, value *float32, editMode bool) bool {
+ var cbounds C.struct_Rectangle
+ cbounds.x = C.float(bounds.X)
+ cbounds.y = C.float(bounds.Y)
+ cbounds.width = C.float(bounds.Width)
+ cbounds.height = C.float(bounds.Height)
+ var ctext *C.char
+ if len(text) > 0 {
+ ctext = C.CString(text)
+ defer C.free(unsafe.Pointer(ctext))
+ }
+
+ bs := []byte(*textValue)
+ if len(bs) == 0 {
+ bs = []byte{byte(0)}
+ }
+ if 0 < len(bs) && bs[len(bs)-1] != byte(0) { // minimalize allocation
+ bs = append(bs, byte(0)) // for next input symbols
+ }
+ ctextValue := (*C.char)(unsafe.Pointer(&bs[0]))
+ defer func() {
+ *textValue = strings.Trim(string(bs), "\x00")
+ // no need : C.free(unsafe.Pointer(ctext))
+ }()
+
+ if value == nil {
+ value = new(float32)
+ }
+ cvalue := C.float(*value)
+ defer func() {
+ *value = float32(cvalue)
+ }()
+
+ return C.GuiValueBoxFloat(cbounds, ctext, ctextValue, &cvalue, C.bool(editMode)) != 0
+}
+
+// Slider control
+func Slider(bounds rl.Rectangle, textLeft, textRight string, value, minValue, maxValue float32) float32 {
+ var cbounds C.struct_Rectangle
+ cbounds.x = C.float(bounds.X)
+ cbounds.y = C.float(bounds.Y)
+ cbounds.width = C.float(bounds.Width)
+ cbounds.height = C.float(bounds.Height)
+
+ var ctextLeft *C.char
+ if len(textLeft) > 0 {
+ ctextLeft = C.CString(textLeft)
+ defer C.free(unsafe.Pointer(ctextLeft))
+ }
+
+ var ctextRight *C.char
+ if len(textRight) > 0 {
+ ctextRight = C.CString(textRight)
+ defer C.free(unsafe.Pointer(ctextRight))
+ }
+
+ cvalue := C.float(value)
+ cminValue := C.float(minValue)
+ cmaxValue := C.float(maxValue)
+ C.GuiSlider(cbounds, ctextLeft, ctextRight, &cvalue, cminValue, cmaxValue)
+ return float32(cvalue)
+}
+
+// SliderBar control, returns selected value
+func SliderBar(bounds rl.Rectangle, textLeft, textRight string, value, minValue, maxValue float32) float32 {
+ var cbounds C.struct_Rectangle
+ cbounds.width = C.float(bounds.Width)
+ cbounds.height = C.float(bounds.Height)
+ cbounds.x = C.float(bounds.X)
+ cbounds.y = C.float(bounds.Y)
+
+ var ctextLeft *C.char
+ if len(textLeft) > 0 {
+ ctextLeft = C.CString(textLeft)
+ defer C.free(unsafe.Pointer(ctextLeft))
+ }
+
+ var ctextRight *C.char
+ if len(textRight) > 0 {
+ ctextRight = C.CString(textRight)
+ defer C.free(unsafe.Pointer(ctextRight))
+ }
+
+ cvalue := C.float(value)
+ cminValue := C.float(minValue)
+ cmaxValue := C.float(maxValue)
+ C.GuiSliderBar(cbounds, ctextLeft, ctextRight, &cvalue, cminValue, cmaxValue)
+ return float32(cvalue)
+}
+
+// ProgressBar control, shows current progress value
+func ProgressBar(bounds rl.Rectangle, textLeft, textRight string, value, minValue, maxValue float32) float32 {
+ var cbounds C.struct_Rectangle
+ cbounds.width = C.float(bounds.Width)
+ cbounds.height = C.float(bounds.Height)
+ cbounds.x = C.float(bounds.X)
+ cbounds.y = C.float(bounds.Y)
+
+ var ctextLeft *C.char
+ if len(textLeft) > 0 {
+ ctextLeft = C.CString(textLeft)
+ defer C.free(unsafe.Pointer(ctextLeft))
+ }
+
+ var ctextRight *C.char
+ if len(textRight) > 0 {
+ ctextRight = C.CString(textRight)
+ defer C.free(unsafe.Pointer(ctextRight))
+ }
+
+ cvalue := C.float(value)
+ cminValue := C.float(minValue)
+ cmaxValue := C.float(maxValue)
+ C.GuiProgressBar(cbounds, ctextLeft, ctextRight, &cvalue, cminValue, cmaxValue)
+ return float32(cvalue)
+}
+
+// StatusBar control, shows info text
+func StatusBar(bounds rl.Rectangle, text string) {
+ var cbounds C.struct_Rectangle
+ cbounds.x = C.float(bounds.X)
+ cbounds.y = C.float(bounds.Y)
+ cbounds.width = C.float(bounds.Width)
+ cbounds.height = C.float(bounds.Height)
+ var ctext *C.char
+ if len(text) > 0 {
+ ctext = C.CString(text)
+ defer C.free(unsafe.Pointer(ctext))
+ }
+ C.GuiStatusBar(cbounds, ctext)
+}
+
+// DummyRectangle control, intended for placeholding
+func DummyRec(bounds rl.Rectangle, text string) {
+ var cbounds C.struct_Rectangle
+ cbounds.x = C.float(bounds.X)
+ cbounds.y = C.float(bounds.Y)
+ cbounds.width = C.float(bounds.Width)
+ cbounds.height = C.float(bounds.Height)
+ var ctext *C.char
+ if len(text) > 0 {
+ ctext = C.CString(text)
+ defer C.free(unsafe.Pointer(ctext))
+ }
+ C.GuiDummyRec(cbounds, ctext)
+}
+
+// ListView control, returns selected list item index
+func ListView(bounds rl.Rectangle, text string, scrollIndex *int32, active int32) int32 {
+ var cbounds C.struct_Rectangle
+ cbounds.x = C.float(bounds.X)
+ cbounds.y = C.float(bounds.Y)
+ cbounds.width = C.float(bounds.Width)
+ cbounds.height = C.float(bounds.Height)
+ var ctext *C.char
+ if len(text) > 0 {
+ ctext = C.CString(text)
+ defer C.free(unsafe.Pointer(ctext))
+ }
+
+ if scrollIndex == nil {
+ scrollIndex = new(int32)
+ }
+ cscrollIndex := C.int(*scrollIndex)
+ defer func() {
+ *scrollIndex = int32(cscrollIndex)
+ }()
+
+ cactive := C.int(active)
+
+ C.GuiListView(cbounds, ctext, &cscrollIndex, &cactive)
+ return int32(cactive)
+}
+
+// ListView control with extended parameters
+func ListViewEx(bounds rl.Rectangle, text []string, focus, scrollIndex *int32, active int32) int32 {
+ var cbounds C.struct_Rectangle
+ cbounds.x = C.float(bounds.X)
+ cbounds.y = C.float(bounds.Y)
+ cbounds.width = C.float(bounds.Width)
+ cbounds.height = C.float(bounds.Height)
+
+ ctext := NewCStringArrayFromSlice(text)
+ defer ctext.Free()
+
+ count := C.int(len(text))
+
+ if focus == nil {
+ focus = new(int32)
+ }
+ cfocus := C.int(*focus)
+ defer func() {
+ *focus = int32(cfocus)
+ }()
+
+ if scrollIndex == nil {
+ scrollIndex = new(int32)
+ }
+ cscrollIndex := C.int(*scrollIndex)
+ defer func() {
+ *scrollIndex = int32(cscrollIndex)
+ }()
+
+ cactive := C.int(active)
+
+ C.GuiListViewEx(cbounds, (**C.char)(ctext.Pointer), count, &cfocus, &cscrollIndex, &cactive)
+ return int32(cactive)
+}
+
+// ColorPanel control, Color (RGBA) variant
+func ColorPanel(bounds rl.Rectangle, text string, color rl.Color) rl.Color {
+ var cbounds C.struct_Rectangle
+ cbounds.x = C.float(bounds.X)
+ cbounds.y = C.float(bounds.Y)
+ cbounds.width = C.float(bounds.Width)
+ cbounds.height = C.float(bounds.Height)
+ var ctext *C.char
+ if len(text) > 0 {
+ ctext = C.CString(text)
+ defer C.free(unsafe.Pointer(ctext))
+ }
+ var ccolor C.struct_Color
+ ccolor.b = C.uchar(color.B)
+ ccolor.a = C.uchar(color.A)
+ ccolor.r = C.uchar(color.R)
+ ccolor.g = C.uchar(color.G)
+ C.GuiColorPanel(cbounds, ctext, &ccolor)
+ var goRes rl.Color
+ goRes.A = byte(ccolor.a)
+ goRes.R = byte(ccolor.r)
+ goRes.G = byte(ccolor.g)
+ goRes.B = byte(ccolor.b)
+ return goRes
+}
+
+// ColorBarAlpha control, returns alpha value normalized [0..1]
+func ColorBarAlpha(bounds rl.Rectangle, text string, alpha float32) float32 {
+ var cbounds C.struct_Rectangle
+ cbounds.width = C.float(bounds.Width)
+ cbounds.height = C.float(bounds.Height)
+ cbounds.x = C.float(bounds.X)
+ cbounds.y = C.float(bounds.Y)
+ var ctext *C.char
+ if len(text) > 0 {
+ ctext = C.CString(text)
+ defer C.free(unsafe.Pointer(ctext))
+ }
+ calpha := C.float(alpha)
+ C.GuiColorBarAlpha(cbounds, ctext, &calpha)
+ return float32(calpha)
+}
+
+// ColorBarHue control, returns alpha value normalized [0..1]
+func ColorBarHue(bounds rl.Rectangle, text string, value float32) float32 {
+ var cbounds C.struct_Rectangle
+ cbounds.x = C.float(bounds.X)
+ cbounds.y = C.float(bounds.Y)
+ cbounds.width = C.float(bounds.Width)
+ cbounds.height = C.float(bounds.Height)
+ var ctext *C.char
+ if len(text) > 0 {
+ ctext = C.CString(text)
+ defer C.free(unsafe.Pointer(ctext))
+ }
+ cvalue := C.float(value)
+ C.GuiColorBarHue(cbounds, ctext, &cvalue)
+ return float32(cvalue)
+}
+
+// ColorPicker control (multiple color controls)
+// NOTE: this picker converts RGB to HSV, which can cause the Hue control to jump. If you have this problem, consider using the HSV variant instead
+func ColorPicker(bounds rl.Rectangle, text string, color rl.Color) rl.Color {
+ var cbounds C.struct_Rectangle
+ cbounds.width = C.float(bounds.Width)
+ cbounds.height = C.float(bounds.Height)
+ cbounds.x = C.float(bounds.X)
+ cbounds.y = C.float(bounds.Y)
+ var ctext *C.char
+ if len(text) > 0 {
+ ctext = C.CString(text)
+ defer C.free(unsafe.Pointer(ctext))
+ }
+ var ccolor C.struct_Color
+ ccolor.r = C.uchar(color.R)
+ ccolor.g = C.uchar(color.G)
+ ccolor.b = C.uchar(color.B)
+ ccolor.a = C.uchar(color.A)
+ C.GuiColorPicker(cbounds, ctext, &ccolor)
+ var goRes rl.Color
+ goRes.A = byte(ccolor.a)
+ goRes.R = byte(ccolor.r)
+ goRes.G = byte(ccolor.g)
+ goRes.B = byte(ccolor.b)
+ return goRes
+}
+
+// ColorPicker control that avoids conversion to RGB on each call (multiple color controls)
+func ColorPickerHSV(bounds rl.Rectangle, text string, colorHSV *rl.Vector3) int32 {
+ var cbounds C.struct_Rectangle
+ cbounds.width = C.float(bounds.Width)
+ cbounds.height = C.float(bounds.Height)
+ cbounds.x = C.float(bounds.X)
+ cbounds.y = C.float(bounds.Y)
+
+ var ctext *C.char
+ if len(text) > 0 {
+ ctext = C.CString(text)
+ defer C.free(unsafe.Pointer(ctext))
+ }
+
+ var ccolorHSV C.struct_Vector3
+ ccolorHSV.x = C.float(colorHSV.X)
+ ccolorHSV.y = C.float(colorHSV.Y)
+ ccolorHSV.z = C.float(colorHSV.Z)
+ defer func() {
+ colorHSV.X = float32(ccolorHSV.x)
+ colorHSV.Y = float32(ccolorHSV.y)
+ colorHSV.Z = float32(ccolorHSV.z)
+ }()
+
+ return int32(C.GuiColorPickerHSV(cbounds, ctext, &ccolorHSV))
+}
+
+// ColorPanel control that returns HSV color value
+func ColorPanelHSV(bounds rl.Rectangle, text string, colorHSV *rl.Vector3) int32 {
+ var cbounds C.struct_Rectangle
+ cbounds.width = C.float(bounds.Width)
+ cbounds.height = C.float(bounds.Height)
+ cbounds.x = C.float(bounds.X)
+ cbounds.y = C.float(bounds.Y)
+
+ var ctext *C.char
+ if len(text) > 0 {
+ ctext = C.CString(text)
+ defer C.free(unsafe.Pointer(ctext))
+ }
+
+ var ccolorHSV C.struct_Vector3
+ ccolorHSV.x = C.float(colorHSV.X)
+ ccolorHSV.y = C.float(colorHSV.Y)
+ ccolorHSV.z = C.float(colorHSV.Z)
+ defer func() {
+ colorHSV.X = float32(ccolorHSV.x)
+ colorHSV.Y = float32(ccolorHSV.y)
+ colorHSV.Z = float32(ccolorHSV.z)
+ }()
+
+ return int32(C.GuiColorPanelHSV(cbounds, ctext, &ccolorHSV))
+}
+
+// MessageBox control
+func MessageBox(bounds rl.Rectangle, title, message, buttons string) int32 {
+ var cbounds C.struct_Rectangle
+ cbounds.x = C.float(bounds.X)
+ cbounds.y = C.float(bounds.Y)
+ cbounds.width = C.float(bounds.Width)
+ cbounds.height = C.float(bounds.Height)
+ var ctitle *C.char
+ if len(title) > 0 {
+ ctitle = C.CString(title)
+ defer C.free(unsafe.Pointer(ctitle))
+ }
+ var cmessage *C.char
+ if len(message) > 0 {
+ cmessage = C.CString(message)
+ defer C.free(unsafe.Pointer(cmessage))
+ }
+ cbuttons := C.CString(buttons)
+ defer C.free(unsafe.Pointer(cbuttons))
+ return int32(C.GuiMessageBox(cbounds, ctitle, cmessage, cbuttons))
+}
+
+// TextInputBox control, ask for text
+func TextInputBox(bounds rl.Rectangle, title, message, buttons string, text *string, textMaxSize int32, secretViewActive *bool) int32 {
+ var cbounds C.struct_Rectangle
+ cbounds.x = C.float(bounds.X)
+ cbounds.y = C.float(bounds.Y)
+ cbounds.width = C.float(bounds.Width)
+ cbounds.height = C.float(bounds.Height)
+
+ var ctitle *C.char
+ if len(title) > 0 {
+ ctitle = C.CString(title)
+ defer C.free(unsafe.Pointer(ctitle))
+ }
+
+ var cmessage *C.char
+ if len(message) > 0 {
+ cmessage = C.CString(message)
+ defer C.free(unsafe.Pointer(cmessage))
+ }
+
+ cbuttons := C.CString(buttons)
+ defer C.free(unsafe.Pointer(cbuttons))
+
+ bs := []byte(*text)
+ if len(bs) == 0 {
+ bs = []byte{byte(0)}
+ }
+ if 0 < len(bs) && bs[len(bs)-1] != byte(0) { // minimalize allocation
+ bs = append(bs, byte(0)) // for next input symbols
+ }
+ ctext := (*C.char)(unsafe.Pointer(&bs[0]))
+ defer func() {
+ *text = strings.TrimSpace(strings.Trim(string(bs), "\x00"))
+ // no need : C.free(unsafe.Pointer(ctext))
+ }()
+
+ ctextMaxSize := C.int(textMaxSize)
+
+ csecretViewActive := C.bool(*secretViewActive)
+ defer func() {
+ *secretViewActive = bool(csecretViewActive)
+ }()
+
+ return int32(C.GuiTextInputBox(cbounds, ctitle, cmessage, cbuttons, ctext, ctextMaxSize, &csecretViewActive))
+}
+
+// Grid control, returns mouse cell position
+func Grid(bounds rl.Rectangle, text string, spacing float32, subdivs int32, mouseCell *rl.Vector2) int32 {
+ var cbounds C.struct_Rectangle
+ cbounds.y = C.float(bounds.Y)
+ cbounds.width = C.float(bounds.Width)
+ cbounds.height = C.float(bounds.Height)
+ cbounds.x = C.float(bounds.X)
+ var ctext *C.char
+ if len(text) > 0 {
+ ctext = C.CString(text)
+ defer C.free(unsafe.Pointer(ctext))
+ }
+ cspacing := C.float(spacing)
+ csubdivs := C.int(subdivs)
+ var cmouseCell C.struct_Vector2
+ cmouseCell.x = C.float(mouseCell.X)
+ cmouseCell.y = C.float(mouseCell.Y)
+ res := C.GuiGrid(cbounds, ctext, cspacing, csubdivs, &cmouseCell)
+ mouseCell.X = float32(cmouseCell.x)
+ mouseCell.Y = float32(cmouseCell.y)
+ return int32(res)
+}
+
+//----------------------------------------------------------------------------------
+// Tooltip management functions
+// NOTE: Tooltips requires some global variables: tooltipPtr
+//----------------------------------------------------------------------------------
+
+// Enable gui tooltips (global state)
+func EnableTooltip() {
+ C.GuiEnableTooltip()
+}
+
+// Disable gui tooltips (global state)
+func DisableTooltip() {
+ C.GuiDisableTooltip()
+}
+
+// Set tooltip string
+func SetTooltip(tooltip string) {
+ ctooltip := C.CString(tooltip)
+ defer C.free(unsafe.Pointer(ctooltip))
+ C.GuiSetTooltip(ctooltip)
+}
+
+//----------------------------------------------------------------------------------
+// Styles loading functions
+//----------------------------------------------------------------------------------
+
+// Load raygui style file (.rgs)
+func LoadStyle(fileName string) {
+ cfileName := C.CString(fileName)
+ defer C.free(unsafe.Pointer(cfileName))
+ C.GuiLoadStyle(cfileName)
+}
+
+// Load style default over global style
+func LoadStyleDefault() {
+ C.GuiLoadStyleDefault()
+}
+
+// IconText gets text with icon id prepended (if supported)
+func IconText(iconId IconID, text string) string {
+ ciconId := C.int(iconId)
+ ctext := C.CString(text)
+ defer C.free(unsafe.Pointer(ctext))
+ return C.GoString(C.GuiIconText(ciconId, ctext))
+}
+
+// Load raygui icons file (.rgi)
+func LoadIcons(fileName string, loadIconsName bool) {
+ cfileName := C.CString(fileName)
+ defer C.free(unsafe.Pointer(cfileName))
+ C.GuiLoadIcons(cfileName, C.bool(loadIconsName))
+}
+
+// Load icons from memory (Binary files only)
+func LoadIconsFromMemory(data []byte, loadIconsName bool) {
+ C.GuiLoadIconsFromMemory((*C.uchar)(unsafe.Pointer(&data[0])), C.int(len(data)), C.bool(loadIconsName))
+}
+
+// Draw icon using pixel size at specified position
+func DrawIcon(iconId IconID, posX, posY, pixelSize int32, col color.RGBA) {
+ C.GuiDrawIcon(C.int(iconId), C.int(posX), C.int(posY), C.int(pixelSize), *(*C.Color)(unsafe.Pointer(&col)))
+}
+
+// Set icon drawing size
+func SetIconScale(scale int32) {
+ C.GuiSetIconScale(C.int(scale))
+}
+
+// Get text width considering gui style and icon size (if required)
+func GetTextWidth(text string) int32 {
+ ctext := C.CString(text)
+ defer C.free(unsafe.Pointer(ctext))
+ return int32(C.GuiGetTextWidth(ctext))
+}
+
+//----------------------------------------------------------------------------------
+// Module Internal Functions Definition
+//----------------------------------------------------------------------------------
+
+// Load style from memory (Binary files only)
+func LoadStyleFromMemory(data []byte) {
+ C.GuiLoadStyleFromMemory((*C.uchar)(unsafe.Pointer(&data[0])), C.int(len(data)))
+}
+
+// ScrollBar control
+func ScrollBar(bounds rl.Rectangle, value, minValue, maxValue int32) int32 {
+ var cbounds C.struct_Rectangle
+ cbounds.x = C.float(bounds.X)
+ cbounds.y = C.float(bounds.Y)
+ cbounds.width = C.float(bounds.Width)
+ cbounds.height = C.float(bounds.Height)
+
+ cvalue := C.int(value)
+ cminValue := C.int(minValue)
+ cmaxValue := C.int(maxValue)
+
+ return int32(C.GuiScrollBar(cbounds, cvalue, cminValue, cmaxValue))
+}
+
+// Color fade-in or fade-out, alpha value normalized [0..1]
+// WARNING: It multiplies current alpha by alpha scale factor
+func Fade(color rl.Color, alpha float32) rl.Color {
+ ccolor := C.struct_Color{C.uchar(color.R), C.uchar(color.G), C.uchar(color.B), C.uchar(color.A)}
+ calpha := C.float(alpha)
+ cresult := C.GuiFade(ccolor, calpha)
+ return rl.Color{R: uint8(cresult.r), G: uint8(cresult.g), B: uint8(cresult.b), A: uint8(cresult.a)}
+}
+
+//----------------------------------------------------------------------------------
+// Additional Draw functions
+//----------------------------------------------------------------------------------
+
+func DrawRectangle(bounds rl.Rectangle, borderWidth int32, borderColor, fillColor rl.Color) {
+ var cbounds C.struct_Rectangle
+ cbounds.x = C.float(bounds.X)
+ cbounds.y = C.float(bounds.Y)
+ cbounds.width = C.float(bounds.Width)
+ cbounds.height = C.float(bounds.Height)
+
+ var cborderColor C.struct_Color
+ cborderColor.r = C.uchar(borderColor.R)
+ cborderColor.g = C.uchar(borderColor.G)
+ cborderColor.b = C.uchar(borderColor.B)
+ cborderColor.a = C.uchar(borderColor.A)
+
+ var cfillColor C.struct_Color
+ cfillColor.r = C.uchar(fillColor.R)
+ cfillColor.g = C.uchar(fillColor.G)
+ cfillColor.b = C.uchar(fillColor.B)
+ cfillColor.a = C.uchar(fillColor.A)
+
+ bw := C.int(borderWidth)
+
+ C.GuiDrawRectangle(cbounds, bw, cborderColor, cfillColor)
+}
+
+// DrawText - static void GuiDrawText(const char *text, Rectangle textBounds, int alignment, Color tint);
+func DrawText(text string, position rl.Rectangle, alignment int32, color rl.Color) {
+ ctext := C.CString(text)
+ defer C.free(unsafe.Pointer(ctext))
+
+ var cposition C.struct_Rectangle
+ cposition.x = C.float(position.X)
+ cposition.y = C.float(position.Y)
+ cposition.width = C.float(position.Width)
+ cposition.height = C.float(position.Height)
+
+ calignment := C.int(alignment)
+ var ccolor C.struct_Color
+ ccolor.r = C.uchar(color.R)
+ ccolor.g = C.uchar(color.G)
+ ccolor.b = C.uchar(color.B)
+ ccolor.a = C.uchar(color.A)
+
+ C.GuiDrawText(ctext, cposition, calignment, ccolor)
+}
+
+// GetTextBounds - static Rectangle GetTextBounds(int control, Rectangle bounds)
+func GetTextBounds(control ControlID, bounds rl.Rectangle) rl.Rectangle {
+ var cbounds C.struct_Rectangle
+ cbounds.x = C.float(bounds.X)
+ cbounds.y = C.float(bounds.Y)
+ cbounds.width = C.float(bounds.Width)
+ cbounds.height = C.float(bounds.Height)
+
+ ccontrol := C.int(control)
+ cretBounds := C.GetTextBounds(ccontrol, cbounds)
+ return rl.Rectangle{
+ X: float32(cretBounds.x),
+ Y: float32(cretBounds.y),
+ Width: float32(cretBounds.width),
+ Height: float32(cretBounds.height),
+ }
+}
diff --git a/raymenu/vendor/github.com/gen2brain/raylib-go/raygui/raygui.h b/raymenu/vendor/github.com/gen2brain/raylib-go/raygui/raygui.h
new file mode 100644
index 0000000..64b4586
--- /dev/null
+++ b/raymenu/vendor/github.com/gen2brain/raylib-go/raygui/raygui.h
@@ -0,0 +1,5987 @@
+/*******************************************************************************************
+*
+* raygui v4.5-dev - A simple and easy-to-use immediate-mode gui library
+*
+* DESCRIPTION:
+* raygui is a tools-dev-focused immediate-mode-gui library based on raylib but also
+* available as a standalone library, as long as input and drawing functions are provided
+*
+* FEATURES:
+* - Immediate-mode gui, minimal retained data
+* - +25 controls provided (basic and advanced)
+* - Styling system for colors, font and metrics
+* - Icons supported, embedded as a 1-bit icons pack
+* - Standalone mode option (custom input/graphics backend)
+* - Multiple support tools provided for raygui development
+*
+* POSSIBLE IMPROVEMENTS:
+* - Better standalone mode API for easy plug of custom backends
+* - Externalize required inputs, allow user easier customization
+*
+* LIMITATIONS:
+* - No editable multi-line word-wraped text box supported
+* - No auto-layout mechanism, up to the user to define controls position and size
+* - Standalone mode requires library modification and some user work to plug another backend
+*
+* NOTES:
+* - WARNING: GuiLoadStyle() and GuiLoadStyle{Custom}() functions, allocate memory for
+* font atlas recs and glyphs, freeing that memory is (usually) up to the user,
+* no unload function is explicitly provided... but note that GuiLoadStyleDefault() unloads
+* by default any previously loaded font (texture, recs, glyphs)
+* - Global UI alpha (guiAlpha) is applied inside GuiDrawRectangle() and GuiDrawText() functions
+*
+* CONTROLS PROVIDED:
+* # Container/separators Controls
+* - WindowBox --> StatusBar, Panel
+* - GroupBox --> Line
+* - Line
+* - Panel --> StatusBar
+* - ScrollPanel --> StatusBar
+* - TabBar --> Button
+*
+* # Basic Controls
+* - Label
+* - LabelButton --> Label
+* - Button
+* - Toggle
+* - ToggleGroup --> Toggle
+* - ToggleSlider
+* - CheckBox
+* - ComboBox
+* - DropdownBox
+* - TextBox
+* - ValueBox --> TextBox
+* - Spinner --> Button, ValueBox
+* - Slider
+* - SliderBar --> Slider
+* - ProgressBar
+* - StatusBar
+* - DummyRec
+* - Grid
+*
+* # Advance Controls
+* - ListView
+* - ColorPicker --> ColorPanel, ColorBarHue
+* - MessageBox --> Window, Label, Button
+* - TextInputBox --> Window, Label, TextBox, Button
+*
+* It also provides a set of functions for styling the controls based on its properties (size, color)
+*
+*
+* RAYGUI STYLE (guiStyle):
+* raygui uses a global data array for all gui style properties (allocated on data segment by default),
+* when a new style is loaded, it is loaded over the global style... but a default gui style could always be
+* recovered with GuiLoadStyleDefault() function, that overwrites the current style to the default one
+*
+* The global style array size is fixed and depends on the number of controls and properties:
+*
+* static unsigned int guiStyle[RAYGUI_MAX_CONTROLS*(RAYGUI_MAX_PROPS_BASE + RAYGUI_MAX_PROPS_EXTENDED)];
+*
+* guiStyle size is by default: 16*(16 + 8) = 384 int = 384*4 bytes = 1536 bytes = 1.5 KB
+*
+* Note that the first set of BASE properties (by default guiStyle[0..15]) belong to the generic style
+* used for all controls, when any of those base values is set, it is automatically populated to all
+* controls, so, specific control values overwriting generic style should be set after base values
+*
+* After the first BASE set we have the EXTENDED properties (by default guiStyle[16..23]), those
+* properties are actually common to all controls and can not be overwritten individually (like BASE ones)
+* Some of those properties are: TEXT_SIZE, TEXT_SPACING, LINE_COLOR, BACKGROUND_COLOR
+*
+* Custom control properties can be defined using the EXTENDED properties for each independent control.
+*
+* TOOL: rGuiStyler is a visual tool to customize raygui style: github.com/raysan5/rguistyler
+*
+*
+* RAYGUI ICONS (guiIcons):
+* raygui could use a global array containing icons data (allocated on data segment by default),
+* a custom icons set could be loaded over this array using GuiLoadIcons(), but loaded icons set
+* must be same RAYGUI_ICON_SIZE and no more than RAYGUI_ICON_MAX_ICONS will be loaded
+*
+* Every icon is codified in binary form, using 1 bit per pixel, so, every 16x16 icon
+* requires 8 integers (16*16/32) to be stored in memory.
+*
+* When the icon is draw, actually one quad per pixel is drawn if the bit for that pixel is set
+*
+* The global icons array size is fixed and depends on the number of icons and size:
+*
+* static unsigned int guiIcons[RAYGUI_ICON_MAX_ICONS*RAYGUI_ICON_DATA_ELEMENTS];
+*
+* guiIcons size is by default: 256*(16*16/32) = 2048*4 = 8192 bytes = 8 KB
+*
+* TOOL: rGuiIcons is a visual tool to customize/create raygui icons: github.com/raysan5/rguiicons
+*
+* RAYGUI LAYOUT:
+* raygui currently does not provide an auto-layout mechanism like other libraries,
+* layouts must be defined manually on controls drawing, providing the right bounds Rectangle for it
+*
+* TOOL: rGuiLayout is a visual tool to create raygui layouts: github.com/raysan5/rguilayout
+*
+* CONFIGURATION:
+* #define RAYGUI_IMPLEMENTATION
+* Generates the implementation of the library into the included file
+* If not defined, the library is in header only mode and can be included in other headers
+* or source files without problems. But only ONE file should hold the implementation
+*
+* #define RAYGUI_STANDALONE
+* Avoid raylib.h header inclusion in this file. Data types defined on raylib are defined
+* internally in the library and input management and drawing functions must be provided by
+* the user (check library implementation for further details)
+*
+* #define RAYGUI_NO_ICONS
+* Avoid including embedded ricons data (256 icons, 16x16 pixels, 1-bit per pixel, 2KB)
+*
+* #define RAYGUI_CUSTOM_ICONS
+* Includes custom ricons.h header defining a set of custom icons,
+* this file can be generated using rGuiIcons tool
+*
+* #define RAYGUI_DEBUG_RECS_BOUNDS
+* Draw control bounds rectangles for debug
+*
+* #define RAYGUI_DEBUG_TEXT_BOUNDS
+* Draw text bounds rectangles for debug
+*
+* VERSIONS HISTORY:
+* 5.0 (xx-Nov-2025) ADDED: Support up to 32 controls (v500)
+* ADDED: guiControlExclusiveMode and guiControlExclusiveRec for exclusive modes
+* ADDED: GuiValueBoxFloat()
+* ADDED: GuiDropdonwBox() properties: DROPDOWN_ARROW_HIDDEN, DROPDOWN_ROLL_UP
+* ADDED: GuiListView() property: LIST_ITEMS_BORDER_WIDTH
+* ADDED: GuiLoadIconsFromMemory()
+* ADDED: Multiple new icons
+* REMOVED: GuiSpinner() from controls list, using BUTTON + VALUEBOX properties
+* REMOVED: GuiSliderPro(), functionality was redundant
+* REVIEWED: Controls using text labels to use LABEL properties
+* REVIEWED: Replaced sprintf() by snprintf() for more safety
+* REVIEWED: GuiTabBar(), close tab with mouse middle button
+* REVIEWED: GuiScrollPanel(), scroll speed proportional to content
+* REVIEWED: GuiDropdownBox(), support roll up and hidden arrow
+* REVIEWED: GuiTextBox(), cursor position initialization
+* REVIEWED: GuiSliderPro(), control value change check
+* REVIEWED: GuiGrid(), simplified implementation
+* REVIEWED: GuiIconText(), increase buffer size and reviewed padding
+* REVIEWED: GuiDrawText(), improved wrap mode drawing
+* REVIEWED: GuiScrollBar(), minor tweaks
+* REVIEWED: GuiProgressBar(), improved borders computing
+* REVIEWED: GuiTextBox(), multiple improvements: autocursor and more
+* REVIEWED: Functions descriptions, removed wrong return value reference
+* REDESIGNED: GuiColorPanel(), improved HSV <-> RGBA convertion
+*
+* 4.0 (12-Sep-2023) ADDED: GuiToggleSlider()
+* ADDED: GuiColorPickerHSV() and GuiColorPanelHSV()
+* ADDED: Multiple new icons, mostly compiler related
+* ADDED: New DEFAULT properties: TEXT_LINE_SPACING, TEXT_ALIGNMENT_VERTICAL, TEXT_WRAP_MODE
+* ADDED: New enum values: GuiTextAlignment, GuiTextAlignmentVertical, GuiTextWrapMode
+* ADDED: Support loading styles with custom font charset from external file
+* REDESIGNED: GuiTextBox(), support mouse cursor positioning
+* REDESIGNED: GuiDrawText(), support multiline and word-wrap modes (read only)
+* REDESIGNED: GuiProgressBar() to be more visual, progress affects border color
+* REDESIGNED: Global alpha consideration moved to GuiDrawRectangle() and GuiDrawText()
+* REDESIGNED: GuiScrollPanel(), get parameters by reference and return result value
+* REDESIGNED: GuiToggleGroup(), get parameters by reference and return result value
+* REDESIGNED: GuiComboBox(), get parameters by reference and return result value
+* REDESIGNED: GuiCheckBox(), get parameters by reference and return result value
+* REDESIGNED: GuiSlider(), get parameters by reference and return result value
+* REDESIGNED: GuiSliderBar(), get parameters by reference and return result value
+* REDESIGNED: GuiProgressBar(), get parameters by reference and return result value
+* REDESIGNED: GuiListView(), get parameters by reference and return result value
+* REDESIGNED: GuiColorPicker(), get parameters by reference and return result value
+* REDESIGNED: GuiColorPanel(), get parameters by reference and return result value
+* REDESIGNED: GuiColorBarAlpha(), get parameters by reference and return result value
+* REDESIGNED: GuiColorBarHue(), get parameters by reference and return result value
+* REDESIGNED: GuiGrid(), get parameters by reference and return result value
+* REDESIGNED: GuiGrid(), added extra parameter
+* REDESIGNED: GuiListViewEx(), change parameters order
+* REDESIGNED: All controls return result as int value
+* REVIEWED: GuiScrollPanel() to avoid smallish scroll-bars
+* REVIEWED: All examples and specially controls_test_suite
+* RENAMED: gui_file_dialog module to gui_window_file_dialog
+* UPDATED: All styles to include ISO-8859-15 charset (as much as possible)
+*
+* 3.6 (10-May-2023) ADDED: New icon: SAND_TIMER
+* ADDED: GuiLoadStyleFromMemory() (binary only)
+* REVIEWED: GuiScrollBar() horizontal movement key
+* REVIEWED: GuiTextBox() crash on cursor movement
+* REVIEWED: GuiTextBox(), additional inputs support
+* REVIEWED: GuiLabelButton(), avoid text cut
+* REVIEWED: GuiTextInputBox(), password input
+* REVIEWED: Local GetCodepointNext(), aligned with raylib
+* REDESIGNED: GuiSlider*()/GuiScrollBar() to support out-of-bounds
+*
+* 3.5 (20-Apr-2023) ADDED: GuiTabBar(), based on GuiToggle()
+* ADDED: Helper functions to split text in separate lines
+* ADDED: Multiple new icons, useful for code editing tools
+* REMOVED: Unneeded icon editing functions
+* REMOVED: GuiTextBoxMulti(), very limited and broken
+* REMOVED: MeasureTextEx() dependency, logic directly implemented
+* REMOVED: DrawTextEx() dependency, logic directly implemented
+* REVIEWED: GuiScrollBar(), improve mouse-click behaviour
+* REVIEWED: Library header info, more info, better organized
+* REDESIGNED: GuiTextBox() to support cursor movement
+* REDESIGNED: GuiDrawText() to divide drawing by lines
+*
+* 3.2 (22-May-2022) RENAMED: Some enum values, for unification, avoiding prefixes
+* REMOVED: GuiScrollBar(), only internal
+* REDESIGNED: GuiPanel() to support text parameter
+* REDESIGNED: GuiScrollPanel() to support text parameter
+* REDESIGNED: GuiColorPicker() to support text parameter
+* REDESIGNED: GuiColorPanel() to support text parameter
+* REDESIGNED: GuiColorBarAlpha() to support text parameter
+* REDESIGNED: GuiColorBarHue() to support text parameter
+* REDESIGNED: GuiTextInputBox() to support password
+*
+* 3.1 (12-Jan-2022) REVIEWED: Default style for consistency (aligned with rGuiLayout v2.5 tool)
+* REVIEWED: GuiLoadStyle() to support compressed font atlas image data and unload previous textures
+* REVIEWED: External icons usage logic
+* REVIEWED: GuiLine() for centered alignment when including text
+* RENAMED: Multiple controls properties definitions to prepend RAYGUI_
+* RENAMED: RICON_ references to RAYGUI_ICON_ for library consistency
+* Projects updated and multiple tweaks
+*
+* 3.0 (04-Nov-2021) Integrated ricons data to avoid external file
+* REDESIGNED: GuiTextBoxMulti()
+* REMOVED: GuiImageButton*()
+* Multiple minor tweaks and bugs corrected
+*
+* 2.9 (17-Mar-2021) REMOVED: Tooltip API
+* 2.8 (03-May-2020) Centralized rectangles drawing to GuiDrawRectangle()
+* 2.7 (20-Feb-2020) ADDED: Possible tooltips API
+* 2.6 (09-Sep-2019) ADDED: GuiTextInputBox()
+* REDESIGNED: GuiListView*(), GuiDropdownBox(), GuiSlider*(), GuiProgressBar(), GuiMessageBox()
+* REVIEWED: GuiTextBox(), GuiSpinner(), GuiValueBox(), GuiLoadStyle()
+* Replaced property INNER_PADDING by TEXT_PADDING, renamed some properties
+* ADDED: 8 new custom styles ready to use
+* Multiple minor tweaks and bugs corrected
+*
+* 2.5 (28-May-2019) Implemented extended GuiTextBox(), GuiValueBox(), GuiSpinner()
+* 2.3 (29-Apr-2019) ADDED: rIcons auxiliar library and support for it, multiple controls reviewed
+* Refactor all controls drawing mechanism to use control state
+* 2.2 (05-Feb-2019) ADDED: GuiScrollBar(), GuiScrollPanel(), reviewed GuiListView(), removed Gui*Ex() controls
+* 2.1 (26-Dec-2018) REDESIGNED: GuiCheckBox(), GuiComboBox(), GuiDropdownBox(), GuiToggleGroup() > Use combined text string
+* REDESIGNED: Style system (breaking change)
+* 2.0 (08-Nov-2018) ADDED: Support controls guiLock and custom fonts
+* REVIEWED: GuiComboBox(), GuiListView()...
+* 1.9 (09-Oct-2018) REVIEWED: GuiGrid(), GuiTextBox(), GuiTextBoxMulti(), GuiValueBox()...
+* 1.8 (01-May-2018) Lot of rework and redesign to align with rGuiStyler and rGuiLayout
+* 1.5 (21-Jun-2017) Working in an improved styles system
+* 1.4 (15-Jun-2017) Rewritten all GUI functions (removed useless ones)
+* 1.3 (12-Jun-2017) Complete redesign of style system
+* 1.1 (01-Jun-2017) Complete review of the library
+* 1.0 (07-Jun-2016) Converted to header-only by Ramon Santamaria
+* 0.9 (07-Mar-2016) Reviewed and tested by Albert Martos, Ian Eito, Sergio Martinez and Ramon Santamaria
+* 0.8 (27-Aug-2015) Initial release. Implemented by Kevin Gato, Daniel Nicolás and Ramon Santamaria
+*
+* DEPENDENCIES:
+* raylib 5.6-dev - Inputs reading (keyboard/mouse), shapes drawing, font loading and text drawing
+*
+* STANDALONE MODE:
+* By default raygui depends on raylib mostly for the inputs and the drawing functionality but that dependency can be disabled
+* with the config flag RAYGUI_STANDALONE. In that case is up to the user to provide another backend to cover library needs
+*
+* The following functions should be redefined for a custom backend:
+*
+* - Vector2 GetMousePosition(void);
+* - float GetMouseWheelMove(void);
+* - bool IsMouseButtonDown(int button);
+* - bool IsMouseButtonPressed(int button);
+* - bool IsMouseButtonReleased(int button);
+* - bool IsKeyDown(int key);
+* - bool IsKeyPressed(int key);
+* - int GetCharPressed(void); // -- GuiTextBox(), GuiValueBox()
+*
+* - void DrawRectangle(int x, int y, int width, int height, Color color); // -- GuiDrawRectangle()
+* - void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3, Color col4); // -- GuiColorPicker()
+*
+* - Font GetFontDefault(void); // -- GuiLoadStyleDefault()
+* - Font LoadFontEx(const char *fileName, int fontSize, int *codepoints, int codepointCount); // -- GuiLoadStyle()
+* - Texture2D LoadTextureFromImage(Image image); // -- GuiLoadStyle(), required to load texture from embedded font atlas image
+* - void SetShapesTexture(Texture2D tex, Rectangle rec); // -- GuiLoadStyle(), required to set shapes rec to font white rec (optimization)
+* - char *LoadFileText(const char *fileName); // -- GuiLoadStyle(), required to load charset data
+* - void UnloadFileText(char *text); // -- GuiLoadStyle(), required to unload charset data
+* - const char *GetDirectoryPath(const char *filePath); // -- GuiLoadStyle(), required to find charset/font file from text .rgs
+* - int *LoadCodepoints(const char *text, int *count); // -- GuiLoadStyle(), required to load required font codepoints list
+* - void UnloadCodepoints(int *codepoints); // -- GuiLoadStyle(), required to unload codepoints list
+* - unsigned char *DecompressData(const unsigned char *compData, int compDataSize, int *dataSize); // -- GuiLoadStyle()
+*
+* CONTRIBUTORS:
+* Ramon Santamaria: Supervision, review, redesign, update and maintenance
+* Vlad Adrian: Complete rewrite of GuiTextBox() to support extended features (2019)
+* Sergio Martinez: Review, testing (2015) and redesign of multiple controls (2018)
+* Adria Arranz: Testing and implementation of additional controls (2018)
+* Jordi Jorba: Testing and implementation of additional controls (2018)
+* Albert Martos: Review and testing of the library (2015)
+* Ian Eito: Review and testing of the library (2015)
+* Kevin Gato: Initial implementation of basic components (2014)
+* Daniel Nicolas: Initial implementation of basic components (2014)
+*
+*
+* LICENSE: zlib/libpng
+*
+* Copyright (c) 2014-2025 Ramon Santamaria (@raysan5)
+*
+* This software is provided "as-is", without any express or implied warranty. In no event
+* will the authors be held liable for any damages arising from the use of this software.
+*
+* Permission is granted to anyone to use this software for any purpose, including commercial
+* applications, and to alter it and redistribute it freely, subject to the following restrictions:
+*
+* 1. The origin of this software must not be misrepresented; you must not claim that you
+* wrote the original software. If you use this software in a product, an acknowledgment
+* in the product documentation would be appreciated but is not required.
+*
+* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
+* as being the original software.
+*
+* 3. This notice may not be removed or altered from any source distribution.
+*
+**********************************************************************************************/
+
+#ifndef RAYGUI_H
+#define RAYGUI_H
+
+#define RAYGUI_VERSION_MAJOR 4
+#define RAYGUI_VERSION_MINOR 5
+#define RAYGUI_VERSION_PATCH 0
+#define RAYGUI_VERSION "5.0-dev"
+
+#if !defined(RAYGUI_STANDALONE)
+ #include "raylib.h"
+#endif
+
+// Function specifiers in case library is build/used as a shared library (Windows)
+// NOTE: Microsoft specifiers to tell compiler that symbols are imported/exported from a .dll
+#if defined(_WIN32)
+ #if defined(BUILD_LIBTYPE_SHARED)
+ #define RAYGUIAPI __declspec(dllexport) // We are building the library as a Win32 shared library (.dll)
+ #elif defined(USE_LIBTYPE_SHARED)
+ #define RAYGUIAPI __declspec(dllimport) // We are using the library as a Win32 shared library (.dll)
+ #endif
+#endif
+
+// Function specifiers definition
+#ifndef RAYGUIAPI
+ #define RAYGUIAPI // Functions defined as 'extern' by default (implicit specifiers)
+#endif
+
+//----------------------------------------------------------------------------------
+// Defines and Macros
+//----------------------------------------------------------------------------------
+// Simple log system to avoid printf() calls if required
+// NOTE: Avoiding those calls, also avoids const strings memory usage
+#define RAYGUI_SUPPORT_LOG_INFO
+#if defined(RAYGUI_SUPPORT_LOG_INFO)
+ #define RAYGUI_LOG(...) printf(__VA_ARGS__)
+#else
+ #define RAYGUI_LOG(...)
+#endif
+
+//----------------------------------------------------------------------------------
+// Types and Structures Definition
+// NOTE: Some types are required for RAYGUI_STANDALONE usage
+//----------------------------------------------------------------------------------
+#if defined(RAYGUI_STANDALONE)
+ #ifndef __cplusplus
+ // Boolean type
+ #ifndef true
+ typedef enum { false, true } bool;
+ #endif
+ #endif
+
+ // Vector2 type
+ typedef struct Vector2 {
+ float x;
+ float y;
+ } Vector2;
+
+ // Vector3 type // -- ConvertHSVtoRGB(), ConvertRGBtoHSV()
+ typedef struct Vector3 {
+ float x;
+ float y;
+ float z;
+ } Vector3;
+
+ // Color type, RGBA (32bit)
+ typedef struct Color {
+ unsigned char r;
+ unsigned char g;
+ unsigned char b;
+ unsigned char a;
+ } Color;
+
+ // Rectangle type
+ typedef struct Rectangle {
+ float x;
+ float y;
+ float width;
+ float height;
+ } Rectangle;
+
+ // TODO: Texture2D type is very coupled to raylib, required by Font type
+ // It should be redesigned to be provided by user
+ typedef struct Texture {
+ unsigned int id; // OpenGL texture id
+ int width; // Texture base width
+ int height; // Texture base height
+ int mipmaps; // Mipmap levels, 1 by default
+ int format; // Data format (PixelFormat type)
+ } Texture;
+
+ // Texture2D, same as Texture
+ typedef Texture Texture2D;
+
+ // Image, pixel data stored in CPU memory (RAM)
+ typedef struct Image {
+ void *data; // Image raw data
+ int width; // Image base width
+ int height; // Image base height
+ int mipmaps; // Mipmap levels, 1 by default
+ int format; // Data format (PixelFormat type)
+ } Image;
+
+ // GlyphInfo, font characters glyphs info
+ typedef struct GlyphInfo {
+ int value; // Character value (Unicode)
+ int offsetX; // Character offset X when drawing
+ int offsetY; // Character offset Y when drawing
+ int advanceX; // Character advance position X
+ Image image; // Character image data
+ } GlyphInfo;
+
+ // TODO: Font type is very coupled to raylib, mostly required by GuiLoadStyle()
+ // It should be redesigned to be provided by user
+ typedef struct Font {
+ int baseSize; // Base size (default chars height)
+ int glyphCount; // Number of glyph characters
+ int glyphPadding; // Padding around the glyph characters
+ Texture2D texture; // Texture atlas containing the glyphs
+ Rectangle *recs; // Rectangles in texture for the glyphs
+ GlyphInfo *glyphs; // Glyphs info data
+ } Font;
+#endif
+
+// Style property
+// NOTE: Used when exporting style as code for convenience
+typedef struct GuiStyleProp {
+ unsigned short controlId; // Control identifier
+ unsigned short propertyId; // Property identifier
+ int propertyValue; // Property value
+} GuiStyleProp;
+
+/*
+// Controls text style -NOT USED-
+// NOTE: Text style is defined by control
+typedef struct GuiTextStyle {
+ unsigned int size;
+ int charSpacing;
+ int lineSpacing;
+ int alignmentH;
+ int alignmentV;
+ int padding;
+} GuiTextStyle;
+*/
+
+// Gui control state
+typedef enum {
+ STATE_NORMAL = 0,
+ STATE_FOCUSED,
+ STATE_PRESSED,
+ STATE_DISABLED
+} GuiState;
+
+// Gui control text alignment
+typedef enum {
+ TEXT_ALIGN_LEFT = 0,
+ TEXT_ALIGN_CENTER,
+ TEXT_ALIGN_RIGHT
+} GuiTextAlignment;
+
+// Gui control text alignment vertical
+// NOTE: Text vertical position inside the text bounds
+typedef enum {
+ TEXT_ALIGN_TOP = 0,
+ TEXT_ALIGN_MIDDLE,
+ TEXT_ALIGN_BOTTOM
+} GuiTextAlignmentVertical;
+
+// Gui control text wrap mode
+// NOTE: Useful for multiline text
+typedef enum {
+ TEXT_WRAP_NONE = 0,
+ TEXT_WRAP_CHAR,
+ TEXT_WRAP_WORD
+} GuiTextWrapMode;
+
+// Gui controls
+typedef enum {
+ // Default -> populates to all controls when set
+ DEFAULT = 0,
+
+ // Basic controls
+ LABEL, // Used also for: LABELBUTTON
+ BUTTON,
+ TOGGLE, // Used also for: TOGGLEGROUP
+ SLIDER, // Used also for: SLIDERBAR, TOGGLESLIDER
+ PROGRESSBAR,
+ CHECKBOX,
+ COMBOBOX,
+ DROPDOWNBOX,
+ TEXTBOX, // Used also for: TEXTBOXMULTI
+ VALUEBOX,
+ CONTROL11,
+ LISTVIEW,
+ COLORPICKER,
+ SCROLLBAR,
+ STATUSBAR
+} GuiControl;
+
+// Gui base properties for every control
+// NOTE: RAYGUI_MAX_PROPS_BASE properties (by default 16 properties)
+typedef enum {
+ BORDER_COLOR_NORMAL = 0, // Control border color in STATE_NORMAL
+ BASE_COLOR_NORMAL, // Control base color in STATE_NORMAL
+ TEXT_COLOR_NORMAL, // Control text color in STATE_NORMAL
+ BORDER_COLOR_FOCUSED, // Control border color in STATE_FOCUSED
+ BASE_COLOR_FOCUSED, // Control base color in STATE_FOCUSED
+ TEXT_COLOR_FOCUSED, // Control text color in STATE_FOCUSED
+ BORDER_COLOR_PRESSED, // Control border color in STATE_PRESSED
+ BASE_COLOR_PRESSED, // Control base color in STATE_PRESSED
+ TEXT_COLOR_PRESSED, // Control text color in STATE_PRESSED
+ BORDER_COLOR_DISABLED, // Control border color in STATE_DISABLED
+ BASE_COLOR_DISABLED, // Control base color in STATE_DISABLED
+ TEXT_COLOR_DISABLED, // Control text color in STATE_DISABLED
+ BORDER_WIDTH = 12, // Control border size, 0 for no border
+ //TEXT_SIZE, // Control text size (glyphs max height) -> GLOBAL for all controls
+ //TEXT_SPACING, // Control text spacing between glyphs -> GLOBAL for all controls
+ //TEXT_LINE_SPACING, // Control text spacing between lines -> GLOBAL for all controls
+ TEXT_PADDING = 13, // Control text padding, not considering border
+ TEXT_ALIGNMENT = 14, // Control text horizontal alignment inside control text bound (after border and padding)
+ //TEXT_WRAP_MODE // Control text wrap-mode inside text bounds -> GLOBAL for all controls
+} GuiControlProperty;
+
+// TODO: Which text styling properties should be global or per-control?
+// At this moment TEXT_PADDING and TEXT_ALIGNMENT is configured and saved per control while
+// TEXT_SIZE, TEXT_SPACING, TEXT_LINE_SPACING, TEXT_ALIGNMENT_VERTICAL, TEXT_WRAP_MODE are global and
+// should be configured by user as needed while defining the UI layout
+
+// Gui extended properties depend on control
+// NOTE: RAYGUI_MAX_PROPS_EXTENDED properties (by default, max 8 properties)
+//----------------------------------------------------------------------------------
+// DEFAULT extended properties
+// NOTE: Those properties are common to all controls or global
+// WARNING: We only have 8 slots for those properties by default!!! -> New global control: TEXT?
+typedef enum {
+ TEXT_SIZE = 16, // Text size (glyphs max height)
+ TEXT_SPACING, // Text spacing between glyphs
+ LINE_COLOR, // Line control color
+ BACKGROUND_COLOR, // Background color
+ TEXT_LINE_SPACING, // Text spacing between lines
+ TEXT_ALIGNMENT_VERTICAL, // Text vertical alignment inside text bounds (after border and padding)
+ TEXT_WRAP_MODE // Text wrap-mode inside text bounds
+ //TEXT_DECORATION // Text decoration: 0-None, 1-Underline, 2-Line-through, 3-Overline
+ //TEXT_DECORATION_THICK // Text decoration line thickness
+} GuiDefaultProperty;
+
+// Other possible text properties:
+// TEXT_WEIGHT // Normal, Italic, Bold -> Requires specific font change
+// TEXT_INDENT // Text indentation -> Now using TEXT_PADDING...
+
+// Label
+//typedef enum { } GuiLabelProperty;
+
+// Button/Spinner
+//typedef enum { } GuiButtonProperty;
+
+// Toggle/ToggleGroup
+typedef enum {
+ GROUP_PADDING = 16, // ToggleGroup separation between toggles
+} GuiToggleProperty;
+
+// Slider/SliderBar
+typedef enum {
+ SLIDER_WIDTH = 16, // Slider size of internal bar
+ SLIDER_PADDING // Slider/SliderBar internal bar padding
+} GuiSliderProperty;
+
+// ProgressBar
+typedef enum {
+ PROGRESS_PADDING = 16, // ProgressBar internal padding
+} GuiProgressBarProperty;
+
+// ScrollBar
+typedef enum {
+ ARROWS_SIZE = 16, // ScrollBar arrows size
+ ARROWS_VISIBLE, // ScrollBar arrows visible
+ SCROLL_SLIDER_PADDING, // ScrollBar slider internal padding
+ SCROLL_SLIDER_SIZE, // ScrollBar slider size
+ SCROLL_PADDING, // ScrollBar scroll padding from arrows
+ SCROLL_SPEED, // ScrollBar scrolling speed
+} GuiScrollBarProperty;
+
+// CheckBox
+typedef enum {
+ CHECK_PADDING = 16 // CheckBox internal check padding
+} GuiCheckBoxProperty;
+
+// ComboBox
+typedef enum {
+ COMBO_BUTTON_WIDTH = 16, // ComboBox right button width
+ COMBO_BUTTON_SPACING // ComboBox button separation
+} GuiComboBoxProperty;
+
+// DropdownBox
+typedef enum {
+ ARROW_PADDING = 16, // DropdownBox arrow separation from border and items
+ DROPDOWN_ITEMS_SPACING, // DropdownBox items separation
+ DROPDOWN_ARROW_HIDDEN, // DropdownBox arrow hidden
+ DROPDOWN_ROLL_UP // DropdownBox roll up flag (default rolls down)
+} GuiDropdownBoxProperty;
+
+// TextBox/TextBoxMulti/ValueBox/Spinner
+typedef enum {
+ TEXT_READONLY = 16, // TextBox in read-only mode: 0-text editable, 1-text no-editable
+} GuiTextBoxProperty;
+
+// ValueBox/Spinner
+typedef enum {
+ SPINNER_BUTTON_WIDTH = 16, // Spinner left/right buttons width
+ SPINNER_BUTTON_SPACING, // Spinner buttons separation
+} GuiValueBoxProperty;
+
+// Control11
+//typedef enum { } GuiControl11Property;
+
+// ListView
+typedef enum {
+ LIST_ITEMS_HEIGHT = 16, // ListView items height
+ LIST_ITEMS_SPACING, // ListView items separation
+ SCROLLBAR_WIDTH, // ListView scrollbar size (usually width)
+ SCROLLBAR_SIDE, // ListView scrollbar side (0-SCROLLBAR_LEFT_SIDE, 1-SCROLLBAR_RIGHT_SIDE)
+ LIST_ITEMS_BORDER_NORMAL, // ListView items border enabled in normal state
+ LIST_ITEMS_BORDER_WIDTH // ListView items border width
+} GuiListViewProperty;
+
+// ColorPicker
+typedef enum {
+ COLOR_SELECTOR_SIZE = 16,
+ HUEBAR_WIDTH, // ColorPicker right hue bar width
+ HUEBAR_PADDING, // ColorPicker right hue bar separation from panel
+ HUEBAR_SELECTOR_HEIGHT, // ColorPicker right hue bar selector height
+ HUEBAR_SELECTOR_OVERFLOW // ColorPicker right hue bar selector overflow
+} GuiColorPickerProperty;
+
+#define SCROLLBAR_LEFT_SIDE 0
+#define SCROLLBAR_RIGHT_SIDE 1
+
+//----------------------------------------------------------------------------------
+// Global Variables Definition
+//----------------------------------------------------------------------------------
+// ...
+
+//----------------------------------------------------------------------------------
+// Module Functions Declaration
+//----------------------------------------------------------------------------------
+
+#if defined(__cplusplus)
+extern "C" { // Prevents name mangling of functions
+#endif
+
+// Global gui state control functions
+RAYGUIAPI void GuiEnable(void); // Enable gui controls (global state)
+RAYGUIAPI void GuiDisable(void); // Disable gui controls (global state)
+RAYGUIAPI void GuiLock(void); // Lock gui controls (global state)
+RAYGUIAPI void GuiUnlock(void); // Unlock gui controls (global state)
+RAYGUIAPI bool GuiIsLocked(void); // Check if gui is locked (global state)
+RAYGUIAPI void GuiSetAlpha(float alpha); // Set gui controls alpha (global state), alpha goes from 0.0f to 1.0f
+RAYGUIAPI void GuiSetState(int state); // Set gui state (global state)
+RAYGUIAPI int GuiGetState(void); // Get gui state (global state)
+
+// Font set/get functions
+RAYGUIAPI void GuiSetFont(Font font); // Set gui custom font (global state)
+RAYGUIAPI Font GuiGetFont(void); // Get gui custom font (global state)
+
+// Style set/get functions
+RAYGUIAPI void GuiSetStyle(int control, int property, int value); // Set one style property
+RAYGUIAPI int GuiGetStyle(int control, int property); // Get one style property
+
+// Styles loading functions
+RAYGUIAPI void GuiLoadStyle(const char *fileName); // Load style file over global style variable (.rgs)
+RAYGUIAPI void GuiLoadStyleDefault(void); // Load style default over global style
+
+// Tooltips management functions
+RAYGUIAPI void GuiEnableTooltip(void); // Enable gui tooltips (global state)
+RAYGUIAPI void GuiDisableTooltip(void); // Disable gui tooltips (global state)
+RAYGUIAPI void GuiSetTooltip(const char *tooltip); // Set tooltip string
+
+// Icons functionality
+RAYGUIAPI const char *GuiIconText(int iconId, const char *text); // Get text with icon id prepended (if supported)
+#if !defined(RAYGUI_NO_ICONS)
+RAYGUIAPI void GuiSetIconScale(int scale); // Set default icon drawing size
+RAYGUIAPI unsigned int *GuiGetIcons(void); // Get raygui icons data pointer
+RAYGUIAPI char **GuiLoadIcons(const char *fileName, bool loadIconsName); // Load raygui icons file (.rgi) into internal icons data
+RAYGUIAPI void GuiDrawIcon(int iconId, int posX, int posY, int pixelSize, Color color); // Draw icon using pixel size at specified position
+#endif
+
+// Utility functions
+RAYGUIAPI int GuiGetTextWidth(const char *text); // Get text width considering gui style and icon size (if required)
+
+// Controls
+//----------------------------------------------------------------------------------------------------------
+// Container/separator controls, useful for controls organization
+RAYGUIAPI int GuiWindowBox(Rectangle bounds, const char *title); // Window Box control, shows a window that can be closed
+RAYGUIAPI int GuiGroupBox(Rectangle bounds, const char *text); // Group Box control with text name
+RAYGUIAPI int GuiLine(Rectangle bounds, const char *text); // Line separator control, could contain text
+RAYGUIAPI int GuiPanel(Rectangle bounds, const char *text); // Panel control, useful to group controls
+RAYGUIAPI int GuiTabBar(Rectangle bounds, const char **text, int count, int *active); // Tab Bar control, returns TAB to be closed or -1
+RAYGUIAPI int GuiScrollPanel(Rectangle bounds, const char *text, Rectangle content, Vector2 *scroll, Rectangle *view); // Scroll Panel control
+
+// Basic controls set
+RAYGUIAPI int GuiLabel(Rectangle bounds, const char *text); // Label control
+RAYGUIAPI int GuiButton(Rectangle bounds, const char *text); // Button control, returns true when clicked
+RAYGUIAPI int GuiLabelButton(Rectangle bounds, const char *text); // Label button control, returns true when clicked
+RAYGUIAPI int GuiToggle(Rectangle bounds, const char *text, bool *active); // Toggle Button control
+RAYGUIAPI int GuiToggleGroup(Rectangle bounds, const char *text, int *active); // Toggle Group control
+RAYGUIAPI int GuiToggleSlider(Rectangle bounds, const char *text, int *active); // Toggle Slider control
+RAYGUIAPI int GuiCheckBox(Rectangle bounds, const char *text, bool *checked); // Check Box control, returns true when active
+RAYGUIAPI int GuiComboBox(Rectangle bounds, const char *text, int *active); // Combo Box control
+
+RAYGUIAPI int GuiDropdownBox(Rectangle bounds, const char *text, int *active, bool editMode); // Dropdown Box control
+RAYGUIAPI int GuiSpinner(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, bool editMode); // Spinner control
+RAYGUIAPI int GuiValueBox(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, bool editMode); // Value Box control, updates input text with numbers
+RAYGUIAPI int GuiValueBoxFloat(Rectangle bounds, const char *text, char *textValue, float *value, bool editMode); // Value box control for float values
+RAYGUIAPI int GuiTextBox(Rectangle bounds, char *text, int textSize, bool editMode); // Text Box control, updates input text
+
+RAYGUIAPI int GuiSlider(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue); // Slider control
+RAYGUIAPI int GuiSliderBar(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue); // Slider Bar control
+RAYGUIAPI int GuiProgressBar(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue); // Progress Bar control
+RAYGUIAPI int GuiStatusBar(Rectangle bounds, const char *text); // Status Bar control, shows info text
+RAYGUIAPI int GuiDummyRec(Rectangle bounds, const char *text); // Dummy control for placeholders
+RAYGUIAPI int GuiGrid(Rectangle bounds, const char *text, float spacing, int subdivs, Vector2 *mouseCell); // Grid control
+
+// Advance controls set
+RAYGUIAPI int GuiListView(Rectangle bounds, const char *text, int *scrollIndex, int *active); // List View control
+RAYGUIAPI int GuiListViewEx(Rectangle bounds, const char **text, int count, int *scrollIndex, int *active, int *focus); // List View with extended parameters
+RAYGUIAPI int GuiMessageBox(Rectangle bounds, const char *title, const char *message, const char *buttons); // Message Box control, displays a message
+RAYGUIAPI int GuiTextInputBox(Rectangle bounds, const char *title, const char *message, const char *buttons, char *text, int textMaxSize, bool *secretViewActive); // Text Input Box control, ask for text, supports secret
+RAYGUIAPI int GuiColorPicker(Rectangle bounds, const char *text, Color *color); // Color Picker control (multiple color controls)
+RAYGUIAPI int GuiColorPanel(Rectangle bounds, const char *text, Color *color); // Color Panel control
+RAYGUIAPI int GuiColorBarAlpha(Rectangle bounds, const char *text, float *alpha); // Color Bar Alpha control
+RAYGUIAPI int GuiColorBarHue(Rectangle bounds, const char *text, float *value); // Color Bar Hue control
+RAYGUIAPI int GuiColorPickerHSV(Rectangle bounds, const char *text, Vector3 *colorHsv); // Color Picker control that avoids conversion to RGB on each call (multiple color controls)
+RAYGUIAPI int GuiColorPanelHSV(Rectangle bounds, const char *text, Vector3 *colorHsv); // Color Panel control that updates Hue-Saturation-Value color value, used by GuiColorPickerHSV()
+//----------------------------------------------------------------------------------------------------------
+
+#if !defined(RAYGUI_NO_ICONS)
+
+#if !defined(RAYGUI_CUSTOM_ICONS)
+//----------------------------------------------------------------------------------
+// Icons enumeration
+//----------------------------------------------------------------------------------
+typedef enum {
+ ICON_NONE = 0,
+ ICON_FOLDER_FILE_OPEN = 1,
+ ICON_FILE_SAVE_CLASSIC = 2,
+ ICON_FOLDER_OPEN = 3,
+ ICON_FOLDER_SAVE = 4,
+ ICON_FILE_OPEN = 5,
+ ICON_FILE_SAVE = 6,
+ ICON_FILE_EXPORT = 7,
+ ICON_FILE_ADD = 8,
+ ICON_FILE_DELETE = 9,
+ ICON_FILETYPE_TEXT = 10,
+ ICON_FILETYPE_AUDIO = 11,
+ ICON_FILETYPE_IMAGE = 12,
+ ICON_FILETYPE_PLAY = 13,
+ ICON_FILETYPE_VIDEO = 14,
+ ICON_FILETYPE_INFO = 15,
+ ICON_FILE_COPY = 16,
+ ICON_FILE_CUT = 17,
+ ICON_FILE_PASTE = 18,
+ ICON_CURSOR_HAND = 19,
+ ICON_CURSOR_POINTER = 20,
+ ICON_CURSOR_CLASSIC = 21,
+ ICON_PENCIL = 22,
+ ICON_PENCIL_BIG = 23,
+ ICON_BRUSH_CLASSIC = 24,
+ ICON_BRUSH_PAINTER = 25,
+ ICON_WATER_DROP = 26,
+ ICON_COLOR_PICKER = 27,
+ ICON_RUBBER = 28,
+ ICON_COLOR_BUCKET = 29,
+ ICON_TEXT_T = 30,
+ ICON_TEXT_A = 31,
+ ICON_SCALE = 32,
+ ICON_RESIZE = 33,
+ ICON_FILTER_POINT = 34,
+ ICON_FILTER_BILINEAR = 35,
+ ICON_CROP = 36,
+ ICON_CROP_ALPHA = 37,
+ ICON_SQUARE_TOGGLE = 38,
+ ICON_SYMMETRY = 39,
+ ICON_SYMMETRY_HORIZONTAL = 40,
+ ICON_SYMMETRY_VERTICAL = 41,
+ ICON_LENS = 42,
+ ICON_LENS_BIG = 43,
+ ICON_EYE_ON = 44,
+ ICON_EYE_OFF = 45,
+ ICON_FILTER_TOP = 46,
+ ICON_FILTER = 47,
+ ICON_TARGET_POINT = 48,
+ ICON_TARGET_SMALL = 49,
+ ICON_TARGET_BIG = 50,
+ ICON_TARGET_MOVE = 51,
+ ICON_CURSOR_MOVE = 52,
+ ICON_CURSOR_SCALE = 53,
+ ICON_CURSOR_SCALE_RIGHT = 54,
+ ICON_CURSOR_SCALE_LEFT = 55,
+ ICON_UNDO = 56,
+ ICON_REDO = 57,
+ ICON_REREDO = 58,
+ ICON_MUTATE = 59,
+ ICON_ROTATE = 60,
+ ICON_REPEAT = 61,
+ ICON_SHUFFLE = 62,
+ ICON_EMPTYBOX = 63,
+ ICON_TARGET = 64,
+ ICON_TARGET_SMALL_FILL = 65,
+ ICON_TARGET_BIG_FILL = 66,
+ ICON_TARGET_MOVE_FILL = 67,
+ ICON_CURSOR_MOVE_FILL = 68,
+ ICON_CURSOR_SCALE_FILL = 69,
+ ICON_CURSOR_SCALE_RIGHT_FILL = 70,
+ ICON_CURSOR_SCALE_LEFT_FILL = 71,
+ ICON_UNDO_FILL = 72,
+ ICON_REDO_FILL = 73,
+ ICON_REREDO_FILL = 74,
+ ICON_MUTATE_FILL = 75,
+ ICON_ROTATE_FILL = 76,
+ ICON_REPEAT_FILL = 77,
+ ICON_SHUFFLE_FILL = 78,
+ ICON_EMPTYBOX_SMALL = 79,
+ ICON_BOX = 80,
+ ICON_BOX_TOP = 81,
+ ICON_BOX_TOP_RIGHT = 82,
+ ICON_BOX_RIGHT = 83,
+ ICON_BOX_BOTTOM_RIGHT = 84,
+ ICON_BOX_BOTTOM = 85,
+ ICON_BOX_BOTTOM_LEFT = 86,
+ ICON_BOX_LEFT = 87,
+ ICON_BOX_TOP_LEFT = 88,
+ ICON_BOX_CENTER = 89,
+ ICON_BOX_CIRCLE_MASK = 90,
+ ICON_POT = 91,
+ ICON_ALPHA_MULTIPLY = 92,
+ ICON_ALPHA_CLEAR = 93,
+ ICON_DITHERING = 94,
+ ICON_MIPMAPS = 95,
+ ICON_BOX_GRID = 96,
+ ICON_GRID = 97,
+ ICON_BOX_CORNERS_SMALL = 98,
+ ICON_BOX_CORNERS_BIG = 99,
+ ICON_FOUR_BOXES = 100,
+ ICON_GRID_FILL = 101,
+ ICON_BOX_MULTISIZE = 102,
+ ICON_ZOOM_SMALL = 103,
+ ICON_ZOOM_MEDIUM = 104,
+ ICON_ZOOM_BIG = 105,
+ ICON_ZOOM_ALL = 106,
+ ICON_ZOOM_CENTER = 107,
+ ICON_BOX_DOTS_SMALL = 108,
+ ICON_BOX_DOTS_BIG = 109,
+ ICON_BOX_CONCENTRIC = 110,
+ ICON_BOX_GRID_BIG = 111,
+ ICON_OK_TICK = 112,
+ ICON_CROSS = 113,
+ ICON_ARROW_LEFT = 114,
+ ICON_ARROW_RIGHT = 115,
+ ICON_ARROW_DOWN = 116,
+ ICON_ARROW_UP = 117,
+ ICON_ARROW_LEFT_FILL = 118,
+ ICON_ARROW_RIGHT_FILL = 119,
+ ICON_ARROW_DOWN_FILL = 120,
+ ICON_ARROW_UP_FILL = 121,
+ ICON_AUDIO = 122,
+ ICON_FX = 123,
+ ICON_WAVE = 124,
+ ICON_WAVE_SINUS = 125,
+ ICON_WAVE_SQUARE = 126,
+ ICON_WAVE_TRIANGULAR = 127,
+ ICON_CROSS_SMALL = 128,
+ ICON_PLAYER_PREVIOUS = 129,
+ ICON_PLAYER_PLAY_BACK = 130,
+ ICON_PLAYER_PLAY = 131,
+ ICON_PLAYER_PAUSE = 132,
+ ICON_PLAYER_STOP = 133,
+ ICON_PLAYER_NEXT = 134,
+ ICON_PLAYER_RECORD = 135,
+ ICON_MAGNET = 136,
+ ICON_LOCK_CLOSE = 137,
+ ICON_LOCK_OPEN = 138,
+ ICON_CLOCK = 139,
+ ICON_TOOLS = 140,
+ ICON_GEAR = 141,
+ ICON_GEAR_BIG = 142,
+ ICON_BIN = 143,
+ ICON_HAND_POINTER = 144,
+ ICON_LASER = 145,
+ ICON_COIN = 146,
+ ICON_EXPLOSION = 147,
+ ICON_1UP = 148,
+ ICON_PLAYER = 149,
+ ICON_PLAYER_JUMP = 150,
+ ICON_KEY = 151,
+ ICON_DEMON = 152,
+ ICON_TEXT_POPUP = 153,
+ ICON_GEAR_EX = 154,
+ ICON_CRACK = 155,
+ ICON_CRACK_POINTS = 156,
+ ICON_STAR = 157,
+ ICON_DOOR = 158,
+ ICON_EXIT = 159,
+ ICON_MODE_2D = 160,
+ ICON_MODE_3D = 161,
+ ICON_CUBE = 162,
+ ICON_CUBE_FACE_TOP = 163,
+ ICON_CUBE_FACE_LEFT = 164,
+ ICON_CUBE_FACE_FRONT = 165,
+ ICON_CUBE_FACE_BOTTOM = 166,
+ ICON_CUBE_FACE_RIGHT = 167,
+ ICON_CUBE_FACE_BACK = 168,
+ ICON_CAMERA = 169,
+ ICON_SPECIAL = 170,
+ ICON_LINK_NET = 171,
+ ICON_LINK_BOXES = 172,
+ ICON_LINK_MULTI = 173,
+ ICON_LINK = 174,
+ ICON_LINK_BROKE = 175,
+ ICON_TEXT_NOTES = 176,
+ ICON_NOTEBOOK = 177,
+ ICON_SUITCASE = 178,
+ ICON_SUITCASE_ZIP = 179,
+ ICON_MAILBOX = 180,
+ ICON_MONITOR = 181,
+ ICON_PRINTER = 182,
+ ICON_PHOTO_CAMERA = 183,
+ ICON_PHOTO_CAMERA_FLASH = 184,
+ ICON_HOUSE = 185,
+ ICON_HEART = 186,
+ ICON_CORNER = 187,
+ ICON_VERTICAL_BARS = 188,
+ ICON_VERTICAL_BARS_FILL = 189,
+ ICON_LIFE_BARS = 190,
+ ICON_INFO = 191,
+ ICON_CROSSLINE = 192,
+ ICON_HELP = 193,
+ ICON_FILETYPE_ALPHA = 194,
+ ICON_FILETYPE_HOME = 195,
+ ICON_LAYERS_VISIBLE = 196,
+ ICON_LAYERS = 197,
+ ICON_WINDOW = 198,
+ ICON_HIDPI = 199,
+ ICON_FILETYPE_BINARY = 200,
+ ICON_HEX = 201,
+ ICON_SHIELD = 202,
+ ICON_FILE_NEW = 203,
+ ICON_FOLDER_ADD = 204,
+ ICON_ALARM = 205,
+ ICON_CPU = 206,
+ ICON_ROM = 207,
+ ICON_STEP_OVER = 208,
+ ICON_STEP_INTO = 209,
+ ICON_STEP_OUT = 210,
+ ICON_RESTART = 211,
+ ICON_BREAKPOINT_ON = 212,
+ ICON_BREAKPOINT_OFF = 213,
+ ICON_BURGER_MENU = 214,
+ ICON_CASE_SENSITIVE = 215,
+ ICON_REG_EXP = 216,
+ ICON_FOLDER = 217,
+ ICON_FILE = 218,
+ ICON_SAND_TIMER = 219,
+ ICON_WARNING = 220,
+ ICON_HELP_BOX = 221,
+ ICON_INFO_BOX = 222,
+ ICON_PRIORITY = 223,
+ ICON_LAYERS_ISO = 224,
+ ICON_LAYERS2 = 225,
+ ICON_MLAYERS = 226,
+ ICON_MAPS = 227,
+ ICON_HOT = 228,
+ ICON_LABEL = 229,
+ ICON_NAME_ID = 230,
+ ICON_SLICING = 231,
+ ICON_MANUAL_CONTROL = 232,
+ ICON_COLLISION = 233,
+ ICON_CIRCLE_ADD = 234,
+ ICON_CIRCLE_ADD_FILL = 235,
+ ICON_CIRCLE_WARNING = 236,
+ ICON_CIRCLE_WARNING_FILL = 237,
+ ICON_BOX_MORE = 238,
+ ICON_BOX_MORE_FILL = 239,
+ ICON_BOX_MINUS = 240,
+ ICON_BOX_MINUS_FILL = 241,
+ ICON_UNION = 242,
+ ICON_INTERSECTION = 243,
+ ICON_DIFFERENCE = 244,
+ ICON_SPHERE = 245,
+ ICON_CYLINDER = 246,
+ ICON_CONE = 247,
+ ICON_ELLIPSOID = 248,
+ ICON_CAPSULE = 249,
+ ICON_250 = 250,
+ ICON_251 = 251,
+ ICON_252 = 252,
+ ICON_253 = 253,
+ ICON_254 = 254,
+ ICON_255 = 255
+} GuiIconName;
+#endif
+
+#endif
+
+#if defined(__cplusplus)
+} // Prevents name mangling of functions
+#endif
+
+#endif // RAYGUI_H
+
+/***********************************************************************************
+*
+* RAYGUI IMPLEMENTATION
+*
+************************************************************************************/
+
+#if defined(RAYGUI_IMPLEMENTATION)
+
+#include // required for: isspace() [GuiTextBox()]
+#include // Required for: FILE, fopen(), fclose(), fprintf(), feof(), fscanf(), snprintf(), vsprintf() [GuiLoadStyle(), GuiLoadIcons()]
+#include // Required for: strlen() [GuiTextBox(), GuiValueBox()], memset(), memcpy()
+#include // Required for: va_list, va_start(), vfprintf(), va_end() [TextFormat()]
+#include // Required for: roundf() [GuiColorPicker()]
+
+// Allow custom memory allocators
+#if defined(RAYGUI_MALLOC) || defined(RAYGUI_CALLOC) || defined(RAYGUI_FREE)
+ #if !defined(RAYGUI_MALLOC) || !defined(RAYGUI_CALLOC) || !defined(RAYGUI_FREE)
+ #error "RAYGUI: if RAYGUI_MALLOC, RAYGUI_CALLOC, or RAYGUI_FREE is customized, all three must be customized"
+ #endif
+#else
+ #include // Required for: malloc(), calloc(), free() [GuiLoadStyle(), GuiLoadIcons()]
+
+ #define RAYGUI_MALLOC(sz) malloc(sz)
+ #define RAYGUI_CALLOC(n,sz) calloc(n,sz)
+ #define RAYGUI_FREE(p) free(p)
+#endif
+
+#ifdef __cplusplus
+ #define RAYGUI_CLITERAL(name) name
+#else
+ #define RAYGUI_CLITERAL(name) (name)
+#endif
+
+// Check if two rectangles are equal, used to validate a slider bounds as an id
+#ifndef CHECK_BOUNDS_ID
+ #define CHECK_BOUNDS_ID(src, dst) (((int)src.x == (int)dst.x) && ((int)src.y == (int)dst.y) && ((int)src.width == (int)dst.width) && ((int)src.height == (int)dst.height))
+#endif
+
+#if !defined(RAYGUI_NO_ICONS) && !defined(RAYGUI_CUSTOM_ICONS)
+
+// Embedded icons, no external file provided
+#define RAYGUI_ICON_SIZE 16 // Size of icons in pixels (squared)
+#define RAYGUI_ICON_MAX_ICONS 256 // Maximum number of icons
+#define RAYGUI_ICON_MAX_NAME_LENGTH 32 // Maximum length of icon name id
+
+// Icons data is defined by bit array (every bit represents one pixel)
+// Those arrays are stored as unsigned int data arrays, so,
+// every array element defines 32 pixels (bits) of information
+// One icon is defined by 8 int, (8 int*32 bit = 256 bit = 16*16 pixels)
+// NOTE: Number of elemens depend on RAYGUI_ICON_SIZE (by default 16x16 pixels)
+#define RAYGUI_ICON_DATA_ELEMENTS (RAYGUI_ICON_SIZE*RAYGUI_ICON_SIZE/32)
+
+//----------------------------------------------------------------------------------
+// Icons data for all gui possible icons (allocated on data segment by default)
+//
+// NOTE 1: Every icon is codified in binary form, using 1 bit per pixel, so,
+// every 16x16 icon requires 8 integers (16*16/32) to be stored
+//
+// NOTE 2: A different icon set could be loaded over this array using GuiLoadIcons(),
+// but loaded icons set must be same RAYGUI_ICON_SIZE and no more than RAYGUI_ICON_MAX_ICONS
+//
+// guiIcons size is by default: 256*(16*16/32) = 2048*4 = 8192 bytes = 8 KB
+//----------------------------------------------------------------------------------
+static unsigned int guiIcons[RAYGUI_ICON_MAX_ICONS*RAYGUI_ICON_DATA_ELEMENTS] = {
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_NONE
+ 0x3ff80000, 0x2f082008, 0x2042207e, 0x40027fc2, 0x40024002, 0x40024002, 0x40024002, 0x00007ffe, // ICON_FOLDER_FILE_OPEN
+ 0x3ffe0000, 0x44226422, 0x400247e2, 0x5ffa4002, 0x57ea500a, 0x500a500a, 0x40025ffa, 0x00007ffe, // ICON_FILE_SAVE_CLASSIC
+ 0x00000000, 0x0042007e, 0x40027fc2, 0x40024002, 0x41024002, 0x44424282, 0x793e4102, 0x00000100, // ICON_FOLDER_OPEN
+ 0x00000000, 0x0042007e, 0x40027fc2, 0x40024002, 0x41024102, 0x44424102, 0x793e4282, 0x00000000, // ICON_FOLDER_SAVE
+ 0x3ff00000, 0x201c2010, 0x20042004, 0x21042004, 0x24442284, 0x21042104, 0x20042104, 0x00003ffc, // ICON_FILE_OPEN
+ 0x3ff00000, 0x201c2010, 0x20042004, 0x21042004, 0x21042104, 0x22842444, 0x20042104, 0x00003ffc, // ICON_FILE_SAVE
+ 0x3ff00000, 0x201c2010, 0x00042004, 0x20041004, 0x20844784, 0x00841384, 0x20042784, 0x00003ffc, // ICON_FILE_EXPORT
+ 0x3ff00000, 0x201c2010, 0x20042004, 0x20042004, 0x22042204, 0x22042f84, 0x20042204, 0x00003ffc, // ICON_FILE_ADD
+ 0x3ff00000, 0x201c2010, 0x20042004, 0x20042004, 0x25042884, 0x25042204, 0x20042884, 0x00003ffc, // ICON_FILE_DELETE
+ 0x3ff00000, 0x201c2010, 0x20042004, 0x20042ff4, 0x20042ff4, 0x20042ff4, 0x20042004, 0x00003ffc, // ICON_FILETYPE_TEXT
+ 0x3ff00000, 0x201c2010, 0x27042004, 0x244424c4, 0x26442444, 0x20642664, 0x20042004, 0x00003ffc, // ICON_FILETYPE_AUDIO
+ 0x3ff00000, 0x201c2010, 0x26042604, 0x20042004, 0x35442884, 0x2414222c, 0x20042004, 0x00003ffc, // ICON_FILETYPE_IMAGE
+ 0x3ff00000, 0x201c2010, 0x20c42004, 0x22442144, 0x22442444, 0x20c42144, 0x20042004, 0x00003ffc, // ICON_FILETYPE_PLAY
+ 0x3ff00000, 0x3ffc2ff0, 0x3f3c2ff4, 0x3dbc2eb4, 0x3dbc2bb4, 0x3f3c2eb4, 0x3ffc2ff4, 0x00002ff4, // ICON_FILETYPE_VIDEO
+ 0x3ff00000, 0x201c2010, 0x21842184, 0x21842004, 0x21842184, 0x21842184, 0x20042184, 0x00003ffc, // ICON_FILETYPE_INFO
+ 0x0ff00000, 0x381c0810, 0x28042804, 0x28042804, 0x28042804, 0x28042804, 0x20102ffc, 0x00003ff0, // ICON_FILE_COPY
+ 0x00000000, 0x701c0000, 0x079c1e14, 0x55a000f0, 0x079c00f0, 0x701c1e14, 0x00000000, 0x00000000, // ICON_FILE_CUT
+ 0x01c00000, 0x13e41bec, 0x3f841004, 0x204420c4, 0x20442044, 0x20442044, 0x207c2044, 0x00003fc0, // ICON_FILE_PASTE
+ 0x00000000, 0x3aa00fe0, 0x2abc2aa0, 0x2aa42aa4, 0x20042aa4, 0x20042004, 0x3ffc2004, 0x00000000, // ICON_CURSOR_HAND
+ 0x00000000, 0x003c000c, 0x030800c8, 0x30100c10, 0x10202020, 0x04400840, 0x01800280, 0x00000000, // ICON_CURSOR_POINTER
+ 0x00000000, 0x00180000, 0x01f00078, 0x03e007f0, 0x07c003e0, 0x04000e40, 0x00000000, 0x00000000, // ICON_CURSOR_CLASSIC
+ 0x00000000, 0x04000000, 0x11000a00, 0x04400a80, 0x01100220, 0x00580088, 0x00000038, 0x00000000, // ICON_PENCIL
+ 0x04000000, 0x15000a00, 0x50402880, 0x14102820, 0x05040a08, 0x015c028c, 0x007c00bc, 0x00000000, // ICON_PENCIL_BIG
+ 0x01c00000, 0x01400140, 0x01400140, 0x0ff80140, 0x0ff80808, 0x0aa80808, 0x0aa80aa8, 0x00000ff8, // ICON_BRUSH_CLASSIC
+ 0x1ffc0000, 0x5ffc7ffe, 0x40004000, 0x00807f80, 0x01c001c0, 0x01c001c0, 0x01c001c0, 0x00000080, // ICON_BRUSH_PAINTER
+ 0x00000000, 0x00800000, 0x01c00080, 0x03e001c0, 0x07f003e0, 0x036006f0, 0x000001c0, 0x00000000, // ICON_WATER_DROP
+ 0x00000000, 0x3e003800, 0x1f803f80, 0x0c201e40, 0x02080c10, 0x00840104, 0x00380044, 0x00000000, // ICON_COLOR_PICKER
+ 0x00000000, 0x07800300, 0x1fe00fc0, 0x3f883fd0, 0x0e021f04, 0x02040402, 0x00f00108, 0x00000000, // ICON_RUBBER
+ 0x00c00000, 0x02800140, 0x08200440, 0x20081010, 0x2ffe3004, 0x03f807fc, 0x00e001f0, 0x00000040, // ICON_COLOR_BUCKET
+ 0x00000000, 0x21843ffc, 0x01800180, 0x01800180, 0x01800180, 0x01800180, 0x03c00180, 0x00000000, // ICON_TEXT_T
+ 0x00800000, 0x01400180, 0x06200340, 0x0c100620, 0x1ff80c10, 0x380c1808, 0x70067004, 0x0000f80f, // ICON_TEXT_A
+ 0x78000000, 0x50004000, 0x00004800, 0x03c003c0, 0x03c003c0, 0x00100000, 0x0002000a, 0x0000000e, // ICON_SCALE
+ 0x75560000, 0x5e004002, 0x54001002, 0x41001202, 0x408200fe, 0x40820082, 0x40820082, 0x00006afe, // ICON_RESIZE
+ 0x00000000, 0x3f003f00, 0x3f003f00, 0x3f003f00, 0x00400080, 0x001c0020, 0x001c001c, 0x00000000, // ICON_FILTER_POINT
+ 0x6d800000, 0x00004080, 0x40804080, 0x40800000, 0x00406d80, 0x001c0020, 0x001c001c, 0x00000000, // ICON_FILTER_BILINEAR
+ 0x40080000, 0x1ffe2008, 0x14081008, 0x11081208, 0x10481088, 0x10081028, 0x10047ff8, 0x00001002, // ICON_CROP
+ 0x00100000, 0x3ffc0010, 0x2ab03550, 0x22b02550, 0x20b02150, 0x20302050, 0x2000fff0, 0x00002000, // ICON_CROP_ALPHA
+ 0x40000000, 0x1ff82000, 0x04082808, 0x01082208, 0x00482088, 0x00182028, 0x35542008, 0x00000002, // ICON_SQUARE_TOGGLE
+ 0x00000000, 0x02800280, 0x06c006c0, 0x0ea00ee0, 0x1e901eb0, 0x3e883e98, 0x7efc7e8c, 0x00000000, // ICON_SYMMETRY
+ 0x01000000, 0x05600100, 0x1d480d50, 0x7d423d44, 0x3d447d42, 0x0d501d48, 0x01000560, 0x00000100, // ICON_SYMMETRY_HORIZONTAL
+ 0x01800000, 0x04200240, 0x10080810, 0x00001ff8, 0x00007ffe, 0x0ff01ff8, 0x03c007e0, 0x00000180, // ICON_SYMMETRY_VERTICAL
+ 0x00000000, 0x010800f0, 0x02040204, 0x02040204, 0x07f00308, 0x1c000e00, 0x30003800, 0x00000000, // ICON_LENS
+ 0x00000000, 0x061803f0, 0x08240c0c, 0x08040814, 0x0c0c0804, 0x23f01618, 0x18002400, 0x00000000, // ICON_LENS_BIG
+ 0x00000000, 0x00000000, 0x1c7007c0, 0x638e3398, 0x1c703398, 0x000007c0, 0x00000000, 0x00000000, // ICON_EYE_ON
+ 0x00000000, 0x10002000, 0x04700fc0, 0x610e3218, 0x1c703098, 0x001007a0, 0x00000008, 0x00000000, // ICON_EYE_OFF
+ 0x00000000, 0x00007ffc, 0x40047ffc, 0x10102008, 0x04400820, 0x02800280, 0x02800280, 0x00000100, // ICON_FILTER_TOP
+ 0x00000000, 0x40027ffe, 0x10082004, 0x04200810, 0x02400240, 0x02400240, 0x01400240, 0x000000c0, // ICON_FILTER
+ 0x00800000, 0x00800080, 0x00000080, 0x3c9e0000, 0x00000000, 0x00800080, 0x00800080, 0x00000000, // ICON_TARGET_POINT
+ 0x00800000, 0x00800080, 0x00800080, 0x3f7e01c0, 0x008001c0, 0x00800080, 0x00800080, 0x00000000, // ICON_TARGET_SMALL
+ 0x00800000, 0x00800080, 0x03e00080, 0x3e3e0220, 0x03e00220, 0x00800080, 0x00800080, 0x00000000, // ICON_TARGET_BIG
+ 0x01000000, 0x04400280, 0x01000100, 0x43842008, 0x43849ab2, 0x01002008, 0x04400100, 0x01000280, // ICON_TARGET_MOVE
+ 0x01000000, 0x04400280, 0x01000100, 0x41042108, 0x41049ff2, 0x01002108, 0x04400100, 0x01000280, // ICON_CURSOR_MOVE
+ 0x781e0000, 0x500a4002, 0x04204812, 0x00000240, 0x02400000, 0x48120420, 0x4002500a, 0x0000781e, // ICON_CURSOR_SCALE
+ 0x00000000, 0x20003c00, 0x24002800, 0x01000200, 0x00400080, 0x00140024, 0x003c0004, 0x00000000, // ICON_CURSOR_SCALE_RIGHT
+ 0x00000000, 0x0004003c, 0x00240014, 0x00800040, 0x02000100, 0x28002400, 0x3c002000, 0x00000000, // ICON_CURSOR_SCALE_LEFT
+ 0x00000000, 0x00100020, 0x10101fc8, 0x10001020, 0x10001000, 0x10001000, 0x00001fc0, 0x00000000, // ICON_UNDO
+ 0x00000000, 0x08000400, 0x080813f8, 0x00080408, 0x00080008, 0x00080008, 0x000003f8, 0x00000000, // ICON_REDO
+ 0x00000000, 0x3ffc0000, 0x20042004, 0x20002000, 0x20402000, 0x3f902020, 0x00400020, 0x00000000, // ICON_REREDO
+ 0x00000000, 0x3ffc0000, 0x20042004, 0x27fc2004, 0x20202000, 0x3fc82010, 0x00200010, 0x00000000, // ICON_MUTATE
+ 0x00000000, 0x0ff00000, 0x10081818, 0x11801008, 0x10001180, 0x18101020, 0x00100fc8, 0x00000020, // ICON_ROTATE
+ 0x00000000, 0x04000200, 0x240429fc, 0x20042204, 0x20442004, 0x3f942024, 0x00400020, 0x00000000, // ICON_REPEAT
+ 0x00000000, 0x20001000, 0x22104c0e, 0x00801120, 0x11200040, 0x4c0e2210, 0x10002000, 0x00000000, // ICON_SHUFFLE
+ 0x7ffe0000, 0x50024002, 0x44024802, 0x41024202, 0x40424082, 0x40124022, 0x4002400a, 0x00007ffe, // ICON_EMPTYBOX
+ 0x00800000, 0x03e00080, 0x08080490, 0x3c9e0808, 0x08080808, 0x03e00490, 0x00800080, 0x00000000, // ICON_TARGET
+ 0x00800000, 0x00800080, 0x00800080, 0x3ffe01c0, 0x008001c0, 0x00800080, 0x00800080, 0x00000000, // ICON_TARGET_SMALL_FILL
+ 0x00800000, 0x00800080, 0x03e00080, 0x3ffe03e0, 0x03e003e0, 0x00800080, 0x00800080, 0x00000000, // ICON_TARGET_BIG_FILL
+ 0x01000000, 0x07c00380, 0x01000100, 0x638c2008, 0x638cfbbe, 0x01002008, 0x07c00100, 0x01000380, // ICON_TARGET_MOVE_FILL
+ 0x01000000, 0x07c00380, 0x01000100, 0x610c2108, 0x610cfffe, 0x01002108, 0x07c00100, 0x01000380, // ICON_CURSOR_MOVE_FILL
+ 0x781e0000, 0x6006700e, 0x04204812, 0x00000240, 0x02400000, 0x48120420, 0x700e6006, 0x0000781e, // ICON_CURSOR_SCALE_FILL
+ 0x00000000, 0x38003c00, 0x24003000, 0x01000200, 0x00400080, 0x000c0024, 0x003c001c, 0x00000000, // ICON_CURSOR_SCALE_RIGHT_FILL
+ 0x00000000, 0x001c003c, 0x0024000c, 0x00800040, 0x02000100, 0x30002400, 0x3c003800, 0x00000000, // ICON_CURSOR_SCALE_LEFT_FILL
+ 0x00000000, 0x00300020, 0x10301ff8, 0x10001020, 0x10001000, 0x10001000, 0x00001fc0, 0x00000000, // ICON_UNDO_FILL
+ 0x00000000, 0x0c000400, 0x0c081ff8, 0x00080408, 0x00080008, 0x00080008, 0x000003f8, 0x00000000, // ICON_REDO_FILL
+ 0x00000000, 0x3ffc0000, 0x20042004, 0x20002000, 0x20402000, 0x3ff02060, 0x00400060, 0x00000000, // ICON_REREDO_FILL
+ 0x00000000, 0x3ffc0000, 0x20042004, 0x27fc2004, 0x20202000, 0x3ff82030, 0x00200030, 0x00000000, // ICON_MUTATE_FILL
+ 0x00000000, 0x0ff00000, 0x10081818, 0x11801008, 0x10001180, 0x18301020, 0x00300ff8, 0x00000020, // ICON_ROTATE_FILL
+ 0x00000000, 0x06000200, 0x26042ffc, 0x20042204, 0x20442004, 0x3ff42064, 0x00400060, 0x00000000, // ICON_REPEAT_FILL
+ 0x00000000, 0x30001000, 0x32107c0e, 0x00801120, 0x11200040, 0x7c0e3210, 0x10003000, 0x00000000, // ICON_SHUFFLE_FILL
+ 0x00000000, 0x30043ffc, 0x24042804, 0x21042204, 0x20442084, 0x20142024, 0x3ffc200c, 0x00000000, // ICON_EMPTYBOX_SMALL
+ 0x00000000, 0x20043ffc, 0x20042004, 0x20042004, 0x20042004, 0x20042004, 0x3ffc2004, 0x00000000, // ICON_BOX
+ 0x00000000, 0x23c43ffc, 0x23c423c4, 0x200423c4, 0x20042004, 0x20042004, 0x3ffc2004, 0x00000000, // ICON_BOX_TOP
+ 0x00000000, 0x3e043ffc, 0x3e043e04, 0x20043e04, 0x20042004, 0x20042004, 0x3ffc2004, 0x00000000, // ICON_BOX_TOP_RIGHT
+ 0x00000000, 0x20043ffc, 0x20042004, 0x3e043e04, 0x3e043e04, 0x20042004, 0x3ffc2004, 0x00000000, // ICON_BOX_RIGHT
+ 0x00000000, 0x20043ffc, 0x20042004, 0x20042004, 0x3e042004, 0x3e043e04, 0x3ffc3e04, 0x00000000, // ICON_BOX_BOTTOM_RIGHT
+ 0x00000000, 0x20043ffc, 0x20042004, 0x20042004, 0x23c42004, 0x23c423c4, 0x3ffc23c4, 0x00000000, // ICON_BOX_BOTTOM
+ 0x00000000, 0x20043ffc, 0x20042004, 0x20042004, 0x207c2004, 0x207c207c, 0x3ffc207c, 0x00000000, // ICON_BOX_BOTTOM_LEFT
+ 0x00000000, 0x20043ffc, 0x20042004, 0x207c207c, 0x207c207c, 0x20042004, 0x3ffc2004, 0x00000000, // ICON_BOX_LEFT
+ 0x00000000, 0x207c3ffc, 0x207c207c, 0x2004207c, 0x20042004, 0x20042004, 0x3ffc2004, 0x00000000, // ICON_BOX_TOP_LEFT
+ 0x00000000, 0x20043ffc, 0x20042004, 0x23c423c4, 0x23c423c4, 0x20042004, 0x3ffc2004, 0x00000000, // ICON_BOX_CENTER
+ 0x7ffe0000, 0x40024002, 0x47e24182, 0x4ff247e2, 0x47e24ff2, 0x418247e2, 0x40024002, 0x00007ffe, // ICON_BOX_CIRCLE_MASK
+ 0x7fff0000, 0x40014001, 0x40014001, 0x49555ddd, 0x4945495d, 0x400149c5, 0x40014001, 0x00007fff, // ICON_POT
+ 0x7ffe0000, 0x53327332, 0x44ce4cce, 0x41324332, 0x404e40ce, 0x48125432, 0x4006540e, 0x00007ffe, // ICON_ALPHA_MULTIPLY
+ 0x7ffe0000, 0x53327332, 0x44ce4cce, 0x41324332, 0x5c4e40ce, 0x44124432, 0x40065c0e, 0x00007ffe, // ICON_ALPHA_CLEAR
+ 0x7ffe0000, 0x42fe417e, 0x42fe417e, 0x42fe417e, 0x42fe417e, 0x42fe417e, 0x42fe417e, 0x00007ffe, // ICON_DITHERING
+ 0x07fe0000, 0x1ffa0002, 0x7fea000a, 0x402a402a, 0x5b2a512a, 0x5128552a, 0x40205128, 0x00007fe0, // ICON_MIPMAPS
+ 0x00000000, 0x1ff80000, 0x12481248, 0x12481ff8, 0x1ff81248, 0x12481248, 0x00001ff8, 0x00000000, // ICON_BOX_GRID
+ 0x12480000, 0x7ffe1248, 0x12481248, 0x12487ffe, 0x7ffe1248, 0x12481248, 0x12487ffe, 0x00001248, // ICON_GRID
+ 0x00000000, 0x1c380000, 0x1c3817e8, 0x08100810, 0x08100810, 0x17e81c38, 0x00001c38, 0x00000000, // ICON_BOX_CORNERS_SMALL
+ 0x700e0000, 0x700e5ffa, 0x20042004, 0x20042004, 0x20042004, 0x20042004, 0x5ffa700e, 0x0000700e, // ICON_BOX_CORNERS_BIG
+ 0x3f7e0000, 0x21422142, 0x21422142, 0x00003f7e, 0x21423f7e, 0x21422142, 0x3f7e2142, 0x00000000, // ICON_FOUR_BOXES
+ 0x00000000, 0x3bb80000, 0x3bb83bb8, 0x3bb80000, 0x3bb83bb8, 0x3bb80000, 0x3bb83bb8, 0x00000000, // ICON_GRID_FILL
+ 0x7ffe0000, 0x7ffe7ffe, 0x77fe7000, 0x77fe77fe, 0x777e7700, 0x777e777e, 0x777e777e, 0x0000777e, // ICON_BOX_MULTISIZE
+ 0x781e0000, 0x40024002, 0x00004002, 0x01800000, 0x00000180, 0x40020000, 0x40024002, 0x0000781e, // ICON_ZOOM_SMALL
+ 0x781e0000, 0x40024002, 0x00004002, 0x03c003c0, 0x03c003c0, 0x40020000, 0x40024002, 0x0000781e, // ICON_ZOOM_MEDIUM
+ 0x781e0000, 0x40024002, 0x07e04002, 0x07e007e0, 0x07e007e0, 0x400207e0, 0x40024002, 0x0000781e, // ICON_ZOOM_BIG
+ 0x781e0000, 0x5ffa4002, 0x1ff85ffa, 0x1ff81ff8, 0x1ff81ff8, 0x5ffa1ff8, 0x40025ffa, 0x0000781e, // ICON_ZOOM_ALL
+ 0x00000000, 0x2004381c, 0x00002004, 0x00000000, 0x00000000, 0x20040000, 0x381c2004, 0x00000000, // ICON_ZOOM_CENTER
+ 0x00000000, 0x1db80000, 0x10081008, 0x10080000, 0x00001008, 0x10081008, 0x00001db8, 0x00000000, // ICON_BOX_DOTS_SMALL
+ 0x35560000, 0x00002002, 0x00002002, 0x00002002, 0x00002002, 0x00002002, 0x35562002, 0x00000000, // ICON_BOX_DOTS_BIG
+ 0x7ffe0000, 0x40024002, 0x48124ff2, 0x49924812, 0x48124992, 0x4ff24812, 0x40024002, 0x00007ffe, // ICON_BOX_CONCENTRIC
+ 0x00000000, 0x10841ffc, 0x10841084, 0x1ffc1084, 0x10841084, 0x10841084, 0x00001ffc, 0x00000000, // ICON_BOX_GRID_BIG
+ 0x00000000, 0x00000000, 0x10000000, 0x04000800, 0x01040200, 0x00500088, 0x00000020, 0x00000000, // ICON_OK_TICK
+ 0x00000000, 0x10080000, 0x04200810, 0x01800240, 0x02400180, 0x08100420, 0x00001008, 0x00000000, // ICON_CROSS
+ 0x00000000, 0x02000000, 0x00800100, 0x00200040, 0x00200010, 0x00800040, 0x02000100, 0x00000000, // ICON_ARROW_LEFT
+ 0x00000000, 0x00400000, 0x01000080, 0x04000200, 0x04000800, 0x01000200, 0x00400080, 0x00000000, // ICON_ARROW_RIGHT
+ 0x00000000, 0x00000000, 0x00000000, 0x08081004, 0x02200410, 0x00800140, 0x00000000, 0x00000000, // ICON_ARROW_DOWN
+ 0x00000000, 0x00000000, 0x01400080, 0x04100220, 0x10040808, 0x00000000, 0x00000000, 0x00000000, // ICON_ARROW_UP
+ 0x00000000, 0x02000000, 0x03800300, 0x03e003c0, 0x03e003f0, 0x038003c0, 0x02000300, 0x00000000, // ICON_ARROW_LEFT_FILL
+ 0x00000000, 0x00400000, 0x01c000c0, 0x07c003c0, 0x07c00fc0, 0x01c003c0, 0x004000c0, 0x00000000, // ICON_ARROW_RIGHT_FILL
+ 0x00000000, 0x00000000, 0x00000000, 0x0ff81ffc, 0x03e007f0, 0x008001c0, 0x00000000, 0x00000000, // ICON_ARROW_DOWN_FILL
+ 0x00000000, 0x00000000, 0x01c00080, 0x07f003e0, 0x1ffc0ff8, 0x00000000, 0x00000000, 0x00000000, // ICON_ARROW_UP_FILL
+ 0x00000000, 0x18a008c0, 0x32881290, 0x24822686, 0x26862482, 0x12903288, 0x08c018a0, 0x00000000, // ICON_AUDIO
+ 0x00000000, 0x04800780, 0x004000c0, 0x662000f0, 0x08103c30, 0x130a0e18, 0x0000318e, 0x00000000, // ICON_FX
+ 0x00000000, 0x00800000, 0x08880888, 0x2aaa0a8a, 0x0a8a2aaa, 0x08880888, 0x00000080, 0x00000000, // ICON_WAVE
+ 0x00000000, 0x00600000, 0x01080090, 0x02040108, 0x42044204, 0x24022402, 0x00001800, 0x00000000, // ICON_WAVE_SINUS
+ 0x00000000, 0x07f80000, 0x04080408, 0x04080408, 0x04080408, 0x7c0e0408, 0x00000000, 0x00000000, // ICON_WAVE_SQUARE
+ 0x00000000, 0x00000000, 0x00a00040, 0x22084110, 0x08021404, 0x00000000, 0x00000000, 0x00000000, // ICON_WAVE_TRIANGULAR
+ 0x00000000, 0x00000000, 0x04200000, 0x01800240, 0x02400180, 0x00000420, 0x00000000, 0x00000000, // ICON_CROSS_SMALL
+ 0x00000000, 0x18380000, 0x12281428, 0x10a81128, 0x112810a8, 0x14281228, 0x00001838, 0x00000000, // ICON_PLAYER_PREVIOUS
+ 0x00000000, 0x18000000, 0x11801600, 0x10181060, 0x10601018, 0x16001180, 0x00001800, 0x00000000, // ICON_PLAYER_PLAY_BACK
+ 0x00000000, 0x00180000, 0x01880068, 0x18080608, 0x06081808, 0x00680188, 0x00000018, 0x00000000, // ICON_PLAYER_PLAY
+ 0x00000000, 0x1e780000, 0x12481248, 0x12481248, 0x12481248, 0x12481248, 0x00001e78, 0x00000000, // ICON_PLAYER_PAUSE
+ 0x00000000, 0x1ff80000, 0x10081008, 0x10081008, 0x10081008, 0x10081008, 0x00001ff8, 0x00000000, // ICON_PLAYER_STOP
+ 0x00000000, 0x1c180000, 0x14481428, 0x15081488, 0x14881508, 0x14281448, 0x00001c18, 0x00000000, // ICON_PLAYER_NEXT
+ 0x00000000, 0x03c00000, 0x08100420, 0x10081008, 0x10081008, 0x04200810, 0x000003c0, 0x00000000, // ICON_PLAYER_RECORD
+ 0x00000000, 0x0c3007e0, 0x13c81818, 0x14281668, 0x14281428, 0x1c381c38, 0x08102244, 0x00000000, // ICON_MAGNET
+ 0x07c00000, 0x08200820, 0x3ff80820, 0x23882008, 0x21082388, 0x20082108, 0x1ff02008, 0x00000000, // ICON_LOCK_CLOSE
+ 0x07c00000, 0x08000800, 0x3ff80800, 0x23882008, 0x21082388, 0x20082108, 0x1ff02008, 0x00000000, // ICON_LOCK_OPEN
+ 0x01c00000, 0x0c180770, 0x3086188c, 0x60832082, 0x60034781, 0x30062002, 0x0c18180c, 0x01c00770, // ICON_CLOCK
+ 0x0a200000, 0x1b201b20, 0x04200e20, 0x04200420, 0x04700420, 0x0e700e70, 0x0e700e70, 0x04200e70, // ICON_TOOLS
+ 0x01800000, 0x3bdc318c, 0x0ff01ff8, 0x7c3e1e78, 0x1e787c3e, 0x1ff80ff0, 0x318c3bdc, 0x00000180, // ICON_GEAR
+ 0x01800000, 0x3ffc318c, 0x1c381ff8, 0x781e1818, 0x1818781e, 0x1ff81c38, 0x318c3ffc, 0x00000180, // ICON_GEAR_BIG
+ 0x00000000, 0x08080ff8, 0x08081ffc, 0x0aa80aa8, 0x0aa80aa8, 0x0aa80aa8, 0x08080aa8, 0x00000ff8, // ICON_BIN
+ 0x00000000, 0x00000000, 0x20043ffc, 0x08043f84, 0x04040f84, 0x04040784, 0x000007fc, 0x00000000, // ICON_HAND_POINTER
+ 0x00000000, 0x24400400, 0x00001480, 0x6efe0e00, 0x00000e00, 0x24401480, 0x00000400, 0x00000000, // ICON_LASER
+ 0x00000000, 0x03c00000, 0x08300460, 0x11181118, 0x11181118, 0x04600830, 0x000003c0, 0x00000000, // ICON_COIN
+ 0x00000000, 0x10880080, 0x06c00810, 0x366c07e0, 0x07e00240, 0x00001768, 0x04200240, 0x00000000, // ICON_EXPLOSION
+ 0x00000000, 0x3d280000, 0x2528252c, 0x3d282528, 0x05280528, 0x05e80528, 0x00000000, 0x00000000, // ICON_1UP
+ 0x01800000, 0x03c003c0, 0x018003c0, 0x0ff007e0, 0x0bd00bd0, 0x0a500bd0, 0x02400240, 0x02400240, // ICON_PLAYER
+ 0x01800000, 0x03c003c0, 0x118013c0, 0x03c81ff8, 0x07c003c8, 0x04400440, 0x0c080478, 0x00000000, // ICON_PLAYER_JUMP
+ 0x3ff80000, 0x30183ff8, 0x30183018, 0x3ff83ff8, 0x03000300, 0x03c003c0, 0x03e00300, 0x000003e0, // ICON_KEY
+ 0x3ff80000, 0x3ff83ff8, 0x33983ff8, 0x3ff83398, 0x3ff83ff8, 0x00000540, 0x0fe00aa0, 0x00000fe0, // ICON_DEMON
+ 0x00000000, 0x0ff00000, 0x20041008, 0x25442004, 0x10082004, 0x06000bf0, 0x00000300, 0x00000000, // ICON_TEXT_POPUP
+ 0x00000000, 0x11440000, 0x07f00be8, 0x1c1c0e38, 0x1c1c0c18, 0x07f00e38, 0x11440be8, 0x00000000, // ICON_GEAR_EX
+ 0x00000000, 0x20080000, 0x0c601010, 0x07c00fe0, 0x07c007c0, 0x0c600fe0, 0x20081010, 0x00000000, // ICON_CRACK
+ 0x00000000, 0x20080000, 0x0c601010, 0x04400fe0, 0x04405554, 0x0c600fe0, 0x20081010, 0x00000000, // ICON_CRACK_POINTS
+ 0x00000000, 0x00800080, 0x01c001c0, 0x1ffc3ffe, 0x03e007f0, 0x07f003e0, 0x0c180770, 0x00000808, // ICON_STAR
+ 0x0ff00000, 0x08180810, 0x08100818, 0x0a100810, 0x08180810, 0x08100818, 0x08100810, 0x00001ff8, // ICON_DOOR
+ 0x0ff00000, 0x08100810, 0x08100810, 0x10100010, 0x4f902010, 0x10102010, 0x08100010, 0x00000ff0, // ICON_EXIT
+ 0x00040000, 0x001f000e, 0x0ef40004, 0x12f41284, 0x0ef41214, 0x10040004, 0x7ffc3004, 0x10003000, // ICON_MODE_2D
+ 0x78040000, 0x501f600e, 0x0ef44004, 0x12f41284, 0x0ef41284, 0x10140004, 0x7ffc300c, 0x10003000, // ICON_MODE_3D
+ 0x7fe00000, 0x50286030, 0x47fe4804, 0x44224402, 0x44224422, 0x241275e2, 0x0c06140a, 0x000007fe, // ICON_CUBE
+ 0x7fe00000, 0x5ff87ff0, 0x47fe4ffc, 0x44224402, 0x44224422, 0x241275e2, 0x0c06140a, 0x000007fe, // ICON_CUBE_FACE_TOP
+ 0x7fe00000, 0x50386030, 0x47c2483c, 0x443e443e, 0x443e443e, 0x241e75fe, 0x0c06140e, 0x000007fe, // ICON_CUBE_FACE_LEFT
+ 0x7fe00000, 0x50286030, 0x47fe4804, 0x47fe47fe, 0x47fe47fe, 0x27fe77fe, 0x0ffe17fe, 0x000007fe, // ICON_CUBE_FACE_FRONT
+ 0x7fe00000, 0x50286030, 0x47fe4804, 0x44224402, 0x44224422, 0x3bf27be2, 0x0bfe1bfa, 0x000007fe, // ICON_CUBE_FACE_BOTTOM
+ 0x7fe00000, 0x70286030, 0x7ffe7804, 0x7c227c02, 0x7c227c22, 0x3c127de2, 0x0c061c0a, 0x000007fe, // ICON_CUBE_FACE_RIGHT
+ 0x7fe00000, 0x6fe85ff0, 0x781e77e4, 0x7be27be2, 0x7be27be2, 0x24127be2, 0x0c06140a, 0x000007fe, // ICON_CUBE_FACE_BACK
+ 0x00000000, 0x2a0233fe, 0x22022602, 0x22022202, 0x2a022602, 0x00a033fe, 0x02080110, 0x00000000, // ICON_CAMERA
+ 0x00000000, 0x200c3ffc, 0x000c000c, 0x3ffc000c, 0x30003000, 0x30003000, 0x3ffc3004, 0x00000000, // ICON_SPECIAL
+ 0x00000000, 0x0022003e, 0x012201e2, 0x0100013e, 0x01000100, 0x79000100, 0x4f004900, 0x00007800, // ICON_LINK_NET
+ 0x00000000, 0x44007c00, 0x45004600, 0x00627cbe, 0x00620022, 0x45007cbe, 0x44004600, 0x00007c00, // ICON_LINK_BOXES
+ 0x00000000, 0x0044007c, 0x0010007c, 0x3f100010, 0x3f1021f0, 0x3f100010, 0x3f0021f0, 0x00000000, // ICON_LINK_MULTI
+ 0x00000000, 0x0044007c, 0x00440044, 0x0010007c, 0x00100010, 0x44107c10, 0x440047f0, 0x00007c00, // ICON_LINK
+ 0x00000000, 0x0044007c, 0x00440044, 0x0000007c, 0x00000010, 0x44007c10, 0x44004550, 0x00007c00, // ICON_LINK_BROKE
+ 0x02a00000, 0x22a43ffc, 0x20042004, 0x20042ff4, 0x20042ff4, 0x20042ff4, 0x20042004, 0x00003ffc, // ICON_TEXT_NOTES
+ 0x3ffc0000, 0x20042004, 0x245e27c4, 0x27c42444, 0x2004201e, 0x201e2004, 0x20042004, 0x00003ffc, // ICON_NOTEBOOK
+ 0x00000000, 0x07e00000, 0x04200420, 0x24243ffc, 0x24242424, 0x24242424, 0x3ffc2424, 0x00000000, // ICON_SUITCASE
+ 0x00000000, 0x0fe00000, 0x08200820, 0x40047ffc, 0x7ffc5554, 0x40045554, 0x7ffc4004, 0x00000000, // ICON_SUITCASE_ZIP
+ 0x00000000, 0x20043ffc, 0x3ffc2004, 0x13c81008, 0x100813c8, 0x10081008, 0x1ff81008, 0x00000000, // ICON_MAILBOX
+ 0x00000000, 0x40027ffe, 0x5ffa5ffa, 0x5ffa5ffa, 0x40025ffa, 0x03c07ffe, 0x1ff81ff8, 0x00000000, // ICON_MONITOR
+ 0x0ff00000, 0x6bfe7ffe, 0x7ffe7ffe, 0x68167ffe, 0x08106816, 0x08100810, 0x0ff00810, 0x00000000, // ICON_PRINTER
+ 0x3ff80000, 0xfffe2008, 0x870a8002, 0x904a888a, 0x904a904a, 0x870a888a, 0xfffe8002, 0x00000000, // ICON_PHOTO_CAMERA
+ 0x0fc00000, 0xfcfe0cd8, 0x8002fffe, 0x84428382, 0x84428442, 0x80028382, 0xfffe8002, 0x00000000, // ICON_PHOTO_CAMERA_FLASH
+ 0x00000000, 0x02400180, 0x08100420, 0x20041008, 0x23c42004, 0x22442244, 0x3ffc2244, 0x00000000, // ICON_HOUSE
+ 0x00000000, 0x1c700000, 0x3ff83ef8, 0x3ff83ff8, 0x0fe01ff0, 0x038007c0, 0x00000100, 0x00000000, // ICON_HEART
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x80000000, 0xe000c000, // ICON_CORNER
+ 0x00000000, 0x14001c00, 0x15c01400, 0x15401540, 0x155c1540, 0x15541554, 0x1ddc1554, 0x00000000, // ICON_VERTICAL_BARS
+ 0x00000000, 0x03000300, 0x1b001b00, 0x1b601b60, 0x1b6c1b60, 0x1b6c1b6c, 0x1b6c1b6c, 0x00000000, // ICON_VERTICAL_BARS_FILL
+ 0x00000000, 0x00000000, 0x403e7ffe, 0x7ffe403e, 0x7ffe0000, 0x43fe43fe, 0x00007ffe, 0x00000000, // ICON_LIFE_BARS
+ 0x7ffc0000, 0x43844004, 0x43844284, 0x43844004, 0x42844284, 0x42844284, 0x40044384, 0x00007ffc, // ICON_INFO
+ 0x40008000, 0x10002000, 0x04000800, 0x01000200, 0x00400080, 0x00100020, 0x00040008, 0x00010002, // ICON_CROSSLINE
+ 0x00000000, 0x1ff01ff0, 0x18301830, 0x1f001830, 0x03001f00, 0x00000300, 0x03000300, 0x00000000, // ICON_HELP
+ 0x3ff00000, 0x2abc3550, 0x2aac3554, 0x2aac3554, 0x2aac3554, 0x2aac3554, 0x2aac3554, 0x00003ffc, // ICON_FILETYPE_ALPHA
+ 0x3ff00000, 0x201c2010, 0x22442184, 0x28142424, 0x29942814, 0x2ff42994, 0x20042004, 0x00003ffc, // ICON_FILETYPE_HOME
+ 0x07fe0000, 0x04020402, 0x7fe20402, 0x44224422, 0x44224422, 0x402047fe, 0x40204020, 0x00007fe0, // ICON_LAYERS_VISIBLE
+ 0x07fe0000, 0x04020402, 0x7c020402, 0x44024402, 0x44024402, 0x402047fe, 0x40204020, 0x00007fe0, // ICON_LAYERS
+ 0x00000000, 0x40027ffe, 0x7ffe4002, 0x40024002, 0x40024002, 0x40024002, 0x7ffe4002, 0x00000000, // ICON_WINDOW
+ 0x09100000, 0x09f00910, 0x09100910, 0x00000910, 0x24a2779e, 0x27a224a2, 0x709e20a2, 0x00000000, // ICON_HIDPI
+ 0x3ff00000, 0x201c2010, 0x2a842e84, 0x2e842a84, 0x2ba42004, 0x2aa42aa4, 0x20042ba4, 0x00003ffc, // ICON_FILETYPE_BINARY
+ 0x00000000, 0x00000000, 0x00120012, 0x4a5e4bd2, 0x485233d2, 0x00004bd2, 0x00000000, 0x00000000, // ICON_HEX
+ 0x01800000, 0x381c0660, 0x23c42004, 0x23c42044, 0x13c82204, 0x08101008, 0x02400420, 0x00000180, // ICON_SHIELD
+ 0x007e0000, 0x20023fc2, 0x40227fe2, 0x400a403a, 0x400a400a, 0x400a400a, 0x4008400e, 0x00007ff8, // ICON_FILE_NEW
+ 0x00000000, 0x0042007e, 0x40027fc2, 0x44024002, 0x5f024402, 0x44024402, 0x7ffe4002, 0x00000000, // ICON_FOLDER_ADD
+ 0x44220000, 0x12482244, 0xf3cf0000, 0x14280420, 0x48122424, 0x08100810, 0x1ff81008, 0x03c00420, // ICON_ALARM
+ 0x0aa00000, 0x1ff80aa0, 0x1068700e, 0x1008706e, 0x1008700e, 0x1008700e, 0x0aa01ff8, 0x00000aa0, // ICON_CPU
+ 0x07e00000, 0x04201db8, 0x04a01c38, 0x04a01d38, 0x04a01d38, 0x04a01d38, 0x04201d38, 0x000007e0, // ICON_ROM
+ 0x00000000, 0x03c00000, 0x3c382ff0, 0x3c04380c, 0x01800000, 0x03c003c0, 0x00000180, 0x00000000, // ICON_STEP_OVER
+ 0x01800000, 0x01800180, 0x01800180, 0x03c007e0, 0x00000180, 0x01800000, 0x03c003c0, 0x00000180, // ICON_STEP_INTO
+ 0x01800000, 0x07e003c0, 0x01800180, 0x01800180, 0x00000180, 0x01800000, 0x03c003c0, 0x00000180, // ICON_STEP_OUT
+ 0x00000000, 0x0ff003c0, 0x181c1c34, 0x303c301c, 0x30003000, 0x1c301800, 0x03c00ff0, 0x00000000, // ICON_RESTART
+ 0x00000000, 0x00000000, 0x07e003c0, 0x0ff00ff0, 0x0ff00ff0, 0x03c007e0, 0x00000000, 0x00000000, // ICON_BREAKPOINT_ON
+ 0x00000000, 0x00000000, 0x042003c0, 0x08100810, 0x08100810, 0x03c00420, 0x00000000, 0x00000000, // ICON_BREAKPOINT_OFF
+ 0x00000000, 0x00000000, 0x1ff81ff8, 0x1ff80000, 0x00001ff8, 0x1ff81ff8, 0x00000000, 0x00000000, // ICON_BURGER_MENU
+ 0x00000000, 0x00000000, 0x00880070, 0x0c880088, 0x1e8810f8, 0x3e881288, 0x00000000, 0x00000000, // ICON_CASE_SENSITIVE
+ 0x00000000, 0x02000000, 0x07000a80, 0x07001fc0, 0x02000a80, 0x00300030, 0x00000000, 0x00000000, // ICON_REG_EXP
+ 0x00000000, 0x0042007e, 0x40027fc2, 0x40024002, 0x40024002, 0x40024002, 0x7ffe4002, 0x00000000, // ICON_FOLDER
+ 0x3ff00000, 0x201c2010, 0x20042004, 0x20042004, 0x20042004, 0x20042004, 0x20042004, 0x00003ffc, // ICON_FILE
+ 0x1ff00000, 0x20082008, 0x17d02fe8, 0x05400ba0, 0x09200540, 0x23881010, 0x2fe827c8, 0x00001ff0, // ICON_SAND_TIMER
+ 0x01800000, 0x02400240, 0x05a00420, 0x09900990, 0x11881188, 0x21842004, 0x40024182, 0x00003ffc, // ICON_WARNING
+ 0x7ffe0000, 0x4ff24002, 0x4c324ff2, 0x4f824c02, 0x41824f82, 0x41824002, 0x40024182, 0x00007ffe, // ICON_HELP_BOX
+ 0x7ffe0000, 0x41824002, 0x40024182, 0x41824182, 0x41824182, 0x41824182, 0x40024182, 0x00007ffe, // ICON_INFO_BOX
+ 0x01800000, 0x04200240, 0x10080810, 0x7bde2004, 0x0a500a50, 0x08500bd0, 0x08100850, 0x00000ff0, // ICON_PRIORITY
+ 0x01800000, 0x18180660, 0x80016006, 0x98196006, 0x99996666, 0x19986666, 0x01800660, 0x00000000, // ICON_LAYERS_ISO
+ 0x07fe0000, 0x1c020402, 0x74021402, 0x54025402, 0x54025402, 0x500857fe, 0x40205ff8, 0x00007fe0, // ICON_LAYERS2
+ 0x0ffe0000, 0x3ffa0802, 0x7fea200a, 0x402a402a, 0x422a422a, 0x422e422a, 0x40384e28, 0x00007fe0, // ICON_MLAYERS
+ 0x0ffe0000, 0x3ffa0802, 0x7fea200a, 0x402a402a, 0x5b2a512a, 0x512e552a, 0x40385128, 0x00007fe0, // ICON_MAPS
+ 0x04200000, 0x1cf00c60, 0x11f019f0, 0x0f3807b8, 0x1e3c0f3c, 0x1c1c1e1c, 0x1e3c1c1c, 0x00000f70, // ICON_HOT
+ 0x00000000, 0x20803f00, 0x2a202e40, 0x20082e10, 0x08021004, 0x02040402, 0x00900108, 0x00000060, // ICON_LABEL
+ 0x00000000, 0x042007e0, 0x47e27c3e, 0x4ffa4002, 0x47fa4002, 0x4ffa4002, 0x7ffe4002, 0x00000000, // ICON_NAME_ID
+ 0x7fe00000, 0x402e4020, 0x43ce5e0a, 0x40504078, 0x438e4078, 0x402e5e0a, 0x7fe04020, 0x00000000, // ICON_SLICING
+ 0x00000000, 0x40027ffe, 0x47c24002, 0x55425d42, 0x55725542, 0x50125552, 0x10105016, 0x00001ff0, // ICON_MANUAL_CONTROL
+ 0x7ffe0000, 0x43c24002, 0x48124422, 0x500a500a, 0x500a500a, 0x44224812, 0x400243c2, 0x00007ffe, // ICON_COLLISION
+ 0x03c00000, 0x10080c30, 0x21842184, 0x4ff24182, 0x41824ff2, 0x21842184, 0x0c301008, 0x000003c0, // ICON_CIRCLE_ADD
+ 0x03c00000, 0x1ff80ff0, 0x3e7c3e7c, 0x700e7e7e, 0x7e7e700e, 0x3e7c3e7c, 0x0ff01ff8, 0x000003c0, // ICON_CIRCLE_ADD_FILL
+ 0x03c00000, 0x10080c30, 0x21842184, 0x41824182, 0x40024182, 0x21842184, 0x0c301008, 0x000003c0, // ICON_CIRCLE_WARNING
+ 0x03c00000, 0x1ff80ff0, 0x3e7c3e7c, 0x7e7e7e7e, 0x7ffe7e7e, 0x3e7c3e7c, 0x0ff01ff8, 0x000003c0, // ICON_CIRCLE_WARNING_FILL
+ 0x00000000, 0x10041ffc, 0x10841004, 0x13e41084, 0x10841084, 0x10041004, 0x00001ffc, 0x00000000, // ICON_BOX_MORE
+ 0x00000000, 0x1ffc1ffc, 0x1f7c1ffc, 0x1c1c1f7c, 0x1f7c1f7c, 0x1ffc1ffc, 0x00001ffc, 0x00000000, // ICON_BOX_MORE_FILL
+ 0x00000000, 0x1ffc1ffc, 0x1ffc1ffc, 0x1c1c1ffc, 0x1ffc1ffc, 0x1ffc1ffc, 0x00001ffc, 0x00000000, // ICON_BOX_MINUS
+ 0x00000000, 0x10041ffc, 0x10041004, 0x13e41004, 0x10041004, 0x10041004, 0x00001ffc, 0x00000000, // ICON_BOX_MINUS_FILL
+ 0x07fe0000, 0x055606aa, 0x7ff606aa, 0x55766eba, 0x55766eaa, 0x55606ffe, 0x55606aa0, 0x00007fe0, // ICON_UNION
+ 0x07fe0000, 0x04020402, 0x7fe20402, 0x456246a2, 0x456246a2, 0x402047fe, 0x40204020, 0x00007fe0, // ICON_INTERSECTION
+ 0x07fe0000, 0x055606aa, 0x7ff606aa, 0x4436442a, 0x4436442a, 0x402047fe, 0x40204020, 0x00007fe0, // ICON_DIFFERENCE
+ 0x03c00000, 0x10080c30, 0x20042004, 0x60064002, 0x47e2581a, 0x20042004, 0x0c301008, 0x000003c0, // ICON_SPHERE
+ 0x03e00000, 0x08080410, 0x0c180808, 0x08080be8, 0x08080808, 0x08080808, 0x04100808, 0x000003e0, // ICON_CYLINDER
+ 0x00800000, 0x01400140, 0x02200220, 0x04100410, 0x08080808, 0x1c1c13e4, 0x08081004, 0x000007f0, // ICON_CONE
+ 0x00000000, 0x07e00000, 0x20841918, 0x40824082, 0x40824082, 0x19182084, 0x000007e0, 0x00000000, // ICON_ELLIPSOID
+ 0x00000000, 0x00000000, 0x20041ff8, 0x40024002, 0x40024002, 0x1ff82004, 0x00000000, 0x00000000, // ICON_CAPSULE
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_250
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_251
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_252
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_253
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_254
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_255
+};
+
+// NOTE: A pointer to current icons array should be defined
+static unsigned int *guiIconsPtr = guiIcons;
+
+#endif // !RAYGUI_NO_ICONS && !RAYGUI_CUSTOM_ICONS
+
+#ifndef RAYGUI_ICON_SIZE
+ #define RAYGUI_ICON_SIZE 0
+#endif
+
+// WARNING: Those values define the total size of the style data array,
+// if changed, previous saved styles could become incompatible
+#define RAYGUI_MAX_CONTROLS 16 // Maximum number of controls
+#define RAYGUI_MAX_PROPS_BASE 16 // Maximum number of base properties
+#define RAYGUI_MAX_PROPS_EXTENDED 8 // Maximum number of extended properties
+
+//----------------------------------------------------------------------------------
+// Module Types and Structures Definition
+//----------------------------------------------------------------------------------
+// Gui control property style color element
+typedef enum { BORDER = 0, BASE, TEXT, OTHER } GuiPropertyElement;
+
+//----------------------------------------------------------------------------------
+// Global Variables Definition
+//----------------------------------------------------------------------------------
+static GuiState guiState = STATE_NORMAL; // Gui global state, if !STATE_NORMAL, forces defined state
+
+static Font guiFont = { 0 }; // Gui current font (WARNING: highly coupled to raylib)
+static bool guiLocked = false; // Gui lock state (no inputs processed)
+static float guiAlpha = 1.0f; // Gui controls transparency
+
+static unsigned int guiIconScale = 1; // Gui icon default scale (if icons enabled)
+
+static bool guiTooltip = false; // Tooltip enabled/disabled
+static const char *guiTooltipPtr = NULL; // Tooltip string pointer (string provided by user)
+
+static bool guiControlExclusiveMode = false; // Gui control exclusive mode (no inputs processed except current control)
+static Rectangle guiControlExclusiveRec = { 0 }; // Gui control exclusive bounds rectangle, used as an unique identifier
+
+static int textBoxCursorIndex = 0; // Cursor index, shared by all GuiTextBox*()
+//static int blinkCursorFrameCounter = 0; // Frame counter for cursor blinking
+static int autoCursorCounter = 0; // Frame counter for automatic repeated cursor movement on key-down (cooldown and delay)
+
+//----------------------------------------------------------------------------------
+// Style data array for all gui style properties (allocated on data segment by default)
+//
+// NOTE 1: First set of BASE properties are generic to all controls but could be individually
+// overwritten per control, first set of EXTENDED properties are generic to all controls and
+// can not be overwritten individually but custom EXTENDED properties can be used by control
+//
+// NOTE 2: A new style set could be loaded over this array using GuiLoadStyle(),
+// but default gui style could always be recovered with GuiLoadStyleDefault()
+//
+// guiStyle size is by default: 16*(16 + 8) = 384*4 = 1536 bytes = 1.5 KB
+//----------------------------------------------------------------------------------
+static unsigned int guiStyle[RAYGUI_MAX_CONTROLS*(RAYGUI_MAX_PROPS_BASE + RAYGUI_MAX_PROPS_EXTENDED)] = { 0 };
+
+static bool guiStyleLoaded = false; // Style loaded flag for lazy style initialization
+
+//----------------------------------------------------------------------------------
+// Standalone Mode Functions Declaration
+//
+// NOTE: raygui depend on some raylib input and drawing functions
+// To use raygui as standalone library, below functions must be defined by the user
+//----------------------------------------------------------------------------------
+#if defined(RAYGUI_STANDALONE)
+
+#define KEY_RIGHT 262
+#define KEY_LEFT 263
+#define KEY_DOWN 264
+#define KEY_UP 265
+#define KEY_BACKSPACE 259
+#define KEY_ENTER 257
+
+#define MOUSE_LEFT_BUTTON 0
+
+// Input required functions
+//-------------------------------------------------------------------------------
+static Vector2 GetMousePosition(void);
+static float GetMouseWheelMove(void);
+static bool IsMouseButtonDown(int button);
+static bool IsMouseButtonPressed(int button);
+static bool IsMouseButtonReleased(int button);
+
+static bool IsKeyDown(int key);
+static bool IsKeyPressed(int key);
+static int GetCharPressed(void); // -- GuiTextBox(), GuiValueBox()
+//-------------------------------------------------------------------------------
+
+// Drawing required functions
+//-------------------------------------------------------------------------------
+static void DrawRectangle(int x, int y, int width, int height, Color color); // -- GuiDrawRectangle()
+static void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3, Color col4); // -- GuiColorPicker()
+//-------------------------------------------------------------------------------
+
+// Text required functions
+//-------------------------------------------------------------------------------
+static Font GetFontDefault(void); // -- GuiLoadStyleDefault()
+static Font LoadFontEx(const char *fileName, int fontSize, int *codepoints, int codepointCount); // -- GuiLoadStyle(), load font
+
+static Texture2D LoadTextureFromImage(Image image); // -- GuiLoadStyle(), required to load texture from embedded font atlas image
+static void SetShapesTexture(Texture2D tex, Rectangle rec); // -- GuiLoadStyle(), required to set shapes rec to font white rec (optimization)
+
+static char *LoadFileText(const char *fileName); // -- GuiLoadStyle(), required to load charset data
+static void UnloadFileText(char *text); // -- GuiLoadStyle(), required to unload charset data
+
+static const char *GetDirectoryPath(const char *filePath); // -- GuiLoadStyle(), required to find charset/font file from text .rgs
+
+static int *LoadCodepoints(const char *text, int *count); // -- GuiLoadStyle(), required to load required font codepoints list
+static void UnloadCodepoints(int *codepoints); // -- GuiLoadStyle(), required to unload codepoints list
+
+static unsigned char *DecompressData(const unsigned char *compData, int compDataSize, int *dataSize); // -- GuiLoadStyle()
+//-------------------------------------------------------------------------------
+
+// raylib functions already implemented in raygui
+//-------------------------------------------------------------------------------
+static Color GetColor(int hexValue); // Returns a Color struct from hexadecimal value
+static int ColorToInt(Color color); // Returns hexadecimal value for a Color
+static bool CheckCollisionPointRec(Vector2 point, Rectangle rec); // Check if point is inside rectangle
+static const char *TextFormat(const char *text, ...); // Formatting of text with variables to 'embed'
+static const char **TextSplit(const char *text, char delimiter, int *count); // Split text into multiple strings
+static int TextToInteger(const char *text); // Get integer value from text
+static float TextToFloat(const char *text); // Get float value from text
+
+static int GetCodepointNext(const char *text, int *codepointSize); // Get next codepoint in a UTF-8 encoded text
+static const char *CodepointToUTF8(int codepoint, int *byteSize); // Encode codepoint into UTF-8 text (char array size returned as parameter)
+
+static void DrawRectangleGradientV(int posX, int posY, int width, int height, Color color1, Color color2); // Draw rectangle vertical gradient
+//-------------------------------------------------------------------------------
+
+#endif // RAYGUI_STANDALONE
+
+//----------------------------------------------------------------------------------
+// Module Internal Functions Declaration
+//----------------------------------------------------------------------------------
+static void GuiLoadStyleFromMemory(const unsigned char *fileData, int dataSize); // Load style from memory (binary only)
+
+static Rectangle GetTextBounds(int control, Rectangle bounds); // Get text bounds considering control bounds
+static const char *GetTextIcon(const char *text, int *iconId); // Get text icon if provided and move text cursor
+
+static void GuiDrawText(const char *text, Rectangle textBounds, int alignment, Color tint); // Gui draw text using default font
+static void GuiDrawRectangle(Rectangle rec, int borderWidth, Color borderColor, Color color); // Gui draw rectangle using default raygui style
+
+static const char **GuiTextSplit(const char *text, char delimiter, int *count, int *textRow); // Split controls text into multiple strings
+static Vector3 ConvertHSVtoRGB(Vector3 hsv); // Convert color data from HSV to RGB
+static Vector3 ConvertRGBtoHSV(Vector3 rgb); // Convert color data from RGB to HSV
+
+static int GuiScrollBar(Rectangle bounds, int value, int minValue, int maxValue); // Scroll bar control, used by GuiScrollPanel()
+static void GuiTooltip(Rectangle controlRec); // Draw tooltip using control rec position
+
+static Color GuiFade(Color color, float alpha); // Fade color by an alpha factor
+
+//----------------------------------------------------------------------------------
+// Gui Setup Functions Definition
+//----------------------------------------------------------------------------------
+// Enable gui global state
+// NOTE: We check for STATE_DISABLED to avoid messing custom global state setups
+void GuiEnable(void) { if (guiState == STATE_DISABLED) guiState = STATE_NORMAL; }
+
+// Disable gui global state
+// NOTE: We check for STATE_NORMAL to avoid messing custom global state setups
+void GuiDisable(void) { if (guiState == STATE_NORMAL) guiState = STATE_DISABLED; }
+
+// Lock gui global state
+void GuiLock(void) { guiLocked = true; }
+
+// Unlock gui global state
+void GuiUnlock(void) { guiLocked = false; }
+
+// Check if gui is locked (global state)
+bool GuiIsLocked(void) { return guiLocked; }
+
+// Set gui controls alpha global state
+void GuiSetAlpha(float alpha)
+{
+ if (alpha < 0.0f) alpha = 0.0f;
+ else if (alpha > 1.0f) alpha = 1.0f;
+
+ guiAlpha = alpha;
+}
+
+// Set gui state (global state)
+void GuiSetState(int state) { guiState = (GuiState)state; }
+
+// Get gui state (global state)
+int GuiGetState(void) { return guiState; }
+
+// Set custom gui font
+// NOTE: Font loading/unloading is external to raygui
+void GuiSetFont(Font font)
+{
+ if (font.texture.id > 0)
+ {
+ // NOTE: If we try to setup a font but default style has not been
+ // lazily loaded before, it will be overwritten, so we need to force
+ // default style loading first
+ if (!guiStyleLoaded) GuiLoadStyleDefault();
+
+ guiFont = font;
+ }
+}
+
+// Get custom gui font
+Font GuiGetFont(void)
+{
+ return guiFont;
+}
+
+// Set control style property value
+void GuiSetStyle(int control, int property, int value)
+{
+ if (!guiStyleLoaded) GuiLoadStyleDefault();
+ guiStyle[control*(RAYGUI_MAX_PROPS_BASE + RAYGUI_MAX_PROPS_EXTENDED) + property] = value;
+
+ // Default properties are propagated to all controls
+ if ((control == 0) && (property < RAYGUI_MAX_PROPS_BASE))
+ {
+ for (int i = 1; i < RAYGUI_MAX_CONTROLS; i++) guiStyle[i*(RAYGUI_MAX_PROPS_BASE + RAYGUI_MAX_PROPS_EXTENDED) + property] = value;
+ }
+}
+
+// Get control style property value
+int GuiGetStyle(int control, int property)
+{
+ if (!guiStyleLoaded) GuiLoadStyleDefault();
+ return guiStyle[control*(RAYGUI_MAX_PROPS_BASE + RAYGUI_MAX_PROPS_EXTENDED) + property];
+}
+
+//----------------------------------------------------------------------------------
+// Gui Controls Functions Definition
+//----------------------------------------------------------------------------------
+
+// Window Box control
+int GuiWindowBox(Rectangle bounds, const char *title)
+{
+ // Window title bar height (including borders)
+ // NOTE: This define is also used by GuiMessageBox() and GuiTextInputBox()
+ #if !defined(RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT)
+ #define RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT 24
+ #endif
+
+ #if !defined(RAYGUI_WINDOWBOX_CLOSEBUTTON_HEIGHT)
+ #define RAYGUI_WINDOWBOX_CLOSEBUTTON_HEIGHT 18
+ #endif
+
+ int result = 0;
+ //GuiState state = guiState;
+
+ int statusBarHeight = RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT;
+
+ Rectangle statusBar = { bounds.x, bounds.y, bounds.width, (float)statusBarHeight };
+ if (bounds.height < statusBarHeight*2.0f) bounds.height = statusBarHeight*2.0f;
+
+ const float vPadding = statusBarHeight/2.0f - RAYGUI_WINDOWBOX_CLOSEBUTTON_HEIGHT/2.0f;
+ Rectangle windowPanel = { bounds.x, bounds.y + (float)statusBarHeight - 1, bounds.width, bounds.height - (float)statusBarHeight + 1 };
+ Rectangle closeButtonRec = { statusBar.x + statusBar.width - GuiGetStyle(STATUSBAR, BORDER_WIDTH) - RAYGUI_WINDOWBOX_CLOSEBUTTON_HEIGHT - vPadding,
+ statusBar.y + vPadding, RAYGUI_WINDOWBOX_CLOSEBUTTON_HEIGHT, RAYGUI_WINDOWBOX_CLOSEBUTTON_HEIGHT };
+
+ // Update control
+ //--------------------------------------------------------------------
+ // NOTE: Logic is directly managed by button
+ //--------------------------------------------------------------------
+
+ // Draw control
+ //--------------------------------------------------------------------
+ GuiStatusBar(statusBar, title); // Draw window header as status bar
+ GuiPanel(windowPanel, NULL); // Draw window base
+
+ // Draw window close button
+ int tempBorderWidth = GuiGetStyle(BUTTON, BORDER_WIDTH);
+ int tempTextAlignment = GuiGetStyle(BUTTON, TEXT_ALIGNMENT);
+ GuiSetStyle(BUTTON, BORDER_WIDTH, 1);
+ GuiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER);
+#if defined(RAYGUI_NO_ICONS)
+ result = GuiButton(closeButtonRec, "x");
+#else
+ result = GuiButton(closeButtonRec, GuiIconText(ICON_CROSS_SMALL, NULL));
+#endif
+ GuiSetStyle(BUTTON, BORDER_WIDTH, tempBorderWidth);
+ GuiSetStyle(BUTTON, TEXT_ALIGNMENT, tempTextAlignment);
+ //--------------------------------------------------------------------
+
+ return result; // Window close button clicked: result = 1
+}
+
+// Group Box control with text name
+int GuiGroupBox(Rectangle bounds, const char *text)
+{
+ #if !defined(RAYGUI_GROUPBOX_LINE_THICK)
+ #define RAYGUI_GROUPBOX_LINE_THICK 1
+ #endif
+
+ int result = 0;
+ GuiState state = guiState;
+
+ // Draw control
+ //--------------------------------------------------------------------
+ GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y, RAYGUI_GROUPBOX_LINE_THICK, bounds.height }, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? (int)BORDER_COLOR_DISABLED : (int)LINE_COLOR)));
+ GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + bounds.height - 1, bounds.width, RAYGUI_GROUPBOX_LINE_THICK }, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? (int)BORDER_COLOR_DISABLED : (int)LINE_COLOR)));
+ GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - 1, bounds.y, RAYGUI_GROUPBOX_LINE_THICK, bounds.height }, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? (int)BORDER_COLOR_DISABLED : (int)LINE_COLOR)));
+
+ GuiLine(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y - GuiGetStyle(DEFAULT, TEXT_SIZE)/2, bounds.width, (float)GuiGetStyle(DEFAULT, TEXT_SIZE) }, text);
+ //--------------------------------------------------------------------
+
+ return result;
+}
+
+// Line control
+int GuiLine(Rectangle bounds, const char *text)
+{
+ #if !defined(RAYGUI_LINE_MARGIN_TEXT)
+ #define RAYGUI_LINE_MARGIN_TEXT 12
+ #endif
+ #if !defined(RAYGUI_LINE_TEXT_PADDING)
+ #define RAYGUI_LINE_TEXT_PADDING 4
+ #endif
+
+ int result = 0;
+ GuiState state = guiState;
+
+ Color color = GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? (int)BORDER_COLOR_DISABLED : (int)LINE_COLOR));
+
+ // Draw control
+ //--------------------------------------------------------------------
+ if (text == NULL) GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + bounds.height/2, bounds.width, 1 }, 0, BLANK, color);
+ else
+ {
+ Rectangle textBounds = { 0 };
+ textBounds.width = (float)GuiGetTextWidth(text) + 2;
+ textBounds.height = bounds.height;
+ textBounds.x = bounds.x + RAYGUI_LINE_MARGIN_TEXT;
+ textBounds.y = bounds.y;
+
+ // Draw line with embedded text label: "--- text --------------"
+ GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + bounds.height/2, RAYGUI_LINE_MARGIN_TEXT - RAYGUI_LINE_TEXT_PADDING, 1 }, 0, BLANK, color);
+ GuiDrawText(text, textBounds, TEXT_ALIGN_LEFT, color);
+ GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + 12 + textBounds.width + 4, bounds.y + bounds.height/2, bounds.width - textBounds.width - RAYGUI_LINE_MARGIN_TEXT - RAYGUI_LINE_TEXT_PADDING, 1 }, 0, BLANK, color);
+ }
+ //--------------------------------------------------------------------
+
+ return result;
+}
+
+// Panel control
+int GuiPanel(Rectangle bounds, const char *text)
+{
+ #if !defined(RAYGUI_PANEL_BORDER_WIDTH)
+ #define RAYGUI_PANEL_BORDER_WIDTH 1
+ #endif
+
+ int result = 0;
+ GuiState state = guiState;
+
+ // Text will be drawn as a header bar (if provided)
+ Rectangle statusBar = { bounds.x, bounds.y, bounds.width, (float)RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT };
+ if ((text != NULL) && (bounds.height < RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT*2.0f)) bounds.height = RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT*2.0f;
+
+ if (text != NULL)
+ {
+ // Move panel bounds after the header bar
+ bounds.y += (float)RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - 1;
+ bounds.height -= (float)RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - 1;
+ }
+
+ // Draw control
+ //--------------------------------------------------------------------
+ if (text != NULL) GuiStatusBar(statusBar, text); // Draw panel header as status bar
+
+ GuiDrawRectangle(bounds, RAYGUI_PANEL_BORDER_WIDTH, GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? (int)BORDER_COLOR_DISABLED : (int)LINE_COLOR)),
+ GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? (int)BASE_COLOR_DISABLED : (int)BACKGROUND_COLOR)));
+ //--------------------------------------------------------------------
+
+ return result;
+}
+
+// Tab Bar control
+// NOTE: Using GuiToggle() for the TABS
+int GuiTabBar(Rectangle bounds, const char **text, int count, int *active)
+{
+ #define RAYGUI_TABBAR_ITEM_WIDTH 148
+
+ int result = -1;
+ //GuiState state = guiState;
+
+ Rectangle tabBounds = { bounds.x, bounds.y, RAYGUI_TABBAR_ITEM_WIDTH, bounds.height };
+
+ if (*active < 0) *active = 0;
+ else if (*active > count - 1) *active = count - 1;
+
+ int offsetX = 0; // Required in case tabs go out of screen
+ offsetX = (*active + 2)*RAYGUI_TABBAR_ITEM_WIDTH - GetScreenWidth();
+ if (offsetX < 0) offsetX = 0;
+
+ bool toggle = false; // Required for individual toggles
+
+ // Draw control
+ //--------------------------------------------------------------------
+ for (int i = 0; i < count; i++)
+ {
+ tabBounds.x = bounds.x + (RAYGUI_TABBAR_ITEM_WIDTH + 4)*i - offsetX;
+
+ if (tabBounds.x < GetScreenWidth())
+ {
+ // Draw tabs as toggle controls
+ int textAlignment = GuiGetStyle(TOGGLE, TEXT_ALIGNMENT);
+ int textPadding = GuiGetStyle(TOGGLE, TEXT_PADDING);
+ GuiSetStyle(TOGGLE, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT);
+ GuiSetStyle(TOGGLE, TEXT_PADDING, 8);
+
+ if (i == (*active))
+ {
+ toggle = true;
+ GuiToggle(tabBounds, text[i], &toggle);
+ }
+ else
+ {
+ toggle = false;
+ GuiToggle(tabBounds, text[i], &toggle);
+ if (toggle) *active = i;
+ }
+
+ // Close tab with middle mouse button pressed
+ if (CheckCollisionPointRec(GetMousePosition(), tabBounds) && IsMouseButtonPressed(MOUSE_MIDDLE_BUTTON)) result = i;
+
+ GuiSetStyle(TOGGLE, TEXT_PADDING, textPadding);
+ GuiSetStyle(TOGGLE, TEXT_ALIGNMENT, textAlignment);
+
+ // Draw tab close button
+ // NOTE: Only draw close button for current tab: if (CheckCollisionPointRec(mousePosition, tabBounds))
+ int tempBorderWidth = GuiGetStyle(BUTTON, BORDER_WIDTH);
+ int tempTextAlignment = GuiGetStyle(BUTTON, TEXT_ALIGNMENT);
+ GuiSetStyle(BUTTON, BORDER_WIDTH, 1);
+ GuiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER);
+#if defined(RAYGUI_NO_ICONS)
+ if (GuiButton(RAYGUI_CLITERAL(Rectangle){ tabBounds.x + tabBounds.width - 14 - 5, tabBounds.y + 5, 14, 14 }, "x")) result = i;
+#else
+ if (GuiButton(RAYGUI_CLITERAL(Rectangle){ tabBounds.x + tabBounds.width - 14 - 5, tabBounds.y + 5, 14, 14 }, GuiIconText(ICON_CROSS_SMALL, NULL))) result = i;
+#endif
+ GuiSetStyle(BUTTON, BORDER_WIDTH, tempBorderWidth);
+ GuiSetStyle(BUTTON, TEXT_ALIGNMENT, tempTextAlignment);
+ }
+ }
+
+ // Draw tab-bar bottom line
+ GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + bounds.height - 1, bounds.width, 1 }, 0, BLANK, GetColor(GuiGetStyle(TOGGLE, BORDER_COLOR_NORMAL)));
+ //--------------------------------------------------------------------
+
+ return result; // Return as result the current TAB closing requested
+}
+
+// Scroll Panel control
+int GuiScrollPanel(Rectangle bounds, const char *text, Rectangle content, Vector2 *scroll, Rectangle *view)
+{
+ #define RAYGUI_MIN_SCROLLBAR_WIDTH 40
+ #define RAYGUI_MIN_SCROLLBAR_HEIGHT 40
+ #define RAYGUI_MIN_MOUSE_WHEEL_SPEED 20
+
+ int result = 0;
+ GuiState state = guiState;
+
+ Rectangle temp = { 0 };
+ if (view == NULL) view = &temp;
+
+ Vector2 scrollPos = { 0.0f, 0.0f };
+ if (scroll != NULL) scrollPos = *scroll;
+
+ // Text will be drawn as a header bar (if provided)
+ Rectangle statusBar = { bounds.x, bounds.y, bounds.width, (float)RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT };
+ if (bounds.height < RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT*2.0f) bounds.height = RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT*2.0f;
+
+ if (text != NULL)
+ {
+ // Move panel bounds after the header bar
+ bounds.y += (float)RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - 1;
+ bounds.height -= (float)RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT + 1;
+ }
+
+ bool hasHorizontalScrollBar = (content.width > bounds.width - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH))? true : false;
+ bool hasVerticalScrollBar = (content.height > bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH))? true : false;
+
+ // Recheck to account for the other scrollbar being visible
+ if (!hasHorizontalScrollBar) hasHorizontalScrollBar = (hasVerticalScrollBar && (content.width > (bounds.width - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH))))? true : false;
+ if (!hasVerticalScrollBar) hasVerticalScrollBar = (hasHorizontalScrollBar && (content.height > (bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH))))? true : false;
+
+ int horizontalScrollBarWidth = hasHorizontalScrollBar? GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH) : 0;
+ int verticalScrollBarWidth = hasVerticalScrollBar? GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH) : 0;
+ Rectangle horizontalScrollBar = {
+ (float)((GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? (float)bounds.x + verticalScrollBarWidth : (float)bounds.x) + GuiGetStyle(DEFAULT, BORDER_WIDTH),
+ (float)bounds.y + bounds.height - horizontalScrollBarWidth - GuiGetStyle(DEFAULT, BORDER_WIDTH),
+ (float)bounds.width - verticalScrollBarWidth - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH),
+ (float)horizontalScrollBarWidth
+ };
+ Rectangle verticalScrollBar = {
+ (float)((GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? (float)bounds.x + GuiGetStyle(DEFAULT, BORDER_WIDTH) : (float)bounds.x + bounds.width - verticalScrollBarWidth - GuiGetStyle(DEFAULT, BORDER_WIDTH)),
+ (float)bounds.y + GuiGetStyle(DEFAULT, BORDER_WIDTH),
+ (float)verticalScrollBarWidth,
+ (float)bounds.height - horizontalScrollBarWidth - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH)
+ };
+
+ // Make sure scroll bars have a minimum width/height
+ if (horizontalScrollBar.width < RAYGUI_MIN_SCROLLBAR_WIDTH) horizontalScrollBar.width = RAYGUI_MIN_SCROLLBAR_WIDTH;
+ if (verticalScrollBar.height < RAYGUI_MIN_SCROLLBAR_HEIGHT) verticalScrollBar.height = RAYGUI_MIN_SCROLLBAR_HEIGHT;
+
+ // Calculate view area (area without the scrollbars)
+ *view = (GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)?
+ RAYGUI_CLITERAL(Rectangle){ bounds.x + verticalScrollBarWidth + GuiGetStyle(DEFAULT, BORDER_WIDTH), bounds.y + GuiGetStyle(DEFAULT, BORDER_WIDTH), bounds.width - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - verticalScrollBarWidth, bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - horizontalScrollBarWidth } :
+ RAYGUI_CLITERAL(Rectangle){ bounds.x + GuiGetStyle(DEFAULT, BORDER_WIDTH), bounds.y + GuiGetStyle(DEFAULT, BORDER_WIDTH), bounds.width - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - verticalScrollBarWidth, bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - horizontalScrollBarWidth };
+
+ // Clip view area to the actual content size
+ if (view->width > content.width) view->width = content.width;
+ if (view->height > content.height) view->height = content.height;
+
+ float horizontalMin = hasHorizontalScrollBar? ((GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? (float)-verticalScrollBarWidth : 0) - (float)GuiGetStyle(DEFAULT, BORDER_WIDTH) : (((float)GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? (float)-verticalScrollBarWidth : 0) - (float)GuiGetStyle(DEFAULT, BORDER_WIDTH);
+ float horizontalMax = hasHorizontalScrollBar? content.width - bounds.width + (float)verticalScrollBarWidth + GuiGetStyle(DEFAULT, BORDER_WIDTH) - (((float)GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? (float)verticalScrollBarWidth : 0) : (float)-GuiGetStyle(DEFAULT, BORDER_WIDTH);
+ float verticalMin = hasVerticalScrollBar? 0.0f : -1.0f;
+ float verticalMax = hasVerticalScrollBar? content.height - bounds.height + (float)horizontalScrollBarWidth + (float)GuiGetStyle(DEFAULT, BORDER_WIDTH) : (float)-GuiGetStyle(DEFAULT, BORDER_WIDTH);
+
+ // Update control
+ //--------------------------------------------------------------------
+ if ((state != STATE_DISABLED) && !guiLocked)
+ {
+ Vector2 mousePoint = GetMousePosition();
+
+ // Check button state
+ if (CheckCollisionPointRec(mousePoint, bounds))
+ {
+ if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED;
+ else state = STATE_FOCUSED;
+
+#if defined(SUPPORT_SCROLLBAR_KEY_INPUT)
+ if (hasHorizontalScrollBar)
+ {
+ if (IsKeyDown(KEY_RIGHT)) scrollPos.x -= GuiGetStyle(SCROLLBAR, SCROLL_SPEED);
+ if (IsKeyDown(KEY_LEFT)) scrollPos.x += GuiGetStyle(SCROLLBAR, SCROLL_SPEED);
+ }
+
+ if (hasVerticalScrollBar)
+ {
+ if (IsKeyDown(KEY_DOWN)) scrollPos.y -= GuiGetStyle(SCROLLBAR, SCROLL_SPEED);
+ if (IsKeyDown(KEY_UP)) scrollPos.y += GuiGetStyle(SCROLLBAR, SCROLL_SPEED);
+ }
+#endif
+ float wheelMove = GetMouseWheelMove();
+
+ // Set scrolling speed with mouse wheel based on ratio between bounds and content
+ Vector2 mouseWheelSpeed = { content.width/bounds.width, content.height/bounds.height };
+ if (mouseWheelSpeed.x < RAYGUI_MIN_MOUSE_WHEEL_SPEED) mouseWheelSpeed.x = RAYGUI_MIN_MOUSE_WHEEL_SPEED;
+ if (mouseWheelSpeed.y < RAYGUI_MIN_MOUSE_WHEEL_SPEED) mouseWheelSpeed.y = RAYGUI_MIN_MOUSE_WHEEL_SPEED;
+
+ // Horizontal and vertical scrolling with mouse wheel
+ if (hasHorizontalScrollBar && (IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_LEFT_SHIFT))) scrollPos.x += wheelMove*mouseWheelSpeed.x;
+ else scrollPos.y += wheelMove*mouseWheelSpeed.y; // Vertical scroll
+ }
+ }
+
+ // Normalize scroll values
+ if (scrollPos.x > -horizontalMin) scrollPos.x = -horizontalMin;
+ if (scrollPos.x < -horizontalMax) scrollPos.x = -horizontalMax;
+ if (scrollPos.y > -verticalMin) scrollPos.y = -verticalMin;
+ if (scrollPos.y < -verticalMax) scrollPos.y = -verticalMax;
+ //--------------------------------------------------------------------
+
+ // Draw control
+ //--------------------------------------------------------------------
+ if (text != NULL) GuiStatusBar(statusBar, text); // Draw panel header as status bar
+
+ GuiDrawRectangle(bounds, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR))); // Draw background
+
+ // Save size of the scrollbar slider
+ const int slider = GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE);
+
+ // Draw horizontal scrollbar if visible
+ if (hasHorizontalScrollBar)
+ {
+ // Change scrollbar slider size to show the diff in size between the content width and the widget width
+ GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, (int)(((bounds.width - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - verticalScrollBarWidth)/(int)content.width)*((int)bounds.width - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - verticalScrollBarWidth)));
+ scrollPos.x = (float)-GuiScrollBar(horizontalScrollBar, (int)-scrollPos.x, (int)horizontalMin, (int)horizontalMax);
+ }
+ else scrollPos.x = 0.0f;
+
+ // Draw vertical scrollbar if visible
+ if (hasVerticalScrollBar)
+ {
+ // Change scrollbar slider size to show the diff in size between the content height and the widget height
+ GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, (int)(((bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - horizontalScrollBarWidth)/(int)content.height)*((int)bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - horizontalScrollBarWidth)));
+ scrollPos.y = (float)-GuiScrollBar(verticalScrollBar, (int)-scrollPos.y, (int)verticalMin, (int)verticalMax);
+ }
+ else scrollPos.y = 0.0f;
+
+ // Draw detail corner rectangle if both scroll bars are visible
+ if (hasHorizontalScrollBar && hasVerticalScrollBar)
+ {
+ Rectangle corner = { (GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? (bounds.x + GuiGetStyle(DEFAULT, BORDER_WIDTH) + 2) : (horizontalScrollBar.x + horizontalScrollBar.width + 2), verticalScrollBar.y + verticalScrollBar.height + 2, (float)horizontalScrollBarWidth - 4, (float)verticalScrollBarWidth - 4 };
+ GuiDrawRectangle(corner, 0, BLANK, GetColor(GuiGetStyle(LISTVIEW, TEXT + (state*3))));
+ }
+
+ // Draw scrollbar lines depending on current state
+ GuiDrawRectangle(bounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER + (state*3))), BLANK);
+
+ // Set scrollbar slider size back to the way it was before
+ GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, slider);
+ //--------------------------------------------------------------------
+
+ if (scroll != NULL) *scroll = scrollPos;
+
+ return result;
+}
+
+// Label control
+int GuiLabel(Rectangle bounds, const char *text)
+{
+ int result = 0;
+ GuiState state = guiState;
+
+ // Update control
+ //--------------------------------------------------------------------
+ //...
+ //--------------------------------------------------------------------
+
+ // Draw control
+ //--------------------------------------------------------------------
+ GuiDrawText(text, GetTextBounds(LABEL, bounds), GuiGetStyle(LABEL, TEXT_ALIGNMENT), GetColor(GuiGetStyle(LABEL, TEXT + (state*3))));
+ //--------------------------------------------------------------------
+
+ return result;
+}
+
+// Button control, returns true when clicked
+int GuiButton(Rectangle bounds, const char *text)
+{
+ int result = 0;
+ GuiState state = guiState;
+
+ // Update control
+ //--------------------------------------------------------------------
+ if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode)
+ {
+ Vector2 mousePoint = GetMousePosition();
+
+ // Check button state
+ if (CheckCollisionPointRec(mousePoint, bounds))
+ {
+ if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED;
+ else state = STATE_FOCUSED;
+
+ if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) result = 1;
+ }
+ }
+ //--------------------------------------------------------------------
+
+ // Draw control
+ //--------------------------------------------------------------------
+ GuiDrawRectangle(bounds, GuiGetStyle(BUTTON, BORDER_WIDTH), GetColor(GuiGetStyle(BUTTON, BORDER + (state*3))), GetColor(GuiGetStyle(BUTTON, BASE + (state*3))));
+ GuiDrawText(text, GetTextBounds(BUTTON, bounds), GuiGetStyle(BUTTON, TEXT_ALIGNMENT), GetColor(GuiGetStyle(BUTTON, TEXT + (state*3))));
+
+ if (state == STATE_FOCUSED) GuiTooltip(bounds);
+ //------------------------------------------------------------------
+
+ return result; // Button pressed: result = 1
+}
+
+// Label button control
+int GuiLabelButton(Rectangle bounds, const char *text)
+{
+ GuiState state = guiState;
+ bool pressed = false;
+
+ // NOTE: We force bounds.width to be all text
+ float textWidth = (float)GuiGetTextWidth(text);
+ if ((bounds.width - 2*GuiGetStyle(LABEL, BORDER_WIDTH) - 2*GuiGetStyle(LABEL, TEXT_PADDING)) < textWidth) bounds.width = textWidth + 2*GuiGetStyle(LABEL, BORDER_WIDTH) + 2*GuiGetStyle(LABEL, TEXT_PADDING) + 2;
+
+ // Update control
+ //--------------------------------------------------------------------
+ if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode)
+ {
+ Vector2 mousePoint = GetMousePosition();
+
+ // Check checkbox state
+ if (CheckCollisionPointRec(mousePoint, bounds))
+ {
+ if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED;
+ else state = STATE_FOCUSED;
+
+ if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) pressed = true;
+ }
+ }
+ //--------------------------------------------------------------------
+
+ // Draw control
+ //--------------------------------------------------------------------
+ GuiDrawText(text, GetTextBounds(LABEL, bounds), GuiGetStyle(LABEL, TEXT_ALIGNMENT), GetColor(GuiGetStyle(LABEL, TEXT + (state*3))));
+ //--------------------------------------------------------------------
+
+ return pressed;
+}
+
+// Toggle Button control
+int GuiToggle(Rectangle bounds, const char *text, bool *active)
+{
+ int result = 0;
+ GuiState state = guiState;
+
+ bool temp = false;
+ if (active == NULL) active = &temp;
+
+ // Update control
+ //--------------------------------------------------------------------
+ if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode)
+ {
+ Vector2 mousePoint = GetMousePosition();
+
+ // Check toggle button state
+ if (CheckCollisionPointRec(mousePoint, bounds))
+ {
+ if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED;
+ else if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON))
+ {
+ state = STATE_NORMAL;
+ *active = !(*active);
+ }
+ else state = STATE_FOCUSED;
+ }
+ }
+ //--------------------------------------------------------------------
+
+ // Draw control
+ //--------------------------------------------------------------------
+ if (state == STATE_NORMAL)
+ {
+ GuiDrawRectangle(bounds, GuiGetStyle(TOGGLE, BORDER_WIDTH), GetColor(GuiGetStyle(TOGGLE, ((*active)? BORDER_COLOR_PRESSED : (BORDER + state*3)))), GetColor(GuiGetStyle(TOGGLE, ((*active)? BASE_COLOR_PRESSED : (BASE + state*3)))));
+ GuiDrawText(text, GetTextBounds(TOGGLE, bounds), GuiGetStyle(TOGGLE, TEXT_ALIGNMENT), GetColor(GuiGetStyle(TOGGLE, ((*active)? TEXT_COLOR_PRESSED : (TEXT + state*3)))));
+ }
+ else
+ {
+ GuiDrawRectangle(bounds, GuiGetStyle(TOGGLE, BORDER_WIDTH), GetColor(GuiGetStyle(TOGGLE, BORDER + state*3)), GetColor(GuiGetStyle(TOGGLE, BASE + state*3)));
+ GuiDrawText(text, GetTextBounds(TOGGLE, bounds), GuiGetStyle(TOGGLE, TEXT_ALIGNMENT), GetColor(GuiGetStyle(TOGGLE, TEXT + state*3)));
+ }
+
+ if (state == STATE_FOCUSED) GuiTooltip(bounds);
+ //--------------------------------------------------------------------
+
+ return result;
+}
+
+// Toggle Group control
+int GuiToggleGroup(Rectangle bounds, const char *text, int *active)
+{
+ #if !defined(RAYGUI_TOGGLEGROUP_MAX_ITEMS)
+ #define RAYGUI_TOGGLEGROUP_MAX_ITEMS 32
+ #endif
+
+ int result = 0;
+ float initBoundsX = bounds.x;
+
+ int temp = 0;
+ if (active == NULL) active = &temp;
+
+ bool toggle = false; // Required for individual toggles
+
+ // Get substrings items from text (items pointers)
+ int rows[RAYGUI_TOGGLEGROUP_MAX_ITEMS] = { 0 };
+ int itemCount = 0;
+ const char **items = GuiTextSplit(text, ';', &itemCount, rows);
+
+ int prevRow = rows[0];
+
+ for (int i = 0; i < itemCount; i++)
+ {
+ if (prevRow != rows[i])
+ {
+ bounds.x = initBoundsX;
+ bounds.y += (bounds.height + GuiGetStyle(TOGGLE, GROUP_PADDING));
+ prevRow = rows[i];
+ }
+
+ if (i == (*active))
+ {
+ toggle = true;
+ GuiToggle(bounds, items[i], &toggle);
+ }
+ else
+ {
+ toggle = false;
+ GuiToggle(bounds, items[i], &toggle);
+ if (toggle) *active = i;
+ }
+
+ bounds.x += (bounds.width + GuiGetStyle(TOGGLE, GROUP_PADDING));
+ }
+
+ return result;
+}
+
+// Toggle Slider control extended
+int GuiToggleSlider(Rectangle bounds, const char *text, int *active)
+{
+ int result = 0;
+ GuiState state = guiState;
+
+ int temp = 0;
+ if (active == NULL) active = &temp;
+
+ //bool toggle = false; // Required for individual toggles
+
+ // Get substrings items from text (items pointers)
+ int itemCount = 0;
+ const char **items = NULL;
+
+ if (text != NULL) items = GuiTextSplit(text, ';', &itemCount, NULL);
+
+ Rectangle slider = {
+ 0, // Calculated later depending on the active toggle
+ bounds.y + GuiGetStyle(SLIDER, BORDER_WIDTH) + GuiGetStyle(SLIDER, SLIDER_PADDING),
+ (bounds.width - 2*GuiGetStyle(SLIDER, BORDER_WIDTH) - (itemCount + 1)*GuiGetStyle(SLIDER, SLIDER_PADDING))/itemCount,
+ bounds.height - 2*GuiGetStyle(SLIDER, BORDER_WIDTH) - 2*GuiGetStyle(SLIDER, SLIDER_PADDING) };
+
+ // Update control
+ //--------------------------------------------------------------------
+ if ((state != STATE_DISABLED) && !guiLocked)
+ {
+ Vector2 mousePoint = GetMousePosition();
+
+ if (CheckCollisionPointRec(mousePoint, bounds))
+ {
+ if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED;
+ else if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON))
+ {
+ state = STATE_PRESSED;
+ (*active)++;
+ result = 1;
+ }
+ else state = STATE_FOCUSED;
+ }
+
+ if ((*active) && (state != STATE_FOCUSED)) state = STATE_PRESSED;
+ }
+
+ if (*active >= itemCount) *active = 0;
+ slider.x = bounds.x + GuiGetStyle(SLIDER, BORDER_WIDTH) + (*active + 1)*GuiGetStyle(SLIDER, SLIDER_PADDING) + (*active)*slider.width;
+ //--------------------------------------------------------------------
+
+ // Draw control
+ //--------------------------------------------------------------------
+ GuiDrawRectangle(bounds, GuiGetStyle(SLIDER, BORDER_WIDTH), GetColor(GuiGetStyle(TOGGLE, BORDER + (state*3))),
+ GetColor(GuiGetStyle(TOGGLE, BASE_COLOR_NORMAL)));
+
+ // Draw internal slider
+ if (state == STATE_NORMAL) GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, BASE_COLOR_PRESSED)));
+ else if (state == STATE_FOCUSED) GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, BASE_COLOR_FOCUSED)));
+ else if (state == STATE_PRESSED) GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, BASE_COLOR_PRESSED)));
+
+ // Draw text in slider
+ if (text != NULL)
+ {
+ Rectangle textBounds = { 0 };
+ textBounds.width = (float)GuiGetTextWidth(text);
+ textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE);
+ textBounds.x = slider.x + slider.width/2 - textBounds.width/2;
+ textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2;
+
+ GuiDrawText(items[*active], textBounds, GuiGetStyle(TOGGLE, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(TOGGLE, TEXT + (state*3))), guiAlpha));
+ }
+ //--------------------------------------------------------------------
+
+ return result;
+}
+
+// Check Box control, returns 1 when state changed
+int GuiCheckBox(Rectangle bounds, const char *text, bool *checked)
+{
+ int result = 0;
+ GuiState state = guiState;
+
+ bool temp = false;
+ if (checked == NULL) checked = &temp;
+
+ Rectangle textBounds = { 0 };
+
+ if (text != NULL)
+ {
+ textBounds.width = (float)GuiGetTextWidth(text) + 2;
+ textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE);
+ textBounds.x = bounds.x + bounds.width + GuiGetStyle(CHECKBOX, TEXT_PADDING);
+ textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2;
+ if (GuiGetStyle(CHECKBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_LEFT) textBounds.x = bounds.x - textBounds.width - GuiGetStyle(CHECKBOX, TEXT_PADDING);
+ }
+
+ // Update control
+ //--------------------------------------------------------------------
+ if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode)
+ {
+ Vector2 mousePoint = GetMousePosition();
+
+ Rectangle totalBounds = {
+ (GuiGetStyle(CHECKBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_LEFT)? textBounds.x : bounds.x,
+ bounds.y,
+ bounds.width + textBounds.width + GuiGetStyle(CHECKBOX, TEXT_PADDING),
+ bounds.height,
+ };
+
+ // Check checkbox state
+ if (CheckCollisionPointRec(mousePoint, totalBounds))
+ {
+ if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED;
+ else state = STATE_FOCUSED;
+
+ if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON))
+ {
+ *checked = !(*checked);
+ result = 1;
+ }
+ }
+ }
+ //--------------------------------------------------------------------
+
+ // Draw control
+ //--------------------------------------------------------------------
+ GuiDrawRectangle(bounds, GuiGetStyle(CHECKBOX, BORDER_WIDTH), GetColor(GuiGetStyle(CHECKBOX, BORDER + (state*3))), BLANK);
+
+ if (*checked)
+ {
+ Rectangle check = { bounds.x + GuiGetStyle(CHECKBOX, BORDER_WIDTH) + GuiGetStyle(CHECKBOX, CHECK_PADDING),
+ bounds.y + GuiGetStyle(CHECKBOX, BORDER_WIDTH) + GuiGetStyle(CHECKBOX, CHECK_PADDING),
+ bounds.width - 2*(GuiGetStyle(CHECKBOX, BORDER_WIDTH) + GuiGetStyle(CHECKBOX, CHECK_PADDING)),
+ bounds.height - 2*(GuiGetStyle(CHECKBOX, BORDER_WIDTH) + GuiGetStyle(CHECKBOX, CHECK_PADDING)) };
+ GuiDrawRectangle(check, 0, BLANK, GetColor(GuiGetStyle(CHECKBOX, TEXT + state*3)));
+ }
+
+ GuiDrawText(text, textBounds, (GuiGetStyle(CHECKBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_RIGHT)? TEXT_ALIGN_LEFT : TEXT_ALIGN_RIGHT, GetColor(GuiGetStyle(LABEL, TEXT + (state*3))));
+ //--------------------------------------------------------------------
+
+ return result;
+}
+
+// Combo Box control
+int GuiComboBox(Rectangle bounds, const char *text, int *active)
+{
+ int result = 0;
+ GuiState state = guiState;
+
+ int temp = 0;
+ if (active == NULL) active = &temp;
+
+ bounds.width -= (GuiGetStyle(COMBOBOX, COMBO_BUTTON_WIDTH) + GuiGetStyle(COMBOBOX, COMBO_BUTTON_SPACING));
+
+ Rectangle selector = { (float)bounds.x + bounds.width + GuiGetStyle(COMBOBOX, COMBO_BUTTON_SPACING),
+ (float)bounds.y, (float)GuiGetStyle(COMBOBOX, COMBO_BUTTON_WIDTH), (float)bounds.height };
+
+ // Get substrings items from text (items pointers, lengths and count)
+ int itemCount = 0;
+ const char **items = GuiTextSplit(text, ';', &itemCount, NULL);
+
+ if (*active < 0) *active = 0;
+ else if (*active > (itemCount - 1)) *active = itemCount - 1;
+
+ // Update control
+ //--------------------------------------------------------------------
+ if ((state != STATE_DISABLED) && !guiLocked && (itemCount > 1) && !guiControlExclusiveMode)
+ {
+ Vector2 mousePoint = GetMousePosition();
+
+ if (CheckCollisionPointRec(mousePoint, bounds) ||
+ CheckCollisionPointRec(mousePoint, selector))
+ {
+ if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
+ {
+ *active += 1;
+ if (*active >= itemCount) *active = 0; // Cyclic combobox
+ }
+
+ if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED;
+ else state = STATE_FOCUSED;
+ }
+ }
+ //--------------------------------------------------------------------
+
+ // Draw control
+ //--------------------------------------------------------------------
+ // Draw combo box main
+ GuiDrawRectangle(bounds, GuiGetStyle(COMBOBOX, BORDER_WIDTH), GetColor(GuiGetStyle(COMBOBOX, BORDER + (state*3))), GetColor(GuiGetStyle(COMBOBOX, BASE + (state*3))));
+ GuiDrawText(items[*active], GetTextBounds(COMBOBOX, bounds), GuiGetStyle(COMBOBOX, TEXT_ALIGNMENT), GetColor(GuiGetStyle(COMBOBOX, TEXT + (state*3))));
+
+ // Draw selector using a custom button
+ // NOTE: BORDER_WIDTH and TEXT_ALIGNMENT forced values
+ int tempBorderWidth = GuiGetStyle(BUTTON, BORDER_WIDTH);
+ int tempTextAlign = GuiGetStyle(BUTTON, TEXT_ALIGNMENT);
+ GuiSetStyle(BUTTON, BORDER_WIDTH, 1);
+ GuiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER);
+
+ GuiButton(selector, TextFormat("%i/%i", *active + 1, itemCount));
+
+ GuiSetStyle(BUTTON, TEXT_ALIGNMENT, tempTextAlign);
+ GuiSetStyle(BUTTON, BORDER_WIDTH, tempBorderWidth);
+ //--------------------------------------------------------------------
+
+ return result;
+}
+
+// Dropdown Box control
+// NOTE: Returns mouse click
+int GuiDropdownBox(Rectangle bounds, const char *text, int *active, bool editMode)
+{
+ int result = 0;
+ GuiState state = guiState;
+
+ int temp = 0;
+ if (active == NULL) active = &temp;
+
+ int itemSelected = *active;
+ int itemFocused = -1;
+
+ int direction = 0; // Dropdown box open direction: down (default)
+ if (GuiGetStyle(DROPDOWNBOX, DROPDOWN_ROLL_UP) == 1) direction = 1; // Up
+
+ // Get substrings items from text (items pointers, lengths and count)
+ int itemCount = 0;
+ const char **items = GuiTextSplit(text, ';', &itemCount, NULL);
+
+ Rectangle boundsOpen = bounds;
+ boundsOpen.height = (itemCount + 1)*(bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING));
+ if (direction == 1) boundsOpen.y -= itemCount*(bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING)) + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING);
+
+ Rectangle itemBounds = bounds;
+
+ // Update control
+ //--------------------------------------------------------------------
+ if ((state != STATE_DISABLED) && (editMode || !guiLocked) && (itemCount > 1) && !guiControlExclusiveMode)
+ {
+ Vector2 mousePoint = GetMousePosition();
+
+ if (editMode)
+ {
+ state = STATE_PRESSED;
+
+ // Check if mouse has been pressed or released outside limits
+ if (!CheckCollisionPointRec(mousePoint, boundsOpen))
+ {
+ if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON) || IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) result = 1;
+ }
+
+ // Check if already selected item has been pressed again
+ if (CheckCollisionPointRec(mousePoint, bounds) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) result = 1;
+
+ // Check focused and selected item
+ for (int i = 0; i < itemCount; i++)
+ {
+ // Update item rectangle y position for next item
+ if (direction == 0) itemBounds.y += (bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING));
+ else itemBounds.y -= (bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING));
+
+ if (CheckCollisionPointRec(mousePoint, itemBounds))
+ {
+ itemFocused = i;
+ if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON))
+ {
+ itemSelected = i;
+ result = 1; // Item selected
+ }
+ break;
+ }
+ }
+
+ itemBounds = bounds;
+ }
+ else
+ {
+ if (CheckCollisionPointRec(mousePoint, bounds))
+ {
+ if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
+ {
+ result = 1;
+ state = STATE_PRESSED;
+ }
+ else state = STATE_FOCUSED;
+ }
+ }
+ }
+ //--------------------------------------------------------------------
+
+ // Draw control
+ //--------------------------------------------------------------------
+ if (editMode) GuiPanel(boundsOpen, NULL);
+
+ GuiDrawRectangle(bounds, GuiGetStyle(DROPDOWNBOX, BORDER_WIDTH), GetColor(GuiGetStyle(DROPDOWNBOX, BORDER + state*3)), GetColor(GuiGetStyle(DROPDOWNBOX, BASE + state*3)));
+ GuiDrawText(items[itemSelected], GetTextBounds(DROPDOWNBOX, bounds), GuiGetStyle(DROPDOWNBOX, TEXT_ALIGNMENT), GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + state*3)));
+
+ if (editMode)
+ {
+ // Draw visible items
+ for (int i = 0; i < itemCount; i++)
+ {
+ // Update item rectangle y position for next item
+ if (direction == 0) itemBounds.y += (bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING));
+ else itemBounds.y -= (bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING));
+
+ if (i == itemSelected)
+ {
+ GuiDrawRectangle(itemBounds, GuiGetStyle(DROPDOWNBOX, BORDER_WIDTH), GetColor(GuiGetStyle(DROPDOWNBOX, BORDER_COLOR_PRESSED)), GetColor(GuiGetStyle(DROPDOWNBOX, BASE_COLOR_PRESSED)));
+ GuiDrawText(items[i], GetTextBounds(DROPDOWNBOX, itemBounds), GuiGetStyle(DROPDOWNBOX, TEXT_ALIGNMENT), GetColor(GuiGetStyle(DROPDOWNBOX, TEXT_COLOR_PRESSED)));
+ }
+ else if (i == itemFocused)
+ {
+ GuiDrawRectangle(itemBounds, GuiGetStyle(DROPDOWNBOX, BORDER_WIDTH), GetColor(GuiGetStyle(DROPDOWNBOX, BORDER_COLOR_FOCUSED)), GetColor(GuiGetStyle(DROPDOWNBOX, BASE_COLOR_FOCUSED)));
+ GuiDrawText(items[i], GetTextBounds(DROPDOWNBOX, itemBounds), GuiGetStyle(DROPDOWNBOX, TEXT_ALIGNMENT), GetColor(GuiGetStyle(DROPDOWNBOX, TEXT_COLOR_FOCUSED)));
+ }
+ else GuiDrawText(items[i], GetTextBounds(DROPDOWNBOX, itemBounds), GuiGetStyle(DROPDOWNBOX, TEXT_ALIGNMENT), GetColor(GuiGetStyle(DROPDOWNBOX, TEXT_COLOR_NORMAL)));
+ }
+ }
+
+ if (!GuiGetStyle(DROPDOWNBOX, DROPDOWN_ARROW_HIDDEN))
+ {
+ // Draw arrows (using icon if available)
+#if defined(RAYGUI_NO_ICONS)
+ GuiDrawText("v", RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - GuiGetStyle(DROPDOWNBOX, ARROW_PADDING), bounds.y + bounds.height/2 - 2, 10, 10 },
+ TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3))));
+#else
+ GuiDrawText(direction? "#121#" : "#120#", RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - GuiGetStyle(DROPDOWNBOX, ARROW_PADDING), bounds.y + bounds.height/2 - 6, 10, 10 },
+ TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3)))); // ICON_ARROW_DOWN_FILL
+#endif
+ }
+ //--------------------------------------------------------------------
+
+ *active = itemSelected;
+
+ // TODO: Use result to return more internal states: mouse-press out-of-bounds, mouse-press over selected-item...
+ return result; // Mouse click: result = 1
+}
+
+// Text Box control
+// NOTE: Returns true on ENTER pressed (useful for data validation)
+int GuiTextBox(Rectangle bounds, char *text, int textSize, bool editMode)
+{
+ #if !defined(RAYGUI_TEXTBOX_AUTO_CURSOR_COOLDOWN)
+ #define RAYGUI_TEXTBOX_AUTO_CURSOR_COOLDOWN 20 // Frames to wait for autocursor movement
+ #endif
+ #if !defined(RAYGUI_TEXTBOX_AUTO_CURSOR_DELAY)
+ #define RAYGUI_TEXTBOX_AUTO_CURSOR_DELAY 1 // Frames delay for autocursor movement
+ #endif
+
+ int result = 0;
+ GuiState state = guiState;
+
+ bool multiline = false; // TODO: Consider multiline text input
+ int wrapMode = GuiGetStyle(DEFAULT, TEXT_WRAP_MODE);
+
+ Rectangle textBounds = GetTextBounds(TEXTBOX, bounds);
+ int textLength = (text != NULL)? (int)strlen(text) : 0; // Get current text length
+ int thisCursorIndex = textBoxCursorIndex;
+ if (thisCursorIndex > textLength) thisCursorIndex = textLength;
+ int textWidth = GuiGetTextWidth(text) - GuiGetTextWidth(text + thisCursorIndex);
+ int textIndexOffset = 0; // Text index offset to start drawing in the box
+
+ // Cursor rectangle
+ // NOTE: Position X value should be updated
+ Rectangle cursor = {
+ textBounds.x + textWidth + GuiGetStyle(DEFAULT, TEXT_SPACING),
+ textBounds.y + textBounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE),
+ 2,
+ (float)GuiGetStyle(DEFAULT, TEXT_SIZE)*2
+ };
+
+ if (cursor.height >= bounds.height) cursor.height = bounds.height - GuiGetStyle(TEXTBOX, BORDER_WIDTH)*2;
+ if (cursor.y < (bounds.y + GuiGetStyle(TEXTBOX, BORDER_WIDTH))) cursor.y = bounds.y + GuiGetStyle(TEXTBOX, BORDER_WIDTH);
+
+ // Mouse cursor rectangle
+ // NOTE: Initialized outside of screen
+ Rectangle mouseCursor = cursor;
+ mouseCursor.x = -1;
+ mouseCursor.width = 1;
+
+ // Blink-cursor frame counter
+ //if (!autoCursorMode) blinkCursorFrameCounter++;
+ //else blinkCursorFrameCounter = 0;
+
+ // Update control
+ //--------------------------------------------------------------------
+ // WARNING: Text editing is only supported under certain conditions:
+ if ((state != STATE_DISABLED) && // Control not disabled
+ !GuiGetStyle(TEXTBOX, TEXT_READONLY) && // TextBox not on read-only mode
+ !guiLocked && // Gui not locked
+ !guiControlExclusiveMode && // No gui slider on dragging
+ (wrapMode == TEXT_WRAP_NONE)) // No wrap mode
+ {
+ Vector2 mousePosition = GetMousePosition();
+
+ if (editMode)
+ {
+ // GLOBAL: Auto-cursor movement logic
+ // NOTE: Keystrokes are handled repeatedly when button is held down for some time
+ if (IsKeyDown(KEY_LEFT) || IsKeyDown(KEY_RIGHT) || IsKeyDown(KEY_UP) || IsKeyDown(KEY_DOWN) || IsKeyDown(KEY_BACKSPACE) || IsKeyDown(KEY_DELETE)) autoCursorCounter++;
+ else autoCursorCounter = 0;
+
+ bool autoCursorShouldTrigger = (autoCursorCounter > RAYGUI_TEXTBOX_AUTO_CURSOR_COOLDOWN) && ((autoCursorCounter % RAYGUI_TEXTBOX_AUTO_CURSOR_DELAY) == 0);
+
+ state = STATE_PRESSED;
+
+ if (textBoxCursorIndex > textLength) textBoxCursorIndex = textLength;
+
+ // If text does not fit in the textbox and current cursor position is out of bounds,
+ // we add an index offset to text for drawing only what requires depending on cursor
+ while (textWidth >= textBounds.width)
+ {
+ int nextCodepointSize = 0;
+ GetCodepointNext(text + textIndexOffset, &nextCodepointSize);
+
+ textIndexOffset += nextCodepointSize;
+
+ textWidth = GuiGetTextWidth(text + textIndexOffset) - GuiGetTextWidth(text + textBoxCursorIndex);
+ }
+
+ int codepoint = GetCharPressed(); // Get Unicode codepoint
+ if (multiline && IsKeyPressed(KEY_ENTER)) codepoint = (int)'\n';
+
+ // Encode codepoint as UTF-8
+ int codepointSize = 0;
+ const char *charEncoded = CodepointToUTF8(codepoint, &codepointSize);
+
+ // Handle text paste action
+ if (IsKeyPressed(KEY_V) && (IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_RIGHT_CONTROL)))
+ {
+ const char *pasteText = GetClipboardText();
+ if (pasteText != NULL)
+ {
+ int pasteLength = 0;
+ int pasteCodepoint;
+ int pasteCodepointSize;
+
+ // Count how many codepoints to copy, stopping at the first unwanted control character
+ while (true)
+ {
+ pasteCodepoint = GetCodepointNext(pasteText + pasteLength, &pasteCodepointSize);
+ if (textLength + pasteLength + pasteCodepointSize >= textSize) break;
+ if (!(multiline && (pasteCodepoint == (int)'\n')) && !(pasteCodepoint >= 32)) break;
+ pasteLength += pasteCodepointSize;
+ }
+
+ if (pasteLength > 0)
+ {
+ // Move forward data from cursor position
+ for (int i = textLength + pasteLength; i > textBoxCursorIndex; i--) text[i] = text[i - pasteLength];
+
+ // Paste data in at cursor
+ for (int i = 0; i < pasteLength; i++) text[textBoxCursorIndex + i] = pasteText[i];
+
+ textBoxCursorIndex += pasteLength;
+ textLength += pasteLength;
+ text[textLength] = '\0';
+ }
+ }
+ }
+ else if (((multiline && (codepoint == (int)'\n')) || (codepoint >= 32)) && ((textLength + codepointSize) < textSize))
+ {
+ // Adding codepoint to text, at current cursor position
+
+ // Move forward data from cursor position
+ for (int i = (textLength + codepointSize); i > textBoxCursorIndex; i--) text[i] = text[i - codepointSize];
+
+ // Add new codepoint in current cursor position
+ for (int i = 0; i < codepointSize; i++) text[textBoxCursorIndex + i] = charEncoded[i];
+
+ textBoxCursorIndex += codepointSize;
+ textLength += codepointSize;
+
+ // Make sure text last character is EOL
+ text[textLength] = '\0';
+ }
+
+ // Move cursor to start
+ if ((textLength > 0) && IsKeyPressed(KEY_HOME)) textBoxCursorIndex = 0;
+
+ // Move cursor to end
+ if ((textLength > textBoxCursorIndex) && IsKeyPressed(KEY_END)) textBoxCursorIndex = textLength;
+
+ // Delete related codepoints from text, after current cursor position
+ if ((textLength > textBoxCursorIndex) && IsKeyPressed(KEY_DELETE) && (IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_RIGHT_CONTROL)))
+ {
+ int offset = textBoxCursorIndex;
+ int accCodepointSize = 0;
+ int nextCodepointSize;
+ int nextCodepoint;
+
+ // Check characters of the same type to delete (either ASCII punctuation or anything non-whitespace)
+ // Not using isalnum() since it only works on ASCII characters
+ nextCodepoint = GetCodepointNext(text + offset, &nextCodepointSize);
+ bool puctuation = ispunct(nextCodepoint & 0xff);
+ while (offset < textLength)
+ {
+ if ((puctuation && !ispunct(nextCodepoint & 0xff)) || (!puctuation && (isspace(nextCodepoint & 0xff) || ispunct(nextCodepoint & 0xff))))
+ break;
+ offset += nextCodepointSize;
+ accCodepointSize += nextCodepointSize;
+ nextCodepoint = GetCodepointNext(text + offset, &nextCodepointSize);
+ }
+
+ // Check whitespace to delete (ASCII only)
+ while (offset < textLength)
+ {
+ if (!isspace(nextCodepoint & 0xff)) break;
+
+ offset += nextCodepointSize;
+ accCodepointSize += nextCodepointSize;
+ nextCodepoint = GetCodepointNext(text + offset, &nextCodepointSize);
+ }
+
+ // Move text after cursor forward (including final null terminator)
+ for (int i = offset; i <= textLength; i++) text[i - accCodepointSize] = text[i];
+
+ textLength -= accCodepointSize;
+ }
+
+ else if ((textLength > textBoxCursorIndex) && (IsKeyPressed(KEY_DELETE) || (IsKeyDown(KEY_DELETE) && autoCursorShouldTrigger)))
+ {
+ // Delete single codepoint from text, after current cursor position
+
+ int nextCodepointSize = 0;
+ GetCodepointNext(text + textBoxCursorIndex, &nextCodepointSize);
+
+ // Move text after cursor forward (including final null terminator)
+ for (int i = textBoxCursorIndex + nextCodepointSize; i <= textLength; i++) text[i - nextCodepointSize] = text[i];
+
+ textLength -= nextCodepointSize;
+ }
+
+ // Delete related codepoints from text, before current cursor position
+ if ((textBoxCursorIndex > 0) && IsKeyPressed(KEY_BACKSPACE) && (IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_RIGHT_CONTROL)))
+ {
+ int offset = textBoxCursorIndex;
+ int accCodepointSize = 0;
+ int prevCodepointSize = 0;
+ int prevCodepoint = 0;
+
+ // Check whitespace to delete (ASCII only)
+ while (offset > 0)
+ {
+ prevCodepoint = GetCodepointPrevious(text + offset, &prevCodepointSize);
+ if (!isspace(prevCodepoint & 0xff)) break;
+
+ offset -= prevCodepointSize;
+ accCodepointSize += prevCodepointSize;
+ }
+
+ // Check characters of the same type to delete (either ASCII punctuation or anything non-whitespace)
+ // Not using isalnum() since it only works on ASCII characters
+ bool puctuation = ispunct(prevCodepoint & 0xff);
+ while (offset > 0)
+ {
+ prevCodepoint = GetCodepointPrevious(text + offset, &prevCodepointSize);
+ if ((puctuation && !ispunct(prevCodepoint & 0xff)) || (!puctuation && (isspace(prevCodepoint & 0xff) || ispunct(prevCodepoint & 0xff)))) break;
+
+ offset -= prevCodepointSize;
+ accCodepointSize += prevCodepointSize;
+ }
+
+ // Move text after cursor forward (including final null terminator)
+ for (int i = textBoxCursorIndex; i <= textLength; i++) text[i - accCodepointSize] = text[i];
+
+ textLength -= accCodepointSize;
+ textBoxCursorIndex -= accCodepointSize;
+ }
+
+ else if ((textBoxCursorIndex > 0) && (IsKeyPressed(KEY_BACKSPACE) || (IsKeyDown(KEY_BACKSPACE) && autoCursorShouldTrigger)))
+ {
+ // Delete single codepoint from text, before current cursor position
+
+ int prevCodepointSize = 0;
+
+ GetCodepointPrevious(text + textBoxCursorIndex, &prevCodepointSize);
+
+ // Move text after cursor forward (including final null terminator)
+ for (int i = textBoxCursorIndex; i <= textLength; i++) text[i - prevCodepointSize] = text[i];
+
+ textLength -= prevCodepointSize;
+ textBoxCursorIndex -= prevCodepointSize;
+ }
+
+ // Move cursor position with keys
+ if ((textBoxCursorIndex > 0) && IsKeyPressed(KEY_LEFT) && (IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_RIGHT_CONTROL)))
+ {
+ int offset = textBoxCursorIndex;
+ //int accCodepointSize = 0;
+ int prevCodepointSize = 0;
+ int prevCodepoint = 0;
+
+ // Check whitespace to skip (ASCII only)
+ while (offset > 0)
+ {
+ prevCodepoint = GetCodepointPrevious(text + offset, &prevCodepointSize);
+ if (!isspace(prevCodepoint & 0xff)) break;
+
+ offset -= prevCodepointSize;
+ //accCodepointSize += prevCodepointSize;
+ }
+
+ // Check characters of the same type to skip (either ASCII punctuation or anything non-whitespace)
+ // Not using isalnum() since it only works on ASCII characters
+ bool puctuation = ispunct(prevCodepoint & 0xff);
+ while (offset > 0)
+ {
+ prevCodepoint = GetCodepointPrevious(text + offset, &prevCodepointSize);
+ if ((puctuation && !ispunct(prevCodepoint & 0xff)) || (!puctuation && (isspace(prevCodepoint & 0xff) || ispunct(prevCodepoint & 0xff)))) break;
+
+ offset -= prevCodepointSize;
+ //accCodepointSize += prevCodepointSize;
+ }
+
+ textBoxCursorIndex = offset;
+ }
+ else if ((textBoxCursorIndex > 0) && (IsKeyPressed(KEY_LEFT) || (IsKeyDown(KEY_LEFT) && autoCursorShouldTrigger)))
+ {
+ int prevCodepointSize = 0;
+ GetCodepointPrevious(text + textBoxCursorIndex, &prevCodepointSize);
+
+ textBoxCursorIndex -= prevCodepointSize;
+ }
+ else if ((textLength > textBoxCursorIndex) && IsKeyPressed(KEY_RIGHT) && (IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_RIGHT_CONTROL)))
+ {
+ int offset = textBoxCursorIndex;
+ //int accCodepointSize = 0;
+ int nextCodepointSize;
+ int nextCodepoint;
+
+ // Check characters of the same type to skip (either ASCII punctuation or anything non-whitespace)
+ // Not using isalnum() since it only works on ASCII characters
+ nextCodepoint = GetCodepointNext(text + offset, &nextCodepointSize);
+ bool puctuation = ispunct(nextCodepoint & 0xff);
+ while (offset < textLength)
+ {
+ if ((puctuation && !ispunct(nextCodepoint & 0xff)) || (!puctuation && (isspace(nextCodepoint & 0xff) || ispunct(nextCodepoint & 0xff)))) break;
+
+ offset += nextCodepointSize;
+ //accCodepointSize += nextCodepointSize;
+ nextCodepoint = GetCodepointNext(text + offset, &nextCodepointSize);
+ }
+
+ // Check whitespace to skip (ASCII only)
+ while (offset < textLength)
+ {
+ if (!isspace(nextCodepoint & 0xff)) break;
+
+ offset += nextCodepointSize;
+ //accCodepointSize += nextCodepointSize;
+ nextCodepoint = GetCodepointNext(text + offset, &nextCodepointSize);
+ }
+
+ textBoxCursorIndex = offset;
+ }
+ else if ((textLength > textBoxCursorIndex) && (IsKeyPressed(KEY_RIGHT) || (IsKeyDown(KEY_RIGHT) && autoCursorShouldTrigger)))
+ {
+ int nextCodepointSize = 0;
+ GetCodepointNext(text + textBoxCursorIndex, &nextCodepointSize);
+
+ textBoxCursorIndex += nextCodepointSize;
+ }
+
+ // Move cursor position with mouse
+ if (CheckCollisionPointRec(mousePosition, textBounds)) // Mouse hover text
+ {
+ float scaleFactor = (float)GuiGetStyle(DEFAULT, TEXT_SIZE)/(float)guiFont.baseSize;
+ int codepointIndex = 0;
+ float glyphWidth = 0.0f;
+ float widthToMouseX = 0;
+ int mouseCursorIndex = 0;
+
+ for (int i = textIndexOffset; i < textLength; i += codepointSize)
+ {
+ codepoint = GetCodepointNext(&text[i], &codepointSize);
+ codepointIndex = GetGlyphIndex(guiFont, codepoint);
+
+ if (guiFont.glyphs[codepointIndex].advanceX == 0) glyphWidth = ((float)guiFont.recs[codepointIndex].width*scaleFactor);
+ else glyphWidth = ((float)guiFont.glyphs[codepointIndex].advanceX*scaleFactor);
+
+ if (mousePosition.x <= (textBounds.x + (widthToMouseX + glyphWidth/2)))
+ {
+ mouseCursor.x = textBounds.x + widthToMouseX;
+ mouseCursorIndex = i;
+ break;
+ }
+
+ widthToMouseX += (glyphWidth + (float)GuiGetStyle(DEFAULT, TEXT_SPACING));
+ }
+
+ // Check if mouse cursor is at the last position
+ int textEndWidth = GuiGetTextWidth(text + textIndexOffset);
+ if (GetMousePosition().x >= (textBounds.x + textEndWidth - glyphWidth/2))
+ {
+ mouseCursor.x = textBounds.x + textEndWidth;
+ mouseCursorIndex = textLength;
+ }
+
+ // Place cursor at required index on mouse click
+ if ((mouseCursor.x >= 0) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
+ {
+ cursor.x = mouseCursor.x;
+ textBoxCursorIndex = mouseCursorIndex;
+ }
+ }
+ else mouseCursor.x = -1;
+
+ // Recalculate cursor position.y depending on textBoxCursorIndex
+ cursor.x = bounds.x + GuiGetStyle(TEXTBOX, TEXT_PADDING) + GuiGetTextWidth(text + textIndexOffset) - GuiGetTextWidth(text + textBoxCursorIndex) + GuiGetStyle(DEFAULT, TEXT_SPACING);
+ //if (multiline) cursor.y = GetTextLines()
+
+ // Finish text editing on ENTER or mouse click outside bounds
+ if ((!multiline && IsKeyPressed(KEY_ENTER)) ||
+ (!CheckCollisionPointRec(mousePosition, bounds) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)))
+ {
+ textBoxCursorIndex = 0; // GLOBAL: Reset the shared cursor index
+ autoCursorCounter = 0; // GLOBAL: Reset counter for repeated keystrokes
+ result = 1;
+ }
+ }
+ else
+ {
+ if (CheckCollisionPointRec(mousePosition, bounds))
+ {
+ state = STATE_FOCUSED;
+
+ if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
+ {
+ textBoxCursorIndex = textLength; // GLOBAL: Place cursor index to the end of current text
+ autoCursorCounter = 0; // GLOBAL: Reset counter for repeated keystrokes
+ result = 1;
+ }
+ }
+ }
+ }
+ //--------------------------------------------------------------------
+
+ // Draw control
+ //--------------------------------------------------------------------
+ if (state == STATE_PRESSED)
+ {
+ GuiDrawRectangle(bounds, GuiGetStyle(TEXTBOX, BORDER_WIDTH), GetColor(GuiGetStyle(TEXTBOX, BORDER + (state*3))), GetColor(GuiGetStyle(TEXTBOX, BASE_COLOR_PRESSED)));
+ }
+ else if (state == STATE_DISABLED)
+ {
+ GuiDrawRectangle(bounds, GuiGetStyle(TEXTBOX, BORDER_WIDTH), GetColor(GuiGetStyle(TEXTBOX, BORDER + (state*3))), GetColor(GuiGetStyle(TEXTBOX, BASE_COLOR_DISABLED)));
+ }
+ else GuiDrawRectangle(bounds, GuiGetStyle(TEXTBOX, BORDER_WIDTH), GetColor(GuiGetStyle(TEXTBOX, BORDER + (state*3))), BLANK);
+
+ // Draw text considering index offset if required
+ // NOTE: Text index offset depends on cursor position
+ GuiDrawText(text + textIndexOffset, textBounds, GuiGetStyle(TEXTBOX, TEXT_ALIGNMENT), GetColor(GuiGetStyle(TEXTBOX, TEXT + (state*3))));
+
+ // Draw cursor
+ if (editMode && !GuiGetStyle(TEXTBOX, TEXT_READONLY))
+ {
+ //if (autoCursorMode || ((blinkCursorFrameCounter/40)%2 == 0))
+ GuiDrawRectangle(cursor, 0, BLANK, GetColor(GuiGetStyle(TEXTBOX, BORDER_COLOR_PRESSED)));
+
+ // Draw mouse position cursor (if required)
+ if (mouseCursor.x >= 0) GuiDrawRectangle(mouseCursor, 0, BLANK, GetColor(GuiGetStyle(TEXTBOX, BORDER_COLOR_PRESSED)));
+ }
+ else if (state == STATE_FOCUSED) GuiTooltip(bounds);
+ //--------------------------------------------------------------------
+
+ return result; // Mouse button pressed: result = 1
+}
+
+/*
+// Text Box control with multiple lines and word-wrap
+// NOTE: This text-box is readonly, no editing supported by default
+bool GuiTextBoxMulti(Rectangle bounds, char *text, int textSize, bool editMode)
+{
+ bool pressed = false;
+
+ GuiSetStyle(TEXTBOX, TEXT_READONLY, 1);
+ GuiSetStyle(DEFAULT, TEXT_WRAP_MODE, TEXT_WRAP_WORD); // WARNING: If wrap mode enabled, text editing is not supported
+ GuiSetStyle(DEFAULT, TEXT_ALIGNMENT_VERTICAL, TEXT_ALIGN_TOP);
+
+ // TODO: Implement methods to calculate cursor position properly
+ pressed = GuiTextBox(bounds, text, textSize, editMode);
+
+ GuiSetStyle(DEFAULT, TEXT_ALIGNMENT_VERTICAL, TEXT_ALIGN_MIDDLE);
+ GuiSetStyle(DEFAULT, TEXT_WRAP_MODE, TEXT_WRAP_NONE);
+ GuiSetStyle(TEXTBOX, TEXT_READONLY, 0);
+
+ return pressed;
+}
+*/
+
+// Spinner control, returns selected value
+int GuiSpinner(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, bool editMode)
+{
+ int result = 1;
+ GuiState state = guiState;
+
+ int tempValue = *value;
+
+ Rectangle valueBoxBounds = {
+ bounds.x + GuiGetStyle(VALUEBOX, SPINNER_BUTTON_WIDTH) + GuiGetStyle(VALUEBOX, SPINNER_BUTTON_SPACING),
+ bounds.y,
+ bounds.width - 2*(GuiGetStyle(VALUEBOX, SPINNER_BUTTON_WIDTH) + GuiGetStyle(VALUEBOX, SPINNER_BUTTON_SPACING)), bounds.height };
+ Rectangle leftButtonBound = { (float)bounds.x, (float)bounds.y, (float)GuiGetStyle(VALUEBOX, SPINNER_BUTTON_WIDTH), (float)bounds.height };
+ Rectangle rightButtonBound = { (float)bounds.x + bounds.width - GuiGetStyle(VALUEBOX, SPINNER_BUTTON_WIDTH), (float)bounds.y,
+ (float)GuiGetStyle(VALUEBOX, SPINNER_BUTTON_WIDTH), (float)bounds.height };
+
+ Rectangle textBounds = { 0 };
+ if (text != NULL)
+ {
+ textBounds.width = (float)GuiGetTextWidth(text) + 2;
+ textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE);
+ textBounds.x = bounds.x + bounds.width + GuiGetStyle(VALUEBOX, TEXT_PADDING);
+ textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2;
+ if (GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_LEFT) textBounds.x = bounds.x - textBounds.width - GuiGetStyle(VALUEBOX, TEXT_PADDING);
+ }
+
+ // Update control
+ //--------------------------------------------------------------------
+ if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode)
+ {
+ Vector2 mousePoint = GetMousePosition();
+
+ // Check spinner state
+ if (CheckCollisionPointRec(mousePoint, bounds))
+ {
+ if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED;
+ else state = STATE_FOCUSED;
+ }
+ }
+
+#if defined(RAYGUI_NO_ICONS)
+ if (GuiButton(leftButtonBound, "<")) tempValue--;
+ if (GuiButton(rightButtonBound, ">")) tempValue++;
+#else
+ if (GuiButton(leftButtonBound, GuiIconText(ICON_ARROW_LEFT_FILL, NULL))) tempValue--;
+ if (GuiButton(rightButtonBound, GuiIconText(ICON_ARROW_RIGHT_FILL, NULL))) tempValue++;
+#endif
+
+ if (!editMode)
+ {
+ if (tempValue < minValue) tempValue = minValue;
+ if (tempValue > maxValue) tempValue = maxValue;
+ }
+ //--------------------------------------------------------------------
+
+ // Draw control
+ //--------------------------------------------------------------------
+ result = GuiValueBox(valueBoxBounds, NULL, &tempValue, minValue, maxValue, editMode);
+
+ // Draw value selector custom buttons
+ // NOTE: BORDER_WIDTH and TEXT_ALIGNMENT forced values
+ int tempBorderWidth = GuiGetStyle(BUTTON, BORDER_WIDTH);
+ int tempTextAlign = GuiGetStyle(BUTTON, TEXT_ALIGNMENT);
+ GuiSetStyle(BUTTON, BORDER_WIDTH, GuiGetStyle(VALUEBOX, BORDER_WIDTH));
+ GuiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER);
+
+ GuiSetStyle(BUTTON, TEXT_ALIGNMENT, tempTextAlign);
+ GuiSetStyle(BUTTON, BORDER_WIDTH, tempBorderWidth);
+
+ // Draw text label if provided
+ GuiDrawText(text, textBounds, (GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_RIGHT)? TEXT_ALIGN_LEFT : TEXT_ALIGN_RIGHT, GetColor(GuiGetStyle(LABEL, TEXT + (state*3))));
+ //--------------------------------------------------------------------
+
+ *value = tempValue;
+ return result;
+}
+
+// Value Box control, updates input text with numbers
+// NOTE: Requires static variables: frameCounter
+int GuiValueBox(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, bool editMode)
+{
+ #if !defined(RAYGUI_VALUEBOX_MAX_CHARS)
+ #define RAYGUI_VALUEBOX_MAX_CHARS 32
+ #endif
+
+ int result = 0;
+ GuiState state = guiState;
+
+ char textValue[RAYGUI_VALUEBOX_MAX_CHARS + 1] = { 0 };
+ snprintf(textValue, RAYGUI_VALUEBOX_MAX_CHARS + 1, "%i", *value);
+
+ Rectangle textBounds = { 0 };
+ if (text != NULL)
+ {
+ textBounds.width = (float)GuiGetTextWidth(text) + 2;
+ textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE);
+ textBounds.x = bounds.x + bounds.width + GuiGetStyle(VALUEBOX, TEXT_PADDING);
+ textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2;
+ if (GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_LEFT) textBounds.x = bounds.x - textBounds.width - GuiGetStyle(VALUEBOX, TEXT_PADDING);
+ }
+
+ // Update control
+ //--------------------------------------------------------------------
+ if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode)
+ {
+ Vector2 mousePoint = GetMousePosition();
+ bool valueHasChanged = false;
+
+ if (editMode)
+ {
+ state = STATE_PRESSED;
+
+ int keyCount = (int)strlen(textValue);
+
+ // Add or remove minus symbol
+ if (IsKeyPressed(KEY_MINUS))
+ {
+ if (textValue[0] == '-')
+ {
+ for (int i = 0 ; i < keyCount; i++) textValue[i] = textValue[i + 1];
+
+ keyCount--;
+ valueHasChanged = true;
+ }
+ else if (keyCount < RAYGUI_VALUEBOX_MAX_CHARS)
+ {
+ if (keyCount == 0)
+ {
+ textValue[0] = '0';
+ textValue[1] = '\0';
+ keyCount++;
+ }
+
+ for (int i = keyCount ; i > -1; i--) textValue[i + 1] = textValue[i];
+
+ textValue[0] = '-';
+ keyCount++;
+ valueHasChanged = true;
+ }
+ }
+
+ // Add new digit to text value
+ if ((keyCount >= 0) && (keyCount < RAYGUI_VALUEBOX_MAX_CHARS) && (GuiGetTextWidth(textValue) < bounds.width))
+ {
+ int key = GetCharPressed();
+
+ // Only allow keys in range [48..57]
+ if ((key >= 48) && (key <= 57))
+ {
+ textValue[keyCount] = (char)key;
+ keyCount++;
+ valueHasChanged = true;
+ }
+ }
+
+ // Delete text
+ if ((keyCount > 0) && IsKeyPressed(KEY_BACKSPACE))
+ {
+ keyCount--;
+ textValue[keyCount] = '\0';
+ valueHasChanged = true;
+ }
+
+ if (valueHasChanged) *value = TextToInteger(textValue);
+
+ // NOTE: We are not clamp values until user input finishes
+ //if (*value > maxValue) *value = maxValue;
+ //else if (*value < minValue) *value = minValue;
+
+ if ((IsKeyPressed(KEY_ENTER) || IsKeyPressed(KEY_KP_ENTER)) || (!CheckCollisionPointRec(mousePoint, bounds) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)))
+ {
+ if (*value > maxValue) *value = maxValue;
+ else if (*value < minValue) *value = minValue;
+
+ result = 1;
+ }
+ }
+ else
+ {
+ if (*value > maxValue) *value = maxValue;
+ else if (*value < minValue) *value = minValue;
+
+ if (CheckCollisionPointRec(mousePoint, bounds))
+ {
+ state = STATE_FOCUSED;
+ if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) result = 1;
+ }
+ }
+ }
+ //--------------------------------------------------------------------
+
+ // Draw control
+ //--------------------------------------------------------------------
+ Color baseColor = BLANK;
+ if (state == STATE_PRESSED) baseColor = GetColor(GuiGetStyle(VALUEBOX, BASE_COLOR_PRESSED));
+ else if (state == STATE_DISABLED) baseColor = GetColor(GuiGetStyle(VALUEBOX, BASE_COLOR_DISABLED));
+
+ GuiDrawRectangle(bounds, GuiGetStyle(VALUEBOX, BORDER_WIDTH), GetColor(GuiGetStyle(VALUEBOX, BORDER + (state*3))), baseColor);
+ GuiDrawText(textValue, GetTextBounds(VALUEBOX, bounds), TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(VALUEBOX, TEXT + (state*3))));
+
+ // Draw cursor rectangle
+ if (editMode)
+ {
+ // NOTE: ValueBox internal text is always centered
+ Rectangle cursor = { bounds.x + GuiGetTextWidth(textValue)/2 + bounds.width/2 + 1,
+ bounds.y + GuiGetStyle(TEXTBOX, BORDER_WIDTH) + 2,
+ 2, bounds.height - GuiGetStyle(TEXTBOX, BORDER_WIDTH)*2 - 4 };
+ if (cursor.height > bounds.height) cursor.height = bounds.height - GuiGetStyle(TEXTBOX, BORDER_WIDTH)*2;
+ GuiDrawRectangle(cursor, 0, BLANK, GetColor(GuiGetStyle(VALUEBOX, BORDER_COLOR_PRESSED)));
+ }
+
+ // Draw text label if provided
+ GuiDrawText(text, textBounds, (GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_RIGHT)? TEXT_ALIGN_LEFT : TEXT_ALIGN_RIGHT, GetColor(GuiGetStyle(LABEL, TEXT + (state*3))));
+ //--------------------------------------------------------------------
+
+ return result;
+}
+
+// Floating point Value Box control, updates input val_str with numbers
+// NOTE: Requires static variables: frameCounter
+int GuiValueBoxFloat(Rectangle bounds, const char *text, char *textValue, float *value, bool editMode)
+{
+ #if !defined(RAYGUI_VALUEBOX_MAX_CHARS)
+ #define RAYGUI_VALUEBOX_MAX_CHARS 32
+ #endif
+
+ int result = 0;
+ GuiState state = guiState;
+
+ //char textValue[RAYGUI_VALUEBOX_MAX_CHARS + 1] = "\0";
+ //snprintf(textValue, sizeof(textValue), "%2.2f", *value);
+
+ Rectangle textBounds = { 0 };
+ if (text != NULL)
+ {
+ textBounds.width = (float)GuiGetTextWidth(text) + 2;
+ textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE);
+ textBounds.x = bounds.x + bounds.width + GuiGetStyle(VALUEBOX, TEXT_PADDING);
+ textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2;
+ if (GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_LEFT) textBounds.x = bounds.x - textBounds.width - GuiGetStyle(VALUEBOX, TEXT_PADDING);
+ }
+
+ // Update control
+ //--------------------------------------------------------------------
+ if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode)
+ {
+ Vector2 mousePoint = GetMousePosition();
+
+ bool valueHasChanged = false;
+
+ if (editMode)
+ {
+ state = STATE_PRESSED;
+
+ int keyCount = (int)strlen(textValue);
+
+ // Add or remove minus symbol
+ if (IsKeyPressed(KEY_MINUS))
+ {
+ if (textValue[0] == '-')
+ {
+ for (int i = 0; i < keyCount; i++) textValue[i] = textValue[i + 1];
+
+ keyCount--;
+ valueHasChanged = true;
+ }
+ else if (keyCount < (RAYGUI_VALUEBOX_MAX_CHARS - 1))
+ {
+ if (keyCount == 0)
+ {
+ textValue[0] = '0';
+ textValue[1] = '\0';
+ keyCount++;
+ }
+
+ for (int i = keyCount; i > -1; i--) textValue[i + 1] = textValue[i];
+
+ textValue[0] = '-';
+ keyCount++;
+ valueHasChanged = true;
+ }
+ }
+
+ // Only allow keys in range [48..57]
+ if (keyCount < RAYGUI_VALUEBOX_MAX_CHARS)
+ {
+ if (GuiGetTextWidth(textValue) < bounds.width)
+ {
+ int key = GetCharPressed();
+ if (((key >= 48) && (key <= 57)) ||
+ (key == '.') ||
+ ((keyCount == 0) && (key == '+')) || // NOTE: Sign can only be in first position
+ ((keyCount == 0) && (key == '-')))
+ {
+ textValue[keyCount] = (char)key;
+ keyCount++;
+
+ valueHasChanged = true;
+ }
+ }
+ }
+
+ // Pressed backspace
+ if (IsKeyPressed(KEY_BACKSPACE))
+ {
+ if (keyCount > 0)
+ {
+ keyCount--;
+ textValue[keyCount] = '\0';
+ valueHasChanged = true;
+ }
+ }
+
+ if (valueHasChanged) *value = TextToFloat(textValue);
+
+ if ((IsKeyPressed(KEY_ENTER) || IsKeyPressed(KEY_KP_ENTER)) || (!CheckCollisionPointRec(mousePoint, bounds) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) result = 1;
+ }
+ else
+ {
+ if (CheckCollisionPointRec(mousePoint, bounds))
+ {
+ state = STATE_FOCUSED;
+ if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) result = 1;
+ }
+ }
+ }
+ //--------------------------------------------------------------------
+
+ // Draw control
+ //--------------------------------------------------------------------
+ Color baseColor = BLANK;
+ if (state == STATE_PRESSED) baseColor = GetColor(GuiGetStyle(VALUEBOX, BASE_COLOR_PRESSED));
+ else if (state == STATE_DISABLED) baseColor = GetColor(GuiGetStyle(VALUEBOX, BASE_COLOR_DISABLED));
+
+ GuiDrawRectangle(bounds, GuiGetStyle(VALUEBOX, BORDER_WIDTH), GetColor(GuiGetStyle(VALUEBOX, BORDER + (state*3))), baseColor);
+ GuiDrawText(textValue, GetTextBounds(VALUEBOX, bounds), TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(VALUEBOX, TEXT + (state*3))));
+
+ // Draw cursor
+ if (editMode)
+ {
+ // NOTE: ValueBox internal text is always centered
+ Rectangle cursor = {bounds.x + GuiGetTextWidth(textValue)/2 + bounds.width/2 + 1,
+ bounds.y + 2*GuiGetStyle(VALUEBOX, BORDER_WIDTH), 4,
+ bounds.height - 4*GuiGetStyle(VALUEBOX, BORDER_WIDTH)};
+ GuiDrawRectangle(cursor, 0, BLANK, GetColor(GuiGetStyle(VALUEBOX, BORDER_COLOR_PRESSED)));
+ }
+
+ // Draw text label if provided
+ GuiDrawText(text, textBounds,
+ (GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_RIGHT)? TEXT_ALIGN_LEFT : TEXT_ALIGN_RIGHT,
+ GetColor(GuiGetStyle(LABEL, TEXT + (state*3))));
+ //--------------------------------------------------------------------
+
+ return result;
+}
+
+// Slider control with pro parameters
+// NOTE: Other GuiSlider*() controls use this one
+int GuiSlider(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue)
+{
+ int result = 0;
+ GuiState state = guiState;
+
+ float temp = (maxValue - minValue)/2.0f;
+ if (value == NULL) value = &temp;
+ float oldValue = *value;
+
+ int sliderWidth = GuiGetStyle(SLIDER, SLIDER_WIDTH);
+
+ Rectangle slider = { bounds.x, bounds.y + GuiGetStyle(SLIDER, BORDER_WIDTH) + GuiGetStyle(SLIDER, SLIDER_PADDING),
+ 0, bounds.height - 2*GuiGetStyle(SLIDER, BORDER_WIDTH) - 2*GuiGetStyle(SLIDER, SLIDER_PADDING) };
+
+ // Update control
+ //--------------------------------------------------------------------
+ if ((state != STATE_DISABLED) && !guiLocked)
+ {
+ Vector2 mousePoint = GetMousePosition();
+
+ if (guiControlExclusiveMode) // Allows to keep dragging outside of bounds
+ {
+ if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
+ {
+ if (CHECK_BOUNDS_ID(bounds, guiControlExclusiveRec))
+ {
+ state = STATE_PRESSED;
+ // Get equivalent value and slider position from mousePosition.x
+ *value = (maxValue - minValue)*((mousePoint.x - bounds.x - sliderWidth/2)/(bounds.width - sliderWidth)) + minValue;
+ }
+ }
+ else
+ {
+ guiControlExclusiveMode = false;
+ guiControlExclusiveRec = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 };
+ }
+ }
+ else if (CheckCollisionPointRec(mousePoint, bounds))
+ {
+ if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
+ {
+ state = STATE_PRESSED;
+ guiControlExclusiveMode = true;
+ guiControlExclusiveRec = bounds; // Store bounds as an identifier when dragging starts
+
+ if (!CheckCollisionPointRec(mousePoint, slider))
+ {
+ // Get equivalent value and slider position from mousePosition.x
+ *value = (maxValue - minValue)*((mousePoint.x - bounds.x - sliderWidth/2)/(bounds.width - sliderWidth)) + minValue;
+ }
+ }
+ else state = STATE_FOCUSED;
+ }
+
+ if (*value > maxValue) *value = maxValue;
+ else if (*value < minValue) *value = minValue;
+ }
+
+ // Control value change check
+ if (oldValue == *value) result = 0;
+ else result = 1;
+
+ // Slider bar limits check
+ float sliderValue = (((*value - minValue)/(maxValue - minValue))*(bounds.width - sliderWidth - 2*GuiGetStyle(SLIDER, BORDER_WIDTH)));
+ if (sliderWidth > 0) // Slider
+ {
+ slider.x += sliderValue;
+ slider.width = (float)sliderWidth;
+ if (slider.x <= (bounds.x + GuiGetStyle(SLIDER, BORDER_WIDTH))) slider.x = bounds.x + GuiGetStyle(SLIDER, BORDER_WIDTH);
+ else if ((slider.x + slider.width) >= (bounds.x + bounds.width)) slider.x = bounds.x + bounds.width - slider.width - GuiGetStyle(SLIDER, BORDER_WIDTH);
+ }
+ else if (sliderWidth == 0) // SliderBar
+ {
+ slider.x += GuiGetStyle(SLIDER, BORDER_WIDTH);
+ slider.width = sliderValue;
+ if (slider.width > bounds.width) slider.width = bounds.width - 2*GuiGetStyle(SLIDER, BORDER_WIDTH);
+ }
+ //--------------------------------------------------------------------
+
+ // Draw control
+ //--------------------------------------------------------------------
+ GuiDrawRectangle(bounds, GuiGetStyle(SLIDER, BORDER_WIDTH), GetColor(GuiGetStyle(SLIDER, BORDER + (state*3))), GetColor(GuiGetStyle(SLIDER, (state != STATE_DISABLED)? BASE_COLOR_NORMAL : BASE_COLOR_DISABLED)));
+
+ // Draw slider internal bar (depends on state)
+ if (state == STATE_NORMAL) GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, BASE_COLOR_PRESSED)));
+ else if (state == STATE_FOCUSED) GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, TEXT_COLOR_FOCUSED)));
+ else if (state == STATE_PRESSED) GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, TEXT_COLOR_PRESSED)));
+ else if (state == STATE_DISABLED) GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, TEXT_COLOR_DISABLED)));
+
+ // Draw left/right text if provided
+ if (textLeft != NULL)
+ {
+ Rectangle textBounds = { 0 };
+ textBounds.width = (float)GuiGetTextWidth(textLeft);
+ textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE);
+ textBounds.x = bounds.x - textBounds.width - GuiGetStyle(SLIDER, TEXT_PADDING);
+ textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2;
+
+ GuiDrawText(textLeft, textBounds, TEXT_ALIGN_RIGHT, GetColor(GuiGetStyle(LABEL, TEXT + (state*3))));
+ }
+
+ if (textRight != NULL)
+ {
+ Rectangle textBounds = { 0 };
+ textBounds.width = (float)GuiGetTextWidth(textRight);
+ textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE);
+ textBounds.x = bounds.x + bounds.width + GuiGetStyle(SLIDER, TEXT_PADDING);
+ textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2;
+
+ GuiDrawText(textRight, textBounds, TEXT_ALIGN_LEFT, GetColor(GuiGetStyle(LABEL, TEXT + (state*3))));
+ }
+ //--------------------------------------------------------------------
+
+ return result;
+}
+
+// Slider Bar control extended, returns selected value
+int GuiSliderBar(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue)
+{
+ int result = 0;
+ int preSliderWidth = GuiGetStyle(SLIDER, SLIDER_WIDTH);
+ GuiSetStyle(SLIDER, SLIDER_WIDTH, 0);
+ result = GuiSlider(bounds, textLeft, textRight, value, minValue, maxValue);
+ GuiSetStyle(SLIDER, SLIDER_WIDTH, preSliderWidth);
+
+ return result;
+}
+
+// Progress Bar control extended, shows current progress value
+int GuiProgressBar(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue)
+{
+ int result = 0;
+ GuiState state = guiState;
+
+ float temp = (maxValue - minValue)/2.0f;
+ if (value == NULL) value = &temp;
+
+ // Progress bar
+ Rectangle progress = { bounds.x + GuiGetStyle(PROGRESSBAR, BORDER_WIDTH),
+ bounds.y + GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) + GuiGetStyle(PROGRESSBAR, PROGRESS_PADDING), 0,
+ bounds.height - GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) - 2*GuiGetStyle(PROGRESSBAR, PROGRESS_PADDING) -1 };
+
+ // Update control
+ //--------------------------------------------------------------------
+ if (*value > maxValue) *value = maxValue;
+
+ // WARNING: Working with floats could lead to rounding issues
+ if ((state != STATE_DISABLED)) progress.width = ((float)*value/(maxValue - minValue))*(bounds.width - 2*GuiGetStyle(PROGRESSBAR, BORDER_WIDTH));
+ //--------------------------------------------------------------------
+
+ // Draw control
+ //--------------------------------------------------------------------
+ if (state == STATE_DISABLED)
+ {
+ GuiDrawRectangle(bounds, GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), GetColor(GuiGetStyle(PROGRESSBAR, BORDER + (state*3))), BLANK);
+ }
+ else
+ {
+ if (*value > minValue)
+ {
+ // Draw progress bar with colored border, more visual
+ GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y, (int)progress.width + (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_FOCUSED)));
+ GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + 1, (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.height - 2 }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_FOCUSED)));
+ GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + bounds.height - 1, (int)progress.width + (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_FOCUSED)));
+ }
+ else GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y, (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.height+GuiGetStyle(PROGRESSBAR, BORDER_WIDTH)-1 }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_NORMAL)));
+
+ if (*value >= maxValue) GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + progress.width + (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.y, (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.height+GuiGetStyle(PROGRESSBAR, BORDER_WIDTH)-1}, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_FOCUSED)));
+ else
+ {
+ // Draw borders not yet reached by value
+ GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + (int)progress.width + (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.y, bounds.width - (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) - (int)progress.width - 1, (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_NORMAL)));
+ GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + (int)progress.width + (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.y + bounds.height - 1, bounds.width - (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) - (int)progress.width - 1, (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_NORMAL)));
+ GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.y, (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.height+GuiGetStyle(PROGRESSBAR, BORDER_WIDTH)-1 }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_NORMAL)));
+ }
+
+ // Draw slider internal progress bar (depends on state)
+ GuiDrawRectangle(progress, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BASE_COLOR_PRESSED)));
+ }
+
+ // Draw left/right text if provided
+ if (textLeft != NULL)
+ {
+ Rectangle textBounds = { 0 };
+ textBounds.width = (float)GuiGetTextWidth(textLeft);
+ textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE);
+ textBounds.x = bounds.x - textBounds.width - GuiGetStyle(PROGRESSBAR, TEXT_PADDING);
+ textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2;
+
+ GuiDrawText(textLeft, textBounds, TEXT_ALIGN_RIGHT, GetColor(GuiGetStyle(LABEL, TEXT + (state*3))));
+ }
+
+ if (textRight != NULL)
+ {
+ Rectangle textBounds = { 0 };
+ textBounds.width = (float)GuiGetTextWidth(textRight);
+ textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE);
+ textBounds.x = bounds.x + bounds.width + GuiGetStyle(PROGRESSBAR, TEXT_PADDING);
+ textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2;
+
+ GuiDrawText(textRight, textBounds, TEXT_ALIGN_LEFT, GetColor(GuiGetStyle(LABEL, TEXT + (state*3))));
+ }
+ //--------------------------------------------------------------------
+
+ return result;
+}
+
+// Status Bar control
+int GuiStatusBar(Rectangle bounds, const char *text)
+{
+ int result = 0;
+ GuiState state = guiState;
+
+ // Draw control
+ //--------------------------------------------------------------------
+ GuiDrawRectangle(bounds, GuiGetStyle(STATUSBAR, BORDER_WIDTH), GetColor(GuiGetStyle(STATUSBAR, BORDER + (state*3))), GetColor(GuiGetStyle(STATUSBAR, BASE + (state*3))));
+ GuiDrawText(text, GetTextBounds(STATUSBAR, bounds), GuiGetStyle(STATUSBAR, TEXT_ALIGNMENT), GetColor(GuiGetStyle(STATUSBAR, TEXT + (state*3))));
+ //--------------------------------------------------------------------
+
+ return result;
+}
+
+// Dummy rectangle control, intended for placeholding
+int GuiDummyRec(Rectangle bounds, const char *text)
+{
+ int result = 0;
+ GuiState state = guiState;
+
+ // Update control
+ //--------------------------------------------------------------------
+ if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode)
+ {
+ Vector2 mousePoint = GetMousePosition();
+
+ // Check button state
+ if (CheckCollisionPointRec(mousePoint, bounds))
+ {
+ if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED;
+ else state = STATE_FOCUSED;
+ }
+ }
+ //--------------------------------------------------------------------
+
+ // Draw control
+ //--------------------------------------------------------------------
+ GuiDrawRectangle(bounds, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, (state != STATE_DISABLED)? BASE_COLOR_NORMAL : BASE_COLOR_DISABLED)));
+ GuiDrawText(text, GetTextBounds(DEFAULT, bounds), TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(BUTTON, (state != STATE_DISABLED)? TEXT_COLOR_NORMAL : TEXT_COLOR_DISABLED)));
+ //------------------------------------------------------------------
+
+ return result;
+}
+
+// List View control
+int GuiListView(Rectangle bounds, const char *text, int *scrollIndex, int *active)
+{
+ int result = 0;
+ int itemCount = 0;
+ const char **items = NULL;
+
+ if (text != NULL) items = GuiTextSplit(text, ';', &itemCount, NULL);
+
+ result = GuiListViewEx(bounds, items, itemCount, scrollIndex, active, NULL);
+
+ return result;
+}
+
+// List View control with extended parameters
+int GuiListViewEx(Rectangle bounds, const char **text, int count, int *scrollIndex, int *active, int *focus)
+{
+ int result = 0;
+ GuiState state = guiState;
+
+ int itemFocused = (focus == NULL)? -1 : *focus;
+ int itemSelected = (active == NULL)? -1 : *active;
+
+ // Check if we need a scroll bar
+ bool useScrollBar = false;
+ if ((GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING))*count > bounds.height) useScrollBar = true;
+
+ // Define base item rectangle [0]
+ Rectangle itemBounds = { 0 };
+ itemBounds.x = bounds.x + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING);
+ itemBounds.y = bounds.y + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING) + GuiGetStyle(DEFAULT, BORDER_WIDTH);
+ itemBounds.width = bounds.width - 2*GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING) - GuiGetStyle(DEFAULT, BORDER_WIDTH);
+ itemBounds.height = (float)GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT);
+ if (useScrollBar) itemBounds.width -= GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH);
+
+ // Get items on the list
+ int visibleItems = (int)bounds.height/(GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING));
+ if (visibleItems > count) visibleItems = count;
+
+ int startIndex = (scrollIndex == NULL)? 0 : *scrollIndex;
+ if ((startIndex < 0) || (startIndex > (count - visibleItems))) startIndex = 0;
+ int endIndex = startIndex + visibleItems;
+
+ // Update control
+ //--------------------------------------------------------------------
+ if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode)
+ {
+ Vector2 mousePoint = GetMousePosition();
+
+ // Check mouse inside list view
+ if (CheckCollisionPointRec(mousePoint, bounds))
+ {
+ state = STATE_FOCUSED;
+
+ // Check focused and selected item
+ for (int i = 0; i < visibleItems; i++)
+ {
+ if (CheckCollisionPointRec(mousePoint, itemBounds))
+ {
+ itemFocused = startIndex + i;
+ if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
+ {
+ if (itemSelected == (startIndex + i)) itemSelected = -1;
+ else itemSelected = startIndex + i;
+ }
+ break;
+ }
+
+ // Update item rectangle y position for next item
+ itemBounds.y += (GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING));
+ }
+
+ if (useScrollBar)
+ {
+ int wheelMove = (int)GetMouseWheelMove();
+ startIndex -= wheelMove;
+
+ if (startIndex < 0) startIndex = 0;
+ else if (startIndex > (count - visibleItems)) startIndex = count - visibleItems;
+
+ endIndex = startIndex + visibleItems;
+ if (endIndex > count) endIndex = count;
+ }
+ }
+ else itemFocused = -1;
+
+ // Reset item rectangle y to [0]
+ itemBounds.y = bounds.y + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING) + GuiGetStyle(DEFAULT, BORDER_WIDTH);
+ }
+ //--------------------------------------------------------------------
+
+ // Draw control
+ //--------------------------------------------------------------------
+ GuiDrawRectangle(bounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER + state*3)), GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR))); // Draw background
+
+ // Draw visible items
+ for (int i = 0; ((i < visibleItems) && (text != NULL)); i++)
+ {
+ if (GuiGetStyle(LISTVIEW, LIST_ITEMS_BORDER_NORMAL)) GuiDrawRectangle(itemBounds, GuiGetStyle(LISTVIEW, LIST_ITEMS_BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_NORMAL)), BLANK);
+
+ if (state == STATE_DISABLED)
+ {
+ if ((startIndex + i) == itemSelected) GuiDrawRectangle(itemBounds, GuiGetStyle(LISTVIEW, LIST_ITEMS_BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_DISABLED)), GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_DISABLED)));
+
+ GuiDrawText(text[startIndex + i], GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_DISABLED)));
+ }
+ else
+ {
+ if (((startIndex + i) == itemSelected) && (active != NULL))
+ {
+ // Draw item selected
+ GuiDrawRectangle(itemBounds, GuiGetStyle(LISTVIEW, LIST_ITEMS_BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_PRESSED)), GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_PRESSED)));
+ GuiDrawText(text[startIndex + i], GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_PRESSED)));
+ }
+ else if (((startIndex + i) == itemFocused)) // && (focus != NULL)) // NOTE: We want items focused, despite not returned!
+ {
+ // Draw item focused
+ GuiDrawRectangle(itemBounds, GuiGetStyle(LISTVIEW, LIST_ITEMS_BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_FOCUSED)), GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_FOCUSED)));
+ GuiDrawText(text[startIndex + i], GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_FOCUSED)));
+ }
+ else
+ {
+ // Draw item normal (no rectangle)
+ GuiDrawText(text[startIndex + i], GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_NORMAL)));
+ }
+ }
+
+ // Update item rectangle y position for next item
+ itemBounds.y += (GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING));
+ }
+
+ if (useScrollBar)
+ {
+ Rectangle scrollBarBounds = {
+ bounds.x + bounds.width - GuiGetStyle(LISTVIEW, BORDER_WIDTH) - GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH),
+ bounds.y + GuiGetStyle(LISTVIEW, BORDER_WIDTH), (float)GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH),
+ bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH)
+ };
+
+ // Calculate percentage of visible items and apply same percentage to scrollbar
+ float percentVisible = (float)(endIndex - startIndex)/count;
+ float sliderSize = bounds.height*percentVisible;
+
+ int prevSliderSize = GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE); // Save default slider size
+ int prevScrollSpeed = GuiGetStyle(SCROLLBAR, SCROLL_SPEED); // Save default scroll speed
+ GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, (int)sliderSize); // Change slider size
+ GuiSetStyle(SCROLLBAR, SCROLL_SPEED, count - visibleItems); // Change scroll speed
+
+ startIndex = GuiScrollBar(scrollBarBounds, startIndex, 0, count - visibleItems);
+
+ GuiSetStyle(SCROLLBAR, SCROLL_SPEED, prevScrollSpeed); // Reset scroll speed to default
+ GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, prevSliderSize); // Reset slider size to default
+ }
+ //--------------------------------------------------------------------
+
+ if (active != NULL) *active = itemSelected;
+ if (focus != NULL) *focus = itemFocused;
+ if (scrollIndex != NULL) *scrollIndex = startIndex;
+
+ return result;
+}
+
+// Color Panel control - Color (RGBA) variant
+int GuiColorPanel(Rectangle bounds, const char *text, Color *color)
+{
+ int result = 0;
+
+ Vector3 vcolor = { (float)color->r/255.0f, (float)color->g/255.0f, (float)color->b/255.0f };
+ Vector3 hsv = ConvertRGBtoHSV(vcolor);
+ Vector3 prevHsv = hsv; // workaround to see if GuiColorPanelHSV modifies the hsv
+
+ GuiColorPanelHSV(bounds, text, &hsv);
+
+ // Check if the hsv was changed, only then change the color
+ // This is required, because the Color->HSV->Color conversion has precision errors
+ // Thus the assignment from HSV to Color should only be made, if the HSV has a new user-entered value
+ // Otherwise GuiColorPanel would often modify it's color without user input
+ // TODO: GuiColorPanelHSV could return 1 if the slider was dragged, to simplify this check
+ if (hsv.x != prevHsv.x || hsv.y != prevHsv.y || hsv.z != prevHsv.z)
+ {
+ Vector3 rgb = ConvertHSVtoRGB(hsv);
+
+ // NOTE: Vector3ToColor() only available on raylib 1.8.1
+ *color = RAYGUI_CLITERAL(Color){ (unsigned char)(255.0f*rgb.x),
+ (unsigned char)(255.0f*rgb.y),
+ (unsigned char)(255.0f*rgb.z),
+ color->a };
+ }
+ return result;
+}
+
+// Color Bar Alpha control
+// NOTE: Returns alpha value normalized [0..1]
+int GuiColorBarAlpha(Rectangle bounds, const char *text, float *alpha)
+{
+ #if !defined(RAYGUI_COLORBARALPHA_CHECKED_SIZE)
+ #define RAYGUI_COLORBARALPHA_CHECKED_SIZE 10
+ #endif
+
+ int result = 0;
+ GuiState state = guiState;
+ Rectangle selector = { (float)bounds.x + (*alpha)*bounds.width - GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_HEIGHT)/2,
+ (float)bounds.y - GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW),
+ (float)GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_HEIGHT),
+ (float)bounds.height + GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW)*2 };
+
+ // Update control
+ //--------------------------------------------------------------------
+ if ((state != STATE_DISABLED) && !guiLocked)
+ {
+ Vector2 mousePoint = GetMousePosition();
+
+ if (guiControlExclusiveMode) // Allows to keep dragging outside of bounds
+ {
+ if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
+ {
+ if (CHECK_BOUNDS_ID(bounds, guiControlExclusiveRec))
+ {
+ state = STATE_PRESSED;
+
+ *alpha = (mousePoint.x - bounds.x)/bounds.width;
+ if (*alpha <= 0.0f) *alpha = 0.0f;
+ if (*alpha >= 1.0f) *alpha = 1.0f;
+ }
+ }
+ else
+ {
+ guiControlExclusiveMode = false;
+ guiControlExclusiveRec = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 };
+ }
+ }
+ else if (CheckCollisionPointRec(mousePoint, bounds) || CheckCollisionPointRec(mousePoint, selector))
+ {
+ if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
+ {
+ state = STATE_PRESSED;
+ guiControlExclusiveMode = true;
+ guiControlExclusiveRec = bounds; // Store bounds as an identifier when dragging starts
+
+ *alpha = (mousePoint.x - bounds.x)/bounds.width;
+ if (*alpha <= 0.0f) *alpha = 0.0f;
+ if (*alpha >= 1.0f) *alpha = 1.0f;
+ //selector.x = bounds.x + (int)(((alpha - 0)/(100 - 0))*(bounds.width - 2*GuiGetStyle(SLIDER, BORDER_WIDTH))) - selector.width/2;
+ }
+ else state = STATE_FOCUSED;
+ }
+ }
+ //--------------------------------------------------------------------
+
+ // Draw control
+ //--------------------------------------------------------------------
+ // Draw alpha bar: checked background
+ if (state != STATE_DISABLED)
+ {
+ int checksX = (int)bounds.width/RAYGUI_COLORBARALPHA_CHECKED_SIZE;
+ int checksY = (int)bounds.height/RAYGUI_COLORBARALPHA_CHECKED_SIZE;
+
+ for (int x = 0; x < checksX; x++)
+ {
+ for (int y = 0; y < checksY; y++)
+ {
+ Rectangle check = { bounds.x + x*RAYGUI_COLORBARALPHA_CHECKED_SIZE, bounds.y + y*RAYGUI_COLORBARALPHA_CHECKED_SIZE, RAYGUI_COLORBARALPHA_CHECKED_SIZE, RAYGUI_COLORBARALPHA_CHECKED_SIZE };
+ GuiDrawRectangle(check, 0, BLANK, ((x + y)%2)? Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), 0.4f) : Fade(GetColor(GuiGetStyle(COLORPICKER, BASE_COLOR_DISABLED)), 0.4f));
+ }
+ }
+
+ DrawRectangleGradientEx(bounds, RAYGUI_CLITERAL(Color){ 255, 255, 255, 0 }, RAYGUI_CLITERAL(Color){ 255, 255, 255, 0 }, Fade(RAYGUI_CLITERAL(Color){ 0, 0, 0, 255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 0, 0, 0, 255 }, guiAlpha));
+ }
+ else DrawRectangleGradientEx(bounds, Fade(GetColor(GuiGetStyle(COLORPICKER, BASE_COLOR_DISABLED)), 0.1f), Fade(GetColor(GuiGetStyle(COLORPICKER, BASE_COLOR_DISABLED)), 0.1f), Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), guiAlpha), Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), guiAlpha));
+
+ GuiDrawRectangle(bounds, GuiGetStyle(COLORPICKER, BORDER_WIDTH), GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3)), BLANK);
+
+ // Draw alpha bar: selector
+ GuiDrawRectangle(selector, 0, BLANK, GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3)));
+ //--------------------------------------------------------------------
+
+ return result;
+}
+
+// Color Bar Hue control
+// Returns hue value normalized [0..1]
+// NOTE: Other similar bars (for reference):
+// Color GuiColorBarSat() [WHITE->color]
+// Color GuiColorBarValue() [BLACK->color], HSV/HSL
+// float GuiColorBarLuminance() [BLACK->WHITE]
+int GuiColorBarHue(Rectangle bounds, const char *text, float *hue)
+{
+ int result = 0;
+ GuiState state = guiState;
+ Rectangle selector = { (float)bounds.x - GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW), (float)bounds.y + (*hue)/360.0f*bounds.height - GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_HEIGHT)/2, (float)bounds.width + GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW)*2, (float)GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_HEIGHT) };
+
+ // Update control
+ //--------------------------------------------------------------------
+ if ((state != STATE_DISABLED) && !guiLocked)
+ {
+ Vector2 mousePoint = GetMousePosition();
+
+ if (guiControlExclusiveMode) // Allows to keep dragging outside of bounds
+ {
+ if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
+ {
+ if (CHECK_BOUNDS_ID(bounds, guiControlExclusiveRec))
+ {
+ state = STATE_PRESSED;
+
+ *hue = (mousePoint.y - bounds.y)*360/bounds.height;
+ if (*hue <= 0.0f) *hue = 0.0f;
+ if (*hue >= 359.0f) *hue = 359.0f;
+ }
+ }
+ else
+ {
+ guiControlExclusiveMode = false;
+ guiControlExclusiveRec = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 };
+ }
+ }
+ else if (CheckCollisionPointRec(mousePoint, bounds) || CheckCollisionPointRec(mousePoint, selector))
+ {
+ if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
+ {
+ state = STATE_PRESSED;
+ guiControlExclusiveMode = true;
+ guiControlExclusiveRec = bounds; // Store bounds as an identifier when dragging starts
+
+ *hue = (mousePoint.y - bounds.y)*360/bounds.height;
+ if (*hue <= 0.0f) *hue = 0.0f;
+ if (*hue >= 359.0f) *hue = 359.0f;
+
+ }
+ else state = STATE_FOCUSED;
+
+ /*if (IsKeyDown(KEY_UP))
+ {
+ hue -= 2.0f;
+ if (hue <= 0.0f) hue = 0.0f;
+ }
+ else if (IsKeyDown(KEY_DOWN))
+ {
+ hue += 2.0f;
+ if (hue >= 360.0f) hue = 360.0f;
+ }*/
+ }
+ }
+ //--------------------------------------------------------------------
+
+ // Draw control
+ //--------------------------------------------------------------------
+ if (state != STATE_DISABLED)
+ {
+ // Draw hue bar:color bars
+ // TODO: Use directly DrawRectangleGradientEx(bounds, color1, color2, color2, color1);
+ DrawRectangleGradientV((int)bounds.x, (int)(bounds.y), (int)bounds.width, (int)ceilf(bounds.height/6), Fade(RAYGUI_CLITERAL(Color){ 255, 0, 0, 255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 255, 255, 0, 255 }, guiAlpha));
+ DrawRectangleGradientV((int)bounds.x, (int)(bounds.y + bounds.height/6), (int)bounds.width, (int)ceilf(bounds.height/6), Fade(RAYGUI_CLITERAL(Color){ 255, 255, 0, 255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 0, 255, 0, 255 }, guiAlpha));
+ DrawRectangleGradientV((int)bounds.x, (int)(bounds.y + 2*(bounds.height/6)), (int)bounds.width, (int)ceilf(bounds.height/6), Fade(RAYGUI_CLITERAL(Color){ 0, 255, 0, 255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 0, 255, 255, 255 }, guiAlpha));
+ DrawRectangleGradientV((int)bounds.x, (int)(bounds.y + 3*(bounds.height/6)), (int)bounds.width, (int)ceilf(bounds.height/6), Fade(RAYGUI_CLITERAL(Color){ 0, 255, 255, 255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 0, 0, 255, 255 }, guiAlpha));
+ DrawRectangleGradientV((int)bounds.x, (int)(bounds.y + 4*(bounds.height/6)), (int)bounds.width, (int)ceilf(bounds.height/6), Fade(RAYGUI_CLITERAL(Color){ 0, 0, 255, 255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 255, 0, 255, 255 }, guiAlpha));
+ DrawRectangleGradientV((int)bounds.x, (int)(bounds.y + 5*(bounds.height/6)), (int)bounds.width, (int)(bounds.height/6), Fade(RAYGUI_CLITERAL(Color){ 255, 0, 255, 255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 255, 0, 0, 255 }, guiAlpha));
+ }
+ else DrawRectangleGradientV((int)bounds.x, (int)bounds.y, (int)bounds.width, (int)bounds.height, Fade(Fade(GetColor(GuiGetStyle(COLORPICKER, BASE_COLOR_DISABLED)), 0.1f), guiAlpha), Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), guiAlpha));
+
+ GuiDrawRectangle(bounds, GuiGetStyle(COLORPICKER, BORDER_WIDTH), GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3)), BLANK);
+
+ // Draw hue bar: selector
+ GuiDrawRectangle(selector, 0, BLANK, GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3)));
+ //--------------------------------------------------------------------
+
+ return result;
+}
+
+// Color Picker control
+// NOTE: It's divided in multiple controls:
+// Color GuiColorPanel(Rectangle bounds, Color color)
+// float GuiColorBarAlpha(Rectangle bounds, float alpha)
+// float GuiColorBarHue(Rectangle bounds, float value)
+// NOTE: bounds define GuiColorPanel() size
+// NOTE: this picker converts RGB to HSV, which can cause the Hue control to jump. If you have this problem, consider using the HSV variant instead
+int GuiColorPicker(Rectangle bounds, const char *text, Color *color)
+{
+ int result = 0;
+
+ Color temp = { 200, 0, 0, 255 };
+ if (color == NULL) color = &temp;
+
+ GuiColorPanel(bounds, NULL, color);
+
+ Rectangle boundsHue = { (float)bounds.x + bounds.width + GuiGetStyle(COLORPICKER, HUEBAR_PADDING), (float)bounds.y, (float)GuiGetStyle(COLORPICKER, HUEBAR_WIDTH), (float)bounds.height };
+ //Rectangle boundsAlpha = { bounds.x, bounds.y + bounds.height + GuiGetStyle(COLORPICKER, BARS_PADDING), bounds.width, GuiGetStyle(COLORPICKER, BARS_THICK) };
+
+ // NOTE: this conversion can cause low hue-resolution, if the r, g and b value are very similar, which causes the hue bar to shift around when only the GuiColorPanel is used
+ Vector3 hsv = ConvertRGBtoHSV(RAYGUI_CLITERAL(Vector3){ (*color).r/255.0f, (*color).g/255.0f, (*color).b/255.0f });
+
+ GuiColorBarHue(boundsHue, NULL, &hsv.x);
+
+ //color.a = (unsigned char)(GuiColorBarAlpha(boundsAlpha, (float)color.a/255.0f)*255.0f);
+ Vector3 rgb = ConvertHSVtoRGB(hsv);
+
+ *color = RAYGUI_CLITERAL(Color){ (unsigned char)roundf(rgb.x*255.0f), (unsigned char)roundf(rgb.y*255.0f), (unsigned char)roundf(rgb.z*255.0f), (*color).a };
+
+ return result;
+}
+
+// Color Picker control that avoids conversion to RGB and back to HSV on each call, thus avoiding jittering
+// The user can call ConvertHSVtoRGB() to convert *colorHsv value to RGB
+// NOTE: It's divided in multiple controls:
+// int GuiColorPanelHSV(Rectangle bounds, const char *text, Vector3 *colorHsv)
+// int GuiColorBarAlpha(Rectangle bounds, const char *text, float *alpha)
+// float GuiColorBarHue(Rectangle bounds, float value)
+// NOTE: bounds define GuiColorPanelHSV() size
+int GuiColorPickerHSV(Rectangle bounds, const char *text, Vector3 *colorHsv)
+{
+ int result = 0;
+
+ Vector3 tempHsv = { 0 };
+
+ if (colorHsv == NULL)
+ {
+ const Vector3 tempColor = { 200.0f/255.0f, 0.0f, 0.0f };
+ tempHsv = ConvertRGBtoHSV(tempColor);
+ colorHsv = &tempHsv;
+ }
+
+ GuiColorPanelHSV(bounds, NULL, colorHsv);
+
+ const Rectangle boundsHue = { (float)bounds.x + bounds.width + GuiGetStyle(COLORPICKER, HUEBAR_PADDING), (float)bounds.y, (float)GuiGetStyle(COLORPICKER, HUEBAR_WIDTH), (float)bounds.height };
+
+ GuiColorBarHue(boundsHue, NULL, &colorHsv->x);
+
+ return result;
+}
+
+// Color Panel control - HSV variant
+int GuiColorPanelHSV(Rectangle bounds, const char *text, Vector3 *colorHsv)
+{
+ int result = 0;
+ GuiState state = guiState;
+ Vector2 pickerSelector = { 0 };
+
+ const Color colWhite = { 255, 255, 255, 255 };
+ const Color colBlack = { 0, 0, 0, 255 };
+
+ pickerSelector.x = bounds.x + (float)colorHsv->y*bounds.width; // HSV: Saturation
+ pickerSelector.y = bounds.y + (1.0f - (float)colorHsv->z)*bounds.height; // HSV: Value
+
+ Vector3 maxHue = { colorHsv->x, 1.0f, 1.0f };
+ Vector3 rgbHue = ConvertHSVtoRGB(maxHue);
+ Color maxHueCol = { (unsigned char)(255.0f*rgbHue.x),
+ (unsigned char)(255.0f*rgbHue.y),
+ (unsigned char)(255.0f*rgbHue.z), 255 };
+
+ // Update control
+ //--------------------------------------------------------------------
+ if ((state != STATE_DISABLED) && !guiLocked)
+ {
+ Vector2 mousePoint = GetMousePosition();
+
+ if (guiControlExclusiveMode) // Allows to keep dragging outside of bounds
+ {
+ if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
+ {
+ if (CHECK_BOUNDS_ID(bounds, guiControlExclusiveRec))
+ {
+ pickerSelector = mousePoint;
+
+ if (pickerSelector.x < bounds.x) pickerSelector.x = bounds.x;
+ if (pickerSelector.x > bounds.x + bounds.width) pickerSelector.x = bounds.x + bounds.width;
+ if (pickerSelector.y < bounds.y) pickerSelector.y = bounds.y;
+ if (pickerSelector.y > bounds.y + bounds.height) pickerSelector.y = bounds.y + bounds.height;
+
+ // Calculate color from picker
+ Vector2 colorPick = { pickerSelector.x - bounds.x, pickerSelector.y - bounds.y };
+
+ colorPick.x /= (float)bounds.width; // Get normalized value on x
+ colorPick.y /= (float)bounds.height; // Get normalized value on y
+
+ colorHsv->y = colorPick.x;
+ colorHsv->z = 1.0f - colorPick.y;
+
+ }
+ }
+ else
+ {
+ guiControlExclusiveMode = false;
+ guiControlExclusiveRec = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 };
+ }
+ }
+ else if (CheckCollisionPointRec(mousePoint, bounds))
+ {
+ if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
+ {
+ state = STATE_PRESSED;
+ guiControlExclusiveMode = true;
+ guiControlExclusiveRec = bounds;
+ pickerSelector = mousePoint;
+
+ // Calculate color from picker
+ Vector2 colorPick = { pickerSelector.x - bounds.x, pickerSelector.y - bounds.y };
+
+ colorPick.x /= (float)bounds.width; // Get normalized value on x
+ colorPick.y /= (float)bounds.height; // Get normalized value on y
+
+ colorHsv->y = colorPick.x;
+ colorHsv->z = 1.0f - colorPick.y;
+ }
+ else state = STATE_FOCUSED;
+ }
+ }
+ //--------------------------------------------------------------------
+
+ // Draw control
+ //--------------------------------------------------------------------
+ if (state != STATE_DISABLED)
+ {
+ DrawRectangleGradientEx(bounds, Fade(colWhite, guiAlpha), Fade(colWhite, guiAlpha), Fade(maxHueCol, guiAlpha), Fade(maxHueCol, guiAlpha));
+ DrawRectangleGradientEx(bounds, Fade(colBlack, 0), Fade(colBlack, guiAlpha), Fade(colBlack, guiAlpha), Fade(colBlack, 0));
+
+ // Draw color picker: selector
+ Rectangle selector = { pickerSelector.x - GuiGetStyle(COLORPICKER, COLOR_SELECTOR_SIZE)/2, pickerSelector.y - GuiGetStyle(COLORPICKER, COLOR_SELECTOR_SIZE)/2, (float)GuiGetStyle(COLORPICKER, COLOR_SELECTOR_SIZE), (float)GuiGetStyle(COLORPICKER, COLOR_SELECTOR_SIZE) };
+ GuiDrawRectangle(selector, 0, BLANK, colWhite);
+ }
+ else
+ {
+ DrawRectangleGradientEx(bounds, Fade(Fade(GetColor(GuiGetStyle(COLORPICKER, BASE_COLOR_DISABLED)), 0.1f), guiAlpha), Fade(Fade(colBlack, 0.6f), guiAlpha), Fade(Fade(colBlack, 0.6f), guiAlpha), Fade(Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), 0.6f), guiAlpha));
+ }
+
+ GuiDrawRectangle(bounds, GuiGetStyle(COLORPICKER, BORDER_WIDTH), GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3)), BLANK);
+ //--------------------------------------------------------------------
+
+ return result;
+}
+
+// Message Box control
+int GuiMessageBox(Rectangle bounds, const char *title, const char *message, const char *buttons)
+{
+ #if !defined(RAYGUI_MESSAGEBOX_BUTTON_HEIGHT)
+ #define RAYGUI_MESSAGEBOX_BUTTON_HEIGHT 24
+ #endif
+ #if !defined(RAYGUI_MESSAGEBOX_BUTTON_PADDING)
+ #define RAYGUI_MESSAGEBOX_BUTTON_PADDING 12
+ #endif
+
+ int result = -1; // Returns clicked button from buttons list, 0 refers to closed window button
+
+ int buttonCount = 0;
+ const char **buttonsText = GuiTextSplit(buttons, ';', &buttonCount, NULL);
+ Rectangle buttonBounds = { 0 };
+ buttonBounds.x = bounds.x + RAYGUI_MESSAGEBOX_BUTTON_PADDING;
+ buttonBounds.y = bounds.y + bounds.height - RAYGUI_MESSAGEBOX_BUTTON_HEIGHT - RAYGUI_MESSAGEBOX_BUTTON_PADDING;
+ buttonBounds.width = (bounds.width - RAYGUI_MESSAGEBOX_BUTTON_PADDING*(buttonCount + 1))/buttonCount;
+ buttonBounds.height = RAYGUI_MESSAGEBOX_BUTTON_HEIGHT;
+
+ //int textWidth = GuiGetTextWidth(message) + 2;
+
+ Rectangle textBounds = { 0 };
+ textBounds.x = bounds.x + RAYGUI_MESSAGEBOX_BUTTON_PADDING;
+ textBounds.y = bounds.y + RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT + RAYGUI_MESSAGEBOX_BUTTON_PADDING;
+ textBounds.width = bounds.width - RAYGUI_MESSAGEBOX_BUTTON_PADDING*2;
+ textBounds.height = bounds.height - RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - 3*RAYGUI_MESSAGEBOX_BUTTON_PADDING - RAYGUI_MESSAGEBOX_BUTTON_HEIGHT;
+
+ // Draw control
+ //--------------------------------------------------------------------
+ if (GuiWindowBox(bounds, title)) result = 0;
+
+ int prevTextAlignment = GuiGetStyle(LABEL, TEXT_ALIGNMENT);
+ GuiSetStyle(LABEL, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER);
+ GuiLabel(textBounds, message);
+ GuiSetStyle(LABEL, TEXT_ALIGNMENT, prevTextAlignment);
+
+ prevTextAlignment = GuiGetStyle(BUTTON, TEXT_ALIGNMENT);
+ GuiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER);
+
+ for (int i = 0; i < buttonCount; i++)
+ {
+ if (GuiButton(buttonBounds, buttonsText[i])) result = i + 1;
+ buttonBounds.x += (buttonBounds.width + RAYGUI_MESSAGEBOX_BUTTON_PADDING);
+ }
+
+ GuiSetStyle(BUTTON, TEXT_ALIGNMENT, prevTextAlignment);
+ //--------------------------------------------------------------------
+
+ return result;
+}
+
+// Text Input Box control, ask for text
+int GuiTextInputBox(Rectangle bounds, const char *title, const char *message, const char *buttons, char *text, int textMaxSize, bool *secretViewActive)
+{
+ #if !defined(RAYGUI_TEXTINPUTBOX_BUTTON_HEIGHT)
+ #define RAYGUI_TEXTINPUTBOX_BUTTON_HEIGHT 24
+ #endif
+ #if !defined(RAYGUI_TEXTINPUTBOX_BUTTON_PADDING)
+ #define RAYGUI_TEXTINPUTBOX_BUTTON_PADDING 12
+ #endif
+ #if !defined(RAYGUI_TEXTINPUTBOX_HEIGHT)
+ #define RAYGUI_TEXTINPUTBOX_HEIGHT 26
+ #endif
+
+ // Used to enable text edit mode
+ // WARNING: No more than one GuiTextInputBox() should be open at the same time
+ static bool textEditMode = false;
+
+ int result = -1;
+
+ int buttonCount = 0;
+ const char **buttonsText = GuiTextSplit(buttons, ';', &buttonCount, NULL);
+ Rectangle buttonBounds = { 0 };
+ buttonBounds.x = bounds.x + RAYGUI_TEXTINPUTBOX_BUTTON_PADDING;
+ buttonBounds.y = bounds.y + bounds.height - RAYGUI_TEXTINPUTBOX_BUTTON_HEIGHT - RAYGUI_TEXTINPUTBOX_BUTTON_PADDING;
+ buttonBounds.width = (bounds.width - RAYGUI_TEXTINPUTBOX_BUTTON_PADDING*(buttonCount + 1))/buttonCount;
+ buttonBounds.height = RAYGUI_TEXTINPUTBOX_BUTTON_HEIGHT;
+
+ int messageInputHeight = (int)bounds.height - RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - GuiGetStyle(STATUSBAR, BORDER_WIDTH) - RAYGUI_TEXTINPUTBOX_BUTTON_HEIGHT - 2*RAYGUI_TEXTINPUTBOX_BUTTON_PADDING;
+
+ Rectangle textBounds = { 0 };
+ if (message != NULL)
+ {
+ int textSize = GuiGetTextWidth(message) + 2;
+
+ textBounds.x = bounds.x + bounds.width/2 - textSize/2;
+ textBounds.y = bounds.y + RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT + messageInputHeight/4 - (float)GuiGetStyle(DEFAULT, TEXT_SIZE)/2;
+ textBounds.width = (float)textSize;
+ textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE);
+ }
+
+ Rectangle textBoxBounds = { 0 };
+ textBoxBounds.x = bounds.x + RAYGUI_TEXTINPUTBOX_BUTTON_PADDING;
+ textBoxBounds.y = bounds.y + RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - RAYGUI_TEXTINPUTBOX_HEIGHT/2;
+ if (message == NULL) textBoxBounds.y = bounds.y + 24 + RAYGUI_TEXTINPUTBOX_BUTTON_PADDING;
+ else textBoxBounds.y += (messageInputHeight/2 + messageInputHeight/4);
+ textBoxBounds.width = bounds.width - RAYGUI_TEXTINPUTBOX_BUTTON_PADDING*2;
+ textBoxBounds.height = RAYGUI_TEXTINPUTBOX_HEIGHT;
+
+ // Draw control
+ //--------------------------------------------------------------------
+ if (GuiWindowBox(bounds, title)) result = 0;
+
+ // Draw message if available
+ if (message != NULL)
+ {
+ int prevTextAlignment = GuiGetStyle(LABEL, TEXT_ALIGNMENT);
+ GuiSetStyle(LABEL, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER);
+ GuiLabel(textBounds, message);
+ GuiSetStyle(LABEL, TEXT_ALIGNMENT, prevTextAlignment);
+ }
+
+ if (secretViewActive != NULL)
+ {
+ static char stars[] = "****************";
+ if (GuiTextBox(RAYGUI_CLITERAL(Rectangle){ textBoxBounds.x, textBoxBounds.y, textBoxBounds.width - 4 - RAYGUI_TEXTINPUTBOX_HEIGHT, textBoxBounds.height },
+ ((*secretViewActive == 1) || textEditMode)? text : stars, textMaxSize, textEditMode)) textEditMode = !textEditMode;
+
+ GuiToggle(RAYGUI_CLITERAL(Rectangle){ textBoxBounds.x + textBoxBounds.width - RAYGUI_TEXTINPUTBOX_HEIGHT, textBoxBounds.y, RAYGUI_TEXTINPUTBOX_HEIGHT, RAYGUI_TEXTINPUTBOX_HEIGHT }, (*secretViewActive == 1)? "#44#" : "#45#", secretViewActive);
+ }
+ else
+ {
+ if (GuiTextBox(textBoxBounds, text, textMaxSize, textEditMode)) textEditMode = !textEditMode;
+ }
+
+ int prevBtnTextAlignment = GuiGetStyle(BUTTON, TEXT_ALIGNMENT);
+ GuiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER);
+
+ for (int i = 0; i < buttonCount; i++)
+ {
+ if (GuiButton(buttonBounds, buttonsText[i])) result = i + 1;
+ buttonBounds.x += (buttonBounds.width + RAYGUI_MESSAGEBOX_BUTTON_PADDING);
+ }
+
+ if (result >= 0) textEditMode = false;
+
+ GuiSetStyle(BUTTON, TEXT_ALIGNMENT, prevBtnTextAlignment);
+ //--------------------------------------------------------------------
+
+ return result; // Result is the pressed button index
+}
+
+// Grid control
+// NOTE: Returns grid mouse-hover selected cell
+// About drawing lines at subpixel spacing, simple put, not easy solution:
+// REF: https://stackoverflow.com/questions/4435450/2d-opengl-drawing-lines-that-dont-exactly-fit-pixel-raster
+int GuiGrid(Rectangle bounds, const char *text, float spacing, int subdivs, Vector2 *mouseCell)
+{
+ // Grid lines alpha amount
+ #if !defined(RAYGUI_GRID_ALPHA)
+ #define RAYGUI_GRID_ALPHA 0.15f
+ #endif
+
+ int result = 0;
+ GuiState state = guiState;
+
+ Vector2 mousePoint = GetMousePosition();
+ Vector2 currentMouseCell = { -1, -1 };
+
+ float spaceWidth = spacing/(float)subdivs;
+ int linesV = (int)(bounds.width/spaceWidth) + 1;
+ int linesH = (int)(bounds.height/spaceWidth) + 1;
+
+ int color = GuiGetStyle(DEFAULT, LINE_COLOR);
+
+ // Update control
+ //--------------------------------------------------------------------
+ if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode)
+ {
+ if (CheckCollisionPointRec(mousePoint, bounds))
+ {
+ // NOTE: Cell values must be the upper left of the cell the mouse is in
+ currentMouseCell.x = floorf((mousePoint.x - bounds.x)/spacing);
+ currentMouseCell.y = floorf((mousePoint.y - bounds.y)/spacing);
+ }
+ }
+ //--------------------------------------------------------------------
+
+ // Draw control
+ //--------------------------------------------------------------------
+ if (state == STATE_DISABLED) color = GuiGetStyle(DEFAULT, BORDER_COLOR_DISABLED);
+
+ if (subdivs > 0)
+ {
+ // Draw vertical grid lines
+ for (int i = 0; i < linesV; i++)
+ {
+ Rectangle lineV = { bounds.x + spacing*i/subdivs, bounds.y, 1, bounds.height + 1 };
+ GuiDrawRectangle(lineV, 0, BLANK, ((i%subdivs) == 0)? GuiFade(GetColor(color), RAYGUI_GRID_ALPHA*4) : GuiFade(GetColor(color), RAYGUI_GRID_ALPHA));
+ }
+
+ // Draw horizontal grid lines
+ for (int i = 0; i < linesH; i++)
+ {
+ Rectangle lineH = { bounds.x, bounds.y + spacing*i/subdivs, bounds.width + 1, 1 };
+ GuiDrawRectangle(lineH, 0, BLANK, ((i%subdivs) == 0)? GuiFade(GetColor(color), RAYGUI_GRID_ALPHA*4) : GuiFade(GetColor(color), RAYGUI_GRID_ALPHA));
+ }
+ }
+
+ if (mouseCell != NULL) *mouseCell = currentMouseCell;
+ return result;
+}
+
+//----------------------------------------------------------------------------------
+// Tooltip management functions
+// NOTE: Tooltips requires some global variables: tooltipPtr
+//----------------------------------------------------------------------------------
+// Enable gui tooltips (global state)
+void GuiEnableTooltip(void) { guiTooltip = true; }
+
+// Disable gui tooltips (global state)
+void GuiDisableTooltip(void) { guiTooltip = false; }
+
+// Set tooltip string
+void GuiSetTooltip(const char *tooltip) { guiTooltipPtr = tooltip; }
+
+//----------------------------------------------------------------------------------
+// Styles loading functions
+//----------------------------------------------------------------------------------
+
+// Load raygui style file (.rgs)
+// NOTE: By default a binary file is expected, that file could contain a custom font,
+// in that case, custom font image atlas is GRAY+ALPHA and pixel data can be compressed (DEFLATE)
+void GuiLoadStyle(const char *fileName)
+{
+ #define MAX_LINE_BUFFER_SIZE 256
+
+ bool tryBinary = false;
+ if (!guiStyleLoaded) GuiLoadStyleDefault();
+
+ // Try reading the files as text file first
+ FILE *rgsFile = fopen(fileName, "rt");
+
+ if (rgsFile != NULL)
+ {
+ char buffer[MAX_LINE_BUFFER_SIZE] = { 0 };
+ fgets(buffer, MAX_LINE_BUFFER_SIZE, rgsFile);
+
+ if (buffer[0] == '#')
+ {
+ int controlId = 0;
+ int propertyId = 0;
+ unsigned int propertyValue = 0;
+
+ while (!feof(rgsFile))
+ {
+ switch (buffer[0])
+ {
+ case 'p':
+ {
+ // Style property: p
+
+ sscanf(buffer, "p %d %d 0x%x", &controlId, &propertyId, &propertyValue);
+ GuiSetStyle(controlId, propertyId, (int)propertyValue);
+
+ } break;
+ case 'f':
+ {
+ // Style font: f
+
+ int fontSize = 0;
+ char charmapFileName[256] = { 0 };
+ char fontFileName[256] = { 0 };
+ sscanf(buffer, "f %d %s %[^\r\n]s", &fontSize, charmapFileName, fontFileName);
+
+ Font font = { 0 };
+ int *codepoints = NULL;
+ int codepointCount = 0;
+
+ if (charmapFileName[0] != '0')
+ {
+ // Load text data from file
+ // NOTE: Expected an UTF-8 array of codepoints, no separation
+ char *textData = LoadFileText(TextFormat("%s/%s", GetDirectoryPath(fileName), charmapFileName));
+ codepoints = LoadCodepoints(textData, &codepointCount);
+ UnloadFileText(textData);
+ }
+
+ if (fontFileName[0] != '\0')
+ {
+ // In case a font is already loaded and it is not default internal font, unload it
+ if (font.texture.id != GetFontDefault().texture.id) UnloadTexture(font.texture);
+
+ if (codepointCount > 0) font = LoadFontEx(TextFormat("%s/%s", GetDirectoryPath(fileName), fontFileName), fontSize, codepoints, codepointCount);
+ else font = LoadFontEx(TextFormat("%s/%s", GetDirectoryPath(fileName), fontFileName), fontSize, NULL, 0); // Default to 95 standard codepoints
+ }
+
+ // If font texture not properly loaded, revert to default font and size/spacing
+ if (font.texture.id == 0)
+ {
+ font = GetFontDefault();
+ GuiSetStyle(DEFAULT, TEXT_SIZE, 10);
+ GuiSetStyle(DEFAULT, TEXT_SPACING, 1);
+ }
+
+ UnloadCodepoints(codepoints);
+
+ if ((font.texture.id > 0) && (font.glyphCount > 0)) GuiSetFont(font);
+
+ } break;
+ default: break;
+ }
+
+ fgets(buffer, MAX_LINE_BUFFER_SIZE, rgsFile);
+ }
+ }
+ else tryBinary = true;
+
+ fclose(rgsFile);
+ }
+
+ if (tryBinary)
+ {
+ rgsFile = fopen(fileName, "rb");
+
+ if (rgsFile != NULL)
+ {
+ fseek(rgsFile, 0, SEEK_END);
+ int fileDataSize = ftell(rgsFile);
+ fseek(rgsFile, 0, SEEK_SET);
+
+ if (fileDataSize > 0)
+ {
+ unsigned char *fileData = (unsigned char *)RAYGUI_CALLOC(fileDataSize, sizeof(unsigned char));
+ fread(fileData, sizeof(unsigned char), fileDataSize, rgsFile);
+
+ GuiLoadStyleFromMemory(fileData, fileDataSize);
+
+ RAYGUI_FREE(fileData);
+ }
+
+ fclose(rgsFile);
+ }
+ }
+}
+
+// Load style default over global style
+void GuiLoadStyleDefault(void)
+{
+ // We set this variable first to avoid cyclic function calls
+ // when calling GuiSetStyle() and GuiGetStyle()
+ guiStyleLoaded = true;
+
+ // Initialize default LIGHT style property values
+ // WARNING: Default value are applied to all controls on set but
+ // they can be overwritten later on for every custom control
+ GuiSetStyle(DEFAULT, BORDER_COLOR_NORMAL, 0x838383ff);
+ GuiSetStyle(DEFAULT, BASE_COLOR_NORMAL, 0xc9c9c9ff);
+ GuiSetStyle(DEFAULT, TEXT_COLOR_NORMAL, 0x686868ff);
+ GuiSetStyle(DEFAULT, BORDER_COLOR_FOCUSED, 0x5bb2d9ff);
+ GuiSetStyle(DEFAULT, BASE_COLOR_FOCUSED, 0xc9effeff);
+ GuiSetStyle(DEFAULT, TEXT_COLOR_FOCUSED, 0x6c9bbcff);
+ GuiSetStyle(DEFAULT, BORDER_COLOR_PRESSED, 0x0492c7ff);
+ GuiSetStyle(DEFAULT, BASE_COLOR_PRESSED, 0x97e8ffff);
+ GuiSetStyle(DEFAULT, TEXT_COLOR_PRESSED, 0x368bafff);
+ GuiSetStyle(DEFAULT, BORDER_COLOR_DISABLED, 0xb5c1c2ff);
+ GuiSetStyle(DEFAULT, BASE_COLOR_DISABLED, 0xe6e9e9ff);
+ GuiSetStyle(DEFAULT, TEXT_COLOR_DISABLED, 0xaeb7b8ff);
+ GuiSetStyle(DEFAULT, BORDER_WIDTH, 1);
+ GuiSetStyle(DEFAULT, TEXT_PADDING, 0);
+ GuiSetStyle(DEFAULT, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER);
+
+ // Initialize default extended property values
+ // NOTE: By default, extended property values are initialized to 0
+ GuiSetStyle(DEFAULT, TEXT_SIZE, 10); // DEFAULT, shared by all controls
+ GuiSetStyle(DEFAULT, TEXT_SPACING, 1); // DEFAULT, shared by all controls
+ GuiSetStyle(DEFAULT, LINE_COLOR, 0x90abb5ff); // DEFAULT specific property
+ GuiSetStyle(DEFAULT, BACKGROUND_COLOR, 0xf5f5f5ff); // DEFAULT specific property
+ GuiSetStyle(DEFAULT, TEXT_LINE_SPACING, 15); // DEFAULT, 15 pixels between lines
+ GuiSetStyle(DEFAULT, TEXT_ALIGNMENT_VERTICAL, TEXT_ALIGN_MIDDLE); // DEFAULT, text aligned vertically to middle of text-bounds
+
+ // Initialize control-specific property values
+ // NOTE: Those properties are in default list but require specific values by control type
+ GuiSetStyle(LABEL, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT);
+ GuiSetStyle(BUTTON, BORDER_WIDTH, 2);
+ GuiSetStyle(SLIDER, TEXT_PADDING, 4);
+ GuiSetStyle(PROGRESSBAR, TEXT_PADDING, 4);
+ GuiSetStyle(CHECKBOX, TEXT_PADDING, 4);
+ GuiSetStyle(CHECKBOX, TEXT_ALIGNMENT, TEXT_ALIGN_RIGHT);
+ GuiSetStyle(DROPDOWNBOX, TEXT_PADDING, 0);
+ GuiSetStyle(DROPDOWNBOX, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER);
+ GuiSetStyle(TEXTBOX, TEXT_PADDING, 4);
+ GuiSetStyle(TEXTBOX, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT);
+ GuiSetStyle(VALUEBOX, TEXT_PADDING, 0);
+ GuiSetStyle(VALUEBOX, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT);
+ GuiSetStyle(STATUSBAR, TEXT_PADDING, 8);
+ GuiSetStyle(STATUSBAR, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT);
+
+ // Initialize extended property values
+ // NOTE: By default, extended property values are initialized to 0
+ GuiSetStyle(TOGGLE, GROUP_PADDING, 2);
+ GuiSetStyle(SLIDER, SLIDER_WIDTH, 16);
+ GuiSetStyle(SLIDER, SLIDER_PADDING, 1);
+ GuiSetStyle(PROGRESSBAR, PROGRESS_PADDING, 1);
+ GuiSetStyle(CHECKBOX, CHECK_PADDING, 1);
+ GuiSetStyle(COMBOBOX, COMBO_BUTTON_WIDTH, 32);
+ GuiSetStyle(COMBOBOX, COMBO_BUTTON_SPACING, 2);
+ GuiSetStyle(DROPDOWNBOX, ARROW_PADDING, 16);
+ GuiSetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING, 2);
+ GuiSetStyle(VALUEBOX, SPINNER_BUTTON_WIDTH, 24);
+ GuiSetStyle(VALUEBOX, SPINNER_BUTTON_SPACING, 2);
+ GuiSetStyle(SCROLLBAR, BORDER_WIDTH, 0);
+ GuiSetStyle(SCROLLBAR, ARROWS_VISIBLE, 0);
+ GuiSetStyle(SCROLLBAR, ARROWS_SIZE, 6);
+ GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_PADDING, 0);
+ GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, 16);
+ GuiSetStyle(SCROLLBAR, SCROLL_PADDING, 0);
+ GuiSetStyle(SCROLLBAR, SCROLL_SPEED, 12);
+ GuiSetStyle(LISTVIEW, LIST_ITEMS_HEIGHT, 28);
+ GuiSetStyle(LISTVIEW, LIST_ITEMS_SPACING, 2);
+ GuiSetStyle(LISTVIEW, LIST_ITEMS_BORDER_WIDTH, 1);
+ GuiSetStyle(LISTVIEW, SCROLLBAR_WIDTH, 12);
+ GuiSetStyle(LISTVIEW, SCROLLBAR_SIDE, SCROLLBAR_RIGHT_SIDE);
+ GuiSetStyle(COLORPICKER, COLOR_SELECTOR_SIZE, 8);
+ GuiSetStyle(COLORPICKER, HUEBAR_WIDTH, 16);
+ GuiSetStyle(COLORPICKER, HUEBAR_PADDING, 8);
+ GuiSetStyle(COLORPICKER, HUEBAR_SELECTOR_HEIGHT, 8);
+ GuiSetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW, 2);
+
+ if (guiFont.texture.id != GetFontDefault().texture.id)
+ {
+ // Unload previous font texture
+ UnloadTexture(guiFont.texture);
+ RAYGUI_FREE(guiFont.recs);
+ RAYGUI_FREE(guiFont.glyphs);
+ guiFont.recs = NULL;
+ guiFont.glyphs = NULL;
+
+ // Setup default raylib font
+ guiFont = GetFontDefault();
+
+ // NOTE: Default raylib font character 95 is a white square
+ Rectangle whiteChar = guiFont.recs[95];
+
+ // NOTE: We set up a 1px padding on char rectangle to avoid pixel bleeding on MSAA filtering
+ SetShapesTexture(guiFont.texture, RAYGUI_CLITERAL(Rectangle){ whiteChar.x + 1, whiteChar.y + 1, whiteChar.width - 2, whiteChar.height - 2 });
+ }
+}
+
+// Get text with icon id prepended
+// NOTE: Useful to add icons by name id (enum) instead of
+// a number that can change between ricon versions
+const char *GuiIconText(int iconId, const char *text)
+{
+#if defined(RAYGUI_NO_ICONS)
+ return NULL;
+#else
+ static char buffer[1024] = { 0 };
+ static char iconBuffer[16] = { 0 };
+
+ if (text != NULL)
+ {
+ memset(buffer, 0, 1024);
+ snprintf(buffer, 1024, "#%03i#", iconId);
+
+ for (int i = 5; i < 1024; i++)
+ {
+ buffer[i] = text[i - 5];
+ if (text[i - 5] == '\0') break;
+ }
+
+ return buffer;
+ }
+ else
+ {
+ snprintf(iconBuffer, 16, "#%03i#", iconId);
+
+ return iconBuffer;
+ }
+#endif
+}
+
+#if !defined(RAYGUI_NO_ICONS)
+// Get full icons data pointer
+unsigned int *GuiGetIcons(void) { return guiIconsPtr; }
+
+// Load raygui icons file (.rgi)
+// NOTE: In case nameIds are required, they can be requested with loadIconsName,
+// they are returned as a guiIconsName[iconCount][RAYGUI_ICON_MAX_NAME_LENGTH],
+// WARNING: guiIconsName[]][] memory should be manually freed!
+char **GuiLoadIcons(const char *fileName, bool loadIconsName)
+{
+ // Style File Structure (.rgi)
+ // ------------------------------------------------------
+ // Offset | Size | Type | Description
+ // ------------------------------------------------------
+ // 0 | 4 | char | Signature: "rGI "
+ // 4 | 2 | short | Version: 100
+ // 6 | 2 | short | reserved
+
+ // 8 | 2 | short | Num icons (N)
+ // 10 | 2 | short | Icons size (Options: 16, 32, 64) (S)
+
+ // Icons name id (32 bytes per name id)
+ // foreach (icon)
+ // {
+ // 12+32*i | 32 | char | Icon NameId
+ // }
+
+ // Icons data: One bit per pixel, stored as unsigned int array (depends on icon size)
+ // S*S pixels/32bit per unsigned int = K unsigned int per icon
+ // foreach (icon)
+ // {
+ // ... | K | unsigned int | Icon Data
+ // }
+
+ FILE *rgiFile = fopen(fileName, "rb");
+
+ char **guiIconsName = NULL;
+
+ if (rgiFile != NULL)
+ {
+ char signature[5] = { 0 };
+ short version = 0;
+ short reserved = 0;
+ short iconCount = 0;
+ short iconSize = 0;
+
+ fread(signature, 1, 4, rgiFile);
+ fread(&version, sizeof(short), 1, rgiFile);
+ fread(&reserved, sizeof(short), 1, rgiFile);
+ fread(&iconCount, sizeof(short), 1, rgiFile);
+ fread(&iconSize, sizeof(short), 1, rgiFile);
+
+ if ((signature[0] == 'r') &&
+ (signature[1] == 'G') &&
+ (signature[2] == 'I') &&
+ (signature[3] == ' '))
+ {
+ if (loadIconsName)
+ {
+ guiIconsName = (char **)RAYGUI_CALLOC(iconCount, sizeof(char *));
+ for (int i = 0; i < iconCount; i++)
+ {
+ guiIconsName[i] = (char *)RAYGUI_CALLOC(RAYGUI_ICON_MAX_NAME_LENGTH, sizeof(char));
+ fread(guiIconsName[i], 1, RAYGUI_ICON_MAX_NAME_LENGTH, rgiFile);
+ }
+ }
+ else fseek(rgiFile, iconCount*RAYGUI_ICON_MAX_NAME_LENGTH, SEEK_CUR);
+
+ // Read icons data directly over internal icons array
+ fread(guiIconsPtr, sizeof(unsigned int), (int)iconCount*((int)iconSize*(int)iconSize/32), rgiFile);
+ }
+
+ fclose(rgiFile);
+ }
+
+ return guiIconsName;
+}
+
+// Load icons from memory
+// WARNING: Binary files only
+char **GuiLoadIconsFromMemory(const unsigned char *fileData, int dataSize, bool loadIconsName)
+{
+ unsigned char *fileDataPtr = (unsigned char *)fileData;
+ char **guiIconsName = NULL;
+
+ char signature[5] = { 0 };
+ short version = 0;
+ short reserved = 0;
+ short iconCount = 0;
+ short iconSize = 0;
+
+ memcpy(signature, fileDataPtr, 4);
+ memcpy(&version, fileDataPtr + 4, sizeof(short));
+ memcpy(&reserved, fileDataPtr + 4 + 2, sizeof(short));
+ memcpy(&iconCount, fileDataPtr + 4 + 2 + 2, sizeof(short));
+ memcpy(&iconSize, fileDataPtr + 4 + 2 + 2 + 2, sizeof(short));
+ fileDataPtr += 12;
+
+ if ((signature[0] == 'r') &&
+ (signature[1] == 'G') &&
+ (signature[2] == 'I') &&
+ (signature[3] == ' '))
+ {
+ if (loadIconsName)
+ {
+ guiIconsName = (char **)RAYGUI_CALLOC(iconCount, sizeof(char *));
+ for (int i = 0; i < iconCount; i++)
+ {
+ guiIconsName[i] = (char *)RAYGUI_CALLOC(RAYGUI_ICON_MAX_NAME_LENGTH, sizeof(char));
+ memcpy(guiIconsName[i], fileDataPtr, RAYGUI_ICON_MAX_NAME_LENGTH);
+ fileDataPtr += RAYGUI_ICON_MAX_NAME_LENGTH;
+ }
+ }
+ else
+ {
+ // Skip icon name data if not required
+ fileDataPtr += iconCount*RAYGUI_ICON_MAX_NAME_LENGTH;
+ }
+
+ int iconDataSize = iconCount*((int)iconSize*(int)iconSize/32)*(int)sizeof(unsigned int);
+ guiIconsPtr = (unsigned int *)RAYGUI_CALLOC(iconDataSize, 1);
+
+ memcpy(guiIconsPtr, fileDataPtr, iconDataSize);
+ }
+
+ return guiIconsName;
+}
+
+// Draw selected icon using rectangles pixel-by-pixel
+void GuiDrawIcon(int iconId, int posX, int posY, int pixelSize, Color color)
+{
+ #define BIT_CHECK(a,b) ((a) & (1u<<(b)))
+
+ for (int i = 0, y = 0; i < RAYGUI_ICON_SIZE*RAYGUI_ICON_SIZE/32; i++)
+ {
+ for (int k = 0; k < 32; k++)
+ {
+ if (BIT_CHECK(guiIconsPtr[iconId*RAYGUI_ICON_DATA_ELEMENTS + i], k))
+ {
+ #if !defined(RAYGUI_STANDALONE)
+ GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ (float)posX + (k%RAYGUI_ICON_SIZE)*pixelSize, (float)posY + y*pixelSize, (float)pixelSize, (float)pixelSize }, 0, BLANK, color);
+ #endif
+ }
+
+ if ((k == 15) || (k == 31)) y++;
+ }
+ }
+}
+
+// Set icon drawing size
+void GuiSetIconScale(int scale)
+{
+ if (scale >= 1) guiIconScale = scale;
+}
+
+// Get text width considering gui style and icon size (if required)
+int GuiGetTextWidth(const char *text)
+{
+ #if !defined(ICON_TEXT_PADDING)
+ #define ICON_TEXT_PADDING 4
+ #endif
+
+ Vector2 textSize = { 0 };
+ int textIconOffset = 0;
+
+ if ((text != NULL) && (text[0] != '\0'))
+ {
+ if (text[0] == '#')
+ {
+ for (int i = 1; (i < 5) && (text[i] != '\0'); i++)
+ {
+ if (text[i] == '#')
+ {
+ textIconOffset = i;
+ break;
+ }
+ }
+ }
+
+ text += textIconOffset;
+
+ // Make sure guiFont is set, GuiGetStyle() initializes it lazynessly
+ float fontSize = (float)GuiGetStyle(DEFAULT, TEXT_SIZE);
+
+ // Custom MeasureText() implementation
+ if ((guiFont.texture.id > 0) && (text != NULL))
+ {
+ // Get size in bytes of text, considering end of line and line break
+ int size = 0;
+ for (int i = 0; i < MAX_LINE_BUFFER_SIZE; i++)
+ {
+ if ((text[i] != '\0') && (text[i] != '\n')) size++;
+ else break;
+ }
+
+ float scaleFactor = fontSize/(float)guiFont.baseSize;
+ textSize.y = (float)guiFont.baseSize*scaleFactor;
+ float glyphWidth = 0.0f;
+
+ for (int i = 0, codepointSize = 0; i < size; i += codepointSize)
+ {
+ int codepoint = GetCodepointNext(&text[i], &codepointSize);
+ int codepointIndex = GetGlyphIndex(guiFont, codepoint);
+
+ if (guiFont.glyphs[codepointIndex].advanceX == 0) glyphWidth = ((float)guiFont.recs[codepointIndex].width*scaleFactor);
+ else glyphWidth = ((float)guiFont.glyphs[codepointIndex].advanceX*scaleFactor);
+
+ textSize.x += (glyphWidth + (float)GuiGetStyle(DEFAULT, TEXT_SPACING));
+ }
+ }
+
+ if (textIconOffset > 0) textSize.x += (RAYGUI_ICON_SIZE + ICON_TEXT_PADDING);
+ }
+
+ return (int)textSize.x;
+}
+
+#endif // !RAYGUI_NO_ICONS
+
+//----------------------------------------------------------------------------------
+// Module Internal Functions Definition
+//----------------------------------------------------------------------------------
+// Load style from memory
+// WARNING: Binary files only
+static void GuiLoadStyleFromMemory(const unsigned char *fileData, int dataSize)
+{
+ unsigned char *fileDataPtr = (unsigned char *)fileData;
+
+ char signature[5] = { 0 };
+ short version = 0;
+ short reserved = 0;
+ int propertyCount = 0;
+
+ memcpy(signature, fileDataPtr, 4);
+ memcpy(&version, fileDataPtr + 4, sizeof(short));
+ memcpy(&reserved, fileDataPtr + 4 + 2, sizeof(short));
+ memcpy(&propertyCount, fileDataPtr + 4 + 2 + 2, sizeof(int));
+ fileDataPtr += 12;
+
+ if ((signature[0] == 'r') &&
+ (signature[1] == 'G') &&
+ (signature[2] == 'S') &&
+ (signature[3] == ' '))
+ {
+ short controlId = 0;
+ short propertyId = 0;
+ unsigned int propertyValue = 0;
+
+ for (int i = 0; i < propertyCount; i++)
+ {
+ memcpy(&controlId, fileDataPtr, sizeof(short));
+ memcpy(&propertyId, fileDataPtr + 2, sizeof(short));
+ memcpy(&propertyValue, fileDataPtr + 2 + 2, sizeof(unsigned int));
+ fileDataPtr += 8;
+
+ if (controlId == 0) // DEFAULT control
+ {
+ // If a DEFAULT property is loaded, it is propagated to all controls
+ // NOTE: All DEFAULT properties should be defined first in the file
+ GuiSetStyle(0, (int)propertyId, propertyValue);
+
+ if (propertyId < RAYGUI_MAX_PROPS_BASE) for (int j = 1; j < RAYGUI_MAX_CONTROLS; j++) GuiSetStyle(j, (int)propertyId, propertyValue);
+ }
+ else GuiSetStyle((int)controlId, (int)propertyId, propertyValue);
+ }
+
+ // Font loading is highly dependant on raylib API to load font data and image
+
+#if !defined(RAYGUI_STANDALONE)
+ // Load custom font if available
+ int fontDataSize = 0;
+ memcpy(&fontDataSize, fileDataPtr, sizeof(int));
+ fileDataPtr += 4;
+
+ if (fontDataSize > 0)
+ {
+ Font font = { 0 };
+ int fontType = 0; // 0-Normal, 1-SDF
+
+ memcpy(&font.baseSize, fileDataPtr, sizeof(int));
+ memcpy(&font.glyphCount, fileDataPtr + 4, sizeof(int));
+ memcpy(&fontType, fileDataPtr + 4 + 4, sizeof(int));
+ fileDataPtr += 12;
+
+ // Load font white rectangle
+ Rectangle fontWhiteRec = { 0 };
+ memcpy(&fontWhiteRec, fileDataPtr, sizeof(Rectangle));
+ fileDataPtr += 16;
+
+ // Load font image parameters
+ int fontImageUncompSize = 0;
+ int fontImageCompSize = 0;
+ memcpy(&fontImageUncompSize, fileDataPtr, sizeof(int));
+ memcpy(&fontImageCompSize, fileDataPtr + 4, sizeof(int));
+ fileDataPtr += 8;
+
+ Image imFont = { 0 };
+ imFont.mipmaps = 1;
+ memcpy(&imFont.width, fileDataPtr, sizeof(int));
+ memcpy(&imFont.height, fileDataPtr + 4, sizeof(int));
+ memcpy(&imFont.format, fileDataPtr + 4 + 4, sizeof(int));
+ fileDataPtr += 12;
+
+ if ((fontImageCompSize > 0) && (fontImageCompSize != fontImageUncompSize))
+ {
+ // Compressed font atlas image data (DEFLATE), it requires DecompressData()
+ int dataUncompSize = 0;
+ unsigned char *compData = (unsigned char *)RAYGUI_CALLOC(fontImageCompSize, sizeof(unsigned char));
+ memcpy(compData, fileDataPtr, fontImageCompSize);
+ fileDataPtr += fontImageCompSize;
+
+ imFont.data = DecompressData(compData, fontImageCompSize, &dataUncompSize);
+
+ // Security check, dataUncompSize must match the provided fontImageUncompSize
+ if (dataUncompSize != fontImageUncompSize) RAYGUI_LOG("WARNING: Uncompressed font atlas image data could be corrupted");
+
+ RAYGUI_FREE(compData);
+ }
+ else
+ {
+ // Font atlas image data is not compressed
+ imFont.data = (unsigned char *)RAYGUI_CALLOC(fontImageUncompSize, sizeof(unsigned char));
+ memcpy(imFont.data, fileDataPtr, fontImageUncompSize);
+ fileDataPtr += fontImageUncompSize;
+ }
+
+ if (font.texture.id != GetFontDefault().texture.id) UnloadTexture(font.texture);
+ font.texture = LoadTextureFromImage(imFont);
+
+ RAYGUI_FREE(imFont.data);
+
+ // Validate font atlas texture was loaded correctly
+ if (font.texture.id != 0)
+ {
+ // Load font recs data
+ int recsDataSize = font.glyphCount*sizeof(Rectangle);
+ int recsDataCompressedSize = 0;
+
+ // WARNING: Version 400 adds the compression size parameter
+ if (version >= 400)
+ {
+ // RGS files version 400 support compressed recs data
+ memcpy(&recsDataCompressedSize, fileDataPtr, sizeof(int));
+ fileDataPtr += sizeof(int);
+ }
+
+ if ((recsDataCompressedSize > 0) && (recsDataCompressedSize != recsDataSize))
+ {
+ // Recs data is compressed, uncompress it
+ unsigned char *recsDataCompressed = (unsigned char *)RAYGUI_CALLOC(recsDataCompressedSize, sizeof(unsigned char));
+
+ memcpy(recsDataCompressed, fileDataPtr, recsDataCompressedSize);
+ fileDataPtr += recsDataCompressedSize;
+
+ int recsDataUncompSize = 0;
+ font.recs = (Rectangle *)DecompressData(recsDataCompressed, recsDataCompressedSize, &recsDataUncompSize);
+
+ // Security check, data uncompressed size must match the expected original data size
+ if (recsDataUncompSize != recsDataSize) RAYGUI_LOG("WARNING: Uncompressed font recs data could be corrupted");
+
+ RAYGUI_FREE(recsDataCompressed);
+ }
+ else
+ {
+ // Recs data is uncompressed
+ font.recs = (Rectangle *)RAYGUI_CALLOC(font.glyphCount, sizeof(Rectangle));
+ for (int i = 0; i < font.glyphCount; i++)
+ {
+ memcpy(&font.recs[i], fileDataPtr, sizeof(Rectangle));
+ fileDataPtr += sizeof(Rectangle);
+ }
+ }
+
+ // Load font glyphs info data
+ int glyphsDataSize = font.glyphCount*16; // 16 bytes data per glyph
+ int glyphsDataCompressedSize = 0;
+
+ // WARNING: Version 400 adds the compression size parameter
+ if (version >= 400)
+ {
+ // RGS files version 400 support compressed glyphs data
+ memcpy(&glyphsDataCompressedSize, fileDataPtr, sizeof(int));
+ fileDataPtr += sizeof(int);
+ }
+
+ // Allocate required glyphs space to fill with data
+ font.glyphs = (GlyphInfo *)RAYGUI_CALLOC(font.glyphCount, sizeof(GlyphInfo));
+
+ if ((glyphsDataCompressedSize > 0) && (glyphsDataCompressedSize != glyphsDataSize))
+ {
+ // Glyphs data is compressed, uncompress it
+ unsigned char *glypsDataCompressed = (unsigned char *)RAYGUI_CALLOC(glyphsDataCompressedSize, sizeof(unsigned char));
+
+ memcpy(glypsDataCompressed, fileDataPtr, glyphsDataCompressedSize);
+ fileDataPtr += glyphsDataCompressedSize;
+
+ int glyphsDataUncompSize = 0;
+ unsigned char *glyphsDataUncomp = DecompressData(glypsDataCompressed, glyphsDataCompressedSize, &glyphsDataUncompSize);
+
+ // Security check, data uncompressed size must match the expected original data size
+ if (glyphsDataUncompSize != glyphsDataSize) RAYGUI_LOG("WARNING: Uncompressed font glyphs data could be corrupted");
+
+ unsigned char *glyphsDataUncompPtr = glyphsDataUncomp;
+
+ for (int i = 0; i < font.glyphCount; i++)
+ {
+ memcpy(&font.glyphs[i].value, glyphsDataUncompPtr, sizeof(int));
+ memcpy(&font.glyphs[i].offsetX, glyphsDataUncompPtr + 4, sizeof(int));
+ memcpy(&font.glyphs[i].offsetY, glyphsDataUncompPtr + 8, sizeof(int));
+ memcpy(&font.glyphs[i].advanceX, glyphsDataUncompPtr + 12, sizeof(int));
+ glyphsDataUncompPtr += 16;
+ }
+
+ RAYGUI_FREE(glypsDataCompressed);
+ RAYGUI_FREE(glyphsDataUncomp);
+ }
+ else
+ {
+ // Glyphs data is uncompressed
+ for (int i = 0; i < font.glyphCount; i++)
+ {
+ memcpy(&font.glyphs[i].value, fileDataPtr, sizeof(int));
+ memcpy(&font.glyphs[i].offsetX, fileDataPtr + 4, sizeof(int));
+ memcpy(&font.glyphs[i].offsetY, fileDataPtr + 8, sizeof(int));
+ memcpy(&font.glyphs[i].advanceX, fileDataPtr + 12, sizeof(int));
+ fileDataPtr += 16;
+ }
+ }
+ }
+ else font = GetFontDefault(); // Fallback in case of errors loading font atlas texture
+
+ GuiSetFont(font);
+
+ // Set font texture source rectangle to be used as white texture to draw shapes
+ // NOTE: It makes possible to draw shapes and text (full UI) in a single draw call
+ if ((fontWhiteRec.x > 0) &&
+ (fontWhiteRec.y > 0) &&
+ (fontWhiteRec.width > 0) &&
+ (fontWhiteRec.height > 0)) SetShapesTexture(font.texture, fontWhiteRec);
+ }
+#endif
+ }
+}
+
+// Get text bounds considering control bounds
+static Rectangle GetTextBounds(int control, Rectangle bounds)
+{
+ Rectangle textBounds = bounds;
+
+ textBounds.x = bounds.x + GuiGetStyle(control, BORDER_WIDTH);
+ textBounds.y = bounds.y + GuiGetStyle(control, BORDER_WIDTH) + GuiGetStyle(control, TEXT_PADDING);
+ textBounds.width = bounds.width - 2*GuiGetStyle(control, BORDER_WIDTH) - 2*GuiGetStyle(control, TEXT_PADDING);
+ textBounds.height = bounds.height - 2*GuiGetStyle(control, BORDER_WIDTH) - 2*GuiGetStyle(control, TEXT_PADDING); // NOTE: Text is processed line per line!
+
+ // Depending on control, TEXT_PADDING and TEXT_ALIGNMENT properties could affect the text-bounds
+ switch (control)
+ {
+ case COMBOBOX:
+ case DROPDOWNBOX:
+ case LISTVIEW:
+ // TODO: Special cases (no label): COMBOBOX, DROPDOWNBOX, LISTVIEW
+ case SLIDER:
+ case CHECKBOX:
+ case VALUEBOX:
+ case CONTROL11:
+ // TODO: More special cases (label on side): SLIDER, CHECKBOX, VALUEBOX, SPINNER
+ default:
+ {
+ // TODO: WARNING: TEXT_ALIGNMENT is already considered in GuiDrawText()
+ if (GuiGetStyle(control, TEXT_ALIGNMENT) == TEXT_ALIGN_RIGHT) textBounds.x -= GuiGetStyle(control, TEXT_PADDING);
+ else textBounds.x += GuiGetStyle(control, TEXT_PADDING);
+ }
+ break;
+ }
+
+ return textBounds;
+}
+
+// Get text icon if provided and move text cursor
+// NOTE: We support up to 999 values for iconId
+static const char *GetTextIcon(const char *text, int *iconId)
+{
+#if !defined(RAYGUI_NO_ICONS)
+ *iconId = -1;
+ if (text[0] == '#') // Maybe we have an icon!
+ {
+ char iconValue[4] = { 0 }; // Maximum length for icon value: 3 digits + '\0'
+
+ int pos = 1;
+ while ((pos < 4) && (text[pos] >= '0') && (text[pos] <= '9'))
+ {
+ iconValue[pos - 1] = text[pos];
+ pos++;
+ }
+
+ if (text[pos] == '#')
+ {
+ *iconId = TextToInteger(iconValue);
+
+ // Move text pointer after icon
+ // WARNING: If only icon provided, it could point to EOL character: '\0'
+ if (*iconId >= 0) text += (pos + 1);
+ }
+ }
+#endif
+
+ return text;
+}
+
+// Get text divided into lines (by line-breaks '\n')
+// WARNING: It returns pointers to new lines but it does not add NULL ('\0') terminator!
+static const char **GetTextLines(const char *text, int *count)
+{
+ #define RAYGUI_MAX_TEXT_LINES 128
+
+ static const char *lines[RAYGUI_MAX_TEXT_LINES] = { 0 };
+ for (int i = 0; i < RAYGUI_MAX_TEXT_LINES; i++) lines[i] = NULL; // Init NULL pointers to substrings
+
+ int textLength = (int)strlen(text);
+
+ lines[0] = text;
+ *count = 1;
+
+ for (int i = 0, k = 0; (i < textLength) && (*count < RAYGUI_MAX_TEXT_LINES); i++)
+ {
+ if (text[i] == '\n')
+ {
+ k++;
+ lines[k] = &text[i + 1]; // WARNING: next value is valid?
+ *count += 1;
+ }
+ }
+
+ return lines;
+}
+
+// Get text width to next space for provided string
+static float GetNextSpaceWidth(const char *text, int *nextSpaceIndex)
+{
+ float width = 0;
+ int codepointByteCount = 0;
+ int codepoint = 0;
+ int index = 0;
+ float glyphWidth = 0;
+ float scaleFactor = (float)GuiGetStyle(DEFAULT, TEXT_SIZE)/guiFont.baseSize;
+
+ for (int i = 0; text[i] != '\0'; i++)
+ {
+ if (text[i] != ' ')
+ {
+ codepoint = GetCodepoint(&text[i], &codepointByteCount);
+ index = GetGlyphIndex(guiFont, codepoint);
+ glyphWidth = (guiFont.glyphs[index].advanceX == 0)? guiFont.recs[index].width*scaleFactor : guiFont.glyphs[index].advanceX*scaleFactor;
+ width += (glyphWidth + (float)GuiGetStyle(DEFAULT, TEXT_SPACING));
+ }
+ else
+ {
+ *nextSpaceIndex = i;
+ break;
+ }
+ }
+
+ return width;
+}
+
+// Gui draw text using default font
+static void GuiDrawText(const char *text, Rectangle textBounds, int alignment, Color tint)
+{
+ #define TEXT_VALIGN_PIXEL_OFFSET(h) ((int)h%2) // Vertical alignment for pixel perfect
+
+ #if !defined(ICON_TEXT_PADDING)
+ #define ICON_TEXT_PADDING 4
+ #endif
+
+ if ((text == NULL) || (text[0] == '\0')) return; // Security check
+
+ // PROCEDURE:
+ // - Text is processed line per line
+ // - For every line, horizontal alignment is defined
+ // - For all text, vertical alignment is defined (multiline text only)
+ // - For every line, wordwrap mode is checked (useful for GuitextBox(), read-only)
+
+ // Get text lines (using '\n' as delimiter) to be processed individually
+ // WARNING: We can't use GuiTextSplit() function because it can be already used
+ // before the GuiDrawText() call and its buffer is static, it would be overriden :(
+ int lineCount = 0;
+ const char **lines = GetTextLines(text, &lineCount);
+
+ // Text style variables
+ //int alignment = GuiGetStyle(DEFAULT, TEXT_ALIGNMENT);
+ int alignmentVertical = GuiGetStyle(DEFAULT, TEXT_ALIGNMENT_VERTICAL);
+ int wrapMode = GuiGetStyle(DEFAULT, TEXT_WRAP_MODE); // Wrap-mode only available in read-only mode, no for text editing
+
+ // TODO: WARNING: This totalHeight is not valid for vertical alignment in case of word-wrap
+ float totalHeight = (float)(lineCount*GuiGetStyle(DEFAULT, TEXT_SIZE) + (lineCount - 1)*GuiGetStyle(DEFAULT, TEXT_SIZE)/2);
+ float posOffsetY = 0.0f;
+
+ for (int i = 0; i < lineCount; i++)
+ {
+ int iconId = 0;
+ lines[i] = GetTextIcon(lines[i], &iconId); // Check text for icon and move cursor
+
+ // Get text position depending on alignment and iconId
+ //---------------------------------------------------------------------------------
+ Vector2 textBoundsPosition = { textBounds.x, textBounds.y };
+ float textBoundsWidthOffset = 0.0f;
+
+ // NOTE: We get text size after icon has been processed
+ // WARNING: GuiGetTextWidth() also processes text icon to get width! -> Really needed?
+ int textSizeX = GuiGetTextWidth(lines[i]);
+
+ // If text requires an icon, add size to measure
+ if (iconId >= 0)
+ {
+ textSizeX += RAYGUI_ICON_SIZE*guiIconScale;
+
+ // WARNING: If only icon provided, text could be pointing to EOF character: '\0'
+#if !defined(RAYGUI_NO_ICONS)
+ if ((lines[i] != NULL) && (lines[i][0] != '\0')) textSizeX += ICON_TEXT_PADDING;
+#endif
+ }
+
+ // Check guiTextAlign global variables
+ switch (alignment)
+ {
+ case TEXT_ALIGN_LEFT: textBoundsPosition.x = textBounds.x; break;
+ case TEXT_ALIGN_CENTER: textBoundsPosition.x = textBounds.x + textBounds.width/2 - textSizeX/2; break;
+ case TEXT_ALIGN_RIGHT: textBoundsPosition.x = textBounds.x + textBounds.width - textSizeX; break;
+ default: break;
+ }
+
+ if (textSizeX > textBounds.width && (lines[i] != NULL) && (lines[i][0] != '\0')) textBoundsPosition.x = textBounds.x;
+
+ switch (alignmentVertical)
+ {
+ // Only valid in case of wordWrap = 0;
+ case TEXT_ALIGN_TOP: textBoundsPosition.y = textBounds.y + posOffsetY; break;
+ case TEXT_ALIGN_MIDDLE: textBoundsPosition.y = textBounds.y + posOffsetY + textBounds.height/2 - totalHeight/2 + TEXT_VALIGN_PIXEL_OFFSET(textBounds.height); break;
+ case TEXT_ALIGN_BOTTOM: textBoundsPosition.y = textBounds.y + posOffsetY + textBounds.height - totalHeight + TEXT_VALIGN_PIXEL_OFFSET(textBounds.height); break;
+ default: break;
+ }
+
+ // NOTE: Make sure we get pixel-perfect coordinates,
+ // In case of decimals we got weird text positioning
+ textBoundsPosition.x = (float)((int)textBoundsPosition.x);
+ textBoundsPosition.y = (float)((int)textBoundsPosition.y);
+ //---------------------------------------------------------------------------------
+
+ // Draw text (with icon if available)
+ //---------------------------------------------------------------------------------
+#if !defined(RAYGUI_NO_ICONS)
+ if (iconId >= 0)
+ {
+ // NOTE: We consider icon height, probably different than text size
+ GuiDrawIcon(iconId, (int)textBoundsPosition.x, (int)(textBounds.y + textBounds.height/2 - RAYGUI_ICON_SIZE*guiIconScale/2 + TEXT_VALIGN_PIXEL_OFFSET(textBounds.height)), guiIconScale, tint);
+ textBoundsPosition.x += (float)(RAYGUI_ICON_SIZE*guiIconScale + ICON_TEXT_PADDING);
+ textBoundsWidthOffset = (float)(RAYGUI_ICON_SIZE*guiIconScale + ICON_TEXT_PADDING);
+ }
+#endif
+ // Get size in bytes of text,
+ // considering end of line and line break
+ int lineSize = 0;
+ for (int c = 0; (lines[i][c] != '\0') && (lines[i][c] != '\n') && (lines[i][c] != '\r'); c++, lineSize++){ }
+ float scaleFactor = (float)GuiGetStyle(DEFAULT, TEXT_SIZE)/guiFont.baseSize;
+
+ int lastSpaceIndex = 0;
+ bool tempWrapCharMode = false;
+
+ int textOffsetY = 0;
+ float textOffsetX = 0.0f;
+ float glyphWidth = 0;
+
+ int ellipsisWidth = GuiGetTextWidth("...");
+ bool textOverflow = false;
+ for (int c = 0, codepointSize = 0; c < lineSize; c += codepointSize)
+ {
+ int codepoint = GetCodepointNext(&lines[i][c], &codepointSize);
+ int index = GetGlyphIndex(guiFont, codepoint);
+
+ // NOTE: Normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f)
+ // but we need to draw all of the bad bytes using the '?' symbol moving one byte
+ if (codepoint == 0x3f) codepointSize = 1; // TODO: Review not recognized codepoints size
+
+ // Get glyph width to check if it goes out of bounds
+ if (guiFont.glyphs[index].advanceX == 0) glyphWidth = ((float)guiFont.recs[index].width*scaleFactor);
+ else glyphWidth = (float)guiFont.glyphs[index].advanceX*scaleFactor;
+
+ // Wrap mode text measuring, to validate if
+ // it can be drawn or a new line is required
+ if (wrapMode == TEXT_WRAP_CHAR)
+ {
+ // Jump to next line if current character reach end of the box limits
+ if ((textOffsetX + glyphWidth) > textBounds.width - textBoundsWidthOffset)
+ {
+ textOffsetX = 0.0f;
+ textOffsetY += GuiGetStyle(DEFAULT, TEXT_LINE_SPACING);
+
+ if (tempWrapCharMode) // Wrap at char level when too long words
+ {
+ wrapMode = TEXT_WRAP_WORD;
+ tempWrapCharMode = false;
+ }
+ }
+ }
+ else if (wrapMode == TEXT_WRAP_WORD)
+ {
+ if (codepoint == 32) lastSpaceIndex = c;
+
+ // Get width to next space in line
+ int nextSpaceIndex = 0;
+ float nextSpaceWidth = GetNextSpaceWidth(lines[i] + c, &nextSpaceIndex);
+
+ int nextSpaceIndex2 = 0;
+ float nextWordSize = GetNextSpaceWidth(lines[i] + lastSpaceIndex + 1, &nextSpaceIndex2);
+
+ if (nextWordSize > textBounds.width - textBoundsWidthOffset)
+ {
+ // Considering the case the next word is longer than bounds
+ tempWrapCharMode = true;
+ wrapMode = TEXT_WRAP_CHAR;
+ }
+ else if ((textOffsetX + nextSpaceWidth) > textBounds.width - textBoundsWidthOffset)
+ {
+ textOffsetX = 0.0f;
+ textOffsetY += GuiGetStyle(DEFAULT, TEXT_LINE_SPACING);
+ }
+ }
+
+ if (codepoint == '\n') break; // WARNING: Lines are already processed manually, no need to keep drawing after this codepoint
+ else
+ {
+ // TODO: There are multiple types of spaces in Unicode,
+ // maybe it's a good idea to add support for more: http://jkorpela.fi/chars/spaces.html
+ if ((codepoint != ' ') && (codepoint != '\t')) // Do not draw codepoints with no glyph
+ {
+ if (wrapMode == TEXT_WRAP_NONE)
+ {
+ // Draw only required text glyphs fitting the textBounds.width
+ if (textSizeX > textBounds.width)
+ {
+ if (textOffsetX <= (textBounds.width - glyphWidth - textBoundsWidthOffset - ellipsisWidth))
+ {
+ DrawTextCodepoint(guiFont, codepoint, RAYGUI_CLITERAL(Vector2){ textBoundsPosition.x + textOffsetX, textBoundsPosition.y + textOffsetY }, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), GuiFade(tint, guiAlpha));
+ }
+ else if (!textOverflow)
+ {
+ textOverflow = true;
+
+ for (int j = 0; j < ellipsisWidth; j += ellipsisWidth/3)
+ {
+ DrawTextCodepoint(guiFont, '.', RAYGUI_CLITERAL(Vector2){ textBoundsPosition.x + textOffsetX + j, textBoundsPosition.y + textOffsetY }, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), GuiFade(tint, guiAlpha));
+ }
+ }
+ }
+ else
+ {
+ DrawTextCodepoint(guiFont, codepoint, RAYGUI_CLITERAL(Vector2){ textBoundsPosition.x + textOffsetX, textBoundsPosition.y + textOffsetY }, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), GuiFade(tint, guiAlpha));
+ }
+ }
+ else if ((wrapMode == TEXT_WRAP_CHAR) || (wrapMode == TEXT_WRAP_WORD))
+ {
+ // Draw only glyphs inside the bounds
+ if ((textBoundsPosition.y + textOffsetY) <= (textBounds.y + textBounds.height - GuiGetStyle(DEFAULT, TEXT_SIZE)))
+ {
+ DrawTextCodepoint(guiFont, codepoint, RAYGUI_CLITERAL(Vector2){ textBoundsPosition.x + textOffsetX, textBoundsPosition.y + textOffsetY }, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), GuiFade(tint, guiAlpha));
+ }
+ }
+ }
+
+ if (guiFont.glyphs[index].advanceX == 0) textOffsetX += ((float)guiFont.recs[index].width*scaleFactor + (float)GuiGetStyle(DEFAULT, TEXT_SPACING));
+ else textOffsetX += ((float)guiFont.glyphs[index].advanceX*scaleFactor + (float)GuiGetStyle(DEFAULT, TEXT_SPACING));
+ }
+ }
+
+ if (wrapMode == TEXT_WRAP_NONE) posOffsetY += (float)GuiGetStyle(DEFAULT, TEXT_LINE_SPACING);
+ else if ((wrapMode == TEXT_WRAP_CHAR) || (wrapMode == TEXT_WRAP_WORD)) posOffsetY += (textOffsetY + (float)GuiGetStyle(DEFAULT, TEXT_LINE_SPACING));
+ //---------------------------------------------------------------------------------
+ }
+
+#if defined(RAYGUI_DEBUG_TEXT_BOUNDS)
+ GuiDrawRectangle(textBounds, 0, WHITE, Fade(BLUE, 0.4f));
+#endif
+}
+
+// Gui draw rectangle using default raygui plain style with borders
+static void GuiDrawRectangle(Rectangle rec, int borderWidth, Color borderColor, Color color)
+{
+ if (color.a > 0)
+ {
+ // Draw rectangle filled with color
+ DrawRectangle((int)rec.x, (int)rec.y, (int)rec.width, (int)rec.height, GuiFade(color, guiAlpha));
+ }
+
+ if (borderWidth > 0)
+ {
+ // Draw rectangle border lines with color
+ DrawRectangle((int)rec.x, (int)rec.y, (int)rec.width, borderWidth, GuiFade(borderColor, guiAlpha));
+ DrawRectangle((int)rec.x, (int)rec.y + borderWidth, borderWidth, (int)rec.height - 2*borderWidth, GuiFade(borderColor, guiAlpha));
+ DrawRectangle((int)rec.x + (int)rec.width - borderWidth, (int)rec.y + borderWidth, borderWidth, (int)rec.height - 2*borderWidth, GuiFade(borderColor, guiAlpha));
+ DrawRectangle((int)rec.x, (int)rec.y + (int)rec.height - borderWidth, (int)rec.width, borderWidth, GuiFade(borderColor, guiAlpha));
+ }
+
+#if defined(RAYGUI_DEBUG_RECS_BOUNDS)
+ DrawRectangle((int)rec.x, (int)rec.y, (int)rec.width, (int)rec.height, Fade(RED, 0.4f));
+#endif
+}
+
+// Draw tooltip using control bounds
+static void GuiTooltip(Rectangle controlRec)
+{
+ if (!guiLocked && guiTooltip && (guiTooltipPtr != NULL) && !guiControlExclusiveMode)
+ {
+ Vector2 textSize = MeasureTextEx(GuiGetFont(), guiTooltipPtr, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), (float)GuiGetStyle(DEFAULT, TEXT_SPACING));
+
+ if ((controlRec.x + textSize.x + 16) > GetScreenWidth()) controlRec.x -= (textSize.x + 16 - controlRec.width);
+
+ GuiPanel(RAYGUI_CLITERAL(Rectangle){ controlRec.x, controlRec.y + controlRec.height + 4, textSize.x + 16, GuiGetStyle(DEFAULT, TEXT_SIZE) + 8.0f }, NULL);
+
+ int textPadding = GuiGetStyle(LABEL, TEXT_PADDING);
+ int textAlignment = GuiGetStyle(LABEL, TEXT_ALIGNMENT);
+ GuiSetStyle(LABEL, TEXT_PADDING, 0);
+ GuiSetStyle(LABEL, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER);
+ GuiLabel(RAYGUI_CLITERAL(Rectangle){ controlRec.x, controlRec.y + controlRec.height + 4, textSize.x + 16, GuiGetStyle(DEFAULT, TEXT_SIZE) + 8.0f }, guiTooltipPtr);
+ GuiSetStyle(LABEL, TEXT_ALIGNMENT, textAlignment);
+ GuiSetStyle(LABEL, TEXT_PADDING, textPadding);
+ }
+}
+
+// Split controls text into multiple strings
+// Also check for multiple columns (required by GuiToggleGroup())
+static const char **GuiTextSplit(const char *text, char delimiter, int *count, int *textRow)
+{
+ // NOTE: Current implementation returns a copy of the provided string with '\0' (string end delimiter)
+ // inserted between strings defined by "delimiter" parameter. No memory is dynamically allocated,
+ // all used memory is static... it has some limitations:
+ // 1. Maximum number of possible split strings is set by RAYGUI_TEXTSPLIT_MAX_ITEMS
+ // 2. Maximum size of text to split is RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE
+ // NOTE: Those definitions could be externally provided if required
+
+ // TODO: HACK: GuiTextSplit() - Review how textRows are returned to user
+ // textRow is an externally provided array of integers that stores row number for every splitted string
+
+ #if !defined(RAYGUI_TEXTSPLIT_MAX_ITEMS)
+ #define RAYGUI_TEXTSPLIT_MAX_ITEMS 128
+ #endif
+ #if !defined(RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE)
+ #define RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE 1024
+ #endif
+
+ static const char *result[RAYGUI_TEXTSPLIT_MAX_ITEMS] = { NULL }; // String pointers array (points to buffer data)
+ static char buffer[RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE] = { 0 }; // Buffer data (text input copy with '\0' added)
+ memset(buffer, 0, RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE);
+
+ result[0] = buffer;
+ int counter = 1;
+
+ if (textRow != NULL) textRow[0] = 0;
+
+ // Count how many substrings we have on text and point to every one
+ for (int i = 0; i < RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE; i++)
+ {
+ buffer[i] = text[i];
+ if (buffer[i] == '\0') break;
+ else if ((buffer[i] == delimiter) || (buffer[i] == '\n'))
+ {
+ result[counter] = buffer + i + 1;
+
+ if (textRow != NULL)
+ {
+ if (buffer[i] == '\n') textRow[counter] = textRow[counter - 1] + 1;
+ else textRow[counter] = textRow[counter - 1];
+ }
+
+ buffer[i] = '\0'; // Set an end of string at this point
+
+ counter++;
+ if (counter >= RAYGUI_TEXTSPLIT_MAX_ITEMS) break;
+ }
+ }
+
+ *count = counter;
+
+ return result;
+}
+
+// Convert color data from RGB to HSV
+// NOTE: Color data should be passed normalized
+static Vector3 ConvertRGBtoHSV(Vector3 rgb)
+{
+ Vector3 hsv = { 0 };
+ float min = 0.0f;
+ float max = 0.0f;
+ float delta = 0.0f;
+
+ 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;
+
+ hsv.z = max; // Value
+ delta = max - min;
+
+ if (delta < 0.00001f)
+ {
+ hsv.y = 0.0f;
+ hsv.x = 0.0f; // Undefined, maybe NAN?
+ return hsv;
+ }
+
+ if (max > 0.0f)
+ {
+ // NOTE: If max is 0, this divide would cause a crash
+ hsv.y = (delta/max); // Saturation
+ }
+ else
+ {
+ // NOTE: If max is 0, then r = g = b = 0, s = 0, h is undefined
+ hsv.y = 0.0f;
+ hsv.x = 0.0f; // Undefined, maybe NAN?
+ return hsv;
+ }
+
+ // NOTE: Comparing float values could not work properly
+ if (rgb.x >= max) hsv.x = (rgb.y - rgb.z)/delta; // Between yellow & magenta
+ else
+ {
+ if (rgb.y >= max) hsv.x = 2.0f + (rgb.z - rgb.x)/delta; // Between cyan & yellow
+ else hsv.x = 4.0f + (rgb.x - rgb.y)/delta; // Between magenta & cyan
+ }
+
+ hsv.x *= 60.0f; // Convert to degrees
+
+ if (hsv.x < 0.0f) hsv.x += 360.0f;
+
+ return hsv;
+}
+
+// Convert color data from HSV to RGB
+// NOTE: Color data should be passed normalized
+static Vector3 ConvertHSVtoRGB(Vector3 hsv)
+{
+ Vector3 rgb = { 0 };
+ float hh = 0.0f, p = 0.0f, q = 0.0f, t = 0.0f, ff = 0.0f;
+ long i = 0;
+
+ // NOTE: Comparing float values could not work properly
+ if (hsv.y <= 0.0f)
+ {
+ rgb.x = hsv.z;
+ rgb.y = hsv.z;
+ rgb.z = hsv.z;
+ return rgb;
+ }
+
+ hh = hsv.x;
+ if (hh >= 360.0f) hh = 0.0f;
+ hh /= 60.0f;
+
+ i = (long)hh;
+ ff = hh - i;
+ p = hsv.z*(1.0f - hsv.y);
+ q = hsv.z*(1.0f - (hsv.y*ff));
+ t = hsv.z*(1.0f - (hsv.y*(1.0f - ff)));
+
+ switch (i)
+ {
+ case 0:
+ {
+ rgb.x = hsv.z;
+ rgb.y = t;
+ rgb.z = p;
+ } break;
+ case 1:
+ {
+ rgb.x = q;
+ rgb.y = hsv.z;
+ rgb.z = p;
+ } break;
+ case 2:
+ {
+ rgb.x = p;
+ rgb.y = hsv.z;
+ rgb.z = t;
+ } break;
+ case 3:
+ {
+ rgb.x = p;
+ rgb.y = q;
+ rgb.z = hsv.z;
+ } break;
+ case 4:
+ {
+ rgb.x = t;
+ rgb.y = p;
+ rgb.z = hsv.z;
+ } break;
+ case 5:
+ default:
+ {
+ rgb.x = hsv.z;
+ rgb.y = p;
+ rgb.z = q;
+ } break;
+ }
+
+ return rgb;
+}
+
+// Scroll bar control (used by GuiScrollPanel())
+static int GuiScrollBar(Rectangle bounds, int value, int minValue, int maxValue)
+{
+ GuiState state = guiState;
+
+ // Is the scrollbar horizontal or vertical?
+ bool isVertical = (bounds.width > bounds.height)? false : true;
+
+ // The size (width or height depending on scrollbar type) of the spinner buttons
+ const int spinnerSize = GuiGetStyle(SCROLLBAR, ARROWS_VISIBLE)?
+ (isVertical? (int)bounds.width - 2*GuiGetStyle(SCROLLBAR, BORDER_WIDTH) :
+ (int)bounds.height - 2*GuiGetStyle(SCROLLBAR, BORDER_WIDTH)) : 0;
+
+ // Arrow buttons [<] [>] [∧] [∨]
+ Rectangle arrowUpLeft = { 0 };
+ Rectangle arrowDownRight = { 0 };
+
+ // Actual area of the scrollbar excluding the arrow buttons
+ Rectangle scrollbar = { 0 };
+
+ // Slider bar that moves --[///]-----
+ Rectangle slider = { 0 };
+
+ // Normalize value
+ if (value > maxValue) value = maxValue;
+ if (value < minValue) value = minValue;
+
+ int valueRange = maxValue - minValue;
+ if (valueRange <= 0) valueRange = 1;
+
+ int sliderSize = GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE);
+ if (sliderSize < 1) sliderSize = 1; // TODO: Consider a minimum slider size
+
+ // Calculate rectangles for all of the components
+ arrowUpLeft = RAYGUI_CLITERAL(Rectangle){
+ (float)bounds.x + GuiGetStyle(SCROLLBAR, BORDER_WIDTH),
+ (float)bounds.y + GuiGetStyle(SCROLLBAR, BORDER_WIDTH),
+ (float)spinnerSize, (float)spinnerSize };
+
+ if (isVertical)
+ {
+ arrowDownRight = RAYGUI_CLITERAL(Rectangle){ (float)bounds.x + GuiGetStyle(SCROLLBAR, BORDER_WIDTH), (float)bounds.y + bounds.height - spinnerSize - GuiGetStyle(SCROLLBAR, BORDER_WIDTH), (float)spinnerSize, (float)spinnerSize };
+ scrollbar = RAYGUI_CLITERAL(Rectangle){ bounds.x + GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_PADDING), arrowUpLeft.y + arrowUpLeft.height, bounds.width - 2*(GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_PADDING)), bounds.height - arrowUpLeft.height - arrowDownRight.height - 2*GuiGetStyle(SCROLLBAR, BORDER_WIDTH) };
+
+ // Make sure the slider won't get outside of the scrollbar
+ sliderSize = (sliderSize >= scrollbar.height)? ((int)scrollbar.height - 2) : sliderSize;
+ slider = RAYGUI_CLITERAL(Rectangle){
+ bounds.x + GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_PADDING),
+ scrollbar.y + (int)(((float)(value - minValue)/valueRange)*(scrollbar.height - sliderSize)),
+ bounds.width - 2*(GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_PADDING)),
+ (float)sliderSize };
+ }
+ else // horizontal
+ {
+ arrowDownRight = RAYGUI_CLITERAL(Rectangle){ (float)bounds.x + bounds.width - spinnerSize - GuiGetStyle(SCROLLBAR, BORDER_WIDTH), (float)bounds.y + GuiGetStyle(SCROLLBAR, BORDER_WIDTH), (float)spinnerSize, (float)spinnerSize };
+ scrollbar = RAYGUI_CLITERAL(Rectangle){ arrowUpLeft.x + arrowUpLeft.width, bounds.y + GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_PADDING), bounds.width - arrowUpLeft.width - arrowDownRight.width - 2*GuiGetStyle(SCROLLBAR, BORDER_WIDTH), bounds.height - 2*(GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_PADDING)) };
+
+ // Make sure the slider won't get outside of the scrollbar
+ sliderSize = (sliderSize >= scrollbar.width)? ((int)scrollbar.width - 2) : sliderSize;
+ slider = RAYGUI_CLITERAL(Rectangle){
+ scrollbar.x + (int)(((float)(value - minValue)/valueRange)*(scrollbar.width - sliderSize)),
+ bounds.y + GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_PADDING),
+ (float)sliderSize,
+ bounds.height - 2*(GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_PADDING)) };
+ }
+
+ // Update control
+ //--------------------------------------------------------------------
+ if ((state != STATE_DISABLED) && !guiLocked)
+ {
+ Vector2 mousePoint = GetMousePosition();
+
+ if (guiControlExclusiveMode) // Allows to keep dragging outside of bounds
+ {
+ if (IsMouseButtonDown(MOUSE_LEFT_BUTTON) &&
+ !CheckCollisionPointRec(mousePoint, arrowUpLeft) &&
+ !CheckCollisionPointRec(mousePoint, arrowDownRight))
+ {
+ if (CHECK_BOUNDS_ID(bounds, guiControlExclusiveRec))
+ {
+ state = STATE_PRESSED;
+
+ if (isVertical) value = (int)(((float)(mousePoint.y - scrollbar.y - slider.height/2)*valueRange)/(scrollbar.height - slider.height) + minValue);
+ else value = (int)(((float)(mousePoint.x - scrollbar.x - slider.width/2)*valueRange)/(scrollbar.width - slider.width) + minValue);
+ }
+ }
+ else
+ {
+ guiControlExclusiveMode = false;
+ guiControlExclusiveRec = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 };
+ }
+ }
+ else if (CheckCollisionPointRec(mousePoint, bounds))
+ {
+ state = STATE_FOCUSED;
+
+ // Handle mouse wheel
+ int wheel = (int)GetMouseWheelMove();
+ if (wheel != 0) value += wheel;
+
+ // Handle mouse button down
+ if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
+ {
+ guiControlExclusiveMode = true;
+ guiControlExclusiveRec = bounds; // Store bounds as an identifier when dragging starts
+
+ // Check arrows click
+ if (CheckCollisionPointRec(mousePoint, arrowUpLeft)) value -= valueRange/GuiGetStyle(SCROLLBAR, SCROLL_SPEED);
+ else if (CheckCollisionPointRec(mousePoint, arrowDownRight)) value += valueRange/GuiGetStyle(SCROLLBAR, SCROLL_SPEED);
+ else if (!CheckCollisionPointRec(mousePoint, slider))
+ {
+ // If click on scrollbar position but not on slider, place slider directly on that position
+ if (isVertical) value = (int)(((float)(mousePoint.y - scrollbar.y - slider.height/2)*valueRange)/(scrollbar.height - slider.height) + minValue);
+ else value = (int)(((float)(mousePoint.x - scrollbar.x - slider.width/2)*valueRange)/(scrollbar.width - slider.width) + minValue);
+ }
+
+ state = STATE_PRESSED;
+ }
+
+ // Keyboard control on mouse hover scrollbar
+ /*
+ if (isVertical)
+ {
+ if (IsKeyDown(KEY_DOWN)) value += 5;
+ else if (IsKeyDown(KEY_UP)) value -= 5;
+ }
+ else
+ {
+ if (IsKeyDown(KEY_RIGHT)) value += 5;
+ else if (IsKeyDown(KEY_LEFT)) value -= 5;
+ }
+ */
+ }
+
+ // Normalize value
+ if (value > maxValue) value = maxValue;
+ if (value < minValue) value = minValue;
+ }
+ //--------------------------------------------------------------------
+
+ // Draw control
+ //--------------------------------------------------------------------
+ GuiDrawRectangle(bounds, GuiGetStyle(SCROLLBAR, BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER + state*3)), GetColor(GuiGetStyle(DEFAULT, BORDER_COLOR_DISABLED))); // Draw the background
+
+ GuiDrawRectangle(scrollbar, 0, BLANK, GetColor(GuiGetStyle(BUTTON, BASE_COLOR_NORMAL))); // Draw the scrollbar active area background
+ GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, BORDER + state*3))); // Draw the slider bar
+
+ // Draw arrows (using icon if available)
+ if (GuiGetStyle(SCROLLBAR, ARROWS_VISIBLE))
+ {
+#if defined(RAYGUI_NO_ICONS)
+ GuiDrawText(isVertical? "^" : "<",
+ RAYGUI_CLITERAL(Rectangle){ arrowUpLeft.x, arrowUpLeft.y, isVertical? bounds.width : bounds.height, isVertical? bounds.width : bounds.height },
+ TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3))));
+ GuiDrawText(isVertical? "v" : ">",
+ RAYGUI_CLITERAL(Rectangle){ arrowDownRight.x, arrowDownRight.y, isVertical? bounds.width : bounds.height, isVertical? bounds.width : bounds.height },
+ TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3))));
+#else
+ GuiDrawText(isVertical? "#121#" : "#118#",
+ RAYGUI_CLITERAL(Rectangle){ arrowUpLeft.x, arrowUpLeft.y, isVertical? bounds.width : bounds.height, isVertical? bounds.width : bounds.height },
+ TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(SCROLLBAR, TEXT + state*3))); // ICON_ARROW_UP_FILL / ICON_ARROW_LEFT_FILL
+ GuiDrawText(isVertical? "#120#" : "#119#",
+ RAYGUI_CLITERAL(Rectangle){ arrowDownRight.x, arrowDownRight.y, isVertical? bounds.width : bounds.height, isVertical? bounds.width : bounds.height },
+ TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(SCROLLBAR, TEXT + state*3))); // ICON_ARROW_DOWN_FILL / ICON_ARROW_RIGHT_FILL
+#endif
+ }
+ //--------------------------------------------------------------------
+
+ return value;
+}
+
+// Color fade-in or fade-out, alpha goes from 0.0f to 1.0f
+// WARNING: It multiplies current alpha by alpha scale factor
+static Color GuiFade(Color color, float alpha)
+{
+ if (alpha < 0.0f) alpha = 0.0f;
+ else if (alpha > 1.0f) alpha = 1.0f;
+
+ Color result = { color.r, color.g, color.b, (unsigned char)(color.a*alpha) };
+
+ return result;
+}
+
+#if defined(RAYGUI_STANDALONE)
+// Returns a Color struct from hexadecimal value
+static Color GetColor(int hexValue)
+{
+ Color color;
+
+ color.r = (unsigned char)(hexValue >> 24) & 0xff;
+ color.g = (unsigned char)(hexValue >> 16) & 0xff;
+ color.b = (unsigned char)(hexValue >> 8) & 0xff;
+ color.a = (unsigned char)hexValue & 0xff;
+
+ return color;
+}
+
+// Returns hexadecimal value for a Color
+static int ColorToInt(Color color)
+{
+ return (((int)color.r << 24) | ((int)color.g << 16) | ((int)color.b << 8) | (int)color.a);
+}
+
+// Check if point is inside rectangle
+static bool CheckCollisionPointRec(Vector2 point, Rectangle rec)
+{
+ bool collision = false;
+
+ if ((point.x >= rec.x) && (point.x <= (rec.x + rec.width)) &&
+ (point.y >= rec.y) && (point.y <= (rec.y + rec.height))) collision = true;
+
+ return collision;
+}
+
+// Formatting of text with variables to 'embed'
+static const char *TextFormat(const char *text, ...)
+{
+ #if !defined(RAYGUI_TEXTFORMAT_MAX_SIZE)
+ #define RAYGUI_TEXTFORMAT_MAX_SIZE 256
+ #endif
+
+ static char buffer[RAYGUI_TEXTFORMAT_MAX_SIZE];
+
+ va_list args;
+ va_start(args, text);
+ vsnprintf(buffer, RAYGUI_TEXTFORMAT_MAX_SIZE, text, args);
+ va_end(args);
+
+ return buffer;
+}
+
+// Draw rectangle with vertical gradient fill color
+// NOTE: This function is only used by GuiColorPicker()
+static void DrawRectangleGradientV(int posX, int posY, int width, int height, Color color1, Color color2)
+{
+ Rectangle bounds = { (float)posX, (float)posY, (float)width, (float)height };
+ DrawRectangleGradientEx(bounds, color1, color2, color2, color1);
+}
+
+// Split string into multiple strings
+const char **TextSplit(const char *text, char delimiter, int *count)
+{
+ // NOTE: Current implementation returns a copy of the provided string with '\0' (string end delimiter)
+ // inserted between strings defined by "delimiter" parameter. No memory is dynamically allocated,
+ // all used memory is static... it has some limitations:
+ // 1. Maximum number of possible split strings is set by RAYGUI_TEXTSPLIT_MAX_ITEMS
+ // 2. Maximum size of text to split is RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE
+
+ #if !defined(RAYGUI_TEXTSPLIT_MAX_ITEMS)
+ #define RAYGUI_TEXTSPLIT_MAX_ITEMS 128
+ #endif
+ #if !defined(RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE)
+ #define RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE 1024
+ #endif
+
+ static const char *result[RAYGUI_TEXTSPLIT_MAX_ITEMS] = { NULL };
+ static char buffer[RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE] = { 0 };
+ memset(buffer, 0, RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE);
+
+ result[0] = buffer;
+ int counter = 0;
+
+ if (text != NULL)
+ {
+ counter = 1;
+
+ // Count how many substrings we have on text and point to every one
+ for (int i = 0; i < RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE; i++)
+ {
+ buffer[i] = text[i];
+ if (buffer[i] == '\0') break;
+ else if (buffer[i] == delimiter)
+ {
+ buffer[i] = '\0'; // Set an end of string at this point
+ result[counter] = buffer + i + 1;
+ counter++;
+
+ if (counter == RAYGUI_TEXTSPLIT_MAX_ITEMS) break;
+ }
+ }
+ }
+
+ *count = counter;
+ return result;
+}
+
+// Get integer value from text
+// NOTE: This function replaces atoi() [stdlib.h]
+static int TextToInteger(const char *text)
+{
+ int value = 0;
+ int sign = 1;
+
+ if ((text[0] == '+') || (text[0] == '-'))
+ {
+ if (text[0] == '-') sign = -1;
+ text++;
+ }
+
+ for (int i = 0; ((text[i] >= '0') && (text[i] <= '9')); i++) value = value*10 + (int)(text[i] - '0');
+
+ return value*sign;
+}
+
+// Get float value from text
+// NOTE: This function replaces atof() [stdlib.h]
+// WARNING: Only '.' character is understood as decimal point
+static float TextToFloat(const char *text)
+{
+ float value = 0.0f;
+ float sign = 1.0f;
+
+ if ((text[0] == '+') || (text[0] == '-'))
+ {
+ if (text[0] == '-') sign = -1.0f;
+ text++;
+ }
+
+ int i = 0;
+ for (; ((text[i] >= '0') && (text[i] <= '9')); i++) value = value*10.0f + (float)(text[i] - '0');
+
+ if (text[i++] != '.') value *= sign;
+ else
+ {
+ float divisor = 10.0f;
+ for (; ((text[i] >= '0') && (text[i] <= '9')); i++)
+ {
+ value += ((float)(text[i] - '0'))/divisor;
+ divisor = divisor*10.0f;
+ }
+ }
+
+ return value;
+}
+
+// Encode codepoint into UTF-8 text (char array size returned as parameter)
+static const char *CodepointToUTF8(int codepoint, int *byteSize)
+{
+ static char utf8[6] = { 0 };
+ int size = 0;
+
+ if (codepoint <= 0x7f)
+ {
+ utf8[0] = (char)codepoint;
+ size = 1;
+ }
+ else if (codepoint <= 0x7ff)
+ {
+ utf8[0] = (char)(((codepoint >> 6) & 0x1f) | 0xc0);
+ utf8[1] = (char)((codepoint & 0x3f) | 0x80);
+ size = 2;
+ }
+ else if (codepoint <= 0xffff)
+ {
+ utf8[0] = (char)(((codepoint >> 12) & 0x0f) | 0xe0);
+ utf8[1] = (char)(((codepoint >> 6) & 0x3f) | 0x80);
+ utf8[2] = (char)((codepoint & 0x3f) | 0x80);
+ size = 3;
+ }
+ else if (codepoint <= 0x10ffff)
+ {
+ utf8[0] = (char)(((codepoint >> 18) & 0x07) | 0xf0);
+ utf8[1] = (char)(((codepoint >> 12) & 0x3f) | 0x80);
+ utf8[2] = (char)(((codepoint >> 6) & 0x3f) | 0x80);
+ utf8[3] = (char)((codepoint & 0x3f) | 0x80);
+ size = 4;
+ }
+
+ *byteSize = size;
+
+ return utf8;
+}
+
+// Get next codepoint in a UTF-8 encoded text, scanning until '\0' is found
+// When a invalid UTF-8 byte is encountered we exit as soon as possible and a '?'(0x3f) codepoint is returned
+// Total number of bytes processed are returned as a parameter
+// NOTE: the standard says U+FFFD should be returned in case of errors
+// but that character is not supported by the default font in raylib
+static int GetCodepointNext(const char *text, int *codepointSize)
+{
+ const char *ptr = text;
+ int codepoint = 0x3f; // Codepoint (defaults to '?')
+ *codepointSize = 1;
+
+ // Get current codepoint and bytes processed
+ if (0xf0 == (0xf8 & ptr[0]))
+ {
+ // 4 byte UTF-8 codepoint
+ if (((ptr[1] & 0xC0) ^ 0x80) || ((ptr[2] & 0xC0) ^ 0x80) || ((ptr[3] & 0xC0) ^ 0x80)) { return codepoint; } //10xxxxxx checks
+ codepoint = ((0x07 & ptr[0]) << 18) | ((0x3f & ptr[1]) << 12) | ((0x3f & ptr[2]) << 6) | (0x3f & ptr[3]);
+ *codepointSize = 4;
+ }
+ else if (0xe0 == (0xf0 & ptr[0]))
+ {
+ // 3 byte UTF-8 codepoint
+ if (((ptr[1] & 0xC0) ^ 0x80) || ((ptr[2] & 0xC0) ^ 0x80)) { return codepoint; } //10xxxxxx checks
+ codepoint = ((0x0f & ptr[0]) << 12) | ((0x3f & ptr[1]) << 6) | (0x3f & ptr[2]);
+ *codepointSize = 3;
+ }
+ else if (0xc0 == (0xe0 & ptr[0]))
+ {
+ // 2 byte UTF-8 codepoint
+ if ((ptr[1] & 0xC0) ^ 0x80) { return codepoint; } //10xxxxxx checks
+ codepoint = ((0x1f & ptr[0]) << 6) | (0x3f & ptr[1]);
+ *codepointSize = 2;
+ }
+ else if (0x00 == (0x80 & ptr[0]))
+ {
+ // 1 byte UTF-8 codepoint
+ codepoint = ptr[0];
+ *codepointSize = 1;
+ }
+
+ return codepoint;
+}
+#endif // RAYGUI_STANDALONE
+
+#endif // RAYGUI_IMPLEMENTATION
\ No newline at end of file
diff --git a/raymenu/vendor/github.com/gen2brain/raylib-go/raygui/raylib.h b/raymenu/vendor/github.com/gen2brain/raylib-go/raygui/raylib.h
new file mode 100644
index 0000000..ba80e40
--- /dev/null
+++ b/raymenu/vendor/github.com/gen2brain/raylib-go/raygui/raylib.h
@@ -0,0 +1,1727 @@
+/**********************************************************************************************
+*
+* raylib v5.6-dev - A simple and easy-to-use library to enjoy videogames programming (www.raylib.com)
+*
+* FEATURES:
+* - NO external dependencies, all required libraries included with raylib
+* - Multiplatform: Windows, Linux, FreeBSD, OpenBSD, NetBSD, DragonFly,
+* MacOS, Haiku, Android, Raspberry Pi, DRM native, HTML5
+* - Written in plain C code (C99) in PascalCase/camelCase notation
+* - Hardware accelerated with OpenGL (1.1, 2.1, 3.3, 4.3, ES2, ES3 - choose at compile)
+* - Unique OpenGL abstraction layer (usable as standalone module): [rlgl]
+* - Multiple Fonts formats supported (TTF, OTF, FNT, BDF, Sprite fonts)
+* - Outstanding texture formats support, including compressed formats (DXT, ETC, ASTC)
+* - Full 3d support for 3d Shapes, Models, Billboards, Heightmaps and more!
+* - Flexible Materials system, supporting classic maps and PBR maps
+* - Animated 3D models supported (skeletal bones animation) (IQM, M3D, GLTF)
+* - Shaders support, including Model shaders and Postprocessing shaders
+* - Powerful math module for Vector, Matrix and Quaternion operations: [raymath]
+* - Audio loading and playing with streaming support (WAV, OGG, MP3, FLAC, QOA, XM, MOD)
+* - VR stereo rendering with configurable HMD device parameters
+* - Bindings to multiple programming languages available!
+*
+* NOTES:
+* - One default Font is loaded on InitWindow()->LoadFontDefault() [core, text]
+* - One default Texture2D is loaded on rlglInit(), 1x1 white pixel R8G8B8A8 [rlgl] (OpenGL 3.3 or ES2)
+* - One default Shader is loaded on rlglInit()->rlLoadShaderDefault() [rlgl] (OpenGL 3.3 or ES2)
+* - One default RenderBatch is loaded on rlglInit()->rlLoadRenderBatch() [rlgl] (OpenGL 3.3 or ES2)
+*
+* DEPENDENCIES (included):
+* [rcore][GLFW] rglfw (Camilla Löwy - github.com/glfw/glfw) for window/context management and input
+* [rcore][RGFW] rgfw (ColleagueRiley - github.com/ColleagueRiley/RGFW) for window/context management and input
+* [rlgl] glad/glad_gles2 (David Herberth - github.com/Dav1dde/glad) for OpenGL 3.3 extensions loading
+* [raudio] miniaudio (David Reid - github.com/mackron/miniaudio) for audio device/context management
+*
+* OPTIONAL DEPENDENCIES (included):
+* [rcore] sinfl (Micha Mettke) for DEFLATE decompression algorithm
+* [rcore] sdefl (Micha Mettke) for DEFLATE compression algorithm
+* [rcore] rprand (Ramon Santamaria) for pseudo-random numbers generation
+* [rtextures] qoi (Dominic Szablewski - https://phoboslab.org) for QOI image manage
+* [rtextures] stb_image (Sean Barret) for images loading (BMP, TGA, PNG, JPEG, HDR...)
+* [rtextures] stb_image_write (Sean Barret) for image writing (BMP, TGA, PNG, JPG)
+* [rtextures] stb_image_resize2 (Sean Barret) for image resizing algorithms
+* [rtextures] stb_perlin (Sean Barret) for Perlin Noise image generation
+* [rtext] stb_truetype (Sean Barret) for ttf fonts loading
+* [rtext] stb_rect_pack (Sean Barret) for rectangles packing
+* [rmodels] par_shapes (Philip Rideout) for parametric 3d shapes generation
+* [rmodels] tinyobj_loader_c (Syoyo Fujita) for models loading (OBJ, MTL)
+* [rmodels] cgltf (Johannes Kuhlmann) for models loading (glTF)
+* [rmodels] m3d (bzt) for models loading (M3D, https://bztsrc.gitlab.io/model3d)
+* [rmodels] vox_loader (Johann Nadalutti) for models loading (VOX)
+* [raudio] dr_wav (David Reid) for WAV audio file loading
+* [raudio] dr_flac (David Reid) for FLAC audio file loading
+* [raudio] dr_mp3 (David Reid) for MP3 audio file loading
+* [raudio] stb_vorbis (Sean Barret) for OGG audio loading
+* [raudio] jar_xm (Joshua Reisenauer) for XM audio module loading
+* [raudio] jar_mod (Joshua Reisenauer) for MOD audio module loading
+* [raudio] qoa (Dominic Szablewski - https://phoboslab.org) for QOA audio manage
+*
+*
+* LICENSE: zlib/libpng
+*
+* raylib is 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) 2013-2025 Ramon Santamaria (@raysan5)
+*
+* This software is provided "as-is", without any express or implied warranty. In no event
+* will the authors be held liable for any damages arising from the use of this software.
+*
+* Permission is granted to anyone to use this software for any purpose, including commercial
+* applications, and to alter it and redistribute it freely, subject to the following restrictions:
+*
+* 1. The origin of this software must not be misrepresented; you must not claim that you
+* wrote the original software. If you use this software in a product, an acknowledgment
+* in the product documentation would be appreciated but is not required.
+*
+* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
+* as being the original software.
+*
+* 3. This notice may not be removed or altered from any source distribution.
+*
+**********************************************************************************************/
+
+#ifndef RAYLIB_H
+#define RAYLIB_H
+
+#include // Required for: va_list - Only used by TraceLogCallback
+
+#define RAYLIB_VERSION_MAJOR 5
+#define RAYLIB_VERSION_MINOR 6
+#define RAYLIB_VERSION_PATCH 0
+#define RAYLIB_VERSION "5.6-dev"
+
+// Function specifiers in case library is build/used as a shared library
+// NOTE: Microsoft specifiers to tell compiler that symbols are imported/exported from a .dll
+// NOTE: visibility("default") attribute makes symbols "visible" when compiled with -fvisibility=hidden
+#if defined(_WIN32)
+ #if defined(__TINYC__)
+ #define __declspec(x) __attribute__((x))
+ #endif
+ #if defined(BUILD_LIBTYPE_SHARED)
+ #define RLAPI __declspec(dllexport) // Building the library as a Win32 shared library (.dll)
+ #elif defined(USE_LIBTYPE_SHARED)
+ #define RLAPI __declspec(dllimport) // Using the library as a Win32 shared library (.dll)
+ #endif
+#else
+ #if defined(BUILD_LIBTYPE_SHARED)
+ #define RLAPI __attribute__((visibility("default"))) // Building as a Unix shared library (.so/.dylib)
+ #endif
+#endif
+
+#ifndef RLAPI
+ #define RLAPI // Functions defined as 'extern' by default (implicit specifiers)
+#endif
+
+//----------------------------------------------------------------------------------
+// Defines and Macros
+//----------------------------------------------------------------------------------
+#ifndef PI
+ #define PI 3.14159265358979323846f
+#endif
+#ifndef DEG2RAD
+ #define DEG2RAD (PI/180.0f)
+#endif
+#ifndef RAD2DEG
+ #define RAD2DEG (180.0f/PI)
+#endif
+
+// Allow custom memory allocators
+// NOTE: Require recompiling raylib sources
+#ifndef RL_MALLOC
+ #define RL_MALLOC(sz) malloc(sz)
+#endif
+#ifndef RL_CALLOC
+ #define RL_CALLOC(n,sz) calloc(n,sz)
+#endif
+#ifndef RL_REALLOC
+ #define RL_REALLOC(ptr,sz) realloc(ptr,sz)
+#endif
+#ifndef RL_FREE
+ #define RL_FREE(ptr) free(ptr)
+#endif
+
+// NOTE: MSVC C++ compiler does not support compound literals (C99 feature)
+// Plain structures in C++ (without constructors) can be initialized with { }
+// This is called aggregate initialization (C++11 feature)
+#if defined(__cplusplus)
+ #define CLITERAL(type) type
+#else
+ #define CLITERAL(type) (type)
+#endif
+
+// Some compilers (mostly macos clang) default to C++98,
+// where aggregate initialization can't be used
+// So, give a more clear error stating how to fix this
+#if !defined(_MSC_VER) && (defined(__cplusplus) && __cplusplus < 201103L)
+ #error "C++11 or later is required. Add -std=c++11"
+#endif
+
+// NOTE: Set some defines with some data types declared by raylib
+// Other modules (raymath, rlgl) also require some of those types, so,
+// to be able to use those other modules as standalone (not depending on raylib)
+// this defines are very useful for internal check and avoid type (re)definitions
+#define RL_COLOR_TYPE
+#define RL_RECTANGLE_TYPE
+#define RL_VECTOR2_TYPE
+#define RL_VECTOR3_TYPE
+#define RL_VECTOR4_TYPE
+#define RL_QUATERNION_TYPE
+#define RL_MATRIX_TYPE
+
+// Some Basic Colors
+// NOTE: Custom raylib color palette for amazing visuals on WHITE background
+#define LIGHTGRAY CLITERAL(Color){ 200, 200, 200, 255 } // Light Gray
+#define GRAY CLITERAL(Color){ 130, 130, 130, 255 } // Gray
+#define DARKGRAY CLITERAL(Color){ 80, 80, 80, 255 } // Dark Gray
+#define YELLOW CLITERAL(Color){ 253, 249, 0, 255 } // Yellow
+#define GOLD CLITERAL(Color){ 255, 203, 0, 255 } // Gold
+#define ORANGE CLITERAL(Color){ 255, 161, 0, 255 } // Orange
+#define PINK CLITERAL(Color){ 255, 109, 194, 255 } // Pink
+#define RED CLITERAL(Color){ 230, 41, 55, 255 } // Red
+#define MAROON CLITERAL(Color){ 190, 33, 55, 255 } // Maroon
+#define GREEN CLITERAL(Color){ 0, 228, 48, 255 } // Green
+#define LIME CLITERAL(Color){ 0, 158, 47, 255 } // Lime
+#define DARKGREEN CLITERAL(Color){ 0, 117, 44, 255 } // Dark Green
+#define SKYBLUE CLITERAL(Color){ 102, 191, 255, 255 } // Sky Blue
+#define BLUE CLITERAL(Color){ 0, 121, 241, 255 } // Blue
+#define DARKBLUE CLITERAL(Color){ 0, 82, 172, 255 } // Dark Blue
+#define PURPLE CLITERAL(Color){ 200, 122, 255, 255 } // Purple
+#define VIOLET CLITERAL(Color){ 135, 60, 190, 255 } // Violet
+#define DARKPURPLE CLITERAL(Color){ 112, 31, 126, 255 } // Dark Purple
+#define BEIGE CLITERAL(Color){ 211, 176, 131, 255 } // Beige
+#define BROWN CLITERAL(Color){ 127, 106, 79, 255 } // Brown
+#define DARKBROWN CLITERAL(Color){ 76, 63, 47, 255 } // Dark Brown
+
+#define WHITE CLITERAL(Color){ 255, 255, 255, 255 } // White
+#define BLACK CLITERAL(Color){ 0, 0, 0, 255 } // Black
+#define BLANK CLITERAL(Color){ 0, 0, 0, 0 } // Blank (Transparent)
+#define MAGENTA CLITERAL(Color){ 255, 0, 255, 255 } // Magenta
+#define RAYWHITE CLITERAL(Color){ 245, 245, 245, 255 } // My own White (raylib logo)
+
+//----------------------------------------------------------------------------------
+// Types and Structures Definition
+//----------------------------------------------------------------------------------
+// Boolean type
+#if (defined(__STDC__) && __STDC_VERSION__ >= 199901L) || (defined(_MSC_VER) && _MSC_VER >= 1800)
+ #include
+#elif !defined(__cplusplus) && !defined(bool)
+ typedef enum bool { false = 0, true = !false } bool;
+ #define RL_BOOL_TYPE
+#endif
+
+// Vector2, 2 components
+typedef struct Vector2 {
+ float x; // Vector x component
+ float y; // Vector y component
+} Vector2;
+
+// Vector3, 3 components
+typedef struct Vector3 {
+ float x; // Vector x component
+ float y; // Vector y component
+ float z; // Vector z component
+} Vector3;
+
+// Vector4, 4 components
+typedef struct Vector4 {
+ float x; // Vector x component
+ float y; // Vector y component
+ float z; // Vector z component
+ float w; // Vector w component
+} Vector4;
+
+// Quaternion, 4 components (Vector4 alias)
+typedef Vector4 Quaternion;
+
+// Matrix, 4x4 components, column major, OpenGL style, right-handed
+typedef struct Matrix {
+ float m0, m4, m8, m12; // Matrix first row (4 components)
+ float m1, m5, m9, m13; // Matrix second row (4 components)
+ float m2, m6, m10, m14; // Matrix third row (4 components)
+ float m3, m7, m11, m15; // Matrix fourth row (4 components)
+} Matrix;
+
+// Color, 4 components, R8G8B8A8 (32bit)
+typedef struct Color {
+ unsigned char r; // Color red value
+ unsigned char g; // Color green value
+ unsigned char b; // Color blue value
+ unsigned char a; // Color alpha value
+} Color;
+
+// Rectangle, 4 components
+typedef struct Rectangle {
+ float x; // Rectangle top-left corner position x
+ float y; // Rectangle top-left corner position y
+ float width; // Rectangle width
+ float height; // Rectangle height
+} Rectangle;
+
+// Image, pixel data stored in CPU memory (RAM)
+typedef struct Image {
+ void *data; // Image raw data
+ int width; // Image base width
+ int height; // Image base height
+ int mipmaps; // Mipmap levels, 1 by default
+ int format; // Data format (PixelFormat type)
+} Image;
+
+// Texture, tex data stored in GPU memory (VRAM)
+typedef struct Texture {
+ unsigned int id; // OpenGL texture id
+ int width; // Texture base width
+ int height; // Texture base height
+ int mipmaps; // Mipmap levels, 1 by default
+ int format; // Data format (PixelFormat type)
+} Texture;
+
+// Texture2D, same as Texture
+typedef Texture Texture2D;
+
+// TextureCubemap, same as Texture
+typedef Texture TextureCubemap;
+
+// RenderTexture, fbo for texture rendering
+typedef struct RenderTexture {
+ unsigned int id; // OpenGL framebuffer object id
+ Texture texture; // Color buffer attachment texture
+ Texture depth; // Depth buffer attachment texture
+} RenderTexture;
+
+// RenderTexture2D, same as RenderTexture
+typedef RenderTexture RenderTexture2D;
+
+// NPatchInfo, n-patch layout info
+typedef struct NPatchInfo {
+ Rectangle source; // Texture source rectangle
+ int left; // Left border offset
+ int top; // Top border offset
+ int right; // Right border offset
+ int bottom; // Bottom border offset
+ int layout; // Layout of the n-patch: 3x3, 1x3 or 3x1
+} NPatchInfo;
+
+// GlyphInfo, font characters glyphs info
+typedef struct GlyphInfo {
+ int value; // Character value (Unicode)
+ int offsetX; // Character offset X when drawing
+ int offsetY; // Character offset Y when drawing
+ int advanceX; // Character advance position X
+ Image image; // Character image data
+} GlyphInfo;
+
+// Font, font texture and GlyphInfo array data
+typedef struct Font {
+ int baseSize; // Base size (default chars height)
+ int glyphCount; // Number of glyph characters
+ int glyphPadding; // Padding around the glyph characters
+ Texture2D texture; // Texture atlas containing the glyphs
+ Rectangle *recs; // Rectangles in texture for the glyphs
+ GlyphInfo *glyphs; // Glyphs info data
+} Font;
+
+// Camera, defines position/orientation in 3d space
+typedef struct Camera3D {
+ Vector3 position; // Camera position
+ Vector3 target; // Camera target it looks-at
+ Vector3 up; // Camera up vector (rotation over its axis)
+ float fovy; // Camera field-of-view aperture in Y (degrees) in perspective, used as near plane height in world units in orthographic
+ int projection; // Camera projection: CAMERA_PERSPECTIVE or CAMERA_ORTHOGRAPHIC
+} Camera3D;
+
+typedef Camera3D Camera; // Camera type fallback, defaults to Camera3D
+
+// Camera2D, defines position/orientation in 2d space
+typedef struct Camera2D {
+ Vector2 offset; // Camera offset (screen space offset from window origin)
+ Vector2 target; // Camera target (world space target point that is mapped to screen space offset)
+ float rotation; // Camera rotation in degrees (pivots around target)
+ float zoom; // Camera zoom (scaling around target), must not be set to 0, set to 1.0f for no scale
+} Camera2D;
+
+// Mesh, vertex data and vao/vbo
+typedef struct Mesh {
+ int vertexCount; // Number of vertices stored in arrays
+ int triangleCount; // Number of triangles stored (indexed or not)
+
+ // Vertex attributes data
+ float *vertices; // Vertex position (XYZ - 3 components per vertex) (shader-location = 0)
+ float *texcoords; // Vertex texture coordinates (UV - 2 components per vertex) (shader-location = 1)
+ float *texcoords2; // Vertex texture second coordinates (UV - 2 components per vertex) (shader-location = 5)
+ float *normals; // Vertex normals (XYZ - 3 components per vertex) (shader-location = 2)
+ float *tangents; // Vertex tangents (XYZW - 4 components per vertex) (shader-location = 4)
+ unsigned char *colors; // Vertex colors (RGBA - 4 components per vertex) (shader-location = 3)
+ unsigned short *indices; // Vertex indices (in case vertex data comes indexed)
+
+ // Animation vertex data
+ float *animVertices; // Animated vertex positions (after bones transformations)
+ float *animNormals; // Animated normals (after bones transformations)
+ unsigned char *boneIds; // Vertex bone ids, max 255 bone ids, up to 4 bones influence by vertex (skinning) (shader-location = 6)
+ float *boneWeights; // Vertex bone weight, up to 4 bones influence by vertex (skinning) (shader-location = 7)
+ Matrix *boneMatrices; // Bones animated transformation matrices
+ int boneCount; // Number of bones
+
+ // OpenGL identifiers
+ unsigned int vaoId; // OpenGL Vertex Array Object id
+ unsigned int *vboId; // OpenGL Vertex Buffer Objects id (default vertex data)
+} Mesh;
+
+// Shader
+typedef struct Shader {
+ unsigned int id; // Shader program id
+ int *locs; // Shader locations array (RL_MAX_SHADER_LOCATIONS)
+} Shader;
+
+// MaterialMap
+typedef struct MaterialMap {
+ Texture2D texture; // Material map texture
+ Color color; // Material map color
+ float value; // Material map value
+} MaterialMap;
+
+// Material, includes shader and maps
+typedef struct Material {
+ Shader shader; // Material shader
+ MaterialMap *maps; // Material maps array (MAX_MATERIAL_MAPS)
+ float params[4]; // Material generic parameters (if required)
+} Material;
+
+// Transform, vertex transformation data
+typedef struct Transform {
+ Vector3 translation; // Translation
+ Quaternion rotation; // Rotation
+ Vector3 scale; // Scale
+} Transform;
+
+// Bone, skeletal animation bone
+typedef struct BoneInfo {
+ char name[32]; // Bone name
+ int parent; // Bone parent
+} BoneInfo;
+
+// Model, meshes, materials and animation data
+typedef struct Model {
+ Matrix transform; // Local transform matrix
+
+ int meshCount; // Number of meshes
+ int materialCount; // Number of materials
+ Mesh *meshes; // Meshes array
+ Material *materials; // Materials array
+ int *meshMaterial; // Mesh material number
+
+ // Animation data
+ int boneCount; // Number of bones
+ BoneInfo *bones; // Bones information (skeleton)
+ Transform *bindPose; // Bones base transformation (pose)
+} Model;
+
+// ModelAnimation
+typedef struct ModelAnimation {
+ int boneCount; // Number of bones
+ int frameCount; // Number of animation frames
+ BoneInfo *bones; // Bones information (skeleton)
+ Transform **framePoses; // Poses array by frame
+ char name[32]; // Animation name
+} ModelAnimation;
+
+// Ray, ray for raycasting
+typedef struct Ray {
+ Vector3 position; // Ray position (origin)
+ Vector3 direction; // Ray direction (normalized)
+} Ray;
+
+// RayCollision, ray hit information
+typedef struct RayCollision {
+ bool hit; // Did the ray hit something?
+ float distance; // Distance to the nearest hit
+ Vector3 point; // Point of the nearest hit
+ Vector3 normal; // Surface normal of hit
+} RayCollision;
+
+// BoundingBox
+typedef struct BoundingBox {
+ Vector3 min; // Minimum vertex box-corner
+ Vector3 max; // Maximum vertex box-corner
+} BoundingBox;
+
+// Wave, audio wave data
+typedef struct Wave {
+ unsigned int frameCount; // Total number of frames (considering channels)
+ unsigned int sampleRate; // Frequency (samples per second)
+ unsigned int sampleSize; // Bit depth (bits per sample): 8, 16, 32 (24 not supported)
+ unsigned int channels; // Number of channels (1-mono, 2-stereo, ...)
+ void *data; // Buffer data pointer
+} Wave;
+
+// Opaque structs declaration
+// NOTE: Actual structs are defined internally in raudio module
+typedef struct rAudioBuffer rAudioBuffer;
+typedef struct rAudioProcessor rAudioProcessor;
+
+// AudioStream, custom audio stream
+typedef struct AudioStream {
+ rAudioBuffer *buffer; // Pointer to internal data used by the audio system
+ rAudioProcessor *processor; // Pointer to internal data processor, useful for audio effects
+
+ unsigned int sampleRate; // Frequency (samples per second)
+ unsigned int sampleSize; // Bit depth (bits per sample): 8, 16, 32 (24 not supported)
+ unsigned int channels; // Number of channels (1-mono, 2-stereo, ...)
+} AudioStream;
+
+// Sound
+typedef struct Sound {
+ AudioStream stream; // Audio stream
+ unsigned int frameCount; // Total number of frames (considering channels)
+} Sound;
+
+// Music, audio stream, anything longer than ~10 seconds should be streamed
+typedef struct Music {
+ AudioStream stream; // Audio stream
+ unsigned int frameCount; // Total number of frames (considering channels)
+ bool looping; // Music looping enable
+
+ int ctxType; // Type of music context (audio filetype)
+ void *ctxData; // Audio context data, depends on type
+} Music;
+
+// VrDeviceInfo, Head-Mounted-Display device parameters
+typedef struct VrDeviceInfo {
+ int hResolution; // Horizontal resolution in pixels
+ int vResolution; // Vertical resolution in pixels
+ float hScreenSize; // Horizontal size in meters
+ float vScreenSize; // Vertical size in meters
+ float eyeToScreenDistance; // Distance between eye and display in meters
+ float lensSeparationDistance; // Lens separation distance in meters
+ float interpupillaryDistance; // IPD (distance between pupils) in meters
+ float lensDistortionValues[4]; // Lens distortion constant parameters
+ float chromaAbCorrection[4]; // Chromatic aberration correction parameters
+} VrDeviceInfo;
+
+// VrStereoConfig, VR stereo rendering configuration for simulator
+typedef struct VrStereoConfig {
+ Matrix projection[2]; // VR projection matrices (per eye)
+ Matrix viewOffset[2]; // VR view offset matrices (per eye)
+ float leftLensCenter[2]; // VR left lens center
+ float rightLensCenter[2]; // VR right lens center
+ float leftScreenCenter[2]; // VR left screen center
+ float rightScreenCenter[2]; // VR right screen center
+ float scale[2]; // VR distortion scale
+ float scaleIn[2]; // VR distortion scale in
+} VrStereoConfig;
+
+// File path list
+typedef struct FilePathList {
+ unsigned int capacity; // Filepaths max entries
+ unsigned int count; // Filepaths entries count
+ char **paths; // Filepaths entries
+} FilePathList;
+
+// Automation event
+typedef struct AutomationEvent {
+ unsigned int frame; // Event frame
+ unsigned int type; // Event type (AutomationEventType)
+ int params[4]; // Event parameters (if required)
+} AutomationEvent;
+
+// Automation event list
+typedef struct AutomationEventList {
+ unsigned int capacity; // Events max entries (MAX_AUTOMATION_EVENTS)
+ unsigned int count; // Events entries count
+ AutomationEvent *events; // Events entries
+} AutomationEventList;
+
+//----------------------------------------------------------------------------------
+// Enumerators Definition
+//----------------------------------------------------------------------------------
+// System/Window config flags
+// NOTE: Every bit registers one state (use it with bit masks)
+// By default all flags are set to 0
+typedef enum {
+ FLAG_VSYNC_HINT = 0x00000040, // Set to try enabling V-Sync on GPU
+ FLAG_FULLSCREEN_MODE = 0x00000002, // Set to run program in fullscreen
+ FLAG_WINDOW_RESIZABLE = 0x00000004, // Set to allow resizable window
+ FLAG_WINDOW_UNDECORATED = 0x00000008, // Set to disable window decoration (frame and buttons)
+ FLAG_WINDOW_HIDDEN = 0x00000080, // Set to hide window
+ FLAG_WINDOW_MINIMIZED = 0x00000200, // Set to minimize window (iconify)
+ FLAG_WINDOW_MAXIMIZED = 0x00000400, // Set to maximize window (expanded to monitor)
+ FLAG_WINDOW_UNFOCUSED = 0x00000800, // Set to window non focused
+ FLAG_WINDOW_TOPMOST = 0x00001000, // Set to window always on top
+ FLAG_WINDOW_ALWAYS_RUN = 0x00000100, // Set to allow windows running while minimized
+ FLAG_WINDOW_TRANSPARENT = 0x00000010, // Set to allow transparent framebuffer
+ FLAG_WINDOW_HIGHDPI = 0x00002000, // Set to support HighDPI
+ FLAG_WINDOW_MOUSE_PASSTHROUGH = 0x00004000, // Set to support mouse passthrough, only supported when FLAG_WINDOW_UNDECORATED
+ FLAG_BORDERLESS_WINDOWED_MODE = 0x00008000, // Set to run program in borderless windowed mode
+ FLAG_MSAA_4X_HINT = 0x00000020, // Set to try enabling MSAA 4X
+ FLAG_INTERLACED_HINT = 0x00010000 // Set to try enabling interlaced video format (for V3D)
+} ConfigFlags;
+
+// Trace log level
+// NOTE: Organized by priority level
+typedef enum {
+ LOG_ALL = 0, // Display all logs
+ LOG_TRACE, // Trace logging, intended for internal use only
+ LOG_DEBUG, // Debug logging, used for internal debugging, it should be disabled on release builds
+ LOG_INFO, // Info logging, used for program execution info
+ LOG_WARNING, // Warning logging, used on recoverable failures
+ LOG_ERROR, // Error logging, used on unrecoverable failures
+ LOG_FATAL, // Fatal logging, used to abort program: exit(EXIT_FAILURE)
+ LOG_NONE // Disable logging
+} TraceLogLevel;
+
+// Keyboard keys (US keyboard layout)
+// NOTE: Use GetKeyPressed() to allow redefining
+// required keys for alternative layouts
+typedef enum {
+ KEY_NULL = 0, // Key: NULL, used for no key pressed
+ // Alphanumeric keys
+ KEY_APOSTROPHE = 39, // Key: '
+ KEY_COMMA = 44, // Key: ,
+ KEY_MINUS = 45, // Key: -
+ KEY_PERIOD = 46, // Key: .
+ KEY_SLASH = 47, // Key: /
+ KEY_ZERO = 48, // Key: 0
+ KEY_ONE = 49, // Key: 1
+ KEY_TWO = 50, // Key: 2
+ KEY_THREE = 51, // Key: 3
+ KEY_FOUR = 52, // Key: 4
+ KEY_FIVE = 53, // Key: 5
+ KEY_SIX = 54, // Key: 6
+ KEY_SEVEN = 55, // Key: 7
+ KEY_EIGHT = 56, // Key: 8
+ KEY_NINE = 57, // Key: 9
+ KEY_SEMICOLON = 59, // Key: ;
+ KEY_EQUAL = 61, // Key: =
+ KEY_A = 65, // Key: A | a
+ KEY_B = 66, // Key: B | b
+ KEY_C = 67, // Key: C | c
+ KEY_D = 68, // Key: D | d
+ KEY_E = 69, // Key: E | e
+ KEY_F = 70, // Key: F | f
+ KEY_G = 71, // Key: G | g
+ KEY_H = 72, // Key: H | h
+ KEY_I = 73, // Key: I | i
+ KEY_J = 74, // Key: J | j
+ KEY_K = 75, // Key: K | k
+ KEY_L = 76, // Key: L | l
+ KEY_M = 77, // Key: M | m
+ KEY_N = 78, // Key: N | n
+ KEY_O = 79, // Key: O | o
+ KEY_P = 80, // Key: P | p
+ KEY_Q = 81, // Key: Q | q
+ KEY_R = 82, // Key: R | r
+ KEY_S = 83, // Key: S | s
+ KEY_T = 84, // Key: T | t
+ KEY_U = 85, // Key: U | u
+ KEY_V = 86, // Key: V | v
+ KEY_W = 87, // Key: W | w
+ KEY_X = 88, // Key: X | x
+ KEY_Y = 89, // Key: Y | y
+ KEY_Z = 90, // Key: Z | z
+ KEY_LEFT_BRACKET = 91, // Key: [
+ KEY_BACKSLASH = 92, // Key: '\'
+ KEY_RIGHT_BRACKET = 93, // Key: ]
+ KEY_GRAVE = 96, // Key: `
+ // Function keys
+ KEY_SPACE = 32, // Key: Space
+ KEY_ESCAPE = 256, // Key: Esc
+ KEY_ENTER = 257, // Key: Enter
+ KEY_TAB = 258, // Key: Tab
+ KEY_BACKSPACE = 259, // Key: Backspace
+ KEY_INSERT = 260, // Key: Ins
+ KEY_DELETE = 261, // Key: Del
+ KEY_RIGHT = 262, // Key: Cursor right
+ KEY_LEFT = 263, // Key: Cursor left
+ KEY_DOWN = 264, // Key: Cursor down
+ KEY_UP = 265, // Key: Cursor up
+ KEY_PAGE_UP = 266, // Key: Page up
+ KEY_PAGE_DOWN = 267, // Key: Page down
+ KEY_HOME = 268, // Key: Home
+ KEY_END = 269, // Key: End
+ KEY_CAPS_LOCK = 280, // Key: Caps lock
+ KEY_SCROLL_LOCK = 281, // Key: Scroll down
+ KEY_NUM_LOCK = 282, // Key: Num lock
+ KEY_PRINT_SCREEN = 283, // Key: Print screen
+ KEY_PAUSE = 284, // Key: Pause
+ KEY_F1 = 290, // Key: F1
+ KEY_F2 = 291, // Key: F2
+ KEY_F3 = 292, // Key: F3
+ KEY_F4 = 293, // Key: F4
+ KEY_F5 = 294, // Key: F5
+ KEY_F6 = 295, // Key: F6
+ KEY_F7 = 296, // Key: F7
+ KEY_F8 = 297, // Key: F8
+ KEY_F9 = 298, // Key: F9
+ KEY_F10 = 299, // Key: F10
+ KEY_F11 = 300, // Key: F11
+ KEY_F12 = 301, // Key: F12
+ KEY_LEFT_SHIFT = 340, // Key: Shift left
+ KEY_LEFT_CONTROL = 341, // Key: Control left
+ KEY_LEFT_ALT = 342, // Key: Alt left
+ KEY_LEFT_SUPER = 343, // Key: Super left
+ KEY_RIGHT_SHIFT = 344, // Key: Shift right
+ KEY_RIGHT_CONTROL = 345, // Key: Control right
+ KEY_RIGHT_ALT = 346, // Key: Alt right
+ KEY_RIGHT_SUPER = 347, // Key: Super right
+ KEY_KB_MENU = 348, // Key: KB menu
+ // Keypad keys
+ KEY_KP_0 = 320, // Key: Keypad 0
+ KEY_KP_1 = 321, // Key: Keypad 1
+ KEY_KP_2 = 322, // Key: Keypad 2
+ KEY_KP_3 = 323, // Key: Keypad 3
+ KEY_KP_4 = 324, // Key: Keypad 4
+ KEY_KP_5 = 325, // Key: Keypad 5
+ KEY_KP_6 = 326, // Key: Keypad 6
+ KEY_KP_7 = 327, // Key: Keypad 7
+ KEY_KP_8 = 328, // Key: Keypad 8
+ KEY_KP_9 = 329, // Key: Keypad 9
+ KEY_KP_DECIMAL = 330, // Key: Keypad .
+ KEY_KP_DIVIDE = 331, // Key: Keypad /
+ KEY_KP_MULTIPLY = 332, // Key: Keypad *
+ KEY_KP_SUBTRACT = 333, // Key: Keypad -
+ KEY_KP_ADD = 334, // Key: Keypad +
+ KEY_KP_ENTER = 335, // Key: Keypad Enter
+ KEY_KP_EQUAL = 336, // Key: Keypad =
+ // Android key buttons
+ KEY_BACK = 4, // Key: Android back button
+ KEY_MENU = 5, // Key: Android menu button
+ KEY_VOLUME_UP = 24, // Key: Android volume up button
+ KEY_VOLUME_DOWN = 25 // Key: Android volume down button
+} KeyboardKey;
+
+// Add backwards compatibility support for deprecated names
+#define MOUSE_LEFT_BUTTON MOUSE_BUTTON_LEFT
+#define MOUSE_RIGHT_BUTTON MOUSE_BUTTON_RIGHT
+#define MOUSE_MIDDLE_BUTTON MOUSE_BUTTON_MIDDLE
+
+// Mouse buttons
+typedef enum {
+ MOUSE_BUTTON_LEFT = 0, // Mouse button left
+ MOUSE_BUTTON_RIGHT = 1, // Mouse button right
+ MOUSE_BUTTON_MIDDLE = 2, // Mouse button middle (pressed wheel)
+ MOUSE_BUTTON_SIDE = 3, // Mouse button side (advanced mouse device)
+ MOUSE_BUTTON_EXTRA = 4, // Mouse button extra (advanced mouse device)
+ MOUSE_BUTTON_FORWARD = 5, // Mouse button forward (advanced mouse device)
+ MOUSE_BUTTON_BACK = 6, // Mouse button back (advanced mouse device)
+} MouseButton;
+
+// Mouse cursor
+typedef enum {
+ MOUSE_CURSOR_DEFAULT = 0, // Default pointer shape
+ MOUSE_CURSOR_ARROW = 1, // Arrow shape
+ MOUSE_CURSOR_IBEAM = 2, // Text writing cursor shape
+ MOUSE_CURSOR_CROSSHAIR = 3, // Cross shape
+ MOUSE_CURSOR_POINTING_HAND = 4, // Pointing hand cursor
+ MOUSE_CURSOR_RESIZE_EW = 5, // Horizontal resize/move arrow shape
+ MOUSE_CURSOR_RESIZE_NS = 6, // Vertical resize/move arrow shape
+ MOUSE_CURSOR_RESIZE_NWSE = 7, // Top-left to bottom-right diagonal resize/move arrow shape
+ MOUSE_CURSOR_RESIZE_NESW = 8, // The top-right to bottom-left diagonal resize/move arrow shape
+ MOUSE_CURSOR_RESIZE_ALL = 9, // The omnidirectional resize/move cursor shape
+ MOUSE_CURSOR_NOT_ALLOWED = 10 // The operation-not-allowed shape
+} MouseCursor;
+
+// Gamepad buttons
+typedef enum {
+ GAMEPAD_BUTTON_UNKNOWN = 0, // Unknown button, just for error checking
+ GAMEPAD_BUTTON_LEFT_FACE_UP, // Gamepad left DPAD up button
+ GAMEPAD_BUTTON_LEFT_FACE_RIGHT, // Gamepad left DPAD right button
+ GAMEPAD_BUTTON_LEFT_FACE_DOWN, // Gamepad left DPAD down button
+ GAMEPAD_BUTTON_LEFT_FACE_LEFT, // Gamepad left DPAD left button
+ GAMEPAD_BUTTON_RIGHT_FACE_UP, // Gamepad right button up (i.e. PS3: Triangle, Xbox: Y)
+ GAMEPAD_BUTTON_RIGHT_FACE_RIGHT, // Gamepad right button right (i.e. PS3: Circle, Xbox: B)
+ GAMEPAD_BUTTON_RIGHT_FACE_DOWN, // Gamepad right button down (i.e. PS3: Cross, Xbox: A)
+ GAMEPAD_BUTTON_RIGHT_FACE_LEFT, // Gamepad right button left (i.e. PS3: Square, Xbox: X)
+ GAMEPAD_BUTTON_LEFT_TRIGGER_1, // Gamepad top/back trigger left (first), it could be a trailing button
+ GAMEPAD_BUTTON_LEFT_TRIGGER_2, // Gamepad top/back trigger left (second), it could be a trailing button
+ GAMEPAD_BUTTON_RIGHT_TRIGGER_1, // Gamepad top/back trigger right (first), it could be a trailing button
+ GAMEPAD_BUTTON_RIGHT_TRIGGER_2, // Gamepad top/back trigger right (second), it could be a trailing button
+ GAMEPAD_BUTTON_MIDDLE_LEFT, // Gamepad center buttons, left one (i.e. PS3: Select)
+ GAMEPAD_BUTTON_MIDDLE, // Gamepad center buttons, middle one (i.e. PS3: PS, Xbox: XBOX)
+ GAMEPAD_BUTTON_MIDDLE_RIGHT, // Gamepad center buttons, right one (i.e. PS3: Start)
+ GAMEPAD_BUTTON_LEFT_THUMB, // Gamepad joystick pressed button left
+ GAMEPAD_BUTTON_RIGHT_THUMB // Gamepad joystick pressed button right
+} GamepadButton;
+
+// Gamepad axes
+typedef enum {
+ GAMEPAD_AXIS_LEFT_X = 0, // Gamepad left stick X axis
+ GAMEPAD_AXIS_LEFT_Y = 1, // Gamepad left stick Y axis
+ GAMEPAD_AXIS_RIGHT_X = 2, // Gamepad right stick X axis
+ GAMEPAD_AXIS_RIGHT_Y = 3, // Gamepad right stick Y axis
+ GAMEPAD_AXIS_LEFT_TRIGGER = 4, // Gamepad back trigger left, pressure level: [1..-1]
+ GAMEPAD_AXIS_RIGHT_TRIGGER = 5 // Gamepad back trigger right, pressure level: [1..-1]
+} GamepadAxis;
+
+// Material map index
+typedef enum {
+ MATERIAL_MAP_ALBEDO = 0, // Albedo material (same as: MATERIAL_MAP_DIFFUSE)
+ MATERIAL_MAP_METALNESS, // Metalness material (same as: MATERIAL_MAP_SPECULAR)
+ MATERIAL_MAP_NORMAL, // Normal material
+ MATERIAL_MAP_ROUGHNESS, // Roughness material
+ MATERIAL_MAP_OCCLUSION, // Ambient occlusion material
+ MATERIAL_MAP_EMISSION, // Emission material
+ MATERIAL_MAP_HEIGHT, // Heightmap material
+ MATERIAL_MAP_CUBEMAP, // Cubemap material (NOTE: Uses GL_TEXTURE_CUBE_MAP)
+ MATERIAL_MAP_IRRADIANCE, // Irradiance material (NOTE: Uses GL_TEXTURE_CUBE_MAP)
+ MATERIAL_MAP_PREFILTER, // Prefilter material (NOTE: Uses GL_TEXTURE_CUBE_MAP)
+ MATERIAL_MAP_BRDF // Brdf material
+} MaterialMapIndex;
+
+#define MATERIAL_MAP_DIFFUSE MATERIAL_MAP_ALBEDO
+#define MATERIAL_MAP_SPECULAR MATERIAL_MAP_METALNESS
+
+// Shader location index
+typedef enum {
+ SHADER_LOC_VERTEX_POSITION = 0, // Shader location: vertex attribute: position
+ SHADER_LOC_VERTEX_TEXCOORD01, // Shader location: vertex attribute: texcoord01
+ SHADER_LOC_VERTEX_TEXCOORD02, // Shader location: vertex attribute: texcoord02
+ SHADER_LOC_VERTEX_NORMAL, // Shader location: vertex attribute: normal
+ SHADER_LOC_VERTEX_TANGENT, // Shader location: vertex attribute: tangent
+ SHADER_LOC_VERTEX_COLOR, // Shader location: vertex attribute: color
+ SHADER_LOC_MATRIX_MVP, // Shader location: matrix uniform: model-view-projection
+ SHADER_LOC_MATRIX_VIEW, // Shader location: matrix uniform: view (camera transform)
+ SHADER_LOC_MATRIX_PROJECTION, // Shader location: matrix uniform: projection
+ SHADER_LOC_MATRIX_MODEL, // Shader location: matrix uniform: model (transform)
+ SHADER_LOC_MATRIX_NORMAL, // Shader location: matrix uniform: normal
+ SHADER_LOC_VECTOR_VIEW, // Shader location: vector uniform: view
+ SHADER_LOC_COLOR_DIFFUSE, // Shader location: vector uniform: diffuse color
+ SHADER_LOC_COLOR_SPECULAR, // Shader location: vector uniform: specular color
+ SHADER_LOC_COLOR_AMBIENT, // Shader location: vector uniform: ambient color
+ SHADER_LOC_MAP_ALBEDO, // Shader location: sampler2d texture: albedo (same as: SHADER_LOC_MAP_DIFFUSE)
+ SHADER_LOC_MAP_METALNESS, // Shader location: sampler2d texture: metalness (same as: SHADER_LOC_MAP_SPECULAR)
+ SHADER_LOC_MAP_NORMAL, // Shader location: sampler2d texture: normal
+ SHADER_LOC_MAP_ROUGHNESS, // Shader location: sampler2d texture: roughness
+ SHADER_LOC_MAP_OCCLUSION, // Shader location: sampler2d texture: occlusion
+ SHADER_LOC_MAP_EMISSION, // Shader location: sampler2d texture: emission
+ SHADER_LOC_MAP_HEIGHT, // Shader location: sampler2d texture: height
+ SHADER_LOC_MAP_CUBEMAP, // Shader location: samplerCube texture: cubemap
+ SHADER_LOC_MAP_IRRADIANCE, // Shader location: samplerCube texture: irradiance
+ SHADER_LOC_MAP_PREFILTER, // Shader location: samplerCube texture: prefilter
+ SHADER_LOC_MAP_BRDF, // Shader location: sampler2d texture: brdf
+ SHADER_LOC_VERTEX_BONEIDS, // Shader location: vertex attribute: boneIds
+ SHADER_LOC_VERTEX_BONEWEIGHTS, // Shader location: vertex attribute: boneWeights
+ SHADER_LOC_BONE_MATRICES, // Shader location: array of matrices uniform: boneMatrices
+ SHADER_LOC_VERTEX_INSTANCE_TX // Shader location: vertex attribute: instanceTransform
+} ShaderLocationIndex;
+
+#define SHADER_LOC_MAP_DIFFUSE SHADER_LOC_MAP_ALBEDO
+#define SHADER_LOC_MAP_SPECULAR SHADER_LOC_MAP_METALNESS
+
+// Shader uniform data type
+typedef enum {
+ SHADER_UNIFORM_FLOAT = 0, // Shader uniform type: float
+ SHADER_UNIFORM_VEC2, // Shader uniform type: vec2 (2 float)
+ SHADER_UNIFORM_VEC3, // Shader uniform type: vec3 (3 float)
+ SHADER_UNIFORM_VEC4, // Shader uniform type: vec4 (4 float)
+ SHADER_UNIFORM_INT, // Shader uniform type: int
+ SHADER_UNIFORM_IVEC2, // Shader uniform type: ivec2 (2 int)
+ SHADER_UNIFORM_IVEC3, // Shader uniform type: ivec3 (3 int)
+ SHADER_UNIFORM_IVEC4, // Shader uniform type: ivec4 (4 int)
+ SHADER_UNIFORM_UINT, // Shader uniform type: unsigned int
+ SHADER_UNIFORM_UIVEC2, // Shader uniform type: uivec2 (2 unsigned int)
+ SHADER_UNIFORM_UIVEC3, // Shader uniform type: uivec3 (3 unsigned int)
+ SHADER_UNIFORM_UIVEC4, // Shader uniform type: uivec4 (4 unsigned int)
+ SHADER_UNIFORM_SAMPLER2D // Shader uniform type: sampler2d
+} ShaderUniformDataType;
+
+// Shader attribute data types
+typedef enum {
+ SHADER_ATTRIB_FLOAT = 0, // Shader attribute type: float
+ SHADER_ATTRIB_VEC2, // Shader attribute type: vec2 (2 float)
+ SHADER_ATTRIB_VEC3, // Shader attribute type: vec3 (3 float)
+ SHADER_ATTRIB_VEC4 // Shader attribute type: vec4 (4 float)
+} ShaderAttributeDataType;
+
+// Pixel formats
+// NOTE: Support depends on OpenGL version and platform
+typedef enum {
+ PIXELFORMAT_UNCOMPRESSED_GRAYSCALE = 1, // 8 bit per pixel (no alpha)
+ PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA, // 8*2 bpp (2 channels)
+ PIXELFORMAT_UNCOMPRESSED_R5G6B5, // 16 bpp
+ PIXELFORMAT_UNCOMPRESSED_R8G8B8, // 24 bpp
+ PIXELFORMAT_UNCOMPRESSED_R5G5B5A1, // 16 bpp (1 bit alpha)
+ PIXELFORMAT_UNCOMPRESSED_R4G4B4A4, // 16 bpp (4 bit alpha)
+ PIXELFORMAT_UNCOMPRESSED_R8G8B8A8, // 32 bpp
+ PIXELFORMAT_UNCOMPRESSED_R32, // 32 bpp (1 channel - float)
+ PIXELFORMAT_UNCOMPRESSED_R32G32B32, // 32*3 bpp (3 channels - float)
+ PIXELFORMAT_UNCOMPRESSED_R32G32B32A32, // 32*4 bpp (4 channels - float)
+ PIXELFORMAT_UNCOMPRESSED_R16, // 16 bpp (1 channel - half float)
+ PIXELFORMAT_UNCOMPRESSED_R16G16B16, // 16*3 bpp (3 channels - half float)
+ PIXELFORMAT_UNCOMPRESSED_R16G16B16A16, // 16*4 bpp (4 channels - half float)
+ PIXELFORMAT_COMPRESSED_DXT1_RGB, // 4 bpp (no alpha)
+ PIXELFORMAT_COMPRESSED_DXT1_RGBA, // 4 bpp (1 bit alpha)
+ PIXELFORMAT_COMPRESSED_DXT3_RGBA, // 8 bpp
+ PIXELFORMAT_COMPRESSED_DXT5_RGBA, // 8 bpp
+ PIXELFORMAT_COMPRESSED_ETC1_RGB, // 4 bpp
+ PIXELFORMAT_COMPRESSED_ETC2_RGB, // 4 bpp
+ PIXELFORMAT_COMPRESSED_ETC2_EAC_RGBA, // 8 bpp
+ PIXELFORMAT_COMPRESSED_PVRT_RGB, // 4 bpp
+ PIXELFORMAT_COMPRESSED_PVRT_RGBA, // 4 bpp
+ PIXELFORMAT_COMPRESSED_ASTC_4x4_RGBA, // 8 bpp
+ PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA // 2 bpp
+} PixelFormat;
+
+// Texture parameters: filter mode
+// NOTE 1: Filtering considers mipmaps if available in the texture
+// NOTE 2: Filter is accordingly set for minification and magnification
+typedef enum {
+ TEXTURE_FILTER_POINT = 0, // No filter, just pixel approximation
+ TEXTURE_FILTER_BILINEAR, // Linear filtering
+ TEXTURE_FILTER_TRILINEAR, // Trilinear filtering (linear with mipmaps)
+ TEXTURE_FILTER_ANISOTROPIC_4X, // Anisotropic filtering 4x
+ TEXTURE_FILTER_ANISOTROPIC_8X, // Anisotropic filtering 8x
+ TEXTURE_FILTER_ANISOTROPIC_16X, // Anisotropic filtering 16x
+} TextureFilter;
+
+// Texture parameters: wrap mode
+typedef enum {
+ TEXTURE_WRAP_REPEAT = 0, // Repeats texture in tiled mode
+ TEXTURE_WRAP_CLAMP, // Clamps texture to edge pixel in tiled mode
+ TEXTURE_WRAP_MIRROR_REPEAT, // Mirrors and repeats the texture in tiled mode
+ TEXTURE_WRAP_MIRROR_CLAMP // Mirrors and clamps to border the texture in tiled mode
+} TextureWrap;
+
+// Cubemap layouts
+typedef enum {
+ CUBEMAP_LAYOUT_AUTO_DETECT = 0, // Automatically detect layout type
+ CUBEMAP_LAYOUT_LINE_VERTICAL, // Layout is defined by a vertical line with faces
+ CUBEMAP_LAYOUT_LINE_HORIZONTAL, // Layout is defined by a horizontal line with faces
+ CUBEMAP_LAYOUT_CROSS_THREE_BY_FOUR, // Layout is defined by a 3x4 cross with cubemap faces
+ CUBEMAP_LAYOUT_CROSS_FOUR_BY_THREE // Layout is defined by a 4x3 cross with cubemap faces
+} CubemapLayout;
+
+// Font type, defines generation method
+typedef enum {
+ FONT_DEFAULT = 0, // Default font generation, anti-aliased
+ FONT_BITMAP, // Bitmap font generation, no anti-aliasing
+ FONT_SDF // SDF font generation, requires external shader
+} FontType;
+
+// Color blending modes (pre-defined)
+typedef enum {
+ BLEND_ALPHA = 0, // Blend textures considering alpha (default)
+ BLEND_ADDITIVE, // Blend textures adding colors
+ BLEND_MULTIPLIED, // Blend textures multiplying colors
+ BLEND_ADD_COLORS, // Blend textures adding colors (alternative)
+ BLEND_SUBTRACT_COLORS, // Blend textures subtracting colors (alternative)
+ BLEND_ALPHA_PREMULTIPLY, // Blend premultiplied textures considering alpha
+ BLEND_CUSTOM, // Blend textures using custom src/dst factors (use rlSetBlendFactors())
+ BLEND_CUSTOM_SEPARATE // Blend textures using custom rgb/alpha separate src/dst factors (use rlSetBlendFactorsSeparate())
+} BlendMode;
+
+// Gesture
+// NOTE: Provided as bit-wise flags to enable only desired gestures
+typedef enum {
+ GESTURE_NONE = 0, // No gesture
+ GESTURE_TAP = 1, // Tap gesture
+ GESTURE_DOUBLETAP = 2, // Double tap gesture
+ GESTURE_HOLD = 4, // Hold gesture
+ GESTURE_DRAG = 8, // Drag gesture
+ GESTURE_SWIPE_RIGHT = 16, // Swipe right gesture
+ GESTURE_SWIPE_LEFT = 32, // Swipe left gesture
+ GESTURE_SWIPE_UP = 64, // Swipe up gesture
+ GESTURE_SWIPE_DOWN = 128, // Swipe down gesture
+ GESTURE_PINCH_IN = 256, // Pinch in gesture
+ GESTURE_PINCH_OUT = 512 // Pinch out gesture
+} Gesture;
+
+// Camera system modes
+typedef enum {
+ CAMERA_CUSTOM = 0, // Camera custom, controlled by user (UpdateCamera() does nothing)
+ CAMERA_FREE, // Camera free mode
+ CAMERA_ORBITAL, // Camera orbital, around target, zoom supported
+ CAMERA_FIRST_PERSON, // Camera first person
+ CAMERA_THIRD_PERSON // Camera third person
+} CameraMode;
+
+// Camera projection
+typedef enum {
+ CAMERA_PERSPECTIVE = 0, // Perspective projection
+ CAMERA_ORTHOGRAPHIC // Orthographic projection
+} CameraProjection;
+
+// N-patch layout
+typedef enum {
+ NPATCH_NINE_PATCH = 0, // Npatch layout: 3x3 tiles
+ NPATCH_THREE_PATCH_VERTICAL, // Npatch layout: 1x3 tiles
+ NPATCH_THREE_PATCH_HORIZONTAL // Npatch layout: 3x1 tiles
+} NPatchLayout;
+
+// Callbacks to hook some internal functions
+// WARNING: These callbacks are intended for advanced users
+typedef void (*TraceLogCallback)(int logLevel, const char *text, va_list args); // Logging: Redirect trace log messages
+typedef unsigned char *(*LoadFileDataCallback)(const char *fileName, int *dataSize); // FileIO: Load binary data
+typedef bool (*SaveFileDataCallback)(const char *fileName, void *data, int dataSize); // FileIO: Save binary data
+typedef char *(*LoadFileTextCallback)(const char *fileName); // FileIO: Load text data
+typedef bool (*SaveFileTextCallback)(const char *fileName, const char *text); // FileIO: Save text data
+
+//------------------------------------------------------------------------------------
+// Global Variables Definition
+//------------------------------------------------------------------------------------
+// It's lonely here...
+
+//------------------------------------------------------------------------------------
+// Window and Graphics Device Functions (Module: core)
+//------------------------------------------------------------------------------------
+
+#if defined(__cplusplus)
+extern "C" { // Prevents name mangling of functions
+#endif
+
+// Window-related functions
+RLAPI void InitWindow(int width, int height, const char *title); // Initialize window and OpenGL context
+RLAPI void CloseWindow(void); // Close window and unload OpenGL context
+RLAPI bool WindowShouldClose(void); // Check if application should close (KEY_ESCAPE pressed or windows close icon clicked)
+RLAPI bool IsWindowReady(void); // Check if window has been initialized successfully
+RLAPI bool IsWindowFullscreen(void); // Check if window is currently fullscreen
+RLAPI bool IsWindowHidden(void); // Check if window is currently hidden
+RLAPI bool IsWindowMinimized(void); // Check if window is currently minimized
+RLAPI bool IsWindowMaximized(void); // Check if window is currently maximized
+RLAPI bool IsWindowFocused(void); // Check if window is currently focused
+RLAPI bool IsWindowResized(void); // Check if window has been resized last frame
+RLAPI bool IsWindowState(unsigned int flag); // Check if one specific window flag is enabled
+RLAPI void SetWindowState(unsigned int flags); // Set window configuration state using flags
+RLAPI void ClearWindowState(unsigned int flags); // Clear window configuration state flags
+RLAPI void ToggleFullscreen(void); // Toggle window state: fullscreen/windowed, resizes monitor to match window resolution
+RLAPI void ToggleBorderlessWindowed(void); // Toggle window state: borderless windowed, resizes window to match monitor resolution
+RLAPI void MaximizeWindow(void); // Set window state: maximized, if resizable
+RLAPI void MinimizeWindow(void); // Set window state: minimized, if resizable
+RLAPI void RestoreWindow(void); // Restore window from being minimized/maximized
+RLAPI void SetWindowIcon(Image image); // Set icon for window (single image, RGBA 32bit)
+RLAPI void SetWindowIcons(Image *images, int count); // Set icon for window (multiple images, RGBA 32bit)
+RLAPI void SetWindowTitle(const char *title); // Set title for window
+RLAPI void SetWindowPosition(int x, int y); // Set window position on screen
+RLAPI void SetWindowMonitor(int monitor); // Set monitor for the current window
+RLAPI void SetWindowMinSize(int width, int height); // Set window minimum dimensions (for FLAG_WINDOW_RESIZABLE)
+RLAPI void SetWindowMaxSize(int width, int height); // Set window maximum dimensions (for FLAG_WINDOW_RESIZABLE)
+RLAPI void SetWindowSize(int width, int height); // Set window dimensions
+RLAPI void SetWindowOpacity(float opacity); // Set window opacity [0.0f..1.0f]
+RLAPI void SetWindowFocused(void); // Set window focused
+RLAPI void *GetWindowHandle(void); // Get native window handle
+RLAPI int GetScreenWidth(void); // Get current screen width
+RLAPI int GetScreenHeight(void); // Get current screen height
+RLAPI int GetRenderWidth(void); // Get current render width (it considers HiDPI)
+RLAPI int GetRenderHeight(void); // Get current render height (it considers HiDPI)
+RLAPI int GetMonitorCount(void); // Get number of connected monitors
+RLAPI int GetCurrentMonitor(void); // Get current monitor where window is placed
+RLAPI Vector2 GetMonitorPosition(int monitor); // Get specified monitor position
+RLAPI int GetMonitorWidth(int monitor); // Get specified monitor width (current video mode used by monitor)
+RLAPI int GetMonitorHeight(int monitor); // Get specified monitor height (current video mode used by monitor)
+RLAPI int GetMonitorPhysicalWidth(int monitor); // Get specified monitor physical width in millimetres
+RLAPI int GetMonitorPhysicalHeight(int monitor); // Get specified monitor physical height in millimetres
+RLAPI int GetMonitorRefreshRate(int monitor); // Get specified monitor refresh rate
+RLAPI Vector2 GetWindowPosition(void); // Get window position XY on monitor
+RLAPI Vector2 GetWindowScaleDPI(void); // Get window scale DPI factor
+RLAPI const char *GetMonitorName(int monitor); // Get the human-readable, UTF-8 encoded name of the specified monitor
+RLAPI void SetClipboardText(const char *text); // Set clipboard text content
+RLAPI const char *GetClipboardText(void); // Get clipboard text content
+RLAPI Image GetClipboardImage(void); // Get clipboard image content
+RLAPI void EnableEventWaiting(void); // Enable waiting for events on EndDrawing(), no automatic event polling
+RLAPI void DisableEventWaiting(void); // Disable waiting for events on EndDrawing(), automatic events polling
+
+// Cursor-related functions
+RLAPI void ShowCursor(void); // Shows cursor
+RLAPI void HideCursor(void); // Hides cursor
+RLAPI bool IsCursorHidden(void); // Check if cursor is not visible
+RLAPI void EnableCursor(void); // Enables cursor (unlock cursor)
+RLAPI void DisableCursor(void); // Disables cursor (lock cursor)
+RLAPI bool IsCursorOnScreen(void); // Check if cursor is on the screen
+
+// Drawing-related functions
+RLAPI void ClearBackground(Color color); // Set background color (framebuffer clear color)
+RLAPI void BeginDrawing(void); // Setup canvas (framebuffer) to start drawing
+RLAPI void EndDrawing(void); // End canvas drawing and swap buffers (double buffering)
+RLAPI void BeginMode2D(Camera2D camera); // Begin 2D mode with custom camera (2D)
+RLAPI void EndMode2D(void); // Ends 2D mode with custom camera
+RLAPI void BeginMode3D(Camera3D camera); // Begin 3D mode with custom camera (3D)
+RLAPI void EndMode3D(void); // Ends 3D mode and returns to default 2D orthographic mode
+RLAPI void BeginTextureMode(RenderTexture2D target); // Begin drawing to render texture
+RLAPI void EndTextureMode(void); // Ends drawing to render texture
+RLAPI void BeginShaderMode(Shader shader); // Begin custom shader drawing
+RLAPI void EndShaderMode(void); // End custom shader drawing (use default shader)
+RLAPI void BeginBlendMode(int mode); // Begin blending mode (alpha, additive, multiplied, subtract, custom)
+RLAPI void EndBlendMode(void); // End blending mode (reset to default: alpha blending)
+RLAPI void BeginScissorMode(int x, int y, int width, int height); // Begin scissor mode (define screen area for following drawing)
+RLAPI void EndScissorMode(void); // End scissor mode
+RLAPI void BeginVrStereoMode(VrStereoConfig config); // Begin stereo rendering (requires VR simulator)
+RLAPI void EndVrStereoMode(void); // End stereo rendering (requires VR simulator)
+
+// VR stereo config functions for VR simulator
+RLAPI VrStereoConfig LoadVrStereoConfig(VrDeviceInfo device); // Load VR stereo config for VR simulator device parameters
+RLAPI void UnloadVrStereoConfig(VrStereoConfig config); // Unload VR stereo config
+
+// Shader management functions
+// NOTE: Shader functionality is not available on OpenGL 1.1
+RLAPI Shader LoadShader(const char *vsFileName, const char *fsFileName); // Load shader from files and bind default locations
+RLAPI Shader LoadShaderFromMemory(const char *vsCode, const char *fsCode); // Load shader from code strings and bind default locations
+RLAPI bool IsShaderValid(Shader shader); // Check if a shader is valid (loaded on GPU)
+RLAPI int GetShaderLocation(Shader shader, const char *uniformName); // Get shader uniform location
+RLAPI int GetShaderLocationAttrib(Shader shader, const char *attribName); // Get shader attribute location
+RLAPI void SetShaderValue(Shader shader, int locIndex, const void *value, int uniformType); // Set shader uniform value
+RLAPI void SetShaderValueV(Shader shader, int locIndex, const void *value, int uniformType, int count); // Set shader uniform value vector
+RLAPI void SetShaderValueMatrix(Shader shader, int locIndex, Matrix mat); // Set shader uniform value (matrix 4x4)
+RLAPI void SetShaderValueTexture(Shader shader, int locIndex, Texture2D texture); // Set shader uniform value and bind the texture (sampler2d)
+RLAPI void UnloadShader(Shader shader); // Unload shader from GPU memory (VRAM)
+
+// Screen-space-related functions
+#define GetMouseRay GetScreenToWorldRay // Compatibility hack for previous raylib versions
+RLAPI Ray GetScreenToWorldRay(Vector2 position, Camera camera); // Get a ray trace from screen position (i.e mouse)
+RLAPI Ray GetScreenToWorldRayEx(Vector2 position, Camera camera, int width, int height); // Get a ray trace from screen position (i.e mouse) in a viewport
+RLAPI Vector2 GetWorldToScreen(Vector3 position, Camera camera); // Get the screen space position for a 3d world space position
+RLAPI Vector2 GetWorldToScreenEx(Vector3 position, Camera camera, int width, int height); // Get size position for a 3d world space position
+RLAPI Vector2 GetWorldToScreen2D(Vector2 position, Camera2D camera); // Get the screen space position for a 2d camera world space position
+RLAPI Vector2 GetScreenToWorld2D(Vector2 position, Camera2D camera); // Get the world space position for a 2d camera screen space position
+RLAPI Matrix GetCameraMatrix(Camera camera); // Get camera transform matrix (view matrix)
+RLAPI Matrix GetCameraMatrix2D(Camera2D camera); // Get camera 2d transform matrix
+
+// Timing-related functions
+RLAPI void SetTargetFPS(int fps); // Set target FPS (maximum)
+RLAPI float GetFrameTime(void); // Get time in seconds for last frame drawn (delta time)
+RLAPI double GetTime(void); // Get elapsed time in seconds since InitWindow()
+RLAPI int GetFPS(void); // Get current FPS
+
+// Custom frame control functions
+// NOTE: Those functions are intended for advanced users that want full control over the frame processing
+// By default EndDrawing() does this job: draws everything + SwapScreenBuffer() + manage frame timing + PollInputEvents()
+// To avoid that behaviour and control frame processes manually, enable in config.h: SUPPORT_CUSTOM_FRAME_CONTROL
+RLAPI void SwapScreenBuffer(void); // Swap back buffer with front buffer (screen drawing)
+RLAPI void PollInputEvents(void); // Register all input events
+RLAPI void WaitTime(double seconds); // Wait for some time (halt program execution)
+
+// Random values generation functions
+RLAPI void SetRandomSeed(unsigned int seed); // Set the seed for the random number generator
+RLAPI int GetRandomValue(int min, int max); // Get a random value between min and max (both included)
+RLAPI int *LoadRandomSequence(unsigned int count, int min, int max); // Load random values sequence, no values repeated
+RLAPI void UnloadRandomSequence(int *sequence); // Unload random values sequence
+
+// Misc. functions
+RLAPI void TakeScreenshot(const char *fileName); // Takes a screenshot of current screen (filename extension defines format)
+RLAPI void SetConfigFlags(unsigned int flags); // Setup init configuration flags (view FLAGS)
+RLAPI void OpenURL(const char *url); // Open URL with default system browser (if available)
+
+// NOTE: Following functions implemented in module [utils]
+//------------------------------------------------------------------
+RLAPI void TraceLog(int logLevel, const char *text, ...); // Show trace log messages (LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERROR...)
+RLAPI void SetTraceLogLevel(int logLevel); // Set the current threshold (minimum) log level
+RLAPI void *MemAlloc(unsigned int size); // Internal memory allocator
+RLAPI void *MemRealloc(void *ptr, unsigned int size); // Internal memory reallocator
+RLAPI void MemFree(void *ptr); // Internal memory free
+
+// Set custom callbacks
+// WARNING: Callbacks setup is intended for advanced users
+RLAPI void SetTraceLogCallback(TraceLogCallback callback); // Set custom trace log
+RLAPI void SetLoadFileDataCallback(LoadFileDataCallback callback); // Set custom file binary data loader
+RLAPI void SetSaveFileDataCallback(SaveFileDataCallback callback); // Set custom file binary data saver
+RLAPI void SetLoadFileTextCallback(LoadFileTextCallback callback); // Set custom file text data loader
+RLAPI void SetSaveFileTextCallback(SaveFileTextCallback callback); // Set custom file text data saver
+
+// Files management functions
+RLAPI unsigned char *LoadFileData(const char *fileName, int *dataSize); // Load file data as byte array (read)
+RLAPI void UnloadFileData(unsigned char *data); // Unload file data allocated by LoadFileData()
+RLAPI bool SaveFileData(const char *fileName, void *data, int dataSize); // Save data to file from byte array (write), returns true on success
+RLAPI bool ExportDataAsCode(const unsigned char *data, int dataSize, const char *fileName); // Export data to code (.h), returns true on success
+RLAPI char *LoadFileText(const char *fileName); // Load text data from file (read), returns a '\0' terminated string
+RLAPI void UnloadFileText(char *text); // Unload file text data allocated by LoadFileText()
+RLAPI bool SaveFileText(const char *fileName, const char *text); // Save text data to file (write), string must be '\0' terminated, returns true on success
+//------------------------------------------------------------------
+
+// File system functions
+RLAPI int FileRename(const char *fileName, const char *fileRename); // Rename file (if exists)
+RLAPI int FileRemove(const char *fileName); // Remove file (if exists)
+RLAPI int FileCopy(const char *srcPath, const char *dstPath); // Copy file from one path to another, dstPath created if it doesn't exist
+RLAPI int FileMove(const char *srcPath, const char *dstPath); // Move file from one directory to another, dstPath created if it doesn't exist
+RLAPI int FileTextReplace(const char *fileName, const char *search, const char *replacement); // Replace text in an existing file
+RLAPI int FileTextFindIndex(const char *fileName, const char *search); // Find text in existing file
+RLAPI bool FileExists(const char *fileName); // Check if file exists
+RLAPI bool DirectoryExists(const char *dirPath); // Check if a directory path exists
+RLAPI bool IsFileExtension(const char *fileName, const char *ext); // Check file extension (recommended include point: .png, .wav)
+RLAPI int GetFileLength(const char *fileName); // Get file length in bytes (NOTE: GetFileSize() conflicts with windows.h)
+RLAPI long GetFileModTime(const char *fileName); // Get file modification time (last write time)
+RLAPI const char *GetFileExtension(const char *fileName); // Get pointer to extension for a filename string (includes dot: '.png')
+RLAPI const char *GetFileName(const char *filePath); // Get pointer to filename for a path string
+RLAPI const char *GetFileNameWithoutExt(const char *filePath); // Get filename string without extension (uses static string)
+RLAPI const char *GetDirectoryPath(const char *filePath); // Get full path for a given fileName with path (uses static string)
+RLAPI const char *GetPrevDirectoryPath(const char *dirPath); // Get previous directory path for a given path (uses static string)
+RLAPI const char *GetWorkingDirectory(void); // Get current working directory (uses static string)
+RLAPI const char *GetApplicationDirectory(void); // Get the directory of the running application (uses static string)
+RLAPI int MakeDirectory(const char *dirPath); // Create directories (including full path requested), returns 0 on success
+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 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
+RLAPI void UnloadDroppedFiles(FilePathList files); // Unload dropped filepaths
+
+// Compression/Encoding functionality
+RLAPI unsigned char *CompressData(const unsigned char *data, int dataSize, int *compDataSize); // Compress data (DEFLATE algorithm), memory must be MemFree()
+RLAPI unsigned char *DecompressData(const unsigned char *compData, int compDataSize, int *dataSize); // Decompress data (DEFLATE algorithm), memory must be MemFree()
+RLAPI char *EncodeDataBase64(const unsigned char *data, int dataSize, int *outputSize); // Encode data to Base64 string (includes NULL terminator), memory must be MemFree()
+RLAPI unsigned char *DecodeDataBase64(const char *text, int *outputSize); // Decode Base64 string (expected NULL terminated), memory must be MemFree()
+RLAPI unsigned int ComputeCRC32(unsigned char *data, int dataSize); // Compute CRC32 hash code
+RLAPI unsigned int *ComputeMD5(unsigned char *data, int dataSize); // Compute MD5 hash code, returns static int[4] (16 bytes)
+RLAPI unsigned int *ComputeSHA1(unsigned char *data, int dataSize); // Compute SHA1 hash code, returns static int[5] (20 bytes)
+RLAPI unsigned int *ComputeSHA256(unsigned char *data, int dataSize); // Compute SHA256 hash code, returns static int[8] (32 bytes)
+
+// Automation events functionality
+RLAPI AutomationEventList LoadAutomationEventList(const char *fileName); // Load automation events list from file, NULL for empty list, capacity = MAX_AUTOMATION_EVENTS
+RLAPI void UnloadAutomationEventList(AutomationEventList list); // Unload automation events list from file
+RLAPI bool ExportAutomationEventList(AutomationEventList list, const char *fileName); // Export automation events list as text file
+RLAPI void SetAutomationEventList(AutomationEventList *list); // Set automation event list to record to
+RLAPI void SetAutomationEventBaseFrame(int frame); // Set automation event internal base frame to start recording
+RLAPI void StartAutomationEventRecording(void); // Start recording automation events (AutomationEventList must be set)
+RLAPI void StopAutomationEventRecording(void); // Stop recording automation events
+RLAPI void PlayAutomationEvent(AutomationEvent event); // Play a recorded automation event
+
+//------------------------------------------------------------------------------------
+// Input Handling Functions (Module: core)
+//------------------------------------------------------------------------------------
+
+// Input-related functions: keyboard
+RLAPI bool IsKeyPressed(int key); // Check if a key has been pressed once
+RLAPI bool IsKeyPressedRepeat(int key); // Check if a key has been pressed again
+RLAPI bool IsKeyDown(int key); // Check if a key is being pressed
+RLAPI bool IsKeyReleased(int key); // Check if a key has been released once
+RLAPI bool IsKeyUp(int key); // Check if a key is NOT being pressed
+RLAPI int GetKeyPressed(void); // Get key pressed (keycode), call it multiple times for keys queued, returns 0 when the queue is empty
+RLAPI int GetCharPressed(void); // Get char pressed (unicode), call it multiple times for chars queued, returns 0 when the queue is empty
+RLAPI const char *GetKeyName(int key); // Get name of a QWERTY key on the current keyboard layout (eg returns string 'q' for KEY_A on an AZERTY keyboard)
+RLAPI void SetExitKey(int key); // Set a custom key to exit program (default is ESC)
+
+// Input-related functions: gamepads
+RLAPI bool IsGamepadAvailable(int gamepad); // Check if a gamepad is available
+RLAPI const char *GetGamepadName(int gamepad); // Get gamepad internal name id
+RLAPI bool IsGamepadButtonPressed(int gamepad, int button); // Check if a gamepad button has been pressed once
+RLAPI bool IsGamepadButtonDown(int gamepad, int button); // Check if a gamepad button is being pressed
+RLAPI bool IsGamepadButtonReleased(int gamepad, int button); // Check if a gamepad button has been released once
+RLAPI bool IsGamepadButtonUp(int gamepad, int button); // Check if a gamepad button is NOT being pressed
+RLAPI int GetGamepadButtonPressed(void); // Get the last gamepad button pressed
+RLAPI int GetGamepadAxisCount(int gamepad); // Get axis count for a gamepad
+RLAPI float GetGamepadAxisMovement(int gamepad, int axis); // Get movement value for a gamepad axis
+RLAPI int SetGamepadMappings(const char *mappings); // Set internal gamepad mappings (SDL_GameControllerDB)
+RLAPI void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float duration); // Set gamepad vibration for both motors (duration in seconds)
+
+// Input-related functions: mouse
+RLAPI bool IsMouseButtonPressed(int button); // Check if a mouse button has been pressed once
+RLAPI bool IsMouseButtonDown(int button); // Check if a mouse button is being pressed
+RLAPI bool IsMouseButtonReleased(int button); // Check if a mouse button has been released once
+RLAPI bool IsMouseButtonUp(int button); // Check if a mouse button is NOT being pressed
+RLAPI int GetMouseX(void); // Get mouse position X
+RLAPI int GetMouseY(void); // Get mouse position Y
+RLAPI Vector2 GetMousePosition(void); // Get mouse position XY
+RLAPI Vector2 GetMouseDelta(void); // Get mouse delta between frames
+RLAPI void SetMousePosition(int x, int y); // Set mouse position XY
+RLAPI void SetMouseOffset(int offsetX, int offsetY); // Set mouse offset
+RLAPI void SetMouseScale(float scaleX, float scaleY); // Set mouse scaling
+RLAPI float GetMouseWheelMove(void); // Get mouse wheel movement for X or Y, whichever is larger
+RLAPI Vector2 GetMouseWheelMoveV(void); // Get mouse wheel movement for both X and Y
+RLAPI void SetMouseCursor(int cursor); // Set mouse cursor
+
+// Input-related functions: touch
+RLAPI int GetTouchX(void); // Get touch position X for touch point 0 (relative to screen size)
+RLAPI int GetTouchY(void); // Get touch position Y for touch point 0 (relative to screen size)
+RLAPI Vector2 GetTouchPosition(int index); // Get touch position XY for a touch point index (relative to screen size)
+RLAPI int GetTouchPointId(int index); // Get touch point identifier for given index
+RLAPI int GetTouchPointCount(void); // Get number of touch points
+
+//------------------------------------------------------------------------------------
+// Gestures and Touch Handling Functions (Module: rgestures)
+//------------------------------------------------------------------------------------
+RLAPI void SetGesturesEnabled(unsigned int flags); // Enable a set of gestures using flags
+RLAPI bool IsGestureDetected(unsigned int gesture); // Check if a gesture have been detected
+RLAPI int GetGestureDetected(void); // Get latest detected gesture
+RLAPI float GetGestureHoldDuration(void); // Get gesture hold time in seconds
+RLAPI Vector2 GetGestureDragVector(void); // Get gesture drag vector
+RLAPI float GetGestureDragAngle(void); // Get gesture drag angle
+RLAPI Vector2 GetGesturePinchVector(void); // Get gesture pinch delta
+RLAPI float GetGesturePinchAngle(void); // Get gesture pinch angle
+
+//------------------------------------------------------------------------------------
+// Camera System Functions (Module: rcamera)
+//------------------------------------------------------------------------------------
+RLAPI void UpdateCamera(Camera *camera, int mode); // Update camera position for selected mode
+RLAPI void UpdateCameraPro(Camera *camera, Vector3 movement, Vector3 rotation, float zoom); // Update camera movement/rotation
+
+//------------------------------------------------------------------------------------
+// Basic Shapes Drawing Functions (Module: shapes)
+//------------------------------------------------------------------------------------
+// Set texture and rectangle to be used on shapes drawing
+// NOTE: It can be useful when using basic shapes and one single font,
+// defining a font char white rectangle would allow drawing everything in a single draw call
+RLAPI void SetShapesTexture(Texture2D texture, Rectangle source); // Set texture and rectangle to be used on shapes drawing
+RLAPI Texture2D GetShapesTexture(void); // Get texture that is used for shapes drawing
+RLAPI Rectangle GetShapesTextureRectangle(void); // Get texture source rectangle that is used for shapes drawing
+
+// Basic shapes drawing functions
+RLAPI void DrawPixel(int posX, int posY, Color color); // Draw a pixel using geometry [Can be slow, use with care]
+RLAPI void DrawPixelV(Vector2 position, Color color); // Draw a pixel using geometry (Vector version) [Can be slow, use with care]
+RLAPI void DrawLine(int startPosX, int startPosY, int endPosX, int endPosY, Color color); // Draw a line
+RLAPI void DrawLineV(Vector2 startPos, Vector2 endPos, Color color); // Draw a line (using gl lines)
+RLAPI void DrawLineEx(Vector2 startPos, Vector2 endPos, float thick, Color color); // Draw a line (using triangles/quads)
+RLAPI void DrawLineStrip(const Vector2 *points, int pointCount, Color color); // Draw lines sequence (using gl lines)
+RLAPI void DrawLineBezier(Vector2 startPos, Vector2 endPos, float thick, Color color); // Draw line segment cubic-bezier in-out interpolation
+RLAPI void DrawLineDashed(Vector2 startPos, Vector2 endPos, int dashSize, int spaceSize, Color color); // Draw a dashed line
+RLAPI void DrawCircle(int centerX, int centerY, float radius, Color color); // Draw a color-filled circle
+RLAPI void DrawCircleSector(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw a piece of a circle
+RLAPI void DrawCircleSectorLines(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw circle sector outline
+RLAPI void DrawCircleGradient(int centerX, int centerY, float radius, Color inner, Color outer); // Draw a gradient-filled circle
+RLAPI void DrawCircleV(Vector2 center, float radius, Color color); // Draw a color-filled circle (Vector version)
+RLAPI void DrawCircleLines(int centerX, int centerY, float radius, Color color); // Draw circle outline
+RLAPI void DrawCircleLinesV(Vector2 center, float radius, Color color); // Draw circle outline (Vector version)
+RLAPI void DrawEllipse(int centerX, int centerY, float radiusH, float radiusV, Color color); // Draw ellipse
+RLAPI void DrawEllipseV(Vector2 center, float radiusH, float radiusV, Color color); // Draw ellipse (Vector version)
+RLAPI void DrawEllipseLines(int centerX, int centerY, float radiusH, float radiusV, Color color); // Draw ellipse outline
+RLAPI void DrawEllipseLinesV(Vector2 center, float radiusH, float radiusV, Color color); // Draw ellipse outline (Vector version)
+RLAPI void DrawRing(Vector2 center, float innerRadius, float outerRadius, float startAngle, float endAngle, int segments, Color color); // Draw ring
+RLAPI void DrawRingLines(Vector2 center, float innerRadius, float outerRadius, float startAngle, float endAngle, int segments, Color color); // Draw ring outline
+RLAPI void DrawRectangle(int posX, int posY, int width, int height, Color color); // Draw a color-filled rectangle
+RLAPI void DrawRectangleV(Vector2 position, Vector2 size, Color color); // Draw a color-filled rectangle (Vector version)
+RLAPI void DrawRectangleRec(Rectangle rec, Color color); // Draw a color-filled rectangle
+RLAPI void DrawRectanglePro(Rectangle rec, Vector2 origin, float rotation, Color color); // Draw a color-filled rectangle with pro parameters
+RLAPI void DrawRectangleGradientV(int posX, int posY, int width, int height, Color top, Color bottom); // Draw a vertical-gradient-filled rectangle
+RLAPI void DrawRectangleGradientH(int posX, int posY, int width, int height, Color left, Color right); // Draw a horizontal-gradient-filled rectangle
+RLAPI void DrawRectangleGradientEx(Rectangle rec, Color topLeft, Color bottomLeft, Color bottomRight, Color topRight); // Draw a gradient-filled rectangle with custom vertex colors
+RLAPI void DrawRectangleLines(int posX, int posY, int width, int height, Color color); // Draw rectangle outline
+RLAPI void DrawRectangleLinesEx(Rectangle rec, float lineThick, Color color); // Draw rectangle outline with extended parameters
+RLAPI void DrawRectangleRounded(Rectangle rec, float roundness, int segments, Color color); // Draw rectangle with rounded edges
+RLAPI void DrawRectangleRoundedLines(Rectangle rec, float roundness, int segments, Color color); // Draw rectangle lines with rounded edges
+RLAPI void DrawRectangleRoundedLinesEx(Rectangle rec, float roundness, int segments, float lineThick, Color color); // Draw rectangle with rounded edges outline
+RLAPI void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw a color-filled triangle (vertex in counter-clockwise order!)
+RLAPI void DrawTriangleLines(Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw triangle outline (vertex in counter-clockwise order!)
+RLAPI void DrawTriangleFan(const Vector2 *points, int pointCount, Color color); // Draw a triangle fan defined by points (first vertex is the center)
+RLAPI void DrawTriangleStrip(const Vector2 *points, int pointCount, Color color); // Draw a triangle strip defined by points
+RLAPI void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color color); // Draw a regular polygon (Vector version)
+RLAPI void DrawPolyLines(Vector2 center, int sides, float radius, float rotation, Color color); // Draw a polygon outline of n sides
+RLAPI void DrawPolyLinesEx(Vector2 center, int sides, float radius, float rotation, float lineThick, Color color); // Draw a polygon outline of n sides with extended parameters
+
+// Splines drawing functions
+RLAPI void DrawSplineLinear(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Linear, minimum 2 points
+RLAPI void DrawSplineBasis(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: B-Spline, minimum 4 points
+RLAPI void DrawSplineCatmullRom(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Catmull-Rom, minimum 4 points
+RLAPI void DrawSplineBezierQuadratic(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Quadratic Bezier, minimum 3 points (1 control point): [p1, c2, p3, c4...]
+RLAPI void DrawSplineBezierCubic(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Cubic Bezier, minimum 4 points (2 control points): [p1, c2, c3, p4, c5, c6...]
+RLAPI void DrawSplineSegmentLinear(Vector2 p1, Vector2 p2, float thick, Color color); // Draw spline segment: Linear, 2 points
+RLAPI void DrawSplineSegmentBasis(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, float thick, Color color); // Draw spline segment: B-Spline, 4 points
+RLAPI void DrawSplineSegmentCatmullRom(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, float thick, Color color); // Draw spline segment: Catmull-Rom, 4 points
+RLAPI void DrawSplineSegmentBezierQuadratic(Vector2 p1, Vector2 c2, Vector2 p3, float thick, Color color); // Draw spline segment: Quadratic Bezier, 2 points, 1 control point
+RLAPI void DrawSplineSegmentBezierCubic(Vector2 p1, Vector2 c2, Vector2 c3, Vector2 p4, float thick, Color color); // Draw spline segment: Cubic Bezier, 2 points, 2 control points
+
+// Spline segment point evaluation functions, for a given t [0.0f .. 1.0f]
+RLAPI Vector2 GetSplinePointLinear(Vector2 startPos, Vector2 endPos, float t); // Get (evaluate) spline point: Linear
+RLAPI Vector2 GetSplinePointBasis(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, float t); // Get (evaluate) spline point: B-Spline
+RLAPI Vector2 GetSplinePointCatmullRom(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, float t); // Get (evaluate) spline point: Catmull-Rom
+RLAPI Vector2 GetSplinePointBezierQuad(Vector2 p1, Vector2 c2, Vector2 p3, float t); // Get (evaluate) spline point: Quadratic Bezier
+RLAPI Vector2 GetSplinePointBezierCubic(Vector2 p1, Vector2 c2, Vector2 c3, Vector2 p4, float t); // Get (evaluate) spline point: Cubic Bezier
+
+// Basic shapes collision detection functions
+RLAPI bool CheckCollisionRecs(Rectangle rec1, Rectangle rec2); // Check collision between two rectangles
+RLAPI bool CheckCollisionCircles(Vector2 center1, float radius1, Vector2 center2, float radius2); // Check collision between two circles
+RLAPI bool CheckCollisionCircleRec(Vector2 center, float radius, Rectangle rec); // Check collision between circle and rectangle
+RLAPI bool CheckCollisionCircleLine(Vector2 center, float radius, Vector2 p1, Vector2 p2); // Check if circle collides with a line created betweeen two points [p1] and [p2]
+RLAPI bool CheckCollisionPointRec(Vector2 point, Rectangle rec); // Check if point is inside rectangle
+RLAPI bool CheckCollisionPointCircle(Vector2 point, Vector2 center, float radius); // Check if point is inside circle
+RLAPI bool CheckCollisionPointTriangle(Vector2 point, Vector2 p1, Vector2 p2, Vector2 p3); // Check if point is inside a triangle
+RLAPI bool CheckCollisionPointLine(Vector2 point, Vector2 p1, Vector2 p2, int threshold); // Check if point belongs to line created between two points [p1] and [p2] with defined margin in pixels [threshold]
+RLAPI bool CheckCollisionPointPoly(Vector2 point, const Vector2 *points, int pointCount); // Check if point is within a polygon described by array of vertices
+RLAPI bool CheckCollisionLines(Vector2 startPos1, Vector2 endPos1, Vector2 startPos2, Vector2 endPos2, Vector2 *collisionPoint); // Check the collision between two lines defined by two points each, returns collision point by reference
+RLAPI Rectangle GetCollisionRec(Rectangle rec1, Rectangle rec2); // Get collision rectangle for two rectangles collision
+
+//------------------------------------------------------------------------------------
+// Texture Loading and Drawing Functions (Module: textures)
+//------------------------------------------------------------------------------------
+
+// Image loading functions
+// NOTE: These functions do not require GPU access
+RLAPI Image LoadImage(const char *fileName); // Load image from file into CPU memory (RAM)
+RLAPI Image LoadImageRaw(const char *fileName, int width, int height, int format, int headerSize); // Load image from RAW file data
+RLAPI Image LoadImageAnim(const char *fileName, int *frames); // Load image sequence from file (frames appended to image.data)
+RLAPI Image LoadImageAnimFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int *frames); // Load image sequence from memory buffer
+RLAPI Image LoadImageFromMemory(const char *fileType, const unsigned char *fileData, int dataSize); // Load image from memory buffer, fileType refers to extension: i.e. '.png'
+RLAPI Image LoadImageFromTexture(Texture2D texture); // Load image from GPU texture data
+RLAPI Image LoadImageFromScreen(void); // Load image from screen buffer and (screenshot)
+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 bool ExportImageAsCode(Image image, const char *fileName); // Export image as code file defining an array of bytes, returns true on success
+
+// Image generation functions
+RLAPI Image GenImageColor(int width, int height, Color color); // Generate image: plain color
+RLAPI Image GenImageGradientLinear(int width, int height, int direction, Color start, Color end); // Generate image: linear gradient, direction in degrees [0..360], 0=Vertical gradient
+RLAPI Image GenImageGradientRadial(int width, int height, float density, Color inner, Color outer); // Generate image: radial gradient
+RLAPI Image GenImageGradientSquare(int width, int height, float density, Color inner, Color outer); // Generate image: square gradient
+RLAPI Image GenImageChecked(int width, int height, int checksX, int checksY, Color col1, Color col2); // Generate image: checked
+RLAPI Image GenImageWhiteNoise(int width, int height, float factor); // Generate image: white noise
+RLAPI Image GenImagePerlinNoise(int width, int height, int offsetX, int offsetY, float scale); // Generate image: perlin noise
+RLAPI Image GenImageCellular(int width, int height, int tileSize); // Generate image: cellular algorithm, bigger tileSize means bigger cells
+RLAPI Image GenImageText(int width, int height, const char *text); // Generate image: grayscale image from text data
+
+// Image manipulation functions
+RLAPI Image ImageCopy(Image image); // Create an image duplicate (useful for transformations)
+RLAPI Image ImageFromImage(Image image, Rectangle rec); // Create an image from another image piece
+RLAPI Image ImageFromChannel(Image image, int selectedChannel); // Create an image from a selected channel of another image (GRAYSCALE)
+RLAPI Image ImageText(const char *text, int fontSize, Color color); // Create an image from text (default font)
+RLAPI Image ImageTextEx(Font font, const char *text, float fontSize, float spacing, Color tint); // Create an image from text (custom sprite font)
+RLAPI void ImageFormat(Image *image, int newFormat); // Convert image data to desired format
+RLAPI void ImageToPOT(Image *image, Color fill); // Convert image to POT (power-of-two)
+RLAPI void ImageCrop(Image *image, Rectangle crop); // Crop an image to a defined rectangle
+RLAPI void ImageAlphaCrop(Image *image, float threshold); // Crop image depending on alpha value
+RLAPI void ImageAlphaClear(Image *image, Color color, float threshold); // Clear alpha channel to desired color
+RLAPI void ImageAlphaMask(Image *image, Image alphaMask); // Apply alpha mask to image
+RLAPI void ImageAlphaPremultiply(Image *image); // Premultiply alpha channel
+RLAPI void ImageBlurGaussian(Image *image, int blurSize); // Apply Gaussian blur using a box blur approximation
+RLAPI void ImageKernelConvolution(Image *image, const float *kernel, int kernelSize); // Apply custom square convolution kernel to image
+RLAPI void ImageResize(Image *image, int newWidth, int newHeight); // Resize image (Bicubic scaling algorithm)
+RLAPI void ImageResizeNN(Image *image, int newWidth, int newHeight); // Resize image (Nearest-Neighbor scaling algorithm)
+RLAPI void ImageResizeCanvas(Image *image, int newWidth, int newHeight, int offsetX, int offsetY, Color fill); // Resize canvas and fill with color
+RLAPI void ImageMipmaps(Image *image); // Compute all mipmap levels for a provided image
+RLAPI void ImageDither(Image *image, int rBpp, int gBpp, int bBpp, int aBpp); // Dither image data to 16bpp or lower (Floyd-Steinberg dithering)
+RLAPI void ImageFlipVertical(Image *image); // Flip image vertically
+RLAPI void ImageFlipHorizontal(Image *image); // Flip image horizontally
+RLAPI void ImageRotate(Image *image, int degrees); // Rotate image by input angle in degrees (-359 to 359)
+RLAPI void ImageRotateCW(Image *image); // Rotate image clockwise 90deg
+RLAPI void ImageRotateCCW(Image *image); // Rotate image counter-clockwise 90deg
+RLAPI void ImageColorTint(Image *image, Color color); // Modify image color: tint
+RLAPI void ImageColorInvert(Image *image); // Modify image color: invert
+RLAPI void ImageColorGrayscale(Image *image); // Modify image color: grayscale
+RLAPI void ImageColorContrast(Image *image, float contrast); // Modify image color: contrast (-100 to 100)
+RLAPI void ImageColorBrightness(Image *image, int brightness); // Modify image color: brightness (-255 to 255)
+RLAPI void ImageColorReplace(Image *image, Color color, Color replace); // Modify image color: replace color
+RLAPI Color *LoadImageColors(Image image); // Load color data from image as a Color array (RGBA - 32bit)
+RLAPI Color *LoadImagePalette(Image image, int maxPaletteSize, int *colorCount); // Load colors palette from image as a Color array (RGBA - 32bit)
+RLAPI void UnloadImageColors(Color *colors); // Unload color data loaded with LoadImageColors()
+RLAPI void UnloadImagePalette(Color *colors); // Unload colors palette loaded with LoadImagePalette()
+RLAPI Rectangle GetImageAlphaBorder(Image image, float threshold); // Get image alpha border rectangle
+RLAPI Color GetImageColor(Image image, int x, int y); // Get image pixel color at (x, y) position
+
+// Image drawing functions
+// NOTE: Image software-rendering functions (CPU)
+RLAPI void ImageClearBackground(Image *dst, Color color); // Clear image background with given color
+RLAPI void ImageDrawPixel(Image *dst, int posX, int posY, Color color); // Draw pixel within an image
+RLAPI void ImageDrawPixelV(Image *dst, Vector2 position, Color color); // Draw pixel within an image (Vector version)
+RLAPI void ImageDrawLine(Image *dst, int startPosX, int startPosY, int endPosX, int endPosY, Color color); // Draw line within an image
+RLAPI void ImageDrawLineV(Image *dst, Vector2 start, Vector2 end, Color color); // Draw line within an image (Vector version)
+RLAPI void ImageDrawLineEx(Image *dst, Vector2 start, Vector2 end, int thick, Color color); // Draw a line defining thickness within an image
+RLAPI void ImageDrawCircle(Image *dst, int centerX, int centerY, int radius, Color color); // Draw a filled circle within an image
+RLAPI void ImageDrawCircleV(Image *dst, Vector2 center, int radius, Color color); // Draw a filled circle within an image (Vector version)
+RLAPI void ImageDrawCircleLines(Image *dst, int centerX, int centerY, int radius, Color color); // Draw circle outline within an image
+RLAPI void ImageDrawCircleLinesV(Image *dst, Vector2 center, int radius, Color color); // Draw circle outline within an image (Vector version)
+RLAPI void ImageDrawRectangle(Image *dst, int posX, int posY, int width, int height, Color color); // Draw rectangle within an image
+RLAPI void ImageDrawRectangleV(Image *dst, Vector2 position, Vector2 size, Color color); // Draw rectangle within an image (Vector version)
+RLAPI void ImageDrawRectangleRec(Image *dst, Rectangle rec, Color color); // Draw rectangle within an image
+RLAPI void ImageDrawRectangleLines(Image *dst, Rectangle rec, int thick, Color color); // Draw rectangle lines within an image
+RLAPI void ImageDrawTriangle(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw triangle within an image
+RLAPI void ImageDrawTriangleEx(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color c1, Color c2, Color c3); // Draw triangle with interpolated colors within an image
+RLAPI void ImageDrawTriangleLines(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw triangle outline within an image
+RLAPI void ImageDrawTriangleFan(Image *dst, const Vector2 *points, int pointCount, Color color); // Draw a triangle fan defined by points within an image (first vertex is the center)
+RLAPI void ImageDrawTriangleStrip(Image *dst, const Vector2 *points, int pointCount, Color color); // Draw a triangle strip defined by points within an image
+RLAPI void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec, Color tint); // Draw a source image within a destination image (tint applied to source)
+RLAPI void ImageDrawText(Image *dst, const char *text, int posX, int posY, int fontSize, Color color); // Draw text (using default font) within an image (destination)
+RLAPI void ImageDrawTextEx(Image *dst, Font font, const char *text, Vector2 position, float fontSize, float spacing, Color tint); // Draw text (custom sprite font) within an image (destination)
+
+// Texture loading functions
+// NOTE: These functions require GPU access
+RLAPI Texture2D LoadTexture(const char *fileName); // Load texture from file into GPU memory (VRAM)
+RLAPI Texture2D LoadTextureFromImage(Image image); // Load texture from image data
+RLAPI TextureCubemap LoadTextureCubemap(Image image, int layout); // Load cubemap from image, multiple image cubemap layouts supported
+RLAPI RenderTexture2D LoadRenderTexture(int width, int height); // Load texture for rendering (framebuffer)
+RLAPI bool IsTextureValid(Texture2D texture); // Check if a texture is valid (loaded in GPU)
+RLAPI void UnloadTexture(Texture2D texture); // Unload texture from GPU memory (VRAM)
+RLAPI bool IsRenderTextureValid(RenderTexture2D target); // Check if a render texture is valid (loaded in GPU)
+RLAPI void UnloadRenderTexture(RenderTexture2D target); // Unload render texture from GPU memory (VRAM)
+RLAPI void UpdateTexture(Texture2D texture, const void *pixels); // Update GPU texture with new data (pixels should be able to fill texture)
+RLAPI void UpdateTextureRec(Texture2D texture, Rectangle rec, const void *pixels); // Update GPU texture rectangle with new data (pixels and rec should fit in texture)
+
+// Texture configuration functions
+RLAPI void GenTextureMipmaps(Texture2D *texture); // Generate GPU mipmaps for a texture
+RLAPI void SetTextureFilter(Texture2D texture, int filter); // Set texture scaling filter mode
+RLAPI void SetTextureWrap(Texture2D texture, int wrap); // Set texture wrapping mode
+
+// Texture drawing functions
+RLAPI void DrawTexture(Texture2D texture, int posX, int posY, Color tint); // Draw a Texture2D
+RLAPI void DrawTextureV(Texture2D texture, Vector2 position, Color tint); // Draw a Texture2D with position defined as Vector2
+RLAPI void DrawTextureEx(Texture2D texture, Vector2 position, float rotation, float scale, Color tint); // Draw a Texture2D with extended parameters
+RLAPI void DrawTextureRec(Texture2D texture, Rectangle source, Vector2 position, Color tint); // Draw a part of a texture defined by a rectangle
+RLAPI void DrawTexturePro(Texture2D texture, Rectangle source, Rectangle dest, Vector2 origin, float rotation, Color tint); // Draw a part of a texture defined by a rectangle with 'pro' parameters
+RLAPI void DrawTextureNPatch(Texture2D texture, NPatchInfo nPatchInfo, Rectangle dest, Vector2 origin, float rotation, Color tint); // Draws a texture (or part of it) that stretches or shrinks nicely
+
+// Color/pixel related functions
+RLAPI bool ColorIsEqual(Color col1, Color col2); // Check if two colors are equal
+RLAPI Color Fade(Color color, float alpha); // Get color with alpha applied, alpha goes from 0.0f to 1.0f
+RLAPI int ColorToInt(Color color); // Get hexadecimal value for a Color (0xRRGGBBAA)
+RLAPI Vector4 ColorNormalize(Color color); // Get Color normalized as float [0..1]
+RLAPI Color ColorFromNormalized(Vector4 normalized); // Get Color from normalized values [0..1]
+RLAPI Vector3 ColorToHSV(Color color); // Get HSV values for a Color, hue [0..360], saturation/value [0..1]
+RLAPI Color ColorFromHSV(float hue, float saturation, float value); // Get a Color from HSV values, hue [0..360], saturation/value [0..1]
+RLAPI Color ColorTint(Color color, Color tint); // Get color multiplied with another color
+RLAPI Color ColorBrightness(Color color, float factor); // Get color with brightness correction, brightness factor goes from -1.0f to 1.0f
+RLAPI Color ColorContrast(Color color, float contrast); // Get color with contrast correction, contrast values between -1.0f and 1.0f
+RLAPI Color ColorAlpha(Color color, float alpha); // Get color with alpha applied, alpha goes from 0.0f to 1.0f
+RLAPI Color ColorAlphaBlend(Color dst, Color src, Color tint); // Get src alpha-blended into dst color with tint
+RLAPI Color ColorLerp(Color color1, Color color2, float factor); // Get color lerp interpolation between two colors, factor [0.0f..1.0f]
+RLAPI Color GetColor(unsigned int hexValue); // Get Color structure from hexadecimal value
+RLAPI Color GetPixelColor(void *srcPtr, int format); // Get Color from a source pixel pointer of certain format
+RLAPI void SetPixelColor(void *dstPtr, Color color, int format); // Set color formatted into destination pixel pointer
+RLAPI int GetPixelDataSize(int width, int height, int format); // Get pixel data size in bytes for certain format
+
+//------------------------------------------------------------------------------------
+// Font Loading and Text Drawing Functions (Module: text)
+//------------------------------------------------------------------------------------
+
+// Font loading/unloading functions
+RLAPI Font GetFontDefault(void); // Get the default Font
+RLAPI Font LoadFont(const char *fileName); // Load font from file into GPU memory (VRAM)
+RLAPI Font LoadFontEx(const char *fileName, int fontSize, const int *codepoints, int codepointCount); // Load font from file with extended parameters, use NULL for codepoints and 0 for codepointCount to load the default character set, font size is provided in pixels height
+RLAPI Font LoadFontFromImage(Image image, Color key, int firstChar); // Load font from Image (XNA style)
+RLAPI Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int fontSize, const int *codepoints, int codepointCount); // Load font from memory buffer, fileType refers to extension: i.e. '.ttf'
+RLAPI bool IsFontValid(Font font); // Check if a font is valid (font data loaded, WARNING: GPU texture not checked)
+RLAPI GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, const int *codepoints, int codepointCount, int type, int *glyphCount); // Load font data for further use
+RLAPI Image GenImageFontAtlas(const GlyphInfo *glyphs, Rectangle **glyphRecs, int glyphCount, int fontSize, int padding, int packMethod); // Generate image font atlas using chars info
+RLAPI void UnloadFontData(GlyphInfo *glyphs, int glyphCount); // Unload font chars info data (RAM)
+RLAPI void UnloadFont(Font font); // Unload font from GPU memory (VRAM)
+RLAPI bool ExportFontAsCode(Font font, const char *fileName); // Export font as code file, returns true on success
+
+// Text drawing functions
+RLAPI void DrawFPS(int posX, int posY); // Draw current FPS
+RLAPI void DrawText(const char *text, int posX, int posY, int fontSize, Color color); // Draw text (using default font)
+RLAPI void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, float spacing, Color tint); // Draw text using font and additional parameters
+RLAPI void DrawTextPro(Font font, const char *text, Vector2 position, Vector2 origin, float rotation, float fontSize, float spacing, Color tint); // Draw text using Font and pro parameters (rotation)
+RLAPI void DrawTextCodepoint(Font font, int codepoint, Vector2 position, float fontSize, Color tint); // Draw one character (codepoint)
+RLAPI void DrawTextCodepoints(Font font, const int *codepoints, int codepointCount, Vector2 position, float fontSize, float spacing, Color tint); // Draw multiple character (codepoint)
+
+// Text font info functions
+RLAPI void SetTextLineSpacing(int spacing); // Set vertical line spacing when drawing with line-breaks
+RLAPI int MeasureText(const char *text, int fontSize); // Measure string width for default font
+RLAPI Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing); // Measure string size for Font
+RLAPI int GetGlyphIndex(Font font, int codepoint); // Get glyph index position in font for a codepoint (unicode character), fallback to '?' if not found
+RLAPI GlyphInfo GetGlyphInfo(Font font, int codepoint); // Get glyph font info data for a codepoint (unicode character), fallback to '?' if not found
+RLAPI Rectangle GetGlyphAtlasRec(Font font, int codepoint); // Get glyph rectangle in font atlas for a codepoint (unicode character), fallback to '?' if not found
+
+// Text codepoints management functions (unicode characters)
+RLAPI char *LoadUTF8(const int *codepoints, int length); // Load UTF-8 text encoded from codepoints array
+RLAPI void UnloadUTF8(char *text); // Unload UTF-8 text encoded from codepoints array
+RLAPI int *LoadCodepoints(const char *text, int *count); // Load all codepoints from a UTF-8 text string, codepoints count returned by parameter
+RLAPI void UnloadCodepoints(int *codepoints); // Unload codepoints data from memory
+RLAPI int GetCodepointCount(const char *text); // Get total number of codepoints in a UTF-8 encoded string
+RLAPI int GetCodepoint(const char *text, int *codepointSize); // Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure
+RLAPI int GetCodepointNext(const char *text, int *codepointSize); // Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure
+RLAPI int GetCodepointPrevious(const char *text, int *codepointSize); // Get previous codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure
+RLAPI const char *CodepointToUTF8(int codepoint, int *utf8Size); // Encode one codepoint into UTF-8 byte array (array length returned as parameter)
+
+// 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()
+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
+RLAPI bool TextIsEqual(const char *text1, const char *text2); // Check if two text string are equal
+RLAPI unsigned int TextLength(const char *text); // Get text length, checks for '\0' ending
+RLAPI const char *TextFormat(const char *text, ...); // Text formatting with variables (sprintf() style)
+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 *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
+RLAPI int TextFindIndex(const char *text, const char *search); // Find first text occurrence within a string, -1 if not found
+RLAPI char *TextToUpper(const char *text); // Get upper case version of provided string
+RLAPI char *TextToLower(const char *text); // Get lower case version of provided string
+RLAPI char *TextToPascal(const char *text); // Get Pascal case notation version of provided string
+RLAPI char *TextToSnake(const char *text); // Get Snake case notation version of provided string
+RLAPI char *TextToCamel(const char *text); // Get Camel case notation version of provided string
+RLAPI int TextToInteger(const char *text); // Get integer value from text
+RLAPI float TextToFloat(const char *text); // Get float value from text
+
+//------------------------------------------------------------------------------------
+// Basic 3d Shapes Drawing Functions (Module: models)
+//------------------------------------------------------------------------------------
+
+// Basic geometric 3D shapes drawing functions
+RLAPI void DrawLine3D(Vector3 startPos, Vector3 endPos, Color color); // Draw a line in 3D world space
+RLAPI void DrawPoint3D(Vector3 position, Color color); // Draw a point in 3D space, actually a small line
+RLAPI void DrawCircle3D(Vector3 center, float radius, Vector3 rotationAxis, float rotationAngle, Color color); // Draw a circle in 3D world space
+RLAPI void DrawTriangle3D(Vector3 v1, Vector3 v2, Vector3 v3, Color color); // Draw a color-filled triangle (vertex in counter-clockwise order!)
+RLAPI void DrawTriangleStrip3D(const Vector3 *points, int pointCount, Color color); // Draw a triangle strip defined by points
+RLAPI void DrawCube(Vector3 position, float width, float height, float length, Color color); // Draw cube
+RLAPI void DrawCubeV(Vector3 position, Vector3 size, Color color); // Draw cube (Vector version)
+RLAPI void DrawCubeWires(Vector3 position, float width, float height, float length, Color color); // Draw cube wires
+RLAPI void DrawCubeWiresV(Vector3 position, Vector3 size, Color color); // Draw cube wires (Vector version)
+RLAPI void DrawSphere(Vector3 centerPos, float radius, Color color); // Draw sphere
+RLAPI void DrawSphereEx(Vector3 centerPos, float radius, int rings, int slices, Color color); // Draw sphere with extended parameters
+RLAPI void DrawSphereWires(Vector3 centerPos, float radius, int rings, int slices, Color color); // Draw sphere wires
+RLAPI void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float height, int slices, Color color); // Draw a cylinder/cone
+RLAPI void DrawCylinderEx(Vector3 startPos, Vector3 endPos, float startRadius, float endRadius, int sides, Color color); // Draw a cylinder with base at startPos and top at endPos
+RLAPI void DrawCylinderWires(Vector3 position, float radiusTop, float radiusBottom, float height, int slices, Color color); // Draw a cylinder/cone wires
+RLAPI void DrawCylinderWiresEx(Vector3 startPos, Vector3 endPos, float startRadius, float endRadius, int sides, Color color); // Draw a cylinder wires with base at startPos and top at endPos
+RLAPI void DrawCapsule(Vector3 startPos, Vector3 endPos, float radius, int slices, int rings, Color color); // Draw a capsule with the center of its sphere caps at startPos and endPos
+RLAPI void DrawCapsuleWires(Vector3 startPos, Vector3 endPos, float radius, int slices, int rings, Color color); // Draw capsule wireframe with the center of its sphere caps at startPos and endPos
+RLAPI void DrawPlane(Vector3 centerPos, Vector2 size, Color color); // Draw a plane XZ
+RLAPI void DrawRay(Ray ray, Color color); // Draw a ray line
+RLAPI void DrawGrid(int slices, float spacing); // Draw a grid (centered at (0, 0, 0))
+
+//------------------------------------------------------------------------------------
+// Model 3d Loading and Drawing Functions (Module: models)
+//------------------------------------------------------------------------------------
+
+// Model management functions
+RLAPI Model LoadModel(const char *fileName); // Load model from files (meshes and materials)
+RLAPI Model LoadModelFromMesh(Mesh mesh); // Load model from generated mesh (default material)
+RLAPI bool IsModelValid(Model model); // Check if a model is valid (loaded in GPU, VAO/VBOs)
+RLAPI void UnloadModel(Model model); // Unload model (including meshes) from memory (RAM and/or VRAM)
+RLAPI BoundingBox GetModelBoundingBox(Model model); // Compute model bounding box limits (considers all meshes)
+
+// Model drawing functions
+RLAPI void DrawModel(Model model, Vector3 position, float scale, Color tint); // Draw a model (with texture if set)
+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
+RLAPI void DrawBillboardPro(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector3 up, Vector2 size, Vector2 origin, float rotation, Color tint); // Draw a billboard texture defined by source and rotation
+
+// Mesh management functions
+RLAPI void UploadMesh(Mesh *mesh, bool dynamic); // Upload mesh vertex data in GPU and provide VAO/VBO ids
+RLAPI void UpdateMeshBuffer(Mesh mesh, int index, const void *data, int dataSize, int offset); // Update mesh vertex data in GPU for a specific buffer index
+RLAPI void UnloadMesh(Mesh mesh); // Unload mesh data from CPU and GPU
+RLAPI void DrawMesh(Mesh mesh, Material material, Matrix transform); // Draw a 3d mesh with material and transform
+RLAPI void DrawMeshInstanced(Mesh mesh, Material material, const Matrix *transforms, int instances); // Draw multiple mesh instances with material and different transforms
+RLAPI BoundingBox GetMeshBoundingBox(Mesh mesh); // Compute mesh bounding box limits
+RLAPI void GenMeshTangents(Mesh *mesh); // Compute mesh tangents
+RLAPI bool ExportMesh(Mesh mesh, const char *fileName); // Export mesh data to file, returns true on success
+RLAPI bool ExportMeshAsCode(Mesh mesh, const char *fileName); // Export mesh as code file (.h) defining multiple arrays of vertex attributes
+
+// Mesh generation functions
+RLAPI Mesh GenMeshPoly(int sides, float radius); // Generate polygonal mesh
+RLAPI Mesh GenMeshPlane(float width, float length, int resX, int resZ); // Generate plane mesh (with subdivisions)
+RLAPI Mesh GenMeshCube(float width, float height, float length); // Generate cuboid mesh
+RLAPI Mesh GenMeshSphere(float radius, int rings, int slices); // Generate sphere mesh (standard sphere)
+RLAPI Mesh GenMeshHemiSphere(float radius, int rings, int slices); // Generate half-sphere mesh (no bottom cap)
+RLAPI Mesh GenMeshCylinder(float radius, float height, int slices); // Generate cylinder mesh
+RLAPI Mesh GenMeshCone(float radius, float height, int slices); // Generate cone/pyramid mesh
+RLAPI Mesh GenMeshTorus(float radius, float size, int radSeg, int sides); // Generate torus mesh
+RLAPI Mesh GenMeshKnot(float radius, float size, int radSeg, int sides); // Generate trefoil knot mesh
+RLAPI Mesh GenMeshHeightmap(Image heightmap, Vector3 size); // Generate heightmap mesh from image data
+RLAPI Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize); // Generate cubes-based map mesh from image data
+
+// Material loading/unloading functions
+RLAPI Material *LoadMaterials(const char *fileName, int *materialCount); // Load materials from model file
+RLAPI Material LoadMaterialDefault(void); // Load default material (Supports: DIFFUSE, SPECULAR, NORMAL maps)
+RLAPI bool IsMaterialValid(Material material); // Check if a material is valid (shader assigned, map textures loaded in GPU)
+RLAPI void UnloadMaterial(Material material); // Unload material from GPU memory (VRAM)
+RLAPI void SetMaterialTexture(Material *material, int mapType, Texture2D texture); // Set texture for a material map type (MATERIAL_MAP_DIFFUSE, MATERIAL_MAP_SPECULAR...)
+RLAPI void SetModelMeshMaterial(Model *model, int meshId, int materialId); // Set material for a mesh
+
+// Model animations loading/unloading functions
+RLAPI ModelAnimation *LoadModelAnimations(const char *fileName, int *animCount); // Load model animations from file
+RLAPI void UpdateModelAnimation(Model model, ModelAnimation anim, int frame); // Update model animation pose (CPU)
+RLAPI void UpdateModelAnimationBones(Model model, ModelAnimation anim, int frame); // Update model animation mesh bone matrices (GPU skinning)
+RLAPI void UnloadModelAnimation(ModelAnimation anim); // Unload animation data
+RLAPI void UnloadModelAnimations(ModelAnimation *animations, int animCount); // Unload animation array data
+RLAPI bool IsModelAnimationValid(Model model, ModelAnimation anim); // Check model animation skeleton match
+
+// Collision detection functions
+RLAPI bool CheckCollisionSpheres(Vector3 center1, float radius1, Vector3 center2, float radius2); // Check collision between two spheres
+RLAPI bool CheckCollisionBoxes(BoundingBox box1, BoundingBox box2); // Check collision between two bounding boxes
+RLAPI bool CheckCollisionBoxSphere(BoundingBox box, Vector3 center, float radius); // Check collision between box and sphere
+RLAPI RayCollision GetRayCollisionSphere(Ray ray, Vector3 center, float radius); // Get collision info between ray and sphere
+RLAPI RayCollision GetRayCollisionBox(Ray ray, BoundingBox box); // Get collision info between ray and box
+RLAPI RayCollision GetRayCollisionMesh(Ray ray, Mesh mesh, Matrix transform); // Get collision info between ray and mesh
+RLAPI RayCollision GetRayCollisionTriangle(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3); // Get collision info between ray and triangle
+RLAPI RayCollision GetRayCollisionQuad(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3, Vector3 p4); // Get collision info between ray and quad
+
+//------------------------------------------------------------------------------------
+// Audio Loading and Playing Functions (Module: audio)
+//------------------------------------------------------------------------------------
+typedef void (*AudioCallback)(void *bufferData, unsigned int frames);
+
+// Audio device management functions
+RLAPI void InitAudioDevice(void); // Initialize audio device and context
+RLAPI void CloseAudioDevice(void); // Close the audio device and context
+RLAPI bool IsAudioDeviceReady(void); // Check if audio device has been initialized successfully
+RLAPI void SetMasterVolume(float volume); // Set master volume (listener)
+RLAPI float GetMasterVolume(void); // Get master volume (listener)
+
+// Wave/Sound loading/unloading functions
+RLAPI Wave LoadWave(const char *fileName); // Load wave data from file
+RLAPI Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int dataSize); // Load wave from memory buffer, fileType refers to extension: i.e. '.wav'
+RLAPI bool IsWaveValid(Wave wave); // Checks if wave data is valid (data loaded and parameters)
+RLAPI Sound LoadSound(const char *fileName); // Load sound from file
+RLAPI Sound LoadSoundFromWave(Wave wave); // Load sound from wave data
+RLAPI Sound LoadSoundAlias(Sound source); // Create a new sound that shares the same sample data as the source sound, does not own the sound data
+RLAPI bool IsSoundValid(Sound sound); // Checks if a sound is valid (data loaded and buffers initialized)
+RLAPI void UpdateSound(Sound sound, const void *data, int sampleCount); // Update sound buffer with new data (default data format: 32 bit float, stereo)
+RLAPI void UnloadWave(Wave wave); // Unload wave data
+RLAPI void UnloadSound(Sound sound); // Unload sound
+RLAPI void UnloadSoundAlias(Sound alias); // Unload a sound alias (does not deallocate sample data)
+RLAPI bool ExportWave(Wave wave, const char *fileName); // Export wave data to file, returns true on success
+RLAPI bool ExportWaveAsCode(Wave wave, const char *fileName); // Export wave sample data to code (.h), returns true on success
+
+// Wave/Sound management functions
+RLAPI void PlaySound(Sound sound); // Play a sound
+RLAPI void StopSound(Sound sound); // Stop playing a sound
+RLAPI void PauseSound(Sound sound); // Pause a sound
+RLAPI void ResumeSound(Sound sound); // Resume a paused sound
+RLAPI bool IsSoundPlaying(Sound sound); // Check if a sound is currently playing
+RLAPI void SetSoundVolume(Sound sound, float volume); // Set volume for a sound (1.0 is max level)
+RLAPI void SetSoundPitch(Sound sound, float pitch); // Set pitch for a sound (1.0 is base level)
+RLAPI void SetSoundPan(Sound sound, float pan); // Set pan for a sound (-1.0 left, 0.0 center, 1.0 right)
+RLAPI Wave WaveCopy(Wave wave); // Copy a wave to a new wave
+RLAPI void WaveCrop(Wave *wave, int initFrame, int finalFrame); // Crop a wave to defined frames range
+RLAPI void WaveFormat(Wave *wave, int sampleRate, int sampleSize, int channels); // Convert wave data to desired format
+RLAPI float *LoadWaveSamples(Wave wave); // Load samples data from wave as a 32bit float data array
+RLAPI void UnloadWaveSamples(float *samples); // Unload samples data loaded with LoadWaveSamples()
+
+// Music management functions
+RLAPI Music LoadMusicStream(const char *fileName); // Load music stream from file
+RLAPI Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data, int dataSize); // Load music stream from data
+RLAPI bool IsMusicValid(Music music); // Checks if a music stream is valid (context and buffers initialized)
+RLAPI void UnloadMusicStream(Music music); // Unload music stream
+RLAPI void PlayMusicStream(Music music); // Start music playing
+RLAPI bool IsMusicStreamPlaying(Music music); // Check if music is playing
+RLAPI void UpdateMusicStream(Music music); // Updates buffers for music streaming
+RLAPI void StopMusicStream(Music music); // Stop music playing
+RLAPI void PauseMusicStream(Music music); // Pause music playing
+RLAPI void ResumeMusicStream(Music music); // Resume playing paused music
+RLAPI void SeekMusicStream(Music music, float position); // Seek music to a position (in seconds)
+RLAPI void SetMusicVolume(Music music, float volume); // Set volume for music (1.0 is max level)
+RLAPI void SetMusicPitch(Music music, float pitch); // Set pitch for a music (1.0 is base level)
+RLAPI void SetMusicPan(Music music, float pan); // Set pan for a music (-1.0 left, 0.0 center, 1.0 right)
+RLAPI float GetMusicTimeLength(Music music); // Get music time length (in seconds)
+RLAPI float GetMusicTimePlayed(Music music); // Get current music time played (in seconds)
+
+// AudioStream management functions
+RLAPI AudioStream LoadAudioStream(unsigned int sampleRate, unsigned int sampleSize, unsigned int channels); // Load audio stream (to stream raw audio pcm data)
+RLAPI bool IsAudioStreamValid(AudioStream stream); // Checks if an audio stream is valid (buffers initialized)
+RLAPI void UnloadAudioStream(AudioStream stream); // Unload audio stream and free memory
+RLAPI void UpdateAudioStream(AudioStream stream, const void *data, int frameCount); // Update audio stream buffers with data
+RLAPI bool IsAudioStreamProcessed(AudioStream stream); // Check if any audio stream buffers requires refill
+RLAPI void PlayAudioStream(AudioStream stream); // Play audio stream
+RLAPI void PauseAudioStream(AudioStream stream); // Pause audio stream
+RLAPI void ResumeAudioStream(AudioStream stream); // Resume audio stream
+RLAPI bool IsAudioStreamPlaying(AudioStream stream); // Check if audio stream is playing
+RLAPI void StopAudioStream(AudioStream stream); // Stop audio stream
+RLAPI void SetAudioStreamVolume(AudioStream stream, float volume); // Set volume for audio stream (1.0 is max level)
+RLAPI void SetAudioStreamPitch(AudioStream stream, float pitch); // Set pitch for audio stream (1.0 is base level)
+RLAPI void SetAudioStreamPan(AudioStream stream, float pan); // Set pan for audio stream (0.5 is centered)
+RLAPI void SetAudioStreamBufferSizeDefault(int size); // Default size for new audio streams
+RLAPI void SetAudioStreamCallback(AudioStream stream, AudioCallback callback); // Audio thread callback to request new data
+
+RLAPI void AttachAudioStreamProcessor(AudioStream stream, AudioCallback processor); // Attach audio stream processor to stream, receives frames x 2 samples as 'float' (stereo)
+RLAPI void DetachAudioStreamProcessor(AudioStream stream, AudioCallback processor); // Detach audio stream processor from stream
+
+RLAPI void AttachAudioMixedProcessor(AudioCallback processor); // Attach audio stream processor to the entire audio pipeline, receives frames x 2 samples as 'float' (stereo)
+RLAPI void DetachAudioMixedProcessor(AudioCallback processor); // Detach audio stream processor from the entire audio pipeline
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif // RAYLIB_H
diff --git a/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/LICENSE b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/LICENSE
new file mode 100644
index 0000000..2329060
--- /dev/null
+++ b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/LICENSE
@@ -0,0 +1,17 @@
+ Copyright (C) 2016 Milan Nikolic (gen2brain)
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
diff --git a/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo.go b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo.go
new file mode 100644
index 0000000..88562e0
--- /dev/null
+++ b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo.go
@@ -0,0 +1,6 @@
+package rl
+
+/*
+#cgo CFLAGS: -std=gnu99 -Wno-missing-braces -Wno-unused-result -Wno-implicit-function-declaration -Wno-int-to-pointer-cast
+*/
+import "C"
diff --git a/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo_android.go b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo_android.go
new file mode 100644
index 0000000..11714e9
--- /dev/null
+++ b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo_android.go
@@ -0,0 +1,14 @@
+//go:build android
+// +build android
+
+package rl
+
+/*
+#include "external/android/native_app_glue/android_native_app_glue.c"
+
+#cgo android LDFLAGS: -llog -landroid -lEGL -lGLESv2 -lOpenSLES -lm
+#cgo android CFLAGS: -DPLATFORM_ANDROID -DGRAPHICS_API_OPENGL_ES2 -Iexternal/android/native_app_glue -Wno-implicit-const-int-float-conversion
+
+#cgo android,arm CFLAGS: -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16
+*/
+import "C"
diff --git a/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo_darwin.go b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo_darwin.go
new file mode 100644
index 0000000..575fb88
--- /dev/null
+++ b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo_darwin.go
@@ -0,0 +1,42 @@
+//go:build darwin && !rgfw && !sdl && !sdl3
+// +build darwin,!rgfw,!sdl,!sdl3
+
+package rl
+
+/*
+#include "external/glfw/src/context.c"
+#include "external/glfw/src/init.c"
+#include "external/glfw/src/input.c"
+#include "external/glfw/src/monitor.c"
+#include "external/glfw/src/platform.c"
+#include "external/glfw/src/vulkan.c"
+#include "external/glfw/src/window.c"
+
+#include "external/glfw/src/cocoa_init.m"
+#include "external/glfw/src/cocoa_joystick.m"
+#include "external/glfw/src/cocoa_monitor.m"
+#include "external/glfw/src/cocoa_time.c"
+#include "external/glfw/src/cocoa_window.m"
+#include "external/glfw/src/posix_module.c"
+#include "external/glfw/src/posix_thread.c"
+#include "external/glfw/src/nsgl_context.m"
+#include "external/glfw/src/egl_context.c"
+#include "external/glfw/src/osmesa_context.c"
+
+GLFWbool _glfwConnectNull(int platformID, _GLFWplatform* platform) {
+ return GLFW_TRUE;
+}
+
+#cgo darwin LDFLAGS: -framework Cocoa -framework IOKit -framework CoreVideo -framework CoreFoundation
+#cgo darwin CFLAGS: -x objective-c -Iexternal/glfw/include -D_GLFW_COCOA -D_GLFW_USE_CHDIR -D_GLFW_USE_MENUBAR -D_GLFW_USE_RETINA -Wno-deprecated-declarations -Wno-implicit-const-int-float-conversion -DPLATFORM_DESKTOP
+
+#cgo darwin,!es2,!es3 LDFLAGS: -framework OpenGL
+
+#cgo darwin,opengl11,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_11
+#cgo darwin,opengl21,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_21
+#cgo darwin,opengl43,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_43
+#cgo darwin,!opengl11,!opengl21,!opengl43,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_33
+#cgo darwin,es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_ES2
+#cgo darwin,es3,!es2 CFLAGS: -DGRAPHICS_API_OPENGL_ES3
+*/
+import "C"
diff --git a/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo_darwin_rgfw.go b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo_darwin_rgfw.go
new file mode 100644
index 0000000..3006c24
--- /dev/null
+++ b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo_darwin_rgfw.go
@@ -0,0 +1,20 @@
+//go:build darwin && rgfw && !sdl && !sdl3
+// +build darwin,rgfw,!sdl,!sdl3
+
+package rl
+
+/*
+#cgo darwin LDFLAGS: -framework Foundation -framework AppKit -framework CoreVideo
+#cgo darwin CFLAGS: -DPLATFORM_DESKTOP_RGFW -Wno-deprecated-declarations -Wno-implicit-const-int-float-conversion -Wno-typedef-redefinition -Wno-extern-initializer -Wno-unused-value
+#cgo darwin CFLAGS: -Wno-incompatible-pointer-types -Wno-incompatible-function-pointer-types -Wno-incompatible-pointer-types-discards-qualifiers -Wno-macro-redefined
+
+#cgo darwin,!es2,!es3 LDFLAGS: -framework OpenGL
+
+#cgo darwin,opengl11,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_11
+#cgo darwin,opengl21,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_21
+#cgo darwin,opengl43,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_43
+#cgo darwin,!opengl11,!opengl21,!opengl43,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_33
+#cgo darwin,es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_ES2
+#cgo darwin,es3,!es2 CFLAGS: -DGRAPHICS_API_OPENGL_ES3
+*/
+import "C"
diff --git a/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo_darwin_sdl.go b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo_darwin_sdl.go
new file mode 100644
index 0000000..a5d3a08
--- /dev/null
+++ b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo_darwin_sdl.go
@@ -0,0 +1,25 @@
+//go:build darwin && (sdl || sdl3) && !rgfw
+// +build darwin
+// +build sdl sdl3
+// +build !rgfw
+
+package rl
+
+/*
+#cgo darwin LDFLAGS: -framework Cocoa -framework IOKit -framework CoreVideo -framework CoreFoundation
+#cgo darwin CFLAGS: -Wno-deprecated-declarations -Wno-implicit-const-int-float-conversion
+#cgo darwin,sdl CFLAGS: -DPLATFORM_DESKTOP_SDL
+#cgo darwin,sdl3 CFLAGS: -DPLATFORM_DESKTOP_SDL -DPLATFORM_DESKTOP_SDL3
+#cgo darwin,sdl pkg-config: sdl2
+#cgo darwin,sdl3 pkg-config: sdl3
+
+#cgo darwin,!es2,!es3 LDFLAGS: -framework OpenGL
+
+#cgo darwin,opengl11,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_11
+#cgo darwin,opengl21,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_21
+#cgo darwin,opengl43,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_43
+#cgo darwin,!opengl11,!opengl21,!opengl43,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_33
+#cgo darwin,es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_ES2
+#cgo darwin,es3,!es2 CFLAGS: -DGRAPHICS_API_OPENGL_ES3
+*/
+import "C"
diff --git a/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo_freebsd.go b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo_freebsd.go
new file mode 100644
index 0000000..c29c731
--- /dev/null
+++ b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo_freebsd.go
@@ -0,0 +1,45 @@
+//go:build freebsd && !linux && !rgfw && !drm && !sdl && !sdl3 && !android
+// +build freebsd,!linux,!rgfw,!drm,!sdl,!sdl3,!android
+
+package rl
+
+/*
+#include "external/glfw/src/context.c"
+#include "external/glfw/src/init.c"
+#include "external/glfw/src/input.c"
+#include "external/glfw/src/monitor.c"
+#include "external/glfw/src/platform.c"
+#include "external/glfw/src/vulkan.c"
+#include "external/glfw/src/window.c"
+
+#include "external/glfw/src/x11_init.c"
+#include "external/glfw/src/x11_monitor.c"
+#include "external/glfw/src/x11_window.c"
+#include "external/glfw/src/glx_context.c"
+
+#include "external/glfw/src/null_joystick.c"
+#include "external/glfw/src/posix_module.c"
+#include "external/glfw/src/posix_poll.c"
+#include "external/glfw/src/posix_thread.c"
+#include "external/glfw/src/posix_time.c"
+#include "external/glfw/src/xkb_unicode.c"
+#include "external/glfw/src/egl_context.c"
+#include "external/glfw/src/osmesa_context.c"
+
+GLFWbool _glfwConnectNull(int platformID, _GLFWplatform* platform) {
+ return GLFW_TRUE;
+}
+
+#cgo freebsd CFLAGS: -I. -I/usr/local/include -Iexternal/glfw/include -DPLATFORM_DESKTOP -D_GLFW_X11
+#cgo freebsd LDFLAGS: -L/usr/local/lib -lm -pthread -ldl -lrt -lX11
+
+#cgo freebsd,!es2,!es3 LDFLAGS: -lGL
+
+#cgo freebsd,opengl11,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_11
+#cgo freebsd,opengl21,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_21
+#cgo freebsd,opengl43,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_43
+#cgo freebsd,!opengl11,!opengl21,!opengl43,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_33
+#cgo freebsd,es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_ES2
+#cgo freebsd,es3,!es2 CFLAGS: -DGRAPHICS_API_OPENGL_ES3
+*/
+import "C"
diff --git a/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo_freebsd_rgfw.go b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo_freebsd_rgfw.go
new file mode 100644
index 0000000..6df34b8
--- /dev/null
+++ b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo_freebsd_rgfw.go
@@ -0,0 +1,19 @@
+//go:build freebsd && rgfw && !linux && !drm && !sdl && !sdl3 && !android
+// +build freebsd,rgfw,!linux,!drm,!sdl,!sdl3,!android
+
+package rl
+
+/*
+#cgo freebsd CFLAGS: -I. -I/usr/local/include -DPLATFORM_DESKTOP_RGFW
+#cgo freebsd LDFLAGS: -L/usr/local/lib -lX11 -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor -lm -lpthread -ldl -lrt
+
+#cgo freebsd,!es2,!es3 LDFLAGS: -lGL
+
+#cgo freebsd,opengl11,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_11
+#cgo freebsd,opengl21,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_21
+#cgo freebsd,opengl43,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_43
+#cgo freebsd,!opengl11,!opengl21,!opengl43,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_33
+#cgo freebsd,es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_ES2
+#cgo freebsd,es3,!es2 CFLAGS: -DGRAPHICS_API_OPENGL_ES3
+*/
+import "C"
diff --git a/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo_freebsd_sdl.go b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo_freebsd_sdl.go
new file mode 100644
index 0000000..cc56b7e
--- /dev/null
+++ b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo_freebsd_sdl.go
@@ -0,0 +1,29 @@
+//go:build freebsd && !linux && (sdl || sdl3) && !rgfw && !drm && !android
+// +build freebsd
+// +build !linux
+// +build sdl sdl3
+// +build !rgfw
+// +build !drm
+// +build !android
+
+package rl
+
+/*
+#cgo freebsd CFLAGS: -I. -I/usr/local/include
+#cgo freebsd,sdl CFLAGS: -DPLATFORM_DESKTOP_SDL
+#cgo freebsd,sdl3 CFLAGS: -DPLATFORM_DESKTOP_SDL -DPLATFORM_DESKTOP_SDL3
+#cgo freebsd LDFLAGS: -L/usr/local/lib
+
+#cgo freebsd,sdl pkg-config: sdl2
+#cgo freebsd,sdl3 pkg-config: sdl3
+
+#cgo freebsd,!es2,!es3 LDFLAGS: -lGL
+
+#cgo freebsd,opengl11,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_11
+#cgo freebsd,opengl21,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_21
+#cgo freebsd,opengl43,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_43
+#cgo freebsd,!opengl11,!opengl21,!opengl43,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_33
+#cgo freebsd,es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_ES2
+#cgo freebsd,es3,!es2 CFLAGS: -DGRAPHICS_API_OPENGL_ES3
+*/
+import "C"
diff --git a/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo_linux.go b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo_linux.go
new file mode 100644
index 0000000..453d563
--- /dev/null
+++ b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo_linux.go
@@ -0,0 +1,58 @@
+//go:build linux && !rgfw && !drm && !sdl && !sdl3 && !android
+// +build linux,!rgfw,!drm,!sdl,!sdl3,!android
+
+package rl
+
+/*
+#include "external/glfw/src/context.c"
+#include "external/glfw/src/init.c"
+#include "external/glfw/src/input.c"
+#include "external/glfw/src/monitor.c"
+#include "external/glfw/src/platform.c"
+#include "external/glfw/src/vulkan.c"
+#include "external/glfw/src/window.c"
+
+#if defined _GLFW_WAYLAND
+#include "external/glfw/src/wl_init.c"
+#include "external/glfw/src/wl_monitor.c"
+#include "external/glfw/src/wl_window.c"
+#endif
+
+#if defined _GLFW_X11
+#include "external/glfw/src/x11_init.c"
+#include "external/glfw/src/x11_monitor.c"
+#include "external/glfw/src/x11_window.c"
+#include "external/glfw/src/glx_context.c"
+#endif
+
+#include "external/glfw/src/linux_joystick.c"
+#include "external/glfw/src/posix_module.c"
+#include "external/glfw/src/posix_poll.c"
+#include "external/glfw/src/posix_thread.c"
+#include "external/glfw/src/posix_time.c"
+#include "external/glfw/src/xkb_unicode.c"
+#include "external/glfw/src/egl_context.c"
+#include "external/glfw/src/osmesa_context.c"
+
+GLFWbool _glfwConnectNull(int platformID, _GLFWplatform* platform) {
+ return GLFW_TRUE;
+}
+
+#cgo linux CFLAGS: -Iexternal/glfw/include -DPLATFORM_DESKTOP -Wno-stringop-overflow
+#cgo linux LDFLAGS: -lm -pthread -ldl -lrt -lxkbcommon
+#cgo linux,!x11 LDFLAGS: -lwayland-client -lwayland-cursor -lwayland-egl
+
+#cgo linux,x11 CFLAGS: -D_GLFW_X11
+#cgo linux,wayland CFLAGS: -D_GLFW_WAYLAND
+#cgo linux,!x11,!wayland CFLAGS: -D_GLFW_X11 -D_GLFW_WAYLAND
+
+#cgo linux,!es2,!es3,!wayland LDFLAGS: -lGL
+
+#cgo linux,opengl11,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_11
+#cgo linux,opengl21,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_21
+#cgo linux,opengl43,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_43
+#cgo linux,!opengl11,!opengl21,!opengl43,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_33
+#cgo linux,es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_ES2
+#cgo linux,es3,!es2 CFLAGS: -DGRAPHICS_API_OPENGL_ES3
+*/
+import "C"
diff --git a/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo_linux_drm.go b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo_linux_drm.go
new file mode 100644
index 0000000..c50ce91
--- /dev/null
+++ b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo_linux_drm.go
@@ -0,0 +1,10 @@
+//go:build linux && drm && !rgfw && !sdl && !sdl3 && !android
+// +build linux,drm,!rgfw,!sdl,!sdl3,!android
+
+package rl
+
+/*
+#cgo linux,drm LDFLAGS: -lGLESv2 -lEGL -ldrm -lgbm -lpthread -lrt -lm -ldl
+#cgo linux,drm CFLAGS: -DPLATFORM_DRM -DGRAPHICS_API_OPENGL_ES2 -DEGL_NO_X11 -I/usr/include/libdrm
+*/
+import "C"
diff --git a/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo_linux_rgfw.go b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo_linux_rgfw.go
new file mode 100644
index 0000000..7585836
--- /dev/null
+++ b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo_linux_rgfw.go
@@ -0,0 +1,20 @@
+//go:build linux && rgfw && !drm && !sdl && !sdl3 && !android
+// +build linux,rgfw,!drm,!sdl,!sdl3,!android
+
+package rl
+
+/*
+#cgo linux,!es2 LDFLAGS: -lm
+#cgo linux CFLAGS: -DPLATFORM_DESKTOP_RGFW -Wno-builtin-declaration-mismatch -Wno-discarded-qualifiers -Wno-int-conversion
+#cgo linux LDFLAGS: -lX11 -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor -lm -lpthread -ldl -lrt
+
+#cgo linux,!es2,!es3 LDFLAGS: -lGL
+
+#cgo linux,opengl11,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_11
+#cgo linux,opengl21,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_21
+#cgo linux,opengl43,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_43
+#cgo linux,!opengl11,!opengl21,!opengl43,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_33
+#cgo linux,es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_ES2
+#cgo linux,es3,!es2 CFLAGS: -DGRAPHICS_API_OPENGL_ES3
+*/
+import "C"
diff --git a/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo_linux_sdl.go b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo_linux_sdl.go
new file mode 100644
index 0000000..cde87da
--- /dev/null
+++ b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo_linux_sdl.go
@@ -0,0 +1,27 @@
+//go:build linux && (sdl || sdl3) && !rgfw && !drm && !android
+// +build linux
+// +build sdl sdl3
+// +build !rgfw
+// +build !drm
+// +build !android
+
+package rl
+
+/*
+#cgo linux,!es2 LDFLAGS: -lm
+#cgo linux CFLAGS: -Wno-stringop-overflow
+#cgo linux,sdl CFLAGS: -DPLATFORM_DESKTOP_SDL
+#cgo linux,sdl3 CFLAGS: -DPLATFORM_DESKTOP_SDL -DPLATFORM_DESKTOP_SDL3
+#cgo linux,sdl pkg-config: sdl2
+#cgo linux,sdl3 pkg-config: sdl3
+
+#cgo linux,!es2,!es3 LDFLAGS: -lGL
+
+#cgo linux,opengl11,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_11
+#cgo linux,opengl21,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_21
+#cgo linux,opengl43,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_43
+#cgo linux,!opengl11,!opengl21,!opengl43,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_33
+#cgo linux,es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_ES2
+#cgo linux,es3,!es2 CFLAGS: -DGRAPHICS_API_OPENGL_ES3
+*/
+import "C"
diff --git a/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo_openbsd.go b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo_openbsd.go
new file mode 100644
index 0000000..a40ee1c
--- /dev/null
+++ b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo_openbsd.go
@@ -0,0 +1,45 @@
+//go:build openbsd && !linux && !rgfw && !drm && !sdl && !sdl3 && !android
+// +build openbsd,!linux,!rgfw,!drm,!sdl,!sdl3,!android
+
+package rl
+
+/*
+#include "external/glfw/src/context.c"
+#include "external/glfw/src/init.c"
+#include "external/glfw/src/input.c"
+#include "external/glfw/src/monitor.c"
+#include "external/glfw/src/platform.c"
+#include "external/glfw/src/vulkan.c"
+#include "external/glfw/src/window.c"
+
+#include "external/glfw/src/x11_init.c"
+#include "external/glfw/src/x11_monitor.c"
+#include "external/glfw/src/x11_window.c"
+#include "external/glfw/src/glx_context.c"
+
+#include "external/glfw/src/null_joystick.c"
+#include "external/glfw/src/posix_module.c"
+#include "external/glfw/src/posix_poll.c"
+#include "external/glfw/src/posix_thread.c"
+#include "external/glfw/src/posix_time.c"
+#include "external/glfw/src/xkb_unicode.c"
+#include "external/glfw/src/egl_context.c"
+#include "external/glfw/src/osmesa_context.c"
+
+GLFWbool _glfwConnectNull(int platformID, _GLFWplatform* platform) {
+ return GLFW_TRUE;
+}
+
+#cgo openbsd CFLAGS: -I. -I/usr/X11R6/include -Iexternal/glfw/include -DPLATFORM_DESKTOP -D_GLFW_X11
+#cgo openbsd LDFLAGS: -L/usr/X11R6/lib -lm -pthread -lX11
+
+#cgo openbsd,!es2,!es3 LDFLAGS: -lGL
+
+#cgo openbsd,opengl11,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_11
+#cgo openbsd,opengl21,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_21
+#cgo openbsd,opengl43,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_43
+#cgo openbsd,!opengl11,!opengl21,!opengl43,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_33
+#cgo openbsd,es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_ES2
+#cgo openbsd,es3,!es2 CFLAGS: -DGRAPHICS_API_OPENGL_ES3
+*/
+import "C"
diff --git a/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo_openbsd_rgfw.go b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo_openbsd_rgfw.go
new file mode 100644
index 0000000..11441dc
--- /dev/null
+++ b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo_openbsd_rgfw.go
@@ -0,0 +1,19 @@
+//go:build openbsd && rgfw && !linux && !sdl && !sdl3 && !drm && !android
+// +build openbsd,rgfw,!linux,!sdl,!sdl3,!drm,!android
+
+package rl
+
+/*
+#cgo openbsd CFLAGS: -I. -I/usr/X11R6/include -DPLATFORM_DESKTOP_RGFW
+#cgo openbsd LDFLAGS: -L/usr/X11R6/lib -lX11 -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor -lm -lpthread -ldl -lrt
+
+#cgo openbsd,!es2,!es3 LDFLAGS: -lGL
+
+#cgo openbsd,opengl11,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_11
+#cgo openbsd,opengl21,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_21
+#cgo openbsd,opengl43,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_43
+#cgo openbsd,!opengl11,!opengl21,!opengl43,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_33
+#cgo openbsd,es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_ES2
+#cgo openbsd,es3,!es2 CFLAGS: -DGRAPHICS_API_OPENGL_ES3
+*/
+import "C"
diff --git a/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo_openbsd_sdl.go b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo_openbsd_sdl.go
new file mode 100644
index 0000000..4fe5e5a
--- /dev/null
+++ b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo_openbsd_sdl.go
@@ -0,0 +1,29 @@
+//go:build openbsd && !linux && (sdl || sdl3) && !rgfw && !drm && !android
+// +build openbsd
+// +build !linux
+// +build sdl sdl3
+// +build !rgfw
+// +build !drm
+// +build !android
+
+package rl
+
+/*
+#cgo openbsd CFLAGS: -I. -I/usr/X11R6/include
+#cgo openbsd,sdl CFLAGS: -DPLATFORM_DESKTOP_SDL
+#cgo openbsd,sdl3 CFLAGS: -DPLATFORM_DESKTOP_SDL -DPLATFORM_DESKTOP_SDL3
+#cgo openbsd LDFLAGS: -L/usr/X11R6/lib
+
+#cgo openbsd,sdl pkg-config: sdl2
+#cgo openbsd,sdl3 pkg-config: sdl3
+
+#cgo openbsd,!es2,!es3 LDFLAGS: -lGL
+
+#cgo openbsd,opengl11,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_11
+#cgo openbsd,opengl21,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_21
+#cgo openbsd,opengl43,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_43
+#cgo openbsd,!opengl11,!opengl21,!opengl43,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_33
+#cgo openbsd,es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_ES2
+#cgo openbsd,es3,!es2 CFLAGS: -DGRAPHICS_API_OPENGL_ES3
+*/
+import "C"
diff --git a/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo_vendor.go b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo_vendor.go
new file mode 100644
index 0000000..ecee6e9
--- /dev/null
+++ b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo_vendor.go
@@ -0,0 +1,12 @@
+//go:build required
+// +build required
+
+package rl
+
+import (
+ _ "github.com/gen2brain/raylib-go/raylib/external"
+ _ "github.com/gen2brain/raylib-go/raylib/external/android/native_app_glue"
+ _ "github.com/gen2brain/raylib-go/raylib/external/glfw/include/GLFW"
+ _ "github.com/gen2brain/raylib-go/raylib/external/glfw/src"
+ _ "github.com/gen2brain/raylib-go/raylib/platforms"
+)
diff --git a/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo_windows.go b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo_windows.go
new file mode 100644
index 0000000..c2cd044
--- /dev/null
+++ b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo_windows.go
@@ -0,0 +1,42 @@
+//go:build windows && !rgfw && !sdl && !sdl3
+// +build windows,!rgfw,!sdl,!sdl3
+
+package rl
+
+/*
+#include "external/glfw/src/context.c"
+#include "external/glfw/src/init.c"
+#include "external/glfw/src/input.c"
+#include "external/glfw/src/monitor.c"
+#include "external/glfw/src/platform.c"
+#include "external/glfw/src/vulkan.c"
+#include "external/glfw/src/window.c"
+
+#include "external/glfw/src/win32_init.c"
+#include "external/glfw/src/win32_joystick.c"
+#include "external/glfw/src/win32_module.c"
+#include "external/glfw/src/win32_monitor.c"
+#include "external/glfw/src/win32_thread.c"
+#include "external/glfw/src/win32_time.c"
+#include "external/glfw/src/win32_window.c"
+#include "external/glfw/src/wgl_context.c"
+#include "external/glfw/src/egl_context.c"
+#include "external/glfw/src/osmesa_context.c"
+
+GLFWbool _glfwConnectNull(int platformID, _GLFWplatform* platform) {
+ return GLFW_TRUE;
+}
+
+#cgo windows LDFLAGS: -lgdi32 -lwinmm -lole32
+#cgo windows CFLAGS: -Iexternal -Iexternal/glfw/include -DPLATFORM_DESKTOP -D_GLFW_WIN32 -Wno-stringop-overflow
+
+#cgo windows,!es2,!es3 LDFLAGS: -lopengl32
+
+#cgo windows,opengl11,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_11
+#cgo windows,opengl21,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_21
+#cgo windows,opengl43,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_43
+#cgo windows,!opengl11,!opengl21,!opengl43,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_33
+#cgo windows,es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_ES2
+#cgo windows,es3,!es2 CFLAGS: -DGRAPHICS_API_OPENGL_ES3
+*/
+import "C"
diff --git a/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo_windows_rgfw.go b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo_windows_rgfw.go
new file mode 100644
index 0000000..eea463d
--- /dev/null
+++ b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo_windows_rgfw.go
@@ -0,0 +1,19 @@
+//go:build windows && rgfw && !sdl && !sdl3
+// +build windows,rgfw,!sdl,!sdl3
+
+package rl
+
+/*
+#cgo windows LDFLAGS: -lgdi32 -lwinmm
+#cgo windows CFLAGS: -Iexternal -DPLATFORM_DESKTOP_RGFW -Wno-stringop-overflow -Wno-discarded-qualifiers
+
+#cgo windows,!es2,!es3 LDFLAGS: -lopengl32
+
+#cgo windows,opengl11,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_11
+#cgo windows,opengl21,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_21
+#cgo windows,opengl43,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_43
+#cgo windows,!opengl11,!opengl21,!opengl43,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_33
+#cgo windows,es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_ES2
+#cgo windows,es3,!es2 CFLAGS: -DGRAPHICS_API_OPENGL_ES3
+*/
+import "C"
diff --git a/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo_windows_sdl.go b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo_windows_sdl.go
new file mode 100644
index 0000000..58d53a4
--- /dev/null
+++ b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/cgo_windows_sdl.go
@@ -0,0 +1,25 @@
+//go:build windows && (sdl || sdl3) && !rgfw
+// +build windows
+// +build sdl sdl3
+// +build !rgfw
+
+package rl
+
+/*
+#cgo windows LDFLAGS: -lgdi32 -lwinmm -lole32
+#cgo windows,sdl LDFLAGS: -lSDL2
+#cgo windows,sdl3 LDFLAGS: -lSDL3
+#cgo windows CFLAGS: -Iexternal -Wno-stringop-overflow
+#cgo windows,sdl CFLAGS: -DPLATFORM_DESKTOP_SDL
+#cgo windows,sdl3 CFLAGS: -DPLATFORM_DESKTOP_SDL -DPLATFORM_DESKTOP_SDL3
+
+#cgo windows,!es2,!es3 LDFLAGS: -lopengl32
+
+#cgo windows,opengl11,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_11
+#cgo windows,opengl21,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_21
+#cgo windows,opengl43,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_43
+#cgo windows,!opengl11,!opengl21,!opengl43,!es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_33
+#cgo windows,es2,!es3 CFLAGS: -DGRAPHICS_API_OPENGL_ES2
+#cgo windows,es3,!es2 CFLAGS: -DGRAPHICS_API_OPENGL_ES3
+*/
+import "C"
diff --git a/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/compat.go b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/compat.go
new file mode 100644
index 0000000..3cd0337
--- /dev/null
+++ b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/compat.go
@@ -0,0 +1,98 @@
+//go:build go1.21
+// +build go1.21
+
+package rl
+
+/*
+#include "raylib.h"
+#include
+*/
+import "C"
+
+import (
+ "runtime"
+ "slices"
+)
+
+// List of VaoIDs of meshes created by calling UploadMesh()
+// Used by UnloadMesh() to determine if mesh is go-managed or C-allocated
+var goManagedMeshIDs = make([]uint32, 0)
+
+// UploadMesh - Upload vertex data into a VAO (if supported) and VBO
+func UploadMesh(mesh *Mesh, dynamic bool) {
+ // check if mesh has already been uploaded to prevent duplication
+ if mesh.VaoID != 0 {
+ TraceLog(LogWarning, "VAO: [ID %d] Trying to re-load an already loaded mesh", mesh.VaoID)
+ return
+ }
+
+ pinner := runtime.Pinner{}
+ // Mesh pointer fields must be pinned to allow a Mesh pointer to be passed to C.UploadMesh() below
+ // nil checks are required because Pin() will panic if passed nil
+ if mesh.Vertices != nil {
+ pinner.Pin(mesh.Vertices)
+ }
+ if mesh.Texcoords != nil {
+ pinner.Pin(mesh.Texcoords)
+ }
+ if mesh.Texcoords2 != nil {
+ pinner.Pin(mesh.Texcoords2)
+ }
+ if mesh.Normals != nil {
+ pinner.Pin(mesh.Normals)
+ }
+ if mesh.Tangents != nil {
+ pinner.Pin(mesh.Tangents)
+ }
+ if mesh.Colors != nil {
+ pinner.Pin(mesh.Colors)
+ }
+ if mesh.Indices != nil {
+ pinner.Pin(mesh.Indices)
+ }
+ if mesh.AnimVertices != nil {
+ pinner.Pin(mesh.AnimVertices)
+ }
+ if mesh.AnimNormals != nil {
+ pinner.Pin(mesh.AnimNormals)
+ }
+ if mesh.BoneIds != nil {
+ pinner.Pin(mesh.BoneIds)
+ }
+ if mesh.BoneWeights != nil {
+ pinner.Pin(mesh.BoneWeights)
+ }
+ // VboID of a new mesh should always be nil before uploading, but including this in case a mesh happens to have it set.
+ if mesh.VboID != nil {
+ pinner.Pin(mesh.VboID)
+ }
+
+ cMesh := mesh.cptr()
+ C.UploadMesh(cMesh, C.bool(dynamic))
+
+ // Add new mesh VaoID to list
+ goManagedMeshIDs = append(goManagedMeshIDs, mesh.VaoID)
+
+ pinner.Unpin()
+}
+
+// UnloadMesh - Unload mesh from memory (RAM and/or VRAM)
+func UnloadMesh(mesh *Mesh) {
+ // Check list of go-managed mesh IDs
+ if slices.Contains(goManagedMeshIDs, mesh.VaoID) {
+ // C.UnloadMesh() only needs to read the VaoID & VboID
+ // passing a temporary struct with all other fields nil makes it safe for the C code to call free()
+ tempMesh := Mesh{
+ VaoID: mesh.VaoID,
+ VboID: mesh.VboID,
+ }
+ cmesh := tempMesh.cptr()
+ C.UnloadMesh(*cmesh)
+
+ // remove mesh VaoID from list
+ goManagedMeshIDs = slices.DeleteFunc(goManagedMeshIDs, func(id uint32) bool { return id == mesh.VaoID })
+ } else {
+ cmesh := mesh.cptr()
+ C.UnloadMesh(*cmesh)
+ }
+}
diff --git a/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/compat_compat.go b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/compat_compat.go
new file mode 100644
index 0000000..1c362fb
--- /dev/null
+++ b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/compat_compat.go
@@ -0,0 +1,69 @@
+//go:build !go1.21
+// +build !go1.21
+
+package rl
+
+/*
+#include "raylib.h"
+#include
+*/
+import "C"
+
+import (
+ "runtime"
+
+ "golang.org/x/exp/slices"
+)
+
+// List of VaoIDs of meshes created by calling UploadMesh()
+// Used by UnloadMesh() to determine if mesh is go-managed or C-allocated
+var goManagedMeshIDs = make([]uint32, 0)
+
+// UploadMesh - Upload vertex data into a VAO (if supported) and VBO
+func UploadMesh(mesh *Mesh, dynamic bool) {
+ // check if mesh has already been uploaded to prevent duplication
+ if mesh.VaoID != 0 {
+ TraceLog(LogWarning, "VAO: [ID %d] Trying to re-load an already loaded mesh", mesh.VaoID)
+ return
+ }
+
+ defer runtime.KeepAlive(mesh.Vertices)
+ defer runtime.KeepAlive(mesh.Texcoords)
+ defer runtime.KeepAlive(mesh.Texcoords2)
+ defer runtime.KeepAlive(mesh.Normals)
+ defer runtime.KeepAlive(mesh.Tangents)
+ defer runtime.KeepAlive(mesh.Colors)
+ defer runtime.KeepAlive(mesh.Indices)
+ defer runtime.KeepAlive(mesh.AnimVertices)
+ defer runtime.KeepAlive(mesh.AnimNormals)
+ defer runtime.KeepAlive(mesh.BoneIds)
+ defer runtime.KeepAlive(mesh.BoneWeights)
+ defer runtime.KeepAlive(mesh.VboID)
+
+ cMesh := mesh.cptr()
+ C.UploadMesh(cMesh, C.bool(dynamic))
+
+ // Add new mesh VaoID to list
+ goManagedMeshIDs = append(goManagedMeshIDs, mesh.VaoID)
+}
+
+// UnloadMesh - Unload mesh from memory (RAM and/or VRAM)
+func UnloadMesh(mesh *Mesh) {
+ // Check list of go-managed mesh IDs
+ if slices.Contains(goManagedMeshIDs, mesh.VaoID) {
+ // C.UnloadMesh() only needs to read the VaoID & VboID
+ // passing a temporary struct with all other fields nil makes it safe for the C code to call free()
+ tempMesh := Mesh{
+ VaoID: mesh.VaoID,
+ VboID: mesh.VboID,
+ }
+ cmesh := tempMesh.cptr()
+ C.UnloadMesh(*cmesh)
+
+ // remove mesh VaoID from list
+ goManagedMeshIDs = slices.DeleteFunc(goManagedMeshIDs, func(id uint32) bool { return id == mesh.VaoID })
+ } else {
+ cmesh := mesh.cptr()
+ C.UnloadMesh(*cmesh)
+ }
+}
diff --git a/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/config.h b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/config.h
new file mode 100644
index 0000000..d682e46
--- /dev/null
+++ b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/config.h
@@ -0,0 +1,303 @@
+/**********************************************************************************************
+*
+* raylib configuration flags
+*
+* This file defines all the configuration flags for the different raylib modules
+*
+* LICENSE: zlib/libpng
+*
+* Copyright (c) 2018-2024 Ahmad Fatoum & Ramon Santamaria (@raysan5)
+*
+* This software is provided "as-is", without any express or implied warranty. In no event
+* will the authors be held liable for any damages arising from the use of this software.
+*
+* Permission is granted to anyone to use this software for any purpose, including commercial
+* applications, and to alter it and redistribute it freely, subject to the following restrictions:
+*
+* 1. The origin of this software must not be misrepresented; you must not claim that you
+* wrote the original software. If you use this software in a product, an acknowledgment
+* in the product documentation would be appreciated but is not required.
+*
+* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
+* as being the original software.
+*
+* 3. This notice may not be removed or altered from any source distribution.
+*
+**********************************************************************************************/
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+//------------------------------------------------------------------------------------
+// Module selection - Some modules could be avoided
+// Mandatory modules: rcore, rlgl, utils
+//------------------------------------------------------------------------------------
+#define SUPPORT_MODULE_RSHAPES 1
+#define SUPPORT_MODULE_RTEXTURES 1
+#define SUPPORT_MODULE_RTEXT 1 // WARNING: It requires SUPPORT_MODULE_RTEXTURES to load sprite font textures
+#define SUPPORT_MODULE_RMODELS 1
+#define SUPPORT_MODULE_RAUDIO 1
+
+//------------------------------------------------------------------------------------
+// Module: rcore - Configuration Flags
+//------------------------------------------------------------------------------------
+// Camera module is included (rcamera.h) and multiple predefined cameras are available: free, 1st/3rd person, orbital
+#define SUPPORT_CAMERA_SYSTEM 1
+// Gestures module is included (rgestures.h) to support gestures detection: tap, hold, swipe, drag
+#define SUPPORT_GESTURES_SYSTEM 1
+// Include pseudo-random numbers generator (rprand.h), based on Xoshiro128** and SplitMix64
+#define SUPPORT_RPRAND_GENERATOR 1
+// Mouse gestures are directly mapped like touches and processed by gestures system
+#define SUPPORT_MOUSE_GESTURES 1
+// Reconfigure standard input to receive key inputs, works with SSH connection.
+#define SUPPORT_SSH_KEYBOARD_RPI 1
+// Setting a higher resolution can improve the accuracy of time-out intervals in wait functions.
+// However, it can also reduce overall system performance, because the thread scheduler switches tasks more often.
+#define SUPPORT_WINMM_HIGHRES_TIMER 1
+// Use busy wait loop for timing sync, if not defined, a high-resolution timer is set up and used
+//#define SUPPORT_BUSY_WAIT_LOOP 1
+// Use a partial-busy wait loop, in this case frame sleeps for most of the time, but then runs a busy loop at the end for accuracy
+#define SUPPORT_PARTIALBUSY_WAIT_LOOP 1
+// Allow automatic screen capture of current screen pressing F12, defined in KeyCallback()
+#define SUPPORT_SCREEN_CAPTURE 1
+// Allow automatic gif recording of current screen pressing CTRL+F12, defined in KeyCallback()
+#define SUPPORT_GIF_RECORDING 1
+// Support CompressData() and DecompressData() functions
+#define SUPPORT_COMPRESSION_API 1
+// Support automatic generated events, loading and recording of those events when required
+#define SUPPORT_AUTOMATION_EVENTS 1
+// Support custom frame control, only for advanced users
+// By default EndDrawing() does this job: draws everything + SwapScreenBuffer() + manage frame timing + PollInputEvents()
+// Enabling this flag allows manual control of the frame processes, use at your own risk
+//#define SUPPORT_CUSTOM_FRAME_CONTROL 1
+
+
+// rcore: Configuration values
+//------------------------------------------------------------------------------------
+#define MAX_FILEPATH_CAPACITY 8192 // Maximum file paths capacity
+#define MAX_FILEPATH_LENGTH 4096 // Maximum length for filepaths (Linux PATH_MAX default value)
+
+#define MAX_KEYBOARD_KEYS 512 // Maximum number of keyboard keys supported
+#define MAX_MOUSE_BUTTONS 8 // Maximum number of mouse buttons supported
+#define MAX_GAMEPADS 4 // Maximum number of gamepads supported
+#define MAX_GAMEPAD_AXIS 8 // Maximum number of axis supported (per gamepad)
+#define MAX_GAMEPAD_BUTTONS 32 // Maximum number of buttons supported (per gamepad)
+#define MAX_GAMEPAD_VIBRATION_TIME 2.0f // Maximum vibration time in seconds
+#define MAX_TOUCH_POINTS 8 // Maximum number of touch points supported
+#define MAX_KEY_PRESSED_QUEUE 16 // Maximum number of keys in the key input queue
+#define MAX_CHAR_PRESSED_QUEUE 16 // Maximum number of characters in the char input queue
+
+#define MAX_DECOMPRESSION_SIZE 64 // Max size allocated for decompression in MB
+
+#define MAX_AUTOMATION_EVENTS 16384 // Maximum number of automation events to record
+
+//------------------------------------------------------------------------------------
+// Module: rlgl - Configuration values
+//------------------------------------------------------------------------------------
+
+// Enable OpenGL Debug Context (only available on OpenGL 4.3)
+//#define RLGL_ENABLE_OPENGL_DEBUG_CONTEXT 1
+
+// Show OpenGL extensions and capabilities detailed logs on init
+//#define RLGL_SHOW_GL_DETAILS_INFO 1
+
+#define RL_SUPPORT_MESH_GPU_SKINNING 1 // GPU skinning, comment if your GPU does not support more than 8 VBOs
+
+//#define RL_DEFAULT_BATCH_BUFFER_ELEMENTS 4096 // Default internal render batch elements limits
+#define RL_DEFAULT_BATCH_BUFFERS 1 // Default number of batch buffers (multi-buffering)
+#define RL_DEFAULT_BATCH_DRAWCALLS 256 // Default number of batch draw calls (by state changes: mode, texture)
+#define RL_DEFAULT_BATCH_MAX_TEXTURE_UNITS 4 // Maximum number of textures units that can be activated on batch drawing (SetShaderValueTexture())
+
+#define RL_MAX_MATRIX_STACK_SIZE 32 // Maximum size of internal Matrix stack
+
+#define RL_MAX_SHADER_LOCATIONS 32 // Maximum number of shader locations supported
+
+#define RL_CULL_DISTANCE_NEAR 0.01 // Default projection matrix near cull distance
+#define RL_CULL_DISTANCE_FAR 1000.0 // Default projection matrix far cull distance
+
+// Default shader vertex attribute locations
+#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION 0
+#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD 1
+#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL 2
+#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR 3
+#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT 4
+#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2 5
+#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_INDICES 6
+#if defined(RL_SUPPORT_MESH_GPU_SKINNING)
+ #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS 7
+ #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS 8
+#endif
+
+// Default shader vertex attribute names to set location points
+// NOTE: When a new shader is loaded, the following locations are tried to be set for convenience
+#define RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION "vertexPosition" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION
+#define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD "vertexTexCoord" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD
+#define RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL "vertexNormal" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL
+#define RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR "vertexColor" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR
+#define RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT "vertexTangent" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT
+#define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2 "vertexTexCoord2" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2
+
+#define RL_DEFAULT_SHADER_UNIFORM_NAME_MVP "mvp" // model-view-projection matrix
+#define RL_DEFAULT_SHADER_UNIFORM_NAME_VIEW "matView" // view matrix
+#define RL_DEFAULT_SHADER_UNIFORM_NAME_PROJECTION "matProjection" // projection matrix
+#define RL_DEFAULT_SHADER_UNIFORM_NAME_MODEL "matModel" // model matrix
+#define RL_DEFAULT_SHADER_UNIFORM_NAME_NORMAL "matNormal" // normal matrix (transpose(inverse(matModelView))
+#define RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR "colDiffuse" // color diffuse (base tint color, multiplied by texture color)
+#define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0 "texture0" // texture0 (texture slot active 0)
+#define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE1 "texture1" // texture1 (texture slot active 1)
+#define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE2 "texture2" // texture2 (texture slot active 2)
+
+
+//------------------------------------------------------------------------------------
+// Module: rshapes - Configuration Flags
+//------------------------------------------------------------------------------------
+// Use QUADS instead of TRIANGLES for drawing when possible
+// Some lines-based shapes could still use lines
+#define SUPPORT_QUADS_DRAW_MODE 1
+
+// rshapes: Configuration values
+//------------------------------------------------------------------------------------
+#define SPLINE_SEGMENT_DIVISIONS 24 // Spline segments subdivisions
+
+
+//------------------------------------------------------------------------------------
+// Module: rtextures - Configuration Flags
+//------------------------------------------------------------------------------------
+// Selecte desired fileformats to be supported for image data loading
+#define SUPPORT_FILEFORMAT_PNG 1
+#define SUPPORT_FILEFORMAT_BMP 1
+//#define SUPPORT_FILEFORMAT_TGA 1
+#define SUPPORT_FILEFORMAT_JPG 1
+#define SUPPORT_FILEFORMAT_GIF 1
+#define SUPPORT_FILEFORMAT_QOI 1
+//#define SUPPORT_FILEFORMAT_PSD 1
+#define SUPPORT_FILEFORMAT_DDS 1
+//#define SUPPORT_FILEFORMAT_HDR 1
+//#define SUPPORT_FILEFORMAT_PIC 1
+//#define SUPPORT_FILEFORMAT_KTX 1
+//#define SUPPORT_FILEFORMAT_ASTC 1
+//#define SUPPORT_FILEFORMAT_PKM 1
+//#define SUPPORT_FILEFORMAT_PVR 1
+
+// Support image export functionality (.png, .bmp, .tga, .jpg, .qoi)
+#define SUPPORT_IMAGE_EXPORT 1
+// Support procedural image generation functionality (gradient, spot, perlin-noise, cellular)
+#define SUPPORT_IMAGE_GENERATION 1
+// Support multiple image editing functions to scale, adjust colors, flip, draw on images, crop...
+// If not defined, still some functions are supported: ImageFormat(), ImageCrop(), ImageToPOT()
+#define SUPPORT_IMAGE_MANIPULATION 1
+
+
+//------------------------------------------------------------------------------------
+// Module: rtext - Configuration Flags
+//------------------------------------------------------------------------------------
+// Default font is loaded on window initialization to be available for the user to render simple text
+// NOTE: If enabled, uses external module functions to load default raylib font
+#define SUPPORT_DEFAULT_FONT 1
+// Selected desired font fileformats to be supported for loading
+#define SUPPORT_FILEFORMAT_TTF 1
+#define SUPPORT_FILEFORMAT_FNT 1
+#define SUPPORT_FILEFORMAT_BDF 1
+
+// Support text management functions
+// If not defined, still some functions are supported: TextLength(), TextFormat()
+#define SUPPORT_TEXT_MANIPULATION 1
+
+// On font atlas image generation [GenImageFontAtlas()], add a 3x3 pixels white rectangle
+// at the bottom-right corner of the atlas. It can be useful to for shapes drawing, to allow
+// drawing text and shapes with a single draw call [SetShapesTexture()].
+#define SUPPORT_FONT_ATLAS_WHITE_REC 1
+
+// rtext: Configuration values
+//------------------------------------------------------------------------------------
+#define MAX_TEXT_BUFFER_LENGTH 1024 // Size of internal static buffers used on some functions:
+ // TextFormat(), TextSubtext(), TextToUpper(), TextToLower(), TextToPascal(), TextSplit()
+#define MAX_TEXTSPLIT_COUNT 128 // Maximum number of substrings to split: TextSplit()
+
+
+//------------------------------------------------------------------------------------
+// Module: rmodels - Configuration Flags
+//------------------------------------------------------------------------------------
+// Selected desired model fileformats to be supported for loading
+#define SUPPORT_FILEFORMAT_OBJ 1
+#define SUPPORT_FILEFORMAT_MTL 1
+#define SUPPORT_FILEFORMAT_IQM 1
+#define SUPPORT_FILEFORMAT_GLTF 1
+#define SUPPORT_FILEFORMAT_VOX 1
+#define SUPPORT_FILEFORMAT_M3D 1
+// Support procedural mesh generation functions, uses external par_shapes.h library
+// NOTE: Some generated meshes DO NOT include generated texture coordinates
+#define SUPPORT_MESH_GENERATION 1
+
+// rmodels: Configuration values
+//------------------------------------------------------------------------------------
+#define MAX_MATERIAL_MAPS 12 // Maximum number of shader maps supported
+
+#ifdef RL_SUPPORT_MESH_GPU_SKINNING
+#define MAX_MESH_VERTEX_BUFFERS 9 // Maximum vertex buffers (VBO) per mesh
+#else
+#define MAX_MESH_VERTEX_BUFFERS 7 // Maximum vertex buffers (VBO) per mesh
+#endif
+
+//------------------------------------------------------------------------------------
+// Module: raudio - Configuration Flags
+//------------------------------------------------------------------------------------
+// Desired audio fileformats to be supported for loading
+#define SUPPORT_FILEFORMAT_WAV 1
+#define SUPPORT_FILEFORMAT_OGG 1
+#define SUPPORT_FILEFORMAT_MP3 1
+#define SUPPORT_FILEFORMAT_QOA 1
+//#define SUPPORT_FILEFORMAT_FLAC 1
+#define SUPPORT_FILEFORMAT_XM 1
+#define SUPPORT_FILEFORMAT_MOD 1
+
+// raudio: Configuration values
+//------------------------------------------------------------------------------------
+#define AUDIO_DEVICE_FORMAT ma_format_f32 // Device output format (miniaudio: float-32bit)
+#define AUDIO_DEVICE_CHANNELS 2 // Device output channels: stereo
+#define AUDIO_DEVICE_SAMPLE_RATE 0 // Device sample rate (device default)
+
+#define MAX_AUDIO_BUFFER_POOL_CHANNELS 16 // Maximum number of audio pool channels
+
+//------------------------------------------------------------------------------------
+// Module: utils - Configuration Flags
+//------------------------------------------------------------------------------------
+// Standard file io library (stdio.h) included
+#define SUPPORT_STANDARD_FILEIO 1
+// Show TRACELOG() output messages
+// NOTE: By default LOG_DEBUG traces not shown
+#define SUPPORT_TRACELOG 1
+//#define SUPPORT_TRACELOG_DEBUG 1
+
+// utils: Configuration values
+//------------------------------------------------------------------------------------
+#define MAX_TRACELOG_MSG_LENGTH 256 // Max length of one trace-log message
+
+
+// Enable partial support for clipboard image, only working on SDL3 or
+// being on both Windows OS + GLFW or Windows OS + RGFW
+#define SUPPORT_CLIPBOARD_IMAGE 1
+
+#if defined(SUPPORT_CLIPBOARD_IMAGE)
+ #ifndef STBI_REQUIRED
+ #define STBI_REQUIRED
+ #endif
+
+ #ifndef SUPPORT_FILEFORMAT_BMP // For clipboard image on Windows
+ #define SUPPORT_FILEFORMAT_BMP 1
+ #endif
+
+ #ifndef SUPPORT_FILEFORMAT_PNG // Wayland uses png for prints, at least it was on 22 LTS ubuntu
+ #define SUPPORT_FILEFORMAT_PNG 1
+ #endif
+
+ #ifndef SUPPORT_FILEFORMAT_JPG
+ #define SUPPORT_FILEFORMAT_JPG 1
+ #endif
+
+ #ifndef SUPPORT_MODULE_RTEXTURES
+ #define SUPPORT_MODULE_RTEXTURES 1
+ #endif
+#endif
+
+#endif // CONFIG_H
diff --git a/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/RGFW.h b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/RGFW.h
new file mode 100644
index 0000000..978536f
--- /dev/null
+++ b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/RGFW.h
@@ -0,0 +1,9015 @@
+/*
+* Copyright (C) 2023-24 ColleagueRiley
+*
+* libpng license
+*
+* This software is provided 'as-is', without any express or implied
+* warranty. In no event will the authors be held liable for any damages
+* arising from the use of this software.
+*
+* Permission is granted to anyone to use this software for any purpose,
+* including commercial applications, and to alter it and redistribute it
+* freely, subject to the following restrictions:
+*
+* 1. The origin of this software must not be misrepresented; you must not
+* claim that you wrote the original software. If you use this software
+* in a product, an acknowledgment in the product documentation would be
+* appreciated but is not required.
+* 2. Altered source versions must be plainly marked as such, and must not be
+* misrepresented as being the original software.
+* 3. This notice may not be removed or altered from any source distribution.
+*
+*
+*/
+
+/*
+ (MAKE SURE RGFW_IMPLEMENTATION is in exactly one header or you use -D RGFW_IMPLEMENTATION)
+ #define RGFW_IMPLEMENTATION - makes it so source code is included with header
+*/
+
+/*
+ #define RGFW_IMPLEMENTATION - (required) makes it so the source code is included
+ #define RGFW_PRINT_ERRORS - (optional) makes it so RGFW prints errors when they're found
+ #define RGFW_OSMESA - (optional) use OSmesa as backend (instead of system's opengl api + regular opengl)
+ #define RGFW_BUFFER - (optional) just draw directly to (RGFW) window pixel buffer that is drawn to screen (the buffer is in the RGBA format)
+ #define RGFW_EGL - (optional) use EGL for loading an OpenGL context (instead of the system's opengl api)
+ #define RGFW_OPENGL_ES1 - (optional) use EGL to load and use Opengl ES (version 1) for backend rendering (instead of the system's opengl api)
+ This version doesn't work for desktops (I'm pretty sure)
+ #define RGFW_OPENGL_ES2 - (optional) use OpenGL ES (version 2)
+ #define RGFW_OPENGL_ES3 - (optional) use OpenGL ES (version 3)
+ #define RGFW_DIRECTX - (optional) use directX for the rendering backend (rather than opengl) (windows only, defaults to opengl for unix)
+ #define RGFW_WEBGPU - (optional) use webGPU for rendering (Web ONLY)
+ #define RGFW_NO_API - (optional) don't use any rendering API (no opengl, no vulkan, no directX)
+
+ #define RGFW_LINK_EGL (optional) (windows only) if EGL is being used, if EGL functions should be defined dymanically (using GetProcAddress)
+ #define RGFW_LINK_OSMESA (optional) (windows only) if EGL is being used, if OS Mesa functions should be defined dymanically (using GetProcAddress)
+
+ #define RGFW_X11 (optional) (unix only) if X11 should be used. This option is turned on by default by unix systems except for MacOS
+ #define RGFW_WGL_LOAD (optional) (windows only) if WGL should be loaded dynamically during runtime
+ #define RGFW_NO_X11_CURSOR (optional) (unix only) don't use XCursor
+ #define RGFW_NO_X11_CURSOR_PRELOAD (optional) (unix only) Use XCursor, but don't link it in code, (you'll have to link it with -lXcursor)
+
+ #define RGFW_NO_DPI - Do not include calculate DPI (no XRM nor libShcore included)
+
+ #define RGFW_ALLOC_DROPFILES (optional) if room should be allocating for drop files (by default it's global data)
+ #define RGFW_MALLOC x - choose what function to use to allocate, by default the standard malloc is used
+ #define RGFW_CALLOC x - choose what function to use to allocate (calloc), by default the standard calloc is used
+ #define RGFW_FREE x - choose what function to use to allocated memory, by default the standard free is used
+
+ #define RGFW_EXPORT - Use when building RGFW
+ #define RGFW_IMPORT - Use when linking with RGFW (not as a single-header)
+
+ #define RGFW_STD_INT - force the use stdint.h (for systems that might not have stdint.h (msvc))
+*/
+
+/*
+ Credits :
+ EimaMei/Sacode : Much of the code for creating windows using winapi, Wrote the Silicon library, helped with MacOS Support, siliapp.h -> referencing
+
+ stb - This project is heavily inspired by the stb single header files
+
+ GLFW:
+ certain parts of winapi and X11 are very poorly documented,
+ GLFW's source code was referenced and used throughout the project (used code is marked in some way),
+ this mainly includes, code for drag and drops, code for setting the icon to a bitmap and the code for managing the clipboard for X11 (as these parts are not documented very well)
+
+ GLFW Copyright, https::/github.com/GLFW/GLFW
+
+ Copyright (c) 2002-2006 Marcus Geelnard
+ Copyright (c) 2006-2019 Camilla Löwy
+
+ contributors : (feel free to put yourself here if you contribute)
+ krisvers -> code review
+ EimaMei (SaCode) -> code review
+ Code-Nycticebus -> bug fixes
+ Rob Rohan -> X11 bugs and missing features, MacOS/Cocoa fixing memory issues/bugs
+ AICDG (@THISISAGOODNAME) -> vulkan support (example)
+ @Easymode -> support, testing/debugging, bug fixes and reviews
+ Joshua Rowe (omnisci3nce) - bug fix, review (macOS)
+ @lesleyrs -> bug fix, review (OpenGL)
+ Nick Porcino (meshula) - testing, organization, review (MacOS, examples)
+*/
+
+#if _MSC_VER
+ #pragma comment(lib, "gdi32")
+ #pragma comment(lib, "shell32")
+ #pragma comment(lib, "opengl32")
+ #pragma comment(lib, "winmm")
+ #pragma comment(lib, "user32")
+#endif
+
+#ifndef RGFW_MALLOC
+ #include
+
+ #ifndef __USE_POSIX199309
+ #define __USE_POSIX199309
+ #endif
+
+ #include
+ #define RGFW_MALLOC malloc
+ #define RGFW_CALLOC calloc
+ #define RGFW_FREE free
+#endif
+
+#if !_MSC_VER
+ #ifndef inline
+ #ifndef __APPLE__
+ #define inline __inline
+ #endif
+ #endif
+#endif
+
+#ifdef RGFW_WIN95 /* for windows 95 testing (not that it really works) */
+ #define RGFW_NO_MONITOR
+ #define RGFW_NO_PASSTHROUGH
+#endif
+
+#if defined(RGFW_EXPORT) || defined(RGFW_IMPORT)
+ #if defined(_WIN32)
+ #if defined(__TINYC__) && (defined(RGFW_EXPORT) || defined(RGFW_IMPORT))
+ #define __declspec(x) __attribute__((x))
+ #endif
+
+ #if defined(RGFW_EXPORT)
+ #define RGFWDEF __declspec(dllexport)
+ #else
+ #define RGFWDEF __declspec(dllimport)
+ #endif
+ #else
+ #if defined(RGFW_EXPORT)
+ #define RGFWDEF __attribute__((visibility("default")))
+ #endif
+ #endif
+#endif
+
+#ifndef RGFWDEF
+ #ifdef __clang__
+ #define RGFWDEF static inline
+ #else
+ #define RGFWDEF inline
+ #endif
+#endif
+
+#ifndef RGFW_ENUM
+ #define RGFW_ENUM(type, name) type name; enum
+#endif
+
+#ifndef RGFW_UNUSED
+ #define RGFW_UNUSED(x) (void)(x);
+#endif
+
+#if defined(__cplusplus) && !defined(__EMSCRIPTEN__)
+ extern "C" {
+#endif
+
+ /* makes sure the header file part is only defined once by default */
+#ifndef RGFW_HEADER
+
+#define RGFW_HEADER
+
+#if !defined(u8)
+ #if ((defined(_MSC_VER) || defined(__SYMBIAN32__)) && !defined(RGFW_STD_INT)) /* MSVC might not have stdint.h */
+ typedef unsigned char u8;
+ typedef signed char i8;
+ typedef unsigned short u16;
+ typedef signed short i16;
+ typedef unsigned int u32;
+ typedef signed int i32;
+ typedef unsigned long u64;
+ typedef signed long i64;
+ #else /* use stdint standard types instead of c ""standard"" types */
+ #include
+
+ typedef uint8_t u8;
+ typedef int8_t i8;
+ typedef uint16_t u16;
+ typedef int16_t i16;
+ typedef uint32_t u32;
+ typedef int32_t i32;
+ typedef uint64_t u64;
+ typedef int64_t i64;
+ #endif
+#endif
+
+#if !defined(b8) /* RGFW bool type */
+ typedef u8 b8;
+ typedef u32 b32;
+#endif
+
+#define RGFW_TRUE (!(0))
+#define RGFW_FALSE 0
+
+/* thse OS macros looks better & are standardized */
+/* plus it helps with cross-compiling */
+
+#ifdef __EMSCRIPTEN__
+ #define RGFW_WEBASM
+
+ #if !defined(RGFW_NO_API) && !defined(RGFW_WEBGPU)
+ #define RGFW_OPENGL
+ #endif
+
+ #ifdef RGFW_EGL
+ #undef RGFW_EGL
+ #endif
+
+ #include
+ #include
+
+ #ifdef RGFW_WEBGPU
+ #include
+ #endif
+#endif
+
+#if defined(RGFW_X11) && defined(__APPLE__)
+ #define RGFW_MACOS_X11
+ #undef __APPLE__
+#endif
+
+#if defined(_WIN32) && !defined(RGFW_X11) && !defined(RGFW_WEBASM) /* (if you're using X11 on windows some how) */
+ #define RGFW_WINDOWS
+
+ /* make sure the correct architecture is defined */
+ #if defined(_WIN64)
+ #define _AMD64_
+ #undef _X86_
+ #else
+ #undef _AMD64_
+ #ifndef _X86_
+ #define _X86_
+ #endif
+ #endif
+
+ #ifndef RGFW_NO_XINPUT
+ #ifdef __MINGW32__ /* try to find the right header */
+ #include
+ #else
+ #include
+ #endif
+ #endif
+
+ #if defined(RGFW_DIRECTX)
+ #include
+ #include
+ #include
+ #include
+
+ #ifndef __cplusplus
+ #define __uuidof(T) IID_##T
+ #endif
+ #endif
+
+#elif defined(RGFW_WAYLAND)
+ #if !defined(RGFW_NO_API) && (!defined(RGFW_BUFFER) || defined(RGFW_OPENGL))
+ #define RGFW_EGL
+ #define RGFW_OPENGL
+ #include
+ #endif
+
+ #include
+#elif (defined(__unix__) || defined(RGFW_MACOS_X11) || defined(RGFW_X11)) && !defined(RGFW_WEBASM)
+ #define RGFW_MACOS_X11
+ #define RGFW_X11
+ #include
+#elif defined(__APPLE__) && !defined(RGFW_MACOS_X11) && !defined(RGFW_X11) && !defined(RGFW_WEBASM)
+ #define RGFW_MACOS
+#endif
+
+#if (defined(RGFW_OPENGL_ES1) || defined(RGFW_OPENGL_ES2) || defined(RGFW_OPENGL_ES3)) && !defined(RGFW_EGL)
+ #define RGFW_EGL
+#endif
+
+#if !defined(RGFW_OSMESA) && !defined(RGFW_EGL) && !defined(RGFW_OPENGL) && !defined(RGFW_DIRECTX) && !defined(RGFW_BUFFER) && !defined(RGFW_NO_API)
+ #define RGFW_OPENGL
+#endif
+
+#ifdef RGFW_EGL
+ #include
+#elif defined(RGFW_OSMESA)
+ #ifndef __APPLE__
+ #include
+ #else
+ #include
+ #endif
+#endif
+
+#if defined(RGFW_OPENGL) && defined(RGFW_X11)
+ #ifndef GLX_MESA_swap_control
+ #define GLX_MESA_swap_control
+ #endif
+ #include /* GLX defs, xlib.h, gl.h */
+#endif
+
+#ifndef RGFW_ALPHA
+ #define RGFW_ALPHA 128 /* alpha value for RGFW_TRANSPARENT_WINDOW (WINAPI ONLY, macOS + linux don't need this) */
+#endif
+
+/*! Optional arguments for making a windows */
+#define RGFW_TRANSPARENT_WINDOW (1L<<9) /*!< the window is transparent (only properly works on X11 and MacOS, although it's although for windows) */
+#define RGFW_NO_BORDER (1L<<3) /*!< the window doesn't have border */
+#define RGFW_NO_RESIZE (1L<<4) /*!< the window cannot be resized by the user */
+#define RGFW_ALLOW_DND (1L<<5) /*!< the window supports drag and drop*/
+#define RGFW_HIDE_MOUSE (1L<<6) /*! the window should hide the mouse or not (can be toggled later on) using `RGFW_window_mouseShow*/
+#define RGFW_FULLSCREEN (1L<<8) /* the window is fullscreen by default or not */
+#define RGFW_CENTER (1L<<10) /*! center the window on the screen */
+#define RGFW_OPENGL_SOFTWARE (1L<<11) /*! use OpenGL software rendering */
+#define RGFW_COCOA_MOVE_TO_RESOURCE_DIR (1L << 12) /* (cocoa only), move to resource folder */
+#define RGFW_SCALE_TO_MONITOR (1L << 13) /* scale the window to the screen */
+#define RGFW_NO_INIT_API (1L << 2) /* DO not init an API (mostly for bindings, you should use `#define RGFW_NO_API` in C */
+
+#define RGFW_NO_GPU_RENDER (1L<<14) /* don't render (using the GPU based API)*/
+#define RGFW_NO_CPU_RENDER (1L<<15) /* don't render (using the CPU based buffer rendering)*/
+#define RGFW_WINDOW_HIDE (1L << 16)/* the window is hidden */
+
+typedef RGFW_ENUM(u8, RGFW_event_types) {
+ /*! event codes */
+ RGFW_keyPressed = 1, /* a key has been pressed */
+ RGFW_keyReleased, /*!< a key has been released*/
+ /*! key event note
+ the code of the key pressed is stored in
+ RGFW_Event.keyCode
+ !!Keycodes defined at the bottom of the RGFW_HEADER part of this file!!
+
+ while a string version is stored in
+ RGFW_Event.KeyString
+
+ RGFW_Event.lockState holds the current lockState
+ this means if CapsLock, NumLock are active or not
+ */
+ RGFW_mouseButtonPressed, /*!< a mouse button has been pressed (left,middle,right)*/
+ RGFW_mouseButtonReleased, /*!< a mouse button has been released (left,middle,right)*/
+ RGFW_mousePosChanged, /*!< the position of the mouse has been changed*/
+ /*! mouse event note
+ the x and y of the mouse can be found in the vector, RGFW_Event.point
+
+ RGFW_Event.button holds which mouse button was pressed
+ */
+ RGFW_jsButtonPressed, /*!< a joystick button was pressed */
+ RGFW_jsButtonReleased, /*!< a joystick button was released */
+ RGFW_jsAxisMove, /*!< an axis of a joystick was moved*/
+ /*! joystick event note
+ RGFW_Event.joystick holds which joystick was altered, if any
+ RGFW_Event.button holds which joystick button was pressed
+
+ RGFW_Event.axis holds the data of all the axis
+ RGFW_Event.axisCount says how many axis there are
+ */
+ RGFW_windowMoved, /*!< the window was moved (by the user) */
+ RGFW_windowResized, /*!< the window was resized (by the user), [on webASM this means the browser was resized] */
+ RGFW_focusIn, /*!< window is in focus now */
+ RGFW_focusOut, /*!< window is out of focus now */
+ RGFW_mouseEnter, /* mouse entered the window */
+ RGFW_mouseLeave, /* mouse left the window */
+ RGFW_windowRefresh, /* The window content needs to be refreshed */
+
+ /* attribs change event note
+ The event data is sent straight to the window structure
+ with win->r.x, win->r.y, win->r.w and win->r.h
+ */
+ RGFW_quit, /*!< the user clicked the quit button*/
+ RGFW_dnd, /*!< a file has been dropped into the window*/
+ RGFW_dnd_init /*!< the start of a dnd event, when the place where the file drop is known */
+ /* dnd data note
+ The x and y coords of the drop are stored in the vector RGFW_Event.point
+
+ RGFW_Event.droppedFilesCount holds how many files were dropped
+
+ This is also the size of the array which stores all the dropped file string,
+ RGFW_Event.droppedFiles
+ */
+};
+
+/*! mouse button codes (RGFW_Event.button) */
+#define RGFW_mouseLeft 1 /*!< left mouse button is pressed*/
+#define RGFW_mouseMiddle 2 /*!< mouse-wheel-button is pressed*/
+#define RGFW_mouseRight 3 /*!< right mouse button is pressed*/
+#define RGFW_mouseScrollUp 4 /*!< mouse wheel is scrolling up*/
+#define RGFW_mouseScrollDown 5 /*!< mouse wheel is scrolling down*/
+
+#ifndef RGFW_MAX_PATH
+#define RGFW_MAX_PATH 260 /* max length of a path (for dnd) */
+#endif
+#ifndef RGFW_MAX_DROPS
+#define RGFW_MAX_DROPS 260 /* max items you can drop at once */
+#endif
+
+
+/* for RGFW_Event.lockstate */
+#define RGFW_CAPSLOCK (1L << 1)
+#define RGFW_NUMLOCK (1L << 2)
+
+/*! joystick button codes (based on xbox/playstation), you may need to change these values per controller */
+#ifndef RGFW_joystick_codes
+ typedef RGFW_ENUM(u8, RGFW_joystick_codes) {
+ RGFW_JS_A = 0, /*!< or PS X button */
+ RGFW_JS_B = 1, /*!< or PS circle button */
+ RGFW_JS_Y = 2, /*!< or PS triangle button */
+ RGFW_JS_X = 3, /*!< or PS square button */
+ RGFW_JS_START = 9, /*!< start button */
+ RGFW_JS_SELECT = 8, /*!< select button */
+ RGFW_JS_HOME = 10, /*!< home button */
+ RGFW_JS_UP = 13, /*!< dpad up */
+ RGFW_JS_DOWN = 14, /*!< dpad down*/
+ RGFW_JS_LEFT = 15, /*!< dpad left */
+ RGFW_JS_RIGHT = 16, /*!< dpad right */
+ RGFW_JS_L1 = 4, /*!< left bump */
+ RGFW_JS_L2 = 5, /*!< left trigger*/
+ RGFW_JS_R1 = 6, /*!< right bumper */
+ RGFW_JS_R2 = 7, /*!< right trigger */
+ };
+#endif
+
+/*! basic vector type, if there's not already a point/vector type of choice */
+#ifndef RGFW_point
+ typedef struct { i32 x, y; } RGFW_point;
+#endif
+
+/*! basic rect type, if there's not already a rect type of choice */
+#ifndef RGFW_rect
+ typedef struct { i32 x, y, w, h; } RGFW_rect;
+#endif
+
+/*! basic area type, if there's not already a area type of choice */
+#ifndef RGFW_area
+ typedef struct { u32 w, h; } RGFW_area;
+#endif
+
+#ifndef __cplusplus
+#define RGFW_POINT(x, y) (RGFW_point){(i32)(x), (i32)(y)}
+#define RGFW_RECT(x, y, w, h) (RGFW_rect){(i32)(x), (i32)(y), (i32)(w), (i32)(h)}
+#define RGFW_AREA(w, h) (RGFW_area){(u32)(w), (u32)(h)}
+#else
+#define RGFW_POINT(x, y) {(i32)(x), (i32)(y)}
+#define RGFW_RECT(x, y, w, h) {(i32)(x), (i32)(y), (i32)(w), (i32)(h)}
+#define RGFW_AREA(w, h) {(u32)(w), (u32)(h)}
+#endif
+
+#ifndef RGFW_NO_MONITOR
+ /*! structure for monitor data */
+ typedef struct RGFW_monitor {
+ char name[128]; /*!< monitor name */
+ RGFW_rect rect; /*!< monitor Workarea */
+ float scaleX, scaleY; /*!< monitor content scale*/
+ float physW, physH; /*!< monitor physical size */
+ } RGFW_monitor;
+
+ /*
+ NOTE : Monitor functions should be ran only as many times as needed (not in a loop)
+ */
+
+ /*! get an array of all the monitors (max 6) */
+ RGFWDEF RGFW_monitor* RGFW_getMonitors(void);
+ /*! get the primary monitor */
+ RGFWDEF RGFW_monitor RGFW_getPrimaryMonitor(void);
+#endif
+
+/* NOTE: some parts of the data can represent different things based on the event (read comments in RGFW_Event struct) */
+/*! Event structure for checking/getting events */
+typedef struct RGFW_Event {
+ char keyName[16]; /*!< key name of event*/
+
+ /*! drag and drop data */
+ /* 260 max paths with a max length of 260 */
+#ifdef RGFW_ALLOC_DROPFILES
+ char** droppedFiles;
+#else
+ char droppedFiles[RGFW_MAX_DROPS][RGFW_MAX_PATH]; /*!< dropped files*/
+#endif
+ u32 droppedFilesCount; /*!< house many files were dropped */
+
+ u32 type; /*!< which event has been sent?*/
+ RGFW_point point; /*!< mouse x, y of event (or drop point) */
+
+ u8 keyCode; /*!< keycode of event !!Keycodes defined at the bottom of the RGFW_HEADER part of this file!! */
+
+ b8 repeat; /*!< key press event repeated (the key is being held) */
+ b8 inFocus; /*!< if the window is in focus or not (this is always true for MacOS windows due to the api being weird) */
+
+ u8 lockState;
+
+ u8 button; /* !< which mouse button was pressed */
+ double scroll; /*!< the raw mouse scroll value */
+
+ u16 joystick; /*! which joystick this event applies to (if applicable to any) */
+ u8 axisesCount; /*!< number of axises */
+ RGFW_point axis[2]; /*!< x, y of axises (-100 to 100) */
+
+ u64 frameTime, frameTime2; /*!< this is used for counting the fps */
+} RGFW_Event;
+
+/*! source data for the window (used by the APIs) */
+typedef struct RGFW_window_src {
+#ifdef RGFW_WINDOWS
+ HWND window; /*!< source window */
+ HDC hdc; /*!< source HDC */
+ u32 hOffset; /*!< height offset for window */
+ #if (defined(RGFW_OPENGL)) && !defined(RGFW_OSMESA) && !defined(RGFW_EGL)
+ HGLRC ctx; /*!< source graphics context */
+ #elif defined(RGFW_OSMESA)
+ OSMesaContext ctx;
+ #elif defined(RGFW_DIRECTX)
+ IDXGISwapChain* swapchain;
+ ID3D11RenderTargetView* renderTargetView;
+ ID3D11DepthStencilView* pDepthStencilView;
+ #elif defined(RGFW_EGL)
+ EGLSurface EGL_surface;
+ EGLDisplay EGL_display;
+ EGLContext EGL_context;
+ #endif
+
+ #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER)
+ HDC hdcMem;
+ HBITMAP bitmap;
+ #endif
+ RGFW_area maxSize, minSize; /*!< for setting max/min resize (RGFW_WINDOWS) */
+#elif defined(RGFW_X11)
+ Display* display; /*!< source display */
+ Window window; /*!< source window */
+ #if (defined(RGFW_OPENGL)) && !defined(RGFW_OSMESA) && !defined(RGFW_EGL)
+ GLXContext ctx; /*!< source graphics context */
+ #elif defined(RGFW_OSMESA)
+ OSMesaContext ctx;
+ #elif defined(RGFW_EGL)
+ EGLSurface EGL_surface;
+ EGLDisplay EGL_display;
+ EGLContext EGL_context;
+ #endif
+
+#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER)
+ XImage* bitmap;
+ GC gc;
+#endif
+#elif defined(RGFW_WAYLAND)
+ struct wl_display* display;
+ struct wl_surface* surface;
+ struct wl_buffer* wl_buffer;
+ struct wl_keyboard* keyboard;
+
+ struct xdg_surface* xdg_surface;
+ struct xdg_toplevel* xdg_toplevel;
+ struct zxdg_toplevel_decoration_v1* decoration;
+ RGFW_Event events[20];
+ i32 eventLen;
+ size_t eventIndex;
+ #if defined(RGFW_EGL)
+ struct wl_egl_window* window;
+ EGLSurface EGL_surface;
+ EGLDisplay EGL_display;
+ EGLContext EGL_context;
+ #elif defined(RGFW_OSMESA)
+ OSMesaContext ctx;
+ #endif
+#elif defined(RGFW_MACOS)
+ u32 display;
+ void* displayLink;
+ void* window;
+ b8 dndPassed;
+#if (defined(RGFW_OPENGL)) && !defined(RGFW_OSMESA) && !defined(RGFW_EGL)
+ void* ctx; /*!< source graphics context */
+#elif defined(RGFW_OSMESA)
+ OSMesaContext ctx;
+#elif defined(RGFW_EGL)
+ EGLSurface EGL_surface;
+ EGLDisplay EGL_display;
+ EGLContext EGL_context;
+#endif
+
+ void* view; /*apple viewpoint thingy*/
+
+#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER)
+ void* bitmap; /*!< API's bitmap for storing or managing */
+ void* image;
+#endif
+#elif defined(RGFW_WEBASM)
+ #ifdef RGFW_WEBGPU
+ WGPUInstance ctx;
+ WGPUDevice device;
+ WGPUQueue queue;
+ #else
+ EMSCRIPTEN_WEBGL_CONTEXT_HANDLE ctx;
+ #endif
+#endif
+} RGFW_window_src;
+
+
+
+typedef struct RGFW_window {
+ RGFW_window_src src; /*!< src window data */
+
+#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER)
+ u8* buffer; /*!< buffer for non-GPU systems (OSMesa, basic software rendering) */
+ /* when rendering using RGFW_BUFFER, the buffer is in the RGBA format */
+#endif
+ void* userPtr; /* ptr for usr data */
+
+ RGFW_Event event; /*!< current event */
+
+ RGFW_rect r; /*!< the x, y, w and h of the struct */
+
+ RGFW_point _lastMousePoint; /*!< last cusor point (for raw mouse data) */
+
+ u32 _winArgs; /*!< windows args (for RGFW to check) */
+} RGFW_window; /*!< Window structure for managing the window */
+
+#if defined(RGFW_X11) || defined(RGFW_MACOS)
+ typedef u64 RGFW_thread; /*!< thread type unix */
+#else
+ typedef void* RGFW_thread; /*!< thread type for window */
+#endif
+
+/** * @defgroup Window_management
+* @{ */
+
+
+/*!
+ * the class name for X11 and WinAPI. apps with the same class will be grouped by the WM
+ * by default the class name will == the root window's name
+*/
+RGFWDEF void RGFW_setClassName(char* name);
+
+/*! this has to be set before createWindow is called, else the fulscreen size is used */
+RGFWDEF void RGFW_setBufferSize(RGFW_area size); /*!< the buffer cannot be resized (by RGFW) */
+
+RGFWDEF RGFW_window* RGFW_createWindow(
+ const char* name, /* name of the window */
+ RGFW_rect rect, /* rect of window */
+ u16 args /* extra arguments (NULL / (u16)0 means no args used)*/
+); /*!< function to create a window struct */
+
+/*! get the size of the screen to an area struct */
+RGFWDEF RGFW_area RGFW_getScreenSize(void);
+
+/*!
+ this function checks an *individual* event (and updates window structure attributes)
+ this means, using this function without a while loop may cause event lag
+
+ ex.
+
+ while (RGFW_window_checkEvent(win) != NULL) [this keeps checking events until it reaches the last one]
+
+ this function is optional if you choose to use event callbacks,
+ although you still need some way to tell RGFW to process events eg. `RGFW_window_checkEvents`
+*/
+
+RGFWDEF RGFW_Event* RGFW_window_checkEvent(RGFW_window* win); /*!< check current event (returns a pointer to win->event or NULL if there is no event)*/
+
+/*!
+ for RGFW_window_eventWait and RGFW_window_checkEvents
+ waitMS -> Allows th e function to keep checking for events even after `RGFW_window_checkEvent == NULL`
+ if waitMS == 0, the loop will not wait for events
+ if waitMS == a positive integer, the loop will wait that many miliseconds after there are no more events until it returns
+ if waitMS == a negative integer, the loop will not return until it gets another event
+*/
+typedef RGFW_ENUM(i32, RGFW_eventWait) {
+ RGFW_NEXT = -1,
+ RGFW_NO_WAIT = 0
+};
+
+/*! sleep until RGFW gets an event or the timer ends (defined by OS) */
+RGFWDEF void RGFW_window_eventWait(RGFW_window* win, i32 waitMS);
+
+/*!
+ check all the events until there are none left,
+ this should only be used if you're using callbacks only
+*/
+RGFWDEF void RGFW_window_checkEvents(RGFW_window* win, i32 waitMS);
+
+/*!
+ Tell RGFW_window_eventWait to stop waiting, to be ran from another thread
+*/
+RGFWDEF void RGFW_stopCheckEvents(void);
+
+/*! window managment functions*/
+RGFWDEF void RGFW_window_close(RGFW_window* win); /*!< close the window and free leftover data */
+
+/*! moves window to a given point */
+RGFWDEF void RGFW_window_move(RGFW_window* win,
+ RGFW_point v/*!< new pos*/
+);
+
+#ifndef RGFW_NO_MONITOR
+ /*! move to a specific monitor */
+ RGFWDEF void RGFW_window_moveToMonitor(RGFW_window* win, RGFW_monitor m /* monitor */);
+#endif
+
+/*! resize window to a current size/area */
+RGFWDEF void RGFW_window_resize(RGFW_window* win, /*!< source window */
+ RGFW_area a/*!< new size*/
+);
+
+/*! set the minimum size a user can shrink a window to a given size/area */
+RGFWDEF void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a);
+/*! set the minimum size a user can extend a window to a given size/area */
+RGFWDEF void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a);
+
+RGFWDEF void RGFW_window_maximize(RGFW_window* win); /*!< maximize the window size */
+RGFWDEF void RGFW_window_minimize(RGFW_window* win); /*!< minimize the window (in taskbar (per OS))*/
+RGFWDEF void RGFW_window_restore(RGFW_window* win); /*!< restore the window from minimized (per OS)*/
+
+/*! if the window should have a border or not (borderless) based on bool value of `border` */
+RGFWDEF void RGFW_window_setBorder(RGFW_window* win, b8 border);
+
+/*! turn on / off dnd (RGFW_ALLOW_DND stil must be passed to the window)*/
+RGFWDEF void RGFW_window_setDND(RGFW_window* win, b8 allow);
+
+#ifndef RGFW_NO_PASSTHROUGH
+ /*!! turn on / off mouse passthrough */
+ RGFWDEF void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough);
+#endif
+
+/*! rename window to a given string */
+RGFWDEF void RGFW_window_setName(RGFW_window* win,
+ char* name
+);
+
+RGFWDEF void RGFW_window_setIcon(RGFW_window* win, /*!< source window */
+ u8* icon /*!< icon bitmap */,
+ RGFW_area a /*!< width and height of the bitmap*/,
+ i32 channels /*!< how many channels the bitmap has (rgb : 3, rgba : 4) */
+); /*!< image resized by default */
+
+/*!< sets mouse to bitmap (very simular to RGFW_window_setIcon), image NOT resized by default*/
+RGFWDEF void RGFW_window_setMouse(RGFW_window* win, u8* image, RGFW_area a, i32 channels);
+
+/*!< sets the mouse to a standard API cursor (based on RGFW_MOUSE, as seen at the end of the RGFW_HEADER part of this file) */
+RGFWDEF void RGFW_window_setMouseStandard(RGFW_window* win, u8 mouse);
+
+RGFWDEF void RGFW_window_setMouseDefault(RGFW_window* win); /*!< sets the mouse to the default mouse icon */
+/*
+ Locks cursor at the center of the window
+ win->event.point become raw mouse movement data
+
+ this is useful for a 3D camera
+*/
+RGFWDEF void RGFW_window_mouseHold(RGFW_window* win, RGFW_area area);
+/*! stop holding the mouse and let it move freely */
+RGFWDEF void RGFW_window_mouseUnhold(RGFW_window* win);
+
+/*! hide the window */
+RGFWDEF void RGFW_window_hide(RGFW_window* win);
+/*! show the window */
+RGFWDEF void RGFW_window_show(RGFW_window* win);
+
+/*
+ makes it so `RGFW_window_shouldClose` returns true
+ by setting the window event.type to RGFW_quit
+*/
+RGFWDEF void RGFW_window_setShouldClose(RGFW_window* win);
+
+/*! where the mouse is on the screen */
+RGFWDEF RGFW_point RGFW_getGlobalMousePoint(void);
+
+/*! where the mouse is on the window */
+RGFWDEF RGFW_point RGFW_window_getMousePoint(RGFW_window* win);
+
+/*! show the mouse or hide the mouse*/
+RGFWDEF void RGFW_window_showMouse(RGFW_window* win, i8 show);
+/*! move the mouse to a set x, y pos*/
+RGFWDEF void RGFW_window_moveMouse(RGFW_window* win, RGFW_point v);
+
+/*! if the window should close (RGFW_close was sent or escape was pressed) */
+RGFWDEF b8 RGFW_window_shouldClose(RGFW_window* win);
+/*! if window is fullscreen'd */
+RGFWDEF b8 RGFW_window_isFullscreen(RGFW_window* win);
+/*! if window is hidden */
+RGFWDEF b8 RGFW_window_isHidden(RGFW_window* win);
+/*! if window is minimized */
+RGFWDEF b8 RGFW_window_isMinimized(RGFW_window* win);
+/*! if window is maximized */
+RGFWDEF b8 RGFW_window_isMaximized(RGFW_window* win);
+
+/** @} */
+
+/** * @defgroup Monitor
+* @{ */
+
+#ifndef RGFW_NO_MONITOR
+/*
+scale the window to the monitor,
+this is run by default if the user uses the arg `RGFW_SCALE_TO_MONITOR` during window creation
+*/
+RGFWDEF void RGFW_window_scaleToMonitor(RGFW_window* win);
+/*! get the struct of the window's monitor */
+RGFWDEF RGFW_monitor RGFW_window_getMonitor(RGFW_window* win);
+#endif
+
+/** @} */
+
+/** * @defgroup Input
+* @{ */
+
+/*error handling*/
+RGFWDEF b8 RGFW_Error(void); /*!< returns true if an error has occurred (doesn't print errors itself) */
+
+/*! returns true if the key should be shifted */
+RGFWDEF b8 RGFW_shouldShift(u32 keycode, u8 lockState);
+
+/*! get char from RGFW keycode (using a LUT), uses shift'd version if shift = true */
+RGFWDEF char RGFW_keyCodeToChar(u32 keycode, b8 shift);
+/*! get char from RGFW keycode (using a LUT), uses lockState for shouldShift) */
+RGFWDEF char RGFW_keyCodeToCharAuto(u32 keycode, u8 lockState);
+
+/*! if window == NULL, it checks if the key is pressed globally. Otherwise, it checks only if the key is pressed while the window in focus.*/
+RGFWDEF b8 RGFW_isPressed(RGFW_window* win, u8 key); /*!< if key is pressed (key code)*/
+
+RGFWDEF b8 RGFW_wasPressed(RGFW_window* win, u8 key); /*!< if key was pressed (checks previous state only) (key code)*/
+
+RGFWDEF b8 RGFW_isHeld(RGFW_window* win, u8 key); /*!< if key is held (key code)*/
+RGFWDEF b8 RGFW_isReleased(RGFW_window* win, u8 key); /*!< if key is released (key code)*/
+
+/* if a key is pressed and then released, pretty much the same as RGFW_isReleased */
+RGFWDEF b8 RGFW_isClicked(RGFW_window* win, u8 key /*!< key code*/);
+
+/*! if a mouse button is pressed */
+RGFWDEF b8 RGFW_isMousePressed(RGFW_window* win, u8 button /*!< mouse button code */ );
+/*! if a mouse button is held */
+RGFWDEF b8 RGFW_isMouseHeld(RGFW_window* win, u8 button /*!< mouse button code */ );
+/*! if a mouse button was released */
+RGFWDEF b8 RGFW_isMouseReleased(RGFW_window* win, u8 button /*!< mouse button code */ );
+/*! if a mouse button was pressed (checks previous state only) */
+RGFWDEF b8 RGFW_wasMousePressed(RGFW_window* win, u8 button /*!< mouse button code */ );
+/** @} */
+
+/** * @defgroup Clipboard
+* @{ */
+RGFWDEF char* RGFW_readClipboard(size_t* size); /*!< read clipboard data */
+RGFWDEF void RGFW_clipboardFree(char* str); /*!< the string returned from RGFW_readClipboard must be freed */
+
+RGFWDEF void RGFW_writeClipboard(const char* text, u32 textLen); /*!< write text to the clipboard */
+/** @} */
+
+/**
+
+
+ Event callbacks,
+ these are completely optional, you can use the normal
+ RGFW_checkEvent() method if you prefer that
+
+* @defgroup Callbacks
+* @{
+*/
+
+/*! RGFW_windowMoved, the window and its new rect value */
+typedef void (* RGFW_windowmovefunc)(RGFW_window* win, RGFW_rect r);
+/*! RGFW_windowResized, the window and its new rect value */
+typedef void (* RGFW_windowresizefunc)(RGFW_window* win, RGFW_rect r);
+/*! RGFW_quit, the window that was closed */
+typedef void (* RGFW_windowquitfunc)(RGFW_window* win);
+/*! RGFW_focusIn / RGFW_focusOut, the window who's focus has changed and if its inFocus */
+typedef void (* RGFW_focusfunc)(RGFW_window* win, b8 inFocus);
+/*! RGFW_mouseEnter / RGFW_mouseLeave, the window that changed, the point of the mouse (enter only) and if the mouse has entered */
+typedef void (* RGFW_mouseNotifyfunc)(RGFW_window* win, RGFW_point point, b8 status);
+/*! RGFW_mousePosChanged, the window that the move happened on and the new point of the mouse */
+typedef void (* RGFW_mouseposfunc)(RGFW_window* win, RGFW_point point);
+/*! RGFW_dnd_init, the window, the point of the drop on the windows */
+typedef void (* RGFW_dndInitfunc)(RGFW_window* win, RGFW_point point);
+/*! RGFW_windowRefresh, the window that needs to be refreshed */
+typedef void (* RGFW_windowrefreshfunc)(RGFW_window* win);
+/*! RGFW_keyPressed / RGFW_keyReleased, the window that got the event, the keycode, the string version, the state of mod keys, if it was a press (else it's a release) */
+typedef void (* RGFW_keyfunc)(RGFW_window* win, u32 keycode, char keyName[16], u8 lockState, b8 pressed);
+/*! RGFW_mouseButtonPressed / RGFW_mouseButtonReleased, the window that got the event, the button that was pressed, the scroll value, if it was a press (else it's a release) */
+typedef void (* RGFW_mousebuttonfunc)(RGFW_window* win, u8 button, double scroll, b8 pressed);
+/*! RGFW_jsButtonPressed / RGFW_jsButtonReleased, the window that got the event, the button that was pressed, the scroll value, if it was a press (else it's a release) */
+typedef void (* RGFW_jsButtonfunc)(RGFW_window* win, u16 joystick, u8 button, b8 pressed);
+/*! RGFW_jsAxisMove, the window that got the event, the joystick in question, the axis values and the amount of axises */
+typedef void (* RGFW_jsAxisfunc)(RGFW_window* win, u16 joystick, RGFW_point axis[2], u8 axisesCount);
+
+
+/*! RGFW_dnd, the window that had the drop, the drop data and the amount files dropped returns previous callback function (if it was set) */
+#ifdef RGFW_ALLOC_DROPFILES
+ typedef void (* RGFW_dndfunc)(RGFW_window* win, char** droppedFiles, u32 droppedFilesCount);
+#else
+ typedef void (* RGFW_dndfunc)(RGFW_window* win, char droppedFiles[RGFW_MAX_DROPS][RGFW_MAX_PATH], u32 droppedFilesCount);
+#endif
+/*! set callback for a window move event returns previous callback function (if it was set) */
+RGFWDEF RGFW_windowmovefunc RGFW_setWindowMoveCallback(RGFW_windowmovefunc func);
+/*! set callback for a window resize event returns previous callback function (if it was set) */
+RGFWDEF RGFW_windowresizefunc RGFW_setWindowResizeCallback(RGFW_windowresizefunc func);
+/*! set callback for a window quit event returns previous callback function (if it was set) */
+RGFWDEF RGFW_windowquitfunc RGFW_setWindowQuitCallback(RGFW_windowquitfunc func);
+/*! set callback for a mouse move event returns previous callback function (if it was set) */
+RGFWDEF RGFW_mouseposfunc RGFW_setMousePosCallback(RGFW_mouseposfunc func);
+/*! set callback for a window refresh event returns previous callback function (if it was set) */
+RGFWDEF RGFW_windowrefreshfunc RGFW_setWindowRefreshCallback(RGFW_windowrefreshfunc func);
+/*! set callback for a window focus change event returns previous callback function (if it was set) */
+RGFWDEF RGFW_focusfunc RGFW_setFocusCallback(RGFW_focusfunc func);
+/*! set callback for a mouse notify event returns previous callback function (if it was set) */
+RGFWDEF RGFW_mouseNotifyfunc RGFW_setMouseNotifyCallBack(RGFW_mouseNotifyfunc func);
+/*! set callback for a drop event event returns previous callback function (if it was set) */
+RGFWDEF RGFW_dndfunc RGFW_setDndCallback(RGFW_dndfunc func);
+/*! set callback for a start of a drop event returns previous callback function (if it was set) */
+RGFWDEF RGFW_dndInitfunc RGFW_setDndInitCallback(RGFW_dndInitfunc func);
+/*! set callback for a key (press / release ) event returns previous callback function (if it was set) */
+RGFWDEF RGFW_keyfunc RGFW_setKeyCallback(RGFW_keyfunc func);
+/*! set callback for a mouse button (press / release ) event returns previous callback function (if it was set) */
+RGFWDEF RGFW_mousebuttonfunc RGFW_setMouseButtonCallback(RGFW_mousebuttonfunc func);
+/*! set callback for a controller button (press / release ) event returns previous callback function (if it was set) */
+RGFWDEF RGFW_jsButtonfunc RGFW_setjsButtonCallback(RGFW_jsButtonfunc func);
+/*! set callback for a joystick axis mov event returns previous callback function (if it was set) */
+RGFWDEF RGFW_jsAxisfunc RGFW_setjsAxisCallback(RGFW_jsAxisfunc func);
+
+/** @} */
+
+/** * @defgroup Threads
+* @{ */
+
+#ifndef RGFW_NO_THREADS
+ /*! threading functions*/
+
+ /*! NOTE! (for X11/linux) : if you define a window in a thread, it must be run after the original thread's window is created or else there will be a memory error */
+ /*
+ I'd suggest you use sili's threading functions instead
+ if you're going to use sili
+ which is a good idea generally
+ */
+
+ #if defined(__unix__) || defined(__APPLE__) || defined(RGFW_WEBASM)
+ typedef void* (* RGFW_threadFunc_ptr)(void*);
+ #else
+ typedef DWORD (__stdcall *RGFW_threadFunc_ptr) (LPVOID lpThreadParameter);
+ #endif
+
+ RGFWDEF RGFW_thread RGFW_createThread(RGFW_threadFunc_ptr ptr, void* args); /*!< create a thread*/
+ RGFWDEF void RGFW_cancelThread(RGFW_thread thread); /*!< cancels a thread*/
+ RGFWDEF void RGFW_joinThread(RGFW_thread thread); /*!< join thread to current thread */
+ RGFWDEF void RGFW_setThreadPriority(RGFW_thread thread, u8 priority); /*!< sets the priority priority */
+#endif
+
+/** @} */
+
+/** * @defgroup joystick
+* @{ */
+
+/*! joystick count starts at 0*/
+/*!< register joystick to window based on a number (the number is based on when it was connected eg. /dev/js0)*/
+RGFWDEF u16 RGFW_registerJoystick(RGFW_window* win, i32 jsNumber);
+RGFWDEF u16 RGFW_registerJoystickF(RGFW_window* win, char* file);
+
+RGFWDEF u32 RGFW_isPressedJS(RGFW_window* win, u16 controller, u8 button);
+
+/** @} */
+
+/** * @defgroup graphics_API
+* @{ */
+
+/*!< make the window the current opengl drawing context
+
+ NOTE:
+ if you want to switch the graphics context's thread,
+ you have to run RGFW_window_makeCurrent(NULL); on the old thread
+ then RGFW_window_makeCurrent(valid_window) on the new thread
+*/
+RGFWDEF void RGFW_window_makeCurrent(RGFW_window* win);
+
+/*< updates fps / sets fps to cap (must by ran manually by the user at the end of a frame), returns current fps */
+RGFWDEF u32 RGFW_window_checkFPS(RGFW_window* win, u32 fpsCap);
+
+/* supports openGL, directX, OSMesa, EGL and software rendering */
+RGFWDEF void RGFW_window_swapBuffers(RGFW_window* win); /*!< swap the rendering buffer */
+RGFWDEF void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval);
+
+RGFWDEF void RGFW_window_setGPURender(RGFW_window* win, i8 set);
+RGFWDEF void RGFW_window_setCPURender(RGFW_window* win, i8 set);
+
+/*! native API functions */
+#if defined(RGFW_OPENGL) || defined(RGFW_EGL)
+ /*! OpenGL init hints */
+ RGFWDEF void RGFW_setGLStencil(i32 stencil); /*!< set stencil buffer bit size (8 by default) */
+ RGFWDEF void RGFW_setGLSamples(i32 samples); /*!< set number of sampiling buffers (4 by default) */
+ RGFWDEF void RGFW_setGLStereo(i32 stereo); /*!< use GL_STEREO (GL_FALSE by default) */
+ RGFWDEF void RGFW_setGLAuxBuffers(i32 auxBuffers); /*!< number of aux buffers (0 by default) */
+
+ /*! which profile to use for the opengl verion */
+ typedef RGFW_ENUM(u8, RGFW_GL_profile) { RGFW_GL_CORE = 0, RGFW_GL_COMPATIBILITY };
+ /*! Set OpenGL version hint (core or compatibility profile)*/
+ RGFWDEF void RGFW_setGLVersion(RGFW_GL_profile profile, i32 major, i32 minor);
+ RGFWDEF void RGFW_setDoubleBuffer(b8 useDoubleBuffer);
+ RGFWDEF void* RGFW_getProcAddress(const char* procname); /*!< get native opengl proc address */
+ RGFWDEF void RGFW_window_makeCurrent_OpenGL(RGFW_window* win); /*!< to be called by RGFW_window_makeCurrent */
+#elif defined(RGFW_DIRECTX)
+ typedef struct {
+ IDXGIFactory* pFactory;
+ IDXGIAdapter* pAdapter;
+ ID3D11Device* pDevice;
+ ID3D11DeviceContext* pDeviceContext;
+ } RGFW_directXinfo;
+
+ /*
+ RGFW stores a global instance of RGFW_directXinfo,
+ you can use this function to get a pointer the instance
+ */
+ RGFWDEF RGFW_directXinfo* RGFW_getDirectXInfo(void);
+#endif
+
+/** @} */
+
+/** * @defgroup Supporting
+* @{ */
+RGFWDEF u64 RGFW_getTime(void); /*!< get time in seconds */
+RGFWDEF u64 RGFW_getTimeNS(void); /*!< get time in nanoseconds */
+RGFWDEF void RGFW_sleep(u64 milisecond); /*!< sleep for a set time */
+
+/*!
+ key codes and mouse icon enums
+*/
+
+typedef RGFW_ENUM(u8, RGFW_Key) {
+ RGFW_KEY_NULL = 0,
+ RGFW_Escape,
+ RGFW_F1,
+ RGFW_F2,
+ RGFW_F3,
+ RGFW_F4,
+ RGFW_F5,
+ RGFW_F6,
+ RGFW_F7,
+ RGFW_F8,
+ RGFW_F9,
+ RGFW_F10,
+ RGFW_F11,
+ RGFW_F12,
+
+ RGFW_Backtick,
+
+ RGFW_0,
+ RGFW_1,
+ RGFW_2,
+ RGFW_3,
+ RGFW_4,
+ RGFW_5,
+ RGFW_6,
+ RGFW_7,
+ RGFW_8,
+ RGFW_9,
+
+ RGFW_Minus,
+ RGFW_Equals,
+ RGFW_BackSpace,
+ RGFW_Tab,
+ RGFW_CapsLock,
+ RGFW_ShiftL,
+ RGFW_ControlL,
+ RGFW_AltL,
+ RGFW_SuperL,
+ RGFW_ShiftR,
+ RGFW_ControlR,
+ RGFW_AltR,
+ RGFW_SuperR,
+ RGFW_Space,
+
+ RGFW_a,
+ RGFW_b,
+ RGFW_c,
+ RGFW_d,
+ RGFW_e,
+ RGFW_f,
+ RGFW_g,
+ RGFW_h,
+ RGFW_i,
+ RGFW_j,
+ RGFW_k,
+ RGFW_l,
+ RGFW_m,
+ RGFW_n,
+ RGFW_o,
+ RGFW_p,
+ RGFW_q,
+ RGFW_r,
+ RGFW_s,
+ RGFW_t,
+ RGFW_u,
+ RGFW_v,
+ RGFW_w,
+ RGFW_x,
+ RGFW_y,
+ RGFW_z,
+
+ RGFW_Period,
+ RGFW_Comma,
+ RGFW_Slash,
+ RGFW_Bracket,
+ RGFW_CloseBracket,
+ RGFW_Semicolon,
+ RGFW_Return,
+ RGFW_Quote,
+ RGFW_BackSlash,
+
+ RGFW_Up,
+ RGFW_Down,
+ RGFW_Left,
+ RGFW_Right,
+
+ RGFW_Delete,
+ RGFW_Insert,
+ RGFW_End,
+ RGFW_Home,
+ RGFW_PageUp,
+ RGFW_PageDown,
+
+ RGFW_Numlock,
+ RGFW_KP_Slash,
+ RGFW_Multiply,
+ RGFW_KP_Minus,
+ RGFW_KP_1,
+ RGFW_KP_2,
+ RGFW_KP_3,
+ RGFW_KP_4,
+ RGFW_KP_5,
+ RGFW_KP_6,
+ RGFW_KP_7,
+ RGFW_KP_8,
+ RGFW_KP_9,
+ RGFW_KP_0,
+ RGFW_KP_Period,
+ RGFW_KP_Return,
+
+ final_key,
+};
+
+
+typedef RGFW_ENUM(u8, RGFW_mouseIcons) {
+ RGFW_MOUSE_NORMAL = 0,
+ RGFW_MOUSE_ARROW,
+ RGFW_MOUSE_IBEAM,
+ RGFW_MOUSE_CROSSHAIR,
+ RGFW_MOUSE_POINTING_HAND,
+ RGFW_MOUSE_RESIZE_EW,
+ RGFW_MOUSE_RESIZE_NS,
+ RGFW_MOUSE_RESIZE_NWSE,
+ RGFW_MOUSE_RESIZE_NESW,
+ RGFW_MOUSE_RESIZE_ALL,
+ RGFW_MOUSE_NOT_ALLOWED,
+};
+
+/** @} */
+
+#endif /* RGFW_HEADER */
+
+/*
+Example to get you started :
+
+linux : gcc main.c -lX11 -lXcursor -lGL
+windows : gcc main.c -lopengl32 -lshell32 -lgdi32
+macos : gcc main.c -framework Foundation -framework AppKit -framework OpenGL -framework CoreVideo
+
+#define RGFW_IMPLEMENTATION
+#include "RGFW.h"
+
+u8 icon[4 * 3 * 3] = {0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF};
+
+int main() {
+ RGFW_window* win = RGFW_createWindow("name", RGFW_RECT(500, 500, 500, 500), (u64)0);
+
+ RGFW_window_setIcon(win, icon, RGFW_AREA(3, 3), 4);
+
+ for (;;) {
+ RGFW_window_checkEvent(win); // NOTE: checking events outside of a while loop may cause input lag
+ if (win->event.type == RGFW_quit || RGFW_isPressed(win, RGFW_Escape))
+ break;
+
+ RGFW_window_swapBuffers(win);
+
+ glClearColor(0xFF, 0XFF, 0xFF, 0xFF);
+ glClear(GL_COLOR_BUFFER_BIT);
+ }
+
+ RGFW_window_close(win);
+}
+
+ compiling :
+
+ if you wish to compile the library all you have to do is create a new file with this in it
+
+ rgfw.c
+ #define RGFW_IMPLEMENTATION
+ #include "RGFW.h"
+
+ then you can use gcc (or whatever compile you wish to use) to compile the library into object file
+
+ ex. gcc -c RGFW.c -fPIC
+
+ after you compile the library into an object file, you can also turn the object file into an static or shared library
+
+ (commands ar and gcc can be replaced with whatever equivalent your system uses)
+ static : ar rcs RGFW.a RGFW.o
+ shared :
+ windows:
+ gcc -shared RGFW.o -lwinmm -lopengl32 -lshell32 -lgdi32 -o RGFW.dll
+ linux:
+ gcc -shared RGFW.o -lX11 -lXcursor -lGL -lXrandr -o RGFW.so
+ macos:
+ gcc -shared RGFW.o -framework Foundation -framework AppKit -framework OpenGL -framework CoreVideo
+*/
+
+#ifdef RGFW_X11
+ #define RGFW_OS_BASED_VALUE(l, w, m, h, ww) l
+#elif defined(RGFW_WINDOWS)
+ #define RGFW_OS_BASED_VALUE(l, w, m, h, ww) w
+#elif defined(RGFW_MACOS)
+ #define RGFW_OS_BASED_VALUE(l, w, m, h, ww) m
+#elif defined(RGFW_WEBASM)
+ #define RGFW_OS_BASED_VALUE(l, w, m, h, ww) h
+#elif defined(RGFW_WAYLAND)
+ #define RGFW_OS_BASED_VALUE(l, w, m, h, ww) ww
+#endif
+
+
+#ifdef RGFW_IMPLEMENTATION
+
+#include
+#include
+#include
+#include
+
+/*
+RGFW_IMPLEMENTATION starts with generic RGFW defines
+
+This is the start of keycode data
+
+ Why not use macros instead of the numbers itself?
+ Windows -> Not all virtual keys are macros (VK_0 - VK_1, VK_a - VK_z)
+ Linux -> Only symcodes are values, (XK_0 - XK_1, XK_a - XK_z) are larger than 0xFF00, I can't find any way to work with them without making the array an unreasonable size
+ MacOS -> windows and linux already don't have keycodes as macros, so there's no point
+*/
+
+
+
+/*
+ the c++ compiler doesn't support setting up an array like,
+ we'll have to do it during runtime using a function & this messy setup
+*/
+#ifndef __cplusplus
+#define RGFW_NEXT ,
+#define RGFW_MAP
+#else
+#define RGFW_NEXT ;
+#define RGFW_MAP RGFW_keycodes
+#endif
+
+#ifdef RGFW_WAYLAND
+#include
+#endif
+
+u8 RGFW_keycodes [RGFW_OS_BASED_VALUE(136, 337, 128, DOM_VK_WIN_OEM_CLEAR + 1, 130)] = {
+#ifdef __cplusplus
+ 0
+};
+void RGFW_init_keys(void) {
+#endif
+ RGFW_MAP [RGFW_OS_BASED_VALUE(49, 192, 50, DOM_VK_BACK_QUOTE, KEY_GRAVE)] = RGFW_Backtick RGFW_NEXT
+
+ RGFW_MAP [RGFW_OS_BASED_VALUE(19, 0x30, 29, DOM_VK_0, KEY_0)] = RGFW_0 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(10, 0x31, 18, DOM_VK_1, KEY_1)] = RGFW_1 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(11, 0x32, 19, DOM_VK_2, KEY_2)] = RGFW_2 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(12, 0x33, 20, DOM_VK_3, KEY_3)] = RGFW_3 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(13, 0x34, 21, DOM_VK_4, KEY_4)] = RGFW_4 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(14, 0x35, 23, DOM_VK_5, KEY_5)] = RGFW_5 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(15, 0x36, 22, DOM_VK_6, KEY_6)] = RGFW_6 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(16, 0x37, 26, DOM_VK_7, KEY_7)] = RGFW_7 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(17, 0x38, 28, DOM_VK_8, KEY_8)] = RGFW_8 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(18, 0x39, 25, DOM_VK_9, KEY_9)] = RGFW_9,
+
+ RGFW_MAP [RGFW_OS_BASED_VALUE(65, 0x20, 49, DOM_VK_SPACE, KEY_SPACE)] = RGFW_Space,
+
+ RGFW_MAP [RGFW_OS_BASED_VALUE(38, 0x41, 0, DOM_VK_A, KEY_A)] = RGFW_a RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(56, 0x42, 11, DOM_VK_B, KEY_B)] = RGFW_b RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(54, 0x43, 8, DOM_VK_C, KEY_C)] = RGFW_c RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(40, 0x44, 2, DOM_VK_D, KEY_D)] = RGFW_d RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(26, 0x45, 14, DOM_VK_E, KEY_E)] = RGFW_e RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(41, 0x46, 3, DOM_VK_F, KEY_F)] = RGFW_f RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(42, 0x47, 5, DOM_VK_G, KEY_G)] = RGFW_g RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(43, 0x48, 4, DOM_VK_H, KEY_H)] = RGFW_h RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(31, 0x49, 34, DOM_VK_I, KEY_I)] = RGFW_i RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(44, 0x4A, 38, DOM_VK_J, KEY_J)] = RGFW_j RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(45, 0x4B, 40, DOM_VK_K, KEY_K)] = RGFW_k RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(46, 0x4C, 37, DOM_VK_L, KEY_L)] = RGFW_l RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(58, 0x4D, 46, DOM_VK_M, KEY_M)] = RGFW_m RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(57, 0x4E, 45, DOM_VK_N, KEY_N)] = RGFW_n RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(32, 0x4F, 31, DOM_VK_O, KEY_O)] = RGFW_o RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(33, 0x50, 35, DOM_VK_P, KEY_P)] = RGFW_p RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(24, 0x51, 12, DOM_VK_Q, KEY_Q)] = RGFW_q RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(27, 0x52, 15, DOM_VK_R, KEY_R)] = RGFW_r RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(39, 0x53, 1, DOM_VK_S, KEY_S)] = RGFW_s RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(28, 0x54, 17, DOM_VK_T, KEY_T)] = RGFW_t RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(30, 0x55, 32, DOM_VK_U, KEY_U)] = RGFW_u RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(55, 0x56, 9, DOM_VK_V, KEY_V)] = RGFW_v RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(25, 0x57, 13, DOM_VK_W, KEY_W)] = RGFW_w RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(53, 0x58, 7, DOM_VK_X, KEY_X)] = RGFW_x RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(29, 0x59, 16, DOM_VK_Y, KEY_Y)] = RGFW_y RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(52, 0x5A, 6, DOM_VK_Z, KEY_Z)] = RGFW_z,
+
+ RGFW_MAP [RGFW_OS_BASED_VALUE(60, 190, 47, DOM_VK_PERIOD, KEY_DOT)] = RGFW_Period RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(59, 188, 43, DOM_VK_COMMA, KEY_COMMA)] = RGFW_Comma RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(61, 191, 44, DOM_VK_SLASH, KEY_SLASH)] = RGFW_Slash RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(34, 219, 33, DOM_VK_OPEN_BRACKET, KEY_LEFTBRACE)] = RGFW_Bracket RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(35, 221, 30, DOM_VK_CLOSE_BRACKET, KEY_RIGHTBRACE)] = RGFW_CloseBracket RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(47, 186, 41, DOM_VK_SEMICOLON, KEY_SEMICOLON)] = RGFW_Semicolon RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(48, 222, 39, DOM_VK_QUOTE, KEY_APOSTROPHE)] = RGFW_Quote RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(51, 322, 42, DOM_VK_BACK_SLASH, KEY_BACKSLASH)] = RGFW_BackSlash,
+
+ RGFW_MAP [RGFW_OS_BASED_VALUE(36, 0x0D, 36, DOM_VK_RETURN, KEY_ENTER)] = RGFW_Return RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(119, 0x2E, 118, DOM_VK_DELETE, KEY_DELETE)] = RGFW_Delete RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(77, 0x90, 72, DOM_VK_NUM_LOCK, KEY_NUMLOCK)] = RGFW_Numlock RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(106, 0x6F, 82, DOM_VK_DIVIDE, KEY_KPSLASH)] = RGFW_KP_Slash RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(63, 0x6A, 76, DOM_VK_MULTIPLY, KEY_KPASTERISK)] = RGFW_Multiply RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(82, 0x6D, 67, DOM_VK_SUBTRACT, KEY_KPMINUS)] = RGFW_KP_Minus RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(87, 0x61, 84, DOM_VK_NUMPAD1, KEY_KP1)] = RGFW_KP_1 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(88, 0x62, 85, DOM_VK_NUMPAD2, KEY_KP2)] = RGFW_KP_2 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(89, 0x63, 86, DOM_VK_NUMPAD3, KEY_KP3)] = RGFW_KP_3 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(83, 0x64, 87, DOM_VK_NUMPAD4, KEY_KP4)] = RGFW_KP_4 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(84, 0x65, 88, DOM_VK_NUMPAD5, KEY_KP5)] = RGFW_KP_5 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(85, 0x66, 89, DOM_VK_NUMPAD6, KEY_KP6)] = RGFW_KP_6 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(79, 0x67, 90, DOM_VK_NUMPAD7, KEY_KP7)] = RGFW_KP_7 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(80, 0x68, 92, DOM_VK_NUMPAD8, KEY_KP8)] = RGFW_KP_8 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(81, 0x69, 93, DOM_VK_NUMPAD9, KEY_KP9)] = RGFW_KP_9 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(90, 0x60, 83, DOM_VK_NUMPAD0, KEY_KP0)] = RGFW_KP_0 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(91, 0x6E, 65, DOM_VK_DECIMAL, KEY_KPDOT)] = RGFW_KP_Period RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(104, 0x92, 77, 0, KEY_KPENTER)] = RGFW_KP_Return,
+
+ RGFW_MAP [RGFW_OS_BASED_VALUE(20, 189, 27, DOM_VK_HYPHEN_MINUS, KEY_MINUS)] = RGFW_Minus RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(21, 187, 24, DOM_VK_EQUALS, KEY_EQUAL)] = RGFW_Equals RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(22, 8, 51, DOM_VK_BACK_SPACE, KEY_BACKSPACE)] = RGFW_BackSpace RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(23, 0x09, 48, DOM_VK_TAB, KEY_TAB)] = RGFW_Tab RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(66, 20, 57, DOM_VK_CAPS_LOCK, KEY_CAPSLOCK)] = RGFW_CapsLock RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(50, 0x10, 56, DOM_VK_SHIFT, KEY_LEFTSHIFT)] = RGFW_ShiftL RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(37, 0x11, 59, DOM_VK_CONTROL, KEY_LEFTCTRL)] = RGFW_ControlL RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(64,0x12, 58, DOM_VK_ALT, KEY_LEFTALT)] = RGFW_AltL RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(133, 0x5B, 55, DOM_VK_WIN, KEY_LEFTMETA)] = RGFW_SuperL,
+
+ #if !defined(RGFW_WINDOWS) && !defined(RGFW_MACOS) && !defined(RGFW_WEBASM)
+ RGFW_MAP [RGFW_OS_BASED_VALUE(105, 0x11, 59, 0, KEY_RIGHTCTRL)] = RGFW_ControlR RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(135, 0xA4, 55, 0, KEY_RIGHTMETA)] = RGFW_SuperR,
+ RGFW_MAP [RGFW_OS_BASED_VALUE(62, 0x5C, 56, 0, KEY_RIGHTSHIFT)] = RGFW_ShiftR RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(108, 165, 58, 0, KEY_RIGHTALT)] = RGFW_AltR,
+ #endif
+
+ RGFW_MAP [RGFW_OS_BASED_VALUE(67, 0x70, 127, DOM_VK_F1, KEY_F1)] = RGFW_F1 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(68, 0x71, 121, DOM_VK_F2, KEY_F2)] = RGFW_F2 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(69, 0x72, 100, DOM_VK_F3, KEY_F3)] = RGFW_F3 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(70, 0x73, 119, DOM_VK_F4, KEY_F4)] = RGFW_F4 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(71, 0x74, 97, DOM_VK_F5, KEY_F5)] = RGFW_F5 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(72, 0x75, 98, DOM_VK_F6, KEY_F6)] = RGFW_F6 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(73, 0x76, 99, DOM_VK_F7, KEY_F7)] = RGFW_F7 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(74, 0x77, 101, DOM_VK_F8, KEY_F8)] = RGFW_F8 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(75, 0x78, 102, DOM_VK_F9, KEY_F9)] = RGFW_F9 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(76, 0x79, 110, DOM_VK_F10, KEY_F10)] = RGFW_F10 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(95, 0x7A, 104, DOM_VK_F11, KEY_F11)] = RGFW_F11 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(96, 0x7B, 112, DOM_VK_F12, KEY_F12)] = RGFW_F12 RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(111, 0x26, 126, DOM_VK_UP, KEY_UP)] = RGFW_Up RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(116, 0x28, 125, DOM_VK_DOWN, KEY_DOWN)] = RGFW_Down RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(113, 0x25, 123, DOM_VK_LEFT, KEY_LEFT)] = RGFW_Left RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(114, 0x27, 124, DOM_VK_RIGHT, KEY_RIGHT)] = RGFW_Right RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(118, 0x2D, 115, DOM_VK_INSERT, KEY_INSERT)] = RGFW_Insert RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(115, 0x23, 120, DOM_VK_END, KEY_END)] = RGFW_End RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(112, 336, 117, DOM_VK_PAGE_UP, KEY_PAGEUP)] = RGFW_PageUp RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(117, 325, 122, DOM_VK_PAGE_DOWN, KEY_PAGEDOWN)] = RGFW_PageDown RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(9, 0x1B, 53, DOM_VK_ESCAPE, KEY_ESC)] = RGFW_Escape RGFW_NEXT
+ RGFW_MAP [RGFW_OS_BASED_VALUE(110, 0x24, 116, DOM_VK_HOME, KEY_HOME)] = RGFW_Home RGFW_NEXT
+#ifndef __cplusplus
+};
+#else
+}
+#endif
+
+#undef RGFW_NEXT
+#undef RGFW_MAP
+
+typedef struct {
+ b8 current : 1;
+ b8 prev : 1;
+} RGFW_keyState;
+
+RGFW_keyState RGFW_keyboard[final_key] = { {0, 0} };
+
+RGFWDEF u32 RGFW_apiKeyCodeToRGFW(u32 keycode);
+
+u32 RGFW_apiKeyCodeToRGFW(u32 keycode) {
+ #ifdef __cplusplus
+ if (RGFW_OS_BASED_VALUE(49, 192, 50, DOM_VK_BACK_QUOTE, KEY_GRAVE) != RGFW_Backtick) {
+ RGFW_init_keys();
+ }
+ #endif
+
+ /* make sure the key isn't out of bounds */
+ if (keycode > sizeof(RGFW_keycodes) / sizeof(u8))
+ return 0;
+
+ return RGFW_keycodes[keycode];
+}
+
+RGFWDEF void RGFW_resetKey(void);
+void RGFW_resetKey(void) {
+ size_t len = final_key; /*!< last_key == length */
+
+ size_t i; /*!< reset each previous state */
+ for (i = 0; i < len; i++)
+ RGFW_keyboard[i].prev = 0;
+}
+
+b8 RGFW_shouldShift(u32 keycode, u8 lockState) {
+ #define RGFW_xor(x, y) (( (x) && (!(y)) ) || ((y) && (!(x)) ))
+ b8 caps4caps = (lockState & RGFW_CAPSLOCK) && ((keycode >= RGFW_a) && (keycode <= RGFW_z));
+ b8 shouldShift = RGFW_xor((RGFW_isPressed(NULL, RGFW_ShiftL) || RGFW_isPressed(NULL, RGFW_ShiftR)), caps4caps);
+ #undef RGFW_xor
+
+ return shouldShift;
+}
+
+char RGFW_keyCodeToChar(u32 keycode, b8 shift) {
+ static const char map[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '`', '0', '1', '2', '3', '4', '5', '6', '7', '8',
+ '9', '-', '=', 0, '\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, ' ', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '.', ',', '/', '[', ']', ';', '\n', '\'', '\\',
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '/', '*', '-', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '\n'
+ };
+
+ static const char mapCaps[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '~', ')', '!', '@', '#', '$', '%', '^', '&', '*',
+ '(', '_', '+', 0, '0', 0, 0, 0, 0, 0, 0, 0, 0, 0, ' ', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
+ 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
+ 'X', 'Y', 'Z', '>', '<', '?', '{', '}', ':', '\n', '"', '|',
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '?', '*', '-', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+
+ if (shift == RGFW_FALSE)
+ return map[keycode];
+ return mapCaps[keycode];
+}
+
+char RGFW_keyCodeToCharAuto(u32 keycode, u8 lockState) { return RGFW_keyCodeToChar(keycode, RGFW_shouldShift(keycode, lockState)); }
+
+/*
+ this is the end of keycode data
+*/
+
+/* joystick data */
+u8 RGFW_jsPressed[4][16]; /*!< if a key is currently pressed or not (per joystick) */
+
+i32 RGFW_joysticks[4]; /*!< limit of 4 joysticks at a time */
+u16 RGFW_joystickCount; /*!< the actual amount of joysticks */
+
+/*
+ event callback defines start here
+*/
+
+
+/*
+ These exist to avoid the
+ if (func == NULL) check
+ for (allegedly) better performance
+*/
+void RGFW_windowmovefuncEMPTY(RGFW_window* win, RGFW_rect r) { RGFW_UNUSED(win); RGFW_UNUSED(r); }
+void RGFW_windowresizefuncEMPTY(RGFW_window* win, RGFW_rect r) { RGFW_UNUSED(win); RGFW_UNUSED(r); }
+void RGFW_windowquitfuncEMPTY(RGFW_window* win) { RGFW_UNUSED(win); }
+void RGFW_focusfuncEMPTY(RGFW_window* win, b8 inFocus) {RGFW_UNUSED(win); RGFW_UNUSED(inFocus);}
+void RGFW_mouseNotifyfuncEMPTY(RGFW_window* win, RGFW_point point, b8 status) {RGFW_UNUSED(win); RGFW_UNUSED(point); RGFW_UNUSED(status);}
+void RGFW_mouseposfuncEMPTY(RGFW_window* win, RGFW_point point) {RGFW_UNUSED(win); RGFW_UNUSED(point);}
+void RGFW_dndInitfuncEMPTY(RGFW_window* win, RGFW_point point) {RGFW_UNUSED(win); RGFW_UNUSED(point);}
+void RGFW_windowrefreshfuncEMPTY(RGFW_window* win) {RGFW_UNUSED(win); }
+void RGFW_keyfuncEMPTY(RGFW_window* win, u32 keycode, char keyName[16], u8 lockState, b8 pressed) {RGFW_UNUSED(win); RGFW_UNUSED(keycode); RGFW_UNUSED(keyName); RGFW_UNUSED(lockState); RGFW_UNUSED(pressed);}
+void RGFW_mousebuttonfuncEMPTY(RGFW_window* win, u8 button, double scroll, b8 pressed) {RGFW_UNUSED(win); RGFW_UNUSED(button); RGFW_UNUSED(scroll); RGFW_UNUSED(pressed);}
+void RGFW_jsButtonfuncEMPTY(RGFW_window* win, u16 joystick, u8 button, b8 pressed){RGFW_UNUSED(win); RGFW_UNUSED(joystick); RGFW_UNUSED(button); RGFW_UNUSED(pressed); }
+void RGFW_jsAxisfuncEMPTY(RGFW_window* win, u16 joystick, RGFW_point axis[2], u8 axisesCount){RGFW_UNUSED(win); RGFW_UNUSED(joystick); RGFW_UNUSED(axis); RGFW_UNUSED(axisesCount); }
+
+#ifdef RGFW_ALLOC_DROPFILES
+void RGFW_dndfuncEMPTY(RGFW_window* win, char** droppedFiles, u32 droppedFilesCount) {RGFW_UNUSED(win); RGFW_UNUSED(droppedFiles); RGFW_UNUSED(droppedFilesCount);}
+#else
+void RGFW_dndfuncEMPTY(RGFW_window* win, char droppedFiles[RGFW_MAX_DROPS][RGFW_MAX_PATH], u32 droppedFilesCount) {RGFW_UNUSED(win); RGFW_UNUSED(droppedFiles); RGFW_UNUSED(droppedFilesCount);}
+#endif
+
+RGFW_windowmovefunc RGFW_windowMoveCallback = RGFW_windowmovefuncEMPTY;
+RGFW_windowresizefunc RGFW_windowResizeCallback = RGFW_windowresizefuncEMPTY;
+RGFW_windowquitfunc RGFW_windowQuitCallback = RGFW_windowquitfuncEMPTY;
+RGFW_mouseposfunc RGFW_mousePosCallback = RGFW_mouseposfuncEMPTY;
+RGFW_windowrefreshfunc RGFW_windowRefreshCallback = RGFW_windowrefreshfuncEMPTY;
+RGFW_focusfunc RGFW_focusCallback = RGFW_focusfuncEMPTY;
+RGFW_mouseNotifyfunc RGFW_mouseNotifyCallBack = RGFW_mouseNotifyfuncEMPTY;
+RGFW_dndfunc RGFW_dndCallback = RGFW_dndfuncEMPTY;
+RGFW_dndInitfunc RGFW_dndInitCallback = RGFW_dndInitfuncEMPTY;
+RGFW_keyfunc RGFW_keyCallback = RGFW_keyfuncEMPTY;
+RGFW_mousebuttonfunc RGFW_mouseButtonCallback = RGFW_mousebuttonfuncEMPTY;
+RGFW_jsButtonfunc RGFW_jsButtonCallback = RGFW_jsButtonfuncEMPTY;
+RGFW_jsAxisfunc RGFW_jsAxisCallback = RGFW_jsAxisfuncEMPTY;
+
+void RGFW_window_checkEvents(RGFW_window* win, i32 waitMS) {
+ RGFW_window_eventWait(win, waitMS);
+
+ while (RGFW_window_checkEvent(win) != NULL && RGFW_window_shouldClose(win) == 0) {
+ if (win->event.type == RGFW_quit) return;
+ }
+
+ #ifdef RGFW_WEBASM /* webasm needs to run the sleep function for asyncify */
+ RGFW_sleep(0);
+ #endif
+}
+
+RGFW_windowmovefunc RGFW_setWindowMoveCallback(RGFW_windowmovefunc func) {
+ RGFW_windowmovefunc prev = (RGFW_windowMoveCallback == RGFW_windowmovefuncEMPTY) ? NULL : RGFW_windowMoveCallback;
+ RGFW_windowMoveCallback = func;
+ return prev;
+}
+RGFW_windowresizefunc RGFW_setWindowResizeCallback(RGFW_windowresizefunc func) {
+ RGFW_windowresizefunc prev = (RGFW_windowResizeCallback == RGFW_windowresizefuncEMPTY) ? NULL : RGFW_windowResizeCallback;
+ RGFW_windowResizeCallback = func;
+ return prev;
+}
+RGFW_windowquitfunc RGFW_setWindowQuitCallback(RGFW_windowquitfunc func) {
+ RGFW_windowquitfunc prev = (RGFW_windowQuitCallback == RGFW_windowquitfuncEMPTY) ? NULL : RGFW_windowQuitCallback;
+ RGFW_windowQuitCallback = func;
+ return prev;
+}
+
+RGFW_mouseposfunc RGFW_setMousePosCallback(RGFW_mouseposfunc func) {
+ RGFW_mouseposfunc prev = (RGFW_mousePosCallback == RGFW_mouseposfuncEMPTY) ? NULL : RGFW_mousePosCallback;
+ RGFW_mousePosCallback = func;
+ return prev;
+}
+RGFW_windowrefreshfunc RGFW_setWindowRefreshCallback(RGFW_windowrefreshfunc func) {
+ RGFW_windowrefreshfunc prev = (RGFW_windowRefreshCallback == RGFW_windowrefreshfuncEMPTY) ? NULL : RGFW_windowRefreshCallback;
+ RGFW_windowRefreshCallback = func;
+ return prev;
+}
+RGFW_focusfunc RGFW_setFocusCallback(RGFW_focusfunc func) {
+ RGFW_focusfunc prev = (RGFW_focusCallback == RGFW_focusfuncEMPTY) ? NULL : RGFW_focusCallback;
+ RGFW_focusCallback = func;
+ return prev;
+}
+
+RGFW_mouseNotifyfunc RGFW_setMouseNotifyCallBack(RGFW_mouseNotifyfunc func) {
+ RGFW_mouseNotifyfunc prev = (RGFW_mouseNotifyCallBack == RGFW_mouseNotifyfuncEMPTY) ? NULL : RGFW_mouseNotifyCallBack;
+ RGFW_mouseNotifyCallBack = func;
+ return prev;
+}
+RGFW_dndfunc RGFW_setDndCallback(RGFW_dndfunc func) {
+ RGFW_dndfunc prev = (RGFW_dndCallback == RGFW_dndfuncEMPTY) ? NULL : RGFW_dndCallback;
+ RGFW_dndCallback = func;
+ return prev;
+}
+RGFW_dndInitfunc RGFW_setDndInitCallback(RGFW_dndInitfunc func) {
+ RGFW_dndInitfunc prev = (RGFW_dndInitCallback == RGFW_dndInitfuncEMPTY) ? NULL : RGFW_dndInitCallback;
+ RGFW_dndInitCallback = func;
+ return prev;
+}
+RGFW_keyfunc RGFW_setKeyCallback(RGFW_keyfunc func) {
+ RGFW_keyfunc prev = (RGFW_keyCallback == RGFW_keyfuncEMPTY) ? NULL : RGFW_keyCallback;
+ RGFW_keyCallback = func;
+ return prev;
+}
+RGFW_mousebuttonfunc RGFW_setMouseButtonCallback(RGFW_mousebuttonfunc func) {
+ RGFW_mousebuttonfunc prev = (RGFW_mouseButtonCallback == RGFW_mousebuttonfuncEMPTY) ? NULL : RGFW_mouseButtonCallback;
+ RGFW_mouseButtonCallback = func;
+ return prev;
+}
+RGFW_jsButtonfunc RGFW_setjsButtonCallback(RGFW_jsButtonfunc func) {
+ RGFW_jsButtonfunc prev = (RGFW_jsButtonCallback == RGFW_jsButtonfuncEMPTY) ? NULL : RGFW_jsButtonCallback;
+ RGFW_jsButtonCallback = func;
+ return prev;
+}
+RGFW_jsAxisfunc RGFW_setjsAxisCallback(RGFW_jsAxisfunc func) {
+ RGFW_jsAxisfunc prev = (RGFW_jsAxisCallback == RGFW_jsAxisfuncEMPTY) ? NULL : RGFW_jsAxisCallback;
+ RGFW_jsAxisCallback = func;
+ return prev;
+}
+/*
+no more event call back defines
+*/
+
+#define RGFW_ASSERT(check, str) {\
+ if (!(check)) { \
+ printf(str); \
+ assert(check); \
+ } \
+}
+
+b8 RGFW_error = 0;
+b8 RGFW_Error(void) { return RGFW_error; }
+
+#define SET_ATTRIB(a, v) { \
+ assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
+ attribs[index++] = a; \
+ attribs[index++] = v; \
+}
+
+RGFW_area RGFW_bufferSize = {0, 0};
+void RGFW_setBufferSize(RGFW_area size) {
+ RGFW_bufferSize = size;
+}
+
+
+RGFWDEF RGFW_window* RGFW_window_basic_init(RGFW_rect rect, u16 args);
+
+/* do a basic initialization for RGFW_window, this is to standard it for each OS */
+RGFW_window* RGFW_window_basic_init(RGFW_rect rect, u16 args) {
+ RGFW_window* win = (RGFW_window*) RGFW_MALLOC(sizeof(RGFW_window)); /*!< make a new RGFW struct */
+
+ /* clear out dnd info */
+#ifdef RGFW_ALLOC_DROPFILES
+ win->event.droppedFiles = (char**) RGFW_MALLOC(sizeof(char*) * RGFW_MAX_DROPS);
+ u32 i;
+ for (i = 0; i < RGFW_MAX_DROPS; i++)
+ win->event.droppedFiles[i] = (char*) RGFW_CALLOC(RGFW_MAX_PATH, sizeof(char));
+#endif
+
+ /* X11 requires us to have a display to get the screen size */
+ #ifndef RGFW_X11
+ RGFW_area screenR = RGFW_getScreenSize();
+ #else
+ win->src.display = XOpenDisplay(NULL);
+ assert(win->src.display != NULL);
+
+ Screen* scrn = DefaultScreenOfDisplay((Display*)win->src.display);
+ RGFW_area screenR = RGFW_AREA((u32)scrn->width, (u32)scrn->height);
+ #endif
+
+ /* rect based the requested args */
+ if (args & RGFW_FULLSCREEN)
+ rect = RGFW_RECT(0, 0, screenR.w, screenR.h);
+
+ /* set and init the new window's data */
+ win->r = rect;
+ win->event.inFocus = 1;
+ win->event.droppedFilesCount = 0;
+ RGFW_joystickCount = 0;
+ win->_winArgs = 0;
+ win->event.lockState = 0;
+
+ return win;
+}
+
+#ifndef RGFW_NO_MONITOR
+void RGFW_window_scaleToMonitor(RGFW_window* win) {
+ RGFW_monitor monitor = RGFW_window_getMonitor(win);
+
+ RGFW_window_resize(win, RGFW_AREA((u32)(monitor.scaleX * (float)win->r.w), (u32)(monitor.scaleX * (float)win->r.h)));
+}
+#endif
+
+RGFW_window* RGFW_root = NULL;
+
+
+#define RGFW_HOLD_MOUSE (1L<<2) /*!< hold the moues still */
+#define RGFW_MOUSE_LEFT (1L<<3) /* if mouse left the window */
+
+#ifdef RGFW_MACOS
+RGFWDEF void RGFW_window_cocoaSetLayer(RGFW_window* win, void* layer);
+RGFWDEF void* RGFW_cocoaGetLayer(void);
+#endif
+
+char* RGFW_className = NULL;
+void RGFW_setClassName(char* name) {
+ RGFW_className = name;
+}
+
+void RGFW_clipboardFree(char* str) { RGFW_FREE(str); }
+
+RGFW_keyState RGFW_mouseButtons[5] = { {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0} };
+
+b8 RGFW_isMousePressed(RGFW_window* win, u8 button) {
+ assert(win != NULL);
+ return RGFW_mouseButtons[button].current && (win != NULL) && win->event.inFocus;
+}
+b8 RGFW_wasMousePressed(RGFW_window* win, u8 button) {
+ assert(win != NULL);
+ return RGFW_mouseButtons[button].prev && (win != NULL) && win->event.inFocus;
+}
+b8 RGFW_isMouseHeld(RGFW_window* win, u8 button) {
+ return (RGFW_isMousePressed(win, button) && RGFW_wasMousePressed(win, button));
+}
+b8 RGFW_isMouseReleased(RGFW_window* win, u8 button) {
+ return (!RGFW_isMousePressed(win, button) && RGFW_wasMousePressed(win, button));
+}
+
+b8 RGFW_isPressed(RGFW_window* win, u8 key) {
+ return RGFW_keyboard[key].current && (win == NULL || win->event.inFocus);
+}
+
+b8 RGFW_wasPressed(RGFW_window* win, u8 key) {
+ return RGFW_keyboard[key].prev && (win == NULL || win->event.inFocus);
+}
+
+b8 RGFW_isHeld(RGFW_window* win, u8 key) {
+ return (RGFW_isPressed(win, key) && RGFW_wasPressed(win, key));
+}
+
+b8 RGFW_isClicked(RGFW_window* win, u8 key) {
+ return (RGFW_wasPressed(win, key) && !RGFW_isPressed(win, key));
+}
+
+b8 RGFW_isReleased(RGFW_window* win, u8 key) {
+ return (!RGFW_isPressed(win, key) && RGFW_wasPressed(win, key));
+}
+
+#if defined(RGFW_WINDOWS) && defined(RGFW_DIRECTX) /* defines for directX context*/
+ RGFW_directXinfo RGFW_dxInfo;
+ RGFW_directXinfo* RGFW_getDirectXInfo(void) { return &RGFW_dxInfo; }
+#endif
+
+void RGFW_window_makeCurrent(RGFW_window* win) {
+#if defined(RGFW_WINDOWS) && defined(RGFW_DIRECTX)
+ if (win == NULL)
+ RGFW_dxInfo.pDeviceContext->lpVtbl->OMSetRenderTargets(RGFW_dxInfo.pDeviceContext, 1, NULL, NULL);
+ else
+ RGFW_dxInfo.pDeviceContext->lpVtbl->OMSetRenderTargets(RGFW_dxInfo.pDeviceContext, 1, &win->src.renderTargetView, NULL);
+#elif defined(RGFW_OPENGL)
+ RGFW_window_makeCurrent_OpenGL(win);
+#else
+ RGFW_UNUSED(win)
+#endif
+}
+
+void RGFW_window_setGPURender(RGFW_window* win, i8 set) {
+ if (!set && !(win->_winArgs & RGFW_NO_GPU_RENDER))
+ win->_winArgs |= RGFW_NO_GPU_RENDER;
+
+ else if (set && win->_winArgs & RGFW_NO_GPU_RENDER)
+ win->_winArgs ^= RGFW_NO_GPU_RENDER;
+}
+
+void RGFW_window_setCPURender(RGFW_window* win, i8 set) {
+ if (!set && !(win->_winArgs & RGFW_NO_CPU_RENDER))
+ win->_winArgs |= RGFW_NO_CPU_RENDER;
+
+ else if (set && win->_winArgs & RGFW_NO_CPU_RENDER)
+ win->_winArgs ^= RGFW_NO_CPU_RENDER;
+}
+
+void RGFW_window_maximize(RGFW_window* win) {
+ assert(win != NULL);
+
+ RGFW_area screen = RGFW_getScreenSize();
+
+ RGFW_window_move(win, RGFW_POINT(0, 0));
+ RGFW_window_resize(win, screen);
+}
+
+b8 RGFW_window_shouldClose(RGFW_window* win) {
+ assert(win != NULL);
+ return (win->event.type == RGFW_quit || RGFW_isPressed(win, RGFW_Escape));
+}
+
+void RGFW_window_setShouldClose(RGFW_window* win) { win->event.type = RGFW_quit; RGFW_windowQuitCallback(win); }
+
+#ifndef RGFW_NO_MONITOR
+ void RGFW_window_moveToMonitor(RGFW_window* win, RGFW_monitor m) {
+ RGFW_window_move(win, RGFW_POINT(m.rect.x + win->r.x, m.rect.y + win->r.y));
+ }
+#endif
+
+RGFWDEF void RGFW_captureCursor(RGFW_window* win, RGFW_rect);
+RGFWDEF void RGFW_releaseCursor(RGFW_window* win);
+
+void RGFW_window_mouseHold(RGFW_window* win, RGFW_area area) {
+ if ((win->_winArgs & RGFW_HOLD_MOUSE))
+ return;
+
+
+ if (!area.w && !area.h)
+ area = RGFW_AREA(win->r.w / 2, win->r.h / 2);
+
+ win->_winArgs |= RGFW_HOLD_MOUSE;
+ RGFW_captureCursor(win, win->r);
+ RGFW_window_moveMouse(win, RGFW_POINT(win->r.x + (win->r.w / 2), win->r.y + (win->r.h / 2)));
+}
+
+void RGFW_window_mouseUnhold(RGFW_window* win) {
+ if ((win->_winArgs & RGFW_HOLD_MOUSE)) {
+ win->_winArgs ^= RGFW_HOLD_MOUSE;
+
+ RGFW_releaseCursor(win);
+ }
+}
+
+u32 RGFW_window_checkFPS(RGFW_window* win, u32 fpsCap) {
+ u64 deltaTime = RGFW_getTimeNS() - win->event.frameTime;
+
+ u32 output_fps = 0;
+ u64 fps = round(1e+9 / deltaTime);
+ output_fps= fps;
+
+ if (fpsCap && fps > fpsCap) {
+ u64 frameTimeNS = 1e+9 / fpsCap;
+ u64 sleepTimeMS = (frameTimeNS - deltaTime) / 1e6;
+
+ if (sleepTimeMS > 0) {
+ RGFW_sleep(sleepTimeMS);
+ win->event.frameTime = 0;
+ }
+ }
+
+ win->event.frameTime = RGFW_getTimeNS();
+
+ if (fpsCap == 0)
+ return (u32) output_fps;
+
+ deltaTime = RGFW_getTimeNS() - win->event.frameTime2;
+ output_fps = round(1e+9 / deltaTime);
+ win->event.frameTime2 = RGFW_getTimeNS();
+
+ return output_fps;
+}
+
+u32 RGFW_isPressedJS(RGFW_window* win, u16 c, u8 button) {
+ RGFW_UNUSED(win);
+ return RGFW_jsPressed[c][button];
+}
+
+#if defined(RGFW_X11) || defined(RGFW_WINDOWS)
+ void RGFW_window_showMouse(RGFW_window* win, i8 show) {
+ static u8 RGFW_blk[] = { 0, 0, 0, 0 };
+ if (show == 0)
+ RGFW_window_setMouse(win, RGFW_blk, RGFW_AREA(1, 1), 4);
+ else
+ RGFW_window_setMouseDefault(win);
+ }
+#endif
+
+RGFWDEF void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock);
+void RGFW_updateLockState(RGFW_window* win, b8 capital, b8 numlock) {
+ if (capital && !(win->event.lockState & RGFW_CAPSLOCK))
+ win->event.lockState |= RGFW_CAPSLOCK;
+ else if (!capital && (win->event.lockState & RGFW_CAPSLOCK))
+ win->event.lockState ^= RGFW_CAPSLOCK;
+
+ if (numlock && !(win->event.lockState & RGFW_NUMLOCK))
+ win->event.lockState |= RGFW_NUMLOCK;
+ else if (!numlock && (win->event.lockState & RGFW_NUMLOCK))
+ win->event.lockState ^= RGFW_NUMLOCK;
+}
+
+#if defined(RGFW_X11) || defined(RGFW_MACOS) || defined(RGFW_WEBASM) || defined(RGFW_WAYLAND)
+ struct timespec;
+
+ int nanosleep(const struct timespec* duration, struct timespec* rem);
+ int clock_gettime(clockid_t clk_id, struct timespec* tp);
+ int setenv(const char *name, const char *value, int overwrite);
+
+ void RGFW_window_setDND(RGFW_window* win, b8 allow) {
+ if (allow && !(win->_winArgs & RGFW_ALLOW_DND))
+ win->_winArgs |= RGFW_ALLOW_DND;
+
+ else if (!allow && (win->_winArgs & RGFW_ALLOW_DND))
+ win->_winArgs ^= RGFW_ALLOW_DND;
+ }
+#endif
+
+/*
+ graphics API specific code (end of generic code)
+ starts here
+*/
+
+
+/*
+ OpenGL defines start here (Normal, EGL, OSMesa)
+*/
+
+#if defined(RGFW_OPENGL) || defined(RGFW_EGL) || defined(RGFW_OSMESA)
+ #ifdef RGFW_WINDOWS
+ #define WIN32_LEAN_AND_MEAN
+ #define OEMRESOURCE
+ #include
+ #endif
+
+ #if !defined(__APPLE__) && !defined(RGFW_NO_GL_HEADER)
+ #include
+ #elif defined(__APPLE__)
+ #ifndef GL_SILENCE_DEPRECATION
+ #define GL_SILENCE_DEPRECATION
+ #endif
+ #include
+ #include
+ #endif
+
+/* EGL, normal OpenGL only */
+#if !defined(RGFW_OSMESA)
+ i32 RGFW_majorVersion = 0, RGFW_minorVersion = 0;
+ b8 RGFW_profile = RGFW_GL_CORE;
+
+ #ifndef RGFW_EGL
+ i32 RGFW_STENCIL = 8, RGFW_SAMPLES = 4, RGFW_STEREO = 0, RGFW_AUX_BUFFERS = 0, RGFW_DOUBLE_BUFFER = 1;
+ #else
+ i32 RGFW_STENCIL = 0, RGFW_SAMPLES = 0, RGFW_STEREO = 0, RGFW_AUX_BUFFERS = 0, RGFW_DOUBLE_BUFFER = 1;
+ #endif
+
+
+ void RGFW_setGLStencil(i32 stencil) { RGFW_STENCIL = stencil; }
+ void RGFW_setGLSamples(i32 samples) { RGFW_SAMPLES = samples; }
+ void RGFW_setGLStereo(i32 stereo) { RGFW_STEREO = stereo; }
+ void RGFW_setGLAuxBuffers(i32 auxBuffers) { RGFW_AUX_BUFFERS = auxBuffers; }
+ void RGFW_setDoubleBuffer(b8 useDoubleBuffer) { RGFW_DOUBLE_BUFFER = useDoubleBuffer; }
+
+ void RGFW_setGLVersion(b8 profile, i32 major, i32 minor) {
+ RGFW_profile = profile;
+ RGFW_majorVersion = major;
+ RGFW_minorVersion = minor;
+ }
+
+/* OPENGL normal only (no EGL / OSMesa) */
+#ifndef RGFW_EGL
+
+#define RGFW_GL_RENDER_TYPE RGFW_OS_BASED_VALUE(GLX_X_VISUAL_TYPE, 0x2003, 73, 0, 0)
+ #define RGFW_GL_ALPHA_SIZE RGFW_OS_BASED_VALUE(GLX_ALPHA_SIZE, 0x201b, 11, 0, 0)
+ #define RGFW_GL_DEPTH_SIZE RGFW_OS_BASED_VALUE(GLX_DEPTH_SIZE, 0x2022, 12, 0, 0)
+ #define RGFW_GL_DOUBLEBUFFER RGFW_OS_BASED_VALUE(GLX_DOUBLEBUFFER, 0x2011, 5, 0, 0)
+ #define RGFW_GL_STENCIL_SIZE RGFW_OS_BASED_VALUE(GLX_STENCIL_SIZE, 0x2023, 13, 0, 0)
+ #define RGFW_GL_SAMPLES RGFW_OS_BASED_VALUE(GLX_SAMPLES, 0x2042, 55, 0, 0)
+ #define RGFW_GL_STEREO RGFW_OS_BASED_VALUE(GLX_STEREO, 0x2012, 6, 0, 0)
+ #define RGFW_GL_AUX_BUFFERS RGFW_OS_BASED_VALUE(GLX_AUX_BUFFERS, 0x2024, 7, 0, 0)
+
+#if defined(RGFW_X11) || defined(RGFW_WINDOWS)
+ #define RGFW_GL_DRAW RGFW_OS_BASED_VALUE(GLX_X_RENDERABLE, 0x2001, 0, 0, 0)
+ #define RGFW_GL_DRAW_TYPE RGFW_OS_BASED_VALUE(GLX_RENDER_TYPE, 0x2013, 0, 0, 0)
+ #define RGFW_GL_FULL_FORMAT RGFW_OS_BASED_VALUE(GLX_TRUE_COLOR, 0x2027, 0, 0, 0)
+ #define RGFW_GL_RED_SIZE RGFW_OS_BASED_VALUE(GLX_RED_SIZE, 0x2015, 0, 0, 0)
+ #define RGFW_GL_GREEN_SIZE RGFW_OS_BASED_VALUE(GLX_GREEN_SIZE, 0x2017, 0, 0, 0)
+ #define RGFW_GL_BLUE_SIZE RGFW_OS_BASED_VALUE(GLX_BLUE_SIZE, 0x2019, 0, 0, 0)
+ #define RGFW_GL_USE_RGBA RGFW_OS_BASED_VALUE(GLX_RGBA_BIT, 0x202B, 0, 0, 0)
+#endif
+
+#ifdef RGFW_WINDOWS
+ #define WGL_SUPPORT_OPENGL_ARB 0x2010
+ #define WGL_COLOR_BITS_ARB 0x2014
+ #define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000
+ #define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
+ #define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
+ #define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
+ #define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
+ #define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
+ #define WGL_SAMPLE_BUFFERS_ARB 0x2041
+ #define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20a9
+ #define WGL_PIXEL_TYPE_ARB 0x2013
+ #define WGL_TYPE_RGBA_ARB 0x202B
+
+ #define WGL_TRANSPARENT_ARB 0x200A
+#endif
+
+/* The window'ing api needs to know how to render the data we (or opengl) give it
+ MacOS and Windows do this using a structure called a "pixel format"
+ X11 calls it a "Visual"
+ This function returns the attributes for the format we want */
+ static u32* RGFW_initFormatAttribs(u32 useSoftware) {
+ RGFW_UNUSED(useSoftware);
+ static u32 attribs[] = {
+ #if defined(RGFW_X11) || defined(RGFW_WINDOWS)
+ RGFW_GL_RENDER_TYPE,
+ RGFW_GL_FULL_FORMAT,
+ #endif
+ RGFW_GL_ALPHA_SIZE , 8,
+ RGFW_GL_DEPTH_SIZE , 24,
+ #if defined(RGFW_X11) || defined(RGFW_WINDOWS)
+ RGFW_GL_DRAW, 1,
+ RGFW_GL_RED_SIZE , 8,
+ RGFW_GL_GREEN_SIZE , 8,
+ RGFW_GL_BLUE_SIZE , 8,
+ RGFW_GL_DRAW_TYPE , RGFW_GL_USE_RGBA,
+ #endif
+
+ #ifdef RGFW_X11
+ GLX_DRAWABLE_TYPE , GLX_WINDOW_BIT,
+ #endif
+
+ #ifdef RGFW_MACOS
+ 72,
+ 8, 24,
+ #endif
+
+ #ifdef RGFW_WINDOWS
+ WGL_SUPPORT_OPENGL_ARB, 1,
+ WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
+ WGL_COLOR_BITS_ARB, 32,
+ #endif
+
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+
+ size_t index = (sizeof(attribs) / sizeof(attribs[0])) - 13;
+
+ #define RGFW_GL_ADD_ATTRIB(attrib, attVal) \
+ if (attVal) { \
+ attribs[index] = attrib;\
+ attribs[index + 1] = attVal;\
+ index += 2;\
+ }
+
+ RGFW_GL_ADD_ATTRIB(RGFW_GL_DOUBLEBUFFER, 1);
+
+ RGFW_GL_ADD_ATTRIB(RGFW_GL_STENCIL_SIZE, RGFW_STENCIL);
+ RGFW_GL_ADD_ATTRIB(RGFW_GL_STEREO, RGFW_STEREO);
+ RGFW_GL_ADD_ATTRIB(RGFW_GL_AUX_BUFFERS, RGFW_AUX_BUFFERS);
+
+#ifndef RGFW_X11
+ RGFW_GL_ADD_ATTRIB(RGFW_GL_SAMPLES, RGFW_SAMPLES);
+#endif
+
+#ifdef RGFW_MACOS
+ if (useSoftware) {
+ RGFW_GL_ADD_ATTRIB(70, kCGLRendererGenericFloatID);
+ } else {
+ attribs[index] = RGFW_GL_RENDER_TYPE;
+ index += 1;
+ }
+#endif
+
+#ifdef RGFW_MACOS
+ /* macOS has the surface attribs and the opengl attribs connected for some reason
+ maybe this is to give macOS more control to limit openGL/the opengl version? */
+
+ attribs[index] = 99;
+ attribs[index + 1] = 0x1000;
+
+ if (RGFW_majorVersion >= 4 || RGFW_majorVersion >= 3) {
+ attribs[index + 1] = (u32) ((RGFW_majorVersion >= 4) ? 0x4100 : 0x3200);
+ }
+#endif
+
+ RGFW_GL_ADD_ATTRIB(0, 0);
+
+ return attribs;
+ }
+
+/* EGL only (no OSMesa nor normal OPENGL) */
+#elif defined(RGFW_EGL)
+
+#include
+
+#if defined(RGFW_LINK_EGL)
+ typedef EGLBoolean(EGLAPIENTRY* PFN_eglInitialize)(EGLDisplay, EGLint*, EGLint*);
+
+ PFNEGLINITIALIZEPROC eglInitializeSource;
+ PFNEGLGETCONFIGSPROC eglGetConfigsSource;
+ PFNEGLCHOOSECONFIGPROC eglChooseConfigSource;
+ PFNEGLCREATEWINDOWSURFACEPROC eglCreateWindowSurfaceSource;
+ PFNEGLCREATECONTEXTPROC eglCreateContextSource;
+ PFNEGLMAKECURRENTPROC eglMakeCurrentSource;
+ PFNEGLGETDISPLAYPROC eglGetDisplaySource;
+ PFNEGLSWAPBUFFERSPROC eglSwapBuffersSource;
+ PFNEGLSWAPINTERVALPROC eglSwapIntervalSource;
+ PFNEGLBINDAPIPROC eglBindAPISource;
+ PFNEGLDESTROYCONTEXTPROC eglDestroyContextSource;
+ PFNEGLTERMINATEPROC eglTerminateSource;
+ PFNEGLDESTROYSURFACEPROC eglDestroySurfaceSource;
+
+#define eglInitialize eglInitializeSource
+#define eglGetConfigs eglGetConfigsSource
+#define eglChooseConfig eglChooseConfigSource
+#define eglCreateWindowSurface eglCreateWindowSurfaceSource
+#define eglCreateContext eglCreateContextSource
+#define eglMakeCurrent eglMakeCurrentSource
+#define eglGetDisplay eglGetDisplaySource
+#define eglSwapBuffers eglSwapBuffersSource
+#define eglSwapInterval eglSwapIntervalSource
+#define eglBindAPI eglBindAPISource
+#define eglDestroyContext eglDestroyContextSource
+#define eglTerminate eglTerminateSource
+#define eglDestroySurface eglDestroySurfaceSource;
+#endif
+
+
+#define EGL_SURFACE_MAJOR_VERSION_KHR 0x3098
+#define EGL_SURFACE_MINOR_VERSION_KHR 0x30fb
+
+#ifndef RGFW_GL_ADD_ATTRIB
+#define RGFW_GL_ADD_ATTRIB(attrib, attVal) \
+ if (attVal) { \
+ attribs[index] = attrib;\
+ attribs[index + 1] = attVal;\
+ index += 2;\
+ }
+#endif
+
+
+ void RGFW_createOpenGLContext(RGFW_window* win) {
+#if defined(RGFW_LINK_EGL)
+ eglInitializeSource = (PFNEGLINITIALIZEPROC) eglGetProcAddress("eglInitialize");
+ eglGetConfigsSource = (PFNEGLGETCONFIGSPROC) eglGetProcAddress("eglGetConfigs");
+ eglChooseConfigSource = (PFNEGLCHOOSECONFIGPROC) eglGetProcAddress("eglChooseConfig");
+ eglCreateWindowSurfaceSource = (PFNEGLCREATEWINDOWSURFACEPROC) eglGetProcAddress("eglCreateWindowSurface");
+ eglCreateContextSource = (PFNEGLCREATECONTEXTPROC) eglGetProcAddress("eglCreateContext");
+ eglMakeCurrentSource = (PFNEGLMAKECURRENTPROC) eglGetProcAddress("eglMakeCurrent");
+ eglGetDisplaySource = (PFNEGLGETDISPLAYPROC) eglGetProcAddress("eglGetDisplay");
+ eglSwapBuffersSource = (PFNEGLSWAPBUFFERSPROC) eglGetProcAddress("eglSwapBuffers");
+ eglSwapIntervalSource = (PFNEGLSWAPINTERVALPROC) eglGetProcAddress("eglSwapInterval");
+ eglBindAPISource = (PFNEGLBINDAPIPROC) eglGetProcAddress("eglBindAPI");
+ eglDestroyContextSource = (PFNEGLDESTROYCONTEXTPROC) eglGetProcAddress("eglDestroyContext");
+ eglTerminateSource = (PFNEGLTERMINATEPROC) eglGetProcAddress("eglTerminate");
+ eglDestroySurfaceSource = (PFNEGLDESTROYSURFACEPROC) eglGetProcAddress("eglDestroySurface");
+#endif /* RGFW_LINK_EGL */
+
+ #ifdef RGFW_WINDOWS
+ win->src.EGL_display = eglGetDisplay((EGLNativeDisplayType) win->src.hdc);
+ #elif defined(RGFW_MACOS)
+ win->src.EGL_display = eglGetDisplay((EGLNativeDisplayType)0);
+ #else
+ win->src.EGL_display = eglGetDisplay((EGLNativeDisplayType) win->src.display);
+ #endif
+
+ EGLint major, minor;
+
+ eglInitialize(win->src.EGL_display, &major, &minor);
+
+ #ifndef EGL_OPENGL_ES1_BIT
+ #define EGL_OPENGL_ES1_BIT 0x1
+ #endif
+
+ EGLint egl_config[] = {
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+ EGL_RENDERABLE_TYPE,
+ #ifdef RGFW_OPENGL_ES1
+ EGL_OPENGL_ES1_BIT,
+ #elif defined(RGFW_OPENGL_ES3)
+ EGL_OPENGL_ES3_BIT,
+ #elif defined(RGFW_OPENGL_ES2)
+ EGL_OPENGL_ES2_BIT,
+ #else
+ EGL_OPENGL_BIT,
+ #endif
+ EGL_NONE, EGL_NONE
+ };
+
+ EGLConfig config;
+ EGLint numConfigs;
+ eglChooseConfig(win->src.EGL_display, egl_config, &config, 1, &numConfigs);
+
+ #if defined(RGFW_MACOS)
+ void* layer = RGFW_cocoaGetLayer();
+
+ RGFW_window_cocoaSetLayer(win, layer);
+
+ win->src.EGL_surface = eglCreateWindowSurface(win->src.EGL_display, config, (EGLNativeWindowType) layer, NULL);
+ #else
+ win->src.EGL_surface = eglCreateWindowSurface(win->src.EGL_display, config, (EGLNativeWindowType) win->src.window, NULL);
+ #endif
+
+ EGLint attribs[] = {
+ EGL_CONTEXT_CLIENT_VERSION,
+ #ifdef RGFW_OPENGL_ES1
+ 1,
+ #else
+ 2,
+ #endif
+ EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE, EGL_NONE
+ };
+
+ size_t index = 4;
+ RGFW_GL_ADD_ATTRIB(EGL_STENCIL_SIZE, RGFW_STENCIL);
+ RGFW_GL_ADD_ATTRIB(EGL_SAMPLES, RGFW_SAMPLES);
+
+ if (RGFW_DOUBLE_BUFFER)
+ RGFW_GL_ADD_ATTRIB(EGL_RENDER_BUFFER, EGL_BACK_BUFFER);
+
+ if (RGFW_majorVersion) {
+ attribs[1] = RGFW_majorVersion;
+
+ RGFW_GL_ADD_ATTRIB(EGL_CONTEXT_MAJOR_VERSION, RGFW_majorVersion);
+ RGFW_GL_ADD_ATTRIB(EGL_CONTEXT_MINOR_VERSION, RGFW_minorVersion);
+
+ if (RGFW_profile == RGFW_GL_CORE) {
+ RGFW_GL_ADD_ATTRIB(EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT);
+ }
+ else {
+ RGFW_GL_ADD_ATTRIB(EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT);
+ }
+
+ }
+
+ #if defined(RGFW_OPENGL_ES1) || defined(RGFW_OPENGL_ES2) || defined(RGFW_OPENGL_ES3)
+ eglBindAPI(EGL_OPENGL_ES_API);
+ #else
+ eglBindAPI(EGL_OPENGL_API);
+ #endif
+
+ win->src.EGL_context = eglCreateContext(win->src.EGL_display, config, EGL_NO_CONTEXT, attribs);
+
+ if (win->src.EGL_context == NULL)
+ fprintf(stderr, "failed to create an EGL opengl context\n");
+
+ eglMakeCurrent(win->src.EGL_display, win->src.EGL_surface, win->src.EGL_surface, win->src.EGL_context);
+ eglSwapBuffers(win->src.EGL_display, win->src.EGL_surface);
+ }
+
+ void RGFW_window_makeCurrent_OpenGL(RGFW_window* win) {
+ eglMakeCurrent(win->src.EGL_display, win->src.EGL_surface, win->src.EGL_surface, win->src.EGL_context);
+ }
+
+ #ifdef RGFW_APPLE
+ void* RGFWnsglFramework = NULL;
+ #elif defined(RGFW_WINDOWS)
+ static HMODULE wglinstance = NULL;
+ #endif
+
+ void* RGFW_getProcAddress(const char* procname) {
+ #if defined(RGFW_WINDOWS)
+ void* proc = (void*) GetProcAddress(wglinstance, procname);
+
+ if (proc)
+ return proc;
+ #endif
+
+ return (void*) eglGetProcAddress(procname);
+ }
+
+ void RGFW_closeEGL(RGFW_window* win) {
+ eglDestroySurface(win->src.EGL_display, win->src.EGL_surface);
+ eglDestroyContext(win->src.EGL_display, win->src.EGL_context);
+
+ eglTerminate(win->src.EGL_display);
+ }
+
+ void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) {
+ assert(win != NULL);
+
+ eglSwapInterval(win->src.EGL_display, swapInterval);
+
+ }
+#endif /* RGFW_EGL */
+
+/*
+ end of RGFW_EGL defines
+*/
+
+/* OPENGL Normal / EGL defines only (no OS MESA) Ends here */
+
+#elif defined(RGFW_OSMESA) /* OSmesa only */
+RGFWDEF void RGFW_OSMesa_reorganize(void);
+
+/* reorganize buffer for osmesa */
+void RGFW_OSMesa_reorganize(void) {
+ u8* row = (u8*) RGFW_MALLOC(win->r.w * 3);
+
+ i32 half_height = win->r.h / 2;
+ i32 stride = win->r.w * 3;
+
+ i32 y;
+ for (y = 0; y < half_height; ++y) {
+ i32 top_offset = y * stride;
+ i32 bottom_offset = (win->r.h - y - 1) * stride;
+ memcpy(row, win->buffer + top_offset, stride);
+ memcpy(win->buffer + top_offset, win->buffer + bottom_offset, stride);
+ memcpy(win->buffer + bottom_offset, row, stride);
+ }
+
+ RGFW_FREE(row);
+}
+#endif /* RGFW_OSMesa */
+
+#endif /* RGFW_GL (OpenGL, EGL, OSMesa )*/
+
+/*
+This is where OS specific stuff starts
+*/
+
+
+#if defined(RGFW_WAYLAND) || defined(RGFW_X11)
+ int RGFW_eventWait_forceStop[] = {0, 0, 0}; /* for wait events */
+
+ #ifdef __linux__
+ #include
+ #include
+ #include
+
+ RGFW_Event* RGFW_linux_updateJoystick(RGFW_window* win) {
+ static int xAxis = 0, yAxis = 0;
+ u8 i;
+ for (i = 0; i < RGFW_joystickCount; i++) {
+ struct js_event e;
+
+
+ if (RGFW_joysticks[i] == 0)
+ continue;
+
+ i32 flags = fcntl(RGFW_joysticks[i], F_GETFL, 0);
+ fcntl(RGFW_joysticks[i], F_SETFL, flags | O_NONBLOCK);
+
+ ssize_t bytes;
+ while ((bytes = read(RGFW_joysticks[i], &e, sizeof(e))) > 0) {
+ switch (e.type) {
+ case JS_EVENT_BUTTON:
+ win->event.type = e.value ? RGFW_jsButtonPressed : RGFW_jsButtonReleased;
+ win->event.button = e.number;
+ RGFW_jsPressed[i][e.number] = e.value;
+ RGFW_jsButtonCallback(win, i, e.number, e.value);
+ return &win->event;
+ case JS_EVENT_AXIS:
+ ioctl(RGFW_joysticks[i], JSIOCGAXES, &win->event.axisesCount);
+
+ if ((e.number == 0 || e.number % 2) && e.number != 1)
+ xAxis = e.value;
+ else
+ yAxis = e.value;
+
+ win->event.axis[e.number / 2].x = xAxis;
+ win->event.axis[e.number / 2].y = yAxis;
+ win->event.type = RGFW_jsAxisMove;
+ win->event.joystick = i;
+ RGFW_jsAxisCallback(win, i, win->event.axis, win->event.axisesCount);
+ return &win->event;
+
+ default: break;
+ }
+ }
+ }
+
+ return NULL;
+ }
+
+ #endif
+#endif
+
+/*
+
+
+Start of Linux / Unix defines
+
+
+*/
+
+#ifdef RGFW_X11
+#ifndef RGFW_NO_X11_CURSOR
+#include
+#endif
+#include
+
+#ifndef RGFW_NO_DPI
+#include
+#include
+#endif
+
+#include
+#include
+#include
+#include
+
+#include /* for converting keycode to string */
+#include /* for hiding */
+#include
+#include
+#include
+
+#include /* for data limits (mainly used in drag and drop functions) */
+#include
+
+
+#ifdef __linux__
+#include
+#endif
+
+ u8 RGFW_mouseIconSrc[] = { XC_arrow, XC_left_ptr, XC_xterm, XC_crosshair, XC_hand2, XC_sb_h_double_arrow, XC_sb_v_double_arrow, XC_bottom_left_corner, XC_bottom_right_corner, XC_fleur, XC_X_cursor};
+ /*atoms needed for drag and drop*/
+ Atom XdndAware, XdndTypeList, XdndSelection, XdndEnter, XdndPosition, XdndStatus, XdndLeave, XdndDrop, XdndFinished, XdndActionCopy, XtextPlain, XtextUriList;
+
+ Atom wm_delete_window = 0;
+
+#if !defined(RGFW_NO_X11_CURSOR) && !defined(RGFW_NO_X11_CURSOR_PRELOAD)
+ typedef XcursorImage* (*PFN_XcursorImageCreate)(int, int);
+ typedef void (*PFN_XcursorImageDestroy)(XcursorImage*);
+ typedef Cursor(*PFN_XcursorImageLoadCursor)(Display*, const XcursorImage*);
+#endif
+#ifdef RGFW_OPENGL
+ typedef GLXContext(*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*);
+#endif
+
+#if !defined(RGFW_NO_X11_XI_PRELOAD)
+ typedef int (* PFN_XISelectEvents)(Display*,Window,XIEventMask*,int);
+ PFN_XISelectEvents XISelectEventsSrc = NULL;
+ #define XISelectEvents XISelectEventsSrc
+
+ void* X11Xihandle = NULL;
+#endif
+
+#if !defined(RGFW_NO_X11_CURSOR) && !defined(RGFW_NO_X11_CURSOR_PRELOAD)
+ PFN_XcursorImageLoadCursor XcursorImageLoadCursorSrc = NULL;
+ PFN_XcursorImageCreate XcursorImageCreateSrc = NULL;
+ PFN_XcursorImageDestroy XcursorImageDestroySrc = NULL;
+
+#define XcursorImageLoadCursor XcursorImageLoadCursorSrc
+#define XcursorImageCreate XcursorImageCreateSrc
+#define XcursorImageDestroy XcursorImageDestroySrc
+
+ void* X11Cursorhandle = NULL;
+#endif
+
+ u32 RGFW_windowsOpen = 0;
+
+#ifdef RGFW_OPENGL
+ void* RGFW_getProcAddress(const char* procname) { return (void*) glXGetProcAddress((GLubyte*) procname); }
+#endif
+
+ RGFWDEF void RGFW_init_buffer(RGFW_window* win, XVisualInfo* vi);
+ void RGFW_init_buffer(RGFW_window* win, XVisualInfo* vi) {
+#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER)
+ if (RGFW_bufferSize.w == 0 && RGFW_bufferSize.h == 0)
+ RGFW_bufferSize = RGFW_getScreenSize();
+
+ win->buffer = (u8*)RGFW_MALLOC(RGFW_bufferSize.w * RGFW_bufferSize.h * 4);
+
+ #ifdef RGFW_OSMESA
+ win->src.ctx = OSMesaCreateContext(OSMESA_RGBA, NULL);
+ OSMesaMakeCurrent(win->src.ctx, win->buffer, GL_UNSIGNED_BYTE, win->r.w, win->r.h);
+ #endif
+
+ win->src.bitmap = XCreateImage(
+ win->src.display, XDefaultVisual(win->src.display, vi->screen),
+ vi->depth,
+ ZPixmap, 0, NULL, RGFW_bufferSize.w, RGFW_bufferSize.h,
+ 32, 0
+ );
+
+ win->src.gc = XCreateGC(win->src.display, win->src.window, 0, NULL);
+
+ #else
+ RGFW_UNUSED(win); /*!< if buffer rendering is not being used */
+ RGFW_UNUSED(vi)
+ #endif
+ }
+
+
+
+ void RGFW_window_setBorder(RGFW_window* win, u8 border) {
+ static Atom _MOTIF_WM_HINTS = 0;
+ if (_MOTIF_WM_HINTS == 0 )
+ _MOTIF_WM_HINTS = XInternAtom(win->src.display, "_MOTIF_WM_HINTS", False);
+
+ struct __x11WindowHints {
+ unsigned long flags, functions, decorations, status;
+ long input_mode;
+ } hints;
+ hints.flags = (1L << 1);
+ hints.decorations = border;
+
+ XChangeProperty(
+ win->src.display, win->src.window,
+ _MOTIF_WM_HINTS, _MOTIF_WM_HINTS,
+ 32, PropModeReplace, (u8*)&hints, 5
+ );
+ }
+
+ void RGFW_releaseCursor(RGFW_window* win) {
+ XUngrabPointer(win->src.display, CurrentTime);
+
+ /* disable raw input */
+ unsigned char mask[] = { 0 };
+ XIEventMask em;
+ em.deviceid = XIAllMasterDevices;
+ em.mask_len = sizeof(mask);
+ em.mask = mask;
+
+ XISelectEvents(win->src.display, XDefaultRootWindow(win->src.display), &em, 1);
+ }
+
+ void RGFW_captureCursor(RGFW_window* win, RGFW_rect r) {
+ /* enable raw input */
+ unsigned char mask[XIMaskLen(XI_RawMotion)] = { 0 };
+ XISetMask(mask, XI_RawMotion);
+
+ XIEventMask em;
+ em.deviceid = XIAllMasterDevices;
+ em.mask_len = sizeof(mask);
+ em.mask = mask;
+
+ XISelectEvents(win->src.display, XDefaultRootWindow(win->src.display), &em, 1);
+
+ XGrabPointer(win->src.display, win->src.window, True, PointerMotionMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
+
+ RGFW_window_moveMouse(win, RGFW_POINT(win->r.x + (i32)(r.w / 2), win->r.y + (i32)(r.h / 2)));
+ }
+
+ RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, u16 args) {
+#if !defined(RGFW_NO_X11_CURSOR) && !defined(RGFW_NO_X11_CURSOR_PRELOAD)
+ if (X11Cursorhandle == NULL) {
+#if defined(__CYGWIN__)
+ X11Cursorhandle = dlopen("libXcursor-1.so", RTLD_LAZY | RTLD_LOCAL);
+#elif defined(__OpenBSD__) || defined(__NetBSD__)
+ X11Cursorhandle = dlopen("libXcursor.so", RTLD_LAZY | RTLD_LOCAL);
+#else
+ X11Cursorhandle = dlopen("libXcursor.so.1", RTLD_LAZY | RTLD_LOCAL);
+#endif
+
+ XcursorImageCreateSrc = (PFN_XcursorImageCreate) dlsym(X11Cursorhandle, "XcursorImageCreate");
+ XcursorImageDestroySrc = (PFN_XcursorImageDestroy) dlsym(X11Cursorhandle, "XcursorImageDestroy");
+ XcursorImageLoadCursorSrc = (PFN_XcursorImageLoadCursor) dlsym(X11Cursorhandle, "XcursorImageLoadCursor");
+ }
+#endif
+
+#if !defined(RGFW_NO_X11_XI_PRELOAD)
+ if (X11Xihandle == NULL) {
+#if defined(__CYGWIN__)
+ X11Xihandle = dlopen("libXi-6.so", RTLD_LAZY | RTLD_LOCAL);
+#elif defined(__OpenBSD__) || defined(__NetBSD__)
+ X11Xihandle = dlopen("libXi.so", RTLD_LAZY | RTLD_LOCAL);
+#else
+ X11Xihandle = dlopen("libXi.so.6", RTLD_LAZY | RTLD_LOCAL);
+#endif
+
+ XISelectEventsSrc = (PFN_XISelectEvents) dlsym(X11Xihandle, "XISelectEvents");
+ }
+#endif
+
+ XInitThreads(); /*!< init X11 threading*/
+
+ if (args & RGFW_OPENGL_SOFTWARE)
+ setenv("LIBGL_ALWAYS_SOFTWARE", "1", 1);
+
+ RGFW_window* win = RGFW_window_basic_init(rect, args);
+
+ u64 event_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | StructureNotifyMask | FocusChangeMask | LeaveWindowMask | EnterWindowMask | ExposureMask; /*!< X11 events accepted*/
+
+#ifdef RGFW_OPENGL
+ u32* visual_attribs = RGFW_initFormatAttribs(args & RGFW_OPENGL_SOFTWARE);
+ i32 fbcount;
+ GLXFBConfig* fbc = glXChooseFBConfig((Display*) win->src.display, DefaultScreen(win->src.display), (i32*) visual_attribs, &fbcount);
+
+ i32 best_fbc = -1;
+
+ if (fbcount == 0) {
+ printf("Failed to find any valid GLX visual configs\n");
+ return NULL;
+ }
+
+ u32 i;
+ for (i = 0; i < (u32)fbcount; i++) {
+ XVisualInfo* vi = glXGetVisualFromFBConfig((Display*) win->src.display, fbc[i]);
+ if (vi == NULL)
+ continue;
+
+ XFree(vi);
+
+ i32 samp_buf, samples;
+ glXGetFBConfigAttrib((Display*) win->src.display, fbc[i], GLX_SAMPLE_BUFFERS, &samp_buf);
+ glXGetFBConfigAttrib((Display*) win->src.display, fbc[i], GLX_SAMPLES, &samples);
+
+ if ((!(args & RGFW_TRANSPARENT_WINDOW) || vi->depth == 32) &&
+ (best_fbc < 0 || samp_buf) && (samples == RGFW_SAMPLES || best_fbc == -1)) {
+ best_fbc = i;
+ }
+ }
+
+ if (best_fbc == -1) {
+ printf("Failed to get a valid GLX visual\n");
+ return NULL;
+ }
+
+ GLXFBConfig bestFbc = fbc[best_fbc];
+
+ /* Get a visual */
+ XVisualInfo* vi = glXGetVisualFromFBConfig((Display*) win->src.display, bestFbc);
+
+ XFree(fbc);
+#else
+ XVisualInfo viNorm;
+
+ viNorm.visual = DefaultVisual((Display*) win->src.display, DefaultScreen((Display*) win->src.display));
+
+ viNorm.depth = 0;
+ XVisualInfo* vi = &viNorm;
+
+ XMatchVisualInfo((Display*) win->src.display, DefaultScreen((Display*) win->src.display), 32, TrueColor, vi); /*!< for RGBA backgrounds*/
+#endif
+ /* make X window attrubutes*/
+ XSetWindowAttributes swa;
+ Colormap cmap;
+
+ swa.colormap = cmap = XCreateColormap((Display*) win->src.display,
+ DefaultRootWindow(win->src.display),
+ vi->visual, AllocNone);
+
+ swa.background_pixmap = None;
+ swa.border_pixel = 0;
+ swa.event_mask = event_mask;
+
+ swa.background_pixel = 0;
+
+ /* create the window*/
+ win->src.window = XCreateWindow((Display*) win->src.display, DefaultRootWindow((Display*) win->src.display), win->r.x, win->r.y, win->r.w, win->r.h,
+ 0, vi->depth, InputOutput, vi->visual,
+ CWColormap | CWBorderPixel | CWBackPixel | CWEventMask, &swa);
+
+ XFreeColors((Display*) win->src.display, cmap, NULL, 0, 0);
+
+ #ifdef RGFW_OPENGL
+ XFree(vi);
+ #endif
+
+ // In your .desktop app, if you set the property
+ // StartupWMClass=RGFW that will assoicate the launcher icon
+ // with your application - robrohan
+
+ if (RGFW_className == NULL)
+ RGFW_className = (char*)name;
+
+ XClassHint *hint = XAllocClassHint();
+ assert(hint != NULL);
+ hint->res_class = (char*)RGFW_className;
+ hint->res_name = (char*)name; // just use the window name as the app name
+ XSetClassHint((Display*) win->src.display, win->src.window, hint);
+ XFree(hint);
+
+ if ((args & RGFW_NO_INIT_API) == 0) {
+#ifdef RGFW_OPENGL /* This is the second part of setting up opengl. This is where we ask OpenGL for a specific version. */
+ i32 context_attribs[7] = { 0, 0, 0, 0, 0, 0, 0 };
+ context_attribs[0] = GLX_CONTEXT_PROFILE_MASK_ARB;
+ if (RGFW_profile == RGFW_GL_CORE)
+ context_attribs[1] = GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
+ else
+ context_attribs[1] = GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
+
+ if (RGFW_majorVersion || RGFW_minorVersion) {
+ context_attribs[2] = GLX_CONTEXT_MAJOR_VERSION_ARB;
+ context_attribs[3] = RGFW_majorVersion;
+ context_attribs[4] = GLX_CONTEXT_MINOR_VERSION_ARB;
+ context_attribs[5] = RGFW_minorVersion;
+ }
+
+ glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0;
+ glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)
+ glXGetProcAddressARB((GLubyte*) "glXCreateContextAttribsARB");
+
+ GLXContext ctx = NULL;
+
+ if (RGFW_root != NULL)
+ ctx = RGFW_root->src.ctx;
+
+ win->src.ctx = glXCreateContextAttribsARB((Display*) win->src.display, bestFbc, ctx, True, context_attribs);
+#endif
+ if (RGFW_root == NULL)
+ RGFW_root = win;
+
+ RGFW_init_buffer(win, vi);
+ }
+
+
+ #ifndef RGFW_NO_MONITOR
+ if (args & RGFW_SCALE_TO_MONITOR)
+ RGFW_window_scaleToMonitor(win);
+ #endif
+
+ if (args & RGFW_CENTER) {
+ RGFW_area screenR = RGFW_getScreenSize();
+ RGFW_window_move(win, RGFW_POINT((screenR.w - win->r.w) / 2, (screenR.h - win->r.h) / 2));
+ }
+
+ if (args & RGFW_NO_RESIZE) { /* make it so the user can't resize the window*/
+ XSizeHints* sh = XAllocSizeHints();
+ sh->flags = (1L << 4) | (1L << 5);
+ sh->min_width = sh->max_width = win->r.w;
+ sh->min_height = sh->max_height = win->r.h;
+
+ XSetWMSizeHints((Display*) win->src.display, (Drawable) win->src.window, sh, XA_WM_NORMAL_HINTS);
+ XFree(sh);
+ }
+
+ if (args & RGFW_NO_BORDER) {
+ RGFW_window_setBorder(win, 0);
+ }
+
+ XSelectInput((Display*) win->src.display, (Drawable) win->src.window, event_mask); /*!< tell X11 what events we want*/
+
+ /* make it so the user can't close the window until the program does*/
+ if (wm_delete_window == 0)
+ wm_delete_window = XInternAtom((Display*) win->src.display, "WM_DELETE_WINDOW", False);
+
+ XSetWMProtocols((Display*) win->src.display, (Drawable) win->src.window, &wm_delete_window, 1);
+
+ /* connect the context to the window*/
+#ifdef RGFW_OPENGL
+ if ((args & RGFW_NO_INIT_API) == 0)
+ glXMakeCurrent((Display*) win->src.display, (Drawable) win->src.window, (GLXContext) win->src.ctx);
+#endif
+
+ /* set the background*/
+ XStoreName((Display*) win->src.display, (Drawable) win->src.window, name); /*!< set the name*/
+
+ XMapWindow((Display*) win->src.display, (Drawable) win->src.window); /* draw the window*/
+ XMoveWindow((Display*) win->src.display, (Drawable) win->src.window, win->r.x, win->r.y); /*!< move the window to it's proper cords*/
+
+ if (args & RGFW_ALLOW_DND) { /* init drag and drop atoms and turn on drag and drop for this window */
+ win->_winArgs |= RGFW_ALLOW_DND;
+
+ XdndTypeList = XInternAtom((Display*) win->src.display, "XdndTypeList", False);
+ XdndSelection = XInternAtom((Display*) win->src.display, "XdndSelection", False);
+
+ /* client messages */
+ XdndEnter = XInternAtom((Display*) win->src.display, "XdndEnter", False);
+ XdndPosition = XInternAtom((Display*) win->src.display, "XdndPosition", False);
+ XdndStatus = XInternAtom((Display*) win->src.display, "XdndStatus", False);
+ XdndLeave = XInternAtom((Display*) win->src.display, "XdndLeave", False);
+ XdndDrop = XInternAtom((Display*) win->src.display, "XdndDrop", False);
+ XdndFinished = XInternAtom((Display*) win->src.display, "XdndFinished", False);
+
+ /* actions */
+ XdndActionCopy = XInternAtom((Display*) win->src.display, "XdndActionCopy", False);
+
+ XtextUriList = XInternAtom((Display*) win->src.display, "text/uri-list", False);
+ XtextPlain = XInternAtom((Display*) win->src.display, "text/plain", False);
+
+ XdndAware = XInternAtom((Display*) win->src.display, "XdndAware", False);
+ const u8 version = 5;
+
+ XChangeProperty((Display*) win->src.display, (Window) win->src.window,
+ XdndAware, 4, 32,
+ PropModeReplace, &version, 1); /*!< turns on drag and drop */
+ }
+
+ #ifdef RGFW_EGL
+ if ((args & RGFW_NO_INIT_API) == 0)
+ RGFW_createOpenGLContext(win);
+ #endif
+
+ RGFW_window_setMouseDefault(win);
+
+ RGFW_windowsOpen++;
+
+ return win; /*return newly created window*/
+ }
+
+ RGFW_area RGFW_getScreenSize(void) {
+ assert(RGFW_root != NULL);
+
+ Screen* scrn = DefaultScreenOfDisplay((Display*) RGFW_root->src.display);
+ return RGFW_AREA(scrn->width, scrn->height);
+ }
+
+ RGFW_point RGFW_getGlobalMousePoint(void) {
+ assert(RGFW_root != NULL);
+
+ RGFW_point RGFWMouse;
+
+ i32 x, y;
+ u32 z;
+ Window window1, window2;
+ XQueryPointer((Display*) RGFW_root->src.display, XDefaultRootWindow((Display*) RGFW_root->src.display), &window1, &window2, &RGFWMouse.x, &RGFWMouse.y, &x, &y, &z);
+
+ return RGFWMouse;
+ }
+
+ RGFW_point RGFW_window_getMousePoint(RGFW_window* win) {
+ assert(win != NULL);
+
+ RGFW_point RGFWMouse;
+
+ i32 x, y;
+ u32 z;
+ Window window1, window2;
+ XQueryPointer((Display*) win->src.display, win->src.window, &window1, &window2, &x, &y, &RGFWMouse.x, &RGFWMouse.y, &z);
+
+ return RGFWMouse;
+ }
+
+ int xAxis = 0, yAxis = 0;
+
+ RGFW_Event* RGFW_window_checkEvent(RGFW_window* win) {
+ assert(win != NULL);
+
+ static struct {
+ long source, version;
+ i32 format;
+ } xdnd;
+
+ if (win->event.type == 0)
+ RGFW_resetKey();
+
+ if (win->event.type == RGFW_quit) {
+ return NULL;
+ }
+
+ win->event.type = 0;
+
+#ifdef __linux__
+ RGFW_Event* event = RGFW_linux_updateJoystick(win);
+ if (event != NULL)
+ return event;
+#endif
+
+ XPending(win->src.display);
+
+ XEvent E; /*!< raw X11 event */
+
+ /* if there is no unread qued events, get a new one */
+ if ((QLength(win->src.display) || XEventsQueued((Display*) win->src.display, QueuedAlready) + XEventsQueued((Display*) win->src.display, QueuedAfterReading))
+ && win->event.type != RGFW_quit
+ )
+ XNextEvent((Display*) win->src.display, &E);
+ else {
+ return NULL;
+ }
+
+ u32 i;
+ win->event.type = 0;
+
+
+ switch (E.type) {
+ case KeyPress:
+ case KeyRelease: {
+ win->event.repeat = RGFW_FALSE;
+ /* check if it's a real key release */
+ if (E.type == KeyRelease && XEventsQueued((Display*) win->src.display, QueuedAfterReading)) { /* get next event if there is one*/
+ XEvent NE;
+ XPeekEvent((Display*) win->src.display, &NE);
+
+ if (E.xkey.time == NE.xkey.time && E.xkey.keycode == NE.xkey.keycode) /* check if the current and next are both the same*/
+ win->event.repeat = RGFW_TRUE;
+ }
+
+ /* set event key data */
+ KeySym sym = (KeySym)XkbKeycodeToKeysym((Display*) win->src.display, E.xkey.keycode, 0, E.xkey.state & ShiftMask ? 1 : 0);
+ win->event.keyCode = RGFW_apiKeyCodeToRGFW(E.xkey.keycode);
+
+ char* str = (char*)XKeysymToString(sym);
+ if (str != NULL)
+ strncpy(win->event.keyName, str, 16);
+
+ win->event.keyName[15] = '\0';
+
+ RGFW_keyboard[win->event.keyCode].prev = RGFW_isPressed(win, win->event.keyCode);
+
+ /* get keystate data */
+ win->event.type = (E.type == KeyPress) ? RGFW_keyPressed : RGFW_keyReleased;
+
+ XKeyboardState keystate;
+ XGetKeyboardControl((Display*) win->src.display, &keystate);
+
+ RGFW_updateLockState(win, (keystate.led_mask & 1), (keystate.led_mask & 2));
+ RGFW_keyboard[win->event.keyCode].current = (E.type == KeyPress);
+ RGFW_keyCallback(win, win->event.keyCode, win->event.keyName, win->event.lockState, (E.type == KeyPress));
+ break;
+ }
+ case ButtonPress:
+ case ButtonRelease:
+ win->event.type = RGFW_mouseButtonPressed + (E.type == ButtonRelease); // the events match
+
+ switch(win->event.button) {
+ case RGFW_mouseScrollUp:
+ win->event.scroll = 1;
+ break;
+ case RGFW_mouseScrollDown:
+ win->event.scroll = -1;
+ break;
+ default: break;
+ }
+
+ win->event.button = E.xbutton.button;
+ RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current;
+
+ if (win->event.repeat == RGFW_FALSE)
+ win->event.repeat = RGFW_isPressed(win, win->event.keyCode);
+
+ RGFW_mouseButtons[win->event.button].current = (E.type == ButtonPress);
+ RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, (E.type == ButtonPress));
+ break;
+
+ case MotionNotify:
+ win->event.point.x = E.xmotion.x;
+ win->event.point.y = E.xmotion.y;
+
+ if ((win->_winArgs & RGFW_HOLD_MOUSE)) {
+ win->event.point.y = E.xmotion.y;
+
+ win->event.point.x = win->_lastMousePoint.x - abs(win->event.point.x);
+ win->event.point.y = win->_lastMousePoint.y - abs(win->event.point.y);
+ }
+
+ win->_lastMousePoint = RGFW_POINT(E.xmotion.x, E.xmotion.y);
+
+ win->event.type = RGFW_mousePosChanged;
+ RGFW_mousePosCallback(win, win->event.point);
+ break;
+
+ case GenericEvent: {
+ /* MotionNotify is used for mouse events if the mouse isn't held */
+ if (!(win->_winArgs & RGFW_HOLD_MOUSE)) {
+ XFreeEventData(win->src.display, &E.xcookie);
+ break;
+ }
+
+ XGetEventData(win->src.display, &E.xcookie);
+ if (E.xcookie.evtype == XI_RawMotion) {
+ XIRawEvent *raw = (XIRawEvent *)E.xcookie.data;
+ if (raw->valuators.mask_len == 0) {
+ XFreeEventData(win->src.display, &E.xcookie);
+ break;
+ }
+
+ double deltaX = 0.0f;
+ double deltaY = 0.0f;
+
+ /* check if relative motion data exists where we think it does */
+ if (XIMaskIsSet(raw->valuators.mask, 0) != 0)
+ deltaX += raw->raw_values[0];
+ if (XIMaskIsSet(raw->valuators.mask, 1) != 0)
+ deltaY += raw->raw_values[1];
+
+ win->event.point = RGFW_POINT((i32)deltaX, (i32)deltaY);
+
+ RGFW_window_moveMouse(win, RGFW_POINT(win->r.x + (win->r.w / 2), win->r.y + (win->r.h / 2)));
+
+ win->event.type = RGFW_mousePosChanged;
+ RGFW_mousePosCallback(win, win->event.point);
+ }
+
+ XFreeEventData(win->src.display, &E.xcookie);
+ break;
+ }
+
+ case Expose:
+ win->event.type = RGFW_windowRefresh;
+ RGFW_windowRefreshCallback(win);
+ break;
+
+ case ClientMessage:
+ /* if the client closed the window*/
+ if (E.xclient.data.l[0] == (i64) wm_delete_window) {
+ win->event.type = RGFW_quit;
+ RGFW_windowQuitCallback(win);
+ break;
+ }
+
+ /* reset DND values */
+ if (win->event.droppedFilesCount) {
+ for (i = 0; i < win->event.droppedFilesCount; i++)
+ win->event.droppedFiles[i][0] = '\0';
+ }
+
+ win->event.droppedFilesCount = 0;
+
+ if ((win->_winArgs & RGFW_ALLOW_DND) == 0)
+ break;
+
+ XEvent reply = { ClientMessage };
+ reply.xclient.window = xdnd.source;
+ reply.xclient.format = 32;
+ reply.xclient.data.l[0] = (long) win->src.window;
+ reply.xclient.data.l[1] = 0;
+ reply.xclient.data.l[2] = None;
+
+ if (E.xclient.message_type == XdndEnter) {
+ unsigned long count;
+ Atom* formats;
+ Atom real_formats[6];
+
+ Bool list = E.xclient.data.l[1] & 1;
+
+ xdnd.source = E.xclient.data.l[0];
+ xdnd.version = E.xclient.data.l[1] >> 24;
+ xdnd.format = None;
+
+ if (xdnd.version > 5)
+ break;
+
+ if (list) {
+ Atom actualType;
+ i32 actualFormat;
+ unsigned long bytesAfter;
+
+ XGetWindowProperty((Display*) win->src.display,
+ xdnd.source,
+ XdndTypeList,
+ 0,
+ LONG_MAX,
+ False,
+ 4,
+ &actualType,
+ &actualFormat,
+ &count,
+ &bytesAfter,
+ (u8**) &formats);
+ } else {
+ count = 0;
+
+ if (E.xclient.data.l[2] != None)
+ real_formats[count++] = E.xclient.data.l[2];
+ if (E.xclient.data.l[3] != None)
+ real_formats[count++] = E.xclient.data.l[3];
+ if (E.xclient.data.l[4] != None)
+ real_formats[count++] = E.xclient.data.l[4];
+
+ formats = real_formats;
+ }
+
+ unsigned long i;
+ for (i = 0; i < count; i++) {
+ if (formats[i] == XtextUriList || formats[i] == XtextPlain) {
+ xdnd.format = formats[i];
+ break;
+ }
+ }
+
+ if (list) {
+ XFree(formats);
+ }
+
+ break;
+ }
+ if (E.xclient.message_type == XdndPosition) {
+ const i32 xabs = (E.xclient.data.l[2] >> 16) & 0xffff;
+ const i32 yabs = (E.xclient.data.l[2]) & 0xffff;
+ Window dummy;
+ i32 xpos, ypos;
+
+ if (xdnd.version > 5)
+ break;
+
+ XTranslateCoordinates((Display*) win->src.display,
+ XDefaultRootWindow((Display*) win->src.display),
+ (Window) win->src.window,
+ xabs, yabs,
+ &xpos, &ypos,
+ &dummy);
+
+ win->event.point.x = xpos;
+ win->event.point.y = ypos;
+
+ reply.xclient.window = xdnd.source;
+ reply.xclient.message_type = XdndStatus;
+
+ if (xdnd.format) {
+ reply.xclient.data.l[1] = 1;
+ if (xdnd.version >= 2)
+ reply.xclient.data.l[4] = XdndActionCopy;
+ }
+
+ XSendEvent((Display*) win->src.display, xdnd.source, False, NoEventMask, &reply);
+ XFlush((Display*) win->src.display);
+ break;
+ }
+
+ if (E.xclient.message_type != XdndDrop)
+ break;
+
+ if (xdnd.version > 5)
+ break;
+
+ win->event.type = RGFW_dnd_init;
+
+ if (xdnd.format) {
+ Time time = CurrentTime;
+
+ if (xdnd.version >= 1)
+ time = E.xclient.data.l[2];
+
+ XConvertSelection((Display*) win->src.display,
+ XdndSelection,
+ xdnd.format,
+ XdndSelection,
+ (Window) win->src.window,
+ time);
+ } else if (xdnd.version >= 2) {
+ XEvent reply = { ClientMessage };
+
+ XSendEvent((Display*) win->src.display, xdnd.source,
+ False, NoEventMask, &reply);
+ XFlush((Display*) win->src.display);
+ }
+
+ RGFW_dndInitCallback(win, win->event.point);
+ break;
+ case SelectionNotify: {
+ /* this is only for checking for xdnd drops */
+ if (E.xselection.property != XdndSelection || !(win->_winArgs | RGFW_ALLOW_DND))
+ break;
+
+ char* data;
+ unsigned long result;
+
+ Atom actualType;
+ i32 actualFormat;
+ unsigned long bytesAfter;
+
+ XGetWindowProperty((Display*) win->src.display, E.xselection.requestor, E.xselection.property, 0, LONG_MAX, False, E.xselection.target, &actualType, &actualFormat, &result, &bytesAfter, (u8**) &data);
+
+ if (result == 0)
+ break;
+
+ /*
+ SOURCED FROM GLFW _glfwParseUriList
+ Copyright (c) 2002-2006 Marcus Geelnard
+ Copyright (c) 2006-2019 Camilla Löwy
+ */
+
+ const char* prefix = (const char*)"file://";
+
+ char* line;
+
+ win->event.droppedFilesCount = 0;
+
+ win->event.type = RGFW_dnd;
+
+ while ((line = strtok(data, "\r\n"))) {
+ char path[RGFW_MAX_PATH];
+
+ data = NULL;
+
+ if (line[0] == '#')
+ continue;
+
+ char* l;
+ for (l = line; 1; l++) {
+ if ((l - line) > 7)
+ break;
+ else if (*l != prefix[(l - line)])
+ break;
+ else if (*l == '\0' && prefix[(l - line)] == '\0') {
+ line += 7;
+ while (*line != '/')
+ line++;
+ break;
+ } else if (*l == '\0')
+ break;
+ }
+
+ win->event.droppedFilesCount++;
+
+ size_t index = 0;
+ while (*line) {
+ if (line[0] == '%' && line[1] && line[2]) {
+ const char digits[3] = { line[1], line[2], '\0' };
+ path[index] = (char) strtol(digits, NULL, 16);
+ line += 2;
+ } else
+ path[index] = *line;
+
+ index++;
+ line++;
+ }
+ path[index] = '\0';
+ strncpy(win->event.droppedFiles[win->event.droppedFilesCount - 1], path, index + 1);
+ }
+
+ if (data)
+ XFree(data);
+
+ if (xdnd.version >= 2) {
+ reply.xclient.message_type = XdndFinished;
+ reply.xclient.data.l[1] = result;
+ reply.xclient.data.l[2] = XdndActionCopy;
+
+ XSendEvent((Display*) win->src.display, xdnd.source, False, NoEventMask, &reply);
+ XFlush((Display*) win->src.display);
+ }
+
+ RGFW_dndCallback(win, win->event.droppedFiles, win->event.droppedFilesCount);
+ break;
+ }
+ case FocusIn:
+ win->event.inFocus = 1;
+ win->event.type = RGFW_focusIn;
+ RGFW_focusCallback(win, 1);
+ break;
+
+ break;
+ case FocusOut:
+ win->event.inFocus = 0;
+ win->event.type = RGFW_focusOut;
+ RGFW_focusCallback(win, 0);
+ break;
+
+ case EnterNotify: {
+ win->event.type = RGFW_mouseEnter;
+ win->event.point.x = E.xcrossing.x;
+ win->event.point.y = E.xcrossing.y;
+ RGFW_mouseNotifyCallBack(win, win->event.point, 1);
+ break;
+ }
+
+ case LeaveNotify: {
+ win->event.type = RGFW_mouseLeave;
+ RGFW_mouseNotifyCallBack(win, win->event.point, 0);
+ break;
+ }
+
+ case ConfigureNotify: {
+ /* detect resize */
+ if (E.xconfigure.width != win->r.w || E.xconfigure.height != win->r.h) {
+ win->event.type = RGFW_windowResized;
+ win->r = RGFW_RECT(win->r.x, win->r.y, E.xconfigure.width, E.xconfigure.height);
+ RGFW_windowResizeCallback(win, win->r);
+ break;
+ }
+
+ /* detect move */
+ if (E.xconfigure.x != win->r.x || E.xconfigure.y != win->r.y) {
+ win->event.type = RGFW_windowMoved;
+ win->r = RGFW_RECT(E.xconfigure.x, E.xconfigure.y, win->r.w, win->r.h);
+ RGFW_windowMoveCallback(win, win->r);
+ break;
+ }
+
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+
+ XFlush((Display*) win->src.display);
+
+ if (win->event.type)
+ return &win->event;
+ else
+ return NULL;
+ }
+
+ void RGFW_window_move(RGFW_window* win, RGFW_point v) {
+ assert(win != NULL);
+ win->r.x = v.x;
+ win->r.y = v.y;
+
+ XMoveWindow((Display*) win->src.display, (Window) win->src.window, v.x, v.y);
+ }
+
+
+ void RGFW_window_resize(RGFW_window* win, RGFW_area a) {
+ assert(win != NULL);
+ win->r.w = a.w;
+ win->r.h = a.h;
+
+ XResizeWindow((Display*) win->src.display, (Window) win->src.window, a.w, a.h);
+ }
+
+ void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a) {
+ assert(win != NULL);
+
+ if (a.w == 0 && a.h == 0)
+ return;
+
+ XSizeHints hints;
+ long flags;
+
+ XGetWMNormalHints(win->src.display, (Window) win->src.window, &hints, &flags);
+
+ hints.flags |= PMinSize;
+
+ hints.min_width = a.w;
+ hints.min_height = a.h;
+
+ XSetWMNormalHints(win->src.display, (Window) win->src.window, &hints);
+ }
+
+ void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a) {
+ assert(win != NULL);
+
+ if (a.w == 0 && a.h == 0)
+ return;
+
+ XSizeHints hints;
+ long flags;
+
+ XGetWMNormalHints(win->src.display, (Window) win->src.window, &hints, &flags);
+
+ hints.flags |= PMaxSize;
+
+ hints.max_width = a.w;
+ hints.max_height = a.h;
+
+ XSetWMNormalHints(win->src.display, (Window) win->src.window, &hints);
+ }
+
+
+ void RGFW_window_minimize(RGFW_window* win) {
+ assert(win != NULL);
+
+ XIconifyWindow(win->src.display, (Window) win->src.window, DefaultScreen(win->src.display));
+ XFlush(win->src.display);
+ }
+
+ void RGFW_window_restore(RGFW_window* win) {
+ assert(win != NULL);
+
+ XMapWindow(win->src.display, (Window) win->src.window);
+ XFlush(win->src.display);
+ }
+
+ void RGFW_window_setName(RGFW_window* win, char* name) {
+ assert(win != NULL);
+
+ XStoreName((Display*) win->src.display, (Window) win->src.window, name);
+ }
+
+ void* RGFW_libxshape = NULL;
+
+ #ifndef RGFW_NO_PASSTHROUGH
+ void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough) {
+ assert(win != NULL);
+
+ #if defined(__CYGWIN__)
+ RGFW_libxshape = dlopen("libXext-6.so", RTLD_LAZY | RTLD_LOCAL);
+ #elif defined(__OpenBSD__) || defined(__NetBSD__)
+ RGFW_libxshape = dlopen("libXext.so", RTLD_LAZY | RTLD_LOCAL);
+ #else
+ RGFW_libxshape = dlopen("libXext.so.6", RTLD_LAZY | RTLD_LOCAL);
+ #endif
+
+ typedef void (* PFN_XShapeCombineMask)(Display*,Window,int,int,int,Pixmap,int);
+ static PFN_XShapeCombineMask XShapeCombineMask;
+
+ typedef void (* PFN_XShapeCombineRegion)(Display*,Window,int,int,int,Region,int);
+ static PFN_XShapeCombineRegion XShapeCombineRegion;
+
+ if (XShapeCombineMask != NULL)
+ XShapeCombineMask = (PFN_XShapeCombineMask) dlsym(RGFW_libxshape, "XShapeCombineMask");
+
+ if (XShapeCombineRegion != NULL)
+ XShapeCombineRegion = (PFN_XShapeCombineRegion) dlsym(RGFW_libxshape, "XShapeCombineMask");
+
+ if (passthrough) {
+ Region region = XCreateRegion();
+ XShapeCombineRegion(win->src.display, win->src.window, ShapeInput, 0, 0, region, ShapeSet);
+ XDestroyRegion(region);
+
+ return;
+ }
+
+ XShapeCombineMask(win->src.display, win->src.window, ShapeInput, 0, 0, None, ShapeSet);
+ }
+ #endif
+
+ /*
+ the majority function is sourced from GLFW
+ */
+
+ void RGFW_window_setIcon(RGFW_window* win, u8* icon, RGFW_area a, i32 channels) {
+ assert(win != NULL);
+
+ i32 longCount = 2 + a.w * a.h;
+
+ u64* X11Icon = (u64*) RGFW_MALLOC(longCount * sizeof(u64));
+ u64* target = X11Icon;
+
+ *target++ = a.w;
+ *target++ = a.h;
+
+ u32 i;
+
+ for (i = 0; i < a.w * a.h; i++) {
+ if (channels == 3)
+ *target++ = ((icon[i * 3 + 0]) << 16) |
+ ((icon[i * 3 + 1]) << 8) |
+ ((icon[i * 3 + 2]) << 0) |
+ (0xFF << 24);
+
+ else if (channels == 4)
+ *target++ = ((icon[i * 4 + 0]) << 16) |
+ ((icon[i * 4 + 1]) << 8) |
+ ((icon[i * 4 + 2]) << 0) |
+ ((icon[i * 4 + 3]) << 24);
+ }
+
+ static Atom NET_WM_ICON = 0;
+ if (NET_WM_ICON == 0)
+ NET_WM_ICON = XInternAtom((Display*) win->src.display, "_NET_WM_ICON", False);
+
+ XChangeProperty((Display*) win->src.display, (Window) win->src.window,
+ NET_WM_ICON,
+ 6, 32,
+ PropModeReplace,
+ (u8*) X11Icon,
+ longCount);
+
+ RGFW_FREE(X11Icon);
+
+ XFlush((Display*) win->src.display);
+ }
+
+ void RGFW_window_setMouse(RGFW_window* win, u8* image, RGFW_area a, i32 channels) {
+ assert(win != NULL);
+
+#ifndef RGFW_NO_X11_CURSOR
+ XcursorImage* native = XcursorImageCreate(a.w, a.h);
+ native->xhot = 0;
+ native->yhot = 0;
+
+ u8* source = (u8*) image;
+ XcursorPixel* target = native->pixels;
+
+ u32 i;
+ for (i = 0; i < a.w * a.h; i++, target++, source += 4) {
+ u8 alpha = 0xFF;
+ if (channels == 4)
+ alpha = source[3];
+
+ *target = (alpha << 24) | (((source[0] * alpha) / 255) << 16) | (((source[1] * alpha) / 255) << 8) | (((source[2] * alpha) / 255) << 0);
+ }
+
+ Cursor cursor = XcursorImageLoadCursor((Display*) win->src.display, native);
+ XDefineCursor((Display*) win->src.display, (Window) win->src.window, (Cursor) cursor);
+
+ XFreeCursor((Display*) win->src.display, (Cursor) cursor);
+ XcursorImageDestroy(native);
+#else
+ RGFW_UNUSED(image) RGFW_UNUSED(a.w) RGFW_UNUSED(channels)
+#endif
+ }
+
+ void RGFW_window_moveMouse(RGFW_window* win, RGFW_point v) {
+ assert(win != NULL);
+
+ XEvent event;
+ XQueryPointer(win->src.display, DefaultRootWindow(win->src.display),
+ &event.xbutton.root, &event.xbutton.window,
+ &event.xbutton.x_root, &event.xbutton.y_root,
+ &event.xbutton.x, &event.xbutton.y,
+ &event.xbutton.state);
+
+ if (event.xbutton.x == v.x && event.xbutton.y == v.y)
+ return;
+
+ XWarpPointer(win->src.display, None, win->src.window, 0, 0, 0, 0, (int) v.x - win->r.x, (int) v.y - win->r.y);
+ }
+
+ RGFWDEF void RGFW_window_disableMouse(RGFW_window* win) {
+ RGFW_UNUSED(win);
+ }
+
+ void RGFW_window_setMouseDefault(RGFW_window* win) {
+ RGFW_window_setMouseStandard(win, RGFW_MOUSE_ARROW);
+ }
+
+ void RGFW_window_setMouseStandard(RGFW_window* win, u8 mouse) {
+ assert(win != NULL);
+
+ if (mouse > (sizeof(RGFW_mouseIconSrc) / sizeof(u8)))
+ return;
+
+ mouse = RGFW_mouseIconSrc[mouse];
+
+ Cursor cursor = XCreateFontCursor((Display*) win->src.display, mouse);
+ XDefineCursor((Display*) win->src.display, (Window) win->src.window, (Cursor) cursor);
+
+ XFreeCursor((Display*) win->src.display, (Cursor) cursor);
+ }
+
+ void RGFW_window_hide(RGFW_window* win) {
+ XMapWindow(win->src.display, win->src.window);
+ }
+
+ void RGFW_window_show(RGFW_window* win) {
+ XUnmapWindow(win->src.display, win->src.window);
+ }
+
+ /*
+ the majority function is sourced from GLFW
+ */
+ char* RGFW_readClipboard(size_t* size) {
+ static Atom UTF8 = 0;
+ if (UTF8 == 0)
+ UTF8 = XInternAtom(RGFW_root->src.display, "UTF8_STRING", True);
+
+ XEvent event;
+ int format;
+ unsigned long N, sizeN;
+ char* data, * s = NULL;
+ Atom target;
+ Atom CLIPBOARD = 0, XSEL_DATA = 0;
+
+ if (CLIPBOARD == 0) {
+ CLIPBOARD = XInternAtom(RGFW_root->src.display, "CLIPBOARD", 0);
+ XSEL_DATA = XInternAtom(RGFW_root->src.display, "XSEL_DATA", 0);
+ }
+
+ XConvertSelection(RGFW_root->src.display, CLIPBOARD, UTF8, XSEL_DATA, RGFW_root->src.window, CurrentTime);
+ XSync(RGFW_root->src.display, 0);
+ XNextEvent(RGFW_root->src.display, &event);
+
+ if (event.type != SelectionNotify || event.xselection.selection != CLIPBOARD || event.xselection.property == 0)
+ return NULL;
+
+ XGetWindowProperty(event.xselection.display, event.xselection.requestor,
+ event.xselection.property, 0L, (~0L), 0, AnyPropertyType, &target,
+ &format, &sizeN, &N, (unsigned char**) &data);
+
+ if (target == UTF8 || target == XA_STRING) {
+ s = (char*)RGFW_MALLOC(sizeof(char) * sizeN);
+ strncpy(s, data, sizeN);
+ s[sizeN] = '\0';
+ XFree(data);
+ }
+
+ XDeleteProperty(event.xselection.display, event.xselection.requestor, event.xselection.property);
+
+ if (s != NULL && size != NULL)
+ *size = sizeN;
+
+ return s;
+ }
+
+ /*
+ almost all of this function is sourced from GLFW
+ */
+ void RGFW_writeClipboard(const char* text, u32 textLen) {
+ static Atom CLIPBOARD = 0,
+ UTF8_STRING = 0,
+ SAVE_TARGETS = 0,
+ TARGETS = 0,
+ MULTIPLE = 0,
+ ATOM_PAIR = 0,
+ CLIPBOARD_MANAGER = 0;
+
+ if (CLIPBOARD == 0) {
+ CLIPBOARD = XInternAtom((Display*) RGFW_root->src.display, "CLIPBOARD", False);
+ UTF8_STRING = XInternAtom((Display*) RGFW_root->src.display, "UTF8_STRING", False);
+ SAVE_TARGETS = XInternAtom((Display*) RGFW_root->src.display, "SAVE_TARGETS", False);
+ TARGETS = XInternAtom((Display*) RGFW_root->src.display, "TARGETS", False);
+ MULTIPLE = XInternAtom((Display*) RGFW_root->src.display, "MULTIPLE", False);
+ ATOM_PAIR = XInternAtom((Display*) RGFW_root->src.display, "ATOM_PAIR", False);
+ CLIPBOARD_MANAGER = XInternAtom((Display*) RGFW_root->src.display, "CLIPBOARD_MANAGER", False);
+ }
+
+ XSetSelectionOwner((Display*) RGFW_root->src.display, CLIPBOARD, (Window) RGFW_root->src.window, CurrentTime);
+
+ XConvertSelection((Display*) RGFW_root->src.display, CLIPBOARD_MANAGER, SAVE_TARGETS, None, (Window) RGFW_root->src.window, CurrentTime);
+ for (;;) {
+ XEvent event;
+
+ XNextEvent((Display*) RGFW_root->src.display, &event);
+ if (event.type != SelectionRequest) {
+ break;
+ }
+
+ const XSelectionRequestEvent* request = &event.xselectionrequest;
+
+ XEvent reply = { SelectionNotify };
+ reply.xselection.property = 0;
+
+ if (request->target == TARGETS) {
+ const Atom targets[] = { TARGETS,
+ MULTIPLE,
+ UTF8_STRING,
+ XA_STRING };
+
+ XChangeProperty((Display*) RGFW_root->src.display,
+ request->requestor,
+ request->property,
+ 4,
+ 32,
+ PropModeReplace,
+ (u8*) targets,
+ sizeof(targets) / sizeof(targets[0]));
+
+ reply.xselection.property = request->property;
+ }
+
+ if (request->target == MULTIPLE) {
+ Atom* targets = NULL;
+
+ Atom actualType = 0;
+ int actualFormat = 0;
+ unsigned long count = 0, bytesAfter = 0;
+
+ XGetWindowProperty((Display*) RGFW_root->src.display, request->requestor, request->property, 0, LONG_MAX, False, ATOM_PAIR, &actualType, &actualFormat, &count, &bytesAfter, (u8**) &targets);
+
+ unsigned long i;
+ for (i = 0; i < (u32)count; i += 2) {
+ if (targets[i] == UTF8_STRING || targets[i] == XA_STRING) {
+ XChangeProperty((Display*) RGFW_root->src.display,
+ request->requestor,
+ targets[i + 1],
+ targets[i],
+ 8,
+ PropModeReplace,
+ (u8*) text,
+ textLen);
+ XFlush(RGFW_root->src.display);
+ } else {
+ targets[i + 1] = None;
+ }
+ }
+
+ XChangeProperty((Display*) RGFW_root->src.display,
+ request->requestor,
+ request->property,
+ ATOM_PAIR,
+ 32,
+ PropModeReplace,
+ (u8*) targets,
+ count);
+
+ XFlush(RGFW_root->src.display);
+ XFree(targets);
+
+ reply.xselection.property = request->property;
+ }
+
+ reply.xselection.display = request->display;
+ reply.xselection.requestor = request->requestor;
+ reply.xselection.selection = request->selection;
+ reply.xselection.target = request->target;
+ reply.xselection.time = request->time;
+
+ XSendEvent((Display*) RGFW_root->src.display, request->requestor, False, 0, &reply);
+ XFlush(RGFW_root->src.display);
+ }
+ }
+
+ u8 RGFW_window_isFullscreen(RGFW_window* win) {
+ assert(win != NULL);
+
+ XWindowAttributes windowAttributes;
+ XGetWindowAttributes(win->src.display, (Window) win->src.window, &windowAttributes);
+
+ /* check if the window is visable */
+ if (windowAttributes.map_state != IsViewable)
+ return 0;
+
+ /* check if the window covers the full screen */
+ return (windowAttributes.x == 0 && windowAttributes.y == 0 &&
+ windowAttributes.width == XDisplayWidth(win->src.display, DefaultScreen(win->src.display)) &&
+ windowAttributes.height == XDisplayHeight(win->src.display, DefaultScreen(win->src.display)));
+ }
+
+ u8 RGFW_window_isHidden(RGFW_window* win) {
+ assert(win != NULL);
+
+ XWindowAttributes windowAttributes;
+ XGetWindowAttributes(win->src.display, (Window) win->src.window, &windowAttributes);
+
+ return (windowAttributes.map_state == IsUnmapped && !RGFW_window_isMinimized(win));
+ }
+
+ u8 RGFW_window_isMinimized(RGFW_window* win) {
+ assert(win != NULL);
+
+ static Atom prop = 0;
+ if (prop == 0)
+ prop = XInternAtom(win->src.display, "WM_STATE", False);
+
+ Atom actual_type;
+ i32 actual_format;
+ unsigned long nitems, bytes_after;
+ unsigned char* prop_data;
+
+ i16 status = XGetWindowProperty(win->src.display, (Window) win->src.window, prop, 0, 2, False,
+ AnyPropertyType, &actual_type, &actual_format,
+ &nitems, &bytes_after, &prop_data);
+
+ if (status == Success && nitems >= 1 && *((int*) prop_data) == IconicState) {
+ XFree(prop_data);
+ return 1;
+ }
+
+ if (prop_data != NULL)
+ XFree(prop_data);
+
+ return 0;
+ }
+
+ u8 RGFW_window_isMaximized(RGFW_window* win) {
+ assert(win != NULL);
+
+ static Atom net_wm_state = 0;
+ static Atom net_wm_state_maximized_horz = 0;
+ static Atom net_wm_state_maximized_vert = 0;
+
+ if (net_wm_state == 0) {
+ net_wm_state = XInternAtom(win->src.display, "_NET_WM_STATE", False);
+ net_wm_state_maximized_vert = XInternAtom(win->src.display, "_NET_WM_STATE_MAXIMIZED_VERT", False);
+ net_wm_state_maximized_horz = XInternAtom(win->src.display, "_NET_WM_STATE_MAXIMIZED_HORZ", False);
+ }
+
+ Atom actual_type;
+ i32 actual_format;
+ unsigned long nitems, bytes_after;
+ unsigned char* prop_data;
+
+ i16 status = XGetWindowProperty(win->src.display, (Window) win->src.window, net_wm_state, 0, 1024, False,
+ XA_ATOM, &actual_type, &actual_format,
+ &nitems, &bytes_after, &prop_data);
+
+ if (status != Success) {
+ if (prop_data != NULL)
+ XFree(prop_data);
+
+ return 0;
+ }
+
+ Atom* atoms = (Atom*) prop_data;
+ u64 i;
+ for (i = 0; i < nitems; ++i) {
+ if (atoms[i] == net_wm_state_maximized_horz ||
+ atoms[i] == net_wm_state_maximized_vert) {
+ XFree(prop_data);
+ return 1;
+ }
+ }
+
+ return 0;
+ }
+
+ static void XGetSystemContentScale(Display* display, float* xscale, float* yscale) {
+ float xdpi = 96.f, ydpi = 96.f;
+
+#ifndef RGFW_NO_DPI
+ char* rms = XResourceManagerString(display);
+ XrmDatabase db = NULL;
+
+ if (rms && db)
+ db = XrmGetStringDatabase(rms);
+
+ if (db == 0) {
+ *xscale = xdpi / 96.f;
+ *yscale = ydpi / 96.f;
+ return;
+ }
+
+ XrmValue value;
+ char* type = NULL;
+
+ if (XrmGetResource(db, "Xft.dpi", "Xft.Dpi", &type, &value) && type && strncmp(type, "String", 7) == 0)
+ xdpi = ydpi = atof(value.addr);
+ XrmDestroyDatabase(db);
+#endif
+
+ * xscale = xdpi / 96.f;
+ *yscale = ydpi / 96.f;
+ }
+
+ RGFW_monitor RGFW_XCreateMonitor(i32 screen) {
+ RGFW_monitor monitor;
+
+ Display* display = XOpenDisplay(NULL);
+
+ RGFW_area size = RGFW_getScreenSize();
+
+ monitor.rect = RGFW_RECT(0, 0, size.w, size.h);
+ monitor.physW = DisplayWidthMM(display, screen);
+ monitor.physH = DisplayHeightMM(display, screen);
+
+ XGetSystemContentScale(display, &monitor.scaleX, &monitor.scaleY);
+ XRRScreenResources* sr = XRRGetScreenResourcesCurrent(display, RootWindow(display, screen));
+
+ XRRCrtcInfo* ci = NULL;
+ int crtc = screen;
+
+ if (sr->ncrtc > crtc) {
+ ci = XRRGetCrtcInfo(display, sr, sr->crtcs[crtc]);
+ }
+
+ if (ci == NULL) {
+ float dpi_width = round((double)monitor.rect.w/(((double)monitor.physW)/25.4));
+ float dpi_height = round((double)monitor.rect.h/(((double)monitor.physH)/25.4));
+
+ monitor.scaleX = (float) (dpi_width) / (float) 96;
+ monitor.scaleY = (float) (dpi_height) / (float) 96;
+ XRRFreeScreenResources(sr);
+ XCloseDisplay(display);
+ return monitor;
+ }
+
+ XRROutputInfo* info = XRRGetOutputInfo (display, sr, sr->outputs[screen]);
+ monitor.physW = info->mm_width;
+ monitor.physH = info->mm_height;
+
+ monitor.rect.x = ci->x;
+ monitor.rect.y = ci->y;
+ monitor.rect.w = ci->width;
+ monitor.rect.h = ci->height;
+
+ float dpi_width = round((double)monitor.rect.w/(((double)monitor.physW)/25.4));
+ float dpi_height = round((double)monitor.rect.h/(((double)monitor.physH)/25.4));
+
+ monitor.scaleX = (float) (dpi_width) / (float) 96;
+ monitor.scaleY = (float) (dpi_height) / (float) 96;
+
+ if (monitor.scaleX > 1 && monitor.scaleX < 1.1)
+ monitor.scaleX = 1;
+
+ if (monitor.scaleY > 1 && monitor.scaleY < 1.1)
+ monitor.scaleY = 1;
+
+ XRRFreeCrtcInfo(ci);
+ XRRFreeScreenResources(sr);
+
+ XCloseDisplay(display);
+
+ return monitor;
+ }
+
+ RGFW_monitor RGFW_monitors[6];
+ RGFW_monitor* RGFW_getMonitors(void) {
+ size_t i;
+ for (i = 0; i < (size_t)ScreenCount(RGFW_root->src.display) && i < 6; i++)
+ RGFW_monitors[i] = RGFW_XCreateMonitor(i);
+
+ return RGFW_monitors;
+ }
+
+ RGFW_monitor RGFW_getPrimaryMonitor(void) {
+ assert(RGFW_root != NULL);
+
+ i32 primary = -1;
+ Window root = DefaultRootWindow(RGFW_root->src.display);
+ XRRScreenResources* res = XRRGetScreenResources(RGFW_root->src.display, root);
+
+ for (int i = 0; i < res->noutput; i++) {
+ XRROutputInfo* output_info = XRRGetOutputInfo(RGFW_root->src.display, res, res->outputs[i]);
+ if (output_info->connection == RR_Connected && output_info->crtc) {
+ XRRCrtcInfo* crtc_info = XRRGetCrtcInfo(RGFW_root->src.display, res, output_info->crtc);
+ if (crtc_info->mode != None && crtc_info->x == 0 && crtc_info->y == 0) {
+ primary = i;
+ XRRFreeCrtcInfo(crtc_info);
+ XRRFreeOutputInfo(output_info);
+ break;
+ }
+ XRRFreeCrtcInfo(crtc_info);
+ }
+ XRRFreeOutputInfo(output_info);
+ }
+
+ XRRFreeScreenResources(res);
+
+ return RGFW_XCreateMonitor(primary);
+ }
+
+ RGFW_monitor RGFW_window_getMonitor(RGFW_window* win) {
+ return RGFW_XCreateMonitor(DefaultScreen(win->src.display));
+ }
+
+ #ifdef RGFW_OPENGL
+ void RGFW_window_makeCurrent_OpenGL(RGFW_window* win) {
+ if (win == NULL)
+ glXMakeCurrent((Display*) NULL, (Drawable)NULL, (GLXContext) NULL);
+ else
+ glXMakeCurrent((Display*) win->src.display, (Drawable) win->src.window, (GLXContext) win->src.ctx);
+ }
+ #endif
+
+
+ void RGFW_window_swapBuffers(RGFW_window* win) {
+ assert(win != NULL);
+
+ /* clear the window*/
+ if (!(win->_winArgs & RGFW_NO_CPU_RENDER)) {
+#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER)
+ #ifdef RGFW_OSMESA
+ RGFW_OSMesa_reorganize();
+ #endif
+ RGFW_area area = RGFW_bufferSize;
+
+#ifndef RGFW_X11_DONT_CONVERT_BGR
+ win->src.bitmap->data = (char*) win->buffer;
+ u32 x, y;
+ for (y = 0; y < (u32)win->r.h; y++) {
+ for (x = 0; x < (u32)win->r.w; x++) {
+ u32 index = (y * 4 * area.w) + x * 4;
+
+ u8 red = win->src.bitmap->data[index];
+ win->src.bitmap->data[index] = win->buffer[index + 2];
+ win->src.bitmap->data[index + 2] = red;
+
+ }
+ }
+#endif
+ XPutImage(win->src.display, (Window) win->src.window, win->src.gc, win->src.bitmap, 0, 0, 0, 0, RGFW_bufferSize.w, RGFW_bufferSize.h);
+#endif
+ }
+
+ if (!(win->_winArgs & RGFW_NO_GPU_RENDER)) {
+ #ifdef RGFW_EGL
+ eglSwapBuffers(win->src.EGL_display, win->src.EGL_surface);
+ #elif defined(RGFW_OPENGL)
+ glXSwapBuffers((Display*) win->src.display, (Window) win->src.window);
+ #endif
+ }
+ }
+
+ #if !defined(RGFW_EGL)
+ void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) {
+ assert(win != NULL);
+
+ #if defined(RGFW_OPENGL)
+ ((PFNGLXSWAPINTERVALEXTPROC) glXGetProcAddress((GLubyte*) "glXSwapIntervalEXT"))((Display*) win->src.display, (Window) win->src.window, swapInterval);
+ #else
+ RGFW_UNUSED(swapInterval);
+ #endif
+ }
+ #endif
+
+
+ void RGFW_window_close(RGFW_window* win) {
+ /* ungrab pointer if it was grabbed */
+ if (win->_winArgs & RGFW_HOLD_MOUSE)
+ XUngrabPointer(win->src.display, CurrentTime);
+
+ assert(win != NULL);
+#ifdef RGFW_EGL
+ RGFW_closeEGL(win);
+#endif
+
+#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER)
+ if (win->buffer != NULL) {
+ XDestroyImage((XImage*) win->src.bitmap);
+ XFreeGC(win->src.display, win->src.gc);
+ }
+#endif
+
+ if ((Display*) win->src.display) {
+#ifdef RGFW_OPENGL
+ glXDestroyContext((Display*) win->src.display, win->src.ctx);
+#endif
+
+ if (win == RGFW_root)
+ RGFW_root = NULL;
+
+ if ((Drawable) win->src.window)
+ XDestroyWindow((Display*) win->src.display, (Drawable) win->src.window); /*!< close the window*/
+
+ XCloseDisplay((Display*) win->src.display); /*!< kill the display*/
+ }
+
+#ifdef RGFW_ALLOC_DROPFILES
+ {
+ u32 i;
+ for (i = 0; i < RGFW_MAX_DROPS; i++)
+ RGFW_FREE(win->event.droppedFiles[i]);
+
+
+ RGFW_FREE(win->event.droppedFiles);
+ }
+#endif
+
+ RGFW_windowsOpen--;
+#if !defined(RGFW_NO_X11_CURSOR_PRELOAD) && !defined(RGFW_NO_X11_CURSOR)
+ if (X11Cursorhandle != NULL && RGFW_windowsOpen <= 0) {
+ dlclose(X11Cursorhandle);
+
+ X11Cursorhandle = NULL;
+ }
+#endif
+#if !defined(RGFW_NO_X11_XI_PRELOAD)
+ if (X11Xihandle != NULL && RGFW_windowsOpen <= 0) {
+ dlclose(X11Xihandle);
+
+ X11Xihandle = NULL;
+ }
+#endif
+
+ if (RGFW_libxshape != NULL && RGFW_windowsOpen <= 0) {
+ dlclose(RGFW_libxshape);
+ RGFW_libxshape = NULL;
+ }
+
+ if (RGFW_windowsOpen <= 0) {
+ if (RGFW_eventWait_forceStop[0] || RGFW_eventWait_forceStop[1]){
+ close(RGFW_eventWait_forceStop[0]);
+ close(RGFW_eventWait_forceStop[1]);
+ }
+
+ u8 i;
+ for (i = 0; i < RGFW_joystickCount; i++)
+ close(RGFW_joysticks[i]);
+ }
+
+ /* set cleared display / window to NULL for error checking */
+ win->src.display = (Display*) 0;
+ win->src.window = (Window) 0;
+
+ RGFW_FREE(win); /*!< free collected window data */
+ }
+
+
+/*
+ End of X11 linux / unix defines
+*/
+
+#endif /* RGFW_X11 */
+
+
+/* wayland or X11 defines*/
+#if defined(RGFW_WAYLAND) || defined(RGFW_X11)
+#include
+#include
+#include
+ u16 RGFW_registerJoystickF(RGFW_window* win, char* file) {
+ assert(win != NULL);
+
+#ifdef __linux__
+
+ i32 js = open(file, O_RDONLY);
+
+ if (js && RGFW_joystickCount < 4) {
+ RGFW_joystickCount++;
+
+ RGFW_joysticks[RGFW_joystickCount - 1] = open(file, O_RDONLY);
+
+ u8 i;
+ for (i = 0; i < 16; i++)
+ RGFW_jsPressed[RGFW_joystickCount - 1][i] = 0;
+
+ }
+
+ else {
+#ifdef RGFW_PRINT_ERRORS
+ RGFW_error = 1;
+ fprintf(stderr, "Error RGFW_registerJoystickF : Cannot open file %s\n", file);
+#endif
+ }
+
+ return RGFW_joystickCount - 1;
+#endif
+ }
+
+ u16 RGFW_registerJoystick(RGFW_window* win, i32 jsNumber) {
+ assert(win != NULL);
+
+#ifdef __linux__
+ char file[15];
+ sprintf(file, "/dev/input/js%i", jsNumber);
+
+ return RGFW_registerJoystickF(win, file);
+#endif
+ }
+
+ void RGFW_stopCheckEvents(void) {
+ RGFW_eventWait_forceStop[2] = 1;
+ while (1) {
+ const char byte = 0;
+ const ssize_t result = write(RGFW_eventWait_forceStop[1], &byte, 1);
+ if (result == 1 || result == -1)
+ break;
+ }
+ }
+
+ void RGFW_window_eventWait(RGFW_window* win, i32 waitMS) {
+ if (waitMS == 0)
+ return;
+
+ u8 i;
+
+ if (RGFW_eventWait_forceStop[0] == 0 || RGFW_eventWait_forceStop[1] == 0) {
+ if (pipe(RGFW_eventWait_forceStop) != -1) {
+ fcntl(RGFW_eventWait_forceStop[0], F_GETFL, 0);
+ fcntl(RGFW_eventWait_forceStop[0], F_GETFD, 0);
+ fcntl(RGFW_eventWait_forceStop[1], F_GETFL, 0);
+ fcntl(RGFW_eventWait_forceStop[1], F_GETFD, 0);
+ }
+ }
+
+ struct pollfd fds[] = {
+ #ifdef RGFW_WAYLAND
+ { wl_display_get_fd(win->src.display), POLLIN, 0 },
+ #else
+ { ConnectionNumber(win->src.display), POLLIN, 0 },
+ #endif
+ { RGFW_eventWait_forceStop[0], POLLIN, 0 },
+ #ifdef __linux__ /* blank space for 4 joystick files*/
+ { -1, POLLIN, 0 }, {-1, POLLIN, 0 }, {-1, POLLIN, 0 }, {-1, POLLIN, 0}
+ #endif
+ };
+
+ u8 index = 2;
+
+ #if defined(__linux__)
+ for (i = 0; i < RGFW_joystickCount; i++) {
+ if (RGFW_joysticks[i] == 0)
+ continue;
+
+ fds[index].fd = RGFW_joysticks[i];
+ index++;
+ }
+ #endif
+
+
+ u64 start = RGFW_getTimeNS();
+
+ #ifdef RGFW_WAYLAND
+ while (wl_display_dispatch(win->src.display) <= 0 && waitMS >= -1) {
+ #else
+ while (XPending(win->src.display) == 0 && waitMS >= -1) {
+ #endif
+ if (poll(fds, index, waitMS) <= 0)
+ break;
+
+ if (waitMS > 0) {
+ waitMS -= (RGFW_getTimeNS() - start) / 1e+6;
+ }
+ }
+
+ /* drain any data in the stop request */
+ if (RGFW_eventWait_forceStop[2]) {
+ char data[64];
+ (void)!read(RGFW_eventWait_forceStop[0], data, sizeof(data));
+
+ RGFW_eventWait_forceStop[2] = 0;
+ }
+ }
+
+ u64 RGFW_getTimeNS(void) {
+ struct timespec ts = { 0 };
+ clock_gettime(1, &ts);
+ unsigned long long int nanoSeconds = (unsigned long long int)ts.tv_sec*1000000000LLU + (unsigned long long int)ts.tv_nsec;
+
+ return nanoSeconds;
+ }
+
+ u64 RGFW_getTime(void) {
+ struct timespec ts = { 0 };
+ clock_gettime(1, &ts);
+ unsigned long long int nanoSeconds = (unsigned long long int)ts.tv_sec*1000000000LLU + (unsigned long long int)ts.tv_nsec;
+
+ return (double)(nanoSeconds) * 1e-9;
+ }
+#endif /* end of wayland or X11 time defines*/
+
+
+/*
+
+ Start of Wayland defines
+
+
+*/
+
+#ifdef RGFW_WAYLAND
+/*
+Wayland TODO:
+- fix RGFW_keyPressed lock state
+
+ RGFW_windowMoved, the window was moved (by the user)
+ RGFW_windowResized the window was resized (by the user), [on webASM this means the browser was resized]
+ RGFW_windowRefresh The window content needs to be refreshed
+
+ RGFW_dnd a file has been dropped into the window
+ RGFW_dnd_init
+
+- window args:
+ #define RGFW_NO_RESIZE the window cannot be resized by the user
+ #define RGFW_ALLOW_DND the window supports drag and drop
+ #define RGFW_SCALE_TO_MONITOR scale the window to the screen
+
+- other missing functions functions ("TODO wayland") (~30 functions)
+- fix buffer rendering weird behavior
+*/
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include
+
+RGFW_window* RGFW_key_win = NULL;
+
+void RGFW_eventPipe_push(RGFW_window* win, RGFW_Event event) {
+ if (win == NULL) {
+ win = RGFW_key_win;
+
+ if (win == NULL) return;
+ }
+
+ if (win->src.eventLen >= (i32)(sizeof(win->src.events) / sizeof(win->src.events[0])))
+ return;
+
+ win->src.events[win->src.eventLen] = event;
+ win->src.eventLen += 1;
+}
+
+RGFW_Event RGFW_eventPipe_pop(RGFW_window* win) {
+ RGFW_Event ev;
+ ev.type = 0;
+
+ if (win->src.eventLen > -1)
+ win->src.eventLen -= 1;
+
+ if (win->src.eventLen >= 0)
+ ev = win->src.events[win->src.eventLen];
+
+ return ev;
+}
+
+/* wayland global garbage (wayland bad, X11 is fine (ish) (not really)) */
+#include "xdg-shell.h"
+#include "xdg-decoration-unstable-v1.h"
+
+struct xdg_wm_base *xdg_wm_base;
+struct wl_compositor* RGFW_compositor = NULL;
+struct wl_shm* shm = NULL;
+struct wl_shell* RGFW_shell = NULL;
+static struct wl_seat *seat = NULL;
+static struct xkb_context *xkb_context;
+static struct xkb_keymap *keymap = NULL;
+static struct xkb_state *xkb_state = NULL;
+enum zxdg_toplevel_decoration_v1_mode client_preferred_mode, RGFW_current_mode;
+static struct zxdg_decoration_manager_v1 *decoration_manager = NULL;
+
+struct wl_cursor_theme* RGFW_wl_cursor_theme = NULL;
+struct wl_surface* RGFW_cursor_surface = NULL;
+struct wl_cursor_image* RGFW_cursor_image = NULL;
+
+static void xdg_wm_base_ping_handler(void *data,
+ struct xdg_wm_base *wm_base, uint32_t serial)
+{
+ RGFW_UNUSED(data);
+ xdg_wm_base_pong(wm_base, serial);
+}
+
+static const struct xdg_wm_base_listener xdg_wm_base_listener = {
+ .ping = xdg_wm_base_ping_handler,
+};
+
+b8 RGFW_wl_configured = 0;
+
+static void xdg_surface_configure_handler(void *data,
+ struct xdg_surface *xdg_surface, uint32_t serial)
+{
+ RGFW_UNUSED(data);
+ xdg_surface_ack_configure(xdg_surface, serial);
+ #ifdef RGFW_DEBUG
+ printf("Surface configured\n");
+ #endif
+ RGFW_wl_configured = 1;
+}
+
+static const struct xdg_surface_listener xdg_surface_listener = {
+ .configure = xdg_surface_configure_handler,
+};
+
+static void xdg_toplevel_configure_handler(void *data,
+ struct xdg_toplevel *toplevel, int32_t width, int32_t height,
+ struct wl_array *states)
+{
+ RGFW_UNUSED(data); RGFW_UNUSED(toplevel); RGFW_UNUSED(states)
+ fprintf(stderr, "XDG toplevel configure: %dx%d\n", width, height);
+}
+
+static void xdg_toplevel_close_handler(void *data,
+ struct xdg_toplevel *toplevel)
+{
+ RGFW_UNUSED(data);
+ RGFW_window* win = (RGFW_window*)xdg_toplevel_get_user_data(toplevel);
+ if (win == NULL)
+ win = RGFW_key_win;
+
+ RGFW_Event ev;
+ ev.type = RGFW_quit;
+
+ RGFW_eventPipe_push(win, ev);
+
+ RGFW_windowQuitCallback(win);
+}
+
+static void shm_format_handler(void *data,
+ struct wl_shm *shm, uint32_t format)
+{
+ RGFW_UNUSED(data); RGFW_UNUSED(shm);
+ fprintf(stderr, "Format %d\n", format);
+}
+
+static const struct wl_shm_listener shm_listener = {
+ .format = shm_format_handler,
+};
+
+static const struct xdg_toplevel_listener xdg_toplevel_listener = {
+ .configure = xdg_toplevel_configure_handler,
+ .close = xdg_toplevel_close_handler,
+};
+
+RGFW_window* RGFW_mouse_win = NULL;
+
+static void pointer_enter(void *data, struct wl_pointer *pointer, uint32_t serial, struct wl_surface *surface, wl_fixed_t surface_x, wl_fixed_t surface_y) {
+ RGFW_UNUSED(data); RGFW_UNUSED(pointer); RGFW_UNUSED(serial); RGFW_UNUSED(surface_x); RGFW_UNUSED(surface_y);
+ RGFW_window* win = (RGFW_window*)wl_surface_get_user_data(surface);
+ RGFW_mouse_win = win;
+
+ RGFW_Event ev;
+ ev.type = RGFW_mouseEnter;
+ ev.point = win->event.point;
+
+ RGFW_eventPipe_push(win, ev);
+
+ RGFW_mouseNotifyCallBack(win, win->event.point, RGFW_TRUE);
+}
+static void pointer_leave(void *data, struct wl_pointer *pointer, uint32_t serial, struct wl_surface *surface) {
+ RGFW_UNUSED(data); RGFW_UNUSED(pointer); RGFW_UNUSED(serial); RGFW_UNUSED(surface);
+ RGFW_window* win = (RGFW_window*)wl_surface_get_user_data(surface);
+ if (RGFW_mouse_win == win)
+ RGFW_mouse_win = NULL;
+
+ RGFW_Event ev;
+ ev.type = RGFW_mouseLeave;
+ ev.point = win->event.point;
+ RGFW_eventPipe_push(win, ev);
+
+ RGFW_mouseNotifyCallBack(win, win->event.point, RGFW_FALSE);
+}
+static void pointer_motion(void *data, struct wl_pointer *pointer, uint32_t time, wl_fixed_t x, wl_fixed_t y) {
+ RGFW_UNUSED(data); RGFW_UNUSED(pointer); RGFW_UNUSED(time); RGFW_UNUSED(x); RGFW_UNUSED(y);
+
+ assert(RGFW_mouse_win != NULL);
+
+ RGFW_Event ev;
+ ev.type = RGFW_mousePosChanged;
+ ev.point = RGFW_POINT(wl_fixed_to_double(x), wl_fixed_to_double(y));
+ RGFW_eventPipe_push(RGFW_mouse_win, ev);
+
+ RGFW_mousePosCallback(RGFW_mouse_win, RGFW_POINT(wl_fixed_to_double(x), wl_fixed_to_double(y)));
+}
+static void pointer_button(void *data, struct wl_pointer *pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state) {
+ RGFW_UNUSED(data); RGFW_UNUSED(pointer); RGFW_UNUSED(time); RGFW_UNUSED(serial);
+ assert(RGFW_mouse_win != NULL);
+
+ u32 b = (button - 0x110) + 1;
+
+ /* flip right and middle button codes */
+ if (b == 2) b = 3;
+ else if (b == 3) b = 2;
+
+ RGFW_mouseButtons[b].prev = RGFW_mouseButtons[b].current;
+ RGFW_mouseButtons[b].current = state;
+
+ RGFW_Event ev;
+ ev.type = RGFW_mouseButtonPressed + state;
+ ev.button = b;
+ RGFW_eventPipe_push(RGFW_mouse_win, ev);
+
+ RGFW_mouseButtonCallback(RGFW_mouse_win, b, 0, state);
+}
+static void pointer_axis(void *data, struct wl_pointer *pointer, uint32_t time, uint32_t axis, wl_fixed_t value) {
+ RGFW_UNUSED(data); RGFW_UNUSED(pointer); RGFW_UNUSED(time); RGFW_UNUSED(axis);
+ assert(RGFW_mouse_win != NULL);
+
+ double scroll = wl_fixed_to_double(value);
+
+ RGFW_Event ev;
+ ev.type = RGFW_mouseButtonPressed;
+ ev.button = RGFW_mouseScrollUp + (scroll < 0);
+ RGFW_eventPipe_push(RGFW_mouse_win, ev);
+
+ RGFW_mouseButtonCallback(RGFW_mouse_win, RGFW_mouseScrollUp + (scroll < 0), scroll, 1);
+}
+
+void RGFW_doNothing(void) { }
+static struct wl_pointer_listener pointer_listener = (struct wl_pointer_listener){&pointer_enter, &pointer_leave, &pointer_motion, &pointer_button, &pointer_axis, (void*)&RGFW_doNothing, (void*)&RGFW_doNothing, (void*)&RGFW_doNothing, (void*)&RGFW_doNothing, (void*)&RGFW_doNothing, (void*)&RGFW_doNothing};
+
+static void keyboard_keymap (void *data, struct wl_keyboard *keyboard, uint32_t format, int32_t fd, uint32_t size) {
+ RGFW_UNUSED(data); RGFW_UNUSED(keyboard); RGFW_UNUSED(format);
+
+ char *keymap_string = mmap (NULL, size, PROT_READ, MAP_SHARED, fd, 0);
+ xkb_keymap_unref (keymap);
+ keymap = xkb_keymap_new_from_string (xkb_context, keymap_string, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
+
+ munmap (keymap_string, size);
+ close (fd);
+ xkb_state_unref (xkb_state);
+ xkb_state = xkb_state_new (keymap);
+}
+static void keyboard_enter (void *data, struct wl_keyboard *keyboard, uint32_t serial, struct wl_surface *surface, struct wl_array *keys) {
+ RGFW_UNUSED(data); RGFW_UNUSED(keyboard); RGFW_UNUSED(serial); RGFW_UNUSED(keys);
+
+ RGFW_key_win = (RGFW_window*)wl_surface_get_user_data(surface);
+
+ RGFW_Event ev;
+ ev.type = RGFW_focusIn;
+ ev.inFocus = RGFW_TRUE;
+ RGFW_key_win->event.inFocus = RGFW_TRUE;
+
+ RGFW_eventPipe_push((RGFW_window*)RGFW_mouse_win, ev);
+
+ RGFW_focusCallback(RGFW_key_win, RGFW_TRUE);
+}
+static void keyboard_leave (void *data, struct wl_keyboard *keyboard, uint32_t serial, struct wl_surface *surface) {
+ RGFW_UNUSED(data); RGFW_UNUSED(keyboard); RGFW_UNUSED(serial);
+
+ RGFW_window* win = (RGFW_window*)wl_surface_get_user_data(surface);
+ if (RGFW_key_win == win)
+ RGFW_key_win = NULL;
+
+ RGFW_Event ev;
+ ev.type = RGFW_focusOut;
+ ev.inFocus = RGFW_FALSE;
+ win->event.inFocus = RGFW_FALSE;
+ RGFW_eventPipe_push(win, ev);
+
+ RGFW_focusCallback(win, RGFW_FALSE);
+}
+static void keyboard_key (void *data, struct wl_keyboard *keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t state) {
+ RGFW_UNUSED(data); RGFW_UNUSED(keyboard); RGFW_UNUSED(serial); RGFW_UNUSED(time);
+
+ assert(RGFW_key_win != NULL);
+
+ xkb_keysym_t keysym = xkb_state_key_get_one_sym (xkb_state, key+8);
+ char name[16];
+ xkb_keysym_get_name(keysym, name, 16);
+
+ u32 RGFW_key = RGFW_apiKeyCodeToRGFW(key);
+ RGFW_keyboard[RGFW_key].prev = RGFW_keyboard[RGFW_key].current;
+ RGFW_keyboard[RGFW_key].current = state;
+ RGFW_Event ev;
+ ev.type = RGFW_keyPressed + state;
+ ev.keyCode = RGFW_key;
+ strcpy(ev.keyName, name);
+ ev.repeat = RGFW_isHeld(RGFW_key_win, RGFW_key);
+ RGFW_eventPipe_push(RGFW_key_win, ev);
+
+ RGFW_updateLockState(RGFW_key_win, xkb_keymap_mod_get_index(keymap, "Lock"), xkb_keymap_mod_get_index(keymap, "Mod2"));
+
+ RGFW_keyCallback(RGFW_key_win, RGFW_key, name, RGFW_key_win->event.lockState, state);
+}
+static void keyboard_modifiers (void *data, struct wl_keyboard *keyboard, uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group) {
+ RGFW_UNUSED(data); RGFW_UNUSED(keyboard); RGFW_UNUSED(serial); RGFW_UNUSED(time);
+ xkb_state_update_mask (xkb_state, mods_depressed, mods_latched, mods_locked, 0, 0, group);
+}
+static struct wl_keyboard_listener keyboard_listener = {&keyboard_keymap, &keyboard_enter, &keyboard_leave, &keyboard_key, &keyboard_modifiers, (void*)&RGFW_doNothing};
+
+static void seat_capabilities (void *data, struct wl_seat *seat, uint32_t capabilities) {
+ RGFW_UNUSED(data);
+
+ if (capabilities & WL_SEAT_CAPABILITY_POINTER) {
+ struct wl_pointer *pointer = wl_seat_get_pointer (seat);
+ wl_pointer_add_listener (pointer, &pointer_listener, NULL);
+ }
+ if (capabilities & WL_SEAT_CAPABILITY_KEYBOARD) {
+ struct wl_keyboard *keyboard = wl_seat_get_keyboard (seat);
+ wl_keyboard_add_listener (keyboard, &keyboard_listener, NULL);
+ }
+}
+static struct wl_seat_listener seat_listener = {&seat_capabilities, (void*)&RGFW_doNothing};
+
+static void wl_global_registry_handler(void *data,
+ struct wl_registry *registry, uint32_t id, const char *interface,
+ uint32_t version)
+{
+ RGFW_UNUSED(data); RGFW_UNUSED(version);
+
+ if (strcmp(interface, "wl_compositor") == 0) {
+ RGFW_compositor = wl_registry_bind(registry,
+ id, &wl_compositor_interface, 4);
+ } else if (strcmp(interface, "xdg_wm_base") == 0) {
+ xdg_wm_base = wl_registry_bind(registry,
+ id, &xdg_wm_base_interface, 1);
+ } else if (strcmp(interface, zxdg_decoration_manager_v1_interface.name) == 0) {
+ decoration_manager = wl_registry_bind(registry, id, &zxdg_decoration_manager_v1_interface, 1);
+ } else if (strcmp(interface, "wl_shm") == 0) {
+ shm = wl_registry_bind(registry,
+ id, &wl_shm_interface, 1);
+ wl_shm_add_listener(shm, &shm_listener, NULL);
+ } else if (strcmp(interface,"wl_seat") == 0) {
+ seat = wl_registry_bind(registry, id, &wl_seat_interface, 1);
+ wl_seat_add_listener(seat, &seat_listener, NULL);
+ }
+
+ else {
+ #ifdef RGFW_DEBUG
+ printf("did not register %s\n", interface);
+ return;
+ #endif
+ }
+
+ #ifdef RGFW_DEBUG
+ printf("registered %s\n", interface);
+ #endif
+}
+
+static void wl_global_registry_remove(void *data, struct wl_registry *registry, uint32_t name) { RGFW_UNUSED(data); RGFW_UNUSED(registry); RGFW_UNUSED(name); }
+static const struct wl_registry_listener registry_listener = {
+ .global = wl_global_registry_handler,
+ .global_remove = wl_global_registry_remove,
+};
+
+static const char *get_mode_name(enum zxdg_toplevel_decoration_v1_mode mode) {
+ switch (mode) {
+ case ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE:
+ return "client-side decorations";
+ case ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE:
+ return "server-side decorations";
+ }
+ abort();
+}
+
+
+static void decoration_handle_configure(void *data,
+ struct zxdg_toplevel_decoration_v1 *decoration,
+ enum zxdg_toplevel_decoration_v1_mode mode) {
+ RGFW_UNUSED(data); RGFW_UNUSED(decoration);
+ printf("Using %s\n", get_mode_name(mode));
+ RGFW_current_mode = mode;
+}
+
+static const struct zxdg_toplevel_decoration_v1_listener decoration_listener = {
+ .configure = decoration_handle_configure,
+};
+
+static void randname(char *buf) {
+ struct timespec ts;
+ clock_gettime(CLOCK_REALTIME, &ts);
+ long r = ts.tv_nsec;
+ for (int i = 0; i < 6; ++i) {
+ buf[i] = 'A'+(r&15)+(r&16)*2;
+ r >>= 5;
+ }
+}
+
+static int anonymous_shm_open(void) {
+ char name[] = "/RGFW-wayland-XXXXXX";
+ int retries = 100;
+
+ do {
+ randname(name + strlen(name) - 6);
+
+ --retries;
+ // shm_open guarantees that O_CLOEXEC is set
+ int fd = shm_open(name, O_RDWR | O_CREAT | O_EXCL, 0600);
+ if (fd >= 0) {
+ shm_unlink(name);
+ return fd;
+ }
+ } while (retries > 0 && errno == EEXIST);
+
+ return -1;
+}
+
+int create_shm_file(off_t size) {
+ int fd = anonymous_shm_open();
+ if (fd < 0) {
+ return fd;
+ }
+
+ if (ftruncate(fd, size) < 0) {
+ close(fd);
+ return -1;
+ }
+
+ return fd;
+}
+
+static void wl_surface_frame_done(void *data, struct wl_callback *cb, uint32_t time) {
+ #ifdef RGFW_BUFFER
+ RGFW_window* win = (RGFW_window*)data;
+ if ((win->_winArgs & RGFW_NO_CPU_RENDER))
+ return;
+
+ #ifndef RGFW_X11_DONT_CONVERT_BGR
+ u32 x, y;
+ for (y = 0; y < (u32)win->r.h; y++) {
+ for (x = 0; x < (u32)win->r.w; x++) {
+ u32 index = (y * 4 * win->r.w) + x * 4;
+
+ u8 red = win->buffer[index];
+ win->buffer[index] = win->buffer[index + 2];
+ win->buffer[index + 2] = red;
+
+ }
+ }
+ #endif
+
+ wl_surface_attach(win->src.surface, win->src.wl_buffer, 0, 0);
+ wl_surface_damage_buffer(win->src.surface, 0, 0, win->r.w, win->r.h);
+ wl_surface_commit(win->src.surface);
+ #endif
+}
+
+static const struct wl_callback_listener wl_surface_frame_listener = {
+ .done = wl_surface_frame_done,
+};
+
+
+ /* normal wayland RGFW stuff */
+
+ RGFW_area RGFW_getScreenSize(void) {
+ RGFW_area area = {};
+
+ if (RGFW_root != NULL)
+ /* this isn't right but it's here for buffers */
+ area = RGFW_AREA(RGFW_root->r.w, RGFW_root->r.h);
+
+ /* TODO wayland */
+ return area;
+ }
+
+ void RGFW_releaseCursor(RGFW_window* win) {
+ RGFW_UNUSED(win);
+ }
+
+ void RGFW_captureCursor(RGFW_window* win, RGFW_rect r) {
+ RGFW_UNUSED(win); RGFW_UNUSED(r);
+
+ /* TODO wayland */
+ }
+
+
+ RGFWDEF void RGFW_init_buffer(RGFW_window* win);
+ void RGFW_init_buffer(RGFW_window* win) {
+ #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER)
+ size_t size = win->r.w * win->r.h * 4;
+ int fd = create_shm_file(size);
+ if (fd < 0) {
+ fprintf(stderr, "Failed to create a buffer. size: %ld\n", size);
+ exit(1);
+ }
+
+ win->buffer = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ if (win->buffer == MAP_FAILED) {
+ fprintf(stderr, "mmap failed!\n");
+ close(fd);
+ exit(1);
+ }
+
+ struct wl_shm_pool* pool = wl_shm_create_pool(shm, fd, size);
+ win->src.wl_buffer = wl_shm_pool_create_buffer(pool, 0, win->r.w, win->r.h, win->r.w * 4,
+ WL_SHM_FORMAT_ARGB8888);
+ wl_shm_pool_destroy(pool);
+
+ close(fd);
+
+ wl_surface_attach(win->src.surface, win->src.wl_buffer, 0, 0);
+ wl_surface_commit(win->src.surface);
+
+ u8 color[] = {0x00, 0x00, 0x00, 0xFF};
+
+ size_t i;
+ for (i = 0; i < size; i += 4) {
+ memcpy(&win->buffer[i], color, 4);
+ }
+
+ #if defined(RGFW_OSMESA)
+ win->src.ctx = OSMesaCreateContext(OSMESA_RGBA, NULL);
+ OSMesaMakeCurrent(win->src.ctx, win->buffer, GL_UNSIGNED_BYTE, win->r.w, win->r.h);
+ #endif
+ #else
+ RGFW_UNUSED(win);
+ #endif
+ }
+
+
+ RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, u16 args) {
+ RGFW_window* win = RGFW_window_basic_init(rect, args);
+
+ fprintf(stderr, "Warning: RGFW Wayland support is experimental\n");
+
+ win->src.display = wl_display_connect(NULL);
+ if (win->src.display == NULL) {
+ #ifdef RGFW_DEBUG
+ fprintf(stderr, "Failed to load Wayland display\n");
+ #endif
+ return NULL;
+ }
+
+ struct wl_registry *registry = wl_display_get_registry(win->src.display);
+ wl_registry_add_listener(registry, ®istry_listener, NULL);
+
+ wl_display_dispatch(win->src.display);
+ wl_display_roundtrip(win->src.display);
+
+ if (RGFW_compositor == NULL) {
+ #ifdef RGFW_DEBUG
+ fprintf(stderr, "Can't find compositor.\n");
+ #endif
+
+ return NULL;
+ }
+
+ if (RGFW_wl_cursor_theme == NULL) {
+ RGFW_wl_cursor_theme = wl_cursor_theme_load(NULL, 24, shm);
+ RGFW_cursor_surface = wl_compositor_create_surface(RGFW_compositor);
+
+ struct wl_cursor* cursor = wl_cursor_theme_get_cursor(RGFW_wl_cursor_theme, "left_ptr");
+ RGFW_cursor_image = cursor->images[0];
+ struct wl_buffer* cursor_buffer = wl_cursor_image_get_buffer(RGFW_cursor_image);
+
+ wl_surface_attach(RGFW_cursor_surface, cursor_buffer, 0, 0);
+ wl_surface_commit(RGFW_cursor_surface);
+ }
+
+ if (RGFW_root == NULL)
+ xdg_wm_base_add_listener(xdg_wm_base, &xdg_wm_base_listener, NULL);
+
+ xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
+
+ win->src.surface = wl_compositor_create_surface(RGFW_compositor);
+ wl_surface_set_user_data(win->src.surface, win);
+
+ win->src.xdg_surface = xdg_wm_base_get_xdg_surface(xdg_wm_base, win->src.surface);
+ xdg_surface_add_listener(win->src.xdg_surface, &xdg_surface_listener, NULL);
+
+ xdg_wm_base_set_user_data(xdg_wm_base, win);
+
+ win->src.xdg_toplevel = xdg_surface_get_toplevel(win->src.xdg_surface);
+ xdg_toplevel_set_user_data(win->src.xdg_toplevel, win);
+ xdg_toplevel_set_title(win->src.xdg_toplevel, name);
+ xdg_toplevel_add_listener(win->src.xdg_toplevel, &xdg_toplevel_listener, NULL);
+
+ xdg_surface_set_window_geometry(win->src.xdg_surface, 0, 0, win->r.w, win->r.h);
+
+ if (!(args & RGFW_NO_BORDER)) {
+ win->src.decoration = zxdg_decoration_manager_v1_get_toplevel_decoration(
+ decoration_manager, win->src.xdg_toplevel);
+ }
+
+ if (args & RGFW_CENTER) {
+ RGFW_area screenR = RGFW_getScreenSize();
+ RGFW_window_move(win, RGFW_POINT((screenR.w - win->r.w) / 2, (screenR.h - win->r.h) / 2));
+ }
+
+ if (args & RGFW_OPENGL_SOFTWARE)
+ setenv("LIBGL_ALWAYS_SOFTWARE", "1", 1);
+
+ wl_display_roundtrip(win->src.display);
+
+ wl_surface_commit(win->src.surface);
+
+ /* wait for the surface to be configured */
+ while (wl_display_dispatch(win->src.display) != -1 && !RGFW_wl_configured) { }
+
+
+ #ifdef RGFW_OPENGL
+ if ((args & RGFW_NO_INIT_API) == 0) {
+ win->src.window = wl_egl_window_create(win->src.surface, win->r.w, win->r.h);
+ RGFW_createOpenGLContext(win);
+ }
+ #endif
+
+ RGFW_init_buffer(win);
+
+ struct wl_callback* callback = wl_surface_frame(win->src.surface);
+ wl_callback_add_listener(callback, &wl_surface_frame_listener, win);
+ wl_surface_commit(win->src.surface);
+
+ if (args & RGFW_HIDE_MOUSE) {
+ RGFW_window_showMouse(win, 0);
+ }
+
+ if (RGFW_root == NULL) {
+ RGFW_root = win;
+ }
+
+ win->src.eventIndex = 0;
+ win->src.eventLen = 0;
+
+ return win;
+ }
+
+ RGFW_Event* RGFW_window_checkEvent(RGFW_window* win) {
+ if (win->_winArgs & RGFW_WINDOW_HIDE)
+ return NULL;
+
+ if (win->src.eventIndex == 0) {
+ if (wl_display_roundtrip(win->src.display) == -1) {
+ return NULL;
+ }
+ RGFW_resetKey();
+ }
+
+ #ifdef __linux__
+ RGFW_Event* event = RGFW_linux_updateJoystick(win);
+ if (event != NULL)
+ return event;
+ #endif
+
+ if (win->src.eventLen == 0) {
+ return NULL;
+ }
+
+ RGFW_Event ev = RGFW_eventPipe_pop(win);
+
+ if (ev.type == 0 || win->event.type == RGFW_quit) {
+ return NULL;
+ }
+
+ ev.frameTime = win->event.frameTime;
+ ev.frameTime2 = win->event.frameTime2;
+ ev.inFocus = win->event.inFocus;
+ win->event = ev;
+
+ return &win->event;
+ }
+
+
+ void RGFW_window_resize(RGFW_window* win, RGFW_area a) {
+ RGFW_UNUSED(win); RGFW_UNUSED(a);
+
+ /* TODO wayland */
+ }
+
+ void RGFW_window_move(RGFW_window* win, RGFW_point v) {
+ RGFW_UNUSED(win); RGFW_UNUSED(v);
+
+ /* TODO wayland */
+ }
+
+ void RGFW_window_setIcon(RGFW_window* win, u8* src, RGFW_area a, i32 channels) {
+ RGFW_UNUSED(win); RGFW_UNUSED(src); RGFW_UNUSED(a); RGFW_UNUSED(channels)
+ /* TODO wayland */
+ }
+
+ void RGFW_window_moveMouse(RGFW_window* win, RGFW_point v) {
+ RGFW_UNUSED(win); RGFW_UNUSED(v);
+
+ /* TODO wayland */
+ }
+
+ void RGFW_window_showMouse(RGFW_window* win, i8 show) {
+ RGFW_UNUSED(win);
+
+ if (show) {
+
+ }
+ else {
+
+ }
+
+ /* TODO wayland */
+ }
+
+ b8 RGFW_window_isMaximized(RGFW_window* win) {
+ RGFW_UNUSED(win);
+ /* TODO wayland */
+ return 0;
+ }
+
+ b8 RGFW_window_isMinimized(RGFW_window* win) {
+ RGFW_UNUSED(win);
+ /* TODO wayland */
+ return 0;
+ }
+
+ b8 RGFW_window_isHidden(RGFW_window* win) {
+ RGFW_UNUSED(win);
+ /* TODO wayland */
+ return 0;
+ }
+
+ b8 RGFW_window_isFullscreen(RGFW_window* win) {
+ RGFW_UNUSED(win);
+ /* TODO wayland */
+ return 0;
+ }
+
+ RGFW_point RGFW_window_getMousePoint(RGFW_window* win) {
+ RGFW_UNUSED(win);
+ /* TODO wayland */
+ return RGFW_POINT(0, 0);
+ }
+
+ RGFW_point RGFW_getGlobalMousePoint(void) {
+ /* TODO wayland */
+ return RGFW_POINT(0, 0);
+ }
+
+ void RGFW_window_show(RGFW_window* win) {
+ //wl_surface_attach(win->src.surface, win->rc., 0, 0);
+ wl_surface_commit(win->src.surface);
+
+ if (win->_winArgs & RGFW_WINDOW_HIDE)
+ win->_winArgs ^= RGFW_WINDOW_HIDE;
+ }
+
+ void RGFW_window_hide(RGFW_window* win) {
+ wl_surface_attach(win->src.surface, NULL, 0, 0);
+ wl_surface_commit(win->src.surface);
+ win->_winArgs |= RGFW_WINDOW_HIDE;
+ }
+
+ void RGFW_window_setMouseDefault(RGFW_window* win) {
+ RGFW_UNUSED(win);
+
+ RGFW_window_setMouseStandard(win, RGFW_MOUSE_NORMAL);
+ }
+
+ void RGFW_window_setMouseStandard(RGFW_window* win, u8 mouse) {
+ RGFW_UNUSED(win);
+
+ static const char* iconStrings[] = { "left_ptr", "left_ptr", "text", "cross", "pointer", "e-resize", "n-resize", "nw-resize", "ne-resize", "all-resize", "not-allowed" };
+
+ struct wl_cursor* cursor = wl_cursor_theme_get_cursor(RGFW_wl_cursor_theme, iconStrings[mouse]);
+ RGFW_cursor_image = cursor->images[0];
+ struct wl_buffer* cursor_buffer = wl_cursor_image_get_buffer(RGFW_cursor_image);
+
+ wl_surface_attach(RGFW_cursor_surface, cursor_buffer, 0, 0);
+ wl_surface_commit(RGFW_cursor_surface);
+ }
+
+ void RGFW_window_setMouse(RGFW_window* win, u8* image, RGFW_area a, i32 channels) {
+ RGFW_UNUSED(win); RGFW_UNUSED(image); RGFW_UNUSED(a); RGFW_UNUSED(channels)
+ //struct wl_cursor* cursor = wl_cursor_theme_get_cursor(RGFW_wl_cursor_theme, iconStrings[mouse]);
+ //RGFW_cursor_image = image;
+ struct wl_buffer* cursor_buffer = wl_cursor_image_get_buffer(RGFW_cursor_image);
+
+ wl_surface_attach(RGFW_cursor_surface, cursor_buffer, 0, 0);
+ wl_surface_commit(RGFW_cursor_surface);
+ }
+
+ void RGFW_window_setName(RGFW_window* win, char* name) {
+ xdg_toplevel_set_title(win->src.xdg_toplevel, name);
+ }
+
+ void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough) {
+ RGFW_UNUSED(win); RGFW_UNUSED(passthrough);
+
+ /* TODO wayland */
+ }
+
+ void RGFW_window_setBorder(RGFW_window* win, b8 border) {
+ RGFW_UNUSED(win); RGFW_UNUSED(border);
+
+ /* TODO wayland */
+ }
+
+ void RGFW_window_restore(RGFW_window* win) {
+ RGFW_UNUSED(win);
+
+ /* TODO wayland */
+ }
+
+ void RGFW_window_minimize(RGFW_window* win) {
+ RGFW_UNUSED(win);
+
+ /* TODO wayland */
+ }
+
+ void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a) {
+ RGFW_UNUSED(win); RGFW_UNUSED(a);
+
+ /* TODO wayland */
+ }
+
+ void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a) {
+ RGFW_UNUSED(win); RGFW_UNUSED(a);
+
+ /* TODO wayland */
+ }
+
+ RGFW_monitor RGFW_window_getMonitor(RGFW_window* win) {
+ RGFW_monitor m = {};
+ RGFW_UNUSED(win);
+ RGFW_UNUSED(m);
+ /* TODO wayland */
+
+ return m;
+ }
+
+
+ #ifndef RGFW_EGL
+ void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) { RGFW_UNUSED(win); RGFW_UNUSED(swapInterval); }
+ #endif
+
+ void RGFW_window_swapBuffers(RGFW_window* win) {
+ assert(win != NULL);
+
+ /* clear the window*/
+ #ifdef RGFW_BUFFER
+ wl_surface_frame_done(win, NULL, 0);
+ if (!(win->_winArgs & RGFW_NO_GPU_RENDER))
+ #endif
+ {
+ #ifdef RGFW_OPENGL
+ eglSwapBuffers(win->src.EGL_display, win->src.EGL_surface);
+ #endif
+ }
+
+ wl_display_flush(win->src.display);
+ }
+
+ void RGFW_window_close(RGFW_window* win) {
+ #ifdef RGFW_EGL
+ RGFW_closeEGL(win);
+ #endif
+
+ if (RGFW_root == win) {
+ RGFW_root = NULL;
+ }
+
+ xdg_toplevel_destroy(win->src.xdg_toplevel);
+ xdg_surface_destroy(win->src.xdg_surface);
+ wl_surface_destroy(win->src.surface);
+
+ #ifdef RGFW_BUFFER
+ wl_buffer_destroy(win->src.wl_buffer);
+ #endif
+
+ wl_display_disconnect(win->src.display);
+ RGFW_FREE(win);
+ }
+
+ RGFW_monitor RGFW_getPrimaryMonitor(void) {
+ /* TODO wayland */
+
+ return (RGFW_monitor){};
+ }
+
+ RGFW_monitor* RGFW_getMonitors(void) {
+ /* TODO wayland */
+
+ return NULL;
+ }
+
+ void RGFW_writeClipboard(const char* text, u32 textLen) {
+ RGFW_UNUSED(text); RGFW_UNUSED(textLen);
+
+ /* TODO wayland */
+ }
+
+ char* RGFW_readClipboard(size_t* size) {
+ RGFW_UNUSED(size);
+
+ /* TODO wayland */
+
+ return NULL;
+ }
+#endif /* RGFW_WAYLAND */
+
+/*
+ End of Wayland defines
+*/
+
+
+/*
+
+ Start of Windows defines
+
+
+*/
+
+#ifdef RGFW_WINDOWS
+ #define WIN32_LEAN_AND_MEAN
+ #define OEMRESOURCE
+ #include
+
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include
+
+ #include
+
+ __declspec(dllimport) int __stdcall WideCharToMultiByte( UINT CodePage, DWORD dwFlags, const WCHAR* lpWideCharStr, int cchWideChar, LPSTR lpMultiByteStr, int cbMultiByte, LPCCH lpDefaultChar, LPBOOL lpUsedDefaultChar);
+
+ #ifndef RGFW_NO_XINPUT
+ typedef DWORD (WINAPI * PFN_XInputGetState)(DWORD,XINPUT_STATE*);
+ PFN_XInputGetState XInputGetStateSRC = NULL;
+ #define XInputGetState XInputGetStateSRC
+
+ typedef DWORD (WINAPI * PFN_XInputGetKeystroke)(DWORD, DWORD, PXINPUT_KEYSTROKE);
+ PFN_XInputGetKeystroke XInputGetKeystrokeSRC = NULL;
+ #define XInputGetKeystroke XInputGetKeystrokeSRC
+
+ static HMODULE RGFW_XInput_dll = NULL;
+ #endif
+
+ u32 RGFW_mouseIconSrc[] = {OCR_NORMAL, OCR_NORMAL, OCR_IBEAM, OCR_CROSS, OCR_HAND, OCR_SIZEWE, OCR_SIZENS, OCR_SIZENWSE, OCR_SIZENESW, OCR_SIZEALL, OCR_NO};
+
+ char* createUTF8FromWideStringWin32(const WCHAR* source);
+
+#define GL_FRONT 0x0404
+#define GL_BACK 0x0405
+#define GL_LEFT 0x0406
+#define GL_RIGHT 0x0407
+
+#if defined(RGFW_OSMESA) && defined(RGFW_LINK_OSMESA)
+
+ typedef void (GLAPIENTRY* PFN_OSMesaDestroyContext)(OSMesaContext);
+ typedef i32(GLAPIENTRY* PFN_OSMesaMakeCurrent)(OSMesaContext, void*, int, int, int);
+ typedef OSMesaContext(GLAPIENTRY* PFN_OSMesaCreateContext)(GLenum, OSMesaContext);
+
+ PFN_OSMesaMakeCurrent OSMesaMakeCurrentSource;
+ PFN_OSMesaCreateContext OSMesaCreateContextSource;
+ PFN_OSMesaDestroyContext OSMesaDestroyContextSource;
+
+#define OSMesaCreateContext OSMesaCreateContextSource
+#define OSMesaMakeCurrent OSMesaMakeCurrentSource
+#define OSMesaDestroyContext OSMesaDestroyContextSource
+#endif
+
+ typedef int (*PFN_wglGetSwapIntervalEXT)(void);
+ PFN_wglGetSwapIntervalEXT wglGetSwapIntervalEXTSrc = NULL;
+#define wglGetSwapIntervalEXT wglGetSwapIntervalEXTSrc
+
+
+ void* RGFWjoystickApi = NULL;
+
+ /* these two wgl functions need to be preloaded */
+ typedef HGLRC (WINAPI *PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC hdc, HGLRC hglrc, const int *attribList);
+ PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = NULL;
+
+ /* defines for creating ARB attributes */
+#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000
+#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
+#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
+#define WGL_DRAW_TO_WINDOW_ARB 0x2001
+#define WGL_ACCELERATION_ARB 0x2003
+#define WGL_NO_ACCELERATION_ARB 0x2025
+#define WGL_DOUBLE_BUFFER_ARB 0x2011
+#define WGL_COLOR_BITS_ARB 0x2014
+#define WGL_RED_BITS_ARB 0x2015
+#define WGL_RED_SHIFT_ARB 0x2016
+#define WGL_GREEN_BITS_ARB 0x2017
+#define WGL_GREEN_SHIFT_ARB 0x2018
+#define WGL_BLUE_BITS_ARB 0x2019
+#define WGL_BLUE_SHIFT_ARB 0x201a
+#define WGL_ALPHA_BITS_ARB 0x201b
+#define WGL_ALPHA_SHIFT_ARB 0x201c
+#define WGL_ACCUM_BITS_ARB 0x201d
+#define WGL_ACCUM_RED_BITS_ARB 0x201e
+#define WGL_ACCUM_GREEN_BITS_ARB 0x201f
+#define WGL_ACCUM_BLUE_BITS_ARB 0x2020
+#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021
+#define WGL_DEPTH_BITS_ARB 0x2022
+#define WGL_AUX_BUFFERS_ARB 0x2024
+#define WGL_STEREO_ARB 0x2012
+#define WGL_DEPTH_BITS_ARB 0x2022
+#define WGL_STENCIL_BITS_ARB 0x2023
+#define WGL_FULL_ACCELERATION_ARB 0x2027
+#define WGL_CONTEXT_FLAGS_ARB 0x2094
+#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
+#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
+#define WGL_SAMPLE_BUFFERS_ARB 0x2041
+#define WGL_SAMPLES_ARB 0x2042
+#define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20a9
+
+#ifndef RGFW_EGL
+static HMODULE wglinstance = NULL;
+#endif
+
+#ifdef RGFW_WGL_LOAD
+ typedef HGLRC(WINAPI* PFN_wglCreateContext)(HDC);
+ typedef BOOL(WINAPI* PFN_wglDeleteContext)(HGLRC);
+ typedef PROC(WINAPI* PFN_wglGetProcAddress)(LPCSTR);
+ typedef BOOL(WINAPI* PFN_wglMakeCurrent)(HDC, HGLRC);
+ typedef HDC(WINAPI* PFN_wglGetCurrentDC)();
+ typedef HGLRC(WINAPI* PFN_wglGetCurrentContext)();
+
+ PFN_wglCreateContext wglCreateContextSRC;
+ PFN_wglDeleteContext wglDeleteContextSRC;
+ PFN_wglGetProcAddress wglGetProcAddressSRC;
+ PFN_wglMakeCurrent wglMakeCurrentSRC;
+ PFN_wglGetCurrentDC wglGetCurrentDCSRC;
+ PFN_wglGetCurrentContext wglGetCurrentContextSRC;
+
+ #define wglCreateContext wglCreateContextSRC
+ #define wglDeleteContext wglDeleteContextSRC
+ #define wglGetProcAddress wglGetProcAddressSRC
+ #define wglMakeCurrent wglMakeCurrentSRC
+
+ #define wglGetCurrentDC wglGetCurrentDCSRC
+ #define wglGetCurrentContext wglGetCurrentContextSRC
+#endif
+
+#ifdef RGFW_OPENGL
+ void* RGFW_getProcAddress(const char* procname) {
+ void* proc = (void*) wglGetProcAddress(procname);
+ if (proc)
+ return proc;
+
+ return (void*) GetProcAddress(wglinstance, procname);
+ }
+
+ typedef HRESULT (APIENTRY* PFNWGLCHOOSEPIXELFORMATARBPROC)(HDC hdc, const int* piAttribIList, const FLOAT* pfAttribFList, UINT nMaxFormats, int* piFormats, UINT* nNumFormats);
+ static PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = NULL;
+#endif
+
+ RGFW_window RGFW_eventWindow;
+
+ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
+ switch (message) {
+ case WM_MOVE:
+ RGFW_eventWindow.r.x = LOWORD(lParam);
+ RGFW_eventWindow.r.y = HIWORD(lParam);
+ RGFW_eventWindow.src.window = hWnd;
+ return DefWindowProcA(hWnd, message, wParam, lParam);
+ case WM_SIZE:
+ RGFW_eventWindow.r.w = LOWORD(lParam);
+ RGFW_eventWindow.r.h = HIWORD(lParam);
+ RGFW_eventWindow.src.window = hWnd;
+ return DefWindowProcA(hWnd, message, wParam, lParam); // Call DefWindowProc after handling
+ default:
+ return DefWindowProcA(hWnd, message, wParam, lParam);
+ }
+ }
+
+ #ifndef RGFW_NO_DPI
+ static HMODULE RGFW_Shcore_dll = NULL;
+ typedef HRESULT (WINAPI * PFN_GetDpiForMonitor)(HMONITOR,MONITOR_DPI_TYPE,UINT*,UINT*);
+ PFN_GetDpiForMonitor GetDpiForMonitorSRC = NULL;
+ #define GetDpiForMonitor GetDpiForMonitorSRC
+ #endif
+
+ __declspec(dllimport) u32 __stdcall timeBeginPeriod(u32 uPeriod);
+
+ #ifndef RGFW_NO_XINPUT
+ void RGFW_loadXInput(void) {
+ u32 i;
+ static const char* names[] = {
+ "xinput1_4.dll",
+ "xinput1_3.dll",
+ "xinput9_1_0.dll",
+ "xinput1_2.dll",
+ "xinput1_1.dll"
+ };
+
+ for (i = 0; i < sizeof(names) / sizeof(const char*); i++) {
+ RGFW_XInput_dll = LoadLibraryA(names[i]);
+
+ if (RGFW_XInput_dll) {
+ XInputGetStateSRC = (PFN_XInputGetState)(void*)GetProcAddress(RGFW_XInput_dll, "XInputGetState");
+
+ if (XInputGetStateSRC == NULL)
+ printf("Failed to load XInputGetState");
+ }
+ }
+ }
+ #endif
+
+ RGFWDEF void RGFW_init_buffer(RGFW_window* win);
+ void RGFW_init_buffer(RGFW_window* win) {
+#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER)
+ if (RGFW_bufferSize.w == 0 && RGFW_bufferSize.h == 0)
+ RGFW_bufferSize = RGFW_getScreenSize();
+
+ BITMAPV5HEADER bi = { 0 };
+ ZeroMemory(&bi, sizeof(bi));
+ bi.bV5Size = sizeof(bi);
+ bi.bV5Width = RGFW_bufferSize.w;
+ bi.bV5Height = -((LONG) RGFW_bufferSize.h);
+ bi.bV5Planes = 1;
+ bi.bV5BitCount = 32;
+ bi.bV5Compression = BI_BITFIELDS;
+ bi.bV5BlueMask = 0x00ff0000;
+ bi.bV5GreenMask = 0x0000ff00;
+ bi.bV5RedMask = 0x000000ff;
+ bi.bV5AlphaMask = 0xff000000;
+
+ win->src.bitmap = CreateDIBSection(win->src.hdc,
+ (BITMAPINFO*) &bi,
+ DIB_RGB_COLORS,
+ (void**) &win->buffer,
+ NULL,
+ (DWORD) 0);
+
+ win->src.hdcMem = CreateCompatibleDC(win->src.hdc);
+
+ #if defined(RGFW_OSMESA)
+ win->src.ctx = OSMesaCreateContext(OSMESA_RGBA, NULL);
+ OSMesaMakeCurrent(win->src.ctx, win->buffer, GL_UNSIGNED_BYTE, win->r.w, win->r.h);
+ #endif
+#else
+RGFW_UNUSED(win); /*!< if buffer rendering is not being used */
+#endif
+ }
+
+ void RGFW_window_setDND(RGFW_window* win, b8 allow) {
+ DragAcceptFiles(win->src.window, allow);
+ }
+
+ void RGFW_releaseCursor(RGFW_window* win) {
+ RGFW_UNUSED(win);
+ ClipCursor(NULL);
+ const RAWINPUTDEVICE id = { 0x01, 0x02, RIDEV_REMOVE, NULL };
+ RegisterRawInputDevices(&id, 1, sizeof(id));
+ }
+
+ void RGFW_captureCursor(RGFW_window* win, RGFW_rect rect) {
+ RGFW_UNUSED(win); RGFW_UNUSED(rect);
+
+ RECT clipRect;
+ GetClientRect(win->src.window, &clipRect);
+ ClientToScreen(win->src.window, (POINT*) &clipRect.left);
+ ClientToScreen(win->src.window, (POINT*) &clipRect.right);
+ ClipCursor(&clipRect);
+
+ const RAWINPUTDEVICE id = { 0x01, 0x02, 0, win->src.window };
+ RegisterRawInputDevices(&id, 1, sizeof(id));
+ }
+
+ RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, u16 args) {
+ #ifndef RGFW_NO_XINPUT
+ if (RGFW_XInput_dll == NULL)
+ RGFW_loadXInput();
+ #endif
+
+ #ifndef RGFW_NO_DPI
+ if (RGFW_Shcore_dll == NULL) {
+ RGFW_Shcore_dll = LoadLibraryA("shcore.dll");
+ GetDpiForMonitorSRC = (PFN_GetDpiForMonitor)(void*)GetProcAddress(RGFW_Shcore_dll, "GetDpiForMonitor");
+ SetProcessDPIAware();
+ }
+ #endif
+
+ if (wglinstance == NULL) {
+ wglinstance = LoadLibraryA("opengl32.dll");
+#ifdef RGFW_WGL_LOAD
+ wglCreateContextSRC = (PFN_wglCreateContext) GetProcAddress(wglinstance, "wglCreateContext");
+ wglDeleteContextSRC = (PFN_wglDeleteContext) GetProcAddress(wglinstance, "wglDeleteContext");
+ wglGetProcAddressSRC = (PFN_wglGetProcAddress) GetProcAddress(wglinstance, "wglGetProcAddress");
+ wglMakeCurrentSRC = (PFN_wglMakeCurrent) GetProcAddress(wglinstance, "wglMakeCurrent");
+ wglGetCurrentDCSRC = (PFN_wglGetCurrentDC) GetProcAddress(wglinstance, "wglGetCurrentDC");
+ wglGetCurrentContextSRC = (PFN_wglGetCurrentContext) GetProcAddress(wglinstance, "wglGetCurrentContext");
+#endif
+ }
+
+ if (name[0] == 0) name = (char*) " ";
+
+ RGFW_eventWindow.r = RGFW_RECT(-1, -1, -1, -1);
+ RGFW_eventWindow.src.window = NULL;
+
+ RGFW_window* win = RGFW_window_basic_init(rect, args);
+
+ win->src.maxSize = RGFW_AREA(0, 0);
+ win->src.minSize = RGFW_AREA(0, 0);
+
+
+ HINSTANCE inh = GetModuleHandleA(NULL);
+
+ #ifndef __cplusplus
+ WNDCLASSA Class = { 0 }; /*!< Setup the Window class. */
+ #else
+ WNDCLASSA Class = { };
+ #endif
+
+ if (RGFW_className == NULL)
+ RGFW_className = (char*)name;
+
+ Class.lpszClassName = RGFW_className;
+ Class.hInstance = inh;
+ Class.hCursor = LoadCursor(NULL, IDC_ARROW);
+ Class.lpfnWndProc = WndProc;
+
+ RegisterClassA(&Class);
+
+ DWORD window_style = WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
+
+ RECT windowRect, clientRect;
+
+ if (!(args & RGFW_NO_BORDER)) {
+ window_style |= WS_CAPTION | WS_SYSMENU | WS_BORDER | WS_MINIMIZEBOX;
+
+ if (!(args & RGFW_NO_RESIZE))
+ window_style |= WS_SIZEBOX | WS_MAXIMIZEBOX | WS_THICKFRAME;
+ } else
+ window_style |= WS_POPUP | WS_VISIBLE | WS_SYSMENU | WS_MINIMIZEBOX;
+
+ HWND dummyWin = CreateWindowA(Class.lpszClassName, name, window_style, win->r.x, win->r.y, win->r.w, win->r.h, 0, 0, inh, 0);
+
+ GetWindowRect(dummyWin, &windowRect);
+ GetClientRect(dummyWin, &clientRect);
+
+ win->src.hOffset = (windowRect.bottom - windowRect.top) - (clientRect.bottom - clientRect.top);
+ win->src.window = CreateWindowA(Class.lpszClassName, name, window_style, win->r.x, win->r.y, win->r.w, win->r.h + win->src.hOffset, 0, 0, inh, 0);
+
+ if (args & RGFW_ALLOW_DND) {
+ win->_winArgs |= RGFW_ALLOW_DND;
+ RGFW_window_setDND(win, 1);
+ }
+ win->src.hdc = GetDC(win->src.window);
+
+ if ((args & RGFW_NO_INIT_API) == 0) {
+#ifdef RGFW_DIRECTX
+ assert(FAILED(CreateDXGIFactory(&__uuidof(IDXGIFactory), (void**) &RGFW_dxInfo.pFactory)) == 0);
+
+ if (FAILED(RGFW_dxInfo.pFactory->lpVtbl->EnumAdapters(RGFW_dxInfo.pFactory, 0, &RGFW_dxInfo.pAdapter))) {
+ fprintf(stderr, "Failed to enumerate DXGI adapters\n");
+ RGFW_dxInfo.pFactory->lpVtbl->Release(RGFW_dxInfo.pFactory);
+ return NULL;
+ }
+
+ D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_11_0 };
+
+ if (FAILED(D3D11CreateDevice(RGFW_dxInfo.pAdapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, 0, featureLevels, 1, D3D11_SDK_VERSION, &RGFW_dxInfo.pDevice, NULL, &RGFW_dxInfo.pDeviceContext))) {
+ fprintf(stderr, "Failed to create Direct3D device\n");
+ RGFW_dxInfo.pAdapter->lpVtbl->Release(RGFW_dxInfo.pAdapter);
+ RGFW_dxInfo.pFactory->lpVtbl->Release(RGFW_dxInfo.pFactory);
+ return NULL;
+ }
+
+ DXGI_SWAP_CHAIN_DESC swapChainDesc = { 0 };
+ swapChainDesc.BufferCount = 1;
+ swapChainDesc.BufferDesc.Width = win->r.w;
+ swapChainDesc.BufferDesc.Height = win->r.h;
+ swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+ swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
+ swapChainDesc.OutputWindow = win->src.window;
+ swapChainDesc.SampleDesc.Count = 1;
+ swapChainDesc.SampleDesc.Quality = 0;
+ swapChainDesc.Windowed = TRUE;
+ RGFW_dxInfo.pFactory->lpVtbl->CreateSwapChain(RGFW_dxInfo.pFactory, (IUnknown*) RGFW_dxInfo.pDevice, &swapChainDesc, &win->src.swapchain);
+
+ ID3D11Texture2D* pBackBuffer;
+ win->src.swapchain->lpVtbl->GetBuffer(win->src.swapchain, 0, &__uuidof(ID3D11Texture2D), (LPVOID*) &pBackBuffer);
+ RGFW_dxInfo.pDevice->lpVtbl->CreateRenderTargetView(RGFW_dxInfo.pDevice, (ID3D11Resource*) pBackBuffer, NULL, &win->src.renderTargetView);
+ pBackBuffer->lpVtbl->Release(pBackBuffer);
+
+ D3D11_TEXTURE2D_DESC depthStencilDesc = { 0 };
+ depthStencilDesc.Width = win->r.w;
+ depthStencilDesc.Height = win->r.h;
+ depthStencilDesc.MipLevels = 1;
+ depthStencilDesc.ArraySize = 1;
+ depthStencilDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
+ depthStencilDesc.SampleDesc.Count = 1;
+ depthStencilDesc.SampleDesc.Quality = 0;
+ depthStencilDesc.Usage = D3D11_USAGE_DEFAULT;
+ depthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
+
+ ID3D11Texture2D* pDepthStencilTexture = NULL;
+ RGFW_dxInfo.pDevice->lpVtbl->CreateTexture2D(RGFW_dxInfo.pDevice, &depthStencilDesc, NULL, &pDepthStencilTexture);
+
+ D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc = { 0 };
+ depthStencilViewDesc.Format = depthStencilDesc.Format;
+ depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
+ depthStencilViewDesc.Texture2D.MipSlice = 0;
+
+ RGFW_dxInfo.pDevice->lpVtbl->CreateDepthStencilView(RGFW_dxInfo.pDevice, (ID3D11Resource*) pDepthStencilTexture, &depthStencilViewDesc, &win->src.pDepthStencilView);
+
+ pDepthStencilTexture->lpVtbl->Release(pDepthStencilTexture);
+
+ RGFW_dxInfo.pDeviceContext->lpVtbl->OMSetRenderTargets(RGFW_dxInfo.pDeviceContext, 1, &win->src.renderTargetView, win->src.pDepthStencilView);
+#endif
+
+#ifdef RGFW_OPENGL
+ HDC dummy_dc = GetDC(dummyWin);
+
+ u32 pfd_flags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
+
+ //if (RGFW_DOUBLE_BUFFER)
+ pfd_flags |= PFD_DOUBLEBUFFER;
+
+ PIXELFORMATDESCRIPTOR pfd = {
+ sizeof(pfd),
+ 1, /* version */
+ pfd_flags,
+ PFD_TYPE_RGBA, /* ipixel type */
+ 24, /* color bits */
+ 0, 0, 0, 0, 0, 0,
+ 8, /* alpha bits */
+ 0, 0, 0, 0, 0, 0,
+ 32, /* depth bits */
+ 8, /* stencil bits */
+ 0,
+ PFD_MAIN_PLANE, /* Layer type */
+ 0, 0, 0, 0
+ };
+
+ int pixel_format = ChoosePixelFormat(dummy_dc, &pfd);
+ SetPixelFormat(dummy_dc, pixel_format, &pfd);
+
+ HGLRC dummy_context = wglCreateContext(dummy_dc);
+ wglMakeCurrent(dummy_dc, dummy_context);
+
+ if (wglChoosePixelFormatARB == NULL) {
+ wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC) (void*) wglGetProcAddress("wglCreateContextAttribsARB");
+ wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC) (void*)wglGetProcAddress("wglChoosePixelFormatARB");
+ }
+
+ wglMakeCurrent(dummy_dc, 0);
+ wglDeleteContext(dummy_context);
+ ReleaseDC(dummyWin, dummy_dc);
+
+ /* try to create the pixel format we want for opengl and then try to create an opengl context for the specified version */
+ if (wglCreateContextAttribsARB != NULL) {
+ PIXELFORMATDESCRIPTOR pfd = {sizeof(pfd), 1, pfd_flags, PFD_TYPE_RGBA, 32, 8, PFD_MAIN_PLANE, 24, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+ if (args & RGFW_OPENGL_SOFTWARE)
+ pfd.dwFlags |= PFD_GENERIC_FORMAT | PFD_GENERIC_ACCELERATED;
+
+ if (wglChoosePixelFormatARB != NULL) {
+ i32* pixel_format_attribs = (i32*)RGFW_initFormatAttribs(args & RGFW_OPENGL_SOFTWARE);
+
+ int pixel_format;
+ UINT num_formats;
+ wglChoosePixelFormatARB(win->src.hdc, pixel_format_attribs, 0, 1, &pixel_format, &num_formats);
+ if (!num_formats) {
+ printf("Failed to create a pixel format for WGL.\n");
+ }
+
+ DescribePixelFormat(win->src.hdc, pixel_format, sizeof(pfd), &pfd);
+ if (!SetPixelFormat(win->src.hdc, pixel_format, &pfd)) {
+ printf("Failed to set the WGL pixel format.\n");
+ }
+ }
+
+ /* create opengl/WGL context for the specified version */
+ u32 index = 0;
+ i32 attribs[40];
+
+ if (RGFW_profile == RGFW_GL_CORE) {
+ SET_ATTRIB(WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB);
+ }
+ else {
+ SET_ATTRIB(WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB);
+ }
+
+ if (RGFW_majorVersion || RGFW_minorVersion) {
+ SET_ATTRIB(WGL_CONTEXT_MAJOR_VERSION_ARB, RGFW_majorVersion);
+ SET_ATTRIB(WGL_CONTEXT_MINOR_VERSION_ARB, RGFW_minorVersion);
+ }
+
+ SET_ATTRIB(0, 0);
+
+ win->src.ctx = (HGLRC)wglCreateContextAttribsARB(win->src.hdc, NULL, attribs);
+ } else { /* fall back to a default context (probably opengl 2 or something) */
+ fprintf(stderr, "Failed to create an accelerated OpenGL Context\n");
+
+ int pixel_format = ChoosePixelFormat(win->src.hdc, &pfd);
+ SetPixelFormat(win->src.hdc, pixel_format, &pfd);
+
+ win->src.ctx = wglCreateContext(win->src.hdc);
+ }
+
+ wglMakeCurrent(win->src.hdc, win->src.ctx);
+#endif
+ }
+
+#ifdef RGFW_OSMESA
+#ifdef RGFW_LINK_OSM ESA
+ OSMesaMakeCurrentSource = (PFN_OSMesaMakeCurrent) GetProcAddress(win->src.hdc, "OSMesaMakeCurrent");
+ OSMesaCreateContextSource = (PFN_OSMesaCreateContext) GetProcAddress(win->src.hdc, "OSMesaCreateContext");
+ OSMesaDestroyContextSource = (PFN_OSMesaDestroyContext) GetProcAddress(win->src.hdc, "OSMesaDestroyContext");
+#endif
+#endif
+
+#ifdef RGFW_OPENGL
+ if ((args & RGFW_NO_INIT_API) == 0) {
+ ReleaseDC(win->src.window, win->src.hdc);
+ win->src.hdc = GetDC(win->src.window);
+ wglMakeCurrent(win->src.hdc, win->src.ctx);
+ }
+#endif
+
+ DestroyWindow(dummyWin);
+ RGFW_init_buffer(win);
+
+
+ #ifndef RGFW_NO_MONITOR
+ if (args & RGFW_SCALE_TO_MONITOR)
+ RGFW_window_scaleToMonitor(win);
+ #endif
+
+ if (args & RGFW_CENTER) {
+ RGFW_area screenR = RGFW_getScreenSize();
+ RGFW_window_move(win, RGFW_POINT((screenR.w - win->r.w) / 2, (screenR.h - win->r.h) / 2));
+ }
+
+#ifdef RGFW_EGL
+ if ((args & RGFW_NO_INIT_API) == 0)
+ RGFW_createOpenGLContext(win);
+#endif
+
+ if (args & RGFW_HIDE_MOUSE)
+ RGFW_window_showMouse(win, 0);
+
+ if (args & RGFW_TRANSPARENT_WINDOW) {
+ SetWindowLong(win->src.window, GWL_EXSTYLE, GetWindowLong(win->src.window, GWL_EXSTYLE) | WS_EX_LAYERED);
+ SetLayeredWindowAttributes(win->src.window, RGB(255, 255, 255), RGFW_ALPHA, LWA_ALPHA);
+ }
+
+ ShowWindow(win->src.window, SW_SHOWNORMAL);
+
+ if (RGFW_root == NULL)
+ RGFW_root = win;
+
+ #ifdef RGFW_OPENGL
+ else
+ wglShareLists(RGFW_root->src.ctx, win->src.ctx);
+ #endif
+
+ return win;
+ }
+
+ void RGFW_window_setBorder(RGFW_window* win, u8 border) {
+ DWORD style = GetWindowLong(win->src.window, GWL_STYLE);
+
+ if (border == 0) {
+ SetWindowLong(win->src.window, GWL_STYLE, style & ~WS_OVERLAPPEDWINDOW);
+ SetWindowPos(
+ win->src.window, HWND_TOP, 0, 0, 0, 0,
+ SWP_NOZORDER | SWP_FRAMECHANGED | SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE
+ );
+ }
+ else {
+ SetWindowLong(win->src.window, GWL_STYLE, style | WS_OVERLAPPEDWINDOW);
+ SetWindowPos(
+ win->src.window, HWND_TOP, 0, 0, 0, 0,
+ SWP_NOZORDER | SWP_FRAMECHANGED | SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE
+ );
+ }
+ }
+
+
+ RGFW_area RGFW_getScreenSize(void) {
+ return RGFW_AREA(GetDeviceCaps(GetDC(NULL), HORZRES), GetDeviceCaps(GetDC(NULL), VERTRES));
+ }
+
+ RGFW_point RGFW_getGlobalMousePoint(void) {
+ POINT p;
+ GetCursorPos(&p);
+
+ return RGFW_POINT(p.x, p.y);
+ }
+
+ RGFW_point RGFW_window_getMousePoint(RGFW_window* win) {
+ POINT p;
+ GetCursorPos(&p);
+ ScreenToClient(win->src.window, &p);
+
+ return RGFW_POINT(p.x, p.y);
+ }
+
+ void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a) {
+ assert(win != NULL);
+ win->src.minSize = a;
+ }
+
+ void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a) {
+ assert(win != NULL);
+ win->src.maxSize = a;
+ }
+
+
+ void RGFW_window_minimize(RGFW_window* win) {
+ assert(win != NULL);
+
+ ShowWindow(win->src.window, SW_MINIMIZE);
+ }
+
+ void RGFW_window_restore(RGFW_window* win) {
+ assert(win != NULL);
+
+ ShowWindow(win->src.window, SW_RESTORE);
+ }
+
+
+ u8 RGFW_xinput2RGFW[] = {
+ RGFW_JS_A, /* or PS X button */
+ RGFW_JS_B, /* or PS circle button */
+ RGFW_JS_X, /* or PS square button */
+ RGFW_JS_Y, /* or PS triangle button */
+ RGFW_JS_R1, /* right bumper */
+ RGFW_JS_L1, /* left bump */
+ RGFW_JS_L2, /* left trigger*/
+ RGFW_JS_R2, /* right trigger */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ RGFW_JS_UP, /* dpad up */
+ RGFW_JS_DOWN, /* dpad down*/
+ RGFW_JS_LEFT, /* dpad left */
+ RGFW_JS_RIGHT, /* dpad right */
+ RGFW_JS_START, /* start button */
+ RGFW_JS_SELECT/* select button */
+ };
+
+ static i32 RGFW_checkXInput(RGFW_window* win, RGFW_Event* e) {
+ RGFW_UNUSED(win)
+
+ size_t i;
+ for (i = 0; i < 4; i++) {
+ XINPUT_KEYSTROKE keystroke;
+
+ if (XInputGetKeystroke == NULL)
+ return 0;
+
+ DWORD result = XInputGetKeystroke((DWORD)i, 0, &keystroke);
+
+ if ((keystroke.Flags & XINPUT_KEYSTROKE_REPEAT) == 0 && result != ERROR_EMPTY) {
+ if (result != ERROR_SUCCESS)
+ return 0;
+
+ if (keystroke.VirtualKey > VK_PAD_BACK)
+ continue;
+
+ // RGFW_jsButtonPressed + 1 = RGFW_jsButtonReleased
+ e->type = RGFW_jsButtonPressed + !(keystroke.Flags & XINPUT_KEYSTROKE_KEYDOWN);
+ e->button = RGFW_xinput2RGFW[keystroke.VirtualKey - 0x5800];
+ RGFW_jsPressed[i][e->button] = !(keystroke.Flags & XINPUT_KEYSTROKE_KEYDOWN);
+
+ return 1;
+ }
+
+ XINPUT_STATE state;
+ if (XInputGetState == NULL ||
+ XInputGetState((DWORD) i, &state) == ERROR_DEVICE_NOT_CONNECTED
+ )
+ return 0;
+#define INPUT_DEADZONE ( 0.24f * (float)(0x7FFF) ) // Default to 24% of the +/- 32767 range. This is a reasonable default value but can be altered if needed.
+
+ if ((state.Gamepad.sThumbLX < INPUT_DEADZONE &&
+ state.Gamepad.sThumbLX > -INPUT_DEADZONE) &&
+ (state.Gamepad.sThumbLY < INPUT_DEADZONE &&
+ state.Gamepad.sThumbLY > -INPUT_DEADZONE))
+ {
+ state.Gamepad.sThumbLX = 0;
+ state.Gamepad.sThumbLY = 0;
+ }
+
+ if ((state.Gamepad.sThumbRX < INPUT_DEADZONE &&
+ state.Gamepad.sThumbRX > -INPUT_DEADZONE) &&
+ (state.Gamepad.sThumbRY < INPUT_DEADZONE &&
+ state.Gamepad.sThumbRY > -INPUT_DEADZONE))
+ {
+ state.Gamepad.sThumbRX = 0;
+ state.Gamepad.sThumbRY = 0;
+ }
+
+ e->axisesCount = 2;
+ RGFW_point axis1 = RGFW_POINT(state.Gamepad.sThumbLX, state.Gamepad.sThumbLY);
+ RGFW_point axis2 = RGFW_POINT(state.Gamepad.sThumbRX, state.Gamepad.sThumbRY);
+
+ if (axis1.x != e->axis[0].x || axis1.y != e->axis[0].y || axis2.x != e->axis[1].x || axis2.y != e->axis[1].y) {
+ e->type = RGFW_jsAxisMove;
+
+ e->axis[0] = axis1;
+ e->axis[1] = axis2;
+
+ return 1;
+ }
+
+ e->axis[0] = axis1;
+ e->axis[1] = axis2;
+ }
+
+ return 0;
+ }
+
+ void RGFW_stopCheckEvents(void) {
+ PostMessageW(RGFW_root->src.window, WM_NULL, 0, 0);
+ }
+
+ void RGFW_window_eventWait(RGFW_window* win, i32 waitMS) {
+ RGFW_UNUSED(win);
+
+ MsgWaitForMultipleObjects(0, NULL, FALSE, (DWORD) (waitMS * 1e3), QS_ALLINPUT);
+ }
+
+ RGFW_Event* RGFW_window_checkEvent(RGFW_window* win) {
+ assert(win != NULL);
+
+ if (win->event.type == RGFW_quit) {
+ return NULL;
+ }
+
+ MSG msg;
+
+ if (RGFW_eventWindow.src.window == win->src.window) {
+ if (RGFW_eventWindow.r.x != -1) {
+ win->r.x = RGFW_eventWindow.r.x;
+ win->r.y = RGFW_eventWindow.r.y;
+ win->event.type = RGFW_windowMoved;
+ RGFW_windowMoveCallback(win, win->r);
+ }
+
+ if (RGFW_eventWindow.r.w != -1) {
+ win->r.w = RGFW_eventWindow.r.w;
+ win->r.h = RGFW_eventWindow.r.h;
+ win->event.type = RGFW_windowResized;
+ RGFW_windowResizeCallback(win, win->r);
+ }
+
+ RGFW_eventWindow.src.window = NULL;
+ RGFW_eventWindow.r = RGFW_RECT(-1, -1, -1, -1);
+
+ return &win->event;
+ }
+
+
+ static HDROP drop;
+
+ if (win->event.type == RGFW_dnd_init) {
+ if (win->event.droppedFilesCount) {
+ u32 i;
+ for (i = 0; i < win->event.droppedFilesCount; i++)
+ win->event.droppedFiles[i][0] = '\0';
+ }
+
+ win->event.droppedFilesCount = 0;
+ win->event.droppedFilesCount = DragQueryFileW(drop, 0xffffffff, NULL, 0);
+ //win->event.droppedFiles = (char**)RGFW_CALLOC(win->event.droppedFilesCount, sizeof(char*));
+
+ u32 i;
+ for (i = 0; i < win->event.droppedFilesCount; i++) {
+ const UINT length = DragQueryFileW(drop, i, NULL, 0);
+ WCHAR* buffer = (WCHAR*) RGFW_CALLOC((size_t) length + 1, sizeof(WCHAR));
+
+ DragQueryFileW(drop, i, buffer, length + 1);
+ strncpy(win->event.droppedFiles[i], createUTF8FromWideStringWin32(buffer), RGFW_MAX_PATH);
+ win->event.droppedFiles[i][RGFW_MAX_PATH - 1] = '\0';
+ RGFW_FREE(buffer);
+ }
+
+ DragFinish(drop);
+ RGFW_dndCallback(win, win->event.droppedFiles, win->event.droppedFilesCount);
+
+ win->event.type = RGFW_dnd;
+ return &win->event;
+ }
+
+ win->event.inFocus = (GetForegroundWindow() == win->src.window);
+
+ if (RGFW_checkXInput(win, &win->event))
+ return &win->event;
+
+ static BYTE keyboardState[256];
+
+ if (PeekMessageA(&msg, win->src.window, 0u, 0u, PM_REMOVE)) {
+ switch (msg.message) {
+ case WM_CLOSE:
+ case WM_QUIT:
+ RGFW_windowQuitCallback(win);
+ win->event.type = RGFW_quit;
+ break;
+
+ case WM_ACTIVATE:
+ win->event.inFocus = (LOWORD(msg.wParam) == WA_INACTIVE);
+
+ if (win->event.inFocus) {
+ win->event.type = RGFW_focusIn;
+ RGFW_focusCallback(win, 1);
+ }
+ else {
+ win->event.type = RGFW_focusOut;
+ RGFW_focusCallback(win, 0);
+ }
+
+ break;
+
+ case WM_PAINT:
+ win->event.type = RGFW_windowRefresh;
+ RGFW_windowRefreshCallback(win);
+ break;
+
+ case WM_MOUSELEAVE:
+ win->event.type = RGFW_mouseLeave;
+ win->_winArgs |= RGFW_MOUSE_LEFT;
+ RGFW_mouseNotifyCallBack(win, win->event.point, 0);
+ break;
+
+ case WM_KEYUP: {
+ win->event.keyCode = RGFW_apiKeyCodeToRGFW((u32) msg.wParam);
+
+ RGFW_keyboard[win->event.keyCode].prev = RGFW_isPressed(win, win->event.keyCode);
+
+ static char keyName[16];
+
+ {
+ GetKeyNameTextA((LONG) msg.lParam, keyName, 16);
+
+ if ((!(GetKeyState(VK_CAPITAL) & 0x0001) && !(GetKeyState(VK_SHIFT) & 0x8000)) ||
+ ((GetKeyState(VK_CAPITAL) & 0x0001) && (GetKeyState(VK_SHIFT) & 0x8000))) {
+ CharLowerBuffA(keyName, 16);
+ }
+ }
+
+ RGFW_updateLockState(win, (GetKeyState(VK_CAPITAL) & 0x0001), (GetKeyState(VK_NUMLOCK) & 0x0001));
+
+ strncpy(win->event.keyName, keyName, 16);
+
+ if (RGFW_isPressed(win, RGFW_ShiftL)) {
+ ToAscii((UINT) msg.wParam, MapVirtualKey((UINT) msg.wParam, MAPVK_VK_TO_CHAR),
+ keyboardState, (LPWORD) win->event.keyName, 0);
+ }
+
+ win->event.type = RGFW_keyReleased;
+ RGFW_keyboard[win->event.keyCode].current = 0;
+ RGFW_keyCallback(win, win->event.keyCode, win->event.keyName, win->event.lockState, 0);
+ break;
+ }
+ case WM_KEYDOWN: {
+ win->event.keyCode = RGFW_apiKeyCodeToRGFW((u32) msg.wParam);
+
+ RGFW_keyboard[win->event.keyCode].prev = RGFW_isPressed(win, win->event.keyCode);
+
+ static char keyName[16];
+
+ {
+ GetKeyNameTextA((LONG) msg.lParam, keyName, 16);
+
+ if ((!(GetKeyState(VK_CAPITAL) & 0x0001) && !(GetKeyState(VK_SHIFT) & 0x8000)) ||
+ ((GetKeyState(VK_CAPITAL) & 0x0001) && (GetKeyState(VK_SHIFT) & 0x8000))) {
+ CharLowerBuffA(keyName, 16);
+ }
+ }
+
+ RGFW_updateLockState(win, (GetKeyState(VK_CAPITAL) & 0x0001), (GetKeyState(VK_NUMLOCK) & 0x0001));
+
+ strncpy(win->event.keyName, keyName, 16);
+
+ if (RGFW_isPressed(win, RGFW_ShiftL) & 0x8000) {
+ ToAscii((UINT) msg.wParam, MapVirtualKey((UINT) msg.wParam, MAPVK_VK_TO_CHAR),
+ keyboardState, (LPWORD) win->event.keyName, 0);
+ }
+
+ win->event.type = RGFW_keyPressed;
+ win->event.repeat = RGFW_isPressed(win, win->event.keyCode);
+ RGFW_keyboard[win->event.keyCode].current = 1;
+ RGFW_keyCallback(win, win->event.keyCode, win->event.keyName, win->event.lockState, 1);
+ break;
+ }
+
+ case WM_MOUSEMOVE:
+ if ((win->_winArgs & RGFW_HOLD_MOUSE))
+ break;
+
+ win->event.type = RGFW_mousePosChanged;
+
+ win->event.point.x = GET_X_LPARAM(msg.lParam);
+ win->event.point.y = GET_Y_LPARAM(msg.lParam);
+
+ RGFW_mousePosCallback(win, win->event.point);
+
+ if (win->_winArgs & RGFW_MOUSE_LEFT) {
+ win->_winArgs ^= RGFW_MOUSE_LEFT;
+ win->event.type = RGFW_mouseEnter;
+ RGFW_mouseNotifyCallBack(win, win->event.point, 1);
+ }
+
+ break;
+
+ case WM_INPUT: {
+ if (!(win->_winArgs & RGFW_HOLD_MOUSE))
+ break;
+
+ unsigned size = sizeof(RAWINPUT);
+ static RAWINPUT raw[sizeof(RAWINPUT)];
+ GetRawInputData((HRAWINPUT)msg.lParam, RID_INPUT, raw, &size, sizeof(RAWINPUTHEADER));
+
+ if (raw->header.dwType != RIM_TYPEMOUSE || (raw->data.mouse.lLastX == 0 && raw->data.mouse.lLastY == 0) )
+ break;
+
+ win->event.type = RGFW_mousePosChanged;
+ win->event.point.x = raw->data.mouse.lLastX;
+ win->event.point.y = raw->data.mouse.lLastY;
+ break;
+ }
+
+ case WM_LBUTTONDOWN:
+ win->event.button = RGFW_mouseLeft;
+ RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current;
+ RGFW_mouseButtons[win->event.button].current = 1;
+ win->event.type = RGFW_mouseButtonPressed;
+ RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1);
+ break;
+ case WM_RBUTTONDOWN:
+ win->event.button = RGFW_mouseRight;
+ win->event.type = RGFW_mouseButtonPressed;
+ RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current;
+ RGFW_mouseButtons[win->event.button].current = 1;
+ RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1);
+ break;
+ case WM_MBUTTONDOWN:
+ win->event.button = RGFW_mouseMiddle;
+ win->event.type = RGFW_mouseButtonPressed;
+ RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current;
+ RGFW_mouseButtons[win->event.button].current = 1;
+ RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1);
+ break;
+
+ case WM_MOUSEWHEEL:
+ if (msg.wParam > 0)
+ win->event.button = RGFW_mouseScrollUp;
+ else
+ win->event.button = RGFW_mouseScrollDown;
+
+ RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current;
+ RGFW_mouseButtons[win->event.button].current = 1;
+
+ win->event.scroll = (SHORT) HIWORD(msg.wParam) / (double) WHEEL_DELTA;
+
+ win->event.type = RGFW_mouseButtonPressed;
+ RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1);
+ break;
+
+ case WM_LBUTTONUP:
+
+ win->event.button = RGFW_mouseLeft;
+ win->event.type = RGFW_mouseButtonReleased;
+
+ RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current;
+ RGFW_mouseButtons[win->event.button].current = 0;
+ RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0);
+ break;
+ case WM_RBUTTONUP:
+ win->event.button = RGFW_mouseRight;
+ win->event.type = RGFW_mouseButtonReleased;
+
+ RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current;
+ RGFW_mouseButtons[win->event.button].current = 0;
+ RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0);
+ break;
+ case WM_MBUTTONUP:
+ win->event.button = RGFW_mouseMiddle;
+ win->event.type = RGFW_mouseButtonReleased;
+
+ RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current;
+ RGFW_mouseButtons[win->event.button].current = 0;
+ RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0);
+ break;
+
+ /*
+ much of this event is source from glfw
+ */
+ case WM_DROPFILES: {
+ win->event.type = RGFW_dnd_init;
+
+ drop = (HDROP) msg.wParam;
+ POINT pt;
+
+ /* Move the mouse to the position of the drop */
+ DragQueryPoint(drop, &pt);
+
+ win->event.point.x = pt.x;
+ win->event.point.y = pt.y;
+
+ RGFW_dndInitCallback(win, win->event.point);
+ }
+ break;
+ case WM_GETMINMAXINFO:
+ {
+ if (win->src.maxSize.w == 0 && win->src.maxSize.h == 0)
+ break;
+
+ MINMAXINFO* mmi = (MINMAXINFO*) msg.lParam;
+ mmi->ptMinTrackSize.x = win->src.minSize.w;
+ mmi->ptMinTrackSize.y = win->src.minSize.h;
+ mmi->ptMaxTrackSize.x = win->src.maxSize.w;
+ mmi->ptMaxTrackSize.y = win->src.maxSize.h;
+ return 0;
+ }
+ default:
+ win->event.type = 0;
+ break;
+ }
+
+ TranslateMessage(&msg);
+ DispatchMessageA(&msg);
+ }
+
+ else
+ win->event.type = 0;
+
+ if (!IsWindow(win->src.window)) {
+ win->event.type = RGFW_quit;
+ RGFW_windowQuitCallback(win);
+ }
+
+ if (win->event.type)
+ return &win->event;
+ else
+ return NULL;
+ }
+
+ u8 RGFW_window_isFullscreen(RGFW_window* win) {
+ assert(win != NULL);
+
+ #ifndef __cplusplus
+ WINDOWPLACEMENT placement = { 0 };
+ #else
+ WINDOWPLACEMENT placement = { };
+ #endif
+ GetWindowPlacement(win->src.window, &placement);
+ return placement.showCmd == SW_SHOWMAXIMIZED;
+ }
+
+ u8 RGFW_window_isHidden(RGFW_window* win) {
+ assert(win != NULL);
+
+ return IsWindowVisible(win->src.window) == 0 && !RGFW_window_isMinimized(win);
+ }
+
+ u8 RGFW_window_isMinimized(RGFW_window* win) {
+ assert(win != NULL);
+
+ #ifndef __cplusplus
+ WINDOWPLACEMENT placement = { 0 };
+ #else
+ WINDOWPLACEMENT placement = { };
+ #endif
+ GetWindowPlacement(win->src.window, &placement);
+ return placement.showCmd == SW_SHOWMINIMIZED;
+ }
+
+ u8 RGFW_window_isMaximized(RGFW_window* win) {
+ assert(win != NULL);
+
+ #ifndef __cplusplus
+ WINDOWPLACEMENT placement = { 0 };
+ #else
+ WINDOWPLACEMENT placement = { };
+ #endif
+ GetWindowPlacement(win->src.window, &placement);
+ return placement.showCmd == SW_SHOWMAXIMIZED;
+ }
+
+ typedef struct { int iIndex; HMONITOR hMonitor; } RGFW_mInfo;
+ BOOL CALLBACK GetMonitorByHandle(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) {
+ RGFW_UNUSED(hdcMonitor)
+ RGFW_UNUSED(lprcMonitor)
+
+ RGFW_mInfo* info = (RGFW_mInfo*) dwData;
+ if (info->hMonitor == hMonitor)
+ return FALSE;
+
+ info->iIndex++;
+ return TRUE;
+ }
+
+ #ifndef RGFW_NO_MONITOR
+ RGFW_monitor win32CreateMonitor(HMONITOR src) {
+ RGFW_monitor monitor;
+ MONITORINFO monitorInfo;
+
+ monitorInfo.cbSize = sizeof(MONITORINFO);
+ GetMonitorInfoA(src, &monitorInfo);
+
+ RGFW_mInfo info;
+ info.iIndex = 0;
+ info.hMonitor = src;
+
+ /* get the monitor's index */
+ if (EnumDisplayMonitors(NULL, NULL, GetMonitorByHandle, (LPARAM) &info)) {
+ DISPLAY_DEVICEA dd;
+ dd.cb = sizeof(dd);
+
+ /* loop through the devices until you find a device with the monitor's index */
+ size_t deviceIndex;
+ for (deviceIndex = 0; EnumDisplayDevicesA(0, (DWORD) deviceIndex, &dd, 0); deviceIndex++) {
+ char* deviceName = dd.DeviceName;
+ if (EnumDisplayDevicesA(deviceName, info.iIndex, &dd, 0)) {
+ strncpy(monitor.name, dd.DeviceString, 128); /*!< copy the monitor's name */
+ break;
+ }
+ }
+ }
+
+ monitor.rect.x = monitorInfo.rcWork.left;
+ monitor.rect.y = monitorInfo.rcWork.top;
+ monitor.rect.w = monitorInfo.rcWork.right - monitorInfo.rcWork.left;
+ monitor.rect.h = monitorInfo.rcWork.bottom - monitorInfo.rcWork.top;
+
+#ifndef RGFW_NO_DPI
+ #ifndef USER_DEFAULT_SCREEN_DPI
+ #define USER_DEFAULT_SCREEN_DPI 96
+ #endif
+
+ if (GetDpiForMonitor != NULL) {
+ u32 x, y;
+ GetDpiForMonitor(src, MDT_EFFECTIVE_DPI, &x, &y);
+
+ monitor.scaleX = (float) (x) / (float) USER_DEFAULT_SCREEN_DPI;
+ monitor.scaleY = (float) (y) / (float) USER_DEFAULT_SCREEN_DPI;
+ }
+#endif
+
+ HDC hdc = GetDC(NULL);
+ /* get pixels per inch */
+ i32 ppiX = GetDeviceCaps(hdc, LOGPIXELSX);
+ i32 ppiY = GetDeviceCaps(hdc, LOGPIXELSY);
+ ReleaseDC(NULL, hdc);
+
+ /* Calculate physical height in inches */
+ monitor.physW = GetSystemMetrics(SM_CYSCREEN) / (float) ppiX;
+ monitor.physH = GetSystemMetrics(SM_CXSCREEN) / (float) ppiY;
+
+ return monitor;
+ }
+ #endif /* RGFW_NO_MONITOR */
+
+
+ #ifndef RGFW_NO_MONITOR
+ RGFW_monitor RGFW_monitors[6];
+ BOOL CALLBACK GetMonitorHandle(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) {
+ RGFW_UNUSED(hdcMonitor)
+ RGFW_UNUSED(lprcMonitor)
+
+ RGFW_mInfo* info = (RGFW_mInfo*) dwData;
+
+ if (info->iIndex >= 6)
+ return FALSE;
+
+ RGFW_monitors[info->iIndex] = win32CreateMonitor(hMonitor);
+ info->iIndex++;
+
+ return TRUE;
+ }
+
+ RGFW_monitor RGFW_getPrimaryMonitor(void) {
+ #ifdef __cplusplus
+ return win32CreateMonitor(MonitorFromPoint({ 0, 0 }, MONITOR_DEFAULTTOPRIMARY));
+ #else
+ return win32CreateMonitor(MonitorFromPoint((POINT) { 0, 0 }, MONITOR_DEFAULTTOPRIMARY));
+ #endif
+ }
+
+ RGFW_monitor* RGFW_getMonitors(void) {
+ RGFW_mInfo info;
+ info.iIndex = 0;
+ while (EnumDisplayMonitors(NULL, NULL, GetMonitorHandle, (LPARAM) &info));
+
+ return RGFW_monitors;
+ }
+
+ RGFW_monitor RGFW_window_getMonitor(RGFW_window* win) {
+ HMONITOR src = MonitorFromWindow(win->src.window, MONITOR_DEFAULTTOPRIMARY);
+ return win32CreateMonitor(src);
+ }
+ #endif
+
+ HICON RGFW_loadHandleImage(RGFW_window* win, u8* src, RGFW_area a, BOOL icon) {
+ assert(win != NULL);
+
+ u32 i;
+ HDC dc;
+ HICON handle;
+ HBITMAP color, mask;
+ BITMAPV5HEADER bi;
+ ICONINFO ii;
+ u8* target = NULL;
+ u8* source = src;
+
+ ZeroMemory(&bi, sizeof(bi));
+ bi.bV5Size = sizeof(bi);
+ bi.bV5Width = a.w;
+ bi.bV5Height = -((LONG) a.h);
+ bi.bV5Planes = 1;
+ bi.bV5BitCount = 32;
+ bi.bV5Compression = BI_BITFIELDS;
+ bi.bV5RedMask = 0x00ff0000;
+ bi.bV5GreenMask = 0x0000ff00;
+ bi.bV5BlueMask = 0x000000ff;
+ bi.bV5AlphaMask = 0xff000000;
+
+ dc = GetDC(NULL);
+ color = CreateDIBSection(dc,
+ (BITMAPINFO*) &bi,
+ DIB_RGB_COLORS,
+ (void**) &target,
+ NULL,
+ (DWORD) 0);
+ ReleaseDC(NULL, dc);
+
+ mask = CreateBitmap(a.w, a.h, 1, 1, NULL);
+
+ for (i = 0; i < a.w * a.h; i++) {
+ target[0] = source[2];
+ target[1] = source[1];
+ target[2] = source[0];
+ target[3] = source[3];
+ target += 4;
+ source += 4;
+ }
+
+ ZeroMemory(&ii, sizeof(ii));
+ ii.fIcon = icon;
+ ii.xHotspot = 0;
+ ii.yHotspot = 0;
+ ii.hbmMask = mask;
+ ii.hbmColor = color;
+
+ handle = CreateIconIndirect(&ii);
+
+ DeleteObject(color);
+ DeleteObject(mask);
+
+ return handle;
+ }
+
+ void RGFW_window_setMouse(RGFW_window* win, u8* image, RGFW_area a, i32 channels) {
+ assert(win != NULL);
+ RGFW_UNUSED(channels)
+
+ HCURSOR cursor = (HCURSOR) RGFW_loadHandleImage(win, image, a, FALSE);
+ SetClassLongPtrA(win->src.window, GCLP_HCURSOR, (LPARAM) cursor);
+ SetCursor(cursor);
+ DestroyCursor(cursor);
+ }
+
+ void RGFW_window_setMouseDefault(RGFW_window* win) {
+ RGFW_window_setMouseStandard(win, RGFW_MOUSE_ARROW);
+ }
+
+ void RGFW_window_setMouseStandard(RGFW_window* win, u8 mouse) {
+ assert(win != NULL);
+
+ if (mouse > (sizeof(RGFW_mouseIconSrc) / sizeof(u32)))
+ return;
+
+ char* icon = MAKEINTRESOURCEA(RGFW_mouseIconSrc[mouse]);
+
+ SetClassLongPtrA(win->src.window, GCLP_HCURSOR, (LPARAM) LoadCursorA(NULL, icon));
+ SetCursor(LoadCursorA(NULL, icon));
+ }
+
+ void RGFW_window_hide(RGFW_window* win) {
+ ShowWindow(win->src.window, SW_HIDE);
+ }
+
+ void RGFW_window_show(RGFW_window* win) {
+ ShowWindow(win->src.window, SW_RESTORE);
+ }
+
+ void RGFW_window_close(RGFW_window* win) {
+ assert(win != NULL);
+
+#ifdef RGFW_EGL
+ RGFW_closeEGL(win);
+#endif
+
+ if (win == RGFW_root) {
+#ifdef RGFW_DIRECTX
+ RGFW_dxInfo.pDeviceContext->lpVtbl->Release(RGFW_dxInfo.pDeviceContext);
+ RGFW_dxInfo.pDevice->lpVtbl->Release(RGFW_dxInfo.pDevice);
+ RGFW_dxInfo.pAdapter->lpVtbl->Release(RGFW_dxInfo.pAdapter);
+ RGFW_dxInfo.pFactory->lpVtbl->Release(RGFW_dxInfo.pFactory);
+#endif
+
+ if (RGFW_XInput_dll != NULL) {
+ FreeLibrary(RGFW_XInput_dll);
+ RGFW_XInput_dll = NULL;
+ }
+
+ #ifndef RGFW_NO_DPI
+ if (RGFW_Shcore_dll != NULL) {
+ FreeLibrary(RGFW_Shcore_dll);
+ RGFW_Shcore_dll = NULL;
+ }
+ #endif
+
+ if (wglinstance != NULL) {
+ FreeLibrary(wglinstance);
+ wglinstance = NULL;
+ }
+
+ RGFW_root = NULL;
+ }
+
+#ifdef RGFW_DIRECTX
+ win->src.swapchain->lpVtbl->Release(win->src.swapchain);
+ win->src.renderTargetView->lpVtbl->Release(win->src.renderTargetView);
+ win->src.pDepthStencilView->lpVtbl->Release(win->src.pDepthStencilView);
+#endif
+
+#ifdef RGFW_BUFFER
+ DeleteDC(win->src.hdcMem);
+ DeleteObject(win->src.bitmap);
+#endif
+
+#ifdef RGFW_OPENGL
+ wglDeleteContext((HGLRC) win->src.ctx); /*!< delete opengl context */
+#endif
+ DeleteDC(win->src.hdc); /*!< delete device context */
+ DestroyWindow(win->src.window); /*!< delete window */
+
+#if defined(RGFW_OSMESA)
+ if (win->buffer != NULL)
+ RGFW_FREE(win->buffer);
+#endif
+
+#ifdef RGFW_ALLOC_DROPFILES
+ {
+ u32 i;
+ for (i = 0; i < RGFW_MAX_DROPS; i++)
+ RGFW_FREE(win->event.droppedFiles[i]);
+
+
+ RGFW_FREE(win->event.droppedFiles);
+ }
+#endif
+
+ RGFW_FREE(win);
+ }
+
+ void RGFW_window_move(RGFW_window* win, RGFW_point v) {
+ assert(win != NULL);
+
+ win->r.x = v.x;
+ win->r.y = v.y;
+ SetWindowPos(win->src.window, HWND_TOP, win->r.x, win->r.y, 0, 0, SWP_NOSIZE);
+ }
+
+ void RGFW_window_resize(RGFW_window* win, RGFW_area a) {
+ assert(win != NULL);
+
+ win->r.w = a.w;
+ win->r.h = a.h;
+ SetWindowPos(win->src.window, HWND_TOP, 0, 0, win->r.w, win->r.h + win->src.hOffset, SWP_NOMOVE);
+ }
+
+
+ void RGFW_window_setName(RGFW_window* win, char* name) {
+ assert(win != NULL);
+
+ SetWindowTextA(win->src.window, name);
+ }
+
+ /* sourced from GLFW */
+ #ifndef RGFW_NO_PASSTHROUGH
+ void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough) {
+ assert(win != NULL);
+
+ COLORREF key = 0;
+ BYTE alpha = 0;
+ DWORD flags = 0;
+ DWORD exStyle = GetWindowLongW(win->src.window, GWL_EXSTYLE);
+
+ if (exStyle & WS_EX_LAYERED)
+ GetLayeredWindowAttributes(win->src.window, &key, &alpha, &flags);
+
+ if (passthrough)
+ exStyle |= (WS_EX_TRANSPARENT | WS_EX_LAYERED);
+ else
+ {
+ exStyle &= ~WS_EX_TRANSPARENT;
+ // NOTE: Window opacity also needs the layered window style so do not
+ // remove it if the window is alpha blended
+ if (exStyle & WS_EX_LAYERED)
+ {
+ if (!(flags & LWA_ALPHA))
+ exStyle &= ~WS_EX_LAYERED;
+ }
+ }
+
+ SetWindowLongW(win->src.window, GWL_EXSTYLE, exStyle);
+
+ if (passthrough) {
+ SetLayeredWindowAttributes(win->src.window, key, alpha, flags);
+ }
+ }
+ #endif
+
+ /* much of this function is sourced from GLFW */
+ void RGFW_window_setIcon(RGFW_window* win, u8* src, RGFW_area a, i32 channels) {
+ assert(win != NULL);
+ #ifndef RGFW_WIN95
+ RGFW_UNUSED(channels)
+
+ HICON handle = RGFW_loadHandleImage(win, src, a, TRUE);
+
+ SetClassLongPtrA(win->src.window, GCLP_HICON, (LPARAM) handle);
+
+ DestroyIcon(handle);
+ #else
+ RGFW_UNUSED(src)
+ RGFW_UNUSED(a)
+ RGFW_UNUSED(channels)
+ #endif
+ }
+
+ char* RGFW_readClipboard(size_t* size) {
+ /* Open the clipboard */
+ if (OpenClipboard(NULL) == 0)
+ return (char*) "";
+
+ /* Get the clipboard data as a Unicode string */
+ HANDLE hData = GetClipboardData(CF_UNICODETEXT);
+ if (hData == NULL) {
+ CloseClipboard();
+ return (char*) "";
+ }
+
+ wchar_t* wstr = (wchar_t*) GlobalLock(hData);
+
+ char* text;
+
+ {
+ setlocale(LC_ALL, "en_US.UTF-8");
+
+ size_t textLen = wcstombs(NULL, wstr, 0);
+ if (textLen == 0)
+ return (char*) "";
+
+ text = (char*) RGFW_MALLOC((textLen * sizeof(char)) + 1);
+
+ wcstombs(text, wstr, (textLen) +1);
+
+ if (size != NULL)
+ *size = textLen + 1;
+
+ text[textLen] = '\0';
+ }
+
+ /* Release the clipboard data */
+ GlobalUnlock(hData);
+ CloseClipboard();
+
+ return text;
+ }
+
+ void RGFW_writeClipboard(const char* text, u32 textLen) {
+ HANDLE object;
+ WCHAR* buffer;
+
+ object = GlobalAlloc(GMEM_MOVEABLE, (1 + textLen) * sizeof(WCHAR));
+ if (!object)
+ return;
+
+ buffer = (WCHAR*) GlobalLock(object);
+ if (!buffer) {
+ GlobalFree(object);
+ return;
+ }
+
+ MultiByteToWideChar(CP_UTF8, 0, text, -1, buffer, textLen);
+ GlobalUnlock(object);
+
+ if (!OpenClipboard(RGFW_root->src.window)) {
+ GlobalFree(object);
+ return;
+ }
+
+ EmptyClipboard();
+ SetClipboardData(CF_UNICODETEXT, object);
+ CloseClipboard();
+ }
+
+ u16 RGFW_registerJoystick(RGFW_window* win, i32 jsNumber) {
+ assert(win != NULL);
+
+ RGFW_UNUSED(jsNumber)
+
+ return RGFW_registerJoystickF(win, (char*) "");
+ }
+
+ u16 RGFW_registerJoystickF(RGFW_window* win, char* file) {
+ assert(win != NULL);
+ RGFW_UNUSED(file)
+
+ return RGFW_joystickCount - 1;
+ }
+
+ void RGFW_window_moveMouse(RGFW_window* win, RGFW_point p) {
+ assert(win != NULL);
+
+ SetCursorPos(p.x, p.y);
+ }
+
+ #ifdef RGFW_OPENGL
+ void RGFW_window_makeCurrent_OpenGL(RGFW_window* win) {
+ if (win == NULL)
+ wglMakeCurrent(NULL, NULL);
+ else
+ wglMakeCurrent(win->src.hdc, (HGLRC) win->src.ctx);
+ }
+ #endif
+
+ #ifndef RGFW_EGL
+ void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) {
+ assert(win != NULL);
+
+ #if defined(RGFW_OPENGL)
+ typedef BOOL(APIENTRY* PFNWGLSWAPINTERVALEXTPROC)(int interval);
+ static PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = NULL;
+ static void* loadSwapFunc = (void*) 1;
+
+ if (loadSwapFunc == NULL) {
+ fprintf(stderr, "wglSwapIntervalEXT not supported\n");
+ return;
+ }
+
+ if (wglSwapIntervalEXT == NULL) {
+ loadSwapFunc = (void*) wglGetProcAddress("wglSwapIntervalEXT");
+ wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC) loadSwapFunc;
+ }
+
+ if (wglSwapIntervalEXT(swapInterval) == FALSE)
+ fprintf(stderr, "Failed to set swap interval\n");
+ #else
+ RGFW_UNUSED(swapInterval);
+ #endif
+
+ }
+ #endif
+
+ void RGFW_window_swapBuffers(RGFW_window* win) {
+ //assert(win != NULL);
+ /* clear the window*/
+
+ if (!(win->_winArgs & RGFW_NO_CPU_RENDER)) {
+#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER)
+ #ifdef RGFW_OSMESA
+ RGFW_OSMesa_reorganize();
+ #endif
+
+ HGDIOBJ oldbmp = SelectObject(win->src.hdcMem, win->src.bitmap);
+ BitBlt(win->src.hdc, 0, 0, win->r.w, win->r.h, win->src.hdcMem, 0, 0, SRCCOPY);
+ SelectObject(win->src.hdcMem, oldbmp);
+#endif
+ }
+
+ if (!(win->_winArgs & RGFW_NO_GPU_RENDER)) {
+ #ifdef RGFW_EGL
+ eglSwapBuffers(win->src.EGL_display, win->src.EGL_surface);
+ #elif defined(RGFW_OPENGL)
+ SwapBuffers(win->src.hdc);
+ #endif
+
+ #if defined(RGFW_WINDOWS) && defined(RGFW_DIRECTX)
+ win->src.swapchain->lpVtbl->Present(win->src.swapchain, 0, 0);
+ #endif
+ }
+ }
+
+ char* createUTF8FromWideStringWin32(const WCHAR* source) {
+ char* target;
+ i32 size;
+
+ size = WideCharToMultiByte(CP_UTF8, 0, source, -1, NULL, 0, NULL, NULL);
+ if (!size) {
+ return NULL;
+ }
+
+ target = (char*) RGFW_CALLOC(size, 1);
+
+ if (!WideCharToMultiByte(CP_UTF8, 0, source, -1, target, size, NULL, NULL)) {
+ RGFW_FREE(target);
+ return NULL;
+ }
+
+ return target;
+ }
+
+ static inline LARGE_INTEGER RGFW_win32_initTimer(void) {
+ static LARGE_INTEGER frequency = {{0, 0}};
+ if (frequency.QuadPart == 0) {
+ timeBeginPeriod(1);
+ QueryPerformanceFrequency(&frequency);
+ }
+
+ return frequency;
+ }
+
+ u64 RGFW_getTimeNS(void) {
+ LARGE_INTEGER frequency = RGFW_win32_initTimer();
+
+ LARGE_INTEGER counter;
+ QueryPerformanceCounter(&counter);
+
+ return (u64) ((counter.QuadPart * 1e9) / frequency.QuadPart);
+ }
+
+ u64 RGFW_getTime(void) {
+ LARGE_INTEGER frequency = RGFW_win32_initTimer();
+
+ LARGE_INTEGER counter;
+ QueryPerformanceCounter(&counter);
+ return (u64) (counter.QuadPart / (double) frequency.QuadPart);
+ }
+
+ void RGFW_sleep(u64 ms) {
+ Sleep(ms);
+ }
+
+#ifndef RGFW_NO_THREADS
+ RGFW_thread RGFW_createThread(RGFW_threadFunc_ptr ptr, void* args) { return CreateThread(NULL, 0, ptr, args, 0, NULL); }
+ void RGFW_cancelThread(RGFW_thread thread) { CloseHandle((HANDLE) thread); }
+ void RGFW_joinThread(RGFW_thread thread) { WaitForSingleObject((HANDLE) thread, INFINITE); }
+ void RGFW_setThreadPriority(RGFW_thread thread, u8 priority) { SetThreadPriority((HANDLE) thread, priority); }
+#endif
+#endif /* RGFW_WINDOWS */
+
+/*
+ End of Windows defines
+*/
+
+
+
+/*
+
+ Start of MacOS defines
+
+
+*/
+
+#if defined(RGFW_MACOS)
+ /*
+ based on silicon.h
+ start of cocoa wrapper
+ */
+
+#include
+#include
+#include
+#include
+#include
+
+ typedef CGRect NSRect;
+ typedef CGPoint NSPoint;
+ typedef CGSize NSSize;
+
+ typedef void NSBitmapImageRep;
+ typedef void NSCursor;
+ typedef void NSDraggingInfo;
+ typedef void NSWindow;
+ typedef void NSApplication;
+ typedef void NSScreen;
+ typedef void NSEvent;
+ typedef void NSString;
+ typedef void NSOpenGLContext;
+ typedef void NSPasteboard;
+ typedef void NSColor;
+ typedef void NSArray;
+ typedef void NSImageRep;
+ typedef void NSImage;
+ typedef void NSOpenGLView;
+
+
+ typedef const char* NSPasteboardType;
+ typedef unsigned long NSUInteger;
+ typedef long NSInteger;
+ typedef NSInteger NSModalResponse;
+
+#ifdef __arm64__
+ /* ARM just uses objc_msgSend */
+#define abi_objc_msgSend_stret objc_msgSend
+#define abi_objc_msgSend_fpret objc_msgSend
+#else /* __i386__ */
+ /* x86 just uses abi_objc_msgSend_fpret and (NSColor *)objc_msgSend_id respectively */
+#define abi_objc_msgSend_stret objc_msgSend_stret
+#define abi_objc_msgSend_fpret objc_msgSend_fpret
+#endif
+
+#define NSAlloc(nsclass) objc_msgSend_id((id)nsclass, sel_registerName("alloc"))
+#define objc_msgSend_bool ((BOOL (*)(id, SEL))objc_msgSend)
+#define objc_msgSend_void ((void (*)(id, SEL))objc_msgSend)
+#define objc_msgSend_void_id ((void (*)(id, SEL, id))objc_msgSend)
+#define objc_msgSend_uint ((NSUInteger (*)(id, SEL))objc_msgSend)
+#define objc_msgSend_void_bool ((void (*)(id, SEL, BOOL))objc_msgSend)
+#define objc_msgSend_bool_void ((BOOL (*)(id, SEL))objc_msgSend)
+#define objc_msgSend_void_SEL ((void (*)(id, SEL, SEL))objc_msgSend)
+#define objc_msgSend_id ((id (*)(id, SEL))objc_msgSend)
+#define objc_msgSend_id_id ((id (*)(id, SEL, id))objc_msgSend)
+#define objc_msgSend_id_bool ((BOOL (*)(id, SEL, id))objc_msgSend)
+#define objc_msgSend_int ((id (*)(id, SEL, int))objc_msgSend)
+#define objc_msgSend_arr ((id (*)(id, SEL, int))objc_msgSend)
+#define objc_msgSend_ptr ((id (*)(id, SEL, void*))objc_msgSend)
+#define objc_msgSend_class ((id (*)(Class, SEL))objc_msgSend)
+#define objc_msgSend_class_char ((id (*)(Class, SEL, char*))objc_msgSend)
+
+ NSApplication* NSApp = NULL;
+
+ void NSRelease(id obj) {
+ objc_msgSend_void(obj, sel_registerName("release"));
+ }
+
+ #define release NSRelease
+
+ NSString* NSString_stringWithUTF8String(const char* str) {
+ return ((id(*)(id, SEL, const char*))objc_msgSend)
+ ((id)objc_getClass("NSString"), sel_registerName("stringWithUTF8String:"), str);
+ }
+
+ const char* NSString_to_char(NSString* str) {
+ return ((const char* (*)(id, SEL)) objc_msgSend) (str, sel_registerName("UTF8String"));
+ }
+
+ void si_impl_func_to_SEL_with_name(const char* class_name, const char* register_name, void* function) {
+ Class selected_class;
+
+ if (strcmp(class_name, "NSView") == 0) {
+ selected_class = objc_getClass("ViewClass");
+ } else if (strcmp(class_name, "NSWindow") == 0) {
+ selected_class = objc_getClass("WindowClass");
+ } else {
+ selected_class = objc_getClass(class_name);
+ }
+
+ class_addMethod(selected_class, sel_registerName(register_name), (IMP) function, 0);
+ }
+
+ /* Header for the array. */
+ typedef struct siArrayHeader {
+ size_t count;
+ /* TODO(EimaMei): Add a `type_width` later on. */
+ } siArrayHeader;
+
+ /* Gets the header of the siArray. */
+#define SI_ARRAY_HEADER(s) ((siArrayHeader*)s - 1)
+
+ void* si_array_init_reserve(size_t sizeof_element, size_t count) {
+ siArrayHeader* ptr = malloc(sizeof(siArrayHeader) + (sizeof_element * count));
+ void* array = ptr + sizeof(siArrayHeader);
+
+ siArrayHeader* header = SI_ARRAY_HEADER(array);
+ header->count = count;
+
+ return array;
+ }
+
+#define si_array_len(array) (SI_ARRAY_HEADER(array)->count)
+#define si_func_to_SEL(class_name, function) si_impl_func_to_SEL_with_name(class_name, #function":", function)
+ /* Creates an Objective-C method (SEL) from a regular C function with the option to set the register name.*/
+#define si_func_to_SEL_with_name(class_name, register_name, function) si_impl_func_to_SEL_with_name(class_name, register_name":", function)
+
+ unsigned char* NSBitmapImageRep_bitmapData(NSBitmapImageRep* imageRep) {
+ return ((unsigned char* (*)(id, SEL))objc_msgSend)
+ (imageRep, sel_registerName("bitmapData"));
+ }
+
+#define NS_ENUM(type, name) type name; enum
+
+ typedef NS_ENUM(NSUInteger, NSBitmapFormat) {
+ NSBitmapFormatAlphaFirst = 1 << 0, // 0 means is alpha last (RGBA, CMYKA, etc.)
+ NSBitmapFormatAlphaNonpremultiplied = 1 << 1, // 0 means is premultiplied
+ NSBitmapFormatFloatingPointSamples = 1 << 2, // 0 is integer
+
+ NSBitmapFormatSixteenBitLittleEndian API_AVAILABLE(macos(10.10)) = (1 << 8),
+ NSBitmapFormatThirtyTwoBitLittleEndian API_AVAILABLE(macos(10.10)) = (1 << 9),
+ NSBitmapFormatSixteenBitBigEndian API_AVAILABLE(macos(10.10)) = (1 << 10),
+ NSBitmapFormatThirtyTwoBitBigEndian API_AVAILABLE(macos(10.10)) = (1 << 11)
+ };
+
+ NSBitmapImageRep* NSBitmapImageRep_initWithBitmapData(unsigned char** planes, NSInteger width, NSInteger height, NSInteger bps, NSInteger spp, bool alpha, bool isPlanar, const char* colorSpaceName, NSBitmapFormat bitmapFormat, NSInteger rowBytes, NSInteger pixelBits) {
+ void* func = sel_registerName("initWithBitmapDataPlanes:pixelsWide:pixelsHigh:bitsPerSample:samplesPerPixel:hasAlpha:isPlanar:colorSpaceName:bitmapFormat:bytesPerRow:bitsPerPixel:");
+
+ return (NSBitmapImageRep*) ((id(*)(id, SEL, unsigned char**, NSInteger, NSInteger, NSInteger, NSInteger, bool, bool, const char*, NSBitmapFormat, NSInteger, NSInteger))objc_msgSend)
+ (NSAlloc((id)objc_getClass("NSBitmapImageRep")), func, planes, width, height, bps, spp, alpha, isPlanar, NSString_stringWithUTF8String(colorSpaceName), bitmapFormat, rowBytes, pixelBits);
+ }
+
+ NSColor* NSColor_colorWithSRGB(CGFloat red, CGFloat green, CGFloat blue, CGFloat alpha) {
+ void* nsclass = objc_getClass("NSColor");
+ void* func = sel_registerName("colorWithSRGBRed:green:blue:alpha:");
+ return ((id(*)(id, SEL, CGFloat, CGFloat, CGFloat, CGFloat))objc_msgSend)
+ (nsclass, func, red, green, blue, alpha);
+ }
+
+ NSCursor* NSCursor_initWithImage(NSImage* newImage, NSPoint aPoint) {
+ void* func = sel_registerName("initWithImage:hotSpot:");
+ void* nsclass = objc_getClass("NSCursor");
+
+ return (NSCursor*) ((id(*)(id, SEL, id, NSPoint))objc_msgSend)
+ (NSAlloc(nsclass), func, newImage, aPoint);
+ }
+
+ void NSImage_addRepresentation(NSImage* image, NSImageRep* imageRep) {
+ void* func = sel_registerName("addRepresentation:");
+ objc_msgSend_void_id(image, func, imageRep);
+ }
+
+ NSImage* NSImage_initWithSize(NSSize size) {
+ void* func = sel_registerName("initWithSize:");
+ return ((id(*)(id, SEL, NSSize))objc_msgSend)
+ (NSAlloc((id)objc_getClass("NSImage")), func, size);
+ }
+#define NS_OPENGL_ENUM_DEPRECATED(minVers, maxVers) API_AVAILABLE(macos(minVers))
+ typedef NS_ENUM(NSInteger, NSOpenGLContextParameter) {
+ NSOpenGLContextParameterSwapInterval NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 222, /* 1 param. 0 -> Don't sync, 1 -> Sync to vertical retrace */
+ NSOpenGLContextParametectxaceOrder NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 235, /* 1 param. 1 -> Above Window (default), -1 -> Below Window */
+ NSOpenGLContextParametectxaceOpacity NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 236, /* 1 param. 1-> Surface is opaque (default), 0 -> non-opaque */
+ NSOpenGLContextParametectxaceBackingSize NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 304, /* 2 params. Width/height of surface backing size */
+ NSOpenGLContextParameterReclaimResources NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 308, /* 0 params. */
+ NSOpenGLContextParameterCurrentRendererID NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 309, /* 1 param. Retrieves the current renderer ID */
+ NSOpenGLContextParameterGPUVertexProcessing NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 310, /* 1 param. Currently processing vertices with GPU (get) */
+ NSOpenGLContextParameterGPUFragmentProcessing NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 311, /* 1 param. Currently processing fragments with GPU (get) */
+ NSOpenGLContextParameterHasDrawable NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 314, /* 1 param. Boolean returned if drawable is attached */
+ NSOpenGLContextParameterMPSwapsInFlight NS_OPENGL_ENUM_DEPRECATED(10.0, 10.14) = 315, /* 1 param. Max number of swaps queued by the MP GL engine */
+
+ NSOpenGLContextParameterSwapRectangle API_DEPRECATED("", macos(10.0, 10.14)) = 200, /* 4 params. Set or get the swap rectangle {x, y, w, h} */
+ NSOpenGLContextParameterSwapRectangleEnable API_DEPRECATED("", macos(10.0, 10.14)) = 201, /* Enable or disable the swap rectangle */
+ NSOpenGLContextParameterRasterizationEnable API_DEPRECATED("", macos(10.0, 10.14)) = 221, /* Enable or disable all rasterization */
+ NSOpenGLContextParameterStateValidation API_DEPRECATED("", macos(10.0, 10.14)) = 301, /* Validate state for multi-screen functionality */
+ NSOpenGLContextParametectxaceSurfaceVolatile API_DEPRECATED("", macos(10.0, 10.14)) = 306, /* 1 param. Surface volatile state */
+ };
+
+
+ void NSOpenGLContext_setValues(NSOpenGLContext* context, const int* vals, NSOpenGLContextParameter param) {
+ void* func = sel_registerName("setValues:forParameter:");
+ ((void (*)(id, SEL, const int*, NSOpenGLContextParameter))objc_msgSend)
+ (context, func, vals, param);
+ }
+
+ void* NSOpenGLPixelFormat_initWithAttributes(const uint32_t* attribs) {
+ void* func = sel_registerName("initWithAttributes:");
+ return (void*) ((id(*)(id, SEL, const uint32_t*))objc_msgSend)
+ (NSAlloc((id)objc_getClass("NSOpenGLPixelFormat")), func, attribs);
+ }
+
+ NSOpenGLView* NSOpenGLView_initWithFrame(NSRect frameRect, uint32_t* format) {
+ void* func = sel_registerName("initWithFrame:pixelFormat:");
+ return (NSOpenGLView*) ((id(*)(id, SEL, NSRect, uint32_t*))objc_msgSend)
+ (NSAlloc((id)objc_getClass("NSOpenGLView")), func, frameRect, format);
+ }
+
+ void NSCursor_performSelector(NSCursor* cursor, void* selector) {
+ void* func = sel_registerName("performSelector:");
+ objc_msgSend_void_SEL(cursor, func, selector);
+ }
+
+ NSPasteboard* NSPasteboard_generalPasteboard(void) {
+ return (NSPasteboard*) objc_msgSend_id((id)objc_getClass("NSPasteboard"), sel_registerName("generalPasteboard"));
+ }
+
+ NSString** cstrToNSStringArray(char** strs, size_t len) {
+ static NSString* nstrs[6];
+ size_t i;
+ for (i = 0; i < len; i++)
+ nstrs[i] = NSString_stringWithUTF8String(strs[i]);
+
+ return nstrs;
+ }
+
+ const char* NSPasteboard_stringForType(NSPasteboard* pasteboard, NSPasteboardType dataType) {
+ void* func = sel_registerName("stringForType:");
+ return (const char*) NSString_to_char(((id(*)(id, SEL, const char*))objc_msgSend)(pasteboard, func, NSString_stringWithUTF8String(dataType)));
+ }
+
+ NSArray* c_array_to_NSArray(void* array, size_t len) {
+ SEL func = sel_registerName("initWithObjects:count:");
+ void* nsclass = objc_getClass("NSArray");
+ return ((id (*)(id, SEL, void*, NSUInteger))objc_msgSend)
+ (NSAlloc(nsclass), func, array, len);
+ }
+
+ void NSregisterForDraggedTypes(void* view, NSPasteboardType* newTypes, size_t len) {
+ NSString** ntypes = cstrToNSStringArray((char**)newTypes, len);
+
+ NSArray* array = c_array_to_NSArray(ntypes, len);
+ objc_msgSend_void_id(view, sel_registerName("registerForDraggedTypes:"), array);
+ NSRelease(array);
+ }
+
+ NSInteger NSPasteBoard_declareTypes(NSPasteboard* pasteboard, NSPasteboardType* newTypes, size_t len, void* owner) {
+ NSString** ntypes = cstrToNSStringArray((char**)newTypes, len);
+
+ void* func = sel_registerName("declareTypes:owner:");
+
+ NSArray* array = c_array_to_NSArray(ntypes, len);
+
+ NSInteger output = ((NSInteger(*)(id, SEL, id, void*))objc_msgSend)
+ (pasteboard, func, array, owner);
+ NSRelease(array);
+
+ return output;
+ }
+
+ bool NSPasteBoard_setString(NSPasteboard* pasteboard, const char* stringToWrite, NSPasteboardType dataType) {
+ void* func = sel_registerName("setString:forType:");
+ return ((bool (*)(id, SEL, id, NSPasteboardType))objc_msgSend)
+ (pasteboard, func, NSString_stringWithUTF8String(stringToWrite), NSString_stringWithUTF8String(dataType));
+ }
+
+ void NSRetain(id obj) { objc_msgSend_void(obj, sel_registerName("retain")); }
+
+ typedef enum NSApplicationActivationPolicy {
+ NSApplicationActivationPolicyRegular,
+ NSApplicationActivationPolicyAccessory,
+ NSApplicationActivationPolicyProhibited
+ } NSApplicationActivationPolicy;
+
+ typedef NS_ENUM(u32, NSBackingStoreType) {
+ NSBackingStoreRetained = 0,
+ NSBackingStoreNonretained = 1,
+ NSBackingStoreBuffered = 2
+ };
+
+ typedef NS_ENUM(u32, NSWindowStyleMask) {
+ NSWindowStyleMaskBorderless = 0,
+ NSWindowStyleMaskTitled = 1 << 0,
+ NSWindowStyleMaskClosable = 1 << 1,
+ NSWindowStyleMaskMiniaturizable = 1 << 2,
+ NSWindowStyleMaskResizable = 1 << 3,
+ NSWindowStyleMaskTexturedBackground = 1 << 8, /* deprecated */
+ NSWindowStyleMaskUnifiedTitleAndToolbar = 1 << 12,
+ NSWindowStyleMaskFullScreen = 1 << 14,
+ NSWindowStyleMaskFullSizeContentView = 1 << 15,
+ NSWindowStyleMaskUtilityWindow = 1 << 4,
+ NSWindowStyleMaskDocModalWindow = 1 << 6,
+ NSWindowStyleMaskNonactivatingPanel = 1 << 7,
+ NSWindowStyleMaskHUDWindow = 1 << 13
+ };
+
+ NSPasteboardType const NSPasteboardTypeString = "public.utf8-plain-text"; // Replaces NSStringPboardType
+
+
+ typedef NS_ENUM(i32, NSDragOperation) {
+ NSDragOperationNone = 0,
+ NSDragOperationCopy = 1,
+ NSDragOperationLink = 2,
+ NSDragOperationGeneric = 4,
+ NSDragOperationPrivate = 8,
+ NSDragOperationMove = 16,
+ NSDragOperationDelete = 32,
+ NSDragOperationEvery = ULONG_MAX,
+
+ //NSDragOperationAll_Obsolete API_DEPRECATED("", macos(10.0,10.10)) = 15, // Use NSDragOperationEvery
+ //NSDragOperationAll API_DEPRECATED("", macos(10.0,10.10)) = NSDragOperationAll_Obsolete, // Use NSDragOperationEvery
+ };
+
+ void* NSArray_objectAtIndex(NSArray* array, NSUInteger index) {
+ void* func = sel_registerName("objectAtIndex:");
+ return ((id(*)(id, SEL, NSUInteger))objc_msgSend)(array, func, index);
+ }
+
+ const char** NSPasteboard_readObjectsForClasses(NSPasteboard* pasteboard, Class* classArray, size_t len, void* options) {
+ void* func = sel_registerName("readObjectsForClasses:options:");
+
+ NSArray* array = c_array_to_NSArray(classArray, len);
+
+ NSArray* output = (NSArray*) ((id(*)(id, SEL, id, void*))objc_msgSend)
+ (pasteboard, func, array, options);
+
+ NSRelease(array);
+ NSUInteger count = ((NSUInteger(*)(id, SEL))objc_msgSend)(output, sel_registerName("count"));
+
+ const char** res = si_array_init_reserve(sizeof(const char*), count);
+
+ void* path_func = sel_registerName("path");
+
+ for (NSUInteger i = 0; i < count; i++) {
+ void* url = NSArray_objectAtIndex(output, i);
+ NSString* url_str = ((id(*)(id, SEL))objc_msgSend)(url, path_func);
+ res[i] = NSString_to_char(url_str);
+ }
+
+ return res;
+ }
+
+ void* NSWindow_contentView(NSWindow* window) {
+ void* func = sel_registerName("contentView");
+ return objc_msgSend_id(window, func);
+ }
+
+ /*
+ End of cocoa wrapper
+ */
+
+ char* RGFW_mouseIconSrc[] = {"arrowCursor", "arrowCursor", "IBeamCursor", "crosshairCursor", "pointingHandCursor", "resizeLeftRightCursor", "resizeUpDownCursor", "_windowResizeNorthWestSouthEastCursor", "_windowResizeNorthEastSouthWestCursor", "closedHandCursor", "operationNotAllowedCursor"};
+
+ void* RGFWnsglFramework = NULL;
+
+#ifdef RGFW_OPENGL
+ void* RGFW_getProcAddress(const char* procname) {
+ if (RGFWnsglFramework == NULL)
+ RGFWnsglFramework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl"));
+
+ CFStringRef symbolName = CFStringCreateWithCString(kCFAllocatorDefault, procname, kCFStringEncodingASCII);
+
+ void* symbol = CFBundleGetFunctionPointerForName(RGFWnsglFramework, symbolName);
+
+ CFRelease(symbolName);
+
+ return symbol;
+ }
+#endif
+
+ CVReturn displayCallback(CVDisplayLinkRef displayLink, const CVTimeStamp* inNow, const CVTimeStamp* inOutputTime, CVOptionFlags flagsIn, CVOptionFlags* flagsOut, void* displayLinkContext) {
+ RGFW_UNUSED(displayLink) RGFW_UNUSED(inNow) RGFW_UNUSED(inOutputTime) RGFW_UNUSED(flagsIn) RGFW_UNUSED(flagsOut) RGFW_UNUSED(displayLinkContext)
+ return kCVReturnSuccess;
+ }
+
+ id NSWindow_delegate(RGFW_window* win) {
+ return (id) objc_msgSend_id(win->src.window, sel_registerName("delegate"));
+ }
+
+ u32 RGFW_OnClose(void* self) {
+ RGFW_window* win = NULL;
+ object_getInstanceVariable(self, "RGFW_window", (void*)&win);
+ if (win == NULL)
+ return true;
+
+ win->event.type = RGFW_quit;
+ RGFW_windowQuitCallback(win);
+
+ return true;
+ }
+
+ /* NOTE(EimaMei): Fixes the constant clicking when the app is running under a terminal. */
+ bool acceptsFirstResponder(void) { return true; }
+ bool performKeyEquivalent(NSEvent* event) { RGFW_UNUSED(event); return true; }
+
+ NSDragOperation draggingEntered(id self, SEL sel, id sender) {
+ RGFW_UNUSED(sender); RGFW_UNUSED(self); RGFW_UNUSED(sel);
+
+ return NSDragOperationCopy;
+ }
+ NSDragOperation draggingUpdated(id self, SEL sel, id sender) {
+ RGFW_UNUSED(sel);
+
+ RGFW_window* win = NULL;
+ object_getInstanceVariable(self, "RGFW_window", (void*)&win);
+ if (win == NULL)
+ return 0;
+
+ if (!(win->_winArgs & RGFW_ALLOW_DND)) {
+ return 0;
+ }
+
+ win->event.type = RGFW_dnd_init;
+ win->src.dndPassed = 0;
+
+ NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)(sender, sel_registerName("draggingLocation"));
+
+ win->event.point = RGFW_POINT((u32) p.x, (u32) (win->r.h - p.y));
+ RGFW_dndInitCallback(win, win->event.point);
+
+ return NSDragOperationCopy;
+ }
+ bool prepareForDragOperation(id self) {
+ RGFW_window* win = NULL;
+ object_getInstanceVariable(self, "RGFW_window", (void*)&win);
+ if (win == NULL)
+ return true;
+
+ if (!(win->_winArgs & RGFW_ALLOW_DND)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ void RGFW__osxDraggingEnded(id self, SEL sel, id sender) { RGFW_UNUSED(sender); RGFW_UNUSED(self); RGFW_UNUSED(sel); return; }
+
+ /* NOTE(EimaMei): Usually, you never need 'id self, SEL cmd' for C -> Obj-C methods. This isn't the case. */
+ bool performDragOperation(id self, SEL sel, id sender) {
+ RGFW_UNUSED(sender); RGFW_UNUSED(self); RGFW_UNUSED(sel);
+
+ RGFW_window* win = NULL;
+ object_getInstanceVariable(self, "RGFW_window", (void*)&win);
+
+ if (win == NULL)
+ return false;
+
+ // NSPasteboard* pasteBoard = objc_msgSend_id(sender, sel_registerName("draggingPasteboard"));
+
+ /////////////////////////////
+ id pasteBoard = objc_msgSend_id(sender, sel_registerName("draggingPasteboard"));
+
+ // Get the types of data available on the pasteboard
+ id types = objc_msgSend_id(pasteBoard, sel_registerName("types"));
+
+ // Get the string type for file URLs
+ id fileURLsType = objc_msgSend_class_char(objc_getClass("NSString"), sel_registerName("stringWithUTF8String:"), "NSFilenamesPboardType");
+
+ // Check if the pasteboard contains file URLs
+ if (objc_msgSend_id_bool(types, sel_registerName("containsObject:"), fileURLsType) == 0) {
+ #ifdef RGFW_DEBUG
+ printf("No files found on the pasteboard.\n");
+ #endif
+
+ return 0;
+ }
+
+ id fileURLs = objc_msgSend_id_id(pasteBoard, sel_registerName("propertyListForType:"), fileURLsType);
+ int count = ((int (*)(id, SEL))objc_msgSend)(fileURLs, sel_registerName("count"));
+
+ if (count == 0)
+ return 0;
+
+ for (int i = 0; i < count; i++) {
+ id fileURL = objc_msgSend_arr(fileURLs, sel_registerName("objectAtIndex:"), i);
+ const char *filePath = ((const char* (*)(id, SEL))objc_msgSend)(fileURL, sel_registerName("UTF8String"));
+ strncpy(win->event.droppedFiles[i], filePath, RGFW_MAX_PATH);
+ win->event.droppedFiles[i][RGFW_MAX_PATH - 1] = '\0';
+ }
+ win->event.droppedFilesCount = count;
+
+ win->event.type = RGFW_dnd;
+ win->src.dndPassed = 0;
+
+ NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)(sender, sel_registerName("draggingLocation"));
+ win->event.point = RGFW_POINT((u32) p.x, (u32) (win->r.h - p.y));
+
+ RGFW_dndCallback(win, win->event.droppedFiles, win->event.droppedFilesCount);
+
+ return false;
+ }
+
+ static void NSMoveToResourceDir(void) {
+ /* sourced from glfw */
+ char resourcesPath[255];
+
+ CFBundleRef bundle = CFBundleGetMainBundle();
+ if (!bundle)
+ return;
+
+ CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(bundle);
+ CFStringRef last = CFURLCopyLastPathComponent(resourcesURL);
+
+ if (
+ CFStringCompare(CFSTR("Resources"), last, 0) != kCFCompareEqualTo ||
+ CFURLGetFileSystemRepresentation(resourcesURL, true, (u8*) resourcesPath, 255) == 0
+ ) {
+ CFRelease(last);
+ CFRelease(resourcesURL);
+ return;
+ }
+
+ CFRelease(last);
+ CFRelease(resourcesURL);
+
+ chdir(resourcesPath);
+ }
+
+
+ NSSize RGFW__osxWindowResize(void* self, SEL sel, NSSize frameSize) {
+ RGFW_UNUSED(sel);
+
+ RGFW_window* win = NULL;
+ object_getInstanceVariable(self, "RGFW_window", (void*)&win);
+ if (win == NULL)
+ return frameSize;
+
+ win->r.w = frameSize.width;
+ win->r.h = frameSize.height;
+ win->event.type = RGFW_windowResized;
+ RGFW_windowResizeCallback(win, win->r);
+ return frameSize;
+ }
+
+ void RGFW__osxWindowMove(void* self, SEL sel) {
+ RGFW_UNUSED(sel);
+
+ RGFW_window* win = NULL;
+ object_getInstanceVariable(self, "RGFW_window", (void*)&win);
+ if (win == NULL)
+ return;
+
+ NSRect frame = ((NSRect(*)(id, SEL))abi_objc_msgSend_stret)(win->src.window, sel_registerName("frame"));
+ win->r.x = (i32) frame.origin.x;
+ win->r.y = (i32) frame.origin.y;
+
+ win->event.type = RGFW_windowMoved;
+ RGFW_windowMoveCallback(win, win->r);
+ }
+
+ void RGFW__osxUpdateLayer(void* self, SEL sel) {
+ RGFW_UNUSED(sel);
+
+ RGFW_window* win = NULL;
+ object_getInstanceVariable(self, "RGFW_window", (void*)&win);
+ if (win == NULL)
+ return;
+
+ win->event.type = RGFW_windowRefresh;
+ RGFW_windowRefreshCallback(win);
+ }
+
+ RGFWDEF void RGFW_init_buffer(RGFW_window* win);
+ void RGFW_init_buffer(RGFW_window* win) {
+ #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER)
+ if (RGFW_bufferSize.w == 0 && RGFW_bufferSize.h == 0)
+ RGFW_bufferSize = RGFW_getScreenSize();
+
+ win->buffer = RGFW_MALLOC(RGFW_bufferSize.w * RGFW_bufferSize.h * 4);
+
+ #ifdef RGFW_OSMESA
+ win->src.ctx = OSMesaCreateContext(OSMESA_RGBA, NULL);
+ OSMesaMakeCurrent(win->src.ctx, win->buffer, GL_UNSIGNED_BYTE, win->r.w, win->r.h);
+ #endif
+ #else
+ RGFW_UNUSED(win); /*!< if buffer rendering is not being used */
+ #endif
+ }
+
+
+ void RGFW_window_cocoaSetLayer(RGFW_window* win, void* layer) {
+ objc_msgSend_void_id(win->src.view, sel_registerName("setLayer"), layer);
+ }
+
+ void* RGFW_cocoaGetLayer(void) {
+ return objc_msgSend_class(objc_getClass("CAMetalLayer"), sel_registerName("layer"));
+ }
+
+
+ NSPasteboardType const NSPasteboardTypeURL = "public.url";
+ NSPasteboardType const NSPasteboardTypeFileURL = "public.file-url";
+
+ RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, u16 args) {
+ static u8 RGFW_loaded = 0;
+
+ /* NOTE(EimaMei): Why does Apple hate good code? Like wtf, who thought of methods being a great idea???
+ Imagine a universe, where MacOS had a proper system API (we would probably have like 20% better performance).
+ */
+ si_func_to_SEL_with_name("NSObject", "windowShouldClose", RGFW_OnClose);
+
+ /* NOTE(EimaMei): Fixes the 'Boop' sfx from constantly playing each time you click a key. Only a problem when running in the terminal. */
+ si_func_to_SEL("NSWindow", acceptsFirstResponder);
+ si_func_to_SEL("NSWindow", performKeyEquivalent);
+
+ // RR Create an autorelease pool
+ id pool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc"));
+ pool = objc_msgSend_id(pool, sel_registerName("init"));
+
+ if (NSApp == NULL) {
+ NSApp = objc_msgSend_id((id)objc_getClass("NSApplication"), sel_registerName("sharedApplication"));
+
+ ((void (*)(id, SEL, NSUInteger))objc_msgSend)
+ (NSApp, sel_registerName("setActivationPolicy:"), NSApplicationActivationPolicyRegular);
+ }
+
+ RGFW_window* win = RGFW_window_basic_init(rect, args);
+
+ RGFW_window_setMouseDefault(win);
+
+ NSRect windowRect;
+ windowRect.origin.x = win->r.x;
+ windowRect.origin.y = win->r.y;
+ windowRect.size.width = win->r.w;
+ windowRect.size.height = win->r.h;
+
+ NSBackingStoreType macArgs = NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSBackingStoreBuffered | NSWindowStyleMaskTitled;
+
+ if (!(args & RGFW_NO_RESIZE))
+ macArgs |= NSWindowStyleMaskResizable;
+ if (!(args & RGFW_NO_BORDER))
+ macArgs |= NSWindowStyleMaskTitled;
+ else
+ macArgs = NSWindowStyleMaskBorderless;
+ {
+ void* nsclass = objc_getClass("NSWindow");
+ void* func = sel_registerName("initWithContentRect:styleMask:backing:defer:");
+
+ win->src.window = ((id(*)(id, SEL, NSRect, NSWindowStyleMask, NSBackingStoreType, bool))objc_msgSend)
+ (NSAlloc(nsclass), func, windowRect, macArgs, macArgs, false);
+ }
+
+ NSString* str = NSString_stringWithUTF8String(name);
+ objc_msgSend_void_id(win->src.window, sel_registerName("setTitle:"), str);
+
+#ifdef RGFW_EGL
+ if ((args & RGFW_NO_INIT_API) == 0)
+ RGFW_createOpenGLContext(win);
+#endif
+
+#ifdef RGFW_OPENGL
+ if ((args & RGFW_NO_INIT_API) == 0) {
+ void* attrs = RGFW_initFormatAttribs(args & RGFW_OPENGL_SOFTWARE);
+ void* format = NSOpenGLPixelFormat_initWithAttributes(attrs);
+
+ if (format == NULL) {
+ printf("Failed to load pixel format for OpenGL\n");
+
+ void* attrs = RGFW_initFormatAttribs(1);
+ format = NSOpenGLPixelFormat_initWithAttributes(attrs);
+ if (format == NULL)
+ printf("and loading software rendering OpenGL failed\n");
+ else
+ printf("Switching to software rendering\n");
+ }
+
+ /* the pixel format can be passed directly to opengl context creation to create a context
+ this is because the format also includes information about the opengl version (which may be a bad thing) */
+ win->src.view = NSOpenGLView_initWithFrame((NSRect){{0, 0}, {win->r.w, win->r.h}}, format);
+ objc_msgSend_void(win->src.view, sel_registerName("prepareOpenGL"));
+ win->src.ctx = objc_msgSend_id(win->src.view, sel_registerName("openGLContext"));
+ } else
+#endif
+ {
+ NSRect contentRect = (NSRect){{0, 0}, {win->r.w, win->r.h}};
+ win->src.view = ((id(*)(id, SEL, NSRect))objc_msgSend)
+ (NSAlloc((id)objc_getClass("NSView")), sel_registerName("initWithFrame:"),
+ contentRect);
+ }
+
+ void* contentView = NSWindow_contentView(win->src.window);
+ objc_msgSend_void_bool(contentView, sel_registerName("setWantsLayer:"), true);
+
+ objc_msgSend_void_id(win->src.window, sel_registerName("setContentView:"), win->src.view);
+
+#ifdef RGFW_OPENGL
+ if ((args & RGFW_NO_INIT_API) == 0)
+ objc_msgSend_void(win->src.ctx, sel_registerName("makeCurrentContext"));
+#endif
+ if (args & RGFW_TRANSPARENT_WINDOW) {
+#ifdef RGFW_OPENGL
+ if ((args & RGFW_NO_INIT_API) == 0) {
+ i32 opacity = 0;
+ #define NSOpenGLCPSurfaceOpacity 236
+ NSOpenGLContext_setValues(win->src.ctx, &opacity, NSOpenGLCPSurfaceOpacity);
+ }
+#endif
+
+ objc_msgSend_void_bool(win->src.window, sel_registerName("setOpaque:"), false);
+
+ objc_msgSend_void_id(win->src.window, sel_registerName("setBackgroundColor:"),
+ NSColor_colorWithSRGB(0, 0, 0, 0));
+ }
+
+ win->src.display = CGMainDisplayID();
+ CVDisplayLinkCreateWithCGDisplay(win->src.display, (CVDisplayLinkRef*)&win->src.displayLink);
+ CVDisplayLinkSetOutputCallback(win->src.displayLink, displayCallback, win);
+ CVDisplayLinkStart(win->src.displayLink);
+
+ RGFW_init_buffer(win);
+
+ #ifndef RGFW_NO_MONITOR
+ if (args & RGFW_SCALE_TO_MONITOR)
+ RGFW_window_scaleToMonitor(win);
+ #endif
+
+ if (args & RGFW_CENTER) {
+ RGFW_area screenR = RGFW_getScreenSize();
+ RGFW_window_move(win, RGFW_POINT((screenR.w - win->r.w) / 2, (screenR.h - win->r.h) / 2));
+ }
+
+ if (args & RGFW_HIDE_MOUSE)
+ RGFW_window_showMouse(win, 0);
+
+ if (args & RGFW_COCOA_MOVE_TO_RESOURCE_DIR)
+ NSMoveToResourceDir();
+
+ Class delegateClass = objc_allocateClassPair(objc_getClass("NSObject"), "WindowDelegate", 0);
+
+ class_addIvar(
+ delegateClass, "RGFW_window",
+ sizeof(RGFW_window*), rint(log2(sizeof(RGFW_window*))),
+ "L"
+ );
+
+ class_addMethod(delegateClass, sel_registerName("windowWillResize:toSize:"), (IMP) RGFW__osxWindowResize, "{NSSize=ff}@:{NSSize=ff}");
+ class_addMethod(delegateClass, sel_registerName("updateLayer:"), (IMP) RGFW__osxUpdateLayer, "");
+ class_addMethod(delegateClass, sel_registerName("windowWillMove:"), (IMP) RGFW__osxWindowMove, "");
+ class_addMethod(delegateClass, sel_registerName("windowDidMove:"), (IMP) RGFW__osxWindowMove, "");
+ class_addMethod(delegateClass, sel_registerName("draggingEntered:"), (IMP)draggingEntered, "l@:@");
+ class_addMethod(delegateClass, sel_registerName("draggingUpdated:"), (IMP)draggingUpdated, "l@:@");
+ class_addMethod(delegateClass, sel_registerName("draggingExited:"), (IMP)RGFW__osxDraggingEnded, "v@:@");
+ class_addMethod(delegateClass, sel_registerName("draggingEnded:"), (IMP)RGFW__osxDraggingEnded, "v@:@");
+ class_addMethod(delegateClass, sel_registerName("prepareForDragOperation:"), (IMP)prepareForDragOperation, "B@:@");
+ class_addMethod(delegateClass, sel_registerName("performDragOperation:"), (IMP)performDragOperation, "B@:@");
+
+ id delegate = objc_msgSend_id(NSAlloc(delegateClass), sel_registerName("init"));
+
+ object_setInstanceVariable(delegate, "RGFW_window", win);
+
+ objc_msgSend_void_id(win->src.window, sel_registerName("setDelegate:"), delegate);
+
+ if (args & RGFW_ALLOW_DND) {
+ win->_winArgs |= RGFW_ALLOW_DND;
+
+ NSPasteboardType types[] = {NSPasteboardTypeURL, NSPasteboardTypeFileURL, NSPasteboardTypeString};
+ NSregisterForDraggedTypes(win->src.window, types, 3);
+ }
+
+ // Show the window
+ objc_msgSend_void_bool(NSApp, sel_registerName("activateIgnoringOtherApps:"), true);
+ ((id(*)(id, SEL, SEL))objc_msgSend)(win->src.window, sel_registerName("makeKeyAndOrderFront:"), NULL);
+ objc_msgSend_void_bool(win->src.window, sel_registerName("setIsVisible:"), true);
+
+ if (!RGFW_loaded) {
+ objc_msgSend_void(win->src.window, sel_registerName("makeMainWindow"));
+
+ RGFW_loaded = 1;
+ }
+
+ objc_msgSend_void(win->src.window, sel_registerName("makeKeyWindow"));
+
+ objc_msgSend_void(NSApp, sel_registerName("finishLaunching"));
+
+ if (RGFW_root == NULL)
+ RGFW_root = win;
+
+ NSRetain(win->src.window);
+ NSRetain(NSApp);
+
+ return win;
+ }
+
+ void RGFW_window_setBorder(RGFW_window* win, u8 border) {
+ NSBackingStoreType storeType = NSWindowStyleMaskBorderless;
+ if (!border) {
+ storeType = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable;
+ }
+ if (!(win->_winArgs & RGFW_NO_RESIZE)) {
+ storeType |= NSWindowStyleMaskResizable;
+ }
+
+ ((void (*)(id, SEL, NSBackingStoreType))objc_msgSend)(win->src.window, sel_registerName("setStyleMask:"), storeType);
+
+ objc_msgSend_void_bool(win->src.window, sel_registerName("setHasShadow:"), border);
+ }
+
+ RGFW_area RGFW_getScreenSize(void) {
+ static CGDirectDisplayID display = 0;
+
+ if (display == 0)
+ display = CGMainDisplayID();
+
+ return RGFW_AREA(CGDisplayPixelsWide(display), CGDisplayPixelsHigh(display));
+ }
+
+ RGFW_point RGFW_getGlobalMousePoint(void) {
+ assert(RGFW_root != NULL);
+
+ CGEventRef e = CGEventCreate(NULL);
+ CGPoint point = CGEventGetLocation(e);
+ CFRelease(e);
+
+ return RGFW_POINT((u32) point.x, (u32) point.y); /*!< the point is loaded during event checks */
+ }
+
+ RGFW_point RGFW_window_getMousePoint(RGFW_window* win) {
+ NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)(win->src.window, sel_registerName("mouseLocationOutsideOfEventStream"));
+
+ return RGFW_POINT((u32) p.x, (u32) (win->r.h - p.y));
+ }
+
+ u32 RGFW_keysPressed[10]; /*10 keys at a time*/
+ typedef NS_ENUM(u32, NSEventType) { /* various types of events */
+ NSEventTypeLeftMouseDown = 1,
+ NSEventTypeLeftMouseUp = 2,
+ NSEventTypeRightMouseDown = 3,
+ NSEventTypeRightMouseUp = 4,
+ NSEventTypeMouseMoved = 5,
+ NSEventTypeLeftMouseDragged = 6,
+ NSEventTypeRightMouseDragged = 7,
+ NSEventTypeMouseEntered = 8,
+ NSEventTypeMouseExited = 9,
+ NSEventTypeKeyDown = 10,
+ NSEventTypeKeyUp = 11,
+ NSEventTypeFlagsChanged = 12,
+ NSEventTypeAppKitDefined = 13,
+ NSEventTypeSystemDefined = 14,
+ NSEventTypeApplicationDefined = 15,
+ NSEventTypePeriodic = 16,
+ NSEventTypeCursorUpdate = 17,
+ NSEventTypeScrollWheel = 22,
+ NSEventTypeTabletPoint = 23,
+ NSEventTypeTabletProximity = 24,
+ NSEventTypeOtherMouseDown = 25,
+ NSEventTypeOtherMouseUp = 26,
+ NSEventTypeOtherMouseDragged = 27,
+ /* The following event types are available on some hardware on 10.5.2 and later */
+ NSEventTypeGesture API_AVAILABLE(macos(10.5)) = 29,
+ NSEventTypeMagnify API_AVAILABLE(macos(10.5)) = 30,
+ NSEventTypeSwipe API_AVAILABLE(macos(10.5)) = 31,
+ NSEventTypeRotate API_AVAILABLE(macos(10.5)) = 18,
+ NSEventTypeBeginGesture API_AVAILABLE(macos(10.5)) = 19,
+ NSEventTypeEndGesture API_AVAILABLE(macos(10.5)) = 20,
+
+ NSEventTypeSmartMagnify API_AVAILABLE(macos(10.8)) = 32,
+ NSEventTypeQuickLook API_AVAILABLE(macos(10.8)) = 33,
+
+ NSEventTypePressure API_AVAILABLE(macos(10.10.3)) = 34,
+ NSEventTypeDirectTouch API_AVAILABLE(macos(10.10)) = 37,
+
+ NSEventTypeChangeMode API_AVAILABLE(macos(10.15)) = 38,
+ };
+
+ typedef NS_ENUM(unsigned long long, NSEventMask) { /* masks for the types of events */
+ NSEventMaskLeftMouseDown = 1ULL << NSEventTypeLeftMouseDown,
+ NSEventMaskLeftMouseUp = 1ULL << NSEventTypeLeftMouseUp,
+ NSEventMaskRightMouseDown = 1ULL << NSEventTypeRightMouseDown,
+ NSEventMaskRightMouseUp = 1ULL << NSEventTypeRightMouseUp,
+ NSEventMaskMouseMoved = 1ULL << NSEventTypeMouseMoved,
+ NSEventMaskLeftMouseDragged = 1ULL << NSEventTypeLeftMouseDragged,
+ NSEventMaskRightMouseDragged = 1ULL << NSEventTypeRightMouseDragged,
+ NSEventMaskMouseEntered = 1ULL << NSEventTypeMouseEntered,
+ NSEventMaskMouseExited = 1ULL << NSEventTypeMouseExited,
+ NSEventMaskKeyDown = 1ULL << NSEventTypeKeyDown,
+ NSEventMaskKeyUp = 1ULL << NSEventTypeKeyUp,
+ NSEventMaskFlagsChanged = 1ULL << NSEventTypeFlagsChanged,
+ NSEventMaskAppKitDefined = 1ULL << NSEventTypeAppKitDefined,
+ NSEventMaskSystemDefined = 1ULL << NSEventTypeSystemDefined,
+ NSEventMaskApplicationDefined = 1ULL << NSEventTypeApplicationDefined,
+ NSEventMaskPeriodic = 1ULL << NSEventTypePeriodic,
+ NSEventMaskCursorUpdate = 1ULL << NSEventTypeCursorUpdate,
+ NSEventMaskScrollWheel = 1ULL << NSEventTypeScrollWheel,
+ NSEventMaskTabletPoint = 1ULL << NSEventTypeTabletPoint,
+ NSEventMaskTabletProximity = 1ULL << NSEventTypeTabletProximity,
+ NSEventMaskOtherMouseDown = 1ULL << NSEventTypeOtherMouseDown,
+ NSEventMaskOtherMouseUp = 1ULL << NSEventTypeOtherMouseUp,
+ NSEventMaskOtherMouseDragged = 1ULL << NSEventTypeOtherMouseDragged,
+ /* The following event masks are available on some hardware on 10.5.2 and later */
+ NSEventMaskGesture API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeGesture,
+ NSEventMaskMagnify API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeMagnify,
+ NSEventMaskSwipe API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeSwipe,
+ NSEventMaskRotate API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeRotate,
+ NSEventMaskBeginGesture API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeBeginGesture,
+ NSEventMaskEndGesture API_AVAILABLE(macos(10.5)) = 1ULL << NSEventTypeEndGesture,
+
+ /* Note: You can only use these event masks on 64 bit. In other words, you cannot setup a local, nor global, event monitor for these event types on 32 bit. Also, you cannot search the event queue for them (nextEventMatchingMask:...) on 32 bit.
+ */
+ NSEventMaskSmartMagnify API_AVAILABLE(macos(10.8)) = 1ULL << NSEventTypeSmartMagnify,
+ NSEventMaskPressure API_AVAILABLE(macos(10.10.3)) = 1ULL << NSEventTypePressure,
+ NSEventMaskDirectTouch API_AVAILABLE(macos(10.12.2)) = 1ULL << NSEventTypeDirectTouch,
+
+ NSEventMaskChangeMode API_AVAILABLE(macos(10.15)) = 1ULL << NSEventTypeChangeMode,
+
+ NSEventMaskAny = ULONG_MAX,
+
+ };
+
+ typedef enum NSEventModifierFlags {
+ NSEventModifierFlagCapsLock = 1 << 16,
+ NSEventModifierFlagShift = 1 << 17,
+ NSEventModifierFlagControl = 1 << 18,
+ NSEventModifierFlagOption = 1 << 19,
+ NSEventModifierFlagCommand = 1 << 20,
+ NSEventModifierFlagNumericPad = 1 << 21
+ } NSEventModifierFlags;
+
+ void RGFW_stopCheckEvents(void) {
+ id eventPool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc"));
+ eventPool = objc_msgSend_id(eventPool, sel_registerName("init"));
+
+ NSEvent* e = (NSEvent*) ((id(*)(id, SEL, NSEventType, NSPoint, NSEventModifierFlags, void*, NSInteger, void**, short, NSInteger, NSInteger))objc_msgSend)
+ (NSApp, sel_registerName("otherEventWithType:location:modifierFlags:timestamp:windowNumber:context:subtype:data1:data2:"),
+ NSEventTypeApplicationDefined, (NSPoint){0, 0}, 0, 0, 0, NULL, 0, 0, 0);
+
+ ((void (*)(id, SEL, id, bool))objc_msgSend)
+ (NSApp, sel_registerName("postEvent:atStart:"), e, 1);
+
+ objc_msgSend_bool_void(eventPool, sel_registerName("drain"));
+ }
+
+ void RGFW_window_eventWait(RGFW_window* win, i32 waitMS) {
+ RGFW_UNUSED(win);
+
+ id eventPool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc"));
+ eventPool = objc_msgSend_id(eventPool, sel_registerName("init"));
+
+ void* date = (void*) ((id(*)(Class, SEL, double))objc_msgSend)
+ (objc_getClass("NSDate"), sel_registerName("dateWithTimeIntervalSinceNow:"), waitMS);
+
+ NSEvent* e = (NSEvent*) ((id(*)(id, SEL, NSEventMask, void*, NSString*, bool))objc_msgSend)
+ (NSApp, sel_registerName("nextEventMatchingMask:untilDate:inMode:dequeue:"),
+ ULONG_MAX, date, NSString_stringWithUTF8String("kCFRunLoopDefaultMode"), true);
+
+
+ if (e) {
+ objc_msgSend_void_id(NSApp, sel_registerName("sendEvent:"), e);
+ }
+
+ objc_msgSend_bool_void(eventPool, sel_registerName("drain"));
+ }
+
+ RGFW_Event* RGFW_window_checkEvent(RGFW_window* win) {
+ assert(win != NULL);
+
+ if (win->event.type == RGFW_quit)
+ return NULL;
+
+ if ((win->event.type == RGFW_dnd || win->event.type == RGFW_dnd_init) && win->src.dndPassed == 0) {
+ win->src.dndPassed = 1;
+ return &win->event;
+ }
+
+ id eventPool = objc_msgSend_class(objc_getClass("NSAutoreleasePool"), sel_registerName("alloc"));
+ eventPool = objc_msgSend_id(eventPool, sel_registerName("init"));
+
+ static void* eventFunc = NULL;
+ if (eventFunc == NULL)
+ eventFunc = sel_registerName("nextEventMatchingMask:untilDate:inMode:dequeue:");
+
+ if ((win->event.type == RGFW_windowMoved || win->event.type == RGFW_windowResized || win->event.type == RGFW_windowRefresh) && win->event.keyCode != 120) {
+ win->event.keyCode = 120;
+ objc_msgSend_bool_void(eventPool, sel_registerName("drain"));
+ return &win->event;
+ }
+
+ void* date = NULL;
+
+ NSEvent* e = (NSEvent*) ((id(*)(id, SEL, NSEventMask, void*, NSString*, bool))objc_msgSend)
+ (NSApp, eventFunc, ULONG_MAX, date, NSString_stringWithUTF8String("kCFRunLoopDefaultMode"), true);
+
+ if (e == NULL) {
+ objc_msgSend_bool_void(eventPool, sel_registerName("drain"));
+ return NULL;
+ }
+
+ if (objc_msgSend_id(e, sel_registerName("window")) != win->src.window) {
+ ((void (*)(id, SEL, id, bool))objc_msgSend)
+ (NSApp, sel_registerName("postEvent:atStart:"), e, 0);
+
+ objc_msgSend_bool_void(eventPool, sel_registerName("drain"));
+ return NULL;
+ }
+
+ if (win->event.droppedFilesCount) {
+ u32 i;
+ for (i = 0; i < win->event.droppedFilesCount; i++)
+ win->event.droppedFiles[i][0] = '\0';
+ }
+
+ win->event.droppedFilesCount = 0;
+ win->event.type = 0;
+
+ switch (objc_msgSend_uint(e, sel_registerName("type"))) {
+ case NSEventTypeMouseEntered: {
+ win->event.type = RGFW_mouseEnter;
+ NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)(e, sel_registerName("locationInWindow"));
+
+ win->event.point = RGFW_POINT((i32) p.x, (i32) (win->r.h - p.y));
+ RGFW_mouseNotifyCallBack(win, win->event.point, 1);
+ break;
+ }
+
+ case NSEventTypeMouseExited:
+ win->event.type = RGFW_mouseLeave;
+ RGFW_mouseNotifyCallBack(win, win->event.point, 0);
+ break;
+
+ case NSEventTypeKeyDown: {
+ u32 key = (u16) objc_msgSend_uint(e, sel_registerName("keyCode"));
+ win->event.keyCode = RGFW_apiKeyCodeToRGFW(key);
+ RGFW_keyboard[win->event.keyCode].prev = RGFW_keyboard[win->event.keyCode].current;
+
+ win->event.type = RGFW_keyPressed;
+ char* str = (char*)(const char*) NSString_to_char(objc_msgSend_id(e, sel_registerName("characters")));
+ strncpy(win->event.keyName, str, 16);
+ win->event.repeat = RGFW_isPressed(win, win->event.keyCode);
+ RGFW_keyboard[win->event.keyCode].current = 1;
+
+ RGFW_keyCallback(win, win->event.keyCode, win->event.keyName, win->event.lockState, 1);
+ break;
+ }
+
+ case NSEventTypeKeyUp: {
+ u32 key = (u16) objc_msgSend_uint(e, sel_registerName("keyCode"));
+ win->event.keyCode = RGFW_apiKeyCodeToRGFW(key);;
+
+ RGFW_keyboard[win->event.keyCode].prev = RGFW_keyboard[win->event.keyCode].current;
+
+ win->event.type = RGFW_keyReleased;
+ char* str = (char*)(const char*) NSString_to_char(objc_msgSend_id(e, sel_registerName("characters")));
+ strncpy(win->event.keyName, str, 16);
+
+ RGFW_keyboard[win->event.keyCode].current = 0;
+ RGFW_keyCallback(win, win->event.keyCode, win->event.keyName, win->event.lockState, 0);
+ break;
+ }
+
+ case NSEventTypeFlagsChanged: {
+ u32 flags = objc_msgSend_uint(e, sel_registerName("modifierFlags"));
+ RGFW_updateLockState(win, ((u32)(flags & NSEventModifierFlagCapsLock) % 255), ((flags & NSEventModifierFlagNumericPad) % 255));
+
+ u8 i;
+ for (i = 0; i < 9; i++)
+ RGFW_keyboard[i + RGFW_CapsLock].prev = 0;
+
+ for (i = 0; i < 5; i++) {
+ u32 shift = (1 << (i + 16));
+ u32 key = i + RGFW_CapsLock;
+
+ if ((flags & shift) && !RGFW_wasPressed(win, key)) {
+ RGFW_keyboard[key].current = 1;
+
+ if (key != RGFW_CapsLock)
+ RGFW_keyboard[key+ 4].current = 1;
+
+ win->event.type = RGFW_keyPressed;
+ win->event.keyCode = key;
+ break;
+ }
+
+ if (!(flags & shift) && RGFW_wasPressed(win, key)) {
+ RGFW_keyboard[key].current = 0;
+
+ if (key != RGFW_CapsLock)
+ RGFW_keyboard[key + 4].current = 0;
+
+ win->event.type = RGFW_keyReleased;
+ win->event.keyCode = key;
+ break;
+ }
+ }
+
+ RGFW_keyCallback(win, win->event.keyCode, win->event.keyName, win->event.lockState, win->event.type == RGFW_keyPressed);
+
+ break;
+ }
+ case NSEventTypeLeftMouseDragged:
+ case NSEventTypeOtherMouseDragged:
+ case NSEventTypeRightMouseDragged:
+ case NSEventTypeMouseMoved:
+ win->event.type = RGFW_mousePosChanged;
+ NSPoint p = ((NSPoint(*)(id, SEL)) objc_msgSend)(e, sel_registerName("locationInWindow"));
+ win->event.point = RGFW_POINT((u32) p.x, (u32) (win->r.h - p.y));
+
+ if ((win->_winArgs & RGFW_HOLD_MOUSE)) {
+ p.x = ((CGFloat(*)(id, SEL))abi_objc_msgSend_fpret)(e, sel_registerName("deltaX"));
+ p.y = ((CGFloat(*)(id, SEL))abi_objc_msgSend_fpret)(e, sel_registerName("deltaY"));
+
+ win->event.point = RGFW_POINT((i32)p.x, (i32)p.y);
+ }
+
+ RGFW_mousePosCallback(win, win->event.point);
+ break;
+
+ case NSEventTypeLeftMouseDown:
+ win->event.button = RGFW_mouseLeft;
+ win->event.type = RGFW_mouseButtonPressed;
+ RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current;
+ RGFW_mouseButtons[win->event.button].current = 1;
+ RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1);
+ break;
+
+ case NSEventTypeOtherMouseDown:
+ win->event.button = RGFW_mouseMiddle;
+ win->event.type = RGFW_mouseButtonPressed;
+ RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current;
+ RGFW_mouseButtons[win->event.button].current = 1;
+ RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1);
+ break;
+
+ case NSEventTypeRightMouseDown:
+ win->event.button = RGFW_mouseRight;
+ win->event.type = RGFW_mouseButtonPressed;
+ RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current;
+ RGFW_mouseButtons[win->event.button].current = 1;
+ RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1);
+ break;
+
+ case NSEventTypeLeftMouseUp:
+ win->event.button = RGFW_mouseLeft;
+ win->event.type = RGFW_mouseButtonReleased;
+ RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current;
+ RGFW_mouseButtons[win->event.button].current = 0;
+ RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0);
+ break;
+
+ case NSEventTypeOtherMouseUp:
+ win->event.button = RGFW_mouseMiddle;
+ RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current;
+ RGFW_mouseButtons[win->event.button].current = 0;
+ win->event.type = RGFW_mouseButtonReleased;
+ RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0);
+ break;
+
+ case NSEventTypeRightMouseUp:
+ win->event.button = RGFW_mouseRight;
+ RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current;
+ RGFW_mouseButtons[win->event.button].current = 0;
+ win->event.type = RGFW_mouseButtonReleased;
+ RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 0);
+ break;
+
+ case NSEventTypeScrollWheel: {
+ double deltaY = ((CGFloat(*)(id, SEL))abi_objc_msgSend_fpret)(e, sel_registerName("deltaY"));
+
+ if (deltaY > 0) {
+ win->event.button = RGFW_mouseScrollUp;
+ }
+ else if (deltaY < 0) {
+ win->event.button = RGFW_mouseScrollDown;
+ }
+
+ RGFW_mouseButtons[win->event.button].prev = RGFW_mouseButtons[win->event.button].current;
+ RGFW_mouseButtons[win->event.button].current = 1;
+
+ win->event.scroll = deltaY;
+
+ win->event.type = RGFW_mouseButtonPressed;
+ RGFW_mouseButtonCallback(win, win->event.button, win->event.scroll, 1);
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ objc_msgSend_void_id(NSApp, sel_registerName("sendEvent:"), e);
+ ((void(*)(id, SEL))objc_msgSend)(NSApp, sel_registerName("updateWindows"));
+
+ objc_msgSend_bool_void(eventPool, sel_registerName("drain"));
+ return &win->event;
+ }
+
+
+ void RGFW_window_move(RGFW_window* win, RGFW_point v) {
+ assert(win != NULL);
+
+ win->r.x = v.x;
+ win->r.y = v.y;
+ ((void(*)(id, SEL, NSRect, bool, bool))objc_msgSend)
+ (win->src.window, sel_registerName("setFrame:display:animate:"), (NSRect){{win->r.x, win->r.y}, {win->r.w, win->r.h}}, true, true);
+ }
+
+ void RGFW_window_resize(RGFW_window* win, RGFW_area a) {
+ assert(win != NULL);
+
+ win->r.w = a.w;
+ win->r.h = a.h;
+ ((void(*)(id, SEL, NSRect, bool, bool))objc_msgSend)
+ (win->src.window, sel_registerName("setFrame:display:animate:"), (NSRect){{win->r.x, win->r.y}, {win->r.w, win->r.h}}, true, true);
+ }
+
+ void RGFW_window_minimize(RGFW_window* win) {
+ assert(win != NULL);
+
+ objc_msgSend_void_SEL(win->src.window, sel_registerName("performMiniaturize:"), NULL);
+ }
+
+ void RGFW_window_restore(RGFW_window* win) {
+ assert(win != NULL);
+
+ objc_msgSend_void_SEL(win->src.window, sel_registerName("deminiaturize:"), NULL);
+ }
+
+ void RGFW_window_setName(RGFW_window* win, char* name) {
+ assert(win != NULL);
+
+ NSString* str = NSString_stringWithUTF8String(name);
+ objc_msgSend_void_id(win->src.window, sel_registerName("setTitle:"), str);
+ }
+
+ #ifndef RGFW_NO_PASSTHROUGH
+ void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough) {
+ objc_msgSend_void_bool(win->src.window, sel_registerName("setIgnoresMouseEvents:"), passthrough);
+ }
+ #endif
+
+ void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a) {
+ if (a.w == 0 && a.h == 0)
+ return;
+
+ ((void (*)(id, SEL, NSSize))objc_msgSend)
+ (win->src.window, sel_registerName("setMinSize:"), (NSSize){a.w, a.h});
+ }
+
+ void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a) {
+ if (a.w == 0 && a.h == 0)
+ return;
+
+ ((void (*)(id, SEL, NSSize))objc_msgSend)
+ (win->src.window, sel_registerName("setMaxSize:"), (NSSize){a.w, a.h});
+ }
+
+ void RGFW_window_setIcon(RGFW_window* win, u8* data, RGFW_area area, i32 channels) {
+ assert(win != NULL);
+
+ /* code by EimaMei */
+ // Make a bitmap representation, then copy the loaded image into it.
+ void* representation = NSBitmapImageRep_initWithBitmapData(NULL, area.w, area.h, 8, channels, (channels == 4), false, "NSCalibratedRGBColorSpace", 1 << 1, area.w * channels, 8 * channels);
+ memcpy(NSBitmapImageRep_bitmapData(representation), data, area.w * area.h * channels);
+
+ // Add ze representation.
+ void* dock_image = NSImage_initWithSize((NSSize){area.w, area.h});
+ NSImage_addRepresentation(dock_image, (void*) representation);
+
+ // Finally, set the dock image to it.
+ objc_msgSend_void_id(NSApp, sel_registerName("setApplicationIconImage:"), dock_image);
+ // Free the garbage.
+ release(dock_image);
+ release(representation);
+ }
+
+ NSCursor* NSCursor_arrowStr(char* str) {
+ void* nclass = objc_getClass("NSCursor");
+ void* func = sel_registerName(str);
+ return (NSCursor*) objc_msgSend_id(nclass, func);
+ }
+
+ void RGFW_window_setMouse(RGFW_window* win, u8* image, RGFW_area a, i32 channels) {
+ assert(win != NULL);
+
+ if (image == NULL) {
+ objc_msgSend_void(NSCursor_arrowStr("arrowCursor"), sel_registerName("set"));
+ return;
+ }
+
+ /* NOTE(EimaMei): Code by yours truly. */
+ // Make a bitmap representation, then copy the loaded image into it.
+ void* representation = NSBitmapImageRep_initWithBitmapData(NULL, a.w, a.h, 8, channels, (channels == 4), false, "NSCalibratedRGBColorSpace", 1 << 1, a.w * channels, 8 * channels);
+ memcpy(NSBitmapImageRep_bitmapData(representation), image, a.w * a.h * channels);
+
+ // Add ze representation.
+ void* cursor_image = NSImage_initWithSize((NSSize){a.w, a.h});
+ NSImage_addRepresentation(cursor_image, representation);
+
+ // Finally, set the cursor image.
+ void* cursor = NSCursor_initWithImage(cursor_image, (NSPoint){0.0, 0.0});
+
+ objc_msgSend_void(cursor, sel_registerName("set"));
+
+ // Free the garbage.
+ release(cursor_image);
+ release(representation);
+ }
+
+ void RGFW_window_setMouseDefault(RGFW_window* win) {
+ RGFW_window_setMouseStandard(win, RGFW_MOUSE_ARROW);
+ }
+
+ void RGFW_window_showMouse(RGFW_window* win, i8 show) {
+ RGFW_UNUSED(win);
+
+ if (show) {
+ CGDisplayShowCursor(kCGDirectMainDisplay);
+ }
+ else {
+ CGDisplayHideCursor(kCGDirectMainDisplay);
+ }
+ }
+
+ void RGFW_window_setMouseStandard(RGFW_window* win, u8 stdMouses) {
+ if (stdMouses > ((sizeof(RGFW_mouseIconSrc)) / (sizeof(char*))))
+ return;
+
+ char* mouseStr = RGFW_mouseIconSrc[stdMouses];
+ void* mouse = NSCursor_arrowStr(mouseStr);
+
+ if (mouse == NULL)
+ return;
+
+ RGFW_UNUSED(win);
+ CGDisplayShowCursor(kCGDirectMainDisplay);
+ objc_msgSend_void(mouse, sel_registerName("set"));
+ }
+
+ void RGFW_releaseCursor(RGFW_window* win) {
+ RGFW_UNUSED(win);
+ CGAssociateMouseAndMouseCursorPosition(1);
+ }
+
+ void RGFW_captureCursor(RGFW_window* win, RGFW_rect r) {
+ RGFW_UNUSED(win)
+
+ CGWarpMouseCursorPosition(CGPointMake(r.x + (r.w / 2), r.y + (r.h / 2)));
+ CGAssociateMouseAndMouseCursorPosition(0);
+ }
+
+ void RGFW_window_moveMouse(RGFW_window* win, RGFW_point v) {
+ RGFW_UNUSED(win);
+
+ CGWarpMouseCursorPosition(CGPointMake(v.x, v.y));
+ }
+
+
+ void RGFW_window_hide(RGFW_window* win) {
+ objc_msgSend_void_bool(win->src.window, sel_registerName("setIsVisible:"), false);
+ }
+
+ void RGFW_window_show(RGFW_window* win) {
+ ((id(*)(id, SEL, SEL))objc_msgSend)(win->src.window, sel_registerName("makeKeyAndOrderFront:"), NULL);
+ objc_msgSend_void_bool(win->src.window, sel_registerName("setIsVisible:"), true);
+ }
+
+ u8 RGFW_window_isFullscreen(RGFW_window* win) {
+ assert(win != NULL);
+
+ NSWindowStyleMask mask = (NSWindowStyleMask) objc_msgSend_uint(win->src.window, sel_registerName("styleMask"));
+ return (mask & NSWindowStyleMaskFullScreen) == NSWindowStyleMaskFullScreen;
+ }
+
+ u8 RGFW_window_isHidden(RGFW_window* win) {
+ assert(win != NULL);
+
+ bool visible = objc_msgSend_bool(win->src.window, sel_registerName("isVisible"));
+ return visible == NO && !RGFW_window_isMinimized(win);
+ }
+
+ u8 RGFW_window_isMinimized(RGFW_window* win) {
+ assert(win != NULL);
+
+ return objc_msgSend_bool(win->src.window, sel_registerName("isMiniaturized")) == YES;
+ }
+
+ u8 RGFW_window_isMaximized(RGFW_window* win) {
+ assert(win != NULL);
+
+ return objc_msgSend_bool(win->src.window, sel_registerName("isZoomed"));
+ }
+
+ static RGFW_monitor RGFW_NSCreateMonitor(CGDirectDisplayID display) {
+ RGFW_monitor monitor;
+
+ CGRect bounds = CGDisplayBounds(display);
+ monitor.rect = RGFW_RECT((int) bounds.origin.x, (int) bounds.origin.y, (int) bounds.size.width, (int) bounds.size.height);
+
+ CGSize screenSizeMM = CGDisplayScreenSize(display);
+ monitor.physW = screenSizeMM.width;
+ monitor.physH = screenSizeMM.height;
+
+ monitor.scaleX = ((monitor.rect.w / (screenSizeMM.width / 25.4)) / 96) + 0.25;
+ monitor.scaleY = ((monitor.rect.h / (screenSizeMM.height / 25.4)) / 96) + 0.25;
+
+ return monitor;
+ }
+
+
+ static RGFW_monitor RGFW_monitors[7];
+
+ RGFW_monitor* RGFW_getMonitors(void) {
+ static CGDirectDisplayID displays[7];
+ u32 count;
+
+ if (CGGetActiveDisplayList(6, displays, &count) != kCGErrorSuccess)
+ return NULL;
+
+ for (u32 i = 0; i < count; i++)
+ RGFW_monitors[i] = RGFW_NSCreateMonitor(displays[i]);
+
+ return RGFW_monitors;
+ }
+
+ RGFW_monitor RGFW_getPrimaryMonitor(void) {
+ CGDirectDisplayID primary = CGMainDisplayID();
+ return RGFW_NSCreateMonitor(primary);
+ }
+
+ RGFW_monitor RGFW_window_getMonitor(RGFW_window* win) {
+ return RGFW_NSCreateMonitor(win->src.display);
+ }
+
+ char* RGFW_readClipboard(size_t* size) {
+ char* clip = (char*)NSPasteboard_stringForType(NSPasteboard_generalPasteboard(), NSPasteboardTypeString);
+
+ size_t clip_len = 1;
+
+ if (clip != NULL) {
+ clip_len = strlen(clip) + 1;
+ }
+
+ char* str = (char*)RGFW_MALLOC(sizeof(char) * clip_len);
+
+ if (clip != NULL) {
+ strncpy(str, clip, clip_len);
+ }
+
+ str[clip_len] = '\0';
+
+ if (size != NULL)
+ *size = clip_len;
+ return str;
+ }
+
+ void RGFW_writeClipboard(const char* text, u32 textLen) {
+ RGFW_UNUSED(textLen);
+
+ NSPasteboardType array[] = { NSPasteboardTypeString, NULL };
+ NSPasteBoard_declareTypes(NSPasteboard_generalPasteboard(), array, 1, NULL);
+
+ NSPasteBoard_setString(NSPasteboard_generalPasteboard(), text, NSPasteboardTypeString);
+ }
+
+ u16 RGFW_registerJoystick(RGFW_window* win, i32 jsNumber) {
+ RGFW_UNUSED(jsNumber);
+
+ assert(win != NULL);
+
+ return RGFW_registerJoystickF(win, (char*) "");
+ }
+
+ u16 RGFW_registerJoystickF(RGFW_window* win, char* file) {
+ RGFW_UNUSED(file);
+
+ assert(win != NULL);
+
+ return RGFW_joystickCount - 1;
+ }
+
+ #ifdef RGFW_OPENGL
+ void RGFW_window_makeCurrent_OpenGL(RGFW_window* win) {
+ assert(win != NULL);
+ objc_msgSend_void(win->src.ctx, sel_registerName("makeCurrentContext"));
+ }
+ #endif
+
+ #if !defined(RGFW_EGL)
+ void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) {
+ assert(win != NULL);
+ #if defined(RGFW_OPENGL)
+
+ NSOpenGLContext_setValues(win->src.ctx, &swapInterval, 222);
+ #else
+ RGFW_UNUSED(swapInterval);
+ #endif
+ }
+ #endif
+
+ // Function to create a CGImageRef from an array of bytes
+ CGImageRef createImageFromBytes(unsigned char *buffer, int width, int height)
+ {
+ // Define color space
+ CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
+ // Create bitmap context
+ CGContextRef context = CGBitmapContextCreate(
+ buffer,
+ width, height,
+ 8,
+ RGFW_bufferSize.w * 4,
+ colorSpace,
+ kCGImageAlphaPremultipliedLast);
+ // Create image from bitmap context
+ CGImageRef image = CGBitmapContextCreateImage(context);
+ // Release the color space and context
+ CGColorSpaceRelease(colorSpace);
+ CGContextRelease(context);
+
+ return image;
+ }
+
+ void RGFW_window_swapBuffers(RGFW_window* win) {
+ assert(win != NULL);
+ /* clear the window*/
+
+ if (!(win->_winArgs & RGFW_NO_CPU_RENDER)) {
+#if defined(RGFW_OSMESA) || defined(RGFW_BUFFER)
+ #ifdef RGFW_OSMESA
+ RGFW_OSMesa_reorganize();
+ #endif
+
+ void* view = NSWindow_contentView(win->src.window);
+ void* layer = objc_msgSend_id(view, sel_registerName("layer"));
+
+ ((void(*)(id, SEL, NSRect))objc_msgSend)(layer,
+ sel_registerName("setFrame:"),
+ (NSRect){{0, 0}, {win->r.w, win->r.h}});
+
+ CGImageRef image = createImageFromBytes(win->buffer, win->r.w, win->r.h);
+ // Get the current graphics context
+ id graphicsContext = objc_msgSend_class(objc_getClass("NSGraphicsContext"), sel_registerName("currentContext"));
+ // Get the CGContext from the current NSGraphicsContext
+ id cgContext = objc_msgSend_id(graphicsContext, sel_registerName("graphicsPort"));
+ // Draw the image in the context
+ NSRect bounds = (NSRect){{0,0}, {win->r.w, win->r.h}};
+ CGContextDrawImage((void*)cgContext, *(CGRect*)&bounds, image);
+ // Flush the graphics context to ensure the drawing is displayed
+ objc_msgSend_id(graphicsContext, sel_registerName("flushGraphics"));
+
+ objc_msgSend_void_id(layer, sel_registerName("setContents:"), (id)image);
+ objc_msgSend_id(layer, sel_registerName("setNeedsDisplay"));
+
+ CGImageRelease(image);
+#endif
+ }
+
+ if (!(win->_winArgs & RGFW_NO_GPU_RENDER)) {
+ #ifdef RGFW_EGL
+ eglSwapBuffers(win->src.EGL_display, win->src.EGL_surface);
+ #elif defined(RGFW_OPENGL)
+ objc_msgSend_void(win->src.ctx, sel_registerName("flushBuffer"));
+ #endif
+ }
+ }
+
+ void RGFW_window_close(RGFW_window* win) {
+ assert(win != NULL);
+ release(win->src.view);
+
+#ifdef RGFW_ALLOC_DROPFILES
+ {
+ u32 i;
+ for (i = 0; i < RGFW_MAX_DROPS; i++)
+ RGFW_FREE(win->event.droppedFiles[i]);
+
+
+ RGFW_FREE(win->event.droppedFiles);
+ }
+#endif
+
+#ifdef RGFW_BUFFER
+ release(win->src.bitmap);
+ release(win->src.image);
+#endif
+
+ CVDisplayLinkStop(win->src.displayLink);
+ CVDisplayLinkRelease(win->src.displayLink);
+
+ RGFW_FREE(win);
+ }
+
+ u64 RGFW_getTimeNS(void) {
+ static mach_timebase_info_data_t timebase_info;
+ if (timebase_info.denom == 0) {
+ mach_timebase_info(&timebase_info);
+ }
+ return mach_absolute_time() * timebase_info.numer / timebase_info.denom;
+ }
+
+ u64 RGFW_getTime(void) {
+ static mach_timebase_info_data_t timebase_info;
+ if (timebase_info.denom == 0) {
+ mach_timebase_info(&timebase_info);
+ }
+ return (double) mach_absolute_time() * (double) timebase_info.numer / ((double) timebase_info.denom * 1e9);
+ }
+#endif /* RGFW_MACOS */
+
+/*
+ End of MaOS defines
+*/
+
+/*
+ WEBASM defines
+*/
+
+#ifdef RGFW_WEBASM
+RGFW_Event RGFW_events[20];
+size_t RGFW_eventLen = 0;
+
+EM_BOOL Emscripten_on_keydown(int eventType, const EmscriptenKeyboardEvent* e, void* userData) {
+ RGFW_UNUSED(eventType); RGFW_UNUSED(userData);
+
+ RGFW_events[RGFW_eventLen].type = RGFW_keyPressed;
+ memcpy(RGFW_events[RGFW_eventLen].keyName, e->key, 16);
+ RGFW_events[RGFW_eventLen].keyCode = RGFW_apiKeyCodeToRGFW(e->keyCode);
+ RGFW_events[RGFW_eventLen].lockState = 0;
+ RGFW_eventLen++;
+
+ RGFW_keyboard[RGFW_apiKeyCodeToRGFW(e->keyCode)].prev = RGFW_keyboard[RGFW_apiKeyCodeToRGFW(e->keyCode)].current;
+ RGFW_keyboard[RGFW_apiKeyCodeToRGFW(e->keyCode)].current = 1;
+ RGFW_keyCallback(RGFW_root, RGFW_apiKeyCodeToRGFW(e->keyCode), RGFW_events[RGFW_eventLen].keyName, 0, 1);
+
+ return EM_TRUE;
+}
+
+EM_BOOL Emscripten_on_keyup(int eventType, const EmscriptenKeyboardEvent* e, void* userData) {
+ RGFW_UNUSED(eventType); RGFW_UNUSED(userData);
+
+ RGFW_events[RGFW_eventLen].type = RGFW_keyReleased;
+ memcpy(RGFW_events[RGFW_eventLen].keyName, e->key, 16);
+ RGFW_events[RGFW_eventLen].keyCode = RGFW_apiKeyCodeToRGFW(e->keyCode);
+ RGFW_events[RGFW_eventLen].lockState = 0;
+ RGFW_eventLen++;
+
+ RGFW_keyboard[RGFW_apiKeyCodeToRGFW(e->keyCode)].prev = RGFW_keyboard[RGFW_apiKeyCodeToRGFW(e->keyCode)].current;
+ RGFW_keyboard[RGFW_apiKeyCodeToRGFW(e->keyCode)].current = 0;
+
+ RGFW_keyCallback(RGFW_root, RGFW_apiKeyCodeToRGFW(e->keyCode), RGFW_events[RGFW_eventLen].keyName, 0, 0);
+
+ return EM_TRUE;
+}
+
+EM_BOOL Emscripten_on_resize(int eventType, const EmscriptenUiEvent* e, void* userData) {
+ RGFW_UNUSED(eventType); RGFW_UNUSED(userData);
+
+ RGFW_events[RGFW_eventLen].type = RGFW_windowResized;
+ RGFW_eventLen++;
+
+ RGFW_windowResizeCallback(RGFW_root, RGFW_RECT(0, 0, e->windowInnerWidth, e->windowInnerHeight));
+ return EM_TRUE;
+}
+
+EM_BOOL Emscripten_on_fullscreenchange(int eventType, const EmscriptenFullscreenChangeEvent* e, void* userData) {
+ RGFW_UNUSED(eventType); RGFW_UNUSED(userData);
+
+ RGFW_events[RGFW_eventLen].type = RGFW_windowResized;
+ RGFW_eventLen++;
+
+ RGFW_root->r = RGFW_RECT(0, 0, e->elementWidth, e->elementHeight);
+ RGFW_windowResizeCallback(RGFW_root, RGFW_root->r);
+ return EM_TRUE;
+}
+
+EM_BOOL Emscripten_on_focusin(int eventType, const EmscriptenFocusEvent* e, void* userData) {
+ RGFW_UNUSED(eventType); RGFW_UNUSED(userData); RGFW_UNUSED(e);
+
+ RGFW_events[RGFW_eventLen].type = RGFW_focusIn;
+ RGFW_eventLen++;
+
+ RGFW_root->event.inFocus = 1;
+ RGFW_focusCallback(RGFW_root, 1);
+ return EM_TRUE;
+}
+
+EM_BOOL Emscripten_on_focusout(int eventType, const EmscriptenFocusEvent* e, void* userData) {
+ RGFW_UNUSED(eventType); RGFW_UNUSED(userData); RGFW_UNUSED(e);
+
+ RGFW_events[RGFW_eventLen].type = RGFW_focusOut;
+ RGFW_eventLen++;
+
+ RGFW_root->event.inFocus = 0;
+ RGFW_focusCallback(RGFW_root, 0);
+ return EM_TRUE;
+}
+
+EM_BOOL Emscripten_on_mousemove(int eventType, const EmscriptenMouseEvent* e, void* userData) {
+ RGFW_UNUSED(eventType); RGFW_UNUSED(userData);
+
+ RGFW_events[RGFW_eventLen].type = RGFW_mousePosChanged;
+
+ if ((RGFW_root->_winArgs & RGFW_HOLD_MOUSE)) {
+ RGFW_point p = RGFW_POINT(e->movementX, e->movementY);
+ RGFW_events[RGFW_eventLen].point = p;
+ }
+ else
+ RGFW_events[RGFW_eventLen].point = RGFW_POINT(e->targetX, e->targetY);
+ RGFW_eventLen++;
+
+ RGFW_mousePosCallback(RGFW_root, RGFW_events[RGFW_eventLen].point);
+ return EM_TRUE;
+}
+
+EM_BOOL Emscripten_on_mousedown(int eventType, const EmscriptenMouseEvent* e, void* userData) {
+ RGFW_UNUSED(eventType); RGFW_UNUSED(userData);
+
+ RGFW_events[RGFW_eventLen].type = RGFW_mouseButtonPressed;
+ RGFW_events[RGFW_eventLen].point = RGFW_POINT(e->targetX, e->targetY);
+ RGFW_events[RGFW_eventLen].button = e->button + 1;
+ RGFW_events[RGFW_eventLen].scroll = 0;
+
+ RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].prev = RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current;
+ RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current = 1;
+
+ RGFW_mouseButtonCallback(RGFW_root, RGFW_events[RGFW_eventLen].button, RGFW_events[RGFW_eventLen].scroll, 1);
+ RGFW_eventLen++;
+
+ return EM_TRUE;
+}
+
+EM_BOOL Emscripten_on_mouseup(int eventType, const EmscriptenMouseEvent* e, void* userData) {
+ RGFW_UNUSED(eventType); RGFW_UNUSED(userData);
+
+ RGFW_events[RGFW_eventLen].type = RGFW_mouseButtonReleased;
+ RGFW_events[RGFW_eventLen].point = RGFW_POINT(e->targetX, e->targetY);
+ RGFW_events[RGFW_eventLen].button = e->button + 1;
+ RGFW_events[RGFW_eventLen].scroll = 0;
+
+ RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].prev = RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current;
+ RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current = 0;
+
+ RGFW_mouseButtonCallback(RGFW_root, RGFW_events[RGFW_eventLen].button, RGFW_events[RGFW_eventLen].scroll, 0);
+ RGFW_eventLen++;
+ return EM_TRUE;
+}
+
+EM_BOOL Emscripten_on_wheel(int eventType, const EmscriptenWheelEvent* e, void* userData) {
+ RGFW_UNUSED(eventType); RGFW_UNUSED(userData);
+
+ RGFW_events[RGFW_eventLen].type = RGFW_mouseButtonPressed;
+ RGFW_events[RGFW_eventLen].point = RGFW_POINT(e->mouse.targetX, e->mouse.targetY);
+ RGFW_events[RGFW_eventLen].button = RGFW_mouseScrollUp + (e->deltaY < 0);
+ RGFW_events[RGFW_eventLen].scroll = e->deltaY;
+
+ RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].prev = RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current;
+ RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current = 1;
+
+ RGFW_mouseButtonCallback(RGFW_root, RGFW_events[RGFW_eventLen].button, RGFW_events[RGFW_eventLen].scroll, 1);
+ RGFW_eventLen++;
+
+ return EM_TRUE;
+}
+
+EM_BOOL Emscripten_on_touchstart(int eventType, const EmscriptenTouchEvent* e, void* userData) {
+ RGFW_UNUSED(eventType); RGFW_UNUSED(userData);
+
+ size_t i;
+ for (i = 0; i < (size_t)e->numTouches; i++) {
+ RGFW_events[RGFW_eventLen].type = RGFW_mouseButtonPressed;
+ RGFW_events[RGFW_eventLen].point = RGFW_POINT(e->touches[i].targetX, e->touches[i].targetY);
+ RGFW_events[RGFW_eventLen].button = 1;
+ RGFW_events[RGFW_eventLen].scroll = 0;
+
+
+ RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].prev = RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current;
+ RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current = 1;
+
+ RGFW_mousePosCallback(RGFW_root, RGFW_events[RGFW_eventLen].point);
+
+ RGFW_mouseButtonCallback(RGFW_root, RGFW_events[RGFW_eventLen].button, RGFW_events[RGFW_eventLen].scroll, 1);
+ RGFW_eventLen++;
+ }
+
+ return EM_TRUE;
+}
+EM_BOOL Emscripten_on_touchmove(int eventType, const EmscriptenTouchEvent* e, void* userData) {
+ RGFW_UNUSED(eventType); RGFW_UNUSED(userData);
+
+ size_t i;
+ for (i = 0; i < (size_t)e->numTouches; i++) {
+ RGFW_events[RGFW_eventLen].type = RGFW_mousePosChanged;
+ RGFW_events[RGFW_eventLen].point = RGFW_POINT(e->touches[i].targetX, e->touches[i].targetY);
+
+ RGFW_mousePosCallback(RGFW_root, RGFW_events[RGFW_eventLen].point);
+ RGFW_eventLen++;
+ }
+ return EM_TRUE;
+}
+
+EM_BOOL Emscripten_on_touchend(int eventType, const EmscriptenTouchEvent* e, void* userData) {
+ RGFW_UNUSED(eventType); RGFW_UNUSED(userData);
+
+ size_t i;
+ for (i = 0; i < (size_t)e->numTouches; i++) {
+ RGFW_events[RGFW_eventLen].type = RGFW_mouseButtonReleased;
+ RGFW_events[RGFW_eventLen].point = RGFW_POINT(e->touches[i].targetX, e->touches[i].targetY);
+ RGFW_events[RGFW_eventLen].button = 1;
+ RGFW_events[RGFW_eventLen].scroll = 0;
+
+ RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].prev = RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current;
+ RGFW_mouseButtons[RGFW_events[RGFW_eventLen].button].current = 0;
+
+ RGFW_mouseButtonCallback(RGFW_root, RGFW_events[RGFW_eventLen].button, RGFW_events[RGFW_eventLen].scroll, 0);
+ RGFW_eventLen++;
+ }
+ return EM_TRUE;
+}
+
+EM_BOOL Emscripten_on_touchcancel(int eventType, const EmscriptenTouchEvent* e, void* userData) { RGFW_UNUSED(eventType); RGFW_UNUSED(userData); RGFW_UNUSED(e); return EM_TRUE; }
+
+EM_BOOL Emscripten_on_gamepad(int eventType, const EmscriptenGamepadEvent *gamepadEvent, void *userData) {
+ RGFW_UNUSED(eventType); RGFW_UNUSED(userData);
+
+ if (gamepadEvent->index >= 4)
+ return 0;
+
+ RGFW_joysticks[gamepadEvent->index] = gamepadEvent->connected;
+
+ return 1; // The event was consumed by the callback handler
+}
+
+void EMSCRIPTEN_KEEPALIVE Emscripten_onDrop(size_t count) {
+ if (!(RGFW_root->_winArgs & RGFW_ALLOW_DND))
+ return;
+
+ RGFW_events[RGFW_eventLen].droppedFilesCount = count;
+ RGFW_dndCallback(RGFW_root, RGFW_events[RGFW_eventLen].droppedFiles, count);
+ RGFW_eventLen++;
+}
+
+b8 RGFW_stopCheckEvents_bool = RGFW_FALSE;
+void RGFW_stopCheckEvents(void) {
+ RGFW_stopCheckEvents_bool = RGFW_TRUE;
+}
+
+void RGFW_window_eventWait(RGFW_window* win, i32 waitMS) {
+ RGFW_UNUSED(win);
+
+ if (waitMS == 0)
+ return;
+
+ u32 start = (u32)(((u64)RGFW_getTimeNS()) / 1e+6);
+
+ while ((RGFW_eventLen == 0) && RGFW_stopCheckEvents_bool == RGFW_FALSE &&
+ (waitMS < 0 || (RGFW_getTimeNS() / 1e+6) - start < waitMS)
+ ) {
+ emscripten_sleep(0);
+ }
+
+ RGFW_stopCheckEvents_bool = RGFW_FALSE;
+}
+
+RGFWDEF void RGFW_init_buffer(RGFW_window* win);
+void RGFW_init_buffer(RGFW_window* win) {
+ #if defined(RGFW_OSMESA) || defined(RGFW_BUFFER)
+ if (RGFW_bufferSize.w == 0 && RGFW_bufferSize.h == 0)
+ RGFW_bufferSize = RGFW_getScreenSize();
+
+ win->buffer = RGFW_MALLOC(RGFW_bufferSize.w * RGFW_bufferSize.h * 4);
+ #ifdef RGFW_OSMESA
+ win->src.ctx = OSMesaCreateContext(OSMESA_RGBA, NULL);
+ OSMesaMakeCurrent(win->src.ctx, win->buffer, GL_UNSIGNED_BYTE, win->r.w, win->r.h);
+ #endif
+ #else
+ RGFW_UNUSED(win); /*!< if buffer rendering is not being used */
+ #endif
+}
+
+void EMSCRIPTEN_KEEPALIVE RGFW_makeSetValue(size_t index, char* file) {
+ /* This seems like a terrible idea, don't replicate this unless you hate yourself or the OS */
+ /* TODO: find a better way to do this,
+ strcpy doesn't seem to work, maybe because of asyncio
+ */
+
+ RGFW_events[RGFW_eventLen].type = RGFW_dnd;
+ char** arr = (char**)&RGFW_events[RGFW_eventLen].droppedFiles[index];
+ *arr = file;
+}
+
+#include
+#include
+#include
+
+void EMSCRIPTEN_KEEPALIVE RGFW_mkdir(char* name) { mkdir(name, 0755); }
+
+void EMSCRIPTEN_KEEPALIVE RGFW_writeFile(const char *path, const char *data, size_t len) {
+ FILE* file = fopen(path, "w+");
+ if (file == NULL)
+ return;
+
+ fwrite(data, sizeof(char), len, file);
+ fclose(file);
+}
+
+RGFW_window* RGFW_createWindow(const char* name, RGFW_rect rect, u16 args) {
+ RGFW_UNUSED(name)
+
+ RGFW_UNUSED(RGFW_initFormatAttribs);
+
+ RGFW_window* win = RGFW_window_basic_init(rect, args);
+
+#ifndef RGFW_WEBGPU
+ EmscriptenWebGLContextAttributes attrs;
+ attrs.alpha = EM_TRUE;
+ attrs.depth = EM_TRUE;
+ attrs.alpha = EM_TRUE;
+ attrs.stencil = RGFW_STENCIL;
+ attrs.antialias = RGFW_SAMPLES;
+ attrs.premultipliedAlpha = EM_TRUE;
+ attrs.preserveDrawingBuffer = EM_FALSE;
+
+ if (RGFW_DOUBLE_BUFFER == 0)
+ attrs.renderViaOffscreenBackBuffer = 0;
+ else
+ attrs.renderViaOffscreenBackBuffer = RGFW_AUX_BUFFERS;
+
+ attrs.failIfMajorPerformanceCaveat = EM_FALSE;
+ attrs.majorVersion = (RGFW_majorVersion == 0) ? 1 : RGFW_majorVersion;
+ attrs.minorVersion = RGFW_minorVersion;
+
+ attrs.enableExtensionsByDefault = EM_TRUE;
+ attrs.explicitSwapControl = EM_TRUE;
+
+ emscripten_webgl_init_context_attributes(&attrs);
+ win->src.ctx = emscripten_webgl_create_context("#canvas", &attrs);
+ emscripten_webgl_make_context_current(win->src.ctx);
+
+ #ifdef LEGACY_GL_EMULATION
+ EM_ASM("Module.useWebGL = true; GLImmediate.init();");
+ #endif
+#else
+ win->src.ctx = wgpuCreateInstance(NULL);
+ win->src.device = emscripten_webgpu_get_device();
+ win->src.queue = wgpuDeviceGetQueue(win->src.device);
+#endif
+
+ emscripten_set_canvas_element_size("#canvas", rect.w, rect.h);
+ emscripten_set_window_title(name);
+
+ /* load callbacks */
+ emscripten_set_keydown_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, EM_FALSE, Emscripten_on_keydown);
+ emscripten_set_keyup_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, EM_FALSE, Emscripten_on_keyup);
+ emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, EM_FALSE, Emscripten_on_resize);
+ emscripten_set_fullscreenchange_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, NULL, EM_FALSE, Emscripten_on_fullscreenchange);
+ emscripten_set_mousemove_callback("#canvas", NULL, EM_FALSE, Emscripten_on_mousemove);
+ emscripten_set_touchstart_callback("#canvas", NULL, EM_FALSE, Emscripten_on_touchstart);
+ emscripten_set_touchend_callback("#canvas", NULL, EM_FALSE, Emscripten_on_touchend);
+ emscripten_set_touchmove_callback("#canvas", NULL, EM_FALSE, Emscripten_on_touchmove);
+ emscripten_set_touchcancel_callback("#canvas", NULL, EM_FALSE, Emscripten_on_touchcancel);
+ emscripten_set_mousedown_callback("#canvas", NULL, EM_FALSE, Emscripten_on_mousedown);
+ emscripten_set_mouseup_callback("#canvas", NULL, EM_FALSE, Emscripten_on_mouseup);
+ emscripten_set_wheel_callback("#canvas", NULL, EM_FALSE, Emscripten_on_wheel);
+ emscripten_set_focusin_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, EM_FALSE, Emscripten_on_focusin);
+ emscripten_set_focusout_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, EM_FALSE, Emscripten_on_focusout);
+ emscripten_set_gamepadconnected_callback(NULL, 1, Emscripten_on_gamepad);
+ emscripten_set_gamepaddisconnected_callback(NULL, 1, Emscripten_on_gamepad);
+
+ if (args & RGFW_ALLOW_DND) {
+ win->_winArgs |= RGFW_ALLOW_DND;
+ }
+
+ EM_ASM({
+ var canvas = document.getElementById('canvas');
+ canvas.addEventListener('drop', function(e) {
+ e.preventDefault();
+ if (e.dataTransfer.file < 0)
+ return;
+
+ var filenamesArray = [];
+ var count = e.dataTransfer.files.length;
+
+ /* Read and save the files to emscripten's files */
+ var drop_dir = '.rgfw_dropped_files';
+ Module._RGFW_mkdir(drop_dir);
+
+ for (var i = 0; i < count; i++) {
+ var file = e.dataTransfer.files[i];
+
+ var path = '/' + drop_dir + '/' + file.name.replace("//", '_');
+ var reader = new FileReader();
+
+ reader.onloadend = (e) => {
+ if (reader.readyState != 2) {
+ out('failed to read dropped file: '+file.name+': '+reader.error);
+ }
+ else {
+ var data = e.target.result;
+
+ _RGFW_writeFile(path, new Uint8Array(data), file.size);
+ }
+ };
+
+ reader.readAsArrayBuffer(file);
+ // This works weird on modern opengl
+ var filename = stringToNewUTF8(path);
+
+ filenamesArray.push(filename);
+
+ Module._RGFW_makeSetValue(i, filename);
+ }
+
+ Module._Emscripten_onDrop(count);
+
+ for (var i = 0; i < count; ++i) {
+ _free(filenamesArray[i]);
+ }
+ }, true);
+
+ canvas.addEventListener('dragover', function(e) { e.preventDefault(); return false; }, true);
+ });
+
+ RGFW_init_buffer(win);
+ glViewport(0, 0, rect.w, rect.h);
+
+ RGFW_root = win;
+
+ if (args & RGFW_HIDE_MOUSE) {
+ RGFW_window_showMouse(win, 0);
+ }
+
+ if (args & RGFW_FULLSCREEN) {
+ RGFW_window_resize(win, RGFW_getScreenSize());
+ }
+
+ return win;
+}
+
+RGFW_Event* RGFW_window_checkEvent(RGFW_window* win) {
+ static u8 index = 0;
+
+ if (index == 0)
+ RGFW_resetKey();
+
+ /* check gamepads */
+ for (int i = 0; (i < emscripten_get_num_gamepads()) && (i < 4); i++) {
+ if (RGFW_joysticks[i] == 0)
+ continue;;
+
+ EmscriptenGamepadEvent gamepadState;
+
+ if (emscripten_get_gamepad_status(i, &gamepadState) != EMSCRIPTEN_RESULT_SUCCESS)
+ break;
+
+ // Register buttons data for every connected gamepad
+ for (int j = 0; (j < gamepadState.numButtons) && (j < 16); j++) {
+ u32 map[] = {
+ RGFW_JS_A, RGFW_JS_X, RGFW_JS_B, RGFW_JS_Y,
+ RGFW_JS_L1, RGFW_JS_R1, RGFW_JS_L2, RGFW_JS_R2,
+ RGFW_JS_SELECT, RGFW_JS_START,
+ 0, 0,
+ RGFW_JS_UP, RGFW_JS_DOWN, RGFW_JS_LEFT, RGFW_JS_RIGHT
+ };
+
+ u32 button = map[j];
+ if (RGFW_jsPressed[i][button] != gamepadState.digitalButton[j]) {
+ win->event.type = RGFW_jsButtonPressed;
+ win->event.joystick = i;
+ win->event.button = map[j];
+ return &win->event;
+ }
+
+ RGFW_jsPressed[i][button] = gamepadState.digitalButton[j];
+ }
+
+ for (int j = 0; (j < gamepadState.numAxes) && (j < 4); j += 2) {
+ win->event.axisesCount = gamepadState.numAxes;
+ if (win->event.axis[j].x != gamepadState.axis[j] ||
+ win->event.axis[j].y != gamepadState.axis[j + 1]
+ ) {
+ win->event.axis[j].x = gamepadState.axis[j];
+ win->event.axis[j].y = gamepadState.axis[j + 1];
+ win->event.type = RGFW_jsAxisMove;
+ win->event.joystick = i;
+ return &win->event;
+ }
+ }
+ }
+
+ /* check queued events */
+ if (RGFW_eventLen == 0)
+ return NULL;
+
+ RGFW_events[index].frameTime = win->event.frameTime;
+ RGFW_events[index].frameTime2 = win->event.frameTime2;
+ RGFW_events[index].inFocus = win->event.inFocus;
+
+ win->event = RGFW_events[index];
+
+ RGFW_eventLen--;
+
+ if (RGFW_eventLen)
+ index++;
+ else
+ index = 0;
+
+ return &win->event;
+}
+
+void RGFW_window_resize(RGFW_window* win, RGFW_area a) {
+ RGFW_UNUSED(win)
+ emscripten_set_canvas_element_size("#canvas", a.w, a.h);
+}
+
+/* NOTE: I don't know if this is possible */
+void RGFW_window_moveMouse(RGFW_window* win, RGFW_point v) { RGFW_UNUSED(win); RGFW_UNUSED(v); }
+/* this one might be possible but it looks iffy */
+void RGFW_window_setMouse(RGFW_window* win, u8* image, RGFW_area a, i32 channels) { RGFW_UNUSED(win); RGFW_UNUSED(channels) RGFW_UNUSED(a) RGFW_UNUSED(image) }
+
+const char RGFW_CURSORS[11][12] = {
+ "default",
+ "default",
+ "text",
+ "crosshair",
+ "pointer",
+ "ew-resize",
+ "ns-resize",
+ "nwse-resize",
+ "nesw-resize",
+ "move",
+ "not-allowed"
+};
+
+void RGFW_window_setMouseStandard(RGFW_window* win, u8 mouse) {
+ RGFW_UNUSED(win)
+ EM_ASM( { document.getElementById("canvas").style.cursor = UTF8ToString($0); }, RGFW_CURSORS[mouse]);
+}
+
+void RGFW_window_setMouseDefault(RGFW_window* win) {
+ RGFW_window_setMouseStandard(win, RGFW_MOUSE_NORMAL);
+}
+
+void RGFW_window_showMouse(RGFW_window* win, i8 show) {
+ if (show)
+ RGFW_window_setMouseDefault(win);
+ else
+ EM_ASM(document.getElementById('canvas').style.cursor = 'none';);
+}
+
+RGFW_point RGFW_getGlobalMousePoint(void) {
+ RGFW_point point;
+ point.x = EM_ASM_INT({
+ return window.mouseX || 0;
+ });
+ point.y = EM_ASM_INT({
+ return window.mouseY || 0;
+ });
+ return point;
+}
+
+RGFW_point RGFW_window_getMousePoint(RGFW_window* win) {
+ RGFW_UNUSED(win);
+
+ EmscriptenMouseEvent mouseEvent;
+ emscripten_get_mouse_status(&mouseEvent);
+ return RGFW_POINT( mouseEvent.targetX, mouseEvent.targetY);
+}
+
+void RGFW_window_setMousePassthrough(RGFW_window* win, b8 passthrough) {
+ RGFW_UNUSED(win);
+
+ EM_ASM_({
+ var canvas = document.getElementById('canvas');
+ if ($0) {
+ canvas.style.pointerEvents = 'none';
+ } else {
+ canvas.style.pointerEvents = 'auto';
+ }
+ }, passthrough);
+}
+
+void RGFW_writeClipboard(const char* text, u32 textLen) {
+ RGFW_UNUSED(textLen)
+ EM_ASM({ navigator.clipboard.writeText(UTF8ToString($0)); }, text);
+}
+
+
+char* RGFW_readClipboard(size_t* size) {
+ /*
+ placeholder code for later
+ I'm not sure if this is possible do the the async stuff
+ */
+
+ if (size != NULL)
+ *size = 0;
+
+ char* str = (char*)malloc(1);
+ str[0] = '\0';
+
+ return str;
+}
+
+void RGFW_window_swapBuffers(RGFW_window* win) {
+ RGFW_UNUSED(win);
+
+ #ifdef RGFW_BUFFER
+ if (!(win->_winArgs & RGFW_NO_CPU_RENDER)) {
+ glEnable(GL_TEXTURE_2D);
+
+ GLuint texture;
+ glGenTextures(1,&texture);
+
+ glBindTexture(GL_TEXTURE_2D,texture);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, RGFW_bufferSize.w, RGFW_bufferSize.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, win->buffer);
+
+ float ratioX = ((float)win->r.w / (float)RGFW_bufferSize.w);
+ float ratioY = ((float)win->r.h / (float)RGFW_bufferSize.h);
+
+ // Set up the viewport
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glBegin(GL_TRIANGLES);
+ glTexCoord2f(0, ratioY); glColor3f(1, 1, 1); glVertex2f(-1, -1);
+ glTexCoord2f(0, 0); glColor3f(1, 1, 1); glVertex2f(-1, 1);
+ glTexCoord2f(ratioX, ratioY); glColor3f(1, 1, 1); glVertex2f(1, -1);
+
+ glTexCoord2f(ratioX, 0); glColor3f(1, 1, 1); glVertex2f(1, 1);
+ glTexCoord2f(ratioX, ratioY); glColor3f(1, 1, 1); glVertex2f(1, -1);
+ glTexCoord2f(0, 0); glColor3f(1, 1, 1); glVertex2f(-1, 1);
+ glEnd();
+
+ glDeleteTextures(1, &texture);
+ }
+ #endif
+
+#ifndef RGFW_WEBGPU
+ emscripten_webgl_commit_frame();
+#endif
+ emscripten_sleep(0);
+}
+
+
+void RGFW_window_makeCurrent_OpenGL(RGFW_window* win) {
+#ifndef RGFW_WEBGPU
+ if (win == NULL)
+ emscripten_webgl_make_context_current(0);
+ else
+ emscripten_webgl_make_context_current(win->src.ctx);
+#endif
+}
+
+#ifndef RGFW_EGL
+void RGFW_window_swapInterval(RGFW_window* win, i32 swapInterval) { RGFW_UNUSED(win); RGFW_UNUSED(swapInterval); }
+#endif
+
+void RGFW_window_close(RGFW_window* win) {
+#ifndef RGFW_WEBGPU
+ emscripten_webgl_destroy_context(win->src.ctx);
+#endif
+
+ free(win);
+}
+
+int RGFW_innerWidth(void) { return EM_ASM_INT({ return window.innerWidth; }); }
+int RGFW_innerHeight(void) { return EM_ASM_INT({ return window.innerHeight; }); }
+
+RGFW_area RGFW_getScreenSize(void) {
+ return RGFW_AREA(RGFW_innerWidth(), RGFW_innerHeight());
+}
+
+void* RGFW_getProcAddress(const char* procname) {
+ return emscripten_webgl_get_proc_address(procname);
+}
+
+void RGFW_sleep(u64 milisecond) {
+ emscripten_sleep(milisecond);
+}
+
+u64 RGFW_getTimeNS(void) {
+ return emscripten_get_now() * 1e+6;
+}
+
+u64 RGFW_getTime(void) {
+ return emscripten_get_now() * 1000;
+}
+
+void RGFW_releaseCursor(RGFW_window* win) {
+ RGFW_UNUSED(win);
+ emscripten_exit_pointerlock();
+}
+
+void RGFW_captureCursor(RGFW_window* win, RGFW_rect r) {
+ RGFW_UNUSED(win); RGFW_UNUSED(r);
+
+ emscripten_request_pointerlock("#canvas", 1);
+}
+
+
+void RGFW_window_setName(RGFW_window* win, char* name) {
+ RGFW_UNUSED(win);
+ emscripten_set_window_title(name);
+}
+
+/* unsupported functions */
+RGFW_monitor* RGFW_getMonitors(void) { return NULL; }
+RGFW_monitor RGFW_getPrimaryMonitor(void) { return (RGFW_monitor){}; }
+void RGFW_window_move(RGFW_window* win, RGFW_point v) { RGFW_UNUSED(win) RGFW_UNUSED(v) }
+void RGFW_window_setMinSize(RGFW_window* win, RGFW_area a) { RGFW_UNUSED(win) RGFW_UNUSED(a) }
+void RGFW_window_setMaxSize(RGFW_window* win, RGFW_area a) { RGFW_UNUSED(win) RGFW_UNUSED(a) }
+void RGFW_window_minimize(RGFW_window* win) { RGFW_UNUSED(win)}
+void RGFW_window_restore(RGFW_window* win) { RGFW_UNUSED(win) }
+void RGFW_window_setBorder(RGFW_window* win, b8 border) { RGFW_UNUSED(win) RGFW_UNUSED(border) }
+void RGFW_window_setIcon(RGFW_window* win, u8* icon, RGFW_area a, i32 channels) { RGFW_UNUSED(win) RGFW_UNUSED(icon) RGFW_UNUSED(a) RGFW_UNUSED(channels) }
+void RGFW_window_hide(RGFW_window* win) { RGFW_UNUSED(win) }
+void RGFW_window_show(RGFW_window* win) {RGFW_UNUSED(win) }
+b8 RGFW_window_isHidden(RGFW_window* win) { RGFW_UNUSED(win) return 0; }
+b8 RGFW_window_isMinimized(RGFW_window* win) { RGFW_UNUSED(win) return 0; }
+b8 RGFW_window_isMaximized(RGFW_window* win) { RGFW_UNUSED(win) return 0; }
+RGFW_monitor RGFW_window_getMonitor(RGFW_window* win) { RGFW_UNUSED(win) return (RGFW_monitor){}; }
+
+#endif
+
+/* end of web asm defines */
+
+/* unix (macOS, linux, web asm) only stuff */
+#if defined(RGFW_X11) || defined(RGFW_MACOS) || defined(RGFW_WEBASM) || defined(RGFW_WAYLAND)
+/* unix threading */
+#ifndef RGFW_NO_THREADS
+#include
+
+ RGFW_thread RGFW_createThread(RGFW_threadFunc_ptr ptr, void* args) {
+ RGFW_UNUSED(args);
+
+ RGFW_thread t;
+ pthread_create((pthread_t*) &t, NULL, *ptr, NULL);
+ return t;
+ }
+ void RGFW_cancelThread(RGFW_thread thread) { pthread_cancel((pthread_t) thread); }
+ void RGFW_joinThread(RGFW_thread thread) { pthread_join((pthread_t) thread, NULL); }
+#ifdef __linux__
+ void RGFW_setThreadPriority(RGFW_thread thread, u8 priority) { pthread_setschedprio((pthread_t)thread, priority); }
+#endif
+#endif
+
+#ifndef RGFW_WEBASM
+/* unix sleep */
+ void RGFW_sleep(u64 ms) {
+ struct timespec time;
+ time.tv_sec = 0;
+ time.tv_nsec = ms * 1e+6;
+
+ nanosleep(&time, NULL);
+ }
+#endif
+
+#endif /* end of unix / mac stuff*/
+#endif /*RGFW_IMPLEMENTATION*/
+
+#if defined(__cplusplus) && !defined(__EMSCRIPTEN__)
+}
+#endif
diff --git a/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/android/native_app_glue/NOTICE b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/android/native_app_glue/NOTICE
new file mode 100644
index 0000000..d6c0922
--- /dev/null
+++ b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/android/native_app_glue/NOTICE
@@ -0,0 +1,13 @@
+Copyright (C) 2016 The Android Open Source Project
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/android/native_app_glue/android_native_app_glue.c b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/android/native_app_glue/android_native_app_glue.c
new file mode 100644
index 0000000..7eada08
--- /dev/null
+++ b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/android/native_app_glue/android_native_app_glue.c
@@ -0,0 +1,442 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#include "android_native_app_glue.h"
+#include
+
+#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "threaded_app", __VA_ARGS__))
+#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, "threaded_app", __VA_ARGS__))
+
+/* For debug builds, always enable the debug traces in this library */
+#ifndef NDEBUG
+# define LOGV(...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, "threaded_app", __VA_ARGS__))
+#else
+# define LOGV(...) ((void)0)
+#endif
+
+static void free_saved_state(struct android_app* android_app) {
+ pthread_mutex_lock(&android_app->mutex);
+ if (android_app->savedState != NULL) {
+ free(android_app->savedState);
+ android_app->savedState = NULL;
+ android_app->savedStateSize = 0;
+ }
+ pthread_mutex_unlock(&android_app->mutex);
+}
+
+int8_t android_app_read_cmd(struct android_app* android_app) {
+ int8_t cmd;
+ if (read(android_app->msgread, &cmd, sizeof(cmd)) == sizeof(cmd)) {
+ switch (cmd) {
+ case APP_CMD_SAVE_STATE:
+ free_saved_state(android_app);
+ break;
+ }
+ return cmd;
+ } else {
+ LOGE("No data on command pipe!");
+ }
+ return -1;
+}
+
+static void print_cur_config(struct android_app* android_app) {
+ char lang[2], country[2];
+ AConfiguration_getLanguage(android_app->config, lang);
+ AConfiguration_getCountry(android_app->config, country);
+
+ LOGV("Config: mcc=%d mnc=%d lang=%c%c cnt=%c%c orien=%d touch=%d dens=%d "
+ "keys=%d nav=%d keysHid=%d navHid=%d sdk=%d size=%d long=%d "
+ "modetype=%d modenight=%d",
+ AConfiguration_getMcc(android_app->config),
+ AConfiguration_getMnc(android_app->config),
+ lang[0], lang[1], country[0], country[1],
+ AConfiguration_getOrientation(android_app->config),
+ AConfiguration_getTouchscreen(android_app->config),
+ AConfiguration_getDensity(android_app->config),
+ AConfiguration_getKeyboard(android_app->config),
+ AConfiguration_getNavigation(android_app->config),
+ AConfiguration_getKeysHidden(android_app->config),
+ AConfiguration_getNavHidden(android_app->config),
+ AConfiguration_getSdkVersion(android_app->config),
+ AConfiguration_getScreenSize(android_app->config),
+ AConfiguration_getScreenLong(android_app->config),
+ AConfiguration_getUiModeType(android_app->config),
+ AConfiguration_getUiModeNight(android_app->config));
+}
+
+void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd) {
+ switch (cmd) {
+ case APP_CMD_INPUT_CHANGED:
+ LOGV("APP_CMD_INPUT_CHANGED\n");
+ pthread_mutex_lock(&android_app->mutex);
+ if (android_app->inputQueue != NULL) {
+ AInputQueue_detachLooper(android_app->inputQueue);
+ }
+ android_app->inputQueue = android_app->pendingInputQueue;
+ if (android_app->inputQueue != NULL) {
+ LOGV("Attaching input queue to looper");
+ AInputQueue_attachLooper(android_app->inputQueue,
+ android_app->looper, LOOPER_ID_INPUT, NULL,
+ &android_app->inputPollSource);
+ }
+ pthread_cond_broadcast(&android_app->cond);
+ pthread_mutex_unlock(&android_app->mutex);
+ break;
+
+ case APP_CMD_INIT_WINDOW:
+ LOGV("APP_CMD_INIT_WINDOW\n");
+ pthread_mutex_lock(&android_app->mutex);
+ android_app->window = android_app->pendingWindow;
+ pthread_cond_broadcast(&android_app->cond);
+ pthread_mutex_unlock(&android_app->mutex);
+ break;
+
+ case APP_CMD_TERM_WINDOW:
+ LOGV("APP_CMD_TERM_WINDOW\n");
+ pthread_cond_broadcast(&android_app->cond);
+ break;
+
+ case APP_CMD_RESUME:
+ case APP_CMD_START:
+ case APP_CMD_PAUSE:
+ case APP_CMD_STOP:
+ LOGV("activityState=%d\n", cmd);
+ pthread_mutex_lock(&android_app->mutex);
+ android_app->activityState = cmd;
+ pthread_cond_broadcast(&android_app->cond);
+ pthread_mutex_unlock(&android_app->mutex);
+ break;
+
+ case APP_CMD_CONFIG_CHANGED:
+ LOGV("APP_CMD_CONFIG_CHANGED\n");
+ AConfiguration_fromAssetManager(android_app->config,
+ android_app->activity->assetManager);
+ print_cur_config(android_app);
+ break;
+
+ case APP_CMD_DESTROY:
+ LOGV("APP_CMD_DESTROY\n");
+ android_app->destroyRequested = 1;
+ break;
+ }
+}
+
+void android_app_post_exec_cmd(struct android_app* android_app, int8_t cmd) {
+ switch (cmd) {
+ case APP_CMD_TERM_WINDOW:
+ LOGV("APP_CMD_TERM_WINDOW\n");
+ pthread_mutex_lock(&android_app->mutex);
+ android_app->window = NULL;
+ pthread_cond_broadcast(&android_app->cond);
+ pthread_mutex_unlock(&android_app->mutex);
+ break;
+
+ case APP_CMD_SAVE_STATE:
+ LOGV("APP_CMD_SAVE_STATE\n");
+ pthread_mutex_lock(&android_app->mutex);
+ android_app->stateSaved = 1;
+ pthread_cond_broadcast(&android_app->cond);
+ pthread_mutex_unlock(&android_app->mutex);
+ break;
+
+ case APP_CMD_RESUME:
+ free_saved_state(android_app);
+ break;
+ }
+}
+
+void app_dummy() {
+
+}
+
+static void android_app_destroy(struct android_app* android_app) {
+ LOGV("android_app_destroy!");
+ free_saved_state(android_app);
+ pthread_mutex_lock(&android_app->mutex);
+ if (android_app->inputQueue != NULL) {
+ AInputQueue_detachLooper(android_app->inputQueue);
+ }
+ AConfiguration_delete(android_app->config);
+ android_app->destroyed = 1;
+ pthread_cond_broadcast(&android_app->cond);
+ pthread_mutex_unlock(&android_app->mutex);
+ // Can't touch android_app object after this.
+}
+
+static void process_input(struct android_app* app, struct android_poll_source* source) {
+ AInputEvent* event = NULL;
+ while (AInputQueue_getEvent(app->inputQueue, &event) >= 0) {
+ LOGV("New input event: type=%d\n", AInputEvent_getType(event));
+ if (AInputQueue_preDispatchEvent(app->inputQueue, event)) {
+ continue;
+ }
+ int32_t handled = 0;
+ if (app->onInputEvent != NULL) handled = app->onInputEvent(app, event);
+ AInputQueue_finishEvent(app->inputQueue, event, handled);
+ }
+}
+
+static void process_cmd(struct android_app* app, struct android_poll_source* source) {
+ int8_t cmd = android_app_read_cmd(app);
+ android_app_pre_exec_cmd(app, cmd);
+ if (app->onAppCmd != NULL) app->onAppCmd(app, cmd);
+ android_app_post_exec_cmd(app, cmd);
+}
+
+static void* android_app_entry(void* param) {
+ struct android_app* android_app = (struct android_app*)param;
+
+ android_app->config = AConfiguration_new();
+ AConfiguration_fromAssetManager(android_app->config, android_app->activity->assetManager);
+
+ print_cur_config(android_app);
+
+ android_app->cmdPollSource.id = LOOPER_ID_MAIN;
+ android_app->cmdPollSource.app = android_app;
+ android_app->cmdPollSource.process = process_cmd;
+ android_app->inputPollSource.id = LOOPER_ID_INPUT;
+ android_app->inputPollSource.app = android_app;
+ android_app->inputPollSource.process = process_input;
+
+ ALooper* looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
+ ALooper_addFd(looper, android_app->msgread, LOOPER_ID_MAIN, ALOOPER_EVENT_INPUT, NULL,
+ &android_app->cmdPollSource);
+ android_app->looper = looper;
+
+ pthread_mutex_lock(&android_app->mutex);
+ android_app->running = 1;
+ pthread_cond_broadcast(&android_app->cond);
+ pthread_mutex_unlock(&android_app->mutex);
+
+ android_main(android_app);
+
+ android_app_destroy(android_app);
+ return NULL;
+}
+
+// --------------------------------------------------------------------
+// Native activity interaction (called from main thread)
+// --------------------------------------------------------------------
+
+static struct android_app* android_app_create(ANativeActivity* activity,
+ void* savedState, size_t savedStateSize) {
+ struct android_app* android_app = (struct android_app*)malloc(sizeof(struct android_app));
+ memset(android_app, 0, sizeof(struct android_app));
+ android_app->activity = activity;
+
+ pthread_mutex_init(&android_app->mutex, NULL);
+ pthread_cond_init(&android_app->cond, NULL);
+
+ if (savedState != NULL) {
+ android_app->savedState = malloc(savedStateSize);
+ android_app->savedStateSize = savedStateSize;
+ memcpy(android_app->savedState, savedState, savedStateSize);
+ }
+
+ int msgpipe[2];
+ if (pipe(msgpipe)) {
+ LOGE("could not create pipe: %s", strerror(errno));
+ return NULL;
+ }
+ android_app->msgread = msgpipe[0];
+ android_app->msgwrite = msgpipe[1];
+
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+ pthread_create(&android_app->thread, &attr, android_app_entry, android_app);
+
+ // Wait for thread to start.
+ pthread_mutex_lock(&android_app->mutex);
+ while (!android_app->running) {
+ pthread_cond_wait(&android_app->cond, &android_app->mutex);
+ }
+ pthread_mutex_unlock(&android_app->mutex);
+
+ return android_app;
+}
+
+static void android_app_write_cmd(struct android_app* android_app, int8_t cmd) {
+ if (write(android_app->msgwrite, &cmd, sizeof(cmd)) != sizeof(cmd)) {
+ LOGE("Failure writing android_app cmd: %s\n", strerror(errno));
+ }
+}
+
+static void android_app_set_input(struct android_app* android_app, AInputQueue* inputQueue) {
+ pthread_mutex_lock(&android_app->mutex);
+ android_app->pendingInputQueue = inputQueue;
+ android_app_write_cmd(android_app, APP_CMD_INPUT_CHANGED);
+ while (android_app->inputQueue != android_app->pendingInputQueue) {
+ pthread_cond_wait(&android_app->cond, &android_app->mutex);
+ }
+ pthread_mutex_unlock(&android_app->mutex);
+}
+
+static void android_app_set_window(struct android_app* android_app, ANativeWindow* window) {
+ pthread_mutex_lock(&android_app->mutex);
+ if (android_app->pendingWindow != NULL) {
+ android_app_write_cmd(android_app, APP_CMD_TERM_WINDOW);
+ }
+ android_app->pendingWindow = window;
+ if (window != NULL) {
+ android_app_write_cmd(android_app, APP_CMD_INIT_WINDOW);
+ }
+ while (android_app->window != android_app->pendingWindow) {
+ pthread_cond_wait(&android_app->cond, &android_app->mutex);
+ }
+ pthread_mutex_unlock(&android_app->mutex);
+}
+
+static void android_app_set_activity_state(struct android_app* android_app, int8_t cmd) {
+ pthread_mutex_lock(&android_app->mutex);
+ android_app_write_cmd(android_app, cmd);
+ while (android_app->activityState != cmd) {
+ pthread_cond_wait(&android_app->cond, &android_app->mutex);
+ }
+ pthread_mutex_unlock(&android_app->mutex);
+}
+
+static void android_app_free(struct android_app* android_app) {
+ pthread_mutex_lock(&android_app->mutex);
+ android_app_write_cmd(android_app, APP_CMD_DESTROY);
+ while (!android_app->destroyed) {
+ pthread_cond_wait(&android_app->cond, &android_app->mutex);
+ }
+ pthread_mutex_unlock(&android_app->mutex);
+
+ close(android_app->msgread);
+ close(android_app->msgwrite);
+ pthread_cond_destroy(&android_app->cond);
+ pthread_mutex_destroy(&android_app->mutex);
+ free(android_app);
+}
+
+static void onDestroy(ANativeActivity* activity) {
+ LOGV("Destroy: %p\n", activity);
+ android_app_free((struct android_app*)activity->instance);
+}
+
+static void onStart(ANativeActivity* activity) {
+ LOGV("Start: %p\n", activity);
+ android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_START);
+}
+
+static void onResume(ANativeActivity* activity) {
+ LOGV("Resume: %p\n", activity);
+ android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_RESUME);
+}
+
+static void* onSaveInstanceState(ANativeActivity* activity, size_t* outLen) {
+ struct android_app* android_app = (struct android_app*)activity->instance;
+ void* savedState = NULL;
+
+ LOGV("SaveInstanceState: %p\n", activity);
+ pthread_mutex_lock(&android_app->mutex);
+ android_app->stateSaved = 0;
+ android_app_write_cmd(android_app, APP_CMD_SAVE_STATE);
+ while (!android_app->stateSaved) {
+ pthread_cond_wait(&android_app->cond, &android_app->mutex);
+ }
+
+ if (android_app->savedState != NULL) {
+ savedState = android_app->savedState;
+ *outLen = android_app->savedStateSize;
+ android_app->savedState = NULL;
+ android_app->savedStateSize = 0;
+ }
+
+ pthread_mutex_unlock(&android_app->mutex);
+
+ return savedState;
+}
+
+static void onPause(ANativeActivity* activity) {
+ LOGV("Pause: %p\n", activity);
+ android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_PAUSE);
+}
+
+static void onStop(ANativeActivity* activity) {
+ LOGV("Stop: %p\n", activity);
+ android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_STOP);
+}
+
+static void onConfigurationChanged(ANativeActivity* activity) {
+ struct android_app* android_app = (struct android_app*)activity->instance;
+ LOGV("ConfigurationChanged: %p\n", activity);
+ android_app_write_cmd(android_app, APP_CMD_CONFIG_CHANGED);
+}
+
+static void onLowMemory(ANativeActivity* activity) {
+ struct android_app* android_app = (struct android_app*)activity->instance;
+ LOGV("LowMemory: %p\n", activity);
+ android_app_write_cmd(android_app, APP_CMD_LOW_MEMORY);
+}
+
+static void onWindowFocusChanged(ANativeActivity* activity, int focused) {
+ LOGV("WindowFocusChanged: %p -- %d\n", activity, focused);
+ android_app_write_cmd((struct android_app*)activity->instance,
+ focused ? APP_CMD_GAINED_FOCUS : APP_CMD_LOST_FOCUS);
+}
+
+static void onNativeWindowCreated(ANativeActivity* activity, ANativeWindow* window) {
+ LOGV("NativeWindowCreated: %p -- %p\n", activity, window);
+ android_app_set_window((struct android_app*)activity->instance, window);
+}
+
+static void onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow* window) {
+ LOGV("NativeWindowDestroyed: %p -- %p\n", activity, window);
+ android_app_set_window((struct android_app*)activity->instance, NULL);
+}
+
+static void onInputQueueCreated(ANativeActivity* activity, AInputQueue* queue) {
+ LOGV("InputQueueCreated: %p -- %p\n", activity, queue);
+ android_app_set_input((struct android_app*)activity->instance, queue);
+}
+
+static void onInputQueueDestroyed(ANativeActivity* activity, AInputQueue* queue) {
+ LOGV("InputQueueDestroyed: %p -- %p\n", activity, queue);
+ android_app_set_input((struct android_app*)activity->instance, NULL);
+}
+
+JNIEXPORT
+void ANativeActivity_onCreate(ANativeActivity* activity, void* savedState,
+ size_t savedStateSize) {
+ LOGV("Creating: %p\n", activity);
+ activity->callbacks->onDestroy = onDestroy;
+ activity->callbacks->onStart = onStart;
+ activity->callbacks->onResume = onResume;
+ activity->callbacks->onSaveInstanceState = onSaveInstanceState;
+ activity->callbacks->onPause = onPause;
+ activity->callbacks->onStop = onStop;
+ activity->callbacks->onConfigurationChanged = onConfigurationChanged;
+ activity->callbacks->onLowMemory = onLowMemory;
+ activity->callbacks->onWindowFocusChanged = onWindowFocusChanged;
+ activity->callbacks->onNativeWindowCreated = onNativeWindowCreated;
+ activity->callbacks->onNativeWindowDestroyed = onNativeWindowDestroyed;
+ activity->callbacks->onInputQueueCreated = onInputQueueCreated;
+ activity->callbacks->onInputQueueDestroyed = onInputQueueDestroyed;
+
+ activity->instance = android_app_create(activity, savedState, savedStateSize);
+}
diff --git a/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/android/native_app_glue/android_native_app_glue.h b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/android/native_app_glue/android_native_app_glue.h
new file mode 100644
index 0000000..c99d6e1
--- /dev/null
+++ b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/android/native_app_glue/android_native_app_glue.h
@@ -0,0 +1,354 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef _ANDROID_NATIVE_APP_GLUE_H
+#define _ANDROID_NATIVE_APP_GLUE_H
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * The native activity interface provided by
+ * is based on a set of application-provided callbacks that will be called
+ * by the Activity's main thread when certain events occur.
+ *
+ * This means that each one of this callbacks _should_ _not_ block, or they
+ * risk having the system force-close the application. This programming
+ * model is direct, lightweight, but constraining.
+ *
+ * The 'android_native_app_glue' static library is used to provide a different
+ * execution model where the application can implement its own main event
+ * loop in a different thread instead. Here's how it works:
+ *
+ * 1/ The application must provide a function named "android_main()" that
+ * will be called when the activity is created, in a new thread that is
+ * distinct from the activity's main thread.
+ *
+ * 2/ android_main() receives a pointer to a valid "android_app" structure
+ * that contains references to other important objects, e.g. the
+ * ANativeActivity obejct instance the application is running in.
+ *
+ * 3/ the "android_app" object holds an ALooper instance that already
+ * listens to two important things:
+ *
+ * - activity lifecycle events (e.g. "pause", "resume"). See APP_CMD_XXX
+ * declarations below.
+ *
+ * - input events coming from the AInputQueue attached to the activity.
+ *
+ * Each of these correspond to an ALooper identifier returned by
+ * ALooper_pollOnce with values of LOOPER_ID_MAIN and LOOPER_ID_INPUT,
+ * respectively.
+ *
+ * Your application can use the same ALooper to listen to additional
+ * file-descriptors. They can either be callback based, or with return
+ * identifiers starting with LOOPER_ID_USER.
+ *
+ * 4/ Whenever you receive a LOOPER_ID_MAIN or LOOPER_ID_INPUT event,
+ * the returned data will point to an android_poll_source structure. You
+ * can call the process() function on it, and fill in android_app->onAppCmd
+ * and android_app->onInputEvent to be called for your own processing
+ * of the event.
+ *
+ * Alternatively, you can call the low-level functions to read and process
+ * the data directly... look at the process_cmd() and process_input()
+ * implementations in the glue to see how to do this.
+ *
+ * See the sample named "native-activity" that comes with the NDK with a
+ * full usage example. Also look at the JavaDoc of NativeActivity.
+ */
+
+struct android_app;
+
+/**
+ * Data associated with an ALooper fd that will be returned as the "outData"
+ * when that source has data ready.
+ */
+struct android_poll_source {
+ // The identifier of this source. May be LOOPER_ID_MAIN or
+ // LOOPER_ID_INPUT.
+ int32_t id;
+
+ // The android_app this ident is associated with.
+ struct android_app* app;
+
+ // Function to call to perform the standard processing of data from
+ // this source.
+ void (*process)(struct android_app* app, struct android_poll_source* source);
+};
+
+/**
+ * This is the interface for the standard glue code of a threaded
+ * application. In this model, the application's code is running
+ * in its own thread separate from the main thread of the process.
+ * It is not required that this thread be associated with the Java
+ * VM, although it will need to be in order to make JNI calls any
+ * Java objects.
+ */
+struct android_app {
+ // The application can place a pointer to its own state object
+ // here if it likes.
+ void* userData;
+
+ // Fill this in with the function to process main app commands (APP_CMD_*)
+ void (*onAppCmd)(struct android_app* app, int32_t cmd);
+
+ // Fill this in with the function to process input events. At this point
+ // the event has already been pre-dispatched, and it will be finished upon
+ // return. Return 1 if you have handled the event, 0 for any default
+ // dispatching.
+ int32_t (*onInputEvent)(struct android_app* app, AInputEvent* event);
+
+ // The ANativeActivity object instance that this app is running in.
+ ANativeActivity* activity;
+
+ // The current configuration the app is running in.
+ AConfiguration* config;
+
+ // This is the last instance's saved state, as provided at creation time.
+ // It is NULL if there was no state. You can use this as you need; the
+ // memory will remain around until you call android_app_exec_cmd() for
+ // APP_CMD_RESUME, at which point it will be freed and savedState set to NULL.
+ // These variables should only be changed when processing a APP_CMD_SAVE_STATE,
+ // at which point they will be initialized to NULL and you can malloc your
+ // state and place the information here. In that case the memory will be
+ // freed for you later.
+ void* savedState;
+ size_t savedStateSize;
+
+ // The ALooper associated with the app's thread.
+ ALooper* looper;
+
+ // When non-NULL, this is the input queue from which the app will
+ // receive user input events.
+ AInputQueue* inputQueue;
+
+ // When non-NULL, this is the window surface that the app can draw in.
+ ANativeWindow* window;
+
+ // Current content rectangle of the window; this is the area where the
+ // window's content should be placed to be seen by the user.
+ ARect contentRect;
+
+ // Current state of the app's activity. May be either APP_CMD_START,
+ // APP_CMD_RESUME, APP_CMD_PAUSE, or APP_CMD_STOP; see below.
+ int activityState;
+
+ // This is non-zero when the application's NativeActivity is being
+ // destroyed and waiting for the app thread to complete.
+ int destroyRequested;
+
+ // -------------------------------------------------
+ // Below are "private" implementation of the glue code.
+
+ pthread_mutex_t mutex;
+ pthread_cond_t cond;
+
+ int msgread;
+ int msgwrite;
+
+ pthread_t thread;
+
+ struct android_poll_source cmdPollSource;
+ struct android_poll_source inputPollSource;
+
+ int running;
+ int stateSaved;
+ int destroyed;
+ int redrawNeeded;
+ AInputQueue* pendingInputQueue;
+ ANativeWindow* pendingWindow;
+ ARect pendingContentRect;
+};
+
+enum {
+ /**
+ * Looper data ID of commands coming from the app's main thread, which
+ * is returned as an identifier from ALooper_pollOnce(). The data for this
+ * identifier is a pointer to an android_poll_source structure.
+ * These can be retrieved and processed with android_app_read_cmd()
+ * and android_app_exec_cmd().
+ */
+ LOOPER_ID_MAIN = 1,
+
+ /**
+ * Looper data ID of events coming from the AInputQueue of the
+ * application's window, which is returned as an identifier from
+ * ALooper_pollOnce(). The data for this identifier is a pointer to an
+ * android_poll_source structure. These can be read via the inputQueue
+ * object of android_app.
+ */
+ LOOPER_ID_INPUT = 2,
+
+ /**
+ * Start of user-defined ALooper identifiers.
+ */
+ LOOPER_ID_USER = 3,
+};
+
+enum {
+ /**
+ * Command from main thread: the AInputQueue has changed. Upon processing
+ * this command, android_app->inputQueue will be updated to the new queue
+ * (or NULL).
+ */
+ APP_CMD_INPUT_CHANGED,
+
+ /**
+ * Command from main thread: a new ANativeWindow is ready for use. Upon
+ * receiving this command, android_app->window will contain the new window
+ * surface.
+ */
+ APP_CMD_INIT_WINDOW,
+
+ /**
+ * Command from main thread: the existing ANativeWindow needs to be
+ * terminated. Upon receiving this command, android_app->window still
+ * contains the existing window; after calling android_app_exec_cmd
+ * it will be set to NULL.
+ */
+ APP_CMD_TERM_WINDOW,
+
+ /**
+ * Command from main thread: the current ANativeWindow has been resized.
+ * Please redraw with its new size.
+ */
+ APP_CMD_WINDOW_RESIZED,
+
+ /**
+ * Command from main thread: the system needs that the current ANativeWindow
+ * be redrawn. You should redraw the window before handing this to
+ * android_app_exec_cmd() in order to avoid transient drawing glitches.
+ */
+ APP_CMD_WINDOW_REDRAW_NEEDED,
+
+ /**
+ * Command from main thread: the content area of the window has changed,
+ * such as from the soft input window being shown or hidden. You can
+ * find the new content rect in android_app::contentRect.
+ */
+ APP_CMD_CONTENT_RECT_CHANGED,
+
+ /**
+ * Command from main thread: the app's activity window has gained
+ * input focus.
+ */
+ APP_CMD_GAINED_FOCUS,
+
+ /**
+ * Command from main thread: the app's activity window has lost
+ * input focus.
+ */
+ APP_CMD_LOST_FOCUS,
+
+ /**
+ * Command from main thread: the current device configuration has changed.
+ */
+ APP_CMD_CONFIG_CHANGED,
+
+ /**
+ * Command from main thread: the system is running low on memory.
+ * Try to reduce your memory use.
+ */
+ APP_CMD_LOW_MEMORY,
+
+ /**
+ * Command from main thread: the app's activity has been started.
+ */
+ APP_CMD_START,
+
+ /**
+ * Command from main thread: the app's activity has been resumed.
+ */
+ APP_CMD_RESUME,
+
+ /**
+ * Command from main thread: the app should generate a new saved state
+ * for itself, to restore from later if needed. If you have saved state,
+ * allocate it with malloc and place it in android_app.savedState with
+ * the size in android_app.savedStateSize. The will be freed for you
+ * later.
+ */
+ APP_CMD_SAVE_STATE,
+
+ /**
+ * Command from main thread: the app's activity has been paused.
+ */
+ APP_CMD_PAUSE,
+
+ /**
+ * Command from main thread: the app's activity has been stopped.
+ */
+ APP_CMD_STOP,
+
+ /**
+ * Command from main thread: the app's activity is being destroyed,
+ * and waiting for the app thread to clean up and exit before proceeding.
+ */
+ APP_CMD_DESTROY,
+};
+
+/**
+ * Call when ALooper_pollAll() returns LOOPER_ID_MAIN, reading the next
+ * app command message.
+ */
+int8_t android_app_read_cmd(struct android_app* android_app);
+
+/**
+ * Call with the command returned by android_app_read_cmd() to do the
+ * initial pre-processing of the given command. You can perform your own
+ * actions for the command after calling this function.
+ */
+void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd);
+
+/**
+ * Call with the command returned by android_app_read_cmd() to do the
+ * final post-processing of the given command. You must have done your own
+ * actions for the command before calling this function.
+ */
+void android_app_post_exec_cmd(struct android_app* android_app, int8_t cmd);
+
+/**
+ * Dummy function that used to be used to prevent the linker from stripping app
+ * glue code. No longer necessary, since __attribute__((visibility("default")))
+ * does this for us.
+ */
+__attribute__((
+ deprecated("Calls to app_dummy are no longer necessary. See "
+ "https://github.com/android-ndk/ndk/issues/381."))) void
+app_dummy();
+
+/**
+ * This is the function that application code must implement, representing
+ * the main entry to the app.
+ */
+extern void android_main(struct android_app* app);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ANDROID_NATIVE_APP_GLUE_H */
diff --git a/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/android/native_app_glue/vendor.go b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/android/native_app_glue/vendor.go
new file mode 100644
index 0000000..0fb2a0f
--- /dev/null
+++ b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/android/native_app_glue/vendor.go
@@ -0,0 +1,4 @@
+//go:build required
+// +build required
+
+package vendor
diff --git a/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/cgltf.h b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/cgltf.h
new file mode 100644
index 0000000..36fd644
--- /dev/null
+++ b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/cgltf.h
@@ -0,0 +1,7081 @@
+/**
+ * cgltf - a single-file glTF 2.0 parser written in C99.
+ *
+ * Version: 1.14
+ *
+ * Website: https://github.com/jkuhlmann/cgltf
+ *
+ * Distributed under the MIT License, see notice at the end of this file.
+ *
+ * Building:
+ * Include this file where you need the struct and function
+ * declarations. Have exactly one source file where you define
+ * `CGLTF_IMPLEMENTATION` before including this file to get the
+ * function definitions.
+ *
+ * Reference:
+ * `cgltf_result cgltf_parse(const cgltf_options*, const void*,
+ * cgltf_size, cgltf_data**)` parses both glTF and GLB data. If
+ * this function returns `cgltf_result_success`, you have to call
+ * `cgltf_free()` on the created `cgltf_data*` variable.
+ * Note that contents of external files for buffers and images are not
+ * automatically loaded. You'll need to read these files yourself using
+ * URIs in the `cgltf_data` structure.
+ *
+ * `cgltf_options` is the struct passed to `cgltf_parse()` to control
+ * parts of the parsing process. You can use it to force the file type
+ * and provide memory allocation as well as file operation callbacks.
+ * Should be zero-initialized to trigger default behavior.
+ *
+ * `cgltf_data` is the struct allocated and filled by `cgltf_parse()`.
+ * It generally mirrors the glTF format as described by the spec (see
+ * https://github.com/KhronosGroup/glTF/tree/master/specification/2.0).
+ *
+ * `void cgltf_free(cgltf_data*)` frees the allocated `cgltf_data`
+ * variable.
+ *
+ * `cgltf_result cgltf_load_buffers(const cgltf_options*, cgltf_data*,
+ * const char* gltf_path)` can be optionally called to open and read buffer
+ * files using the `FILE*` APIs. The `gltf_path` argument is the path to
+ * the original glTF file, which allows the parser to resolve the path to
+ * buffer files.
+ *
+ * `cgltf_result cgltf_load_buffer_base64(const cgltf_options* options,
+ * cgltf_size size, const char* base64, void** out_data)` decodes
+ * base64-encoded data content. Used internally by `cgltf_load_buffers()`.
+ * This is useful when decoding data URIs in images.
+ *
+ * `cgltf_result cgltf_parse_file(const cgltf_options* options, const
+ * char* path, cgltf_data** out_data)` can be used to open the given
+ * file using `FILE*` APIs and parse the data using `cgltf_parse()`.
+ *
+ * `cgltf_result cgltf_validate(cgltf_data*)` can be used to do additional
+ * checks to make sure the parsed glTF data is valid.
+ *
+ * `cgltf_node_transform_local` converts the translation / rotation / scale properties of a node
+ * into a mat4.
+ *
+ * `cgltf_node_transform_world` calls `cgltf_node_transform_local` on every ancestor in order
+ * to compute the root-to-node transformation.
+ *
+ * `cgltf_accessor_unpack_floats` reads in the data from an accessor, applies sparse data (if any),
+ * and converts them to floating point. Assumes that `cgltf_load_buffers` has already been called.
+ * By passing null for the output pointer, users can find out how many floats are required in the
+ * output buffer.
+ *
+ * `cgltf_accessor_unpack_indices` reads in the index data from an accessor. Assumes that
+ * `cgltf_load_buffers` has already been called. By passing null for the output pointer, users can
+ * find out how many indices are required in the output buffer. Returns 0 if the accessor is
+ * sparse or if the output component size is less than the accessor's component size.
+ *
+ * `cgltf_num_components` is a tiny utility that tells you the dimensionality of
+ * a certain accessor type. This can be used before `cgltf_accessor_unpack_floats` to help allocate
+ * the necessary amount of memory. `cgltf_component_size` and `cgltf_calc_size` exist for
+ * similar purposes.
+ *
+ * `cgltf_accessor_read_float` reads a certain element from a non-sparse accessor and converts it to
+ * floating point, assuming that `cgltf_load_buffers` has already been called. The passed-in element
+ * size is the number of floats in the output buffer, which should be in the range [1, 16]. Returns
+ * false if the passed-in element_size is too small, or if the accessor is sparse.
+ *
+ * `cgltf_accessor_read_uint` is similar to its floating-point counterpart, but limited to reading
+ * vector types and does not support matrix types. The passed-in element size is the number of uints
+ * in the output buffer, which should be in the range [1, 4]. Returns false if the passed-in
+ * element_size is too small, or if the accessor is sparse.
+ *
+ * `cgltf_accessor_read_index` is similar to its floating-point counterpart, but it returns size_t
+ * and only works with single-component data types.
+ *
+ * `cgltf_copy_extras_json` allows users to retrieve the "extras" data that can be attached to many
+ * glTF objects (which can be arbitrary JSON data). This is a legacy function, consider using
+ * cgltf_extras::data directly instead. You can parse this data using your own JSON parser
+ * or, if you've included the cgltf implementation using the integrated JSMN JSON parser.
+ */
+#ifndef CGLTF_H_INCLUDED__
+#define CGLTF_H_INCLUDED__
+
+#include
+#include /* For uint8_t, uint32_t */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef size_t cgltf_size;
+typedef long long int cgltf_ssize;
+typedef float cgltf_float;
+typedef int cgltf_int;
+typedef unsigned int cgltf_uint;
+typedef int cgltf_bool;
+
+typedef enum cgltf_file_type
+{
+ cgltf_file_type_invalid,
+ cgltf_file_type_gltf,
+ cgltf_file_type_glb,
+ cgltf_file_type_max_enum
+} cgltf_file_type;
+
+typedef enum cgltf_result
+{
+ cgltf_result_success,
+ cgltf_result_data_too_short,
+ cgltf_result_unknown_format,
+ cgltf_result_invalid_json,
+ cgltf_result_invalid_gltf,
+ cgltf_result_invalid_options,
+ cgltf_result_file_not_found,
+ cgltf_result_io_error,
+ cgltf_result_out_of_memory,
+ cgltf_result_legacy_gltf,
+ cgltf_result_max_enum
+} cgltf_result;
+
+typedef struct cgltf_memory_options
+{
+ void* (*alloc_func)(void* user, cgltf_size size);
+ void (*free_func) (void* user, void* ptr);
+ void* user_data;
+} 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* user_data;
+} cgltf_file_options;
+
+typedef struct cgltf_options
+{
+ cgltf_file_type type; /* invalid == auto detect */
+ cgltf_size json_token_count; /* 0 == auto */
+ cgltf_memory_options memory;
+ cgltf_file_options file;
+} cgltf_options;
+
+typedef enum cgltf_buffer_view_type
+{
+ cgltf_buffer_view_type_invalid,
+ cgltf_buffer_view_type_indices,
+ cgltf_buffer_view_type_vertices,
+ cgltf_buffer_view_type_max_enum
+} cgltf_buffer_view_type;
+
+typedef enum cgltf_attribute_type
+{
+ cgltf_attribute_type_invalid,
+ cgltf_attribute_type_position,
+ cgltf_attribute_type_normal,
+ cgltf_attribute_type_tangent,
+ cgltf_attribute_type_texcoord,
+ cgltf_attribute_type_color,
+ cgltf_attribute_type_joints,
+ cgltf_attribute_type_weights,
+ cgltf_attribute_type_custom,
+ cgltf_attribute_type_max_enum
+} cgltf_attribute_type;
+
+typedef enum cgltf_component_type
+{
+ cgltf_component_type_invalid,
+ cgltf_component_type_r_8, /* BYTE */
+ cgltf_component_type_r_8u, /* UNSIGNED_BYTE */
+ cgltf_component_type_r_16, /* SHORT */
+ cgltf_component_type_r_16u, /* UNSIGNED_SHORT */
+ cgltf_component_type_r_32u, /* UNSIGNED_INT */
+ cgltf_component_type_r_32f, /* FLOAT */
+ cgltf_component_type_max_enum
+} cgltf_component_type;
+
+typedef enum cgltf_type
+{
+ cgltf_type_invalid,
+ cgltf_type_scalar,
+ cgltf_type_vec2,
+ cgltf_type_vec3,
+ cgltf_type_vec4,
+ cgltf_type_mat2,
+ cgltf_type_mat3,
+ cgltf_type_mat4,
+ cgltf_type_max_enum
+} cgltf_type;
+
+typedef enum cgltf_primitive_type
+{
+ cgltf_primitive_type_invalid,
+ cgltf_primitive_type_points,
+ cgltf_primitive_type_lines,
+ cgltf_primitive_type_line_loop,
+ cgltf_primitive_type_line_strip,
+ cgltf_primitive_type_triangles,
+ cgltf_primitive_type_triangle_strip,
+ cgltf_primitive_type_triangle_fan,
+ cgltf_primitive_type_max_enum
+} cgltf_primitive_type;
+
+typedef enum cgltf_alpha_mode
+{
+ cgltf_alpha_mode_opaque,
+ cgltf_alpha_mode_mask,
+ cgltf_alpha_mode_blend,
+ cgltf_alpha_mode_max_enum
+} cgltf_alpha_mode;
+
+typedef enum cgltf_animation_path_type {
+ cgltf_animation_path_type_invalid,
+ cgltf_animation_path_type_translation,
+ cgltf_animation_path_type_rotation,
+ cgltf_animation_path_type_scale,
+ cgltf_animation_path_type_weights,
+ cgltf_animation_path_type_max_enum
+} cgltf_animation_path_type;
+
+typedef enum cgltf_interpolation_type {
+ cgltf_interpolation_type_linear,
+ cgltf_interpolation_type_step,
+ cgltf_interpolation_type_cubic_spline,
+ cgltf_interpolation_type_max_enum
+} cgltf_interpolation_type;
+
+typedef enum cgltf_camera_type {
+ cgltf_camera_type_invalid,
+ cgltf_camera_type_perspective,
+ cgltf_camera_type_orthographic,
+ cgltf_camera_type_max_enum
+} cgltf_camera_type;
+
+typedef enum cgltf_light_type {
+ cgltf_light_type_invalid,
+ cgltf_light_type_directional,
+ cgltf_light_type_point,
+ cgltf_light_type_spot,
+ cgltf_light_type_max_enum
+} cgltf_light_type;
+
+typedef enum cgltf_data_free_method {
+ cgltf_data_free_method_none,
+ cgltf_data_free_method_file_release,
+ cgltf_data_free_method_memory_free,
+ cgltf_data_free_method_max_enum
+} cgltf_data_free_method;
+
+typedef struct cgltf_extras {
+ cgltf_size start_offset; /* this field is deprecated and will be removed in the future; use data instead */
+ cgltf_size end_offset; /* this field is deprecated and will be removed in the future; use data instead */
+
+ char* data;
+} cgltf_extras;
+
+typedef struct cgltf_extension {
+ char* name;
+ char* data;
+} cgltf_extension;
+
+typedef struct cgltf_buffer
+{
+ char* name;
+ cgltf_size size;
+ char* uri;
+ void* data; /* loaded by cgltf_load_buffers */
+ cgltf_data_free_method data_free_method;
+ cgltf_extras extras;
+ cgltf_size extensions_count;
+ cgltf_extension* extensions;
+} cgltf_buffer;
+
+typedef enum cgltf_meshopt_compression_mode {
+ cgltf_meshopt_compression_mode_invalid,
+ cgltf_meshopt_compression_mode_attributes,
+ cgltf_meshopt_compression_mode_triangles,
+ cgltf_meshopt_compression_mode_indices,
+ cgltf_meshopt_compression_mode_max_enum
+} cgltf_meshopt_compression_mode;
+
+typedef enum cgltf_meshopt_compression_filter {
+ cgltf_meshopt_compression_filter_none,
+ cgltf_meshopt_compression_filter_octahedral,
+ cgltf_meshopt_compression_filter_quaternion,
+ cgltf_meshopt_compression_filter_exponential,
+ cgltf_meshopt_compression_filter_max_enum
+} cgltf_meshopt_compression_filter;
+
+typedef struct cgltf_meshopt_compression
+{
+ cgltf_buffer* buffer;
+ cgltf_size offset;
+ cgltf_size size;
+ cgltf_size stride;
+ cgltf_size count;
+ cgltf_meshopt_compression_mode mode;
+ cgltf_meshopt_compression_filter filter;
+} cgltf_meshopt_compression;
+
+typedef struct cgltf_buffer_view
+{
+ char *name;
+ cgltf_buffer* buffer;
+ cgltf_size offset;
+ cgltf_size size;
+ cgltf_size stride; /* 0 == automatically determined by accessor */
+ cgltf_buffer_view_type type;
+ void* data; /* overrides buffer->data if present, filled by extensions */
+ cgltf_bool has_meshopt_compression;
+ cgltf_meshopt_compression meshopt_compression;
+ cgltf_extras extras;
+ cgltf_size extensions_count;
+ cgltf_extension* extensions;
+} cgltf_buffer_view;
+
+typedef struct cgltf_accessor_sparse
+{
+ cgltf_size count;
+ cgltf_buffer_view* indices_buffer_view;
+ cgltf_size indices_byte_offset;
+ cgltf_component_type indices_component_type;
+ cgltf_buffer_view* values_buffer_view;
+ cgltf_size values_byte_offset;
+} cgltf_accessor_sparse;
+
+typedef struct cgltf_accessor
+{
+ char* name;
+ cgltf_component_type component_type;
+ cgltf_bool normalized;
+ cgltf_type type;
+ cgltf_size offset;
+ cgltf_size count;
+ cgltf_size stride;
+ cgltf_buffer_view* buffer_view;
+ cgltf_bool has_min;
+ cgltf_float min[16];
+ cgltf_bool has_max;
+ cgltf_float max[16];
+ cgltf_bool is_sparse;
+ cgltf_accessor_sparse sparse;
+ cgltf_extras extras;
+ cgltf_size extensions_count;
+ cgltf_extension* extensions;
+} cgltf_accessor;
+
+typedef struct cgltf_attribute
+{
+ char* name;
+ cgltf_attribute_type type;
+ cgltf_int index;
+ cgltf_accessor* data;
+} cgltf_attribute;
+
+typedef struct cgltf_image
+{
+ char* name;
+ char* uri;
+ cgltf_buffer_view* buffer_view;
+ char* mime_type;
+ cgltf_extras extras;
+ cgltf_size extensions_count;
+ cgltf_extension* extensions;
+} cgltf_image;
+
+typedef struct cgltf_sampler
+{
+ char* name;
+ cgltf_int mag_filter;
+ cgltf_int min_filter;
+ cgltf_int wrap_s;
+ cgltf_int wrap_t;
+ cgltf_extras extras;
+ cgltf_size extensions_count;
+ cgltf_extension* extensions;
+} cgltf_sampler;
+
+typedef struct cgltf_texture
+{
+ char* name;
+ cgltf_image* image;
+ cgltf_sampler* sampler;
+ cgltf_bool has_basisu;
+ cgltf_image* basisu_image;
+ cgltf_bool has_webp;
+ cgltf_image* webp_image;
+ cgltf_extras extras;
+ cgltf_size extensions_count;
+ cgltf_extension* extensions;
+} cgltf_texture;
+
+typedef struct cgltf_texture_transform
+{
+ cgltf_float offset[2];
+ cgltf_float rotation;
+ cgltf_float scale[2];
+ cgltf_bool has_texcoord;
+ cgltf_int texcoord;
+} cgltf_texture_transform;
+
+typedef struct cgltf_texture_view
+{
+ cgltf_texture* texture;
+ cgltf_int texcoord;
+ cgltf_float scale; /* equivalent to strength for occlusion_texture */
+ cgltf_bool has_transform;
+ cgltf_texture_transform transform;
+} cgltf_texture_view;
+
+typedef struct cgltf_pbr_metallic_roughness
+{
+ cgltf_texture_view base_color_texture;
+ cgltf_texture_view metallic_roughness_texture;
+
+ cgltf_float base_color_factor[4];
+ cgltf_float metallic_factor;
+ cgltf_float roughness_factor;
+} cgltf_pbr_metallic_roughness;
+
+typedef struct cgltf_pbr_specular_glossiness
+{
+ cgltf_texture_view diffuse_texture;
+ cgltf_texture_view specular_glossiness_texture;
+
+ cgltf_float diffuse_factor[4];
+ cgltf_float specular_factor[3];
+ cgltf_float glossiness_factor;
+} cgltf_pbr_specular_glossiness;
+
+typedef struct cgltf_clearcoat
+{
+ cgltf_texture_view clearcoat_texture;
+ cgltf_texture_view clearcoat_roughness_texture;
+ cgltf_texture_view clearcoat_normal_texture;
+
+ cgltf_float clearcoat_factor;
+ cgltf_float clearcoat_roughness_factor;
+} cgltf_clearcoat;
+
+typedef struct cgltf_transmission
+{
+ cgltf_texture_view transmission_texture;
+ cgltf_float transmission_factor;
+} cgltf_transmission;
+
+typedef struct cgltf_ior
+{
+ cgltf_float ior;
+} cgltf_ior;
+
+typedef struct cgltf_specular
+{
+ cgltf_texture_view specular_texture;
+ cgltf_texture_view specular_color_texture;
+ cgltf_float specular_color_factor[3];
+ cgltf_float specular_factor;
+} cgltf_specular;
+
+typedef struct cgltf_volume
+{
+ cgltf_texture_view thickness_texture;
+ cgltf_float thickness_factor;
+ cgltf_float attenuation_color[3];
+ cgltf_float attenuation_distance;
+} cgltf_volume;
+
+typedef struct cgltf_sheen
+{
+ cgltf_texture_view sheen_color_texture;
+ cgltf_float sheen_color_factor[3];
+ cgltf_texture_view sheen_roughness_texture;
+ cgltf_float sheen_roughness_factor;
+} cgltf_sheen;
+
+typedef struct cgltf_emissive_strength
+{
+ cgltf_float emissive_strength;
+} cgltf_emissive_strength;
+
+typedef struct cgltf_iridescence
+{
+ cgltf_float iridescence_factor;
+ cgltf_texture_view iridescence_texture;
+ cgltf_float iridescence_ior;
+ cgltf_float iridescence_thickness_min;
+ cgltf_float iridescence_thickness_max;
+ cgltf_texture_view iridescence_thickness_texture;
+} cgltf_iridescence;
+
+typedef struct cgltf_anisotropy
+{
+ cgltf_float anisotropy_strength;
+ cgltf_float anisotropy_rotation;
+ cgltf_texture_view anisotropy_texture;
+} cgltf_anisotropy;
+
+typedef struct cgltf_dispersion
+{
+ cgltf_float dispersion;
+} cgltf_dispersion;
+
+typedef struct cgltf_material
+{
+ char* name;
+ cgltf_bool has_pbr_metallic_roughness;
+ cgltf_bool has_pbr_specular_glossiness;
+ cgltf_bool has_clearcoat;
+ cgltf_bool has_transmission;
+ cgltf_bool has_volume;
+ cgltf_bool has_ior;
+ cgltf_bool has_specular;
+ cgltf_bool has_sheen;
+ cgltf_bool has_emissive_strength;
+ cgltf_bool has_iridescence;
+ cgltf_bool has_anisotropy;
+ cgltf_bool has_dispersion;
+ cgltf_pbr_metallic_roughness pbr_metallic_roughness;
+ cgltf_pbr_specular_glossiness pbr_specular_glossiness;
+ cgltf_clearcoat clearcoat;
+ cgltf_ior ior;
+ cgltf_specular specular;
+ cgltf_sheen sheen;
+ cgltf_transmission transmission;
+ cgltf_volume volume;
+ cgltf_emissive_strength emissive_strength;
+ cgltf_iridescence iridescence;
+ cgltf_anisotropy anisotropy;
+ cgltf_dispersion dispersion;
+ cgltf_texture_view normal_texture;
+ cgltf_texture_view occlusion_texture;
+ cgltf_texture_view emissive_texture;
+ cgltf_float emissive_factor[3];
+ cgltf_alpha_mode alpha_mode;
+ cgltf_float alpha_cutoff;
+ cgltf_bool double_sided;
+ cgltf_bool unlit;
+ cgltf_extras extras;
+ cgltf_size extensions_count;
+ cgltf_extension* extensions;
+} cgltf_material;
+
+typedef struct cgltf_material_mapping
+{
+ cgltf_size variant;
+ cgltf_material* material;
+ cgltf_extras extras;
+} cgltf_material_mapping;
+
+typedef struct cgltf_morph_target {
+ cgltf_attribute* attributes;
+ cgltf_size attributes_count;
+} cgltf_morph_target;
+
+typedef struct cgltf_draco_mesh_compression {
+ cgltf_buffer_view* buffer_view;
+ cgltf_attribute* attributes;
+ cgltf_size attributes_count;
+} cgltf_draco_mesh_compression;
+
+typedef struct cgltf_mesh_gpu_instancing {
+ cgltf_attribute* attributes;
+ cgltf_size attributes_count;
+} cgltf_mesh_gpu_instancing;
+
+typedef struct cgltf_primitive {
+ cgltf_primitive_type type;
+ cgltf_accessor* indices;
+ cgltf_material* material;
+ cgltf_attribute* attributes;
+ cgltf_size attributes_count;
+ cgltf_morph_target* targets;
+ cgltf_size targets_count;
+ cgltf_extras extras;
+ cgltf_bool has_draco_mesh_compression;
+ cgltf_draco_mesh_compression draco_mesh_compression;
+ cgltf_material_mapping* mappings;
+ cgltf_size mappings_count;
+ cgltf_size extensions_count;
+ cgltf_extension* extensions;
+} cgltf_primitive;
+
+typedef struct cgltf_mesh {
+ char* name;
+ cgltf_primitive* primitives;
+ cgltf_size primitives_count;
+ cgltf_float* weights;
+ cgltf_size weights_count;
+ char** target_names;
+ cgltf_size target_names_count;
+ cgltf_extras extras;
+ cgltf_size extensions_count;
+ cgltf_extension* extensions;
+} cgltf_mesh;
+
+typedef struct cgltf_node cgltf_node;
+
+typedef struct cgltf_skin {
+ char* name;
+ cgltf_node** joints;
+ cgltf_size joints_count;
+ cgltf_node* skeleton;
+ cgltf_accessor* inverse_bind_matrices;
+ cgltf_extras extras;
+ cgltf_size extensions_count;
+ cgltf_extension* extensions;
+} cgltf_skin;
+
+typedef struct cgltf_camera_perspective {
+ cgltf_bool has_aspect_ratio;
+ cgltf_float aspect_ratio;
+ cgltf_float yfov;
+ cgltf_bool has_zfar;
+ cgltf_float zfar;
+ cgltf_float znear;
+ cgltf_extras extras;
+} cgltf_camera_perspective;
+
+typedef struct cgltf_camera_orthographic {
+ cgltf_float xmag;
+ cgltf_float ymag;
+ cgltf_float zfar;
+ cgltf_float znear;
+ cgltf_extras extras;
+} cgltf_camera_orthographic;
+
+typedef struct cgltf_camera {
+ char* name;
+ cgltf_camera_type type;
+ union {
+ cgltf_camera_perspective perspective;
+ cgltf_camera_orthographic orthographic;
+ } data;
+ cgltf_extras extras;
+ cgltf_size extensions_count;
+ cgltf_extension* extensions;
+} cgltf_camera;
+
+typedef struct cgltf_light {
+ char* name;
+ cgltf_float color[3];
+ cgltf_float intensity;
+ cgltf_light_type type;
+ cgltf_float range;
+ cgltf_float spot_inner_cone_angle;
+ cgltf_float spot_outer_cone_angle;
+ cgltf_extras extras;
+} cgltf_light;
+
+struct cgltf_node {
+ char* name;
+ cgltf_node* parent;
+ cgltf_node** children;
+ cgltf_size children_count;
+ cgltf_skin* skin;
+ cgltf_mesh* mesh;
+ cgltf_camera* camera;
+ cgltf_light* light;
+ cgltf_float* weights;
+ cgltf_size weights_count;
+ cgltf_bool has_translation;
+ cgltf_bool has_rotation;
+ cgltf_bool has_scale;
+ cgltf_bool has_matrix;
+ cgltf_float translation[3];
+ cgltf_float rotation[4];
+ cgltf_float scale[3];
+ cgltf_float matrix[16];
+ cgltf_extras extras;
+ cgltf_bool has_mesh_gpu_instancing;
+ cgltf_mesh_gpu_instancing mesh_gpu_instancing;
+ cgltf_size extensions_count;
+ cgltf_extension* extensions;
+};
+
+typedef struct cgltf_scene {
+ char* name;
+ cgltf_node** nodes;
+ cgltf_size nodes_count;
+ cgltf_extras extras;
+ cgltf_size extensions_count;
+ cgltf_extension* extensions;
+} cgltf_scene;
+
+typedef struct cgltf_animation_sampler {
+ cgltf_accessor* input;
+ cgltf_accessor* output;
+ cgltf_interpolation_type interpolation;
+ cgltf_extras extras;
+ cgltf_size extensions_count;
+ cgltf_extension* extensions;
+} cgltf_animation_sampler;
+
+typedef struct cgltf_animation_channel {
+ cgltf_animation_sampler* sampler;
+ cgltf_node* target_node;
+ cgltf_animation_path_type target_path;
+ cgltf_extras extras;
+ cgltf_size extensions_count;
+ cgltf_extension* extensions;
+} cgltf_animation_channel;
+
+typedef struct cgltf_animation {
+ char* name;
+ cgltf_animation_sampler* samplers;
+ cgltf_size samplers_count;
+ cgltf_animation_channel* channels;
+ cgltf_size channels_count;
+ cgltf_extras extras;
+ cgltf_size extensions_count;
+ cgltf_extension* extensions;
+} cgltf_animation;
+
+typedef struct cgltf_material_variant
+{
+ char* name;
+ cgltf_extras extras;
+} cgltf_material_variant;
+
+typedef struct cgltf_asset {
+ char* copyright;
+ char* generator;
+ char* version;
+ char* min_version;
+ cgltf_extras extras;
+ cgltf_size extensions_count;
+ cgltf_extension* extensions;
+} cgltf_asset;
+
+typedef struct cgltf_data
+{
+ cgltf_file_type file_type;
+ void* file_data;
+
+ cgltf_asset asset;
+
+ cgltf_mesh* meshes;
+ cgltf_size meshes_count;
+
+ cgltf_material* materials;
+ cgltf_size materials_count;
+
+ cgltf_accessor* accessors;
+ cgltf_size accessors_count;
+
+ cgltf_buffer_view* buffer_views;
+ cgltf_size buffer_views_count;
+
+ cgltf_buffer* buffers;
+ cgltf_size buffers_count;
+
+ cgltf_image* images;
+ cgltf_size images_count;
+
+ cgltf_texture* textures;
+ cgltf_size textures_count;
+
+ cgltf_sampler* samplers;
+ cgltf_size samplers_count;
+
+ cgltf_skin* skins;
+ cgltf_size skins_count;
+
+ cgltf_camera* cameras;
+ cgltf_size cameras_count;
+
+ cgltf_light* lights;
+ cgltf_size lights_count;
+
+ cgltf_node* nodes;
+ cgltf_size nodes_count;
+
+ cgltf_scene* scenes;
+ cgltf_size scenes_count;
+
+ cgltf_scene* scene;
+
+ cgltf_animation* animations;
+ cgltf_size animations_count;
+
+ cgltf_material_variant* variants;
+ cgltf_size variants_count;
+
+ cgltf_extras extras;
+
+ cgltf_size data_extensions_count;
+ cgltf_extension* data_extensions;
+
+ char** extensions_used;
+ cgltf_size extensions_used_count;
+
+ char** extensions_required;
+ cgltf_size extensions_required_count;
+
+ const char* json;
+ cgltf_size json_size;
+
+ const void* bin;
+ cgltf_size bin_size;
+
+ cgltf_memory_options memory;
+ cgltf_file_options file;
+} cgltf_data;
+
+cgltf_result cgltf_parse(
+ const cgltf_options* options,
+ const void* data,
+ cgltf_size size,
+ cgltf_data** out_data);
+
+cgltf_result cgltf_parse_file(
+ const cgltf_options* options,
+ const char* path,
+ cgltf_data** out_data);
+
+cgltf_result cgltf_load_buffers(
+ const cgltf_options* options,
+ cgltf_data* data,
+ const char* gltf_path);
+
+cgltf_result cgltf_load_buffer_base64(const cgltf_options* options, cgltf_size size, const char* base64, void** out_data);
+
+cgltf_size cgltf_decode_string(char* string);
+cgltf_size cgltf_decode_uri(char* uri);
+
+cgltf_result cgltf_validate(cgltf_data* data);
+
+void cgltf_free(cgltf_data* data);
+
+void cgltf_node_transform_local(const cgltf_node* node, cgltf_float* out_matrix);
+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);
+
+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);
+
+cgltf_size cgltf_num_components(cgltf_type type);
+cgltf_size cgltf_component_size(cgltf_component_type component_type);
+cgltf_size cgltf_calc_size(cgltf_type type, cgltf_component_type component_type);
+
+cgltf_size cgltf_accessor_unpack_floats(const cgltf_accessor* accessor, cgltf_float* out, cgltf_size float_count);
+cgltf_size cgltf_accessor_unpack_indices(const cgltf_accessor* accessor, void* out, cgltf_size out_component_size, cgltf_size index_count);
+
+/* this function is deprecated and will be removed in the future; use cgltf_extras::data instead */
+cgltf_result cgltf_copy_extras_json(const cgltf_data* data, const cgltf_extras* extras, char* dest, cgltf_size* dest_size);
+
+cgltf_size cgltf_mesh_index(const cgltf_data* data, const cgltf_mesh* object);
+cgltf_size cgltf_material_index(const cgltf_data* data, const cgltf_material* object);
+cgltf_size cgltf_accessor_index(const cgltf_data* data, const cgltf_accessor* object);
+cgltf_size cgltf_buffer_view_index(const cgltf_data* data, const cgltf_buffer_view* object);
+cgltf_size cgltf_buffer_index(const cgltf_data* data, const cgltf_buffer* object);
+cgltf_size cgltf_image_index(const cgltf_data* data, const cgltf_image* object);
+cgltf_size cgltf_texture_index(const cgltf_data* data, const cgltf_texture* object);
+cgltf_size cgltf_sampler_index(const cgltf_data* data, const cgltf_sampler* object);
+cgltf_size cgltf_skin_index(const cgltf_data* data, const cgltf_skin* object);
+cgltf_size cgltf_camera_index(const cgltf_data* data, const cgltf_camera* object);
+cgltf_size cgltf_light_index(const cgltf_data* data, const cgltf_light* object);
+cgltf_size cgltf_node_index(const cgltf_data* data, const cgltf_node* object);
+cgltf_size cgltf_scene_index(const cgltf_data* data, const cgltf_scene* object);
+cgltf_size cgltf_animation_index(const cgltf_data* data, const cgltf_animation* object);
+cgltf_size cgltf_animation_sampler_index(const cgltf_animation* animation, const cgltf_animation_sampler* object);
+cgltf_size cgltf_animation_channel_index(const cgltf_animation* animation, const cgltf_animation_channel* object);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* #ifndef CGLTF_H_INCLUDED__ */
+
+/*
+ *
+ * Stop now, if you are only interested in the API.
+ * Below, you find the implementation.
+ *
+ */
+
+#if defined(__INTELLISENSE__) || defined(__JETBRAINS_IDE__)
+/* This makes MSVC/CLion intellisense work. */
+#define CGLTF_IMPLEMENTATION
+#endif
+
+#ifdef CGLTF_IMPLEMENTATION
+
+#include /* For assert */
+#include /* For strncpy */
+#include /* For fopen */
+#include /* For UINT_MAX etc */
+#include /* For FLT_MAX */
+
+#if !defined(CGLTF_MALLOC) || !defined(CGLTF_FREE) || !defined(CGLTF_ATOI) || !defined(CGLTF_ATOF) || !defined(CGLTF_ATOLL)
+#include /* For malloc, free, atoi, atof */
+#endif
+
+/* JSMN_PARENT_LINKS is necessary to make parsing large structures linear in input size */
+#define JSMN_PARENT_LINKS
+
+/* JSMN_STRICT is necessary to reject invalid JSON documents */
+#define JSMN_STRICT
+
+/*
+ * -- jsmn.h start --
+ * Source: https://github.com/zserge/jsmn
+ * License: MIT
+ */
+typedef enum {
+ JSMN_UNDEFINED = 0,
+ JSMN_OBJECT = 1,
+ JSMN_ARRAY = 2,
+ JSMN_STRING = 3,
+ JSMN_PRIMITIVE = 4
+} jsmntype_t;
+enum jsmnerr {
+ /* Not enough tokens were provided */
+ JSMN_ERROR_NOMEM = -1,
+ /* Invalid character inside JSON string */
+ JSMN_ERROR_INVAL = -2,
+ /* The string is not a full JSON packet, more bytes expected */
+ JSMN_ERROR_PART = -3
+};
+typedef struct {
+ jsmntype_t type;
+ ptrdiff_t start;
+ ptrdiff_t end;
+ int size;
+#ifdef JSMN_PARENT_LINKS
+ int parent;
+#endif
+} jsmntok_t;
+typedef struct {
+ size_t pos; /* offset in the JSON string */
+ unsigned int toknext; /* next token to allocate */
+ int toksuper; /* superior token node, e.g parent object or array */
+} jsmn_parser;
+static void jsmn_init(jsmn_parser *parser);
+static int jsmn_parse(jsmn_parser *parser, const char *js, size_t len, jsmntok_t *tokens, size_t num_tokens);
+/*
+ * -- jsmn.h end --
+ */
+
+
+#ifndef CGLTF_CONSTS
+#define GlbHeaderSize 12
+#define GlbChunkHeaderSize 8
+static const uint32_t GlbVersion = 2;
+static const uint32_t GlbMagic = 0x46546C67;
+static const uint32_t GlbMagicJsonChunk = 0x4E4F534A;
+static const uint32_t GlbMagicBinChunk = 0x004E4942;
+#define CGLTF_CONSTS
+#endif
+
+#ifndef CGLTF_MALLOC
+#define CGLTF_MALLOC(size) malloc(size)
+#endif
+#ifndef CGLTF_FREE
+#define CGLTF_FREE(ptr) free(ptr)
+#endif
+#ifndef CGLTF_ATOI
+#define CGLTF_ATOI(str) atoi(str)
+#endif
+#ifndef CGLTF_ATOF
+#define CGLTF_ATOF(str) atof(str)
+#endif
+#ifndef CGLTF_ATOLL
+#define CGLTF_ATOLL(str) atoll(str)
+#endif
+#ifndef CGLTF_VALIDATE_ENABLE_ASSERTS
+#define CGLTF_VALIDATE_ENABLE_ASSERTS 0
+#endif
+
+static void* cgltf_default_alloc(void* user, cgltf_size size)
+{
+ (void)user;
+ return CGLTF_MALLOC(size);
+}
+
+static void cgltf_default_free(void* user, void* ptr)
+{
+ (void)user;
+ CGLTF_FREE(ptr);
+}
+
+static void* cgltf_calloc(cgltf_options* options, size_t element_size, cgltf_size count)
+{
+ if (SIZE_MAX / element_size < count)
+ {
+ return NULL;
+ }
+ void* result = options->memory.alloc_func(options->memory.user_data, element_size * count);
+ if (!result)
+ {
+ return NULL;
+ }
+ memset(result, 0, element_size * count);
+ return result;
+}
+
+static cgltf_result cgltf_default_file_read(const struct cgltf_memory_options* memory_options, const struct cgltf_file_options* file_options, const char* path, cgltf_size* size, void** data)
+{
+ (void)file_options;
+ void* (*memory_alloc)(void*, cgltf_size) = memory_options->alloc_func ? memory_options->alloc_func : &cgltf_default_alloc;
+ void (*memory_free)(void*, void*) = memory_options->free_func ? memory_options->free_func : &cgltf_default_free;
+
+ FILE* file = fopen(path, "rb");
+ if (!file)
+ {
+ return cgltf_result_file_not_found;
+ }
+
+ cgltf_size file_size = size ? *size : 0;
+
+ if (file_size == 0)
+ {
+ fseek(file, 0, SEEK_END);
+
+#ifdef _MSC_VER
+ __int64 length = _ftelli64(file);
+#else
+ long length = ftell(file);
+#endif
+
+ if (length < 0)
+ {
+ fclose(file);
+ return cgltf_result_io_error;
+ }
+
+ fseek(file, 0, SEEK_SET);
+ file_size = (cgltf_size)length;
+ }
+
+ char* file_data = (char*)memory_alloc(memory_options->user_data, file_size);
+ if (!file_data)
+ {
+ fclose(file);
+ return cgltf_result_out_of_memory;
+ }
+
+ cgltf_size read_size = fread(file_data, 1, file_size, file);
+
+ fclose(file);
+
+ if (read_size != file_size)
+ {
+ memory_free(memory_options->user_data, file_data);
+ return cgltf_result_io_error;
+ }
+
+ if (size)
+ {
+ *size = file_size;
+ }
+ if (data)
+ {
+ *data = file_data;
+ }
+
+ 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)
+{
+ (void)file_options;
+ void (*memfree)(void*, void*) = memory_options->free_func ? memory_options->free_func : &cgltf_default_free;
+ memfree(memory_options->user_data, data);
+}
+
+static cgltf_result cgltf_parse_json(cgltf_options* options, const uint8_t* json_chunk, cgltf_size size, cgltf_data** out_data);
+
+cgltf_result cgltf_parse(const cgltf_options* options, const void* data, cgltf_size size, cgltf_data** out_data)
+{
+ if (size < GlbHeaderSize)
+ {
+ return cgltf_result_data_too_short;
+ }
+
+ if (options == NULL)
+ {
+ return cgltf_result_invalid_options;
+ }
+
+ cgltf_options fixed_options = *options;
+ if (fixed_options.memory.alloc_func == NULL)
+ {
+ fixed_options.memory.alloc_func = &cgltf_default_alloc;
+ }
+ if (fixed_options.memory.free_func == NULL)
+ {
+ fixed_options.memory.free_func = &cgltf_default_free;
+ }
+
+ uint32_t tmp;
+ // Magic
+ memcpy(&tmp, data, 4);
+ if (tmp != GlbMagic)
+ {
+ if (fixed_options.type == cgltf_file_type_invalid)
+ {
+ fixed_options.type = cgltf_file_type_gltf;
+ }
+ else if (fixed_options.type == cgltf_file_type_glb)
+ {
+ return cgltf_result_unknown_format;
+ }
+ }
+
+ if (fixed_options.type == cgltf_file_type_gltf)
+ {
+ cgltf_result json_result = cgltf_parse_json(&fixed_options, (const uint8_t*)data, size, out_data);
+ if (json_result != cgltf_result_success)
+ {
+ return json_result;
+ }
+
+ (*out_data)->file_type = cgltf_file_type_gltf;
+
+ return cgltf_result_success;
+ }
+
+ const uint8_t* ptr = (const uint8_t*)data;
+ // Version
+ memcpy(&tmp, ptr + 4, 4);
+ uint32_t version = tmp;
+ if (version != GlbVersion)
+ {
+ return version < GlbVersion ? cgltf_result_legacy_gltf : cgltf_result_unknown_format;
+ }
+
+ // Total length
+ memcpy(&tmp, ptr + 8, 4);
+ if (tmp > size)
+ {
+ return cgltf_result_data_too_short;
+ }
+
+ const uint8_t* json_chunk = ptr + GlbHeaderSize;
+
+ if (GlbHeaderSize + GlbChunkHeaderSize > size)
+ {
+ return cgltf_result_data_too_short;
+ }
+
+ // JSON chunk: length
+ uint32_t json_length;
+ memcpy(&json_length, json_chunk, 4);
+ if (json_length > size - GlbHeaderSize - GlbChunkHeaderSize)
+ {
+ return cgltf_result_data_too_short;
+ }
+
+ // JSON chunk: magic
+ memcpy(&tmp, json_chunk + 4, 4);
+ if (tmp != GlbMagicJsonChunk)
+ {
+ return cgltf_result_unknown_format;
+ }
+
+ json_chunk += GlbChunkHeaderSize;
+
+ const void* bin = NULL;
+ cgltf_size bin_size = 0;
+
+ if (GlbChunkHeaderSize <= size - GlbHeaderSize - GlbChunkHeaderSize - json_length)
+ {
+ // We can read another chunk
+ const uint8_t* bin_chunk = json_chunk + json_length;
+
+ // Bin chunk: length
+ uint32_t bin_length;
+ memcpy(&bin_length, bin_chunk, 4);
+ if (bin_length > size - GlbHeaderSize - GlbChunkHeaderSize - json_length - GlbChunkHeaderSize)
+ {
+ return cgltf_result_data_too_short;
+ }
+
+ // Bin chunk: magic
+ memcpy(&tmp, bin_chunk + 4, 4);
+ if (tmp != GlbMagicBinChunk)
+ {
+ return cgltf_result_unknown_format;
+ }
+
+ bin_chunk += GlbChunkHeaderSize;
+
+ bin = bin_chunk;
+ bin_size = bin_length;
+ }
+
+ cgltf_result json_result = cgltf_parse_json(&fixed_options, json_chunk, json_length, out_data);
+ if (json_result != cgltf_result_success)
+ {
+ return json_result;
+ }
+
+ (*out_data)->file_type = cgltf_file_type_glb;
+ (*out_data)->bin = bin;
+ (*out_data)->bin_size = bin_size;
+
+ return cgltf_result_success;
+}
+
+cgltf_result cgltf_parse_file(const cgltf_options* options, const char* path, cgltf_data** out_data)
+{
+ if (options == NULL)
+ {
+ return cgltf_result_invalid_options;
+ }
+
+ 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_data = NULL;
+ cgltf_size file_size = 0;
+ cgltf_result result = file_read(&options->memory, &options->file, path, &file_size, &file_data);
+ if (result != cgltf_result_success)
+ {
+ return result;
+ }
+
+ result = cgltf_parse(options, file_data, file_size, out_data);
+
+ if (result != cgltf_result_success)
+ {
+ file_release(&options->memory, &options->file, file_data);
+ return result;
+ }
+
+ (*out_data)->file_data = file_data;
+
+ return cgltf_result_success;
+}
+
+static void cgltf_combine_paths(char* path, const char* base, const char* uri)
+{
+ const char* s0 = strrchr(base, '/');
+ const char* s1 = strrchr(base, '\\');
+ const char* slash = s0 ? (s1 && s1 > s0 ? s1 : s0) : s1;
+
+ if (slash)
+ {
+ size_t prefix = slash - base + 1;
+
+ strncpy(path, base, prefix);
+ strcpy(path + prefix, uri);
+ }
+ else
+ {
+ strcpy(path, uri);
+ }
+}
+
+static cgltf_result cgltf_load_buffer_file(const cgltf_options* options, cgltf_size size, const char* uri, const char* gltf_path, void** out_data)
+{
+ void* (*memory_alloc)(void*, cgltf_size) = options->memory.alloc_func ? options->memory.alloc_func : &cgltf_default_alloc;
+ void (*memory_free)(void*, void*) = options->memory.free_func ? options->memory.free_func : &cgltf_default_free;
+ 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;
+
+ char* path = (char*)memory_alloc(options->memory.user_data, strlen(uri) + strlen(gltf_path) + 1);
+ if (!path)
+ {
+ return cgltf_result_out_of_memory;
+ }
+
+ cgltf_combine_paths(path, gltf_path, uri);
+
+ // after combining, the tail of the resulting path is a uri; decode_uri converts it into path
+ cgltf_decode_uri(path + strlen(path) - strlen(uri));
+
+ void* file_data = NULL;
+ cgltf_result result = file_read(&options->memory, &options->file, path, &size, &file_data);
+
+ memory_free(options->memory.user_data, path);
+
+ *out_data = (result == cgltf_result_success) ? file_data : NULL;
+
+ return result;
+}
+
+cgltf_result cgltf_load_buffer_base64(const cgltf_options* options, cgltf_size size, const char* base64, void** out_data)
+{
+ void* (*memory_alloc)(void*, cgltf_size) = options->memory.alloc_func ? options->memory.alloc_func : &cgltf_default_alloc;
+ void (*memory_free)(void*, void*) = options->memory.free_func ? options->memory.free_func : &cgltf_default_free;
+
+ unsigned char* data = (unsigned char*)memory_alloc(options->memory.user_data, size);
+ if (!data)
+ {
+ return cgltf_result_out_of_memory;
+ }
+
+ unsigned int buffer = 0;
+ unsigned int buffer_bits = 0;
+
+ for (cgltf_size i = 0; i < size; ++i)
+ {
+ while (buffer_bits < 8)
+ {
+ char ch = *base64++;
+
+ int index =
+ (unsigned)(ch - 'A') < 26 ? (ch - 'A') :
+ (unsigned)(ch - 'a') < 26 ? (ch - 'a') + 26 :
+ (unsigned)(ch - '0') < 10 ? (ch - '0') + 52 :
+ ch == '+' ? 62 :
+ ch == '/' ? 63 :
+ -1;
+
+ if (index < 0)
+ {
+ memory_free(options->memory.user_data, data);
+ return cgltf_result_io_error;
+ }
+
+ buffer = (buffer << 6) | index;
+ buffer_bits += 6;
+ }
+
+ data[i] = (unsigned char)(buffer >> (buffer_bits - 8));
+ buffer_bits -= 8;
+ }
+
+ *out_data = data;
+
+ return cgltf_result_success;
+}
+
+static int cgltf_unhex(char ch)
+{
+ return
+ (unsigned)(ch - '0') < 10 ? (ch - '0') :
+ (unsigned)(ch - 'A') < 6 ? (ch - 'A') + 10 :
+ (unsigned)(ch - 'a') < 6 ? (ch - 'a') + 10 :
+ -1;
+}
+
+cgltf_size cgltf_decode_string(char* string)
+{
+ char* read = string + strcspn(string, "\\");
+ if (*read == 0)
+ {
+ return read - string;
+ }
+ char* write = string;
+ char* last = string;
+
+ for (;;)
+ {
+ // Copy characters since last escaped sequence
+ cgltf_size written = read - last;
+ memmove(write, last, written);
+ write += written;
+
+ if (*read++ == 0)
+ {
+ break;
+ }
+
+ // jsmn already checked that all escape sequences are valid
+ switch (*read++)
+ {
+ case '\"': *write++ = '\"'; break;
+ case '/': *write++ = '/'; break;
+ case '\\': *write++ = '\\'; break;
+ case 'b': *write++ = '\b'; break;
+ case 'f': *write++ = '\f'; break;
+ case 'r': *write++ = '\r'; break;
+ case 'n': *write++ = '\n'; break;
+ case 't': *write++ = '\t'; break;
+ case 'u':
+ {
+ // UCS-2 codepoint \uXXXX to UTF-8
+ int character = 0;
+ for (cgltf_size i = 0; i < 4; ++i)
+ {
+ character = (character << 4) + cgltf_unhex(*read++);
+ }
+
+ if (character <= 0x7F)
+ {
+ *write++ = character & 0xFF;
+ }
+ else if (character <= 0x7FF)
+ {
+ *write++ = 0xC0 | ((character >> 6) & 0xFF);
+ *write++ = 0x80 | (character & 0x3F);
+ }
+ else
+ {
+ *write++ = 0xE0 | ((character >> 12) & 0xFF);
+ *write++ = 0x80 | ((character >> 6) & 0x3F);
+ *write++ = 0x80 | (character & 0x3F);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+
+ last = read;
+ read += strcspn(read, "\\");
+ }
+
+ *write = 0;
+ return write - string;
+}
+
+cgltf_size cgltf_decode_uri(char* uri)
+{
+ char* write = uri;
+ char* i = uri;
+
+ while (*i)
+ {
+ if (*i == '%')
+ {
+ int ch1 = cgltf_unhex(i[1]);
+
+ if (ch1 >= 0)
+ {
+ int ch2 = cgltf_unhex(i[2]);
+
+ if (ch2 >= 0)
+ {
+ *write++ = (char)(ch1 * 16 + ch2);
+ i += 3;
+ continue;
+ }
+ }
+ }
+
+ *write++ = *i++;
+ }
+
+ *write = 0;
+ return write - uri;
+}
+
+cgltf_result cgltf_load_buffers(const cgltf_options* options, cgltf_data* data, const char* gltf_path)
+{
+ if (options == NULL)
+ {
+ return cgltf_result_invalid_options;
+ }
+
+ if (data->buffers_count && data->buffers[0].data == NULL && data->buffers[0].uri == NULL && data->bin)
+ {
+ if (data->bin_size < data->buffers[0].size)
+ {
+ return cgltf_result_data_too_short;
+ }
+
+ data->buffers[0].data = (void*)data->bin;
+ data->buffers[0].data_free_method = cgltf_data_free_method_none;
+ }
+
+ for (cgltf_size i = 0; i < data->buffers_count; ++i)
+ {
+ if (data->buffers[i].data)
+ {
+ continue;
+ }
+
+ const char* uri = data->buffers[i].uri;
+
+ if (uri == NULL)
+ {
+ continue;
+ }
+
+ if (strncmp(uri, "data:", 5) == 0)
+ {
+ const char* comma = strchr(uri, ',');
+
+ if (comma && comma - uri >= 7 && strncmp(comma - 7, ";base64", 7) == 0)
+ {
+ cgltf_result res = cgltf_load_buffer_base64(options, data->buffers[i].size, comma + 1, &data->buffers[i].data);
+ data->buffers[i].data_free_method = cgltf_data_free_method_memory_free;
+
+ if (res != cgltf_result_success)
+ {
+ return res;
+ }
+ }
+ else
+ {
+ return cgltf_result_unknown_format;
+ }
+ }
+ else if (strstr(uri, "://") == NULL && gltf_path)
+ {
+ cgltf_result res = cgltf_load_buffer_file(options, data->buffers[i].size, uri, gltf_path, &data->buffers[i].data);
+ data->buffers[i].data_free_method = cgltf_data_free_method_file_release;
+
+ if (res != cgltf_result_success)
+ {
+ return res;
+ }
+ }
+ else
+ {
+ return cgltf_result_unknown_format;
+ }
+ }
+
+ return cgltf_result_success;
+}
+
+static cgltf_size cgltf_calc_index_bound(cgltf_buffer_view* buffer_view, cgltf_size offset, cgltf_component_type component_type, cgltf_size count)
+{
+ char* data = (char*)buffer_view->buffer->data + offset + buffer_view->offset;
+ cgltf_size bound = 0;
+
+ switch (component_type)
+ {
+ case cgltf_component_type_r_8u:
+ for (size_t i = 0; i < count; ++i)
+ {
+ cgltf_size v = ((unsigned char*)data)[i];
+ bound = bound > v ? bound : v;
+ }
+ break;
+
+ case cgltf_component_type_r_16u:
+ for (size_t i = 0; i < count; ++i)
+ {
+ cgltf_size v = ((unsigned short*)data)[i];
+ bound = bound > v ? bound : v;
+ }
+ break;
+
+ case cgltf_component_type_r_32u:
+ for (size_t i = 0; i < count; ++i)
+ {
+ cgltf_size v = ((unsigned int*)data)[i];
+ bound = bound > v ? bound : v;
+ }
+ break;
+
+ default:
+ ;
+ }
+
+ return bound;
+}
+
+#if CGLTF_VALIDATE_ENABLE_ASSERTS
+#define CGLTF_ASSERT_IF(cond, result) assert(!(cond)); if (cond) return result;
+#else
+#define CGLTF_ASSERT_IF(cond, result) if (cond) return result;
+#endif
+
+cgltf_result cgltf_validate(cgltf_data* data)
+{
+ for (cgltf_size i = 0; i < data->accessors_count; ++i)
+ {
+ cgltf_accessor* accessor = &data->accessors[i];
+
+ CGLTF_ASSERT_IF(data->accessors[i].component_type == cgltf_component_type_invalid, cgltf_result_invalid_gltf);
+ CGLTF_ASSERT_IF(data->accessors[i].type == cgltf_type_invalid, cgltf_result_invalid_gltf);
+
+ cgltf_size element_size = cgltf_calc_size(accessor->type, accessor->component_type);
+
+ if (accessor->buffer_view)
+ {
+ cgltf_size req_size = accessor->offset + accessor->stride * (accessor->count - 1) + element_size;
+
+ CGLTF_ASSERT_IF(accessor->buffer_view->size < req_size, cgltf_result_data_too_short);
+ }
+
+ if (accessor->is_sparse)
+ {
+ cgltf_accessor_sparse* sparse = &accessor->sparse;
+
+ cgltf_size indices_component_size = cgltf_component_size(sparse->indices_component_type);
+ cgltf_size indices_req_size = sparse->indices_byte_offset + indices_component_size * sparse->count;
+ cgltf_size values_req_size = sparse->values_byte_offset + element_size * sparse->count;
+
+ CGLTF_ASSERT_IF(sparse->indices_buffer_view->size < indices_req_size ||
+ sparse->values_buffer_view->size < values_req_size, cgltf_result_data_too_short);
+
+ CGLTF_ASSERT_IF(sparse->indices_component_type != cgltf_component_type_r_8u &&
+ sparse->indices_component_type != cgltf_component_type_r_16u &&
+ sparse->indices_component_type != cgltf_component_type_r_32u, cgltf_result_invalid_gltf);
+
+ if (sparse->indices_buffer_view->buffer->data)
+ {
+ cgltf_size index_bound = cgltf_calc_index_bound(sparse->indices_buffer_view, sparse->indices_byte_offset, sparse->indices_component_type, sparse->count);
+
+ CGLTF_ASSERT_IF(index_bound >= accessor->count, cgltf_result_data_too_short);
+ }
+ }
+ }
+
+ for (cgltf_size i = 0; i < data->buffer_views_count; ++i)
+ {
+ cgltf_size req_size = data->buffer_views[i].offset + data->buffer_views[i].size;
+
+ CGLTF_ASSERT_IF(data->buffer_views[i].buffer && data->buffer_views[i].buffer->size < req_size, cgltf_result_data_too_short);
+
+ if (data->buffer_views[i].has_meshopt_compression)
+ {
+ cgltf_meshopt_compression* mc = &data->buffer_views[i].meshopt_compression;
+
+ CGLTF_ASSERT_IF(mc->buffer == NULL || mc->buffer->size < mc->offset + mc->size, cgltf_result_data_too_short);
+
+ CGLTF_ASSERT_IF(data->buffer_views[i].stride && mc->stride != data->buffer_views[i].stride, cgltf_result_invalid_gltf);
+
+ CGLTF_ASSERT_IF(data->buffer_views[i].size != mc->stride * mc->count, cgltf_result_invalid_gltf);
+
+ CGLTF_ASSERT_IF(mc->mode == cgltf_meshopt_compression_mode_invalid, cgltf_result_invalid_gltf);
+
+ CGLTF_ASSERT_IF(mc->mode == cgltf_meshopt_compression_mode_attributes && !(mc->stride % 4 == 0 && mc->stride <= 256), cgltf_result_invalid_gltf);
+
+ CGLTF_ASSERT_IF(mc->mode == cgltf_meshopt_compression_mode_triangles && mc->count % 3 != 0, cgltf_result_invalid_gltf);
+
+ CGLTF_ASSERT_IF((mc->mode == cgltf_meshopt_compression_mode_triangles || mc->mode == cgltf_meshopt_compression_mode_indices) && mc->stride != 2 && mc->stride != 4, cgltf_result_invalid_gltf);
+
+ 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);
+ }
+ }
+
+ for (cgltf_size i = 0; i < data->meshes_count; ++i)
+ {
+ if (data->meshes[i].weights)
+ {
+ CGLTF_ASSERT_IF(data->meshes[i].primitives_count && data->meshes[i].primitives[0].targets_count != data->meshes[i].weights_count, cgltf_result_invalid_gltf);
+ }
+
+ if (data->meshes[i].target_names)
+ {
+ CGLTF_ASSERT_IF(data->meshes[i].primitives_count && data->meshes[i].primitives[0].targets_count != data->meshes[i].target_names_count, cgltf_result_invalid_gltf);
+ }
+
+ for (cgltf_size j = 0; j < data->meshes[i].primitives_count; ++j)
+ {
+ CGLTF_ASSERT_IF(data->meshes[i].primitives[j].type == cgltf_primitive_type_invalid, cgltf_result_invalid_gltf);
+ CGLTF_ASSERT_IF(data->meshes[i].primitives[j].targets_count != data->meshes[i].primitives[0].targets_count, cgltf_result_invalid_gltf);
+
+ CGLTF_ASSERT_IF(data->meshes[i].primitives[j].attributes_count == 0, cgltf_result_invalid_gltf);
+
+ cgltf_accessor* first = data->meshes[i].primitives[j].attributes[0].data;
+
+ CGLTF_ASSERT_IF(first->count == 0, cgltf_result_invalid_gltf);
+
+ for (cgltf_size k = 0; k < data->meshes[i].primitives[j].attributes_count; ++k)
+ {
+ CGLTF_ASSERT_IF(data->meshes[i].primitives[j].attributes[k].data->count != first->count, cgltf_result_invalid_gltf);
+ }
+
+ for (cgltf_size k = 0; k < data->meshes[i].primitives[j].targets_count; ++k)
+ {
+ for (cgltf_size m = 0; m < data->meshes[i].primitives[j].targets[k].attributes_count; ++m)
+ {
+ CGLTF_ASSERT_IF(data->meshes[i].primitives[j].targets[k].attributes[m].data->count != first->count, cgltf_result_invalid_gltf);
+ }
+ }
+
+ cgltf_accessor* indices = data->meshes[i].primitives[j].indices;
+
+ CGLTF_ASSERT_IF(indices &&
+ indices->component_type != cgltf_component_type_r_8u &&
+ indices->component_type != cgltf_component_type_r_16u &&
+ indices->component_type != cgltf_component_type_r_32u, cgltf_result_invalid_gltf);
+
+ CGLTF_ASSERT_IF(indices && indices->type != cgltf_type_scalar, cgltf_result_invalid_gltf);
+ CGLTF_ASSERT_IF(indices && indices->stride != cgltf_component_size(indices->component_type), cgltf_result_invalid_gltf);
+
+ if (indices && indices->buffer_view && indices->buffer_view->buffer->data)
+ {
+ cgltf_size index_bound = cgltf_calc_index_bound(indices->buffer_view, indices->offset, indices->component_type, indices->count);
+
+ CGLTF_ASSERT_IF(index_bound >= first->count, cgltf_result_data_too_short);
+ }
+
+ for (cgltf_size k = 0; k < data->meshes[i].primitives[j].mappings_count; ++k)
+ {
+ CGLTF_ASSERT_IF(data->meshes[i].primitives[j].mappings[k].variant >= data->variants_count, cgltf_result_invalid_gltf);
+ }
+ }
+ }
+
+ for (cgltf_size i = 0; i < data->nodes_count; ++i)
+ {
+ if (data->nodes[i].weights && data->nodes[i].mesh)
+ {
+ CGLTF_ASSERT_IF(data->nodes[i].mesh->primitives_count && data->nodes[i].mesh->primitives[0].targets_count != data->nodes[i].weights_count, cgltf_result_invalid_gltf);
+ }
+
+ if (data->nodes[i].has_mesh_gpu_instancing)
+ {
+ CGLTF_ASSERT_IF(data->nodes[i].mesh == NULL, cgltf_result_invalid_gltf);
+ CGLTF_ASSERT_IF(data->nodes[i].mesh_gpu_instancing.attributes_count == 0, cgltf_result_invalid_gltf);
+
+ cgltf_accessor* first = data->nodes[i].mesh_gpu_instancing.attributes[0].data;
+
+ for (cgltf_size k = 0; k < data->nodes[i].mesh_gpu_instancing.attributes_count; ++k)
+ {
+ CGLTF_ASSERT_IF(data->nodes[i].mesh_gpu_instancing.attributes[k].data->count != first->count, cgltf_result_invalid_gltf);
+ }
+ }
+ }
+
+ for (cgltf_size i = 0; i < data->nodes_count; ++i)
+ {
+ cgltf_node* p1 = data->nodes[i].parent;
+ cgltf_node* p2 = p1 ? p1->parent : NULL;
+
+ while (p1 && p2)
+ {
+ CGLTF_ASSERT_IF(p1 == p2, cgltf_result_invalid_gltf);
+
+ p1 = p1->parent;
+ p2 = p2->parent ? p2->parent->parent : NULL;
+ }
+ }
+
+ for (cgltf_size i = 0; i < data->scenes_count; ++i)
+ {
+ for (cgltf_size j = 0; j < data->scenes[i].nodes_count; ++j)
+ {
+ CGLTF_ASSERT_IF(data->scenes[i].nodes[j]->parent, cgltf_result_invalid_gltf);
+ }
+ }
+
+ for (cgltf_size i = 0; i < data->animations_count; ++i)
+ {
+ for (cgltf_size j = 0; j < data->animations[i].channels_count; ++j)
+ {
+ cgltf_animation_channel* channel = &data->animations[i].channels[j];
+
+ if (!channel->target_node)
+ {
+ continue;
+ }
+
+ cgltf_size components = 1;
+
+ if (channel->target_path == cgltf_animation_path_type_weights)
+ {
+ CGLTF_ASSERT_IF(!channel->target_node->mesh || !channel->target_node->mesh->primitives_count, cgltf_result_invalid_gltf);
+
+ components = channel->target_node->mesh->primitives[0].targets_count;
+ }
+
+ cgltf_size values = channel->sampler->interpolation == cgltf_interpolation_type_cubic_spline ? 3 : 1;
+
+ CGLTF_ASSERT_IF(channel->sampler->input->count * components * values != channel->sampler->output->count, cgltf_result_invalid_gltf);
+ }
+ }
+
+ for (cgltf_size i = 0; i < data->variants_count; ++i)
+ {
+ CGLTF_ASSERT_IF(!data->variants[i].name, cgltf_result_invalid_gltf);
+ }
+
+ return cgltf_result_success;
+}
+
+cgltf_result cgltf_copy_extras_json(const cgltf_data* data, const cgltf_extras* extras, char* dest, cgltf_size* dest_size)
+{
+ cgltf_size json_size = extras->end_offset - extras->start_offset;
+
+ if (!dest)
+ {
+ if (dest_size)
+ {
+ *dest_size = json_size + 1;
+ return cgltf_result_success;
+ }
+ return cgltf_result_invalid_options;
+ }
+
+ if (*dest_size + 1 < json_size)
+ {
+ strncpy(dest, data->json + extras->start_offset, *dest_size - 1);
+ dest[*dest_size - 1] = 0;
+ }
+ else
+ {
+ strncpy(dest, data->json + extras->start_offset, json_size);
+ dest[json_size] = 0;
+ }
+
+ return cgltf_result_success;
+}
+
+static void cgltf_free_extras(cgltf_data* data, cgltf_extras* extras)
+{
+ data->memory.free_func(data->memory.user_data, extras->data);
+}
+
+static void cgltf_free_extensions(cgltf_data* data, cgltf_extension* extensions, cgltf_size extensions_count)
+{
+ for (cgltf_size i = 0; i < extensions_count; ++i)
+ {
+ data->memory.free_func(data->memory.user_data, extensions[i].name);
+ data->memory.free_func(data->memory.user_data, extensions[i].data);
+ }
+ data->memory.free_func(data->memory.user_data, extensions);
+}
+
+void cgltf_free(cgltf_data* data)
+{
+ if (!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;
+
+ data->memory.free_func(data->memory.user_data, data->asset.copyright);
+ data->memory.free_func(data->memory.user_data, data->asset.generator);
+ data->memory.free_func(data->memory.user_data, data->asset.version);
+ data->memory.free_func(data->memory.user_data, data->asset.min_version);
+
+ cgltf_free_extensions(data, data->asset.extensions, data->asset.extensions_count);
+ cgltf_free_extras(data, &data->asset.extras);
+
+ for (cgltf_size i = 0; i < data->accessors_count; ++i)
+ {
+ data->memory.free_func(data->memory.user_data, data->accessors[i].name);
+
+ cgltf_free_extensions(data, data->accessors[i].extensions, data->accessors[i].extensions_count);
+ cgltf_free_extras(data, &data->accessors[i].extras);
+ }
+ data->memory.free_func(data->memory.user_data, data->accessors);
+
+ for (cgltf_size i = 0; i < data->buffer_views_count; ++i)
+ {
+ data->memory.free_func(data->memory.user_data, data->buffer_views[i].name);
+ data->memory.free_func(data->memory.user_data, data->buffer_views[i].data);
+
+ cgltf_free_extensions(data, data->buffer_views[i].extensions, data->buffer_views[i].extensions_count);
+ cgltf_free_extras(data, &data->buffer_views[i].extras);
+ }
+ data->memory.free_func(data->memory.user_data, data->buffer_views);
+
+ for (cgltf_size i = 0; i < data->buffers_count; ++i)
+ {
+ data->memory.free_func(data->memory.user_data, data->buffers[i].name);
+
+ if (data->buffers[i].data_free_method == cgltf_data_free_method_file_release)
+ {
+ file_release(&data->memory, &data->file, data->buffers[i].data);
+ }
+ else if (data->buffers[i].data_free_method == cgltf_data_free_method_memory_free)
+ {
+ data->memory.free_func(data->memory.user_data, data->buffers[i].data);
+ }
+
+ data->memory.free_func(data->memory.user_data, data->buffers[i].uri);
+
+ cgltf_free_extensions(data, data->buffers[i].extensions, data->buffers[i].extensions_count);
+ cgltf_free_extras(data, &data->buffers[i].extras);
+ }
+ data->memory.free_func(data->memory.user_data, data->buffers);
+
+ for (cgltf_size i = 0; i < data->meshes_count; ++i)
+ {
+ data->memory.free_func(data->memory.user_data, data->meshes[i].name);
+
+ for (cgltf_size j = 0; j < data->meshes[i].primitives_count; ++j)
+ {
+ for (cgltf_size k = 0; k < data->meshes[i].primitives[j].attributes_count; ++k)
+ {
+ data->memory.free_func(data->memory.user_data, data->meshes[i].primitives[j].attributes[k].name);
+ }
+
+ data->memory.free_func(data->memory.user_data, data->meshes[i].primitives[j].attributes);
+
+ for (cgltf_size k = 0; k < data->meshes[i].primitives[j].targets_count; ++k)
+ {
+ for (cgltf_size m = 0; m < data->meshes[i].primitives[j].targets[k].attributes_count; ++m)
+ {
+ data->memory.free_func(data->memory.user_data, data->meshes[i].primitives[j].targets[k].attributes[m].name);
+ }
+
+ data->memory.free_func(data->memory.user_data, data->meshes[i].primitives[j].targets[k].attributes);
+ }
+
+ data->memory.free_func(data->memory.user_data, data->meshes[i].primitives[j].targets);
+
+ if (data->meshes[i].primitives[j].has_draco_mesh_compression)
+ {
+ for (cgltf_size k = 0; k < data->meshes[i].primitives[j].draco_mesh_compression.attributes_count; ++k)
+ {
+ data->memory.free_func(data->memory.user_data, data->meshes[i].primitives[j].draco_mesh_compression.attributes[k].name);
+ }
+
+ data->memory.free_func(data->memory.user_data, data->meshes[i].primitives[j].draco_mesh_compression.attributes);
+ }
+
+ for (cgltf_size k = 0; k < data->meshes[i].primitives[j].mappings_count; ++k)
+ {
+ cgltf_free_extras(data, &data->meshes[i].primitives[j].mappings[k].extras);
+ }
+
+ data->memory.free_func(data->memory.user_data, data->meshes[i].primitives[j].mappings);
+
+ cgltf_free_extensions(data, data->meshes[i].primitives[j].extensions, data->meshes[i].primitives[j].extensions_count);
+ cgltf_free_extras(data, &data->meshes[i].primitives[j].extras);
+ }
+
+ data->memory.free_func(data->memory.user_data, data->meshes[i].primitives);
+ data->memory.free_func(data->memory.user_data, data->meshes[i].weights);
+
+ for (cgltf_size j = 0; j < data->meshes[i].target_names_count; ++j)
+ {
+ data->memory.free_func(data->memory.user_data, data->meshes[i].target_names[j]);
+ }
+
+ cgltf_free_extensions(data, data->meshes[i].extensions, data->meshes[i].extensions_count);
+ cgltf_free_extras(data, &data->meshes[i].extras);
+
+ data->memory.free_func(data->memory.user_data, data->meshes[i].target_names);
+ }
+
+ data->memory.free_func(data->memory.user_data, data->meshes);
+
+ for (cgltf_size i = 0; i < data->materials_count; ++i)
+ {
+ data->memory.free_func(data->memory.user_data, data->materials[i].name);
+
+ cgltf_free_extensions(data, data->materials[i].extensions, data->materials[i].extensions_count);
+ cgltf_free_extras(data, &data->materials[i].extras);
+ }
+
+ data->memory.free_func(data->memory.user_data, data->materials);
+
+ for (cgltf_size i = 0; i < data->images_count; ++i)
+ {
+ data->memory.free_func(data->memory.user_data, data->images[i].name);
+ data->memory.free_func(data->memory.user_data, data->images[i].uri);
+ data->memory.free_func(data->memory.user_data, data->images[i].mime_type);
+
+ cgltf_free_extensions(data, data->images[i].extensions, data->images[i].extensions_count);
+ cgltf_free_extras(data, &data->images[i].extras);
+ }
+
+ data->memory.free_func(data->memory.user_data, data->images);
+
+ for (cgltf_size i = 0; i < data->textures_count; ++i)
+ {
+ data->memory.free_func(data->memory.user_data, data->textures[i].name);
+
+ cgltf_free_extensions(data, data->textures[i].extensions, data->textures[i].extensions_count);
+ cgltf_free_extras(data, &data->textures[i].extras);
+ }
+
+ data->memory.free_func(data->memory.user_data, data->textures);
+
+ for (cgltf_size i = 0; i < data->samplers_count; ++i)
+ {
+ data->memory.free_func(data->memory.user_data, data->samplers[i].name);
+
+ cgltf_free_extensions(data, data->samplers[i].extensions, data->samplers[i].extensions_count);
+ cgltf_free_extras(data, &data->samplers[i].extras);
+ }
+
+ data->memory.free_func(data->memory.user_data, data->samplers);
+
+ for (cgltf_size i = 0; i < data->skins_count; ++i)
+ {
+ data->memory.free_func(data->memory.user_data, data->skins[i].name);
+ data->memory.free_func(data->memory.user_data, data->skins[i].joints);
+
+ cgltf_free_extensions(data, data->skins[i].extensions, data->skins[i].extensions_count);
+ cgltf_free_extras(data, &data->skins[i].extras);
+ }
+
+ data->memory.free_func(data->memory.user_data, data->skins);
+
+ for (cgltf_size i = 0; i < data->cameras_count; ++i)
+ {
+ data->memory.free_func(data->memory.user_data, data->cameras[i].name);
+
+ if (data->cameras[i].type == cgltf_camera_type_perspective)
+ {
+ cgltf_free_extras(data, &data->cameras[i].data.perspective.extras);
+ }
+ else if (data->cameras[i].type == cgltf_camera_type_orthographic)
+ {
+ cgltf_free_extras(data, &data->cameras[i].data.orthographic.extras);
+ }
+
+ cgltf_free_extensions(data, data->cameras[i].extensions, data->cameras[i].extensions_count);
+ cgltf_free_extras(data, &data->cameras[i].extras);
+ }
+
+ data->memory.free_func(data->memory.user_data, data->cameras);
+
+ for (cgltf_size i = 0; i < data->lights_count; ++i)
+ {
+ data->memory.free_func(data->memory.user_data, data->lights[i].name);
+
+ cgltf_free_extras(data, &data->lights[i].extras);
+ }
+
+ data->memory.free_func(data->memory.user_data, data->lights);
+
+ for (cgltf_size i = 0; i < data->nodes_count; ++i)
+ {
+ data->memory.free_func(data->memory.user_data, data->nodes[i].name);
+ data->memory.free_func(data->memory.user_data, data->nodes[i].children);
+ data->memory.free_func(data->memory.user_data, data->nodes[i].weights);
+
+ if (data->nodes[i].has_mesh_gpu_instancing)
+ {
+ for (cgltf_size j = 0; j < data->nodes[i].mesh_gpu_instancing.attributes_count; ++j)
+ {
+ data->memory.free_func(data->memory.user_data, data->nodes[i].mesh_gpu_instancing.attributes[j].name);
+ }
+
+ data->memory.free_func(data->memory.user_data, data->nodes[i].mesh_gpu_instancing.attributes);
+ }
+
+ cgltf_free_extensions(data, data->nodes[i].extensions, data->nodes[i].extensions_count);
+ cgltf_free_extras(data, &data->nodes[i].extras);
+ }
+
+ data->memory.free_func(data->memory.user_data, data->nodes);
+
+ for (cgltf_size i = 0; i < data->scenes_count; ++i)
+ {
+ data->memory.free_func(data->memory.user_data, data->scenes[i].name);
+ data->memory.free_func(data->memory.user_data, data->scenes[i].nodes);
+
+ cgltf_free_extensions(data, data->scenes[i].extensions, data->scenes[i].extensions_count);
+ cgltf_free_extras(data, &data->scenes[i].extras);
+ }
+
+ data->memory.free_func(data->memory.user_data, data->scenes);
+
+ for (cgltf_size i = 0; i < data->animations_count; ++i)
+ {
+ data->memory.free_func(data->memory.user_data, data->animations[i].name);
+ for (cgltf_size j = 0; j < data->animations[i].samplers_count; ++j)
+ {
+ cgltf_free_extensions(data, data->animations[i].samplers[j].extensions, data->animations[i].samplers[j].extensions_count);
+ cgltf_free_extras(data, &data->animations[i].samplers[j].extras);
+ }
+ data->memory.free_func(data->memory.user_data, data->animations[i].samplers);
+
+ for (cgltf_size j = 0; j < data->animations[i].channels_count; ++j)
+ {
+ cgltf_free_extensions(data, data->animations[i].channels[j].extensions, data->animations[i].channels[j].extensions_count);
+ cgltf_free_extras(data, &data->animations[i].channels[j].extras);
+ }
+ data->memory.free_func(data->memory.user_data, data->animations[i].channels);
+
+ cgltf_free_extensions(data, data->animations[i].extensions, data->animations[i].extensions_count);
+ cgltf_free_extras(data, &data->animations[i].extras);
+ }
+
+ data->memory.free_func(data->memory.user_data, data->animations);
+
+ for (cgltf_size i = 0; i < data->variants_count; ++i)
+ {
+ data->memory.free_func(data->memory.user_data, data->variants[i].name);
+
+ cgltf_free_extras(data, &data->variants[i].extras);
+ }
+
+ data->memory.free_func(data->memory.user_data, data->variants);
+
+ cgltf_free_extensions(data, data->data_extensions, data->data_extensions_count);
+ cgltf_free_extras(data, &data->extras);
+
+ for (cgltf_size i = 0; i < data->extensions_used_count; ++i)
+ {
+ data->memory.free_func(data->memory.user_data, data->extensions_used[i]);
+ }
+
+ data->memory.free_func(data->memory.user_data, data->extensions_used);
+
+ for (cgltf_size i = 0; i < data->extensions_required_count; ++i)
+ {
+ data->memory.free_func(data->memory.user_data, data->extensions_required[i]);
+ }
+
+ data->memory.free_func(data->memory.user_data, data->extensions_required);
+
+ file_release(&data->memory, &data->file, data->file_data);
+
+ data->memory.free_func(data->memory.user_data, data);
+}
+
+void cgltf_node_transform_local(const cgltf_node* node, cgltf_float* out_matrix)
+{
+ cgltf_float* lm = out_matrix;
+
+ if (node->has_matrix)
+ {
+ memcpy(lm, node->matrix, sizeof(float) * 16);
+ }
+ else
+ {
+ float tx = node->translation[0];
+ float ty = node->translation[1];
+ float tz = node->translation[2];
+
+ float qx = node->rotation[0];
+ float qy = node->rotation[1];
+ float qz = node->rotation[2];
+ float qw = node->rotation[3];
+
+ float sx = node->scale[0];
+ float sy = node->scale[1];
+ float sz = node->scale[2];
+
+ lm[0] = (1 - 2 * qy*qy - 2 * qz*qz) * sx;
+ lm[1] = (2 * qx*qy + 2 * qz*qw) * sx;
+ lm[2] = (2 * qx*qz - 2 * qy*qw) * sx;
+ lm[3] = 0.f;
+
+ lm[4] = (2 * qx*qy - 2 * qz*qw) * sy;
+ lm[5] = (1 - 2 * qx*qx - 2 * qz*qz) * sy;
+ lm[6] = (2 * qy*qz + 2 * qx*qw) * sy;
+ lm[7] = 0.f;
+
+ lm[8] = (2 * qx*qz + 2 * qy*qw) * sz;
+ lm[9] = (2 * qy*qz - 2 * qx*qw) * sz;
+ lm[10] = (1 - 2 * qx*qx - 2 * qy*qy) * sz;
+ lm[11] = 0.f;
+
+ lm[12] = tx;
+ lm[13] = ty;
+ lm[14] = tz;
+ lm[15] = 1.f;
+ }
+}
+
+void cgltf_node_transform_world(const cgltf_node* node, cgltf_float* out_matrix)
+{
+ cgltf_float* lm = out_matrix;
+ cgltf_node_transform_local(node, lm);
+
+ const cgltf_node* parent = node->parent;
+
+ while (parent)
+ {
+ float pm[16];
+ cgltf_node_transform_local(parent, pm);
+
+ for (int i = 0; i < 4; ++i)
+ {
+ float l0 = lm[i * 4 + 0];
+ float l1 = lm[i * 4 + 1];
+ float l2 = lm[i * 4 + 2];
+
+ float r0 = l0 * pm[0] + l1 * pm[4] + l2 * pm[8];
+ float r1 = l0 * pm[1] + l1 * pm[5] + l2 * pm[9];
+ float r2 = l0 * pm[2] + l1 * pm[6] + l2 * pm[10];
+
+ lm[i * 4 + 0] = r0;
+ lm[i * 4 + 1] = r1;
+ lm[i * 4 + 2] = r2;
+ }
+
+ lm[12] += pm[12];
+ lm[13] += pm[13];
+ lm[14] += pm[14];
+
+ parent = parent->parent;
+ }
+}
+
+static cgltf_ssize cgltf_component_read_integer(const void* in, cgltf_component_type component_type)
+{
+ switch (component_type)
+ {
+ case cgltf_component_type_r_16:
+ return *((const int16_t*) in);
+ case cgltf_component_type_r_16u:
+ return *((const uint16_t*) in);
+ case cgltf_component_type_r_32u:
+ return *((const uint32_t*) in);
+ case cgltf_component_type_r_8:
+ return *((const int8_t*) in);
+ case cgltf_component_type_r_8u:
+ return *((const uint8_t*) in);
+ default:
+ return 0;
+ }
+}
+
+static cgltf_size cgltf_component_read_index(const void* in, cgltf_component_type component_type)
+{
+ switch (component_type)
+ {
+ case cgltf_component_type_r_16u:
+ return *((const uint16_t*) in);
+ case cgltf_component_type_r_32u:
+ return *((const uint32_t*) in);
+ case cgltf_component_type_r_8u:
+ return *((const uint8_t*) in);
+ default:
+ return 0;
+ }
+}
+
+static cgltf_float cgltf_component_read_float(const void* in, cgltf_component_type component_type, cgltf_bool normalized)
+{
+ if (component_type == cgltf_component_type_r_32f)
+ {
+ return *((const float*) in);
+ }
+
+ if (normalized)
+ {
+ switch (component_type)
+ {
+ // note: glTF spec doesn't currently define normalized conversions for 32-bit integers
+ case cgltf_component_type_r_16:
+ return *((const int16_t*) in) / (cgltf_float)32767;
+ case cgltf_component_type_r_16u:
+ return *((const uint16_t*) in) / (cgltf_float)65535;
+ case cgltf_component_type_r_8:
+ return *((const int8_t*) in) / (cgltf_float)127;
+ case cgltf_component_type_r_8u:
+ return *((const uint8_t*) in) / (cgltf_float)255;
+ default:
+ return 0;
+ }
+ }
+
+ return (cgltf_float)cgltf_component_read_integer(in, component_type);
+}
+
+static cgltf_bool cgltf_element_read_float(const uint8_t* element, cgltf_type type, cgltf_component_type component_type, cgltf_bool normalized, cgltf_float* out, cgltf_size element_size)
+{
+ cgltf_size num_components = cgltf_num_components(type);
+
+ if (element_size < num_components) {
+ return 0;
+ }
+
+ // There are three special cases for component extraction, see #data-alignment in the 2.0 spec.
+
+ cgltf_size component_size = cgltf_component_size(component_type);
+
+ if (type == cgltf_type_mat2 && component_size == 1)
+ {
+ out[0] = cgltf_component_read_float(element, component_type, normalized);
+ out[1] = cgltf_component_read_float(element + 1, component_type, normalized);
+ out[2] = cgltf_component_read_float(element + 4, component_type, normalized);
+ out[3] = cgltf_component_read_float(element + 5, component_type, normalized);
+ return 1;
+ }
+
+ if (type == cgltf_type_mat3 && component_size == 1)
+ {
+ out[0] = cgltf_component_read_float(element, component_type, normalized);
+ out[1] = cgltf_component_read_float(element + 1, component_type, normalized);
+ out[2] = cgltf_component_read_float(element + 2, component_type, normalized);
+ out[3] = cgltf_component_read_float(element + 4, component_type, normalized);
+ out[4] = cgltf_component_read_float(element + 5, component_type, normalized);
+ out[5] = cgltf_component_read_float(element + 6, component_type, normalized);
+ out[6] = cgltf_component_read_float(element + 8, component_type, normalized);
+ out[7] = cgltf_component_read_float(element + 9, component_type, normalized);
+ out[8] = cgltf_component_read_float(element + 10, component_type, normalized);
+ return 1;
+ }
+
+ if (type == cgltf_type_mat3 && component_size == 2)
+ {
+ out[0] = cgltf_component_read_float(element, component_type, normalized);
+ out[1] = cgltf_component_read_float(element + 2, component_type, normalized);
+ out[2] = cgltf_component_read_float(element + 4, component_type, normalized);
+ out[3] = cgltf_component_read_float(element + 8, component_type, normalized);
+ out[4] = cgltf_component_read_float(element + 10, component_type, normalized);
+ out[5] = cgltf_component_read_float(element + 12, component_type, normalized);
+ out[6] = cgltf_component_read_float(element + 16, component_type, normalized);
+ out[7] = cgltf_component_read_float(element + 18, component_type, normalized);
+ out[8] = cgltf_component_read_float(element + 20, component_type, normalized);
+ return 1;
+ }
+
+ for (cgltf_size i = 0; i < num_components; ++i)
+ {
+ out[i] = cgltf_component_read_float(element + component_size * i, component_type, normalized);
+ }
+ return 1;
+}
+
+const uint8_t* cgltf_buffer_view_data(const cgltf_buffer_view* view)
+{
+ if (view->data)
+ return (const uint8_t*)view->data;
+
+ if (!view->buffer->data)
+ return NULL;
+
+ const uint8_t* result = (const uint8_t*)view->buffer->data;
+ result += view->offset;
+ return result;
+}
+
+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;
+ }
+ if (accessor->buffer_view == NULL)
+ {
+ memset(out, 0, element_size * sizeof(cgltf_float));
+ return 1;
+ }
+ const uint8_t* element = cgltf_buffer_view_data(accessor->buffer_view);
+ if (element == NULL)
+ {
+ return 0;
+ }
+ element += accessor->offset + accessor->stride * index;
+ return cgltf_element_read_float(element, accessor->type, accessor->component_type, accessor->normalized, out, element_size);
+}
+
+cgltf_size cgltf_accessor_unpack_floats(const cgltf_accessor* accessor, cgltf_float* out, cgltf_size float_count)
+{
+ cgltf_size floats_per_element = cgltf_num_components(accessor->type);
+ cgltf_size available_floats = accessor->count * floats_per_element;
+ if (out == NULL)
+ {
+ return available_floats;
+ }
+
+ float_count = available_floats < float_count ? available_floats : float_count;
+ cgltf_size element_count = float_count / floats_per_element;
+
+ // First pass: convert each element in the base accessor.
+ if (accessor->buffer_view == NULL)
+ {
+ memset(out, 0, element_count * floats_per_element * sizeof(cgltf_float));
+ }
+ else
+ {
+ const uint8_t* element = cgltf_buffer_view_data(accessor->buffer_view);
+ if (element == NULL)
+ {
+ return 0;
+ }
+ element += accessor->offset;
+
+ if (accessor->component_type == cgltf_component_type_r_32f && accessor->stride == floats_per_element * sizeof(cgltf_float))
+ {
+ memcpy(out, element, element_count * floats_per_element * sizeof(cgltf_float));
+ }
+ else
+ {
+ cgltf_float* dest = out;
+
+ for (cgltf_size index = 0; index < element_count; index++, dest += floats_per_element, element += accessor->stride)
+ {
+ if (!cgltf_element_read_float(element, accessor->type, accessor->component_type, accessor->normalized, dest, floats_per_element))
+ {
+ return 0;
+ }
+ }
+ }
+ }
+
+ // Second pass: write out each element in the sparse accessor.
+ if (accessor->is_sparse)
+ {
+ const cgltf_accessor_sparse* sparse = &accessor->sparse;
+
+ const uint8_t* index_data = cgltf_buffer_view_data(sparse->indices_buffer_view);
+ const uint8_t* reader_head = cgltf_buffer_view_data(sparse->values_buffer_view);
+
+ if (index_data == NULL || reader_head == NULL)
+ {
+ return 0;
+ }
+
+ index_data += sparse->indices_byte_offset;
+ reader_head += sparse->values_byte_offset;
+
+ cgltf_size index_stride = cgltf_component_size(sparse->indices_component_type);
+ for (cgltf_size reader_index = 0; reader_index < sparse->count; reader_index++, index_data += index_stride, reader_head += accessor->stride)
+ {
+ size_t writer_index = cgltf_component_read_index(index_data, sparse->indices_component_type);
+ float* writer_head = out + writer_index * floats_per_element;
+
+ if (!cgltf_element_read_float(reader_head, accessor->type, accessor->component_type, accessor->normalized, writer_head, floats_per_element))
+ {
+ return 0;
+ }
+ }
+ }
+
+ return element_count * floats_per_element;
+}
+
+static cgltf_uint cgltf_component_read_uint(const void* in, cgltf_component_type component_type)
+{
+ switch (component_type)
+ {
+ case cgltf_component_type_r_8:
+ return *((const int8_t*) in);
+
+ case cgltf_component_type_r_8u:
+ return *((const uint8_t*) in);
+
+ case cgltf_component_type_r_16:
+ return *((const int16_t*) in);
+
+ case cgltf_component_type_r_16u:
+ return *((const uint16_t*) in);
+
+ case cgltf_component_type_r_32u:
+ return *((const uint32_t*) in);
+
+ default:
+ return 0;
+ }
+}
+
+static cgltf_bool cgltf_element_read_uint(const uint8_t* element, cgltf_type type, cgltf_component_type component_type, cgltf_uint* out, cgltf_size element_size)
+{
+ cgltf_size num_components = cgltf_num_components(type);
+
+ if (element_size < num_components)
+ {
+ return 0;
+ }
+
+ // Reading integer matrices is not a valid use case
+ if (type == cgltf_type_mat2 || type == cgltf_type_mat3 || type == cgltf_type_mat4)
+ {
+ return 0;
+ }
+
+ cgltf_size component_size = cgltf_component_size(component_type);
+
+ for (cgltf_size i = 0; i < num_components; ++i)
+ {
+ out[i] = cgltf_component_read_uint(element + component_size * i, component_type);
+ }
+ return 1;
+}
+
+cgltf_bool cgltf_accessor_read_uint(const cgltf_accessor* accessor, cgltf_size index, cgltf_uint* out, cgltf_size element_size)
+{
+ if (accessor->is_sparse)
+ {
+ return 0;
+ }
+ if (accessor->buffer_view == NULL)
+ {
+ memset(out, 0, element_size * sizeof( cgltf_uint ));
+ return 1;
+ }
+ const uint8_t* element = cgltf_buffer_view_data(accessor->buffer_view);
+ if (element == NULL)
+ {
+ return 0;
+ }
+ element += accessor->offset + accessor->stride * index;
+ return cgltf_element_read_uint(element, accessor->type, accessor->component_type, out, element_size);
+}
+
+cgltf_size cgltf_accessor_read_index(const cgltf_accessor* accessor, cgltf_size index)
+{
+ if (accessor->is_sparse)
+ {
+ return 0; // This is an error case, but we can't communicate the error with existing interface.
+ }
+ if (accessor->buffer_view == NULL)
+ {
+ return 0;
+ }
+ const uint8_t* element = cgltf_buffer_view_data(accessor->buffer_view);
+ if (element == NULL)
+ {
+ return 0; // This is an error case, but we can't communicate the error with existing interface.
+ }
+ element += accessor->offset + accessor->stride * index;
+ return cgltf_component_read_index(element, accessor->component_type);
+}
+
+cgltf_size cgltf_mesh_index(const cgltf_data* data, const cgltf_mesh* object)
+{
+ assert(object && (cgltf_size)(object - data->meshes) < data->meshes_count);
+ return (cgltf_size)(object - data->meshes);
+}
+
+cgltf_size cgltf_material_index(const cgltf_data* data, const cgltf_material* object)
+{
+ assert(object && (cgltf_size)(object - data->materials) < data->materials_count);
+ return (cgltf_size)(object - data->materials);
+}
+
+cgltf_size cgltf_accessor_index(const cgltf_data* data, const cgltf_accessor* object)
+{
+ assert(object && (cgltf_size)(object - data->accessors) < data->accessors_count);
+ return (cgltf_size)(object - data->accessors);
+}
+
+cgltf_size cgltf_buffer_view_index(const cgltf_data* data, const cgltf_buffer_view* object)
+{
+ assert(object && (cgltf_size)(object - data->buffer_views) < data->buffer_views_count);
+ return (cgltf_size)(object - data->buffer_views);
+}
+
+cgltf_size cgltf_buffer_index(const cgltf_data* data, const cgltf_buffer* object)
+{
+ assert(object && (cgltf_size)(object - data->buffers) < data->buffers_count);
+ return (cgltf_size)(object - data->buffers);
+}
+
+cgltf_size cgltf_image_index(const cgltf_data* data, const cgltf_image* object)
+{
+ assert(object && (cgltf_size)(object - data->images) < data->images_count);
+ return (cgltf_size)(object - data->images);
+}
+
+cgltf_size cgltf_texture_index(const cgltf_data* data, const cgltf_texture* object)
+{
+ assert(object && (cgltf_size)(object - data->textures) < data->textures_count);
+ return (cgltf_size)(object - data->textures);
+}
+
+cgltf_size cgltf_sampler_index(const cgltf_data* data, const cgltf_sampler* object)
+{
+ assert(object && (cgltf_size)(object - data->samplers) < data->samplers_count);
+ return (cgltf_size)(object - data->samplers);
+}
+
+cgltf_size cgltf_skin_index(const cgltf_data* data, const cgltf_skin* object)
+{
+ assert(object && (cgltf_size)(object - data->skins) < data->skins_count);
+ return (cgltf_size)(object - data->skins);
+}
+
+cgltf_size cgltf_camera_index(const cgltf_data* data, const cgltf_camera* object)
+{
+ assert(object && (cgltf_size)(object - data->cameras) < data->cameras_count);
+ return (cgltf_size)(object - data->cameras);
+}
+
+cgltf_size cgltf_light_index(const cgltf_data* data, const cgltf_light* object)
+{
+ assert(object && (cgltf_size)(object - data->lights) < data->lights_count);
+ return (cgltf_size)(object - data->lights);
+}
+
+cgltf_size cgltf_node_index(const cgltf_data* data, const cgltf_node* object)
+{
+ assert(object && (cgltf_size)(object - data->nodes) < data->nodes_count);
+ return (cgltf_size)(object - data->nodes);
+}
+
+cgltf_size cgltf_scene_index(const cgltf_data* data, const cgltf_scene* object)
+{
+ assert(object && (cgltf_size)(object - data->scenes) < data->scenes_count);
+ return (cgltf_size)(object - data->scenes);
+}
+
+cgltf_size cgltf_animation_index(const cgltf_data* data, const cgltf_animation* object)
+{
+ assert(object && (cgltf_size)(object - data->animations) < data->animations_count);
+ return (cgltf_size)(object - data->animations);
+}
+
+cgltf_size cgltf_animation_sampler_index(const cgltf_animation* animation, const cgltf_animation_sampler* object)
+{
+ assert(object && (cgltf_size)(object - animation->samplers) < animation->samplers_count);
+ return (cgltf_size)(object - animation->samplers);
+}
+
+cgltf_size cgltf_animation_channel_index(const cgltf_animation* animation, const cgltf_animation_channel* object)
+{
+ assert(object && (cgltf_size)(object - animation->channels) < animation->channels_count);
+ return (cgltf_size)(object - animation->channels);
+}
+
+cgltf_size cgltf_accessor_unpack_indices(const cgltf_accessor* accessor, void* out, cgltf_size out_component_size, cgltf_size index_count)
+{
+ if (out == NULL)
+ {
+ return accessor->count;
+ }
+
+ index_count = accessor->count < index_count ? accessor->count : index_count;
+ cgltf_size index_component_size = cgltf_component_size(accessor->component_type);
+
+ if (accessor->is_sparse)
+ {
+ return 0;
+ }
+ if (accessor->buffer_view == NULL)
+ {
+ return 0;
+ }
+ if (index_component_size > out_component_size)
+ {
+ return 0;
+ }
+ const uint8_t* element = cgltf_buffer_view_data(accessor->buffer_view);
+ if (element == NULL)
+ {
+ return 0;
+ }
+ element += accessor->offset;
+
+ if (index_component_size == out_component_size && accessor->stride == out_component_size)
+ {
+ memcpy(out, element, index_count * index_component_size);
+ return index_count;
+ }
+
+ // 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 2:
+ for (cgltf_size index = 0; index < index_count; index++, element += accessor->stride)
+ {
+ ((uint16_t*)out)[index] = (uint16_t)cgltf_component_read_index(element, accessor->component_type);
+ }
+ break;
+ case 4:
+ for (cgltf_size index = 0; index < index_count; index++, element += accessor->stride)
+ {
+ ((uint32_t*)out)[index] = (uint32_t)cgltf_component_read_index(element, accessor->component_type);
+ }
+ break;
+ default:
+ break;
+ }
+
+ return index_count;
+}
+
+#define CGLTF_ERROR_JSON -1
+#define CGLTF_ERROR_NOMEM -2
+#define CGLTF_ERROR_LEGACY -3
+
+#define CGLTF_CHECK_TOKTYPE(tok_, type_) if ((tok_).type != (type_)) { return CGLTF_ERROR_JSON; }
+#define CGLTF_CHECK_TOKTYPE_RET(tok_, type_, ret_) if ((tok_).type != (type_)) { return ret_; }
+#define CGLTF_CHECK_KEY(tok_) if ((tok_).type != JSMN_STRING || (tok_).size == 0) { return CGLTF_ERROR_JSON; } /* checking size for 0 verifies that a value follows the key */
+
+#define CGLTF_PTRINDEX(type, idx) (type*)((cgltf_size)idx + 1)
+#define CGLTF_PTRFIXUP(var, data, size) if (var) { if ((cgltf_size)var > size) { return CGLTF_ERROR_JSON; } var = &data[(cgltf_size)var-1]; }
+#define CGLTF_PTRFIXUP_REQ(var, data, size) if (!var || (cgltf_size)var > size) { return CGLTF_ERROR_JSON; } var = &data[(cgltf_size)var-1];
+
+static int cgltf_json_strcmp(jsmntok_t const* tok, const uint8_t* json_chunk, const char* str)
+{
+ CGLTF_CHECK_TOKTYPE(*tok, JSMN_STRING);
+ size_t const str_len = strlen(str);
+ size_t const name_length = (size_t)(tok->end - tok->start);
+ return (str_len == name_length) ? strncmp((const char*)json_chunk + tok->start, str, str_len) : 128;
+}
+
+static int cgltf_json_to_int(jsmntok_t const* tok, const uint8_t* json_chunk)
+{
+ CGLTF_CHECK_TOKTYPE(*tok, JSMN_PRIMITIVE);
+ char tmp[128];
+ int size = (size_t)(tok->end - tok->start) < sizeof(tmp) ? (int)(tok->end - tok->start) : (int)(sizeof(tmp) - 1);
+ strncpy(tmp, (const char*)json_chunk + tok->start, size);
+ tmp[size] = 0;
+ return CGLTF_ATOI(tmp);
+}
+
+static cgltf_size cgltf_json_to_size(jsmntok_t const* tok, const uint8_t* json_chunk)
+{
+ CGLTF_CHECK_TOKTYPE_RET(*tok, JSMN_PRIMITIVE, 0);
+ char tmp[128];
+ int size = (size_t)(tok->end - tok->start) < sizeof(tmp) ? (int)(tok->end - tok->start) : (int)(sizeof(tmp) - 1);
+ strncpy(tmp, (const char*)json_chunk + tok->start, size);
+ tmp[size] = 0;
+ long long res = CGLTF_ATOLL(tmp);
+ return res < 0 ? 0 : (cgltf_size)res;
+}
+
+static cgltf_float cgltf_json_to_float(jsmntok_t const* tok, const uint8_t* json_chunk)
+{
+ CGLTF_CHECK_TOKTYPE(*tok, JSMN_PRIMITIVE);
+ char tmp[128];
+ int size = (size_t)(tok->end - tok->start) < sizeof(tmp) ? (int)(tok->end - tok->start) : (int)(sizeof(tmp) - 1);
+ strncpy(tmp, (const char*)json_chunk + tok->start, size);
+ tmp[size] = 0;
+ return (cgltf_float)CGLTF_ATOF(tmp);
+}
+
+static cgltf_bool cgltf_json_to_bool(jsmntok_t const* tok, const uint8_t* json_chunk)
+{
+ int size = (int)(tok->end - tok->start);
+ return size == 4 && memcmp(json_chunk + tok->start, "true", 4) == 0;
+}
+
+static int cgltf_skip_json(jsmntok_t const* tokens, int i)
+{
+ int end = i + 1;
+
+ while (i < end)
+ {
+ switch (tokens[i].type)
+ {
+ case JSMN_OBJECT:
+ end += tokens[i].size * 2;
+ break;
+
+ case JSMN_ARRAY:
+ end += tokens[i].size;
+ break;
+
+ case JSMN_PRIMITIVE:
+ case JSMN_STRING:
+ break;
+
+ default:
+ return -1;
+ }
+
+ i++;
+ }
+
+ return i;
+}
+
+static void cgltf_fill_float_array(float* out_array, int size, float value)
+{
+ for (int j = 0; j < size; ++j)
+ {
+ out_array[j] = value;
+ }
+}
+
+static int cgltf_parse_json_float_array(jsmntok_t const* tokens, int i, const uint8_t* json_chunk, float* out_array, int size)
+{
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_ARRAY);
+ if (tokens[i].size != size)
+ {
+ return CGLTF_ERROR_JSON;
+ }
+ ++i;
+ for (int j = 0; j < size; ++j)
+ {
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
+ out_array[j] = cgltf_json_to_float(tokens + i, json_chunk);
+ ++i;
+ }
+ return i;
+}
+
+static int cgltf_parse_json_string(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, char** out_string)
+{
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_STRING);
+ if (*out_string)
+ {
+ return CGLTF_ERROR_JSON;
+ }
+ int size = (int)(tokens[i].end - tokens[i].start);
+ char* result = (char*)options->memory.alloc_func(options->memory.user_data, size + 1);
+ if (!result)
+ {
+ return CGLTF_ERROR_NOMEM;
+ }
+ strncpy(result, (const char*)json_chunk + tokens[i].start, size);
+ result[size] = 0;
+ *out_string = result;
+ return i + 1;
+}
+
+static int cgltf_parse_json_array(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, size_t element_size, void** out_array, cgltf_size* out_size)
+{
+ (void)json_chunk;
+ if (tokens[i].type != JSMN_ARRAY)
+ {
+ return tokens[i].type == JSMN_OBJECT ? CGLTF_ERROR_LEGACY : CGLTF_ERROR_JSON;
+ }
+ if (*out_array)
+ {
+ return CGLTF_ERROR_JSON;
+ }
+ int size = tokens[i].size;
+ void* result = cgltf_calloc(options, element_size, size);
+ if (!result)
+ {
+ return CGLTF_ERROR_NOMEM;
+ }
+ *out_array = result;
+ *out_size = size;
+ return i + 1;
+}
+
+static int cgltf_parse_json_string_array(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, char*** out_array, cgltf_size* out_size)
+{
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_ARRAY);
+ i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(char*), (void**)out_array, out_size);
+ if (i < 0)
+ {
+ return i;
+ }
+
+ for (cgltf_size j = 0; j < *out_size; ++j)
+ {
+ i = cgltf_parse_json_string(options, tokens, i, json_chunk, j + (*out_array));
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+ return i;
+}
+
+static void cgltf_parse_attribute_type(const char* name, cgltf_attribute_type* out_type, int* out_index)
+{
+ if (*name == '_')
+ {
+ *out_type = cgltf_attribute_type_custom;
+ return;
+ }
+
+ const char* us = strchr(name, '_');
+ size_t len = us ? (size_t)(us - name) : strlen(name);
+
+ if (len == 8 && strncmp(name, "POSITION", 8) == 0)
+ {
+ *out_type = cgltf_attribute_type_position;
+ }
+ else if (len == 6 && strncmp(name, "NORMAL", 6) == 0)
+ {
+ *out_type = cgltf_attribute_type_normal;
+ }
+ else if (len == 7 && strncmp(name, "TANGENT", 7) == 0)
+ {
+ *out_type = cgltf_attribute_type_tangent;
+ }
+ else if (len == 8 && strncmp(name, "TEXCOORD", 8) == 0)
+ {
+ *out_type = cgltf_attribute_type_texcoord;
+ }
+ else if (len == 5 && strncmp(name, "COLOR", 5) == 0)
+ {
+ *out_type = cgltf_attribute_type_color;
+ }
+ else if (len == 6 && strncmp(name, "JOINTS", 6) == 0)
+ {
+ *out_type = cgltf_attribute_type_joints;
+ }
+ else if (len == 7 && strncmp(name, "WEIGHTS", 7) == 0)
+ {
+ *out_type = cgltf_attribute_type_weights;
+ }
+ else
+ {
+ *out_type = cgltf_attribute_type_invalid;
+ }
+
+ if (us && *out_type != cgltf_attribute_type_invalid)
+ {
+ *out_index = CGLTF_ATOI(us + 1);
+ if (*out_index < 0)
+ {
+ *out_type = cgltf_attribute_type_invalid;
+ *out_index = 0;
+ }
+ }
+}
+
+static int cgltf_parse_json_attribute_list(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_attribute** out_attributes, cgltf_size* out_attributes_count)
+{
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+
+ if (*out_attributes)
+ {
+ return CGLTF_ERROR_JSON;
+ }
+
+ *out_attributes_count = tokens[i].size;
+ *out_attributes = (cgltf_attribute*)cgltf_calloc(options, sizeof(cgltf_attribute), *out_attributes_count);
+ ++i;
+
+ if (!*out_attributes)
+ {
+ return CGLTF_ERROR_NOMEM;
+ }
+
+ for (cgltf_size j = 0; j < *out_attributes_count; ++j)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ i = cgltf_parse_json_string(options, tokens, i, json_chunk, &(*out_attributes)[j].name);
+ if (i < 0)
+ {
+ return CGLTF_ERROR_JSON;
+ }
+
+ cgltf_parse_attribute_type((*out_attributes)[j].name, &(*out_attributes)[j].type, &(*out_attributes)[j].index);
+
+ (*out_attributes)[j].data = CGLTF_PTRINDEX(cgltf_accessor, cgltf_json_to_int(tokens + i, json_chunk));
+ ++i;
+ }
+
+ return i;
+}
+
+static int cgltf_parse_json_extras(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_extras* out_extras)
+{
+ if (out_extras->data)
+ {
+ return CGLTF_ERROR_JSON;
+ }
+
+ /* fill deprecated fields for now, this will be removed in the future */
+ out_extras->start_offset = tokens[i].start;
+ out_extras->end_offset = tokens[i].end;
+
+ size_t start = tokens[i].start;
+ size_t size = tokens[i].end - start;
+ out_extras->data = (char*)options->memory.alloc_func(options->memory.user_data, size + 1);
+ if (!out_extras->data)
+ {
+ return CGLTF_ERROR_NOMEM;
+ }
+ strncpy(out_extras->data, (const char*)json_chunk + start, size);
+ out_extras->data[size] = '\0';
+
+ i = cgltf_skip_json(tokens, i);
+ return i;
+}
+
+static int cgltf_parse_json_unprocessed_extension(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_extension* out_extension)
+{
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_STRING);
+ CGLTF_CHECK_TOKTYPE(tokens[i+1], JSMN_OBJECT);
+ if (out_extension->name)
+ {
+ return CGLTF_ERROR_JSON;
+ }
+
+ cgltf_size name_length = tokens[i].end - tokens[i].start;
+ out_extension->name = (char*)options->memory.alloc_func(options->memory.user_data, name_length + 1);
+ if (!out_extension->name)
+ {
+ return CGLTF_ERROR_NOMEM;
+ }
+ strncpy(out_extension->name, (const char*)json_chunk + tokens[i].start, name_length);
+ out_extension->name[name_length] = 0;
+ i++;
+
+ size_t start = tokens[i].start;
+ size_t size = tokens[i].end - start;
+ out_extension->data = (char*)options->memory.alloc_func(options->memory.user_data, size + 1);
+ if (!out_extension->data)
+ {
+ return CGLTF_ERROR_NOMEM;
+ }
+ strncpy(out_extension->data, (const char*)json_chunk + start, size);
+ out_extension->data[size] = '\0';
+
+ i = cgltf_skip_json(tokens, i);
+
+ return i;
+}
+
+static int cgltf_parse_json_unprocessed_extensions(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_size* out_extensions_count, cgltf_extension** out_extensions)
+{
+ ++i;
+
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+ if(*out_extensions)
+ {
+ return CGLTF_ERROR_JSON;
+ }
+
+ int extensions_size = tokens[i].size;
+ *out_extensions_count = 0;
+ *out_extensions = (cgltf_extension*)cgltf_calloc(options, sizeof(cgltf_extension), extensions_size);
+
+ if (!*out_extensions)
+ {
+ return CGLTF_ERROR_NOMEM;
+ }
+
+ ++i;
+
+ for (int j = 0; j < extensions_size; ++j)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ cgltf_size extension_index = (*out_extensions_count)++;
+ cgltf_extension* extension = &((*out_extensions)[extension_index]);
+ i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, extension);
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+ return i;
+}
+
+static int cgltf_parse_json_draco_mesh_compression(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_draco_mesh_compression* out_draco_mesh_compression)
+{
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+
+ int size = tokens[i].size;
+ ++i;
+
+ for (int j = 0; j < size; ++j)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens + i, json_chunk, "attributes") == 0)
+ {
+ i = cgltf_parse_json_attribute_list(options, tokens, i + 1, json_chunk, &out_draco_mesh_compression->attributes, &out_draco_mesh_compression->attributes_count);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "bufferView") == 0)
+ {
+ ++i;
+ out_draco_mesh_compression->buffer_view = CGLTF_PTRINDEX(cgltf_buffer_view, cgltf_json_to_int(tokens + i, json_chunk));
+ ++i;
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i+1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+
+ return i;
+}
+
+static int cgltf_parse_json_mesh_gpu_instancing(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_mesh_gpu_instancing* out_mesh_gpu_instancing)
+{
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+
+ int size = tokens[i].size;
+ ++i;
+
+ for (int j = 0; j < size; ++j)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens + i, json_chunk, "attributes") == 0)
+ {
+ i = cgltf_parse_json_attribute_list(options, tokens, i + 1, json_chunk, &out_mesh_gpu_instancing->attributes, &out_mesh_gpu_instancing->attributes_count);
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i+1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+
+ return i;
+}
+
+static int cgltf_parse_json_material_mapping_data(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_material_mapping* out_mappings, cgltf_size* offset)
+{
+ (void)options;
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_ARRAY);
+
+ int size = tokens[i].size;
+ ++i;
+
+ for (int j = 0; j < size; ++j)
+ {
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+
+ int obj_size = tokens[i].size;
+ ++i;
+
+ int material = -1;
+ int variants_tok = -1;
+ int extras_tok = -1;
+
+ for (int k = 0; k < obj_size; ++k)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens + i, json_chunk, "material") == 0)
+ {
+ ++i;
+ material = cgltf_json_to_int(tokens + i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "variants") == 0)
+ {
+ variants_tok = i+1;
+ CGLTF_CHECK_TOKTYPE(tokens[variants_tok], JSMN_ARRAY);
+
+ i = cgltf_skip_json(tokens, i+1);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
+ {
+ extras_tok = i + 1;
+ i = cgltf_skip_json(tokens, extras_tok);
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i+1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+
+ if (material < 0 || variants_tok < 0)
+ {
+ return CGLTF_ERROR_JSON;
+ }
+
+ if (out_mappings)
+ {
+ for (int k = 0; k < tokens[variants_tok].size; ++k)
+ {
+ int variant = cgltf_json_to_int(&tokens[variants_tok + 1 + k], json_chunk);
+ if (variant < 0)
+ return variant;
+
+ out_mappings[*offset].material = CGLTF_PTRINDEX(cgltf_material, material);
+ out_mappings[*offset].variant = variant;
+
+ if (extras_tok >= 0)
+ {
+ int e = cgltf_parse_json_extras(options, tokens, extras_tok, json_chunk, &out_mappings[*offset].extras);
+ if (e < 0)
+ return e;
+ }
+
+ (*offset)++;
+ }
+ }
+ else
+ {
+ (*offset) += tokens[variants_tok].size;
+ }
+ }
+
+ return i;
+}
+
+static int cgltf_parse_json_material_mappings(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_primitive* out_prim)
+{
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+
+ int size = tokens[i].size;
+ ++i;
+
+ for (int j = 0; j < size; ++j)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens + i, json_chunk, "mappings") == 0)
+ {
+ if (out_prim->mappings)
+ {
+ return CGLTF_ERROR_JSON;
+ }
+
+ cgltf_size mappings_offset = 0;
+ int k = cgltf_parse_json_material_mapping_data(options, tokens, i + 1, json_chunk, NULL, &mappings_offset);
+ if (k < 0)
+ {
+ return k;
+ }
+
+ out_prim->mappings_count = mappings_offset;
+ out_prim->mappings = (cgltf_material_mapping*)cgltf_calloc(options, sizeof(cgltf_material_mapping), out_prim->mappings_count);
+
+ mappings_offset = 0;
+ i = cgltf_parse_json_material_mapping_data(options, tokens, i + 1, json_chunk, out_prim->mappings, &mappings_offset);
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i+1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+
+ return i;
+}
+
+static cgltf_primitive_type cgltf_json_to_primitive_type(jsmntok_t const* tok, const uint8_t* json_chunk)
+{
+ int type = cgltf_json_to_int(tok, json_chunk);
+
+ switch (type)
+ {
+ case 0:
+ return cgltf_primitive_type_points;
+ case 1:
+ return cgltf_primitive_type_lines;
+ case 2:
+ return cgltf_primitive_type_line_loop;
+ case 3:
+ return cgltf_primitive_type_line_strip;
+ case 4:
+ return cgltf_primitive_type_triangles;
+ case 5:
+ return cgltf_primitive_type_triangle_strip;
+ case 6:
+ return cgltf_primitive_type_triangle_fan;
+ default:
+ return cgltf_primitive_type_invalid;
+ }
+}
+
+static int cgltf_parse_json_primitive(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_primitive* out_prim)
+{
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+
+ out_prim->type = cgltf_primitive_type_triangles;
+
+ int size = tokens[i].size;
+ ++i;
+
+ for (int j = 0; j < size; ++j)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens+i, json_chunk, "mode") == 0)
+ {
+ ++i;
+ out_prim->type = cgltf_json_to_primitive_type(tokens+i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "indices") == 0)
+ {
+ ++i;
+ out_prim->indices = CGLTF_PTRINDEX(cgltf_accessor, cgltf_json_to_int(tokens + i, json_chunk));
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "material") == 0)
+ {
+ ++i;
+ out_prim->material = CGLTF_PTRINDEX(cgltf_material, cgltf_json_to_int(tokens + i, json_chunk));
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "attributes") == 0)
+ {
+ i = cgltf_parse_json_attribute_list(options, tokens, i + 1, json_chunk, &out_prim->attributes, &out_prim->attributes_count);
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "targets") == 0)
+ {
+ i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk, sizeof(cgltf_morph_target), (void**)&out_prim->targets, &out_prim->targets_count);
+ if (i < 0)
+ {
+ return i;
+ }
+
+ for (cgltf_size k = 0; k < out_prim->targets_count; ++k)
+ {
+ i = cgltf_parse_json_attribute_list(options, tokens, i, json_chunk, &out_prim->targets[k].attributes, &out_prim->targets[k].attributes_count);
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
+ {
+ i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_prim->extras);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
+ {
+ ++i;
+
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+ if(out_prim->extensions)
+ {
+ return CGLTF_ERROR_JSON;
+ }
+
+ int extensions_size = tokens[i].size;
+ out_prim->extensions_count = 0;
+ out_prim->extensions = (cgltf_extension*)cgltf_calloc(options, sizeof(cgltf_extension), extensions_size);
+
+ if (!out_prim->extensions)
+ {
+ return CGLTF_ERROR_NOMEM;
+ }
+
+ ++i;
+ for (int k = 0; k < extensions_size; ++k)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_draco_mesh_compression") == 0)
+ {
+ out_prim->has_draco_mesh_compression = 1;
+ i = cgltf_parse_json_draco_mesh_compression(options, tokens, i + 1, json_chunk, &out_prim->draco_mesh_compression);
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_variants") == 0)
+ {
+ i = cgltf_parse_json_material_mappings(options, tokens, i + 1, json_chunk, out_prim);
+ }
+ else
+ {
+ i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_prim->extensions[out_prim->extensions_count++]));
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i+1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+
+ return i;
+}
+
+static int cgltf_parse_json_mesh(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_mesh* out_mesh)
+{
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+
+ int size = tokens[i].size;
+ ++i;
+
+ for (int j = 0; j < size; ++j)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens+i, json_chunk, "name") == 0)
+ {
+ i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_mesh->name);
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "primitives") == 0)
+ {
+ i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk, sizeof(cgltf_primitive), (void**)&out_mesh->primitives, &out_mesh->primitives_count);
+ if (i < 0)
+ {
+ return i;
+ }
+
+ for (cgltf_size prim_index = 0; prim_index < out_mesh->primitives_count; ++prim_index)
+ {
+ i = cgltf_parse_json_primitive(options, tokens, i, json_chunk, &out_mesh->primitives[prim_index]);
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "weights") == 0)
+ {
+ i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk, sizeof(cgltf_float), (void**)&out_mesh->weights, &out_mesh->weights_count);
+ if (i < 0)
+ {
+ return i;
+ }
+
+ i = cgltf_parse_json_float_array(tokens, i - 1, json_chunk, out_mesh->weights, (int)out_mesh->weights_count);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
+ {
+ ++i;
+
+ out_mesh->extras.start_offset = tokens[i].start;
+ out_mesh->extras.end_offset = tokens[i].end;
+
+ if (tokens[i].type == JSMN_OBJECT)
+ {
+ int extras_size = tokens[i].size;
+ ++i;
+
+ for (int k = 0; k < extras_size; ++k)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens+i, json_chunk, "targetNames") == 0 && tokens[i+1].type == JSMN_ARRAY)
+ {
+ i = cgltf_parse_json_string_array(options, tokens, i + 1, json_chunk, &out_mesh->target_names, &out_mesh->target_names_count);
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i+1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i);
+ }
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
+ {
+ i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_mesh->extensions_count, &out_mesh->extensions);
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i+1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+
+ return i;
+}
+
+static int cgltf_parse_json_meshes(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
+{
+ i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_mesh), (void**)&out_data->meshes, &out_data->meshes_count);
+ if (i < 0)
+ {
+ return i;
+ }
+
+ for (cgltf_size j = 0; j < out_data->meshes_count; ++j)
+ {
+ i = cgltf_parse_json_mesh(options, tokens, i, json_chunk, &out_data->meshes[j]);
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+ return i;
+}
+
+static cgltf_component_type cgltf_json_to_component_type(jsmntok_t const* tok, const uint8_t* json_chunk)
+{
+ int type = cgltf_json_to_int(tok, json_chunk);
+
+ switch (type)
+ {
+ case 5120:
+ return cgltf_component_type_r_8;
+ case 5121:
+ return cgltf_component_type_r_8u;
+ case 5122:
+ return cgltf_component_type_r_16;
+ case 5123:
+ return cgltf_component_type_r_16u;
+ case 5125:
+ return cgltf_component_type_r_32u;
+ case 5126:
+ return cgltf_component_type_r_32f;
+ default:
+ return cgltf_component_type_invalid;
+ }
+}
+
+static int cgltf_parse_json_accessor_sparse(jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_accessor_sparse* out_sparse)
+{
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+
+ int size = tokens[i].size;
+ ++i;
+
+ for (int j = 0; j < size; ++j)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens+i, json_chunk, "count") == 0)
+ {
+ ++i;
+ out_sparse->count = cgltf_json_to_size(tokens + i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "indices") == 0)
+ {
+ ++i;
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+
+ int indices_size = tokens[i].size;
+ ++i;
+
+ for (int k = 0; k < indices_size; ++k)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens+i, json_chunk, "bufferView") == 0)
+ {
+ ++i;
+ out_sparse->indices_buffer_view = CGLTF_PTRINDEX(cgltf_buffer_view, cgltf_json_to_int(tokens + i, json_chunk));
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteOffset") == 0)
+ {
+ ++i;
+ out_sparse->indices_byte_offset = cgltf_json_to_size(tokens + i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "componentType") == 0)
+ {
+ ++i;
+ out_sparse->indices_component_type = cgltf_json_to_component_type(tokens + i, json_chunk);
+ ++i;
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i+1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "values") == 0)
+ {
+ ++i;
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+
+ int values_size = tokens[i].size;
+ ++i;
+
+ for (int k = 0; k < values_size; ++k)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens+i, json_chunk, "bufferView") == 0)
+ {
+ ++i;
+ out_sparse->values_buffer_view = CGLTF_PTRINDEX(cgltf_buffer_view, cgltf_json_to_int(tokens + i, json_chunk));
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteOffset") == 0)
+ {
+ ++i;
+ out_sparse->values_byte_offset = cgltf_json_to_size(tokens + i, json_chunk);
+ ++i;
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i+1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i+1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+
+ return i;
+}
+
+static int cgltf_parse_json_accessor(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_accessor* out_accessor)
+{
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+
+ int size = tokens[i].size;
+ ++i;
+
+ for (int j = 0; j < size; ++j)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens + i, json_chunk, "name") == 0)
+ {
+ i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_accessor->name);
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "bufferView") == 0)
+ {
+ ++i;
+ out_accessor->buffer_view = CGLTF_PTRINDEX(cgltf_buffer_view, cgltf_json_to_int(tokens + i, json_chunk));
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteOffset") == 0)
+ {
+ ++i;
+ out_accessor->offset =
+ cgltf_json_to_size(tokens+i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "componentType") == 0)
+ {
+ ++i;
+ out_accessor->component_type = cgltf_json_to_component_type(tokens + i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "normalized") == 0)
+ {
+ ++i;
+ out_accessor->normalized = cgltf_json_to_bool(tokens+i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "count") == 0)
+ {
+ ++i;
+ out_accessor->count = cgltf_json_to_size(tokens+i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "type") == 0)
+ {
+ ++i;
+ if (cgltf_json_strcmp(tokens+i, json_chunk, "SCALAR") == 0)
+ {
+ out_accessor->type = cgltf_type_scalar;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "VEC2") == 0)
+ {
+ out_accessor->type = cgltf_type_vec2;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "VEC3") == 0)
+ {
+ out_accessor->type = cgltf_type_vec3;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "VEC4") == 0)
+ {
+ out_accessor->type = cgltf_type_vec4;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "MAT2") == 0)
+ {
+ out_accessor->type = cgltf_type_mat2;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "MAT3") == 0)
+ {
+ out_accessor->type = cgltf_type_mat3;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "MAT4") == 0)
+ {
+ out_accessor->type = cgltf_type_mat4;
+ }
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "min") == 0)
+ {
+ ++i;
+ out_accessor->has_min = 1;
+ // note: we can't parse the precise number of elements since type may not have been computed yet
+ int min_size = tokens[i].size > 16 ? 16 : tokens[i].size;
+ i = cgltf_parse_json_float_array(tokens, i, json_chunk, out_accessor->min, min_size);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "max") == 0)
+ {
+ ++i;
+ out_accessor->has_max = 1;
+ // note: we can't parse the precise number of elements since type may not have been computed yet
+ int max_size = tokens[i].size > 16 ? 16 : tokens[i].size;
+ i = cgltf_parse_json_float_array(tokens, i, json_chunk, out_accessor->max, max_size);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "sparse") == 0)
+ {
+ out_accessor->is_sparse = 1;
+ i = cgltf_parse_json_accessor_sparse(tokens, i + 1, json_chunk, &out_accessor->sparse);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
+ {
+ i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_accessor->extras);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
+ {
+ i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_accessor->extensions_count, &out_accessor->extensions);
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i+1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+
+ return i;
+}
+
+static int cgltf_parse_json_texture_transform(jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_texture_transform* out_texture_transform)
+{
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+
+ int size = tokens[i].size;
+ ++i;
+
+ for (int j = 0; j < size; ++j)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens + i, json_chunk, "offset") == 0)
+ {
+ i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_texture_transform->offset, 2);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "rotation") == 0)
+ {
+ ++i;
+ out_texture_transform->rotation = cgltf_json_to_float(tokens + i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "scale") == 0)
+ {
+ i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_texture_transform->scale, 2);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "texCoord") == 0)
+ {
+ ++i;
+ out_texture_transform->has_texcoord = 1;
+ out_texture_transform->texcoord = cgltf_json_to_int(tokens + i, json_chunk);
+ ++i;
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i + 1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+
+ return i;
+}
+
+static int cgltf_parse_json_texture_view(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_texture_view* out_texture_view)
+{
+ (void)options;
+
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+
+ out_texture_view->scale = 1.0f;
+ cgltf_fill_float_array(out_texture_view->transform.scale, 2, 1.0f);
+
+ int size = tokens[i].size;
+ ++i;
+
+ for (int j = 0; j < size; ++j)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens + i, json_chunk, "index") == 0)
+ {
+ ++i;
+ out_texture_view->texture = CGLTF_PTRINDEX(cgltf_texture, cgltf_json_to_int(tokens + i, json_chunk));
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "texCoord") == 0)
+ {
+ ++i;
+ out_texture_view->texcoord = cgltf_json_to_int(tokens + i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "scale") == 0)
+ {
+ ++i;
+ out_texture_view->scale = cgltf_json_to_float(tokens + i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "strength") == 0)
+ {
+ ++i;
+ out_texture_view->scale = cgltf_json_to_float(tokens + i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
+ {
+ ++i;
+
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+ int extensions_size = tokens[i].size;
+
+ ++i;
+
+ for (int k = 0; k < extensions_size; ++k)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_texture_transform") == 0)
+ {
+ out_texture_view->has_transform = 1;
+ i = cgltf_parse_json_texture_transform(tokens, i + 1, json_chunk, &out_texture_view->transform);
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i + 1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i + 1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+
+ return i;
+}
+
+static int cgltf_parse_json_pbr_metallic_roughness(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_pbr_metallic_roughness* out_pbr)
+{
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+
+ int size = tokens[i].size;
+ ++i;
+
+ for (int j = 0; j < size; ++j)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens+i, json_chunk, "metallicFactor") == 0)
+ {
+ ++i;
+ out_pbr->metallic_factor =
+ cgltf_json_to_float(tokens + i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "roughnessFactor") == 0)
+ {
+ ++i;
+ out_pbr->roughness_factor =
+ cgltf_json_to_float(tokens+i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "baseColorFactor") == 0)
+ {
+ i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_pbr->base_color_factor, 4);
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "baseColorTexture") == 0)
+ {
+ i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_pbr->base_color_texture);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "metallicRoughnessTexture") == 0)
+ {
+ i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_pbr->metallic_roughness_texture);
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i+1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+
+ return i;
+}
+
+static int cgltf_parse_json_pbr_specular_glossiness(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_pbr_specular_glossiness* out_pbr)
+{
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+ int size = tokens[i].size;
+ ++i;
+
+ for (int j = 0; j < size; ++j)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens+i, json_chunk, "diffuseFactor") == 0)
+ {
+ i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_pbr->diffuse_factor, 4);
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "specularFactor") == 0)
+ {
+ i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_pbr->specular_factor, 3);
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "glossinessFactor") == 0)
+ {
+ ++i;
+ out_pbr->glossiness_factor = cgltf_json_to_float(tokens + i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "diffuseTexture") == 0)
+ {
+ i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_pbr->diffuse_texture);
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "specularGlossinessTexture") == 0)
+ {
+ i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_pbr->specular_glossiness_texture);
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i+1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+
+ return i;
+}
+
+static int cgltf_parse_json_clearcoat(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_clearcoat* out_clearcoat)
+{
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+ int size = tokens[i].size;
+ ++i;
+
+ for (int j = 0; j < size; ++j)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens+i, json_chunk, "clearcoatFactor") == 0)
+ {
+ ++i;
+ out_clearcoat->clearcoat_factor = cgltf_json_to_float(tokens + i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "clearcoatRoughnessFactor") == 0)
+ {
+ ++i;
+ out_clearcoat->clearcoat_roughness_factor = cgltf_json_to_float(tokens + i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "clearcoatTexture") == 0)
+ {
+ i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_clearcoat->clearcoat_texture);
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "clearcoatRoughnessTexture") == 0)
+ {
+ i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_clearcoat->clearcoat_roughness_texture);
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "clearcoatNormalTexture") == 0)
+ {
+ i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_clearcoat->clearcoat_normal_texture);
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i+1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+
+ return i;
+}
+
+static int cgltf_parse_json_ior(jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_ior* out_ior)
+{
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+ int size = tokens[i].size;
+ ++i;
+
+ // Default values
+ out_ior->ior = 1.5f;
+
+ for (int j = 0; j < size; ++j)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens+i, json_chunk, "ior") == 0)
+ {
+ ++i;
+ out_ior->ior = cgltf_json_to_float(tokens + i, json_chunk);
+ ++i;
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i+1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+
+ return i;
+}
+
+static int cgltf_parse_json_specular(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_specular* out_specular)
+{
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+ int size = tokens[i].size;
+ ++i;
+
+ // Default values
+ out_specular->specular_factor = 1.0f;
+ cgltf_fill_float_array(out_specular->specular_color_factor, 3, 1.0f);
+
+ for (int j = 0; j < size; ++j)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens+i, json_chunk, "specularFactor") == 0)
+ {
+ ++i;
+ out_specular->specular_factor = cgltf_json_to_float(tokens + i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "specularColorFactor") == 0)
+ {
+ i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_specular->specular_color_factor, 3);
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "specularTexture") == 0)
+ {
+ i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_specular->specular_texture);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "specularColorTexture") == 0)
+ {
+ i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_specular->specular_color_texture);
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i+1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+
+ return i;
+}
+
+static int cgltf_parse_json_transmission(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_transmission* out_transmission)
+{
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+ int size = tokens[i].size;
+ ++i;
+
+ for (int j = 0; j < size; ++j)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens+i, json_chunk, "transmissionFactor") == 0)
+ {
+ ++i;
+ out_transmission->transmission_factor = cgltf_json_to_float(tokens + i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "transmissionTexture") == 0)
+ {
+ i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_transmission->transmission_texture);
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i+1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+
+ return i;
+}
+
+static int cgltf_parse_json_volume(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_volume* out_volume)
+{
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+ int size = tokens[i].size;
+ ++i;
+
+ for (int j = 0; j < size; ++j)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens + i, json_chunk, "thicknessFactor") == 0)
+ {
+ ++i;
+ out_volume->thickness_factor = cgltf_json_to_float(tokens + i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "thicknessTexture") == 0)
+ {
+ i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_volume->thickness_texture);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "attenuationColor") == 0)
+ {
+ i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_volume->attenuation_color, 3);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "attenuationDistance") == 0)
+ {
+ ++i;
+ out_volume->attenuation_distance = cgltf_json_to_float(tokens + i, json_chunk);
+ ++i;
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i + 1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+
+ return i;
+}
+
+static int cgltf_parse_json_sheen(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_sheen* out_sheen)
+{
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+ int size = tokens[i].size;
+ ++i;
+
+ for (int j = 0; j < size; ++j)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens+i, json_chunk, "sheenColorFactor") == 0)
+ {
+ i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_sheen->sheen_color_factor, 3);
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "sheenColorTexture") == 0)
+ {
+ i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_sheen->sheen_color_texture);
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "sheenRoughnessFactor") == 0)
+ {
+ ++i;
+ out_sheen->sheen_roughness_factor = cgltf_json_to_float(tokens + i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "sheenRoughnessTexture") == 0)
+ {
+ i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_sheen->sheen_roughness_texture);
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i+1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+
+ return i;
+}
+
+static int cgltf_parse_json_emissive_strength(jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_emissive_strength* out_emissive_strength)
+{
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+ int size = tokens[i].size;
+ ++i;
+
+ // Default
+ out_emissive_strength->emissive_strength = 1.f;
+
+ for (int j = 0; j < size; ++j)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens + i, json_chunk, "emissiveStrength") == 0)
+ {
+ ++i;
+ out_emissive_strength->emissive_strength = cgltf_json_to_float(tokens + i, json_chunk);
+ ++i;
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i + 1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+
+ return i;
+}
+
+static int cgltf_parse_json_iridescence(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_iridescence* out_iridescence)
+{
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+ int size = tokens[i].size;
+ ++i;
+
+ // Default
+ out_iridescence->iridescence_ior = 1.3f;
+ out_iridescence->iridescence_thickness_min = 100.f;
+ out_iridescence->iridescence_thickness_max = 400.f;
+
+ for (int j = 0; j < size; ++j)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens + i, json_chunk, "iridescenceFactor") == 0)
+ {
+ ++i;
+ out_iridescence->iridescence_factor = cgltf_json_to_float(tokens + i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "iridescenceTexture") == 0)
+ {
+ i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_iridescence->iridescence_texture);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "iridescenceIor") == 0)
+ {
+ ++i;
+ out_iridescence->iridescence_ior = cgltf_json_to_float(tokens + i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "iridescenceThicknessMinimum") == 0)
+ {
+ ++i;
+ out_iridescence->iridescence_thickness_min = cgltf_json_to_float(tokens + i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "iridescenceThicknessMaximum") == 0)
+ {
+ ++i;
+ out_iridescence->iridescence_thickness_max = cgltf_json_to_float(tokens + i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "iridescenceThicknessTexture") == 0)
+ {
+ i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_iridescence->iridescence_thickness_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);
+ int size = tokens[i].size;
+ ++i;
+
+
+ for (int j = 0; j < size; ++j)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens + i, json_chunk, "anisotropyStrength") == 0)
+ {
+ ++i;
+ out_anisotropy->anisotropy_strength = cgltf_json_to_float(tokens + i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "anisotropyRotation") == 0)
+ {
+ ++i;
+ out_anisotropy->anisotropy_rotation = cgltf_json_to_float(tokens + i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "anisotropyTexture") == 0)
+ {
+ i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_anisotropy->anisotropy_texture);
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i + 1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+
+ return i;
+}
+
+static int cgltf_parse_json_dispersion(jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_dispersion* out_dispersion)
+{
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+ int size = tokens[i].size;
+ ++i;
+
+
+ for (int j = 0; j < size; ++j)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens + i, json_chunk, "dispersion") == 0)
+ {
+ ++i;
+ out_dispersion->dispersion = cgltf_json_to_float(tokens + i, json_chunk);
+ ++i;
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i + 1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+
+ return i;
+}
+
+static int cgltf_parse_json_image(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_image* out_image)
+{
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+
+ int size = tokens[i].size;
+ ++i;
+
+ for (int j = 0; j < size; ++j)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens + i, json_chunk, "uri") == 0)
+ {
+ i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_image->uri);
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "bufferView") == 0)
+ {
+ ++i;
+ out_image->buffer_view = CGLTF_PTRINDEX(cgltf_buffer_view, cgltf_json_to_int(tokens + i, json_chunk));
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "mimeType") == 0)
+ {
+ i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_image->mime_type);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "name") == 0)
+ {
+ i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_image->name);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
+ {
+ i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_image->extras);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
+ {
+ i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_image->extensions_count, &out_image->extensions);
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i + 1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+
+ return i;
+}
+
+static int cgltf_parse_json_sampler(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_sampler* out_sampler)
+{
+ (void)options;
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+
+ out_sampler->wrap_s = 10497;
+ out_sampler->wrap_t = 10497;
+
+ int size = tokens[i].size;
+ ++i;
+
+ for (int j = 0; j < size; ++j)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens + i, json_chunk, "name") == 0)
+ {
+ i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_sampler->name);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "magFilter") == 0)
+ {
+ ++i;
+ out_sampler->mag_filter
+ = 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);
+ ++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);
+ ++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);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
+ {
+ i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_sampler->extras);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
+ {
+ i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_sampler->extensions_count, &out_sampler->extensions);
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i + 1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+
+ return i;
+}
+
+static int cgltf_parse_json_texture(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_texture* out_texture)
+{
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+
+ int size = tokens[i].size;
+ ++i;
+
+ for (int j = 0; j < size; ++j)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens+i, json_chunk, "name") == 0)
+ {
+ i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_texture->name);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "sampler") == 0)
+ {
+ ++i;
+ out_texture->sampler = CGLTF_PTRINDEX(cgltf_sampler, cgltf_json_to_int(tokens + i, json_chunk));
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "source") == 0)
+ {
+ ++i;
+ out_texture->image = CGLTF_PTRINDEX(cgltf_image, cgltf_json_to_int(tokens + i, json_chunk));
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
+ {
+ i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_texture->extras);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
+ {
+ ++i;
+
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+ if (out_texture->extensions)
+ {
+ return CGLTF_ERROR_JSON;
+ }
+
+ int extensions_size = tokens[i].size;
+ ++i;
+ out_texture->extensions = (cgltf_extension*)cgltf_calloc(options, sizeof(cgltf_extension), extensions_size);
+ out_texture->extensions_count = 0;
+
+ if (!out_texture->extensions)
+ {
+ return CGLTF_ERROR_NOMEM;
+ }
+
+ for (int k = 0; k < extensions_size; ++k)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens + i, json_chunk, "KHR_texture_basisu") == 0)
+ {
+ out_texture->has_basisu = 1;
+ ++i;
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+ int num_properties = tokens[i].size;
+ ++i;
+
+ for (int t = 0; t < num_properties; ++t)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens + i, json_chunk, "source") == 0)
+ {
+ ++i;
+ out_texture->basisu_image = CGLTF_PTRINDEX(cgltf_image, cgltf_json_to_int(tokens + i, json_chunk));
+ ++i;
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i + 1);
+ }
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "EXT_texture_webp") == 0)
+ {
+ out_texture->has_webp = 1;
+ ++i;
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+ int num_properties = tokens[i].size;
+ ++i;
+
+ for (int t = 0; t < num_properties; ++t)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens + i, json_chunk, "source") == 0)
+ {
+ ++i;
+ out_texture->webp_image = CGLTF_PTRINDEX(cgltf_image, cgltf_json_to_int(tokens + i, json_chunk));
+ ++i;
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i + 1);
+ }
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+ }
+ else
+ {
+ i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_texture->extensions[out_texture->extensions_count++]));
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i + 1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+
+ return i;
+}
+
+static int cgltf_parse_json_material(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_material* out_material)
+{
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+
+ cgltf_fill_float_array(out_material->pbr_metallic_roughness.base_color_factor, 4, 1.0f);
+ out_material->pbr_metallic_roughness.metallic_factor = 1.0f;
+ out_material->pbr_metallic_roughness.roughness_factor = 1.0f;
+
+ cgltf_fill_float_array(out_material->pbr_specular_glossiness.diffuse_factor, 4, 1.0f);
+ cgltf_fill_float_array(out_material->pbr_specular_glossiness.specular_factor, 3, 1.0f);
+ out_material->pbr_specular_glossiness.glossiness_factor = 1.0f;
+
+ cgltf_fill_float_array(out_material->volume.attenuation_color, 3, 1.0f);
+ out_material->volume.attenuation_distance = FLT_MAX;
+
+ out_material->alpha_cutoff = 0.5f;
+
+ int size = tokens[i].size;
+ ++i;
+
+ for (int j = 0; j < size; ++j)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens+i, json_chunk, "name") == 0)
+ {
+ i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_material->name);
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "pbrMetallicRoughness") == 0)
+ {
+ out_material->has_pbr_metallic_roughness = 1;
+ i = cgltf_parse_json_pbr_metallic_roughness(options, tokens, i + 1, json_chunk, &out_material->pbr_metallic_roughness);
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "emissiveFactor") == 0)
+ {
+ i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_material->emissive_factor, 3);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "normalTexture") == 0)
+ {
+ i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk,
+ &out_material->normal_texture);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "occlusionTexture") == 0)
+ {
+ i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk,
+ &out_material->occlusion_texture);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "emissiveTexture") == 0)
+ {
+ i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk,
+ &out_material->emissive_texture);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "alphaMode") == 0)
+ {
+ ++i;
+ if (cgltf_json_strcmp(tokens + i, json_chunk, "OPAQUE") == 0)
+ {
+ out_material->alpha_mode = cgltf_alpha_mode_opaque;
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "MASK") == 0)
+ {
+ out_material->alpha_mode = cgltf_alpha_mode_mask;
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "BLEND") == 0)
+ {
+ out_material->alpha_mode = cgltf_alpha_mode_blend;
+ }
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "alphaCutoff") == 0)
+ {
+ ++i;
+ out_material->alpha_cutoff = cgltf_json_to_float(tokens + i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "doubleSided") == 0)
+ {
+ ++i;
+ out_material->double_sided =
+ cgltf_json_to_bool(tokens + i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
+ {
+ i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_material->extras);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
+ {
+ ++i;
+
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+ if(out_material->extensions)
+ {
+ return CGLTF_ERROR_JSON;
+ }
+
+ int extensions_size = tokens[i].size;
+ ++i;
+ out_material->extensions = (cgltf_extension*)cgltf_calloc(options, sizeof(cgltf_extension), extensions_size);
+ out_material->extensions_count= 0;
+
+ if (!out_material->extensions)
+ {
+ return CGLTF_ERROR_NOMEM;
+ }
+
+ for (int k = 0; k < extensions_size; ++k)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_pbrSpecularGlossiness") == 0)
+ {
+ out_material->has_pbr_specular_glossiness = 1;
+ i = cgltf_parse_json_pbr_specular_glossiness(options, tokens, i + 1, json_chunk, &out_material->pbr_specular_glossiness);
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_unlit") == 0)
+ {
+ out_material->unlit = 1;
+ i = cgltf_skip_json(tokens, i+1);
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_clearcoat") == 0)
+ {
+ out_material->has_clearcoat = 1;
+ i = cgltf_parse_json_clearcoat(options, tokens, i + 1, json_chunk, &out_material->clearcoat);
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_ior") == 0)
+ {
+ out_material->has_ior = 1;
+ i = cgltf_parse_json_ior(tokens, i + 1, json_chunk, &out_material->ior);
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_specular") == 0)
+ {
+ out_material->has_specular = 1;
+ i = cgltf_parse_json_specular(options, tokens, i + 1, json_chunk, &out_material->specular);
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_transmission") == 0)
+ {
+ out_material->has_transmission = 1;
+ i = cgltf_parse_json_transmission(options, tokens, i + 1, json_chunk, &out_material->transmission);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "KHR_materials_volume") == 0)
+ {
+ out_material->has_volume = 1;
+ i = cgltf_parse_json_volume(options, tokens, i + 1, json_chunk, &out_material->volume);
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_sheen") == 0)
+ {
+ out_material->has_sheen = 1;
+ i = cgltf_parse_json_sheen(options, tokens, i + 1, json_chunk, &out_material->sheen);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "KHR_materials_emissive_strength") == 0)
+ {
+ out_material->has_emissive_strength = 1;
+ i = cgltf_parse_json_emissive_strength(tokens, i + 1, json_chunk, &out_material->emissive_strength);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "KHR_materials_iridescence") == 0)
+ {
+ 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_anisotropy") == 0)
+ {
+ out_material->has_anisotropy = 1;
+ i = cgltf_parse_json_anisotropy(options, tokens, i + 1, json_chunk, &out_material->anisotropy);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "KHR_materials_dispersion") == 0)
+ {
+ out_material->has_dispersion = 1;
+ i = cgltf_parse_json_dispersion(tokens, i + 1, json_chunk, &out_material->dispersion);
+ }
+ else
+ {
+ i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_material->extensions[out_material->extensions_count++]));
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i+1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+
+ return i;
+}
+
+static int cgltf_parse_json_accessors(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
+{
+ i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_accessor), (void**)&out_data->accessors, &out_data->accessors_count);
+ if (i < 0)
+ {
+ return i;
+ }
+
+ for (cgltf_size j = 0; j < out_data->accessors_count; ++j)
+ {
+ i = cgltf_parse_json_accessor(options, tokens, i, json_chunk, &out_data->accessors[j]);
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+ return i;
+}
+
+static int cgltf_parse_json_materials(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
+{
+ i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_material), (void**)&out_data->materials, &out_data->materials_count);
+ if (i < 0)
+ {
+ return i;
+ }
+
+ for (cgltf_size j = 0; j < out_data->materials_count; ++j)
+ {
+ i = cgltf_parse_json_material(options, tokens, i, json_chunk, &out_data->materials[j]);
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+ return i;
+}
+
+static int cgltf_parse_json_images(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
+{
+ i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_image), (void**)&out_data->images, &out_data->images_count);
+ if (i < 0)
+ {
+ return i;
+ }
+
+ for (cgltf_size j = 0; j < out_data->images_count; ++j)
+ {
+ i = cgltf_parse_json_image(options, tokens, i, json_chunk, &out_data->images[j]);
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+ return i;
+}
+
+static int cgltf_parse_json_textures(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
+{
+ i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_texture), (void**)&out_data->textures, &out_data->textures_count);
+ if (i < 0)
+ {
+ return i;
+ }
+
+ for (cgltf_size j = 0; j < out_data->textures_count; ++j)
+ {
+ i = cgltf_parse_json_texture(options, tokens, i, json_chunk, &out_data->textures[j]);
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+ return i;
+}
+
+static int cgltf_parse_json_samplers(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
+{
+ i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_sampler), (void**)&out_data->samplers, &out_data->samplers_count);
+ if (i < 0)
+ {
+ return i;
+ }
+
+ for (cgltf_size j = 0; j < out_data->samplers_count; ++j)
+ {
+ i = cgltf_parse_json_sampler(options, tokens, i, json_chunk, &out_data->samplers[j]);
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+ return i;
+}
+
+static int cgltf_parse_json_meshopt_compression(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_meshopt_compression* out_meshopt_compression)
+{
+ (void)options;
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+
+ int size = tokens[i].size;
+ ++i;
+
+ for (int j = 0; j < size; ++j)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens+i, json_chunk, "buffer") == 0)
+ {
+ ++i;
+ out_meshopt_compression->buffer = CGLTF_PTRINDEX(cgltf_buffer, cgltf_json_to_int(tokens + i, json_chunk));
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteOffset") == 0)
+ {
+ ++i;
+ out_meshopt_compression->offset = cgltf_json_to_size(tokens+i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteLength") == 0)
+ {
+ ++i;
+ out_meshopt_compression->size = cgltf_json_to_size(tokens+i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteStride") == 0)
+ {
+ ++i;
+ out_meshopt_compression->stride = cgltf_json_to_size(tokens+i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "count") == 0)
+ {
+ ++i;
+ out_meshopt_compression->count = cgltf_json_to_size(tokens+i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "mode") == 0)
+ {
+ ++i;
+ if (cgltf_json_strcmp(tokens+i, json_chunk, "ATTRIBUTES") == 0)
+ {
+ out_meshopt_compression->mode = cgltf_meshopt_compression_mode_attributes;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "TRIANGLES") == 0)
+ {
+ out_meshopt_compression->mode = cgltf_meshopt_compression_mode_triangles;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "INDICES") == 0)
+ {
+ out_meshopt_compression->mode = cgltf_meshopt_compression_mode_indices;
+ }
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "filter") == 0)
+ {
+ ++i;
+ if (cgltf_json_strcmp(tokens+i, json_chunk, "NONE") == 0)
+ {
+ out_meshopt_compression->filter = cgltf_meshopt_compression_filter_none;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "OCTAHEDRAL") == 0)
+ {
+ out_meshopt_compression->filter = cgltf_meshopt_compression_filter_octahedral;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "QUATERNION") == 0)
+ {
+ out_meshopt_compression->filter = cgltf_meshopt_compression_filter_quaternion;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "EXPONENTIAL") == 0)
+ {
+ out_meshopt_compression->filter = cgltf_meshopt_compression_filter_exponential;
+ }
+ ++i;
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i+1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+
+ return i;
+}
+
+static int cgltf_parse_json_buffer_view(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_buffer_view* out_buffer_view)
+{
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+
+ int size = tokens[i].size;
+ ++i;
+
+ for (int j = 0; j < size; ++j)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens + i, json_chunk, "name") == 0)
+ {
+ i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_buffer_view->name);
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "buffer") == 0)
+ {
+ ++i;
+ out_buffer_view->buffer = CGLTF_PTRINDEX(cgltf_buffer, cgltf_json_to_int(tokens + i, json_chunk));
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteOffset") == 0)
+ {
+ ++i;
+ out_buffer_view->offset =
+ cgltf_json_to_size(tokens+i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteLength") == 0)
+ {
+ ++i;
+ out_buffer_view->size =
+ cgltf_json_to_size(tokens+i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteStride") == 0)
+ {
+ ++i;
+ out_buffer_view->stride =
+ cgltf_json_to_size(tokens+i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "target") == 0)
+ {
+ ++i;
+ int type = cgltf_json_to_int(tokens+i, json_chunk);
+ switch (type)
+ {
+ case 34962:
+ type = cgltf_buffer_view_type_vertices;
+ break;
+ case 34963:
+ type = cgltf_buffer_view_type_indices;
+ break;
+ default:
+ type = cgltf_buffer_view_type_invalid;
+ break;
+ }
+ out_buffer_view->type = (cgltf_buffer_view_type)type;
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
+ {
+ i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_buffer_view->extras);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
+ {
+ ++i;
+
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+ if(out_buffer_view->extensions)
+ {
+ return CGLTF_ERROR_JSON;
+ }
+
+ int extensions_size = tokens[i].size;
+ out_buffer_view->extensions_count = 0;
+ out_buffer_view->extensions = (cgltf_extension*)cgltf_calloc(options, sizeof(cgltf_extension), extensions_size);
+
+ if (!out_buffer_view->extensions)
+ {
+ return CGLTF_ERROR_NOMEM;
+ }
+
+ ++i;
+ for (int k = 0; k < extensions_size; ++k)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens+i, json_chunk, "EXT_meshopt_compression") == 0)
+ {
+ 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
+ {
+ i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_buffer_view->extensions[out_buffer_view->extensions_count++]));
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i+1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+
+ return i;
+}
+
+static int cgltf_parse_json_buffer_views(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
+{
+ i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_buffer_view), (void**)&out_data->buffer_views, &out_data->buffer_views_count);
+ if (i < 0)
+ {
+ return i;
+ }
+
+ for (cgltf_size j = 0; j < out_data->buffer_views_count; ++j)
+ {
+ i = cgltf_parse_json_buffer_view(options, tokens, i, json_chunk, &out_data->buffer_views[j]);
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+ return i;
+}
+
+static int cgltf_parse_json_buffer(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_buffer* out_buffer)
+{
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+
+ int size = tokens[i].size;
+ ++i;
+
+ for (int j = 0; j < size; ++j)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens + i, json_chunk, "name") == 0)
+ {
+ i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_buffer->name);
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "byteLength") == 0)
+ {
+ ++i;
+ out_buffer->size =
+ cgltf_json_to_size(tokens+i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "uri") == 0)
+ {
+ i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_buffer->uri);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
+ {
+ i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_buffer->extras);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
+ {
+ i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_buffer->extensions_count, &out_buffer->extensions);
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i+1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+
+ return i;
+}
+
+static int cgltf_parse_json_buffers(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
+{
+ i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_buffer), (void**)&out_data->buffers, &out_data->buffers_count);
+ if (i < 0)
+ {
+ return i;
+ }
+
+ for (cgltf_size j = 0; j < out_data->buffers_count; ++j)
+ {
+ i = cgltf_parse_json_buffer(options, tokens, i, json_chunk, &out_data->buffers[j]);
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+ return i;
+}
+
+static int cgltf_parse_json_skin(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_skin* out_skin)
+{
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+
+ int size = tokens[i].size;
+ ++i;
+
+ for (int j = 0; j < size; ++j)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens+i, json_chunk, "name") == 0)
+ {
+ i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_skin->name);
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "joints") == 0)
+ {
+ i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk, sizeof(cgltf_node*), (void**)&out_skin->joints, &out_skin->joints_count);
+ if (i < 0)
+ {
+ return i;
+ }
+
+ for (cgltf_size k = 0; k < out_skin->joints_count; ++k)
+ {
+ out_skin->joints[k] = CGLTF_PTRINDEX(cgltf_node, cgltf_json_to_int(tokens + i, json_chunk));
+ ++i;
+ }
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "skeleton") == 0)
+ {
+ ++i;
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
+ out_skin->skeleton = CGLTF_PTRINDEX(cgltf_node, cgltf_json_to_int(tokens + i, json_chunk));
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "inverseBindMatrices") == 0)
+ {
+ ++i;
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
+ out_skin->inverse_bind_matrices = CGLTF_PTRINDEX(cgltf_accessor, cgltf_json_to_int(tokens + i, json_chunk));
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
+ {
+ i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_skin->extras);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
+ {
+ i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_skin->extensions_count, &out_skin->extensions);
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i+1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+
+ return i;
+}
+
+static int cgltf_parse_json_skins(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
+{
+ i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_skin), (void**)&out_data->skins, &out_data->skins_count);
+ if (i < 0)
+ {
+ return i;
+ }
+
+ for (cgltf_size j = 0; j < out_data->skins_count; ++j)
+ {
+ i = cgltf_parse_json_skin(options, tokens, i, json_chunk, &out_data->skins[j]);
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+ return i;
+}
+
+static int cgltf_parse_json_camera(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_camera* out_camera)
+{
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+
+ int size = tokens[i].size;
+ ++i;
+
+ for (int j = 0; j < size; ++j)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens+i, json_chunk, "name") == 0)
+ {
+ i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_camera->name);
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "perspective") == 0)
+ {
+ ++i;
+
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+
+ int data_size = tokens[i].size;
+ ++i;
+
+ if (out_camera->type != cgltf_camera_type_invalid)
+ {
+ return CGLTF_ERROR_JSON;
+ }
+
+ out_camera->type = cgltf_camera_type_perspective;
+
+ for (int k = 0; k < data_size; ++k)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens+i, json_chunk, "aspectRatio") == 0)
+ {
+ ++i;
+ out_camera->data.perspective.has_aspect_ratio = 1;
+ out_camera->data.perspective.aspect_ratio = cgltf_json_to_float(tokens + i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "yfov") == 0)
+ {
+ ++i;
+ out_camera->data.perspective.yfov = cgltf_json_to_float(tokens + i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "zfar") == 0)
+ {
+ ++i;
+ out_camera->data.perspective.has_zfar = 1;
+ out_camera->data.perspective.zfar = cgltf_json_to_float(tokens + i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "znear") == 0)
+ {
+ ++i;
+ out_camera->data.perspective.znear = cgltf_json_to_float(tokens + i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
+ {
+ i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_camera->data.perspective.extras);
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i+1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "orthographic") == 0)
+ {
+ ++i;
+
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+
+ int data_size = tokens[i].size;
+ ++i;
+
+ if (out_camera->type != cgltf_camera_type_invalid)
+ {
+ return CGLTF_ERROR_JSON;
+ }
+
+ out_camera->type = cgltf_camera_type_orthographic;
+
+ for (int k = 0; k < data_size; ++k)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens+i, json_chunk, "xmag") == 0)
+ {
+ ++i;
+ out_camera->data.orthographic.xmag = cgltf_json_to_float(tokens + i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "ymag") == 0)
+ {
+ ++i;
+ out_camera->data.orthographic.ymag = cgltf_json_to_float(tokens + i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "zfar") == 0)
+ {
+ ++i;
+ out_camera->data.orthographic.zfar = cgltf_json_to_float(tokens + i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "znear") == 0)
+ {
+ ++i;
+ out_camera->data.orthographic.znear = cgltf_json_to_float(tokens + i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
+ {
+ i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_camera->data.orthographic.extras);
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i+1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
+ {
+ i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_camera->extras);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
+ {
+ i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_camera->extensions_count, &out_camera->extensions);
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i+1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+
+ return i;
+}
+
+static int cgltf_parse_json_cameras(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
+{
+ i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_camera), (void**)&out_data->cameras, &out_data->cameras_count);
+ if (i < 0)
+ {
+ return i;
+ }
+
+ for (cgltf_size j = 0; j < out_data->cameras_count; ++j)
+ {
+ i = cgltf_parse_json_camera(options, tokens, i, json_chunk, &out_data->cameras[j]);
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+ return i;
+}
+
+static int cgltf_parse_json_light(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_light* out_light)
+{
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+
+ out_light->color[0] = 1.f;
+ out_light->color[1] = 1.f;
+ out_light->color[2] = 1.f;
+ out_light->intensity = 1.f;
+
+ out_light->spot_inner_cone_angle = 0.f;
+ out_light->spot_outer_cone_angle = 3.1415926535f / 4.0f;
+
+ int size = tokens[i].size;
+ ++i;
+
+ for (int j = 0; j < size; ++j)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens+i, json_chunk, "name") == 0)
+ {
+ i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_light->name);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "color") == 0)
+ {
+ i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_light->color, 3);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "intensity") == 0)
+ {
+ ++i;
+ out_light->intensity = cgltf_json_to_float(tokens + i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "type") == 0)
+ {
+ ++i;
+ if (cgltf_json_strcmp(tokens + i, json_chunk, "directional") == 0)
+ {
+ out_light->type = cgltf_light_type_directional;
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "point") == 0)
+ {
+ out_light->type = cgltf_light_type_point;
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "spot") == 0)
+ {
+ out_light->type = cgltf_light_type_spot;
+ }
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "range") == 0)
+ {
+ ++i;
+ out_light->range = cgltf_json_to_float(tokens + i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "spot") == 0)
+ {
+ ++i;
+
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+
+ int data_size = tokens[i].size;
+ ++i;
+
+ for (int k = 0; k < data_size; ++k)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens+i, json_chunk, "innerConeAngle") == 0)
+ {
+ ++i;
+ out_light->spot_inner_cone_angle = cgltf_json_to_float(tokens + i, json_chunk);
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "outerConeAngle") == 0)
+ {
+ ++i;
+ out_light->spot_outer_cone_angle = cgltf_json_to_float(tokens + i, json_chunk);
+ ++i;
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i+1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
+ {
+ i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_light->extras);
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i+1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+
+ return i;
+}
+
+static int cgltf_parse_json_lights(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
+{
+ i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_light), (void**)&out_data->lights, &out_data->lights_count);
+ if (i < 0)
+ {
+ return i;
+ }
+
+ for (cgltf_size j = 0; j < out_data->lights_count; ++j)
+ {
+ i = cgltf_parse_json_light(options, tokens, i, json_chunk, &out_data->lights[j]);
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+ return i;
+}
+
+static int cgltf_parse_json_node(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_node* out_node)
+{
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+
+ out_node->rotation[3] = 1.0f;
+ out_node->scale[0] = 1.0f;
+ out_node->scale[1] = 1.0f;
+ out_node->scale[2] = 1.0f;
+ out_node->matrix[0] = 1.0f;
+ out_node->matrix[5] = 1.0f;
+ out_node->matrix[10] = 1.0f;
+ out_node->matrix[15] = 1.0f;
+
+ int size = tokens[i].size;
+ ++i;
+
+ for (int j = 0; j < size; ++j)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens+i, json_chunk, "name") == 0)
+ {
+ i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_node->name);
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "children") == 0)
+ {
+ i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk, sizeof(cgltf_node*), (void**)&out_node->children, &out_node->children_count);
+ if (i < 0)
+ {
+ return i;
+ }
+
+ for (cgltf_size k = 0; k < out_node->children_count; ++k)
+ {
+ out_node->children[k] = CGLTF_PTRINDEX(cgltf_node, cgltf_json_to_int(tokens + i, json_chunk));
+ ++i;
+ }
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "mesh") == 0)
+ {
+ ++i;
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
+ out_node->mesh = CGLTF_PTRINDEX(cgltf_mesh, cgltf_json_to_int(tokens + i, json_chunk));
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "skin") == 0)
+ {
+ ++i;
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
+ out_node->skin = CGLTF_PTRINDEX(cgltf_skin, cgltf_json_to_int(tokens + i, json_chunk));
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "camera") == 0)
+ {
+ ++i;
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
+ out_node->camera = CGLTF_PTRINDEX(cgltf_camera, cgltf_json_to_int(tokens + i, json_chunk));
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "translation") == 0)
+ {
+ out_node->has_translation = 1;
+ i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_node->translation, 3);
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "rotation") == 0)
+ {
+ out_node->has_rotation = 1;
+ i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_node->rotation, 4);
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "scale") == 0)
+ {
+ out_node->has_scale = 1;
+ i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_node->scale, 3);
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "matrix") == 0)
+ {
+ out_node->has_matrix = 1;
+ i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_node->matrix, 16);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "weights") == 0)
+ {
+ i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk, sizeof(cgltf_float), (void**)&out_node->weights, &out_node->weights_count);
+ if (i < 0)
+ {
+ return i;
+ }
+
+ i = cgltf_parse_json_float_array(tokens, i - 1, json_chunk, out_node->weights, (int)out_node->weights_count);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
+ {
+ i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_node->extras);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
+ {
+ ++i;
+
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+ if(out_node->extensions)
+ {
+ return CGLTF_ERROR_JSON;
+ }
+
+ int extensions_size = tokens[i].size;
+ out_node->extensions_count= 0;
+ out_node->extensions = (cgltf_extension*)cgltf_calloc(options, sizeof(cgltf_extension), extensions_size);
+
+ if (!out_node->extensions)
+ {
+ return CGLTF_ERROR_NOMEM;
+ }
+
+ ++i;
+
+ for (int k = 0; k < extensions_size; ++k)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_lights_punctual") == 0)
+ {
+ ++i;
+
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+
+ int data_size = tokens[i].size;
+ ++i;
+
+ for (int m = 0; m < data_size; ++m)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens + i, json_chunk, "light") == 0)
+ {
+ ++i;
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_PRIMITIVE);
+ out_node->light = CGLTF_PTRINDEX(cgltf_light, cgltf_json_to_int(tokens + i, json_chunk));
+ ++i;
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i + 1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "EXT_mesh_gpu_instancing") == 0)
+ {
+ out_node->has_mesh_gpu_instancing = 1;
+ i = cgltf_parse_json_mesh_gpu_instancing(options, tokens, i + 1, json_chunk, &out_node->mesh_gpu_instancing);
+ }
+ else
+ {
+ i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_node->extensions[out_node->extensions_count++]));
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i+1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+
+ return i;
+}
+
+static int cgltf_parse_json_nodes(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
+{
+ i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_node), (void**)&out_data->nodes, &out_data->nodes_count);
+ if (i < 0)
+ {
+ return i;
+ }
+
+ for (cgltf_size j = 0; j < out_data->nodes_count; ++j)
+ {
+ i = cgltf_parse_json_node(options, tokens, i, json_chunk, &out_data->nodes[j]);
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+ return i;
+}
+
+static int cgltf_parse_json_scene(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_scene* out_scene)
+{
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+
+ int size = tokens[i].size;
+ ++i;
+
+ for (int j = 0; j < size; ++j)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens+i, json_chunk, "name") == 0)
+ {
+ i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_scene->name);
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "nodes") == 0)
+ {
+ i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk, sizeof(cgltf_node*), (void**)&out_scene->nodes, &out_scene->nodes_count);
+ if (i < 0)
+ {
+ return i;
+ }
+
+ for (cgltf_size k = 0; k < out_scene->nodes_count; ++k)
+ {
+ out_scene->nodes[k] = CGLTF_PTRINDEX(cgltf_node, cgltf_json_to_int(tokens + i, json_chunk));
+ ++i;
+ }
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
+ {
+ i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_scene->extras);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
+ {
+ i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_scene->extensions_count, &out_scene->extensions);
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i+1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+
+ return i;
+}
+
+static int cgltf_parse_json_scenes(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
+{
+ i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_scene), (void**)&out_data->scenes, &out_data->scenes_count);
+ if (i < 0)
+ {
+ return i;
+ }
+
+ for (cgltf_size j = 0; j < out_data->scenes_count; ++j)
+ {
+ i = cgltf_parse_json_scene(options, tokens, i, json_chunk, &out_data->scenes[j]);
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+ return i;
+}
+
+static int cgltf_parse_json_animation_sampler(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_animation_sampler* out_sampler)
+{
+ (void)options;
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+
+ int size = tokens[i].size;
+ ++i;
+
+ for (int j = 0; j < size; ++j)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens+i, json_chunk, "input") == 0)
+ {
+ ++i;
+ out_sampler->input = CGLTF_PTRINDEX(cgltf_accessor, cgltf_json_to_int(tokens + i, json_chunk));
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "output") == 0)
+ {
+ ++i;
+ out_sampler->output = CGLTF_PTRINDEX(cgltf_accessor, cgltf_json_to_int(tokens + i, json_chunk));
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "interpolation") == 0)
+ {
+ ++i;
+ if (cgltf_json_strcmp(tokens + i, json_chunk, "LINEAR") == 0)
+ {
+ out_sampler->interpolation = cgltf_interpolation_type_linear;
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "STEP") == 0)
+ {
+ out_sampler->interpolation = cgltf_interpolation_type_step;
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "CUBICSPLINE") == 0)
+ {
+ out_sampler->interpolation = cgltf_interpolation_type_cubic_spline;
+ }
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
+ {
+ i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_sampler->extras);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
+ {
+ i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_sampler->extensions_count, &out_sampler->extensions);
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i+1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+
+ return i;
+}
+
+static int cgltf_parse_json_animation_channel(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_animation_channel* out_channel)
+{
+ (void)options;
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+
+ int size = tokens[i].size;
+ ++i;
+
+ for (int j = 0; j < size; ++j)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens+i, json_chunk, "sampler") == 0)
+ {
+ ++i;
+ out_channel->sampler = CGLTF_PTRINDEX(cgltf_animation_sampler, cgltf_json_to_int(tokens + i, json_chunk));
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "target") == 0)
+ {
+ ++i;
+
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+
+ int target_size = tokens[i].size;
+ ++i;
+
+ for (int k = 0; k < target_size; ++k)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens+i, json_chunk, "node") == 0)
+ {
+ ++i;
+ out_channel->target_node = CGLTF_PTRINDEX(cgltf_node, cgltf_json_to_int(tokens + i, json_chunk));
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "path") == 0)
+ {
+ ++i;
+ if (cgltf_json_strcmp(tokens+i, json_chunk, "translation") == 0)
+ {
+ out_channel->target_path = cgltf_animation_path_type_translation;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "rotation") == 0)
+ {
+ out_channel->target_path = cgltf_animation_path_type_rotation;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "scale") == 0)
+ {
+ out_channel->target_path = cgltf_animation_path_type_scale;
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "weights") == 0)
+ {
+ out_channel->target_path = cgltf_animation_path_type_weights;
+ }
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
+ {
+ i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_channel->extras);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
+ {
+ i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_channel->extensions_count, &out_channel->extensions);
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i+1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i+1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+
+ return i;
+}
+
+static int cgltf_parse_json_animation(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_animation* out_animation)
+{
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+
+ int size = tokens[i].size;
+ ++i;
+
+ for (int j = 0; j < size; ++j)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens+i, json_chunk, "name") == 0)
+ {
+ i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_animation->name);
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "samplers") == 0)
+ {
+ i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk, sizeof(cgltf_animation_sampler), (void**)&out_animation->samplers, &out_animation->samplers_count);
+ if (i < 0)
+ {
+ return i;
+ }
+
+ for (cgltf_size k = 0; k < out_animation->samplers_count; ++k)
+ {
+ i = cgltf_parse_json_animation_sampler(options, tokens, i, json_chunk, &out_animation->samplers[k]);
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "channels") == 0)
+ {
+ i = cgltf_parse_json_array(options, tokens, i + 1, json_chunk, sizeof(cgltf_animation_channel), (void**)&out_animation->channels, &out_animation->channels_count);
+ if (i < 0)
+ {
+ return i;
+ }
+
+ for (cgltf_size k = 0; k < out_animation->channels_count; ++k)
+ {
+ i = cgltf_parse_json_animation_channel(options, tokens, i, json_chunk, &out_animation->channels[k]);
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
+ {
+ i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_animation->extras);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
+ {
+ i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_animation->extensions_count, &out_animation->extensions);
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i+1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+
+ return i;
+}
+
+static int cgltf_parse_json_animations(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
+{
+ i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_animation), (void**)&out_data->animations, &out_data->animations_count);
+ if (i < 0)
+ {
+ return i;
+ }
+
+ for (cgltf_size j = 0; j < out_data->animations_count; ++j)
+ {
+ i = cgltf_parse_json_animation(options, tokens, i, json_chunk, &out_data->animations[j]);
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+ return i;
+}
+
+static int cgltf_parse_json_variant(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_material_variant* out_variant)
+{
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+
+ int size = tokens[i].size;
+ ++i;
+
+ for (int j = 0; j < size; ++j)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens+i, json_chunk, "name") == 0)
+ {
+ i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_variant->name);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
+ {
+ i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_variant->extras);
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i+1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+
+ return i;
+}
+
+static int cgltf_parse_json_variants(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
+{
+ i = cgltf_parse_json_array(options, tokens, i, json_chunk, sizeof(cgltf_material_variant), (void**)&out_data->variants, &out_data->variants_count);
+ if (i < 0)
+ {
+ return i;
+ }
+
+ for (cgltf_size j = 0; j < out_data->variants_count; ++j)
+ {
+ i = cgltf_parse_json_variant(options, tokens, i, json_chunk, &out_data->variants[j]);
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+ return i;
+}
+
+static int cgltf_parse_json_asset(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_asset* out_asset)
+{
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+
+ int size = tokens[i].size;
+ ++i;
+
+ for (int j = 0; j < size; ++j)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens+i, json_chunk, "copyright") == 0)
+ {
+ i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_asset->copyright);
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "generator") == 0)
+ {
+ i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_asset->generator);
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "version") == 0)
+ {
+ i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_asset->version);
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "minVersion") == 0)
+ {
+ i = cgltf_parse_json_string(options, tokens, i + 1, json_chunk, &out_asset->min_version);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
+ {
+ i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_asset->extras);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
+ {
+ i = cgltf_parse_json_unprocessed_extensions(options, tokens, i, json_chunk, &out_asset->extensions_count, &out_asset->extensions);
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i+1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+
+ if (out_asset->version && CGLTF_ATOF(out_asset->version) < 2)
+ {
+ return CGLTF_ERROR_LEGACY;
+ }
+
+ return i;
+}
+
+cgltf_size cgltf_num_components(cgltf_type type) {
+ switch (type)
+ {
+ case cgltf_type_vec2:
+ return 2;
+ case cgltf_type_vec3:
+ return 3;
+ case cgltf_type_vec4:
+ return 4;
+ case cgltf_type_mat2:
+ return 4;
+ case cgltf_type_mat3:
+ return 9;
+ case cgltf_type_mat4:
+ return 16;
+ case cgltf_type_invalid:
+ case cgltf_type_scalar:
+ default:
+ return 1;
+ }
+}
+
+cgltf_size cgltf_component_size(cgltf_component_type component_type) {
+ switch (component_type)
+ {
+ case cgltf_component_type_r_8:
+ case cgltf_component_type_r_8u:
+ return 1;
+ case cgltf_component_type_r_16:
+ case cgltf_component_type_r_16u:
+ return 2;
+ case cgltf_component_type_r_32u:
+ case cgltf_component_type_r_32f:
+ return 4;
+ case cgltf_component_type_invalid:
+ default:
+ return 0;
+ }
+}
+
+cgltf_size cgltf_calc_size(cgltf_type type, cgltf_component_type component_type)
+{
+ cgltf_size component_size = cgltf_component_size(component_type);
+ if (type == cgltf_type_mat2 && component_size == 1)
+ {
+ return 8 * component_size;
+ }
+ else if (type == cgltf_type_mat3 && (component_size == 1 || component_size == 2))
+ {
+ return 12 * component_size;
+ }
+ return component_size * cgltf_num_components(type);
+}
+
+static int cgltf_fixup_pointers(cgltf_data* out_data);
+
+static int cgltf_parse_json_root(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_data* out_data)
+{
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+
+ int size = tokens[i].size;
+ ++i;
+
+ for (int j = 0; j < size; ++j)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens + i, json_chunk, "asset") == 0)
+ {
+ i = cgltf_parse_json_asset(options, tokens, i + 1, json_chunk, &out_data->asset);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "meshes") == 0)
+ {
+ i = cgltf_parse_json_meshes(options, tokens, i + 1, json_chunk, out_data);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "accessors") == 0)
+ {
+ i = cgltf_parse_json_accessors(options, tokens, i + 1, json_chunk, out_data);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "bufferViews") == 0)
+ {
+ i = cgltf_parse_json_buffer_views(options, tokens, i + 1, json_chunk, out_data);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "buffers") == 0)
+ {
+ i = cgltf_parse_json_buffers(options, tokens, i + 1, json_chunk, out_data);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "materials") == 0)
+ {
+ i = cgltf_parse_json_materials(options, tokens, i + 1, json_chunk, out_data);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "images") == 0)
+ {
+ i = cgltf_parse_json_images(options, tokens, i + 1, json_chunk, out_data);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "textures") == 0)
+ {
+ i = cgltf_parse_json_textures(options, tokens, i + 1, json_chunk, out_data);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "samplers") == 0)
+ {
+ i = cgltf_parse_json_samplers(options, tokens, i + 1, json_chunk, out_data);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "skins") == 0)
+ {
+ i = cgltf_parse_json_skins(options, tokens, i + 1, json_chunk, out_data);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "cameras") == 0)
+ {
+ i = cgltf_parse_json_cameras(options, tokens, i + 1, json_chunk, out_data);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "nodes") == 0)
+ {
+ i = cgltf_parse_json_nodes(options, tokens, i + 1, json_chunk, out_data);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "scenes") == 0)
+ {
+ i = cgltf_parse_json_scenes(options, tokens, i + 1, json_chunk, out_data);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "scene") == 0)
+ {
+ ++i;
+ out_data->scene = CGLTF_PTRINDEX(cgltf_scene, cgltf_json_to_int(tokens + i, json_chunk));
+ ++i;
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "animations") == 0)
+ {
+ i = cgltf_parse_json_animations(options, tokens, i + 1, json_chunk, out_data);
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "extras") == 0)
+ {
+ i = cgltf_parse_json_extras(options, tokens, i + 1, json_chunk, &out_data->extras);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensions") == 0)
+ {
+ ++i;
+
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+ if(out_data->data_extensions)
+ {
+ return CGLTF_ERROR_JSON;
+ }
+
+ int extensions_size = tokens[i].size;
+ out_data->data_extensions_count = 0;
+ out_data->data_extensions = (cgltf_extension*)cgltf_calloc(options, sizeof(cgltf_extension), extensions_size);
+
+ if (!out_data->data_extensions)
+ {
+ return CGLTF_ERROR_NOMEM;
+ }
+
+ ++i;
+
+ for (int k = 0; k < extensions_size; ++k)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_lights_punctual") == 0)
+ {
+ ++i;
+
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+
+ int data_size = tokens[i].size;
+ ++i;
+
+ for (int m = 0; m < data_size; ++m)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens + i, json_chunk, "lights") == 0)
+ {
+ i = cgltf_parse_json_lights(options, tokens, i + 1, json_chunk, out_data);
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i + 1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+ }
+ else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_materials_variants") == 0)
+ {
+ ++i;
+
+ CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
+
+ int data_size = tokens[i].size;
+ ++i;
+
+ for (int m = 0; m < data_size; ++m)
+ {
+ CGLTF_CHECK_KEY(tokens[i]);
+
+ if (cgltf_json_strcmp(tokens + i, json_chunk, "variants") == 0)
+ {
+ i = cgltf_parse_json_variants(options, tokens, i + 1, json_chunk, out_data);
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i + 1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+ }
+ else
+ {
+ i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_data->data_extensions[out_data->data_extensions_count++]));
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensionsUsed") == 0)
+ {
+ i = cgltf_parse_json_string_array(options, tokens, i + 1, json_chunk, &out_data->extensions_used, &out_data->extensions_used_count);
+ }
+ else if (cgltf_json_strcmp(tokens + i, json_chunk, "extensionsRequired") == 0)
+ {
+ i = cgltf_parse_json_string_array(options, tokens, i + 1, json_chunk, &out_data->extensions_required, &out_data->extensions_required_count);
+ }
+ else
+ {
+ i = cgltf_skip_json(tokens, i + 1);
+ }
+
+ if (i < 0)
+ {
+ return i;
+ }
+ }
+
+ return i;
+}
+
+cgltf_result cgltf_parse_json(cgltf_options* options, const uint8_t* json_chunk, cgltf_size size, cgltf_data** out_data)
+{
+ jsmn_parser parser = { 0, 0, 0 };
+
+ if (options->json_token_count == 0)
+ {
+ int token_count = jsmn_parse(&parser, (const char*)json_chunk, size, NULL, 0);
+
+ if (token_count <= 0)
+ {
+ return cgltf_result_invalid_json;
+ }
+
+ options->json_token_count = token_count;
+ }
+
+ jsmntok_t* tokens = (jsmntok_t*)options->memory.alloc_func(options->memory.user_data, sizeof(jsmntok_t) * (options->json_token_count + 1));
+
+ if (!tokens)
+ {
+ return cgltf_result_out_of_memory;
+ }
+
+ jsmn_init(&parser);
+
+ int token_count = jsmn_parse(&parser, (const char*)json_chunk, size, tokens, options->json_token_count);
+
+ if (token_count <= 0)
+ {
+ options->memory.free_func(options->memory.user_data, tokens);
+ return cgltf_result_invalid_json;
+ }
+
+ // this makes sure that we always have an UNDEFINED token at the end of the stream
+ // for invalid JSON inputs this makes sure we don't perform out of bound reads of token data
+ tokens[token_count].type = JSMN_UNDEFINED;
+
+ cgltf_data* data = (cgltf_data*)options->memory.alloc_func(options->memory.user_data, sizeof(cgltf_data));
+
+ if (!data)
+ {
+ options->memory.free_func(options->memory.user_data, tokens);
+ return cgltf_result_out_of_memory;
+ }
+
+ memset(data, 0, sizeof(cgltf_data));
+ data->memory = options->memory;
+ data->file = options->file;
+
+ int i = cgltf_parse_json_root(options, tokens, 0, json_chunk, data);
+
+ options->memory.free_func(options->memory.user_data, tokens);
+
+ if (i < 0)
+ {
+ cgltf_free(data);
+
+ switch (i)
+ {
+ case CGLTF_ERROR_NOMEM: return cgltf_result_out_of_memory;
+ case CGLTF_ERROR_LEGACY: return cgltf_result_legacy_gltf;
+ default: return cgltf_result_invalid_gltf;
+ }
+ }
+
+ if (cgltf_fixup_pointers(data) < 0)
+ {
+ cgltf_free(data);
+ return cgltf_result_invalid_gltf;
+ }
+
+ data->json = (const char*)json_chunk;
+ data->json_size = size;
+
+ *out_data = data;
+
+ return cgltf_result_success;
+}
+
+static int cgltf_fixup_pointers(cgltf_data* data)
+{
+ for (cgltf_size i = 0; i < data->meshes_count; ++i)
+ {
+ for (cgltf_size j = 0; j < data->meshes[i].primitives_count; ++j)
+ {
+ CGLTF_PTRFIXUP(data->meshes[i].primitives[j].indices, data->accessors, data->accessors_count);
+ CGLTF_PTRFIXUP(data->meshes[i].primitives[j].material, data->materials, data->materials_count);
+
+ for (cgltf_size k = 0; k < data->meshes[i].primitives[j].attributes_count; ++k)
+ {
+ CGLTF_PTRFIXUP_REQ(data->meshes[i].primitives[j].attributes[k].data, data->accessors, data->accessors_count);
+ }
+
+ for (cgltf_size k = 0; k < data->meshes[i].primitives[j].targets_count; ++k)
+ {
+ for (cgltf_size m = 0; m < data->meshes[i].primitives[j].targets[k].attributes_count; ++m)
+ {
+ CGLTF_PTRFIXUP_REQ(data->meshes[i].primitives[j].targets[k].attributes[m].data, data->accessors, data->accessors_count);
+ }
+ }
+
+ if (data->meshes[i].primitives[j].has_draco_mesh_compression)
+ {
+ CGLTF_PTRFIXUP_REQ(data->meshes[i].primitives[j].draco_mesh_compression.buffer_view, data->buffer_views, data->buffer_views_count);
+ for (cgltf_size m = 0; m < data->meshes[i].primitives[j].draco_mesh_compression.attributes_count; ++m)
+ {
+ CGLTF_PTRFIXUP_REQ(data->meshes[i].primitives[j].draco_mesh_compression.attributes[m].data, data->accessors, data->accessors_count);
+ }
+ }
+
+ for (cgltf_size k = 0; k < data->meshes[i].primitives[j].mappings_count; ++k)
+ {
+ CGLTF_PTRFIXUP_REQ(data->meshes[i].primitives[j].mappings[k].material, data->materials, data->materials_count);
+ }
+ }
+ }
+
+ for (cgltf_size i = 0; i < data->accessors_count; ++i)
+ {
+ CGLTF_PTRFIXUP(data->accessors[i].buffer_view, data->buffer_views, data->buffer_views_count);
+
+ if (data->accessors[i].is_sparse)
+ {
+ CGLTF_PTRFIXUP_REQ(data->accessors[i].sparse.indices_buffer_view, data->buffer_views, data->buffer_views_count);
+ CGLTF_PTRFIXUP_REQ(data->accessors[i].sparse.values_buffer_view, data->buffer_views, data->buffer_views_count);
+ }
+
+ if (data->accessors[i].buffer_view)
+ {
+ data->accessors[i].stride = data->accessors[i].buffer_view->stride;
+ }
+
+ if (data->accessors[i].stride == 0)
+ {
+ data->accessors[i].stride = cgltf_calc_size(data->accessors[i].type, data->accessors[i].component_type);
+ }
+ }
+
+ for (cgltf_size i = 0; i < data->textures_count; ++i)
+ {
+ CGLTF_PTRFIXUP(data->textures[i].image, data->images, data->images_count);
+ CGLTF_PTRFIXUP(data->textures[i].basisu_image, data->images, data->images_count);
+ CGLTF_PTRFIXUP(data->textures[i].webp_image, data->images, data->images_count);
+ CGLTF_PTRFIXUP(data->textures[i].sampler, data->samplers, data->samplers_count);
+ }
+
+ for (cgltf_size i = 0; i < data->images_count; ++i)
+ {
+ CGLTF_PTRFIXUP(data->images[i].buffer_view, data->buffer_views, data->buffer_views_count);
+ }
+
+ for (cgltf_size i = 0; i < data->materials_count; ++i)
+ {
+ CGLTF_PTRFIXUP(data->materials[i].normal_texture.texture, data->textures, data->textures_count);
+ CGLTF_PTRFIXUP(data->materials[i].emissive_texture.texture, data->textures, data->textures_count);
+ CGLTF_PTRFIXUP(data->materials[i].occlusion_texture.texture, data->textures, data->textures_count);
+
+ CGLTF_PTRFIXUP(data->materials[i].pbr_metallic_roughness.base_color_texture.texture, data->textures, data->textures_count);
+ CGLTF_PTRFIXUP(data->materials[i].pbr_metallic_roughness.metallic_roughness_texture.texture, data->textures, data->textures_count);
+
+ CGLTF_PTRFIXUP(data->materials[i].pbr_specular_glossiness.diffuse_texture.texture, data->textures, data->textures_count);
+ CGLTF_PTRFIXUP(data->materials[i].pbr_specular_glossiness.specular_glossiness_texture.texture, data->textures, data->textures_count);
+
+ CGLTF_PTRFIXUP(data->materials[i].clearcoat.clearcoat_texture.texture, data->textures, data->textures_count);
+ CGLTF_PTRFIXUP(data->materials[i].clearcoat.clearcoat_roughness_texture.texture, data->textures, data->textures_count);
+ CGLTF_PTRFIXUP(data->materials[i].clearcoat.clearcoat_normal_texture.texture, data->textures, data->textures_count);
+
+ CGLTF_PTRFIXUP(data->materials[i].specular.specular_texture.texture, data->textures, data->textures_count);
+ CGLTF_PTRFIXUP(data->materials[i].specular.specular_color_texture.texture, data->textures, data->textures_count);
+
+ CGLTF_PTRFIXUP(data->materials[i].transmission.transmission_texture.texture, data->textures, data->textures_count);
+
+ CGLTF_PTRFIXUP(data->materials[i].volume.thickness_texture.texture, data->textures, data->textures_count);
+
+ CGLTF_PTRFIXUP(data->materials[i].sheen.sheen_color_texture.texture, data->textures, data->textures_count);
+ CGLTF_PTRFIXUP(data->materials[i].sheen.sheen_roughness_texture.texture, data->textures, data->textures_count);
+
+ 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].anisotropy.anisotropy_texture.texture, data->textures, data->textures_count);
+ }
+
+ for (cgltf_size i = 0; i < data->buffer_views_count; ++i)
+ {
+ CGLTF_PTRFIXUP_REQ(data->buffer_views[i].buffer, data->buffers, data->buffers_count);
+
+ if (data->buffer_views[i].has_meshopt_compression)
+ {
+ CGLTF_PTRFIXUP_REQ(data->buffer_views[i].meshopt_compression.buffer, data->buffers, data->buffers_count);
+ }
+ }
+
+ for (cgltf_size i = 0; i < data->skins_count; ++i)
+ {
+ for (cgltf_size j = 0; j < data->skins[i].joints_count; ++j)
+ {
+ CGLTF_PTRFIXUP_REQ(data->skins[i].joints[j], data->nodes, data->nodes_count);
+ }
+
+ CGLTF_PTRFIXUP(data->skins[i].skeleton, data->nodes, data->nodes_count);
+ CGLTF_PTRFIXUP(data->skins[i].inverse_bind_matrices, data->accessors, data->accessors_count);
+ }
+
+ for (cgltf_size i = 0; i < data->nodes_count; ++i)
+ {
+ for (cgltf_size j = 0; j < data->nodes[i].children_count; ++j)
+ {
+ CGLTF_PTRFIXUP_REQ(data->nodes[i].children[j], data->nodes, data->nodes_count);
+
+ if (data->nodes[i].children[j]->parent)
+ {
+ return CGLTF_ERROR_JSON;
+ }
+
+ data->nodes[i].children[j]->parent = &data->nodes[i];
+ }
+
+ CGLTF_PTRFIXUP(data->nodes[i].mesh, data->meshes, data->meshes_count);
+ CGLTF_PTRFIXUP(data->nodes[i].skin, data->skins, data->skins_count);
+ CGLTF_PTRFIXUP(data->nodes[i].camera, data->cameras, data->cameras_count);
+ CGLTF_PTRFIXUP(data->nodes[i].light, data->lights, data->lights_count);
+
+ if (data->nodes[i].has_mesh_gpu_instancing)
+ {
+ for (cgltf_size m = 0; m < data->nodes[i].mesh_gpu_instancing.attributes_count; ++m)
+ {
+ CGLTF_PTRFIXUP_REQ(data->nodes[i].mesh_gpu_instancing.attributes[m].data, data->accessors, data->accessors_count);
+ }
+ }
+ }
+
+ for (cgltf_size i = 0; i < data->scenes_count; ++i)
+ {
+ for (cgltf_size j = 0; j < data->scenes[i].nodes_count; ++j)
+ {
+ CGLTF_PTRFIXUP_REQ(data->scenes[i].nodes[j], data->nodes, data->nodes_count);
+
+ if (data->scenes[i].nodes[j]->parent)
+ {
+ return CGLTF_ERROR_JSON;
+ }
+ }
+ }
+
+ CGLTF_PTRFIXUP(data->scene, data->scenes, data->scenes_count);
+
+ for (cgltf_size i = 0; i < data->animations_count; ++i)
+ {
+ for (cgltf_size j = 0; j < data->animations[i].samplers_count; ++j)
+ {
+ CGLTF_PTRFIXUP_REQ(data->animations[i].samplers[j].input, data->accessors, data->accessors_count);
+ CGLTF_PTRFIXUP_REQ(data->animations[i].samplers[j].output, data->accessors, data->accessors_count);
+ }
+
+ for (cgltf_size j = 0; j < data->animations[i].channels_count; ++j)
+ {
+ CGLTF_PTRFIXUP_REQ(data->animations[i].channels[j].sampler, data->animations[i].samplers, data->animations[i].samplers_count);
+ CGLTF_PTRFIXUP(data->animations[i].channels[j].target_node, data->nodes, data->nodes_count);
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * -- jsmn.c start --
+ * Source: https://github.com/zserge/jsmn
+ * License: MIT
+ *
+ * Copyright (c) 2010 Serge A. Zaitsev
+
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/**
+ * Allocates a fresh unused token from the token pull.
+ */
+static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser,
+ jsmntok_t *tokens, size_t num_tokens) {
+ jsmntok_t *tok;
+ if (parser->toknext >= num_tokens) {
+ return NULL;
+ }
+ tok = &tokens[parser->toknext++];
+ tok->start = tok->end = -1;
+ tok->size = 0;
+#ifdef JSMN_PARENT_LINKS
+ tok->parent = -1;
+#endif
+ return tok;
+}
+
+/**
+ * Fills token type and boundaries.
+ */
+static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type,
+ ptrdiff_t start, ptrdiff_t end) {
+ token->type = type;
+ token->start = start;
+ token->end = end;
+ token->size = 0;
+}
+
+/**
+ * Fills next available token with JSON primitive.
+ */
+static int jsmn_parse_primitive(jsmn_parser *parser, const char *js,
+ size_t len, jsmntok_t *tokens, size_t num_tokens) {
+ jsmntok_t *token;
+ ptrdiff_t start;
+
+ start = parser->pos;
+
+ for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
+ switch (js[parser->pos]) {
+#ifndef JSMN_STRICT
+ /* In strict mode primitive must be followed by "," or "}" or "]" */
+ case ':':
+#endif
+ case '\t' : case '\r' : case '\n' : case ' ' :
+ case ',' : case ']' : case '}' :
+ goto found;
+ }
+ if (js[parser->pos] < 32 || js[parser->pos] >= 127) {
+ parser->pos = start;
+ return JSMN_ERROR_INVAL;
+ }
+ }
+#ifdef JSMN_STRICT
+ /* In strict mode primitive must be followed by a comma/object/array */
+ parser->pos = start;
+ return JSMN_ERROR_PART;
+#endif
+
+found:
+ if (tokens == NULL) {
+ parser->pos--;
+ return 0;
+ }
+ token = jsmn_alloc_token(parser, tokens, num_tokens);
+ if (token == NULL) {
+ parser->pos = start;
+ return JSMN_ERROR_NOMEM;
+ }
+ jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos);
+#ifdef JSMN_PARENT_LINKS
+ token->parent = parser->toksuper;
+#endif
+ parser->pos--;
+ return 0;
+}
+
+/**
+ * Fills next token with JSON string.
+ */
+static int jsmn_parse_string(jsmn_parser *parser, const char *js,
+ size_t len, jsmntok_t *tokens, size_t num_tokens) {
+ jsmntok_t *token;
+
+ ptrdiff_t start = parser->pos;
+
+ parser->pos++;
+
+ /* Skip starting quote */
+ for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
+ char c = js[parser->pos];
+
+ /* Quote: end of string */
+ if (c == '\"') {
+ if (tokens == NULL) {
+ return 0;
+ }
+ token = jsmn_alloc_token(parser, tokens, num_tokens);
+ if (token == NULL) {
+ parser->pos = start;
+ return JSMN_ERROR_NOMEM;
+ }
+ jsmn_fill_token(token, JSMN_STRING, start+1, parser->pos);
+#ifdef JSMN_PARENT_LINKS
+ token->parent = parser->toksuper;
+#endif
+ return 0;
+ }
+
+ /* Backslash: Quoted symbol expected */
+ if (c == '\\' && parser->pos + 1 < len) {
+ int i;
+ parser->pos++;
+ switch (js[parser->pos]) {
+ /* Allowed escaped symbols */
+ case '\"': case '/' : case '\\' : case 'b' :
+ case 'f' : case 'r' : case 'n' : case 't' :
+ break;
+ /* Allows escaped symbol \uXXXX */
+ case 'u':
+ parser->pos++;
+ for(i = 0; i < 4 && parser->pos < len && js[parser->pos] != '\0'; i++) {
+ /* If it isn't a hex character we have an error */
+ if(!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */
+ (js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */
+ (js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */
+ parser->pos = start;
+ return JSMN_ERROR_INVAL;
+ }
+ parser->pos++;
+ }
+ parser->pos--;
+ break;
+ /* Unexpected symbol */
+ default:
+ parser->pos = start;
+ return JSMN_ERROR_INVAL;
+ }
+ }
+ }
+ parser->pos = start;
+ return JSMN_ERROR_PART;
+}
+
+/**
+ * Parse JSON string and fill tokens.
+ */
+static int jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
+ jsmntok_t *tokens, size_t num_tokens) {
+ int r;
+ int i;
+ jsmntok_t *token;
+ int count = parser->toknext;
+
+ for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
+ char c;
+ jsmntype_t type;
+
+ c = js[parser->pos];
+ switch (c) {
+ case '{': case '[':
+ count++;
+ if (tokens == NULL) {
+ break;
+ }
+ token = jsmn_alloc_token(parser, tokens, num_tokens);
+ if (token == NULL)
+ return JSMN_ERROR_NOMEM;
+ if (parser->toksuper != -1) {
+ tokens[parser->toksuper].size++;
+#ifdef JSMN_PARENT_LINKS
+ token->parent = parser->toksuper;
+#endif
+ }
+ token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY);
+ token->start = parser->pos;
+ parser->toksuper = parser->toknext - 1;
+ break;
+ case '}': case ']':
+ if (tokens == NULL)
+ break;
+ type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY);
+#ifdef JSMN_PARENT_LINKS
+ if (parser->toknext < 1) {
+ return JSMN_ERROR_INVAL;
+ }
+ token = &tokens[parser->toknext - 1];
+ for (;;) {
+ if (token->start != -1 && token->end == -1) {
+ if (token->type != type) {
+ return JSMN_ERROR_INVAL;
+ }
+ token->end = parser->pos + 1;
+ parser->toksuper = token->parent;
+ break;
+ }
+ if (token->parent == -1) {
+ if(token->type != type || parser->toksuper == -1) {
+ return JSMN_ERROR_INVAL;
+ }
+ break;
+ }
+ token = &tokens[token->parent];
+ }
+#else
+ for (i = parser->toknext - 1; i >= 0; i--) {
+ token = &tokens[i];
+ if (token->start != -1 && token->end == -1) {
+ if (token->type != type) {
+ return JSMN_ERROR_INVAL;
+ }
+ parser->toksuper = -1;
+ token->end = parser->pos + 1;
+ break;
+ }
+ }
+ /* Error if unmatched closing bracket */
+ if (i == -1) return JSMN_ERROR_INVAL;
+ for (; i >= 0; i--) {
+ token = &tokens[i];
+ if (token->start != -1 && token->end == -1) {
+ parser->toksuper = i;
+ break;
+ }
+ }
+#endif
+ break;
+ case '\"':
+ r = jsmn_parse_string(parser, js, len, tokens, num_tokens);
+ if (r < 0) return r;
+ count++;
+ if (parser->toksuper != -1 && tokens != NULL)
+ tokens[parser->toksuper].size++;
+ break;
+ case '\t' : case '\r' : case '\n' : case ' ':
+ break;
+ case ':':
+ parser->toksuper = parser->toknext - 1;
+ break;
+ case ',':
+ if (tokens != NULL && parser->toksuper != -1 &&
+ tokens[parser->toksuper].type != JSMN_ARRAY &&
+ tokens[parser->toksuper].type != JSMN_OBJECT) {
+#ifdef JSMN_PARENT_LINKS
+ parser->toksuper = tokens[parser->toksuper].parent;
+#else
+ for (i = parser->toknext - 1; i >= 0; i--) {
+ if (tokens[i].type == JSMN_ARRAY || tokens[i].type == JSMN_OBJECT) {
+ if (tokens[i].start != -1 && tokens[i].end == -1) {
+ parser->toksuper = i;
+ break;
+ }
+ }
+ }
+#endif
+ }
+ break;
+#ifdef JSMN_STRICT
+ /* In strict mode primitives are: numbers and booleans */
+ case '-': case '0': case '1' : case '2': case '3' : case '4':
+ case '5': case '6': case '7' : case '8': case '9':
+ case 't': case 'f': case 'n' :
+ /* And they must not be keys of the object */
+ if (tokens != NULL && parser->toksuper != -1) {
+ jsmntok_t *t = &tokens[parser->toksuper];
+ if (t->type == JSMN_OBJECT ||
+ (t->type == JSMN_STRING && t->size != 0)) {
+ return JSMN_ERROR_INVAL;
+ }
+ }
+#else
+ /* In non-strict mode every unquoted value is a primitive */
+ default:
+#endif
+ r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens);
+ if (r < 0) return r;
+ count++;
+ if (parser->toksuper != -1 && tokens != NULL)
+ tokens[parser->toksuper].size++;
+ break;
+
+#ifdef JSMN_STRICT
+ /* Unexpected char in strict mode */
+ default:
+ return JSMN_ERROR_INVAL;
+#endif
+ }
+ }
+
+ if (tokens != NULL) {
+ for (i = parser->toknext - 1; i >= 0; i--) {
+ /* Unmatched opened object or array */
+ if (tokens[i].start != -1 && tokens[i].end == -1) {
+ return JSMN_ERROR_PART;
+ }
+ }
+ }
+
+ return count;
+}
+
+/**
+ * Creates a new parser based over a given buffer with an array of tokens
+ * available.
+ */
+static void jsmn_init(jsmn_parser *parser) {
+ parser->pos = 0;
+ parser->toknext = 0;
+ parser->toksuper = -1;
+}
+/*
+ * -- jsmn.c end --
+ */
+
+#endif /* #ifdef CGLTF_IMPLEMENTATION */
+
+/* cgltf is distributed under MIT license:
+ *
+ * Copyright (c) 2018-2021 Johannes Kuhlmann
+
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
diff --git a/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/dirent.h b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/dirent.h
new file mode 100644
index 0000000..c611376
--- /dev/null
+++ b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/dirent.h
@@ -0,0 +1,183 @@
+/****************************************************************************
+
+ Declaration of POSIX directory browsing functions and types for Win32.
+
+ Author: Kevlin Henney (kevlin@acm.org, kevlin@curbralan.com)
+ History: Created March 1997. Updated June 2003.
+ Reviewed by Ramon Santamaria for raylib on January 2020.
+
+ Copyright Kevlin Henney, 1997, 2003. All rights reserved.
+
+ Permission to use, copy, modify, and distribute this software and its
+ documentation for any purpose is hereby granted without fee, provided
+ that this copyright and permissions notice appear in all copies and
+ derivatives.
+
+ This software is supplied "as is" without express or implied warranty.
+
+ But that said, if there are any problems please get in touch.
+
+****************************************************************************/
+
+#ifndef DIRENT_H
+#define DIRENT_H
+
+// Allow custom memory allocators
+#ifndef DIRENT_MALLOC
+ #define DIRENT_MALLOC(sz) malloc(sz)
+#endif
+#ifndef DIRENT_FREE
+ #define DIRENT_FREE(p) free(p)
+#endif
+
+//----------------------------------------------------------------------------------
+// Types and Structures Definition
+//----------------------------------------------------------------------------------
+
+// Fordward declaration of DIR, implementation below
+typedef struct DIR DIR;
+
+struct dirent {
+ char *d_name;
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//------------------------------------------------------------------------------------
+// Functions Declaration
+//------------------------------------------------------------------------------------
+DIR *opendir(const char *name);
+int closedir(DIR *dir);
+struct dirent *readdir(DIR *dir);
+void rewinddir(DIR *dir);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // DIRENT_H
+
+/****************************************************************************
+
+ Implementation of POSIX directory browsing functions and types for Win32.
+
+ Author: Kevlin Henney (kevlin@acm.org, kevlin@curbralan.com)
+ History: Created March 1997. Updated June 2003.
+ Reviewed by Ramon Santamaria for raylib on January 2020.
+
+ Copyright Kevlin Henney, 1997, 2003. All rights reserved.
+
+ Permission to use, copy, modify, and distribute this software and its
+ documentation for any purpose is hereby granted without fee, provided
+ that this copyright and permissions notice appear in all copies and
+ derivatives.
+
+ This software is supplied "as is" without express or implied warranty.
+
+ But that said, if there are any problems please get in touch.
+
+****************************************************************************/
+
+#include // _findfirst and _findnext set errno iff they return -1
+#include
+#include
+#include
+
+//----------------------------------------------------------------------------------
+// Types and Structures Definition
+//----------------------------------------------------------------------------------
+typedef ptrdiff_t handle_type; // C99's intptr_t not sufficiently portable
+
+struct DIR {
+ handle_type handle; // -1 for failed rewind
+ struct _finddata_t info;
+ struct dirent result; // d_name null iff first time
+ char *name; // null-terminated char string
+};
+
+DIR *opendir(const char *name)
+{
+ DIR *dir = 0;
+
+ if (name && name[0])
+ {
+ size_t base_length = strlen(name);
+
+ // Search pattern must end with suitable wildcard
+ const char *all = strchr("/\\", name[base_length - 1]) ? "*" : "/*";
+
+ if ((dir = (DIR *)DIRENT_MALLOC(sizeof *dir)) != 0 &&
+ (dir->name = (char *)DIRENT_MALLOC(base_length + strlen(all) + 1)) != 0)
+ {
+ strcat(strcpy(dir->name, name), all);
+
+ if ((dir->handle = (handle_type) _findfirst(dir->name, &dir->info)) != -1)
+ {
+ dir->result.d_name = 0;
+ }
+ else // rollback
+ {
+ DIRENT_FREE(dir->name);
+ DIRENT_FREE(dir);
+ dir = 0;
+ }
+ }
+ else // rollback
+ {
+ DIRENT_FREE(dir);
+ dir = 0;
+ errno = ENOMEM;
+ }
+ }
+ else errno = EINVAL;
+
+ return dir;
+}
+
+int closedir(DIR *dir)
+{
+ int result = -1;
+
+ if (dir)
+ {
+ if (dir->handle != -1) result = _findclose(dir->handle);
+
+ DIRENT_FREE(dir->name);
+ DIRENT_FREE(dir);
+ }
+
+ // NOTE: All errors ampped to EBADF
+ if (result == -1) errno = EBADF;
+
+ return result;
+}
+
+struct dirent *readdir(DIR *dir)
+{
+ struct dirent *result = 0;
+
+ if (dir && dir->handle != -1)
+ {
+ if (!dir->result.d_name || _findnext(dir->handle, &dir->info) != -1)
+ {
+ result = &dir->result;
+ result->d_name = dir->info.name;
+ }
+ }
+ else errno = EBADF;
+
+ return result;
+}
+
+void rewinddir(DIR *dir)
+{
+ if (dir && dir->handle != -1)
+ {
+ _findclose(dir->handle);
+ dir->handle = (handle_type) _findfirst(dir->name, &dir->info);
+ dir->result.d_name = 0;
+ }
+ else errno = EBADF;
+}
diff --git a/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/dr_flac.h b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/dr_flac.h
new file mode 100644
index 0000000..14324cf
--- /dev/null
+++ b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/dr_flac.h
@@ -0,0 +1,12536 @@
+/*
+FLAC audio decoder. Choice of public domain or MIT-0. See license statements at the end of this file.
+dr_flac - v0.12.42 - 2023-11-02
+
+David Reid - mackron@gmail.com
+
+GitHub: https://github.com/mackron/dr_libs
+*/
+
+/*
+RELEASE NOTES - v0.12.0
+=======================
+Version 0.12.0 has breaking API changes including changes to the existing API and the removal of deprecated APIs.
+
+
+Improved Client-Defined Memory Allocation
+-----------------------------------------
+The main change with this release is the addition of a more flexible way of implementing custom memory allocation routines. The
+existing system of DRFLAC_MALLOC, DRFLAC_REALLOC and DRFLAC_FREE are still in place and will be used by default when no custom
+allocation callbacks are specified.
+
+To use the new system, you pass in a pointer to a drflac_allocation_callbacks object to drflac_open() and family, like this:
+
+ void* my_malloc(size_t sz, void* pUserData)
+ {
+ return malloc(sz);
+ }
+ void* my_realloc(void* p, size_t sz, void* pUserData)
+ {
+ return realloc(p, sz);
+ }
+ void my_free(void* p, void* pUserData)
+ {
+ free(p);
+ }
+
+ ...
+
+ drflac_allocation_callbacks allocationCallbacks;
+ allocationCallbacks.pUserData = &myData;
+ allocationCallbacks.onMalloc = my_malloc;
+ allocationCallbacks.onRealloc = my_realloc;
+ allocationCallbacks.onFree = my_free;
+ drflac* pFlac = drflac_open_file("my_file.flac", &allocationCallbacks);
+
+The advantage of this new system is that it allows you to specify user data which will be passed in to the allocation routines.
+
+Passing in null for the allocation callbacks object will cause dr_flac to use defaults which is the same as DRFLAC_MALLOC,
+DRFLAC_REALLOC and DRFLAC_FREE and the equivalent of how it worked in previous versions.
+
+Every API that opens a drflac object now takes this extra parameter. These include the following:
+
+ drflac_open()
+ drflac_open_relaxed()
+ drflac_open_with_metadata()
+ drflac_open_with_metadata_relaxed()
+ drflac_open_file()
+ drflac_open_file_with_metadata()
+ drflac_open_memory()
+ drflac_open_memory_with_metadata()
+ drflac_open_and_read_pcm_frames_s32()
+ drflac_open_and_read_pcm_frames_s16()
+ drflac_open_and_read_pcm_frames_f32()
+ drflac_open_file_and_read_pcm_frames_s32()
+ drflac_open_file_and_read_pcm_frames_s16()
+ drflac_open_file_and_read_pcm_frames_f32()
+ drflac_open_memory_and_read_pcm_frames_s32()
+ drflac_open_memory_and_read_pcm_frames_s16()
+ drflac_open_memory_and_read_pcm_frames_f32()
+
+
+
+Optimizations
+-------------
+Seeking performance has been greatly improved. A new binary search based seeking algorithm has been introduced which significantly
+improves performance over the brute force method which was used when no seek table was present. Seek table based seeking also takes
+advantage of the new binary search seeking system to further improve performance there as well. Note that this depends on CRC which
+means it will be disabled when DR_FLAC_NO_CRC is used.
+
+The SSE4.1 pipeline has been cleaned up and optimized. You should see some improvements with decoding speed of 24-bit files in
+particular. 16-bit streams should also see some improvement.
+
+drflac_read_pcm_frames_s16() has been optimized. Previously this sat on top of drflac_read_pcm_frames_s32() and performed it's s32
+to s16 conversion in a second pass. This is now all done in a single pass. This includes SSE2 and ARM NEON optimized paths.
+
+A minor optimization has been implemented for drflac_read_pcm_frames_s32(). This will now use an SSE2 optimized pipeline for stereo
+channel reconstruction which is the last part of the decoding process.
+
+The ARM build has seen a few improvements. The CLZ (count leading zeroes) and REV (byte swap) instructions are now used when
+compiling with GCC and Clang which is achieved using inline assembly. The CLZ instruction requires ARM architecture version 5 at
+compile time and the REV instruction requires ARM architecture version 6.
+
+An ARM NEON optimized pipeline has been implemented. To enable this you'll need to add -mfpu=neon to the command line when compiling.
+
+
+Removed APIs
+------------
+The following APIs were deprecated in version 0.11.0 and have been completely removed in version 0.12.0:
+
+ drflac_read_s32() -> drflac_read_pcm_frames_s32()
+ drflac_read_s16() -> drflac_read_pcm_frames_s16()
+ drflac_read_f32() -> drflac_read_pcm_frames_f32()
+ drflac_seek_to_sample() -> drflac_seek_to_pcm_frame()
+ drflac_open_and_decode_s32() -> drflac_open_and_read_pcm_frames_s32()
+ drflac_open_and_decode_s16() -> drflac_open_and_read_pcm_frames_s16()
+ drflac_open_and_decode_f32() -> drflac_open_and_read_pcm_frames_f32()
+ drflac_open_and_decode_file_s32() -> drflac_open_file_and_read_pcm_frames_s32()
+ drflac_open_and_decode_file_s16() -> drflac_open_file_and_read_pcm_frames_s16()
+ drflac_open_and_decode_file_f32() -> drflac_open_file_and_read_pcm_frames_f32()
+ drflac_open_and_decode_memory_s32() -> drflac_open_memory_and_read_pcm_frames_s32()
+ drflac_open_and_decode_memory_s16() -> drflac_open_memory_and_read_pcm_frames_s16()
+ drflac_open_and_decode_memory_f32() -> drflac_open_memroy_and_read_pcm_frames_f32()
+
+Prior versions of dr_flac operated on a per-sample basis whereas now it operates on PCM frames. The removed APIs all relate
+to the old per-sample APIs. You now need to use the "pcm_frame" versions.
+*/
+
+
+/*
+Introduction
+============
+dr_flac is a single file library. To use it, do something like the following in one .c file.
+
+ ```c
+ #define DR_FLAC_IMPLEMENTATION
+ #include "dr_flac.h"
+ ```
+
+You can then #include this file in other parts of the program as you would with any other header file. To decode audio data, do something like the following:
+
+ ```c
+ drflac* pFlac = drflac_open_file("MySong.flac", NULL);
+ if (pFlac == NULL) {
+ // Failed to open FLAC file
+ }
+
+ drflac_int32* pSamples = malloc(pFlac->totalPCMFrameCount * pFlac->channels * sizeof(drflac_int32));
+ drflac_uint64 numberOfInterleavedSamplesActuallyRead = drflac_read_pcm_frames_s32(pFlac, pFlac->totalPCMFrameCount, pSamples);
+ ```
+
+The drflac object represents the decoder. It is a transparent type so all the information you need, such as the number of channels and the bits per sample,
+should be directly accessible - just make sure you don't change their values. Samples are always output as interleaved signed 32-bit PCM. In the example above
+a native FLAC stream was opened, however dr_flac has seamless support for Ogg encapsulated FLAC streams as well.
+
+You do not need to decode the entire stream in one go - you just specify how many samples you'd like at any given time and the decoder will give you as many
+samples as it can, up to the amount requested. Later on when you need the next batch of samples, just call it again. Example:
+
+ ```c
+ while (drflac_read_pcm_frames_s32(pFlac, chunkSizeInPCMFrames, pChunkSamples) > 0) {
+ do_something();
+ }
+ ```
+
+You can seek to a specific PCM frame with `drflac_seek_to_pcm_frame()`.
+
+If you just want to quickly decode an entire FLAC file in one go you can do something like this:
+
+ ```c
+ unsigned int channels;
+ unsigned int sampleRate;
+ drflac_uint64 totalPCMFrameCount;
+ drflac_int32* pSampleData = drflac_open_file_and_read_pcm_frames_s32("MySong.flac", &channels, &sampleRate, &totalPCMFrameCount, NULL);
+ if (pSampleData == NULL) {
+ // Failed to open and decode FLAC file.
+ }
+
+ ...
+
+ drflac_free(pSampleData, NULL);
+ ```
+
+You can read samples as signed 16-bit integer and 32-bit floating-point PCM with the *_s16() and *_f32() family of APIs respectively, but note that these
+should be considered lossy.
+
+
+If you need access to metadata (album art, etc.), use `drflac_open_with_metadata()`, `drflac_open_file_with_metdata()` or `drflac_open_memory_with_metadata()`.
+The rationale for keeping these APIs separate is that they're slightly slower than the normal versions and also just a little bit harder to use. dr_flac
+reports metadata to the application through the use of a callback, and every metadata block is reported before `drflac_open_with_metdata()` returns.
+
+The main opening APIs (`drflac_open()`, etc.) will fail if the header is not present. The presents a problem in certain scenarios such as broadcast style
+streams or internet radio where the header may not be present because the user has started playback mid-stream. To handle this, use the relaxed APIs:
+
+ `drflac_open_relaxed()`
+ `drflac_open_with_metadata_relaxed()`
+
+It is not recommended to use these APIs for file based streams because a missing header would usually indicate a corrupt or perverse file. In addition, these
+APIs can take a long time to initialize because they may need to spend a lot of time finding the first frame.
+
+
+
+Build Options
+=============
+#define these options before including this file.
+
+#define DR_FLAC_NO_STDIO
+ Disable `drflac_open_file()` and family.
+
+#define DR_FLAC_NO_OGG
+ Disables support for Ogg/FLAC streams.
+
+#define DR_FLAC_BUFFER_SIZE
+ Defines the size of the internal buffer to store data from onRead(). This buffer is used to reduce the number of calls back to the client for more data.
+ Larger values means more memory, but better performance. My tests show diminishing returns after about 4KB (which is the default). Consider reducing this if
+ you have a very efficient implementation of onRead(), or increase it if it's very inefficient. Must be a multiple of 8.
+
+#define DR_FLAC_NO_CRC
+ Disables CRC checks. This will offer a performance boost when CRC is unnecessary. This will disable binary search seeking. When seeking, the seek table will
+ be used if available. Otherwise the seek will be performed using brute force.
+
+#define DR_FLAC_NO_SIMD
+ Disables SIMD optimizations (SSE on x86/x64 architectures, NEON on ARM architectures). Use this if you are having compatibility issues with your compiler.
+
+#define DR_FLAC_NO_WCHAR
+ Disables all functions ending with `_w`. Use this if your compiler does not provide wchar.h. Not required if DR_FLAC_NO_STDIO is also defined.
+
+
+
+Notes
+=====
+- dr_flac does not support changing the sample rate nor channel count mid stream.
+- dr_flac is not thread-safe, but its APIs can be called from any thread so long as you do your own synchronization.
+- When using Ogg encapsulation, a corrupted metadata block will result in `drflac_open_with_metadata()` and `drflac_open()` returning inconsistent samples due
+ to differences in corrupted stream recorvery logic between the two APIs.
+*/
+
+#ifndef dr_flac_h
+#define dr_flac_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define DRFLAC_STRINGIFY(x) #x
+#define DRFLAC_XSTRINGIFY(x) DRFLAC_STRINGIFY(x)
+
+#define DRFLAC_VERSION_MAJOR 0
+#define DRFLAC_VERSION_MINOR 12
+#define DRFLAC_VERSION_REVISION 42
+#define DRFLAC_VERSION_STRING DRFLAC_XSTRINGIFY(DRFLAC_VERSION_MAJOR) "." DRFLAC_XSTRINGIFY(DRFLAC_VERSION_MINOR) "." DRFLAC_XSTRINGIFY(DRFLAC_VERSION_REVISION)
+
+#include /* For size_t. */
+
+/* Sized Types */
+typedef signed char drflac_int8;
+typedef unsigned char drflac_uint8;
+typedef signed short drflac_int16;
+typedef unsigned short drflac_uint16;
+typedef signed int drflac_int32;
+typedef unsigned int drflac_uint32;
+#if defined(_MSC_VER) && !defined(__clang__)
+ typedef signed __int64 drflac_int64;
+ typedef unsigned __int64 drflac_uint64;
+#else
+ #if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wlong-long"
+ #if defined(__clang__)
+ #pragma GCC diagnostic ignored "-Wc++11-long-long"
+ #endif
+ #endif
+ typedef signed long long drflac_int64;
+ typedef unsigned long long drflac_uint64;
+ #if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
+ #pragma GCC diagnostic pop
+ #endif
+#endif
+#if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__)) || defined(_M_X64) || defined(__ia64) || defined(_M_IA64) || defined(__aarch64__) || defined(_M_ARM64) || defined(__powerpc64__)
+ typedef drflac_uint64 drflac_uintptr;
+#else
+ typedef drflac_uint32 drflac_uintptr;
+#endif
+typedef drflac_uint8 drflac_bool8;
+typedef drflac_uint32 drflac_bool32;
+#define DRFLAC_TRUE 1
+#define DRFLAC_FALSE 0
+/* End Sized Types */
+
+/* Decorations */
+#if !defined(DRFLAC_API)
+ #if defined(DRFLAC_DLL)
+ #if defined(_WIN32)
+ #define DRFLAC_DLL_IMPORT __declspec(dllimport)
+ #define DRFLAC_DLL_EXPORT __declspec(dllexport)
+ #define DRFLAC_DLL_PRIVATE static
+ #else
+ #if defined(__GNUC__) && __GNUC__ >= 4
+ #define DRFLAC_DLL_IMPORT __attribute__((visibility("default")))
+ #define DRFLAC_DLL_EXPORT __attribute__((visibility("default")))
+ #define DRFLAC_DLL_PRIVATE __attribute__((visibility("hidden")))
+ #else
+ #define DRFLAC_DLL_IMPORT
+ #define DRFLAC_DLL_EXPORT
+ #define DRFLAC_DLL_PRIVATE static
+ #endif
+ #endif
+
+ #if defined(DR_FLAC_IMPLEMENTATION) || defined(DRFLAC_IMPLEMENTATION)
+ #define DRFLAC_API DRFLAC_DLL_EXPORT
+ #else
+ #define DRFLAC_API DRFLAC_DLL_IMPORT
+ #endif
+ #define DRFLAC_PRIVATE DRFLAC_DLL_PRIVATE
+ #else
+ #define DRFLAC_API extern
+ #define DRFLAC_PRIVATE static
+ #endif
+#endif
+/* End Decorations */
+
+#if defined(_MSC_VER) && _MSC_VER >= 1700 /* Visual Studio 2012 */
+ #define DRFLAC_DEPRECATED __declspec(deprecated)
+#elif (defined(__GNUC__) && __GNUC__ >= 4) /* GCC 4 */
+ #define DRFLAC_DEPRECATED __attribute__((deprecated))
+#elif defined(__has_feature) /* Clang */
+ #if __has_feature(attribute_deprecated)
+ #define DRFLAC_DEPRECATED __attribute__((deprecated))
+ #else
+ #define DRFLAC_DEPRECATED
+ #endif
+#else
+ #define DRFLAC_DEPRECATED
+#endif
+
+DRFLAC_API void drflac_version(drflac_uint32* pMajor, drflac_uint32* pMinor, drflac_uint32* pRevision);
+DRFLAC_API const char* drflac_version_string(void);
+
+/* Allocation Callbacks */
+typedef struct
+{
+ void* pUserData;
+ void* (* onMalloc)(size_t sz, void* pUserData);
+ void* (* onRealloc)(void* p, size_t sz, void* pUserData);
+ void (* onFree)(void* p, void* pUserData);
+} drflac_allocation_callbacks;
+/* End Allocation Callbacks */
+
+/*
+As data is read from the client it is placed into an internal buffer for fast access. This controls the size of that buffer. Larger values means more speed,
+but also more memory. In my testing there is diminishing returns after about 4KB, but you can fiddle with this to suit your own needs. Must be a multiple of 8.
+*/
+#ifndef DR_FLAC_BUFFER_SIZE
+#define DR_FLAC_BUFFER_SIZE 4096
+#endif
+
+
+/* Architecture Detection */
+#if defined(_WIN64) || defined(_LP64) || defined(__LP64__)
+#define DRFLAC_64BIT
+#endif
+
+#if defined(__x86_64__) || defined(_M_X64)
+ #define DRFLAC_X64
+#elif defined(__i386) || defined(_M_IX86)
+ #define DRFLAC_X86
+#elif defined(__arm__) || defined(_M_ARM) || defined(__arm64) || defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64)
+ #define DRFLAC_ARM
+#endif
+/* End Architecture Detection */
+
+
+#ifdef DRFLAC_64BIT
+typedef drflac_uint64 drflac_cache_t;
+#else
+typedef drflac_uint32 drflac_cache_t;
+#endif
+
+/* The various metadata block types. */
+#define DRFLAC_METADATA_BLOCK_TYPE_STREAMINFO 0
+#define DRFLAC_METADATA_BLOCK_TYPE_PADDING 1
+#define DRFLAC_METADATA_BLOCK_TYPE_APPLICATION 2
+#define DRFLAC_METADATA_BLOCK_TYPE_SEEKTABLE 3
+#define DRFLAC_METADATA_BLOCK_TYPE_VORBIS_COMMENT 4
+#define DRFLAC_METADATA_BLOCK_TYPE_CUESHEET 5
+#define DRFLAC_METADATA_BLOCK_TYPE_PICTURE 6
+#define DRFLAC_METADATA_BLOCK_TYPE_INVALID 127
+
+/* The various picture types specified in the PICTURE block. */
+#define DRFLAC_PICTURE_TYPE_OTHER 0
+#define DRFLAC_PICTURE_TYPE_FILE_ICON 1
+#define DRFLAC_PICTURE_TYPE_OTHER_FILE_ICON 2
+#define DRFLAC_PICTURE_TYPE_COVER_FRONT 3
+#define DRFLAC_PICTURE_TYPE_COVER_BACK 4
+#define DRFLAC_PICTURE_TYPE_LEAFLET_PAGE 5
+#define DRFLAC_PICTURE_TYPE_MEDIA 6
+#define DRFLAC_PICTURE_TYPE_LEAD_ARTIST 7
+#define DRFLAC_PICTURE_TYPE_ARTIST 8
+#define DRFLAC_PICTURE_TYPE_CONDUCTOR 9
+#define DRFLAC_PICTURE_TYPE_BAND 10
+#define DRFLAC_PICTURE_TYPE_COMPOSER 11
+#define DRFLAC_PICTURE_TYPE_LYRICIST 12
+#define DRFLAC_PICTURE_TYPE_RECORDING_LOCATION 13
+#define DRFLAC_PICTURE_TYPE_DURING_RECORDING 14
+#define DRFLAC_PICTURE_TYPE_DURING_PERFORMANCE 15
+#define DRFLAC_PICTURE_TYPE_SCREEN_CAPTURE 16
+#define DRFLAC_PICTURE_TYPE_BRIGHT_COLORED_FISH 17
+#define DRFLAC_PICTURE_TYPE_ILLUSTRATION 18
+#define DRFLAC_PICTURE_TYPE_BAND_LOGOTYPE 19
+#define DRFLAC_PICTURE_TYPE_PUBLISHER_LOGOTYPE 20
+
+typedef enum
+{
+ drflac_container_native,
+ drflac_container_ogg,
+ drflac_container_unknown
+} drflac_container;
+
+typedef enum
+{
+ drflac_seek_origin_start,
+ drflac_seek_origin_current
+} drflac_seek_origin;
+
+/* The order of members in this structure is important because we map this directly to the raw data within the SEEKTABLE metadata block. */
+typedef struct
+{
+ drflac_uint64 firstPCMFrame;
+ drflac_uint64 flacFrameOffset; /* The offset from the first byte of the header of the first frame. */
+ drflac_uint16 pcmFrameCount;
+} drflac_seekpoint;
+
+typedef struct
+{
+ drflac_uint16 minBlockSizeInPCMFrames;
+ drflac_uint16 maxBlockSizeInPCMFrames;
+ drflac_uint32 minFrameSizeInPCMFrames;
+ drflac_uint32 maxFrameSizeInPCMFrames;
+ drflac_uint32 sampleRate;
+ drflac_uint8 channels;
+ drflac_uint8 bitsPerSample;
+ drflac_uint64 totalPCMFrameCount;
+ drflac_uint8 md5[16];
+} drflac_streaminfo;
+
+typedef struct
+{
+ /*
+ The metadata type. Use this to know how to interpret the data below. Will be set to one of the
+ DRFLAC_METADATA_BLOCK_TYPE_* tokens.
+ */
+ drflac_uint32 type;
+
+ /*
+ 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
+ information about the metadata. It's possible for this to be null.
+ */
+ 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;
+
+ struct
+ {
+ int unused;
+ } padding;
+
+ struct
+ {
+ drflac_uint32 id;
+ const void* pData;
+ drflac_uint32 dataSize;
+ } application;
+
+ struct
+ {
+ drflac_uint32 seekpointCount;
+ const drflac_seekpoint* pSeekpoints;
+ } seektable;
+
+ struct
+ {
+ drflac_uint32 vendorLength;
+ const char* vendor;
+ drflac_uint32 commentCount;
+ const void* pComments;
+ } vorbis_comment;
+
+ struct
+ {
+ char catalog[128];
+ drflac_uint64 leadInSampleCount;
+ drflac_bool32 isCD;
+ drflac_uint8 trackCount;
+ const void* pTrackData;
+ } cuesheet;
+
+ struct
+ {
+ drflac_uint32 type;
+ drflac_uint32 mimeLength;
+ const char* mime;
+ drflac_uint32 descriptionLength;
+ const char* description;
+ drflac_uint32 width;
+ drflac_uint32 height;
+ drflac_uint32 colorDepth;
+ drflac_uint32 indexColorCount;
+ drflac_uint32 pictureDataSize;
+ const drflac_uint8* pPictureData;
+ } picture;
+ } data;
+} drflac_metadata;
+
+
+/*
+Callback for when data needs to be read from the client.
+
+
+Parameters
+----------
+pUserData (in)
+ The user data that was passed to drflac_open() and family.
+
+pBufferOut (out)
+ The output buffer.
+
+bytesToRead (in)
+ The number of bytes to read.
+
+
+Return Value
+------------
+The number of bytes actually read.
+
+
+Remarks
+-------
+A return value of less than bytesToRead indicates the end of the stream. Do _not_ return from this callback until either the entire bytesToRead is filled or
+you have reached the end of the stream.
+*/
+typedef size_t (* drflac_read_proc)(void* pUserData, void* pBufferOut, size_t bytesToRead);
+
+/*
+Callback for when data needs to be seeked.
+
+
+Parameters
+----------
+pUserData (in)
+ The user data that was passed to drflac_open() and family.
+
+offset (in)
+ The number of bytes to move, relative to the origin. Will never be negative.
+
+origin (in)
+ The origin of the seek - the current position or the start of the stream.
+
+
+Return Value
+------------
+Whether or not the seek was successful.
+
+
+Remarks
+-------
+The offset will never be negative. Whether or not it is relative to the beginning or current position is determined by the "origin" parameter which will be
+either drflac_seek_origin_start or drflac_seek_origin_current.
+
+When seeking to a PCM frame using drflac_seek_to_pcm_frame(), dr_flac may call this with an offset beyond the end of the FLAC stream. This needs to be detected
+and handled by returning DRFLAC_FALSE.
+*/
+typedef drflac_bool32 (* drflac_seek_proc)(void* pUserData, int offset, drflac_seek_origin origin);
+
+/*
+Callback for when a metadata block is read.
+
+
+Parameters
+----------
+pUserData (in)
+ The user data that was passed to drflac_open() and family.
+
+pMetadata (in)
+ A pointer to a structure containing the data of the metadata block.
+
+
+Remarks
+-------
+Use pMetadata->type to determine which metadata block is being handled and how to read the data. This
+will be set to one of the DRFLAC_METADATA_BLOCK_TYPE_* tokens.
+*/
+typedef void (* drflac_meta_proc)(void* pUserData, drflac_metadata* pMetadata);
+
+
+/* Structure for internal use. Only used for decoders opened with drflac_open_memory. */
+typedef struct
+{
+ const drflac_uint8* data;
+ size_t dataSize;
+ size_t currentReadPos;
+} drflac__memory_stream;
+
+/* Structure for internal use. Used for bit streaming. */
+typedef struct
+{
+ /* The function to call when more data needs to be read. */
+ drflac_read_proc onRead;
+
+ /* The function to call when the current read position needs to be moved. */
+ drflac_seek_proc onSeek;
+
+ /* The user data to pass around to onRead and onSeek. */
+ void* pUserData;
+
+
+ /*
+ The number of unaligned bytes in the L2 cache. This will always be 0 until the end of the stream is hit. At the end of the
+ stream there will be a number of bytes that don't cleanly fit in an L1 cache line, so we use this variable to know whether
+ or not the bistreamer needs to run on a slower path to read those last bytes. This will never be more than sizeof(drflac_cache_t).
+ */
+ size_t unalignedByteCount;
+
+ /* The content of the unaligned bytes. */
+ drflac_cache_t unalignedCache;
+
+ /* The index of the next valid cache line in the "L2" cache. */
+ drflac_uint32 nextL2Line;
+
+ /* The number of bits that have been consumed by the cache. This is used to determine how many valid bits are remaining. */
+ drflac_uint32 consumedBits;
+
+ /*
+ The cached data which was most recently read from the client. There are two levels of cache. Data flows as such:
+ Client -> L2 -> L1. The L2 -> L1 movement is aligned and runs on a fast path in just a few instructions.
+ */
+ drflac_cache_t cacheL2[DR_FLAC_BUFFER_SIZE/sizeof(drflac_cache_t)];
+ drflac_cache_t cache;
+
+ /*
+ CRC-16. This is updated whenever bits are read from the bit stream. Manually set this to 0 to reset the CRC. For FLAC, this
+ is reset to 0 at the beginning of each frame.
+ */
+ drflac_uint16 crc16;
+ drflac_cache_t crc16Cache; /* A cache for optimizing CRC calculations. This is filled when when the L1 cache is reloaded. */
+ drflac_uint32 crc16CacheIgnoredBytes; /* The number of bytes to ignore when updating the CRC-16 from the CRC-16 cache. */
+} drflac_bs;
+
+typedef struct
+{
+ /* The type of the subframe: SUBFRAME_CONSTANT, SUBFRAME_VERBATIM, SUBFRAME_FIXED or SUBFRAME_LPC. */
+ drflac_uint8 subframeType;
+
+ /* The number of wasted bits per sample as specified by the sub-frame header. */
+ drflac_uint8 wastedBitsPerSample;
+
+ /* The order to use for the prediction stage for SUBFRAME_FIXED and SUBFRAME_LPC. */
+ drflac_uint8 lpcOrder;
+
+ /* A pointer to the buffer containing the decoded samples in the subframe. This pointer is an offset from drflac::pExtraData. */
+ drflac_int32* pSamplesS32;
+} drflac_subframe;
+
+typedef struct
+{
+ /*
+ If the stream uses variable block sizes, this will be set to the index of the first PCM frame. If fixed block sizes are used, this will
+ always be set to 0. This is 64-bit because the decoded PCM frame number will be 36 bits.
+ */
+ drflac_uint64 pcmFrameNumber;
+
+ /*
+ If the stream uses fixed block sizes, this will be set to the frame number. If variable block sizes are used, this will always be 0. This
+ is 32-bit because in fixed block sizes, the maximum frame number will be 31 bits.
+ */
+ drflac_uint32 flacFrameNumber;
+
+ /* The sample rate of this frame. */
+ drflac_uint32 sampleRate;
+
+ /* The number of PCM frames in each sub-frame within this frame. */
+ drflac_uint16 blockSizeInPCMFrames;
+
+ /*
+ The channel assignment of this frame. This is not always set to the channel count. If interchannel decorrelation is being used this
+ will be set to DRFLAC_CHANNEL_ASSIGNMENT_LEFT_SIDE, DRFLAC_CHANNEL_ASSIGNMENT_RIGHT_SIDE or DRFLAC_CHANNEL_ASSIGNMENT_MID_SIDE.
+ */
+ drflac_uint8 channelAssignment;
+
+ /* The number of bits per sample within this frame. */
+ drflac_uint8 bitsPerSample;
+
+ /* The frame's CRC. */
+ drflac_uint8 crc8;
+} drflac_frame_header;
+
+typedef struct
+{
+ /* The header. */
+ drflac_frame_header header;
+
+ /*
+ The number of PCM frames left to be read in this FLAC frame. This is initially set to the block size. As PCM frames are read,
+ this will be decremented. When it reaches 0, the decoder will see this frame as fully consumed and load the next frame.
+ */
+ drflac_uint32 pcmFramesRemaining;
+
+ /* The list of sub-frames within the frame. There is one sub-frame for each channel, and there's a maximum of 8 channels. */
+ drflac_subframe subframes[8];
+} drflac_frame;
+
+typedef struct
+{
+ /* The function to call when a metadata block is read. */
+ drflac_meta_proc onMeta;
+
+ /* The user data posted to the metadata callback function. */
+ void* pUserDataMD;
+
+ /* Memory allocation callbacks. */
+ drflac_allocation_callbacks allocationCallbacks;
+
+
+ /* The sample rate. Will be set to something like 44100. */
+ drflac_uint32 sampleRate;
+
+ /*
+ The number of channels. This will be set to 1 for monaural streams, 2 for stereo, etc. Maximum 8. This is set based on the
+ value specified in the STREAMINFO block.
+ */
+ drflac_uint8 channels;
+
+ /* The bits per sample. Will be set to something like 16, 24, etc. */
+ drflac_uint8 bitsPerSample;
+
+ /* The maximum block size, in samples. This number represents the number of samples in each channel (not combined). */
+ drflac_uint16 maxBlockSizeInPCMFrames;
+
+ /*
+ The total number of PCM Frames making up the stream. Can be 0 in which case it's still a valid stream, but just means
+ the total PCM frame count is unknown. Likely the case with streams like internet radio.
+ */
+ drflac_uint64 totalPCMFrameCount;
+
+
+ /* The container type. This is set based on whether or not the decoder was opened from a native or Ogg stream. */
+ drflac_container container;
+
+ /* The number of seekpoints in the seektable. */
+ drflac_uint32 seekpointCount;
+
+
+ /* Information about the frame the decoder is currently sitting on. */
+ drflac_frame currentFLACFrame;
+
+
+ /* The index of the PCM frame the decoder is currently sitting on. This is only used for seeking. */
+ drflac_uint64 currentPCMFrame;
+
+ /* The position of the first FLAC frame in the stream. This is only ever used for seeking. */
+ drflac_uint64 firstFLACFramePosInBytes;
+
+
+ /* A hack to avoid a malloc() when opening a decoder with drflac_open_memory(). */
+ drflac__memory_stream memoryStream;
+
+
+ /* A pointer to the decoded sample data. This is an offset of pExtraData. */
+ drflac_int32* pDecodedSamples;
+
+ /* A pointer to the seek table. This is an offset of pExtraData, or NULL if there is no seek table. */
+ drflac_seekpoint* pSeekpoints;
+
+ /* Internal use only. Only used with Ogg containers. Points to a drflac_oggbs object. This is an offset of pExtraData. */
+ void* _oggbs;
+
+ /* Internal use only. Used for profiling and testing different seeking modes. */
+ drflac_bool32 _noSeekTableSeek : 1;
+ drflac_bool32 _noBinarySearchSeek : 1;
+ drflac_bool32 _noBruteForceSeek : 1;
+
+ /* The bit streamer. The raw FLAC data is fed through this object. */
+ drflac_bs bs;
+
+ /* Variable length extra data. We attach this to the end of the object so we can avoid unnecessary mallocs. */
+ drflac_uint8 pExtraData[1];
+} drflac;
+
+
+/*
+Opens a FLAC decoder.
+
+
+Parameters
+----------
+onRead (in)
+ The function to call when data needs to be read from the client.
+
+onSeek (in)
+ The function to call when the read position of the client data needs to move.
+
+pUserData (in, optional)
+ A pointer to application defined data that will be passed to onRead and onSeek.
+
+pAllocationCallbacks (in, optional)
+ A pointer to application defined callbacks for managing memory allocations.
+
+
+Return Value
+------------
+Returns a pointer to an object representing the decoder.
+
+
+Remarks
+-------
+Close the decoder with `drflac_close()`.
+
+`pAllocationCallbacks` can be NULL in which case it will use `DRFLAC_MALLOC`, `DRFLAC_REALLOC` and `DRFLAC_FREE`.
+
+This function will automatically detect whether or not you are attempting to open a native or Ogg encapsulated FLAC, both of which should work seamlessly
+without any manual intervention. Ogg encapsulation also works with multiplexed streams which basically means it can play FLAC encoded audio tracks in videos.
+
+This is the lowest level function for opening a FLAC stream. You can also use `drflac_open_file()` and `drflac_open_memory()` to open the stream from a file or
+from a block of memory respectively.
+
+The STREAMINFO block must be present for this to succeed. Use `drflac_open_relaxed()` to open a FLAC stream where the header may not be present.
+
+Use `drflac_open_with_metadata()` if you need access to metadata.
+
+
+Seek Also
+---------
+drflac_open_file()
+drflac_open_memory()
+drflac_open_with_metadata()
+drflac_close()
+*/
+DRFLAC_API drflac* drflac_open(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks);
+
+/*
+Opens a FLAC stream with relaxed validation of the header block.
+
+
+Parameters
+----------
+onRead (in)
+ The function to call when data needs to be read from the client.
+
+onSeek (in)
+ The function to call when the read position of the client data needs to move.
+
+container (in)
+ Whether or not the FLAC stream is encapsulated using standard FLAC encapsulation or Ogg encapsulation.
+
+pUserData (in, optional)
+ A pointer to application defined data that will be passed to onRead and onSeek.
+
+pAllocationCallbacks (in, optional)
+ A pointer to application defined callbacks for managing memory allocations.
+
+
+Return Value
+------------
+A pointer to an object representing the decoder.
+
+
+Remarks
+-------
+The same as drflac_open(), except attempts to open the stream even when a header block is not present.
+
+Because the header is not necessarily available, the caller must explicitly define the container (Native or Ogg). Do not set this to `drflac_container_unknown`
+as that is for internal use only.
+
+Opening in relaxed mode will continue reading data from onRead until it finds a valid frame. If a frame is never found it will continue forever. To abort,
+force your `onRead` callback to return 0, which dr_flac will use as an indicator that the end of the stream was found.
+
+Use `drflac_open_with_metadata_relaxed()` if you need access to metadata.
+*/
+DRFLAC_API drflac* drflac_open_relaxed(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_container container, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks);
+
+/*
+Opens a FLAC decoder and notifies the caller of the metadata chunks (album art, etc.).
+
+
+Parameters
+----------
+onRead (in)
+ The function to call when data needs to be read from the client.
+
+onSeek (in)
+ The function to call when the read position of the client data needs to move.
+
+onMeta (in)
+ The function to call for every metadata block.
+
+pUserData (in, optional)
+ A pointer to application defined data that will be passed to onRead, onSeek and onMeta.
+
+pAllocationCallbacks (in, optional)
+ A pointer to application defined callbacks for managing memory allocations.
+
+
+Return Value
+------------
+A pointer to an object representing the decoder.
+
+
+Remarks
+-------
+Close the decoder with `drflac_close()`.
+
+`pAllocationCallbacks` can be NULL in which case it will use `DRFLAC_MALLOC`, `DRFLAC_REALLOC` and `DRFLAC_FREE`.
+
+This is slower than `drflac_open()`, so avoid this one if you don't need metadata. Internally, this will allocate and free memory on the heap for every
+metadata block except for STREAMINFO and PADDING blocks.
+
+The caller is notified of the metadata via the `onMeta` callback. All metadata blocks will be handled before the function returns. This callback takes a
+pointer to a `drflac_metadata` object which is a union containing the data of all relevant metadata blocks. Use the `type` member to discriminate against
+the different metadata types.
+
+The STREAMINFO block must be present for this to succeed. Use `drflac_open_with_metadata_relaxed()` to open a FLAC stream where the header may not be present.
+
+Note that this will behave inconsistently with `drflac_open()` if the stream is an Ogg encapsulated stream and a metadata block is corrupted. This is due to
+the way the Ogg stream recovers from corrupted pages. When `drflac_open_with_metadata()` is being used, the open routine will try to read the contents of the
+metadata block, whereas `drflac_open()` will simply seek past it (for the sake of efficiency). This inconsistency can result in different samples being
+returned depending on whether or not the stream is being opened with metadata.
+
+
+Seek Also
+---------
+drflac_open_file_with_metadata()
+drflac_open_memory_with_metadata()
+drflac_open()
+drflac_close()
+*/
+DRFLAC_API drflac* drflac_open_with_metadata(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks);
+
+/*
+The same as drflac_open_with_metadata(), except attempts to open the stream even when a header block is not present.
+
+See Also
+--------
+drflac_open_with_metadata()
+drflac_open_relaxed()
+*/
+DRFLAC_API drflac* drflac_open_with_metadata_relaxed(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, drflac_container container, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks);
+
+/*
+Closes the given FLAC decoder.
+
+
+Parameters
+----------
+pFlac (in)
+ The decoder to close.
+
+
+Remarks
+-------
+This will destroy the decoder object.
+
+
+See Also
+--------
+drflac_open()
+drflac_open_with_metadata()
+drflac_open_file()
+drflac_open_file_w()
+drflac_open_file_with_metadata()
+drflac_open_file_with_metadata_w()
+drflac_open_memory()
+drflac_open_memory_with_metadata()
+*/
+DRFLAC_API void drflac_close(drflac* pFlac);
+
+
+/*
+Reads sample data from the given FLAC decoder, output as interleaved signed 32-bit PCM.
+
+
+Parameters
+----------
+pFlac (in)
+ The decoder.
+
+framesToRead (in)
+ The number of PCM frames to read.
+
+pBufferOut (out, optional)
+ A pointer to the buffer that will receive the decoded samples.
+
+
+Return Value
+------------
+Returns the number of PCM frames actually read. If the return value is less than `framesToRead` it has reached the end.
+
+
+Remarks
+-------
+pBufferOut can be null, in which case the call will act as a seek, and the return value will be the number of frames seeked.
+*/
+DRFLAC_API drflac_uint64 drflac_read_pcm_frames_s32(drflac* pFlac, drflac_uint64 framesToRead, drflac_int32* pBufferOut);
+
+
+/*
+Reads sample data from the given FLAC decoder, output as interleaved signed 16-bit PCM.
+
+
+Parameters
+----------
+pFlac (in)
+ The decoder.
+
+framesToRead (in)
+ The number of PCM frames to read.
+
+pBufferOut (out, optional)
+ A pointer to the buffer that will receive the decoded samples.
+
+
+Return Value
+------------
+Returns the number of PCM frames actually read. If the return value is less than `framesToRead` it has reached the end.
+
+
+Remarks
+-------
+pBufferOut can be null, in which case the call will act as a seek, and the return value will be the number of frames seeked.
+
+Note that this is lossy for streams where the bits per sample is larger than 16.
+*/
+DRFLAC_API drflac_uint64 drflac_read_pcm_frames_s16(drflac* pFlac, drflac_uint64 framesToRead, drflac_int16* pBufferOut);
+
+/*
+Reads sample data from the given FLAC decoder, output as interleaved 32-bit floating point PCM.
+
+
+Parameters
+----------
+pFlac (in)
+ The decoder.
+
+framesToRead (in)
+ The number of PCM frames to read.
+
+pBufferOut (out, optional)
+ A pointer to the buffer that will receive the decoded samples.
+
+
+Return Value
+------------
+Returns the number of PCM frames actually read. If the return value is less than `framesToRead` it has reached the end.
+
+
+Remarks
+-------
+pBufferOut can be null, in which case the call will act as a seek, and the return value will be the number of frames seeked.
+
+Note that this should be considered lossy due to the nature of floating point numbers not being able to exactly represent every possible number.
+*/
+DRFLAC_API drflac_uint64 drflac_read_pcm_frames_f32(drflac* pFlac, drflac_uint64 framesToRead, float* pBufferOut);
+
+/*
+Seeks to the PCM frame at the given index.
+
+
+Parameters
+----------
+pFlac (in)
+ The decoder.
+
+pcmFrameIndex (in)
+ The index of the PCM frame to seek to. See notes below.
+
+
+Return Value
+-------------
+`DRFLAC_TRUE` if successful; `DRFLAC_FALSE` otherwise.
+*/
+DRFLAC_API drflac_bool32 drflac_seek_to_pcm_frame(drflac* pFlac, drflac_uint64 pcmFrameIndex);
+
+
+
+#ifndef DR_FLAC_NO_STDIO
+/*
+Opens a FLAC decoder from the file at the given path.
+
+
+Parameters
+----------
+pFileName (in)
+ The path of the file to open, either absolute or relative to the current directory.
+
+pAllocationCallbacks (in, optional)
+ A pointer to application defined callbacks for managing memory allocations.
+
+
+Return Value
+------------
+A pointer to an object representing the decoder.
+
+
+Remarks
+-------
+Close the decoder with drflac_close().
+
+
+Remarks
+-------
+This will hold a handle to the file until the decoder is closed with drflac_close(). Some platforms will restrict the number of files a process can have open
+at any given time, so keep this mind if you have many decoders open at the same time.
+
+
+See Also
+--------
+drflac_open_file_with_metadata()
+drflac_open()
+drflac_close()
+*/
+DRFLAC_API drflac* drflac_open_file(const char* pFileName, const drflac_allocation_callbacks* pAllocationCallbacks);
+DRFLAC_API drflac* drflac_open_file_w(const wchar_t* pFileName, const drflac_allocation_callbacks* pAllocationCallbacks);
+
+/*
+Opens a FLAC decoder from the file at the given path and notifies the caller of the metadata chunks (album art, etc.)
+
+
+Parameters
+----------
+pFileName (in)
+ The path of the file to open, either absolute or relative to the current directory.
+
+pAllocationCallbacks (in, optional)
+ A pointer to application defined callbacks for managing memory allocations.
+
+onMeta (in)
+ The callback to fire for each metadata block.
+
+pUserData (in)
+ A pointer to the user data to pass to the metadata callback.
+
+pAllocationCallbacks (in)
+ A pointer to application defined callbacks for managing memory allocations.
+
+
+Remarks
+-------
+Look at the documentation for drflac_open_with_metadata() for more information on how metadata is handled.
+
+
+See Also
+--------
+drflac_open_with_metadata()
+drflac_open()
+drflac_close()
+*/
+DRFLAC_API drflac* drflac_open_file_with_metadata(const char* pFileName, drflac_meta_proc onMeta, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks);
+DRFLAC_API drflac* drflac_open_file_with_metadata_w(const wchar_t* pFileName, drflac_meta_proc onMeta, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks);
+#endif
+
+/*
+Opens a FLAC decoder from a pre-allocated block of memory
+
+
+Parameters
+----------
+pData (in)
+ A pointer to the raw encoded FLAC data.
+
+dataSize (in)
+ The size in bytes of `data`.
+
+pAllocationCallbacks (in)
+ A pointer to application defined callbacks for managing memory allocations.
+
+
+Return Value
+------------
+A pointer to an object representing the decoder.
+
+
+Remarks
+-------
+This does not create a copy of the data. It is up to the application to ensure the buffer remains valid for the lifetime of the decoder.
+
+
+See Also
+--------
+drflac_open()
+drflac_close()
+*/
+DRFLAC_API drflac* drflac_open_memory(const void* pData, size_t dataSize, const drflac_allocation_callbacks* pAllocationCallbacks);
+
+/*
+Opens a FLAC decoder from a pre-allocated block of memory and notifies the caller of the metadata chunks (album art, etc.)
+
+
+Parameters
+----------
+pData (in)
+ A pointer to the raw encoded FLAC data.
+
+dataSize (in)
+ The size in bytes of `data`.
+
+onMeta (in)
+ The callback to fire for each metadata block.
+
+pUserData (in)
+ A pointer to the user data to pass to the metadata callback.
+
+pAllocationCallbacks (in)
+ A pointer to application defined callbacks for managing memory allocations.
+
+
+Remarks
+-------
+Look at the documentation for drflac_open_with_metadata() for more information on how metadata is handled.
+
+
+See Also
+-------
+drflac_open_with_metadata()
+drflac_open()
+drflac_close()
+*/
+DRFLAC_API drflac* drflac_open_memory_with_metadata(const void* pData, size_t dataSize, drflac_meta_proc onMeta, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks);
+
+
+
+/* High Level APIs */
+
+/*
+Opens a FLAC stream from the given callbacks and fully decodes it in a single operation. The return value is a
+pointer to the sample data as interleaved signed 32-bit PCM. The returned data must be freed with drflac_free().
+
+You can pass in custom memory allocation callbacks via the pAllocationCallbacks parameter. This can be NULL in which
+case it will use DRFLAC_MALLOC, DRFLAC_REALLOC and DRFLAC_FREE.
+
+Sometimes a FLAC file won't keep track of the total sample count. In this situation the function will continuously
+read samples into a dynamically sized buffer on the heap until no samples are left.
+
+Do not call this function on a broadcast type of stream (like internet radio streams and whatnot).
+*/
+DRFLAC_API drflac_int32* drflac_open_and_read_pcm_frames_s32(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks);
+
+/* Same as drflac_open_and_read_pcm_frames_s32(), except returns signed 16-bit integer samples. */
+DRFLAC_API drflac_int16* drflac_open_and_read_pcm_frames_s16(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks);
+
+/* Same as drflac_open_and_read_pcm_frames_s32(), except returns 32-bit floating-point samples. */
+DRFLAC_API float* drflac_open_and_read_pcm_frames_f32(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks);
+
+#ifndef DR_FLAC_NO_STDIO
+/* Same as drflac_open_and_read_pcm_frames_s32() except opens the decoder from a file. */
+DRFLAC_API drflac_int32* drflac_open_file_and_read_pcm_frames_s32(const char* filename, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks);
+
+/* Same as drflac_open_file_and_read_pcm_frames_s32(), except returns signed 16-bit integer samples. */
+DRFLAC_API drflac_int16* drflac_open_file_and_read_pcm_frames_s16(const char* filename, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks);
+
+/* Same as drflac_open_file_and_read_pcm_frames_s32(), except returns 32-bit floating-point samples. */
+DRFLAC_API float* drflac_open_file_and_read_pcm_frames_f32(const char* filename, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks);
+#endif
+
+/* Same as drflac_open_and_read_pcm_frames_s32() except opens the decoder from a block of memory. */
+DRFLAC_API drflac_int32* drflac_open_memory_and_read_pcm_frames_s32(const void* data, size_t dataSize, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks);
+
+/* Same as drflac_open_memory_and_read_pcm_frames_s32(), except returns signed 16-bit integer samples. */
+DRFLAC_API drflac_int16* drflac_open_memory_and_read_pcm_frames_s16(const void* data, size_t dataSize, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks);
+
+/* Same as drflac_open_memory_and_read_pcm_frames_s32(), except returns 32-bit floating-point samples. */
+DRFLAC_API float* drflac_open_memory_and_read_pcm_frames_f32(const void* data, size_t dataSize, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks);
+
+/*
+Frees memory that was allocated internally by dr_flac.
+
+Set pAllocationCallbacks to the same object that was passed to drflac_open_*_and_read_pcm_frames_*(). If you originally passed in NULL, pass in NULL for this.
+*/
+DRFLAC_API void drflac_free(void* p, const drflac_allocation_callbacks* pAllocationCallbacks);
+
+
+/* Structure representing an iterator for vorbis comments in a VORBIS_COMMENT metadata block. */
+typedef struct
+{
+ drflac_uint32 countRemaining;
+ const char* pRunningData;
+} drflac_vorbis_comment_iterator;
+
+/*
+Initializes a vorbis comment iterator. This can be used for iterating over the vorbis comments in a VORBIS_COMMENT
+metadata block.
+*/
+DRFLAC_API void drflac_init_vorbis_comment_iterator(drflac_vorbis_comment_iterator* pIter, drflac_uint32 commentCount, const void* pComments);
+
+/*
+Goes to the next vorbis comment in the given iterator. If null is returned it means there are no more comments. The
+returned string is NOT null terminated.
+*/
+DRFLAC_API const char* drflac_next_vorbis_comment(drflac_vorbis_comment_iterator* pIter, drflac_uint32* pCommentLengthOut);
+
+
+/* Structure representing an iterator for cuesheet tracks in a CUESHEET metadata block. */
+typedef struct
+{
+ drflac_uint32 countRemaining;
+ const char* pRunningData;
+} drflac_cuesheet_track_iterator;
+
+/* The order of members here is important because we map this directly to the raw data within the CUESHEET metadata block. */
+typedef struct
+{
+ drflac_uint64 offset;
+ drflac_uint8 index;
+ drflac_uint8 reserved[3];
+} drflac_cuesheet_track_index;
+
+typedef struct
+{
+ drflac_uint64 offset;
+ drflac_uint8 trackNumber;
+ char ISRC[12];
+ drflac_bool8 isAudio;
+ drflac_bool8 preEmphasis;
+ drflac_uint8 indexCount;
+ const drflac_cuesheet_track_index* pIndexPoints;
+} drflac_cuesheet_track;
+
+/*
+Initializes a cuesheet track iterator. This can be used for iterating over the cuesheet tracks in a CUESHEET metadata
+block.
+*/
+DRFLAC_API void drflac_init_cuesheet_track_iterator(drflac_cuesheet_track_iterator* pIter, drflac_uint32 trackCount, const void* pTrackData);
+
+/* Goes to the next cuesheet track in the given iterator. If DRFLAC_FALSE is returned it means there are no more comments. */
+DRFLAC_API drflac_bool32 drflac_next_cuesheet_track(drflac_cuesheet_track_iterator* pIter, drflac_cuesheet_track* pCuesheetTrack);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* dr_flac_h */
+
+
+/************************************************************************************************************************************************************
+ ************************************************************************************************************************************************************
+
+ IMPLEMENTATION
+
+ ************************************************************************************************************************************************************
+ ************************************************************************************************************************************************************/
+#if defined(DR_FLAC_IMPLEMENTATION) || defined(DRFLAC_IMPLEMENTATION)
+#ifndef dr_flac_c
+#define dr_flac_c
+
+/* Disable some annoying warnings. */
+#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
+ #pragma GCC diagnostic push
+ #if __GNUC__ >= 7
+ #pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
+ #endif
+#endif
+
+#ifdef __linux__
+ #ifndef _BSD_SOURCE
+ #define _BSD_SOURCE
+ #endif
+ #ifndef _DEFAULT_SOURCE
+ #define _DEFAULT_SOURCE
+ #endif
+ #ifndef __USE_BSD
+ #define __USE_BSD
+ #endif
+ #include
+#endif
+
+#include
+#include
+
+/* Inline */
+#ifdef _MSC_VER
+ #define DRFLAC_INLINE __forceinline
+#elif defined(__GNUC__)
+ /*
+ I've had a bug report where GCC is emitting warnings about functions possibly not being inlineable. This warning happens when
+ the __attribute__((always_inline)) attribute is defined without an "inline" statement. I think therefore there must be some
+ case where "__inline__" is not always defined, thus the compiler emitting these warnings. When using -std=c89 or -ansi on the
+ command line, we cannot use the "inline" keyword and instead need to use "__inline__". In an attempt to work around this issue
+ I am using "__inline__" only when we're compiling in strict ANSI mode.
+ */
+ #if defined(__STRICT_ANSI__)
+ #define DRFLAC_GNUC_INLINE_HINT __inline__
+ #else
+ #define DRFLAC_GNUC_INLINE_HINT inline
+ #endif
+
+ #if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 2)) || defined(__clang__)
+ #define DRFLAC_INLINE DRFLAC_GNUC_INLINE_HINT __attribute__((always_inline))
+ #else
+ #define DRFLAC_INLINE DRFLAC_GNUC_INLINE_HINT
+ #endif
+#elif defined(__WATCOMC__)
+ #define DRFLAC_INLINE __inline
+#else
+ #define DRFLAC_INLINE
+#endif
+/* End Inline */
+
+/*
+Intrinsics Support
+
+There's a bug in GCC 4.2.x which results in an incorrect compilation error when using _mm_slli_epi32() where it complains with
+
+ "error: shift must be an immediate"
+
+Unfortuantely dr_flac depends on this for a few things so we're just going to disable SSE on GCC 4.2 and below.
+*/
+#if !defined(DR_FLAC_NO_SIMD)
+ #if defined(DRFLAC_X64) || defined(DRFLAC_X86)
+ #if defined(_MSC_VER) && !defined(__clang__)
+ /* MSVC. */
+ #if _MSC_VER >= 1400 && !defined(DRFLAC_NO_SSE2) /* 2005 */
+ #define DRFLAC_SUPPORT_SSE2
+ #endif
+ #if _MSC_VER >= 1600 && !defined(DRFLAC_NO_SSE41) /* 2010 */
+ #define DRFLAC_SUPPORT_SSE41
+ #endif
+ #elif defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)))
+ /* Assume GNUC-style. */
+ #if defined(__SSE2__) && !defined(DRFLAC_NO_SSE2)
+ #define DRFLAC_SUPPORT_SSE2
+ #endif
+ #if defined(__SSE4_1__) && !defined(DRFLAC_NO_SSE41)
+ #define DRFLAC_SUPPORT_SSE41
+ #endif
+ #endif
+
+ /* If at this point we still haven't determined compiler support for the intrinsics just fall back to __has_include. */
+ #if !defined(__GNUC__) && !defined(__clang__) && defined(__has_include)
+ #if !defined(DRFLAC_SUPPORT_SSE2) && !defined(DRFLAC_NO_SSE2) && __has_include()
+ #define DRFLAC_SUPPORT_SSE2
+ #endif
+ #if !defined(DRFLAC_SUPPORT_SSE41) && !defined(DRFLAC_NO_SSE41) && __has_include()
+ #define DRFLAC_SUPPORT_SSE41
+ #endif
+ #endif
+
+ #if defined(DRFLAC_SUPPORT_SSE41)
+ #include
+ #elif defined(DRFLAC_SUPPORT_SSE2)
+ #include
+ #endif
+ #endif
+
+ #if defined(DRFLAC_ARM)
+ #if !defined(DRFLAC_NO_NEON) && (defined(__ARM_NEON) || defined(__aarch64__) || defined(_M_ARM64))
+ #define DRFLAC_SUPPORT_NEON
+ #include
+ #endif
+ #endif
+#endif
+
+/* Compile-time CPU feature support. */
+#if !defined(DR_FLAC_NO_SIMD) && (defined(DRFLAC_X86) || defined(DRFLAC_X64))
+ #if defined(_MSC_VER) && !defined(__clang__)
+ #if _MSC_VER >= 1400
+ #include
+ static void drflac__cpuid(int info[4], int fid)
+ {
+ __cpuid(info, fid);
+ }
+ #else
+ #define DRFLAC_NO_CPUID
+ #endif
+ #else
+ #if defined(__GNUC__) || defined(__clang__)
+ static void drflac__cpuid(int info[4], int fid)
+ {
+ /*
+ It looks like the -fPIC option uses the ebx register which GCC complains about. We can work around this by just using a different register, the
+ specific register of which I'm letting the compiler decide on. The "k" prefix is used to specify a 32-bit register. The {...} syntax is for
+ supporting different assembly dialects.
+
+ What's basically happening is that we're saving and restoring the ebx register manually.
+ */
+ #if defined(DRFLAC_X86) && defined(__PIC__)
+ __asm__ __volatile__ (
+ "xchg{l} {%%}ebx, %k1;"
+ "cpuid;"
+ "xchg{l} {%%}ebx, %k1;"
+ : "=a"(info[0]), "=&r"(info[1]), "=c"(info[2]), "=d"(info[3]) : "a"(fid), "c"(0)
+ );
+ #else
+ __asm__ __volatile__ (
+ "cpuid" : "=a"(info[0]), "=b"(info[1]), "=c"(info[2]), "=d"(info[3]) : "a"(fid), "c"(0)
+ );
+ #endif
+ }
+ #else
+ #define DRFLAC_NO_CPUID
+ #endif
+ #endif
+#else
+ #define DRFLAC_NO_CPUID
+#endif
+
+static DRFLAC_INLINE drflac_bool32 drflac_has_sse2(void)
+{
+#if defined(DRFLAC_SUPPORT_SSE2)
+ #if (defined(DRFLAC_X64) || defined(DRFLAC_X86)) && !defined(DRFLAC_NO_SSE2)
+ #if defined(DRFLAC_X64)
+ return DRFLAC_TRUE; /* 64-bit targets always support SSE2. */
+ #elif (defined(_M_IX86_FP) && _M_IX86_FP == 2) || defined(__SSE2__)
+ return DRFLAC_TRUE; /* If the compiler is allowed to freely generate SSE2 code we can assume support. */
+ #else
+ #if defined(DRFLAC_NO_CPUID)
+ return DRFLAC_FALSE;
+ #else
+ int info[4];
+ drflac__cpuid(info, 1);
+ return (info[3] & (1 << 26)) != 0;
+ #endif
+ #endif
+ #else
+ return DRFLAC_FALSE; /* SSE2 is only supported on x86 and x64 architectures. */
+ #endif
+#else
+ return DRFLAC_FALSE; /* No compiler support. */
+#endif
+}
+
+static DRFLAC_INLINE drflac_bool32 drflac_has_sse41(void)
+{
+#if defined(DRFLAC_SUPPORT_SSE41)
+ #if (defined(DRFLAC_X64) || defined(DRFLAC_X86)) && !defined(DRFLAC_NO_SSE41)
+ #if defined(__SSE4_1__) || defined(__AVX__)
+ return DRFLAC_TRUE; /* If the compiler is allowed to freely generate SSE41 code we can assume support. */
+ #else
+ #if defined(DRFLAC_NO_CPUID)
+ return DRFLAC_FALSE;
+ #else
+ int info[4];
+ drflac__cpuid(info, 1);
+ return (info[2] & (1 << 19)) != 0;
+ #endif
+ #endif
+ #else
+ return DRFLAC_FALSE; /* SSE41 is only supported on x86 and x64 architectures. */
+ #endif
+#else
+ return DRFLAC_FALSE; /* No compiler support. */
+#endif
+}
+
+
+#if defined(_MSC_VER) && _MSC_VER >= 1500 && (defined(DRFLAC_X86) || defined(DRFLAC_X64)) && !defined(__clang__)
+ #define DRFLAC_HAS_LZCNT_INTRINSIC
+#elif (defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)))
+ #define DRFLAC_HAS_LZCNT_INTRINSIC
+#elif defined(__clang__)
+ #if defined(__has_builtin)
+ #if __has_builtin(__builtin_clzll) || __has_builtin(__builtin_clzl)
+ #define DRFLAC_HAS_LZCNT_INTRINSIC
+ #endif
+ #endif
+#endif
+
+#if defined(_MSC_VER) && _MSC_VER >= 1400 && !defined(__clang__)
+ #define DRFLAC_HAS_BYTESWAP16_INTRINSIC
+ #define DRFLAC_HAS_BYTESWAP32_INTRINSIC
+ #define DRFLAC_HAS_BYTESWAP64_INTRINSIC
+#elif defined(__clang__)
+ #if defined(__has_builtin)
+ #if __has_builtin(__builtin_bswap16)
+ #define DRFLAC_HAS_BYTESWAP16_INTRINSIC
+ #endif
+ #if __has_builtin(__builtin_bswap32)
+ #define DRFLAC_HAS_BYTESWAP32_INTRINSIC
+ #endif
+ #if __has_builtin(__builtin_bswap64)
+ #define DRFLAC_HAS_BYTESWAP64_INTRINSIC
+ #endif
+ #endif
+#elif defined(__GNUC__)
+ #if ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
+ #define DRFLAC_HAS_BYTESWAP32_INTRINSIC
+ #define DRFLAC_HAS_BYTESWAP64_INTRINSIC
+ #endif
+ #if ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))
+ #define DRFLAC_HAS_BYTESWAP16_INTRINSIC
+ #endif
+#elif defined(__WATCOMC__) && defined(__386__)
+ #define DRFLAC_HAS_BYTESWAP16_INTRINSIC
+ #define DRFLAC_HAS_BYTESWAP32_INTRINSIC
+ #define DRFLAC_HAS_BYTESWAP64_INTRINSIC
+ extern __inline drflac_uint16 _watcom_bswap16(drflac_uint16);
+ extern __inline drflac_uint32 _watcom_bswap32(drflac_uint32);
+ extern __inline drflac_uint64 _watcom_bswap64(drflac_uint64);
+#pragma aux _watcom_bswap16 = \
+ "xchg al, ah" \
+ parm [ax] \
+ value [ax] \
+ modify nomemory;
+#pragma aux _watcom_bswap32 = \
+ "bswap eax" \
+ parm [eax] \
+ value [eax] \
+ modify nomemory;
+#pragma aux _watcom_bswap64 = \
+ "bswap eax" \
+ "bswap edx" \
+ "xchg eax,edx" \
+ parm [eax edx] \
+ value [eax edx] \
+ modify nomemory;
+#endif
+
+
+/* Standard library stuff. */
+#ifndef DRFLAC_ASSERT
+#include
+#define DRFLAC_ASSERT(expression) assert(expression)
+#endif
+#ifndef DRFLAC_MALLOC
+#define DRFLAC_MALLOC(sz) malloc((sz))
+#endif
+#ifndef DRFLAC_REALLOC
+#define DRFLAC_REALLOC(p, sz) realloc((p), (sz))
+#endif
+#ifndef DRFLAC_FREE
+#define DRFLAC_FREE(p) free((p))
+#endif
+#ifndef DRFLAC_COPY_MEMORY
+#define DRFLAC_COPY_MEMORY(dst, src, sz) memcpy((dst), (src), (sz))
+#endif
+#ifndef DRFLAC_ZERO_MEMORY
+#define DRFLAC_ZERO_MEMORY(p, sz) memset((p), 0, (sz))
+#endif
+#ifndef DRFLAC_ZERO_OBJECT
+#define DRFLAC_ZERO_OBJECT(p) DRFLAC_ZERO_MEMORY((p), sizeof(*(p)))
+#endif
+
+#define DRFLAC_MAX_SIMD_VECTOR_SIZE 64 /* 64 for AVX-512 in the future. */
+
+/* Result Codes */
+typedef drflac_int32 drflac_result;
+#define DRFLAC_SUCCESS 0
+#define DRFLAC_ERROR -1 /* A generic error. */
+#define DRFLAC_INVALID_ARGS -2
+#define DRFLAC_INVALID_OPERATION -3
+#define DRFLAC_OUT_OF_MEMORY -4
+#define DRFLAC_OUT_OF_RANGE -5
+#define DRFLAC_ACCESS_DENIED -6
+#define DRFLAC_DOES_NOT_EXIST -7
+#define DRFLAC_ALREADY_EXISTS -8
+#define DRFLAC_TOO_MANY_OPEN_FILES -9
+#define DRFLAC_INVALID_FILE -10
+#define DRFLAC_TOO_BIG -11
+#define DRFLAC_PATH_TOO_LONG -12
+#define DRFLAC_NAME_TOO_LONG -13
+#define DRFLAC_NOT_DIRECTORY -14
+#define DRFLAC_IS_DIRECTORY -15
+#define DRFLAC_DIRECTORY_NOT_EMPTY -16
+#define DRFLAC_END_OF_FILE -17
+#define DRFLAC_NO_SPACE -18
+#define DRFLAC_BUSY -19
+#define DRFLAC_IO_ERROR -20
+#define DRFLAC_INTERRUPT -21
+#define DRFLAC_UNAVAILABLE -22
+#define DRFLAC_ALREADY_IN_USE -23
+#define DRFLAC_BAD_ADDRESS -24
+#define DRFLAC_BAD_SEEK -25
+#define DRFLAC_BAD_PIPE -26
+#define DRFLAC_DEADLOCK -27
+#define DRFLAC_TOO_MANY_LINKS -28
+#define DRFLAC_NOT_IMPLEMENTED -29
+#define DRFLAC_NO_MESSAGE -30
+#define DRFLAC_BAD_MESSAGE -31
+#define DRFLAC_NO_DATA_AVAILABLE -32
+#define DRFLAC_INVALID_DATA -33
+#define DRFLAC_TIMEOUT -34
+#define DRFLAC_NO_NETWORK -35
+#define DRFLAC_NOT_UNIQUE -36
+#define DRFLAC_NOT_SOCKET -37
+#define DRFLAC_NO_ADDRESS -38
+#define DRFLAC_BAD_PROTOCOL -39
+#define DRFLAC_PROTOCOL_UNAVAILABLE -40
+#define DRFLAC_PROTOCOL_NOT_SUPPORTED -41
+#define DRFLAC_PROTOCOL_FAMILY_NOT_SUPPORTED -42
+#define DRFLAC_ADDRESS_FAMILY_NOT_SUPPORTED -43
+#define DRFLAC_SOCKET_NOT_SUPPORTED -44
+#define DRFLAC_CONNECTION_RESET -45
+#define DRFLAC_ALREADY_CONNECTED -46
+#define DRFLAC_NOT_CONNECTED -47
+#define DRFLAC_CONNECTION_REFUSED -48
+#define DRFLAC_NO_HOST -49
+#define DRFLAC_IN_PROGRESS -50
+#define DRFLAC_CANCELLED -51
+#define DRFLAC_MEMORY_ALREADY_MAPPED -52
+#define DRFLAC_AT_END -53
+
+#define DRFLAC_CRC_MISMATCH -100
+/* End Result Codes */
+
+
+#define DRFLAC_SUBFRAME_CONSTANT 0
+#define DRFLAC_SUBFRAME_VERBATIM 1
+#define DRFLAC_SUBFRAME_FIXED 8
+#define DRFLAC_SUBFRAME_LPC 32
+#define DRFLAC_SUBFRAME_RESERVED 255
+
+#define DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE 0
+#define DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE2 1
+
+#define DRFLAC_CHANNEL_ASSIGNMENT_INDEPENDENT 0
+#define DRFLAC_CHANNEL_ASSIGNMENT_LEFT_SIDE 8
+#define DRFLAC_CHANNEL_ASSIGNMENT_RIGHT_SIDE 9
+#define DRFLAC_CHANNEL_ASSIGNMENT_MID_SIDE 10
+
+#define DRFLAC_SEEKPOINT_SIZE_IN_BYTES 18
+#define DRFLAC_CUESHEET_TRACK_SIZE_IN_BYTES 36
+#define DRFLAC_CUESHEET_TRACK_INDEX_SIZE_IN_BYTES 12
+
+#define drflac_align(x, a) ((((x) + (a) - 1) / (a)) * (a))
+
+
+DRFLAC_API void drflac_version(drflac_uint32* pMajor, drflac_uint32* pMinor, drflac_uint32* pRevision)
+{
+ if (pMajor) {
+ *pMajor = DRFLAC_VERSION_MAJOR;
+ }
+
+ if (pMinor) {
+ *pMinor = DRFLAC_VERSION_MINOR;
+ }
+
+ if (pRevision) {
+ *pRevision = DRFLAC_VERSION_REVISION;
+ }
+}
+
+DRFLAC_API const char* drflac_version_string(void)
+{
+ return DRFLAC_VERSION_STRING;
+}
+
+
+/* CPU caps. */
+#if defined(__has_feature)
+ #if __has_feature(thread_sanitizer)
+ #define DRFLAC_NO_THREAD_SANITIZE __attribute__((no_sanitize("thread")))
+ #else
+ #define DRFLAC_NO_THREAD_SANITIZE
+ #endif
+#else
+ #define DRFLAC_NO_THREAD_SANITIZE
+#endif
+
+#if defined(DRFLAC_HAS_LZCNT_INTRINSIC)
+static drflac_bool32 drflac__gIsLZCNTSupported = DRFLAC_FALSE;
+#endif
+
+#ifndef DRFLAC_NO_CPUID
+static drflac_bool32 drflac__gIsSSE2Supported = DRFLAC_FALSE;
+static drflac_bool32 drflac__gIsSSE41Supported = DRFLAC_FALSE;
+
+/*
+I've had a bug report that Clang's ThreadSanitizer presents a warning in this function. Having reviewed this, this does
+actually make sense. However, since CPU caps should never differ for a running process, I don't think the trade off of
+complicating internal API's by passing around CPU caps versus just disabling the warnings is worthwhile. I'm therefore
+just going to disable these warnings. This is disabled via the DRFLAC_NO_THREAD_SANITIZE attribute.
+*/
+DRFLAC_NO_THREAD_SANITIZE static void drflac__init_cpu_caps(void)
+{
+ static drflac_bool32 isCPUCapsInitialized = DRFLAC_FALSE;
+
+ if (!isCPUCapsInitialized) {
+ /* LZCNT */
+#if defined(DRFLAC_HAS_LZCNT_INTRINSIC)
+ int info[4] = {0};
+ drflac__cpuid(info, 0x80000001);
+ drflac__gIsLZCNTSupported = (info[2] & (1 << 5)) != 0;
+#endif
+
+ /* SSE2 */
+ drflac__gIsSSE2Supported = drflac_has_sse2();
+
+ /* SSE4.1 */
+ drflac__gIsSSE41Supported = drflac_has_sse41();
+
+ /* Initialized. */
+ isCPUCapsInitialized = DRFLAC_TRUE;
+ }
+}
+#else
+static drflac_bool32 drflac__gIsNEONSupported = DRFLAC_FALSE;
+
+static DRFLAC_INLINE drflac_bool32 drflac__has_neon(void)
+{
+#if defined(DRFLAC_SUPPORT_NEON)
+ #if defined(DRFLAC_ARM) && !defined(DRFLAC_NO_NEON)
+ #if (defined(__ARM_NEON) || defined(__aarch64__) || defined(_M_ARM64))
+ return DRFLAC_TRUE; /* If the compiler is allowed to freely generate NEON code we can assume support. */
+ #else
+ /* TODO: Runtime check. */
+ return DRFLAC_FALSE;
+ #endif
+ #else
+ return DRFLAC_FALSE; /* NEON is only supported on ARM architectures. */
+ #endif
+#else
+ return DRFLAC_FALSE; /* No compiler support. */
+#endif
+}
+
+DRFLAC_NO_THREAD_SANITIZE static void drflac__init_cpu_caps(void)
+{
+ drflac__gIsNEONSupported = drflac__has_neon();
+
+#if defined(DRFLAC_HAS_LZCNT_INTRINSIC) && defined(DRFLAC_ARM) && (defined(__ARM_ARCH) && __ARM_ARCH >= 5)
+ drflac__gIsLZCNTSupported = DRFLAC_TRUE;
+#endif
+}
+#endif
+
+
+/* Endian Management */
+static DRFLAC_INLINE drflac_bool32 drflac__is_little_endian(void)
+{
+#if defined(DRFLAC_X86) || defined(DRFLAC_X64)
+ return DRFLAC_TRUE;
+#elif defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && __BYTE_ORDER == __LITTLE_ENDIAN
+ return DRFLAC_TRUE;
+#else
+ int n = 1;
+ return (*(char*)&n) == 1;
+#endif
+}
+
+static DRFLAC_INLINE drflac_uint16 drflac__swap_endian_uint16(drflac_uint16 n)
+{
+#ifdef DRFLAC_HAS_BYTESWAP16_INTRINSIC
+ #if defined(_MSC_VER) && !defined(__clang__)
+ return _byteswap_ushort(n);
+ #elif defined(__GNUC__) || defined(__clang__)
+ return __builtin_bswap16(n);
+ #elif defined(__WATCOMC__) && defined(__386__)
+ return _watcom_bswap16(n);
+ #else
+ #error "This compiler does not support the byte swap intrinsic."
+ #endif
+#else
+ return ((n & 0xFF00) >> 8) |
+ ((n & 0x00FF) << 8);
+#endif
+}
+
+static DRFLAC_INLINE drflac_uint32 drflac__swap_endian_uint32(drflac_uint32 n)
+{
+#ifdef DRFLAC_HAS_BYTESWAP32_INTRINSIC
+ #if defined(_MSC_VER) && !defined(__clang__)
+ return _byteswap_ulong(n);
+ #elif defined(__GNUC__) || defined(__clang__)
+ #if defined(DRFLAC_ARM) && (defined(__ARM_ARCH) && __ARM_ARCH >= 6) && !defined(__ARM_ARCH_6M__) && !defined(DRFLAC_64BIT) /* <-- 64-bit inline assembly has not been tested, so disabling for now. */
+ /* Inline assembly optimized implementation for ARM. In my testing, GCC does not generate optimized code with __builtin_bswap32(). */
+ drflac_uint32 r;
+ __asm__ __volatile__ (
+ #if defined(DRFLAC_64BIT)
+ "rev %w[out], %w[in]" : [out]"=r"(r) : [in]"r"(n) /* <-- This is untested. If someone in the community could test this, that would be appreciated! */
+ #else
+ "rev %[out], %[in]" : [out]"=r"(r) : [in]"r"(n)
+ #endif
+ );
+ return r;
+ #else
+ return __builtin_bswap32(n);
+ #endif
+ #elif defined(__WATCOMC__) && defined(__386__)
+ return _watcom_bswap32(n);
+ #else
+ #error "This compiler does not support the byte swap intrinsic."
+ #endif
+#else
+ return ((n & 0xFF000000) >> 24) |
+ ((n & 0x00FF0000) >> 8) |
+ ((n & 0x0000FF00) << 8) |
+ ((n & 0x000000FF) << 24);
+#endif
+}
+
+static DRFLAC_INLINE drflac_uint64 drflac__swap_endian_uint64(drflac_uint64 n)
+{
+#ifdef DRFLAC_HAS_BYTESWAP64_INTRINSIC
+ #if defined(_MSC_VER) && !defined(__clang__)
+ return _byteswap_uint64(n);
+ #elif defined(__GNUC__) || defined(__clang__)
+ return __builtin_bswap64(n);
+ #elif defined(__WATCOMC__) && defined(__386__)
+ return _watcom_bswap64(n);
+ #else
+ #error "This compiler does not support the byte swap intrinsic."
+ #endif
+#else
+ /* Weird "<< 32" bitshift is required for C89 because it doesn't support 64-bit constants. Should be optimized out by a good compiler. */
+ return ((n & ((drflac_uint64)0xFF000000 << 32)) >> 56) |
+ ((n & ((drflac_uint64)0x00FF0000 << 32)) >> 40) |
+ ((n & ((drflac_uint64)0x0000FF00 << 32)) >> 24) |
+ ((n & ((drflac_uint64)0x000000FF << 32)) >> 8) |
+ ((n & ((drflac_uint64)0xFF000000 )) << 8) |
+ ((n & ((drflac_uint64)0x00FF0000 )) << 24) |
+ ((n & ((drflac_uint64)0x0000FF00 )) << 40) |
+ ((n & ((drflac_uint64)0x000000FF )) << 56);
+#endif
+}
+
+
+static DRFLAC_INLINE drflac_uint16 drflac__be2host_16(drflac_uint16 n)
+{
+ if (drflac__is_little_endian()) {
+ return drflac__swap_endian_uint16(n);
+ }
+
+ return n;
+}
+
+static DRFLAC_INLINE drflac_uint32 drflac__be2host_32(drflac_uint32 n)
+{
+ if (drflac__is_little_endian()) {
+ return drflac__swap_endian_uint32(n);
+ }
+
+ return n;
+}
+
+static DRFLAC_INLINE drflac_uint32 drflac__be2host_32_ptr_unaligned(const void* pData)
+{
+ const drflac_uint8* pNum = (drflac_uint8*)pData;
+ return *(pNum) << 24 | *(pNum+1) << 16 | *(pNum+2) << 8 | *(pNum+3);
+}
+
+static DRFLAC_INLINE drflac_uint64 drflac__be2host_64(drflac_uint64 n)
+{
+ if (drflac__is_little_endian()) {
+ return drflac__swap_endian_uint64(n);
+ }
+
+ return n;
+}
+
+
+static DRFLAC_INLINE drflac_uint32 drflac__le2host_32(drflac_uint32 n)
+{
+ if (!drflac__is_little_endian()) {
+ return drflac__swap_endian_uint32(n);
+ }
+
+ return n;
+}
+
+static DRFLAC_INLINE drflac_uint32 drflac__le2host_32_ptr_unaligned(const void* pData)
+{
+ const drflac_uint8* pNum = (drflac_uint8*)pData;
+ return *pNum | *(pNum+1) << 8 | *(pNum+2) << 16 | *(pNum+3) << 24;
+}
+
+
+static DRFLAC_INLINE drflac_uint32 drflac__unsynchsafe_32(drflac_uint32 n)
+{
+ drflac_uint32 result = 0;
+ result |= (n & 0x7F000000) >> 3;
+ result |= (n & 0x007F0000) >> 2;
+ result |= (n & 0x00007F00) >> 1;
+ result |= (n & 0x0000007F) >> 0;
+
+ return result;
+}
+
+
+
+/* The CRC code below is based on this document: http://zlib.net/crc_v3.txt */
+static drflac_uint8 drflac__crc8_table[] = {
+ 0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15, 0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D,
+ 0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65, 0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D,
+ 0xE0, 0xE7, 0xEE, 0xE9, 0xFC, 0xFB, 0xF2, 0xF5, 0xD8, 0xDF, 0xD6, 0xD1, 0xC4, 0xC3, 0xCA, 0xCD,
+ 0x90, 0x97, 0x9E, 0x99, 0x8C, 0x8B, 0x82, 0x85, 0xA8, 0xAF, 0xA6, 0xA1, 0xB4, 0xB3, 0xBA, 0xBD,
+ 0xC7, 0xC0, 0xC9, 0xCE, 0xDB, 0xDC, 0xD5, 0xD2, 0xFF, 0xF8, 0xF1, 0xF6, 0xE3, 0xE4, 0xED, 0xEA,
+ 0xB7, 0xB0, 0xB9, 0xBE, 0xAB, 0xAC, 0xA5, 0xA2, 0x8F, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9D, 0x9A,
+ 0x27, 0x20, 0x29, 0x2E, 0x3B, 0x3C, 0x35, 0x32, 0x1F, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0D, 0x0A,
+ 0x57, 0x50, 0x59, 0x5E, 0x4B, 0x4C, 0x45, 0x42, 0x6F, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7D, 0x7A,
+ 0x89, 0x8E, 0x87, 0x80, 0x95, 0x92, 0x9B, 0x9C, 0xB1, 0xB6, 0xBF, 0xB8, 0xAD, 0xAA, 0xA3, 0xA4,
+ 0xF9, 0xFE, 0xF7, 0xF0, 0xE5, 0xE2, 0xEB, 0xEC, 0xC1, 0xC6, 0xCF, 0xC8, 0xDD, 0xDA, 0xD3, 0xD4,
+ 0x69, 0x6E, 0x67, 0x60, 0x75, 0x72, 0x7B, 0x7C, 0x51, 0x56, 0x5F, 0x58, 0x4D, 0x4A, 0x43, 0x44,
+ 0x19, 0x1E, 0x17, 0x10, 0x05, 0x02, 0x0B, 0x0C, 0x21, 0x26, 0x2F, 0x28, 0x3D, 0x3A, 0x33, 0x34,
+ 0x4E, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5C, 0x5B, 0x76, 0x71, 0x78, 0x7F, 0x6A, 0x6D, 0x64, 0x63,
+ 0x3E, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2C, 0x2B, 0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13,
+ 0xAE, 0xA9, 0xA0, 0xA7, 0xB2, 0xB5, 0xBC, 0xBB, 0x96, 0x91, 0x98, 0x9F, 0x8A, 0x8D, 0x84, 0x83,
+ 0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB, 0xE6, 0xE1, 0xE8, 0xEF, 0xFA, 0xFD, 0xF4, 0xF3
+};
+
+static drflac_uint16 drflac__crc16_table[] = {
+ 0x0000, 0x8005, 0x800F, 0x000A, 0x801B, 0x001E, 0x0014, 0x8011,
+ 0x8033, 0x0036, 0x003C, 0x8039, 0x0028, 0x802D, 0x8027, 0x0022,
+ 0x8063, 0x0066, 0x006C, 0x8069, 0x0078, 0x807D, 0x8077, 0x0072,
+ 0x0050, 0x8055, 0x805F, 0x005A, 0x804B, 0x004E, 0x0044, 0x8041,
+ 0x80C3, 0x00C6, 0x00CC, 0x80C9, 0x00D8, 0x80DD, 0x80D7, 0x00D2,
+ 0x00F0, 0x80F5, 0x80FF, 0x00FA, 0x80EB, 0x00EE, 0x00E4, 0x80E1,
+ 0x00A0, 0x80A5, 0x80AF, 0x00AA, 0x80BB, 0x00BE, 0x00B4, 0x80B1,
+ 0x8093, 0x0096, 0x009C, 0x8099, 0x0088, 0x808D, 0x8087, 0x0082,
+ 0x8183, 0x0186, 0x018C, 0x8189, 0x0198, 0x819D, 0x8197, 0x0192,
+ 0x01B0, 0x81B5, 0x81BF, 0x01BA, 0x81AB, 0x01AE, 0x01A4, 0x81A1,
+ 0x01E0, 0x81E5, 0x81EF, 0x01EA, 0x81FB, 0x01FE, 0x01F4, 0x81F1,
+ 0x81D3, 0x01D6, 0x01DC, 0x81D9, 0x01C8, 0x81CD, 0x81C7, 0x01C2,
+ 0x0140, 0x8145, 0x814F, 0x014A, 0x815B, 0x015E, 0x0154, 0x8151,
+ 0x8173, 0x0176, 0x017C, 0x8179, 0x0168, 0x816D, 0x8167, 0x0162,
+ 0x8123, 0x0126, 0x012C, 0x8129, 0x0138, 0x813D, 0x8137, 0x0132,
+ 0x0110, 0x8115, 0x811F, 0x011A, 0x810B, 0x010E, 0x0104, 0x8101,
+ 0x8303, 0x0306, 0x030C, 0x8309, 0x0318, 0x831D, 0x8317, 0x0312,
+ 0x0330, 0x8335, 0x833F, 0x033A, 0x832B, 0x032E, 0x0324, 0x8321,
+ 0x0360, 0x8365, 0x836F, 0x036A, 0x837B, 0x037E, 0x0374, 0x8371,
+ 0x8353, 0x0356, 0x035C, 0x8359, 0x0348, 0x834D, 0x8347, 0x0342,
+ 0x03C0, 0x83C5, 0x83CF, 0x03CA, 0x83DB, 0x03DE, 0x03D4, 0x83D1,
+ 0x83F3, 0x03F6, 0x03FC, 0x83F9, 0x03E8, 0x83ED, 0x83E7, 0x03E2,
+ 0x83A3, 0x03A6, 0x03AC, 0x83A9, 0x03B8, 0x83BD, 0x83B7, 0x03B2,
+ 0x0390, 0x8395, 0x839F, 0x039A, 0x838B, 0x038E, 0x0384, 0x8381,
+ 0x0280, 0x8285, 0x828F, 0x028A, 0x829B, 0x029E, 0x0294, 0x8291,
+ 0x82B3, 0x02B6, 0x02BC, 0x82B9, 0x02A8, 0x82AD, 0x82A7, 0x02A2,
+ 0x82E3, 0x02E6, 0x02EC, 0x82E9, 0x02F8, 0x82FD, 0x82F7, 0x02F2,
+ 0x02D0, 0x82D5, 0x82DF, 0x02DA, 0x82CB, 0x02CE, 0x02C4, 0x82C1,
+ 0x8243, 0x0246, 0x024C, 0x8249, 0x0258, 0x825D, 0x8257, 0x0252,
+ 0x0270, 0x8275, 0x827F, 0x027A, 0x826B, 0x026E, 0x0264, 0x8261,
+ 0x0220, 0x8225, 0x822F, 0x022A, 0x823B, 0x023E, 0x0234, 0x8231,
+ 0x8213, 0x0216, 0x021C, 0x8219, 0x0208, 0x820D, 0x8207, 0x0202
+};
+
+static DRFLAC_INLINE drflac_uint8 drflac_crc8_byte(drflac_uint8 crc, drflac_uint8 data)
+{
+ return drflac__crc8_table[crc ^ data];
+}
+
+static DRFLAC_INLINE drflac_uint8 drflac_crc8(drflac_uint8 crc, drflac_uint32 data, drflac_uint32 count)
+{
+#ifdef DR_FLAC_NO_CRC
+ (void)crc;
+ (void)data;
+ (void)count;
+ return 0;
+#else
+#if 0
+ /* REFERENCE (use of this implementation requires an explicit flush by doing "drflac_crc8(crc, 0, 8);") */
+ drflac_uint8 p = 0x07;
+ for (int i = count-1; i >= 0; --i) {
+ drflac_uint8 bit = (data & (1 << i)) >> i;
+ if (crc & 0x80) {
+ crc = ((crc << 1) | bit) ^ p;
+ } else {
+ crc = ((crc << 1) | bit);
+ }
+ }
+ return crc;
+#else
+ drflac_uint32 wholeBytes;
+ drflac_uint32 leftoverBits;
+ drflac_uint64 leftoverDataMask;
+
+ static drflac_uint64 leftoverDataMaskTable[8] = {
+ 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F
+ };
+
+ DRFLAC_ASSERT(count <= 32);
+
+ wholeBytes = count >> 3;
+ leftoverBits = count - (wholeBytes*8);
+ leftoverDataMask = leftoverDataMaskTable[leftoverBits];
+
+ switch (wholeBytes) {
+ case 4: crc = drflac_crc8_byte(crc, (drflac_uint8)((data & (0xFF000000UL << leftoverBits)) >> (24 + leftoverBits)));
+ case 3: crc = drflac_crc8_byte(crc, (drflac_uint8)((data & (0x00FF0000UL << leftoverBits)) >> (16 + leftoverBits)));
+ case 2: crc = drflac_crc8_byte(crc, (drflac_uint8)((data & (0x0000FF00UL << leftoverBits)) >> ( 8 + leftoverBits)));
+ case 1: crc = drflac_crc8_byte(crc, (drflac_uint8)((data & (0x000000FFUL << leftoverBits)) >> ( 0 + leftoverBits)));
+ case 0: if (leftoverBits > 0) crc = (drflac_uint8)((crc << leftoverBits) ^ drflac__crc8_table[(crc >> (8 - leftoverBits)) ^ (data & leftoverDataMask)]);
+ }
+ return crc;
+#endif
+#endif
+}
+
+static DRFLAC_INLINE drflac_uint16 drflac_crc16_byte(drflac_uint16 crc, drflac_uint8 data)
+{
+ return (crc << 8) ^ drflac__crc16_table[(drflac_uint8)(crc >> 8) ^ data];
+}
+
+static DRFLAC_INLINE drflac_uint16 drflac_crc16_cache(drflac_uint16 crc, drflac_cache_t data)
+{
+#ifdef DRFLAC_64BIT
+ crc = drflac_crc16_byte(crc, (drflac_uint8)((data >> 56) & 0xFF));
+ crc = drflac_crc16_byte(crc, (drflac_uint8)((data >> 48) & 0xFF));
+ crc = drflac_crc16_byte(crc, (drflac_uint8)((data >> 40) & 0xFF));
+ crc = drflac_crc16_byte(crc, (drflac_uint8)((data >> 32) & 0xFF));
+#endif
+ crc = drflac_crc16_byte(crc, (drflac_uint8)((data >> 24) & 0xFF));
+ crc = drflac_crc16_byte(crc, (drflac_uint8)((data >> 16) & 0xFF));
+ crc = drflac_crc16_byte(crc, (drflac_uint8)((data >> 8) & 0xFF));
+ crc = drflac_crc16_byte(crc, (drflac_uint8)((data >> 0) & 0xFF));
+
+ return crc;
+}
+
+static DRFLAC_INLINE drflac_uint16 drflac_crc16_bytes(drflac_uint16 crc, drflac_cache_t data, drflac_uint32 byteCount)
+{
+ switch (byteCount)
+ {
+#ifdef DRFLAC_64BIT
+ case 8: crc = drflac_crc16_byte(crc, (drflac_uint8)((data >> 56) & 0xFF));
+ case 7: crc = drflac_crc16_byte(crc, (drflac_uint8)((data >> 48) & 0xFF));
+ case 6: crc = drflac_crc16_byte(crc, (drflac_uint8)((data >> 40) & 0xFF));
+ case 5: crc = drflac_crc16_byte(crc, (drflac_uint8)((data >> 32) & 0xFF));
+#endif
+ case 4: crc = drflac_crc16_byte(crc, (drflac_uint8)((data >> 24) & 0xFF));
+ case 3: crc = drflac_crc16_byte(crc, (drflac_uint8)((data >> 16) & 0xFF));
+ case 2: crc = drflac_crc16_byte(crc, (drflac_uint8)((data >> 8) & 0xFF));
+ case 1: crc = drflac_crc16_byte(crc, (drflac_uint8)((data >> 0) & 0xFF));
+ }
+
+ return crc;
+}
+
+#if 0
+static DRFLAC_INLINE drflac_uint16 drflac_crc16__32bit(drflac_uint16 crc, drflac_uint32 data, drflac_uint32 count)
+{
+#ifdef DR_FLAC_NO_CRC
+ (void)crc;
+ (void)data;
+ (void)count;
+ return 0;
+#else
+#if 0
+ /* REFERENCE (use of this implementation requires an explicit flush by doing "drflac_crc16(crc, 0, 16);") */
+ drflac_uint16 p = 0x8005;
+ for (int i = count-1; i >= 0; --i) {
+ drflac_uint16 bit = (data & (1ULL << i)) >> i;
+ if (r & 0x8000) {
+ r = ((r << 1) | bit) ^ p;
+ } else {
+ r = ((r << 1) | bit);
+ }
+ }
+
+ return crc;
+#else
+ drflac_uint32 wholeBytes;
+ drflac_uint32 leftoverBits;
+ drflac_uint64 leftoverDataMask;
+
+ static drflac_uint64 leftoverDataMaskTable[8] = {
+ 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F
+ };
+
+ DRFLAC_ASSERT(count <= 64);
+
+ wholeBytes = count >> 3;
+ leftoverBits = count & 7;
+ leftoverDataMask = leftoverDataMaskTable[leftoverBits];
+
+ switch (wholeBytes) {
+ default:
+ case 4: crc = drflac_crc16_byte(crc, (drflac_uint8)((data & (0xFF000000UL << leftoverBits)) >> (24 + leftoverBits)));
+ case 3: crc = drflac_crc16_byte(crc, (drflac_uint8)((data & (0x00FF0000UL << leftoverBits)) >> (16 + leftoverBits)));
+ case 2: crc = drflac_crc16_byte(crc, (drflac_uint8)((data & (0x0000FF00UL << leftoverBits)) >> ( 8 + leftoverBits)));
+ case 1: crc = drflac_crc16_byte(crc, (drflac_uint8)((data & (0x000000FFUL << leftoverBits)) >> ( 0 + leftoverBits)));
+ case 0: if (leftoverBits > 0) crc = (crc << leftoverBits) ^ drflac__crc16_table[(crc >> (16 - leftoverBits)) ^ (data & leftoverDataMask)];
+ }
+ return crc;
+#endif
+#endif
+}
+
+static DRFLAC_INLINE drflac_uint16 drflac_crc16__64bit(drflac_uint16 crc, drflac_uint64 data, drflac_uint32 count)
+{
+#ifdef DR_FLAC_NO_CRC
+ (void)crc;
+ (void)data;
+ (void)count;
+ return 0;
+#else
+ drflac_uint32 wholeBytes;
+ drflac_uint32 leftoverBits;
+ drflac_uint64 leftoverDataMask;
+
+ static drflac_uint64 leftoverDataMaskTable[8] = {
+ 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F
+ };
+
+ DRFLAC_ASSERT(count <= 64);
+
+ wholeBytes = count >> 3;
+ leftoverBits = count & 7;
+ leftoverDataMask = leftoverDataMaskTable[leftoverBits];
+
+ switch (wholeBytes) {
+ default:
+ case 8: crc = drflac_crc16_byte(crc, (drflac_uint8)((data & (((drflac_uint64)0xFF000000 << 32) << leftoverBits)) >> (56 + leftoverBits))); /* Weird "<< 32" bitshift is required for C89 because it doesn't support 64-bit constants. Should be optimized out by a good compiler. */
+ case 7: crc = drflac_crc16_byte(crc, (drflac_uint8)((data & (((drflac_uint64)0x00FF0000 << 32) << leftoverBits)) >> (48 + leftoverBits)));
+ case 6: crc = drflac_crc16_byte(crc, (drflac_uint8)((data & (((drflac_uint64)0x0000FF00 << 32) << leftoverBits)) >> (40 + leftoverBits)));
+ case 5: crc = drflac_crc16_byte(crc, (drflac_uint8)((data & (((drflac_uint64)0x000000FF << 32) << leftoverBits)) >> (32 + leftoverBits)));
+ case 4: crc = drflac_crc16_byte(crc, (drflac_uint8)((data & (((drflac_uint64)0xFF000000 ) << leftoverBits)) >> (24 + leftoverBits)));
+ case 3: crc = drflac_crc16_byte(crc, (drflac_uint8)((data & (((drflac_uint64)0x00FF0000 ) << leftoverBits)) >> (16 + leftoverBits)));
+ case 2: crc = drflac_crc16_byte(crc, (drflac_uint8)((data & (((drflac_uint64)0x0000FF00 ) << leftoverBits)) >> ( 8 + leftoverBits)));
+ case 1: crc = drflac_crc16_byte(crc, (drflac_uint8)((data & (((drflac_uint64)0x000000FF ) << leftoverBits)) >> ( 0 + leftoverBits)));
+ case 0: if (leftoverBits > 0) crc = (crc << leftoverBits) ^ drflac__crc16_table[(crc >> (16 - leftoverBits)) ^ (data & leftoverDataMask)];
+ }
+ return crc;
+#endif
+}
+
+
+static DRFLAC_INLINE drflac_uint16 drflac_crc16(drflac_uint16 crc, drflac_cache_t data, drflac_uint32 count)
+{
+#ifdef DRFLAC_64BIT
+ return drflac_crc16__64bit(crc, data, count);
+#else
+ return drflac_crc16__32bit(crc, data, count);
+#endif
+}
+#endif
+
+
+#ifdef DRFLAC_64BIT
+#define drflac__be2host__cache_line drflac__be2host_64
+#else
+#define drflac__be2host__cache_line drflac__be2host_32
+#endif
+
+/*
+BIT READING ATTEMPT #2
+
+This uses a 32- or 64-bit bit-shifted cache - as bits are read, the cache is shifted such that the first valid bit is sitting
+on the most significant bit. It uses the notion of an L1 and L2 cache (borrowed from CPU architecture), where the L1 cache
+is a 32- or 64-bit unsigned integer (depending on whether or not a 32- or 64-bit build is being compiled) and the L2 is an
+array of "cache lines", with each cache line being the same size as the L1. The L2 is a buffer of about 4KB and is where data
+from onRead() is read into.
+*/
+#define DRFLAC_CACHE_L1_SIZE_BYTES(bs) (sizeof((bs)->cache))
+#define DRFLAC_CACHE_L1_SIZE_BITS(bs) (sizeof((bs)->cache)*8)
+#define DRFLAC_CACHE_L1_BITS_REMAINING(bs) (DRFLAC_CACHE_L1_SIZE_BITS(bs) - (bs)->consumedBits)
+#define DRFLAC_CACHE_L1_SELECTION_MASK(_bitCount) (~((~(drflac_cache_t)0) >> (_bitCount)))
+#define DRFLAC_CACHE_L1_SELECTION_SHIFT(bs, _bitCount) (DRFLAC_CACHE_L1_SIZE_BITS(bs) - (_bitCount))
+#define DRFLAC_CACHE_L1_SELECT(bs, _bitCount) (((bs)->cache) & DRFLAC_CACHE_L1_SELECTION_MASK(_bitCount))
+#define DRFLAC_CACHE_L1_SELECT_AND_SHIFT(bs, _bitCount) (DRFLAC_CACHE_L1_SELECT((bs), (_bitCount)) >> DRFLAC_CACHE_L1_SELECTION_SHIFT((bs), (_bitCount)))
+#define DRFLAC_CACHE_L1_SELECT_AND_SHIFT_SAFE(bs, _bitCount)(DRFLAC_CACHE_L1_SELECT((bs), (_bitCount)) >> (DRFLAC_CACHE_L1_SELECTION_SHIFT((bs), (_bitCount)) & (DRFLAC_CACHE_L1_SIZE_BITS(bs)-1)))
+#define DRFLAC_CACHE_L2_SIZE_BYTES(bs) (sizeof((bs)->cacheL2))
+#define DRFLAC_CACHE_L2_LINE_COUNT(bs) (DRFLAC_CACHE_L2_SIZE_BYTES(bs) / sizeof((bs)->cacheL2[0]))
+#define DRFLAC_CACHE_L2_LINES_REMAINING(bs) (DRFLAC_CACHE_L2_LINE_COUNT(bs) - (bs)->nextL2Line)
+
+
+#ifndef DR_FLAC_NO_CRC
+static DRFLAC_INLINE void drflac__reset_crc16(drflac_bs* bs)
+{
+ bs->crc16 = 0;
+ bs->crc16CacheIgnoredBytes = bs->consumedBits >> 3;
+}
+
+static DRFLAC_INLINE void drflac__update_crc16(drflac_bs* bs)
+{
+ if (bs->crc16CacheIgnoredBytes == 0) {
+ bs->crc16 = drflac_crc16_cache(bs->crc16, bs->crc16Cache);
+ } else {
+ bs->crc16 = drflac_crc16_bytes(bs->crc16, bs->crc16Cache, DRFLAC_CACHE_L1_SIZE_BYTES(bs) - bs->crc16CacheIgnoredBytes);
+ bs->crc16CacheIgnoredBytes = 0;
+ }
+}
+
+static DRFLAC_INLINE drflac_uint16 drflac__flush_crc16(drflac_bs* bs)
+{
+ /* We should never be flushing in a situation where we are not aligned on a byte boundary. */
+ DRFLAC_ASSERT((DRFLAC_CACHE_L1_BITS_REMAINING(bs) & 7) == 0);
+
+ /*
+ The bits that were read from the L1 cache need to be accumulated. The number of bytes needing to be accumulated is determined
+ by the number of bits that have been consumed.
+ */
+ if (DRFLAC_CACHE_L1_BITS_REMAINING(bs) == 0) {
+ drflac__update_crc16(bs);
+ } else {
+ /* We only accumulate the consumed bits. */
+ bs->crc16 = drflac_crc16_bytes(bs->crc16, bs->crc16Cache >> DRFLAC_CACHE_L1_BITS_REMAINING(bs), (bs->consumedBits >> 3) - bs->crc16CacheIgnoredBytes);
+
+ /*
+ The bits that we just accumulated should never be accumulated again. We need to keep track of how many bytes were accumulated
+ so we can handle that later.
+ */
+ bs->crc16CacheIgnoredBytes = bs->consumedBits >> 3;
+ }
+
+ return bs->crc16;
+}
+#endif
+
+static DRFLAC_INLINE drflac_bool32 drflac__reload_l1_cache_from_l2(drflac_bs* bs)
+{
+ size_t bytesRead;
+ size_t alignedL1LineCount;
+
+ /* Fast path. Try loading straight from L2. */
+ if (bs->nextL2Line < DRFLAC_CACHE_L2_LINE_COUNT(bs)) {
+ bs->cache = bs->cacheL2[bs->nextL2Line++];
+ return DRFLAC_TRUE;
+ }
+
+ /*
+ If we get here it means we've run out of data in the L2 cache. We'll need to fetch more from the client, if there's
+ any left.
+ */
+ if (bs->unalignedByteCount > 0) {
+ return DRFLAC_FALSE; /* If we have any unaligned bytes it means there's no more aligned bytes left in the client. */
+ }
+
+ bytesRead = bs->onRead(bs->pUserData, bs->cacheL2, DRFLAC_CACHE_L2_SIZE_BYTES(bs));
+
+ bs->nextL2Line = 0;
+ if (bytesRead == DRFLAC_CACHE_L2_SIZE_BYTES(bs)) {
+ bs->cache = bs->cacheL2[bs->nextL2Line++];
+ return DRFLAC_TRUE;
+ }
+
+
+ /*
+ If we get here it means we were unable to retrieve enough data to fill the entire L2 cache. It probably
+ means we've just reached the end of the file. We need to move the valid data down to the end of the buffer
+ and adjust the index of the next line accordingly. Also keep in mind that the L2 cache must be aligned to
+ the size of the L1 so we'll need to seek backwards by any misaligned bytes.
+ */
+ alignedL1LineCount = bytesRead / DRFLAC_CACHE_L1_SIZE_BYTES(bs);
+
+ /* We need to keep track of any unaligned bytes for later use. */
+ bs->unalignedByteCount = bytesRead - (alignedL1LineCount * DRFLAC_CACHE_L1_SIZE_BYTES(bs));
+ if (bs->unalignedByteCount > 0) {
+ bs->unalignedCache = bs->cacheL2[alignedL1LineCount];
+ }
+
+ if (alignedL1LineCount > 0) {
+ size_t offset = DRFLAC_CACHE_L2_LINE_COUNT(bs) - alignedL1LineCount;
+ size_t i;
+ for (i = alignedL1LineCount; i > 0; --i) {
+ bs->cacheL2[i-1 + offset] = bs->cacheL2[i-1];
+ }
+
+ bs->nextL2Line = (drflac_uint32)offset;
+ bs->cache = bs->cacheL2[bs->nextL2Line++];
+ return DRFLAC_TRUE;
+ } else {
+ /* If we get into this branch it means we weren't able to load any L1-aligned data. */
+ bs->nextL2Line = DRFLAC_CACHE_L2_LINE_COUNT(bs);
+ return DRFLAC_FALSE;
+ }
+}
+
+static drflac_bool32 drflac__reload_cache(drflac_bs* bs)
+{
+ size_t bytesRead;
+
+#ifndef DR_FLAC_NO_CRC
+ drflac__update_crc16(bs);
+#endif
+
+ /* Fast path. Try just moving the next value in the L2 cache to the L1 cache. */
+ if (drflac__reload_l1_cache_from_l2(bs)) {
+ bs->cache = drflac__be2host__cache_line(bs->cache);
+ bs->consumedBits = 0;
+#ifndef DR_FLAC_NO_CRC
+ bs->crc16Cache = bs->cache;
+#endif
+ return DRFLAC_TRUE;
+ }
+
+ /* Slow path. */
+
+ /*
+ If we get here it means we have failed to load the L1 cache from the L2. Likely we've just reached the end of the stream and the last
+ few bytes did not meet the alignment requirements for the L2 cache. In this case we need to fall back to a slower path and read the
+ data from the unaligned cache.
+ */
+ bytesRead = bs->unalignedByteCount;
+ if (bytesRead == 0) {
+ bs->consumedBits = DRFLAC_CACHE_L1_SIZE_BITS(bs); /* <-- The stream has been exhausted, so marked the bits as consumed. */
+ return DRFLAC_FALSE;
+ }
+
+ DRFLAC_ASSERT(bytesRead < DRFLAC_CACHE_L1_SIZE_BYTES(bs));
+ bs->consumedBits = (drflac_uint32)(DRFLAC_CACHE_L1_SIZE_BYTES(bs) - bytesRead) * 8;
+
+ bs->cache = drflac__be2host__cache_line(bs->unalignedCache);
+ bs->cache &= DRFLAC_CACHE_L1_SELECTION_MASK(DRFLAC_CACHE_L1_BITS_REMAINING(bs)); /* <-- Make sure the consumed bits are always set to zero. Other parts of the library depend on this property. */
+ bs->unalignedByteCount = 0; /* <-- At this point the unaligned bytes have been moved into the cache and we thus have no more unaligned bytes. */
+
+#ifndef DR_FLAC_NO_CRC
+ bs->crc16Cache = bs->cache >> bs->consumedBits;
+ bs->crc16CacheIgnoredBytes = bs->consumedBits >> 3;
+#endif
+ return DRFLAC_TRUE;
+}
+
+static void drflac__reset_cache(drflac_bs* bs)
+{
+ bs->nextL2Line = DRFLAC_CACHE_L2_LINE_COUNT(bs); /* <-- This clears the L2 cache. */
+ bs->consumedBits = DRFLAC_CACHE_L1_SIZE_BITS(bs); /* <-- This clears the L1 cache. */
+ bs->cache = 0;
+ bs->unalignedByteCount = 0; /* <-- This clears the trailing unaligned bytes. */
+ bs->unalignedCache = 0;
+
+#ifndef DR_FLAC_NO_CRC
+ bs->crc16Cache = 0;
+ bs->crc16CacheIgnoredBytes = 0;
+#endif
+}
+
+
+static DRFLAC_INLINE drflac_bool32 drflac__read_uint32(drflac_bs* bs, unsigned int bitCount, drflac_uint32* pResultOut)
+{
+ DRFLAC_ASSERT(bs != NULL);
+ DRFLAC_ASSERT(pResultOut != NULL);
+ DRFLAC_ASSERT(bitCount > 0);
+ DRFLAC_ASSERT(bitCount <= 32);
+
+ if (bs->consumedBits == DRFLAC_CACHE_L1_SIZE_BITS(bs)) {
+ if (!drflac__reload_cache(bs)) {
+ return DRFLAC_FALSE;
+ }
+ }
+
+ if (bitCount <= DRFLAC_CACHE_L1_BITS_REMAINING(bs)) {
+ /*
+ If we want to load all 32-bits from a 32-bit cache we need to do it slightly differently because we can't do
+ a 32-bit shift on a 32-bit integer. This will never be the case on 64-bit caches, so we can have a slightly
+ more optimal solution for this.
+ */
+#ifdef DRFLAC_64BIT
+ *pResultOut = (drflac_uint32)DRFLAC_CACHE_L1_SELECT_AND_SHIFT(bs, bitCount);
+ bs->consumedBits += bitCount;
+ bs->cache <<= bitCount;
+#else
+ if (bitCount < DRFLAC_CACHE_L1_SIZE_BITS(bs)) {
+ *pResultOut = (drflac_uint32)DRFLAC_CACHE_L1_SELECT_AND_SHIFT(bs, bitCount);
+ bs->consumedBits += bitCount;
+ bs->cache <<= bitCount;
+ } else {
+ /* Cannot shift by 32-bits, so need to do it differently. */
+ *pResultOut = (drflac_uint32)bs->cache;
+ bs->consumedBits = DRFLAC_CACHE_L1_SIZE_BITS(bs);
+ bs->cache = 0;
+ }
+#endif
+
+ return DRFLAC_TRUE;
+ } else {
+ /* It straddles the cached data. It will never cover more than the next chunk. We just read the number in two parts and combine them. */
+ drflac_uint32 bitCountHi = DRFLAC_CACHE_L1_BITS_REMAINING(bs);
+ drflac_uint32 bitCountLo = bitCount - bitCountHi;
+ drflac_uint32 resultHi;
+
+ DRFLAC_ASSERT(bitCountHi > 0);
+ DRFLAC_ASSERT(bitCountHi < 32);
+ resultHi = (drflac_uint32)DRFLAC_CACHE_L1_SELECT_AND_SHIFT(bs, bitCountHi);
+
+ if (!drflac__reload_cache(bs)) {
+ return DRFLAC_FALSE;
+ }
+ if (bitCountLo > DRFLAC_CACHE_L1_BITS_REMAINING(bs)) {
+ /* This happens when we get to end of stream */
+ return DRFLAC_FALSE;
+ }
+
+ *pResultOut = (resultHi << bitCountLo) | (drflac_uint32)DRFLAC_CACHE_L1_SELECT_AND_SHIFT(bs, bitCountLo);
+ bs->consumedBits += bitCountLo;
+ bs->cache <<= bitCountLo;
+ return DRFLAC_TRUE;
+ }
+}
+
+static drflac_bool32 drflac__read_int32(drflac_bs* bs, unsigned int bitCount, drflac_int32* pResult)
+{
+ drflac_uint32 result;
+
+ DRFLAC_ASSERT(bs != NULL);
+ DRFLAC_ASSERT(pResult != NULL);
+ DRFLAC_ASSERT(bitCount > 0);
+ DRFLAC_ASSERT(bitCount <= 32);
+
+ if (!drflac__read_uint32(bs, bitCount, &result)) {
+ return DRFLAC_FALSE;
+ }
+
+ /* Do not attempt to shift by 32 as it's undefined. */
+ if (bitCount < 32) {
+ drflac_uint32 signbit;
+ signbit = ((result >> (bitCount-1)) & 0x01);
+ result |= (~signbit + 1) << bitCount;
+ }
+
+ *pResult = (drflac_int32)result;
+ return DRFLAC_TRUE;
+}
+
+#ifdef DRFLAC_64BIT
+static drflac_bool32 drflac__read_uint64(drflac_bs* bs, unsigned int bitCount, drflac_uint64* pResultOut)
+{
+ drflac_uint32 resultHi;
+ drflac_uint32 resultLo;
+
+ DRFLAC_ASSERT(bitCount <= 64);
+ DRFLAC_ASSERT(bitCount > 32);
+
+ if (!drflac__read_uint32(bs, bitCount - 32, &resultHi)) {
+ return DRFLAC_FALSE;
+ }
+
+ if (!drflac__read_uint32(bs, 32, &resultLo)) {
+ return DRFLAC_FALSE;
+ }
+
+ *pResultOut = (((drflac_uint64)resultHi) << 32) | ((drflac_uint64)resultLo);
+ return DRFLAC_TRUE;
+}
+#endif
+
+/* Function below is unused, but leaving it here in case I need to quickly add it again. */
+#if 0
+static drflac_bool32 drflac__read_int64(drflac_bs* bs, unsigned int bitCount, drflac_int64* pResultOut)
+{
+ drflac_uint64 result;
+ drflac_uint64 signbit;
+
+ DRFLAC_ASSERT(bitCount <= 64);
+
+ if (!drflac__read_uint64(bs, bitCount, &result)) {
+ return DRFLAC_FALSE;
+ }
+
+ signbit = ((result >> (bitCount-1)) & 0x01);
+ result |= (~signbit + 1) << bitCount;
+
+ *pResultOut = (drflac_int64)result;
+ return DRFLAC_TRUE;
+}
+#endif
+
+static drflac_bool32 drflac__read_uint16(drflac_bs* bs, unsigned int bitCount, drflac_uint16* pResult)
+{
+ drflac_uint32 result;
+
+ DRFLAC_ASSERT(bs != NULL);
+ DRFLAC_ASSERT(pResult != NULL);
+ DRFLAC_ASSERT(bitCount > 0);
+ DRFLAC_ASSERT(bitCount <= 16);
+
+ if (!drflac__read_uint32(bs, bitCount, &result)) {
+ return DRFLAC_FALSE;
+ }
+
+ *pResult = (drflac_uint16)result;
+ return DRFLAC_TRUE;
+}
+
+#if 0
+static drflac_bool32 drflac__read_int16(drflac_bs* bs, unsigned int bitCount, drflac_int16* pResult)
+{
+ drflac_int32 result;
+
+ DRFLAC_ASSERT(bs != NULL);
+ DRFLAC_ASSERT(pResult != NULL);
+ DRFLAC_ASSERT(bitCount > 0);
+ DRFLAC_ASSERT(bitCount <= 16);
+
+ if (!drflac__read_int32(bs, bitCount, &result)) {
+ return DRFLAC_FALSE;
+ }
+
+ *pResult = (drflac_int16)result;
+ return DRFLAC_TRUE;
+}
+#endif
+
+static drflac_bool32 drflac__read_uint8(drflac_bs* bs, unsigned int bitCount, drflac_uint8* pResult)
+{
+ drflac_uint32 result;
+
+ DRFLAC_ASSERT(bs != NULL);
+ DRFLAC_ASSERT(pResult != NULL);
+ DRFLAC_ASSERT(bitCount > 0);
+ DRFLAC_ASSERT(bitCount <= 8);
+
+ if (!drflac__read_uint32(bs, bitCount, &result)) {
+ return DRFLAC_FALSE;
+ }
+
+ *pResult = (drflac_uint8)result;
+ return DRFLAC_TRUE;
+}
+
+static drflac_bool32 drflac__read_int8(drflac_bs* bs, unsigned int bitCount, drflac_int8* pResult)
+{
+ drflac_int32 result;
+
+ DRFLAC_ASSERT(bs != NULL);
+ DRFLAC_ASSERT(pResult != NULL);
+ DRFLAC_ASSERT(bitCount > 0);
+ DRFLAC_ASSERT(bitCount <= 8);
+
+ if (!drflac__read_int32(bs, bitCount, &result)) {
+ return DRFLAC_FALSE;
+ }
+
+ *pResult = (drflac_int8)result;
+ return DRFLAC_TRUE;
+}
+
+
+static drflac_bool32 drflac__seek_bits(drflac_bs* bs, size_t bitsToSeek)
+{
+ if (bitsToSeek <= DRFLAC_CACHE_L1_BITS_REMAINING(bs)) {
+ bs->consumedBits += (drflac_uint32)bitsToSeek;
+ bs->cache <<= bitsToSeek;
+ return DRFLAC_TRUE;
+ } else {
+ /* It straddles the cached data. This function isn't called too frequently so I'm favouring simplicity here. */
+ bitsToSeek -= DRFLAC_CACHE_L1_BITS_REMAINING(bs);
+ bs->consumedBits += DRFLAC_CACHE_L1_BITS_REMAINING(bs);
+ bs->cache = 0;
+
+ /* Simple case. Seek in groups of the same number as bits that fit within a cache line. */
+#ifdef DRFLAC_64BIT
+ while (bitsToSeek >= DRFLAC_CACHE_L1_SIZE_BITS(bs)) {
+ drflac_uint64 bin;
+ if (!drflac__read_uint64(bs, DRFLAC_CACHE_L1_SIZE_BITS(bs), &bin)) {
+ return DRFLAC_FALSE;
+ }
+ bitsToSeek -= DRFLAC_CACHE_L1_SIZE_BITS(bs);
+ }
+#else
+ while (bitsToSeek >= DRFLAC_CACHE_L1_SIZE_BITS(bs)) {
+ drflac_uint32 bin;
+ if (!drflac__read_uint32(bs, DRFLAC_CACHE_L1_SIZE_BITS(bs), &bin)) {
+ return DRFLAC_FALSE;
+ }
+ bitsToSeek -= DRFLAC_CACHE_L1_SIZE_BITS(bs);
+ }
+#endif
+
+ /* Whole leftover bytes. */
+ while (bitsToSeek >= 8) {
+ drflac_uint8 bin;
+ if (!drflac__read_uint8(bs, 8, &bin)) {
+ return DRFLAC_FALSE;
+ }
+ bitsToSeek -= 8;
+ }
+
+ /* Leftover bits. */
+ if (bitsToSeek > 0) {
+ drflac_uint8 bin;
+ if (!drflac__read_uint8(bs, (drflac_uint32)bitsToSeek, &bin)) {
+ return DRFLAC_FALSE;
+ }
+ bitsToSeek = 0; /* <-- Necessary for the assert below. */
+ }
+
+ DRFLAC_ASSERT(bitsToSeek == 0);
+ return DRFLAC_TRUE;
+ }
+}
+
+
+/* This function moves the bit streamer to the first bit after the sync code (bit 15 of the of the frame header). It will also update the CRC-16. */
+static drflac_bool32 drflac__find_and_seek_to_next_sync_code(drflac_bs* bs)
+{
+ DRFLAC_ASSERT(bs != NULL);
+
+ /*
+ The sync code is always aligned to 8 bits. This is convenient for us because it means we can do byte-aligned movements. The first
+ thing to do is align to the next byte.
+ */
+ if (!drflac__seek_bits(bs, DRFLAC_CACHE_L1_BITS_REMAINING(bs) & 7)) {
+ return DRFLAC_FALSE;
+ }
+
+ for (;;) {
+ drflac_uint8 hi;
+
+#ifndef DR_FLAC_NO_CRC
+ drflac__reset_crc16(bs);
+#endif
+
+ if (!drflac__read_uint8(bs, 8, &hi)) {
+ return DRFLAC_FALSE;
+ }
+
+ if (hi == 0xFF) {
+ drflac_uint8 lo;
+ if (!drflac__read_uint8(bs, 6, &lo)) {
+ return DRFLAC_FALSE;
+ }
+
+ if (lo == 0x3E) {
+ return DRFLAC_TRUE;
+ } else {
+ if (!drflac__seek_bits(bs, DRFLAC_CACHE_L1_BITS_REMAINING(bs) & 7)) {
+ return DRFLAC_FALSE;
+ }
+ }
+ }
+ }
+
+ /* Should never get here. */
+ /*return DRFLAC_FALSE;*/
+}
+
+
+#if defined(DRFLAC_HAS_LZCNT_INTRINSIC)
+#define DRFLAC_IMPLEMENT_CLZ_LZCNT
+#endif
+#if defined(_MSC_VER) && _MSC_VER >= 1400 && (defined(DRFLAC_X64) || defined(DRFLAC_X86)) && !defined(__clang__)
+#define DRFLAC_IMPLEMENT_CLZ_MSVC
+#endif
+#if defined(__WATCOMC__) && defined(__386__)
+#define DRFLAC_IMPLEMENT_CLZ_WATCOM
+#endif
+#ifdef __MRC__
+#include
+#define DRFLAC_IMPLEMENT_CLZ_MRC
+#endif
+
+static DRFLAC_INLINE drflac_uint32 drflac__clz_software(drflac_cache_t x)
+{
+ drflac_uint32 n;
+ static drflac_uint32 clz_table_4[] = {
+ 0,
+ 4,
+ 3, 3,
+ 2, 2, 2, 2,
+ 1, 1, 1, 1, 1, 1, 1, 1
+ };
+
+ if (x == 0) {
+ return sizeof(x)*8;
+ }
+
+ n = clz_table_4[x >> (sizeof(x)*8 - 4)];
+ if (n == 0) {
+#ifdef DRFLAC_64BIT
+ if ((x & ((drflac_uint64)0xFFFFFFFF << 32)) == 0) { n = 32; x <<= 32; }
+ if ((x & ((drflac_uint64)0xFFFF0000 << 32)) == 0) { n += 16; x <<= 16; }
+ if ((x & ((drflac_uint64)0xFF000000 << 32)) == 0) { n += 8; x <<= 8; }
+ if ((x & ((drflac_uint64)0xF0000000 << 32)) == 0) { n += 4; x <<= 4; }
+#else
+ if ((x & 0xFFFF0000) == 0) { n = 16; x <<= 16; }
+ if ((x & 0xFF000000) == 0) { n += 8; x <<= 8; }
+ if ((x & 0xF0000000) == 0) { n += 4; x <<= 4; }
+#endif
+ n += clz_table_4[x >> (sizeof(x)*8 - 4)];
+ }
+
+ return n - 1;
+}
+
+#ifdef DRFLAC_IMPLEMENT_CLZ_LZCNT
+static DRFLAC_INLINE drflac_bool32 drflac__is_lzcnt_supported(void)
+{
+ /* Fast compile time check for ARM. */
+#if defined(DRFLAC_HAS_LZCNT_INTRINSIC) && defined(DRFLAC_ARM) && (defined(__ARM_ARCH) && __ARM_ARCH >= 5)
+ return DRFLAC_TRUE;
+#elif defined(__MRC__)
+ return DRFLAC_TRUE;
+#else
+ /* If the compiler itself does not support the intrinsic then we'll need to return false. */
+ #ifdef DRFLAC_HAS_LZCNT_INTRINSIC
+ return drflac__gIsLZCNTSupported;
+ #else
+ return DRFLAC_FALSE;
+ #endif
+#endif
+}
+
+static DRFLAC_INLINE drflac_uint32 drflac__clz_lzcnt(drflac_cache_t x)
+{
+ /*
+ It's critical for competitive decoding performance that this function be highly optimal. With MSVC we can use the __lzcnt64() and __lzcnt() intrinsics
+ to achieve good performance, however on GCC and Clang it's a little bit more annoying. The __builtin_clzl() and __builtin_clzll() intrinsics leave
+ it undefined as to the return value when `x` is 0. We need this to be well defined as returning 32 or 64, depending on whether or not it's a 32- or
+ 64-bit build. To work around this we would need to add a conditional to check for the x = 0 case, but this creates unnecessary inefficiency. To work
+ around this problem I have written some inline assembly to emit the LZCNT (x86) or CLZ (ARM) instruction directly which removes the need to include
+ the conditional. This has worked well in the past, but for some reason Clang's MSVC compatible driver, clang-cl, does not seem to be handling this
+ in the same way as the normal Clang driver. It seems that `clang-cl` is just outputting the wrong results sometimes, maybe due to some register
+ getting clobbered?
+
+ I'm not sure if this is a bug with dr_flac's inlined assembly (most likely), a bug in `clang-cl` or just a misunderstanding on my part with inline
+ assembly rules for `clang-cl`. If somebody can identify an error in dr_flac's inlined assembly I'm happy to get that fixed.
+
+ Fortunately there is an easy workaround for this. Clang implements MSVC-specific intrinsics for compatibility. It also defines _MSC_VER for extra
+ compatibility. We can therefore just check for _MSC_VER and use the MSVC intrinsic which, fortunately for us, Clang supports. It would still be nice
+ to know how to fix the inlined assembly for correctness sake, however.
+ */
+
+#if defined(_MSC_VER) /*&& !defined(__clang__)*/ /* <-- Intentionally wanting Clang to use the MSVC __lzcnt64/__lzcnt intrinsics due to above ^. */
+ #ifdef DRFLAC_64BIT
+ return (drflac_uint32)__lzcnt64(x);
+ #else
+ return (drflac_uint32)__lzcnt(x);
+ #endif
+#else
+ #if defined(__GNUC__) || defined(__clang__)
+ #if defined(DRFLAC_X64)
+ {
+ drflac_uint64 r;
+ __asm__ __volatile__ (
+ "lzcnt{ %1, %0| %0, %1}" : "=r"(r) : "r"(x) : "cc"
+ );
+
+ return (drflac_uint32)r;
+ }
+ #elif defined(DRFLAC_X86)
+ {
+ drflac_uint32 r;
+ __asm__ __volatile__ (
+ "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. */
+ {
+ unsigned int r;
+ __asm__ __volatile__ (
+ #if defined(DRFLAC_64BIT)
+ "clz %w[out], %w[in]" : [out]"=r"(r) : [in]"r"(x) /* <-- This is untested. If someone in the community could test this, that would be appreciated! */
+ #else
+ "clz %[out], %[in]" : [out]"=r"(r) : [in]"r"(x)
+ #endif
+ );
+
+ return r;
+ }
+ #else
+ if (x == 0) {
+ return sizeof(x)*8;
+ }
+ #ifdef DRFLAC_64BIT
+ return (drflac_uint32)__builtin_clzll((drflac_uint64)x);
+ #else
+ return (drflac_uint32)__builtin_clzl((drflac_uint32)x);
+ #endif
+ #endif
+ #else
+ /* Unsupported compiler. */
+ #error "This compiler does not support the lzcnt intrinsic."
+ #endif
+#endif
+}
+#endif
+
+#ifdef DRFLAC_IMPLEMENT_CLZ_MSVC
+#include /* For BitScanReverse(). */
+
+static DRFLAC_INLINE drflac_uint32 drflac__clz_msvc(drflac_cache_t x)
+{
+ drflac_uint32 n;
+
+ if (x == 0) {
+ return sizeof(x)*8;
+ }
+
+#ifdef DRFLAC_64BIT
+ _BitScanReverse64((unsigned long*)&n, x);
+#else
+ _BitScanReverse((unsigned long*)&n, x);
+#endif
+ return sizeof(x)*8 - n - 1;
+}
+#endif
+
+#ifdef DRFLAC_IMPLEMENT_CLZ_WATCOM
+static __inline drflac_uint32 drflac__clz_watcom (drflac_uint32);
+#ifdef DRFLAC_IMPLEMENT_CLZ_WATCOM_LZCNT
+/* Use the LZCNT instruction (only available on some processors since the 2010s). */
+#pragma aux drflac__clz_watcom_lzcnt = \
+ "db 0F3h, 0Fh, 0BDh, 0C0h" /* lzcnt eax, eax */ \
+ parm [eax] \
+ value [eax] \
+ modify nomemory;
+#else
+/* Use the 386+-compatible implementation. */
+#pragma aux drflac__clz_watcom = \
+ "bsr eax, eax" \
+ "xor eax, 31" \
+ parm [eax] nomemory \
+ value [eax] \
+ modify exact [eax] nomemory;
+#endif
+#endif
+
+static DRFLAC_INLINE drflac_uint32 drflac__clz(drflac_cache_t x)
+{
+#ifdef DRFLAC_IMPLEMENT_CLZ_LZCNT
+ if (drflac__is_lzcnt_supported()) {
+ return drflac__clz_lzcnt(x);
+ } else
+#endif
+ {
+#ifdef DRFLAC_IMPLEMENT_CLZ_MSVC
+ return drflac__clz_msvc(x);
+#elif defined(DRFLAC_IMPLEMENT_CLZ_WATCOM_LZCNT)
+ return drflac__clz_watcom_lzcnt(x);
+#elif defined(DRFLAC_IMPLEMENT_CLZ_WATCOM)
+ return (x == 0) ? sizeof(x)*8 : drflac__clz_watcom(x);
+#elif defined(__MRC__)
+ return __cntlzw(x);
+#else
+ return drflac__clz_software(x);
+#endif
+ }
+}
+
+
+static DRFLAC_INLINE drflac_bool32 drflac__seek_past_next_set_bit(drflac_bs* bs, unsigned int* pOffsetOut)
+{
+ drflac_uint32 zeroCounter = 0;
+ drflac_uint32 setBitOffsetPlus1;
+
+ while (bs->cache == 0) {
+ zeroCounter += (drflac_uint32)DRFLAC_CACHE_L1_BITS_REMAINING(bs);
+ if (!drflac__reload_cache(bs)) {
+ return DRFLAC_FALSE;
+ }
+ }
+
+ if (bs->cache == 1) {
+ /* Not catching this would lead to undefined behaviour: a shift of a 32-bit number by 32 or more is undefined */
+ *pOffsetOut = zeroCounter + (drflac_uint32)DRFLAC_CACHE_L1_BITS_REMAINING(bs) - 1;
+ if (!drflac__reload_cache(bs)) {
+ return DRFLAC_FALSE;
+ }
+
+ return DRFLAC_TRUE;
+ }
+
+ setBitOffsetPlus1 = drflac__clz(bs->cache);
+ setBitOffsetPlus1 += 1;
+
+ if (setBitOffsetPlus1 > DRFLAC_CACHE_L1_BITS_REMAINING(bs)) {
+ /* This happens when we get to end of stream */
+ return DRFLAC_FALSE;
+ }
+
+ bs->consumedBits += setBitOffsetPlus1;
+ bs->cache <<= setBitOffsetPlus1;
+
+ *pOffsetOut = zeroCounter + setBitOffsetPlus1 - 1;
+ return DRFLAC_TRUE;
+}
+
+
+
+static drflac_bool32 drflac__seek_to_byte(drflac_bs* bs, drflac_uint64 offsetFromStart)
+{
+ DRFLAC_ASSERT(bs != NULL);
+ DRFLAC_ASSERT(offsetFromStart > 0);
+
+ /*
+ Seeking from the start is not quite as trivial as it sounds because the onSeek callback takes a signed 32-bit integer (which
+ is intentional because it simplifies the implementation of the onSeek callbacks), however offsetFromStart is unsigned 64-bit.
+ To resolve we just need to do an initial seek from the start, and then a series of offset seeks to make up the remainder.
+ */
+ if (offsetFromStart > 0x7FFFFFFF) {
+ drflac_uint64 bytesRemaining = offsetFromStart;
+ if (!bs->onSeek(bs->pUserData, 0x7FFFFFFF, drflac_seek_origin_start)) {
+ return DRFLAC_FALSE;
+ }
+ bytesRemaining -= 0x7FFFFFFF;
+
+ while (bytesRemaining > 0x7FFFFFFF) {
+ if (!bs->onSeek(bs->pUserData, 0x7FFFFFFF, drflac_seek_origin_current)) {
+ return DRFLAC_FALSE;
+ }
+ bytesRemaining -= 0x7FFFFFFF;
+ }
+
+ if (bytesRemaining > 0) {
+ if (!bs->onSeek(bs->pUserData, (int)bytesRemaining, drflac_seek_origin_current)) {
+ return DRFLAC_FALSE;
+ }
+ }
+ } else {
+ if (!bs->onSeek(bs->pUserData, (int)offsetFromStart, drflac_seek_origin_start)) {
+ return DRFLAC_FALSE;
+ }
+ }
+
+ /* The cache should be reset to force a reload of fresh data from the client. */
+ drflac__reset_cache(bs);
+ return DRFLAC_TRUE;
+}
+
+
+static drflac_result drflac__read_utf8_coded_number(drflac_bs* bs, drflac_uint64* pNumberOut, drflac_uint8* pCRCOut)
+{
+ drflac_uint8 crc;
+ drflac_uint64 result;
+ drflac_uint8 utf8[7] = {0};
+ int byteCount;
+ int i;
+
+ DRFLAC_ASSERT(bs != NULL);
+ DRFLAC_ASSERT(pNumberOut != NULL);
+ DRFLAC_ASSERT(pCRCOut != NULL);
+
+ crc = *pCRCOut;
+
+ if (!drflac__read_uint8(bs, 8, utf8)) {
+ *pNumberOut = 0;
+ return DRFLAC_AT_END;
+ }
+ crc = drflac_crc8(crc, utf8[0], 8);
+
+ if ((utf8[0] & 0x80) == 0) {
+ *pNumberOut = utf8[0];
+ *pCRCOut = crc;
+ return DRFLAC_SUCCESS;
+ }
+
+ /*byteCount = 1;*/
+ if ((utf8[0] & 0xE0) == 0xC0) {
+ byteCount = 2;
+ } else if ((utf8[0] & 0xF0) == 0xE0) {
+ byteCount = 3;
+ } else if ((utf8[0] & 0xF8) == 0xF0) {
+ byteCount = 4;
+ } else if ((utf8[0] & 0xFC) == 0xF8) {
+ byteCount = 5;
+ } else if ((utf8[0] & 0xFE) == 0xFC) {
+ byteCount = 6;
+ } else if ((utf8[0] & 0xFF) == 0xFE) {
+ byteCount = 7;
+ } else {
+ *pNumberOut = 0;
+ return DRFLAC_CRC_MISMATCH; /* Bad UTF-8 encoding. */
+ }
+
+ /* Read extra bytes. */
+ DRFLAC_ASSERT(byteCount > 1);
+
+ result = (drflac_uint64)(utf8[0] & (0xFF >> (byteCount + 1)));
+ for (i = 1; i < byteCount; ++i) {
+ if (!drflac__read_uint8(bs, 8, utf8 + i)) {
+ *pNumberOut = 0;
+ return DRFLAC_AT_END;
+ }
+ crc = drflac_crc8(crc, utf8[i], 8);
+
+ result = (result << 6) | (utf8[i] & 0x3F);
+ }
+
+ *pNumberOut = result;
+ *pCRCOut = crc;
+ return DRFLAC_SUCCESS;
+}
+
+
+static DRFLAC_INLINE drflac_uint32 drflac__ilog2_u32(drflac_uint32 x)
+{
+#if 1 /* Needs optimizing. */
+ drflac_uint32 result = 0;
+ while (x > 0) {
+ result += 1;
+ x >>= 1;
+ }
+
+ return result;
+#endif
+}
+
+static DRFLAC_INLINE drflac_bool32 drflac__use_64_bit_prediction(drflac_uint32 bitsPerSample, drflac_uint32 order, drflac_uint32 precision)
+{
+ /* https://web.archive.org/web/20220205005724/https://github.com/ietf-wg-cellar/flac-specification/blob/37a49aa48ba4ba12e8757badfc59c0df35435fec/rfc_backmatter.md */
+ return bitsPerSample + precision + drflac__ilog2_u32(order) > 32;
+}
+
+
+/*
+The next two functions are responsible for calculating the prediction.
+
+When the bits per sample is >16 we need to use 64-bit integer arithmetic because otherwise we'll run out of precision. It's
+safe to assume this will be slower on 32-bit platforms so we use a more optimal solution when the bits per sample is <=16.
+*/
+#if defined(__clang__)
+__attribute__((no_sanitize("signed-integer-overflow")))
+#endif
+static DRFLAC_INLINE drflac_int32 drflac__calculate_prediction_32(drflac_uint32 order, drflac_int32 shift, const drflac_int32* coefficients, drflac_int32* pDecodedSamples)
+{
+ drflac_int32 prediction = 0;
+
+ DRFLAC_ASSERT(order <= 32);
+
+ /* 32-bit version. */
+
+ /* VC++ optimizes this to a single jmp. I've not yet verified this for other compilers. */
+ switch (order)
+ {
+ case 32: prediction += coefficients[31] * pDecodedSamples[-32];
+ case 31: prediction += coefficients[30] * pDecodedSamples[-31];
+ case 30: prediction += coefficients[29] * pDecodedSamples[-30];
+ case 29: prediction += coefficients[28] * pDecodedSamples[-29];
+ case 28: prediction += coefficients[27] * pDecodedSamples[-28];
+ case 27: prediction += coefficients[26] * pDecodedSamples[-27];
+ case 26: prediction += coefficients[25] * pDecodedSamples[-26];
+ case 25: prediction += coefficients[24] * pDecodedSamples[-25];
+ case 24: prediction += coefficients[23] * pDecodedSamples[-24];
+ case 23: prediction += coefficients[22] * pDecodedSamples[-23];
+ case 22: prediction += coefficients[21] * pDecodedSamples[-22];
+ case 21: prediction += coefficients[20] * pDecodedSamples[-21];
+ case 20: prediction += coefficients[19] * pDecodedSamples[-20];
+ case 19: prediction += coefficients[18] * pDecodedSamples[-19];
+ case 18: prediction += coefficients[17] * pDecodedSamples[-18];
+ case 17: prediction += coefficients[16] * pDecodedSamples[-17];
+ case 16: prediction += coefficients[15] * pDecodedSamples[-16];
+ case 15: prediction += coefficients[14] * pDecodedSamples[-15];
+ case 14: prediction += coefficients[13] * pDecodedSamples[-14];
+ case 13: prediction += coefficients[12] * pDecodedSamples[-13];
+ case 12: prediction += coefficients[11] * pDecodedSamples[-12];
+ case 11: prediction += coefficients[10] * pDecodedSamples[-11];
+ case 10: prediction += coefficients[ 9] * pDecodedSamples[-10];
+ case 9: prediction += coefficients[ 8] * pDecodedSamples[- 9];
+ case 8: prediction += coefficients[ 7] * pDecodedSamples[- 8];
+ case 7: prediction += coefficients[ 6] * pDecodedSamples[- 7];
+ case 6: prediction += coefficients[ 5] * pDecodedSamples[- 6];
+ case 5: prediction += coefficients[ 4] * pDecodedSamples[- 5];
+ case 4: prediction += coefficients[ 3] * pDecodedSamples[- 4];
+ case 3: prediction += coefficients[ 2] * pDecodedSamples[- 3];
+ case 2: prediction += coefficients[ 1] * pDecodedSamples[- 2];
+ case 1: prediction += coefficients[ 0] * pDecodedSamples[- 1];
+ }
+
+ return (drflac_int32)(prediction >> shift);
+}
+
+static DRFLAC_INLINE drflac_int32 drflac__calculate_prediction_64(drflac_uint32 order, drflac_int32 shift, const drflac_int32* coefficients, drflac_int32* pDecodedSamples)
+{
+ drflac_int64 prediction;
+
+ DRFLAC_ASSERT(order <= 32);
+
+ /* 64-bit version. */
+
+ /* This method is faster on the 32-bit build when compiling with VC++. See note below. */
+#ifndef DRFLAC_64BIT
+ if (order == 8)
+ {
+ prediction = coefficients[0] * (drflac_int64)pDecodedSamples[-1];
+ prediction += coefficients[1] * (drflac_int64)pDecodedSamples[-2];
+ prediction += coefficients[2] * (drflac_int64)pDecodedSamples[-3];
+ prediction += coefficients[3] * (drflac_int64)pDecodedSamples[-4];
+ prediction += coefficients[4] * (drflac_int64)pDecodedSamples[-5];
+ prediction += coefficients[5] * (drflac_int64)pDecodedSamples[-6];
+ prediction += coefficients[6] * (drflac_int64)pDecodedSamples[-7];
+ prediction += coefficients[7] * (drflac_int64)pDecodedSamples[-8];
+ }
+ else if (order == 7)
+ {
+ prediction = coefficients[0] * (drflac_int64)pDecodedSamples[-1];
+ prediction += coefficients[1] * (drflac_int64)pDecodedSamples[-2];
+ prediction += coefficients[2] * (drflac_int64)pDecodedSamples[-3];
+ prediction += coefficients[3] * (drflac_int64)pDecodedSamples[-4];
+ prediction += coefficients[4] * (drflac_int64)pDecodedSamples[-5];
+ prediction += coefficients[5] * (drflac_int64)pDecodedSamples[-6];
+ prediction += coefficients[6] * (drflac_int64)pDecodedSamples[-7];
+ }
+ else if (order == 3)
+ {
+ prediction = coefficients[0] * (drflac_int64)pDecodedSamples[-1];
+ prediction += coefficients[1] * (drflac_int64)pDecodedSamples[-2];
+ prediction += coefficients[2] * (drflac_int64)pDecodedSamples[-3];
+ }
+ else if (order == 6)
+ {
+ prediction = coefficients[0] * (drflac_int64)pDecodedSamples[-1];
+ prediction += coefficients[1] * (drflac_int64)pDecodedSamples[-2];
+ prediction += coefficients[2] * (drflac_int64)pDecodedSamples[-3];
+ prediction += coefficients[3] * (drflac_int64)pDecodedSamples[-4];
+ prediction += coefficients[4] * (drflac_int64)pDecodedSamples[-5];
+ prediction += coefficients[5] * (drflac_int64)pDecodedSamples[-6];
+ }
+ else if (order == 5)
+ {
+ prediction = coefficients[0] * (drflac_int64)pDecodedSamples[-1];
+ prediction += coefficients[1] * (drflac_int64)pDecodedSamples[-2];
+ prediction += coefficients[2] * (drflac_int64)pDecodedSamples[-3];
+ prediction += coefficients[3] * (drflac_int64)pDecodedSamples[-4];
+ prediction += coefficients[4] * (drflac_int64)pDecodedSamples[-5];
+ }
+ else if (order == 4)
+ {
+ prediction = coefficients[0] * (drflac_int64)pDecodedSamples[-1];
+ prediction += coefficients[1] * (drflac_int64)pDecodedSamples[-2];
+ prediction += coefficients[2] * (drflac_int64)pDecodedSamples[-3];
+ prediction += coefficients[3] * (drflac_int64)pDecodedSamples[-4];
+ }
+ else if (order == 12)
+ {
+ prediction = coefficients[0] * (drflac_int64)pDecodedSamples[-1];
+ prediction += coefficients[1] * (drflac_int64)pDecodedSamples[-2];
+ prediction += coefficients[2] * (drflac_int64)pDecodedSamples[-3];
+ prediction += coefficients[3] * (drflac_int64)pDecodedSamples[-4];
+ prediction += coefficients[4] * (drflac_int64)pDecodedSamples[-5];
+ prediction += coefficients[5] * (drflac_int64)pDecodedSamples[-6];
+ prediction += coefficients[6] * (drflac_int64)pDecodedSamples[-7];
+ prediction += coefficients[7] * (drflac_int64)pDecodedSamples[-8];
+ prediction += coefficients[8] * (drflac_int64)pDecodedSamples[-9];
+ prediction += coefficients[9] * (drflac_int64)pDecodedSamples[-10];
+ prediction += coefficients[10] * (drflac_int64)pDecodedSamples[-11];
+ prediction += coefficients[11] * (drflac_int64)pDecodedSamples[-12];
+ }
+ else if (order == 2)
+ {
+ prediction = coefficients[0] * (drflac_int64)pDecodedSamples[-1];
+ prediction += coefficients[1] * (drflac_int64)pDecodedSamples[-2];
+ }
+ else if (order == 1)
+ {
+ prediction = coefficients[0] * (drflac_int64)pDecodedSamples[-1];
+ }
+ else if (order == 10)
+ {
+ prediction = coefficients[0] * (drflac_int64)pDecodedSamples[-1];
+ prediction += coefficients[1] * (drflac_int64)pDecodedSamples[-2];
+ prediction += coefficients[2] * (drflac_int64)pDecodedSamples[-3];
+ prediction += coefficients[3] * (drflac_int64)pDecodedSamples[-4];
+ prediction += coefficients[4] * (drflac_int64)pDecodedSamples[-5];
+ prediction += coefficients[5] * (drflac_int64)pDecodedSamples[-6];
+ prediction += coefficients[6] * (drflac_int64)pDecodedSamples[-7];
+ prediction += coefficients[7] * (drflac_int64)pDecodedSamples[-8];
+ prediction += coefficients[8] * (drflac_int64)pDecodedSamples[-9];
+ prediction += coefficients[9] * (drflac_int64)pDecodedSamples[-10];
+ }
+ else if (order == 9)
+ {
+ prediction = coefficients[0] * (drflac_int64)pDecodedSamples[-1];
+ prediction += coefficients[1] * (drflac_int64)pDecodedSamples[-2];
+ prediction += coefficients[2] * (drflac_int64)pDecodedSamples[-3];
+ prediction += coefficients[3] * (drflac_int64)pDecodedSamples[-4];
+ prediction += coefficients[4] * (drflac_int64)pDecodedSamples[-5];
+ prediction += coefficients[5] * (drflac_int64)pDecodedSamples[-6];
+ prediction += coefficients[6] * (drflac_int64)pDecodedSamples[-7];
+ prediction += coefficients[7] * (drflac_int64)pDecodedSamples[-8];
+ prediction += coefficients[8] * (drflac_int64)pDecodedSamples[-9];
+ }
+ else if (order == 11)
+ {
+ prediction = coefficients[0] * (drflac_int64)pDecodedSamples[-1];
+ prediction += coefficients[1] * (drflac_int64)pDecodedSamples[-2];
+ prediction += coefficients[2] * (drflac_int64)pDecodedSamples[-3];
+ prediction += coefficients[3] * (drflac_int64)pDecodedSamples[-4];
+ prediction += coefficients[4] * (drflac_int64)pDecodedSamples[-5];
+ prediction += coefficients[5] * (drflac_int64)pDecodedSamples[-6];
+ prediction += coefficients[6] * (drflac_int64)pDecodedSamples[-7];
+ prediction += coefficients[7] * (drflac_int64)pDecodedSamples[-8];
+ prediction += coefficients[8] * (drflac_int64)pDecodedSamples[-9];
+ prediction += coefficients[9] * (drflac_int64)pDecodedSamples[-10];
+ prediction += coefficients[10] * (drflac_int64)pDecodedSamples[-11];
+ }
+ else
+ {
+ int j;
+
+ prediction = 0;
+ for (j = 0; j < (int)order; ++j) {
+ prediction += coefficients[j] * (drflac_int64)pDecodedSamples[-j-1];
+ }
+ }
+#endif
+
+ /*
+ VC++ optimizes this to a single jmp instruction, but only the 64-bit build. The 32-bit build generates less efficient code for some
+ reason. The ugly version above is faster so we'll just switch between the two depending on the target platform.
+ */
+#ifdef DRFLAC_64BIT
+ prediction = 0;
+ switch (order)
+ {
+ case 32: prediction += coefficients[31] * (drflac_int64)pDecodedSamples[-32];
+ case 31: prediction += coefficients[30] * (drflac_int64)pDecodedSamples[-31];
+ case 30: prediction += coefficients[29] * (drflac_int64)pDecodedSamples[-30];
+ case 29: prediction += coefficients[28] * (drflac_int64)pDecodedSamples[-29];
+ case 28: prediction += coefficients[27] * (drflac_int64)pDecodedSamples[-28];
+ case 27: prediction += coefficients[26] * (drflac_int64)pDecodedSamples[-27];
+ case 26: prediction += coefficients[25] * (drflac_int64)pDecodedSamples[-26];
+ case 25: prediction += coefficients[24] * (drflac_int64)pDecodedSamples[-25];
+ case 24: prediction += coefficients[23] * (drflac_int64)pDecodedSamples[-24];
+ case 23: prediction += coefficients[22] * (drflac_int64)pDecodedSamples[-23];
+ case 22: prediction += coefficients[21] * (drflac_int64)pDecodedSamples[-22];
+ case 21: prediction += coefficients[20] * (drflac_int64)pDecodedSamples[-21];
+ case 20: prediction += coefficients[19] * (drflac_int64)pDecodedSamples[-20];
+ case 19: prediction += coefficients[18] * (drflac_int64)pDecodedSamples[-19];
+ case 18: prediction += coefficients[17] * (drflac_int64)pDecodedSamples[-18];
+ case 17: prediction += coefficients[16] * (drflac_int64)pDecodedSamples[-17];
+ case 16: prediction += coefficients[15] * (drflac_int64)pDecodedSamples[-16];
+ case 15: prediction += coefficients[14] * (drflac_int64)pDecodedSamples[-15];
+ case 14: prediction += coefficients[13] * (drflac_int64)pDecodedSamples[-14];
+ case 13: prediction += coefficients[12] * (drflac_int64)pDecodedSamples[-13];
+ case 12: prediction += coefficients[11] * (drflac_int64)pDecodedSamples[-12];
+ case 11: prediction += coefficients[10] * (drflac_int64)pDecodedSamples[-11];
+ case 10: prediction += coefficients[ 9] * (drflac_int64)pDecodedSamples[-10];
+ case 9: prediction += coefficients[ 8] * (drflac_int64)pDecodedSamples[- 9];
+ case 8: prediction += coefficients[ 7] * (drflac_int64)pDecodedSamples[- 8];
+ case 7: prediction += coefficients[ 6] * (drflac_int64)pDecodedSamples[- 7];
+ case 6: prediction += coefficients[ 5] * (drflac_int64)pDecodedSamples[- 6];
+ case 5: prediction += coefficients[ 4] * (drflac_int64)pDecodedSamples[- 5];
+ case 4: prediction += coefficients[ 3] * (drflac_int64)pDecodedSamples[- 4];
+ case 3: prediction += coefficients[ 2] * (drflac_int64)pDecodedSamples[- 3];
+ case 2: prediction += coefficients[ 1] * (drflac_int64)pDecodedSamples[- 2];
+ case 1: prediction += coefficients[ 0] * (drflac_int64)pDecodedSamples[- 1];
+ }
+#endif
+
+ return (drflac_int32)(prediction >> shift);
+}
+
+
+#if 0
+/*
+Reference implementation for reading and decoding samples with residual. This is intentionally left unoptimized for the
+sake of readability and should only be used as a reference.
+*/
+static drflac_bool32 drflac__decode_samples_with_residual__rice__reference(drflac_bs* bs, drflac_uint32 bitsPerSample, drflac_uint32 count, drflac_uint8 riceParam, drflac_uint32 lpcOrder, drflac_int32 lpcShift, drflac_uint32 lpcPrecision, const drflac_int32* coefficients, drflac_int32* pSamplesOut)
+{
+ drflac_uint32 i;
+
+ DRFLAC_ASSERT(bs != NULL);
+ DRFLAC_ASSERT(pSamplesOut != NULL);
+
+ for (i = 0; i < count; ++i) {
+ drflac_uint32 zeroCounter = 0;
+ for (;;) {
+ drflac_uint8 bit;
+ if (!drflac__read_uint8(bs, 1, &bit)) {
+ return DRFLAC_FALSE;
+ }
+
+ if (bit == 0) {
+ zeroCounter += 1;
+ } else {
+ break;
+ }
+ }
+
+ drflac_uint32 decodedRice;
+ if (riceParam > 0) {
+ if (!drflac__read_uint32(bs, riceParam, &decodedRice)) {
+ return DRFLAC_FALSE;
+ }
+ } else {
+ decodedRice = 0;
+ }
+
+ decodedRice |= (zeroCounter << riceParam);
+ if ((decodedRice & 0x01)) {
+ decodedRice = ~(decodedRice >> 1);
+ } else {
+ decodedRice = (decodedRice >> 1);
+ }
+
+
+ if (drflac__use_64_bit_prediction(bitsPerSample, lpcOrder, lpcPrecision)) {
+ pSamplesOut[i] = decodedRice + drflac__calculate_prediction_64(lpcOrder, lpcShift, coefficients, pSamplesOut + i);
+ } else {
+ pSamplesOut[i] = decodedRice + drflac__calculate_prediction_32(lpcOrder, lpcShift, coefficients, pSamplesOut + i);
+ }
+ }
+
+ return DRFLAC_TRUE;
+}
+#endif
+
+#if 0
+static drflac_bool32 drflac__read_rice_parts__reference(drflac_bs* bs, drflac_uint8 riceParam, drflac_uint32* pZeroCounterOut, drflac_uint32* pRiceParamPartOut)
+{
+ drflac_uint32 zeroCounter = 0;
+ drflac_uint32 decodedRice;
+
+ for (;;) {
+ drflac_uint8 bit;
+ if (!drflac__read_uint8(bs, 1, &bit)) {
+ return DRFLAC_FALSE;
+ }
+
+ if (bit == 0) {
+ zeroCounter += 1;
+ } else {
+ break;
+ }
+ }
+
+ if (riceParam > 0) {
+ if (!drflac__read_uint32(bs, riceParam, &decodedRice)) {
+ return DRFLAC_FALSE;
+ }
+ } else {
+ decodedRice = 0;
+ }
+
+ *pZeroCounterOut = zeroCounter;
+ *pRiceParamPartOut = decodedRice;
+ return DRFLAC_TRUE;
+}
+#endif
+
+#if 0
+static DRFLAC_INLINE drflac_bool32 drflac__read_rice_parts(drflac_bs* bs, drflac_uint8 riceParam, drflac_uint32* pZeroCounterOut, drflac_uint32* pRiceParamPartOut)
+{
+ drflac_cache_t riceParamMask;
+ drflac_uint32 zeroCounter;
+ drflac_uint32 setBitOffsetPlus1;
+ drflac_uint32 riceParamPart;
+ drflac_uint32 riceLength;
+
+ DRFLAC_ASSERT(riceParam > 0); /* <-- riceParam should never be 0. drflac__read_rice_parts__param_equals_zero() should be used instead for this case. */
+
+ riceParamMask = DRFLAC_CACHE_L1_SELECTION_MASK(riceParam);
+
+ zeroCounter = 0;
+ while (bs->cache == 0) {
+ zeroCounter += (drflac_uint32)DRFLAC_CACHE_L1_BITS_REMAINING(bs);
+ if (!drflac__reload_cache(bs)) {
+ return DRFLAC_FALSE;
+ }
+ }
+
+ setBitOffsetPlus1 = drflac__clz(bs->cache);
+ zeroCounter += setBitOffsetPlus1;
+ setBitOffsetPlus1 += 1;
+
+ riceLength = setBitOffsetPlus1 + riceParam;
+ if (riceLength < DRFLAC_CACHE_L1_BITS_REMAINING(bs)) {
+ riceParamPart = (drflac_uint32)((bs->cache & (riceParamMask >> setBitOffsetPlus1)) >> DRFLAC_CACHE_L1_SELECTION_SHIFT(bs, riceLength));
+
+ bs->consumedBits += riceLength;
+ bs->cache <<= riceLength;
+ } else {
+ drflac_uint32 bitCountLo;
+ drflac_cache_t resultHi;
+
+ bs->consumedBits += riceLength;
+ bs->cache <<= setBitOffsetPlus1 & (DRFLAC_CACHE_L1_SIZE_BITS(bs)-1); /* <-- Equivalent to "if (setBitOffsetPlus1 < DRFLAC_CACHE_L1_SIZE_BITS(bs)) { bs->cache <<= setBitOffsetPlus1; }" */
+
+ /* It straddles the cached data. It will never cover more than the next chunk. We just read the number in two parts and combine them. */
+ bitCountLo = bs->consumedBits - DRFLAC_CACHE_L1_SIZE_BITS(bs);
+ resultHi = DRFLAC_CACHE_L1_SELECT_AND_SHIFT(bs, riceParam); /* <-- Use DRFLAC_CACHE_L1_SELECT_AND_SHIFT_SAFE() if ever this function allows riceParam=0. */
+
+ if (bs->nextL2Line < DRFLAC_CACHE_L2_LINE_COUNT(bs)) {
+#ifndef DR_FLAC_NO_CRC
+ drflac__update_crc16(bs);
+#endif
+ bs->cache = drflac__be2host__cache_line(bs->cacheL2[bs->nextL2Line++]);
+ bs->consumedBits = 0;
+#ifndef DR_FLAC_NO_CRC
+ bs->crc16Cache = bs->cache;
+#endif
+ } else {
+ /* Slow path. We need to fetch more data from the client. */
+ if (!drflac__reload_cache(bs)) {
+ return DRFLAC_FALSE;
+ }
+ if (bitCountLo > DRFLAC_CACHE_L1_BITS_REMAINING(bs)) {
+ /* This happens when we get to end of stream */
+ return DRFLAC_FALSE;
+ }
+ }
+
+ riceParamPart = (drflac_uint32)(resultHi | DRFLAC_CACHE_L1_SELECT_AND_SHIFT_SAFE(bs, bitCountLo));
+
+ bs->consumedBits += bitCountLo;
+ bs->cache <<= bitCountLo;
+ }
+
+ pZeroCounterOut[0] = zeroCounter;
+ pRiceParamPartOut[0] = riceParamPart;
+
+ return DRFLAC_TRUE;
+}
+#endif
+
+static DRFLAC_INLINE drflac_bool32 drflac__read_rice_parts_x1(drflac_bs* bs, drflac_uint8 riceParam, drflac_uint32* pZeroCounterOut, drflac_uint32* pRiceParamPartOut)
+{
+ drflac_uint32 riceParamPlus1 = riceParam + 1;
+ /*drflac_cache_t riceParamPlus1Mask = DRFLAC_CACHE_L1_SELECTION_MASK(riceParamPlus1);*/
+ drflac_uint32 riceParamPlus1Shift = DRFLAC_CACHE_L1_SELECTION_SHIFT(bs, riceParamPlus1);
+ drflac_uint32 riceParamPlus1MaxConsumedBits = DRFLAC_CACHE_L1_SIZE_BITS(bs) - riceParamPlus1;
+
+ /*
+ The idea here is to use local variables for the cache in an attempt to encourage the compiler to store them in registers. I have
+ no idea how this will work in practice...
+ */
+ drflac_cache_t bs_cache = bs->cache;
+ drflac_uint32 bs_consumedBits = bs->consumedBits;
+
+ /* The first thing to do is find the first unset bit. Most likely a bit will be set in the current cache line. */
+ drflac_uint32 lzcount = drflac__clz(bs_cache);
+ if (lzcount < sizeof(bs_cache)*8) {
+ pZeroCounterOut[0] = lzcount;
+
+ /*
+ It is most likely that the riceParam part (which comes after the zero counter) is also on this cache line. When extracting
+ this, we include the set bit from the unary coded part because it simplifies cache management. This bit will be handled
+ outside of this function at a higher level.
+ */
+ extract_rice_param_part:
+ bs_cache <<= lzcount;
+ bs_consumedBits += lzcount;
+
+ if (bs_consumedBits <= riceParamPlus1MaxConsumedBits) {
+ /* Getting here means the rice parameter part is wholly contained within the current cache line. */
+ pRiceParamPartOut[0] = (drflac_uint32)(bs_cache >> riceParamPlus1Shift);
+ bs_cache <<= riceParamPlus1;
+ bs_consumedBits += riceParamPlus1;
+ } else {
+ drflac_uint32 riceParamPartHi;
+ drflac_uint32 riceParamPartLo;
+ drflac_uint32 riceParamPartLoBitCount;
+
+ /*
+ Getting here means the rice parameter part straddles the cache line. We need to read from the tail of the current cache
+ line, reload the cache, and then combine it with the head of the next cache line.
+ */
+
+ /* Grab the high part of the rice parameter part. */
+ riceParamPartHi = (drflac_uint32)(bs_cache >> riceParamPlus1Shift);
+
+ /* Before reloading the cache we need to grab the size in bits of the low part. */
+ riceParamPartLoBitCount = bs_consumedBits - riceParamPlus1MaxConsumedBits;
+ DRFLAC_ASSERT(riceParamPartLoBitCount > 0 && riceParamPartLoBitCount < 32);
+
+ /* Now reload the cache. */
+ if (bs->nextL2Line < DRFLAC_CACHE_L2_LINE_COUNT(bs)) {
+ #ifndef DR_FLAC_NO_CRC
+ drflac__update_crc16(bs);
+ #endif
+ bs_cache = drflac__be2host__cache_line(bs->cacheL2[bs->nextL2Line++]);
+ bs_consumedBits = riceParamPartLoBitCount;
+ #ifndef DR_FLAC_NO_CRC
+ bs->crc16Cache = bs_cache;
+ #endif
+ } else {
+ /* Slow path. We need to fetch more data from the client. */
+ if (!drflac__reload_cache(bs)) {
+ return DRFLAC_FALSE;
+ }
+ if (riceParamPartLoBitCount > DRFLAC_CACHE_L1_BITS_REMAINING(bs)) {
+ /* This happens when we get to end of stream */
+ return DRFLAC_FALSE;
+ }
+
+ bs_cache = bs->cache;
+ bs_consumedBits = bs->consumedBits + riceParamPartLoBitCount;
+ }
+
+ /* We should now have enough information to construct the rice parameter part. */
+ riceParamPartLo = (drflac_uint32)(bs_cache >> (DRFLAC_CACHE_L1_SELECTION_SHIFT(bs, riceParamPartLoBitCount)));
+ pRiceParamPartOut[0] = riceParamPartHi | riceParamPartLo;
+
+ bs_cache <<= riceParamPartLoBitCount;
+ }
+ } else {
+ /*
+ Getting here means there are no bits set on the cache line. This is a less optimal case because we just wasted a call
+ to drflac__clz() and we need to reload the cache.
+ */
+ drflac_uint32 zeroCounter = (drflac_uint32)(DRFLAC_CACHE_L1_SIZE_BITS(bs) - bs_consumedBits);
+ for (;;) {
+ if (bs->nextL2Line < DRFLAC_CACHE_L2_LINE_COUNT(bs)) {
+ #ifndef DR_FLAC_NO_CRC
+ drflac__update_crc16(bs);
+ #endif
+ bs_cache = drflac__be2host__cache_line(bs->cacheL2[bs->nextL2Line++]);
+ bs_consumedBits = 0;
+ #ifndef DR_FLAC_NO_CRC
+ bs->crc16Cache = bs_cache;
+ #endif
+ } else {
+ /* Slow path. We need to fetch more data from the client. */
+ if (!drflac__reload_cache(bs)) {
+ return DRFLAC_FALSE;
+ }
+
+ bs_cache = bs->cache;
+ bs_consumedBits = bs->consumedBits;
+ }
+
+ lzcount = drflac__clz(bs_cache);
+ zeroCounter += lzcount;
+
+ if (lzcount < sizeof(bs_cache)*8) {
+ break;
+ }
+ }
+
+ pZeroCounterOut[0] = zeroCounter;
+ goto extract_rice_param_part;
+ }
+
+ /* Make sure the cache is restored at the end of it all. */
+ bs->cache = bs_cache;
+ bs->consumedBits = bs_consumedBits;
+
+ return DRFLAC_TRUE;
+}
+
+static DRFLAC_INLINE drflac_bool32 drflac__seek_rice_parts(drflac_bs* bs, drflac_uint8 riceParam)
+{
+ drflac_uint32 riceParamPlus1 = riceParam + 1;
+ drflac_uint32 riceParamPlus1MaxConsumedBits = DRFLAC_CACHE_L1_SIZE_BITS(bs) - riceParamPlus1;
+
+ /*
+ The idea here is to use local variables for the cache in an attempt to encourage the compiler to store them in registers. I have
+ no idea how this will work in practice...
+ */
+ drflac_cache_t bs_cache = bs->cache;
+ drflac_uint32 bs_consumedBits = bs->consumedBits;
+
+ /* The first thing to do is find the first unset bit. Most likely a bit will be set in the current cache line. */
+ drflac_uint32 lzcount = drflac__clz(bs_cache);
+ if (lzcount < sizeof(bs_cache)*8) {
+ /*
+ It is most likely that the riceParam part (which comes after the zero counter) is also on this cache line. When extracting
+ this, we include the set bit from the unary coded part because it simplifies cache management. This bit will be handled
+ outside of this function at a higher level.
+ */
+ extract_rice_param_part:
+ bs_cache <<= lzcount;
+ bs_consumedBits += lzcount;
+
+ if (bs_consumedBits <= riceParamPlus1MaxConsumedBits) {
+ /* Getting here means the rice parameter part is wholly contained within the current cache line. */
+ bs_cache <<= riceParamPlus1;
+ bs_consumedBits += riceParamPlus1;
+ } else {
+ /*
+ Getting here means the rice parameter part straddles the cache line. We need to read from the tail of the current cache
+ line, reload the cache, and then combine it with the head of the next cache line.
+ */
+
+ /* Before reloading the cache we need to grab the size in bits of the low part. */
+ drflac_uint32 riceParamPartLoBitCount = bs_consumedBits - riceParamPlus1MaxConsumedBits;
+ DRFLAC_ASSERT(riceParamPartLoBitCount > 0 && riceParamPartLoBitCount < 32);
+
+ /* Now reload the cache. */
+ if (bs->nextL2Line < DRFLAC_CACHE_L2_LINE_COUNT(bs)) {
+ #ifndef DR_FLAC_NO_CRC
+ drflac__update_crc16(bs);
+ #endif
+ bs_cache = drflac__be2host__cache_line(bs->cacheL2[bs->nextL2Line++]);
+ bs_consumedBits = riceParamPartLoBitCount;
+ #ifndef DR_FLAC_NO_CRC
+ bs->crc16Cache = bs_cache;
+ #endif
+ } else {
+ /* Slow path. We need to fetch more data from the client. */
+ if (!drflac__reload_cache(bs)) {
+ return DRFLAC_FALSE;
+ }
+
+ if (riceParamPartLoBitCount > DRFLAC_CACHE_L1_BITS_REMAINING(bs)) {
+ /* This happens when we get to end of stream */
+ return DRFLAC_FALSE;
+ }
+
+ bs_cache = bs->cache;
+ bs_consumedBits = bs->consumedBits + riceParamPartLoBitCount;
+ }
+
+ bs_cache <<= riceParamPartLoBitCount;
+ }
+ } else {
+ /*
+ Getting here means there are no bits set on the cache line. This is a less optimal case because we just wasted a call
+ to drflac__clz() and we need to reload the cache.
+ */
+ for (;;) {
+ if (bs->nextL2Line < DRFLAC_CACHE_L2_LINE_COUNT(bs)) {
+ #ifndef DR_FLAC_NO_CRC
+ drflac__update_crc16(bs);
+ #endif
+ bs_cache = drflac__be2host__cache_line(bs->cacheL2[bs->nextL2Line++]);
+ bs_consumedBits = 0;
+ #ifndef DR_FLAC_NO_CRC
+ bs->crc16Cache = bs_cache;
+ #endif
+ } else {
+ /* Slow path. We need to fetch more data from the client. */
+ if (!drflac__reload_cache(bs)) {
+ return DRFLAC_FALSE;
+ }
+
+ bs_cache = bs->cache;
+ bs_consumedBits = bs->consumedBits;
+ }
+
+ lzcount = drflac__clz(bs_cache);
+ if (lzcount < sizeof(bs_cache)*8) {
+ break;
+ }
+ }
+
+ goto extract_rice_param_part;
+ }
+
+ /* Make sure the cache is restored at the end of it all. */
+ bs->cache = bs_cache;
+ bs->consumedBits = bs_consumedBits;
+
+ return DRFLAC_TRUE;
+}
+
+
+static drflac_bool32 drflac__decode_samples_with_residual__rice__scalar_zeroorder(drflac_bs* bs, drflac_uint32 bitsPerSample, drflac_uint32 count, drflac_uint8 riceParam, drflac_uint32 order, drflac_int32 shift, const drflac_int32* coefficients, drflac_int32* pSamplesOut)
+{
+ drflac_uint32 t[2] = {0x00000000, 0xFFFFFFFF};
+ drflac_uint32 zeroCountPart0;
+ drflac_uint32 riceParamPart0;
+ drflac_uint32 riceParamMask;
+ drflac_uint32 i;
+
+ DRFLAC_ASSERT(bs != NULL);
+ DRFLAC_ASSERT(pSamplesOut != NULL);
+
+ (void)bitsPerSample;
+ (void)order;
+ (void)shift;
+ (void)coefficients;
+
+ riceParamMask = (drflac_uint32)~((~0UL) << riceParam);
+
+ i = 0;
+ while (i < count) {
+ /* Rice extraction. */
+ if (!drflac__read_rice_parts_x1(bs, riceParam, &zeroCountPart0, &riceParamPart0)) {
+ return DRFLAC_FALSE;
+ }
+
+ /* Rice reconstruction. */
+ riceParamPart0 &= riceParamMask;
+ riceParamPart0 |= (zeroCountPart0 << riceParam);
+ riceParamPart0 = (riceParamPart0 >> 1) ^ t[riceParamPart0 & 0x01];
+
+ pSamplesOut[i] = riceParamPart0;
+
+ i += 1;
+ }
+
+ return DRFLAC_TRUE;
+}
+
+static drflac_bool32 drflac__decode_samples_with_residual__rice__scalar(drflac_bs* bs, drflac_uint32 bitsPerSample, drflac_uint32 count, drflac_uint8 riceParam, drflac_uint32 lpcOrder, drflac_int32 lpcShift, drflac_uint32 lpcPrecision, const drflac_int32* coefficients, drflac_int32* pSamplesOut)
+{
+ drflac_uint32 t[2] = {0x00000000, 0xFFFFFFFF};
+ drflac_uint32 zeroCountPart0 = 0;
+ drflac_uint32 zeroCountPart1 = 0;
+ drflac_uint32 zeroCountPart2 = 0;
+ drflac_uint32 zeroCountPart3 = 0;
+ drflac_uint32 riceParamPart0 = 0;
+ drflac_uint32 riceParamPart1 = 0;
+ drflac_uint32 riceParamPart2 = 0;
+ drflac_uint32 riceParamPart3 = 0;
+ drflac_uint32 riceParamMask;
+ const drflac_int32* pSamplesOutEnd;
+ drflac_uint32 i;
+
+ DRFLAC_ASSERT(bs != NULL);
+ DRFLAC_ASSERT(pSamplesOut != NULL);
+
+ if (lpcOrder == 0) {
+ return drflac__decode_samples_with_residual__rice__scalar_zeroorder(bs, bitsPerSample, count, riceParam, lpcOrder, lpcShift, coefficients, pSamplesOut);
+ }
+
+ riceParamMask = (drflac_uint32)~((~0UL) << riceParam);
+ pSamplesOutEnd = pSamplesOut + (count & ~3);
+
+ if (drflac__use_64_bit_prediction(bitsPerSample, lpcOrder, lpcPrecision)) {
+ while (pSamplesOut < pSamplesOutEnd) {
+ /*
+ Rice extraction. It's faster to do this one at a time against local variables than it is to use the x4 version
+ against an array. Not sure why, but perhaps it's making more efficient use of registers?
+ */
+ if (!drflac__read_rice_parts_x1(bs, riceParam, &zeroCountPart0, &riceParamPart0) ||
+ !drflac__read_rice_parts_x1(bs, riceParam, &zeroCountPart1, &riceParamPart1) ||
+ !drflac__read_rice_parts_x1(bs, riceParam, &zeroCountPart2, &riceParamPart2) ||
+ !drflac__read_rice_parts_x1(bs, riceParam, &zeroCountPart3, &riceParamPart3)) {
+ return DRFLAC_FALSE;
+ }
+
+ riceParamPart0 &= riceParamMask;
+ riceParamPart1 &= riceParamMask;
+ riceParamPart2 &= riceParamMask;
+ riceParamPart3 &= riceParamMask;
+
+ riceParamPart0 |= (zeroCountPart0 << riceParam);
+ riceParamPart1 |= (zeroCountPart1 << riceParam);
+ riceParamPart2 |= (zeroCountPart2 << riceParam);
+ riceParamPart3 |= (zeroCountPart3 << riceParam);
+
+ riceParamPart0 = (riceParamPart0 >> 1) ^ t[riceParamPart0 & 0x01];
+ riceParamPart1 = (riceParamPart1 >> 1) ^ t[riceParamPart1 & 0x01];
+ riceParamPart2 = (riceParamPart2 >> 1) ^ t[riceParamPart2 & 0x01];
+ riceParamPart3 = (riceParamPart3 >> 1) ^ t[riceParamPart3 & 0x01];
+
+ pSamplesOut[0] = riceParamPart0 + drflac__calculate_prediction_64(lpcOrder, lpcShift, coefficients, pSamplesOut + 0);
+ pSamplesOut[1] = riceParamPart1 + drflac__calculate_prediction_64(lpcOrder, lpcShift, coefficients, pSamplesOut + 1);
+ pSamplesOut[2] = riceParamPart2 + drflac__calculate_prediction_64(lpcOrder, lpcShift, coefficients, pSamplesOut + 2);
+ pSamplesOut[3] = riceParamPart3 + drflac__calculate_prediction_64(lpcOrder, lpcShift, coefficients, pSamplesOut + 3);
+
+ pSamplesOut += 4;
+ }
+ } else {
+ while (pSamplesOut < pSamplesOutEnd) {
+ if (!drflac__read_rice_parts_x1(bs, riceParam, &zeroCountPart0, &riceParamPart0) ||
+ !drflac__read_rice_parts_x1(bs, riceParam, &zeroCountPart1, &riceParamPart1) ||
+ !drflac__read_rice_parts_x1(bs, riceParam, &zeroCountPart2, &riceParamPart2) ||
+ !drflac__read_rice_parts_x1(bs, riceParam, &zeroCountPart3, &riceParamPart3)) {
+ return DRFLAC_FALSE;
+ }
+
+ riceParamPart0 &= riceParamMask;
+ riceParamPart1 &= riceParamMask;
+ riceParamPart2 &= riceParamMask;
+ riceParamPart3 &= riceParamMask;
+
+ riceParamPart0 |= (zeroCountPart0 << riceParam);
+ riceParamPart1 |= (zeroCountPart1 << riceParam);
+ riceParamPart2 |= (zeroCountPart2 << riceParam);
+ riceParamPart3 |= (zeroCountPart3 << riceParam);
+
+ riceParamPart0 = (riceParamPart0 >> 1) ^ t[riceParamPart0 & 0x01];
+ riceParamPart1 = (riceParamPart1 >> 1) ^ t[riceParamPart1 & 0x01];
+ riceParamPart2 = (riceParamPart2 >> 1) ^ t[riceParamPart2 & 0x01];
+ riceParamPart3 = (riceParamPart3 >> 1) ^ t[riceParamPart3 & 0x01];
+
+ pSamplesOut[0] = riceParamPart0 + drflac__calculate_prediction_32(lpcOrder, lpcShift, coefficients, pSamplesOut + 0);
+ pSamplesOut[1] = riceParamPart1 + drflac__calculate_prediction_32(lpcOrder, lpcShift, coefficients, pSamplesOut + 1);
+ pSamplesOut[2] = riceParamPart2 + drflac__calculate_prediction_32(lpcOrder, lpcShift, coefficients, pSamplesOut + 2);
+ pSamplesOut[3] = riceParamPart3 + drflac__calculate_prediction_32(lpcOrder, lpcShift, coefficients, pSamplesOut + 3);
+
+ pSamplesOut += 4;
+ }
+ }
+
+ i = (count & ~3);
+ while (i < count) {
+ /* Rice extraction. */
+ if (!drflac__read_rice_parts_x1(bs, riceParam, &zeroCountPart0, &riceParamPart0)) {
+ return DRFLAC_FALSE;
+ }
+
+ /* Rice reconstruction. */
+ riceParamPart0 &= riceParamMask;
+ riceParamPart0 |= (zeroCountPart0 << riceParam);
+ riceParamPart0 = (riceParamPart0 >> 1) ^ t[riceParamPart0 & 0x01];
+ /*riceParamPart0 = (riceParamPart0 >> 1) ^ (~(riceParamPart0 & 0x01) + 1);*/
+
+ /* Sample reconstruction. */
+ if (drflac__use_64_bit_prediction(bitsPerSample, lpcOrder, lpcPrecision)) {
+ pSamplesOut[0] = riceParamPart0 + drflac__calculate_prediction_64(lpcOrder, lpcShift, coefficients, pSamplesOut + 0);
+ } else {
+ pSamplesOut[0] = riceParamPart0 + drflac__calculate_prediction_32(lpcOrder, lpcShift, coefficients, pSamplesOut + 0);
+ }
+
+ i += 1;
+ pSamplesOut += 1;
+ }
+
+ return DRFLAC_TRUE;
+}
+
+#if defined(DRFLAC_SUPPORT_SSE2)
+static DRFLAC_INLINE __m128i drflac__mm_packs_interleaved_epi32(__m128i a, __m128i b)
+{
+ __m128i r;
+
+ /* Pack. */
+ r = _mm_packs_epi32(a, b);
+
+ /* a3a2 a1a0 b3b2 b1b0 -> a3a2 b3b2 a1a0 b1b0 */
+ r = _mm_shuffle_epi32(r, _MM_SHUFFLE(3, 1, 2, 0));
+
+ /* a3a2 b3b2 a1a0 b1b0 -> a3b3 a2b2 a1b1 a0b0 */
+ r = _mm_shufflehi_epi16(r, _MM_SHUFFLE(3, 1, 2, 0));
+ r = _mm_shufflelo_epi16(r, _MM_SHUFFLE(3, 1, 2, 0));
+
+ return r;
+}
+#endif
+
+#if defined(DRFLAC_SUPPORT_SSE41)
+static DRFLAC_INLINE __m128i drflac__mm_not_si128(__m128i a)
+{
+ return _mm_xor_si128(a, _mm_cmpeq_epi32(_mm_setzero_si128(), _mm_setzero_si128()));
+}
+
+static DRFLAC_INLINE __m128i drflac__mm_hadd_epi32(__m128i x)
+{
+ __m128i x64 = _mm_add_epi32(x, _mm_shuffle_epi32(x, _MM_SHUFFLE(1, 0, 3, 2)));
+ __m128i x32 = _mm_shufflelo_epi16(x64, _MM_SHUFFLE(1, 0, 3, 2));
+ return _mm_add_epi32(x64, x32);
+}
+
+static DRFLAC_INLINE __m128i drflac__mm_hadd_epi64(__m128i x)
+{
+ return _mm_add_epi64(x, _mm_shuffle_epi32(x, _MM_SHUFFLE(1, 0, 3, 2)));
+}
+
+static DRFLAC_INLINE __m128i drflac__mm_srai_epi64(__m128i x, int count)
+{
+ /*
+ To simplify this we are assuming count < 32. This restriction allows us to work on a low side and a high side. The low side
+ is shifted with zero bits, whereas the right side is shifted with sign bits.
+ */
+ __m128i lo = _mm_srli_epi64(x, count);
+ __m128i hi = _mm_srai_epi32(x, count);
+
+ hi = _mm_and_si128(hi, _mm_set_epi32(0xFFFFFFFF, 0, 0xFFFFFFFF, 0)); /* The high part needs to have the low part cleared. */
+
+ return _mm_or_si128(lo, hi);
+}
+
+static drflac_bool32 drflac__decode_samples_with_residual__rice__sse41_32(drflac_bs* bs, drflac_uint32 count, drflac_uint8 riceParam, drflac_uint32 order, drflac_int32 shift, const drflac_int32* coefficients, drflac_int32* pSamplesOut)
+{
+ int i;
+ drflac_uint32 riceParamMask;
+ drflac_int32* pDecodedSamples = pSamplesOut;
+ drflac_int32* pDecodedSamplesEnd = pSamplesOut + (count & ~3);
+ drflac_uint32 zeroCountParts0 = 0;
+ drflac_uint32 zeroCountParts1 = 0;
+ drflac_uint32 zeroCountParts2 = 0;
+ drflac_uint32 zeroCountParts3 = 0;
+ drflac_uint32 riceParamParts0 = 0;
+ drflac_uint32 riceParamParts1 = 0;
+ drflac_uint32 riceParamParts2 = 0;
+ drflac_uint32 riceParamParts3 = 0;
+ __m128i coefficients128_0;
+ __m128i coefficients128_4;
+ __m128i coefficients128_8;
+ __m128i samples128_0;
+ __m128i samples128_4;
+ __m128i samples128_8;
+ __m128i riceParamMask128;
+
+ const drflac_uint32 t[2] = {0x00000000, 0xFFFFFFFF};
+
+ riceParamMask = (drflac_uint32)~((~0UL) << riceParam);
+ riceParamMask128 = _mm_set1_epi32(riceParamMask);
+
+ /* Pre-load. */
+ coefficients128_0 = _mm_setzero_si128();
+ coefficients128_4 = _mm_setzero_si128();
+ coefficients128_8 = _mm_setzero_si128();
+
+ samples128_0 = _mm_setzero_si128();
+ samples128_4 = _mm_setzero_si128();
+ samples128_8 = _mm_setzero_si128();
+
+ /*
+ Pre-loading the coefficients and prior samples is annoying because we need to ensure we don't try reading more than
+ what's available in the input buffers. It would be convenient to use a fall-through switch to do this, but this results
+ in strict aliasing warnings with GCC. To work around this I'm just doing something hacky. This feels a bit convoluted
+ so I think there's opportunity for this to be simplified.
+ */
+#if 1
+ {
+ int runningOrder = order;
+
+ /* 0 - 3. */
+ if (runningOrder >= 4) {
+ coefficients128_0 = _mm_loadu_si128((const __m128i*)(coefficients + 0));
+ samples128_0 = _mm_loadu_si128((const __m128i*)(pSamplesOut - 4));
+ runningOrder -= 4;
+ } else {
+ switch (runningOrder) {
+ case 3: coefficients128_0 = _mm_set_epi32(0, coefficients[2], coefficients[1], coefficients[0]); samples128_0 = _mm_set_epi32(pSamplesOut[-1], pSamplesOut[-2], pSamplesOut[-3], 0); break;
+ case 2: coefficients128_0 = _mm_set_epi32(0, 0, coefficients[1], coefficients[0]); samples128_0 = _mm_set_epi32(pSamplesOut[-1], pSamplesOut[-2], 0, 0); break;
+ case 1: coefficients128_0 = _mm_set_epi32(0, 0, 0, coefficients[0]); samples128_0 = _mm_set_epi32(pSamplesOut[-1], 0, 0, 0); break;
+ }
+ runningOrder = 0;
+ }
+
+ /* 4 - 7 */
+ if (runningOrder >= 4) {
+ coefficients128_4 = _mm_loadu_si128((const __m128i*)(coefficients + 4));
+ samples128_4 = _mm_loadu_si128((const __m128i*)(pSamplesOut - 8));
+ runningOrder -= 4;
+ } else {
+ switch (runningOrder) {
+ case 3: coefficients128_4 = _mm_set_epi32(0, coefficients[6], coefficients[5], coefficients[4]); samples128_4 = _mm_set_epi32(pSamplesOut[-5], pSamplesOut[-6], pSamplesOut[-7], 0); break;
+ case 2: coefficients128_4 = _mm_set_epi32(0, 0, coefficients[5], coefficients[4]); samples128_4 = _mm_set_epi32(pSamplesOut[-5], pSamplesOut[-6], 0, 0); break;
+ case 1: coefficients128_4 = _mm_set_epi32(0, 0, 0, coefficients[4]); samples128_4 = _mm_set_epi32(pSamplesOut[-5], 0, 0, 0); break;
+ }
+ runningOrder = 0;
+ }
+
+ /* 8 - 11 */
+ if (runningOrder == 4) {
+ coefficients128_8 = _mm_loadu_si128((const __m128i*)(coefficients + 8));
+ samples128_8 = _mm_loadu_si128((const __m128i*)(pSamplesOut - 12));
+ runningOrder -= 4;
+ } else {
+ switch (runningOrder) {
+ case 3: coefficients128_8 = _mm_set_epi32(0, coefficients[10], coefficients[9], coefficients[8]); samples128_8 = _mm_set_epi32(pSamplesOut[-9], pSamplesOut[-10], pSamplesOut[-11], 0); break;
+ case 2: coefficients128_8 = _mm_set_epi32(0, 0, coefficients[9], coefficients[8]); samples128_8 = _mm_set_epi32(pSamplesOut[-9], pSamplesOut[-10], 0, 0); break;
+ case 1: coefficients128_8 = _mm_set_epi32(0, 0, 0, coefficients[8]); samples128_8 = _mm_set_epi32(pSamplesOut[-9], 0, 0, 0); break;
+ }
+ runningOrder = 0;
+ }
+
+ /* Coefficients need to be shuffled for our streaming algorithm below to work. Samples are already in the correct order from the loading routine above. */
+ coefficients128_0 = _mm_shuffle_epi32(coefficients128_0, _MM_SHUFFLE(0, 1, 2, 3));
+ coefficients128_4 = _mm_shuffle_epi32(coefficients128_4, _MM_SHUFFLE(0, 1, 2, 3));
+ coefficients128_8 = _mm_shuffle_epi32(coefficients128_8, _MM_SHUFFLE(0, 1, 2, 3));
+ }
+#else
+ /* This causes strict-aliasing warnings with GCC. */
+ switch (order)
+ {
+ case 12: ((drflac_int32*)&coefficients128_8)[0] = coefficients[11]; ((drflac_int32*)&samples128_8)[0] = pDecodedSamples[-12];
+ case 11: ((drflac_int32*)&coefficients128_8)[1] = coefficients[10]; ((drflac_int32*)&samples128_8)[1] = pDecodedSamples[-11];
+ case 10: ((drflac_int32*)&coefficients128_8)[2] = coefficients[ 9]; ((drflac_int32*)&samples128_8)[2] = pDecodedSamples[-10];
+ case 9: ((drflac_int32*)&coefficients128_8)[3] = coefficients[ 8]; ((drflac_int32*)&samples128_8)[3] = pDecodedSamples[- 9];
+ case 8: ((drflac_int32*)&coefficients128_4)[0] = coefficients[ 7]; ((drflac_int32*)&samples128_4)[0] = pDecodedSamples[- 8];
+ case 7: ((drflac_int32*)&coefficients128_4)[1] = coefficients[ 6]; ((drflac_int32*)&samples128_4)[1] = pDecodedSamples[- 7];
+ case 6: ((drflac_int32*)&coefficients128_4)[2] = coefficients[ 5]; ((drflac_int32*)&samples128_4)[2] = pDecodedSamples[- 6];
+ case 5: ((drflac_int32*)&coefficients128_4)[3] = coefficients[ 4]; ((drflac_int32*)&samples128_4)[3] = pDecodedSamples[- 5];
+ case 4: ((drflac_int32*)&coefficients128_0)[0] = coefficients[ 3]; ((drflac_int32*)&samples128_0)[0] = pDecodedSamples[- 4];
+ case 3: ((drflac_int32*)&coefficients128_0)[1] = coefficients[ 2]; ((drflac_int32*)&samples128_0)[1] = pDecodedSamples[- 3];
+ case 2: ((drflac_int32*)&coefficients128_0)[2] = coefficients[ 1]; ((drflac_int32*)&samples128_0)[2] = pDecodedSamples[- 2];
+ case 1: ((drflac_int32*)&coefficients128_0)[3] = coefficients[ 0]; ((drflac_int32*)&samples128_0)[3] = pDecodedSamples[- 1];
+ }
+#endif
+
+ /* For this version we are doing one sample at a time. */
+ while (pDecodedSamples < pDecodedSamplesEnd) {
+ __m128i prediction128;
+ __m128i zeroCountPart128;
+ __m128i riceParamPart128;
+
+ if (!drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts0, &riceParamParts0) ||
+ !drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts1, &riceParamParts1) ||
+ !drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts2, &riceParamParts2) ||
+ !drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts3, &riceParamParts3)) {
+ return DRFLAC_FALSE;
+ }
+
+ zeroCountPart128 = _mm_set_epi32(zeroCountParts3, zeroCountParts2, zeroCountParts1, zeroCountParts0);
+ riceParamPart128 = _mm_set_epi32(riceParamParts3, riceParamParts2, riceParamParts1, riceParamParts0);
+
+ riceParamPart128 = _mm_and_si128(riceParamPart128, riceParamMask128);
+ riceParamPart128 = _mm_or_si128(riceParamPart128, _mm_slli_epi32(zeroCountPart128, riceParam));
+ riceParamPart128 = _mm_xor_si128(_mm_srli_epi32(riceParamPart128, 1), _mm_add_epi32(drflac__mm_not_si128(_mm_and_si128(riceParamPart128, _mm_set1_epi32(0x01))), _mm_set1_epi32(0x01))); /* <-- SSE2 compatible */
+ /*riceParamPart128 = _mm_xor_si128(_mm_srli_epi32(riceParamPart128, 1), _mm_mullo_epi32(_mm_and_si128(riceParamPart128, _mm_set1_epi32(0x01)), _mm_set1_epi32(0xFFFFFFFF)));*/ /* <-- Only supported from SSE4.1 and is slower in my testing... */
+
+ if (order <= 4) {
+ for (i = 0; i < 4; i += 1) {
+ prediction128 = _mm_mullo_epi32(coefficients128_0, samples128_0);
+
+ /* Horizontal add and shift. */
+ prediction128 = drflac__mm_hadd_epi32(prediction128);
+ prediction128 = _mm_srai_epi32(prediction128, shift);
+ prediction128 = _mm_add_epi32(riceParamPart128, prediction128);
+
+ samples128_0 = _mm_alignr_epi8(prediction128, samples128_0, 4);
+ riceParamPart128 = _mm_alignr_epi8(_mm_setzero_si128(), riceParamPart128, 4);
+ }
+ } else if (order <= 8) {
+ for (i = 0; i < 4; i += 1) {
+ prediction128 = _mm_mullo_epi32(coefficients128_4, samples128_4);
+ prediction128 = _mm_add_epi32(prediction128, _mm_mullo_epi32(coefficients128_0, samples128_0));
+
+ /* Horizontal add and shift. */
+ prediction128 = drflac__mm_hadd_epi32(prediction128);
+ prediction128 = _mm_srai_epi32(prediction128, shift);
+ prediction128 = _mm_add_epi32(riceParamPart128, prediction128);
+
+ samples128_4 = _mm_alignr_epi8(samples128_0, samples128_4, 4);
+ samples128_0 = _mm_alignr_epi8(prediction128, samples128_0, 4);
+ riceParamPart128 = _mm_alignr_epi8(_mm_setzero_si128(), riceParamPart128, 4);
+ }
+ } else {
+ for (i = 0; i < 4; i += 1) {
+ prediction128 = _mm_mullo_epi32(coefficients128_8, samples128_8);
+ prediction128 = _mm_add_epi32(prediction128, _mm_mullo_epi32(coefficients128_4, samples128_4));
+ prediction128 = _mm_add_epi32(prediction128, _mm_mullo_epi32(coefficients128_0, samples128_0));
+
+ /* Horizontal add and shift. */
+ prediction128 = drflac__mm_hadd_epi32(prediction128);
+ prediction128 = _mm_srai_epi32(prediction128, shift);
+ prediction128 = _mm_add_epi32(riceParamPart128, prediction128);
+
+ samples128_8 = _mm_alignr_epi8(samples128_4, samples128_8, 4);
+ samples128_4 = _mm_alignr_epi8(samples128_0, samples128_4, 4);
+ samples128_0 = _mm_alignr_epi8(prediction128, samples128_0, 4);
+ riceParamPart128 = _mm_alignr_epi8(_mm_setzero_si128(), riceParamPart128, 4);
+ }
+ }
+
+ /* We store samples in groups of 4. */
+ _mm_storeu_si128((__m128i*)pDecodedSamples, samples128_0);
+ pDecodedSamples += 4;
+ }
+
+ /* Make sure we process the last few samples. */
+ i = (count & ~3);
+ while (i < (int)count) {
+ /* Rice extraction. */
+ if (!drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts0, &riceParamParts0)) {
+ return DRFLAC_FALSE;
+ }
+
+ /* Rice reconstruction. */
+ riceParamParts0 &= riceParamMask;
+ riceParamParts0 |= (zeroCountParts0 << riceParam);
+ riceParamParts0 = (riceParamParts0 >> 1) ^ t[riceParamParts0 & 0x01];
+
+ /* Sample reconstruction. */
+ pDecodedSamples[0] = riceParamParts0 + drflac__calculate_prediction_32(order, shift, coefficients, pDecodedSamples);
+
+ i += 1;
+ pDecodedSamples += 1;
+ }
+
+ return DRFLAC_TRUE;
+}
+
+static drflac_bool32 drflac__decode_samples_with_residual__rice__sse41_64(drflac_bs* bs, drflac_uint32 count, drflac_uint8 riceParam, drflac_uint32 order, drflac_int32 shift, const drflac_int32* coefficients, drflac_int32* pSamplesOut)
+{
+ int i;
+ drflac_uint32 riceParamMask;
+ drflac_int32* pDecodedSamples = pSamplesOut;
+ drflac_int32* pDecodedSamplesEnd = pSamplesOut + (count & ~3);
+ drflac_uint32 zeroCountParts0 = 0;
+ drflac_uint32 zeroCountParts1 = 0;
+ drflac_uint32 zeroCountParts2 = 0;
+ drflac_uint32 zeroCountParts3 = 0;
+ drflac_uint32 riceParamParts0 = 0;
+ drflac_uint32 riceParamParts1 = 0;
+ drflac_uint32 riceParamParts2 = 0;
+ drflac_uint32 riceParamParts3 = 0;
+ __m128i coefficients128_0;
+ __m128i coefficients128_4;
+ __m128i coefficients128_8;
+ __m128i samples128_0;
+ __m128i samples128_4;
+ __m128i samples128_8;
+ __m128i prediction128;
+ __m128i riceParamMask128;
+
+ const drflac_uint32 t[2] = {0x00000000, 0xFFFFFFFF};
+
+ DRFLAC_ASSERT(order <= 12);
+
+ riceParamMask = (drflac_uint32)~((~0UL) << riceParam);
+ riceParamMask128 = _mm_set1_epi32(riceParamMask);
+
+ prediction128 = _mm_setzero_si128();
+
+ /* Pre-load. */
+ coefficients128_0 = _mm_setzero_si128();
+ coefficients128_4 = _mm_setzero_si128();
+ coefficients128_8 = _mm_setzero_si128();
+
+ samples128_0 = _mm_setzero_si128();
+ samples128_4 = _mm_setzero_si128();
+ samples128_8 = _mm_setzero_si128();
+
+#if 1
+ {
+ int runningOrder = order;
+
+ /* 0 - 3. */
+ if (runningOrder >= 4) {
+ coefficients128_0 = _mm_loadu_si128((const __m128i*)(coefficients + 0));
+ samples128_0 = _mm_loadu_si128((const __m128i*)(pSamplesOut - 4));
+ runningOrder -= 4;
+ } else {
+ switch (runningOrder) {
+ case 3: coefficients128_0 = _mm_set_epi32(0, coefficients[2], coefficients[1], coefficients[0]); samples128_0 = _mm_set_epi32(pSamplesOut[-1], pSamplesOut[-2], pSamplesOut[-3], 0); break;
+ case 2: coefficients128_0 = _mm_set_epi32(0, 0, coefficients[1], coefficients[0]); samples128_0 = _mm_set_epi32(pSamplesOut[-1], pSamplesOut[-2], 0, 0); break;
+ case 1: coefficients128_0 = _mm_set_epi32(0, 0, 0, coefficients[0]); samples128_0 = _mm_set_epi32(pSamplesOut[-1], 0, 0, 0); break;
+ }
+ runningOrder = 0;
+ }
+
+ /* 4 - 7 */
+ if (runningOrder >= 4) {
+ coefficients128_4 = _mm_loadu_si128((const __m128i*)(coefficients + 4));
+ samples128_4 = _mm_loadu_si128((const __m128i*)(pSamplesOut - 8));
+ runningOrder -= 4;
+ } else {
+ switch (runningOrder) {
+ case 3: coefficients128_4 = _mm_set_epi32(0, coefficients[6], coefficients[5], coefficients[4]); samples128_4 = _mm_set_epi32(pSamplesOut[-5], pSamplesOut[-6], pSamplesOut[-7], 0); break;
+ case 2: coefficients128_4 = _mm_set_epi32(0, 0, coefficients[5], coefficients[4]); samples128_4 = _mm_set_epi32(pSamplesOut[-5], pSamplesOut[-6], 0, 0); break;
+ case 1: coefficients128_4 = _mm_set_epi32(0, 0, 0, coefficients[4]); samples128_4 = _mm_set_epi32(pSamplesOut[-5], 0, 0, 0); break;
+ }
+ runningOrder = 0;
+ }
+
+ /* 8 - 11 */
+ if (runningOrder == 4) {
+ coefficients128_8 = _mm_loadu_si128((const __m128i*)(coefficients + 8));
+ samples128_8 = _mm_loadu_si128((const __m128i*)(pSamplesOut - 12));
+ runningOrder -= 4;
+ } else {
+ switch (runningOrder) {
+ case 3: coefficients128_8 = _mm_set_epi32(0, coefficients[10], coefficients[9], coefficients[8]); samples128_8 = _mm_set_epi32(pSamplesOut[-9], pSamplesOut[-10], pSamplesOut[-11], 0); break;
+ case 2: coefficients128_8 = _mm_set_epi32(0, 0, coefficients[9], coefficients[8]); samples128_8 = _mm_set_epi32(pSamplesOut[-9], pSamplesOut[-10], 0, 0); break;
+ case 1: coefficients128_8 = _mm_set_epi32(0, 0, 0, coefficients[8]); samples128_8 = _mm_set_epi32(pSamplesOut[-9], 0, 0, 0); break;
+ }
+ runningOrder = 0;
+ }
+
+ /* Coefficients need to be shuffled for our streaming algorithm below to work. Samples are already in the correct order from the loading routine above. */
+ coefficients128_0 = _mm_shuffle_epi32(coefficients128_0, _MM_SHUFFLE(0, 1, 2, 3));
+ coefficients128_4 = _mm_shuffle_epi32(coefficients128_4, _MM_SHUFFLE(0, 1, 2, 3));
+ coefficients128_8 = _mm_shuffle_epi32(coefficients128_8, _MM_SHUFFLE(0, 1, 2, 3));
+ }
+#else
+ switch (order)
+ {
+ case 12: ((drflac_int32*)&coefficients128_8)[0] = coefficients[11]; ((drflac_int32*)&samples128_8)[0] = pDecodedSamples[-12];
+ case 11: ((drflac_int32*)&coefficients128_8)[1] = coefficients[10]; ((drflac_int32*)&samples128_8)[1] = pDecodedSamples[-11];
+ case 10: ((drflac_int32*)&coefficients128_8)[2] = coefficients[ 9]; ((drflac_int32*)&samples128_8)[2] = pDecodedSamples[-10];
+ case 9: ((drflac_int32*)&coefficients128_8)[3] = coefficients[ 8]; ((drflac_int32*)&samples128_8)[3] = pDecodedSamples[- 9];
+ case 8: ((drflac_int32*)&coefficients128_4)[0] = coefficients[ 7]; ((drflac_int32*)&samples128_4)[0] = pDecodedSamples[- 8];
+ case 7: ((drflac_int32*)&coefficients128_4)[1] = coefficients[ 6]; ((drflac_int32*)&samples128_4)[1] = pDecodedSamples[- 7];
+ case 6: ((drflac_int32*)&coefficients128_4)[2] = coefficients[ 5]; ((drflac_int32*)&samples128_4)[2] = pDecodedSamples[- 6];
+ case 5: ((drflac_int32*)&coefficients128_4)[3] = coefficients[ 4]; ((drflac_int32*)&samples128_4)[3] = pDecodedSamples[- 5];
+ case 4: ((drflac_int32*)&coefficients128_0)[0] = coefficients[ 3]; ((drflac_int32*)&samples128_0)[0] = pDecodedSamples[- 4];
+ case 3: ((drflac_int32*)&coefficients128_0)[1] = coefficients[ 2]; ((drflac_int32*)&samples128_0)[1] = pDecodedSamples[- 3];
+ case 2: ((drflac_int32*)&coefficients128_0)[2] = coefficients[ 1]; ((drflac_int32*)&samples128_0)[2] = pDecodedSamples[- 2];
+ case 1: ((drflac_int32*)&coefficients128_0)[3] = coefficients[ 0]; ((drflac_int32*)&samples128_0)[3] = pDecodedSamples[- 1];
+ }
+#endif
+
+ /* For this version we are doing one sample at a time. */
+ while (pDecodedSamples < pDecodedSamplesEnd) {
+ __m128i zeroCountPart128;
+ __m128i riceParamPart128;
+
+ if (!drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts0, &riceParamParts0) ||
+ !drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts1, &riceParamParts1) ||
+ !drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts2, &riceParamParts2) ||
+ !drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts3, &riceParamParts3)) {
+ return DRFLAC_FALSE;
+ }
+
+ zeroCountPart128 = _mm_set_epi32(zeroCountParts3, zeroCountParts2, zeroCountParts1, zeroCountParts0);
+ riceParamPart128 = _mm_set_epi32(riceParamParts3, riceParamParts2, riceParamParts1, riceParamParts0);
+
+ riceParamPart128 = _mm_and_si128(riceParamPart128, riceParamMask128);
+ riceParamPart128 = _mm_or_si128(riceParamPart128, _mm_slli_epi32(zeroCountPart128, riceParam));
+ riceParamPart128 = _mm_xor_si128(_mm_srli_epi32(riceParamPart128, 1), _mm_add_epi32(drflac__mm_not_si128(_mm_and_si128(riceParamPart128, _mm_set1_epi32(1))), _mm_set1_epi32(1)));
+
+ for (i = 0; i < 4; i += 1) {
+ prediction128 = _mm_xor_si128(prediction128, prediction128); /* Reset to 0. */
+
+ switch (order)
+ {
+ case 12:
+ case 11: prediction128 = _mm_add_epi64(prediction128, _mm_mul_epi32(_mm_shuffle_epi32(coefficients128_8, _MM_SHUFFLE(1, 1, 0, 0)), _mm_shuffle_epi32(samples128_8, _MM_SHUFFLE(1, 1, 0, 0))));
+ case 10:
+ case 9: prediction128 = _mm_add_epi64(prediction128, _mm_mul_epi32(_mm_shuffle_epi32(coefficients128_8, _MM_SHUFFLE(3, 3, 2, 2)), _mm_shuffle_epi32(samples128_8, _MM_SHUFFLE(3, 3, 2, 2))));
+ case 8:
+ case 7: prediction128 = _mm_add_epi64(prediction128, _mm_mul_epi32(_mm_shuffle_epi32(coefficients128_4, _MM_SHUFFLE(1, 1, 0, 0)), _mm_shuffle_epi32(samples128_4, _MM_SHUFFLE(1, 1, 0, 0))));
+ case 6:
+ case 5: prediction128 = _mm_add_epi64(prediction128, _mm_mul_epi32(_mm_shuffle_epi32(coefficients128_4, _MM_SHUFFLE(3, 3, 2, 2)), _mm_shuffle_epi32(samples128_4, _MM_SHUFFLE(3, 3, 2, 2))));
+ case 4:
+ case 3: prediction128 = _mm_add_epi64(prediction128, _mm_mul_epi32(_mm_shuffle_epi32(coefficients128_0, _MM_SHUFFLE(1, 1, 0, 0)), _mm_shuffle_epi32(samples128_0, _MM_SHUFFLE(1, 1, 0, 0))));
+ case 2:
+ case 1: prediction128 = _mm_add_epi64(prediction128, _mm_mul_epi32(_mm_shuffle_epi32(coefficients128_0, _MM_SHUFFLE(3, 3, 2, 2)), _mm_shuffle_epi32(samples128_0, _MM_SHUFFLE(3, 3, 2, 2))));
+ }
+
+ /* Horizontal add and shift. */
+ prediction128 = drflac__mm_hadd_epi64(prediction128);
+ prediction128 = drflac__mm_srai_epi64(prediction128, shift);
+ prediction128 = _mm_add_epi32(riceParamPart128, prediction128);
+
+ /* Our value should be sitting in prediction128[0]. We need to combine this with our SSE samples. */
+ samples128_8 = _mm_alignr_epi8(samples128_4, samples128_8, 4);
+ samples128_4 = _mm_alignr_epi8(samples128_0, samples128_4, 4);
+ samples128_0 = _mm_alignr_epi8(prediction128, samples128_0, 4);
+
+ /* Slide our rice parameter down so that the value in position 0 contains the next one to process. */
+ riceParamPart128 = _mm_alignr_epi8(_mm_setzero_si128(), riceParamPart128, 4);
+ }
+
+ /* We store samples in groups of 4. */
+ _mm_storeu_si128((__m128i*)pDecodedSamples, samples128_0);
+ pDecodedSamples += 4;
+ }
+
+ /* Make sure we process the last few samples. */
+ i = (count & ~3);
+ while (i < (int)count) {
+ /* Rice extraction. */
+ if (!drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts0, &riceParamParts0)) {
+ return DRFLAC_FALSE;
+ }
+
+ /* Rice reconstruction. */
+ riceParamParts0 &= riceParamMask;
+ riceParamParts0 |= (zeroCountParts0 << riceParam);
+ riceParamParts0 = (riceParamParts0 >> 1) ^ t[riceParamParts0 & 0x01];
+
+ /* Sample reconstruction. */
+ pDecodedSamples[0] = riceParamParts0 + drflac__calculate_prediction_64(order, shift, coefficients, pDecodedSamples);
+
+ i += 1;
+ pDecodedSamples += 1;
+ }
+
+ return DRFLAC_TRUE;
+}
+
+static drflac_bool32 drflac__decode_samples_with_residual__rice__sse41(drflac_bs* bs, drflac_uint32 bitsPerSample, drflac_uint32 count, drflac_uint8 riceParam, drflac_uint32 lpcOrder, drflac_int32 lpcShift, drflac_uint32 lpcPrecision, const drflac_int32* coefficients, drflac_int32* pSamplesOut)
+{
+ DRFLAC_ASSERT(bs != NULL);
+ DRFLAC_ASSERT(pSamplesOut != NULL);
+
+ /* In my testing the order is rarely > 12, so in this case I'm going to simplify the SSE implementation by only handling order <= 12. */
+ if (lpcOrder > 0 && lpcOrder <= 12) {
+ if (drflac__use_64_bit_prediction(bitsPerSample, lpcOrder, lpcPrecision)) {
+ return drflac__decode_samples_with_residual__rice__sse41_64(bs, count, riceParam, lpcOrder, lpcShift, coefficients, pSamplesOut);
+ } else {
+ return drflac__decode_samples_with_residual__rice__sse41_32(bs, count, riceParam, lpcOrder, lpcShift, coefficients, pSamplesOut);
+ }
+ } else {
+ return drflac__decode_samples_with_residual__rice__scalar(bs, bitsPerSample, count, riceParam, lpcOrder, lpcShift, lpcPrecision, coefficients, pSamplesOut);
+ }
+}
+#endif
+
+#if defined(DRFLAC_SUPPORT_NEON)
+static DRFLAC_INLINE void drflac__vst2q_s32(drflac_int32* p, int32x4x2_t x)
+{
+ vst1q_s32(p+0, x.val[0]);
+ vst1q_s32(p+4, x.val[1]);
+}
+
+static DRFLAC_INLINE void drflac__vst2q_u32(drflac_uint32* p, uint32x4x2_t x)
+{
+ vst1q_u32(p+0, x.val[0]);
+ vst1q_u32(p+4, x.val[1]);
+}
+
+static DRFLAC_INLINE void drflac__vst2q_f32(float* p, float32x4x2_t x)
+{
+ vst1q_f32(p+0, x.val[0]);
+ vst1q_f32(p+4, x.val[1]);
+}
+
+static DRFLAC_INLINE void drflac__vst2q_s16(drflac_int16* p, int16x4x2_t x)
+{
+ vst1q_s16(p, vcombine_s16(x.val[0], x.val[1]));
+}
+
+static DRFLAC_INLINE void drflac__vst2q_u16(drflac_uint16* p, uint16x4x2_t x)
+{
+ vst1q_u16(p, vcombine_u16(x.val[0], x.val[1]));
+}
+
+static DRFLAC_INLINE int32x4_t drflac__vdupq_n_s32x4(drflac_int32 x3, drflac_int32 x2, drflac_int32 x1, drflac_int32 x0)
+{
+ drflac_int32 x[4];
+ x[3] = x3;
+ x[2] = x2;
+ x[1] = x1;
+ x[0] = x0;
+ return vld1q_s32(x);
+}
+
+static DRFLAC_INLINE int32x4_t drflac__valignrq_s32_1(int32x4_t a, int32x4_t b)
+{
+ /* Equivalent to SSE's _mm_alignr_epi8(a, b, 4) */
+
+ /* Reference */
+ /*return drflac__vdupq_n_s32x4(
+ vgetq_lane_s32(a, 0),
+ vgetq_lane_s32(b, 3),
+ vgetq_lane_s32(b, 2),
+ vgetq_lane_s32(b, 1)
+ );*/
+
+ return vextq_s32(b, a, 1);
+}
+
+static DRFLAC_INLINE uint32x4_t drflac__valignrq_u32_1(uint32x4_t a, uint32x4_t b)
+{
+ /* Equivalent to SSE's _mm_alignr_epi8(a, b, 4) */
+
+ /* Reference */
+ /*return drflac__vdupq_n_s32x4(
+ vgetq_lane_s32(a, 0),
+ vgetq_lane_s32(b, 3),
+ vgetq_lane_s32(b, 2),
+ vgetq_lane_s32(b, 1)
+ );*/
+
+ return vextq_u32(b, a, 1);
+}
+
+static DRFLAC_INLINE int32x2_t drflac__vhaddq_s32(int32x4_t x)
+{
+ /* The sum must end up in position 0. */
+
+ /* Reference */
+ /*return vdupq_n_s32(
+ vgetq_lane_s32(x, 3) +
+ vgetq_lane_s32(x, 2) +
+ vgetq_lane_s32(x, 1) +
+ vgetq_lane_s32(x, 0)
+ );*/
+
+ int32x2_t r = vadd_s32(vget_high_s32(x), vget_low_s32(x));
+ return vpadd_s32(r, r);
+}
+
+static DRFLAC_INLINE int64x1_t drflac__vhaddq_s64(int64x2_t x)
+{
+ return vadd_s64(vget_high_s64(x), vget_low_s64(x));
+}
+
+static DRFLAC_INLINE int32x4_t drflac__vrevq_s32(int32x4_t x)
+{
+ /* Reference */
+ /*return drflac__vdupq_n_s32x4(
+ vgetq_lane_s32(x, 0),
+ vgetq_lane_s32(x, 1),
+ vgetq_lane_s32(x, 2),
+ vgetq_lane_s32(x, 3)
+ );*/
+
+ return vrev64q_s32(vcombine_s32(vget_high_s32(x), vget_low_s32(x)));
+}
+
+static DRFLAC_INLINE int32x4_t drflac__vnotq_s32(int32x4_t x)
+{
+ return veorq_s32(x, vdupq_n_s32(0xFFFFFFFF));
+}
+
+static DRFLAC_INLINE uint32x4_t drflac__vnotq_u32(uint32x4_t x)
+{
+ return veorq_u32(x, vdupq_n_u32(0xFFFFFFFF));
+}
+
+static drflac_bool32 drflac__decode_samples_with_residual__rice__neon_32(drflac_bs* bs, drflac_uint32 count, drflac_uint8 riceParam, drflac_uint32 order, drflac_int32 shift, const drflac_int32* coefficients, drflac_int32* pSamplesOut)
+{
+ int i;
+ drflac_uint32 riceParamMask;
+ drflac_int32* pDecodedSamples = pSamplesOut;
+ drflac_int32* pDecodedSamplesEnd = pSamplesOut + (count & ~3);
+ drflac_uint32 zeroCountParts[4];
+ drflac_uint32 riceParamParts[4];
+ int32x4_t coefficients128_0;
+ int32x4_t coefficients128_4;
+ int32x4_t coefficients128_8;
+ int32x4_t samples128_0;
+ int32x4_t samples128_4;
+ int32x4_t samples128_8;
+ uint32x4_t riceParamMask128;
+ int32x4_t riceParam128;
+ int32x2_t shift64;
+ uint32x4_t one128;
+
+ const drflac_uint32 t[2] = {0x00000000, 0xFFFFFFFF};
+
+ riceParamMask = (drflac_uint32)~((~0UL) << riceParam);
+ riceParamMask128 = vdupq_n_u32(riceParamMask);
+
+ riceParam128 = vdupq_n_s32(riceParam);
+ shift64 = vdup_n_s32(-shift); /* Negate the shift because we'll be doing a variable shift using vshlq_s32(). */
+ one128 = vdupq_n_u32(1);
+
+ /*
+ Pre-loading the coefficients and prior samples is annoying because we need to ensure we don't try reading more than
+ what's available in the input buffers. It would be conenient to use a fall-through switch to do this, but this results
+ in strict aliasing warnings with GCC. To work around this I'm just doing something hacky. This feels a bit convoluted
+ so I think there's opportunity for this to be simplified.
+ */
+ {
+ int runningOrder = order;
+ drflac_int32 tempC[4] = {0, 0, 0, 0};
+ drflac_int32 tempS[4] = {0, 0, 0, 0};
+
+ /* 0 - 3. */
+ if (runningOrder >= 4) {
+ coefficients128_0 = vld1q_s32(coefficients + 0);
+ samples128_0 = vld1q_s32(pSamplesOut - 4);
+ runningOrder -= 4;
+ } else {
+ switch (runningOrder) {
+ case 3: tempC[2] = coefficients[2]; tempS[1] = pSamplesOut[-3]; /* fallthrough */
+ case 2: tempC[1] = coefficients[1]; tempS[2] = pSamplesOut[-2]; /* fallthrough */
+ case 1: tempC[0] = coefficients[0]; tempS[3] = pSamplesOut[-1]; /* fallthrough */
+ }
+
+ coefficients128_0 = vld1q_s32(tempC);
+ samples128_0 = vld1q_s32(tempS);
+ runningOrder = 0;
+ }
+
+ /* 4 - 7 */
+ if (runningOrder >= 4) {
+ coefficients128_4 = vld1q_s32(coefficients + 4);
+ samples128_4 = vld1q_s32(pSamplesOut - 8);
+ runningOrder -= 4;
+ } else {
+ switch (runningOrder) {
+ case 3: tempC[2] = coefficients[6]; tempS[1] = pSamplesOut[-7]; /* fallthrough */
+ case 2: tempC[1] = coefficients[5]; tempS[2] = pSamplesOut[-6]; /* fallthrough */
+ case 1: tempC[0] = coefficients[4]; tempS[3] = pSamplesOut[-5]; /* fallthrough */
+ }
+
+ coefficients128_4 = vld1q_s32(tempC);
+ samples128_4 = vld1q_s32(tempS);
+ runningOrder = 0;
+ }
+
+ /* 8 - 11 */
+ if (runningOrder == 4) {
+ coefficients128_8 = vld1q_s32(coefficients + 8);
+ samples128_8 = vld1q_s32(pSamplesOut - 12);
+ runningOrder -= 4;
+ } else {
+ switch (runningOrder) {
+ case 3: tempC[2] = coefficients[10]; tempS[1] = pSamplesOut[-11]; /* fallthrough */
+ case 2: tempC[1] = coefficients[ 9]; tempS[2] = pSamplesOut[-10]; /* fallthrough */
+ case 1: tempC[0] = coefficients[ 8]; tempS[3] = pSamplesOut[- 9]; /* fallthrough */
+ }
+
+ coefficients128_8 = vld1q_s32(tempC);
+ samples128_8 = vld1q_s32(tempS);
+ runningOrder = 0;
+ }
+
+ /* Coefficients need to be shuffled for our streaming algorithm below to work. Samples are already in the correct order from the loading routine above. */
+ coefficients128_0 = drflac__vrevq_s32(coefficients128_0);
+ coefficients128_4 = drflac__vrevq_s32(coefficients128_4);
+ coefficients128_8 = drflac__vrevq_s32(coefficients128_8);
+ }
+
+ /* For this version we are doing one sample at a time. */
+ while (pDecodedSamples < pDecodedSamplesEnd) {
+ int32x4_t prediction128;
+ int32x2_t prediction64;
+ uint32x4_t zeroCountPart128;
+ uint32x4_t riceParamPart128;
+
+ if (!drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts[0], &riceParamParts[0]) ||
+ !drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts[1], &riceParamParts[1]) ||
+ !drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts[2], &riceParamParts[2]) ||
+ !drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts[3], &riceParamParts[3])) {
+ return DRFLAC_FALSE;
+ }
+
+ zeroCountPart128 = vld1q_u32(zeroCountParts);
+ riceParamPart128 = vld1q_u32(riceParamParts);
+
+ riceParamPart128 = vandq_u32(riceParamPart128, riceParamMask128);
+ riceParamPart128 = vorrq_u32(riceParamPart128, vshlq_u32(zeroCountPart128, riceParam128));
+ riceParamPart128 = veorq_u32(vshrq_n_u32(riceParamPart128, 1), vaddq_u32(drflac__vnotq_u32(vandq_u32(riceParamPart128, one128)), one128));
+
+ if (order <= 4) {
+ for (i = 0; i < 4; i += 1) {
+ prediction128 = vmulq_s32(coefficients128_0, samples128_0);
+
+ /* Horizontal add and shift. */
+ prediction64 = drflac__vhaddq_s32(prediction128);
+ prediction64 = vshl_s32(prediction64, shift64);
+ prediction64 = vadd_s32(prediction64, vget_low_s32(vreinterpretq_s32_u32(riceParamPart128)));
+
+ samples128_0 = drflac__valignrq_s32_1(vcombine_s32(prediction64, vdup_n_s32(0)), samples128_0);
+ riceParamPart128 = drflac__valignrq_u32_1(vdupq_n_u32(0), riceParamPart128);
+ }
+ } else if (order <= 8) {
+ for (i = 0; i < 4; i += 1) {
+ prediction128 = vmulq_s32(coefficients128_4, samples128_4);
+ prediction128 = vmlaq_s32(prediction128, coefficients128_0, samples128_0);
+
+ /* Horizontal add and shift. */
+ prediction64 = drflac__vhaddq_s32(prediction128);
+ prediction64 = vshl_s32(prediction64, shift64);
+ prediction64 = vadd_s32(prediction64, vget_low_s32(vreinterpretq_s32_u32(riceParamPart128)));
+
+ samples128_4 = drflac__valignrq_s32_1(samples128_0, samples128_4);
+ samples128_0 = drflac__valignrq_s32_1(vcombine_s32(prediction64, vdup_n_s32(0)), samples128_0);
+ riceParamPart128 = drflac__valignrq_u32_1(vdupq_n_u32(0), riceParamPart128);
+ }
+ } else {
+ for (i = 0; i < 4; i += 1) {
+ prediction128 = vmulq_s32(coefficients128_8, samples128_8);
+ prediction128 = vmlaq_s32(prediction128, coefficients128_4, samples128_4);
+ prediction128 = vmlaq_s32(prediction128, coefficients128_0, samples128_0);
+
+ /* Horizontal add and shift. */
+ prediction64 = drflac__vhaddq_s32(prediction128);
+ prediction64 = vshl_s32(prediction64, shift64);
+ prediction64 = vadd_s32(prediction64, vget_low_s32(vreinterpretq_s32_u32(riceParamPart128)));
+
+ samples128_8 = drflac__valignrq_s32_1(samples128_4, samples128_8);
+ samples128_4 = drflac__valignrq_s32_1(samples128_0, samples128_4);
+ samples128_0 = drflac__valignrq_s32_1(vcombine_s32(prediction64, vdup_n_s32(0)), samples128_0);
+ riceParamPart128 = drflac__valignrq_u32_1(vdupq_n_u32(0), riceParamPart128);
+ }
+ }
+
+ /* We store samples in groups of 4. */
+ vst1q_s32(pDecodedSamples, samples128_0);
+ pDecodedSamples += 4;
+ }
+
+ /* Make sure we process the last few samples. */
+ i = (count & ~3);
+ while (i < (int)count) {
+ /* Rice extraction. */
+ if (!drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts[0], &riceParamParts[0])) {
+ return DRFLAC_FALSE;
+ }
+
+ /* Rice reconstruction. */
+ riceParamParts[0] &= riceParamMask;
+ riceParamParts[0] |= (zeroCountParts[0] << riceParam);
+ riceParamParts[0] = (riceParamParts[0] >> 1) ^ t[riceParamParts[0] & 0x01];
+
+ /* Sample reconstruction. */
+ pDecodedSamples[0] = riceParamParts[0] + drflac__calculate_prediction_32(order, shift, coefficients, pDecodedSamples);
+
+ i += 1;
+ pDecodedSamples += 1;
+ }
+
+ return DRFLAC_TRUE;
+}
+
+static drflac_bool32 drflac__decode_samples_with_residual__rice__neon_64(drflac_bs* bs, drflac_uint32 count, drflac_uint8 riceParam, drflac_uint32 order, drflac_int32 shift, const drflac_int32* coefficients, drflac_int32* pSamplesOut)
+{
+ int i;
+ drflac_uint32 riceParamMask;
+ drflac_int32* pDecodedSamples = pSamplesOut;
+ drflac_int32* pDecodedSamplesEnd = pSamplesOut + (count & ~3);
+ drflac_uint32 zeroCountParts[4];
+ drflac_uint32 riceParamParts[4];
+ int32x4_t coefficients128_0;
+ int32x4_t coefficients128_4;
+ int32x4_t coefficients128_8;
+ int32x4_t samples128_0;
+ int32x4_t samples128_4;
+ int32x4_t samples128_8;
+ uint32x4_t riceParamMask128;
+ int32x4_t riceParam128;
+ int64x1_t shift64;
+ uint32x4_t one128;
+ int64x2_t prediction128 = { 0 };
+ uint32x4_t zeroCountPart128;
+ uint32x4_t riceParamPart128;
+
+ const drflac_uint32 t[2] = {0x00000000, 0xFFFFFFFF};
+
+ riceParamMask = (drflac_uint32)~((~0UL) << riceParam);
+ riceParamMask128 = vdupq_n_u32(riceParamMask);
+
+ riceParam128 = vdupq_n_s32(riceParam);
+ shift64 = vdup_n_s64(-shift); /* Negate the shift because we'll be doing a variable shift using vshlq_s32(). */
+ one128 = vdupq_n_u32(1);
+
+ /*
+ Pre-loading the coefficients and prior samples is annoying because we need to ensure we don't try reading more than
+ what's available in the input buffers. It would be convenient to use a fall-through switch to do this, but this results
+ in strict aliasing warnings with GCC. To work around this I'm just doing something hacky. This feels a bit convoluted
+ so I think there's opportunity for this to be simplified.
+ */
+ {
+ int runningOrder = order;
+ drflac_int32 tempC[4] = {0, 0, 0, 0};
+ drflac_int32 tempS[4] = {0, 0, 0, 0};
+
+ /* 0 - 3. */
+ if (runningOrder >= 4) {
+ coefficients128_0 = vld1q_s32(coefficients + 0);
+ samples128_0 = vld1q_s32(pSamplesOut - 4);
+ runningOrder -= 4;
+ } else {
+ switch (runningOrder) {
+ case 3: tempC[2] = coefficients[2]; tempS[1] = pSamplesOut[-3]; /* fallthrough */
+ case 2: tempC[1] = coefficients[1]; tempS[2] = pSamplesOut[-2]; /* fallthrough */
+ case 1: tempC[0] = coefficients[0]; tempS[3] = pSamplesOut[-1]; /* fallthrough */
+ }
+
+ coefficients128_0 = vld1q_s32(tempC);
+ samples128_0 = vld1q_s32(tempS);
+ runningOrder = 0;
+ }
+
+ /* 4 - 7 */
+ if (runningOrder >= 4) {
+ coefficients128_4 = vld1q_s32(coefficients + 4);
+ samples128_4 = vld1q_s32(pSamplesOut - 8);
+ runningOrder -= 4;
+ } else {
+ switch (runningOrder) {
+ case 3: tempC[2] = coefficients[6]; tempS[1] = pSamplesOut[-7]; /* fallthrough */
+ case 2: tempC[1] = coefficients[5]; tempS[2] = pSamplesOut[-6]; /* fallthrough */
+ case 1: tempC[0] = coefficients[4]; tempS[3] = pSamplesOut[-5]; /* fallthrough */
+ }
+
+ coefficients128_4 = vld1q_s32(tempC);
+ samples128_4 = vld1q_s32(tempS);
+ runningOrder = 0;
+ }
+
+ /* 8 - 11 */
+ if (runningOrder == 4) {
+ coefficients128_8 = vld1q_s32(coefficients + 8);
+ samples128_8 = vld1q_s32(pSamplesOut - 12);
+ runningOrder -= 4;
+ } else {
+ switch (runningOrder) {
+ case 3: tempC[2] = coefficients[10]; tempS[1] = pSamplesOut[-11]; /* fallthrough */
+ case 2: tempC[1] = coefficients[ 9]; tempS[2] = pSamplesOut[-10]; /* fallthrough */
+ case 1: tempC[0] = coefficients[ 8]; tempS[3] = pSamplesOut[- 9]; /* fallthrough */
+ }
+
+ coefficients128_8 = vld1q_s32(tempC);
+ samples128_8 = vld1q_s32(tempS);
+ runningOrder = 0;
+ }
+
+ /* Coefficients need to be shuffled for our streaming algorithm below to work. Samples are already in the correct order from the loading routine above. */
+ coefficients128_0 = drflac__vrevq_s32(coefficients128_0);
+ coefficients128_4 = drflac__vrevq_s32(coefficients128_4);
+ coefficients128_8 = drflac__vrevq_s32(coefficients128_8);
+ }
+
+ /* For this version we are doing one sample at a time. */
+ while (pDecodedSamples < pDecodedSamplesEnd) {
+ if (!drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts[0], &riceParamParts[0]) ||
+ !drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts[1], &riceParamParts[1]) ||
+ !drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts[2], &riceParamParts[2]) ||
+ !drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts[3], &riceParamParts[3])) {
+ return DRFLAC_FALSE;
+ }
+
+ zeroCountPart128 = vld1q_u32(zeroCountParts);
+ riceParamPart128 = vld1q_u32(riceParamParts);
+
+ riceParamPart128 = vandq_u32(riceParamPart128, riceParamMask128);
+ riceParamPart128 = vorrq_u32(riceParamPart128, vshlq_u32(zeroCountPart128, riceParam128));
+ riceParamPart128 = veorq_u32(vshrq_n_u32(riceParamPart128, 1), vaddq_u32(drflac__vnotq_u32(vandq_u32(riceParamPart128, one128)), one128));
+
+ for (i = 0; i < 4; i += 1) {
+ int64x1_t prediction64;
+
+ prediction128 = veorq_s64(prediction128, prediction128); /* Reset to 0. */
+ switch (order)
+ {
+ case 12:
+ case 11: prediction128 = vaddq_s64(prediction128, vmull_s32(vget_low_s32(coefficients128_8), vget_low_s32(samples128_8)));
+ case 10:
+ case 9: prediction128 = vaddq_s64(prediction128, vmull_s32(vget_high_s32(coefficients128_8), vget_high_s32(samples128_8)));
+ case 8:
+ case 7: prediction128 = vaddq_s64(prediction128, vmull_s32(vget_low_s32(coefficients128_4), vget_low_s32(samples128_4)));
+ case 6:
+ case 5: prediction128 = vaddq_s64(prediction128, vmull_s32(vget_high_s32(coefficients128_4), vget_high_s32(samples128_4)));
+ case 4:
+ case 3: prediction128 = vaddq_s64(prediction128, vmull_s32(vget_low_s32(coefficients128_0), vget_low_s32(samples128_0)));
+ case 2:
+ case 1: prediction128 = vaddq_s64(prediction128, vmull_s32(vget_high_s32(coefficients128_0), vget_high_s32(samples128_0)));
+ }
+
+ /* Horizontal add and shift. */
+ prediction64 = drflac__vhaddq_s64(prediction128);
+ prediction64 = vshl_s64(prediction64, shift64);
+ prediction64 = vadd_s64(prediction64, vdup_n_s64(vgetq_lane_u32(riceParamPart128, 0)));
+
+ /* Our value should be sitting in prediction64[0]. We need to combine this with our SSE samples. */
+ samples128_8 = drflac__valignrq_s32_1(samples128_4, samples128_8);
+ samples128_4 = drflac__valignrq_s32_1(samples128_0, samples128_4);
+ samples128_0 = drflac__valignrq_s32_1(vcombine_s32(vreinterpret_s32_s64(prediction64), vdup_n_s32(0)), samples128_0);
+
+ /* Slide our rice parameter down so that the value in position 0 contains the next one to process. */
+ riceParamPart128 = drflac__valignrq_u32_1(vdupq_n_u32(0), riceParamPart128);
+ }
+
+ /* We store samples in groups of 4. */
+ vst1q_s32(pDecodedSamples, samples128_0);
+ pDecodedSamples += 4;
+ }
+
+ /* Make sure we process the last few samples. */
+ i = (count & ~3);
+ while (i < (int)count) {
+ /* Rice extraction. */
+ if (!drflac__read_rice_parts_x1(bs, riceParam, &zeroCountParts[0], &riceParamParts[0])) {
+ return DRFLAC_FALSE;
+ }
+
+ /* Rice reconstruction. */
+ riceParamParts[0] &= riceParamMask;
+ riceParamParts[0] |= (zeroCountParts[0] << riceParam);
+ riceParamParts[0] = (riceParamParts[0] >> 1) ^ t[riceParamParts[0] & 0x01];
+
+ /* Sample reconstruction. */
+ pDecodedSamples[0] = riceParamParts[0] + drflac__calculate_prediction_64(order, shift, coefficients, pDecodedSamples);
+
+ i += 1;
+ pDecodedSamples += 1;
+ }
+
+ return DRFLAC_TRUE;
+}
+
+static drflac_bool32 drflac__decode_samples_with_residual__rice__neon(drflac_bs* bs, drflac_uint32 bitsPerSample, drflac_uint32 count, drflac_uint8 riceParam, drflac_uint32 lpcOrder, drflac_int32 lpcShift, drflac_uint32 lpcPrecision, const drflac_int32* coefficients, drflac_int32* pSamplesOut)
+{
+ DRFLAC_ASSERT(bs != NULL);
+ DRFLAC_ASSERT(pSamplesOut != NULL);
+
+ /* In my testing the order is rarely > 12, so in this case I'm going to simplify the NEON implementation by only handling order <= 12. */
+ if (lpcOrder > 0 && lpcOrder <= 12) {
+ if (drflac__use_64_bit_prediction(bitsPerSample, lpcOrder, lpcPrecision)) {
+ return drflac__decode_samples_with_residual__rice__neon_64(bs, count, riceParam, lpcOrder, lpcShift, coefficients, pSamplesOut);
+ } else {
+ return drflac__decode_samples_with_residual__rice__neon_32(bs, count, riceParam, lpcOrder, lpcShift, coefficients, pSamplesOut);
+ }
+ } else {
+ return drflac__decode_samples_with_residual__rice__scalar(bs, bitsPerSample, count, riceParam, lpcOrder, lpcShift, lpcPrecision, coefficients, pSamplesOut);
+ }
+}
+#endif
+
+static drflac_bool32 drflac__decode_samples_with_residual__rice(drflac_bs* bs, drflac_uint32 bitsPerSample, drflac_uint32 count, drflac_uint8 riceParam, drflac_uint32 lpcOrder, drflac_int32 lpcShift, drflac_uint32 lpcPrecision, const drflac_int32* coefficients, drflac_int32* pSamplesOut)
+{
+#if defined(DRFLAC_SUPPORT_SSE41)
+ if (drflac__gIsSSE41Supported) {
+ return drflac__decode_samples_with_residual__rice__sse41(bs, bitsPerSample, count, riceParam, lpcOrder, lpcShift, lpcPrecision, coefficients, pSamplesOut);
+ } else
+#elif defined(DRFLAC_SUPPORT_NEON)
+ if (drflac__gIsNEONSupported) {
+ return drflac__decode_samples_with_residual__rice__neon(bs, bitsPerSample, count, riceParam, lpcOrder, lpcShift, lpcPrecision, coefficients, pSamplesOut);
+ } else
+#endif
+ {
+ /* Scalar fallback. */
+ #if 0
+ return drflac__decode_samples_with_residual__rice__reference(bs, bitsPerSample, count, riceParam, lpcOrder, lpcShift, lpcPrecision, coefficients, pSamplesOut);
+ #else
+ return drflac__decode_samples_with_residual__rice__scalar(bs, bitsPerSample, count, riceParam, lpcOrder, lpcShift, lpcPrecision, coefficients, pSamplesOut);
+ #endif
+ }
+}
+
+/* Reads and seeks past a string of residual values as Rice codes. The decoder should be sitting on the first bit of the Rice codes. */
+static drflac_bool32 drflac__read_and_seek_residual__rice(drflac_bs* bs, drflac_uint32 count, drflac_uint8 riceParam)
+{
+ drflac_uint32 i;
+
+ DRFLAC_ASSERT(bs != NULL);
+
+ for (i = 0; i < count; ++i) {
+ if (!drflac__seek_rice_parts(bs, riceParam)) {
+ return DRFLAC_FALSE;
+ }
+ }
+
+ return DRFLAC_TRUE;
+}
+
+#if defined(__clang__)
+__attribute__((no_sanitize("signed-integer-overflow")))
+#endif
+static drflac_bool32 drflac__decode_samples_with_residual__unencoded(drflac_bs* bs, drflac_uint32 bitsPerSample, drflac_uint32 count, drflac_uint8 unencodedBitsPerSample, drflac_uint32 lpcOrder, drflac_int32 lpcShift, drflac_uint32 lpcPrecision, const drflac_int32* coefficients, drflac_int32* pSamplesOut)
+{
+ drflac_uint32 i;
+
+ DRFLAC_ASSERT(bs != NULL);
+ DRFLAC_ASSERT(unencodedBitsPerSample <= 31); /* <-- unencodedBitsPerSample is a 5 bit number, so cannot exceed 31. */
+ DRFLAC_ASSERT(pSamplesOut != NULL);
+
+ for (i = 0; i < count; ++i) {
+ if (unencodedBitsPerSample > 0) {
+ if (!drflac__read_int32(bs, unencodedBitsPerSample, pSamplesOut + i)) {
+ return DRFLAC_FALSE;
+ }
+ } else {
+ pSamplesOut[i] = 0;
+ }
+
+ if (drflac__use_64_bit_prediction(bitsPerSample, lpcOrder, lpcPrecision)) {
+ pSamplesOut[i] += drflac__calculate_prediction_64(lpcOrder, lpcShift, coefficients, pSamplesOut + i);
+ } else {
+ pSamplesOut[i] += drflac__calculate_prediction_32(lpcOrder, lpcShift, coefficients, pSamplesOut + i);
+ }
+ }
+
+ return DRFLAC_TRUE;
+}
+
+
+/*
+Reads and decodes the residual for the sub-frame the decoder is currently sitting on. This function should be called
+when the decoder is sitting at the very start of the RESIDUAL block. The first residuals will be ignored. The
+ and parameters are used to determine how many residual values need to be decoded.
+*/
+static drflac_bool32 drflac__decode_samples_with_residual(drflac_bs* bs, drflac_uint32 bitsPerSample, drflac_uint32 blockSize, drflac_uint32 lpcOrder, drflac_int32 lpcShift, drflac_uint32 lpcPrecision, const drflac_int32* coefficients, drflac_int32* pDecodedSamples)
+{
+ drflac_uint8 residualMethod;
+ drflac_uint8 partitionOrder;
+ drflac_uint32 samplesInPartition;
+ drflac_uint32 partitionsRemaining;
+
+ DRFLAC_ASSERT(bs != NULL);
+ DRFLAC_ASSERT(blockSize != 0);
+ DRFLAC_ASSERT(pDecodedSamples != NULL); /* <-- Should we allow NULL, in which case we just seek past the residual rather than do a full decode? */
+
+ if (!drflac__read_uint8(bs, 2, &residualMethod)) {
+ return DRFLAC_FALSE;
+ }
+
+ if (residualMethod != DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE && residualMethod != DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE2) {
+ return DRFLAC_FALSE; /* Unknown or unsupported residual coding method. */
+ }
+
+ /* Ignore the first values. */
+ pDecodedSamples += lpcOrder;
+
+ if (!drflac__read_uint8(bs, 4, &partitionOrder)) {
+ return DRFLAC_FALSE;
+ }
+
+ /*
+ From the FLAC spec:
+ The Rice partition order in a Rice-coded residual section must be less than or equal to 8.
+ */
+ if (partitionOrder > 8) {
+ return DRFLAC_FALSE;
+ }
+
+ /* Validation check. */
+ if ((blockSize / (1 << partitionOrder)) < lpcOrder) {
+ return DRFLAC_FALSE;
+ }
+
+ samplesInPartition = (blockSize / (1 << partitionOrder)) - lpcOrder;
+ partitionsRemaining = (1 << partitionOrder);
+ for (;;) {
+ drflac_uint8 riceParam = 0;
+ if (residualMethod == DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE) {
+ if (!drflac__read_uint8(bs, 4, &riceParam)) {
+ return DRFLAC_FALSE;
+ }
+ if (riceParam == 15) {
+ riceParam = 0xFF;
+ }
+ } else if (residualMethod == DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE2) {
+ if (!drflac__read_uint8(bs, 5, &riceParam)) {
+ return DRFLAC_FALSE;
+ }
+ if (riceParam == 31) {
+ riceParam = 0xFF;
+ }
+ }
+
+ if (riceParam != 0xFF) {
+ if (!drflac__decode_samples_with_residual__rice(bs, bitsPerSample, samplesInPartition, riceParam, lpcOrder, lpcShift, lpcPrecision, coefficients, pDecodedSamples)) {
+ return DRFLAC_FALSE;
+ }
+ } else {
+ drflac_uint8 unencodedBitsPerSample = 0;
+ if (!drflac__read_uint8(bs, 5, &unencodedBitsPerSample)) {
+ return DRFLAC_FALSE;
+ }
+
+ if (!drflac__decode_samples_with_residual__unencoded(bs, bitsPerSample, samplesInPartition, unencodedBitsPerSample, lpcOrder, lpcShift, lpcPrecision, coefficients, pDecodedSamples)) {
+ return DRFLAC_FALSE;
+ }
+ }
+
+ pDecodedSamples += samplesInPartition;
+
+ if (partitionsRemaining == 1) {
+ break;
+ }
+
+ partitionsRemaining -= 1;
+
+ if (partitionOrder != 0) {
+ samplesInPartition = blockSize / (1 << partitionOrder);
+ }
+ }
+
+ return DRFLAC_TRUE;
+}
+
+/*
+Reads and seeks past the residual for the sub-frame the decoder is currently sitting on. This function should be called
+when the decoder is sitting at the very start of the RESIDUAL block. The first residuals will be set to 0. The
+ and parameters are used to determine how many residual values need to be decoded.
+*/
+static drflac_bool32 drflac__read_and_seek_residual(drflac_bs* bs, drflac_uint32 blockSize, drflac_uint32 order)
+{
+ drflac_uint8 residualMethod;
+ drflac_uint8 partitionOrder;
+ drflac_uint32 samplesInPartition;
+ drflac_uint32 partitionsRemaining;
+
+ DRFLAC_ASSERT(bs != NULL);
+ DRFLAC_ASSERT(blockSize != 0);
+
+ if (!drflac__read_uint8(bs, 2, &residualMethod)) {
+ return DRFLAC_FALSE;
+ }
+
+ if (residualMethod != DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE && residualMethod != DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE2) {
+ return DRFLAC_FALSE; /* Unknown or unsupported residual coding method. */
+ }
+
+ if (!drflac__read_uint8(bs, 4, &partitionOrder)) {
+ return DRFLAC_FALSE;
+ }
+
+ /*
+ From the FLAC spec:
+ The Rice partition order in a Rice-coded residual section must be less than or equal to 8.
+ */
+ if (partitionOrder > 8) {
+ return DRFLAC_FALSE;
+ }
+
+ /* Validation check. */
+ if ((blockSize / (1 << partitionOrder)) <= order) {
+ return DRFLAC_FALSE;
+ }
+
+ samplesInPartition = (blockSize / (1 << partitionOrder)) - order;
+ partitionsRemaining = (1 << partitionOrder);
+ for (;;)
+ {
+ drflac_uint8 riceParam = 0;
+ if (residualMethod == DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE) {
+ if (!drflac__read_uint8(bs, 4, &riceParam)) {
+ return DRFLAC_FALSE;
+ }
+ if (riceParam == 15) {
+ riceParam = 0xFF;
+ }
+ } else if (residualMethod == DRFLAC_RESIDUAL_CODING_METHOD_PARTITIONED_RICE2) {
+ if (!drflac__read_uint8(bs, 5, &riceParam)) {
+ return DRFLAC_FALSE;
+ }
+ if (riceParam == 31) {
+ riceParam = 0xFF;
+ }
+ }
+
+ if (riceParam != 0xFF) {
+ if (!drflac__read_and_seek_residual__rice(bs, samplesInPartition, riceParam)) {
+ return DRFLAC_FALSE;
+ }
+ } else {
+ drflac_uint8 unencodedBitsPerSample = 0;
+ if (!drflac__read_uint8(bs, 5, &unencodedBitsPerSample)) {
+ return DRFLAC_FALSE;
+ }
+
+ if (!drflac__seek_bits(bs, unencodedBitsPerSample * samplesInPartition)) {
+ return DRFLAC_FALSE;
+ }
+ }
+
+
+ if (partitionsRemaining == 1) {
+ break;
+ }
+
+ partitionsRemaining -= 1;
+ samplesInPartition = blockSize / (1 << partitionOrder);
+ }
+
+ return DRFLAC_TRUE;
+}
+
+
+static drflac_bool32 drflac__decode_samples__constant(drflac_bs* bs, drflac_uint32 blockSize, drflac_uint32 subframeBitsPerSample, drflac_int32* pDecodedSamples)
+{
+ drflac_uint32 i;
+
+ /* Only a single sample needs to be decoded here. */
+ drflac_int32 sample;
+ if (!drflac__read_int32(bs, subframeBitsPerSample, &sample)) {
+ return DRFLAC_FALSE;
+ }
+
+ /*
+ We don't really need to expand this, but it does simplify the process of reading samples. If this becomes a performance issue (unlikely)
+ we'll want to look at a more efficient way.
+ */
+ for (i = 0; i < blockSize; ++i) {
+ pDecodedSamples[i] = sample;
+ }
+
+ return DRFLAC_TRUE;
+}
+
+static drflac_bool32 drflac__decode_samples__verbatim(drflac_bs* bs, drflac_uint32 blockSize, drflac_uint32 subframeBitsPerSample, drflac_int32* pDecodedSamples)
+{
+ drflac_uint32 i;
+
+ for (i = 0; i < blockSize; ++i) {
+ drflac_int32 sample;
+ if (!drflac__read_int32(bs, subframeBitsPerSample, &sample)) {
+ return DRFLAC_FALSE;
+ }
+
+ pDecodedSamples[i] = sample;
+ }
+
+ return DRFLAC_TRUE;
+}
+
+static drflac_bool32 drflac__decode_samples__fixed(drflac_bs* bs, drflac_uint32 blockSize, drflac_uint32 subframeBitsPerSample, drflac_uint8 lpcOrder, drflac_int32* pDecodedSamples)
+{
+ drflac_uint32 i;
+
+ static drflac_int32 lpcCoefficientsTable[5][4] = {
+ {0, 0, 0, 0},
+ {1, 0, 0, 0},
+ {2, -1, 0, 0},
+ {3, -3, 1, 0},
+ {4, -6, 4, -1}
+ };
+
+ /* Warm up samples and coefficients. */
+ for (i = 0; i < lpcOrder; ++i) {
+ drflac_int32 sample;
+ if (!drflac__read_int32(bs, subframeBitsPerSample, &sample)) {
+ return DRFLAC_FALSE;
+ }
+
+ pDecodedSamples[i] = sample;
+ }
+
+ if (!drflac__decode_samples_with_residual(bs, subframeBitsPerSample, blockSize, lpcOrder, 0, 4, lpcCoefficientsTable[lpcOrder], pDecodedSamples)) {
+ return DRFLAC_FALSE;
+ }
+
+ return DRFLAC_TRUE;
+}
+
+static drflac_bool32 drflac__decode_samples__lpc(drflac_bs* bs, drflac_uint32 blockSize, drflac_uint32 bitsPerSample, drflac_uint8 lpcOrder, drflac_int32* pDecodedSamples)
+{
+ drflac_uint8 i;
+ drflac_uint8 lpcPrecision;
+ drflac_int8 lpcShift;
+ drflac_int32 coefficients[32];
+
+ /* Warm up samples. */
+ for (i = 0; i < lpcOrder; ++i) {
+ drflac_int32 sample;
+ if (!drflac__read_int32(bs, bitsPerSample, &sample)) {
+ return DRFLAC_FALSE;
+ }
+
+ pDecodedSamples[i] = sample;
+ }
+
+ if (!drflac__read_uint8(bs, 4, &lpcPrecision)) {
+ return DRFLAC_FALSE;
+ }
+ if (lpcPrecision == 15) {
+ return DRFLAC_FALSE; /* Invalid. */
+ }
+ lpcPrecision += 1;
+
+ if (!drflac__read_int8(bs, 5, &lpcShift)) {
+ return DRFLAC_FALSE;
+ }
+
+ /*
+ From the FLAC specification:
+
+ Quantized linear predictor coefficient shift needed in bits (NOTE: this number is signed two's-complement)
+
+ Emphasis on the "signed two's-complement". In practice there does not seem to be any encoders nor decoders supporting negative shifts. For now dr_flac is
+ not going to support negative shifts as I don't have any reference files. However, when a reference file comes through I will consider adding support.
+ */
+ if (lpcShift < 0) {
+ return DRFLAC_FALSE;
+ }
+
+ DRFLAC_ZERO_MEMORY(coefficients, sizeof(coefficients));
+ for (i = 0; i < lpcOrder; ++i) {
+ if (!drflac__read_int32(bs, lpcPrecision, coefficients + i)) {
+ return DRFLAC_FALSE;
+ }
+ }
+
+ if (!drflac__decode_samples_with_residual(bs, bitsPerSample, blockSize, lpcOrder, lpcShift, lpcPrecision, coefficients, pDecodedSamples)) {
+ return DRFLAC_FALSE;
+ }
+
+ return DRFLAC_TRUE;
+}
+
+
+static drflac_bool32 drflac__read_next_flac_frame_header(drflac_bs* bs, drflac_uint8 streaminfoBitsPerSample, drflac_frame_header* header)
+{
+ const drflac_uint32 sampleRateTable[12] = {0, 88200, 176400, 192000, 8000, 16000, 22050, 24000, 32000, 44100, 48000, 96000};
+ const drflac_uint8 bitsPerSampleTable[8] = {0, 8, 12, (drflac_uint8)-1, 16, 20, 24, (drflac_uint8)-1}; /* -1 = reserved. */
+
+ DRFLAC_ASSERT(bs != NULL);
+ DRFLAC_ASSERT(header != NULL);
+
+ /* Keep looping until we find a valid sync code. */
+ for (;;) {
+ drflac_uint8 crc8 = 0xCE; /* 0xCE = drflac_crc8(0, 0x3FFE, 14); */
+ drflac_uint8 reserved = 0;
+ drflac_uint8 blockingStrategy = 0;
+ drflac_uint8 blockSize = 0;
+ drflac_uint8 sampleRate = 0;
+ drflac_uint8 channelAssignment = 0;
+ drflac_uint8 bitsPerSample = 0;
+ drflac_bool32 isVariableBlockSize;
+
+ if (!drflac__find_and_seek_to_next_sync_code(bs)) {
+ return DRFLAC_FALSE;
+ }
+
+ if (!drflac__read_uint8(bs, 1, &reserved)) {
+ return DRFLAC_FALSE;
+ }
+ if (reserved == 1) {
+ continue;
+ }
+ crc8 = drflac_crc8(crc8, reserved, 1);
+
+ if (!drflac__read_uint8(bs, 1, &blockingStrategy)) {
+ return DRFLAC_FALSE;
+ }
+ crc8 = drflac_crc8(crc8, blockingStrategy, 1);
+
+ if (!drflac__read_uint8(bs, 4, &blockSize)) {
+ return DRFLAC_FALSE;
+ }
+ if (blockSize == 0) {
+ continue;
+ }
+ crc8 = drflac_crc8(crc8, blockSize, 4);
+
+ if (!drflac__read_uint8(bs, 4, &sampleRate)) {
+ return DRFLAC_FALSE;
+ }
+ crc8 = drflac_crc8(crc8, sampleRate, 4);
+
+ if (!drflac__read_uint8(bs, 4, &channelAssignment)) {
+ return DRFLAC_FALSE;
+ }
+ if (channelAssignment > 10) {
+ continue;
+ }
+ crc8 = drflac_crc8(crc8, channelAssignment, 4);
+
+ if (!drflac__read_uint8(bs, 3, &bitsPerSample)) {
+ return DRFLAC_FALSE;
+ }
+ if (bitsPerSample == 3 || bitsPerSample == 7) {
+ continue;
+ }
+ crc8 = drflac_crc8(crc8, bitsPerSample, 3);
+
+
+ if (!drflac__read_uint8(bs, 1, &reserved)) {
+ return DRFLAC_FALSE;
+ }
+ if (reserved == 1) {
+ continue;
+ }
+ crc8 = drflac_crc8(crc8, reserved, 1);
+
+
+ isVariableBlockSize = blockingStrategy == 1;
+ if (isVariableBlockSize) {
+ drflac_uint64 pcmFrameNumber;
+ drflac_result result = drflac__read_utf8_coded_number(bs, &pcmFrameNumber, &crc8);
+ if (result != DRFLAC_SUCCESS) {
+ if (result == DRFLAC_AT_END) {
+ return DRFLAC_FALSE;
+ } else {
+ continue;
+ }
+ }
+ header->flacFrameNumber = 0;
+ header->pcmFrameNumber = pcmFrameNumber;
+ } else {
+ drflac_uint64 flacFrameNumber = 0;
+ drflac_result result = drflac__read_utf8_coded_number(bs, &flacFrameNumber, &crc8);
+ if (result != DRFLAC_SUCCESS) {
+ if (result == DRFLAC_AT_END) {
+ return DRFLAC_FALSE;
+ } else {
+ continue;
+ }
+ }
+ header->flacFrameNumber = (drflac_uint32)flacFrameNumber; /* <-- Safe cast. */
+ header->pcmFrameNumber = 0;
+ }
+
+
+ DRFLAC_ASSERT(blockSize > 0);
+ if (blockSize == 1) {
+ header->blockSizeInPCMFrames = 192;
+ } else if (blockSize <= 5) {
+ DRFLAC_ASSERT(blockSize >= 2);
+ header->blockSizeInPCMFrames = 576 * (1 << (blockSize - 2));
+ } else if (blockSize == 6) {
+ if (!drflac__read_uint16(bs, 8, &header->blockSizeInPCMFrames)) {
+ return DRFLAC_FALSE;
+ }
+ crc8 = drflac_crc8(crc8, header->blockSizeInPCMFrames, 8);
+ header->blockSizeInPCMFrames += 1;
+ } else if (blockSize == 7) {
+ if (!drflac__read_uint16(bs, 16, &header->blockSizeInPCMFrames)) {
+ return DRFLAC_FALSE;
+ }
+ crc8 = drflac_crc8(crc8, header->blockSizeInPCMFrames, 16);
+ if (header->blockSizeInPCMFrames == 0xFFFF) {
+ return DRFLAC_FALSE; /* Frame is too big. This is the size of the frame minus 1. The STREAMINFO block defines the max block size which is 16-bits. Adding one will make it 17 bits and therefore too big. */
+ }
+ header->blockSizeInPCMFrames += 1;
+ } else {
+ DRFLAC_ASSERT(blockSize >= 8);
+ header->blockSizeInPCMFrames = 256 * (1 << (blockSize - 8));
+ }
+
+
+ if (sampleRate <= 11) {
+ header->sampleRate = sampleRateTable[sampleRate];
+ } else if (sampleRate == 12) {
+ if (!drflac__read_uint32(bs, 8, &header->sampleRate)) {
+ return DRFLAC_FALSE;
+ }
+ crc8 = drflac_crc8(crc8, header->sampleRate, 8);
+ header->sampleRate *= 1000;
+ } else if (sampleRate == 13) {
+ if (!drflac__read_uint32(bs, 16, &header->sampleRate)) {
+ return DRFLAC_FALSE;
+ }
+ crc8 = drflac_crc8(crc8, header->sampleRate, 16);
+ } else if (sampleRate == 14) {
+ if (!drflac__read_uint32(bs, 16, &header->sampleRate)) {
+ return DRFLAC_FALSE;
+ }
+ crc8 = drflac_crc8(crc8, header->sampleRate, 16);
+ header->sampleRate *= 10;
+ } else {
+ continue; /* Invalid. Assume an invalid block. */
+ }
+
+
+ header->channelAssignment = channelAssignment;
+
+ header->bitsPerSample = bitsPerSampleTable[bitsPerSample];
+ if (header->bitsPerSample == 0) {
+ header->bitsPerSample = streaminfoBitsPerSample;
+ }
+
+ if (header->bitsPerSample != streaminfoBitsPerSample) {
+ /* If this subframe has a different bitsPerSample then streaminfo or the first frame, reject it */
+ return DRFLAC_FALSE;
+ }
+
+ if (!drflac__read_uint8(bs, 8, &header->crc8)) {
+ return DRFLAC_FALSE;
+ }
+
+#ifndef DR_FLAC_NO_CRC
+ if (header->crc8 != crc8) {
+ continue; /* CRC mismatch. Loop back to the top and find the next sync code. */
+ }
+#endif
+ return DRFLAC_TRUE;
+ }
+}
+
+static drflac_bool32 drflac__read_subframe_header(drflac_bs* bs, drflac_subframe* pSubframe)
+{
+ drflac_uint8 header;
+ int type;
+
+ if (!drflac__read_uint8(bs, 8, &header)) {
+ return DRFLAC_FALSE;
+ }
+
+ /* First bit should always be 0. */
+ if ((header & 0x80) != 0) {
+ return DRFLAC_FALSE;
+ }
+
+ type = (header & 0x7E) >> 1;
+ if (type == 0) {
+ pSubframe->subframeType = DRFLAC_SUBFRAME_CONSTANT;
+ } else if (type == 1) {
+ pSubframe->subframeType = DRFLAC_SUBFRAME_VERBATIM;
+ } else {
+ if ((type & 0x20) != 0) {
+ pSubframe->subframeType = DRFLAC_SUBFRAME_LPC;
+ pSubframe->lpcOrder = (drflac_uint8)(type & 0x1F) + 1;
+ } else if ((type & 0x08) != 0) {
+ pSubframe->subframeType = DRFLAC_SUBFRAME_FIXED;
+ pSubframe->lpcOrder = (drflac_uint8)(type & 0x07);
+ if (pSubframe->lpcOrder > 4) {
+ pSubframe->subframeType = DRFLAC_SUBFRAME_RESERVED;
+ pSubframe->lpcOrder = 0;
+ }
+ } else {
+ pSubframe->subframeType = DRFLAC_SUBFRAME_RESERVED;
+ }
+ }
+
+ if (pSubframe->subframeType == DRFLAC_SUBFRAME_RESERVED) {
+ return DRFLAC_FALSE;
+ }
+
+ /* Wasted bits per sample. */
+ pSubframe->wastedBitsPerSample = 0;
+ if ((header & 0x01) == 1) {
+ unsigned int wastedBitsPerSample;
+ if (!drflac__seek_past_next_set_bit(bs, &wastedBitsPerSample)) {
+ return DRFLAC_FALSE;
+ }
+ pSubframe->wastedBitsPerSample = (drflac_uint8)wastedBitsPerSample + 1;
+ }
+
+ return DRFLAC_TRUE;
+}
+
+static drflac_bool32 drflac__decode_subframe(drflac_bs* bs, drflac_frame* frame, int subframeIndex, drflac_int32* pDecodedSamplesOut)
+{
+ drflac_subframe* pSubframe;
+ drflac_uint32 subframeBitsPerSample;
+
+ DRFLAC_ASSERT(bs != NULL);
+ DRFLAC_ASSERT(frame != NULL);
+
+ pSubframe = frame->subframes + subframeIndex;
+ if (!drflac__read_subframe_header(bs, pSubframe)) {
+ return DRFLAC_FALSE;
+ }
+
+ /* Side channels require an extra bit per sample. Took a while to figure that one out... */
+ subframeBitsPerSample = frame->header.bitsPerSample;
+ if ((frame->header.channelAssignment == DRFLAC_CHANNEL_ASSIGNMENT_LEFT_SIDE || frame->header.channelAssignment == DRFLAC_CHANNEL_ASSIGNMENT_MID_SIDE) && subframeIndex == 1) {
+ subframeBitsPerSample += 1;
+ } else if (frame->header.channelAssignment == DRFLAC_CHANNEL_ASSIGNMENT_RIGHT_SIDE && subframeIndex == 0) {
+ subframeBitsPerSample += 1;
+ }
+
+ if (subframeBitsPerSample > 32) {
+ /* libFLAC and ffmpeg reject 33-bit subframes as well */
+ return DRFLAC_FALSE;
+ }
+
+ /* Need to handle wasted bits per sample. */
+ if (pSubframe->wastedBitsPerSample >= subframeBitsPerSample) {
+ return DRFLAC_FALSE;
+ }
+ subframeBitsPerSample -= pSubframe->wastedBitsPerSample;
+
+ pSubframe->pSamplesS32 = pDecodedSamplesOut;
+
+ switch (pSubframe->subframeType)
+ {
+ case DRFLAC_SUBFRAME_CONSTANT:
+ {
+ drflac__decode_samples__constant(bs, frame->header.blockSizeInPCMFrames, subframeBitsPerSample, pSubframe->pSamplesS32);
+ } break;
+
+ case DRFLAC_SUBFRAME_VERBATIM:
+ {
+ drflac__decode_samples__verbatim(bs, frame->header.blockSizeInPCMFrames, subframeBitsPerSample, pSubframe->pSamplesS32);
+ } break;
+
+ case DRFLAC_SUBFRAME_FIXED:
+ {
+ drflac__decode_samples__fixed(bs, frame->header.blockSizeInPCMFrames, subframeBitsPerSample, pSubframe->lpcOrder, pSubframe->pSamplesS32);
+ } break;
+
+ case DRFLAC_SUBFRAME_LPC:
+ {
+ drflac__decode_samples__lpc(bs, frame->header.blockSizeInPCMFrames, subframeBitsPerSample, pSubframe->lpcOrder, pSubframe->pSamplesS32);
+ } break;
+
+ default: return DRFLAC_FALSE;
+ }
+
+ return DRFLAC_TRUE;
+}
+
+static drflac_bool32 drflac__seek_subframe(drflac_bs* bs, drflac_frame* frame, int subframeIndex)
+{
+ drflac_subframe* pSubframe;
+ drflac_uint32 subframeBitsPerSample;
+
+ DRFLAC_ASSERT(bs != NULL);
+ DRFLAC_ASSERT(frame != NULL);
+
+ pSubframe = frame->subframes + subframeIndex;
+ if (!drflac__read_subframe_header(bs, pSubframe)) {
+ return DRFLAC_FALSE;
+ }
+
+ /* Side channels require an extra bit per sample. Took a while to figure that one out... */
+ subframeBitsPerSample = frame->header.bitsPerSample;
+ if ((frame->header.channelAssignment == DRFLAC_CHANNEL_ASSIGNMENT_LEFT_SIDE || frame->header.channelAssignment == DRFLAC_CHANNEL_ASSIGNMENT_MID_SIDE) && subframeIndex == 1) {
+ subframeBitsPerSample += 1;
+ } else if (frame->header.channelAssignment == DRFLAC_CHANNEL_ASSIGNMENT_RIGHT_SIDE && subframeIndex == 0) {
+ subframeBitsPerSample += 1;
+ }
+
+ /* Need to handle wasted bits per sample. */
+ if (pSubframe->wastedBitsPerSample >= subframeBitsPerSample) {
+ return DRFLAC_FALSE;
+ }
+ subframeBitsPerSample -= pSubframe->wastedBitsPerSample;
+
+ pSubframe->pSamplesS32 = NULL;
+
+ switch (pSubframe->subframeType)
+ {
+ case DRFLAC_SUBFRAME_CONSTANT:
+ {
+ if (!drflac__seek_bits(bs, subframeBitsPerSample)) {
+ return DRFLAC_FALSE;
+ }
+ } break;
+
+ case DRFLAC_SUBFRAME_VERBATIM:
+ {
+ unsigned int bitsToSeek = frame->header.blockSizeInPCMFrames * subframeBitsPerSample;
+ if (!drflac__seek_bits(bs, bitsToSeek)) {
+ return DRFLAC_FALSE;
+ }
+ } break;
+
+ case DRFLAC_SUBFRAME_FIXED:
+ {
+ unsigned int bitsToSeek = pSubframe->lpcOrder * subframeBitsPerSample;
+ if (!drflac__seek_bits(bs, bitsToSeek)) {
+ return DRFLAC_FALSE;
+ }
+
+ if (!drflac__read_and_seek_residual(bs, frame->header.blockSizeInPCMFrames, pSubframe->lpcOrder)) {
+ return DRFLAC_FALSE;
+ }
+ } break;
+
+ case DRFLAC_SUBFRAME_LPC:
+ {
+ drflac_uint8 lpcPrecision;
+
+ unsigned int bitsToSeek = pSubframe->lpcOrder * subframeBitsPerSample;
+ if (!drflac__seek_bits(bs, bitsToSeek)) {
+ return DRFLAC_FALSE;
+ }
+
+ if (!drflac__read_uint8(bs, 4, &lpcPrecision)) {
+ return DRFLAC_FALSE;
+ }
+ if (lpcPrecision == 15) {
+ return DRFLAC_FALSE; /* Invalid. */
+ }
+ lpcPrecision += 1;
+
+
+ bitsToSeek = (pSubframe->lpcOrder * lpcPrecision) + 5; /* +5 for shift. */
+ if (!drflac__seek_bits(bs, bitsToSeek)) {
+ return DRFLAC_FALSE;
+ }
+
+ if (!drflac__read_and_seek_residual(bs, frame->header.blockSizeInPCMFrames, pSubframe->lpcOrder)) {
+ return DRFLAC_FALSE;
+ }
+ } break;
+
+ default: return DRFLAC_FALSE;
+ }
+
+ return DRFLAC_TRUE;
+}
+
+
+static DRFLAC_INLINE drflac_uint8 drflac__get_channel_count_from_channel_assignment(drflac_int8 channelAssignment)
+{
+ drflac_uint8 lookup[] = {1, 2, 3, 4, 5, 6, 7, 8, 2, 2, 2};
+
+ DRFLAC_ASSERT(channelAssignment <= 10);
+ return lookup[channelAssignment];
+}
+
+static drflac_result drflac__decode_flac_frame(drflac* pFlac)
+{
+ int channelCount;
+ int i;
+ drflac_uint8 paddingSizeInBits;
+ drflac_uint16 desiredCRC16;
+#ifndef DR_FLAC_NO_CRC
+ drflac_uint16 actualCRC16;
+#endif
+
+ /* This function should be called while the stream is sitting on the first byte after the frame header. */
+ DRFLAC_ZERO_MEMORY(pFlac->currentFLACFrame.subframes, sizeof(pFlac->currentFLACFrame.subframes));
+
+ /* The frame block size must never be larger than the maximum block size defined by the FLAC stream. */
+ if (pFlac->currentFLACFrame.header.blockSizeInPCMFrames > pFlac->maxBlockSizeInPCMFrames) {
+ return DRFLAC_ERROR;
+ }
+
+ /* The number of channels in the frame must match the channel count from the STREAMINFO block. */
+ channelCount = drflac__get_channel_count_from_channel_assignment(pFlac->currentFLACFrame.header.channelAssignment);
+ if (channelCount != (int)pFlac->channels) {
+ return DRFLAC_ERROR;
+ }
+
+ for (i = 0; i < channelCount; ++i) {
+ if (!drflac__decode_subframe(&pFlac->bs, &pFlac->currentFLACFrame, i, pFlac->pDecodedSamples + (pFlac->currentFLACFrame.header.blockSizeInPCMFrames * i))) {
+ return DRFLAC_ERROR;
+ }
+ }
+
+ paddingSizeInBits = (drflac_uint8)(DRFLAC_CACHE_L1_BITS_REMAINING(&pFlac->bs) & 7);
+ if (paddingSizeInBits > 0) {
+ drflac_uint8 padding = 0;
+ if (!drflac__read_uint8(&pFlac->bs, paddingSizeInBits, &padding)) {
+ return DRFLAC_AT_END;
+ }
+ }
+
+#ifndef DR_FLAC_NO_CRC
+ actualCRC16 = drflac__flush_crc16(&pFlac->bs);
+#endif
+ if (!drflac__read_uint16(&pFlac->bs, 16, &desiredCRC16)) {
+ return DRFLAC_AT_END;
+ }
+
+#ifndef DR_FLAC_NO_CRC
+ if (actualCRC16 != desiredCRC16) {
+ return DRFLAC_CRC_MISMATCH; /* CRC mismatch. */
+ }
+#endif
+
+ pFlac->currentFLACFrame.pcmFramesRemaining = pFlac->currentFLACFrame.header.blockSizeInPCMFrames;
+
+ return DRFLAC_SUCCESS;
+}
+
+static drflac_result drflac__seek_flac_frame(drflac* pFlac)
+{
+ int channelCount;
+ int i;
+ drflac_uint16 desiredCRC16;
+#ifndef DR_FLAC_NO_CRC
+ drflac_uint16 actualCRC16;
+#endif
+
+ channelCount = drflac__get_channel_count_from_channel_assignment(pFlac->currentFLACFrame.header.channelAssignment);
+ for (i = 0; i < channelCount; ++i) {
+ if (!drflac__seek_subframe(&pFlac->bs, &pFlac->currentFLACFrame, i)) {
+ return DRFLAC_ERROR;
+ }
+ }
+
+ /* Padding. */
+ if (!drflac__seek_bits(&pFlac->bs, DRFLAC_CACHE_L1_BITS_REMAINING(&pFlac->bs) & 7)) {
+ return DRFLAC_ERROR;
+ }
+
+ /* CRC. */
+#ifndef DR_FLAC_NO_CRC
+ actualCRC16 = drflac__flush_crc16(&pFlac->bs);
+#endif
+ if (!drflac__read_uint16(&pFlac->bs, 16, &desiredCRC16)) {
+ return DRFLAC_AT_END;
+ }
+
+#ifndef DR_FLAC_NO_CRC
+ if (actualCRC16 != desiredCRC16) {
+ return DRFLAC_CRC_MISMATCH; /* CRC mismatch. */
+ }
+#endif
+
+ return DRFLAC_SUCCESS;
+}
+
+static drflac_bool32 drflac__read_and_decode_next_flac_frame(drflac* pFlac)
+{
+ DRFLAC_ASSERT(pFlac != NULL);
+
+ for (;;) {
+ drflac_result result;
+
+ if (!drflac__read_next_flac_frame_header(&pFlac->bs, pFlac->bitsPerSample, &pFlac->currentFLACFrame.header)) {
+ return DRFLAC_FALSE;
+ }
+
+ result = drflac__decode_flac_frame(pFlac);
+ if (result != DRFLAC_SUCCESS) {
+ if (result == DRFLAC_CRC_MISMATCH) {
+ continue; /* CRC mismatch. Skip to the next frame. */
+ } else {
+ return DRFLAC_FALSE;
+ }
+ }
+
+ return DRFLAC_TRUE;
+ }
+}
+
+static void drflac__get_pcm_frame_range_of_current_flac_frame(drflac* pFlac, drflac_uint64* pFirstPCMFrame, drflac_uint64* pLastPCMFrame)
+{
+ drflac_uint64 firstPCMFrame;
+ drflac_uint64 lastPCMFrame;
+
+ DRFLAC_ASSERT(pFlac != NULL);
+
+ firstPCMFrame = pFlac->currentFLACFrame.header.pcmFrameNumber;
+ if (firstPCMFrame == 0) {
+ firstPCMFrame = ((drflac_uint64)pFlac->currentFLACFrame.header.flacFrameNumber) * pFlac->maxBlockSizeInPCMFrames;
+ }
+
+ lastPCMFrame = firstPCMFrame + pFlac->currentFLACFrame.header.blockSizeInPCMFrames;
+ if (lastPCMFrame > 0) {
+ lastPCMFrame -= 1; /* Needs to be zero based. */
+ }
+
+ if (pFirstPCMFrame) {
+ *pFirstPCMFrame = firstPCMFrame;
+ }
+ if (pLastPCMFrame) {
+ *pLastPCMFrame = lastPCMFrame;
+ }
+}
+
+static drflac_bool32 drflac__seek_to_first_frame(drflac* pFlac)
+{
+ drflac_bool32 result;
+
+ DRFLAC_ASSERT(pFlac != NULL);
+
+ result = drflac__seek_to_byte(&pFlac->bs, pFlac->firstFLACFramePosInBytes);
+
+ DRFLAC_ZERO_MEMORY(&pFlac->currentFLACFrame, sizeof(pFlac->currentFLACFrame));
+ pFlac->currentPCMFrame = 0;
+
+ return result;
+}
+
+static DRFLAC_INLINE drflac_result drflac__seek_to_next_flac_frame(drflac* pFlac)
+{
+ /* This function should only ever be called while the decoder is sitting on the first byte past the FRAME_HEADER section. */
+ DRFLAC_ASSERT(pFlac != NULL);
+ return drflac__seek_flac_frame(pFlac);
+}
+
+
+static drflac_uint64 drflac__seek_forward_by_pcm_frames(drflac* pFlac, drflac_uint64 pcmFramesToSeek)
+{
+ drflac_uint64 pcmFramesRead = 0;
+ while (pcmFramesToSeek > 0) {
+ if (pFlac->currentFLACFrame.pcmFramesRemaining == 0) {
+ if (!drflac__read_and_decode_next_flac_frame(pFlac)) {
+ break; /* Couldn't read the next frame, so just break from the loop and return. */
+ }
+ } else {
+ if (pFlac->currentFLACFrame.pcmFramesRemaining > pcmFramesToSeek) {
+ pcmFramesRead += pcmFramesToSeek;
+ pFlac->currentFLACFrame.pcmFramesRemaining -= (drflac_uint32)pcmFramesToSeek; /* <-- Safe cast. Will always be < currentFrame.pcmFramesRemaining < 65536. */
+ pcmFramesToSeek = 0;
+ } else {
+ pcmFramesRead += pFlac->currentFLACFrame.pcmFramesRemaining;
+ pcmFramesToSeek -= pFlac->currentFLACFrame.pcmFramesRemaining;
+ pFlac->currentFLACFrame.pcmFramesRemaining = 0;
+ }
+ }
+ }
+
+ pFlac->currentPCMFrame += pcmFramesRead;
+ return pcmFramesRead;
+}
+
+
+static drflac_bool32 drflac__seek_to_pcm_frame__brute_force(drflac* pFlac, drflac_uint64 pcmFrameIndex)
+{
+ drflac_bool32 isMidFrame = DRFLAC_FALSE;
+ drflac_uint64 runningPCMFrameCount;
+
+ DRFLAC_ASSERT(pFlac != NULL);
+
+ /* If we are seeking forward we start from the current position. Otherwise we need to start all the way from the start of the file. */
+ if (pcmFrameIndex >= pFlac->currentPCMFrame) {
+ /* Seeking forward. Need to seek from the current position. */
+ runningPCMFrameCount = pFlac->currentPCMFrame;
+
+ /* The frame header for the first frame may not yet have been read. We need to do that if necessary. */
+ if (pFlac->currentPCMFrame == 0 && pFlac->currentFLACFrame.pcmFramesRemaining == 0) {
+ if (!drflac__read_next_flac_frame_header(&pFlac->bs, pFlac->bitsPerSample, &pFlac->currentFLACFrame.header)) {
+ return DRFLAC_FALSE;
+ }
+ } else {
+ isMidFrame = DRFLAC_TRUE;
+ }
+ } else {
+ /* Seeking backwards. Need to seek from the start of the file. */
+ runningPCMFrameCount = 0;
+
+ /* Move back to the start. */
+ if (!drflac__seek_to_first_frame(pFlac)) {
+ return DRFLAC_FALSE;
+ }
+
+ /* Decode the first frame in preparation for sample-exact seeking below. */
+ if (!drflac__read_next_flac_frame_header(&pFlac->bs, pFlac->bitsPerSample, &pFlac->currentFLACFrame.header)) {
+ return DRFLAC_FALSE;
+ }
+ }
+
+ /*
+ We need to as quickly as possible find the frame that contains the target sample. To do this, we iterate over each frame and inspect its
+ header. If based on the header we can determine that the frame contains the sample, we do a full decode of that frame.
+ */
+ for (;;) {
+ drflac_uint64 pcmFrameCountInThisFLACFrame;
+ drflac_uint64 firstPCMFrameInFLACFrame = 0;
+ drflac_uint64 lastPCMFrameInFLACFrame = 0;
+
+ drflac__get_pcm_frame_range_of_current_flac_frame(pFlac, &firstPCMFrameInFLACFrame, &lastPCMFrameInFLACFrame);
+
+ pcmFrameCountInThisFLACFrame = (lastPCMFrameInFLACFrame - firstPCMFrameInFLACFrame) + 1;
+ if (pcmFrameIndex < (runningPCMFrameCount + pcmFrameCountInThisFLACFrame)) {
+ /*
+ The sample should be in this frame. We need to fully decode it, however if it's an invalid frame (a CRC mismatch), we need to pretend
+ it never existed and keep iterating.
+ */
+ drflac_uint64 pcmFramesToDecode = pcmFrameIndex - runningPCMFrameCount;
+
+ if (!isMidFrame) {
+ drflac_result result = drflac__decode_flac_frame(pFlac);
+ if (result == DRFLAC_SUCCESS) {
+ /* The frame is valid. We just need to skip over some samples to ensure it's sample-exact. */
+ return drflac__seek_forward_by_pcm_frames(pFlac, pcmFramesToDecode) == pcmFramesToDecode; /* <-- If this fails, something bad has happened (it should never fail). */
+ } else {
+ if (result == DRFLAC_CRC_MISMATCH) {
+ goto next_iteration; /* CRC mismatch. Pretend this frame never existed. */
+ } else {
+ return DRFLAC_FALSE;
+ }
+ }
+ } else {
+ /* We started seeking mid-frame which means we need to skip the frame decoding part. */
+ return drflac__seek_forward_by_pcm_frames(pFlac, pcmFramesToDecode) == pcmFramesToDecode;
+ }
+ } else {
+ /*
+ It's not in this frame. We need to seek past the frame, but check if there was a CRC mismatch. If so, we pretend this
+ frame never existed and leave the running sample count untouched.
+ */
+ if (!isMidFrame) {
+ drflac_result result = drflac__seek_to_next_flac_frame(pFlac);
+ if (result == DRFLAC_SUCCESS) {
+ runningPCMFrameCount += pcmFrameCountInThisFLACFrame;
+ } else {
+ if (result == DRFLAC_CRC_MISMATCH) {
+ goto next_iteration; /* CRC mismatch. Pretend this frame never existed. */
+ } else {
+ return DRFLAC_FALSE;
+ }
+ }
+ } else {
+ /*
+ We started seeking mid-frame which means we need to seek by reading to the end of the frame instead of with
+ drflac__seek_to_next_flac_frame() which only works if the decoder is sitting on the byte just after the frame header.
+ */
+ runningPCMFrameCount += pFlac->currentFLACFrame.pcmFramesRemaining;
+ pFlac->currentFLACFrame.pcmFramesRemaining = 0;
+ isMidFrame = DRFLAC_FALSE;
+ }
+
+ /* If we are seeking to the end of the file and we've just hit it, we're done. */
+ if (pcmFrameIndex == pFlac->totalPCMFrameCount && runningPCMFrameCount == pFlac->totalPCMFrameCount) {
+ return DRFLAC_TRUE;
+ }
+ }
+
+ next_iteration:
+ /* Grab the next frame in preparation for the next iteration. */
+ if (!drflac__read_next_flac_frame_header(&pFlac->bs, pFlac->bitsPerSample, &pFlac->currentFLACFrame.header)) {
+ return DRFLAC_FALSE;
+ }
+ }
+}
+
+
+#if !defined(DR_FLAC_NO_CRC)
+/*
+We use an average compression ratio to determine our approximate start location. FLAC files are generally about 50%-70% the size of their
+uncompressed counterparts so we'll use this as a basis. I'm going to split the middle and use a factor of 0.6 to determine the starting
+location.
+*/
+#define DRFLAC_BINARY_SEARCH_APPROX_COMPRESSION_RATIO 0.6f
+
+static drflac_bool32 drflac__seek_to_approximate_flac_frame_to_byte(drflac* pFlac, drflac_uint64 targetByte, drflac_uint64 rangeLo, drflac_uint64 rangeHi, drflac_uint64* pLastSuccessfulSeekOffset)
+{
+ DRFLAC_ASSERT(pFlac != NULL);
+ DRFLAC_ASSERT(pLastSuccessfulSeekOffset != NULL);
+ DRFLAC_ASSERT(targetByte >= rangeLo);
+ DRFLAC_ASSERT(targetByte <= rangeHi);
+
+ *pLastSuccessfulSeekOffset = pFlac->firstFLACFramePosInBytes;
+
+ for (;;) {
+ /* After rangeLo == rangeHi == targetByte fails, we need to break out. */
+ drflac_uint64 lastTargetByte = targetByte;
+
+ /* When seeking to a byte, failure probably means we've attempted to seek beyond the end of the stream. To counter this we just halve it each attempt. */
+ if (!drflac__seek_to_byte(&pFlac->bs, targetByte)) {
+ /* If we couldn't even seek to the first byte in the stream we have a problem. Just abandon the whole thing. */
+ if (targetByte == 0) {
+ drflac__seek_to_first_frame(pFlac); /* Try to recover. */
+ return DRFLAC_FALSE;
+ }
+
+ /* Halve the byte location and continue. */
+ targetByte = rangeLo + ((rangeHi - rangeLo)/2);
+ rangeHi = targetByte;
+ } else {
+ /* Getting here should mean that we have seeked to an appropriate byte. */
+
+ /* Clear the details of the FLAC frame so we don't misreport data. */
+ DRFLAC_ZERO_MEMORY(&pFlac->currentFLACFrame, sizeof(pFlac->currentFLACFrame));
+
+ /*
+ Now seek to the next FLAC frame. We need to decode the entire frame (not just the header) because it's possible for the header to incorrectly pass the
+ CRC check and return bad data. We need to decode the entire frame to be more certain. Although this seems unlikely, this has happened to me in testing
+ so it needs to stay this way for now.
+ */
+#if 1
+ if (!drflac__read_and_decode_next_flac_frame(pFlac)) {
+ /* Halve the byte location and continue. */
+ targetByte = rangeLo + ((rangeHi - rangeLo)/2);
+ rangeHi = targetByte;
+ } else {
+ break;
+ }
+#else
+ if (!drflac__read_next_flac_frame_header(&pFlac->bs, pFlac->bitsPerSample, &pFlac->currentFLACFrame.header)) {
+ /* Halve the byte location and continue. */
+ targetByte = rangeLo + ((rangeHi - rangeLo)/2);
+ rangeHi = targetByte;
+ } else {
+ break;
+ }
+#endif
+ }
+
+ /* We already tried this byte and there are no more to try, break out. */
+ if(targetByte == lastTargetByte) {
+ return DRFLAC_FALSE;
+ }
+ }
+
+ /* The current PCM frame needs to be updated based on the frame we just seeked to. */
+ drflac__get_pcm_frame_range_of_current_flac_frame(pFlac, &pFlac->currentPCMFrame, NULL);
+
+ DRFLAC_ASSERT(targetByte <= rangeHi);
+
+ *pLastSuccessfulSeekOffset = targetByte;
+ return DRFLAC_TRUE;
+}
+
+static drflac_bool32 drflac__decode_flac_frame_and_seek_forward_by_pcm_frames(drflac* pFlac, drflac_uint64 offset)
+{
+ /* This section of code would be used if we were only decoding the FLAC frame header when calling drflac__seek_to_approximate_flac_frame_to_byte(). */
+#if 0
+ if (drflac__decode_flac_frame(pFlac) != DRFLAC_SUCCESS) {
+ /* We failed to decode this frame which may be due to it being corrupt. We'll just use the next valid FLAC frame. */
+ if (drflac__read_and_decode_next_flac_frame(pFlac) == DRFLAC_FALSE) {
+ return DRFLAC_FALSE;
+ }
+ }
+#endif
+
+ return drflac__seek_forward_by_pcm_frames(pFlac, offset) == offset;
+}
+
+
+static drflac_bool32 drflac__seek_to_pcm_frame__binary_search_internal(drflac* pFlac, drflac_uint64 pcmFrameIndex, drflac_uint64 byteRangeLo, drflac_uint64 byteRangeHi)
+{
+ /* This assumes pFlac->currentPCMFrame is sitting on byteRangeLo upon entry. */
+
+ drflac_uint64 targetByte;
+ drflac_uint64 pcmRangeLo = pFlac->totalPCMFrameCount;
+ drflac_uint64 pcmRangeHi = 0;
+ drflac_uint64 lastSuccessfulSeekOffset = (drflac_uint64)-1;
+ drflac_uint64 closestSeekOffsetBeforeTargetPCMFrame = byteRangeLo;
+ drflac_uint32 seekForwardThreshold = (pFlac->maxBlockSizeInPCMFrames != 0) ? pFlac->maxBlockSizeInPCMFrames*2 : 4096;
+
+ targetByte = byteRangeLo + (drflac_uint64)(((drflac_int64)((pcmFrameIndex - pFlac->currentPCMFrame) * pFlac->channels * pFlac->bitsPerSample)/8.0f) * DRFLAC_BINARY_SEARCH_APPROX_COMPRESSION_RATIO);
+ if (targetByte > byteRangeHi) {
+ targetByte = byteRangeHi;
+ }
+
+ for (;;) {
+ if (drflac__seek_to_approximate_flac_frame_to_byte(pFlac, targetByte, byteRangeLo, byteRangeHi, &lastSuccessfulSeekOffset)) {
+ /* We found a FLAC frame. We need to check if it contains the sample we're looking for. */
+ drflac_uint64 newPCMRangeLo;
+ drflac_uint64 newPCMRangeHi;
+ drflac__get_pcm_frame_range_of_current_flac_frame(pFlac, &newPCMRangeLo, &newPCMRangeHi);
+
+ /* If we selected the same frame, it means we should be pretty close. Just decode the rest. */
+ if (pcmRangeLo == newPCMRangeLo) {
+ if (!drflac__seek_to_approximate_flac_frame_to_byte(pFlac, closestSeekOffsetBeforeTargetPCMFrame, closestSeekOffsetBeforeTargetPCMFrame, byteRangeHi, &lastSuccessfulSeekOffset)) {
+ break; /* Failed to seek to closest frame. */
+ }
+
+ if (drflac__decode_flac_frame_and_seek_forward_by_pcm_frames(pFlac, pcmFrameIndex - pFlac->currentPCMFrame)) {
+ return DRFLAC_TRUE;
+ } else {
+ break; /* Failed to seek forward. */
+ }
+ }
+
+ pcmRangeLo = newPCMRangeLo;
+ pcmRangeHi = newPCMRangeHi;
+
+ if (pcmRangeLo <= pcmFrameIndex && pcmRangeHi >= pcmFrameIndex) {
+ /* The target PCM frame is in this FLAC frame. */
+ if (drflac__decode_flac_frame_and_seek_forward_by_pcm_frames(pFlac, pcmFrameIndex - pFlac->currentPCMFrame) ) {
+ return DRFLAC_TRUE;
+ } else {
+ break; /* Failed to seek to FLAC frame. */
+ }
+ } else {
+ const float approxCompressionRatio = (drflac_int64)(lastSuccessfulSeekOffset - pFlac->firstFLACFramePosInBytes) / ((drflac_int64)(pcmRangeLo * pFlac->channels * pFlac->bitsPerSample)/8.0f);
+
+ if (pcmRangeLo > pcmFrameIndex) {
+ /* We seeked too far forward. We need to move our target byte backward and try again. */
+ byteRangeHi = lastSuccessfulSeekOffset;
+ if (byteRangeLo > byteRangeHi) {
+ byteRangeLo = byteRangeHi;
+ }
+
+ targetByte = byteRangeLo + ((byteRangeHi - byteRangeLo) / 2);
+ if (targetByte < byteRangeLo) {
+ targetByte = byteRangeLo;
+ }
+ } else /*if (pcmRangeHi < pcmFrameIndex)*/ {
+ /* We didn't seek far enough. We need to move our target byte forward and try again. */
+
+ /* If we're close enough we can just seek forward. */
+ if ((pcmFrameIndex - pcmRangeLo) < seekForwardThreshold) {
+ if (drflac__decode_flac_frame_and_seek_forward_by_pcm_frames(pFlac, pcmFrameIndex - pFlac->currentPCMFrame)) {
+ return DRFLAC_TRUE;
+ } else {
+ break; /* Failed to seek to FLAC frame. */
+ }
+ } else {
+ byteRangeLo = lastSuccessfulSeekOffset;
+ if (byteRangeHi < byteRangeLo) {
+ byteRangeHi = byteRangeLo;
+ }
+
+ targetByte = lastSuccessfulSeekOffset + (drflac_uint64)(((drflac_int64)((pcmFrameIndex-pcmRangeLo) * pFlac->channels * pFlac->bitsPerSample)/8.0f) * approxCompressionRatio);
+ if (targetByte > byteRangeHi) {
+ targetByte = byteRangeHi;
+ }
+
+ if (closestSeekOffsetBeforeTargetPCMFrame < lastSuccessfulSeekOffset) {
+ closestSeekOffsetBeforeTargetPCMFrame = lastSuccessfulSeekOffset;
+ }
+ }
+ }
+ }
+ } else {
+ /* Getting here is really bad. We just recover as best we can, but moving to the first frame in the stream, and then abort. */
+ break;
+ }
+ }
+
+ drflac__seek_to_first_frame(pFlac); /* <-- Try to recover. */
+ return DRFLAC_FALSE;
+}
+
+static drflac_bool32 drflac__seek_to_pcm_frame__binary_search(drflac* pFlac, drflac_uint64 pcmFrameIndex)
+{
+ drflac_uint64 byteRangeLo;
+ drflac_uint64 byteRangeHi;
+ drflac_uint32 seekForwardThreshold = (pFlac->maxBlockSizeInPCMFrames != 0) ? pFlac->maxBlockSizeInPCMFrames*2 : 4096;
+
+ /* Our algorithm currently assumes the FLAC stream is currently sitting at the start. */
+ if (drflac__seek_to_first_frame(pFlac) == DRFLAC_FALSE) {
+ return DRFLAC_FALSE;
+ }
+
+ /* If we're close enough to the start, just move to the start and seek forward. */
+ if (pcmFrameIndex < seekForwardThreshold) {
+ return drflac__seek_forward_by_pcm_frames(pFlac, pcmFrameIndex) == pcmFrameIndex;
+ }
+
+ /*
+ Our starting byte range is the byte position of the first FLAC frame and the approximate end of the file as if it were completely uncompressed. This ensures
+ the entire file is included, even though most of the time it'll exceed the end of the actual stream. This is OK as the frame searching logic will handle it.
+ */
+ byteRangeLo = pFlac->firstFLACFramePosInBytes;
+ byteRangeHi = pFlac->firstFLACFramePosInBytes + (drflac_uint64)((drflac_int64)(pFlac->totalPCMFrameCount * pFlac->channels * pFlac->bitsPerSample)/8.0f);
+
+ return drflac__seek_to_pcm_frame__binary_search_internal(pFlac, pcmFrameIndex, byteRangeLo, byteRangeHi);
+}
+#endif /* !DR_FLAC_NO_CRC */
+
+static drflac_bool32 drflac__seek_to_pcm_frame__seek_table(drflac* pFlac, drflac_uint64 pcmFrameIndex)
+{
+ drflac_uint32 iClosestSeekpoint = 0;
+ drflac_bool32 isMidFrame = DRFLAC_FALSE;
+ drflac_uint64 runningPCMFrameCount;
+ drflac_uint32 iSeekpoint;
+
+
+ DRFLAC_ASSERT(pFlac != NULL);
+
+ if (pFlac->pSeekpoints == NULL || pFlac->seekpointCount == 0) {
+ return DRFLAC_FALSE;
+ }
+
+ /* Do not use the seektable if pcmFramIndex is not coverd by it. */
+ if (pFlac->pSeekpoints[0].firstPCMFrame > pcmFrameIndex) {
+ return DRFLAC_FALSE;
+ }
+
+ for (iSeekpoint = 0; iSeekpoint < pFlac->seekpointCount; ++iSeekpoint) {
+ if (pFlac->pSeekpoints[iSeekpoint].firstPCMFrame >= pcmFrameIndex) {
+ break;
+ }
+
+ iClosestSeekpoint = iSeekpoint;
+ }
+
+ /* There's been cases where the seek table contains only zeros. We need to do some basic validation on the closest seekpoint. */
+ if (pFlac->pSeekpoints[iClosestSeekpoint].pcmFrameCount == 0 || pFlac->pSeekpoints[iClosestSeekpoint].pcmFrameCount > pFlac->maxBlockSizeInPCMFrames) {
+ return DRFLAC_FALSE;
+ }
+ if (pFlac->pSeekpoints[iClosestSeekpoint].firstPCMFrame > pFlac->totalPCMFrameCount && pFlac->totalPCMFrameCount > 0) {
+ return DRFLAC_FALSE;
+ }
+
+#if !defined(DR_FLAC_NO_CRC)
+ /* At this point we should know the closest seek point. We can use a binary search for this. We need to know the total sample count for this. */
+ if (pFlac->totalPCMFrameCount > 0) {
+ drflac_uint64 byteRangeLo;
+ drflac_uint64 byteRangeHi;
+
+ byteRangeHi = pFlac->firstFLACFramePosInBytes + (drflac_uint64)((drflac_int64)(pFlac->totalPCMFrameCount * pFlac->channels * pFlac->bitsPerSample)/8.0f);
+ byteRangeLo = pFlac->firstFLACFramePosInBytes + pFlac->pSeekpoints[iClosestSeekpoint].flacFrameOffset;
+
+ /*
+ If our closest seek point is not the last one, we only need to search between it and the next one. The section below calculates an appropriate starting
+ value for byteRangeHi which will clamp it appropriately.
+
+ Note that the next seekpoint must have an offset greater than the closest seekpoint because otherwise our binary search algorithm will break down. There
+ have been cases where a seektable consists of seek points where every byte offset is set to 0 which causes problems. If this happens we need to abort.
+ */
+ if (iClosestSeekpoint < pFlac->seekpointCount-1) {
+ drflac_uint32 iNextSeekpoint = iClosestSeekpoint + 1;
+
+ /* Basic validation on the seekpoints to ensure they're usable. */
+ if (pFlac->pSeekpoints[iClosestSeekpoint].flacFrameOffset >= pFlac->pSeekpoints[iNextSeekpoint].flacFrameOffset || pFlac->pSeekpoints[iNextSeekpoint].pcmFrameCount == 0) {
+ return DRFLAC_FALSE; /* The next seekpoint doesn't look right. The seek table cannot be trusted from here. Abort. */
+ }
+
+ if (pFlac->pSeekpoints[iNextSeekpoint].firstPCMFrame != (((drflac_uint64)0xFFFFFFFF << 32) | 0xFFFFFFFF)) { /* Make sure it's not a placeholder seekpoint. */
+ byteRangeHi = pFlac->firstFLACFramePosInBytes + pFlac->pSeekpoints[iNextSeekpoint].flacFrameOffset - 1; /* byteRangeHi must be zero based. */
+ }
+ }
+
+ if (drflac__seek_to_byte(&pFlac->bs, pFlac->firstFLACFramePosInBytes + pFlac->pSeekpoints[iClosestSeekpoint].flacFrameOffset)) {
+ if (drflac__read_next_flac_frame_header(&pFlac->bs, pFlac->bitsPerSample, &pFlac->currentFLACFrame.header)) {
+ drflac__get_pcm_frame_range_of_current_flac_frame(pFlac, &pFlac->currentPCMFrame, NULL);
+
+ if (drflac__seek_to_pcm_frame__binary_search_internal(pFlac, pcmFrameIndex, byteRangeLo, byteRangeHi)) {
+ return DRFLAC_TRUE;
+ }
+ }
+ }
+ }
+#endif /* !DR_FLAC_NO_CRC */
+
+ /* Getting here means we need to use a slower algorithm because the binary search method failed or cannot be used. */
+
+ /*
+ If we are seeking forward and the closest seekpoint is _before_ the current sample, we just seek forward from where we are. Otherwise we start seeking
+ from the seekpoint's first sample.
+ */
+ if (pcmFrameIndex >= pFlac->currentPCMFrame && pFlac->pSeekpoints[iClosestSeekpoint].firstPCMFrame <= pFlac->currentPCMFrame) {
+ /* Optimized case. Just seek forward from where we are. */
+ runningPCMFrameCount = pFlac->currentPCMFrame;
+
+ /* The frame header for the first frame may not yet have been read. We need to do that if necessary. */
+ if (pFlac->currentPCMFrame == 0 && pFlac->currentFLACFrame.pcmFramesRemaining == 0) {
+ if (!drflac__read_next_flac_frame_header(&pFlac->bs, pFlac->bitsPerSample, &pFlac->currentFLACFrame.header)) {
+ return DRFLAC_FALSE;
+ }
+ } else {
+ isMidFrame = DRFLAC_TRUE;
+ }
+ } else {
+ /* Slower case. Seek to the start of the seekpoint and then seek forward from there. */
+ runningPCMFrameCount = pFlac->pSeekpoints[iClosestSeekpoint].firstPCMFrame;
+
+ if (!drflac__seek_to_byte(&pFlac->bs, pFlac->firstFLACFramePosInBytes + pFlac->pSeekpoints[iClosestSeekpoint].flacFrameOffset)) {
+ return DRFLAC_FALSE;
+ }
+
+ /* Grab the frame the seekpoint is sitting on in preparation for the sample-exact seeking below. */
+ if (!drflac__read_next_flac_frame_header(&pFlac->bs, pFlac->bitsPerSample, &pFlac->currentFLACFrame.header)) {
+ return DRFLAC_FALSE;
+ }
+ }
+
+ for (;;) {
+ drflac_uint64 pcmFrameCountInThisFLACFrame;
+ drflac_uint64 firstPCMFrameInFLACFrame = 0;
+ drflac_uint64 lastPCMFrameInFLACFrame = 0;
+
+ drflac__get_pcm_frame_range_of_current_flac_frame(pFlac, &firstPCMFrameInFLACFrame, &lastPCMFrameInFLACFrame);
+
+ pcmFrameCountInThisFLACFrame = (lastPCMFrameInFLACFrame - firstPCMFrameInFLACFrame) + 1;
+ if (pcmFrameIndex < (runningPCMFrameCount + pcmFrameCountInThisFLACFrame)) {
+ /*
+ The sample should be in this frame. We need to fully decode it, but if it's an invalid frame (a CRC mismatch) we need to pretend
+ it never existed and keep iterating.
+ */
+ drflac_uint64 pcmFramesToDecode = pcmFrameIndex - runningPCMFrameCount;
+
+ if (!isMidFrame) {
+ drflac_result result = drflac__decode_flac_frame(pFlac);
+ if (result == DRFLAC_SUCCESS) {
+ /* The frame is valid. We just need to skip over some samples to ensure it's sample-exact. */
+ return drflac__seek_forward_by_pcm_frames(pFlac, pcmFramesToDecode) == pcmFramesToDecode; /* <-- If this fails, something bad has happened (it should never fail). */
+ } else {
+ if (result == DRFLAC_CRC_MISMATCH) {
+ goto next_iteration; /* CRC mismatch. Pretend this frame never existed. */
+ } else {
+ return DRFLAC_FALSE;
+ }
+ }
+ } else {
+ /* We started seeking mid-frame which means we need to skip the frame decoding part. */
+ return drflac__seek_forward_by_pcm_frames(pFlac, pcmFramesToDecode) == pcmFramesToDecode;
+ }
+ } else {
+ /*
+ It's not in this frame. We need to seek past the frame, but check if there was a CRC mismatch. If so, we pretend this
+ frame never existed and leave the running sample count untouched.
+ */
+ if (!isMidFrame) {
+ drflac_result result = drflac__seek_to_next_flac_frame(pFlac);
+ if (result == DRFLAC_SUCCESS) {
+ runningPCMFrameCount += pcmFrameCountInThisFLACFrame;
+ } else {
+ if (result == DRFLAC_CRC_MISMATCH) {
+ goto next_iteration; /* CRC mismatch. Pretend this frame never existed. */
+ } else {
+ return DRFLAC_FALSE;
+ }
+ }
+ } else {
+ /*
+ We started seeking mid-frame which means we need to seek by reading to the end of the frame instead of with
+ drflac__seek_to_next_flac_frame() which only works if the decoder is sitting on the byte just after the frame header.
+ */
+ runningPCMFrameCount += pFlac->currentFLACFrame.pcmFramesRemaining;
+ pFlac->currentFLACFrame.pcmFramesRemaining = 0;
+ isMidFrame = DRFLAC_FALSE;
+ }
+
+ /* If we are seeking to the end of the file and we've just hit it, we're done. */
+ if (pcmFrameIndex == pFlac->totalPCMFrameCount && runningPCMFrameCount == pFlac->totalPCMFrameCount) {
+ return DRFLAC_TRUE;
+ }
+ }
+
+ next_iteration:
+ /* Grab the next frame in preparation for the next iteration. */
+ if (!drflac__read_next_flac_frame_header(&pFlac->bs, pFlac->bitsPerSample, &pFlac->currentFLACFrame.header)) {
+ return DRFLAC_FALSE;
+ }
+ }
+}
+
+
+#ifndef DR_FLAC_NO_OGG
+typedef struct
+{
+ drflac_uint8 capturePattern[4]; /* Should be "OggS" */
+ drflac_uint8 structureVersion; /* Always 0. */
+ drflac_uint8 headerType;
+ drflac_uint64 granulePosition;
+ drflac_uint32 serialNumber;
+ drflac_uint32 sequenceNumber;
+ drflac_uint32 checksum;
+ drflac_uint8 segmentCount;
+ drflac_uint8 segmentTable[255];
+} drflac_ogg_page_header;
+#endif
+
+typedef struct
+{
+ drflac_read_proc onRead;
+ drflac_seek_proc onSeek;
+ drflac_meta_proc onMeta;
+ drflac_container container;
+ void* pUserData;
+ void* pUserDataMD;
+ drflac_uint32 sampleRate;
+ drflac_uint8 channels;
+ drflac_uint8 bitsPerSample;
+ drflac_uint64 totalPCMFrameCount;
+ drflac_uint16 maxBlockSizeInPCMFrames;
+ drflac_uint64 runningFilePos;
+ drflac_bool32 hasStreamInfoBlock;
+ drflac_bool32 hasMetadataBlocks;
+ drflac_bs bs; /* <-- A bit streamer is required for loading data during initialization. */
+ drflac_frame_header firstFrameHeader; /* <-- The header of the first frame that was read during relaxed initalization. Only set if there is no STREAMINFO block. */
+
+#ifndef DR_FLAC_NO_OGG
+ drflac_uint32 oggSerial;
+ drflac_uint64 oggFirstBytePos;
+ drflac_ogg_page_header oggBosHeader;
+#endif
+} drflac_init_info;
+
+static DRFLAC_INLINE void drflac__decode_block_header(drflac_uint32 blockHeader, drflac_uint8* isLastBlock, drflac_uint8* blockType, drflac_uint32* blockSize)
+{
+ blockHeader = drflac__be2host_32(blockHeader);
+ *isLastBlock = (drflac_uint8)((blockHeader & 0x80000000UL) >> 31);
+ *blockType = (drflac_uint8)((blockHeader & 0x7F000000UL) >> 24);
+ *blockSize = (blockHeader & 0x00FFFFFFUL);
+}
+
+static DRFLAC_INLINE drflac_bool32 drflac__read_and_decode_block_header(drflac_read_proc onRead, void* pUserData, drflac_uint8* isLastBlock, drflac_uint8* blockType, drflac_uint32* blockSize)
+{
+ drflac_uint32 blockHeader;
+
+ *blockSize = 0;
+ if (onRead(pUserData, &blockHeader, 4) != 4) {
+ return DRFLAC_FALSE;
+ }
+
+ drflac__decode_block_header(blockHeader, isLastBlock, blockType, blockSize);
+ return DRFLAC_TRUE;
+}
+
+static drflac_bool32 drflac__read_streaminfo(drflac_read_proc onRead, void* pUserData, drflac_streaminfo* pStreamInfo)
+{
+ drflac_uint32 blockSizes;
+ drflac_uint64 frameSizes = 0;
+ drflac_uint64 importantProps;
+ drflac_uint8 md5[16];
+
+ /* min/max block size. */
+ if (onRead(pUserData, &blockSizes, 4) != 4) {
+ return DRFLAC_FALSE;
+ }
+
+ /* min/max frame size. */
+ if (onRead(pUserData, &frameSizes, 6) != 6) {
+ return DRFLAC_FALSE;
+ }
+
+ /* Sample rate, channels, bits per sample and total sample count. */
+ if (onRead(pUserData, &importantProps, 8) != 8) {
+ return DRFLAC_FALSE;
+ }
+
+ /* MD5 */
+ if (onRead(pUserData, md5, sizeof(md5)) != sizeof(md5)) {
+ return DRFLAC_FALSE;
+ }
+
+ blockSizes = drflac__be2host_32(blockSizes);
+ frameSizes = drflac__be2host_64(frameSizes);
+ importantProps = drflac__be2host_64(importantProps);
+
+ pStreamInfo->minBlockSizeInPCMFrames = (drflac_uint16)((blockSizes & 0xFFFF0000) >> 16);
+ pStreamInfo->maxBlockSizeInPCMFrames = (drflac_uint16) (blockSizes & 0x0000FFFF);
+ pStreamInfo->minFrameSizeInPCMFrames = (drflac_uint32)((frameSizes & (((drflac_uint64)0x00FFFFFF << 16) << 24)) >> 40);
+ pStreamInfo->maxFrameSizeInPCMFrames = (drflac_uint32)((frameSizes & (((drflac_uint64)0x00FFFFFF << 16) << 0)) >> 16);
+ pStreamInfo->sampleRate = (drflac_uint32)((importantProps & (((drflac_uint64)0x000FFFFF << 16) << 28)) >> 44);
+ pStreamInfo->channels = (drflac_uint8 )((importantProps & (((drflac_uint64)0x0000000E << 16) << 24)) >> 41) + 1;
+ pStreamInfo->bitsPerSample = (drflac_uint8 )((importantProps & (((drflac_uint64)0x0000001F << 16) << 20)) >> 36) + 1;
+ pStreamInfo->totalPCMFrameCount = ((importantProps & ((((drflac_uint64)0x0000000F << 16) << 16) | 0xFFFFFFFF)));
+ DRFLAC_COPY_MEMORY(pStreamInfo->md5, md5, sizeof(md5));
+
+ return DRFLAC_TRUE;
+}
+
+
+static void* drflac__malloc_default(size_t sz, void* pUserData)
+{
+ (void)pUserData;
+ return DRFLAC_MALLOC(sz);
+}
+
+static void* drflac__realloc_default(void* p, size_t sz, void* pUserData)
+{
+ (void)pUserData;
+ return DRFLAC_REALLOC(p, sz);
+}
+
+static void drflac__free_default(void* p, void* pUserData)
+{
+ (void)pUserData;
+ DRFLAC_FREE(p);
+}
+
+
+static void* drflac__malloc_from_callbacks(size_t sz, const drflac_allocation_callbacks* pAllocationCallbacks)
+{
+ if (pAllocationCallbacks == NULL) {
+ return NULL;
+ }
+
+ if (pAllocationCallbacks->onMalloc != NULL) {
+ return pAllocationCallbacks->onMalloc(sz, pAllocationCallbacks->pUserData);
+ }
+
+ /* Try using realloc(). */
+ if (pAllocationCallbacks->onRealloc != NULL) {
+ return pAllocationCallbacks->onRealloc(NULL, sz, pAllocationCallbacks->pUserData);
+ }
+
+ return NULL;
+}
+
+static void* drflac__realloc_from_callbacks(void* p, size_t szNew, size_t szOld, const drflac_allocation_callbacks* pAllocationCallbacks)
+{
+ if (pAllocationCallbacks == NULL) {
+ return NULL;
+ }
+
+ if (pAllocationCallbacks->onRealloc != NULL) {
+ return pAllocationCallbacks->onRealloc(p, szNew, pAllocationCallbacks->pUserData);
+ }
+
+ /* Try emulating realloc() in terms of malloc()/free(). */
+ if (pAllocationCallbacks->onMalloc != NULL && pAllocationCallbacks->onFree != NULL) {
+ void* p2;
+
+ p2 = pAllocationCallbacks->onMalloc(szNew, pAllocationCallbacks->pUserData);
+ if (p2 == NULL) {
+ return NULL;
+ }
+
+ if (p != NULL) {
+ DRFLAC_COPY_MEMORY(p2, p, szOld);
+ pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData);
+ }
+
+ return p2;
+ }
+
+ return NULL;
+}
+
+static void drflac__free_from_callbacks(void* p, const drflac_allocation_callbacks* pAllocationCallbacks)
+{
+ if (p == NULL || pAllocationCallbacks == NULL) {
+ return;
+ }
+
+ if (pAllocationCallbacks->onFree != NULL) {
+ pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData);
+ }
+}
+
+
+static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, void* pUserData, void* pUserDataMD, drflac_uint64* pFirstFramePos, drflac_uint64* pSeektablePos, drflac_uint32* pSeekpointCount, drflac_allocation_callbacks* pAllocationCallbacks)
+{
+ /*
+ We want to keep track of the byte position in the stream of the seektable. At the time of calling this function we know that
+ we'll be sitting on byte 42.
+ */
+ drflac_uint64 runningFilePos = 42;
+ drflac_uint64 seektablePos = 0;
+ drflac_uint32 seektableSize = 0;
+
+ for (;;) {
+ drflac_metadata metadata;
+ drflac_uint8 isLastBlock = 0;
+ drflac_uint8 blockType = 0;
+ drflac_uint32 blockSize;
+ if (drflac__read_and_decode_block_header(onRead, pUserData, &isLastBlock, &blockType, &blockSize) == DRFLAC_FALSE) {
+ return DRFLAC_FALSE;
+ }
+ runningFilePos += 4;
+
+ metadata.type = blockType;
+ metadata.pRawData = NULL;
+ metadata.rawDataSize = 0;
+
+ switch (blockType)
+ {
+ case DRFLAC_METADATA_BLOCK_TYPE_APPLICATION:
+ {
+ if (blockSize < 4) {
+ return DRFLAC_FALSE;
+ }
+
+ if (onMeta) {
+ void* pRawData = drflac__malloc_from_callbacks(blockSize, pAllocationCallbacks);
+ if (pRawData == NULL) {
+ return DRFLAC_FALSE;
+ }
+
+ if (onRead(pUserData, pRawData, blockSize) != blockSize) {
+ drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
+ return DRFLAC_FALSE;
+ }
+
+ metadata.pRawData = pRawData;
+ metadata.rawDataSize = blockSize;
+ metadata.data.application.id = drflac__be2host_32(*(drflac_uint32*)pRawData);
+ metadata.data.application.pData = (const void*)((drflac_uint8*)pRawData + sizeof(drflac_uint32));
+ metadata.data.application.dataSize = blockSize - sizeof(drflac_uint32);
+ onMeta(pUserDataMD, &metadata);
+
+ drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
+ }
+ } break;
+
+ case DRFLAC_METADATA_BLOCK_TYPE_SEEKTABLE:
+ {
+ seektablePos = runningFilePos;
+ seektableSize = blockSize;
+
+ if (onMeta) {
+ drflac_uint32 seekpointCount;
+ drflac_uint32 iSeekpoint;
+ void* pRawData;
+
+ seekpointCount = blockSize/DRFLAC_SEEKPOINT_SIZE_IN_BYTES;
+
+ pRawData = drflac__malloc_from_callbacks(seekpointCount * sizeof(drflac_seekpoint), pAllocationCallbacks);
+ if (pRawData == NULL) {
+ return DRFLAC_FALSE;
+ }
+
+ /* We need to read seekpoint by seekpoint and do some processing. */
+ for (iSeekpoint = 0; iSeekpoint < seekpointCount; ++iSeekpoint) {
+ drflac_seekpoint* pSeekpoint = (drflac_seekpoint*)pRawData + iSeekpoint;
+
+ if (onRead(pUserData, pSeekpoint, DRFLAC_SEEKPOINT_SIZE_IN_BYTES) != DRFLAC_SEEKPOINT_SIZE_IN_BYTES) {
+ drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
+ return DRFLAC_FALSE;
+ }
+
+ /* Endian swap. */
+ pSeekpoint->firstPCMFrame = drflac__be2host_64(pSeekpoint->firstPCMFrame);
+ pSeekpoint->flacFrameOffset = drflac__be2host_64(pSeekpoint->flacFrameOffset);
+ pSeekpoint->pcmFrameCount = drflac__be2host_16(pSeekpoint->pcmFrameCount);
+ }
+
+ metadata.pRawData = pRawData;
+ metadata.rawDataSize = blockSize;
+ metadata.data.seektable.seekpointCount = seekpointCount;
+ metadata.data.seektable.pSeekpoints = (const drflac_seekpoint*)pRawData;
+
+ onMeta(pUserDataMD, &metadata);
+
+ drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
+ }
+ } break;
+
+ case DRFLAC_METADATA_BLOCK_TYPE_VORBIS_COMMENT:
+ {
+ if (blockSize < 8) {
+ return DRFLAC_FALSE;
+ }
+
+ if (onMeta) {
+ void* pRawData;
+ const char* pRunningData;
+ const char* pRunningDataEnd;
+ drflac_uint32 i;
+
+ pRawData = drflac__malloc_from_callbacks(blockSize, pAllocationCallbacks);
+ if (pRawData == NULL) {
+ return DRFLAC_FALSE;
+ }
+
+ if (onRead(pUserData, pRawData, blockSize) != blockSize) {
+ drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
+ return DRFLAC_FALSE;
+ }
+
+ metadata.pRawData = pRawData;
+ metadata.rawDataSize = blockSize;
+
+ pRunningData = (const char*)pRawData;
+ pRunningDataEnd = (const char*)pRawData + blockSize;
+
+ metadata.data.vorbis_comment.vendorLength = drflac__le2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
+
+ /* Need space for the rest of the block */
+ if ((pRunningDataEnd - pRunningData) - 4 < (drflac_int64)metadata.data.vorbis_comment.vendorLength) { /* <-- Note the order of operations to avoid overflow to a valid value */
+ drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
+ return DRFLAC_FALSE;
+ }
+ metadata.data.vorbis_comment.vendor = pRunningData; pRunningData += metadata.data.vorbis_comment.vendorLength;
+ metadata.data.vorbis_comment.commentCount = drflac__le2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
+
+ /* Need space for 'commentCount' comments after the block, which at minimum is a drflac_uint32 per comment */
+ if ((pRunningDataEnd - pRunningData) / sizeof(drflac_uint32) < metadata.data.vorbis_comment.commentCount) { /* <-- Note the order of operations to avoid overflow to a valid value */
+ drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
+ return DRFLAC_FALSE;
+ }
+ metadata.data.vorbis_comment.pComments = pRunningData;
+
+ /* Check that the comments section is valid before passing it to the callback */
+ for (i = 0; i < metadata.data.vorbis_comment.commentCount; ++i) {
+ drflac_uint32 commentLength;
+
+ if (pRunningDataEnd - pRunningData < 4) {
+ drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
+ return DRFLAC_FALSE;
+ }
+
+ commentLength = drflac__le2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
+ if (pRunningDataEnd - pRunningData < (drflac_int64)commentLength) { /* <-- Note the order of operations to avoid overflow to a valid value */
+ drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
+ return DRFLAC_FALSE;
+ }
+ pRunningData += commentLength;
+ }
+
+ onMeta(pUserDataMD, &metadata);
+
+ drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
+ }
+ } break;
+
+ case DRFLAC_METADATA_BLOCK_TYPE_CUESHEET:
+ {
+ if (blockSize < 396) {
+ return DRFLAC_FALSE;
+ }
+
+ if (onMeta) {
+ void* pRawData;
+ const char* pRunningData;
+ const char* pRunningDataEnd;
+ size_t bufferSize;
+ drflac_uint8 iTrack;
+ drflac_uint8 iIndex;
+ void* pTrackData;
+
+ /*
+ This needs to be loaded in two passes. The first pass is used to calculate the size of the memory allocation
+ we need for storing the necessary data. The second pass will fill that buffer with usable data.
+ */
+ pRawData = drflac__malloc_from_callbacks(blockSize, pAllocationCallbacks);
+ if (pRawData == NULL) {
+ return DRFLAC_FALSE;
+ }
+
+ if (onRead(pUserData, pRawData, blockSize) != blockSize) {
+ drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
+ return DRFLAC_FALSE;
+ }
+
+ metadata.pRawData = pRawData;
+ metadata.rawDataSize = blockSize;
+
+ pRunningData = (const char*)pRawData;
+ pRunningDataEnd = (const char*)pRawData + blockSize;
+
+ DRFLAC_COPY_MEMORY(metadata.data.cuesheet.catalog, pRunningData, 128); pRunningData += 128;
+ metadata.data.cuesheet.leadInSampleCount = drflac__be2host_64(*(const drflac_uint64*)pRunningData); pRunningData += 8;
+ metadata.data.cuesheet.isCD = (pRunningData[0] & 0x80) != 0; pRunningData += 259;
+ metadata.data.cuesheet.trackCount = pRunningData[0]; pRunningData += 1;
+ metadata.data.cuesheet.pTrackData = NULL; /* Will be filled later. */
+
+ /* Pass 1: Calculate the size of the buffer for the track data. */
+ {
+ const char* pRunningDataSaved = pRunningData; /* Will be restored at the end in preparation for the second pass. */
+
+ bufferSize = metadata.data.cuesheet.trackCount * DRFLAC_CUESHEET_TRACK_SIZE_IN_BYTES;
+
+ for (iTrack = 0; iTrack < metadata.data.cuesheet.trackCount; ++iTrack) {
+ drflac_uint8 indexCount;
+ drflac_uint32 indexPointSize;
+
+ if (pRunningDataEnd - pRunningData < DRFLAC_CUESHEET_TRACK_SIZE_IN_BYTES) {
+ drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
+ return DRFLAC_FALSE;
+ }
+
+ /* Skip to the index point count */
+ pRunningData += 35;
+
+ indexCount = pRunningData[0];
+ pRunningData += 1;
+
+ bufferSize += indexCount * sizeof(drflac_cuesheet_track_index);
+
+ /* Quick validation check. */
+ indexPointSize = indexCount * DRFLAC_CUESHEET_TRACK_INDEX_SIZE_IN_BYTES;
+ if (pRunningDataEnd - pRunningData < (drflac_int64)indexPointSize) {
+ drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
+ return DRFLAC_FALSE;
+ }
+
+ pRunningData += indexPointSize;
+ }
+
+ pRunningData = pRunningDataSaved;
+ }
+
+ /* Pass 2: Allocate a buffer and fill the data. Validation was done in the step above so can be skipped. */
+ {
+ char* pRunningTrackData;
+
+ pTrackData = drflac__malloc_from_callbacks(bufferSize, pAllocationCallbacks);
+ if (pTrackData == NULL) {
+ drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
+ return DRFLAC_FALSE;
+ }
+
+ pRunningTrackData = (char*)pTrackData;
+
+ for (iTrack = 0; iTrack < metadata.data.cuesheet.trackCount; ++iTrack) {
+ drflac_uint8 indexCount;
+
+ DRFLAC_COPY_MEMORY(pRunningTrackData, pRunningData, DRFLAC_CUESHEET_TRACK_SIZE_IN_BYTES);
+ pRunningData += DRFLAC_CUESHEET_TRACK_SIZE_IN_BYTES-1; /* Skip forward, but not beyond the last byte in the CUESHEET_TRACK block which is the index count. */
+ pRunningTrackData += DRFLAC_CUESHEET_TRACK_SIZE_IN_BYTES-1;
+
+ /* Grab the index count for the next part. */
+ indexCount = pRunningData[0];
+ pRunningData += 1;
+ pRunningTrackData += 1;
+
+ /* Extract each track index. */
+ for (iIndex = 0; iIndex < indexCount; ++iIndex) {
+ drflac_cuesheet_track_index* pTrackIndex = (drflac_cuesheet_track_index*)pRunningTrackData;
+
+ DRFLAC_COPY_MEMORY(pRunningTrackData, pRunningData, DRFLAC_CUESHEET_TRACK_INDEX_SIZE_IN_BYTES);
+ pRunningData += DRFLAC_CUESHEET_TRACK_INDEX_SIZE_IN_BYTES;
+ pRunningTrackData += sizeof(drflac_cuesheet_track_index);
+
+ pTrackIndex->offset = drflac__be2host_64(pTrackIndex->offset);
+ }
+ }
+
+ metadata.data.cuesheet.pTrackData = pTrackData;
+ }
+
+ /* The original data is no longer needed. */
+ drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
+ pRawData = NULL;
+
+ onMeta(pUserDataMD, &metadata);
+
+ drflac__free_from_callbacks(pTrackData, pAllocationCallbacks);
+ pTrackData = NULL;
+ }
+ } break;
+
+ case DRFLAC_METADATA_BLOCK_TYPE_PICTURE:
+ {
+ if (blockSize < 32) {
+ return DRFLAC_FALSE;
+ }
+
+ if (onMeta) {
+ void* pRawData;
+ const char* pRunningData;
+ const char* pRunningDataEnd;
+
+ pRawData = drflac__malloc_from_callbacks(blockSize, pAllocationCallbacks);
+ if (pRawData == NULL) {
+ return DRFLAC_FALSE;
+ }
+
+ if (onRead(pUserData, pRawData, blockSize) != blockSize) {
+ drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
+ return DRFLAC_FALSE;
+ }
+
+ 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;
+ }
+ metadata.data.picture.mime = pRunningData; pRunningData += metadata.data.picture.mimeLength;
+ metadata.data.picture.descriptionLength = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
+
+ /* 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;
+ }
+ 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;
+
+ /* 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;
+ }
+
+ onMeta(pUserDataMD, &metadata);
+
+ drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
+ }
+ } break;
+
+ case DRFLAC_METADATA_BLOCK_TYPE_PADDING:
+ {
+ if (onMeta) {
+ metadata.data.padding.unused = 0;
+
+ /* Padding doesn't have anything meaningful in it, so just skip over it, but make sure the caller is aware of it by firing the callback. */
+ if (!onSeek(pUserData, blockSize, drflac_seek_origin_current)) {
+ isLastBlock = DRFLAC_TRUE; /* An error occurred while seeking. Attempt to recover by treating this as the last block which will in turn terminate the loop. */
+ } else {
+ onMeta(pUserDataMD, &metadata);
+ }
+ }
+ } break;
+
+ case DRFLAC_METADATA_BLOCK_TYPE_INVALID:
+ {
+ /* Invalid chunk. Just skip over this one. */
+ if (onMeta) {
+ if (!onSeek(pUserData, blockSize, drflac_seek_origin_current)) {
+ isLastBlock = DRFLAC_TRUE; /* An error occurred while seeking. Attempt to recover by treating this as the last block which will in turn terminate the loop. */
+ }
+ }
+ } break;
+
+ default:
+ {
+ /*
+ It's an unknown chunk, but not necessarily invalid. There's a chance more metadata blocks might be defined later on, so we
+ can at the very least report the chunk to the application and let it look at the raw data.
+ */
+ if (onMeta) {
+ void* pRawData = drflac__malloc_from_callbacks(blockSize, pAllocationCallbacks);
+ if (pRawData == NULL) {
+ return DRFLAC_FALSE;
+ }
+
+ if (onRead(pUserData, pRawData, blockSize) != blockSize) {
+ drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
+ return DRFLAC_FALSE;
+ }
+
+ metadata.pRawData = pRawData;
+ metadata.rawDataSize = blockSize;
+ onMeta(pUserDataMD, &metadata);
+
+ drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
+ }
+ } break;
+ }
+
+ /* If we're not handling metadata, just skip over the block. If we are, it will have been handled earlier in the switch statement above. */
+ if (onMeta == NULL && blockSize > 0) {
+ if (!onSeek(pUserData, blockSize, drflac_seek_origin_current)) {
+ isLastBlock = DRFLAC_TRUE;
+ }
+ }
+
+ runningFilePos += blockSize;
+ if (isLastBlock) {
+ break;
+ }
+ }
+
+ *pSeektablePos = seektablePos;
+ *pSeekpointCount = seektableSize / DRFLAC_SEEKPOINT_SIZE_IN_BYTES;
+ *pFirstFramePos = runningFilePos;
+
+ return DRFLAC_TRUE;
+}
+
+static drflac_bool32 drflac__init_private__native(drflac_init_info* pInit, drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, void* pUserData, void* pUserDataMD, drflac_bool32 relaxed)
+{
+ /* Pre Condition: The bit stream should be sitting just past the 4-byte id header. */
+
+ drflac_uint8 isLastBlock;
+ drflac_uint8 blockType;
+ drflac_uint32 blockSize;
+
+ (void)onSeek;
+
+ pInit->container = drflac_container_native;
+
+ /* The first metadata block should be the STREAMINFO block. */
+ if (!drflac__read_and_decode_block_header(onRead, pUserData, &isLastBlock, &blockType, &blockSize)) {
+ return DRFLAC_FALSE;
+ }
+
+ if (blockType != DRFLAC_METADATA_BLOCK_TYPE_STREAMINFO || blockSize != 34) {
+ if (!relaxed) {
+ /* We're opening in strict mode and the first block is not the STREAMINFO block. Error. */
+ return DRFLAC_FALSE;
+ } else {
+ /*
+ Relaxed mode. To open from here we need to just find the first frame and set the sample rate, etc. to whatever is defined
+ for that frame.
+ */
+ pInit->hasStreamInfoBlock = DRFLAC_FALSE;
+ pInit->hasMetadataBlocks = DRFLAC_FALSE;
+
+ if (!drflac__read_next_flac_frame_header(&pInit->bs, 0, &pInit->firstFrameHeader)) {
+ return DRFLAC_FALSE; /* Couldn't find a frame. */
+ }
+
+ if (pInit->firstFrameHeader.bitsPerSample == 0) {
+ return DRFLAC_FALSE; /* Failed to initialize because the first frame depends on the STREAMINFO block, which does not exist. */
+ }
+
+ pInit->sampleRate = pInit->firstFrameHeader.sampleRate;
+ pInit->channels = drflac__get_channel_count_from_channel_assignment(pInit->firstFrameHeader.channelAssignment);
+ pInit->bitsPerSample = pInit->firstFrameHeader.bitsPerSample;
+ pInit->maxBlockSizeInPCMFrames = 65535; /* <-- See notes here: https://xiph.org/flac/format.html#metadata_block_streaminfo */
+ return DRFLAC_TRUE;
+ }
+ } else {
+ drflac_streaminfo streaminfo;
+ if (!drflac__read_streaminfo(onRead, pUserData, &streaminfo)) {
+ return DRFLAC_FALSE;
+ }
+
+ pInit->hasStreamInfoBlock = DRFLAC_TRUE;
+ pInit->sampleRate = streaminfo.sampleRate;
+ pInit->channels = streaminfo.channels;
+ pInit->bitsPerSample = streaminfo.bitsPerSample;
+ pInit->totalPCMFrameCount = streaminfo.totalPCMFrameCount;
+ pInit->maxBlockSizeInPCMFrames = streaminfo.maxBlockSizeInPCMFrames; /* Don't care about the min block size - only the max (used for determining the size of the memory allocation). */
+ pInit->hasMetadataBlocks = !isLastBlock;
+
+ if (onMeta) {
+ drflac_metadata metadata;
+ metadata.type = DRFLAC_METADATA_BLOCK_TYPE_STREAMINFO;
+ metadata.pRawData = NULL;
+ metadata.rawDataSize = 0;
+ metadata.data.streaminfo = streaminfo;
+ onMeta(pUserDataMD, &metadata);
+ }
+
+ return DRFLAC_TRUE;
+ }
+}
+
+#ifndef DR_FLAC_NO_OGG
+#define DRFLAC_OGG_MAX_PAGE_SIZE 65307
+#define DRFLAC_OGG_CAPTURE_PATTERN_CRC32 1605413199 /* CRC-32 of "OggS". */
+
+typedef enum
+{
+ drflac_ogg_recover_on_crc_mismatch,
+ drflac_ogg_fail_on_crc_mismatch
+} drflac_ogg_crc_mismatch_recovery;
+
+#ifndef DR_FLAC_NO_CRC
+static drflac_uint32 drflac__crc32_table[] = {
+ 0x00000000L, 0x04C11DB7L, 0x09823B6EL, 0x0D4326D9L,
+ 0x130476DCL, 0x17C56B6BL, 0x1A864DB2L, 0x1E475005L,
+ 0x2608EDB8L, 0x22C9F00FL, 0x2F8AD6D6L, 0x2B4BCB61L,
+ 0x350C9B64L, 0x31CD86D3L, 0x3C8EA00AL, 0x384FBDBDL,
+ 0x4C11DB70L, 0x48D0C6C7L, 0x4593E01EL, 0x4152FDA9L,
+ 0x5F15ADACL, 0x5BD4B01BL, 0x569796C2L, 0x52568B75L,
+ 0x6A1936C8L, 0x6ED82B7FL, 0x639B0DA6L, 0x675A1011L,
+ 0x791D4014L, 0x7DDC5DA3L, 0x709F7B7AL, 0x745E66CDL,
+ 0x9823B6E0L, 0x9CE2AB57L, 0x91A18D8EL, 0x95609039L,
+ 0x8B27C03CL, 0x8FE6DD8BL, 0x82A5FB52L, 0x8664E6E5L,
+ 0xBE2B5B58L, 0xBAEA46EFL, 0xB7A96036L, 0xB3687D81L,
+ 0xAD2F2D84L, 0xA9EE3033L, 0xA4AD16EAL, 0xA06C0B5DL,
+ 0xD4326D90L, 0xD0F37027L, 0xDDB056FEL, 0xD9714B49L,
+ 0xC7361B4CL, 0xC3F706FBL, 0xCEB42022L, 0xCA753D95L,
+ 0xF23A8028L, 0xF6FB9D9FL, 0xFBB8BB46L, 0xFF79A6F1L,
+ 0xE13EF6F4L, 0xE5FFEB43L, 0xE8BCCD9AL, 0xEC7DD02DL,
+ 0x34867077L, 0x30476DC0L, 0x3D044B19L, 0x39C556AEL,
+ 0x278206ABL, 0x23431B1CL, 0x2E003DC5L, 0x2AC12072L,
+ 0x128E9DCFL, 0x164F8078L, 0x1B0CA6A1L, 0x1FCDBB16L,
+ 0x018AEB13L, 0x054BF6A4L, 0x0808D07DL, 0x0CC9CDCAL,
+ 0x7897AB07L, 0x7C56B6B0L, 0x71159069L, 0x75D48DDEL,
+ 0x6B93DDDBL, 0x6F52C06CL, 0x6211E6B5L, 0x66D0FB02L,
+ 0x5E9F46BFL, 0x5A5E5B08L, 0x571D7DD1L, 0x53DC6066L,
+ 0x4D9B3063L, 0x495A2DD4L, 0x44190B0DL, 0x40D816BAL,
+ 0xACA5C697L, 0xA864DB20L, 0xA527FDF9L, 0xA1E6E04EL,
+ 0xBFA1B04BL, 0xBB60ADFCL, 0xB6238B25L, 0xB2E29692L,
+ 0x8AAD2B2FL, 0x8E6C3698L, 0x832F1041L, 0x87EE0DF6L,
+ 0x99A95DF3L, 0x9D684044L, 0x902B669DL, 0x94EA7B2AL,
+ 0xE0B41DE7L, 0xE4750050L, 0xE9362689L, 0xEDF73B3EL,
+ 0xF3B06B3BL, 0xF771768CL, 0xFA325055L, 0xFEF34DE2L,
+ 0xC6BCF05FL, 0xC27DEDE8L, 0xCF3ECB31L, 0xCBFFD686L,
+ 0xD5B88683L, 0xD1799B34L, 0xDC3ABDEDL, 0xD8FBA05AL,
+ 0x690CE0EEL, 0x6DCDFD59L, 0x608EDB80L, 0x644FC637L,
+ 0x7A089632L, 0x7EC98B85L, 0x738AAD5CL, 0x774BB0EBL,
+ 0x4F040D56L, 0x4BC510E1L, 0x46863638L, 0x42472B8FL,
+ 0x5C007B8AL, 0x58C1663DL, 0x558240E4L, 0x51435D53L,
+ 0x251D3B9EL, 0x21DC2629L, 0x2C9F00F0L, 0x285E1D47L,
+ 0x36194D42L, 0x32D850F5L, 0x3F9B762CL, 0x3B5A6B9BL,
+ 0x0315D626L, 0x07D4CB91L, 0x0A97ED48L, 0x0E56F0FFL,
+ 0x1011A0FAL, 0x14D0BD4DL, 0x19939B94L, 0x1D528623L,
+ 0xF12F560EL, 0xF5EE4BB9L, 0xF8AD6D60L, 0xFC6C70D7L,
+ 0xE22B20D2L, 0xE6EA3D65L, 0xEBA91BBCL, 0xEF68060BL,
+ 0xD727BBB6L, 0xD3E6A601L, 0xDEA580D8L, 0xDA649D6FL,
+ 0xC423CD6AL, 0xC0E2D0DDL, 0xCDA1F604L, 0xC960EBB3L,
+ 0xBD3E8D7EL, 0xB9FF90C9L, 0xB4BCB610L, 0xB07DABA7L,
+ 0xAE3AFBA2L, 0xAAFBE615L, 0xA7B8C0CCL, 0xA379DD7BL,
+ 0x9B3660C6L, 0x9FF77D71L, 0x92B45BA8L, 0x9675461FL,
+ 0x8832161AL, 0x8CF30BADL, 0x81B02D74L, 0x857130C3L,
+ 0x5D8A9099L, 0x594B8D2EL, 0x5408ABF7L, 0x50C9B640L,
+ 0x4E8EE645L, 0x4A4FFBF2L, 0x470CDD2BL, 0x43CDC09CL,
+ 0x7B827D21L, 0x7F436096L, 0x7200464FL, 0x76C15BF8L,
+ 0x68860BFDL, 0x6C47164AL, 0x61043093L, 0x65C52D24L,
+ 0x119B4BE9L, 0x155A565EL, 0x18197087L, 0x1CD86D30L,
+ 0x029F3D35L, 0x065E2082L, 0x0B1D065BL, 0x0FDC1BECL,
+ 0x3793A651L, 0x3352BBE6L, 0x3E119D3FL, 0x3AD08088L,
+ 0x2497D08DL, 0x2056CD3AL, 0x2D15EBE3L, 0x29D4F654L,
+ 0xC5A92679L, 0xC1683BCEL, 0xCC2B1D17L, 0xC8EA00A0L,
+ 0xD6AD50A5L, 0xD26C4D12L, 0xDF2F6BCBL, 0xDBEE767CL,
+ 0xE3A1CBC1L, 0xE760D676L, 0xEA23F0AFL, 0xEEE2ED18L,
+ 0xF0A5BD1DL, 0xF464A0AAL, 0xF9278673L, 0xFDE69BC4L,
+ 0x89B8FD09L, 0x8D79E0BEL, 0x803AC667L, 0x84FBDBD0L,
+ 0x9ABC8BD5L, 0x9E7D9662L, 0x933EB0BBL, 0x97FFAD0CL,
+ 0xAFB010B1L, 0xAB710D06L, 0xA6322BDFL, 0xA2F33668L,
+ 0xBCB4666DL, 0xB8757BDAL, 0xB5365D03L, 0xB1F740B4L
+};
+#endif
+
+static DRFLAC_INLINE drflac_uint32 drflac_crc32_byte(drflac_uint32 crc32, drflac_uint8 data)
+{
+#ifndef DR_FLAC_NO_CRC
+ return (crc32 << 8) ^ drflac__crc32_table[(drflac_uint8)((crc32 >> 24) & 0xFF) ^ data];
+#else
+ (void)data;
+ return crc32;
+#endif
+}
+
+#if 0
+static DRFLAC_INLINE drflac_uint32 drflac_crc32_uint32(drflac_uint32 crc32, drflac_uint32 data)
+{
+ crc32 = drflac_crc32_byte(crc32, (drflac_uint8)((data >> 24) & 0xFF));
+ crc32 = drflac_crc32_byte(crc32, (drflac_uint8)((data >> 16) & 0xFF));
+ crc32 = drflac_crc32_byte(crc32, (drflac_uint8)((data >> 8) & 0xFF));
+ crc32 = drflac_crc32_byte(crc32, (drflac_uint8)((data >> 0) & 0xFF));
+ return crc32;
+}
+
+static DRFLAC_INLINE drflac_uint32 drflac_crc32_uint64(drflac_uint32 crc32, drflac_uint64 data)
+{
+ crc32 = drflac_crc32_uint32(crc32, (drflac_uint32)((data >> 32) & 0xFFFFFFFF));
+ crc32 = drflac_crc32_uint32(crc32, (drflac_uint32)((data >> 0) & 0xFFFFFFFF));
+ return crc32;
+}
+#endif
+
+static DRFLAC_INLINE drflac_uint32 drflac_crc32_buffer(drflac_uint32 crc32, drflac_uint8* pData, drflac_uint32 dataSize)
+{
+ /* This can be optimized. */
+ drflac_uint32 i;
+ for (i = 0; i < dataSize; ++i) {
+ crc32 = drflac_crc32_byte(crc32, pData[i]);
+ }
+ return crc32;
+}
+
+
+static DRFLAC_INLINE drflac_bool32 drflac_ogg__is_capture_pattern(drflac_uint8 pattern[4])
+{
+ return pattern[0] == 'O' && pattern[1] == 'g' && pattern[2] == 'g' && pattern[3] == 'S';
+}
+
+static DRFLAC_INLINE drflac_uint32 drflac_ogg__get_page_header_size(drflac_ogg_page_header* pHeader)
+{
+ return 27 + pHeader->segmentCount;
+}
+
+static DRFLAC_INLINE drflac_uint32 drflac_ogg__get_page_body_size(drflac_ogg_page_header* pHeader)
+{
+ drflac_uint32 pageBodySize = 0;
+ int i;
+
+ for (i = 0; i < pHeader->segmentCount; ++i) {
+ pageBodySize += pHeader->segmentTable[i];
+ }
+
+ return pageBodySize;
+}
+
+static drflac_result drflac_ogg__read_page_header_after_capture_pattern(drflac_read_proc onRead, void* pUserData, drflac_ogg_page_header* pHeader, drflac_uint32* pBytesRead, drflac_uint32* pCRC32)
+{
+ drflac_uint8 data[23];
+ drflac_uint32 i;
+
+ DRFLAC_ASSERT(*pCRC32 == DRFLAC_OGG_CAPTURE_PATTERN_CRC32);
+
+ if (onRead(pUserData, data, 23) != 23) {
+ return DRFLAC_AT_END;
+ }
+ *pBytesRead += 23;
+
+ /*
+ It's not actually used, but set the capture pattern to 'OggS' for completeness. Not doing this will cause static analysers to complain about
+ us trying to access uninitialized data. We could alternatively just comment out this member of the drflac_ogg_page_header structure, but I
+ like to have it map to the structure of the underlying data.
+ */
+ pHeader->capturePattern[0] = 'O';
+ pHeader->capturePattern[1] = 'g';
+ pHeader->capturePattern[2] = 'g';
+ pHeader->capturePattern[3] = 'S';
+
+ pHeader->structureVersion = data[0];
+ pHeader->headerType = data[1];
+ DRFLAC_COPY_MEMORY(&pHeader->granulePosition, &data[ 2], 8);
+ DRFLAC_COPY_MEMORY(&pHeader->serialNumber, &data[10], 4);
+ DRFLAC_COPY_MEMORY(&pHeader->sequenceNumber, &data[14], 4);
+ DRFLAC_COPY_MEMORY(&pHeader->checksum, &data[18], 4);
+ pHeader->segmentCount = data[22];
+
+ /* Calculate the CRC. Note that for the calculation the checksum part of the page needs to be set to 0. */
+ data[18] = 0;
+ data[19] = 0;
+ data[20] = 0;
+ data[21] = 0;
+
+ for (i = 0; i < 23; ++i) {
+ *pCRC32 = drflac_crc32_byte(*pCRC32, data[i]);
+ }
+
+
+ if (onRead(pUserData, pHeader->segmentTable, pHeader->segmentCount) != pHeader->segmentCount) {
+ return DRFLAC_AT_END;
+ }
+ *pBytesRead += pHeader->segmentCount;
+
+ for (i = 0; i < pHeader->segmentCount; ++i) {
+ *pCRC32 = drflac_crc32_byte(*pCRC32, pHeader->segmentTable[i]);
+ }
+
+ return DRFLAC_SUCCESS;
+}
+
+static drflac_result drflac_ogg__read_page_header(drflac_read_proc onRead, void* pUserData, drflac_ogg_page_header* pHeader, drflac_uint32* pBytesRead, drflac_uint32* pCRC32)
+{
+ drflac_uint8 id[4];
+
+ *pBytesRead = 0;
+
+ if (onRead(pUserData, id, 4) != 4) {
+ return DRFLAC_AT_END;
+ }
+ *pBytesRead += 4;
+
+ /* We need to read byte-by-byte until we find the OggS capture pattern. */
+ for (;;) {
+ if (drflac_ogg__is_capture_pattern(id)) {
+ drflac_result result;
+
+ *pCRC32 = DRFLAC_OGG_CAPTURE_PATTERN_CRC32;
+
+ result = drflac_ogg__read_page_header_after_capture_pattern(onRead, pUserData, pHeader, pBytesRead, pCRC32);
+ if (result == DRFLAC_SUCCESS) {
+ return DRFLAC_SUCCESS;
+ } else {
+ if (result == DRFLAC_CRC_MISMATCH) {
+ continue;
+ } else {
+ return result;
+ }
+ }
+ } else {
+ /* The first 4 bytes did not equal the capture pattern. Read the next byte and try again. */
+ id[0] = id[1];
+ id[1] = id[2];
+ id[2] = id[3];
+ if (onRead(pUserData, &id[3], 1) != 1) {
+ return DRFLAC_AT_END;
+ }
+ *pBytesRead += 1;
+ }
+ }
+}
+
+
+/*
+The main part of the Ogg encapsulation is the conversion from the physical Ogg bitstream to the native FLAC bitstream. It works
+in three general stages: Ogg Physical Bitstream -> Ogg/FLAC Logical Bitstream -> FLAC Native Bitstream. dr_flac is designed
+in such a way that the core sections assume everything is delivered in native format. Therefore, for each encapsulation type
+dr_flac is supporting there needs to be a layer sitting on top of the onRead and onSeek callbacks that ensures the bits read from
+the physical Ogg bitstream are converted and delivered in native FLAC format.
+*/
+typedef struct
+{
+ drflac_read_proc onRead; /* The original onRead callback from drflac_open() and family. */
+ drflac_seek_proc onSeek; /* The original onSeek callback from drflac_open() and family. */
+ void* pUserData; /* The user data passed on onRead and onSeek. This is the user data that was passed on drflac_open() and family. */
+ drflac_uint64 currentBytePos; /* The position of the byte we are sitting on in the physical byte stream. Used for efficient seeking. */
+ drflac_uint64 firstBytePos; /* The position of the first byte in the physical bitstream. Points to the start of the "OggS" identifier of the FLAC bos page. */
+ drflac_uint32 serialNumber; /* The serial number of the FLAC audio pages. This is determined by the initial header page that was read during initialization. */
+ drflac_ogg_page_header bosPageHeader; /* Used for seeking. */
+ drflac_ogg_page_header currentPageHeader;
+ drflac_uint32 bytesRemainingInPage;
+ drflac_uint32 pageDataSize;
+ drflac_uint8 pageData[DRFLAC_OGG_MAX_PAGE_SIZE];
+} drflac_oggbs; /* oggbs = Ogg Bitstream */
+
+static size_t drflac_oggbs__read_physical(drflac_oggbs* oggbs, void* bufferOut, size_t bytesToRead)
+{
+ size_t bytesActuallyRead = oggbs->onRead(oggbs->pUserData, bufferOut, bytesToRead);
+ oggbs->currentBytePos += bytesActuallyRead;
+
+ return bytesActuallyRead;
+}
+
+static drflac_bool32 drflac_oggbs__seek_physical(drflac_oggbs* oggbs, drflac_uint64 offset, drflac_seek_origin origin)
+{
+ if (origin == drflac_seek_origin_start) {
+ if (offset <= 0x7FFFFFFF) {
+ if (!oggbs->onSeek(oggbs->pUserData, (int)offset, drflac_seek_origin_start)) {
+ return DRFLAC_FALSE;
+ }
+ oggbs->currentBytePos = offset;
+
+ return DRFLAC_TRUE;
+ } else {
+ if (!oggbs->onSeek(oggbs->pUserData, 0x7FFFFFFF, drflac_seek_origin_start)) {
+ return DRFLAC_FALSE;
+ }
+ oggbs->currentBytePos = offset;
+
+ return drflac_oggbs__seek_physical(oggbs, offset - 0x7FFFFFFF, drflac_seek_origin_current);
+ }
+ } else {
+ while (offset > 0x7FFFFFFF) {
+ if (!oggbs->onSeek(oggbs->pUserData, 0x7FFFFFFF, drflac_seek_origin_current)) {
+ return DRFLAC_FALSE;
+ }
+ oggbs->currentBytePos += 0x7FFFFFFF;
+ offset -= 0x7FFFFFFF;
+ }
+
+ if (!oggbs->onSeek(oggbs->pUserData, (int)offset, drflac_seek_origin_current)) { /* <-- Safe cast thanks to the loop above. */
+ return DRFLAC_FALSE;
+ }
+ oggbs->currentBytePos += offset;
+
+ return DRFLAC_TRUE;
+ }
+}
+
+static drflac_bool32 drflac_oggbs__goto_next_page(drflac_oggbs* oggbs, drflac_ogg_crc_mismatch_recovery recoveryMethod)
+{
+ drflac_ogg_page_header header;
+ for (;;) {
+ drflac_uint32 crc32 = 0;
+ drflac_uint32 bytesRead;
+ drflac_uint32 pageBodySize;
+#ifndef DR_FLAC_NO_CRC
+ drflac_uint32 actualCRC32;
+#endif
+
+ if (drflac_ogg__read_page_header(oggbs->onRead, oggbs->pUserData, &header, &bytesRead, &crc32) != DRFLAC_SUCCESS) {
+ return DRFLAC_FALSE;
+ }
+ oggbs->currentBytePos += bytesRead;
+
+ pageBodySize = drflac_ogg__get_page_body_size(&header);
+ if (pageBodySize > DRFLAC_OGG_MAX_PAGE_SIZE) {
+ continue; /* Invalid page size. Assume it's corrupted and just move to the next page. */
+ }
+
+ if (header.serialNumber != oggbs->serialNumber) {
+ /* It's not a FLAC page. Skip it. */
+ if (pageBodySize > 0 && !drflac_oggbs__seek_physical(oggbs, pageBodySize, drflac_seek_origin_current)) {
+ return DRFLAC_FALSE;
+ }
+ continue;
+ }
+
+
+ /* We need to read the entire page and then do a CRC check on it. If there's a CRC mismatch we need to skip this page. */
+ if (drflac_oggbs__read_physical(oggbs, oggbs->pageData, pageBodySize) != pageBodySize) {
+ return DRFLAC_FALSE;
+ }
+ oggbs->pageDataSize = pageBodySize;
+
+#ifndef DR_FLAC_NO_CRC
+ actualCRC32 = drflac_crc32_buffer(crc32, oggbs->pageData, oggbs->pageDataSize);
+ if (actualCRC32 != header.checksum) {
+ if (recoveryMethod == drflac_ogg_recover_on_crc_mismatch) {
+ continue; /* CRC mismatch. Skip this page. */
+ } else {
+ /*
+ Even though we are failing on a CRC mismatch, we still want our stream to be in a good state. Therefore we
+ go to the next valid page to ensure we're in a good state, but return false to let the caller know that the
+ seek did not fully complete.
+ */
+ drflac_oggbs__goto_next_page(oggbs, drflac_ogg_recover_on_crc_mismatch);
+ return DRFLAC_FALSE;
+ }
+ }
+#else
+ (void)recoveryMethod; /* <-- Silence a warning. */
+#endif
+
+ oggbs->currentPageHeader = header;
+ oggbs->bytesRemainingInPage = pageBodySize;
+ return DRFLAC_TRUE;
+ }
+}
+
+/* Function below is unused at the moment, but I might be re-adding it later. */
+#if 0
+static drflac_uint8 drflac_oggbs__get_current_segment_index(drflac_oggbs* oggbs, drflac_uint8* pBytesRemainingInSeg)
+{
+ drflac_uint32 bytesConsumedInPage = drflac_ogg__get_page_body_size(&oggbs->currentPageHeader) - oggbs->bytesRemainingInPage;
+ drflac_uint8 iSeg = 0;
+ drflac_uint32 iByte = 0;
+ while (iByte < bytesConsumedInPage) {
+ drflac_uint8 segmentSize = oggbs->currentPageHeader.segmentTable[iSeg];
+ if (iByte + segmentSize > bytesConsumedInPage) {
+ break;
+ } else {
+ iSeg += 1;
+ iByte += segmentSize;
+ }
+ }
+
+ *pBytesRemainingInSeg = oggbs->currentPageHeader.segmentTable[iSeg] - (drflac_uint8)(bytesConsumedInPage - iByte);
+ return iSeg;
+}
+
+static drflac_bool32 drflac_oggbs__seek_to_next_packet(drflac_oggbs* oggbs)
+{
+ /* The current packet ends when we get to the segment with a lacing value of < 255 which is not at the end of a page. */
+ for (;;) {
+ drflac_bool32 atEndOfPage = DRFLAC_FALSE;
+
+ drflac_uint8 bytesRemainingInSeg;
+ drflac_uint8 iFirstSeg = drflac_oggbs__get_current_segment_index(oggbs, &bytesRemainingInSeg);
+
+ drflac_uint32 bytesToEndOfPacketOrPage = bytesRemainingInSeg;
+ for (drflac_uint8 iSeg = iFirstSeg; iSeg < oggbs->currentPageHeader.segmentCount; ++iSeg) {
+ drflac_uint8 segmentSize = oggbs->currentPageHeader.segmentTable[iSeg];
+ if (segmentSize < 255) {
+ if (iSeg == oggbs->currentPageHeader.segmentCount-1) {
+ atEndOfPage = DRFLAC_TRUE;
+ }
+
+ break;
+ }
+
+ bytesToEndOfPacketOrPage += segmentSize;
+ }
+
+ /*
+ At this point we will have found either the packet or the end of the page. If were at the end of the page we'll
+ want to load the next page and keep searching for the end of the packet.
+ */
+ drflac_oggbs__seek_physical(oggbs, bytesToEndOfPacketOrPage, drflac_seek_origin_current);
+ oggbs->bytesRemainingInPage -= bytesToEndOfPacketOrPage;
+
+ if (atEndOfPage) {
+ /*
+ We're potentially at the next packet, but we need to check the next page first to be sure because the packet may
+ straddle pages.
+ */
+ if (!drflac_oggbs__goto_next_page(oggbs)) {
+ return DRFLAC_FALSE;
+ }
+
+ /* If it's a fresh packet it most likely means we're at the next packet. */
+ if ((oggbs->currentPageHeader.headerType & 0x01) == 0) {
+ return DRFLAC_TRUE;
+ }
+ } else {
+ /* We're at the next packet. */
+ return DRFLAC_TRUE;
+ }
+ }
+}
+
+static drflac_bool32 drflac_oggbs__seek_to_next_frame(drflac_oggbs* oggbs)
+{
+ /* The bitstream should be sitting on the first byte just after the header of the frame. */
+
+ /* What we're actually doing here is seeking to the start of the next packet. */
+ return drflac_oggbs__seek_to_next_packet(oggbs);
+}
+#endif
+
+static size_t drflac__on_read_ogg(void* pUserData, void* bufferOut, size_t bytesToRead)
+{
+ drflac_oggbs* oggbs = (drflac_oggbs*)pUserData;
+ drflac_uint8* pRunningBufferOut = (drflac_uint8*)bufferOut;
+ size_t bytesRead = 0;
+
+ DRFLAC_ASSERT(oggbs != NULL);
+ DRFLAC_ASSERT(pRunningBufferOut != NULL);
+
+ /* Reading is done page-by-page. If we've run out of bytes in the page we need to move to the next one. */
+ while (bytesRead < bytesToRead) {
+ size_t bytesRemainingToRead = bytesToRead - bytesRead;
+
+ if (oggbs->bytesRemainingInPage >= bytesRemainingToRead) {
+ DRFLAC_COPY_MEMORY(pRunningBufferOut, oggbs->pageData + (oggbs->pageDataSize - oggbs->bytesRemainingInPage), bytesRemainingToRead);
+ bytesRead += bytesRemainingToRead;
+ oggbs->bytesRemainingInPage -= (drflac_uint32)bytesRemainingToRead;
+ break;
+ }
+
+ /* If we get here it means some of the requested data is contained in the next pages. */
+ if (oggbs->bytesRemainingInPage > 0) {
+ DRFLAC_COPY_MEMORY(pRunningBufferOut, oggbs->pageData + (oggbs->pageDataSize - oggbs->bytesRemainingInPage), oggbs->bytesRemainingInPage);
+ bytesRead += oggbs->bytesRemainingInPage;
+ pRunningBufferOut += oggbs->bytesRemainingInPage;
+ oggbs->bytesRemainingInPage = 0;
+ }
+
+ DRFLAC_ASSERT(bytesRemainingToRead > 0);
+ if (!drflac_oggbs__goto_next_page(oggbs, drflac_ogg_recover_on_crc_mismatch)) {
+ break; /* Failed to go to the next page. Might have simply hit the end of the stream. */
+ }
+ }
+
+ return bytesRead;
+}
+
+static drflac_bool32 drflac__on_seek_ogg(void* pUserData, int offset, drflac_seek_origin origin)
+{
+ drflac_oggbs* oggbs = (drflac_oggbs*)pUserData;
+ int bytesSeeked = 0;
+
+ DRFLAC_ASSERT(oggbs != NULL);
+ DRFLAC_ASSERT(offset >= 0); /* <-- Never seek backwards. */
+
+ /* Seeking is always forward which makes things a lot simpler. */
+ if (origin == drflac_seek_origin_start) {
+ if (!drflac_oggbs__seek_physical(oggbs, (int)oggbs->firstBytePos, drflac_seek_origin_start)) {
+ return DRFLAC_FALSE;
+ }
+
+ if (!drflac_oggbs__goto_next_page(oggbs, drflac_ogg_fail_on_crc_mismatch)) {
+ return DRFLAC_FALSE;
+ }
+
+ return drflac__on_seek_ogg(pUserData, offset, drflac_seek_origin_current);
+ }
+
+ DRFLAC_ASSERT(origin == drflac_seek_origin_current);
+
+ while (bytesSeeked < offset) {
+ int bytesRemainingToSeek = offset - bytesSeeked;
+ DRFLAC_ASSERT(bytesRemainingToSeek >= 0);
+
+ if (oggbs->bytesRemainingInPage >= (size_t)bytesRemainingToSeek) {
+ bytesSeeked += bytesRemainingToSeek;
+ (void)bytesSeeked; /* <-- Silence a dead store warning emitted by Clang Static Analyzer. */
+ oggbs->bytesRemainingInPage -= bytesRemainingToSeek;
+ break;
+ }
+
+ /* If we get here it means some of the requested data is contained in the next pages. */
+ if (oggbs->bytesRemainingInPage > 0) {
+ bytesSeeked += (int)oggbs->bytesRemainingInPage;
+ oggbs->bytesRemainingInPage = 0;
+ }
+
+ DRFLAC_ASSERT(bytesRemainingToSeek > 0);
+ if (!drflac_oggbs__goto_next_page(oggbs, drflac_ogg_fail_on_crc_mismatch)) {
+ /* Failed to go to the next page. We either hit the end of the stream or had a CRC mismatch. */
+ return DRFLAC_FALSE;
+ }
+ }
+
+ return DRFLAC_TRUE;
+}
+
+
+static drflac_bool32 drflac_ogg__seek_to_pcm_frame(drflac* pFlac, drflac_uint64 pcmFrameIndex)
+{
+ drflac_oggbs* oggbs = (drflac_oggbs*)pFlac->_oggbs;
+ drflac_uint64 originalBytePos;
+ drflac_uint64 runningGranulePosition;
+ drflac_uint64 runningFrameBytePos;
+ drflac_uint64 runningPCMFrameCount;
+
+ DRFLAC_ASSERT(oggbs != NULL);
+
+ originalBytePos = oggbs->currentBytePos; /* For recovery. Points to the OggS identifier. */
+
+ /* First seek to the first frame. */
+ if (!drflac__seek_to_byte(&pFlac->bs, pFlac->firstFLACFramePosInBytes)) {
+ return DRFLAC_FALSE;
+ }
+ oggbs->bytesRemainingInPage = 0;
+
+ runningGranulePosition = 0;
+ for (;;) {
+ if (!drflac_oggbs__goto_next_page(oggbs, drflac_ogg_recover_on_crc_mismatch)) {
+ drflac_oggbs__seek_physical(oggbs, originalBytePos, drflac_seek_origin_start);
+ return DRFLAC_FALSE; /* Never did find that sample... */
+ }
+
+ runningFrameBytePos = oggbs->currentBytePos - drflac_ogg__get_page_header_size(&oggbs->currentPageHeader) - oggbs->pageDataSize;
+ if (oggbs->currentPageHeader.granulePosition >= pcmFrameIndex) {
+ break; /* The sample is somewhere in the previous page. */
+ }
+
+ /*
+ At this point we know the sample is not in the previous page. It could possibly be in this page. For simplicity we
+ disregard any pages that do not begin a fresh packet.
+ */
+ if ((oggbs->currentPageHeader.headerType & 0x01) == 0) { /* <-- Is it a fresh page? */
+ if (oggbs->currentPageHeader.segmentTable[0] >= 2) {
+ drflac_uint8 firstBytesInPage[2];
+ firstBytesInPage[0] = oggbs->pageData[0];
+ firstBytesInPage[1] = oggbs->pageData[1];
+
+ if ((firstBytesInPage[0] == 0xFF) && (firstBytesInPage[1] & 0xFC) == 0xF8) { /* <-- Does the page begin with a frame's sync code? */
+ runningGranulePosition = oggbs->currentPageHeader.granulePosition;
+ }
+
+ continue;
+ }
+ }
+ }
+
+ /*
+ We found the page that that is closest to the sample, so now we need to find it. The first thing to do is seek to the
+ start of that page. In the loop above we checked that it was a fresh page which means this page is also the start of
+ a new frame. This property means that after we've seeked to the page we can immediately start looping over frames until
+ we find the one containing the target sample.
+ */
+ if (!drflac_oggbs__seek_physical(oggbs, runningFrameBytePos, drflac_seek_origin_start)) {
+ return DRFLAC_FALSE;
+ }
+ if (!drflac_oggbs__goto_next_page(oggbs, drflac_ogg_recover_on_crc_mismatch)) {
+ return DRFLAC_FALSE;
+ }
+
+ /*
+ At this point we'll be sitting on the first byte of the frame header of the first frame in the page. We just keep
+ looping over these frames until we find the one containing the sample we're after.
+ */
+ runningPCMFrameCount = runningGranulePosition;
+ for (;;) {
+ /*
+ There are two ways to find the sample and seek past irrelevant frames:
+ 1) Use the native FLAC decoder.
+ 2) Use Ogg's framing system.
+
+ Both of these options have their own pros and cons. Using the native FLAC decoder is slower because it needs to
+ do a full decode of the frame. Using Ogg's framing system is faster, but more complicated and involves some code
+ duplication for the decoding of frame headers.
+
+ Another thing to consider is that using the Ogg framing system will perform direct seeking of the physical Ogg
+ bitstream. This is important to consider because it means we cannot read data from the drflac_bs object using the
+ standard drflac__*() APIs because that will read in extra data for its own internal caching which in turn breaks
+ the positioning of the read pointer of the physical Ogg bitstream. Therefore, anything that would normally be read
+ using the native FLAC decoding APIs, such as drflac__read_next_flac_frame_header(), need to be re-implemented so as to
+ avoid the use of the drflac_bs object.
+
+ Considering these issues, I have decided to use the slower native FLAC decoding method for the following reasons:
+ 1) Seeking is already partially accelerated using Ogg's paging system in the code block above.
+ 2) Seeking in an Ogg encapsulated FLAC stream is probably quite uncommon.
+ 3) Simplicity.
+ */
+ drflac_uint64 firstPCMFrameInFLACFrame = 0;
+ drflac_uint64 lastPCMFrameInFLACFrame = 0;
+ drflac_uint64 pcmFrameCountInThisFrame;
+
+ if (!drflac__read_next_flac_frame_header(&pFlac->bs, pFlac->bitsPerSample, &pFlac->currentFLACFrame.header)) {
+ return DRFLAC_FALSE;
+ }
+
+ drflac__get_pcm_frame_range_of_current_flac_frame(pFlac, &firstPCMFrameInFLACFrame, &lastPCMFrameInFLACFrame);
+
+ pcmFrameCountInThisFrame = (lastPCMFrameInFLACFrame - firstPCMFrameInFLACFrame) + 1;
+
+ /* If we are seeking to the end of the file and we've just hit it, we're done. */
+ if (pcmFrameIndex == pFlac->totalPCMFrameCount && (runningPCMFrameCount + pcmFrameCountInThisFrame) == pFlac->totalPCMFrameCount) {
+ drflac_result result = drflac__decode_flac_frame(pFlac);
+ if (result == DRFLAC_SUCCESS) {
+ pFlac->currentPCMFrame = pcmFrameIndex;
+ pFlac->currentFLACFrame.pcmFramesRemaining = 0;
+ return DRFLAC_TRUE;
+ } else {
+ return DRFLAC_FALSE;
+ }
+ }
+
+ if (pcmFrameIndex < (runningPCMFrameCount + pcmFrameCountInThisFrame)) {
+ /*
+ The sample should be in this FLAC frame. We need to fully decode it, however if it's an invalid frame (a CRC mismatch), we need to pretend
+ it never existed and keep iterating.
+ */
+ drflac_result result = drflac__decode_flac_frame(pFlac);
+ if (result == DRFLAC_SUCCESS) {
+ /* The frame is valid. We just need to skip over some samples to ensure it's sample-exact. */
+ drflac_uint64 pcmFramesToDecode = (size_t)(pcmFrameIndex - runningPCMFrameCount); /* <-- Safe cast because the maximum number of samples in a frame is 65535. */
+ if (pcmFramesToDecode == 0) {
+ return DRFLAC_TRUE;
+ }
+
+ pFlac->currentPCMFrame = runningPCMFrameCount;
+
+ return drflac__seek_forward_by_pcm_frames(pFlac, pcmFramesToDecode) == pcmFramesToDecode; /* <-- If this fails, something bad has happened (it should never fail). */
+ } else {
+ if (result == DRFLAC_CRC_MISMATCH) {
+ continue; /* CRC mismatch. Pretend this frame never existed. */
+ } else {
+ return DRFLAC_FALSE;
+ }
+ }
+ } else {
+ /*
+ It's not in this frame. We need to seek past the frame, but check if there was a CRC mismatch. If so, we pretend this
+ frame never existed and leave the running sample count untouched.
+ */
+ drflac_result result = drflac__seek_to_next_flac_frame(pFlac);
+ if (result == DRFLAC_SUCCESS) {
+ runningPCMFrameCount += pcmFrameCountInThisFrame;
+ } else {
+ if (result == DRFLAC_CRC_MISMATCH) {
+ continue; /* CRC mismatch. Pretend this frame never existed. */
+ } else {
+ return DRFLAC_FALSE;
+ }
+ }
+ }
+ }
+}
+
+
+
+static drflac_bool32 drflac__init_private__ogg(drflac_init_info* pInit, drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, void* pUserData, void* pUserDataMD, drflac_bool32 relaxed)
+{
+ drflac_ogg_page_header header;
+ drflac_uint32 crc32 = DRFLAC_OGG_CAPTURE_PATTERN_CRC32;
+ drflac_uint32 bytesRead = 0;
+
+ /* Pre Condition: The bit stream should be sitting just past the 4-byte OggS capture pattern. */
+ (void)relaxed;
+
+ pInit->container = drflac_container_ogg;
+ pInit->oggFirstBytePos = 0;
+
+ /*
+ We'll get here if the first 4 bytes of the stream were the OggS capture pattern, however it doesn't necessarily mean the
+ stream includes FLAC encoded audio. To check for this we need to scan the beginning-of-stream page markers and check if
+ any match the FLAC specification. Important to keep in mind that the stream may be multiplexed.
+ */
+ if (drflac_ogg__read_page_header_after_capture_pattern(onRead, pUserData, &header, &bytesRead, &crc32) != DRFLAC_SUCCESS) {
+ return DRFLAC_FALSE;
+ }
+ pInit->runningFilePos += bytesRead;
+
+ for (;;) {
+ int pageBodySize;
+
+ /* Break if we're past the beginning of stream page. */
+ if ((header.headerType & 0x02) == 0) {
+ return DRFLAC_FALSE;
+ }
+
+ /* Check if it's a FLAC header. */
+ pageBodySize = drflac_ogg__get_page_body_size(&header);
+ if (pageBodySize == 51) { /* 51 = the lacing value of the FLAC header packet. */
+ /* It could be a FLAC page... */
+ drflac_uint32 bytesRemainingInPage = pageBodySize;
+ drflac_uint8 packetType;
+
+ if (onRead(pUserData, &packetType, 1) != 1) {
+ return DRFLAC_FALSE;
+ }
+
+ bytesRemainingInPage -= 1;
+ if (packetType == 0x7F) {
+ /* Increasingly more likely to be a FLAC page... */
+ drflac_uint8 sig[4];
+ if (onRead(pUserData, sig, 4) != 4) {
+ return DRFLAC_FALSE;
+ }
+
+ bytesRemainingInPage -= 4;
+ if (sig[0] == 'F' && sig[1] == 'L' && sig[2] == 'A' && sig[3] == 'C') {
+ /* Almost certainly a FLAC page... */
+ drflac_uint8 mappingVersion[2];
+ if (onRead(pUserData, mappingVersion, 2) != 2) {
+ return DRFLAC_FALSE;
+ }
+
+ if (mappingVersion[0] != 1) {
+ return DRFLAC_FALSE; /* Only supporting version 1.x of the Ogg mapping. */
+ }
+
+ /*
+ The next 2 bytes are the non-audio packets, not including this one. We don't care about this because we're going to
+ be handling it in a generic way based on the serial number and packet types.
+ */
+ if (!onSeek(pUserData, 2, drflac_seek_origin_current)) {
+ return DRFLAC_FALSE;
+ }
+
+ /* Expecting the native FLAC signature "fLaC". */
+ if (onRead(pUserData, sig, 4) != 4) {
+ return DRFLAC_FALSE;
+ }
+
+ if (sig[0] == 'f' && sig[1] == 'L' && sig[2] == 'a' && sig[3] == 'C') {
+ /* The remaining data in the page should be the STREAMINFO block. */
+ drflac_streaminfo streaminfo;
+ drflac_uint8 isLastBlock;
+ drflac_uint8 blockType;
+ drflac_uint32 blockSize;
+ if (!drflac__read_and_decode_block_header(onRead, pUserData, &isLastBlock, &blockType, &blockSize)) {
+ return DRFLAC_FALSE;
+ }
+
+ if (blockType != DRFLAC_METADATA_BLOCK_TYPE_STREAMINFO || blockSize != 34) {
+ return DRFLAC_FALSE; /* Invalid block type. First block must be the STREAMINFO block. */
+ }
+
+ if (drflac__read_streaminfo(onRead, pUserData, &streaminfo)) {
+ /* Success! */
+ pInit->hasStreamInfoBlock = DRFLAC_TRUE;
+ pInit->sampleRate = streaminfo.sampleRate;
+ pInit->channels = streaminfo.channels;
+ pInit->bitsPerSample = streaminfo.bitsPerSample;
+ pInit->totalPCMFrameCount = streaminfo.totalPCMFrameCount;
+ pInit->maxBlockSizeInPCMFrames = streaminfo.maxBlockSizeInPCMFrames;
+ pInit->hasMetadataBlocks = !isLastBlock;
+
+ if (onMeta) {
+ drflac_metadata metadata;
+ metadata.type = DRFLAC_METADATA_BLOCK_TYPE_STREAMINFO;
+ metadata.pRawData = NULL;
+ metadata.rawDataSize = 0;
+ metadata.data.streaminfo = streaminfo;
+ onMeta(pUserDataMD, &metadata);
+ }
+
+ pInit->runningFilePos += pageBodySize;
+ pInit->oggFirstBytePos = pInit->runningFilePos - 79; /* Subtracting 79 will place us right on top of the "OggS" identifier of the FLAC bos page. */
+ pInit->oggSerial = header.serialNumber;
+ pInit->oggBosHeader = header;
+ break;
+ } else {
+ /* Failed to read STREAMINFO block. Aww, so close... */
+ return DRFLAC_FALSE;
+ }
+ } else {
+ /* Invalid file. */
+ return DRFLAC_FALSE;
+ }
+ } else {
+ /* Not a FLAC header. Skip it. */
+ if (!onSeek(pUserData, bytesRemainingInPage, drflac_seek_origin_current)) {
+ return DRFLAC_FALSE;
+ }
+ }
+ } else {
+ /* Not a FLAC header. Seek past the entire page and move on to the next. */
+ if (!onSeek(pUserData, bytesRemainingInPage, drflac_seek_origin_current)) {
+ return DRFLAC_FALSE;
+ }
+ }
+ } else {
+ if (!onSeek(pUserData, pageBodySize, drflac_seek_origin_current)) {
+ return DRFLAC_FALSE;
+ }
+ }
+
+ pInit->runningFilePos += pageBodySize;
+
+
+ /* Read the header of the next page. */
+ if (drflac_ogg__read_page_header(onRead, pUserData, &header, &bytesRead, &crc32) != DRFLAC_SUCCESS) {
+ return DRFLAC_FALSE;
+ }
+ pInit->runningFilePos += bytesRead;
+ }
+
+ /*
+ If we get here it means we found a FLAC audio stream. We should be sitting on the first byte of the header of the next page. The next
+ packets in the FLAC logical stream contain the metadata. The only thing left to do in the initialization phase for Ogg is to create the
+ Ogg bistream object.
+ */
+ pInit->hasMetadataBlocks = DRFLAC_TRUE; /* <-- Always have at least VORBIS_COMMENT metadata block. */
+ return DRFLAC_TRUE;
+}
+#endif
+
+static drflac_bool32 drflac__init_private(drflac_init_info* pInit, drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, drflac_container container, void* pUserData, void* pUserDataMD)
+{
+ drflac_bool32 relaxed;
+ drflac_uint8 id[4];
+
+ if (pInit == NULL || onRead == NULL || onSeek == NULL) {
+ return DRFLAC_FALSE;
+ }
+
+ DRFLAC_ZERO_MEMORY(pInit, sizeof(*pInit));
+ pInit->onRead = onRead;
+ pInit->onSeek = onSeek;
+ pInit->onMeta = onMeta;
+ pInit->container = container;
+ pInit->pUserData = pUserData;
+ pInit->pUserDataMD = pUserDataMD;
+
+ pInit->bs.onRead = onRead;
+ pInit->bs.onSeek = onSeek;
+ pInit->bs.pUserData = pUserData;
+ drflac__reset_cache(&pInit->bs);
+
+
+ /* If the container is explicitly defined then we can try opening in relaxed mode. */
+ relaxed = container != drflac_container_unknown;
+
+ /* Skip over any ID3 tags. */
+ for (;;) {
+ if (onRead(pUserData, id, 4) != 4) {
+ return DRFLAC_FALSE; /* Ran out of data. */
+ }
+ pInit->runningFilePos += 4;
+
+ if (id[0] == 'I' && id[1] == 'D' && id[2] == '3') {
+ drflac_uint8 header[6];
+ drflac_uint8 flags;
+ drflac_uint32 headerSize;
+
+ if (onRead(pUserData, header, 6) != 6) {
+ return DRFLAC_FALSE; /* Ran out of data. */
+ }
+ pInit->runningFilePos += 6;
+
+ flags = header[1];
+
+ DRFLAC_COPY_MEMORY(&headerSize, header+2, 4);
+ headerSize = drflac__unsynchsafe_32(drflac__be2host_32(headerSize));
+ if (flags & 0x10) {
+ headerSize += 10;
+ }
+
+ if (!onSeek(pUserData, headerSize, drflac_seek_origin_current)) {
+ return DRFLAC_FALSE; /* Failed to seek past the tag. */
+ }
+ pInit->runningFilePos += headerSize;
+ } else {
+ break;
+ }
+ }
+
+ if (id[0] == 'f' && id[1] == 'L' && id[2] == 'a' && id[3] == 'C') {
+ return drflac__init_private__native(pInit, onRead, onSeek, onMeta, pUserData, pUserDataMD, relaxed);
+ }
+#ifndef DR_FLAC_NO_OGG
+ if (id[0] == 'O' && id[1] == 'g' && id[2] == 'g' && id[3] == 'S') {
+ return drflac__init_private__ogg(pInit, onRead, onSeek, onMeta, pUserData, pUserDataMD, relaxed);
+ }
+#endif
+
+ /* If we get here it means we likely don't have a header. Try opening in relaxed mode, if applicable. */
+ if (relaxed) {
+ if (container == drflac_container_native) {
+ return drflac__init_private__native(pInit, onRead, onSeek, onMeta, pUserData, pUserDataMD, relaxed);
+ }
+#ifndef DR_FLAC_NO_OGG
+ if (container == drflac_container_ogg) {
+ return drflac__init_private__ogg(pInit, onRead, onSeek, onMeta, pUserData, pUserDataMD, relaxed);
+ }
+#endif
+ }
+
+ /* Unsupported container. */
+ return DRFLAC_FALSE;
+}
+
+static void drflac__init_from_info(drflac* pFlac, const drflac_init_info* pInit)
+{
+ DRFLAC_ASSERT(pFlac != NULL);
+ DRFLAC_ASSERT(pInit != NULL);
+
+ DRFLAC_ZERO_MEMORY(pFlac, sizeof(*pFlac));
+ pFlac->bs = pInit->bs;
+ pFlac->onMeta = pInit->onMeta;
+ pFlac->pUserDataMD = pInit->pUserDataMD;
+ pFlac->maxBlockSizeInPCMFrames = pInit->maxBlockSizeInPCMFrames;
+ pFlac->sampleRate = pInit->sampleRate;
+ pFlac->channels = (drflac_uint8)pInit->channels;
+ pFlac->bitsPerSample = (drflac_uint8)pInit->bitsPerSample;
+ pFlac->totalPCMFrameCount = pInit->totalPCMFrameCount;
+ pFlac->container = pInit->container;
+}
+
+
+static drflac* drflac_open_with_metadata_private(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, drflac_container container, void* pUserData, void* pUserDataMD, const drflac_allocation_callbacks* pAllocationCallbacks)
+{
+ drflac_init_info init;
+ drflac_uint32 allocationSize;
+ drflac_uint32 wholeSIMDVectorCountPerChannel;
+ drflac_uint32 decodedSamplesAllocationSize;
+#ifndef DR_FLAC_NO_OGG
+ drflac_oggbs* pOggbs = NULL;
+#endif
+ drflac_uint64 firstFramePos;
+ drflac_uint64 seektablePos;
+ drflac_uint32 seekpointCount;
+ drflac_allocation_callbacks allocationCallbacks;
+ drflac* pFlac;
+
+ /* CPU support first. */
+ drflac__init_cpu_caps();
+
+ if (!drflac__init_private(&init, onRead, onSeek, onMeta, container, pUserData, pUserDataMD)) {
+ return NULL;
+ }
+
+ if (pAllocationCallbacks != NULL) {
+ allocationCallbacks = *pAllocationCallbacks;
+ if (allocationCallbacks.onFree == NULL || (allocationCallbacks.onMalloc == NULL && allocationCallbacks.onRealloc == NULL)) {
+ return NULL; /* Invalid allocation callbacks. */
+ }
+ } else {
+ allocationCallbacks.pUserData = NULL;
+ allocationCallbacks.onMalloc = drflac__malloc_default;
+ allocationCallbacks.onRealloc = drflac__realloc_default;
+ allocationCallbacks.onFree = drflac__free_default;
+ }
+
+
+ /*
+ The size of the allocation for the drflac object needs to be large enough to fit the following:
+ 1) The main members of the drflac structure
+ 2) A block of memory large enough to store the decoded samples of the largest frame in the stream
+ 3) If the container is Ogg, a drflac_oggbs object
+
+ The complicated part of the allocation is making sure there's enough room the decoded samples, taking into consideration
+ the different SIMD instruction sets.
+ */
+ allocationSize = sizeof(drflac);
+
+ /*
+ The allocation size for decoded frames depends on the number of 32-bit integers that fit inside the largest SIMD vector
+ we are supporting.
+ */
+ if ((init.maxBlockSizeInPCMFrames % (DRFLAC_MAX_SIMD_VECTOR_SIZE / sizeof(drflac_int32))) == 0) {
+ wholeSIMDVectorCountPerChannel = (init.maxBlockSizeInPCMFrames / (DRFLAC_MAX_SIMD_VECTOR_SIZE / sizeof(drflac_int32)));
+ } else {
+ wholeSIMDVectorCountPerChannel = (init.maxBlockSizeInPCMFrames / (DRFLAC_MAX_SIMD_VECTOR_SIZE / sizeof(drflac_int32))) + 1;
+ }
+
+ decodedSamplesAllocationSize = wholeSIMDVectorCountPerChannel * DRFLAC_MAX_SIMD_VECTOR_SIZE * init.channels;
+
+ allocationSize += decodedSamplesAllocationSize;
+ allocationSize += DRFLAC_MAX_SIMD_VECTOR_SIZE; /* Allocate extra bytes to ensure we have enough for alignment. */
+
+#ifndef DR_FLAC_NO_OGG
+ /* There's additional data required for Ogg streams. */
+ if (init.container == drflac_container_ogg) {
+ allocationSize += sizeof(drflac_oggbs);
+
+ pOggbs = (drflac_oggbs*)drflac__malloc_from_callbacks(sizeof(*pOggbs), &allocationCallbacks);
+ if (pOggbs == NULL) {
+ return NULL; /*DRFLAC_OUT_OF_MEMORY;*/
+ }
+
+ DRFLAC_ZERO_MEMORY(pOggbs, sizeof(*pOggbs));
+ pOggbs->onRead = onRead;
+ pOggbs->onSeek = onSeek;
+ pOggbs->pUserData = pUserData;
+ pOggbs->currentBytePos = init.oggFirstBytePos;
+ pOggbs->firstBytePos = init.oggFirstBytePos;
+ pOggbs->serialNumber = init.oggSerial;
+ pOggbs->bosPageHeader = init.oggBosHeader;
+ pOggbs->bytesRemainingInPage = 0;
+ }
+#endif
+
+ /*
+ This part is a bit awkward. We need to load the seektable so that it can be referenced in-memory, but I want the drflac object to
+ consist of only a single heap allocation. To this, the size of the seek table needs to be known, which we determine when reading
+ and decoding the metadata.
+ */
+ firstFramePos = 42; /* <-- We know we are at byte 42 at this point. */
+ seektablePos = 0;
+ seekpointCount = 0;
+ if (init.hasMetadataBlocks) {
+ drflac_read_proc onReadOverride = onRead;
+ drflac_seek_proc onSeekOverride = onSeek;
+ void* pUserDataOverride = pUserData;
+
+#ifndef DR_FLAC_NO_OGG
+ if (init.container == drflac_container_ogg) {
+ onReadOverride = drflac__on_read_ogg;
+ onSeekOverride = drflac__on_seek_ogg;
+ pUserDataOverride = (void*)pOggbs;
+ }
+#endif
+
+ if (!drflac__read_and_decode_metadata(onReadOverride, onSeekOverride, onMeta, pUserDataOverride, pUserDataMD, &firstFramePos, &seektablePos, &seekpointCount, &allocationCallbacks)) {
+ #ifndef DR_FLAC_NO_OGG
+ drflac__free_from_callbacks(pOggbs, &allocationCallbacks);
+ #endif
+ return NULL;
+ }
+
+ allocationSize += seekpointCount * sizeof(drflac_seekpoint);
+ }
+
+
+ pFlac = (drflac*)drflac__malloc_from_callbacks(allocationSize, &allocationCallbacks);
+ if (pFlac == NULL) {
+ #ifndef DR_FLAC_NO_OGG
+ drflac__free_from_callbacks(pOggbs, &allocationCallbacks);
+ #endif
+ return NULL;
+ }
+
+ drflac__init_from_info(pFlac, &init);
+ pFlac->allocationCallbacks = allocationCallbacks;
+ pFlac->pDecodedSamples = (drflac_int32*)drflac_align((size_t)pFlac->pExtraData, DRFLAC_MAX_SIMD_VECTOR_SIZE);
+
+#ifndef DR_FLAC_NO_OGG
+ if (init.container == drflac_container_ogg) {
+ drflac_oggbs* pInternalOggbs = (drflac_oggbs*)((drflac_uint8*)pFlac->pDecodedSamples + decodedSamplesAllocationSize + (seekpointCount * sizeof(drflac_seekpoint)));
+ DRFLAC_COPY_MEMORY(pInternalOggbs, pOggbs, sizeof(*pOggbs));
+
+ /* At this point the pOggbs object has been handed over to pInternalOggbs and can be freed. */
+ drflac__free_from_callbacks(pOggbs, &allocationCallbacks);
+ pOggbs = NULL;
+
+ /* The Ogg bistream needs to be layered on top of the original bitstream. */
+ pFlac->bs.onRead = drflac__on_read_ogg;
+ pFlac->bs.onSeek = drflac__on_seek_ogg;
+ pFlac->bs.pUserData = (void*)pInternalOggbs;
+ pFlac->_oggbs = (void*)pInternalOggbs;
+ }
+#endif
+
+ pFlac->firstFLACFramePosInBytes = firstFramePos;
+
+ /* NOTE: Seektables are not currently compatible with Ogg encapsulation (Ogg has its own accelerated seeking system). I may change this later, so I'm leaving this here for now. */
+#ifndef DR_FLAC_NO_OGG
+ if (init.container == drflac_container_ogg)
+ {
+ pFlac->pSeekpoints = NULL;
+ pFlac->seekpointCount = 0;
+ }
+ else
+#endif
+ {
+ /* If we have a seektable we need to load it now, making sure we move back to where we were previously. */
+ if (seektablePos != 0) {
+ pFlac->seekpointCount = seekpointCount;
+ pFlac->pSeekpoints = (drflac_seekpoint*)((drflac_uint8*)pFlac->pDecodedSamples + decodedSamplesAllocationSize);
+
+ DRFLAC_ASSERT(pFlac->bs.onSeek != NULL);
+ DRFLAC_ASSERT(pFlac->bs.onRead != NULL);
+
+ /* Seek to the seektable, then just read directly into our seektable buffer. */
+ if (pFlac->bs.onSeek(pFlac->bs.pUserData, (int)seektablePos, drflac_seek_origin_start)) {
+ drflac_uint32 iSeekpoint;
+
+ for (iSeekpoint = 0; iSeekpoint < seekpointCount; iSeekpoint += 1) {
+ if (pFlac->bs.onRead(pFlac->bs.pUserData, pFlac->pSeekpoints + iSeekpoint, DRFLAC_SEEKPOINT_SIZE_IN_BYTES) == DRFLAC_SEEKPOINT_SIZE_IN_BYTES) {
+ /* Endian swap. */
+ pFlac->pSeekpoints[iSeekpoint].firstPCMFrame = drflac__be2host_64(pFlac->pSeekpoints[iSeekpoint].firstPCMFrame);
+ pFlac->pSeekpoints[iSeekpoint].flacFrameOffset = drflac__be2host_64(pFlac->pSeekpoints[iSeekpoint].flacFrameOffset);
+ pFlac->pSeekpoints[iSeekpoint].pcmFrameCount = drflac__be2host_16(pFlac->pSeekpoints[iSeekpoint].pcmFrameCount);
+ } else {
+ /* Failed to read the seektable. Pretend we don't have one. */
+ pFlac->pSeekpoints = NULL;
+ pFlac->seekpointCount = 0;
+ break;
+ }
+ }
+
+ /* We need to seek back to where we were. If this fails it's a critical error. */
+ if (!pFlac->bs.onSeek(pFlac->bs.pUserData, (int)pFlac->firstFLACFramePosInBytes, drflac_seek_origin_start)) {
+ drflac__free_from_callbacks(pFlac, &allocationCallbacks);
+ return NULL;
+ }
+ } else {
+ /* Failed to seek to the seektable. Ominous sign, but for now we can just pretend we don't have one. */
+ pFlac->pSeekpoints = NULL;
+ pFlac->seekpointCount = 0;
+ }
+ }
+ }
+
+
+ /*
+ If we get here, but don't have a STREAMINFO block, it means we've opened the stream in relaxed mode and need to decode
+ the first frame.
+ */
+ if (!init.hasStreamInfoBlock) {
+ pFlac->currentFLACFrame.header = init.firstFrameHeader;
+ for (;;) {
+ drflac_result result = drflac__decode_flac_frame(pFlac);
+ if (result == DRFLAC_SUCCESS) {
+ break;
+ } else {
+ if (result == DRFLAC_CRC_MISMATCH) {
+ if (!drflac__read_next_flac_frame_header(&pFlac->bs, pFlac->bitsPerSample, &pFlac->currentFLACFrame.header)) {
+ drflac__free_from_callbacks(pFlac, &allocationCallbacks);
+ return NULL;
+ }
+ continue;
+ } else {
+ drflac__free_from_callbacks(pFlac, &allocationCallbacks);
+ return NULL;
+ }
+ }
+ }
+ }
+
+ return pFlac;
+}
+
+
+
+#ifndef DR_FLAC_NO_STDIO
+#include
+#ifndef DR_FLAC_NO_WCHAR
+#include /* For wcslen(), wcsrtombs() */
+#endif
+
+/* Errno */
+/* drflac_result_from_errno() is only used for fopen() and wfopen() so putting it inside DR_WAV_NO_STDIO for now. If something else needs this later we can move it out. */
+#include
+static drflac_result drflac_result_from_errno(int e)
+{
+ switch (e)
+ {
+ case 0: return DRFLAC_SUCCESS;
+ #ifdef EPERM
+ case EPERM: return DRFLAC_INVALID_OPERATION;
+ #endif
+ #ifdef ENOENT
+ case ENOENT: return DRFLAC_DOES_NOT_EXIST;
+ #endif
+ #ifdef ESRCH
+ case ESRCH: return DRFLAC_DOES_NOT_EXIST;
+ #endif
+ #ifdef EINTR
+ case EINTR: return DRFLAC_INTERRUPT;
+ #endif
+ #ifdef EIO
+ case EIO: return DRFLAC_IO_ERROR;
+ #endif
+ #ifdef ENXIO
+ case ENXIO: return DRFLAC_DOES_NOT_EXIST;
+ #endif
+ #ifdef E2BIG
+ case E2BIG: return DRFLAC_INVALID_ARGS;
+ #endif
+ #ifdef ENOEXEC
+ case ENOEXEC: return DRFLAC_INVALID_FILE;
+ #endif
+ #ifdef EBADF
+ case EBADF: return DRFLAC_INVALID_FILE;
+ #endif
+ #ifdef ECHILD
+ case ECHILD: return DRFLAC_ERROR;
+ #endif
+ #ifdef EAGAIN
+ case EAGAIN: return DRFLAC_UNAVAILABLE;
+ #endif
+ #ifdef ENOMEM
+ case ENOMEM: return DRFLAC_OUT_OF_MEMORY;
+ #endif
+ #ifdef EACCES
+ case EACCES: return DRFLAC_ACCESS_DENIED;
+ #endif
+ #ifdef EFAULT
+ case EFAULT: return DRFLAC_BAD_ADDRESS;
+ #endif
+ #ifdef ENOTBLK
+ case ENOTBLK: return DRFLAC_ERROR;
+ #endif
+ #ifdef EBUSY
+ case EBUSY: return DRFLAC_BUSY;
+ #endif
+ #ifdef EEXIST
+ case EEXIST: return DRFLAC_ALREADY_EXISTS;
+ #endif
+ #ifdef EXDEV
+ case EXDEV: return DRFLAC_ERROR;
+ #endif
+ #ifdef ENODEV
+ case ENODEV: return DRFLAC_DOES_NOT_EXIST;
+ #endif
+ #ifdef ENOTDIR
+ case ENOTDIR: return DRFLAC_NOT_DIRECTORY;
+ #endif
+ #ifdef EISDIR
+ case EISDIR: return DRFLAC_IS_DIRECTORY;
+ #endif
+ #ifdef EINVAL
+ case EINVAL: return DRFLAC_INVALID_ARGS;
+ #endif
+ #ifdef ENFILE
+ case ENFILE: return DRFLAC_TOO_MANY_OPEN_FILES;
+ #endif
+ #ifdef EMFILE
+ case EMFILE: return DRFLAC_TOO_MANY_OPEN_FILES;
+ #endif
+ #ifdef ENOTTY
+ case ENOTTY: return DRFLAC_INVALID_OPERATION;
+ #endif
+ #ifdef ETXTBSY
+ case ETXTBSY: return DRFLAC_BUSY;
+ #endif
+ #ifdef EFBIG
+ case EFBIG: return DRFLAC_TOO_BIG;
+ #endif
+ #ifdef ENOSPC
+ case ENOSPC: return DRFLAC_NO_SPACE;
+ #endif
+ #ifdef ESPIPE
+ case ESPIPE: return DRFLAC_BAD_SEEK;
+ #endif
+ #ifdef EROFS
+ case EROFS: return DRFLAC_ACCESS_DENIED;
+ #endif
+ #ifdef EMLINK
+ case EMLINK: return DRFLAC_TOO_MANY_LINKS;
+ #endif
+ #ifdef EPIPE
+ case EPIPE: return DRFLAC_BAD_PIPE;
+ #endif
+ #ifdef EDOM
+ case EDOM: return DRFLAC_OUT_OF_RANGE;
+ #endif
+ #ifdef ERANGE
+ case ERANGE: return DRFLAC_OUT_OF_RANGE;
+ #endif
+ #ifdef EDEADLK
+ case EDEADLK: return DRFLAC_DEADLOCK;
+ #endif
+ #ifdef ENAMETOOLONG
+ case ENAMETOOLONG: return DRFLAC_PATH_TOO_LONG;
+ #endif
+ #ifdef ENOLCK
+ case ENOLCK: return DRFLAC_ERROR;
+ #endif
+ #ifdef ENOSYS
+ case ENOSYS: return DRFLAC_NOT_IMPLEMENTED;
+ #endif
+ #ifdef ENOTEMPTY
+ case ENOTEMPTY: return DRFLAC_DIRECTORY_NOT_EMPTY;
+ #endif
+ #ifdef ELOOP
+ case ELOOP: return DRFLAC_TOO_MANY_LINKS;
+ #endif
+ #ifdef ENOMSG
+ case ENOMSG: return DRFLAC_NO_MESSAGE;
+ #endif
+ #ifdef EIDRM
+ case EIDRM: return DRFLAC_ERROR;
+ #endif
+ #ifdef ECHRNG
+ case ECHRNG: return DRFLAC_ERROR;
+ #endif
+ #ifdef EL2NSYNC
+ case EL2NSYNC: return DRFLAC_ERROR;
+ #endif
+ #ifdef EL3HLT
+ case EL3HLT: return DRFLAC_ERROR;
+ #endif
+ #ifdef EL3RST
+ case EL3RST: return DRFLAC_ERROR;
+ #endif
+ #ifdef ELNRNG
+ case ELNRNG: return DRFLAC_OUT_OF_RANGE;
+ #endif
+ #ifdef EUNATCH
+ case EUNATCH: return DRFLAC_ERROR;
+ #endif
+ #ifdef ENOCSI
+ case ENOCSI: return DRFLAC_ERROR;
+ #endif
+ #ifdef EL2HLT
+ case EL2HLT: return DRFLAC_ERROR;
+ #endif
+ #ifdef EBADE
+ case EBADE: return DRFLAC_ERROR;
+ #endif
+ #ifdef EBADR
+ case EBADR: return DRFLAC_ERROR;
+ #endif
+ #ifdef EXFULL
+ case EXFULL: return DRFLAC_ERROR;
+ #endif
+ #ifdef ENOANO
+ case ENOANO: return DRFLAC_ERROR;
+ #endif
+ #ifdef EBADRQC
+ case EBADRQC: return DRFLAC_ERROR;
+ #endif
+ #ifdef EBADSLT
+ case EBADSLT: return DRFLAC_ERROR;
+ #endif
+ #ifdef EBFONT
+ case EBFONT: return DRFLAC_INVALID_FILE;
+ #endif
+ #ifdef ENOSTR
+ case ENOSTR: return DRFLAC_ERROR;
+ #endif
+ #ifdef ENODATA
+ case ENODATA: return DRFLAC_NO_DATA_AVAILABLE;
+ #endif
+ #ifdef ETIME
+ case ETIME: return DRFLAC_TIMEOUT;
+ #endif
+ #ifdef ENOSR
+ case ENOSR: return DRFLAC_NO_DATA_AVAILABLE;
+ #endif
+ #ifdef ENONET
+ case ENONET: return DRFLAC_NO_NETWORK;
+ #endif
+ #ifdef ENOPKG
+ case ENOPKG: return DRFLAC_ERROR;
+ #endif
+ #ifdef EREMOTE
+ case EREMOTE: return DRFLAC_ERROR;
+ #endif
+ #ifdef ENOLINK
+ case ENOLINK: return DRFLAC_ERROR;
+ #endif
+ #ifdef EADV
+ case EADV: return DRFLAC_ERROR;
+ #endif
+ #ifdef ESRMNT
+ case ESRMNT: return DRFLAC_ERROR;
+ #endif
+ #ifdef ECOMM
+ case ECOMM: return DRFLAC_ERROR;
+ #endif
+ #ifdef EPROTO
+ case EPROTO: return DRFLAC_ERROR;
+ #endif
+ #ifdef EMULTIHOP
+ case EMULTIHOP: return DRFLAC_ERROR;
+ #endif
+ #ifdef EDOTDOT
+ case EDOTDOT: return DRFLAC_ERROR;
+ #endif
+ #ifdef EBADMSG
+ case EBADMSG: return DRFLAC_BAD_MESSAGE;
+ #endif
+ #ifdef EOVERFLOW
+ case EOVERFLOW: return DRFLAC_TOO_BIG;
+ #endif
+ #ifdef ENOTUNIQ
+ case ENOTUNIQ: return DRFLAC_NOT_UNIQUE;
+ #endif
+ #ifdef EBADFD
+ case EBADFD: return DRFLAC_ERROR;
+ #endif
+ #ifdef EREMCHG
+ case EREMCHG: return DRFLAC_ERROR;
+ #endif
+ #ifdef ELIBACC
+ case ELIBACC: return DRFLAC_ACCESS_DENIED;
+ #endif
+ #ifdef ELIBBAD
+ case ELIBBAD: return DRFLAC_INVALID_FILE;
+ #endif
+ #ifdef ELIBSCN
+ case ELIBSCN: return DRFLAC_INVALID_FILE;
+ #endif
+ #ifdef ELIBMAX
+ case ELIBMAX: return DRFLAC_ERROR;
+ #endif
+ #ifdef ELIBEXEC
+ case ELIBEXEC: return DRFLAC_ERROR;
+ #endif
+ #ifdef EILSEQ
+ case EILSEQ: return DRFLAC_INVALID_DATA;
+ #endif
+ #ifdef ERESTART
+ case ERESTART: return DRFLAC_ERROR;
+ #endif
+ #ifdef ESTRPIPE
+ case ESTRPIPE: return DRFLAC_ERROR;
+ #endif
+ #ifdef EUSERS
+ case EUSERS: return DRFLAC_ERROR;
+ #endif
+ #ifdef ENOTSOCK
+ case ENOTSOCK: return DRFLAC_NOT_SOCKET;
+ #endif
+ #ifdef EDESTADDRREQ
+ case EDESTADDRREQ: return DRFLAC_NO_ADDRESS;
+ #endif
+ #ifdef EMSGSIZE
+ case EMSGSIZE: return DRFLAC_TOO_BIG;
+ #endif
+ #ifdef EPROTOTYPE
+ case EPROTOTYPE: return DRFLAC_BAD_PROTOCOL;
+ #endif
+ #ifdef ENOPROTOOPT
+ case ENOPROTOOPT: return DRFLAC_PROTOCOL_UNAVAILABLE;
+ #endif
+ #ifdef EPROTONOSUPPORT
+ case EPROTONOSUPPORT: return DRFLAC_PROTOCOL_NOT_SUPPORTED;
+ #endif
+ #ifdef ESOCKTNOSUPPORT
+ case ESOCKTNOSUPPORT: return DRFLAC_SOCKET_NOT_SUPPORTED;
+ #endif
+ #ifdef EOPNOTSUPP
+ case EOPNOTSUPP: return DRFLAC_INVALID_OPERATION;
+ #endif
+ #ifdef EPFNOSUPPORT
+ case EPFNOSUPPORT: return DRFLAC_PROTOCOL_FAMILY_NOT_SUPPORTED;
+ #endif
+ #ifdef EAFNOSUPPORT
+ case EAFNOSUPPORT: return DRFLAC_ADDRESS_FAMILY_NOT_SUPPORTED;
+ #endif
+ #ifdef EADDRINUSE
+ case EADDRINUSE: return DRFLAC_ALREADY_IN_USE;
+ #endif
+ #ifdef EADDRNOTAVAIL
+ case EADDRNOTAVAIL: return DRFLAC_ERROR;
+ #endif
+ #ifdef ENETDOWN
+ case ENETDOWN: return DRFLAC_NO_NETWORK;
+ #endif
+ #ifdef ENETUNREACH
+ case ENETUNREACH: return DRFLAC_NO_NETWORK;
+ #endif
+ #ifdef ENETRESET
+ case ENETRESET: return DRFLAC_NO_NETWORK;
+ #endif
+ #ifdef ECONNABORTED
+ case ECONNABORTED: return DRFLAC_NO_NETWORK;
+ #endif
+ #ifdef ECONNRESET
+ case ECONNRESET: return DRFLAC_CONNECTION_RESET;
+ #endif
+ #ifdef ENOBUFS
+ case ENOBUFS: return DRFLAC_NO_SPACE;
+ #endif
+ #ifdef EISCONN
+ case EISCONN: return DRFLAC_ALREADY_CONNECTED;
+ #endif
+ #ifdef ENOTCONN
+ case ENOTCONN: return DRFLAC_NOT_CONNECTED;
+ #endif
+ #ifdef ESHUTDOWN
+ case ESHUTDOWN: return DRFLAC_ERROR;
+ #endif
+ #ifdef ETOOMANYREFS
+ case ETOOMANYREFS: return DRFLAC_ERROR;
+ #endif
+ #ifdef ETIMEDOUT
+ case ETIMEDOUT: return DRFLAC_TIMEOUT;
+ #endif
+ #ifdef ECONNREFUSED
+ case ECONNREFUSED: return DRFLAC_CONNECTION_REFUSED;
+ #endif
+ #ifdef EHOSTDOWN
+ case EHOSTDOWN: return DRFLAC_NO_HOST;
+ #endif
+ #ifdef EHOSTUNREACH
+ case EHOSTUNREACH: return DRFLAC_NO_HOST;
+ #endif
+ #ifdef EALREADY
+ case EALREADY: return DRFLAC_IN_PROGRESS;
+ #endif
+ #ifdef EINPROGRESS
+ case EINPROGRESS: return DRFLAC_IN_PROGRESS;
+ #endif
+ #ifdef ESTALE
+ case ESTALE: return DRFLAC_INVALID_FILE;
+ #endif
+ #ifdef EUCLEAN
+ case EUCLEAN: return DRFLAC_ERROR;
+ #endif
+ #ifdef ENOTNAM
+ case ENOTNAM: return DRFLAC_ERROR;
+ #endif
+ #ifdef ENAVAIL
+ case ENAVAIL: return DRFLAC_ERROR;
+ #endif
+ #ifdef EISNAM
+ case EISNAM: return DRFLAC_ERROR;
+ #endif
+ #ifdef EREMOTEIO
+ case EREMOTEIO: return DRFLAC_IO_ERROR;
+ #endif
+ #ifdef EDQUOT
+ case EDQUOT: return DRFLAC_NO_SPACE;
+ #endif
+ #ifdef ENOMEDIUM
+ case ENOMEDIUM: return DRFLAC_DOES_NOT_EXIST;
+ #endif
+ #ifdef EMEDIUMTYPE
+ case EMEDIUMTYPE: return DRFLAC_ERROR;
+ #endif
+ #ifdef ECANCELED
+ case ECANCELED: return DRFLAC_CANCELLED;
+ #endif
+ #ifdef ENOKEY
+ case ENOKEY: return DRFLAC_ERROR;
+ #endif
+ #ifdef EKEYEXPIRED
+ case EKEYEXPIRED: return DRFLAC_ERROR;
+ #endif
+ #ifdef EKEYREVOKED
+ case EKEYREVOKED: return DRFLAC_ERROR;
+ #endif
+ #ifdef EKEYREJECTED
+ case EKEYREJECTED: return DRFLAC_ERROR;
+ #endif
+ #ifdef EOWNERDEAD
+ case EOWNERDEAD: return DRFLAC_ERROR;
+ #endif
+ #ifdef ENOTRECOVERABLE
+ case ENOTRECOVERABLE: return DRFLAC_ERROR;
+ #endif
+ #ifdef ERFKILL
+ case ERFKILL: return DRFLAC_ERROR;
+ #endif
+ #ifdef EHWPOISON
+ case EHWPOISON: return DRFLAC_ERROR;
+ #endif
+ default: return DRFLAC_ERROR;
+ }
+}
+/* End Errno */
+
+/* fopen */
+static drflac_result drflac_fopen(FILE** ppFile, const char* pFilePath, const char* pOpenMode)
+{
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+ errno_t err;
+#endif
+
+ if (ppFile != NULL) {
+ *ppFile = NULL; /* Safety. */
+ }
+
+ if (pFilePath == NULL || pOpenMode == NULL || ppFile == NULL) {
+ return DRFLAC_INVALID_ARGS;
+ }
+
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+ err = fopen_s(ppFile, pFilePath, pOpenMode);
+ if (err != 0) {
+ return drflac_result_from_errno(err);
+ }
+#else
+#if defined(_WIN32) || defined(__APPLE__)
+ *ppFile = fopen(pFilePath, pOpenMode);
+#else
+ #if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64 && defined(_LARGEFILE64_SOURCE)
+ *ppFile = fopen64(pFilePath, pOpenMode);
+ #else
+ *ppFile = fopen(pFilePath, pOpenMode);
+ #endif
+#endif
+ if (*ppFile == NULL) {
+ drflac_result result = drflac_result_from_errno(errno);
+ if (result == DRFLAC_SUCCESS) {
+ result = DRFLAC_ERROR; /* Just a safety check to make sure we never ever return success when pFile == NULL. */
+ }
+
+ return result;
+ }
+#endif
+
+ return DRFLAC_SUCCESS;
+}
+
+/*
+_wfopen() isn't always available in all compilation environments.
+
+ * Windows only.
+ * MSVC seems to support it universally as far back as VC6 from what I can tell (haven't checked further back).
+ * MinGW-64 (both 32- and 64-bit) seems to support it.
+ * MinGW wraps it in !defined(__STRICT_ANSI__).
+ * OpenWatcom wraps it in !defined(_NO_EXT_KEYS).
+
+This can be reviewed as compatibility issues arise. The preference is to use _wfopen_s() and _wfopen() as opposed to the wcsrtombs()
+fallback, so if you notice your compiler not detecting this properly I'm happy to look at adding support.
+*/
+#if defined(_WIN32)
+ #if defined(_MSC_VER) || defined(__MINGW64__) || (!defined(__STRICT_ANSI__) && !defined(_NO_EXT_KEYS))
+ #define DRFLAC_HAS_WFOPEN
+ #endif
+#endif
+
+#ifndef DR_FLAC_NO_WCHAR
+static drflac_result drflac_wfopen(FILE** ppFile, const wchar_t* pFilePath, const wchar_t* pOpenMode, const drflac_allocation_callbacks* pAllocationCallbacks)
+{
+ if (ppFile != NULL) {
+ *ppFile = NULL; /* Safety. */
+ }
+
+ if (pFilePath == NULL || pOpenMode == NULL || ppFile == NULL) {
+ return DRFLAC_INVALID_ARGS;
+ }
+
+#if defined(DRFLAC_HAS_WFOPEN)
+ {
+ /* Use _wfopen() on Windows. */
+ #if defined(_MSC_VER) && _MSC_VER >= 1400
+ errno_t err = _wfopen_s(ppFile, pFilePath, pOpenMode);
+ if (err != 0) {
+ return drflac_result_from_errno(err);
+ }
+ #else
+ *ppFile = _wfopen(pFilePath, pOpenMode);
+ if (*ppFile == NULL) {
+ return drflac_result_from_errno(errno);
+ }
+ #endif
+ (void)pAllocationCallbacks;
+ }
+#else
+ /*
+ Use fopen() on anything other than Windows. Requires a conversion. This is annoying because
+ fopen() is locale specific. The only real way I can think of to do this is with wcsrtombs(). Note
+ that wcstombs() is apparently not thread-safe because it uses a static global mbstate_t object for
+ maintaining state. I've checked this with -std=c89 and it works, but if somebody get's a compiler
+ error I'll look into improving compatibility.
+ */
+
+ /*
+ Some compilers don't support wchar_t or wcsrtombs() which we're using below. In this case we just
+ need to abort with an error. If you encounter a compiler lacking such support, add it to this list
+ and submit a bug report and it'll be added to the library upstream.
+ */
+ #if defined(__DJGPP__)
+ {
+ /* Nothing to do here. This will fall through to the error check below. */
+ }
+ #else
+ {
+ mbstate_t mbs;
+ size_t lenMB;
+ const wchar_t* pFilePathTemp = pFilePath;
+ char* pFilePathMB = NULL;
+ char pOpenModeMB[32] = {0};
+
+ /* Get the length first. */
+ DRFLAC_ZERO_OBJECT(&mbs);
+ lenMB = wcsrtombs(NULL, &pFilePathTemp, 0, &mbs);
+ if (lenMB == (size_t)-1) {
+ return drflac_result_from_errno(errno);
+ }
+
+ pFilePathMB = (char*)drflac__malloc_from_callbacks(lenMB + 1, pAllocationCallbacks);
+ if (pFilePathMB == NULL) {
+ return DRFLAC_OUT_OF_MEMORY;
+ }
+
+ pFilePathTemp = pFilePath;
+ DRFLAC_ZERO_OBJECT(&mbs);
+ wcsrtombs(pFilePathMB, &pFilePathTemp, lenMB + 1, &mbs);
+
+ /* The open mode should always consist of ASCII characters so we should be able to do a trivial conversion. */
+ {
+ size_t i = 0;
+ for (;;) {
+ if (pOpenMode[i] == 0) {
+ pOpenModeMB[i] = '\0';
+ break;
+ }
+
+ pOpenModeMB[i] = (char)pOpenMode[i];
+ i += 1;
+ }
+ }
+
+ *ppFile = fopen(pFilePathMB, pOpenModeMB);
+
+ drflac__free_from_callbacks(pFilePathMB, pAllocationCallbacks);
+ }
+ #endif
+
+ if (*ppFile == NULL) {
+ return DRFLAC_ERROR;
+ }
+#endif
+
+ return DRFLAC_SUCCESS;
+}
+#endif
+/* End fopen */
+
+static size_t drflac__on_read_stdio(void* pUserData, void* bufferOut, size_t bytesToRead)
+{
+ return fread(bufferOut, 1, bytesToRead, (FILE*)pUserData);
+}
+
+static drflac_bool32 drflac__on_seek_stdio(void* pUserData, int offset, drflac_seek_origin origin)
+{
+ DRFLAC_ASSERT(offset >= 0); /* <-- Never seek backwards. */
+
+ return fseek((FILE*)pUserData, offset, (origin == drflac_seek_origin_current) ? SEEK_CUR : SEEK_SET) == 0;
+}
+
+
+DRFLAC_API drflac* drflac_open_file(const char* pFileName, const drflac_allocation_callbacks* pAllocationCallbacks)
+{
+ drflac* pFlac;
+ FILE* pFile;
+
+ if (drflac_fopen(&pFile, pFileName, "rb") != DRFLAC_SUCCESS) {
+ return NULL;
+ }
+
+ pFlac = drflac_open(drflac__on_read_stdio, drflac__on_seek_stdio, (void*)pFile, pAllocationCallbacks);
+ if (pFlac == NULL) {
+ fclose(pFile);
+ return NULL;
+ }
+
+ return pFlac;
+}
+
+#ifndef DR_FLAC_NO_WCHAR
+DRFLAC_API drflac* drflac_open_file_w(const wchar_t* pFileName, const drflac_allocation_callbacks* pAllocationCallbacks)
+{
+ drflac* pFlac;
+ FILE* pFile;
+
+ if (drflac_wfopen(&pFile, pFileName, L"rb", pAllocationCallbacks) != DRFLAC_SUCCESS) {
+ return NULL;
+ }
+
+ pFlac = drflac_open(drflac__on_read_stdio, drflac__on_seek_stdio, (void*)pFile, pAllocationCallbacks);
+ if (pFlac == NULL) {
+ fclose(pFile);
+ return NULL;
+ }
+
+ return pFlac;
+}
+#endif
+
+DRFLAC_API drflac* drflac_open_file_with_metadata(const char* pFileName, drflac_meta_proc onMeta, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks)
+{
+ drflac* pFlac;
+ FILE* pFile;
+
+ if (drflac_fopen(&pFile, pFileName, "rb") != DRFLAC_SUCCESS) {
+ return NULL;
+ }
+
+ pFlac = drflac_open_with_metadata_private(drflac__on_read_stdio, drflac__on_seek_stdio, onMeta, drflac_container_unknown, (void*)pFile, pUserData, pAllocationCallbacks);
+ if (pFlac == NULL) {
+ fclose(pFile);
+ return pFlac;
+ }
+
+ return pFlac;
+}
+
+#ifndef DR_FLAC_NO_WCHAR
+DRFLAC_API drflac* drflac_open_file_with_metadata_w(const wchar_t* pFileName, drflac_meta_proc onMeta, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks)
+{
+ drflac* pFlac;
+ FILE* pFile;
+
+ if (drflac_wfopen(&pFile, pFileName, L"rb", pAllocationCallbacks) != DRFLAC_SUCCESS) {
+ return NULL;
+ }
+
+ pFlac = drflac_open_with_metadata_private(drflac__on_read_stdio, drflac__on_seek_stdio, onMeta, drflac_container_unknown, (void*)pFile, pUserData, pAllocationCallbacks);
+ if (pFlac == NULL) {
+ fclose(pFile);
+ return pFlac;
+ }
+
+ return pFlac;
+}
+#endif
+#endif /* DR_FLAC_NO_STDIO */
+
+static size_t drflac__on_read_memory(void* pUserData, void* bufferOut, size_t bytesToRead)
+{
+ drflac__memory_stream* memoryStream = (drflac__memory_stream*)pUserData;
+ size_t bytesRemaining;
+
+ DRFLAC_ASSERT(memoryStream != NULL);
+ DRFLAC_ASSERT(memoryStream->dataSize >= memoryStream->currentReadPos);
+
+ bytesRemaining = memoryStream->dataSize - memoryStream->currentReadPos;
+ if (bytesToRead > bytesRemaining) {
+ bytesToRead = bytesRemaining;
+ }
+
+ if (bytesToRead > 0) {
+ DRFLAC_COPY_MEMORY(bufferOut, memoryStream->data + memoryStream->currentReadPos, bytesToRead);
+ memoryStream->currentReadPos += bytesToRead;
+ }
+
+ return bytesToRead;
+}
+
+static drflac_bool32 drflac__on_seek_memory(void* pUserData, int offset, drflac_seek_origin origin)
+{
+ drflac__memory_stream* memoryStream = (drflac__memory_stream*)pUserData;
+
+ DRFLAC_ASSERT(memoryStream != NULL);
+ DRFLAC_ASSERT(offset >= 0); /* <-- Never seek backwards. */
+
+ if (offset > (drflac_int64)memoryStream->dataSize) {
+ return DRFLAC_FALSE;
+ }
+
+ if (origin == drflac_seek_origin_current) {
+ if (memoryStream->currentReadPos + offset <= memoryStream->dataSize) {
+ memoryStream->currentReadPos += offset;
+ } else {
+ return DRFLAC_FALSE; /* Trying to seek too far forward. */
+ }
+ } else {
+ if ((drflac_uint32)offset <= memoryStream->dataSize) {
+ memoryStream->currentReadPos = offset;
+ } else {
+ return DRFLAC_FALSE; /* Trying to seek too far forward. */
+ }
+ }
+
+ return DRFLAC_TRUE;
+}
+
+DRFLAC_API drflac* drflac_open_memory(const void* pData, size_t dataSize, const drflac_allocation_callbacks* pAllocationCallbacks)
+{
+ drflac__memory_stream memoryStream;
+ drflac* pFlac;
+
+ memoryStream.data = (const drflac_uint8*)pData;
+ memoryStream.dataSize = dataSize;
+ memoryStream.currentReadPos = 0;
+ pFlac = drflac_open(drflac__on_read_memory, drflac__on_seek_memory, &memoryStream, pAllocationCallbacks);
+ if (pFlac == NULL) {
+ return NULL;
+ }
+
+ pFlac->memoryStream = memoryStream;
+
+ /* This is an awful hack... */
+#ifndef DR_FLAC_NO_OGG
+ if (pFlac->container == drflac_container_ogg)
+ {
+ drflac_oggbs* oggbs = (drflac_oggbs*)pFlac->_oggbs;
+ oggbs->pUserData = &pFlac->memoryStream;
+ }
+ else
+#endif
+ {
+ pFlac->bs.pUserData = &pFlac->memoryStream;
+ }
+
+ return pFlac;
+}
+
+DRFLAC_API drflac* drflac_open_memory_with_metadata(const void* pData, size_t dataSize, drflac_meta_proc onMeta, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks)
+{
+ drflac__memory_stream memoryStream;
+ drflac* pFlac;
+
+ memoryStream.data = (const drflac_uint8*)pData;
+ memoryStream.dataSize = dataSize;
+ memoryStream.currentReadPos = 0;
+ pFlac = drflac_open_with_metadata_private(drflac__on_read_memory, drflac__on_seek_memory, onMeta, drflac_container_unknown, &memoryStream, pUserData, pAllocationCallbacks);
+ if (pFlac == NULL) {
+ return NULL;
+ }
+
+ pFlac->memoryStream = memoryStream;
+
+ /* This is an awful hack... */
+#ifndef DR_FLAC_NO_OGG
+ if (pFlac->container == drflac_container_ogg)
+ {
+ drflac_oggbs* oggbs = (drflac_oggbs*)pFlac->_oggbs;
+ oggbs->pUserData = &pFlac->memoryStream;
+ }
+ else
+#endif
+ {
+ pFlac->bs.pUserData = &pFlac->memoryStream;
+ }
+
+ return pFlac;
+}
+
+
+
+DRFLAC_API drflac* drflac_open(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks)
+{
+ return drflac_open_with_metadata_private(onRead, onSeek, NULL, drflac_container_unknown, pUserData, pUserData, pAllocationCallbacks);
+}
+DRFLAC_API drflac* drflac_open_relaxed(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_container container, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks)
+{
+ return drflac_open_with_metadata_private(onRead, onSeek, NULL, container, pUserData, pUserData, pAllocationCallbacks);
+}
+
+DRFLAC_API drflac* drflac_open_with_metadata(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks)
+{
+ return drflac_open_with_metadata_private(onRead, onSeek, onMeta, drflac_container_unknown, pUserData, pUserData, pAllocationCallbacks);
+}
+DRFLAC_API drflac* drflac_open_with_metadata_relaxed(drflac_read_proc onRead, drflac_seek_proc onSeek, drflac_meta_proc onMeta, drflac_container container, void* pUserData, const drflac_allocation_callbacks* pAllocationCallbacks)
+{
+ return drflac_open_with_metadata_private(onRead, onSeek, onMeta, container, pUserData, pUserData, pAllocationCallbacks);
+}
+
+DRFLAC_API void drflac_close(drflac* pFlac)
+{
+ if (pFlac == NULL) {
+ return;
+ }
+
+#ifndef DR_FLAC_NO_STDIO
+ /*
+ If we opened the file with drflac_open_file() we will want to close the file handle. We can know whether or not drflac_open_file()
+ was used by looking at the callbacks.
+ */
+ if (pFlac->bs.onRead == drflac__on_read_stdio) {
+ fclose((FILE*)pFlac->bs.pUserData);
+ }
+
+#ifndef DR_FLAC_NO_OGG
+ /* Need to clean up Ogg streams a bit differently due to the way the bit streaming is chained. */
+ if (pFlac->container == drflac_container_ogg) {
+ drflac_oggbs* oggbs = (drflac_oggbs*)pFlac->_oggbs;
+ DRFLAC_ASSERT(pFlac->bs.onRead == drflac__on_read_ogg);
+
+ if (oggbs->onRead == drflac__on_read_stdio) {
+ fclose((FILE*)oggbs->pUserData);
+ }
+ }
+#endif
+#endif
+
+ drflac__free_from_callbacks(pFlac, &pFlac->allocationCallbacks);
+}
+
+
+#if 0
+static DRFLAC_INLINE void drflac_read_pcm_frames_s32__decode_left_side__reference(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int32* pOutputSamples)
+{
+ drflac_uint64 i;
+ for (i = 0; i < frameCount; ++i) {
+ drflac_uint32 left = (drflac_uint32)pInputSamples0[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample);
+ drflac_uint32 side = (drflac_uint32)pInputSamples1[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample);
+ drflac_uint32 right = left - side;
+
+ pOutputSamples[i*2+0] = (drflac_int32)left;
+ pOutputSamples[i*2+1] = (drflac_int32)right;
+ }
+}
+#endif
+
+static DRFLAC_INLINE void drflac_read_pcm_frames_s32__decode_left_side__scalar(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int32* pOutputSamples)
+{
+ drflac_uint64 i;
+ drflac_uint64 frameCount4 = frameCount >> 2;
+ const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
+ const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
+ drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+
+ for (i = 0; i < frameCount4; ++i) {
+ drflac_uint32 left0 = pInputSamples0U32[i*4+0] << shift0;
+ drflac_uint32 left1 = pInputSamples0U32[i*4+1] << shift0;
+ drflac_uint32 left2 = pInputSamples0U32[i*4+2] << shift0;
+ drflac_uint32 left3 = pInputSamples0U32[i*4+3] << shift0;
+
+ drflac_uint32 side0 = pInputSamples1U32[i*4+0] << shift1;
+ drflac_uint32 side1 = pInputSamples1U32[i*4+1] << shift1;
+ drflac_uint32 side2 = pInputSamples1U32[i*4+2] << shift1;
+ drflac_uint32 side3 = pInputSamples1U32[i*4+3] << shift1;
+
+ drflac_uint32 right0 = left0 - side0;
+ drflac_uint32 right1 = left1 - side1;
+ drflac_uint32 right2 = left2 - side2;
+ drflac_uint32 right3 = left3 - side3;
+
+ pOutputSamples[i*8+0] = (drflac_int32)left0;
+ pOutputSamples[i*8+1] = (drflac_int32)right0;
+ pOutputSamples[i*8+2] = (drflac_int32)left1;
+ pOutputSamples[i*8+3] = (drflac_int32)right1;
+ pOutputSamples[i*8+4] = (drflac_int32)left2;
+ pOutputSamples[i*8+5] = (drflac_int32)right2;
+ pOutputSamples[i*8+6] = (drflac_int32)left3;
+ pOutputSamples[i*8+7] = (drflac_int32)right3;
+ }
+
+ for (i = (frameCount4 << 2); i < frameCount; ++i) {
+ drflac_uint32 left = pInputSamples0U32[i] << shift0;
+ drflac_uint32 side = pInputSamples1U32[i] << shift1;
+ drflac_uint32 right = left - side;
+
+ pOutputSamples[i*2+0] = (drflac_int32)left;
+ pOutputSamples[i*2+1] = (drflac_int32)right;
+ }
+}
+
+#if defined(DRFLAC_SUPPORT_SSE2)
+static DRFLAC_INLINE void drflac_read_pcm_frames_s32__decode_left_side__sse2(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int32* pOutputSamples)
+{
+ drflac_uint64 i;
+ drflac_uint64 frameCount4 = frameCount >> 2;
+ const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
+ const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
+ drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+
+ DRFLAC_ASSERT(pFlac->bitsPerSample <= 24);
+
+ for (i = 0; i < frameCount4; ++i) {
+ __m128i left = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples0 + i), shift0);
+ __m128i side = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples1 + i), shift1);
+ __m128i right = _mm_sub_epi32(left, side);
+
+ _mm_storeu_si128((__m128i*)(pOutputSamples + i*8 + 0), _mm_unpacklo_epi32(left, right));
+ _mm_storeu_si128((__m128i*)(pOutputSamples + i*8 + 4), _mm_unpackhi_epi32(left, right));
+ }
+
+ for (i = (frameCount4 << 2); i < frameCount; ++i) {
+ drflac_uint32 left = pInputSamples0U32[i] << shift0;
+ drflac_uint32 side = pInputSamples1U32[i] << shift1;
+ drflac_uint32 right = left - side;
+
+ pOutputSamples[i*2+0] = (drflac_int32)left;
+ pOutputSamples[i*2+1] = (drflac_int32)right;
+ }
+}
+#endif
+
+#if defined(DRFLAC_SUPPORT_NEON)
+static DRFLAC_INLINE void drflac_read_pcm_frames_s32__decode_left_side__neon(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int32* pOutputSamples)
+{
+ drflac_uint64 i;
+ drflac_uint64 frameCount4 = frameCount >> 2;
+ const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
+ const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
+ drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+ int32x4_t shift0_4;
+ int32x4_t shift1_4;
+
+ DRFLAC_ASSERT(pFlac->bitsPerSample <= 24);
+
+ shift0_4 = vdupq_n_s32(shift0);
+ shift1_4 = vdupq_n_s32(shift1);
+
+ for (i = 0; i < frameCount4; ++i) {
+ uint32x4_t left;
+ uint32x4_t side;
+ uint32x4_t right;
+
+ left = vshlq_u32(vld1q_u32(pInputSamples0U32 + i*4), shift0_4);
+ side = vshlq_u32(vld1q_u32(pInputSamples1U32 + i*4), shift1_4);
+ right = vsubq_u32(left, side);
+
+ drflac__vst2q_u32((drflac_uint32*)pOutputSamples + i*8, vzipq_u32(left, right));
+ }
+
+ for (i = (frameCount4 << 2); i < frameCount; ++i) {
+ drflac_uint32 left = pInputSamples0U32[i] << shift0;
+ drflac_uint32 side = pInputSamples1U32[i] << shift1;
+ drflac_uint32 right = left - side;
+
+ pOutputSamples[i*2+0] = (drflac_int32)left;
+ pOutputSamples[i*2+1] = (drflac_int32)right;
+ }
+}
+#endif
+
+static DRFLAC_INLINE void drflac_read_pcm_frames_s32__decode_left_side(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int32* pOutputSamples)
+{
+#if defined(DRFLAC_SUPPORT_SSE2)
+ if (drflac__gIsSSE2Supported && pFlac->bitsPerSample <= 24) {
+ drflac_read_pcm_frames_s32__decode_left_side__sse2(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
+ } else
+#elif defined(DRFLAC_SUPPORT_NEON)
+ if (drflac__gIsNEONSupported && pFlac->bitsPerSample <= 24) {
+ drflac_read_pcm_frames_s32__decode_left_side__neon(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
+ } else
+#endif
+ {
+ /* Scalar fallback. */
+#if 0
+ drflac_read_pcm_frames_s32__decode_left_side__reference(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
+#else
+ drflac_read_pcm_frames_s32__decode_left_side__scalar(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
+#endif
+ }
+}
+
+
+#if 0
+static DRFLAC_INLINE void drflac_read_pcm_frames_s32__decode_right_side__reference(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int32* pOutputSamples)
+{
+ drflac_uint64 i;
+ for (i = 0; i < frameCount; ++i) {
+ drflac_uint32 side = (drflac_uint32)pInputSamples0[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample);
+ drflac_uint32 right = (drflac_uint32)pInputSamples1[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample);
+ drflac_uint32 left = right + side;
+
+ pOutputSamples[i*2+0] = (drflac_int32)left;
+ pOutputSamples[i*2+1] = (drflac_int32)right;
+ }
+}
+#endif
+
+static DRFLAC_INLINE void drflac_read_pcm_frames_s32__decode_right_side__scalar(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int32* pOutputSamples)
+{
+ drflac_uint64 i;
+ drflac_uint64 frameCount4 = frameCount >> 2;
+ const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
+ const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
+ drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+
+ for (i = 0; i < frameCount4; ++i) {
+ drflac_uint32 side0 = pInputSamples0U32[i*4+0] << shift0;
+ drflac_uint32 side1 = pInputSamples0U32[i*4+1] << shift0;
+ drflac_uint32 side2 = pInputSamples0U32[i*4+2] << shift0;
+ drflac_uint32 side3 = pInputSamples0U32[i*4+3] << shift0;
+
+ drflac_uint32 right0 = pInputSamples1U32[i*4+0] << shift1;
+ drflac_uint32 right1 = pInputSamples1U32[i*4+1] << shift1;
+ drflac_uint32 right2 = pInputSamples1U32[i*4+2] << shift1;
+ drflac_uint32 right3 = pInputSamples1U32[i*4+3] << shift1;
+
+ drflac_uint32 left0 = right0 + side0;
+ drflac_uint32 left1 = right1 + side1;
+ drflac_uint32 left2 = right2 + side2;
+ drflac_uint32 left3 = right3 + side3;
+
+ pOutputSamples[i*8+0] = (drflac_int32)left0;
+ pOutputSamples[i*8+1] = (drflac_int32)right0;
+ pOutputSamples[i*8+2] = (drflac_int32)left1;
+ pOutputSamples[i*8+3] = (drflac_int32)right1;
+ pOutputSamples[i*8+4] = (drflac_int32)left2;
+ pOutputSamples[i*8+5] = (drflac_int32)right2;
+ pOutputSamples[i*8+6] = (drflac_int32)left3;
+ pOutputSamples[i*8+7] = (drflac_int32)right3;
+ }
+
+ for (i = (frameCount4 << 2); i < frameCount; ++i) {
+ drflac_uint32 side = pInputSamples0U32[i] << shift0;
+ drflac_uint32 right = pInputSamples1U32[i] << shift1;
+ drflac_uint32 left = right + side;
+
+ pOutputSamples[i*2+0] = (drflac_int32)left;
+ pOutputSamples[i*2+1] = (drflac_int32)right;
+ }
+}
+
+#if defined(DRFLAC_SUPPORT_SSE2)
+static DRFLAC_INLINE void drflac_read_pcm_frames_s32__decode_right_side__sse2(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int32* pOutputSamples)
+{
+ drflac_uint64 i;
+ drflac_uint64 frameCount4 = frameCount >> 2;
+ const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
+ const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
+ drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+
+ DRFLAC_ASSERT(pFlac->bitsPerSample <= 24);
+
+ for (i = 0; i < frameCount4; ++i) {
+ __m128i side = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples0 + i), shift0);
+ __m128i right = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples1 + i), shift1);
+ __m128i left = _mm_add_epi32(right, side);
+
+ _mm_storeu_si128((__m128i*)(pOutputSamples + i*8 + 0), _mm_unpacklo_epi32(left, right));
+ _mm_storeu_si128((__m128i*)(pOutputSamples + i*8 + 4), _mm_unpackhi_epi32(left, right));
+ }
+
+ for (i = (frameCount4 << 2); i < frameCount; ++i) {
+ drflac_uint32 side = pInputSamples0U32[i] << shift0;
+ drflac_uint32 right = pInputSamples1U32[i] << shift1;
+ drflac_uint32 left = right + side;
+
+ pOutputSamples[i*2+0] = (drflac_int32)left;
+ pOutputSamples[i*2+1] = (drflac_int32)right;
+ }
+}
+#endif
+
+#if defined(DRFLAC_SUPPORT_NEON)
+static DRFLAC_INLINE void drflac_read_pcm_frames_s32__decode_right_side__neon(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int32* pOutputSamples)
+{
+ drflac_uint64 i;
+ drflac_uint64 frameCount4 = frameCount >> 2;
+ const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
+ const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
+ drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+ int32x4_t shift0_4;
+ int32x4_t shift1_4;
+
+ DRFLAC_ASSERT(pFlac->bitsPerSample <= 24);
+
+ shift0_4 = vdupq_n_s32(shift0);
+ shift1_4 = vdupq_n_s32(shift1);
+
+ for (i = 0; i < frameCount4; ++i) {
+ uint32x4_t side;
+ uint32x4_t right;
+ uint32x4_t left;
+
+ side = vshlq_u32(vld1q_u32(pInputSamples0U32 + i*4), shift0_4);
+ right = vshlq_u32(vld1q_u32(pInputSamples1U32 + i*4), shift1_4);
+ left = vaddq_u32(right, side);
+
+ drflac__vst2q_u32((drflac_uint32*)pOutputSamples + i*8, vzipq_u32(left, right));
+ }
+
+ for (i = (frameCount4 << 2); i < frameCount; ++i) {
+ drflac_uint32 side = pInputSamples0U32[i] << shift0;
+ drflac_uint32 right = pInputSamples1U32[i] << shift1;
+ drflac_uint32 left = right + side;
+
+ pOutputSamples[i*2+0] = (drflac_int32)left;
+ pOutputSamples[i*2+1] = (drflac_int32)right;
+ }
+}
+#endif
+
+static DRFLAC_INLINE void drflac_read_pcm_frames_s32__decode_right_side(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int32* pOutputSamples)
+{
+#if defined(DRFLAC_SUPPORT_SSE2)
+ if (drflac__gIsSSE2Supported && pFlac->bitsPerSample <= 24) {
+ drflac_read_pcm_frames_s32__decode_right_side__sse2(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
+ } else
+#elif defined(DRFLAC_SUPPORT_NEON)
+ if (drflac__gIsNEONSupported && pFlac->bitsPerSample <= 24) {
+ drflac_read_pcm_frames_s32__decode_right_side__neon(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
+ } else
+#endif
+ {
+ /* Scalar fallback. */
+#if 0
+ drflac_read_pcm_frames_s32__decode_right_side__reference(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
+#else
+ drflac_read_pcm_frames_s32__decode_right_side__scalar(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
+#endif
+ }
+}
+
+
+#if 0
+static DRFLAC_INLINE void drflac_read_pcm_frames_s32__decode_mid_side__reference(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int32* pOutputSamples)
+{
+ for (drflac_uint64 i = 0; i < frameCount; ++i) {
+ drflac_uint32 mid = pInputSamples0U32[i] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 side = pInputSamples1U32[i] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+
+ mid = (mid << 1) | (side & 0x01);
+
+ pOutputSamples[i*2+0] = (drflac_int32)((drflac_uint32)((drflac_int32)(mid + side) >> 1) << unusedBitsPerSample);
+ pOutputSamples[i*2+1] = (drflac_int32)((drflac_uint32)((drflac_int32)(mid - side) >> 1) << unusedBitsPerSample);
+ }
+}
+#endif
+
+static DRFLAC_INLINE void drflac_read_pcm_frames_s32__decode_mid_side__scalar(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int32* pOutputSamples)
+{
+ drflac_uint64 i;
+ drflac_uint64 frameCount4 = frameCount >> 2;
+ const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
+ const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
+ drflac_int32 shift = unusedBitsPerSample;
+
+ if (shift > 0) {
+ shift -= 1;
+ for (i = 0; i < frameCount4; ++i) {
+ drflac_uint32 temp0L;
+ drflac_uint32 temp1L;
+ drflac_uint32 temp2L;
+ drflac_uint32 temp3L;
+ drflac_uint32 temp0R;
+ drflac_uint32 temp1R;
+ drflac_uint32 temp2R;
+ drflac_uint32 temp3R;
+
+ drflac_uint32 mid0 = pInputSamples0U32[i*4+0] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 mid1 = pInputSamples0U32[i*4+1] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 mid2 = pInputSamples0U32[i*4+2] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 mid3 = pInputSamples0U32[i*4+3] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+
+ drflac_uint32 side0 = pInputSamples1U32[i*4+0] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+ drflac_uint32 side1 = pInputSamples1U32[i*4+1] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+ drflac_uint32 side2 = pInputSamples1U32[i*4+2] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+ drflac_uint32 side3 = pInputSamples1U32[i*4+3] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+
+ mid0 = (mid0 << 1) | (side0 & 0x01);
+ mid1 = (mid1 << 1) | (side1 & 0x01);
+ mid2 = (mid2 << 1) | (side2 & 0x01);
+ mid3 = (mid3 << 1) | (side3 & 0x01);
+
+ temp0L = (mid0 + side0) << shift;
+ temp1L = (mid1 + side1) << shift;
+ temp2L = (mid2 + side2) << shift;
+ temp3L = (mid3 + side3) << shift;
+
+ temp0R = (mid0 - side0) << shift;
+ temp1R = (mid1 - side1) << shift;
+ temp2R = (mid2 - side2) << shift;
+ temp3R = (mid3 - side3) << shift;
+
+ pOutputSamples[i*8+0] = (drflac_int32)temp0L;
+ pOutputSamples[i*8+1] = (drflac_int32)temp0R;
+ pOutputSamples[i*8+2] = (drflac_int32)temp1L;
+ pOutputSamples[i*8+3] = (drflac_int32)temp1R;
+ pOutputSamples[i*8+4] = (drflac_int32)temp2L;
+ pOutputSamples[i*8+5] = (drflac_int32)temp2R;
+ pOutputSamples[i*8+6] = (drflac_int32)temp3L;
+ pOutputSamples[i*8+7] = (drflac_int32)temp3R;
+ }
+ } else {
+ for (i = 0; i < frameCount4; ++i) {
+ drflac_uint32 temp0L;
+ drflac_uint32 temp1L;
+ drflac_uint32 temp2L;
+ drflac_uint32 temp3L;
+ drflac_uint32 temp0R;
+ drflac_uint32 temp1R;
+ drflac_uint32 temp2R;
+ drflac_uint32 temp3R;
+
+ drflac_uint32 mid0 = pInputSamples0U32[i*4+0] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 mid1 = pInputSamples0U32[i*4+1] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 mid2 = pInputSamples0U32[i*4+2] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 mid3 = pInputSamples0U32[i*4+3] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+
+ drflac_uint32 side0 = pInputSamples1U32[i*4+0] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+ drflac_uint32 side1 = pInputSamples1U32[i*4+1] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+ drflac_uint32 side2 = pInputSamples1U32[i*4+2] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+ drflac_uint32 side3 = pInputSamples1U32[i*4+3] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+
+ mid0 = (mid0 << 1) | (side0 & 0x01);
+ mid1 = (mid1 << 1) | (side1 & 0x01);
+ mid2 = (mid2 << 1) | (side2 & 0x01);
+ mid3 = (mid3 << 1) | (side3 & 0x01);
+
+ temp0L = (drflac_uint32)((drflac_int32)(mid0 + side0) >> 1);
+ temp1L = (drflac_uint32)((drflac_int32)(mid1 + side1) >> 1);
+ temp2L = (drflac_uint32)((drflac_int32)(mid2 + side2) >> 1);
+ temp3L = (drflac_uint32)((drflac_int32)(mid3 + side3) >> 1);
+
+ temp0R = (drflac_uint32)((drflac_int32)(mid0 - side0) >> 1);
+ temp1R = (drflac_uint32)((drflac_int32)(mid1 - side1) >> 1);
+ temp2R = (drflac_uint32)((drflac_int32)(mid2 - side2) >> 1);
+ temp3R = (drflac_uint32)((drflac_int32)(mid3 - side3) >> 1);
+
+ pOutputSamples[i*8+0] = (drflac_int32)temp0L;
+ pOutputSamples[i*8+1] = (drflac_int32)temp0R;
+ pOutputSamples[i*8+2] = (drflac_int32)temp1L;
+ pOutputSamples[i*8+3] = (drflac_int32)temp1R;
+ pOutputSamples[i*8+4] = (drflac_int32)temp2L;
+ pOutputSamples[i*8+5] = (drflac_int32)temp2R;
+ pOutputSamples[i*8+6] = (drflac_int32)temp3L;
+ pOutputSamples[i*8+7] = (drflac_int32)temp3R;
+ }
+ }
+
+ for (i = (frameCount4 << 2); i < frameCount; ++i) {
+ drflac_uint32 mid = pInputSamples0U32[i] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 side = pInputSamples1U32[i] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+
+ mid = (mid << 1) | (side & 0x01);
+
+ pOutputSamples[i*2+0] = (drflac_int32)((drflac_uint32)((drflac_int32)(mid + side) >> 1) << unusedBitsPerSample);
+ pOutputSamples[i*2+1] = (drflac_int32)((drflac_uint32)((drflac_int32)(mid - side) >> 1) << unusedBitsPerSample);
+ }
+}
+
+#if defined(DRFLAC_SUPPORT_SSE2)
+static DRFLAC_INLINE void drflac_read_pcm_frames_s32__decode_mid_side__sse2(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int32* pOutputSamples)
+{
+ drflac_uint64 i;
+ drflac_uint64 frameCount4 = frameCount >> 2;
+ const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
+ const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
+ drflac_int32 shift = unusedBitsPerSample;
+
+ DRFLAC_ASSERT(pFlac->bitsPerSample <= 24);
+
+ if (shift == 0) {
+ for (i = 0; i < frameCount4; ++i) {
+ __m128i mid;
+ __m128i side;
+ __m128i left;
+ __m128i right;
+
+ mid = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples0 + i), pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample);
+ side = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples1 + i), pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample);
+
+ mid = _mm_or_si128(_mm_slli_epi32(mid, 1), _mm_and_si128(side, _mm_set1_epi32(0x01)));
+
+ left = _mm_srai_epi32(_mm_add_epi32(mid, side), 1);
+ right = _mm_srai_epi32(_mm_sub_epi32(mid, side), 1);
+
+ _mm_storeu_si128((__m128i*)(pOutputSamples + i*8 + 0), _mm_unpacklo_epi32(left, right));
+ _mm_storeu_si128((__m128i*)(pOutputSamples + i*8 + 4), _mm_unpackhi_epi32(left, right));
+ }
+
+ for (i = (frameCount4 << 2); i < frameCount; ++i) {
+ drflac_uint32 mid = pInputSamples0U32[i] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 side = pInputSamples1U32[i] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+
+ mid = (mid << 1) | (side & 0x01);
+
+ pOutputSamples[i*2+0] = (drflac_int32)(mid + side) >> 1;
+ pOutputSamples[i*2+1] = (drflac_int32)(mid - side) >> 1;
+ }
+ } else {
+ shift -= 1;
+ for (i = 0; i < frameCount4; ++i) {
+ __m128i mid;
+ __m128i side;
+ __m128i left;
+ __m128i right;
+
+ mid = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples0 + i), pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample);
+ side = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples1 + i), pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample);
+
+ mid = _mm_or_si128(_mm_slli_epi32(mid, 1), _mm_and_si128(side, _mm_set1_epi32(0x01)));
+
+ left = _mm_slli_epi32(_mm_add_epi32(mid, side), shift);
+ right = _mm_slli_epi32(_mm_sub_epi32(mid, side), shift);
+
+ _mm_storeu_si128((__m128i*)(pOutputSamples + i*8 + 0), _mm_unpacklo_epi32(left, right));
+ _mm_storeu_si128((__m128i*)(pOutputSamples + i*8 + 4), _mm_unpackhi_epi32(left, right));
+ }
+
+ for (i = (frameCount4 << 2); i < frameCount; ++i) {
+ drflac_uint32 mid = pInputSamples0U32[i] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 side = pInputSamples1U32[i] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+
+ mid = (mid << 1) | (side & 0x01);
+
+ pOutputSamples[i*2+0] = (drflac_int32)((mid + side) << shift);
+ pOutputSamples[i*2+1] = (drflac_int32)((mid - side) << shift);
+ }
+ }
+}
+#endif
+
+#if defined(DRFLAC_SUPPORT_NEON)
+static DRFLAC_INLINE void drflac_read_pcm_frames_s32__decode_mid_side__neon(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int32* pOutputSamples)
+{
+ drflac_uint64 i;
+ drflac_uint64 frameCount4 = frameCount >> 2;
+ const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
+ const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
+ drflac_int32 shift = unusedBitsPerSample;
+ int32x4_t wbpsShift0_4; /* wbps = Wasted Bits Per Sample */
+ int32x4_t wbpsShift1_4; /* wbps = Wasted Bits Per Sample */
+ uint32x4_t one4;
+
+ DRFLAC_ASSERT(pFlac->bitsPerSample <= 24);
+
+ wbpsShift0_4 = vdupq_n_s32(pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample);
+ wbpsShift1_4 = vdupq_n_s32(pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample);
+ one4 = vdupq_n_u32(1);
+
+ if (shift == 0) {
+ for (i = 0; i < frameCount4; ++i) {
+ uint32x4_t mid;
+ uint32x4_t side;
+ int32x4_t left;
+ int32x4_t right;
+
+ mid = vshlq_u32(vld1q_u32(pInputSamples0U32 + i*4), wbpsShift0_4);
+ side = vshlq_u32(vld1q_u32(pInputSamples1U32 + i*4), wbpsShift1_4);
+
+ mid = vorrq_u32(vshlq_n_u32(mid, 1), vandq_u32(side, one4));
+
+ left = vshrq_n_s32(vreinterpretq_s32_u32(vaddq_u32(mid, side)), 1);
+ right = vshrq_n_s32(vreinterpretq_s32_u32(vsubq_u32(mid, side)), 1);
+
+ drflac__vst2q_s32(pOutputSamples + i*8, vzipq_s32(left, right));
+ }
+
+ for (i = (frameCount4 << 2); i < frameCount; ++i) {
+ drflac_uint32 mid = pInputSamples0U32[i] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 side = pInputSamples1U32[i] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+
+ mid = (mid << 1) | (side & 0x01);
+
+ pOutputSamples[i*2+0] = (drflac_int32)(mid + side) >> 1;
+ pOutputSamples[i*2+1] = (drflac_int32)(mid - side) >> 1;
+ }
+ } else {
+ int32x4_t shift4;
+
+ shift -= 1;
+ shift4 = vdupq_n_s32(shift);
+
+ for (i = 0; i < frameCount4; ++i) {
+ uint32x4_t mid;
+ uint32x4_t side;
+ int32x4_t left;
+ int32x4_t right;
+
+ mid = vshlq_u32(vld1q_u32(pInputSamples0U32 + i*4), wbpsShift0_4);
+ side = vshlq_u32(vld1q_u32(pInputSamples1U32 + i*4), wbpsShift1_4);
+
+ mid = vorrq_u32(vshlq_n_u32(mid, 1), vandq_u32(side, one4));
+
+ left = vreinterpretq_s32_u32(vshlq_u32(vaddq_u32(mid, side), shift4));
+ right = vreinterpretq_s32_u32(vshlq_u32(vsubq_u32(mid, side), shift4));
+
+ drflac__vst2q_s32(pOutputSamples + i*8, vzipq_s32(left, right));
+ }
+
+ for (i = (frameCount4 << 2); i < frameCount; ++i) {
+ drflac_uint32 mid = pInputSamples0U32[i] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 side = pInputSamples1U32[i] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+
+ mid = (mid << 1) | (side & 0x01);
+
+ pOutputSamples[i*2+0] = (drflac_int32)((mid + side) << shift);
+ pOutputSamples[i*2+1] = (drflac_int32)((mid - side) << shift);
+ }
+ }
+}
+#endif
+
+static DRFLAC_INLINE void drflac_read_pcm_frames_s32__decode_mid_side(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int32* pOutputSamples)
+{
+#if defined(DRFLAC_SUPPORT_SSE2)
+ if (drflac__gIsSSE2Supported && pFlac->bitsPerSample <= 24) {
+ drflac_read_pcm_frames_s32__decode_mid_side__sse2(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
+ } else
+#elif defined(DRFLAC_SUPPORT_NEON)
+ if (drflac__gIsNEONSupported && pFlac->bitsPerSample <= 24) {
+ drflac_read_pcm_frames_s32__decode_mid_side__neon(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
+ } else
+#endif
+ {
+ /* Scalar fallback. */
+#if 0
+ drflac_read_pcm_frames_s32__decode_mid_side__reference(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
+#else
+ drflac_read_pcm_frames_s32__decode_mid_side__scalar(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
+#endif
+ }
+}
+
+
+#if 0
+static DRFLAC_INLINE void drflac_read_pcm_frames_s32__decode_independent_stereo__reference(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int32* pOutputSamples)
+{
+ for (drflac_uint64 i = 0; i < frameCount; ++i) {
+ pOutputSamples[i*2+0] = (drflac_int32)((drflac_uint32)pInputSamples0[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample));
+ pOutputSamples[i*2+1] = (drflac_int32)((drflac_uint32)pInputSamples1[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample));
+ }
+}
+#endif
+
+static DRFLAC_INLINE void drflac_read_pcm_frames_s32__decode_independent_stereo__scalar(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int32* pOutputSamples)
+{
+ drflac_uint64 i;
+ drflac_uint64 frameCount4 = frameCount >> 2;
+ const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
+ const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
+ drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+
+ for (i = 0; i < frameCount4; ++i) {
+ drflac_uint32 tempL0 = pInputSamples0U32[i*4+0] << shift0;
+ drflac_uint32 tempL1 = pInputSamples0U32[i*4+1] << shift0;
+ drflac_uint32 tempL2 = pInputSamples0U32[i*4+2] << shift0;
+ drflac_uint32 tempL3 = pInputSamples0U32[i*4+3] << shift0;
+
+ drflac_uint32 tempR0 = pInputSamples1U32[i*4+0] << shift1;
+ drflac_uint32 tempR1 = pInputSamples1U32[i*4+1] << shift1;
+ drflac_uint32 tempR2 = pInputSamples1U32[i*4+2] << shift1;
+ drflac_uint32 tempR3 = pInputSamples1U32[i*4+3] << shift1;
+
+ pOutputSamples[i*8+0] = (drflac_int32)tempL0;
+ pOutputSamples[i*8+1] = (drflac_int32)tempR0;
+ pOutputSamples[i*8+2] = (drflac_int32)tempL1;
+ pOutputSamples[i*8+3] = (drflac_int32)tempR1;
+ pOutputSamples[i*8+4] = (drflac_int32)tempL2;
+ pOutputSamples[i*8+5] = (drflac_int32)tempR2;
+ pOutputSamples[i*8+6] = (drflac_int32)tempL3;
+ pOutputSamples[i*8+7] = (drflac_int32)tempR3;
+ }
+
+ for (i = (frameCount4 << 2); i < frameCount; ++i) {
+ pOutputSamples[i*2+0] = (drflac_int32)(pInputSamples0U32[i] << shift0);
+ pOutputSamples[i*2+1] = (drflac_int32)(pInputSamples1U32[i] << shift1);
+ }
+}
+
+#if defined(DRFLAC_SUPPORT_SSE2)
+static DRFLAC_INLINE void drflac_read_pcm_frames_s32__decode_independent_stereo__sse2(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int32* pOutputSamples)
+{
+ drflac_uint64 i;
+ drflac_uint64 frameCount4 = frameCount >> 2;
+ const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
+ const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
+ drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+
+ for (i = 0; i < frameCount4; ++i) {
+ __m128i left = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples0 + i), shift0);
+ __m128i right = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples1 + i), shift1);
+
+ _mm_storeu_si128((__m128i*)(pOutputSamples + i*8 + 0), _mm_unpacklo_epi32(left, right));
+ _mm_storeu_si128((__m128i*)(pOutputSamples + i*8 + 4), _mm_unpackhi_epi32(left, right));
+ }
+
+ for (i = (frameCount4 << 2); i < frameCount; ++i) {
+ pOutputSamples[i*2+0] = (drflac_int32)(pInputSamples0U32[i] << shift0);
+ pOutputSamples[i*2+1] = (drflac_int32)(pInputSamples1U32[i] << shift1);
+ }
+}
+#endif
+
+#if defined(DRFLAC_SUPPORT_NEON)
+static DRFLAC_INLINE void drflac_read_pcm_frames_s32__decode_independent_stereo__neon(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int32* pOutputSamples)
+{
+ drflac_uint64 i;
+ drflac_uint64 frameCount4 = frameCount >> 2;
+ const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
+ const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
+ drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+
+ int32x4_t shift4_0 = vdupq_n_s32(shift0);
+ int32x4_t shift4_1 = vdupq_n_s32(shift1);
+
+ for (i = 0; i < frameCount4; ++i) {
+ int32x4_t left;
+ int32x4_t right;
+
+ left = vreinterpretq_s32_u32(vshlq_u32(vld1q_u32(pInputSamples0U32 + i*4), shift4_0));
+ right = vreinterpretq_s32_u32(vshlq_u32(vld1q_u32(pInputSamples1U32 + i*4), shift4_1));
+
+ drflac__vst2q_s32(pOutputSamples + i*8, vzipq_s32(left, right));
+ }
+
+ for (i = (frameCount4 << 2); i < frameCount; ++i) {
+ pOutputSamples[i*2+0] = (drflac_int32)(pInputSamples0U32[i] << shift0);
+ pOutputSamples[i*2+1] = (drflac_int32)(pInputSamples1U32[i] << shift1);
+ }
+}
+#endif
+
+static DRFLAC_INLINE void drflac_read_pcm_frames_s32__decode_independent_stereo(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int32* pOutputSamples)
+{
+#if defined(DRFLAC_SUPPORT_SSE2)
+ if (drflac__gIsSSE2Supported && pFlac->bitsPerSample <= 24) {
+ drflac_read_pcm_frames_s32__decode_independent_stereo__sse2(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
+ } else
+#elif defined(DRFLAC_SUPPORT_NEON)
+ if (drflac__gIsNEONSupported && pFlac->bitsPerSample <= 24) {
+ drflac_read_pcm_frames_s32__decode_independent_stereo__neon(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
+ } else
+#endif
+ {
+ /* Scalar fallback. */
+#if 0
+ drflac_read_pcm_frames_s32__decode_independent_stereo__reference(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
+#else
+ drflac_read_pcm_frames_s32__decode_independent_stereo__scalar(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
+#endif
+ }
+}
+
+
+DRFLAC_API drflac_uint64 drflac_read_pcm_frames_s32(drflac* pFlac, drflac_uint64 framesToRead, drflac_int32* pBufferOut)
+{
+ drflac_uint64 framesRead;
+ drflac_uint32 unusedBitsPerSample;
+
+ if (pFlac == NULL || framesToRead == 0) {
+ return 0;
+ }
+
+ if (pBufferOut == NULL) {
+ return drflac__seek_forward_by_pcm_frames(pFlac, framesToRead);
+ }
+
+ DRFLAC_ASSERT(pFlac->bitsPerSample <= 32);
+ unusedBitsPerSample = 32 - pFlac->bitsPerSample;
+
+ framesRead = 0;
+ while (framesToRead > 0) {
+ /* If we've run out of samples in this frame, go to the next. */
+ if (pFlac->currentFLACFrame.pcmFramesRemaining == 0) {
+ if (!drflac__read_and_decode_next_flac_frame(pFlac)) {
+ break; /* Couldn't read the next frame, so just break from the loop and return. */
+ }
+ } else {
+ unsigned int channelCount = drflac__get_channel_count_from_channel_assignment(pFlac->currentFLACFrame.header.channelAssignment);
+ drflac_uint64 iFirstPCMFrame = pFlac->currentFLACFrame.header.blockSizeInPCMFrames - pFlac->currentFLACFrame.pcmFramesRemaining;
+ drflac_uint64 frameCountThisIteration = framesToRead;
+
+ if (frameCountThisIteration > pFlac->currentFLACFrame.pcmFramesRemaining) {
+ frameCountThisIteration = pFlac->currentFLACFrame.pcmFramesRemaining;
+ }
+
+ if (channelCount == 2) {
+ const drflac_int32* pDecodedSamples0 = pFlac->currentFLACFrame.subframes[0].pSamplesS32 + iFirstPCMFrame;
+ const drflac_int32* pDecodedSamples1 = pFlac->currentFLACFrame.subframes[1].pSamplesS32 + iFirstPCMFrame;
+
+ switch (pFlac->currentFLACFrame.header.channelAssignment)
+ {
+ case DRFLAC_CHANNEL_ASSIGNMENT_LEFT_SIDE:
+ {
+ drflac_read_pcm_frames_s32__decode_left_side(pFlac, frameCountThisIteration, unusedBitsPerSample, pDecodedSamples0, pDecodedSamples1, pBufferOut);
+ } break;
+
+ case DRFLAC_CHANNEL_ASSIGNMENT_RIGHT_SIDE:
+ {
+ drflac_read_pcm_frames_s32__decode_right_side(pFlac, frameCountThisIteration, unusedBitsPerSample, pDecodedSamples0, pDecodedSamples1, pBufferOut);
+ } break;
+
+ case DRFLAC_CHANNEL_ASSIGNMENT_MID_SIDE:
+ {
+ drflac_read_pcm_frames_s32__decode_mid_side(pFlac, frameCountThisIteration, unusedBitsPerSample, pDecodedSamples0, pDecodedSamples1, pBufferOut);
+ } break;
+
+ case DRFLAC_CHANNEL_ASSIGNMENT_INDEPENDENT:
+ default:
+ {
+ drflac_read_pcm_frames_s32__decode_independent_stereo(pFlac, frameCountThisIteration, unusedBitsPerSample, pDecodedSamples0, pDecodedSamples1, pBufferOut);
+ } break;
+ }
+ } else {
+ /* Generic interleaving. */
+ drflac_uint64 i;
+ for (i = 0; i < frameCountThisIteration; ++i) {
+ unsigned int j;
+ for (j = 0; j < channelCount; ++j) {
+ pBufferOut[(i*channelCount)+j] = (drflac_int32)((drflac_uint32)(pFlac->currentFLACFrame.subframes[j].pSamplesS32[iFirstPCMFrame + i]) << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[j].wastedBitsPerSample));
+ }
+ }
+ }
+
+ framesRead += frameCountThisIteration;
+ pBufferOut += frameCountThisIteration * channelCount;
+ framesToRead -= frameCountThisIteration;
+ pFlac->currentPCMFrame += frameCountThisIteration;
+ pFlac->currentFLACFrame.pcmFramesRemaining -= (drflac_uint32)frameCountThisIteration;
+ }
+ }
+
+ return framesRead;
+}
+
+
+#if 0
+static DRFLAC_INLINE void drflac_read_pcm_frames_s16__decode_left_side__reference(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int16* pOutputSamples)
+{
+ drflac_uint64 i;
+ for (i = 0; i < frameCount; ++i) {
+ drflac_uint32 left = (drflac_uint32)pInputSamples0[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample);
+ drflac_uint32 side = (drflac_uint32)pInputSamples1[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample);
+ drflac_uint32 right = left - side;
+
+ left >>= 16;
+ right >>= 16;
+
+ pOutputSamples[i*2+0] = (drflac_int16)left;
+ pOutputSamples[i*2+1] = (drflac_int16)right;
+ }
+}
+#endif
+
+static DRFLAC_INLINE void drflac_read_pcm_frames_s16__decode_left_side__scalar(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int16* pOutputSamples)
+{
+ drflac_uint64 i;
+ drflac_uint64 frameCount4 = frameCount >> 2;
+ const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
+ const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
+ drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+
+ for (i = 0; i < frameCount4; ++i) {
+ drflac_uint32 left0 = pInputSamples0U32[i*4+0] << shift0;
+ drflac_uint32 left1 = pInputSamples0U32[i*4+1] << shift0;
+ drflac_uint32 left2 = pInputSamples0U32[i*4+2] << shift0;
+ drflac_uint32 left3 = pInputSamples0U32[i*4+3] << shift0;
+
+ drflac_uint32 side0 = pInputSamples1U32[i*4+0] << shift1;
+ drflac_uint32 side1 = pInputSamples1U32[i*4+1] << shift1;
+ drflac_uint32 side2 = pInputSamples1U32[i*4+2] << shift1;
+ drflac_uint32 side3 = pInputSamples1U32[i*4+3] << shift1;
+
+ drflac_uint32 right0 = left0 - side0;
+ drflac_uint32 right1 = left1 - side1;
+ drflac_uint32 right2 = left2 - side2;
+ drflac_uint32 right3 = left3 - side3;
+
+ left0 >>= 16;
+ left1 >>= 16;
+ left2 >>= 16;
+ left3 >>= 16;
+
+ right0 >>= 16;
+ right1 >>= 16;
+ right2 >>= 16;
+ right3 >>= 16;
+
+ pOutputSamples[i*8+0] = (drflac_int16)left0;
+ pOutputSamples[i*8+1] = (drflac_int16)right0;
+ pOutputSamples[i*8+2] = (drflac_int16)left1;
+ pOutputSamples[i*8+3] = (drflac_int16)right1;
+ pOutputSamples[i*8+4] = (drflac_int16)left2;
+ pOutputSamples[i*8+5] = (drflac_int16)right2;
+ pOutputSamples[i*8+6] = (drflac_int16)left3;
+ pOutputSamples[i*8+7] = (drflac_int16)right3;
+ }
+
+ for (i = (frameCount4 << 2); i < frameCount; ++i) {
+ drflac_uint32 left = pInputSamples0U32[i] << shift0;
+ drflac_uint32 side = pInputSamples1U32[i] << shift1;
+ drflac_uint32 right = left - side;
+
+ left >>= 16;
+ right >>= 16;
+
+ pOutputSamples[i*2+0] = (drflac_int16)left;
+ pOutputSamples[i*2+1] = (drflac_int16)right;
+ }
+}
+
+#if defined(DRFLAC_SUPPORT_SSE2)
+static DRFLAC_INLINE void drflac_read_pcm_frames_s16__decode_left_side__sse2(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int16* pOutputSamples)
+{
+ drflac_uint64 i;
+ drflac_uint64 frameCount4 = frameCount >> 2;
+ const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
+ const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
+ drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+
+ DRFLAC_ASSERT(pFlac->bitsPerSample <= 24);
+
+ for (i = 0; i < frameCount4; ++i) {
+ __m128i left = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples0 + i), shift0);
+ __m128i side = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples1 + i), shift1);
+ __m128i right = _mm_sub_epi32(left, side);
+
+ left = _mm_srai_epi32(left, 16);
+ right = _mm_srai_epi32(right, 16);
+
+ _mm_storeu_si128((__m128i*)(pOutputSamples + i*8), drflac__mm_packs_interleaved_epi32(left, right));
+ }
+
+ for (i = (frameCount4 << 2); i < frameCount; ++i) {
+ drflac_uint32 left = pInputSamples0U32[i] << shift0;
+ drflac_uint32 side = pInputSamples1U32[i] << shift1;
+ drflac_uint32 right = left - side;
+
+ left >>= 16;
+ right >>= 16;
+
+ pOutputSamples[i*2+0] = (drflac_int16)left;
+ pOutputSamples[i*2+1] = (drflac_int16)right;
+ }
+}
+#endif
+
+#if defined(DRFLAC_SUPPORT_NEON)
+static DRFLAC_INLINE void drflac_read_pcm_frames_s16__decode_left_side__neon(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int16* pOutputSamples)
+{
+ drflac_uint64 i;
+ drflac_uint64 frameCount4 = frameCount >> 2;
+ const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
+ const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
+ drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+ int32x4_t shift0_4;
+ int32x4_t shift1_4;
+
+ DRFLAC_ASSERT(pFlac->bitsPerSample <= 24);
+
+ shift0_4 = vdupq_n_s32(shift0);
+ shift1_4 = vdupq_n_s32(shift1);
+
+ for (i = 0; i < frameCount4; ++i) {
+ uint32x4_t left;
+ uint32x4_t side;
+ uint32x4_t right;
+
+ left = vshlq_u32(vld1q_u32(pInputSamples0U32 + i*4), shift0_4);
+ side = vshlq_u32(vld1q_u32(pInputSamples1U32 + i*4), shift1_4);
+ right = vsubq_u32(left, side);
+
+ left = vshrq_n_u32(left, 16);
+ right = vshrq_n_u32(right, 16);
+
+ drflac__vst2q_u16((drflac_uint16*)pOutputSamples + i*8, vzip_u16(vmovn_u32(left), vmovn_u32(right)));
+ }
+
+ for (i = (frameCount4 << 2); i < frameCount; ++i) {
+ drflac_uint32 left = pInputSamples0U32[i] << shift0;
+ drflac_uint32 side = pInputSamples1U32[i] << shift1;
+ drflac_uint32 right = left - side;
+
+ left >>= 16;
+ right >>= 16;
+
+ pOutputSamples[i*2+0] = (drflac_int16)left;
+ pOutputSamples[i*2+1] = (drflac_int16)right;
+ }
+}
+#endif
+
+static DRFLAC_INLINE void drflac_read_pcm_frames_s16__decode_left_side(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int16* pOutputSamples)
+{
+#if defined(DRFLAC_SUPPORT_SSE2)
+ if (drflac__gIsSSE2Supported && pFlac->bitsPerSample <= 24) {
+ drflac_read_pcm_frames_s16__decode_left_side__sse2(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
+ } else
+#elif defined(DRFLAC_SUPPORT_NEON)
+ if (drflac__gIsNEONSupported && pFlac->bitsPerSample <= 24) {
+ drflac_read_pcm_frames_s16__decode_left_side__neon(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
+ } else
+#endif
+ {
+ /* Scalar fallback. */
+#if 0
+ drflac_read_pcm_frames_s16__decode_left_side__reference(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
+#else
+ drflac_read_pcm_frames_s16__decode_left_side__scalar(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
+#endif
+ }
+}
+
+
+#if 0
+static DRFLAC_INLINE void drflac_read_pcm_frames_s16__decode_right_side__reference(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int16* pOutputSamples)
+{
+ drflac_uint64 i;
+ for (i = 0; i < frameCount; ++i) {
+ drflac_uint32 side = (drflac_uint32)pInputSamples0[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample);
+ drflac_uint32 right = (drflac_uint32)pInputSamples1[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample);
+ drflac_uint32 left = right + side;
+
+ left >>= 16;
+ right >>= 16;
+
+ pOutputSamples[i*2+0] = (drflac_int16)left;
+ pOutputSamples[i*2+1] = (drflac_int16)right;
+ }
+}
+#endif
+
+static DRFLAC_INLINE void drflac_read_pcm_frames_s16__decode_right_side__scalar(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int16* pOutputSamples)
+{
+ drflac_uint64 i;
+ drflac_uint64 frameCount4 = frameCount >> 2;
+ const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
+ const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
+ drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+
+ for (i = 0; i < frameCount4; ++i) {
+ drflac_uint32 side0 = pInputSamples0U32[i*4+0] << shift0;
+ drflac_uint32 side1 = pInputSamples0U32[i*4+1] << shift0;
+ drflac_uint32 side2 = pInputSamples0U32[i*4+2] << shift0;
+ drflac_uint32 side3 = pInputSamples0U32[i*4+3] << shift0;
+
+ drflac_uint32 right0 = pInputSamples1U32[i*4+0] << shift1;
+ drflac_uint32 right1 = pInputSamples1U32[i*4+1] << shift1;
+ drflac_uint32 right2 = pInputSamples1U32[i*4+2] << shift1;
+ drflac_uint32 right3 = pInputSamples1U32[i*4+3] << shift1;
+
+ drflac_uint32 left0 = right0 + side0;
+ drflac_uint32 left1 = right1 + side1;
+ drflac_uint32 left2 = right2 + side2;
+ drflac_uint32 left3 = right3 + side3;
+
+ left0 >>= 16;
+ left1 >>= 16;
+ left2 >>= 16;
+ left3 >>= 16;
+
+ right0 >>= 16;
+ right1 >>= 16;
+ right2 >>= 16;
+ right3 >>= 16;
+
+ pOutputSamples[i*8+0] = (drflac_int16)left0;
+ pOutputSamples[i*8+1] = (drflac_int16)right0;
+ pOutputSamples[i*8+2] = (drflac_int16)left1;
+ pOutputSamples[i*8+3] = (drflac_int16)right1;
+ pOutputSamples[i*8+4] = (drflac_int16)left2;
+ pOutputSamples[i*8+5] = (drflac_int16)right2;
+ pOutputSamples[i*8+6] = (drflac_int16)left3;
+ pOutputSamples[i*8+7] = (drflac_int16)right3;
+ }
+
+ for (i = (frameCount4 << 2); i < frameCount; ++i) {
+ drflac_uint32 side = pInputSamples0U32[i] << shift0;
+ drflac_uint32 right = pInputSamples1U32[i] << shift1;
+ drflac_uint32 left = right + side;
+
+ left >>= 16;
+ right >>= 16;
+
+ pOutputSamples[i*2+0] = (drflac_int16)left;
+ pOutputSamples[i*2+1] = (drflac_int16)right;
+ }
+}
+
+#if defined(DRFLAC_SUPPORT_SSE2)
+static DRFLAC_INLINE void drflac_read_pcm_frames_s16__decode_right_side__sse2(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int16* pOutputSamples)
+{
+ drflac_uint64 i;
+ drflac_uint64 frameCount4 = frameCount >> 2;
+ const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
+ const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
+ drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+
+ DRFLAC_ASSERT(pFlac->bitsPerSample <= 24);
+
+ for (i = 0; i < frameCount4; ++i) {
+ __m128i side = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples0 + i), shift0);
+ __m128i right = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples1 + i), shift1);
+ __m128i left = _mm_add_epi32(right, side);
+
+ left = _mm_srai_epi32(left, 16);
+ right = _mm_srai_epi32(right, 16);
+
+ _mm_storeu_si128((__m128i*)(pOutputSamples + i*8), drflac__mm_packs_interleaved_epi32(left, right));
+ }
+
+ for (i = (frameCount4 << 2); i < frameCount; ++i) {
+ drflac_uint32 side = pInputSamples0U32[i] << shift0;
+ drflac_uint32 right = pInputSamples1U32[i] << shift1;
+ drflac_uint32 left = right + side;
+
+ left >>= 16;
+ right >>= 16;
+
+ pOutputSamples[i*2+0] = (drflac_int16)left;
+ pOutputSamples[i*2+1] = (drflac_int16)right;
+ }
+}
+#endif
+
+#if defined(DRFLAC_SUPPORT_NEON)
+static DRFLAC_INLINE void drflac_read_pcm_frames_s16__decode_right_side__neon(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int16* pOutputSamples)
+{
+ drflac_uint64 i;
+ drflac_uint64 frameCount4 = frameCount >> 2;
+ const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
+ const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
+ drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+ int32x4_t shift0_4;
+ int32x4_t shift1_4;
+
+ DRFLAC_ASSERT(pFlac->bitsPerSample <= 24);
+
+ shift0_4 = vdupq_n_s32(shift0);
+ shift1_4 = vdupq_n_s32(shift1);
+
+ for (i = 0; i < frameCount4; ++i) {
+ uint32x4_t side;
+ uint32x4_t right;
+ uint32x4_t left;
+
+ side = vshlq_u32(vld1q_u32(pInputSamples0U32 + i*4), shift0_4);
+ right = vshlq_u32(vld1q_u32(pInputSamples1U32 + i*4), shift1_4);
+ left = vaddq_u32(right, side);
+
+ left = vshrq_n_u32(left, 16);
+ right = vshrq_n_u32(right, 16);
+
+ drflac__vst2q_u16((drflac_uint16*)pOutputSamples + i*8, vzip_u16(vmovn_u32(left), vmovn_u32(right)));
+ }
+
+ for (i = (frameCount4 << 2); i < frameCount; ++i) {
+ drflac_uint32 side = pInputSamples0U32[i] << shift0;
+ drflac_uint32 right = pInputSamples1U32[i] << shift1;
+ drflac_uint32 left = right + side;
+
+ left >>= 16;
+ right >>= 16;
+
+ pOutputSamples[i*2+0] = (drflac_int16)left;
+ pOutputSamples[i*2+1] = (drflac_int16)right;
+ }
+}
+#endif
+
+static DRFLAC_INLINE void drflac_read_pcm_frames_s16__decode_right_side(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int16* pOutputSamples)
+{
+#if defined(DRFLAC_SUPPORT_SSE2)
+ if (drflac__gIsSSE2Supported && pFlac->bitsPerSample <= 24) {
+ drflac_read_pcm_frames_s16__decode_right_side__sse2(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
+ } else
+#elif defined(DRFLAC_SUPPORT_NEON)
+ if (drflac__gIsNEONSupported && pFlac->bitsPerSample <= 24) {
+ drflac_read_pcm_frames_s16__decode_right_side__neon(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
+ } else
+#endif
+ {
+ /* Scalar fallback. */
+#if 0
+ drflac_read_pcm_frames_s16__decode_right_side__reference(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
+#else
+ drflac_read_pcm_frames_s16__decode_right_side__scalar(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
+#endif
+ }
+}
+
+
+#if 0
+static DRFLAC_INLINE void drflac_read_pcm_frames_s16__decode_mid_side__reference(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int16* pOutputSamples)
+{
+ for (drflac_uint64 i = 0; i < frameCount; ++i) {
+ drflac_uint32 mid = (drflac_uint32)pInputSamples0[i] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 side = (drflac_uint32)pInputSamples1[i] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+
+ mid = (mid << 1) | (side & 0x01);
+
+ pOutputSamples[i*2+0] = (drflac_int16)(((drflac_uint32)((drflac_int32)(mid + side) >> 1) << unusedBitsPerSample) >> 16);
+ pOutputSamples[i*2+1] = (drflac_int16)(((drflac_uint32)((drflac_int32)(mid - side) >> 1) << unusedBitsPerSample) >> 16);
+ }
+}
+#endif
+
+static DRFLAC_INLINE void drflac_read_pcm_frames_s16__decode_mid_side__scalar(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int16* pOutputSamples)
+{
+ drflac_uint64 i;
+ drflac_uint64 frameCount4 = frameCount >> 2;
+ const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
+ const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
+ drflac_uint32 shift = unusedBitsPerSample;
+
+ if (shift > 0) {
+ shift -= 1;
+ for (i = 0; i < frameCount4; ++i) {
+ drflac_uint32 temp0L;
+ drflac_uint32 temp1L;
+ drflac_uint32 temp2L;
+ drflac_uint32 temp3L;
+ drflac_uint32 temp0R;
+ drflac_uint32 temp1R;
+ drflac_uint32 temp2R;
+ drflac_uint32 temp3R;
+
+ drflac_uint32 mid0 = pInputSamples0U32[i*4+0] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 mid1 = pInputSamples0U32[i*4+1] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 mid2 = pInputSamples0U32[i*4+2] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 mid3 = pInputSamples0U32[i*4+3] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+
+ drflac_uint32 side0 = pInputSamples1U32[i*4+0] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+ drflac_uint32 side1 = pInputSamples1U32[i*4+1] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+ drflac_uint32 side2 = pInputSamples1U32[i*4+2] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+ drflac_uint32 side3 = pInputSamples1U32[i*4+3] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+
+ mid0 = (mid0 << 1) | (side0 & 0x01);
+ mid1 = (mid1 << 1) | (side1 & 0x01);
+ mid2 = (mid2 << 1) | (side2 & 0x01);
+ mid3 = (mid3 << 1) | (side3 & 0x01);
+
+ temp0L = (mid0 + side0) << shift;
+ temp1L = (mid1 + side1) << shift;
+ temp2L = (mid2 + side2) << shift;
+ temp3L = (mid3 + side3) << shift;
+
+ temp0R = (mid0 - side0) << shift;
+ temp1R = (mid1 - side1) << shift;
+ temp2R = (mid2 - side2) << shift;
+ temp3R = (mid3 - side3) << shift;
+
+ temp0L >>= 16;
+ temp1L >>= 16;
+ temp2L >>= 16;
+ temp3L >>= 16;
+
+ temp0R >>= 16;
+ temp1R >>= 16;
+ temp2R >>= 16;
+ temp3R >>= 16;
+
+ pOutputSamples[i*8+0] = (drflac_int16)temp0L;
+ pOutputSamples[i*8+1] = (drflac_int16)temp0R;
+ pOutputSamples[i*8+2] = (drflac_int16)temp1L;
+ pOutputSamples[i*8+3] = (drflac_int16)temp1R;
+ pOutputSamples[i*8+4] = (drflac_int16)temp2L;
+ pOutputSamples[i*8+5] = (drflac_int16)temp2R;
+ pOutputSamples[i*8+6] = (drflac_int16)temp3L;
+ pOutputSamples[i*8+7] = (drflac_int16)temp3R;
+ }
+ } else {
+ for (i = 0; i < frameCount4; ++i) {
+ drflac_uint32 temp0L;
+ drflac_uint32 temp1L;
+ drflac_uint32 temp2L;
+ drflac_uint32 temp3L;
+ drflac_uint32 temp0R;
+ drflac_uint32 temp1R;
+ drflac_uint32 temp2R;
+ drflac_uint32 temp3R;
+
+ drflac_uint32 mid0 = pInputSamples0U32[i*4+0] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 mid1 = pInputSamples0U32[i*4+1] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 mid2 = pInputSamples0U32[i*4+2] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 mid3 = pInputSamples0U32[i*4+3] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+
+ drflac_uint32 side0 = pInputSamples1U32[i*4+0] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+ drflac_uint32 side1 = pInputSamples1U32[i*4+1] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+ drflac_uint32 side2 = pInputSamples1U32[i*4+2] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+ drflac_uint32 side3 = pInputSamples1U32[i*4+3] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+
+ mid0 = (mid0 << 1) | (side0 & 0x01);
+ mid1 = (mid1 << 1) | (side1 & 0x01);
+ mid2 = (mid2 << 1) | (side2 & 0x01);
+ mid3 = (mid3 << 1) | (side3 & 0x01);
+
+ temp0L = ((drflac_int32)(mid0 + side0) >> 1);
+ temp1L = ((drflac_int32)(mid1 + side1) >> 1);
+ temp2L = ((drflac_int32)(mid2 + side2) >> 1);
+ temp3L = ((drflac_int32)(mid3 + side3) >> 1);
+
+ temp0R = ((drflac_int32)(mid0 - side0) >> 1);
+ temp1R = ((drflac_int32)(mid1 - side1) >> 1);
+ temp2R = ((drflac_int32)(mid2 - side2) >> 1);
+ temp3R = ((drflac_int32)(mid3 - side3) >> 1);
+
+ temp0L >>= 16;
+ temp1L >>= 16;
+ temp2L >>= 16;
+ temp3L >>= 16;
+
+ temp0R >>= 16;
+ temp1R >>= 16;
+ temp2R >>= 16;
+ temp3R >>= 16;
+
+ pOutputSamples[i*8+0] = (drflac_int16)temp0L;
+ pOutputSamples[i*8+1] = (drflac_int16)temp0R;
+ pOutputSamples[i*8+2] = (drflac_int16)temp1L;
+ pOutputSamples[i*8+3] = (drflac_int16)temp1R;
+ pOutputSamples[i*8+4] = (drflac_int16)temp2L;
+ pOutputSamples[i*8+5] = (drflac_int16)temp2R;
+ pOutputSamples[i*8+6] = (drflac_int16)temp3L;
+ pOutputSamples[i*8+7] = (drflac_int16)temp3R;
+ }
+ }
+
+ for (i = (frameCount4 << 2); i < frameCount; ++i) {
+ drflac_uint32 mid = pInputSamples0U32[i] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 side = pInputSamples1U32[i] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+
+ mid = (mid << 1) | (side & 0x01);
+
+ pOutputSamples[i*2+0] = (drflac_int16)(((drflac_uint32)((drflac_int32)(mid + side) >> 1) << unusedBitsPerSample) >> 16);
+ pOutputSamples[i*2+1] = (drflac_int16)(((drflac_uint32)((drflac_int32)(mid - side) >> 1) << unusedBitsPerSample) >> 16);
+ }
+}
+
+#if defined(DRFLAC_SUPPORT_SSE2)
+static DRFLAC_INLINE void drflac_read_pcm_frames_s16__decode_mid_side__sse2(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int16* pOutputSamples)
+{
+ drflac_uint64 i;
+ drflac_uint64 frameCount4 = frameCount >> 2;
+ const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
+ const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
+ drflac_uint32 shift = unusedBitsPerSample;
+
+ DRFLAC_ASSERT(pFlac->bitsPerSample <= 24);
+
+ if (shift == 0) {
+ for (i = 0; i < frameCount4; ++i) {
+ __m128i mid;
+ __m128i side;
+ __m128i left;
+ __m128i right;
+
+ mid = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples0 + i), pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample);
+ side = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples1 + i), pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample);
+
+ mid = _mm_or_si128(_mm_slli_epi32(mid, 1), _mm_and_si128(side, _mm_set1_epi32(0x01)));
+
+ left = _mm_srai_epi32(_mm_add_epi32(mid, side), 1);
+ right = _mm_srai_epi32(_mm_sub_epi32(mid, side), 1);
+
+ left = _mm_srai_epi32(left, 16);
+ right = _mm_srai_epi32(right, 16);
+
+ _mm_storeu_si128((__m128i*)(pOutputSamples + i*8), drflac__mm_packs_interleaved_epi32(left, right));
+ }
+
+ for (i = (frameCount4 << 2); i < frameCount; ++i) {
+ drflac_uint32 mid = pInputSamples0U32[i] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 side = pInputSamples1U32[i] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+
+ mid = (mid << 1) | (side & 0x01);
+
+ pOutputSamples[i*2+0] = (drflac_int16)(((drflac_int32)(mid + side) >> 1) >> 16);
+ pOutputSamples[i*2+1] = (drflac_int16)(((drflac_int32)(mid - side) >> 1) >> 16);
+ }
+ } else {
+ shift -= 1;
+ for (i = 0; i < frameCount4; ++i) {
+ __m128i mid;
+ __m128i side;
+ __m128i left;
+ __m128i right;
+
+ mid = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples0 + i), pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample);
+ side = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples1 + i), pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample);
+
+ mid = _mm_or_si128(_mm_slli_epi32(mid, 1), _mm_and_si128(side, _mm_set1_epi32(0x01)));
+
+ left = _mm_slli_epi32(_mm_add_epi32(mid, side), shift);
+ right = _mm_slli_epi32(_mm_sub_epi32(mid, side), shift);
+
+ left = _mm_srai_epi32(left, 16);
+ right = _mm_srai_epi32(right, 16);
+
+ _mm_storeu_si128((__m128i*)(pOutputSamples + i*8), drflac__mm_packs_interleaved_epi32(left, right));
+ }
+
+ for (i = (frameCount4 << 2); i < frameCount; ++i) {
+ drflac_uint32 mid = pInputSamples0U32[i] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 side = pInputSamples1U32[i] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+
+ mid = (mid << 1) | (side & 0x01);
+
+ pOutputSamples[i*2+0] = (drflac_int16)(((mid + side) << shift) >> 16);
+ pOutputSamples[i*2+1] = (drflac_int16)(((mid - side) << shift) >> 16);
+ }
+ }
+}
+#endif
+
+#if defined(DRFLAC_SUPPORT_NEON)
+static DRFLAC_INLINE void drflac_read_pcm_frames_s16__decode_mid_side__neon(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int16* pOutputSamples)
+{
+ drflac_uint64 i;
+ drflac_uint64 frameCount4 = frameCount >> 2;
+ const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
+ const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
+ drflac_uint32 shift = unusedBitsPerSample;
+ int32x4_t wbpsShift0_4; /* wbps = Wasted Bits Per Sample */
+ int32x4_t wbpsShift1_4; /* wbps = Wasted Bits Per Sample */
+
+ DRFLAC_ASSERT(pFlac->bitsPerSample <= 24);
+
+ wbpsShift0_4 = vdupq_n_s32(pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample);
+ wbpsShift1_4 = vdupq_n_s32(pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample);
+
+ if (shift == 0) {
+ for (i = 0; i < frameCount4; ++i) {
+ uint32x4_t mid;
+ uint32x4_t side;
+ int32x4_t left;
+ int32x4_t right;
+
+ mid = vshlq_u32(vld1q_u32(pInputSamples0U32 + i*4), wbpsShift0_4);
+ side = vshlq_u32(vld1q_u32(pInputSamples1U32 + i*4), wbpsShift1_4);
+
+ mid = vorrq_u32(vshlq_n_u32(mid, 1), vandq_u32(side, vdupq_n_u32(1)));
+
+ left = vshrq_n_s32(vreinterpretq_s32_u32(vaddq_u32(mid, side)), 1);
+ right = vshrq_n_s32(vreinterpretq_s32_u32(vsubq_u32(mid, side)), 1);
+
+ left = vshrq_n_s32(left, 16);
+ right = vshrq_n_s32(right, 16);
+
+ drflac__vst2q_s16(pOutputSamples + i*8, vzip_s16(vmovn_s32(left), vmovn_s32(right)));
+ }
+
+ for (i = (frameCount4 << 2); i < frameCount; ++i) {
+ drflac_uint32 mid = pInputSamples0U32[i] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 side = pInputSamples1U32[i] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+
+ mid = (mid << 1) | (side & 0x01);
+
+ pOutputSamples[i*2+0] = (drflac_int16)(((drflac_int32)(mid + side) >> 1) >> 16);
+ pOutputSamples[i*2+1] = (drflac_int16)(((drflac_int32)(mid - side) >> 1) >> 16);
+ }
+ } else {
+ int32x4_t shift4;
+
+ shift -= 1;
+ shift4 = vdupq_n_s32(shift);
+
+ for (i = 0; i < frameCount4; ++i) {
+ uint32x4_t mid;
+ uint32x4_t side;
+ int32x4_t left;
+ int32x4_t right;
+
+ mid = vshlq_u32(vld1q_u32(pInputSamples0U32 + i*4), wbpsShift0_4);
+ side = vshlq_u32(vld1q_u32(pInputSamples1U32 + i*4), wbpsShift1_4);
+
+ mid = vorrq_u32(vshlq_n_u32(mid, 1), vandq_u32(side, vdupq_n_u32(1)));
+
+ left = vreinterpretq_s32_u32(vshlq_u32(vaddq_u32(mid, side), shift4));
+ right = vreinterpretq_s32_u32(vshlq_u32(vsubq_u32(mid, side), shift4));
+
+ left = vshrq_n_s32(left, 16);
+ right = vshrq_n_s32(right, 16);
+
+ drflac__vst2q_s16(pOutputSamples + i*8, vzip_s16(vmovn_s32(left), vmovn_s32(right)));
+ }
+
+ for (i = (frameCount4 << 2); i < frameCount; ++i) {
+ drflac_uint32 mid = pInputSamples0U32[i] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 side = pInputSamples1U32[i] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+
+ mid = (mid << 1) | (side & 0x01);
+
+ pOutputSamples[i*2+0] = (drflac_int16)(((mid + side) << shift) >> 16);
+ pOutputSamples[i*2+1] = (drflac_int16)(((mid - side) << shift) >> 16);
+ }
+ }
+}
+#endif
+
+static DRFLAC_INLINE void drflac_read_pcm_frames_s16__decode_mid_side(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int16* pOutputSamples)
+{
+#if defined(DRFLAC_SUPPORT_SSE2)
+ if (drflac__gIsSSE2Supported && pFlac->bitsPerSample <= 24) {
+ drflac_read_pcm_frames_s16__decode_mid_side__sse2(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
+ } else
+#elif defined(DRFLAC_SUPPORT_NEON)
+ if (drflac__gIsNEONSupported && pFlac->bitsPerSample <= 24) {
+ drflac_read_pcm_frames_s16__decode_mid_side__neon(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
+ } else
+#endif
+ {
+ /* Scalar fallback. */
+#if 0
+ drflac_read_pcm_frames_s16__decode_mid_side__reference(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
+#else
+ drflac_read_pcm_frames_s16__decode_mid_side__scalar(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
+#endif
+ }
+}
+
+
+#if 0
+static DRFLAC_INLINE void drflac_read_pcm_frames_s16__decode_independent_stereo__reference(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int16* pOutputSamples)
+{
+ for (drflac_uint64 i = 0; i < frameCount; ++i) {
+ pOutputSamples[i*2+0] = (drflac_int16)((drflac_int32)((drflac_uint32)pInputSamples0[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample)) >> 16);
+ pOutputSamples[i*2+1] = (drflac_int16)((drflac_int32)((drflac_uint32)pInputSamples1[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample)) >> 16);
+ }
+}
+#endif
+
+static DRFLAC_INLINE void drflac_read_pcm_frames_s16__decode_independent_stereo__scalar(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int16* pOutputSamples)
+{
+ drflac_uint64 i;
+ drflac_uint64 frameCount4 = frameCount >> 2;
+ const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
+ const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
+ drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+
+ for (i = 0; i < frameCount4; ++i) {
+ drflac_uint32 tempL0 = pInputSamples0U32[i*4+0] << shift0;
+ drflac_uint32 tempL1 = pInputSamples0U32[i*4+1] << shift0;
+ drflac_uint32 tempL2 = pInputSamples0U32[i*4+2] << shift0;
+ drflac_uint32 tempL3 = pInputSamples0U32[i*4+3] << shift0;
+
+ drflac_uint32 tempR0 = pInputSamples1U32[i*4+0] << shift1;
+ drflac_uint32 tempR1 = pInputSamples1U32[i*4+1] << shift1;
+ drflac_uint32 tempR2 = pInputSamples1U32[i*4+2] << shift1;
+ drflac_uint32 tempR3 = pInputSamples1U32[i*4+3] << shift1;
+
+ tempL0 >>= 16;
+ tempL1 >>= 16;
+ tempL2 >>= 16;
+ tempL3 >>= 16;
+
+ tempR0 >>= 16;
+ tempR1 >>= 16;
+ tempR2 >>= 16;
+ tempR3 >>= 16;
+
+ pOutputSamples[i*8+0] = (drflac_int16)tempL0;
+ pOutputSamples[i*8+1] = (drflac_int16)tempR0;
+ pOutputSamples[i*8+2] = (drflac_int16)tempL1;
+ pOutputSamples[i*8+3] = (drflac_int16)tempR1;
+ pOutputSamples[i*8+4] = (drflac_int16)tempL2;
+ pOutputSamples[i*8+5] = (drflac_int16)tempR2;
+ pOutputSamples[i*8+6] = (drflac_int16)tempL3;
+ pOutputSamples[i*8+7] = (drflac_int16)tempR3;
+ }
+
+ for (i = (frameCount4 << 2); i < frameCount; ++i) {
+ pOutputSamples[i*2+0] = (drflac_int16)((pInputSamples0U32[i] << shift0) >> 16);
+ pOutputSamples[i*2+1] = (drflac_int16)((pInputSamples1U32[i] << shift1) >> 16);
+ }
+}
+
+#if defined(DRFLAC_SUPPORT_SSE2)
+static DRFLAC_INLINE void drflac_read_pcm_frames_s16__decode_independent_stereo__sse2(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int16* pOutputSamples)
+{
+ drflac_uint64 i;
+ drflac_uint64 frameCount4 = frameCount >> 2;
+ const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
+ const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
+ drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+
+ for (i = 0; i < frameCount4; ++i) {
+ __m128i left = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples0 + i), shift0);
+ __m128i right = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples1 + i), shift1);
+
+ left = _mm_srai_epi32(left, 16);
+ right = _mm_srai_epi32(right, 16);
+
+ /* At this point we have results. We can now pack and interleave these into a single __m128i object and then store the in the output buffer. */
+ _mm_storeu_si128((__m128i*)(pOutputSamples + i*8), drflac__mm_packs_interleaved_epi32(left, right));
+ }
+
+ for (i = (frameCount4 << 2); i < frameCount; ++i) {
+ pOutputSamples[i*2+0] = (drflac_int16)((pInputSamples0U32[i] << shift0) >> 16);
+ pOutputSamples[i*2+1] = (drflac_int16)((pInputSamples1U32[i] << shift1) >> 16);
+ }
+}
+#endif
+
+#if defined(DRFLAC_SUPPORT_NEON)
+static DRFLAC_INLINE void drflac_read_pcm_frames_s16__decode_independent_stereo__neon(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int16* pOutputSamples)
+{
+ drflac_uint64 i;
+ drflac_uint64 frameCount4 = frameCount >> 2;
+ const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
+ const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
+ drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+
+ int32x4_t shift0_4 = vdupq_n_s32(shift0);
+ int32x4_t shift1_4 = vdupq_n_s32(shift1);
+
+ for (i = 0; i < frameCount4; ++i) {
+ int32x4_t left;
+ int32x4_t right;
+
+ left = vreinterpretq_s32_u32(vshlq_u32(vld1q_u32(pInputSamples0U32 + i*4), shift0_4));
+ right = vreinterpretq_s32_u32(vshlq_u32(vld1q_u32(pInputSamples1U32 + i*4), shift1_4));
+
+ left = vshrq_n_s32(left, 16);
+ right = vshrq_n_s32(right, 16);
+
+ drflac__vst2q_s16(pOutputSamples + i*8, vzip_s16(vmovn_s32(left), vmovn_s32(right)));
+ }
+
+ for (i = (frameCount4 << 2); i < frameCount; ++i) {
+ pOutputSamples[i*2+0] = (drflac_int16)((pInputSamples0U32[i] << shift0) >> 16);
+ pOutputSamples[i*2+1] = (drflac_int16)((pInputSamples1U32[i] << shift1) >> 16);
+ }
+}
+#endif
+
+static DRFLAC_INLINE void drflac_read_pcm_frames_s16__decode_independent_stereo(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, drflac_int16* pOutputSamples)
+{
+#if defined(DRFLAC_SUPPORT_SSE2)
+ if (drflac__gIsSSE2Supported && pFlac->bitsPerSample <= 24) {
+ drflac_read_pcm_frames_s16__decode_independent_stereo__sse2(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
+ } else
+#elif defined(DRFLAC_SUPPORT_NEON)
+ if (drflac__gIsNEONSupported && pFlac->bitsPerSample <= 24) {
+ drflac_read_pcm_frames_s16__decode_independent_stereo__neon(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
+ } else
+#endif
+ {
+ /* Scalar fallback. */
+#if 0
+ drflac_read_pcm_frames_s16__decode_independent_stereo__reference(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
+#else
+ drflac_read_pcm_frames_s16__decode_independent_stereo__scalar(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
+#endif
+ }
+}
+
+DRFLAC_API drflac_uint64 drflac_read_pcm_frames_s16(drflac* pFlac, drflac_uint64 framesToRead, drflac_int16* pBufferOut)
+{
+ drflac_uint64 framesRead;
+ drflac_uint32 unusedBitsPerSample;
+
+ if (pFlac == NULL || framesToRead == 0) {
+ return 0;
+ }
+
+ if (pBufferOut == NULL) {
+ return drflac__seek_forward_by_pcm_frames(pFlac, framesToRead);
+ }
+
+ DRFLAC_ASSERT(pFlac->bitsPerSample <= 32);
+ unusedBitsPerSample = 32 - pFlac->bitsPerSample;
+
+ framesRead = 0;
+ while (framesToRead > 0) {
+ /* If we've run out of samples in this frame, go to the next. */
+ if (pFlac->currentFLACFrame.pcmFramesRemaining == 0) {
+ if (!drflac__read_and_decode_next_flac_frame(pFlac)) {
+ break; /* Couldn't read the next frame, so just break from the loop and return. */
+ }
+ } else {
+ unsigned int channelCount = drflac__get_channel_count_from_channel_assignment(pFlac->currentFLACFrame.header.channelAssignment);
+ drflac_uint64 iFirstPCMFrame = pFlac->currentFLACFrame.header.blockSizeInPCMFrames - pFlac->currentFLACFrame.pcmFramesRemaining;
+ drflac_uint64 frameCountThisIteration = framesToRead;
+
+ if (frameCountThisIteration > pFlac->currentFLACFrame.pcmFramesRemaining) {
+ frameCountThisIteration = pFlac->currentFLACFrame.pcmFramesRemaining;
+ }
+
+ if (channelCount == 2) {
+ const drflac_int32* pDecodedSamples0 = pFlac->currentFLACFrame.subframes[0].pSamplesS32 + iFirstPCMFrame;
+ const drflac_int32* pDecodedSamples1 = pFlac->currentFLACFrame.subframes[1].pSamplesS32 + iFirstPCMFrame;
+
+ switch (pFlac->currentFLACFrame.header.channelAssignment)
+ {
+ case DRFLAC_CHANNEL_ASSIGNMENT_LEFT_SIDE:
+ {
+ drflac_read_pcm_frames_s16__decode_left_side(pFlac, frameCountThisIteration, unusedBitsPerSample, pDecodedSamples0, pDecodedSamples1, pBufferOut);
+ } break;
+
+ case DRFLAC_CHANNEL_ASSIGNMENT_RIGHT_SIDE:
+ {
+ drflac_read_pcm_frames_s16__decode_right_side(pFlac, frameCountThisIteration, unusedBitsPerSample, pDecodedSamples0, pDecodedSamples1, pBufferOut);
+ } break;
+
+ case DRFLAC_CHANNEL_ASSIGNMENT_MID_SIDE:
+ {
+ drflac_read_pcm_frames_s16__decode_mid_side(pFlac, frameCountThisIteration, unusedBitsPerSample, pDecodedSamples0, pDecodedSamples1, pBufferOut);
+ } break;
+
+ case DRFLAC_CHANNEL_ASSIGNMENT_INDEPENDENT:
+ default:
+ {
+ drflac_read_pcm_frames_s16__decode_independent_stereo(pFlac, frameCountThisIteration, unusedBitsPerSample, pDecodedSamples0, pDecodedSamples1, pBufferOut);
+ } break;
+ }
+ } else {
+ /* Generic interleaving. */
+ drflac_uint64 i;
+ for (i = 0; i < frameCountThisIteration; ++i) {
+ unsigned int j;
+ for (j = 0; j < channelCount; ++j) {
+ drflac_int32 sampleS32 = (drflac_int32)((drflac_uint32)(pFlac->currentFLACFrame.subframes[j].pSamplesS32[iFirstPCMFrame + i]) << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[j].wastedBitsPerSample));
+ pBufferOut[(i*channelCount)+j] = (drflac_int16)(sampleS32 >> 16);
+ }
+ }
+ }
+
+ framesRead += frameCountThisIteration;
+ pBufferOut += frameCountThisIteration * channelCount;
+ framesToRead -= frameCountThisIteration;
+ pFlac->currentPCMFrame += frameCountThisIteration;
+ pFlac->currentFLACFrame.pcmFramesRemaining -= (drflac_uint32)frameCountThisIteration;
+ }
+ }
+
+ return framesRead;
+}
+
+
+#if 0
+static DRFLAC_INLINE void drflac_read_pcm_frames_f32__decode_left_side__reference(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, float* pOutputSamples)
+{
+ drflac_uint64 i;
+ for (i = 0; i < frameCount; ++i) {
+ drflac_uint32 left = (drflac_uint32)pInputSamples0[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample);
+ drflac_uint32 side = (drflac_uint32)pInputSamples1[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample);
+ drflac_uint32 right = left - side;
+
+ pOutputSamples[i*2+0] = (float)((drflac_int32)left / 2147483648.0);
+ pOutputSamples[i*2+1] = (float)((drflac_int32)right / 2147483648.0);
+ }
+}
+#endif
+
+static DRFLAC_INLINE void drflac_read_pcm_frames_f32__decode_left_side__scalar(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, float* pOutputSamples)
+{
+ drflac_uint64 i;
+ drflac_uint64 frameCount4 = frameCount >> 2;
+ const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
+ const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
+ drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+
+ float factor = 1 / 2147483648.0;
+
+ for (i = 0; i < frameCount4; ++i) {
+ drflac_uint32 left0 = pInputSamples0U32[i*4+0] << shift0;
+ drflac_uint32 left1 = pInputSamples0U32[i*4+1] << shift0;
+ drflac_uint32 left2 = pInputSamples0U32[i*4+2] << shift0;
+ drflac_uint32 left3 = pInputSamples0U32[i*4+3] << shift0;
+
+ drflac_uint32 side0 = pInputSamples1U32[i*4+0] << shift1;
+ drflac_uint32 side1 = pInputSamples1U32[i*4+1] << shift1;
+ drflac_uint32 side2 = pInputSamples1U32[i*4+2] << shift1;
+ drflac_uint32 side3 = pInputSamples1U32[i*4+3] << shift1;
+
+ drflac_uint32 right0 = left0 - side0;
+ drflac_uint32 right1 = left1 - side1;
+ drflac_uint32 right2 = left2 - side2;
+ drflac_uint32 right3 = left3 - side3;
+
+ pOutputSamples[i*8+0] = (drflac_int32)left0 * factor;
+ pOutputSamples[i*8+1] = (drflac_int32)right0 * factor;
+ pOutputSamples[i*8+2] = (drflac_int32)left1 * factor;
+ pOutputSamples[i*8+3] = (drflac_int32)right1 * factor;
+ pOutputSamples[i*8+4] = (drflac_int32)left2 * factor;
+ pOutputSamples[i*8+5] = (drflac_int32)right2 * factor;
+ pOutputSamples[i*8+6] = (drflac_int32)left3 * factor;
+ pOutputSamples[i*8+7] = (drflac_int32)right3 * factor;
+ }
+
+ for (i = (frameCount4 << 2); i < frameCount; ++i) {
+ drflac_uint32 left = pInputSamples0U32[i] << shift0;
+ drflac_uint32 side = pInputSamples1U32[i] << shift1;
+ drflac_uint32 right = left - side;
+
+ pOutputSamples[i*2+0] = (drflac_int32)left * factor;
+ pOutputSamples[i*2+1] = (drflac_int32)right * factor;
+ }
+}
+
+#if defined(DRFLAC_SUPPORT_SSE2)
+static DRFLAC_INLINE void drflac_read_pcm_frames_f32__decode_left_side__sse2(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, float* pOutputSamples)
+{
+ drflac_uint64 i;
+ drflac_uint64 frameCount4 = frameCount >> 2;
+ const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
+ const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
+ drflac_uint32 shift0 = (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample) - 8;
+ drflac_uint32 shift1 = (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample) - 8;
+ __m128 factor;
+
+ DRFLAC_ASSERT(pFlac->bitsPerSample <= 24);
+
+ factor = _mm_set1_ps(1.0f / 8388608.0f);
+
+ for (i = 0; i < frameCount4; ++i) {
+ __m128i left = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples0 + i), shift0);
+ __m128i side = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples1 + i), shift1);
+ __m128i right = _mm_sub_epi32(left, side);
+ __m128 leftf = _mm_mul_ps(_mm_cvtepi32_ps(left), factor);
+ __m128 rightf = _mm_mul_ps(_mm_cvtepi32_ps(right), factor);
+
+ _mm_storeu_ps(pOutputSamples + i*8 + 0, _mm_unpacklo_ps(leftf, rightf));
+ _mm_storeu_ps(pOutputSamples + i*8 + 4, _mm_unpackhi_ps(leftf, rightf));
+ }
+
+ for (i = (frameCount4 << 2); i < frameCount; ++i) {
+ drflac_uint32 left = pInputSamples0U32[i] << shift0;
+ drflac_uint32 side = pInputSamples1U32[i] << shift1;
+ drflac_uint32 right = left - side;
+
+ pOutputSamples[i*2+0] = (drflac_int32)left / 8388608.0f;
+ pOutputSamples[i*2+1] = (drflac_int32)right / 8388608.0f;
+ }
+}
+#endif
+
+#if defined(DRFLAC_SUPPORT_NEON)
+static DRFLAC_INLINE void drflac_read_pcm_frames_f32__decode_left_side__neon(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, float* pOutputSamples)
+{
+ drflac_uint64 i;
+ drflac_uint64 frameCount4 = frameCount >> 2;
+ const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
+ const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
+ drflac_uint32 shift0 = (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample) - 8;
+ drflac_uint32 shift1 = (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample) - 8;
+ float32x4_t factor4;
+ int32x4_t shift0_4;
+ int32x4_t shift1_4;
+
+ DRFLAC_ASSERT(pFlac->bitsPerSample <= 24);
+
+ factor4 = vdupq_n_f32(1.0f / 8388608.0f);
+ shift0_4 = vdupq_n_s32(shift0);
+ shift1_4 = vdupq_n_s32(shift1);
+
+ for (i = 0; i < frameCount4; ++i) {
+ uint32x4_t left;
+ uint32x4_t side;
+ uint32x4_t right;
+ float32x4_t leftf;
+ float32x4_t rightf;
+
+ left = vshlq_u32(vld1q_u32(pInputSamples0U32 + i*4), shift0_4);
+ side = vshlq_u32(vld1q_u32(pInputSamples1U32 + i*4), shift1_4);
+ right = vsubq_u32(left, side);
+ leftf = vmulq_f32(vcvtq_f32_s32(vreinterpretq_s32_u32(left)), factor4);
+ rightf = vmulq_f32(vcvtq_f32_s32(vreinterpretq_s32_u32(right)), factor4);
+
+ drflac__vst2q_f32(pOutputSamples + i*8, vzipq_f32(leftf, rightf));
+ }
+
+ for (i = (frameCount4 << 2); i < frameCount; ++i) {
+ drflac_uint32 left = pInputSamples0U32[i] << shift0;
+ drflac_uint32 side = pInputSamples1U32[i] << shift1;
+ drflac_uint32 right = left - side;
+
+ pOutputSamples[i*2+0] = (drflac_int32)left / 8388608.0f;
+ pOutputSamples[i*2+1] = (drflac_int32)right / 8388608.0f;
+ }
+}
+#endif
+
+static DRFLAC_INLINE void drflac_read_pcm_frames_f32__decode_left_side(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, float* pOutputSamples)
+{
+#if defined(DRFLAC_SUPPORT_SSE2)
+ if (drflac__gIsSSE2Supported && pFlac->bitsPerSample <= 24) {
+ drflac_read_pcm_frames_f32__decode_left_side__sse2(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
+ } else
+#elif defined(DRFLAC_SUPPORT_NEON)
+ if (drflac__gIsNEONSupported && pFlac->bitsPerSample <= 24) {
+ drflac_read_pcm_frames_f32__decode_left_side__neon(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
+ } else
+#endif
+ {
+ /* Scalar fallback. */
+#if 0
+ drflac_read_pcm_frames_f32__decode_left_side__reference(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
+#else
+ drflac_read_pcm_frames_f32__decode_left_side__scalar(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
+#endif
+ }
+}
+
+
+#if 0
+static DRFLAC_INLINE void drflac_read_pcm_frames_f32__decode_right_side__reference(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, float* pOutputSamples)
+{
+ drflac_uint64 i;
+ for (i = 0; i < frameCount; ++i) {
+ drflac_uint32 side = (drflac_uint32)pInputSamples0[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample);
+ drflac_uint32 right = (drflac_uint32)pInputSamples1[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample);
+ drflac_uint32 left = right + side;
+
+ pOutputSamples[i*2+0] = (float)((drflac_int32)left / 2147483648.0);
+ pOutputSamples[i*2+1] = (float)((drflac_int32)right / 2147483648.0);
+ }
+}
+#endif
+
+static DRFLAC_INLINE void drflac_read_pcm_frames_f32__decode_right_side__scalar(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, float* pOutputSamples)
+{
+ drflac_uint64 i;
+ drflac_uint64 frameCount4 = frameCount >> 2;
+ const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
+ const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
+ drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+ float factor = 1 / 2147483648.0;
+
+ for (i = 0; i < frameCount4; ++i) {
+ drflac_uint32 side0 = pInputSamples0U32[i*4+0] << shift0;
+ drflac_uint32 side1 = pInputSamples0U32[i*4+1] << shift0;
+ drflac_uint32 side2 = pInputSamples0U32[i*4+2] << shift0;
+ drflac_uint32 side3 = pInputSamples0U32[i*4+3] << shift0;
+
+ drflac_uint32 right0 = pInputSamples1U32[i*4+0] << shift1;
+ drflac_uint32 right1 = pInputSamples1U32[i*4+1] << shift1;
+ drflac_uint32 right2 = pInputSamples1U32[i*4+2] << shift1;
+ drflac_uint32 right3 = pInputSamples1U32[i*4+3] << shift1;
+
+ drflac_uint32 left0 = right0 + side0;
+ drflac_uint32 left1 = right1 + side1;
+ drflac_uint32 left2 = right2 + side2;
+ drflac_uint32 left3 = right3 + side3;
+
+ pOutputSamples[i*8+0] = (drflac_int32)left0 * factor;
+ pOutputSamples[i*8+1] = (drflac_int32)right0 * factor;
+ pOutputSamples[i*8+2] = (drflac_int32)left1 * factor;
+ pOutputSamples[i*8+3] = (drflac_int32)right1 * factor;
+ pOutputSamples[i*8+4] = (drflac_int32)left2 * factor;
+ pOutputSamples[i*8+5] = (drflac_int32)right2 * factor;
+ pOutputSamples[i*8+6] = (drflac_int32)left3 * factor;
+ pOutputSamples[i*8+7] = (drflac_int32)right3 * factor;
+ }
+
+ for (i = (frameCount4 << 2); i < frameCount; ++i) {
+ drflac_uint32 side = pInputSamples0U32[i] << shift0;
+ drflac_uint32 right = pInputSamples1U32[i] << shift1;
+ drflac_uint32 left = right + side;
+
+ pOutputSamples[i*2+0] = (drflac_int32)left * factor;
+ pOutputSamples[i*2+1] = (drflac_int32)right * factor;
+ }
+}
+
+#if defined(DRFLAC_SUPPORT_SSE2)
+static DRFLAC_INLINE void drflac_read_pcm_frames_f32__decode_right_side__sse2(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, float* pOutputSamples)
+{
+ drflac_uint64 i;
+ drflac_uint64 frameCount4 = frameCount >> 2;
+ const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
+ const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
+ drflac_uint32 shift0 = (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample) - 8;
+ drflac_uint32 shift1 = (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample) - 8;
+ __m128 factor;
+
+ DRFLAC_ASSERT(pFlac->bitsPerSample <= 24);
+
+ factor = _mm_set1_ps(1.0f / 8388608.0f);
+
+ for (i = 0; i < frameCount4; ++i) {
+ __m128i side = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples0 + i), shift0);
+ __m128i right = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples1 + i), shift1);
+ __m128i left = _mm_add_epi32(right, side);
+ __m128 leftf = _mm_mul_ps(_mm_cvtepi32_ps(left), factor);
+ __m128 rightf = _mm_mul_ps(_mm_cvtepi32_ps(right), factor);
+
+ _mm_storeu_ps(pOutputSamples + i*8 + 0, _mm_unpacklo_ps(leftf, rightf));
+ _mm_storeu_ps(pOutputSamples + i*8 + 4, _mm_unpackhi_ps(leftf, rightf));
+ }
+
+ for (i = (frameCount4 << 2); i < frameCount; ++i) {
+ drflac_uint32 side = pInputSamples0U32[i] << shift0;
+ drflac_uint32 right = pInputSamples1U32[i] << shift1;
+ drflac_uint32 left = right + side;
+
+ pOutputSamples[i*2+0] = (drflac_int32)left / 8388608.0f;
+ pOutputSamples[i*2+1] = (drflac_int32)right / 8388608.0f;
+ }
+}
+#endif
+
+#if defined(DRFLAC_SUPPORT_NEON)
+static DRFLAC_INLINE void drflac_read_pcm_frames_f32__decode_right_side__neon(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, float* pOutputSamples)
+{
+ drflac_uint64 i;
+ drflac_uint64 frameCount4 = frameCount >> 2;
+ const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
+ const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
+ drflac_uint32 shift0 = (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample) - 8;
+ drflac_uint32 shift1 = (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample) - 8;
+ float32x4_t factor4;
+ int32x4_t shift0_4;
+ int32x4_t shift1_4;
+
+ DRFLAC_ASSERT(pFlac->bitsPerSample <= 24);
+
+ factor4 = vdupq_n_f32(1.0f / 8388608.0f);
+ shift0_4 = vdupq_n_s32(shift0);
+ shift1_4 = vdupq_n_s32(shift1);
+
+ for (i = 0; i < frameCount4; ++i) {
+ uint32x4_t side;
+ uint32x4_t right;
+ uint32x4_t left;
+ float32x4_t leftf;
+ float32x4_t rightf;
+
+ side = vshlq_u32(vld1q_u32(pInputSamples0U32 + i*4), shift0_4);
+ right = vshlq_u32(vld1q_u32(pInputSamples1U32 + i*4), shift1_4);
+ left = vaddq_u32(right, side);
+ leftf = vmulq_f32(vcvtq_f32_s32(vreinterpretq_s32_u32(left)), factor4);
+ rightf = vmulq_f32(vcvtq_f32_s32(vreinterpretq_s32_u32(right)), factor4);
+
+ drflac__vst2q_f32(pOutputSamples + i*8, vzipq_f32(leftf, rightf));
+ }
+
+ for (i = (frameCount4 << 2); i < frameCount; ++i) {
+ drflac_uint32 side = pInputSamples0U32[i] << shift0;
+ drflac_uint32 right = pInputSamples1U32[i] << shift1;
+ drflac_uint32 left = right + side;
+
+ pOutputSamples[i*2+0] = (drflac_int32)left / 8388608.0f;
+ pOutputSamples[i*2+1] = (drflac_int32)right / 8388608.0f;
+ }
+}
+#endif
+
+static DRFLAC_INLINE void drflac_read_pcm_frames_f32__decode_right_side(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, float* pOutputSamples)
+{
+#if defined(DRFLAC_SUPPORT_SSE2)
+ if (drflac__gIsSSE2Supported && pFlac->bitsPerSample <= 24) {
+ drflac_read_pcm_frames_f32__decode_right_side__sse2(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
+ } else
+#elif defined(DRFLAC_SUPPORT_NEON)
+ if (drflac__gIsNEONSupported && pFlac->bitsPerSample <= 24) {
+ drflac_read_pcm_frames_f32__decode_right_side__neon(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
+ } else
+#endif
+ {
+ /* Scalar fallback. */
+#if 0
+ drflac_read_pcm_frames_f32__decode_right_side__reference(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
+#else
+ drflac_read_pcm_frames_f32__decode_right_side__scalar(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
+#endif
+ }
+}
+
+
+#if 0
+static DRFLAC_INLINE void drflac_read_pcm_frames_f32__decode_mid_side__reference(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, float* pOutputSamples)
+{
+ for (drflac_uint64 i = 0; i < frameCount; ++i) {
+ drflac_uint32 mid = (drflac_uint32)pInputSamples0[i] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 side = (drflac_uint32)pInputSamples1[i] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+
+ mid = (mid << 1) | (side & 0x01);
+
+ pOutputSamples[i*2+0] = (float)((((drflac_int32)(mid + side) >> 1) << (unusedBitsPerSample)) / 2147483648.0);
+ pOutputSamples[i*2+1] = (float)((((drflac_int32)(mid - side) >> 1) << (unusedBitsPerSample)) / 2147483648.0);
+ }
+}
+#endif
+
+static DRFLAC_INLINE void drflac_read_pcm_frames_f32__decode_mid_side__scalar(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, float* pOutputSamples)
+{
+ drflac_uint64 i;
+ drflac_uint64 frameCount4 = frameCount >> 2;
+ const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
+ const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
+ drflac_uint32 shift = unusedBitsPerSample;
+ float factor = 1 / 2147483648.0;
+
+ if (shift > 0) {
+ shift -= 1;
+ for (i = 0; i < frameCount4; ++i) {
+ drflac_uint32 temp0L;
+ drflac_uint32 temp1L;
+ drflac_uint32 temp2L;
+ drflac_uint32 temp3L;
+ drflac_uint32 temp0R;
+ drflac_uint32 temp1R;
+ drflac_uint32 temp2R;
+ drflac_uint32 temp3R;
+
+ drflac_uint32 mid0 = pInputSamples0U32[i*4+0] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 mid1 = pInputSamples0U32[i*4+1] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 mid2 = pInputSamples0U32[i*4+2] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 mid3 = pInputSamples0U32[i*4+3] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+
+ drflac_uint32 side0 = pInputSamples1U32[i*4+0] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+ drflac_uint32 side1 = pInputSamples1U32[i*4+1] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+ drflac_uint32 side2 = pInputSamples1U32[i*4+2] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+ drflac_uint32 side3 = pInputSamples1U32[i*4+3] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+
+ mid0 = (mid0 << 1) | (side0 & 0x01);
+ mid1 = (mid1 << 1) | (side1 & 0x01);
+ mid2 = (mid2 << 1) | (side2 & 0x01);
+ mid3 = (mid3 << 1) | (side3 & 0x01);
+
+ temp0L = (mid0 + side0) << shift;
+ temp1L = (mid1 + side1) << shift;
+ temp2L = (mid2 + side2) << shift;
+ temp3L = (mid3 + side3) << shift;
+
+ temp0R = (mid0 - side0) << shift;
+ temp1R = (mid1 - side1) << shift;
+ temp2R = (mid2 - side2) << shift;
+ temp3R = (mid3 - side3) << shift;
+
+ pOutputSamples[i*8+0] = (drflac_int32)temp0L * factor;
+ pOutputSamples[i*8+1] = (drflac_int32)temp0R * factor;
+ pOutputSamples[i*8+2] = (drflac_int32)temp1L * factor;
+ pOutputSamples[i*8+3] = (drflac_int32)temp1R * factor;
+ pOutputSamples[i*8+4] = (drflac_int32)temp2L * factor;
+ pOutputSamples[i*8+5] = (drflac_int32)temp2R * factor;
+ pOutputSamples[i*8+6] = (drflac_int32)temp3L * factor;
+ pOutputSamples[i*8+7] = (drflac_int32)temp3R * factor;
+ }
+ } else {
+ for (i = 0; i < frameCount4; ++i) {
+ drflac_uint32 temp0L;
+ drflac_uint32 temp1L;
+ drflac_uint32 temp2L;
+ drflac_uint32 temp3L;
+ drflac_uint32 temp0R;
+ drflac_uint32 temp1R;
+ drflac_uint32 temp2R;
+ drflac_uint32 temp3R;
+
+ drflac_uint32 mid0 = pInputSamples0U32[i*4+0] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 mid1 = pInputSamples0U32[i*4+1] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 mid2 = pInputSamples0U32[i*4+2] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 mid3 = pInputSamples0U32[i*4+3] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+
+ drflac_uint32 side0 = pInputSamples1U32[i*4+0] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+ drflac_uint32 side1 = pInputSamples1U32[i*4+1] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+ drflac_uint32 side2 = pInputSamples1U32[i*4+2] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+ drflac_uint32 side3 = pInputSamples1U32[i*4+3] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+
+ mid0 = (mid0 << 1) | (side0 & 0x01);
+ mid1 = (mid1 << 1) | (side1 & 0x01);
+ mid2 = (mid2 << 1) | (side2 & 0x01);
+ mid3 = (mid3 << 1) | (side3 & 0x01);
+
+ temp0L = (drflac_uint32)((drflac_int32)(mid0 + side0) >> 1);
+ temp1L = (drflac_uint32)((drflac_int32)(mid1 + side1) >> 1);
+ temp2L = (drflac_uint32)((drflac_int32)(mid2 + side2) >> 1);
+ temp3L = (drflac_uint32)((drflac_int32)(mid3 + side3) >> 1);
+
+ temp0R = (drflac_uint32)((drflac_int32)(mid0 - side0) >> 1);
+ temp1R = (drflac_uint32)((drflac_int32)(mid1 - side1) >> 1);
+ temp2R = (drflac_uint32)((drflac_int32)(mid2 - side2) >> 1);
+ temp3R = (drflac_uint32)((drflac_int32)(mid3 - side3) >> 1);
+
+ pOutputSamples[i*8+0] = (drflac_int32)temp0L * factor;
+ pOutputSamples[i*8+1] = (drflac_int32)temp0R * factor;
+ pOutputSamples[i*8+2] = (drflac_int32)temp1L * factor;
+ pOutputSamples[i*8+3] = (drflac_int32)temp1R * factor;
+ pOutputSamples[i*8+4] = (drflac_int32)temp2L * factor;
+ pOutputSamples[i*8+5] = (drflac_int32)temp2R * factor;
+ pOutputSamples[i*8+6] = (drflac_int32)temp3L * factor;
+ pOutputSamples[i*8+7] = (drflac_int32)temp3R * factor;
+ }
+ }
+
+ for (i = (frameCount4 << 2); i < frameCount; ++i) {
+ drflac_uint32 mid = pInputSamples0U32[i] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 side = pInputSamples1U32[i] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+
+ mid = (mid << 1) | (side & 0x01);
+
+ pOutputSamples[i*2+0] = (drflac_int32)((drflac_uint32)((drflac_int32)(mid + side) >> 1) << unusedBitsPerSample) * factor;
+ pOutputSamples[i*2+1] = (drflac_int32)((drflac_uint32)((drflac_int32)(mid - side) >> 1) << unusedBitsPerSample) * factor;
+ }
+}
+
+#if defined(DRFLAC_SUPPORT_SSE2)
+static DRFLAC_INLINE void drflac_read_pcm_frames_f32__decode_mid_side__sse2(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, float* pOutputSamples)
+{
+ drflac_uint64 i;
+ drflac_uint64 frameCount4 = frameCount >> 2;
+ const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
+ const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
+ drflac_uint32 shift = unusedBitsPerSample - 8;
+ float factor;
+ __m128 factor128;
+
+ DRFLAC_ASSERT(pFlac->bitsPerSample <= 24);
+
+ factor = 1.0f / 8388608.0f;
+ factor128 = _mm_set1_ps(factor);
+
+ if (shift == 0) {
+ for (i = 0; i < frameCount4; ++i) {
+ __m128i mid;
+ __m128i side;
+ __m128i tempL;
+ __m128i tempR;
+ __m128 leftf;
+ __m128 rightf;
+
+ mid = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples0 + i), pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample);
+ side = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples1 + i), pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample);
+
+ mid = _mm_or_si128(_mm_slli_epi32(mid, 1), _mm_and_si128(side, _mm_set1_epi32(0x01)));
+
+ tempL = _mm_srai_epi32(_mm_add_epi32(mid, side), 1);
+ tempR = _mm_srai_epi32(_mm_sub_epi32(mid, side), 1);
+
+ leftf = _mm_mul_ps(_mm_cvtepi32_ps(tempL), factor128);
+ rightf = _mm_mul_ps(_mm_cvtepi32_ps(tempR), factor128);
+
+ _mm_storeu_ps(pOutputSamples + i*8 + 0, _mm_unpacklo_ps(leftf, rightf));
+ _mm_storeu_ps(pOutputSamples + i*8 + 4, _mm_unpackhi_ps(leftf, rightf));
+ }
+
+ for (i = (frameCount4 << 2); i < frameCount; ++i) {
+ drflac_uint32 mid = pInputSamples0U32[i] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 side = pInputSamples1U32[i] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+
+ mid = (mid << 1) | (side & 0x01);
+
+ pOutputSamples[i*2+0] = ((drflac_int32)(mid + side) >> 1) * factor;
+ pOutputSamples[i*2+1] = ((drflac_int32)(mid - side) >> 1) * factor;
+ }
+ } else {
+ shift -= 1;
+ for (i = 0; i < frameCount4; ++i) {
+ __m128i mid;
+ __m128i side;
+ __m128i tempL;
+ __m128i tempR;
+ __m128 leftf;
+ __m128 rightf;
+
+ mid = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples0 + i), pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample);
+ side = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples1 + i), pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample);
+
+ mid = _mm_or_si128(_mm_slli_epi32(mid, 1), _mm_and_si128(side, _mm_set1_epi32(0x01)));
+
+ tempL = _mm_slli_epi32(_mm_add_epi32(mid, side), shift);
+ tempR = _mm_slli_epi32(_mm_sub_epi32(mid, side), shift);
+
+ leftf = _mm_mul_ps(_mm_cvtepi32_ps(tempL), factor128);
+ rightf = _mm_mul_ps(_mm_cvtepi32_ps(tempR), factor128);
+
+ _mm_storeu_ps(pOutputSamples + i*8 + 0, _mm_unpacklo_ps(leftf, rightf));
+ _mm_storeu_ps(pOutputSamples + i*8 + 4, _mm_unpackhi_ps(leftf, rightf));
+ }
+
+ for (i = (frameCount4 << 2); i < frameCount; ++i) {
+ drflac_uint32 mid = pInputSamples0U32[i] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 side = pInputSamples1U32[i] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+
+ mid = (mid << 1) | (side & 0x01);
+
+ pOutputSamples[i*2+0] = (drflac_int32)((mid + side) << shift) * factor;
+ pOutputSamples[i*2+1] = (drflac_int32)((mid - side) << shift) * factor;
+ }
+ }
+}
+#endif
+
+#if defined(DRFLAC_SUPPORT_NEON)
+static DRFLAC_INLINE void drflac_read_pcm_frames_f32__decode_mid_side__neon(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, float* pOutputSamples)
+{
+ drflac_uint64 i;
+ drflac_uint64 frameCount4 = frameCount >> 2;
+ const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
+ const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
+ drflac_uint32 shift = unusedBitsPerSample - 8;
+ float factor;
+ float32x4_t factor4;
+ int32x4_t shift4;
+ int32x4_t wbps0_4; /* Wasted Bits Per Sample */
+ int32x4_t wbps1_4; /* Wasted Bits Per Sample */
+
+ DRFLAC_ASSERT(pFlac->bitsPerSample <= 24);
+
+ factor = 1.0f / 8388608.0f;
+ factor4 = vdupq_n_f32(factor);
+ wbps0_4 = vdupq_n_s32(pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample);
+ wbps1_4 = vdupq_n_s32(pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample);
+
+ if (shift == 0) {
+ for (i = 0; i < frameCount4; ++i) {
+ int32x4_t lefti;
+ int32x4_t righti;
+ float32x4_t leftf;
+ float32x4_t rightf;
+
+ uint32x4_t mid = vshlq_u32(vld1q_u32(pInputSamples0U32 + i*4), wbps0_4);
+ uint32x4_t side = vshlq_u32(vld1q_u32(pInputSamples1U32 + i*4), wbps1_4);
+
+ mid = vorrq_u32(vshlq_n_u32(mid, 1), vandq_u32(side, vdupq_n_u32(1)));
+
+ lefti = vshrq_n_s32(vreinterpretq_s32_u32(vaddq_u32(mid, side)), 1);
+ righti = vshrq_n_s32(vreinterpretq_s32_u32(vsubq_u32(mid, side)), 1);
+
+ leftf = vmulq_f32(vcvtq_f32_s32(lefti), factor4);
+ rightf = vmulq_f32(vcvtq_f32_s32(righti), factor4);
+
+ drflac__vst2q_f32(pOutputSamples + i*8, vzipq_f32(leftf, rightf));
+ }
+
+ for (i = (frameCount4 << 2); i < frameCount; ++i) {
+ drflac_uint32 mid = pInputSamples0U32[i] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 side = pInputSamples1U32[i] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+
+ mid = (mid << 1) | (side & 0x01);
+
+ pOutputSamples[i*2+0] = ((drflac_int32)(mid + side) >> 1) * factor;
+ pOutputSamples[i*2+1] = ((drflac_int32)(mid - side) >> 1) * factor;
+ }
+ } else {
+ shift -= 1;
+ shift4 = vdupq_n_s32(shift);
+ for (i = 0; i < frameCount4; ++i) {
+ uint32x4_t mid;
+ uint32x4_t side;
+ int32x4_t lefti;
+ int32x4_t righti;
+ float32x4_t leftf;
+ float32x4_t rightf;
+
+ mid = vshlq_u32(vld1q_u32(pInputSamples0U32 + i*4), wbps0_4);
+ side = vshlq_u32(vld1q_u32(pInputSamples1U32 + i*4), wbps1_4);
+
+ mid = vorrq_u32(vshlq_n_u32(mid, 1), vandq_u32(side, vdupq_n_u32(1)));
+
+ lefti = vreinterpretq_s32_u32(vshlq_u32(vaddq_u32(mid, side), shift4));
+ righti = vreinterpretq_s32_u32(vshlq_u32(vsubq_u32(mid, side), shift4));
+
+ leftf = vmulq_f32(vcvtq_f32_s32(lefti), factor4);
+ rightf = vmulq_f32(vcvtq_f32_s32(righti), factor4);
+
+ drflac__vst2q_f32(pOutputSamples + i*8, vzipq_f32(leftf, rightf));
+ }
+
+ for (i = (frameCount4 << 2); i < frameCount; ++i) {
+ drflac_uint32 mid = pInputSamples0U32[i] << pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 side = pInputSamples1U32[i] << pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+
+ mid = (mid << 1) | (side & 0x01);
+
+ pOutputSamples[i*2+0] = (drflac_int32)((mid + side) << shift) * factor;
+ pOutputSamples[i*2+1] = (drflac_int32)((mid - side) << shift) * factor;
+ }
+ }
+}
+#endif
+
+static DRFLAC_INLINE void drflac_read_pcm_frames_f32__decode_mid_side(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, float* pOutputSamples)
+{
+#if defined(DRFLAC_SUPPORT_SSE2)
+ if (drflac__gIsSSE2Supported && pFlac->bitsPerSample <= 24) {
+ drflac_read_pcm_frames_f32__decode_mid_side__sse2(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
+ } else
+#elif defined(DRFLAC_SUPPORT_NEON)
+ if (drflac__gIsNEONSupported && pFlac->bitsPerSample <= 24) {
+ drflac_read_pcm_frames_f32__decode_mid_side__neon(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
+ } else
+#endif
+ {
+ /* Scalar fallback. */
+#if 0
+ drflac_read_pcm_frames_f32__decode_mid_side__reference(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
+#else
+ drflac_read_pcm_frames_f32__decode_mid_side__scalar(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
+#endif
+ }
+}
+
+#if 0
+static DRFLAC_INLINE void drflac_read_pcm_frames_f32__decode_independent_stereo__reference(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, float* pOutputSamples)
+{
+ for (drflac_uint64 i = 0; i < frameCount; ++i) {
+ pOutputSamples[i*2+0] = (float)((drflac_int32)((drflac_uint32)pInputSamples0[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample)) / 2147483648.0);
+ pOutputSamples[i*2+1] = (float)((drflac_int32)((drflac_uint32)pInputSamples1[i] << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample)) / 2147483648.0);
+ }
+}
+#endif
+
+static DRFLAC_INLINE void drflac_read_pcm_frames_f32__decode_independent_stereo__scalar(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, float* pOutputSamples)
+{
+ drflac_uint64 i;
+ drflac_uint64 frameCount4 = frameCount >> 2;
+ const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
+ const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
+ drflac_uint32 shift0 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample;
+ drflac_uint32 shift1 = unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample;
+ float factor = 1 / 2147483648.0;
+
+ for (i = 0; i < frameCount4; ++i) {
+ drflac_uint32 tempL0 = pInputSamples0U32[i*4+0] << shift0;
+ drflac_uint32 tempL1 = pInputSamples0U32[i*4+1] << shift0;
+ drflac_uint32 tempL2 = pInputSamples0U32[i*4+2] << shift0;
+ drflac_uint32 tempL3 = pInputSamples0U32[i*4+3] << shift0;
+
+ drflac_uint32 tempR0 = pInputSamples1U32[i*4+0] << shift1;
+ drflac_uint32 tempR1 = pInputSamples1U32[i*4+1] << shift1;
+ drflac_uint32 tempR2 = pInputSamples1U32[i*4+2] << shift1;
+ drflac_uint32 tempR3 = pInputSamples1U32[i*4+3] << shift1;
+
+ pOutputSamples[i*8+0] = (drflac_int32)tempL0 * factor;
+ pOutputSamples[i*8+1] = (drflac_int32)tempR0 * factor;
+ pOutputSamples[i*8+2] = (drflac_int32)tempL1 * factor;
+ pOutputSamples[i*8+3] = (drflac_int32)tempR1 * factor;
+ pOutputSamples[i*8+4] = (drflac_int32)tempL2 * factor;
+ pOutputSamples[i*8+5] = (drflac_int32)tempR2 * factor;
+ pOutputSamples[i*8+6] = (drflac_int32)tempL3 * factor;
+ pOutputSamples[i*8+7] = (drflac_int32)tempR3 * factor;
+ }
+
+ for (i = (frameCount4 << 2); i < frameCount; ++i) {
+ pOutputSamples[i*2+0] = (drflac_int32)(pInputSamples0U32[i] << shift0) * factor;
+ pOutputSamples[i*2+1] = (drflac_int32)(pInputSamples1U32[i] << shift1) * factor;
+ }
+}
+
+#if defined(DRFLAC_SUPPORT_SSE2)
+static DRFLAC_INLINE void drflac_read_pcm_frames_f32__decode_independent_stereo__sse2(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, float* pOutputSamples)
+{
+ drflac_uint64 i;
+ drflac_uint64 frameCount4 = frameCount >> 2;
+ const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
+ const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
+ drflac_uint32 shift0 = (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample) - 8;
+ drflac_uint32 shift1 = (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample) - 8;
+
+ float factor = 1.0f / 8388608.0f;
+ __m128 factor128 = _mm_set1_ps(factor);
+
+ for (i = 0; i < frameCount4; ++i) {
+ __m128i lefti;
+ __m128i righti;
+ __m128 leftf;
+ __m128 rightf;
+
+ lefti = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples0 + i), shift0);
+ righti = _mm_slli_epi32(_mm_loadu_si128((const __m128i*)pInputSamples1 + i), shift1);
+
+ leftf = _mm_mul_ps(_mm_cvtepi32_ps(lefti), factor128);
+ rightf = _mm_mul_ps(_mm_cvtepi32_ps(righti), factor128);
+
+ _mm_storeu_ps(pOutputSamples + i*8 + 0, _mm_unpacklo_ps(leftf, rightf));
+ _mm_storeu_ps(pOutputSamples + i*8 + 4, _mm_unpackhi_ps(leftf, rightf));
+ }
+
+ for (i = (frameCount4 << 2); i < frameCount; ++i) {
+ pOutputSamples[i*2+0] = (drflac_int32)(pInputSamples0U32[i] << shift0) * factor;
+ pOutputSamples[i*2+1] = (drflac_int32)(pInputSamples1U32[i] << shift1) * factor;
+ }
+}
+#endif
+
+#if defined(DRFLAC_SUPPORT_NEON)
+static DRFLAC_INLINE void drflac_read_pcm_frames_f32__decode_independent_stereo__neon(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, float* pOutputSamples)
+{
+ drflac_uint64 i;
+ drflac_uint64 frameCount4 = frameCount >> 2;
+ const drflac_uint32* pInputSamples0U32 = (const drflac_uint32*)pInputSamples0;
+ const drflac_uint32* pInputSamples1U32 = (const drflac_uint32*)pInputSamples1;
+ drflac_uint32 shift0 = (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[0].wastedBitsPerSample) - 8;
+ drflac_uint32 shift1 = (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[1].wastedBitsPerSample) - 8;
+
+ float factor = 1.0f / 8388608.0f;
+ float32x4_t factor4 = vdupq_n_f32(factor);
+ int32x4_t shift0_4 = vdupq_n_s32(shift0);
+ int32x4_t shift1_4 = vdupq_n_s32(shift1);
+
+ for (i = 0; i < frameCount4; ++i) {
+ int32x4_t lefti;
+ int32x4_t righti;
+ float32x4_t leftf;
+ float32x4_t rightf;
+
+ lefti = vreinterpretq_s32_u32(vshlq_u32(vld1q_u32(pInputSamples0U32 + i*4), shift0_4));
+ righti = vreinterpretq_s32_u32(vshlq_u32(vld1q_u32(pInputSamples1U32 + i*4), shift1_4));
+
+ leftf = vmulq_f32(vcvtq_f32_s32(lefti), factor4);
+ rightf = vmulq_f32(vcvtq_f32_s32(righti), factor4);
+
+ drflac__vst2q_f32(pOutputSamples + i*8, vzipq_f32(leftf, rightf));
+ }
+
+ for (i = (frameCount4 << 2); i < frameCount; ++i) {
+ pOutputSamples[i*2+0] = (drflac_int32)(pInputSamples0U32[i] << shift0) * factor;
+ pOutputSamples[i*2+1] = (drflac_int32)(pInputSamples1U32[i] << shift1) * factor;
+ }
+}
+#endif
+
+static DRFLAC_INLINE void drflac_read_pcm_frames_f32__decode_independent_stereo(drflac* pFlac, drflac_uint64 frameCount, drflac_uint32 unusedBitsPerSample, const drflac_int32* pInputSamples0, const drflac_int32* pInputSamples1, float* pOutputSamples)
+{
+#if defined(DRFLAC_SUPPORT_SSE2)
+ if (drflac__gIsSSE2Supported && pFlac->bitsPerSample <= 24) {
+ drflac_read_pcm_frames_f32__decode_independent_stereo__sse2(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
+ } else
+#elif defined(DRFLAC_SUPPORT_NEON)
+ if (drflac__gIsNEONSupported && pFlac->bitsPerSample <= 24) {
+ drflac_read_pcm_frames_f32__decode_independent_stereo__neon(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
+ } else
+#endif
+ {
+ /* Scalar fallback. */
+#if 0
+ drflac_read_pcm_frames_f32__decode_independent_stereo__reference(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
+#else
+ drflac_read_pcm_frames_f32__decode_independent_stereo__scalar(pFlac, frameCount, unusedBitsPerSample, pInputSamples0, pInputSamples1, pOutputSamples);
+#endif
+ }
+}
+
+DRFLAC_API drflac_uint64 drflac_read_pcm_frames_f32(drflac* pFlac, drflac_uint64 framesToRead, float* pBufferOut)
+{
+ drflac_uint64 framesRead;
+ drflac_uint32 unusedBitsPerSample;
+
+ if (pFlac == NULL || framesToRead == 0) {
+ return 0;
+ }
+
+ if (pBufferOut == NULL) {
+ return drflac__seek_forward_by_pcm_frames(pFlac, framesToRead);
+ }
+
+ DRFLAC_ASSERT(pFlac->bitsPerSample <= 32);
+ unusedBitsPerSample = 32 - pFlac->bitsPerSample;
+
+ framesRead = 0;
+ while (framesToRead > 0) {
+ /* If we've run out of samples in this frame, go to the next. */
+ if (pFlac->currentFLACFrame.pcmFramesRemaining == 0) {
+ if (!drflac__read_and_decode_next_flac_frame(pFlac)) {
+ break; /* Couldn't read the next frame, so just break from the loop and return. */
+ }
+ } else {
+ unsigned int channelCount = drflac__get_channel_count_from_channel_assignment(pFlac->currentFLACFrame.header.channelAssignment);
+ drflac_uint64 iFirstPCMFrame = pFlac->currentFLACFrame.header.blockSizeInPCMFrames - pFlac->currentFLACFrame.pcmFramesRemaining;
+ drflac_uint64 frameCountThisIteration = framesToRead;
+
+ if (frameCountThisIteration > pFlac->currentFLACFrame.pcmFramesRemaining) {
+ frameCountThisIteration = pFlac->currentFLACFrame.pcmFramesRemaining;
+ }
+
+ if (channelCount == 2) {
+ const drflac_int32* pDecodedSamples0 = pFlac->currentFLACFrame.subframes[0].pSamplesS32 + iFirstPCMFrame;
+ const drflac_int32* pDecodedSamples1 = pFlac->currentFLACFrame.subframes[1].pSamplesS32 + iFirstPCMFrame;
+
+ switch (pFlac->currentFLACFrame.header.channelAssignment)
+ {
+ case DRFLAC_CHANNEL_ASSIGNMENT_LEFT_SIDE:
+ {
+ drflac_read_pcm_frames_f32__decode_left_side(pFlac, frameCountThisIteration, unusedBitsPerSample, pDecodedSamples0, pDecodedSamples1, pBufferOut);
+ } break;
+
+ case DRFLAC_CHANNEL_ASSIGNMENT_RIGHT_SIDE:
+ {
+ drflac_read_pcm_frames_f32__decode_right_side(pFlac, frameCountThisIteration, unusedBitsPerSample, pDecodedSamples0, pDecodedSamples1, pBufferOut);
+ } break;
+
+ case DRFLAC_CHANNEL_ASSIGNMENT_MID_SIDE:
+ {
+ drflac_read_pcm_frames_f32__decode_mid_side(pFlac, frameCountThisIteration, unusedBitsPerSample, pDecodedSamples0, pDecodedSamples1, pBufferOut);
+ } break;
+
+ case DRFLAC_CHANNEL_ASSIGNMENT_INDEPENDENT:
+ default:
+ {
+ drflac_read_pcm_frames_f32__decode_independent_stereo(pFlac, frameCountThisIteration, unusedBitsPerSample, pDecodedSamples0, pDecodedSamples1, pBufferOut);
+ } break;
+ }
+ } else {
+ /* Generic interleaving. */
+ drflac_uint64 i;
+ for (i = 0; i < frameCountThisIteration; ++i) {
+ unsigned int j;
+ for (j = 0; j < channelCount; ++j) {
+ drflac_int32 sampleS32 = (drflac_int32)((drflac_uint32)(pFlac->currentFLACFrame.subframes[j].pSamplesS32[iFirstPCMFrame + i]) << (unusedBitsPerSample + pFlac->currentFLACFrame.subframes[j].wastedBitsPerSample));
+ pBufferOut[(i*channelCount)+j] = (float)(sampleS32 / 2147483648.0);
+ }
+ }
+ }
+
+ framesRead += frameCountThisIteration;
+ pBufferOut += frameCountThisIteration * channelCount;
+ framesToRead -= frameCountThisIteration;
+ pFlac->currentPCMFrame += frameCountThisIteration;
+ pFlac->currentFLACFrame.pcmFramesRemaining -= (unsigned int)frameCountThisIteration;
+ }
+ }
+
+ return framesRead;
+}
+
+
+DRFLAC_API drflac_bool32 drflac_seek_to_pcm_frame(drflac* pFlac, drflac_uint64 pcmFrameIndex)
+{
+ if (pFlac == NULL) {
+ return DRFLAC_FALSE;
+ }
+
+ /* Don't do anything if we're already on the seek point. */
+ if (pFlac->currentPCMFrame == pcmFrameIndex) {
+ return DRFLAC_TRUE;
+ }
+
+ /*
+ If we don't know where the first frame begins then we can't seek. This will happen when the STREAMINFO block was not present
+ when the decoder was opened.
+ */
+ if (pFlac->firstFLACFramePosInBytes == 0) {
+ return DRFLAC_FALSE;
+ }
+
+ if (pcmFrameIndex == 0) {
+ pFlac->currentPCMFrame = 0;
+ return drflac__seek_to_first_frame(pFlac);
+ } else {
+ drflac_bool32 wasSuccessful = DRFLAC_FALSE;
+ drflac_uint64 originalPCMFrame = pFlac->currentPCMFrame;
+
+ /* Clamp the sample to the end. */
+ if (pcmFrameIndex > pFlac->totalPCMFrameCount) {
+ pcmFrameIndex = pFlac->totalPCMFrameCount;
+ }
+
+ /* If the target sample and the current sample are in the same frame we just move the position forward. */
+ if (pcmFrameIndex > pFlac->currentPCMFrame) {
+ /* Forward. */
+ drflac_uint32 offset = (drflac_uint32)(pcmFrameIndex - pFlac->currentPCMFrame);
+ if (pFlac->currentFLACFrame.pcmFramesRemaining > offset) {
+ pFlac->currentFLACFrame.pcmFramesRemaining -= offset;
+ pFlac->currentPCMFrame = pcmFrameIndex;
+ return DRFLAC_TRUE;
+ }
+ } else {
+ /* Backward. */
+ drflac_uint32 offsetAbs = (drflac_uint32)(pFlac->currentPCMFrame - pcmFrameIndex);
+ drflac_uint32 currentFLACFramePCMFrameCount = pFlac->currentFLACFrame.header.blockSizeInPCMFrames;
+ drflac_uint32 currentFLACFramePCMFramesConsumed = currentFLACFramePCMFrameCount - pFlac->currentFLACFrame.pcmFramesRemaining;
+ if (currentFLACFramePCMFramesConsumed > offsetAbs) {
+ pFlac->currentFLACFrame.pcmFramesRemaining += offsetAbs;
+ pFlac->currentPCMFrame = pcmFrameIndex;
+ return DRFLAC_TRUE;
+ }
+ }
+
+ /*
+ Different techniques depending on encapsulation. Using the native FLAC seektable with Ogg encapsulation is a bit awkward so
+ we'll instead use Ogg's natural seeking facility.
+ */
+#ifndef DR_FLAC_NO_OGG
+ if (pFlac->container == drflac_container_ogg)
+ {
+ wasSuccessful = drflac_ogg__seek_to_pcm_frame(pFlac, pcmFrameIndex);
+ }
+ else
+#endif
+ {
+ /* First try seeking via the seek table. If this fails, fall back to a brute force seek which is much slower. */
+ if (/*!wasSuccessful && */!pFlac->_noSeekTableSeek) {
+ wasSuccessful = drflac__seek_to_pcm_frame__seek_table(pFlac, pcmFrameIndex);
+ }
+
+#if !defined(DR_FLAC_NO_CRC)
+ /* Fall back to binary search if seek table seeking fails. This requires the length of the stream to be known. */
+ if (!wasSuccessful && !pFlac->_noBinarySearchSeek && pFlac->totalPCMFrameCount > 0) {
+ wasSuccessful = drflac__seek_to_pcm_frame__binary_search(pFlac, pcmFrameIndex);
+ }
+#endif
+
+ /* Fall back to brute force if all else fails. */
+ if (!wasSuccessful && !pFlac->_noBruteForceSeek) {
+ wasSuccessful = drflac__seek_to_pcm_frame__brute_force(pFlac, pcmFrameIndex);
+ }
+ }
+
+ if (wasSuccessful) {
+ pFlac->currentPCMFrame = pcmFrameIndex;
+ } else {
+ /* Seek failed. Try putting the decoder back to it's original state. */
+ if (drflac_seek_to_pcm_frame(pFlac, originalPCMFrame) == DRFLAC_FALSE) {
+ /* Failed to seek back to the original PCM frame. Fall back to 0. */
+ drflac_seek_to_pcm_frame(pFlac, 0);
+ }
+ }
+
+ return wasSuccessful;
+ }
+}
+
+
+
+/* High Level APIs */
+
+/* SIZE_MAX */
+#if defined(SIZE_MAX)
+ #define DRFLAC_SIZE_MAX SIZE_MAX
+#else
+ #if defined(DRFLAC_64BIT)
+ #define DRFLAC_SIZE_MAX ((drflac_uint64)0xFFFFFFFFFFFFFFFF)
+ #else
+ #define DRFLAC_SIZE_MAX 0xFFFFFFFF
+ #endif
+#endif
+/* End SIZE_MAX */
+
+
+/* Using a macro as the definition of the drflac__full_decode_and_close_*() API family. Sue me. */
+#define DRFLAC_DEFINE_FULL_READ_AND_CLOSE(extension, type) \
+static type* drflac__full_read_and_close_ ## extension (drflac* pFlac, unsigned int* channelsOut, unsigned int* sampleRateOut, drflac_uint64* totalPCMFrameCountOut)\
+{ \
+ 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); \
+ \
+ pSampleData = (type*)drflac__malloc_from_callbacks(sampleDataBufferSize, &pFlac->allocationCallbacks); \
+ if (pSampleData == NULL) { \
+ goto on_error; \
+ } \
+ \
+ while ((pcmFramesRead = (drflac_uint64)drflac_read_pcm_frames_##extension(pFlac, sizeof(buffer)/sizeof(buffer[0])/pFlac->channels, buffer)) > 0) { \
+ if (((totalPCMFrameCount + pcmFramesRead) * pFlac->channels * sizeof(type)) > sampleDataBufferSize) { \
+ type* pNewSampleData; \
+ size_t newSampleDataBufferSize; \
+ \
+ newSampleDataBufferSize = sampleDataBufferSize * 2; \
+ pNewSampleData = (type*)drflac__realloc_from_callbacks(pSampleData, newSampleDataBufferSize, sampleDataBufferSize, &pFlac->allocationCallbacks); \
+ if (pNewSampleData == NULL) { \
+ drflac__free_from_callbacks(pSampleData, &pFlac->allocationCallbacks); \
+ goto on_error; \
+ } \
+ \
+ sampleDataBufferSize = newSampleDataBufferSize; \
+ pSampleData = pNewSampleData; \
+ } \
+ \
+ DRFLAC_COPY_MEMORY(pSampleData + (totalPCMFrameCount*pFlac->channels), buffer, (size_t)(pcmFramesRead*pFlac->channels*sizeof(type))); \
+ totalPCMFrameCount += pcmFramesRead; \
+ } \
+ \
+ /* 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; \
+ if (totalPCMFrameCountOut) *totalPCMFrameCountOut = totalPCMFrameCount; \
+ \
+ drflac_close(pFlac); \
+ return pSampleData; \
+ \
+on_error: \
+ drflac_close(pFlac); \
+ return NULL; \
+}
+
+DRFLAC_DEFINE_FULL_READ_AND_CLOSE(s32, drflac_int32)
+DRFLAC_DEFINE_FULL_READ_AND_CLOSE(s16, drflac_int16)
+DRFLAC_DEFINE_FULL_READ_AND_CLOSE(f32, float)
+
+DRFLAC_API drflac_int32* drflac_open_and_read_pcm_frames_s32(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drflac_uint64* totalPCMFrameCountOut, const drflac_allocation_callbacks* pAllocationCallbacks)
+{
+ drflac* pFlac;
+
+ if (channelsOut) {
+ *channelsOut = 0;
+ }
+ if (sampleRateOut) {
+ *sampleRateOut = 0;
+ }
+ if (totalPCMFrameCountOut) {
+ *totalPCMFrameCountOut = 0;
+ }
+
+ pFlac = drflac_open(onRead, onSeek, pUserData, pAllocationCallbacks);
+ if (pFlac == NULL) {
+ return NULL;
+ }
+
+ return drflac__full_read_and_close_s32(pFlac, channelsOut, sampleRateOut, totalPCMFrameCountOut);
+}
+
+DRFLAC_API drflac_int16* drflac_open_and_read_pcm_frames_s16(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drflac_uint64* totalPCMFrameCountOut, const drflac_allocation_callbacks* pAllocationCallbacks)
+{
+ drflac* pFlac;
+
+ if (channelsOut) {
+ *channelsOut = 0;
+ }
+ if (sampleRateOut) {
+ *sampleRateOut = 0;
+ }
+ if (totalPCMFrameCountOut) {
+ *totalPCMFrameCountOut = 0;
+ }
+
+ pFlac = drflac_open(onRead, onSeek, pUserData, pAllocationCallbacks);
+ if (pFlac == NULL) {
+ return NULL;
+ }
+
+ return drflac__full_read_and_close_s16(pFlac, channelsOut, sampleRateOut, totalPCMFrameCountOut);
+}
+
+DRFLAC_API float* drflac_open_and_read_pcm_frames_f32(drflac_read_proc onRead, drflac_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drflac_uint64* totalPCMFrameCountOut, const drflac_allocation_callbacks* pAllocationCallbacks)
+{
+ drflac* pFlac;
+
+ if (channelsOut) {
+ *channelsOut = 0;
+ }
+ if (sampleRateOut) {
+ *sampleRateOut = 0;
+ }
+ if (totalPCMFrameCountOut) {
+ *totalPCMFrameCountOut = 0;
+ }
+
+ pFlac = drflac_open(onRead, onSeek, pUserData, pAllocationCallbacks);
+ if (pFlac == NULL) {
+ return NULL;
+ }
+
+ return drflac__full_read_and_close_f32(pFlac, channelsOut, sampleRateOut, totalPCMFrameCountOut);
+}
+
+#ifndef DR_FLAC_NO_STDIO
+DRFLAC_API drflac_int32* drflac_open_file_and_read_pcm_frames_s32(const char* filename, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks)
+{
+ drflac* pFlac;
+
+ if (sampleRate) {
+ *sampleRate = 0;
+ }
+ if (channels) {
+ *channels = 0;
+ }
+ if (totalPCMFrameCount) {
+ *totalPCMFrameCount = 0;
+ }
+
+ pFlac = drflac_open_file(filename, pAllocationCallbacks);
+ if (pFlac == NULL) {
+ return NULL;
+ }
+
+ return drflac__full_read_and_close_s32(pFlac, channels, sampleRate, totalPCMFrameCount);
+}
+
+DRFLAC_API drflac_int16* drflac_open_file_and_read_pcm_frames_s16(const char* filename, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks)
+{
+ drflac* pFlac;
+
+ if (sampleRate) {
+ *sampleRate = 0;
+ }
+ if (channels) {
+ *channels = 0;
+ }
+ if (totalPCMFrameCount) {
+ *totalPCMFrameCount = 0;
+ }
+
+ pFlac = drflac_open_file(filename, pAllocationCallbacks);
+ if (pFlac == NULL) {
+ return NULL;
+ }
+
+ return drflac__full_read_and_close_s16(pFlac, channels, sampleRate, totalPCMFrameCount);
+}
+
+DRFLAC_API float* drflac_open_file_and_read_pcm_frames_f32(const char* filename, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks)
+{
+ drflac* pFlac;
+
+ if (sampleRate) {
+ *sampleRate = 0;
+ }
+ if (channels) {
+ *channels = 0;
+ }
+ if (totalPCMFrameCount) {
+ *totalPCMFrameCount = 0;
+ }
+
+ pFlac = drflac_open_file(filename, pAllocationCallbacks);
+ if (pFlac == NULL) {
+ return NULL;
+ }
+
+ return drflac__full_read_and_close_f32(pFlac, channels, sampleRate, totalPCMFrameCount);
+}
+#endif
+
+DRFLAC_API drflac_int32* drflac_open_memory_and_read_pcm_frames_s32(const void* data, size_t dataSize, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks)
+{
+ drflac* pFlac;
+
+ if (sampleRate) {
+ *sampleRate = 0;
+ }
+ if (channels) {
+ *channels = 0;
+ }
+ if (totalPCMFrameCount) {
+ *totalPCMFrameCount = 0;
+ }
+
+ pFlac = drflac_open_memory(data, dataSize, pAllocationCallbacks);
+ if (pFlac == NULL) {
+ return NULL;
+ }
+
+ return drflac__full_read_and_close_s32(pFlac, channels, sampleRate, totalPCMFrameCount);
+}
+
+DRFLAC_API drflac_int16* drflac_open_memory_and_read_pcm_frames_s16(const void* data, size_t dataSize, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks)
+{
+ drflac* pFlac;
+
+ if (sampleRate) {
+ *sampleRate = 0;
+ }
+ if (channels) {
+ *channels = 0;
+ }
+ if (totalPCMFrameCount) {
+ *totalPCMFrameCount = 0;
+ }
+
+ pFlac = drflac_open_memory(data, dataSize, pAllocationCallbacks);
+ if (pFlac == NULL) {
+ return NULL;
+ }
+
+ return drflac__full_read_and_close_s16(pFlac, channels, sampleRate, totalPCMFrameCount);
+}
+
+DRFLAC_API float* drflac_open_memory_and_read_pcm_frames_f32(const void* data, size_t dataSize, unsigned int* channels, unsigned int* sampleRate, drflac_uint64* totalPCMFrameCount, const drflac_allocation_callbacks* pAllocationCallbacks)
+{
+ drflac* pFlac;
+
+ if (sampleRate) {
+ *sampleRate = 0;
+ }
+ if (channels) {
+ *channels = 0;
+ }
+ if (totalPCMFrameCount) {
+ *totalPCMFrameCount = 0;
+ }
+
+ pFlac = drflac_open_memory(data, dataSize, pAllocationCallbacks);
+ if (pFlac == NULL) {
+ return NULL;
+ }
+
+ return drflac__full_read_and_close_f32(pFlac, channels, sampleRate, totalPCMFrameCount);
+}
+
+
+DRFLAC_API void drflac_free(void* p, const drflac_allocation_callbacks* pAllocationCallbacks)
+{
+ if (pAllocationCallbacks != NULL) {
+ drflac__free_from_callbacks(p, pAllocationCallbacks);
+ } else {
+ drflac__free_default(p, NULL);
+ }
+}
+
+
+
+
+DRFLAC_API void drflac_init_vorbis_comment_iterator(drflac_vorbis_comment_iterator* pIter, drflac_uint32 commentCount, const void* pComments)
+{
+ if (pIter == NULL) {
+ return;
+ }
+
+ pIter->countRemaining = commentCount;
+ pIter->pRunningData = (const char*)pComments;
+}
+
+DRFLAC_API const char* drflac_next_vorbis_comment(drflac_vorbis_comment_iterator* pIter, drflac_uint32* pCommentLengthOut)
+{
+ drflac_int32 length;
+ const char* pComment;
+
+ /* Safety. */
+ if (pCommentLengthOut) {
+ *pCommentLengthOut = 0;
+ }
+
+ if (pIter == NULL || pIter->countRemaining == 0 || pIter->pRunningData == NULL) {
+ return NULL;
+ }
+
+ length = drflac__le2host_32_ptr_unaligned(pIter->pRunningData);
+ pIter->pRunningData += 4;
+
+ pComment = pIter->pRunningData;
+ pIter->pRunningData += length;
+ pIter->countRemaining -= 1;
+
+ if (pCommentLengthOut) {
+ *pCommentLengthOut = length;
+ }
+
+ return pComment;
+}
+
+
+
+
+DRFLAC_API void drflac_init_cuesheet_track_iterator(drflac_cuesheet_track_iterator* pIter, drflac_uint32 trackCount, const void* pTrackData)
+{
+ if (pIter == NULL) {
+ return;
+ }
+
+ pIter->countRemaining = trackCount;
+ pIter->pRunningData = (const char*)pTrackData;
+}
+
+DRFLAC_API drflac_bool32 drflac_next_cuesheet_track(drflac_cuesheet_track_iterator* pIter, drflac_cuesheet_track* pCuesheetTrack)
+{
+ drflac_cuesheet_track cuesheetTrack;
+ const char* pRunningData;
+ drflac_uint64 offsetHi;
+ drflac_uint64 offsetLo;
+
+ if (pIter == NULL || pIter->countRemaining == 0 || pIter->pRunningData == NULL) {
+ return DRFLAC_FALSE;
+ }
+
+ pRunningData = pIter->pRunningData;
+
+ offsetHi = drflac__be2host_32(*(const drflac_uint32*)pRunningData); pRunningData += 4;
+ offsetLo = drflac__be2host_32(*(const drflac_uint32*)pRunningData); pRunningData += 4;
+ cuesheetTrack.offset = offsetLo | (offsetHi << 32);
+ cuesheetTrack.trackNumber = pRunningData[0]; pRunningData += 1;
+ DRFLAC_COPY_MEMORY(cuesheetTrack.ISRC, pRunningData, sizeof(cuesheetTrack.ISRC)); pRunningData += 12;
+ cuesheetTrack.isAudio = (pRunningData[0] & 0x80) != 0;
+ cuesheetTrack.preEmphasis = (pRunningData[0] & 0x40) != 0; pRunningData += 14;
+ cuesheetTrack.indexCount = pRunningData[0]; pRunningData += 1;
+ cuesheetTrack.pIndexPoints = (const drflac_cuesheet_track_index*)pRunningData; pRunningData += cuesheetTrack.indexCount * sizeof(drflac_cuesheet_track_index);
+
+ pIter->pRunningData = pRunningData;
+ pIter->countRemaining -= 1;
+
+ if (pCuesheetTrack) {
+ *pCuesheetTrack = cuesheetTrack;
+ }
+
+ return DRFLAC_TRUE;
+}
+
+#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
+ #pragma GCC diagnostic pop
+#endif
+#endif /* dr_flac_c */
+#endif /* DR_FLAC_IMPLEMENTATION */
+
+
+/*
+REVISION HISTORY
+================
+v0.12.42 - 2023-11-02
+ - Fix build for ARMv6-M.
+ - Fix a compilation warning with GCC.
+
+v0.12.41 - 2023-06-17
+ - Fix an incorrect date in revision history. No functional change.
+
+v0.12.40 - 2023-05-22
+ - Minor code restructure. No functional change.
+
+v0.12.39 - 2022-09-17
+ - Fix compilation with DJGPP.
+ - Fix compilation error with Visual Studio 2019 and the ARM build.
+ - Fix an error with SSE 4.1 detection.
+ - Add support for disabling wchar_t with DR_WAV_NO_WCHAR.
+ - Improve compatibility with compilers which lack support for explicit struct packing.
+ - Improve compatibility with low-end and embedded hardware by reducing the amount of stack
+ allocation when loading an Ogg encapsulated file.
+
+v0.12.38 - 2022-04-10
+ - Fix compilation error on older versions of GCC.
+
+v0.12.37 - 2022-02-12
+ - Improve ARM detection.
+
+v0.12.36 - 2022-02-07
+ - Fix a compilation error with the ARM build.
+
+v0.12.35 - 2022-02-06
+ - Fix a bug due to underestimating the amount of precision required for the prediction stage.
+ - Fix some bugs found from fuzz testing.
+
+v0.12.34 - 2022-01-07
+ - Fix some misalignment bugs when reading metadata.
+
+v0.12.33 - 2021-12-22
+ - Fix a bug with seeking when the seek table does not start at PCM frame 0.
+
+v0.12.32 - 2021-12-11
+ - Fix a warning with Clang.
+
+v0.12.31 - 2021-08-16
+ - Silence some warnings.
+
+v0.12.30 - 2021-07-31
+ - Fix platform detection for ARM64.
+
+v0.12.29 - 2021-04-02
+ - Fix a bug where the running PCM frame index is set to an invalid value when over-seeking.
+ - Fix a decoding error due to an incorrect validation check.
+
+v0.12.28 - 2021-02-21
+ - Fix a warning due to referencing _MSC_VER when it is undefined.
+
+v0.12.27 - 2021-01-31
+ - Fix a static analysis warning.
+
+v0.12.26 - 2021-01-17
+ - Fix a compilation warning due to _BSD_SOURCE being deprecated.
+
+v0.12.25 - 2020-12-26
+ - Update documentation.
+
+v0.12.24 - 2020-11-29
+ - Fix ARM64/NEON detection when compiling with MSVC.
+
+v0.12.23 - 2020-11-21
+ - Fix compilation with OpenWatcom.
+
+v0.12.22 - 2020-11-01
+ - Fix an error with the previous release.
+
+v0.12.21 - 2020-11-01
+ - Fix a possible deadlock when seeking.
+ - Improve compiler support for older versions of GCC.
+
+v0.12.20 - 2020-09-08
+ - Fix a compilation error on older compilers.
+
+v0.12.19 - 2020-08-30
+ - Fix a bug due to an undefined 32-bit shift.
+
+v0.12.18 - 2020-08-14
+ - Fix a crash when compiling with clang-cl.
+
+v0.12.17 - 2020-08-02
+ - Simplify sized types.
+
+v0.12.16 - 2020-07-25
+ - Fix a compilation warning.
+
+v0.12.15 - 2020-07-06
+ - Check for negative LPC shifts and return an error.
+
+v0.12.14 - 2020-06-23
+ - Add include guard for the implementation section.
+
+v0.12.13 - 2020-05-16
+ - Add compile-time and run-time version querying.
+ - DRFLAC_VERSION_MINOR
+ - DRFLAC_VERSION_MAJOR
+ - DRFLAC_VERSION_REVISION
+ - DRFLAC_VERSION_STRING
+ - drflac_version()
+ - drflac_version_string()
+
+v0.12.12 - 2020-04-30
+ - Fix compilation errors with VC6.
+
+v0.12.11 - 2020-04-19
+ - Fix some pedantic warnings.
+ - Fix some undefined behaviour warnings.
+
+v0.12.10 - 2020-04-10
+ - Fix some bugs when trying to seek with an invalid seek table.
+
+v0.12.9 - 2020-04-05
+ - Fix warnings.
+
+v0.12.8 - 2020-04-04
+ - Add drflac_open_file_w() and drflac_open_file_with_metadata_w().
+ - Fix some static analysis warnings.
+ - Minor documentation updates.
+
+v0.12.7 - 2020-03-14
+ - Fix compilation errors with VC6.
+
+v0.12.6 - 2020-03-07
+ - Fix compilation error with Visual Studio .NET 2003.
+
+v0.12.5 - 2020-01-30
+ - Silence some static analysis warnings.
+
+v0.12.4 - 2020-01-29
+ - Silence some static analysis warnings.
+
+v0.12.3 - 2019-12-02
+ - Fix some warnings when compiling with GCC and the -Og flag.
+ - Fix a crash in out-of-memory situations.
+ - Fix potential integer overflow bug.
+ - Fix some static analysis warnings.
+ - Fix a possible crash when using custom memory allocators without a custom realloc() implementation.
+ - Fix a bug with binary search seeking where the bits per sample is not a multiple of 8.
+
+v0.12.2 - 2019-10-07
+ - Internal code clean up.
+
+v0.12.1 - 2019-09-29
+ - Fix some Clang Static Analyzer warnings.
+ - Fix an unused variable warning.
+
+v0.12.0 - 2019-09-23
+ - API CHANGE: Add support for user defined memory allocation routines. This system allows the program to specify their own memory allocation
+ routines with a user data pointer for client-specific contextual data. This adds an extra parameter to the end of the following APIs:
+ - drflac_open()
+ - drflac_open_relaxed()
+ - drflac_open_with_metadata()
+ - drflac_open_with_metadata_relaxed()
+ - drflac_open_file()
+ - drflac_open_file_with_metadata()
+ - drflac_open_memory()
+ - drflac_open_memory_with_metadata()
+ - drflac_open_and_read_pcm_frames_s32()
+ - drflac_open_and_read_pcm_frames_s16()
+ - drflac_open_and_read_pcm_frames_f32()
+ - drflac_open_file_and_read_pcm_frames_s32()
+ - drflac_open_file_and_read_pcm_frames_s16()
+ - drflac_open_file_and_read_pcm_frames_f32()
+ - drflac_open_memory_and_read_pcm_frames_s32()
+ - drflac_open_memory_and_read_pcm_frames_s16()
+ - drflac_open_memory_and_read_pcm_frames_f32()
+ Set this extra parameter to NULL to use defaults which is the same as the previous behaviour. Setting this NULL will use
+ DRFLAC_MALLOC, DRFLAC_REALLOC and DRFLAC_FREE.
+ - Remove deprecated APIs:
+ - drflac_read_s32()
+ - drflac_read_s16()
+ - drflac_read_f32()
+ - drflac_seek_to_sample()
+ - drflac_open_and_decode_s32()
+ - drflac_open_and_decode_s16()
+ - drflac_open_and_decode_f32()
+ - drflac_open_and_decode_file_s32()
+ - drflac_open_and_decode_file_s16()
+ - drflac_open_and_decode_file_f32()
+ - drflac_open_and_decode_memory_s32()
+ - drflac_open_and_decode_memory_s16()
+ - drflac_open_and_decode_memory_f32()
+ - Remove drflac.totalSampleCount which is now replaced with drflac.totalPCMFrameCount. You can emulate drflac.totalSampleCount
+ by doing pFlac->totalPCMFrameCount*pFlac->channels.
+ - Rename drflac.currentFrame to drflac.currentFLACFrame to remove ambiguity with PCM frames.
+ - Fix errors when seeking to the end of a stream.
+ - Optimizations to seeking.
+ - SSE improvements and optimizations.
+ - ARM NEON optimizations.
+ - Optimizations to drflac_read_pcm_frames_s16().
+ - Optimizations to drflac_read_pcm_frames_s32().
+
+v0.11.10 - 2019-06-26
+ - Fix a compiler error.
+
+v0.11.9 - 2019-06-16
+ - Silence some ThreadSanitizer warnings.
+
+v0.11.8 - 2019-05-21
+ - Fix warnings.
+
+v0.11.7 - 2019-05-06
+ - C89 fixes.
+
+v0.11.6 - 2019-05-05
+ - Add support for C89.
+ - Fix a compiler warning when CRC is disabled.
+ - Change license to choice of public domain or MIT-0.
+
+v0.11.5 - 2019-04-19
+ - Fix a compiler error with GCC.
+
+v0.11.4 - 2019-04-17
+ - Fix some warnings with GCC when compiling with -std=c99.
+
+v0.11.3 - 2019-04-07
+ - Silence warnings with GCC.
+
+v0.11.2 - 2019-03-10
+ - Fix a warning.
+
+v0.11.1 - 2019-02-17
+ - Fix a potential bug with seeking.
+
+v0.11.0 - 2018-12-16
+ - API CHANGE: Deprecated drflac_read_s32(), drflac_read_s16() and drflac_read_f32() and replaced them with
+ drflac_read_pcm_frames_s32(), drflac_read_pcm_frames_s16() and drflac_read_pcm_frames_f32(). The new APIs take
+ and return PCM frame counts instead of sample counts. To upgrade you will need to change the input count by
+ dividing it by the channel count, and then do the same with the return value.
+ - API_CHANGE: Deprecated drflac_seek_to_sample() and replaced with drflac_seek_to_pcm_frame(). Same rules as
+ the changes to drflac_read_*() apply.
+ - API CHANGE: Deprecated drflac_open_and_decode_*() and replaced with drflac_open_*_and_read_*(). Same rules as
+ the changes to drflac_read_*() apply.
+ - Optimizations.
+
+v0.10.0 - 2018-09-11
+ - Remove the DR_FLAC_NO_WIN32_IO option and the Win32 file IO functionality. If you need to use Win32 file IO you
+ need to do it yourself via the callback API.
+ - Fix the clang build.
+ - Fix undefined behavior.
+ - Fix errors with CUESHEET metdata blocks.
+ - Add an API for iterating over each cuesheet track in the CUESHEET metadata block. This works the same way as the
+ Vorbis comment API.
+ - Other miscellaneous bug fixes, mostly relating to invalid FLAC streams.
+ - Minor optimizations.
+
+v0.9.11 - 2018-08-29
+ - Fix a bug with sample reconstruction.
+
+v0.9.10 - 2018-08-07
+ - Improve 64-bit detection.
+
+v0.9.9 - 2018-08-05
+ - Fix C++ build on older versions of GCC.
+
+v0.9.8 - 2018-07-24
+ - Fix compilation errors.
+
+v0.9.7 - 2018-07-05
+ - Fix a warning.
+
+v0.9.6 - 2018-06-29
+ - Fix some typos.
+
+v0.9.5 - 2018-06-23
+ - Fix some warnings.
+
+v0.9.4 - 2018-06-14
+ - Optimizations to seeking.
+ - Clean up.
+
+v0.9.3 - 2018-05-22
+ - Bug fix.
+
+v0.9.2 - 2018-05-12
+ - Fix a compilation error due to a missing break statement.
+
+v0.9.1 - 2018-04-29
+ - Fix compilation error with Clang.
+
+v0.9 - 2018-04-24
+ - Fix Clang build.
+ - Start using major.minor.revision versioning.
+
+v0.8g - 2018-04-19
+ - Fix build on non-x86/x64 architectures.
+
+v0.8f - 2018-02-02
+ - Stop pretending to support changing rate/channels mid stream.
+
+v0.8e - 2018-02-01
+ - Fix a crash when the block size of a frame is larger than the maximum block size defined by the FLAC stream.
+ - Fix a crash the the Rice partition order is invalid.
+
+v0.8d - 2017-09-22
+ - Add support for decoding streams with ID3 tags. ID3 tags are just skipped.
+
+v0.8c - 2017-09-07
+ - Fix warning on non-x86/x64 architectures.
+
+v0.8b - 2017-08-19
+ - Fix build on non-x86/x64 architectures.
+
+v0.8a - 2017-08-13
+ - A small optimization for the Clang build.
+
+v0.8 - 2017-08-12
+ - API CHANGE: Rename dr_* types to drflac_*.
+ - Optimizations. This brings dr_flac back to about the same class of efficiency as the reference implementation.
+ - Add support for custom implementations of malloc(), realloc(), etc.
+ - Add CRC checking to Ogg encapsulated streams.
+ - Fix VC++ 6 build. This is only for the C++ compiler. The C compiler is not currently supported.
+ - Bug fixes.
+
+v0.7 - 2017-07-23
+ - Add support for opening a stream without a header block. To do this, use drflac_open_relaxed() / drflac_open_with_metadata_relaxed().
+
+v0.6 - 2017-07-22
+ - Add support for recovering from invalid frames. With this change, dr_flac will simply skip over invalid frames as if they
+ never existed. Frames are checked against their sync code, the CRC-8 of the frame header and the CRC-16 of the whole frame.
+
+v0.5 - 2017-07-16
+ - Fix typos.
+ - Change drflac_bool* types to unsigned.
+ - Add CRC checking. This makes dr_flac slower, but can be disabled with #define DR_FLAC_NO_CRC.
+
+v0.4f - 2017-03-10
+ - Fix a couple of bugs with the bitstreaming code.
+
+v0.4e - 2017-02-17
+ - Fix some warnings.
+
+v0.4d - 2016-12-26
+ - Add support for 32-bit floating-point PCM decoding.
+ - Use drflac_int* and drflac_uint* sized types to improve compiler support.
+ - Minor improvements to documentation.
+
+v0.4c - 2016-12-26
+ - Add support for signed 16-bit integer PCM decoding.
+
+v0.4b - 2016-10-23
+ - A minor change to drflac_bool8 and drflac_bool32 types.
+
+v0.4a - 2016-10-11
+ - Rename drBool32 to drflac_bool32 for styling consistency.
+
+v0.4 - 2016-09-29
+ - API/ABI CHANGE: Use fixed size 32-bit booleans instead of the built-in bool type.
+ - API CHANGE: Rename drflac_open_and_decode*() to drflac_open_and_decode*_s32().
+ - API CHANGE: Swap the order of "channels" and "sampleRate" parameters in drflac_open_and_decode*(). Rationale for this is to
+ keep it consistent with drflac_audio.
+
+v0.3f - 2016-09-21
+ - Fix a warning with GCC.
+
+v0.3e - 2016-09-18
+ - Fixed a bug where GCC 4.3+ was not getting properly identified.
+ - Fixed a few typos.
+ - Changed date formats to ISO 8601 (YYYY-MM-DD).
+
+v0.3d - 2016-06-11
+ - Minor clean up.
+
+v0.3c - 2016-05-28
+ - Fixed compilation error.
+
+v0.3b - 2016-05-16
+ - Fixed Linux/GCC build.
+ - Updated documentation.
+
+v0.3a - 2016-05-15
+ - Minor fixes to documentation.
+
+v0.3 - 2016-05-11
+ - Optimizations. Now at about parity with the reference implementation on 32-bit builds.
+ - Lots of clean up.
+
+v0.2b - 2016-05-10
+ - Bug fixes.
+
+v0.2a - 2016-05-10
+ - Made drflac_open_and_decode() more robust.
+ - Removed an unused debugging variable
+
+v0.2 - 2016-05-09
+ - Added support for Ogg encapsulation.
+ - API CHANGE. Have the onSeek callback take a third argument which specifies whether or not the seek
+ should be relative to the start or the current position. Also changes the seeking rules such that
+ seeking offsets will never be negative.
+ - Have drflac_open_and_decode() fail gracefully if the stream has an unknown total sample count.
+
+v0.1b - 2016-05-07
+ - Properly close the file handle in drflac_open_file() and family when the decoder fails to initialize.
+ - Removed a stale comment.
+
+v0.1a - 2016-05-05
+ - Minor formatting changes.
+ - Fixed a warning on the GCC build.
+
+v0.1 - 2016-05-03
+ - Initial versioned release.
+*/
+
+/*
+This software is available as a choice of the following licenses. Choose
+whichever you prefer.
+
+===============================================================================
+ALTERNATIVE 1 - Public Domain (www.unlicense.org)
+===============================================================================
+This is free and unencumbered software released into the public domain.
+
+Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
+software, either in source code form or as a compiled binary, for any purpose,
+commercial or non-commercial, and by any means.
+
+In jurisdictions that recognize copyright laws, the author or authors of this
+software dedicate any and all copyright interest in the software to the public
+domain. We make this dedication for the benefit of the public at large and to
+the detriment of our heirs and successors. We intend this dedication to be an
+overt act of relinquishment in perpetuity of all present and future rights to
+this software under copyright law.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+For more information, please refer to
+
+===============================================================================
+ALTERNATIVE 2 - MIT No Attribution
+===============================================================================
+Copyright 2023 David Reid
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
diff --git a/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/dr_mp3.h b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/dr_mp3.h
new file mode 100644
index 0000000..e1a66d9
--- /dev/null
+++ b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/dr_mp3.h
@@ -0,0 +1,4837 @@
+/*
+MP3 audio decoder. Choice of public domain or MIT-0. See license statements at the end of this file.
+dr_mp3 - v0.6.39 - 2024-02-27
+
+David Reid - mackron@gmail.com
+
+GitHub: https://github.com/mackron/dr_libs
+
+Based on minimp3 (https://github.com/lieff/minimp3) which is where the real work was done. See the bottom of this file for differences between minimp3 and dr_mp3.
+*/
+
+/*
+RELEASE NOTES - VERSION 0.6
+===========================
+Version 0.6 includes breaking changes with the configuration of decoders. The ability to customize the number of output channels and the sample rate has been
+removed. You must now use the channel count and sample rate reported by the MP3 stream itself, and all channel and sample rate conversion must be done
+yourself.
+
+
+Changes to Initialization
+-------------------------
+Previously, `drmp3_init()`, etc. took a pointer to a `drmp3_config` object that allowed you to customize the output channels and sample rate. This has been
+removed. If you need the old behaviour you will need to convert the data yourself or just not upgrade. The following APIs have changed.
+
+ `drmp3_init()`
+ `drmp3_init_memory()`
+ `drmp3_init_file()`
+
+
+Miscellaneous Changes
+---------------------
+Support for loading a file from a `wchar_t` string has been added via the `drmp3_init_file_w()` API.
+*/
+
+/*
+Introducation
+=============
+dr_mp3 is a single file library. To use it, do something like the following in one .c file.
+
+ ```c
+ #define DR_MP3_IMPLEMENTATION
+ #include "dr_mp3.h"
+ ```
+
+You can then #include this file in other parts of the program as you would with any other header file. To decode audio data, do something like the following:
+
+ ```c
+ drmp3 mp3;
+ if (!drmp3_init_file(&mp3, "MySong.mp3", NULL)) {
+ // Failed to open file
+ }
+
+ ...
+
+ drmp3_uint64 framesRead = drmp3_read_pcm_frames_f32(pMP3, framesToRead, pFrames);
+ ```
+
+The drmp3 object is transparent so you can get access to the channel count and sample rate like so:
+
+ ```
+ drmp3_uint32 channels = mp3.channels;
+ drmp3_uint32 sampleRate = mp3.sampleRate;
+ ```
+
+The example above initializes a decoder from a file, but you can also initialize it from a block of memory and read and seek callbacks with
+`drmp3_init_memory()` and `drmp3_init()` respectively.
+
+You do not need to do any annoying memory management when reading PCM frames - this is all managed internally. You can request any number of PCM frames in each
+call to `drmp3_read_pcm_frames_f32()` and it will return as many PCM frames as it can, up to the requested amount.
+
+You can also decode an entire file in one go with `drmp3_open_and_read_pcm_frames_f32()`, `drmp3_open_memory_and_read_pcm_frames_f32()` and
+`drmp3_open_file_and_read_pcm_frames_f32()`.
+
+
+Build Options
+=============
+#define these options before including this file.
+
+#define DR_MP3_NO_STDIO
+ Disable drmp3_init_file(), etc.
+
+#define DR_MP3_NO_SIMD
+ Disable SIMD optimizations.
+*/
+
+#ifndef dr_mp3_h
+#define dr_mp3_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define DRMP3_STRINGIFY(x) #x
+#define DRMP3_XSTRINGIFY(x) DRMP3_STRINGIFY(x)
+
+#define DRMP3_VERSION_MAJOR 0
+#define DRMP3_VERSION_MINOR 6
+#define DRMP3_VERSION_REVISION 39
+#define DRMP3_VERSION_STRING DRMP3_XSTRINGIFY(DRMP3_VERSION_MAJOR) "." DRMP3_XSTRINGIFY(DRMP3_VERSION_MINOR) "." DRMP3_XSTRINGIFY(DRMP3_VERSION_REVISION)
+
+#include /* For size_t. */
+
+/* Sized Types */
+typedef signed char drmp3_int8;
+typedef unsigned char drmp3_uint8;
+typedef signed short drmp3_int16;
+typedef unsigned short drmp3_uint16;
+typedef signed int drmp3_int32;
+typedef unsigned int drmp3_uint32;
+#if defined(_MSC_VER) && !defined(__clang__)
+ typedef signed __int64 drmp3_int64;
+ typedef unsigned __int64 drmp3_uint64;
+#else
+ #if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wlong-long"
+ #if defined(__clang__)
+ #pragma GCC diagnostic ignored "-Wc++11-long-long"
+ #endif
+ #endif
+ typedef signed long long drmp3_int64;
+ typedef unsigned long long drmp3_uint64;
+ #if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
+ #pragma GCC diagnostic pop
+ #endif
+#endif
+#if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__)) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(_M_ARM64) || defined(__powerpc64__)
+ typedef drmp3_uint64 drmp3_uintptr;
+#else
+ typedef drmp3_uint32 drmp3_uintptr;
+#endif
+typedef drmp3_uint8 drmp3_bool8;
+typedef drmp3_uint32 drmp3_bool32;
+#define DRMP3_TRUE 1
+#define DRMP3_FALSE 0
+/* End Sized Types */
+
+/* Decorations */
+#if !defined(DRMP3_API)
+ #if defined(DRMP3_DLL)
+ #if defined(_WIN32)
+ #define DRMP3_DLL_IMPORT __declspec(dllimport)
+ #define DRMP3_DLL_EXPORT __declspec(dllexport)
+ #define DRMP3_DLL_PRIVATE static
+ #else
+ #if defined(__GNUC__) && __GNUC__ >= 4
+ #define DRMP3_DLL_IMPORT __attribute__((visibility("default")))
+ #define DRMP3_DLL_EXPORT __attribute__((visibility("default")))
+ #define DRMP3_DLL_PRIVATE __attribute__((visibility("hidden")))
+ #else
+ #define DRMP3_DLL_IMPORT
+ #define DRMP3_DLL_EXPORT
+ #define DRMP3_DLL_PRIVATE static
+ #endif
+ #endif
+
+ #if defined(DR_MP3_IMPLEMENTATION) || defined(DRMP3_IMPLEMENTATION)
+ #define DRMP3_API DRMP3_DLL_EXPORT
+ #else
+ #define DRMP3_API DRMP3_DLL_IMPORT
+ #endif
+ #define DRMP3_PRIVATE DRMP3_DLL_PRIVATE
+ #else
+ #define DRMP3_API extern
+ #define DRMP3_PRIVATE static
+ #endif
+#endif
+/* End Decorations */
+
+/* Result Codes */
+typedef drmp3_int32 drmp3_result;
+#define DRMP3_SUCCESS 0
+#define DRMP3_ERROR -1 /* A generic error. */
+#define DRMP3_INVALID_ARGS -2
+#define DRMP3_INVALID_OPERATION -3
+#define DRMP3_OUT_OF_MEMORY -4
+#define DRMP3_OUT_OF_RANGE -5
+#define DRMP3_ACCESS_DENIED -6
+#define DRMP3_DOES_NOT_EXIST -7
+#define DRMP3_ALREADY_EXISTS -8
+#define DRMP3_TOO_MANY_OPEN_FILES -9
+#define DRMP3_INVALID_FILE -10
+#define DRMP3_TOO_BIG -11
+#define DRMP3_PATH_TOO_LONG -12
+#define DRMP3_NAME_TOO_LONG -13
+#define DRMP3_NOT_DIRECTORY -14
+#define DRMP3_IS_DIRECTORY -15
+#define DRMP3_DIRECTORY_NOT_EMPTY -16
+#define DRMP3_END_OF_FILE -17
+#define DRMP3_NO_SPACE -18
+#define DRMP3_BUSY -19
+#define DRMP3_IO_ERROR -20
+#define DRMP3_INTERRUPT -21
+#define DRMP3_UNAVAILABLE -22
+#define DRMP3_ALREADY_IN_USE -23
+#define DRMP3_BAD_ADDRESS -24
+#define DRMP3_BAD_SEEK -25
+#define DRMP3_BAD_PIPE -26
+#define DRMP3_DEADLOCK -27
+#define DRMP3_TOO_MANY_LINKS -28
+#define DRMP3_NOT_IMPLEMENTED -29
+#define DRMP3_NO_MESSAGE -30
+#define DRMP3_BAD_MESSAGE -31
+#define DRMP3_NO_DATA_AVAILABLE -32
+#define DRMP3_INVALID_DATA -33
+#define DRMP3_TIMEOUT -34
+#define DRMP3_NO_NETWORK -35
+#define DRMP3_NOT_UNIQUE -36
+#define DRMP3_NOT_SOCKET -37
+#define DRMP3_NO_ADDRESS -38
+#define DRMP3_BAD_PROTOCOL -39
+#define DRMP3_PROTOCOL_UNAVAILABLE -40
+#define DRMP3_PROTOCOL_NOT_SUPPORTED -41
+#define DRMP3_PROTOCOL_FAMILY_NOT_SUPPORTED -42
+#define DRMP3_ADDRESS_FAMILY_NOT_SUPPORTED -43
+#define DRMP3_SOCKET_NOT_SUPPORTED -44
+#define DRMP3_CONNECTION_RESET -45
+#define DRMP3_ALREADY_CONNECTED -46
+#define DRMP3_NOT_CONNECTED -47
+#define DRMP3_CONNECTION_REFUSED -48
+#define DRMP3_NO_HOST -49
+#define DRMP3_IN_PROGRESS -50
+#define DRMP3_CANCELLED -51
+#define DRMP3_MEMORY_ALREADY_MAPPED -52
+#define DRMP3_AT_END -53
+/* End Result Codes */
+
+#define DRMP3_MAX_PCM_FRAMES_PER_MP3_FRAME 1152
+#define DRMP3_MAX_SAMPLES_PER_FRAME (DRMP3_MAX_PCM_FRAMES_PER_MP3_FRAME*2)
+
+/* Inline */
+#ifdef _MSC_VER
+ #define DRMP3_INLINE __forceinline
+#elif defined(__GNUC__)
+ /*
+ I've had a bug report where GCC is emitting warnings about functions possibly not being inlineable. This warning happens when
+ the __attribute__((always_inline)) attribute is defined without an "inline" statement. I think therefore there must be some
+ case where "__inline__" is not always defined, thus the compiler emitting these warnings. When using -std=c89 or -ansi on the
+ command line, we cannot use the "inline" keyword and instead need to use "__inline__". In an attempt to work around this issue
+ I am using "__inline__" only when we're compiling in strict ANSI mode.
+ */
+ #if defined(__STRICT_ANSI__)
+ #define DRMP3_GNUC_INLINE_HINT __inline__
+ #else
+ #define DRMP3_GNUC_INLINE_HINT inline
+ #endif
+
+ #if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 2)) || defined(__clang__)
+ #define DRMP3_INLINE DRMP3_GNUC_INLINE_HINT __attribute__((always_inline))
+ #else
+ #define DRMP3_INLINE DRMP3_GNUC_INLINE_HINT
+ #endif
+#elif defined(__WATCOMC__)
+ #define DRMP3_INLINE __inline
+#else
+ #define DRMP3_INLINE
+#endif
+/* End Inline */
+
+
+DRMP3_API void drmp3_version(drmp3_uint32* pMajor, drmp3_uint32* pMinor, drmp3_uint32* pRevision);
+DRMP3_API const char* drmp3_version_string(void);
+
+
+/* Allocation Callbacks */
+typedef struct
+{
+ void* pUserData;
+ void* (* onMalloc)(size_t sz, void* pUserData);
+ void* (* onRealloc)(void* p, size_t sz, void* pUserData);
+ void (* onFree)(void* p, void* pUserData);
+} drmp3_allocation_callbacks;
+/* End Allocation Callbacks */
+
+
+/*
+Low Level Push API
+==================
+*/
+typedef struct
+{
+ int frame_bytes, channels, hz, layer, bitrate_kbps;
+} drmp3dec_frame_info;
+
+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;
+
+/* Initializes a low level decoder. */
+DRMP3_API void drmp3dec_init(drmp3dec *dec);
+
+/* Reads a frame from a low level decoder. */
+DRMP3_API int drmp3dec_decode_frame(drmp3dec *dec, const drmp3_uint8 *mp3, int mp3_bytes, void *pcm, drmp3dec_frame_info *info);
+
+/* Helper for converting between f32 and s16. */
+DRMP3_API void drmp3dec_f32_to_s16(const float *in, drmp3_int16 *out, size_t num_samples);
+
+
+
+/*
+Main API (Pull API)
+===================
+*/
+typedef enum
+{
+ drmp3_seek_origin_start,
+ drmp3_seek_origin_current
+} drmp3_seek_origin;
+
+typedef struct
+{
+ drmp3_uint64 seekPosInBytes; /* Points to the first byte of an MP3 frame. */
+ drmp3_uint64 pcmFrameIndex; /* The index of the PCM frame this seek point targets. */
+ drmp3_uint16 mp3FramesToDiscard; /* The number of whole MP3 frames to be discarded before pcmFramesToDiscard. */
+ drmp3_uint16 pcmFramesToDiscard; /* The number of leading samples to read and discard. These are discarded after mp3FramesToDiscard. */
+} drmp3_seek_point;
+
+/*
+Callback for when data is read. Return value is the number of bytes actually read.
+
+pUserData [in] The user data that was passed to drmp3_init(), drmp3_open() and family.
+pBufferOut [out] The output buffer.
+bytesToRead [in] The number of bytes to read.
+
+Returns the number of bytes actually read.
+
+A return value of less than bytesToRead indicates the end of the stream. Do _not_ return from this callback until
+either the entire bytesToRead is filled or you have reached the end of the stream.
+*/
+typedef size_t (* drmp3_read_proc)(void* pUserData, void* pBufferOut, size_t bytesToRead);
+
+/*
+Callback for when data needs to be seeked.
+
+pUserData [in] The user data that was passed to drmp3_init(), drmp3_open() and family.
+offset [in] The number of bytes to move, relative to the origin. Will never be negative.
+origin [in] The origin of the seek - the current position or the start of the stream.
+
+Returns whether or not the seek was successful.
+
+Whether or not it is relative to the beginning or current position is determined by the "origin" parameter which
+will be either drmp3_seek_origin_start or drmp3_seek_origin_current.
+*/
+typedef drmp3_bool32 (* drmp3_seek_proc)(void* pUserData, int offset, drmp3_seek_origin origin);
+
+typedef struct
+{
+ drmp3_uint32 channels;
+ drmp3_uint32 sampleRate;
+} drmp3_config;
+
+typedef struct
+{
+ drmp3dec decoder;
+ drmp3_uint32 channels;
+ drmp3_uint32 sampleRate;
+ drmp3_read_proc onRead;
+ drmp3_seek_proc onSeek;
+ void* pUserData;
+ drmp3_allocation_callbacks allocationCallbacks;
+ drmp3_uint32 mp3FrameChannels; /* The number of channels in the currently loaded MP3 frame. Internal use only. */
+ drmp3_uint32 mp3FrameSampleRate; /* The sample rate of the currently loaded MP3 frame. Internal use only. */
+ drmp3_uint32 pcmFramesConsumedInMP3Frame;
+ drmp3_uint32 pcmFramesRemainingInMP3Frame;
+ drmp3_uint8 pcmFrames[sizeof(float)*DRMP3_MAX_SAMPLES_PER_FRAME]; /* <-- Multipled by sizeof(float) to ensure there's enough room for DR_MP3_FLOAT_OUTPUT. */
+ drmp3_uint64 currentPCMFrame; /* The current PCM frame, globally, based on the output sample rate. Mainly used for seeking. */
+ drmp3_uint64 streamCursor; /* The current byte the decoder is sitting on in the raw stream. */
+ drmp3_seek_point* pSeekPoints; /* NULL by default. Set with drmp3_bind_seek_table(). Memory is owned by the client. dr_mp3 will never attempt to free this pointer. */
+ drmp3_uint32 seekPointCount; /* The number of items in pSeekPoints. When set to 0 assumes to no seek table. Defaults to zero. */
+ size_t dataSize;
+ size_t dataCapacity;
+ size_t dataConsumed;
+ drmp3_uint8* pData;
+ drmp3_bool32 atEnd : 1;
+ struct
+ {
+ const drmp3_uint8* pData;
+ size_t dataSize;
+ size_t currentReadPos;
+ } memory; /* Only used for decoders that were opened against a block of memory. */
+} drmp3;
+
+/*
+Initializes an MP3 decoder.
+
+onRead [in] The function to call when data needs to be read from the client.
+onSeek [in] The function to call when the read position of the client data needs to move.
+pUserData [in, optional] A pointer to application defined data that will be passed to onRead and onSeek.
+
+Returns true if successful; false otherwise.
+
+Close the loader with drmp3_uninit().
+
+See also: drmp3_init_file(), drmp3_init_memory(), drmp3_uninit()
+*/
+DRMP3_API drmp3_bool32 drmp3_init(drmp3* pMP3, drmp3_read_proc onRead, drmp3_seek_proc onSeek, void* pUserData, const drmp3_allocation_callbacks* pAllocationCallbacks);
+
+/*
+Initializes an MP3 decoder from a block of memory.
+
+This does not create a copy of the data. It is up to the application to ensure the buffer remains valid for
+the lifetime of the drmp3 object.
+
+The buffer should contain the contents of the entire MP3 file.
+*/
+DRMP3_API drmp3_bool32 drmp3_init_memory(drmp3* pMP3, const void* pData, size_t dataSize, const drmp3_allocation_callbacks* pAllocationCallbacks);
+
+#ifndef DR_MP3_NO_STDIO
+/*
+Initializes an MP3 decoder from a file.
+
+This holds the internal FILE object until drmp3_uninit() is called. Keep this in mind if you're caching drmp3
+objects because the operating system may restrict the number of file handles an application can have open at
+any given time.
+*/
+DRMP3_API drmp3_bool32 drmp3_init_file(drmp3* pMP3, const char* pFilePath, const drmp3_allocation_callbacks* pAllocationCallbacks);
+DRMP3_API drmp3_bool32 drmp3_init_file_w(drmp3* pMP3, const wchar_t* pFilePath, const drmp3_allocation_callbacks* pAllocationCallbacks);
+#endif
+
+/*
+Uninitializes an MP3 decoder.
+*/
+DRMP3_API void drmp3_uninit(drmp3* pMP3);
+
+/*
+Reads PCM frames as interleaved 32-bit IEEE floating point PCM.
+
+Note that framesToRead specifies the number of PCM frames to read, _not_ the number of MP3 frames.
+*/
+DRMP3_API drmp3_uint64 drmp3_read_pcm_frames_f32(drmp3* pMP3, drmp3_uint64 framesToRead, float* pBufferOut);
+
+/*
+Reads PCM frames as interleaved signed 16-bit integer PCM.
+
+Note that framesToRead specifies the number of PCM frames to read, _not_ the number of MP3 frames.
+*/
+DRMP3_API drmp3_uint64 drmp3_read_pcm_frames_s16(drmp3* pMP3, drmp3_uint64 framesToRead, drmp3_int16* pBufferOut);
+
+/*
+Seeks to a specific frame.
+
+Note that this is _not_ an MP3 frame, but rather a PCM frame.
+*/
+DRMP3_API drmp3_bool32 drmp3_seek_to_pcm_frame(drmp3* pMP3, drmp3_uint64 frameIndex);
+
+/*
+Calculates the total number of PCM frames in the MP3 stream. Cannot be used for infinite streams such as internet
+radio. Runs in linear time. Returns 0 on error.
+*/
+DRMP3_API drmp3_uint64 drmp3_get_pcm_frame_count(drmp3* pMP3);
+
+/*
+Calculates the total number of MP3 frames in the MP3 stream. Cannot be used for infinite streams such as internet
+radio. Runs in linear time. Returns 0 on error.
+*/
+DRMP3_API drmp3_uint64 drmp3_get_mp3_frame_count(drmp3* pMP3);
+
+/*
+Calculates the total number of MP3 and PCM frames in the MP3 stream. Cannot be used for infinite streams such as internet
+radio. Runs in linear time. Returns 0 on error.
+
+This is equivalent to calling drmp3_get_mp3_frame_count() and drmp3_get_pcm_frame_count() except that it's more efficient.
+*/
+DRMP3_API drmp3_bool32 drmp3_get_mp3_and_pcm_frame_count(drmp3* pMP3, drmp3_uint64* pMP3FrameCount, drmp3_uint64* pPCMFrameCount);
+
+/*
+Calculates the seekpoints based on PCM frames. This is slow.
+
+pSeekpoint count is a pointer to a uint32 containing the seekpoint count. On input it contains the desired count.
+On output it contains the actual count. The reason for this design is that the client may request too many
+seekpoints, in which case dr_mp3 will return a corrected count.
+
+Note that seektable seeking is not quite sample exact when the MP3 stream contains inconsistent sample rates.
+*/
+DRMP3_API drmp3_bool32 drmp3_calculate_seek_points(drmp3* pMP3, drmp3_uint32* pSeekPointCount, drmp3_seek_point* pSeekPoints);
+
+/*
+Binds a seek table to the decoder.
+
+This does _not_ make a copy of pSeekPoints - it only references it. It is up to the application to ensure this
+remains valid while it is bound to the decoder.
+
+Use drmp3_calculate_seek_points() to calculate the seek points.
+*/
+DRMP3_API drmp3_bool32 drmp3_bind_seek_table(drmp3* pMP3, drmp3_uint32 seekPointCount, drmp3_seek_point* pSeekPoints);
+
+
+/*
+Opens an decodes an entire MP3 stream as a single operation.
+
+On output pConfig will receive the channel count and sample rate of the stream.
+
+Free the returned pointer with drmp3_free().
+*/
+DRMP3_API float* drmp3_open_and_read_pcm_frames_f32(drmp3_read_proc onRead, drmp3_seek_proc onSeek, void* pUserData, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount, const drmp3_allocation_callbacks* pAllocationCallbacks);
+DRMP3_API drmp3_int16* drmp3_open_and_read_pcm_frames_s16(drmp3_read_proc onRead, drmp3_seek_proc onSeek, void* pUserData, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount, const drmp3_allocation_callbacks* pAllocationCallbacks);
+
+DRMP3_API float* drmp3_open_memory_and_read_pcm_frames_f32(const void* pData, size_t dataSize, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount, const drmp3_allocation_callbacks* pAllocationCallbacks);
+DRMP3_API drmp3_int16* drmp3_open_memory_and_read_pcm_frames_s16(const void* pData, size_t dataSize, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount, const drmp3_allocation_callbacks* pAllocationCallbacks);
+
+#ifndef DR_MP3_NO_STDIO
+DRMP3_API float* drmp3_open_file_and_read_pcm_frames_f32(const char* filePath, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount, const drmp3_allocation_callbacks* pAllocationCallbacks);
+DRMP3_API drmp3_int16* drmp3_open_file_and_read_pcm_frames_s16(const char* filePath, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount, const drmp3_allocation_callbacks* pAllocationCallbacks);
+#endif
+
+/*
+Allocates a block of memory on the heap.
+*/
+DRMP3_API void* drmp3_malloc(size_t sz, const drmp3_allocation_callbacks* pAllocationCallbacks);
+
+/*
+Frees any memory that was allocated by a public drmp3 API.
+*/
+DRMP3_API void drmp3_free(void* p, const drmp3_allocation_callbacks* pAllocationCallbacks);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* dr_mp3_h */
+
+
+/************************************************************************************************************************************************************
+ ************************************************************************************************************************************************************
+
+ IMPLEMENTATION
+
+ ************************************************************************************************************************************************************
+ ************************************************************************************************************************************************************/
+#if defined(DR_MP3_IMPLEMENTATION) || defined(DRMP3_IMPLEMENTATION)
+#ifndef dr_mp3_c
+#define dr_mp3_c
+
+#include
+#include
+#include /* For INT_MAX */
+
+DRMP3_API void drmp3_version(drmp3_uint32* pMajor, drmp3_uint32* pMinor, drmp3_uint32* pRevision)
+{
+ if (pMajor) {
+ *pMajor = DRMP3_VERSION_MAJOR;
+ }
+
+ if (pMinor) {
+ *pMinor = DRMP3_VERSION_MINOR;
+ }
+
+ if (pRevision) {
+ *pRevision = DRMP3_VERSION_REVISION;
+ }
+}
+
+DRMP3_API const char* drmp3_version_string(void)
+{
+ return DRMP3_VERSION_STRING;
+}
+
+/* Disable SIMD when compiling with TCC for now. */
+#if defined(__TINYC__)
+#define DR_MP3_NO_SIMD
+#endif
+
+#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
+#define DRMP3_MODE_JOINT_STEREO 1
+#define DRMP3_HDR_SIZE 4
+#define DRMP3_HDR_IS_MONO(h) (((h[3]) & 0xC0) == 0xC0)
+#define DRMP3_HDR_IS_MS_STEREO(h) (((h[3]) & 0xE0) == 0x60)
+#define DRMP3_HDR_IS_FREE_FORMAT(h) (((h[2]) & 0xF0) == 0)
+#define DRMP3_HDR_IS_CRC(h) (!((h[1]) & 1))
+#define DRMP3_HDR_TEST_PADDING(h) ((h[2]) & 0x2)
+#define DRMP3_HDR_TEST_MPEG1(h) ((h[1]) & 0x8)
+#define DRMP3_HDR_TEST_NOT_MPEG25(h) ((h[1]) & 0x10)
+#define DRMP3_HDR_TEST_I_STEREO(h) ((h[3]) & 0x10)
+#define DRMP3_HDR_TEST_MS_STEREO(h) ((h[3]) & 0x20)
+#define DRMP3_HDR_GET_STEREO_MODE(h) (((h[3]) >> 6) & 3)
+#define DRMP3_HDR_GET_STEREO_MODE_EXT(h) (((h[3]) >> 4) & 3)
+#define DRMP3_HDR_GET_LAYER(h) (((h[1]) >> 1) & 3)
+#define DRMP3_HDR_GET_BITRATE(h) ((h[2]) >> 4)
+#define DRMP3_HDR_GET_SAMPLE_RATE(h) (((h[2]) >> 2) & 3)
+#define DRMP3_HDR_GET_MY_SAMPLE_RATE(h) (DRMP3_HDR_GET_SAMPLE_RATE(h) + (((h[1] >> 3) & 1) + ((h[1] >> 4) & 1))*3)
+#define DRMP3_HDR_IS_FRAME_576(h) ((h[1] & 14) == 2)
+#define DRMP3_HDR_IS_LAYER_1(h) ((h[1] & 6) == 6)
+
+#define DRMP3_BITS_DEQUANTIZER_OUT -1
+#define DRMP3_MAX_SCF (255 + DRMP3_BITS_DEQUANTIZER_OUT*4 - 210)
+#define DRMP3_MAX_SCFI ((DRMP3_MAX_SCF + 3) & ~3)
+
+#define DRMP3_MIN(a, b) ((a) > (b) ? (b) : (a))
+#define DRMP3_MAX(a, b) ((a) < (b) ? (b) : (a))
+
+#if !defined(DR_MP3_NO_SIMD)
+
+#if !defined(DR_MP3_ONLY_SIMD) && (defined(_M_X64) || defined(__x86_64__) || defined(__aarch64__) || defined(_M_ARM64))
+/* x64 always have SSE2, arm64 always have neon, no need for generic code */
+#define DR_MP3_ONLY_SIMD
+#endif
+
+#if ((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__)))
+#if defined(_MSC_VER)
+#include
+#endif
+#include
+#define DRMP3_HAVE_SSE 1
+#define DRMP3_HAVE_SIMD 1
+#define DRMP3_VSTORE _mm_storeu_ps
+#define DRMP3_VLD _mm_loadu_ps
+#define DRMP3_VSET _mm_set1_ps
+#define DRMP3_VADD _mm_add_ps
+#define DRMP3_VSUB _mm_sub_ps
+#define DRMP3_VMUL _mm_mul_ps
+#define DRMP3_VMAC(a, x, y) _mm_add_ps(a, _mm_mul_ps(x, y))
+#define DRMP3_VMSB(a, x, y) _mm_sub_ps(a, _mm_mul_ps(x, y))
+#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)
+#define drmp3_cpuid __cpuid
+#else
+static __inline__ __attribute__((always_inline)) void drmp3_cpuid(int CPUInfo[], const int InfoType)
+{
+#if defined(__PIC__)
+ __asm__ __volatile__(
+#if defined(__x86_64__)
+ "push %%rbx\n"
+ "cpuid\n"
+ "xchgl %%ebx, %1\n"
+ "pop %%rbx\n"
+#else
+ "xchgl %%ebx, %1\n"
+ "cpuid\n"
+ "xchgl %%ebx, %1\n"
+#endif
+ : "=a" (CPUInfo[0]), "=r" (CPUInfo[1]), "=c" (CPUInfo[2]), "=d" (CPUInfo[3])
+ : "a" (InfoType));
+#else
+ __asm__ __volatile__(
+ "cpuid"
+ : "=a" (CPUInfo[0]), "=b" (CPUInfo[1]), "=c" (CPUInfo[2]), "=d" (CPUInfo[3])
+ : "a" (InfoType));
+#endif
+}
+#endif
+static int drmp3_have_simd(void)
+{
+#ifdef DR_MP3_ONLY_SIMD
+ return 1;
+#else
+ static int g_have_simd;
+ int CPUInfo[4];
+#ifdef MINIMP3_TEST
+ static int g_counter;
+ if (g_counter++ > 100)
+ return 0;
+#endif
+ if (g_have_simd)
+ goto end;
+ drmp3_cpuid(CPUInfo, 0);
+ if (CPUInfo[0] > 0)
+ {
+ drmp3_cpuid(CPUInfo, 1);
+ g_have_simd = (CPUInfo[3] & (1 << 26)) + 1; /* SSE2 */
+ return g_have_simd - 1;
+ }
+
+end:
+ return g_have_simd - 1;
+#endif
+}
+#elif defined(__ARM_NEON) || defined(__aarch64__) || defined(_M_ARM64)
+#include
+#define DRMP3_HAVE_SSE 0
+#define DRMP3_HAVE_SIMD 1
+#define DRMP3_VSTORE vst1q_f32
+#define DRMP3_VLD vld1q_f32
+#define DRMP3_VSET vmovq_n_f32
+#define DRMP3_VADD vaddq_f32
+#define DRMP3_VSUB vsubq_f32
+#define DRMP3_VMUL vmulq_f32
+#define DRMP3_VMAC(a, x, y) vmlaq_f32(a, x, y)
+#define DRMP3_VMSB(a, x, y) vmlsq_f32(a, x, y)
+#define DRMP3_VMUL_S(x, s) vmulq_f32(x, vmovq_n_f32(s))
+#define DRMP3_VREV(x) vcombine_f32(vget_high_f32(vrev64q_f32(x)), vget_low_f32(vrev64q_f32(x)))
+typedef float32x4_t drmp3_f4;
+static int drmp3_have_simd(void)
+{ /* TODO: detect neon for !DR_MP3_ONLY_SIMD */
+ return 1;
+}
+#else
+#define DRMP3_HAVE_SSE 0
+#define DRMP3_HAVE_SIMD 0
+#ifdef DR_MP3_ONLY_SIMD
+#error DR_MP3_ONLY_SIMD used, but SSE/NEON not enabled
+#endif
+#endif
+
+#else
+
+#define DRMP3_HAVE_SIMD 0
+
+#endif
+
+#if defined(__ARM_ARCH) && (__ARM_ARCH >= 6) && !defined(__aarch64__) && !defined(_M_ARM64) && !defined(__ARM_ARCH_6M__)
+#define DRMP3_HAVE_ARMV6 1
+static __inline__ __attribute__((always_inline)) drmp3_int32 drmp3_clip_int16_arm(drmp3_int32 a)
+{
+ drmp3_int32 x = 0;
+ __asm__ ("ssat %0, #16, %1" : "=r"(x) : "r"(a));
+ return x;
+}
+#else
+#define DRMP3_HAVE_ARMV6 0
+#endif
+
+
+/* Standard library stuff. */
+#ifndef DRMP3_ASSERT
+#include
+#define DRMP3_ASSERT(expression) assert(expression)
+#endif
+#ifndef DRMP3_COPY_MEMORY
+#define DRMP3_COPY_MEMORY(dst, src, sz) memcpy((dst), (src), (sz))
+#endif
+#ifndef DRMP3_MOVE_MEMORY
+#define DRMP3_MOVE_MEMORY(dst, src, sz) memmove((dst), (src), (sz))
+#endif
+#ifndef DRMP3_ZERO_MEMORY
+#define DRMP3_ZERO_MEMORY(p, sz) memset((p), 0, (sz))
+#endif
+#define DRMP3_ZERO_OBJECT(p) DRMP3_ZERO_MEMORY((p), sizeof(*(p)))
+#ifndef DRMP3_MALLOC
+#define DRMP3_MALLOC(sz) malloc((sz))
+#endif
+#ifndef DRMP3_REALLOC
+#define DRMP3_REALLOC(p, sz) realloc((p), (sz))
+#endif
+#ifndef DRMP3_FREE
+#define DRMP3_FREE(p) free((p))
+#endif
+
+typedef struct
+{
+ const drmp3_uint8 *buf;
+ int pos, limit;
+} drmp3_bs;
+
+typedef struct
+{
+ float scf[3*64];
+ drmp3_uint8 total_bands, stereo_bands, bitalloc[64], scfcod[64];
+} drmp3_L12_scale_info;
+
+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;
+ bs->pos = 0;
+ bs->limit = bytes*8;
+}
+
+static drmp3_uint32 drmp3_bs_get_bits(drmp3_bs *bs, int n)
+{
+ drmp3_uint32 next, cache = 0, s = bs->pos & 7;
+ int shl = n + s;
+ const drmp3_uint8 *p = bs->buf + (bs->pos >> 3);
+ if ((bs->pos += n) > bs->limit)
+ return 0;
+ next = *p++ & (255 >> s);
+ while ((shl -= 8) > 0)
+ {
+ cache |= next << shl;
+ next = *p++;
+ }
+ return cache | (next >> -shl);
+}
+
+static int drmp3_hdr_valid(const drmp3_uint8 *h)
+{
+ return h[0] == 0xff &&
+ ((h[1] & 0xF0) == 0xf0 || (h[1] & 0xFE) == 0xe2) &&
+ (DRMP3_HDR_GET_LAYER(h) != 0) &&
+ (DRMP3_HDR_GET_BITRATE(h) != 15) &&
+ (DRMP3_HDR_GET_SAMPLE_RATE(h) != 3);
+}
+
+static int drmp3_hdr_compare(const drmp3_uint8 *h1, const drmp3_uint8 *h2)
+{
+ return drmp3_hdr_valid(h2) &&
+ ((h1[1] ^ h2[1]) & 0xFE) == 0 &&
+ ((h1[2] ^ h2[2]) & 0x0C) == 0 &&
+ !(DRMP3_HDR_IS_FREE_FORMAT(h1) ^ DRMP3_HDR_IS_FREE_FORMAT(h2));
+}
+
+static unsigned drmp3_hdr_bitrate_kbps(const drmp3_uint8 *h)
+{
+ static const drmp3_uint8 halfrate[2][3][15] = {
+ { { 0,4,8,12,16,20,24,28,32,40,48,56,64,72,80 }, { 0,4,8,12,16,20,24,28,32,40,48,56,64,72,80 }, { 0,16,24,28,32,40,48,56,64,72,80,88,96,112,128 } },
+ { { 0,16,20,24,28,32,40,48,56,64,80,96,112,128,160 }, { 0,16,24,28,32,40,48,56,64,80,96,112,128,160,192 }, { 0,16,32,48,64,80,96,112,128,144,160,176,192,208,224 } },
+ };
+ return 2*halfrate[!!DRMP3_HDR_TEST_MPEG1(h)][DRMP3_HDR_GET_LAYER(h) - 1][DRMP3_HDR_GET_BITRATE(h)];
+}
+
+static unsigned drmp3_hdr_sample_rate_hz(const drmp3_uint8 *h)
+{
+ static const unsigned g_hz[3] = { 44100, 48000, 32000 };
+ return g_hz[DRMP3_HDR_GET_SAMPLE_RATE(h)] >> (int)!DRMP3_HDR_TEST_MPEG1(h) >> (int)!DRMP3_HDR_TEST_NOT_MPEG25(h);
+}
+
+static unsigned drmp3_hdr_frame_samples(const drmp3_uint8 *h)
+{
+ return DRMP3_HDR_IS_LAYER_1(h) ? 384 : (1152 >> (int)DRMP3_HDR_IS_FRAME_576(h));
+}
+
+static int drmp3_hdr_frame_bytes(const drmp3_uint8 *h, int free_format_size)
+{
+ int frame_bytes = drmp3_hdr_frame_samples(h)*drmp3_hdr_bitrate_kbps(h)*125/drmp3_hdr_sample_rate_hz(h);
+ if (DRMP3_HDR_IS_LAYER_1(h))
+ {
+ frame_bytes &= ~3; /* slot align */
+ }
+ return frame_bytes ? frame_bytes : free_format_size;
+}
+
+static int drmp3_hdr_padding(const drmp3_uint8 *h)
+{
+ return DRMP3_HDR_TEST_PADDING(h) ? (DRMP3_HDR_IS_LAYER_1(h) ? 4 : 1) : 0;
+}
+
+#ifndef DR_MP3_ONLY_MP3
+static const drmp3_L12_subband_alloc *drmp3_L12_subband_alloc_table(const drmp3_uint8 *hdr, drmp3_L12_scale_info *sci)
+{
+ const drmp3_L12_subband_alloc *alloc;
+ int mode = DRMP3_HDR_GET_STEREO_MODE(hdr);
+ int nbands, stereo_bands = (mode == DRMP3_MODE_MONO) ? 0 : (mode == DRMP3_MODE_JOINT_STEREO) ? (DRMP3_HDR_GET_STEREO_MODE_EXT(hdr) << 2) + 4 : 32;
+
+ if (DRMP3_HDR_IS_LAYER_1(hdr))
+ {
+ static const drmp3_L12_subband_alloc g_alloc_L1[] = { { 76, 4, 32 } };
+ alloc = g_alloc_L1;
+ nbands = 32;
+ } else if (!DRMP3_HDR_TEST_MPEG1(hdr))
+ {
+ static const drmp3_L12_subband_alloc g_alloc_L2M2[] = { { 60, 4, 4 }, { 44, 3, 7 }, { 44, 2, 19 } };
+ alloc = g_alloc_L2M2;
+ nbands = 30;
+ } else
+ {
+ static const drmp3_L12_subband_alloc g_alloc_L2M1[] = { { 0, 4, 3 }, { 16, 4, 8 }, { 32, 3, 12 }, { 40, 2, 7 } };
+ int sample_rate_idx = DRMP3_HDR_GET_SAMPLE_RATE(hdr);
+ unsigned kbps = drmp3_hdr_bitrate_kbps(hdr) >> (int)(mode != DRMP3_MODE_MONO);
+ if (!kbps) /* free-format */
+ {
+ kbps = 192;
+ }
+
+ alloc = g_alloc_L2M1;
+ nbands = 27;
+ if (kbps < 56)
+ {
+ static const drmp3_L12_subband_alloc g_alloc_L2M1_lowrate[] = { { 44, 4, 2 }, { 44, 3, 10 } };
+ alloc = g_alloc_L2M1_lowrate;
+ nbands = sample_rate_idx == 2 ? 12 : 8;
+ } else if (kbps >= 96 && sample_rate_idx != 1)
+ {
+ nbands = 30;
+ }
+ }
+
+ sci->total_bands = (drmp3_uint8)nbands;
+ sci->stereo_bands = (drmp3_uint8)DRMP3_MIN(stereo_bands, nbands);
+
+ return alloc;
+}
+
+static void drmp3_L12_read_scalefactors(drmp3_bs *bs, drmp3_uint8 *pba, drmp3_uint8 *scfcod, int bands, float *scf)
+{
+ static const float g_deq_L12[18*3] = {
+#define DRMP3_DQ(x) 9.53674316e-07f/x, 7.56931807e-07f/x, 6.00777173e-07f/x
+ DRMP3_DQ(3),DRMP3_DQ(7),DRMP3_DQ(15),DRMP3_DQ(31),DRMP3_DQ(63),DRMP3_DQ(127),DRMP3_DQ(255),DRMP3_DQ(511),DRMP3_DQ(1023),DRMP3_DQ(2047),DRMP3_DQ(4095),DRMP3_DQ(8191),DRMP3_DQ(16383),DRMP3_DQ(32767),DRMP3_DQ(65535),DRMP3_DQ(3),DRMP3_DQ(5),DRMP3_DQ(9)
+ };
+ int i, m;
+ for (i = 0; i < bands; i++)
+ {
+ float s = 0;
+ int ba = *pba++;
+ int mask = ba ? 4 + ((19 >> scfcod[i]) & 3) : 0;
+ for (m = 4; m; m >>= 1)
+ {
+ if (mask & m)
+ {
+ int b = drmp3_bs_get_bits(bs, 6);
+ s = g_deq_L12[ba*3 - 6 + b % 3]*(int)(1 << 21 >> b/3);
+ }
+ *scf++ = s;
+ }
+ }
+}
+
+static void drmp3_L12_read_scale_info(const drmp3_uint8 *hdr, drmp3_bs *bs, drmp3_L12_scale_info *sci)
+{
+ static const drmp3_uint8 g_bitalloc_code_tab[] = {
+ 0,17, 3, 4, 5,6,7, 8,9,10,11,12,13,14,15,16,
+ 0,17,18, 3,19,4,5, 6,7, 8, 9,10,11,12,13,16,
+ 0,17,18, 3,19,4,5,16,
+ 0,17,18,16,
+ 0,17,18,19, 4,5,6, 7,8, 9,10,11,12,13,14,15,
+ 0,17,18, 3,19,4,5, 6,7, 8, 9,10,11,12,13,14,
+ 0, 2, 3, 4, 5,6,7, 8,9,10,11,12,13,14,15,16
+ };
+ const drmp3_L12_subband_alloc *subband_alloc = drmp3_L12_subband_alloc_table(hdr, sci);
+
+ int i, k = 0, ba_bits = 0;
+ const drmp3_uint8 *ba_code_tab = g_bitalloc_code_tab;
+
+ for (i = 0; i < sci->total_bands; i++)
+ {
+ drmp3_uint8 ba;
+ if (i == k)
+ {
+ k += subband_alloc->band_count;
+ ba_bits = subband_alloc->code_tab_width;
+ ba_code_tab = g_bitalloc_code_tab + subband_alloc->tab_offset;
+ subband_alloc++;
+ }
+ ba = ba_code_tab[drmp3_bs_get_bits(bs, ba_bits)];
+ sci->bitalloc[2*i] = ba;
+ if (i < sci->stereo_bands)
+ {
+ ba = ba_code_tab[drmp3_bs_get_bits(bs, ba_bits)];
+ }
+ sci->bitalloc[2*i + 1] = sci->stereo_bands ? ba : 0;
+ }
+
+ for (i = 0; i < 2*sci->total_bands; i++)
+ {
+ sci->scfcod[i] = (drmp3_uint8)(sci->bitalloc[i] ? DRMP3_HDR_IS_LAYER_1(hdr) ? 2 : drmp3_bs_get_bits(bs, 2) : 6);
+ }
+
+ drmp3_L12_read_scalefactors(bs, sci->bitalloc, sci->scfcod, sci->total_bands*2, sci->scf);
+
+ for (i = sci->stereo_bands; i < sci->total_bands; i++)
+ {
+ sci->bitalloc[2*i + 1] = 0;
+ }
+}
+
+static int drmp3_L12_dequantize_granule(float *grbuf, drmp3_bs *bs, drmp3_L12_scale_info *sci, int group_size)
+{
+ int i, j, k, choff = 576;
+ for (j = 0; j < 4; j++)
+ {
+ float *dst = grbuf + group_size*j;
+ for (i = 0; i < 2*sci->total_bands; i++)
+ {
+ int ba = sci->bitalloc[i];
+ if (ba != 0)
+ {
+ if (ba < 17)
+ {
+ int half = (1 << (ba - 1)) - 1;
+ for (k = 0; k < group_size; k++)
+ {
+ dst[k] = (float)((int)drmp3_bs_get_bits(bs, ba) - half);
+ }
+ } else
+ {
+ unsigned mod = (2 << (ba - 17)) + 1; /* 3, 5, 9 */
+ unsigned code = drmp3_bs_get_bits(bs, mod + 2 - (mod >> 3)); /* 5, 7, 10 */
+ for (k = 0; k < group_size; k++, code /= mod)
+ {
+ dst[k] = (float)((int)(code % mod - mod/2));
+ }
+ }
+ }
+ dst += choff;
+ choff = 18 - choff;
+ }
+ }
+ return group_size*4;
+}
+
+static void drmp3_L12_apply_scf_384(drmp3_L12_scale_info *sci, const float *scf, float *dst)
+{
+ int i, k;
+ DRMP3_COPY_MEMORY(dst + 576 + sci->stereo_bands*18, dst + sci->stereo_bands*18, (sci->total_bands - sci->stereo_bands)*18*sizeof(float));
+ for (i = 0; i < sci->total_bands; i++, dst += 18, scf += 6)
+ {
+ for (k = 0; k < 12; k++)
+ {
+ dst[k + 0] *= scf[0];
+ dst[k + 576] *= scf[3];
+ }
+ }
+}
+#endif
+
+static int drmp3_L3_read_side_info(drmp3_bs *bs, drmp3_L3_gr_info *gr, const drmp3_uint8 *hdr)
+{
+ static const drmp3_uint8 g_scf_long[8][23] = {
+ { 6,6,6,6,6,6,8,10,12,14,16,20,24,28,32,38,46,52,60,68,58,54,0 },
+ { 12,12,12,12,12,12,16,20,24,28,32,40,48,56,64,76,90,2,2,2,2,2,0 },
+ { 6,6,6,6,6,6,8,10,12,14,16,20,24,28,32,38,46,52,60,68,58,54,0 },
+ { 6,6,6,6,6,6,8,10,12,14,16,18,22,26,32,38,46,54,62,70,76,36,0 },
+ { 6,6,6,6,6,6,8,10,12,14,16,20,24,28,32,38,46,52,60,68,58,54,0 },
+ { 4,4,4,4,4,4,6,6,8,8,10,12,16,20,24,28,34,42,50,54,76,158,0 },
+ { 4,4,4,4,4,4,6,6,6,8,10,12,16,18,22,28,34,40,46,54,54,192,0 },
+ { 4,4,4,4,4,4,6,6,8,10,12,16,20,24,30,38,46,56,68,84,102,26,0 }
+ };
+ static const drmp3_uint8 g_scf_short[8][40] = {
+ { 4,4,4,4,4,4,4,4,4,6,6,6,8,8,8,10,10,10,12,12,12,14,14,14,18,18,18,24,24,24,30,30,30,40,40,40,18,18,18,0 },
+ { 8,8,8,8,8,8,8,8,8,12,12,12,16,16,16,20,20,20,24,24,24,28,28,28,36,36,36,2,2,2,2,2,2,2,2,2,26,26,26,0 },
+ { 4,4,4,4,4,4,4,4,4,6,6,6,6,6,6,8,8,8,10,10,10,14,14,14,18,18,18,26,26,26,32,32,32,42,42,42,18,18,18,0 },
+ { 4,4,4,4,4,4,4,4,4,6,6,6,8,8,8,10,10,10,12,12,12,14,14,14,18,18,18,24,24,24,32,32,32,44,44,44,12,12,12,0 },
+ { 4,4,4,4,4,4,4,4,4,6,6,6,8,8,8,10,10,10,12,12,12,14,14,14,18,18,18,24,24,24,30,30,30,40,40,40,18,18,18,0 },
+ { 4,4,4,4,4,4,4,4,4,4,4,4,6,6,6,8,8,8,10,10,10,12,12,12,14,14,14,18,18,18,22,22,22,30,30,30,56,56,56,0 },
+ { 4,4,4,4,4,4,4,4,4,4,4,4,6,6,6,6,6,6,10,10,10,12,12,12,14,14,14,16,16,16,20,20,20,26,26,26,66,66,66,0 },
+ { 4,4,4,4,4,4,4,4,4,4,4,4,6,6,6,8,8,8,12,12,12,16,16,16,20,20,20,26,26,26,34,34,34,42,42,42,12,12,12,0 }
+ };
+ static const drmp3_uint8 g_scf_mixed[8][40] = {
+ { 6,6,6,6,6,6,6,6,6,8,8,8,10,10,10,12,12,12,14,14,14,18,18,18,24,24,24,30,30,30,40,40,40,18,18,18,0 },
+ { 12,12,12,4,4,4,8,8,8,12,12,12,16,16,16,20,20,20,24,24,24,28,28,28,36,36,36,2,2,2,2,2,2,2,2,2,26,26,26,0 },
+ { 6,6,6,6,6,6,6,6,6,6,6,6,8,8,8,10,10,10,14,14,14,18,18,18,26,26,26,32,32,32,42,42,42,18,18,18,0 },
+ { 6,6,6,6,6,6,6,6,6,8,8,8,10,10,10,12,12,12,14,14,14,18,18,18,24,24,24,32,32,32,44,44,44,12,12,12,0 },
+ { 6,6,6,6,6,6,6,6,6,8,8,8,10,10,10,12,12,12,14,14,14,18,18,18,24,24,24,30,30,30,40,40,40,18,18,18,0 },
+ { 4,4,4,4,4,4,6,6,4,4,4,6,6,6,8,8,8,10,10,10,12,12,12,14,14,14,18,18,18,22,22,22,30,30,30,56,56,56,0 },
+ { 4,4,4,4,4,4,6,6,4,4,4,6,6,6,6,6,6,10,10,10,12,12,12,14,14,14,16,16,16,20,20,20,26,26,26,66,66,66,0 },
+ { 4,4,4,4,4,4,6,6,4,4,4,6,6,6,8,8,8,12,12,12,16,16,16,20,20,20,26,26,26,34,34,34,42,42,42,12,12,12,0 }
+ };
+
+ unsigned tables, scfsi = 0;
+ int main_data_begin, part_23_sum = 0;
+ int gr_count = DRMP3_HDR_IS_MONO(hdr) ? 1 : 2;
+ int sr_idx = DRMP3_HDR_GET_MY_SAMPLE_RATE(hdr); sr_idx -= (sr_idx != 0);
+
+ if (DRMP3_HDR_TEST_MPEG1(hdr))
+ {
+ gr_count *= 2;
+ main_data_begin = drmp3_bs_get_bits(bs, 9);
+ scfsi = drmp3_bs_get_bits(bs, 7 + gr_count);
+ } else
+ {
+ main_data_begin = drmp3_bs_get_bits(bs, 8 + gr_count) >> gr_count;
+ }
+
+ do
+ {
+ if (DRMP3_HDR_IS_MONO(hdr))
+ {
+ scfsi <<= 4;
+ }
+ gr->part_23_length = (drmp3_uint16)drmp3_bs_get_bits(bs, 12);
+ part_23_sum += gr->part_23_length;
+ gr->big_values = (drmp3_uint16)drmp3_bs_get_bits(bs, 9);
+ if (gr->big_values > 288)
+ {
+ return -1;
+ }
+ gr->global_gain = (drmp3_uint8)drmp3_bs_get_bits(bs, 8);
+ gr->scalefac_compress = (drmp3_uint16)drmp3_bs_get_bits(bs, DRMP3_HDR_TEST_MPEG1(hdr) ? 4 : 9);
+ gr->sfbtab = g_scf_long[sr_idx];
+ gr->n_long_sfb = 22;
+ gr->n_short_sfb = 0;
+ if (drmp3_bs_get_bits(bs, 1))
+ {
+ gr->block_type = (drmp3_uint8)drmp3_bs_get_bits(bs, 2);
+ if (!gr->block_type)
+ {
+ return -1;
+ }
+ gr->mixed_block_flag = (drmp3_uint8)drmp3_bs_get_bits(bs, 1);
+ gr->region_count[0] = 7;
+ gr->region_count[1] = 255;
+ if (gr->block_type == DRMP3_SHORT_BLOCK_TYPE)
+ {
+ scfsi &= 0x0F0F;
+ if (!gr->mixed_block_flag)
+ {
+ gr->region_count[0] = 8;
+ gr->sfbtab = g_scf_short[sr_idx];
+ gr->n_long_sfb = 0;
+ gr->n_short_sfb = 39;
+ } else
+ {
+ gr->sfbtab = g_scf_mixed[sr_idx];
+ gr->n_long_sfb = DRMP3_HDR_TEST_MPEG1(hdr) ? 8 : 6;
+ gr->n_short_sfb = 30;
+ }
+ }
+ tables = drmp3_bs_get_bits(bs, 10);
+ tables <<= 5;
+ gr->subblock_gain[0] = (drmp3_uint8)drmp3_bs_get_bits(bs, 3);
+ gr->subblock_gain[1] = (drmp3_uint8)drmp3_bs_get_bits(bs, 3);
+ gr->subblock_gain[2] = (drmp3_uint8)drmp3_bs_get_bits(bs, 3);
+ } else
+ {
+ gr->block_type = 0;
+ gr->mixed_block_flag = 0;
+ tables = drmp3_bs_get_bits(bs, 15);
+ gr->region_count[0] = (drmp3_uint8)drmp3_bs_get_bits(bs, 4);
+ gr->region_count[1] = (drmp3_uint8)drmp3_bs_get_bits(bs, 3);
+ gr->region_count[2] = 255;
+ }
+ gr->table_select[0] = (drmp3_uint8)(tables >> 10);
+ gr->table_select[1] = (drmp3_uint8)((tables >> 5) & 31);
+ gr->table_select[2] = (drmp3_uint8)((tables) & 31);
+ gr->preflag = (drmp3_uint8)(DRMP3_HDR_TEST_MPEG1(hdr) ? drmp3_bs_get_bits(bs, 1) : (gr->scalefac_compress >= 500));
+ gr->scalefac_scale = (drmp3_uint8)drmp3_bs_get_bits(bs, 1);
+ gr->count1_table = (drmp3_uint8)drmp3_bs_get_bits(bs, 1);
+ gr->scfsi = (drmp3_uint8)((scfsi >> 12) & 15);
+ scfsi <<= 4;
+ gr++;
+ } while(--gr_count);
+
+ if (part_23_sum + bs->pos > bs->limit + main_data_begin*8)
+ {
+ return -1;
+ }
+
+ return main_data_begin;
+}
+
+static void drmp3_L3_read_scalefactors(drmp3_uint8 *scf, drmp3_uint8 *ist_pos, const drmp3_uint8 *scf_size, const drmp3_uint8 *scf_count, drmp3_bs *bitbuf, int scfsi)
+{
+ int i, k;
+ for (i = 0; i < 4 && scf_count[i]; i++, scfsi *= 2)
+ {
+ int cnt = scf_count[i];
+ if (scfsi & 8)
+ {
+ DRMP3_COPY_MEMORY(scf, ist_pos, cnt);
+ } else
+ {
+ int bits = scf_size[i];
+ if (!bits)
+ {
+ DRMP3_ZERO_MEMORY(scf, cnt);
+ DRMP3_ZERO_MEMORY(ist_pos, cnt);
+ } else
+ {
+ int max_scf = (scfsi < 0) ? (1 << bits) - 1 : -1;
+ for (k = 0; k < cnt; k++)
+ {
+ int s = drmp3_bs_get_bits(bitbuf, bits);
+ ist_pos[k] = (drmp3_uint8)(s == max_scf ? -1 : s);
+ scf[k] = (drmp3_uint8)s;
+ }
+ }
+ }
+ ist_pos += cnt;
+ scf += cnt;
+ }
+ scf[0] = scf[1] = scf[2] = 0;
+}
+
+static float drmp3_L3_ldexp_q2(float y, int exp_q2)
+{
+ static const float g_expfrac[4] = { 9.31322575e-10f,7.83145814e-10f,6.58544508e-10f,5.53767716e-10f };
+ int e;
+ do
+ {
+ e = DRMP3_MIN(30*4, exp_q2);
+ y *= g_expfrac[e & 3]*(1 << 30 >> (e >> 2));
+ } while ((exp_q2 -= e) > 0);
+ return y;
+}
+
+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] = {
+ { 6,5,5, 5,6,5,5,5,6,5, 7,3,11,10,0,0, 7, 7, 7,0, 6, 6,6,3, 8, 8,5,0 },
+ { 8,9,6,12,6,9,9,9,6,9,12,6,15,18,0,0, 6,15,12,0, 6,12,9,6, 6,18,9,0 },
+ { 9,9,6,12,9,9,9,9,9,9,12,6,18,18,0,0,12,12,12,0,12, 9,9,6,15,12,9,0 }
+ };
+ const drmp3_uint8 *scf_partition = g_scf_partitions[!!gr->n_short_sfb + !gr->n_long_sfb];
+ drmp3_uint8 scf_size[4], iscf[40];
+ int i, scf_shift = gr->scalefac_scale + 1, gain_exp, scfsi = gr->scfsi;
+ float gain;
+
+ if (DRMP3_HDR_TEST_MPEG1(hdr))
+ {
+ static const drmp3_uint8 g_scfc_decode[16] = { 0,1,2,3, 12,5,6,7, 9,10,11,13, 14,15,18,19 };
+ int part = g_scfc_decode[gr->scalefac_compress];
+ scf_size[1] = scf_size[0] = (drmp3_uint8)(part >> 2);
+ scf_size[3] = scf_size[2] = (drmp3_uint8)(part & 3);
+ } else
+ {
+ static const drmp3_uint8 g_mod[6*4] = { 5,5,4,4,5,5,4,1,4,3,1,1,5,6,6,1,4,4,4,1,4,3,1,1 };
+ int k, modprod, sfc, ist = DRMP3_HDR_TEST_I_STEREO(hdr) && ch;
+ sfc = gr->scalefac_compress >> ist;
+ for (k = ist*3*4; sfc >= 0; sfc -= modprod, k += 4)
+ {
+ for (modprod = 1, i = 3; i >= 0; i--)
+ {
+ scf_size[i] = (drmp3_uint8)(sfc / modprod % g_mod[k + i]);
+ modprod *= g_mod[k + i];
+ }
+ }
+ scf_partition += k;
+ scfsi = -16;
+ }
+ drmp3_L3_read_scalefactors(iscf, ist_pos, scf_size, scf_partition, bs, scfsi);
+
+ if (gr->n_short_sfb)
+ {
+ int sh = 3 - scf_shift;
+ for (i = 0; i < gr->n_short_sfb; i += 3)
+ {
+ iscf[gr->n_long_sfb + i + 0] = (drmp3_uint8)(iscf[gr->n_long_sfb + i + 0] + (gr->subblock_gain[0] << sh));
+ iscf[gr->n_long_sfb + i + 1] = (drmp3_uint8)(iscf[gr->n_long_sfb + i + 1] + (gr->subblock_gain[1] << sh));
+ iscf[gr->n_long_sfb + i + 2] = (drmp3_uint8)(iscf[gr->n_long_sfb + i + 2] + (gr->subblock_gain[2] << sh));
+ }
+ } else if (gr->preflag)
+ {
+ static const drmp3_uint8 g_preamp[10] = { 1,1,1,1,2,2,3,3,3,2 };
+ for (i = 0; i < 10; i++)
+ {
+ iscf[11 + i] = (drmp3_uint8)(iscf[11 + i] + g_preamp[i]);
+ }
+ }
+
+ gain_exp = gr->global_gain + DRMP3_BITS_DEQUANTIZER_OUT*4 - 210 - (DRMP3_HDR_IS_MS_STEREO(hdr) ? 2 : 0);
+ gain = drmp3_L3_ldexp_q2(1 << (DRMP3_MAX_SCFI/4), DRMP3_MAX_SCFI - gain_exp);
+ for (i = 0; i < (int)(gr->n_long_sfb + gr->n_short_sfb); i++)
+ {
+ scf[i] = drmp3_L3_ldexp_q2(gain, iscf[i] << scf_shift);
+ }
+}
+
+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,
+ 0,1,2.519842f,4.326749f,6.349604f,8.549880f,10.902724f,13.390518f,16.000000f,18.720754f,21.544347f,24.463781f,27.473142f,30.567351f,33.741992f,36.993181f,40.317474f,43.711787f,47.173345f,50.699631f,54.288352f,57.937408f,61.644865f,65.408941f,69.227979f,73.100443f,77.024898f,81.000000f,85.024491f,89.097188f,93.216975f,97.382800f,101.593667f,105.848633f,110.146801f,114.487321f,118.869381f,123.292209f,127.755065f,132.257246f,136.798076f,141.376907f,145.993119f,150.646117f,155.335327f,160.060199f,164.820202f,169.614826f,174.443577f,179.305980f,184.201575f,189.129918f,194.090580f,199.083145f,204.107210f,209.162385f,214.248292f,219.364564f,224.510845f,229.686789f,234.892058f,240.126328f,245.389280f,250.680604f,256.000000f,261.347174f,266.721841f,272.123723f,277.552547f,283.008049f,288.489971f,293.998060f,299.532071f,305.091761f,310.676898f,316.287249f,321.922592f,327.582707f,333.267377f,338.976394f,344.709550f,350.466646f,356.247482f,362.051866f,367.879608f,373.730522f,379.604427f,385.501143f,391.420496f,397.362314f,403.326427f,409.312672f,415.320884f,421.350905f,427.402579f,433.475750f,439.570269f,445.685987f,451.822757f,457.980436f,464.158883f,470.357960f,476.577530f,482.817459f,489.077615f,495.357868f,501.658090f,507.978156f,514.317941f,520.677324f,527.056184f,533.454404f,539.871867f,546.308458f,552.764065f,559.238575f,565.731879f,572.243870f,578.774440f,585.323483f,591.890898f,598.476581f,605.080431f,611.702349f,618.342238f,625.000000f,631.675540f,638.368763f,645.079578f
+};
+
+static float drmp3_L3_pow_43(int x)
+{
+ float frac;
+ int sign, mult = 256;
+
+ if (x < 129)
+ {
+ return g_drmp3_pow43[16 + x];
+ }
+
+ if (x < 1024)
+ {
+ mult = 16;
+ x <<= 3;
+ }
+
+ sign = 2*x & 64;
+ frac = (float)((x & 63) - sign) / ((x & ~63) + sign);
+ return g_drmp3_pow43[16 + ((x + sign) >> 6)]*(1.f + frac*((4.f/3) + frac*(2.f/9)))*mult;
+}
+
+static void drmp3_L3_huffman(float *dst, drmp3_bs *bs, const drmp3_L3_gr_info *gr_info, const float *scf, int layer3gr_limit)
+{
+ static const drmp3_int16 tabs[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 785,785,785,785,784,784,784,784,513,513,513,513,513,513,513,513,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,
+ -255,1313,1298,1282,785,785,785,785,784,784,784,784,769,769,769,769,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,290,288,
+ -255,1313,1298,1282,769,769,769,769,529,529,529,529,529,529,529,529,528,528,528,528,528,528,528,528,512,512,512,512,512,512,512,512,290,288,
+ -253,-318,-351,-367,785,785,785,785,784,784,784,784,769,769,769,769,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,819,818,547,547,275,275,275,275,561,560,515,546,289,274,288,258,
+ -254,-287,1329,1299,1314,1312,1057,1057,1042,1042,1026,1026,784,784,784,784,529,529,529,529,529,529,529,529,769,769,769,769,768,768,768,768,563,560,306,306,291,259,
+ -252,-413,-477,-542,1298,-575,1041,1041,784,784,784,784,769,769,769,769,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,-383,-399,1107,1092,1106,1061,849,849,789,789,1104,1091,773,773,1076,1075,341,340,325,309,834,804,577,577,532,532,516,516,832,818,803,816,561,561,531,531,515,546,289,289,288,258,
+ -252,-429,-493,-559,1057,1057,1042,1042,529,529,529,529,529,529,529,529,784,784,784,784,769,769,769,769,512,512,512,512,512,512,512,512,-382,1077,-415,1106,1061,1104,849,849,789,789,1091,1076,1029,1075,834,834,597,581,340,340,339,324,804,833,532,532,832,772,818,803,817,787,816,771,290,290,290,290,288,258,
+ -253,-349,-414,-447,-463,1329,1299,-479,1314,1312,1057,1057,1042,1042,1026,1026,785,785,785,785,784,784,784,784,769,769,769,769,768,768,768,768,-319,851,821,-335,836,850,805,849,341,340,325,336,533,533,579,579,564,564,773,832,578,548,563,516,321,276,306,291,304,259,
+ -251,-572,-733,-830,-863,-879,1041,1041,784,784,784,784,769,769,769,769,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,-511,-527,-543,1396,1351,1381,1366,1395,1335,1380,-559,1334,1138,1138,1063,1063,1350,1392,1031,1031,1062,1062,1364,1363,1120,1120,1333,1348,881,881,881,881,375,374,359,373,343,358,341,325,791,791,1123,1122,-703,1105,1045,-719,865,865,790,790,774,774,1104,1029,338,293,323,308,-799,-815,833,788,772,818,803,816,322,292,307,320,561,531,515,546,289,274,288,258,
+ -251,-525,-605,-685,-765,-831,-846,1298,1057,1057,1312,1282,785,785,785,785,784,784,784,784,769,769,769,769,512,512,512,512,512,512,512,512,1399,1398,1383,1367,1382,1396,1351,-511,1381,1366,1139,1139,1079,1079,1124,1124,1364,1349,1363,1333,882,882,882,882,807,807,807,807,1094,1094,1136,1136,373,341,535,535,881,775,867,822,774,-591,324,338,-671,849,550,550,866,864,609,609,293,336,534,534,789,835,773,-751,834,804,308,307,833,788,832,772,562,562,547,547,305,275,560,515,290,290,
+ -252,-397,-477,-557,-622,-653,-719,-735,-750,1329,1299,1314,1057,1057,1042,1042,1312,1282,1024,1024,785,785,785,785,784,784,784,784,769,769,769,769,-383,1127,1141,1111,1126,1140,1095,1110,869,869,883,883,1079,1109,882,882,375,374,807,868,838,881,791,-463,867,822,368,263,852,837,836,-543,610,610,550,550,352,336,534,534,865,774,851,821,850,805,593,533,579,564,773,832,578,578,548,548,577,577,307,276,306,291,516,560,259,259,
+ -250,-2107,-2507,-2764,-2909,-2974,-3007,-3023,1041,1041,1040,1040,769,769,769,769,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,-767,-1052,-1213,-1277,-1358,-1405,-1469,-1535,-1550,-1582,-1614,-1647,-1662,-1694,-1726,-1759,-1774,-1807,-1822,-1854,-1886,1565,-1919,-1935,-1951,-1967,1731,1730,1580,1717,-1983,1729,1564,-1999,1548,-2015,-2031,1715,1595,-2047,1714,-2063,1610,-2079,1609,-2095,1323,1323,1457,1457,1307,1307,1712,1547,1641,1700,1699,1594,1685,1625,1442,1442,1322,1322,-780,-973,-910,1279,1278,1277,1262,1276,1261,1275,1215,1260,1229,-959,974,974,989,989,-943,735,478,478,495,463,506,414,-1039,1003,958,1017,927,942,987,957,431,476,1272,1167,1228,-1183,1256,-1199,895,895,941,941,1242,1227,1212,1135,1014,1014,490,489,503,487,910,1013,985,925,863,894,970,955,1012,847,-1343,831,755,755,984,909,428,366,754,559,-1391,752,486,457,924,997,698,698,983,893,740,740,908,877,739,739,667,667,953,938,497,287,271,271,683,606,590,712,726,574,302,302,738,736,481,286,526,725,605,711,636,724,696,651,589,681,666,710,364,467,573,695,466,466,301,465,379,379,709,604,665,679,316,316,634,633,436,436,464,269,424,394,452,332,438,363,347,408,393,448,331,422,362,407,392,421,346,406,391,376,375,359,1441,1306,-2367,1290,-2383,1337,-2399,-2415,1426,1321,-2431,1411,1336,-2447,-2463,-2479,1169,1169,1049,1049,1424,1289,1412,1352,1319,-2495,1154,1154,1064,1064,1153,1153,416,390,360,404,403,389,344,374,373,343,358,372,327,357,342,311,356,326,1395,1394,1137,1137,1047,1047,1365,1392,1287,1379,1334,1364,1349,1378,1318,1363,792,792,792,792,1152,1152,1032,1032,1121,1121,1046,1046,1120,1120,1030,1030,-2895,1106,1061,1104,849,849,789,789,1091,1076,1029,1090,1060,1075,833,833,309,324,532,532,832,772,818,803,561,561,531,560,515,546,289,274,288,258,
+ -250,-1179,-1579,-1836,-1996,-2124,-2253,-2333,-2413,-2477,-2542,-2574,-2607,-2622,-2655,1314,1313,1298,1312,1282,785,785,785,785,1040,1040,1025,1025,768,768,768,768,-766,-798,-830,-862,-895,-911,-927,-943,-959,-975,-991,-1007,-1023,-1039,-1055,-1070,1724,1647,-1103,-1119,1631,1767,1662,1738,1708,1723,-1135,1780,1615,1779,1599,1677,1646,1778,1583,-1151,1777,1567,1737,1692,1765,1722,1707,1630,1751,1661,1764,1614,1736,1676,1763,1750,1645,1598,1721,1691,1762,1706,1582,1761,1566,-1167,1749,1629,767,766,751,765,494,494,735,764,719,749,734,763,447,447,748,718,477,506,431,491,446,476,461,505,415,430,475,445,504,399,460,489,414,503,383,474,429,459,502,502,746,752,488,398,501,473,413,472,486,271,480,270,-1439,-1455,1357,-1471,-1487,-1503,1341,1325,-1519,1489,1463,1403,1309,-1535,1372,1448,1418,1476,1356,1462,1387,-1551,1475,1340,1447,1402,1386,-1567,1068,1068,1474,1461,455,380,468,440,395,425,410,454,364,467,466,464,453,269,409,448,268,432,1371,1473,1432,1417,1308,1460,1355,1446,1459,1431,1083,1083,1401,1416,1458,1445,1067,1067,1370,1457,1051,1051,1291,1430,1385,1444,1354,1415,1400,1443,1082,1082,1173,1113,1186,1066,1185,1050,-1967,1158,1128,1172,1097,1171,1081,-1983,1157,1112,416,266,375,400,1170,1142,1127,1065,793,793,1169,1033,1156,1096,1141,1111,1155,1080,1126,1140,898,898,808,808,897,897,792,792,1095,1152,1032,1125,1110,1139,1079,1124,882,807,838,881,853,791,-2319,867,368,263,822,852,837,866,806,865,-2399,851,352,262,534,534,821,836,594,594,549,549,593,593,533,533,848,773,579,579,564,578,548,563,276,276,577,576,306,291,516,560,305,305,275,259,
+ -251,-892,-2058,-2620,-2828,-2957,-3023,-3039,1041,1041,1040,1040,769,769,769,769,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,-511,-527,-543,-559,1530,-575,-591,1528,1527,1407,1526,1391,1023,1023,1023,1023,1525,1375,1268,1268,1103,1103,1087,1087,1039,1039,1523,-604,815,815,815,815,510,495,509,479,508,463,507,447,431,505,415,399,-734,-782,1262,-815,1259,1244,-831,1258,1228,-847,-863,1196,-879,1253,987,987,748,-767,493,493,462,477,414,414,686,669,478,446,461,445,474,429,487,458,412,471,1266,1264,1009,1009,799,799,-1019,-1276,-1452,-1581,-1677,-1757,-1821,-1886,-1933,-1997,1257,1257,1483,1468,1512,1422,1497,1406,1467,1496,1421,1510,1134,1134,1225,1225,1466,1451,1374,1405,1252,1252,1358,1480,1164,1164,1251,1251,1238,1238,1389,1465,-1407,1054,1101,-1423,1207,-1439,830,830,1248,1038,1237,1117,1223,1148,1236,1208,411,426,395,410,379,269,1193,1222,1132,1235,1221,1116,976,976,1192,1162,1177,1220,1131,1191,963,963,-1647,961,780,-1663,558,558,994,993,437,408,393,407,829,978,813,797,947,-1743,721,721,377,392,844,950,828,890,706,706,812,859,796,960,948,843,934,874,571,571,-1919,690,555,689,421,346,539,539,944,779,918,873,932,842,903,888,570,570,931,917,674,674,-2575,1562,-2591,1609,-2607,1654,1322,1322,1441,1441,1696,1546,1683,1593,1669,1624,1426,1426,1321,1321,1639,1680,1425,1425,1305,1305,1545,1668,1608,1623,1667,1592,1638,1666,1320,1320,1652,1607,1409,1409,1304,1304,1288,1288,1664,1637,1395,1395,1335,1335,1622,1636,1394,1394,1319,1319,1606,1621,1392,1392,1137,1137,1137,1137,345,390,360,375,404,373,1047,-2751,-2767,-2783,1062,1121,1046,-2799,1077,-2815,1106,1061,789,789,1105,1104,263,355,310,340,325,354,352,262,339,324,1091,1076,1029,1090,1060,1075,833,833,788,788,1088,1028,818,818,803,803,561,561,531,531,816,771,546,546,289,274,288,258,
+ -253,-317,-381,-446,-478,-509,1279,1279,-811,-1179,-1451,-1756,-1900,-2028,-2189,-2253,-2333,-2414,-2445,-2511,-2526,1313,1298,-2559,1041,1041,1040,1040,1025,1025,1024,1024,1022,1007,1021,991,1020,975,1019,959,687,687,1018,1017,671,671,655,655,1016,1015,639,639,758,758,623,623,757,607,756,591,755,575,754,559,543,543,1009,783,-575,-621,-685,-749,496,-590,750,749,734,748,974,989,1003,958,988,973,1002,942,987,957,972,1001,926,986,941,971,956,1000,910,985,925,999,894,970,-1071,-1087,-1102,1390,-1135,1436,1509,1451,1374,-1151,1405,1358,1480,1420,-1167,1507,1494,1389,1342,1465,1435,1450,1326,1505,1310,1493,1373,1479,1404,1492,1464,1419,428,443,472,397,736,526,464,464,486,457,442,471,484,482,1357,1449,1434,1478,1388,1491,1341,1490,1325,1489,1463,1403,1309,1477,1372,1448,1418,1433,1476,1356,1462,1387,-1439,1475,1340,1447,1402,1474,1324,1461,1371,1473,269,448,1432,1417,1308,1460,-1711,1459,-1727,1441,1099,1099,1446,1386,1431,1401,-1743,1289,1083,1083,1160,1160,1458,1445,1067,1067,1370,1457,1307,1430,1129,1129,1098,1098,268,432,267,416,266,400,-1887,1144,1187,1082,1173,1113,1186,1066,1050,1158,1128,1143,1172,1097,1171,1081,420,391,1157,1112,1170,1142,1127,1065,1169,1049,1156,1096,1141,1111,1155,1080,1126,1154,1064,1153,1140,1095,1048,-2159,1125,1110,1137,-2175,823,823,1139,1138,807,807,384,264,368,263,868,838,853,791,867,822,852,837,866,806,865,790,-2319,851,821,836,352,262,850,805,849,-2399,533,533,835,820,336,261,578,548,563,577,532,532,832,772,562,562,547,547,305,275,560,515,290,290,288,258 };
+ static const drmp3_uint8 tab32[] = { 130,162,193,209,44,28,76,140,9,9,9,9,9,9,9,9,190,254,222,238,126,94,157,157,109,61,173,205};
+ static const drmp3_uint8 tab33[] = { 252,236,220,204,188,172,156,140,124,108,92,76,60,44,28,12 };
+ static const drmp3_int16 tabindex[2*16] = { 0,32,64,98,0,132,180,218,292,364,426,538,648,746,0,1126,1460,1460,1460,1460,1460,1460,1460,1460,1842,1842,1842,1842,1842,1842,1842,1842 };
+ static const drmp3_uint8 g_linbits[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,3,4,6,8,10,13,4,5,6,7,8,9,11,13 };
+
+#define DRMP3_PEEK_BITS(n) (bs_cache >> (32 - (n)))
+#define DRMP3_FLUSH_BITS(n) { bs_cache <<= (n); bs_sh += (n); }
+#define DRMP3_CHECK_BITS while (bs_sh >= 0) { bs_cache |= (drmp3_uint32)*bs_next_ptr++ << bs_sh; bs_sh -= 8; }
+#define DRMP3_BSPOS ((bs_next_ptr - bs->buf)*8 - 24 + bs_sh)
+
+ float one = 0.0f;
+ int ireg = 0, big_val_cnt = gr_info->big_values;
+ const drmp3_uint8 *sfb = gr_info->sfbtab;
+ const drmp3_uint8 *bs_next_ptr = bs->buf + bs->pos/8;
+ drmp3_uint32 bs_cache = (((bs_next_ptr[0]*256u + bs_next_ptr[1])*256u + bs_next_ptr[2])*256u + bs_next_ptr[3]) << (bs->pos & 7);
+ int pairs_to_decode, np, bs_sh = (bs->pos & 7) - 8;
+ bs_next_ptr += 4;
+
+ while (big_val_cnt > 0)
+ {
+ int tab_num = gr_info->table_select[ireg];
+ int sfb_cnt = gr_info->region_count[ireg++];
+ const drmp3_int16 *codebook = tabs + tabindex[tab_num];
+ int linbits = g_linbits[tab_num];
+ if (linbits)
+ {
+ do
+ {
+ np = *sfb++ / 2;
+ pairs_to_decode = DRMP3_MIN(big_val_cnt, np);
+ one = *scf++;
+ do
+ {
+ int j, w = 5;
+ int leaf = codebook[DRMP3_PEEK_BITS(w)];
+ while (leaf < 0)
+ {
+ DRMP3_FLUSH_BITS(w);
+ w = leaf & 7;
+ leaf = codebook[DRMP3_PEEK_BITS(w) - (leaf >> 3)];
+ }
+ DRMP3_FLUSH_BITS(leaf >> 8);
+
+ for (j = 0; j < 2; j++, dst++, leaf >>= 4)
+ {
+ int lsb = leaf & 0x0F;
+ if (lsb == 15)
+ {
+ lsb += DRMP3_PEEK_BITS(linbits);
+ DRMP3_FLUSH_BITS(linbits);
+ DRMP3_CHECK_BITS;
+ *dst = one*drmp3_L3_pow_43(lsb)*((drmp3_int32)bs_cache < 0 ? -1: 1);
+ } else
+ {
+ *dst = g_drmp3_pow43[16 + lsb - 16*(bs_cache >> 31)]*one;
+ }
+ DRMP3_FLUSH_BITS(lsb ? 1 : 0);
+ }
+ DRMP3_CHECK_BITS;
+ } while (--pairs_to_decode);
+ } while ((big_val_cnt -= np) > 0 && --sfb_cnt >= 0);
+ } else
+ {
+ do
+ {
+ np = *sfb++ / 2;
+ pairs_to_decode = DRMP3_MIN(big_val_cnt, np);
+ one = *scf++;
+ do
+ {
+ int j, w = 5;
+ int leaf = codebook[DRMP3_PEEK_BITS(w)];
+ while (leaf < 0)
+ {
+ DRMP3_FLUSH_BITS(w);
+ w = leaf & 7;
+ leaf = codebook[DRMP3_PEEK_BITS(w) - (leaf >> 3)];
+ }
+ DRMP3_FLUSH_BITS(leaf >> 8);
+
+ for (j = 0; j < 2; j++, dst++, leaf >>= 4)
+ {
+ int lsb = leaf & 0x0F;
+ *dst = g_drmp3_pow43[16 + lsb - 16*(bs_cache >> 31)]*one;
+ DRMP3_FLUSH_BITS(lsb ? 1 : 0);
+ }
+ DRMP3_CHECK_BITS;
+ } while (--pairs_to_decode);
+ } while ((big_val_cnt -= np) > 0 && --sfb_cnt >= 0);
+ }
+ }
+
+ for (np = 1 - big_val_cnt;; dst += 4)
+ {
+ const drmp3_uint8 *codebook_count1 = (gr_info->count1_table) ? tab33 : tab32;
+ int leaf = codebook_count1[DRMP3_PEEK_BITS(4)];
+ if (!(leaf & 8))
+ {
+ leaf = codebook_count1[(leaf >> 3) + (bs_cache << 4 >> (32 - (leaf & 3)))];
+ }
+ DRMP3_FLUSH_BITS(leaf & 7);
+ if (DRMP3_BSPOS > layer3gr_limit)
+ {
+ break;
+ }
+#define DRMP3_RELOAD_SCALEFACTOR if (!--np) { np = *sfb++/2; if (!np) break; one = *scf++; }
+#define DRMP3_DEQ_COUNT1(s) if (leaf & (128 >> s)) { dst[s] = ((drmp3_int32)bs_cache < 0) ? -one : one; DRMP3_FLUSH_BITS(1) }
+ DRMP3_RELOAD_SCALEFACTOR;
+ DRMP3_DEQ_COUNT1(0);
+ DRMP3_DEQ_COUNT1(1);
+ DRMP3_RELOAD_SCALEFACTOR;
+ DRMP3_DEQ_COUNT1(2);
+ DRMP3_DEQ_COUNT1(3);
+ DRMP3_CHECK_BITS;
+ }
+
+ bs->pos = layer3gr_limit;
+}
+
+static void drmp3_L3_midside_stereo(float *left, int n)
+{
+ int i = 0;
+ float *right = left + 576;
+#if DRMP3_HAVE_SIMD
+ if (drmp3_have_simd())
+ {
+ for (; i < n - 3; i += 4)
+ {
+ drmp3_f4 vl = DRMP3_VLD(left + i);
+ drmp3_f4 vr = DRMP3_VLD(right + i);
+ DRMP3_VSTORE(left + i, DRMP3_VADD(vl, vr));
+ DRMP3_VSTORE(right + i, DRMP3_VSUB(vl, vr));
+ }
+#ifdef __GNUC__
+ /* Workaround for spurious -Waggressive-loop-optimizations warning from gcc.
+ * For more info see: https://github.com/lieff/minimp3/issues/88
+ */
+ if (__builtin_constant_p(n % 4 == 0) && n % 4 == 0)
+ return;
+#endif
+ }
+#endif
+ for (; i < n; i++)
+ {
+ float a = left[i];
+ float b = right[i];
+ left[i] = a + b;
+ right[i] = a - b;
+ }
+}
+
+static void drmp3_L3_intensity_stereo_band(float *left, int n, float kl, float kr)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ {
+ left[i + 576] = left[i]*kr;
+ left[i] = left[i]*kl;
+ }
+}
+
+static void drmp3_L3_stereo_top_band(const float *right, const drmp3_uint8 *sfb, int nbands, int max_band[3])
+{
+ int i, k;
+
+ max_band[0] = max_band[1] = max_band[2] = -1;
+
+ for (i = 0; i < nbands; i++)
+ {
+ for (k = 0; k < sfb[i]; k += 2)
+ {
+ if (right[k] != 0 || right[k + 1] != 0)
+ {
+ max_band[i % 3] = i;
+ break;
+ }
+ }
+ right += sfb[i];
+ }
+}
+
+static void drmp3_L3_stereo_process(float *left, const drmp3_uint8 *ist_pos, const drmp3_uint8 *sfb, const drmp3_uint8 *hdr, int max_band[3], int mpeg2_sh)
+{
+ static const float g_pan[7*2] = { 0,1,0.21132487f,0.78867513f,0.36602540f,0.63397460f,0.5f,0.5f,0.63397460f,0.36602540f,0.78867513f,0.21132487f,1,0 };
+ unsigned i, max_pos = DRMP3_HDR_TEST_MPEG1(hdr) ? 7 : 64;
+
+ for (i = 0; sfb[i]; i++)
+ {
+ unsigned ipos = ist_pos[i];
+ if ((int)i > max_band[i % 3] && ipos < max_pos)
+ {
+ float kl, kr, s = DRMP3_HDR_TEST_MS_STEREO(hdr) ? 1.41421356f : 1;
+ if (DRMP3_HDR_TEST_MPEG1(hdr))
+ {
+ kl = g_pan[2*ipos];
+ kr = g_pan[2*ipos + 1];
+ } else
+ {
+ kl = 1;
+ kr = drmp3_L3_ldexp_q2(1, (ipos + 1) >> 1 << mpeg2_sh);
+ if (ipos & 1)
+ {
+ kl = kr;
+ kr = 1;
+ }
+ }
+ drmp3_L3_intensity_stereo_band(left, sfb[i], kl*s, kr*s);
+ } else if (DRMP3_HDR_TEST_MS_STEREO(hdr))
+ {
+ drmp3_L3_midside_stereo(left, sfb[i]);
+ }
+ left += sfb[i];
+ }
+}
+
+static void drmp3_L3_intensity_stereo(float *left, drmp3_uint8 *ist_pos, const drmp3_L3_gr_info *gr, const drmp3_uint8 *hdr)
+{
+ int max_band[3], n_sfb = gr->n_long_sfb + gr->n_short_sfb;
+ int i, max_blocks = gr->n_short_sfb ? 3 : 1;
+
+ drmp3_L3_stereo_top_band(left + 576, gr->sfbtab, n_sfb, max_band);
+ if (gr->n_long_sfb)
+ {
+ max_band[0] = max_band[1] = max_band[2] = DRMP3_MAX(DRMP3_MAX(max_band[0], max_band[1]), max_band[2]);
+ }
+ for (i = 0; i < max_blocks; i++)
+ {
+ int default_pos = DRMP3_HDR_TEST_MPEG1(hdr) ? 3 : 0;
+ int itop = n_sfb - max_blocks + i;
+ int prev = itop - max_blocks;
+ ist_pos[itop] = (drmp3_uint8)(max_band[i] >= prev ? default_pos : ist_pos[prev]);
+ }
+ drmp3_L3_stereo_process(left, ist_pos, gr->sfbtab, hdr, max_band, gr[1].scalefac_compress & 1);
+}
+
+static void drmp3_L3_reorder(float *grbuf, float *scratch, const drmp3_uint8 *sfb)
+{
+ int i, len;
+ float *src = grbuf, *dst = scratch;
+
+ for (;0 != (len = *sfb); sfb += 3, src += 2*len)
+ {
+ for (i = 0; i < len; i++, src++)
+ {
+ *dst++ = src[0*len];
+ *dst++ = src[1*len];
+ *dst++ = src[2*len];
+ }
+ }
+ DRMP3_COPY_MEMORY(grbuf, scratch, (dst - scratch)*sizeof(float));
+}
+
+static void drmp3_L3_antialias(float *grbuf, int nbands)
+{
+ static const float g_aa[2][8] = {
+ {0.85749293f,0.88174200f,0.94962865f,0.98331459f,0.99551782f,0.99916056f,0.99989920f,0.99999316f},
+ {0.51449576f,0.47173197f,0.31337745f,0.18191320f,0.09457419f,0.04096558f,0.01419856f,0.00369997f}
+ };
+
+ for (; nbands > 0; nbands--, grbuf += 18)
+ {
+ int i = 0;
+#if DRMP3_HAVE_SIMD
+ if (drmp3_have_simd()) for (; i < 8; i += 4)
+ {
+ drmp3_f4 vu = DRMP3_VLD(grbuf + 18 + i);
+ drmp3_f4 vd = DRMP3_VLD(grbuf + 14 - i);
+ drmp3_f4 vc0 = DRMP3_VLD(g_aa[0] + i);
+ drmp3_f4 vc1 = DRMP3_VLD(g_aa[1] + i);
+ vd = DRMP3_VREV(vd);
+ DRMP3_VSTORE(grbuf + 18 + i, DRMP3_VSUB(DRMP3_VMUL(vu, vc0), DRMP3_VMUL(vd, vc1)));
+ vd = DRMP3_VADD(DRMP3_VMUL(vu, vc1), DRMP3_VMUL(vd, vc0));
+ DRMP3_VSTORE(grbuf + 14 - i, DRMP3_VREV(vd));
+ }
+#endif
+#ifndef DR_MP3_ONLY_SIMD
+ for(; i < 8; i++)
+ {
+ float u = grbuf[18 + i];
+ float d = grbuf[17 - i];
+ grbuf[18 + i] = u*g_aa[0][i] - d*g_aa[1][i];
+ grbuf[17 - i] = u*g_aa[1][i] + d*g_aa[0][i];
+ }
+#endif
+ }
+}
+
+static void drmp3_L3_dct3_9(float *y)
+{
+ float s0, s1, s2, s3, s4, s5, s6, s7, s8, t0, t2, t4;
+
+ s0 = y[0]; s2 = y[2]; s4 = y[4]; s6 = y[6]; s8 = y[8];
+ t0 = s0 + s6*0.5f;
+ s0 -= s6;
+ t4 = (s4 + s2)*0.93969262f;
+ t2 = (s8 + s2)*0.76604444f;
+ s6 = (s4 - s8)*0.17364818f;
+ s4 += s8 - s2;
+
+ s2 = s0 - s4*0.5f;
+ y[4] = s4 + s0;
+ s8 = t0 - t2 + s6;
+ s0 = t0 - t4 + t2;
+ s4 = t0 + t4 - s6;
+
+ s1 = y[1]; s3 = y[3]; s5 = y[5]; s7 = y[7];
+
+ s3 *= 0.86602540f;
+ t0 = (s5 + s1)*0.98480775f;
+ t4 = (s5 - s7)*0.34202014f;
+ t2 = (s1 + s7)*0.64278761f;
+ s1 = (s1 - s5 - s7)*0.86602540f;
+
+ s5 = t0 - s3 - t2;
+ s7 = t4 - s3 - t0;
+ s3 = t4 + s3 - t2;
+
+ y[0] = s4 - s7;
+ y[1] = s2 + s1;
+ y[2] = s0 - s3;
+ y[3] = s8 + s5;
+ y[5] = s8 - s5;
+ y[6] = s0 + s3;
+ y[7] = s2 - s1;
+ y[8] = s4 + s7;
+}
+
+static void drmp3_L3_imdct36(float *grbuf, float *overlap, const float *window, int nbands)
+{
+ int i, j;
+ static const float g_twid9[18] = {
+ 0.73727734f,0.79335334f,0.84339145f,0.88701083f,0.92387953f,0.95371695f,0.97629601f,0.99144486f,0.99904822f,0.67559021f,0.60876143f,0.53729961f,0.46174861f,0.38268343f,0.30070580f,0.21643961f,0.13052619f,0.04361938f
+ };
+
+ for (j = 0; j < nbands; j++, grbuf += 18, overlap += 9)
+ {
+ float co[9], si[9];
+ co[0] = -grbuf[0];
+ si[0] = grbuf[17];
+ for (i = 0; i < 4; i++)
+ {
+ si[8 - 2*i] = grbuf[4*i + 1] - grbuf[4*i + 2];
+ co[1 + 2*i] = grbuf[4*i + 1] + grbuf[4*i + 2];
+ si[7 - 2*i] = grbuf[4*i + 4] - grbuf[4*i + 3];
+ co[2 + 2*i] = -(grbuf[4*i + 3] + grbuf[4*i + 4]);
+ }
+ drmp3_L3_dct3_9(co);
+ drmp3_L3_dct3_9(si);
+
+ si[1] = -si[1];
+ si[3] = -si[3];
+ si[5] = -si[5];
+ si[7] = -si[7];
+
+ i = 0;
+
+#if DRMP3_HAVE_SIMD
+ if (drmp3_have_simd()) for (; i < 8; i += 4)
+ {
+ drmp3_f4 vovl = DRMP3_VLD(overlap + i);
+ drmp3_f4 vc = DRMP3_VLD(co + i);
+ drmp3_f4 vs = DRMP3_VLD(si + i);
+ drmp3_f4 vr0 = DRMP3_VLD(g_twid9 + i);
+ drmp3_f4 vr1 = DRMP3_VLD(g_twid9 + 9 + i);
+ drmp3_f4 vw0 = DRMP3_VLD(window + i);
+ drmp3_f4 vw1 = DRMP3_VLD(window + 9 + i);
+ drmp3_f4 vsum = DRMP3_VADD(DRMP3_VMUL(vc, vr1), DRMP3_VMUL(vs, vr0));
+ DRMP3_VSTORE(overlap + i, DRMP3_VSUB(DRMP3_VMUL(vc, vr0), DRMP3_VMUL(vs, vr1)));
+ DRMP3_VSTORE(grbuf + i, DRMP3_VSUB(DRMP3_VMUL(vovl, vw0), DRMP3_VMUL(vsum, vw1)));
+ vsum = DRMP3_VADD(DRMP3_VMUL(vovl, vw1), DRMP3_VMUL(vsum, vw0));
+ DRMP3_VSTORE(grbuf + 14 - i, DRMP3_VREV(vsum));
+ }
+#endif
+ for (; i < 9; i++)
+ {
+ float ovl = overlap[i];
+ float sum = co[i]*g_twid9[9 + i] + si[i]*g_twid9[0 + i];
+ overlap[i] = co[i]*g_twid9[0 + i] - si[i]*g_twid9[9 + i];
+ grbuf[i] = ovl*window[0 + i] - sum*window[9 + i];
+ grbuf[17 - i] = ovl*window[9 + i] + sum*window[0 + i];
+ }
+ }
+}
+
+static void drmp3_L3_idct3(float x0, float x1, float x2, float *dst)
+{
+ float m1 = x1*0.86602540f;
+ float a1 = x0 - x2*0.5f;
+ dst[1] = x0 + x2;
+ dst[0] = a1 + m1;
+ dst[2] = a1 - m1;
+}
+
+static void drmp3_L3_imdct12(float *x, float *dst, float *overlap)
+{
+ static const float g_twid3[6] = { 0.79335334f,0.92387953f,0.99144486f, 0.60876143f,0.38268343f,0.13052619f };
+ float co[3], si[3];
+ int i;
+
+ drmp3_L3_idct3(-x[0], x[6] + x[3], x[12] + x[9], co);
+ drmp3_L3_idct3(x[15], x[12] - x[9], x[6] - x[3], si);
+ si[1] = -si[1];
+
+ for (i = 0; i < 3; i++)
+ {
+ float ovl = overlap[i];
+ float sum = co[i]*g_twid3[3 + i] + si[i]*g_twid3[0 + i];
+ overlap[i] = co[i]*g_twid3[0 + i] - si[i]*g_twid3[3 + i];
+ dst[i] = ovl*g_twid3[2 - i] - sum*g_twid3[5 - i];
+ dst[5 - i] = ovl*g_twid3[5 - i] + sum*g_twid3[2 - i];
+ }
+}
+
+static void drmp3_L3_imdct_short(float *grbuf, float *overlap, int nbands)
+{
+ for (;nbands > 0; nbands--, overlap += 9, grbuf += 18)
+ {
+ float tmp[18];
+ DRMP3_COPY_MEMORY(tmp, grbuf, sizeof(tmp));
+ DRMP3_COPY_MEMORY(grbuf, overlap, 6*sizeof(float));
+ drmp3_L3_imdct12(tmp, grbuf + 6, overlap + 6);
+ drmp3_L3_imdct12(tmp + 1, grbuf + 12, overlap + 6);
+ drmp3_L3_imdct12(tmp + 2, overlap, overlap + 6);
+ }
+}
+
+static void drmp3_L3_change_sign(float *grbuf)
+{
+ int b, i;
+ for (b = 0, grbuf += 18; b < 32; b += 2, grbuf += 36)
+ for (i = 1; i < 18; i += 2)
+ grbuf[i] = -grbuf[i];
+}
+
+static void drmp3_L3_imdct_gr(float *grbuf, float *overlap, unsigned block_type, unsigned n_long_bands)
+{
+ static const float g_mdct_window[2][18] = {
+ { 0.99904822f,0.99144486f,0.97629601f,0.95371695f,0.92387953f,0.88701083f,0.84339145f,0.79335334f,0.73727734f,0.04361938f,0.13052619f,0.21643961f,0.30070580f,0.38268343f,0.46174861f,0.53729961f,0.60876143f,0.67559021f },
+ { 1,1,1,1,1,1,0.99144486f,0.92387953f,0.79335334f,0,0,0,0,0,0,0.13052619f,0.38268343f,0.60876143f }
+ };
+ if (n_long_bands)
+ {
+ drmp3_L3_imdct36(grbuf, overlap, g_mdct_window[0], n_long_bands);
+ grbuf += 18*n_long_bands;
+ overlap += 9*n_long_bands;
+ }
+ if (block_type == DRMP3_SHORT_BLOCK_TYPE)
+ drmp3_L3_imdct_short(grbuf, overlap, 32 - n_long_bands);
+ else
+ drmp3_L3_imdct36(grbuf, overlap, g_mdct_window[block_type == DRMP3_STOP_BLOCK_TYPE], 32 - n_long_bands);
+}
+
+static void drmp3_L3_save_reservoir(drmp3dec *h, drmp3dec_scratch *s)
+{
+ int pos = (s->bs.pos + 7)/8u;
+ int remains = s->bs.limit/8u - pos;
+ if (remains > DRMP3_MAX_BITRESERVOIR_BYTES)
+ {
+ pos += remains - DRMP3_MAX_BITRESERVOIR_BYTES;
+ remains = DRMP3_MAX_BITRESERVOIR_BYTES;
+ }
+ if (remains > 0)
+ {
+ DRMP3_MOVE_MEMORY(h->reserv_buf, s->maindata + pos, remains);
+ }
+ h->reserv = remains;
+}
+
+static int drmp3_L3_restore_reservoir(drmp3dec *h, drmp3_bs *bs, drmp3dec_scratch *s, int main_data_begin)
+{
+ int frame_bytes = (bs->limit - bs->pos)/8;
+ int bytes_have = DRMP3_MIN(h->reserv, main_data_begin);
+ DRMP3_COPY_MEMORY(s->maindata, h->reserv_buf + DRMP3_MAX(0, h->reserv - main_data_begin), DRMP3_MIN(h->reserv, main_data_begin));
+ DRMP3_COPY_MEMORY(s->maindata + bytes_have, bs->buf + bs->pos/8, frame_bytes);
+ drmp3_bs_init(&s->bs, s->maindata, bytes_have + frame_bytes);
+ return h->reserv >= main_data_begin;
+}
+
+static void drmp3_L3_decode(drmp3dec *h, drmp3dec_scratch *s, drmp3_L3_gr_info *gr_info, int nch)
+{
+ int ch;
+
+ for (ch = 0; ch < nch; ch++)
+ {
+ int layer3gr_limit = s->bs.pos + gr_info[ch].part_23_length;
+ drmp3_L3_decode_scalefactors(h->header, s->ist_pos[ch], &s->bs, gr_info + ch, s->scf, ch);
+ drmp3_L3_huffman(s->grbuf[ch], &s->bs, gr_info + ch, s->scf, layer3gr_limit);
+ }
+
+ if (DRMP3_HDR_TEST_I_STEREO(h->header))
+ {
+ drmp3_L3_intensity_stereo(s->grbuf[0], s->ist_pos[1], gr_info, h->header);
+ } else if (DRMP3_HDR_IS_MS_STEREO(h->header))
+ {
+ drmp3_L3_midside_stereo(s->grbuf[0], 576);
+ }
+
+ for (ch = 0; ch < nch; ch++, gr_info++)
+ {
+ int aa_bands = 31;
+ int n_long_bands = (gr_info->mixed_block_flag ? 2 : 0) << (int)(DRMP3_HDR_GET_MY_SAMPLE_RATE(h->header) == 2);
+
+ if (gr_info->n_short_sfb)
+ {
+ aa_bands = n_long_bands - 1;
+ drmp3_L3_reorder(s->grbuf[ch] + n_long_bands*18, s->syn[0], gr_info->sfbtab + gr_info->n_long_sfb);
+ }
+
+ drmp3_L3_antialias(s->grbuf[ch], aa_bands);
+ drmp3_L3_imdct_gr(s->grbuf[ch], h->mdct_overlap[ch], gr_info->block_type, n_long_bands);
+ drmp3_L3_change_sign(s->grbuf[ch]);
+ }
+}
+
+static void drmp3d_DCT_II(float *grbuf, int n)
+{
+ static const float g_sec[24] = {
+ 10.19000816f,0.50060302f,0.50241929f,3.40760851f,0.50547093f,0.52249861f,2.05778098f,0.51544732f,0.56694406f,1.48416460f,0.53104258f,0.64682180f,1.16943991f,0.55310392f,0.78815460f,0.97256821f,0.58293498f,1.06067765f,0.83934963f,0.62250412f,1.72244716f,0.74453628f,0.67480832f,5.10114861f
+ };
+ int i, k = 0;
+#if DRMP3_HAVE_SIMD
+ if (drmp3_have_simd()) for (; k < n; k += 4)
+ {
+ drmp3_f4 t[4][8], *x;
+ float *y = grbuf + k;
+
+ for (x = t[0], i = 0; i < 8; i++, x++)
+ {
+ drmp3_f4 x0 = DRMP3_VLD(&y[i*18]);
+ drmp3_f4 x1 = DRMP3_VLD(&y[(15 - i)*18]);
+ drmp3_f4 x2 = DRMP3_VLD(&y[(16 + i)*18]);
+ drmp3_f4 x3 = DRMP3_VLD(&y[(31 - i)*18]);
+ drmp3_f4 t0 = DRMP3_VADD(x0, x3);
+ drmp3_f4 t1 = DRMP3_VADD(x1, x2);
+ drmp3_f4 t2 = DRMP3_VMUL_S(DRMP3_VSUB(x1, x2), g_sec[3*i + 0]);
+ drmp3_f4 t3 = DRMP3_VMUL_S(DRMP3_VSUB(x0, x3), g_sec[3*i + 1]);
+ x[0] = DRMP3_VADD(t0, t1);
+ x[8] = DRMP3_VMUL_S(DRMP3_VSUB(t0, t1), g_sec[3*i + 2]);
+ x[16] = DRMP3_VADD(t3, t2);
+ x[24] = DRMP3_VMUL_S(DRMP3_VSUB(t3, t2), g_sec[3*i + 2]);
+ }
+ for (x = t[0], i = 0; i < 4; i++, x += 8)
+ {
+ drmp3_f4 x0 = x[0], x1 = x[1], x2 = x[2], x3 = x[3], x4 = x[4], x5 = x[5], x6 = x[6], x7 = x[7], xt;
+ xt = DRMP3_VSUB(x0, x7); x0 = DRMP3_VADD(x0, x7);
+ x7 = DRMP3_VSUB(x1, x6); x1 = DRMP3_VADD(x1, x6);
+ x6 = DRMP3_VSUB(x2, x5); x2 = DRMP3_VADD(x2, x5);
+ x5 = DRMP3_VSUB(x3, x4); x3 = DRMP3_VADD(x3, x4);
+ x4 = DRMP3_VSUB(x0, x3); x0 = DRMP3_VADD(x0, x3);
+ x3 = DRMP3_VSUB(x1, x2); x1 = DRMP3_VADD(x1, x2);
+ x[0] = DRMP3_VADD(x0, x1);
+ x[4] = DRMP3_VMUL_S(DRMP3_VSUB(x0, x1), 0.70710677f);
+ x5 = DRMP3_VADD(x5, x6);
+ x6 = DRMP3_VMUL_S(DRMP3_VADD(x6, x7), 0.70710677f);
+ x7 = DRMP3_VADD(x7, xt);
+ x3 = DRMP3_VMUL_S(DRMP3_VADD(x3, x4), 0.70710677f);
+ x5 = DRMP3_VSUB(x5, DRMP3_VMUL_S(x7, 0.198912367f)); /* rotate by PI/8 */
+ x7 = DRMP3_VADD(x7, DRMP3_VMUL_S(x5, 0.382683432f));
+ x5 = DRMP3_VSUB(x5, DRMP3_VMUL_S(x7, 0.198912367f));
+ x0 = DRMP3_VSUB(xt, x6); xt = DRMP3_VADD(xt, x6);
+ x[1] = DRMP3_VMUL_S(DRMP3_VADD(xt, x7), 0.50979561f);
+ x[2] = DRMP3_VMUL_S(DRMP3_VADD(x4, x3), 0.54119611f);
+ x[3] = DRMP3_VMUL_S(DRMP3_VSUB(x0, x5), 0.60134488f);
+ x[5] = DRMP3_VMUL_S(DRMP3_VADD(x0, x5), 0.89997619f);
+ x[6] = DRMP3_VMUL_S(DRMP3_VSUB(x4, x3), 1.30656302f);
+ x[7] = DRMP3_VMUL_S(DRMP3_VSUB(xt, x7), 2.56291556f);
+ }
+
+ if (k > n - 3)
+ {
+#if DRMP3_HAVE_SSE
+#define DRMP3_VSAVE2(i, v) _mm_storel_pi((__m64 *)(void*)&y[i*18], v)
+#else
+#define DRMP3_VSAVE2(i, v) vst1_f32((float32_t *)&y[(i)*18], vget_low_f32(v))
+#endif
+ for (i = 0; i < 7; i++, y += 4*18)
+ {
+ drmp3_f4 s = DRMP3_VADD(t[3][i], t[3][i + 1]);
+ DRMP3_VSAVE2(0, t[0][i]);
+ DRMP3_VSAVE2(1, DRMP3_VADD(t[2][i], s));
+ DRMP3_VSAVE2(2, DRMP3_VADD(t[1][i], t[1][i + 1]));
+ DRMP3_VSAVE2(3, DRMP3_VADD(t[2][1 + i], s));
+ }
+ DRMP3_VSAVE2(0, t[0][7]);
+ DRMP3_VSAVE2(1, DRMP3_VADD(t[2][7], t[3][7]));
+ DRMP3_VSAVE2(2, t[1][7]);
+ DRMP3_VSAVE2(3, t[3][7]);
+ } else
+ {
+#define DRMP3_VSAVE4(i, v) DRMP3_VSTORE(&y[(i)*18], v)
+ for (i = 0; i < 7; i++, y += 4*18)
+ {
+ drmp3_f4 s = DRMP3_VADD(t[3][i], t[3][i + 1]);
+ DRMP3_VSAVE4(0, t[0][i]);
+ DRMP3_VSAVE4(1, DRMP3_VADD(t[2][i], s));
+ DRMP3_VSAVE4(2, DRMP3_VADD(t[1][i], t[1][i + 1]));
+ DRMP3_VSAVE4(3, DRMP3_VADD(t[2][1 + i], s));
+ }
+ DRMP3_VSAVE4(0, t[0][7]);
+ DRMP3_VSAVE4(1, DRMP3_VADD(t[2][7], t[3][7]));
+ DRMP3_VSAVE4(2, t[1][7]);
+ DRMP3_VSAVE4(3, t[3][7]);
+ }
+ } else
+#endif
+#ifdef DR_MP3_ONLY_SIMD
+ {} /* for HAVE_SIMD=1, MINIMP3_ONLY_SIMD=1 case we do not need non-intrinsic "else" branch */
+#else
+ for (; k < n; k++)
+ {
+ float t[4][8], *x, *y = grbuf + k;
+
+ for (x = t[0], i = 0; i < 8; i++, x++)
+ {
+ float x0 = y[i*18];
+ float x1 = y[(15 - i)*18];
+ float x2 = y[(16 + i)*18];
+ float x3 = y[(31 - i)*18];
+ float t0 = x0 + x3;
+ float t1 = x1 + x2;
+ float t2 = (x1 - x2)*g_sec[3*i + 0];
+ float t3 = (x0 - x3)*g_sec[3*i + 1];
+ x[0] = t0 + t1;
+ x[8] = (t0 - t1)*g_sec[3*i + 2];
+ x[16] = t3 + t2;
+ x[24] = (t3 - t2)*g_sec[3*i + 2];
+ }
+ for (x = t[0], i = 0; i < 4; i++, x += 8)
+ {
+ float x0 = x[0], x1 = x[1], x2 = x[2], x3 = x[3], x4 = x[4], x5 = x[5], x6 = x[6], x7 = x[7], xt;
+ xt = x0 - x7; x0 += x7;
+ x7 = x1 - x6; x1 += x6;
+ x6 = x2 - x5; x2 += x5;
+ x5 = x3 - x4; x3 += x4;
+ x4 = x0 - x3; x0 += x3;
+ x3 = x1 - x2; x1 += x2;
+ x[0] = x0 + x1;
+ x[4] = (x0 - x1)*0.70710677f;
+ x5 = x5 + x6;
+ x6 = (x6 + x7)*0.70710677f;
+ x7 = x7 + xt;
+ x3 = (x3 + x4)*0.70710677f;
+ x5 -= x7*0.198912367f; /* rotate by PI/8 */
+ x7 += x5*0.382683432f;
+ x5 -= x7*0.198912367f;
+ x0 = xt - x6; xt += x6;
+ x[1] = (xt + x7)*0.50979561f;
+ x[2] = (x4 + x3)*0.54119611f;
+ x[3] = (x0 - x5)*0.60134488f;
+ x[5] = (x0 + x5)*0.89997619f;
+ x[6] = (x4 - x3)*1.30656302f;
+ x[7] = (xt - x7)*2.56291556f;
+
+ }
+ for (i = 0; i < 7; i++, y += 4*18)
+ {
+ y[0*18] = t[0][i];
+ y[1*18] = t[2][i] + t[3][i] + t[3][i + 1];
+ y[2*18] = t[1][i] + t[1][i + 1];
+ y[3*18] = t[2][i + 1] + t[3][i] + t[3][i + 1];
+ }
+ y[0*18] = t[0][7];
+ y[1*18] = t[2][7] + t[3][7];
+ y[2*18] = t[1][7];
+ y[3*18] = t[3][7];
+ }
+#endif
+}
+
+#ifndef DR_MP3_FLOAT_OUTPUT
+typedef drmp3_int16 drmp3d_sample_t;
+
+static drmp3_int16 drmp3d_scale_pcm(float sample)
+{
+ drmp3_int16 s;
+#if DRMP3_HAVE_ARMV6
+ drmp3_int32 s32 = (drmp3_int32)(sample + .5f);
+ s32 -= (s32 < 0);
+ s = (drmp3_int16)drmp3_clip_int16_arm(s32);
+#else
+ if (sample >= 32766.5f) return (drmp3_int16) 32767;
+ if (sample <= -32767.5f) return (drmp3_int16)-32768;
+ s = (drmp3_int16)(sample + .5f);
+ s -= (s < 0); /* away from zero, to be compliant */
+#endif
+ return s;
+}
+#else
+typedef float drmp3d_sample_t;
+
+static float drmp3d_scale_pcm(float sample)
+{
+ return sample*(1.f/32768.f);
+}
+#endif
+
+static void drmp3d_synth_pair(drmp3d_sample_t *pcm, int nch, const float *z)
+{
+ float a;
+ a = (z[14*64] - z[ 0]) * 29;
+ a += (z[ 1*64] + z[13*64]) * 213;
+ a += (z[12*64] - z[ 2*64]) * 459;
+ a += (z[ 3*64] + z[11*64]) * 2037;
+ a += (z[10*64] - z[ 4*64]) * 5153;
+ a += (z[ 5*64] + z[ 9*64]) * 6574;
+ a += (z[ 8*64] - z[ 6*64]) * 37489;
+ a += z[ 7*64] * 75038;
+ pcm[0] = drmp3d_scale_pcm(a);
+
+ z += 2;
+ a = z[14*64] * 104;
+ a += z[12*64] * 1567;
+ a += z[10*64] * 9727;
+ a += z[ 8*64] * 64019;
+ a += z[ 6*64] * -9975;
+ a += z[ 4*64] * -45;
+ a += z[ 2*64] * 146;
+ a += z[ 0*64] * -5;
+ pcm[16*nch] = drmp3d_scale_pcm(a);
+}
+
+static void drmp3d_synth(float *xl, drmp3d_sample_t *dstl, int nch, float *lins)
+{
+ int i;
+ float *xr = xl + 576*(nch - 1);
+ drmp3d_sample_t *dstr = dstl + (nch - 1);
+
+ static const float g_win[] = {
+ -1,26,-31,208,218,401,-519,2063,2000,4788,-5517,7134,5959,35640,-39336,74992,
+ -1,24,-35,202,222,347,-581,2080,1952,4425,-5879,7640,5288,33791,-41176,74856,
+ -1,21,-38,196,225,294,-645,2087,1893,4063,-6237,8092,4561,31947,-43006,74630,
+ -1,19,-41,190,227,244,-711,2085,1822,3705,-6589,8492,3776,30112,-44821,74313,
+ -1,17,-45,183,228,197,-779,2075,1739,3351,-6935,8840,2935,28289,-46617,73908,
+ -1,16,-49,176,228,153,-848,2057,1644,3004,-7271,9139,2037,26482,-48390,73415,
+ -2,14,-53,169,227,111,-919,2032,1535,2663,-7597,9389,1082,24694,-50137,72835,
+ -2,13,-58,161,224,72,-991,2001,1414,2330,-7910,9592,70,22929,-51853,72169,
+ -2,11,-63,154,221,36,-1064,1962,1280,2006,-8209,9750,-998,21189,-53534,71420,
+ -2,10,-68,147,215,2,-1137,1919,1131,1692,-8491,9863,-2122,19478,-55178,70590,
+ -3,9,-73,139,208,-29,-1210,1870,970,1388,-8755,9935,-3300,17799,-56778,69679,
+ -3,8,-79,132,200,-57,-1283,1817,794,1095,-8998,9966,-4533,16155,-58333,68692,
+ -4,7,-85,125,189,-83,-1356,1759,605,814,-9219,9959,-5818,14548,-59838,67629,
+ -4,7,-91,117,177,-106,-1428,1698,402,545,-9416,9916,-7154,12980,-61289,66494,
+ -5,6,-97,111,163,-127,-1498,1634,185,288,-9585,9838,-8540,11455,-62684,65290
+ };
+ float *zlin = lins + 15*64;
+ const float *w = g_win;
+
+ zlin[4*15] = xl[18*16];
+ zlin[4*15 + 1] = xr[18*16];
+ zlin[4*15 + 2] = xl[0];
+ zlin[4*15 + 3] = xr[0];
+
+ zlin[4*31] = xl[1 + 18*16];
+ zlin[4*31 + 1] = xr[1 + 18*16];
+ zlin[4*31 + 2] = xl[1];
+ zlin[4*31 + 3] = xr[1];
+
+ drmp3d_synth_pair(dstr, nch, lins + 4*15 + 1);
+ drmp3d_synth_pair(dstr + 32*nch, nch, lins + 4*15 + 64 + 1);
+ drmp3d_synth_pair(dstl, nch, lins + 4*15);
+ drmp3d_synth_pair(dstl + 32*nch, nch, lins + 4*15 + 64);
+
+#if DRMP3_HAVE_SIMD
+ if (drmp3_have_simd()) for (i = 14; i >= 0; i--)
+ {
+#define DRMP3_VLOAD(k) drmp3_f4 w0 = DRMP3_VSET(*w++); drmp3_f4 w1 = DRMP3_VSET(*w++); drmp3_f4 vz = DRMP3_VLD(&zlin[4*i - 64*k]); drmp3_f4 vy = DRMP3_VLD(&zlin[4*i - 64*(15 - k)]);
+#define DRMP3_V0(k) { DRMP3_VLOAD(k) b = DRMP3_VADD(DRMP3_VMUL(vz, w1), DRMP3_VMUL(vy, w0)) ; a = DRMP3_VSUB(DRMP3_VMUL(vz, w0), DRMP3_VMUL(vy, w1)); }
+#define DRMP3_V1(k) { DRMP3_VLOAD(k) b = DRMP3_VADD(b, DRMP3_VADD(DRMP3_VMUL(vz, w1), DRMP3_VMUL(vy, w0))); a = DRMP3_VADD(a, DRMP3_VSUB(DRMP3_VMUL(vz, w0), DRMP3_VMUL(vy, w1))); }
+#define DRMP3_V2(k) { DRMP3_VLOAD(k) b = DRMP3_VADD(b, DRMP3_VADD(DRMP3_VMUL(vz, w1), DRMP3_VMUL(vy, w0))); a = DRMP3_VADD(a, DRMP3_VSUB(DRMP3_VMUL(vy, w1), DRMP3_VMUL(vz, w0))); }
+ drmp3_f4 a, b;
+ zlin[4*i] = xl[18*(31 - i)];
+ zlin[4*i + 1] = xr[18*(31 - i)];
+ zlin[4*i + 2] = xl[1 + 18*(31 - i)];
+ zlin[4*i + 3] = xr[1 + 18*(31 - i)];
+ zlin[4*i + 64] = xl[1 + 18*(1 + i)];
+ zlin[4*i + 64 + 1] = xr[1 + 18*(1 + i)];
+ zlin[4*i - 64 + 2] = xl[18*(1 + i)];
+ zlin[4*i - 64 + 3] = xr[18*(1 + i)];
+
+ DRMP3_V0(0) DRMP3_V2(1) DRMP3_V1(2) DRMP3_V2(3) DRMP3_V1(4) DRMP3_V2(5) DRMP3_V1(6) DRMP3_V2(7)
+
+ {
+#ifndef DR_MP3_FLOAT_OUTPUT
+#if DRMP3_HAVE_SSE
+ static const drmp3_f4 g_max = { 32767.0f, 32767.0f, 32767.0f, 32767.0f };
+ static const drmp3_f4 g_min = { -32768.0f, -32768.0f, -32768.0f, -32768.0f };
+ __m128i pcm8 = _mm_packs_epi32(_mm_cvtps_epi32(_mm_max_ps(_mm_min_ps(a, g_max), g_min)),
+ _mm_cvtps_epi32(_mm_max_ps(_mm_min_ps(b, g_max), g_min)));
+ dstr[(15 - i)*nch] = (drmp3_int16)_mm_extract_epi16(pcm8, 1);
+ dstr[(17 + i)*nch] = (drmp3_int16)_mm_extract_epi16(pcm8, 5);
+ dstl[(15 - i)*nch] = (drmp3_int16)_mm_extract_epi16(pcm8, 0);
+ dstl[(17 + i)*nch] = (drmp3_int16)_mm_extract_epi16(pcm8, 4);
+ dstr[(47 - i)*nch] = (drmp3_int16)_mm_extract_epi16(pcm8, 3);
+ dstr[(49 + i)*nch] = (drmp3_int16)_mm_extract_epi16(pcm8, 7);
+ dstl[(47 - i)*nch] = (drmp3_int16)_mm_extract_epi16(pcm8, 2);
+ dstl[(49 + i)*nch] = (drmp3_int16)_mm_extract_epi16(pcm8, 6);
+#else
+ int16x4_t pcma, pcmb;
+ a = DRMP3_VADD(a, DRMP3_VSET(0.5f));
+ b = DRMP3_VADD(b, DRMP3_VSET(0.5f));
+ pcma = vqmovn_s32(vqaddq_s32(vcvtq_s32_f32(a), vreinterpretq_s32_u32(vcltq_f32(a, DRMP3_VSET(0)))));
+ pcmb = vqmovn_s32(vqaddq_s32(vcvtq_s32_f32(b), vreinterpretq_s32_u32(vcltq_f32(b, DRMP3_VSET(0)))));
+ vst1_lane_s16(dstr + (15 - i)*nch, pcma, 1);
+ vst1_lane_s16(dstr + (17 + i)*nch, pcmb, 1);
+ vst1_lane_s16(dstl + (15 - i)*nch, pcma, 0);
+ vst1_lane_s16(dstl + (17 + i)*nch, pcmb, 0);
+ vst1_lane_s16(dstr + (47 - i)*nch, pcma, 3);
+ vst1_lane_s16(dstr + (49 + i)*nch, pcmb, 3);
+ vst1_lane_s16(dstl + (47 - i)*nch, pcma, 2);
+ vst1_lane_s16(dstl + (49 + i)*nch, pcmb, 2);
+#endif
+#else
+ #if DRMP3_HAVE_SSE
+ static const drmp3_f4 g_scale = { 1.0f/32768.0f, 1.0f/32768.0f, 1.0f/32768.0f, 1.0f/32768.0f };
+ #else
+ const drmp3_f4 g_scale = vdupq_n_f32(1.0f/32768.0f);
+ #endif
+ a = DRMP3_VMUL(a, g_scale);
+ b = DRMP3_VMUL(b, g_scale);
+#if DRMP3_HAVE_SSE
+ _mm_store_ss(dstr + (15 - i)*nch, _mm_shuffle_ps(a, a, _MM_SHUFFLE(1, 1, 1, 1)));
+ _mm_store_ss(dstr + (17 + i)*nch, _mm_shuffle_ps(b, b, _MM_SHUFFLE(1, 1, 1, 1)));
+ _mm_store_ss(dstl + (15 - i)*nch, _mm_shuffle_ps(a, a, _MM_SHUFFLE(0, 0, 0, 0)));
+ _mm_store_ss(dstl + (17 + i)*nch, _mm_shuffle_ps(b, b, _MM_SHUFFLE(0, 0, 0, 0)));
+ _mm_store_ss(dstr + (47 - i)*nch, _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 3, 3, 3)));
+ _mm_store_ss(dstr + (49 + i)*nch, _mm_shuffle_ps(b, b, _MM_SHUFFLE(3, 3, 3, 3)));
+ _mm_store_ss(dstl + (47 - i)*nch, _mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 2, 2, 2)));
+ _mm_store_ss(dstl + (49 + i)*nch, _mm_shuffle_ps(b, b, _MM_SHUFFLE(2, 2, 2, 2)));
+#else
+ vst1q_lane_f32(dstr + (15 - i)*nch, a, 1);
+ vst1q_lane_f32(dstr + (17 + i)*nch, b, 1);
+ vst1q_lane_f32(dstl + (15 - i)*nch, a, 0);
+ vst1q_lane_f32(dstl + (17 + i)*nch, b, 0);
+ vst1q_lane_f32(dstr + (47 - i)*nch, a, 3);
+ vst1q_lane_f32(dstr + (49 + i)*nch, b, 3);
+ vst1q_lane_f32(dstl + (47 - i)*nch, a, 2);
+ vst1q_lane_f32(dstl + (49 + i)*nch, b, 2);
+#endif
+#endif /* DR_MP3_FLOAT_OUTPUT */
+ }
+ } else
+#endif
+#ifdef DR_MP3_ONLY_SIMD
+ {} /* for HAVE_SIMD=1, MINIMP3_ONLY_SIMD=1 case we do not need non-intrinsic "else" branch */
+#else
+ for (i = 14; i >= 0; i--)
+ {
+#define DRMP3_LOAD(k) float w0 = *w++; float w1 = *w++; float *vz = &zlin[4*i - k*64]; float *vy = &zlin[4*i - (15 - k)*64];
+#define DRMP3_S0(k) { int j; DRMP3_LOAD(k); for (j = 0; j < 4; j++) b[j] = vz[j]*w1 + vy[j]*w0, a[j] = vz[j]*w0 - vy[j]*w1; }
+#define DRMP3_S1(k) { int j; DRMP3_LOAD(k); for (j = 0; j < 4; j++) b[j] += vz[j]*w1 + vy[j]*w0, a[j] += vz[j]*w0 - vy[j]*w1; }
+#define DRMP3_S2(k) { int j; DRMP3_LOAD(k); for (j = 0; j < 4; j++) b[j] += vz[j]*w1 + vy[j]*w0, a[j] += vy[j]*w1 - vz[j]*w0; }
+ float a[4], b[4];
+
+ zlin[4*i] = xl[18*(31 - i)];
+ zlin[4*i + 1] = xr[18*(31 - i)];
+ zlin[4*i + 2] = xl[1 + 18*(31 - i)];
+ zlin[4*i + 3] = xr[1 + 18*(31 - i)];
+ zlin[4*(i + 16)] = xl[1 + 18*(1 + i)];
+ zlin[4*(i + 16) + 1] = xr[1 + 18*(1 + i)];
+ zlin[4*(i - 16) + 2] = xl[18*(1 + i)];
+ zlin[4*(i - 16) + 3] = xr[18*(1 + i)];
+
+ DRMP3_S0(0) DRMP3_S2(1) DRMP3_S1(2) DRMP3_S2(3) DRMP3_S1(4) DRMP3_S2(5) DRMP3_S1(6) DRMP3_S2(7)
+
+ dstr[(15 - i)*nch] = drmp3d_scale_pcm(a[1]);
+ dstr[(17 + i)*nch] = drmp3d_scale_pcm(b[1]);
+ dstl[(15 - i)*nch] = drmp3d_scale_pcm(a[0]);
+ dstl[(17 + i)*nch] = drmp3d_scale_pcm(b[0]);
+ dstr[(47 - i)*nch] = drmp3d_scale_pcm(a[3]);
+ dstr[(49 + i)*nch] = drmp3d_scale_pcm(b[3]);
+ dstl[(47 - i)*nch] = drmp3d_scale_pcm(a[2]);
+ dstl[(49 + i)*nch] = drmp3d_scale_pcm(b[2]);
+ }
+#endif
+}
+
+static void drmp3d_synth_granule(float *qmf_state, float *grbuf, int nbands, int nch, drmp3d_sample_t *pcm, float *lins)
+{
+ int i;
+ for (i = 0; i < nch; i++)
+ {
+ drmp3d_DCT_II(grbuf + 576*i, nbands);
+ }
+
+ DRMP3_COPY_MEMORY(lins, qmf_state, sizeof(float)*15*64);
+
+ for (i = 0; i < nbands; i += 2)
+ {
+ drmp3d_synth(grbuf + i, pcm + 32*nch*i, nch, lins + i*64);
+ }
+#ifndef DR_MP3_NONSTANDARD_BUT_LOGICAL
+ if (nch == 1)
+ {
+ for (i = 0; i < 15*64; i += 2)
+ {
+ qmf_state[i] = lins[nbands*64 + i];
+ }
+ } else
+#endif
+ {
+ DRMP3_COPY_MEMORY(qmf_state, lins + nbands*64, sizeof(float)*15*64);
+ }
+}
+
+static int drmp3d_match_frame(const drmp3_uint8 *hdr, int mp3_bytes, int frame_bytes)
+{
+ int i, nmatch;
+ for (i = 0, nmatch = 0; nmatch < DRMP3_MAX_FRAME_SYNC_MATCHES; nmatch++)
+ {
+ i += drmp3_hdr_frame_bytes(hdr + i, frame_bytes) + drmp3_hdr_padding(hdr + i);
+ if (i + DRMP3_HDR_SIZE > mp3_bytes)
+ return nmatch > 0;
+ if (!drmp3_hdr_compare(hdr, hdr + i))
+ return 0;
+ }
+ return 1;
+}
+
+static int drmp3d_find_frame(const drmp3_uint8 *mp3, int mp3_bytes, int *free_format_bytes, int *ptr_frame_bytes)
+{
+ int i, k;
+ for (i = 0; i < mp3_bytes - DRMP3_HDR_SIZE; i++, mp3++)
+ {
+ if (drmp3_hdr_valid(mp3))
+ {
+ int frame_bytes = drmp3_hdr_frame_bytes(mp3, *free_format_bytes);
+ int frame_and_padding = frame_bytes + drmp3_hdr_padding(mp3);
+
+ for (k = DRMP3_HDR_SIZE; !frame_bytes && k < DRMP3_MAX_FREE_FORMAT_FRAME_SIZE && i + 2*k < mp3_bytes - DRMP3_HDR_SIZE; k++)
+ {
+ if (drmp3_hdr_compare(mp3, mp3 + k))
+ {
+ int fb = k - drmp3_hdr_padding(mp3);
+ int nextfb = fb + drmp3_hdr_padding(mp3 + k);
+ if (i + k + nextfb + DRMP3_HDR_SIZE > mp3_bytes || !drmp3_hdr_compare(mp3, mp3 + k + nextfb))
+ continue;
+ frame_and_padding = k;
+ frame_bytes = fb;
+ *free_format_bytes = fb;
+ }
+ }
+
+ if ((frame_bytes && i + frame_and_padding <= mp3_bytes &&
+ drmp3d_match_frame(mp3, mp3_bytes - i, frame_bytes)) ||
+ (!i && frame_and_padding == mp3_bytes))
+ {
+ *ptr_frame_bytes = frame_and_padding;
+ return i;
+ }
+ *free_format_bytes = 0;
+ }
+ }
+ *ptr_frame_bytes = 0;
+ return mp3_bytes;
+}
+
+DRMP3_API void drmp3dec_init(drmp3dec *dec)
+{
+ dec->header[0] = 0;
+}
+
+DRMP3_API int drmp3dec_decode_frame(drmp3dec *dec, const drmp3_uint8 *mp3, int mp3_bytes, void *pcm, drmp3dec_frame_info *info)
+{
+ 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))
+ {
+ frame_size = drmp3_hdr_frame_bytes(mp3, dec->free_format_bytes) + drmp3_hdr_padding(mp3);
+ if (frame_size != mp3_bytes && (frame_size + DRMP3_HDR_SIZE > mp3_bytes || !drmp3_hdr_compare(mp3, mp3 + frame_size)))
+ {
+ frame_size = 0;
+ }
+ }
+ if (!frame_size)
+ {
+ DRMP3_ZERO_MEMORY(dec, sizeof(drmp3dec));
+ i = drmp3d_find_frame(mp3, mp3_bytes, &dec->free_format_bytes, &frame_size);
+ if (!frame_size || i + frame_size > mp3_bytes)
+ {
+ info->frame_bytes = i;
+ return 0;
+ }
+ }
+
+ hdr = mp3 + i;
+ DRMP3_COPY_MEMORY(dec->header, hdr, DRMP3_HDR_SIZE);
+ info->frame_bytes = i + frame_size;
+ info->channels = DRMP3_HDR_IS_MONO(hdr) ? 1 : 2;
+ info->hz = drmp3_hdr_sample_rate_hz(hdr);
+ info->layer = 4 - DRMP3_HDR_GET_LAYER(hdr);
+ info->bitrate_kbps = drmp3_hdr_bitrate_kbps(hdr);
+
+ drmp3_bs_init(bs_frame, hdr + DRMP3_HDR_SIZE, frame_size - DRMP3_HDR_SIZE);
+ if (DRMP3_HDR_IS_CRC(hdr))
+ {
+ drmp3_bs_get_bits(bs_frame, 16);
+ }
+
+ if (info->layer == 3)
+ {
+ int main_data_begin = drmp3_L3_read_side_info(bs_frame, 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);
+ 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_L3_save_reservoir(dec, &scratch);
+ } else
+ {
+#ifdef DR_MP3_ONLY_MP3
+ return 0;
+#else
+ drmp3_L12_scale_info sci[1];
+
+ if (pcm == NULL) {
+ return drmp3_hdr_frame_samples(hdr);
+ }
+
+ drmp3_L12_read_scale_info(hdr, bs_frame, sci);
+
+ DRMP3_ZERO_MEMORY(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)))
+ {
+ 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));
+ pcm = DRMP3_OFFSET_PTR(pcm, sizeof(drmp3d_sample_t)*384*info->channels);
+ }
+ if (bs_frame->pos > bs_frame->limit)
+ {
+ drmp3dec_init(dec);
+ return 0;
+ }
+ }
+#endif
+ }
+
+ return success*drmp3_hdr_frame_samples(dec->header);
+}
+
+DRMP3_API void drmp3dec_f32_to_s16(const float *in, drmp3_int16 *out, size_t num_samples)
+{
+ size_t i = 0;
+#if DRMP3_HAVE_SIMD
+ size_t aligned_count = num_samples & ~7;
+ for(; i < aligned_count; i+=8)
+ {
+ drmp3_f4 scale = DRMP3_VSET(32768.0f);
+ drmp3_f4 a = DRMP3_VMUL(DRMP3_VLD(&in[i ]), scale);
+ drmp3_f4 b = DRMP3_VMUL(DRMP3_VLD(&in[i+4]), scale);
+#if DRMP3_HAVE_SSE
+ drmp3_f4 s16max = DRMP3_VSET( 32767.0f);
+ drmp3_f4 s16min = DRMP3_VSET(-32768.0f);
+ __m128i pcm8 = _mm_packs_epi32(_mm_cvtps_epi32(_mm_max_ps(_mm_min_ps(a, s16max), s16min)),
+ _mm_cvtps_epi32(_mm_max_ps(_mm_min_ps(b, s16max), s16min)));
+ out[i ] = (drmp3_int16)_mm_extract_epi16(pcm8, 0);
+ out[i+1] = (drmp3_int16)_mm_extract_epi16(pcm8, 1);
+ out[i+2] = (drmp3_int16)_mm_extract_epi16(pcm8, 2);
+ out[i+3] = (drmp3_int16)_mm_extract_epi16(pcm8, 3);
+ out[i+4] = (drmp3_int16)_mm_extract_epi16(pcm8, 4);
+ out[i+5] = (drmp3_int16)_mm_extract_epi16(pcm8, 5);
+ out[i+6] = (drmp3_int16)_mm_extract_epi16(pcm8, 6);
+ out[i+7] = (drmp3_int16)_mm_extract_epi16(pcm8, 7);
+#else
+ int16x4_t pcma, pcmb;
+ a = DRMP3_VADD(a, DRMP3_VSET(0.5f));
+ b = DRMP3_VADD(b, DRMP3_VSET(0.5f));
+ pcma = vqmovn_s32(vqaddq_s32(vcvtq_s32_f32(a), vreinterpretq_s32_u32(vcltq_f32(a, DRMP3_VSET(0)))));
+ pcmb = vqmovn_s32(vqaddq_s32(vcvtq_s32_f32(b), vreinterpretq_s32_u32(vcltq_f32(b, DRMP3_VSET(0)))));
+ vst1_lane_s16(out+i , pcma, 0);
+ vst1_lane_s16(out+i+1, pcma, 1);
+ vst1_lane_s16(out+i+2, pcma, 2);
+ vst1_lane_s16(out+i+3, pcma, 3);
+ vst1_lane_s16(out+i+4, pcmb, 0);
+ vst1_lane_s16(out+i+5, pcmb, 1);
+ vst1_lane_s16(out+i+6, pcmb, 2);
+ vst1_lane_s16(out+i+7, pcmb, 3);
+#endif
+ }
+#endif
+ for(; i < num_samples; i++)
+ {
+ float sample = in[i] * 32768.0f;
+ if (sample >= 32766.5f)
+ out[i] = (drmp3_int16) 32767;
+ else if (sample <= -32767.5f)
+ out[i] = (drmp3_int16)-32768;
+ else
+ {
+ short s = (drmp3_int16)(sample + .5f);
+ s -= (s < 0); /* away from zero, to be compliant */
+ out[i] = s;
+ }
+ }
+}
+
+
+
+/************************************************************************************************************************************************************
+
+ Main Public API
+
+ ************************************************************************************************************************************************************/
+/* SIZE_MAX */
+#if defined(SIZE_MAX)
+ #define DRMP3_SIZE_MAX SIZE_MAX
+#else
+ #if defined(_WIN64) || defined(_LP64) || defined(__LP64__)
+ #define DRMP3_SIZE_MAX ((drmp3_uint64)0xFFFFFFFFFFFFFFFF)
+ #else
+ #define DRMP3_SIZE_MAX 0xFFFFFFFF
+ #endif
+#endif
+/* End SIZE_MAX */
+
+/* Options. */
+#ifndef DRMP3_SEEK_LEADING_MP3_FRAMES
+#define DRMP3_SEEK_LEADING_MP3_FRAMES 2
+#endif
+
+#define DRMP3_MIN_DATA_CHUNK_SIZE 16384
+
+/* The size in bytes of each chunk of data to read from the MP3 stream. minimp3 recommends at least 16K, but in an attempt to reduce data movement I'm making this slightly larger. */
+#ifndef DRMP3_DATA_CHUNK_SIZE
+#define DRMP3_DATA_CHUNK_SIZE (DRMP3_MIN_DATA_CHUNK_SIZE*4)
+#endif
+
+
+#define DRMP3_COUNTOF(x) (sizeof(x) / sizeof(x[0]))
+#define DRMP3_CLAMP(x, lo, hi) (DRMP3_MAX(lo, DRMP3_MIN(x, hi)))
+
+#ifndef DRMP3_PI_D
+#define DRMP3_PI_D 3.14159265358979323846264
+#endif
+
+#define DRMP3_DEFAULT_RESAMPLER_LPF_ORDER 2
+
+static DRMP3_INLINE float drmp3_mix_f32(float x, float y, float a)
+{
+ return x*(1-a) + y*a;
+}
+static DRMP3_INLINE float drmp3_mix_f32_fast(float x, float y, float a)
+{
+ float r0 = (y - x);
+ float r1 = r0*a;
+ return x + r1;
+ /*return x + (y - x)*a;*/
+}
+
+
+/*
+Greatest common factor using Euclid's algorithm iteratively.
+*/
+static DRMP3_INLINE drmp3_uint32 drmp3_gcf_u32(drmp3_uint32 a, drmp3_uint32 b)
+{
+ for (;;) {
+ if (b == 0) {
+ break;
+ } else {
+ drmp3_uint32 t = a;
+ a = b;
+ b = t % a;
+ }
+ }
+
+ return a;
+}
+
+
+static void* drmp3__malloc_default(size_t sz, void* pUserData)
+{
+ (void)pUserData;
+ return DRMP3_MALLOC(sz);
+}
+
+static void* drmp3__realloc_default(void* p, size_t sz, void* pUserData)
+{
+ (void)pUserData;
+ return DRMP3_REALLOC(p, sz);
+}
+
+static void drmp3__free_default(void* p, void* pUserData)
+{
+ (void)pUserData;
+ DRMP3_FREE(p);
+}
+
+
+static void* drmp3__malloc_from_callbacks(size_t sz, const drmp3_allocation_callbacks* pAllocationCallbacks)
+{
+ if (pAllocationCallbacks == NULL) {
+ return NULL;
+ }
+
+ if (pAllocationCallbacks->onMalloc != NULL) {
+ return pAllocationCallbacks->onMalloc(sz, pAllocationCallbacks->pUserData);
+ }
+
+ /* Try using realloc(). */
+ if (pAllocationCallbacks->onRealloc != NULL) {
+ return pAllocationCallbacks->onRealloc(NULL, sz, pAllocationCallbacks->pUserData);
+ }
+
+ return NULL;
+}
+
+static void* drmp3__realloc_from_callbacks(void* p, size_t szNew, size_t szOld, const drmp3_allocation_callbacks* pAllocationCallbacks)
+{
+ if (pAllocationCallbacks == NULL) {
+ return NULL;
+ }
+
+ if (pAllocationCallbacks->onRealloc != NULL) {
+ return pAllocationCallbacks->onRealloc(p, szNew, pAllocationCallbacks->pUserData);
+ }
+
+ /* Try emulating realloc() in terms of malloc()/free(). */
+ if (pAllocationCallbacks->onMalloc != NULL && pAllocationCallbacks->onFree != NULL) {
+ void* p2;
+
+ p2 = pAllocationCallbacks->onMalloc(szNew, pAllocationCallbacks->pUserData);
+ if (p2 == NULL) {
+ return NULL;
+ }
+
+ if (p != NULL) {
+ DRMP3_COPY_MEMORY(p2, p, szOld);
+ pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData);
+ }
+
+ return p2;
+ }
+
+ return NULL;
+}
+
+static void drmp3__free_from_callbacks(void* p, const drmp3_allocation_callbacks* pAllocationCallbacks)
+{
+ if (p == NULL || pAllocationCallbacks == NULL) {
+ return;
+ }
+
+ if (pAllocationCallbacks->onFree != NULL) {
+ pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData);
+ }
+}
+
+
+static drmp3_allocation_callbacks drmp3_copy_allocation_callbacks_or_defaults(const drmp3_allocation_callbacks* pAllocationCallbacks)
+{
+ if (pAllocationCallbacks != NULL) {
+ /* Copy. */
+ return *pAllocationCallbacks;
+ } else {
+ /* Defaults. */
+ drmp3_allocation_callbacks allocationCallbacks;
+ allocationCallbacks.pUserData = NULL;
+ allocationCallbacks.onMalloc = drmp3__malloc_default;
+ allocationCallbacks.onRealloc = drmp3__realloc_default;
+ allocationCallbacks.onFree = drmp3__free_default;
+ return allocationCallbacks;
+ }
+}
+
+
+
+static size_t drmp3__on_read(drmp3* pMP3, void* pBufferOut, size_t bytesToRead)
+{
+ size_t bytesRead = pMP3->onRead(pMP3->pUserData, pBufferOut, bytesToRead);
+ pMP3->streamCursor += bytesRead;
+ return bytesRead;
+}
+
+static drmp3_bool32 drmp3__on_seek(drmp3* pMP3, int offset, drmp3_seek_origin origin)
+{
+ DRMP3_ASSERT(offset >= 0);
+
+ if (!pMP3->onSeek(pMP3->pUserData, offset, origin)) {
+ return DRMP3_FALSE;
+ }
+
+ if (origin == drmp3_seek_origin_start) {
+ pMP3->streamCursor = (drmp3_uint64)offset;
+ } else {
+ pMP3->streamCursor += offset;
+ }
+
+ return DRMP3_TRUE;
+}
+
+static drmp3_bool32 drmp3__on_seek_64(drmp3* pMP3, drmp3_uint64 offset, drmp3_seek_origin origin)
+{
+ if (offset <= 0x7FFFFFFF) {
+ return drmp3__on_seek(pMP3, (int)offset, origin);
+ }
+
+
+ /* Getting here "offset" is too large for a 32-bit integer. We just keep seeking forward until we hit the offset. */
+ if (!drmp3__on_seek(pMP3, 0x7FFFFFFF, drmp3_seek_origin_start)) {
+ return DRMP3_FALSE;
+ }
+
+ offset -= 0x7FFFFFFF;
+ while (offset > 0) {
+ if (offset <= 0x7FFFFFFF) {
+ if (!drmp3__on_seek(pMP3, (int)offset, drmp3_seek_origin_current)) {
+ return DRMP3_FALSE;
+ }
+ offset = 0;
+ } else {
+ if (!drmp3__on_seek(pMP3, 0x7FFFFFFF, drmp3_seek_origin_current)) {
+ return DRMP3_FALSE;
+ }
+ offset -= 0x7FFFFFFF;
+ }
+ }
+
+ return DRMP3_TRUE;
+}
+
+
+static drmp3_uint32 drmp3_decode_next_frame_ex__callbacks(drmp3* pMP3, drmp3d_sample_t* pPCMFrames)
+{
+ drmp3_uint32 pcmFramesRead = 0;
+
+ DRMP3_ASSERT(pMP3 != NULL);
+ DRMP3_ASSERT(pMP3->onRead != NULL);
+
+ if (pMP3->atEnd) {
+ return 0;
+ }
+
+ for (;;) {
+ drmp3dec_frame_info info;
+
+ /* minimp3 recommends doing data submission in chunks of at least 16K. If we don't have at least 16K bytes available, get more. */
+ if (pMP3->dataSize < DRMP3_MIN_DATA_CHUNK_SIZE) {
+ size_t bytesRead;
+
+ /* First we need to move the data down. */
+ if (pMP3->pData != NULL) {
+ DRMP3_MOVE_MEMORY(pMP3->pData, pMP3->pData + pMP3->dataConsumed, pMP3->dataSize);
+ }
+
+ pMP3->dataConsumed = 0;
+
+ if (pMP3->dataCapacity < DRMP3_DATA_CHUNK_SIZE) {
+ drmp3_uint8* pNewData;
+ size_t newDataCap;
+
+ newDataCap = DRMP3_DATA_CHUNK_SIZE;
+
+ pNewData = (drmp3_uint8*)drmp3__realloc_from_callbacks(pMP3->pData, newDataCap, pMP3->dataCapacity, &pMP3->allocationCallbacks);
+ if (pNewData == NULL) {
+ return 0; /* Out of memory. */
+ }
+
+ pMP3->pData = pNewData;
+ pMP3->dataCapacity = newDataCap;
+ }
+
+ bytesRead = drmp3__on_read(pMP3, pMP3->pData + pMP3->dataSize, (pMP3->dataCapacity - pMP3->dataSize));
+ if (bytesRead == 0) {
+ if (pMP3->dataSize == 0) {
+ pMP3->atEnd = DRMP3_TRUE;
+ return 0; /* No data. */
+ }
+ }
+
+ pMP3->dataSize += bytesRead;
+ }
+
+ if (pMP3->dataSize > INT_MAX) {
+ pMP3->atEnd = DRMP3_TRUE;
+ return 0; /* File too big. */
+ }
+
+ DRMP3_ASSERT(pMP3->pData != NULL);
+ DRMP3_ASSERT(pMP3->dataCapacity > 0);
+
+ /* Do a runtime check here to try silencing a false-positive from clang-analyzer. */
+ if (pMP3->pData == NULL) {
+ return 0;
+ }
+
+ pcmFramesRead = drmp3dec_decode_frame(&pMP3->decoder, pMP3->pData + pMP3->dataConsumed, (int)pMP3->dataSize, pPCMFrames, &info); /* <-- Safe size_t -> int conversion thanks to the check above. */
+
+ /* Consume the data. */
+ if (info.frame_bytes > 0) {
+ pMP3->dataConsumed += (size_t)info.frame_bytes;
+ pMP3->dataSize -= (size_t)info.frame_bytes;
+ }
+
+ /* pcmFramesRead will be equal to 0 if decoding failed. If it is zero and info.frame_bytes > 0 then we have successfully decoded the frame. */
+ if (pcmFramesRead > 0) {
+ pcmFramesRead = drmp3_hdr_frame_samples(pMP3->decoder.header);
+ pMP3->pcmFramesConsumedInMP3Frame = 0;
+ pMP3->pcmFramesRemainingInMP3Frame = pcmFramesRead;
+ pMP3->mp3FrameChannels = info.channels;
+ pMP3->mp3FrameSampleRate = info.hz;
+ break;
+ } else if (info.frame_bytes == 0) {
+ /* Need more data. minimp3 recommends doing data submission in 16K chunks. */
+ size_t bytesRead;
+
+ /* First we need to move the data down. */
+ DRMP3_MOVE_MEMORY(pMP3->pData, pMP3->pData + pMP3->dataConsumed, pMP3->dataSize);
+ pMP3->dataConsumed = 0;
+
+ if (pMP3->dataCapacity == pMP3->dataSize) {
+ /* No room. Expand. */
+ drmp3_uint8* pNewData;
+ size_t newDataCap;
+
+ newDataCap = pMP3->dataCapacity + DRMP3_DATA_CHUNK_SIZE;
+
+ pNewData = (drmp3_uint8*)drmp3__realloc_from_callbacks(pMP3->pData, newDataCap, pMP3->dataCapacity, &pMP3->allocationCallbacks);
+ if (pNewData == NULL) {
+ return 0; /* Out of memory. */
+ }
+
+ pMP3->pData = pNewData;
+ pMP3->dataCapacity = newDataCap;
+ }
+
+ /* Fill in a chunk. */
+ bytesRead = drmp3__on_read(pMP3, pMP3->pData + pMP3->dataSize, (pMP3->dataCapacity - pMP3->dataSize));
+ if (bytesRead == 0) {
+ pMP3->atEnd = DRMP3_TRUE;
+ return 0; /* Error reading more data. */
+ }
+
+ pMP3->dataSize += bytesRead;
+ }
+ };
+
+ return pcmFramesRead;
+}
+
+static drmp3_uint32 drmp3_decode_next_frame_ex__memory(drmp3* pMP3, drmp3d_sample_t* pPCMFrames)
+{
+ drmp3_uint32 pcmFramesRead = 0;
+ drmp3dec_frame_info info;
+
+ DRMP3_ASSERT(pMP3 != NULL);
+ DRMP3_ASSERT(pMP3->memory.pData != NULL);
+
+ if (pMP3->atEnd) {
+ return 0;
+ }
+
+ for (;;) {
+ pcmFramesRead = drmp3dec_decode_frame(&pMP3->decoder, pMP3->memory.pData + pMP3->memory.currentReadPos, (int)(pMP3->memory.dataSize - pMP3->memory.currentReadPos), pPCMFrames, &info);
+ if (pcmFramesRead > 0) {
+ pcmFramesRead = drmp3_hdr_frame_samples(pMP3->decoder.header);
+ pMP3->pcmFramesConsumedInMP3Frame = 0;
+ pMP3->pcmFramesRemainingInMP3Frame = pcmFramesRead;
+ pMP3->mp3FrameChannels = info.channels;
+ pMP3->mp3FrameSampleRate = info.hz;
+ break;
+ } else if (info.frame_bytes > 0) {
+ /* No frames were read, but it looks like we skipped past one. Read the next MP3 frame. */
+ pMP3->memory.currentReadPos += (size_t)info.frame_bytes;
+ } else {
+ /* Nothing at all was read. Abort. */
+ break;
+ }
+ }
+
+ /* Consume the data. */
+ pMP3->memory.currentReadPos += (size_t)info.frame_bytes;
+
+ return pcmFramesRead;
+}
+
+static drmp3_uint32 drmp3_decode_next_frame_ex(drmp3* pMP3, drmp3d_sample_t* pPCMFrames)
+{
+ if (pMP3->memory.pData != NULL && pMP3->memory.dataSize > 0) {
+ return drmp3_decode_next_frame_ex__memory(pMP3, pPCMFrames);
+ } else {
+ return drmp3_decode_next_frame_ex__callbacks(pMP3, pPCMFrames);
+ }
+}
+
+static drmp3_uint32 drmp3_decode_next_frame(drmp3* pMP3)
+{
+ DRMP3_ASSERT(pMP3 != NULL);
+ return drmp3_decode_next_frame_ex(pMP3, (drmp3d_sample_t*)pMP3->pcmFrames);
+}
+
+#if 0
+static drmp3_uint32 drmp3_seek_next_frame(drmp3* pMP3)
+{
+ drmp3_uint32 pcmFrameCount;
+
+ DRMP3_ASSERT(pMP3 != NULL);
+
+ pcmFrameCount = drmp3_decode_next_frame_ex(pMP3, NULL);
+ if (pcmFrameCount == 0) {
+ return 0;
+ }
+
+ /* We have essentially just skipped past the frame, so just set the remaining samples to 0. */
+ pMP3->currentPCMFrame += pcmFrameCount;
+ pMP3->pcmFramesConsumedInMP3Frame = pcmFrameCount;
+ pMP3->pcmFramesRemainingInMP3Frame = 0;
+
+ return pcmFrameCount;
+}
+#endif
+
+static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drmp3_seek_proc onSeek, void* pUserData, const drmp3_allocation_callbacks* pAllocationCallbacks)
+{
+ DRMP3_ASSERT(pMP3 != NULL);
+ DRMP3_ASSERT(onRead != NULL);
+
+ /* This function assumes the output object has already been reset to 0. Do not do that here, otherwise things will break. */
+ drmp3dec_init(&pMP3->decoder);
+
+ pMP3->onRead = onRead;
+ pMP3->onSeek = onSeek;
+ pMP3->pUserData = pUserData;
+ pMP3->allocationCallbacks = drmp3_copy_allocation_callbacks_or_defaults(pAllocationCallbacks);
+
+ if (pMP3->allocationCallbacks.onFree == NULL || (pMP3->allocationCallbacks.onMalloc == NULL && pMP3->allocationCallbacks.onRealloc == NULL)) {
+ return DRMP3_FALSE; /* Invalid allocation callbacks. */
+ }
+
+ /* Decode the first frame to confirm that it is indeed a valid MP3 stream. */
+ if (drmp3_decode_next_frame(pMP3) == 0) {
+ drmp3__free_from_callbacks(pMP3->pData, &pMP3->allocationCallbacks); /* The call above may have allocated memory. Need to make sure it's freed before aborting. */
+ return DRMP3_FALSE; /* Not a valid MP3 stream. */
+ }
+
+ pMP3->channels = pMP3->mp3FrameChannels;
+ pMP3->sampleRate = pMP3->mp3FrameSampleRate;
+
+ return DRMP3_TRUE;
+}
+
+DRMP3_API drmp3_bool32 drmp3_init(drmp3* pMP3, drmp3_read_proc onRead, drmp3_seek_proc onSeek, void* pUserData, const drmp3_allocation_callbacks* pAllocationCallbacks)
+{
+ if (pMP3 == NULL || onRead == NULL) {
+ return DRMP3_FALSE;
+ }
+
+ DRMP3_ZERO_OBJECT(pMP3);
+ return drmp3_init_internal(pMP3, onRead, onSeek, pUserData, pAllocationCallbacks);
+}
+
+
+static size_t drmp3__on_read_memory(void* pUserData, void* pBufferOut, size_t bytesToRead)
+{
+ drmp3* pMP3 = (drmp3*)pUserData;
+ size_t bytesRemaining;
+
+ DRMP3_ASSERT(pMP3 != NULL);
+ DRMP3_ASSERT(pMP3->memory.dataSize >= pMP3->memory.currentReadPos);
+
+ bytesRemaining = pMP3->memory.dataSize - pMP3->memory.currentReadPos;
+ if (bytesToRead > bytesRemaining) {
+ bytesToRead = bytesRemaining;
+ }
+
+ if (bytesToRead > 0) {
+ DRMP3_COPY_MEMORY(pBufferOut, pMP3->memory.pData + pMP3->memory.currentReadPos, bytesToRead);
+ pMP3->memory.currentReadPos += bytesToRead;
+ }
+
+ return bytesToRead;
+}
+
+static drmp3_bool32 drmp3__on_seek_memory(void* pUserData, int byteOffset, drmp3_seek_origin origin)
+{
+ drmp3* pMP3 = (drmp3*)pUserData;
+
+ DRMP3_ASSERT(pMP3 != NULL);
+
+ if (origin == drmp3_seek_origin_current) {
+ if (byteOffset > 0) {
+ if (pMP3->memory.currentReadPos + byteOffset > pMP3->memory.dataSize) {
+ byteOffset = (int)(pMP3->memory.dataSize - pMP3->memory.currentReadPos); /* Trying to seek too far forward. */
+ }
+ } else {
+ if (pMP3->memory.currentReadPos < (size_t)-byteOffset) {
+ byteOffset = -(int)pMP3->memory.currentReadPos; /* Trying to seek too far backwards. */
+ }
+ }
+
+ /* This will never underflow thanks to the clamps above. */
+ pMP3->memory.currentReadPos += byteOffset;
+ } else {
+ if ((drmp3_uint32)byteOffset <= pMP3->memory.dataSize) {
+ pMP3->memory.currentReadPos = byteOffset;
+ } else {
+ pMP3->memory.currentReadPos = pMP3->memory.dataSize; /* Trying to seek too far forward. */
+ }
+ }
+
+ return DRMP3_TRUE;
+}
+
+DRMP3_API drmp3_bool32 drmp3_init_memory(drmp3* pMP3, const void* pData, size_t dataSize, const drmp3_allocation_callbacks* pAllocationCallbacks)
+{
+ if (pMP3 == NULL) {
+ return DRMP3_FALSE;
+ }
+
+ DRMP3_ZERO_OBJECT(pMP3);
+
+ if (pData == NULL || dataSize == 0) {
+ return DRMP3_FALSE;
+ }
+
+ pMP3->memory.pData = (const drmp3_uint8*)pData;
+ pMP3->memory.dataSize = dataSize;
+ pMP3->memory.currentReadPos = 0;
+
+ return drmp3_init_internal(pMP3, drmp3__on_read_memory, drmp3__on_seek_memory, pMP3, pAllocationCallbacks);
+}
+
+
+#ifndef DR_MP3_NO_STDIO
+#include
+#include /* For wcslen(), wcsrtombs() */
+
+/* Errno */
+/* drmp3_result_from_errno() is only used inside DR_MP3_NO_STDIO for now. Move this out if it's ever used elsewhere. */
+#include
+static drmp3_result drmp3_result_from_errno(int e)
+{
+ switch (e)
+ {
+ case 0: return DRMP3_SUCCESS;
+ #ifdef EPERM
+ case EPERM: return DRMP3_INVALID_OPERATION;
+ #endif
+ #ifdef ENOENT
+ case ENOENT: return DRMP3_DOES_NOT_EXIST;
+ #endif
+ #ifdef ESRCH
+ case ESRCH: return DRMP3_DOES_NOT_EXIST;
+ #endif
+ #ifdef EINTR
+ case EINTR: return DRMP3_INTERRUPT;
+ #endif
+ #ifdef EIO
+ case EIO: return DRMP3_IO_ERROR;
+ #endif
+ #ifdef ENXIO
+ case ENXIO: return DRMP3_DOES_NOT_EXIST;
+ #endif
+ #ifdef E2BIG
+ case E2BIG: return DRMP3_INVALID_ARGS;
+ #endif
+ #ifdef ENOEXEC
+ case ENOEXEC: return DRMP3_INVALID_FILE;
+ #endif
+ #ifdef EBADF
+ case EBADF: return DRMP3_INVALID_FILE;
+ #endif
+ #ifdef ECHILD
+ case ECHILD: return DRMP3_ERROR;
+ #endif
+ #ifdef EAGAIN
+ case EAGAIN: return DRMP3_UNAVAILABLE;
+ #endif
+ #ifdef ENOMEM
+ case ENOMEM: return DRMP3_OUT_OF_MEMORY;
+ #endif
+ #ifdef EACCES
+ case EACCES: return DRMP3_ACCESS_DENIED;
+ #endif
+ #ifdef EFAULT
+ case EFAULT: return DRMP3_BAD_ADDRESS;
+ #endif
+ #ifdef ENOTBLK
+ case ENOTBLK: return DRMP3_ERROR;
+ #endif
+ #ifdef EBUSY
+ case EBUSY: return DRMP3_BUSY;
+ #endif
+ #ifdef EEXIST
+ case EEXIST: return DRMP3_ALREADY_EXISTS;
+ #endif
+ #ifdef EXDEV
+ case EXDEV: return DRMP3_ERROR;
+ #endif
+ #ifdef ENODEV
+ case ENODEV: return DRMP3_DOES_NOT_EXIST;
+ #endif
+ #ifdef ENOTDIR
+ case ENOTDIR: return DRMP3_NOT_DIRECTORY;
+ #endif
+ #ifdef EISDIR
+ case EISDIR: return DRMP3_IS_DIRECTORY;
+ #endif
+ #ifdef EINVAL
+ case EINVAL: return DRMP3_INVALID_ARGS;
+ #endif
+ #ifdef ENFILE
+ case ENFILE: return DRMP3_TOO_MANY_OPEN_FILES;
+ #endif
+ #ifdef EMFILE
+ case EMFILE: return DRMP3_TOO_MANY_OPEN_FILES;
+ #endif
+ #ifdef ENOTTY
+ case ENOTTY: return DRMP3_INVALID_OPERATION;
+ #endif
+ #ifdef ETXTBSY
+ case ETXTBSY: return DRMP3_BUSY;
+ #endif
+ #ifdef EFBIG
+ case EFBIG: return DRMP3_TOO_BIG;
+ #endif
+ #ifdef ENOSPC
+ case ENOSPC: return DRMP3_NO_SPACE;
+ #endif
+ #ifdef ESPIPE
+ case ESPIPE: return DRMP3_BAD_SEEK;
+ #endif
+ #ifdef EROFS
+ case EROFS: return DRMP3_ACCESS_DENIED;
+ #endif
+ #ifdef EMLINK
+ case EMLINK: return DRMP3_TOO_MANY_LINKS;
+ #endif
+ #ifdef EPIPE
+ case EPIPE: return DRMP3_BAD_PIPE;
+ #endif
+ #ifdef EDOM
+ case EDOM: return DRMP3_OUT_OF_RANGE;
+ #endif
+ #ifdef ERANGE
+ case ERANGE: return DRMP3_OUT_OF_RANGE;
+ #endif
+ #ifdef EDEADLK
+ case EDEADLK: return DRMP3_DEADLOCK;
+ #endif
+ #ifdef ENAMETOOLONG
+ case ENAMETOOLONG: return DRMP3_PATH_TOO_LONG;
+ #endif
+ #ifdef ENOLCK
+ case ENOLCK: return DRMP3_ERROR;
+ #endif
+ #ifdef ENOSYS
+ case ENOSYS: return DRMP3_NOT_IMPLEMENTED;
+ #endif
+ #ifdef ENOTEMPTY
+ case ENOTEMPTY: return DRMP3_DIRECTORY_NOT_EMPTY;
+ #endif
+ #ifdef ELOOP
+ case ELOOP: return DRMP3_TOO_MANY_LINKS;
+ #endif
+ #ifdef ENOMSG
+ case ENOMSG: return DRMP3_NO_MESSAGE;
+ #endif
+ #ifdef EIDRM
+ case EIDRM: return DRMP3_ERROR;
+ #endif
+ #ifdef ECHRNG
+ case ECHRNG: return DRMP3_ERROR;
+ #endif
+ #ifdef EL2NSYNC
+ case EL2NSYNC: return DRMP3_ERROR;
+ #endif
+ #ifdef EL3HLT
+ case EL3HLT: return DRMP3_ERROR;
+ #endif
+ #ifdef EL3RST
+ case EL3RST: return DRMP3_ERROR;
+ #endif
+ #ifdef ELNRNG
+ case ELNRNG: return DRMP3_OUT_OF_RANGE;
+ #endif
+ #ifdef EUNATCH
+ case EUNATCH: return DRMP3_ERROR;
+ #endif
+ #ifdef ENOCSI
+ case ENOCSI: return DRMP3_ERROR;
+ #endif
+ #ifdef EL2HLT
+ case EL2HLT: return DRMP3_ERROR;
+ #endif
+ #ifdef EBADE
+ case EBADE: return DRMP3_ERROR;
+ #endif
+ #ifdef EBADR
+ case EBADR: return DRMP3_ERROR;
+ #endif
+ #ifdef EXFULL
+ case EXFULL: return DRMP3_ERROR;
+ #endif
+ #ifdef ENOANO
+ case ENOANO: return DRMP3_ERROR;
+ #endif
+ #ifdef EBADRQC
+ case EBADRQC: return DRMP3_ERROR;
+ #endif
+ #ifdef EBADSLT
+ case EBADSLT: return DRMP3_ERROR;
+ #endif
+ #ifdef EBFONT
+ case EBFONT: return DRMP3_INVALID_FILE;
+ #endif
+ #ifdef ENOSTR
+ case ENOSTR: return DRMP3_ERROR;
+ #endif
+ #ifdef ENODATA
+ case ENODATA: return DRMP3_NO_DATA_AVAILABLE;
+ #endif
+ #ifdef ETIME
+ case ETIME: return DRMP3_TIMEOUT;
+ #endif
+ #ifdef ENOSR
+ case ENOSR: return DRMP3_NO_DATA_AVAILABLE;
+ #endif
+ #ifdef ENONET
+ case ENONET: return DRMP3_NO_NETWORK;
+ #endif
+ #ifdef ENOPKG
+ case ENOPKG: return DRMP3_ERROR;
+ #endif
+ #ifdef EREMOTE
+ case EREMOTE: return DRMP3_ERROR;
+ #endif
+ #ifdef ENOLINK
+ case ENOLINK: return DRMP3_ERROR;
+ #endif
+ #ifdef EADV
+ case EADV: return DRMP3_ERROR;
+ #endif
+ #ifdef ESRMNT
+ case ESRMNT: return DRMP3_ERROR;
+ #endif
+ #ifdef ECOMM
+ case ECOMM: return DRMP3_ERROR;
+ #endif
+ #ifdef EPROTO
+ case EPROTO: return DRMP3_ERROR;
+ #endif
+ #ifdef EMULTIHOP
+ case EMULTIHOP: return DRMP3_ERROR;
+ #endif
+ #ifdef EDOTDOT
+ case EDOTDOT: return DRMP3_ERROR;
+ #endif
+ #ifdef EBADMSG
+ case EBADMSG: return DRMP3_BAD_MESSAGE;
+ #endif
+ #ifdef EOVERFLOW
+ case EOVERFLOW: return DRMP3_TOO_BIG;
+ #endif
+ #ifdef ENOTUNIQ
+ case ENOTUNIQ: return DRMP3_NOT_UNIQUE;
+ #endif
+ #ifdef EBADFD
+ case EBADFD: return DRMP3_ERROR;
+ #endif
+ #ifdef EREMCHG
+ case EREMCHG: return DRMP3_ERROR;
+ #endif
+ #ifdef ELIBACC
+ case ELIBACC: return DRMP3_ACCESS_DENIED;
+ #endif
+ #ifdef ELIBBAD
+ case ELIBBAD: return DRMP3_INVALID_FILE;
+ #endif
+ #ifdef ELIBSCN
+ case ELIBSCN: return DRMP3_INVALID_FILE;
+ #endif
+ #ifdef ELIBMAX
+ case ELIBMAX: return DRMP3_ERROR;
+ #endif
+ #ifdef ELIBEXEC
+ case ELIBEXEC: return DRMP3_ERROR;
+ #endif
+ #ifdef EILSEQ
+ case EILSEQ: return DRMP3_INVALID_DATA;
+ #endif
+ #ifdef ERESTART
+ case ERESTART: return DRMP3_ERROR;
+ #endif
+ #ifdef ESTRPIPE
+ case ESTRPIPE: return DRMP3_ERROR;
+ #endif
+ #ifdef EUSERS
+ case EUSERS: return DRMP3_ERROR;
+ #endif
+ #ifdef ENOTSOCK
+ case ENOTSOCK: return DRMP3_NOT_SOCKET;
+ #endif
+ #ifdef EDESTADDRREQ
+ case EDESTADDRREQ: return DRMP3_NO_ADDRESS;
+ #endif
+ #ifdef EMSGSIZE
+ case EMSGSIZE: return DRMP3_TOO_BIG;
+ #endif
+ #ifdef EPROTOTYPE
+ case EPROTOTYPE: return DRMP3_BAD_PROTOCOL;
+ #endif
+ #ifdef ENOPROTOOPT
+ case ENOPROTOOPT: return DRMP3_PROTOCOL_UNAVAILABLE;
+ #endif
+ #ifdef EPROTONOSUPPORT
+ case EPROTONOSUPPORT: return DRMP3_PROTOCOL_NOT_SUPPORTED;
+ #endif
+ #ifdef ESOCKTNOSUPPORT
+ case ESOCKTNOSUPPORT: return DRMP3_SOCKET_NOT_SUPPORTED;
+ #endif
+ #ifdef EOPNOTSUPP
+ case EOPNOTSUPP: return DRMP3_INVALID_OPERATION;
+ #endif
+ #ifdef EPFNOSUPPORT
+ case EPFNOSUPPORT: return DRMP3_PROTOCOL_FAMILY_NOT_SUPPORTED;
+ #endif
+ #ifdef EAFNOSUPPORT
+ case EAFNOSUPPORT: return DRMP3_ADDRESS_FAMILY_NOT_SUPPORTED;
+ #endif
+ #ifdef EADDRINUSE
+ case EADDRINUSE: return DRMP3_ALREADY_IN_USE;
+ #endif
+ #ifdef EADDRNOTAVAIL
+ case EADDRNOTAVAIL: return DRMP3_ERROR;
+ #endif
+ #ifdef ENETDOWN
+ case ENETDOWN: return DRMP3_NO_NETWORK;
+ #endif
+ #ifdef ENETUNREACH
+ case ENETUNREACH: return DRMP3_NO_NETWORK;
+ #endif
+ #ifdef ENETRESET
+ case ENETRESET: return DRMP3_NO_NETWORK;
+ #endif
+ #ifdef ECONNABORTED
+ case ECONNABORTED: return DRMP3_NO_NETWORK;
+ #endif
+ #ifdef ECONNRESET
+ case ECONNRESET: return DRMP3_CONNECTION_RESET;
+ #endif
+ #ifdef ENOBUFS
+ case ENOBUFS: return DRMP3_NO_SPACE;
+ #endif
+ #ifdef EISCONN
+ case EISCONN: return DRMP3_ALREADY_CONNECTED;
+ #endif
+ #ifdef ENOTCONN
+ case ENOTCONN: return DRMP3_NOT_CONNECTED;
+ #endif
+ #ifdef ESHUTDOWN
+ case ESHUTDOWN: return DRMP3_ERROR;
+ #endif
+ #ifdef ETOOMANYREFS
+ case ETOOMANYREFS: return DRMP3_ERROR;
+ #endif
+ #ifdef ETIMEDOUT
+ case ETIMEDOUT: return DRMP3_TIMEOUT;
+ #endif
+ #ifdef ECONNREFUSED
+ case ECONNREFUSED: return DRMP3_CONNECTION_REFUSED;
+ #endif
+ #ifdef EHOSTDOWN
+ case EHOSTDOWN: return DRMP3_NO_HOST;
+ #endif
+ #ifdef EHOSTUNREACH
+ case EHOSTUNREACH: return DRMP3_NO_HOST;
+ #endif
+ #ifdef EALREADY
+ case EALREADY: return DRMP3_IN_PROGRESS;
+ #endif
+ #ifdef EINPROGRESS
+ case EINPROGRESS: return DRMP3_IN_PROGRESS;
+ #endif
+ #ifdef ESTALE
+ case ESTALE: return DRMP3_INVALID_FILE;
+ #endif
+ #ifdef EUCLEAN
+ case EUCLEAN: return DRMP3_ERROR;
+ #endif
+ #ifdef ENOTNAM
+ case ENOTNAM: return DRMP3_ERROR;
+ #endif
+ #ifdef ENAVAIL
+ case ENAVAIL: return DRMP3_ERROR;
+ #endif
+ #ifdef EISNAM
+ case EISNAM: return DRMP3_ERROR;
+ #endif
+ #ifdef EREMOTEIO
+ case EREMOTEIO: return DRMP3_IO_ERROR;
+ #endif
+ #ifdef EDQUOT
+ case EDQUOT: return DRMP3_NO_SPACE;
+ #endif
+ #ifdef ENOMEDIUM
+ case ENOMEDIUM: return DRMP3_DOES_NOT_EXIST;
+ #endif
+ #ifdef EMEDIUMTYPE
+ case EMEDIUMTYPE: return DRMP3_ERROR;
+ #endif
+ #ifdef ECANCELED
+ case ECANCELED: return DRMP3_CANCELLED;
+ #endif
+ #ifdef ENOKEY
+ case ENOKEY: return DRMP3_ERROR;
+ #endif
+ #ifdef EKEYEXPIRED
+ case EKEYEXPIRED: return DRMP3_ERROR;
+ #endif
+ #ifdef EKEYREVOKED
+ case EKEYREVOKED: return DRMP3_ERROR;
+ #endif
+ #ifdef EKEYREJECTED
+ case EKEYREJECTED: return DRMP3_ERROR;
+ #endif
+ #ifdef EOWNERDEAD
+ case EOWNERDEAD: return DRMP3_ERROR;
+ #endif
+ #ifdef ENOTRECOVERABLE
+ case ENOTRECOVERABLE: return DRMP3_ERROR;
+ #endif
+ #ifdef ERFKILL
+ case ERFKILL: return DRMP3_ERROR;
+ #endif
+ #ifdef EHWPOISON
+ case EHWPOISON: return DRMP3_ERROR;
+ #endif
+ default: return DRMP3_ERROR;
+ }
+}
+/* End Errno */
+
+/* fopen */
+static drmp3_result drmp3_fopen(FILE** ppFile, const char* pFilePath, const char* pOpenMode)
+{
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+ errno_t err;
+#endif
+
+ if (ppFile != NULL) {
+ *ppFile = NULL; /* Safety. */
+ }
+
+ if (pFilePath == NULL || pOpenMode == NULL || ppFile == NULL) {
+ return DRMP3_INVALID_ARGS;
+ }
+
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+ err = fopen_s(ppFile, pFilePath, pOpenMode);
+ if (err != 0) {
+ return drmp3_result_from_errno(err);
+ }
+#else
+#if defined(_WIN32) || defined(__APPLE__)
+ *ppFile = fopen(pFilePath, pOpenMode);
+#else
+ #if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64 && defined(_LARGEFILE64_SOURCE)
+ *ppFile = fopen64(pFilePath, pOpenMode);
+ #else
+ *ppFile = fopen(pFilePath, pOpenMode);
+ #endif
+#endif
+ if (*ppFile == NULL) {
+ drmp3_result result = drmp3_result_from_errno(errno);
+ if (result == DRMP3_SUCCESS) {
+ result = DRMP3_ERROR; /* Just a safety check to make sure we never ever return success when pFile == NULL. */
+ }
+
+ return result;
+ }
+#endif
+
+ return DRMP3_SUCCESS;
+}
+
+/*
+_wfopen() isn't always available in all compilation environments.
+
+ * Windows only.
+ * MSVC seems to support it universally as far back as VC6 from what I can tell (haven't checked further back).
+ * MinGW-64 (both 32- and 64-bit) seems to support it.
+ * MinGW wraps it in !defined(__STRICT_ANSI__).
+ * OpenWatcom wraps it in !defined(_NO_EXT_KEYS).
+
+This can be reviewed as compatibility issues arise. The preference is to use _wfopen_s() and _wfopen() as opposed to the wcsrtombs()
+fallback, so if you notice your compiler not detecting this properly I'm happy to look at adding support.
+*/
+#if defined(_WIN32)
+ #if defined(_MSC_VER) || defined(__MINGW64__) || (!defined(__STRICT_ANSI__) && !defined(_NO_EXT_KEYS))
+ #define DRMP3_HAS_WFOPEN
+ #endif
+#endif
+
+static drmp3_result drmp3_wfopen(FILE** ppFile, const wchar_t* pFilePath, const wchar_t* pOpenMode, const drmp3_allocation_callbacks* pAllocationCallbacks)
+{
+ if (ppFile != NULL) {
+ *ppFile = NULL; /* Safety. */
+ }
+
+ if (pFilePath == NULL || pOpenMode == NULL || ppFile == NULL) {
+ return DRMP3_INVALID_ARGS;
+ }
+
+#if defined(DRMP3_HAS_WFOPEN)
+ {
+ /* Use _wfopen() on Windows. */
+ #if defined(_MSC_VER) && _MSC_VER >= 1400
+ errno_t err = _wfopen_s(ppFile, pFilePath, pOpenMode);
+ if (err != 0) {
+ return drmp3_result_from_errno(err);
+ }
+ #else
+ *ppFile = _wfopen(pFilePath, pOpenMode);
+ if (*ppFile == NULL) {
+ return drmp3_result_from_errno(errno);
+ }
+ #endif
+ (void)pAllocationCallbacks;
+ }
+#else
+ /*
+ Use fopen() on anything other than Windows. Requires a conversion. This is annoying because
+ fopen() is locale specific. The only real way I can think of to do this is with wcsrtombs(). Note
+ that wcstombs() is apparently not thread-safe because it uses a static global mbstate_t object for
+ maintaining state. I've checked this with -std=c89 and it works, but if somebody get's a compiler
+ error I'll look into improving compatibility.
+ */
+
+ /*
+ Some compilers don't support wchar_t or wcsrtombs() which we're using below. In this case we just
+ need to abort with an error. If you encounter a compiler lacking such support, add it to this list
+ and submit a bug report and it'll be added to the library upstream.
+ */
+ #if defined(__DJGPP__)
+ {
+ /* Nothing to do here. This will fall through to the error check below. */
+ }
+ #else
+ {
+ mbstate_t mbs;
+ size_t lenMB;
+ const wchar_t* pFilePathTemp = pFilePath;
+ char* pFilePathMB = NULL;
+ char pOpenModeMB[32] = {0};
+
+ /* Get the length first. */
+ DRMP3_ZERO_OBJECT(&mbs);
+ lenMB = wcsrtombs(NULL, &pFilePathTemp, 0, &mbs);
+ if (lenMB == (size_t)-1) {
+ return drmp3_result_from_errno(errno);
+ }
+
+ pFilePathMB = (char*)drmp3__malloc_from_callbacks(lenMB + 1, pAllocationCallbacks);
+ if (pFilePathMB == NULL) {
+ return DRMP3_OUT_OF_MEMORY;
+ }
+
+ pFilePathTemp = pFilePath;
+ DRMP3_ZERO_OBJECT(&mbs);
+ wcsrtombs(pFilePathMB, &pFilePathTemp, lenMB + 1, &mbs);
+
+ /* The open mode should always consist of ASCII characters so we should be able to do a trivial conversion. */
+ {
+ size_t i = 0;
+ for (;;) {
+ if (pOpenMode[i] == 0) {
+ pOpenModeMB[i] = '\0';
+ break;
+ }
+
+ pOpenModeMB[i] = (char)pOpenMode[i];
+ i += 1;
+ }
+ }
+
+ *ppFile = fopen(pFilePathMB, pOpenModeMB);
+
+ drmp3__free_from_callbacks(pFilePathMB, pAllocationCallbacks);
+ }
+ #endif
+
+ if (*ppFile == NULL) {
+ return DRMP3_ERROR;
+ }
+#endif
+
+ return DRMP3_SUCCESS;
+}
+/* End fopen */
+
+
+static size_t drmp3__on_read_stdio(void* pUserData, void* pBufferOut, size_t bytesToRead)
+{
+ return fread(pBufferOut, 1, bytesToRead, (FILE*)pUserData);
+}
+
+static drmp3_bool32 drmp3__on_seek_stdio(void* pUserData, int offset, drmp3_seek_origin origin)
+{
+ return fseek((FILE*)pUserData, offset, (origin == drmp3_seek_origin_current) ? SEEK_CUR : SEEK_SET) == 0;
+}
+
+DRMP3_API drmp3_bool32 drmp3_init_file(drmp3* pMP3, const char* pFilePath, const drmp3_allocation_callbacks* pAllocationCallbacks)
+{
+ drmp3_bool32 result;
+ FILE* pFile;
+
+ if (drmp3_fopen(&pFile, pFilePath, "rb") != DRMP3_SUCCESS) {
+ return DRMP3_FALSE;
+ }
+
+ result = drmp3_init(pMP3, drmp3__on_read_stdio, drmp3__on_seek_stdio, (void*)pFile, pAllocationCallbacks);
+ if (result != DRMP3_TRUE) {
+ fclose(pFile);
+ return result;
+ }
+
+ return DRMP3_TRUE;
+}
+
+DRMP3_API drmp3_bool32 drmp3_init_file_w(drmp3* pMP3, const wchar_t* pFilePath, const drmp3_allocation_callbacks* pAllocationCallbacks)
+{
+ drmp3_bool32 result;
+ FILE* pFile;
+
+ if (drmp3_wfopen(&pFile, pFilePath, L"rb", pAllocationCallbacks) != DRMP3_SUCCESS) {
+ return DRMP3_FALSE;
+ }
+
+ result = drmp3_init(pMP3, drmp3__on_read_stdio, drmp3__on_seek_stdio, (void*)pFile, pAllocationCallbacks);
+ if (result != DRMP3_TRUE) {
+ fclose(pFile);
+ return result;
+ }
+
+ return DRMP3_TRUE;
+}
+#endif
+
+DRMP3_API void drmp3_uninit(drmp3* pMP3)
+{
+ if (pMP3 == NULL) {
+ return;
+ }
+
+#ifndef DR_MP3_NO_STDIO
+ if (pMP3->onRead == drmp3__on_read_stdio) {
+ FILE* pFile = (FILE*)pMP3->pUserData;
+ if (pFile != NULL) {
+ fclose(pFile);
+ pMP3->pUserData = NULL; /* Make sure the file handle is cleared to NULL to we don't attempt to close it a second time. */
+ }
+ }
+#endif
+
+ drmp3__free_from_callbacks(pMP3->pData, &pMP3->allocationCallbacks);
+}
+
+#if defined(DR_MP3_FLOAT_OUTPUT)
+static void drmp3_f32_to_s16(drmp3_int16* dst, const float* src, drmp3_uint64 sampleCount)
+{
+ drmp3_uint64 i;
+ drmp3_uint64 i4;
+ drmp3_uint64 sampleCount4;
+
+ /* Unrolled. */
+ i = 0;
+ sampleCount4 = sampleCount >> 2;
+ for (i4 = 0; i4 < sampleCount4; i4 += 1) {
+ float x0 = src[i+0];
+ float x1 = src[i+1];
+ float x2 = src[i+2];
+ float x3 = src[i+3];
+
+ x0 = ((x0 < -1) ? -1 : ((x0 > 1) ? 1 : x0));
+ x1 = ((x1 < -1) ? -1 : ((x1 > 1) ? 1 : x1));
+ x2 = ((x2 < -1) ? -1 : ((x2 > 1) ? 1 : x2));
+ x3 = ((x3 < -1) ? -1 : ((x3 > 1) ? 1 : x3));
+
+ x0 = x0 * 32767.0f;
+ x1 = x1 * 32767.0f;
+ x2 = x2 * 32767.0f;
+ x3 = x3 * 32767.0f;
+
+ dst[i+0] = (drmp3_int16)x0;
+ dst[i+1] = (drmp3_int16)x1;
+ dst[i+2] = (drmp3_int16)x2;
+ dst[i+3] = (drmp3_int16)x3;
+
+ i += 4;
+ }
+
+ /* Leftover. */
+ for (; i < sampleCount; i += 1) {
+ float x = src[i];
+ x = ((x < -1) ? -1 : ((x > 1) ? 1 : x)); /* clip */
+ x = x * 32767.0f; /* -1..1 to -32767..32767 */
+
+ dst[i] = (drmp3_int16)x;
+ }
+}
+#endif
+
+#if !defined(DR_MP3_FLOAT_OUTPUT)
+static void drmp3_s16_to_f32(float* dst, const drmp3_int16* src, drmp3_uint64 sampleCount)
+{
+ drmp3_uint64 i;
+ for (i = 0; i < sampleCount; i += 1) {
+ float x = (float)src[i];
+ x = x * 0.000030517578125f; /* -32768..32767 to -1..0.999969482421875 */
+ dst[i] = x;
+ }
+}
+#endif
+
+
+static drmp3_uint64 drmp3_read_pcm_frames_raw(drmp3* pMP3, drmp3_uint64 framesToRead, void* pBufferOut)
+{
+ drmp3_uint64 totalFramesRead = 0;
+
+ DRMP3_ASSERT(pMP3 != NULL);
+ DRMP3_ASSERT(pMP3->onRead != NULL);
+
+ while (framesToRead > 0) {
+ drmp3_uint32 framesToConsume = (drmp3_uint32)DRMP3_MIN(pMP3->pcmFramesRemainingInMP3Frame, framesToRead);
+ if (pBufferOut != NULL) {
+ #if defined(DR_MP3_FLOAT_OUTPUT)
+ /* f32 */
+ float* pFramesOutF32 = (float*)DRMP3_OFFSET_PTR(pBufferOut, sizeof(float) * totalFramesRead * pMP3->channels);
+ float* pFramesInF32 = (float*)DRMP3_OFFSET_PTR(&pMP3->pcmFrames[0], sizeof(float) * pMP3->pcmFramesConsumedInMP3Frame * pMP3->mp3FrameChannels);
+ DRMP3_COPY_MEMORY(pFramesOutF32, pFramesInF32, sizeof(float) * framesToConsume * pMP3->channels);
+ #else
+ /* s16 */
+ drmp3_int16* pFramesOutS16 = (drmp3_int16*)DRMP3_OFFSET_PTR(pBufferOut, sizeof(drmp3_int16) * totalFramesRead * pMP3->channels);
+ drmp3_int16* pFramesInS16 = (drmp3_int16*)DRMP3_OFFSET_PTR(&pMP3->pcmFrames[0], sizeof(drmp3_int16) * pMP3->pcmFramesConsumedInMP3Frame * pMP3->mp3FrameChannels);
+ DRMP3_COPY_MEMORY(pFramesOutS16, pFramesInS16, sizeof(drmp3_int16) * framesToConsume * pMP3->channels);
+ #endif
+ }
+
+ pMP3->currentPCMFrame += framesToConsume;
+ pMP3->pcmFramesConsumedInMP3Frame += framesToConsume;
+ pMP3->pcmFramesRemainingInMP3Frame -= framesToConsume;
+ totalFramesRead += framesToConsume;
+ framesToRead -= framesToConsume;
+
+ if (framesToRead == 0) {
+ break;
+ }
+
+ DRMP3_ASSERT(pMP3->pcmFramesRemainingInMP3Frame == 0);
+
+ /*
+ At this point we have exhausted our in-memory buffer so we need to re-fill. Note that the sample rate may have changed
+ at this point which means we'll also need to update our sample rate conversion pipeline.
+ */
+ if (drmp3_decode_next_frame(pMP3) == 0) {
+ break;
+ }
+ }
+
+ return totalFramesRead;
+}
+
+
+DRMP3_API drmp3_uint64 drmp3_read_pcm_frames_f32(drmp3* pMP3, drmp3_uint64 framesToRead, float* pBufferOut)
+{
+ if (pMP3 == NULL || pMP3->onRead == NULL) {
+ return 0;
+ }
+
+#if defined(DR_MP3_FLOAT_OUTPUT)
+ /* Fast path. No conversion required. */
+ return drmp3_read_pcm_frames_raw(pMP3, framesToRead, pBufferOut);
+#else
+ /* Slow path. Convert from s16 to f32. */
+ {
+ drmp3_int16 pTempS16[8192];
+ drmp3_uint64 totalPCMFramesRead = 0;
+
+ while (totalPCMFramesRead < framesToRead) {
+ drmp3_uint64 framesJustRead;
+ drmp3_uint64 framesRemaining = framesToRead - totalPCMFramesRead;
+ drmp3_uint64 framesToReadNow = DRMP3_COUNTOF(pTempS16) / pMP3->channels;
+ if (framesToReadNow > framesRemaining) {
+ framesToReadNow = framesRemaining;
+ }
+
+ framesJustRead = drmp3_read_pcm_frames_raw(pMP3, framesToReadNow, pTempS16);
+ if (framesJustRead == 0) {
+ break;
+ }
+
+ drmp3_s16_to_f32((float*)DRMP3_OFFSET_PTR(pBufferOut, sizeof(float) * totalPCMFramesRead * pMP3->channels), pTempS16, framesJustRead * pMP3->channels);
+ totalPCMFramesRead += framesJustRead;
+ }
+
+ return totalPCMFramesRead;
+ }
+#endif
+}
+
+DRMP3_API drmp3_uint64 drmp3_read_pcm_frames_s16(drmp3* pMP3, drmp3_uint64 framesToRead, drmp3_int16* pBufferOut)
+{
+ if (pMP3 == NULL || pMP3->onRead == NULL) {
+ return 0;
+ }
+
+#if !defined(DR_MP3_FLOAT_OUTPUT)
+ /* Fast path. No conversion required. */
+ return drmp3_read_pcm_frames_raw(pMP3, framesToRead, pBufferOut);
+#else
+ /* Slow path. Convert from f32 to s16. */
+ {
+ float pTempF32[4096];
+ drmp3_uint64 totalPCMFramesRead = 0;
+
+ while (totalPCMFramesRead < framesToRead) {
+ drmp3_uint64 framesJustRead;
+ drmp3_uint64 framesRemaining = framesToRead - totalPCMFramesRead;
+ drmp3_uint64 framesToReadNow = DRMP3_COUNTOF(pTempF32) / pMP3->channels;
+ if (framesToReadNow > framesRemaining) {
+ framesToReadNow = framesRemaining;
+ }
+
+ framesJustRead = drmp3_read_pcm_frames_raw(pMP3, framesToReadNow, pTempF32);
+ if (framesJustRead == 0) {
+ break;
+ }
+
+ drmp3_f32_to_s16((drmp3_int16*)DRMP3_OFFSET_PTR(pBufferOut, sizeof(drmp3_int16) * totalPCMFramesRead * pMP3->channels), pTempF32, framesJustRead * pMP3->channels);
+ totalPCMFramesRead += framesJustRead;
+ }
+
+ return totalPCMFramesRead;
+ }
+#endif
+}
+
+static void drmp3_reset(drmp3* pMP3)
+{
+ DRMP3_ASSERT(pMP3 != NULL);
+
+ pMP3->pcmFramesConsumedInMP3Frame = 0;
+ pMP3->pcmFramesRemainingInMP3Frame = 0;
+ pMP3->currentPCMFrame = 0;
+ pMP3->dataSize = 0;
+ pMP3->atEnd = DRMP3_FALSE;
+ drmp3dec_init(&pMP3->decoder);
+}
+
+static drmp3_bool32 drmp3_seek_to_start_of_stream(drmp3* pMP3)
+{
+ DRMP3_ASSERT(pMP3 != NULL);
+ DRMP3_ASSERT(pMP3->onSeek != NULL);
+
+ /* Seek to the start of the stream to begin with. */
+ if (!drmp3__on_seek(pMP3, 0, drmp3_seek_origin_start)) {
+ return DRMP3_FALSE;
+ }
+
+ /* Clear any cached data. */
+ drmp3_reset(pMP3);
+ return DRMP3_TRUE;
+}
+
+
+static drmp3_bool32 drmp3_seek_forward_by_pcm_frames__brute_force(drmp3* pMP3, drmp3_uint64 frameOffset)
+{
+ drmp3_uint64 framesRead;
+
+ /*
+ Just using a dumb read-and-discard for now. What would be nice is to parse only the header of the MP3 frame, and then skip over leading
+ frames without spending the time doing a full decode. I cannot see an easy way to do this in minimp3, however, so it may involve some
+ kind of manual processing.
+ */
+#if defined(DR_MP3_FLOAT_OUTPUT)
+ framesRead = drmp3_read_pcm_frames_f32(pMP3, frameOffset, NULL);
+#else
+ framesRead = drmp3_read_pcm_frames_s16(pMP3, frameOffset, NULL);
+#endif
+ if (framesRead != frameOffset) {
+ return DRMP3_FALSE;
+ }
+
+ return DRMP3_TRUE;
+}
+
+static drmp3_bool32 drmp3_seek_to_pcm_frame__brute_force(drmp3* pMP3, drmp3_uint64 frameIndex)
+{
+ DRMP3_ASSERT(pMP3 != NULL);
+
+ if (frameIndex == pMP3->currentPCMFrame) {
+ return DRMP3_TRUE;
+ }
+
+ /*
+ If we're moving foward we just read from where we're at. Otherwise we need to move back to the start of
+ the stream and read from the beginning.
+ */
+ if (frameIndex < pMP3->currentPCMFrame) {
+ /* Moving backward. Move to the start of the stream and then move forward. */
+ if (!drmp3_seek_to_start_of_stream(pMP3)) {
+ return DRMP3_FALSE;
+ }
+ }
+
+ DRMP3_ASSERT(frameIndex >= pMP3->currentPCMFrame);
+ return drmp3_seek_forward_by_pcm_frames__brute_force(pMP3, (frameIndex - pMP3->currentPCMFrame));
+}
+
+static drmp3_bool32 drmp3_find_closest_seek_point(drmp3* pMP3, drmp3_uint64 frameIndex, drmp3_uint32* pSeekPointIndex)
+{
+ drmp3_uint32 iSeekPoint;
+
+ DRMP3_ASSERT(pSeekPointIndex != NULL);
+
+ *pSeekPointIndex = 0;
+
+ if (frameIndex < pMP3->pSeekPoints[0].pcmFrameIndex) {
+ return DRMP3_FALSE;
+ }
+
+ /* Linear search for simplicity to begin with while I'm getting this thing working. Once it's all working change this to a binary search. */
+ for (iSeekPoint = 0; iSeekPoint < pMP3->seekPointCount; ++iSeekPoint) {
+ if (pMP3->pSeekPoints[iSeekPoint].pcmFrameIndex > frameIndex) {
+ break; /* Found it. */
+ }
+
+ *pSeekPointIndex = iSeekPoint;
+ }
+
+ return DRMP3_TRUE;
+}
+
+static drmp3_bool32 drmp3_seek_to_pcm_frame__seek_table(drmp3* pMP3, drmp3_uint64 frameIndex)
+{
+ drmp3_seek_point seekPoint;
+ drmp3_uint32 priorSeekPointIndex;
+ drmp3_uint16 iMP3Frame;
+ drmp3_uint64 leftoverFrames;
+
+ DRMP3_ASSERT(pMP3 != NULL);
+ DRMP3_ASSERT(pMP3->pSeekPoints != NULL);
+ DRMP3_ASSERT(pMP3->seekPointCount > 0);
+
+ /* If there is no prior seekpoint it means the target PCM frame comes before the first seek point. Just assume a seekpoint at the start of the file in this case. */
+ if (drmp3_find_closest_seek_point(pMP3, frameIndex, &priorSeekPointIndex)) {
+ seekPoint = pMP3->pSeekPoints[priorSeekPointIndex];
+ } else {
+ seekPoint.seekPosInBytes = 0;
+ seekPoint.pcmFrameIndex = 0;
+ seekPoint.mp3FramesToDiscard = 0;
+ seekPoint.pcmFramesToDiscard = 0;
+ }
+
+ /* First thing to do is seek to the first byte of the relevant MP3 frame. */
+ if (!drmp3__on_seek_64(pMP3, seekPoint.seekPosInBytes, drmp3_seek_origin_start)) {
+ return DRMP3_FALSE; /* Failed to seek. */
+ }
+
+ /* Clear any cached data. */
+ drmp3_reset(pMP3);
+
+ /* Whole MP3 frames need to be discarded first. */
+ for (iMP3Frame = 0; iMP3Frame < seekPoint.mp3FramesToDiscard; ++iMP3Frame) {
+ drmp3_uint32 pcmFramesRead;
+ drmp3d_sample_t* pPCMFrames;
+
+ /* Pass in non-null for the last frame because we want to ensure the sample rate converter is preloaded correctly. */
+ pPCMFrames = NULL;
+ if (iMP3Frame == seekPoint.mp3FramesToDiscard-1) {
+ pPCMFrames = (drmp3d_sample_t*)pMP3->pcmFrames;
+ }
+
+ /* We first need to decode the next frame. */
+ pcmFramesRead = drmp3_decode_next_frame_ex(pMP3, pPCMFrames);
+ if (pcmFramesRead == 0) {
+ return DRMP3_FALSE;
+ }
+ }
+
+ /* We seeked to an MP3 frame in the raw stream so we need to make sure the current PCM frame is set correctly. */
+ pMP3->currentPCMFrame = seekPoint.pcmFrameIndex - seekPoint.pcmFramesToDiscard;
+
+ /*
+ Now at this point we can follow the same process as the brute force technique where we just skip over unnecessary MP3 frames and then
+ read-and-discard at least 2 whole MP3 frames.
+ */
+ leftoverFrames = frameIndex - pMP3->currentPCMFrame;
+ return drmp3_seek_forward_by_pcm_frames__brute_force(pMP3, leftoverFrames);
+}
+
+DRMP3_API drmp3_bool32 drmp3_seek_to_pcm_frame(drmp3* pMP3, drmp3_uint64 frameIndex)
+{
+ if (pMP3 == NULL || pMP3->onSeek == NULL) {
+ return DRMP3_FALSE;
+ }
+
+ if (frameIndex == 0) {
+ return drmp3_seek_to_start_of_stream(pMP3);
+ }
+
+ /* Use the seek table if we have one. */
+ if (pMP3->pSeekPoints != NULL && pMP3->seekPointCount > 0) {
+ return drmp3_seek_to_pcm_frame__seek_table(pMP3, frameIndex);
+ } else {
+ return drmp3_seek_to_pcm_frame__brute_force(pMP3, frameIndex);
+ }
+}
+
+DRMP3_API drmp3_bool32 drmp3_get_mp3_and_pcm_frame_count(drmp3* pMP3, drmp3_uint64* pMP3FrameCount, drmp3_uint64* pPCMFrameCount)
+{
+ drmp3_uint64 currentPCMFrame;
+ drmp3_uint64 totalPCMFrameCount;
+ drmp3_uint64 totalMP3FrameCount;
+
+ if (pMP3 == NULL) {
+ return DRMP3_FALSE;
+ }
+
+ /*
+ The way this works is we move back to the start of the stream, iterate over each MP3 frame and calculate the frame count based
+ on our output sample rate, the seek back to the PCM frame we were sitting on before calling this function.
+ */
+
+ /* The stream must support seeking for this to work. */
+ if (pMP3->onSeek == NULL) {
+ return DRMP3_FALSE;
+ }
+
+ /* We'll need to seek back to where we were, so grab the PCM frame we're currently sitting on so we can restore later. */
+ currentPCMFrame = pMP3->currentPCMFrame;
+
+ if (!drmp3_seek_to_start_of_stream(pMP3)) {
+ return DRMP3_FALSE;
+ }
+
+ totalPCMFrameCount = 0;
+ totalMP3FrameCount = 0;
+
+ for (;;) {
+ drmp3_uint32 pcmFramesInCurrentMP3Frame;
+
+ pcmFramesInCurrentMP3Frame = drmp3_decode_next_frame_ex(pMP3, NULL);
+ if (pcmFramesInCurrentMP3Frame == 0) {
+ break;
+ }
+
+ totalPCMFrameCount += pcmFramesInCurrentMP3Frame;
+ totalMP3FrameCount += 1;
+ }
+
+ /* Finally, we need to seek back to where we were. */
+ if (!drmp3_seek_to_start_of_stream(pMP3)) {
+ return DRMP3_FALSE;
+ }
+
+ if (!drmp3_seek_to_pcm_frame(pMP3, currentPCMFrame)) {
+ return DRMP3_FALSE;
+ }
+
+ if (pMP3FrameCount != NULL) {
+ *pMP3FrameCount = totalMP3FrameCount;
+ }
+ if (pPCMFrameCount != NULL) {
+ *pPCMFrameCount = totalPCMFrameCount;
+ }
+
+ return DRMP3_TRUE;
+}
+
+DRMP3_API drmp3_uint64 drmp3_get_pcm_frame_count(drmp3* pMP3)
+{
+ drmp3_uint64 totalPCMFrameCount;
+ if (!drmp3_get_mp3_and_pcm_frame_count(pMP3, NULL, &totalPCMFrameCount)) {
+ return 0;
+ }
+
+ return totalPCMFrameCount;
+}
+
+DRMP3_API drmp3_uint64 drmp3_get_mp3_frame_count(drmp3* pMP3)
+{
+ drmp3_uint64 totalMP3FrameCount;
+ if (!drmp3_get_mp3_and_pcm_frame_count(pMP3, &totalMP3FrameCount, NULL)) {
+ return 0;
+ }
+
+ return totalMP3FrameCount;
+}
+
+static void drmp3__accumulate_running_pcm_frame_count(drmp3* pMP3, drmp3_uint32 pcmFrameCountIn, drmp3_uint64* pRunningPCMFrameCount, float* pRunningPCMFrameCountFractionalPart)
+{
+ float srcRatio;
+ float pcmFrameCountOutF;
+ drmp3_uint32 pcmFrameCountOut;
+
+ srcRatio = (float)pMP3->mp3FrameSampleRate / (float)pMP3->sampleRate;
+ DRMP3_ASSERT(srcRatio > 0);
+
+ pcmFrameCountOutF = *pRunningPCMFrameCountFractionalPart + (pcmFrameCountIn / srcRatio);
+ pcmFrameCountOut = (drmp3_uint32)pcmFrameCountOutF;
+ *pRunningPCMFrameCountFractionalPart = pcmFrameCountOutF - pcmFrameCountOut;
+ *pRunningPCMFrameCount += pcmFrameCountOut;
+}
+
+typedef struct
+{
+ drmp3_uint64 bytePos;
+ drmp3_uint64 pcmFrameIndex; /* <-- After sample rate conversion. */
+} drmp3__seeking_mp3_frame_info;
+
+DRMP3_API drmp3_bool32 drmp3_calculate_seek_points(drmp3* pMP3, drmp3_uint32* pSeekPointCount, drmp3_seek_point* pSeekPoints)
+{
+ drmp3_uint32 seekPointCount;
+ drmp3_uint64 currentPCMFrame;
+ drmp3_uint64 totalMP3FrameCount;
+ drmp3_uint64 totalPCMFrameCount;
+
+ if (pMP3 == NULL || pSeekPointCount == NULL || pSeekPoints == NULL) {
+ return DRMP3_FALSE; /* Invalid args. */
+ }
+
+ seekPointCount = *pSeekPointCount;
+ if (seekPointCount == 0) {
+ return DRMP3_FALSE; /* The client has requested no seek points. Consider this to be invalid arguments since the client has probably not intended this. */
+ }
+
+ /* We'll need to seek back to the current sample after calculating the seekpoints so we need to go ahead and grab the current location at the top. */
+ currentPCMFrame = pMP3->currentPCMFrame;
+
+ /* We never do more than the total number of MP3 frames and we limit it to 32-bits. */
+ if (!drmp3_get_mp3_and_pcm_frame_count(pMP3, &totalMP3FrameCount, &totalPCMFrameCount)) {
+ return DRMP3_FALSE;
+ }
+
+ /* If there's less than DRMP3_SEEK_LEADING_MP3_FRAMES+1 frames we just report 1 seek point which will be the very start of the stream. */
+ if (totalMP3FrameCount < DRMP3_SEEK_LEADING_MP3_FRAMES+1) {
+ seekPointCount = 1;
+ pSeekPoints[0].seekPosInBytes = 0;
+ pSeekPoints[0].pcmFrameIndex = 0;
+ pSeekPoints[0].mp3FramesToDiscard = 0;
+ pSeekPoints[0].pcmFramesToDiscard = 0;
+ } else {
+ drmp3_uint64 pcmFramesBetweenSeekPoints;
+ drmp3__seeking_mp3_frame_info mp3FrameInfo[DRMP3_SEEK_LEADING_MP3_FRAMES+1];
+ drmp3_uint64 runningPCMFrameCount = 0;
+ float runningPCMFrameCountFractionalPart = 0;
+ drmp3_uint64 nextTargetPCMFrame;
+ drmp3_uint32 iMP3Frame;
+ drmp3_uint32 iSeekPoint;
+
+ if (seekPointCount > totalMP3FrameCount-1) {
+ seekPointCount = (drmp3_uint32)totalMP3FrameCount-1;
+ }
+
+ pcmFramesBetweenSeekPoints = totalPCMFrameCount / (seekPointCount+1);
+
+ /*
+ Here is where we actually calculate the seek points. We need to start by moving the start of the stream. We then enumerate over each
+ MP3 frame.
+ */
+ if (!drmp3_seek_to_start_of_stream(pMP3)) {
+ return DRMP3_FALSE;
+ }
+
+ /*
+ We need to cache the byte positions of the previous MP3 frames. As a new MP3 frame is iterated, we cycle the byte positions in this
+ array. The value in the first item in this array is the byte position that will be reported in the next seek point.
+ */
+
+ /* We need to initialize the array of MP3 byte positions for the leading MP3 frames. */
+ for (iMP3Frame = 0; iMP3Frame < DRMP3_SEEK_LEADING_MP3_FRAMES+1; ++iMP3Frame) {
+ drmp3_uint32 pcmFramesInCurrentMP3FrameIn;
+
+ /* The byte position of the next frame will be the stream's cursor position, minus whatever is sitting in the buffer. */
+ DRMP3_ASSERT(pMP3->streamCursor >= pMP3->dataSize);
+ mp3FrameInfo[iMP3Frame].bytePos = pMP3->streamCursor - pMP3->dataSize;
+ mp3FrameInfo[iMP3Frame].pcmFrameIndex = runningPCMFrameCount;
+
+ /* We need to get information about this frame so we can know how many samples it contained. */
+ pcmFramesInCurrentMP3FrameIn = drmp3_decode_next_frame_ex(pMP3, NULL);
+ if (pcmFramesInCurrentMP3FrameIn == 0) {
+ return DRMP3_FALSE; /* This should never happen. */
+ }
+
+ drmp3__accumulate_running_pcm_frame_count(pMP3, pcmFramesInCurrentMP3FrameIn, &runningPCMFrameCount, &runningPCMFrameCountFractionalPart);
+ }
+
+ /*
+ At this point we will have extracted the byte positions of the leading MP3 frames. We can now start iterating over each seek point and
+ calculate them.
+ */
+ nextTargetPCMFrame = 0;
+ for (iSeekPoint = 0; iSeekPoint < seekPointCount; ++iSeekPoint) {
+ nextTargetPCMFrame += pcmFramesBetweenSeekPoints;
+
+ for (;;) {
+ if (nextTargetPCMFrame < runningPCMFrameCount) {
+ /* The next seek point is in the current MP3 frame. */
+ pSeekPoints[iSeekPoint].seekPosInBytes = mp3FrameInfo[0].bytePos;
+ pSeekPoints[iSeekPoint].pcmFrameIndex = nextTargetPCMFrame;
+ pSeekPoints[iSeekPoint].mp3FramesToDiscard = DRMP3_SEEK_LEADING_MP3_FRAMES;
+ pSeekPoints[iSeekPoint].pcmFramesToDiscard = (drmp3_uint16)(nextTargetPCMFrame - mp3FrameInfo[DRMP3_SEEK_LEADING_MP3_FRAMES-1].pcmFrameIndex);
+ break;
+ } else {
+ size_t i;
+ drmp3_uint32 pcmFramesInCurrentMP3FrameIn;
+
+ /*
+ The next seek point is not in the current MP3 frame, so continue on to the next one. The first thing to do is cycle the cached
+ MP3 frame info.
+ */
+ for (i = 0; i < DRMP3_COUNTOF(mp3FrameInfo)-1; ++i) {
+ mp3FrameInfo[i] = mp3FrameInfo[i+1];
+ }
+
+ /* Cache previous MP3 frame info. */
+ mp3FrameInfo[DRMP3_COUNTOF(mp3FrameInfo)-1].bytePos = pMP3->streamCursor - pMP3->dataSize;
+ mp3FrameInfo[DRMP3_COUNTOF(mp3FrameInfo)-1].pcmFrameIndex = runningPCMFrameCount;
+
+ /*
+ Go to the next MP3 frame. This shouldn't ever fail, but just in case it does we just set the seek point and break. If it happens, it
+ should only ever do it for the last seek point.
+ */
+ pcmFramesInCurrentMP3FrameIn = drmp3_decode_next_frame_ex(pMP3, NULL);
+ if (pcmFramesInCurrentMP3FrameIn == 0) {
+ pSeekPoints[iSeekPoint].seekPosInBytes = mp3FrameInfo[0].bytePos;
+ pSeekPoints[iSeekPoint].pcmFrameIndex = nextTargetPCMFrame;
+ pSeekPoints[iSeekPoint].mp3FramesToDiscard = DRMP3_SEEK_LEADING_MP3_FRAMES;
+ pSeekPoints[iSeekPoint].pcmFramesToDiscard = (drmp3_uint16)(nextTargetPCMFrame - mp3FrameInfo[DRMP3_SEEK_LEADING_MP3_FRAMES-1].pcmFrameIndex);
+ break;
+ }
+
+ drmp3__accumulate_running_pcm_frame_count(pMP3, pcmFramesInCurrentMP3FrameIn, &runningPCMFrameCount, &runningPCMFrameCountFractionalPart);
+ }
+ }
+ }
+
+ /* Finally, we need to seek back to where we were. */
+ if (!drmp3_seek_to_start_of_stream(pMP3)) {
+ return DRMP3_FALSE;
+ }
+ if (!drmp3_seek_to_pcm_frame(pMP3, currentPCMFrame)) {
+ return DRMP3_FALSE;
+ }
+ }
+
+ *pSeekPointCount = seekPointCount;
+ return DRMP3_TRUE;
+}
+
+DRMP3_API drmp3_bool32 drmp3_bind_seek_table(drmp3* pMP3, drmp3_uint32 seekPointCount, drmp3_seek_point* pSeekPoints)
+{
+ if (pMP3 == NULL) {
+ return DRMP3_FALSE;
+ }
+
+ if (seekPointCount == 0 || pSeekPoints == NULL) {
+ /* Unbinding. */
+ pMP3->seekPointCount = 0;
+ pMP3->pSeekPoints = NULL;
+ } else {
+ /* Binding. */
+ pMP3->seekPointCount = seekPointCount;
+ pMP3->pSeekPoints = pSeekPoints;
+ }
+
+ return DRMP3_TRUE;
+}
+
+
+static float* drmp3__full_read_and_close_f32(drmp3* pMP3, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount)
+{
+ drmp3_uint64 totalFramesRead = 0;
+ drmp3_uint64 framesCapacity = 0;
+ float* pFrames = NULL;
+ float temp[4096];
+
+ DRMP3_ASSERT(pMP3 != NULL);
+
+ for (;;) {
+ drmp3_uint64 framesToReadRightNow = DRMP3_COUNTOF(temp) / pMP3->channels;
+ drmp3_uint64 framesJustRead = drmp3_read_pcm_frames_f32(pMP3, framesToReadRightNow, temp);
+ if (framesJustRead == 0) {
+ break;
+ }
+
+ /* Reallocate the output buffer if there's not enough room. */
+ if (framesCapacity < totalFramesRead + framesJustRead) {
+ drmp3_uint64 oldFramesBufferSize;
+ drmp3_uint64 newFramesBufferSize;
+ drmp3_uint64 newFramesCap;
+ float* pNewFrames;
+
+ newFramesCap = framesCapacity * 2;
+ if (newFramesCap < totalFramesRead + framesJustRead) {
+ newFramesCap = totalFramesRead + framesJustRead;
+ }
+
+ oldFramesBufferSize = framesCapacity * pMP3->channels * sizeof(float);
+ newFramesBufferSize = newFramesCap * pMP3->channels * sizeof(float);
+ if (newFramesBufferSize > (drmp3_uint64)DRMP3_SIZE_MAX) {
+ break;
+ }
+
+ 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);
+ break;
+ }
+
+ pFrames = pNewFrames;
+ framesCapacity = newFramesCap;
+ }
+
+ DRMP3_COPY_MEMORY(pFrames + totalFramesRead*pMP3->channels, temp, (size_t)(framesJustRead*pMP3->channels*sizeof(float)));
+ totalFramesRead += framesJustRead;
+
+ /* If the number of frames we asked for is less that what we actually read it means we've reached the end. */
+ if (framesJustRead != framesToReadRightNow) {
+ break;
+ }
+ }
+
+ if (pConfig != NULL) {
+ pConfig->channels = pMP3->channels;
+ pConfig->sampleRate = pMP3->sampleRate;
+ }
+
+ drmp3_uninit(pMP3);
+
+ if (pTotalFrameCount) {
+ *pTotalFrameCount = totalFramesRead;
+ }
+
+ return pFrames;
+}
+
+static drmp3_int16* drmp3__full_read_and_close_s16(drmp3* pMP3, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount)
+{
+ drmp3_uint64 totalFramesRead = 0;
+ drmp3_uint64 framesCapacity = 0;
+ drmp3_int16* pFrames = NULL;
+ drmp3_int16 temp[4096];
+
+ DRMP3_ASSERT(pMP3 != NULL);
+
+ for (;;) {
+ drmp3_uint64 framesToReadRightNow = DRMP3_COUNTOF(temp) / pMP3->channels;
+ drmp3_uint64 framesJustRead = drmp3_read_pcm_frames_s16(pMP3, framesToReadRightNow, temp);
+ if (framesJustRead == 0) {
+ break;
+ }
+
+ /* Reallocate the output buffer if there's not enough room. */
+ if (framesCapacity < totalFramesRead + framesJustRead) {
+ drmp3_uint64 newFramesBufferSize;
+ drmp3_uint64 oldFramesBufferSize;
+ drmp3_uint64 newFramesCap;
+ drmp3_int16* pNewFrames;
+
+ newFramesCap = framesCapacity * 2;
+ if (newFramesCap < totalFramesRead + framesJustRead) {
+ newFramesCap = totalFramesRead + framesJustRead;
+ }
+
+ oldFramesBufferSize = framesCapacity * pMP3->channels * sizeof(drmp3_int16);
+ newFramesBufferSize = newFramesCap * pMP3->channels * sizeof(drmp3_int16);
+ if (newFramesBufferSize > (drmp3_uint64)DRMP3_SIZE_MAX) {
+ break;
+ }
+
+ 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);
+ break;
+ }
+
+ pFrames = pNewFrames;
+ framesCapacity = newFramesCap;
+ }
+
+ DRMP3_COPY_MEMORY(pFrames + totalFramesRead*pMP3->channels, temp, (size_t)(framesJustRead*pMP3->channels*sizeof(drmp3_int16)));
+ totalFramesRead += framesJustRead;
+
+ /* If the number of frames we asked for is less that what we actually read it means we've reached the end. */
+ if (framesJustRead != framesToReadRightNow) {
+ break;
+ }
+ }
+
+ if (pConfig != NULL) {
+ pConfig->channels = pMP3->channels;
+ pConfig->sampleRate = pMP3->sampleRate;
+ }
+
+ drmp3_uninit(pMP3);
+
+ if (pTotalFrameCount) {
+ *pTotalFrameCount = totalFramesRead;
+ }
+
+ return pFrames;
+}
+
+
+DRMP3_API float* drmp3_open_and_read_pcm_frames_f32(drmp3_read_proc onRead, drmp3_seek_proc onSeek, void* pUserData, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount, const drmp3_allocation_callbacks* pAllocationCallbacks)
+{
+ drmp3 mp3;
+ if (!drmp3_init(&mp3, onRead, onSeek, pUserData, pAllocationCallbacks)) {
+ return NULL;
+ }
+
+ return drmp3__full_read_and_close_f32(&mp3, pConfig, pTotalFrameCount);
+}
+
+DRMP3_API drmp3_int16* drmp3_open_and_read_pcm_frames_s16(drmp3_read_proc onRead, drmp3_seek_proc onSeek, void* pUserData, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount, const drmp3_allocation_callbacks* pAllocationCallbacks)
+{
+ drmp3 mp3;
+ if (!drmp3_init(&mp3, onRead, onSeek, pUserData, pAllocationCallbacks)) {
+ return NULL;
+ }
+
+ return drmp3__full_read_and_close_s16(&mp3, pConfig, pTotalFrameCount);
+}
+
+
+DRMP3_API float* drmp3_open_memory_and_read_pcm_frames_f32(const void* pData, size_t dataSize, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount, const drmp3_allocation_callbacks* pAllocationCallbacks)
+{
+ drmp3 mp3;
+ if (!drmp3_init_memory(&mp3, pData, dataSize, pAllocationCallbacks)) {
+ return NULL;
+ }
+
+ return drmp3__full_read_and_close_f32(&mp3, pConfig, pTotalFrameCount);
+}
+
+DRMP3_API drmp3_int16* drmp3_open_memory_and_read_pcm_frames_s16(const void* pData, size_t dataSize, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount, const drmp3_allocation_callbacks* pAllocationCallbacks)
+{
+ drmp3 mp3;
+ if (!drmp3_init_memory(&mp3, pData, dataSize, pAllocationCallbacks)) {
+ return NULL;
+ }
+
+ return drmp3__full_read_and_close_s16(&mp3, pConfig, pTotalFrameCount);
+}
+
+
+#ifndef DR_MP3_NO_STDIO
+DRMP3_API float* drmp3_open_file_and_read_pcm_frames_f32(const char* filePath, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount, const drmp3_allocation_callbacks* pAllocationCallbacks)
+{
+ drmp3 mp3;
+ if (!drmp3_init_file(&mp3, filePath, pAllocationCallbacks)) {
+ return NULL;
+ }
+
+ return drmp3__full_read_and_close_f32(&mp3, pConfig, pTotalFrameCount);
+}
+
+DRMP3_API drmp3_int16* drmp3_open_file_and_read_pcm_frames_s16(const char* filePath, drmp3_config* pConfig, drmp3_uint64* pTotalFrameCount, const drmp3_allocation_callbacks* pAllocationCallbacks)
+{
+ drmp3 mp3;
+ if (!drmp3_init_file(&mp3, filePath, pAllocationCallbacks)) {
+ return NULL;
+ }
+
+ return drmp3__full_read_and_close_s16(&mp3, pConfig, pTotalFrameCount);
+}
+#endif
+
+DRMP3_API void* drmp3_malloc(size_t sz, const drmp3_allocation_callbacks* pAllocationCallbacks)
+{
+ if (pAllocationCallbacks != NULL) {
+ return drmp3__malloc_from_callbacks(sz, pAllocationCallbacks);
+ } else {
+ return drmp3__malloc_default(sz, NULL);
+ }
+}
+
+DRMP3_API void drmp3_free(void* p, const drmp3_allocation_callbacks* pAllocationCallbacks)
+{
+ if (pAllocationCallbacks != NULL) {
+ drmp3__free_from_callbacks(p, pAllocationCallbacks);
+ } else {
+ drmp3__free_default(p, NULL);
+ }
+}
+
+#endif /* dr_mp3_c */
+#endif /*DR_MP3_IMPLEMENTATION*/
+
+/*
+DIFFERENCES BETWEEN minimp3 AND dr_mp3
+======================================
+- First, keep in mind that minimp3 (https://github.com/lieff/minimp3) is where all the real work was done. All of the
+ code relating to the actual decoding remains mostly unmodified, apart from some namespacing changes.
+- dr_mp3 adds a pulling style API which allows you to deliver raw data via callbacks. So, rather than pushing data
+ to the decoder, the decoder _pulls_ data from your callbacks.
+- In addition to callbacks, a decoder can be initialized from a block of memory and a file.
+- The dr_mp3 pull API reads PCM frames rather than whole MP3 frames.
+- dr_mp3 adds convenience APIs for opening and decoding entire files in one go.
+- dr_mp3 is fully namespaced, including the implementation section, which is more suitable when compiling projects
+ as a single translation unit (aka unity builds). At the time of writing this, a unity build is not possible when
+ using minimp3 in conjunction with stb_vorbis. dr_mp3 addresses this.
+*/
+
+/*
+RELEASE NOTES - v0.5.0
+=======================
+Version 0.5.0 has breaking API changes.
+
+Improved Client-Defined Memory Allocation
+-----------------------------------------
+The main change with this release is the addition of a more flexible way of implementing custom memory allocation routines. The
+existing system of DRMP3_MALLOC, DRMP3_REALLOC and DRMP3_FREE are still in place and will be used by default when no custom
+allocation callbacks are specified.
+
+To use the new system, you pass in a pointer to a drmp3_allocation_callbacks object to drmp3_init() and family, like this:
+
+ void* my_malloc(size_t sz, void* pUserData)
+ {
+ return malloc(sz);
+ }
+ void* my_realloc(void* p, size_t sz, void* pUserData)
+ {
+ return realloc(p, sz);
+ }
+ void my_free(void* p, void* pUserData)
+ {
+ free(p);
+ }
+
+ ...
+
+ drmp3_allocation_callbacks allocationCallbacks;
+ allocationCallbacks.pUserData = &myData;
+ allocationCallbacks.onMalloc = my_malloc;
+ allocationCallbacks.onRealloc = my_realloc;
+ allocationCallbacks.onFree = my_free;
+ drmp3_init_file(&mp3, "my_file.mp3", NULL, &allocationCallbacks);
+
+The advantage of this new system is that it allows you to specify user data which will be passed in to the allocation routines.
+
+Passing in null for the allocation callbacks object will cause dr_mp3 to use defaults which is the same as DRMP3_MALLOC,
+DRMP3_REALLOC and DRMP3_FREE and the equivalent of how it worked in previous versions.
+
+Every API that opens a drmp3 object now takes this extra parameter. These include the following:
+
+ drmp3_init()
+ drmp3_init_file()
+ drmp3_init_memory()
+ drmp3_open_and_read_pcm_frames_f32()
+ drmp3_open_and_read_pcm_frames_s16()
+ drmp3_open_memory_and_read_pcm_frames_f32()
+ drmp3_open_memory_and_read_pcm_frames_s16()
+ drmp3_open_file_and_read_pcm_frames_f32()
+ drmp3_open_file_and_read_pcm_frames_s16()
+
+Renamed APIs
+------------
+The following APIs have been renamed for consistency with other dr_* libraries and to make it clear that they return PCM frame
+counts rather than sample counts.
+
+ drmp3_open_and_read_f32() -> drmp3_open_and_read_pcm_frames_f32()
+ drmp3_open_and_read_s16() -> drmp3_open_and_read_pcm_frames_s16()
+ drmp3_open_memory_and_read_f32() -> drmp3_open_memory_and_read_pcm_frames_f32()
+ drmp3_open_memory_and_read_s16() -> drmp3_open_memory_and_read_pcm_frames_s16()
+ drmp3_open_file_and_read_f32() -> drmp3_open_file_and_read_pcm_frames_f32()
+ drmp3_open_file_and_read_s16() -> drmp3_open_file_and_read_pcm_frames_s16()
+*/
+
+/*
+REVISION HISTORY
+================
+v0.6.39 - 2024-02-27
+ - Fix a Wdouble-promotion warning.
+
+v0.6.38 - 2023-11-02
+ - Fix build for ARMv6-M.
+
+v0.6.37 - 2023-07-07
+ - Silence a static analysis warning.
+
+v0.6.36 - 2023-06-17
+ - Fix an incorrect date in revision history. No functional change.
+
+v0.6.35 - 2023-05-22
+ - Minor code restructure. No functional change.
+
+v0.6.34 - 2022-09-17
+ - Fix compilation with DJGPP.
+ - Fix compilation when compiling with x86 with no SSE2.
+ - Remove an unnecessary variable from the drmp3 structure.
+
+v0.6.33 - 2022-04-10
+ - Fix compilation error with the MSVC ARM64 build.
+ - Fix compilation error on older versions of GCC.
+ - Remove some unused functions.
+
+v0.6.32 - 2021-12-11
+ - Fix a warning with Clang.
+
+v0.6.31 - 2021-08-22
+ - Fix a bug when loading from memory.
+
+v0.6.30 - 2021-08-16
+ - Silence some warnings.
+ - Replace memory operations with DRMP3_* macros.
+
+v0.6.29 - 2021-08-08
+ - Bring up to date with minimp3.
+
+v0.6.28 - 2021-07-31
+ - Fix platform detection for ARM64.
+ - Fix a compilation error with C89.
+
+v0.6.27 - 2021-02-21
+ - Fix a warning due to referencing _MSC_VER when it is undefined.
+
+v0.6.26 - 2021-01-31
+ - Bring up to date with minimp3.
+
+v0.6.25 - 2020-12-26
+ - Remove DRMP3_DEFAULT_CHANNELS and DRMP3_DEFAULT_SAMPLE_RATE which are leftovers from some removed APIs.
+
+v0.6.24 - 2020-12-07
+ - Fix a typo in version date for 0.6.23.
+
+v0.6.23 - 2020-12-03
+ - Fix an error where a file can be closed twice when initialization of the decoder fails.
+
+v0.6.22 - 2020-12-02
+ - Fix an error where it's possible for a file handle to be left open when initialization of the decoder fails.
+
+v0.6.21 - 2020-11-28
+ - Bring up to date with minimp3.
+
+v0.6.20 - 2020-11-21
+ - Fix compilation with OpenWatcom.
+
+v0.6.19 - 2020-11-13
+ - Minor code clean up.
+
+v0.6.18 - 2020-11-01
+ - Improve compiler support for older versions of GCC.
+
+v0.6.17 - 2020-09-28
+ - Bring up to date with minimp3.
+
+v0.6.16 - 2020-08-02
+ - Simplify sized types.
+
+v0.6.15 - 2020-07-25
+ - Fix a compilation warning.
+
+v0.6.14 - 2020-07-23
+ - Fix undefined behaviour with memmove().
+
+v0.6.13 - 2020-07-06
+ - Fix a bug when converting from s16 to f32 in drmp3_read_pcm_frames_f32().
+
+v0.6.12 - 2020-06-23
+ - Add include guard for the implementation section.
+
+v0.6.11 - 2020-05-26
+ - Fix use of uninitialized variable error.
+
+v0.6.10 - 2020-05-16
+ - Add compile-time and run-time version querying.
+ - DRMP3_VERSION_MINOR
+ - DRMP3_VERSION_MAJOR
+ - DRMP3_VERSION_REVISION
+ - DRMP3_VERSION_STRING
+ - drmp3_version()
+ - drmp3_version_string()
+
+v0.6.9 - 2020-04-30
+ - Change the `pcm` parameter of drmp3dec_decode_frame() to a `const drmp3_uint8*` for consistency with internal APIs.
+
+v0.6.8 - 2020-04-26
+ - Optimizations to decoding when initializing from memory.
+
+v0.6.7 - 2020-04-25
+ - Fix a compilation error with DR_MP3_NO_STDIO
+ - Optimization to decoding by reducing some data movement.
+
+v0.6.6 - 2020-04-23
+ - Fix a minor bug with the running PCM frame counter.
+
+v0.6.5 - 2020-04-19
+ - Fix compilation error on ARM builds.
+
+v0.6.4 - 2020-04-19
+ - Bring up to date with changes to minimp3.
+
+v0.6.3 - 2020-04-13
+ - Fix some pedantic warnings.
+
+v0.6.2 - 2020-04-10
+ - Fix a crash in drmp3_open_*_and_read_pcm_frames_*() if the output config object is NULL.
+
+v0.6.1 - 2020-04-05
+ - Fix warnings.
+
+v0.6.0 - 2020-04-04
+ - API CHANGE: Remove the pConfig parameter from the following APIs:
+ - drmp3_init()
+ - drmp3_init_memory()
+ - drmp3_init_file()
+ - Add drmp3_init_file_w() for opening a file from a wchar_t encoded path.
+
+v0.5.6 - 2020-02-12
+ - Bring up to date with minimp3.
+
+v0.5.5 - 2020-01-29
+ - Fix a memory allocation bug in high level s16 decoding APIs.
+
+v0.5.4 - 2019-12-02
+ - Fix a possible null pointer dereference when using custom memory allocators for realloc().
+
+v0.5.3 - 2019-11-14
+ - Fix typos in documentation.
+
+v0.5.2 - 2019-11-02
+ - Bring up to date with minimp3.
+
+v0.5.1 - 2019-10-08
+ - Fix a warning with GCC.
+
+v0.5.0 - 2019-10-07
+ - API CHANGE: Add support for user defined memory allocation routines. This system allows the program to specify their own memory allocation
+ routines with a user data pointer for client-specific contextual data. This adds an extra parameter to the end of the following APIs:
+ - drmp3_init()
+ - drmp3_init_file()
+ - drmp3_init_memory()
+ - drmp3_open_and_read_pcm_frames_f32()
+ - drmp3_open_and_read_pcm_frames_s16()
+ - drmp3_open_memory_and_read_pcm_frames_f32()
+ - drmp3_open_memory_and_read_pcm_frames_s16()
+ - drmp3_open_file_and_read_pcm_frames_f32()
+ - drmp3_open_file_and_read_pcm_frames_s16()
+ - API CHANGE: Renamed the following APIs:
+ - drmp3_open_and_read_f32() -> drmp3_open_and_read_pcm_frames_f32()
+ - drmp3_open_and_read_s16() -> drmp3_open_and_read_pcm_frames_s16()
+ - drmp3_open_memory_and_read_f32() -> drmp3_open_memory_and_read_pcm_frames_f32()
+ - drmp3_open_memory_and_read_s16() -> drmp3_open_memory_and_read_pcm_frames_s16()
+ - drmp3_open_file_and_read_f32() -> drmp3_open_file_and_read_pcm_frames_f32()
+ - drmp3_open_file_and_read_s16() -> drmp3_open_file_and_read_pcm_frames_s16()
+
+v0.4.7 - 2019-07-28
+ - Fix a compiler error.
+
+v0.4.6 - 2019-06-14
+ - Fix a compiler error.
+
+v0.4.5 - 2019-06-06
+ - Bring up to date with minimp3.
+
+v0.4.4 - 2019-05-06
+ - Fixes to the VC6 build.
+
+v0.4.3 - 2019-05-05
+ - Use the channel count and/or sample rate of the first MP3 frame instead of DRMP3_DEFAULT_CHANNELS and
+ DRMP3_DEFAULT_SAMPLE_RATE when they are set to 0. To use the old behaviour, just set the relevant property to
+ DRMP3_DEFAULT_CHANNELS or DRMP3_DEFAULT_SAMPLE_RATE.
+ - Add s16 reading APIs
+ - drmp3_read_pcm_frames_s16
+ - drmp3_open_memory_and_read_pcm_frames_s16
+ - drmp3_open_and_read_pcm_frames_s16
+ - drmp3_open_file_and_read_pcm_frames_s16
+ - Add drmp3_get_mp3_and_pcm_frame_count() to the public header section.
+ - Add support for C89.
+ - Change license to choice of public domain or MIT-0.
+
+v0.4.2 - 2019-02-21
+ - Fix a warning.
+
+v0.4.1 - 2018-12-30
+ - Fix a warning.
+
+v0.4.0 - 2018-12-16
+ - API CHANGE: Rename some APIs:
+ - drmp3_read_f32 -> to drmp3_read_pcm_frames_f32
+ - drmp3_seek_to_frame -> drmp3_seek_to_pcm_frame
+ - drmp3_open_and_decode_f32 -> drmp3_open_and_read_pcm_frames_f32
+ - drmp3_open_and_decode_memory_f32 -> drmp3_open_memory_and_read_pcm_frames_f32
+ - drmp3_open_and_decode_file_f32 -> drmp3_open_file_and_read_pcm_frames_f32
+ - Add drmp3_get_pcm_frame_count().
+ - Add drmp3_get_mp3_frame_count().
+ - Improve seeking performance.
+
+v0.3.2 - 2018-09-11
+ - Fix a couple of memory leaks.
+ - Bring up to date with minimp3.
+
+v0.3.1 - 2018-08-25
+ - Fix C++ build.
+
+v0.3.0 - 2018-08-25
+ - Bring up to date with minimp3. This has a minor API change: the "pcm" parameter of drmp3dec_decode_frame() has
+ been changed from short* to void* because it can now output both s16 and f32 samples, depending on whether or
+ not the DR_MP3_FLOAT_OUTPUT option is set.
+
+v0.2.11 - 2018-08-08
+ - Fix a bug where the last part of a file is not read.
+
+v0.2.10 - 2018-08-07
+ - Improve 64-bit detection.
+
+v0.2.9 - 2018-08-05
+ - Fix C++ build on older versions of GCC.
+ - Bring up to date with minimp3.
+
+v0.2.8 - 2018-08-02
+ - Fix compilation errors with older versions of GCC.
+
+v0.2.7 - 2018-07-13
+ - Bring up to date with minimp3.
+
+v0.2.6 - 2018-07-12
+ - Bring up to date with minimp3.
+
+v0.2.5 - 2018-06-22
+ - Bring up to date with minimp3.
+
+v0.2.4 - 2018-05-12
+ - Bring up to date with minimp3.
+
+v0.2.3 - 2018-04-29
+ - Fix TCC build.
+
+v0.2.2 - 2018-04-28
+ - Fix bug when opening a decoder from memory.
+
+v0.2.1 - 2018-04-27
+ - Efficiency improvements when the decoder reaches the end of the stream.
+
+v0.2 - 2018-04-21
+ - Bring up to date with minimp3.
+ - Start using major.minor.revision versioning.
+
+v0.1d - 2018-03-30
+ - Bring up to date with minimp3.
+
+v0.1c - 2018-03-11
+ - Fix C++ build error.
+
+v0.1b - 2018-03-07
+ - Bring up to date with minimp3.
+
+v0.1a - 2018-02-28
+ - Fix compilation error on GCC/Clang.
+ - Fix some warnings.
+
+v0.1 - 2018-02-xx
+ - Initial versioned release.
+*/
+
+/*
+This software is available as a choice of the following licenses. Choose
+whichever you prefer.
+
+===============================================================================
+ALTERNATIVE 1 - Public Domain (www.unlicense.org)
+===============================================================================
+This is free and unencumbered software released into the public domain.
+
+Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
+software, either in source code form or as a compiled binary, for any purpose,
+commercial or non-commercial, and by any means.
+
+In jurisdictions that recognize copyright laws, the author or authors of this
+software dedicate any and all copyright interest in the software to the public
+domain. We make this dedication for the benefit of the public at large and to
+the detriment of our heirs and successors. We intend this dedication to be an
+overt act of relinquishment in perpetuity of all present and future rights to
+this software under copyright law.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+For more information, please refer to
+
+===============================================================================
+ALTERNATIVE 2 - MIT No Attribution
+===============================================================================
+Copyright 2023 David Reid
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+/*
+ https://github.com/lieff/minimp3
+ To the extent possible under law, the author(s) have dedicated all copyright and related and neighboring rights to this software to the public domain worldwide.
+ This software is distributed without any warranty.
+ See .
+*/
diff --git a/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/dr_wav.h b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/dr_wav.h
new file mode 100644
index 0000000..a8207ab
--- /dev/null
+++ b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/dr_wav.h
@@ -0,0 +1,8815 @@
+/*
+WAV audio loader and writer. Choice of public domain or MIT-0. See license statements at the end of this file.
+dr_wav - v0.13.16 - 2024-02-27
+
+David Reid - mackron@gmail.com
+
+GitHub: https://github.com/mackron/dr_libs
+*/
+
+/*
+Introduction
+============
+This is a single file library. To use it, do something like the following in one .c file.
+
+ ```c
+ #define DR_WAV_IMPLEMENTATION
+ #include "dr_wav.h"
+ ```
+
+You can then #include this file in other parts of the program as you would with any other header file. Do something like the following to read audio data:
+
+ ```c
+ drwav wav;
+ if (!drwav_init_file(&wav, "my_song.wav", NULL)) {
+ // Error opening WAV file.
+ }
+
+ drwav_int32* pDecodedInterleavedPCMFrames = malloc(wav.totalPCMFrameCount * wav.channels * sizeof(drwav_int32));
+ size_t numberOfSamplesActuallyDecoded = drwav_read_pcm_frames_s32(&wav, wav.totalPCMFrameCount, pDecodedInterleavedPCMFrames);
+
+ ...
+
+ drwav_uninit(&wav);
+ ```
+
+If you just want to quickly open and read the audio data in a single operation you can do something like this:
+
+ ```c
+ unsigned int channels;
+ unsigned int sampleRate;
+ drwav_uint64 totalPCMFrameCount;
+ float* pSampleData = drwav_open_file_and_read_pcm_frames_f32("my_song.wav", &channels, &sampleRate, &totalPCMFrameCount, NULL);
+ if (pSampleData == NULL) {
+ // Error opening and reading WAV file.
+ }
+
+ ...
+
+ drwav_free(pSampleData, NULL);
+ ```
+
+The examples above use versions of the API that convert the audio data to a consistent format (32-bit signed PCM, in this case), but you can still output the
+audio data in its internal format (see notes below for supported formats):
+
+ ```c
+ size_t framesRead = drwav_read_pcm_frames(&wav, wav.totalPCMFrameCount, pDecodedInterleavedPCMFrames);
+ ```
+
+You can also read the raw bytes of audio data, which could be useful if dr_wav does not have native support for a particular data format:
+
+ ```c
+ size_t bytesRead = drwav_read_raw(&wav, bytesToRead, pRawDataBuffer);
+ ```
+
+dr_wav can also be used to output WAV files. This does not currently support compressed formats. To use this, look at `drwav_init_write()`,
+`drwav_init_file_write()`, etc. Use `drwav_write_pcm_frames()` to write samples, or `drwav_write_raw()` to write raw data in the "data" chunk.
+
+ ```c
+ drwav_data_format format;
+ format.container = drwav_container_riff; // <-- drwav_container_riff = normal WAV files, drwav_container_w64 = Sony Wave64.
+ format.format = DR_WAVE_FORMAT_PCM; // <-- Any of the DR_WAVE_FORMAT_* codes.
+ format.channels = 2;
+ format.sampleRate = 44100;
+ format.bitsPerSample = 16;
+ drwav_init_file_write(&wav, "data/recording.wav", &format, NULL);
+
+ ...
+
+ drwav_uint64 framesWritten = drwav_write_pcm_frames(pWav, frameCount, pSamples);
+ ```
+
+Note that writing to AIFF or RIFX is not supported.
+
+dr_wav has support for decoding from a number of different encapsulation formats. See below for details.
+
+
+Build Options
+=============
+#define these options before including this file.
+
+#define DR_WAV_NO_CONVERSION_API
+ Disables conversion APIs such as `drwav_read_pcm_frames_f32()` and `drwav_s16_to_f32()`.
+
+#define DR_WAV_NO_STDIO
+ Disables APIs that initialize a decoder from a file such as `drwav_init_file()`, `drwav_init_file_write()`, etc.
+
+#define DR_WAV_NO_WCHAR
+ Disables all functions ending with `_w`. Use this if your compiler does not provide wchar.h. Not required if DR_WAV_NO_STDIO is also defined.
+
+
+Supported Encapsulations
+========================
+- RIFF (Regular WAV)
+- RIFX (Big-Endian)
+- AIFF (Does not currently support ADPCM)
+- RF64
+- W64
+
+Note that AIFF and RIFX do not support write mode, nor do they support reading of metadata.
+
+
+Supported Encodings
+===================
+- Unsigned 8-bit PCM
+- Signed 12-bit PCM
+- Signed 16-bit PCM
+- Signed 24-bit PCM
+- Signed 32-bit PCM
+- IEEE 32-bit floating point
+- IEEE 64-bit floating point
+- A-law and u-law
+- Microsoft ADPCM
+- IMA ADPCM (DVI, format code 0x11)
+
+8-bit PCM encodings are always assumed to be unsigned. Signed 8-bit encoding can only be read with `drwav_read_raw()`.
+
+Note that ADPCM is not currently supported with AIFF. Contributions welcome.
+
+
+Notes
+=====
+- Samples are always interleaved.
+- The default read function does not do any data conversion. Use `drwav_read_pcm_frames_f32()`, `drwav_read_pcm_frames_s32()` and `drwav_read_pcm_frames_s16()`
+ to read and convert audio data to 32-bit floating point, signed 32-bit integer and signed 16-bit integer samples respectively.
+- dr_wav will try to read the WAV file as best it can, even if it's not strictly conformant to the WAV format.
+*/
+
+#ifndef dr_wav_h
+#define dr_wav_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define DRWAV_STRINGIFY(x) #x
+#define DRWAV_XSTRINGIFY(x) DRWAV_STRINGIFY(x)
+
+#define DRWAV_VERSION_MAJOR 0
+#define DRWAV_VERSION_MINOR 13
+#define DRWAV_VERSION_REVISION 16
+#define DRWAV_VERSION_STRING DRWAV_XSTRINGIFY(DRWAV_VERSION_MAJOR) "." DRWAV_XSTRINGIFY(DRWAV_VERSION_MINOR) "." DRWAV_XSTRINGIFY(DRWAV_VERSION_REVISION)
+
+#include /* For size_t. */
+
+/* Sized Types */
+typedef signed char drwav_int8;
+typedef unsigned char drwav_uint8;
+typedef signed short drwav_int16;
+typedef unsigned short drwav_uint16;
+typedef signed int drwav_int32;
+typedef unsigned int drwav_uint32;
+#if defined(_MSC_VER) && !defined(__clang__)
+ typedef signed __int64 drwav_int64;
+ typedef unsigned __int64 drwav_uint64;
+#else
+ #if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wlong-long"
+ #if defined(__clang__)
+ #pragma GCC diagnostic ignored "-Wc++11-long-long"
+ #endif
+ #endif
+ typedef signed long long drwav_int64;
+ typedef unsigned long long drwav_uint64;
+ #if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
+ #pragma GCC diagnostic pop
+ #endif
+#endif
+#if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__)) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(_M_ARM64) || defined(__powerpc64__)
+ typedef drwav_uint64 drwav_uintptr;
+#else
+ typedef drwav_uint32 drwav_uintptr;
+#endif
+typedef drwav_uint8 drwav_bool8;
+typedef drwav_uint32 drwav_bool32;
+#define DRWAV_TRUE 1
+#define DRWAV_FALSE 0
+/* End Sized Types */
+
+/* Decorations */
+#if !defined(DRWAV_API)
+ #if defined(DRWAV_DLL)
+ #if defined(_WIN32)
+ #define DRWAV_DLL_IMPORT __declspec(dllimport)
+ #define DRWAV_DLL_EXPORT __declspec(dllexport)
+ #define DRWAV_DLL_PRIVATE static
+ #else
+ #if defined(__GNUC__) && __GNUC__ >= 4
+ #define DRWAV_DLL_IMPORT __attribute__((visibility("default")))
+ #define DRWAV_DLL_EXPORT __attribute__((visibility("default")))
+ #define DRWAV_DLL_PRIVATE __attribute__((visibility("hidden")))
+ #else
+ #define DRWAV_DLL_IMPORT
+ #define DRWAV_DLL_EXPORT
+ #define DRWAV_DLL_PRIVATE static
+ #endif
+ #endif
+
+ #if defined(DR_WAV_IMPLEMENTATION) || defined(DRWAV_IMPLEMENTATION)
+ #define DRWAV_API DRWAV_DLL_EXPORT
+ #else
+ #define DRWAV_API DRWAV_DLL_IMPORT
+ #endif
+ #define DRWAV_PRIVATE DRWAV_DLL_PRIVATE
+ #else
+ #define DRWAV_API extern
+ #define DRWAV_PRIVATE static
+ #endif
+#endif
+/* End Decorations */
+
+/* Result Codes */
+typedef drwav_int32 drwav_result;
+#define DRWAV_SUCCESS 0
+#define DRWAV_ERROR -1 /* A generic error. */
+#define DRWAV_INVALID_ARGS -2
+#define DRWAV_INVALID_OPERATION -3
+#define DRWAV_OUT_OF_MEMORY -4
+#define DRWAV_OUT_OF_RANGE -5
+#define DRWAV_ACCESS_DENIED -6
+#define DRWAV_DOES_NOT_EXIST -7
+#define DRWAV_ALREADY_EXISTS -8
+#define DRWAV_TOO_MANY_OPEN_FILES -9
+#define DRWAV_INVALID_FILE -10
+#define DRWAV_TOO_BIG -11
+#define DRWAV_PATH_TOO_LONG -12
+#define DRWAV_NAME_TOO_LONG -13
+#define DRWAV_NOT_DIRECTORY -14
+#define DRWAV_IS_DIRECTORY -15
+#define DRWAV_DIRECTORY_NOT_EMPTY -16
+#define DRWAV_END_OF_FILE -17
+#define DRWAV_NO_SPACE -18
+#define DRWAV_BUSY -19
+#define DRWAV_IO_ERROR -20
+#define DRWAV_INTERRUPT -21
+#define DRWAV_UNAVAILABLE -22
+#define DRWAV_ALREADY_IN_USE -23
+#define DRWAV_BAD_ADDRESS -24
+#define DRWAV_BAD_SEEK -25
+#define DRWAV_BAD_PIPE -26
+#define DRWAV_DEADLOCK -27
+#define DRWAV_TOO_MANY_LINKS -28
+#define DRWAV_NOT_IMPLEMENTED -29
+#define DRWAV_NO_MESSAGE -30
+#define DRWAV_BAD_MESSAGE -31
+#define DRWAV_NO_DATA_AVAILABLE -32
+#define DRWAV_INVALID_DATA -33
+#define DRWAV_TIMEOUT -34
+#define DRWAV_NO_NETWORK -35
+#define DRWAV_NOT_UNIQUE -36
+#define DRWAV_NOT_SOCKET -37
+#define DRWAV_NO_ADDRESS -38
+#define DRWAV_BAD_PROTOCOL -39
+#define DRWAV_PROTOCOL_UNAVAILABLE -40
+#define DRWAV_PROTOCOL_NOT_SUPPORTED -41
+#define DRWAV_PROTOCOL_FAMILY_NOT_SUPPORTED -42
+#define DRWAV_ADDRESS_FAMILY_NOT_SUPPORTED -43
+#define DRWAV_SOCKET_NOT_SUPPORTED -44
+#define DRWAV_CONNECTION_RESET -45
+#define DRWAV_ALREADY_CONNECTED -46
+#define DRWAV_NOT_CONNECTED -47
+#define DRWAV_CONNECTION_REFUSED -48
+#define DRWAV_NO_HOST -49
+#define DRWAV_IN_PROGRESS -50
+#define DRWAV_CANCELLED -51
+#define DRWAV_MEMORY_ALREADY_MAPPED -52
+#define DRWAV_AT_END -53
+/* End Result Codes */
+
+/* Common data formats. */
+#define DR_WAVE_FORMAT_PCM 0x1
+#define DR_WAVE_FORMAT_ADPCM 0x2
+#define DR_WAVE_FORMAT_IEEE_FLOAT 0x3
+#define DR_WAVE_FORMAT_ALAW 0x6
+#define DR_WAVE_FORMAT_MULAW 0x7
+#define DR_WAVE_FORMAT_DVI_ADPCM 0x11
+#define DR_WAVE_FORMAT_EXTENSIBLE 0xFFFE
+
+/* Flags to pass into drwav_init_ex(), etc. */
+#define DRWAV_SEQUENTIAL 0x00000001
+#define DRWAV_WITH_METADATA 0x00000002
+
+DRWAV_API void drwav_version(drwav_uint32* pMajor, drwav_uint32* pMinor, drwav_uint32* pRevision);
+DRWAV_API const char* drwav_version_string(void);
+
+/* Allocation Callbacks */
+typedef struct
+{
+ void* pUserData;
+ void* (* onMalloc)(size_t sz, void* pUserData);
+ void* (* onRealloc)(void* p, size_t sz, void* pUserData);
+ void (* onFree)(void* p, void* pUserData);
+} drwav_allocation_callbacks;
+/* End Allocation Callbacks */
+
+typedef enum
+{
+ drwav_seek_origin_start,
+ drwav_seek_origin_current
+} drwav_seek_origin;
+
+typedef enum
+{
+ drwav_container_riff,
+ drwav_container_rifx,
+ drwav_container_w64,
+ drwav_container_rf64,
+ drwav_container_aiff
+} drwav_container;
+
+typedef struct
+{
+ union
+ {
+ drwav_uint8 fourcc[4];
+ drwav_uint8 guid[16];
+ } id;
+
+ /* The size in bytes of the chunk. */
+ drwav_uint64 sizeInBytes;
+
+ /*
+ RIFF = 2 byte alignment.
+ W64 = 8 byte alignment.
+ */
+ unsigned int paddingSize;
+} drwav_chunk_header;
+
+typedef struct
+{
+ /*
+ The format tag exactly as specified in the wave file's "fmt" chunk. This can be used by applications
+ that require support for data formats not natively supported by dr_wav.
+ */
+ drwav_uint16 formatTag;
+
+ /* The number of channels making up the audio data. When this is set to 1 it is mono, 2 is stereo, etc. */
+ drwav_uint16 channels;
+
+ /* The sample rate. Usually set to something like 44100. */
+ drwav_uint32 sampleRate;
+
+ /* Average bytes per second. You probably don't need this, but it's left here for informational purposes. */
+ drwav_uint32 avgBytesPerSec;
+
+ /* Block align. This is equal to the number of channels * bytes per sample. */
+ drwav_uint16 blockAlign;
+
+ /* Bits per sample. */
+ drwav_uint16 bitsPerSample;
+
+ /* The size of the extended data. Only used internally for validation, but left here for informational purposes. */
+ drwav_uint16 extendedSize;
+
+ /*
+ The number of valid bits per sample. When is equal to WAVE_FORMAT_EXTENSIBLE,
+ is always rounded up to the nearest multiple of 8. This variable contains information about exactly how
+ many bits are valid per sample. Mainly used for informational purposes.
+ */
+ drwav_uint16 validBitsPerSample;
+
+ /* The channel mask. Not used at the moment. */
+ drwav_uint32 channelMask;
+
+ /* The sub-format, exactly as specified by the wave file. */
+ drwav_uint8 subFormat[16];
+} drwav_fmt;
+
+DRWAV_API drwav_uint16 drwav_fmt_get_format(const drwav_fmt* pFMT);
+
+
+/*
+Callback for when data is read. Return value is the number of bytes actually read.
+
+pUserData [in] The user data that was passed to drwav_init() and family.
+pBufferOut [out] The output buffer.
+bytesToRead [in] The number of bytes to read.
+
+Returns the number of bytes actually read.
+
+A return value of less than bytesToRead indicates the end of the stream. Do _not_ return from this callback until
+either the entire bytesToRead is filled or you have reached the end of the stream.
+*/
+typedef size_t (* drwav_read_proc)(void* pUserData, void* pBufferOut, size_t bytesToRead);
+
+/*
+Callback for when data is written. Returns value is the number of bytes actually written.
+
+pUserData [in] The user data that was passed to drwav_init_write() and family.
+pData [out] A pointer to the data to write.
+bytesToWrite [in] The number of bytes to write.
+
+Returns the number of bytes actually written.
+
+If the return value differs from bytesToWrite, it indicates an error.
+*/
+typedef size_t (* drwav_write_proc)(void* pUserData, const void* pData, size_t bytesToWrite);
+
+/*
+Callback for when data needs to be seeked.
+
+pUserData [in] The user data that was passed to drwav_init() and family.
+offset [in] The number of bytes to move, relative to the origin. Will never be negative.
+origin [in] The origin of the seek - the current position or the start of the stream.
+
+Returns whether or not the seek was successful.
+
+Whether or not it is relative to the beginning or current position is determined by the "origin" parameter which will be either drwav_seek_origin_start or
+drwav_seek_origin_current.
+*/
+typedef drwav_bool32 (* drwav_seek_proc)(void* pUserData, int offset, drwav_seek_origin origin);
+
+/*
+Callback for when drwav_init_ex() finds a chunk.
+
+pChunkUserData [in] The user data that was passed to the pChunkUserData parameter of drwav_init_ex() and family.
+onRead [in] A pointer to the function to call when reading.
+onSeek [in] A pointer to the function to call when seeking.
+pReadSeekUserData [in] The user data that was passed to the pReadSeekUserData parameter of drwav_init_ex() and family.
+pChunkHeader [in] A pointer to an object containing basic header information about the chunk. Use this to identify the chunk.
+container [in] Whether or not the WAV file is a RIFF or Wave64 container. If you're unsure of the difference, assume RIFF.
+pFMT [in] A pointer to the object containing the contents of the "fmt" chunk.
+
+Returns the number of bytes read + seeked.
+
+To read data from the chunk, call onRead(), passing in pReadSeekUserData as the first parameter. Do the same for seeking with onSeek(). The return value must
+be the total number of bytes you have read _plus_ seeked.
+
+Use the `container` argument to discriminate the fields in `pChunkHeader->id`. If the container is `drwav_container_riff` or `drwav_container_rf64` you should
+use `id.fourcc`, otherwise you should use `id.guid`.
+
+The `pFMT` parameter can be used to determine the data format of the wave file. Use `drwav_fmt_get_format()` to get the sample format, which will be one of the
+`DR_WAVE_FORMAT_*` identifiers.
+
+The read pointer will be sitting on the first byte after the chunk's header. You must not attempt to read beyond the boundary of the chunk.
+*/
+typedef drwav_uint64 (* drwav_chunk_proc)(void* pChunkUserData, drwav_read_proc onRead, drwav_seek_proc onSeek, void* pReadSeekUserData, const drwav_chunk_header* pChunkHeader, drwav_container container, const drwav_fmt* pFMT);
+
+
+/* Structure for internal use. Only used for loaders opened with drwav_init_memory(). */
+typedef struct
+{
+ const drwav_uint8* data;
+ size_t dataSize;
+ size_t currentReadPos;
+} drwav__memory_stream;
+
+/* Structure for internal use. Only used for writers opened with drwav_init_memory_write(). */
+typedef struct
+{
+ void** ppData;
+ size_t* pDataSize;
+ size_t dataSize;
+ size_t dataCapacity;
+ size_t currentWritePos;
+} drwav__memory_stream_write;
+
+typedef struct
+{
+ drwav_container container; /* RIFF, W64. */
+ drwav_uint32 format; /* DR_WAVE_FORMAT_* */
+ drwav_uint32 channels;
+ drwav_uint32 sampleRate;
+ drwav_uint32 bitsPerSample;
+} drwav_data_format;
+
+typedef enum
+{
+ drwav_metadata_type_none = 0,
+
+ /*
+ Unknown simply means a chunk that drwav does not handle specifically. You can still ask to
+ receive these chunks as metadata objects. It is then up to you to interpret the chunk's data.
+ You can also write unknown metadata to a wav file. Be careful writing unknown chunks if you
+ have also edited the audio data. The unknown chunks could represent offsets/sizes that no
+ longer correctly correspond to the audio data.
+ */
+ drwav_metadata_type_unknown = 1 << 0,
+
+ /* Only 1 of each of these metadata items are allowed in a wav file. */
+ drwav_metadata_type_smpl = 1 << 1,
+ drwav_metadata_type_inst = 1 << 2,
+ drwav_metadata_type_cue = 1 << 3,
+ drwav_metadata_type_acid = 1 << 4,
+ drwav_metadata_type_bext = 1 << 5,
+
+ /*
+ Wav files often have a LIST chunk. This is a chunk that contains a set of subchunks. For this
+ higher-level metadata API, we don't make a distinction between a regular chunk and a LIST
+ subchunk. Instead, they are all just 'metadata' items.
+
+ There can be multiple of these metadata items in a wav file.
+ */
+ drwav_metadata_type_list_label = 1 << 6,
+ drwav_metadata_type_list_note = 1 << 7,
+ drwav_metadata_type_list_labelled_cue_region = 1 << 8,
+
+ drwav_metadata_type_list_info_software = 1 << 9,
+ drwav_metadata_type_list_info_copyright = 1 << 10,
+ drwav_metadata_type_list_info_title = 1 << 11,
+ drwav_metadata_type_list_info_artist = 1 << 12,
+ drwav_metadata_type_list_info_comment = 1 << 13,
+ drwav_metadata_type_list_info_date = 1 << 14,
+ drwav_metadata_type_list_info_genre = 1 << 15,
+ drwav_metadata_type_list_info_album = 1 << 16,
+ drwav_metadata_type_list_info_tracknumber = 1 << 17,
+
+ /* Other type constants for convenience. */
+ drwav_metadata_type_list_all_info_strings = drwav_metadata_type_list_info_software
+ | drwav_metadata_type_list_info_copyright
+ | drwav_metadata_type_list_info_title
+ | drwav_metadata_type_list_info_artist
+ | drwav_metadata_type_list_info_comment
+ | drwav_metadata_type_list_info_date
+ | drwav_metadata_type_list_info_genre
+ | drwav_metadata_type_list_info_album
+ | drwav_metadata_type_list_info_tracknumber,
+
+ drwav_metadata_type_list_all_adtl = drwav_metadata_type_list_label
+ | drwav_metadata_type_list_note
+ | drwav_metadata_type_list_labelled_cue_region,
+
+ drwav_metadata_type_all = -2, /*0xFFFFFFFF & ~drwav_metadata_type_unknown,*/
+ drwav_metadata_type_all_including_unknown = -1 /*0xFFFFFFFF,*/
+} drwav_metadata_type;
+
+/*
+Sampler Metadata
+
+The sampler chunk contains information about how a sound should be played in the context of a whole
+audio production, and when used in a sampler. See https://en.wikipedia.org/wiki/Sample-based_synthesis.
+*/
+typedef enum
+{
+ drwav_smpl_loop_type_forward = 0,
+ drwav_smpl_loop_type_pingpong = 1,
+ drwav_smpl_loop_type_backward = 2
+} drwav_smpl_loop_type;
+
+typedef struct
+{
+ /* The ID of the associated cue point, see drwav_cue and drwav_cue_point. As with all cue point IDs, this can correspond to a label chunk to give this loop a name, see drwav_list_label_or_note. */
+ drwav_uint32 cuePointId;
+
+ /* See drwav_smpl_loop_type. */
+ drwav_uint32 type;
+
+ /* The byte offset of the first sample to be played in the loop. */
+ drwav_uint32 firstSampleByteOffset;
+
+ /* The byte offset into the audio data of the last sample to be played in the loop. */
+ drwav_uint32 lastSampleByteOffset;
+
+ /* A value to represent that playback should occur at a point between samples. This value ranges from 0 to UINT32_MAX. Where a value of 0 means no fraction, and a value of (UINT32_MAX / 2) would mean half a sample. */
+ drwav_uint32 sampleFraction;
+
+ /* Number of times to play the loop. 0 means loop infinitely. */
+ drwav_uint32 playCount;
+} drwav_smpl_loop;
+
+typedef struct
+{
+ /* IDs for a particular MIDI manufacturer. 0 if not used. */
+ drwav_uint32 manufacturerId;
+ drwav_uint32 productId;
+
+ /* The period of 1 sample in nanoseconds. */
+ drwav_uint32 samplePeriodNanoseconds;
+
+ /* The MIDI root note of this file. 0 to 127. */
+ drwav_uint32 midiUnityNote;
+
+ /* The fraction of a semitone up from the given MIDI note. This is a value from 0 to UINT32_MAX, where 0 means no change and (UINT32_MAX / 2) is half a semitone (AKA 50 cents). */
+ drwav_uint32 midiPitchFraction;
+
+ /* Data relating to SMPTE standards which are used for syncing audio and video. 0 if not used. */
+ drwav_uint32 smpteFormat;
+ drwav_uint32 smpteOffset;
+
+ /* drwav_smpl_loop loops. */
+ drwav_uint32 sampleLoopCount;
+
+ /* Optional sampler-specific data. */
+ drwav_uint32 samplerSpecificDataSizeInBytes;
+
+ drwav_smpl_loop* pLoops;
+ drwav_uint8* pSamplerSpecificData;
+} drwav_smpl;
+
+/*
+Instrument Metadata
+
+The inst metadata contains data about how a sound should be played as part of an instrument. This
+commonly read by samplers. See https://en.wikipedia.org/wiki/Sample-based_synthesis.
+*/
+typedef struct
+{
+ drwav_int8 midiUnityNote; /* The root note of the audio as a MIDI note number. 0 to 127. */
+ drwav_int8 fineTuneCents; /* -50 to +50 */
+ drwav_int8 gainDecibels; /* -64 to +64 */
+ drwav_int8 lowNote; /* 0 to 127 */
+ drwav_int8 highNote; /* 0 to 127 */
+ drwav_int8 lowVelocity; /* 1 to 127 */
+ drwav_int8 highVelocity; /* 1 to 127 */
+} drwav_inst;
+
+/*
+Cue Metadata
+
+Cue points are markers at specific points in the audio. They often come with an associated piece of
+drwav_list_label_or_note metadata which contains the text for the marker.
+*/
+typedef struct
+{
+ /* Unique identification value. */
+ drwav_uint32 id;
+
+ /* Set to 0. This is only relevant if there is a 'playlist' chunk - which is not supported by dr_wav. */
+ drwav_uint32 playOrderPosition;
+
+ /* Should always be "data". This represents the fourcc value of the chunk that this cue point corresponds to. dr_wav only supports a single data chunk so this should always be "data". */
+ drwav_uint8 dataChunkId[4];
+
+ /* Set to 0. This is only relevant if there is a wave list chunk. dr_wav, like lots of readers/writers, do not support this. */
+ drwav_uint32 chunkStart;
+
+ /* Set to 0 for uncompressed formats. Else the last byte in compressed wave data where decompression can begin to find the value of the corresponding sample value. */
+ drwav_uint32 blockStart;
+
+ /* For uncompressed formats this is the byte offset of the cue point into the audio data. For compressed formats this is relative to the block specified with blockStart. */
+ drwav_uint32 sampleByteOffset;
+} drwav_cue_point;
+
+typedef struct
+{
+ drwav_uint32 cuePointCount;
+ drwav_cue_point *pCuePoints;
+} drwav_cue;
+
+/*
+Acid Metadata
+
+This chunk contains some information about the time signature and the tempo of the audio.
+*/
+typedef enum
+{
+ drwav_acid_flag_one_shot = 1, /* If this is not set, then it is a loop instead of a one-shot. */
+ drwav_acid_flag_root_note_set = 2,
+ drwav_acid_flag_stretch = 4,
+ drwav_acid_flag_disk_based = 8,
+ drwav_acid_flag_acidizer = 16 /* Not sure what this means. */
+} drwav_acid_flag;
+
+typedef struct
+{
+ /* A bit-field, see drwav_acid_flag. */
+ drwav_uint32 flags;
+
+ /* Valid if flags contains drwav_acid_flag_root_note_set. It represents the MIDI root note the file - a value from 0 to 127. */
+ drwav_uint16 midiUnityNote;
+
+ /* Reserved values that should probably be ignored. reserved1 seems to often be 128 and reserved2 is 0. */
+ drwav_uint16 reserved1;
+ float reserved2;
+
+ /* Number of beats. */
+ drwav_uint32 numBeats;
+
+ /* The time signature of the audio. */
+ drwav_uint16 meterDenominator;
+ drwav_uint16 meterNumerator;
+
+ /* Beats per minute of the track. Setting a value of 0 suggests that there is no tempo. */
+ float tempo;
+} drwav_acid;
+
+/*
+Cue Label or Note metadata
+
+These are 2 different types of metadata, but they have the exact same format. Labels tend to be the
+more common and represent a short name for a cue point. Notes might be used to represent a longer
+comment.
+*/
+typedef struct
+{
+ /* The ID of a cue point that this label or note corresponds to. */
+ drwav_uint32 cuePointId;
+
+ /* Size of the string not including any null terminator. */
+ drwav_uint32 stringLength;
+
+ /* The string. The *init_with_metadata functions null terminate this for convenience. */
+ char* pString;
+} drwav_list_label_or_note;
+
+/*
+BEXT metadata, also known as Broadcast Wave Format (BWF)
+
+This metadata adds some extra description to an audio file. You must check the version field to
+determine if the UMID or the loudness fields are valid.
+*/
+typedef struct
+{
+ /*
+ These top 3 fields, and the umid field are actually defined in the standard as a statically
+ sized buffers. In order to reduce the size of this struct (and therefore the union in the
+ metadata struct), we instead store these as pointers.
+ */
+ char* pDescription; /* Can be NULL or a null-terminated string, must be <= 256 characters. */
+ char* pOriginatorName; /* Can be NULL or a null-terminated string, must be <= 32 characters. */
+ char* pOriginatorReference; /* Can be NULL or a null-terminated string, must be <= 32 characters. */
+ char pOriginationDate[10]; /* ASCII "yyyy:mm:dd". */
+ char pOriginationTime[8]; /* ASCII "hh:mm:ss". */
+ drwav_uint64 timeReference; /* First sample count since midnight. */
+ drwav_uint16 version; /* Version of the BWF, check this to see if the fields below are valid. */
+
+ /*
+ Unrestricted ASCII characters containing a collection of strings terminated by CR/LF. Each
+ string shall contain a description of a coding process applied to the audio data.
+ */
+ char* pCodingHistory;
+ drwav_uint32 codingHistorySize;
+
+ /* Fields below this point are only valid if the version is 1 or above. */
+ drwav_uint8* pUMID; /* Exactly 64 bytes of SMPTE UMID */
+
+ /* Fields below this point are only valid if the version is 2 or above. */
+ drwav_uint16 loudnessValue; /* Integrated Loudness Value of the file in LUFS (multiplied by 100). */
+ drwav_uint16 loudnessRange; /* Loudness Range of the file in LU (multiplied by 100). */
+ drwav_uint16 maxTruePeakLevel; /* Maximum True Peak Level of the file expressed as dBTP (multiplied by 100). */
+ drwav_uint16 maxMomentaryLoudness; /* Highest value of the Momentary Loudness Level of the file in LUFS (multiplied by 100). */
+ drwav_uint16 maxShortTermLoudness; /* Highest value of the Short-Term Loudness Level of the file in LUFS (multiplied by 100). */
+} drwav_bext;
+
+/*
+Info Text Metadata
+
+There a many different types of information text that can be saved in this format. This is where
+things like the album name, the artists, the year it was produced, etc are saved. See
+drwav_metadata_type for the full list of types that dr_wav supports.
+*/
+typedef struct
+{
+ /* Size of the string not including any null terminator. */
+ drwav_uint32 stringLength;
+
+ /* The string. The *init_with_metadata functions null terminate this for convenience. */
+ char* pString;
+} drwav_list_info_text;
+
+/*
+Labelled Cue Region Metadata
+
+The labelled cue region metadata is used to associate some region of audio with text. The region
+starts at a cue point, and extends for the given number of samples.
+*/
+typedef struct
+{
+ /* The ID of a cue point that this object corresponds to. */
+ drwav_uint32 cuePointId;
+
+ /* The number of samples from the cue point forwards that should be considered this region */
+ drwav_uint32 sampleLength;
+
+ /* Four characters used to say what the purpose of this region is. */
+ drwav_uint8 purposeId[4];
+
+ /* Unsure of the exact meanings of these. It appears to be acceptable to set them all to 0. */
+ drwav_uint16 country;
+ drwav_uint16 language;
+ drwav_uint16 dialect;
+ drwav_uint16 codePage;
+
+ /* Size of the string not including any null terminator. */
+ drwav_uint32 stringLength;
+
+ /* The string. The *init_with_metadata functions null terminate this for convenience. */
+ char* pString;
+} drwav_list_labelled_cue_region;
+
+/*
+Unknown Metadata
+
+This chunk just represents a type of chunk that dr_wav does not understand.
+
+Unknown metadata has a location attached to it. This is because wav files can have a LIST chunk
+that contains subchunks. These LIST chunks can be one of two types. An adtl list, or an INFO
+list. This enum is used to specify the location of a chunk that dr_wav currently doesn't support.
+*/
+typedef enum
+{
+ drwav_metadata_location_invalid,
+ drwav_metadata_location_top_level,
+ drwav_metadata_location_inside_info_list,
+ drwav_metadata_location_inside_adtl_list
+} drwav_metadata_location;
+
+typedef struct
+{
+ drwav_uint8 id[4];
+ drwav_metadata_location chunkLocation;
+ drwav_uint32 dataSizeInBytes;
+ drwav_uint8* pData;
+} drwav_unknown_metadata;
+
+/*
+Metadata is saved as a union of all the supported types.
+*/
+typedef struct
+{
+ /* Determines which item in the union is valid. */
+ drwav_metadata_type type;
+
+ union
+ {
+ drwav_cue cue;
+ drwav_smpl smpl;
+ drwav_acid acid;
+ drwav_inst inst;
+ drwav_bext bext;
+ drwav_list_label_or_note labelOrNote; /* List label or list note. */
+ drwav_list_labelled_cue_region labelledCueRegion;
+ drwav_list_info_text infoText; /* Any of the list info types. */
+ drwav_unknown_metadata unknown;
+ } data;
+} drwav_metadata;
+
+typedef struct
+{
+ /* A pointer to the function to call when more data is needed. */
+ drwav_read_proc onRead;
+
+ /* A pointer to the function to call when data needs to be written. Only used when the drwav object is opened in write mode. */
+ drwav_write_proc onWrite;
+
+ /* A pointer to the function to call when the wav file needs to be seeked. */
+ drwav_seek_proc onSeek;
+
+ /* The user data to pass to callbacks. */
+ void* pUserData;
+
+ /* Allocation callbacks. */
+ drwav_allocation_callbacks allocationCallbacks;
+
+
+ /* Whether or not the WAV file is formatted as a standard RIFF file or W64. */
+ drwav_container container;
+
+
+ /* Structure containing format information exactly as specified by the wav file. */
+ drwav_fmt fmt;
+
+ /* The sample rate. Will be set to something like 44100. */
+ drwav_uint32 sampleRate;
+
+ /* The number of channels. This will be set to 1 for monaural streams, 2 for stereo, etc. */
+ drwav_uint16 channels;
+
+ /* The bits per sample. Will be set to something like 16, 24, etc. */
+ drwav_uint16 bitsPerSample;
+
+ /* Equal to fmt.formatTag, or the value specified by fmt.subFormat if fmt.formatTag is equal to 65534 (WAVE_FORMAT_EXTENSIBLE). */
+ drwav_uint16 translatedFormatTag;
+
+ /* The total number of PCM frames making up the audio data. */
+ drwav_uint64 totalPCMFrameCount;
+
+
+ /* The size in bytes of the data chunk. */
+ drwav_uint64 dataChunkDataSize;
+
+ /* The position in the stream of the first data byte of the data chunk. This is used for seeking. */
+ drwav_uint64 dataChunkDataPos;
+
+ /* The number of bytes remaining in the data chunk. */
+ drwav_uint64 bytesRemaining;
+
+ /* The current read position in PCM frames. */
+ drwav_uint64 readCursorInPCMFrames;
+
+
+ /*
+ Only used in sequential write mode. Keeps track of the desired size of the "data" chunk at the point of initialization time. Always
+ set to 0 for non-sequential writes and when the drwav object is opened in read mode. Used for validation.
+ */
+ drwav_uint64 dataChunkDataSizeTargetWrite;
+
+ /* Keeps track of whether or not the wav writer was initialized in sequential mode. */
+ drwav_bool32 isSequentialWrite;
+
+
+ /* A array of metadata. This is valid after the *init_with_metadata call returns. It will be valid until drwav_uninit() is called. You can take ownership of this data with drwav_take_ownership_of_metadata(). */
+ drwav_metadata* pMetadata;
+ drwav_uint32 metadataCount;
+
+
+ /* A hack to avoid a DRWAV_MALLOC() when opening a decoder with drwav_init_memory(). */
+ drwav__memory_stream memoryStream;
+ drwav__memory_stream_write memoryStreamWrite;
+
+
+ /* Microsoft ADPCM specific data. */
+ struct
+ {
+ drwav_uint32 bytesRemainingInBlock;
+ drwav_uint16 predictor[2];
+ drwav_int32 delta[2];
+ drwav_int32 cachedFrames[4]; /* Samples are stored in this cache during decoding. */
+ drwav_uint32 cachedFrameCount;
+ drwav_int32 prevFrames[2][2]; /* The previous 2 samples for each channel (2 channels at most). */
+ } msadpcm;
+
+ /* IMA ADPCM specific data. */
+ struct
+ {
+ drwav_uint32 bytesRemainingInBlock;
+ drwav_int32 predictor[2];
+ drwav_int32 stepIndex[2];
+ drwav_int32 cachedFrames[16]; /* Samples are stored in this cache during decoding. */
+ drwav_uint32 cachedFrameCount;
+ } ima;
+
+ /* AIFF specific data. */
+ struct
+ {
+ drwav_bool8 isLE; /* Will be set to true if the audio data is little-endian encoded. */
+ drwav_bool8 isUnsigned; /* Only used for 8-bit samples. When set to true, will be treated as unsigned. */
+ } aiff;
+} drwav;
+
+
+/*
+Initializes a pre-allocated drwav object for reading.
+
+pWav [out] A pointer to the drwav object being initialized.
+onRead [in] The function to call when data needs to be read from the client.
+onSeek [in] The function to call when the read position of the client data needs to move.
+onChunk [in, optional] The function to call when a chunk is enumerated at initialized time.
+pUserData, pReadSeekUserData [in, optional] A pointer to application defined data that will be passed to onRead and onSeek.
+pChunkUserData [in, optional] A pointer to application defined data that will be passed to onChunk.
+flags [in, optional] A set of flags for controlling how things are loaded.
+
+Returns true if successful; false otherwise.
+
+Close the loader with drwav_uninit().
+
+This is the lowest level function for initializing a WAV file. You can also use drwav_init_file() and drwav_init_memory()
+to open the stream from a file or from a block of memory respectively.
+
+Possible values for flags:
+ DRWAV_SEQUENTIAL: Never perform a backwards seek while loading. This disables the chunk callback and will cause this function
+ to return as soon as the data chunk is found. Any chunks after the data chunk will be ignored.
+
+drwav_init() is equivalent to "drwav_init_ex(pWav, onRead, onSeek, NULL, pUserData, NULL, 0);".
+
+The onChunk callback is not called for the WAVE or FMT chunks. The contents of the FMT chunk can be read from pWav->fmt
+after the function returns.
+
+See also: drwav_init_file(), drwav_init_memory(), drwav_uninit()
+*/
+DRWAV_API drwav_bool32 drwav_init(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, const drwav_allocation_callbacks* pAllocationCallbacks);
+DRWAV_API drwav_bool32 drwav_init_ex(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, drwav_chunk_proc onChunk, void* pReadSeekUserData, void* pChunkUserData, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks);
+DRWAV_API drwav_bool32 drwav_init_with_metadata(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks);
+
+/*
+Initializes a pre-allocated drwav object for writing.
+
+onWrite [in] The function to call when data needs to be written.
+onSeek [in] The function to call when the write position needs to move.
+pUserData [in, optional] A pointer to application defined data that will be passed to onWrite and onSeek.
+metadata, numMetadata [in, optional] An array of metadata objects that should be written to the file. The array is not edited. You are responsible for this metadata memory and it must maintain valid until drwav_uninit() is called.
+
+Returns true if successful; false otherwise.
+
+Close the writer with drwav_uninit().
+
+This is the lowest level function for initializing a WAV file. You can also use drwav_init_file_write() and drwav_init_memory_write()
+to open the stream from a file or from a block of memory respectively.
+
+If the total sample count is known, you can use drwav_init_write_sequential(). This avoids the need for dr_wav to perform
+a post-processing step for storing the total sample count and the size of the data chunk which requires a backwards seek.
+
+See also: drwav_init_file_write(), drwav_init_memory_write(), drwav_uninit()
+*/
+DRWAV_API drwav_bool32 drwav_init_write(drwav* pWav, const drwav_data_format* pFormat, drwav_write_proc onWrite, drwav_seek_proc onSeek, void* pUserData, const drwav_allocation_callbacks* pAllocationCallbacks);
+DRWAV_API drwav_bool32 drwav_init_write_sequential(drwav* pWav, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, drwav_write_proc onWrite, void* pUserData, const drwav_allocation_callbacks* pAllocationCallbacks);
+DRWAV_API drwav_bool32 drwav_init_write_sequential_pcm_frames(drwav* pWav, const drwav_data_format* pFormat, drwav_uint64 totalPCMFrameCount, drwav_write_proc onWrite, void* pUserData, const drwav_allocation_callbacks* pAllocationCallbacks);
+DRWAV_API drwav_bool32 drwav_init_write_with_metadata(drwav* pWav, const drwav_data_format* pFormat, drwav_write_proc onWrite, drwav_seek_proc onSeek, void* pUserData, const drwav_allocation_callbacks* pAllocationCallbacks, drwav_metadata* pMetadata, drwav_uint32 metadataCount);
+
+/*
+Utility function to determine the target size of the entire data to be written (including all headers and chunks).
+
+Returns the target size in bytes.
+
+The metadata argument can be NULL meaning no metadata exists.
+
+Useful if the application needs to know the size to allocate.
+
+Only writing to the RIFF chunk and one data chunk is currently supported.
+
+See also: drwav_init_write(), drwav_init_file_write(), drwav_init_memory_write()
+*/
+DRWAV_API drwav_uint64 drwav_target_write_size_bytes(const drwav_data_format* pFormat, drwav_uint64 totalFrameCount, drwav_metadata* pMetadata, drwav_uint32 metadataCount);
+
+/*
+Take ownership of the metadata objects that were allocated via one of the init_with_metadata() function calls. The init_with_metdata functions perform a single heap allocation for this metadata.
+
+Useful if you want the data to persist beyond the lifetime of the drwav object.
+
+You must free the data returned from this function using drwav_free().
+*/
+DRWAV_API drwav_metadata* drwav_take_ownership_of_metadata(drwav* pWav);
+
+/*
+Uninitializes the given drwav object.
+
+Use this only for objects initialized with drwav_init*() functions (drwav_init(), drwav_init_ex(), drwav_init_write(), drwav_init_write_sequential()).
+*/
+DRWAV_API drwav_result drwav_uninit(drwav* pWav);
+
+
+/*
+Reads raw audio data.
+
+This is the lowest level function for reading audio data. It simply reads the given number of
+bytes of the raw internal sample data.
+
+Consider using drwav_read_pcm_frames_s16(), drwav_read_pcm_frames_s32() or drwav_read_pcm_frames_f32() for
+reading sample data in a consistent format.
+
+pBufferOut can be NULL in which case a seek will be performed.
+
+Returns the number of bytes actually read.
+*/
+DRWAV_API size_t drwav_read_raw(drwav* pWav, size_t bytesToRead, void* pBufferOut);
+
+/*
+Reads up to the specified number of PCM frames from the WAV file.
+
+The output data will be in the file's internal format, converted to native-endian byte order. Use
+drwav_read_pcm_frames_s16/f32/s32() to read data in a specific format.
+
+If the return value is less than it means the end of the file has been reached or
+you have requested more PCM frames than can possibly fit in the output buffer.
+
+This function will only work when sample data is of a fixed size and uncompressed. If you are
+using a compressed format consider using drwav_read_raw() or drwav_read_pcm_frames_s16/s32/f32().
+
+pBufferOut can be NULL in which case a seek will be performed.
+*/
+DRWAV_API drwav_uint64 drwav_read_pcm_frames(drwav* pWav, drwav_uint64 framesToRead, void* pBufferOut);
+DRWAV_API drwav_uint64 drwav_read_pcm_frames_le(drwav* pWav, drwav_uint64 framesToRead, void* pBufferOut);
+DRWAV_API drwav_uint64 drwav_read_pcm_frames_be(drwav* pWav, drwav_uint64 framesToRead, void* pBufferOut);
+
+/*
+Seeks to the given PCM frame.
+
+Returns true if successful; false otherwise.
+*/
+DRWAV_API drwav_bool32 drwav_seek_to_pcm_frame(drwav* pWav, drwav_uint64 targetFrameIndex);
+
+/*
+Retrieves the current read position in pcm frames.
+*/
+DRWAV_API drwav_result drwav_get_cursor_in_pcm_frames(drwav* pWav, drwav_uint64* pCursor);
+
+/*
+Retrieves the length of the file.
+*/
+DRWAV_API drwav_result drwav_get_length_in_pcm_frames(drwav* pWav, drwav_uint64* pLength);
+
+
+/*
+Writes raw audio data.
+
+Returns the number of bytes actually written. If this differs from bytesToWrite, it indicates an error.
+*/
+DRWAV_API size_t drwav_write_raw(drwav* pWav, size_t bytesToWrite, const void* pData);
+
+/*
+Writes PCM frames.
+
+Returns the number of PCM frames written.
+
+Input samples need to be in native-endian byte order. On big-endian architectures the input data will be converted to
+little-endian. Use drwav_write_raw() to write raw audio data without performing any conversion.
+*/
+DRWAV_API drwav_uint64 drwav_write_pcm_frames(drwav* pWav, drwav_uint64 framesToWrite, const void* pData);
+DRWAV_API drwav_uint64 drwav_write_pcm_frames_le(drwav* pWav, drwav_uint64 framesToWrite, const void* pData);
+DRWAV_API drwav_uint64 drwav_write_pcm_frames_be(drwav* pWav, drwav_uint64 framesToWrite, const void* pData);
+
+/* Conversion Utilities */
+#ifndef DR_WAV_NO_CONVERSION_API
+
+/*
+Reads a chunk of audio data and converts it to signed 16-bit PCM samples.
+
+pBufferOut can be NULL in which case a seek will be performed.
+
+Returns the number of PCM frames actually read.
+
+If the return value is less than it means the end of the file has been reached.
+*/
+DRWAV_API drwav_uint64 drwav_read_pcm_frames_s16(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut);
+DRWAV_API drwav_uint64 drwav_read_pcm_frames_s16le(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut);
+DRWAV_API drwav_uint64 drwav_read_pcm_frames_s16be(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut);
+
+/* Low-level function for converting unsigned 8-bit PCM samples to signed 16-bit PCM samples. */
+DRWAV_API void drwav_u8_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCount);
+
+/* Low-level function for converting signed 24-bit PCM samples to signed 16-bit PCM samples. */
+DRWAV_API void drwav_s24_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCount);
+
+/* Low-level function for converting signed 32-bit PCM samples to signed 16-bit PCM samples. */
+DRWAV_API void drwav_s32_to_s16(drwav_int16* pOut, const drwav_int32* pIn, size_t sampleCount);
+
+/* Low-level function for converting IEEE 32-bit floating point samples to signed 16-bit PCM samples. */
+DRWAV_API void drwav_f32_to_s16(drwav_int16* pOut, const float* pIn, size_t sampleCount);
+
+/* Low-level function for converting IEEE 64-bit floating point samples to signed 16-bit PCM samples. */
+DRWAV_API void drwav_f64_to_s16(drwav_int16* pOut, const double* pIn, size_t sampleCount);
+
+/* Low-level function for converting A-law samples to signed 16-bit PCM samples. */
+DRWAV_API void drwav_alaw_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCount);
+
+/* Low-level function for converting u-law samples to signed 16-bit PCM samples. */
+DRWAV_API void drwav_mulaw_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCount);
+
+
+/*
+Reads a chunk of audio data and converts it to IEEE 32-bit floating point samples.
+
+pBufferOut can be NULL in which case a seek will be performed.
+
+Returns the number of PCM frames actually read.
+
+If the return value is less than it means the end of the file has been reached.
+*/
+DRWAV_API drwav_uint64 drwav_read_pcm_frames_f32(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut);
+DRWAV_API drwav_uint64 drwav_read_pcm_frames_f32le(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut);
+DRWAV_API drwav_uint64 drwav_read_pcm_frames_f32be(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut);
+
+/* Low-level function for converting unsigned 8-bit PCM samples to IEEE 32-bit floating point samples. */
+DRWAV_API void drwav_u8_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount);
+
+/* Low-level function for converting signed 16-bit PCM samples to IEEE 32-bit floating point samples. */
+DRWAV_API void drwav_s16_to_f32(float* pOut, const drwav_int16* pIn, size_t sampleCount);
+
+/* Low-level function for converting signed 24-bit PCM samples to IEEE 32-bit floating point samples. */
+DRWAV_API void drwav_s24_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount);
+
+/* Low-level function for converting signed 32-bit PCM samples to IEEE 32-bit floating point samples. */
+DRWAV_API void drwav_s32_to_f32(float* pOut, const drwav_int32* pIn, size_t sampleCount);
+
+/* Low-level function for converting IEEE 64-bit floating point samples to IEEE 32-bit floating point samples. */
+DRWAV_API void drwav_f64_to_f32(float* pOut, const double* pIn, size_t sampleCount);
+
+/* Low-level function for converting A-law samples to IEEE 32-bit floating point samples. */
+DRWAV_API void drwav_alaw_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount);
+
+/* Low-level function for converting u-law samples to IEEE 32-bit floating point samples. */
+DRWAV_API void drwav_mulaw_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount);
+
+
+/*
+Reads a chunk of audio data and converts it to signed 32-bit PCM samples.
+
+pBufferOut can be NULL in which case a seek will be performed.
+
+Returns the number of PCM frames actually read.
+
+If the return value is less than it means the end of the file has been reached.
+*/
+DRWAV_API drwav_uint64 drwav_read_pcm_frames_s32(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut);
+DRWAV_API drwav_uint64 drwav_read_pcm_frames_s32le(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut);
+DRWAV_API drwav_uint64 drwav_read_pcm_frames_s32be(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut);
+
+/* Low-level function for converting unsigned 8-bit PCM samples to signed 32-bit PCM samples. */
+DRWAV_API void drwav_u8_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount);
+
+/* Low-level function for converting signed 16-bit PCM samples to signed 32-bit PCM samples. */
+DRWAV_API void drwav_s16_to_s32(drwav_int32* pOut, const drwav_int16* pIn, size_t sampleCount);
+
+/* Low-level function for converting signed 24-bit PCM samples to signed 32-bit PCM samples. */
+DRWAV_API void drwav_s24_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount);
+
+/* Low-level function for converting IEEE 32-bit floating point samples to signed 32-bit PCM samples. */
+DRWAV_API void drwav_f32_to_s32(drwav_int32* pOut, const float* pIn, size_t sampleCount);
+
+/* Low-level function for converting IEEE 64-bit floating point samples to signed 32-bit PCM samples. */
+DRWAV_API void drwav_f64_to_s32(drwav_int32* pOut, const double* pIn, size_t sampleCount);
+
+/* Low-level function for converting A-law samples to signed 32-bit PCM samples. */
+DRWAV_API void drwav_alaw_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount);
+
+/* Low-level function for converting u-law samples to signed 32-bit PCM samples. */
+DRWAV_API void drwav_mulaw_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount);
+
+#endif /* DR_WAV_NO_CONVERSION_API */
+
+
+/* High-Level Convenience Helpers */
+
+#ifndef DR_WAV_NO_STDIO
+/*
+Helper for initializing a wave file for reading using stdio.
+
+This holds the internal FILE object until drwav_uninit() is called. Keep this in mind if you're caching drwav
+objects because the operating system may restrict the number of file handles an application can have open at
+any given time.
+*/
+DRWAV_API drwav_bool32 drwav_init_file(drwav* pWav, const char* filename, const drwav_allocation_callbacks* pAllocationCallbacks);
+DRWAV_API drwav_bool32 drwav_init_file_ex(drwav* pWav, const char* filename, drwav_chunk_proc onChunk, void* pChunkUserData, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks);
+DRWAV_API drwav_bool32 drwav_init_file_w(drwav* pWav, const wchar_t* filename, const drwav_allocation_callbacks* pAllocationCallbacks);
+DRWAV_API drwav_bool32 drwav_init_file_ex_w(drwav* pWav, const wchar_t* filename, drwav_chunk_proc onChunk, void* pChunkUserData, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks);
+DRWAV_API drwav_bool32 drwav_init_file_with_metadata(drwav* pWav, const char* filename, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks);
+DRWAV_API drwav_bool32 drwav_init_file_with_metadata_w(drwav* pWav, const wchar_t* filename, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks);
+
+
+/*
+Helper for initializing a wave file for writing using stdio.
+
+This holds the internal FILE object until drwav_uninit() is called. Keep this in mind if you're caching drwav
+objects because the operating system may restrict the number of file handles an application can have open at
+any given time.
+*/
+DRWAV_API drwav_bool32 drwav_init_file_write(drwav* pWav, const char* filename, const drwav_data_format* pFormat, const drwav_allocation_callbacks* pAllocationCallbacks);
+DRWAV_API drwav_bool32 drwav_init_file_write_sequential(drwav* pWav, const char* filename, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, const drwav_allocation_callbacks* pAllocationCallbacks);
+DRWAV_API drwav_bool32 drwav_init_file_write_sequential_pcm_frames(drwav* pWav, const char* filename, const drwav_data_format* pFormat, drwav_uint64 totalPCMFrameCount, const drwav_allocation_callbacks* pAllocationCallbacks);
+DRWAV_API drwav_bool32 drwav_init_file_write_w(drwav* pWav, const wchar_t* filename, const drwav_data_format* pFormat, const drwav_allocation_callbacks* pAllocationCallbacks);
+DRWAV_API drwav_bool32 drwav_init_file_write_sequential_w(drwav* pWav, const wchar_t* filename, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, const drwav_allocation_callbacks* pAllocationCallbacks);
+DRWAV_API drwav_bool32 drwav_init_file_write_sequential_pcm_frames_w(drwav* pWav, const wchar_t* filename, const drwav_data_format* pFormat, drwav_uint64 totalPCMFrameCount, const drwav_allocation_callbacks* pAllocationCallbacks);
+#endif /* DR_WAV_NO_STDIO */
+
+/*
+Helper for initializing a loader from a pre-allocated memory buffer.
+
+This does not create a copy of the data. It is up to the application to ensure the buffer remains valid for
+the lifetime of the drwav object.
+
+The buffer should contain the contents of the entire wave file, not just the sample data.
+*/
+DRWAV_API drwav_bool32 drwav_init_memory(drwav* pWav, const void* data, size_t dataSize, const drwav_allocation_callbacks* pAllocationCallbacks);
+DRWAV_API drwav_bool32 drwav_init_memory_ex(drwav* pWav, const void* data, size_t dataSize, drwav_chunk_proc onChunk, void* pChunkUserData, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks);
+DRWAV_API drwav_bool32 drwav_init_memory_with_metadata(drwav* pWav, const void* data, size_t dataSize, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks);
+
+/*
+Helper for initializing a writer which outputs data to a memory buffer.
+
+dr_wav will manage the memory allocations, however it is up to the caller to free the data with drwav_free().
+
+The buffer will remain allocated even after drwav_uninit() is called. The buffer should not be considered valid
+until after drwav_uninit() has been called.
+*/
+DRWAV_API drwav_bool32 drwav_init_memory_write(drwav* pWav, void** ppData, size_t* pDataSize, const drwav_data_format* pFormat, const drwav_allocation_callbacks* pAllocationCallbacks);
+DRWAV_API drwav_bool32 drwav_init_memory_write_sequential(drwav* pWav, void** ppData, size_t* pDataSize, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, const drwav_allocation_callbacks* pAllocationCallbacks);
+DRWAV_API drwav_bool32 drwav_init_memory_write_sequential_pcm_frames(drwav* pWav, void** ppData, size_t* pDataSize, const drwav_data_format* pFormat, drwav_uint64 totalPCMFrameCount, const drwav_allocation_callbacks* pAllocationCallbacks);
+
+
+#ifndef DR_WAV_NO_CONVERSION_API
+/*
+Opens and reads an entire wav file in a single operation.
+
+The return value is a heap-allocated buffer containing the audio data. Use drwav_free() to free the buffer.
+*/
+DRWAV_API drwav_int16* drwav_open_and_read_pcm_frames_s16(drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks);
+DRWAV_API float* drwav_open_and_read_pcm_frames_f32(drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks);
+DRWAV_API drwav_int32* drwav_open_and_read_pcm_frames_s32(drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks);
+#ifndef DR_WAV_NO_STDIO
+/*
+Opens and decodes an entire wav file in a single operation.
+
+The return value is a heap-allocated buffer containing the audio data. Use drwav_free() to free the buffer.
+*/
+DRWAV_API drwav_int16* drwav_open_file_and_read_pcm_frames_s16(const char* filename, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks);
+DRWAV_API float* drwav_open_file_and_read_pcm_frames_f32(const char* filename, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks);
+DRWAV_API drwav_int32* drwav_open_file_and_read_pcm_frames_s32(const char* filename, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks);
+DRWAV_API drwav_int16* drwav_open_file_and_read_pcm_frames_s16_w(const wchar_t* filename, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks);
+DRWAV_API float* drwav_open_file_and_read_pcm_frames_f32_w(const wchar_t* filename, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks);
+DRWAV_API drwav_int32* drwav_open_file_and_read_pcm_frames_s32_w(const wchar_t* filename, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks);
+#endif
+/*
+Opens and decodes an entire wav file from a block of memory in a single operation.
+
+The return value is a heap-allocated buffer containing the audio data. Use drwav_free() to free the buffer.
+*/
+DRWAV_API drwav_int16* drwav_open_memory_and_read_pcm_frames_s16(const void* data, size_t dataSize, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks);
+DRWAV_API float* drwav_open_memory_and_read_pcm_frames_f32(const void* data, size_t dataSize, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks);
+DRWAV_API drwav_int32* drwav_open_memory_and_read_pcm_frames_s32(const void* data, size_t dataSize, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks);
+#endif
+
+/* Frees data that was allocated internally by dr_wav. */
+DRWAV_API void drwav_free(void* p, const drwav_allocation_callbacks* pAllocationCallbacks);
+
+/* Converts bytes from a wav stream to a sized type of native endian. */
+DRWAV_API drwav_uint16 drwav_bytes_to_u16(const drwav_uint8* data);
+DRWAV_API drwav_int16 drwav_bytes_to_s16(const drwav_uint8* data);
+DRWAV_API drwav_uint32 drwav_bytes_to_u32(const drwav_uint8* data);
+DRWAV_API drwav_int32 drwav_bytes_to_s32(const drwav_uint8* data);
+DRWAV_API drwav_uint64 drwav_bytes_to_u64(const drwav_uint8* data);
+DRWAV_API drwav_int64 drwav_bytes_to_s64(const drwav_uint8* data);
+DRWAV_API float drwav_bytes_to_f32(const drwav_uint8* data);
+
+/* Compares a GUID for the purpose of checking the type of a Wave64 chunk. */
+DRWAV_API drwav_bool32 drwav_guid_equal(const drwav_uint8 a[16], const drwav_uint8 b[16]);
+
+/* Compares a four-character-code for the purpose of checking the type of a RIFF chunk. */
+DRWAV_API drwav_bool32 drwav_fourcc_equal(const drwav_uint8* a, const char* b);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* dr_wav_h */
+
+
+/************************************************************************************************************************************************************
+ ************************************************************************************************************************************************************
+
+ IMPLEMENTATION
+
+ ************************************************************************************************************************************************************
+ ************************************************************************************************************************************************************/
+#if defined(DR_WAV_IMPLEMENTATION) || defined(DRWAV_IMPLEMENTATION)
+#ifndef dr_wav_c
+#define dr_wav_c
+
+#ifdef __MRC__
+/* MrC currently doesn't compile dr_wav correctly with any optimizations enabled. */
+#pragma options opt off
+#endif
+
+#include
+#include
+#include /* For INT_MAX */
+
+#ifndef DR_WAV_NO_STDIO
+#include
+#ifndef DR_WAV_NO_WCHAR
+#include
+#endif
+#endif
+
+/* Standard library stuff. */
+#ifndef DRWAV_ASSERT
+#include
+#define DRWAV_ASSERT(expression) assert(expression)
+#endif
+#ifndef DRWAV_MALLOC
+#define DRWAV_MALLOC(sz) malloc((sz))
+#endif
+#ifndef DRWAV_REALLOC
+#define DRWAV_REALLOC(p, sz) realloc((p), (sz))
+#endif
+#ifndef DRWAV_FREE
+#define DRWAV_FREE(p) free((p))
+#endif
+#ifndef DRWAV_COPY_MEMORY
+#define DRWAV_COPY_MEMORY(dst, src, sz) memcpy((dst), (src), (sz))
+#endif
+#ifndef DRWAV_ZERO_MEMORY
+#define DRWAV_ZERO_MEMORY(p, sz) memset((p), 0, (sz))
+#endif
+#ifndef DRWAV_ZERO_OBJECT
+#define DRWAV_ZERO_OBJECT(p) DRWAV_ZERO_MEMORY((p), sizeof(*p))
+#endif
+
+#define drwav_countof(x) (sizeof(x) / sizeof(x[0]))
+#define drwav_align(x, a) ((((x) + (a) - 1) / (a)) * (a))
+#define drwav_min(a, b) (((a) < (b)) ? (a) : (b))
+#define drwav_max(a, b) (((a) > (b)) ? (a) : (b))
+#define drwav_clamp(x, lo, hi) (drwav_max((lo), drwav_min((hi), (x))))
+#define drwav_offset_ptr(p, offset) (((drwav_uint8*)(p)) + (offset))
+
+#define DRWAV_MAX_SIMD_VECTOR_SIZE 32
+
+/* Architecture Detection */
+#if defined(__x86_64__) || defined(_M_X64)
+ #define DRWAV_X64
+#elif defined(__i386) || defined(_M_IX86)
+ #define DRWAV_X86
+#elif defined(__arm__) || defined(_M_ARM)
+ #define DRWAV_ARM
+#endif
+/* End Architecture Detection */
+
+/* Inline */
+#ifdef _MSC_VER
+ #define DRWAV_INLINE __forceinline
+#elif defined(__GNUC__)
+ /*
+ I've had a bug report where GCC is emitting warnings about functions possibly not being inlineable. This warning happens when
+ the __attribute__((always_inline)) attribute is defined without an "inline" statement. I think therefore there must be some
+ case where "__inline__" is not always defined, thus the compiler emitting these warnings. When using -std=c89 or -ansi on the
+ command line, we cannot use the "inline" keyword and instead need to use "__inline__". In an attempt to work around this issue
+ I am using "__inline__" only when we're compiling in strict ANSI mode.
+ */
+ #if defined(__STRICT_ANSI__)
+ #define DRWAV_GNUC_INLINE_HINT __inline__
+ #else
+ #define DRWAV_GNUC_INLINE_HINT inline
+ #endif
+
+ #if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 2)) || defined(__clang__)
+ #define DRWAV_INLINE DRWAV_GNUC_INLINE_HINT __attribute__((always_inline))
+ #else
+ #define DRWAV_INLINE DRWAV_GNUC_INLINE_HINT
+ #endif
+#elif defined(__WATCOMC__)
+ #define DRWAV_INLINE __inline
+#else
+ #define DRWAV_INLINE
+#endif
+/* End Inline */
+
+/* SIZE_MAX */
+#if defined(SIZE_MAX)
+ #define DRWAV_SIZE_MAX SIZE_MAX
+#else
+ #if defined(_WIN64) || defined(_LP64) || defined(__LP64__)
+ #define DRWAV_SIZE_MAX ((drwav_uint64)0xFFFFFFFFFFFFFFFF)
+ #else
+ #define DRWAV_SIZE_MAX 0xFFFFFFFF
+ #endif
+#endif
+/* End SIZE_MAX */
+
+/* Weird bit manipulation is for C89 compatibility (no direct support for 64-bit integers). */
+#define DRWAV_INT64_MIN ((drwav_int64) ((drwav_uint64)0x80000000 << 32))
+#define DRWAV_INT64_MAX ((drwav_int64)(((drwav_uint64)0x7FFFFFFF << 32) | 0xFFFFFFFF))
+
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+ #define DRWAV_HAS_BYTESWAP16_INTRINSIC
+ #define DRWAV_HAS_BYTESWAP32_INTRINSIC
+ #define DRWAV_HAS_BYTESWAP64_INTRINSIC
+#elif defined(__clang__)
+ #if defined(__has_builtin)
+ #if __has_builtin(__builtin_bswap16)
+ #define DRWAV_HAS_BYTESWAP16_INTRINSIC
+ #endif
+ #if __has_builtin(__builtin_bswap32)
+ #define DRWAV_HAS_BYTESWAP32_INTRINSIC
+ #endif
+ #if __has_builtin(__builtin_bswap64)
+ #define DRWAV_HAS_BYTESWAP64_INTRINSIC
+ #endif
+ #endif
+#elif defined(__GNUC__)
+ #if ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
+ #define DRWAV_HAS_BYTESWAP32_INTRINSIC
+ #define DRWAV_HAS_BYTESWAP64_INTRINSIC
+ #endif
+ #if ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))
+ #define DRWAV_HAS_BYTESWAP16_INTRINSIC
+ #endif
+#endif
+
+DRWAV_API void drwav_version(drwav_uint32* pMajor, drwav_uint32* pMinor, drwav_uint32* pRevision)
+{
+ if (pMajor) {
+ *pMajor = DRWAV_VERSION_MAJOR;
+ }
+
+ if (pMinor) {
+ *pMinor = DRWAV_VERSION_MINOR;
+ }
+
+ if (pRevision) {
+ *pRevision = DRWAV_VERSION_REVISION;
+ }
+}
+
+DRWAV_API const char* drwav_version_string(void)
+{
+ return DRWAV_VERSION_STRING;
+}
+
+/*
+These limits are used for basic validation when initializing the decoder. If you exceed these limits, first of all: what on Earth are
+you doing?! (Let me know, I'd be curious!) Second, you can adjust these by #define-ing them before the dr_wav implementation.
+*/
+#ifndef DRWAV_MAX_SAMPLE_RATE
+#define DRWAV_MAX_SAMPLE_RATE 384000
+#endif
+#ifndef DRWAV_MAX_CHANNELS
+#define DRWAV_MAX_CHANNELS 256
+#endif
+#ifndef DRWAV_MAX_BITS_PER_SAMPLE
+#define DRWAV_MAX_BITS_PER_SAMPLE 64
+#endif
+
+static const drwav_uint8 drwavGUID_W64_RIFF[16] = {0x72,0x69,0x66,0x66, 0x2E,0x91, 0xCF,0x11, 0xA5,0xD6, 0x28,0xDB,0x04,0xC1,0x00,0x00}; /* 66666972-912E-11CF-A5D6-28DB04C10000 */
+static const drwav_uint8 drwavGUID_W64_WAVE[16] = {0x77,0x61,0x76,0x65, 0xF3,0xAC, 0xD3,0x11, 0x8C,0xD1, 0x00,0xC0,0x4F,0x8E,0xDB,0x8A}; /* 65766177-ACF3-11D3-8CD1-00C04F8EDB8A */
+/*static const drwav_uint8 drwavGUID_W64_JUNK[16] = {0x6A,0x75,0x6E,0x6B, 0xF3,0xAC, 0xD3,0x11, 0x8C,0xD1, 0x00,0xC0,0x4F,0x8E,0xDB,0x8A};*/ /* 6B6E756A-ACF3-11D3-8CD1-00C04F8EDB8A */
+static const drwav_uint8 drwavGUID_W64_FMT [16] = {0x66,0x6D,0x74,0x20, 0xF3,0xAC, 0xD3,0x11, 0x8C,0xD1, 0x00,0xC0,0x4F,0x8E,0xDB,0x8A}; /* 20746D66-ACF3-11D3-8CD1-00C04F8EDB8A */
+static const drwav_uint8 drwavGUID_W64_FACT[16] = {0x66,0x61,0x63,0x74, 0xF3,0xAC, 0xD3,0x11, 0x8C,0xD1, 0x00,0xC0,0x4F,0x8E,0xDB,0x8A}; /* 74636166-ACF3-11D3-8CD1-00C04F8EDB8A */
+static const drwav_uint8 drwavGUID_W64_DATA[16] = {0x64,0x61,0x74,0x61, 0xF3,0xAC, 0xD3,0x11, 0x8C,0xD1, 0x00,0xC0,0x4F,0x8E,0xDB,0x8A}; /* 61746164-ACF3-11D3-8CD1-00C04F8EDB8A */
+/*static const drwav_uint8 drwavGUID_W64_SMPL[16] = {0x73,0x6D,0x70,0x6C, 0xF3,0xAC, 0xD3,0x11, 0x8C,0xD1, 0x00,0xC0,0x4F,0x8E,0xDB,0x8A};*/ /* 6C706D73-ACF3-11D3-8CD1-00C04F8EDB8A */
+
+
+static DRWAV_INLINE int drwav__is_little_endian(void)
+{
+#if defined(DRWAV_X86) || defined(DRWAV_X64)
+ return DRWAV_TRUE;
+#elif defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && __BYTE_ORDER == __LITTLE_ENDIAN
+ return DRWAV_TRUE;
+#else
+ int n = 1;
+ return (*(char*)&n) == 1;
+#endif
+}
+
+
+static DRWAV_INLINE void drwav_bytes_to_guid(const drwav_uint8* data, drwav_uint8* guid)
+{
+ int i;
+ for (i = 0; i < 16; ++i) {
+ guid[i] = data[i];
+ }
+}
+
+
+static DRWAV_INLINE drwav_uint16 drwav__bswap16(drwav_uint16 n)
+{
+#ifdef DRWAV_HAS_BYTESWAP16_INTRINSIC
+ #if defined(_MSC_VER)
+ return _byteswap_ushort(n);
+ #elif defined(__GNUC__) || defined(__clang__)
+ return __builtin_bswap16(n);
+ #else
+ #error "This compiler does not support the byte swap intrinsic."
+ #endif
+#else
+ return ((n & 0xFF00) >> 8) |
+ ((n & 0x00FF) << 8);
+#endif
+}
+
+static DRWAV_INLINE drwav_uint32 drwav__bswap32(drwav_uint32 n)
+{
+#ifdef DRWAV_HAS_BYTESWAP32_INTRINSIC
+ #if defined(_MSC_VER)
+ return _byteswap_ulong(n);
+ #elif defined(__GNUC__) || defined(__clang__)
+ #if defined(DRWAV_ARM) && (defined(__ARM_ARCH) && __ARM_ARCH >= 6) && !defined(DRWAV_64BIT) /* <-- 64-bit inline assembly has not been tested, so disabling for now. */
+ /* Inline assembly optimized implementation for ARM. In my testing, GCC does not generate optimized code with __builtin_bswap32(). */
+ drwav_uint32 r;
+ __asm__ __volatile__ (
+ #if defined(DRWAV_64BIT)
+ "rev %w[out], %w[in]" : [out]"=r"(r) : [in]"r"(n) /* <-- This is untested. If someone in the community could test this, that would be appreciated! */
+ #else
+ "rev %[out], %[in]" : [out]"=r"(r) : [in]"r"(n)
+ #endif
+ );
+ return r;
+ #else
+ return __builtin_bswap32(n);
+ #endif
+ #else
+ #error "This compiler does not support the byte swap intrinsic."
+ #endif
+#else
+ return ((n & 0xFF000000) >> 24) |
+ ((n & 0x00FF0000) >> 8) |
+ ((n & 0x0000FF00) << 8) |
+ ((n & 0x000000FF) << 24);
+#endif
+}
+
+static DRWAV_INLINE drwav_uint64 drwav__bswap64(drwav_uint64 n)
+{
+#ifdef DRWAV_HAS_BYTESWAP64_INTRINSIC
+ #if defined(_MSC_VER)
+ return _byteswap_uint64(n);
+ #elif defined(__GNUC__) || defined(__clang__)
+ return __builtin_bswap64(n);
+ #else
+ #error "This compiler does not support the byte swap intrinsic."
+ #endif
+#else
+ /* Weird "<< 32" bitshift is required for C89 because it doesn't support 64-bit constants. Should be optimized out by a good compiler. */
+ return ((n & ((drwav_uint64)0xFF000000 << 32)) >> 56) |
+ ((n & ((drwav_uint64)0x00FF0000 << 32)) >> 40) |
+ ((n & ((drwav_uint64)0x0000FF00 << 32)) >> 24) |
+ ((n & ((drwav_uint64)0x000000FF << 32)) >> 8) |
+ ((n & ((drwav_uint64)0xFF000000 )) << 8) |
+ ((n & ((drwav_uint64)0x00FF0000 )) << 24) |
+ ((n & ((drwav_uint64)0x0000FF00 )) << 40) |
+ ((n & ((drwav_uint64)0x000000FF )) << 56);
+#endif
+}
+
+
+static DRWAV_INLINE drwav_int16 drwav__bswap_s16(drwav_int16 n)
+{
+ return (drwav_int16)drwav__bswap16((drwav_uint16)n);
+}
+
+static DRWAV_INLINE void drwav__bswap_samples_s16(drwav_int16* pSamples, drwav_uint64 sampleCount)
+{
+ drwav_uint64 iSample;
+ for (iSample = 0; iSample < sampleCount; iSample += 1) {
+ pSamples[iSample] = drwav__bswap_s16(pSamples[iSample]);
+ }
+}
+
+
+static DRWAV_INLINE void drwav__bswap_s24(drwav_uint8* p)
+{
+ drwav_uint8 t;
+ t = p[0];
+ p[0] = p[2];
+ p[2] = t;
+}
+
+static DRWAV_INLINE void drwav__bswap_samples_s24(drwav_uint8* pSamples, drwav_uint64 sampleCount)
+{
+ drwav_uint64 iSample;
+ for (iSample = 0; iSample < sampleCount; iSample += 1) {
+ drwav_uint8* pSample = pSamples + (iSample*3);
+ drwav__bswap_s24(pSample);
+ }
+}
+
+
+static DRWAV_INLINE drwav_int32 drwav__bswap_s32(drwav_int32 n)
+{
+ return (drwav_int32)drwav__bswap32((drwav_uint32)n);
+}
+
+static DRWAV_INLINE void drwav__bswap_samples_s32(drwav_int32* pSamples, drwav_uint64 sampleCount)
+{
+ drwav_uint64 iSample;
+ for (iSample = 0; iSample < sampleCount; iSample += 1) {
+ pSamples[iSample] = drwav__bswap_s32(pSamples[iSample]);
+ }
+}
+
+
+static DRWAV_INLINE drwav_int64 drwav__bswap_s64(drwav_int64 n)
+{
+ return (drwav_int64)drwav__bswap64((drwav_uint64)n);
+}
+
+static DRWAV_INLINE void drwav__bswap_samples_s64(drwav_int64* pSamples, drwav_uint64 sampleCount)
+{
+ drwav_uint64 iSample;
+ for (iSample = 0; iSample < sampleCount; iSample += 1) {
+ pSamples[iSample] = drwav__bswap_s64(pSamples[iSample]);
+ }
+}
+
+
+static DRWAV_INLINE float drwav__bswap_f32(float n)
+{
+ union {
+ drwav_uint32 i;
+ float f;
+ } x;
+ x.f = n;
+ x.i = drwav__bswap32(x.i);
+
+ return x.f;
+}
+
+static DRWAV_INLINE void drwav__bswap_samples_f32(float* pSamples, drwav_uint64 sampleCount)
+{
+ drwav_uint64 iSample;
+ for (iSample = 0; iSample < sampleCount; iSample += 1) {
+ pSamples[iSample] = drwav__bswap_f32(pSamples[iSample]);
+ }
+}
+
+
+static DRWAV_INLINE void drwav__bswap_samples(void* pSamples, drwav_uint64 sampleCount, drwav_uint32 bytesPerSample)
+{
+ switch (bytesPerSample)
+ {
+ case 1:
+ {
+ /* No-op. */
+ } break;
+ case 2:
+ {
+ drwav__bswap_samples_s16((drwav_int16*)pSamples, sampleCount);
+ } break;
+ case 3:
+ {
+ drwav__bswap_samples_s24((drwav_uint8*)pSamples, sampleCount);
+ } break;
+ case 4:
+ {
+ drwav__bswap_samples_s32((drwav_int32*)pSamples, sampleCount);
+ } break;
+ case 8:
+ {
+ drwav__bswap_samples_s64((drwav_int64*)pSamples, sampleCount);
+ } break;
+ default:
+ {
+ /* Unsupported format. */
+ DRWAV_ASSERT(DRWAV_FALSE);
+ } break;
+ }
+}
+
+
+
+DRWAV_PRIVATE DRWAV_INLINE drwav_bool32 drwav_is_container_be(drwav_container container)
+{
+ if (container == drwav_container_rifx || container == drwav_container_aiff) {
+ return DRWAV_TRUE;
+ } else {
+ return DRWAV_FALSE;
+ }
+}
+
+
+DRWAV_PRIVATE DRWAV_INLINE drwav_uint16 drwav_bytes_to_u16_le(const drwav_uint8* data)
+{
+ return ((drwav_uint16)data[0] << 0) | ((drwav_uint16)data[1] << 8);
+}
+
+DRWAV_PRIVATE DRWAV_INLINE drwav_uint16 drwav_bytes_to_u16_be(const drwav_uint8* data)
+{
+ return ((drwav_uint16)data[1] << 0) | ((drwav_uint16)data[0] << 8);
+}
+
+DRWAV_PRIVATE DRWAV_INLINE drwav_uint16 drwav_bytes_to_u16_ex(const drwav_uint8* data, drwav_container container)
+{
+ if (drwav_is_container_be(container)) {
+ return drwav_bytes_to_u16_be(data);
+ } else {
+ return drwav_bytes_to_u16_le(data);
+ }
+}
+
+
+DRWAV_PRIVATE DRWAV_INLINE drwav_uint32 drwav_bytes_to_u32_le(const drwav_uint8* data)
+{
+ return ((drwav_uint32)data[0] << 0) | ((drwav_uint32)data[1] << 8) | ((drwav_uint32)data[2] << 16) | ((drwav_uint32)data[3] << 24);
+}
+
+DRWAV_PRIVATE DRWAV_INLINE drwav_uint32 drwav_bytes_to_u32_be(const drwav_uint8* data)
+{
+ return ((drwav_uint32)data[3] << 0) | ((drwav_uint32)data[2] << 8) | ((drwav_uint32)data[1] << 16) | ((drwav_uint32)data[0] << 24);
+}
+
+DRWAV_PRIVATE DRWAV_INLINE drwav_uint32 drwav_bytes_to_u32_ex(const drwav_uint8* data, drwav_container container)
+{
+ if (drwav_is_container_be(container)) {
+ return drwav_bytes_to_u32_be(data);
+ } else {
+ return drwav_bytes_to_u32_le(data);
+ }
+}
+
+
+
+DRWAV_PRIVATE drwav_int64 drwav_aiff_extented_to_s64(const drwav_uint8* data)
+{
+ drwav_uint32 exponent = ((drwav_uint32)data[0] << 8) | data[1];
+ drwav_uint64 hi = ((drwav_uint64)data[2] << 24) | ((drwav_uint64)data[3] << 16) | ((drwav_uint64)data[4] << 8) | ((drwav_uint64)data[5] << 0);
+ drwav_uint64 lo = ((drwav_uint64)data[6] << 24) | ((drwav_uint64)data[7] << 16) | ((drwav_uint64)data[8] << 8) | ((drwav_uint64)data[9] << 0);
+ drwav_uint64 significand = (hi << 32) | lo;
+ int sign = exponent >> 15;
+
+ /* Remove sign bit. */
+ exponent &= 0x7FFF;
+
+ /* Special cases. */
+ if (exponent == 0 && significand == 0) {
+ return 0;
+ } else if (exponent == 0x7FFF) {
+ return sign ? DRWAV_INT64_MIN : DRWAV_INT64_MAX; /* Infinite. */
+ }
+
+ exponent -= 16383;
+
+ if (exponent > 63) {
+ return sign ? DRWAV_INT64_MIN : DRWAV_INT64_MAX; /* Too big for a 64-bit integer. */
+ } else if (exponent < 1) {
+ return 0; /* Number is less than 1, so rounds down to 0. */
+ }
+
+ significand >>= (63 - exponent);
+
+ if (sign) {
+ return -(drwav_int64)significand;
+ } else {
+ return (drwav_int64)significand;
+ }
+}
+
+
+DRWAV_PRIVATE void* drwav__malloc_default(size_t sz, void* pUserData)
+{
+ (void)pUserData;
+ return DRWAV_MALLOC(sz);
+}
+
+DRWAV_PRIVATE void* drwav__realloc_default(void* p, size_t sz, void* pUserData)
+{
+ (void)pUserData;
+ return DRWAV_REALLOC(p, sz);
+}
+
+DRWAV_PRIVATE void drwav__free_default(void* p, void* pUserData)
+{
+ (void)pUserData;
+ DRWAV_FREE(p);
+}
+
+
+DRWAV_PRIVATE void* drwav__malloc_from_callbacks(size_t sz, const drwav_allocation_callbacks* pAllocationCallbacks)
+{
+ if (pAllocationCallbacks == NULL) {
+ return NULL;
+ }
+
+ if (pAllocationCallbacks->onMalloc != NULL) {
+ return pAllocationCallbacks->onMalloc(sz, pAllocationCallbacks->pUserData);
+ }
+
+ /* Try using realloc(). */
+ if (pAllocationCallbacks->onRealloc != NULL) {
+ return pAllocationCallbacks->onRealloc(NULL, sz, pAllocationCallbacks->pUserData);
+ }
+
+ return NULL;
+}
+
+DRWAV_PRIVATE void* drwav__realloc_from_callbacks(void* p, size_t szNew, size_t szOld, const drwav_allocation_callbacks* pAllocationCallbacks)
+{
+ if (pAllocationCallbacks == NULL) {
+ return NULL;
+ }
+
+ if (pAllocationCallbacks->onRealloc != NULL) {
+ return pAllocationCallbacks->onRealloc(p, szNew, pAllocationCallbacks->pUserData);
+ }
+
+ /* Try emulating realloc() in terms of malloc()/free(). */
+ if (pAllocationCallbacks->onMalloc != NULL && pAllocationCallbacks->onFree != NULL) {
+ void* p2;
+
+ p2 = pAllocationCallbacks->onMalloc(szNew, pAllocationCallbacks->pUserData);
+ if (p2 == NULL) {
+ return NULL;
+ }
+
+ if (p != NULL) {
+ DRWAV_COPY_MEMORY(p2, p, szOld);
+ pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData);
+ }
+
+ return p2;
+ }
+
+ return NULL;
+}
+
+DRWAV_PRIVATE void drwav__free_from_callbacks(void* p, const drwav_allocation_callbacks* pAllocationCallbacks)
+{
+ if (p == NULL || pAllocationCallbacks == NULL) {
+ return;
+ }
+
+ if (pAllocationCallbacks->onFree != NULL) {
+ pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData);
+ }
+}
+
+
+DRWAV_PRIVATE drwav_allocation_callbacks drwav_copy_allocation_callbacks_or_defaults(const drwav_allocation_callbacks* pAllocationCallbacks)
+{
+ if (pAllocationCallbacks != NULL) {
+ /* Copy. */
+ return *pAllocationCallbacks;
+ } else {
+ /* Defaults. */
+ drwav_allocation_callbacks allocationCallbacks;
+ allocationCallbacks.pUserData = NULL;
+ allocationCallbacks.onMalloc = drwav__malloc_default;
+ allocationCallbacks.onRealloc = drwav__realloc_default;
+ allocationCallbacks.onFree = drwav__free_default;
+ return allocationCallbacks;
+ }
+}
+
+
+static DRWAV_INLINE drwav_bool32 drwav__is_compressed_format_tag(drwav_uint16 formatTag)
+{
+ return
+ formatTag == DR_WAVE_FORMAT_ADPCM ||
+ formatTag == DR_WAVE_FORMAT_DVI_ADPCM;
+}
+
+DRWAV_PRIVATE unsigned int drwav__chunk_padding_size_riff(drwav_uint64 chunkSize)
+{
+ return (unsigned int)(chunkSize % 2);
+}
+
+DRWAV_PRIVATE unsigned int drwav__chunk_padding_size_w64(drwav_uint64 chunkSize)
+{
+ return (unsigned int)(chunkSize % 8);
+}
+
+DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__msadpcm(drwav* pWav, drwav_uint64 samplesToRead, drwav_int16* pBufferOut);
+DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__ima(drwav* pWav, drwav_uint64 samplesToRead, drwav_int16* pBufferOut);
+DRWAV_PRIVATE drwav_bool32 drwav_init_write__internal(drwav* pWav, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount);
+
+DRWAV_PRIVATE drwav_result drwav__read_chunk_header(drwav_read_proc onRead, void* pUserData, drwav_container container, drwav_uint64* pRunningBytesReadOut, drwav_chunk_header* pHeaderOut)
+{
+ if (container == drwav_container_riff || container == drwav_container_rifx || container == drwav_container_rf64 || container == drwav_container_aiff) {
+ drwav_uint8 sizeInBytes[4];
+
+ if (onRead(pUserData, pHeaderOut->id.fourcc, 4) != 4) {
+ return DRWAV_AT_END;
+ }
+
+ if (onRead(pUserData, sizeInBytes, 4) != 4) {
+ return DRWAV_INVALID_FILE;
+ }
+
+ pHeaderOut->sizeInBytes = drwav_bytes_to_u32_ex(sizeInBytes, container);
+ pHeaderOut->paddingSize = drwav__chunk_padding_size_riff(pHeaderOut->sizeInBytes);
+
+ *pRunningBytesReadOut += 8;
+ } else if (container == drwav_container_w64) {
+ drwav_uint8 sizeInBytes[8];
+
+ if (onRead(pUserData, pHeaderOut->id.guid, 16) != 16) {
+ return DRWAV_AT_END;
+ }
+
+ if (onRead(pUserData, sizeInBytes, 8) != 8) {
+ return DRWAV_INVALID_FILE;
+ }
+
+ pHeaderOut->sizeInBytes = drwav_bytes_to_u64(sizeInBytes) - 24; /* <-- Subtract 24 because w64 includes the size of the header. */
+ pHeaderOut->paddingSize = drwav__chunk_padding_size_w64(pHeaderOut->sizeInBytes);
+ *pRunningBytesReadOut += 24;
+ } else {
+ return DRWAV_INVALID_FILE;
+ }
+
+ return DRWAV_SUCCESS;
+}
+
+DRWAV_PRIVATE drwav_bool32 drwav__seek_forward(drwav_seek_proc onSeek, drwav_uint64 offset, void* pUserData)
+{
+ drwav_uint64 bytesRemainingToSeek = offset;
+ while (bytesRemainingToSeek > 0) {
+ if (bytesRemainingToSeek > 0x7FFFFFFF) {
+ if (!onSeek(pUserData, 0x7FFFFFFF, drwav_seek_origin_current)) {
+ return DRWAV_FALSE;
+ }
+ bytesRemainingToSeek -= 0x7FFFFFFF;
+ } else {
+ if (!onSeek(pUserData, (int)bytesRemainingToSeek, drwav_seek_origin_current)) {
+ return DRWAV_FALSE;
+ }
+ bytesRemainingToSeek = 0;
+ }
+ }
+
+ return DRWAV_TRUE;
+}
+
+DRWAV_PRIVATE drwav_bool32 drwav__seek_from_start(drwav_seek_proc onSeek, drwav_uint64 offset, void* pUserData)
+{
+ if (offset <= 0x7FFFFFFF) {
+ return onSeek(pUserData, (int)offset, drwav_seek_origin_start);
+ }
+
+ /* Larger than 32-bit seek. */
+ if (!onSeek(pUserData, 0x7FFFFFFF, drwav_seek_origin_start)) {
+ return DRWAV_FALSE;
+ }
+ offset -= 0x7FFFFFFF;
+
+ for (;;) {
+ if (offset <= 0x7FFFFFFF) {
+ return onSeek(pUserData, (int)offset, drwav_seek_origin_current);
+ }
+
+ if (!onSeek(pUserData, 0x7FFFFFFF, drwav_seek_origin_current)) {
+ return DRWAV_FALSE;
+ }
+ offset -= 0x7FFFFFFF;
+ }
+
+ /* Should never get here. */
+ /*return DRWAV_TRUE; */
+}
+
+
+
+DRWAV_PRIVATE size_t drwav__on_read(drwav_read_proc onRead, void* pUserData, void* pBufferOut, size_t bytesToRead, drwav_uint64* pCursor)
+{
+ size_t bytesRead;
+
+ DRWAV_ASSERT(onRead != NULL);
+ DRWAV_ASSERT(pCursor != NULL);
+
+ bytesRead = onRead(pUserData, pBufferOut, bytesToRead);
+ *pCursor += bytesRead;
+ return bytesRead;
+}
+
+#if 0
+DRWAV_PRIVATE drwav_bool32 drwav__on_seek(drwav_seek_proc onSeek, void* pUserData, int offset, drwav_seek_origin origin, drwav_uint64* pCursor)
+{
+ DRWAV_ASSERT(onSeek != NULL);
+ DRWAV_ASSERT(pCursor != NULL);
+
+ if (!onSeek(pUserData, offset, origin)) {
+ return DRWAV_FALSE;
+ }
+
+ if (origin == drwav_seek_origin_start) {
+ *pCursor = offset;
+ } else {
+ *pCursor += offset;
+ }
+
+ return DRWAV_TRUE;
+}
+#endif
+
+
+#define DRWAV_SMPL_BYTES 36
+#define DRWAV_SMPL_LOOP_BYTES 24
+#define DRWAV_INST_BYTES 7
+#define DRWAV_ACID_BYTES 24
+#define DRWAV_CUE_BYTES 4
+#define DRWAV_BEXT_BYTES 602
+#define DRWAV_BEXT_DESCRIPTION_BYTES 256
+#define DRWAV_BEXT_ORIGINATOR_NAME_BYTES 32
+#define DRWAV_BEXT_ORIGINATOR_REF_BYTES 32
+#define DRWAV_BEXT_RESERVED_BYTES 180
+#define DRWAV_BEXT_UMID_BYTES 64
+#define DRWAV_CUE_POINT_BYTES 24
+#define DRWAV_LIST_LABEL_OR_NOTE_BYTES 4
+#define DRWAV_LIST_LABELLED_TEXT_BYTES 20
+
+#define DRWAV_METADATA_ALIGNMENT 8
+
+typedef enum
+{
+ drwav__metadata_parser_stage_count,
+ drwav__metadata_parser_stage_read
+} drwav__metadata_parser_stage;
+
+typedef struct
+{
+ drwav_read_proc onRead;
+ drwav_seek_proc onSeek;
+ void *pReadSeekUserData;
+ drwav__metadata_parser_stage stage;
+ drwav_metadata *pMetadata;
+ drwav_uint32 metadataCount;
+ drwav_uint8 *pData;
+ drwav_uint8 *pDataCursor;
+ drwav_uint64 metadataCursor;
+ drwav_uint64 extraCapacity;
+} drwav__metadata_parser;
+
+DRWAV_PRIVATE size_t drwav__metadata_memory_capacity(drwav__metadata_parser* pParser)
+{
+ drwav_uint64 cap = sizeof(drwav_metadata) * (drwav_uint64)pParser->metadataCount + pParser->extraCapacity;
+ if (cap > DRWAV_SIZE_MAX) {
+ return 0; /* Too big. */
+ }
+
+ return (size_t)cap; /* Safe cast thanks to the check above. */
+}
+
+DRWAV_PRIVATE drwav_uint8* drwav__metadata_get_memory(drwav__metadata_parser* pParser, size_t size, size_t align)
+{
+ drwav_uint8* pResult;
+
+ if (align) {
+ drwav_uintptr modulo = (drwav_uintptr)pParser->pDataCursor % align;
+ if (modulo != 0) {
+ pParser->pDataCursor += align - modulo;
+ }
+ }
+
+ pResult = pParser->pDataCursor;
+
+ /*
+ Getting to the point where this function is called means there should always be memory
+ available. Out of memory checks should have been done at an earlier stage.
+ */
+ DRWAV_ASSERT((pResult + size) <= (pParser->pData + drwav__metadata_memory_capacity(pParser)));
+
+ pParser->pDataCursor += size;
+ return pResult;
+}
+
+DRWAV_PRIVATE void drwav__metadata_request_extra_memory_for_stage_2(drwav__metadata_parser* pParser, size_t bytes, size_t align)
+{
+ size_t extra = bytes + (align ? (align - 1) : 0);
+ pParser->extraCapacity += extra;
+}
+
+DRWAV_PRIVATE drwav_result drwav__metadata_alloc(drwav__metadata_parser* pParser, drwav_allocation_callbacks* pAllocationCallbacks)
+{
+ if (pParser->extraCapacity != 0 || pParser->metadataCount != 0) {
+ pAllocationCallbacks->onFree(pParser->pData, pAllocationCallbacks->pUserData);
+
+ pParser->pData = (drwav_uint8*)pAllocationCallbacks->onMalloc(drwav__metadata_memory_capacity(pParser), pAllocationCallbacks->pUserData);
+ pParser->pDataCursor = pParser->pData;
+
+ if (pParser->pData == NULL) {
+ return DRWAV_OUT_OF_MEMORY;
+ }
+
+ /*
+ We don't need to worry about specifying an alignment here because malloc always returns something
+ of suitable alignment. This also means pParser->pMetadata is all that we need to store in order
+ for us to free when we are done.
+ */
+ pParser->pMetadata = (drwav_metadata*)drwav__metadata_get_memory(pParser, sizeof(drwav_metadata) * pParser->metadataCount, 1);
+ pParser->metadataCursor = 0;
+ }
+
+ return DRWAV_SUCCESS;
+}
+
+DRWAV_PRIVATE size_t drwav__metadata_parser_read(drwav__metadata_parser* pParser, void* pBufferOut, size_t bytesToRead, drwav_uint64* pCursor)
+{
+ if (pCursor != NULL) {
+ return drwav__on_read(pParser->onRead, pParser->pReadSeekUserData, pBufferOut, bytesToRead, pCursor);
+ } else {
+ return pParser->onRead(pParser->pReadSeekUserData, pBufferOut, bytesToRead);
+ }
+}
+
+DRWAV_PRIVATE drwav_uint64 drwav__read_smpl_to_metadata_obj(drwav__metadata_parser* pParser, const drwav_chunk_header* pChunkHeader, drwav_metadata* pMetadata)
+{
+ drwav_uint8 smplHeaderData[DRWAV_SMPL_BYTES];
+ drwav_uint64 totalBytesRead = 0;
+ size_t bytesJustRead;
+
+ if (pMetadata == NULL) {
+ return 0;
+ }
+
+ bytesJustRead = drwav__metadata_parser_read(pParser, smplHeaderData, sizeof(smplHeaderData), &totalBytesRead);
+
+ DRWAV_ASSERT(pParser->stage == drwav__metadata_parser_stage_read);
+ DRWAV_ASSERT(pChunkHeader != NULL);
+
+ if (pMetadata != NULL && bytesJustRead == sizeof(smplHeaderData)) {
+ drwav_uint32 iSampleLoop;
+
+ pMetadata->type = drwav_metadata_type_smpl;
+ pMetadata->data.smpl.manufacturerId = drwav_bytes_to_u32(smplHeaderData + 0);
+ pMetadata->data.smpl.productId = drwav_bytes_to_u32(smplHeaderData + 4);
+ pMetadata->data.smpl.samplePeriodNanoseconds = drwav_bytes_to_u32(smplHeaderData + 8);
+ pMetadata->data.smpl.midiUnityNote = drwav_bytes_to_u32(smplHeaderData + 12);
+ pMetadata->data.smpl.midiPitchFraction = drwav_bytes_to_u32(smplHeaderData + 16);
+ pMetadata->data.smpl.smpteFormat = drwav_bytes_to_u32(smplHeaderData + 20);
+ pMetadata->data.smpl.smpteOffset = drwav_bytes_to_u32(smplHeaderData + 24);
+ pMetadata->data.smpl.sampleLoopCount = drwav_bytes_to_u32(smplHeaderData + 28);
+ pMetadata->data.smpl.samplerSpecificDataSizeInBytes = drwav_bytes_to_u32(smplHeaderData + 32);
+
+ /*
+ 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) {
+ 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) {
+ drwav_uint8 smplLoopData[DRWAV_SMPL_LOOP_BYTES];
+ bytesJustRead = drwav__metadata_parser_read(pParser, smplLoopData, sizeof(smplLoopData), &totalBytesRead);
+
+ if (bytesJustRead == sizeof(smplLoopData)) {
+ pMetadata->data.smpl.pLoops[iSampleLoop].cuePointId = drwav_bytes_to_u32(smplLoopData + 0);
+ pMetadata->data.smpl.pLoops[iSampleLoop].type = drwav_bytes_to_u32(smplLoopData + 4);
+ pMetadata->data.smpl.pLoops[iSampleLoop].firstSampleByteOffset = drwav_bytes_to_u32(smplLoopData + 8);
+ pMetadata->data.smpl.pLoops[iSampleLoop].lastSampleByteOffset = drwav_bytes_to_u32(smplLoopData + 12);
+ pMetadata->data.smpl.pLoops[iSampleLoop].sampleFraction = drwav_bytes_to_u32(smplLoopData + 16);
+ pMetadata->data.smpl.pLoops[iSampleLoop].playCount = drwav_bytes_to_u32(smplLoopData + 20);
+ } else {
+ break;
+ }
+ }
+
+ if (pMetadata->data.smpl.samplerSpecificDataSizeInBytes > 0) {
+ pMetadata->data.smpl.pSamplerSpecificData = drwav__metadata_get_memory(pParser, pMetadata->data.smpl.samplerSpecificDataSizeInBytes, 1);
+ DRWAV_ASSERT(pMetadata->data.smpl.pSamplerSpecificData != NULL);
+
+ drwav__metadata_parser_read(pParser, pMetadata->data.smpl.pSamplerSpecificData, pMetadata->data.smpl.samplerSpecificDataSizeInBytes, &totalBytesRead);
+ }
+ }
+ }
+
+ return totalBytesRead;
+}
+
+DRWAV_PRIVATE drwav_uint64 drwav__read_cue_to_metadata_obj(drwav__metadata_parser* pParser, const drwav_chunk_header* pChunkHeader, drwav_metadata* pMetadata)
+{
+ drwav_uint8 cueHeaderSectionData[DRWAV_CUE_BYTES];
+ drwav_uint64 totalBytesRead = 0;
+ size_t bytesJustRead;
+
+ if (pMetadata == NULL) {
+ return 0;
+ }
+
+ bytesJustRead = drwav__metadata_parser_read(pParser, cueHeaderSectionData, sizeof(cueHeaderSectionData), &totalBytesRead);
+
+ DRWAV_ASSERT(pParser->stage == drwav__metadata_parser_stage_read);
+
+ if (bytesJustRead == sizeof(cueHeaderSectionData)) {
+ pMetadata->type = drwav_metadata_type_cue;
+ pMetadata->data.cue.cuePointCount = drwav_bytes_to_u32(cueHeaderSectionData);
+
+ /*
+ We need to validate the cue point count against the size of the chunk so we don't read
+ beyond the chunk.
+ */
+ if (pMetadata->data.cue.cuePointCount == (pChunkHeader->sizeInBytes - DRWAV_CUE_BYTES) / DRWAV_CUE_POINT_BYTES) {
+ pMetadata->data.cue.pCuePoints = (drwav_cue_point*)drwav__metadata_get_memory(pParser, sizeof(drwav_cue_point) * pMetadata->data.cue.cuePointCount, DRWAV_METADATA_ALIGNMENT);
+ DRWAV_ASSERT(pMetadata->data.cue.pCuePoints != NULL);
+
+ if (pMetadata->data.cue.cuePointCount > 0) {
+ drwav_uint32 iCuePoint;
+
+ for (iCuePoint = 0; iCuePoint < pMetadata->data.cue.cuePointCount; ++iCuePoint) {
+ drwav_uint8 cuePointData[DRWAV_CUE_POINT_BYTES];
+ bytesJustRead = drwav__metadata_parser_read(pParser, cuePointData, sizeof(cuePointData), &totalBytesRead);
+
+ if (bytesJustRead == sizeof(cuePointData)) {
+ pMetadata->data.cue.pCuePoints[iCuePoint].id = drwav_bytes_to_u32(cuePointData + 0);
+ pMetadata->data.cue.pCuePoints[iCuePoint].playOrderPosition = drwav_bytes_to_u32(cuePointData + 4);
+ pMetadata->data.cue.pCuePoints[iCuePoint].dataChunkId[0] = cuePointData[8];
+ pMetadata->data.cue.pCuePoints[iCuePoint].dataChunkId[1] = cuePointData[9];
+ pMetadata->data.cue.pCuePoints[iCuePoint].dataChunkId[2] = cuePointData[10];
+ pMetadata->data.cue.pCuePoints[iCuePoint].dataChunkId[3] = cuePointData[11];
+ pMetadata->data.cue.pCuePoints[iCuePoint].chunkStart = drwav_bytes_to_u32(cuePointData + 12);
+ pMetadata->data.cue.pCuePoints[iCuePoint].blockStart = drwav_bytes_to_u32(cuePointData + 16);
+ pMetadata->data.cue.pCuePoints[iCuePoint].sampleByteOffset = drwav_bytes_to_u32(cuePointData + 20);
+ } else {
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ return totalBytesRead;
+}
+
+DRWAV_PRIVATE drwav_uint64 drwav__read_inst_to_metadata_obj(drwav__metadata_parser* pParser, drwav_metadata* pMetadata)
+{
+ drwav_uint8 instData[DRWAV_INST_BYTES];
+ drwav_uint64 bytesRead;
+
+ if (pMetadata == NULL) {
+ return 0;
+ }
+
+ bytesRead = drwav__metadata_parser_read(pParser, instData, sizeof(instData), NULL);
+
+ DRWAV_ASSERT(pParser->stage == drwav__metadata_parser_stage_read);
+
+ if (bytesRead == sizeof(instData)) {
+ pMetadata->type = drwav_metadata_type_inst;
+ pMetadata->data.inst.midiUnityNote = (drwav_int8)instData[0];
+ pMetadata->data.inst.fineTuneCents = (drwav_int8)instData[1];
+ pMetadata->data.inst.gainDecibels = (drwav_int8)instData[2];
+ pMetadata->data.inst.lowNote = (drwav_int8)instData[3];
+ pMetadata->data.inst.highNote = (drwav_int8)instData[4];
+ pMetadata->data.inst.lowVelocity = (drwav_int8)instData[5];
+ pMetadata->data.inst.highVelocity = (drwav_int8)instData[6];
+ }
+
+ return bytesRead;
+}
+
+DRWAV_PRIVATE drwav_uint64 drwav__read_acid_to_metadata_obj(drwav__metadata_parser* pParser, drwav_metadata* pMetadata)
+{
+ drwav_uint8 acidData[DRWAV_ACID_BYTES];
+ drwav_uint64 bytesRead;
+
+ if (pMetadata == NULL) {
+ return 0;
+ }
+
+ bytesRead = drwav__metadata_parser_read(pParser, acidData, sizeof(acidData), NULL);
+
+ DRWAV_ASSERT(pParser->stage == drwav__metadata_parser_stage_read);
+
+ if (bytesRead == sizeof(acidData)) {
+ pMetadata->type = drwav_metadata_type_acid;
+ pMetadata->data.acid.flags = drwav_bytes_to_u32(acidData + 0);
+ pMetadata->data.acid.midiUnityNote = drwav_bytes_to_u16(acidData + 4);
+ pMetadata->data.acid.reserved1 = drwav_bytes_to_u16(acidData + 6);
+ pMetadata->data.acid.reserved2 = drwav_bytes_to_f32(acidData + 8);
+ pMetadata->data.acid.numBeats = drwav_bytes_to_u32(acidData + 12);
+ pMetadata->data.acid.meterDenominator = drwav_bytes_to_u16(acidData + 16);
+ pMetadata->data.acid.meterNumerator = drwav_bytes_to_u16(acidData + 18);
+ pMetadata->data.acid.tempo = drwav_bytes_to_f32(acidData + 20);
+ }
+
+ return bytesRead;
+}
+
+DRWAV_PRIVATE size_t drwav__strlen(const char* str)
+{
+ size_t result = 0;
+
+ while (*str++) {
+ result += 1;
+ }
+
+ return result;
+}
+
+DRWAV_PRIVATE size_t drwav__strlen_clamped(const char* str, size_t maxToRead)
+{
+ size_t result = 0;
+
+ while (*str++ && result < maxToRead) {
+ result += 1;
+ }
+
+ return result;
+}
+
+DRWAV_PRIVATE char* drwav__metadata_copy_string(drwav__metadata_parser* pParser, const char* str, size_t maxToRead)
+{
+ size_t len = drwav__strlen_clamped(str, maxToRead);
+
+ if (len) {
+ char* result = (char*)drwav__metadata_get_memory(pParser, len + 1, 1);
+ DRWAV_ASSERT(result != NULL);
+
+ DRWAV_COPY_MEMORY(result, str, len);
+ result[len] = '\0';
+
+ return result;
+ } else {
+ return NULL;
+ }
+}
+
+typedef struct
+{
+ const void* pBuffer;
+ size_t sizeInBytes;
+ size_t cursor;
+} drwav_buffer_reader;
+
+DRWAV_PRIVATE drwav_result drwav_buffer_reader_init(const void* pBuffer, size_t sizeInBytes, drwav_buffer_reader* pReader)
+{
+ DRWAV_ASSERT(pBuffer != NULL);
+ DRWAV_ASSERT(pReader != NULL);
+
+ DRWAV_ZERO_OBJECT(pReader);
+
+ pReader->pBuffer = pBuffer;
+ pReader->sizeInBytes = sizeInBytes;
+ pReader->cursor = 0;
+
+ return DRWAV_SUCCESS;
+}
+
+DRWAV_PRIVATE const void* drwav_buffer_reader_ptr(const drwav_buffer_reader* pReader)
+{
+ DRWAV_ASSERT(pReader != NULL);
+
+ return drwav_offset_ptr(pReader->pBuffer, pReader->cursor);
+}
+
+DRWAV_PRIVATE drwav_result drwav_buffer_reader_seek(drwav_buffer_reader* pReader, size_t bytesToSeek)
+{
+ DRWAV_ASSERT(pReader != NULL);
+
+ if (pReader->cursor + bytesToSeek > pReader->sizeInBytes) {
+ return DRWAV_BAD_SEEK; /* Seeking too far forward. */
+ }
+
+ pReader->cursor += bytesToSeek;
+
+ return DRWAV_SUCCESS;
+}
+
+DRWAV_PRIVATE drwav_result drwav_buffer_reader_read(drwav_buffer_reader* pReader, void* pDst, size_t bytesToRead, size_t* pBytesRead)
+{
+ drwav_result result = DRWAV_SUCCESS;
+ size_t bytesRemaining;
+
+ DRWAV_ASSERT(pReader != NULL);
+
+ if (pBytesRead != NULL) {
+ *pBytesRead = 0;
+ }
+
+ bytesRemaining = (pReader->sizeInBytes - pReader->cursor);
+ if (bytesToRead > bytesRemaining) {
+ bytesToRead = bytesRemaining;
+ }
+
+ if (pDst == NULL) {
+ /* Seek. */
+ result = drwav_buffer_reader_seek(pReader, bytesToRead);
+ } else {
+ /* Read. */
+ DRWAV_COPY_MEMORY(pDst, drwav_buffer_reader_ptr(pReader), bytesToRead);
+ pReader->cursor += bytesToRead;
+ }
+
+ DRWAV_ASSERT(pReader->cursor <= pReader->sizeInBytes);
+
+ if (result == DRWAV_SUCCESS) {
+ if (pBytesRead != NULL) {
+ *pBytesRead = bytesToRead;
+ }
+ }
+
+ return DRWAV_SUCCESS;
+}
+
+DRWAV_PRIVATE drwav_result drwav_buffer_reader_read_u16(drwav_buffer_reader* pReader, drwav_uint16* pDst)
+{
+ drwav_result result;
+ size_t bytesRead;
+ drwav_uint8 data[2];
+
+ DRWAV_ASSERT(pReader != NULL);
+ DRWAV_ASSERT(pDst != NULL);
+
+ *pDst = 0; /* Safety. */
+
+ result = drwav_buffer_reader_read(pReader, data, sizeof(*pDst), &bytesRead);
+ if (result != DRWAV_SUCCESS || bytesRead != sizeof(*pDst)) {
+ return result;
+ }
+
+ *pDst = drwav_bytes_to_u16(data);
+
+ return DRWAV_SUCCESS;
+}
+
+DRWAV_PRIVATE drwav_result drwav_buffer_reader_read_u32(drwav_buffer_reader* pReader, drwav_uint32* pDst)
+{
+ drwav_result result;
+ size_t bytesRead;
+ drwav_uint8 data[4];
+
+ DRWAV_ASSERT(pReader != NULL);
+ DRWAV_ASSERT(pDst != NULL);
+
+ *pDst = 0; /* Safety. */
+
+ result = drwav_buffer_reader_read(pReader, data, sizeof(*pDst), &bytesRead);
+ if (result != DRWAV_SUCCESS || bytesRead != sizeof(*pDst)) {
+ return result;
+ }
+
+ *pDst = drwav_bytes_to_u32(data);
+
+ return DRWAV_SUCCESS;
+}
+
+
+
+DRWAV_PRIVATE drwav_uint64 drwav__read_bext_to_metadata_obj(drwav__metadata_parser* pParser, drwav_metadata* pMetadata, drwav_uint64 chunkSize)
+{
+ drwav_uint8 bextData[DRWAV_BEXT_BYTES];
+ size_t bytesRead = drwav__metadata_parser_read(pParser, bextData, sizeof(bextData), NULL);
+
+ DRWAV_ASSERT(pParser->stage == drwav__metadata_parser_stage_read);
+
+ if (bytesRead == sizeof(bextData)) {
+ drwav_buffer_reader reader;
+ drwav_uint32 timeReferenceLow;
+ drwav_uint32 timeReferenceHigh;
+ size_t extraBytes;
+
+ pMetadata->type = drwav_metadata_type_bext;
+
+ if (drwav_buffer_reader_init(bextData, bytesRead, &reader) == DRWAV_SUCCESS) {
+ pMetadata->data.bext.pDescription = drwav__metadata_copy_string(pParser, (const char*)drwav_buffer_reader_ptr(&reader), DRWAV_BEXT_DESCRIPTION_BYTES);
+ drwav_buffer_reader_seek(&reader, DRWAV_BEXT_DESCRIPTION_BYTES);
+
+ pMetadata->data.bext.pOriginatorName = drwav__metadata_copy_string(pParser, (const char*)drwav_buffer_reader_ptr(&reader), DRWAV_BEXT_ORIGINATOR_NAME_BYTES);
+ drwav_buffer_reader_seek(&reader, DRWAV_BEXT_ORIGINATOR_NAME_BYTES);
+
+ pMetadata->data.bext.pOriginatorReference = drwav__metadata_copy_string(pParser, (const char*)drwav_buffer_reader_ptr(&reader), DRWAV_BEXT_ORIGINATOR_REF_BYTES);
+ drwav_buffer_reader_seek(&reader, DRWAV_BEXT_ORIGINATOR_REF_BYTES);
+
+ drwav_buffer_reader_read(&reader, pMetadata->data.bext.pOriginationDate, sizeof(pMetadata->data.bext.pOriginationDate), NULL);
+ drwav_buffer_reader_read(&reader, pMetadata->data.bext.pOriginationTime, sizeof(pMetadata->data.bext.pOriginationTime), NULL);
+
+ drwav_buffer_reader_read_u32(&reader, &timeReferenceLow);
+ drwav_buffer_reader_read_u32(&reader, &timeReferenceHigh);
+ pMetadata->data.bext.timeReference = ((drwav_uint64)timeReferenceHigh << 32) + timeReferenceLow;
+
+ drwav_buffer_reader_read_u16(&reader, &pMetadata->data.bext.version);
+
+ pMetadata->data.bext.pUMID = drwav__metadata_get_memory(pParser, DRWAV_BEXT_UMID_BYTES, 1);
+ drwav_buffer_reader_read(&reader, pMetadata->data.bext.pUMID, DRWAV_BEXT_UMID_BYTES, NULL);
+
+ drwav_buffer_reader_read_u16(&reader, &pMetadata->data.bext.loudnessValue);
+ drwav_buffer_reader_read_u16(&reader, &pMetadata->data.bext.loudnessRange);
+ drwav_buffer_reader_read_u16(&reader, &pMetadata->data.bext.maxTruePeakLevel);
+ drwav_buffer_reader_read_u16(&reader, &pMetadata->data.bext.maxMomentaryLoudness);
+ drwav_buffer_reader_read_u16(&reader, &pMetadata->data.bext.maxShortTermLoudness);
+
+ DRWAV_ASSERT((drwav_offset_ptr(drwav_buffer_reader_ptr(&reader), DRWAV_BEXT_RESERVED_BYTES)) == (bextData + DRWAV_BEXT_BYTES));
+
+ extraBytes = (size_t)(chunkSize - DRWAV_BEXT_BYTES);
+ if (extraBytes > 0) {
+ pMetadata->data.bext.pCodingHistory = (char*)drwav__metadata_get_memory(pParser, extraBytes + 1, 1);
+ DRWAV_ASSERT(pMetadata->data.bext.pCodingHistory != NULL);
+
+ bytesRead += drwav__metadata_parser_read(pParser, pMetadata->data.bext.pCodingHistory, extraBytes, NULL);
+ pMetadata->data.bext.codingHistorySize = (drwav_uint32)drwav__strlen(pMetadata->data.bext.pCodingHistory);
+ } else {
+ pMetadata->data.bext.pCodingHistory = NULL;
+ pMetadata->data.bext.codingHistorySize = 0;
+ }
+ }
+ }
+
+ return bytesRead;
+}
+
+DRWAV_PRIVATE drwav_uint64 drwav__read_list_label_or_note_to_metadata_obj(drwav__metadata_parser* pParser, drwav_metadata* pMetadata, drwav_uint64 chunkSize, drwav_metadata_type type)
+{
+ drwav_uint8 cueIDBuffer[DRWAV_LIST_LABEL_OR_NOTE_BYTES];
+ drwav_uint64 totalBytesRead = 0;
+ size_t bytesJustRead = drwav__metadata_parser_read(pParser, cueIDBuffer, sizeof(cueIDBuffer), &totalBytesRead);
+
+ DRWAV_ASSERT(pParser->stage == drwav__metadata_parser_stage_read);
+
+ if (bytesJustRead == sizeof(cueIDBuffer)) {
+ drwav_uint32 sizeIncludingNullTerminator;
+
+ pMetadata->type = type;
+ pMetadata->data.labelOrNote.cuePointId = drwav_bytes_to_u32(cueIDBuffer);
+
+ sizeIncludingNullTerminator = (drwav_uint32)chunkSize - DRWAV_LIST_LABEL_OR_NOTE_BYTES;
+ if (sizeIncludingNullTerminator > 0) {
+ pMetadata->data.labelOrNote.stringLength = sizeIncludingNullTerminator - 1;
+ pMetadata->data.labelOrNote.pString = (char*)drwav__metadata_get_memory(pParser, sizeIncludingNullTerminator, 1);
+ DRWAV_ASSERT(pMetadata->data.labelOrNote.pString != NULL);
+
+ drwav__metadata_parser_read(pParser, pMetadata->data.labelOrNote.pString, sizeIncludingNullTerminator, &totalBytesRead);
+ } else {
+ pMetadata->data.labelOrNote.stringLength = 0;
+ pMetadata->data.labelOrNote.pString = NULL;
+ }
+ }
+
+ return totalBytesRead;
+}
+
+DRWAV_PRIVATE drwav_uint64 drwav__read_list_labelled_cue_region_to_metadata_obj(drwav__metadata_parser* pParser, drwav_metadata* pMetadata, drwav_uint64 chunkSize)
+{
+ drwav_uint8 buffer[DRWAV_LIST_LABELLED_TEXT_BYTES];
+ drwav_uint64 totalBytesRead = 0;
+ size_t bytesJustRead = drwav__metadata_parser_read(pParser, buffer, sizeof(buffer), &totalBytesRead);
+
+ DRWAV_ASSERT(pParser->stage == drwav__metadata_parser_stage_read);
+
+ if (bytesJustRead == sizeof(buffer)) {
+ drwav_uint32 sizeIncludingNullTerminator;
+
+ pMetadata->type = drwav_metadata_type_list_labelled_cue_region;
+ pMetadata->data.labelledCueRegion.cuePointId = drwav_bytes_to_u32(buffer + 0);
+ pMetadata->data.labelledCueRegion.sampleLength = drwav_bytes_to_u32(buffer + 4);
+ pMetadata->data.labelledCueRegion.purposeId[0] = buffer[8];
+ pMetadata->data.labelledCueRegion.purposeId[1] = buffer[9];
+ pMetadata->data.labelledCueRegion.purposeId[2] = buffer[10];
+ pMetadata->data.labelledCueRegion.purposeId[3] = buffer[11];
+ pMetadata->data.labelledCueRegion.country = drwav_bytes_to_u16(buffer + 12);
+ pMetadata->data.labelledCueRegion.language = drwav_bytes_to_u16(buffer + 14);
+ pMetadata->data.labelledCueRegion.dialect = drwav_bytes_to_u16(buffer + 16);
+ pMetadata->data.labelledCueRegion.codePage = drwav_bytes_to_u16(buffer + 18);
+
+ sizeIncludingNullTerminator = (drwav_uint32)chunkSize - DRWAV_LIST_LABELLED_TEXT_BYTES;
+ if (sizeIncludingNullTerminator > 0) {
+ pMetadata->data.labelledCueRegion.stringLength = sizeIncludingNullTerminator - 1;
+ pMetadata->data.labelledCueRegion.pString = (char*)drwav__metadata_get_memory(pParser, sizeIncludingNullTerminator, 1);
+ DRWAV_ASSERT(pMetadata->data.labelledCueRegion.pString != NULL);
+
+ drwav__metadata_parser_read(pParser, pMetadata->data.labelledCueRegion.pString, sizeIncludingNullTerminator, &totalBytesRead);
+ } else {
+ pMetadata->data.labelledCueRegion.stringLength = 0;
+ pMetadata->data.labelledCueRegion.pString = NULL;
+ }
+ }
+
+ return totalBytesRead;
+}
+
+DRWAV_PRIVATE drwav_uint64 drwav__metadata_process_info_text_chunk(drwav__metadata_parser* pParser, drwav_uint64 chunkSize, drwav_metadata_type type)
+{
+ drwav_uint64 bytesRead = 0;
+ drwav_uint32 stringSizeWithNullTerminator = (drwav_uint32)chunkSize;
+
+ if (pParser->stage == drwav__metadata_parser_stage_count) {
+ pParser->metadataCount += 1;
+ drwav__metadata_request_extra_memory_for_stage_2(pParser, stringSizeWithNullTerminator, 1);
+ } else {
+ drwav_metadata* pMetadata = &pParser->pMetadata[pParser->metadataCursor];
+ pMetadata->type = type;
+ if (stringSizeWithNullTerminator > 0) {
+ pMetadata->data.infoText.stringLength = stringSizeWithNullTerminator - 1;
+ pMetadata->data.infoText.pString = (char*)drwav__metadata_get_memory(pParser, stringSizeWithNullTerminator, 1);
+ DRWAV_ASSERT(pMetadata->data.infoText.pString != NULL);
+
+ bytesRead = drwav__metadata_parser_read(pParser, pMetadata->data.infoText.pString, (size_t)stringSizeWithNullTerminator, NULL);
+ if (bytesRead == chunkSize) {
+ pParser->metadataCursor += 1;
+ } else {
+ /* Failed to parse. */
+ }
+ } else {
+ pMetadata->data.infoText.stringLength = 0;
+ pMetadata->data.infoText.pString = NULL;
+ pParser->metadataCursor += 1;
+ }
+ }
+
+ return bytesRead;
+}
+
+DRWAV_PRIVATE drwav_uint64 drwav__metadata_process_unknown_chunk(drwav__metadata_parser* pParser, const drwav_uint8* pChunkId, drwav_uint64 chunkSize, drwav_metadata_location location)
+{
+ drwav_uint64 bytesRead = 0;
+
+ if (location == drwav_metadata_location_invalid) {
+ return 0;
+ }
+
+ if (drwav_fourcc_equal(pChunkId, "data") || drwav_fourcc_equal(pChunkId, "fmt ") || drwav_fourcc_equal(pChunkId, "fact")) {
+ return 0;
+ }
+
+ if (pParser->stage == drwav__metadata_parser_stage_count) {
+ pParser->metadataCount += 1;
+ drwav__metadata_request_extra_memory_for_stage_2(pParser, (size_t)chunkSize, 1);
+ } else {
+ drwav_metadata* pMetadata = &pParser->pMetadata[pParser->metadataCursor];
+ pMetadata->type = drwav_metadata_type_unknown;
+ pMetadata->data.unknown.chunkLocation = location;
+ pMetadata->data.unknown.id[0] = pChunkId[0];
+ pMetadata->data.unknown.id[1] = pChunkId[1];
+ pMetadata->data.unknown.id[2] = pChunkId[2];
+ pMetadata->data.unknown.id[3] = pChunkId[3];
+ pMetadata->data.unknown.dataSizeInBytes = (drwav_uint32)chunkSize;
+ pMetadata->data.unknown.pData = (drwav_uint8 *)drwav__metadata_get_memory(pParser, (size_t)chunkSize, 1);
+ DRWAV_ASSERT(pMetadata->data.unknown.pData != NULL);
+
+ bytesRead = drwav__metadata_parser_read(pParser, pMetadata->data.unknown.pData, pMetadata->data.unknown.dataSizeInBytes, NULL);
+ if (bytesRead == pMetadata->data.unknown.dataSizeInBytes) {
+ pParser->metadataCursor += 1;
+ } else {
+ /* Failed to read. */
+ }
+ }
+
+ return bytesRead;
+}
+
+DRWAV_PRIVATE drwav_bool32 drwav__chunk_matches(drwav_metadata_type allowedMetadataTypes, const drwav_uint8* pChunkID, drwav_metadata_type type, const char* pID)
+{
+ return (allowedMetadataTypes & type) && drwav_fourcc_equal(pChunkID, pID);
+}
+
+DRWAV_PRIVATE drwav_uint64 drwav__metadata_process_chunk(drwav__metadata_parser* pParser, const drwav_chunk_header* pChunkHeader, drwav_metadata_type allowedMetadataTypes)
+{
+ const drwav_uint8 *pChunkID = pChunkHeader->id.fourcc;
+ drwav_uint64 bytesRead = 0;
+
+ if (drwav__chunk_matches(allowedMetadataTypes, pChunkID, drwav_metadata_type_smpl, "smpl")) {
+ if (pChunkHeader->sizeInBytes >= DRWAV_SMPL_BYTES) {
+ if (pParser->stage == drwav__metadata_parser_stage_count) {
+ drwav_uint8 buffer[4];
+ size_t bytesJustRead;
+
+ if (!pParser->onSeek(pParser->pReadSeekUserData, 28, drwav_seek_origin_current)) {
+ return bytesRead;
+ }
+ bytesRead += 28;
+
+ bytesJustRead = drwav__metadata_parser_read(pParser, buffer, sizeof(buffer), &bytesRead);
+ if (bytesJustRead == sizeof(buffer)) {
+ drwav_uint32 loopCount = drwav_bytes_to_u32(buffer);
+ drwav_uint64 calculatedLoopCount;
+
+ /* The loop count must be validated against the size of the chunk. */
+ calculatedLoopCount = (pChunkHeader->sizeInBytes - DRWAV_SMPL_BYTES) / DRWAV_SMPL_LOOP_BYTES;
+ if (calculatedLoopCount == loopCount) {
+ bytesJustRead = drwav__metadata_parser_read(pParser, buffer, sizeof(buffer), &bytesRead);
+ if (bytesJustRead == sizeof(buffer)) {
+ drwav_uint32 samplerSpecificDataSizeInBytes = drwav_bytes_to_u32(buffer);
+
+ pParser->metadataCount += 1;
+ drwav__metadata_request_extra_memory_for_stage_2(pParser, sizeof(drwav_smpl_loop) * loopCount, DRWAV_METADATA_ALIGNMENT);
+ drwav__metadata_request_extra_memory_for_stage_2(pParser, samplerSpecificDataSizeInBytes, 1);
+ }
+ } else {
+ /* Loop count in header does not match the size of the chunk. */
+ }
+ }
+ } else {
+ bytesRead = drwav__read_smpl_to_metadata_obj(pParser, pChunkHeader, &pParser->pMetadata[pParser->metadataCursor]);
+ if (bytesRead == pChunkHeader->sizeInBytes) {
+ pParser->metadataCursor += 1;
+ } else {
+ /* Failed to parse. */
+ }
+ }
+ } else {
+ /* Incorrectly formed chunk. */
+ }
+ } else if (drwav__chunk_matches(allowedMetadataTypes, pChunkID, drwav_metadata_type_inst, "inst")) {
+ if (pChunkHeader->sizeInBytes == DRWAV_INST_BYTES) {
+ if (pParser->stage == drwav__metadata_parser_stage_count) {
+ pParser->metadataCount += 1;
+ } else {
+ bytesRead = drwav__read_inst_to_metadata_obj(pParser, &pParser->pMetadata[pParser->metadataCursor]);
+ if (bytesRead == pChunkHeader->sizeInBytes) {
+ pParser->metadataCursor += 1;
+ } else {
+ /* Failed to parse. */
+ }
+ }
+ } else {
+ /* Incorrectly formed chunk. */
+ }
+ } else if (drwav__chunk_matches(allowedMetadataTypes, pChunkID, drwav_metadata_type_acid, "acid")) {
+ if (pChunkHeader->sizeInBytes == DRWAV_ACID_BYTES) {
+ if (pParser->stage == drwav__metadata_parser_stage_count) {
+ pParser->metadataCount += 1;
+ } else {
+ bytesRead = drwav__read_acid_to_metadata_obj(pParser, &pParser->pMetadata[pParser->metadataCursor]);
+ if (bytesRead == pChunkHeader->sizeInBytes) {
+ pParser->metadataCursor += 1;
+ } else {
+ /* Failed to parse. */
+ }
+ }
+ } else {
+ /* Incorrectly formed chunk. */
+ }
+ } else if (drwav__chunk_matches(allowedMetadataTypes, pChunkID, drwav_metadata_type_cue, "cue ")) {
+ if (pChunkHeader->sizeInBytes >= DRWAV_CUE_BYTES) {
+ if (pParser->stage == drwav__metadata_parser_stage_count) {
+ size_t cueCount;
+
+ pParser->metadataCount += 1;
+ cueCount = (size_t)(pChunkHeader->sizeInBytes - DRWAV_CUE_BYTES) / DRWAV_CUE_POINT_BYTES;
+ drwav__metadata_request_extra_memory_for_stage_2(pParser, sizeof(drwav_cue_point) * cueCount, DRWAV_METADATA_ALIGNMENT);
+ } else {
+ bytesRead = drwav__read_cue_to_metadata_obj(pParser, pChunkHeader, &pParser->pMetadata[pParser->metadataCursor]);
+ if (bytesRead == pChunkHeader->sizeInBytes) {
+ pParser->metadataCursor += 1;
+ } else {
+ /* Failed to parse. */
+ }
+ }
+ } else {
+ /* Incorrectly formed chunk. */
+ }
+ } else if (drwav__chunk_matches(allowedMetadataTypes, pChunkID, drwav_metadata_type_bext, "bext")) {
+ if (pChunkHeader->sizeInBytes >= DRWAV_BEXT_BYTES) {
+ if (pParser->stage == drwav__metadata_parser_stage_count) {
+ /* The description field is the largest one in a bext chunk, so that is the max size of this temporary buffer. */
+ char buffer[DRWAV_BEXT_DESCRIPTION_BYTES + 1];
+ size_t allocSizeNeeded = DRWAV_BEXT_UMID_BYTES; /* We know we will need SMPTE umid size. */
+ size_t bytesJustRead;
+
+ buffer[DRWAV_BEXT_DESCRIPTION_BYTES] = '\0';
+ bytesJustRead = drwav__metadata_parser_read(pParser, buffer, DRWAV_BEXT_DESCRIPTION_BYTES, &bytesRead);
+ if (bytesJustRead != DRWAV_BEXT_DESCRIPTION_BYTES) {
+ return bytesRead;
+ }
+ allocSizeNeeded += drwav__strlen(buffer) + 1;
+
+ buffer[DRWAV_BEXT_ORIGINATOR_NAME_BYTES] = '\0';
+ bytesJustRead = drwav__metadata_parser_read(pParser, buffer, DRWAV_BEXT_ORIGINATOR_NAME_BYTES, &bytesRead);
+ if (bytesJustRead != DRWAV_BEXT_ORIGINATOR_NAME_BYTES) {
+ return bytesRead;
+ }
+ allocSizeNeeded += drwav__strlen(buffer) + 1;
+
+ buffer[DRWAV_BEXT_ORIGINATOR_REF_BYTES] = '\0';
+ bytesJustRead = drwav__metadata_parser_read(pParser, buffer, DRWAV_BEXT_ORIGINATOR_REF_BYTES, &bytesRead);
+ if (bytesJustRead != DRWAV_BEXT_ORIGINATOR_REF_BYTES) {
+ return bytesRead;
+ }
+ allocSizeNeeded += drwav__strlen(buffer) + 1;
+ allocSizeNeeded += (size_t)pChunkHeader->sizeInBytes - DRWAV_BEXT_BYTES; /* Coding history. */
+
+ drwav__metadata_request_extra_memory_for_stage_2(pParser, allocSizeNeeded, 1);
+
+ pParser->metadataCount += 1;
+ } else {
+ bytesRead = drwav__read_bext_to_metadata_obj(pParser, &pParser->pMetadata[pParser->metadataCursor], pChunkHeader->sizeInBytes);
+ if (bytesRead == pChunkHeader->sizeInBytes) {
+ pParser->metadataCursor += 1;
+ } else {
+ /* Failed to parse. */
+ }
+ }
+ } else {
+ /* Incorrectly formed chunk. */
+ }
+ } else if (drwav_fourcc_equal(pChunkID, "LIST") || drwav_fourcc_equal(pChunkID, "list")) {
+ drwav_metadata_location listType = drwav_metadata_location_invalid;
+ while (bytesRead < pChunkHeader->sizeInBytes) {
+ drwav_uint8 subchunkId[4];
+ drwav_uint8 subchunkSizeBuffer[4];
+ drwav_uint64 subchunkDataSize;
+ drwav_uint64 subchunkBytesRead = 0;
+ drwav_uint64 bytesJustRead = drwav__metadata_parser_read(pParser, subchunkId, sizeof(subchunkId), &bytesRead);
+ if (bytesJustRead != sizeof(subchunkId)) {
+ break;
+ }
+
+ /*
+ The first thing in a list chunk should be "adtl" or "INFO".
+
+ - adtl means this list is a Associated Data List Chunk and will contain labels, notes
+ or labelled cue regions.
+ - INFO means this list is an Info List Chunk containing info text chunks such as IPRD
+ which would specifies the album of this wav file.
+
+ No data follows the adtl or INFO id so we just make note of what type this list is and
+ continue.
+ */
+ if (drwav_fourcc_equal(subchunkId, "adtl")) {
+ listType = drwav_metadata_location_inside_adtl_list;
+ continue;
+ } else if (drwav_fourcc_equal(subchunkId, "INFO")) {
+ listType = drwav_metadata_location_inside_info_list;
+ continue;
+ }
+
+ bytesJustRead = drwav__metadata_parser_read(pParser, subchunkSizeBuffer, sizeof(subchunkSizeBuffer), &bytesRead);
+ if (bytesJustRead != sizeof(subchunkSizeBuffer)) {
+ break;
+ }
+ subchunkDataSize = drwav_bytes_to_u32(subchunkSizeBuffer);
+
+ if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_label, "labl") || drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_note, "note")) {
+ if (subchunkDataSize >= DRWAV_LIST_LABEL_OR_NOTE_BYTES) {
+ drwav_uint64 stringSizeWithNullTerm = subchunkDataSize - DRWAV_LIST_LABEL_OR_NOTE_BYTES;
+ if (pParser->stage == drwav__metadata_parser_stage_count) {
+ pParser->metadataCount += 1;
+ drwav__metadata_request_extra_memory_for_stage_2(pParser, (size_t)stringSizeWithNullTerm, 1);
+ } else {
+ subchunkBytesRead = drwav__read_list_label_or_note_to_metadata_obj(pParser, &pParser->pMetadata[pParser->metadataCursor], subchunkDataSize, drwav_fourcc_equal(subchunkId, "labl") ? drwav_metadata_type_list_label : drwav_metadata_type_list_note);
+ if (subchunkBytesRead == subchunkDataSize) {
+ pParser->metadataCursor += 1;
+ } else {
+ /* Failed to parse. */
+ }
+ }
+ } else {
+ /* Incorrectly formed chunk. */
+ }
+ } else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_labelled_cue_region, "ltxt")) {
+ if (subchunkDataSize >= DRWAV_LIST_LABELLED_TEXT_BYTES) {
+ drwav_uint64 stringSizeWithNullTerminator = subchunkDataSize - DRWAV_LIST_LABELLED_TEXT_BYTES;
+ if (pParser->stage == drwav__metadata_parser_stage_count) {
+ pParser->metadataCount += 1;
+ drwav__metadata_request_extra_memory_for_stage_2(pParser, (size_t)stringSizeWithNullTerminator, 1);
+ } else {
+ subchunkBytesRead = drwav__read_list_labelled_cue_region_to_metadata_obj(pParser, &pParser->pMetadata[pParser->metadataCursor], subchunkDataSize);
+ if (subchunkBytesRead == subchunkDataSize) {
+ pParser->metadataCursor += 1;
+ } else {
+ /* Failed to parse. */
+ }
+ }
+ } else {
+ /* Incorrectly formed chunk. */
+ }
+ } else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_software, "ISFT")) {
+ subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize, drwav_metadata_type_list_info_software);
+ } else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_copyright, "ICOP")) {
+ subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize, drwav_metadata_type_list_info_copyright);
+ } else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_title, "INAM")) {
+ subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize, drwav_metadata_type_list_info_title);
+ } else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_artist, "IART")) {
+ subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize, drwav_metadata_type_list_info_artist);
+ } else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_comment, "ICMT")) {
+ subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize, drwav_metadata_type_list_info_comment);
+ } else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_date, "ICRD")) {
+ subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize, drwav_metadata_type_list_info_date);
+ } else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_genre, "IGNR")) {
+ subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize, drwav_metadata_type_list_info_genre);
+ } else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_album, "IPRD")) {
+ subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize, drwav_metadata_type_list_info_album);
+ } else if (drwav__chunk_matches(allowedMetadataTypes, subchunkId, drwav_metadata_type_list_info_tracknumber, "ITRK")) {
+ subchunkBytesRead = drwav__metadata_process_info_text_chunk(pParser, subchunkDataSize, drwav_metadata_type_list_info_tracknumber);
+ } else if ((allowedMetadataTypes & drwav_metadata_type_unknown) != 0) {
+ subchunkBytesRead = drwav__metadata_process_unknown_chunk(pParser, subchunkId, subchunkDataSize, listType);
+ }
+
+ bytesRead += subchunkBytesRead;
+ DRWAV_ASSERT(subchunkBytesRead <= subchunkDataSize);
+
+ if (subchunkBytesRead < subchunkDataSize) {
+ drwav_uint64 bytesToSeek = subchunkDataSize - subchunkBytesRead;
+
+ if (!pParser->onSeek(pParser->pReadSeekUserData, (int)bytesToSeek, drwav_seek_origin_current)) {
+ break;
+ }
+ bytesRead += bytesToSeek;
+ }
+
+ if ((subchunkDataSize % 2) == 1) {
+ if (!pParser->onSeek(pParser->pReadSeekUserData, 1, drwav_seek_origin_current)) {
+ break;
+ }
+ bytesRead += 1;
+ }
+ }
+ } else if ((allowedMetadataTypes & drwav_metadata_type_unknown) != 0) {
+ bytesRead = drwav__metadata_process_unknown_chunk(pParser, pChunkID, pChunkHeader->sizeInBytes, drwav_metadata_location_top_level);
+ }
+
+ return bytesRead;
+}
+
+
+DRWAV_PRIVATE drwav_uint32 drwav_get_bytes_per_pcm_frame(drwav* pWav)
+{
+ drwav_uint32 bytesPerFrame;
+
+ /*
+ The bytes per frame is a bit ambiguous. It can be either be based on the bits per sample, or the block align. The way I'm doing it here
+ is that if the bits per sample is a multiple of 8, use floor(bitsPerSample*channels/8), otherwise fall back to the block align.
+ */
+ if ((pWav->bitsPerSample & 0x7) == 0) {
+ /* Bits per sample is a multiple of 8. */
+ bytesPerFrame = (pWav->bitsPerSample * pWav->fmt.channels) >> 3;
+ } else {
+ bytesPerFrame = pWav->fmt.blockAlign;
+ }
+
+ /* Validation for known formats. a-law and mu-law should be 1 byte per channel. If it's not, it's not decodable. */
+ if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ALAW || pWav->translatedFormatTag == DR_WAVE_FORMAT_MULAW) {
+ if (bytesPerFrame != pWav->fmt.channels) {
+ return 0; /* Invalid file. */
+ }
+ }
+
+ return bytesPerFrame;
+}
+
+DRWAV_API drwav_uint16 drwav_fmt_get_format(const drwav_fmt* pFMT)
+{
+ if (pFMT == NULL) {
+ return 0;
+ }
+
+ if (pFMT->formatTag != DR_WAVE_FORMAT_EXTENSIBLE) {
+ return pFMT->formatTag;
+ } else {
+ return drwav_bytes_to_u16(pFMT->subFormat); /* Only the first two bytes are required. */
+ }
+}
+
+DRWAV_PRIVATE drwav_bool32 drwav_preinit(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, void* pReadSeekUserData, const drwav_allocation_callbacks* pAllocationCallbacks)
+{
+ if (pWav == NULL || onRead == NULL || onSeek == NULL) {
+ return DRWAV_FALSE;
+ }
+
+ DRWAV_ZERO_MEMORY(pWav, sizeof(*pWav));
+ pWav->onRead = onRead;
+ pWav->onSeek = onSeek;
+ pWav->pUserData = pReadSeekUserData;
+ pWav->allocationCallbacks = drwav_copy_allocation_callbacks_or_defaults(pAllocationCallbacks);
+
+ if (pWav->allocationCallbacks.onFree == NULL || (pWav->allocationCallbacks.onMalloc == NULL && pWav->allocationCallbacks.onRealloc == NULL)) {
+ return DRWAV_FALSE; /* Invalid allocation callbacks. */
+ }
+
+ return DRWAV_TRUE;
+}
+
+DRWAV_PRIVATE drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc onChunk, void* pChunkUserData, drwav_uint32 flags)
+{
+ /* This function assumes drwav_preinit() has been called beforehand. */
+ drwav_result result;
+ drwav_uint64 cursor; /* <-- Keeps track of the byte position so we can seek to specific locations. */
+ drwav_bool32 sequential;
+ drwav_uint8 riff[4];
+ drwav_fmt fmt;
+ unsigned short translatedFormatTag;
+ drwav_uint64 dataChunkSize = 0; /* <-- Important! Don't explicitly set this to 0 anywhere else. Calculation of the size of the data chunk is performed in different paths depending on the container. */
+ drwav_uint64 sampleCountFromFactChunk = 0; /* Same as dataChunkSize - make sure this is the only place this is initialized to 0. */
+ drwav_uint64 metadataStartPos;
+ drwav__metadata_parser metadataParser;
+ drwav_bool8 isProcessingMetadata = DRWAV_FALSE;
+ drwav_bool8 foundChunk_fmt = DRWAV_FALSE;
+ drwav_bool8 foundChunk_data = DRWAV_FALSE;
+ drwav_bool8 isAIFCFormType = DRWAV_FALSE; /* Only used with AIFF. */
+ drwav_uint64 aiffFrameCount = 0;
+
+ cursor = 0;
+ sequential = (flags & DRWAV_SEQUENTIAL) != 0;
+ DRWAV_ZERO_OBJECT(&fmt);
+
+ /* The first 4 bytes should be the RIFF identifier. */
+ if (drwav__on_read(pWav->onRead, pWav->pUserData, riff, sizeof(riff), &cursor) != sizeof(riff)) {
+ return DRWAV_FALSE;
+ }
+
+ /*
+ The first 4 bytes can be used to identify the container. For RIFF files it will start with "RIFF" and for
+ w64 it will start with "riff".
+ */
+ if (drwav_fourcc_equal(riff, "RIFF")) {
+ pWav->container = drwav_container_riff;
+ } else if (drwav_fourcc_equal(riff, "RIFX")) {
+ pWav->container = drwav_container_rifx;
+ } else if (drwav_fourcc_equal(riff, "riff")) {
+ int i;
+ drwav_uint8 riff2[12];
+
+ pWav->container = drwav_container_w64;
+
+ /* Check the rest of the GUID for validity. */
+ if (drwav__on_read(pWav->onRead, pWav->pUserData, riff2, sizeof(riff2), &cursor) != sizeof(riff2)) {
+ return DRWAV_FALSE;
+ }
+
+ for (i = 0; i < 12; ++i) {
+ if (riff2[i] != drwavGUID_W64_RIFF[i+4]) {
+ return DRWAV_FALSE;
+ }
+ }
+ } else if (drwav_fourcc_equal(riff, "RF64")) {
+ pWav->container = drwav_container_rf64;
+ } else if (drwav_fourcc_equal(riff, "FORM")) {
+ pWav->container = drwav_container_aiff;
+ } else {
+ return DRWAV_FALSE; /* Unknown or unsupported container. */
+ }
+
+
+ if (pWav->container == drwav_container_riff || pWav->container == drwav_container_rifx || pWav->container == drwav_container_rf64) {
+ drwav_uint8 chunkSizeBytes[4];
+ drwav_uint8 wave[4];
+
+ if (drwav__on_read(pWav->onRead, pWav->pUserData, chunkSizeBytes, sizeof(chunkSizeBytes), &cursor) != sizeof(chunkSizeBytes)) {
+ return DRWAV_FALSE;
+ }
+
+ if (pWav->container == drwav_container_riff || pWav->container == drwav_container_rifx) {
+ if (drwav_bytes_to_u32_ex(chunkSizeBytes, pWav->container) < 36) {
+ /*
+ I've had a report of a WAV file failing to load when the size of the WAVE chunk is not encoded
+ and is instead just set to 0. I'm going to relax the validation here to allow these files to
+ load. Considering the chunk size isn't actually used this should be safe. With this change my
+ test suite still passes.
+ */
+ /*return DRWAV_FALSE;*/ /* Chunk size should always be at least 36 bytes. */
+ }
+ } else if (pWav->container == drwav_container_rf64) {
+ if (drwav_bytes_to_u32_le(chunkSizeBytes) != 0xFFFFFFFF) {
+ return DRWAV_FALSE; /* Chunk size should always be set to -1/0xFFFFFFFF for RF64. The actual size is retrieved later. */
+ }
+ } else {
+ return DRWAV_FALSE; /* Should never hit this. */
+ }
+
+ if (drwav__on_read(pWav->onRead, pWav->pUserData, wave, sizeof(wave), &cursor) != sizeof(wave)) {
+ return DRWAV_FALSE;
+ }
+
+ if (!drwav_fourcc_equal(wave, "WAVE")) {
+ return DRWAV_FALSE; /* Expecting "WAVE". */
+ }
+ } else if (pWav->container == drwav_container_w64) {
+ drwav_uint8 chunkSizeBytes[8];
+ drwav_uint8 wave[16];
+
+ if (drwav__on_read(pWav->onRead, pWav->pUserData, chunkSizeBytes, sizeof(chunkSizeBytes), &cursor) != sizeof(chunkSizeBytes)) {
+ return DRWAV_FALSE;
+ }
+
+ if (drwav_bytes_to_u64(chunkSizeBytes) < 80) {
+ return DRWAV_FALSE;
+ }
+
+ if (drwav__on_read(pWav->onRead, pWav->pUserData, wave, sizeof(wave), &cursor) != sizeof(wave)) {
+ return DRWAV_FALSE;
+ }
+
+ if (!drwav_guid_equal(wave, drwavGUID_W64_WAVE)) {
+ return DRWAV_FALSE;
+ }
+ } else if (pWav->container == drwav_container_aiff) {
+ drwav_uint8 chunkSizeBytes[4];
+ drwav_uint8 aiff[4];
+
+ if (drwav__on_read(pWav->onRead, pWav->pUserData, chunkSizeBytes, sizeof(chunkSizeBytes), &cursor) != sizeof(chunkSizeBytes)) {
+ return DRWAV_FALSE;
+ }
+
+ if (drwav_bytes_to_u32_be(chunkSizeBytes) < 18) {
+ return DRWAV_FALSE;
+ }
+
+ if (drwav__on_read(pWav->onRead, pWav->pUserData, aiff, sizeof(aiff), &cursor) != sizeof(aiff)) {
+ return DRWAV_FALSE;
+ }
+
+ if (drwav_fourcc_equal(aiff, "AIFF")) {
+ isAIFCFormType = DRWAV_FALSE;
+ } else if (drwav_fourcc_equal(aiff, "AIFC")) {
+ isAIFCFormType = DRWAV_TRUE;
+ } else {
+ return DRWAV_FALSE; /* Expecting "AIFF" or "AIFC". */
+ }
+ } else {
+ return DRWAV_FALSE;
+ }
+
+
+ /* For RF64, the "ds64" chunk must come next, before the "fmt " chunk. */
+ if (pWav->container == drwav_container_rf64) {
+ drwav_uint8 sizeBytes[8];
+ drwav_uint64 bytesRemainingInChunk;
+ drwav_chunk_header header;
+ result = drwav__read_chunk_header(pWav->onRead, pWav->pUserData, pWav->container, &cursor, &header);
+ if (result != DRWAV_SUCCESS) {
+ return DRWAV_FALSE;
+ }
+
+ if (!drwav_fourcc_equal(header.id.fourcc, "ds64")) {
+ return DRWAV_FALSE; /* Expecting "ds64". */
+ }
+
+ bytesRemainingInChunk = header.sizeInBytes + header.paddingSize;
+
+ /* We don't care about the size of the RIFF chunk - skip it. */
+ if (!drwav__seek_forward(pWav->onSeek, 8, pWav->pUserData)) {
+ return DRWAV_FALSE;
+ }
+ bytesRemainingInChunk -= 8;
+ cursor += 8;
+
+
+ /* Next 8 bytes is the size of the "data" chunk. */
+ if (drwav__on_read(pWav->onRead, pWav->pUserData, sizeBytes, sizeof(sizeBytes), &cursor) != sizeof(sizeBytes)) {
+ return DRWAV_FALSE;
+ }
+ bytesRemainingInChunk -= 8;
+ dataChunkSize = drwav_bytes_to_u64(sizeBytes);
+
+
+ /* Next 8 bytes is the same count which we would usually derived from the FACT chunk if it was available. */
+ if (drwav__on_read(pWav->onRead, pWav->pUserData, sizeBytes, sizeof(sizeBytes), &cursor) != sizeof(sizeBytes)) {
+ return DRWAV_FALSE;
+ }
+ bytesRemainingInChunk -= 8;
+ sampleCountFromFactChunk = drwav_bytes_to_u64(sizeBytes);
+
+
+ /* Skip over everything else. */
+ if (!drwav__seek_forward(pWav->onSeek, bytesRemainingInChunk, pWav->pUserData)) {
+ return DRWAV_FALSE;
+ }
+ cursor += bytesRemainingInChunk;
+ }
+
+
+ metadataStartPos = cursor;
+
+ /*
+ Whether or not we are processing metadata controls how we load. We can load more efficiently when
+ metadata is not being processed, but we also cannot process metadata for Wave64 because I have not
+ been able to test it. If someone is able to test this and provide a patch I'm happy to enable it.
+
+ Seqential mode cannot support metadata because it involves seeking backwards.
+ */
+ isProcessingMetadata = !sequential && ((flags & DRWAV_WITH_METADATA) != 0);
+
+ /* Don't allow processing of metadata with untested containers. */
+ if (pWav->container != drwav_container_riff && pWav->container != drwav_container_rf64) {
+ isProcessingMetadata = DRWAV_FALSE;
+ }
+
+ DRWAV_ZERO_MEMORY(&metadataParser, sizeof(metadataParser));
+ if (isProcessingMetadata) {
+ metadataParser.onRead = pWav->onRead;
+ metadataParser.onSeek = pWav->onSeek;
+ metadataParser.pReadSeekUserData = pWav->pUserData;
+ metadataParser.stage = drwav__metadata_parser_stage_count;
+ }
+
+
+ /*
+ From here on out, chunks might be in any order. In order to robustly handle metadata we'll need
+ to loop through every chunk and handle them as we find them. In sequential mode we need to get
+ out of the loop as soon as we find the data chunk because we won't be able to seek back.
+ */
+ for (;;) { /* For each chunk... */
+ drwav_chunk_header header;
+ drwav_uint64 chunkSize;
+
+ result = drwav__read_chunk_header(pWav->onRead, pWav->pUserData, pWav->container, &cursor, &header);
+ if (result != DRWAV_SUCCESS) {
+ break;
+ }
+
+ chunkSize = header.sizeInBytes;
+
+
+ /*
+ Always tell the caller about this chunk. We cannot do this in sequential mode because the
+ callback is allowed to read from the file, in which case we'll need to rewind.
+ */
+ if (!sequential && onChunk != NULL) {
+ drwav_uint64 callbackBytesRead = onChunk(pChunkUserData, pWav->onRead, pWav->onSeek, pWav->pUserData, &header, pWav->container, &fmt);
+
+ /*
+ dr_wav may need to read the contents of the chunk, so we now need to seek back to the position before
+ we called the callback.
+ */
+ if (callbackBytesRead > 0) {
+ if (drwav__seek_from_start(pWav->onSeek, cursor, pWav->pUserData) == DRWAV_FALSE) {
+ return DRWAV_FALSE;
+ }
+ }
+ }
+
+
+ /* Explicitly handle known chunks first. */
+
+ /* "fmt " */
+ if (((pWav->container == drwav_container_riff || pWav->container == drwav_container_rifx || pWav->container == drwav_container_rf64) && drwav_fourcc_equal(header.id.fourcc, "fmt ")) ||
+ ((pWav->container == drwav_container_w64) && drwav_guid_equal(header.id.guid, drwavGUID_W64_FMT))) {
+ drwav_uint8 fmtData[16];
+
+ foundChunk_fmt = DRWAV_TRUE;
+
+ if (pWav->onRead(pWav->pUserData, fmtData, sizeof(fmtData)) != sizeof(fmtData)) {
+ return DRWAV_FALSE;
+ }
+ cursor += sizeof(fmtData);
+
+ fmt.formatTag = drwav_bytes_to_u16_ex(fmtData + 0, pWav->container);
+ fmt.channels = drwav_bytes_to_u16_ex(fmtData + 2, pWav->container);
+ fmt.sampleRate = drwav_bytes_to_u32_ex(fmtData + 4, pWav->container);
+ fmt.avgBytesPerSec = drwav_bytes_to_u32_ex(fmtData + 8, pWav->container);
+ fmt.blockAlign = drwav_bytes_to_u16_ex(fmtData + 12, pWav->container);
+ fmt.bitsPerSample = drwav_bytes_to_u16_ex(fmtData + 14, pWav->container);
+
+ fmt.extendedSize = 0;
+ fmt.validBitsPerSample = 0;
+ fmt.channelMask = 0;
+ DRWAV_ZERO_MEMORY(fmt.subFormat, sizeof(fmt.subFormat));
+
+ if (header.sizeInBytes > 16) {
+ drwav_uint8 fmt_cbSize[2];
+ int bytesReadSoFar = 0;
+
+ if (pWav->onRead(pWav->pUserData, fmt_cbSize, sizeof(fmt_cbSize)) != sizeof(fmt_cbSize)) {
+ return DRWAV_FALSE; /* Expecting more data. */
+ }
+ cursor += sizeof(fmt_cbSize);
+
+ bytesReadSoFar = 18;
+
+ fmt.extendedSize = drwav_bytes_to_u16_ex(fmt_cbSize, pWav->container);
+ if (fmt.extendedSize > 0) {
+ /* Simple validation. */
+ if (fmt.formatTag == DR_WAVE_FORMAT_EXTENSIBLE) {
+ if (fmt.extendedSize != 22) {
+ return DRWAV_FALSE;
+ }
+ }
+
+ if (fmt.formatTag == DR_WAVE_FORMAT_EXTENSIBLE) {
+ drwav_uint8 fmtext[22];
+
+ if (pWav->onRead(pWav->pUserData, fmtext, fmt.extendedSize) != fmt.extendedSize) {
+ return DRWAV_FALSE; /* Expecting more data. */
+ }
+
+ fmt.validBitsPerSample = drwav_bytes_to_u16_ex(fmtext + 0, pWav->container);
+ fmt.channelMask = drwav_bytes_to_u32_ex(fmtext + 2, pWav->container);
+ drwav_bytes_to_guid(fmtext + 6, fmt.subFormat);
+ } else {
+ if (pWav->onSeek(pWav->pUserData, fmt.extendedSize, drwav_seek_origin_current) == DRWAV_FALSE) {
+ return DRWAV_FALSE;
+ }
+ }
+ cursor += fmt.extendedSize;
+
+ bytesReadSoFar += fmt.extendedSize;
+ }
+
+ /* Seek past any leftover bytes. For w64 the leftover will be defined based on the chunk size. */
+ if (pWav->onSeek(pWav->pUserData, (int)(header.sizeInBytes - bytesReadSoFar), drwav_seek_origin_current) == DRWAV_FALSE) {
+ return DRWAV_FALSE;
+ }
+ cursor += (header.sizeInBytes - bytesReadSoFar);
+ }
+
+ if (header.paddingSize > 0) {
+ if (drwav__seek_forward(pWav->onSeek, header.paddingSize, pWav->pUserData) == DRWAV_FALSE) {
+ break;
+ }
+ cursor += header.paddingSize;
+ }
+
+ /* Go to the next chunk. Don't include this chunk in metadata. */
+ continue;
+ }
+
+ /* "data" */
+ if (((pWav->container == drwav_container_riff || pWav->container == drwav_container_rifx || pWav->container == drwav_container_rf64) && drwav_fourcc_equal(header.id.fourcc, "data")) ||
+ ((pWav->container == drwav_container_w64) && drwav_guid_equal(header.id.guid, drwavGUID_W64_DATA))) {
+ foundChunk_data = DRWAV_TRUE;
+
+ pWav->dataChunkDataPos = cursor;
+
+ if (pWav->container != drwav_container_rf64) { /* The data chunk size for RF64 will always be set to 0xFFFFFFFF here. It was set to it's true value earlier. */
+ dataChunkSize = chunkSize;
+ }
+
+ /* If we're running in sequential mode, or we're not reading metadata, we have enough now that we can get out of the loop. */
+ if (sequential || !isProcessingMetadata) {
+ break; /* No need to keep reading beyond the data chunk. */
+ } else {
+ chunkSize += header.paddingSize; /* <-- Make sure we seek past the padding. */
+ if (drwav__seek_forward(pWav->onSeek, chunkSize, pWav->pUserData) == DRWAV_FALSE) {
+ break;
+ }
+ cursor += chunkSize;
+
+ continue; /* There may be some more metadata to read. */
+ }
+ }
+
+ /* "fact". This is optional. Can use this to get the sample count which is useful for compressed formats. For RF64 we retrieved the sample count from the ds64 chunk earlier. */
+ if (((pWav->container == drwav_container_riff || pWav->container == drwav_container_rifx || pWav->container == drwav_container_rf64) && drwav_fourcc_equal(header.id.fourcc, "fact")) ||
+ ((pWav->container == drwav_container_w64) && drwav_guid_equal(header.id.guid, drwavGUID_W64_FACT))) {
+ if (pWav->container == drwav_container_riff || pWav->container == drwav_container_rifx) {
+ drwav_uint8 sampleCount[4];
+ if (drwav__on_read(pWav->onRead, pWav->pUserData, &sampleCount, 4, &cursor) != 4) {
+ return DRWAV_FALSE;
+ }
+
+ chunkSize -= 4;
+
+ /*
+ The sample count in the "fact" chunk is either unreliable, or I'm not understanding it properly. For now I am only enabling this
+ for Microsoft ADPCM formats.
+ */
+ if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM) {
+ sampleCountFromFactChunk = drwav_bytes_to_u32_ex(sampleCount, pWav->container);
+ } else {
+ sampleCountFromFactChunk = 0;
+ }
+ } else if (pWav->container == drwav_container_w64) {
+ if (drwav__on_read(pWav->onRead, pWav->pUserData, &sampleCountFromFactChunk, 8, &cursor) != 8) {
+ return DRWAV_FALSE;
+ }
+
+ chunkSize -= 8;
+ } else if (pWav->container == drwav_container_rf64) {
+ /* We retrieved the sample count from the ds64 chunk earlier so no need to do that here. */
+ }
+
+ /* Seek to the next chunk in preparation for the next iteration. */
+ chunkSize += header.paddingSize; /* <-- Make sure we seek past the padding. */
+ if (drwav__seek_forward(pWav->onSeek, chunkSize, pWav->pUserData) == DRWAV_FALSE) {
+ break;
+ }
+ cursor += chunkSize;
+
+ continue;
+ }
+
+
+ /* "COMM". AIFF/AIFC only. */
+ if (pWav->container == drwav_container_aiff && drwav_fourcc_equal(header.id.fourcc, "COMM")) {
+ drwav_uint8 commData[24];
+ drwav_uint32 commDataBytesToRead;
+ drwav_uint16 channels;
+ drwav_uint32 frameCount;
+ drwav_uint16 sampleSizeInBits;
+ drwav_int64 sampleRate;
+ drwav_uint16 compressionFormat;
+
+ foundChunk_fmt = DRWAV_TRUE;
+
+ if (isAIFCFormType) {
+ commDataBytesToRead = 24;
+ if (header.sizeInBytes < commDataBytesToRead) {
+ return DRWAV_FALSE; /* Invalid COMM chunk. */
+ }
+ } else {
+ commDataBytesToRead = 18;
+ if (header.sizeInBytes != commDataBytesToRead) {
+ return DRWAV_FALSE; /* INVALID COMM chunk. */
+ }
+ }
+
+ if (drwav__on_read(pWav->onRead, pWav->pUserData, commData, commDataBytesToRead, &cursor) != commDataBytesToRead) {
+ return DRWAV_FALSE;
+ }
+
+
+ channels = drwav_bytes_to_u16_ex (commData + 0, pWav->container);
+ frameCount = drwav_bytes_to_u32_ex (commData + 2, pWav->container);
+ sampleSizeInBits = drwav_bytes_to_u16_ex (commData + 6, pWav->container);
+ sampleRate = drwav_aiff_extented_to_s64(commData + 8);
+
+ if (sampleRate < 0 || sampleRate > 0xFFFFFFFF) {
+ return DRWAV_FALSE; /* Invalid sample rate. */
+ }
+
+ if (isAIFCFormType) {
+ const drwav_uint8* type = commData + 18;
+
+ if (drwav_fourcc_equal(type, "NONE")) {
+ compressionFormat = DR_WAVE_FORMAT_PCM; /* PCM, big-endian. */
+ } else if (drwav_fourcc_equal(type, "raw ")) {
+ compressionFormat = DR_WAVE_FORMAT_PCM;
+
+ /* In my testing, it looks like when the "raw " compression type is used, 8-bit samples should be considered unsigned. */
+ if (sampleSizeInBits == 8) {
+ pWav->aiff.isUnsigned = DRWAV_TRUE;
+ }
+ } else if (drwav_fourcc_equal(type, "sowt")) {
+ compressionFormat = DR_WAVE_FORMAT_PCM; /* PCM, little-endian. */
+ pWav->aiff.isLE = DRWAV_TRUE;
+ } else if (drwav_fourcc_equal(type, "fl32") || drwav_fourcc_equal(type, "fl64") || drwav_fourcc_equal(type, "FL32") || drwav_fourcc_equal(type, "FL64")) {
+ compressionFormat = DR_WAVE_FORMAT_IEEE_FLOAT;
+ } else if (drwav_fourcc_equal(type, "alaw") || drwav_fourcc_equal(type, "ALAW")) {
+ compressionFormat = DR_WAVE_FORMAT_ALAW;
+ } else if (drwav_fourcc_equal(type, "ulaw") || drwav_fourcc_equal(type, "ULAW")) {
+ compressionFormat = DR_WAVE_FORMAT_MULAW;
+ } else if (drwav_fourcc_equal(type, "ima4")) {
+ compressionFormat = DR_WAVE_FORMAT_DVI_ADPCM;
+ sampleSizeInBits = 4;
+
+ /*
+ I haven't been able to figure out how to get correct decoding for IMA ADPCM. Until this is figured out
+ we'll need to abort when we encounter such an encoding. Advice welcome!
+ */
+ return DRWAV_FALSE;
+ } else {
+ return DRWAV_FALSE; /* Unknown or unsupported compression format. Need to abort. */
+ }
+ } else {
+ compressionFormat = DR_WAVE_FORMAT_PCM; /* It's a standard AIFF form which is always compressed. */
+ }
+
+ /* With AIFF we want to use the explicitly defined frame count rather than deriving it from the size of the chunk. */
+ aiffFrameCount = frameCount;
+
+ /* We should now have enough information to fill out our fmt structure. */
+ fmt.formatTag = compressionFormat;
+ fmt.channels = channels;
+ fmt.sampleRate = (drwav_uint32)sampleRate;
+ fmt.bitsPerSample = sampleSizeInBits;
+ fmt.blockAlign = (drwav_uint16)(fmt.channels * fmt.bitsPerSample / 8);
+ fmt.avgBytesPerSec = fmt.blockAlign * fmt.sampleRate;
+
+ if (fmt.blockAlign == 0 && compressionFormat == DR_WAVE_FORMAT_DVI_ADPCM) {
+ fmt.blockAlign = 34 * fmt.channels;
+ }
+
+ /*
+ Weird one. I've seen some alaw and ulaw encoded files that for some reason set the bits per sample to 16 when
+ it should be 8. To get this working I need to explicitly check for this and change it.
+ */
+ if (compressionFormat == DR_WAVE_FORMAT_ALAW || compressionFormat == DR_WAVE_FORMAT_MULAW) {
+ if (fmt.bitsPerSample > 8) {
+ fmt.bitsPerSample = 8;
+ fmt.blockAlign = fmt.channels;
+ }
+ }
+
+ /* In AIFF, samples are padded to 8 byte boundaries. We need to round up our bits per sample here. */
+ fmt.bitsPerSample += (fmt.bitsPerSample & 7);
+
+
+ /* If the form type is AIFC there will be some additional data in the chunk. We need to seek past it. */
+ if (isAIFCFormType) {
+ if (drwav__seek_forward(pWav->onSeek, (chunkSize - commDataBytesToRead), pWav->pUserData) == DRWAV_FALSE) {
+ return DRWAV_FALSE;
+ }
+ cursor += (chunkSize - commDataBytesToRead);
+ }
+
+ /* Don't fall through or else we'll end up treating this chunk as metadata which is incorrect. */
+ continue;
+ }
+
+
+ /* "SSND". AIFF/AIFC only. This is the AIFF equivalent of the "data" chunk. */
+ if (pWav->container == drwav_container_aiff && drwav_fourcc_equal(header.id.fourcc, "SSND")) {
+ drwav_uint8 offsetAndBlockSizeData[8];
+ drwav_uint32 offset;
+
+ foundChunk_data = DRWAV_TRUE;
+
+ if (drwav__on_read(pWav->onRead, pWav->pUserData, offsetAndBlockSizeData, sizeof(offsetAndBlockSizeData), &cursor) != sizeof(offsetAndBlockSizeData)) {
+ return DRWAV_FALSE;
+ }
+
+ /* We need to seek forward by the offset. */
+ offset = drwav_bytes_to_u32_ex(offsetAndBlockSizeData + 0, pWav->container);
+ if (drwav__seek_forward(pWav->onSeek, offset, pWav->pUserData) == DRWAV_FALSE) {
+ return DRWAV_FALSE;
+ }
+ cursor += offset;
+
+ pWav->dataChunkDataPos = cursor;
+ dataChunkSize = chunkSize;
+
+ /* If we're running in sequential mode, or we're not reading metadata, we have enough now that we can get out of the loop. */
+ if (sequential || !isProcessingMetadata) {
+ break; /* No need to keep reading beyond the data chunk. */
+ } else {
+ if (drwav__seek_forward(pWav->onSeek, chunkSize, pWav->pUserData) == DRWAV_FALSE) {
+ break;
+ }
+ cursor += chunkSize;
+
+ continue; /* There may be some more metadata to read. */
+ }
+ }
+
+
+
+ /* Getting here means it's not a chunk that we care about internally, but might need to be handled as metadata by the caller. */
+ if (isProcessingMetadata) {
+ drwav__metadata_process_chunk(&metadataParser, &header, drwav_metadata_type_all_including_unknown);
+
+ /* Go back to the start of the chunk so we can normalize the position of the cursor. */
+ if (drwav__seek_from_start(pWav->onSeek, cursor, pWav->pUserData) == DRWAV_FALSE) {
+ break; /* Failed to seek. Can't reliable read the remaining chunks. Get out. */
+ }
+ }
+
+
+ /* Make sure we skip past the content of this chunk before we go to the next one. */
+ chunkSize += header.paddingSize; /* <-- Make sure we seek past the padding. */
+ if (drwav__seek_forward(pWav->onSeek, chunkSize, pWav->pUserData) == DRWAV_FALSE) {
+ break;
+ }
+ cursor += chunkSize;
+ }
+
+ /* There's some mandatory chunks that must exist. If they were not found in the iteration above we must abort. */
+ if (!foundChunk_fmt || !foundChunk_data) {
+ return DRWAV_FALSE;
+ }
+
+ /* Basic validation. */
+ if ((fmt.sampleRate == 0 || fmt.sampleRate > DRWAV_MAX_SAMPLE_RATE ) ||
+ (fmt.channels == 0 || fmt.channels > DRWAV_MAX_CHANNELS ) ||
+ (fmt.bitsPerSample == 0 || fmt.bitsPerSample > DRWAV_MAX_BITS_PER_SAMPLE) ||
+ fmt.blockAlign == 0) {
+ return DRWAV_FALSE; /* Probably an invalid WAV file. */
+ }
+
+ /* Translate the internal format. */
+ translatedFormatTag = fmt.formatTag;
+ if (translatedFormatTag == DR_WAVE_FORMAT_EXTENSIBLE) {
+ translatedFormatTag = drwav_bytes_to_u16_ex(fmt.subFormat + 0, pWav->container);
+ }
+
+ /* We may have moved passed the data chunk. If so we need to move back. If running in sequential mode we can assume we are already sitting on the data chunk. */
+ if (!sequential) {
+ if (!drwav__seek_from_start(pWav->onSeek, pWav->dataChunkDataPos, pWav->pUserData)) {
+ return DRWAV_FALSE;
+ }
+ cursor = pWav->dataChunkDataPos;
+ }
+
+
+ /*
+ At this point we should have done the initial parsing of each of our chunks, but we now need to
+ do a second pass to extract the actual contents of the metadata (the first pass just calculated
+ the length of the memory allocation).
+
+ We only do this if we've actually got metadata to parse.
+ */
+ if (isProcessingMetadata && metadataParser.metadataCount > 0) {
+ if (drwav__seek_from_start(pWav->onSeek, metadataStartPos, pWav->pUserData) == DRWAV_FALSE) {
+ return DRWAV_FALSE;
+ }
+
+ result = drwav__metadata_alloc(&metadataParser, &pWav->allocationCallbacks);
+ if (result != DRWAV_SUCCESS) {
+ return DRWAV_FALSE;
+ }
+
+ metadataParser.stage = drwav__metadata_parser_stage_read;
+
+ for (;;) {
+ drwav_chunk_header header;
+ drwav_uint64 metadataBytesRead;
+
+ result = drwav__read_chunk_header(pWav->onRead, pWav->pUserData, pWav->container, &cursor, &header);
+ if (result != DRWAV_SUCCESS) {
+ break;
+ }
+
+ metadataBytesRead = drwav__metadata_process_chunk(&metadataParser, &header, drwav_metadata_type_all_including_unknown);
+
+ /* Move to the end of the chunk so we can keep iterating. */
+ if (drwav__seek_forward(pWav->onSeek, (header.sizeInBytes + header.paddingSize) - metadataBytesRead, pWav->pUserData) == DRWAV_FALSE) {
+ drwav_free(metadataParser.pMetadata, &pWav->allocationCallbacks);
+ return DRWAV_FALSE;
+ }
+ }
+
+ /* Getting here means we're finished parsing the metadata. */
+ pWav->pMetadata = metadataParser.pMetadata;
+ pWav->metadataCount = metadataParser.metadataCount;
+ }
+
+
+ /* At this point we should be sitting on the first byte of the raw audio data. */
+
+ /*
+ I've seen a WAV file in the wild where a RIFF-ecapsulated file has the size of it's "RIFF" and
+ "data" chunks set to 0xFFFFFFFF when the file is definitely not that big. In this case we're
+ going to have to calculate the size by reading and discarding bytes, and then seeking back. We
+ cannot do this in sequential mode. We just assume that the rest of the file is audio data.
+ */
+ if (dataChunkSize == 0xFFFFFFFF && (pWav->container == drwav_container_riff || pWav->container == drwav_container_rifx) && pWav->isSequentialWrite == DRWAV_FALSE) {
+ dataChunkSize = 0;
+
+ for (;;) {
+ drwav_uint8 temp[4096];
+ size_t bytesRead = pWav->onRead(pWav->pUserData, temp, sizeof(temp));
+ dataChunkSize += bytesRead;
+
+ if (bytesRead < sizeof(temp)) {
+ break;
+ }
+ }
+ }
+
+ if (drwav__seek_from_start(pWav->onSeek, pWav->dataChunkDataPos, pWav->pUserData) == DRWAV_FALSE) {
+ drwav_free(pWav->pMetadata, &pWav->allocationCallbacks);
+ return DRWAV_FALSE;
+ }
+
+
+ pWav->fmt = fmt;
+ pWav->sampleRate = fmt.sampleRate;
+ pWav->channels = fmt.channels;
+ pWav->bitsPerSample = fmt.bitsPerSample;
+ pWav->bytesRemaining = dataChunkSize;
+ pWav->translatedFormatTag = translatedFormatTag;
+ pWav->dataChunkDataSize = dataChunkSize;
+
+ if (sampleCountFromFactChunk != 0) {
+ pWav->totalPCMFrameCount = sampleCountFromFactChunk;
+ } else if (aiffFrameCount != 0) {
+ pWav->totalPCMFrameCount = aiffFrameCount;
+ } else {
+ drwav_uint32 bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
+ if (bytesPerFrame == 0) {
+ drwav_free(pWav->pMetadata, &pWav->allocationCallbacks);
+ return DRWAV_FALSE; /* Invalid file. */
+ }
+
+ pWav->totalPCMFrameCount = dataChunkSize / bytesPerFrame;
+
+ if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM) {
+ drwav_uint64 totalBlockHeaderSizeInBytes;
+ drwav_uint64 blockCount = dataChunkSize / fmt.blockAlign;
+
+ /* Make sure any trailing partial block is accounted for. */
+ if ((blockCount * fmt.blockAlign) < dataChunkSize) {
+ blockCount += 1;
+ }
+
+ /* We decode two samples per byte. There will be blockCount headers in the data chunk. This is enough to know how to calculate the total PCM frame count. */
+ totalBlockHeaderSizeInBytes = blockCount * (6*fmt.channels);
+ pWav->totalPCMFrameCount = ((dataChunkSize - totalBlockHeaderSizeInBytes) * 2) / fmt.channels;
+ }
+ if (pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
+ drwav_uint64 totalBlockHeaderSizeInBytes;
+ drwav_uint64 blockCount = dataChunkSize / fmt.blockAlign;
+
+ /* Make sure any trailing partial block is accounted for. */
+ if ((blockCount * fmt.blockAlign) < dataChunkSize) {
+ blockCount += 1;
+ }
+
+ /* We decode two samples per byte. There will be blockCount headers in the data chunk. This is enough to know how to calculate the total PCM frame count. */
+ totalBlockHeaderSizeInBytes = blockCount * (4*fmt.channels);
+ pWav->totalPCMFrameCount = ((dataChunkSize - totalBlockHeaderSizeInBytes) * 2) / fmt.channels;
+
+ /* The header includes a decoded sample for each channel which acts as the initial predictor sample. */
+ pWav->totalPCMFrameCount += blockCount;
+ }
+ }
+
+ /* Some formats only support a certain number of channels. */
+ if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM || pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
+ if (pWav->channels > 2) {
+ drwav_free(pWav->pMetadata, &pWav->allocationCallbacks);
+ return DRWAV_FALSE;
+ }
+ }
+
+ /* The number of bytes per frame must be known. If not, it's an invalid file and not decodable. */
+ if (drwav_get_bytes_per_pcm_frame(pWav) == 0) {
+ drwav_free(pWav->pMetadata, &pWav->allocationCallbacks);
+ return DRWAV_FALSE;
+ }
+
+#ifdef DR_WAV_LIBSNDFILE_COMPAT
+ /*
+ I use libsndfile as a benchmark for testing, however in the version I'm using (from the Windows installer on the libsndfile website),
+ it appears the total sample count libsndfile uses for MS-ADPCM is incorrect. It would seem they are computing the total sample count
+ from the number of blocks, however this results in the inclusion of extra silent samples at the end of the last block. The correct
+ way to know the total sample count is to inspect the "fact" chunk, which should always be present for compressed formats, and should
+ always include the sample count. This little block of code below is only used to emulate the libsndfile logic so I can properly run my
+ correctness tests against libsndfile, and is disabled by default.
+ */
+ if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM) {
+ drwav_uint64 blockCount = dataChunkSize / fmt.blockAlign;
+ pWav->totalPCMFrameCount = (((blockCount * (fmt.blockAlign - (6*pWav->channels))) * 2)) / fmt.channels; /* x2 because two samples per byte. */
+ }
+ if (pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
+ drwav_uint64 blockCount = dataChunkSize / fmt.blockAlign;
+ pWav->totalPCMFrameCount = (((blockCount * (fmt.blockAlign - (4*pWav->channels))) * 2) + (blockCount * pWav->channels)) / fmt.channels;
+ }
+#endif
+
+ return DRWAV_TRUE;
+}
+
+DRWAV_API drwav_bool32 drwav_init(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, const drwav_allocation_callbacks* pAllocationCallbacks)
+{
+ return drwav_init_ex(pWav, onRead, onSeek, NULL, pUserData, NULL, 0, pAllocationCallbacks);
+}
+
+DRWAV_API drwav_bool32 drwav_init_ex(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, drwav_chunk_proc onChunk, void* pReadSeekUserData, void* pChunkUserData, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks)
+{
+ if (!drwav_preinit(pWav, onRead, onSeek, pReadSeekUserData, pAllocationCallbacks)) {
+ return DRWAV_FALSE;
+ }
+
+ return drwav_init__internal(pWav, onChunk, pChunkUserData, flags);
+}
+
+DRWAV_API drwav_bool32 drwav_init_with_metadata(drwav* pWav, drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks)
+{
+ if (!drwav_preinit(pWav, onRead, onSeek, pUserData, pAllocationCallbacks)) {
+ return DRWAV_FALSE;
+ }
+
+ return drwav_init__internal(pWav, NULL, NULL, flags | DRWAV_WITH_METADATA);
+}
+
+DRWAV_API drwav_metadata* drwav_take_ownership_of_metadata(drwav* pWav)
+{
+ drwav_metadata *result = pWav->pMetadata;
+
+ pWav->pMetadata = NULL;
+ pWav->metadataCount = 0;
+
+ return result;
+}
+
+
+DRWAV_PRIVATE size_t drwav__write(drwav* pWav, const void* pData, size_t dataSize)
+{
+ DRWAV_ASSERT(pWav != NULL);
+ DRWAV_ASSERT(pWav->onWrite != NULL);
+
+ /* Generic write. Assumes no byte reordering required. */
+ return pWav->onWrite(pWav->pUserData, pData, dataSize);
+}
+
+DRWAV_PRIVATE size_t drwav__write_byte(drwav* pWav, drwav_uint8 byte)
+{
+ DRWAV_ASSERT(pWav != NULL);
+ DRWAV_ASSERT(pWav->onWrite != NULL);
+
+ return pWav->onWrite(pWav->pUserData, &byte, 1);
+}
+
+DRWAV_PRIVATE size_t drwav__write_u16ne_to_le(drwav* pWav, drwav_uint16 value)
+{
+ DRWAV_ASSERT(pWav != NULL);
+ DRWAV_ASSERT(pWav->onWrite != NULL);
+
+ if (!drwav__is_little_endian()) {
+ value = drwav__bswap16(value);
+ }
+
+ return drwav__write(pWav, &value, 2);
+}
+
+DRWAV_PRIVATE size_t drwav__write_u32ne_to_le(drwav* pWav, drwav_uint32 value)
+{
+ DRWAV_ASSERT(pWav != NULL);
+ DRWAV_ASSERT(pWav->onWrite != NULL);
+
+ if (!drwav__is_little_endian()) {
+ value = drwav__bswap32(value);
+ }
+
+ return drwav__write(pWav, &value, 4);
+}
+
+DRWAV_PRIVATE size_t drwav__write_u64ne_to_le(drwav* pWav, drwav_uint64 value)
+{
+ DRWAV_ASSERT(pWav != NULL);
+ DRWAV_ASSERT(pWav->onWrite != NULL);
+
+ if (!drwav__is_little_endian()) {
+ value = drwav__bswap64(value);
+ }
+
+ return drwav__write(pWav, &value, 8);
+}
+
+DRWAV_PRIVATE size_t drwav__write_f32ne_to_le(drwav* pWav, float value)
+{
+ union {
+ drwav_uint32 u32;
+ float f32;
+ } u;
+
+ DRWAV_ASSERT(pWav != NULL);
+ DRWAV_ASSERT(pWav->onWrite != NULL);
+
+ u.f32 = value;
+
+ if (!drwav__is_little_endian()) {
+ u.u32 = drwav__bswap32(u.u32);
+ }
+
+ return drwav__write(pWav, &u.u32, 4);
+}
+
+DRWAV_PRIVATE size_t drwav__write_or_count(drwav* pWav, const void* pData, size_t dataSize)
+{
+ if (pWav == NULL) {
+ return dataSize;
+ }
+
+ return drwav__write(pWav, pData, dataSize);
+}
+
+DRWAV_PRIVATE size_t drwav__write_or_count_byte(drwav* pWav, drwav_uint8 byte)
+{
+ if (pWav == NULL) {
+ return 1;
+ }
+
+ return drwav__write_byte(pWav, byte);
+}
+
+DRWAV_PRIVATE size_t drwav__write_or_count_u16ne_to_le(drwav* pWav, drwav_uint16 value)
+{
+ if (pWav == NULL) {
+ return 2;
+ }
+
+ return drwav__write_u16ne_to_le(pWav, value);
+}
+
+DRWAV_PRIVATE size_t drwav__write_or_count_u32ne_to_le(drwav* pWav, drwav_uint32 value)
+{
+ if (pWav == NULL) {
+ return 4;
+ }
+
+ return drwav__write_u32ne_to_le(pWav, value);
+}
+
+#if 0 /* Unused for now. */
+DRWAV_PRIVATE size_t drwav__write_or_count_u64ne_to_le(drwav* pWav, drwav_uint64 value)
+{
+ if (pWav == NULL) {
+ return 8;
+ }
+
+ return drwav__write_u64ne_to_le(pWav, value);
+}
+#endif
+
+DRWAV_PRIVATE size_t drwav__write_or_count_f32ne_to_le(drwav* pWav, float value)
+{
+ if (pWav == NULL) {
+ return 4;
+ }
+
+ return drwav__write_f32ne_to_le(pWav, value);
+}
+
+DRWAV_PRIVATE size_t drwav__write_or_count_string_to_fixed_size_buf(drwav* pWav, char* str, size_t bufFixedSize)
+{
+ size_t len;
+
+ if (pWav == NULL) {
+ return bufFixedSize;
+ }
+
+ len = drwav__strlen_clamped(str, bufFixedSize);
+ drwav__write_or_count(pWav, str, len);
+
+ if (len < bufFixedSize) {
+ size_t i;
+ for (i = 0; i < bufFixedSize - len; ++i) {
+ drwav__write_byte(pWav, 0);
+ }
+ }
+
+ return bufFixedSize;
+}
+
+
+/* pWav can be NULL meaning just count the bytes that would be written. */
+DRWAV_PRIVATE size_t drwav__write_or_count_metadata(drwav* pWav, drwav_metadata* pMetadatas, drwav_uint32 metadataCount)
+{
+ size_t bytesWritten = 0;
+ drwav_bool32 hasListAdtl = DRWAV_FALSE;
+ drwav_bool32 hasListInfo = DRWAV_FALSE;
+ drwav_uint32 iMetadata;
+
+ if (pMetadatas == NULL || metadataCount == 0) {
+ return 0;
+ }
+
+ for (iMetadata = 0; iMetadata < metadataCount; ++iMetadata) {
+ drwav_metadata* pMetadata = &pMetadatas[iMetadata];
+ drwav_uint32 chunkSize = 0;
+
+ if ((pMetadata->type & drwav_metadata_type_list_all_info_strings) || (pMetadata->type == drwav_metadata_type_unknown && pMetadata->data.unknown.chunkLocation == drwav_metadata_location_inside_info_list)) {
+ hasListInfo = DRWAV_TRUE;
+ }
+
+ if ((pMetadata->type & drwav_metadata_type_list_all_adtl) || (pMetadata->type == drwav_metadata_type_unknown && pMetadata->data.unknown.chunkLocation == drwav_metadata_location_inside_adtl_list)) {
+ hasListAdtl = DRWAV_TRUE;
+ }
+
+ switch (pMetadata->type) {
+ case drwav_metadata_type_smpl:
+ {
+ drwav_uint32 iLoop;
+
+ chunkSize = DRWAV_SMPL_BYTES + DRWAV_SMPL_LOOP_BYTES * pMetadata->data.smpl.sampleLoopCount + pMetadata->data.smpl.samplerSpecificDataSizeInBytes;
+
+ bytesWritten += drwav__write_or_count(pWav, "smpl", 4);
+ bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, chunkSize);
+
+ bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.manufacturerId);
+ bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.productId);
+ bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.samplePeriodNanoseconds);
+ bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.midiUnityNote);
+ bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.midiPitchFraction);
+ bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.smpteFormat);
+ bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.smpteOffset);
+ bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.sampleLoopCount);
+ bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.samplerSpecificDataSizeInBytes);
+
+ for (iLoop = 0; iLoop < pMetadata->data.smpl.sampleLoopCount; ++iLoop) {
+ bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].cuePointId);
+ bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].type);
+ bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].firstSampleByteOffset);
+ bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].lastSampleByteOffset);
+ bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].sampleFraction);
+ bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.smpl.pLoops[iLoop].playCount);
+ }
+
+ if (pMetadata->data.smpl.samplerSpecificDataSizeInBytes > 0) {
+ bytesWritten += drwav__write_or_count(pWav, pMetadata->data.smpl.pSamplerSpecificData, pMetadata->data.smpl.samplerSpecificDataSizeInBytes);
+ }
+ } break;
+
+ case drwav_metadata_type_inst:
+ {
+ chunkSize = DRWAV_INST_BYTES;
+
+ bytesWritten += drwav__write_or_count(pWav, "inst", 4);
+ bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, chunkSize);
+ bytesWritten += drwav__write_or_count(pWav, &pMetadata->data.inst.midiUnityNote, 1);
+ bytesWritten += drwav__write_or_count(pWav, &pMetadata->data.inst.fineTuneCents, 1);
+ bytesWritten += drwav__write_or_count(pWav, &pMetadata->data.inst.gainDecibels, 1);
+ bytesWritten += drwav__write_or_count(pWav, &pMetadata->data.inst.lowNote, 1);
+ bytesWritten += drwav__write_or_count(pWav, &pMetadata->data.inst.highNote, 1);
+ bytesWritten += drwav__write_or_count(pWav, &pMetadata->data.inst.lowVelocity, 1);
+ bytesWritten += drwav__write_or_count(pWav, &pMetadata->data.inst.highVelocity, 1);
+ } break;
+
+ case drwav_metadata_type_cue:
+ {
+ drwav_uint32 iCuePoint;
+
+ chunkSize = DRWAV_CUE_BYTES + DRWAV_CUE_POINT_BYTES * pMetadata->data.cue.cuePointCount;
+
+ bytesWritten += drwav__write_or_count(pWav, "cue ", 4);
+ bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, chunkSize);
+ bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.cue.cuePointCount);
+ for (iCuePoint = 0; iCuePoint < pMetadata->data.cue.cuePointCount; ++iCuePoint) {
+ bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.cue.pCuePoints[iCuePoint].id);
+ bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.cue.pCuePoints[iCuePoint].playOrderPosition);
+ bytesWritten += drwav__write_or_count(pWav, pMetadata->data.cue.pCuePoints[iCuePoint].dataChunkId, 4);
+ bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.cue.pCuePoints[iCuePoint].chunkStart);
+ bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.cue.pCuePoints[iCuePoint].blockStart);
+ bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.cue.pCuePoints[iCuePoint].sampleByteOffset);
+ }
+ } break;
+
+ case drwav_metadata_type_acid:
+ {
+ chunkSize = DRWAV_ACID_BYTES;
+
+ bytesWritten += drwav__write_or_count(pWav, "acid", 4);
+ bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, chunkSize);
+ bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.acid.flags);
+ bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.acid.midiUnityNote);
+ bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.acid.reserved1);
+ bytesWritten += drwav__write_or_count_f32ne_to_le(pWav, pMetadata->data.acid.reserved2);
+ bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.acid.numBeats);
+ bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.acid.meterDenominator);
+ bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.acid.meterNumerator);
+ bytesWritten += drwav__write_or_count_f32ne_to_le(pWav, pMetadata->data.acid.tempo);
+ } break;
+
+ case drwav_metadata_type_bext:
+ {
+ char reservedBuf[DRWAV_BEXT_RESERVED_BYTES];
+ drwav_uint32 timeReferenceLow;
+ drwav_uint32 timeReferenceHigh;
+
+ chunkSize = DRWAV_BEXT_BYTES + pMetadata->data.bext.codingHistorySize;
+
+ bytesWritten += drwav__write_or_count(pWav, "bext", 4);
+ bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, chunkSize);
+
+ bytesWritten += drwav__write_or_count_string_to_fixed_size_buf(pWav, pMetadata->data.bext.pDescription, DRWAV_BEXT_DESCRIPTION_BYTES);
+ bytesWritten += drwav__write_or_count_string_to_fixed_size_buf(pWav, pMetadata->data.bext.pOriginatorName, DRWAV_BEXT_ORIGINATOR_NAME_BYTES);
+ bytesWritten += drwav__write_or_count_string_to_fixed_size_buf(pWav, pMetadata->data.bext.pOriginatorReference, DRWAV_BEXT_ORIGINATOR_REF_BYTES);
+ bytesWritten += drwav__write_or_count(pWav, pMetadata->data.bext.pOriginationDate, sizeof(pMetadata->data.bext.pOriginationDate));
+ bytesWritten += drwav__write_or_count(pWav, pMetadata->data.bext.pOriginationTime, sizeof(pMetadata->data.bext.pOriginationTime));
+
+ timeReferenceLow = (drwav_uint32)(pMetadata->data.bext.timeReference & 0xFFFFFFFF);
+ timeReferenceHigh = (drwav_uint32)(pMetadata->data.bext.timeReference >> 32);
+ bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, timeReferenceLow);
+ bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, timeReferenceHigh);
+
+ bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.bext.version);
+ bytesWritten += drwav__write_or_count(pWav, pMetadata->data.bext.pUMID, DRWAV_BEXT_UMID_BYTES);
+ bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.bext.loudnessValue);
+ bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.bext.loudnessRange);
+ bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.bext.maxTruePeakLevel);
+ bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.bext.maxMomentaryLoudness);
+ bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.bext.maxShortTermLoudness);
+
+ DRWAV_ZERO_MEMORY(reservedBuf, sizeof(reservedBuf));
+ bytesWritten += drwav__write_or_count(pWav, reservedBuf, sizeof(reservedBuf));
+
+ if (pMetadata->data.bext.codingHistorySize > 0) {
+ bytesWritten += drwav__write_or_count(pWav, pMetadata->data.bext.pCodingHistory, pMetadata->data.bext.codingHistorySize);
+ }
+ } break;
+
+ case drwav_metadata_type_unknown:
+ {
+ if (pMetadata->data.unknown.chunkLocation == drwav_metadata_location_top_level) {
+ chunkSize = pMetadata->data.unknown.dataSizeInBytes;
+
+ bytesWritten += drwav__write_or_count(pWav, pMetadata->data.unknown.id, 4);
+ bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, chunkSize);
+ bytesWritten += drwav__write_or_count(pWav, pMetadata->data.unknown.pData, pMetadata->data.unknown.dataSizeInBytes);
+ }
+ } break;
+
+ default: break;
+ }
+ if ((chunkSize % 2) != 0) {
+ bytesWritten += drwav__write_or_count_byte(pWav, 0);
+ }
+ }
+
+ if (hasListInfo) {
+ drwav_uint32 chunkSize = 4; /* Start with 4 bytes for "INFO". */
+ for (iMetadata = 0; iMetadata < metadataCount; ++iMetadata) {
+ drwav_metadata* pMetadata = &pMetadatas[iMetadata];
+
+ if ((pMetadata->type & drwav_metadata_type_list_all_info_strings)) {
+ chunkSize += 8; /* For id and string size. */
+ chunkSize += pMetadata->data.infoText.stringLength + 1; /* Include null terminator. */
+ } else if (pMetadata->type == drwav_metadata_type_unknown && pMetadata->data.unknown.chunkLocation == drwav_metadata_location_inside_info_list) {
+ chunkSize += 8; /* For id string size. */
+ chunkSize += pMetadata->data.unknown.dataSizeInBytes;
+ }
+
+ if ((chunkSize % 2) != 0) {
+ chunkSize += 1;
+ }
+ }
+
+ bytesWritten += drwav__write_or_count(pWav, "LIST", 4);
+ bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, chunkSize);
+ bytesWritten += drwav__write_or_count(pWav, "INFO", 4);
+
+ for (iMetadata = 0; iMetadata < metadataCount; ++iMetadata) {
+ drwav_metadata* pMetadata = &pMetadatas[iMetadata];
+ drwav_uint32 subchunkSize = 0;
+
+ if (pMetadata->type & drwav_metadata_type_list_all_info_strings) {
+ const char* pID = NULL;
+
+ switch (pMetadata->type) {
+ case drwav_metadata_type_list_info_software: pID = "ISFT"; break;
+ case drwav_metadata_type_list_info_copyright: pID = "ICOP"; break;
+ case drwav_metadata_type_list_info_title: pID = "INAM"; break;
+ case drwav_metadata_type_list_info_artist: pID = "IART"; break;
+ case drwav_metadata_type_list_info_comment: pID = "ICMT"; break;
+ case drwav_metadata_type_list_info_date: pID = "ICRD"; break;
+ case drwav_metadata_type_list_info_genre: pID = "IGNR"; break;
+ case drwav_metadata_type_list_info_album: pID = "IPRD"; break;
+ case drwav_metadata_type_list_info_tracknumber: pID = "ITRK"; break;
+ default: break;
+ }
+
+ DRWAV_ASSERT(pID != NULL);
+
+ if (pMetadata->data.infoText.stringLength) {
+ subchunkSize = pMetadata->data.infoText.stringLength + 1;
+ bytesWritten += drwav__write_or_count(pWav, pID, 4);
+ bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, subchunkSize);
+ bytesWritten += drwav__write_or_count(pWav, pMetadata->data.infoText.pString, pMetadata->data.infoText.stringLength);
+ bytesWritten += drwav__write_or_count_byte(pWav, '\0');
+ }
+ } else if (pMetadata->type == drwav_metadata_type_unknown && pMetadata->data.unknown.chunkLocation == drwav_metadata_location_inside_info_list) {
+ if (pMetadata->data.unknown.dataSizeInBytes) {
+ subchunkSize = pMetadata->data.unknown.dataSizeInBytes;
+
+ bytesWritten += drwav__write_or_count(pWav, pMetadata->data.unknown.id, 4);
+ bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.unknown.dataSizeInBytes);
+ bytesWritten += drwav__write_or_count(pWav, pMetadata->data.unknown.pData, subchunkSize);
+ }
+ }
+
+ if ((subchunkSize % 2) != 0) {
+ bytesWritten += drwav__write_or_count_byte(pWav, 0);
+ }
+ }
+ }
+
+ if (hasListAdtl) {
+ drwav_uint32 chunkSize = 4; /* start with 4 bytes for "adtl" */
+
+ for (iMetadata = 0; iMetadata < metadataCount; ++iMetadata) {
+ drwav_metadata* pMetadata = &pMetadatas[iMetadata];
+
+ switch (pMetadata->type)
+ {
+ case drwav_metadata_type_list_label:
+ case drwav_metadata_type_list_note:
+ {
+ chunkSize += 8; /* for id and chunk size */
+ chunkSize += DRWAV_LIST_LABEL_OR_NOTE_BYTES;
+
+ if (pMetadata->data.labelOrNote.stringLength > 0) {
+ chunkSize += pMetadata->data.labelOrNote.stringLength + 1;
+ }
+ } break;
+
+ case drwav_metadata_type_list_labelled_cue_region:
+ {
+ chunkSize += 8; /* for id and chunk size */
+ chunkSize += DRWAV_LIST_LABELLED_TEXT_BYTES;
+
+ if (pMetadata->data.labelledCueRegion.stringLength > 0) {
+ chunkSize += pMetadata->data.labelledCueRegion.stringLength + 1;
+ }
+ } break;
+
+ case drwav_metadata_type_unknown:
+ {
+ if (pMetadata->data.unknown.chunkLocation == drwav_metadata_location_inside_adtl_list) {
+ chunkSize += 8; /* for id and chunk size */
+ chunkSize += pMetadata->data.unknown.dataSizeInBytes;
+ }
+ } break;
+
+ default: break;
+ }
+
+ if ((chunkSize % 2) != 0) {
+ chunkSize += 1;
+ }
+ }
+
+ bytesWritten += drwav__write_or_count(pWav, "LIST", 4);
+ bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, chunkSize);
+ bytesWritten += drwav__write_or_count(pWav, "adtl", 4);
+
+ for (iMetadata = 0; iMetadata < metadataCount; ++iMetadata) {
+ drwav_metadata* pMetadata = &pMetadatas[iMetadata];
+ drwav_uint32 subchunkSize = 0;
+
+ switch (pMetadata->type)
+ {
+ case drwav_metadata_type_list_label:
+ case drwav_metadata_type_list_note:
+ {
+ if (pMetadata->data.labelOrNote.stringLength > 0) {
+ const char *pID = NULL;
+
+ if (pMetadata->type == drwav_metadata_type_list_label) {
+ pID = "labl";
+ }
+ else if (pMetadata->type == drwav_metadata_type_list_note) {
+ pID = "note";
+ }
+
+ DRWAV_ASSERT(pID != NULL);
+ DRWAV_ASSERT(pMetadata->data.labelOrNote.pString != NULL);
+
+ subchunkSize = DRWAV_LIST_LABEL_OR_NOTE_BYTES;
+
+ bytesWritten += drwav__write_or_count(pWav, pID, 4);
+ subchunkSize += pMetadata->data.labelOrNote.stringLength + 1;
+ bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, subchunkSize);
+
+ bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.labelOrNote.cuePointId);
+ bytesWritten += drwav__write_or_count(pWav, pMetadata->data.labelOrNote.pString, pMetadata->data.labelOrNote.stringLength);
+ bytesWritten += drwav__write_or_count_byte(pWav, '\0');
+ }
+ } break;
+
+ case drwav_metadata_type_list_labelled_cue_region:
+ {
+ subchunkSize = DRWAV_LIST_LABELLED_TEXT_BYTES;
+
+ bytesWritten += drwav__write_or_count(pWav, "ltxt", 4);
+ if (pMetadata->data.labelledCueRegion.stringLength > 0) {
+ subchunkSize += pMetadata->data.labelledCueRegion.stringLength + 1;
+ }
+ bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, subchunkSize);
+ bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.labelledCueRegion.cuePointId);
+ bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, pMetadata->data.labelledCueRegion.sampleLength);
+ bytesWritten += drwav__write_or_count(pWav, pMetadata->data.labelledCueRegion.purposeId, 4);
+ bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.labelledCueRegion.country);
+ bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.labelledCueRegion.language);
+ bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.labelledCueRegion.dialect);
+ bytesWritten += drwav__write_or_count_u16ne_to_le(pWav, pMetadata->data.labelledCueRegion.codePage);
+
+ if (pMetadata->data.labelledCueRegion.stringLength > 0) {
+ DRWAV_ASSERT(pMetadata->data.labelledCueRegion.pString != NULL);
+
+ bytesWritten += drwav__write_or_count(pWav, pMetadata->data.labelledCueRegion.pString, pMetadata->data.labelledCueRegion.stringLength);
+ bytesWritten += drwav__write_or_count_byte(pWav, '\0');
+ }
+ } break;
+
+ case drwav_metadata_type_unknown:
+ {
+ if (pMetadata->data.unknown.chunkLocation == drwav_metadata_location_inside_adtl_list) {
+ subchunkSize = pMetadata->data.unknown.dataSizeInBytes;
+
+ DRWAV_ASSERT(pMetadata->data.unknown.pData != NULL);
+ bytesWritten += drwav__write_or_count(pWav, pMetadata->data.unknown.id, 4);
+ bytesWritten += drwav__write_or_count_u32ne_to_le(pWav, subchunkSize);
+ bytesWritten += drwav__write_or_count(pWav, pMetadata->data.unknown.pData, subchunkSize);
+ }
+ } break;
+
+ default: break;
+ }
+
+ if ((subchunkSize % 2) != 0) {
+ bytesWritten += drwav__write_or_count_byte(pWav, 0);
+ }
+ }
+ }
+
+ DRWAV_ASSERT((bytesWritten % 2) == 0);
+
+ return bytesWritten;
+}
+
+DRWAV_PRIVATE drwav_uint32 drwav__riff_chunk_size_riff(drwav_uint64 dataChunkSize, drwav_metadata* pMetadata, drwav_uint32 metadataCount)
+{
+ drwav_uint64 chunkSize = 4 + 24 + (drwav_uint64)drwav__write_or_count_metadata(NULL, pMetadata, metadataCount) + 8 + dataChunkSize + drwav__chunk_padding_size_riff(dataChunkSize); /* 4 = "WAVE". 24 = "fmt " chunk. 8 = "data" + u32 data size. */
+ if (chunkSize > 0xFFFFFFFFUL) {
+ chunkSize = 0xFFFFFFFFUL;
+ }
+
+ return (drwav_uint32)chunkSize; /* Safe cast due to the clamp above. */
+}
+
+DRWAV_PRIVATE drwav_uint32 drwav__data_chunk_size_riff(drwav_uint64 dataChunkSize)
+{
+ if (dataChunkSize <= 0xFFFFFFFFUL) {
+ return (drwav_uint32)dataChunkSize;
+ } else {
+ return 0xFFFFFFFFUL;
+ }
+}
+
+DRWAV_PRIVATE drwav_uint64 drwav__riff_chunk_size_w64(drwav_uint64 dataChunkSize)
+{
+ drwav_uint64 dataSubchunkPaddingSize = drwav__chunk_padding_size_w64(dataChunkSize);
+
+ return 80 + 24 + dataChunkSize + dataSubchunkPaddingSize; /* +24 because W64 includes the size of the GUID and size fields. */
+}
+
+DRWAV_PRIVATE drwav_uint64 drwav__data_chunk_size_w64(drwav_uint64 dataChunkSize)
+{
+ return 24 + dataChunkSize; /* +24 because W64 includes the size of the GUID and size fields. */
+}
+
+DRWAV_PRIVATE drwav_uint64 drwav__riff_chunk_size_rf64(drwav_uint64 dataChunkSize, drwav_metadata *metadata, drwav_uint32 numMetadata)
+{
+ drwav_uint64 chunkSize = 4 + 36 + 24 + (drwav_uint64)drwav__write_or_count_metadata(NULL, metadata, numMetadata) + 8 + dataChunkSize + drwav__chunk_padding_size_riff(dataChunkSize); /* 4 = "WAVE". 36 = "ds64" chunk. 24 = "fmt " chunk. 8 = "data" + u32 data size. */
+ if (chunkSize > 0xFFFFFFFFUL) {
+ chunkSize = 0xFFFFFFFFUL;
+ }
+
+ return chunkSize;
+}
+
+DRWAV_PRIVATE drwav_uint64 drwav__data_chunk_size_rf64(drwav_uint64 dataChunkSize)
+{
+ return dataChunkSize;
+}
+
+
+
+DRWAV_PRIVATE drwav_bool32 drwav_preinit_write(drwav* pWav, const drwav_data_format* pFormat, drwav_bool32 isSequential, drwav_write_proc onWrite, drwav_seek_proc onSeek, void* pUserData, const drwav_allocation_callbacks* pAllocationCallbacks)
+{
+ if (pWav == NULL || onWrite == NULL) {
+ return DRWAV_FALSE;
+ }
+
+ if (!isSequential && onSeek == NULL) {
+ return DRWAV_FALSE; /* <-- onSeek is required when in non-sequential mode. */
+ }
+
+ /* Not currently supporting compressed formats. Will need to add support for the "fact" chunk before we enable this. */
+ if (pFormat->format == DR_WAVE_FORMAT_EXTENSIBLE) {
+ return DRWAV_FALSE;
+ }
+ if (pFormat->format == DR_WAVE_FORMAT_ADPCM || pFormat->format == DR_WAVE_FORMAT_DVI_ADPCM) {
+ return DRWAV_FALSE;
+ }
+
+ DRWAV_ZERO_MEMORY(pWav, sizeof(*pWav));
+ pWav->onWrite = onWrite;
+ pWav->onSeek = onSeek;
+ pWav->pUserData = pUserData;
+ pWav->allocationCallbacks = drwav_copy_allocation_callbacks_or_defaults(pAllocationCallbacks);
+
+ if (pWav->allocationCallbacks.onFree == NULL || (pWav->allocationCallbacks.onMalloc == NULL && pWav->allocationCallbacks.onRealloc == NULL)) {
+ return DRWAV_FALSE; /* Invalid allocation callbacks. */
+ }
+
+ pWav->fmt.formatTag = (drwav_uint16)pFormat->format;
+ pWav->fmt.channels = (drwav_uint16)pFormat->channels;
+ pWav->fmt.sampleRate = pFormat->sampleRate;
+ pWav->fmt.avgBytesPerSec = (drwav_uint32)((pFormat->bitsPerSample * pFormat->sampleRate * pFormat->channels) / 8);
+ pWav->fmt.blockAlign = (drwav_uint16)((pFormat->channels * pFormat->bitsPerSample) / 8);
+ pWav->fmt.bitsPerSample = (drwav_uint16)pFormat->bitsPerSample;
+ pWav->fmt.extendedSize = 0;
+ pWav->isSequentialWrite = isSequential;
+
+ return DRWAV_TRUE;
+}
+
+
+DRWAV_PRIVATE drwav_bool32 drwav_init_write__internal(drwav* pWav, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount)
+{
+ /* The function assumes drwav_preinit_write() was called beforehand. */
+
+ size_t runningPos = 0;
+ drwav_uint64 initialDataChunkSize = 0;
+ drwav_uint64 chunkSizeFMT;
+
+ /*
+ The initial values for the "RIFF" and "data" chunks depends on whether or not we are initializing in sequential mode or not. In
+ sequential mode we set this to its final values straight away since they can be calculated from the total sample count. In non-
+ sequential mode we initialize it all to zero and fill it out in drwav_uninit() using a backwards seek.
+ */
+ if (pWav->isSequentialWrite) {
+ initialDataChunkSize = (totalSampleCount * pWav->fmt.bitsPerSample) / 8;
+
+ /*
+ The RIFF container has a limit on the number of samples. drwav is not allowing this. There's no practical limits for Wave64
+ so for the sake of simplicity I'm not doing any validation for that.
+ */
+ if (pFormat->container == drwav_container_riff) {
+ if (initialDataChunkSize > (0xFFFFFFFFUL - 36)) {
+ return DRWAV_FALSE; /* Not enough room to store every sample. */
+ }
+ }
+ }
+
+ pWav->dataChunkDataSizeTargetWrite = initialDataChunkSize;
+
+
+ /* "RIFF" chunk. */
+ if (pFormat->container == drwav_container_riff) {
+ drwav_uint32 chunkSizeRIFF = 28 + (drwav_uint32)initialDataChunkSize; /* +28 = "WAVE" + [sizeof "fmt " chunk] */
+ runningPos += drwav__write(pWav, "RIFF", 4);
+ runningPos += drwav__write_u32ne_to_le(pWav, chunkSizeRIFF);
+ runningPos += drwav__write(pWav, "WAVE", 4);
+ } else if (pFormat->container == drwav_container_w64) {
+ drwav_uint64 chunkSizeRIFF = 80 + 24 + initialDataChunkSize; /* +24 because W64 includes the size of the GUID and size fields. */
+ runningPos += drwav__write(pWav, drwavGUID_W64_RIFF, 16);
+ runningPos += drwav__write_u64ne_to_le(pWav, chunkSizeRIFF);
+ runningPos += drwav__write(pWav, drwavGUID_W64_WAVE, 16);
+ } else if (pFormat->container == drwav_container_rf64) {
+ runningPos += drwav__write(pWav, "RF64", 4);
+ runningPos += drwav__write_u32ne_to_le(pWav, 0xFFFFFFFF); /* Always 0xFFFFFFFF for RF64. Set to a proper value in the "ds64" chunk. */
+ runningPos += drwav__write(pWav, "WAVE", 4);
+ } else {
+ return DRWAV_FALSE; /* Container not supported for writing. */
+ }
+
+
+ /* "ds64" chunk (RF64 only). */
+ if (pFormat->container == drwav_container_rf64) {
+ drwav_uint32 initialds64ChunkSize = 28; /* 28 = [Size of RIFF (8 bytes)] + [Size of DATA (8 bytes)] + [Sample Count (8 bytes)] + [Table Length (4 bytes)]. Table length always set to 0. */
+ drwav_uint64 initialRiffChunkSize = 8 + initialds64ChunkSize + initialDataChunkSize; /* +8 for the ds64 header. */
+
+ runningPos += drwav__write(pWav, "ds64", 4);
+ runningPos += drwav__write_u32ne_to_le(pWav, initialds64ChunkSize); /* Size of ds64. */
+ runningPos += drwav__write_u64ne_to_le(pWav, initialRiffChunkSize); /* Size of RIFF. Set to true value at the end. */
+ runningPos += drwav__write_u64ne_to_le(pWav, initialDataChunkSize); /* Size of DATA. Set to true value at the end. */
+ runningPos += drwav__write_u64ne_to_le(pWav, totalSampleCount); /* Sample count. */
+ runningPos += drwav__write_u32ne_to_le(pWav, 0); /* Table length. Always set to zero in our case since we're not doing any other chunks than "DATA". */
+ }
+
+
+ /* "fmt " chunk. */
+ if (pFormat->container == drwav_container_riff || pFormat->container == drwav_container_rf64) {
+ chunkSizeFMT = 16;
+ runningPos += drwav__write(pWav, "fmt ", 4);
+ runningPos += drwav__write_u32ne_to_le(pWav, (drwav_uint32)chunkSizeFMT);
+ } else if (pFormat->container == drwav_container_w64) {
+ chunkSizeFMT = 40;
+ runningPos += drwav__write(pWav, drwavGUID_W64_FMT, 16);
+ runningPos += drwav__write_u64ne_to_le(pWav, chunkSizeFMT);
+ }
+
+ runningPos += drwav__write_u16ne_to_le(pWav, pWav->fmt.formatTag);
+ runningPos += drwav__write_u16ne_to_le(pWav, pWav->fmt.channels);
+ runningPos += drwav__write_u32ne_to_le(pWav, pWav->fmt.sampleRate);
+ runningPos += drwav__write_u32ne_to_le(pWav, pWav->fmt.avgBytesPerSec);
+ runningPos += drwav__write_u16ne_to_le(pWav, pWav->fmt.blockAlign);
+ runningPos += drwav__write_u16ne_to_le(pWav, pWav->fmt.bitsPerSample);
+
+ /* TODO: is a 'fact' chunk required for DR_WAVE_FORMAT_IEEE_FLOAT? */
+
+ if (!pWav->isSequentialWrite && pWav->pMetadata != NULL && pWav->metadataCount > 0 && (pFormat->container == drwav_container_riff || pFormat->container == drwav_container_rf64)) {
+ runningPos += drwav__write_or_count_metadata(pWav, pWav->pMetadata, pWav->metadataCount);
+ }
+
+ pWav->dataChunkDataPos = runningPos;
+
+ /* "data" chunk. */
+ if (pFormat->container == drwav_container_riff) {
+ drwav_uint32 chunkSizeDATA = (drwav_uint32)initialDataChunkSize;
+ runningPos += drwav__write(pWav, "data", 4);
+ runningPos += drwav__write_u32ne_to_le(pWav, chunkSizeDATA);
+ } else if (pFormat->container == drwav_container_w64) {
+ drwav_uint64 chunkSizeDATA = 24 + initialDataChunkSize; /* +24 because W64 includes the size of the GUID and size fields. */
+ runningPos += drwav__write(pWav, drwavGUID_W64_DATA, 16);
+ runningPos += drwav__write_u64ne_to_le(pWav, chunkSizeDATA);
+ } else if (pFormat->container == drwav_container_rf64) {
+ runningPos += drwav__write(pWav, "data", 4);
+ runningPos += drwav__write_u32ne_to_le(pWav, 0xFFFFFFFF); /* Always set to 0xFFFFFFFF for RF64. The true size of the data chunk is specified in the ds64 chunk. */
+ }
+
+ /* Set some properties for the client's convenience. */
+ pWav->container = pFormat->container;
+ pWav->channels = (drwav_uint16)pFormat->channels;
+ pWav->sampleRate = pFormat->sampleRate;
+ pWav->bitsPerSample = (drwav_uint16)pFormat->bitsPerSample;
+ pWav->translatedFormatTag = (drwav_uint16)pFormat->format;
+ pWav->dataChunkDataPos = runningPos;
+
+ return DRWAV_TRUE;
+}
+
+
+DRWAV_API drwav_bool32 drwav_init_write(drwav* pWav, const drwav_data_format* pFormat, drwav_write_proc onWrite, drwav_seek_proc onSeek, void* pUserData, const drwav_allocation_callbacks* pAllocationCallbacks)
+{
+ if (!drwav_preinit_write(pWav, pFormat, DRWAV_FALSE, onWrite, onSeek, pUserData, pAllocationCallbacks)) {
+ return DRWAV_FALSE;
+ }
+
+ return drwav_init_write__internal(pWav, pFormat, 0); /* DRWAV_FALSE = Not Sequential */
+}
+
+DRWAV_API drwav_bool32 drwav_init_write_sequential(drwav* pWav, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, drwav_write_proc onWrite, void* pUserData, const drwav_allocation_callbacks* pAllocationCallbacks)
+{
+ if (!drwav_preinit_write(pWav, pFormat, DRWAV_TRUE, onWrite, NULL, pUserData, pAllocationCallbacks)) {
+ return DRWAV_FALSE;
+ }
+
+ return drwav_init_write__internal(pWav, pFormat, totalSampleCount); /* DRWAV_TRUE = Sequential */
+}
+
+DRWAV_API drwav_bool32 drwav_init_write_sequential_pcm_frames(drwav* pWav, const drwav_data_format* pFormat, drwav_uint64 totalPCMFrameCount, drwav_write_proc onWrite, void* pUserData, const drwav_allocation_callbacks* pAllocationCallbacks)
+{
+ if (pFormat == NULL) {
+ return DRWAV_FALSE;
+ }
+
+ return drwav_init_write_sequential(pWav, pFormat, totalPCMFrameCount*pFormat->channels, onWrite, pUserData, pAllocationCallbacks);
+}
+
+DRWAV_API drwav_bool32 drwav_init_write_with_metadata(drwav* pWav, const drwav_data_format* pFormat, drwav_write_proc onWrite, drwav_seek_proc onSeek, void* pUserData, const drwav_allocation_callbacks* pAllocationCallbacks, drwav_metadata* pMetadata, drwav_uint32 metadataCount)
+{
+ if (!drwav_preinit_write(pWav, pFormat, DRWAV_FALSE, onWrite, onSeek, pUserData, pAllocationCallbacks)) {
+ return DRWAV_FALSE;
+ }
+
+ pWav->pMetadata = pMetadata;
+ pWav->metadataCount = metadataCount;
+
+ return drwav_init_write__internal(pWav, pFormat, 0);
+}
+
+
+DRWAV_API drwav_uint64 drwav_target_write_size_bytes(const drwav_data_format* pFormat, drwav_uint64 totalFrameCount, drwav_metadata* pMetadata, drwav_uint32 metadataCount)
+{
+ /* Casting totalFrameCount to drwav_int64 for VC6 compatibility. No issues in practice because nobody is going to exhaust the whole 63 bits. */
+ drwav_uint64 targetDataSizeBytes = (drwav_uint64)((drwav_int64)totalFrameCount * pFormat->channels * pFormat->bitsPerSample/8.0);
+ drwav_uint64 riffChunkSizeBytes;
+ drwav_uint64 fileSizeBytes = 0;
+
+ if (pFormat->container == drwav_container_riff) {
+ riffChunkSizeBytes = drwav__riff_chunk_size_riff(targetDataSizeBytes, pMetadata, metadataCount);
+ fileSizeBytes = (8 + riffChunkSizeBytes); /* +8 because WAV doesn't include the size of the ChunkID and ChunkSize fields. */
+ } else if (pFormat->container == drwav_container_w64) {
+ riffChunkSizeBytes = drwav__riff_chunk_size_w64(targetDataSizeBytes);
+ fileSizeBytes = riffChunkSizeBytes;
+ } else if (pFormat->container == drwav_container_rf64) {
+ riffChunkSizeBytes = drwav__riff_chunk_size_rf64(targetDataSizeBytes, pMetadata, metadataCount);
+ fileSizeBytes = (8 + riffChunkSizeBytes); /* +8 because WAV doesn't include the size of the ChunkID and ChunkSize fields. */
+ }
+
+ return fileSizeBytes;
+}
+
+
+#ifndef DR_WAV_NO_STDIO
+
+/* Errno */
+/* drwav_result_from_errno() is only used for fopen() and wfopen() so putting it inside DR_WAV_NO_STDIO for now. If something else needs this later we can move it out. */
+#include
+DRWAV_PRIVATE drwav_result drwav_result_from_errno(int e)
+{
+ switch (e)
+ {
+ case 0: return DRWAV_SUCCESS;
+ #ifdef EPERM
+ case EPERM: return DRWAV_INVALID_OPERATION;
+ #endif
+ #ifdef ENOENT
+ case ENOENT: return DRWAV_DOES_NOT_EXIST;
+ #endif
+ #ifdef ESRCH
+ case ESRCH: return DRWAV_DOES_NOT_EXIST;
+ #endif
+ #ifdef EINTR
+ case EINTR: return DRWAV_INTERRUPT;
+ #endif
+ #ifdef EIO
+ case EIO: return DRWAV_IO_ERROR;
+ #endif
+ #ifdef ENXIO
+ case ENXIO: return DRWAV_DOES_NOT_EXIST;
+ #endif
+ #ifdef E2BIG
+ case E2BIG: return DRWAV_INVALID_ARGS;
+ #endif
+ #ifdef ENOEXEC
+ case ENOEXEC: return DRWAV_INVALID_FILE;
+ #endif
+ #ifdef EBADF
+ case EBADF: return DRWAV_INVALID_FILE;
+ #endif
+ #ifdef ECHILD
+ case ECHILD: return DRWAV_ERROR;
+ #endif
+ #ifdef EAGAIN
+ case EAGAIN: return DRWAV_UNAVAILABLE;
+ #endif
+ #ifdef ENOMEM
+ case ENOMEM: return DRWAV_OUT_OF_MEMORY;
+ #endif
+ #ifdef EACCES
+ case EACCES: return DRWAV_ACCESS_DENIED;
+ #endif
+ #ifdef EFAULT
+ case EFAULT: return DRWAV_BAD_ADDRESS;
+ #endif
+ #ifdef ENOTBLK
+ case ENOTBLK: return DRWAV_ERROR;
+ #endif
+ #ifdef EBUSY
+ case EBUSY: return DRWAV_BUSY;
+ #endif
+ #ifdef EEXIST
+ case EEXIST: return DRWAV_ALREADY_EXISTS;
+ #endif
+ #ifdef EXDEV
+ case EXDEV: return DRWAV_ERROR;
+ #endif
+ #ifdef ENODEV
+ case ENODEV: return DRWAV_DOES_NOT_EXIST;
+ #endif
+ #ifdef ENOTDIR
+ case ENOTDIR: return DRWAV_NOT_DIRECTORY;
+ #endif
+ #ifdef EISDIR
+ case EISDIR: return DRWAV_IS_DIRECTORY;
+ #endif
+ #ifdef EINVAL
+ case EINVAL: return DRWAV_INVALID_ARGS;
+ #endif
+ #ifdef ENFILE
+ case ENFILE: return DRWAV_TOO_MANY_OPEN_FILES;
+ #endif
+ #ifdef EMFILE
+ case EMFILE: return DRWAV_TOO_MANY_OPEN_FILES;
+ #endif
+ #ifdef ENOTTY
+ case ENOTTY: return DRWAV_INVALID_OPERATION;
+ #endif
+ #ifdef ETXTBSY
+ case ETXTBSY: return DRWAV_BUSY;
+ #endif
+ #ifdef EFBIG
+ case EFBIG: return DRWAV_TOO_BIG;
+ #endif
+ #ifdef ENOSPC
+ case ENOSPC: return DRWAV_NO_SPACE;
+ #endif
+ #ifdef ESPIPE
+ case ESPIPE: return DRWAV_BAD_SEEK;
+ #endif
+ #ifdef EROFS
+ case EROFS: return DRWAV_ACCESS_DENIED;
+ #endif
+ #ifdef EMLINK
+ case EMLINK: return DRWAV_TOO_MANY_LINKS;
+ #endif
+ #ifdef EPIPE
+ case EPIPE: return DRWAV_BAD_PIPE;
+ #endif
+ #ifdef EDOM
+ case EDOM: return DRWAV_OUT_OF_RANGE;
+ #endif
+ #ifdef ERANGE
+ case ERANGE: return DRWAV_OUT_OF_RANGE;
+ #endif
+ #ifdef EDEADLK
+ case EDEADLK: return DRWAV_DEADLOCK;
+ #endif
+ #ifdef ENAMETOOLONG
+ case ENAMETOOLONG: return DRWAV_PATH_TOO_LONG;
+ #endif
+ #ifdef ENOLCK
+ case ENOLCK: return DRWAV_ERROR;
+ #endif
+ #ifdef ENOSYS
+ case ENOSYS: return DRWAV_NOT_IMPLEMENTED;
+ #endif
+ #ifdef ENOTEMPTY
+ case ENOTEMPTY: return DRWAV_DIRECTORY_NOT_EMPTY;
+ #endif
+ #ifdef ELOOP
+ case ELOOP: return DRWAV_TOO_MANY_LINKS;
+ #endif
+ #ifdef ENOMSG
+ case ENOMSG: return DRWAV_NO_MESSAGE;
+ #endif
+ #ifdef EIDRM
+ case EIDRM: return DRWAV_ERROR;
+ #endif
+ #ifdef ECHRNG
+ case ECHRNG: return DRWAV_ERROR;
+ #endif
+ #ifdef EL2NSYNC
+ case EL2NSYNC: return DRWAV_ERROR;
+ #endif
+ #ifdef EL3HLT
+ case EL3HLT: return DRWAV_ERROR;
+ #endif
+ #ifdef EL3RST
+ case EL3RST: return DRWAV_ERROR;
+ #endif
+ #ifdef ELNRNG
+ case ELNRNG: return DRWAV_OUT_OF_RANGE;
+ #endif
+ #ifdef EUNATCH
+ case EUNATCH: return DRWAV_ERROR;
+ #endif
+ #ifdef ENOCSI
+ case ENOCSI: return DRWAV_ERROR;
+ #endif
+ #ifdef EL2HLT
+ case EL2HLT: return DRWAV_ERROR;
+ #endif
+ #ifdef EBADE
+ case EBADE: return DRWAV_ERROR;
+ #endif
+ #ifdef EBADR
+ case EBADR: return DRWAV_ERROR;
+ #endif
+ #ifdef EXFULL
+ case EXFULL: return DRWAV_ERROR;
+ #endif
+ #ifdef ENOANO
+ case ENOANO: return DRWAV_ERROR;
+ #endif
+ #ifdef EBADRQC
+ case EBADRQC: return DRWAV_ERROR;
+ #endif
+ #ifdef EBADSLT
+ case EBADSLT: return DRWAV_ERROR;
+ #endif
+ #ifdef EBFONT
+ case EBFONT: return DRWAV_INVALID_FILE;
+ #endif
+ #ifdef ENOSTR
+ case ENOSTR: return DRWAV_ERROR;
+ #endif
+ #ifdef ENODATA
+ case ENODATA: return DRWAV_NO_DATA_AVAILABLE;
+ #endif
+ #ifdef ETIME
+ case ETIME: return DRWAV_TIMEOUT;
+ #endif
+ #ifdef ENOSR
+ case ENOSR: return DRWAV_NO_DATA_AVAILABLE;
+ #endif
+ #ifdef ENONET
+ case ENONET: return DRWAV_NO_NETWORK;
+ #endif
+ #ifdef ENOPKG
+ case ENOPKG: return DRWAV_ERROR;
+ #endif
+ #ifdef EREMOTE
+ case EREMOTE: return DRWAV_ERROR;
+ #endif
+ #ifdef ENOLINK
+ case ENOLINK: return DRWAV_ERROR;
+ #endif
+ #ifdef EADV
+ case EADV: return DRWAV_ERROR;
+ #endif
+ #ifdef ESRMNT
+ case ESRMNT: return DRWAV_ERROR;
+ #endif
+ #ifdef ECOMM
+ case ECOMM: return DRWAV_ERROR;
+ #endif
+ #ifdef EPROTO
+ case EPROTO: return DRWAV_ERROR;
+ #endif
+ #ifdef EMULTIHOP
+ case EMULTIHOP: return DRWAV_ERROR;
+ #endif
+ #ifdef EDOTDOT
+ case EDOTDOT: return DRWAV_ERROR;
+ #endif
+ #ifdef EBADMSG
+ case EBADMSG: return DRWAV_BAD_MESSAGE;
+ #endif
+ #ifdef EOVERFLOW
+ case EOVERFLOW: return DRWAV_TOO_BIG;
+ #endif
+ #ifdef ENOTUNIQ
+ case ENOTUNIQ: return DRWAV_NOT_UNIQUE;
+ #endif
+ #ifdef EBADFD
+ case EBADFD: return DRWAV_ERROR;
+ #endif
+ #ifdef EREMCHG
+ case EREMCHG: return DRWAV_ERROR;
+ #endif
+ #ifdef ELIBACC
+ case ELIBACC: return DRWAV_ACCESS_DENIED;
+ #endif
+ #ifdef ELIBBAD
+ case ELIBBAD: return DRWAV_INVALID_FILE;
+ #endif
+ #ifdef ELIBSCN
+ case ELIBSCN: return DRWAV_INVALID_FILE;
+ #endif
+ #ifdef ELIBMAX
+ case ELIBMAX: return DRWAV_ERROR;
+ #endif
+ #ifdef ELIBEXEC
+ case ELIBEXEC: return DRWAV_ERROR;
+ #endif
+ #ifdef EILSEQ
+ case EILSEQ: return DRWAV_INVALID_DATA;
+ #endif
+ #ifdef ERESTART
+ case ERESTART: return DRWAV_ERROR;
+ #endif
+ #ifdef ESTRPIPE
+ case ESTRPIPE: return DRWAV_ERROR;
+ #endif
+ #ifdef EUSERS
+ case EUSERS: return DRWAV_ERROR;
+ #endif
+ #ifdef ENOTSOCK
+ case ENOTSOCK: return DRWAV_NOT_SOCKET;
+ #endif
+ #ifdef EDESTADDRREQ
+ case EDESTADDRREQ: return DRWAV_NO_ADDRESS;
+ #endif
+ #ifdef EMSGSIZE
+ case EMSGSIZE: return DRWAV_TOO_BIG;
+ #endif
+ #ifdef EPROTOTYPE
+ case EPROTOTYPE: return DRWAV_BAD_PROTOCOL;
+ #endif
+ #ifdef ENOPROTOOPT
+ case ENOPROTOOPT: return DRWAV_PROTOCOL_UNAVAILABLE;
+ #endif
+ #ifdef EPROTONOSUPPORT
+ case EPROTONOSUPPORT: return DRWAV_PROTOCOL_NOT_SUPPORTED;
+ #endif
+ #ifdef ESOCKTNOSUPPORT
+ case ESOCKTNOSUPPORT: return DRWAV_SOCKET_NOT_SUPPORTED;
+ #endif
+ #ifdef EOPNOTSUPP
+ case EOPNOTSUPP: return DRWAV_INVALID_OPERATION;
+ #endif
+ #ifdef EPFNOSUPPORT
+ case EPFNOSUPPORT: return DRWAV_PROTOCOL_FAMILY_NOT_SUPPORTED;
+ #endif
+ #ifdef EAFNOSUPPORT
+ case EAFNOSUPPORT: return DRWAV_ADDRESS_FAMILY_NOT_SUPPORTED;
+ #endif
+ #ifdef EADDRINUSE
+ case EADDRINUSE: return DRWAV_ALREADY_IN_USE;
+ #endif
+ #ifdef EADDRNOTAVAIL
+ case EADDRNOTAVAIL: return DRWAV_ERROR;
+ #endif
+ #ifdef ENETDOWN
+ case ENETDOWN: return DRWAV_NO_NETWORK;
+ #endif
+ #ifdef ENETUNREACH
+ case ENETUNREACH: return DRWAV_NO_NETWORK;
+ #endif
+ #ifdef ENETRESET
+ case ENETRESET: return DRWAV_NO_NETWORK;
+ #endif
+ #ifdef ECONNABORTED
+ case ECONNABORTED: return DRWAV_NO_NETWORK;
+ #endif
+ #ifdef ECONNRESET
+ case ECONNRESET: return DRWAV_CONNECTION_RESET;
+ #endif
+ #ifdef ENOBUFS
+ case ENOBUFS: return DRWAV_NO_SPACE;
+ #endif
+ #ifdef EISCONN
+ case EISCONN: return DRWAV_ALREADY_CONNECTED;
+ #endif
+ #ifdef ENOTCONN
+ case ENOTCONN: return DRWAV_NOT_CONNECTED;
+ #endif
+ #ifdef ESHUTDOWN
+ case ESHUTDOWN: return DRWAV_ERROR;
+ #endif
+ #ifdef ETOOMANYREFS
+ case ETOOMANYREFS: return DRWAV_ERROR;
+ #endif
+ #ifdef ETIMEDOUT
+ case ETIMEDOUT: return DRWAV_TIMEOUT;
+ #endif
+ #ifdef ECONNREFUSED
+ case ECONNREFUSED: return DRWAV_CONNECTION_REFUSED;
+ #endif
+ #ifdef EHOSTDOWN
+ case EHOSTDOWN: return DRWAV_NO_HOST;
+ #endif
+ #ifdef EHOSTUNREACH
+ case EHOSTUNREACH: return DRWAV_NO_HOST;
+ #endif
+ #ifdef EALREADY
+ case EALREADY: return DRWAV_IN_PROGRESS;
+ #endif
+ #ifdef EINPROGRESS
+ case EINPROGRESS: return DRWAV_IN_PROGRESS;
+ #endif
+ #ifdef ESTALE
+ case ESTALE: return DRWAV_INVALID_FILE;
+ #endif
+ #ifdef EUCLEAN
+ case EUCLEAN: return DRWAV_ERROR;
+ #endif
+ #ifdef ENOTNAM
+ case ENOTNAM: return DRWAV_ERROR;
+ #endif
+ #ifdef ENAVAIL
+ case ENAVAIL: return DRWAV_ERROR;
+ #endif
+ #ifdef EISNAM
+ case EISNAM: return DRWAV_ERROR;
+ #endif
+ #ifdef EREMOTEIO
+ case EREMOTEIO: return DRWAV_IO_ERROR;
+ #endif
+ #ifdef EDQUOT
+ case EDQUOT: return DRWAV_NO_SPACE;
+ #endif
+ #ifdef ENOMEDIUM
+ case ENOMEDIUM: return DRWAV_DOES_NOT_EXIST;
+ #endif
+ #ifdef EMEDIUMTYPE
+ case EMEDIUMTYPE: return DRWAV_ERROR;
+ #endif
+ #ifdef ECANCELED
+ case ECANCELED: return DRWAV_CANCELLED;
+ #endif
+ #ifdef ENOKEY
+ case ENOKEY: return DRWAV_ERROR;
+ #endif
+ #ifdef EKEYEXPIRED
+ case EKEYEXPIRED: return DRWAV_ERROR;
+ #endif
+ #ifdef EKEYREVOKED
+ case EKEYREVOKED: return DRWAV_ERROR;
+ #endif
+ #ifdef EKEYREJECTED
+ case EKEYREJECTED: return DRWAV_ERROR;
+ #endif
+ #ifdef EOWNERDEAD
+ case EOWNERDEAD: return DRWAV_ERROR;
+ #endif
+ #ifdef ENOTRECOVERABLE
+ case ENOTRECOVERABLE: return DRWAV_ERROR;
+ #endif
+ #ifdef ERFKILL
+ case ERFKILL: return DRWAV_ERROR;
+ #endif
+ #ifdef EHWPOISON
+ case EHWPOISON: return DRWAV_ERROR;
+ #endif
+ default: return DRWAV_ERROR;
+ }
+}
+/* End Errno */
+
+/* fopen */
+DRWAV_PRIVATE drwav_result drwav_fopen(FILE** ppFile, const char* pFilePath, const char* pOpenMode)
+{
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+ errno_t err;
+#endif
+
+ if (ppFile != NULL) {
+ *ppFile = NULL; /* Safety. */
+ }
+
+ if (pFilePath == NULL || pOpenMode == NULL || ppFile == NULL) {
+ return DRWAV_INVALID_ARGS;
+ }
+
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+ err = fopen_s(ppFile, pFilePath, pOpenMode);
+ if (err != 0) {
+ return drwav_result_from_errno(err);
+ }
+#else
+#if defined(_WIN32) || defined(__APPLE__)
+ *ppFile = fopen(pFilePath, pOpenMode);
+#else
+ #if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64 && defined(_LARGEFILE64_SOURCE)
+ *ppFile = fopen64(pFilePath, pOpenMode);
+ #else
+ *ppFile = fopen(pFilePath, pOpenMode);
+ #endif
+#endif
+ if (*ppFile == NULL) {
+ drwav_result result = drwav_result_from_errno(errno);
+ if (result == DRWAV_SUCCESS) {
+ result = DRWAV_ERROR; /* Just a safety check to make sure we never ever return success when pFile == NULL. */
+ }
+
+ return result;
+ }
+#endif
+
+ return DRWAV_SUCCESS;
+}
+
+/*
+_wfopen() isn't always available in all compilation environments.
+
+ * Windows only.
+ * MSVC seems to support it universally as far back as VC6 from what I can tell (haven't checked further back).
+ * MinGW-64 (both 32- and 64-bit) seems to support it.
+ * MinGW wraps it in !defined(__STRICT_ANSI__).
+ * OpenWatcom wraps it in !defined(_NO_EXT_KEYS).
+
+This can be reviewed as compatibility issues arise. The preference is to use _wfopen_s() and _wfopen() as opposed to the wcsrtombs()
+fallback, so if you notice your compiler not detecting this properly I'm happy to look at adding support.
+*/
+#if defined(_WIN32)
+ #if defined(_MSC_VER) || defined(__MINGW64__) || (!defined(__STRICT_ANSI__) && !defined(_NO_EXT_KEYS))
+ #define DRWAV_HAS_WFOPEN
+ #endif
+#endif
+
+#ifndef DR_WAV_NO_WCHAR
+DRWAV_PRIVATE drwav_result drwav_wfopen(FILE** ppFile, const wchar_t* pFilePath, const wchar_t* pOpenMode, const drwav_allocation_callbacks* pAllocationCallbacks)
+{
+ if (ppFile != NULL) {
+ *ppFile = NULL; /* Safety. */
+ }
+
+ if (pFilePath == NULL || pOpenMode == NULL || ppFile == NULL) {
+ return DRWAV_INVALID_ARGS;
+ }
+
+#if defined(DRWAV_HAS_WFOPEN)
+ {
+ /* Use _wfopen() on Windows. */
+ #if defined(_MSC_VER) && _MSC_VER >= 1400
+ errno_t err = _wfopen_s(ppFile, pFilePath, pOpenMode);
+ if (err != 0) {
+ return drwav_result_from_errno(err);
+ }
+ #else
+ *ppFile = _wfopen(pFilePath, pOpenMode);
+ if (*ppFile == NULL) {
+ return drwav_result_from_errno(errno);
+ }
+ #endif
+ (void)pAllocationCallbacks;
+ }
+#else
+ /*
+ Use fopen() on anything other than Windows. Requires a conversion. This is annoying because
+ fopen() is locale specific. The only real way I can think of to do this is with wcsrtombs(). Note
+ that wcstombs() is apparently not thread-safe because it uses a static global mbstate_t object for
+ maintaining state. I've checked this with -std=c89 and it works, but if somebody get's a compiler
+ error I'll look into improving compatibility.
+ */
+
+ /*
+ Some compilers don't support wchar_t or wcsrtombs() which we're using below. In this case we just
+ need to abort with an error. If you encounter a compiler lacking such support, add it to this list
+ and submit a bug report and it'll be added to the library upstream.
+ */
+ #if defined(__DJGPP__)
+ {
+ /* Nothing to do here. This will fall through to the error check below. */
+ }
+ #else
+ {
+ mbstate_t mbs;
+ size_t lenMB;
+ const wchar_t* pFilePathTemp = pFilePath;
+ char* pFilePathMB = NULL;
+ char pOpenModeMB[32] = {0};
+
+ /* Get the length first. */
+ DRWAV_ZERO_OBJECT(&mbs);
+ lenMB = wcsrtombs(NULL, &pFilePathTemp, 0, &mbs);
+ if (lenMB == (size_t)-1) {
+ return drwav_result_from_errno(errno);
+ }
+
+ pFilePathMB = (char*)drwav__malloc_from_callbacks(lenMB + 1, pAllocationCallbacks);
+ if (pFilePathMB == NULL) {
+ return DRWAV_OUT_OF_MEMORY;
+ }
+
+ pFilePathTemp = pFilePath;
+ DRWAV_ZERO_OBJECT(&mbs);
+ wcsrtombs(pFilePathMB, &pFilePathTemp, lenMB + 1, &mbs);
+
+ /* The open mode should always consist of ASCII characters so we should be able to do a trivial conversion. */
+ {
+ size_t i = 0;
+ for (;;) {
+ if (pOpenMode[i] == 0) {
+ pOpenModeMB[i] = '\0';
+ break;
+ }
+
+ pOpenModeMB[i] = (char)pOpenMode[i];
+ i += 1;
+ }
+ }
+
+ *ppFile = fopen(pFilePathMB, pOpenModeMB);
+
+ drwav__free_from_callbacks(pFilePathMB, pAllocationCallbacks);
+ }
+ #endif
+
+ if (*ppFile == NULL) {
+ return DRWAV_ERROR;
+ }
+#endif
+
+ return DRWAV_SUCCESS;
+}
+#endif
+/* End fopen */
+
+
+DRWAV_PRIVATE size_t drwav__on_read_stdio(void* pUserData, void* pBufferOut, size_t bytesToRead)
+{
+ return fread(pBufferOut, 1, bytesToRead, (FILE*)pUserData);
+}
+
+DRWAV_PRIVATE size_t drwav__on_write_stdio(void* pUserData, const void* pData, size_t bytesToWrite)
+{
+ return fwrite(pData, 1, bytesToWrite, (FILE*)pUserData);
+}
+
+DRWAV_PRIVATE drwav_bool32 drwav__on_seek_stdio(void* pUserData, int offset, drwav_seek_origin origin)
+{
+ return fseek((FILE*)pUserData, offset, (origin == drwav_seek_origin_current) ? SEEK_CUR : SEEK_SET) == 0;
+}
+
+DRWAV_API drwav_bool32 drwav_init_file(drwav* pWav, const char* filename, const drwav_allocation_callbacks* pAllocationCallbacks)
+{
+ return drwav_init_file_ex(pWav, filename, NULL, NULL, 0, pAllocationCallbacks);
+}
+
+
+DRWAV_PRIVATE drwav_bool32 drwav_init_file__internal_FILE(drwav* pWav, FILE* pFile, drwav_chunk_proc onChunk, void* pChunkUserData, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks)
+{
+ drwav_bool32 result;
+
+ result = drwav_preinit(pWav, drwav__on_read_stdio, drwav__on_seek_stdio, (void*)pFile, pAllocationCallbacks);
+ if (result != DRWAV_TRUE) {
+ fclose(pFile);
+ return result;
+ }
+
+ result = drwav_init__internal(pWav, onChunk, pChunkUserData, flags);
+ if (result != DRWAV_TRUE) {
+ fclose(pFile);
+ return result;
+ }
+
+ return DRWAV_TRUE;
+}
+
+DRWAV_API drwav_bool32 drwav_init_file_ex(drwav* pWav, const char* filename, drwav_chunk_proc onChunk, void* pChunkUserData, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks)
+{
+ FILE* pFile;
+ if (drwav_fopen(&pFile, filename, "rb") != DRWAV_SUCCESS) {
+ return DRWAV_FALSE;
+ }
+
+ /* This takes ownership of the FILE* object. */
+ return drwav_init_file__internal_FILE(pWav, pFile, onChunk, pChunkUserData, flags, pAllocationCallbacks);
+}
+
+#ifndef DR_WAV_NO_WCHAR
+DRWAV_API drwav_bool32 drwav_init_file_w(drwav* pWav, const wchar_t* filename, const drwav_allocation_callbacks* pAllocationCallbacks)
+{
+ return drwav_init_file_ex_w(pWav, filename, NULL, NULL, 0, pAllocationCallbacks);
+}
+
+DRWAV_API drwav_bool32 drwav_init_file_ex_w(drwav* pWav, const wchar_t* filename, drwav_chunk_proc onChunk, void* pChunkUserData, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks)
+{
+ FILE* pFile;
+ if (drwav_wfopen(&pFile, filename, L"rb", pAllocationCallbacks) != DRWAV_SUCCESS) {
+ return DRWAV_FALSE;
+ }
+
+ /* This takes ownership of the FILE* object. */
+ return drwav_init_file__internal_FILE(pWav, pFile, onChunk, pChunkUserData, flags, pAllocationCallbacks);
+}
+#endif
+
+DRWAV_API drwav_bool32 drwav_init_file_with_metadata(drwav* pWav, const char* filename, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks)
+{
+ FILE* pFile;
+ if (drwav_fopen(&pFile, filename, "rb") != DRWAV_SUCCESS) {
+ return DRWAV_FALSE;
+ }
+
+ /* This takes ownership of the FILE* object. */
+ return drwav_init_file__internal_FILE(pWav, pFile, NULL, NULL, flags | DRWAV_WITH_METADATA, pAllocationCallbacks);
+}
+
+#ifndef DR_WAV_NO_WCHAR
+DRWAV_API drwav_bool32 drwav_init_file_with_metadata_w(drwav* pWav, const wchar_t* filename, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks)
+{
+ FILE* pFile;
+ if (drwav_wfopen(&pFile, filename, L"rb", pAllocationCallbacks) != DRWAV_SUCCESS) {
+ return DRWAV_FALSE;
+ }
+
+ /* This takes ownership of the FILE* object. */
+ return drwav_init_file__internal_FILE(pWav, pFile, NULL, NULL, flags | DRWAV_WITH_METADATA, pAllocationCallbacks);
+}
+#endif
+
+
+DRWAV_PRIVATE drwav_bool32 drwav_init_file_write__internal_FILE(drwav* pWav, FILE* pFile, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, drwav_bool32 isSequential, const drwav_allocation_callbacks* pAllocationCallbacks)
+{
+ drwav_bool32 result;
+
+ result = drwav_preinit_write(pWav, pFormat, isSequential, drwav__on_write_stdio, drwav__on_seek_stdio, (void*)pFile, pAllocationCallbacks);
+ if (result != DRWAV_TRUE) {
+ fclose(pFile);
+ return result;
+ }
+
+ result = drwav_init_write__internal(pWav, pFormat, totalSampleCount);
+ if (result != DRWAV_TRUE) {
+ fclose(pFile);
+ return result;
+ }
+
+ return DRWAV_TRUE;
+}
+
+DRWAV_PRIVATE drwav_bool32 drwav_init_file_write__internal(drwav* pWav, const char* filename, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, drwav_bool32 isSequential, const drwav_allocation_callbacks* pAllocationCallbacks)
+{
+ FILE* pFile;
+ if (drwav_fopen(&pFile, filename, "wb") != DRWAV_SUCCESS) {
+ return DRWAV_FALSE;
+ }
+
+ /* This takes ownership of the FILE* object. */
+ return drwav_init_file_write__internal_FILE(pWav, pFile, pFormat, totalSampleCount, isSequential, pAllocationCallbacks);
+}
+
+#ifndef DR_WAV_NO_WCHAR
+DRWAV_PRIVATE drwav_bool32 drwav_init_file_write_w__internal(drwav* pWav, const wchar_t* filename, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, drwav_bool32 isSequential, const drwav_allocation_callbacks* pAllocationCallbacks)
+{
+ FILE* pFile;
+ if (drwav_wfopen(&pFile, filename, L"wb", pAllocationCallbacks) != DRWAV_SUCCESS) {
+ return DRWAV_FALSE;
+ }
+
+ /* This takes ownership of the FILE* object. */
+ return drwav_init_file_write__internal_FILE(pWav, pFile, pFormat, totalSampleCount, isSequential, pAllocationCallbacks);
+}
+#endif
+
+DRWAV_API drwav_bool32 drwav_init_file_write(drwav* pWav, const char* filename, const drwav_data_format* pFormat, const drwav_allocation_callbacks* pAllocationCallbacks)
+{
+ return drwav_init_file_write__internal(pWav, filename, pFormat, 0, DRWAV_FALSE, pAllocationCallbacks);
+}
+
+DRWAV_API drwav_bool32 drwav_init_file_write_sequential(drwav* pWav, const char* filename, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, const drwav_allocation_callbacks* pAllocationCallbacks)
+{
+ return drwav_init_file_write__internal(pWav, filename, pFormat, totalSampleCount, DRWAV_TRUE, pAllocationCallbacks);
+}
+
+DRWAV_API drwav_bool32 drwav_init_file_write_sequential_pcm_frames(drwav* pWav, const char* filename, const drwav_data_format* pFormat, drwav_uint64 totalPCMFrameCount, const drwav_allocation_callbacks* pAllocationCallbacks)
+{
+ if (pFormat == NULL) {
+ return DRWAV_FALSE;
+ }
+
+ return drwav_init_file_write_sequential(pWav, filename, pFormat, totalPCMFrameCount*pFormat->channels, pAllocationCallbacks);
+}
+
+#ifndef DR_WAV_NO_WCHAR
+DRWAV_API drwav_bool32 drwav_init_file_write_w(drwav* pWav, const wchar_t* filename, const drwav_data_format* pFormat, const drwav_allocation_callbacks* pAllocationCallbacks)
+{
+ return drwav_init_file_write_w__internal(pWav, filename, pFormat, 0, DRWAV_FALSE, pAllocationCallbacks);
+}
+
+DRWAV_API drwav_bool32 drwav_init_file_write_sequential_w(drwav* pWav, const wchar_t* filename, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, const drwav_allocation_callbacks* pAllocationCallbacks)
+{
+ return drwav_init_file_write_w__internal(pWav, filename, pFormat, totalSampleCount, DRWAV_TRUE, pAllocationCallbacks);
+}
+
+DRWAV_API drwav_bool32 drwav_init_file_write_sequential_pcm_frames_w(drwav* pWav, const wchar_t* filename, const drwav_data_format* pFormat, drwav_uint64 totalPCMFrameCount, const drwav_allocation_callbacks* pAllocationCallbacks)
+{
+ if (pFormat == NULL) {
+ return DRWAV_FALSE;
+ }
+
+ return drwav_init_file_write_sequential_w(pWav, filename, pFormat, totalPCMFrameCount*pFormat->channels, pAllocationCallbacks);
+}
+#endif
+#endif /* DR_WAV_NO_STDIO */
+
+
+DRWAV_PRIVATE size_t drwav__on_read_memory(void* pUserData, void* pBufferOut, size_t bytesToRead)
+{
+ drwav* pWav = (drwav*)pUserData;
+ size_t bytesRemaining;
+
+ DRWAV_ASSERT(pWav != NULL);
+ DRWAV_ASSERT(pWav->memoryStream.dataSize >= pWav->memoryStream.currentReadPos);
+
+ bytesRemaining = pWav->memoryStream.dataSize - pWav->memoryStream.currentReadPos;
+ if (bytesToRead > bytesRemaining) {
+ bytesToRead = bytesRemaining;
+ }
+
+ if (bytesToRead > 0) {
+ DRWAV_COPY_MEMORY(pBufferOut, pWav->memoryStream.data + pWav->memoryStream.currentReadPos, bytesToRead);
+ pWav->memoryStream.currentReadPos += bytesToRead;
+ }
+
+ return bytesToRead;
+}
+
+DRWAV_PRIVATE drwav_bool32 drwav__on_seek_memory(void* pUserData, int offset, drwav_seek_origin origin)
+{
+ drwav* pWav = (drwav*)pUserData;
+ DRWAV_ASSERT(pWav != NULL);
+
+ if (origin == drwav_seek_origin_current) {
+ if (offset > 0) {
+ if (pWav->memoryStream.currentReadPos + offset > pWav->memoryStream.dataSize) {
+ return DRWAV_FALSE; /* Trying to seek too far forward. */
+ }
+ } else {
+ if (pWav->memoryStream.currentReadPos < (size_t)-offset) {
+ return DRWAV_FALSE; /* Trying to seek too far backwards. */
+ }
+ }
+
+ /* This will never underflow thanks to the clamps above. */
+ pWav->memoryStream.currentReadPos += offset;
+ } else {
+ if ((drwav_uint32)offset <= pWav->memoryStream.dataSize) {
+ pWav->memoryStream.currentReadPos = offset;
+ } else {
+ return DRWAV_FALSE; /* Trying to seek too far forward. */
+ }
+ }
+
+ return DRWAV_TRUE;
+}
+
+DRWAV_PRIVATE size_t drwav__on_write_memory(void* pUserData, const void* pDataIn, size_t bytesToWrite)
+{
+ drwav* pWav = (drwav*)pUserData;
+ size_t bytesRemaining;
+
+ DRWAV_ASSERT(pWav != NULL);
+ DRWAV_ASSERT(pWav->memoryStreamWrite.dataCapacity >= pWav->memoryStreamWrite.currentWritePos);
+
+ bytesRemaining = pWav->memoryStreamWrite.dataCapacity - pWav->memoryStreamWrite.currentWritePos;
+ if (bytesRemaining < bytesToWrite) {
+ /* Need to reallocate. */
+ void* pNewData;
+ size_t newDataCapacity = (pWav->memoryStreamWrite.dataCapacity == 0) ? 256 : pWav->memoryStreamWrite.dataCapacity * 2;
+
+ /* If doubling wasn't enough, just make it the minimum required size to write the data. */
+ if ((newDataCapacity - pWav->memoryStreamWrite.currentWritePos) < bytesToWrite) {
+ newDataCapacity = pWav->memoryStreamWrite.currentWritePos + bytesToWrite;
+ }
+
+ pNewData = drwav__realloc_from_callbacks(*pWav->memoryStreamWrite.ppData, newDataCapacity, pWav->memoryStreamWrite.dataCapacity, &pWav->allocationCallbacks);
+ if (pNewData == NULL) {
+ return 0;
+ }
+
+ *pWav->memoryStreamWrite.ppData = pNewData;
+ pWav->memoryStreamWrite.dataCapacity = newDataCapacity;
+ }
+
+ DRWAV_COPY_MEMORY(((drwav_uint8*)(*pWav->memoryStreamWrite.ppData)) + pWav->memoryStreamWrite.currentWritePos, pDataIn, bytesToWrite);
+
+ pWav->memoryStreamWrite.currentWritePos += bytesToWrite;
+ if (pWav->memoryStreamWrite.dataSize < pWav->memoryStreamWrite.currentWritePos) {
+ pWav->memoryStreamWrite.dataSize = pWav->memoryStreamWrite.currentWritePos;
+ }
+
+ *pWav->memoryStreamWrite.pDataSize = pWav->memoryStreamWrite.dataSize;
+
+ return bytesToWrite;
+}
+
+DRWAV_PRIVATE drwav_bool32 drwav__on_seek_memory_write(void* pUserData, int offset, drwav_seek_origin origin)
+{
+ drwav* pWav = (drwav*)pUserData;
+ DRWAV_ASSERT(pWav != NULL);
+
+ if (origin == drwav_seek_origin_current) {
+ if (offset > 0) {
+ if (pWav->memoryStreamWrite.currentWritePos + offset > pWav->memoryStreamWrite.dataSize) {
+ offset = (int)(pWav->memoryStreamWrite.dataSize - pWav->memoryStreamWrite.currentWritePos); /* Trying to seek too far forward. */
+ }
+ } else {
+ if (pWav->memoryStreamWrite.currentWritePos < (size_t)-offset) {
+ offset = -(int)pWav->memoryStreamWrite.currentWritePos; /* Trying to seek too far backwards. */
+ }
+ }
+
+ /* This will never underflow thanks to the clamps above. */
+ pWav->memoryStreamWrite.currentWritePos += offset;
+ } else {
+ if ((drwav_uint32)offset <= pWav->memoryStreamWrite.dataSize) {
+ pWav->memoryStreamWrite.currentWritePos = offset;
+ } else {
+ pWav->memoryStreamWrite.currentWritePos = pWav->memoryStreamWrite.dataSize; /* Trying to seek too far forward. */
+ }
+ }
+
+ return DRWAV_TRUE;
+}
+
+DRWAV_API drwav_bool32 drwav_init_memory(drwav* pWav, const void* data, size_t dataSize, const drwav_allocation_callbacks* pAllocationCallbacks)
+{
+ return drwav_init_memory_ex(pWav, data, dataSize, NULL, NULL, 0, pAllocationCallbacks);
+}
+
+DRWAV_API drwav_bool32 drwav_init_memory_ex(drwav* pWav, const void* data, size_t dataSize, drwav_chunk_proc onChunk, void* pChunkUserData, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks)
+{
+ if (data == NULL || dataSize == 0) {
+ return DRWAV_FALSE;
+ }
+
+ if (!drwav_preinit(pWav, drwav__on_read_memory, drwav__on_seek_memory, pWav, pAllocationCallbacks)) {
+ return DRWAV_FALSE;
+ }
+
+ pWav->memoryStream.data = (const drwav_uint8*)data;
+ pWav->memoryStream.dataSize = dataSize;
+ pWav->memoryStream.currentReadPos = 0;
+
+ return drwav_init__internal(pWav, onChunk, pChunkUserData, flags);
+}
+
+DRWAV_API drwav_bool32 drwav_init_memory_with_metadata(drwav* pWav, const void* data, size_t dataSize, drwav_uint32 flags, const drwav_allocation_callbacks* pAllocationCallbacks)
+{
+ if (data == NULL || dataSize == 0) {
+ return DRWAV_FALSE;
+ }
+
+ if (!drwav_preinit(pWav, drwav__on_read_memory, drwav__on_seek_memory, pWav, pAllocationCallbacks)) {
+ return DRWAV_FALSE;
+ }
+
+ pWav->memoryStream.data = (const drwav_uint8*)data;
+ pWav->memoryStream.dataSize = dataSize;
+ pWav->memoryStream.currentReadPos = 0;
+
+ return drwav_init__internal(pWav, NULL, NULL, flags | DRWAV_WITH_METADATA);
+}
+
+
+DRWAV_PRIVATE drwav_bool32 drwav_init_memory_write__internal(drwav* pWav, void** ppData, size_t* pDataSize, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, drwav_bool32 isSequential, const drwav_allocation_callbacks* pAllocationCallbacks)
+{
+ if (ppData == NULL || pDataSize == NULL) {
+ return DRWAV_FALSE;
+ }
+
+ *ppData = NULL; /* Important because we're using realloc()! */
+ *pDataSize = 0;
+
+ if (!drwav_preinit_write(pWav, pFormat, isSequential, drwav__on_write_memory, drwav__on_seek_memory_write, pWav, pAllocationCallbacks)) {
+ return DRWAV_FALSE;
+ }
+
+ pWav->memoryStreamWrite.ppData = ppData;
+ pWav->memoryStreamWrite.pDataSize = pDataSize;
+ pWav->memoryStreamWrite.dataSize = 0;
+ pWav->memoryStreamWrite.dataCapacity = 0;
+ pWav->memoryStreamWrite.currentWritePos = 0;
+
+ return drwav_init_write__internal(pWav, pFormat, totalSampleCount);
+}
+
+DRWAV_API drwav_bool32 drwav_init_memory_write(drwav* pWav, void** ppData, size_t* pDataSize, const drwav_data_format* pFormat, const drwav_allocation_callbacks* pAllocationCallbacks)
+{
+ return drwav_init_memory_write__internal(pWav, ppData, pDataSize, pFormat, 0, DRWAV_FALSE, pAllocationCallbacks);
+}
+
+DRWAV_API drwav_bool32 drwav_init_memory_write_sequential(drwav* pWav, void** ppData, size_t* pDataSize, const drwav_data_format* pFormat, drwav_uint64 totalSampleCount, const drwav_allocation_callbacks* pAllocationCallbacks)
+{
+ return drwav_init_memory_write__internal(pWav, ppData, pDataSize, pFormat, totalSampleCount, DRWAV_TRUE, pAllocationCallbacks);
+}
+
+DRWAV_API drwav_bool32 drwav_init_memory_write_sequential_pcm_frames(drwav* pWav, void** ppData, size_t* pDataSize, const drwav_data_format* pFormat, drwav_uint64 totalPCMFrameCount, const drwav_allocation_callbacks* pAllocationCallbacks)
+{
+ if (pFormat == NULL) {
+ return DRWAV_FALSE;
+ }
+
+ return drwav_init_memory_write_sequential(pWav, ppData, pDataSize, pFormat, totalPCMFrameCount*pFormat->channels, pAllocationCallbacks);
+}
+
+
+
+DRWAV_API drwav_result drwav_uninit(drwav* pWav)
+{
+ drwav_result result = DRWAV_SUCCESS;
+
+ if (pWav == NULL) {
+ return DRWAV_INVALID_ARGS;
+ }
+
+ /*
+ If the drwav object was opened in write mode we'll need to finalize a few things:
+ - Make sure the "data" chunk is aligned to 16-bits for RIFF containers, or 64 bits for W64 containers.
+ - Set the size of the "data" chunk.
+ */
+ if (pWav->onWrite != NULL) {
+ drwav_uint32 paddingSize = 0;
+
+ /* Padding. Do not adjust pWav->dataChunkDataSize - this should not include the padding. */
+ if (pWav->container == drwav_container_riff || pWav->container == drwav_container_rf64) {
+ paddingSize = drwav__chunk_padding_size_riff(pWav->dataChunkDataSize);
+ } else {
+ paddingSize = drwav__chunk_padding_size_w64(pWav->dataChunkDataSize);
+ }
+
+ if (paddingSize > 0) {
+ drwav_uint64 paddingData = 0;
+ drwav__write(pWav, &paddingData, paddingSize); /* Byte order does not matter for this. */
+ }
+
+ /*
+ Chunk sizes. When using sequential mode, these will have been filled in at initialization time. We only need
+ to do this when using non-sequential mode.
+ */
+ if (pWav->onSeek && !pWav->isSequentialWrite) {
+ if (pWav->container == drwav_container_riff) {
+ /* The "RIFF" chunk size. */
+ if (pWav->onSeek(pWav->pUserData, 4, drwav_seek_origin_start)) {
+ drwav_uint32 riffChunkSize = drwav__riff_chunk_size_riff(pWav->dataChunkDataSize, pWav->pMetadata, pWav->metadataCount);
+ drwav__write_u32ne_to_le(pWav, riffChunkSize);
+ }
+
+ /* The "data" chunk size. */
+ if (pWav->onSeek(pWav->pUserData, (int)pWav->dataChunkDataPos - 4, drwav_seek_origin_start)) {
+ drwav_uint32 dataChunkSize = drwav__data_chunk_size_riff(pWav->dataChunkDataSize);
+ drwav__write_u32ne_to_le(pWav, dataChunkSize);
+ }
+ } else if (pWav->container == drwav_container_w64) {
+ /* The "RIFF" chunk size. */
+ if (pWav->onSeek(pWav->pUserData, 16, drwav_seek_origin_start)) {
+ drwav_uint64 riffChunkSize = drwav__riff_chunk_size_w64(pWav->dataChunkDataSize);
+ drwav__write_u64ne_to_le(pWav, riffChunkSize);
+ }
+
+ /* The "data" chunk size. */
+ if (pWav->onSeek(pWav->pUserData, (int)pWav->dataChunkDataPos - 8, drwav_seek_origin_start)) {
+ drwav_uint64 dataChunkSize = drwav__data_chunk_size_w64(pWav->dataChunkDataSize);
+ drwav__write_u64ne_to_le(pWav, dataChunkSize);
+ }
+ } else if (pWav->container == drwav_container_rf64) {
+ /* We only need to update the ds64 chunk. The "RIFF" and "data" chunks always have their sizes set to 0xFFFFFFFF for RF64. */
+ int ds64BodyPos = 12 + 8;
+
+ /* The "RIFF" chunk size. */
+ if (pWav->onSeek(pWav->pUserData, ds64BodyPos + 0, drwav_seek_origin_start)) {
+ drwav_uint64 riffChunkSize = drwav__riff_chunk_size_rf64(pWav->dataChunkDataSize, pWav->pMetadata, pWav->metadataCount);
+ drwav__write_u64ne_to_le(pWav, riffChunkSize);
+ }
+
+ /* The "data" chunk size. */
+ if (pWav->onSeek(pWav->pUserData, ds64BodyPos + 8, drwav_seek_origin_start)) {
+ drwav_uint64 dataChunkSize = drwav__data_chunk_size_rf64(pWav->dataChunkDataSize);
+ drwav__write_u64ne_to_le(pWav, dataChunkSize);
+ }
+ }
+ }
+
+ /* Validation for sequential mode. */
+ if (pWav->isSequentialWrite) {
+ if (pWav->dataChunkDataSize != pWav->dataChunkDataSizeTargetWrite) {
+ result = DRWAV_INVALID_FILE;
+ }
+ }
+ } else {
+ drwav_free(pWav->pMetadata, &pWav->allocationCallbacks);
+ }
+
+#ifndef DR_WAV_NO_STDIO
+ /*
+ If we opened the file with drwav_open_file() we will want to close the file handle. We can know whether or not drwav_open_file()
+ was used by looking at the onRead and onSeek callbacks.
+ */
+ if (pWav->onRead == drwav__on_read_stdio || pWav->onWrite == drwav__on_write_stdio) {
+ fclose((FILE*)pWav->pUserData);
+ }
+#endif
+
+ return result;
+}
+
+
+
+DRWAV_API size_t drwav_read_raw(drwav* pWav, size_t bytesToRead, void* pBufferOut)
+{
+ size_t bytesRead;
+ drwav_uint32 bytesPerFrame;
+
+ if (pWav == NULL || bytesToRead == 0) {
+ return 0; /* Invalid args. */
+ }
+
+ if (bytesToRead > pWav->bytesRemaining) {
+ bytesToRead = (size_t)pWav->bytesRemaining;
+ }
+
+ if (bytesToRead == 0) {
+ return 0; /* At end. */
+ }
+
+ bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
+ if (bytesPerFrame == 0) {
+ return 0; /* Could not determine the bytes per frame. */
+ }
+
+ if (pBufferOut != NULL) {
+ bytesRead = pWav->onRead(pWav->pUserData, pBufferOut, bytesToRead);
+ } else {
+ /* We need to seek. If we fail, we need to read-and-discard to make sure we get a good byte count. */
+ bytesRead = 0;
+ while (bytesRead < bytesToRead) {
+ size_t bytesToSeek = (bytesToRead - bytesRead);
+ if (bytesToSeek > 0x7FFFFFFF) {
+ bytesToSeek = 0x7FFFFFFF;
+ }
+
+ if (pWav->onSeek(pWav->pUserData, (int)bytesToSeek, drwav_seek_origin_current) == DRWAV_FALSE) {
+ break;
+ }
+
+ bytesRead += bytesToSeek;
+ }
+
+ /* When we get here we may need to read-and-discard some data. */
+ while (bytesRead < bytesToRead) {
+ drwav_uint8 buffer[4096];
+ size_t bytesSeeked;
+ size_t bytesToSeek = (bytesToRead - bytesRead);
+ if (bytesToSeek > sizeof(buffer)) {
+ bytesToSeek = sizeof(buffer);
+ }
+
+ bytesSeeked = pWav->onRead(pWav->pUserData, buffer, bytesToSeek);
+ bytesRead += bytesSeeked;
+
+ if (bytesSeeked < bytesToSeek) {
+ break; /* Reached the end. */
+ }
+ }
+ }
+
+ pWav->readCursorInPCMFrames += bytesRead / bytesPerFrame;
+
+ pWav->bytesRemaining -= bytesRead;
+ return bytesRead;
+}
+
+
+
+DRWAV_API drwav_uint64 drwav_read_pcm_frames_le(drwav* pWav, drwav_uint64 framesToRead, void* pBufferOut)
+{
+ drwav_uint32 bytesPerFrame;
+ drwav_uint64 bytesToRead; /* Intentionally uint64 instead of size_t so we can do a check that we're not reading too much on 32-bit builds. */
+ drwav_uint64 framesRemainingInFile;
+
+ if (pWav == NULL || framesToRead == 0) {
+ return 0;
+ }
+
+ /* Cannot use this function for compressed formats. */
+ if (drwav__is_compressed_format_tag(pWav->translatedFormatTag)) {
+ return 0;
+ }
+
+ framesRemainingInFile = pWav->totalPCMFrameCount - pWav->readCursorInPCMFrames;
+ if (framesToRead > framesRemainingInFile) {
+ framesToRead = framesRemainingInFile;
+ }
+
+ bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
+ if (bytesPerFrame == 0) {
+ return 0;
+ }
+
+ /* Don't try to read more samples than can potentially fit in the output buffer. */
+ bytesToRead = framesToRead * bytesPerFrame;
+ if (bytesToRead > DRWAV_SIZE_MAX) {
+ bytesToRead = (DRWAV_SIZE_MAX / bytesPerFrame) * bytesPerFrame; /* Round the number of bytes to read to a clean frame boundary. */
+ }
+
+ /*
+ Doing an explicit check here just to make it clear that we don't want to be attempt to read anything if there's no bytes to read. There
+ *could* be a time where it evaluates to 0 due to overflowing.
+ */
+ if (bytesToRead == 0) {
+ return 0;
+ }
+
+ return drwav_read_raw(pWav, (size_t)bytesToRead, pBufferOut) / bytesPerFrame;
+}
+
+DRWAV_API drwav_uint64 drwav_read_pcm_frames_be(drwav* pWav, drwav_uint64 framesToRead, void* pBufferOut)
+{
+ drwav_uint64 framesRead = drwav_read_pcm_frames_le(pWav, framesToRead, pBufferOut);
+
+ if (pBufferOut != NULL) {
+ drwav_uint32 bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
+ if (bytesPerFrame == 0) {
+ return 0; /* Could not get the bytes per frame which means bytes per sample cannot be determined and we don't know how to byte swap. */
+ }
+
+ drwav__bswap_samples(pBufferOut, framesRead*pWav->channels, bytesPerFrame/pWav->channels);
+ }
+
+ return framesRead;
+}
+
+DRWAV_API drwav_uint64 drwav_read_pcm_frames(drwav* pWav, drwav_uint64 framesToRead, void* pBufferOut)
+{
+ drwav_uint64 framesRead = 0;
+
+ if (drwav_is_container_be(pWav->container)) {
+ /*
+ Special case for AIFF. AIFF is a big-endian encoded format, but it supports a format that is
+ PCM in little-endian encoding. In this case, we fall through this branch and treate it as
+ little-endian.
+ */
+ if (pWav->container != drwav_container_aiff || pWav->aiff.isLE == DRWAV_FALSE) {
+ if (drwav__is_little_endian()) {
+ framesRead = drwav_read_pcm_frames_be(pWav, framesToRead, pBufferOut);
+ } else {
+ framesRead = drwav_read_pcm_frames_le(pWav, framesToRead, pBufferOut);
+ }
+
+ goto post_process;
+ }
+ }
+
+ /* Getting here means the data should be considered little-endian. */
+ if (drwav__is_little_endian()) {
+ framesRead = drwav_read_pcm_frames_le(pWav, framesToRead, pBufferOut);
+ } else {
+ framesRead = drwav_read_pcm_frames_be(pWav, framesToRead, pBufferOut);
+ }
+
+ /*
+ Here is where we check if we need to do a signed/unsigned conversion for AIFF. The reason we need to do this
+ is because dr_wav always assumes an 8-bit sample is unsigned, whereas AIFF can have signed 8-bit formats.
+ */
+ post_process:
+ {
+ if (pWav->container == drwav_container_aiff && pWav->bitsPerSample == 8 && pWav->aiff.isUnsigned == DRWAV_FALSE) {
+ if (pBufferOut != NULL) {
+ drwav_uint64 iSample;
+
+ for (iSample = 0; iSample < framesRead * pWav->channels; iSample += 1) {
+ ((drwav_uint8*)pBufferOut)[iSample] += 128;
+ }
+ }
+ }
+ }
+
+ return framesRead;
+}
+
+
+
+DRWAV_PRIVATE drwav_bool32 drwav_seek_to_first_pcm_frame(drwav* pWav)
+{
+ if (pWav->onWrite != NULL) {
+ return DRWAV_FALSE; /* No seeking in write mode. */
+ }
+
+ if (!pWav->onSeek(pWav->pUserData, (int)pWav->dataChunkDataPos, drwav_seek_origin_start)) {
+ return DRWAV_FALSE;
+ }
+
+ if (drwav__is_compressed_format_tag(pWav->translatedFormatTag)) {
+ /* Cached data needs to be cleared for compressed formats. */
+ if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM) {
+ DRWAV_ZERO_OBJECT(&pWav->msadpcm);
+ } else if (pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
+ DRWAV_ZERO_OBJECT(&pWav->ima);
+ } else {
+ DRWAV_ASSERT(DRWAV_FALSE); /* If this assertion is triggered it means I've implemented a new compressed format but forgot to add a branch for it here. */
+ }
+ }
+
+ pWav->readCursorInPCMFrames = 0;
+ pWav->bytesRemaining = pWav->dataChunkDataSize;
+
+ return DRWAV_TRUE;
+}
+
+DRWAV_API drwav_bool32 drwav_seek_to_pcm_frame(drwav* pWav, drwav_uint64 targetFrameIndex)
+{
+ /* Seeking should be compatible with wave files > 2GB. */
+
+ if (pWav == NULL || pWav->onSeek == NULL) {
+ return DRWAV_FALSE;
+ }
+
+ /* No seeking in write mode. */
+ if (pWav->onWrite != NULL) {
+ return DRWAV_FALSE;
+ }
+
+ /* If there are no samples, just return DRWAV_TRUE without doing anything. */
+ if (pWav->totalPCMFrameCount == 0) {
+ return DRWAV_TRUE;
+ }
+
+ /* Make sure the sample is clamped. */
+ if (targetFrameIndex > pWav->totalPCMFrameCount) {
+ targetFrameIndex = pWav->totalPCMFrameCount;
+ }
+
+ /*
+ For compressed formats we just use a slow generic seek. If we are seeking forward we just seek forward. If we are going backwards we need
+ to seek back to the start.
+ */
+ if (drwav__is_compressed_format_tag(pWav->translatedFormatTag)) {
+ /* TODO: This can be optimized. */
+
+ /*
+ If we're seeking forward it's simple - just keep reading samples until we hit the sample we're requesting. If we're seeking backwards,
+ we first need to seek back to the start and then just do the same thing as a forward seek.
+ */
+ if (targetFrameIndex < pWav->readCursorInPCMFrames) {
+ if (!drwav_seek_to_first_pcm_frame(pWav)) {
+ return DRWAV_FALSE;
+ }
+ }
+
+ if (targetFrameIndex > pWav->readCursorInPCMFrames) {
+ drwav_uint64 offsetInFrames = targetFrameIndex - pWav->readCursorInPCMFrames;
+
+ drwav_int16 devnull[2048];
+ while (offsetInFrames > 0) {
+ drwav_uint64 framesRead = 0;
+ drwav_uint64 framesToRead = offsetInFrames;
+ if (framesToRead > drwav_countof(devnull)/pWav->channels) {
+ framesToRead = drwav_countof(devnull)/pWav->channels;
+ }
+
+ if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM) {
+ framesRead = drwav_read_pcm_frames_s16__msadpcm(pWav, framesToRead, devnull);
+ } else if (pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
+ framesRead = drwav_read_pcm_frames_s16__ima(pWav, framesToRead, devnull);
+ } else {
+ DRWAV_ASSERT(DRWAV_FALSE); /* If this assertion is triggered it means I've implemented a new compressed format but forgot to add a branch for it here. */
+ }
+
+ if (framesRead != framesToRead) {
+ return DRWAV_FALSE;
+ }
+
+ offsetInFrames -= framesRead;
+ }
+ }
+ } else {
+ drwav_uint64 totalSizeInBytes;
+ drwav_uint64 currentBytePos;
+ drwav_uint64 targetBytePos;
+ drwav_uint64 offset;
+ drwav_uint32 bytesPerFrame;
+
+ bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
+ if (bytesPerFrame == 0) {
+ return DRWAV_FALSE; /* Not able to calculate offset. */
+ }
+
+ totalSizeInBytes = pWav->totalPCMFrameCount * bytesPerFrame;
+ /*DRWAV_ASSERT(totalSizeInBytes >= pWav->bytesRemaining);*/
+
+ currentBytePos = totalSizeInBytes - pWav->bytesRemaining;
+ targetBytePos = targetFrameIndex * bytesPerFrame;
+
+ if (currentBytePos < targetBytePos) {
+ /* Offset forwards. */
+ offset = (targetBytePos - currentBytePos);
+ } else {
+ /* Offset backwards. */
+ if (!drwav_seek_to_first_pcm_frame(pWav)) {
+ return DRWAV_FALSE;
+ }
+ offset = targetBytePos;
+ }
+
+ while (offset > 0) {
+ int offset32 = ((offset > INT_MAX) ? INT_MAX : (int)offset);
+ if (!pWav->onSeek(pWav->pUserData, offset32, drwav_seek_origin_current)) {
+ return DRWAV_FALSE;
+ }
+
+ pWav->readCursorInPCMFrames += offset32 / bytesPerFrame;
+ pWav->bytesRemaining -= offset32;
+ offset -= offset32;
+ }
+ }
+
+ return DRWAV_TRUE;
+}
+
+DRWAV_API drwav_result drwav_get_cursor_in_pcm_frames(drwav* pWav, drwav_uint64* pCursor)
+{
+ if (pCursor == NULL) {
+ return DRWAV_INVALID_ARGS;
+ }
+
+ *pCursor = 0; /* Safety. */
+
+ if (pWav == NULL) {
+ return DRWAV_INVALID_ARGS;
+ }
+
+ *pCursor = pWav->readCursorInPCMFrames;
+
+ return DRWAV_SUCCESS;
+}
+
+DRWAV_API drwav_result drwav_get_length_in_pcm_frames(drwav* pWav, drwav_uint64* pLength)
+{
+ if (pLength == NULL) {
+ return DRWAV_INVALID_ARGS;
+ }
+
+ *pLength = 0; /* Safety. */
+
+ if (pWav == NULL) {
+ return DRWAV_INVALID_ARGS;
+ }
+
+ *pLength = pWav->totalPCMFrameCount;
+
+ return DRWAV_SUCCESS;
+}
+
+
+DRWAV_API size_t drwav_write_raw(drwav* pWav, size_t bytesToWrite, const void* pData)
+{
+ size_t bytesWritten;
+
+ if (pWav == NULL || bytesToWrite == 0 || pData == NULL) {
+ return 0;
+ }
+
+ bytesWritten = pWav->onWrite(pWav->pUserData, pData, bytesToWrite);
+ pWav->dataChunkDataSize += bytesWritten;
+
+ return bytesWritten;
+}
+
+DRWAV_API drwav_uint64 drwav_write_pcm_frames_le(drwav* pWav, drwav_uint64 framesToWrite, const void* pData)
+{
+ drwav_uint64 bytesToWrite;
+ drwav_uint64 bytesWritten;
+ const drwav_uint8* pRunningData;
+
+ if (pWav == NULL || framesToWrite == 0 || pData == NULL) {
+ return 0;
+ }
+
+ bytesToWrite = ((framesToWrite * pWav->channels * pWav->bitsPerSample) / 8);
+ if (bytesToWrite > DRWAV_SIZE_MAX) {
+ return 0;
+ }
+
+ bytesWritten = 0;
+ pRunningData = (const drwav_uint8*)pData;
+
+ while (bytesToWrite > 0) {
+ size_t bytesJustWritten;
+ drwav_uint64 bytesToWriteThisIteration;
+
+ bytesToWriteThisIteration = bytesToWrite;
+ DRWAV_ASSERT(bytesToWriteThisIteration <= DRWAV_SIZE_MAX); /* <-- This is checked above. */
+
+ bytesJustWritten = drwav_write_raw(pWav, (size_t)bytesToWriteThisIteration, pRunningData);
+ if (bytesJustWritten == 0) {
+ break;
+ }
+
+ bytesToWrite -= bytesJustWritten;
+ bytesWritten += bytesJustWritten;
+ pRunningData += bytesJustWritten;
+ }
+
+ return (bytesWritten * 8) / pWav->bitsPerSample / pWav->channels;
+}
+
+DRWAV_API drwav_uint64 drwav_write_pcm_frames_be(drwav* pWav, drwav_uint64 framesToWrite, const void* pData)
+{
+ drwav_uint64 bytesToWrite;
+ drwav_uint64 bytesWritten;
+ drwav_uint32 bytesPerSample;
+ const drwav_uint8* pRunningData;
+
+ if (pWav == NULL || framesToWrite == 0 || pData == NULL) {
+ return 0;
+ }
+
+ bytesToWrite = ((framesToWrite * pWav->channels * pWav->bitsPerSample) / 8);
+ if (bytesToWrite > DRWAV_SIZE_MAX) {
+ return 0;
+ }
+
+ bytesWritten = 0;
+ pRunningData = (const drwav_uint8*)pData;
+
+ bytesPerSample = drwav_get_bytes_per_pcm_frame(pWav) / pWav->channels;
+ if (bytesPerSample == 0) {
+ return 0; /* Cannot determine bytes per sample, or bytes per sample is less than one byte. */
+ }
+
+ while (bytesToWrite > 0) {
+ drwav_uint8 temp[4096];
+ drwav_uint32 sampleCount;
+ size_t bytesJustWritten;
+ drwav_uint64 bytesToWriteThisIteration;
+
+ bytesToWriteThisIteration = bytesToWrite;
+ DRWAV_ASSERT(bytesToWriteThisIteration <= DRWAV_SIZE_MAX); /* <-- This is checked above. */
+
+ /*
+ WAV files are always little-endian. We need to byte swap on big-endian architectures. Since our input buffer is read-only we need
+ to use an intermediary buffer for the conversion.
+ */
+ sampleCount = sizeof(temp)/bytesPerSample;
+
+ if (bytesToWriteThisIteration > ((drwav_uint64)sampleCount)*bytesPerSample) {
+ bytesToWriteThisIteration = ((drwav_uint64)sampleCount)*bytesPerSample;
+ }
+
+ DRWAV_COPY_MEMORY(temp, pRunningData, (size_t)bytesToWriteThisIteration);
+ drwav__bswap_samples(temp, sampleCount, bytesPerSample);
+
+ bytesJustWritten = drwav_write_raw(pWav, (size_t)bytesToWriteThisIteration, temp);
+ if (bytesJustWritten == 0) {
+ break;
+ }
+
+ bytesToWrite -= bytesJustWritten;
+ bytesWritten += bytesJustWritten;
+ pRunningData += bytesJustWritten;
+ }
+
+ return (bytesWritten * 8) / pWav->bitsPerSample / pWav->channels;
+}
+
+DRWAV_API drwav_uint64 drwav_write_pcm_frames(drwav* pWav, drwav_uint64 framesToWrite, const void* pData)
+{
+ if (drwav__is_little_endian()) {
+ return drwav_write_pcm_frames_le(pWav, framesToWrite, pData);
+ } else {
+ return drwav_write_pcm_frames_be(pWav, framesToWrite, pData);
+ }
+}
+
+
+DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__msadpcm(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut)
+{
+ drwav_uint64 totalFramesRead = 0;
+
+ DRWAV_ASSERT(pWav != NULL);
+ DRWAV_ASSERT(framesToRead > 0);
+
+ /* TODO: Lots of room for optimization here. */
+
+ while (pWav->readCursorInPCMFrames < pWav->totalPCMFrameCount) {
+ DRWAV_ASSERT(framesToRead > 0); /* This loop iteration will never get hit with framesToRead == 0 because it's asserted at the top, and we check for 0 inside the loop just below. */
+
+ /* If there are no cached frames we need to load a new block. */
+ if (pWav->msadpcm.cachedFrameCount == 0 && pWav->msadpcm.bytesRemainingInBlock == 0) {
+ if (pWav->channels == 1) {
+ /* Mono. */
+ drwav_uint8 header[7];
+ if (pWav->onRead(pWav->pUserData, header, sizeof(header)) != sizeof(header)) {
+ return totalFramesRead;
+ }
+ pWav->msadpcm.bytesRemainingInBlock = pWav->fmt.blockAlign - sizeof(header);
+
+ pWav->msadpcm.predictor[0] = header[0];
+ pWav->msadpcm.delta[0] = drwav_bytes_to_s16(header + 1);
+ pWav->msadpcm.prevFrames[0][1] = (drwav_int32)drwav_bytes_to_s16(header + 3);
+ pWav->msadpcm.prevFrames[0][0] = (drwav_int32)drwav_bytes_to_s16(header + 5);
+ pWav->msadpcm.cachedFrames[2] = pWav->msadpcm.prevFrames[0][0];
+ pWav->msadpcm.cachedFrames[3] = pWav->msadpcm.prevFrames[0][1];
+ pWav->msadpcm.cachedFrameCount = 2;
+ } else {
+ /* Stereo. */
+ drwav_uint8 header[14];
+ if (pWav->onRead(pWav->pUserData, header, sizeof(header)) != sizeof(header)) {
+ return totalFramesRead;
+ }
+ pWav->msadpcm.bytesRemainingInBlock = pWav->fmt.blockAlign - sizeof(header);
+
+ pWav->msadpcm.predictor[0] = header[0];
+ pWav->msadpcm.predictor[1] = header[1];
+ pWav->msadpcm.delta[0] = drwav_bytes_to_s16(header + 2);
+ pWav->msadpcm.delta[1] = drwav_bytes_to_s16(header + 4);
+ pWav->msadpcm.prevFrames[0][1] = (drwav_int32)drwav_bytes_to_s16(header + 6);
+ pWav->msadpcm.prevFrames[1][1] = (drwav_int32)drwav_bytes_to_s16(header + 8);
+ pWav->msadpcm.prevFrames[0][0] = (drwav_int32)drwav_bytes_to_s16(header + 10);
+ pWav->msadpcm.prevFrames[1][0] = (drwav_int32)drwav_bytes_to_s16(header + 12);
+
+ pWav->msadpcm.cachedFrames[0] = pWav->msadpcm.prevFrames[0][0];
+ pWav->msadpcm.cachedFrames[1] = pWav->msadpcm.prevFrames[1][0];
+ pWav->msadpcm.cachedFrames[2] = pWav->msadpcm.prevFrames[0][1];
+ pWav->msadpcm.cachedFrames[3] = pWav->msadpcm.prevFrames[1][1];
+ pWav->msadpcm.cachedFrameCount = 2;
+ }
+ }
+
+ /* Output anything that's cached. */
+ while (framesToRead > 0 && pWav->msadpcm.cachedFrameCount > 0 && pWav->readCursorInPCMFrames < pWav->totalPCMFrameCount) {
+ if (pBufferOut != NULL) {
+ drwav_uint32 iSample = 0;
+ for (iSample = 0; iSample < pWav->channels; iSample += 1) {
+ pBufferOut[iSample] = (drwav_int16)pWav->msadpcm.cachedFrames[(drwav_countof(pWav->msadpcm.cachedFrames) - (pWav->msadpcm.cachedFrameCount*pWav->channels)) + iSample];
+ }
+
+ pBufferOut += pWav->channels;
+ }
+
+ framesToRead -= 1;
+ totalFramesRead += 1;
+ pWav->readCursorInPCMFrames += 1;
+ pWav->msadpcm.cachedFrameCount -= 1;
+ }
+
+ if (framesToRead == 0) {
+ break;
+ }
+
+
+ /*
+ If there's nothing left in the cache, just go ahead and load more. If there's nothing left to load in the current block we just continue to the next
+ loop iteration which will trigger the loading of a new block.
+ */
+ if (pWav->msadpcm.cachedFrameCount == 0) {
+ if (pWav->msadpcm.bytesRemainingInBlock == 0) {
+ continue;
+ } else {
+ static 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 };
+
+ drwav_uint8 nibbles;
+ drwav_int32 nibble0;
+ drwav_int32 nibble1;
+
+ if (pWav->onRead(pWav->pUserData, &nibbles, 1) != 1) {
+ return totalFramesRead;
+ }
+ pWav->msadpcm.bytesRemainingInBlock -= 1;
+
+ /* TODO: Optimize away these if statements. */
+ nibble0 = ((nibbles & 0xF0) >> 4); if ((nibbles & 0x80)) { nibble0 |= 0xFFFFFFF0UL; }
+ nibble1 = ((nibbles & 0x0F) >> 0); if ((nibbles & 0x08)) { nibble1 |= 0xFFFFFFF0UL; }
+
+ if (pWav->channels == 1) {
+ /* Mono. */
+ drwav_int32 newSample0;
+ drwav_int32 newSample1;
+
+ 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.prevFrames[0][0] = pWav->msadpcm.prevFrames[0][1];
+ pWav->msadpcm.prevFrames[0][1] = newSample0;
+
+
+ newSample1 = ((pWav->msadpcm.prevFrames[0][1] * coeff1Table[pWav->msadpcm.predictor[0]]) + (pWav->msadpcm.prevFrames[0][0] * coeff2Table[pWav->msadpcm.predictor[0]])) >> 8;
+ 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.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;
+ } else {
+ /* Stereo. */
+ drwav_int32 newSample0;
+ drwav_int32 newSample1;
+
+ /* Left. */
+ 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.prevFrames[0][0] = pWav->msadpcm.prevFrames[0][1];
+ pWav->msadpcm.prevFrames[0][1] = newSample0;
+
+
+ /* Right. */
+ 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.prevFrames[1][0] = pWav->msadpcm.prevFrames[1][1];
+ pWav->msadpcm.prevFrames[1][1] = newSample1;
+
+ pWav->msadpcm.cachedFrames[2] = newSample0;
+ pWav->msadpcm.cachedFrames[3] = newSample1;
+ pWav->msadpcm.cachedFrameCount = 1;
+ }
+ }
+ }
+ }
+
+ return totalFramesRead;
+}
+
+
+DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__ima(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut)
+{
+ drwav_uint64 totalFramesRead = 0;
+ drwav_uint32 iChannel;
+
+ static 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] = {
+ 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,
+ 130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
+ 337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
+ 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
+ 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
+ 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
+ 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
+ };
+
+ DRWAV_ASSERT(pWav != NULL);
+ DRWAV_ASSERT(framesToRead > 0);
+
+ /* TODO: Lots of room for optimization here. */
+
+ while (pWav->readCursorInPCMFrames < pWav->totalPCMFrameCount) {
+ DRWAV_ASSERT(framesToRead > 0); /* This loop iteration will never get hit with framesToRead == 0 because it's asserted at the top, and we check for 0 inside the loop just below. */
+
+ /* If there are no cached samples we need to load a new block. */
+ if (pWav->ima.cachedFrameCount == 0 && pWav->ima.bytesRemainingInBlock == 0) {
+ if (pWav->channels == 1) {
+ /* Mono. */
+ drwav_uint8 header[4];
+ if (pWav->onRead(pWav->pUserData, header, sizeof(header)) != sizeof(header)) {
+ return totalFramesRead;
+ }
+ pWav->ima.bytesRemainingInBlock = pWav->fmt.blockAlign - sizeof(header);
+
+ if (header[2] >= drwav_countof(stepTable)) {
+ pWav->onSeek(pWav->pUserData, pWav->ima.bytesRemainingInBlock, drwav_seek_origin_current);
+ pWav->ima.bytesRemainingInBlock = 0;
+ return totalFramesRead; /* Invalid data. */
+ }
+
+ pWav->ima.predictor[0] = (drwav_int16)drwav_bytes_to_u16(header + 0);
+ pWav->ima.stepIndex[0] = drwav_clamp(header[2], 0, (drwav_int32)drwav_countof(stepTable)-1); /* Clamp not necessary because we checked above, but adding here to silence a static analysis warning. */
+ pWav->ima.cachedFrames[drwav_countof(pWav->ima.cachedFrames) - 1] = pWav->ima.predictor[0];
+ pWav->ima.cachedFrameCount = 1;
+ } else {
+ /* Stereo. */
+ drwav_uint8 header[8];
+ if (pWav->onRead(pWav->pUserData, header, sizeof(header)) != sizeof(header)) {
+ return totalFramesRead;
+ }
+ pWav->ima.bytesRemainingInBlock = pWav->fmt.blockAlign - sizeof(header);
+
+ if (header[2] >= drwav_countof(stepTable) || header[6] >= drwav_countof(stepTable)) {
+ pWav->onSeek(pWav->pUserData, pWav->ima.bytesRemainingInBlock, drwav_seek_origin_current);
+ pWav->ima.bytesRemainingInBlock = 0;
+ return totalFramesRead; /* Invalid data. */
+ }
+
+ pWav->ima.predictor[0] = drwav_bytes_to_s16(header + 0);
+ pWav->ima.stepIndex[0] = drwav_clamp(header[2], 0, (drwav_int32)drwav_countof(stepTable)-1); /* Clamp not necessary because we checked above, but adding here to silence a static analysis warning. */
+ pWav->ima.predictor[1] = drwav_bytes_to_s16(header + 4);
+ pWav->ima.stepIndex[1] = drwav_clamp(header[6], 0, (drwav_int32)drwav_countof(stepTable)-1); /* Clamp not necessary because we checked above, but adding here to silence a static analysis warning. */
+
+ pWav->ima.cachedFrames[drwav_countof(pWav->ima.cachedFrames) - 2] = pWav->ima.predictor[0];
+ pWav->ima.cachedFrames[drwav_countof(pWav->ima.cachedFrames) - 1] = pWav->ima.predictor[1];
+ pWav->ima.cachedFrameCount = 1;
+ }
+ }
+
+ /* Output anything that's cached. */
+ while (framesToRead > 0 && pWav->ima.cachedFrameCount > 0 && pWav->readCursorInPCMFrames < pWav->totalPCMFrameCount) {
+ if (pBufferOut != NULL) {
+ drwav_uint32 iSample;
+ for (iSample = 0; iSample < pWav->channels; iSample += 1) {
+ pBufferOut[iSample] = (drwav_int16)pWav->ima.cachedFrames[(drwav_countof(pWav->ima.cachedFrames) - (pWav->ima.cachedFrameCount*pWav->channels)) + iSample];
+ }
+ pBufferOut += pWav->channels;
+ }
+
+ framesToRead -= 1;
+ totalFramesRead += 1;
+ pWav->readCursorInPCMFrames += 1;
+ pWav->ima.cachedFrameCount -= 1;
+ }
+
+ if (framesToRead == 0) {
+ break;
+ }
+
+ /*
+ If there's nothing left in the cache, just go ahead and load more. If there's nothing left to load in the current block we just continue to the next
+ loop iteration which will trigger the loading of a new block.
+ */
+ if (pWav->ima.cachedFrameCount == 0) {
+ if (pWav->ima.bytesRemainingInBlock == 0) {
+ continue;
+ } else {
+ /*
+ From what I can tell with stereo streams, it looks like every 4 bytes (8 samples) is for one channel. So it goes 4 bytes for the
+ left channel, 4 bytes for the right channel.
+ */
+ pWav->ima.cachedFrameCount = 8;
+ for (iChannel = 0; iChannel < pWav->channels; ++iChannel) {
+ drwav_uint32 iByte;
+ drwav_uint8 nibbles[4];
+ if (pWav->onRead(pWav->pUserData, &nibbles, 4) != 4) {
+ pWav->ima.cachedFrameCount = 0;
+ return totalFramesRead;
+ }
+ pWav->ima.bytesRemainingInBlock -= 4;
+
+ for (iByte = 0; iByte < 4; ++iByte) {
+ drwav_uint8 nibble0 = ((nibbles[iByte] & 0x0F) >> 0);
+ drwav_uint8 nibble1 = ((nibbles[iByte] & 0xF0) >> 4);
+
+ drwav_int32 step = stepTable[pWav->ima.stepIndex[iChannel]];
+ drwav_int32 predictor = pWav->ima.predictor[iChannel];
+
+ drwav_int32 diff = step >> 3;
+ if (nibble0 & 1) diff += step >> 2;
+ if (nibble0 & 2) diff += step >> 1;
+ if (nibble0 & 4) diff += step;
+ if (nibble0 & 8) diff = -diff;
+
+ predictor = drwav_clamp(predictor + diff, -32768, 32767);
+ pWav->ima.predictor[iChannel] = predictor;
+ pWav->ima.stepIndex[iChannel] = drwav_clamp(pWav->ima.stepIndex[iChannel] + indexTable[nibble0], 0, (drwav_int32)drwav_countof(stepTable)-1);
+ pWav->ima.cachedFrames[(drwav_countof(pWav->ima.cachedFrames) - (pWav->ima.cachedFrameCount*pWav->channels)) + (iByte*2+0)*pWav->channels + iChannel] = predictor;
+
+
+ step = stepTable[pWav->ima.stepIndex[iChannel]];
+ predictor = pWav->ima.predictor[iChannel];
+
+ diff = step >> 3;
+ if (nibble1 & 1) diff += step >> 2;
+ if (nibble1 & 2) diff += step >> 1;
+ if (nibble1 & 4) diff += step;
+ if (nibble1 & 8) diff = -diff;
+
+ predictor = drwav_clamp(predictor + diff, -32768, 32767);
+ pWav->ima.predictor[iChannel] = predictor;
+ pWav->ima.stepIndex[iChannel] = drwav_clamp(pWav->ima.stepIndex[iChannel] + indexTable[nibble1], 0, (drwav_int32)drwav_countof(stepTable)-1);
+ pWav->ima.cachedFrames[(drwav_countof(pWav->ima.cachedFrames) - (pWav->ima.cachedFrameCount*pWav->channels)) + (iByte*2+1)*pWav->channels + iChannel] = predictor;
+ }
+ }
+ }
+ }
+ }
+
+ return totalFramesRead;
+}
+
+
+#ifndef DR_WAV_NO_CONVERSION_API
+static 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,
+ 0xD500, 0xD700, 0xD100, 0xD300, 0xDD00, 0xDF00, 0xD900, 0xDB00, 0xC500, 0xC700, 0xC100, 0xC300, 0xCD00, 0xCF00, 0xC900, 0xCB00,
+ 0xFEA8, 0xFEB8, 0xFE88, 0xFE98, 0xFEE8, 0xFEF8, 0xFEC8, 0xFED8, 0xFE28, 0xFE38, 0xFE08, 0xFE18, 0xFE68, 0xFE78, 0xFE48, 0xFE58,
+ 0xFFA8, 0xFFB8, 0xFF88, 0xFF98, 0xFFE8, 0xFFF8, 0xFFC8, 0xFFD8, 0xFF28, 0xFF38, 0xFF08, 0xFF18, 0xFF68, 0xFF78, 0xFF48, 0xFF58,
+ 0xFAA0, 0xFAE0, 0xFA20, 0xFA60, 0xFBA0, 0xFBE0, 0xFB20, 0xFB60, 0xF8A0, 0xF8E0, 0xF820, 0xF860, 0xF9A0, 0xF9E0, 0xF920, 0xF960,
+ 0xFD50, 0xFD70, 0xFD10, 0xFD30, 0xFDD0, 0xFDF0, 0xFD90, 0xFDB0, 0xFC50, 0xFC70, 0xFC10, 0xFC30, 0xFCD0, 0xFCF0, 0xFC90, 0xFCB0,
+ 0x1580, 0x1480, 0x1780, 0x1680, 0x1180, 0x1080, 0x1380, 0x1280, 0x1D80, 0x1C80, 0x1F80, 0x1E80, 0x1980, 0x1880, 0x1B80, 0x1A80,
+ 0x0AC0, 0x0A40, 0x0BC0, 0x0B40, 0x08C0, 0x0840, 0x09C0, 0x0940, 0x0EC0, 0x0E40, 0x0FC0, 0x0F40, 0x0CC0, 0x0C40, 0x0DC0, 0x0D40,
+ 0x5600, 0x5200, 0x5E00, 0x5A00, 0x4600, 0x4200, 0x4E00, 0x4A00, 0x7600, 0x7200, 0x7E00, 0x7A00, 0x6600, 0x6200, 0x6E00, 0x6A00,
+ 0x2B00, 0x2900, 0x2F00, 0x2D00, 0x2300, 0x2100, 0x2700, 0x2500, 0x3B00, 0x3900, 0x3F00, 0x3D00, 0x3300, 0x3100, 0x3700, 0x3500,
+ 0x0158, 0x0148, 0x0178, 0x0168, 0x0118, 0x0108, 0x0138, 0x0128, 0x01D8, 0x01C8, 0x01F8, 0x01E8, 0x0198, 0x0188, 0x01B8, 0x01A8,
+ 0x0058, 0x0048, 0x0078, 0x0068, 0x0018, 0x0008, 0x0038, 0x0028, 0x00D8, 0x00C8, 0x00F8, 0x00E8, 0x0098, 0x0088, 0x00B8, 0x00A8,
+ 0x0560, 0x0520, 0x05E0, 0x05A0, 0x0460, 0x0420, 0x04E0, 0x04A0, 0x0760, 0x0720, 0x07E0, 0x07A0, 0x0660, 0x0620, 0x06E0, 0x06A0,
+ 0x02B0, 0x0290, 0x02F0, 0x02D0, 0x0230, 0x0210, 0x0270, 0x0250, 0x03B0, 0x0390, 0x03F0, 0x03D0, 0x0330, 0x0310, 0x0370, 0x0350
+};
+
+static unsigned short g_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,
+ 0xF0C4, 0xF144, 0xF1C4, 0xF244, 0xF2C4, 0xF344, 0xF3C4, 0xF444, 0xF4C4, 0xF544, 0xF5C4, 0xF644, 0xF6C4, 0xF744, 0xF7C4, 0xF844,
+ 0xF8A4, 0xF8E4, 0xF924, 0xF964, 0xF9A4, 0xF9E4, 0xFA24, 0xFA64, 0xFAA4, 0xFAE4, 0xFB24, 0xFB64, 0xFBA4, 0xFBE4, 0xFC24, 0xFC64,
+ 0xFC94, 0xFCB4, 0xFCD4, 0xFCF4, 0xFD14, 0xFD34, 0xFD54, 0xFD74, 0xFD94, 0xFDB4, 0xFDD4, 0xFDF4, 0xFE14, 0xFE34, 0xFE54, 0xFE74,
+ 0xFE8C, 0xFE9C, 0xFEAC, 0xFEBC, 0xFECC, 0xFEDC, 0xFEEC, 0xFEFC, 0xFF0C, 0xFF1C, 0xFF2C, 0xFF3C, 0xFF4C, 0xFF5C, 0xFF6C, 0xFF7C,
+ 0xFF88, 0xFF90, 0xFF98, 0xFFA0, 0xFFA8, 0xFFB0, 0xFFB8, 0xFFC0, 0xFFC8, 0xFFD0, 0xFFD8, 0xFFE0, 0xFFE8, 0xFFF0, 0xFFF8, 0x0000,
+ 0x7D7C, 0x797C, 0x757C, 0x717C, 0x6D7C, 0x697C, 0x657C, 0x617C, 0x5D7C, 0x597C, 0x557C, 0x517C, 0x4D7C, 0x497C, 0x457C, 0x417C,
+ 0x3E7C, 0x3C7C, 0x3A7C, 0x387C, 0x367C, 0x347C, 0x327C, 0x307C, 0x2E7C, 0x2C7C, 0x2A7C, 0x287C, 0x267C, 0x247C, 0x227C, 0x207C,
+ 0x1EFC, 0x1DFC, 0x1CFC, 0x1BFC, 0x1AFC, 0x19FC, 0x18FC, 0x17FC, 0x16FC, 0x15FC, 0x14FC, 0x13FC, 0x12FC, 0x11FC, 0x10FC, 0x0FFC,
+ 0x0F3C, 0x0EBC, 0x0E3C, 0x0DBC, 0x0D3C, 0x0CBC, 0x0C3C, 0x0BBC, 0x0B3C, 0x0ABC, 0x0A3C, 0x09BC, 0x093C, 0x08BC, 0x083C, 0x07BC,
+ 0x075C, 0x071C, 0x06DC, 0x069C, 0x065C, 0x061C, 0x05DC, 0x059C, 0x055C, 0x051C, 0x04DC, 0x049C, 0x045C, 0x041C, 0x03DC, 0x039C,
+ 0x036C, 0x034C, 0x032C, 0x030C, 0x02EC, 0x02CC, 0x02AC, 0x028C, 0x026C, 0x024C, 0x022C, 0x020C, 0x01EC, 0x01CC, 0x01AC, 0x018C,
+ 0x0174, 0x0164, 0x0154, 0x0144, 0x0134, 0x0124, 0x0114, 0x0104, 0x00F4, 0x00E4, 0x00D4, 0x00C4, 0x00B4, 0x00A4, 0x0094, 0x0084,
+ 0x0078, 0x0070, 0x0068, 0x0060, 0x0058, 0x0050, 0x0048, 0x0040, 0x0038, 0x0030, 0x0028, 0x0020, 0x0018, 0x0010, 0x0008, 0x0000
+};
+
+static DRWAV_INLINE drwav_int16 drwav__alaw_to_s16(drwav_uint8 sampleIn)
+{
+ return (short)g_drwavAlawTable[sampleIn];
+}
+
+static DRWAV_INLINE drwav_int16 drwav__mulaw_to_s16(drwav_uint8 sampleIn)
+{
+ return (short)g_drwavMulawTable[sampleIn];
+}
+
+
+
+DRWAV_PRIVATE void drwav__pcm_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t totalSampleCount, unsigned int bytesPerSample)
+{
+ size_t i;
+
+ /* Special case for 8-bit sample data because it's treated as unsigned. */
+ if (bytesPerSample == 1) {
+ drwav_u8_to_s16(pOut, pIn, totalSampleCount);
+ return;
+ }
+
+
+ /* Slightly more optimal implementation for common formats. */
+ if (bytesPerSample == 2) {
+ for (i = 0; i < totalSampleCount; ++i) {
+ *pOut++ = ((const drwav_int16*)pIn)[i];
+ }
+ return;
+ }
+ if (bytesPerSample == 3) {
+ drwav_s24_to_s16(pOut, pIn, totalSampleCount);
+ return;
+ }
+ if (bytesPerSample == 4) {
+ drwav_s32_to_s16(pOut, (const drwav_int32*)pIn, totalSampleCount);
+ return;
+ }
+
+
+ /* Anything more than 64 bits per sample is not supported. */
+ if (bytesPerSample > 8) {
+ DRWAV_ZERO_MEMORY(pOut, totalSampleCount * sizeof(*pOut));
+ return;
+ }
+
+
+ /* Generic, slow converter. */
+ for (i = 0; i < totalSampleCount; ++i) {
+ drwav_uint64 sample = 0;
+ unsigned int shift = (8 - bytesPerSample) * 8;
+
+ unsigned int j;
+ for (j = 0; j < bytesPerSample; j += 1) {
+ DRWAV_ASSERT(j < 8);
+ sample |= (drwav_uint64)(pIn[j]) << shift;
+ shift += 8;
+ }
+
+ pIn += j;
+ *pOut++ = (drwav_int16)((drwav_int64)sample >> 48);
+ }
+}
+
+DRWAV_PRIVATE void drwav__ieee_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t totalSampleCount, unsigned int bytesPerSample)
+{
+ if (bytesPerSample == 4) {
+ drwav_f32_to_s16(pOut, (const float*)pIn, totalSampleCount);
+ return;
+ } else if (bytesPerSample == 8) {
+ drwav_f64_to_s16(pOut, (const double*)pIn, totalSampleCount);
+ return;
+ } else {
+ /* Only supporting 32- and 64-bit float. Output silence in all other cases. Contributions welcome for 16-bit float. */
+ DRWAV_ZERO_MEMORY(pOut, totalSampleCount * sizeof(*pOut));
+ return;
+ }
+}
+
+DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__pcm(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut)
+{
+ drwav_uint64 totalFramesRead;
+ drwav_uint8 sampleData[4096] = {0};
+ drwav_uint32 bytesPerFrame;
+ drwav_uint32 bytesPerSample;
+ drwav_uint64 samplesRead;
+
+ /* Fast path. */
+ if ((pWav->translatedFormatTag == DR_WAVE_FORMAT_PCM && pWav->bitsPerSample == 16) || pBufferOut == NULL) {
+ return drwav_read_pcm_frames(pWav, framesToRead, pBufferOut);
+ }
+
+ bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
+ if (bytesPerFrame == 0) {
+ return 0;
+ }
+
+ bytesPerSample = bytesPerFrame / pWav->channels;
+ if (bytesPerSample == 0 || (bytesPerFrame % pWav->channels) != 0) {
+ return 0; /* Only byte-aligned formats are supported. */
+ }
+
+ totalFramesRead = 0;
+
+ while (framesToRead > 0) {
+ drwav_uint64 framesToReadThisIteration = drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame);
+ drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, framesToReadThisIteration, sampleData);
+ if (framesRead == 0) {
+ break;
+ }
+
+ DRWAV_ASSERT(framesRead <= framesToReadThisIteration); /* If this fails it means there's a bug in drwav_read_pcm_frames(). */
+
+ /* Validation to ensure we don't read too much from out intermediary buffer. This is to protect from invalid files. */
+ samplesRead = framesRead * pWav->channels;
+ if ((samplesRead * bytesPerSample) > sizeof(sampleData)) {
+ DRWAV_ASSERT(DRWAV_FALSE); /* This should never happen with a valid file. */
+ break;
+ }
+
+ drwav__pcm_to_s16(pBufferOut, sampleData, (size_t)samplesRead, bytesPerSample);
+
+ pBufferOut += samplesRead;
+ framesToRead -= framesRead;
+ totalFramesRead += framesRead;
+ }
+
+ return totalFramesRead;
+}
+
+DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__ieee(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut)
+{
+ drwav_uint64 totalFramesRead;
+ drwav_uint8 sampleData[4096] = {0};
+ drwav_uint32 bytesPerFrame;
+ drwav_uint32 bytesPerSample;
+ drwav_uint64 samplesRead;
+
+ if (pBufferOut == NULL) {
+ return drwav_read_pcm_frames(pWav, framesToRead, NULL);
+ }
+
+ bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
+ if (bytesPerFrame == 0) {
+ return 0;
+ }
+
+ bytesPerSample = bytesPerFrame / pWav->channels;
+ if (bytesPerSample == 0 || (bytesPerFrame % pWav->channels) != 0) {
+ return 0; /* Only byte-aligned formats are supported. */
+ }
+
+ totalFramesRead = 0;
+
+ while (framesToRead > 0) {
+ drwav_uint64 framesToReadThisIteration = drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame);
+ drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, framesToReadThisIteration, sampleData);
+ if (framesRead == 0) {
+ break;
+ }
+
+ DRWAV_ASSERT(framesRead <= framesToReadThisIteration); /* If this fails it means there's a bug in drwav_read_pcm_frames(). */
+
+ /* Validation to ensure we don't read too much from out intermediary buffer. This is to protect from invalid files. */
+ samplesRead = framesRead * pWav->channels;
+ if ((samplesRead * bytesPerSample) > sizeof(sampleData)) {
+ DRWAV_ASSERT(DRWAV_FALSE); /* This should never happen with a valid file. */
+ break;
+ }
+
+ drwav__ieee_to_s16(pBufferOut, sampleData, (size_t)samplesRead, bytesPerSample); /* Safe cast. */
+
+ pBufferOut += samplesRead;
+ framesToRead -= framesRead;
+ totalFramesRead += framesRead;
+ }
+
+ return totalFramesRead;
+}
+
+DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__alaw(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut)
+{
+ drwav_uint64 totalFramesRead;
+ drwav_uint8 sampleData[4096] = {0};
+ drwav_uint32 bytesPerFrame;
+ drwav_uint32 bytesPerSample;
+ drwav_uint64 samplesRead;
+
+ if (pBufferOut == NULL) {
+ return drwav_read_pcm_frames(pWav, framesToRead, NULL);
+ }
+
+ bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
+ if (bytesPerFrame == 0) {
+ return 0;
+ }
+
+ bytesPerSample = bytesPerFrame / pWav->channels;
+ if (bytesPerSample == 0 || (bytesPerFrame % pWav->channels) != 0) {
+ return 0; /* Only byte-aligned formats are supported. */
+ }
+
+ totalFramesRead = 0;
+
+ while (framesToRead > 0) {
+ drwav_uint64 framesToReadThisIteration = drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame);
+ drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, framesToReadThisIteration, sampleData);
+ if (framesRead == 0) {
+ break;
+ }
+
+ DRWAV_ASSERT(framesRead <= framesToReadThisIteration); /* If this fails it means there's a bug in drwav_read_pcm_frames(). */
+
+ /* Validation to ensure we don't read too much from out intermediary buffer. This is to protect from invalid files. */
+ samplesRead = framesRead * pWav->channels;
+ if ((samplesRead * bytesPerSample) > sizeof(sampleData)) {
+ DRWAV_ASSERT(DRWAV_FALSE); /* This should never happen with a valid file. */
+ break;
+ }
+
+ drwav_alaw_to_s16(pBufferOut, sampleData, (size_t)samplesRead);
+
+ /*
+ For some reason libsndfile seems to be returning samples of the opposite sign for a-law, but only
+ with AIFF files. For WAV files it seems to be the same as dr_wav. This is resulting in dr_wav's
+ automated tests failing. I'm not sure which is correct, but will assume dr_wav. If we're enforcing
+ libsndfile compatibility we'll swap the signs here.
+ */
+ #ifdef DR_WAV_LIBSNDFILE_COMPAT
+ {
+ if (pWav->container == drwav_container_aiff) {
+ drwav_uint64 iSample;
+ for (iSample = 0; iSample < samplesRead; iSample += 1) {
+ pBufferOut[iSample] = -pBufferOut[iSample];
+ }
+ }
+ }
+ #endif
+
+ pBufferOut += samplesRead;
+ framesToRead -= framesRead;
+ totalFramesRead += framesRead;
+ }
+
+ return totalFramesRead;
+}
+
+DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__mulaw(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut)
+{
+ drwav_uint64 totalFramesRead;
+ drwav_uint8 sampleData[4096] = {0};
+ drwav_uint32 bytesPerFrame;
+ drwav_uint32 bytesPerSample;
+ drwav_uint64 samplesRead;
+
+ if (pBufferOut == NULL) {
+ return drwav_read_pcm_frames(pWav, framesToRead, NULL);
+ }
+
+ bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
+ if (bytesPerFrame == 0) {
+ return 0;
+ }
+
+ bytesPerSample = bytesPerFrame / pWav->channels;
+ if (bytesPerSample == 0 || (bytesPerFrame % pWav->channels) != 0) {
+ return 0; /* Only byte-aligned formats are supported. */
+ }
+
+ totalFramesRead = 0;
+
+ while (framesToRead > 0) {
+ drwav_uint64 framesToReadThisIteration = drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame);
+ drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, framesToReadThisIteration, sampleData);
+ if (framesRead == 0) {
+ break;
+ }
+
+ DRWAV_ASSERT(framesRead <= framesToReadThisIteration); /* If this fails it means there's a bug in drwav_read_pcm_frames(). */
+
+ /* Validation to ensure we don't read too much from out intermediary buffer. This is to protect from invalid files. */
+ samplesRead = framesRead * pWav->channels;
+ if ((samplesRead * bytesPerSample) > sizeof(sampleData)) {
+ DRWAV_ASSERT(DRWAV_FALSE); /* This should never happen with a valid file. */
+ break;
+ }
+
+ drwav_mulaw_to_s16(pBufferOut, sampleData, (size_t)samplesRead);
+
+ /*
+ Just like with alaw, for some reason the signs between libsndfile and dr_wav are opposite. We just need to
+ swap the sign if we're compiling with libsndfile compatiblity so our automated tests don't fail.
+ */
+ #ifdef DR_WAV_LIBSNDFILE_COMPAT
+ {
+ if (pWav->container == drwav_container_aiff) {
+ drwav_uint64 iSample;
+ for (iSample = 0; iSample < samplesRead; iSample += 1) {
+ pBufferOut[iSample] = -pBufferOut[iSample];
+ }
+ }
+ }
+ #endif
+
+ pBufferOut += samplesRead;
+ framesToRead -= framesRead;
+ totalFramesRead += framesRead;
+ }
+
+ return totalFramesRead;
+}
+
+DRWAV_API drwav_uint64 drwav_read_pcm_frames_s16(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut)
+{
+ if (pWav == NULL || framesToRead == 0) {
+ return 0;
+ }
+
+ if (pBufferOut == NULL) {
+ return drwav_read_pcm_frames(pWav, framesToRead, NULL);
+ }
+
+ /* Don't try to read more samples than can potentially fit in the output buffer. */
+ if (framesToRead * pWav->channels * sizeof(drwav_int16) > DRWAV_SIZE_MAX) {
+ framesToRead = DRWAV_SIZE_MAX / sizeof(drwav_int16) / pWav->channels;
+ }
+
+ if (pWav->translatedFormatTag == DR_WAVE_FORMAT_PCM) {
+ return drwav_read_pcm_frames_s16__pcm(pWav, framesToRead, pBufferOut);
+ }
+
+ if (pWav->translatedFormatTag == DR_WAVE_FORMAT_IEEE_FLOAT) {
+ return drwav_read_pcm_frames_s16__ieee(pWav, framesToRead, pBufferOut);
+ }
+
+ if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ALAW) {
+ return drwav_read_pcm_frames_s16__alaw(pWav, framesToRead, pBufferOut);
+ }
+
+ if (pWav->translatedFormatTag == DR_WAVE_FORMAT_MULAW) {
+ return drwav_read_pcm_frames_s16__mulaw(pWav, framesToRead, pBufferOut);
+ }
+
+ if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM) {
+ return drwav_read_pcm_frames_s16__msadpcm(pWav, framesToRead, pBufferOut);
+ }
+
+ if (pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
+ return drwav_read_pcm_frames_s16__ima(pWav, framesToRead, pBufferOut);
+ }
+
+ return 0;
+}
+
+DRWAV_API drwav_uint64 drwav_read_pcm_frames_s16le(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut)
+{
+ drwav_uint64 framesRead = drwav_read_pcm_frames_s16(pWav, framesToRead, pBufferOut);
+ if (pBufferOut != NULL && drwav__is_little_endian() == DRWAV_FALSE) {
+ drwav__bswap_samples_s16(pBufferOut, framesRead*pWav->channels);
+ }
+
+ return framesRead;
+}
+
+DRWAV_API drwav_uint64 drwav_read_pcm_frames_s16be(drwav* pWav, drwav_uint64 framesToRead, drwav_int16* pBufferOut)
+{
+ drwav_uint64 framesRead = drwav_read_pcm_frames_s16(pWav, framesToRead, pBufferOut);
+ if (pBufferOut != NULL && drwav__is_little_endian() == DRWAV_TRUE) {
+ drwav__bswap_samples_s16(pBufferOut, framesRead*pWav->channels);
+ }
+
+ return framesRead;
+}
+
+
+DRWAV_API void drwav_u8_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCount)
+{
+ int r;
+ size_t i;
+ for (i = 0; i < sampleCount; ++i) {
+ int x = pIn[i];
+ r = x << 8;
+ r = r - 32768;
+ pOut[i] = (short)r;
+ }
+}
+
+DRWAV_API void drwav_s24_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCount)
+{
+ int r;
+ size_t i;
+ for (i = 0; i < sampleCount; ++i) {
+ int x = ((int)(((unsigned int)(((const drwav_uint8*)pIn)[i*3+0]) << 8) | ((unsigned int)(((const drwav_uint8*)pIn)[i*3+1]) << 16) | ((unsigned int)(((const drwav_uint8*)pIn)[i*3+2])) << 24)) >> 8;
+ r = x >> 8;
+ pOut[i] = (short)r;
+ }
+}
+
+DRWAV_API void drwav_s32_to_s16(drwav_int16* pOut, const drwav_int32* pIn, size_t sampleCount)
+{
+ int r;
+ size_t i;
+ for (i = 0; i < sampleCount; ++i) {
+ int x = pIn[i];
+ r = x >> 16;
+ pOut[i] = (short)r;
+ }
+}
+
+DRWAV_API void drwav_f32_to_s16(drwav_int16* pOut, const float* pIn, size_t sampleCount)
+{
+ int r;
+ size_t i;
+ for (i = 0; i < sampleCount; ++i) {
+ float x = pIn[i];
+ float c;
+ c = ((x < -1) ? -1 : ((x > 1) ? 1 : x));
+ c = c + 1;
+ r = (int)(c * 32767.5f);
+ r = r - 32768;
+ pOut[i] = (short)r;
+ }
+}
+
+DRWAV_API void drwav_f64_to_s16(drwav_int16* pOut, const double* pIn, size_t sampleCount)
+{
+ int r;
+ size_t i;
+ for (i = 0; i < sampleCount; ++i) {
+ double x = pIn[i];
+ double c;
+ c = ((x < -1) ? -1 : ((x > 1) ? 1 : x));
+ c = c + 1;
+ r = (int)(c * 32767.5);
+ r = r - 32768;
+ pOut[i] = (short)r;
+ }
+}
+
+DRWAV_API void drwav_alaw_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCount)
+{
+ size_t i;
+ for (i = 0; i < sampleCount; ++i) {
+ pOut[i] = drwav__alaw_to_s16(pIn[i]);
+ }
+}
+
+DRWAV_API void drwav_mulaw_to_s16(drwav_int16* pOut, const drwav_uint8* pIn, size_t sampleCount)
+{
+ size_t i;
+ for (i = 0; i < sampleCount; ++i) {
+ pOut[i] = drwav__mulaw_to_s16(pIn[i]);
+ }
+}
+
+
+DRWAV_PRIVATE void drwav__pcm_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount, unsigned int bytesPerSample)
+{
+ unsigned int i;
+
+ /* Special case for 8-bit sample data because it's treated as unsigned. */
+ if (bytesPerSample == 1) {
+ drwav_u8_to_f32(pOut, pIn, sampleCount);
+ return;
+ }
+
+ /* Slightly more optimal implementation for common formats. */
+ if (bytesPerSample == 2) {
+ drwav_s16_to_f32(pOut, (const drwav_int16*)pIn, sampleCount);
+ return;
+ }
+ if (bytesPerSample == 3) {
+ drwav_s24_to_f32(pOut, pIn, sampleCount);
+ return;
+ }
+ if (bytesPerSample == 4) {
+ drwav_s32_to_f32(pOut, (const drwav_int32*)pIn, sampleCount);
+ return;
+ }
+
+
+ /* Anything more than 64 bits per sample is not supported. */
+ if (bytesPerSample > 8) {
+ DRWAV_ZERO_MEMORY(pOut, sampleCount * sizeof(*pOut));
+ return;
+ }
+
+
+ /* Generic, slow converter. */
+ for (i = 0; i < sampleCount; ++i) {
+ drwav_uint64 sample = 0;
+ unsigned int shift = (8 - bytesPerSample) * 8;
+
+ unsigned int j;
+ for (j = 0; j < bytesPerSample; j += 1) {
+ DRWAV_ASSERT(j < 8);
+ sample |= (drwav_uint64)(pIn[j]) << shift;
+ shift += 8;
+ }
+
+ pIn += j;
+ *pOut++ = (float)((drwav_int64)sample / 9223372036854775807.0);
+ }
+}
+
+DRWAV_PRIVATE void drwav__ieee_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount, unsigned int bytesPerSample)
+{
+ if (bytesPerSample == 4) {
+ unsigned int i;
+ for (i = 0; i < sampleCount; ++i) {
+ *pOut++ = ((const float*)pIn)[i];
+ }
+ return;
+ } else if (bytesPerSample == 8) {
+ drwav_f64_to_f32(pOut, (const double*)pIn, sampleCount);
+ return;
+ } else {
+ /* Only supporting 32- and 64-bit float. Output silence in all other cases. Contributions welcome for 16-bit float. */
+ DRWAV_ZERO_MEMORY(pOut, sampleCount * sizeof(*pOut));
+ return;
+ }
+}
+
+
+DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_f32__pcm(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut)
+{
+ drwav_uint64 totalFramesRead;
+ drwav_uint8 sampleData[4096] = {0};
+ drwav_uint32 bytesPerFrame;
+ drwav_uint32 bytesPerSample;
+ drwav_uint64 samplesRead;
+
+ bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
+ if (bytesPerFrame == 0) {
+ return 0;
+ }
+
+ bytesPerSample = bytesPerFrame / pWav->channels;
+ if (bytesPerSample == 0 || (bytesPerFrame % pWav->channels) != 0) {
+ return 0; /* Only byte-aligned formats are supported. */
+ }
+
+ totalFramesRead = 0;
+
+ while (framesToRead > 0) {
+ drwav_uint64 framesToReadThisIteration = drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame);
+ drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, framesToReadThisIteration, sampleData);
+ if (framesRead == 0) {
+ break;
+ }
+
+ DRWAV_ASSERT(framesRead <= framesToReadThisIteration); /* If this fails it means there's a bug in drwav_read_pcm_frames(). */
+
+ /* Validation to ensure we don't read too much from out intermediary buffer. This is to protect from invalid files. */
+ samplesRead = framesRead * pWav->channels;
+ if ((samplesRead * bytesPerSample) > sizeof(sampleData)) {
+ DRWAV_ASSERT(DRWAV_FALSE); /* This should never happen with a valid file. */
+ break;
+ }
+
+ drwav__pcm_to_f32(pBufferOut, sampleData, (size_t)samplesRead, bytesPerSample);
+
+ pBufferOut += samplesRead;
+ framesToRead -= framesRead;
+ totalFramesRead += framesRead;
+ }
+
+ return totalFramesRead;
+}
+
+DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_f32__msadpcm_ima(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut)
+{
+ /*
+ We're just going to borrow the implementation from the drwav_read_s16() since ADPCM is a little bit more complicated than other formats and I don't
+ want to duplicate that code.
+ */
+ drwav_uint64 totalFramesRead;
+ drwav_int16 samples16[2048];
+
+ totalFramesRead = 0;
+
+ while (framesToRead > 0) {
+ drwav_uint64 framesToReadThisIteration = drwav_min(framesToRead, drwav_countof(samples16)/pWav->channels);
+ drwav_uint64 framesRead = drwav_read_pcm_frames_s16(pWav, framesToReadThisIteration, samples16);
+ if (framesRead == 0) {
+ break;
+ }
+
+ DRWAV_ASSERT(framesRead <= framesToReadThisIteration); /* If this fails it means there's a bug in drwav_read_pcm_frames(). */
+
+ drwav_s16_to_f32(pBufferOut, samples16, (size_t)(framesRead*pWav->channels)); /* <-- Safe cast because we're clamping to 2048. */
+
+ pBufferOut += framesRead*pWav->channels;
+ framesToRead -= framesRead;
+ totalFramesRead += framesRead;
+ }
+
+ return totalFramesRead;
+}
+
+DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_f32__ieee(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut)
+{
+ drwav_uint64 totalFramesRead;
+ drwav_uint8 sampleData[4096] = {0};
+ drwav_uint32 bytesPerFrame;
+ drwav_uint32 bytesPerSample;
+ drwav_uint64 samplesRead;
+
+ /* Fast path. */
+ if (pWav->translatedFormatTag == DR_WAVE_FORMAT_IEEE_FLOAT && pWav->bitsPerSample == 32) {
+ return drwav_read_pcm_frames(pWav, framesToRead, pBufferOut);
+ }
+
+ bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
+ if (bytesPerFrame == 0) {
+ return 0;
+ }
+
+ bytesPerSample = bytesPerFrame / pWav->channels;
+ if (bytesPerSample == 0 || (bytesPerFrame % pWav->channels) != 0) {
+ return 0; /* Only byte-aligned formats are supported. */
+ }
+
+ totalFramesRead = 0;
+
+ while (framesToRead > 0) {
+ drwav_uint64 framesToReadThisIteration = drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame);
+ drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, framesToReadThisIteration, sampleData);
+ if (framesRead == 0) {
+ break;
+ }
+
+ DRWAV_ASSERT(framesRead <= framesToReadThisIteration); /* If this fails it means there's a bug in drwav_read_pcm_frames(). */
+
+ /* Validation to ensure we don't read too much from out intermediary buffer. This is to protect from invalid files. */
+ samplesRead = framesRead * pWav->channels;
+ if ((samplesRead * bytesPerSample) > sizeof(sampleData)) {
+ DRWAV_ASSERT(DRWAV_FALSE); /* This should never happen with a valid file. */
+ break;
+ }
+
+ drwav__ieee_to_f32(pBufferOut, sampleData, (size_t)samplesRead, bytesPerSample);
+
+ pBufferOut += samplesRead;
+ framesToRead -= framesRead;
+ totalFramesRead += framesRead;
+ }
+
+ return totalFramesRead;
+}
+
+DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_f32__alaw(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut)
+{
+ drwav_uint64 totalFramesRead;
+ drwav_uint8 sampleData[4096] = {0};
+ drwav_uint32 bytesPerFrame;
+ drwav_uint32 bytesPerSample;
+ drwav_uint64 samplesRead;
+
+ bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
+ if (bytesPerFrame == 0) {
+ return 0;
+ }
+
+ bytesPerSample = bytesPerFrame / pWav->channels;
+ if (bytesPerSample == 0 || (bytesPerFrame % pWav->channels) != 0) {
+ return 0; /* Only byte-aligned formats are supported. */
+ }
+
+ totalFramesRead = 0;
+
+ while (framesToRead > 0) {
+ drwav_uint64 framesToReadThisIteration = drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame);
+ drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, framesToReadThisIteration, sampleData);
+ if (framesRead == 0) {
+ break;
+ }
+
+ DRWAV_ASSERT(framesRead <= framesToReadThisIteration); /* If this fails it means there's a bug in drwav_read_pcm_frames(). */
+
+ /* Validation to ensure we don't read too much from out intermediary buffer. This is to protect from invalid files. */
+ samplesRead = framesRead * pWav->channels;
+ if ((samplesRead * bytesPerSample) > sizeof(sampleData)) {
+ DRWAV_ASSERT(DRWAV_FALSE); /* This should never happen with a valid file. */
+ break;
+ }
+
+ drwav_alaw_to_f32(pBufferOut, sampleData, (size_t)samplesRead);
+
+ #ifdef DR_WAV_LIBSNDFILE_COMPAT
+ {
+ if (pWav->container == drwav_container_aiff) {
+ drwav_uint64 iSample;
+ for (iSample = 0; iSample < samplesRead; iSample += 1) {
+ pBufferOut[iSample] = -pBufferOut[iSample];
+ }
+ }
+ }
+ #endif
+
+ pBufferOut += samplesRead;
+ framesToRead -= framesRead;
+ totalFramesRead += framesRead;
+ }
+
+ return totalFramesRead;
+}
+
+DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_f32__mulaw(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut)
+{
+ drwav_uint64 totalFramesRead;
+ drwav_uint8 sampleData[4096] = {0};
+ drwav_uint32 bytesPerFrame;
+ drwav_uint32 bytesPerSample;
+ drwav_uint64 samplesRead;
+
+ bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
+ if (bytesPerFrame == 0) {
+ return 0;
+ }
+
+ bytesPerSample = bytesPerFrame / pWav->channels;
+ if (bytesPerSample == 0 || (bytesPerFrame % pWav->channels) != 0) {
+ return 0; /* Only byte-aligned formats are supported. */
+ }
+
+ totalFramesRead = 0;
+
+ while (framesToRead > 0) {
+ drwav_uint64 framesToReadThisIteration = drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame);
+ drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, framesToReadThisIteration, sampleData);
+ if (framesRead == 0) {
+ break;
+ }
+
+ DRWAV_ASSERT(framesRead <= framesToReadThisIteration); /* If this fails it means there's a bug in drwav_read_pcm_frames(). */
+
+ /* Validation to ensure we don't read too much from out intermediary buffer. This is to protect from invalid files. */
+ samplesRead = framesRead * pWav->channels;
+ if ((samplesRead * bytesPerSample) > sizeof(sampleData)) {
+ DRWAV_ASSERT(DRWAV_FALSE); /* This should never happen with a valid file. */
+ break;
+ }
+
+ drwav_mulaw_to_f32(pBufferOut, sampleData, (size_t)samplesRead);
+
+ #ifdef DR_WAV_LIBSNDFILE_COMPAT
+ {
+ if (pWav->container == drwav_container_aiff) {
+ drwav_uint64 iSample;
+ for (iSample = 0; iSample < samplesRead; iSample += 1) {
+ pBufferOut[iSample] = -pBufferOut[iSample];
+ }
+ }
+ }
+ #endif
+
+ pBufferOut += samplesRead;
+ framesToRead -= framesRead;
+ totalFramesRead += framesRead;
+ }
+
+ return totalFramesRead;
+}
+
+DRWAV_API drwav_uint64 drwav_read_pcm_frames_f32(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut)
+{
+ if (pWav == NULL || framesToRead == 0) {
+ return 0;
+ }
+
+ if (pBufferOut == NULL) {
+ return drwav_read_pcm_frames(pWav, framesToRead, NULL);
+ }
+
+ /* Don't try to read more samples than can potentially fit in the output buffer. */
+ if (framesToRead * pWav->channels * sizeof(float) > DRWAV_SIZE_MAX) {
+ framesToRead = DRWAV_SIZE_MAX / sizeof(float) / pWav->channels;
+ }
+
+ if (pWav->translatedFormatTag == DR_WAVE_FORMAT_PCM) {
+ return drwav_read_pcm_frames_f32__pcm(pWav, framesToRead, pBufferOut);
+ }
+
+ if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM || pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
+ return drwav_read_pcm_frames_f32__msadpcm_ima(pWav, framesToRead, pBufferOut);
+ }
+
+ if (pWav->translatedFormatTag == DR_WAVE_FORMAT_IEEE_FLOAT) {
+ return drwav_read_pcm_frames_f32__ieee(pWav, framesToRead, pBufferOut);
+ }
+
+ if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ALAW) {
+ return drwav_read_pcm_frames_f32__alaw(pWav, framesToRead, pBufferOut);
+ }
+
+ if (pWav->translatedFormatTag == DR_WAVE_FORMAT_MULAW) {
+ return drwav_read_pcm_frames_f32__mulaw(pWav, framesToRead, pBufferOut);
+ }
+
+ return 0;
+}
+
+DRWAV_API drwav_uint64 drwav_read_pcm_frames_f32le(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut)
+{
+ drwav_uint64 framesRead = drwav_read_pcm_frames_f32(pWav, framesToRead, pBufferOut);
+ if (pBufferOut != NULL && drwav__is_little_endian() == DRWAV_FALSE) {
+ drwav__bswap_samples_f32(pBufferOut, framesRead*pWav->channels);
+ }
+
+ return framesRead;
+}
+
+DRWAV_API drwav_uint64 drwav_read_pcm_frames_f32be(drwav* pWav, drwav_uint64 framesToRead, float* pBufferOut)
+{
+ drwav_uint64 framesRead = drwav_read_pcm_frames_f32(pWav, framesToRead, pBufferOut);
+ if (pBufferOut != NULL && drwav__is_little_endian() == DRWAV_TRUE) {
+ drwav__bswap_samples_f32(pBufferOut, framesRead*pWav->channels);
+ }
+
+ return framesRead;
+}
+
+
+DRWAV_API void drwav_u8_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount)
+{
+ size_t i;
+
+ if (pOut == NULL || pIn == NULL) {
+ return;
+ }
+
+#ifdef DR_WAV_LIBSNDFILE_COMPAT
+ /*
+ It appears libsndfile uses slightly different logic for the u8 -> f32 conversion to dr_wav, which in my opinion is incorrect. It appears
+ libsndfile performs the conversion something like "f32 = (u8 / 256) * 2 - 1", however I think it should be "f32 = (u8 / 255) * 2 - 1" (note
+ the divisor of 256 vs 255). I use libsndfile as a benchmark for testing, so I'm therefore leaving this block here just for my automated
+ correctness testing. This is disabled by default.
+ */
+ for (i = 0; i < sampleCount; ++i) {
+ *pOut++ = (pIn[i] / 256.0f) * 2 - 1;
+ }
+#else
+ for (i = 0; i < sampleCount; ++i) {
+ float x = pIn[i];
+ x = x * 0.00784313725490196078f; /* 0..255 to 0..2 */
+ x = x - 1; /* 0..2 to -1..1 */
+
+ *pOut++ = x;
+ }
+#endif
+}
+
+DRWAV_API void drwav_s16_to_f32(float* pOut, const drwav_int16* pIn, size_t sampleCount)
+{
+ size_t i;
+
+ if (pOut == NULL || pIn == NULL) {
+ return;
+ }
+
+ for (i = 0; i < sampleCount; ++i) {
+ *pOut++ = pIn[i] * 0.000030517578125f;
+ }
+}
+
+DRWAV_API void drwav_s24_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount)
+{
+ size_t i;
+
+ if (pOut == NULL || pIn == NULL) {
+ return;
+ }
+
+ for (i = 0; i < sampleCount; ++i) {
+ double x;
+ drwav_uint32 a = ((drwav_uint32)(pIn[i*3+0]) << 8);
+ drwav_uint32 b = ((drwav_uint32)(pIn[i*3+1]) << 16);
+ drwav_uint32 c = ((drwav_uint32)(pIn[i*3+2]) << 24);
+
+ x = (double)((drwav_int32)(a | b | c) >> 8);
+ *pOut++ = (float)(x * 0.00000011920928955078125);
+ }
+}
+
+DRWAV_API void drwav_s32_to_f32(float* pOut, const drwav_int32* pIn, size_t sampleCount)
+{
+ size_t i;
+ if (pOut == NULL || pIn == NULL) {
+ return;
+ }
+
+ for (i = 0; i < sampleCount; ++i) {
+ *pOut++ = (float)(pIn[i] / 2147483648.0);
+ }
+}
+
+DRWAV_API void drwav_f64_to_f32(float* pOut, const double* pIn, size_t sampleCount)
+{
+ size_t i;
+
+ if (pOut == NULL || pIn == NULL) {
+ return;
+ }
+
+ for (i = 0; i < sampleCount; ++i) {
+ *pOut++ = (float)pIn[i];
+ }
+}
+
+DRWAV_API void drwav_alaw_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount)
+{
+ size_t i;
+
+ if (pOut == NULL || pIn == NULL) {
+ return;
+ }
+
+ for (i = 0; i < sampleCount; ++i) {
+ *pOut++ = drwav__alaw_to_s16(pIn[i]) / 32768.0f;
+ }
+}
+
+DRWAV_API void drwav_mulaw_to_f32(float* pOut, const drwav_uint8* pIn, size_t sampleCount)
+{
+ size_t i;
+
+ if (pOut == NULL || pIn == NULL) {
+ return;
+ }
+
+ for (i = 0; i < sampleCount; ++i) {
+ *pOut++ = drwav__mulaw_to_s16(pIn[i]) / 32768.0f;
+ }
+}
+
+
+
+DRWAV_PRIVATE void drwav__pcm_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t totalSampleCount, unsigned int bytesPerSample)
+{
+ unsigned int i;
+
+ /* Special case for 8-bit sample data because it's treated as unsigned. */
+ if (bytesPerSample == 1) {
+ drwav_u8_to_s32(pOut, pIn, totalSampleCount);
+ return;
+ }
+
+ /* Slightly more optimal implementation for common formats. */
+ if (bytesPerSample == 2) {
+ drwav_s16_to_s32(pOut, (const drwav_int16*)pIn, totalSampleCount);
+ return;
+ }
+ if (bytesPerSample == 3) {
+ drwav_s24_to_s32(pOut, pIn, totalSampleCount);
+ return;
+ }
+ if (bytesPerSample == 4) {
+ for (i = 0; i < totalSampleCount; ++i) {
+ *pOut++ = ((const drwav_int32*)pIn)[i];
+ }
+ return;
+ }
+
+
+ /* Anything more than 64 bits per sample is not supported. */
+ if (bytesPerSample > 8) {
+ DRWAV_ZERO_MEMORY(pOut, totalSampleCount * sizeof(*pOut));
+ return;
+ }
+
+
+ /* Generic, slow converter. */
+ for (i = 0; i < totalSampleCount; ++i) {
+ drwav_uint64 sample = 0;
+ unsigned int shift = (8 - bytesPerSample) * 8;
+
+ unsigned int j;
+ for (j = 0; j < bytesPerSample; j += 1) {
+ DRWAV_ASSERT(j < 8);
+ sample |= (drwav_uint64)(pIn[j]) << shift;
+ shift += 8;
+ }
+
+ pIn += j;
+ *pOut++ = (drwav_int32)((drwav_int64)sample >> 32);
+ }
+}
+
+DRWAV_PRIVATE void drwav__ieee_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t totalSampleCount, unsigned int bytesPerSample)
+{
+ if (bytesPerSample == 4) {
+ drwav_f32_to_s32(pOut, (const float*)pIn, totalSampleCount);
+ return;
+ } else if (bytesPerSample == 8) {
+ drwav_f64_to_s32(pOut, (const double*)pIn, totalSampleCount);
+ return;
+ } else {
+ /* Only supporting 32- and 64-bit float. Output silence in all other cases. Contributions welcome for 16-bit float. */
+ DRWAV_ZERO_MEMORY(pOut, totalSampleCount * sizeof(*pOut));
+ return;
+ }
+}
+
+
+DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s32__pcm(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut)
+{
+ drwav_uint64 totalFramesRead;
+ drwav_uint8 sampleData[4096] = {0};
+ drwav_uint32 bytesPerFrame;
+ drwav_uint32 bytesPerSample;
+ drwav_uint64 samplesRead;
+
+ /* Fast path. */
+ if (pWav->translatedFormatTag == DR_WAVE_FORMAT_PCM && pWav->bitsPerSample == 32) {
+ return drwav_read_pcm_frames(pWav, framesToRead, pBufferOut);
+ }
+
+ bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
+ if (bytesPerFrame == 0) {
+ return 0;
+ }
+
+ bytesPerSample = bytesPerFrame / pWav->channels;
+ if (bytesPerSample == 0 || (bytesPerFrame % pWav->channels) != 0) {
+ return 0; /* Only byte-aligned formats are supported. */
+ }
+
+ totalFramesRead = 0;
+
+ while (framesToRead > 0) {
+ drwav_uint64 framesToReadThisIteration = drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame);
+ drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, framesToReadThisIteration, sampleData);
+ if (framesRead == 0) {
+ break;
+ }
+
+ DRWAV_ASSERT(framesRead <= framesToReadThisIteration); /* If this fails it means there's a bug in drwav_read_pcm_frames(). */
+
+ /* Validation to ensure we don't read too much from out intermediary buffer. This is to protect from invalid files. */
+ samplesRead = framesRead * pWav->channels;
+ if ((samplesRead * bytesPerSample) > sizeof(sampleData)) {
+ DRWAV_ASSERT(DRWAV_FALSE); /* This should never happen with a valid file. */
+ break;
+ }
+
+ drwav__pcm_to_s32(pBufferOut, sampleData, (size_t)samplesRead, bytesPerSample);
+
+ pBufferOut += samplesRead;
+ framesToRead -= framesRead;
+ totalFramesRead += framesRead;
+ }
+
+ return totalFramesRead;
+}
+
+DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s32__msadpcm_ima(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut)
+{
+ /*
+ We're just going to borrow the implementation from the drwav_read_s16() since ADPCM is a little bit more complicated than other formats and I don't
+ want to duplicate that code.
+ */
+ drwav_uint64 totalFramesRead = 0;
+ drwav_int16 samples16[2048];
+
+ while (framesToRead > 0) {
+ drwav_uint64 framesToReadThisIteration = drwav_min(framesToRead, drwav_countof(samples16)/pWav->channels);
+ drwav_uint64 framesRead = drwav_read_pcm_frames_s16(pWav, framesToReadThisIteration, samples16);
+ if (framesRead == 0) {
+ break;
+ }
+
+ DRWAV_ASSERT(framesRead <= framesToReadThisIteration); /* If this fails it means there's a bug in drwav_read_pcm_frames(). */
+
+ drwav_s16_to_s32(pBufferOut, samples16, (size_t)(framesRead*pWav->channels)); /* <-- Safe cast because we're clamping to 2048. */
+
+ pBufferOut += framesRead*pWav->channels;
+ framesToRead -= framesRead;
+ totalFramesRead += framesRead;
+ }
+
+ return totalFramesRead;
+}
+
+DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s32__ieee(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut)
+{
+ drwav_uint64 totalFramesRead;
+ drwav_uint8 sampleData[4096] = {0};
+ drwav_uint32 bytesPerFrame;
+ drwav_uint32 bytesPerSample;
+ drwav_uint64 samplesRead;
+
+ bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
+ if (bytesPerFrame == 0) {
+ return 0;
+ }
+
+ bytesPerSample = bytesPerFrame / pWav->channels;
+ if (bytesPerSample == 0 || (bytesPerFrame % pWav->channels) != 0) {
+ return 0; /* Only byte-aligned formats are supported. */
+ }
+
+ totalFramesRead = 0;
+
+ while (framesToRead > 0) {
+ drwav_uint64 framesToReadThisIteration = drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame);
+ drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, framesToReadThisIteration, sampleData);
+ if (framesRead == 0) {
+ break;
+ }
+
+ DRWAV_ASSERT(framesRead <= framesToReadThisIteration); /* If this fails it means there's a bug in drwav_read_pcm_frames(). */
+
+ /* Validation to ensure we don't read too much from out intermediary buffer. This is to protect from invalid files. */
+ samplesRead = framesRead * pWav->channels;
+ if ((samplesRead * bytesPerSample) > sizeof(sampleData)) {
+ DRWAV_ASSERT(DRWAV_FALSE); /* This should never happen with a valid file. */
+ break;
+ }
+
+ drwav__ieee_to_s32(pBufferOut, sampleData, (size_t)samplesRead, bytesPerSample);
+
+ pBufferOut += samplesRead;
+ framesToRead -= framesRead;
+ totalFramesRead += framesRead;
+ }
+
+ return totalFramesRead;
+}
+
+DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s32__alaw(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut)
+{
+ drwav_uint64 totalFramesRead;
+ drwav_uint8 sampleData[4096] = {0};
+ drwav_uint32 bytesPerFrame;
+ drwav_uint32 bytesPerSample;
+ drwav_uint64 samplesRead;
+
+ bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
+ if (bytesPerFrame == 0) {
+ return 0;
+ }
+
+ bytesPerSample = bytesPerFrame / pWav->channels;
+ if (bytesPerSample == 0 || (bytesPerFrame % pWav->channels) != 0) {
+ return 0; /* Only byte-aligned formats are supported. */
+ }
+
+ totalFramesRead = 0;
+
+ while (framesToRead > 0) {
+ drwav_uint64 framesToReadThisIteration = drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame);
+ drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, framesToReadThisIteration, sampleData);
+ if (framesRead == 0) {
+ break;
+ }
+
+ DRWAV_ASSERT(framesRead <= framesToReadThisIteration); /* If this fails it means there's a bug in drwav_read_pcm_frames(). */
+
+ /* Validation to ensure we don't read too much from out intermediary buffer. This is to protect from invalid files. */
+ samplesRead = framesRead * pWav->channels;
+ if ((samplesRead * bytesPerSample) > sizeof(sampleData)) {
+ DRWAV_ASSERT(DRWAV_FALSE); /* This should never happen with a valid file. */
+ break;
+ }
+
+ drwav_alaw_to_s32(pBufferOut, sampleData, (size_t)samplesRead);
+
+ #ifdef DR_WAV_LIBSNDFILE_COMPAT
+ {
+ if (pWav->container == drwav_container_aiff) {
+ drwav_uint64 iSample;
+ for (iSample = 0; iSample < samplesRead; iSample += 1) {
+ pBufferOut[iSample] = -pBufferOut[iSample];
+ }
+ }
+ }
+ #endif
+
+ pBufferOut += samplesRead;
+ framesToRead -= framesRead;
+ totalFramesRead += framesRead;
+ }
+
+ return totalFramesRead;
+}
+
+DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s32__mulaw(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut)
+{
+ drwav_uint64 totalFramesRead;
+ drwav_uint8 sampleData[4096] = {0};
+ drwav_uint32 bytesPerFrame;
+ drwav_uint32 bytesPerSample;
+ drwav_uint64 samplesRead;
+
+ bytesPerFrame = drwav_get_bytes_per_pcm_frame(pWav);
+ if (bytesPerFrame == 0) {
+ return 0;
+ }
+
+ bytesPerSample = bytesPerFrame / pWav->channels;
+ if (bytesPerSample == 0 || (bytesPerFrame % pWav->channels) != 0) {
+ return 0; /* Only byte-aligned formats are supported. */
+ }
+
+ totalFramesRead = 0;
+
+ while (framesToRead > 0) {
+ drwav_uint64 framesToReadThisIteration = drwav_min(framesToRead, sizeof(sampleData)/bytesPerFrame);
+ drwav_uint64 framesRead = drwav_read_pcm_frames(pWav, framesToReadThisIteration, sampleData);
+ if (framesRead == 0) {
+ break;
+ }
+
+ DRWAV_ASSERT(framesRead <= framesToReadThisIteration); /* If this fails it means there's a bug in drwav_read_pcm_frames(). */
+
+ /* Validation to ensure we don't read too much from out intermediary buffer. This is to protect from invalid files. */
+ samplesRead = framesRead * pWav->channels;
+ if ((samplesRead * bytesPerSample) > sizeof(sampleData)) {
+ DRWAV_ASSERT(DRWAV_FALSE); /* This should never happen with a valid file. */
+ break;
+ }
+
+ drwav_mulaw_to_s32(pBufferOut, sampleData, (size_t)samplesRead);
+
+ #ifdef DR_WAV_LIBSNDFILE_COMPAT
+ {
+ if (pWav->container == drwav_container_aiff) {
+ drwav_uint64 iSample;
+ for (iSample = 0; iSample < samplesRead; iSample += 1) {
+ pBufferOut[iSample] = -pBufferOut[iSample];
+ }
+ }
+ }
+ #endif
+
+ pBufferOut += samplesRead;
+ framesToRead -= framesRead;
+ totalFramesRead += framesRead;
+ }
+
+ return totalFramesRead;
+}
+
+DRWAV_API drwav_uint64 drwav_read_pcm_frames_s32(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut)
+{
+ if (pWav == NULL || framesToRead == 0) {
+ return 0;
+ }
+
+ if (pBufferOut == NULL) {
+ return drwav_read_pcm_frames(pWav, framesToRead, NULL);
+ }
+
+ /* Don't try to read more samples than can potentially fit in the output buffer. */
+ if (framesToRead * pWav->channels * sizeof(drwav_int32) > DRWAV_SIZE_MAX) {
+ framesToRead = DRWAV_SIZE_MAX / sizeof(drwav_int32) / pWav->channels;
+ }
+
+ if (pWav->translatedFormatTag == DR_WAVE_FORMAT_PCM) {
+ return drwav_read_pcm_frames_s32__pcm(pWav, framesToRead, pBufferOut);
+ }
+
+ if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ADPCM || pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
+ return drwav_read_pcm_frames_s32__msadpcm_ima(pWav, framesToRead, pBufferOut);
+ }
+
+ if (pWav->translatedFormatTag == DR_WAVE_FORMAT_IEEE_FLOAT) {
+ return drwav_read_pcm_frames_s32__ieee(pWav, framesToRead, pBufferOut);
+ }
+
+ if (pWav->translatedFormatTag == DR_WAVE_FORMAT_ALAW) {
+ return drwav_read_pcm_frames_s32__alaw(pWav, framesToRead, pBufferOut);
+ }
+
+ if (pWav->translatedFormatTag == DR_WAVE_FORMAT_MULAW) {
+ return drwav_read_pcm_frames_s32__mulaw(pWav, framesToRead, pBufferOut);
+ }
+
+ return 0;
+}
+
+DRWAV_API drwav_uint64 drwav_read_pcm_frames_s32le(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut)
+{
+ drwav_uint64 framesRead = drwav_read_pcm_frames_s32(pWav, framesToRead, pBufferOut);
+ if (pBufferOut != NULL && drwav__is_little_endian() == DRWAV_FALSE) {
+ drwav__bswap_samples_s32(pBufferOut, framesRead*pWav->channels);
+ }
+
+ return framesRead;
+}
+
+DRWAV_API drwav_uint64 drwav_read_pcm_frames_s32be(drwav* pWav, drwav_uint64 framesToRead, drwav_int32* pBufferOut)
+{
+ drwav_uint64 framesRead = drwav_read_pcm_frames_s32(pWav, framesToRead, pBufferOut);
+ if (pBufferOut != NULL && drwav__is_little_endian() == DRWAV_TRUE) {
+ drwav__bswap_samples_s32(pBufferOut, framesRead*pWav->channels);
+ }
+
+ return framesRead;
+}
+
+
+DRWAV_API void drwav_u8_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount)
+{
+ size_t i;
+
+ if (pOut == NULL || pIn == NULL) {
+ return;
+ }
+
+ for (i = 0; i < sampleCount; ++i) {
+ *pOut++ = ((int)pIn[i] - 128) << 24;
+ }
+}
+
+DRWAV_API void drwav_s16_to_s32(drwav_int32* pOut, const drwav_int16* pIn, size_t sampleCount)
+{
+ size_t i;
+
+ if (pOut == NULL || pIn == NULL) {
+ return;
+ }
+
+ for (i = 0; i < sampleCount; ++i) {
+ *pOut++ = pIn[i] << 16;
+ }
+}
+
+DRWAV_API void drwav_s24_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount)
+{
+ size_t i;
+
+ if (pOut == NULL || pIn == NULL) {
+ return;
+ }
+
+ for (i = 0; i < sampleCount; ++i) {
+ unsigned int s0 = pIn[i*3 + 0];
+ unsigned int s1 = pIn[i*3 + 1];
+ unsigned int s2 = pIn[i*3 + 2];
+
+ drwav_int32 sample32 = (drwav_int32)((s0 << 8) | (s1 << 16) | (s2 << 24));
+ *pOut++ = sample32;
+ }
+}
+
+DRWAV_API void drwav_f32_to_s32(drwav_int32* pOut, const float* pIn, size_t sampleCount)
+{
+ size_t i;
+
+ if (pOut == NULL || pIn == NULL) {
+ return;
+ }
+
+ for (i = 0; i < sampleCount; ++i) {
+ *pOut++ = (drwav_int32)(2147483648.0f * pIn[i]);
+ }
+}
+
+DRWAV_API void drwav_f64_to_s32(drwav_int32* pOut, const double* pIn, size_t sampleCount)
+{
+ size_t i;
+
+ if (pOut == NULL || pIn == NULL) {
+ return;
+ }
+
+ for (i = 0; i < sampleCount; ++i) {
+ *pOut++ = (drwav_int32)(2147483648.0 * pIn[i]);
+ }
+}
+
+DRWAV_API void drwav_alaw_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount)
+{
+ size_t i;
+
+ if (pOut == NULL || pIn == NULL) {
+ return;
+ }
+
+ for (i = 0; i < sampleCount; ++i) {
+ *pOut++ = ((drwav_int32)drwav__alaw_to_s16(pIn[i])) << 16;
+ }
+}
+
+DRWAV_API void drwav_mulaw_to_s32(drwav_int32* pOut, const drwav_uint8* pIn, size_t sampleCount)
+{
+ size_t i;
+
+ if (pOut == NULL || pIn == NULL) {
+ return;
+ }
+
+ for (i= 0; i < sampleCount; ++i) {
+ *pOut++ = ((drwav_int32)drwav__mulaw_to_s16(pIn[i])) << 16;
+ }
+}
+
+
+
+DRWAV_PRIVATE drwav_int16* drwav__read_pcm_frames_and_close_s16(drwav* pWav, unsigned int* channels, unsigned int* sampleRate, drwav_uint64* totalFrameCount)
+{
+ drwav_uint64 sampleDataSize;
+ drwav_int16* pSampleData;
+ drwav_uint64 framesRead;
+
+ DRWAV_ASSERT(pWav != NULL);
+
+ sampleDataSize = pWav->totalPCMFrameCount * pWav->channels * sizeof(drwav_int16);
+ if (sampleDataSize > DRWAV_SIZE_MAX) {
+ drwav_uninit(pWav);
+ return NULL; /* File's too big. */
+ }
+
+ pSampleData = (drwav_int16*)drwav__malloc_from_callbacks((size_t)sampleDataSize, &pWav->allocationCallbacks); /* <-- Safe cast due to the check above. */
+ if (pSampleData == NULL) {
+ drwav_uninit(pWav);
+ return NULL; /* Failed to allocate memory. */
+ }
+
+ framesRead = drwav_read_pcm_frames_s16(pWav, (size_t)pWav->totalPCMFrameCount, pSampleData);
+ if (framesRead != pWav->totalPCMFrameCount) {
+ drwav__free_from_callbacks(pSampleData, &pWav->allocationCallbacks);
+ drwav_uninit(pWav);
+ return NULL; /* There was an error reading the samples. */
+ }
+
+ drwav_uninit(pWav);
+
+ if (sampleRate) {
+ *sampleRate = pWav->sampleRate;
+ }
+ if (channels) {
+ *channels = pWav->channels;
+ }
+ if (totalFrameCount) {
+ *totalFrameCount = pWav->totalPCMFrameCount;
+ }
+
+ return pSampleData;
+}
+
+DRWAV_PRIVATE float* drwav__read_pcm_frames_and_close_f32(drwav* pWav, unsigned int* channels, unsigned int* sampleRate, drwav_uint64* totalFrameCount)
+{
+ drwav_uint64 sampleDataSize;
+ float* pSampleData;
+ drwav_uint64 framesRead;
+
+ DRWAV_ASSERT(pWav != NULL);
+
+ sampleDataSize = pWav->totalPCMFrameCount * pWav->channels * sizeof(float);
+ if (sampleDataSize > DRWAV_SIZE_MAX) {
+ drwav_uninit(pWav);
+ return NULL; /* File's too big. */
+ }
+
+ pSampleData = (float*)drwav__malloc_from_callbacks((size_t)sampleDataSize, &pWav->allocationCallbacks); /* <-- Safe cast due to the check above. */
+ if (pSampleData == NULL) {
+ drwav_uninit(pWav);
+ return NULL; /* Failed to allocate memory. */
+ }
+
+ framesRead = drwav_read_pcm_frames_f32(pWav, (size_t)pWav->totalPCMFrameCount, pSampleData);
+ if (framesRead != pWav->totalPCMFrameCount) {
+ drwav__free_from_callbacks(pSampleData, &pWav->allocationCallbacks);
+ drwav_uninit(pWav);
+ return NULL; /* There was an error reading the samples. */
+ }
+
+ drwav_uninit(pWav);
+
+ if (sampleRate) {
+ *sampleRate = pWav->sampleRate;
+ }
+ if (channels) {
+ *channels = pWav->channels;
+ }
+ if (totalFrameCount) {
+ *totalFrameCount = pWav->totalPCMFrameCount;
+ }
+
+ return pSampleData;
+}
+
+DRWAV_PRIVATE drwav_int32* drwav__read_pcm_frames_and_close_s32(drwav* pWav, unsigned int* channels, unsigned int* sampleRate, drwav_uint64* totalFrameCount)
+{
+ drwav_uint64 sampleDataSize;
+ drwav_int32* pSampleData;
+ drwav_uint64 framesRead;
+
+ DRWAV_ASSERT(pWav != NULL);
+
+ sampleDataSize = pWav->totalPCMFrameCount * pWav->channels * sizeof(drwav_int32);
+ if (sampleDataSize > DRWAV_SIZE_MAX) {
+ drwav_uninit(pWav);
+ return NULL; /* File's too big. */
+ }
+
+ pSampleData = (drwav_int32*)drwav__malloc_from_callbacks((size_t)sampleDataSize, &pWav->allocationCallbacks); /* <-- Safe cast due to the check above. */
+ if (pSampleData == NULL) {
+ drwav_uninit(pWav);
+ return NULL; /* Failed to allocate memory. */
+ }
+
+ framesRead = drwav_read_pcm_frames_s32(pWav, (size_t)pWav->totalPCMFrameCount, pSampleData);
+ if (framesRead != pWav->totalPCMFrameCount) {
+ drwav__free_from_callbacks(pSampleData, &pWav->allocationCallbacks);
+ drwav_uninit(pWav);
+ return NULL; /* There was an error reading the samples. */
+ }
+
+ drwav_uninit(pWav);
+
+ if (sampleRate) {
+ *sampleRate = pWav->sampleRate;
+ }
+ if (channels) {
+ *channels = pWav->channels;
+ }
+ if (totalFrameCount) {
+ *totalFrameCount = pWav->totalPCMFrameCount;
+ }
+
+ return pSampleData;
+}
+
+
+
+DRWAV_API drwav_int16* drwav_open_and_read_pcm_frames_s16(drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks)
+{
+ drwav wav;
+
+ if (channelsOut) {
+ *channelsOut = 0;
+ }
+ if (sampleRateOut) {
+ *sampleRateOut = 0;
+ }
+ if (totalFrameCountOut) {
+ *totalFrameCountOut = 0;
+ }
+
+ if (!drwav_init(&wav, onRead, onSeek, pUserData, pAllocationCallbacks)) {
+ return NULL;
+ }
+
+ return drwav__read_pcm_frames_and_close_s16(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
+}
+
+DRWAV_API float* drwav_open_and_read_pcm_frames_f32(drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks)
+{
+ drwav wav;
+
+ if (channelsOut) {
+ *channelsOut = 0;
+ }
+ if (sampleRateOut) {
+ *sampleRateOut = 0;
+ }
+ if (totalFrameCountOut) {
+ *totalFrameCountOut = 0;
+ }
+
+ if (!drwav_init(&wav, onRead, onSeek, pUserData, pAllocationCallbacks)) {
+ return NULL;
+ }
+
+ return drwav__read_pcm_frames_and_close_f32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
+}
+
+DRWAV_API drwav_int32* drwav_open_and_read_pcm_frames_s32(drwav_read_proc onRead, drwav_seek_proc onSeek, void* pUserData, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks)
+{
+ drwav wav;
+
+ if (channelsOut) {
+ *channelsOut = 0;
+ }
+ if (sampleRateOut) {
+ *sampleRateOut = 0;
+ }
+ if (totalFrameCountOut) {
+ *totalFrameCountOut = 0;
+ }
+
+ if (!drwav_init(&wav, onRead, onSeek, pUserData, pAllocationCallbacks)) {
+ return NULL;
+ }
+
+ return drwav__read_pcm_frames_and_close_s32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
+}
+
+#ifndef DR_WAV_NO_STDIO
+DRWAV_API drwav_int16* drwav_open_file_and_read_pcm_frames_s16(const char* filename, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks)
+{
+ drwav wav;
+
+ if (channelsOut) {
+ *channelsOut = 0;
+ }
+ if (sampleRateOut) {
+ *sampleRateOut = 0;
+ }
+ if (totalFrameCountOut) {
+ *totalFrameCountOut = 0;
+ }
+
+ if (!drwav_init_file(&wav, filename, pAllocationCallbacks)) {
+ return NULL;
+ }
+
+ return drwav__read_pcm_frames_and_close_s16(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
+}
+
+DRWAV_API float* drwav_open_file_and_read_pcm_frames_f32(const char* filename, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks)
+{
+ drwav wav;
+
+ if (channelsOut) {
+ *channelsOut = 0;
+ }
+ if (sampleRateOut) {
+ *sampleRateOut = 0;
+ }
+ if (totalFrameCountOut) {
+ *totalFrameCountOut = 0;
+ }
+
+ if (!drwav_init_file(&wav, filename, pAllocationCallbacks)) {
+ return NULL;
+ }
+
+ return drwav__read_pcm_frames_and_close_f32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
+}
+
+DRWAV_API drwav_int32* drwav_open_file_and_read_pcm_frames_s32(const char* filename, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks)
+{
+ drwav wav;
+
+ if (channelsOut) {
+ *channelsOut = 0;
+ }
+ if (sampleRateOut) {
+ *sampleRateOut = 0;
+ }
+ if (totalFrameCountOut) {
+ *totalFrameCountOut = 0;
+ }
+
+ if (!drwav_init_file(&wav, filename, pAllocationCallbacks)) {
+ return NULL;
+ }
+
+ return drwav__read_pcm_frames_and_close_s32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
+}
+
+
+#ifndef DR_WAV_NO_WCHAR
+DRWAV_API drwav_int16* drwav_open_file_and_read_pcm_frames_s16_w(const wchar_t* filename, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks)
+{
+ drwav wav;
+
+ if (sampleRateOut) {
+ *sampleRateOut = 0;
+ }
+ if (channelsOut) {
+ *channelsOut = 0;
+ }
+ if (totalFrameCountOut) {
+ *totalFrameCountOut = 0;
+ }
+
+ if (!drwav_init_file_w(&wav, filename, pAllocationCallbacks)) {
+ return NULL;
+ }
+
+ return drwav__read_pcm_frames_and_close_s16(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
+}
+
+DRWAV_API float* drwav_open_file_and_read_pcm_frames_f32_w(const wchar_t* filename, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks)
+{
+ drwav wav;
+
+ if (sampleRateOut) {
+ *sampleRateOut = 0;
+ }
+ if (channelsOut) {
+ *channelsOut = 0;
+ }
+ if (totalFrameCountOut) {
+ *totalFrameCountOut = 0;
+ }
+
+ if (!drwav_init_file_w(&wav, filename, pAllocationCallbacks)) {
+ return NULL;
+ }
+
+ return drwav__read_pcm_frames_and_close_f32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
+}
+
+DRWAV_API drwav_int32* drwav_open_file_and_read_pcm_frames_s32_w(const wchar_t* filename, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks)
+{
+ drwav wav;
+
+ if (sampleRateOut) {
+ *sampleRateOut = 0;
+ }
+ if (channelsOut) {
+ *channelsOut = 0;
+ }
+ if (totalFrameCountOut) {
+ *totalFrameCountOut = 0;
+ }
+
+ if (!drwav_init_file_w(&wav, filename, pAllocationCallbacks)) {
+ return NULL;
+ }
+
+ return drwav__read_pcm_frames_and_close_s32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
+}
+#endif /* DR_WAV_NO_WCHAR */
+#endif /* DR_WAV_NO_STDIO */
+
+DRWAV_API drwav_int16* drwav_open_memory_and_read_pcm_frames_s16(const void* data, size_t dataSize, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks)
+{
+ drwav wav;
+
+ if (channelsOut) {
+ *channelsOut = 0;
+ }
+ if (sampleRateOut) {
+ *sampleRateOut = 0;
+ }
+ if (totalFrameCountOut) {
+ *totalFrameCountOut = 0;
+ }
+
+ if (!drwav_init_memory(&wav, data, dataSize, pAllocationCallbacks)) {
+ return NULL;
+ }
+
+ return drwav__read_pcm_frames_and_close_s16(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
+}
+
+DRWAV_API float* drwav_open_memory_and_read_pcm_frames_f32(const void* data, size_t dataSize, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks)
+{
+ drwav wav;
+
+ if (channelsOut) {
+ *channelsOut = 0;
+ }
+ if (sampleRateOut) {
+ *sampleRateOut = 0;
+ }
+ if (totalFrameCountOut) {
+ *totalFrameCountOut = 0;
+ }
+
+ if (!drwav_init_memory(&wav, data, dataSize, pAllocationCallbacks)) {
+ return NULL;
+ }
+
+ return drwav__read_pcm_frames_and_close_f32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
+}
+
+DRWAV_API drwav_int32* drwav_open_memory_and_read_pcm_frames_s32(const void* data, size_t dataSize, unsigned int* channelsOut, unsigned int* sampleRateOut, drwav_uint64* totalFrameCountOut, const drwav_allocation_callbacks* pAllocationCallbacks)
+{
+ drwav wav;
+
+ if (channelsOut) {
+ *channelsOut = 0;
+ }
+ if (sampleRateOut) {
+ *sampleRateOut = 0;
+ }
+ if (totalFrameCountOut) {
+ *totalFrameCountOut = 0;
+ }
+
+ if (!drwav_init_memory(&wav, data, dataSize, pAllocationCallbacks)) {
+ return NULL;
+ }
+
+ return drwav__read_pcm_frames_and_close_s32(&wav, channelsOut, sampleRateOut, totalFrameCountOut);
+}
+#endif /* DR_WAV_NO_CONVERSION_API */
+
+
+DRWAV_API void drwav_free(void* p, const drwav_allocation_callbacks* pAllocationCallbacks)
+{
+ if (pAllocationCallbacks != NULL) {
+ drwav__free_from_callbacks(p, pAllocationCallbacks);
+ } else {
+ drwav__free_default(p, NULL);
+ }
+}
+
+DRWAV_API drwav_uint16 drwav_bytes_to_u16(const drwav_uint8* data)
+{
+ return ((drwav_uint16)data[0] << 0) | ((drwav_uint16)data[1] << 8);
+}
+
+DRWAV_API drwav_int16 drwav_bytes_to_s16(const drwav_uint8* data)
+{
+ return (drwav_int16)drwav_bytes_to_u16(data);
+}
+
+DRWAV_API drwav_uint32 drwav_bytes_to_u32(const drwav_uint8* data)
+{
+ return drwav_bytes_to_u32_le(data);
+}
+
+DRWAV_API float drwav_bytes_to_f32(const drwav_uint8* data)
+{
+ union {
+ drwav_uint32 u32;
+ float f32;
+ } value;
+
+ value.u32 = drwav_bytes_to_u32(data);
+ return value.f32;
+}
+
+DRWAV_API drwav_int32 drwav_bytes_to_s32(const drwav_uint8* data)
+{
+ return (drwav_int32)drwav_bytes_to_u32(data);
+}
+
+DRWAV_API drwav_uint64 drwav_bytes_to_u64(const drwav_uint8* data)
+{
+ return
+ ((drwav_uint64)data[0] << 0) | ((drwav_uint64)data[1] << 8) | ((drwav_uint64)data[2] << 16) | ((drwav_uint64)data[3] << 24) |
+ ((drwav_uint64)data[4] << 32) | ((drwav_uint64)data[5] << 40) | ((drwav_uint64)data[6] << 48) | ((drwav_uint64)data[7] << 56);
+}
+
+DRWAV_API drwav_int64 drwav_bytes_to_s64(const drwav_uint8* data)
+{
+ return (drwav_int64)drwav_bytes_to_u64(data);
+}
+
+
+DRWAV_API drwav_bool32 drwav_guid_equal(const drwav_uint8 a[16], const drwav_uint8 b[16])
+{
+ int i;
+ for (i = 0; i < 16; i += 1) {
+ if (a[i] != b[i]) {
+ return DRWAV_FALSE;
+ }
+ }
+
+ return DRWAV_TRUE;
+}
+
+DRWAV_API drwav_bool32 drwav_fourcc_equal(const drwav_uint8* a, const char* b)
+{
+ return
+ a[0] == b[0] &&
+ a[1] == b[1] &&
+ a[2] == b[2] &&
+ a[3] == b[3];
+}
+
+#ifdef __MRC__
+/* Undo the pragma at the beginning of this file. */
+#pragma options opt reset
+#endif
+
+#endif /* dr_wav_c */
+#endif /* DR_WAV_IMPLEMENTATION */
+
+/*
+REVISION HISTORY
+================
+v0.13.16 - 2024-02-27
+ - Fix a Wdouble-promotion warning.
+
+v0.13.15 - 2024-01-23
+ - Relax some unnecessary validation that prevented some files from loading.
+
+v0.13.14 - 2023-12-02
+ - Fix a warning about an unused variable.
+
+v0.13.13 - 2023-11-02
+ - Fix a warning when compiling with Clang.
+
+v0.13.12 - 2023-08-07
+ - Fix a possible crash in drwav_read_pcm_frames().
+
+v0.13.11 - 2023-07-07
+ - AIFF compatibility improvements.
+
+v0.13.10 - 2023-05-29
+ - Fix a bug where drwav_init_with_metadata() does not decode any frames after initializtion.
+
+v0.13.9 - 2023-05-22
+ - Add support for AIFF decoding (writing and metadata not supported).
+ - Add support for RIFX decoding (writing and metadata not supported).
+ - Fix a bug where metadata is not processed if it's located before the "fmt " chunk.
+ - Add a workaround for a type of malformed WAV file where the size of the "RIFF" and "data" chunks
+ are incorrectly set to 0xFFFFFFFF.
+
+v0.13.8 - 2023-03-25
+ - Fix a possible null pointer dereference.
+ - Fix a crash when loading files with badly formed metadata.
+
+v0.13.7 - 2022-09-17
+ - Fix compilation with DJGPP.
+ - Add support for disabling wchar_t with DR_WAV_NO_WCHAR.
+
+v0.13.6 - 2022-04-10
+ - Fix compilation error on older versions of GCC.
+ - Remove some dependencies on the standard library.
+
+v0.13.5 - 2022-01-26
+ - Fix an error when seeking to the end of the file.
+
+v0.13.4 - 2021-12-08
+ - Fix some static analysis warnings.
+
+v0.13.3 - 2021-11-24
+ - Fix an incorrect assertion when trying to endian swap 1-byte sample formats. This is now a no-op
+ rather than a failed assertion.
+ - Fix a bug with parsing of the bext chunk.
+ - Fix some static analysis warnings.
+
+v0.13.2 - 2021-10-02
+ - Fix a possible buffer overflow when reading from compressed formats.
+
+v0.13.1 - 2021-07-31
+ - Fix platform detection for ARM64.
+
+v0.13.0 - 2021-07-01
+ - Improve support for reading and writing metadata. Use the `_with_metadata()` APIs to initialize
+ a WAV decoder and store the metadata within the `drwav` object. Use the `pMetadata` and
+ `metadataCount` members of the `drwav` object to read the data. The old way of handling metadata
+ via a callback is still usable and valid.
+ - API CHANGE: drwav_target_write_size_bytes() now takes extra parameters for calculating the
+ required write size when writing metadata.
+ - Add drwav_get_cursor_in_pcm_frames()
+ - Add drwav_get_length_in_pcm_frames()
+ - Fix a bug where drwav_read_raw() can call the read callback with a byte count of zero.
+
+v0.12.20 - 2021-06-11
+ - Fix some undefined behavior.
+
+v0.12.19 - 2021-02-21
+ - Fix a warning due to referencing _MSC_VER when it is undefined.
+ - Minor improvements to the management of some internal state concerning the data chunk cursor.
+
+v0.12.18 - 2021-01-31
+ - Clean up some static analysis warnings.
+
+v0.12.17 - 2021-01-17
+ - Minor fix to sample code in documentation.
+ - Correctly qualify a private API as private rather than public.
+ - Code cleanup.
+
+v0.12.16 - 2020-12-02
+ - Fix a bug when trying to read more bytes than can fit in a size_t.
+
+v0.12.15 - 2020-11-21
+ - Fix compilation with OpenWatcom.
+
+v0.12.14 - 2020-11-13
+ - Minor code clean up.
+
+v0.12.13 - 2020-11-01
+ - Improve compiler support for older versions of GCC.
+
+v0.12.12 - 2020-09-28
+ - Add support for RF64.
+ - Fix a bug in writing mode where the size of the RIFF chunk incorrectly includes the header section.
+
+v0.12.11 - 2020-09-08
+ - Fix a compilation error on older compilers.
+
+v0.12.10 - 2020-08-24
+ - Fix a bug when seeking with ADPCM formats.
+
+v0.12.9 - 2020-08-02
+ - Simplify sized types.
+
+v0.12.8 - 2020-07-25
+ - Fix a compilation warning.
+
+v0.12.7 - 2020-07-15
+ - Fix some bugs on big-endian architectures.
+ - Fix an error in s24 to f32 conversion.
+
+v0.12.6 - 2020-06-23
+ - Change drwav_read_*() to allow NULL to be passed in as the output buffer which is equivalent to a forward seek.
+ - Fix a buffer overflow when trying to decode invalid IMA-ADPCM files.
+ - Add include guard for the implementation section.
+
+v0.12.5 - 2020-05-27
+ - Minor documentation fix.
+
+v0.12.4 - 2020-05-16
+ - Replace assert() with DRWAV_ASSERT().
+ - Add compile-time and run-time version querying.
+ - DRWAV_VERSION_MINOR
+ - DRWAV_VERSION_MAJOR
+ - DRWAV_VERSION_REVISION
+ - DRWAV_VERSION_STRING
+ - drwav_version()
+ - drwav_version_string()
+
+v0.12.3 - 2020-04-30
+ - Fix compilation errors with VC6.
+
+v0.12.2 - 2020-04-21
+ - Fix a bug where drwav_init_file() does not close the file handle after attempting to load an erroneous file.
+
+v0.12.1 - 2020-04-13
+ - Fix some pedantic warnings.
+
+v0.12.0 - 2020-04-04
+ - API CHANGE: Add container and format parameters to the chunk callback.
+ - Minor documentation updates.
+
+v0.11.5 - 2020-03-07
+ - Fix compilation error with Visual Studio .NET 2003.
+
+v0.11.4 - 2020-01-29
+ - Fix some static analysis warnings.
+ - Fix a bug when reading f32 samples from an A-law encoded stream.
+
+v0.11.3 - 2020-01-12
+ - Minor changes to some f32 format conversion routines.
+ - Minor bug fix for ADPCM conversion when end of file is reached.
+
+v0.11.2 - 2019-12-02
+ - Fix a possible crash when using custom memory allocators without a custom realloc() implementation.
+ - Fix an integer overflow bug.
+ - Fix a null pointer dereference bug.
+ - Add limits to sample rate, channels and bits per sample to tighten up some validation.
+
+v0.11.1 - 2019-10-07
+ - Internal code clean up.
+
+v0.11.0 - 2019-10-06
+ - API CHANGE: Add support for user defined memory allocation routines. This system allows the program to specify their own memory allocation
+ routines with a user data pointer for client-specific contextual data. This adds an extra parameter to the end of the following APIs:
+ - drwav_init()
+ - drwav_init_ex()
+ - drwav_init_file()
+ - drwav_init_file_ex()
+ - drwav_init_file_w()
+ - drwav_init_file_w_ex()
+ - drwav_init_memory()
+ - drwav_init_memory_ex()
+ - drwav_init_write()
+ - drwav_init_write_sequential()
+ - drwav_init_write_sequential_pcm_frames()
+ - drwav_init_file_write()
+ - drwav_init_file_write_sequential()
+ - drwav_init_file_write_sequential_pcm_frames()
+ - drwav_init_file_write_w()
+ - drwav_init_file_write_sequential_w()
+ - drwav_init_file_write_sequential_pcm_frames_w()
+ - drwav_init_memory_write()
+ - drwav_init_memory_write_sequential()
+ - drwav_init_memory_write_sequential_pcm_frames()
+ - drwav_open_and_read_pcm_frames_s16()
+ - drwav_open_and_read_pcm_frames_f32()
+ - drwav_open_and_read_pcm_frames_s32()
+ - drwav_open_file_and_read_pcm_frames_s16()
+ - drwav_open_file_and_read_pcm_frames_f32()
+ - drwav_open_file_and_read_pcm_frames_s32()
+ - drwav_open_file_and_read_pcm_frames_s16_w()
+ - drwav_open_file_and_read_pcm_frames_f32_w()
+ - drwav_open_file_and_read_pcm_frames_s32_w()
+ - drwav_open_memory_and_read_pcm_frames_s16()
+ - drwav_open_memory_and_read_pcm_frames_f32()
+ - drwav_open_memory_and_read_pcm_frames_s32()
+ Set this extra parameter to NULL to use defaults which is the same as the previous behaviour. Setting this NULL will use
+ DRWAV_MALLOC, DRWAV_REALLOC and DRWAV_FREE.
+ - Add support for reading and writing PCM frames in an explicit endianness. New APIs:
+ - drwav_read_pcm_frames_le()
+ - drwav_read_pcm_frames_be()
+ - drwav_read_pcm_frames_s16le()
+ - drwav_read_pcm_frames_s16be()
+ - drwav_read_pcm_frames_f32le()
+ - drwav_read_pcm_frames_f32be()
+ - drwav_read_pcm_frames_s32le()
+ - drwav_read_pcm_frames_s32be()
+ - drwav_write_pcm_frames_le()
+ - drwav_write_pcm_frames_be()
+ - Remove deprecated APIs.
+ - API CHANGE: The following APIs now return native-endian data. Previously they returned little-endian data.
+ - drwav_read_pcm_frames()
+ - drwav_read_pcm_frames_s16()
+ - drwav_read_pcm_frames_s32()
+ - drwav_read_pcm_frames_f32()
+ - drwav_open_and_read_pcm_frames_s16()
+ - drwav_open_and_read_pcm_frames_s32()
+ - drwav_open_and_read_pcm_frames_f32()
+ - drwav_open_file_and_read_pcm_frames_s16()
+ - drwav_open_file_and_read_pcm_frames_s32()
+ - drwav_open_file_and_read_pcm_frames_f32()
+ - drwav_open_file_and_read_pcm_frames_s16_w()
+ - drwav_open_file_and_read_pcm_frames_s32_w()
+ - drwav_open_file_and_read_pcm_frames_f32_w()
+ - drwav_open_memory_and_read_pcm_frames_s16()
+ - drwav_open_memory_and_read_pcm_frames_s32()
+ - drwav_open_memory_and_read_pcm_frames_f32()
+
+v0.10.1 - 2019-08-31
+ - Correctly handle partial trailing ADPCM blocks.
+
+v0.10.0 - 2019-08-04
+ - Remove deprecated APIs.
+ - Add wchar_t variants for file loading APIs:
+ drwav_init_file_w()
+ drwav_init_file_ex_w()
+ drwav_init_file_write_w()
+ drwav_init_file_write_sequential_w()
+ - Add drwav_target_write_size_bytes() which calculates the total size in bytes of a WAV file given a format and sample count.
+ - Add APIs for specifying the PCM frame count instead of the sample count when opening in sequential write mode:
+ drwav_init_write_sequential_pcm_frames()
+ drwav_init_file_write_sequential_pcm_frames()
+ drwav_init_file_write_sequential_pcm_frames_w()
+ drwav_init_memory_write_sequential_pcm_frames()
+ - Deprecate drwav_open*() and drwav_close():
+ drwav_open()
+ drwav_open_ex()
+ drwav_open_write()
+ drwav_open_write_sequential()
+ drwav_open_file()
+ drwav_open_file_ex()
+ drwav_open_file_write()
+ drwav_open_file_write_sequential()
+ drwav_open_memory()
+ drwav_open_memory_ex()
+ drwav_open_memory_write()
+ drwav_open_memory_write_sequential()
+ drwav_close()
+ - Minor documentation updates.
+
+v0.9.2 - 2019-05-21
+ - Fix warnings.
+
+v0.9.1 - 2019-05-05
+ - Add support for C89.
+ - Change license to choice of public domain or MIT-0.
+
+v0.9.0 - 2018-12-16
+ - API CHANGE: Add new reading APIs for reading by PCM frames instead of samples. Old APIs have been deprecated and
+ will be removed in v0.10.0. Deprecated APIs and their replacements:
+ drwav_read() -> drwav_read_pcm_frames()
+ drwav_read_s16() -> drwav_read_pcm_frames_s16()
+ drwav_read_f32() -> drwav_read_pcm_frames_f32()
+ drwav_read_s32() -> drwav_read_pcm_frames_s32()
+ drwav_seek_to_sample() -> drwav_seek_to_pcm_frame()
+ drwav_write() -> drwav_write_pcm_frames()
+ drwav_open_and_read_s16() -> drwav_open_and_read_pcm_frames_s16()
+ drwav_open_and_read_f32() -> drwav_open_and_read_pcm_frames_f32()
+ drwav_open_and_read_s32() -> drwav_open_and_read_pcm_frames_s32()
+ drwav_open_file_and_read_s16() -> drwav_open_file_and_read_pcm_frames_s16()
+ drwav_open_file_and_read_f32() -> drwav_open_file_and_read_pcm_frames_f32()
+ drwav_open_file_and_read_s32() -> drwav_open_file_and_read_pcm_frames_s32()
+ drwav_open_memory_and_read_s16() -> drwav_open_memory_and_read_pcm_frames_s16()
+ drwav_open_memory_and_read_f32() -> drwav_open_memory_and_read_pcm_frames_f32()
+ drwav_open_memory_and_read_s32() -> drwav_open_memory_and_read_pcm_frames_s32()
+ drwav::totalSampleCount -> drwav::totalPCMFrameCount
+ - API CHANGE: Rename drwav_open_and_read_file_*() to drwav_open_file_and_read_*().
+ - API CHANGE: Rename drwav_open_and_read_memory_*() to drwav_open_memory_and_read_*().
+ - Add built-in support for smpl chunks.
+ - Add support for firing a callback for each chunk in the file at initialization time.
+ - This is enabled through the drwav_init_ex(), etc. family of APIs.
+ - Handle invalid FMT chunks more robustly.
+
+v0.8.5 - 2018-09-11
+ - Const correctness.
+ - Fix a potential stack overflow.
+
+v0.8.4 - 2018-08-07
+ - Improve 64-bit detection.
+
+v0.8.3 - 2018-08-05
+ - Fix C++ build on older versions of GCC.
+
+v0.8.2 - 2018-08-02
+ - Fix some big-endian bugs.
+
+v0.8.1 - 2018-06-29
+ - Add support for sequential writing APIs.
+ - Disable seeking in write mode.
+ - Fix bugs with Wave64.
+ - Fix typos.
+
+v0.8 - 2018-04-27
+ - Bug fix.
+ - Start using major.minor.revision versioning.
+
+v0.7f - 2018-02-05
+ - Restrict ADPCM formats to a maximum of 2 channels.
+
+v0.7e - 2018-02-02
+ - Fix a crash.
+
+v0.7d - 2018-02-01
+ - Fix a crash.
+
+v0.7c - 2018-02-01
+ - Set drwav.bytesPerSample to 0 for all compressed formats.
+ - Fix a crash when reading 16-bit floating point WAV files. In this case dr_wav will output silence for
+ all format conversion reading APIs (*_s16, *_s32, *_f32 APIs).
+ - Fix some divide-by-zero errors.
+
+v0.7b - 2018-01-22
+ - Fix errors with seeking of compressed formats.
+ - Fix compilation error when DR_WAV_NO_CONVERSION_API
+
+v0.7a - 2017-11-17
+ - Fix some GCC warnings.
+
+v0.7 - 2017-11-04
+ - Add writing APIs.
+
+v0.6 - 2017-08-16
+ - API CHANGE: Rename dr_* types to drwav_*.
+ - Add support for custom implementations of malloc(), realloc(), etc.
+ - Add support for Microsoft ADPCM.
+ - Add support for IMA ADPCM (DVI, format code 0x11).
+ - Optimizations to drwav_read_s16().
+ - Bug fixes.
+
+v0.5g - 2017-07-16
+ - Change underlying type for booleans to unsigned.
+
+v0.5f - 2017-04-04
+ - Fix a minor bug with drwav_open_and_read_s16() and family.
+
+v0.5e - 2016-12-29
+ - Added support for reading samples as signed 16-bit integers. Use the _s16() family of APIs for this.
+ - Minor fixes to documentation.
+
+v0.5d - 2016-12-28
+ - Use drwav_int* and drwav_uint* sized types to improve compiler support.
+
+v0.5c - 2016-11-11
+ - Properly handle JUNK chunks that come before the FMT chunk.
+
+v0.5b - 2016-10-23
+ - A minor change to drwav_bool8 and drwav_bool32 types.
+
+v0.5a - 2016-10-11
+ - Fixed a bug with drwav_open_and_read() and family due to incorrect argument ordering.
+ - Improve A-law and mu-law efficiency.
+
+v0.5 - 2016-09-29
+ - API CHANGE. Swap the order of "channels" and "sampleRate" parameters in drwav_open_and_read*(). Rationale for this is to
+ keep it consistent with dr_audio and dr_flac.
+
+v0.4b - 2016-09-18
+ - Fixed a typo in documentation.
+
+v0.4a - 2016-09-18
+ - Fixed a typo.
+ - Change date format to ISO 8601 (YYYY-MM-DD)
+
+v0.4 - 2016-07-13
+ - API CHANGE. Make onSeek consistent with dr_flac.
+ - API CHANGE. Rename drwav_seek() to drwav_seek_to_sample() for clarity and consistency with dr_flac.
+ - Added support for Sony Wave64.
+
+v0.3a - 2016-05-28
+ - API CHANGE. Return drwav_bool32 instead of int in onSeek callback.
+ - Fixed a memory leak.
+
+v0.3 - 2016-05-22
+ - Lots of API changes for consistency.
+
+v0.2a - 2016-05-16
+ - Fixed Linux/GCC build.
+
+v0.2 - 2016-05-11
+ - Added support for reading data as signed 32-bit PCM for consistency with dr_flac.
+
+v0.1a - 2016-05-07
+ - Fixed a bug in drwav_open_file() where the file handle would not be closed if the loader failed to initialize.
+
+v0.1 - 2016-05-04
+ - Initial versioned release.
+*/
+
+/*
+This software is available as a choice of the following licenses. Choose
+whichever you prefer.
+
+===============================================================================
+ALTERNATIVE 1 - Public Domain (www.unlicense.org)
+===============================================================================
+This is free and unencumbered software released into the public domain.
+
+Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
+software, either in source code form or as a compiled binary, for any purpose,
+commercial or non-commercial, and by any means.
+
+In jurisdictions that recognize copyright laws, the author or authors of this
+software dedicate any and all copyright interest in the software to the public
+domain. We make this dedication for the benefit of the public at large and to
+the detriment of our heirs and successors. We intend this dedication to be an
+overt act of relinquishment in perpetuity of all present and future rights to
+this software under copyright law.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+For more information, please refer to
+
+===============================================================================
+ALTERNATIVE 2 - MIT No Attribution
+===============================================================================
+Copyright 2023 David Reid
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
diff --git a/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/glad.h b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/glad.h
new file mode 100644
index 0000000..5bb79d4
--- /dev/null
+++ b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/glad.h
@@ -0,0 +1,8682 @@
+/**
+ * Loader generated by glad 2.0.0-beta on Sun Sep 18 18:12:12 2022
+ *
+ * Generator: C/C++
+ * Specification: gl
+ * Extensions: 116
+ *
+ * APIs:
+ * - gl:core=4.3
+ *
+ * Options:
+ * - ALIAS = False
+ * - DEBUG = False
+ * - HEADER_ONLY = True
+ * - LOADER = False
+ * - MX = False
+ * - MX_GLOBAL = False
+ * - ON_DEMAND = False
+ *
+ * Commandline:
+ * --api='gl:core=4.3' --extensions='GL_ARB_ES2_compatibility,GL_ARB_ES3_1_compatibility,GL_ARB_ES3_2_compatibility,GL_ARB_ES3_compatibility,GL_ARB_blend_func_extended,GL_ARB_buffer_storage,GL_ARB_clear_buffer_object,GL_ARB_clear_texture,GL_ARB_color_buffer_float,GL_ARB_compatibility,GL_ARB_compressed_texture_pixel_storage,GL_ARB_compute_shader,GL_ARB_compute_variable_group_size,GL_ARB_copy_buffer,GL_ARB_copy_image,GL_ARB_debug_output,GL_ARB_depth_buffer_float,GL_ARB_depth_clamp,GL_ARB_depth_texture,GL_ARB_direct_state_access,GL_ARB_draw_buffers,GL_ARB_draw_buffers_blend,GL_ARB_draw_elements_base_vertex,GL_ARB_draw_indirect,GL_ARB_draw_instanced,GL_ARB_enhanced_layouts,GL_ARB_explicit_attrib_location,GL_ARB_explicit_uniform_location,GL_ARB_fragment_coord_conventions,GL_ARB_fragment_layer_viewport,GL_ARB_fragment_program,GL_ARB_fragment_program_shadow,GL_ARB_fragment_shader,GL_ARB_fragment_shader_interlock,GL_ARB_framebuffer_no_attachments,GL_ARB_framebuffer_object,GL_ARB_framebuffer_sRGB,GL_ARB_geometry_shader4,GL_ARB_get_program_binary,GL_ARB_get_texture_sub_image,GL_ARB_gl_spirv,GL_ARB_gpu_shader5,GL_ARB_gpu_shader_fp64,GL_ARB_gpu_shader_int64,GL_ARB_half_float_pixel,GL_ARB_half_float_vertex,GL_ARB_instanced_arrays,GL_ARB_internalformat_query,GL_ARB_internalformat_query2,GL_ARB_map_buffer_range,GL_ARB_multi_bind,GL_ARB_multi_draw_indirect,GL_ARB_multisample,GL_ARB_multitexture,GL_ARB_occlusion_query,GL_ARB_occlusion_query2,GL_ARB_pipeline_statistics_query,GL_ARB_query_buffer_object,GL_ARB_sample_locations,GL_ARB_sample_shading,GL_ARB_seamless_cube_map,GL_ARB_seamless_cubemap_per_texture,GL_ARB_shader_atomic_counter_ops,GL_ARB_shader_atomic_counters,GL_ARB_shader_bit_encoding,GL_ARB_shader_clock,GL_ARB_shader_image_load_store,GL_ARB_shader_image_size,GL_ARB_shader_objects,GL_ARB_shader_storage_buffer_object,GL_ARB_shader_texture_lod,GL_ARB_shading_language_100,GL_ARB_shading_language_420pack,GL_ARB_shading_language_include,GL_ARB_shading_language_packing,GL_ARB_spirv_extensions,GL_ARB_tessellation_shader,GL_ARB_texture_border_clamp,GL_ARB_texture_buffer_object_rgb32,GL_ARB_texture_compression,GL_ARB_texture_cube_map,GL_ARB_texture_cube_map_array,GL_ARB_texture_env_add,GL_ARB_texture_filter_anisotropic,GL_ARB_texture_filter_minmax,GL_ARB_texture_float,GL_ARB_texture_mirror_clamp_to_edge,GL_ARB_texture_mirrored_repeat,GL_ARB_texture_multisample,GL_ARB_texture_non_power_of_two,GL_ARB_texture_rg,GL_ARB_texture_storage,GL_ARB_texture_swizzle,GL_ARB_texture_view,GL_ARB_timer_query,GL_ARB_transpose_matrix,GL_ARB_uniform_buffer_object,GL_ARB_vertex_array_bgra,GL_ARB_vertex_array_object,GL_ARB_vertex_attrib_binding,GL_ARB_vertex_buffer_object,GL_ARB_vertex_program,GL_ARB_vertex_shader,GL_EXT_draw_instanced,GL_EXT_fog_coord,GL_EXT_framebuffer_blit,GL_EXT_framebuffer_multisample,GL_EXT_framebuffer_object,GL_EXT_framebuffer_sRGB,GL_EXT_texture_compression_s3tc,GL_EXT_texture_filter_anisotropic,GL_EXT_texture_mirror_clamp,GL_KHR_texture_compression_astc_hdr,GL_KHR_texture_compression_astc_ldr,GL_OES_compressed_paletted_texture,GL_OES_fixed_point' c --header-only
+ *
+ * Online:
+ * http://glad.sh/#api=gl%3Acore%3D4.3&generator=c&options=HEADER_ONLY
+ *
+ */
+
+#ifndef GLAD_GL_H_
+#define GLAD_GL_H_
+
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wreserved-id-macro"
+#endif
+#ifdef __gl_h_
+ #error OpenGL (gl.h) header already included (API: gl), remove previous include!
+#endif
+#define __gl_h_ 1
+#ifdef __gl3_h_
+ #error OpenGL (gl3.h) header already included (API: gl), remove previous include!
+#endif
+#define __gl3_h_ 1
+#ifdef __glext_h_
+ #error OpenGL (glext.h) header already included (API: gl), remove previous include!
+#endif
+#define __glext_h_ 1
+#ifdef __gl3ext_h_
+ #error OpenGL (gl3ext.h) header already included (API: gl), remove previous include!
+#endif
+#define __gl3ext_h_ 1
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
+#define GLAD_GL
+#define GLAD_OPTION_GL_HEADER_ONLY
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef GLAD_PLATFORM_H_
+#define GLAD_PLATFORM_H_
+
+#ifndef GLAD_PLATFORM_WIN32
+ #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) || defined(__MINGW32__)
+ #define GLAD_PLATFORM_WIN32 1
+ #else
+ #define GLAD_PLATFORM_WIN32 0
+ #endif
+#endif
+
+#ifndef GLAD_PLATFORM_APPLE
+ #ifdef __APPLE__
+ #define GLAD_PLATFORM_APPLE 1
+ #else
+ #define GLAD_PLATFORM_APPLE 0
+ #endif
+#endif
+
+#ifndef GLAD_PLATFORM_EMSCRIPTEN
+ #ifdef __EMSCRIPTEN__
+ #define GLAD_PLATFORM_EMSCRIPTEN 1
+ #else
+ #define GLAD_PLATFORM_EMSCRIPTEN 0
+ #endif
+#endif
+
+#ifndef GLAD_PLATFORM_UWP
+ #if defined(_MSC_VER) && !defined(GLAD_INTERNAL_HAVE_WINAPIFAMILY)
+ #ifdef __has_include
+ #if __has_include()
+ #define GLAD_INTERNAL_HAVE_WINAPIFAMILY 1
+ #endif
+ #elif _MSC_VER >= 1700 && !_USING_V110_SDK71_
+ #define GLAD_INTERNAL_HAVE_WINAPIFAMILY 1
+ #endif
+ #endif
+
+ #ifdef GLAD_INTERNAL_HAVE_WINAPIFAMILY
+ #include
+ #if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
+ #define GLAD_PLATFORM_UWP 1
+ #endif
+ #endif
+
+ #ifndef GLAD_PLATFORM_UWP
+ #define GLAD_PLATFORM_UWP 0
+ #endif
+#endif
+
+#ifdef __GNUC__
+ #define GLAD_GNUC_EXTENSION __extension__
+#else
+ #define GLAD_GNUC_EXTENSION
+#endif
+
+#ifndef GLAD_API_CALL
+ #if defined(GLAD_API_CALL_EXPORT)
+ #if GLAD_PLATFORM_WIN32 || defined(__CYGWIN__)
+ #if defined(GLAD_API_CALL_EXPORT_BUILD)
+ #if defined(__GNUC__)
+ #define GLAD_API_CALL __attribute__ ((dllexport)) extern
+ #else
+ #define GLAD_API_CALL __declspec(dllexport) extern
+ #endif
+ #else
+ #if defined(__GNUC__)
+ #define GLAD_API_CALL __attribute__ ((dllimport)) extern
+ #else
+ #define GLAD_API_CALL __declspec(dllimport) extern
+ #endif
+ #endif
+ #elif defined(__GNUC__) && defined(GLAD_API_CALL_EXPORT_BUILD)
+ #define GLAD_API_CALL __attribute__ ((visibility ("default"))) extern
+ #else
+ #define GLAD_API_CALL extern
+ #endif
+ #else
+ #define GLAD_API_CALL extern
+ #endif
+#endif
+
+#ifdef APIENTRY
+ #define GLAD_API_PTR APIENTRY
+#elif GLAD_PLATFORM_WIN32
+ #define GLAD_API_PTR __stdcall
+#else
+ #define GLAD_API_PTR
+#endif
+
+#ifndef GLAPI
+#define GLAPI GLAD_API_CALL
+#endif
+
+#ifndef GLAPIENTRY
+#define GLAPIENTRY GLAD_API_PTR
+#endif
+
+#define GLAD_MAKE_VERSION(major, minor) (major * 10000 + minor)
+#define GLAD_VERSION_MAJOR(version) (version / 10000)
+#define GLAD_VERSION_MINOR(version) (version % 10000)
+
+#define GLAD_GENERATOR_VERSION "2.0.0-beta"
+
+typedef void (*GLADapiproc)(void);
+
+typedef GLADapiproc (*GLADloadfunc)(const char *name);
+typedef GLADapiproc (*GLADuserptrloadfunc)(void *userptr, const char *name);
+
+typedef void (*GLADprecallback)(const char *name, GLADapiproc apiproc, int len_args, ...);
+typedef void (*GLADpostcallback)(void *ret, const char *name, GLADapiproc apiproc, int len_args, ...);
+
+#endif /* GLAD_PLATFORM_H_ */
+
+#define GL_ACTIVE_ATOMIC_COUNTER_BUFFERS 0x92D9
+#define GL_ACTIVE_ATTRIBUTES 0x8B89
+#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
+#define GL_ACTIVE_PROGRAM 0x8259
+#define GL_ACTIVE_RESOURCES 0x92F5
+#define GL_ACTIVE_SUBROUTINES 0x8DE5
+#define GL_ACTIVE_SUBROUTINE_MAX_LENGTH 0x8E48
+#define GL_ACTIVE_SUBROUTINE_UNIFORMS 0x8DE6
+#define GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS 0x8E47
+#define GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH 0x8E49
+#define GL_ACTIVE_TEXTURE 0x84E0
+#define GL_ACTIVE_TEXTURE_ARB 0x84E0
+#define GL_ACTIVE_UNIFORMS 0x8B86
+#define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36
+#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35
+#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87
+#define GL_ACTIVE_VARIABLES 0x9305
+#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E
+#define GL_ALL_BARRIER_BITS 0xFFFFFFFF
+#define GL_ALL_SHADER_BITS 0xFFFFFFFF
+#define GL_ALPHA 0x1906
+#define GL_ALPHA16F_ARB 0x881C
+#define GL_ALPHA32F_ARB 0x8816
+#define GL_ALREADY_SIGNALED 0x911A
+#define GL_ALWAYS 0x0207
+#define GL_AND 0x1501
+#define GL_AND_INVERTED 0x1504
+#define GL_AND_REVERSE 0x1502
+#define GL_ANY_SAMPLES_PASSED 0x8C2F
+#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE 0x8D6A
+#define GL_ARRAY_BUFFER 0x8892
+#define GL_ARRAY_BUFFER_ARB 0x8892
+#define GL_ARRAY_BUFFER_BINDING 0x8894
+#define GL_ARRAY_BUFFER_BINDING_ARB 0x8894
+#define GL_ARRAY_SIZE 0x92FB
+#define GL_ARRAY_STRIDE 0x92FE
+#define GL_ATOMIC_COUNTER_BARRIER_BIT 0x00001000
+#define GL_ATOMIC_COUNTER_BUFFER 0x92C0
+#define GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTERS 0x92C5
+#define GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTER_INDICES 0x92C6
+#define GL_ATOMIC_COUNTER_BUFFER_BINDING 0x92C1
+#define GL_ATOMIC_COUNTER_BUFFER_DATA_SIZE 0x92C4
+#define GL_ATOMIC_COUNTER_BUFFER_INDEX 0x9301
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_COMPUTE_SHADER 0x90ED
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_FRAGMENT_SHADER 0x92CB
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_GEOMETRY_SHADER 0x92CA
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_CONTROL_SHADER 0x92C8
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_EVALUATION_SHADER 0x92C9
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_VERTEX_SHADER 0x92C7
+#define GL_ATOMIC_COUNTER_BUFFER_SIZE 0x92C3
+#define GL_ATOMIC_COUNTER_BUFFER_START 0x92C2
+#define GL_ATTACHED_SHADERS 0x8B85
+#define GL_AUTO_GENERATE_MIPMAP 0x8295
+#define GL_BACK 0x0405
+#define GL_BACK_LEFT 0x0402
+#define GL_BACK_RIGHT 0x0403
+#define GL_BGR 0x80E0
+#define GL_BGRA 0x80E1
+#define GL_BGRA_INTEGER 0x8D9B
+#define GL_BGR_INTEGER 0x8D9A
+#define GL_BLEND 0x0BE2
+#define GL_BLEND_COLOR 0x8005
+#define GL_BLEND_DST 0x0BE0
+#define GL_BLEND_DST_ALPHA 0x80CA
+#define GL_BLEND_DST_RGB 0x80C8
+#define GL_BLEND_EQUATION 0x8009
+#define GL_BLEND_EQUATION_ALPHA 0x883D
+#define GL_BLEND_EQUATION_RGB 0x8009
+#define GL_BLEND_SRC 0x0BE1
+#define GL_BLEND_SRC_ALPHA 0x80CB
+#define GL_BLEND_SRC_RGB 0x80C9
+#define GL_BLOCK_INDEX 0x92FD
+#define GL_BLUE 0x1905
+#define GL_BLUE_INTEGER 0x8D96
+#define GL_BOOL 0x8B56
+#define GL_BOOL_ARB 0x8B56
+#define GL_BOOL_VEC2 0x8B57
+#define GL_BOOL_VEC2_ARB 0x8B57
+#define GL_BOOL_VEC3 0x8B58
+#define GL_BOOL_VEC3_ARB 0x8B58
+#define GL_BOOL_VEC4 0x8B59
+#define GL_BOOL_VEC4_ARB 0x8B59
+#define GL_BUFFER 0x82E0
+#define GL_BUFFER_ACCESS 0x88BB
+#define GL_BUFFER_ACCESS_ARB 0x88BB
+#define GL_BUFFER_ACCESS_FLAGS 0x911F
+#define GL_BUFFER_BINDING 0x9302
+#define GL_BUFFER_DATA_SIZE 0x9303
+#define GL_BUFFER_IMMUTABLE_STORAGE 0x821F
+#define GL_BUFFER_MAPPED 0x88BC
+#define GL_BUFFER_MAPPED_ARB 0x88BC
+#define GL_BUFFER_MAP_LENGTH 0x9120
+#define GL_BUFFER_MAP_OFFSET 0x9121
+#define GL_BUFFER_MAP_POINTER 0x88BD
+#define GL_BUFFER_MAP_POINTER_ARB 0x88BD
+#define GL_BUFFER_SIZE 0x8764
+#define GL_BUFFER_SIZE_ARB 0x8764
+#define GL_BUFFER_STORAGE_FLAGS 0x8220
+#define GL_BUFFER_UPDATE_BARRIER_BIT 0x00000200
+#define GL_BUFFER_USAGE 0x8765
+#define GL_BUFFER_USAGE_ARB 0x8765
+#define GL_BUFFER_VARIABLE 0x92E5
+#define GL_BYTE 0x1400
+#define GL_CAVEAT_SUPPORT 0x82B8
+#define GL_CCW 0x0901
+#define GL_CLAMP_FRAGMENT_COLOR_ARB 0x891B
+#define GL_CLAMP_READ_COLOR 0x891C
+#define GL_CLAMP_READ_COLOR_ARB 0x891C
+#define GL_CLAMP_TO_BORDER 0x812D
+#define GL_CLAMP_TO_BORDER_ARB 0x812D
+#define GL_CLAMP_TO_EDGE 0x812F
+#define GL_CLAMP_VERTEX_COLOR_ARB 0x891A
+#define GL_CLEAR 0x1500
+#define GL_CLEAR_BUFFER 0x82B4
+#define GL_CLEAR_TEXTURE 0x9365
+#define GL_CLIENT_ACTIVE_TEXTURE_ARB 0x84E1
+#define GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT 0x00004000
+#define GL_CLIENT_STORAGE_BIT 0x0200
+#define GL_CLIPPING_INPUT_PRIMITIVES 0x82F6
+#define GL_CLIPPING_INPUT_PRIMITIVES_ARB 0x82F6
+#define GL_CLIPPING_OUTPUT_PRIMITIVES 0x82F7
+#define GL_CLIPPING_OUTPUT_PRIMITIVES_ARB 0x82F7
+#define GL_CLIP_DISTANCE0 0x3000
+#define GL_CLIP_DISTANCE1 0x3001
+#define GL_CLIP_DISTANCE2 0x3002
+#define GL_CLIP_DISTANCE3 0x3003
+#define GL_CLIP_DISTANCE4 0x3004
+#define GL_CLIP_DISTANCE5 0x3005
+#define GL_CLIP_DISTANCE6 0x3006
+#define GL_CLIP_DISTANCE7 0x3007
+#define GL_COLOR 0x1800
+#define GL_COLOR_ARRAY_BUFFER_BINDING_ARB 0x8898
+#define GL_COLOR_ATTACHMENT0 0x8CE0
+#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0
+#define GL_COLOR_ATTACHMENT1 0x8CE1
+#define GL_COLOR_ATTACHMENT10 0x8CEA
+#define GL_COLOR_ATTACHMENT10_EXT 0x8CEA
+#define GL_COLOR_ATTACHMENT11 0x8CEB
+#define GL_COLOR_ATTACHMENT11_EXT 0x8CEB
+#define GL_COLOR_ATTACHMENT12 0x8CEC
+#define GL_COLOR_ATTACHMENT12_EXT 0x8CEC
+#define GL_COLOR_ATTACHMENT13 0x8CED
+#define GL_COLOR_ATTACHMENT13_EXT 0x8CED
+#define GL_COLOR_ATTACHMENT14 0x8CEE
+#define GL_COLOR_ATTACHMENT14_EXT 0x8CEE
+#define GL_COLOR_ATTACHMENT15 0x8CEF
+#define GL_COLOR_ATTACHMENT15_EXT 0x8CEF
+#define GL_COLOR_ATTACHMENT16 0x8CF0
+#define GL_COLOR_ATTACHMENT17 0x8CF1
+#define GL_COLOR_ATTACHMENT18 0x8CF2
+#define GL_COLOR_ATTACHMENT19 0x8CF3
+#define GL_COLOR_ATTACHMENT1_EXT 0x8CE1
+#define GL_COLOR_ATTACHMENT2 0x8CE2
+#define GL_COLOR_ATTACHMENT20 0x8CF4
+#define GL_COLOR_ATTACHMENT21 0x8CF5
+#define GL_COLOR_ATTACHMENT22 0x8CF6
+#define GL_COLOR_ATTACHMENT23 0x8CF7
+#define GL_COLOR_ATTACHMENT24 0x8CF8
+#define GL_COLOR_ATTACHMENT25 0x8CF9
+#define GL_COLOR_ATTACHMENT26 0x8CFA
+#define GL_COLOR_ATTACHMENT27 0x8CFB
+#define GL_COLOR_ATTACHMENT28 0x8CFC
+#define GL_COLOR_ATTACHMENT29 0x8CFD
+#define GL_COLOR_ATTACHMENT2_EXT 0x8CE2
+#define GL_COLOR_ATTACHMENT3 0x8CE3
+#define GL_COLOR_ATTACHMENT30 0x8CFE
+#define GL_COLOR_ATTACHMENT31 0x8CFF
+#define GL_COLOR_ATTACHMENT3_EXT 0x8CE3
+#define GL_COLOR_ATTACHMENT4 0x8CE4
+#define GL_COLOR_ATTACHMENT4_EXT 0x8CE4
+#define GL_COLOR_ATTACHMENT5 0x8CE5
+#define GL_COLOR_ATTACHMENT5_EXT 0x8CE5
+#define GL_COLOR_ATTACHMENT6 0x8CE6
+#define GL_COLOR_ATTACHMENT6_EXT 0x8CE6
+#define GL_COLOR_ATTACHMENT7 0x8CE7
+#define GL_COLOR_ATTACHMENT7_EXT 0x8CE7
+#define GL_COLOR_ATTACHMENT8 0x8CE8
+#define GL_COLOR_ATTACHMENT8_EXT 0x8CE8
+#define GL_COLOR_ATTACHMENT9 0x8CE9
+#define GL_COLOR_ATTACHMENT9_EXT 0x8CE9
+#define GL_COLOR_BUFFER_BIT 0x00004000
+#define GL_COLOR_CLEAR_VALUE 0x0C22
+#define GL_COLOR_COMPONENTS 0x8283
+#define GL_COLOR_ENCODING 0x8296
+#define GL_COLOR_LOGIC_OP 0x0BF2
+#define GL_COLOR_RENDERABLE 0x8286
+#define GL_COLOR_SUM_ARB 0x8458
+#define GL_COLOR_WRITEMASK 0x0C23
+#define GL_COMMAND_BARRIER_BIT 0x00000040
+#define GL_COMPARE_REF_TO_TEXTURE 0x884E
+#define GL_COMPATIBLE_SUBROUTINES 0x8E4B
+#define GL_COMPILE_STATUS 0x8B81
+#define GL_COMPRESSED_ALPHA_ARB 0x84E9
+#define GL_COMPRESSED_INTENSITY_ARB 0x84EC
+#define GL_COMPRESSED_LUMINANCE_ALPHA_ARB 0x84EB
+#define GL_COMPRESSED_LUMINANCE_ARB 0x84EA
+#define GL_COMPRESSED_R11_EAC 0x9270
+#define GL_COMPRESSED_RED 0x8225
+#define GL_COMPRESSED_RED_RGTC1 0x8DBB
+#define GL_COMPRESSED_RG 0x8226
+#define GL_COMPRESSED_RG11_EAC 0x9272
+#define GL_COMPRESSED_RGB 0x84ED
+#define GL_COMPRESSED_RGB8_ETC2 0x9274
+#define GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276
+#define GL_COMPRESSED_RGBA 0x84EE
+#define GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278
+#define GL_COMPRESSED_RGBA_ARB 0x84EE
+#define GL_COMPRESSED_RGBA_ASTC_10x10_KHR 0x93BB
+#define GL_COMPRESSED_RGBA_ASTC_10x5_KHR 0x93B8
+#define GL_COMPRESSED_RGBA_ASTC_10x6_KHR 0x93B9
+#define GL_COMPRESSED_RGBA_ASTC_10x8_KHR 0x93BA
+#define GL_COMPRESSED_RGBA_ASTC_12x10_KHR 0x93BC
+#define GL_COMPRESSED_RGBA_ASTC_12x12_KHR 0x93BD
+#define GL_COMPRESSED_RGBA_ASTC_4x4_KHR 0x93B0
+#define GL_COMPRESSED_RGBA_ASTC_5x4_KHR 0x93B1
+#define GL_COMPRESSED_RGBA_ASTC_5x5_KHR 0x93B2
+#define GL_COMPRESSED_RGBA_ASTC_6x5_KHR 0x93B3
+#define GL_COMPRESSED_RGBA_ASTC_6x6_KHR 0x93B4
+#define GL_COMPRESSED_RGBA_ASTC_8x5_KHR 0x93B5
+#define GL_COMPRESSED_RGBA_ASTC_8x6_KHR 0x93B6
+#define GL_COMPRESSED_RGBA_ASTC_8x8_KHR 0x93B7
+#define GL_COMPRESSED_RGBA_BPTC_UNORM 0x8E8C
+#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
+#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
+#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
+#define GL_COMPRESSED_RGB_ARB 0x84ED
+#define GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT 0x8E8E
+#define GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT 0x8E8F
+#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
+#define GL_COMPRESSED_RG_RGTC2 0x8DBD
+#define GL_COMPRESSED_SIGNED_R11_EAC 0x9271
+#define GL_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC
+#define GL_COMPRESSED_SIGNED_RG11_EAC 0x9273
+#define GL_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE
+#define GL_COMPRESSED_SRGB 0x8C48
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR 0x93DB
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR 0x93D8
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR 0x93D9
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR 0x93DA
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR 0x93DC
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR 0x93DD
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR 0x93D0
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR 0x93D1
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR 0x93D2
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR 0x93D3
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR 0x93D4
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR 0x93D5
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR 0x93D6
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR 0x93D7
+#define GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279
+#define GL_COMPRESSED_SRGB8_ETC2 0x9275
+#define GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277
+#define GL_COMPRESSED_SRGB_ALPHA 0x8C49
+#define GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM 0x8E8D
+#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3
+#define GL_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A3
+#define GL_COMPUTE_SHADER 0x91B9
+#define GL_COMPUTE_SHADER_BIT 0x00000020
+#define GL_COMPUTE_SHADER_INVOCATIONS 0x82F5
+#define GL_COMPUTE_SHADER_INVOCATIONS_ARB 0x82F5
+#define GL_COMPUTE_SUBROUTINE 0x92ED
+#define GL_COMPUTE_SUBROUTINE_UNIFORM 0x92F3
+#define GL_COMPUTE_TEXTURE 0x82A0
+#define GL_COMPUTE_WORK_GROUP_SIZE 0x8267
+#define GL_CONDITION_SATISFIED 0x911C
+#define GL_CONSTANT_ALPHA 0x8003
+#define GL_CONSTANT_COLOR 0x8001
+#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002
+#define GL_CONTEXT_CORE_PROFILE_BIT 0x00000001
+#define GL_CONTEXT_FLAGS 0x821E
+#define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002
+#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x00000001
+#define GL_CONTEXT_PROFILE_MASK 0x9126
+#define GL_COPY 0x1503
+#define GL_COPY_INVERTED 0x150C
+#define GL_COPY_READ_BUFFER 0x8F36
+#define GL_COPY_READ_BUFFER_BINDING 0x8F36
+#define GL_COPY_WRITE_BUFFER 0x8F37
+#define GL_COPY_WRITE_BUFFER_BINDING 0x8F37
+#define GL_CULL_FACE 0x0B44
+#define GL_CULL_FACE_MODE 0x0B45
+#define GL_CURRENT_FOG_COORDINATE_EXT 0x8453
+#define GL_CURRENT_MATRIX_ARB 0x8641
+#define GL_CURRENT_MATRIX_STACK_DEPTH_ARB 0x8640
+#define GL_CURRENT_PROGRAM 0x8B8D
+#define GL_CURRENT_QUERY 0x8865
+#define GL_CURRENT_QUERY_ARB 0x8865
+#define GL_CURRENT_VERTEX_ATTRIB 0x8626
+#define GL_CURRENT_VERTEX_ATTRIB_ARB 0x8626
+#define GL_CW 0x0900
+#define GL_DEBUG_CALLBACK_FUNCTION 0x8244
+#define GL_DEBUG_CALLBACK_FUNCTION_ARB 0x8244
+#define GL_DEBUG_CALLBACK_USER_PARAM 0x8245
+#define GL_DEBUG_CALLBACK_USER_PARAM_ARB 0x8245
+#define GL_DEBUG_GROUP_STACK_DEPTH 0x826D
+#define GL_DEBUG_LOGGED_MESSAGES 0x9145
+#define GL_DEBUG_LOGGED_MESSAGES_ARB 0x9145
+#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH 0x8243
+#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_ARB 0x8243
+#define GL_DEBUG_OUTPUT 0x92E0
+#define GL_DEBUG_OUTPUT_SYNCHRONOUS 0x8242
+#define GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB 0x8242
+#define GL_DEBUG_SEVERITY_HIGH 0x9146
+#define GL_DEBUG_SEVERITY_HIGH_ARB 0x9146
+#define GL_DEBUG_SEVERITY_LOW 0x9148
+#define GL_DEBUG_SEVERITY_LOW_ARB 0x9148
+#define GL_DEBUG_SEVERITY_MEDIUM 0x9147
+#define GL_DEBUG_SEVERITY_MEDIUM_ARB 0x9147
+#define GL_DEBUG_SEVERITY_NOTIFICATION 0x826B
+#define GL_DEBUG_SOURCE_API 0x8246
+#define GL_DEBUG_SOURCE_API_ARB 0x8246
+#define GL_DEBUG_SOURCE_APPLICATION 0x824A
+#define GL_DEBUG_SOURCE_APPLICATION_ARB 0x824A
+#define GL_DEBUG_SOURCE_OTHER 0x824B
+#define GL_DEBUG_SOURCE_OTHER_ARB 0x824B
+#define GL_DEBUG_SOURCE_SHADER_COMPILER 0x8248
+#define GL_DEBUG_SOURCE_SHADER_COMPILER_ARB 0x8248
+#define GL_DEBUG_SOURCE_THIRD_PARTY 0x8249
+#define GL_DEBUG_SOURCE_THIRD_PARTY_ARB 0x8249
+#define GL_DEBUG_SOURCE_WINDOW_SYSTEM 0x8247
+#define GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB 0x8247
+#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR 0x824D
+#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB 0x824D
+#define GL_DEBUG_TYPE_ERROR 0x824C
+#define GL_DEBUG_TYPE_ERROR_ARB 0x824C
+#define GL_DEBUG_TYPE_MARKER 0x8268
+#define GL_DEBUG_TYPE_OTHER 0x8251
+#define GL_DEBUG_TYPE_OTHER_ARB 0x8251
+#define GL_DEBUG_TYPE_PERFORMANCE 0x8250
+#define GL_DEBUG_TYPE_PERFORMANCE_ARB 0x8250
+#define GL_DEBUG_TYPE_POP_GROUP 0x826A
+#define GL_DEBUG_TYPE_PORTABILITY 0x824F
+#define GL_DEBUG_TYPE_PORTABILITY_ARB 0x824F
+#define GL_DEBUG_TYPE_PUSH_GROUP 0x8269
+#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR 0x824E
+#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB 0x824E
+#define GL_DECR 0x1E03
+#define GL_DECR_WRAP 0x8508
+#define GL_DELETE_STATUS 0x8B80
+#define GL_DEPTH 0x1801
+#define GL_DEPTH24_STENCIL8 0x88F0
+#define GL_DEPTH32F_STENCIL8 0x8CAD
+#define GL_DEPTH_ATTACHMENT 0x8D00
+#define GL_DEPTH_ATTACHMENT_EXT 0x8D00
+#define GL_DEPTH_BUFFER_BIT 0x00000100
+#define GL_DEPTH_CLAMP 0x864F
+#define GL_DEPTH_CLEAR_VALUE 0x0B73
+#define GL_DEPTH_COMPONENT 0x1902
+#define GL_DEPTH_COMPONENT16 0x81A5
+#define GL_DEPTH_COMPONENT16_ARB 0x81A5
+#define GL_DEPTH_COMPONENT24 0x81A6
+#define GL_DEPTH_COMPONENT24_ARB 0x81A6
+#define GL_DEPTH_COMPONENT32 0x81A7
+#define GL_DEPTH_COMPONENT32F 0x8CAC
+#define GL_DEPTH_COMPONENT32_ARB 0x81A7
+#define GL_DEPTH_COMPONENTS 0x8284
+#define GL_DEPTH_FUNC 0x0B74
+#define GL_DEPTH_RANGE 0x0B70
+#define GL_DEPTH_RENDERABLE 0x8287
+#define GL_DEPTH_STENCIL 0x84F9
+#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A
+#define GL_DEPTH_STENCIL_TEXTURE_MODE 0x90EA
+#define GL_DEPTH_TEST 0x0B71
+#define GL_DEPTH_TEXTURE_MODE_ARB 0x884B
+#define GL_DEPTH_WRITEMASK 0x0B72
+#define GL_DISPATCH_INDIRECT_BUFFER 0x90EE
+#define GL_DISPATCH_INDIRECT_BUFFER_BINDING 0x90EF
+#define GL_DITHER 0x0BD0
+#define GL_DONT_CARE 0x1100
+#define GL_DOUBLE 0x140A
+#define GL_DOUBLEBUFFER 0x0C32
+#define GL_DOUBLE_MAT2 0x8F46
+#define GL_DOUBLE_MAT2x3 0x8F49
+#define GL_DOUBLE_MAT2x4 0x8F4A
+#define GL_DOUBLE_MAT3 0x8F47
+#define GL_DOUBLE_MAT3x2 0x8F4B
+#define GL_DOUBLE_MAT3x4 0x8F4C
+#define GL_DOUBLE_MAT4 0x8F48
+#define GL_DOUBLE_MAT4x2 0x8F4D
+#define GL_DOUBLE_MAT4x3 0x8F4E
+#define GL_DOUBLE_VEC2 0x8FFC
+#define GL_DOUBLE_VEC3 0x8FFD
+#define GL_DOUBLE_VEC4 0x8FFE
+#define GL_DRAW_BUFFER 0x0C01
+#define GL_DRAW_BUFFER0 0x8825
+#define GL_DRAW_BUFFER0_ARB 0x8825
+#define GL_DRAW_BUFFER1 0x8826
+#define GL_DRAW_BUFFER10 0x882F
+#define GL_DRAW_BUFFER10_ARB 0x882F
+#define GL_DRAW_BUFFER11 0x8830
+#define GL_DRAW_BUFFER11_ARB 0x8830
+#define GL_DRAW_BUFFER12 0x8831
+#define GL_DRAW_BUFFER12_ARB 0x8831
+#define GL_DRAW_BUFFER13 0x8832
+#define GL_DRAW_BUFFER13_ARB 0x8832
+#define GL_DRAW_BUFFER14 0x8833
+#define GL_DRAW_BUFFER14_ARB 0x8833
+#define GL_DRAW_BUFFER15 0x8834
+#define GL_DRAW_BUFFER15_ARB 0x8834
+#define GL_DRAW_BUFFER1_ARB 0x8826
+#define GL_DRAW_BUFFER2 0x8827
+#define GL_DRAW_BUFFER2_ARB 0x8827
+#define GL_DRAW_BUFFER3 0x8828
+#define GL_DRAW_BUFFER3_ARB 0x8828
+#define GL_DRAW_BUFFER4 0x8829
+#define GL_DRAW_BUFFER4_ARB 0x8829
+#define GL_DRAW_BUFFER5 0x882A
+#define GL_DRAW_BUFFER5_ARB 0x882A
+#define GL_DRAW_BUFFER6 0x882B
+#define GL_DRAW_BUFFER6_ARB 0x882B
+#define GL_DRAW_BUFFER7 0x882C
+#define GL_DRAW_BUFFER7_ARB 0x882C
+#define GL_DRAW_BUFFER8 0x882D
+#define GL_DRAW_BUFFER8_ARB 0x882D
+#define GL_DRAW_BUFFER9 0x882E
+#define GL_DRAW_BUFFER9_ARB 0x882E
+#define GL_DRAW_FRAMEBUFFER 0x8CA9
+#define GL_DRAW_FRAMEBUFFER_BINDING 0x8CA6
+#define GL_DRAW_FRAMEBUFFER_BINDING_EXT 0x8CA6
+#define GL_DRAW_FRAMEBUFFER_EXT 0x8CA9
+#define GL_DRAW_INDIRECT_BUFFER 0x8F3F
+#define GL_DRAW_INDIRECT_BUFFER_BINDING 0x8F43
+#define GL_DST_ALPHA 0x0304
+#define GL_DST_COLOR 0x0306
+#define GL_DYNAMIC_COPY 0x88EA
+#define GL_DYNAMIC_COPY_ARB 0x88EA
+#define GL_DYNAMIC_DRAW 0x88E8
+#define GL_DYNAMIC_DRAW_ARB 0x88E8
+#define GL_DYNAMIC_READ 0x88E9
+#define GL_DYNAMIC_READ_ARB 0x88E9
+#define GL_DYNAMIC_STORAGE_BIT 0x0100
+#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB 0x889B
+#define GL_ELEMENT_ARRAY_BARRIER_BIT 0x00000002
+#define GL_ELEMENT_ARRAY_BUFFER 0x8893
+#define GL_ELEMENT_ARRAY_BUFFER_ARB 0x8893
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB 0x8895
+#define GL_EQUAL 0x0202
+#define GL_EQUIV 0x1509
+#define GL_EXTENSIONS 0x1F03
+#define GL_FALSE 0
+#define GL_FASTEST 0x1101
+#define GL_FILL 0x1B02
+#define GL_FILTER 0x829A
+#define GL_FIRST_VERTEX_CONVENTION 0x8E4D
+#define GL_FIXED 0x140C
+#define GL_FIXED_OES 0x140C
+#define GL_FIXED_ONLY 0x891D
+#define GL_FIXED_ONLY_ARB 0x891D
+#define GL_FLOAT 0x1406
+#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD
+#define GL_FLOAT_MAT2 0x8B5A
+#define GL_FLOAT_MAT2_ARB 0x8B5A
+#define GL_FLOAT_MAT2x3 0x8B65
+#define GL_FLOAT_MAT2x4 0x8B66
+#define GL_FLOAT_MAT3 0x8B5B
+#define GL_FLOAT_MAT3_ARB 0x8B5B
+#define GL_FLOAT_MAT3x2 0x8B67
+#define GL_FLOAT_MAT3x4 0x8B68
+#define GL_FLOAT_MAT4 0x8B5C
+#define GL_FLOAT_MAT4_ARB 0x8B5C
+#define GL_FLOAT_MAT4x2 0x8B69
+#define GL_FLOAT_MAT4x3 0x8B6A
+#define GL_FLOAT_VEC2 0x8B50
+#define GL_FLOAT_VEC2_ARB 0x8B50
+#define GL_FLOAT_VEC3 0x8B51
+#define GL_FLOAT_VEC3_ARB 0x8B51
+#define GL_FLOAT_VEC4 0x8B52
+#define GL_FLOAT_VEC4_ARB 0x8B52
+#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB 0x889D
+#define GL_FOG_COORDINATE_ARRAY_EXT 0x8457
+#define GL_FOG_COORDINATE_ARRAY_POINTER_EXT 0x8456
+#define GL_FOG_COORDINATE_ARRAY_STRIDE_EXT 0x8455
+#define GL_FOG_COORDINATE_ARRAY_TYPE_EXT 0x8454
+#define GL_FOG_COORDINATE_EXT 0x8451
+#define GL_FOG_COORDINATE_SOURCE_EXT 0x8450
+#define GL_FRACTIONAL_EVEN 0x8E7C
+#define GL_FRACTIONAL_ODD 0x8E7B
+#define GL_FRAGMENT_DEPTH_EXT 0x8452
+#define GL_FRAGMENT_INTERPOLATION_OFFSET_BITS 0x8E5D
+#define GL_FRAGMENT_PROGRAM_ARB 0x8804
+#define GL_FRAGMENT_SHADER 0x8B30
+#define GL_FRAGMENT_SHADER_ARB 0x8B30
+#define GL_FRAGMENT_SHADER_BIT 0x00000002
+#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B
+#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB 0x8B8B
+#define GL_FRAGMENT_SHADER_INVOCATIONS 0x82F4
+#define GL_FRAGMENT_SHADER_INVOCATIONS_ARB 0x82F4
+#define GL_FRAGMENT_SUBROUTINE 0x92EC
+#define GL_FRAGMENT_SUBROUTINE_UNIFORM 0x92F2
+#define GL_FRAGMENT_TEXTURE 0x829F
+#define GL_FRAMEBUFFER 0x8D40
+#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215
+#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214
+#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210
+#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211
+#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216
+#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213
+#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED 0x8DA7
+#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_ARB 0x8DA7
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT 0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT 0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212
+#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT 0x8CD4
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT 0x8CD3
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT 0x8CD2
+#define GL_FRAMEBUFFER_BARRIER_BIT 0x00000400
+#define GL_FRAMEBUFFER_BINDING 0x8CA6
+#define GL_FRAMEBUFFER_BINDING_EXT 0x8CA6
+#define GL_FRAMEBUFFER_BLEND 0x828B
+#define GL_FRAMEBUFFER_COMPLETE 0x8CD5
+#define GL_FRAMEBUFFER_COMPLETE_EXT 0x8CD5
+#define GL_FRAMEBUFFER_DEFAULT 0x8218
+#define GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS 0x9314
+#define GL_FRAMEBUFFER_DEFAULT_HEIGHT 0x9311
+#define GL_FRAMEBUFFER_DEFAULT_LAYERS 0x9312
+#define GL_FRAMEBUFFER_DEFAULT_SAMPLES 0x9313
+#define GL_FRAMEBUFFER_DEFAULT_WIDTH 0x9310
+#define GL_FRAMEBUFFER_EXT 0x8D40
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT 0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT 0x8CD9
+#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER 0x8CDB
+#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT 0x8CDB
+#define GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT 0x8CDA
+#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_ARB 0x8DA9
+#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS 0x8DA8
+#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_ARB 0x8DA8
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT 0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x8D56
+#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC
+#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT 0x8CDC
+#define GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_ARB 0x9342
+#define GL_FRAMEBUFFER_RENDERABLE 0x8289
+#define GL_FRAMEBUFFER_RENDERABLE_LAYERED 0x828A
+#define GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_ARB 0x9343
+#define GL_FRAMEBUFFER_SRGB 0x8DB9
+#define GL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x8DBA
+#define GL_FRAMEBUFFER_SRGB_EXT 0x8DB9
+#define GL_FRAMEBUFFER_UNDEFINED 0x8219
+#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD
+#define GL_FRAMEBUFFER_UNSUPPORTED_EXT 0x8CDD
+#define GL_FRONT 0x0404
+#define GL_FRONT_AND_BACK 0x0408
+#define GL_FRONT_FACE 0x0B46
+#define GL_FRONT_LEFT 0x0400
+#define GL_FRONT_RIGHT 0x0401
+#define GL_FULL_SUPPORT 0x82B7
+#define GL_FUNC_ADD 0x8006
+#define GL_FUNC_REVERSE_SUBTRACT 0x800B
+#define GL_FUNC_SUBTRACT 0x800A
+#define GL_GEOMETRY_INPUT_TYPE 0x8917
+#define GL_GEOMETRY_INPUT_TYPE_ARB 0x8DDB
+#define GL_GEOMETRY_OUTPUT_TYPE 0x8918
+#define GL_GEOMETRY_OUTPUT_TYPE_ARB 0x8DDC
+#define GL_GEOMETRY_SHADER 0x8DD9
+#define GL_GEOMETRY_SHADER_ARB 0x8DD9
+#define GL_GEOMETRY_SHADER_BIT 0x00000004
+#define GL_GEOMETRY_SHADER_INVOCATIONS 0x887F
+#define GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED 0x82F3
+#define GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED_ARB 0x82F3
+#define GL_GEOMETRY_SUBROUTINE 0x92EB
+#define GL_GEOMETRY_SUBROUTINE_UNIFORM 0x92F1
+#define GL_GEOMETRY_TEXTURE 0x829E
+#define GL_GEOMETRY_VERTICES_OUT 0x8916
+#define GL_GEOMETRY_VERTICES_OUT_ARB 0x8DDA
+#define GL_GEQUAL 0x0206
+#define GL_GET_TEXTURE_IMAGE_FORMAT 0x8291
+#define GL_GET_TEXTURE_IMAGE_TYPE 0x8292
+#define GL_GREATER 0x0204
+#define GL_GREEN 0x1904
+#define GL_GREEN_INTEGER 0x8D95
+#define GL_HALF_FLOAT 0x140B
+#define GL_HALF_FLOAT_ARB 0x140B
+#define GL_HIGH_FLOAT 0x8DF2
+#define GL_HIGH_INT 0x8DF5
+#define GL_IMAGE_1D 0x904C
+#define GL_IMAGE_1D_ARRAY 0x9052
+#define GL_IMAGE_2D 0x904D
+#define GL_IMAGE_2D_ARRAY 0x9053
+#define GL_IMAGE_2D_MULTISAMPLE 0x9055
+#define GL_IMAGE_2D_MULTISAMPLE_ARRAY 0x9056
+#define GL_IMAGE_2D_RECT 0x904F
+#define GL_IMAGE_3D 0x904E
+#define GL_IMAGE_BINDING_ACCESS 0x8F3E
+#define GL_IMAGE_BINDING_FORMAT 0x906E
+#define GL_IMAGE_BINDING_LAYER 0x8F3D
+#define GL_IMAGE_BINDING_LAYERED 0x8F3C
+#define GL_IMAGE_BINDING_LEVEL 0x8F3B
+#define GL_IMAGE_BINDING_NAME 0x8F3A
+#define GL_IMAGE_BUFFER 0x9051
+#define GL_IMAGE_CLASS_10_10_10_2 0x82C3
+#define GL_IMAGE_CLASS_11_11_10 0x82C2
+#define GL_IMAGE_CLASS_1_X_16 0x82BE
+#define GL_IMAGE_CLASS_1_X_32 0x82BB
+#define GL_IMAGE_CLASS_1_X_8 0x82C1
+#define GL_IMAGE_CLASS_2_X_16 0x82BD
+#define GL_IMAGE_CLASS_2_X_32 0x82BA
+#define GL_IMAGE_CLASS_2_X_8 0x82C0
+#define GL_IMAGE_CLASS_4_X_16 0x82BC
+#define GL_IMAGE_CLASS_4_X_32 0x82B9
+#define GL_IMAGE_CLASS_4_X_8 0x82BF
+#define GL_IMAGE_COMPATIBILITY_CLASS 0x82A8
+#define GL_IMAGE_CUBE 0x9050
+#define GL_IMAGE_CUBE_MAP_ARRAY 0x9054
+#define GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS 0x90C9
+#define GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE 0x90C8
+#define GL_IMAGE_FORMAT_COMPATIBILITY_TYPE 0x90C7
+#define GL_IMAGE_PIXEL_FORMAT 0x82A9
+#define GL_IMAGE_PIXEL_TYPE 0x82AA
+#define GL_IMAGE_TEXEL_SIZE 0x82A7
+#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B
+#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A
+#define GL_INCR 0x1E02
+#define GL_INCR_WRAP 0x8507
+#define GL_INDEX_ARRAY_BUFFER_BINDING_ARB 0x8899
+#define GL_INFO_LOG_LENGTH 0x8B84
+#define GL_INT 0x1404
+#define GL_INT64_ARB 0x140E
+#define GL_INT64_VEC2_ARB 0x8FE9
+#define GL_INT64_VEC3_ARB 0x8FEA
+#define GL_INT64_VEC4_ARB 0x8FEB
+#define GL_INTENSITY16F_ARB 0x881D
+#define GL_INTENSITY32F_ARB 0x8817
+#define GL_INTERLEAVED_ATTRIBS 0x8C8C
+#define GL_INTERNALFORMAT_ALPHA_SIZE 0x8274
+#define GL_INTERNALFORMAT_ALPHA_TYPE 0x827B
+#define GL_INTERNALFORMAT_BLUE_SIZE 0x8273
+#define GL_INTERNALFORMAT_BLUE_TYPE 0x827A
+#define GL_INTERNALFORMAT_DEPTH_SIZE 0x8275
+#define GL_INTERNALFORMAT_DEPTH_TYPE 0x827C
+#define GL_INTERNALFORMAT_GREEN_SIZE 0x8272
+#define GL_INTERNALFORMAT_GREEN_TYPE 0x8279
+#define GL_INTERNALFORMAT_PREFERRED 0x8270
+#define GL_INTERNALFORMAT_RED_SIZE 0x8271
+#define GL_INTERNALFORMAT_RED_TYPE 0x8278
+#define GL_INTERNALFORMAT_SHARED_SIZE 0x8277
+#define GL_INTERNALFORMAT_STENCIL_SIZE 0x8276
+#define GL_INTERNALFORMAT_STENCIL_TYPE 0x827D
+#define GL_INTERNALFORMAT_SUPPORTED 0x826F
+#define GL_INT_2_10_10_10_REV 0x8D9F
+#define GL_INT_IMAGE_1D 0x9057
+#define GL_INT_IMAGE_1D_ARRAY 0x905D
+#define GL_INT_IMAGE_2D 0x9058
+#define GL_INT_IMAGE_2D_ARRAY 0x905E
+#define GL_INT_IMAGE_2D_MULTISAMPLE 0x9060
+#define GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x9061
+#define GL_INT_IMAGE_2D_RECT 0x905A
+#define GL_INT_IMAGE_3D 0x9059
+#define GL_INT_IMAGE_BUFFER 0x905C
+#define GL_INT_IMAGE_CUBE 0x905B
+#define GL_INT_IMAGE_CUBE_MAP_ARRAY 0x905F
+#define GL_INT_SAMPLER_1D 0x8DC9
+#define GL_INT_SAMPLER_1D_ARRAY 0x8DCE
+#define GL_INT_SAMPLER_2D 0x8DCA
+#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF
+#define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109
+#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C
+#define GL_INT_SAMPLER_2D_RECT 0x8DCD
+#define GL_INT_SAMPLER_3D 0x8DCB
+#define GL_INT_SAMPLER_BUFFER 0x8DD0
+#define GL_INT_SAMPLER_CUBE 0x8DCC
+#define GL_INT_SAMPLER_CUBE_MAP_ARRAY 0x900E
+#define GL_INT_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900E
+#define GL_INT_VEC2 0x8B53
+#define GL_INT_VEC2_ARB 0x8B53
+#define GL_INT_VEC3 0x8B54
+#define GL_INT_VEC3_ARB 0x8B54
+#define GL_INT_VEC4 0x8B55
+#define GL_INT_VEC4_ARB 0x8B55
+#define GL_INVALID_ENUM 0x0500
+#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506
+#define GL_INVALID_FRAMEBUFFER_OPERATION_EXT 0x0506
+#define GL_INVALID_INDEX 0xFFFFFFFF
+#define GL_INVALID_OPERATION 0x0502
+#define GL_INVALID_VALUE 0x0501
+#define GL_INVERT 0x150A
+#define GL_ISOLINES 0x8E7A
+#define GL_IS_PER_PATCH 0x92E7
+#define GL_IS_ROW_MAJOR 0x9300
+#define GL_KEEP 0x1E00
+#define GL_LAST_VERTEX_CONVENTION 0x8E4E
+#define GL_LAYER_PROVOKING_VERTEX 0x825E
+#define GL_LEFT 0x0406
+#define GL_LEQUAL 0x0203
+#define GL_LESS 0x0201
+#define GL_LINE 0x1B01
+#define GL_LINEAR 0x2601
+#define GL_LINEAR_MIPMAP_LINEAR 0x2703
+#define GL_LINEAR_MIPMAP_NEAREST 0x2701
+#define GL_LINES 0x0001
+#define GL_LINES_ADJACENCY 0x000A
+#define GL_LINES_ADJACENCY_ARB 0x000A
+#define GL_LINE_LOOP 0x0002
+#define GL_LINE_SMOOTH 0x0B20
+#define GL_LINE_SMOOTH_HINT 0x0C52
+#define GL_LINE_STRIP 0x0003
+#define GL_LINE_STRIP_ADJACENCY 0x000B
+#define GL_LINE_STRIP_ADJACENCY_ARB 0x000B
+#define GL_LINE_WIDTH 0x0B21
+#define GL_LINE_WIDTH_GRANULARITY 0x0B23
+#define GL_LINE_WIDTH_RANGE 0x0B22
+#define GL_LINK_STATUS 0x8B82
+#define GL_LOCATION 0x930E
+#define GL_LOCATION_COMPONENT 0x934A
+#define GL_LOCATION_INDEX 0x930F
+#define GL_LOGIC_OP_MODE 0x0BF0
+#define GL_LOWER_LEFT 0x8CA1
+#define GL_LOW_FLOAT 0x8DF0
+#define GL_LOW_INT 0x8DF3
+#define GL_LUMINANCE16F_ARB 0x881E
+#define GL_LUMINANCE32F_ARB 0x8818
+#define GL_LUMINANCE_ALPHA16F_ARB 0x881F
+#define GL_LUMINANCE_ALPHA32F_ARB 0x8819
+#define GL_MAJOR_VERSION 0x821B
+#define GL_MANUAL_GENERATE_MIPMAP 0x8294
+#define GL_MAP_COHERENT_BIT 0x0080
+#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010
+#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008
+#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004
+#define GL_MAP_PERSISTENT_BIT 0x0040
+#define GL_MAP_READ_BIT 0x0001
+#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020
+#define GL_MAP_WRITE_BIT 0x0002
+#define GL_MATRIX0_ARB 0x88C0
+#define GL_MATRIX10_ARB 0x88CA
+#define GL_MATRIX11_ARB 0x88CB
+#define GL_MATRIX12_ARB 0x88CC
+#define GL_MATRIX13_ARB 0x88CD
+#define GL_MATRIX14_ARB 0x88CE
+#define GL_MATRIX15_ARB 0x88CF
+#define GL_MATRIX16_ARB 0x88D0
+#define GL_MATRIX17_ARB 0x88D1
+#define GL_MATRIX18_ARB 0x88D2
+#define GL_MATRIX19_ARB 0x88D3
+#define GL_MATRIX1_ARB 0x88C1
+#define GL_MATRIX20_ARB 0x88D4
+#define GL_MATRIX21_ARB 0x88D5
+#define GL_MATRIX22_ARB 0x88D6
+#define GL_MATRIX23_ARB 0x88D7
+#define GL_MATRIX24_ARB 0x88D8
+#define GL_MATRIX25_ARB 0x88D9
+#define GL_MATRIX26_ARB 0x88DA
+#define GL_MATRIX27_ARB 0x88DB
+#define GL_MATRIX28_ARB 0x88DC
+#define GL_MATRIX29_ARB 0x88DD
+#define GL_MATRIX2_ARB 0x88C2
+#define GL_MATRIX30_ARB 0x88DE
+#define GL_MATRIX31_ARB 0x88DF
+#define GL_MATRIX3_ARB 0x88C3
+#define GL_MATRIX4_ARB 0x88C4
+#define GL_MATRIX5_ARB 0x88C5
+#define GL_MATRIX6_ARB 0x88C6
+#define GL_MATRIX7_ARB 0x88C7
+#define GL_MATRIX8_ARB 0x88C8
+#define GL_MATRIX9_ARB 0x88C9
+#define GL_MATRIX_STRIDE 0x92FF
+#define GL_MAX 0x8008
+#define GL_MAX_3D_TEXTURE_SIZE 0x8073
+#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF
+#define GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS 0x92DC
+#define GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE 0x92D8
+#define GL_MAX_CLIP_DISTANCES 0x0D32
+#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF
+#define GL_MAX_COLOR_ATTACHMENTS_EXT 0x8CDF
+#define GL_MAX_COLOR_TEXTURE_SAMPLES 0x910E
+#define GL_MAX_COMBINED_ATOMIC_COUNTERS 0x92D7
+#define GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS 0x92D1
+#define GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS 0x8266
+#define GL_MAX_COMBINED_DIMENSIONS 0x8282
+#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33
+#define GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS 0x8A32
+#define GL_MAX_COMBINED_IMAGE_UNIFORMS 0x90CF
+#define GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS 0x8F39
+#define GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES 0x8F39
+#define GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS 0x90DC
+#define GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E1E
+#define GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS 0x8E1F
+#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
+#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB 0x8B4D
+#define GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E
+#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31
+#define GL_MAX_COMPUTE_ATOMIC_COUNTERS 0x8265
+#define GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS 0x8264
+#define GL_MAX_COMPUTE_FIXED_GROUP_INVOCATIONS_ARB 0x90EB
+#define GL_MAX_COMPUTE_FIXED_GROUP_SIZE_ARB 0x91BF
+#define GL_MAX_COMPUTE_IMAGE_UNIFORMS 0x91BD
+#define GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS 0x90DB
+#define GL_MAX_COMPUTE_SHARED_MEMORY_SIZE 0x8262
+#define GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS 0x91BC
+#define GL_MAX_COMPUTE_UNIFORM_BLOCKS 0x91BB
+#define GL_MAX_COMPUTE_UNIFORM_COMPONENTS 0x8263
+#define GL_MAX_COMPUTE_VARIABLE_GROUP_INVOCATIONS_ARB 0x9344
+#define GL_MAX_COMPUTE_VARIABLE_GROUP_SIZE_ARB 0x9345
+#define GL_MAX_COMPUTE_WORK_GROUP_COUNT 0x91BE
+#define GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS 0x90EB
+#define GL_MAX_COMPUTE_WORK_GROUP_SIZE 0x91BF
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB 0x851C
+#define GL_MAX_DEBUG_GROUP_STACK_DEPTH 0x826C
+#define GL_MAX_DEBUG_LOGGED_MESSAGES 0x9144
+#define GL_MAX_DEBUG_LOGGED_MESSAGES_ARB 0x9144
+#define GL_MAX_DEBUG_MESSAGE_LENGTH 0x9143
+#define GL_MAX_DEBUG_MESSAGE_LENGTH_ARB 0x9143
+#define GL_MAX_DEPTH 0x8280
+#define GL_MAX_DEPTH_TEXTURE_SAMPLES 0x910F
+#define GL_MAX_DRAW_BUFFERS 0x8824
+#define GL_MAX_DRAW_BUFFERS_ARB 0x8824
+#define GL_MAX_DUAL_SOURCE_DRAW_BUFFERS 0x88FC
+#define GL_MAX_ELEMENTS_INDICES 0x80E9
+#define GL_MAX_ELEMENTS_VERTICES 0x80E8
+#define GL_MAX_ELEMENT_INDEX 0x8D6B
+#define GL_MAX_FRAGMENT_ATOMIC_COUNTERS 0x92D6
+#define GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS 0x92D0
+#define GL_MAX_FRAGMENT_IMAGE_UNIFORMS 0x90CE
+#define GL_MAX_FRAGMENT_INPUT_COMPONENTS 0x9125
+#define GL_MAX_FRAGMENT_INTERPOLATION_OFFSET 0x8E5C
+#define GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS 0x90DA
+#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D
+#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49
+#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB 0x8B49
+#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD
+#define GL_MAX_FRAMEBUFFER_HEIGHT 0x9316
+#define GL_MAX_FRAMEBUFFER_LAYERS 0x9317
+#define GL_MAX_FRAMEBUFFER_SAMPLES 0x9318
+#define GL_MAX_FRAMEBUFFER_WIDTH 0x9315
+#define GL_MAX_GEOMETRY_ATOMIC_COUNTERS 0x92D5
+#define GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS 0x92CF
+#define GL_MAX_GEOMETRY_IMAGE_UNIFORMS 0x90CD
+#define GL_MAX_GEOMETRY_INPUT_COMPONENTS 0x9123
+#define GL_MAX_GEOMETRY_OUTPUT_COMPONENTS 0x9124
+#define GL_MAX_GEOMETRY_OUTPUT_VERTICES 0x8DE0
+#define GL_MAX_GEOMETRY_OUTPUT_VERTICES_ARB 0x8DE0
+#define GL_MAX_GEOMETRY_SHADER_INVOCATIONS 0x8E5A
+#define GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS 0x90D7
+#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS 0x8C29
+#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_ARB 0x8C29
+#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS 0x8DE1
+#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_ARB 0x8DE1
+#define GL_MAX_GEOMETRY_UNIFORM_BLOCKS 0x8A2C
+#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS 0x8DDF
+#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_ARB 0x8DDF
+#define GL_MAX_GEOMETRY_VARYING_COMPONENTS_ARB 0x8DDD
+#define GL_MAX_HEIGHT 0x827F
+#define GL_MAX_IMAGE_SAMPLES 0x906D
+#define GL_MAX_IMAGE_UNITS 0x8F38
+#define GL_MAX_INTEGER_SAMPLES 0x9110
+#define GL_MAX_LABEL_LENGTH 0x82E8
+#define GL_MAX_LAYERS 0x8281
+#define GL_MAX_NAME_LENGTH 0x92F6
+#define GL_MAX_NUM_ACTIVE_VARIABLES 0x92F7
+#define GL_MAX_NUM_COMPATIBLE_SUBROUTINES 0x92F8
+#define GL_MAX_PATCH_VERTICES 0x8E7D
+#define GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B1
+#define GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB 0x880B
+#define GL_MAX_PROGRAM_ATTRIBS_ARB 0x88AD
+#define GL_MAX_PROGRAM_ENV_PARAMETERS_ARB 0x88B5
+#define GL_MAX_PROGRAM_INSTRUCTIONS_ARB 0x88A1
+#define GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB 0x88B4
+#define GL_MAX_PROGRAM_MATRICES_ARB 0x862F
+#define GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB 0x862E
+#define GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B3
+#define GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x880E
+#define GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AF
+#define GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A3
+#define GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AB
+#define GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A7
+#define GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x8810
+#define GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x880F
+#define GL_MAX_PROGRAM_PARAMETERS_ARB 0x88A9
+#define GL_MAX_PROGRAM_TEMPORARIES_ARB 0x88A5
+#define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905
+#define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5F
+#define GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB 0x880D
+#define GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB 0x880C
+#define GL_MAX_RECTANGLE_TEXTURE_SIZE 0x84F8
+#define GL_MAX_RENDERBUFFER_SIZE 0x84E8
+#define GL_MAX_RENDERBUFFER_SIZE_EXT 0x84E8
+#define GL_MAX_SAMPLES 0x8D57
+#define GL_MAX_SAMPLES_EXT 0x8D57
+#define GL_MAX_SAMPLE_MASK_WORDS 0x8E59
+#define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111
+#define GL_MAX_SHADER_STORAGE_BLOCK_SIZE 0x90DE
+#define GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS 0x90DD
+#define GL_MAX_SUBROUTINES 0x8DE7
+#define GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS 0x8DE8
+#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS 0x92D3
+#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS 0x92CD
+#define GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS 0x90CB
+#define GL_MAX_TESS_CONTROL_INPUT_COMPONENTS 0x886C
+#define GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS 0x8E83
+#define GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS 0x90D8
+#define GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS 0x8E81
+#define GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS 0x8E85
+#define GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS 0x8E89
+#define GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E7F
+#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS 0x92D4
+#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS 0x92CE
+#define GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS 0x90CC
+#define GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS 0x886D
+#define GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS 0x8E86
+#define GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS 0x90D9
+#define GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS 0x8E82
+#define GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS 0x8E8A
+#define GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS 0x8E80
+#define GL_MAX_TESS_GEN_LEVEL 0x8E7E
+#define GL_MAX_TESS_PATCH_COMPONENTS 0x8E84
+#define GL_MAX_TEXTURE_BUFFER_SIZE 0x8C2B
+#define GL_MAX_TEXTURE_COORDS_ARB 0x8871
+#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872
+#define GL_MAX_TEXTURE_IMAGE_UNITS_ARB 0x8872
+#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD
+#define GL_MAX_TEXTURE_MAX_ANISOTROPY 0x84FF
+#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
+#define GL_MAX_TEXTURE_SIZE 0x0D33
+#define GL_MAX_TEXTURE_UNITS_ARB 0x84E2
+#define GL_MAX_TRANSFORM_FEEDBACK_BUFFERS 0x8E70
+#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80
+#define GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30
+#define GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F
+#define GL_MAX_UNIFORM_LOCATIONS 0x826E
+#define GL_MAX_VARYING_COMPONENTS 0x8B4B
+#define GL_MAX_VARYING_FLOATS 0x8B4B
+#define GL_MAX_VARYING_FLOATS_ARB 0x8B4B
+#define GL_MAX_VARYING_VECTORS 0x8DFC
+#define GL_MAX_VERTEX_ATOMIC_COUNTERS 0x92D2
+#define GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS 0x92CC
+#define GL_MAX_VERTEX_ATTRIBS 0x8869
+#define GL_MAX_VERTEX_ATTRIBS_ARB 0x8869
+#define GL_MAX_VERTEX_ATTRIB_BINDINGS 0x82DA
+#define GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D9
+#define GL_MAX_VERTEX_IMAGE_UNIFORMS 0x90CA
+#define GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122
+#define GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS 0x90D6
+#define GL_MAX_VERTEX_STREAMS 0x8E71
+#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C
+#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB 0x8B4C
+#define GL_MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B
+#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A
+#define GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB 0x8B4A
+#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB
+#define GL_MAX_VERTEX_VARYING_COMPONENTS_ARB 0x8DDE
+#define GL_MAX_VIEWPORTS 0x825B
+#define GL_MAX_VIEWPORT_DIMS 0x0D3A
+#define GL_MAX_WIDTH 0x827E
+#define GL_MEDIUM_FLOAT 0x8DF1
+#define GL_MEDIUM_INT 0x8DF4
+#define GL_MIN 0x8007
+#define GL_MINOR_VERSION 0x821C
+#define GL_MIN_FRAGMENT_INTERPOLATION_OFFSET 0x8E5B
+#define GL_MIN_MAP_BUFFER_ALIGNMENT 0x90BC
+#define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904
+#define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5E
+#define GL_MIN_SAMPLE_SHADING_VALUE 0x8C37
+#define GL_MIN_SAMPLE_SHADING_VALUE_ARB 0x8C37
+#define GL_MIPMAP 0x8293
+#define GL_MIRRORED_REPEAT 0x8370
+#define GL_MIRRORED_REPEAT_ARB 0x8370
+#define GL_MIRROR_CLAMP_EXT 0x8742
+#define GL_MIRROR_CLAMP_TO_BORDER_EXT 0x8912
+#define GL_MIRROR_CLAMP_TO_EDGE 0x8743
+#define GL_MIRROR_CLAMP_TO_EDGE_EXT 0x8743
+#define GL_MULTISAMPLE 0x809D
+#define GL_MULTISAMPLE_ARB 0x809D
+#define GL_MULTISAMPLE_BIT_ARB 0x20000000
+#define GL_MULTISAMPLE_LINE_WIDTH_GRANULARITY_ARB 0x9382
+#define GL_MULTISAMPLE_LINE_WIDTH_RANGE_ARB 0x9381
+#define GL_NAMED_STRING_LENGTH_ARB 0x8DE9
+#define GL_NAMED_STRING_TYPE_ARB 0x8DEA
+#define GL_NAME_LENGTH 0x92F9
+#define GL_NAND 0x150E
+#define GL_NEAREST 0x2600
+#define GL_NEAREST_MIPMAP_LINEAR 0x2702
+#define GL_NEAREST_MIPMAP_NEAREST 0x2700
+#define GL_NEVER 0x0200
+#define GL_NICEST 0x1102
+#define GL_NONE 0
+#define GL_NOOP 0x1505
+#define GL_NOR 0x1508
+#define GL_NORMAL_ARRAY_BUFFER_BINDING_ARB 0x8897
+#define GL_NORMAL_MAP_ARB 0x8511
+#define GL_NOTEQUAL 0x0205
+#define GL_NO_ERROR 0
+#define GL_NUM_ACTIVE_VARIABLES 0x9304
+#define GL_NUM_COMPATIBLE_SUBROUTINES 0x8E4A
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A2
+#define GL_NUM_EXTENSIONS 0x821D
+#define GL_NUM_PROGRAM_BINARY_FORMATS 0x87FE
+#define GL_NUM_SAMPLE_COUNTS 0x9380
+#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9
+#define GL_NUM_SHADING_LANGUAGE_VERSIONS 0x82E9
+#define GL_NUM_SPIR_V_EXTENSIONS 0x9554
+#define GL_OBJECT_ACTIVE_ATTRIBUTES_ARB 0x8B89
+#define GL_OBJECT_ACTIVE_ATTRIBUTE_MAX_LENGTH_ARB 0x8B8A
+#define GL_OBJECT_ACTIVE_UNIFORMS_ARB 0x8B86
+#define GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB 0x8B87
+#define GL_OBJECT_ATTACHED_OBJECTS_ARB 0x8B85
+#define GL_OBJECT_COMPILE_STATUS_ARB 0x8B81
+#define GL_OBJECT_DELETE_STATUS_ARB 0x8B80
+#define GL_OBJECT_INFO_LOG_LENGTH_ARB 0x8B84
+#define GL_OBJECT_LINK_STATUS_ARB 0x8B82
+#define GL_OBJECT_SHADER_SOURCE_LENGTH_ARB 0x8B88
+#define GL_OBJECT_SUBTYPE_ARB 0x8B4F
+#define GL_OBJECT_TYPE 0x9112
+#define GL_OBJECT_TYPE_ARB 0x8B4E
+#define GL_OBJECT_VALIDATE_STATUS_ARB 0x8B83
+#define GL_OFFSET 0x92FC
+#define GL_ONE 1
+#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004
+#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002
+#define GL_ONE_MINUS_DST_ALPHA 0x0305
+#define GL_ONE_MINUS_DST_COLOR 0x0307
+#define GL_ONE_MINUS_SRC1_ALPHA 0x88FB
+#define GL_ONE_MINUS_SRC1_COLOR 0x88FA
+#define GL_ONE_MINUS_SRC_ALPHA 0x0303
+#define GL_ONE_MINUS_SRC_COLOR 0x0301
+#define GL_OR 0x1507
+#define GL_OR_INVERTED 0x150D
+#define GL_OR_REVERSE 0x150B
+#define GL_OUT_OF_MEMORY 0x0505
+#define GL_PACK_ALIGNMENT 0x0D05
+#define GL_PACK_COMPRESSED_BLOCK_DEPTH 0x912D
+#define GL_PACK_COMPRESSED_BLOCK_HEIGHT 0x912C
+#define GL_PACK_COMPRESSED_BLOCK_SIZE 0x912E
+#define GL_PACK_COMPRESSED_BLOCK_WIDTH 0x912B
+#define GL_PACK_IMAGE_HEIGHT 0x806C
+#define GL_PACK_LSB_FIRST 0x0D01
+#define GL_PACK_ROW_LENGTH 0x0D02
+#define GL_PACK_SKIP_IMAGES 0x806B
+#define GL_PACK_SKIP_PIXELS 0x0D04
+#define GL_PACK_SKIP_ROWS 0x0D03
+#define GL_PACK_SWAP_BYTES 0x0D00
+#define GL_PALETTE4_R5_G6_B5_OES 0x8B92
+#define GL_PALETTE4_RGB5_A1_OES 0x8B94
+#define GL_PALETTE4_RGB8_OES 0x8B90
+#define GL_PALETTE4_RGBA4_OES 0x8B93
+#define GL_PALETTE4_RGBA8_OES 0x8B91
+#define GL_PALETTE8_R5_G6_B5_OES 0x8B97
+#define GL_PALETTE8_RGB5_A1_OES 0x8B99
+#define GL_PALETTE8_RGB8_OES 0x8B95
+#define GL_PALETTE8_RGBA4_OES 0x8B98
+#define GL_PALETTE8_RGBA8_OES 0x8B96
+#define GL_PATCHES 0x000E
+#define GL_PATCH_DEFAULT_INNER_LEVEL 0x8E73
+#define GL_PATCH_DEFAULT_OUTER_LEVEL 0x8E74
+#define GL_PATCH_VERTICES 0x8E72
+#define GL_PIXEL_BUFFER_BARRIER_BIT 0x00000080
+#define GL_PIXEL_PACK_BUFFER 0x88EB
+#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED
+#define GL_PIXEL_UNPACK_BUFFER 0x88EC
+#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF
+#define GL_POINT 0x1B00
+#define GL_POINTS 0x0000
+#define GL_POINT_FADE_THRESHOLD_SIZE 0x8128
+#define GL_POINT_SIZE 0x0B11
+#define GL_POINT_SIZE_GRANULARITY 0x0B13
+#define GL_POINT_SIZE_RANGE 0x0B12
+#define GL_POINT_SPRITE_COORD_ORIGIN 0x8CA0
+#define GL_POLYGON_MODE 0x0B40
+#define GL_POLYGON_OFFSET_FACTOR 0x8038
+#define GL_POLYGON_OFFSET_FILL 0x8037
+#define GL_POLYGON_OFFSET_LINE 0x2A02
+#define GL_POLYGON_OFFSET_POINT 0x2A01
+#define GL_POLYGON_OFFSET_UNITS 0x2A00
+#define GL_POLYGON_SMOOTH 0x0B41
+#define GL_POLYGON_SMOOTH_HINT 0x0C53
+#define GL_PRIMITIVES_GENERATED 0x8C87
+#define GL_PRIMITIVES_SUBMITTED 0x82EF
+#define GL_PRIMITIVES_SUBMITTED_ARB 0x82EF
+#define GL_PRIMITIVE_BOUNDING_BOX_ARB 0x92BE
+#define GL_PRIMITIVE_RESTART 0x8F9D
+#define GL_PRIMITIVE_RESTART_FIXED_INDEX 0x8D69
+#define GL_PRIMITIVE_RESTART_INDEX 0x8F9E
+#define GL_PROGRAM 0x82E2
+#define GL_PROGRAMMABLE_SAMPLE_LOCATION_ARB 0x9341
+#define GL_PROGRAMMABLE_SAMPLE_LOCATION_TABLE_SIZE_ARB 0x9340
+#define GL_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B0
+#define GL_PROGRAM_ALU_INSTRUCTIONS_ARB 0x8805
+#define GL_PROGRAM_ATTRIBS_ARB 0x88AC
+#define GL_PROGRAM_BINARY_FORMATS 0x87FF
+#define GL_PROGRAM_BINARY_LENGTH 0x8741
+#define GL_PROGRAM_BINARY_RETRIEVABLE_HINT 0x8257
+#define GL_PROGRAM_BINDING_ARB 0x8677
+#define GL_PROGRAM_ERROR_POSITION_ARB 0x864B
+#define GL_PROGRAM_ERROR_STRING_ARB 0x8874
+#define GL_PROGRAM_FORMAT_ARB 0x8876
+#define GL_PROGRAM_FORMAT_ASCII_ARB 0x8875
+#define GL_PROGRAM_INPUT 0x92E3
+#define GL_PROGRAM_INSTRUCTIONS_ARB 0x88A0
+#define GL_PROGRAM_LENGTH_ARB 0x8627
+#define GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B2
+#define GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x8808
+#define GL_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AE
+#define GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A2
+#define GL_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AA
+#define GL_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A6
+#define GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x880A
+#define GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x8809
+#define GL_PROGRAM_OBJECT_ARB 0x8B40
+#define GL_PROGRAM_OUTPUT 0x92E4
+#define GL_PROGRAM_PARAMETERS_ARB 0x88A8
+#define GL_PROGRAM_PIPELINE 0x82E4
+#define GL_PROGRAM_PIPELINE_BINDING 0x825A
+#define GL_PROGRAM_POINT_SIZE 0x8642
+#define GL_PROGRAM_POINT_SIZE_ARB 0x8642
+#define GL_PROGRAM_SEPARABLE 0x8258
+#define GL_PROGRAM_STRING_ARB 0x8628
+#define GL_PROGRAM_TEMPORARIES_ARB 0x88A4
+#define GL_PROGRAM_TEX_INDIRECTIONS_ARB 0x8807
+#define GL_PROGRAM_TEX_INSTRUCTIONS_ARB 0x8806
+#define GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB 0x88B6
+#define GL_PROVOKING_VERTEX 0x8E4F
+#define GL_PROXY_TEXTURE_1D 0x8063
+#define GL_PROXY_TEXTURE_1D_ARRAY 0x8C19
+#define GL_PROXY_TEXTURE_2D 0x8064
+#define GL_PROXY_TEXTURE_2D_ARRAY 0x8C1B
+#define GL_PROXY_TEXTURE_2D_MULTISAMPLE 0x9101
+#define GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9103
+#define GL_PROXY_TEXTURE_3D 0x8070
+#define GL_PROXY_TEXTURE_CUBE_MAP 0x851B
+#define GL_PROXY_TEXTURE_CUBE_MAP_ARB 0x851B
+#define GL_PROXY_TEXTURE_CUBE_MAP_ARRAY 0x900B
+#define GL_PROXY_TEXTURE_CUBE_MAP_ARRAY_ARB 0x900B
+#define GL_PROXY_TEXTURE_RECTANGLE 0x84F7
+#define GL_QUADS 0x0007
+#define GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION 0x8E4C
+#define GL_QUERY 0x82E3
+#define GL_QUERY_BUFFER 0x9192
+#define GL_QUERY_BUFFER_BARRIER_BIT 0x00008000
+#define GL_QUERY_BUFFER_BINDING 0x9193
+#define GL_QUERY_BY_REGION_NO_WAIT 0x8E16
+#define GL_QUERY_BY_REGION_WAIT 0x8E15
+#define GL_QUERY_COUNTER_BITS 0x8864
+#define GL_QUERY_COUNTER_BITS_ARB 0x8864
+#define GL_QUERY_NO_WAIT 0x8E14
+#define GL_QUERY_RESULT 0x8866
+#define GL_QUERY_RESULT_ARB 0x8866
+#define GL_QUERY_RESULT_AVAILABLE 0x8867
+#define GL_QUERY_RESULT_AVAILABLE_ARB 0x8867
+#define GL_QUERY_RESULT_NO_WAIT 0x9194
+#define GL_QUERY_TARGET 0x82EA
+#define GL_QUERY_WAIT 0x8E13
+#define GL_R11F_G11F_B10F 0x8C3A
+#define GL_R16 0x822A
+#define GL_R16F 0x822D
+#define GL_R16I 0x8233
+#define GL_R16UI 0x8234
+#define GL_R16_SNORM 0x8F98
+#define GL_R32F 0x822E
+#define GL_R32I 0x8235
+#define GL_R32UI 0x8236
+#define GL_R3_G3_B2 0x2A10
+#define GL_R8 0x8229
+#define GL_R8I 0x8231
+#define GL_R8UI 0x8232
+#define GL_R8_SNORM 0x8F94
+#define GL_RASTERIZER_DISCARD 0x8C89
+#define GL_READ_BUFFER 0x0C02
+#define GL_READ_FRAMEBUFFER 0x8CA8
+#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA
+#define GL_READ_FRAMEBUFFER_BINDING_EXT 0x8CAA
+#define GL_READ_FRAMEBUFFER_EXT 0x8CA8
+#define GL_READ_ONLY 0x88B8
+#define GL_READ_ONLY_ARB 0x88B8
+#define GL_READ_PIXELS 0x828C
+#define GL_READ_PIXELS_FORMAT 0x828D
+#define GL_READ_PIXELS_TYPE 0x828E
+#define GL_READ_WRITE 0x88BA
+#define GL_READ_WRITE_ARB 0x88BA
+#define GL_RED 0x1903
+#define GL_RED_INTEGER 0x8D94
+#define GL_REFERENCED_BY_COMPUTE_SHADER 0x930B
+#define GL_REFERENCED_BY_FRAGMENT_SHADER 0x930A
+#define GL_REFERENCED_BY_GEOMETRY_SHADER 0x9309
+#define GL_REFERENCED_BY_TESS_CONTROL_SHADER 0x9307
+#define GL_REFERENCED_BY_TESS_EVALUATION_SHADER 0x9308
+#define GL_REFERENCED_BY_VERTEX_SHADER 0x9306
+#define GL_REFLECTION_MAP_ARB 0x8512
+#define GL_RENDERBUFFER 0x8D41
+#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53
+#define GL_RENDERBUFFER_ALPHA_SIZE_EXT 0x8D53
+#define GL_RENDERBUFFER_BINDING 0x8CA7
+#define GL_RENDERBUFFER_BINDING_EXT 0x8CA7
+#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52
+#define GL_RENDERBUFFER_BLUE_SIZE_EXT 0x8D52
+#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54
+#define GL_RENDERBUFFER_DEPTH_SIZE_EXT 0x8D54
+#define GL_RENDERBUFFER_EXT 0x8D41
+#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51
+#define GL_RENDERBUFFER_GREEN_SIZE_EXT 0x8D51
+#define GL_RENDERBUFFER_HEIGHT 0x8D43
+#define GL_RENDERBUFFER_HEIGHT_EXT 0x8D43
+#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44
+#define GL_RENDERBUFFER_INTERNAL_FORMAT_EXT 0x8D44
+#define GL_RENDERBUFFER_RED_SIZE 0x8D50
+#define GL_RENDERBUFFER_RED_SIZE_EXT 0x8D50
+#define GL_RENDERBUFFER_SAMPLES 0x8CAB
+#define GL_RENDERBUFFER_SAMPLES_EXT 0x8CAB
+#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55
+#define GL_RENDERBUFFER_STENCIL_SIZE_EXT 0x8D55
+#define GL_RENDERBUFFER_WIDTH 0x8D42
+#define GL_RENDERBUFFER_WIDTH_EXT 0x8D42
+#define GL_RENDERER 0x1F01
+#define GL_REPEAT 0x2901
+#define GL_REPLACE 0x1E01
+#define GL_RG 0x8227
+#define GL_RG16 0x822C
+#define GL_RG16F 0x822F
+#define GL_RG16I 0x8239
+#define GL_RG16UI 0x823A
+#define GL_RG16_SNORM 0x8F99
+#define GL_RG32F 0x8230
+#define GL_RG32I 0x823B
+#define GL_RG32UI 0x823C
+#define GL_RG8 0x822B
+#define GL_RG8I 0x8237
+#define GL_RG8UI 0x8238
+#define GL_RG8_SNORM 0x8F95
+#define GL_RGB 0x1907
+#define GL_RGB10 0x8052
+#define GL_RGB10_A2 0x8059
+#define GL_RGB10_A2UI 0x906F
+#define GL_RGB12 0x8053
+#define GL_RGB16 0x8054
+#define GL_RGB16F 0x881B
+#define GL_RGB16F_ARB 0x881B
+#define GL_RGB16I 0x8D89
+#define GL_RGB16UI 0x8D77
+#define GL_RGB16_SNORM 0x8F9A
+#define GL_RGB32F 0x8815
+#define GL_RGB32F_ARB 0x8815
+#define GL_RGB32I 0x8D83
+#define GL_RGB32UI 0x8D71
+#define GL_RGB4 0x804F
+#define GL_RGB5 0x8050
+#define GL_RGB565 0x8D62
+#define GL_RGB5_A1 0x8057
+#define GL_RGB8 0x8051
+#define GL_RGB8I 0x8D8F
+#define GL_RGB8UI 0x8D7D
+#define GL_RGB8_SNORM 0x8F96
+#define GL_RGB9_E5 0x8C3D
+#define GL_RGBA 0x1908
+#define GL_RGBA12 0x805A
+#define GL_RGBA16 0x805B
+#define GL_RGBA16F 0x881A
+#define GL_RGBA16F_ARB 0x881A
+#define GL_RGBA16I 0x8D88
+#define GL_RGBA16UI 0x8D76
+#define GL_RGBA16_SNORM 0x8F9B
+#define GL_RGBA2 0x8055
+#define GL_RGBA32F 0x8814
+#define GL_RGBA32F_ARB 0x8814
+#define GL_RGBA32I 0x8D82
+#define GL_RGBA32UI 0x8D70
+#define GL_RGBA4 0x8056
+#define GL_RGBA8 0x8058
+#define GL_RGBA8I 0x8D8E
+#define GL_RGBA8UI 0x8D7C
+#define GL_RGBA8_SNORM 0x8F97
+#define GL_RGBA_FLOAT_MODE_ARB 0x8820
+#define GL_RGBA_INTEGER 0x8D99
+#define GL_RGB_INTEGER 0x8D98
+#define GL_RG_INTEGER 0x8228
+#define GL_RIGHT 0x0407
+#define GL_SAMPLER 0x82E6
+#define GL_SAMPLER_1D 0x8B5D
+#define GL_SAMPLER_1D_ARB 0x8B5D
+#define GL_SAMPLER_1D_ARRAY 0x8DC0
+#define GL_SAMPLER_1D_ARRAY_SHADOW 0x8DC3
+#define GL_SAMPLER_1D_SHADOW 0x8B61
+#define GL_SAMPLER_1D_SHADOW_ARB 0x8B61
+#define GL_SAMPLER_2D 0x8B5E
+#define GL_SAMPLER_2D_ARB 0x8B5E
+#define GL_SAMPLER_2D_ARRAY 0x8DC1
+#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4
+#define GL_SAMPLER_2D_MULTISAMPLE 0x9108
+#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910B
+#define GL_SAMPLER_2D_RECT 0x8B63
+#define GL_SAMPLER_2D_RECT_ARB 0x8B63
+#define GL_SAMPLER_2D_RECT_SHADOW 0x8B64
+#define GL_SAMPLER_2D_RECT_SHADOW_ARB 0x8B64
+#define GL_SAMPLER_2D_SHADOW 0x8B62
+#define GL_SAMPLER_2D_SHADOW_ARB 0x8B62
+#define GL_SAMPLER_3D 0x8B5F
+#define GL_SAMPLER_3D_ARB 0x8B5F
+#define GL_SAMPLER_BINDING 0x8919
+#define GL_SAMPLER_BUFFER 0x8DC2
+#define GL_SAMPLER_CUBE 0x8B60
+#define GL_SAMPLER_CUBE_ARB 0x8B60
+#define GL_SAMPLER_CUBE_MAP_ARRAY 0x900C
+#define GL_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900C
+#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW 0x900D
+#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_ARB 0x900D
+#define GL_SAMPLER_CUBE_SHADOW 0x8DC5
+#define GL_SAMPLES 0x80A9
+#define GL_SAMPLES_ARB 0x80A9
+#define GL_SAMPLES_PASSED 0x8914
+#define GL_SAMPLES_PASSED_ARB 0x8914
+#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E
+#define GL_SAMPLE_ALPHA_TO_COVERAGE_ARB 0x809E
+#define GL_SAMPLE_ALPHA_TO_ONE 0x809F
+#define GL_SAMPLE_ALPHA_TO_ONE_ARB 0x809F
+#define GL_SAMPLE_BUFFERS 0x80A8
+#define GL_SAMPLE_BUFFERS_ARB 0x80A8
+#define GL_SAMPLE_COVERAGE 0x80A0
+#define GL_SAMPLE_COVERAGE_ARB 0x80A0
+#define GL_SAMPLE_COVERAGE_INVERT 0x80AB
+#define GL_SAMPLE_COVERAGE_INVERT_ARB 0x80AB
+#define GL_SAMPLE_COVERAGE_VALUE 0x80AA
+#define GL_SAMPLE_COVERAGE_VALUE_ARB 0x80AA
+#define GL_SAMPLE_LOCATION_ARB 0x8E50
+#define GL_SAMPLE_LOCATION_PIXEL_GRID_HEIGHT_ARB 0x933F
+#define GL_SAMPLE_LOCATION_PIXEL_GRID_WIDTH_ARB 0x933E
+#define GL_SAMPLE_LOCATION_SUBPIXEL_BITS_ARB 0x933D
+#define GL_SAMPLE_MASK 0x8E51
+#define GL_SAMPLE_MASK_VALUE 0x8E52
+#define GL_SAMPLE_POSITION 0x8E50
+#define GL_SAMPLE_SHADING 0x8C36
+#define GL_SAMPLE_SHADING_ARB 0x8C36
+#define GL_SCISSOR_BOX 0x0C10
+#define GL_SCISSOR_TEST 0x0C11
+#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB 0x889C
+#define GL_SEPARATE_ATTRIBS 0x8C8D
+#define GL_SET 0x150F
+#define GL_SHADER 0x82E1
+#define GL_SHADER_BINARY_FORMATS 0x8DF8
+#define GL_SHADER_BINARY_FORMAT_SPIR_V 0x9551
+#define GL_SHADER_BINARY_FORMAT_SPIR_V_ARB 0x9551
+#define GL_SHADER_COMPILER 0x8DFA
+#define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT 0x00000020
+#define GL_SHADER_IMAGE_ATOMIC 0x82A6
+#define GL_SHADER_IMAGE_LOAD 0x82A4
+#define GL_SHADER_IMAGE_STORE 0x82A5
+#define GL_SHADER_INCLUDE_ARB 0x8DAE
+#define GL_SHADER_OBJECT_ARB 0x8B48
+#define GL_SHADER_SOURCE_LENGTH 0x8B88
+#define GL_SHADER_STORAGE_BARRIER_BIT 0x00002000
+#define GL_SHADER_STORAGE_BLOCK 0x92E6
+#define GL_SHADER_STORAGE_BUFFER 0x90D2
+#define GL_SHADER_STORAGE_BUFFER_BINDING 0x90D3
+#define GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT 0x90DF
+#define GL_SHADER_STORAGE_BUFFER_SIZE 0x90D5
+#define GL_SHADER_STORAGE_BUFFER_START 0x90D4
+#define GL_SHADER_TYPE 0x8B4F
+#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
+#define GL_SHADING_LANGUAGE_VERSION_ARB 0x8B8C
+#define GL_SHORT 0x1402
+#define GL_SIGNALED 0x9119
+#define GL_SIGNED_NORMALIZED 0x8F9C
+#define GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_TEST 0x82AC
+#define GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_WRITE 0x82AE
+#define GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_TEST 0x82AD
+#define GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_WRITE 0x82AF
+#define GL_SMOOTH_LINE_WIDTH_GRANULARITY 0x0B23
+#define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22
+#define GL_SMOOTH_POINT_SIZE_GRANULARITY 0x0B13
+#define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12
+#define GL_SOURCE1_ALPHA 0x8589
+#define GL_SPIR_V_BINARY 0x9552
+#define GL_SPIR_V_BINARY_ARB 0x9552
+#define GL_SPIR_V_EXTENSIONS 0x9553
+#define GL_SRC1_ALPHA 0x8589
+#define GL_SRC1_COLOR 0x88F9
+#define GL_SRC_ALPHA 0x0302
+#define GL_SRC_ALPHA_SATURATE 0x0308
+#define GL_SRC_COLOR 0x0300
+#define GL_SRGB 0x8C40
+#define GL_SRGB8 0x8C41
+#define GL_SRGB8_ALPHA8 0x8C43
+#define GL_SRGB_ALPHA 0x8C42
+#define GL_SRGB_DECODE_ARB 0x8299
+#define GL_SRGB_READ 0x8297
+#define GL_SRGB_WRITE 0x8298
+#define GL_STACK_OVERFLOW 0x0503
+#define GL_STACK_UNDERFLOW 0x0504
+#define GL_STATIC_COPY 0x88E6
+#define GL_STATIC_COPY_ARB 0x88E6
+#define GL_STATIC_DRAW 0x88E4
+#define GL_STATIC_DRAW_ARB 0x88E4
+#define GL_STATIC_READ 0x88E5
+#define GL_STATIC_READ_ARB 0x88E5
+#define GL_STENCIL 0x1802
+#define GL_STENCIL_ATTACHMENT 0x8D20
+#define GL_STENCIL_ATTACHMENT_EXT 0x8D20
+#define GL_STENCIL_BACK_FAIL 0x8801
+#define GL_STENCIL_BACK_FUNC 0x8800
+#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802
+#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803
+#define GL_STENCIL_BACK_REF 0x8CA3
+#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4
+#define GL_STENCIL_BACK_WRITEMASK 0x8CA5
+#define GL_STENCIL_BUFFER_BIT 0x00000400
+#define GL_STENCIL_CLEAR_VALUE 0x0B91
+#define GL_STENCIL_COMPONENTS 0x8285
+#define GL_STENCIL_FAIL 0x0B94
+#define GL_STENCIL_FUNC 0x0B92
+#define GL_STENCIL_INDEX 0x1901
+#define GL_STENCIL_INDEX1 0x8D46
+#define GL_STENCIL_INDEX16 0x8D49
+#define GL_STENCIL_INDEX16_EXT 0x8D49
+#define GL_STENCIL_INDEX1_EXT 0x8D46
+#define GL_STENCIL_INDEX4 0x8D47
+#define GL_STENCIL_INDEX4_EXT 0x8D47
+#define GL_STENCIL_INDEX8 0x8D48
+#define GL_STENCIL_INDEX8_EXT 0x8D48
+#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95
+#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96
+#define GL_STENCIL_REF 0x0B97
+#define GL_STENCIL_RENDERABLE 0x8288
+#define GL_STENCIL_TEST 0x0B90
+#define GL_STENCIL_VALUE_MASK 0x0B93
+#define GL_STENCIL_WRITEMASK 0x0B98
+#define GL_STEREO 0x0C33
+#define GL_STREAM_COPY 0x88E2
+#define GL_STREAM_COPY_ARB 0x88E2
+#define GL_STREAM_DRAW 0x88E0
+#define GL_STREAM_DRAW_ARB 0x88E0
+#define GL_STREAM_READ 0x88E1
+#define GL_STREAM_READ_ARB 0x88E1
+#define GL_SUBPIXEL_BITS 0x0D50
+#define GL_SYNC_CONDITION 0x9113
+#define GL_SYNC_FENCE 0x9116
+#define GL_SYNC_FLAGS 0x9115
+#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001
+#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117
+#define GL_SYNC_STATUS 0x9114
+#define GL_TESS_CONTROL_OUTPUT_VERTICES 0x8E75
+#define GL_TESS_CONTROL_SHADER 0x8E88
+#define GL_TESS_CONTROL_SHADER_BIT 0x00000008
+#define GL_TESS_CONTROL_SHADER_PATCHES 0x82F1
+#define GL_TESS_CONTROL_SHADER_PATCHES_ARB 0x82F1
+#define GL_TESS_CONTROL_SUBROUTINE 0x92E9
+#define GL_TESS_CONTROL_SUBROUTINE_UNIFORM 0x92EF
+#define GL_TESS_CONTROL_TEXTURE 0x829C
+#define GL_TESS_EVALUATION_SHADER 0x8E87
+#define GL_TESS_EVALUATION_SHADER_BIT 0x00000010
+#define GL_TESS_EVALUATION_SHADER_INVOCATIONS 0x82F2
+#define GL_TESS_EVALUATION_SHADER_INVOCATIONS_ARB 0x82F2
+#define GL_TESS_EVALUATION_SUBROUTINE 0x92EA
+#define GL_TESS_EVALUATION_SUBROUTINE_UNIFORM 0x92F0
+#define GL_TESS_EVALUATION_TEXTURE 0x829D
+#define GL_TESS_GEN_MODE 0x8E76
+#define GL_TESS_GEN_POINT_MODE 0x8E79
+#define GL_TESS_GEN_SPACING 0x8E77
+#define GL_TESS_GEN_VERTEX_ORDER 0x8E78
+#define GL_TEXTURE 0x1702
+#define GL_TEXTURE0 0x84C0
+#define GL_TEXTURE0_ARB 0x84C0
+#define GL_TEXTURE1 0x84C1
+#define GL_TEXTURE10 0x84CA
+#define GL_TEXTURE10_ARB 0x84CA
+#define GL_TEXTURE11 0x84CB
+#define GL_TEXTURE11_ARB 0x84CB
+#define GL_TEXTURE12 0x84CC
+#define GL_TEXTURE12_ARB 0x84CC
+#define GL_TEXTURE13 0x84CD
+#define GL_TEXTURE13_ARB 0x84CD
+#define GL_TEXTURE14 0x84CE
+#define GL_TEXTURE14_ARB 0x84CE
+#define GL_TEXTURE15 0x84CF
+#define GL_TEXTURE15_ARB 0x84CF
+#define GL_TEXTURE16 0x84D0
+#define GL_TEXTURE16_ARB 0x84D0
+#define GL_TEXTURE17 0x84D1
+#define GL_TEXTURE17_ARB 0x84D1
+#define GL_TEXTURE18 0x84D2
+#define GL_TEXTURE18_ARB 0x84D2
+#define GL_TEXTURE19 0x84D3
+#define GL_TEXTURE19_ARB 0x84D3
+#define GL_TEXTURE1_ARB 0x84C1
+#define GL_TEXTURE2 0x84C2
+#define GL_TEXTURE20 0x84D4
+#define GL_TEXTURE20_ARB 0x84D4
+#define GL_TEXTURE21 0x84D5
+#define GL_TEXTURE21_ARB 0x84D5
+#define GL_TEXTURE22 0x84D6
+#define GL_TEXTURE22_ARB 0x84D6
+#define GL_TEXTURE23 0x84D7
+#define GL_TEXTURE23_ARB 0x84D7
+#define GL_TEXTURE24 0x84D8
+#define GL_TEXTURE24_ARB 0x84D8
+#define GL_TEXTURE25 0x84D9
+#define GL_TEXTURE25_ARB 0x84D9
+#define GL_TEXTURE26 0x84DA
+#define GL_TEXTURE26_ARB 0x84DA
+#define GL_TEXTURE27 0x84DB
+#define GL_TEXTURE27_ARB 0x84DB
+#define GL_TEXTURE28 0x84DC
+#define GL_TEXTURE28_ARB 0x84DC
+#define GL_TEXTURE29 0x84DD
+#define GL_TEXTURE29_ARB 0x84DD
+#define GL_TEXTURE2_ARB 0x84C2
+#define GL_TEXTURE3 0x84C3
+#define GL_TEXTURE30 0x84DE
+#define GL_TEXTURE30_ARB 0x84DE
+#define GL_TEXTURE31 0x84DF
+#define GL_TEXTURE31_ARB 0x84DF
+#define GL_TEXTURE3_ARB 0x84C3
+#define GL_TEXTURE4 0x84C4
+#define GL_TEXTURE4_ARB 0x84C4
+#define GL_TEXTURE5 0x84C5
+#define GL_TEXTURE5_ARB 0x84C5
+#define GL_TEXTURE6 0x84C6
+#define GL_TEXTURE6_ARB 0x84C6
+#define GL_TEXTURE7 0x84C7
+#define GL_TEXTURE7_ARB 0x84C7
+#define GL_TEXTURE8 0x84C8
+#define GL_TEXTURE8_ARB 0x84C8
+#define GL_TEXTURE9 0x84C9
+#define GL_TEXTURE9_ARB 0x84C9
+#define GL_TEXTURE_1D 0x0DE0
+#define GL_TEXTURE_1D_ARRAY 0x8C18
+#define GL_TEXTURE_2D 0x0DE1
+#define GL_TEXTURE_2D_ARRAY 0x8C1A
+#define GL_TEXTURE_2D_MULTISAMPLE 0x9100
+#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102
+#define GL_TEXTURE_3D 0x806F
+#define GL_TEXTURE_ALPHA_SIZE 0x805F
+#define GL_TEXTURE_ALPHA_TYPE 0x8C13
+#define GL_TEXTURE_ALPHA_TYPE_ARB 0x8C13
+#define GL_TEXTURE_BASE_LEVEL 0x813C
+#define GL_TEXTURE_BINDING_1D 0x8068
+#define GL_TEXTURE_BINDING_1D_ARRAY 0x8C1C
+#define GL_TEXTURE_BINDING_2D 0x8069
+#define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D
+#define GL_TEXTURE_BINDING_2D_MULTISAMPLE 0x9104
+#define GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY 0x9105
+#define GL_TEXTURE_BINDING_3D 0x806A
+#define GL_TEXTURE_BINDING_BUFFER 0x8C2C
+#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514
+#define GL_TEXTURE_BINDING_CUBE_MAP_ARB 0x8514
+#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY 0x900A
+#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY_ARB 0x900A
+#define GL_TEXTURE_BINDING_RECTANGLE 0x84F6
+#define GL_TEXTURE_BLUE_SIZE 0x805E
+#define GL_TEXTURE_BLUE_TYPE 0x8C12
+#define GL_TEXTURE_BLUE_TYPE_ARB 0x8C12
+#define GL_TEXTURE_BORDER_COLOR 0x1004
+#define GL_TEXTURE_BUFFER 0x8C2A
+#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING 0x8C2D
+#define GL_TEXTURE_BUFFER_OFFSET 0x919D
+#define GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT 0x919F
+#define GL_TEXTURE_BUFFER_SIZE 0x919E
+#define GL_TEXTURE_COMPARE_FUNC 0x884D
+#define GL_TEXTURE_COMPARE_MODE 0x884C
+#define GL_TEXTURE_COMPRESSED 0x86A1
+#define GL_TEXTURE_COMPRESSED_ARB 0x86A1
+#define GL_TEXTURE_COMPRESSED_BLOCK_HEIGHT 0x82B2
+#define GL_TEXTURE_COMPRESSED_BLOCK_SIZE 0x82B3
+#define GL_TEXTURE_COMPRESSED_BLOCK_WIDTH 0x82B1
+#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE 0x86A0
+#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB 0x86A0
+#define GL_TEXTURE_COMPRESSION_HINT 0x84EF
+#define GL_TEXTURE_COMPRESSION_HINT_ARB 0x84EF
+#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB 0x889A
+#define GL_TEXTURE_CUBE_MAP 0x8513
+#define GL_TEXTURE_CUBE_MAP_ARB 0x8513
+#define GL_TEXTURE_CUBE_MAP_ARRAY 0x9009
+#define GL_TEXTURE_CUBE_MAP_ARRAY_ARB 0x9009
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x8516
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x8518
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x851A
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x8515
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x8517
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x8519
+#define GL_TEXTURE_CUBE_MAP_SEAMLESS 0x884F
+#define GL_TEXTURE_DEPTH 0x8071
+#define GL_TEXTURE_DEPTH_SIZE 0x884A
+#define GL_TEXTURE_DEPTH_SIZE_ARB 0x884A
+#define GL_TEXTURE_DEPTH_TYPE 0x8C16
+#define GL_TEXTURE_DEPTH_TYPE_ARB 0x8C16
+#define GL_TEXTURE_FETCH_BARRIER_BIT 0x00000008
+#define GL_TEXTURE_FIXED_SAMPLE_LOCATIONS 0x9107
+#define GL_TEXTURE_GATHER 0x82A2
+#define GL_TEXTURE_GATHER_SHADOW 0x82A3
+#define GL_TEXTURE_GREEN_SIZE 0x805D
+#define GL_TEXTURE_GREEN_TYPE 0x8C11
+#define GL_TEXTURE_GREEN_TYPE_ARB 0x8C11
+#define GL_TEXTURE_HEIGHT 0x1001
+#define GL_TEXTURE_IMAGE_FORMAT 0x828F
+#define GL_TEXTURE_IMAGE_TYPE 0x8290
+#define GL_TEXTURE_IMMUTABLE_FORMAT 0x912F
+#define GL_TEXTURE_IMMUTABLE_LEVELS 0x82DF
+#define GL_TEXTURE_INTENSITY_TYPE_ARB 0x8C15
+#define GL_TEXTURE_INTERNAL_FORMAT 0x1003
+#define GL_TEXTURE_LOD_BIAS 0x8501
+#define GL_TEXTURE_LUMINANCE_TYPE_ARB 0x8C14
+#define GL_TEXTURE_MAG_FILTER 0x2800
+#define GL_TEXTURE_MAX_ANISOTROPY 0x84FE
+#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
+#define GL_TEXTURE_MAX_LEVEL 0x813D
+#define GL_TEXTURE_MAX_LOD 0x813B
+#define GL_TEXTURE_MIN_FILTER 0x2801
+#define GL_TEXTURE_MIN_LOD 0x813A
+#define GL_TEXTURE_RECTANGLE 0x84F5
+#define GL_TEXTURE_REDUCTION_MODE_ARB 0x9366
+#define GL_TEXTURE_RED_SIZE 0x805C
+#define GL_TEXTURE_RED_TYPE 0x8C10
+#define GL_TEXTURE_RED_TYPE_ARB 0x8C10
+#define GL_TEXTURE_SAMPLES 0x9106
+#define GL_TEXTURE_SHADOW 0x82A1
+#define GL_TEXTURE_SHARED_SIZE 0x8C3F
+#define GL_TEXTURE_STENCIL_SIZE 0x88F1
+#define GL_TEXTURE_SWIZZLE_A 0x8E45
+#define GL_TEXTURE_SWIZZLE_B 0x8E44
+#define GL_TEXTURE_SWIZZLE_G 0x8E43
+#define GL_TEXTURE_SWIZZLE_R 0x8E42
+#define GL_TEXTURE_SWIZZLE_RGBA 0x8E46
+#define GL_TEXTURE_TARGET 0x1006
+#define GL_TEXTURE_UPDATE_BARRIER_BIT 0x00000100
+#define GL_TEXTURE_VIEW 0x82B5
+#define GL_TEXTURE_VIEW_MIN_LAYER 0x82DD
+#define GL_TEXTURE_VIEW_MIN_LEVEL 0x82DB
+#define GL_TEXTURE_VIEW_NUM_LAYERS 0x82DE
+#define GL_TEXTURE_VIEW_NUM_LEVELS 0x82DC
+#define GL_TEXTURE_WIDTH 0x1000
+#define GL_TEXTURE_WRAP_R 0x8072
+#define GL_TEXTURE_WRAP_S 0x2802
+#define GL_TEXTURE_WRAP_T 0x2803
+#define GL_TIMEOUT_EXPIRED 0x911B
+#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFF
+#define GL_TIMESTAMP 0x8E28
+#define GL_TIME_ELAPSED 0x88BF
+#define GL_TOP_LEVEL_ARRAY_SIZE 0x930C
+#define GL_TOP_LEVEL_ARRAY_STRIDE 0x930D
+#define GL_TRANSFORM_FEEDBACK 0x8E22
+#define GL_TRANSFORM_FEEDBACK_ACTIVE 0x8E24
+#define GL_TRANSFORM_FEEDBACK_BARRIER_BIT 0x00000800
+#define GL_TRANSFORM_FEEDBACK_BINDING 0x8E25
+#define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E
+#define GL_TRANSFORM_FEEDBACK_BUFFER_ACTIVE 0x8E24
+#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F
+#define GL_TRANSFORM_FEEDBACK_BUFFER_INDEX 0x934B
+#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F
+#define GL_TRANSFORM_FEEDBACK_BUFFER_PAUSED 0x8E23
+#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85
+#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84
+#define GL_TRANSFORM_FEEDBACK_BUFFER_STRIDE 0x934C
+#define GL_TRANSFORM_FEEDBACK_PAUSED 0x8E23
+#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88
+#define GL_TRANSFORM_FEEDBACK_VARYING 0x92F4
+#define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83
+#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76
+#define GL_TRANSPOSE_COLOR_MATRIX_ARB 0x84E6
+#define GL_TRANSPOSE_CURRENT_MATRIX_ARB 0x88B7
+#define GL_TRANSPOSE_MODELVIEW_MATRIX_ARB 0x84E3
+#define GL_TRANSPOSE_PROJECTION_MATRIX_ARB 0x84E4
+#define GL_TRANSPOSE_TEXTURE_MATRIX_ARB 0x84E5
+#define GL_TRIANGLES 0x0004
+#define GL_TRIANGLES_ADJACENCY 0x000C
+#define GL_TRIANGLES_ADJACENCY_ARB 0x000C
+#define GL_TRIANGLE_FAN 0x0006
+#define GL_TRIANGLE_STRIP 0x0005
+#define GL_TRIANGLE_STRIP_ADJACENCY 0x000D
+#define GL_TRIANGLE_STRIP_ADJACENCY_ARB 0x000D
+#define GL_TRUE 1
+#define GL_TYPE 0x92FA
+#define GL_UNDEFINED_VERTEX 0x8260
+#define GL_UNIFORM 0x92E1
+#define GL_UNIFORM_ARRAY_STRIDE 0x8A3C
+#define GL_UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX 0x92DA
+#define GL_UNIFORM_BARRIER_BIT 0x00000004
+#define GL_UNIFORM_BLOCK 0x92E2
+#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42
+#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43
+#define GL_UNIFORM_BLOCK_BINDING 0x8A3F
+#define GL_UNIFORM_BLOCK_DATA_SIZE 0x8A40
+#define GL_UNIFORM_BLOCK_INDEX 0x8A3A
+#define GL_UNIFORM_BLOCK_NAME_LENGTH 0x8A41
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_COMPUTE_SHADER 0x90EC
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER 0x8A45
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_CONTROL_SHADER 0x84F0
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_EVALUATION_SHADER 0x84F1
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44
+#define GL_UNIFORM_BUFFER 0x8A11
+#define GL_UNIFORM_BUFFER_BINDING 0x8A28
+#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34
+#define GL_UNIFORM_BUFFER_SIZE 0x8A2A
+#define GL_UNIFORM_BUFFER_START 0x8A29
+#define GL_UNIFORM_IS_ROW_MAJOR 0x8A3E
+#define GL_UNIFORM_MATRIX_STRIDE 0x8A3D
+#define GL_UNIFORM_NAME_LENGTH 0x8A39
+#define GL_UNIFORM_OFFSET 0x8A3B
+#define GL_UNIFORM_SIZE 0x8A38
+#define GL_UNIFORM_TYPE 0x8A37
+#define GL_UNPACK_ALIGNMENT 0x0CF5
+#define GL_UNPACK_COMPRESSED_BLOCK_DEPTH 0x9129
+#define GL_UNPACK_COMPRESSED_BLOCK_HEIGHT 0x9128
+#define GL_UNPACK_COMPRESSED_BLOCK_SIZE 0x912A
+#define GL_UNPACK_COMPRESSED_BLOCK_WIDTH 0x9127
+#define GL_UNPACK_IMAGE_HEIGHT 0x806E
+#define GL_UNPACK_LSB_FIRST 0x0CF1
+#define GL_UNPACK_ROW_LENGTH 0x0CF2
+#define GL_UNPACK_SKIP_IMAGES 0x806D
+#define GL_UNPACK_SKIP_PIXELS 0x0CF4
+#define GL_UNPACK_SKIP_ROWS 0x0CF3
+#define GL_UNPACK_SWAP_BYTES 0x0CF0
+#define GL_UNSIGNALED 0x9118
+#define GL_UNSIGNED_BYTE 0x1401
+#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362
+#define GL_UNSIGNED_BYTE_3_3_2 0x8032
+#define GL_UNSIGNED_INT 0x1405
+#define GL_UNSIGNED_INT64_ARB 0x140F
+#define GL_UNSIGNED_INT64_VEC2_ARB 0x8FF5
+#define GL_UNSIGNED_INT64_VEC3_ARB 0x8FF6
+#define GL_UNSIGNED_INT64_VEC4_ARB 0x8FF7
+#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B
+#define GL_UNSIGNED_INT_10_10_10_2 0x8036
+#define GL_UNSIGNED_INT_24_8 0x84FA
+#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368
+#define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E
+#define GL_UNSIGNED_INT_8_8_8_8 0x8035
+#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367
+#define GL_UNSIGNED_INT_ATOMIC_COUNTER 0x92DB
+#define GL_UNSIGNED_INT_IMAGE_1D 0x9062
+#define GL_UNSIGNED_INT_IMAGE_1D_ARRAY 0x9068
+#define GL_UNSIGNED_INT_IMAGE_2D 0x9063
+#define GL_UNSIGNED_INT_IMAGE_2D_ARRAY 0x9069
+#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE 0x906B
+#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x906C
+#define GL_UNSIGNED_INT_IMAGE_2D_RECT 0x9065
+#define GL_UNSIGNED_INT_IMAGE_3D 0x9064
+#define GL_UNSIGNED_INT_IMAGE_BUFFER 0x9067
+#define GL_UNSIGNED_INT_IMAGE_CUBE 0x9066
+#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY 0x906A
+#define GL_UNSIGNED_INT_SAMPLER_1D 0x8DD1
+#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY 0x8DD6
+#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2
+#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7
+#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A
+#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D
+#define GL_UNSIGNED_INT_SAMPLER_2D_RECT 0x8DD5
+#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3
+#define GL_UNSIGNED_INT_SAMPLER_BUFFER 0x8DD8
+#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4
+#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY 0x900F
+#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900F
+#define GL_UNSIGNED_INT_VEC2 0x8DC6
+#define GL_UNSIGNED_INT_VEC3 0x8DC7
+#define GL_UNSIGNED_INT_VEC4 0x8DC8
+#define GL_UNSIGNED_NORMALIZED 0x8C17
+#define GL_UNSIGNED_NORMALIZED_ARB 0x8C17
+#define GL_UNSIGNED_SHORT 0x1403
+#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366
+#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033
+#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365
+#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
+#define GL_UNSIGNED_SHORT_5_6_5 0x8363
+#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364
+#define GL_UPPER_LEFT 0x8CA2
+#define GL_VALIDATE_STATUS 0x8B83
+#define GL_VENDOR 0x1F00
+#define GL_VERSION 0x1F02
+#define GL_VERTEX_ARRAY 0x8074
+#define GL_VERTEX_ARRAY_BINDING 0x85B5
+#define GL_VERTEX_ARRAY_BUFFER_BINDING_ARB 0x8896
+#define GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT 0x00000001
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB 0x889F
+#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR 0x88FE
+#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ARB 0x88FE
+#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622
+#define GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB 0x8622
+#define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD
+#define GL_VERTEX_ATTRIB_ARRAY_LONG 0x874E
+#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
+#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB 0x886A
+#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645
+#define GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB 0x8645
+#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623
+#define GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB 0x8623
+#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624
+#define GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB 0x8624
+#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625
+#define GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB 0x8625
+#define GL_VERTEX_ATTRIB_BINDING 0x82D4
+#define GL_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D5
+#define GL_VERTEX_BINDING_BUFFER 0x8F4F
+#define GL_VERTEX_BINDING_DIVISOR 0x82D6
+#define GL_VERTEX_BINDING_OFFSET 0x82D7
+#define GL_VERTEX_BINDING_STRIDE 0x82D8
+#define GL_VERTEX_PROGRAM_ARB 0x8620
+#define GL_VERTEX_PROGRAM_POINT_SIZE 0x8642
+#define GL_VERTEX_PROGRAM_POINT_SIZE_ARB 0x8642
+#define GL_VERTEX_PROGRAM_TWO_SIDE_ARB 0x8643
+#define GL_VERTEX_SHADER 0x8B31
+#define GL_VERTEX_SHADER_ARB 0x8B31
+#define GL_VERTEX_SHADER_BIT 0x00000001
+#define GL_VERTEX_SHADER_INVOCATIONS 0x82F0
+#define GL_VERTEX_SHADER_INVOCATIONS_ARB 0x82F0
+#define GL_VERTEX_SUBROUTINE 0x92E8
+#define GL_VERTEX_SUBROUTINE_UNIFORM 0x92EE
+#define GL_VERTEX_TEXTURE 0x829B
+#define GL_VERTICES_SUBMITTED 0x82EE
+#define GL_VERTICES_SUBMITTED_ARB 0x82EE
+#define GL_VIEWPORT 0x0BA2
+#define GL_VIEWPORT_BOUNDS_RANGE 0x825D
+#define GL_VIEWPORT_INDEX_PROVOKING_VERTEX 0x825F
+#define GL_VIEWPORT_SUBPIXEL_BITS 0x825C
+#define GL_VIEW_CLASS_128_BITS 0x82C4
+#define GL_VIEW_CLASS_16_BITS 0x82CA
+#define GL_VIEW_CLASS_24_BITS 0x82C9
+#define GL_VIEW_CLASS_32_BITS 0x82C8
+#define GL_VIEW_CLASS_48_BITS 0x82C7
+#define GL_VIEW_CLASS_64_BITS 0x82C6
+#define GL_VIEW_CLASS_8_BITS 0x82CB
+#define GL_VIEW_CLASS_96_BITS 0x82C5
+#define GL_VIEW_CLASS_ASTC_10x10_RGBA 0x9393
+#define GL_VIEW_CLASS_ASTC_10x5_RGBA 0x9390
+#define GL_VIEW_CLASS_ASTC_10x6_RGBA 0x9391
+#define GL_VIEW_CLASS_ASTC_10x8_RGBA 0x9392
+#define GL_VIEW_CLASS_ASTC_12x10_RGBA 0x9394
+#define GL_VIEW_CLASS_ASTC_12x12_RGBA 0x9395
+#define GL_VIEW_CLASS_ASTC_4x4_RGBA 0x9388
+#define GL_VIEW_CLASS_ASTC_5x4_RGBA 0x9389
+#define GL_VIEW_CLASS_ASTC_5x5_RGBA 0x938A
+#define GL_VIEW_CLASS_ASTC_6x5_RGBA 0x938B
+#define GL_VIEW_CLASS_ASTC_6x6_RGBA 0x938C
+#define GL_VIEW_CLASS_ASTC_8x5_RGBA 0x938D
+#define GL_VIEW_CLASS_ASTC_8x6_RGBA 0x938E
+#define GL_VIEW_CLASS_ASTC_8x8_RGBA 0x938F
+#define GL_VIEW_CLASS_BPTC_FLOAT 0x82D3
+#define GL_VIEW_CLASS_BPTC_UNORM 0x82D2
+#define GL_VIEW_CLASS_EAC_R11 0x9383
+#define GL_VIEW_CLASS_EAC_RG11 0x9384
+#define GL_VIEW_CLASS_ETC2_EAC_RGBA 0x9387
+#define GL_VIEW_CLASS_ETC2_RGB 0x9385
+#define GL_VIEW_CLASS_ETC2_RGBA 0x9386
+#define GL_VIEW_CLASS_RGTC1_RED 0x82D0
+#define GL_VIEW_CLASS_RGTC2_RG 0x82D1
+#define GL_VIEW_CLASS_S3TC_DXT1_RGB 0x82CC
+#define GL_VIEW_CLASS_S3TC_DXT1_RGBA 0x82CD
+#define GL_VIEW_CLASS_S3TC_DXT3_RGBA 0x82CE
+#define GL_VIEW_CLASS_S3TC_DXT5_RGBA 0x82CF
+#define GL_VIEW_COMPATIBILITY_CLASS 0x82B6
+#define GL_WAIT_FAILED 0x911D
+#define GL_WEIGHTED_AVERAGE_ARB 0x9367
+#define GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB 0x889E
+#define GL_WRITE_ONLY 0x88B9
+#define GL_WRITE_ONLY_ARB 0x88B9
+#define GL_XOR 0x1506
+#define GL_ZERO 0
+
+
+#ifndef __khrplatform_h_
+#define __khrplatform_h_
+
+/*
+** Copyright (c) 2008-2018 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+/* Khronos platform-specific types and definitions.
+ *
+ * The master copy of khrplatform.h is maintained in the Khronos EGL
+ * Registry repository at https://github.com/KhronosGroup/EGL-Registry
+ * The last semantic modification to khrplatform.h was at commit ID:
+ * 67a3e0864c2d75ea5287b9f3d2eb74a745936692
+ *
+ * Adopters may modify this file to suit their platform. Adopters are
+ * encouraged to submit platform specific modifications to the Khronos
+ * group so that they can be included in future versions of this file.
+ * Please submit changes by filing pull requests or issues on
+ * the EGL Registry repository linked above.
+ *
+ *
+ * See the Implementer's Guidelines for information about where this file
+ * should be located on your system and for more details of its use:
+ * http://www.khronos.org/registry/implementers_guide.pdf
+ *
+ * This file should be included as
+ * #include
+ * by Khronos client API header files that use its types and defines.
+ *
+ * The types in khrplatform.h should only be used to define API-specific types.
+ *
+ * Types defined in khrplatform.h:
+ * khronos_int8_t signed 8 bit
+ * khronos_uint8_t unsigned 8 bit
+ * khronos_int16_t signed 16 bit
+ * khronos_uint16_t unsigned 16 bit
+ * khronos_int32_t signed 32 bit
+ * khronos_uint32_t unsigned 32 bit
+ * khronos_int64_t signed 64 bit
+ * khronos_uint64_t unsigned 64 bit
+ * khronos_intptr_t signed same number of bits as a pointer
+ * khronos_uintptr_t unsigned same number of bits as a pointer
+ * khronos_ssize_t signed size
+ * khronos_usize_t unsigned size
+ * khronos_float_t signed 32 bit floating point
+ * khronos_time_ns_t unsigned 64 bit time in nanoseconds
+ * khronos_utime_nanoseconds_t unsigned time interval or absolute time in
+ * nanoseconds
+ * khronos_stime_nanoseconds_t signed time interval in nanoseconds
+ * khronos_boolean_enum_t enumerated boolean type. This should
+ * only be used as a base type when a client API's boolean type is
+ * an enum. Client APIs which use an integer or other type for
+ * booleans cannot use this as the base type for their boolean.
+ *
+ * Tokens defined in khrplatform.h:
+ *
+ * KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values.
+ *
+ * KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0.
+ * KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0.
+ *
+ * Calling convention macros defined in this file:
+ * KHRONOS_APICALL
+ * KHRONOS_GLAD_API_PTR
+ * KHRONOS_APIATTRIBUTES
+ *
+ * These may be used in function prototypes as:
+ *
+ * KHRONOS_APICALL void KHRONOS_GLAD_API_PTR funcname(
+ * int arg1,
+ * int arg2) KHRONOS_APIATTRIBUTES;
+ */
+
+#if defined(__SCITECH_SNAP__) && !defined(KHRONOS_STATIC)
+# define KHRONOS_STATIC 1
+#endif
+
+/*-------------------------------------------------------------------------
+ * Definition of KHRONOS_APICALL
+ *-------------------------------------------------------------------------
+ * This precedes the return type of the function in the function prototype.
+ */
+#if defined(KHRONOS_STATIC)
+ /* If the preprocessor constant KHRONOS_STATIC is defined, make the
+ * header compatible with static linking. */
+# define KHRONOS_APICALL
+#elif defined(_WIN32)
+# define KHRONOS_APICALL __declspec(dllimport)
+#elif defined (__SYMBIAN32__)
+# define KHRONOS_APICALL IMPORT_C
+#elif defined(__ANDROID__)
+# define KHRONOS_APICALL __attribute__((visibility("default")))
+#else
+# define KHRONOS_APICALL
+#endif
+
+/*-------------------------------------------------------------------------
+ * Definition of KHRONOS_GLAD_API_PTR
+ *-------------------------------------------------------------------------
+ * This follows the return type of the function and precedes the function
+ * name in the function prototype.
+ */
+#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__)
+ /* Win32 but not WinCE */
+# define KHRONOS_GLAD_API_PTR __stdcall
+#else
+# define KHRONOS_GLAD_API_PTR
+#endif
+
+/*-------------------------------------------------------------------------
+ * Definition of KHRONOS_APIATTRIBUTES
+ *-------------------------------------------------------------------------
+ * This follows the closing parenthesis of the function prototype arguments.
+ */
+#if defined (__ARMCC_2__)
+#define KHRONOS_APIATTRIBUTES __softfp
+#else
+#define KHRONOS_APIATTRIBUTES
+#endif
+
+/*-------------------------------------------------------------------------
+ * basic type definitions
+ *-----------------------------------------------------------------------*/
+#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__)
+
+
+/*
+ * Using
+ */
+#include
+typedef int32_t khronos_int32_t;
+typedef uint32_t khronos_uint32_t;
+typedef int64_t khronos_int64_t;
+typedef uint64_t khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64 1
+#define KHRONOS_SUPPORT_FLOAT 1
+/*
+ * To support platform where unsigned long cannot be used interchangeably with
+ * inptr_t (e.g. CHERI-extended ISAs), we can use the stdint.h intptr_t.
+ * Ideally, we could just use (u)intptr_t everywhere, but this could result in
+ * ABI breakage if khronos_uintptr_t is changed from unsigned long to
+ * unsigned long long or similar (this results in different C++ name mangling).
+ * To avoid changes for existing platforms, we restrict usage of intptr_t to
+ * platforms where the size of a pointer is larger than the size of long.
+ */
+#if defined(__SIZEOF_LONG__) && defined(__SIZEOF_POINTER__)
+#if __SIZEOF_POINTER__ > __SIZEOF_LONG__
+#define KHRONOS_USE_INTPTR_T
+#endif
+#endif
+
+#elif defined(__VMS ) || defined(__sgi)
+
+/*
+ * Using
+ */
+#include
+typedef int32_t khronos_int32_t;
+typedef uint32_t khronos_uint32_t;
+typedef int64_t khronos_int64_t;
+typedef uint64_t khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64 1
+#define KHRONOS_SUPPORT_FLOAT 1
+
+#elif defined(_WIN32) && !defined(__SCITECH_SNAP__)
+
+/*
+ * Win32
+ */
+typedef __int32 khronos_int32_t;
+typedef unsigned __int32 khronos_uint32_t;
+typedef __int64 khronos_int64_t;
+typedef unsigned __int64 khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64 1
+#define KHRONOS_SUPPORT_FLOAT 1
+
+#elif defined(__sun__) || defined(__digital__)
+
+/*
+ * Sun or Digital
+ */
+typedef int khronos_int32_t;
+typedef unsigned int khronos_uint32_t;
+#if defined(__arch64__) || defined(_LP64)
+typedef long int khronos_int64_t;
+typedef unsigned long int khronos_uint64_t;
+#else
+typedef long long int khronos_int64_t;
+typedef unsigned long long int khronos_uint64_t;
+#endif /* __arch64__ */
+#define KHRONOS_SUPPORT_INT64 1
+#define KHRONOS_SUPPORT_FLOAT 1
+
+#elif 0
+
+/*
+ * Hypothetical platform with no float or int64 support
+ */
+typedef int khronos_int32_t;
+typedef unsigned int khronos_uint32_t;
+#define KHRONOS_SUPPORT_INT64 0
+#define KHRONOS_SUPPORT_FLOAT 0
+
+#else
+
+/*
+ * Generic fallback
+ */
+#include
+typedef int32_t khronos_int32_t;
+typedef uint32_t khronos_uint32_t;
+typedef int64_t khronos_int64_t;
+typedef uint64_t khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64 1
+#define KHRONOS_SUPPORT_FLOAT 1
+
+#endif
+
+
+/*
+ * Types that are (so far) the same on all platforms
+ */
+typedef signed char khronos_int8_t;
+typedef unsigned char khronos_uint8_t;
+typedef signed short int khronos_int16_t;
+typedef unsigned short int khronos_uint16_t;
+
+/*
+ * Types that differ between LLP64 and LP64 architectures - in LLP64,
+ * pointers are 64 bits, but 'long' is still 32 bits. Win64 appears
+ * to be the only LLP64 architecture in current use.
+ */
+#ifdef KHRONOS_USE_INTPTR_T
+typedef intptr_t khronos_intptr_t;
+typedef uintptr_t khronos_uintptr_t;
+#elif defined(_WIN64)
+typedef signed long long int khronos_intptr_t;
+typedef unsigned long long int khronos_uintptr_t;
+#else
+typedef signed long int khronos_intptr_t;
+typedef unsigned long int khronos_uintptr_t;
+#endif
+
+#if defined(_WIN64)
+typedef signed long long int khronos_ssize_t;
+typedef unsigned long long int khronos_usize_t;
+#else
+typedef signed long int khronos_ssize_t;
+typedef unsigned long int khronos_usize_t;
+#endif
+
+#if KHRONOS_SUPPORT_FLOAT
+/*
+ * Float type
+ */
+typedef float khronos_float_t;
+#endif
+
+#if KHRONOS_SUPPORT_INT64
+/* Time types
+ *
+ * These types can be used to represent a time interval in nanoseconds or
+ * an absolute Unadjusted System Time. Unadjusted System Time is the number
+ * of nanoseconds since some arbitrary system event (e.g. since the last
+ * time the system booted). The Unadjusted System Time is an unsigned
+ * 64 bit value that wraps back to 0 every 584 years. Time intervals
+ * may be either signed or unsigned.
+ */
+typedef khronos_uint64_t khronos_utime_nanoseconds_t;
+typedef khronos_int64_t khronos_stime_nanoseconds_t;
+#endif
+
+/*
+ * Dummy value used to pad enum types to 32 bits.
+ */
+#ifndef KHRONOS_MAX_ENUM
+#define KHRONOS_MAX_ENUM 0x7FFFFFFF
+#endif
+
+/*
+ * Enumerated boolean type
+ *
+ * Values other than zero should be considered to be true. Therefore
+ * comparisons should not be made against KHRONOS_TRUE.
+ */
+typedef enum {
+ KHRONOS_FALSE = 0,
+ KHRONOS_TRUE = 1,
+ KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM
+} khronos_boolean_enum_t;
+
+#endif /* __khrplatform_h_ */
+typedef unsigned int GLenum;
+typedef unsigned char GLboolean;
+typedef unsigned int GLbitfield;
+typedef void GLvoid;
+typedef khronos_int8_t GLbyte;
+typedef khronos_uint8_t GLubyte;
+typedef khronos_int16_t GLshort;
+typedef khronos_uint16_t GLushort;
+typedef int GLint;
+typedef unsigned int GLuint;
+typedef khronos_int32_t GLclampx;
+typedef int GLsizei;
+typedef khronos_float_t GLfloat;
+typedef khronos_float_t GLclampf;
+typedef double GLdouble;
+typedef double GLclampd;
+typedef void *GLeglClientBufferEXT;
+typedef void *GLeglImageOES;
+typedef char GLchar;
+typedef char GLcharARB;
+#ifdef __APPLE__
+typedef void *GLhandleARB;
+#else
+typedef unsigned int GLhandleARB;
+#endif
+typedef khronos_uint16_t GLhalf;
+typedef khronos_uint16_t GLhalfARB;
+typedef khronos_int32_t GLfixed;
+#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060)
+typedef khronos_intptr_t GLintptr;
+#else
+typedef khronos_intptr_t GLintptr;
+#endif
+#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060)
+typedef khronos_intptr_t GLintptrARB;
+#else
+typedef khronos_intptr_t GLintptrARB;
+#endif
+#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060)
+typedef khronos_ssize_t GLsizeiptr;
+#else
+typedef khronos_ssize_t GLsizeiptr;
+#endif
+#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060)
+typedef khronos_ssize_t GLsizeiptrARB;
+#else
+typedef khronos_ssize_t GLsizeiptrARB;
+#endif
+typedef khronos_int64_t GLint64;
+typedef khronos_int64_t GLint64EXT;
+typedef khronos_uint64_t GLuint64;
+typedef khronos_uint64_t GLuint64EXT;
+typedef struct __GLsync *GLsync;
+struct _cl_context;
+struct _cl_event;
+typedef void (GLAD_API_PTR *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
+typedef void (GLAD_API_PTR *GLDEBUGPROCARB)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
+typedef void (GLAD_API_PTR *GLDEBUGPROCKHR)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
+typedef void (GLAD_API_PTR *GLDEBUGPROCAMD)(GLuint id,GLenum category,GLenum severity,GLsizei length,const GLchar *message,void *userParam);
+typedef unsigned short GLhalfNV;
+typedef GLintptr GLvdpauSurfaceNV;
+typedef void (GLAD_API_PTR *GLVULKANPROCNV)(void);
+
+
+#define GL_VERSION_1_0 1
+GLAD_API_CALL int GLAD_GL_VERSION_1_0;
+#define GL_VERSION_1_1 1
+GLAD_API_CALL int GLAD_GL_VERSION_1_1;
+#define GL_VERSION_1_2 1
+GLAD_API_CALL int GLAD_GL_VERSION_1_2;
+#define GL_VERSION_1_3 1
+GLAD_API_CALL int GLAD_GL_VERSION_1_3;
+#define GL_VERSION_1_4 1
+GLAD_API_CALL int GLAD_GL_VERSION_1_4;
+#define GL_VERSION_1_5 1
+GLAD_API_CALL int GLAD_GL_VERSION_1_5;
+#define GL_VERSION_2_0 1
+GLAD_API_CALL int GLAD_GL_VERSION_2_0;
+#define GL_VERSION_2_1 1
+GLAD_API_CALL int GLAD_GL_VERSION_2_1;
+#define GL_VERSION_3_0 1
+GLAD_API_CALL int GLAD_GL_VERSION_3_0;
+#define GL_VERSION_3_1 1
+GLAD_API_CALL int GLAD_GL_VERSION_3_1;
+#define GL_VERSION_3_2 1
+GLAD_API_CALL int GLAD_GL_VERSION_3_2;
+#define GL_VERSION_3_3 1
+GLAD_API_CALL int GLAD_GL_VERSION_3_3;
+#define GL_VERSION_4_0 1
+GLAD_API_CALL int GLAD_GL_VERSION_4_0;
+#define GL_VERSION_4_1 1
+GLAD_API_CALL int GLAD_GL_VERSION_4_1;
+#define GL_VERSION_4_2 1
+GLAD_API_CALL int GLAD_GL_VERSION_4_2;
+#define GL_VERSION_4_3 1
+GLAD_API_CALL int GLAD_GL_VERSION_4_3;
+#define GL_ARB_ES2_compatibility 1
+GLAD_API_CALL int GLAD_GL_ARB_ES2_compatibility;
+#define GL_ARB_ES3_1_compatibility 1
+GLAD_API_CALL int GLAD_GL_ARB_ES3_1_compatibility;
+#define GL_ARB_ES3_2_compatibility 1
+GLAD_API_CALL int GLAD_GL_ARB_ES3_2_compatibility;
+#define GL_ARB_ES3_compatibility 1
+GLAD_API_CALL int GLAD_GL_ARB_ES3_compatibility;
+#define GL_ARB_blend_func_extended 1
+GLAD_API_CALL int GLAD_GL_ARB_blend_func_extended;
+#define GL_ARB_buffer_storage 1
+GLAD_API_CALL int GLAD_GL_ARB_buffer_storage;
+#define GL_ARB_clear_buffer_object 1
+GLAD_API_CALL int GLAD_GL_ARB_clear_buffer_object;
+#define GL_ARB_clear_texture 1
+GLAD_API_CALL int GLAD_GL_ARB_clear_texture;
+#define GL_ARB_color_buffer_float 1
+GLAD_API_CALL int GLAD_GL_ARB_color_buffer_float;
+#define GL_ARB_compatibility 1
+GLAD_API_CALL int GLAD_GL_ARB_compatibility;
+#define GL_ARB_compressed_texture_pixel_storage 1
+GLAD_API_CALL int GLAD_GL_ARB_compressed_texture_pixel_storage;
+#define GL_ARB_compute_shader 1
+GLAD_API_CALL int GLAD_GL_ARB_compute_shader;
+#define GL_ARB_compute_variable_group_size 1
+GLAD_API_CALL int GLAD_GL_ARB_compute_variable_group_size;
+#define GL_ARB_copy_buffer 1
+GLAD_API_CALL int GLAD_GL_ARB_copy_buffer;
+#define GL_ARB_copy_image 1
+GLAD_API_CALL int GLAD_GL_ARB_copy_image;
+#define GL_ARB_debug_output 1
+GLAD_API_CALL int GLAD_GL_ARB_debug_output;
+#define GL_ARB_depth_buffer_float 1
+GLAD_API_CALL int GLAD_GL_ARB_depth_buffer_float;
+#define GL_ARB_depth_clamp 1
+GLAD_API_CALL int GLAD_GL_ARB_depth_clamp;
+#define GL_ARB_depth_texture 1
+GLAD_API_CALL int GLAD_GL_ARB_depth_texture;
+#define GL_ARB_direct_state_access 1
+GLAD_API_CALL int GLAD_GL_ARB_direct_state_access;
+#define GL_ARB_draw_buffers 1
+GLAD_API_CALL int GLAD_GL_ARB_draw_buffers;
+#define GL_ARB_draw_buffers_blend 1
+GLAD_API_CALL int GLAD_GL_ARB_draw_buffers_blend;
+#define GL_ARB_draw_elements_base_vertex 1
+GLAD_API_CALL int GLAD_GL_ARB_draw_elements_base_vertex;
+#define GL_ARB_draw_indirect 1
+GLAD_API_CALL int GLAD_GL_ARB_draw_indirect;
+#define GL_ARB_draw_instanced 1
+GLAD_API_CALL int GLAD_GL_ARB_draw_instanced;
+#define GL_ARB_enhanced_layouts 1
+GLAD_API_CALL int GLAD_GL_ARB_enhanced_layouts;
+#define GL_ARB_explicit_attrib_location 1
+GLAD_API_CALL int GLAD_GL_ARB_explicit_attrib_location;
+#define GL_ARB_explicit_uniform_location 1
+GLAD_API_CALL int GLAD_GL_ARB_explicit_uniform_location;
+#define GL_ARB_fragment_coord_conventions 1
+GLAD_API_CALL int GLAD_GL_ARB_fragment_coord_conventions;
+#define GL_ARB_fragment_layer_viewport 1
+GLAD_API_CALL int GLAD_GL_ARB_fragment_layer_viewport;
+#define GL_ARB_fragment_program 1
+GLAD_API_CALL int GLAD_GL_ARB_fragment_program;
+#define GL_ARB_fragment_program_shadow 1
+GLAD_API_CALL int GLAD_GL_ARB_fragment_program_shadow;
+#define GL_ARB_fragment_shader 1
+GLAD_API_CALL int GLAD_GL_ARB_fragment_shader;
+#define GL_ARB_fragment_shader_interlock 1
+GLAD_API_CALL int GLAD_GL_ARB_fragment_shader_interlock;
+#define GL_ARB_framebuffer_no_attachments 1
+GLAD_API_CALL int GLAD_GL_ARB_framebuffer_no_attachments;
+#define GL_ARB_framebuffer_object 1
+GLAD_API_CALL int GLAD_GL_ARB_framebuffer_object;
+#define GL_ARB_framebuffer_sRGB 1
+GLAD_API_CALL int GLAD_GL_ARB_framebuffer_sRGB;
+#define GL_ARB_geometry_shader4 1
+GLAD_API_CALL int GLAD_GL_ARB_geometry_shader4;
+#define GL_ARB_get_program_binary 1
+GLAD_API_CALL int GLAD_GL_ARB_get_program_binary;
+#define GL_ARB_get_texture_sub_image 1
+GLAD_API_CALL int GLAD_GL_ARB_get_texture_sub_image;
+#define GL_ARB_gl_spirv 1
+GLAD_API_CALL int GLAD_GL_ARB_gl_spirv;
+#define GL_ARB_gpu_shader5 1
+GLAD_API_CALL int GLAD_GL_ARB_gpu_shader5;
+#define GL_ARB_gpu_shader_fp64 1
+GLAD_API_CALL int GLAD_GL_ARB_gpu_shader_fp64;
+#define GL_ARB_gpu_shader_int64 1
+GLAD_API_CALL int GLAD_GL_ARB_gpu_shader_int64;
+#define GL_ARB_half_float_pixel 1
+GLAD_API_CALL int GLAD_GL_ARB_half_float_pixel;
+#define GL_ARB_half_float_vertex 1
+GLAD_API_CALL int GLAD_GL_ARB_half_float_vertex;
+#define GL_ARB_instanced_arrays 1
+GLAD_API_CALL int GLAD_GL_ARB_instanced_arrays;
+#define GL_ARB_internalformat_query 1
+GLAD_API_CALL int GLAD_GL_ARB_internalformat_query;
+#define GL_ARB_internalformat_query2 1
+GLAD_API_CALL int GLAD_GL_ARB_internalformat_query2;
+#define GL_ARB_map_buffer_range 1
+GLAD_API_CALL int GLAD_GL_ARB_map_buffer_range;
+#define GL_ARB_multi_bind 1
+GLAD_API_CALL int GLAD_GL_ARB_multi_bind;
+#define GL_ARB_multi_draw_indirect 1
+GLAD_API_CALL int GLAD_GL_ARB_multi_draw_indirect;
+#define GL_ARB_multisample 1
+GLAD_API_CALL int GLAD_GL_ARB_multisample;
+#define GL_ARB_multitexture 1
+GLAD_API_CALL int GLAD_GL_ARB_multitexture;
+#define GL_ARB_occlusion_query 1
+GLAD_API_CALL int GLAD_GL_ARB_occlusion_query;
+#define GL_ARB_occlusion_query2 1
+GLAD_API_CALL int GLAD_GL_ARB_occlusion_query2;
+#define GL_ARB_pipeline_statistics_query 1
+GLAD_API_CALL int GLAD_GL_ARB_pipeline_statistics_query;
+#define GL_ARB_query_buffer_object 1
+GLAD_API_CALL int GLAD_GL_ARB_query_buffer_object;
+#define GL_ARB_sample_locations 1
+GLAD_API_CALL int GLAD_GL_ARB_sample_locations;
+#define GL_ARB_sample_shading 1
+GLAD_API_CALL int GLAD_GL_ARB_sample_shading;
+#define GL_ARB_seamless_cube_map 1
+GLAD_API_CALL int GLAD_GL_ARB_seamless_cube_map;
+#define GL_ARB_seamless_cubemap_per_texture 1
+GLAD_API_CALL int GLAD_GL_ARB_seamless_cubemap_per_texture;
+#define GL_ARB_shader_atomic_counter_ops 1
+GLAD_API_CALL int GLAD_GL_ARB_shader_atomic_counter_ops;
+#define GL_ARB_shader_atomic_counters 1
+GLAD_API_CALL int GLAD_GL_ARB_shader_atomic_counters;
+#define GL_ARB_shader_bit_encoding 1
+GLAD_API_CALL int GLAD_GL_ARB_shader_bit_encoding;
+#define GL_ARB_shader_clock 1
+GLAD_API_CALL int GLAD_GL_ARB_shader_clock;
+#define GL_ARB_shader_image_load_store 1
+GLAD_API_CALL int GLAD_GL_ARB_shader_image_load_store;
+#define GL_ARB_shader_image_size 1
+GLAD_API_CALL int GLAD_GL_ARB_shader_image_size;
+#define GL_ARB_shader_objects 1
+GLAD_API_CALL int GLAD_GL_ARB_shader_objects;
+#define GL_ARB_shader_storage_buffer_object 1
+GLAD_API_CALL int GLAD_GL_ARB_shader_storage_buffer_object;
+#define GL_ARB_shader_texture_lod 1
+GLAD_API_CALL int GLAD_GL_ARB_shader_texture_lod;
+#define GL_ARB_shading_language_100 1
+GLAD_API_CALL int GLAD_GL_ARB_shading_language_100;
+#define GL_ARB_shading_language_420pack 1
+GLAD_API_CALL int GLAD_GL_ARB_shading_language_420pack;
+#define GL_ARB_shading_language_include 1
+GLAD_API_CALL int GLAD_GL_ARB_shading_language_include;
+#define GL_ARB_shading_language_packing 1
+GLAD_API_CALL int GLAD_GL_ARB_shading_language_packing;
+#define GL_ARB_spirv_extensions 1
+GLAD_API_CALL int GLAD_GL_ARB_spirv_extensions;
+#define GL_ARB_tessellation_shader 1
+GLAD_API_CALL int GLAD_GL_ARB_tessellation_shader;
+#define GL_ARB_texture_border_clamp 1
+GLAD_API_CALL int GLAD_GL_ARB_texture_border_clamp;
+#define GL_ARB_texture_buffer_object_rgb32 1
+GLAD_API_CALL int GLAD_GL_ARB_texture_buffer_object_rgb32;
+#define GL_ARB_texture_compression 1
+GLAD_API_CALL int GLAD_GL_ARB_texture_compression;
+#define GL_ARB_texture_cube_map 1
+GLAD_API_CALL int GLAD_GL_ARB_texture_cube_map;
+#define GL_ARB_texture_cube_map_array 1
+GLAD_API_CALL int GLAD_GL_ARB_texture_cube_map_array;
+#define GL_ARB_texture_env_add 1
+GLAD_API_CALL int GLAD_GL_ARB_texture_env_add;
+#define GL_ARB_texture_filter_anisotropic 1
+GLAD_API_CALL int GLAD_GL_ARB_texture_filter_anisotropic;
+#define GL_ARB_texture_filter_minmax 1
+GLAD_API_CALL int GLAD_GL_ARB_texture_filter_minmax;
+#define GL_ARB_texture_float 1
+GLAD_API_CALL int GLAD_GL_ARB_texture_float;
+#define GL_ARB_texture_mirror_clamp_to_edge 1
+GLAD_API_CALL int GLAD_GL_ARB_texture_mirror_clamp_to_edge;
+#define GL_ARB_texture_mirrored_repeat 1
+GLAD_API_CALL int GLAD_GL_ARB_texture_mirrored_repeat;
+#define GL_ARB_texture_multisample 1
+GLAD_API_CALL int GLAD_GL_ARB_texture_multisample;
+#define GL_ARB_texture_non_power_of_two 1
+GLAD_API_CALL int GLAD_GL_ARB_texture_non_power_of_two;
+#define GL_ARB_texture_rg 1
+GLAD_API_CALL int GLAD_GL_ARB_texture_rg;
+#define GL_ARB_texture_storage 1
+GLAD_API_CALL int GLAD_GL_ARB_texture_storage;
+#define GL_ARB_texture_swizzle 1
+GLAD_API_CALL int GLAD_GL_ARB_texture_swizzle;
+#define GL_ARB_texture_view 1
+GLAD_API_CALL int GLAD_GL_ARB_texture_view;
+#define GL_ARB_timer_query 1
+GLAD_API_CALL int GLAD_GL_ARB_timer_query;
+#define GL_ARB_transpose_matrix 1
+GLAD_API_CALL int GLAD_GL_ARB_transpose_matrix;
+#define GL_ARB_uniform_buffer_object 1
+GLAD_API_CALL int GLAD_GL_ARB_uniform_buffer_object;
+#define GL_ARB_vertex_array_bgra 1
+GLAD_API_CALL int GLAD_GL_ARB_vertex_array_bgra;
+#define GL_ARB_vertex_array_object 1
+GLAD_API_CALL int GLAD_GL_ARB_vertex_array_object;
+#define GL_ARB_vertex_attrib_binding 1
+GLAD_API_CALL int GLAD_GL_ARB_vertex_attrib_binding;
+#define GL_ARB_vertex_buffer_object 1
+GLAD_API_CALL int GLAD_GL_ARB_vertex_buffer_object;
+#define GL_ARB_vertex_program 1
+GLAD_API_CALL int GLAD_GL_ARB_vertex_program;
+#define GL_ARB_vertex_shader 1
+GLAD_API_CALL int GLAD_GL_ARB_vertex_shader;
+#define GL_EXT_draw_instanced 1
+GLAD_API_CALL int GLAD_GL_EXT_draw_instanced;
+#define GL_EXT_fog_coord 1
+GLAD_API_CALL int GLAD_GL_EXT_fog_coord;
+#define GL_EXT_framebuffer_blit 1
+GLAD_API_CALL int GLAD_GL_EXT_framebuffer_blit;
+#define GL_EXT_framebuffer_multisample 1
+GLAD_API_CALL int GLAD_GL_EXT_framebuffer_multisample;
+#define GL_EXT_framebuffer_object 1
+GLAD_API_CALL int GLAD_GL_EXT_framebuffer_object;
+#define GL_EXT_framebuffer_sRGB 1
+GLAD_API_CALL int GLAD_GL_EXT_framebuffer_sRGB;
+#define GL_EXT_texture_compression_s3tc 1
+GLAD_API_CALL int GLAD_GL_EXT_texture_compression_s3tc;
+#define GL_EXT_texture_filter_anisotropic 1
+GLAD_API_CALL int GLAD_GL_EXT_texture_filter_anisotropic;
+#define GL_EXT_texture_mirror_clamp 1
+GLAD_API_CALL int GLAD_GL_EXT_texture_mirror_clamp;
+#define GL_KHR_texture_compression_astc_hdr 1
+GLAD_API_CALL int GLAD_GL_KHR_texture_compression_astc_hdr;
+#define GL_KHR_texture_compression_astc_ldr 1
+GLAD_API_CALL int GLAD_GL_KHR_texture_compression_astc_ldr;
+#define GL_OES_compressed_paletted_texture 1
+GLAD_API_CALL int GLAD_GL_OES_compressed_paletted_texture;
+#define GL_OES_fixed_point 1
+GLAD_API_CALL int GLAD_GL_OES_fixed_point;
+
+
+typedef void (GLAD_API_PTR *PFNGLACCUMXOESPROC)(GLenum op, GLfixed value);
+typedef void (GLAD_API_PTR *PFNGLACTIVESHADERPROGRAMPROC)(GLuint pipeline, GLuint program);
+typedef void (GLAD_API_PTR *PFNGLACTIVETEXTUREPROC)(GLenum texture);
+typedef void (GLAD_API_PTR *PFNGLACTIVETEXTUREARBPROC)(GLenum texture);
+typedef void (GLAD_API_PTR *PFNGLALPHAFUNCXOESPROC)(GLenum func, GLfixed ref);
+typedef void (GLAD_API_PTR *PFNGLATTACHOBJECTARBPROC)(GLhandleARB containerObj, GLhandleARB obj);
+typedef void (GLAD_API_PTR *PFNGLATTACHSHADERPROC)(GLuint program, GLuint shader);
+typedef void (GLAD_API_PTR *PFNGLBEGINCONDITIONALRENDERPROC)(GLuint id, GLenum mode);
+typedef void (GLAD_API_PTR *PFNGLBEGINQUERYPROC)(GLenum target, GLuint id);
+typedef void (GLAD_API_PTR *PFNGLBEGINQUERYARBPROC)(GLenum target, GLuint id);
+typedef void (GLAD_API_PTR *PFNGLBEGINQUERYINDEXEDPROC)(GLenum target, GLuint index, GLuint id);
+typedef void (GLAD_API_PTR *PFNGLBEGINTRANSFORMFEEDBACKPROC)(GLenum primitiveMode);
+typedef void (GLAD_API_PTR *PFNGLBINDATTRIBLOCATIONPROC)(GLuint program, GLuint index, const GLchar * name);
+typedef void (GLAD_API_PTR *PFNGLBINDATTRIBLOCATIONARBPROC)(GLhandleARB programObj, GLuint index, const GLcharARB * name);
+typedef void (GLAD_API_PTR *PFNGLBINDBUFFERPROC)(GLenum target, GLuint buffer);
+typedef void (GLAD_API_PTR *PFNGLBINDBUFFERARBPROC)(GLenum target, GLuint buffer);
+typedef void (GLAD_API_PTR *PFNGLBINDBUFFERBASEPROC)(GLenum target, GLuint index, GLuint buffer);
+typedef void (GLAD_API_PTR *PFNGLBINDBUFFERRANGEPROC)(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+typedef void (GLAD_API_PTR *PFNGLBINDBUFFERSBASEPROC)(GLenum target, GLuint first, GLsizei count, const GLuint * buffers);
+typedef void (GLAD_API_PTR *PFNGLBINDBUFFERSRANGEPROC)(GLenum target, GLuint first, GLsizei count, const GLuint * buffers, const GLintptr * offsets, const GLsizeiptr * sizes);
+typedef void (GLAD_API_PTR *PFNGLBINDFRAGDATALOCATIONPROC)(GLuint program, GLuint color, const GLchar * name);
+typedef void (GLAD_API_PTR *PFNGLBINDFRAGDATALOCATIONINDEXEDPROC)(GLuint program, GLuint colorNumber, GLuint index, const GLchar * name);
+typedef void (GLAD_API_PTR *PFNGLBINDFRAMEBUFFERPROC)(GLenum target, GLuint framebuffer);
+typedef void (GLAD_API_PTR *PFNGLBINDFRAMEBUFFEREXTPROC)(GLenum target, GLuint framebuffer);
+typedef void (GLAD_API_PTR *PFNGLBINDIMAGETEXTUREPROC)(GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format);
+typedef void (GLAD_API_PTR *PFNGLBINDIMAGETEXTURESPROC)(GLuint first, GLsizei count, const GLuint * textures);
+typedef void (GLAD_API_PTR *PFNGLBINDPROGRAMARBPROC)(GLenum target, GLuint program);
+typedef void (GLAD_API_PTR *PFNGLBINDPROGRAMPIPELINEPROC)(GLuint pipeline);
+typedef void (GLAD_API_PTR *PFNGLBINDRENDERBUFFERPROC)(GLenum target, GLuint renderbuffer);
+typedef void (GLAD_API_PTR *PFNGLBINDRENDERBUFFEREXTPROC)(GLenum target, GLuint renderbuffer);
+typedef void (GLAD_API_PTR *PFNGLBINDSAMPLERPROC)(GLuint unit, GLuint sampler);
+typedef void (GLAD_API_PTR *PFNGLBINDSAMPLERSPROC)(GLuint first, GLsizei count, const GLuint * samplers);
+typedef void (GLAD_API_PTR *PFNGLBINDTEXTUREPROC)(GLenum target, GLuint texture);
+typedef void (GLAD_API_PTR *PFNGLBINDTEXTUREUNITPROC)(GLuint unit, GLuint texture);
+typedef void (GLAD_API_PTR *PFNGLBINDTEXTURESPROC)(GLuint first, GLsizei count, const GLuint * textures);
+typedef void (GLAD_API_PTR *PFNGLBINDTRANSFORMFEEDBACKPROC)(GLenum target, GLuint id);
+typedef void (GLAD_API_PTR *PFNGLBINDVERTEXARRAYPROC)(GLuint array);
+typedef void (GLAD_API_PTR *PFNGLBINDVERTEXBUFFERPROC)(GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride);
+typedef void (GLAD_API_PTR *PFNGLBINDVERTEXBUFFERSPROC)(GLuint first, GLsizei count, const GLuint * buffers, const GLintptr * offsets, const GLsizei * strides);
+typedef void (GLAD_API_PTR *PFNGLBITMAPXOESPROC)(GLsizei width, GLsizei height, GLfixed xorig, GLfixed yorig, GLfixed xmove, GLfixed ymove, const GLubyte * bitmap);
+typedef void (GLAD_API_PTR *PFNGLBLENDCOLORPROC)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+typedef void (GLAD_API_PTR *PFNGLBLENDCOLORXOESPROC)(GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha);
+typedef void (GLAD_API_PTR *PFNGLBLENDEQUATIONPROC)(GLenum mode);
+typedef void (GLAD_API_PTR *PFNGLBLENDEQUATIONSEPARATEPROC)(GLenum modeRGB, GLenum modeAlpha);
+typedef void (GLAD_API_PTR *PFNGLBLENDEQUATIONSEPARATEIPROC)(GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+typedef void (GLAD_API_PTR *PFNGLBLENDEQUATIONSEPARATEIARBPROC)(GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+typedef void (GLAD_API_PTR *PFNGLBLENDEQUATIONIPROC)(GLuint buf, GLenum mode);
+typedef void (GLAD_API_PTR *PFNGLBLENDEQUATIONIARBPROC)(GLuint buf, GLenum mode);
+typedef void (GLAD_API_PTR *PFNGLBLENDFUNCPROC)(GLenum sfactor, GLenum dfactor);
+typedef void (GLAD_API_PTR *PFNGLBLENDFUNCSEPARATEPROC)(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+typedef void (GLAD_API_PTR *PFNGLBLENDFUNCSEPARATEIPROC)(GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+typedef void (GLAD_API_PTR *PFNGLBLENDFUNCSEPARATEIARBPROC)(GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+typedef void (GLAD_API_PTR *PFNGLBLENDFUNCIPROC)(GLuint buf, GLenum src, GLenum dst);
+typedef void (GLAD_API_PTR *PFNGLBLENDFUNCIARBPROC)(GLuint buf, GLenum src, GLenum dst);
+typedef void (GLAD_API_PTR *PFNGLBLITFRAMEBUFFERPROC)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+typedef void (GLAD_API_PTR *PFNGLBLITFRAMEBUFFEREXTPROC)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+typedef void (GLAD_API_PTR *PFNGLBLITNAMEDFRAMEBUFFERPROC)(GLuint readFramebuffer, GLuint drawFramebuffer, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+typedef void (GLAD_API_PTR *PFNGLBUFFERDATAPROC)(GLenum target, GLsizeiptr size, const void * data, GLenum usage);
+typedef void (GLAD_API_PTR *PFNGLBUFFERDATAARBPROC)(GLenum target, GLsizeiptrARB size, const void * data, GLenum usage);
+typedef void (GLAD_API_PTR *PFNGLBUFFERSTORAGEPROC)(GLenum target, GLsizeiptr size, const void * data, GLbitfield flags);
+typedef void (GLAD_API_PTR *PFNGLBUFFERSUBDATAPROC)(GLenum target, GLintptr offset, GLsizeiptr size, const void * data);
+typedef void (GLAD_API_PTR *PFNGLBUFFERSUBDATAARBPROC)(GLenum target, GLintptrARB offset, GLsizeiptrARB size, const void * data);
+typedef GLenum (GLAD_API_PTR *PFNGLCHECKFRAMEBUFFERSTATUSPROC)(GLenum target);
+typedef GLenum (GLAD_API_PTR *PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)(GLenum target);
+typedef GLenum (GLAD_API_PTR *PFNGLCHECKNAMEDFRAMEBUFFERSTATUSPROC)(GLuint framebuffer, GLenum target);
+typedef void (GLAD_API_PTR *PFNGLCLAMPCOLORPROC)(GLenum target, GLenum clamp);
+typedef void (GLAD_API_PTR *PFNGLCLAMPCOLORARBPROC)(GLenum target, GLenum clamp);
+typedef void (GLAD_API_PTR *PFNGLCLEARPROC)(GLbitfield mask);
+typedef void (GLAD_API_PTR *PFNGLCLEARACCUMXOESPROC)(GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha);
+typedef void (GLAD_API_PTR *PFNGLCLEARBUFFERDATAPROC)(GLenum target, GLenum internalformat, GLenum format, GLenum type, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCLEARBUFFERSUBDATAPROC)(GLenum target, GLenum internalformat, GLintptr offset, GLsizeiptr size, GLenum format, GLenum type, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCLEARBUFFERFIPROC)(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
+typedef void (GLAD_API_PTR *PFNGLCLEARBUFFERFVPROC)(GLenum buffer, GLint drawbuffer, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLCLEARBUFFERIVPROC)(GLenum buffer, GLint drawbuffer, const GLint * value);
+typedef void (GLAD_API_PTR *PFNGLCLEARBUFFERUIVPROC)(GLenum buffer, GLint drawbuffer, const GLuint * value);
+typedef void (GLAD_API_PTR *PFNGLCLEARCOLORPROC)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+typedef void (GLAD_API_PTR *PFNGLCLEARCOLORXOESPROC)(GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha);
+typedef void (GLAD_API_PTR *PFNGLCLEARDEPTHPROC)(GLdouble depth);
+typedef void (GLAD_API_PTR *PFNGLCLEARDEPTHFPROC)(GLfloat d);
+typedef void (GLAD_API_PTR *PFNGLCLEARDEPTHXOESPROC)(GLfixed depth);
+typedef void (GLAD_API_PTR *PFNGLCLEARNAMEDBUFFERDATAPROC)(GLuint buffer, GLenum internalformat, GLenum format, GLenum type, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCLEARNAMEDBUFFERSUBDATAPROC)(GLuint buffer, GLenum internalformat, GLintptr offset, GLsizeiptr size, GLenum format, GLenum type, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCLEARNAMEDFRAMEBUFFERFIPROC)(GLuint framebuffer, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
+typedef void (GLAD_API_PTR *PFNGLCLEARNAMEDFRAMEBUFFERFVPROC)(GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLCLEARNAMEDFRAMEBUFFERIVPROC)(GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLint * value);
+typedef void (GLAD_API_PTR *PFNGLCLEARNAMEDFRAMEBUFFERUIVPROC)(GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLuint * value);
+typedef void (GLAD_API_PTR *PFNGLCLEARSTENCILPROC)(GLint s);
+typedef void (GLAD_API_PTR *PFNGLCLEARTEXIMAGEPROC)(GLuint texture, GLint level, GLenum format, GLenum type, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCLEARTEXSUBIMAGEPROC)(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCLIENTACTIVETEXTUREARBPROC)(GLenum texture);
+typedef GLenum (GLAD_API_PTR *PFNGLCLIENTWAITSYNCPROC)(GLsync sync, GLbitfield flags, GLuint64 timeout);
+typedef void (GLAD_API_PTR *PFNGLCLIPPLANEXOESPROC)(GLenum plane, const GLfixed * equation);
+typedef void (GLAD_API_PTR *PFNGLCOLOR3XOESPROC)(GLfixed red, GLfixed green, GLfixed blue);
+typedef void (GLAD_API_PTR *PFNGLCOLOR3XVOESPROC)(const GLfixed * components);
+typedef void (GLAD_API_PTR *PFNGLCOLOR4XOESPROC)(GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha);
+typedef void (GLAD_API_PTR *PFNGLCOLOR4XVOESPROC)(const GLfixed * components);
+typedef void (GLAD_API_PTR *PFNGLCOLORMASKPROC)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+typedef void (GLAD_API_PTR *PFNGLCOLORMASKIPROC)(GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
+typedef void (GLAD_API_PTR *PFNGLCOMPILESHADERPROC)(GLuint shader);
+typedef void (GLAD_API_PTR *PFNGLCOMPILESHADERARBPROC)(GLhandleARB shaderObj);
+typedef void (GLAD_API_PTR *PFNGLCOMPILESHADERINCLUDEARBPROC)(GLuint shader, GLsizei count, const GLchar *const* path, const GLint * length);
+typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXIMAGE1DPROC)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXIMAGE1DARBPROC)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXIMAGE2DPROC)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXIMAGE2DARBPROC)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXIMAGE3DPROC)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXIMAGE3DARBPROC)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC)(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC)(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXTURESUBIMAGE1DPROC)(GLuint texture, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXTURESUBIMAGE2DPROC)(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXTURESUBIMAGE3DPROC)(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCONVOLUTIONPARAMETERXOESPROC)(GLenum target, GLenum pname, GLfixed param);
+typedef void (GLAD_API_PTR *PFNGLCONVOLUTIONPARAMETERXVOESPROC)(GLenum target, GLenum pname, const GLfixed * params);
+typedef void (GLAD_API_PTR *PFNGLCOPYBUFFERSUBDATAPROC)(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+typedef void (GLAD_API_PTR *PFNGLCOPYIMAGESUBDATAPROC)(GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth);
+typedef void (GLAD_API_PTR *PFNGLCOPYNAMEDBUFFERSUBDATAPROC)(GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+typedef void (GLAD_API_PTR *PFNGLCOPYTEXIMAGE1DPROC)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border);
+typedef void (GLAD_API_PTR *PFNGLCOPYTEXIMAGE2DPROC)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+typedef void (GLAD_API_PTR *PFNGLCOPYTEXSUBIMAGE1DPROC)(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
+typedef void (GLAD_API_PTR *PFNGLCOPYTEXSUBIMAGE2DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GLAD_API_PTR *PFNGLCOPYTEXSUBIMAGE3DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GLAD_API_PTR *PFNGLCOPYTEXTURESUBIMAGE1DPROC)(GLuint texture, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
+typedef void (GLAD_API_PTR *PFNGLCOPYTEXTURESUBIMAGE2DPROC)(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GLAD_API_PTR *PFNGLCOPYTEXTURESUBIMAGE3DPROC)(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GLAD_API_PTR *PFNGLCREATEBUFFERSPROC)(GLsizei n, GLuint * buffers);
+typedef void (GLAD_API_PTR *PFNGLCREATEFRAMEBUFFERSPROC)(GLsizei n, GLuint * framebuffers);
+typedef GLuint (GLAD_API_PTR *PFNGLCREATEPROGRAMPROC)(void);
+typedef GLhandleARB (GLAD_API_PTR *PFNGLCREATEPROGRAMOBJECTARBPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLCREATEPROGRAMPIPELINESPROC)(GLsizei n, GLuint * pipelines);
+typedef void (GLAD_API_PTR *PFNGLCREATEQUERIESPROC)(GLenum target, GLsizei n, GLuint * ids);
+typedef void (GLAD_API_PTR *PFNGLCREATERENDERBUFFERSPROC)(GLsizei n, GLuint * renderbuffers);
+typedef void (GLAD_API_PTR *PFNGLCREATESAMPLERSPROC)(GLsizei n, GLuint * samplers);
+typedef GLuint (GLAD_API_PTR *PFNGLCREATESHADERPROC)(GLenum type);
+typedef GLhandleARB (GLAD_API_PTR *PFNGLCREATESHADEROBJECTARBPROC)(GLenum shaderType);
+typedef GLuint (GLAD_API_PTR *PFNGLCREATESHADERPROGRAMVPROC)(GLenum type, GLsizei count, const GLchar *const* strings);
+typedef void (GLAD_API_PTR *PFNGLCREATETEXTURESPROC)(GLenum target, GLsizei n, GLuint * textures);
+typedef void (GLAD_API_PTR *PFNGLCREATETRANSFORMFEEDBACKSPROC)(GLsizei n, GLuint * ids);
+typedef void (GLAD_API_PTR *PFNGLCREATEVERTEXARRAYSPROC)(GLsizei n, GLuint * arrays);
+typedef void (GLAD_API_PTR *PFNGLCULLFACEPROC)(GLenum mode);
+typedef void (GLAD_API_PTR *PFNGLDEBUGMESSAGECALLBACKPROC)(GLDEBUGPROC callback, const void * userParam);
+typedef void (GLAD_API_PTR *PFNGLDEBUGMESSAGECALLBACKARBPROC)(GLDEBUGPROCARB callback, const void * userParam);
+typedef void (GLAD_API_PTR *PFNGLDEBUGMESSAGECONTROLPROC)(GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint * ids, GLboolean enabled);
+typedef void (GLAD_API_PTR *PFNGLDEBUGMESSAGECONTROLARBPROC)(GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint * ids, GLboolean enabled);
+typedef void (GLAD_API_PTR *PFNGLDEBUGMESSAGEINSERTPROC)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar * buf);
+typedef void (GLAD_API_PTR *PFNGLDEBUGMESSAGEINSERTARBPROC)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar * buf);
+typedef void (GLAD_API_PTR *PFNGLDELETEBUFFERSPROC)(GLsizei n, const GLuint * buffers);
+typedef void (GLAD_API_PTR *PFNGLDELETEBUFFERSARBPROC)(GLsizei n, const GLuint * buffers);
+typedef void (GLAD_API_PTR *PFNGLDELETEFRAMEBUFFERSPROC)(GLsizei n, const GLuint * framebuffers);
+typedef void (GLAD_API_PTR *PFNGLDELETEFRAMEBUFFERSEXTPROC)(GLsizei n, const GLuint * framebuffers);
+typedef void (GLAD_API_PTR *PFNGLDELETENAMEDSTRINGARBPROC)(GLint namelen, const GLchar * name);
+typedef void (GLAD_API_PTR *PFNGLDELETEOBJECTARBPROC)(GLhandleARB obj);
+typedef void (GLAD_API_PTR *PFNGLDELETEPROGRAMPROC)(GLuint program);
+typedef void (GLAD_API_PTR *PFNGLDELETEPROGRAMPIPELINESPROC)(GLsizei n, const GLuint * pipelines);
+typedef void (GLAD_API_PTR *PFNGLDELETEPROGRAMSARBPROC)(GLsizei n, const GLuint * programs);
+typedef void (GLAD_API_PTR *PFNGLDELETEQUERIESPROC)(GLsizei n, const GLuint * ids);
+typedef void (GLAD_API_PTR *PFNGLDELETEQUERIESARBPROC)(GLsizei n, const GLuint * ids);
+typedef void (GLAD_API_PTR *PFNGLDELETERENDERBUFFERSPROC)(GLsizei n, const GLuint * renderbuffers);
+typedef void (GLAD_API_PTR *PFNGLDELETERENDERBUFFERSEXTPROC)(GLsizei n, const GLuint * renderbuffers);
+typedef void (GLAD_API_PTR *PFNGLDELETESAMPLERSPROC)(GLsizei count, const GLuint * samplers);
+typedef void (GLAD_API_PTR *PFNGLDELETESHADERPROC)(GLuint shader);
+typedef void (GLAD_API_PTR *PFNGLDELETESYNCPROC)(GLsync sync);
+typedef void (GLAD_API_PTR *PFNGLDELETETEXTURESPROC)(GLsizei n, const GLuint * textures);
+typedef void (GLAD_API_PTR *PFNGLDELETETRANSFORMFEEDBACKSPROC)(GLsizei n, const GLuint * ids);
+typedef void (GLAD_API_PTR *PFNGLDELETEVERTEXARRAYSPROC)(GLsizei n, const GLuint * arrays);
+typedef void (GLAD_API_PTR *PFNGLDEPTHFUNCPROC)(GLenum func);
+typedef void (GLAD_API_PTR *PFNGLDEPTHMASKPROC)(GLboolean flag);
+typedef void (GLAD_API_PTR *PFNGLDEPTHRANGEPROC)(GLdouble n, GLdouble f);
+typedef void (GLAD_API_PTR *PFNGLDEPTHRANGEARRAYVPROC)(GLuint first, GLsizei count, const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLDEPTHRANGEINDEXEDPROC)(GLuint index, GLdouble n, GLdouble f);
+typedef void (GLAD_API_PTR *PFNGLDEPTHRANGEFPROC)(GLfloat n, GLfloat f);
+typedef void (GLAD_API_PTR *PFNGLDEPTHRANGEXOESPROC)(GLfixed n, GLfixed f);
+typedef void (GLAD_API_PTR *PFNGLDETACHOBJECTARBPROC)(GLhandleARB containerObj, GLhandleARB attachedObj);
+typedef void (GLAD_API_PTR *PFNGLDETACHSHADERPROC)(GLuint program, GLuint shader);
+typedef void (GLAD_API_PTR *PFNGLDISABLEPROC)(GLenum cap);
+typedef void (GLAD_API_PTR *PFNGLDISABLEVERTEXARRAYATTRIBPROC)(GLuint vaobj, GLuint index);
+typedef void (GLAD_API_PTR *PFNGLDISABLEVERTEXATTRIBARRAYPROC)(GLuint index);
+typedef void (GLAD_API_PTR *PFNGLDISABLEVERTEXATTRIBARRAYARBPROC)(GLuint index);
+typedef void (GLAD_API_PTR *PFNGLDISABLEIPROC)(GLenum target, GLuint index);
+typedef void (GLAD_API_PTR *PFNGLDISPATCHCOMPUTEPROC)(GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z);
+typedef void (GLAD_API_PTR *PFNGLDISPATCHCOMPUTEGROUPSIZEARBPROC)(GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z, GLuint group_size_x, GLuint group_size_y, GLuint group_size_z);
+typedef void (GLAD_API_PTR *PFNGLDISPATCHCOMPUTEINDIRECTPROC)(GLintptr indirect);
+typedef void (GLAD_API_PTR *PFNGLDRAWARRAYSPROC)(GLenum mode, GLint first, GLsizei count);
+typedef void (GLAD_API_PTR *PFNGLDRAWARRAYSINDIRECTPROC)(GLenum mode, const void * indirect);
+typedef void (GLAD_API_PTR *PFNGLDRAWARRAYSINSTANCEDPROC)(GLenum mode, GLint first, GLsizei count, GLsizei instancecount);
+typedef void (GLAD_API_PTR *PFNGLDRAWARRAYSINSTANCEDARBPROC)(GLenum mode, GLint first, GLsizei count, GLsizei primcount);
+typedef void (GLAD_API_PTR *PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEPROC)(GLenum mode, GLint first, GLsizei count, GLsizei instancecount, GLuint baseinstance);
+typedef void (GLAD_API_PTR *PFNGLDRAWARRAYSINSTANCEDEXTPROC)(GLenum mode, GLint start, GLsizei count, GLsizei primcount);
+typedef void (GLAD_API_PTR *PFNGLDRAWBUFFERPROC)(GLenum buf);
+typedef void (GLAD_API_PTR *PFNGLDRAWBUFFERSPROC)(GLsizei n, const GLenum * bufs);
+typedef void (GLAD_API_PTR *PFNGLDRAWBUFFERSARBPROC)(GLsizei n, const GLenum * bufs);
+typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices);
+typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSBASEVERTEXPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLint basevertex);
+typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSINDIRECTPROC)(GLenum mode, GLenum type, const void * indirect);
+typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSINSTANCEDPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei instancecount);
+typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSINSTANCEDARBPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei primcount);
+typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei instancecount, GLuint baseinstance);
+typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei instancecount, GLint basevertex);
+typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei instancecount, GLint basevertex, GLuint baseinstance);
+typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSINSTANCEDEXTPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei primcount);
+typedef void (GLAD_API_PTR *PFNGLDRAWRANGEELEMENTSPROC)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void * indices);
+typedef void (GLAD_API_PTR *PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void * indices, GLint basevertex);
+typedef void (GLAD_API_PTR *PFNGLDRAWTRANSFORMFEEDBACKPROC)(GLenum mode, GLuint id);
+typedef void (GLAD_API_PTR *PFNGLDRAWTRANSFORMFEEDBACKINSTANCEDPROC)(GLenum mode, GLuint id, GLsizei instancecount);
+typedef void (GLAD_API_PTR *PFNGLDRAWTRANSFORMFEEDBACKSTREAMPROC)(GLenum mode, GLuint id, GLuint stream);
+typedef void (GLAD_API_PTR *PFNGLDRAWTRANSFORMFEEDBACKSTREAMINSTANCEDPROC)(GLenum mode, GLuint id, GLuint stream, GLsizei instancecount);
+typedef void (GLAD_API_PTR *PFNGLENABLEPROC)(GLenum cap);
+typedef void (GLAD_API_PTR *PFNGLENABLEVERTEXARRAYATTRIBPROC)(GLuint vaobj, GLuint index);
+typedef void (GLAD_API_PTR *PFNGLENABLEVERTEXATTRIBARRAYPROC)(GLuint index);
+typedef void (GLAD_API_PTR *PFNGLENABLEVERTEXATTRIBARRAYARBPROC)(GLuint index);
+typedef void (GLAD_API_PTR *PFNGLENABLEIPROC)(GLenum target, GLuint index);
+typedef void (GLAD_API_PTR *PFNGLENDCONDITIONALRENDERPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLENDQUERYPROC)(GLenum target);
+typedef void (GLAD_API_PTR *PFNGLENDQUERYARBPROC)(GLenum target);
+typedef void (GLAD_API_PTR *PFNGLENDQUERYINDEXEDPROC)(GLenum target, GLuint index);
+typedef void (GLAD_API_PTR *PFNGLENDTRANSFORMFEEDBACKPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLEVALCOORD1XOESPROC)(GLfixed u);
+typedef void (GLAD_API_PTR *PFNGLEVALCOORD1XVOESPROC)(const GLfixed * coords);
+typedef void (GLAD_API_PTR *PFNGLEVALCOORD2XOESPROC)(GLfixed u, GLfixed v);
+typedef void (GLAD_API_PTR *PFNGLEVALCOORD2XVOESPROC)(const GLfixed * coords);
+typedef void (GLAD_API_PTR *PFNGLEVALUATEDEPTHVALUESARBPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLFEEDBACKBUFFERXOESPROC)(GLsizei n, GLenum type, const GLfixed * buffer);
+typedef GLsync (GLAD_API_PTR *PFNGLFENCESYNCPROC)(GLenum condition, GLbitfield flags);
+typedef void (GLAD_API_PTR *PFNGLFINISHPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLFLUSHPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLFLUSHMAPPEDBUFFERRANGEPROC)(GLenum target, GLintptr offset, GLsizeiptr length);
+typedef void (GLAD_API_PTR *PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEPROC)(GLuint buffer, GLintptr offset, GLsizeiptr length);
+typedef void (GLAD_API_PTR *PFNGLFOGCOORDPOINTEREXTPROC)(GLenum type, GLsizei stride, const void * pointer);
+typedef void (GLAD_API_PTR *PFNGLFOGCOORDDEXTPROC)(GLdouble coord);
+typedef void (GLAD_API_PTR *PFNGLFOGCOORDDVEXTPROC)(const GLdouble * coord);
+typedef void (GLAD_API_PTR *PFNGLFOGCOORDFEXTPROC)(GLfloat coord);
+typedef void (GLAD_API_PTR *PFNGLFOGCOORDFVEXTPROC)(const GLfloat * coord);
+typedef void (GLAD_API_PTR *PFNGLFOGXOESPROC)(GLenum pname, GLfixed param);
+typedef void (GLAD_API_PTR *PFNGLFOGXVOESPROC)(GLenum pname, const GLfixed * param);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERPARAMETERIPROC)(GLenum target, GLenum pname, GLint param);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERRENDERBUFFERPROC)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERSAMPLELOCATIONSFVARBPROC)(GLenum target, GLuint start, GLsizei count, const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTUREPROC)(GLenum target, GLenum attachment, GLuint texture, GLint level);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURE1DPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURE1DEXTPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURE2DPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURE3DPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURE3DEXTPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTUREARBPROC)(GLenum target, GLenum attachment, GLuint texture, GLint level);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTUREFACEARBPROC)(GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURELAYERPROC)(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURELAYERARBPROC)(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+typedef void (GLAD_API_PTR *PFNGLFRONTFACEPROC)(GLenum mode);
+typedef void (GLAD_API_PTR *PFNGLFRUSTUMXOESPROC)(GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f);
+typedef void (GLAD_API_PTR *PFNGLGENBUFFERSPROC)(GLsizei n, GLuint * buffers);
+typedef void (GLAD_API_PTR *PFNGLGENBUFFERSARBPROC)(GLsizei n, GLuint * buffers);
+typedef void (GLAD_API_PTR *PFNGLGENFRAMEBUFFERSPROC)(GLsizei n, GLuint * framebuffers);
+typedef void (GLAD_API_PTR *PFNGLGENFRAMEBUFFERSEXTPROC)(GLsizei n, GLuint * framebuffers);
+typedef void (GLAD_API_PTR *PFNGLGENPROGRAMPIPELINESPROC)(GLsizei n, GLuint * pipelines);
+typedef void (GLAD_API_PTR *PFNGLGENPROGRAMSARBPROC)(GLsizei n, GLuint * programs);
+typedef void (GLAD_API_PTR *PFNGLGENQUERIESPROC)(GLsizei n, GLuint * ids);
+typedef void (GLAD_API_PTR *PFNGLGENQUERIESARBPROC)(GLsizei n, GLuint * ids);
+typedef void (GLAD_API_PTR *PFNGLGENRENDERBUFFERSPROC)(GLsizei n, GLuint * renderbuffers);
+typedef void (GLAD_API_PTR *PFNGLGENRENDERBUFFERSEXTPROC)(GLsizei n, GLuint * renderbuffers);
+typedef void (GLAD_API_PTR *PFNGLGENSAMPLERSPROC)(GLsizei count, GLuint * samplers);
+typedef void (GLAD_API_PTR *PFNGLGENTEXTURESPROC)(GLsizei n, GLuint * textures);
+typedef void (GLAD_API_PTR *PFNGLGENTRANSFORMFEEDBACKSPROC)(GLsizei n, GLuint * ids);
+typedef void (GLAD_API_PTR *PFNGLGENVERTEXARRAYSPROC)(GLsizei n, GLuint * arrays);
+typedef void (GLAD_API_PTR *PFNGLGENERATEMIPMAPPROC)(GLenum target);
+typedef void (GLAD_API_PTR *PFNGLGENERATEMIPMAPEXTPROC)(GLenum target);
+typedef void (GLAD_API_PTR *PFNGLGENERATETEXTUREMIPMAPPROC)(GLuint texture);
+typedef void (GLAD_API_PTR *PFNGLGETACTIVEATOMICCOUNTERBUFFERIVPROC)(GLuint program, GLuint bufferIndex, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETACTIVEATTRIBPROC)(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * name);
+typedef void (GLAD_API_PTR *PFNGLGETACTIVEATTRIBARBPROC)(GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei * length, GLint * size, GLenum * type, GLcharARB * name);
+typedef void (GLAD_API_PTR *PFNGLGETACTIVESUBROUTINENAMEPROC)(GLuint program, GLenum shadertype, GLuint index, GLsizei bufSize, GLsizei * length, GLchar * name);
+typedef void (GLAD_API_PTR *PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC)(GLuint program, GLenum shadertype, GLuint index, GLsizei bufSize, GLsizei * length, GLchar * name);
+typedef void (GLAD_API_PTR *PFNGLGETACTIVESUBROUTINEUNIFORMIVPROC)(GLuint program, GLenum shadertype, GLuint index, GLenum pname, GLint * values);
+typedef void (GLAD_API_PTR *PFNGLGETACTIVEUNIFORMPROC)(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * name);
+typedef void (GLAD_API_PTR *PFNGLGETACTIVEUNIFORMARBPROC)(GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei * length, GLint * size, GLenum * type, GLcharARB * name);
+typedef void (GLAD_API_PTR *PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC)(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei * length, GLchar * uniformBlockName);
+typedef void (GLAD_API_PTR *PFNGLGETACTIVEUNIFORMBLOCKIVPROC)(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETACTIVEUNIFORMNAMEPROC)(GLuint program, GLuint uniformIndex, GLsizei bufSize, GLsizei * length, GLchar * uniformName);
+typedef void (GLAD_API_PTR *PFNGLGETACTIVEUNIFORMSIVPROC)(GLuint program, GLsizei uniformCount, const GLuint * uniformIndices, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETATTACHEDOBJECTSARBPROC)(GLhandleARB containerObj, GLsizei maxCount, GLsizei * count, GLhandleARB * obj);
+typedef void (GLAD_API_PTR *PFNGLGETATTACHEDSHADERSPROC)(GLuint program, GLsizei maxCount, GLsizei * count, GLuint * shaders);
+typedef GLint (GLAD_API_PTR *PFNGLGETATTRIBLOCATIONPROC)(GLuint program, const GLchar * name);
+typedef GLint (GLAD_API_PTR *PFNGLGETATTRIBLOCATIONARBPROC)(GLhandleARB programObj, const GLcharARB * name);
+typedef void (GLAD_API_PTR *PFNGLGETBOOLEANI_VPROC)(GLenum target, GLuint index, GLboolean * data);
+typedef void (GLAD_API_PTR *PFNGLGETBOOLEANVPROC)(GLenum pname, GLboolean * data);
+typedef void (GLAD_API_PTR *PFNGLGETBUFFERPARAMETERI64VPROC)(GLenum target, GLenum pname, GLint64 * params);
+typedef void (GLAD_API_PTR *PFNGLGETBUFFERPARAMETERIVPROC)(GLenum target, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETBUFFERPARAMETERIVARBPROC)(GLenum target, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETBUFFERPOINTERVPROC)(GLenum target, GLenum pname, void ** params);
+typedef void (GLAD_API_PTR *PFNGLGETBUFFERPOINTERVARBPROC)(GLenum target, GLenum pname, void ** params);
+typedef void (GLAD_API_PTR *PFNGLGETBUFFERSUBDATAPROC)(GLenum target, GLintptr offset, GLsizeiptr size, void * data);
+typedef void (GLAD_API_PTR *PFNGLGETBUFFERSUBDATAARBPROC)(GLenum target, GLintptrARB offset, GLsizeiptrARB size, void * data);
+typedef void (GLAD_API_PTR *PFNGLGETCLIPPLANEXOESPROC)(GLenum plane, GLfixed * equation);
+typedef void (GLAD_API_PTR *PFNGLGETCOMPRESSEDTEXIMAGEPROC)(GLenum target, GLint level, void * img);
+typedef void (GLAD_API_PTR *PFNGLGETCOMPRESSEDTEXIMAGEARBPROC)(GLenum target, GLint level, void * img);
+typedef void (GLAD_API_PTR *PFNGLGETCOMPRESSEDTEXTUREIMAGEPROC)(GLuint texture, GLint level, GLsizei bufSize, void * pixels);
+typedef void (GLAD_API_PTR *PFNGLGETCOMPRESSEDTEXTURESUBIMAGEPROC)(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei bufSize, void * pixels);
+typedef void (GLAD_API_PTR *PFNGLGETCONVOLUTIONPARAMETERXVOESPROC)(GLenum target, GLenum pname, GLfixed * params);
+typedef GLuint (GLAD_API_PTR *PFNGLGETDEBUGMESSAGELOGPROC)(GLuint count, GLsizei bufSize, GLenum * sources, GLenum * types, GLuint * ids, GLenum * severities, GLsizei * lengths, GLchar * messageLog);
+typedef GLuint (GLAD_API_PTR *PFNGLGETDEBUGMESSAGELOGARBPROC)(GLuint count, GLsizei bufSize, GLenum * sources, GLenum * types, GLuint * ids, GLenum * severities, GLsizei * lengths, GLchar * messageLog);
+typedef void (GLAD_API_PTR *PFNGLGETDOUBLEI_VPROC)(GLenum target, GLuint index, GLdouble * data);
+typedef void (GLAD_API_PTR *PFNGLGETDOUBLEVPROC)(GLenum pname, GLdouble * data);
+typedef GLenum (GLAD_API_PTR *PFNGLGETERRORPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLGETFIXEDVOESPROC)(GLenum pname, GLfixed * params);
+typedef void (GLAD_API_PTR *PFNGLGETFLOATI_VPROC)(GLenum target, GLuint index, GLfloat * data);
+typedef void (GLAD_API_PTR *PFNGLGETFLOATVPROC)(GLenum pname, GLfloat * data);
+typedef GLint (GLAD_API_PTR *PFNGLGETFRAGDATAINDEXPROC)(GLuint program, const GLchar * name);
+typedef GLint (GLAD_API_PTR *PFNGLGETFRAGDATALOCATIONPROC)(GLuint program, const GLchar * name);
+typedef void (GLAD_API_PTR *PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC)(GLenum target, GLenum attachment, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC)(GLenum target, GLenum attachment, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETFRAMEBUFFERPARAMETERIVPROC)(GLenum target, GLenum pname, GLint * params);
+typedef GLhandleARB (GLAD_API_PTR *PFNGLGETHANDLEARBPROC)(GLenum pname);
+typedef void (GLAD_API_PTR *PFNGLGETHISTOGRAMPARAMETERXVOESPROC)(GLenum target, GLenum pname, GLfixed * params);
+typedef void (GLAD_API_PTR *PFNGLGETINFOLOGARBPROC)(GLhandleARB obj, GLsizei maxLength, GLsizei * length, GLcharARB * infoLog);
+typedef void (GLAD_API_PTR *PFNGLGETINTEGER64I_VPROC)(GLenum target, GLuint index, GLint64 * data);
+typedef void (GLAD_API_PTR *PFNGLGETINTEGER64VPROC)(GLenum pname, GLint64 * data);
+typedef void (GLAD_API_PTR *PFNGLGETINTEGERI_VPROC)(GLenum target, GLuint index, GLint * data);
+typedef void (GLAD_API_PTR *PFNGLGETINTEGERVPROC)(GLenum pname, GLint * data);
+typedef void (GLAD_API_PTR *PFNGLGETINTERNALFORMATI64VPROC)(GLenum target, GLenum internalformat, GLenum pname, GLsizei count, GLint64 * params);
+typedef void (GLAD_API_PTR *PFNGLGETINTERNALFORMATIVPROC)(GLenum target, GLenum internalformat, GLenum pname, GLsizei count, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETLIGHTXOESPROC)(GLenum light, GLenum pname, GLfixed * params);
+typedef void (GLAD_API_PTR *PFNGLGETMAPXVOESPROC)(GLenum target, GLenum query, GLfixed * v);
+typedef void (GLAD_API_PTR *PFNGLGETMATERIALXOESPROC)(GLenum face, GLenum pname, GLfixed param);
+typedef void (GLAD_API_PTR *PFNGLGETMULTISAMPLEFVPROC)(GLenum pname, GLuint index, GLfloat * val);
+typedef void (GLAD_API_PTR *PFNGLGETNAMEDBUFFERPARAMETERI64VPROC)(GLuint buffer, GLenum pname, GLint64 * params);
+typedef void (GLAD_API_PTR *PFNGLGETNAMEDBUFFERPARAMETERIVPROC)(GLuint buffer, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETNAMEDBUFFERPOINTERVPROC)(GLuint buffer, GLenum pname, void ** params);
+typedef void (GLAD_API_PTR *PFNGLGETNAMEDBUFFERSUBDATAPROC)(GLuint buffer, GLintptr offset, GLsizeiptr size, void * data);
+typedef void (GLAD_API_PTR *PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVPROC)(GLuint framebuffer, GLenum attachment, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVPROC)(GLuint framebuffer, GLenum pname, GLint * param);
+typedef void (GLAD_API_PTR *PFNGLGETNAMEDRENDERBUFFERPARAMETERIVPROC)(GLuint renderbuffer, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETNAMEDSTRINGARBPROC)(GLint namelen, const GLchar * name, GLsizei bufSize, GLint * stringlen, GLchar * string);
+typedef void (GLAD_API_PTR *PFNGLGETNAMEDSTRINGIVARBPROC)(GLint namelen, const GLchar * name, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETOBJECTLABELPROC)(GLenum identifier, GLuint name, GLsizei bufSize, GLsizei * length, GLchar * label);
+typedef void (GLAD_API_PTR *PFNGLGETOBJECTPARAMETERFVARBPROC)(GLhandleARB obj, GLenum pname, GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLGETOBJECTPARAMETERIVARBPROC)(GLhandleARB obj, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETOBJECTPTRLABELPROC)(const void * ptr, GLsizei bufSize, GLsizei * length, GLchar * label);
+typedef void (GLAD_API_PTR *PFNGLGETPIXELMAPXVPROC)(GLenum map, GLint size, GLfixed * values);
+typedef void (GLAD_API_PTR *PFNGLGETPOINTERVPROC)(GLenum pname, void ** params);
+typedef void (GLAD_API_PTR *PFNGLGETPROGRAMBINARYPROC)(GLuint program, GLsizei bufSize, GLsizei * length, GLenum * binaryFormat, void * binary);
+typedef void (GLAD_API_PTR *PFNGLGETPROGRAMENVPARAMETERDVARBPROC)(GLenum target, GLuint index, GLdouble * params);
+typedef void (GLAD_API_PTR *PFNGLGETPROGRAMENVPARAMETERFVARBPROC)(GLenum target, GLuint index, GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLGETPROGRAMINFOLOGPROC)(GLuint program, GLsizei bufSize, GLsizei * length, GLchar * infoLog);
+typedef void (GLAD_API_PTR *PFNGLGETPROGRAMINTERFACEIVPROC)(GLuint program, GLenum programInterface, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC)(GLenum target, GLuint index, GLdouble * params);
+typedef void (GLAD_API_PTR *PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC)(GLenum target, GLuint index, GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLGETPROGRAMPIPELINEINFOLOGPROC)(GLuint pipeline, GLsizei bufSize, GLsizei * length, GLchar * infoLog);
+typedef void (GLAD_API_PTR *PFNGLGETPROGRAMPIPELINEIVPROC)(GLuint pipeline, GLenum pname, GLint * params);
+typedef GLuint (GLAD_API_PTR *PFNGLGETPROGRAMRESOURCEINDEXPROC)(GLuint program, GLenum programInterface, const GLchar * name);
+typedef GLint (GLAD_API_PTR *PFNGLGETPROGRAMRESOURCELOCATIONPROC)(GLuint program, GLenum programInterface, const GLchar * name);
+typedef GLint (GLAD_API_PTR *PFNGLGETPROGRAMRESOURCELOCATIONINDEXPROC)(GLuint program, GLenum programInterface, const GLchar * name);
+typedef void (GLAD_API_PTR *PFNGLGETPROGRAMRESOURCENAMEPROC)(GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei * length, GLchar * name);
+typedef void (GLAD_API_PTR *PFNGLGETPROGRAMRESOURCEIVPROC)(GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum * props, GLsizei count, GLsizei * length, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETPROGRAMSTAGEIVPROC)(GLuint program, GLenum shadertype, GLenum pname, GLint * values);
+typedef void (GLAD_API_PTR *PFNGLGETPROGRAMSTRINGARBPROC)(GLenum target, GLenum pname, void * string);
+typedef void (GLAD_API_PTR *PFNGLGETPROGRAMIVPROC)(GLuint program, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETPROGRAMIVARBPROC)(GLenum target, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETQUERYBUFFEROBJECTI64VPROC)(GLuint id, GLuint buffer, GLenum pname, GLintptr offset);
+typedef void (GLAD_API_PTR *PFNGLGETQUERYBUFFEROBJECTIVPROC)(GLuint id, GLuint buffer, GLenum pname, GLintptr offset);
+typedef void (GLAD_API_PTR *PFNGLGETQUERYBUFFEROBJECTUI64VPROC)(GLuint id, GLuint buffer, GLenum pname, GLintptr offset);
+typedef void (GLAD_API_PTR *PFNGLGETQUERYBUFFEROBJECTUIVPROC)(GLuint id, GLuint buffer, GLenum pname, GLintptr offset);
+typedef void (GLAD_API_PTR *PFNGLGETQUERYINDEXEDIVPROC)(GLenum target, GLuint index, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETQUERYOBJECTI64VPROC)(GLuint id, GLenum pname, GLint64 * params);
+typedef void (GLAD_API_PTR *PFNGLGETQUERYOBJECTIVPROC)(GLuint id, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETQUERYOBJECTIVARBPROC)(GLuint id, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETQUERYOBJECTUI64VPROC)(GLuint id, GLenum pname, GLuint64 * params);
+typedef void (GLAD_API_PTR *PFNGLGETQUERYOBJECTUIVPROC)(GLuint id, GLenum pname, GLuint * params);
+typedef void (GLAD_API_PTR *PFNGLGETQUERYOBJECTUIVARBPROC)(GLuint id, GLenum pname, GLuint * params);
+typedef void (GLAD_API_PTR *PFNGLGETQUERYIVPROC)(GLenum target, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETQUERYIVARBPROC)(GLenum target, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETRENDERBUFFERPARAMETERIVPROC)(GLenum target, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC)(GLenum target, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETSAMPLERPARAMETERIIVPROC)(GLuint sampler, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETSAMPLERPARAMETERIUIVPROC)(GLuint sampler, GLenum pname, GLuint * params);
+typedef void (GLAD_API_PTR *PFNGLGETSAMPLERPARAMETERFVPROC)(GLuint sampler, GLenum pname, GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLGETSAMPLERPARAMETERIVPROC)(GLuint sampler, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETSHADERINFOLOGPROC)(GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * infoLog);
+typedef void (GLAD_API_PTR *PFNGLGETSHADERPRECISIONFORMATPROC)(GLenum shadertype, GLenum precisiontype, GLint * range, GLint * precision);
+typedef void (GLAD_API_PTR *PFNGLGETSHADERSOURCEPROC)(GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * source);
+typedef void (GLAD_API_PTR *PFNGLGETSHADERSOURCEARBPROC)(GLhandleARB obj, GLsizei maxLength, GLsizei * length, GLcharARB * source);
+typedef void (GLAD_API_PTR *PFNGLGETSHADERIVPROC)(GLuint shader, GLenum pname, GLint * params);
+typedef const GLubyte * (GLAD_API_PTR *PFNGLGETSTRINGPROC)(GLenum name);
+typedef const GLubyte * (GLAD_API_PTR *PFNGLGETSTRINGIPROC)(GLenum name, GLuint index);
+typedef GLuint (GLAD_API_PTR *PFNGLGETSUBROUTINEINDEXPROC)(GLuint program, GLenum shadertype, const GLchar * name);
+typedef GLint (GLAD_API_PTR *PFNGLGETSUBROUTINEUNIFORMLOCATIONPROC)(GLuint program, GLenum shadertype, const GLchar * name);
+typedef void (GLAD_API_PTR *PFNGLGETSYNCIVPROC)(GLsync sync, GLenum pname, GLsizei count, GLsizei * length, GLint * values);
+typedef void (GLAD_API_PTR *PFNGLGETTEXENVXVOESPROC)(GLenum target, GLenum pname, GLfixed * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXGENXVOESPROC)(GLenum coord, GLenum pname, GLfixed * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXIMAGEPROC)(GLenum target, GLint level, GLenum format, GLenum type, void * pixels);
+typedef void (GLAD_API_PTR *PFNGLGETTEXLEVELPARAMETERFVPROC)(GLenum target, GLint level, GLenum pname, GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXLEVELPARAMETERIVPROC)(GLenum target, GLint level, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXLEVELPARAMETERXVOESPROC)(GLenum target, GLint level, GLenum pname, GLfixed * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXPARAMETERIIVPROC)(GLenum target, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXPARAMETERIUIVPROC)(GLenum target, GLenum pname, GLuint * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXPARAMETERFVPROC)(GLenum target, GLenum pname, GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXPARAMETERIVPROC)(GLenum target, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXPARAMETERXVOESPROC)(GLenum target, GLenum pname, GLfixed * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXTUREIMAGEPROC)(GLuint texture, GLint level, GLenum format, GLenum type, GLsizei bufSize, void * pixels);
+typedef void (GLAD_API_PTR *PFNGLGETTEXTURELEVELPARAMETERFVPROC)(GLuint texture, GLint level, GLenum pname, GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXTURELEVELPARAMETERIVPROC)(GLuint texture, GLint level, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXTUREPARAMETERIIVPROC)(GLuint texture, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXTUREPARAMETERIUIVPROC)(GLuint texture, GLenum pname, GLuint * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXTUREPARAMETERFVPROC)(GLuint texture, GLenum pname, GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXTUREPARAMETERIVPROC)(GLuint texture, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXTURESUBIMAGEPROC)(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLsizei bufSize, void * pixels);
+typedef void (GLAD_API_PTR *PFNGLGETTRANSFORMFEEDBACKVARYINGPROC)(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLsizei * size, GLenum * type, GLchar * name);
+typedef void (GLAD_API_PTR *PFNGLGETTRANSFORMFEEDBACKI64_VPROC)(GLuint xfb, GLenum pname, GLuint index, GLint64 * param);
+typedef void (GLAD_API_PTR *PFNGLGETTRANSFORMFEEDBACKI_VPROC)(GLuint xfb, GLenum pname, GLuint index, GLint * param);
+typedef void (GLAD_API_PTR *PFNGLGETTRANSFORMFEEDBACKIVPROC)(GLuint xfb, GLenum pname, GLint * param);
+typedef GLuint (GLAD_API_PTR *PFNGLGETUNIFORMBLOCKINDEXPROC)(GLuint program, const GLchar * uniformBlockName);
+typedef void (GLAD_API_PTR *PFNGLGETUNIFORMINDICESPROC)(GLuint program, GLsizei uniformCount, const GLchar *const* uniformNames, GLuint * uniformIndices);
+typedef GLint (GLAD_API_PTR *PFNGLGETUNIFORMLOCATIONPROC)(GLuint program, const GLchar * name);
+typedef GLint (GLAD_API_PTR *PFNGLGETUNIFORMLOCATIONARBPROC)(GLhandleARB programObj, const GLcharARB * name);
+typedef void (GLAD_API_PTR *PFNGLGETUNIFORMSUBROUTINEUIVPROC)(GLenum shadertype, GLint location, GLuint * params);
+typedef void (GLAD_API_PTR *PFNGLGETUNIFORMDVPROC)(GLuint program, GLint location, GLdouble * params);
+typedef void (GLAD_API_PTR *PFNGLGETUNIFORMFVPROC)(GLuint program, GLint location, GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLGETUNIFORMFVARBPROC)(GLhandleARB programObj, GLint location, GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLGETUNIFORMI64VARBPROC)(GLuint program, GLint location, GLint64 * params);
+typedef void (GLAD_API_PTR *PFNGLGETUNIFORMIVPROC)(GLuint program, GLint location, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETUNIFORMIVARBPROC)(GLhandleARB programObj, GLint location, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETUNIFORMUI64VARBPROC)(GLuint program, GLint location, GLuint64 * params);
+typedef void (GLAD_API_PTR *PFNGLGETUNIFORMUIVPROC)(GLuint program, GLint location, GLuint * params);
+typedef void (GLAD_API_PTR *PFNGLGETVERTEXARRAYINDEXED64IVPROC)(GLuint vaobj, GLuint index, GLenum pname, GLint64 * param);
+typedef void (GLAD_API_PTR *PFNGLGETVERTEXARRAYINDEXEDIVPROC)(GLuint vaobj, GLuint index, GLenum pname, GLint * param);
+typedef void (GLAD_API_PTR *PFNGLGETVERTEXARRAYIVPROC)(GLuint vaobj, GLenum pname, GLint * param);
+typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBIIVPROC)(GLuint index, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBIUIVPROC)(GLuint index, GLenum pname, GLuint * params);
+typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBLDVPROC)(GLuint index, GLenum pname, GLdouble * params);
+typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBPOINTERVPROC)(GLuint index, GLenum pname, void ** pointer);
+typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBPOINTERVARBPROC)(GLuint index, GLenum pname, void ** pointer);
+typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBDVPROC)(GLuint index, GLenum pname, GLdouble * params);
+typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBDVARBPROC)(GLuint index, GLenum pname, GLdouble * params);
+typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBFVPROC)(GLuint index, GLenum pname, GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBFVARBPROC)(GLuint index, GLenum pname, GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBIVPROC)(GLuint index, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBIVARBPROC)(GLuint index, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETNUNIFORMI64VARBPROC)(GLuint program, GLint location, GLsizei bufSize, GLint64 * params);
+typedef void (GLAD_API_PTR *PFNGLGETNUNIFORMUI64VARBPROC)(GLuint program, GLint location, GLsizei bufSize, GLuint64 * params);
+typedef void (GLAD_API_PTR *PFNGLHINTPROC)(GLenum target, GLenum mode);
+typedef void (GLAD_API_PTR *PFNGLINDEXXOESPROC)(GLfixed component);
+typedef void (GLAD_API_PTR *PFNGLINDEXXVOESPROC)(const GLfixed * component);
+typedef void (GLAD_API_PTR *PFNGLINVALIDATEBUFFERDATAPROC)(GLuint buffer);
+typedef void (GLAD_API_PTR *PFNGLINVALIDATEBUFFERSUBDATAPROC)(GLuint buffer, GLintptr offset, GLsizeiptr length);
+typedef void (GLAD_API_PTR *PFNGLINVALIDATEFRAMEBUFFERPROC)(GLenum target, GLsizei numAttachments, const GLenum * attachments);
+typedef void (GLAD_API_PTR *PFNGLINVALIDATENAMEDFRAMEBUFFERDATAPROC)(GLuint framebuffer, GLsizei numAttachments, const GLenum * attachments);
+typedef void (GLAD_API_PTR *PFNGLINVALIDATENAMEDFRAMEBUFFERSUBDATAPROC)(GLuint framebuffer, GLsizei numAttachments, const GLenum * attachments, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GLAD_API_PTR *PFNGLINVALIDATESUBFRAMEBUFFERPROC)(GLenum target, GLsizei numAttachments, const GLenum * attachments, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GLAD_API_PTR *PFNGLINVALIDATETEXIMAGEPROC)(GLuint texture, GLint level);
+typedef void (GLAD_API_PTR *PFNGLINVALIDATETEXSUBIMAGEPROC)(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth);
+typedef GLboolean (GLAD_API_PTR *PFNGLISBUFFERPROC)(GLuint buffer);
+typedef GLboolean (GLAD_API_PTR *PFNGLISBUFFERARBPROC)(GLuint buffer);
+typedef GLboolean (GLAD_API_PTR *PFNGLISENABLEDPROC)(GLenum cap);
+typedef GLboolean (GLAD_API_PTR *PFNGLISENABLEDIPROC)(GLenum target, GLuint index);
+typedef GLboolean (GLAD_API_PTR *PFNGLISFRAMEBUFFERPROC)(GLuint framebuffer);
+typedef GLboolean (GLAD_API_PTR *PFNGLISFRAMEBUFFEREXTPROC)(GLuint framebuffer);
+typedef GLboolean (GLAD_API_PTR *PFNGLISNAMEDSTRINGARBPROC)(GLint namelen, const GLchar * name);
+typedef GLboolean (GLAD_API_PTR *PFNGLISPROGRAMPROC)(GLuint program);
+typedef GLboolean (GLAD_API_PTR *PFNGLISPROGRAMARBPROC)(GLuint program);
+typedef GLboolean (GLAD_API_PTR *PFNGLISPROGRAMPIPELINEPROC)(GLuint pipeline);
+typedef GLboolean (GLAD_API_PTR *PFNGLISQUERYPROC)(GLuint id);
+typedef GLboolean (GLAD_API_PTR *PFNGLISQUERYARBPROC)(GLuint id);
+typedef GLboolean (GLAD_API_PTR *PFNGLISRENDERBUFFERPROC)(GLuint renderbuffer);
+typedef GLboolean (GLAD_API_PTR *PFNGLISRENDERBUFFEREXTPROC)(GLuint renderbuffer);
+typedef GLboolean (GLAD_API_PTR *PFNGLISSAMPLERPROC)(GLuint sampler);
+typedef GLboolean (GLAD_API_PTR *PFNGLISSHADERPROC)(GLuint shader);
+typedef GLboolean (GLAD_API_PTR *PFNGLISSYNCPROC)(GLsync sync);
+typedef GLboolean (GLAD_API_PTR *PFNGLISTEXTUREPROC)(GLuint texture);
+typedef GLboolean (GLAD_API_PTR *PFNGLISTRANSFORMFEEDBACKPROC)(GLuint id);
+typedef GLboolean (GLAD_API_PTR *PFNGLISVERTEXARRAYPROC)(GLuint array);
+typedef void (GLAD_API_PTR *PFNGLLIGHTMODELXOESPROC)(GLenum pname, GLfixed param);
+typedef void (GLAD_API_PTR *PFNGLLIGHTMODELXVOESPROC)(GLenum pname, const GLfixed * param);
+typedef void (GLAD_API_PTR *PFNGLLIGHTXOESPROC)(GLenum light, GLenum pname, GLfixed param);
+typedef void (GLAD_API_PTR *PFNGLLIGHTXVOESPROC)(GLenum light, GLenum pname, const GLfixed * params);
+typedef void (GLAD_API_PTR *PFNGLLINEWIDTHPROC)(GLfloat width);
+typedef void (GLAD_API_PTR *PFNGLLINEWIDTHXOESPROC)(GLfixed width);
+typedef void (GLAD_API_PTR *PFNGLLINKPROGRAMPROC)(GLuint program);
+typedef void (GLAD_API_PTR *PFNGLLINKPROGRAMARBPROC)(GLhandleARB programObj);
+typedef void (GLAD_API_PTR *PFNGLLOADMATRIXXOESPROC)(const GLfixed * m);
+typedef void (GLAD_API_PTR *PFNGLLOADTRANSPOSEMATRIXDARBPROC)(const GLdouble * m);
+typedef void (GLAD_API_PTR *PFNGLLOADTRANSPOSEMATRIXFARBPROC)(const GLfloat * m);
+typedef void (GLAD_API_PTR *PFNGLLOADTRANSPOSEMATRIXXOESPROC)(const GLfixed * m);
+typedef void (GLAD_API_PTR *PFNGLLOGICOPPROC)(GLenum opcode);
+typedef void (GLAD_API_PTR *PFNGLMAP1XOESPROC)(GLenum target, GLfixed u1, GLfixed u2, GLint stride, GLint order, GLfixed points);
+typedef void (GLAD_API_PTR *PFNGLMAP2XOESPROC)(GLenum target, GLfixed u1, GLfixed u2, GLint ustride, GLint uorder, GLfixed v1, GLfixed v2, GLint vstride, GLint vorder, GLfixed points);
+typedef void * (GLAD_API_PTR *PFNGLMAPBUFFERPROC)(GLenum target, GLenum access);
+typedef void * (GLAD_API_PTR *PFNGLMAPBUFFERARBPROC)(GLenum target, GLenum access);
+typedef void * (GLAD_API_PTR *PFNGLMAPBUFFERRANGEPROC)(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+typedef void (GLAD_API_PTR *PFNGLMAPGRID1XOESPROC)(GLint n, GLfixed u1, GLfixed u2);
+typedef void (GLAD_API_PTR *PFNGLMAPGRID2XOESPROC)(GLint n, GLfixed u1, GLfixed u2, GLfixed v1, GLfixed v2);
+typedef void * (GLAD_API_PTR *PFNGLMAPNAMEDBUFFERPROC)(GLuint buffer, GLenum access);
+typedef void * (GLAD_API_PTR *PFNGLMAPNAMEDBUFFERRANGEPROC)(GLuint buffer, GLintptr offset, GLsizeiptr length, GLbitfield access);
+typedef void (GLAD_API_PTR *PFNGLMATERIALXOESPROC)(GLenum face, GLenum pname, GLfixed param);
+typedef void (GLAD_API_PTR *PFNGLMATERIALXVOESPROC)(GLenum face, GLenum pname, const GLfixed * param);
+typedef void (GLAD_API_PTR *PFNGLMEMORYBARRIERPROC)(GLbitfield barriers);
+typedef void (GLAD_API_PTR *PFNGLMEMORYBARRIERBYREGIONPROC)(GLbitfield barriers);
+typedef void (GLAD_API_PTR *PFNGLMINSAMPLESHADINGPROC)(GLfloat value);
+typedef void (GLAD_API_PTR *PFNGLMINSAMPLESHADINGARBPROC)(GLfloat value);
+typedef void (GLAD_API_PTR *PFNGLMULTMATRIXXOESPROC)(const GLfixed * m);
+typedef void (GLAD_API_PTR *PFNGLMULTTRANSPOSEMATRIXDARBPROC)(const GLdouble * m);
+typedef void (GLAD_API_PTR *PFNGLMULTTRANSPOSEMATRIXFARBPROC)(const GLfloat * m);
+typedef void (GLAD_API_PTR *PFNGLMULTTRANSPOSEMATRIXXOESPROC)(const GLfixed * m);
+typedef void (GLAD_API_PTR *PFNGLMULTIDRAWARRAYSPROC)(GLenum mode, const GLint * first, const GLsizei * count, GLsizei drawcount);
+typedef void (GLAD_API_PTR *PFNGLMULTIDRAWARRAYSINDIRECTPROC)(GLenum mode, const void * indirect, GLsizei drawcount, GLsizei stride);
+typedef void (GLAD_API_PTR *PFNGLMULTIDRAWELEMENTSPROC)(GLenum mode, const GLsizei * count, GLenum type, const void *const* indices, GLsizei drawcount);
+typedef void (GLAD_API_PTR *PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC)(GLenum mode, const GLsizei * count, GLenum type, const void *const* indices, GLsizei drawcount, const GLint * basevertex);
+typedef void (GLAD_API_PTR *PFNGLMULTIDRAWELEMENTSINDIRECTPROC)(GLenum mode, GLenum type, const void * indirect, GLsizei drawcount, GLsizei stride);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1DARBPROC)(GLenum target, GLdouble s);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1DVARBPROC)(GLenum target, const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1FARBPROC)(GLenum target, GLfloat s);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1FVARBPROC)(GLenum target, const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1IARBPROC)(GLenum target, GLint s);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1IVARBPROC)(GLenum target, const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1SARBPROC)(GLenum target, GLshort s);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1SVARBPROC)(GLenum target, const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1XOESPROC)(GLenum texture, GLfixed s);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1XVOESPROC)(GLenum texture, const GLfixed * coords);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2DARBPROC)(GLenum target, GLdouble s, GLdouble t);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2DVARBPROC)(GLenum target, const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2FARBPROC)(GLenum target, GLfloat s, GLfloat t);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2FVARBPROC)(GLenum target, const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2IARBPROC)(GLenum target, GLint s, GLint t);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2IVARBPROC)(GLenum target, const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2SARBPROC)(GLenum target, GLshort s, GLshort t);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2SVARBPROC)(GLenum target, const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2XOESPROC)(GLenum texture, GLfixed s, GLfixed t);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2XVOESPROC)(GLenum texture, const GLfixed * coords);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3DARBPROC)(GLenum target, GLdouble s, GLdouble t, GLdouble r);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3DVARBPROC)(GLenum target, const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3FARBPROC)(GLenum target, GLfloat s, GLfloat t, GLfloat r);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3FVARBPROC)(GLenum target, const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3IARBPROC)(GLenum target, GLint s, GLint t, GLint r);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3IVARBPROC)(GLenum target, const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3SARBPROC)(GLenum target, GLshort s, GLshort t, GLshort r);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3SVARBPROC)(GLenum target, const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3XOESPROC)(GLenum texture, GLfixed s, GLfixed t, GLfixed r);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3XVOESPROC)(GLenum texture, const GLfixed * coords);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4DARBPROC)(GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4DVARBPROC)(GLenum target, const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4FARBPROC)(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4FVARBPROC)(GLenum target, const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4IARBPROC)(GLenum target, GLint s, GLint t, GLint r, GLint q);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4IVARBPROC)(GLenum target, const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4SARBPROC)(GLenum target, GLshort s, GLshort t, GLshort r, GLshort q);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4SVARBPROC)(GLenum target, const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4XOESPROC)(GLenum texture, GLfixed s, GLfixed t, GLfixed r, GLfixed q);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4XVOESPROC)(GLenum texture, const GLfixed * coords);
+typedef void (GLAD_API_PTR *PFNGLNAMEDBUFFERDATAPROC)(GLuint buffer, GLsizeiptr size, const void * data, GLenum usage);
+typedef void (GLAD_API_PTR *PFNGLNAMEDBUFFERSTORAGEPROC)(GLuint buffer, GLsizeiptr size, const void * data, GLbitfield flags);
+typedef void (GLAD_API_PTR *PFNGLNAMEDBUFFERSUBDATAPROC)(GLuint buffer, GLintptr offset, GLsizeiptr size, const void * data);
+typedef void (GLAD_API_PTR *PFNGLNAMEDFRAMEBUFFERDRAWBUFFERPROC)(GLuint framebuffer, GLenum buf);
+typedef void (GLAD_API_PTR *PFNGLNAMEDFRAMEBUFFERDRAWBUFFERSPROC)(GLuint framebuffer, GLsizei n, const GLenum * bufs);
+typedef void (GLAD_API_PTR *PFNGLNAMEDFRAMEBUFFERPARAMETERIPROC)(GLuint framebuffer, GLenum pname, GLint param);
+typedef void (GLAD_API_PTR *PFNGLNAMEDFRAMEBUFFERREADBUFFERPROC)(GLuint framebuffer, GLenum src);
+typedef void (GLAD_API_PTR *PFNGLNAMEDFRAMEBUFFERRENDERBUFFERPROC)(GLuint framebuffer, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+typedef void (GLAD_API_PTR *PFNGLNAMEDFRAMEBUFFERSAMPLELOCATIONSFVARBPROC)(GLuint framebuffer, GLuint start, GLsizei count, const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLNAMEDFRAMEBUFFERTEXTUREPROC)(GLuint framebuffer, GLenum attachment, GLuint texture, GLint level);
+typedef void (GLAD_API_PTR *PFNGLNAMEDFRAMEBUFFERTEXTURELAYERPROC)(GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLint layer);
+typedef void (GLAD_API_PTR *PFNGLNAMEDRENDERBUFFERSTORAGEPROC)(GLuint renderbuffer, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GLAD_API_PTR *PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEPROC)(GLuint renderbuffer, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GLAD_API_PTR *PFNGLNAMEDSTRINGARBPROC)(GLenum type, GLint namelen, const GLchar * name, GLint stringlen, const GLchar * string);
+typedef void (GLAD_API_PTR *PFNGLNORMAL3XOESPROC)(GLfixed nx, GLfixed ny, GLfixed nz);
+typedef void (GLAD_API_PTR *PFNGLNORMAL3XVOESPROC)(const GLfixed * coords);
+typedef void (GLAD_API_PTR *PFNGLOBJECTLABELPROC)(GLenum identifier, GLuint name, GLsizei length, const GLchar * label);
+typedef void (GLAD_API_PTR *PFNGLOBJECTPTRLABELPROC)(const void * ptr, GLsizei length, const GLchar * label);
+typedef void (GLAD_API_PTR *PFNGLORTHOXOESPROC)(GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f);
+typedef void (GLAD_API_PTR *PFNGLPASSTHROUGHXOESPROC)(GLfixed token);
+typedef void (GLAD_API_PTR *PFNGLPATCHPARAMETERFVPROC)(GLenum pname, const GLfloat * values);
+typedef void (GLAD_API_PTR *PFNGLPATCHPARAMETERIPROC)(GLenum pname, GLint value);
+typedef void (GLAD_API_PTR *PFNGLPAUSETRANSFORMFEEDBACKPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLPIXELMAPXPROC)(GLenum map, GLint size, const GLfixed * values);
+typedef void (GLAD_API_PTR *PFNGLPIXELSTOREFPROC)(GLenum pname, GLfloat param);
+typedef void (GLAD_API_PTR *PFNGLPIXELSTOREIPROC)(GLenum pname, GLint param);
+typedef void (GLAD_API_PTR *PFNGLPIXELSTOREXPROC)(GLenum pname, GLfixed param);
+typedef void (GLAD_API_PTR *PFNGLPIXELTRANSFERXOESPROC)(GLenum pname, GLfixed param);
+typedef void (GLAD_API_PTR *PFNGLPIXELZOOMXOESPROC)(GLfixed xfactor, GLfixed yfactor);
+typedef void (GLAD_API_PTR *PFNGLPOINTPARAMETERFPROC)(GLenum pname, GLfloat param);
+typedef void (GLAD_API_PTR *PFNGLPOINTPARAMETERFVPROC)(GLenum pname, const GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLPOINTPARAMETERIPROC)(GLenum pname, GLint param);
+typedef void (GLAD_API_PTR *PFNGLPOINTPARAMETERIVPROC)(GLenum pname, const GLint * params);
+typedef void (GLAD_API_PTR *PFNGLPOINTPARAMETERXVOESPROC)(GLenum pname, const GLfixed * params);
+typedef void (GLAD_API_PTR *PFNGLPOINTSIZEPROC)(GLfloat size);
+typedef void (GLAD_API_PTR *PFNGLPOINTSIZEXOESPROC)(GLfixed size);
+typedef void (GLAD_API_PTR *PFNGLPOLYGONMODEPROC)(GLenum face, GLenum mode);
+typedef void (GLAD_API_PTR *PFNGLPOLYGONOFFSETPROC)(GLfloat factor, GLfloat units);
+typedef void (GLAD_API_PTR *PFNGLPOLYGONOFFSETXOESPROC)(GLfixed factor, GLfixed units);
+typedef void (GLAD_API_PTR *PFNGLPOPDEBUGGROUPPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLPRIMITIVEBOUNDINGBOXARBPROC)(GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW);
+typedef void (GLAD_API_PTR *PFNGLPRIMITIVERESTARTINDEXPROC)(GLuint index);
+typedef void (GLAD_API_PTR *PFNGLPRIORITIZETEXTURESXOESPROC)(GLsizei n, const GLuint * textures, const GLfixed * priorities);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMBINARYPROC)(GLuint program, GLenum binaryFormat, const void * binary, GLsizei length);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMENVPARAMETER4DARBPROC)(GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMENVPARAMETER4DVARBPROC)(GLenum target, GLuint index, const GLdouble * params);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMENVPARAMETER4FARBPROC)(GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMENVPARAMETER4FVARBPROC)(GLenum target, GLuint index, const GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMLOCALPARAMETER4DARBPROC)(GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMLOCALPARAMETER4DVARBPROC)(GLenum target, GLuint index, const GLdouble * params);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMLOCALPARAMETER4FARBPROC)(GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMLOCALPARAMETER4FVARBPROC)(GLenum target, GLuint index, const GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMPARAMETERIPROC)(GLuint program, GLenum pname, GLint value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMPARAMETERIARBPROC)(GLuint program, GLenum pname, GLint value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMSTRINGARBPROC)(GLenum target, GLenum format, GLsizei len, const void * string);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM1DPROC)(GLuint program, GLint location, GLdouble v0);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM1DVPROC)(GLuint program, GLint location, GLsizei count, const GLdouble * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM1FPROC)(GLuint program, GLint location, GLfloat v0);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM1FVPROC)(GLuint program, GLint location, GLsizei count, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM1IPROC)(GLuint program, GLint location, GLint v0);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM1I64ARBPROC)(GLuint program, GLint location, GLint64 x);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM1I64VARBPROC)(GLuint program, GLint location, GLsizei count, const GLint64 * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM1IVPROC)(GLuint program, GLint location, GLsizei count, const GLint * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM1UIPROC)(GLuint program, GLint location, GLuint v0);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM1UI64ARBPROC)(GLuint program, GLint location, GLuint64 x);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM1UI64VARBPROC)(GLuint program, GLint location, GLsizei count, const GLuint64 * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM1UIVPROC)(GLuint program, GLint location, GLsizei count, const GLuint * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM2DPROC)(GLuint program, GLint location, GLdouble v0, GLdouble v1);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM2DVPROC)(GLuint program, GLint location, GLsizei count, const GLdouble * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM2FPROC)(GLuint program, GLint location, GLfloat v0, GLfloat v1);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM2FVPROC)(GLuint program, GLint location, GLsizei count, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM2IPROC)(GLuint program, GLint location, GLint v0, GLint v1);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM2I64ARBPROC)(GLuint program, GLint location, GLint64 x, GLint64 y);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM2I64VARBPROC)(GLuint program, GLint location, GLsizei count, const GLint64 * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM2IVPROC)(GLuint program, GLint location, GLsizei count, const GLint * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM2UIPROC)(GLuint program, GLint location, GLuint v0, GLuint v1);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM2UI64ARBPROC)(GLuint program, GLint location, GLuint64 x, GLuint64 y);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM2UI64VARBPROC)(GLuint program, GLint location, GLsizei count, const GLuint64 * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM2UIVPROC)(GLuint program, GLint location, GLsizei count, const GLuint * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM3DPROC)(GLuint program, GLint location, GLdouble v0, GLdouble v1, GLdouble v2);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM3DVPROC)(GLuint program, GLint location, GLsizei count, const GLdouble * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM3FPROC)(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM3FVPROC)(GLuint program, GLint location, GLsizei count, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM3IPROC)(GLuint program, GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM3I64ARBPROC)(GLuint program, GLint location, GLint64 x, GLint64 y, GLint64 z);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM3I64VARBPROC)(GLuint program, GLint location, GLsizei count, const GLint64 * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM3IVPROC)(GLuint program, GLint location, GLsizei count, const GLint * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM3UIPROC)(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM3UI64ARBPROC)(GLuint program, GLint location, GLuint64 x, GLuint64 y, GLuint64 z);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM3UI64VARBPROC)(GLuint program, GLint location, GLsizei count, const GLuint64 * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM3UIVPROC)(GLuint program, GLint location, GLsizei count, const GLuint * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM4DPROC)(GLuint program, GLint location, GLdouble v0, GLdouble v1, GLdouble v2, GLdouble v3);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM4DVPROC)(GLuint program, GLint location, GLsizei count, const GLdouble * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM4FPROC)(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM4FVPROC)(GLuint program, GLint location, GLsizei count, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM4IPROC)(GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM4I64ARBPROC)(GLuint program, GLint location, GLint64 x, GLint64 y, GLint64 z, GLint64 w);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM4I64VARBPROC)(GLuint program, GLint location, GLsizei count, const GLint64 * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM4IVPROC)(GLuint program, GLint location, GLsizei count, const GLint * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM4UIPROC)(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM4UI64ARBPROC)(GLuint program, GLint location, GLuint64 x, GLuint64 y, GLuint64 z, GLuint64 w);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM4UI64VARBPROC)(GLuint program, GLint location, GLsizei count, const GLuint64 * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM4UIVPROC)(GLuint program, GLint location, GLsizei count, const GLuint * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX2DVPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX2FVPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX2X3DVPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX2X4DVPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX3DVPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX3FVPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX3X2DVPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX3X4DVPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX4DVPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX4FVPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX4X2DVPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX4X3DVPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLPROVOKINGVERTEXPROC)(GLenum mode);
+typedef void (GLAD_API_PTR *PFNGLPUSHDEBUGGROUPPROC)(GLenum source, GLuint id, GLsizei length, const GLchar * message);
+typedef void (GLAD_API_PTR *PFNGLQUERYCOUNTERPROC)(GLuint id, GLenum target);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS2XOESPROC)(GLfixed x, GLfixed y);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS2XVOESPROC)(const GLfixed * coords);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS3XOESPROC)(GLfixed x, GLfixed y, GLfixed z);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS3XVOESPROC)(const GLfixed * coords);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS4XOESPROC)(GLfixed x, GLfixed y, GLfixed z, GLfixed w);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS4XVOESPROC)(const GLfixed * coords);
+typedef void (GLAD_API_PTR *PFNGLREADBUFFERPROC)(GLenum src);
+typedef void (GLAD_API_PTR *PFNGLREADPIXELSPROC)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void * pixels);
+typedef void (GLAD_API_PTR *PFNGLRECTXOESPROC)(GLfixed x1, GLfixed y1, GLfixed x2, GLfixed y2);
+typedef void (GLAD_API_PTR *PFNGLRECTXVOESPROC)(const GLfixed * v1, const GLfixed * v2);
+typedef void (GLAD_API_PTR *PFNGLRELEASESHADERCOMPILERPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLRENDERBUFFERSTORAGEPROC)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GLAD_API_PTR *PFNGLRENDERBUFFERSTORAGEEXTPROC)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GLAD_API_PTR *PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GLAD_API_PTR *PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GLAD_API_PTR *PFNGLRESUMETRANSFORMFEEDBACKPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLROTATEXOESPROC)(GLfixed angle, GLfixed x, GLfixed y, GLfixed z);
+typedef void (GLAD_API_PTR *PFNGLSAMPLECOVERAGEPROC)(GLfloat value, GLboolean invert);
+typedef void (GLAD_API_PTR *PFNGLSAMPLECOVERAGEARBPROC)(GLfloat value, GLboolean invert);
+typedef void (GLAD_API_PTR *PFNGLSAMPLEMASKIPROC)(GLuint maskNumber, GLbitfield mask);
+typedef void (GLAD_API_PTR *PFNGLSAMPLERPARAMETERIIVPROC)(GLuint sampler, GLenum pname, const GLint * param);
+typedef void (GLAD_API_PTR *PFNGLSAMPLERPARAMETERIUIVPROC)(GLuint sampler, GLenum pname, const GLuint * param);
+typedef void (GLAD_API_PTR *PFNGLSAMPLERPARAMETERFPROC)(GLuint sampler, GLenum pname, GLfloat param);
+typedef void (GLAD_API_PTR *PFNGLSAMPLERPARAMETERFVPROC)(GLuint sampler, GLenum pname, const GLfloat * param);
+typedef void (GLAD_API_PTR *PFNGLSAMPLERPARAMETERIPROC)(GLuint sampler, GLenum pname, GLint param);
+typedef void (GLAD_API_PTR *PFNGLSAMPLERPARAMETERIVPROC)(GLuint sampler, GLenum pname, const GLint * param);
+typedef void (GLAD_API_PTR *PFNGLSCALEXOESPROC)(GLfixed x, GLfixed y, GLfixed z);
+typedef void (GLAD_API_PTR *PFNGLSCISSORPROC)(GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GLAD_API_PTR *PFNGLSCISSORARRAYVPROC)(GLuint first, GLsizei count, const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLSCISSORINDEXEDPROC)(GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height);
+typedef void (GLAD_API_PTR *PFNGLSCISSORINDEXEDVPROC)(GLuint index, const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLSHADERBINARYPROC)(GLsizei count, const GLuint * shaders, GLenum binaryFormat, const void * binary, GLsizei length);
+typedef void (GLAD_API_PTR *PFNGLSHADERSOURCEPROC)(GLuint shader, GLsizei count, const GLchar *const* string, const GLint * length);
+typedef void (GLAD_API_PTR *PFNGLSHADERSOURCEARBPROC)(GLhandleARB shaderObj, GLsizei count, const GLcharARB ** string, const GLint * length);
+typedef void (GLAD_API_PTR *PFNGLSHADERSTORAGEBLOCKBINDINGPROC)(GLuint program, GLuint storageBlockIndex, GLuint storageBlockBinding);
+typedef void (GLAD_API_PTR *PFNGLSPECIALIZESHADERARBPROC)(GLuint shader, const GLchar * pEntryPoint, GLuint numSpecializationConstants, const GLuint * pConstantIndex, const GLuint * pConstantValue);
+typedef void (GLAD_API_PTR *PFNGLSTENCILFUNCPROC)(GLenum func, GLint ref, GLuint mask);
+typedef void (GLAD_API_PTR *PFNGLSTENCILFUNCSEPARATEPROC)(GLenum face, GLenum func, GLint ref, GLuint mask);
+typedef void (GLAD_API_PTR *PFNGLSTENCILMASKPROC)(GLuint mask);
+typedef void (GLAD_API_PTR *PFNGLSTENCILMASKSEPARATEPROC)(GLenum face, GLuint mask);
+typedef void (GLAD_API_PTR *PFNGLSTENCILOPPROC)(GLenum fail, GLenum zfail, GLenum zpass);
+typedef void (GLAD_API_PTR *PFNGLSTENCILOPSEPARATEPROC)(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+typedef void (GLAD_API_PTR *PFNGLTEXBUFFERPROC)(GLenum target, GLenum internalformat, GLuint buffer);
+typedef void (GLAD_API_PTR *PFNGLTEXBUFFERRANGEPROC)(GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD1XOESPROC)(GLfixed s);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD1XVOESPROC)(const GLfixed * coords);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD2XOESPROC)(GLfixed s, GLfixed t);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD2XVOESPROC)(const GLfixed * coords);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD3XOESPROC)(GLfixed s, GLfixed t, GLfixed r);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD3XVOESPROC)(const GLfixed * coords);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD4XOESPROC)(GLfixed s, GLfixed t, GLfixed r, GLfixed q);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD4XVOESPROC)(const GLfixed * coords);
+typedef void (GLAD_API_PTR *PFNGLTEXENVXOESPROC)(GLenum target, GLenum pname, GLfixed param);
+typedef void (GLAD_API_PTR *PFNGLTEXENVXVOESPROC)(GLenum target, GLenum pname, const GLfixed * params);
+typedef void (GLAD_API_PTR *PFNGLTEXGENXOESPROC)(GLenum coord, GLenum pname, GLfixed param);
+typedef void (GLAD_API_PTR *PFNGLTEXGENXVOESPROC)(GLenum coord, GLenum pname, const GLfixed * params);
+typedef void (GLAD_API_PTR *PFNGLTEXIMAGE1DPROC)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void * pixels);
+typedef void (GLAD_API_PTR *PFNGLTEXIMAGE2DPROC)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void * pixels);
+typedef void (GLAD_API_PTR *PFNGLTEXIMAGE2DMULTISAMPLEPROC)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+typedef void (GLAD_API_PTR *PFNGLTEXIMAGE3DPROC)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void * pixels);
+typedef void (GLAD_API_PTR *PFNGLTEXIMAGE3DMULTISAMPLEPROC)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERIIVPROC)(GLenum target, GLenum pname, const GLint * params);
+typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERIUIVPROC)(GLenum target, GLenum pname, const GLuint * params);
+typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERFPROC)(GLenum target, GLenum pname, GLfloat param);
+typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERFVPROC)(GLenum target, GLenum pname, const GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERIPROC)(GLenum target, GLenum pname, GLint param);
+typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERIVPROC)(GLenum target, GLenum pname, const GLint * params);
+typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERXOESPROC)(GLenum target, GLenum pname, GLfixed param);
+typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERXVOESPROC)(GLenum target, GLenum pname, const GLfixed * params);
+typedef void (GLAD_API_PTR *PFNGLTEXSTORAGE1DPROC)(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+typedef void (GLAD_API_PTR *PFNGLTEXSTORAGE2DPROC)(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GLAD_API_PTR *PFNGLTEXSTORAGE2DMULTISAMPLEPROC)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+typedef void (GLAD_API_PTR *PFNGLTEXSTORAGE3DPROC)(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+typedef void (GLAD_API_PTR *PFNGLTEXSTORAGE3DMULTISAMPLEPROC)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+typedef void (GLAD_API_PTR *PFNGLTEXSUBIMAGE1DPROC)(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void * pixels);
+typedef void (GLAD_API_PTR *PFNGLTEXSUBIMAGE2DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void * pixels);
+typedef void (GLAD_API_PTR *PFNGLTEXSUBIMAGE3DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void * pixels);
+typedef void (GLAD_API_PTR *PFNGLTEXTUREBUFFERPROC)(GLuint texture, GLenum internalformat, GLuint buffer);
+typedef void (GLAD_API_PTR *PFNGLTEXTUREBUFFERRANGEPROC)(GLuint texture, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size);
+typedef void (GLAD_API_PTR *PFNGLTEXTUREPARAMETERIIVPROC)(GLuint texture, GLenum pname, const GLint * params);
+typedef void (GLAD_API_PTR *PFNGLTEXTUREPARAMETERIUIVPROC)(GLuint texture, GLenum pname, const GLuint * params);
+typedef void (GLAD_API_PTR *PFNGLTEXTUREPARAMETERFPROC)(GLuint texture, GLenum pname, GLfloat param);
+typedef void (GLAD_API_PTR *PFNGLTEXTUREPARAMETERFVPROC)(GLuint texture, GLenum pname, const GLfloat * param);
+typedef void (GLAD_API_PTR *PFNGLTEXTUREPARAMETERIPROC)(GLuint texture, GLenum pname, GLint param);
+typedef void (GLAD_API_PTR *PFNGLTEXTUREPARAMETERIVPROC)(GLuint texture, GLenum pname, const GLint * param);
+typedef void (GLAD_API_PTR *PFNGLTEXTURESTORAGE1DPROC)(GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width);
+typedef void (GLAD_API_PTR *PFNGLTEXTURESTORAGE2DPROC)(GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GLAD_API_PTR *PFNGLTEXTURESTORAGE2DMULTISAMPLEPROC)(GLuint texture, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+typedef void (GLAD_API_PTR *PFNGLTEXTURESTORAGE3DPROC)(GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+typedef void (GLAD_API_PTR *PFNGLTEXTURESTORAGE3DMULTISAMPLEPROC)(GLuint texture, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+typedef void (GLAD_API_PTR *PFNGLTEXTURESUBIMAGE1DPROC)(GLuint texture, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void * pixels);
+typedef void (GLAD_API_PTR *PFNGLTEXTURESUBIMAGE2DPROC)(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void * pixels);
+typedef void (GLAD_API_PTR *PFNGLTEXTURESUBIMAGE3DPROC)(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void * pixels);
+typedef void (GLAD_API_PTR *PFNGLTEXTUREVIEWPROC)(GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers);
+typedef void (GLAD_API_PTR *PFNGLTRANSFORMFEEDBACKBUFFERBASEPROC)(GLuint xfb, GLuint index, GLuint buffer);
+typedef void (GLAD_API_PTR *PFNGLTRANSFORMFEEDBACKBUFFERRANGEPROC)(GLuint xfb, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+typedef void (GLAD_API_PTR *PFNGLTRANSFORMFEEDBACKVARYINGSPROC)(GLuint program, GLsizei count, const GLchar *const* varyings, GLenum bufferMode);
+typedef void (GLAD_API_PTR *PFNGLTRANSLATEXOESPROC)(GLfixed x, GLfixed y, GLfixed z);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM1DPROC)(GLint location, GLdouble x);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM1DVPROC)(GLint location, GLsizei count, const GLdouble * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM1FPROC)(GLint location, GLfloat v0);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM1FARBPROC)(GLint location, GLfloat v0);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM1FVPROC)(GLint location, GLsizei count, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM1FVARBPROC)(GLint location, GLsizei count, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM1IPROC)(GLint location, GLint v0);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM1I64ARBPROC)(GLint location, GLint64 x);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM1I64VARBPROC)(GLint location, GLsizei count, const GLint64 * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM1IARBPROC)(GLint location, GLint v0);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM1IVPROC)(GLint location, GLsizei count, const GLint * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM1IVARBPROC)(GLint location, GLsizei count, const GLint * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM1UIPROC)(GLint location, GLuint v0);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM1UI64ARBPROC)(GLint location, GLuint64 x);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM1UI64VARBPROC)(GLint location, GLsizei count, const GLuint64 * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM1UIVPROC)(GLint location, GLsizei count, const GLuint * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM2DPROC)(GLint location, GLdouble x, GLdouble y);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM2DVPROC)(GLint location, GLsizei count, const GLdouble * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM2FPROC)(GLint location, GLfloat v0, GLfloat v1);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM2FARBPROC)(GLint location, GLfloat v0, GLfloat v1);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM2FVPROC)(GLint location, GLsizei count, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM2FVARBPROC)(GLint location, GLsizei count, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM2IPROC)(GLint location, GLint v0, GLint v1);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM2I64ARBPROC)(GLint location, GLint64 x, GLint64 y);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM2I64VARBPROC)(GLint location, GLsizei count, const GLint64 * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM2IARBPROC)(GLint location, GLint v0, GLint v1);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM2IVPROC)(GLint location, GLsizei count, const GLint * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM2IVARBPROC)(GLint location, GLsizei count, const GLint * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM2UIPROC)(GLint location, GLuint v0, GLuint v1);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM2UI64ARBPROC)(GLint location, GLuint64 x, GLuint64 y);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM2UI64VARBPROC)(GLint location, GLsizei count, const GLuint64 * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM2UIVPROC)(GLint location, GLsizei count, const GLuint * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM3DPROC)(GLint location, GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM3DVPROC)(GLint location, GLsizei count, const GLdouble * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM3FPROC)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM3FARBPROC)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM3FVPROC)(GLint location, GLsizei count, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM3FVARBPROC)(GLint location, GLsizei count, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM3IPROC)(GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM3I64ARBPROC)(GLint location, GLint64 x, GLint64 y, GLint64 z);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM3I64VARBPROC)(GLint location, GLsizei count, const GLint64 * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM3IARBPROC)(GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM3IVPROC)(GLint location, GLsizei count, const GLint * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM3IVARBPROC)(GLint location, GLsizei count, const GLint * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM3UIPROC)(GLint location, GLuint v0, GLuint v1, GLuint v2);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM3UI64ARBPROC)(GLint location, GLuint64 x, GLuint64 y, GLuint64 z);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM3UI64VARBPROC)(GLint location, GLsizei count, const GLuint64 * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM3UIVPROC)(GLint location, GLsizei count, const GLuint * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM4DPROC)(GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM4DVPROC)(GLint location, GLsizei count, const GLdouble * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM4FPROC)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM4FARBPROC)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM4FVPROC)(GLint location, GLsizei count, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM4FVARBPROC)(GLint location, GLsizei count, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM4IPROC)(GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM4I64ARBPROC)(GLint location, GLint64 x, GLint64 y, GLint64 z, GLint64 w);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM4I64VARBPROC)(GLint location, GLsizei count, const GLint64 * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM4IARBPROC)(GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM4IVPROC)(GLint location, GLsizei count, const GLint * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM4IVARBPROC)(GLint location, GLsizei count, const GLint * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM4UIPROC)(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM4UI64ARBPROC)(GLint location, GLuint64 x, GLuint64 y, GLuint64 z, GLuint64 w);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM4UI64VARBPROC)(GLint location, GLsizei count, const GLuint64 * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM4UIVPROC)(GLint location, GLsizei count, const GLuint * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMBLOCKBINDINGPROC)(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX2DVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLdouble * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX2FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX2FVARBPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX2X3DVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLdouble * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX2X3FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX2X4DVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLdouble * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX2X4FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX3DVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLdouble * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX3FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX3FVARBPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX3X2DVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLdouble * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX3X2FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX3X4DVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLdouble * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX3X4FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX4DVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLdouble * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX4FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX4FVARBPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX4X2DVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLdouble * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX4X2FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX4X3DVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLdouble * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX4X3FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMSUBROUTINESUIVPROC)(GLenum shadertype, GLsizei count, const GLuint * indices);
+typedef GLboolean (GLAD_API_PTR *PFNGLUNMAPBUFFERPROC)(GLenum target);
+typedef GLboolean (GLAD_API_PTR *PFNGLUNMAPBUFFERARBPROC)(GLenum target);
+typedef GLboolean (GLAD_API_PTR *PFNGLUNMAPNAMEDBUFFERPROC)(GLuint buffer);
+typedef void (GLAD_API_PTR *PFNGLUSEPROGRAMPROC)(GLuint program);
+typedef void (GLAD_API_PTR *PFNGLUSEPROGRAMOBJECTARBPROC)(GLhandleARB programObj);
+typedef void (GLAD_API_PTR *PFNGLUSEPROGRAMSTAGESPROC)(GLuint pipeline, GLbitfield stages, GLuint program);
+typedef void (GLAD_API_PTR *PFNGLVALIDATEPROGRAMPROC)(GLuint program);
+typedef void (GLAD_API_PTR *PFNGLVALIDATEPROGRAMARBPROC)(GLhandleARB programObj);
+typedef void (GLAD_API_PTR *PFNGLVALIDATEPROGRAMPIPELINEPROC)(GLuint pipeline);
+typedef void (GLAD_API_PTR *PFNGLVERTEX2XOESPROC)(GLfixed x);
+typedef void (GLAD_API_PTR *PFNGLVERTEX2XVOESPROC)(const GLfixed * coords);
+typedef void (GLAD_API_PTR *PFNGLVERTEX3XOESPROC)(GLfixed x, GLfixed y);
+typedef void (GLAD_API_PTR *PFNGLVERTEX3XVOESPROC)(const GLfixed * coords);
+typedef void (GLAD_API_PTR *PFNGLVERTEX4XOESPROC)(GLfixed x, GLfixed y, GLfixed z);
+typedef void (GLAD_API_PTR *PFNGLVERTEX4XVOESPROC)(const GLfixed * coords);
+typedef void (GLAD_API_PTR *PFNGLVERTEXARRAYATTRIBBINDINGPROC)(GLuint vaobj, GLuint attribindex, GLuint bindingindex);
+typedef void (GLAD_API_PTR *PFNGLVERTEXARRAYATTRIBFORMATPROC)(GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset);
+typedef void (GLAD_API_PTR *PFNGLVERTEXARRAYATTRIBIFORMATPROC)(GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+typedef void (GLAD_API_PTR *PFNGLVERTEXARRAYATTRIBLFORMATPROC)(GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+typedef void (GLAD_API_PTR *PFNGLVERTEXARRAYBINDINGDIVISORPROC)(GLuint vaobj, GLuint bindingindex, GLuint divisor);
+typedef void (GLAD_API_PTR *PFNGLVERTEXARRAYELEMENTBUFFERPROC)(GLuint vaobj, GLuint buffer);
+typedef void (GLAD_API_PTR *PFNGLVERTEXARRAYVERTEXBUFFERPROC)(GLuint vaobj, GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride);
+typedef void (GLAD_API_PTR *PFNGLVERTEXARRAYVERTEXBUFFERSPROC)(GLuint vaobj, GLuint first, GLsizei count, const GLuint * buffers, const GLintptr * offsets, const GLsizei * strides);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1DPROC)(GLuint index, GLdouble x);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1DARBPROC)(GLuint index, GLdouble x);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1DVPROC)(GLuint index, const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1DVARBPROC)(GLuint index, const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1FPROC)(GLuint index, GLfloat x);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1FARBPROC)(GLuint index, GLfloat x);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1FVPROC)(GLuint index, const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1FVARBPROC)(GLuint index, const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1SPROC)(GLuint index, GLshort x);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1SARBPROC)(GLuint index, GLshort x);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1SVPROC)(GLuint index, const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1SVARBPROC)(GLuint index, const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2DPROC)(GLuint index, GLdouble x, GLdouble y);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2DARBPROC)(GLuint index, GLdouble x, GLdouble y);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2DVPROC)(GLuint index, const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2DVARBPROC)(GLuint index, const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2FPROC)(GLuint index, GLfloat x, GLfloat y);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2FARBPROC)(GLuint index, GLfloat x, GLfloat y);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2FVPROC)(GLuint index, const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2FVARBPROC)(GLuint index, const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2SPROC)(GLuint index, GLshort x, GLshort y);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2SARBPROC)(GLuint index, GLshort x, GLshort y);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2SVPROC)(GLuint index, const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2SVARBPROC)(GLuint index, const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3DPROC)(GLuint index, GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3DARBPROC)(GLuint index, GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3DVPROC)(GLuint index, const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3DVARBPROC)(GLuint index, const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3FPROC)(GLuint index, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3FARBPROC)(GLuint index, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3FVPROC)(GLuint index, const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3FVARBPROC)(GLuint index, const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3SPROC)(GLuint index, GLshort x, GLshort y, GLshort z);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3SARBPROC)(GLuint index, GLshort x, GLshort y, GLshort z);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3SVPROC)(GLuint index, const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3SVARBPROC)(GLuint index, const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NBVPROC)(GLuint index, const GLbyte * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NBVARBPROC)(GLuint index, const GLbyte * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NIVPROC)(GLuint index, const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NIVARBPROC)(GLuint index, const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NSVPROC)(GLuint index, const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NSVARBPROC)(GLuint index, const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NUBPROC)(GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NUBARBPROC)(GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NUBVPROC)(GLuint index, const GLubyte * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NUBVARBPROC)(GLuint index, const GLubyte * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NUIVPROC)(GLuint index, const GLuint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NUIVARBPROC)(GLuint index, const GLuint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NUSVPROC)(GLuint index, const GLushort * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NUSVARBPROC)(GLuint index, const GLushort * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4BVPROC)(GLuint index, const GLbyte * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4BVARBPROC)(GLuint index, const GLbyte * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4DPROC)(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4DARBPROC)(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4DVPROC)(GLuint index, const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4DVARBPROC)(GLuint index, const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4FPROC)(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4FARBPROC)(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4FVPROC)(GLuint index, const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4FVARBPROC)(GLuint index, const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4IVPROC)(GLuint index, const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4IVARBPROC)(GLuint index, const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4SPROC)(GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4SARBPROC)(GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4SVPROC)(GLuint index, const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4SVARBPROC)(GLuint index, const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4UBVPROC)(GLuint index, const GLubyte * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4UBVARBPROC)(GLuint index, const GLubyte * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4UIVPROC)(GLuint index, const GLuint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4UIVARBPROC)(GLuint index, const GLuint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4USVPROC)(GLuint index, const GLushort * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4USVARBPROC)(GLuint index, const GLushort * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBBINDINGPROC)(GLuint attribindex, GLuint bindingindex);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBDIVISORPROC)(GLuint index, GLuint divisor);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBDIVISORARBPROC)(GLuint index, GLuint divisor);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBFORMATPROC)(GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI1IPROC)(GLuint index, GLint x);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI1IVPROC)(GLuint index, const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI1UIPROC)(GLuint index, GLuint x);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI1UIVPROC)(GLuint index, const GLuint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI2IPROC)(GLuint index, GLint x, GLint y);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI2IVPROC)(GLuint index, const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI2UIPROC)(GLuint index, GLuint x, GLuint y);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI2UIVPROC)(GLuint index, const GLuint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI3IPROC)(GLuint index, GLint x, GLint y, GLint z);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI3IVPROC)(GLuint index, const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI3UIPROC)(GLuint index, GLuint x, GLuint y, GLuint z);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI3UIVPROC)(GLuint index, const GLuint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4BVPROC)(GLuint index, const GLbyte * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4IPROC)(GLuint index, GLint x, GLint y, GLint z, GLint w);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4IVPROC)(GLuint index, const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4SVPROC)(GLuint index, const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4UBVPROC)(GLuint index, const GLubyte * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4UIPROC)(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4UIVPROC)(GLuint index, const GLuint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4USVPROC)(GLuint index, const GLushort * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBIFORMATPROC)(GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBIPOINTERPROC)(GLuint index, GLint size, GLenum type, GLsizei stride, const void * pointer);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBL1DPROC)(GLuint index, GLdouble x);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBL1DVPROC)(GLuint index, const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBL2DPROC)(GLuint index, GLdouble x, GLdouble y);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBL2DVPROC)(GLuint index, const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBL3DPROC)(GLuint index, GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBL3DVPROC)(GLuint index, const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBL4DPROC)(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBL4DVPROC)(GLuint index, const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBLFORMATPROC)(GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBLPOINTERPROC)(GLuint index, GLint size, GLenum type, GLsizei stride, const void * pointer);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBP1UIPROC)(GLuint index, GLenum type, GLboolean normalized, GLuint value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBP1UIVPROC)(GLuint index, GLenum type, GLboolean normalized, const GLuint * value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBP2UIPROC)(GLuint index, GLenum type, GLboolean normalized, GLuint value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBP2UIVPROC)(GLuint index, GLenum type, GLboolean normalized, const GLuint * value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBP3UIPROC)(GLuint index, GLenum type, GLboolean normalized, GLuint value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBP3UIVPROC)(GLuint index, GLenum type, GLboolean normalized, const GLuint * value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBP4UIPROC)(GLuint index, GLenum type, GLboolean normalized, GLuint value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBP4UIVPROC)(GLuint index, GLenum type, GLboolean normalized, const GLuint * value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBPOINTERPROC)(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void * pointer);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBPOINTERARBPROC)(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void * pointer);
+typedef void (GLAD_API_PTR *PFNGLVERTEXBINDINGDIVISORPROC)(GLuint bindingindex, GLuint divisor);
+typedef void (GLAD_API_PTR *PFNGLVIEWPORTPROC)(GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GLAD_API_PTR *PFNGLVIEWPORTARRAYVPROC)(GLuint first, GLsizei count, const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLVIEWPORTINDEXEDFPROC)(GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h);
+typedef void (GLAD_API_PTR *PFNGLVIEWPORTINDEXEDFVPROC)(GLuint index, const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLWAITSYNCPROC)(GLsync sync, GLbitfield flags, GLuint64 timeout);
+
+GLAD_API_CALL PFNGLACCUMXOESPROC glad_glAccumxOES;
+#define glAccumxOES glad_glAccumxOES
+GLAD_API_CALL PFNGLACTIVESHADERPROGRAMPROC glad_glActiveShaderProgram;
+#define glActiveShaderProgram glad_glActiveShaderProgram
+GLAD_API_CALL PFNGLACTIVETEXTUREPROC glad_glActiveTexture;
+#define glActiveTexture glad_glActiveTexture
+GLAD_API_CALL PFNGLACTIVETEXTUREARBPROC glad_glActiveTextureARB;
+#define glActiveTextureARB glad_glActiveTextureARB
+GLAD_API_CALL PFNGLALPHAFUNCXOESPROC glad_glAlphaFuncxOES;
+#define glAlphaFuncxOES glad_glAlphaFuncxOES
+GLAD_API_CALL PFNGLATTACHOBJECTARBPROC glad_glAttachObjectARB;
+#define glAttachObjectARB glad_glAttachObjectARB
+GLAD_API_CALL PFNGLATTACHSHADERPROC glad_glAttachShader;
+#define glAttachShader glad_glAttachShader
+GLAD_API_CALL PFNGLBEGINCONDITIONALRENDERPROC glad_glBeginConditionalRender;
+#define glBeginConditionalRender glad_glBeginConditionalRender
+GLAD_API_CALL PFNGLBEGINQUERYPROC glad_glBeginQuery;
+#define glBeginQuery glad_glBeginQuery
+GLAD_API_CALL PFNGLBEGINQUERYARBPROC glad_glBeginQueryARB;
+#define glBeginQueryARB glad_glBeginQueryARB
+GLAD_API_CALL PFNGLBEGINQUERYINDEXEDPROC glad_glBeginQueryIndexed;
+#define glBeginQueryIndexed glad_glBeginQueryIndexed
+GLAD_API_CALL PFNGLBEGINTRANSFORMFEEDBACKPROC glad_glBeginTransformFeedback;
+#define glBeginTransformFeedback glad_glBeginTransformFeedback
+GLAD_API_CALL PFNGLBINDATTRIBLOCATIONPROC glad_glBindAttribLocation;
+#define glBindAttribLocation glad_glBindAttribLocation
+GLAD_API_CALL PFNGLBINDATTRIBLOCATIONARBPROC glad_glBindAttribLocationARB;
+#define glBindAttribLocationARB glad_glBindAttribLocationARB
+GLAD_API_CALL PFNGLBINDBUFFERPROC glad_glBindBuffer;
+#define glBindBuffer glad_glBindBuffer
+GLAD_API_CALL PFNGLBINDBUFFERARBPROC glad_glBindBufferARB;
+#define glBindBufferARB glad_glBindBufferARB
+GLAD_API_CALL PFNGLBINDBUFFERBASEPROC glad_glBindBufferBase;
+#define glBindBufferBase glad_glBindBufferBase
+GLAD_API_CALL PFNGLBINDBUFFERRANGEPROC glad_glBindBufferRange;
+#define glBindBufferRange glad_glBindBufferRange
+GLAD_API_CALL PFNGLBINDBUFFERSBASEPROC glad_glBindBuffersBase;
+#define glBindBuffersBase glad_glBindBuffersBase
+GLAD_API_CALL PFNGLBINDBUFFERSRANGEPROC glad_glBindBuffersRange;
+#define glBindBuffersRange glad_glBindBuffersRange
+GLAD_API_CALL PFNGLBINDFRAGDATALOCATIONPROC glad_glBindFragDataLocation;
+#define glBindFragDataLocation glad_glBindFragDataLocation
+GLAD_API_CALL PFNGLBINDFRAGDATALOCATIONINDEXEDPROC glad_glBindFragDataLocationIndexed;
+#define glBindFragDataLocationIndexed glad_glBindFragDataLocationIndexed
+GLAD_API_CALL PFNGLBINDFRAMEBUFFERPROC glad_glBindFramebuffer;
+#define glBindFramebuffer glad_glBindFramebuffer
+GLAD_API_CALL PFNGLBINDFRAMEBUFFEREXTPROC glad_glBindFramebufferEXT;
+#define glBindFramebufferEXT glad_glBindFramebufferEXT
+GLAD_API_CALL PFNGLBINDIMAGETEXTUREPROC glad_glBindImageTexture;
+#define glBindImageTexture glad_glBindImageTexture
+GLAD_API_CALL PFNGLBINDIMAGETEXTURESPROC glad_glBindImageTextures;
+#define glBindImageTextures glad_glBindImageTextures
+GLAD_API_CALL PFNGLBINDPROGRAMARBPROC glad_glBindProgramARB;
+#define glBindProgramARB glad_glBindProgramARB
+GLAD_API_CALL PFNGLBINDPROGRAMPIPELINEPROC glad_glBindProgramPipeline;
+#define glBindProgramPipeline glad_glBindProgramPipeline
+GLAD_API_CALL PFNGLBINDRENDERBUFFERPROC glad_glBindRenderbuffer;
+#define glBindRenderbuffer glad_glBindRenderbuffer
+GLAD_API_CALL PFNGLBINDRENDERBUFFEREXTPROC glad_glBindRenderbufferEXT;
+#define glBindRenderbufferEXT glad_glBindRenderbufferEXT
+GLAD_API_CALL PFNGLBINDSAMPLERPROC glad_glBindSampler;
+#define glBindSampler glad_glBindSampler
+GLAD_API_CALL PFNGLBINDSAMPLERSPROC glad_glBindSamplers;
+#define glBindSamplers glad_glBindSamplers
+GLAD_API_CALL PFNGLBINDTEXTUREPROC glad_glBindTexture;
+#define glBindTexture glad_glBindTexture
+GLAD_API_CALL PFNGLBINDTEXTUREUNITPROC glad_glBindTextureUnit;
+#define glBindTextureUnit glad_glBindTextureUnit
+GLAD_API_CALL PFNGLBINDTEXTURESPROC glad_glBindTextures;
+#define glBindTextures glad_glBindTextures
+GLAD_API_CALL PFNGLBINDTRANSFORMFEEDBACKPROC glad_glBindTransformFeedback;
+#define glBindTransformFeedback glad_glBindTransformFeedback
+GLAD_API_CALL PFNGLBINDVERTEXARRAYPROC glad_glBindVertexArray;
+#define glBindVertexArray glad_glBindVertexArray
+GLAD_API_CALL PFNGLBINDVERTEXBUFFERPROC glad_glBindVertexBuffer;
+#define glBindVertexBuffer glad_glBindVertexBuffer
+GLAD_API_CALL PFNGLBINDVERTEXBUFFERSPROC glad_glBindVertexBuffers;
+#define glBindVertexBuffers glad_glBindVertexBuffers
+GLAD_API_CALL PFNGLBITMAPXOESPROC glad_glBitmapxOES;
+#define glBitmapxOES glad_glBitmapxOES
+GLAD_API_CALL PFNGLBLENDCOLORPROC glad_glBlendColor;
+#define glBlendColor glad_glBlendColor
+GLAD_API_CALL PFNGLBLENDCOLORXOESPROC glad_glBlendColorxOES;
+#define glBlendColorxOES glad_glBlendColorxOES
+GLAD_API_CALL PFNGLBLENDEQUATIONPROC glad_glBlendEquation;
+#define glBlendEquation glad_glBlendEquation
+GLAD_API_CALL PFNGLBLENDEQUATIONSEPARATEPROC glad_glBlendEquationSeparate;
+#define glBlendEquationSeparate glad_glBlendEquationSeparate
+GLAD_API_CALL PFNGLBLENDEQUATIONSEPARATEIPROC glad_glBlendEquationSeparatei;
+#define glBlendEquationSeparatei glad_glBlendEquationSeparatei
+GLAD_API_CALL PFNGLBLENDEQUATIONSEPARATEIARBPROC glad_glBlendEquationSeparateiARB;
+#define glBlendEquationSeparateiARB glad_glBlendEquationSeparateiARB
+GLAD_API_CALL PFNGLBLENDEQUATIONIPROC glad_glBlendEquationi;
+#define glBlendEquationi glad_glBlendEquationi
+GLAD_API_CALL PFNGLBLENDEQUATIONIARBPROC glad_glBlendEquationiARB;
+#define glBlendEquationiARB glad_glBlendEquationiARB
+GLAD_API_CALL PFNGLBLENDFUNCPROC glad_glBlendFunc;
+#define glBlendFunc glad_glBlendFunc
+GLAD_API_CALL PFNGLBLENDFUNCSEPARATEPROC glad_glBlendFuncSeparate;
+#define glBlendFuncSeparate glad_glBlendFuncSeparate
+GLAD_API_CALL PFNGLBLENDFUNCSEPARATEIPROC glad_glBlendFuncSeparatei;
+#define glBlendFuncSeparatei glad_glBlendFuncSeparatei
+GLAD_API_CALL PFNGLBLENDFUNCSEPARATEIARBPROC glad_glBlendFuncSeparateiARB;
+#define glBlendFuncSeparateiARB glad_glBlendFuncSeparateiARB
+GLAD_API_CALL PFNGLBLENDFUNCIPROC glad_glBlendFunci;
+#define glBlendFunci glad_glBlendFunci
+GLAD_API_CALL PFNGLBLENDFUNCIARBPROC glad_glBlendFunciARB;
+#define glBlendFunciARB glad_glBlendFunciARB
+GLAD_API_CALL PFNGLBLITFRAMEBUFFERPROC glad_glBlitFramebuffer;
+#define glBlitFramebuffer glad_glBlitFramebuffer
+GLAD_API_CALL PFNGLBLITFRAMEBUFFEREXTPROC glad_glBlitFramebufferEXT;
+#define glBlitFramebufferEXT glad_glBlitFramebufferEXT
+GLAD_API_CALL PFNGLBLITNAMEDFRAMEBUFFERPROC glad_glBlitNamedFramebuffer;
+#define glBlitNamedFramebuffer glad_glBlitNamedFramebuffer
+GLAD_API_CALL PFNGLBUFFERDATAPROC glad_glBufferData;
+#define glBufferData glad_glBufferData
+GLAD_API_CALL PFNGLBUFFERDATAARBPROC glad_glBufferDataARB;
+#define glBufferDataARB glad_glBufferDataARB
+GLAD_API_CALL PFNGLBUFFERSTORAGEPROC glad_glBufferStorage;
+#define glBufferStorage glad_glBufferStorage
+GLAD_API_CALL PFNGLBUFFERSUBDATAPROC glad_glBufferSubData;
+#define glBufferSubData glad_glBufferSubData
+GLAD_API_CALL PFNGLBUFFERSUBDATAARBPROC glad_glBufferSubDataARB;
+#define glBufferSubDataARB glad_glBufferSubDataARB
+GLAD_API_CALL PFNGLCHECKFRAMEBUFFERSTATUSPROC glad_glCheckFramebufferStatus;
+#define glCheckFramebufferStatus glad_glCheckFramebufferStatus
+GLAD_API_CALL PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glad_glCheckFramebufferStatusEXT;
+#define glCheckFramebufferStatusEXT glad_glCheckFramebufferStatusEXT
+GLAD_API_CALL PFNGLCHECKNAMEDFRAMEBUFFERSTATUSPROC glad_glCheckNamedFramebufferStatus;
+#define glCheckNamedFramebufferStatus glad_glCheckNamedFramebufferStatus
+GLAD_API_CALL PFNGLCLAMPCOLORPROC glad_glClampColor;
+#define glClampColor glad_glClampColor
+GLAD_API_CALL PFNGLCLAMPCOLORARBPROC glad_glClampColorARB;
+#define glClampColorARB glad_glClampColorARB
+GLAD_API_CALL PFNGLCLEARPROC glad_glClear;
+#define glClear glad_glClear
+GLAD_API_CALL PFNGLCLEARACCUMXOESPROC glad_glClearAccumxOES;
+#define glClearAccumxOES glad_glClearAccumxOES
+GLAD_API_CALL PFNGLCLEARBUFFERDATAPROC glad_glClearBufferData;
+#define glClearBufferData glad_glClearBufferData
+GLAD_API_CALL PFNGLCLEARBUFFERSUBDATAPROC glad_glClearBufferSubData;
+#define glClearBufferSubData glad_glClearBufferSubData
+GLAD_API_CALL PFNGLCLEARBUFFERFIPROC glad_glClearBufferfi;
+#define glClearBufferfi glad_glClearBufferfi
+GLAD_API_CALL PFNGLCLEARBUFFERFVPROC glad_glClearBufferfv;
+#define glClearBufferfv glad_glClearBufferfv
+GLAD_API_CALL PFNGLCLEARBUFFERIVPROC glad_glClearBufferiv;
+#define glClearBufferiv glad_glClearBufferiv
+GLAD_API_CALL PFNGLCLEARBUFFERUIVPROC glad_glClearBufferuiv;
+#define glClearBufferuiv glad_glClearBufferuiv
+GLAD_API_CALL PFNGLCLEARCOLORPROC glad_glClearColor;
+#define glClearColor glad_glClearColor
+GLAD_API_CALL PFNGLCLEARCOLORXOESPROC glad_glClearColorxOES;
+#define glClearColorxOES glad_glClearColorxOES
+GLAD_API_CALL PFNGLCLEARDEPTHPROC glad_glClearDepth;
+#define glClearDepth glad_glClearDepth
+GLAD_API_CALL PFNGLCLEARDEPTHFPROC glad_glClearDepthf;
+#define glClearDepthf glad_glClearDepthf
+GLAD_API_CALL PFNGLCLEARDEPTHXOESPROC glad_glClearDepthxOES;
+#define glClearDepthxOES glad_glClearDepthxOES
+GLAD_API_CALL PFNGLCLEARNAMEDBUFFERDATAPROC glad_glClearNamedBufferData;
+#define glClearNamedBufferData glad_glClearNamedBufferData
+GLAD_API_CALL PFNGLCLEARNAMEDBUFFERSUBDATAPROC glad_glClearNamedBufferSubData;
+#define glClearNamedBufferSubData glad_glClearNamedBufferSubData
+GLAD_API_CALL PFNGLCLEARNAMEDFRAMEBUFFERFIPROC glad_glClearNamedFramebufferfi;
+#define glClearNamedFramebufferfi glad_glClearNamedFramebufferfi
+GLAD_API_CALL PFNGLCLEARNAMEDFRAMEBUFFERFVPROC glad_glClearNamedFramebufferfv;
+#define glClearNamedFramebufferfv glad_glClearNamedFramebufferfv
+GLAD_API_CALL PFNGLCLEARNAMEDFRAMEBUFFERIVPROC glad_glClearNamedFramebufferiv;
+#define glClearNamedFramebufferiv glad_glClearNamedFramebufferiv
+GLAD_API_CALL PFNGLCLEARNAMEDFRAMEBUFFERUIVPROC glad_glClearNamedFramebufferuiv;
+#define glClearNamedFramebufferuiv glad_glClearNamedFramebufferuiv
+GLAD_API_CALL PFNGLCLEARSTENCILPROC glad_glClearStencil;
+#define glClearStencil glad_glClearStencil
+GLAD_API_CALL PFNGLCLEARTEXIMAGEPROC glad_glClearTexImage;
+#define glClearTexImage glad_glClearTexImage
+GLAD_API_CALL PFNGLCLEARTEXSUBIMAGEPROC glad_glClearTexSubImage;
+#define glClearTexSubImage glad_glClearTexSubImage
+GLAD_API_CALL PFNGLCLIENTACTIVETEXTUREARBPROC glad_glClientActiveTextureARB;
+#define glClientActiveTextureARB glad_glClientActiveTextureARB
+GLAD_API_CALL PFNGLCLIENTWAITSYNCPROC glad_glClientWaitSync;
+#define glClientWaitSync glad_glClientWaitSync
+GLAD_API_CALL PFNGLCLIPPLANEXOESPROC glad_glClipPlanexOES;
+#define glClipPlanexOES glad_glClipPlanexOES
+GLAD_API_CALL PFNGLCOLOR3XOESPROC glad_glColor3xOES;
+#define glColor3xOES glad_glColor3xOES
+GLAD_API_CALL PFNGLCOLOR3XVOESPROC glad_glColor3xvOES;
+#define glColor3xvOES glad_glColor3xvOES
+GLAD_API_CALL PFNGLCOLOR4XOESPROC glad_glColor4xOES;
+#define glColor4xOES glad_glColor4xOES
+GLAD_API_CALL PFNGLCOLOR4XVOESPROC glad_glColor4xvOES;
+#define glColor4xvOES glad_glColor4xvOES
+GLAD_API_CALL PFNGLCOLORMASKPROC glad_glColorMask;
+#define glColorMask glad_glColorMask
+GLAD_API_CALL PFNGLCOLORMASKIPROC glad_glColorMaski;
+#define glColorMaski glad_glColorMaski
+GLAD_API_CALL PFNGLCOMPILESHADERPROC glad_glCompileShader;
+#define glCompileShader glad_glCompileShader
+GLAD_API_CALL PFNGLCOMPILESHADERARBPROC glad_glCompileShaderARB;
+#define glCompileShaderARB glad_glCompileShaderARB
+GLAD_API_CALL PFNGLCOMPILESHADERINCLUDEARBPROC glad_glCompileShaderIncludeARB;
+#define glCompileShaderIncludeARB glad_glCompileShaderIncludeARB
+GLAD_API_CALL PFNGLCOMPRESSEDTEXIMAGE1DPROC glad_glCompressedTexImage1D;
+#define glCompressedTexImage1D glad_glCompressedTexImage1D
+GLAD_API_CALL PFNGLCOMPRESSEDTEXIMAGE1DARBPROC glad_glCompressedTexImage1DARB;
+#define glCompressedTexImage1DARB glad_glCompressedTexImage1DARB
+GLAD_API_CALL PFNGLCOMPRESSEDTEXIMAGE2DPROC glad_glCompressedTexImage2D;
+#define glCompressedTexImage2D glad_glCompressedTexImage2D
+GLAD_API_CALL PFNGLCOMPRESSEDTEXIMAGE2DARBPROC glad_glCompressedTexImage2DARB;
+#define glCompressedTexImage2DARB glad_glCompressedTexImage2DARB
+GLAD_API_CALL PFNGLCOMPRESSEDTEXIMAGE3DPROC glad_glCompressedTexImage3D;
+#define glCompressedTexImage3D glad_glCompressedTexImage3D
+GLAD_API_CALL PFNGLCOMPRESSEDTEXIMAGE3DARBPROC glad_glCompressedTexImage3DARB;
+#define glCompressedTexImage3DARB glad_glCompressedTexImage3DARB
+GLAD_API_CALL PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC glad_glCompressedTexSubImage1D;
+#define glCompressedTexSubImage1D glad_glCompressedTexSubImage1D
+GLAD_API_CALL PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC glad_glCompressedTexSubImage1DARB;
+#define glCompressedTexSubImage1DARB glad_glCompressedTexSubImage1DARB
+GLAD_API_CALL PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC glad_glCompressedTexSubImage2D;
+#define glCompressedTexSubImage2D glad_glCompressedTexSubImage2D
+GLAD_API_CALL PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC glad_glCompressedTexSubImage2DARB;
+#define glCompressedTexSubImage2DARB glad_glCompressedTexSubImage2DARB
+GLAD_API_CALL PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC glad_glCompressedTexSubImage3D;
+#define glCompressedTexSubImage3D glad_glCompressedTexSubImage3D
+GLAD_API_CALL PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC glad_glCompressedTexSubImage3DARB;
+#define glCompressedTexSubImage3DARB glad_glCompressedTexSubImage3DARB
+GLAD_API_CALL PFNGLCOMPRESSEDTEXTURESUBIMAGE1DPROC glad_glCompressedTextureSubImage1D;
+#define glCompressedTextureSubImage1D glad_glCompressedTextureSubImage1D
+GLAD_API_CALL PFNGLCOMPRESSEDTEXTURESUBIMAGE2DPROC glad_glCompressedTextureSubImage2D;
+#define glCompressedTextureSubImage2D glad_glCompressedTextureSubImage2D
+GLAD_API_CALL PFNGLCOMPRESSEDTEXTURESUBIMAGE3DPROC glad_glCompressedTextureSubImage3D;
+#define glCompressedTextureSubImage3D glad_glCompressedTextureSubImage3D
+GLAD_API_CALL PFNGLCONVOLUTIONPARAMETERXOESPROC glad_glConvolutionParameterxOES;
+#define glConvolutionParameterxOES glad_glConvolutionParameterxOES
+GLAD_API_CALL PFNGLCONVOLUTIONPARAMETERXVOESPROC glad_glConvolutionParameterxvOES;
+#define glConvolutionParameterxvOES glad_glConvolutionParameterxvOES
+GLAD_API_CALL PFNGLCOPYBUFFERSUBDATAPROC glad_glCopyBufferSubData;
+#define glCopyBufferSubData glad_glCopyBufferSubData
+GLAD_API_CALL PFNGLCOPYIMAGESUBDATAPROC glad_glCopyImageSubData;
+#define glCopyImageSubData glad_glCopyImageSubData
+GLAD_API_CALL PFNGLCOPYNAMEDBUFFERSUBDATAPROC glad_glCopyNamedBufferSubData;
+#define glCopyNamedBufferSubData glad_glCopyNamedBufferSubData
+GLAD_API_CALL PFNGLCOPYTEXIMAGE1DPROC glad_glCopyTexImage1D;
+#define glCopyTexImage1D glad_glCopyTexImage1D
+GLAD_API_CALL PFNGLCOPYTEXIMAGE2DPROC glad_glCopyTexImage2D;
+#define glCopyTexImage2D glad_glCopyTexImage2D
+GLAD_API_CALL PFNGLCOPYTEXSUBIMAGE1DPROC glad_glCopyTexSubImage1D;
+#define glCopyTexSubImage1D glad_glCopyTexSubImage1D
+GLAD_API_CALL PFNGLCOPYTEXSUBIMAGE2DPROC glad_glCopyTexSubImage2D;
+#define glCopyTexSubImage2D glad_glCopyTexSubImage2D
+GLAD_API_CALL PFNGLCOPYTEXSUBIMAGE3DPROC glad_glCopyTexSubImage3D;
+#define glCopyTexSubImage3D glad_glCopyTexSubImage3D
+GLAD_API_CALL PFNGLCOPYTEXTURESUBIMAGE1DPROC glad_glCopyTextureSubImage1D;
+#define glCopyTextureSubImage1D glad_glCopyTextureSubImage1D
+GLAD_API_CALL PFNGLCOPYTEXTURESUBIMAGE2DPROC glad_glCopyTextureSubImage2D;
+#define glCopyTextureSubImage2D glad_glCopyTextureSubImage2D
+GLAD_API_CALL PFNGLCOPYTEXTURESUBIMAGE3DPROC glad_glCopyTextureSubImage3D;
+#define glCopyTextureSubImage3D glad_glCopyTextureSubImage3D
+GLAD_API_CALL PFNGLCREATEBUFFERSPROC glad_glCreateBuffers;
+#define glCreateBuffers glad_glCreateBuffers
+GLAD_API_CALL PFNGLCREATEFRAMEBUFFERSPROC glad_glCreateFramebuffers;
+#define glCreateFramebuffers glad_glCreateFramebuffers
+GLAD_API_CALL PFNGLCREATEPROGRAMPROC glad_glCreateProgram;
+#define glCreateProgram glad_glCreateProgram
+GLAD_API_CALL PFNGLCREATEPROGRAMOBJECTARBPROC glad_glCreateProgramObjectARB;
+#define glCreateProgramObjectARB glad_glCreateProgramObjectARB
+GLAD_API_CALL PFNGLCREATEPROGRAMPIPELINESPROC glad_glCreateProgramPipelines;
+#define glCreateProgramPipelines glad_glCreateProgramPipelines
+GLAD_API_CALL PFNGLCREATEQUERIESPROC glad_glCreateQueries;
+#define glCreateQueries glad_glCreateQueries
+GLAD_API_CALL PFNGLCREATERENDERBUFFERSPROC glad_glCreateRenderbuffers;
+#define glCreateRenderbuffers glad_glCreateRenderbuffers
+GLAD_API_CALL PFNGLCREATESAMPLERSPROC glad_glCreateSamplers;
+#define glCreateSamplers glad_glCreateSamplers
+GLAD_API_CALL PFNGLCREATESHADERPROC glad_glCreateShader;
+#define glCreateShader glad_glCreateShader
+GLAD_API_CALL PFNGLCREATESHADEROBJECTARBPROC glad_glCreateShaderObjectARB;
+#define glCreateShaderObjectARB glad_glCreateShaderObjectARB
+GLAD_API_CALL PFNGLCREATESHADERPROGRAMVPROC glad_glCreateShaderProgramv;
+#define glCreateShaderProgramv glad_glCreateShaderProgramv
+GLAD_API_CALL PFNGLCREATETEXTURESPROC glad_glCreateTextures;
+#define glCreateTextures glad_glCreateTextures
+GLAD_API_CALL PFNGLCREATETRANSFORMFEEDBACKSPROC glad_glCreateTransformFeedbacks;
+#define glCreateTransformFeedbacks glad_glCreateTransformFeedbacks
+GLAD_API_CALL PFNGLCREATEVERTEXARRAYSPROC glad_glCreateVertexArrays;
+#define glCreateVertexArrays glad_glCreateVertexArrays
+GLAD_API_CALL PFNGLCULLFACEPROC glad_glCullFace;
+#define glCullFace glad_glCullFace
+GLAD_API_CALL PFNGLDEBUGMESSAGECALLBACKPROC glad_glDebugMessageCallback;
+#define glDebugMessageCallback glad_glDebugMessageCallback
+GLAD_API_CALL PFNGLDEBUGMESSAGECALLBACKARBPROC glad_glDebugMessageCallbackARB;
+#define glDebugMessageCallbackARB glad_glDebugMessageCallbackARB
+GLAD_API_CALL PFNGLDEBUGMESSAGECONTROLPROC glad_glDebugMessageControl;
+#define glDebugMessageControl glad_glDebugMessageControl
+GLAD_API_CALL PFNGLDEBUGMESSAGECONTROLARBPROC glad_glDebugMessageControlARB;
+#define glDebugMessageControlARB glad_glDebugMessageControlARB
+GLAD_API_CALL PFNGLDEBUGMESSAGEINSERTPROC glad_glDebugMessageInsert;
+#define glDebugMessageInsert glad_glDebugMessageInsert
+GLAD_API_CALL PFNGLDEBUGMESSAGEINSERTARBPROC glad_glDebugMessageInsertARB;
+#define glDebugMessageInsertARB glad_glDebugMessageInsertARB
+GLAD_API_CALL PFNGLDELETEBUFFERSPROC glad_glDeleteBuffers;
+#define glDeleteBuffers glad_glDeleteBuffers
+GLAD_API_CALL PFNGLDELETEBUFFERSARBPROC glad_glDeleteBuffersARB;
+#define glDeleteBuffersARB glad_glDeleteBuffersARB
+GLAD_API_CALL PFNGLDELETEFRAMEBUFFERSPROC glad_glDeleteFramebuffers;
+#define glDeleteFramebuffers glad_glDeleteFramebuffers
+GLAD_API_CALL PFNGLDELETEFRAMEBUFFERSEXTPROC glad_glDeleteFramebuffersEXT;
+#define glDeleteFramebuffersEXT glad_glDeleteFramebuffersEXT
+GLAD_API_CALL PFNGLDELETENAMEDSTRINGARBPROC glad_glDeleteNamedStringARB;
+#define glDeleteNamedStringARB glad_glDeleteNamedStringARB
+GLAD_API_CALL PFNGLDELETEOBJECTARBPROC glad_glDeleteObjectARB;
+#define glDeleteObjectARB glad_glDeleteObjectARB
+GLAD_API_CALL PFNGLDELETEPROGRAMPROC glad_glDeleteProgram;
+#define glDeleteProgram glad_glDeleteProgram
+GLAD_API_CALL PFNGLDELETEPROGRAMPIPELINESPROC glad_glDeleteProgramPipelines;
+#define glDeleteProgramPipelines glad_glDeleteProgramPipelines
+GLAD_API_CALL PFNGLDELETEPROGRAMSARBPROC glad_glDeleteProgramsARB;
+#define glDeleteProgramsARB glad_glDeleteProgramsARB
+GLAD_API_CALL PFNGLDELETEQUERIESPROC glad_glDeleteQueries;
+#define glDeleteQueries glad_glDeleteQueries
+GLAD_API_CALL PFNGLDELETEQUERIESARBPROC glad_glDeleteQueriesARB;
+#define glDeleteQueriesARB glad_glDeleteQueriesARB
+GLAD_API_CALL PFNGLDELETERENDERBUFFERSPROC glad_glDeleteRenderbuffers;
+#define glDeleteRenderbuffers glad_glDeleteRenderbuffers
+GLAD_API_CALL PFNGLDELETERENDERBUFFERSEXTPROC glad_glDeleteRenderbuffersEXT;
+#define glDeleteRenderbuffersEXT glad_glDeleteRenderbuffersEXT
+GLAD_API_CALL PFNGLDELETESAMPLERSPROC glad_glDeleteSamplers;
+#define glDeleteSamplers glad_glDeleteSamplers
+GLAD_API_CALL PFNGLDELETESHADERPROC glad_glDeleteShader;
+#define glDeleteShader glad_glDeleteShader
+GLAD_API_CALL PFNGLDELETESYNCPROC glad_glDeleteSync;
+#define glDeleteSync glad_glDeleteSync
+GLAD_API_CALL PFNGLDELETETEXTURESPROC glad_glDeleteTextures;
+#define glDeleteTextures glad_glDeleteTextures
+GLAD_API_CALL PFNGLDELETETRANSFORMFEEDBACKSPROC glad_glDeleteTransformFeedbacks;
+#define glDeleteTransformFeedbacks glad_glDeleteTransformFeedbacks
+GLAD_API_CALL PFNGLDELETEVERTEXARRAYSPROC glad_glDeleteVertexArrays;
+#define glDeleteVertexArrays glad_glDeleteVertexArrays
+GLAD_API_CALL PFNGLDEPTHFUNCPROC glad_glDepthFunc;
+#define glDepthFunc glad_glDepthFunc
+GLAD_API_CALL PFNGLDEPTHMASKPROC glad_glDepthMask;
+#define glDepthMask glad_glDepthMask
+GLAD_API_CALL PFNGLDEPTHRANGEPROC glad_glDepthRange;
+#define glDepthRange glad_glDepthRange
+GLAD_API_CALL PFNGLDEPTHRANGEARRAYVPROC glad_glDepthRangeArrayv;
+#define glDepthRangeArrayv glad_glDepthRangeArrayv
+GLAD_API_CALL PFNGLDEPTHRANGEINDEXEDPROC glad_glDepthRangeIndexed;
+#define glDepthRangeIndexed glad_glDepthRangeIndexed
+GLAD_API_CALL PFNGLDEPTHRANGEFPROC glad_glDepthRangef;
+#define glDepthRangef glad_glDepthRangef
+GLAD_API_CALL PFNGLDEPTHRANGEXOESPROC glad_glDepthRangexOES;
+#define glDepthRangexOES glad_glDepthRangexOES
+GLAD_API_CALL PFNGLDETACHOBJECTARBPROC glad_glDetachObjectARB;
+#define glDetachObjectARB glad_glDetachObjectARB
+GLAD_API_CALL PFNGLDETACHSHADERPROC glad_glDetachShader;
+#define glDetachShader glad_glDetachShader
+GLAD_API_CALL PFNGLDISABLEPROC glad_glDisable;
+#define glDisable glad_glDisable
+GLAD_API_CALL PFNGLDISABLEVERTEXARRAYATTRIBPROC glad_glDisableVertexArrayAttrib;
+#define glDisableVertexArrayAttrib glad_glDisableVertexArrayAttrib
+GLAD_API_CALL PFNGLDISABLEVERTEXATTRIBARRAYPROC glad_glDisableVertexAttribArray;
+#define glDisableVertexAttribArray glad_glDisableVertexAttribArray
+GLAD_API_CALL PFNGLDISABLEVERTEXATTRIBARRAYARBPROC glad_glDisableVertexAttribArrayARB;
+#define glDisableVertexAttribArrayARB glad_glDisableVertexAttribArrayARB
+GLAD_API_CALL PFNGLDISABLEIPROC glad_glDisablei;
+#define glDisablei glad_glDisablei
+GLAD_API_CALL PFNGLDISPATCHCOMPUTEPROC glad_glDispatchCompute;
+#define glDispatchCompute glad_glDispatchCompute
+GLAD_API_CALL PFNGLDISPATCHCOMPUTEGROUPSIZEARBPROC glad_glDispatchComputeGroupSizeARB;
+#define glDispatchComputeGroupSizeARB glad_glDispatchComputeGroupSizeARB
+GLAD_API_CALL PFNGLDISPATCHCOMPUTEINDIRECTPROC glad_glDispatchComputeIndirect;
+#define glDispatchComputeIndirect glad_glDispatchComputeIndirect
+GLAD_API_CALL PFNGLDRAWARRAYSPROC glad_glDrawArrays;
+#define glDrawArrays glad_glDrawArrays
+GLAD_API_CALL PFNGLDRAWARRAYSINDIRECTPROC glad_glDrawArraysIndirect;
+#define glDrawArraysIndirect glad_glDrawArraysIndirect
+GLAD_API_CALL PFNGLDRAWARRAYSINSTANCEDPROC glad_glDrawArraysInstanced;
+#define glDrawArraysInstanced glad_glDrawArraysInstanced
+GLAD_API_CALL PFNGLDRAWARRAYSINSTANCEDARBPROC glad_glDrawArraysInstancedARB;
+#define glDrawArraysInstancedARB glad_glDrawArraysInstancedARB
+GLAD_API_CALL PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEPROC glad_glDrawArraysInstancedBaseInstance;
+#define glDrawArraysInstancedBaseInstance glad_glDrawArraysInstancedBaseInstance
+GLAD_API_CALL PFNGLDRAWARRAYSINSTANCEDEXTPROC glad_glDrawArraysInstancedEXT;
+#define glDrawArraysInstancedEXT glad_glDrawArraysInstancedEXT
+GLAD_API_CALL PFNGLDRAWBUFFERPROC glad_glDrawBuffer;
+#define glDrawBuffer glad_glDrawBuffer
+GLAD_API_CALL PFNGLDRAWBUFFERSPROC glad_glDrawBuffers;
+#define glDrawBuffers glad_glDrawBuffers
+GLAD_API_CALL PFNGLDRAWBUFFERSARBPROC glad_glDrawBuffersARB;
+#define glDrawBuffersARB glad_glDrawBuffersARB
+GLAD_API_CALL PFNGLDRAWELEMENTSPROC glad_glDrawElements;
+#define glDrawElements glad_glDrawElements
+GLAD_API_CALL PFNGLDRAWELEMENTSBASEVERTEXPROC glad_glDrawElementsBaseVertex;
+#define glDrawElementsBaseVertex glad_glDrawElementsBaseVertex
+GLAD_API_CALL PFNGLDRAWELEMENTSINDIRECTPROC glad_glDrawElementsIndirect;
+#define glDrawElementsIndirect glad_glDrawElementsIndirect
+GLAD_API_CALL PFNGLDRAWELEMENTSINSTANCEDPROC glad_glDrawElementsInstanced;
+#define glDrawElementsInstanced glad_glDrawElementsInstanced
+GLAD_API_CALL PFNGLDRAWELEMENTSINSTANCEDARBPROC glad_glDrawElementsInstancedARB;
+#define glDrawElementsInstancedARB glad_glDrawElementsInstancedARB
+GLAD_API_CALL PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEPROC glad_glDrawElementsInstancedBaseInstance;
+#define glDrawElementsInstancedBaseInstance glad_glDrawElementsInstancedBaseInstance
+GLAD_API_CALL PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC glad_glDrawElementsInstancedBaseVertex;
+#define glDrawElementsInstancedBaseVertex glad_glDrawElementsInstancedBaseVertex
+GLAD_API_CALL PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC glad_glDrawElementsInstancedBaseVertexBaseInstance;
+#define glDrawElementsInstancedBaseVertexBaseInstance glad_glDrawElementsInstancedBaseVertexBaseInstance
+GLAD_API_CALL PFNGLDRAWELEMENTSINSTANCEDEXTPROC glad_glDrawElementsInstancedEXT;
+#define glDrawElementsInstancedEXT glad_glDrawElementsInstancedEXT
+GLAD_API_CALL PFNGLDRAWRANGEELEMENTSPROC glad_glDrawRangeElements;
+#define glDrawRangeElements glad_glDrawRangeElements
+GLAD_API_CALL PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC glad_glDrawRangeElementsBaseVertex;
+#define glDrawRangeElementsBaseVertex glad_glDrawRangeElementsBaseVertex
+GLAD_API_CALL PFNGLDRAWTRANSFORMFEEDBACKPROC glad_glDrawTransformFeedback;
+#define glDrawTransformFeedback glad_glDrawTransformFeedback
+GLAD_API_CALL PFNGLDRAWTRANSFORMFEEDBACKINSTANCEDPROC glad_glDrawTransformFeedbackInstanced;
+#define glDrawTransformFeedbackInstanced glad_glDrawTransformFeedbackInstanced
+GLAD_API_CALL PFNGLDRAWTRANSFORMFEEDBACKSTREAMPROC glad_glDrawTransformFeedbackStream;
+#define glDrawTransformFeedbackStream glad_glDrawTransformFeedbackStream
+GLAD_API_CALL PFNGLDRAWTRANSFORMFEEDBACKSTREAMINSTANCEDPROC glad_glDrawTransformFeedbackStreamInstanced;
+#define glDrawTransformFeedbackStreamInstanced glad_glDrawTransformFeedbackStreamInstanced
+GLAD_API_CALL PFNGLENABLEPROC glad_glEnable;
+#define glEnable glad_glEnable
+GLAD_API_CALL PFNGLENABLEVERTEXARRAYATTRIBPROC glad_glEnableVertexArrayAttrib;
+#define glEnableVertexArrayAttrib glad_glEnableVertexArrayAttrib
+GLAD_API_CALL PFNGLENABLEVERTEXATTRIBARRAYPROC glad_glEnableVertexAttribArray;
+#define glEnableVertexAttribArray glad_glEnableVertexAttribArray
+GLAD_API_CALL PFNGLENABLEVERTEXATTRIBARRAYARBPROC glad_glEnableVertexAttribArrayARB;
+#define glEnableVertexAttribArrayARB glad_glEnableVertexAttribArrayARB
+GLAD_API_CALL PFNGLENABLEIPROC glad_glEnablei;
+#define glEnablei glad_glEnablei
+GLAD_API_CALL PFNGLENDCONDITIONALRENDERPROC glad_glEndConditionalRender;
+#define glEndConditionalRender glad_glEndConditionalRender
+GLAD_API_CALL PFNGLENDQUERYPROC glad_glEndQuery;
+#define glEndQuery glad_glEndQuery
+GLAD_API_CALL PFNGLENDQUERYARBPROC glad_glEndQueryARB;
+#define glEndQueryARB glad_glEndQueryARB
+GLAD_API_CALL PFNGLENDQUERYINDEXEDPROC glad_glEndQueryIndexed;
+#define glEndQueryIndexed glad_glEndQueryIndexed
+GLAD_API_CALL PFNGLENDTRANSFORMFEEDBACKPROC glad_glEndTransformFeedback;
+#define glEndTransformFeedback glad_glEndTransformFeedback
+GLAD_API_CALL PFNGLEVALCOORD1XOESPROC glad_glEvalCoord1xOES;
+#define glEvalCoord1xOES glad_glEvalCoord1xOES
+GLAD_API_CALL PFNGLEVALCOORD1XVOESPROC glad_glEvalCoord1xvOES;
+#define glEvalCoord1xvOES glad_glEvalCoord1xvOES
+GLAD_API_CALL PFNGLEVALCOORD2XOESPROC glad_glEvalCoord2xOES;
+#define glEvalCoord2xOES glad_glEvalCoord2xOES
+GLAD_API_CALL PFNGLEVALCOORD2XVOESPROC glad_glEvalCoord2xvOES;
+#define glEvalCoord2xvOES glad_glEvalCoord2xvOES
+GLAD_API_CALL PFNGLEVALUATEDEPTHVALUESARBPROC glad_glEvaluateDepthValuesARB;
+#define glEvaluateDepthValuesARB glad_glEvaluateDepthValuesARB
+GLAD_API_CALL PFNGLFEEDBACKBUFFERXOESPROC glad_glFeedbackBufferxOES;
+#define glFeedbackBufferxOES glad_glFeedbackBufferxOES
+GLAD_API_CALL PFNGLFENCESYNCPROC glad_glFenceSync;
+#define glFenceSync glad_glFenceSync
+GLAD_API_CALL PFNGLFINISHPROC glad_glFinish;
+#define glFinish glad_glFinish
+GLAD_API_CALL PFNGLFLUSHPROC glad_glFlush;
+#define glFlush glad_glFlush
+GLAD_API_CALL PFNGLFLUSHMAPPEDBUFFERRANGEPROC glad_glFlushMappedBufferRange;
+#define glFlushMappedBufferRange glad_glFlushMappedBufferRange
+GLAD_API_CALL PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEPROC glad_glFlushMappedNamedBufferRange;
+#define glFlushMappedNamedBufferRange glad_glFlushMappedNamedBufferRange
+GLAD_API_CALL PFNGLFOGCOORDPOINTEREXTPROC glad_glFogCoordPointerEXT;
+#define glFogCoordPointerEXT glad_glFogCoordPointerEXT
+GLAD_API_CALL PFNGLFOGCOORDDEXTPROC glad_glFogCoorddEXT;
+#define glFogCoorddEXT glad_glFogCoorddEXT
+GLAD_API_CALL PFNGLFOGCOORDDVEXTPROC glad_glFogCoorddvEXT;
+#define glFogCoorddvEXT glad_glFogCoorddvEXT
+GLAD_API_CALL PFNGLFOGCOORDFEXTPROC glad_glFogCoordfEXT;
+#define glFogCoordfEXT glad_glFogCoordfEXT
+GLAD_API_CALL PFNGLFOGCOORDFVEXTPROC glad_glFogCoordfvEXT;
+#define glFogCoordfvEXT glad_glFogCoordfvEXT
+GLAD_API_CALL PFNGLFOGXOESPROC glad_glFogxOES;
+#define glFogxOES glad_glFogxOES
+GLAD_API_CALL PFNGLFOGXVOESPROC glad_glFogxvOES;
+#define glFogxvOES glad_glFogxvOES
+GLAD_API_CALL PFNGLFRAMEBUFFERPARAMETERIPROC glad_glFramebufferParameteri;
+#define glFramebufferParameteri glad_glFramebufferParameteri
+GLAD_API_CALL PFNGLFRAMEBUFFERRENDERBUFFERPROC glad_glFramebufferRenderbuffer;
+#define glFramebufferRenderbuffer glad_glFramebufferRenderbuffer
+GLAD_API_CALL PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glad_glFramebufferRenderbufferEXT;
+#define glFramebufferRenderbufferEXT glad_glFramebufferRenderbufferEXT
+GLAD_API_CALL PFNGLFRAMEBUFFERSAMPLELOCATIONSFVARBPROC glad_glFramebufferSampleLocationsfvARB;
+#define glFramebufferSampleLocationsfvARB glad_glFramebufferSampleLocationsfvARB
+GLAD_API_CALL PFNGLFRAMEBUFFERTEXTUREPROC glad_glFramebufferTexture;
+#define glFramebufferTexture glad_glFramebufferTexture
+GLAD_API_CALL PFNGLFRAMEBUFFERTEXTURE1DPROC glad_glFramebufferTexture1D;
+#define glFramebufferTexture1D glad_glFramebufferTexture1D
+GLAD_API_CALL PFNGLFRAMEBUFFERTEXTURE1DEXTPROC glad_glFramebufferTexture1DEXT;
+#define glFramebufferTexture1DEXT glad_glFramebufferTexture1DEXT
+GLAD_API_CALL PFNGLFRAMEBUFFERTEXTURE2DPROC glad_glFramebufferTexture2D;
+#define glFramebufferTexture2D glad_glFramebufferTexture2D
+GLAD_API_CALL PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glad_glFramebufferTexture2DEXT;
+#define glFramebufferTexture2DEXT glad_glFramebufferTexture2DEXT
+GLAD_API_CALL PFNGLFRAMEBUFFERTEXTURE3DPROC glad_glFramebufferTexture3D;
+#define glFramebufferTexture3D glad_glFramebufferTexture3D
+GLAD_API_CALL PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glad_glFramebufferTexture3DEXT;
+#define glFramebufferTexture3DEXT glad_glFramebufferTexture3DEXT
+GLAD_API_CALL PFNGLFRAMEBUFFERTEXTUREARBPROC glad_glFramebufferTextureARB;
+#define glFramebufferTextureARB glad_glFramebufferTextureARB
+GLAD_API_CALL PFNGLFRAMEBUFFERTEXTUREFACEARBPROC glad_glFramebufferTextureFaceARB;
+#define glFramebufferTextureFaceARB glad_glFramebufferTextureFaceARB
+GLAD_API_CALL PFNGLFRAMEBUFFERTEXTURELAYERPROC glad_glFramebufferTextureLayer;
+#define glFramebufferTextureLayer glad_glFramebufferTextureLayer
+GLAD_API_CALL PFNGLFRAMEBUFFERTEXTURELAYERARBPROC glad_glFramebufferTextureLayerARB;
+#define glFramebufferTextureLayerARB glad_glFramebufferTextureLayerARB
+GLAD_API_CALL PFNGLFRONTFACEPROC glad_glFrontFace;
+#define glFrontFace glad_glFrontFace
+GLAD_API_CALL PFNGLFRUSTUMXOESPROC glad_glFrustumxOES;
+#define glFrustumxOES glad_glFrustumxOES
+GLAD_API_CALL PFNGLGENBUFFERSPROC glad_glGenBuffers;
+#define glGenBuffers glad_glGenBuffers
+GLAD_API_CALL PFNGLGENBUFFERSARBPROC glad_glGenBuffersARB;
+#define glGenBuffersARB glad_glGenBuffersARB
+GLAD_API_CALL PFNGLGENFRAMEBUFFERSPROC glad_glGenFramebuffers;
+#define glGenFramebuffers glad_glGenFramebuffers
+GLAD_API_CALL PFNGLGENFRAMEBUFFERSEXTPROC glad_glGenFramebuffersEXT;
+#define glGenFramebuffersEXT glad_glGenFramebuffersEXT
+GLAD_API_CALL PFNGLGENPROGRAMPIPELINESPROC glad_glGenProgramPipelines;
+#define glGenProgramPipelines glad_glGenProgramPipelines
+GLAD_API_CALL PFNGLGENPROGRAMSARBPROC glad_glGenProgramsARB;
+#define glGenProgramsARB glad_glGenProgramsARB
+GLAD_API_CALL PFNGLGENQUERIESPROC glad_glGenQueries;
+#define glGenQueries glad_glGenQueries
+GLAD_API_CALL PFNGLGENQUERIESARBPROC glad_glGenQueriesARB;
+#define glGenQueriesARB glad_glGenQueriesARB
+GLAD_API_CALL PFNGLGENRENDERBUFFERSPROC glad_glGenRenderbuffers;
+#define glGenRenderbuffers glad_glGenRenderbuffers
+GLAD_API_CALL PFNGLGENRENDERBUFFERSEXTPROC glad_glGenRenderbuffersEXT;
+#define glGenRenderbuffersEXT glad_glGenRenderbuffersEXT
+GLAD_API_CALL PFNGLGENSAMPLERSPROC glad_glGenSamplers;
+#define glGenSamplers glad_glGenSamplers
+GLAD_API_CALL PFNGLGENTEXTURESPROC glad_glGenTextures;
+#define glGenTextures glad_glGenTextures
+GLAD_API_CALL PFNGLGENTRANSFORMFEEDBACKSPROC glad_glGenTransformFeedbacks;
+#define glGenTransformFeedbacks glad_glGenTransformFeedbacks
+GLAD_API_CALL PFNGLGENVERTEXARRAYSPROC glad_glGenVertexArrays;
+#define glGenVertexArrays glad_glGenVertexArrays
+GLAD_API_CALL PFNGLGENERATEMIPMAPPROC glad_glGenerateMipmap;
+#define glGenerateMipmap glad_glGenerateMipmap
+GLAD_API_CALL PFNGLGENERATEMIPMAPEXTPROC glad_glGenerateMipmapEXT;
+#define glGenerateMipmapEXT glad_glGenerateMipmapEXT
+GLAD_API_CALL PFNGLGENERATETEXTUREMIPMAPPROC glad_glGenerateTextureMipmap;
+#define glGenerateTextureMipmap glad_glGenerateTextureMipmap
+GLAD_API_CALL PFNGLGETACTIVEATOMICCOUNTERBUFFERIVPROC glad_glGetActiveAtomicCounterBufferiv;
+#define glGetActiveAtomicCounterBufferiv glad_glGetActiveAtomicCounterBufferiv
+GLAD_API_CALL PFNGLGETACTIVEATTRIBPROC glad_glGetActiveAttrib;
+#define glGetActiveAttrib glad_glGetActiveAttrib
+GLAD_API_CALL PFNGLGETACTIVEATTRIBARBPROC glad_glGetActiveAttribARB;
+#define glGetActiveAttribARB glad_glGetActiveAttribARB
+GLAD_API_CALL PFNGLGETACTIVESUBROUTINENAMEPROC glad_glGetActiveSubroutineName;
+#define glGetActiveSubroutineName glad_glGetActiveSubroutineName
+GLAD_API_CALL PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC glad_glGetActiveSubroutineUniformName;
+#define glGetActiveSubroutineUniformName glad_glGetActiveSubroutineUniformName
+GLAD_API_CALL PFNGLGETACTIVESUBROUTINEUNIFORMIVPROC glad_glGetActiveSubroutineUniformiv;
+#define glGetActiveSubroutineUniformiv glad_glGetActiveSubroutineUniformiv
+GLAD_API_CALL PFNGLGETACTIVEUNIFORMPROC glad_glGetActiveUniform;
+#define glGetActiveUniform glad_glGetActiveUniform
+GLAD_API_CALL PFNGLGETACTIVEUNIFORMARBPROC glad_glGetActiveUniformARB;
+#define glGetActiveUniformARB glad_glGetActiveUniformARB
+GLAD_API_CALL PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC glad_glGetActiveUniformBlockName;
+#define glGetActiveUniformBlockName glad_glGetActiveUniformBlockName
+GLAD_API_CALL PFNGLGETACTIVEUNIFORMBLOCKIVPROC glad_glGetActiveUniformBlockiv;
+#define glGetActiveUniformBlockiv glad_glGetActiveUniformBlockiv
+GLAD_API_CALL PFNGLGETACTIVEUNIFORMNAMEPROC glad_glGetActiveUniformName;
+#define glGetActiveUniformName glad_glGetActiveUniformName
+GLAD_API_CALL PFNGLGETACTIVEUNIFORMSIVPROC glad_glGetActiveUniformsiv;
+#define glGetActiveUniformsiv glad_glGetActiveUniformsiv
+GLAD_API_CALL PFNGLGETATTACHEDOBJECTSARBPROC glad_glGetAttachedObjectsARB;
+#define glGetAttachedObjectsARB glad_glGetAttachedObjectsARB
+GLAD_API_CALL PFNGLGETATTACHEDSHADERSPROC glad_glGetAttachedShaders;
+#define glGetAttachedShaders glad_glGetAttachedShaders
+GLAD_API_CALL PFNGLGETATTRIBLOCATIONPROC glad_glGetAttribLocation;
+#define glGetAttribLocation glad_glGetAttribLocation
+GLAD_API_CALL PFNGLGETATTRIBLOCATIONARBPROC glad_glGetAttribLocationARB;
+#define glGetAttribLocationARB glad_glGetAttribLocationARB
+GLAD_API_CALL PFNGLGETBOOLEANI_VPROC glad_glGetBooleani_v;
+#define glGetBooleani_v glad_glGetBooleani_v
+GLAD_API_CALL PFNGLGETBOOLEANVPROC glad_glGetBooleanv;
+#define glGetBooleanv glad_glGetBooleanv
+GLAD_API_CALL PFNGLGETBUFFERPARAMETERI64VPROC glad_glGetBufferParameteri64v;
+#define glGetBufferParameteri64v glad_glGetBufferParameteri64v
+GLAD_API_CALL PFNGLGETBUFFERPARAMETERIVPROC glad_glGetBufferParameteriv;
+#define glGetBufferParameteriv glad_glGetBufferParameteriv
+GLAD_API_CALL PFNGLGETBUFFERPARAMETERIVARBPROC glad_glGetBufferParameterivARB;
+#define glGetBufferParameterivARB glad_glGetBufferParameterivARB
+GLAD_API_CALL PFNGLGETBUFFERPOINTERVPROC glad_glGetBufferPointerv;
+#define glGetBufferPointerv glad_glGetBufferPointerv
+GLAD_API_CALL PFNGLGETBUFFERPOINTERVARBPROC glad_glGetBufferPointervARB;
+#define glGetBufferPointervARB glad_glGetBufferPointervARB
+GLAD_API_CALL PFNGLGETBUFFERSUBDATAPROC glad_glGetBufferSubData;
+#define glGetBufferSubData glad_glGetBufferSubData
+GLAD_API_CALL PFNGLGETBUFFERSUBDATAARBPROC glad_glGetBufferSubDataARB;
+#define glGetBufferSubDataARB glad_glGetBufferSubDataARB
+GLAD_API_CALL PFNGLGETCLIPPLANEXOESPROC glad_glGetClipPlanexOES;
+#define glGetClipPlanexOES glad_glGetClipPlanexOES
+GLAD_API_CALL PFNGLGETCOMPRESSEDTEXIMAGEPROC glad_glGetCompressedTexImage;
+#define glGetCompressedTexImage glad_glGetCompressedTexImage
+GLAD_API_CALL PFNGLGETCOMPRESSEDTEXIMAGEARBPROC glad_glGetCompressedTexImageARB;
+#define glGetCompressedTexImageARB glad_glGetCompressedTexImageARB
+GLAD_API_CALL PFNGLGETCOMPRESSEDTEXTUREIMAGEPROC glad_glGetCompressedTextureImage;
+#define glGetCompressedTextureImage glad_glGetCompressedTextureImage
+GLAD_API_CALL PFNGLGETCOMPRESSEDTEXTURESUBIMAGEPROC glad_glGetCompressedTextureSubImage;
+#define glGetCompressedTextureSubImage glad_glGetCompressedTextureSubImage
+GLAD_API_CALL PFNGLGETCONVOLUTIONPARAMETERXVOESPROC glad_glGetConvolutionParameterxvOES;
+#define glGetConvolutionParameterxvOES glad_glGetConvolutionParameterxvOES
+GLAD_API_CALL PFNGLGETDEBUGMESSAGELOGPROC glad_glGetDebugMessageLog;
+#define glGetDebugMessageLog glad_glGetDebugMessageLog
+GLAD_API_CALL PFNGLGETDEBUGMESSAGELOGARBPROC glad_glGetDebugMessageLogARB;
+#define glGetDebugMessageLogARB glad_glGetDebugMessageLogARB
+GLAD_API_CALL PFNGLGETDOUBLEI_VPROC glad_glGetDoublei_v;
+#define glGetDoublei_v glad_glGetDoublei_v
+GLAD_API_CALL PFNGLGETDOUBLEVPROC glad_glGetDoublev;
+#define glGetDoublev glad_glGetDoublev
+GLAD_API_CALL PFNGLGETERRORPROC glad_glGetError;
+#define glGetError glad_glGetError
+GLAD_API_CALL PFNGLGETFIXEDVOESPROC glad_glGetFixedvOES;
+#define glGetFixedvOES glad_glGetFixedvOES
+GLAD_API_CALL PFNGLGETFLOATI_VPROC glad_glGetFloati_v;
+#define glGetFloati_v glad_glGetFloati_v
+GLAD_API_CALL PFNGLGETFLOATVPROC glad_glGetFloatv;
+#define glGetFloatv glad_glGetFloatv
+GLAD_API_CALL PFNGLGETFRAGDATAINDEXPROC glad_glGetFragDataIndex;
+#define glGetFragDataIndex glad_glGetFragDataIndex
+GLAD_API_CALL PFNGLGETFRAGDATALOCATIONPROC glad_glGetFragDataLocation;
+#define glGetFragDataLocation glad_glGetFragDataLocation
+GLAD_API_CALL PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glad_glGetFramebufferAttachmentParameteriv;
+#define glGetFramebufferAttachmentParameteriv glad_glGetFramebufferAttachmentParameteriv
+GLAD_API_CALL PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glad_glGetFramebufferAttachmentParameterivEXT;
+#define glGetFramebufferAttachmentParameterivEXT glad_glGetFramebufferAttachmentParameterivEXT
+GLAD_API_CALL PFNGLGETFRAMEBUFFERPARAMETERIVPROC glad_glGetFramebufferParameteriv;
+#define glGetFramebufferParameteriv glad_glGetFramebufferParameteriv
+GLAD_API_CALL PFNGLGETHANDLEARBPROC glad_glGetHandleARB;
+#define glGetHandleARB glad_glGetHandleARB
+GLAD_API_CALL PFNGLGETHISTOGRAMPARAMETERXVOESPROC glad_glGetHistogramParameterxvOES;
+#define glGetHistogramParameterxvOES glad_glGetHistogramParameterxvOES
+GLAD_API_CALL PFNGLGETINFOLOGARBPROC glad_glGetInfoLogARB;
+#define glGetInfoLogARB glad_glGetInfoLogARB
+GLAD_API_CALL PFNGLGETINTEGER64I_VPROC glad_glGetInteger64i_v;
+#define glGetInteger64i_v glad_glGetInteger64i_v
+GLAD_API_CALL PFNGLGETINTEGER64VPROC glad_glGetInteger64v;
+#define glGetInteger64v glad_glGetInteger64v
+GLAD_API_CALL PFNGLGETINTEGERI_VPROC glad_glGetIntegeri_v;
+#define glGetIntegeri_v glad_glGetIntegeri_v
+GLAD_API_CALL PFNGLGETINTEGERVPROC glad_glGetIntegerv;
+#define glGetIntegerv glad_glGetIntegerv
+GLAD_API_CALL PFNGLGETINTERNALFORMATI64VPROC glad_glGetInternalformati64v;
+#define glGetInternalformati64v glad_glGetInternalformati64v
+GLAD_API_CALL PFNGLGETINTERNALFORMATIVPROC glad_glGetInternalformativ;
+#define glGetInternalformativ glad_glGetInternalformativ
+GLAD_API_CALL PFNGLGETLIGHTXOESPROC glad_glGetLightxOES;
+#define glGetLightxOES glad_glGetLightxOES
+GLAD_API_CALL PFNGLGETMAPXVOESPROC glad_glGetMapxvOES;
+#define glGetMapxvOES glad_glGetMapxvOES
+GLAD_API_CALL PFNGLGETMATERIALXOESPROC glad_glGetMaterialxOES;
+#define glGetMaterialxOES glad_glGetMaterialxOES
+GLAD_API_CALL PFNGLGETMULTISAMPLEFVPROC glad_glGetMultisamplefv;
+#define glGetMultisamplefv glad_glGetMultisamplefv
+GLAD_API_CALL PFNGLGETNAMEDBUFFERPARAMETERI64VPROC glad_glGetNamedBufferParameteri64v;
+#define glGetNamedBufferParameteri64v glad_glGetNamedBufferParameteri64v
+GLAD_API_CALL PFNGLGETNAMEDBUFFERPARAMETERIVPROC glad_glGetNamedBufferParameteriv;
+#define glGetNamedBufferParameteriv glad_glGetNamedBufferParameteriv
+GLAD_API_CALL PFNGLGETNAMEDBUFFERPOINTERVPROC glad_glGetNamedBufferPointerv;
+#define glGetNamedBufferPointerv glad_glGetNamedBufferPointerv
+GLAD_API_CALL PFNGLGETNAMEDBUFFERSUBDATAPROC glad_glGetNamedBufferSubData;
+#define glGetNamedBufferSubData glad_glGetNamedBufferSubData
+GLAD_API_CALL PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVPROC glad_glGetNamedFramebufferAttachmentParameteriv;
+#define glGetNamedFramebufferAttachmentParameteriv glad_glGetNamedFramebufferAttachmentParameteriv
+GLAD_API_CALL PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVPROC glad_glGetNamedFramebufferParameteriv;
+#define glGetNamedFramebufferParameteriv glad_glGetNamedFramebufferParameteriv
+GLAD_API_CALL PFNGLGETNAMEDRENDERBUFFERPARAMETERIVPROC glad_glGetNamedRenderbufferParameteriv;
+#define glGetNamedRenderbufferParameteriv glad_glGetNamedRenderbufferParameteriv
+GLAD_API_CALL PFNGLGETNAMEDSTRINGARBPROC glad_glGetNamedStringARB;
+#define glGetNamedStringARB glad_glGetNamedStringARB
+GLAD_API_CALL PFNGLGETNAMEDSTRINGIVARBPROC glad_glGetNamedStringivARB;
+#define glGetNamedStringivARB glad_glGetNamedStringivARB
+GLAD_API_CALL PFNGLGETOBJECTLABELPROC glad_glGetObjectLabel;
+#define glGetObjectLabel glad_glGetObjectLabel
+GLAD_API_CALL PFNGLGETOBJECTPARAMETERFVARBPROC glad_glGetObjectParameterfvARB;
+#define glGetObjectParameterfvARB glad_glGetObjectParameterfvARB
+GLAD_API_CALL PFNGLGETOBJECTPARAMETERIVARBPROC glad_glGetObjectParameterivARB;
+#define glGetObjectParameterivARB glad_glGetObjectParameterivARB
+GLAD_API_CALL PFNGLGETOBJECTPTRLABELPROC glad_glGetObjectPtrLabel;
+#define glGetObjectPtrLabel glad_glGetObjectPtrLabel
+GLAD_API_CALL PFNGLGETPIXELMAPXVPROC glad_glGetPixelMapxv;
+#define glGetPixelMapxv glad_glGetPixelMapxv
+GLAD_API_CALL PFNGLGETPOINTERVPROC glad_glGetPointerv;
+#define glGetPointerv glad_glGetPointerv
+GLAD_API_CALL PFNGLGETPROGRAMBINARYPROC glad_glGetProgramBinary;
+#define glGetProgramBinary glad_glGetProgramBinary
+GLAD_API_CALL PFNGLGETPROGRAMENVPARAMETERDVARBPROC glad_glGetProgramEnvParameterdvARB;
+#define glGetProgramEnvParameterdvARB glad_glGetProgramEnvParameterdvARB
+GLAD_API_CALL PFNGLGETPROGRAMENVPARAMETERFVARBPROC glad_glGetProgramEnvParameterfvARB;
+#define glGetProgramEnvParameterfvARB glad_glGetProgramEnvParameterfvARB
+GLAD_API_CALL PFNGLGETPROGRAMINFOLOGPROC glad_glGetProgramInfoLog;
+#define glGetProgramInfoLog glad_glGetProgramInfoLog
+GLAD_API_CALL PFNGLGETPROGRAMINTERFACEIVPROC glad_glGetProgramInterfaceiv;
+#define glGetProgramInterfaceiv glad_glGetProgramInterfaceiv
+GLAD_API_CALL PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC glad_glGetProgramLocalParameterdvARB;
+#define glGetProgramLocalParameterdvARB glad_glGetProgramLocalParameterdvARB
+GLAD_API_CALL PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC glad_glGetProgramLocalParameterfvARB;
+#define glGetProgramLocalParameterfvARB glad_glGetProgramLocalParameterfvARB
+GLAD_API_CALL PFNGLGETPROGRAMPIPELINEINFOLOGPROC glad_glGetProgramPipelineInfoLog;
+#define glGetProgramPipelineInfoLog glad_glGetProgramPipelineInfoLog
+GLAD_API_CALL PFNGLGETPROGRAMPIPELINEIVPROC glad_glGetProgramPipelineiv;
+#define glGetProgramPipelineiv glad_glGetProgramPipelineiv
+GLAD_API_CALL PFNGLGETPROGRAMRESOURCEINDEXPROC glad_glGetProgramResourceIndex;
+#define glGetProgramResourceIndex glad_glGetProgramResourceIndex
+GLAD_API_CALL PFNGLGETPROGRAMRESOURCELOCATIONPROC glad_glGetProgramResourceLocation;
+#define glGetProgramResourceLocation glad_glGetProgramResourceLocation
+GLAD_API_CALL PFNGLGETPROGRAMRESOURCELOCATIONINDEXPROC glad_glGetProgramResourceLocationIndex;
+#define glGetProgramResourceLocationIndex glad_glGetProgramResourceLocationIndex
+GLAD_API_CALL PFNGLGETPROGRAMRESOURCENAMEPROC glad_glGetProgramResourceName;
+#define glGetProgramResourceName glad_glGetProgramResourceName
+GLAD_API_CALL PFNGLGETPROGRAMRESOURCEIVPROC glad_glGetProgramResourceiv;
+#define glGetProgramResourceiv glad_glGetProgramResourceiv
+GLAD_API_CALL PFNGLGETPROGRAMSTAGEIVPROC glad_glGetProgramStageiv;
+#define glGetProgramStageiv glad_glGetProgramStageiv
+GLAD_API_CALL PFNGLGETPROGRAMSTRINGARBPROC glad_glGetProgramStringARB;
+#define glGetProgramStringARB glad_glGetProgramStringARB
+GLAD_API_CALL PFNGLGETPROGRAMIVPROC glad_glGetProgramiv;
+#define glGetProgramiv glad_glGetProgramiv
+GLAD_API_CALL PFNGLGETPROGRAMIVARBPROC glad_glGetProgramivARB;
+#define glGetProgramivARB glad_glGetProgramivARB
+GLAD_API_CALL PFNGLGETQUERYBUFFEROBJECTI64VPROC glad_glGetQueryBufferObjecti64v;
+#define glGetQueryBufferObjecti64v glad_glGetQueryBufferObjecti64v
+GLAD_API_CALL PFNGLGETQUERYBUFFEROBJECTIVPROC glad_glGetQueryBufferObjectiv;
+#define glGetQueryBufferObjectiv glad_glGetQueryBufferObjectiv
+GLAD_API_CALL PFNGLGETQUERYBUFFEROBJECTUI64VPROC glad_glGetQueryBufferObjectui64v;
+#define glGetQueryBufferObjectui64v glad_glGetQueryBufferObjectui64v
+GLAD_API_CALL PFNGLGETQUERYBUFFEROBJECTUIVPROC glad_glGetQueryBufferObjectuiv;
+#define glGetQueryBufferObjectuiv glad_glGetQueryBufferObjectuiv
+GLAD_API_CALL PFNGLGETQUERYINDEXEDIVPROC glad_glGetQueryIndexediv;
+#define glGetQueryIndexediv glad_glGetQueryIndexediv
+GLAD_API_CALL PFNGLGETQUERYOBJECTI64VPROC glad_glGetQueryObjecti64v;
+#define glGetQueryObjecti64v glad_glGetQueryObjecti64v
+GLAD_API_CALL PFNGLGETQUERYOBJECTIVPROC glad_glGetQueryObjectiv;
+#define glGetQueryObjectiv glad_glGetQueryObjectiv
+GLAD_API_CALL PFNGLGETQUERYOBJECTIVARBPROC glad_glGetQueryObjectivARB;
+#define glGetQueryObjectivARB glad_glGetQueryObjectivARB
+GLAD_API_CALL PFNGLGETQUERYOBJECTUI64VPROC glad_glGetQueryObjectui64v;
+#define glGetQueryObjectui64v glad_glGetQueryObjectui64v
+GLAD_API_CALL PFNGLGETQUERYOBJECTUIVPROC glad_glGetQueryObjectuiv;
+#define glGetQueryObjectuiv glad_glGetQueryObjectuiv
+GLAD_API_CALL PFNGLGETQUERYOBJECTUIVARBPROC glad_glGetQueryObjectuivARB;
+#define glGetQueryObjectuivARB glad_glGetQueryObjectuivARB
+GLAD_API_CALL PFNGLGETQUERYIVPROC glad_glGetQueryiv;
+#define glGetQueryiv glad_glGetQueryiv
+GLAD_API_CALL PFNGLGETQUERYIVARBPROC glad_glGetQueryivARB;
+#define glGetQueryivARB glad_glGetQueryivARB
+GLAD_API_CALL PFNGLGETRENDERBUFFERPARAMETERIVPROC glad_glGetRenderbufferParameteriv;
+#define glGetRenderbufferParameteriv glad_glGetRenderbufferParameteriv
+GLAD_API_CALL PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC glad_glGetRenderbufferParameterivEXT;
+#define glGetRenderbufferParameterivEXT glad_glGetRenderbufferParameterivEXT
+GLAD_API_CALL PFNGLGETSAMPLERPARAMETERIIVPROC glad_glGetSamplerParameterIiv;
+#define glGetSamplerParameterIiv glad_glGetSamplerParameterIiv
+GLAD_API_CALL PFNGLGETSAMPLERPARAMETERIUIVPROC glad_glGetSamplerParameterIuiv;
+#define glGetSamplerParameterIuiv glad_glGetSamplerParameterIuiv
+GLAD_API_CALL PFNGLGETSAMPLERPARAMETERFVPROC glad_glGetSamplerParameterfv;
+#define glGetSamplerParameterfv glad_glGetSamplerParameterfv
+GLAD_API_CALL PFNGLGETSAMPLERPARAMETERIVPROC glad_glGetSamplerParameteriv;
+#define glGetSamplerParameteriv glad_glGetSamplerParameteriv
+GLAD_API_CALL PFNGLGETSHADERINFOLOGPROC glad_glGetShaderInfoLog;
+#define glGetShaderInfoLog glad_glGetShaderInfoLog
+GLAD_API_CALL PFNGLGETSHADERPRECISIONFORMATPROC glad_glGetShaderPrecisionFormat;
+#define glGetShaderPrecisionFormat glad_glGetShaderPrecisionFormat
+GLAD_API_CALL PFNGLGETSHADERSOURCEPROC glad_glGetShaderSource;
+#define glGetShaderSource glad_glGetShaderSource
+GLAD_API_CALL PFNGLGETSHADERSOURCEARBPROC glad_glGetShaderSourceARB;
+#define glGetShaderSourceARB glad_glGetShaderSourceARB
+GLAD_API_CALL PFNGLGETSHADERIVPROC glad_glGetShaderiv;
+#define glGetShaderiv glad_glGetShaderiv
+GLAD_API_CALL PFNGLGETSTRINGPROC glad_glGetString;
+#define glGetString glad_glGetString
+GLAD_API_CALL PFNGLGETSTRINGIPROC glad_glGetStringi;
+#define glGetStringi glad_glGetStringi
+GLAD_API_CALL PFNGLGETSUBROUTINEINDEXPROC glad_glGetSubroutineIndex;
+#define glGetSubroutineIndex glad_glGetSubroutineIndex
+GLAD_API_CALL PFNGLGETSUBROUTINEUNIFORMLOCATIONPROC glad_glGetSubroutineUniformLocation;
+#define glGetSubroutineUniformLocation glad_glGetSubroutineUniformLocation
+GLAD_API_CALL PFNGLGETSYNCIVPROC glad_glGetSynciv;
+#define glGetSynciv glad_glGetSynciv
+GLAD_API_CALL PFNGLGETTEXENVXVOESPROC glad_glGetTexEnvxvOES;
+#define glGetTexEnvxvOES glad_glGetTexEnvxvOES
+GLAD_API_CALL PFNGLGETTEXGENXVOESPROC glad_glGetTexGenxvOES;
+#define glGetTexGenxvOES glad_glGetTexGenxvOES
+GLAD_API_CALL PFNGLGETTEXIMAGEPROC glad_glGetTexImage;
+#define glGetTexImage glad_glGetTexImage
+GLAD_API_CALL PFNGLGETTEXLEVELPARAMETERFVPROC glad_glGetTexLevelParameterfv;
+#define glGetTexLevelParameterfv glad_glGetTexLevelParameterfv
+GLAD_API_CALL PFNGLGETTEXLEVELPARAMETERIVPROC glad_glGetTexLevelParameteriv;
+#define glGetTexLevelParameteriv glad_glGetTexLevelParameteriv
+GLAD_API_CALL PFNGLGETTEXLEVELPARAMETERXVOESPROC glad_glGetTexLevelParameterxvOES;
+#define glGetTexLevelParameterxvOES glad_glGetTexLevelParameterxvOES
+GLAD_API_CALL PFNGLGETTEXPARAMETERIIVPROC glad_glGetTexParameterIiv;
+#define glGetTexParameterIiv glad_glGetTexParameterIiv
+GLAD_API_CALL PFNGLGETTEXPARAMETERIUIVPROC glad_glGetTexParameterIuiv;
+#define glGetTexParameterIuiv glad_glGetTexParameterIuiv
+GLAD_API_CALL PFNGLGETTEXPARAMETERFVPROC glad_glGetTexParameterfv;
+#define glGetTexParameterfv glad_glGetTexParameterfv
+GLAD_API_CALL PFNGLGETTEXPARAMETERIVPROC glad_glGetTexParameteriv;
+#define glGetTexParameteriv glad_glGetTexParameteriv
+GLAD_API_CALL PFNGLGETTEXPARAMETERXVOESPROC glad_glGetTexParameterxvOES;
+#define glGetTexParameterxvOES glad_glGetTexParameterxvOES
+GLAD_API_CALL PFNGLGETTEXTUREIMAGEPROC glad_glGetTextureImage;
+#define glGetTextureImage glad_glGetTextureImage
+GLAD_API_CALL PFNGLGETTEXTURELEVELPARAMETERFVPROC glad_glGetTextureLevelParameterfv;
+#define glGetTextureLevelParameterfv glad_glGetTextureLevelParameterfv
+GLAD_API_CALL PFNGLGETTEXTURELEVELPARAMETERIVPROC glad_glGetTextureLevelParameteriv;
+#define glGetTextureLevelParameteriv glad_glGetTextureLevelParameteriv
+GLAD_API_CALL PFNGLGETTEXTUREPARAMETERIIVPROC glad_glGetTextureParameterIiv;
+#define glGetTextureParameterIiv glad_glGetTextureParameterIiv
+GLAD_API_CALL PFNGLGETTEXTUREPARAMETERIUIVPROC glad_glGetTextureParameterIuiv;
+#define glGetTextureParameterIuiv glad_glGetTextureParameterIuiv
+GLAD_API_CALL PFNGLGETTEXTUREPARAMETERFVPROC glad_glGetTextureParameterfv;
+#define glGetTextureParameterfv glad_glGetTextureParameterfv
+GLAD_API_CALL PFNGLGETTEXTUREPARAMETERIVPROC glad_glGetTextureParameteriv;
+#define glGetTextureParameteriv glad_glGetTextureParameteriv
+GLAD_API_CALL PFNGLGETTEXTURESUBIMAGEPROC glad_glGetTextureSubImage;
+#define glGetTextureSubImage glad_glGetTextureSubImage
+GLAD_API_CALL PFNGLGETTRANSFORMFEEDBACKVARYINGPROC glad_glGetTransformFeedbackVarying;
+#define glGetTransformFeedbackVarying glad_glGetTransformFeedbackVarying
+GLAD_API_CALL PFNGLGETTRANSFORMFEEDBACKI64_VPROC glad_glGetTransformFeedbacki64_v;
+#define glGetTransformFeedbacki64_v glad_glGetTransformFeedbacki64_v
+GLAD_API_CALL PFNGLGETTRANSFORMFEEDBACKI_VPROC glad_glGetTransformFeedbacki_v;
+#define glGetTransformFeedbacki_v glad_glGetTransformFeedbacki_v
+GLAD_API_CALL PFNGLGETTRANSFORMFEEDBACKIVPROC glad_glGetTransformFeedbackiv;
+#define glGetTransformFeedbackiv glad_glGetTransformFeedbackiv
+GLAD_API_CALL PFNGLGETUNIFORMBLOCKINDEXPROC glad_glGetUniformBlockIndex;
+#define glGetUniformBlockIndex glad_glGetUniformBlockIndex
+GLAD_API_CALL PFNGLGETUNIFORMINDICESPROC glad_glGetUniformIndices;
+#define glGetUniformIndices glad_glGetUniformIndices
+GLAD_API_CALL PFNGLGETUNIFORMLOCATIONPROC glad_glGetUniformLocation;
+#define glGetUniformLocation glad_glGetUniformLocation
+GLAD_API_CALL PFNGLGETUNIFORMLOCATIONARBPROC glad_glGetUniformLocationARB;
+#define glGetUniformLocationARB glad_glGetUniformLocationARB
+GLAD_API_CALL PFNGLGETUNIFORMSUBROUTINEUIVPROC glad_glGetUniformSubroutineuiv;
+#define glGetUniformSubroutineuiv glad_glGetUniformSubroutineuiv
+GLAD_API_CALL PFNGLGETUNIFORMDVPROC glad_glGetUniformdv;
+#define glGetUniformdv glad_glGetUniformdv
+GLAD_API_CALL PFNGLGETUNIFORMFVPROC glad_glGetUniformfv;
+#define glGetUniformfv glad_glGetUniformfv
+GLAD_API_CALL PFNGLGETUNIFORMFVARBPROC glad_glGetUniformfvARB;
+#define glGetUniformfvARB glad_glGetUniformfvARB
+GLAD_API_CALL PFNGLGETUNIFORMI64VARBPROC glad_glGetUniformi64vARB;
+#define glGetUniformi64vARB glad_glGetUniformi64vARB
+GLAD_API_CALL PFNGLGETUNIFORMIVPROC glad_glGetUniformiv;
+#define glGetUniformiv glad_glGetUniformiv
+GLAD_API_CALL PFNGLGETUNIFORMIVARBPROC glad_glGetUniformivARB;
+#define glGetUniformivARB glad_glGetUniformivARB
+GLAD_API_CALL PFNGLGETUNIFORMUI64VARBPROC glad_glGetUniformui64vARB;
+#define glGetUniformui64vARB glad_glGetUniformui64vARB
+GLAD_API_CALL PFNGLGETUNIFORMUIVPROC glad_glGetUniformuiv;
+#define glGetUniformuiv glad_glGetUniformuiv
+GLAD_API_CALL PFNGLGETVERTEXARRAYINDEXED64IVPROC glad_glGetVertexArrayIndexed64iv;
+#define glGetVertexArrayIndexed64iv glad_glGetVertexArrayIndexed64iv
+GLAD_API_CALL PFNGLGETVERTEXARRAYINDEXEDIVPROC glad_glGetVertexArrayIndexediv;
+#define glGetVertexArrayIndexediv glad_glGetVertexArrayIndexediv
+GLAD_API_CALL PFNGLGETVERTEXARRAYIVPROC glad_glGetVertexArrayiv;
+#define glGetVertexArrayiv glad_glGetVertexArrayiv
+GLAD_API_CALL PFNGLGETVERTEXATTRIBIIVPROC glad_glGetVertexAttribIiv;
+#define glGetVertexAttribIiv glad_glGetVertexAttribIiv
+GLAD_API_CALL PFNGLGETVERTEXATTRIBIUIVPROC glad_glGetVertexAttribIuiv;
+#define glGetVertexAttribIuiv glad_glGetVertexAttribIuiv
+GLAD_API_CALL PFNGLGETVERTEXATTRIBLDVPROC glad_glGetVertexAttribLdv;
+#define glGetVertexAttribLdv glad_glGetVertexAttribLdv
+GLAD_API_CALL PFNGLGETVERTEXATTRIBPOINTERVPROC glad_glGetVertexAttribPointerv;
+#define glGetVertexAttribPointerv glad_glGetVertexAttribPointerv
+GLAD_API_CALL PFNGLGETVERTEXATTRIBPOINTERVARBPROC glad_glGetVertexAttribPointervARB;
+#define glGetVertexAttribPointervARB glad_glGetVertexAttribPointervARB
+GLAD_API_CALL PFNGLGETVERTEXATTRIBDVPROC glad_glGetVertexAttribdv;
+#define glGetVertexAttribdv glad_glGetVertexAttribdv
+GLAD_API_CALL PFNGLGETVERTEXATTRIBDVARBPROC glad_glGetVertexAttribdvARB;
+#define glGetVertexAttribdvARB glad_glGetVertexAttribdvARB
+GLAD_API_CALL PFNGLGETVERTEXATTRIBFVPROC glad_glGetVertexAttribfv;
+#define glGetVertexAttribfv glad_glGetVertexAttribfv
+GLAD_API_CALL PFNGLGETVERTEXATTRIBFVARBPROC glad_glGetVertexAttribfvARB;
+#define glGetVertexAttribfvARB glad_glGetVertexAttribfvARB
+GLAD_API_CALL PFNGLGETVERTEXATTRIBIVPROC glad_glGetVertexAttribiv;
+#define glGetVertexAttribiv glad_glGetVertexAttribiv
+GLAD_API_CALL PFNGLGETVERTEXATTRIBIVARBPROC glad_glGetVertexAttribivARB;
+#define glGetVertexAttribivARB glad_glGetVertexAttribivARB
+GLAD_API_CALL PFNGLGETNUNIFORMI64VARBPROC glad_glGetnUniformi64vARB;
+#define glGetnUniformi64vARB glad_glGetnUniformi64vARB
+GLAD_API_CALL PFNGLGETNUNIFORMUI64VARBPROC glad_glGetnUniformui64vARB;
+#define glGetnUniformui64vARB glad_glGetnUniformui64vARB
+GLAD_API_CALL PFNGLHINTPROC glad_glHint;
+#define glHint glad_glHint
+GLAD_API_CALL PFNGLINDEXXOESPROC glad_glIndexxOES;
+#define glIndexxOES glad_glIndexxOES
+GLAD_API_CALL PFNGLINDEXXVOESPROC glad_glIndexxvOES;
+#define glIndexxvOES glad_glIndexxvOES
+GLAD_API_CALL PFNGLINVALIDATEBUFFERDATAPROC glad_glInvalidateBufferData;
+#define glInvalidateBufferData glad_glInvalidateBufferData
+GLAD_API_CALL PFNGLINVALIDATEBUFFERSUBDATAPROC glad_glInvalidateBufferSubData;
+#define glInvalidateBufferSubData glad_glInvalidateBufferSubData
+GLAD_API_CALL PFNGLINVALIDATEFRAMEBUFFERPROC glad_glInvalidateFramebuffer;
+#define glInvalidateFramebuffer glad_glInvalidateFramebuffer
+GLAD_API_CALL PFNGLINVALIDATENAMEDFRAMEBUFFERDATAPROC glad_glInvalidateNamedFramebufferData;
+#define glInvalidateNamedFramebufferData glad_glInvalidateNamedFramebufferData
+GLAD_API_CALL PFNGLINVALIDATENAMEDFRAMEBUFFERSUBDATAPROC glad_glInvalidateNamedFramebufferSubData;
+#define glInvalidateNamedFramebufferSubData glad_glInvalidateNamedFramebufferSubData
+GLAD_API_CALL PFNGLINVALIDATESUBFRAMEBUFFERPROC glad_glInvalidateSubFramebuffer;
+#define glInvalidateSubFramebuffer glad_glInvalidateSubFramebuffer
+GLAD_API_CALL PFNGLINVALIDATETEXIMAGEPROC glad_glInvalidateTexImage;
+#define glInvalidateTexImage glad_glInvalidateTexImage
+GLAD_API_CALL PFNGLINVALIDATETEXSUBIMAGEPROC glad_glInvalidateTexSubImage;
+#define glInvalidateTexSubImage glad_glInvalidateTexSubImage
+GLAD_API_CALL PFNGLISBUFFERPROC glad_glIsBuffer;
+#define glIsBuffer glad_glIsBuffer
+GLAD_API_CALL PFNGLISBUFFERARBPROC glad_glIsBufferARB;
+#define glIsBufferARB glad_glIsBufferARB
+GLAD_API_CALL PFNGLISENABLEDPROC glad_glIsEnabled;
+#define glIsEnabled glad_glIsEnabled
+GLAD_API_CALL PFNGLISENABLEDIPROC glad_glIsEnabledi;
+#define glIsEnabledi glad_glIsEnabledi
+GLAD_API_CALL PFNGLISFRAMEBUFFERPROC glad_glIsFramebuffer;
+#define glIsFramebuffer glad_glIsFramebuffer
+GLAD_API_CALL PFNGLISFRAMEBUFFEREXTPROC glad_glIsFramebufferEXT;
+#define glIsFramebufferEXT glad_glIsFramebufferEXT
+GLAD_API_CALL PFNGLISNAMEDSTRINGARBPROC glad_glIsNamedStringARB;
+#define glIsNamedStringARB glad_glIsNamedStringARB
+GLAD_API_CALL PFNGLISPROGRAMPROC glad_glIsProgram;
+#define glIsProgram glad_glIsProgram
+GLAD_API_CALL PFNGLISPROGRAMARBPROC glad_glIsProgramARB;
+#define glIsProgramARB glad_glIsProgramARB
+GLAD_API_CALL PFNGLISPROGRAMPIPELINEPROC glad_glIsProgramPipeline;
+#define glIsProgramPipeline glad_glIsProgramPipeline
+GLAD_API_CALL PFNGLISQUERYPROC glad_glIsQuery;
+#define glIsQuery glad_glIsQuery
+GLAD_API_CALL PFNGLISQUERYARBPROC glad_glIsQueryARB;
+#define glIsQueryARB glad_glIsQueryARB
+GLAD_API_CALL PFNGLISRENDERBUFFERPROC glad_glIsRenderbuffer;
+#define glIsRenderbuffer glad_glIsRenderbuffer
+GLAD_API_CALL PFNGLISRENDERBUFFEREXTPROC glad_glIsRenderbufferEXT;
+#define glIsRenderbufferEXT glad_glIsRenderbufferEXT
+GLAD_API_CALL PFNGLISSAMPLERPROC glad_glIsSampler;
+#define glIsSampler glad_glIsSampler
+GLAD_API_CALL PFNGLISSHADERPROC glad_glIsShader;
+#define glIsShader glad_glIsShader
+GLAD_API_CALL PFNGLISSYNCPROC glad_glIsSync;
+#define glIsSync glad_glIsSync
+GLAD_API_CALL PFNGLISTEXTUREPROC glad_glIsTexture;
+#define glIsTexture glad_glIsTexture
+GLAD_API_CALL PFNGLISTRANSFORMFEEDBACKPROC glad_glIsTransformFeedback;
+#define glIsTransformFeedback glad_glIsTransformFeedback
+GLAD_API_CALL PFNGLISVERTEXARRAYPROC glad_glIsVertexArray;
+#define glIsVertexArray glad_glIsVertexArray
+GLAD_API_CALL PFNGLLIGHTMODELXOESPROC glad_glLightModelxOES;
+#define glLightModelxOES glad_glLightModelxOES
+GLAD_API_CALL PFNGLLIGHTMODELXVOESPROC glad_glLightModelxvOES;
+#define glLightModelxvOES glad_glLightModelxvOES
+GLAD_API_CALL PFNGLLIGHTXOESPROC glad_glLightxOES;
+#define glLightxOES glad_glLightxOES
+GLAD_API_CALL PFNGLLIGHTXVOESPROC glad_glLightxvOES;
+#define glLightxvOES glad_glLightxvOES
+GLAD_API_CALL PFNGLLINEWIDTHPROC glad_glLineWidth;
+#define glLineWidth glad_glLineWidth
+GLAD_API_CALL PFNGLLINEWIDTHXOESPROC glad_glLineWidthxOES;
+#define glLineWidthxOES glad_glLineWidthxOES
+GLAD_API_CALL PFNGLLINKPROGRAMPROC glad_glLinkProgram;
+#define glLinkProgram glad_glLinkProgram
+GLAD_API_CALL PFNGLLINKPROGRAMARBPROC glad_glLinkProgramARB;
+#define glLinkProgramARB glad_glLinkProgramARB
+GLAD_API_CALL PFNGLLOADMATRIXXOESPROC glad_glLoadMatrixxOES;
+#define glLoadMatrixxOES glad_glLoadMatrixxOES
+GLAD_API_CALL PFNGLLOADTRANSPOSEMATRIXDARBPROC glad_glLoadTransposeMatrixdARB;
+#define glLoadTransposeMatrixdARB glad_glLoadTransposeMatrixdARB
+GLAD_API_CALL PFNGLLOADTRANSPOSEMATRIXFARBPROC glad_glLoadTransposeMatrixfARB;
+#define glLoadTransposeMatrixfARB glad_glLoadTransposeMatrixfARB
+GLAD_API_CALL PFNGLLOADTRANSPOSEMATRIXXOESPROC glad_glLoadTransposeMatrixxOES;
+#define glLoadTransposeMatrixxOES glad_glLoadTransposeMatrixxOES
+GLAD_API_CALL PFNGLLOGICOPPROC glad_glLogicOp;
+#define glLogicOp glad_glLogicOp
+GLAD_API_CALL PFNGLMAP1XOESPROC glad_glMap1xOES;
+#define glMap1xOES glad_glMap1xOES
+GLAD_API_CALL PFNGLMAP2XOESPROC glad_glMap2xOES;
+#define glMap2xOES glad_glMap2xOES
+GLAD_API_CALL PFNGLMAPBUFFERPROC glad_glMapBuffer;
+#define glMapBuffer glad_glMapBuffer
+GLAD_API_CALL PFNGLMAPBUFFERARBPROC glad_glMapBufferARB;
+#define glMapBufferARB glad_glMapBufferARB
+GLAD_API_CALL PFNGLMAPBUFFERRANGEPROC glad_glMapBufferRange;
+#define glMapBufferRange glad_glMapBufferRange
+GLAD_API_CALL PFNGLMAPGRID1XOESPROC glad_glMapGrid1xOES;
+#define glMapGrid1xOES glad_glMapGrid1xOES
+GLAD_API_CALL PFNGLMAPGRID2XOESPROC glad_glMapGrid2xOES;
+#define glMapGrid2xOES glad_glMapGrid2xOES
+GLAD_API_CALL PFNGLMAPNAMEDBUFFERPROC glad_glMapNamedBuffer;
+#define glMapNamedBuffer glad_glMapNamedBuffer
+GLAD_API_CALL PFNGLMAPNAMEDBUFFERRANGEPROC glad_glMapNamedBufferRange;
+#define glMapNamedBufferRange glad_glMapNamedBufferRange
+GLAD_API_CALL PFNGLMATERIALXOESPROC glad_glMaterialxOES;
+#define glMaterialxOES glad_glMaterialxOES
+GLAD_API_CALL PFNGLMATERIALXVOESPROC glad_glMaterialxvOES;
+#define glMaterialxvOES glad_glMaterialxvOES
+GLAD_API_CALL PFNGLMEMORYBARRIERPROC glad_glMemoryBarrier;
+#define glMemoryBarrier glad_glMemoryBarrier
+GLAD_API_CALL PFNGLMEMORYBARRIERBYREGIONPROC glad_glMemoryBarrierByRegion;
+#define glMemoryBarrierByRegion glad_glMemoryBarrierByRegion
+GLAD_API_CALL PFNGLMINSAMPLESHADINGPROC glad_glMinSampleShading;
+#define glMinSampleShading glad_glMinSampleShading
+GLAD_API_CALL PFNGLMINSAMPLESHADINGARBPROC glad_glMinSampleShadingARB;
+#define glMinSampleShadingARB glad_glMinSampleShadingARB
+GLAD_API_CALL PFNGLMULTMATRIXXOESPROC glad_glMultMatrixxOES;
+#define glMultMatrixxOES glad_glMultMatrixxOES
+GLAD_API_CALL PFNGLMULTTRANSPOSEMATRIXDARBPROC glad_glMultTransposeMatrixdARB;
+#define glMultTransposeMatrixdARB glad_glMultTransposeMatrixdARB
+GLAD_API_CALL PFNGLMULTTRANSPOSEMATRIXFARBPROC glad_glMultTransposeMatrixfARB;
+#define glMultTransposeMatrixfARB glad_glMultTransposeMatrixfARB
+GLAD_API_CALL PFNGLMULTTRANSPOSEMATRIXXOESPROC glad_glMultTransposeMatrixxOES;
+#define glMultTransposeMatrixxOES glad_glMultTransposeMatrixxOES
+GLAD_API_CALL PFNGLMULTIDRAWARRAYSPROC glad_glMultiDrawArrays;
+#define glMultiDrawArrays glad_glMultiDrawArrays
+GLAD_API_CALL PFNGLMULTIDRAWARRAYSINDIRECTPROC glad_glMultiDrawArraysIndirect;
+#define glMultiDrawArraysIndirect glad_glMultiDrawArraysIndirect
+GLAD_API_CALL PFNGLMULTIDRAWELEMENTSPROC glad_glMultiDrawElements;
+#define glMultiDrawElements glad_glMultiDrawElements
+GLAD_API_CALL PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC glad_glMultiDrawElementsBaseVertex;
+#define glMultiDrawElementsBaseVertex glad_glMultiDrawElementsBaseVertex
+GLAD_API_CALL PFNGLMULTIDRAWELEMENTSINDIRECTPROC glad_glMultiDrawElementsIndirect;
+#define glMultiDrawElementsIndirect glad_glMultiDrawElementsIndirect
+GLAD_API_CALL PFNGLMULTITEXCOORD1DARBPROC glad_glMultiTexCoord1dARB;
+#define glMultiTexCoord1dARB glad_glMultiTexCoord1dARB
+GLAD_API_CALL PFNGLMULTITEXCOORD1DVARBPROC glad_glMultiTexCoord1dvARB;
+#define glMultiTexCoord1dvARB glad_glMultiTexCoord1dvARB
+GLAD_API_CALL PFNGLMULTITEXCOORD1FARBPROC glad_glMultiTexCoord1fARB;
+#define glMultiTexCoord1fARB glad_glMultiTexCoord1fARB
+GLAD_API_CALL PFNGLMULTITEXCOORD1FVARBPROC glad_glMultiTexCoord1fvARB;
+#define glMultiTexCoord1fvARB glad_glMultiTexCoord1fvARB
+GLAD_API_CALL PFNGLMULTITEXCOORD1IARBPROC glad_glMultiTexCoord1iARB;
+#define glMultiTexCoord1iARB glad_glMultiTexCoord1iARB
+GLAD_API_CALL PFNGLMULTITEXCOORD1IVARBPROC glad_glMultiTexCoord1ivARB;
+#define glMultiTexCoord1ivARB glad_glMultiTexCoord1ivARB
+GLAD_API_CALL PFNGLMULTITEXCOORD1SARBPROC glad_glMultiTexCoord1sARB;
+#define glMultiTexCoord1sARB glad_glMultiTexCoord1sARB
+GLAD_API_CALL PFNGLMULTITEXCOORD1SVARBPROC glad_glMultiTexCoord1svARB;
+#define glMultiTexCoord1svARB glad_glMultiTexCoord1svARB
+GLAD_API_CALL PFNGLMULTITEXCOORD1XOESPROC glad_glMultiTexCoord1xOES;
+#define glMultiTexCoord1xOES glad_glMultiTexCoord1xOES
+GLAD_API_CALL PFNGLMULTITEXCOORD1XVOESPROC glad_glMultiTexCoord1xvOES;
+#define glMultiTexCoord1xvOES glad_glMultiTexCoord1xvOES
+GLAD_API_CALL PFNGLMULTITEXCOORD2DARBPROC glad_glMultiTexCoord2dARB;
+#define glMultiTexCoord2dARB glad_glMultiTexCoord2dARB
+GLAD_API_CALL PFNGLMULTITEXCOORD2DVARBPROC glad_glMultiTexCoord2dvARB;
+#define glMultiTexCoord2dvARB glad_glMultiTexCoord2dvARB
+GLAD_API_CALL PFNGLMULTITEXCOORD2FARBPROC glad_glMultiTexCoord2fARB;
+#define glMultiTexCoord2fARB glad_glMultiTexCoord2fARB
+GLAD_API_CALL PFNGLMULTITEXCOORD2FVARBPROC glad_glMultiTexCoord2fvARB;
+#define glMultiTexCoord2fvARB glad_glMultiTexCoord2fvARB
+GLAD_API_CALL PFNGLMULTITEXCOORD2IARBPROC glad_glMultiTexCoord2iARB;
+#define glMultiTexCoord2iARB glad_glMultiTexCoord2iARB
+GLAD_API_CALL PFNGLMULTITEXCOORD2IVARBPROC glad_glMultiTexCoord2ivARB;
+#define glMultiTexCoord2ivARB glad_glMultiTexCoord2ivARB
+GLAD_API_CALL PFNGLMULTITEXCOORD2SARBPROC glad_glMultiTexCoord2sARB;
+#define glMultiTexCoord2sARB glad_glMultiTexCoord2sARB
+GLAD_API_CALL PFNGLMULTITEXCOORD2SVARBPROC glad_glMultiTexCoord2svARB;
+#define glMultiTexCoord2svARB glad_glMultiTexCoord2svARB
+GLAD_API_CALL PFNGLMULTITEXCOORD2XOESPROC glad_glMultiTexCoord2xOES;
+#define glMultiTexCoord2xOES glad_glMultiTexCoord2xOES
+GLAD_API_CALL PFNGLMULTITEXCOORD2XVOESPROC glad_glMultiTexCoord2xvOES;
+#define glMultiTexCoord2xvOES glad_glMultiTexCoord2xvOES
+GLAD_API_CALL PFNGLMULTITEXCOORD3DARBPROC glad_glMultiTexCoord3dARB;
+#define glMultiTexCoord3dARB glad_glMultiTexCoord3dARB
+GLAD_API_CALL PFNGLMULTITEXCOORD3DVARBPROC glad_glMultiTexCoord3dvARB;
+#define glMultiTexCoord3dvARB glad_glMultiTexCoord3dvARB
+GLAD_API_CALL PFNGLMULTITEXCOORD3FARBPROC glad_glMultiTexCoord3fARB;
+#define glMultiTexCoord3fARB glad_glMultiTexCoord3fARB
+GLAD_API_CALL PFNGLMULTITEXCOORD3FVARBPROC glad_glMultiTexCoord3fvARB;
+#define glMultiTexCoord3fvARB glad_glMultiTexCoord3fvARB
+GLAD_API_CALL PFNGLMULTITEXCOORD3IARBPROC glad_glMultiTexCoord3iARB;
+#define glMultiTexCoord3iARB glad_glMultiTexCoord3iARB
+GLAD_API_CALL PFNGLMULTITEXCOORD3IVARBPROC glad_glMultiTexCoord3ivARB;
+#define glMultiTexCoord3ivARB glad_glMultiTexCoord3ivARB
+GLAD_API_CALL PFNGLMULTITEXCOORD3SARBPROC glad_glMultiTexCoord3sARB;
+#define glMultiTexCoord3sARB glad_glMultiTexCoord3sARB
+GLAD_API_CALL PFNGLMULTITEXCOORD3SVARBPROC glad_glMultiTexCoord3svARB;
+#define glMultiTexCoord3svARB glad_glMultiTexCoord3svARB
+GLAD_API_CALL PFNGLMULTITEXCOORD3XOESPROC glad_glMultiTexCoord3xOES;
+#define glMultiTexCoord3xOES glad_glMultiTexCoord3xOES
+GLAD_API_CALL PFNGLMULTITEXCOORD3XVOESPROC glad_glMultiTexCoord3xvOES;
+#define glMultiTexCoord3xvOES glad_glMultiTexCoord3xvOES
+GLAD_API_CALL PFNGLMULTITEXCOORD4DARBPROC glad_glMultiTexCoord4dARB;
+#define glMultiTexCoord4dARB glad_glMultiTexCoord4dARB
+GLAD_API_CALL PFNGLMULTITEXCOORD4DVARBPROC glad_glMultiTexCoord4dvARB;
+#define glMultiTexCoord4dvARB glad_glMultiTexCoord4dvARB
+GLAD_API_CALL PFNGLMULTITEXCOORD4FARBPROC glad_glMultiTexCoord4fARB;
+#define glMultiTexCoord4fARB glad_glMultiTexCoord4fARB
+GLAD_API_CALL PFNGLMULTITEXCOORD4FVARBPROC glad_glMultiTexCoord4fvARB;
+#define glMultiTexCoord4fvARB glad_glMultiTexCoord4fvARB
+GLAD_API_CALL PFNGLMULTITEXCOORD4IARBPROC glad_glMultiTexCoord4iARB;
+#define glMultiTexCoord4iARB glad_glMultiTexCoord4iARB
+GLAD_API_CALL PFNGLMULTITEXCOORD4IVARBPROC glad_glMultiTexCoord4ivARB;
+#define glMultiTexCoord4ivARB glad_glMultiTexCoord4ivARB
+GLAD_API_CALL PFNGLMULTITEXCOORD4SARBPROC glad_glMultiTexCoord4sARB;
+#define glMultiTexCoord4sARB glad_glMultiTexCoord4sARB
+GLAD_API_CALL PFNGLMULTITEXCOORD4SVARBPROC glad_glMultiTexCoord4svARB;
+#define glMultiTexCoord4svARB glad_glMultiTexCoord4svARB
+GLAD_API_CALL PFNGLMULTITEXCOORD4XOESPROC glad_glMultiTexCoord4xOES;
+#define glMultiTexCoord4xOES glad_glMultiTexCoord4xOES
+GLAD_API_CALL PFNGLMULTITEXCOORD4XVOESPROC glad_glMultiTexCoord4xvOES;
+#define glMultiTexCoord4xvOES glad_glMultiTexCoord4xvOES
+GLAD_API_CALL PFNGLNAMEDBUFFERDATAPROC glad_glNamedBufferData;
+#define glNamedBufferData glad_glNamedBufferData
+GLAD_API_CALL PFNGLNAMEDBUFFERSTORAGEPROC glad_glNamedBufferStorage;
+#define glNamedBufferStorage glad_glNamedBufferStorage
+GLAD_API_CALL PFNGLNAMEDBUFFERSUBDATAPROC glad_glNamedBufferSubData;
+#define glNamedBufferSubData glad_glNamedBufferSubData
+GLAD_API_CALL PFNGLNAMEDFRAMEBUFFERDRAWBUFFERPROC glad_glNamedFramebufferDrawBuffer;
+#define glNamedFramebufferDrawBuffer glad_glNamedFramebufferDrawBuffer
+GLAD_API_CALL PFNGLNAMEDFRAMEBUFFERDRAWBUFFERSPROC glad_glNamedFramebufferDrawBuffers;
+#define glNamedFramebufferDrawBuffers glad_glNamedFramebufferDrawBuffers
+GLAD_API_CALL PFNGLNAMEDFRAMEBUFFERPARAMETERIPROC glad_glNamedFramebufferParameteri;
+#define glNamedFramebufferParameteri glad_glNamedFramebufferParameteri
+GLAD_API_CALL PFNGLNAMEDFRAMEBUFFERREADBUFFERPROC glad_glNamedFramebufferReadBuffer;
+#define glNamedFramebufferReadBuffer glad_glNamedFramebufferReadBuffer
+GLAD_API_CALL PFNGLNAMEDFRAMEBUFFERRENDERBUFFERPROC glad_glNamedFramebufferRenderbuffer;
+#define glNamedFramebufferRenderbuffer glad_glNamedFramebufferRenderbuffer
+GLAD_API_CALL PFNGLNAMEDFRAMEBUFFERSAMPLELOCATIONSFVARBPROC glad_glNamedFramebufferSampleLocationsfvARB;
+#define glNamedFramebufferSampleLocationsfvARB glad_glNamedFramebufferSampleLocationsfvARB
+GLAD_API_CALL PFNGLNAMEDFRAMEBUFFERTEXTUREPROC glad_glNamedFramebufferTexture;
+#define glNamedFramebufferTexture glad_glNamedFramebufferTexture
+GLAD_API_CALL PFNGLNAMEDFRAMEBUFFERTEXTURELAYERPROC glad_glNamedFramebufferTextureLayer;
+#define glNamedFramebufferTextureLayer glad_glNamedFramebufferTextureLayer
+GLAD_API_CALL PFNGLNAMEDRENDERBUFFERSTORAGEPROC glad_glNamedRenderbufferStorage;
+#define glNamedRenderbufferStorage glad_glNamedRenderbufferStorage
+GLAD_API_CALL PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEPROC glad_glNamedRenderbufferStorageMultisample;
+#define glNamedRenderbufferStorageMultisample glad_glNamedRenderbufferStorageMultisample
+GLAD_API_CALL PFNGLNAMEDSTRINGARBPROC glad_glNamedStringARB;
+#define glNamedStringARB glad_glNamedStringARB
+GLAD_API_CALL PFNGLNORMAL3XOESPROC glad_glNormal3xOES;
+#define glNormal3xOES glad_glNormal3xOES
+GLAD_API_CALL PFNGLNORMAL3XVOESPROC glad_glNormal3xvOES;
+#define glNormal3xvOES glad_glNormal3xvOES
+GLAD_API_CALL PFNGLOBJECTLABELPROC glad_glObjectLabel;
+#define glObjectLabel glad_glObjectLabel
+GLAD_API_CALL PFNGLOBJECTPTRLABELPROC glad_glObjectPtrLabel;
+#define glObjectPtrLabel glad_glObjectPtrLabel
+GLAD_API_CALL PFNGLORTHOXOESPROC glad_glOrthoxOES;
+#define glOrthoxOES glad_glOrthoxOES
+GLAD_API_CALL PFNGLPASSTHROUGHXOESPROC glad_glPassThroughxOES;
+#define glPassThroughxOES glad_glPassThroughxOES
+GLAD_API_CALL PFNGLPATCHPARAMETERFVPROC glad_glPatchParameterfv;
+#define glPatchParameterfv glad_glPatchParameterfv
+GLAD_API_CALL PFNGLPATCHPARAMETERIPROC glad_glPatchParameteri;
+#define glPatchParameteri glad_glPatchParameteri
+GLAD_API_CALL PFNGLPAUSETRANSFORMFEEDBACKPROC glad_glPauseTransformFeedback;
+#define glPauseTransformFeedback glad_glPauseTransformFeedback
+GLAD_API_CALL PFNGLPIXELMAPXPROC glad_glPixelMapx;
+#define glPixelMapx glad_glPixelMapx
+GLAD_API_CALL PFNGLPIXELSTOREFPROC glad_glPixelStoref;
+#define glPixelStoref glad_glPixelStoref
+GLAD_API_CALL PFNGLPIXELSTOREIPROC glad_glPixelStorei;
+#define glPixelStorei glad_glPixelStorei
+GLAD_API_CALL PFNGLPIXELSTOREXPROC glad_glPixelStorex;
+#define glPixelStorex glad_glPixelStorex
+GLAD_API_CALL PFNGLPIXELTRANSFERXOESPROC glad_glPixelTransferxOES;
+#define glPixelTransferxOES glad_glPixelTransferxOES
+GLAD_API_CALL PFNGLPIXELZOOMXOESPROC glad_glPixelZoomxOES;
+#define glPixelZoomxOES glad_glPixelZoomxOES
+GLAD_API_CALL PFNGLPOINTPARAMETERFPROC glad_glPointParameterf;
+#define glPointParameterf glad_glPointParameterf
+GLAD_API_CALL PFNGLPOINTPARAMETERFVPROC glad_glPointParameterfv;
+#define glPointParameterfv glad_glPointParameterfv
+GLAD_API_CALL PFNGLPOINTPARAMETERIPROC glad_glPointParameteri;
+#define glPointParameteri glad_glPointParameteri
+GLAD_API_CALL PFNGLPOINTPARAMETERIVPROC glad_glPointParameteriv;
+#define glPointParameteriv glad_glPointParameteriv
+GLAD_API_CALL PFNGLPOINTPARAMETERXVOESPROC glad_glPointParameterxvOES;
+#define glPointParameterxvOES glad_glPointParameterxvOES
+GLAD_API_CALL PFNGLPOINTSIZEPROC glad_glPointSize;
+#define glPointSize glad_glPointSize
+GLAD_API_CALL PFNGLPOINTSIZEXOESPROC glad_glPointSizexOES;
+#define glPointSizexOES glad_glPointSizexOES
+GLAD_API_CALL PFNGLPOLYGONMODEPROC glad_glPolygonMode;
+#define glPolygonMode glad_glPolygonMode
+GLAD_API_CALL PFNGLPOLYGONOFFSETPROC glad_glPolygonOffset;
+#define glPolygonOffset glad_glPolygonOffset
+GLAD_API_CALL PFNGLPOLYGONOFFSETXOESPROC glad_glPolygonOffsetxOES;
+#define glPolygonOffsetxOES glad_glPolygonOffsetxOES
+GLAD_API_CALL PFNGLPOPDEBUGGROUPPROC glad_glPopDebugGroup;
+#define glPopDebugGroup glad_glPopDebugGroup
+GLAD_API_CALL PFNGLPRIMITIVEBOUNDINGBOXARBPROC glad_glPrimitiveBoundingBoxARB;
+#define glPrimitiveBoundingBoxARB glad_glPrimitiveBoundingBoxARB
+GLAD_API_CALL PFNGLPRIMITIVERESTARTINDEXPROC glad_glPrimitiveRestartIndex;
+#define glPrimitiveRestartIndex glad_glPrimitiveRestartIndex
+GLAD_API_CALL PFNGLPRIORITIZETEXTURESXOESPROC glad_glPrioritizeTexturesxOES;
+#define glPrioritizeTexturesxOES glad_glPrioritizeTexturesxOES
+GLAD_API_CALL PFNGLPROGRAMBINARYPROC glad_glProgramBinary;
+#define glProgramBinary glad_glProgramBinary
+GLAD_API_CALL PFNGLPROGRAMENVPARAMETER4DARBPROC glad_glProgramEnvParameter4dARB;
+#define glProgramEnvParameter4dARB glad_glProgramEnvParameter4dARB
+GLAD_API_CALL PFNGLPROGRAMENVPARAMETER4DVARBPROC glad_glProgramEnvParameter4dvARB;
+#define glProgramEnvParameter4dvARB glad_glProgramEnvParameter4dvARB
+GLAD_API_CALL PFNGLPROGRAMENVPARAMETER4FARBPROC glad_glProgramEnvParameter4fARB;
+#define glProgramEnvParameter4fARB glad_glProgramEnvParameter4fARB
+GLAD_API_CALL PFNGLPROGRAMENVPARAMETER4FVARBPROC glad_glProgramEnvParameter4fvARB;
+#define glProgramEnvParameter4fvARB glad_glProgramEnvParameter4fvARB
+GLAD_API_CALL PFNGLPROGRAMLOCALPARAMETER4DARBPROC glad_glProgramLocalParameter4dARB;
+#define glProgramLocalParameter4dARB glad_glProgramLocalParameter4dARB
+GLAD_API_CALL PFNGLPROGRAMLOCALPARAMETER4DVARBPROC glad_glProgramLocalParameter4dvARB;
+#define glProgramLocalParameter4dvARB glad_glProgramLocalParameter4dvARB
+GLAD_API_CALL PFNGLPROGRAMLOCALPARAMETER4FARBPROC glad_glProgramLocalParameter4fARB;
+#define glProgramLocalParameter4fARB glad_glProgramLocalParameter4fARB
+GLAD_API_CALL PFNGLPROGRAMLOCALPARAMETER4FVARBPROC glad_glProgramLocalParameter4fvARB;
+#define glProgramLocalParameter4fvARB glad_glProgramLocalParameter4fvARB
+GLAD_API_CALL PFNGLPROGRAMPARAMETERIPROC glad_glProgramParameteri;
+#define glProgramParameteri glad_glProgramParameteri
+GLAD_API_CALL PFNGLPROGRAMPARAMETERIARBPROC glad_glProgramParameteriARB;
+#define glProgramParameteriARB glad_glProgramParameteriARB
+GLAD_API_CALL PFNGLPROGRAMSTRINGARBPROC glad_glProgramStringARB;
+#define glProgramStringARB glad_glProgramStringARB
+GLAD_API_CALL PFNGLPROGRAMUNIFORM1DPROC glad_glProgramUniform1d;
+#define glProgramUniform1d glad_glProgramUniform1d
+GLAD_API_CALL PFNGLPROGRAMUNIFORM1DVPROC glad_glProgramUniform1dv;
+#define glProgramUniform1dv glad_glProgramUniform1dv
+GLAD_API_CALL PFNGLPROGRAMUNIFORM1FPROC glad_glProgramUniform1f;
+#define glProgramUniform1f glad_glProgramUniform1f
+GLAD_API_CALL PFNGLPROGRAMUNIFORM1FVPROC glad_glProgramUniform1fv;
+#define glProgramUniform1fv glad_glProgramUniform1fv
+GLAD_API_CALL PFNGLPROGRAMUNIFORM1IPROC glad_glProgramUniform1i;
+#define glProgramUniform1i glad_glProgramUniform1i
+GLAD_API_CALL PFNGLPROGRAMUNIFORM1I64ARBPROC glad_glProgramUniform1i64ARB;
+#define glProgramUniform1i64ARB glad_glProgramUniform1i64ARB
+GLAD_API_CALL PFNGLPROGRAMUNIFORM1I64VARBPROC glad_glProgramUniform1i64vARB;
+#define glProgramUniform1i64vARB glad_glProgramUniform1i64vARB
+GLAD_API_CALL PFNGLPROGRAMUNIFORM1IVPROC glad_glProgramUniform1iv;
+#define glProgramUniform1iv glad_glProgramUniform1iv
+GLAD_API_CALL PFNGLPROGRAMUNIFORM1UIPROC glad_glProgramUniform1ui;
+#define glProgramUniform1ui glad_glProgramUniform1ui
+GLAD_API_CALL PFNGLPROGRAMUNIFORM1UI64ARBPROC glad_glProgramUniform1ui64ARB;
+#define glProgramUniform1ui64ARB glad_glProgramUniform1ui64ARB
+GLAD_API_CALL PFNGLPROGRAMUNIFORM1UI64VARBPROC glad_glProgramUniform1ui64vARB;
+#define glProgramUniform1ui64vARB glad_glProgramUniform1ui64vARB
+GLAD_API_CALL PFNGLPROGRAMUNIFORM1UIVPROC glad_glProgramUniform1uiv;
+#define glProgramUniform1uiv glad_glProgramUniform1uiv
+GLAD_API_CALL PFNGLPROGRAMUNIFORM2DPROC glad_glProgramUniform2d;
+#define glProgramUniform2d glad_glProgramUniform2d
+GLAD_API_CALL PFNGLPROGRAMUNIFORM2DVPROC glad_glProgramUniform2dv;
+#define glProgramUniform2dv glad_glProgramUniform2dv
+GLAD_API_CALL PFNGLPROGRAMUNIFORM2FPROC glad_glProgramUniform2f;
+#define glProgramUniform2f glad_glProgramUniform2f
+GLAD_API_CALL PFNGLPROGRAMUNIFORM2FVPROC glad_glProgramUniform2fv;
+#define glProgramUniform2fv glad_glProgramUniform2fv
+GLAD_API_CALL PFNGLPROGRAMUNIFORM2IPROC glad_glProgramUniform2i;
+#define glProgramUniform2i glad_glProgramUniform2i
+GLAD_API_CALL PFNGLPROGRAMUNIFORM2I64ARBPROC glad_glProgramUniform2i64ARB;
+#define glProgramUniform2i64ARB glad_glProgramUniform2i64ARB
+GLAD_API_CALL PFNGLPROGRAMUNIFORM2I64VARBPROC glad_glProgramUniform2i64vARB;
+#define glProgramUniform2i64vARB glad_glProgramUniform2i64vARB
+GLAD_API_CALL PFNGLPROGRAMUNIFORM2IVPROC glad_glProgramUniform2iv;
+#define glProgramUniform2iv glad_glProgramUniform2iv
+GLAD_API_CALL PFNGLPROGRAMUNIFORM2UIPROC glad_glProgramUniform2ui;
+#define glProgramUniform2ui glad_glProgramUniform2ui
+GLAD_API_CALL PFNGLPROGRAMUNIFORM2UI64ARBPROC glad_glProgramUniform2ui64ARB;
+#define glProgramUniform2ui64ARB glad_glProgramUniform2ui64ARB
+GLAD_API_CALL PFNGLPROGRAMUNIFORM2UI64VARBPROC glad_glProgramUniform2ui64vARB;
+#define glProgramUniform2ui64vARB glad_glProgramUniform2ui64vARB
+GLAD_API_CALL PFNGLPROGRAMUNIFORM2UIVPROC glad_glProgramUniform2uiv;
+#define glProgramUniform2uiv glad_glProgramUniform2uiv
+GLAD_API_CALL PFNGLPROGRAMUNIFORM3DPROC glad_glProgramUniform3d;
+#define glProgramUniform3d glad_glProgramUniform3d
+GLAD_API_CALL PFNGLPROGRAMUNIFORM3DVPROC glad_glProgramUniform3dv;
+#define glProgramUniform3dv glad_glProgramUniform3dv
+GLAD_API_CALL PFNGLPROGRAMUNIFORM3FPROC glad_glProgramUniform3f;
+#define glProgramUniform3f glad_glProgramUniform3f
+GLAD_API_CALL PFNGLPROGRAMUNIFORM3FVPROC glad_glProgramUniform3fv;
+#define glProgramUniform3fv glad_glProgramUniform3fv
+GLAD_API_CALL PFNGLPROGRAMUNIFORM3IPROC glad_glProgramUniform3i;
+#define glProgramUniform3i glad_glProgramUniform3i
+GLAD_API_CALL PFNGLPROGRAMUNIFORM3I64ARBPROC glad_glProgramUniform3i64ARB;
+#define glProgramUniform3i64ARB glad_glProgramUniform3i64ARB
+GLAD_API_CALL PFNGLPROGRAMUNIFORM3I64VARBPROC glad_glProgramUniform3i64vARB;
+#define glProgramUniform3i64vARB glad_glProgramUniform3i64vARB
+GLAD_API_CALL PFNGLPROGRAMUNIFORM3IVPROC glad_glProgramUniform3iv;
+#define glProgramUniform3iv glad_glProgramUniform3iv
+GLAD_API_CALL PFNGLPROGRAMUNIFORM3UIPROC glad_glProgramUniform3ui;
+#define glProgramUniform3ui glad_glProgramUniform3ui
+GLAD_API_CALL PFNGLPROGRAMUNIFORM3UI64ARBPROC glad_glProgramUniform3ui64ARB;
+#define glProgramUniform3ui64ARB glad_glProgramUniform3ui64ARB
+GLAD_API_CALL PFNGLPROGRAMUNIFORM3UI64VARBPROC glad_glProgramUniform3ui64vARB;
+#define glProgramUniform3ui64vARB glad_glProgramUniform3ui64vARB
+GLAD_API_CALL PFNGLPROGRAMUNIFORM3UIVPROC glad_glProgramUniform3uiv;
+#define glProgramUniform3uiv glad_glProgramUniform3uiv
+GLAD_API_CALL PFNGLPROGRAMUNIFORM4DPROC glad_glProgramUniform4d;
+#define glProgramUniform4d glad_glProgramUniform4d
+GLAD_API_CALL PFNGLPROGRAMUNIFORM4DVPROC glad_glProgramUniform4dv;
+#define glProgramUniform4dv glad_glProgramUniform4dv
+GLAD_API_CALL PFNGLPROGRAMUNIFORM4FPROC glad_glProgramUniform4f;
+#define glProgramUniform4f glad_glProgramUniform4f
+GLAD_API_CALL PFNGLPROGRAMUNIFORM4FVPROC glad_glProgramUniform4fv;
+#define glProgramUniform4fv glad_glProgramUniform4fv
+GLAD_API_CALL PFNGLPROGRAMUNIFORM4IPROC glad_glProgramUniform4i;
+#define glProgramUniform4i glad_glProgramUniform4i
+GLAD_API_CALL PFNGLPROGRAMUNIFORM4I64ARBPROC glad_glProgramUniform4i64ARB;
+#define glProgramUniform4i64ARB glad_glProgramUniform4i64ARB
+GLAD_API_CALL PFNGLPROGRAMUNIFORM4I64VARBPROC glad_glProgramUniform4i64vARB;
+#define glProgramUniform4i64vARB glad_glProgramUniform4i64vARB
+GLAD_API_CALL PFNGLPROGRAMUNIFORM4IVPROC glad_glProgramUniform4iv;
+#define glProgramUniform4iv glad_glProgramUniform4iv
+GLAD_API_CALL PFNGLPROGRAMUNIFORM4UIPROC glad_glProgramUniform4ui;
+#define glProgramUniform4ui glad_glProgramUniform4ui
+GLAD_API_CALL PFNGLPROGRAMUNIFORM4UI64ARBPROC glad_glProgramUniform4ui64ARB;
+#define glProgramUniform4ui64ARB glad_glProgramUniform4ui64ARB
+GLAD_API_CALL PFNGLPROGRAMUNIFORM4UI64VARBPROC glad_glProgramUniform4ui64vARB;
+#define glProgramUniform4ui64vARB glad_glProgramUniform4ui64vARB
+GLAD_API_CALL PFNGLPROGRAMUNIFORM4UIVPROC glad_glProgramUniform4uiv;
+#define glProgramUniform4uiv glad_glProgramUniform4uiv
+GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX2DVPROC glad_glProgramUniformMatrix2dv;
+#define glProgramUniformMatrix2dv glad_glProgramUniformMatrix2dv
+GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX2FVPROC glad_glProgramUniformMatrix2fv;
+#define glProgramUniformMatrix2fv glad_glProgramUniformMatrix2fv
+GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX2X3DVPROC glad_glProgramUniformMatrix2x3dv;
+#define glProgramUniformMatrix2x3dv glad_glProgramUniformMatrix2x3dv
+GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC glad_glProgramUniformMatrix2x3fv;
+#define glProgramUniformMatrix2x3fv glad_glProgramUniformMatrix2x3fv
+GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX2X4DVPROC glad_glProgramUniformMatrix2x4dv;
+#define glProgramUniformMatrix2x4dv glad_glProgramUniformMatrix2x4dv
+GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC glad_glProgramUniformMatrix2x4fv;
+#define glProgramUniformMatrix2x4fv glad_glProgramUniformMatrix2x4fv
+GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX3DVPROC glad_glProgramUniformMatrix3dv;
+#define glProgramUniformMatrix3dv glad_glProgramUniformMatrix3dv
+GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX3FVPROC glad_glProgramUniformMatrix3fv;
+#define glProgramUniformMatrix3fv glad_glProgramUniformMatrix3fv
+GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX3X2DVPROC glad_glProgramUniformMatrix3x2dv;
+#define glProgramUniformMatrix3x2dv glad_glProgramUniformMatrix3x2dv
+GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC glad_glProgramUniformMatrix3x2fv;
+#define glProgramUniformMatrix3x2fv glad_glProgramUniformMatrix3x2fv
+GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX3X4DVPROC glad_glProgramUniformMatrix3x4dv;
+#define glProgramUniformMatrix3x4dv glad_glProgramUniformMatrix3x4dv
+GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC glad_glProgramUniformMatrix3x4fv;
+#define glProgramUniformMatrix3x4fv glad_glProgramUniformMatrix3x4fv
+GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX4DVPROC glad_glProgramUniformMatrix4dv;
+#define glProgramUniformMatrix4dv glad_glProgramUniformMatrix4dv
+GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX4FVPROC glad_glProgramUniformMatrix4fv;
+#define glProgramUniformMatrix4fv glad_glProgramUniformMatrix4fv
+GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX4X2DVPROC glad_glProgramUniformMatrix4x2dv;
+#define glProgramUniformMatrix4x2dv glad_glProgramUniformMatrix4x2dv
+GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC glad_glProgramUniformMatrix4x2fv;
+#define glProgramUniformMatrix4x2fv glad_glProgramUniformMatrix4x2fv
+GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX4X3DVPROC glad_glProgramUniformMatrix4x3dv;
+#define glProgramUniformMatrix4x3dv glad_glProgramUniformMatrix4x3dv
+GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC glad_glProgramUniformMatrix4x3fv;
+#define glProgramUniformMatrix4x3fv glad_glProgramUniformMatrix4x3fv
+GLAD_API_CALL PFNGLPROVOKINGVERTEXPROC glad_glProvokingVertex;
+#define glProvokingVertex glad_glProvokingVertex
+GLAD_API_CALL PFNGLPUSHDEBUGGROUPPROC glad_glPushDebugGroup;
+#define glPushDebugGroup glad_glPushDebugGroup
+GLAD_API_CALL PFNGLQUERYCOUNTERPROC glad_glQueryCounter;
+#define glQueryCounter glad_glQueryCounter
+GLAD_API_CALL PFNGLRASTERPOS2XOESPROC glad_glRasterPos2xOES;
+#define glRasterPos2xOES glad_glRasterPos2xOES
+GLAD_API_CALL PFNGLRASTERPOS2XVOESPROC glad_glRasterPos2xvOES;
+#define glRasterPos2xvOES glad_glRasterPos2xvOES
+GLAD_API_CALL PFNGLRASTERPOS3XOESPROC glad_glRasterPos3xOES;
+#define glRasterPos3xOES glad_glRasterPos3xOES
+GLAD_API_CALL PFNGLRASTERPOS3XVOESPROC glad_glRasterPos3xvOES;
+#define glRasterPos3xvOES glad_glRasterPos3xvOES
+GLAD_API_CALL PFNGLRASTERPOS4XOESPROC glad_glRasterPos4xOES;
+#define glRasterPos4xOES glad_glRasterPos4xOES
+GLAD_API_CALL PFNGLRASTERPOS4XVOESPROC glad_glRasterPos4xvOES;
+#define glRasterPos4xvOES glad_glRasterPos4xvOES
+GLAD_API_CALL PFNGLREADBUFFERPROC glad_glReadBuffer;
+#define glReadBuffer glad_glReadBuffer
+GLAD_API_CALL PFNGLREADPIXELSPROC glad_glReadPixels;
+#define glReadPixels glad_glReadPixels
+GLAD_API_CALL PFNGLRECTXOESPROC glad_glRectxOES;
+#define glRectxOES glad_glRectxOES
+GLAD_API_CALL PFNGLRECTXVOESPROC glad_glRectxvOES;
+#define glRectxvOES glad_glRectxvOES
+GLAD_API_CALL PFNGLRELEASESHADERCOMPILERPROC glad_glReleaseShaderCompiler;
+#define glReleaseShaderCompiler glad_glReleaseShaderCompiler
+GLAD_API_CALL PFNGLRENDERBUFFERSTORAGEPROC glad_glRenderbufferStorage;
+#define glRenderbufferStorage glad_glRenderbufferStorage
+GLAD_API_CALL PFNGLRENDERBUFFERSTORAGEEXTPROC glad_glRenderbufferStorageEXT;
+#define glRenderbufferStorageEXT glad_glRenderbufferStorageEXT
+GLAD_API_CALL PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glad_glRenderbufferStorageMultisample;
+#define glRenderbufferStorageMultisample glad_glRenderbufferStorageMultisample
+GLAD_API_CALL PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glad_glRenderbufferStorageMultisampleEXT;
+#define glRenderbufferStorageMultisampleEXT glad_glRenderbufferStorageMultisampleEXT
+GLAD_API_CALL PFNGLRESUMETRANSFORMFEEDBACKPROC glad_glResumeTransformFeedback;
+#define glResumeTransformFeedback glad_glResumeTransformFeedback
+GLAD_API_CALL PFNGLROTATEXOESPROC glad_glRotatexOES;
+#define glRotatexOES glad_glRotatexOES
+GLAD_API_CALL PFNGLSAMPLECOVERAGEPROC glad_glSampleCoverage;
+#define glSampleCoverage glad_glSampleCoverage
+GLAD_API_CALL PFNGLSAMPLECOVERAGEARBPROC glad_glSampleCoverageARB;
+#define glSampleCoverageARB glad_glSampleCoverageARB
+GLAD_API_CALL PFNGLSAMPLEMASKIPROC glad_glSampleMaski;
+#define glSampleMaski glad_glSampleMaski
+GLAD_API_CALL PFNGLSAMPLERPARAMETERIIVPROC glad_glSamplerParameterIiv;
+#define glSamplerParameterIiv glad_glSamplerParameterIiv
+GLAD_API_CALL PFNGLSAMPLERPARAMETERIUIVPROC glad_glSamplerParameterIuiv;
+#define glSamplerParameterIuiv glad_glSamplerParameterIuiv
+GLAD_API_CALL PFNGLSAMPLERPARAMETERFPROC glad_glSamplerParameterf;
+#define glSamplerParameterf glad_glSamplerParameterf
+GLAD_API_CALL PFNGLSAMPLERPARAMETERFVPROC glad_glSamplerParameterfv;
+#define glSamplerParameterfv glad_glSamplerParameterfv
+GLAD_API_CALL PFNGLSAMPLERPARAMETERIPROC glad_glSamplerParameteri;
+#define glSamplerParameteri glad_glSamplerParameteri
+GLAD_API_CALL PFNGLSAMPLERPARAMETERIVPROC glad_glSamplerParameteriv;
+#define glSamplerParameteriv glad_glSamplerParameteriv
+GLAD_API_CALL PFNGLSCALEXOESPROC glad_glScalexOES;
+#define glScalexOES glad_glScalexOES
+GLAD_API_CALL PFNGLSCISSORPROC glad_glScissor;
+#define glScissor glad_glScissor
+GLAD_API_CALL PFNGLSCISSORARRAYVPROC glad_glScissorArrayv;
+#define glScissorArrayv glad_glScissorArrayv
+GLAD_API_CALL PFNGLSCISSORINDEXEDPROC glad_glScissorIndexed;
+#define glScissorIndexed glad_glScissorIndexed
+GLAD_API_CALL PFNGLSCISSORINDEXEDVPROC glad_glScissorIndexedv;
+#define glScissorIndexedv glad_glScissorIndexedv
+GLAD_API_CALL PFNGLSHADERBINARYPROC glad_glShaderBinary;
+#define glShaderBinary glad_glShaderBinary
+GLAD_API_CALL PFNGLSHADERSOURCEPROC glad_glShaderSource;
+#define glShaderSource glad_glShaderSource
+GLAD_API_CALL PFNGLSHADERSOURCEARBPROC glad_glShaderSourceARB;
+#define glShaderSourceARB glad_glShaderSourceARB
+GLAD_API_CALL PFNGLSHADERSTORAGEBLOCKBINDINGPROC glad_glShaderStorageBlockBinding;
+#define glShaderStorageBlockBinding glad_glShaderStorageBlockBinding
+GLAD_API_CALL PFNGLSPECIALIZESHADERARBPROC glad_glSpecializeShaderARB;
+#define glSpecializeShaderARB glad_glSpecializeShaderARB
+GLAD_API_CALL PFNGLSTENCILFUNCPROC glad_glStencilFunc;
+#define glStencilFunc glad_glStencilFunc
+GLAD_API_CALL PFNGLSTENCILFUNCSEPARATEPROC glad_glStencilFuncSeparate;
+#define glStencilFuncSeparate glad_glStencilFuncSeparate
+GLAD_API_CALL PFNGLSTENCILMASKPROC glad_glStencilMask;
+#define glStencilMask glad_glStencilMask
+GLAD_API_CALL PFNGLSTENCILMASKSEPARATEPROC glad_glStencilMaskSeparate;
+#define glStencilMaskSeparate glad_glStencilMaskSeparate
+GLAD_API_CALL PFNGLSTENCILOPPROC glad_glStencilOp;
+#define glStencilOp glad_glStencilOp
+GLAD_API_CALL PFNGLSTENCILOPSEPARATEPROC glad_glStencilOpSeparate;
+#define glStencilOpSeparate glad_glStencilOpSeparate
+GLAD_API_CALL PFNGLTEXBUFFERPROC glad_glTexBuffer;
+#define glTexBuffer glad_glTexBuffer
+GLAD_API_CALL PFNGLTEXBUFFERRANGEPROC glad_glTexBufferRange;
+#define glTexBufferRange glad_glTexBufferRange
+GLAD_API_CALL PFNGLTEXCOORD1XOESPROC glad_glTexCoord1xOES;
+#define glTexCoord1xOES glad_glTexCoord1xOES
+GLAD_API_CALL PFNGLTEXCOORD1XVOESPROC glad_glTexCoord1xvOES;
+#define glTexCoord1xvOES glad_glTexCoord1xvOES
+GLAD_API_CALL PFNGLTEXCOORD2XOESPROC glad_glTexCoord2xOES;
+#define glTexCoord2xOES glad_glTexCoord2xOES
+GLAD_API_CALL PFNGLTEXCOORD2XVOESPROC glad_glTexCoord2xvOES;
+#define glTexCoord2xvOES glad_glTexCoord2xvOES
+GLAD_API_CALL PFNGLTEXCOORD3XOESPROC glad_glTexCoord3xOES;
+#define glTexCoord3xOES glad_glTexCoord3xOES
+GLAD_API_CALL PFNGLTEXCOORD3XVOESPROC glad_glTexCoord3xvOES;
+#define glTexCoord3xvOES glad_glTexCoord3xvOES
+GLAD_API_CALL PFNGLTEXCOORD4XOESPROC glad_glTexCoord4xOES;
+#define glTexCoord4xOES glad_glTexCoord4xOES
+GLAD_API_CALL PFNGLTEXCOORD4XVOESPROC glad_glTexCoord4xvOES;
+#define glTexCoord4xvOES glad_glTexCoord4xvOES
+GLAD_API_CALL PFNGLTEXENVXOESPROC glad_glTexEnvxOES;
+#define glTexEnvxOES glad_glTexEnvxOES
+GLAD_API_CALL PFNGLTEXENVXVOESPROC glad_glTexEnvxvOES;
+#define glTexEnvxvOES glad_glTexEnvxvOES
+GLAD_API_CALL PFNGLTEXGENXOESPROC glad_glTexGenxOES;
+#define glTexGenxOES glad_glTexGenxOES
+GLAD_API_CALL PFNGLTEXGENXVOESPROC glad_glTexGenxvOES;
+#define glTexGenxvOES glad_glTexGenxvOES
+GLAD_API_CALL PFNGLTEXIMAGE1DPROC glad_glTexImage1D;
+#define glTexImage1D glad_glTexImage1D
+GLAD_API_CALL PFNGLTEXIMAGE2DPROC glad_glTexImage2D;
+#define glTexImage2D glad_glTexImage2D
+GLAD_API_CALL PFNGLTEXIMAGE2DMULTISAMPLEPROC glad_glTexImage2DMultisample;
+#define glTexImage2DMultisample glad_glTexImage2DMultisample
+GLAD_API_CALL PFNGLTEXIMAGE3DPROC glad_glTexImage3D;
+#define glTexImage3D glad_glTexImage3D
+GLAD_API_CALL PFNGLTEXIMAGE3DMULTISAMPLEPROC glad_glTexImage3DMultisample;
+#define glTexImage3DMultisample glad_glTexImage3DMultisample
+GLAD_API_CALL PFNGLTEXPARAMETERIIVPROC glad_glTexParameterIiv;
+#define glTexParameterIiv glad_glTexParameterIiv
+GLAD_API_CALL PFNGLTEXPARAMETERIUIVPROC glad_glTexParameterIuiv;
+#define glTexParameterIuiv glad_glTexParameterIuiv
+GLAD_API_CALL PFNGLTEXPARAMETERFPROC glad_glTexParameterf;
+#define glTexParameterf glad_glTexParameterf
+GLAD_API_CALL PFNGLTEXPARAMETERFVPROC glad_glTexParameterfv;
+#define glTexParameterfv glad_glTexParameterfv
+GLAD_API_CALL PFNGLTEXPARAMETERIPROC glad_glTexParameteri;
+#define glTexParameteri glad_glTexParameteri
+GLAD_API_CALL PFNGLTEXPARAMETERIVPROC glad_glTexParameteriv;
+#define glTexParameteriv glad_glTexParameteriv
+GLAD_API_CALL PFNGLTEXPARAMETERXOESPROC glad_glTexParameterxOES;
+#define glTexParameterxOES glad_glTexParameterxOES
+GLAD_API_CALL PFNGLTEXPARAMETERXVOESPROC glad_glTexParameterxvOES;
+#define glTexParameterxvOES glad_glTexParameterxvOES
+GLAD_API_CALL PFNGLTEXSTORAGE1DPROC glad_glTexStorage1D;
+#define glTexStorage1D glad_glTexStorage1D
+GLAD_API_CALL PFNGLTEXSTORAGE2DPROC glad_glTexStorage2D;
+#define glTexStorage2D glad_glTexStorage2D
+GLAD_API_CALL PFNGLTEXSTORAGE2DMULTISAMPLEPROC glad_glTexStorage2DMultisample;
+#define glTexStorage2DMultisample glad_glTexStorage2DMultisample
+GLAD_API_CALL PFNGLTEXSTORAGE3DPROC glad_glTexStorage3D;
+#define glTexStorage3D glad_glTexStorage3D
+GLAD_API_CALL PFNGLTEXSTORAGE3DMULTISAMPLEPROC glad_glTexStorage3DMultisample;
+#define glTexStorage3DMultisample glad_glTexStorage3DMultisample
+GLAD_API_CALL PFNGLTEXSUBIMAGE1DPROC glad_glTexSubImage1D;
+#define glTexSubImage1D glad_glTexSubImage1D
+GLAD_API_CALL PFNGLTEXSUBIMAGE2DPROC glad_glTexSubImage2D;
+#define glTexSubImage2D glad_glTexSubImage2D
+GLAD_API_CALL PFNGLTEXSUBIMAGE3DPROC glad_glTexSubImage3D;
+#define glTexSubImage3D glad_glTexSubImage3D
+GLAD_API_CALL PFNGLTEXTUREBUFFERPROC glad_glTextureBuffer;
+#define glTextureBuffer glad_glTextureBuffer
+GLAD_API_CALL PFNGLTEXTUREBUFFERRANGEPROC glad_glTextureBufferRange;
+#define glTextureBufferRange glad_glTextureBufferRange
+GLAD_API_CALL PFNGLTEXTUREPARAMETERIIVPROC glad_glTextureParameterIiv;
+#define glTextureParameterIiv glad_glTextureParameterIiv
+GLAD_API_CALL PFNGLTEXTUREPARAMETERIUIVPROC glad_glTextureParameterIuiv;
+#define glTextureParameterIuiv glad_glTextureParameterIuiv
+GLAD_API_CALL PFNGLTEXTUREPARAMETERFPROC glad_glTextureParameterf;
+#define glTextureParameterf glad_glTextureParameterf
+GLAD_API_CALL PFNGLTEXTUREPARAMETERFVPROC glad_glTextureParameterfv;
+#define glTextureParameterfv glad_glTextureParameterfv
+GLAD_API_CALL PFNGLTEXTUREPARAMETERIPROC glad_glTextureParameteri;
+#define glTextureParameteri glad_glTextureParameteri
+GLAD_API_CALL PFNGLTEXTUREPARAMETERIVPROC glad_glTextureParameteriv;
+#define glTextureParameteriv glad_glTextureParameteriv
+GLAD_API_CALL PFNGLTEXTURESTORAGE1DPROC glad_glTextureStorage1D;
+#define glTextureStorage1D glad_glTextureStorage1D
+GLAD_API_CALL PFNGLTEXTURESTORAGE2DPROC glad_glTextureStorage2D;
+#define glTextureStorage2D glad_glTextureStorage2D
+GLAD_API_CALL PFNGLTEXTURESTORAGE2DMULTISAMPLEPROC glad_glTextureStorage2DMultisample;
+#define glTextureStorage2DMultisample glad_glTextureStorage2DMultisample
+GLAD_API_CALL PFNGLTEXTURESTORAGE3DPROC glad_glTextureStorage3D;
+#define glTextureStorage3D glad_glTextureStorage3D
+GLAD_API_CALL PFNGLTEXTURESTORAGE3DMULTISAMPLEPROC glad_glTextureStorage3DMultisample;
+#define glTextureStorage3DMultisample glad_glTextureStorage3DMultisample
+GLAD_API_CALL PFNGLTEXTURESUBIMAGE1DPROC glad_glTextureSubImage1D;
+#define glTextureSubImage1D glad_glTextureSubImage1D
+GLAD_API_CALL PFNGLTEXTURESUBIMAGE2DPROC glad_glTextureSubImage2D;
+#define glTextureSubImage2D glad_glTextureSubImage2D
+GLAD_API_CALL PFNGLTEXTURESUBIMAGE3DPROC glad_glTextureSubImage3D;
+#define glTextureSubImage3D glad_glTextureSubImage3D
+GLAD_API_CALL PFNGLTEXTUREVIEWPROC glad_glTextureView;
+#define glTextureView glad_glTextureView
+GLAD_API_CALL PFNGLTRANSFORMFEEDBACKBUFFERBASEPROC glad_glTransformFeedbackBufferBase;
+#define glTransformFeedbackBufferBase glad_glTransformFeedbackBufferBase
+GLAD_API_CALL PFNGLTRANSFORMFEEDBACKBUFFERRANGEPROC glad_glTransformFeedbackBufferRange;
+#define glTransformFeedbackBufferRange glad_glTransformFeedbackBufferRange
+GLAD_API_CALL PFNGLTRANSFORMFEEDBACKVARYINGSPROC glad_glTransformFeedbackVaryings;
+#define glTransformFeedbackVaryings glad_glTransformFeedbackVaryings
+GLAD_API_CALL PFNGLTRANSLATEXOESPROC glad_glTranslatexOES;
+#define glTranslatexOES glad_glTranslatexOES
+GLAD_API_CALL PFNGLUNIFORM1DPROC glad_glUniform1d;
+#define glUniform1d glad_glUniform1d
+GLAD_API_CALL PFNGLUNIFORM1DVPROC glad_glUniform1dv;
+#define glUniform1dv glad_glUniform1dv
+GLAD_API_CALL PFNGLUNIFORM1FPROC glad_glUniform1f;
+#define glUniform1f glad_glUniform1f
+GLAD_API_CALL PFNGLUNIFORM1FARBPROC glad_glUniform1fARB;
+#define glUniform1fARB glad_glUniform1fARB
+GLAD_API_CALL PFNGLUNIFORM1FVPROC glad_glUniform1fv;
+#define glUniform1fv glad_glUniform1fv
+GLAD_API_CALL PFNGLUNIFORM1FVARBPROC glad_glUniform1fvARB;
+#define glUniform1fvARB glad_glUniform1fvARB
+GLAD_API_CALL PFNGLUNIFORM1IPROC glad_glUniform1i;
+#define glUniform1i glad_glUniform1i
+GLAD_API_CALL PFNGLUNIFORM1I64ARBPROC glad_glUniform1i64ARB;
+#define glUniform1i64ARB glad_glUniform1i64ARB
+GLAD_API_CALL PFNGLUNIFORM1I64VARBPROC glad_glUniform1i64vARB;
+#define glUniform1i64vARB glad_glUniform1i64vARB
+GLAD_API_CALL PFNGLUNIFORM1IARBPROC glad_glUniform1iARB;
+#define glUniform1iARB glad_glUniform1iARB
+GLAD_API_CALL PFNGLUNIFORM1IVPROC glad_glUniform1iv;
+#define glUniform1iv glad_glUniform1iv
+GLAD_API_CALL PFNGLUNIFORM1IVARBPROC glad_glUniform1ivARB;
+#define glUniform1ivARB glad_glUniform1ivARB
+GLAD_API_CALL PFNGLUNIFORM1UIPROC glad_glUniform1ui;
+#define glUniform1ui glad_glUniform1ui
+GLAD_API_CALL PFNGLUNIFORM1UI64ARBPROC glad_glUniform1ui64ARB;
+#define glUniform1ui64ARB glad_glUniform1ui64ARB
+GLAD_API_CALL PFNGLUNIFORM1UI64VARBPROC glad_glUniform1ui64vARB;
+#define glUniform1ui64vARB glad_glUniform1ui64vARB
+GLAD_API_CALL PFNGLUNIFORM1UIVPROC glad_glUniform1uiv;
+#define glUniform1uiv glad_glUniform1uiv
+GLAD_API_CALL PFNGLUNIFORM2DPROC glad_glUniform2d;
+#define glUniform2d glad_glUniform2d
+GLAD_API_CALL PFNGLUNIFORM2DVPROC glad_glUniform2dv;
+#define glUniform2dv glad_glUniform2dv
+GLAD_API_CALL PFNGLUNIFORM2FPROC glad_glUniform2f;
+#define glUniform2f glad_glUniform2f
+GLAD_API_CALL PFNGLUNIFORM2FARBPROC glad_glUniform2fARB;
+#define glUniform2fARB glad_glUniform2fARB
+GLAD_API_CALL PFNGLUNIFORM2FVPROC glad_glUniform2fv;
+#define glUniform2fv glad_glUniform2fv
+GLAD_API_CALL PFNGLUNIFORM2FVARBPROC glad_glUniform2fvARB;
+#define glUniform2fvARB glad_glUniform2fvARB
+GLAD_API_CALL PFNGLUNIFORM2IPROC glad_glUniform2i;
+#define glUniform2i glad_glUniform2i
+GLAD_API_CALL PFNGLUNIFORM2I64ARBPROC glad_glUniform2i64ARB;
+#define glUniform2i64ARB glad_glUniform2i64ARB
+GLAD_API_CALL PFNGLUNIFORM2I64VARBPROC glad_glUniform2i64vARB;
+#define glUniform2i64vARB glad_glUniform2i64vARB
+GLAD_API_CALL PFNGLUNIFORM2IARBPROC glad_glUniform2iARB;
+#define glUniform2iARB glad_glUniform2iARB
+GLAD_API_CALL PFNGLUNIFORM2IVPROC glad_glUniform2iv;
+#define glUniform2iv glad_glUniform2iv
+GLAD_API_CALL PFNGLUNIFORM2IVARBPROC glad_glUniform2ivARB;
+#define glUniform2ivARB glad_glUniform2ivARB
+GLAD_API_CALL PFNGLUNIFORM2UIPROC glad_glUniform2ui;
+#define glUniform2ui glad_glUniform2ui
+GLAD_API_CALL PFNGLUNIFORM2UI64ARBPROC glad_glUniform2ui64ARB;
+#define glUniform2ui64ARB glad_glUniform2ui64ARB
+GLAD_API_CALL PFNGLUNIFORM2UI64VARBPROC glad_glUniform2ui64vARB;
+#define glUniform2ui64vARB glad_glUniform2ui64vARB
+GLAD_API_CALL PFNGLUNIFORM2UIVPROC glad_glUniform2uiv;
+#define glUniform2uiv glad_glUniform2uiv
+GLAD_API_CALL PFNGLUNIFORM3DPROC glad_glUniform3d;
+#define glUniform3d glad_glUniform3d
+GLAD_API_CALL PFNGLUNIFORM3DVPROC glad_glUniform3dv;
+#define glUniform3dv glad_glUniform3dv
+GLAD_API_CALL PFNGLUNIFORM3FPROC glad_glUniform3f;
+#define glUniform3f glad_glUniform3f
+GLAD_API_CALL PFNGLUNIFORM3FARBPROC glad_glUniform3fARB;
+#define glUniform3fARB glad_glUniform3fARB
+GLAD_API_CALL PFNGLUNIFORM3FVPROC glad_glUniform3fv;
+#define glUniform3fv glad_glUniform3fv
+GLAD_API_CALL PFNGLUNIFORM3FVARBPROC glad_glUniform3fvARB;
+#define glUniform3fvARB glad_glUniform3fvARB
+GLAD_API_CALL PFNGLUNIFORM3IPROC glad_glUniform3i;
+#define glUniform3i glad_glUniform3i
+GLAD_API_CALL PFNGLUNIFORM3I64ARBPROC glad_glUniform3i64ARB;
+#define glUniform3i64ARB glad_glUniform3i64ARB
+GLAD_API_CALL PFNGLUNIFORM3I64VARBPROC glad_glUniform3i64vARB;
+#define glUniform3i64vARB glad_glUniform3i64vARB
+GLAD_API_CALL PFNGLUNIFORM3IARBPROC glad_glUniform3iARB;
+#define glUniform3iARB glad_glUniform3iARB
+GLAD_API_CALL PFNGLUNIFORM3IVPROC glad_glUniform3iv;
+#define glUniform3iv glad_glUniform3iv
+GLAD_API_CALL PFNGLUNIFORM3IVARBPROC glad_glUniform3ivARB;
+#define glUniform3ivARB glad_glUniform3ivARB
+GLAD_API_CALL PFNGLUNIFORM3UIPROC glad_glUniform3ui;
+#define glUniform3ui glad_glUniform3ui
+GLAD_API_CALL PFNGLUNIFORM3UI64ARBPROC glad_glUniform3ui64ARB;
+#define glUniform3ui64ARB glad_glUniform3ui64ARB
+GLAD_API_CALL PFNGLUNIFORM3UI64VARBPROC glad_glUniform3ui64vARB;
+#define glUniform3ui64vARB glad_glUniform3ui64vARB
+GLAD_API_CALL PFNGLUNIFORM3UIVPROC glad_glUniform3uiv;
+#define glUniform3uiv glad_glUniform3uiv
+GLAD_API_CALL PFNGLUNIFORM4DPROC glad_glUniform4d;
+#define glUniform4d glad_glUniform4d
+GLAD_API_CALL PFNGLUNIFORM4DVPROC glad_glUniform4dv;
+#define glUniform4dv glad_glUniform4dv
+GLAD_API_CALL PFNGLUNIFORM4FPROC glad_glUniform4f;
+#define glUniform4f glad_glUniform4f
+GLAD_API_CALL PFNGLUNIFORM4FARBPROC glad_glUniform4fARB;
+#define glUniform4fARB glad_glUniform4fARB
+GLAD_API_CALL PFNGLUNIFORM4FVPROC glad_glUniform4fv;
+#define glUniform4fv glad_glUniform4fv
+GLAD_API_CALL PFNGLUNIFORM4FVARBPROC glad_glUniform4fvARB;
+#define glUniform4fvARB glad_glUniform4fvARB
+GLAD_API_CALL PFNGLUNIFORM4IPROC glad_glUniform4i;
+#define glUniform4i glad_glUniform4i
+GLAD_API_CALL PFNGLUNIFORM4I64ARBPROC glad_glUniform4i64ARB;
+#define glUniform4i64ARB glad_glUniform4i64ARB
+GLAD_API_CALL PFNGLUNIFORM4I64VARBPROC glad_glUniform4i64vARB;
+#define glUniform4i64vARB glad_glUniform4i64vARB
+GLAD_API_CALL PFNGLUNIFORM4IARBPROC glad_glUniform4iARB;
+#define glUniform4iARB glad_glUniform4iARB
+GLAD_API_CALL PFNGLUNIFORM4IVPROC glad_glUniform4iv;
+#define glUniform4iv glad_glUniform4iv
+GLAD_API_CALL PFNGLUNIFORM4IVARBPROC glad_glUniform4ivARB;
+#define glUniform4ivARB glad_glUniform4ivARB
+GLAD_API_CALL PFNGLUNIFORM4UIPROC glad_glUniform4ui;
+#define glUniform4ui glad_glUniform4ui
+GLAD_API_CALL PFNGLUNIFORM4UI64ARBPROC glad_glUniform4ui64ARB;
+#define glUniform4ui64ARB glad_glUniform4ui64ARB
+GLAD_API_CALL PFNGLUNIFORM4UI64VARBPROC glad_glUniform4ui64vARB;
+#define glUniform4ui64vARB glad_glUniform4ui64vARB
+GLAD_API_CALL PFNGLUNIFORM4UIVPROC glad_glUniform4uiv;
+#define glUniform4uiv glad_glUniform4uiv
+GLAD_API_CALL PFNGLUNIFORMBLOCKBINDINGPROC glad_glUniformBlockBinding;
+#define glUniformBlockBinding glad_glUniformBlockBinding
+GLAD_API_CALL PFNGLUNIFORMMATRIX2DVPROC glad_glUniformMatrix2dv;
+#define glUniformMatrix2dv glad_glUniformMatrix2dv
+GLAD_API_CALL PFNGLUNIFORMMATRIX2FVPROC glad_glUniformMatrix2fv;
+#define glUniformMatrix2fv glad_glUniformMatrix2fv
+GLAD_API_CALL PFNGLUNIFORMMATRIX2FVARBPROC glad_glUniformMatrix2fvARB;
+#define glUniformMatrix2fvARB glad_glUniformMatrix2fvARB
+GLAD_API_CALL PFNGLUNIFORMMATRIX2X3DVPROC glad_glUniformMatrix2x3dv;
+#define glUniformMatrix2x3dv glad_glUniformMatrix2x3dv
+GLAD_API_CALL PFNGLUNIFORMMATRIX2X3FVPROC glad_glUniformMatrix2x3fv;
+#define glUniformMatrix2x3fv glad_glUniformMatrix2x3fv
+GLAD_API_CALL PFNGLUNIFORMMATRIX2X4DVPROC glad_glUniformMatrix2x4dv;
+#define glUniformMatrix2x4dv glad_glUniformMatrix2x4dv
+GLAD_API_CALL PFNGLUNIFORMMATRIX2X4FVPROC glad_glUniformMatrix2x4fv;
+#define glUniformMatrix2x4fv glad_glUniformMatrix2x4fv
+GLAD_API_CALL PFNGLUNIFORMMATRIX3DVPROC glad_glUniformMatrix3dv;
+#define glUniformMatrix3dv glad_glUniformMatrix3dv
+GLAD_API_CALL PFNGLUNIFORMMATRIX3FVPROC glad_glUniformMatrix3fv;
+#define glUniformMatrix3fv glad_glUniformMatrix3fv
+GLAD_API_CALL PFNGLUNIFORMMATRIX3FVARBPROC glad_glUniformMatrix3fvARB;
+#define glUniformMatrix3fvARB glad_glUniformMatrix3fvARB
+GLAD_API_CALL PFNGLUNIFORMMATRIX3X2DVPROC glad_glUniformMatrix3x2dv;
+#define glUniformMatrix3x2dv glad_glUniformMatrix3x2dv
+GLAD_API_CALL PFNGLUNIFORMMATRIX3X2FVPROC glad_glUniformMatrix3x2fv;
+#define glUniformMatrix3x2fv glad_glUniformMatrix3x2fv
+GLAD_API_CALL PFNGLUNIFORMMATRIX3X4DVPROC glad_glUniformMatrix3x4dv;
+#define glUniformMatrix3x4dv glad_glUniformMatrix3x4dv
+GLAD_API_CALL PFNGLUNIFORMMATRIX3X4FVPROC glad_glUniformMatrix3x4fv;
+#define glUniformMatrix3x4fv glad_glUniformMatrix3x4fv
+GLAD_API_CALL PFNGLUNIFORMMATRIX4DVPROC glad_glUniformMatrix4dv;
+#define glUniformMatrix4dv glad_glUniformMatrix4dv
+GLAD_API_CALL PFNGLUNIFORMMATRIX4FVPROC glad_glUniformMatrix4fv;
+#define glUniformMatrix4fv glad_glUniformMatrix4fv
+GLAD_API_CALL PFNGLUNIFORMMATRIX4FVARBPROC glad_glUniformMatrix4fvARB;
+#define glUniformMatrix4fvARB glad_glUniformMatrix4fvARB
+GLAD_API_CALL PFNGLUNIFORMMATRIX4X2DVPROC glad_glUniformMatrix4x2dv;
+#define glUniformMatrix4x2dv glad_glUniformMatrix4x2dv
+GLAD_API_CALL PFNGLUNIFORMMATRIX4X2FVPROC glad_glUniformMatrix4x2fv;
+#define glUniformMatrix4x2fv glad_glUniformMatrix4x2fv
+GLAD_API_CALL PFNGLUNIFORMMATRIX4X3DVPROC glad_glUniformMatrix4x3dv;
+#define glUniformMatrix4x3dv glad_glUniformMatrix4x3dv
+GLAD_API_CALL PFNGLUNIFORMMATRIX4X3FVPROC glad_glUniformMatrix4x3fv;
+#define glUniformMatrix4x3fv glad_glUniformMatrix4x3fv
+GLAD_API_CALL PFNGLUNIFORMSUBROUTINESUIVPROC glad_glUniformSubroutinesuiv;
+#define glUniformSubroutinesuiv glad_glUniformSubroutinesuiv
+GLAD_API_CALL PFNGLUNMAPBUFFERPROC glad_glUnmapBuffer;
+#define glUnmapBuffer glad_glUnmapBuffer
+GLAD_API_CALL PFNGLUNMAPBUFFERARBPROC glad_glUnmapBufferARB;
+#define glUnmapBufferARB glad_glUnmapBufferARB
+GLAD_API_CALL PFNGLUNMAPNAMEDBUFFERPROC glad_glUnmapNamedBuffer;
+#define glUnmapNamedBuffer glad_glUnmapNamedBuffer
+GLAD_API_CALL PFNGLUSEPROGRAMPROC glad_glUseProgram;
+#define glUseProgram glad_glUseProgram
+GLAD_API_CALL PFNGLUSEPROGRAMOBJECTARBPROC glad_glUseProgramObjectARB;
+#define glUseProgramObjectARB glad_glUseProgramObjectARB
+GLAD_API_CALL PFNGLUSEPROGRAMSTAGESPROC glad_glUseProgramStages;
+#define glUseProgramStages glad_glUseProgramStages
+GLAD_API_CALL PFNGLVALIDATEPROGRAMPROC glad_glValidateProgram;
+#define glValidateProgram glad_glValidateProgram
+GLAD_API_CALL PFNGLVALIDATEPROGRAMARBPROC glad_glValidateProgramARB;
+#define glValidateProgramARB glad_glValidateProgramARB
+GLAD_API_CALL PFNGLVALIDATEPROGRAMPIPELINEPROC glad_glValidateProgramPipeline;
+#define glValidateProgramPipeline glad_glValidateProgramPipeline
+GLAD_API_CALL PFNGLVERTEX2XOESPROC glad_glVertex2xOES;
+#define glVertex2xOES glad_glVertex2xOES
+GLAD_API_CALL PFNGLVERTEX2XVOESPROC glad_glVertex2xvOES;
+#define glVertex2xvOES glad_glVertex2xvOES
+GLAD_API_CALL PFNGLVERTEX3XOESPROC glad_glVertex3xOES;
+#define glVertex3xOES glad_glVertex3xOES
+GLAD_API_CALL PFNGLVERTEX3XVOESPROC glad_glVertex3xvOES;
+#define glVertex3xvOES glad_glVertex3xvOES
+GLAD_API_CALL PFNGLVERTEX4XOESPROC glad_glVertex4xOES;
+#define glVertex4xOES glad_glVertex4xOES
+GLAD_API_CALL PFNGLVERTEX4XVOESPROC glad_glVertex4xvOES;
+#define glVertex4xvOES glad_glVertex4xvOES
+GLAD_API_CALL PFNGLVERTEXARRAYATTRIBBINDINGPROC glad_glVertexArrayAttribBinding;
+#define glVertexArrayAttribBinding glad_glVertexArrayAttribBinding
+GLAD_API_CALL PFNGLVERTEXARRAYATTRIBFORMATPROC glad_glVertexArrayAttribFormat;
+#define glVertexArrayAttribFormat glad_glVertexArrayAttribFormat
+GLAD_API_CALL PFNGLVERTEXARRAYATTRIBIFORMATPROC glad_glVertexArrayAttribIFormat;
+#define glVertexArrayAttribIFormat glad_glVertexArrayAttribIFormat
+GLAD_API_CALL PFNGLVERTEXARRAYATTRIBLFORMATPROC glad_glVertexArrayAttribLFormat;
+#define glVertexArrayAttribLFormat glad_glVertexArrayAttribLFormat
+GLAD_API_CALL PFNGLVERTEXARRAYBINDINGDIVISORPROC glad_glVertexArrayBindingDivisor;
+#define glVertexArrayBindingDivisor glad_glVertexArrayBindingDivisor
+GLAD_API_CALL PFNGLVERTEXARRAYELEMENTBUFFERPROC glad_glVertexArrayElementBuffer;
+#define glVertexArrayElementBuffer glad_glVertexArrayElementBuffer
+GLAD_API_CALL PFNGLVERTEXARRAYVERTEXBUFFERPROC glad_glVertexArrayVertexBuffer;
+#define glVertexArrayVertexBuffer glad_glVertexArrayVertexBuffer
+GLAD_API_CALL PFNGLVERTEXARRAYVERTEXBUFFERSPROC glad_glVertexArrayVertexBuffers;
+#define glVertexArrayVertexBuffers glad_glVertexArrayVertexBuffers
+GLAD_API_CALL PFNGLVERTEXATTRIB1DPROC glad_glVertexAttrib1d;
+#define glVertexAttrib1d glad_glVertexAttrib1d
+GLAD_API_CALL PFNGLVERTEXATTRIB1DARBPROC glad_glVertexAttrib1dARB;
+#define glVertexAttrib1dARB glad_glVertexAttrib1dARB
+GLAD_API_CALL PFNGLVERTEXATTRIB1DVPROC glad_glVertexAttrib1dv;
+#define glVertexAttrib1dv glad_glVertexAttrib1dv
+GLAD_API_CALL PFNGLVERTEXATTRIB1DVARBPROC glad_glVertexAttrib1dvARB;
+#define glVertexAttrib1dvARB glad_glVertexAttrib1dvARB
+GLAD_API_CALL PFNGLVERTEXATTRIB1FPROC glad_glVertexAttrib1f;
+#define glVertexAttrib1f glad_glVertexAttrib1f
+GLAD_API_CALL PFNGLVERTEXATTRIB1FARBPROC glad_glVertexAttrib1fARB;
+#define glVertexAttrib1fARB glad_glVertexAttrib1fARB
+GLAD_API_CALL PFNGLVERTEXATTRIB1FVPROC glad_glVertexAttrib1fv;
+#define glVertexAttrib1fv glad_glVertexAttrib1fv
+GLAD_API_CALL PFNGLVERTEXATTRIB1FVARBPROC glad_glVertexAttrib1fvARB;
+#define glVertexAttrib1fvARB glad_glVertexAttrib1fvARB
+GLAD_API_CALL PFNGLVERTEXATTRIB1SPROC glad_glVertexAttrib1s;
+#define glVertexAttrib1s glad_glVertexAttrib1s
+GLAD_API_CALL PFNGLVERTEXATTRIB1SARBPROC glad_glVertexAttrib1sARB;
+#define glVertexAttrib1sARB glad_glVertexAttrib1sARB
+GLAD_API_CALL PFNGLVERTEXATTRIB1SVPROC glad_glVertexAttrib1sv;
+#define glVertexAttrib1sv glad_glVertexAttrib1sv
+GLAD_API_CALL PFNGLVERTEXATTRIB1SVARBPROC glad_glVertexAttrib1svARB;
+#define glVertexAttrib1svARB glad_glVertexAttrib1svARB
+GLAD_API_CALL PFNGLVERTEXATTRIB2DPROC glad_glVertexAttrib2d;
+#define glVertexAttrib2d glad_glVertexAttrib2d
+GLAD_API_CALL PFNGLVERTEXATTRIB2DARBPROC glad_glVertexAttrib2dARB;
+#define glVertexAttrib2dARB glad_glVertexAttrib2dARB
+GLAD_API_CALL PFNGLVERTEXATTRIB2DVPROC glad_glVertexAttrib2dv;
+#define glVertexAttrib2dv glad_glVertexAttrib2dv
+GLAD_API_CALL PFNGLVERTEXATTRIB2DVARBPROC glad_glVertexAttrib2dvARB;
+#define glVertexAttrib2dvARB glad_glVertexAttrib2dvARB
+GLAD_API_CALL PFNGLVERTEXATTRIB2FPROC glad_glVertexAttrib2f;
+#define glVertexAttrib2f glad_glVertexAttrib2f
+GLAD_API_CALL PFNGLVERTEXATTRIB2FARBPROC glad_glVertexAttrib2fARB;
+#define glVertexAttrib2fARB glad_glVertexAttrib2fARB
+GLAD_API_CALL PFNGLVERTEXATTRIB2FVPROC glad_glVertexAttrib2fv;
+#define glVertexAttrib2fv glad_glVertexAttrib2fv
+GLAD_API_CALL PFNGLVERTEXATTRIB2FVARBPROC glad_glVertexAttrib2fvARB;
+#define glVertexAttrib2fvARB glad_glVertexAttrib2fvARB
+GLAD_API_CALL PFNGLVERTEXATTRIB2SPROC glad_glVertexAttrib2s;
+#define glVertexAttrib2s glad_glVertexAttrib2s
+GLAD_API_CALL PFNGLVERTEXATTRIB2SARBPROC glad_glVertexAttrib2sARB;
+#define glVertexAttrib2sARB glad_glVertexAttrib2sARB
+GLAD_API_CALL PFNGLVERTEXATTRIB2SVPROC glad_glVertexAttrib2sv;
+#define glVertexAttrib2sv glad_glVertexAttrib2sv
+GLAD_API_CALL PFNGLVERTEXATTRIB2SVARBPROC glad_glVertexAttrib2svARB;
+#define glVertexAttrib2svARB glad_glVertexAttrib2svARB
+GLAD_API_CALL PFNGLVERTEXATTRIB3DPROC glad_glVertexAttrib3d;
+#define glVertexAttrib3d glad_glVertexAttrib3d
+GLAD_API_CALL PFNGLVERTEXATTRIB3DARBPROC glad_glVertexAttrib3dARB;
+#define glVertexAttrib3dARB glad_glVertexAttrib3dARB
+GLAD_API_CALL PFNGLVERTEXATTRIB3DVPROC glad_glVertexAttrib3dv;
+#define glVertexAttrib3dv glad_glVertexAttrib3dv
+GLAD_API_CALL PFNGLVERTEXATTRIB3DVARBPROC glad_glVertexAttrib3dvARB;
+#define glVertexAttrib3dvARB glad_glVertexAttrib3dvARB
+GLAD_API_CALL PFNGLVERTEXATTRIB3FPROC glad_glVertexAttrib3f;
+#define glVertexAttrib3f glad_glVertexAttrib3f
+GLAD_API_CALL PFNGLVERTEXATTRIB3FARBPROC glad_glVertexAttrib3fARB;
+#define glVertexAttrib3fARB glad_glVertexAttrib3fARB
+GLAD_API_CALL PFNGLVERTEXATTRIB3FVPROC glad_glVertexAttrib3fv;
+#define glVertexAttrib3fv glad_glVertexAttrib3fv
+GLAD_API_CALL PFNGLVERTEXATTRIB3FVARBPROC glad_glVertexAttrib3fvARB;
+#define glVertexAttrib3fvARB glad_glVertexAttrib3fvARB
+GLAD_API_CALL PFNGLVERTEXATTRIB3SPROC glad_glVertexAttrib3s;
+#define glVertexAttrib3s glad_glVertexAttrib3s
+GLAD_API_CALL PFNGLVERTEXATTRIB3SARBPROC glad_glVertexAttrib3sARB;
+#define glVertexAttrib3sARB glad_glVertexAttrib3sARB
+GLAD_API_CALL PFNGLVERTEXATTRIB3SVPROC glad_glVertexAttrib3sv;
+#define glVertexAttrib3sv glad_glVertexAttrib3sv
+GLAD_API_CALL PFNGLVERTEXATTRIB3SVARBPROC glad_glVertexAttrib3svARB;
+#define glVertexAttrib3svARB glad_glVertexAttrib3svARB
+GLAD_API_CALL PFNGLVERTEXATTRIB4NBVPROC glad_glVertexAttrib4Nbv;
+#define glVertexAttrib4Nbv glad_glVertexAttrib4Nbv
+GLAD_API_CALL PFNGLVERTEXATTRIB4NBVARBPROC glad_glVertexAttrib4NbvARB;
+#define glVertexAttrib4NbvARB glad_glVertexAttrib4NbvARB
+GLAD_API_CALL PFNGLVERTEXATTRIB4NIVPROC glad_glVertexAttrib4Niv;
+#define glVertexAttrib4Niv glad_glVertexAttrib4Niv
+GLAD_API_CALL PFNGLVERTEXATTRIB4NIVARBPROC glad_glVertexAttrib4NivARB;
+#define glVertexAttrib4NivARB glad_glVertexAttrib4NivARB
+GLAD_API_CALL PFNGLVERTEXATTRIB4NSVPROC glad_glVertexAttrib4Nsv;
+#define glVertexAttrib4Nsv glad_glVertexAttrib4Nsv
+GLAD_API_CALL PFNGLVERTEXATTRIB4NSVARBPROC glad_glVertexAttrib4NsvARB;
+#define glVertexAttrib4NsvARB glad_glVertexAttrib4NsvARB
+GLAD_API_CALL PFNGLVERTEXATTRIB4NUBPROC glad_glVertexAttrib4Nub;
+#define glVertexAttrib4Nub glad_glVertexAttrib4Nub
+GLAD_API_CALL PFNGLVERTEXATTRIB4NUBARBPROC glad_glVertexAttrib4NubARB;
+#define glVertexAttrib4NubARB glad_glVertexAttrib4NubARB
+GLAD_API_CALL PFNGLVERTEXATTRIB4NUBVPROC glad_glVertexAttrib4Nubv;
+#define glVertexAttrib4Nubv glad_glVertexAttrib4Nubv
+GLAD_API_CALL PFNGLVERTEXATTRIB4NUBVARBPROC glad_glVertexAttrib4NubvARB;
+#define glVertexAttrib4NubvARB glad_glVertexAttrib4NubvARB
+GLAD_API_CALL PFNGLVERTEXATTRIB4NUIVPROC glad_glVertexAttrib4Nuiv;
+#define glVertexAttrib4Nuiv glad_glVertexAttrib4Nuiv
+GLAD_API_CALL PFNGLVERTEXATTRIB4NUIVARBPROC glad_glVertexAttrib4NuivARB;
+#define glVertexAttrib4NuivARB glad_glVertexAttrib4NuivARB
+GLAD_API_CALL PFNGLVERTEXATTRIB4NUSVPROC glad_glVertexAttrib4Nusv;
+#define glVertexAttrib4Nusv glad_glVertexAttrib4Nusv
+GLAD_API_CALL PFNGLVERTEXATTRIB4NUSVARBPROC glad_glVertexAttrib4NusvARB;
+#define glVertexAttrib4NusvARB glad_glVertexAttrib4NusvARB
+GLAD_API_CALL PFNGLVERTEXATTRIB4BVPROC glad_glVertexAttrib4bv;
+#define glVertexAttrib4bv glad_glVertexAttrib4bv
+GLAD_API_CALL PFNGLVERTEXATTRIB4BVARBPROC glad_glVertexAttrib4bvARB;
+#define glVertexAttrib4bvARB glad_glVertexAttrib4bvARB
+GLAD_API_CALL PFNGLVERTEXATTRIB4DPROC glad_glVertexAttrib4d;
+#define glVertexAttrib4d glad_glVertexAttrib4d
+GLAD_API_CALL PFNGLVERTEXATTRIB4DARBPROC glad_glVertexAttrib4dARB;
+#define glVertexAttrib4dARB glad_glVertexAttrib4dARB
+GLAD_API_CALL PFNGLVERTEXATTRIB4DVPROC glad_glVertexAttrib4dv;
+#define glVertexAttrib4dv glad_glVertexAttrib4dv
+GLAD_API_CALL PFNGLVERTEXATTRIB4DVARBPROC glad_glVertexAttrib4dvARB;
+#define glVertexAttrib4dvARB glad_glVertexAttrib4dvARB
+GLAD_API_CALL PFNGLVERTEXATTRIB4FPROC glad_glVertexAttrib4f;
+#define glVertexAttrib4f glad_glVertexAttrib4f
+GLAD_API_CALL PFNGLVERTEXATTRIB4FARBPROC glad_glVertexAttrib4fARB;
+#define glVertexAttrib4fARB glad_glVertexAttrib4fARB
+GLAD_API_CALL PFNGLVERTEXATTRIB4FVPROC glad_glVertexAttrib4fv;
+#define glVertexAttrib4fv glad_glVertexAttrib4fv
+GLAD_API_CALL PFNGLVERTEXATTRIB4FVARBPROC glad_glVertexAttrib4fvARB;
+#define glVertexAttrib4fvARB glad_glVertexAttrib4fvARB
+GLAD_API_CALL PFNGLVERTEXATTRIB4IVPROC glad_glVertexAttrib4iv;
+#define glVertexAttrib4iv glad_glVertexAttrib4iv
+GLAD_API_CALL PFNGLVERTEXATTRIB4IVARBPROC glad_glVertexAttrib4ivARB;
+#define glVertexAttrib4ivARB glad_glVertexAttrib4ivARB
+GLAD_API_CALL PFNGLVERTEXATTRIB4SPROC glad_glVertexAttrib4s;
+#define glVertexAttrib4s glad_glVertexAttrib4s
+GLAD_API_CALL PFNGLVERTEXATTRIB4SARBPROC glad_glVertexAttrib4sARB;
+#define glVertexAttrib4sARB glad_glVertexAttrib4sARB
+GLAD_API_CALL PFNGLVERTEXATTRIB4SVPROC glad_glVertexAttrib4sv;
+#define glVertexAttrib4sv glad_glVertexAttrib4sv
+GLAD_API_CALL PFNGLVERTEXATTRIB4SVARBPROC glad_glVertexAttrib4svARB;
+#define glVertexAttrib4svARB glad_glVertexAttrib4svARB
+GLAD_API_CALL PFNGLVERTEXATTRIB4UBVPROC glad_glVertexAttrib4ubv;
+#define glVertexAttrib4ubv glad_glVertexAttrib4ubv
+GLAD_API_CALL PFNGLVERTEXATTRIB4UBVARBPROC glad_glVertexAttrib4ubvARB;
+#define glVertexAttrib4ubvARB glad_glVertexAttrib4ubvARB
+GLAD_API_CALL PFNGLVERTEXATTRIB4UIVPROC glad_glVertexAttrib4uiv;
+#define glVertexAttrib4uiv glad_glVertexAttrib4uiv
+GLAD_API_CALL PFNGLVERTEXATTRIB4UIVARBPROC glad_glVertexAttrib4uivARB;
+#define glVertexAttrib4uivARB glad_glVertexAttrib4uivARB
+GLAD_API_CALL PFNGLVERTEXATTRIB4USVPROC glad_glVertexAttrib4usv;
+#define glVertexAttrib4usv glad_glVertexAttrib4usv
+GLAD_API_CALL PFNGLVERTEXATTRIB4USVARBPROC glad_glVertexAttrib4usvARB;
+#define glVertexAttrib4usvARB glad_glVertexAttrib4usvARB
+GLAD_API_CALL PFNGLVERTEXATTRIBBINDINGPROC glad_glVertexAttribBinding;
+#define glVertexAttribBinding glad_glVertexAttribBinding
+GLAD_API_CALL PFNGLVERTEXATTRIBDIVISORPROC glad_glVertexAttribDivisor;
+#define glVertexAttribDivisor glad_glVertexAttribDivisor
+GLAD_API_CALL PFNGLVERTEXATTRIBDIVISORARBPROC glad_glVertexAttribDivisorARB;
+#define glVertexAttribDivisorARB glad_glVertexAttribDivisorARB
+GLAD_API_CALL PFNGLVERTEXATTRIBFORMATPROC glad_glVertexAttribFormat;
+#define glVertexAttribFormat glad_glVertexAttribFormat
+GLAD_API_CALL PFNGLVERTEXATTRIBI1IPROC glad_glVertexAttribI1i;
+#define glVertexAttribI1i glad_glVertexAttribI1i
+GLAD_API_CALL PFNGLVERTEXATTRIBI1IVPROC glad_glVertexAttribI1iv;
+#define glVertexAttribI1iv glad_glVertexAttribI1iv
+GLAD_API_CALL PFNGLVERTEXATTRIBI1UIPROC glad_glVertexAttribI1ui;
+#define glVertexAttribI1ui glad_glVertexAttribI1ui
+GLAD_API_CALL PFNGLVERTEXATTRIBI1UIVPROC glad_glVertexAttribI1uiv;
+#define glVertexAttribI1uiv glad_glVertexAttribI1uiv
+GLAD_API_CALL PFNGLVERTEXATTRIBI2IPROC glad_glVertexAttribI2i;
+#define glVertexAttribI2i glad_glVertexAttribI2i
+GLAD_API_CALL PFNGLVERTEXATTRIBI2IVPROC glad_glVertexAttribI2iv;
+#define glVertexAttribI2iv glad_glVertexAttribI2iv
+GLAD_API_CALL PFNGLVERTEXATTRIBI2UIPROC glad_glVertexAttribI2ui;
+#define glVertexAttribI2ui glad_glVertexAttribI2ui
+GLAD_API_CALL PFNGLVERTEXATTRIBI2UIVPROC glad_glVertexAttribI2uiv;
+#define glVertexAttribI2uiv glad_glVertexAttribI2uiv
+GLAD_API_CALL PFNGLVERTEXATTRIBI3IPROC glad_glVertexAttribI3i;
+#define glVertexAttribI3i glad_glVertexAttribI3i
+GLAD_API_CALL PFNGLVERTEXATTRIBI3IVPROC glad_glVertexAttribI3iv;
+#define glVertexAttribI3iv glad_glVertexAttribI3iv
+GLAD_API_CALL PFNGLVERTEXATTRIBI3UIPROC glad_glVertexAttribI3ui;
+#define glVertexAttribI3ui glad_glVertexAttribI3ui
+GLAD_API_CALL PFNGLVERTEXATTRIBI3UIVPROC glad_glVertexAttribI3uiv;
+#define glVertexAttribI3uiv glad_glVertexAttribI3uiv
+GLAD_API_CALL PFNGLVERTEXATTRIBI4BVPROC glad_glVertexAttribI4bv;
+#define glVertexAttribI4bv glad_glVertexAttribI4bv
+GLAD_API_CALL PFNGLVERTEXATTRIBI4IPROC glad_glVertexAttribI4i;
+#define glVertexAttribI4i glad_glVertexAttribI4i
+GLAD_API_CALL PFNGLVERTEXATTRIBI4IVPROC glad_glVertexAttribI4iv;
+#define glVertexAttribI4iv glad_glVertexAttribI4iv
+GLAD_API_CALL PFNGLVERTEXATTRIBI4SVPROC glad_glVertexAttribI4sv;
+#define glVertexAttribI4sv glad_glVertexAttribI4sv
+GLAD_API_CALL PFNGLVERTEXATTRIBI4UBVPROC glad_glVertexAttribI4ubv;
+#define glVertexAttribI4ubv glad_glVertexAttribI4ubv
+GLAD_API_CALL PFNGLVERTEXATTRIBI4UIPROC glad_glVertexAttribI4ui;
+#define glVertexAttribI4ui glad_glVertexAttribI4ui
+GLAD_API_CALL PFNGLVERTEXATTRIBI4UIVPROC glad_glVertexAttribI4uiv;
+#define glVertexAttribI4uiv glad_glVertexAttribI4uiv
+GLAD_API_CALL PFNGLVERTEXATTRIBI4USVPROC glad_glVertexAttribI4usv;
+#define glVertexAttribI4usv glad_glVertexAttribI4usv
+GLAD_API_CALL PFNGLVERTEXATTRIBIFORMATPROC glad_glVertexAttribIFormat;
+#define glVertexAttribIFormat glad_glVertexAttribIFormat
+GLAD_API_CALL PFNGLVERTEXATTRIBIPOINTERPROC glad_glVertexAttribIPointer;
+#define glVertexAttribIPointer glad_glVertexAttribIPointer
+GLAD_API_CALL PFNGLVERTEXATTRIBL1DPROC glad_glVertexAttribL1d;
+#define glVertexAttribL1d glad_glVertexAttribL1d
+GLAD_API_CALL PFNGLVERTEXATTRIBL1DVPROC glad_glVertexAttribL1dv;
+#define glVertexAttribL1dv glad_glVertexAttribL1dv
+GLAD_API_CALL PFNGLVERTEXATTRIBL2DPROC glad_glVertexAttribL2d;
+#define glVertexAttribL2d glad_glVertexAttribL2d
+GLAD_API_CALL PFNGLVERTEXATTRIBL2DVPROC glad_glVertexAttribL2dv;
+#define glVertexAttribL2dv glad_glVertexAttribL2dv
+GLAD_API_CALL PFNGLVERTEXATTRIBL3DPROC glad_glVertexAttribL3d;
+#define glVertexAttribL3d glad_glVertexAttribL3d
+GLAD_API_CALL PFNGLVERTEXATTRIBL3DVPROC glad_glVertexAttribL3dv;
+#define glVertexAttribL3dv glad_glVertexAttribL3dv
+GLAD_API_CALL PFNGLVERTEXATTRIBL4DPROC glad_glVertexAttribL4d;
+#define glVertexAttribL4d glad_glVertexAttribL4d
+GLAD_API_CALL PFNGLVERTEXATTRIBL4DVPROC glad_glVertexAttribL4dv;
+#define glVertexAttribL4dv glad_glVertexAttribL4dv
+GLAD_API_CALL PFNGLVERTEXATTRIBLFORMATPROC glad_glVertexAttribLFormat;
+#define glVertexAttribLFormat glad_glVertexAttribLFormat
+GLAD_API_CALL PFNGLVERTEXATTRIBLPOINTERPROC glad_glVertexAttribLPointer;
+#define glVertexAttribLPointer glad_glVertexAttribLPointer
+GLAD_API_CALL PFNGLVERTEXATTRIBP1UIPROC glad_glVertexAttribP1ui;
+#define glVertexAttribP1ui glad_glVertexAttribP1ui
+GLAD_API_CALL PFNGLVERTEXATTRIBP1UIVPROC glad_glVertexAttribP1uiv;
+#define glVertexAttribP1uiv glad_glVertexAttribP1uiv
+GLAD_API_CALL PFNGLVERTEXATTRIBP2UIPROC glad_glVertexAttribP2ui;
+#define glVertexAttribP2ui glad_glVertexAttribP2ui
+GLAD_API_CALL PFNGLVERTEXATTRIBP2UIVPROC glad_glVertexAttribP2uiv;
+#define glVertexAttribP2uiv glad_glVertexAttribP2uiv
+GLAD_API_CALL PFNGLVERTEXATTRIBP3UIPROC glad_glVertexAttribP3ui;
+#define glVertexAttribP3ui glad_glVertexAttribP3ui
+GLAD_API_CALL PFNGLVERTEXATTRIBP3UIVPROC glad_glVertexAttribP3uiv;
+#define glVertexAttribP3uiv glad_glVertexAttribP3uiv
+GLAD_API_CALL PFNGLVERTEXATTRIBP4UIPROC glad_glVertexAttribP4ui;
+#define glVertexAttribP4ui glad_glVertexAttribP4ui
+GLAD_API_CALL PFNGLVERTEXATTRIBP4UIVPROC glad_glVertexAttribP4uiv;
+#define glVertexAttribP4uiv glad_glVertexAttribP4uiv
+GLAD_API_CALL PFNGLVERTEXATTRIBPOINTERPROC glad_glVertexAttribPointer;
+#define glVertexAttribPointer glad_glVertexAttribPointer
+GLAD_API_CALL PFNGLVERTEXATTRIBPOINTERARBPROC glad_glVertexAttribPointerARB;
+#define glVertexAttribPointerARB glad_glVertexAttribPointerARB
+GLAD_API_CALL PFNGLVERTEXBINDINGDIVISORPROC glad_glVertexBindingDivisor;
+#define glVertexBindingDivisor glad_glVertexBindingDivisor
+GLAD_API_CALL PFNGLVIEWPORTPROC glad_glViewport;
+#define glViewport glad_glViewport
+GLAD_API_CALL PFNGLVIEWPORTARRAYVPROC glad_glViewportArrayv;
+#define glViewportArrayv glad_glViewportArrayv
+GLAD_API_CALL PFNGLVIEWPORTINDEXEDFPROC glad_glViewportIndexedf;
+#define glViewportIndexedf glad_glViewportIndexedf
+GLAD_API_CALL PFNGLVIEWPORTINDEXEDFVPROC glad_glViewportIndexedfv;
+#define glViewportIndexedfv glad_glViewportIndexedfv
+GLAD_API_CALL PFNGLWAITSYNCPROC glad_glWaitSync;
+#define glWaitSync glad_glWaitSync
+
+
+
+
+
+GLAD_API_CALL int gladLoadGLUserPtr( GLADuserptrloadfunc load, void *userptr);
+GLAD_API_CALL int gladLoadGL( GLADloadfunc load);
+
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+/* Source */
+#ifdef GLAD_GL_IMPLEMENTATION
+#include
+#include
+#include
+
+#ifndef GLAD_IMPL_UTIL_C_
+#define GLAD_IMPL_UTIL_C_
+
+#ifdef _MSC_VER
+#define GLAD_IMPL_UTIL_SSCANF sscanf_s
+#else
+#define GLAD_IMPL_UTIL_SSCANF sscanf
+#endif
+
+#endif /* GLAD_IMPL_UTIL_C_ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+
+int GLAD_GL_VERSION_1_0 = 0;
+int GLAD_GL_VERSION_1_1 = 0;
+int GLAD_GL_VERSION_1_2 = 0;
+int GLAD_GL_VERSION_1_3 = 0;
+int GLAD_GL_VERSION_1_4 = 0;
+int GLAD_GL_VERSION_1_5 = 0;
+int GLAD_GL_VERSION_2_0 = 0;
+int GLAD_GL_VERSION_2_1 = 0;
+int GLAD_GL_VERSION_3_0 = 0;
+int GLAD_GL_VERSION_3_1 = 0;
+int GLAD_GL_VERSION_3_2 = 0;
+int GLAD_GL_VERSION_3_3 = 0;
+int GLAD_GL_VERSION_4_0 = 0;
+int GLAD_GL_VERSION_4_1 = 0;
+int GLAD_GL_VERSION_4_2 = 0;
+int GLAD_GL_VERSION_4_3 = 0;
+int GLAD_GL_ARB_ES2_compatibility = 0;
+int GLAD_GL_ARB_ES3_1_compatibility = 0;
+int GLAD_GL_ARB_ES3_2_compatibility = 0;
+int GLAD_GL_ARB_ES3_compatibility = 0;
+int GLAD_GL_ARB_blend_func_extended = 0;
+int GLAD_GL_ARB_buffer_storage = 0;
+int GLAD_GL_ARB_clear_buffer_object = 0;
+int GLAD_GL_ARB_clear_texture = 0;
+int GLAD_GL_ARB_color_buffer_float = 0;
+int GLAD_GL_ARB_compatibility = 0;
+int GLAD_GL_ARB_compressed_texture_pixel_storage = 0;
+int GLAD_GL_ARB_compute_shader = 0;
+int GLAD_GL_ARB_compute_variable_group_size = 0;
+int GLAD_GL_ARB_copy_buffer = 0;
+int GLAD_GL_ARB_copy_image = 0;
+int GLAD_GL_ARB_debug_output = 0;
+int GLAD_GL_ARB_depth_buffer_float = 0;
+int GLAD_GL_ARB_depth_clamp = 0;
+int GLAD_GL_ARB_depth_texture = 0;
+int GLAD_GL_ARB_direct_state_access = 0;
+int GLAD_GL_ARB_draw_buffers = 0;
+int GLAD_GL_ARB_draw_buffers_blend = 0;
+int GLAD_GL_ARB_draw_elements_base_vertex = 0;
+int GLAD_GL_ARB_draw_indirect = 0;
+int GLAD_GL_ARB_draw_instanced = 0;
+int GLAD_GL_ARB_enhanced_layouts = 0;
+int GLAD_GL_ARB_explicit_attrib_location = 0;
+int GLAD_GL_ARB_explicit_uniform_location = 0;
+int GLAD_GL_ARB_fragment_coord_conventions = 0;
+int GLAD_GL_ARB_fragment_layer_viewport = 0;
+int GLAD_GL_ARB_fragment_program = 0;
+int GLAD_GL_ARB_fragment_program_shadow = 0;
+int GLAD_GL_ARB_fragment_shader = 0;
+int GLAD_GL_ARB_fragment_shader_interlock = 0;
+int GLAD_GL_ARB_framebuffer_no_attachments = 0;
+int GLAD_GL_ARB_framebuffer_object = 0;
+int GLAD_GL_ARB_framebuffer_sRGB = 0;
+int GLAD_GL_ARB_geometry_shader4 = 0;
+int GLAD_GL_ARB_get_program_binary = 0;
+int GLAD_GL_ARB_get_texture_sub_image = 0;
+int GLAD_GL_ARB_gl_spirv = 0;
+int GLAD_GL_ARB_gpu_shader5 = 0;
+int GLAD_GL_ARB_gpu_shader_fp64 = 0;
+int GLAD_GL_ARB_gpu_shader_int64 = 0;
+int GLAD_GL_ARB_half_float_pixel = 0;
+int GLAD_GL_ARB_half_float_vertex = 0;
+int GLAD_GL_ARB_instanced_arrays = 0;
+int GLAD_GL_ARB_internalformat_query = 0;
+int GLAD_GL_ARB_internalformat_query2 = 0;
+int GLAD_GL_ARB_map_buffer_range = 0;
+int GLAD_GL_ARB_multi_bind = 0;
+int GLAD_GL_ARB_multi_draw_indirect = 0;
+int GLAD_GL_ARB_multisample = 0;
+int GLAD_GL_ARB_multitexture = 0;
+int GLAD_GL_ARB_occlusion_query = 0;
+int GLAD_GL_ARB_occlusion_query2 = 0;
+int GLAD_GL_ARB_pipeline_statistics_query = 0;
+int GLAD_GL_ARB_query_buffer_object = 0;
+int GLAD_GL_ARB_sample_locations = 0;
+int GLAD_GL_ARB_sample_shading = 0;
+int GLAD_GL_ARB_seamless_cube_map = 0;
+int GLAD_GL_ARB_seamless_cubemap_per_texture = 0;
+int GLAD_GL_ARB_shader_atomic_counter_ops = 0;
+int GLAD_GL_ARB_shader_atomic_counters = 0;
+int GLAD_GL_ARB_shader_bit_encoding = 0;
+int GLAD_GL_ARB_shader_clock = 0;
+int GLAD_GL_ARB_shader_image_load_store = 0;
+int GLAD_GL_ARB_shader_image_size = 0;
+int GLAD_GL_ARB_shader_objects = 0;
+int GLAD_GL_ARB_shader_storage_buffer_object = 0;
+int GLAD_GL_ARB_shader_texture_lod = 0;
+int GLAD_GL_ARB_shading_language_100 = 0;
+int GLAD_GL_ARB_shading_language_420pack = 0;
+int GLAD_GL_ARB_shading_language_include = 0;
+int GLAD_GL_ARB_shading_language_packing = 0;
+int GLAD_GL_ARB_spirv_extensions = 0;
+int GLAD_GL_ARB_tessellation_shader = 0;
+int GLAD_GL_ARB_texture_border_clamp = 0;
+int GLAD_GL_ARB_texture_buffer_object_rgb32 = 0;
+int GLAD_GL_ARB_texture_compression = 0;
+int GLAD_GL_ARB_texture_cube_map = 0;
+int GLAD_GL_ARB_texture_cube_map_array = 0;
+int GLAD_GL_ARB_texture_env_add = 0;
+int GLAD_GL_ARB_texture_filter_anisotropic = 0;
+int GLAD_GL_ARB_texture_filter_minmax = 0;
+int GLAD_GL_ARB_texture_float = 0;
+int GLAD_GL_ARB_texture_mirror_clamp_to_edge = 0;
+int GLAD_GL_ARB_texture_mirrored_repeat = 0;
+int GLAD_GL_ARB_texture_multisample = 0;
+int GLAD_GL_ARB_texture_non_power_of_two = 0;
+int GLAD_GL_ARB_texture_rg = 0;
+int GLAD_GL_ARB_texture_storage = 0;
+int GLAD_GL_ARB_texture_swizzle = 0;
+int GLAD_GL_ARB_texture_view = 0;
+int GLAD_GL_ARB_timer_query = 0;
+int GLAD_GL_ARB_transpose_matrix = 0;
+int GLAD_GL_ARB_uniform_buffer_object = 0;
+int GLAD_GL_ARB_vertex_array_bgra = 0;
+int GLAD_GL_ARB_vertex_array_object = 0;
+int GLAD_GL_ARB_vertex_attrib_binding = 0;
+int GLAD_GL_ARB_vertex_buffer_object = 0;
+int GLAD_GL_ARB_vertex_program = 0;
+int GLAD_GL_ARB_vertex_shader = 0;
+int GLAD_GL_EXT_draw_instanced = 0;
+int GLAD_GL_EXT_fog_coord = 0;
+int GLAD_GL_EXT_framebuffer_blit = 0;
+int GLAD_GL_EXT_framebuffer_multisample = 0;
+int GLAD_GL_EXT_framebuffer_object = 0;
+int GLAD_GL_EXT_framebuffer_sRGB = 0;
+int GLAD_GL_EXT_texture_compression_s3tc = 0;
+int GLAD_GL_EXT_texture_filter_anisotropic = 0;
+int GLAD_GL_EXT_texture_mirror_clamp = 0;
+int GLAD_GL_KHR_texture_compression_astc_hdr = 0;
+int GLAD_GL_KHR_texture_compression_astc_ldr = 0;
+int GLAD_GL_OES_compressed_paletted_texture = 0;
+int GLAD_GL_OES_fixed_point = 0;
+
+
+
+PFNGLACCUMXOESPROC glad_glAccumxOES = NULL;
+PFNGLACTIVESHADERPROGRAMPROC glad_glActiveShaderProgram = NULL;
+PFNGLACTIVETEXTUREPROC glad_glActiveTexture = NULL;
+PFNGLACTIVETEXTUREARBPROC glad_glActiveTextureARB = NULL;
+PFNGLALPHAFUNCXOESPROC glad_glAlphaFuncxOES = NULL;
+PFNGLATTACHOBJECTARBPROC glad_glAttachObjectARB = NULL;
+PFNGLATTACHSHADERPROC glad_glAttachShader = NULL;
+PFNGLBEGINCONDITIONALRENDERPROC glad_glBeginConditionalRender = NULL;
+PFNGLBEGINQUERYPROC glad_glBeginQuery = NULL;
+PFNGLBEGINQUERYARBPROC glad_glBeginQueryARB = NULL;
+PFNGLBEGINQUERYINDEXEDPROC glad_glBeginQueryIndexed = NULL;
+PFNGLBEGINTRANSFORMFEEDBACKPROC glad_glBeginTransformFeedback = NULL;
+PFNGLBINDATTRIBLOCATIONPROC glad_glBindAttribLocation = NULL;
+PFNGLBINDATTRIBLOCATIONARBPROC glad_glBindAttribLocationARB = NULL;
+PFNGLBINDBUFFERPROC glad_glBindBuffer = NULL;
+PFNGLBINDBUFFERARBPROC glad_glBindBufferARB = NULL;
+PFNGLBINDBUFFERBASEPROC glad_glBindBufferBase = NULL;
+PFNGLBINDBUFFERRANGEPROC glad_glBindBufferRange = NULL;
+PFNGLBINDBUFFERSBASEPROC glad_glBindBuffersBase = NULL;
+PFNGLBINDBUFFERSRANGEPROC glad_glBindBuffersRange = NULL;
+PFNGLBINDFRAGDATALOCATIONPROC glad_glBindFragDataLocation = NULL;
+PFNGLBINDFRAGDATALOCATIONINDEXEDPROC glad_glBindFragDataLocationIndexed = NULL;
+PFNGLBINDFRAMEBUFFERPROC glad_glBindFramebuffer = NULL;
+PFNGLBINDFRAMEBUFFEREXTPROC glad_glBindFramebufferEXT = NULL;
+PFNGLBINDIMAGETEXTUREPROC glad_glBindImageTexture = NULL;
+PFNGLBINDIMAGETEXTURESPROC glad_glBindImageTextures = NULL;
+PFNGLBINDPROGRAMARBPROC glad_glBindProgramARB = NULL;
+PFNGLBINDPROGRAMPIPELINEPROC glad_glBindProgramPipeline = NULL;
+PFNGLBINDRENDERBUFFERPROC glad_glBindRenderbuffer = NULL;
+PFNGLBINDRENDERBUFFEREXTPROC glad_glBindRenderbufferEXT = NULL;
+PFNGLBINDSAMPLERPROC glad_glBindSampler = NULL;
+PFNGLBINDSAMPLERSPROC glad_glBindSamplers = NULL;
+PFNGLBINDTEXTUREPROC glad_glBindTexture = NULL;
+PFNGLBINDTEXTUREUNITPROC glad_glBindTextureUnit = NULL;
+PFNGLBINDTEXTURESPROC glad_glBindTextures = NULL;
+PFNGLBINDTRANSFORMFEEDBACKPROC glad_glBindTransformFeedback = NULL;
+PFNGLBINDVERTEXARRAYPROC glad_glBindVertexArray = NULL;
+PFNGLBINDVERTEXBUFFERPROC glad_glBindVertexBuffer = NULL;
+PFNGLBINDVERTEXBUFFERSPROC glad_glBindVertexBuffers = NULL;
+PFNGLBITMAPXOESPROC glad_glBitmapxOES = NULL;
+PFNGLBLENDCOLORPROC glad_glBlendColor = NULL;
+PFNGLBLENDCOLORXOESPROC glad_glBlendColorxOES = NULL;
+PFNGLBLENDEQUATIONPROC glad_glBlendEquation = NULL;
+PFNGLBLENDEQUATIONSEPARATEPROC glad_glBlendEquationSeparate = NULL;
+PFNGLBLENDEQUATIONSEPARATEIPROC glad_glBlendEquationSeparatei = NULL;
+PFNGLBLENDEQUATIONSEPARATEIARBPROC glad_glBlendEquationSeparateiARB = NULL;
+PFNGLBLENDEQUATIONIPROC glad_glBlendEquationi = NULL;
+PFNGLBLENDEQUATIONIARBPROC glad_glBlendEquationiARB = NULL;
+PFNGLBLENDFUNCPROC glad_glBlendFunc = NULL;
+PFNGLBLENDFUNCSEPARATEPROC glad_glBlendFuncSeparate = NULL;
+PFNGLBLENDFUNCSEPARATEIPROC glad_glBlendFuncSeparatei = NULL;
+PFNGLBLENDFUNCSEPARATEIARBPROC glad_glBlendFuncSeparateiARB = NULL;
+PFNGLBLENDFUNCIPROC glad_glBlendFunci = NULL;
+PFNGLBLENDFUNCIARBPROC glad_glBlendFunciARB = NULL;
+PFNGLBLITFRAMEBUFFERPROC glad_glBlitFramebuffer = NULL;
+PFNGLBLITFRAMEBUFFEREXTPROC glad_glBlitFramebufferEXT = NULL;
+PFNGLBLITNAMEDFRAMEBUFFERPROC glad_glBlitNamedFramebuffer = NULL;
+PFNGLBUFFERDATAPROC glad_glBufferData = NULL;
+PFNGLBUFFERDATAARBPROC glad_glBufferDataARB = NULL;
+PFNGLBUFFERSTORAGEPROC glad_glBufferStorage = NULL;
+PFNGLBUFFERSUBDATAPROC glad_glBufferSubData = NULL;
+PFNGLBUFFERSUBDATAARBPROC glad_glBufferSubDataARB = NULL;
+PFNGLCHECKFRAMEBUFFERSTATUSPROC glad_glCheckFramebufferStatus = NULL;
+PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glad_glCheckFramebufferStatusEXT = NULL;
+PFNGLCHECKNAMEDFRAMEBUFFERSTATUSPROC glad_glCheckNamedFramebufferStatus = NULL;
+PFNGLCLAMPCOLORPROC glad_glClampColor = NULL;
+PFNGLCLAMPCOLORARBPROC glad_glClampColorARB = NULL;
+PFNGLCLEARPROC glad_glClear = NULL;
+PFNGLCLEARACCUMXOESPROC glad_glClearAccumxOES = NULL;
+PFNGLCLEARBUFFERDATAPROC glad_glClearBufferData = NULL;
+PFNGLCLEARBUFFERSUBDATAPROC glad_glClearBufferSubData = NULL;
+PFNGLCLEARBUFFERFIPROC glad_glClearBufferfi = NULL;
+PFNGLCLEARBUFFERFVPROC glad_glClearBufferfv = NULL;
+PFNGLCLEARBUFFERIVPROC glad_glClearBufferiv = NULL;
+PFNGLCLEARBUFFERUIVPROC glad_glClearBufferuiv = NULL;
+PFNGLCLEARCOLORPROC glad_glClearColor = NULL;
+PFNGLCLEARCOLORXOESPROC glad_glClearColorxOES = NULL;
+PFNGLCLEARDEPTHPROC glad_glClearDepth = NULL;
+PFNGLCLEARDEPTHFPROC glad_glClearDepthf = NULL;
+PFNGLCLEARDEPTHXOESPROC glad_glClearDepthxOES = NULL;
+PFNGLCLEARNAMEDBUFFERDATAPROC glad_glClearNamedBufferData = NULL;
+PFNGLCLEARNAMEDBUFFERSUBDATAPROC glad_glClearNamedBufferSubData = NULL;
+PFNGLCLEARNAMEDFRAMEBUFFERFIPROC glad_glClearNamedFramebufferfi = NULL;
+PFNGLCLEARNAMEDFRAMEBUFFERFVPROC glad_glClearNamedFramebufferfv = NULL;
+PFNGLCLEARNAMEDFRAMEBUFFERIVPROC glad_glClearNamedFramebufferiv = NULL;
+PFNGLCLEARNAMEDFRAMEBUFFERUIVPROC glad_glClearNamedFramebufferuiv = NULL;
+PFNGLCLEARSTENCILPROC glad_glClearStencil = NULL;
+PFNGLCLEARTEXIMAGEPROC glad_glClearTexImage = NULL;
+PFNGLCLEARTEXSUBIMAGEPROC glad_glClearTexSubImage = NULL;
+PFNGLCLIENTACTIVETEXTUREARBPROC glad_glClientActiveTextureARB = NULL;
+PFNGLCLIENTWAITSYNCPROC glad_glClientWaitSync = NULL;
+PFNGLCLIPPLANEXOESPROC glad_glClipPlanexOES = NULL;
+PFNGLCOLOR3XOESPROC glad_glColor3xOES = NULL;
+PFNGLCOLOR3XVOESPROC glad_glColor3xvOES = NULL;
+PFNGLCOLOR4XOESPROC glad_glColor4xOES = NULL;
+PFNGLCOLOR4XVOESPROC glad_glColor4xvOES = NULL;
+PFNGLCOLORMASKPROC glad_glColorMask = NULL;
+PFNGLCOLORMASKIPROC glad_glColorMaski = NULL;
+PFNGLCOMPILESHADERPROC glad_glCompileShader = NULL;
+PFNGLCOMPILESHADERARBPROC glad_glCompileShaderARB = NULL;
+PFNGLCOMPILESHADERINCLUDEARBPROC glad_glCompileShaderIncludeARB = NULL;
+PFNGLCOMPRESSEDTEXIMAGE1DPROC glad_glCompressedTexImage1D = NULL;
+PFNGLCOMPRESSEDTEXIMAGE1DARBPROC glad_glCompressedTexImage1DARB = NULL;
+PFNGLCOMPRESSEDTEXIMAGE2DPROC glad_glCompressedTexImage2D = NULL;
+PFNGLCOMPRESSEDTEXIMAGE2DARBPROC glad_glCompressedTexImage2DARB = NULL;
+PFNGLCOMPRESSEDTEXIMAGE3DPROC glad_glCompressedTexImage3D = NULL;
+PFNGLCOMPRESSEDTEXIMAGE3DARBPROC glad_glCompressedTexImage3DARB = NULL;
+PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC glad_glCompressedTexSubImage1D = NULL;
+PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC glad_glCompressedTexSubImage1DARB = NULL;
+PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC glad_glCompressedTexSubImage2D = NULL;
+PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC glad_glCompressedTexSubImage2DARB = NULL;
+PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC glad_glCompressedTexSubImage3D = NULL;
+PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC glad_glCompressedTexSubImage3DARB = NULL;
+PFNGLCOMPRESSEDTEXTURESUBIMAGE1DPROC glad_glCompressedTextureSubImage1D = NULL;
+PFNGLCOMPRESSEDTEXTURESUBIMAGE2DPROC glad_glCompressedTextureSubImage2D = NULL;
+PFNGLCOMPRESSEDTEXTURESUBIMAGE3DPROC glad_glCompressedTextureSubImage3D = NULL;
+PFNGLCONVOLUTIONPARAMETERXOESPROC glad_glConvolutionParameterxOES = NULL;
+PFNGLCONVOLUTIONPARAMETERXVOESPROC glad_glConvolutionParameterxvOES = NULL;
+PFNGLCOPYBUFFERSUBDATAPROC glad_glCopyBufferSubData = NULL;
+PFNGLCOPYIMAGESUBDATAPROC glad_glCopyImageSubData = NULL;
+PFNGLCOPYNAMEDBUFFERSUBDATAPROC glad_glCopyNamedBufferSubData = NULL;
+PFNGLCOPYTEXIMAGE1DPROC glad_glCopyTexImage1D = NULL;
+PFNGLCOPYTEXIMAGE2DPROC glad_glCopyTexImage2D = NULL;
+PFNGLCOPYTEXSUBIMAGE1DPROC glad_glCopyTexSubImage1D = NULL;
+PFNGLCOPYTEXSUBIMAGE2DPROC glad_glCopyTexSubImage2D = NULL;
+PFNGLCOPYTEXSUBIMAGE3DPROC glad_glCopyTexSubImage3D = NULL;
+PFNGLCOPYTEXTURESUBIMAGE1DPROC glad_glCopyTextureSubImage1D = NULL;
+PFNGLCOPYTEXTURESUBIMAGE2DPROC glad_glCopyTextureSubImage2D = NULL;
+PFNGLCOPYTEXTURESUBIMAGE3DPROC glad_glCopyTextureSubImage3D = NULL;
+PFNGLCREATEBUFFERSPROC glad_glCreateBuffers = NULL;
+PFNGLCREATEFRAMEBUFFERSPROC glad_glCreateFramebuffers = NULL;
+PFNGLCREATEPROGRAMPROC glad_glCreateProgram = NULL;
+PFNGLCREATEPROGRAMOBJECTARBPROC glad_glCreateProgramObjectARB = NULL;
+PFNGLCREATEPROGRAMPIPELINESPROC glad_glCreateProgramPipelines = NULL;
+PFNGLCREATEQUERIESPROC glad_glCreateQueries = NULL;
+PFNGLCREATERENDERBUFFERSPROC glad_glCreateRenderbuffers = NULL;
+PFNGLCREATESAMPLERSPROC glad_glCreateSamplers = NULL;
+PFNGLCREATESHADERPROC glad_glCreateShader = NULL;
+PFNGLCREATESHADEROBJECTARBPROC glad_glCreateShaderObjectARB = NULL;
+PFNGLCREATESHADERPROGRAMVPROC glad_glCreateShaderProgramv = NULL;
+PFNGLCREATETEXTURESPROC glad_glCreateTextures = NULL;
+PFNGLCREATETRANSFORMFEEDBACKSPROC glad_glCreateTransformFeedbacks = NULL;
+PFNGLCREATEVERTEXARRAYSPROC glad_glCreateVertexArrays = NULL;
+PFNGLCULLFACEPROC glad_glCullFace = NULL;
+PFNGLDEBUGMESSAGECALLBACKPROC glad_glDebugMessageCallback = NULL;
+PFNGLDEBUGMESSAGECALLBACKARBPROC glad_glDebugMessageCallbackARB = NULL;
+PFNGLDEBUGMESSAGECONTROLPROC glad_glDebugMessageControl = NULL;
+PFNGLDEBUGMESSAGECONTROLARBPROC glad_glDebugMessageControlARB = NULL;
+PFNGLDEBUGMESSAGEINSERTPROC glad_glDebugMessageInsert = NULL;
+PFNGLDEBUGMESSAGEINSERTARBPROC glad_glDebugMessageInsertARB = NULL;
+PFNGLDELETEBUFFERSPROC glad_glDeleteBuffers = NULL;
+PFNGLDELETEBUFFERSARBPROC glad_glDeleteBuffersARB = NULL;
+PFNGLDELETEFRAMEBUFFERSPROC glad_glDeleteFramebuffers = NULL;
+PFNGLDELETEFRAMEBUFFERSEXTPROC glad_glDeleteFramebuffersEXT = NULL;
+PFNGLDELETENAMEDSTRINGARBPROC glad_glDeleteNamedStringARB = NULL;
+PFNGLDELETEOBJECTARBPROC glad_glDeleteObjectARB = NULL;
+PFNGLDELETEPROGRAMPROC glad_glDeleteProgram = NULL;
+PFNGLDELETEPROGRAMPIPELINESPROC glad_glDeleteProgramPipelines = NULL;
+PFNGLDELETEPROGRAMSARBPROC glad_glDeleteProgramsARB = NULL;
+PFNGLDELETEQUERIESPROC glad_glDeleteQueries = NULL;
+PFNGLDELETEQUERIESARBPROC glad_glDeleteQueriesARB = NULL;
+PFNGLDELETERENDERBUFFERSPROC glad_glDeleteRenderbuffers = NULL;
+PFNGLDELETERENDERBUFFERSEXTPROC glad_glDeleteRenderbuffersEXT = NULL;
+PFNGLDELETESAMPLERSPROC glad_glDeleteSamplers = NULL;
+PFNGLDELETESHADERPROC glad_glDeleteShader = NULL;
+PFNGLDELETESYNCPROC glad_glDeleteSync = NULL;
+PFNGLDELETETEXTURESPROC glad_glDeleteTextures = NULL;
+PFNGLDELETETRANSFORMFEEDBACKSPROC glad_glDeleteTransformFeedbacks = NULL;
+PFNGLDELETEVERTEXARRAYSPROC glad_glDeleteVertexArrays = NULL;
+PFNGLDEPTHFUNCPROC glad_glDepthFunc = NULL;
+PFNGLDEPTHMASKPROC glad_glDepthMask = NULL;
+PFNGLDEPTHRANGEPROC glad_glDepthRange = NULL;
+PFNGLDEPTHRANGEARRAYVPROC glad_glDepthRangeArrayv = NULL;
+PFNGLDEPTHRANGEINDEXEDPROC glad_glDepthRangeIndexed = NULL;
+PFNGLDEPTHRANGEFPROC glad_glDepthRangef = NULL;
+PFNGLDEPTHRANGEXOESPROC glad_glDepthRangexOES = NULL;
+PFNGLDETACHOBJECTARBPROC glad_glDetachObjectARB = NULL;
+PFNGLDETACHSHADERPROC glad_glDetachShader = NULL;
+PFNGLDISABLEPROC glad_glDisable = NULL;
+PFNGLDISABLEVERTEXARRAYATTRIBPROC glad_glDisableVertexArrayAttrib = NULL;
+PFNGLDISABLEVERTEXATTRIBARRAYPROC glad_glDisableVertexAttribArray = NULL;
+PFNGLDISABLEVERTEXATTRIBARRAYARBPROC glad_glDisableVertexAttribArrayARB = NULL;
+PFNGLDISABLEIPROC glad_glDisablei = NULL;
+PFNGLDISPATCHCOMPUTEPROC glad_glDispatchCompute = NULL;
+PFNGLDISPATCHCOMPUTEGROUPSIZEARBPROC glad_glDispatchComputeGroupSizeARB = NULL;
+PFNGLDISPATCHCOMPUTEINDIRECTPROC glad_glDispatchComputeIndirect = NULL;
+PFNGLDRAWARRAYSPROC glad_glDrawArrays = NULL;
+PFNGLDRAWARRAYSINDIRECTPROC glad_glDrawArraysIndirect = NULL;
+PFNGLDRAWARRAYSINSTANCEDPROC glad_glDrawArraysInstanced = NULL;
+PFNGLDRAWARRAYSINSTANCEDARBPROC glad_glDrawArraysInstancedARB = NULL;
+PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEPROC glad_glDrawArraysInstancedBaseInstance = NULL;
+PFNGLDRAWARRAYSINSTANCEDEXTPROC glad_glDrawArraysInstancedEXT = NULL;
+PFNGLDRAWBUFFERPROC glad_glDrawBuffer = NULL;
+PFNGLDRAWBUFFERSPROC glad_glDrawBuffers = NULL;
+PFNGLDRAWBUFFERSARBPROC glad_glDrawBuffersARB = NULL;
+PFNGLDRAWELEMENTSPROC glad_glDrawElements = NULL;
+PFNGLDRAWELEMENTSBASEVERTEXPROC glad_glDrawElementsBaseVertex = NULL;
+PFNGLDRAWELEMENTSINDIRECTPROC glad_glDrawElementsIndirect = NULL;
+PFNGLDRAWELEMENTSINSTANCEDPROC glad_glDrawElementsInstanced = NULL;
+PFNGLDRAWELEMENTSINSTANCEDARBPROC glad_glDrawElementsInstancedARB = NULL;
+PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEPROC glad_glDrawElementsInstancedBaseInstance = NULL;
+PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC glad_glDrawElementsInstancedBaseVertex = NULL;
+PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC glad_glDrawElementsInstancedBaseVertexBaseInstance = NULL;
+PFNGLDRAWELEMENTSINSTANCEDEXTPROC glad_glDrawElementsInstancedEXT = NULL;
+PFNGLDRAWRANGEELEMENTSPROC glad_glDrawRangeElements = NULL;
+PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC glad_glDrawRangeElementsBaseVertex = NULL;
+PFNGLDRAWTRANSFORMFEEDBACKPROC glad_glDrawTransformFeedback = NULL;
+PFNGLDRAWTRANSFORMFEEDBACKINSTANCEDPROC glad_glDrawTransformFeedbackInstanced = NULL;
+PFNGLDRAWTRANSFORMFEEDBACKSTREAMPROC glad_glDrawTransformFeedbackStream = NULL;
+PFNGLDRAWTRANSFORMFEEDBACKSTREAMINSTANCEDPROC glad_glDrawTransformFeedbackStreamInstanced = NULL;
+PFNGLENABLEPROC glad_glEnable = NULL;
+PFNGLENABLEVERTEXARRAYATTRIBPROC glad_glEnableVertexArrayAttrib = NULL;
+PFNGLENABLEVERTEXATTRIBARRAYPROC glad_glEnableVertexAttribArray = NULL;
+PFNGLENABLEVERTEXATTRIBARRAYARBPROC glad_glEnableVertexAttribArrayARB = NULL;
+PFNGLENABLEIPROC glad_glEnablei = NULL;
+PFNGLENDCONDITIONALRENDERPROC glad_glEndConditionalRender = NULL;
+PFNGLENDQUERYPROC glad_glEndQuery = NULL;
+PFNGLENDQUERYARBPROC glad_glEndQueryARB = NULL;
+PFNGLENDQUERYINDEXEDPROC glad_glEndQueryIndexed = NULL;
+PFNGLENDTRANSFORMFEEDBACKPROC glad_glEndTransformFeedback = NULL;
+PFNGLEVALCOORD1XOESPROC glad_glEvalCoord1xOES = NULL;
+PFNGLEVALCOORD1XVOESPROC glad_glEvalCoord1xvOES = NULL;
+PFNGLEVALCOORD2XOESPROC glad_glEvalCoord2xOES = NULL;
+PFNGLEVALCOORD2XVOESPROC glad_glEvalCoord2xvOES = NULL;
+PFNGLEVALUATEDEPTHVALUESARBPROC glad_glEvaluateDepthValuesARB = NULL;
+PFNGLFEEDBACKBUFFERXOESPROC glad_glFeedbackBufferxOES = NULL;
+PFNGLFENCESYNCPROC glad_glFenceSync = NULL;
+PFNGLFINISHPROC glad_glFinish = NULL;
+PFNGLFLUSHPROC glad_glFlush = NULL;
+PFNGLFLUSHMAPPEDBUFFERRANGEPROC glad_glFlushMappedBufferRange = NULL;
+PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEPROC glad_glFlushMappedNamedBufferRange = NULL;
+PFNGLFOGCOORDPOINTEREXTPROC glad_glFogCoordPointerEXT = NULL;
+PFNGLFOGCOORDDEXTPROC glad_glFogCoorddEXT = NULL;
+PFNGLFOGCOORDDVEXTPROC glad_glFogCoorddvEXT = NULL;
+PFNGLFOGCOORDFEXTPROC glad_glFogCoordfEXT = NULL;
+PFNGLFOGCOORDFVEXTPROC glad_glFogCoordfvEXT = NULL;
+PFNGLFOGXOESPROC glad_glFogxOES = NULL;
+PFNGLFOGXVOESPROC glad_glFogxvOES = NULL;
+PFNGLFRAMEBUFFERPARAMETERIPROC glad_glFramebufferParameteri = NULL;
+PFNGLFRAMEBUFFERRENDERBUFFERPROC glad_glFramebufferRenderbuffer = NULL;
+PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glad_glFramebufferRenderbufferEXT = NULL;
+PFNGLFRAMEBUFFERSAMPLELOCATIONSFVARBPROC glad_glFramebufferSampleLocationsfvARB = NULL;
+PFNGLFRAMEBUFFERTEXTUREPROC glad_glFramebufferTexture = NULL;
+PFNGLFRAMEBUFFERTEXTURE1DPROC glad_glFramebufferTexture1D = NULL;
+PFNGLFRAMEBUFFERTEXTURE1DEXTPROC glad_glFramebufferTexture1DEXT = NULL;
+PFNGLFRAMEBUFFERTEXTURE2DPROC glad_glFramebufferTexture2D = NULL;
+PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glad_glFramebufferTexture2DEXT = NULL;
+PFNGLFRAMEBUFFERTEXTURE3DPROC glad_glFramebufferTexture3D = NULL;
+PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glad_glFramebufferTexture3DEXT = NULL;
+PFNGLFRAMEBUFFERTEXTUREARBPROC glad_glFramebufferTextureARB = NULL;
+PFNGLFRAMEBUFFERTEXTUREFACEARBPROC glad_glFramebufferTextureFaceARB = NULL;
+PFNGLFRAMEBUFFERTEXTURELAYERPROC glad_glFramebufferTextureLayer = NULL;
+PFNGLFRAMEBUFFERTEXTURELAYERARBPROC glad_glFramebufferTextureLayerARB = NULL;
+PFNGLFRONTFACEPROC glad_glFrontFace = NULL;
+PFNGLFRUSTUMXOESPROC glad_glFrustumxOES = NULL;
+PFNGLGENBUFFERSPROC glad_glGenBuffers = NULL;
+PFNGLGENBUFFERSARBPROC glad_glGenBuffersARB = NULL;
+PFNGLGENFRAMEBUFFERSPROC glad_glGenFramebuffers = NULL;
+PFNGLGENFRAMEBUFFERSEXTPROC glad_glGenFramebuffersEXT = NULL;
+PFNGLGENPROGRAMPIPELINESPROC glad_glGenProgramPipelines = NULL;
+PFNGLGENPROGRAMSARBPROC glad_glGenProgramsARB = NULL;
+PFNGLGENQUERIESPROC glad_glGenQueries = NULL;
+PFNGLGENQUERIESARBPROC glad_glGenQueriesARB = NULL;
+PFNGLGENRENDERBUFFERSPROC glad_glGenRenderbuffers = NULL;
+PFNGLGENRENDERBUFFERSEXTPROC glad_glGenRenderbuffersEXT = NULL;
+PFNGLGENSAMPLERSPROC glad_glGenSamplers = NULL;
+PFNGLGENTEXTURESPROC glad_glGenTextures = NULL;
+PFNGLGENTRANSFORMFEEDBACKSPROC glad_glGenTransformFeedbacks = NULL;
+PFNGLGENVERTEXARRAYSPROC glad_glGenVertexArrays = NULL;
+PFNGLGENERATEMIPMAPPROC glad_glGenerateMipmap = NULL;
+PFNGLGENERATEMIPMAPEXTPROC glad_glGenerateMipmapEXT = NULL;
+PFNGLGENERATETEXTUREMIPMAPPROC glad_glGenerateTextureMipmap = NULL;
+PFNGLGETACTIVEATOMICCOUNTERBUFFERIVPROC glad_glGetActiveAtomicCounterBufferiv = NULL;
+PFNGLGETACTIVEATTRIBPROC glad_glGetActiveAttrib = NULL;
+PFNGLGETACTIVEATTRIBARBPROC glad_glGetActiveAttribARB = NULL;
+PFNGLGETACTIVESUBROUTINENAMEPROC glad_glGetActiveSubroutineName = NULL;
+PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC glad_glGetActiveSubroutineUniformName = NULL;
+PFNGLGETACTIVESUBROUTINEUNIFORMIVPROC glad_glGetActiveSubroutineUniformiv = NULL;
+PFNGLGETACTIVEUNIFORMPROC glad_glGetActiveUniform = NULL;
+PFNGLGETACTIVEUNIFORMARBPROC glad_glGetActiveUniformARB = NULL;
+PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC glad_glGetActiveUniformBlockName = NULL;
+PFNGLGETACTIVEUNIFORMBLOCKIVPROC glad_glGetActiveUniformBlockiv = NULL;
+PFNGLGETACTIVEUNIFORMNAMEPROC glad_glGetActiveUniformName = NULL;
+PFNGLGETACTIVEUNIFORMSIVPROC glad_glGetActiveUniformsiv = NULL;
+PFNGLGETATTACHEDOBJECTSARBPROC glad_glGetAttachedObjectsARB = NULL;
+PFNGLGETATTACHEDSHADERSPROC glad_glGetAttachedShaders = NULL;
+PFNGLGETATTRIBLOCATIONPROC glad_glGetAttribLocation = NULL;
+PFNGLGETATTRIBLOCATIONARBPROC glad_glGetAttribLocationARB = NULL;
+PFNGLGETBOOLEANI_VPROC glad_glGetBooleani_v = NULL;
+PFNGLGETBOOLEANVPROC glad_glGetBooleanv = NULL;
+PFNGLGETBUFFERPARAMETERI64VPROC glad_glGetBufferParameteri64v = NULL;
+PFNGLGETBUFFERPARAMETERIVPROC glad_glGetBufferParameteriv = NULL;
+PFNGLGETBUFFERPARAMETERIVARBPROC glad_glGetBufferParameterivARB = NULL;
+PFNGLGETBUFFERPOINTERVPROC glad_glGetBufferPointerv = NULL;
+PFNGLGETBUFFERPOINTERVARBPROC glad_glGetBufferPointervARB = NULL;
+PFNGLGETBUFFERSUBDATAPROC glad_glGetBufferSubData = NULL;
+PFNGLGETBUFFERSUBDATAARBPROC glad_glGetBufferSubDataARB = NULL;
+PFNGLGETCLIPPLANEXOESPROC glad_glGetClipPlanexOES = NULL;
+PFNGLGETCOMPRESSEDTEXIMAGEPROC glad_glGetCompressedTexImage = NULL;
+PFNGLGETCOMPRESSEDTEXIMAGEARBPROC glad_glGetCompressedTexImageARB = NULL;
+PFNGLGETCOMPRESSEDTEXTUREIMAGEPROC glad_glGetCompressedTextureImage = NULL;
+PFNGLGETCOMPRESSEDTEXTURESUBIMAGEPROC glad_glGetCompressedTextureSubImage = NULL;
+PFNGLGETCONVOLUTIONPARAMETERXVOESPROC glad_glGetConvolutionParameterxvOES = NULL;
+PFNGLGETDEBUGMESSAGELOGPROC glad_glGetDebugMessageLog = NULL;
+PFNGLGETDEBUGMESSAGELOGARBPROC glad_glGetDebugMessageLogARB = NULL;
+PFNGLGETDOUBLEI_VPROC glad_glGetDoublei_v = NULL;
+PFNGLGETDOUBLEVPROC glad_glGetDoublev = NULL;
+PFNGLGETERRORPROC glad_glGetError = NULL;
+PFNGLGETFIXEDVOESPROC glad_glGetFixedvOES = NULL;
+PFNGLGETFLOATI_VPROC glad_glGetFloati_v = NULL;
+PFNGLGETFLOATVPROC glad_glGetFloatv = NULL;
+PFNGLGETFRAGDATAINDEXPROC glad_glGetFragDataIndex = NULL;
+PFNGLGETFRAGDATALOCATIONPROC glad_glGetFragDataLocation = NULL;
+PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glad_glGetFramebufferAttachmentParameteriv = NULL;
+PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glad_glGetFramebufferAttachmentParameterivEXT = NULL;
+PFNGLGETFRAMEBUFFERPARAMETERIVPROC glad_glGetFramebufferParameteriv = NULL;
+PFNGLGETHANDLEARBPROC glad_glGetHandleARB = NULL;
+PFNGLGETHISTOGRAMPARAMETERXVOESPROC glad_glGetHistogramParameterxvOES = NULL;
+PFNGLGETINFOLOGARBPROC glad_glGetInfoLogARB = NULL;
+PFNGLGETINTEGER64I_VPROC glad_glGetInteger64i_v = NULL;
+PFNGLGETINTEGER64VPROC glad_glGetInteger64v = NULL;
+PFNGLGETINTEGERI_VPROC glad_glGetIntegeri_v = NULL;
+PFNGLGETINTEGERVPROC glad_glGetIntegerv = NULL;
+PFNGLGETINTERNALFORMATI64VPROC glad_glGetInternalformati64v = NULL;
+PFNGLGETINTERNALFORMATIVPROC glad_glGetInternalformativ = NULL;
+PFNGLGETLIGHTXOESPROC glad_glGetLightxOES = NULL;
+PFNGLGETMAPXVOESPROC glad_glGetMapxvOES = NULL;
+PFNGLGETMATERIALXOESPROC glad_glGetMaterialxOES = NULL;
+PFNGLGETMULTISAMPLEFVPROC glad_glGetMultisamplefv = NULL;
+PFNGLGETNAMEDBUFFERPARAMETERI64VPROC glad_glGetNamedBufferParameteri64v = NULL;
+PFNGLGETNAMEDBUFFERPARAMETERIVPROC glad_glGetNamedBufferParameteriv = NULL;
+PFNGLGETNAMEDBUFFERPOINTERVPROC glad_glGetNamedBufferPointerv = NULL;
+PFNGLGETNAMEDBUFFERSUBDATAPROC glad_glGetNamedBufferSubData = NULL;
+PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVPROC glad_glGetNamedFramebufferAttachmentParameteriv = NULL;
+PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVPROC glad_glGetNamedFramebufferParameteriv = NULL;
+PFNGLGETNAMEDRENDERBUFFERPARAMETERIVPROC glad_glGetNamedRenderbufferParameteriv = NULL;
+PFNGLGETNAMEDSTRINGARBPROC glad_glGetNamedStringARB = NULL;
+PFNGLGETNAMEDSTRINGIVARBPROC glad_glGetNamedStringivARB = NULL;
+PFNGLGETOBJECTLABELPROC glad_glGetObjectLabel = NULL;
+PFNGLGETOBJECTPARAMETERFVARBPROC glad_glGetObjectParameterfvARB = NULL;
+PFNGLGETOBJECTPARAMETERIVARBPROC glad_glGetObjectParameterivARB = NULL;
+PFNGLGETOBJECTPTRLABELPROC glad_glGetObjectPtrLabel = NULL;
+PFNGLGETPIXELMAPXVPROC glad_glGetPixelMapxv = NULL;
+PFNGLGETPOINTERVPROC glad_glGetPointerv = NULL;
+PFNGLGETPROGRAMBINARYPROC glad_glGetProgramBinary = NULL;
+PFNGLGETPROGRAMENVPARAMETERDVARBPROC glad_glGetProgramEnvParameterdvARB = NULL;
+PFNGLGETPROGRAMENVPARAMETERFVARBPROC glad_glGetProgramEnvParameterfvARB = NULL;
+PFNGLGETPROGRAMINFOLOGPROC glad_glGetProgramInfoLog = NULL;
+PFNGLGETPROGRAMINTERFACEIVPROC glad_glGetProgramInterfaceiv = NULL;
+PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC glad_glGetProgramLocalParameterdvARB = NULL;
+PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC glad_glGetProgramLocalParameterfvARB = NULL;
+PFNGLGETPROGRAMPIPELINEINFOLOGPROC glad_glGetProgramPipelineInfoLog = NULL;
+PFNGLGETPROGRAMPIPELINEIVPROC glad_glGetProgramPipelineiv = NULL;
+PFNGLGETPROGRAMRESOURCEINDEXPROC glad_glGetProgramResourceIndex = NULL;
+PFNGLGETPROGRAMRESOURCELOCATIONPROC glad_glGetProgramResourceLocation = NULL;
+PFNGLGETPROGRAMRESOURCELOCATIONINDEXPROC glad_glGetProgramResourceLocationIndex = NULL;
+PFNGLGETPROGRAMRESOURCENAMEPROC glad_glGetProgramResourceName = NULL;
+PFNGLGETPROGRAMRESOURCEIVPROC glad_glGetProgramResourceiv = NULL;
+PFNGLGETPROGRAMSTAGEIVPROC glad_glGetProgramStageiv = NULL;
+PFNGLGETPROGRAMSTRINGARBPROC glad_glGetProgramStringARB = NULL;
+PFNGLGETPROGRAMIVPROC glad_glGetProgramiv = NULL;
+PFNGLGETPROGRAMIVARBPROC glad_glGetProgramivARB = NULL;
+PFNGLGETQUERYBUFFEROBJECTI64VPROC glad_glGetQueryBufferObjecti64v = NULL;
+PFNGLGETQUERYBUFFEROBJECTIVPROC glad_glGetQueryBufferObjectiv = NULL;
+PFNGLGETQUERYBUFFEROBJECTUI64VPROC glad_glGetQueryBufferObjectui64v = NULL;
+PFNGLGETQUERYBUFFEROBJECTUIVPROC glad_glGetQueryBufferObjectuiv = NULL;
+PFNGLGETQUERYINDEXEDIVPROC glad_glGetQueryIndexediv = NULL;
+PFNGLGETQUERYOBJECTI64VPROC glad_glGetQueryObjecti64v = NULL;
+PFNGLGETQUERYOBJECTIVPROC glad_glGetQueryObjectiv = NULL;
+PFNGLGETQUERYOBJECTIVARBPROC glad_glGetQueryObjectivARB = NULL;
+PFNGLGETQUERYOBJECTUI64VPROC glad_glGetQueryObjectui64v = NULL;
+PFNGLGETQUERYOBJECTUIVPROC glad_glGetQueryObjectuiv = NULL;
+PFNGLGETQUERYOBJECTUIVARBPROC glad_glGetQueryObjectuivARB = NULL;
+PFNGLGETQUERYIVPROC glad_glGetQueryiv = NULL;
+PFNGLGETQUERYIVARBPROC glad_glGetQueryivARB = NULL;
+PFNGLGETRENDERBUFFERPARAMETERIVPROC glad_glGetRenderbufferParameteriv = NULL;
+PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC glad_glGetRenderbufferParameterivEXT = NULL;
+PFNGLGETSAMPLERPARAMETERIIVPROC glad_glGetSamplerParameterIiv = NULL;
+PFNGLGETSAMPLERPARAMETERIUIVPROC glad_glGetSamplerParameterIuiv = NULL;
+PFNGLGETSAMPLERPARAMETERFVPROC glad_glGetSamplerParameterfv = NULL;
+PFNGLGETSAMPLERPARAMETERIVPROC glad_glGetSamplerParameteriv = NULL;
+PFNGLGETSHADERINFOLOGPROC glad_glGetShaderInfoLog = NULL;
+PFNGLGETSHADERPRECISIONFORMATPROC glad_glGetShaderPrecisionFormat = NULL;
+PFNGLGETSHADERSOURCEPROC glad_glGetShaderSource = NULL;
+PFNGLGETSHADERSOURCEARBPROC glad_glGetShaderSourceARB = NULL;
+PFNGLGETSHADERIVPROC glad_glGetShaderiv = NULL;
+PFNGLGETSTRINGPROC glad_glGetString = NULL;
+PFNGLGETSTRINGIPROC glad_glGetStringi = NULL;
+PFNGLGETSUBROUTINEINDEXPROC glad_glGetSubroutineIndex = NULL;
+PFNGLGETSUBROUTINEUNIFORMLOCATIONPROC glad_glGetSubroutineUniformLocation = NULL;
+PFNGLGETSYNCIVPROC glad_glGetSynciv = NULL;
+PFNGLGETTEXENVXVOESPROC glad_glGetTexEnvxvOES = NULL;
+PFNGLGETTEXGENXVOESPROC glad_glGetTexGenxvOES = NULL;
+PFNGLGETTEXIMAGEPROC glad_glGetTexImage = NULL;
+PFNGLGETTEXLEVELPARAMETERFVPROC glad_glGetTexLevelParameterfv = NULL;
+PFNGLGETTEXLEVELPARAMETERIVPROC glad_glGetTexLevelParameteriv = NULL;
+PFNGLGETTEXLEVELPARAMETERXVOESPROC glad_glGetTexLevelParameterxvOES = NULL;
+PFNGLGETTEXPARAMETERIIVPROC glad_glGetTexParameterIiv = NULL;
+PFNGLGETTEXPARAMETERIUIVPROC glad_glGetTexParameterIuiv = NULL;
+PFNGLGETTEXPARAMETERFVPROC glad_glGetTexParameterfv = NULL;
+PFNGLGETTEXPARAMETERIVPROC glad_glGetTexParameteriv = NULL;
+PFNGLGETTEXPARAMETERXVOESPROC glad_glGetTexParameterxvOES = NULL;
+PFNGLGETTEXTUREIMAGEPROC glad_glGetTextureImage = NULL;
+PFNGLGETTEXTURELEVELPARAMETERFVPROC glad_glGetTextureLevelParameterfv = NULL;
+PFNGLGETTEXTURELEVELPARAMETERIVPROC glad_glGetTextureLevelParameteriv = NULL;
+PFNGLGETTEXTUREPARAMETERIIVPROC glad_glGetTextureParameterIiv = NULL;
+PFNGLGETTEXTUREPARAMETERIUIVPROC glad_glGetTextureParameterIuiv = NULL;
+PFNGLGETTEXTUREPARAMETERFVPROC glad_glGetTextureParameterfv = NULL;
+PFNGLGETTEXTUREPARAMETERIVPROC glad_glGetTextureParameteriv = NULL;
+PFNGLGETTEXTURESUBIMAGEPROC glad_glGetTextureSubImage = NULL;
+PFNGLGETTRANSFORMFEEDBACKVARYINGPROC glad_glGetTransformFeedbackVarying = NULL;
+PFNGLGETTRANSFORMFEEDBACKI64_VPROC glad_glGetTransformFeedbacki64_v = NULL;
+PFNGLGETTRANSFORMFEEDBACKI_VPROC glad_glGetTransformFeedbacki_v = NULL;
+PFNGLGETTRANSFORMFEEDBACKIVPROC glad_glGetTransformFeedbackiv = NULL;
+PFNGLGETUNIFORMBLOCKINDEXPROC glad_glGetUniformBlockIndex = NULL;
+PFNGLGETUNIFORMINDICESPROC glad_glGetUniformIndices = NULL;
+PFNGLGETUNIFORMLOCATIONPROC glad_glGetUniformLocation = NULL;
+PFNGLGETUNIFORMLOCATIONARBPROC glad_glGetUniformLocationARB = NULL;
+PFNGLGETUNIFORMSUBROUTINEUIVPROC glad_glGetUniformSubroutineuiv = NULL;
+PFNGLGETUNIFORMDVPROC glad_glGetUniformdv = NULL;
+PFNGLGETUNIFORMFVPROC glad_glGetUniformfv = NULL;
+PFNGLGETUNIFORMFVARBPROC glad_glGetUniformfvARB = NULL;
+PFNGLGETUNIFORMI64VARBPROC glad_glGetUniformi64vARB = NULL;
+PFNGLGETUNIFORMIVPROC glad_glGetUniformiv = NULL;
+PFNGLGETUNIFORMIVARBPROC glad_glGetUniformivARB = NULL;
+PFNGLGETUNIFORMUI64VARBPROC glad_glGetUniformui64vARB = NULL;
+PFNGLGETUNIFORMUIVPROC glad_glGetUniformuiv = NULL;
+PFNGLGETVERTEXARRAYINDEXED64IVPROC glad_glGetVertexArrayIndexed64iv = NULL;
+PFNGLGETVERTEXARRAYINDEXEDIVPROC glad_glGetVertexArrayIndexediv = NULL;
+PFNGLGETVERTEXARRAYIVPROC glad_glGetVertexArrayiv = NULL;
+PFNGLGETVERTEXATTRIBIIVPROC glad_glGetVertexAttribIiv = NULL;
+PFNGLGETVERTEXATTRIBIUIVPROC glad_glGetVertexAttribIuiv = NULL;
+PFNGLGETVERTEXATTRIBLDVPROC glad_glGetVertexAttribLdv = NULL;
+PFNGLGETVERTEXATTRIBPOINTERVPROC glad_glGetVertexAttribPointerv = NULL;
+PFNGLGETVERTEXATTRIBPOINTERVARBPROC glad_glGetVertexAttribPointervARB = NULL;
+PFNGLGETVERTEXATTRIBDVPROC glad_glGetVertexAttribdv = NULL;
+PFNGLGETVERTEXATTRIBDVARBPROC glad_glGetVertexAttribdvARB = NULL;
+PFNGLGETVERTEXATTRIBFVPROC glad_glGetVertexAttribfv = NULL;
+PFNGLGETVERTEXATTRIBFVARBPROC glad_glGetVertexAttribfvARB = NULL;
+PFNGLGETVERTEXATTRIBIVPROC glad_glGetVertexAttribiv = NULL;
+PFNGLGETVERTEXATTRIBIVARBPROC glad_glGetVertexAttribivARB = NULL;
+PFNGLGETNUNIFORMI64VARBPROC glad_glGetnUniformi64vARB = NULL;
+PFNGLGETNUNIFORMUI64VARBPROC glad_glGetnUniformui64vARB = NULL;
+PFNGLHINTPROC glad_glHint = NULL;
+PFNGLINDEXXOESPROC glad_glIndexxOES = NULL;
+PFNGLINDEXXVOESPROC glad_glIndexxvOES = NULL;
+PFNGLINVALIDATEBUFFERDATAPROC glad_glInvalidateBufferData = NULL;
+PFNGLINVALIDATEBUFFERSUBDATAPROC glad_glInvalidateBufferSubData = NULL;
+PFNGLINVALIDATEFRAMEBUFFERPROC glad_glInvalidateFramebuffer = NULL;
+PFNGLINVALIDATENAMEDFRAMEBUFFERDATAPROC glad_glInvalidateNamedFramebufferData = NULL;
+PFNGLINVALIDATENAMEDFRAMEBUFFERSUBDATAPROC glad_glInvalidateNamedFramebufferSubData = NULL;
+PFNGLINVALIDATESUBFRAMEBUFFERPROC glad_glInvalidateSubFramebuffer = NULL;
+PFNGLINVALIDATETEXIMAGEPROC glad_glInvalidateTexImage = NULL;
+PFNGLINVALIDATETEXSUBIMAGEPROC glad_glInvalidateTexSubImage = NULL;
+PFNGLISBUFFERPROC glad_glIsBuffer = NULL;
+PFNGLISBUFFERARBPROC glad_glIsBufferARB = NULL;
+PFNGLISENABLEDPROC glad_glIsEnabled = NULL;
+PFNGLISENABLEDIPROC glad_glIsEnabledi = NULL;
+PFNGLISFRAMEBUFFERPROC glad_glIsFramebuffer = NULL;
+PFNGLISFRAMEBUFFEREXTPROC glad_glIsFramebufferEXT = NULL;
+PFNGLISNAMEDSTRINGARBPROC glad_glIsNamedStringARB = NULL;
+PFNGLISPROGRAMPROC glad_glIsProgram = NULL;
+PFNGLISPROGRAMARBPROC glad_glIsProgramARB = NULL;
+PFNGLISPROGRAMPIPELINEPROC glad_glIsProgramPipeline = NULL;
+PFNGLISQUERYPROC glad_glIsQuery = NULL;
+PFNGLISQUERYARBPROC glad_glIsQueryARB = NULL;
+PFNGLISRENDERBUFFERPROC glad_glIsRenderbuffer = NULL;
+PFNGLISRENDERBUFFEREXTPROC glad_glIsRenderbufferEXT = NULL;
+PFNGLISSAMPLERPROC glad_glIsSampler = NULL;
+PFNGLISSHADERPROC glad_glIsShader = NULL;
+PFNGLISSYNCPROC glad_glIsSync = NULL;
+PFNGLISTEXTUREPROC glad_glIsTexture = NULL;
+PFNGLISTRANSFORMFEEDBACKPROC glad_glIsTransformFeedback = NULL;
+PFNGLISVERTEXARRAYPROC glad_glIsVertexArray = NULL;
+PFNGLLIGHTMODELXOESPROC glad_glLightModelxOES = NULL;
+PFNGLLIGHTMODELXVOESPROC glad_glLightModelxvOES = NULL;
+PFNGLLIGHTXOESPROC glad_glLightxOES = NULL;
+PFNGLLIGHTXVOESPROC glad_glLightxvOES = NULL;
+PFNGLLINEWIDTHPROC glad_glLineWidth = NULL;
+PFNGLLINEWIDTHXOESPROC glad_glLineWidthxOES = NULL;
+PFNGLLINKPROGRAMPROC glad_glLinkProgram = NULL;
+PFNGLLINKPROGRAMARBPROC glad_glLinkProgramARB = NULL;
+PFNGLLOADMATRIXXOESPROC glad_glLoadMatrixxOES = NULL;
+PFNGLLOADTRANSPOSEMATRIXDARBPROC glad_glLoadTransposeMatrixdARB = NULL;
+PFNGLLOADTRANSPOSEMATRIXFARBPROC glad_glLoadTransposeMatrixfARB = NULL;
+PFNGLLOADTRANSPOSEMATRIXXOESPROC glad_glLoadTransposeMatrixxOES = NULL;
+PFNGLLOGICOPPROC glad_glLogicOp = NULL;
+PFNGLMAP1XOESPROC glad_glMap1xOES = NULL;
+PFNGLMAP2XOESPROC glad_glMap2xOES = NULL;
+PFNGLMAPBUFFERPROC glad_glMapBuffer = NULL;
+PFNGLMAPBUFFERARBPROC glad_glMapBufferARB = NULL;
+PFNGLMAPBUFFERRANGEPROC glad_glMapBufferRange = NULL;
+PFNGLMAPGRID1XOESPROC glad_glMapGrid1xOES = NULL;
+PFNGLMAPGRID2XOESPROC glad_glMapGrid2xOES = NULL;
+PFNGLMAPNAMEDBUFFERPROC glad_glMapNamedBuffer = NULL;
+PFNGLMAPNAMEDBUFFERRANGEPROC glad_glMapNamedBufferRange = NULL;
+PFNGLMATERIALXOESPROC glad_glMaterialxOES = NULL;
+PFNGLMATERIALXVOESPROC glad_glMaterialxvOES = NULL;
+PFNGLMEMORYBARRIERPROC glad_glMemoryBarrier = NULL;
+PFNGLMEMORYBARRIERBYREGIONPROC glad_glMemoryBarrierByRegion = NULL;
+PFNGLMINSAMPLESHADINGPROC glad_glMinSampleShading = NULL;
+PFNGLMINSAMPLESHADINGARBPROC glad_glMinSampleShadingARB = NULL;
+PFNGLMULTMATRIXXOESPROC glad_glMultMatrixxOES = NULL;
+PFNGLMULTTRANSPOSEMATRIXDARBPROC glad_glMultTransposeMatrixdARB = NULL;
+PFNGLMULTTRANSPOSEMATRIXFARBPROC glad_glMultTransposeMatrixfARB = NULL;
+PFNGLMULTTRANSPOSEMATRIXXOESPROC glad_glMultTransposeMatrixxOES = NULL;
+PFNGLMULTIDRAWARRAYSPROC glad_glMultiDrawArrays = NULL;
+PFNGLMULTIDRAWARRAYSINDIRECTPROC glad_glMultiDrawArraysIndirect = NULL;
+PFNGLMULTIDRAWELEMENTSPROC glad_glMultiDrawElements = NULL;
+PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC glad_glMultiDrawElementsBaseVertex = NULL;
+PFNGLMULTIDRAWELEMENTSINDIRECTPROC glad_glMultiDrawElementsIndirect = NULL;
+PFNGLMULTITEXCOORD1DARBPROC glad_glMultiTexCoord1dARB = NULL;
+PFNGLMULTITEXCOORD1DVARBPROC glad_glMultiTexCoord1dvARB = NULL;
+PFNGLMULTITEXCOORD1FARBPROC glad_glMultiTexCoord1fARB = NULL;
+PFNGLMULTITEXCOORD1FVARBPROC glad_glMultiTexCoord1fvARB = NULL;
+PFNGLMULTITEXCOORD1IARBPROC glad_glMultiTexCoord1iARB = NULL;
+PFNGLMULTITEXCOORD1IVARBPROC glad_glMultiTexCoord1ivARB = NULL;
+PFNGLMULTITEXCOORD1SARBPROC glad_glMultiTexCoord1sARB = NULL;
+PFNGLMULTITEXCOORD1SVARBPROC glad_glMultiTexCoord1svARB = NULL;
+PFNGLMULTITEXCOORD1XOESPROC glad_glMultiTexCoord1xOES = NULL;
+PFNGLMULTITEXCOORD1XVOESPROC glad_glMultiTexCoord1xvOES = NULL;
+PFNGLMULTITEXCOORD2DARBPROC glad_glMultiTexCoord2dARB = NULL;
+PFNGLMULTITEXCOORD2DVARBPROC glad_glMultiTexCoord2dvARB = NULL;
+PFNGLMULTITEXCOORD2FARBPROC glad_glMultiTexCoord2fARB = NULL;
+PFNGLMULTITEXCOORD2FVARBPROC glad_glMultiTexCoord2fvARB = NULL;
+PFNGLMULTITEXCOORD2IARBPROC glad_glMultiTexCoord2iARB = NULL;
+PFNGLMULTITEXCOORD2IVARBPROC glad_glMultiTexCoord2ivARB = NULL;
+PFNGLMULTITEXCOORD2SARBPROC glad_glMultiTexCoord2sARB = NULL;
+PFNGLMULTITEXCOORD2SVARBPROC glad_glMultiTexCoord2svARB = NULL;
+PFNGLMULTITEXCOORD2XOESPROC glad_glMultiTexCoord2xOES = NULL;
+PFNGLMULTITEXCOORD2XVOESPROC glad_glMultiTexCoord2xvOES = NULL;
+PFNGLMULTITEXCOORD3DARBPROC glad_glMultiTexCoord3dARB = NULL;
+PFNGLMULTITEXCOORD3DVARBPROC glad_glMultiTexCoord3dvARB = NULL;
+PFNGLMULTITEXCOORD3FARBPROC glad_glMultiTexCoord3fARB = NULL;
+PFNGLMULTITEXCOORD3FVARBPROC glad_glMultiTexCoord3fvARB = NULL;
+PFNGLMULTITEXCOORD3IARBPROC glad_glMultiTexCoord3iARB = NULL;
+PFNGLMULTITEXCOORD3IVARBPROC glad_glMultiTexCoord3ivARB = NULL;
+PFNGLMULTITEXCOORD3SARBPROC glad_glMultiTexCoord3sARB = NULL;
+PFNGLMULTITEXCOORD3SVARBPROC glad_glMultiTexCoord3svARB = NULL;
+PFNGLMULTITEXCOORD3XOESPROC glad_glMultiTexCoord3xOES = NULL;
+PFNGLMULTITEXCOORD3XVOESPROC glad_glMultiTexCoord3xvOES = NULL;
+PFNGLMULTITEXCOORD4DARBPROC glad_glMultiTexCoord4dARB = NULL;
+PFNGLMULTITEXCOORD4DVARBPROC glad_glMultiTexCoord4dvARB = NULL;
+PFNGLMULTITEXCOORD4FARBPROC glad_glMultiTexCoord4fARB = NULL;
+PFNGLMULTITEXCOORD4FVARBPROC glad_glMultiTexCoord4fvARB = NULL;
+PFNGLMULTITEXCOORD4IARBPROC glad_glMultiTexCoord4iARB = NULL;
+PFNGLMULTITEXCOORD4IVARBPROC glad_glMultiTexCoord4ivARB = NULL;
+PFNGLMULTITEXCOORD4SARBPROC glad_glMultiTexCoord4sARB = NULL;
+PFNGLMULTITEXCOORD4SVARBPROC glad_glMultiTexCoord4svARB = NULL;
+PFNGLMULTITEXCOORD4XOESPROC glad_glMultiTexCoord4xOES = NULL;
+PFNGLMULTITEXCOORD4XVOESPROC glad_glMultiTexCoord4xvOES = NULL;
+PFNGLNAMEDBUFFERDATAPROC glad_glNamedBufferData = NULL;
+PFNGLNAMEDBUFFERSTORAGEPROC glad_glNamedBufferStorage = NULL;
+PFNGLNAMEDBUFFERSUBDATAPROC glad_glNamedBufferSubData = NULL;
+PFNGLNAMEDFRAMEBUFFERDRAWBUFFERPROC glad_glNamedFramebufferDrawBuffer = NULL;
+PFNGLNAMEDFRAMEBUFFERDRAWBUFFERSPROC glad_glNamedFramebufferDrawBuffers = NULL;
+PFNGLNAMEDFRAMEBUFFERPARAMETERIPROC glad_glNamedFramebufferParameteri = NULL;
+PFNGLNAMEDFRAMEBUFFERREADBUFFERPROC glad_glNamedFramebufferReadBuffer = NULL;
+PFNGLNAMEDFRAMEBUFFERRENDERBUFFERPROC glad_glNamedFramebufferRenderbuffer = NULL;
+PFNGLNAMEDFRAMEBUFFERSAMPLELOCATIONSFVARBPROC glad_glNamedFramebufferSampleLocationsfvARB = NULL;
+PFNGLNAMEDFRAMEBUFFERTEXTUREPROC glad_glNamedFramebufferTexture = NULL;
+PFNGLNAMEDFRAMEBUFFERTEXTURELAYERPROC glad_glNamedFramebufferTextureLayer = NULL;
+PFNGLNAMEDRENDERBUFFERSTORAGEPROC glad_glNamedRenderbufferStorage = NULL;
+PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEPROC glad_glNamedRenderbufferStorageMultisample = NULL;
+PFNGLNAMEDSTRINGARBPROC glad_glNamedStringARB = NULL;
+PFNGLNORMAL3XOESPROC glad_glNormal3xOES = NULL;
+PFNGLNORMAL3XVOESPROC glad_glNormal3xvOES = NULL;
+PFNGLOBJECTLABELPROC glad_glObjectLabel = NULL;
+PFNGLOBJECTPTRLABELPROC glad_glObjectPtrLabel = NULL;
+PFNGLORTHOXOESPROC glad_glOrthoxOES = NULL;
+PFNGLPASSTHROUGHXOESPROC glad_glPassThroughxOES = NULL;
+PFNGLPATCHPARAMETERFVPROC glad_glPatchParameterfv = NULL;
+PFNGLPATCHPARAMETERIPROC glad_glPatchParameteri = NULL;
+PFNGLPAUSETRANSFORMFEEDBACKPROC glad_glPauseTransformFeedback = NULL;
+PFNGLPIXELMAPXPROC glad_glPixelMapx = NULL;
+PFNGLPIXELSTOREFPROC glad_glPixelStoref = NULL;
+PFNGLPIXELSTOREIPROC glad_glPixelStorei = NULL;
+PFNGLPIXELSTOREXPROC glad_glPixelStorex = NULL;
+PFNGLPIXELTRANSFERXOESPROC glad_glPixelTransferxOES = NULL;
+PFNGLPIXELZOOMXOESPROC glad_glPixelZoomxOES = NULL;
+PFNGLPOINTPARAMETERFPROC glad_glPointParameterf = NULL;
+PFNGLPOINTPARAMETERFVPROC glad_glPointParameterfv = NULL;
+PFNGLPOINTPARAMETERIPROC glad_glPointParameteri = NULL;
+PFNGLPOINTPARAMETERIVPROC glad_glPointParameteriv = NULL;
+PFNGLPOINTPARAMETERXVOESPROC glad_glPointParameterxvOES = NULL;
+PFNGLPOINTSIZEPROC glad_glPointSize = NULL;
+PFNGLPOINTSIZEXOESPROC glad_glPointSizexOES = NULL;
+PFNGLPOLYGONMODEPROC glad_glPolygonMode = NULL;
+PFNGLPOLYGONOFFSETPROC glad_glPolygonOffset = NULL;
+PFNGLPOLYGONOFFSETXOESPROC glad_glPolygonOffsetxOES = NULL;
+PFNGLPOPDEBUGGROUPPROC glad_glPopDebugGroup = NULL;
+PFNGLPRIMITIVEBOUNDINGBOXARBPROC glad_glPrimitiveBoundingBoxARB = NULL;
+PFNGLPRIMITIVERESTARTINDEXPROC glad_glPrimitiveRestartIndex = NULL;
+PFNGLPRIORITIZETEXTURESXOESPROC glad_glPrioritizeTexturesxOES = NULL;
+PFNGLPROGRAMBINARYPROC glad_glProgramBinary = NULL;
+PFNGLPROGRAMENVPARAMETER4DARBPROC glad_glProgramEnvParameter4dARB = NULL;
+PFNGLPROGRAMENVPARAMETER4DVARBPROC glad_glProgramEnvParameter4dvARB = NULL;
+PFNGLPROGRAMENVPARAMETER4FARBPROC glad_glProgramEnvParameter4fARB = NULL;
+PFNGLPROGRAMENVPARAMETER4FVARBPROC glad_glProgramEnvParameter4fvARB = NULL;
+PFNGLPROGRAMLOCALPARAMETER4DARBPROC glad_glProgramLocalParameter4dARB = NULL;
+PFNGLPROGRAMLOCALPARAMETER4DVARBPROC glad_glProgramLocalParameter4dvARB = NULL;
+PFNGLPROGRAMLOCALPARAMETER4FARBPROC glad_glProgramLocalParameter4fARB = NULL;
+PFNGLPROGRAMLOCALPARAMETER4FVARBPROC glad_glProgramLocalParameter4fvARB = NULL;
+PFNGLPROGRAMPARAMETERIPROC glad_glProgramParameteri = NULL;
+PFNGLPROGRAMPARAMETERIARBPROC glad_glProgramParameteriARB = NULL;
+PFNGLPROGRAMSTRINGARBPROC glad_glProgramStringARB = NULL;
+PFNGLPROGRAMUNIFORM1DPROC glad_glProgramUniform1d = NULL;
+PFNGLPROGRAMUNIFORM1DVPROC glad_glProgramUniform1dv = NULL;
+PFNGLPROGRAMUNIFORM1FPROC glad_glProgramUniform1f = NULL;
+PFNGLPROGRAMUNIFORM1FVPROC glad_glProgramUniform1fv = NULL;
+PFNGLPROGRAMUNIFORM1IPROC glad_glProgramUniform1i = NULL;
+PFNGLPROGRAMUNIFORM1I64ARBPROC glad_glProgramUniform1i64ARB = NULL;
+PFNGLPROGRAMUNIFORM1I64VARBPROC glad_glProgramUniform1i64vARB = NULL;
+PFNGLPROGRAMUNIFORM1IVPROC glad_glProgramUniform1iv = NULL;
+PFNGLPROGRAMUNIFORM1UIPROC glad_glProgramUniform1ui = NULL;
+PFNGLPROGRAMUNIFORM1UI64ARBPROC glad_glProgramUniform1ui64ARB = NULL;
+PFNGLPROGRAMUNIFORM1UI64VARBPROC glad_glProgramUniform1ui64vARB = NULL;
+PFNGLPROGRAMUNIFORM1UIVPROC glad_glProgramUniform1uiv = NULL;
+PFNGLPROGRAMUNIFORM2DPROC glad_glProgramUniform2d = NULL;
+PFNGLPROGRAMUNIFORM2DVPROC glad_glProgramUniform2dv = NULL;
+PFNGLPROGRAMUNIFORM2FPROC glad_glProgramUniform2f = NULL;
+PFNGLPROGRAMUNIFORM2FVPROC glad_glProgramUniform2fv = NULL;
+PFNGLPROGRAMUNIFORM2IPROC glad_glProgramUniform2i = NULL;
+PFNGLPROGRAMUNIFORM2I64ARBPROC glad_glProgramUniform2i64ARB = NULL;
+PFNGLPROGRAMUNIFORM2I64VARBPROC glad_glProgramUniform2i64vARB = NULL;
+PFNGLPROGRAMUNIFORM2IVPROC glad_glProgramUniform2iv = NULL;
+PFNGLPROGRAMUNIFORM2UIPROC glad_glProgramUniform2ui = NULL;
+PFNGLPROGRAMUNIFORM2UI64ARBPROC glad_glProgramUniform2ui64ARB = NULL;
+PFNGLPROGRAMUNIFORM2UI64VARBPROC glad_glProgramUniform2ui64vARB = NULL;
+PFNGLPROGRAMUNIFORM2UIVPROC glad_glProgramUniform2uiv = NULL;
+PFNGLPROGRAMUNIFORM3DPROC glad_glProgramUniform3d = NULL;
+PFNGLPROGRAMUNIFORM3DVPROC glad_glProgramUniform3dv = NULL;
+PFNGLPROGRAMUNIFORM3FPROC glad_glProgramUniform3f = NULL;
+PFNGLPROGRAMUNIFORM3FVPROC glad_glProgramUniform3fv = NULL;
+PFNGLPROGRAMUNIFORM3IPROC glad_glProgramUniform3i = NULL;
+PFNGLPROGRAMUNIFORM3I64ARBPROC glad_glProgramUniform3i64ARB = NULL;
+PFNGLPROGRAMUNIFORM3I64VARBPROC glad_glProgramUniform3i64vARB = NULL;
+PFNGLPROGRAMUNIFORM3IVPROC glad_glProgramUniform3iv = NULL;
+PFNGLPROGRAMUNIFORM3UIPROC glad_glProgramUniform3ui = NULL;
+PFNGLPROGRAMUNIFORM3UI64ARBPROC glad_glProgramUniform3ui64ARB = NULL;
+PFNGLPROGRAMUNIFORM3UI64VARBPROC glad_glProgramUniform3ui64vARB = NULL;
+PFNGLPROGRAMUNIFORM3UIVPROC glad_glProgramUniform3uiv = NULL;
+PFNGLPROGRAMUNIFORM4DPROC glad_glProgramUniform4d = NULL;
+PFNGLPROGRAMUNIFORM4DVPROC glad_glProgramUniform4dv = NULL;
+PFNGLPROGRAMUNIFORM4FPROC glad_glProgramUniform4f = NULL;
+PFNGLPROGRAMUNIFORM4FVPROC glad_glProgramUniform4fv = NULL;
+PFNGLPROGRAMUNIFORM4IPROC glad_glProgramUniform4i = NULL;
+PFNGLPROGRAMUNIFORM4I64ARBPROC glad_glProgramUniform4i64ARB = NULL;
+PFNGLPROGRAMUNIFORM4I64VARBPROC glad_glProgramUniform4i64vARB = NULL;
+PFNGLPROGRAMUNIFORM4IVPROC glad_glProgramUniform4iv = NULL;
+PFNGLPROGRAMUNIFORM4UIPROC glad_glProgramUniform4ui = NULL;
+PFNGLPROGRAMUNIFORM4UI64ARBPROC glad_glProgramUniform4ui64ARB = NULL;
+PFNGLPROGRAMUNIFORM4UI64VARBPROC glad_glProgramUniform4ui64vARB = NULL;
+PFNGLPROGRAMUNIFORM4UIVPROC glad_glProgramUniform4uiv = NULL;
+PFNGLPROGRAMUNIFORMMATRIX2DVPROC glad_glProgramUniformMatrix2dv = NULL;
+PFNGLPROGRAMUNIFORMMATRIX2FVPROC glad_glProgramUniformMatrix2fv = NULL;
+PFNGLPROGRAMUNIFORMMATRIX2X3DVPROC glad_glProgramUniformMatrix2x3dv = NULL;
+PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC glad_glProgramUniformMatrix2x3fv = NULL;
+PFNGLPROGRAMUNIFORMMATRIX2X4DVPROC glad_glProgramUniformMatrix2x4dv = NULL;
+PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC glad_glProgramUniformMatrix2x4fv = NULL;
+PFNGLPROGRAMUNIFORMMATRIX3DVPROC glad_glProgramUniformMatrix3dv = NULL;
+PFNGLPROGRAMUNIFORMMATRIX3FVPROC glad_glProgramUniformMatrix3fv = NULL;
+PFNGLPROGRAMUNIFORMMATRIX3X2DVPROC glad_glProgramUniformMatrix3x2dv = NULL;
+PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC glad_glProgramUniformMatrix3x2fv = NULL;
+PFNGLPROGRAMUNIFORMMATRIX3X4DVPROC glad_glProgramUniformMatrix3x4dv = NULL;
+PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC glad_glProgramUniformMatrix3x4fv = NULL;
+PFNGLPROGRAMUNIFORMMATRIX4DVPROC glad_glProgramUniformMatrix4dv = NULL;
+PFNGLPROGRAMUNIFORMMATRIX4FVPROC glad_glProgramUniformMatrix4fv = NULL;
+PFNGLPROGRAMUNIFORMMATRIX4X2DVPROC glad_glProgramUniformMatrix4x2dv = NULL;
+PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC glad_glProgramUniformMatrix4x2fv = NULL;
+PFNGLPROGRAMUNIFORMMATRIX4X3DVPROC glad_glProgramUniformMatrix4x3dv = NULL;
+PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC glad_glProgramUniformMatrix4x3fv = NULL;
+PFNGLPROVOKINGVERTEXPROC glad_glProvokingVertex = NULL;
+PFNGLPUSHDEBUGGROUPPROC glad_glPushDebugGroup = NULL;
+PFNGLQUERYCOUNTERPROC glad_glQueryCounter = NULL;
+PFNGLRASTERPOS2XOESPROC glad_glRasterPos2xOES = NULL;
+PFNGLRASTERPOS2XVOESPROC glad_glRasterPos2xvOES = NULL;
+PFNGLRASTERPOS3XOESPROC glad_glRasterPos3xOES = NULL;
+PFNGLRASTERPOS3XVOESPROC glad_glRasterPos3xvOES = NULL;
+PFNGLRASTERPOS4XOESPROC glad_glRasterPos4xOES = NULL;
+PFNGLRASTERPOS4XVOESPROC glad_glRasterPos4xvOES = NULL;
+PFNGLREADBUFFERPROC glad_glReadBuffer = NULL;
+PFNGLREADPIXELSPROC glad_glReadPixels = NULL;
+PFNGLRECTXOESPROC glad_glRectxOES = NULL;
+PFNGLRECTXVOESPROC glad_glRectxvOES = NULL;
+PFNGLRELEASESHADERCOMPILERPROC glad_glReleaseShaderCompiler = NULL;
+PFNGLRENDERBUFFERSTORAGEPROC glad_glRenderbufferStorage = NULL;
+PFNGLRENDERBUFFERSTORAGEEXTPROC glad_glRenderbufferStorageEXT = NULL;
+PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glad_glRenderbufferStorageMultisample = NULL;
+PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glad_glRenderbufferStorageMultisampleEXT = NULL;
+PFNGLRESUMETRANSFORMFEEDBACKPROC glad_glResumeTransformFeedback = NULL;
+PFNGLROTATEXOESPROC glad_glRotatexOES = NULL;
+PFNGLSAMPLECOVERAGEPROC glad_glSampleCoverage = NULL;
+PFNGLSAMPLECOVERAGEARBPROC glad_glSampleCoverageARB = NULL;
+PFNGLSAMPLEMASKIPROC glad_glSampleMaski = NULL;
+PFNGLSAMPLERPARAMETERIIVPROC glad_glSamplerParameterIiv = NULL;
+PFNGLSAMPLERPARAMETERIUIVPROC glad_glSamplerParameterIuiv = NULL;
+PFNGLSAMPLERPARAMETERFPROC glad_glSamplerParameterf = NULL;
+PFNGLSAMPLERPARAMETERFVPROC glad_glSamplerParameterfv = NULL;
+PFNGLSAMPLERPARAMETERIPROC glad_glSamplerParameteri = NULL;
+PFNGLSAMPLERPARAMETERIVPROC glad_glSamplerParameteriv = NULL;
+PFNGLSCALEXOESPROC glad_glScalexOES = NULL;
+PFNGLSCISSORPROC glad_glScissor = NULL;
+PFNGLSCISSORARRAYVPROC glad_glScissorArrayv = NULL;
+PFNGLSCISSORINDEXEDPROC glad_glScissorIndexed = NULL;
+PFNGLSCISSORINDEXEDVPROC glad_glScissorIndexedv = NULL;
+PFNGLSHADERBINARYPROC glad_glShaderBinary = NULL;
+PFNGLSHADERSOURCEPROC glad_glShaderSource = NULL;
+PFNGLSHADERSOURCEARBPROC glad_glShaderSourceARB = NULL;
+PFNGLSHADERSTORAGEBLOCKBINDINGPROC glad_glShaderStorageBlockBinding = NULL;
+PFNGLSPECIALIZESHADERARBPROC glad_glSpecializeShaderARB = NULL;
+PFNGLSTENCILFUNCPROC glad_glStencilFunc = NULL;
+PFNGLSTENCILFUNCSEPARATEPROC glad_glStencilFuncSeparate = NULL;
+PFNGLSTENCILMASKPROC glad_glStencilMask = NULL;
+PFNGLSTENCILMASKSEPARATEPROC glad_glStencilMaskSeparate = NULL;
+PFNGLSTENCILOPPROC glad_glStencilOp = NULL;
+PFNGLSTENCILOPSEPARATEPROC glad_glStencilOpSeparate = NULL;
+PFNGLTEXBUFFERPROC glad_glTexBuffer = NULL;
+PFNGLTEXBUFFERRANGEPROC glad_glTexBufferRange = NULL;
+PFNGLTEXCOORD1XOESPROC glad_glTexCoord1xOES = NULL;
+PFNGLTEXCOORD1XVOESPROC glad_glTexCoord1xvOES = NULL;
+PFNGLTEXCOORD2XOESPROC glad_glTexCoord2xOES = NULL;
+PFNGLTEXCOORD2XVOESPROC glad_glTexCoord2xvOES = NULL;
+PFNGLTEXCOORD3XOESPROC glad_glTexCoord3xOES = NULL;
+PFNGLTEXCOORD3XVOESPROC glad_glTexCoord3xvOES = NULL;
+PFNGLTEXCOORD4XOESPROC glad_glTexCoord4xOES = NULL;
+PFNGLTEXCOORD4XVOESPROC glad_glTexCoord4xvOES = NULL;
+PFNGLTEXENVXOESPROC glad_glTexEnvxOES = NULL;
+PFNGLTEXENVXVOESPROC glad_glTexEnvxvOES = NULL;
+PFNGLTEXGENXOESPROC glad_glTexGenxOES = NULL;
+PFNGLTEXGENXVOESPROC glad_glTexGenxvOES = NULL;
+PFNGLTEXIMAGE1DPROC glad_glTexImage1D = NULL;
+PFNGLTEXIMAGE2DPROC glad_glTexImage2D = NULL;
+PFNGLTEXIMAGE2DMULTISAMPLEPROC glad_glTexImage2DMultisample = NULL;
+PFNGLTEXIMAGE3DPROC glad_glTexImage3D = NULL;
+PFNGLTEXIMAGE3DMULTISAMPLEPROC glad_glTexImage3DMultisample = NULL;
+PFNGLTEXPARAMETERIIVPROC glad_glTexParameterIiv = NULL;
+PFNGLTEXPARAMETERIUIVPROC glad_glTexParameterIuiv = NULL;
+PFNGLTEXPARAMETERFPROC glad_glTexParameterf = NULL;
+PFNGLTEXPARAMETERFVPROC glad_glTexParameterfv = NULL;
+PFNGLTEXPARAMETERIPROC glad_glTexParameteri = NULL;
+PFNGLTEXPARAMETERIVPROC glad_glTexParameteriv = NULL;
+PFNGLTEXPARAMETERXOESPROC glad_glTexParameterxOES = NULL;
+PFNGLTEXPARAMETERXVOESPROC glad_glTexParameterxvOES = NULL;
+PFNGLTEXSTORAGE1DPROC glad_glTexStorage1D = NULL;
+PFNGLTEXSTORAGE2DPROC glad_glTexStorage2D = NULL;
+PFNGLTEXSTORAGE2DMULTISAMPLEPROC glad_glTexStorage2DMultisample = NULL;
+PFNGLTEXSTORAGE3DPROC glad_glTexStorage3D = NULL;
+PFNGLTEXSTORAGE3DMULTISAMPLEPROC glad_glTexStorage3DMultisample = NULL;
+PFNGLTEXSUBIMAGE1DPROC glad_glTexSubImage1D = NULL;
+PFNGLTEXSUBIMAGE2DPROC glad_glTexSubImage2D = NULL;
+PFNGLTEXSUBIMAGE3DPROC glad_glTexSubImage3D = NULL;
+PFNGLTEXTUREBUFFERPROC glad_glTextureBuffer = NULL;
+PFNGLTEXTUREBUFFERRANGEPROC glad_glTextureBufferRange = NULL;
+PFNGLTEXTUREPARAMETERIIVPROC glad_glTextureParameterIiv = NULL;
+PFNGLTEXTUREPARAMETERIUIVPROC glad_glTextureParameterIuiv = NULL;
+PFNGLTEXTUREPARAMETERFPROC glad_glTextureParameterf = NULL;
+PFNGLTEXTUREPARAMETERFVPROC glad_glTextureParameterfv = NULL;
+PFNGLTEXTUREPARAMETERIPROC glad_glTextureParameteri = NULL;
+PFNGLTEXTUREPARAMETERIVPROC glad_glTextureParameteriv = NULL;
+PFNGLTEXTURESTORAGE1DPROC glad_glTextureStorage1D = NULL;
+PFNGLTEXTURESTORAGE2DPROC glad_glTextureStorage2D = NULL;
+PFNGLTEXTURESTORAGE2DMULTISAMPLEPROC glad_glTextureStorage2DMultisample = NULL;
+PFNGLTEXTURESTORAGE3DPROC glad_glTextureStorage3D = NULL;
+PFNGLTEXTURESTORAGE3DMULTISAMPLEPROC glad_glTextureStorage3DMultisample = NULL;
+PFNGLTEXTURESUBIMAGE1DPROC glad_glTextureSubImage1D = NULL;
+PFNGLTEXTURESUBIMAGE2DPROC glad_glTextureSubImage2D = NULL;
+PFNGLTEXTURESUBIMAGE3DPROC glad_glTextureSubImage3D = NULL;
+PFNGLTEXTUREVIEWPROC glad_glTextureView = NULL;
+PFNGLTRANSFORMFEEDBACKBUFFERBASEPROC glad_glTransformFeedbackBufferBase = NULL;
+PFNGLTRANSFORMFEEDBACKBUFFERRANGEPROC glad_glTransformFeedbackBufferRange = NULL;
+PFNGLTRANSFORMFEEDBACKVARYINGSPROC glad_glTransformFeedbackVaryings = NULL;
+PFNGLTRANSLATEXOESPROC glad_glTranslatexOES = NULL;
+PFNGLUNIFORM1DPROC glad_glUniform1d = NULL;
+PFNGLUNIFORM1DVPROC glad_glUniform1dv = NULL;
+PFNGLUNIFORM1FPROC glad_glUniform1f = NULL;
+PFNGLUNIFORM1FARBPROC glad_glUniform1fARB = NULL;
+PFNGLUNIFORM1FVPROC glad_glUniform1fv = NULL;
+PFNGLUNIFORM1FVARBPROC glad_glUniform1fvARB = NULL;
+PFNGLUNIFORM1IPROC glad_glUniform1i = NULL;
+PFNGLUNIFORM1I64ARBPROC glad_glUniform1i64ARB = NULL;
+PFNGLUNIFORM1I64VARBPROC glad_glUniform1i64vARB = NULL;
+PFNGLUNIFORM1IARBPROC glad_glUniform1iARB = NULL;
+PFNGLUNIFORM1IVPROC glad_glUniform1iv = NULL;
+PFNGLUNIFORM1IVARBPROC glad_glUniform1ivARB = NULL;
+PFNGLUNIFORM1UIPROC glad_glUniform1ui = NULL;
+PFNGLUNIFORM1UI64ARBPROC glad_glUniform1ui64ARB = NULL;
+PFNGLUNIFORM1UI64VARBPROC glad_glUniform1ui64vARB = NULL;
+PFNGLUNIFORM1UIVPROC glad_glUniform1uiv = NULL;
+PFNGLUNIFORM2DPROC glad_glUniform2d = NULL;
+PFNGLUNIFORM2DVPROC glad_glUniform2dv = NULL;
+PFNGLUNIFORM2FPROC glad_glUniform2f = NULL;
+PFNGLUNIFORM2FARBPROC glad_glUniform2fARB = NULL;
+PFNGLUNIFORM2FVPROC glad_glUniform2fv = NULL;
+PFNGLUNIFORM2FVARBPROC glad_glUniform2fvARB = NULL;
+PFNGLUNIFORM2IPROC glad_glUniform2i = NULL;
+PFNGLUNIFORM2I64ARBPROC glad_glUniform2i64ARB = NULL;
+PFNGLUNIFORM2I64VARBPROC glad_glUniform2i64vARB = NULL;
+PFNGLUNIFORM2IARBPROC glad_glUniform2iARB = NULL;
+PFNGLUNIFORM2IVPROC glad_glUniform2iv = NULL;
+PFNGLUNIFORM2IVARBPROC glad_glUniform2ivARB = NULL;
+PFNGLUNIFORM2UIPROC glad_glUniform2ui = NULL;
+PFNGLUNIFORM2UI64ARBPROC glad_glUniform2ui64ARB = NULL;
+PFNGLUNIFORM2UI64VARBPROC glad_glUniform2ui64vARB = NULL;
+PFNGLUNIFORM2UIVPROC glad_glUniform2uiv = NULL;
+PFNGLUNIFORM3DPROC glad_glUniform3d = NULL;
+PFNGLUNIFORM3DVPROC glad_glUniform3dv = NULL;
+PFNGLUNIFORM3FPROC glad_glUniform3f = NULL;
+PFNGLUNIFORM3FARBPROC glad_glUniform3fARB = NULL;
+PFNGLUNIFORM3FVPROC glad_glUniform3fv = NULL;
+PFNGLUNIFORM3FVARBPROC glad_glUniform3fvARB = NULL;
+PFNGLUNIFORM3IPROC glad_glUniform3i = NULL;
+PFNGLUNIFORM3I64ARBPROC glad_glUniform3i64ARB = NULL;
+PFNGLUNIFORM3I64VARBPROC glad_glUniform3i64vARB = NULL;
+PFNGLUNIFORM3IARBPROC glad_glUniform3iARB = NULL;
+PFNGLUNIFORM3IVPROC glad_glUniform3iv = NULL;
+PFNGLUNIFORM3IVARBPROC glad_glUniform3ivARB = NULL;
+PFNGLUNIFORM3UIPROC glad_glUniform3ui = NULL;
+PFNGLUNIFORM3UI64ARBPROC glad_glUniform3ui64ARB = NULL;
+PFNGLUNIFORM3UI64VARBPROC glad_glUniform3ui64vARB = NULL;
+PFNGLUNIFORM3UIVPROC glad_glUniform3uiv = NULL;
+PFNGLUNIFORM4DPROC glad_glUniform4d = NULL;
+PFNGLUNIFORM4DVPROC glad_glUniform4dv = NULL;
+PFNGLUNIFORM4FPROC glad_glUniform4f = NULL;
+PFNGLUNIFORM4FARBPROC glad_glUniform4fARB = NULL;
+PFNGLUNIFORM4FVPROC glad_glUniform4fv = NULL;
+PFNGLUNIFORM4FVARBPROC glad_glUniform4fvARB = NULL;
+PFNGLUNIFORM4IPROC glad_glUniform4i = NULL;
+PFNGLUNIFORM4I64ARBPROC glad_glUniform4i64ARB = NULL;
+PFNGLUNIFORM4I64VARBPROC glad_glUniform4i64vARB = NULL;
+PFNGLUNIFORM4IARBPROC glad_glUniform4iARB = NULL;
+PFNGLUNIFORM4IVPROC glad_glUniform4iv = NULL;
+PFNGLUNIFORM4IVARBPROC glad_glUniform4ivARB = NULL;
+PFNGLUNIFORM4UIPROC glad_glUniform4ui = NULL;
+PFNGLUNIFORM4UI64ARBPROC glad_glUniform4ui64ARB = NULL;
+PFNGLUNIFORM4UI64VARBPROC glad_glUniform4ui64vARB = NULL;
+PFNGLUNIFORM4UIVPROC glad_glUniform4uiv = NULL;
+PFNGLUNIFORMBLOCKBINDINGPROC glad_glUniformBlockBinding = NULL;
+PFNGLUNIFORMMATRIX2DVPROC glad_glUniformMatrix2dv = NULL;
+PFNGLUNIFORMMATRIX2FVPROC glad_glUniformMatrix2fv = NULL;
+PFNGLUNIFORMMATRIX2FVARBPROC glad_glUniformMatrix2fvARB = NULL;
+PFNGLUNIFORMMATRIX2X3DVPROC glad_glUniformMatrix2x3dv = NULL;
+PFNGLUNIFORMMATRIX2X3FVPROC glad_glUniformMatrix2x3fv = NULL;
+PFNGLUNIFORMMATRIX2X4DVPROC glad_glUniformMatrix2x4dv = NULL;
+PFNGLUNIFORMMATRIX2X4FVPROC glad_glUniformMatrix2x4fv = NULL;
+PFNGLUNIFORMMATRIX3DVPROC glad_glUniformMatrix3dv = NULL;
+PFNGLUNIFORMMATRIX3FVPROC glad_glUniformMatrix3fv = NULL;
+PFNGLUNIFORMMATRIX3FVARBPROC glad_glUniformMatrix3fvARB = NULL;
+PFNGLUNIFORMMATRIX3X2DVPROC glad_glUniformMatrix3x2dv = NULL;
+PFNGLUNIFORMMATRIX3X2FVPROC glad_glUniformMatrix3x2fv = NULL;
+PFNGLUNIFORMMATRIX3X4DVPROC glad_glUniformMatrix3x4dv = NULL;
+PFNGLUNIFORMMATRIX3X4FVPROC glad_glUniformMatrix3x4fv = NULL;
+PFNGLUNIFORMMATRIX4DVPROC glad_glUniformMatrix4dv = NULL;
+PFNGLUNIFORMMATRIX4FVPROC glad_glUniformMatrix4fv = NULL;
+PFNGLUNIFORMMATRIX4FVARBPROC glad_glUniformMatrix4fvARB = NULL;
+PFNGLUNIFORMMATRIX4X2DVPROC glad_glUniformMatrix4x2dv = NULL;
+PFNGLUNIFORMMATRIX4X2FVPROC glad_glUniformMatrix4x2fv = NULL;
+PFNGLUNIFORMMATRIX4X3DVPROC glad_glUniformMatrix4x3dv = NULL;
+PFNGLUNIFORMMATRIX4X3FVPROC glad_glUniformMatrix4x3fv = NULL;
+PFNGLUNIFORMSUBROUTINESUIVPROC glad_glUniformSubroutinesuiv = NULL;
+PFNGLUNMAPBUFFERPROC glad_glUnmapBuffer = NULL;
+PFNGLUNMAPBUFFERARBPROC glad_glUnmapBufferARB = NULL;
+PFNGLUNMAPNAMEDBUFFERPROC glad_glUnmapNamedBuffer = NULL;
+PFNGLUSEPROGRAMPROC glad_glUseProgram = NULL;
+PFNGLUSEPROGRAMOBJECTARBPROC glad_glUseProgramObjectARB = NULL;
+PFNGLUSEPROGRAMSTAGESPROC glad_glUseProgramStages = NULL;
+PFNGLVALIDATEPROGRAMPROC glad_glValidateProgram = NULL;
+PFNGLVALIDATEPROGRAMARBPROC glad_glValidateProgramARB = NULL;
+PFNGLVALIDATEPROGRAMPIPELINEPROC glad_glValidateProgramPipeline = NULL;
+PFNGLVERTEX2XOESPROC glad_glVertex2xOES = NULL;
+PFNGLVERTEX2XVOESPROC glad_glVertex2xvOES = NULL;
+PFNGLVERTEX3XOESPROC glad_glVertex3xOES = NULL;
+PFNGLVERTEX3XVOESPROC glad_glVertex3xvOES = NULL;
+PFNGLVERTEX4XOESPROC glad_glVertex4xOES = NULL;
+PFNGLVERTEX4XVOESPROC glad_glVertex4xvOES = NULL;
+PFNGLVERTEXARRAYATTRIBBINDINGPROC glad_glVertexArrayAttribBinding = NULL;
+PFNGLVERTEXARRAYATTRIBFORMATPROC glad_glVertexArrayAttribFormat = NULL;
+PFNGLVERTEXARRAYATTRIBIFORMATPROC glad_glVertexArrayAttribIFormat = NULL;
+PFNGLVERTEXARRAYATTRIBLFORMATPROC glad_glVertexArrayAttribLFormat = NULL;
+PFNGLVERTEXARRAYBINDINGDIVISORPROC glad_glVertexArrayBindingDivisor = NULL;
+PFNGLVERTEXARRAYELEMENTBUFFERPROC glad_glVertexArrayElementBuffer = NULL;
+PFNGLVERTEXARRAYVERTEXBUFFERPROC glad_glVertexArrayVertexBuffer = NULL;
+PFNGLVERTEXARRAYVERTEXBUFFERSPROC glad_glVertexArrayVertexBuffers = NULL;
+PFNGLVERTEXATTRIB1DPROC glad_glVertexAttrib1d = NULL;
+PFNGLVERTEXATTRIB1DARBPROC glad_glVertexAttrib1dARB = NULL;
+PFNGLVERTEXATTRIB1DVPROC glad_glVertexAttrib1dv = NULL;
+PFNGLVERTEXATTRIB1DVARBPROC glad_glVertexAttrib1dvARB = NULL;
+PFNGLVERTEXATTRIB1FPROC glad_glVertexAttrib1f = NULL;
+PFNGLVERTEXATTRIB1FARBPROC glad_glVertexAttrib1fARB = NULL;
+PFNGLVERTEXATTRIB1FVPROC glad_glVertexAttrib1fv = NULL;
+PFNGLVERTEXATTRIB1FVARBPROC glad_glVertexAttrib1fvARB = NULL;
+PFNGLVERTEXATTRIB1SPROC glad_glVertexAttrib1s = NULL;
+PFNGLVERTEXATTRIB1SARBPROC glad_glVertexAttrib1sARB = NULL;
+PFNGLVERTEXATTRIB1SVPROC glad_glVertexAttrib1sv = NULL;
+PFNGLVERTEXATTRIB1SVARBPROC glad_glVertexAttrib1svARB = NULL;
+PFNGLVERTEXATTRIB2DPROC glad_glVertexAttrib2d = NULL;
+PFNGLVERTEXATTRIB2DARBPROC glad_glVertexAttrib2dARB = NULL;
+PFNGLVERTEXATTRIB2DVPROC glad_glVertexAttrib2dv = NULL;
+PFNGLVERTEXATTRIB2DVARBPROC glad_glVertexAttrib2dvARB = NULL;
+PFNGLVERTEXATTRIB2FPROC glad_glVertexAttrib2f = NULL;
+PFNGLVERTEXATTRIB2FARBPROC glad_glVertexAttrib2fARB = NULL;
+PFNGLVERTEXATTRIB2FVPROC glad_glVertexAttrib2fv = NULL;
+PFNGLVERTEXATTRIB2FVARBPROC glad_glVertexAttrib2fvARB = NULL;
+PFNGLVERTEXATTRIB2SPROC glad_glVertexAttrib2s = NULL;
+PFNGLVERTEXATTRIB2SARBPROC glad_glVertexAttrib2sARB = NULL;
+PFNGLVERTEXATTRIB2SVPROC glad_glVertexAttrib2sv = NULL;
+PFNGLVERTEXATTRIB2SVARBPROC glad_glVertexAttrib2svARB = NULL;
+PFNGLVERTEXATTRIB3DPROC glad_glVertexAttrib3d = NULL;
+PFNGLVERTEXATTRIB3DARBPROC glad_glVertexAttrib3dARB = NULL;
+PFNGLVERTEXATTRIB3DVPROC glad_glVertexAttrib3dv = NULL;
+PFNGLVERTEXATTRIB3DVARBPROC glad_glVertexAttrib3dvARB = NULL;
+PFNGLVERTEXATTRIB3FPROC glad_glVertexAttrib3f = NULL;
+PFNGLVERTEXATTRIB3FARBPROC glad_glVertexAttrib3fARB = NULL;
+PFNGLVERTEXATTRIB3FVPROC glad_glVertexAttrib3fv = NULL;
+PFNGLVERTEXATTRIB3FVARBPROC glad_glVertexAttrib3fvARB = NULL;
+PFNGLVERTEXATTRIB3SPROC glad_glVertexAttrib3s = NULL;
+PFNGLVERTEXATTRIB3SARBPROC glad_glVertexAttrib3sARB = NULL;
+PFNGLVERTEXATTRIB3SVPROC glad_glVertexAttrib3sv = NULL;
+PFNGLVERTEXATTRIB3SVARBPROC glad_glVertexAttrib3svARB = NULL;
+PFNGLVERTEXATTRIB4NBVPROC glad_glVertexAttrib4Nbv = NULL;
+PFNGLVERTEXATTRIB4NBVARBPROC glad_glVertexAttrib4NbvARB = NULL;
+PFNGLVERTEXATTRIB4NIVPROC glad_glVertexAttrib4Niv = NULL;
+PFNGLVERTEXATTRIB4NIVARBPROC glad_glVertexAttrib4NivARB = NULL;
+PFNGLVERTEXATTRIB4NSVPROC glad_glVertexAttrib4Nsv = NULL;
+PFNGLVERTEXATTRIB4NSVARBPROC glad_glVertexAttrib4NsvARB = NULL;
+PFNGLVERTEXATTRIB4NUBPROC glad_glVertexAttrib4Nub = NULL;
+PFNGLVERTEXATTRIB4NUBARBPROC glad_glVertexAttrib4NubARB = NULL;
+PFNGLVERTEXATTRIB4NUBVPROC glad_glVertexAttrib4Nubv = NULL;
+PFNGLVERTEXATTRIB4NUBVARBPROC glad_glVertexAttrib4NubvARB = NULL;
+PFNGLVERTEXATTRIB4NUIVPROC glad_glVertexAttrib4Nuiv = NULL;
+PFNGLVERTEXATTRIB4NUIVARBPROC glad_glVertexAttrib4NuivARB = NULL;
+PFNGLVERTEXATTRIB4NUSVPROC glad_glVertexAttrib4Nusv = NULL;
+PFNGLVERTEXATTRIB4NUSVARBPROC glad_glVertexAttrib4NusvARB = NULL;
+PFNGLVERTEXATTRIB4BVPROC glad_glVertexAttrib4bv = NULL;
+PFNGLVERTEXATTRIB4BVARBPROC glad_glVertexAttrib4bvARB = NULL;
+PFNGLVERTEXATTRIB4DPROC glad_glVertexAttrib4d = NULL;
+PFNGLVERTEXATTRIB4DARBPROC glad_glVertexAttrib4dARB = NULL;
+PFNGLVERTEXATTRIB4DVPROC glad_glVertexAttrib4dv = NULL;
+PFNGLVERTEXATTRIB4DVARBPROC glad_glVertexAttrib4dvARB = NULL;
+PFNGLVERTEXATTRIB4FPROC glad_glVertexAttrib4f = NULL;
+PFNGLVERTEXATTRIB4FARBPROC glad_glVertexAttrib4fARB = NULL;
+PFNGLVERTEXATTRIB4FVPROC glad_glVertexAttrib4fv = NULL;
+PFNGLVERTEXATTRIB4FVARBPROC glad_glVertexAttrib4fvARB = NULL;
+PFNGLVERTEXATTRIB4IVPROC glad_glVertexAttrib4iv = NULL;
+PFNGLVERTEXATTRIB4IVARBPROC glad_glVertexAttrib4ivARB = NULL;
+PFNGLVERTEXATTRIB4SPROC glad_glVertexAttrib4s = NULL;
+PFNGLVERTEXATTRIB4SARBPROC glad_glVertexAttrib4sARB = NULL;
+PFNGLVERTEXATTRIB4SVPROC glad_glVertexAttrib4sv = NULL;
+PFNGLVERTEXATTRIB4SVARBPROC glad_glVertexAttrib4svARB = NULL;
+PFNGLVERTEXATTRIB4UBVPROC glad_glVertexAttrib4ubv = NULL;
+PFNGLVERTEXATTRIB4UBVARBPROC glad_glVertexAttrib4ubvARB = NULL;
+PFNGLVERTEXATTRIB4UIVPROC glad_glVertexAttrib4uiv = NULL;
+PFNGLVERTEXATTRIB4UIVARBPROC glad_glVertexAttrib4uivARB = NULL;
+PFNGLVERTEXATTRIB4USVPROC glad_glVertexAttrib4usv = NULL;
+PFNGLVERTEXATTRIB4USVARBPROC glad_glVertexAttrib4usvARB = NULL;
+PFNGLVERTEXATTRIBBINDINGPROC glad_glVertexAttribBinding = NULL;
+PFNGLVERTEXATTRIBDIVISORPROC glad_glVertexAttribDivisor = NULL;
+PFNGLVERTEXATTRIBDIVISORARBPROC glad_glVertexAttribDivisorARB = NULL;
+PFNGLVERTEXATTRIBFORMATPROC glad_glVertexAttribFormat = NULL;
+PFNGLVERTEXATTRIBI1IPROC glad_glVertexAttribI1i = NULL;
+PFNGLVERTEXATTRIBI1IVPROC glad_glVertexAttribI1iv = NULL;
+PFNGLVERTEXATTRIBI1UIPROC glad_glVertexAttribI1ui = NULL;
+PFNGLVERTEXATTRIBI1UIVPROC glad_glVertexAttribI1uiv = NULL;
+PFNGLVERTEXATTRIBI2IPROC glad_glVertexAttribI2i = NULL;
+PFNGLVERTEXATTRIBI2IVPROC glad_glVertexAttribI2iv = NULL;
+PFNGLVERTEXATTRIBI2UIPROC glad_glVertexAttribI2ui = NULL;
+PFNGLVERTEXATTRIBI2UIVPROC glad_glVertexAttribI2uiv = NULL;
+PFNGLVERTEXATTRIBI3IPROC glad_glVertexAttribI3i = NULL;
+PFNGLVERTEXATTRIBI3IVPROC glad_glVertexAttribI3iv = NULL;
+PFNGLVERTEXATTRIBI3UIPROC glad_glVertexAttribI3ui = NULL;
+PFNGLVERTEXATTRIBI3UIVPROC glad_glVertexAttribI3uiv = NULL;
+PFNGLVERTEXATTRIBI4BVPROC glad_glVertexAttribI4bv = NULL;
+PFNGLVERTEXATTRIBI4IPROC glad_glVertexAttribI4i = NULL;
+PFNGLVERTEXATTRIBI4IVPROC glad_glVertexAttribI4iv = NULL;
+PFNGLVERTEXATTRIBI4SVPROC glad_glVertexAttribI4sv = NULL;
+PFNGLVERTEXATTRIBI4UBVPROC glad_glVertexAttribI4ubv = NULL;
+PFNGLVERTEXATTRIBI4UIPROC glad_glVertexAttribI4ui = NULL;
+PFNGLVERTEXATTRIBI4UIVPROC glad_glVertexAttribI4uiv = NULL;
+PFNGLVERTEXATTRIBI4USVPROC glad_glVertexAttribI4usv = NULL;
+PFNGLVERTEXATTRIBIFORMATPROC glad_glVertexAttribIFormat = NULL;
+PFNGLVERTEXATTRIBIPOINTERPROC glad_glVertexAttribIPointer = NULL;
+PFNGLVERTEXATTRIBL1DPROC glad_glVertexAttribL1d = NULL;
+PFNGLVERTEXATTRIBL1DVPROC glad_glVertexAttribL1dv = NULL;
+PFNGLVERTEXATTRIBL2DPROC glad_glVertexAttribL2d = NULL;
+PFNGLVERTEXATTRIBL2DVPROC glad_glVertexAttribL2dv = NULL;
+PFNGLVERTEXATTRIBL3DPROC glad_glVertexAttribL3d = NULL;
+PFNGLVERTEXATTRIBL3DVPROC glad_glVertexAttribL3dv = NULL;
+PFNGLVERTEXATTRIBL4DPROC glad_glVertexAttribL4d = NULL;
+PFNGLVERTEXATTRIBL4DVPROC glad_glVertexAttribL4dv = NULL;
+PFNGLVERTEXATTRIBLFORMATPROC glad_glVertexAttribLFormat = NULL;
+PFNGLVERTEXATTRIBLPOINTERPROC glad_glVertexAttribLPointer = NULL;
+PFNGLVERTEXATTRIBP1UIPROC glad_glVertexAttribP1ui = NULL;
+PFNGLVERTEXATTRIBP1UIVPROC glad_glVertexAttribP1uiv = NULL;
+PFNGLVERTEXATTRIBP2UIPROC glad_glVertexAttribP2ui = NULL;
+PFNGLVERTEXATTRIBP2UIVPROC glad_glVertexAttribP2uiv = NULL;
+PFNGLVERTEXATTRIBP3UIPROC glad_glVertexAttribP3ui = NULL;
+PFNGLVERTEXATTRIBP3UIVPROC glad_glVertexAttribP3uiv = NULL;
+PFNGLVERTEXATTRIBP4UIPROC glad_glVertexAttribP4ui = NULL;
+PFNGLVERTEXATTRIBP4UIVPROC glad_glVertexAttribP4uiv = NULL;
+PFNGLVERTEXATTRIBPOINTERPROC glad_glVertexAttribPointer = NULL;
+PFNGLVERTEXATTRIBPOINTERARBPROC glad_glVertexAttribPointerARB = NULL;
+PFNGLVERTEXBINDINGDIVISORPROC glad_glVertexBindingDivisor = NULL;
+PFNGLVIEWPORTPROC glad_glViewport = NULL;
+PFNGLVIEWPORTARRAYVPROC glad_glViewportArrayv = NULL;
+PFNGLVIEWPORTINDEXEDFPROC glad_glViewportIndexedf = NULL;
+PFNGLVIEWPORTINDEXEDFVPROC glad_glViewportIndexedfv = NULL;
+PFNGLWAITSYNCPROC glad_glWaitSync = NULL;
+
+
+static void glad_gl_load_GL_VERSION_1_0( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_VERSION_1_0) return;
+ glad_glBlendFunc = (PFNGLBLENDFUNCPROC) load(userptr, "glBlendFunc");
+ glad_glClear = (PFNGLCLEARPROC) load(userptr, "glClear");
+ glad_glClearColor = (PFNGLCLEARCOLORPROC) load(userptr, "glClearColor");
+ glad_glClearDepth = (PFNGLCLEARDEPTHPROC) load(userptr, "glClearDepth");
+ glad_glClearStencil = (PFNGLCLEARSTENCILPROC) load(userptr, "glClearStencil");
+ glad_glColorMask = (PFNGLCOLORMASKPROC) load(userptr, "glColorMask");
+ glad_glCullFace = (PFNGLCULLFACEPROC) load(userptr, "glCullFace");
+ glad_glDepthFunc = (PFNGLDEPTHFUNCPROC) load(userptr, "glDepthFunc");
+ glad_glDepthMask = (PFNGLDEPTHMASKPROC) load(userptr, "glDepthMask");
+ glad_glDepthRange = (PFNGLDEPTHRANGEPROC) load(userptr, "glDepthRange");
+ glad_glDisable = (PFNGLDISABLEPROC) load(userptr, "glDisable");
+ glad_glDrawBuffer = (PFNGLDRAWBUFFERPROC) load(userptr, "glDrawBuffer");
+ glad_glEnable = (PFNGLENABLEPROC) load(userptr, "glEnable");
+ glad_glFinish = (PFNGLFINISHPROC) load(userptr, "glFinish");
+ glad_glFlush = (PFNGLFLUSHPROC) load(userptr, "glFlush");
+ glad_glFrontFace = (PFNGLFRONTFACEPROC) load(userptr, "glFrontFace");
+ glad_glGetBooleanv = (PFNGLGETBOOLEANVPROC) load(userptr, "glGetBooleanv");
+ glad_glGetDoublev = (PFNGLGETDOUBLEVPROC) load(userptr, "glGetDoublev");
+ glad_glGetError = (PFNGLGETERRORPROC) load(userptr, "glGetError");
+ glad_glGetFloatv = (PFNGLGETFLOATVPROC) load(userptr, "glGetFloatv");
+ glad_glGetIntegerv = (PFNGLGETINTEGERVPROC) load(userptr, "glGetIntegerv");
+ glad_glGetString = (PFNGLGETSTRINGPROC) load(userptr, "glGetString");
+ glad_glGetTexImage = (PFNGLGETTEXIMAGEPROC) load(userptr, "glGetTexImage");
+ glad_glGetTexLevelParameterfv = (PFNGLGETTEXLEVELPARAMETERFVPROC) load(userptr, "glGetTexLevelParameterfv");
+ glad_glGetTexLevelParameteriv = (PFNGLGETTEXLEVELPARAMETERIVPROC) load(userptr, "glGetTexLevelParameteriv");
+ glad_glGetTexParameterfv = (PFNGLGETTEXPARAMETERFVPROC) load(userptr, "glGetTexParameterfv");
+ glad_glGetTexParameteriv = (PFNGLGETTEXPARAMETERIVPROC) load(userptr, "glGetTexParameteriv");
+ glad_glHint = (PFNGLHINTPROC) load(userptr, "glHint");
+ glad_glIsEnabled = (PFNGLISENABLEDPROC) load(userptr, "glIsEnabled");
+ glad_glLineWidth = (PFNGLLINEWIDTHPROC) load(userptr, "glLineWidth");
+ glad_glLogicOp = (PFNGLLOGICOPPROC) load(userptr, "glLogicOp");
+ glad_glPixelStoref = (PFNGLPIXELSTOREFPROC) load(userptr, "glPixelStoref");
+ glad_glPixelStorei = (PFNGLPIXELSTOREIPROC) load(userptr, "glPixelStorei");
+ glad_glPointSize = (PFNGLPOINTSIZEPROC) load(userptr, "glPointSize");
+ glad_glPolygonMode = (PFNGLPOLYGONMODEPROC) load(userptr, "glPolygonMode");
+ glad_glReadBuffer = (PFNGLREADBUFFERPROC) load(userptr, "glReadBuffer");
+ glad_glReadPixels = (PFNGLREADPIXELSPROC) load(userptr, "glReadPixels");
+ glad_glScissor = (PFNGLSCISSORPROC) load(userptr, "glScissor");
+ glad_glStencilFunc = (PFNGLSTENCILFUNCPROC) load(userptr, "glStencilFunc");
+ glad_glStencilMask = (PFNGLSTENCILMASKPROC) load(userptr, "glStencilMask");
+ glad_glStencilOp = (PFNGLSTENCILOPPROC) load(userptr, "glStencilOp");
+ glad_glTexImage1D = (PFNGLTEXIMAGE1DPROC) load(userptr, "glTexImage1D");
+ glad_glTexImage2D = (PFNGLTEXIMAGE2DPROC) load(userptr, "glTexImage2D");
+ glad_glTexParameterf = (PFNGLTEXPARAMETERFPROC) load(userptr, "glTexParameterf");
+ glad_glTexParameterfv = (PFNGLTEXPARAMETERFVPROC) load(userptr, "glTexParameterfv");
+ glad_glTexParameteri = (PFNGLTEXPARAMETERIPROC) load(userptr, "glTexParameteri");
+ glad_glTexParameteriv = (PFNGLTEXPARAMETERIVPROC) load(userptr, "glTexParameteriv");
+ glad_glViewport = (PFNGLVIEWPORTPROC) load(userptr, "glViewport");
+}
+static void glad_gl_load_GL_VERSION_1_1( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_VERSION_1_1) return;
+ glad_glBindTexture = (PFNGLBINDTEXTUREPROC) load(userptr, "glBindTexture");
+ glad_glCopyTexImage1D = (PFNGLCOPYTEXIMAGE1DPROC) load(userptr, "glCopyTexImage1D");
+ glad_glCopyTexImage2D = (PFNGLCOPYTEXIMAGE2DPROC) load(userptr, "glCopyTexImage2D");
+ glad_glCopyTexSubImage1D = (PFNGLCOPYTEXSUBIMAGE1DPROC) load(userptr, "glCopyTexSubImage1D");
+ glad_glCopyTexSubImage2D = (PFNGLCOPYTEXSUBIMAGE2DPROC) load(userptr, "glCopyTexSubImage2D");
+ glad_glDeleteTextures = (PFNGLDELETETEXTURESPROC) load(userptr, "glDeleteTextures");
+ glad_glDrawArrays = (PFNGLDRAWARRAYSPROC) load(userptr, "glDrawArrays");
+ glad_glDrawElements = (PFNGLDRAWELEMENTSPROC) load(userptr, "glDrawElements");
+ glad_glGenTextures = (PFNGLGENTEXTURESPROC) load(userptr, "glGenTextures");
+ glad_glGetPointerv = (PFNGLGETPOINTERVPROC) load(userptr, "glGetPointerv");
+ glad_glIsTexture = (PFNGLISTEXTUREPROC) load(userptr, "glIsTexture");
+ glad_glPolygonOffset = (PFNGLPOLYGONOFFSETPROC) load(userptr, "glPolygonOffset");
+ glad_glTexSubImage1D = (PFNGLTEXSUBIMAGE1DPROC) load(userptr, "glTexSubImage1D");
+ glad_glTexSubImage2D = (PFNGLTEXSUBIMAGE2DPROC) load(userptr, "glTexSubImage2D");
+}
+static void glad_gl_load_GL_VERSION_1_2( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_VERSION_1_2) return;
+ glad_glCopyTexSubImage3D = (PFNGLCOPYTEXSUBIMAGE3DPROC) load(userptr, "glCopyTexSubImage3D");
+ glad_glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC) load(userptr, "glDrawRangeElements");
+ glad_glTexImage3D = (PFNGLTEXIMAGE3DPROC) load(userptr, "glTexImage3D");
+ glad_glTexSubImage3D = (PFNGLTEXSUBIMAGE3DPROC) load(userptr, "glTexSubImage3D");
+}
+static void glad_gl_load_GL_VERSION_1_3( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_VERSION_1_3) return;
+ glad_glActiveTexture = (PFNGLACTIVETEXTUREPROC) load(userptr, "glActiveTexture");
+ glad_glCompressedTexImage1D = (PFNGLCOMPRESSEDTEXIMAGE1DPROC) load(userptr, "glCompressedTexImage1D");
+ glad_glCompressedTexImage2D = (PFNGLCOMPRESSEDTEXIMAGE2DPROC) load(userptr, "glCompressedTexImage2D");
+ glad_glCompressedTexImage3D = (PFNGLCOMPRESSEDTEXIMAGE3DPROC) load(userptr, "glCompressedTexImage3D");
+ glad_glCompressedTexSubImage1D = (PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC) load(userptr, "glCompressedTexSubImage1D");
+ glad_glCompressedTexSubImage2D = (PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) load(userptr, "glCompressedTexSubImage2D");
+ glad_glCompressedTexSubImage3D = (PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) load(userptr, "glCompressedTexSubImage3D");
+ glad_glGetCompressedTexImage = (PFNGLGETCOMPRESSEDTEXIMAGEPROC) load(userptr, "glGetCompressedTexImage");
+ glad_glSampleCoverage = (PFNGLSAMPLECOVERAGEPROC) load(userptr, "glSampleCoverage");
+}
+static void glad_gl_load_GL_VERSION_1_4( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_VERSION_1_4) return;
+ glad_glBlendColor = (PFNGLBLENDCOLORPROC) load(userptr, "glBlendColor");
+ glad_glBlendEquation = (PFNGLBLENDEQUATIONPROC) load(userptr, "glBlendEquation");
+ glad_glBlendFuncSeparate = (PFNGLBLENDFUNCSEPARATEPROC) load(userptr, "glBlendFuncSeparate");
+ glad_glMultiDrawArrays = (PFNGLMULTIDRAWARRAYSPROC) load(userptr, "glMultiDrawArrays");
+ glad_glMultiDrawElements = (PFNGLMULTIDRAWELEMENTSPROC) load(userptr, "glMultiDrawElements");
+ glad_glPointParameterf = (PFNGLPOINTPARAMETERFPROC) load(userptr, "glPointParameterf");
+ glad_glPointParameterfv = (PFNGLPOINTPARAMETERFVPROC) load(userptr, "glPointParameterfv");
+ glad_glPointParameteri = (PFNGLPOINTPARAMETERIPROC) load(userptr, "glPointParameteri");
+ glad_glPointParameteriv = (PFNGLPOINTPARAMETERIVPROC) load(userptr, "glPointParameteriv");
+}
+static void glad_gl_load_GL_VERSION_1_5( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_VERSION_1_5) return;
+ glad_glBeginQuery = (PFNGLBEGINQUERYPROC) load(userptr, "glBeginQuery");
+ glad_glBindBuffer = (PFNGLBINDBUFFERPROC) load(userptr, "glBindBuffer");
+ glad_glBufferData = (PFNGLBUFFERDATAPROC) load(userptr, "glBufferData");
+ glad_glBufferSubData = (PFNGLBUFFERSUBDATAPROC) load(userptr, "glBufferSubData");
+ glad_glDeleteBuffers = (PFNGLDELETEBUFFERSPROC) load(userptr, "glDeleteBuffers");
+ glad_glDeleteQueries = (PFNGLDELETEQUERIESPROC) load(userptr, "glDeleteQueries");
+ glad_glEndQuery = (PFNGLENDQUERYPROC) load(userptr, "glEndQuery");
+ glad_glGenBuffers = (PFNGLGENBUFFERSPROC) load(userptr, "glGenBuffers");
+ glad_glGenQueries = (PFNGLGENQUERIESPROC) load(userptr, "glGenQueries");
+ glad_glGetBufferParameteriv = (PFNGLGETBUFFERPARAMETERIVPROC) load(userptr, "glGetBufferParameteriv");
+ glad_glGetBufferPointerv = (PFNGLGETBUFFERPOINTERVPROC) load(userptr, "glGetBufferPointerv");
+ glad_glGetBufferSubData = (PFNGLGETBUFFERSUBDATAPROC) load(userptr, "glGetBufferSubData");
+ glad_glGetQueryObjectiv = (PFNGLGETQUERYOBJECTIVPROC) load(userptr, "glGetQueryObjectiv");
+ glad_glGetQueryObjectuiv = (PFNGLGETQUERYOBJECTUIVPROC) load(userptr, "glGetQueryObjectuiv");
+ glad_glGetQueryiv = (PFNGLGETQUERYIVPROC) load(userptr, "glGetQueryiv");
+ glad_glIsBuffer = (PFNGLISBUFFERPROC) load(userptr, "glIsBuffer");
+ glad_glIsQuery = (PFNGLISQUERYPROC) load(userptr, "glIsQuery");
+ glad_glMapBuffer = (PFNGLMAPBUFFERPROC) load(userptr, "glMapBuffer");
+ glad_glUnmapBuffer = (PFNGLUNMAPBUFFERPROC) load(userptr, "glUnmapBuffer");
+}
+static void glad_gl_load_GL_VERSION_2_0( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_VERSION_2_0) return;
+ glad_glAttachShader = (PFNGLATTACHSHADERPROC) load(userptr, "glAttachShader");
+ glad_glBindAttribLocation = (PFNGLBINDATTRIBLOCATIONPROC) load(userptr, "glBindAttribLocation");
+ glad_glBlendEquationSeparate = (PFNGLBLENDEQUATIONSEPARATEPROC) load(userptr, "glBlendEquationSeparate");
+ glad_glCompileShader = (PFNGLCOMPILESHADERPROC) load(userptr, "glCompileShader");
+ glad_glCreateProgram = (PFNGLCREATEPROGRAMPROC) load(userptr, "glCreateProgram");
+ glad_glCreateShader = (PFNGLCREATESHADERPROC) load(userptr, "glCreateShader");
+ glad_glDeleteProgram = (PFNGLDELETEPROGRAMPROC) load(userptr, "glDeleteProgram");
+ glad_glDeleteShader = (PFNGLDELETESHADERPROC) load(userptr, "glDeleteShader");
+ glad_glDetachShader = (PFNGLDETACHSHADERPROC) load(userptr, "glDetachShader");
+ glad_glDisableVertexAttribArray = (PFNGLDISABLEVERTEXATTRIBARRAYPROC) load(userptr, "glDisableVertexAttribArray");
+ glad_glDrawBuffers = (PFNGLDRAWBUFFERSPROC) load(userptr, "glDrawBuffers");
+ glad_glEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC) load(userptr, "glEnableVertexAttribArray");
+ glad_glGetActiveAttrib = (PFNGLGETACTIVEATTRIBPROC) load(userptr, "glGetActiveAttrib");
+ glad_glGetActiveUniform = (PFNGLGETACTIVEUNIFORMPROC) load(userptr, "glGetActiveUniform");
+ glad_glGetAttachedShaders = (PFNGLGETATTACHEDSHADERSPROC) load(userptr, "glGetAttachedShaders");
+ glad_glGetAttribLocation = (PFNGLGETATTRIBLOCATIONPROC) load(userptr, "glGetAttribLocation");
+ glad_glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC) load(userptr, "glGetProgramInfoLog");
+ glad_glGetProgramiv = (PFNGLGETPROGRAMIVPROC) load(userptr, "glGetProgramiv");
+ glad_glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC) load(userptr, "glGetShaderInfoLog");
+ glad_glGetShaderSource = (PFNGLGETSHADERSOURCEPROC) load(userptr, "glGetShaderSource");
+ glad_glGetShaderiv = (PFNGLGETSHADERIVPROC) load(userptr, "glGetShaderiv");
+ glad_glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC) load(userptr, "glGetUniformLocation");
+ glad_glGetUniformfv = (PFNGLGETUNIFORMFVPROC) load(userptr, "glGetUniformfv");
+ glad_glGetUniformiv = (PFNGLGETUNIFORMIVPROC) load(userptr, "glGetUniformiv");
+ glad_glGetVertexAttribPointerv = (PFNGLGETVERTEXATTRIBPOINTERVPROC) load(userptr, "glGetVertexAttribPointerv");
+ glad_glGetVertexAttribdv = (PFNGLGETVERTEXATTRIBDVPROC) load(userptr, "glGetVertexAttribdv");
+ glad_glGetVertexAttribfv = (PFNGLGETVERTEXATTRIBFVPROC) load(userptr, "glGetVertexAttribfv");
+ glad_glGetVertexAttribiv = (PFNGLGETVERTEXATTRIBIVPROC) load(userptr, "glGetVertexAttribiv");
+ glad_glIsProgram = (PFNGLISPROGRAMPROC) load(userptr, "glIsProgram");
+ glad_glIsShader = (PFNGLISSHADERPROC) load(userptr, "glIsShader");
+ glad_glLinkProgram = (PFNGLLINKPROGRAMPROC) load(userptr, "glLinkProgram");
+ glad_glShaderSource = (PFNGLSHADERSOURCEPROC) load(userptr, "glShaderSource");
+ glad_glStencilFuncSeparate = (PFNGLSTENCILFUNCSEPARATEPROC) load(userptr, "glStencilFuncSeparate");
+ glad_glStencilMaskSeparate = (PFNGLSTENCILMASKSEPARATEPROC) load(userptr, "glStencilMaskSeparate");
+ glad_glStencilOpSeparate = (PFNGLSTENCILOPSEPARATEPROC) load(userptr, "glStencilOpSeparate");
+ glad_glUniform1f = (PFNGLUNIFORM1FPROC) load(userptr, "glUniform1f");
+ glad_glUniform1fv = (PFNGLUNIFORM1FVPROC) load(userptr, "glUniform1fv");
+ glad_glUniform1i = (PFNGLUNIFORM1IPROC) load(userptr, "glUniform1i");
+ glad_glUniform1iv = (PFNGLUNIFORM1IVPROC) load(userptr, "glUniform1iv");
+ glad_glUniform2f = (PFNGLUNIFORM2FPROC) load(userptr, "glUniform2f");
+ glad_glUniform2fv = (PFNGLUNIFORM2FVPROC) load(userptr, "glUniform2fv");
+ glad_glUniform2i = (PFNGLUNIFORM2IPROC) load(userptr, "glUniform2i");
+ glad_glUniform2iv = (PFNGLUNIFORM2IVPROC) load(userptr, "glUniform2iv");
+ glad_glUniform3f = (PFNGLUNIFORM3FPROC) load(userptr, "glUniform3f");
+ glad_glUniform3fv = (PFNGLUNIFORM3FVPROC) load(userptr, "glUniform3fv");
+ glad_glUniform3i = (PFNGLUNIFORM3IPROC) load(userptr, "glUniform3i");
+ glad_glUniform3iv = (PFNGLUNIFORM3IVPROC) load(userptr, "glUniform3iv");
+ glad_glUniform4f = (PFNGLUNIFORM4FPROC) load(userptr, "glUniform4f");
+ glad_glUniform4fv = (PFNGLUNIFORM4FVPROC) load(userptr, "glUniform4fv");
+ glad_glUniform4i = (PFNGLUNIFORM4IPROC) load(userptr, "glUniform4i");
+ glad_glUniform4iv = (PFNGLUNIFORM4IVPROC) load(userptr, "glUniform4iv");
+ glad_glUniformMatrix2fv = (PFNGLUNIFORMMATRIX2FVPROC) load(userptr, "glUniformMatrix2fv");
+ glad_glUniformMatrix3fv = (PFNGLUNIFORMMATRIX3FVPROC) load(userptr, "glUniformMatrix3fv");
+ glad_glUniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVPROC) load(userptr, "glUniformMatrix4fv");
+ glad_glUseProgram = (PFNGLUSEPROGRAMPROC) load(userptr, "glUseProgram");
+ glad_glValidateProgram = (PFNGLVALIDATEPROGRAMPROC) load(userptr, "glValidateProgram");
+ glad_glVertexAttrib1d = (PFNGLVERTEXATTRIB1DPROC) load(userptr, "glVertexAttrib1d");
+ glad_glVertexAttrib1dv = (PFNGLVERTEXATTRIB1DVPROC) load(userptr, "glVertexAttrib1dv");
+ glad_glVertexAttrib1f = (PFNGLVERTEXATTRIB1FPROC) load(userptr, "glVertexAttrib1f");
+ glad_glVertexAttrib1fv = (PFNGLVERTEXATTRIB1FVPROC) load(userptr, "glVertexAttrib1fv");
+ glad_glVertexAttrib1s = (PFNGLVERTEXATTRIB1SPROC) load(userptr, "glVertexAttrib1s");
+ glad_glVertexAttrib1sv = (PFNGLVERTEXATTRIB1SVPROC) load(userptr, "glVertexAttrib1sv");
+ glad_glVertexAttrib2d = (PFNGLVERTEXATTRIB2DPROC) load(userptr, "glVertexAttrib2d");
+ glad_glVertexAttrib2dv = (PFNGLVERTEXATTRIB2DVPROC) load(userptr, "glVertexAttrib2dv");
+ glad_glVertexAttrib2f = (PFNGLVERTEXATTRIB2FPROC) load(userptr, "glVertexAttrib2f");
+ glad_glVertexAttrib2fv = (PFNGLVERTEXATTRIB2FVPROC) load(userptr, "glVertexAttrib2fv");
+ glad_glVertexAttrib2s = (PFNGLVERTEXATTRIB2SPROC) load(userptr, "glVertexAttrib2s");
+ glad_glVertexAttrib2sv = (PFNGLVERTEXATTRIB2SVPROC) load(userptr, "glVertexAttrib2sv");
+ glad_glVertexAttrib3d = (PFNGLVERTEXATTRIB3DPROC) load(userptr, "glVertexAttrib3d");
+ glad_glVertexAttrib3dv = (PFNGLVERTEXATTRIB3DVPROC) load(userptr, "glVertexAttrib3dv");
+ glad_glVertexAttrib3f = (PFNGLVERTEXATTRIB3FPROC) load(userptr, "glVertexAttrib3f");
+ glad_glVertexAttrib3fv = (PFNGLVERTEXATTRIB3FVPROC) load(userptr, "glVertexAttrib3fv");
+ glad_glVertexAttrib3s = (PFNGLVERTEXATTRIB3SPROC) load(userptr, "glVertexAttrib3s");
+ glad_glVertexAttrib3sv = (PFNGLVERTEXATTRIB3SVPROC) load(userptr, "glVertexAttrib3sv");
+ glad_glVertexAttrib4Nbv = (PFNGLVERTEXATTRIB4NBVPROC) load(userptr, "glVertexAttrib4Nbv");
+ glad_glVertexAttrib4Niv = (PFNGLVERTEXATTRIB4NIVPROC) load(userptr, "glVertexAttrib4Niv");
+ glad_glVertexAttrib4Nsv = (PFNGLVERTEXATTRIB4NSVPROC) load(userptr, "glVertexAttrib4Nsv");
+ glad_glVertexAttrib4Nub = (PFNGLVERTEXATTRIB4NUBPROC) load(userptr, "glVertexAttrib4Nub");
+ glad_glVertexAttrib4Nubv = (PFNGLVERTEXATTRIB4NUBVPROC) load(userptr, "glVertexAttrib4Nubv");
+ glad_glVertexAttrib4Nuiv = (PFNGLVERTEXATTRIB4NUIVPROC) load(userptr, "glVertexAttrib4Nuiv");
+ glad_glVertexAttrib4Nusv = (PFNGLVERTEXATTRIB4NUSVPROC) load(userptr, "glVertexAttrib4Nusv");
+ glad_glVertexAttrib4bv = (PFNGLVERTEXATTRIB4BVPROC) load(userptr, "glVertexAttrib4bv");
+ glad_glVertexAttrib4d = (PFNGLVERTEXATTRIB4DPROC) load(userptr, "glVertexAttrib4d");
+ glad_glVertexAttrib4dv = (PFNGLVERTEXATTRIB4DVPROC) load(userptr, "glVertexAttrib4dv");
+ glad_glVertexAttrib4f = (PFNGLVERTEXATTRIB4FPROC) load(userptr, "glVertexAttrib4f");
+ glad_glVertexAttrib4fv = (PFNGLVERTEXATTRIB4FVPROC) load(userptr, "glVertexAttrib4fv");
+ glad_glVertexAttrib4iv = (PFNGLVERTEXATTRIB4IVPROC) load(userptr, "glVertexAttrib4iv");
+ glad_glVertexAttrib4s = (PFNGLVERTEXATTRIB4SPROC) load(userptr, "glVertexAttrib4s");
+ glad_glVertexAttrib4sv = (PFNGLVERTEXATTRIB4SVPROC) load(userptr, "glVertexAttrib4sv");
+ glad_glVertexAttrib4ubv = (PFNGLVERTEXATTRIB4UBVPROC) load(userptr, "glVertexAttrib4ubv");
+ glad_glVertexAttrib4uiv = (PFNGLVERTEXATTRIB4UIVPROC) load(userptr, "glVertexAttrib4uiv");
+ glad_glVertexAttrib4usv = (PFNGLVERTEXATTRIB4USVPROC) load(userptr, "glVertexAttrib4usv");
+ glad_glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC) load(userptr, "glVertexAttribPointer");
+}
+static void glad_gl_load_GL_VERSION_2_1( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_VERSION_2_1) return;
+ glad_glUniformMatrix2x3fv = (PFNGLUNIFORMMATRIX2X3FVPROC) load(userptr, "glUniformMatrix2x3fv");
+ glad_glUniformMatrix2x4fv = (PFNGLUNIFORMMATRIX2X4FVPROC) load(userptr, "glUniformMatrix2x4fv");
+ glad_glUniformMatrix3x2fv = (PFNGLUNIFORMMATRIX3X2FVPROC) load(userptr, "glUniformMatrix3x2fv");
+ glad_glUniformMatrix3x4fv = (PFNGLUNIFORMMATRIX3X4FVPROC) load(userptr, "glUniformMatrix3x4fv");
+ glad_glUniformMatrix4x2fv = (PFNGLUNIFORMMATRIX4X2FVPROC) load(userptr, "glUniformMatrix4x2fv");
+ glad_glUniformMatrix4x3fv = (PFNGLUNIFORMMATRIX4X3FVPROC) load(userptr, "glUniformMatrix4x3fv");
+}
+static void glad_gl_load_GL_VERSION_3_0( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_VERSION_3_0) return;
+ glad_glBeginConditionalRender = (PFNGLBEGINCONDITIONALRENDERPROC) load(userptr, "glBeginConditionalRender");
+ glad_glBeginTransformFeedback = (PFNGLBEGINTRANSFORMFEEDBACKPROC) load(userptr, "glBeginTransformFeedback");
+ glad_glBindBufferBase = (PFNGLBINDBUFFERBASEPROC) load(userptr, "glBindBufferBase");
+ glad_glBindBufferRange = (PFNGLBINDBUFFERRANGEPROC) load(userptr, "glBindBufferRange");
+ glad_glBindFragDataLocation = (PFNGLBINDFRAGDATALOCATIONPROC) load(userptr, "glBindFragDataLocation");
+ glad_glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC) load(userptr, "glBindFramebuffer");
+ glad_glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC) load(userptr, "glBindRenderbuffer");
+ glad_glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC) load(userptr, "glBindVertexArray");
+ glad_glBlitFramebuffer = (PFNGLBLITFRAMEBUFFERPROC) load(userptr, "glBlitFramebuffer");
+ glad_glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC) load(userptr, "glCheckFramebufferStatus");
+ glad_glClampColor = (PFNGLCLAMPCOLORPROC) load(userptr, "glClampColor");
+ glad_glClearBufferfi = (PFNGLCLEARBUFFERFIPROC) load(userptr, "glClearBufferfi");
+ glad_glClearBufferfv = (PFNGLCLEARBUFFERFVPROC) load(userptr, "glClearBufferfv");
+ glad_glClearBufferiv = (PFNGLCLEARBUFFERIVPROC) load(userptr, "glClearBufferiv");
+ glad_glClearBufferuiv = (PFNGLCLEARBUFFERUIVPROC) load(userptr, "glClearBufferuiv");
+ glad_glColorMaski = (PFNGLCOLORMASKIPROC) load(userptr, "glColorMaski");
+ glad_glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC) load(userptr, "glDeleteFramebuffers");
+ glad_glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC) load(userptr, "glDeleteRenderbuffers");
+ glad_glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSPROC) load(userptr, "glDeleteVertexArrays");
+ glad_glDisablei = (PFNGLDISABLEIPROC) load(userptr, "glDisablei");
+ glad_glEnablei = (PFNGLENABLEIPROC) load(userptr, "glEnablei");
+ glad_glEndConditionalRender = (PFNGLENDCONDITIONALRENDERPROC) load(userptr, "glEndConditionalRender");
+ glad_glEndTransformFeedback = (PFNGLENDTRANSFORMFEEDBACKPROC) load(userptr, "glEndTransformFeedback");
+ glad_glFlushMappedBufferRange = (PFNGLFLUSHMAPPEDBUFFERRANGEPROC) load(userptr, "glFlushMappedBufferRange");
+ glad_glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC) load(userptr, "glFramebufferRenderbuffer");
+ glad_glFramebufferTexture1D = (PFNGLFRAMEBUFFERTEXTURE1DPROC) load(userptr, "glFramebufferTexture1D");
+ glad_glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC) load(userptr, "glFramebufferTexture2D");
+ glad_glFramebufferTexture3D = (PFNGLFRAMEBUFFERTEXTURE3DPROC) load(userptr, "glFramebufferTexture3D");
+ glad_glFramebufferTextureLayer = (PFNGLFRAMEBUFFERTEXTURELAYERPROC) load(userptr, "glFramebufferTextureLayer");
+ glad_glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC) load(userptr, "glGenFramebuffers");
+ glad_glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC) load(userptr, "glGenRenderbuffers");
+ glad_glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC) load(userptr, "glGenVertexArrays");
+ glad_glGenerateMipmap = (PFNGLGENERATEMIPMAPPROC) load(userptr, "glGenerateMipmap");
+ glad_glGetBooleani_v = (PFNGLGETBOOLEANI_VPROC) load(userptr, "glGetBooleani_v");
+ glad_glGetFragDataLocation = (PFNGLGETFRAGDATALOCATIONPROC) load(userptr, "glGetFragDataLocation");
+ glad_glGetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) load(userptr, "glGetFramebufferAttachmentParameteriv");
+ glad_glGetIntegeri_v = (PFNGLGETINTEGERI_VPROC) load(userptr, "glGetIntegeri_v");
+ glad_glGetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIVPROC) load(userptr, "glGetRenderbufferParameteriv");
+ glad_glGetStringi = (PFNGLGETSTRINGIPROC) load(userptr, "glGetStringi");
+ glad_glGetTexParameterIiv = (PFNGLGETTEXPARAMETERIIVPROC) load(userptr, "glGetTexParameterIiv");
+ glad_glGetTexParameterIuiv = (PFNGLGETTEXPARAMETERIUIVPROC) load(userptr, "glGetTexParameterIuiv");
+ glad_glGetTransformFeedbackVarying = (PFNGLGETTRANSFORMFEEDBACKVARYINGPROC) load(userptr, "glGetTransformFeedbackVarying");
+ glad_glGetUniformuiv = (PFNGLGETUNIFORMUIVPROC) load(userptr, "glGetUniformuiv");
+ glad_glGetVertexAttribIiv = (PFNGLGETVERTEXATTRIBIIVPROC) load(userptr, "glGetVertexAttribIiv");
+ glad_glGetVertexAttribIuiv = (PFNGLGETVERTEXATTRIBIUIVPROC) load(userptr, "glGetVertexAttribIuiv");
+ glad_glIsEnabledi = (PFNGLISENABLEDIPROC) load(userptr, "glIsEnabledi");
+ glad_glIsFramebuffer = (PFNGLISFRAMEBUFFERPROC) load(userptr, "glIsFramebuffer");
+ glad_glIsRenderbuffer = (PFNGLISRENDERBUFFERPROC) load(userptr, "glIsRenderbuffer");
+ glad_glIsVertexArray = (PFNGLISVERTEXARRAYPROC) load(userptr, "glIsVertexArray");
+ glad_glMapBufferRange = (PFNGLMAPBUFFERRANGEPROC) load(userptr, "glMapBufferRange");
+ glad_glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC) load(userptr, "glRenderbufferStorage");
+ glad_glRenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC) load(userptr, "glRenderbufferStorageMultisample");
+ glad_glTexParameterIiv = (PFNGLTEXPARAMETERIIVPROC) load(userptr, "glTexParameterIiv");
+ glad_glTexParameterIuiv = (PFNGLTEXPARAMETERIUIVPROC) load(userptr, "glTexParameterIuiv");
+ glad_glTransformFeedbackVaryings = (PFNGLTRANSFORMFEEDBACKVARYINGSPROC) load(userptr, "glTransformFeedbackVaryings");
+ glad_glUniform1ui = (PFNGLUNIFORM1UIPROC) load(userptr, "glUniform1ui");
+ glad_glUniform1uiv = (PFNGLUNIFORM1UIVPROC) load(userptr, "glUniform1uiv");
+ glad_glUniform2ui = (PFNGLUNIFORM2UIPROC) load(userptr, "glUniform2ui");
+ glad_glUniform2uiv = (PFNGLUNIFORM2UIVPROC) load(userptr, "glUniform2uiv");
+ glad_glUniform3ui = (PFNGLUNIFORM3UIPROC) load(userptr, "glUniform3ui");
+ glad_glUniform3uiv = (PFNGLUNIFORM3UIVPROC) load(userptr, "glUniform3uiv");
+ glad_glUniform4ui = (PFNGLUNIFORM4UIPROC) load(userptr, "glUniform4ui");
+ glad_glUniform4uiv = (PFNGLUNIFORM4UIVPROC) load(userptr, "glUniform4uiv");
+ glad_glVertexAttribI1i = (PFNGLVERTEXATTRIBI1IPROC) load(userptr, "glVertexAttribI1i");
+ glad_glVertexAttribI1iv = (PFNGLVERTEXATTRIBI1IVPROC) load(userptr, "glVertexAttribI1iv");
+ glad_glVertexAttribI1ui = (PFNGLVERTEXATTRIBI1UIPROC) load(userptr, "glVertexAttribI1ui");
+ glad_glVertexAttribI1uiv = (PFNGLVERTEXATTRIBI1UIVPROC) load(userptr, "glVertexAttribI1uiv");
+ glad_glVertexAttribI2i = (PFNGLVERTEXATTRIBI2IPROC) load(userptr, "glVertexAttribI2i");
+ glad_glVertexAttribI2iv = (PFNGLVERTEXATTRIBI2IVPROC) load(userptr, "glVertexAttribI2iv");
+ glad_glVertexAttribI2ui = (PFNGLVERTEXATTRIBI2UIPROC) load(userptr, "glVertexAttribI2ui");
+ glad_glVertexAttribI2uiv = (PFNGLVERTEXATTRIBI2UIVPROC) load(userptr, "glVertexAttribI2uiv");
+ glad_glVertexAttribI3i = (PFNGLVERTEXATTRIBI3IPROC) load(userptr, "glVertexAttribI3i");
+ glad_glVertexAttribI3iv = (PFNGLVERTEXATTRIBI3IVPROC) load(userptr, "glVertexAttribI3iv");
+ glad_glVertexAttribI3ui = (PFNGLVERTEXATTRIBI3UIPROC) load(userptr, "glVertexAttribI3ui");
+ glad_glVertexAttribI3uiv = (PFNGLVERTEXATTRIBI3UIVPROC) load(userptr, "glVertexAttribI3uiv");
+ glad_glVertexAttribI4bv = (PFNGLVERTEXATTRIBI4BVPROC) load(userptr, "glVertexAttribI4bv");
+ glad_glVertexAttribI4i = (PFNGLVERTEXATTRIBI4IPROC) load(userptr, "glVertexAttribI4i");
+ glad_glVertexAttribI4iv = (PFNGLVERTEXATTRIBI4IVPROC) load(userptr, "glVertexAttribI4iv");
+ glad_glVertexAttribI4sv = (PFNGLVERTEXATTRIBI4SVPROC) load(userptr, "glVertexAttribI4sv");
+ glad_glVertexAttribI4ubv = (PFNGLVERTEXATTRIBI4UBVPROC) load(userptr, "glVertexAttribI4ubv");
+ glad_glVertexAttribI4ui = (PFNGLVERTEXATTRIBI4UIPROC) load(userptr, "glVertexAttribI4ui");
+ glad_glVertexAttribI4uiv = (PFNGLVERTEXATTRIBI4UIVPROC) load(userptr, "glVertexAttribI4uiv");
+ glad_glVertexAttribI4usv = (PFNGLVERTEXATTRIBI4USVPROC) load(userptr, "glVertexAttribI4usv");
+ glad_glVertexAttribIPointer = (PFNGLVERTEXATTRIBIPOINTERPROC) load(userptr, "glVertexAttribIPointer");
+}
+static void glad_gl_load_GL_VERSION_3_1( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_VERSION_3_1) return;
+ glad_glBindBufferBase = (PFNGLBINDBUFFERBASEPROC) load(userptr, "glBindBufferBase");
+ glad_glBindBufferRange = (PFNGLBINDBUFFERRANGEPROC) load(userptr, "glBindBufferRange");
+ glad_glCopyBufferSubData = (PFNGLCOPYBUFFERSUBDATAPROC) load(userptr, "glCopyBufferSubData");
+ glad_glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDPROC) load(userptr, "glDrawArraysInstanced");
+ glad_glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDPROC) load(userptr, "glDrawElementsInstanced");
+ glad_glGetActiveUniformBlockName = (PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC) load(userptr, "glGetActiveUniformBlockName");
+ glad_glGetActiveUniformBlockiv = (PFNGLGETACTIVEUNIFORMBLOCKIVPROC) load(userptr, "glGetActiveUniformBlockiv");
+ glad_glGetActiveUniformName = (PFNGLGETACTIVEUNIFORMNAMEPROC) load(userptr, "glGetActiveUniformName");
+ glad_glGetActiveUniformsiv = (PFNGLGETACTIVEUNIFORMSIVPROC) load(userptr, "glGetActiveUniformsiv");
+ glad_glGetIntegeri_v = (PFNGLGETINTEGERI_VPROC) load(userptr, "glGetIntegeri_v");
+ glad_glGetUniformBlockIndex = (PFNGLGETUNIFORMBLOCKINDEXPROC) load(userptr, "glGetUniformBlockIndex");
+ glad_glGetUniformIndices = (PFNGLGETUNIFORMINDICESPROC) load(userptr, "glGetUniformIndices");
+ glad_glPrimitiveRestartIndex = (PFNGLPRIMITIVERESTARTINDEXPROC) load(userptr, "glPrimitiveRestartIndex");
+ glad_glTexBuffer = (PFNGLTEXBUFFERPROC) load(userptr, "glTexBuffer");
+ glad_glUniformBlockBinding = (PFNGLUNIFORMBLOCKBINDINGPROC) load(userptr, "glUniformBlockBinding");
+}
+static void glad_gl_load_GL_VERSION_3_2( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_VERSION_3_2) return;
+ glad_glClientWaitSync = (PFNGLCLIENTWAITSYNCPROC) load(userptr, "glClientWaitSync");
+ glad_glDeleteSync = (PFNGLDELETESYNCPROC) load(userptr, "glDeleteSync");
+ glad_glDrawElementsBaseVertex = (PFNGLDRAWELEMENTSBASEVERTEXPROC) load(userptr, "glDrawElementsBaseVertex");
+ glad_glDrawElementsInstancedBaseVertex = (PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC) load(userptr, "glDrawElementsInstancedBaseVertex");
+ glad_glDrawRangeElementsBaseVertex = (PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC) load(userptr, "glDrawRangeElementsBaseVertex");
+ glad_glFenceSync = (PFNGLFENCESYNCPROC) load(userptr, "glFenceSync");
+ glad_glFramebufferTexture = (PFNGLFRAMEBUFFERTEXTUREPROC) load(userptr, "glFramebufferTexture");
+ glad_glGetBufferParameteri64v = (PFNGLGETBUFFERPARAMETERI64VPROC) load(userptr, "glGetBufferParameteri64v");
+ glad_glGetInteger64i_v = (PFNGLGETINTEGER64I_VPROC) load(userptr, "glGetInteger64i_v");
+ glad_glGetInteger64v = (PFNGLGETINTEGER64VPROC) load(userptr, "glGetInteger64v");
+ glad_glGetMultisamplefv = (PFNGLGETMULTISAMPLEFVPROC) load(userptr, "glGetMultisamplefv");
+ glad_glGetSynciv = (PFNGLGETSYNCIVPROC) load(userptr, "glGetSynciv");
+ glad_glIsSync = (PFNGLISSYNCPROC) load(userptr, "glIsSync");
+ glad_glMultiDrawElementsBaseVertex = (PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC) load(userptr, "glMultiDrawElementsBaseVertex");
+ glad_glProvokingVertex = (PFNGLPROVOKINGVERTEXPROC) load(userptr, "glProvokingVertex");
+ glad_glSampleMaski = (PFNGLSAMPLEMASKIPROC) load(userptr, "glSampleMaski");
+ glad_glTexImage2DMultisample = (PFNGLTEXIMAGE2DMULTISAMPLEPROC) load(userptr, "glTexImage2DMultisample");
+ glad_glTexImage3DMultisample = (PFNGLTEXIMAGE3DMULTISAMPLEPROC) load(userptr, "glTexImage3DMultisample");
+ glad_glWaitSync = (PFNGLWAITSYNCPROC) load(userptr, "glWaitSync");
+}
+static void glad_gl_load_GL_VERSION_3_3( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_VERSION_3_3) return;
+ glad_glBindFragDataLocationIndexed = (PFNGLBINDFRAGDATALOCATIONINDEXEDPROC) load(userptr, "glBindFragDataLocationIndexed");
+ glad_glBindSampler = (PFNGLBINDSAMPLERPROC) load(userptr, "glBindSampler");
+ glad_glDeleteSamplers = (PFNGLDELETESAMPLERSPROC) load(userptr, "glDeleteSamplers");
+ glad_glGenSamplers = (PFNGLGENSAMPLERSPROC) load(userptr, "glGenSamplers");
+ glad_glGetFragDataIndex = (PFNGLGETFRAGDATAINDEXPROC) load(userptr, "glGetFragDataIndex");
+ glad_glGetQueryObjecti64v = (PFNGLGETQUERYOBJECTI64VPROC) load(userptr, "glGetQueryObjecti64v");
+ glad_glGetQueryObjectui64v = (PFNGLGETQUERYOBJECTUI64VPROC) load(userptr, "glGetQueryObjectui64v");
+ glad_glGetSamplerParameterIiv = (PFNGLGETSAMPLERPARAMETERIIVPROC) load(userptr, "glGetSamplerParameterIiv");
+ glad_glGetSamplerParameterIuiv = (PFNGLGETSAMPLERPARAMETERIUIVPROC) load(userptr, "glGetSamplerParameterIuiv");
+ glad_glGetSamplerParameterfv = (PFNGLGETSAMPLERPARAMETERFVPROC) load(userptr, "glGetSamplerParameterfv");
+ glad_glGetSamplerParameteriv = (PFNGLGETSAMPLERPARAMETERIVPROC) load(userptr, "glGetSamplerParameteriv");
+ glad_glIsSampler = (PFNGLISSAMPLERPROC) load(userptr, "glIsSampler");
+ glad_glQueryCounter = (PFNGLQUERYCOUNTERPROC) load(userptr, "glQueryCounter");
+ glad_glSamplerParameterIiv = (PFNGLSAMPLERPARAMETERIIVPROC) load(userptr, "glSamplerParameterIiv");
+ glad_glSamplerParameterIuiv = (PFNGLSAMPLERPARAMETERIUIVPROC) load(userptr, "glSamplerParameterIuiv");
+ glad_glSamplerParameterf = (PFNGLSAMPLERPARAMETERFPROC) load(userptr, "glSamplerParameterf");
+ glad_glSamplerParameterfv = (PFNGLSAMPLERPARAMETERFVPROC) load(userptr, "glSamplerParameterfv");
+ glad_glSamplerParameteri = (PFNGLSAMPLERPARAMETERIPROC) load(userptr, "glSamplerParameteri");
+ glad_glSamplerParameteriv = (PFNGLSAMPLERPARAMETERIVPROC) load(userptr, "glSamplerParameteriv");
+ glad_glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISORPROC) load(userptr, "glVertexAttribDivisor");
+ glad_glVertexAttribP1ui = (PFNGLVERTEXATTRIBP1UIPROC) load(userptr, "glVertexAttribP1ui");
+ glad_glVertexAttribP1uiv = (PFNGLVERTEXATTRIBP1UIVPROC) load(userptr, "glVertexAttribP1uiv");
+ glad_glVertexAttribP2ui = (PFNGLVERTEXATTRIBP2UIPROC) load(userptr, "glVertexAttribP2ui");
+ glad_glVertexAttribP2uiv = (PFNGLVERTEXATTRIBP2UIVPROC) load(userptr, "glVertexAttribP2uiv");
+ glad_glVertexAttribP3ui = (PFNGLVERTEXATTRIBP3UIPROC) load(userptr, "glVertexAttribP3ui");
+ glad_glVertexAttribP3uiv = (PFNGLVERTEXATTRIBP3UIVPROC) load(userptr, "glVertexAttribP3uiv");
+ glad_glVertexAttribP4ui = (PFNGLVERTEXATTRIBP4UIPROC) load(userptr, "glVertexAttribP4ui");
+ glad_glVertexAttribP4uiv = (PFNGLVERTEXATTRIBP4UIVPROC) load(userptr, "glVertexAttribP4uiv");
+}
+static void glad_gl_load_GL_VERSION_4_0( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_VERSION_4_0) return;
+ glad_glBeginQueryIndexed = (PFNGLBEGINQUERYINDEXEDPROC) load(userptr, "glBeginQueryIndexed");
+ glad_glBindTransformFeedback = (PFNGLBINDTRANSFORMFEEDBACKPROC) load(userptr, "glBindTransformFeedback");
+ glad_glBlendEquationSeparatei = (PFNGLBLENDEQUATIONSEPARATEIPROC) load(userptr, "glBlendEquationSeparatei");
+ glad_glBlendEquationi = (PFNGLBLENDEQUATIONIPROC) load(userptr, "glBlendEquationi");
+ glad_glBlendFuncSeparatei = (PFNGLBLENDFUNCSEPARATEIPROC) load(userptr, "glBlendFuncSeparatei");
+ glad_glBlendFunci = (PFNGLBLENDFUNCIPROC) load(userptr, "glBlendFunci");
+ glad_glDeleteTransformFeedbacks = (PFNGLDELETETRANSFORMFEEDBACKSPROC) load(userptr, "glDeleteTransformFeedbacks");
+ glad_glDrawArraysIndirect = (PFNGLDRAWARRAYSINDIRECTPROC) load(userptr, "glDrawArraysIndirect");
+ glad_glDrawElementsIndirect = (PFNGLDRAWELEMENTSINDIRECTPROC) load(userptr, "glDrawElementsIndirect");
+ glad_glDrawTransformFeedback = (PFNGLDRAWTRANSFORMFEEDBACKPROC) load(userptr, "glDrawTransformFeedback");
+ glad_glDrawTransformFeedbackStream = (PFNGLDRAWTRANSFORMFEEDBACKSTREAMPROC) load(userptr, "glDrawTransformFeedbackStream");
+ glad_glEndQueryIndexed = (PFNGLENDQUERYINDEXEDPROC) load(userptr, "glEndQueryIndexed");
+ glad_glGenTransformFeedbacks = (PFNGLGENTRANSFORMFEEDBACKSPROC) load(userptr, "glGenTransformFeedbacks");
+ glad_glGetActiveSubroutineName = (PFNGLGETACTIVESUBROUTINENAMEPROC) load(userptr, "glGetActiveSubroutineName");
+ glad_glGetActiveSubroutineUniformName = (PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC) load(userptr, "glGetActiveSubroutineUniformName");
+ glad_glGetActiveSubroutineUniformiv = (PFNGLGETACTIVESUBROUTINEUNIFORMIVPROC) load(userptr, "glGetActiveSubroutineUniformiv");
+ glad_glGetProgramStageiv = (PFNGLGETPROGRAMSTAGEIVPROC) load(userptr, "glGetProgramStageiv");
+ glad_glGetQueryIndexediv = (PFNGLGETQUERYINDEXEDIVPROC) load(userptr, "glGetQueryIndexediv");
+ glad_glGetSubroutineIndex = (PFNGLGETSUBROUTINEINDEXPROC) load(userptr, "glGetSubroutineIndex");
+ glad_glGetSubroutineUniformLocation = (PFNGLGETSUBROUTINEUNIFORMLOCATIONPROC) load(userptr, "glGetSubroutineUniformLocation");
+ glad_glGetUniformSubroutineuiv = (PFNGLGETUNIFORMSUBROUTINEUIVPROC) load(userptr, "glGetUniformSubroutineuiv");
+ glad_glGetUniformdv = (PFNGLGETUNIFORMDVPROC) load(userptr, "glGetUniformdv");
+ glad_glIsTransformFeedback = (PFNGLISTRANSFORMFEEDBACKPROC) load(userptr, "glIsTransformFeedback");
+ glad_glMinSampleShading = (PFNGLMINSAMPLESHADINGPROC) load(userptr, "glMinSampleShading");
+ glad_glPatchParameterfv = (PFNGLPATCHPARAMETERFVPROC) load(userptr, "glPatchParameterfv");
+ glad_glPatchParameteri = (PFNGLPATCHPARAMETERIPROC) load(userptr, "glPatchParameteri");
+ glad_glPauseTransformFeedback = (PFNGLPAUSETRANSFORMFEEDBACKPROC) load(userptr, "glPauseTransformFeedback");
+ glad_glResumeTransformFeedback = (PFNGLRESUMETRANSFORMFEEDBACKPROC) load(userptr, "glResumeTransformFeedback");
+ glad_glUniform1d = (PFNGLUNIFORM1DPROC) load(userptr, "glUniform1d");
+ glad_glUniform1dv = (PFNGLUNIFORM1DVPROC) load(userptr, "glUniform1dv");
+ glad_glUniform2d = (PFNGLUNIFORM2DPROC) load(userptr, "glUniform2d");
+ glad_glUniform2dv = (PFNGLUNIFORM2DVPROC) load(userptr, "glUniform2dv");
+ glad_glUniform3d = (PFNGLUNIFORM3DPROC) load(userptr, "glUniform3d");
+ glad_glUniform3dv = (PFNGLUNIFORM3DVPROC) load(userptr, "glUniform3dv");
+ glad_glUniform4d = (PFNGLUNIFORM4DPROC) load(userptr, "glUniform4d");
+ glad_glUniform4dv = (PFNGLUNIFORM4DVPROC) load(userptr, "glUniform4dv");
+ glad_glUniformMatrix2dv = (PFNGLUNIFORMMATRIX2DVPROC) load(userptr, "glUniformMatrix2dv");
+ glad_glUniformMatrix2x3dv = (PFNGLUNIFORMMATRIX2X3DVPROC) load(userptr, "glUniformMatrix2x3dv");
+ glad_glUniformMatrix2x4dv = (PFNGLUNIFORMMATRIX2X4DVPROC) load(userptr, "glUniformMatrix2x4dv");
+ glad_glUniformMatrix3dv = (PFNGLUNIFORMMATRIX3DVPROC) load(userptr, "glUniformMatrix3dv");
+ glad_glUniformMatrix3x2dv = (PFNGLUNIFORMMATRIX3X2DVPROC) load(userptr, "glUniformMatrix3x2dv");
+ glad_glUniformMatrix3x4dv = (PFNGLUNIFORMMATRIX3X4DVPROC) load(userptr, "glUniformMatrix3x4dv");
+ glad_glUniformMatrix4dv = (PFNGLUNIFORMMATRIX4DVPROC) load(userptr, "glUniformMatrix4dv");
+ glad_glUniformMatrix4x2dv = (PFNGLUNIFORMMATRIX4X2DVPROC) load(userptr, "glUniformMatrix4x2dv");
+ glad_glUniformMatrix4x3dv = (PFNGLUNIFORMMATRIX4X3DVPROC) load(userptr, "glUniformMatrix4x3dv");
+ glad_glUniformSubroutinesuiv = (PFNGLUNIFORMSUBROUTINESUIVPROC) load(userptr, "glUniformSubroutinesuiv");
+}
+static void glad_gl_load_GL_VERSION_4_1( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_VERSION_4_1) return;
+ glad_glActiveShaderProgram = (PFNGLACTIVESHADERPROGRAMPROC) load(userptr, "glActiveShaderProgram");
+ glad_glBindProgramPipeline = (PFNGLBINDPROGRAMPIPELINEPROC) load(userptr, "glBindProgramPipeline");
+ glad_glClearDepthf = (PFNGLCLEARDEPTHFPROC) load(userptr, "glClearDepthf");
+ glad_glCreateShaderProgramv = (PFNGLCREATESHADERPROGRAMVPROC) load(userptr, "glCreateShaderProgramv");
+ glad_glDeleteProgramPipelines = (PFNGLDELETEPROGRAMPIPELINESPROC) load(userptr, "glDeleteProgramPipelines");
+ glad_glDepthRangeArrayv = (PFNGLDEPTHRANGEARRAYVPROC) load(userptr, "glDepthRangeArrayv");
+ glad_glDepthRangeIndexed = (PFNGLDEPTHRANGEINDEXEDPROC) load(userptr, "glDepthRangeIndexed");
+ glad_glDepthRangef = (PFNGLDEPTHRANGEFPROC) load(userptr, "glDepthRangef");
+ glad_glGenProgramPipelines = (PFNGLGENPROGRAMPIPELINESPROC) load(userptr, "glGenProgramPipelines");
+ glad_glGetDoublei_v = (PFNGLGETDOUBLEI_VPROC) load(userptr, "glGetDoublei_v");
+ glad_glGetFloati_v = (PFNGLGETFLOATI_VPROC) load(userptr, "glGetFloati_v");
+ glad_glGetProgramBinary = (PFNGLGETPROGRAMBINARYPROC) load(userptr, "glGetProgramBinary");
+ glad_glGetProgramPipelineInfoLog = (PFNGLGETPROGRAMPIPELINEINFOLOGPROC) load(userptr, "glGetProgramPipelineInfoLog");
+ glad_glGetProgramPipelineiv = (PFNGLGETPROGRAMPIPELINEIVPROC) load(userptr, "glGetProgramPipelineiv");
+ glad_glGetShaderPrecisionFormat = (PFNGLGETSHADERPRECISIONFORMATPROC) load(userptr, "glGetShaderPrecisionFormat");
+ glad_glGetVertexAttribLdv = (PFNGLGETVERTEXATTRIBLDVPROC) load(userptr, "glGetVertexAttribLdv");
+ glad_glIsProgramPipeline = (PFNGLISPROGRAMPIPELINEPROC) load(userptr, "glIsProgramPipeline");
+ glad_glProgramBinary = (PFNGLPROGRAMBINARYPROC) load(userptr, "glProgramBinary");
+ glad_glProgramParameteri = (PFNGLPROGRAMPARAMETERIPROC) load(userptr, "glProgramParameteri");
+ glad_glProgramUniform1d = (PFNGLPROGRAMUNIFORM1DPROC) load(userptr, "glProgramUniform1d");
+ glad_glProgramUniform1dv = (PFNGLPROGRAMUNIFORM1DVPROC) load(userptr, "glProgramUniform1dv");
+ glad_glProgramUniform1f = (PFNGLPROGRAMUNIFORM1FPROC) load(userptr, "glProgramUniform1f");
+ glad_glProgramUniform1fv = (PFNGLPROGRAMUNIFORM1FVPROC) load(userptr, "glProgramUniform1fv");
+ glad_glProgramUniform1i = (PFNGLPROGRAMUNIFORM1IPROC) load(userptr, "glProgramUniform1i");
+ glad_glProgramUniform1iv = (PFNGLPROGRAMUNIFORM1IVPROC) load(userptr, "glProgramUniform1iv");
+ glad_glProgramUniform1ui = (PFNGLPROGRAMUNIFORM1UIPROC) load(userptr, "glProgramUniform1ui");
+ glad_glProgramUniform1uiv = (PFNGLPROGRAMUNIFORM1UIVPROC) load(userptr, "glProgramUniform1uiv");
+ glad_glProgramUniform2d = (PFNGLPROGRAMUNIFORM2DPROC) load(userptr, "glProgramUniform2d");
+ glad_glProgramUniform2dv = (PFNGLPROGRAMUNIFORM2DVPROC) load(userptr, "glProgramUniform2dv");
+ glad_glProgramUniform2f = (PFNGLPROGRAMUNIFORM2FPROC) load(userptr, "glProgramUniform2f");
+ glad_glProgramUniform2fv = (PFNGLPROGRAMUNIFORM2FVPROC) load(userptr, "glProgramUniform2fv");
+ glad_glProgramUniform2i = (PFNGLPROGRAMUNIFORM2IPROC) load(userptr, "glProgramUniform2i");
+ glad_glProgramUniform2iv = (PFNGLPROGRAMUNIFORM2IVPROC) load(userptr, "glProgramUniform2iv");
+ glad_glProgramUniform2ui = (PFNGLPROGRAMUNIFORM2UIPROC) load(userptr, "glProgramUniform2ui");
+ glad_glProgramUniform2uiv = (PFNGLPROGRAMUNIFORM2UIVPROC) load(userptr, "glProgramUniform2uiv");
+ glad_glProgramUniform3d = (PFNGLPROGRAMUNIFORM3DPROC) load(userptr, "glProgramUniform3d");
+ glad_glProgramUniform3dv = (PFNGLPROGRAMUNIFORM3DVPROC) load(userptr, "glProgramUniform3dv");
+ glad_glProgramUniform3f = (PFNGLPROGRAMUNIFORM3FPROC) load(userptr, "glProgramUniform3f");
+ glad_glProgramUniform3fv = (PFNGLPROGRAMUNIFORM3FVPROC) load(userptr, "glProgramUniform3fv");
+ glad_glProgramUniform3i = (PFNGLPROGRAMUNIFORM3IPROC) load(userptr, "glProgramUniform3i");
+ glad_glProgramUniform3iv = (PFNGLPROGRAMUNIFORM3IVPROC) load(userptr, "glProgramUniform3iv");
+ glad_glProgramUniform3ui = (PFNGLPROGRAMUNIFORM3UIPROC) load(userptr, "glProgramUniform3ui");
+ glad_glProgramUniform3uiv = (PFNGLPROGRAMUNIFORM3UIVPROC) load(userptr, "glProgramUniform3uiv");
+ glad_glProgramUniform4d = (PFNGLPROGRAMUNIFORM4DPROC) load(userptr, "glProgramUniform4d");
+ glad_glProgramUniform4dv = (PFNGLPROGRAMUNIFORM4DVPROC) load(userptr, "glProgramUniform4dv");
+ glad_glProgramUniform4f = (PFNGLPROGRAMUNIFORM4FPROC) load(userptr, "glProgramUniform4f");
+ glad_glProgramUniform4fv = (PFNGLPROGRAMUNIFORM4FVPROC) load(userptr, "glProgramUniform4fv");
+ glad_glProgramUniform4i = (PFNGLPROGRAMUNIFORM4IPROC) load(userptr, "glProgramUniform4i");
+ glad_glProgramUniform4iv = (PFNGLPROGRAMUNIFORM4IVPROC) load(userptr, "glProgramUniform4iv");
+ glad_glProgramUniform4ui = (PFNGLPROGRAMUNIFORM4UIPROC) load(userptr, "glProgramUniform4ui");
+ glad_glProgramUniform4uiv = (PFNGLPROGRAMUNIFORM4UIVPROC) load(userptr, "glProgramUniform4uiv");
+ glad_glProgramUniformMatrix2dv = (PFNGLPROGRAMUNIFORMMATRIX2DVPROC) load(userptr, "glProgramUniformMatrix2dv");
+ glad_glProgramUniformMatrix2fv = (PFNGLPROGRAMUNIFORMMATRIX2FVPROC) load(userptr, "glProgramUniformMatrix2fv");
+ glad_glProgramUniformMatrix2x3dv = (PFNGLPROGRAMUNIFORMMATRIX2X3DVPROC) load(userptr, "glProgramUniformMatrix2x3dv");
+ glad_glProgramUniformMatrix2x3fv = (PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC) load(userptr, "glProgramUniformMatrix2x3fv");
+ glad_glProgramUniformMatrix2x4dv = (PFNGLPROGRAMUNIFORMMATRIX2X4DVPROC) load(userptr, "glProgramUniformMatrix2x4dv");
+ glad_glProgramUniformMatrix2x4fv = (PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC) load(userptr, "glProgramUniformMatrix2x4fv");
+ glad_glProgramUniformMatrix3dv = (PFNGLPROGRAMUNIFORMMATRIX3DVPROC) load(userptr, "glProgramUniformMatrix3dv");
+ glad_glProgramUniformMatrix3fv = (PFNGLPROGRAMUNIFORMMATRIX3FVPROC) load(userptr, "glProgramUniformMatrix3fv");
+ glad_glProgramUniformMatrix3x2dv = (PFNGLPROGRAMUNIFORMMATRIX3X2DVPROC) load(userptr, "glProgramUniformMatrix3x2dv");
+ glad_glProgramUniformMatrix3x2fv = (PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC) load(userptr, "glProgramUniformMatrix3x2fv");
+ glad_glProgramUniformMatrix3x4dv = (PFNGLPROGRAMUNIFORMMATRIX3X4DVPROC) load(userptr, "glProgramUniformMatrix3x4dv");
+ glad_glProgramUniformMatrix3x4fv = (PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC) load(userptr, "glProgramUniformMatrix3x4fv");
+ glad_glProgramUniformMatrix4dv = (PFNGLPROGRAMUNIFORMMATRIX4DVPROC) load(userptr, "glProgramUniformMatrix4dv");
+ glad_glProgramUniformMatrix4fv = (PFNGLPROGRAMUNIFORMMATRIX4FVPROC) load(userptr, "glProgramUniformMatrix4fv");
+ glad_glProgramUniformMatrix4x2dv = (PFNGLPROGRAMUNIFORMMATRIX4X2DVPROC) load(userptr, "glProgramUniformMatrix4x2dv");
+ glad_glProgramUniformMatrix4x2fv = (PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC) load(userptr, "glProgramUniformMatrix4x2fv");
+ glad_glProgramUniformMatrix4x3dv = (PFNGLPROGRAMUNIFORMMATRIX4X3DVPROC) load(userptr, "glProgramUniformMatrix4x3dv");
+ glad_glProgramUniformMatrix4x3fv = (PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC) load(userptr, "glProgramUniformMatrix4x3fv");
+ glad_glReleaseShaderCompiler = (PFNGLRELEASESHADERCOMPILERPROC) load(userptr, "glReleaseShaderCompiler");
+ glad_glScissorArrayv = (PFNGLSCISSORARRAYVPROC) load(userptr, "glScissorArrayv");
+ glad_glScissorIndexed = (PFNGLSCISSORINDEXEDPROC) load(userptr, "glScissorIndexed");
+ glad_glScissorIndexedv = (PFNGLSCISSORINDEXEDVPROC) load(userptr, "glScissorIndexedv");
+ glad_glShaderBinary = (PFNGLSHADERBINARYPROC) load(userptr, "glShaderBinary");
+ glad_glUseProgramStages = (PFNGLUSEPROGRAMSTAGESPROC) load(userptr, "glUseProgramStages");
+ glad_glValidateProgramPipeline = (PFNGLVALIDATEPROGRAMPIPELINEPROC) load(userptr, "glValidateProgramPipeline");
+ glad_glVertexAttribL1d = (PFNGLVERTEXATTRIBL1DPROC) load(userptr, "glVertexAttribL1d");
+ glad_glVertexAttribL1dv = (PFNGLVERTEXATTRIBL1DVPROC) load(userptr, "glVertexAttribL1dv");
+ glad_glVertexAttribL2d = (PFNGLVERTEXATTRIBL2DPROC) load(userptr, "glVertexAttribL2d");
+ glad_glVertexAttribL2dv = (PFNGLVERTEXATTRIBL2DVPROC) load(userptr, "glVertexAttribL2dv");
+ glad_glVertexAttribL3d = (PFNGLVERTEXATTRIBL3DPROC) load(userptr, "glVertexAttribL3d");
+ glad_glVertexAttribL3dv = (PFNGLVERTEXATTRIBL3DVPROC) load(userptr, "glVertexAttribL3dv");
+ glad_glVertexAttribL4d = (PFNGLVERTEXATTRIBL4DPROC) load(userptr, "glVertexAttribL4d");
+ glad_glVertexAttribL4dv = (PFNGLVERTEXATTRIBL4DVPROC) load(userptr, "glVertexAttribL4dv");
+ glad_glVertexAttribLPointer = (PFNGLVERTEXATTRIBLPOINTERPROC) load(userptr, "glVertexAttribLPointer");
+ glad_glViewportArrayv = (PFNGLVIEWPORTARRAYVPROC) load(userptr, "glViewportArrayv");
+ glad_glViewportIndexedf = (PFNGLVIEWPORTINDEXEDFPROC) load(userptr, "glViewportIndexedf");
+ glad_glViewportIndexedfv = (PFNGLVIEWPORTINDEXEDFVPROC) load(userptr, "glViewportIndexedfv");
+}
+static void glad_gl_load_GL_VERSION_4_2( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_VERSION_4_2) return;
+ glad_glBindImageTexture = (PFNGLBINDIMAGETEXTUREPROC) load(userptr, "glBindImageTexture");
+ glad_glDrawArraysInstancedBaseInstance = (PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEPROC) load(userptr, "glDrawArraysInstancedBaseInstance");
+ glad_glDrawElementsInstancedBaseInstance = (PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEPROC) load(userptr, "glDrawElementsInstancedBaseInstance");
+ glad_glDrawElementsInstancedBaseVertexBaseInstance = (PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC) load(userptr, "glDrawElementsInstancedBaseVertexBaseInstance");
+ glad_glDrawTransformFeedbackInstanced = (PFNGLDRAWTRANSFORMFEEDBACKINSTANCEDPROC) load(userptr, "glDrawTransformFeedbackInstanced");
+ glad_glDrawTransformFeedbackStreamInstanced = (PFNGLDRAWTRANSFORMFEEDBACKSTREAMINSTANCEDPROC) load(userptr, "glDrawTransformFeedbackStreamInstanced");
+ glad_glGetActiveAtomicCounterBufferiv = (PFNGLGETACTIVEATOMICCOUNTERBUFFERIVPROC) load(userptr, "glGetActiveAtomicCounterBufferiv");
+ glad_glGetInternalformativ = (PFNGLGETINTERNALFORMATIVPROC) load(userptr, "glGetInternalformativ");
+ glad_glMemoryBarrier = (PFNGLMEMORYBARRIERPROC) load(userptr, "glMemoryBarrier");
+ glad_glTexStorage1D = (PFNGLTEXSTORAGE1DPROC) load(userptr, "glTexStorage1D");
+ glad_glTexStorage2D = (PFNGLTEXSTORAGE2DPROC) load(userptr, "glTexStorage2D");
+ glad_glTexStorage3D = (PFNGLTEXSTORAGE3DPROC) load(userptr, "glTexStorage3D");
+}
+static void glad_gl_load_GL_VERSION_4_3( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_VERSION_4_3) return;
+ glad_glBindVertexBuffer = (PFNGLBINDVERTEXBUFFERPROC) load(userptr, "glBindVertexBuffer");
+ glad_glClearBufferData = (PFNGLCLEARBUFFERDATAPROC) load(userptr, "glClearBufferData");
+ glad_glClearBufferSubData = (PFNGLCLEARBUFFERSUBDATAPROC) load(userptr, "glClearBufferSubData");
+ glad_glCopyImageSubData = (PFNGLCOPYIMAGESUBDATAPROC) load(userptr, "glCopyImageSubData");
+ glad_glDebugMessageCallback = (PFNGLDEBUGMESSAGECALLBACKPROC) load(userptr, "glDebugMessageCallback");
+ glad_glDebugMessageControl = (PFNGLDEBUGMESSAGECONTROLPROC) load(userptr, "glDebugMessageControl");
+ glad_glDebugMessageInsert = (PFNGLDEBUGMESSAGEINSERTPROC) load(userptr, "glDebugMessageInsert");
+ glad_glDispatchCompute = (PFNGLDISPATCHCOMPUTEPROC) load(userptr, "glDispatchCompute");
+ glad_glDispatchComputeIndirect = (PFNGLDISPATCHCOMPUTEINDIRECTPROC) load(userptr, "glDispatchComputeIndirect");
+ glad_glFramebufferParameteri = (PFNGLFRAMEBUFFERPARAMETERIPROC) load(userptr, "glFramebufferParameteri");
+ glad_glGetDebugMessageLog = (PFNGLGETDEBUGMESSAGELOGPROC) load(userptr, "glGetDebugMessageLog");
+ glad_glGetFramebufferParameteriv = (PFNGLGETFRAMEBUFFERPARAMETERIVPROC) load(userptr, "glGetFramebufferParameteriv");
+ glad_glGetInternalformati64v = (PFNGLGETINTERNALFORMATI64VPROC) load(userptr, "glGetInternalformati64v");
+ glad_glGetObjectLabel = (PFNGLGETOBJECTLABELPROC) load(userptr, "glGetObjectLabel");
+ glad_glGetObjectPtrLabel = (PFNGLGETOBJECTPTRLABELPROC) load(userptr, "glGetObjectPtrLabel");
+ glad_glGetPointerv = (PFNGLGETPOINTERVPROC) load(userptr, "glGetPointerv");
+ glad_glGetProgramInterfaceiv = (PFNGLGETPROGRAMINTERFACEIVPROC) load(userptr, "glGetProgramInterfaceiv");
+ glad_glGetProgramResourceIndex = (PFNGLGETPROGRAMRESOURCEINDEXPROC) load(userptr, "glGetProgramResourceIndex");
+ glad_glGetProgramResourceLocation = (PFNGLGETPROGRAMRESOURCELOCATIONPROC) load(userptr, "glGetProgramResourceLocation");
+ glad_glGetProgramResourceLocationIndex = (PFNGLGETPROGRAMRESOURCELOCATIONINDEXPROC) load(userptr, "glGetProgramResourceLocationIndex");
+ glad_glGetProgramResourceName = (PFNGLGETPROGRAMRESOURCENAMEPROC) load(userptr, "glGetProgramResourceName");
+ glad_glGetProgramResourceiv = (PFNGLGETPROGRAMRESOURCEIVPROC) load(userptr, "glGetProgramResourceiv");
+ glad_glInvalidateBufferData = (PFNGLINVALIDATEBUFFERDATAPROC) load(userptr, "glInvalidateBufferData");
+ glad_glInvalidateBufferSubData = (PFNGLINVALIDATEBUFFERSUBDATAPROC) load(userptr, "glInvalidateBufferSubData");
+ glad_glInvalidateFramebuffer = (PFNGLINVALIDATEFRAMEBUFFERPROC) load(userptr, "glInvalidateFramebuffer");
+ glad_glInvalidateSubFramebuffer = (PFNGLINVALIDATESUBFRAMEBUFFERPROC) load(userptr, "glInvalidateSubFramebuffer");
+ glad_glInvalidateTexImage = (PFNGLINVALIDATETEXIMAGEPROC) load(userptr, "glInvalidateTexImage");
+ glad_glInvalidateTexSubImage = (PFNGLINVALIDATETEXSUBIMAGEPROC) load(userptr, "glInvalidateTexSubImage");
+ glad_glMultiDrawArraysIndirect = (PFNGLMULTIDRAWARRAYSINDIRECTPROC) load(userptr, "glMultiDrawArraysIndirect");
+ glad_glMultiDrawElementsIndirect = (PFNGLMULTIDRAWELEMENTSINDIRECTPROC) load(userptr, "glMultiDrawElementsIndirect");
+ glad_glObjectLabel = (PFNGLOBJECTLABELPROC) load(userptr, "glObjectLabel");
+ glad_glObjectPtrLabel = (PFNGLOBJECTPTRLABELPROC) load(userptr, "glObjectPtrLabel");
+ glad_glPopDebugGroup = (PFNGLPOPDEBUGGROUPPROC) load(userptr, "glPopDebugGroup");
+ glad_glPushDebugGroup = (PFNGLPUSHDEBUGGROUPPROC) load(userptr, "glPushDebugGroup");
+ glad_glShaderStorageBlockBinding = (PFNGLSHADERSTORAGEBLOCKBINDINGPROC) load(userptr, "glShaderStorageBlockBinding");
+ glad_glTexBufferRange = (PFNGLTEXBUFFERRANGEPROC) load(userptr, "glTexBufferRange");
+ glad_glTexStorage2DMultisample = (PFNGLTEXSTORAGE2DMULTISAMPLEPROC) load(userptr, "glTexStorage2DMultisample");
+ glad_glTexStorage3DMultisample = (PFNGLTEXSTORAGE3DMULTISAMPLEPROC) load(userptr, "glTexStorage3DMultisample");
+ glad_glTextureView = (PFNGLTEXTUREVIEWPROC) load(userptr, "glTextureView");
+ glad_glVertexAttribBinding = (PFNGLVERTEXATTRIBBINDINGPROC) load(userptr, "glVertexAttribBinding");
+ glad_glVertexAttribFormat = (PFNGLVERTEXATTRIBFORMATPROC) load(userptr, "glVertexAttribFormat");
+ glad_glVertexAttribIFormat = (PFNGLVERTEXATTRIBIFORMATPROC) load(userptr, "glVertexAttribIFormat");
+ glad_glVertexAttribLFormat = (PFNGLVERTEXATTRIBLFORMATPROC) load(userptr, "glVertexAttribLFormat");
+ glad_glVertexBindingDivisor = (PFNGLVERTEXBINDINGDIVISORPROC) load(userptr, "glVertexBindingDivisor");
+}
+static void glad_gl_load_GL_ARB_ES2_compatibility( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_ES2_compatibility) return;
+ glad_glClearDepthf = (PFNGLCLEARDEPTHFPROC) load(userptr, "glClearDepthf");
+ glad_glDepthRangef = (PFNGLDEPTHRANGEFPROC) load(userptr, "glDepthRangef");
+ glad_glGetShaderPrecisionFormat = (PFNGLGETSHADERPRECISIONFORMATPROC) load(userptr, "glGetShaderPrecisionFormat");
+ glad_glReleaseShaderCompiler = (PFNGLRELEASESHADERCOMPILERPROC) load(userptr, "glReleaseShaderCompiler");
+ glad_glShaderBinary = (PFNGLSHADERBINARYPROC) load(userptr, "glShaderBinary");
+}
+static void glad_gl_load_GL_ARB_ES3_1_compatibility( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_ES3_1_compatibility) return;
+ glad_glMemoryBarrierByRegion = (PFNGLMEMORYBARRIERBYREGIONPROC) load(userptr, "glMemoryBarrierByRegion");
+}
+static void glad_gl_load_GL_ARB_ES3_2_compatibility( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_ES3_2_compatibility) return;
+ glad_glPrimitiveBoundingBoxARB = (PFNGLPRIMITIVEBOUNDINGBOXARBPROC) load(userptr, "glPrimitiveBoundingBoxARB");
+}
+static void glad_gl_load_GL_ARB_blend_func_extended( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_blend_func_extended) return;
+ glad_glBindFragDataLocationIndexed = (PFNGLBINDFRAGDATALOCATIONINDEXEDPROC) load(userptr, "glBindFragDataLocationIndexed");
+ glad_glGetFragDataIndex = (PFNGLGETFRAGDATAINDEXPROC) load(userptr, "glGetFragDataIndex");
+}
+static void glad_gl_load_GL_ARB_buffer_storage( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_buffer_storage) return;
+ glad_glBufferStorage = (PFNGLBUFFERSTORAGEPROC) load(userptr, "glBufferStorage");
+}
+static void glad_gl_load_GL_ARB_clear_buffer_object( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_clear_buffer_object) return;
+ glad_glClearBufferData = (PFNGLCLEARBUFFERDATAPROC) load(userptr, "glClearBufferData");
+ glad_glClearBufferSubData = (PFNGLCLEARBUFFERSUBDATAPROC) load(userptr, "glClearBufferSubData");
+}
+static void glad_gl_load_GL_ARB_clear_texture( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_clear_texture) return;
+ glad_glClearTexImage = (PFNGLCLEARTEXIMAGEPROC) load(userptr, "glClearTexImage");
+ glad_glClearTexSubImage = (PFNGLCLEARTEXSUBIMAGEPROC) load(userptr, "glClearTexSubImage");
+}
+static void glad_gl_load_GL_ARB_color_buffer_float( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_color_buffer_float) return;
+ glad_glClampColorARB = (PFNGLCLAMPCOLORARBPROC) load(userptr, "glClampColorARB");
+}
+static void glad_gl_load_GL_ARB_compute_shader( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_compute_shader) return;
+ glad_glDispatchCompute = (PFNGLDISPATCHCOMPUTEPROC) load(userptr, "glDispatchCompute");
+ glad_glDispatchComputeIndirect = (PFNGLDISPATCHCOMPUTEINDIRECTPROC) load(userptr, "glDispatchComputeIndirect");
+}
+static void glad_gl_load_GL_ARB_compute_variable_group_size( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_compute_variable_group_size) return;
+ glad_glDispatchComputeGroupSizeARB = (PFNGLDISPATCHCOMPUTEGROUPSIZEARBPROC) load(userptr, "glDispatchComputeGroupSizeARB");
+}
+static void glad_gl_load_GL_ARB_copy_buffer( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_copy_buffer) return;
+ glad_glCopyBufferSubData = (PFNGLCOPYBUFFERSUBDATAPROC) load(userptr, "glCopyBufferSubData");
+}
+static void glad_gl_load_GL_ARB_copy_image( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_copy_image) return;
+ glad_glCopyImageSubData = (PFNGLCOPYIMAGESUBDATAPROC) load(userptr, "glCopyImageSubData");
+}
+static void glad_gl_load_GL_ARB_debug_output( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_debug_output) return;
+ glad_glDebugMessageCallbackARB = (PFNGLDEBUGMESSAGECALLBACKARBPROC) load(userptr, "glDebugMessageCallbackARB");
+ glad_glDebugMessageControlARB = (PFNGLDEBUGMESSAGECONTROLARBPROC) load(userptr, "glDebugMessageControlARB");
+ glad_glDebugMessageInsertARB = (PFNGLDEBUGMESSAGEINSERTARBPROC) load(userptr, "glDebugMessageInsertARB");
+ glad_glGetDebugMessageLogARB = (PFNGLGETDEBUGMESSAGELOGARBPROC) load(userptr, "glGetDebugMessageLogARB");
+}
+static void glad_gl_load_GL_ARB_direct_state_access( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_direct_state_access) return;
+ glad_glBindTextureUnit = (PFNGLBINDTEXTUREUNITPROC) load(userptr, "glBindTextureUnit");
+ glad_glBlitNamedFramebuffer = (PFNGLBLITNAMEDFRAMEBUFFERPROC) load(userptr, "glBlitNamedFramebuffer");
+ glad_glCheckNamedFramebufferStatus = (PFNGLCHECKNAMEDFRAMEBUFFERSTATUSPROC) load(userptr, "glCheckNamedFramebufferStatus");
+ glad_glClearNamedBufferData = (PFNGLCLEARNAMEDBUFFERDATAPROC) load(userptr, "glClearNamedBufferData");
+ glad_glClearNamedBufferSubData = (PFNGLCLEARNAMEDBUFFERSUBDATAPROC) load(userptr, "glClearNamedBufferSubData");
+ glad_glClearNamedFramebufferfi = (PFNGLCLEARNAMEDFRAMEBUFFERFIPROC) load(userptr, "glClearNamedFramebufferfi");
+ glad_glClearNamedFramebufferfv = (PFNGLCLEARNAMEDFRAMEBUFFERFVPROC) load(userptr, "glClearNamedFramebufferfv");
+ glad_glClearNamedFramebufferiv = (PFNGLCLEARNAMEDFRAMEBUFFERIVPROC) load(userptr, "glClearNamedFramebufferiv");
+ glad_glClearNamedFramebufferuiv = (PFNGLCLEARNAMEDFRAMEBUFFERUIVPROC) load(userptr, "glClearNamedFramebufferuiv");
+ glad_glCompressedTextureSubImage1D = (PFNGLCOMPRESSEDTEXTURESUBIMAGE1DPROC) load(userptr, "glCompressedTextureSubImage1D");
+ glad_glCompressedTextureSubImage2D = (PFNGLCOMPRESSEDTEXTURESUBIMAGE2DPROC) load(userptr, "glCompressedTextureSubImage2D");
+ glad_glCompressedTextureSubImage3D = (PFNGLCOMPRESSEDTEXTURESUBIMAGE3DPROC) load(userptr, "glCompressedTextureSubImage3D");
+ glad_glCopyNamedBufferSubData = (PFNGLCOPYNAMEDBUFFERSUBDATAPROC) load(userptr, "glCopyNamedBufferSubData");
+ glad_glCopyTextureSubImage1D = (PFNGLCOPYTEXTURESUBIMAGE1DPROC) load(userptr, "glCopyTextureSubImage1D");
+ glad_glCopyTextureSubImage2D = (PFNGLCOPYTEXTURESUBIMAGE2DPROC) load(userptr, "glCopyTextureSubImage2D");
+ glad_glCopyTextureSubImage3D = (PFNGLCOPYTEXTURESUBIMAGE3DPROC) load(userptr, "glCopyTextureSubImage3D");
+ glad_glCreateBuffers = (PFNGLCREATEBUFFERSPROC) load(userptr, "glCreateBuffers");
+ glad_glCreateFramebuffers = (PFNGLCREATEFRAMEBUFFERSPROC) load(userptr, "glCreateFramebuffers");
+ glad_glCreateProgramPipelines = (PFNGLCREATEPROGRAMPIPELINESPROC) load(userptr, "glCreateProgramPipelines");
+ glad_glCreateQueries = (PFNGLCREATEQUERIESPROC) load(userptr, "glCreateQueries");
+ glad_glCreateRenderbuffers = (PFNGLCREATERENDERBUFFERSPROC) load(userptr, "glCreateRenderbuffers");
+ glad_glCreateSamplers = (PFNGLCREATESAMPLERSPROC) load(userptr, "glCreateSamplers");
+ glad_glCreateTextures = (PFNGLCREATETEXTURESPROC) load(userptr, "glCreateTextures");
+ glad_glCreateTransformFeedbacks = (PFNGLCREATETRANSFORMFEEDBACKSPROC) load(userptr, "glCreateTransformFeedbacks");
+ glad_glCreateVertexArrays = (PFNGLCREATEVERTEXARRAYSPROC) load(userptr, "glCreateVertexArrays");
+ glad_glDisableVertexArrayAttrib = (PFNGLDISABLEVERTEXARRAYATTRIBPROC) load(userptr, "glDisableVertexArrayAttrib");
+ glad_glEnableVertexArrayAttrib = (PFNGLENABLEVERTEXARRAYATTRIBPROC) load(userptr, "glEnableVertexArrayAttrib");
+ glad_glFlushMappedNamedBufferRange = (PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEPROC) load(userptr, "glFlushMappedNamedBufferRange");
+ glad_glGenerateTextureMipmap = (PFNGLGENERATETEXTUREMIPMAPPROC) load(userptr, "glGenerateTextureMipmap");
+ glad_glGetCompressedTextureImage = (PFNGLGETCOMPRESSEDTEXTUREIMAGEPROC) load(userptr, "glGetCompressedTextureImage");
+ glad_glGetNamedBufferParameteri64v = (PFNGLGETNAMEDBUFFERPARAMETERI64VPROC) load(userptr, "glGetNamedBufferParameteri64v");
+ glad_glGetNamedBufferParameteriv = (PFNGLGETNAMEDBUFFERPARAMETERIVPROC) load(userptr, "glGetNamedBufferParameteriv");
+ glad_glGetNamedBufferPointerv = (PFNGLGETNAMEDBUFFERPOINTERVPROC) load(userptr, "glGetNamedBufferPointerv");
+ glad_glGetNamedBufferSubData = (PFNGLGETNAMEDBUFFERSUBDATAPROC) load(userptr, "glGetNamedBufferSubData");
+ glad_glGetNamedFramebufferAttachmentParameteriv = (PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVPROC) load(userptr, "glGetNamedFramebufferAttachmentParameteriv");
+ glad_glGetNamedFramebufferParameteriv = (PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVPROC) load(userptr, "glGetNamedFramebufferParameteriv");
+ glad_glGetNamedRenderbufferParameteriv = (PFNGLGETNAMEDRENDERBUFFERPARAMETERIVPROC) load(userptr, "glGetNamedRenderbufferParameteriv");
+ glad_glGetQueryBufferObjecti64v = (PFNGLGETQUERYBUFFEROBJECTI64VPROC) load(userptr, "glGetQueryBufferObjecti64v");
+ glad_glGetQueryBufferObjectiv = (PFNGLGETQUERYBUFFEROBJECTIVPROC) load(userptr, "glGetQueryBufferObjectiv");
+ glad_glGetQueryBufferObjectui64v = (PFNGLGETQUERYBUFFEROBJECTUI64VPROC) load(userptr, "glGetQueryBufferObjectui64v");
+ glad_glGetQueryBufferObjectuiv = (PFNGLGETQUERYBUFFEROBJECTUIVPROC) load(userptr, "glGetQueryBufferObjectuiv");
+ glad_glGetTextureImage = (PFNGLGETTEXTUREIMAGEPROC) load(userptr, "glGetTextureImage");
+ glad_glGetTextureLevelParameterfv = (PFNGLGETTEXTURELEVELPARAMETERFVPROC) load(userptr, "glGetTextureLevelParameterfv");
+ glad_glGetTextureLevelParameteriv = (PFNGLGETTEXTURELEVELPARAMETERIVPROC) load(userptr, "glGetTextureLevelParameteriv");
+ glad_glGetTextureParameterIiv = (PFNGLGETTEXTUREPARAMETERIIVPROC) load(userptr, "glGetTextureParameterIiv");
+ glad_glGetTextureParameterIuiv = (PFNGLGETTEXTUREPARAMETERIUIVPROC) load(userptr, "glGetTextureParameterIuiv");
+ glad_glGetTextureParameterfv = (PFNGLGETTEXTUREPARAMETERFVPROC) load(userptr, "glGetTextureParameterfv");
+ glad_glGetTextureParameteriv = (PFNGLGETTEXTUREPARAMETERIVPROC) load(userptr, "glGetTextureParameteriv");
+ glad_glGetTransformFeedbacki64_v = (PFNGLGETTRANSFORMFEEDBACKI64_VPROC) load(userptr, "glGetTransformFeedbacki64_v");
+ glad_glGetTransformFeedbacki_v = (PFNGLGETTRANSFORMFEEDBACKI_VPROC) load(userptr, "glGetTransformFeedbacki_v");
+ glad_glGetTransformFeedbackiv = (PFNGLGETTRANSFORMFEEDBACKIVPROC) load(userptr, "glGetTransformFeedbackiv");
+ glad_glGetVertexArrayIndexed64iv = (PFNGLGETVERTEXARRAYINDEXED64IVPROC) load(userptr, "glGetVertexArrayIndexed64iv");
+ glad_glGetVertexArrayIndexediv = (PFNGLGETVERTEXARRAYINDEXEDIVPROC) load(userptr, "glGetVertexArrayIndexediv");
+ glad_glGetVertexArrayiv = (PFNGLGETVERTEXARRAYIVPROC) load(userptr, "glGetVertexArrayiv");
+ glad_glInvalidateNamedFramebufferData = (PFNGLINVALIDATENAMEDFRAMEBUFFERDATAPROC) load(userptr, "glInvalidateNamedFramebufferData");
+ glad_glInvalidateNamedFramebufferSubData = (PFNGLINVALIDATENAMEDFRAMEBUFFERSUBDATAPROC) load(userptr, "glInvalidateNamedFramebufferSubData");
+ glad_glMapNamedBuffer = (PFNGLMAPNAMEDBUFFERPROC) load(userptr, "glMapNamedBuffer");
+ glad_glMapNamedBufferRange = (PFNGLMAPNAMEDBUFFERRANGEPROC) load(userptr, "glMapNamedBufferRange");
+ glad_glNamedBufferData = (PFNGLNAMEDBUFFERDATAPROC) load(userptr, "glNamedBufferData");
+ glad_glNamedBufferStorage = (PFNGLNAMEDBUFFERSTORAGEPROC) load(userptr, "glNamedBufferStorage");
+ glad_glNamedBufferSubData = (PFNGLNAMEDBUFFERSUBDATAPROC) load(userptr, "glNamedBufferSubData");
+ glad_glNamedFramebufferDrawBuffer = (PFNGLNAMEDFRAMEBUFFERDRAWBUFFERPROC) load(userptr, "glNamedFramebufferDrawBuffer");
+ glad_glNamedFramebufferDrawBuffers = (PFNGLNAMEDFRAMEBUFFERDRAWBUFFERSPROC) load(userptr, "glNamedFramebufferDrawBuffers");
+ glad_glNamedFramebufferParameteri = (PFNGLNAMEDFRAMEBUFFERPARAMETERIPROC) load(userptr, "glNamedFramebufferParameteri");
+ glad_glNamedFramebufferReadBuffer = (PFNGLNAMEDFRAMEBUFFERREADBUFFERPROC) load(userptr, "glNamedFramebufferReadBuffer");
+ glad_glNamedFramebufferRenderbuffer = (PFNGLNAMEDFRAMEBUFFERRENDERBUFFERPROC) load(userptr, "glNamedFramebufferRenderbuffer");
+ glad_glNamedFramebufferTexture = (PFNGLNAMEDFRAMEBUFFERTEXTUREPROC) load(userptr, "glNamedFramebufferTexture");
+ glad_glNamedFramebufferTextureLayer = (PFNGLNAMEDFRAMEBUFFERTEXTURELAYERPROC) load(userptr, "glNamedFramebufferTextureLayer");
+ glad_glNamedRenderbufferStorage = (PFNGLNAMEDRENDERBUFFERSTORAGEPROC) load(userptr, "glNamedRenderbufferStorage");
+ glad_glNamedRenderbufferStorageMultisample = (PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEPROC) load(userptr, "glNamedRenderbufferStorageMultisample");
+ glad_glTextureBuffer = (PFNGLTEXTUREBUFFERPROC) load(userptr, "glTextureBuffer");
+ glad_glTextureBufferRange = (PFNGLTEXTUREBUFFERRANGEPROC) load(userptr, "glTextureBufferRange");
+ glad_glTextureParameterIiv = (PFNGLTEXTUREPARAMETERIIVPROC) load(userptr, "glTextureParameterIiv");
+ glad_glTextureParameterIuiv = (PFNGLTEXTUREPARAMETERIUIVPROC) load(userptr, "glTextureParameterIuiv");
+ glad_glTextureParameterf = (PFNGLTEXTUREPARAMETERFPROC) load(userptr, "glTextureParameterf");
+ glad_glTextureParameterfv = (PFNGLTEXTUREPARAMETERFVPROC) load(userptr, "glTextureParameterfv");
+ glad_glTextureParameteri = (PFNGLTEXTUREPARAMETERIPROC) load(userptr, "glTextureParameteri");
+ glad_glTextureParameteriv = (PFNGLTEXTUREPARAMETERIVPROC) load(userptr, "glTextureParameteriv");
+ glad_glTextureStorage1D = (PFNGLTEXTURESTORAGE1DPROC) load(userptr, "glTextureStorage1D");
+ glad_glTextureStorage2D = (PFNGLTEXTURESTORAGE2DPROC) load(userptr, "glTextureStorage2D");
+ glad_glTextureStorage2DMultisample = (PFNGLTEXTURESTORAGE2DMULTISAMPLEPROC) load(userptr, "glTextureStorage2DMultisample");
+ glad_glTextureStorage3D = (PFNGLTEXTURESTORAGE3DPROC) load(userptr, "glTextureStorage3D");
+ glad_glTextureStorage3DMultisample = (PFNGLTEXTURESTORAGE3DMULTISAMPLEPROC) load(userptr, "glTextureStorage3DMultisample");
+ glad_glTextureSubImage1D = (PFNGLTEXTURESUBIMAGE1DPROC) load(userptr, "glTextureSubImage1D");
+ glad_glTextureSubImage2D = (PFNGLTEXTURESUBIMAGE2DPROC) load(userptr, "glTextureSubImage2D");
+ glad_glTextureSubImage3D = (PFNGLTEXTURESUBIMAGE3DPROC) load(userptr, "glTextureSubImage3D");
+ glad_glTransformFeedbackBufferBase = (PFNGLTRANSFORMFEEDBACKBUFFERBASEPROC) load(userptr, "glTransformFeedbackBufferBase");
+ glad_glTransformFeedbackBufferRange = (PFNGLTRANSFORMFEEDBACKBUFFERRANGEPROC) load(userptr, "glTransformFeedbackBufferRange");
+ glad_glUnmapNamedBuffer = (PFNGLUNMAPNAMEDBUFFERPROC) load(userptr, "glUnmapNamedBuffer");
+ glad_glVertexArrayAttribBinding = (PFNGLVERTEXARRAYATTRIBBINDINGPROC) load(userptr, "glVertexArrayAttribBinding");
+ glad_glVertexArrayAttribFormat = (PFNGLVERTEXARRAYATTRIBFORMATPROC) load(userptr, "glVertexArrayAttribFormat");
+ glad_glVertexArrayAttribIFormat = (PFNGLVERTEXARRAYATTRIBIFORMATPROC) load(userptr, "glVertexArrayAttribIFormat");
+ glad_glVertexArrayAttribLFormat = (PFNGLVERTEXARRAYATTRIBLFORMATPROC) load(userptr, "glVertexArrayAttribLFormat");
+ glad_glVertexArrayBindingDivisor = (PFNGLVERTEXARRAYBINDINGDIVISORPROC) load(userptr, "glVertexArrayBindingDivisor");
+ glad_glVertexArrayElementBuffer = (PFNGLVERTEXARRAYELEMENTBUFFERPROC) load(userptr, "glVertexArrayElementBuffer");
+ glad_glVertexArrayVertexBuffer = (PFNGLVERTEXARRAYVERTEXBUFFERPROC) load(userptr, "glVertexArrayVertexBuffer");
+ glad_glVertexArrayVertexBuffers = (PFNGLVERTEXARRAYVERTEXBUFFERSPROC) load(userptr, "glVertexArrayVertexBuffers");
+}
+static void glad_gl_load_GL_ARB_draw_buffers( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_draw_buffers) return;
+ glad_glDrawBuffersARB = (PFNGLDRAWBUFFERSARBPROC) load(userptr, "glDrawBuffersARB");
+}
+static void glad_gl_load_GL_ARB_draw_buffers_blend( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_draw_buffers_blend) return;
+ glad_glBlendEquationSeparateiARB = (PFNGLBLENDEQUATIONSEPARATEIARBPROC) load(userptr, "glBlendEquationSeparateiARB");
+ glad_glBlendEquationiARB = (PFNGLBLENDEQUATIONIARBPROC) load(userptr, "glBlendEquationiARB");
+ glad_glBlendFuncSeparateiARB = (PFNGLBLENDFUNCSEPARATEIARBPROC) load(userptr, "glBlendFuncSeparateiARB");
+ glad_glBlendFunciARB = (PFNGLBLENDFUNCIARBPROC) load(userptr, "glBlendFunciARB");
+}
+static void glad_gl_load_GL_ARB_draw_elements_base_vertex( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_draw_elements_base_vertex) return;
+ glad_glDrawElementsBaseVertex = (PFNGLDRAWELEMENTSBASEVERTEXPROC) load(userptr, "glDrawElementsBaseVertex");
+ glad_glDrawElementsInstancedBaseVertex = (PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC) load(userptr, "glDrawElementsInstancedBaseVertex");
+ glad_glDrawRangeElementsBaseVertex = (PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC) load(userptr, "glDrawRangeElementsBaseVertex");
+ glad_glMultiDrawElementsBaseVertex = (PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC) load(userptr, "glMultiDrawElementsBaseVertex");
+}
+static void glad_gl_load_GL_ARB_draw_indirect( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_draw_indirect) return;
+ glad_glDrawArraysIndirect = (PFNGLDRAWARRAYSINDIRECTPROC) load(userptr, "glDrawArraysIndirect");
+ glad_glDrawElementsIndirect = (PFNGLDRAWELEMENTSINDIRECTPROC) load(userptr, "glDrawElementsIndirect");
+}
+static void glad_gl_load_GL_ARB_draw_instanced( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_draw_instanced) return;
+ glad_glDrawArraysInstancedARB = (PFNGLDRAWARRAYSINSTANCEDARBPROC) load(userptr, "glDrawArraysInstancedARB");
+ glad_glDrawElementsInstancedARB = (PFNGLDRAWELEMENTSINSTANCEDARBPROC) load(userptr, "glDrawElementsInstancedARB");
+}
+static void glad_gl_load_GL_ARB_fragment_program( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_fragment_program) return;
+ glad_glBindProgramARB = (PFNGLBINDPROGRAMARBPROC) load(userptr, "glBindProgramARB");
+ glad_glDeleteProgramsARB = (PFNGLDELETEPROGRAMSARBPROC) load(userptr, "glDeleteProgramsARB");
+ glad_glGenProgramsARB = (PFNGLGENPROGRAMSARBPROC) load(userptr, "glGenProgramsARB");
+ glad_glGetProgramEnvParameterdvARB = (PFNGLGETPROGRAMENVPARAMETERDVARBPROC) load(userptr, "glGetProgramEnvParameterdvARB");
+ glad_glGetProgramEnvParameterfvARB = (PFNGLGETPROGRAMENVPARAMETERFVARBPROC) load(userptr, "glGetProgramEnvParameterfvARB");
+ glad_glGetProgramLocalParameterdvARB = (PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC) load(userptr, "glGetProgramLocalParameterdvARB");
+ glad_glGetProgramLocalParameterfvARB = (PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC) load(userptr, "glGetProgramLocalParameterfvARB");
+ glad_glGetProgramStringARB = (PFNGLGETPROGRAMSTRINGARBPROC) load(userptr, "glGetProgramStringARB");
+ glad_glGetProgramivARB = (PFNGLGETPROGRAMIVARBPROC) load(userptr, "glGetProgramivARB");
+ glad_glIsProgramARB = (PFNGLISPROGRAMARBPROC) load(userptr, "glIsProgramARB");
+ glad_glProgramEnvParameter4dARB = (PFNGLPROGRAMENVPARAMETER4DARBPROC) load(userptr, "glProgramEnvParameter4dARB");
+ glad_glProgramEnvParameter4dvARB = (PFNGLPROGRAMENVPARAMETER4DVARBPROC) load(userptr, "glProgramEnvParameter4dvARB");
+ glad_glProgramEnvParameter4fARB = (PFNGLPROGRAMENVPARAMETER4FARBPROC) load(userptr, "glProgramEnvParameter4fARB");
+ glad_glProgramEnvParameter4fvARB = (PFNGLPROGRAMENVPARAMETER4FVARBPROC) load(userptr, "glProgramEnvParameter4fvARB");
+ glad_glProgramLocalParameter4dARB = (PFNGLPROGRAMLOCALPARAMETER4DARBPROC) load(userptr, "glProgramLocalParameter4dARB");
+ glad_glProgramLocalParameter4dvARB = (PFNGLPROGRAMLOCALPARAMETER4DVARBPROC) load(userptr, "glProgramLocalParameter4dvARB");
+ glad_glProgramLocalParameter4fARB = (PFNGLPROGRAMLOCALPARAMETER4FARBPROC) load(userptr, "glProgramLocalParameter4fARB");
+ glad_glProgramLocalParameter4fvARB = (PFNGLPROGRAMLOCALPARAMETER4FVARBPROC) load(userptr, "glProgramLocalParameter4fvARB");
+ glad_glProgramStringARB = (PFNGLPROGRAMSTRINGARBPROC) load(userptr, "glProgramStringARB");
+}
+static void glad_gl_load_GL_ARB_framebuffer_no_attachments( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_framebuffer_no_attachments) return;
+ glad_glFramebufferParameteri = (PFNGLFRAMEBUFFERPARAMETERIPROC) load(userptr, "glFramebufferParameteri");
+ glad_glGetFramebufferParameteriv = (PFNGLGETFRAMEBUFFERPARAMETERIVPROC) load(userptr, "glGetFramebufferParameteriv");
+}
+static void glad_gl_load_GL_ARB_framebuffer_object( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_framebuffer_object) return;
+ glad_glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC) load(userptr, "glBindFramebuffer");
+ glad_glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC) load(userptr, "glBindRenderbuffer");
+ glad_glBlitFramebuffer = (PFNGLBLITFRAMEBUFFERPROC) load(userptr, "glBlitFramebuffer");
+ glad_glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC) load(userptr, "glCheckFramebufferStatus");
+ glad_glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC) load(userptr, "glDeleteFramebuffers");
+ glad_glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC) load(userptr, "glDeleteRenderbuffers");
+ glad_glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC) load(userptr, "glFramebufferRenderbuffer");
+ glad_glFramebufferTexture1D = (PFNGLFRAMEBUFFERTEXTURE1DPROC) load(userptr, "glFramebufferTexture1D");
+ glad_glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC) load(userptr, "glFramebufferTexture2D");
+ glad_glFramebufferTexture3D = (PFNGLFRAMEBUFFERTEXTURE3DPROC) load(userptr, "glFramebufferTexture3D");
+ glad_glFramebufferTextureLayer = (PFNGLFRAMEBUFFERTEXTURELAYERPROC) load(userptr, "glFramebufferTextureLayer");
+ glad_glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC) load(userptr, "glGenFramebuffers");
+ glad_glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC) load(userptr, "glGenRenderbuffers");
+ glad_glGenerateMipmap = (PFNGLGENERATEMIPMAPPROC) load(userptr, "glGenerateMipmap");
+ glad_glGetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) load(userptr, "glGetFramebufferAttachmentParameteriv");
+ glad_glGetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIVPROC) load(userptr, "glGetRenderbufferParameteriv");
+ glad_glIsFramebuffer = (PFNGLISFRAMEBUFFERPROC) load(userptr, "glIsFramebuffer");
+ glad_glIsRenderbuffer = (PFNGLISRENDERBUFFERPROC) load(userptr, "glIsRenderbuffer");
+ glad_glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC) load(userptr, "glRenderbufferStorage");
+ glad_glRenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC) load(userptr, "glRenderbufferStorageMultisample");
+}
+static void glad_gl_load_GL_ARB_geometry_shader4( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_geometry_shader4) return;
+ glad_glFramebufferTextureARB = (PFNGLFRAMEBUFFERTEXTUREARBPROC) load(userptr, "glFramebufferTextureARB");
+ glad_glFramebufferTextureFaceARB = (PFNGLFRAMEBUFFERTEXTUREFACEARBPROC) load(userptr, "glFramebufferTextureFaceARB");
+ glad_glFramebufferTextureLayerARB = (PFNGLFRAMEBUFFERTEXTURELAYERARBPROC) load(userptr, "glFramebufferTextureLayerARB");
+ glad_glProgramParameteriARB = (PFNGLPROGRAMPARAMETERIARBPROC) load(userptr, "glProgramParameteriARB");
+}
+static void glad_gl_load_GL_ARB_get_program_binary( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_get_program_binary) return;
+ glad_glGetProgramBinary = (PFNGLGETPROGRAMBINARYPROC) load(userptr, "glGetProgramBinary");
+ glad_glProgramBinary = (PFNGLPROGRAMBINARYPROC) load(userptr, "glProgramBinary");
+ glad_glProgramParameteri = (PFNGLPROGRAMPARAMETERIPROC) load(userptr, "glProgramParameteri");
+}
+static void glad_gl_load_GL_ARB_get_texture_sub_image( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_get_texture_sub_image) return;
+ glad_glGetCompressedTextureSubImage = (PFNGLGETCOMPRESSEDTEXTURESUBIMAGEPROC) load(userptr, "glGetCompressedTextureSubImage");
+ glad_glGetTextureSubImage = (PFNGLGETTEXTURESUBIMAGEPROC) load(userptr, "glGetTextureSubImage");
+}
+static void glad_gl_load_GL_ARB_gl_spirv( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_gl_spirv) return;
+ glad_glSpecializeShaderARB = (PFNGLSPECIALIZESHADERARBPROC) load(userptr, "glSpecializeShaderARB");
+}
+static void glad_gl_load_GL_ARB_gpu_shader_fp64( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_gpu_shader_fp64) return;
+ glad_glGetUniformdv = (PFNGLGETUNIFORMDVPROC) load(userptr, "glGetUniformdv");
+ glad_glUniform1d = (PFNGLUNIFORM1DPROC) load(userptr, "glUniform1d");
+ glad_glUniform1dv = (PFNGLUNIFORM1DVPROC) load(userptr, "glUniform1dv");
+ glad_glUniform2d = (PFNGLUNIFORM2DPROC) load(userptr, "glUniform2d");
+ glad_glUniform2dv = (PFNGLUNIFORM2DVPROC) load(userptr, "glUniform2dv");
+ glad_glUniform3d = (PFNGLUNIFORM3DPROC) load(userptr, "glUniform3d");
+ glad_glUniform3dv = (PFNGLUNIFORM3DVPROC) load(userptr, "glUniform3dv");
+ glad_glUniform4d = (PFNGLUNIFORM4DPROC) load(userptr, "glUniform4d");
+ glad_glUniform4dv = (PFNGLUNIFORM4DVPROC) load(userptr, "glUniform4dv");
+ glad_glUniformMatrix2dv = (PFNGLUNIFORMMATRIX2DVPROC) load(userptr, "glUniformMatrix2dv");
+ glad_glUniformMatrix2x3dv = (PFNGLUNIFORMMATRIX2X3DVPROC) load(userptr, "glUniformMatrix2x3dv");
+ glad_glUniformMatrix2x4dv = (PFNGLUNIFORMMATRIX2X4DVPROC) load(userptr, "glUniformMatrix2x4dv");
+ glad_glUniformMatrix3dv = (PFNGLUNIFORMMATRIX3DVPROC) load(userptr, "glUniformMatrix3dv");
+ glad_glUniformMatrix3x2dv = (PFNGLUNIFORMMATRIX3X2DVPROC) load(userptr, "glUniformMatrix3x2dv");
+ glad_glUniformMatrix3x4dv = (PFNGLUNIFORMMATRIX3X4DVPROC) load(userptr, "glUniformMatrix3x4dv");
+ glad_glUniformMatrix4dv = (PFNGLUNIFORMMATRIX4DVPROC) load(userptr, "glUniformMatrix4dv");
+ glad_glUniformMatrix4x2dv = (PFNGLUNIFORMMATRIX4X2DVPROC) load(userptr, "glUniformMatrix4x2dv");
+ glad_glUniformMatrix4x3dv = (PFNGLUNIFORMMATRIX4X3DVPROC) load(userptr, "glUniformMatrix4x3dv");
+}
+static void glad_gl_load_GL_ARB_gpu_shader_int64( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_gpu_shader_int64) return;
+ glad_glGetUniformi64vARB = (PFNGLGETUNIFORMI64VARBPROC) load(userptr, "glGetUniformi64vARB");
+ glad_glGetUniformui64vARB = (PFNGLGETUNIFORMUI64VARBPROC) load(userptr, "glGetUniformui64vARB");
+ glad_glGetnUniformi64vARB = (PFNGLGETNUNIFORMI64VARBPROC) load(userptr, "glGetnUniformi64vARB");
+ glad_glGetnUniformui64vARB = (PFNGLGETNUNIFORMUI64VARBPROC) load(userptr, "glGetnUniformui64vARB");
+ glad_glProgramUniform1i64ARB = (PFNGLPROGRAMUNIFORM1I64ARBPROC) load(userptr, "glProgramUniform1i64ARB");
+ glad_glProgramUniform1i64vARB = (PFNGLPROGRAMUNIFORM1I64VARBPROC) load(userptr, "glProgramUniform1i64vARB");
+ glad_glProgramUniform1ui64ARB = (PFNGLPROGRAMUNIFORM1UI64ARBPROC) load(userptr, "glProgramUniform1ui64ARB");
+ glad_glProgramUniform1ui64vARB = (PFNGLPROGRAMUNIFORM1UI64VARBPROC) load(userptr, "glProgramUniform1ui64vARB");
+ glad_glProgramUniform2i64ARB = (PFNGLPROGRAMUNIFORM2I64ARBPROC) load(userptr, "glProgramUniform2i64ARB");
+ glad_glProgramUniform2i64vARB = (PFNGLPROGRAMUNIFORM2I64VARBPROC) load(userptr, "glProgramUniform2i64vARB");
+ glad_glProgramUniform2ui64ARB = (PFNGLPROGRAMUNIFORM2UI64ARBPROC) load(userptr, "glProgramUniform2ui64ARB");
+ glad_glProgramUniform2ui64vARB = (PFNGLPROGRAMUNIFORM2UI64VARBPROC) load(userptr, "glProgramUniform2ui64vARB");
+ glad_glProgramUniform3i64ARB = (PFNGLPROGRAMUNIFORM3I64ARBPROC) load(userptr, "glProgramUniform3i64ARB");
+ glad_glProgramUniform3i64vARB = (PFNGLPROGRAMUNIFORM3I64VARBPROC) load(userptr, "glProgramUniform3i64vARB");
+ glad_glProgramUniform3ui64ARB = (PFNGLPROGRAMUNIFORM3UI64ARBPROC) load(userptr, "glProgramUniform3ui64ARB");
+ glad_glProgramUniform3ui64vARB = (PFNGLPROGRAMUNIFORM3UI64VARBPROC) load(userptr, "glProgramUniform3ui64vARB");
+ glad_glProgramUniform4i64ARB = (PFNGLPROGRAMUNIFORM4I64ARBPROC) load(userptr, "glProgramUniform4i64ARB");
+ glad_glProgramUniform4i64vARB = (PFNGLPROGRAMUNIFORM4I64VARBPROC) load(userptr, "glProgramUniform4i64vARB");
+ glad_glProgramUniform4ui64ARB = (PFNGLPROGRAMUNIFORM4UI64ARBPROC) load(userptr, "glProgramUniform4ui64ARB");
+ glad_glProgramUniform4ui64vARB = (PFNGLPROGRAMUNIFORM4UI64VARBPROC) load(userptr, "glProgramUniform4ui64vARB");
+ glad_glUniform1i64ARB = (PFNGLUNIFORM1I64ARBPROC) load(userptr, "glUniform1i64ARB");
+ glad_glUniform1i64vARB = (PFNGLUNIFORM1I64VARBPROC) load(userptr, "glUniform1i64vARB");
+ glad_glUniform1ui64ARB = (PFNGLUNIFORM1UI64ARBPROC) load(userptr, "glUniform1ui64ARB");
+ glad_glUniform1ui64vARB = (PFNGLUNIFORM1UI64VARBPROC) load(userptr, "glUniform1ui64vARB");
+ glad_glUniform2i64ARB = (PFNGLUNIFORM2I64ARBPROC) load(userptr, "glUniform2i64ARB");
+ glad_glUniform2i64vARB = (PFNGLUNIFORM2I64VARBPROC) load(userptr, "glUniform2i64vARB");
+ glad_glUniform2ui64ARB = (PFNGLUNIFORM2UI64ARBPROC) load(userptr, "glUniform2ui64ARB");
+ glad_glUniform2ui64vARB = (PFNGLUNIFORM2UI64VARBPROC) load(userptr, "glUniform2ui64vARB");
+ glad_glUniform3i64ARB = (PFNGLUNIFORM3I64ARBPROC) load(userptr, "glUniform3i64ARB");
+ glad_glUniform3i64vARB = (PFNGLUNIFORM3I64VARBPROC) load(userptr, "glUniform3i64vARB");
+ glad_glUniform3ui64ARB = (PFNGLUNIFORM3UI64ARBPROC) load(userptr, "glUniform3ui64ARB");
+ glad_glUniform3ui64vARB = (PFNGLUNIFORM3UI64VARBPROC) load(userptr, "glUniform3ui64vARB");
+ glad_glUniform4i64ARB = (PFNGLUNIFORM4I64ARBPROC) load(userptr, "glUniform4i64ARB");
+ glad_glUniform4i64vARB = (PFNGLUNIFORM4I64VARBPROC) load(userptr, "glUniform4i64vARB");
+ glad_glUniform4ui64ARB = (PFNGLUNIFORM4UI64ARBPROC) load(userptr, "glUniform4ui64ARB");
+ glad_glUniform4ui64vARB = (PFNGLUNIFORM4UI64VARBPROC) load(userptr, "glUniform4ui64vARB");
+}
+static void glad_gl_load_GL_ARB_instanced_arrays( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_instanced_arrays) return;
+ glad_glVertexAttribDivisorARB = (PFNGLVERTEXATTRIBDIVISORARBPROC) load(userptr, "glVertexAttribDivisorARB");
+}
+static void glad_gl_load_GL_ARB_internalformat_query( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_internalformat_query) return;
+ glad_glGetInternalformativ = (PFNGLGETINTERNALFORMATIVPROC) load(userptr, "glGetInternalformativ");
+}
+static void glad_gl_load_GL_ARB_internalformat_query2( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_internalformat_query2) return;
+ glad_glGetInternalformati64v = (PFNGLGETINTERNALFORMATI64VPROC) load(userptr, "glGetInternalformati64v");
+}
+static void glad_gl_load_GL_ARB_map_buffer_range( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_map_buffer_range) return;
+ glad_glFlushMappedBufferRange = (PFNGLFLUSHMAPPEDBUFFERRANGEPROC) load(userptr, "glFlushMappedBufferRange");
+ glad_glMapBufferRange = (PFNGLMAPBUFFERRANGEPROC) load(userptr, "glMapBufferRange");
+}
+static void glad_gl_load_GL_ARB_multi_bind( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_multi_bind) return;
+ glad_glBindBuffersBase = (PFNGLBINDBUFFERSBASEPROC) load(userptr, "glBindBuffersBase");
+ glad_glBindBuffersRange = (PFNGLBINDBUFFERSRANGEPROC) load(userptr, "glBindBuffersRange");
+ glad_glBindImageTextures = (PFNGLBINDIMAGETEXTURESPROC) load(userptr, "glBindImageTextures");
+ glad_glBindSamplers = (PFNGLBINDSAMPLERSPROC) load(userptr, "glBindSamplers");
+ glad_glBindTextures = (PFNGLBINDTEXTURESPROC) load(userptr, "glBindTextures");
+ glad_glBindVertexBuffers = (PFNGLBINDVERTEXBUFFERSPROC) load(userptr, "glBindVertexBuffers");
+}
+static void glad_gl_load_GL_ARB_multi_draw_indirect( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_multi_draw_indirect) return;
+ glad_glMultiDrawArraysIndirect = (PFNGLMULTIDRAWARRAYSINDIRECTPROC) load(userptr, "glMultiDrawArraysIndirect");
+ glad_glMultiDrawElementsIndirect = (PFNGLMULTIDRAWELEMENTSINDIRECTPROC) load(userptr, "glMultiDrawElementsIndirect");
+}
+static void glad_gl_load_GL_ARB_multisample( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_multisample) return;
+ glad_glSampleCoverageARB = (PFNGLSAMPLECOVERAGEARBPROC) load(userptr, "glSampleCoverageARB");
+}
+static void glad_gl_load_GL_ARB_multitexture( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_multitexture) return;
+ glad_glActiveTextureARB = (PFNGLACTIVETEXTUREARBPROC) load(userptr, "glActiveTextureARB");
+ glad_glClientActiveTextureARB = (PFNGLCLIENTACTIVETEXTUREARBPROC) load(userptr, "glClientActiveTextureARB");
+ glad_glMultiTexCoord1dARB = (PFNGLMULTITEXCOORD1DARBPROC) load(userptr, "glMultiTexCoord1dARB");
+ glad_glMultiTexCoord1dvARB = (PFNGLMULTITEXCOORD1DVARBPROC) load(userptr, "glMultiTexCoord1dvARB");
+ glad_glMultiTexCoord1fARB = (PFNGLMULTITEXCOORD1FARBPROC) load(userptr, "glMultiTexCoord1fARB");
+ glad_glMultiTexCoord1fvARB = (PFNGLMULTITEXCOORD1FVARBPROC) load(userptr, "glMultiTexCoord1fvARB");
+ glad_glMultiTexCoord1iARB = (PFNGLMULTITEXCOORD1IARBPROC) load(userptr, "glMultiTexCoord1iARB");
+ glad_glMultiTexCoord1ivARB = (PFNGLMULTITEXCOORD1IVARBPROC) load(userptr, "glMultiTexCoord1ivARB");
+ glad_glMultiTexCoord1sARB = (PFNGLMULTITEXCOORD1SARBPROC) load(userptr, "glMultiTexCoord1sARB");
+ glad_glMultiTexCoord1svARB = (PFNGLMULTITEXCOORD1SVARBPROC) load(userptr, "glMultiTexCoord1svARB");
+ glad_glMultiTexCoord2dARB = (PFNGLMULTITEXCOORD2DARBPROC) load(userptr, "glMultiTexCoord2dARB");
+ glad_glMultiTexCoord2dvARB = (PFNGLMULTITEXCOORD2DVARBPROC) load(userptr, "glMultiTexCoord2dvARB");
+ glad_glMultiTexCoord2fARB = (PFNGLMULTITEXCOORD2FARBPROC) load(userptr, "glMultiTexCoord2fARB");
+ glad_glMultiTexCoord2fvARB = (PFNGLMULTITEXCOORD2FVARBPROC) load(userptr, "glMultiTexCoord2fvARB");
+ glad_glMultiTexCoord2iARB = (PFNGLMULTITEXCOORD2IARBPROC) load(userptr, "glMultiTexCoord2iARB");
+ glad_glMultiTexCoord2ivARB = (PFNGLMULTITEXCOORD2IVARBPROC) load(userptr, "glMultiTexCoord2ivARB");
+ glad_glMultiTexCoord2sARB = (PFNGLMULTITEXCOORD2SARBPROC) load(userptr, "glMultiTexCoord2sARB");
+ glad_glMultiTexCoord2svARB = (PFNGLMULTITEXCOORD2SVARBPROC) load(userptr, "glMultiTexCoord2svARB");
+ glad_glMultiTexCoord3dARB = (PFNGLMULTITEXCOORD3DARBPROC) load(userptr, "glMultiTexCoord3dARB");
+ glad_glMultiTexCoord3dvARB = (PFNGLMULTITEXCOORD3DVARBPROC) load(userptr, "glMultiTexCoord3dvARB");
+ glad_glMultiTexCoord3fARB = (PFNGLMULTITEXCOORD3FARBPROC) load(userptr, "glMultiTexCoord3fARB");
+ glad_glMultiTexCoord3fvARB = (PFNGLMULTITEXCOORD3FVARBPROC) load(userptr, "glMultiTexCoord3fvARB");
+ glad_glMultiTexCoord3iARB = (PFNGLMULTITEXCOORD3IARBPROC) load(userptr, "glMultiTexCoord3iARB");
+ glad_glMultiTexCoord3ivARB = (PFNGLMULTITEXCOORD3IVARBPROC) load(userptr, "glMultiTexCoord3ivARB");
+ glad_glMultiTexCoord3sARB = (PFNGLMULTITEXCOORD3SARBPROC) load(userptr, "glMultiTexCoord3sARB");
+ glad_glMultiTexCoord3svARB = (PFNGLMULTITEXCOORD3SVARBPROC) load(userptr, "glMultiTexCoord3svARB");
+ glad_glMultiTexCoord4dARB = (PFNGLMULTITEXCOORD4DARBPROC) load(userptr, "glMultiTexCoord4dARB");
+ glad_glMultiTexCoord4dvARB = (PFNGLMULTITEXCOORD4DVARBPROC) load(userptr, "glMultiTexCoord4dvARB");
+ glad_glMultiTexCoord4fARB = (PFNGLMULTITEXCOORD4FARBPROC) load(userptr, "glMultiTexCoord4fARB");
+ glad_glMultiTexCoord4fvARB = (PFNGLMULTITEXCOORD4FVARBPROC) load(userptr, "glMultiTexCoord4fvARB");
+ glad_glMultiTexCoord4iARB = (PFNGLMULTITEXCOORD4IARBPROC) load(userptr, "glMultiTexCoord4iARB");
+ glad_glMultiTexCoord4ivARB = (PFNGLMULTITEXCOORD4IVARBPROC) load(userptr, "glMultiTexCoord4ivARB");
+ glad_glMultiTexCoord4sARB = (PFNGLMULTITEXCOORD4SARBPROC) load(userptr, "glMultiTexCoord4sARB");
+ glad_glMultiTexCoord4svARB = (PFNGLMULTITEXCOORD4SVARBPROC) load(userptr, "glMultiTexCoord4svARB");
+}
+static void glad_gl_load_GL_ARB_occlusion_query( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_occlusion_query) return;
+ glad_glBeginQueryARB = (PFNGLBEGINQUERYARBPROC) load(userptr, "glBeginQueryARB");
+ glad_glDeleteQueriesARB = (PFNGLDELETEQUERIESARBPROC) load(userptr, "glDeleteQueriesARB");
+ glad_glEndQueryARB = (PFNGLENDQUERYARBPROC) load(userptr, "glEndQueryARB");
+ glad_glGenQueriesARB = (PFNGLGENQUERIESARBPROC) load(userptr, "glGenQueriesARB");
+ glad_glGetQueryObjectivARB = (PFNGLGETQUERYOBJECTIVARBPROC) load(userptr, "glGetQueryObjectivARB");
+ glad_glGetQueryObjectuivARB = (PFNGLGETQUERYOBJECTUIVARBPROC) load(userptr, "glGetQueryObjectuivARB");
+ glad_glGetQueryivARB = (PFNGLGETQUERYIVARBPROC) load(userptr, "glGetQueryivARB");
+ glad_glIsQueryARB = (PFNGLISQUERYARBPROC) load(userptr, "glIsQueryARB");
+}
+static void glad_gl_load_GL_ARB_sample_locations( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_sample_locations) return;
+ glad_glEvaluateDepthValuesARB = (PFNGLEVALUATEDEPTHVALUESARBPROC) load(userptr, "glEvaluateDepthValuesARB");
+ glad_glFramebufferSampleLocationsfvARB = (PFNGLFRAMEBUFFERSAMPLELOCATIONSFVARBPROC) load(userptr, "glFramebufferSampleLocationsfvARB");
+ glad_glNamedFramebufferSampleLocationsfvARB = (PFNGLNAMEDFRAMEBUFFERSAMPLELOCATIONSFVARBPROC) load(userptr, "glNamedFramebufferSampleLocationsfvARB");
+}
+static void glad_gl_load_GL_ARB_sample_shading( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_sample_shading) return;
+ glad_glMinSampleShadingARB = (PFNGLMINSAMPLESHADINGARBPROC) load(userptr, "glMinSampleShadingARB");
+}
+static void glad_gl_load_GL_ARB_shader_atomic_counters( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_shader_atomic_counters) return;
+ glad_glGetActiveAtomicCounterBufferiv = (PFNGLGETACTIVEATOMICCOUNTERBUFFERIVPROC) load(userptr, "glGetActiveAtomicCounterBufferiv");
+}
+static void glad_gl_load_GL_ARB_shader_image_load_store( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_shader_image_load_store) return;
+ glad_glBindImageTexture = (PFNGLBINDIMAGETEXTUREPROC) load(userptr, "glBindImageTexture");
+ glad_glMemoryBarrier = (PFNGLMEMORYBARRIERPROC) load(userptr, "glMemoryBarrier");
+}
+static void glad_gl_load_GL_ARB_shader_objects( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_shader_objects) return;
+ glad_glAttachObjectARB = (PFNGLATTACHOBJECTARBPROC) load(userptr, "glAttachObjectARB");
+ glad_glCompileShaderARB = (PFNGLCOMPILESHADERARBPROC) load(userptr, "glCompileShaderARB");
+ glad_glCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC) load(userptr, "glCreateProgramObjectARB");
+ glad_glCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC) load(userptr, "glCreateShaderObjectARB");
+ glad_glDeleteObjectARB = (PFNGLDELETEOBJECTARBPROC) load(userptr, "glDeleteObjectARB");
+ glad_glDetachObjectARB = (PFNGLDETACHOBJECTARBPROC) load(userptr, "glDetachObjectARB");
+ glad_glGetActiveUniformARB = (PFNGLGETACTIVEUNIFORMARBPROC) load(userptr, "glGetActiveUniformARB");
+ glad_glGetAttachedObjectsARB = (PFNGLGETATTACHEDOBJECTSARBPROC) load(userptr, "glGetAttachedObjectsARB");
+ glad_glGetHandleARB = (PFNGLGETHANDLEARBPROC) load(userptr, "glGetHandleARB");
+ glad_glGetInfoLogARB = (PFNGLGETINFOLOGARBPROC) load(userptr, "glGetInfoLogARB");
+ glad_glGetObjectParameterfvARB = (PFNGLGETOBJECTPARAMETERFVARBPROC) load(userptr, "glGetObjectParameterfvARB");
+ glad_glGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC) load(userptr, "glGetObjectParameterivARB");
+ glad_glGetShaderSourceARB = (PFNGLGETSHADERSOURCEARBPROC) load(userptr, "glGetShaderSourceARB");
+ glad_glGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC) load(userptr, "glGetUniformLocationARB");
+ glad_glGetUniformfvARB = (PFNGLGETUNIFORMFVARBPROC) load(userptr, "glGetUniformfvARB");
+ glad_glGetUniformivARB = (PFNGLGETUNIFORMIVARBPROC) load(userptr, "glGetUniformivARB");
+ glad_glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC) load(userptr, "glLinkProgramARB");
+ glad_glShaderSourceARB = (PFNGLSHADERSOURCEARBPROC) load(userptr, "glShaderSourceARB");
+ glad_glUniform1fARB = (PFNGLUNIFORM1FARBPROC) load(userptr, "glUniform1fARB");
+ glad_glUniform1fvARB = (PFNGLUNIFORM1FVARBPROC) load(userptr, "glUniform1fvARB");
+ glad_glUniform1iARB = (PFNGLUNIFORM1IARBPROC) load(userptr, "glUniform1iARB");
+ glad_glUniform1ivARB = (PFNGLUNIFORM1IVARBPROC) load(userptr, "glUniform1ivARB");
+ glad_glUniform2fARB = (PFNGLUNIFORM2FARBPROC) load(userptr, "glUniform2fARB");
+ glad_glUniform2fvARB = (PFNGLUNIFORM2FVARBPROC) load(userptr, "glUniform2fvARB");
+ glad_glUniform2iARB = (PFNGLUNIFORM2IARBPROC) load(userptr, "glUniform2iARB");
+ glad_glUniform2ivARB = (PFNGLUNIFORM2IVARBPROC) load(userptr, "glUniform2ivARB");
+ glad_glUniform3fARB = (PFNGLUNIFORM3FARBPROC) load(userptr, "glUniform3fARB");
+ glad_glUniform3fvARB = (PFNGLUNIFORM3FVARBPROC) load(userptr, "glUniform3fvARB");
+ glad_glUniform3iARB = (PFNGLUNIFORM3IARBPROC) load(userptr, "glUniform3iARB");
+ glad_glUniform3ivARB = (PFNGLUNIFORM3IVARBPROC) load(userptr, "glUniform3ivARB");
+ glad_glUniform4fARB = (PFNGLUNIFORM4FARBPROC) load(userptr, "glUniform4fARB");
+ glad_glUniform4fvARB = (PFNGLUNIFORM4FVARBPROC) load(userptr, "glUniform4fvARB");
+ glad_glUniform4iARB = (PFNGLUNIFORM4IARBPROC) load(userptr, "glUniform4iARB");
+ glad_glUniform4ivARB = (PFNGLUNIFORM4IVARBPROC) load(userptr, "glUniform4ivARB");
+ glad_glUniformMatrix2fvARB = (PFNGLUNIFORMMATRIX2FVARBPROC) load(userptr, "glUniformMatrix2fvARB");
+ glad_glUniformMatrix3fvARB = (PFNGLUNIFORMMATRIX3FVARBPROC) load(userptr, "glUniformMatrix3fvARB");
+ glad_glUniformMatrix4fvARB = (PFNGLUNIFORMMATRIX4FVARBPROC) load(userptr, "glUniformMatrix4fvARB");
+ glad_glUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC) load(userptr, "glUseProgramObjectARB");
+ glad_glValidateProgramARB = (PFNGLVALIDATEPROGRAMARBPROC) load(userptr, "glValidateProgramARB");
+}
+static void glad_gl_load_GL_ARB_shader_storage_buffer_object( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_shader_storage_buffer_object) return;
+ glad_glShaderStorageBlockBinding = (PFNGLSHADERSTORAGEBLOCKBINDINGPROC) load(userptr, "glShaderStorageBlockBinding");
+}
+static void glad_gl_load_GL_ARB_shading_language_include( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_shading_language_include) return;
+ glad_glCompileShaderIncludeARB = (PFNGLCOMPILESHADERINCLUDEARBPROC) load(userptr, "glCompileShaderIncludeARB");
+ glad_glDeleteNamedStringARB = (PFNGLDELETENAMEDSTRINGARBPROC) load(userptr, "glDeleteNamedStringARB");
+ glad_glGetNamedStringARB = (PFNGLGETNAMEDSTRINGARBPROC) load(userptr, "glGetNamedStringARB");
+ glad_glGetNamedStringivARB = (PFNGLGETNAMEDSTRINGIVARBPROC) load(userptr, "glGetNamedStringivARB");
+ glad_glIsNamedStringARB = (PFNGLISNAMEDSTRINGARBPROC) load(userptr, "glIsNamedStringARB");
+ glad_glNamedStringARB = (PFNGLNAMEDSTRINGARBPROC) load(userptr, "glNamedStringARB");
+}
+static void glad_gl_load_GL_ARB_tessellation_shader( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_tessellation_shader) return;
+ glad_glPatchParameterfv = (PFNGLPATCHPARAMETERFVPROC) load(userptr, "glPatchParameterfv");
+ glad_glPatchParameteri = (PFNGLPATCHPARAMETERIPROC) load(userptr, "glPatchParameteri");
+}
+static void glad_gl_load_GL_ARB_texture_compression( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_texture_compression) return;
+ glad_glCompressedTexImage1DARB = (PFNGLCOMPRESSEDTEXIMAGE1DARBPROC) load(userptr, "glCompressedTexImage1DARB");
+ glad_glCompressedTexImage2DARB = (PFNGLCOMPRESSEDTEXIMAGE2DARBPROC) load(userptr, "glCompressedTexImage2DARB");
+ glad_glCompressedTexImage3DARB = (PFNGLCOMPRESSEDTEXIMAGE3DARBPROC) load(userptr, "glCompressedTexImage3DARB");
+ glad_glCompressedTexSubImage1DARB = (PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC) load(userptr, "glCompressedTexSubImage1DARB");
+ glad_glCompressedTexSubImage2DARB = (PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC) load(userptr, "glCompressedTexSubImage2DARB");
+ glad_glCompressedTexSubImage3DARB = (PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC) load(userptr, "glCompressedTexSubImage3DARB");
+ glad_glGetCompressedTexImageARB = (PFNGLGETCOMPRESSEDTEXIMAGEARBPROC) load(userptr, "glGetCompressedTexImageARB");
+}
+static void glad_gl_load_GL_ARB_texture_multisample( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_texture_multisample) return;
+ glad_glGetMultisamplefv = (PFNGLGETMULTISAMPLEFVPROC) load(userptr, "glGetMultisamplefv");
+ glad_glSampleMaski = (PFNGLSAMPLEMASKIPROC) load(userptr, "glSampleMaski");
+ glad_glTexImage2DMultisample = (PFNGLTEXIMAGE2DMULTISAMPLEPROC) load(userptr, "glTexImage2DMultisample");
+ glad_glTexImage3DMultisample = (PFNGLTEXIMAGE3DMULTISAMPLEPROC) load(userptr, "glTexImage3DMultisample");
+}
+static void glad_gl_load_GL_ARB_texture_storage( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_texture_storage) return;
+ glad_glTexStorage1D = (PFNGLTEXSTORAGE1DPROC) load(userptr, "glTexStorage1D");
+ glad_glTexStorage2D = (PFNGLTEXSTORAGE2DPROC) load(userptr, "glTexStorage2D");
+ glad_glTexStorage3D = (PFNGLTEXSTORAGE3DPROC) load(userptr, "glTexStorage3D");
+}
+static void glad_gl_load_GL_ARB_texture_view( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_texture_view) return;
+ glad_glTextureView = (PFNGLTEXTUREVIEWPROC) load(userptr, "glTextureView");
+}
+static void glad_gl_load_GL_ARB_timer_query( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_timer_query) return;
+ glad_glGetQueryObjecti64v = (PFNGLGETQUERYOBJECTI64VPROC) load(userptr, "glGetQueryObjecti64v");
+ glad_glGetQueryObjectui64v = (PFNGLGETQUERYOBJECTUI64VPROC) load(userptr, "glGetQueryObjectui64v");
+ glad_glQueryCounter = (PFNGLQUERYCOUNTERPROC) load(userptr, "glQueryCounter");
+}
+static void glad_gl_load_GL_ARB_transpose_matrix( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_transpose_matrix) return;
+ glad_glLoadTransposeMatrixdARB = (PFNGLLOADTRANSPOSEMATRIXDARBPROC) load(userptr, "glLoadTransposeMatrixdARB");
+ glad_glLoadTransposeMatrixfARB = (PFNGLLOADTRANSPOSEMATRIXFARBPROC) load(userptr, "glLoadTransposeMatrixfARB");
+ glad_glMultTransposeMatrixdARB = (PFNGLMULTTRANSPOSEMATRIXDARBPROC) load(userptr, "glMultTransposeMatrixdARB");
+ glad_glMultTransposeMatrixfARB = (PFNGLMULTTRANSPOSEMATRIXFARBPROC) load(userptr, "glMultTransposeMatrixfARB");
+}
+static void glad_gl_load_GL_ARB_uniform_buffer_object( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_uniform_buffer_object) return;
+ glad_glBindBufferBase = (PFNGLBINDBUFFERBASEPROC) load(userptr, "glBindBufferBase");
+ glad_glBindBufferRange = (PFNGLBINDBUFFERRANGEPROC) load(userptr, "glBindBufferRange");
+ glad_glGetActiveUniformBlockName = (PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC) load(userptr, "glGetActiveUniformBlockName");
+ glad_glGetActiveUniformBlockiv = (PFNGLGETACTIVEUNIFORMBLOCKIVPROC) load(userptr, "glGetActiveUniformBlockiv");
+ glad_glGetActiveUniformName = (PFNGLGETACTIVEUNIFORMNAMEPROC) load(userptr, "glGetActiveUniformName");
+ glad_glGetActiveUniformsiv = (PFNGLGETACTIVEUNIFORMSIVPROC) load(userptr, "glGetActiveUniformsiv");
+ glad_glGetIntegeri_v = (PFNGLGETINTEGERI_VPROC) load(userptr, "glGetIntegeri_v");
+ glad_glGetUniformBlockIndex = (PFNGLGETUNIFORMBLOCKINDEXPROC) load(userptr, "glGetUniformBlockIndex");
+ glad_glGetUniformIndices = (PFNGLGETUNIFORMINDICESPROC) load(userptr, "glGetUniformIndices");
+ glad_glUniformBlockBinding = (PFNGLUNIFORMBLOCKBINDINGPROC) load(userptr, "glUniformBlockBinding");
+}
+static void glad_gl_load_GL_ARB_vertex_array_object( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_vertex_array_object) return;
+ glad_glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC) load(userptr, "glBindVertexArray");
+ glad_glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSPROC) load(userptr, "glDeleteVertexArrays");
+ glad_glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC) load(userptr, "glGenVertexArrays");
+ glad_glIsVertexArray = (PFNGLISVERTEXARRAYPROC) load(userptr, "glIsVertexArray");
+}
+static void glad_gl_load_GL_ARB_vertex_attrib_binding( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_vertex_attrib_binding) return;
+ glad_glBindVertexBuffer = (PFNGLBINDVERTEXBUFFERPROC) load(userptr, "glBindVertexBuffer");
+ glad_glVertexAttribBinding = (PFNGLVERTEXATTRIBBINDINGPROC) load(userptr, "glVertexAttribBinding");
+ glad_glVertexAttribFormat = (PFNGLVERTEXATTRIBFORMATPROC) load(userptr, "glVertexAttribFormat");
+ glad_glVertexAttribIFormat = (PFNGLVERTEXATTRIBIFORMATPROC) load(userptr, "glVertexAttribIFormat");
+ glad_glVertexAttribLFormat = (PFNGLVERTEXATTRIBLFORMATPROC) load(userptr, "glVertexAttribLFormat");
+ glad_glVertexBindingDivisor = (PFNGLVERTEXBINDINGDIVISORPROC) load(userptr, "glVertexBindingDivisor");
+}
+static void glad_gl_load_GL_ARB_vertex_buffer_object( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_vertex_buffer_object) return;
+ glad_glBindBufferARB = (PFNGLBINDBUFFERARBPROC) load(userptr, "glBindBufferARB");
+ glad_glBufferDataARB = (PFNGLBUFFERDATAARBPROC) load(userptr, "glBufferDataARB");
+ glad_glBufferSubDataARB = (PFNGLBUFFERSUBDATAARBPROC) load(userptr, "glBufferSubDataARB");
+ glad_glDeleteBuffersARB = (PFNGLDELETEBUFFERSARBPROC) load(userptr, "glDeleteBuffersARB");
+ glad_glGenBuffersARB = (PFNGLGENBUFFERSARBPROC) load(userptr, "glGenBuffersARB");
+ glad_glGetBufferParameterivARB = (PFNGLGETBUFFERPARAMETERIVARBPROC) load(userptr, "glGetBufferParameterivARB");
+ glad_glGetBufferPointervARB = (PFNGLGETBUFFERPOINTERVARBPROC) load(userptr, "glGetBufferPointervARB");
+ glad_glGetBufferSubDataARB = (PFNGLGETBUFFERSUBDATAARBPROC) load(userptr, "glGetBufferSubDataARB");
+ glad_glIsBufferARB = (PFNGLISBUFFERARBPROC) load(userptr, "glIsBufferARB");
+ glad_glMapBufferARB = (PFNGLMAPBUFFERARBPROC) load(userptr, "glMapBufferARB");
+ glad_glUnmapBufferARB = (PFNGLUNMAPBUFFERARBPROC) load(userptr, "glUnmapBufferARB");
+}
+static void glad_gl_load_GL_ARB_vertex_program( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_vertex_program) return;
+ glad_glBindProgramARB = (PFNGLBINDPROGRAMARBPROC) load(userptr, "glBindProgramARB");
+ glad_glDeleteProgramsARB = (PFNGLDELETEPROGRAMSARBPROC) load(userptr, "glDeleteProgramsARB");
+ glad_glDisableVertexAttribArrayARB = (PFNGLDISABLEVERTEXATTRIBARRAYARBPROC) load(userptr, "glDisableVertexAttribArrayARB");
+ glad_glEnableVertexAttribArrayARB = (PFNGLENABLEVERTEXATTRIBARRAYARBPROC) load(userptr, "glEnableVertexAttribArrayARB");
+ glad_glGenProgramsARB = (PFNGLGENPROGRAMSARBPROC) load(userptr, "glGenProgramsARB");
+ glad_glGetProgramEnvParameterdvARB = (PFNGLGETPROGRAMENVPARAMETERDVARBPROC) load(userptr, "glGetProgramEnvParameterdvARB");
+ glad_glGetProgramEnvParameterfvARB = (PFNGLGETPROGRAMENVPARAMETERFVARBPROC) load(userptr, "glGetProgramEnvParameterfvARB");
+ glad_glGetProgramLocalParameterdvARB = (PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC) load(userptr, "glGetProgramLocalParameterdvARB");
+ glad_glGetProgramLocalParameterfvARB = (PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC) load(userptr, "glGetProgramLocalParameterfvARB");
+ glad_glGetProgramStringARB = (PFNGLGETPROGRAMSTRINGARBPROC) load(userptr, "glGetProgramStringARB");
+ glad_glGetProgramivARB = (PFNGLGETPROGRAMIVARBPROC) load(userptr, "glGetProgramivARB");
+ glad_glGetVertexAttribPointervARB = (PFNGLGETVERTEXATTRIBPOINTERVARBPROC) load(userptr, "glGetVertexAttribPointervARB");
+ glad_glGetVertexAttribdvARB = (PFNGLGETVERTEXATTRIBDVARBPROC) load(userptr, "glGetVertexAttribdvARB");
+ glad_glGetVertexAttribfvARB = (PFNGLGETVERTEXATTRIBFVARBPROC) load(userptr, "glGetVertexAttribfvARB");
+ glad_glGetVertexAttribivARB = (PFNGLGETVERTEXATTRIBIVARBPROC) load(userptr, "glGetVertexAttribivARB");
+ glad_glIsProgramARB = (PFNGLISPROGRAMARBPROC) load(userptr, "glIsProgramARB");
+ glad_glProgramEnvParameter4dARB = (PFNGLPROGRAMENVPARAMETER4DARBPROC) load(userptr, "glProgramEnvParameter4dARB");
+ glad_glProgramEnvParameter4dvARB = (PFNGLPROGRAMENVPARAMETER4DVARBPROC) load(userptr, "glProgramEnvParameter4dvARB");
+ glad_glProgramEnvParameter4fARB = (PFNGLPROGRAMENVPARAMETER4FARBPROC) load(userptr, "glProgramEnvParameter4fARB");
+ glad_glProgramEnvParameter4fvARB = (PFNGLPROGRAMENVPARAMETER4FVARBPROC) load(userptr, "glProgramEnvParameter4fvARB");
+ glad_glProgramLocalParameter4dARB = (PFNGLPROGRAMLOCALPARAMETER4DARBPROC) load(userptr, "glProgramLocalParameter4dARB");
+ glad_glProgramLocalParameter4dvARB = (PFNGLPROGRAMLOCALPARAMETER4DVARBPROC) load(userptr, "glProgramLocalParameter4dvARB");
+ glad_glProgramLocalParameter4fARB = (PFNGLPROGRAMLOCALPARAMETER4FARBPROC) load(userptr, "glProgramLocalParameter4fARB");
+ glad_glProgramLocalParameter4fvARB = (PFNGLPROGRAMLOCALPARAMETER4FVARBPROC) load(userptr, "glProgramLocalParameter4fvARB");
+ glad_glProgramStringARB = (PFNGLPROGRAMSTRINGARBPROC) load(userptr, "glProgramStringARB");
+ glad_glVertexAttrib1dARB = (PFNGLVERTEXATTRIB1DARBPROC) load(userptr, "glVertexAttrib1dARB");
+ glad_glVertexAttrib1dvARB = (PFNGLVERTEXATTRIB1DVARBPROC) load(userptr, "glVertexAttrib1dvARB");
+ glad_glVertexAttrib1fARB = (PFNGLVERTEXATTRIB1FARBPROC) load(userptr, "glVertexAttrib1fARB");
+ glad_glVertexAttrib1fvARB = (PFNGLVERTEXATTRIB1FVARBPROC) load(userptr, "glVertexAttrib1fvARB");
+ glad_glVertexAttrib1sARB = (PFNGLVERTEXATTRIB1SARBPROC) load(userptr, "glVertexAttrib1sARB");
+ glad_glVertexAttrib1svARB = (PFNGLVERTEXATTRIB1SVARBPROC) load(userptr, "glVertexAttrib1svARB");
+ glad_glVertexAttrib2dARB = (PFNGLVERTEXATTRIB2DARBPROC) load(userptr, "glVertexAttrib2dARB");
+ glad_glVertexAttrib2dvARB = (PFNGLVERTEXATTRIB2DVARBPROC) load(userptr, "glVertexAttrib2dvARB");
+ glad_glVertexAttrib2fARB = (PFNGLVERTEXATTRIB2FARBPROC) load(userptr, "glVertexAttrib2fARB");
+ glad_glVertexAttrib2fvARB = (PFNGLVERTEXATTRIB2FVARBPROC) load(userptr, "glVertexAttrib2fvARB");
+ glad_glVertexAttrib2sARB = (PFNGLVERTEXATTRIB2SARBPROC) load(userptr, "glVertexAttrib2sARB");
+ glad_glVertexAttrib2svARB = (PFNGLVERTEXATTRIB2SVARBPROC) load(userptr, "glVertexAttrib2svARB");
+ glad_glVertexAttrib3dARB = (PFNGLVERTEXATTRIB3DARBPROC) load(userptr, "glVertexAttrib3dARB");
+ glad_glVertexAttrib3dvARB = (PFNGLVERTEXATTRIB3DVARBPROC) load(userptr, "glVertexAttrib3dvARB");
+ glad_glVertexAttrib3fARB = (PFNGLVERTEXATTRIB3FARBPROC) load(userptr, "glVertexAttrib3fARB");
+ glad_glVertexAttrib3fvARB = (PFNGLVERTEXATTRIB3FVARBPROC) load(userptr, "glVertexAttrib3fvARB");
+ glad_glVertexAttrib3sARB = (PFNGLVERTEXATTRIB3SARBPROC) load(userptr, "glVertexAttrib3sARB");
+ glad_glVertexAttrib3svARB = (PFNGLVERTEXATTRIB3SVARBPROC) load(userptr, "glVertexAttrib3svARB");
+ glad_glVertexAttrib4NbvARB = (PFNGLVERTEXATTRIB4NBVARBPROC) load(userptr, "glVertexAttrib4NbvARB");
+ glad_glVertexAttrib4NivARB = (PFNGLVERTEXATTRIB4NIVARBPROC) load(userptr, "glVertexAttrib4NivARB");
+ glad_glVertexAttrib4NsvARB = (PFNGLVERTEXATTRIB4NSVARBPROC) load(userptr, "glVertexAttrib4NsvARB");
+ glad_glVertexAttrib4NubARB = (PFNGLVERTEXATTRIB4NUBARBPROC) load(userptr, "glVertexAttrib4NubARB");
+ glad_glVertexAttrib4NubvARB = (PFNGLVERTEXATTRIB4NUBVARBPROC) load(userptr, "glVertexAttrib4NubvARB");
+ glad_glVertexAttrib4NuivARB = (PFNGLVERTEXATTRIB4NUIVARBPROC) load(userptr, "glVertexAttrib4NuivARB");
+ glad_glVertexAttrib4NusvARB = (PFNGLVERTEXATTRIB4NUSVARBPROC) load(userptr, "glVertexAttrib4NusvARB");
+ glad_glVertexAttrib4bvARB = (PFNGLVERTEXATTRIB4BVARBPROC) load(userptr, "glVertexAttrib4bvARB");
+ glad_glVertexAttrib4dARB = (PFNGLVERTEXATTRIB4DARBPROC) load(userptr, "glVertexAttrib4dARB");
+ glad_glVertexAttrib4dvARB = (PFNGLVERTEXATTRIB4DVARBPROC) load(userptr, "glVertexAttrib4dvARB");
+ glad_glVertexAttrib4fARB = (PFNGLVERTEXATTRIB4FARBPROC) load(userptr, "glVertexAttrib4fARB");
+ glad_glVertexAttrib4fvARB = (PFNGLVERTEXATTRIB4FVARBPROC) load(userptr, "glVertexAttrib4fvARB");
+ glad_glVertexAttrib4ivARB = (PFNGLVERTEXATTRIB4IVARBPROC) load(userptr, "glVertexAttrib4ivARB");
+ glad_glVertexAttrib4sARB = (PFNGLVERTEXATTRIB4SARBPROC) load(userptr, "glVertexAttrib4sARB");
+ glad_glVertexAttrib4svARB = (PFNGLVERTEXATTRIB4SVARBPROC) load(userptr, "glVertexAttrib4svARB");
+ glad_glVertexAttrib4ubvARB = (PFNGLVERTEXATTRIB4UBVARBPROC) load(userptr, "glVertexAttrib4ubvARB");
+ glad_glVertexAttrib4uivARB = (PFNGLVERTEXATTRIB4UIVARBPROC) load(userptr, "glVertexAttrib4uivARB");
+ glad_glVertexAttrib4usvARB = (PFNGLVERTEXATTRIB4USVARBPROC) load(userptr, "glVertexAttrib4usvARB");
+ glad_glVertexAttribPointerARB = (PFNGLVERTEXATTRIBPOINTERARBPROC) load(userptr, "glVertexAttribPointerARB");
+}
+static void glad_gl_load_GL_ARB_vertex_shader( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ARB_vertex_shader) return;
+ glad_glBindAttribLocationARB = (PFNGLBINDATTRIBLOCATIONARBPROC) load(userptr, "glBindAttribLocationARB");
+ glad_glDisableVertexAttribArrayARB = (PFNGLDISABLEVERTEXATTRIBARRAYARBPROC) load(userptr, "glDisableVertexAttribArrayARB");
+ glad_glEnableVertexAttribArrayARB = (PFNGLENABLEVERTEXATTRIBARRAYARBPROC) load(userptr, "glEnableVertexAttribArrayARB");
+ glad_glGetActiveAttribARB = (PFNGLGETACTIVEATTRIBARBPROC) load(userptr, "glGetActiveAttribARB");
+ glad_glGetAttribLocationARB = (PFNGLGETATTRIBLOCATIONARBPROC) load(userptr, "glGetAttribLocationARB");
+ glad_glGetVertexAttribPointervARB = (PFNGLGETVERTEXATTRIBPOINTERVARBPROC) load(userptr, "glGetVertexAttribPointervARB");
+ glad_glGetVertexAttribdvARB = (PFNGLGETVERTEXATTRIBDVARBPROC) load(userptr, "glGetVertexAttribdvARB");
+ glad_glGetVertexAttribfvARB = (PFNGLGETVERTEXATTRIBFVARBPROC) load(userptr, "glGetVertexAttribfvARB");
+ glad_glGetVertexAttribivARB = (PFNGLGETVERTEXATTRIBIVARBPROC) load(userptr, "glGetVertexAttribivARB");
+ glad_glVertexAttrib1dARB = (PFNGLVERTEXATTRIB1DARBPROC) load(userptr, "glVertexAttrib1dARB");
+ glad_glVertexAttrib1dvARB = (PFNGLVERTEXATTRIB1DVARBPROC) load(userptr, "glVertexAttrib1dvARB");
+ glad_glVertexAttrib1fARB = (PFNGLVERTEXATTRIB1FARBPROC) load(userptr, "glVertexAttrib1fARB");
+ glad_glVertexAttrib1fvARB = (PFNGLVERTEXATTRIB1FVARBPROC) load(userptr, "glVertexAttrib1fvARB");
+ glad_glVertexAttrib1sARB = (PFNGLVERTEXATTRIB1SARBPROC) load(userptr, "glVertexAttrib1sARB");
+ glad_glVertexAttrib1svARB = (PFNGLVERTEXATTRIB1SVARBPROC) load(userptr, "glVertexAttrib1svARB");
+ glad_glVertexAttrib2dARB = (PFNGLVERTEXATTRIB2DARBPROC) load(userptr, "glVertexAttrib2dARB");
+ glad_glVertexAttrib2dvARB = (PFNGLVERTEXATTRIB2DVARBPROC) load(userptr, "glVertexAttrib2dvARB");
+ glad_glVertexAttrib2fARB = (PFNGLVERTEXATTRIB2FARBPROC) load(userptr, "glVertexAttrib2fARB");
+ glad_glVertexAttrib2fvARB = (PFNGLVERTEXATTRIB2FVARBPROC) load(userptr, "glVertexAttrib2fvARB");
+ glad_glVertexAttrib2sARB = (PFNGLVERTEXATTRIB2SARBPROC) load(userptr, "glVertexAttrib2sARB");
+ glad_glVertexAttrib2svARB = (PFNGLVERTEXATTRIB2SVARBPROC) load(userptr, "glVertexAttrib2svARB");
+ glad_glVertexAttrib3dARB = (PFNGLVERTEXATTRIB3DARBPROC) load(userptr, "glVertexAttrib3dARB");
+ glad_glVertexAttrib3dvARB = (PFNGLVERTEXATTRIB3DVARBPROC) load(userptr, "glVertexAttrib3dvARB");
+ glad_glVertexAttrib3fARB = (PFNGLVERTEXATTRIB3FARBPROC) load(userptr, "glVertexAttrib3fARB");
+ glad_glVertexAttrib3fvARB = (PFNGLVERTEXATTRIB3FVARBPROC) load(userptr, "glVertexAttrib3fvARB");
+ glad_glVertexAttrib3sARB = (PFNGLVERTEXATTRIB3SARBPROC) load(userptr, "glVertexAttrib3sARB");
+ glad_glVertexAttrib3svARB = (PFNGLVERTEXATTRIB3SVARBPROC) load(userptr, "glVertexAttrib3svARB");
+ glad_glVertexAttrib4NbvARB = (PFNGLVERTEXATTRIB4NBVARBPROC) load(userptr, "glVertexAttrib4NbvARB");
+ glad_glVertexAttrib4NivARB = (PFNGLVERTEXATTRIB4NIVARBPROC) load(userptr, "glVertexAttrib4NivARB");
+ glad_glVertexAttrib4NsvARB = (PFNGLVERTEXATTRIB4NSVARBPROC) load(userptr, "glVertexAttrib4NsvARB");
+ glad_glVertexAttrib4NubARB = (PFNGLVERTEXATTRIB4NUBARBPROC) load(userptr, "glVertexAttrib4NubARB");
+ glad_glVertexAttrib4NubvARB = (PFNGLVERTEXATTRIB4NUBVARBPROC) load(userptr, "glVertexAttrib4NubvARB");
+ glad_glVertexAttrib4NuivARB = (PFNGLVERTEXATTRIB4NUIVARBPROC) load(userptr, "glVertexAttrib4NuivARB");
+ glad_glVertexAttrib4NusvARB = (PFNGLVERTEXATTRIB4NUSVARBPROC) load(userptr, "glVertexAttrib4NusvARB");
+ glad_glVertexAttrib4bvARB = (PFNGLVERTEXATTRIB4BVARBPROC) load(userptr, "glVertexAttrib4bvARB");
+ glad_glVertexAttrib4dARB = (PFNGLVERTEXATTRIB4DARBPROC) load(userptr, "glVertexAttrib4dARB");
+ glad_glVertexAttrib4dvARB = (PFNGLVERTEXATTRIB4DVARBPROC) load(userptr, "glVertexAttrib4dvARB");
+ glad_glVertexAttrib4fARB = (PFNGLVERTEXATTRIB4FARBPROC) load(userptr, "glVertexAttrib4fARB");
+ glad_glVertexAttrib4fvARB = (PFNGLVERTEXATTRIB4FVARBPROC) load(userptr, "glVertexAttrib4fvARB");
+ glad_glVertexAttrib4ivARB = (PFNGLVERTEXATTRIB4IVARBPROC) load(userptr, "glVertexAttrib4ivARB");
+ glad_glVertexAttrib4sARB = (PFNGLVERTEXATTRIB4SARBPROC) load(userptr, "glVertexAttrib4sARB");
+ glad_glVertexAttrib4svARB = (PFNGLVERTEXATTRIB4SVARBPROC) load(userptr, "glVertexAttrib4svARB");
+ glad_glVertexAttrib4ubvARB = (PFNGLVERTEXATTRIB4UBVARBPROC) load(userptr, "glVertexAttrib4ubvARB");
+ glad_glVertexAttrib4uivARB = (PFNGLVERTEXATTRIB4UIVARBPROC) load(userptr, "glVertexAttrib4uivARB");
+ glad_glVertexAttrib4usvARB = (PFNGLVERTEXATTRIB4USVARBPROC) load(userptr, "glVertexAttrib4usvARB");
+ glad_glVertexAttribPointerARB = (PFNGLVERTEXATTRIBPOINTERARBPROC) load(userptr, "glVertexAttribPointerARB");
+}
+static void glad_gl_load_GL_EXT_draw_instanced( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_draw_instanced) return;
+ glad_glDrawArraysInstancedEXT = (PFNGLDRAWARRAYSINSTANCEDEXTPROC) load(userptr, "glDrawArraysInstancedEXT");
+ glad_glDrawElementsInstancedEXT = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC) load(userptr, "glDrawElementsInstancedEXT");
+}
+static void glad_gl_load_GL_EXT_fog_coord( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_fog_coord) return;
+ glad_glFogCoordPointerEXT = (PFNGLFOGCOORDPOINTEREXTPROC) load(userptr, "glFogCoordPointerEXT");
+ glad_glFogCoorddEXT = (PFNGLFOGCOORDDEXTPROC) load(userptr, "glFogCoorddEXT");
+ glad_glFogCoorddvEXT = (PFNGLFOGCOORDDVEXTPROC) load(userptr, "glFogCoorddvEXT");
+ glad_glFogCoordfEXT = (PFNGLFOGCOORDFEXTPROC) load(userptr, "glFogCoordfEXT");
+ glad_glFogCoordfvEXT = (PFNGLFOGCOORDFVEXTPROC) load(userptr, "glFogCoordfvEXT");
+}
+static void glad_gl_load_GL_EXT_framebuffer_blit( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_framebuffer_blit) return;
+ glad_glBlitFramebufferEXT = (PFNGLBLITFRAMEBUFFEREXTPROC) load(userptr, "glBlitFramebufferEXT");
+}
+static void glad_gl_load_GL_EXT_framebuffer_multisample( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_framebuffer_multisample) return;
+ glad_glRenderbufferStorageMultisampleEXT = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) load(userptr, "glRenderbufferStorageMultisampleEXT");
+}
+static void glad_gl_load_GL_EXT_framebuffer_object( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_framebuffer_object) return;
+ glad_glBindFramebufferEXT = (PFNGLBINDFRAMEBUFFEREXTPROC) load(userptr, "glBindFramebufferEXT");
+ glad_glBindRenderbufferEXT = (PFNGLBINDRENDERBUFFEREXTPROC) load(userptr, "glBindRenderbufferEXT");
+ glad_glCheckFramebufferStatusEXT = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) load(userptr, "glCheckFramebufferStatusEXT");
+ glad_glDeleteFramebuffersEXT = (PFNGLDELETEFRAMEBUFFERSEXTPROC) load(userptr, "glDeleteFramebuffersEXT");
+ glad_glDeleteRenderbuffersEXT = (PFNGLDELETERENDERBUFFERSEXTPROC) load(userptr, "glDeleteRenderbuffersEXT");
+ glad_glFramebufferRenderbufferEXT = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC) load(userptr, "glFramebufferRenderbufferEXT");
+ glad_glFramebufferTexture1DEXT = (PFNGLFRAMEBUFFERTEXTURE1DEXTPROC) load(userptr, "glFramebufferTexture1DEXT");
+ glad_glFramebufferTexture2DEXT = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) load(userptr, "glFramebufferTexture2DEXT");
+ glad_glFramebufferTexture3DEXT = (PFNGLFRAMEBUFFERTEXTURE3DEXTPROC) load(userptr, "glFramebufferTexture3DEXT");
+ glad_glGenFramebuffersEXT = (PFNGLGENFRAMEBUFFERSEXTPROC) load(userptr, "glGenFramebuffersEXT");
+ glad_glGenRenderbuffersEXT = (PFNGLGENRENDERBUFFERSEXTPROC) load(userptr, "glGenRenderbuffersEXT");
+ glad_glGenerateMipmapEXT = (PFNGLGENERATEMIPMAPEXTPROC) load(userptr, "glGenerateMipmapEXT");
+ glad_glGetFramebufferAttachmentParameterivEXT = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) load(userptr, "glGetFramebufferAttachmentParameterivEXT");
+ glad_glGetRenderbufferParameterivEXT = (PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC) load(userptr, "glGetRenderbufferParameterivEXT");
+ glad_glIsFramebufferEXT = (PFNGLISFRAMEBUFFEREXTPROC) load(userptr, "glIsFramebufferEXT");
+ glad_glIsRenderbufferEXT = (PFNGLISRENDERBUFFEREXTPROC) load(userptr, "glIsRenderbufferEXT");
+ glad_glRenderbufferStorageEXT = (PFNGLRENDERBUFFERSTORAGEEXTPROC) load(userptr, "glRenderbufferStorageEXT");
+}
+static void glad_gl_load_GL_OES_fixed_point( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_OES_fixed_point) return;
+ glad_glAccumxOES = (PFNGLACCUMXOESPROC) load(userptr, "glAccumxOES");
+ glad_glAlphaFuncxOES = (PFNGLALPHAFUNCXOESPROC) load(userptr, "glAlphaFuncxOES");
+ glad_glBitmapxOES = (PFNGLBITMAPXOESPROC) load(userptr, "glBitmapxOES");
+ glad_glBlendColorxOES = (PFNGLBLENDCOLORXOESPROC) load(userptr, "glBlendColorxOES");
+ glad_glClearAccumxOES = (PFNGLCLEARACCUMXOESPROC) load(userptr, "glClearAccumxOES");
+ glad_glClearColorxOES = (PFNGLCLEARCOLORXOESPROC) load(userptr, "glClearColorxOES");
+ glad_glClearDepthxOES = (PFNGLCLEARDEPTHXOESPROC) load(userptr, "glClearDepthxOES");
+ glad_glClipPlanexOES = (PFNGLCLIPPLANEXOESPROC) load(userptr, "glClipPlanexOES");
+ glad_glColor3xOES = (PFNGLCOLOR3XOESPROC) load(userptr, "glColor3xOES");
+ glad_glColor3xvOES = (PFNGLCOLOR3XVOESPROC) load(userptr, "glColor3xvOES");
+ glad_glColor4xOES = (PFNGLCOLOR4XOESPROC) load(userptr, "glColor4xOES");
+ glad_glColor4xvOES = (PFNGLCOLOR4XVOESPROC) load(userptr, "glColor4xvOES");
+ glad_glConvolutionParameterxOES = (PFNGLCONVOLUTIONPARAMETERXOESPROC) load(userptr, "glConvolutionParameterxOES");
+ glad_glConvolutionParameterxvOES = (PFNGLCONVOLUTIONPARAMETERXVOESPROC) load(userptr, "glConvolutionParameterxvOES");
+ glad_glDepthRangexOES = (PFNGLDEPTHRANGEXOESPROC) load(userptr, "glDepthRangexOES");
+ glad_glEvalCoord1xOES = (PFNGLEVALCOORD1XOESPROC) load(userptr, "glEvalCoord1xOES");
+ glad_glEvalCoord1xvOES = (PFNGLEVALCOORD1XVOESPROC) load(userptr, "glEvalCoord1xvOES");
+ glad_glEvalCoord2xOES = (PFNGLEVALCOORD2XOESPROC) load(userptr, "glEvalCoord2xOES");
+ glad_glEvalCoord2xvOES = (PFNGLEVALCOORD2XVOESPROC) load(userptr, "glEvalCoord2xvOES");
+ glad_glFeedbackBufferxOES = (PFNGLFEEDBACKBUFFERXOESPROC) load(userptr, "glFeedbackBufferxOES");
+ glad_glFogxOES = (PFNGLFOGXOESPROC) load(userptr, "glFogxOES");
+ glad_glFogxvOES = (PFNGLFOGXVOESPROC) load(userptr, "glFogxvOES");
+ glad_glFrustumxOES = (PFNGLFRUSTUMXOESPROC) load(userptr, "glFrustumxOES");
+ glad_glGetClipPlanexOES = (PFNGLGETCLIPPLANEXOESPROC) load(userptr, "glGetClipPlanexOES");
+ glad_glGetConvolutionParameterxvOES = (PFNGLGETCONVOLUTIONPARAMETERXVOESPROC) load(userptr, "glGetConvolutionParameterxvOES");
+ glad_glGetFixedvOES = (PFNGLGETFIXEDVOESPROC) load(userptr, "glGetFixedvOES");
+ glad_glGetHistogramParameterxvOES = (PFNGLGETHISTOGRAMPARAMETERXVOESPROC) load(userptr, "glGetHistogramParameterxvOES");
+ glad_glGetLightxOES = (PFNGLGETLIGHTXOESPROC) load(userptr, "glGetLightxOES");
+ glad_glGetMapxvOES = (PFNGLGETMAPXVOESPROC) load(userptr, "glGetMapxvOES");
+ glad_glGetMaterialxOES = (PFNGLGETMATERIALXOESPROC) load(userptr, "glGetMaterialxOES");
+ glad_glGetPixelMapxv = (PFNGLGETPIXELMAPXVPROC) load(userptr, "glGetPixelMapxv");
+ glad_glGetTexEnvxvOES = (PFNGLGETTEXENVXVOESPROC) load(userptr, "glGetTexEnvxvOES");
+ glad_glGetTexGenxvOES = (PFNGLGETTEXGENXVOESPROC) load(userptr, "glGetTexGenxvOES");
+ glad_glGetTexLevelParameterxvOES = (PFNGLGETTEXLEVELPARAMETERXVOESPROC) load(userptr, "glGetTexLevelParameterxvOES");
+ glad_glGetTexParameterxvOES = (PFNGLGETTEXPARAMETERXVOESPROC) load(userptr, "glGetTexParameterxvOES");
+ glad_glIndexxOES = (PFNGLINDEXXOESPROC) load(userptr, "glIndexxOES");
+ glad_glIndexxvOES = (PFNGLINDEXXVOESPROC) load(userptr, "glIndexxvOES");
+ glad_glLightModelxOES = (PFNGLLIGHTMODELXOESPROC) load(userptr, "glLightModelxOES");
+ glad_glLightModelxvOES = (PFNGLLIGHTMODELXVOESPROC) load(userptr, "glLightModelxvOES");
+ glad_glLightxOES = (PFNGLLIGHTXOESPROC) load(userptr, "glLightxOES");
+ glad_glLightxvOES = (PFNGLLIGHTXVOESPROC) load(userptr, "glLightxvOES");
+ glad_glLineWidthxOES = (PFNGLLINEWIDTHXOESPROC) load(userptr, "glLineWidthxOES");
+ glad_glLoadMatrixxOES = (PFNGLLOADMATRIXXOESPROC) load(userptr, "glLoadMatrixxOES");
+ glad_glLoadTransposeMatrixxOES = (PFNGLLOADTRANSPOSEMATRIXXOESPROC) load(userptr, "glLoadTransposeMatrixxOES");
+ glad_glMap1xOES = (PFNGLMAP1XOESPROC) load(userptr, "glMap1xOES");
+ glad_glMap2xOES = (PFNGLMAP2XOESPROC) load(userptr, "glMap2xOES");
+ glad_glMapGrid1xOES = (PFNGLMAPGRID1XOESPROC) load(userptr, "glMapGrid1xOES");
+ glad_glMapGrid2xOES = (PFNGLMAPGRID2XOESPROC) load(userptr, "glMapGrid2xOES");
+ glad_glMaterialxOES = (PFNGLMATERIALXOESPROC) load(userptr, "glMaterialxOES");
+ glad_glMaterialxvOES = (PFNGLMATERIALXVOESPROC) load(userptr, "glMaterialxvOES");
+ glad_glMultMatrixxOES = (PFNGLMULTMATRIXXOESPROC) load(userptr, "glMultMatrixxOES");
+ glad_glMultTransposeMatrixxOES = (PFNGLMULTTRANSPOSEMATRIXXOESPROC) load(userptr, "glMultTransposeMatrixxOES");
+ glad_glMultiTexCoord1xOES = (PFNGLMULTITEXCOORD1XOESPROC) load(userptr, "glMultiTexCoord1xOES");
+ glad_glMultiTexCoord1xvOES = (PFNGLMULTITEXCOORD1XVOESPROC) load(userptr, "glMultiTexCoord1xvOES");
+ glad_glMultiTexCoord2xOES = (PFNGLMULTITEXCOORD2XOESPROC) load(userptr, "glMultiTexCoord2xOES");
+ glad_glMultiTexCoord2xvOES = (PFNGLMULTITEXCOORD2XVOESPROC) load(userptr, "glMultiTexCoord2xvOES");
+ glad_glMultiTexCoord3xOES = (PFNGLMULTITEXCOORD3XOESPROC) load(userptr, "glMultiTexCoord3xOES");
+ glad_glMultiTexCoord3xvOES = (PFNGLMULTITEXCOORD3XVOESPROC) load(userptr, "glMultiTexCoord3xvOES");
+ glad_glMultiTexCoord4xOES = (PFNGLMULTITEXCOORD4XOESPROC) load(userptr, "glMultiTexCoord4xOES");
+ glad_glMultiTexCoord4xvOES = (PFNGLMULTITEXCOORD4XVOESPROC) load(userptr, "glMultiTexCoord4xvOES");
+ glad_glNormal3xOES = (PFNGLNORMAL3XOESPROC) load(userptr, "glNormal3xOES");
+ glad_glNormal3xvOES = (PFNGLNORMAL3XVOESPROC) load(userptr, "glNormal3xvOES");
+ glad_glOrthoxOES = (PFNGLORTHOXOESPROC) load(userptr, "glOrthoxOES");
+ glad_glPassThroughxOES = (PFNGLPASSTHROUGHXOESPROC) load(userptr, "glPassThroughxOES");
+ glad_glPixelMapx = (PFNGLPIXELMAPXPROC) load(userptr, "glPixelMapx");
+ glad_glPixelStorex = (PFNGLPIXELSTOREXPROC) load(userptr, "glPixelStorex");
+ glad_glPixelTransferxOES = (PFNGLPIXELTRANSFERXOESPROC) load(userptr, "glPixelTransferxOES");
+ glad_glPixelZoomxOES = (PFNGLPIXELZOOMXOESPROC) load(userptr, "glPixelZoomxOES");
+ glad_glPointParameterxvOES = (PFNGLPOINTPARAMETERXVOESPROC) load(userptr, "glPointParameterxvOES");
+ glad_glPointSizexOES = (PFNGLPOINTSIZEXOESPROC) load(userptr, "glPointSizexOES");
+ glad_glPolygonOffsetxOES = (PFNGLPOLYGONOFFSETXOESPROC) load(userptr, "glPolygonOffsetxOES");
+ glad_glPrioritizeTexturesxOES = (PFNGLPRIORITIZETEXTURESXOESPROC) load(userptr, "glPrioritizeTexturesxOES");
+ glad_glRasterPos2xOES = (PFNGLRASTERPOS2XOESPROC) load(userptr, "glRasterPos2xOES");
+ glad_glRasterPos2xvOES = (PFNGLRASTERPOS2XVOESPROC) load(userptr, "glRasterPos2xvOES");
+ glad_glRasterPos3xOES = (PFNGLRASTERPOS3XOESPROC) load(userptr, "glRasterPos3xOES");
+ glad_glRasterPos3xvOES = (PFNGLRASTERPOS3XVOESPROC) load(userptr, "glRasterPos3xvOES");
+ glad_glRasterPos4xOES = (PFNGLRASTERPOS4XOESPROC) load(userptr, "glRasterPos4xOES");
+ glad_glRasterPos4xvOES = (PFNGLRASTERPOS4XVOESPROC) load(userptr, "glRasterPos4xvOES");
+ glad_glRectxOES = (PFNGLRECTXOESPROC) load(userptr, "glRectxOES");
+ glad_glRectxvOES = (PFNGLRECTXVOESPROC) load(userptr, "glRectxvOES");
+ glad_glRotatexOES = (PFNGLROTATEXOESPROC) load(userptr, "glRotatexOES");
+ glad_glScalexOES = (PFNGLSCALEXOESPROC) load(userptr, "glScalexOES");
+ glad_glTexCoord1xOES = (PFNGLTEXCOORD1XOESPROC) load(userptr, "glTexCoord1xOES");
+ glad_glTexCoord1xvOES = (PFNGLTEXCOORD1XVOESPROC) load(userptr, "glTexCoord1xvOES");
+ glad_glTexCoord2xOES = (PFNGLTEXCOORD2XOESPROC) load(userptr, "glTexCoord2xOES");
+ glad_glTexCoord2xvOES = (PFNGLTEXCOORD2XVOESPROC) load(userptr, "glTexCoord2xvOES");
+ glad_glTexCoord3xOES = (PFNGLTEXCOORD3XOESPROC) load(userptr, "glTexCoord3xOES");
+ glad_glTexCoord3xvOES = (PFNGLTEXCOORD3XVOESPROC) load(userptr, "glTexCoord3xvOES");
+ glad_glTexCoord4xOES = (PFNGLTEXCOORD4XOESPROC) load(userptr, "glTexCoord4xOES");
+ glad_glTexCoord4xvOES = (PFNGLTEXCOORD4XVOESPROC) load(userptr, "glTexCoord4xvOES");
+ glad_glTexEnvxOES = (PFNGLTEXENVXOESPROC) load(userptr, "glTexEnvxOES");
+ glad_glTexEnvxvOES = (PFNGLTEXENVXVOESPROC) load(userptr, "glTexEnvxvOES");
+ glad_glTexGenxOES = (PFNGLTEXGENXOESPROC) load(userptr, "glTexGenxOES");
+ glad_glTexGenxvOES = (PFNGLTEXGENXVOESPROC) load(userptr, "glTexGenxvOES");
+ glad_glTexParameterxOES = (PFNGLTEXPARAMETERXOESPROC) load(userptr, "glTexParameterxOES");
+ glad_glTexParameterxvOES = (PFNGLTEXPARAMETERXVOESPROC) load(userptr, "glTexParameterxvOES");
+ glad_glTranslatexOES = (PFNGLTRANSLATEXOESPROC) load(userptr, "glTranslatexOES");
+ glad_glVertex2xOES = (PFNGLVERTEX2XOESPROC) load(userptr, "glVertex2xOES");
+ glad_glVertex2xvOES = (PFNGLVERTEX2XVOESPROC) load(userptr, "glVertex2xvOES");
+ glad_glVertex3xOES = (PFNGLVERTEX3XOESPROC) load(userptr, "glVertex3xOES");
+ glad_glVertex3xvOES = (PFNGLVERTEX3XVOESPROC) load(userptr, "glVertex3xvOES");
+ glad_glVertex4xOES = (PFNGLVERTEX4XOESPROC) load(userptr, "glVertex4xOES");
+ glad_glVertex4xvOES = (PFNGLVERTEX4XVOESPROC) load(userptr, "glVertex4xvOES");
+}
+
+
+
+#if defined(GL_ES_VERSION_3_0) || defined(GL_VERSION_3_0)
+#define GLAD_GL_IS_SOME_NEW_VERSION 1
+#else
+#define GLAD_GL_IS_SOME_NEW_VERSION 0
+#endif
+
+static int glad_gl_get_extensions( int version, const char **out_exts, unsigned int *out_num_exts_i, char ***out_exts_i) {
+#if GLAD_GL_IS_SOME_NEW_VERSION
+ if(GLAD_VERSION_MAJOR(version) < 3) {
+#else
+ (void) version;
+ (void) out_num_exts_i;
+ (void) out_exts_i;
+#endif
+ if (glad_glGetString == NULL) {
+ return 0;
+ }
+ *out_exts = (const char *)glad_glGetString(GL_EXTENSIONS);
+#if GLAD_GL_IS_SOME_NEW_VERSION
+ } else {
+ unsigned int index = 0;
+ unsigned int num_exts_i = 0;
+ char **exts_i = NULL;
+ if (glad_glGetStringi == NULL || glad_glGetIntegerv == NULL) {
+ return 0;
+ }
+ glad_glGetIntegerv(GL_NUM_EXTENSIONS, (int*) &num_exts_i);
+ if (num_exts_i > 0) {
+ exts_i = (char **) GLAD_MALLOC(num_exts_i * (sizeof *exts_i));
+ }
+ if (exts_i == NULL) {
+ return 0;
+ }
+ for(index = 0; index < num_exts_i; index++) {
+ const char *gl_str_tmp = (const char*) glad_glGetStringi(GL_EXTENSIONS, index);
+ size_t len = strlen(gl_str_tmp) + 1;
+
+ char *local_str = (char*) GLAD_MALLOC(len * sizeof(char));
+ if(local_str != NULL) {
+ memcpy(local_str, gl_str_tmp, len * sizeof(char));
+ }
+
+ exts_i[index] = local_str;
+ }
+
+ *out_num_exts_i = num_exts_i;
+ *out_exts_i = exts_i;
+ }
+#endif
+ return 1;
+}
+static void glad_gl_free_extensions(char **exts_i, unsigned int num_exts_i) {
+ if (exts_i != NULL) {
+ unsigned int index;
+ for(index = 0; index < num_exts_i; index++) {
+ GLAD_FREE((void *) (exts_i[index]));
+ }
+ GLAD_FREE((void *)exts_i);
+ exts_i = NULL;
+ }
+}
+static int glad_gl_has_extension(int version, const char *exts, unsigned int num_exts_i, char **exts_i, const char *ext) {
+ if(GLAD_VERSION_MAJOR(version) < 3 || !GLAD_GL_IS_SOME_NEW_VERSION) {
+ const char *extensions;
+ const char *loc;
+ const char *terminator;
+ extensions = exts;
+ if(extensions == NULL || ext == NULL) {
+ return 0;
+ }
+ while(1) {
+ loc = strstr(extensions, ext);
+ if(loc == NULL) {
+ return 0;
+ }
+ terminator = loc + strlen(ext);
+ if((loc == extensions || *(loc - 1) == ' ') &&
+ (*terminator == ' ' || *terminator == '\0')) {
+ return 1;
+ }
+ extensions = terminator;
+ }
+ } else {
+ unsigned int index;
+ for(index = 0; index < num_exts_i; index++) {
+ const char *e = exts_i[index];
+ if(strcmp(e, ext) == 0) {
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+static GLADapiproc glad_gl_get_proc_from_userptr(void *userptr, const char* name) {
+ return (GLAD_GNUC_EXTENSION (GLADapiproc (*)(const char *name)) userptr)(name);
+}
+
+static int glad_gl_find_extensions_gl( int version) {
+ const char *exts = NULL;
+ unsigned int num_exts_i = 0;
+ char **exts_i = NULL;
+ if (!glad_gl_get_extensions(version, &exts, &num_exts_i, &exts_i)) return 0;
+
+ GLAD_GL_ARB_ES2_compatibility = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_ES2_compatibility");
+ GLAD_GL_ARB_ES3_1_compatibility = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_ES3_1_compatibility");
+ GLAD_GL_ARB_ES3_2_compatibility = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_ES3_2_compatibility");
+ GLAD_GL_ARB_ES3_compatibility = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_ES3_compatibility");
+ GLAD_GL_ARB_blend_func_extended = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_blend_func_extended");
+ GLAD_GL_ARB_buffer_storage = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_buffer_storage");
+ GLAD_GL_ARB_clear_buffer_object = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_clear_buffer_object");
+ GLAD_GL_ARB_clear_texture = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_clear_texture");
+ GLAD_GL_ARB_color_buffer_float = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_color_buffer_float");
+ GLAD_GL_ARB_compatibility = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_compatibility");
+ GLAD_GL_ARB_compressed_texture_pixel_storage = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_compressed_texture_pixel_storage");
+ GLAD_GL_ARB_compute_shader = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_compute_shader");
+ GLAD_GL_ARB_compute_variable_group_size = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_compute_variable_group_size");
+ GLAD_GL_ARB_copy_buffer = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_copy_buffer");
+ GLAD_GL_ARB_copy_image = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_copy_image");
+ GLAD_GL_ARB_debug_output = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_debug_output");
+ GLAD_GL_ARB_depth_buffer_float = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_depth_buffer_float");
+ GLAD_GL_ARB_depth_clamp = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_depth_clamp");
+ GLAD_GL_ARB_depth_texture = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_depth_texture");
+ GLAD_GL_ARB_direct_state_access = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_direct_state_access");
+ GLAD_GL_ARB_draw_buffers = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_draw_buffers");
+ GLAD_GL_ARB_draw_buffers_blend = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_draw_buffers_blend");
+ GLAD_GL_ARB_draw_elements_base_vertex = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_draw_elements_base_vertex");
+ GLAD_GL_ARB_draw_indirect = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_draw_indirect");
+ GLAD_GL_ARB_draw_instanced = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_draw_instanced");
+ GLAD_GL_ARB_enhanced_layouts = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_enhanced_layouts");
+ GLAD_GL_ARB_explicit_attrib_location = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_explicit_attrib_location");
+ GLAD_GL_ARB_explicit_uniform_location = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_explicit_uniform_location");
+ GLAD_GL_ARB_fragment_coord_conventions = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_fragment_coord_conventions");
+ GLAD_GL_ARB_fragment_layer_viewport = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_fragment_layer_viewport");
+ GLAD_GL_ARB_fragment_program = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_fragment_program");
+ GLAD_GL_ARB_fragment_program_shadow = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_fragment_program_shadow");
+ GLAD_GL_ARB_fragment_shader = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_fragment_shader");
+ GLAD_GL_ARB_fragment_shader_interlock = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_fragment_shader_interlock");
+ GLAD_GL_ARB_framebuffer_no_attachments = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_framebuffer_no_attachments");
+ GLAD_GL_ARB_framebuffer_object = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_framebuffer_object");
+ GLAD_GL_ARB_framebuffer_sRGB = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_framebuffer_sRGB");
+ GLAD_GL_ARB_geometry_shader4 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_geometry_shader4");
+ GLAD_GL_ARB_get_program_binary = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_get_program_binary");
+ GLAD_GL_ARB_get_texture_sub_image = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_get_texture_sub_image");
+ GLAD_GL_ARB_gl_spirv = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_gl_spirv");
+ GLAD_GL_ARB_gpu_shader5 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_gpu_shader5");
+ GLAD_GL_ARB_gpu_shader_fp64 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_gpu_shader_fp64");
+ GLAD_GL_ARB_gpu_shader_int64 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_gpu_shader_int64");
+ GLAD_GL_ARB_half_float_pixel = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_half_float_pixel");
+ GLAD_GL_ARB_half_float_vertex = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_half_float_vertex");
+ GLAD_GL_ARB_instanced_arrays = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_instanced_arrays");
+ GLAD_GL_ARB_internalformat_query = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_internalformat_query");
+ GLAD_GL_ARB_internalformat_query2 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_internalformat_query2");
+ GLAD_GL_ARB_map_buffer_range = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_map_buffer_range");
+ GLAD_GL_ARB_multi_bind = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_multi_bind");
+ GLAD_GL_ARB_multi_draw_indirect = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_multi_draw_indirect");
+ GLAD_GL_ARB_multisample = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_multisample");
+ GLAD_GL_ARB_multitexture = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_multitexture");
+ GLAD_GL_ARB_occlusion_query = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_occlusion_query");
+ GLAD_GL_ARB_occlusion_query2 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_occlusion_query2");
+ GLAD_GL_ARB_pipeline_statistics_query = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_pipeline_statistics_query");
+ GLAD_GL_ARB_query_buffer_object = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_query_buffer_object");
+ GLAD_GL_ARB_sample_locations = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_sample_locations");
+ GLAD_GL_ARB_sample_shading = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_sample_shading");
+ GLAD_GL_ARB_seamless_cube_map = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_seamless_cube_map");
+ GLAD_GL_ARB_seamless_cubemap_per_texture = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_seamless_cubemap_per_texture");
+ GLAD_GL_ARB_shader_atomic_counter_ops = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_shader_atomic_counter_ops");
+ GLAD_GL_ARB_shader_atomic_counters = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_shader_atomic_counters");
+ GLAD_GL_ARB_shader_bit_encoding = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_shader_bit_encoding");
+ GLAD_GL_ARB_shader_clock = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_shader_clock");
+ GLAD_GL_ARB_shader_image_load_store = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_shader_image_load_store");
+ GLAD_GL_ARB_shader_image_size = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_shader_image_size");
+ GLAD_GL_ARB_shader_objects = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_shader_objects");
+ GLAD_GL_ARB_shader_storage_buffer_object = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_shader_storage_buffer_object");
+ GLAD_GL_ARB_shader_texture_lod = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_shader_texture_lod");
+ GLAD_GL_ARB_shading_language_100 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_shading_language_100");
+ GLAD_GL_ARB_shading_language_420pack = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_shading_language_420pack");
+ GLAD_GL_ARB_shading_language_include = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_shading_language_include");
+ GLAD_GL_ARB_shading_language_packing = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_shading_language_packing");
+ GLAD_GL_ARB_spirv_extensions = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_spirv_extensions");
+ GLAD_GL_ARB_tessellation_shader = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_tessellation_shader");
+ GLAD_GL_ARB_texture_border_clamp = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_texture_border_clamp");
+ GLAD_GL_ARB_texture_buffer_object_rgb32 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_texture_buffer_object_rgb32");
+ GLAD_GL_ARB_texture_compression = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_texture_compression");
+ GLAD_GL_ARB_texture_cube_map = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_texture_cube_map");
+ GLAD_GL_ARB_texture_cube_map_array = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_texture_cube_map_array");
+ GLAD_GL_ARB_texture_env_add = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_texture_env_add");
+ GLAD_GL_ARB_texture_filter_anisotropic = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_texture_filter_anisotropic");
+ GLAD_GL_ARB_texture_filter_minmax = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_texture_filter_minmax");
+ GLAD_GL_ARB_texture_float = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_texture_float");
+ GLAD_GL_ARB_texture_mirror_clamp_to_edge = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_texture_mirror_clamp_to_edge");
+ GLAD_GL_ARB_texture_mirrored_repeat = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_texture_mirrored_repeat");
+ GLAD_GL_ARB_texture_multisample = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_texture_multisample");
+ GLAD_GL_ARB_texture_non_power_of_two = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_texture_non_power_of_two");
+ GLAD_GL_ARB_texture_rg = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_texture_rg");
+ GLAD_GL_ARB_texture_storage = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_texture_storage");
+ GLAD_GL_ARB_texture_swizzle = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_texture_swizzle");
+ GLAD_GL_ARB_texture_view = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_texture_view");
+ GLAD_GL_ARB_timer_query = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_timer_query");
+ GLAD_GL_ARB_transpose_matrix = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_transpose_matrix");
+ GLAD_GL_ARB_uniform_buffer_object = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_uniform_buffer_object");
+ GLAD_GL_ARB_vertex_array_bgra = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_vertex_array_bgra");
+ GLAD_GL_ARB_vertex_array_object = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_vertex_array_object");
+ GLAD_GL_ARB_vertex_attrib_binding = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_vertex_attrib_binding");
+ GLAD_GL_ARB_vertex_buffer_object = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_vertex_buffer_object");
+ GLAD_GL_ARB_vertex_program = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_vertex_program");
+ GLAD_GL_ARB_vertex_shader = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_vertex_shader");
+ GLAD_GL_EXT_draw_instanced = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_draw_instanced");
+ GLAD_GL_EXT_fog_coord = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_fog_coord");
+ GLAD_GL_EXT_framebuffer_blit = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_framebuffer_blit");
+ GLAD_GL_EXT_framebuffer_multisample = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_framebuffer_multisample");
+ GLAD_GL_EXT_framebuffer_object = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_framebuffer_object");
+ GLAD_GL_EXT_framebuffer_sRGB = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_framebuffer_sRGB");
+ GLAD_GL_EXT_texture_compression_s3tc = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_compression_s3tc");
+ GLAD_GL_EXT_texture_filter_anisotropic = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_filter_anisotropic");
+ GLAD_GL_EXT_texture_mirror_clamp = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_mirror_clamp");
+ GLAD_GL_KHR_texture_compression_astc_hdr = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_KHR_texture_compression_astc_hdr");
+ GLAD_GL_KHR_texture_compression_astc_ldr = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_KHR_texture_compression_astc_ldr");
+ GLAD_GL_OES_compressed_paletted_texture = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_compressed_paletted_texture");
+ GLAD_GL_OES_fixed_point = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_fixed_point");
+
+ glad_gl_free_extensions(exts_i, num_exts_i);
+
+ return 1;
+}
+
+static int glad_gl_find_core_gl(void) {
+ int i;
+ const char* version;
+ const char* prefixes[] = {
+ "OpenGL ES-CM ",
+ "OpenGL ES-CL ",
+ "OpenGL ES ",
+ "OpenGL SC ",
+ NULL
+ };
+ int major = 0;
+ int minor = 0;
+ version = (const char*) glad_glGetString(GL_VERSION);
+ if (!version) return 0;
+ for (i = 0; prefixes[i]; i++) {
+ const size_t length = strlen(prefixes[i]);
+ if (strncmp(version, prefixes[i], length) == 0) {
+ version += length;
+ break;
+ }
+ }
+
+ GLAD_IMPL_UTIL_SSCANF(version, "%d.%d", &major, &minor);
+
+ GLAD_GL_VERSION_1_0 = (major == 1 && minor >= 0) || major > 1;
+ GLAD_GL_VERSION_1_1 = (major == 1 && minor >= 1) || major > 1;
+ GLAD_GL_VERSION_1_2 = (major == 1 && minor >= 2) || major > 1;
+ GLAD_GL_VERSION_1_3 = (major == 1 && minor >= 3) || major > 1;
+ GLAD_GL_VERSION_1_4 = (major == 1 && minor >= 4) || major > 1;
+ GLAD_GL_VERSION_1_5 = (major == 1 && minor >= 5) || major > 1;
+ GLAD_GL_VERSION_2_0 = (major == 2 && minor >= 0) || major > 2;
+ GLAD_GL_VERSION_2_1 = (major == 2 && minor >= 1) || major > 2;
+ GLAD_GL_VERSION_3_0 = (major == 3 && minor >= 0) || major > 3;
+ GLAD_GL_VERSION_3_1 = (major == 3 && minor >= 1) || major > 3;
+ GLAD_GL_VERSION_3_2 = (major == 3 && minor >= 2) || major > 3;
+ GLAD_GL_VERSION_3_3 = (major == 3 && minor >= 3) || major > 3;
+ GLAD_GL_VERSION_4_0 = (major == 4 && minor >= 0) || major > 4;
+ GLAD_GL_VERSION_4_1 = (major == 4 && minor >= 1) || major > 4;
+ GLAD_GL_VERSION_4_2 = (major == 4 && minor >= 2) || major > 4;
+ GLAD_GL_VERSION_4_3 = (major == 4 && minor >= 3) || major > 4;
+
+ return GLAD_MAKE_VERSION(major, minor);
+}
+
+int gladLoadGLUserPtr( GLADuserptrloadfunc load, void *userptr) {
+ int version;
+
+ glad_glGetString = (PFNGLGETSTRINGPROC) load(userptr, "glGetString");
+ if(glad_glGetString == NULL) return 0;
+ if(glad_glGetString(GL_VERSION) == NULL) return 0;
+ version = glad_gl_find_core_gl();
+
+ glad_gl_load_GL_VERSION_1_0(load, userptr);
+ glad_gl_load_GL_VERSION_1_1(load, userptr);
+ glad_gl_load_GL_VERSION_1_2(load, userptr);
+ glad_gl_load_GL_VERSION_1_3(load, userptr);
+ glad_gl_load_GL_VERSION_1_4(load, userptr);
+ glad_gl_load_GL_VERSION_1_5(load, userptr);
+ glad_gl_load_GL_VERSION_2_0(load, userptr);
+ glad_gl_load_GL_VERSION_2_1(load, userptr);
+ glad_gl_load_GL_VERSION_3_0(load, userptr);
+ glad_gl_load_GL_VERSION_3_1(load, userptr);
+ glad_gl_load_GL_VERSION_3_2(load, userptr);
+ glad_gl_load_GL_VERSION_3_3(load, userptr);
+ glad_gl_load_GL_VERSION_4_0(load, userptr);
+ glad_gl_load_GL_VERSION_4_1(load, userptr);
+ glad_gl_load_GL_VERSION_4_2(load, userptr);
+ glad_gl_load_GL_VERSION_4_3(load, userptr);
+
+ if (!glad_gl_find_extensions_gl(version)) return 0;
+ glad_gl_load_GL_ARB_ES2_compatibility(load, userptr);
+ glad_gl_load_GL_ARB_ES3_1_compatibility(load, userptr);
+ glad_gl_load_GL_ARB_ES3_2_compatibility(load, userptr);
+ glad_gl_load_GL_ARB_blend_func_extended(load, userptr);
+ glad_gl_load_GL_ARB_buffer_storage(load, userptr);
+ glad_gl_load_GL_ARB_clear_buffer_object(load, userptr);
+ glad_gl_load_GL_ARB_clear_texture(load, userptr);
+ glad_gl_load_GL_ARB_color_buffer_float(load, userptr);
+ glad_gl_load_GL_ARB_compute_shader(load, userptr);
+ glad_gl_load_GL_ARB_compute_variable_group_size(load, userptr);
+ glad_gl_load_GL_ARB_copy_buffer(load, userptr);
+ glad_gl_load_GL_ARB_copy_image(load, userptr);
+ glad_gl_load_GL_ARB_debug_output(load, userptr);
+ glad_gl_load_GL_ARB_direct_state_access(load, userptr);
+ glad_gl_load_GL_ARB_draw_buffers(load, userptr);
+ glad_gl_load_GL_ARB_draw_buffers_blend(load, userptr);
+ glad_gl_load_GL_ARB_draw_elements_base_vertex(load, userptr);
+ glad_gl_load_GL_ARB_draw_indirect(load, userptr);
+ glad_gl_load_GL_ARB_draw_instanced(load, userptr);
+ glad_gl_load_GL_ARB_fragment_program(load, userptr);
+ glad_gl_load_GL_ARB_framebuffer_no_attachments(load, userptr);
+ glad_gl_load_GL_ARB_framebuffer_object(load, userptr);
+ glad_gl_load_GL_ARB_geometry_shader4(load, userptr);
+ glad_gl_load_GL_ARB_get_program_binary(load, userptr);
+ glad_gl_load_GL_ARB_get_texture_sub_image(load, userptr);
+ glad_gl_load_GL_ARB_gl_spirv(load, userptr);
+ glad_gl_load_GL_ARB_gpu_shader_fp64(load, userptr);
+ glad_gl_load_GL_ARB_gpu_shader_int64(load, userptr);
+ glad_gl_load_GL_ARB_instanced_arrays(load, userptr);
+ glad_gl_load_GL_ARB_internalformat_query(load, userptr);
+ glad_gl_load_GL_ARB_internalformat_query2(load, userptr);
+ glad_gl_load_GL_ARB_map_buffer_range(load, userptr);
+ glad_gl_load_GL_ARB_multi_bind(load, userptr);
+ glad_gl_load_GL_ARB_multi_draw_indirect(load, userptr);
+ glad_gl_load_GL_ARB_multisample(load, userptr);
+ glad_gl_load_GL_ARB_multitexture(load, userptr);
+ glad_gl_load_GL_ARB_occlusion_query(load, userptr);
+ glad_gl_load_GL_ARB_sample_locations(load, userptr);
+ glad_gl_load_GL_ARB_sample_shading(load, userptr);
+ glad_gl_load_GL_ARB_shader_atomic_counters(load, userptr);
+ glad_gl_load_GL_ARB_shader_image_load_store(load, userptr);
+ glad_gl_load_GL_ARB_shader_objects(load, userptr);
+ glad_gl_load_GL_ARB_shader_storage_buffer_object(load, userptr);
+ glad_gl_load_GL_ARB_shading_language_include(load, userptr);
+ glad_gl_load_GL_ARB_tessellation_shader(load, userptr);
+ glad_gl_load_GL_ARB_texture_compression(load, userptr);
+ glad_gl_load_GL_ARB_texture_multisample(load, userptr);
+ glad_gl_load_GL_ARB_texture_storage(load, userptr);
+ glad_gl_load_GL_ARB_texture_view(load, userptr);
+ glad_gl_load_GL_ARB_timer_query(load, userptr);
+ glad_gl_load_GL_ARB_transpose_matrix(load, userptr);
+ glad_gl_load_GL_ARB_uniform_buffer_object(load, userptr);
+ glad_gl_load_GL_ARB_vertex_array_object(load, userptr);
+ glad_gl_load_GL_ARB_vertex_attrib_binding(load, userptr);
+ glad_gl_load_GL_ARB_vertex_buffer_object(load, userptr);
+ glad_gl_load_GL_ARB_vertex_program(load, userptr);
+ glad_gl_load_GL_ARB_vertex_shader(load, userptr);
+ glad_gl_load_GL_EXT_draw_instanced(load, userptr);
+ glad_gl_load_GL_EXT_fog_coord(load, userptr);
+ glad_gl_load_GL_EXT_framebuffer_blit(load, userptr);
+ glad_gl_load_GL_EXT_framebuffer_multisample(load, userptr);
+ glad_gl_load_GL_EXT_framebuffer_object(load, userptr);
+ glad_gl_load_GL_OES_fixed_point(load, userptr);
+
+
+
+ return version;
+}
+
+
+int gladLoadGL( GLADloadfunc load) {
+ return gladLoadGLUserPtr( glad_gl_get_proc_from_userptr, GLAD_GNUC_EXTENSION (void*) load);
+}
+
+
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GLAD_GL_IMPLEMENTATION */
+
diff --git a/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/glad_gles2.h b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/glad_gles2.h
new file mode 100644
index 0000000..6c753d0
--- /dev/null
+++ b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/glad_gles2.h
@@ -0,0 +1,4774 @@
+/**
+ * Loader generated by glad 2.0.2 on Wed Dec 28 13:28:51 2022
+ *
+ * SPDX-License-Identifier: (WTFPL OR CC0-1.0) AND Apache-2.0
+ *
+ * Generator: C/C++
+ * Specification: gl
+ * Extensions: 170
+ *
+ * APIs:
+ * - gles2=2.0
+ *
+ * Options:
+ * - ALIAS = False
+ * - DEBUG = False
+ * - HEADER_ONLY = True
+ * - LOADER = False
+ * - MX = False
+ * - ON_DEMAND = False
+ *
+ * Commandline:
+ * --api='gles2=2.0' --extensions='GL_EXT_EGL_image_array,GL_EXT_EGL_image_storage,GL_EXT_EGL_image_storage_compression,GL_EXT_YUV_target,GL_EXT_base_instance,GL_EXT_blend_func_extended,GL_EXT_blend_minmax,GL_EXT_buffer_storage,GL_EXT_clear_texture,GL_EXT_clip_control,GL_EXT_clip_cull_distance,GL_EXT_color_buffer_float,GL_EXT_color_buffer_half_float,GL_EXT_conservative_depth,GL_EXT_copy_image,GL_EXT_debug_label,GL_EXT_debug_marker,GL_EXT_depth_clamp,GL_EXT_discard_framebuffer,GL_EXT_disjoint_timer_query,GL_EXT_draw_buffers,GL_EXT_draw_buffers_indexed,GL_EXT_draw_elements_base_vertex,GL_EXT_draw_instanced,GL_EXT_draw_transform_feedback,GL_EXT_external_buffer,GL_EXT_float_blend,GL_EXT_fragment_shading_rate,GL_EXT_geometry_point_size,GL_EXT_geometry_shader,GL_EXT_gpu_shader5,GL_EXT_instanced_arrays,GL_EXT_map_buffer_range,GL_EXT_memory_object,GL_EXT_memory_object_fd,GL_EXT_memory_object_win32,GL_EXT_multi_draw_arrays,GL_EXT_multi_draw_indirect,GL_EXT_multisampled_compatibility,GL_EXT_multisampled_render_to_texture,GL_EXT_multisampled_render_to_texture2,GL_EXT_multiview_draw_buffers,GL_EXT_multiview_tessellation_geometry_shader,GL_EXT_multiview_texture_multisample,GL_EXT_multiview_timer_query,GL_EXT_occlusion_query_boolean,GL_EXT_polygon_offset_clamp,GL_EXT_post_depth_coverage,GL_EXT_primitive_bounding_box,GL_EXT_protected_textures,GL_EXT_pvrtc_sRGB,GL_EXT_raster_multisample,GL_EXT_read_format_bgra,GL_EXT_render_snorm,GL_EXT_robustness,GL_EXT_sRGB,GL_EXT_sRGB_write_control,GL_EXT_semaphore,GL_EXT_semaphore_fd,GL_EXT_semaphore_win32,GL_EXT_separate_depth_stencil,GL_EXT_separate_shader_objects,GL_EXT_shader_framebuffer_fetch,GL_EXT_shader_framebuffer_fetch_non_coherent,GL_EXT_shader_group_vote,GL_EXT_shader_implicit_conversions,GL_EXT_shader_integer_mix,GL_EXT_shader_io_blocks,GL_EXT_shader_non_constant_global_initializers,GL_EXT_shader_pixel_local_storage,GL_EXT_shader_pixel_local_storage2,GL_EXT_shader_samples_identical,GL_EXT_shader_texture_lod,GL_EXT_shadow_samplers,GL_EXT_sparse_texture,GL_EXT_sparse_texture2,GL_EXT_tessellation_point_size,GL_EXT_tessellation_shader,GL_EXT_texture_border_clamp,GL_EXT_texture_buffer,GL_EXT_texture_compression_astc_decode_mode,GL_EXT_texture_compression_bptc,GL_EXT_texture_compression_dxt1,GL_EXT_texture_compression_rgtc,GL_EXT_texture_compression_s3tc,GL_EXT_texture_compression_s3tc_srgb,GL_EXT_texture_cube_map_array,GL_EXT_texture_filter_anisotropic,GL_EXT_texture_filter_minmax,GL_EXT_texture_format_BGRA8888,GL_EXT_texture_format_sRGB_override,GL_EXT_texture_mirror_clamp_to_edge,GL_EXT_texture_norm16,GL_EXT_texture_query_lod,GL_EXT_texture_rg,GL_EXT_texture_sRGB_R8,GL_EXT_texture_sRGB_RG8,GL_EXT_texture_sRGB_decode,GL_EXT_texture_shadow_lod,GL_EXT_texture_storage,GL_EXT_texture_storage_compression,GL_EXT_texture_type_2_10_10_10_REV,GL_EXT_texture_view,GL_EXT_unpack_subimage,GL_EXT_win32_keyed_mutex,GL_EXT_window_rectangles,GL_KHR_blend_equation_advanced,GL_KHR_blend_equation_advanced_coherent,GL_KHR_context_flush_control,GL_KHR_debug,GL_KHR_no_error,GL_KHR_parallel_shader_compile,GL_KHR_robust_buffer_access_behavior,GL_KHR_robustness,GL_KHR_shader_subgroup,GL_KHR_texture_compression_astc_hdr,GL_KHR_texture_compression_astc_ldr,GL_KHR_texture_compression_astc_sliced_3d,GL_OES_EGL_image,GL_OES_EGL_image_external,GL_OES_EGL_image_external_essl3,GL_OES_compressed_ETC1_RGB8_sub_texture,GL_OES_compressed_ETC1_RGB8_texture,GL_OES_compressed_paletted_texture,GL_OES_copy_image,GL_OES_depth24,GL_OES_depth32,GL_OES_depth_texture,GL_OES_draw_buffers_indexed,GL_OES_draw_elements_base_vertex,GL_OES_element_index_uint,GL_OES_fbo_render_mipmap,GL_OES_fragment_precision_high,GL_OES_geometry_point_size,GL_OES_geometry_shader,GL_OES_get_program_binary,GL_OES_gpu_shader5,GL_OES_mapbuffer,GL_OES_packed_depth_stencil,GL_OES_primitive_bounding_box,GL_OES_required_internalformat,GL_OES_rgb8_rgba8,GL_OES_sample_shading,GL_OES_sample_variables,GL_OES_shader_image_atomic,GL_OES_shader_io_blocks,GL_OES_shader_multisample_interpolation,GL_OES_standard_derivatives,GL_OES_stencil1,GL_OES_stencil4,GL_OES_surfaceless_context,GL_OES_tessellation_point_size,GL_OES_tessellation_shader,GL_OES_texture_3D,GL_OES_texture_border_clamp,GL_OES_texture_buffer,GL_OES_texture_compression_astc,GL_OES_texture_cube_map_array,GL_OES_texture_float,GL_OES_texture_float_linear,GL_OES_texture_half_float,GL_OES_texture_half_float_linear,GL_OES_texture_npot,GL_OES_texture_stencil8,GL_OES_texture_storage_multisample_2d_array,GL_OES_texture_view,GL_OES_vertex_array_object,GL_OES_vertex_half_float,GL_OES_vertex_type_10_10_10_2,GL_OES_viewport_array' c --header-only
+ *
+ * Online:
+ * http://glad.sh/#api=gles2%3D2.0&generator=c&options=HEADER_ONLY
+ *
+ */
+
+#ifndef GLAD_GLES2_H_
+#define GLAD_GLES2_H_
+
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wreserved-id-macro"
+#endif
+#ifdef __gl2_h_
+ #error OpenGL ES 2 header already included (API: gles2), remove previous include!
+#endif
+#define __gl2_h_ 1
+#ifdef __gles2_gl2_h_
+ #error OpenGL ES 2 header already included (API: gles2), remove previous include!
+#endif
+#define __gles2_gl2_h_ 1
+#ifdef __gl3_h_
+ #error OpenGL ES 3 header already included (API: gles2), remove previous include!
+#endif
+#define __gl3_h_ 1
+#ifdef __gles2_gl3_h_
+ #error OpenGL ES 3 header already included (API: gles2), remove previous include!
+#endif
+#define __gles2_gl3_h_ 1
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
+#define GLAD_GLES2
+#define GLAD_OPTION_GLES2_HEADER_ONLY
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef GLAD_PLATFORM_H_
+#define GLAD_PLATFORM_H_
+
+#ifndef GLAD_PLATFORM_WIN32
+ #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) || defined(__MINGW32__)
+ #define GLAD_PLATFORM_WIN32 1
+ #else
+ #define GLAD_PLATFORM_WIN32 0
+ #endif
+#endif
+
+#ifndef GLAD_PLATFORM_APPLE
+ #ifdef __APPLE__
+ #define GLAD_PLATFORM_APPLE 1
+ #else
+ #define GLAD_PLATFORM_APPLE 0
+ #endif
+#endif
+
+#ifndef GLAD_PLATFORM_EMSCRIPTEN
+ #ifdef __EMSCRIPTEN__
+ #define GLAD_PLATFORM_EMSCRIPTEN 1
+ #else
+ #define GLAD_PLATFORM_EMSCRIPTEN 0
+ #endif
+#endif
+
+#ifndef GLAD_PLATFORM_UWP
+ #if defined(_MSC_VER) && !defined(GLAD_INTERNAL_HAVE_WINAPIFAMILY)
+ #ifdef __has_include
+ #if __has_include()
+ #define GLAD_INTERNAL_HAVE_WINAPIFAMILY 1
+ #endif
+ #elif _MSC_VER >= 1700 && !_USING_V110_SDK71_
+ #define GLAD_INTERNAL_HAVE_WINAPIFAMILY 1
+ #endif
+ #endif
+
+ #ifdef GLAD_INTERNAL_HAVE_WINAPIFAMILY
+ #include
+ #if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
+ #define GLAD_PLATFORM_UWP 1
+ #endif
+ #endif
+
+ #ifndef GLAD_PLATFORM_UWP
+ #define GLAD_PLATFORM_UWP 0
+ #endif
+#endif
+
+#ifdef __GNUC__
+ #define GLAD_GNUC_EXTENSION __extension__
+#else
+ #define GLAD_GNUC_EXTENSION
+#endif
+
+#define GLAD_UNUSED(x) (void)(x)
+
+#ifndef GLAD_API_CALL
+ #if defined(GLAD_API_CALL_EXPORT)
+ #if GLAD_PLATFORM_WIN32 || defined(__CYGWIN__)
+ #if defined(GLAD_API_CALL_EXPORT_BUILD)
+ #if defined(__GNUC__)
+ #define GLAD_API_CALL __attribute__ ((dllexport)) extern
+ #else
+ #define GLAD_API_CALL __declspec(dllexport) extern
+ #endif
+ #else
+ #if defined(__GNUC__)
+ #define GLAD_API_CALL __attribute__ ((dllimport)) extern
+ #else
+ #define GLAD_API_CALL __declspec(dllimport) extern
+ #endif
+ #endif
+ #elif defined(__GNUC__) && defined(GLAD_API_CALL_EXPORT_BUILD)
+ #define GLAD_API_CALL __attribute__ ((visibility ("default"))) extern
+ #else
+ #define GLAD_API_CALL extern
+ #endif
+ #else
+ #define GLAD_API_CALL extern
+ #endif
+#endif
+
+#ifdef APIENTRY
+ #define GLAD_API_PTR APIENTRY
+#elif GLAD_PLATFORM_WIN32
+ #define GLAD_API_PTR __stdcall
+#else
+ #define GLAD_API_PTR
+#endif
+
+#ifndef GLAPI
+#define GLAPI GLAD_API_CALL
+#endif
+
+#ifndef GLAPIENTRY
+#define GLAPIENTRY GLAD_API_PTR
+#endif
+
+#define GLAD_MAKE_VERSION(major, minor) (major * 10000 + minor)
+#define GLAD_VERSION_MAJOR(version) (version / 10000)
+#define GLAD_VERSION_MINOR(version) (version % 10000)
+
+#define GLAD_GENERATOR_VERSION "2.0.2"
+
+typedef void (*GLADapiproc)(void);
+
+typedef GLADapiproc (*GLADloadfunc)(const char *name);
+typedef GLADapiproc (*GLADuserptrloadfunc)(void *userptr, const char *name);
+
+typedef void (*GLADprecallback)(const char *name, GLADapiproc apiproc, int len_args, ...);
+typedef void (*GLADpostcallback)(void *ret, const char *name, GLADapiproc apiproc, int len_args, ...);
+
+#endif /* GLAD_PLATFORM_H_ */
+
+#define GL_ACTIVE_ATTRIBUTES 0x8B89
+#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
+#define GL_ACTIVE_PROGRAM_EXT 0x8259
+#define GL_ACTIVE_TEXTURE 0x84E0
+#define GL_ACTIVE_UNIFORMS 0x8B86
+#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87
+#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E
+#define GL_ALIASED_POINT_SIZE_RANGE 0x846D
+#define GL_ALL_SHADER_BITS_EXT 0xFFFFFFFF
+#define GL_ALPHA 0x1906
+#define GL_ALPHA16F_EXT 0x881C
+#define GL_ALPHA32F_EXT 0x8816
+#define GL_ALPHA8_EXT 0x803C
+#define GL_ALPHA8_OES 0x803C
+#define GL_ALPHA_BITS 0x0D55
+#define GL_ALWAYS 0x0207
+#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT 0x8D6A
+#define GL_ANY_SAMPLES_PASSED_EXT 0x8C2F
+#define GL_ARRAY_BUFFER 0x8892
+#define GL_ARRAY_BUFFER_BINDING 0x8894
+#define GL_ATTACHED_SHADERS 0x8B85
+#define GL_BACK 0x0405
+#define GL_BGRA8_EXT 0x93A1
+#define GL_BGRA_EXT 0x80E1
+#define GL_BLEND 0x0BE2
+#define GL_BLEND_ADVANCED_COHERENT_KHR 0x9285
+#define GL_BLEND_COLOR 0x8005
+#define GL_BLEND_DST_ALPHA 0x80CA
+#define GL_BLEND_DST_RGB 0x80C8
+#define GL_BLEND_EQUATION 0x8009
+#define GL_BLEND_EQUATION_ALPHA 0x883D
+#define GL_BLEND_EQUATION_RGB 0x8009
+#define GL_BLEND_SRC_ALPHA 0x80CB
+#define GL_BLEND_SRC_RGB 0x80C9
+#define GL_BLUE_BITS 0x0D54
+#define GL_BOOL 0x8B56
+#define GL_BOOL_VEC2 0x8B57
+#define GL_BOOL_VEC3 0x8B58
+#define GL_BOOL_VEC4 0x8B59
+#define GL_BUFFER_ACCESS_OES 0x88BB
+#define GL_BUFFER_IMMUTABLE_STORAGE_EXT 0x821F
+#define GL_BUFFER_KHR 0x82E0
+#define GL_BUFFER_MAPPED_OES 0x88BC
+#define GL_BUFFER_MAP_POINTER_OES 0x88BD
+#define GL_BUFFER_OBJECT_EXT 0x9151
+#define GL_BUFFER_SIZE 0x8764
+#define GL_BUFFER_STORAGE_FLAGS_EXT 0x8220
+#define GL_BUFFER_USAGE 0x8765
+#define GL_BYTE 0x1400
+#define GL_CCW 0x0901
+#define GL_CLAMP_TO_BORDER_EXT 0x812D
+#define GL_CLAMP_TO_BORDER_OES 0x812D
+#define GL_CLAMP_TO_EDGE 0x812F
+#define GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT_EXT 0x00004000
+#define GL_CLIENT_STORAGE_BIT_EXT 0x0200
+#define GL_CLIP_DEPTH_MODE 0x935D
+#define GL_CLIP_DEPTH_MODE_EXT 0x935D
+#define GL_CLIP_DISTANCE0_EXT 0x3000
+#define GL_CLIP_DISTANCE1_EXT 0x3001
+#define GL_CLIP_DISTANCE2_EXT 0x3002
+#define GL_CLIP_DISTANCE3_EXT 0x3003
+#define GL_CLIP_DISTANCE4_EXT 0x3004
+#define GL_CLIP_DISTANCE5_EXT 0x3005
+#define GL_CLIP_DISTANCE6 0x3006
+#define GL_CLIP_DISTANCE6_EXT 0x3006
+#define GL_CLIP_DISTANCE7 0x3007
+#define GL_CLIP_DISTANCE7_EXT 0x3007
+#define GL_CLIP_ORIGIN 0x935C
+#define GL_CLIP_ORIGIN_EXT 0x935C
+#define GL_CLIP_PLANE0 0x3000
+#define GL_CLIP_PLANE1 0x3001
+#define GL_CLIP_PLANE2 0x3002
+#define GL_CLIP_PLANE3 0x3003
+#define GL_CLIP_PLANE4 0x3004
+#define GL_CLIP_PLANE5 0x3005
+#define GL_COLORBURN_KHR 0x929A
+#define GL_COLORDODGE_KHR 0x9299
+#define GL_COLOR_ATTACHMENT0 0x8CE0
+#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0
+#define GL_COLOR_ATTACHMENT10_EXT 0x8CEA
+#define GL_COLOR_ATTACHMENT11_EXT 0x8CEB
+#define GL_COLOR_ATTACHMENT12_EXT 0x8CEC
+#define GL_COLOR_ATTACHMENT13_EXT 0x8CED
+#define GL_COLOR_ATTACHMENT14_EXT 0x8CEE
+#define GL_COLOR_ATTACHMENT15_EXT 0x8CEF
+#define GL_COLOR_ATTACHMENT1_EXT 0x8CE1
+#define GL_COLOR_ATTACHMENT2_EXT 0x8CE2
+#define GL_COLOR_ATTACHMENT3_EXT 0x8CE3
+#define GL_COLOR_ATTACHMENT4_EXT 0x8CE4
+#define GL_COLOR_ATTACHMENT5_EXT 0x8CE5
+#define GL_COLOR_ATTACHMENT6_EXT 0x8CE6
+#define GL_COLOR_ATTACHMENT7_EXT 0x8CE7
+#define GL_COLOR_ATTACHMENT8_EXT 0x8CE8
+#define GL_COLOR_ATTACHMENT9_EXT 0x8CE9
+#define GL_COLOR_ATTACHMENT_EXT 0x90F0
+#define GL_COLOR_BUFFER_BIT 0x00004000
+#define GL_COLOR_CLEAR_VALUE 0x0C22
+#define GL_COLOR_EXT 0x1800
+#define GL_COLOR_WRITEMASK 0x0C23
+#define GL_COMPARE_REF_TO_TEXTURE_EXT 0x884E
+#define GL_COMPILE_STATUS 0x8B81
+#define GL_COMPLETION_STATUS_KHR 0x91B1
+#define GL_COMPRESSED_RED_GREEN_RGTC2_EXT 0x8DBD
+#define GL_COMPRESSED_RED_RGTC1_EXT 0x8DBB
+#define GL_COMPRESSED_RGBA_ASTC_10x10_KHR 0x93BB
+#define GL_COMPRESSED_RGBA_ASTC_10x5_KHR 0x93B8
+#define GL_COMPRESSED_RGBA_ASTC_10x6_KHR 0x93B9
+#define GL_COMPRESSED_RGBA_ASTC_10x8_KHR 0x93BA
+#define GL_COMPRESSED_RGBA_ASTC_12x10_KHR 0x93BC
+#define GL_COMPRESSED_RGBA_ASTC_12x12_KHR 0x93BD
+#define GL_COMPRESSED_RGBA_ASTC_3x3x3_OES 0x93C0
+#define GL_COMPRESSED_RGBA_ASTC_4x3x3_OES 0x93C1
+#define GL_COMPRESSED_RGBA_ASTC_4x4_KHR 0x93B0
+#define GL_COMPRESSED_RGBA_ASTC_4x4x3_OES 0x93C2
+#define GL_COMPRESSED_RGBA_ASTC_4x4x4_OES 0x93C3
+#define GL_COMPRESSED_RGBA_ASTC_5x4_KHR 0x93B1
+#define GL_COMPRESSED_RGBA_ASTC_5x4x4_OES 0x93C4
+#define GL_COMPRESSED_RGBA_ASTC_5x5_KHR 0x93B2
+#define GL_COMPRESSED_RGBA_ASTC_5x5x4_OES 0x93C5
+#define GL_COMPRESSED_RGBA_ASTC_5x5x5_OES 0x93C6
+#define GL_COMPRESSED_RGBA_ASTC_6x5_KHR 0x93B3
+#define GL_COMPRESSED_RGBA_ASTC_6x5x5_OES 0x93C7
+#define GL_COMPRESSED_RGBA_ASTC_6x6_KHR 0x93B4
+#define GL_COMPRESSED_RGBA_ASTC_6x6x5_OES 0x93C8
+#define GL_COMPRESSED_RGBA_ASTC_6x6x6_OES 0x93C9
+#define GL_COMPRESSED_RGBA_ASTC_8x5_KHR 0x93B5
+#define GL_COMPRESSED_RGBA_ASTC_8x6_KHR 0x93B6
+#define GL_COMPRESSED_RGBA_ASTC_8x8_KHR 0x93B7
+#define GL_COMPRESSED_RGBA_BPTC_UNORM_EXT 0x8E8C
+#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
+#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
+#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
+#define GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT 0x8E8E
+#define GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT 0x8E8F
+#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
+#define GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT 0x8DBE
+#define GL_COMPRESSED_SIGNED_RED_RGTC1_EXT 0x8DBC
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR 0x93DB
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR 0x93D8
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR 0x93D9
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR 0x93DA
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR 0x93DC
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR 0x93DD
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_3x3x3_OES 0x93E0
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x3x3_OES 0x93E1
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR 0x93D0
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x3_OES 0x93E2
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x4_OES 0x93E3
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR 0x93D1
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4x4_OES 0x93E4
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR 0x93D2
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x4_OES 0x93E5
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x5_OES 0x93E6
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR 0x93D3
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5x5_OES 0x93E7
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR 0x93D4
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x5_OES 0x93E8
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x6_OES 0x93E9
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR 0x93D5
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR 0x93D6
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR 0x93D7
+#define GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT 0x8E8D
+#define GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT 0x8A56
+#define GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV2_IMG 0x93F0
+#define GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT 0x8A57
+#define GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV2_IMG 0x93F1
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT 0x8C4D
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT 0x8C4E
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT 0x8C4F
+#define GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT 0x8A54
+#define GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT 0x8A55
+#define GL_COMPRESSED_SRGB_S3TC_DXT1_EXT 0x8C4C
+#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3
+#define GL_CONSTANT_ALPHA 0x8003
+#define GL_CONSTANT_COLOR 0x8001
+#define GL_CONTEXT_FLAG_DEBUG_BIT_KHR 0x00000002
+#define GL_CONTEXT_FLAG_NO_ERROR_BIT 0x00000008
+#define GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR 0x00000008
+#define GL_CONTEXT_FLAG_PROTECTED_CONTENT_BIT_EXT 0x00000010
+#define GL_CONTEXT_LOST_KHR 0x0507
+#define GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR 0x82FC
+#define GL_CONTEXT_RELEASE_BEHAVIOR_KHR 0x82FB
+#define GL_CONTEXT_ROBUST_ACCESS_EXT 0x90F3
+#define GL_CONTEXT_ROBUST_ACCESS_KHR 0x90F3
+#define GL_CULL_FACE 0x0B44
+#define GL_CULL_FACE_MODE 0x0B45
+#define GL_CURRENT_PROGRAM 0x8B8D
+#define GL_CURRENT_QUERY_EXT 0x8865
+#define GL_CURRENT_VERTEX_ATTRIB 0x8626
+#define GL_CW 0x0900
+#define GL_D3D12_FENCE_VALUE_EXT 0x9595
+#define GL_DARKEN_KHR 0x9297
+#define GL_DEBUG_CALLBACK_FUNCTION_KHR 0x8244
+#define GL_DEBUG_CALLBACK_USER_PARAM_KHR 0x8245
+#define GL_DEBUG_GROUP_STACK_DEPTH_KHR 0x826D
+#define GL_DEBUG_LOGGED_MESSAGES_KHR 0x9145
+#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_KHR 0x8243
+#define GL_DEBUG_OUTPUT_KHR 0x92E0
+#define GL_DEBUG_OUTPUT_SYNCHRONOUS_KHR 0x8242
+#define GL_DEBUG_SEVERITY_HIGH_KHR 0x9146
+#define GL_DEBUG_SEVERITY_LOW_KHR 0x9148
+#define GL_DEBUG_SEVERITY_MEDIUM_KHR 0x9147
+#define GL_DEBUG_SEVERITY_NOTIFICATION_KHR 0x826B
+#define GL_DEBUG_SOURCE_API_KHR 0x8246
+#define GL_DEBUG_SOURCE_APPLICATION_KHR 0x824A
+#define GL_DEBUG_SOURCE_OTHER_KHR 0x824B
+#define GL_DEBUG_SOURCE_SHADER_COMPILER_KHR 0x8248
+#define GL_DEBUG_SOURCE_THIRD_PARTY_KHR 0x8249
+#define GL_DEBUG_SOURCE_WINDOW_SYSTEM_KHR 0x8247
+#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_KHR 0x824D
+#define GL_DEBUG_TYPE_ERROR_KHR 0x824C
+#define GL_DEBUG_TYPE_MARKER_KHR 0x8268
+#define GL_DEBUG_TYPE_OTHER_KHR 0x8251
+#define GL_DEBUG_TYPE_PERFORMANCE_KHR 0x8250
+#define GL_DEBUG_TYPE_POP_GROUP_KHR 0x826A
+#define GL_DEBUG_TYPE_PORTABILITY_KHR 0x824F
+#define GL_DEBUG_TYPE_PUSH_GROUP_KHR 0x8269
+#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_KHR 0x824E
+#define GL_DECODE_EXT 0x8A49
+#define GL_DECR 0x1E03
+#define GL_DECR_WRAP 0x8508
+#define GL_DEDICATED_MEMORY_OBJECT_EXT 0x9581
+#define GL_DELETE_STATUS 0x8B80
+#define GL_DEPTH24_STENCIL8_OES 0x88F0
+#define GL_DEPTH_ATTACHMENT 0x8D00
+#define GL_DEPTH_BITS 0x0D56
+#define GL_DEPTH_BUFFER_BIT 0x00000100
+#define GL_DEPTH_CLAMP_EXT 0x864F
+#define GL_DEPTH_CLEAR_VALUE 0x0B73
+#define GL_DEPTH_COMPONENT 0x1902
+#define GL_DEPTH_COMPONENT16 0x81A5
+#define GL_DEPTH_COMPONENT16_OES 0x81A5
+#define GL_DEPTH_COMPONENT24_OES 0x81A6
+#define GL_DEPTH_COMPONENT32_OES 0x81A7
+#define GL_DEPTH_EXT 0x1801
+#define GL_DEPTH_FUNC 0x0B74
+#define GL_DEPTH_RANGE 0x0B70
+#define GL_DEPTH_STENCIL_OES 0x84F9
+#define GL_DEPTH_TEST 0x0B71
+#define GL_DEPTH_WRITEMASK 0x0B72
+#define GL_DEVICE_LUID_EXT 0x9599
+#define GL_DEVICE_NODE_MASK_EXT 0x959A
+#define GL_DEVICE_UUID_EXT 0x9597
+#define GL_DIFFERENCE_KHR 0x929E
+#define GL_DITHER 0x0BD0
+#define GL_DONT_CARE 0x1100
+#define GL_DRAW_BUFFER0_EXT 0x8825
+#define GL_DRAW_BUFFER10_EXT 0x882F
+#define GL_DRAW_BUFFER11_EXT 0x8830
+#define GL_DRAW_BUFFER12_EXT 0x8831
+#define GL_DRAW_BUFFER13_EXT 0x8832
+#define GL_DRAW_BUFFER14_EXT 0x8833
+#define GL_DRAW_BUFFER15_EXT 0x8834
+#define GL_DRAW_BUFFER1_EXT 0x8826
+#define GL_DRAW_BUFFER2_EXT 0x8827
+#define GL_DRAW_BUFFER3_EXT 0x8828
+#define GL_DRAW_BUFFER4_EXT 0x8829
+#define GL_DRAW_BUFFER5_EXT 0x882A
+#define GL_DRAW_BUFFER6_EXT 0x882B
+#define GL_DRAW_BUFFER7_EXT 0x882C
+#define GL_DRAW_BUFFER8_EXT 0x882D
+#define GL_DRAW_BUFFER9_EXT 0x882E
+#define GL_DRAW_BUFFER_EXT 0x0C01
+#define GL_DRIVER_UUID_EXT 0x9598
+#define GL_DST_ALPHA 0x0304
+#define GL_DST_COLOR 0x0306
+#define GL_DYNAMIC_DRAW 0x88E8
+#define GL_DYNAMIC_STORAGE_BIT_EXT 0x0100
+#define GL_EFFECTIVE_RASTER_SAMPLES_EXT 0x932C
+#define GL_ELEMENT_ARRAY_BUFFER 0x8893
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895
+#define GL_EQUAL 0x0202
+#define GL_ETC1_RGB8_OES 0x8D64
+#define GL_EXCLUSION_KHR 0x92A0
+#define GL_EXCLUSIVE_EXT 0x8F11
+#define GL_EXTENSIONS 0x1F03
+#define GL_FALSE 0
+#define GL_FASTEST 0x1101
+#define GL_FIRST_VERTEX_CONVENTION_EXT 0x8E4D
+#define GL_FIRST_VERTEX_CONVENTION_OES 0x8E4D
+#define GL_FIXED 0x140C
+#define GL_FLOAT 0x1406
+#define GL_FLOAT_MAT2 0x8B5A
+#define GL_FLOAT_MAT3 0x8B5B
+#define GL_FLOAT_MAT4 0x8B5C
+#define GL_FLOAT_VEC2 0x8B50
+#define GL_FLOAT_VEC3 0x8B51
+#define GL_FLOAT_VEC4 0x8B52
+#define GL_FRACTIONAL_EVEN_EXT 0x8E7C
+#define GL_FRACTIONAL_EVEN_OES 0x8E7C
+#define GL_FRACTIONAL_ODD_EXT 0x8E7B
+#define GL_FRACTIONAL_ODD_OES 0x8E7B
+#define GL_FRAGMENT_INTERPOLATION_OFFSET_BITS_OES 0x8E5D
+#define GL_FRAGMENT_SHADER 0x8B30
+#define GL_FRAGMENT_SHADER_BIT_EXT 0x00000002
+#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES 0x8B8B
+#define GL_FRAGMENT_SHADER_DISCARDS_SAMPLES_EXT 0x8A52
+#define GL_FRAGMENT_SHADING_RATE_ATTACHMENT_WITH_DEFAULT_FRAMEBUFFER_SUPPORTED_EXT 0x96DF
+#define GL_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_EXT 0x96D2
+#define GL_FRAGMENT_SHADING_RATE_COMBINER_OP_MAX_EXT 0x96D5
+#define GL_FRAGMENT_SHADING_RATE_COMBINER_OP_MIN_EXT 0x96D4
+#define GL_FRAGMENT_SHADING_RATE_COMBINER_OP_MUL_EXT 0x96D6
+#define GL_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_EXT 0x96D3
+#define GL_FRAGMENT_SHADING_RATE_NON_TRIVIAL_COMBINERS_SUPPORTED_EXT 0x8F6F
+#define GL_FRAGMENT_SHADING_RATE_WITH_SAMPLE_MASK_SUPPORTED_EXT 0x96DE
+#define GL_FRAGMENT_SHADING_RATE_WITH_SHADER_DEPTH_STENCIL_WRITES_SUPPORTED_EXT 0x96DD
+#define GL_FRAMEBUFFER 0x8D40
+#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT 0x8210
+#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT 0x8211
+#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT 0x8DA7
+#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_OES 0x8DA7
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_OES 0x8CD4
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT 0x8D6C
+#define GL_FRAMEBUFFER_BINDING 0x8CA6
+#define GL_FRAMEBUFFER_COMPLETE 0x8CD5
+#define GL_FRAMEBUFFER_DEFAULT_LAYERS_EXT 0x9312
+#define GL_FRAMEBUFFER_DEFAULT_LAYERS_OES 0x9312
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9
+#define GL_FRAMEBUFFER_INCOMPLETE_INSUFFICIENT_SHADER_COMBINED_LOCAL_STORAGE_EXT 0x9652
+#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT 0x8DA8
+#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_OES 0x8DA8
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x8D56
+#define GL_FRAMEBUFFER_SRGB_EXT 0x8DB9
+#define GL_FRAMEBUFFER_UNDEFINED_OES 0x8219
+#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD
+#define GL_FRONT 0x0404
+#define GL_FRONT_AND_BACK 0x0408
+#define GL_FRONT_FACE 0x0B46
+#define GL_FUNC_ADD 0x8006
+#define GL_FUNC_REVERSE_SUBTRACT 0x800B
+#define GL_FUNC_SUBTRACT 0x800A
+#define GL_GENERATE_MIPMAP_HINT 0x8192
+#define GL_GEOMETRY_LINKED_INPUT_TYPE_EXT 0x8917
+#define GL_GEOMETRY_LINKED_INPUT_TYPE_OES 0x8917
+#define GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT 0x8918
+#define GL_GEOMETRY_LINKED_OUTPUT_TYPE_OES 0x8918
+#define GL_GEOMETRY_LINKED_VERTICES_OUT_EXT 0x8916
+#define GL_GEOMETRY_LINKED_VERTICES_OUT_OES 0x8916
+#define GL_GEOMETRY_SHADER_BIT_EXT 0x00000004
+#define GL_GEOMETRY_SHADER_BIT_OES 0x00000004
+#define GL_GEOMETRY_SHADER_EXT 0x8DD9
+#define GL_GEOMETRY_SHADER_INVOCATIONS_EXT 0x887F
+#define GL_GEOMETRY_SHADER_INVOCATIONS_OES 0x887F
+#define GL_GEOMETRY_SHADER_OES 0x8DD9
+#define GL_GEQUAL 0x0206
+#define GL_GPU_DISJOINT_EXT 0x8FBB
+#define GL_GREATER 0x0204
+#define GL_GREEN_BITS 0x0D53
+#define GL_GUILTY_CONTEXT_RESET_EXT 0x8253
+#define GL_GUILTY_CONTEXT_RESET_KHR 0x8253
+#define GL_HALF_FLOAT_OES 0x8D61
+#define GL_HANDLE_TYPE_D3D11_IMAGE_EXT 0x958B
+#define GL_HANDLE_TYPE_D3D11_IMAGE_KMT_EXT 0x958C
+#define GL_HANDLE_TYPE_D3D12_FENCE_EXT 0x9594
+#define GL_HANDLE_TYPE_D3D12_RESOURCE_EXT 0x958A
+#define GL_HANDLE_TYPE_D3D12_TILEPOOL_EXT 0x9589
+#define GL_HANDLE_TYPE_OPAQUE_FD_EXT 0x9586
+#define GL_HANDLE_TYPE_OPAQUE_WIN32_EXT 0x9587
+#define GL_HANDLE_TYPE_OPAQUE_WIN32_KMT_EXT 0x9588
+#define GL_HARDLIGHT_KHR 0x929B
+#define GL_HIGH_FLOAT 0x8DF2
+#define GL_HIGH_INT 0x8DF5
+#define GL_HSL_COLOR_KHR 0x92AF
+#define GL_HSL_HUE_KHR 0x92AD
+#define GL_HSL_LUMINOSITY_KHR 0x92B0
+#define GL_HSL_SATURATION_KHR 0x92AE
+#define GL_IMAGE_BUFFER_EXT 0x9051
+#define GL_IMAGE_BUFFER_OES 0x9051
+#define GL_IMAGE_CUBE_MAP_ARRAY_EXT 0x9054
+#define GL_IMAGE_CUBE_MAP_ARRAY_OES 0x9054
+#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B
+#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A
+#define GL_INCLUSIVE_EXT 0x8F10
+#define GL_INCR 0x1E02
+#define GL_INCR_WRAP 0x8507
+#define GL_INFO_LOG_LENGTH 0x8B84
+#define GL_INNOCENT_CONTEXT_RESET_EXT 0x8254
+#define GL_INNOCENT_CONTEXT_RESET_KHR 0x8254
+#define GL_INT 0x1404
+#define GL_INT_10_10_10_2_OES 0x8DF7
+#define GL_INT_IMAGE_BUFFER_EXT 0x905C
+#define GL_INT_IMAGE_BUFFER_OES 0x905C
+#define GL_INT_IMAGE_CUBE_MAP_ARRAY_EXT 0x905F
+#define GL_INT_IMAGE_CUBE_MAP_ARRAY_OES 0x905F
+#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY_OES 0x910C
+#define GL_INT_SAMPLER_BUFFER_EXT 0x8DD0
+#define GL_INT_SAMPLER_BUFFER_OES 0x8DD0
+#define GL_INT_SAMPLER_CUBE_MAP_ARRAY_EXT 0x900E
+#define GL_INT_SAMPLER_CUBE_MAP_ARRAY_OES 0x900E
+#define GL_INT_VEC2 0x8B53
+#define GL_INT_VEC3 0x8B54
+#define GL_INT_VEC4 0x8B55
+#define GL_INVALID_ENUM 0x0500
+#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506
+#define GL_INVALID_OPERATION 0x0502
+#define GL_INVALID_VALUE 0x0501
+#define GL_INVERT 0x150A
+#define GL_ISOLINES_EXT 0x8E7A
+#define GL_ISOLINES_OES 0x8E7A
+#define GL_IS_PER_PATCH_EXT 0x92E7
+#define GL_IS_PER_PATCH_OES 0x92E7
+#define GL_KEEP 0x1E00
+#define GL_LAST_VERTEX_CONVENTION_EXT 0x8E4E
+#define GL_LAST_VERTEX_CONVENTION_OES 0x8E4E
+#define GL_LAYER_PROVOKING_VERTEX_EXT 0x825E
+#define GL_LAYER_PROVOKING_VERTEX_OES 0x825E
+#define GL_LAYOUT_COLOR_ATTACHMENT_EXT 0x958E
+#define GL_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_EXT 0x9531
+#define GL_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_EXT 0x9530
+#define GL_LAYOUT_DEPTH_STENCIL_ATTACHMENT_EXT 0x958F
+#define GL_LAYOUT_DEPTH_STENCIL_READ_ONLY_EXT 0x9590
+#define GL_LAYOUT_GENERAL_EXT 0x958D
+#define GL_LAYOUT_SHADER_READ_ONLY_EXT 0x9591
+#define GL_LAYOUT_TRANSFER_DST_EXT 0x9593
+#define GL_LAYOUT_TRANSFER_SRC_EXT 0x9592
+#define GL_LEQUAL 0x0203
+#define GL_LESS 0x0201
+#define GL_LIGHTEN_KHR 0x9298
+#define GL_LINEAR 0x2601
+#define GL_LINEAR_MIPMAP_LINEAR 0x2703
+#define GL_LINEAR_MIPMAP_NEAREST 0x2701
+#define GL_LINEAR_TILING_EXT 0x9585
+#define GL_LINES 0x0001
+#define GL_LINES_ADJACENCY_EXT 0x000A
+#define GL_LINES_ADJACENCY_OES 0x000A
+#define GL_LINE_LOOP 0x0002
+#define GL_LINE_STRIP 0x0003
+#define GL_LINE_STRIP_ADJACENCY_EXT 0x000B
+#define GL_LINE_STRIP_ADJACENCY_OES 0x000B
+#define GL_LINE_WIDTH 0x0B21
+#define GL_LINK_STATUS 0x8B82
+#define GL_LOCATION_INDEX_EXT 0x930F
+#define GL_LOSE_CONTEXT_ON_RESET_EXT 0x8252
+#define GL_LOSE_CONTEXT_ON_RESET_KHR 0x8252
+#define GL_LOWER_LEFT 0x8CA1
+#define GL_LOWER_LEFT_EXT 0x8CA1
+#define GL_LOW_FLOAT 0x8DF0
+#define GL_LOW_INT 0x8DF3
+#define GL_LUID_SIZE_EXT 8
+#define GL_LUMINANCE 0x1909
+#define GL_LUMINANCE16F_EXT 0x881E
+#define GL_LUMINANCE32F_EXT 0x8818
+#define GL_LUMINANCE4_ALPHA4_OES 0x8043
+#define GL_LUMINANCE8_ALPHA8_EXT 0x8045
+#define GL_LUMINANCE8_ALPHA8_OES 0x8045
+#define GL_LUMINANCE8_EXT 0x8040
+#define GL_LUMINANCE8_OES 0x8040
+#define GL_LUMINANCE_ALPHA 0x190A
+#define GL_LUMINANCE_ALPHA16F_EXT 0x881F
+#define GL_LUMINANCE_ALPHA32F_EXT 0x8819
+#define GL_MAP_COHERENT_BIT_EXT 0x0080
+#define GL_MAP_FLUSH_EXPLICIT_BIT_EXT 0x0010
+#define GL_MAP_INVALIDATE_BUFFER_BIT_EXT 0x0008
+#define GL_MAP_INVALIDATE_RANGE_BIT_EXT 0x0004
+#define GL_MAP_PERSISTENT_BIT_EXT 0x0040
+#define GL_MAP_READ_BIT 0x0001
+#define GL_MAP_READ_BIT_EXT 0x0001
+#define GL_MAP_UNSYNCHRONIZED_BIT_EXT 0x0020
+#define GL_MAP_WRITE_BIT 0x0002
+#define GL_MAP_WRITE_BIT_EXT 0x0002
+#define GL_MAX 0x8008
+#define GL_MAX_3D_TEXTURE_SIZE_OES 0x8073
+#define GL_MAX_CLIP_DISTANCES_EXT 0x0D32
+#define GL_MAX_CLIP_PLANES 0x0D32
+#define GL_MAX_COLOR_ATTACHMENTS_EXT 0x8CDF
+#define GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES 0x82FA
+#define GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES_EXT 0x82FA
+#define GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS_EXT 0x8A32
+#define GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS_OES 0x8A32
+#define GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS_EXT 0x8E1E
+#define GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS_OES 0x8E1E
+#define GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS_EXT 0x8E1F
+#define GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS_OES 0x8E1F
+#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C
+#define GL_MAX_CULL_DISTANCES 0x82F9
+#define GL_MAX_CULL_DISTANCES_EXT 0x82F9
+#define GL_MAX_DEBUG_GROUP_STACK_DEPTH_KHR 0x826C
+#define GL_MAX_DEBUG_LOGGED_MESSAGES_KHR 0x9144
+#define GL_MAX_DEBUG_MESSAGE_LENGTH_KHR 0x9143
+#define GL_MAX_DRAW_BUFFERS_EXT 0x8824
+#define GL_MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT 0x88FC
+#define GL_MAX_EXT 0x8008
+#define GL_MAX_FRAGMENT_INTERPOLATION_OFFSET_OES 0x8E5C
+#define GL_MAX_FRAGMENT_SHADING_RATE_ATTACHMENT_LAYERS_EXT 0x96DC
+#define GL_MAX_FRAGMENT_SHADING_RATE_ATTACHMENT_TEXEL_ASPECT_RATIO_EXT 0x96DB
+#define GL_MAX_FRAGMENT_SHADING_RATE_ATTACHMENT_TEXEL_HEIGHT_EXT 0x96DA
+#define GL_MAX_FRAGMENT_SHADING_RATE_ATTACHMENT_TEXEL_WIDTH_EXT 0x96D8
+#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD
+#define GL_MAX_FRAMEBUFFER_LAYERS_EXT 0x9317
+#define GL_MAX_FRAMEBUFFER_LAYERS_OES 0x9317
+#define GL_MAX_GEOMETRY_ATOMIC_COUNTERS_EXT 0x92D5
+#define GL_MAX_GEOMETRY_ATOMIC_COUNTERS_OES 0x92D5
+#define GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT 0x92CF
+#define GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_OES 0x92CF
+#define GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT 0x90CD
+#define GL_MAX_GEOMETRY_IMAGE_UNIFORMS_OES 0x90CD
+#define GL_MAX_GEOMETRY_INPUT_COMPONENTS_EXT 0x9123
+#define GL_MAX_GEOMETRY_INPUT_COMPONENTS_OES 0x9123
+#define GL_MAX_GEOMETRY_OUTPUT_COMPONENTS_EXT 0x9124
+#define GL_MAX_GEOMETRY_OUTPUT_COMPONENTS_OES 0x9124
+#define GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT 0x8DE0
+#define GL_MAX_GEOMETRY_OUTPUT_VERTICES_OES 0x8DE0
+#define GL_MAX_GEOMETRY_SHADER_INVOCATIONS_EXT 0x8E5A
+#define GL_MAX_GEOMETRY_SHADER_INVOCATIONS_OES 0x8E5A
+#define GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT 0x90D7
+#define GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_OES 0x90D7
+#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT 0x8C29
+#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_OES 0x8C29
+#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT 0x8DE1
+#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_OES 0x8DE1
+#define GL_MAX_GEOMETRY_UNIFORM_BLOCKS_EXT 0x8A2C
+#define GL_MAX_GEOMETRY_UNIFORM_BLOCKS_OES 0x8A2C
+#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT 0x8DDF
+#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_OES 0x8DDF
+#define GL_MAX_LABEL_LENGTH_KHR 0x82E8
+#define GL_MAX_MULTIVIEW_BUFFERS_EXT 0x90F2
+#define GL_MAX_PATCH_VERTICES_EXT 0x8E7D
+#define GL_MAX_PATCH_VERTICES_OES 0x8E7D
+#define GL_MAX_RASTER_SAMPLES_EXT 0x9329
+#define GL_MAX_RENDERBUFFER_SIZE 0x84E8
+#define GL_MAX_SAMPLES_EXT 0x8D57
+#define GL_MAX_SHADER_COMBINED_LOCAL_STORAGE_FAST_SIZE_EXT 0x9650
+#define GL_MAX_SHADER_COMBINED_LOCAL_STORAGE_SIZE_EXT 0x9651
+#define GL_MAX_SHADER_COMPILER_THREADS_KHR 0x91B0
+#define GL_MAX_SHADER_PIXEL_LOCAL_STORAGE_FAST_SIZE_EXT 0x8F63
+#define GL_MAX_SHADER_PIXEL_LOCAL_STORAGE_SIZE_EXT 0x8F67
+#define GL_MAX_SPARSE_3D_TEXTURE_SIZE_EXT 0x9199
+#define GL_MAX_SPARSE_ARRAY_TEXTURE_LAYERS_EXT 0x919A
+#define GL_MAX_SPARSE_TEXTURE_SIZE_EXT 0x9198
+#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS_EXT 0x92D3
+#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS_OES 0x92D3
+#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS_EXT 0x92CD
+#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS_OES 0x92CD
+#define GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS_EXT 0x90CB
+#define GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS_OES 0x90CB
+#define GL_MAX_TESS_CONTROL_INPUT_COMPONENTS_EXT 0x886C
+#define GL_MAX_TESS_CONTROL_INPUT_COMPONENTS_OES 0x886C
+#define GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS_EXT 0x8E83
+#define GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS_OES 0x8E83
+#define GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS_EXT 0x90D8
+#define GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS_OES 0x90D8
+#define GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS_EXT 0x8E81
+#define GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS_OES 0x8E81
+#define GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS_EXT 0x8E85
+#define GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS_OES 0x8E85
+#define GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS_EXT 0x8E89
+#define GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS_OES 0x8E89
+#define GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS_EXT 0x8E7F
+#define GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS_OES 0x8E7F
+#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS_EXT 0x92D4
+#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS_OES 0x92D4
+#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS_EXT 0x92CE
+#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS_OES 0x92CE
+#define GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS_EXT 0x90CC
+#define GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS_OES 0x90CC
+#define GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS_EXT 0x886D
+#define GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS_OES 0x886D
+#define GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS_EXT 0x8E86
+#define GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS_OES 0x8E86
+#define GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS_EXT 0x90D9
+#define GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS_OES 0x90D9
+#define GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS_EXT 0x8E82
+#define GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS_OES 0x8E82
+#define GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS_EXT 0x8E8A
+#define GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS_OES 0x8E8A
+#define GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS_EXT 0x8E80
+#define GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS_OES 0x8E80
+#define GL_MAX_TESS_GEN_LEVEL_EXT 0x8E7E
+#define GL_MAX_TESS_GEN_LEVEL_OES 0x8E7E
+#define GL_MAX_TESS_PATCH_COMPONENTS_EXT 0x8E84
+#define GL_MAX_TESS_PATCH_COMPONENTS_OES 0x8E84
+#define GL_MAX_TEXTURE_BUFFER_SIZE_EXT 0x8C2B
+#define GL_MAX_TEXTURE_BUFFER_SIZE_OES 0x8C2B
+#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872
+#define GL_MAX_TEXTURE_MAX_ANISOTROPY 0x84FF
+#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
+#define GL_MAX_TEXTURE_SIZE 0x0D33
+#define GL_MAX_VARYING_VECTORS 0x8DFC
+#define GL_MAX_VERTEX_ATTRIBS 0x8869
+#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C
+#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB
+#define GL_MAX_VIEWPORTS_OES 0x825B
+#define GL_MAX_VIEWPORT_DIMS 0x0D3A
+#define GL_MAX_WINDOW_RECTANGLES_EXT 0x8F14
+#define GL_MEDIUM_FLOAT 0x8DF1
+#define GL_MEDIUM_INT 0x8DF4
+#define GL_MIN 0x8007
+#define GL_MIN_EXT 0x8007
+#define GL_MIN_FRAGMENT_INTERPOLATION_OFFSET_OES 0x8E5B
+#define GL_MIN_FRAGMENT_SHADING_RATE_ATTACHMENT_TEXEL_HEIGHT_EXT 0x96D9
+#define GL_MIN_FRAGMENT_SHADING_RATE_ATTACHMENT_TEXEL_WIDTH_EXT 0x96D7
+#define GL_MIN_SAMPLE_SHADING_VALUE_OES 0x8C37
+#define GL_MIRRORED_REPEAT 0x8370
+#define GL_MIRROR_CLAMP_TO_EDGE_EXT 0x8743
+#define GL_MULTIPLY_KHR 0x9294
+#define GL_MULTISAMPLE_EXT 0x809D
+#define GL_MULTISAMPLE_RASTERIZATION_ALLOWED_EXT 0x932B
+#define GL_MULTIVIEW_EXT 0x90F1
+#define GL_NEAREST 0x2600
+#define GL_NEAREST_MIPMAP_LINEAR 0x2702
+#define GL_NEAREST_MIPMAP_NEAREST 0x2700
+#define GL_NEGATIVE_ONE_TO_ONE 0x935E
+#define GL_NEGATIVE_ONE_TO_ONE_EXT 0x935E
+#define GL_NEVER 0x0200
+#define GL_NICEST 0x1102
+#define GL_NONE 0
+#define GL_NOTEQUAL 0x0205
+#define GL_NO_ERROR 0
+#define GL_NO_RESET_NOTIFICATION_EXT 0x8261
+#define GL_NO_RESET_NOTIFICATION_KHR 0x8261
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
+#define GL_NUM_DEVICE_UUIDS_EXT 0x9596
+#define GL_NUM_PROGRAM_BINARY_FORMATS_OES 0x87FE
+#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9
+#define GL_NUM_SPARSE_LEVELS_EXT 0x91AA
+#define GL_NUM_SURFACE_COMPRESSION_FIXED_RATES_EXT 0x8F6E
+#define GL_NUM_TILING_TYPES_EXT 0x9582
+#define GL_NUM_VIRTUAL_PAGE_SIZES_EXT 0x91A8
+#define GL_NUM_WINDOW_RECTANGLES_EXT 0x8F15
+#define GL_ONE 1
+#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004
+#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002
+#define GL_ONE_MINUS_DST_ALPHA 0x0305
+#define GL_ONE_MINUS_DST_COLOR 0x0307
+#define GL_ONE_MINUS_SRC1_ALPHA_EXT 0x88FB
+#define GL_ONE_MINUS_SRC1_COLOR_EXT 0x88FA
+#define GL_ONE_MINUS_SRC_ALPHA 0x0303
+#define GL_ONE_MINUS_SRC_COLOR 0x0301
+#define GL_OPTIMAL_TILING_EXT 0x9584
+#define GL_OUT_OF_MEMORY 0x0505
+#define GL_OVERLAY_KHR 0x9296
+#define GL_PACK_ALIGNMENT 0x0D05
+#define GL_PALETTE4_R5_G6_B5_OES 0x8B92
+#define GL_PALETTE4_RGB5_A1_OES 0x8B94
+#define GL_PALETTE4_RGB8_OES 0x8B90
+#define GL_PALETTE4_RGBA4_OES 0x8B93
+#define GL_PALETTE4_RGBA8_OES 0x8B91
+#define GL_PALETTE8_R5_G6_B5_OES 0x8B97
+#define GL_PALETTE8_RGB5_A1_OES 0x8B99
+#define GL_PALETTE8_RGB8_OES 0x8B95
+#define GL_PALETTE8_RGBA4_OES 0x8B98
+#define GL_PALETTE8_RGBA8_OES 0x8B96
+#define GL_PATCHES_EXT 0x000E
+#define GL_PATCHES_OES 0x000E
+#define GL_PATCH_VERTICES_EXT 0x8E72
+#define GL_PATCH_VERTICES_OES 0x8E72
+#define GL_POINTS 0x0000
+#define GL_POLYGON_OFFSET_CLAMP 0x8E1B
+#define GL_POLYGON_OFFSET_CLAMP_EXT 0x8E1B
+#define GL_POLYGON_OFFSET_FACTOR 0x8038
+#define GL_POLYGON_OFFSET_FILL 0x8037
+#define GL_POLYGON_OFFSET_UNITS 0x2A00
+#define GL_PRIMITIVES_GENERATED_EXT 0x8C87
+#define GL_PRIMITIVES_GENERATED_OES 0x8C87
+#define GL_PRIMITIVE_BOUNDING_BOX_EXT 0x92BE
+#define GL_PRIMITIVE_BOUNDING_BOX_OES 0x92BE
+#define GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED 0x8221
+#define GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED_OES 0x8221
+#define GL_PROGRAM_BINARY_FORMATS_OES 0x87FF
+#define GL_PROGRAM_BINARY_LENGTH_OES 0x8741
+#define GL_PROGRAM_KHR 0x82E2
+#define GL_PROGRAM_OBJECT_EXT 0x8B40
+#define GL_PROGRAM_PIPELINE_BINDING_EXT 0x825A
+#define GL_PROGRAM_PIPELINE_KHR 0x82E4
+#define GL_PROGRAM_PIPELINE_OBJECT_EXT 0x8A4F
+#define GL_PROGRAM_SEPARABLE_EXT 0x8258
+#define GL_PROTECTED_MEMORY_OBJECT_EXT 0x959B
+#define GL_QUADS_EXT 0x0007
+#define GL_QUADS_OES 0x0007
+#define GL_QUERY_COUNTER_BITS_EXT 0x8864
+#define GL_QUERY_KHR 0x82E3
+#define GL_QUERY_OBJECT_EXT 0x9153
+#define GL_QUERY_RESULT_AVAILABLE_EXT 0x8867
+#define GL_QUERY_RESULT_EXT 0x8866
+#define GL_R16F_EXT 0x822D
+#define GL_R16_EXT 0x822A
+#define GL_R16_SNORM_EXT 0x8F98
+#define GL_R32F_EXT 0x822E
+#define GL_R8_EXT 0x8229
+#define GL_R8_SNORM 0x8F94
+#define GL_RASTER_FIXED_SAMPLE_LOCATIONS_EXT 0x932A
+#define GL_RASTER_MULTISAMPLE_EXT 0x9327
+#define GL_RASTER_SAMPLES_EXT 0x9328
+#define GL_READ_BUFFER_EXT 0x0C02
+#define GL_RED_BITS 0x0D52
+#define GL_RED_EXT 0x1903
+#define GL_REFERENCED_BY_GEOMETRY_SHADER_EXT 0x9309
+#define GL_REFERENCED_BY_GEOMETRY_SHADER_OES 0x9309
+#define GL_REFERENCED_BY_TESS_CONTROL_SHADER_EXT 0x9307
+#define GL_REFERENCED_BY_TESS_CONTROL_SHADER_OES 0x9307
+#define GL_REFERENCED_BY_TESS_EVALUATION_SHADER_EXT 0x9308
+#define GL_REFERENCED_BY_TESS_EVALUATION_SHADER_OES 0x9308
+#define GL_RENDERBUFFER 0x8D41
+#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53
+#define GL_RENDERBUFFER_BINDING 0x8CA7
+#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52
+#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54
+#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51
+#define GL_RENDERBUFFER_HEIGHT 0x8D43
+#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44
+#define GL_RENDERBUFFER_RED_SIZE 0x8D50
+#define GL_RENDERBUFFER_SAMPLES_EXT 0x8CAB
+#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55
+#define GL_RENDERBUFFER_WIDTH 0x8D42
+#define GL_RENDERER 0x1F01
+#define GL_REPEAT 0x2901
+#define GL_REPLACE 0x1E01
+#define GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES 0x8D68
+#define GL_RESET_NOTIFICATION_STRATEGY_EXT 0x8256
+#define GL_RESET_NOTIFICATION_STRATEGY_KHR 0x8256
+#define GL_RG16F_EXT 0x822F
+#define GL_RG16_EXT 0x822C
+#define GL_RG16_SNORM_EXT 0x8F99
+#define GL_RG32F_EXT 0x8230
+#define GL_RG8_EXT 0x822B
+#define GL_RG8_SNORM 0x8F95
+#define GL_RGB 0x1907
+#define GL_RGB10_A2_EXT 0x8059
+#define GL_RGB10_EXT 0x8052
+#define GL_RGB16F_EXT 0x881B
+#define GL_RGB16_EXT 0x8054
+#define GL_RGB16_SNORM_EXT 0x8F9A
+#define GL_RGB32F_EXT 0x8815
+#define GL_RGB565 0x8D62
+#define GL_RGB565_OES 0x8D62
+#define GL_RGB5_A1 0x8057
+#define GL_RGB5_A1_OES 0x8057
+#define GL_RGB8_OES 0x8051
+#define GL_RGBA 0x1908
+#define GL_RGBA16F_EXT 0x881A
+#define GL_RGBA16_EXT 0x805B
+#define GL_RGBA16_SNORM_EXT 0x8F9B
+#define GL_RGBA32F_EXT 0x8814
+#define GL_RGBA4 0x8056
+#define GL_RGBA4_OES 0x8056
+#define GL_RGBA8_OES 0x8058
+#define GL_RGBA8_SNORM 0x8F97
+#define GL_RG_EXT 0x8227
+#define GL_SAMPLER 0x82E6
+#define GL_SAMPLER_2D 0x8B5E
+#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY_OES 0x910B
+#define GL_SAMPLER_2D_SHADOW_EXT 0x8B62
+#define GL_SAMPLER_3D_OES 0x8B5F
+#define GL_SAMPLER_BUFFER_EXT 0x8DC2
+#define GL_SAMPLER_BUFFER_OES 0x8DC2
+#define GL_SAMPLER_CUBE 0x8B60
+#define GL_SAMPLER_CUBE_MAP_ARRAY_EXT 0x900C
+#define GL_SAMPLER_CUBE_MAP_ARRAY_OES 0x900C
+#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_EXT 0x900D
+#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_OES 0x900D
+#define GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT 0x8BE7
+#define GL_SAMPLER_EXTERNAL_OES 0x8D66
+#define GL_SAMPLER_KHR 0x82E6
+#define GL_SAMPLES 0x80A9
+#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E
+#define GL_SAMPLE_ALPHA_TO_ONE_EXT 0x809F
+#define GL_SAMPLE_BUFFERS 0x80A8
+#define GL_SAMPLE_COVERAGE 0x80A0
+#define GL_SAMPLE_COVERAGE_INVERT 0x80AB
+#define GL_SAMPLE_COVERAGE_VALUE 0x80AA
+#define GL_SAMPLE_SHADING_OES 0x8C36
+#define GL_SCISSOR_BOX 0x0C10
+#define GL_SCISSOR_TEST 0x0C11
+#define GL_SCREEN_KHR 0x9295
+#define GL_SHADER_BINARY_FORMATS 0x8DF8
+#define GL_SHADER_COMPILER 0x8DFA
+#define GL_SHADER_KHR 0x82E1
+#define GL_SHADER_OBJECT_EXT 0x8B48
+#define GL_SHADER_PIXEL_LOCAL_STORAGE_EXT 0x8F64
+#define GL_SHADER_SOURCE_LENGTH 0x8B88
+#define GL_SHADER_TYPE 0x8B4F
+#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
+#define GL_SHADING_RATE_1X1_PIXELS_EXT 0x96A6
+#define GL_SHADING_RATE_1X1_PIXELS_QCOM 0x96A6
+#define GL_SHADING_RATE_1X2_PIXELS_EXT 0x96A7
+#define GL_SHADING_RATE_1X2_PIXELS_QCOM 0x96A7
+#define GL_SHADING_RATE_1X4_PIXELS_EXT 0x96AA
+#define GL_SHADING_RATE_1X4_PIXELS_QCOM 0x96AA
+#define GL_SHADING_RATE_2X1_PIXELS_EXT 0x96A8
+#define GL_SHADING_RATE_2X1_PIXELS_QCOM 0x96A8
+#define GL_SHADING_RATE_2X2_PIXELS_EXT 0x96A9
+#define GL_SHADING_RATE_2X2_PIXELS_QCOM 0x96A9
+#define GL_SHADING_RATE_2X4_PIXELS_EXT 0x96AD
+#define GL_SHADING_RATE_2X4_PIXELS_QCOM 0x96AD
+#define GL_SHADING_RATE_4X1_PIXELS_EXT 0x96AB
+#define GL_SHADING_RATE_4X1_PIXELS_QCOM 0x96AB
+#define GL_SHADING_RATE_4X2_PIXELS_EXT 0x96AC
+#define GL_SHADING_RATE_4X2_PIXELS_QCOM 0x96AC
+#define GL_SHADING_RATE_4X4_PIXELS_EXT 0x96AE
+#define GL_SHADING_RATE_4X4_PIXELS_QCOM 0x96AE
+#define GL_SHADING_RATE_ATTACHMENT_EXT 0x96D1
+#define GL_SHADING_RATE_EXT 0x96D0
+#define GL_SHORT 0x1402
+#define GL_SKIP_DECODE_EXT 0x8A4A
+#define GL_SOFTLIGHT_KHR 0x929C
+#define GL_SPARSE_TEXTURE_FULL_ARRAY_CUBE_MIPMAPS_EXT 0x91A9
+#define GL_SR8_EXT 0x8FBD
+#define GL_SRC1_ALPHA_EXT 0x8589
+#define GL_SRC1_COLOR_EXT 0x88F9
+#define GL_SRC_ALPHA 0x0302
+#define GL_SRC_ALPHA_SATURATE 0x0308
+#define GL_SRC_ALPHA_SATURATE_EXT 0x0308
+#define GL_SRC_COLOR 0x0300
+#define GL_SRG8_EXT 0x8FBE
+#define GL_SRGB8_ALPHA8_EXT 0x8C43
+#define GL_SRGB_ALPHA_EXT 0x8C42
+#define GL_SRGB_EXT 0x8C40
+#define GL_STACK_OVERFLOW_KHR 0x0503
+#define GL_STACK_UNDERFLOW_KHR 0x0504
+#define GL_STATIC_DRAW 0x88E4
+#define GL_STENCIL_ATTACHMENT 0x8D20
+#define GL_STENCIL_BACK_FAIL 0x8801
+#define GL_STENCIL_BACK_FUNC 0x8800
+#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802
+#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803
+#define GL_STENCIL_BACK_REF 0x8CA3
+#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4
+#define GL_STENCIL_BACK_WRITEMASK 0x8CA5
+#define GL_STENCIL_BITS 0x0D57
+#define GL_STENCIL_BUFFER_BIT 0x00000400
+#define GL_STENCIL_CLEAR_VALUE 0x0B91
+#define GL_STENCIL_EXT 0x1802
+#define GL_STENCIL_FAIL 0x0B94
+#define GL_STENCIL_FUNC 0x0B92
+#define GL_STENCIL_INDEX1_OES 0x8D46
+#define GL_STENCIL_INDEX4_OES 0x8D47
+#define GL_STENCIL_INDEX8 0x8D48
+#define GL_STENCIL_INDEX8_OES 0x8D48
+#define GL_STENCIL_INDEX_OES 0x1901
+#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95
+#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96
+#define GL_STENCIL_REF 0x0B97
+#define GL_STENCIL_TEST 0x0B90
+#define GL_STENCIL_VALUE_MASK 0x0B93
+#define GL_STENCIL_WRITEMASK 0x0B98
+#define GL_STREAM_DRAW 0x88E0
+#define GL_SUBGROUP_FEATURE_ARITHMETIC_BIT_KHR 0x00000004
+#define GL_SUBGROUP_FEATURE_BALLOT_BIT_KHR 0x00000008
+#define GL_SUBGROUP_FEATURE_BASIC_BIT_KHR 0x00000001
+#define GL_SUBGROUP_FEATURE_CLUSTERED_BIT_KHR 0x00000040
+#define GL_SUBGROUP_FEATURE_QUAD_BIT_KHR 0x00000080
+#define GL_SUBGROUP_FEATURE_SHUFFLE_BIT_KHR 0x00000010
+#define GL_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT_KHR 0x00000020
+#define GL_SUBGROUP_FEATURE_VOTE_BIT_KHR 0x00000002
+#define GL_SUBGROUP_QUAD_ALL_STAGES_KHR 0x9535
+#define GL_SUBGROUP_SIZE_KHR 0x9532
+#define GL_SUBGROUP_SUPPORTED_FEATURES_KHR 0x9534
+#define GL_SUBGROUP_SUPPORTED_STAGES_KHR 0x9533
+#define GL_SUBPIXEL_BITS 0x0D50
+#define GL_SURFACE_COMPRESSION_EXT 0x96C0
+#define GL_SURFACE_COMPRESSION_FIXED_RATE_10BPC_EXT 0x96CD
+#define GL_SURFACE_COMPRESSION_FIXED_RATE_11BPC_EXT 0x96CE
+#define GL_SURFACE_COMPRESSION_FIXED_RATE_12BPC_EXT 0x96CF
+#define GL_SURFACE_COMPRESSION_FIXED_RATE_1BPC_EXT 0x96C4
+#define GL_SURFACE_COMPRESSION_FIXED_RATE_2BPC_EXT 0x96C5
+#define GL_SURFACE_COMPRESSION_FIXED_RATE_3BPC_EXT 0x96C6
+#define GL_SURFACE_COMPRESSION_FIXED_RATE_4BPC_EXT 0x96C7
+#define GL_SURFACE_COMPRESSION_FIXED_RATE_5BPC_EXT 0x96C8
+#define GL_SURFACE_COMPRESSION_FIXED_RATE_6BPC_EXT 0x96C9
+#define GL_SURFACE_COMPRESSION_FIXED_RATE_7BPC_EXT 0x96CA
+#define GL_SURFACE_COMPRESSION_FIXED_RATE_8BPC_EXT 0x96CB
+#define GL_SURFACE_COMPRESSION_FIXED_RATE_9BPC_EXT 0x96CC
+#define GL_SURFACE_COMPRESSION_FIXED_RATE_DEFAULT_EXT 0x96C2
+#define GL_SURFACE_COMPRESSION_FIXED_RATE_NONE_EXT 0x96C1
+#define GL_TESS_CONTROL_OUTPUT_VERTICES_EXT 0x8E75
+#define GL_TESS_CONTROL_OUTPUT_VERTICES_OES 0x8E75
+#define GL_TESS_CONTROL_SHADER_BIT_EXT 0x00000008
+#define GL_TESS_CONTROL_SHADER_BIT_OES 0x00000008
+#define GL_TESS_CONTROL_SHADER_EXT 0x8E88
+#define GL_TESS_CONTROL_SHADER_OES 0x8E88
+#define GL_TESS_EVALUATION_SHADER_BIT_EXT 0x00000010
+#define GL_TESS_EVALUATION_SHADER_BIT_OES 0x00000010
+#define GL_TESS_EVALUATION_SHADER_EXT 0x8E87
+#define GL_TESS_EVALUATION_SHADER_OES 0x8E87
+#define GL_TESS_GEN_MODE_EXT 0x8E76
+#define GL_TESS_GEN_MODE_OES 0x8E76
+#define GL_TESS_GEN_POINT_MODE_EXT 0x8E79
+#define GL_TESS_GEN_POINT_MODE_OES 0x8E79
+#define GL_TESS_GEN_SPACING_EXT 0x8E77
+#define GL_TESS_GEN_SPACING_OES 0x8E77
+#define GL_TESS_GEN_VERTEX_ORDER_EXT 0x8E78
+#define GL_TESS_GEN_VERTEX_ORDER_OES 0x8E78
+#define GL_TEXTURE 0x1702
+#define GL_TEXTURE0 0x84C0
+#define GL_TEXTURE1 0x84C1
+#define GL_TEXTURE10 0x84CA
+#define GL_TEXTURE11 0x84CB
+#define GL_TEXTURE12 0x84CC
+#define GL_TEXTURE13 0x84CD
+#define GL_TEXTURE14 0x84CE
+#define GL_TEXTURE15 0x84CF
+#define GL_TEXTURE16 0x84D0
+#define GL_TEXTURE17 0x84D1
+#define GL_TEXTURE18 0x84D2
+#define GL_TEXTURE19 0x84D3
+#define GL_TEXTURE2 0x84C2
+#define GL_TEXTURE20 0x84D4
+#define GL_TEXTURE21 0x84D5
+#define GL_TEXTURE22 0x84D6
+#define GL_TEXTURE23 0x84D7
+#define GL_TEXTURE24 0x84D8
+#define GL_TEXTURE25 0x84D9
+#define GL_TEXTURE26 0x84DA
+#define GL_TEXTURE27 0x84DB
+#define GL_TEXTURE28 0x84DC
+#define GL_TEXTURE29 0x84DD
+#define GL_TEXTURE3 0x84C3
+#define GL_TEXTURE30 0x84DE
+#define GL_TEXTURE31 0x84DF
+#define GL_TEXTURE4 0x84C4
+#define GL_TEXTURE5 0x84C5
+#define GL_TEXTURE6 0x84C6
+#define GL_TEXTURE7 0x84C7
+#define GL_TEXTURE8 0x84C8
+#define GL_TEXTURE9 0x84C9
+#define GL_TEXTURE_2D 0x0DE1
+#define GL_TEXTURE_2D_ARRAY 0x8C1A
+#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES 0x9102
+#define GL_TEXTURE_3D 0x806F
+#define GL_TEXTURE_3D_OES 0x806F
+#define GL_TEXTURE_ASTC_DECODE_PRECISION_EXT 0x8F69
+#define GL_TEXTURE_BINDING_2D 0x8069
+#define GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY_OES 0x9105
+#define GL_TEXTURE_BINDING_3D_OES 0x806A
+#define GL_TEXTURE_BINDING_BUFFER_EXT 0x8C2C
+#define GL_TEXTURE_BINDING_BUFFER_OES 0x8C2C
+#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514
+#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY_EXT 0x900A
+#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY_OES 0x900A
+#define GL_TEXTURE_BINDING_EXTERNAL_OES 0x8D67
+#define GL_TEXTURE_BORDER_COLOR_EXT 0x1004
+#define GL_TEXTURE_BORDER_COLOR_OES 0x1004
+#define GL_TEXTURE_BUFFER_BINDING_EXT 0x8C2A
+#define GL_TEXTURE_BUFFER_BINDING_OES 0x8C2A
+#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING_EXT 0x8C2D
+#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING_OES 0x8C2D
+#define GL_TEXTURE_BUFFER_EXT 0x8C2A
+#define GL_TEXTURE_BUFFER_OES 0x8C2A
+#define GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT_EXT 0x919F
+#define GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT_OES 0x919F
+#define GL_TEXTURE_BUFFER_OFFSET_EXT 0x919D
+#define GL_TEXTURE_BUFFER_OFFSET_OES 0x919D
+#define GL_TEXTURE_BUFFER_SIZE_EXT 0x919E
+#define GL_TEXTURE_BUFFER_SIZE_OES 0x919E
+#define GL_TEXTURE_COMPARE_FUNC_EXT 0x884D
+#define GL_TEXTURE_COMPARE_MODE_EXT 0x884C
+#define GL_TEXTURE_CUBE_MAP 0x8513
+#define GL_TEXTURE_CUBE_MAP_ARRAY_EXT 0x9009
+#define GL_TEXTURE_CUBE_MAP_ARRAY_OES 0x9009
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519
+#define GL_TEXTURE_EXTERNAL_OES 0x8D65
+#define GL_TEXTURE_FORMAT_SRGB_OVERRIDE_EXT 0x8FBF
+#define GL_TEXTURE_IMMUTABLE_FORMAT_EXT 0x912F
+#define GL_TEXTURE_IMMUTABLE_LEVELS 0x82DF
+#define GL_TEXTURE_MAG_FILTER 0x2800
+#define GL_TEXTURE_MAX_ANISOTROPY 0x84FE
+#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
+#define GL_TEXTURE_MIN_FILTER 0x2801
+#define GL_TEXTURE_PROTECTED_EXT 0x8BFA
+#define GL_TEXTURE_REDUCTION_MODE_ARB 0x9366
+#define GL_TEXTURE_REDUCTION_MODE_EXT 0x9366
+#define GL_TEXTURE_SPARSE_EXT 0x91A6
+#define GL_TEXTURE_SRGB_DECODE_EXT 0x8A48
+#define GL_TEXTURE_TILING_EXT 0x9580
+#define GL_TEXTURE_VIEW_MIN_LAYER_EXT 0x82DD
+#define GL_TEXTURE_VIEW_MIN_LAYER_OES 0x82DD
+#define GL_TEXTURE_VIEW_MIN_LEVEL_EXT 0x82DB
+#define GL_TEXTURE_VIEW_MIN_LEVEL_OES 0x82DB
+#define GL_TEXTURE_VIEW_NUM_LAYERS_EXT 0x82DE
+#define GL_TEXTURE_VIEW_NUM_LAYERS_OES 0x82DE
+#define GL_TEXTURE_VIEW_NUM_LEVELS_EXT 0x82DC
+#define GL_TEXTURE_VIEW_NUM_LEVELS_OES 0x82DC
+#define GL_TEXTURE_WRAP_R_OES 0x8072
+#define GL_TEXTURE_WRAP_S 0x2802
+#define GL_TEXTURE_WRAP_T 0x2803
+#define GL_TILING_TYPES_EXT 0x9583
+#define GL_TIMESTAMP_EXT 0x8E28
+#define GL_TIME_ELAPSED_EXT 0x88BF
+#define GL_TRANSFORM_FEEDBACK 0x8E22
+#define GL_TRIANGLES 0x0004
+#define GL_TRIANGLES_ADJACENCY_EXT 0x000C
+#define GL_TRIANGLES_ADJACENCY_OES 0x000C
+#define GL_TRIANGLE_FAN 0x0006
+#define GL_TRIANGLE_STRIP 0x0005
+#define GL_TRIANGLE_STRIP_ADJACENCY_EXT 0x000D
+#define GL_TRIANGLE_STRIP_ADJACENCY_OES 0x000D
+#define GL_TRUE 1
+#define GL_UNDEFINED_VERTEX_EXT 0x8260
+#define GL_UNDEFINED_VERTEX_OES 0x8260
+#define GL_UNKNOWN_CONTEXT_RESET_EXT 0x8255
+#define GL_UNKNOWN_CONTEXT_RESET_KHR 0x8255
+#define GL_UNPACK_ALIGNMENT 0x0CF5
+#define GL_UNPACK_ROW_LENGTH_EXT 0x0CF2
+#define GL_UNPACK_SKIP_PIXELS_EXT 0x0CF4
+#define GL_UNPACK_SKIP_ROWS_EXT 0x0CF3
+#define GL_UNSIGNED_BYTE 0x1401
+#define GL_UNSIGNED_INT 0x1405
+#define GL_UNSIGNED_INT_10_10_10_2_OES 0x8DF6
+#define GL_UNSIGNED_INT_24_8_OES 0x84FA
+#define GL_UNSIGNED_INT_2_10_10_10_REV_EXT 0x8368
+#define GL_UNSIGNED_INT_IMAGE_BUFFER_EXT 0x9067
+#define GL_UNSIGNED_INT_IMAGE_BUFFER_OES 0x9067
+#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY_EXT 0x906A
+#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY_OES 0x906A
+#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY_OES 0x910D
+#define GL_UNSIGNED_INT_SAMPLER_BUFFER_EXT 0x8DD8
+#define GL_UNSIGNED_INT_SAMPLER_BUFFER_OES 0x8DD8
+#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_EXT 0x900F
+#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_OES 0x900F
+#define GL_UNSIGNED_NORMALIZED_EXT 0x8C17
+#define GL_UNSIGNED_SHORT 0x1403
+#define GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT 0x8366
+#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033
+#define GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT 0x8365
+#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
+#define GL_UNSIGNED_SHORT_5_6_5 0x8363
+#define GL_UPPER_LEFT 0x8CA2
+#define GL_UPPER_LEFT_EXT 0x8CA2
+#define GL_UUID_SIZE_EXT 16
+#define GL_VALIDATE_STATUS 0x8B83
+#define GL_VENDOR 0x1F00
+#define GL_VERSION 0x1F02
+#define GL_VERTEX_ARRAY_BINDING_OES 0x85B5
+#define GL_VERTEX_ARRAY_KHR 0x8074
+#define GL_VERTEX_ARRAY_OBJECT_EXT 0x9154
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
+#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_EXT 0x88FE
+#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622
+#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
+#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645
+#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623
+#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624
+#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625
+#define GL_VERTEX_SHADER 0x8B31
+#define GL_VERTEX_SHADER_BIT_EXT 0x00000001
+#define GL_VIEWPORT 0x0BA2
+#define GL_VIEWPORT_BOUNDS_RANGE_OES 0x825D
+#define GL_VIEWPORT_INDEX_PROVOKING_VERTEX_OES 0x825F
+#define GL_VIEWPORT_SUBPIXEL_BITS_OES 0x825C
+#define GL_VIRTUAL_PAGE_SIZE_INDEX_EXT 0x91A7
+#define GL_VIRTUAL_PAGE_SIZE_X_EXT 0x9195
+#define GL_VIRTUAL_PAGE_SIZE_Y_EXT 0x9196
+#define GL_VIRTUAL_PAGE_SIZE_Z_EXT 0x9197
+#define GL_WEIGHTED_AVERAGE_ARB 0x9367
+#define GL_WEIGHTED_AVERAGE_EXT 0x9367
+#define GL_WINDOW_RECTANGLE_EXT 0x8F12
+#define GL_WINDOW_RECTANGLE_MODE_EXT 0x8F13
+#define GL_WRITE_ONLY_OES 0x88B9
+#define GL_ZERO 0
+#define GL_ZERO_TO_ONE 0x935F
+#define GL_ZERO_TO_ONE_EXT 0x935F
+
+
+#ifndef __khrplatform_h_
+#define __khrplatform_h_
+
+/*
+** Copyright (c) 2008-2018 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+/* Khronos platform-specific types and definitions.
+ *
+ * The master copy of khrplatform.h is maintained in the Khronos EGL
+ * Registry repository at https://github.com/KhronosGroup/EGL-Registry
+ * The last semantic modification to khrplatform.h was at commit ID:
+ * 67a3e0864c2d75ea5287b9f3d2eb74a745936692
+ *
+ * Adopters may modify this file to suit their platform. Adopters are
+ * encouraged to submit platform specific modifications to the Khronos
+ * group so that they can be included in future versions of this file.
+ * Please submit changes by filing pull requests or issues on
+ * the EGL Registry repository linked above.
+ *
+ *
+ * See the Implementer's Guidelines for information about where this file
+ * should be located on your system and for more details of its use:
+ * http://www.khronos.org/registry/implementers_guide.pdf
+ *
+ * This file should be included as
+ * #include
+ * by Khronos client API header files that use its types and defines.
+ *
+ * The types in khrplatform.h should only be used to define API-specific types.
+ *
+ * Types defined in khrplatform.h:
+ * khronos_int8_t signed 8 bit
+ * khronos_uint8_t unsigned 8 bit
+ * khronos_int16_t signed 16 bit
+ * khronos_uint16_t unsigned 16 bit
+ * khronos_int32_t signed 32 bit
+ * khronos_uint32_t unsigned 32 bit
+ * khronos_int64_t signed 64 bit
+ * khronos_uint64_t unsigned 64 bit
+ * khronos_intptr_t signed same number of bits as a pointer
+ * khronos_uintptr_t unsigned same number of bits as a pointer
+ * khronos_ssize_t signed size
+ * khronos_usize_t unsigned size
+ * khronos_float_t signed 32 bit floating point
+ * khronos_time_ns_t unsigned 64 bit time in nanoseconds
+ * khronos_utime_nanoseconds_t unsigned time interval or absolute time in
+ * nanoseconds
+ * khronos_stime_nanoseconds_t signed time interval in nanoseconds
+ * khronos_boolean_enum_t enumerated boolean type. This should
+ * only be used as a base type when a client API's boolean type is
+ * an enum. Client APIs which use an integer or other type for
+ * booleans cannot use this as the base type for their boolean.
+ *
+ * Tokens defined in khrplatform.h:
+ *
+ * KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values.
+ *
+ * KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0.
+ * KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0.
+ *
+ * Calling convention macros defined in this file:
+ * KHRONOS_APICALL
+ * KHRONOS_GLAD_API_PTR
+ * KHRONOS_APIATTRIBUTES
+ *
+ * These may be used in function prototypes as:
+ *
+ * KHRONOS_APICALL void KHRONOS_GLAD_API_PTR funcname(
+ * int arg1,
+ * int arg2) KHRONOS_APIATTRIBUTES;
+ */
+
+#if defined(__SCITECH_SNAP__) && !defined(KHRONOS_STATIC)
+# define KHRONOS_STATIC 1
+#endif
+
+/*-------------------------------------------------------------------------
+ * Definition of KHRONOS_APICALL
+ *-------------------------------------------------------------------------
+ * This precedes the return type of the function in the function prototype.
+ */
+#if defined(KHRONOS_STATIC)
+ /* If the preprocessor constant KHRONOS_STATIC is defined, make the
+ * header compatible with static linking. */
+# define KHRONOS_APICALL
+#elif defined(_WIN32)
+# define KHRONOS_APICALL __declspec(dllimport)
+#elif defined (__SYMBIAN32__)
+# define KHRONOS_APICALL IMPORT_C
+#elif defined(__ANDROID__)
+# define KHRONOS_APICALL __attribute__((visibility("default")))
+#else
+# define KHRONOS_APICALL
+#endif
+
+/*-------------------------------------------------------------------------
+ * Definition of KHRONOS_GLAD_API_PTR
+ *-------------------------------------------------------------------------
+ * This follows the return type of the function and precedes the function
+ * name in the function prototype.
+ */
+#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__)
+ /* Win32 but not WinCE */
+# define KHRONOS_GLAD_API_PTR __stdcall
+#else
+# define KHRONOS_GLAD_API_PTR
+#endif
+
+/*-------------------------------------------------------------------------
+ * Definition of KHRONOS_APIATTRIBUTES
+ *-------------------------------------------------------------------------
+ * This follows the closing parenthesis of the function prototype arguments.
+ */
+#if defined (__ARMCC_2__)
+#define KHRONOS_APIATTRIBUTES __softfp
+#else
+#define KHRONOS_APIATTRIBUTES
+#endif
+
+/*-------------------------------------------------------------------------
+ * basic type definitions
+ *-----------------------------------------------------------------------*/
+#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__)
+
+
+/*
+ * Using
+ */
+#include
+typedef int32_t khronos_int32_t;
+typedef uint32_t khronos_uint32_t;
+typedef int64_t khronos_int64_t;
+typedef uint64_t khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64 1
+#define KHRONOS_SUPPORT_FLOAT 1
+/*
+ * To support platform where unsigned long cannot be used interchangeably with
+ * inptr_t (e.g. CHERI-extended ISAs), we can use the stdint.h intptr_t.
+ * Ideally, we could just use (u)intptr_t everywhere, but this could result in
+ * ABI breakage if khronos_uintptr_t is changed from unsigned long to
+ * unsigned long long or similar (this results in different C++ name mangling).
+ * To avoid changes for existing platforms, we restrict usage of intptr_t to
+ * platforms where the size of a pointer is larger than the size of long.
+ */
+#if defined(__SIZEOF_LONG__) && defined(__SIZEOF_POINTER__)
+#if __SIZEOF_POINTER__ > __SIZEOF_LONG__
+#define KHRONOS_USE_INTPTR_T
+#endif
+#endif
+
+#elif defined(__VMS ) || defined(__sgi)
+
+/*
+ * Using
+ */
+#include
+typedef int32_t khronos_int32_t;
+typedef uint32_t khronos_uint32_t;
+typedef int64_t khronos_int64_t;
+typedef uint64_t khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64 1
+#define KHRONOS_SUPPORT_FLOAT 1
+
+#elif defined(_WIN32) && !defined(__SCITECH_SNAP__)
+
+/*
+ * Win32
+ */
+typedef __int32 khronos_int32_t;
+typedef unsigned __int32 khronos_uint32_t;
+typedef __int64 khronos_int64_t;
+typedef unsigned __int64 khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64 1
+#define KHRONOS_SUPPORT_FLOAT 1
+
+#elif defined(__sun__) || defined(__digital__)
+
+/*
+ * Sun or Digital
+ */
+typedef int khronos_int32_t;
+typedef unsigned int khronos_uint32_t;
+#if defined(__arch64__) || defined(_LP64)
+typedef long int khronos_int64_t;
+typedef unsigned long int khronos_uint64_t;
+#else
+typedef long long int khronos_int64_t;
+typedef unsigned long long int khronos_uint64_t;
+#endif /* __arch64__ */
+#define KHRONOS_SUPPORT_INT64 1
+#define KHRONOS_SUPPORT_FLOAT 1
+
+#elif 0
+
+/*
+ * Hypothetical platform with no float or int64 support
+ */
+typedef int khronos_int32_t;
+typedef unsigned int khronos_uint32_t;
+#define KHRONOS_SUPPORT_INT64 0
+#define KHRONOS_SUPPORT_FLOAT 0
+
+#else
+
+/*
+ * Generic fallback
+ */
+#include
+typedef int32_t khronos_int32_t;
+typedef uint32_t khronos_uint32_t;
+typedef int64_t khronos_int64_t;
+typedef uint64_t khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64 1
+#define KHRONOS_SUPPORT_FLOAT 1
+
+#endif
+
+
+/*
+ * Types that are (so far) the same on all platforms
+ */
+typedef signed char khronos_int8_t;
+typedef unsigned char khronos_uint8_t;
+typedef signed short int khronos_int16_t;
+typedef unsigned short int khronos_uint16_t;
+
+/*
+ * Types that differ between LLP64 and LP64 architectures - in LLP64,
+ * pointers are 64 bits, but 'long' is still 32 bits. Win64 appears
+ * to be the only LLP64 architecture in current use.
+ */
+#ifdef KHRONOS_USE_INTPTR_T
+typedef intptr_t khronos_intptr_t;
+typedef uintptr_t khronos_uintptr_t;
+#elif defined(_WIN64)
+typedef signed long long int khronos_intptr_t;
+typedef unsigned long long int khronos_uintptr_t;
+#else
+typedef signed long int khronos_intptr_t;
+typedef unsigned long int khronos_uintptr_t;
+#endif
+
+#if defined(_WIN64)
+typedef signed long long int khronos_ssize_t;
+typedef unsigned long long int khronos_usize_t;
+#else
+typedef signed long int khronos_ssize_t;
+typedef unsigned long int khronos_usize_t;
+#endif
+
+#if KHRONOS_SUPPORT_FLOAT
+/*
+ * Float type
+ */
+typedef float khronos_float_t;
+#endif
+
+#if KHRONOS_SUPPORT_INT64
+/* Time types
+ *
+ * These types can be used to represent a time interval in nanoseconds or
+ * an absolute Unadjusted System Time. Unadjusted System Time is the number
+ * of nanoseconds since some arbitrary system event (e.g. since the last
+ * time the system booted). The Unadjusted System Time is an unsigned
+ * 64 bit value that wraps back to 0 every 584 years. Time intervals
+ * may be either signed or unsigned.
+ */
+typedef khronos_uint64_t khronos_utime_nanoseconds_t;
+typedef khronos_int64_t khronos_stime_nanoseconds_t;
+#endif
+
+/*
+ * Dummy value used to pad enum types to 32 bits.
+ */
+#ifndef KHRONOS_MAX_ENUM
+#define KHRONOS_MAX_ENUM 0x7FFFFFFF
+#endif
+
+/*
+ * Enumerated boolean type
+ *
+ * Values other than zero should be considered to be true. Therefore
+ * comparisons should not be made against KHRONOS_TRUE.
+ */
+typedef enum {
+ KHRONOS_FALSE = 0,
+ KHRONOS_TRUE = 1,
+ KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM
+} khronos_boolean_enum_t;
+
+#endif /* __khrplatform_h_ */
+typedef unsigned int GLenum;
+typedef unsigned char GLboolean;
+typedef unsigned int GLbitfield;
+typedef void GLvoid;
+typedef khronos_int8_t GLbyte;
+typedef khronos_uint8_t GLubyte;
+typedef khronos_int16_t GLshort;
+typedef khronos_uint16_t GLushort;
+typedef int GLint;
+typedef unsigned int GLuint;
+typedef khronos_int32_t GLclampx;
+typedef int GLsizei;
+typedef khronos_float_t GLfloat;
+typedef khronos_float_t GLclampf;
+typedef double GLdouble;
+typedef double GLclampd;
+typedef void *GLeglClientBufferEXT;
+typedef void *GLeglImageOES;
+typedef char GLchar;
+typedef char GLcharARB;
+#ifdef __APPLE__
+typedef void *GLhandleARB;
+#else
+typedef unsigned int GLhandleARB;
+#endif
+typedef khronos_uint16_t GLhalf;
+typedef khronos_uint16_t GLhalfARB;
+typedef khronos_int32_t GLfixed;
+#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060)
+typedef khronos_intptr_t GLintptr;
+#else
+typedef khronos_intptr_t GLintptr;
+#endif
+#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060)
+typedef khronos_intptr_t GLintptrARB;
+#else
+typedef khronos_intptr_t GLintptrARB;
+#endif
+#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060)
+typedef khronos_ssize_t GLsizeiptr;
+#else
+typedef khronos_ssize_t GLsizeiptr;
+#endif
+#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060)
+typedef khronos_ssize_t GLsizeiptrARB;
+#else
+typedef khronos_ssize_t GLsizeiptrARB;
+#endif
+typedef khronos_int64_t GLint64;
+typedef khronos_int64_t GLint64EXT;
+typedef khronos_uint64_t GLuint64;
+typedef khronos_uint64_t GLuint64EXT;
+typedef struct __GLsync *GLsync;
+struct _cl_context;
+struct _cl_event;
+typedef void (GLAD_API_PTR *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
+typedef void (GLAD_API_PTR *GLDEBUGPROCARB)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
+typedef void (GLAD_API_PTR *GLDEBUGPROCKHR)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
+typedef void (GLAD_API_PTR *GLDEBUGPROCAMD)(GLuint id,GLenum category,GLenum severity,GLsizei length,const GLchar *message,void *userParam);
+typedef unsigned short GLhalfNV;
+typedef GLintptr GLvdpauSurfaceNV;
+typedef void (GLAD_API_PTR *GLVULKANPROCNV)(void);
+
+
+#define GL_ES_VERSION_2_0 1
+GLAD_API_CALL int GLAD_GL_ES_VERSION_2_0;
+#define GL_EXT_EGL_image_array 1
+GLAD_API_CALL int GLAD_GL_EXT_EGL_image_array;
+#define GL_EXT_EGL_image_storage 1
+GLAD_API_CALL int GLAD_GL_EXT_EGL_image_storage;
+#define GL_EXT_EGL_image_storage_compression 1
+GLAD_API_CALL int GLAD_GL_EXT_EGL_image_storage_compression;
+#define GL_EXT_YUV_target 1
+GLAD_API_CALL int GLAD_GL_EXT_YUV_target;
+#define GL_EXT_base_instance 1
+GLAD_API_CALL int GLAD_GL_EXT_base_instance;
+#define GL_EXT_blend_func_extended 1
+GLAD_API_CALL int GLAD_GL_EXT_blend_func_extended;
+#define GL_EXT_blend_minmax 1
+GLAD_API_CALL int GLAD_GL_EXT_blend_minmax;
+#define GL_EXT_buffer_storage 1
+GLAD_API_CALL int GLAD_GL_EXT_buffer_storage;
+#define GL_EXT_clear_texture 1
+GLAD_API_CALL int GLAD_GL_EXT_clear_texture;
+#define GL_EXT_clip_control 1
+GLAD_API_CALL int GLAD_GL_EXT_clip_control;
+#define GL_EXT_clip_cull_distance 1
+GLAD_API_CALL int GLAD_GL_EXT_clip_cull_distance;
+#define GL_EXT_color_buffer_float 1
+GLAD_API_CALL int GLAD_GL_EXT_color_buffer_float;
+#define GL_EXT_color_buffer_half_float 1
+GLAD_API_CALL int GLAD_GL_EXT_color_buffer_half_float;
+#define GL_EXT_conservative_depth 1
+GLAD_API_CALL int GLAD_GL_EXT_conservative_depth;
+#define GL_EXT_copy_image 1
+GLAD_API_CALL int GLAD_GL_EXT_copy_image;
+#define GL_EXT_debug_label 1
+GLAD_API_CALL int GLAD_GL_EXT_debug_label;
+#define GL_EXT_debug_marker 1
+GLAD_API_CALL int GLAD_GL_EXT_debug_marker;
+#define GL_EXT_depth_clamp 1
+GLAD_API_CALL int GLAD_GL_EXT_depth_clamp;
+#define GL_EXT_discard_framebuffer 1
+GLAD_API_CALL int GLAD_GL_EXT_discard_framebuffer;
+#define GL_EXT_disjoint_timer_query 1
+GLAD_API_CALL int GLAD_GL_EXT_disjoint_timer_query;
+#define GL_EXT_draw_buffers 1
+GLAD_API_CALL int GLAD_GL_EXT_draw_buffers;
+#define GL_EXT_draw_buffers_indexed 1
+GLAD_API_CALL int GLAD_GL_EXT_draw_buffers_indexed;
+#define GL_EXT_draw_elements_base_vertex 1
+GLAD_API_CALL int GLAD_GL_EXT_draw_elements_base_vertex;
+#define GL_EXT_draw_instanced 1
+GLAD_API_CALL int GLAD_GL_EXT_draw_instanced;
+#define GL_EXT_draw_transform_feedback 1
+GLAD_API_CALL int GLAD_GL_EXT_draw_transform_feedback;
+#define GL_EXT_external_buffer 1
+GLAD_API_CALL int GLAD_GL_EXT_external_buffer;
+#define GL_EXT_float_blend 1
+GLAD_API_CALL int GLAD_GL_EXT_float_blend;
+#define GL_EXT_fragment_shading_rate 1
+GLAD_API_CALL int GLAD_GL_EXT_fragment_shading_rate;
+#define GL_EXT_geometry_point_size 1
+GLAD_API_CALL int GLAD_GL_EXT_geometry_point_size;
+#define GL_EXT_geometry_shader 1
+GLAD_API_CALL int GLAD_GL_EXT_geometry_shader;
+#define GL_EXT_gpu_shader5 1
+GLAD_API_CALL int GLAD_GL_EXT_gpu_shader5;
+#define GL_EXT_instanced_arrays 1
+GLAD_API_CALL int GLAD_GL_EXT_instanced_arrays;
+#define GL_EXT_map_buffer_range 1
+GLAD_API_CALL int GLAD_GL_EXT_map_buffer_range;
+#define GL_EXT_memory_object 1
+GLAD_API_CALL int GLAD_GL_EXT_memory_object;
+#define GL_EXT_memory_object_fd 1
+GLAD_API_CALL int GLAD_GL_EXT_memory_object_fd;
+#define GL_EXT_memory_object_win32 1
+GLAD_API_CALL int GLAD_GL_EXT_memory_object_win32;
+#define GL_EXT_multi_draw_arrays 1
+GLAD_API_CALL int GLAD_GL_EXT_multi_draw_arrays;
+#define GL_EXT_multi_draw_indirect 1
+GLAD_API_CALL int GLAD_GL_EXT_multi_draw_indirect;
+#define GL_EXT_multisampled_compatibility 1
+GLAD_API_CALL int GLAD_GL_EXT_multisampled_compatibility;
+#define GL_EXT_multisampled_render_to_texture 1
+GLAD_API_CALL int GLAD_GL_EXT_multisampled_render_to_texture;
+#define GL_EXT_multisampled_render_to_texture2 1
+GLAD_API_CALL int GLAD_GL_EXT_multisampled_render_to_texture2;
+#define GL_EXT_multiview_draw_buffers 1
+GLAD_API_CALL int GLAD_GL_EXT_multiview_draw_buffers;
+#define GL_EXT_multiview_tessellation_geometry_shader 1
+GLAD_API_CALL int GLAD_GL_EXT_multiview_tessellation_geometry_shader;
+#define GL_EXT_multiview_texture_multisample 1
+GLAD_API_CALL int GLAD_GL_EXT_multiview_texture_multisample;
+#define GL_EXT_multiview_timer_query 1
+GLAD_API_CALL int GLAD_GL_EXT_multiview_timer_query;
+#define GL_EXT_occlusion_query_boolean 1
+GLAD_API_CALL int GLAD_GL_EXT_occlusion_query_boolean;
+#define GL_EXT_polygon_offset_clamp 1
+GLAD_API_CALL int GLAD_GL_EXT_polygon_offset_clamp;
+#define GL_EXT_post_depth_coverage 1
+GLAD_API_CALL int GLAD_GL_EXT_post_depth_coverage;
+#define GL_EXT_primitive_bounding_box 1
+GLAD_API_CALL int GLAD_GL_EXT_primitive_bounding_box;
+#define GL_EXT_protected_textures 1
+GLAD_API_CALL int GLAD_GL_EXT_protected_textures;
+#define GL_EXT_pvrtc_sRGB 1
+GLAD_API_CALL int GLAD_GL_EXT_pvrtc_sRGB;
+#define GL_EXT_raster_multisample 1
+GLAD_API_CALL int GLAD_GL_EXT_raster_multisample;
+#define GL_EXT_read_format_bgra 1
+GLAD_API_CALL int GLAD_GL_EXT_read_format_bgra;
+#define GL_EXT_render_snorm 1
+GLAD_API_CALL int GLAD_GL_EXT_render_snorm;
+#define GL_EXT_robustness 1
+GLAD_API_CALL int GLAD_GL_EXT_robustness;
+#define GL_EXT_sRGB 1
+GLAD_API_CALL int GLAD_GL_EXT_sRGB;
+#define GL_EXT_sRGB_write_control 1
+GLAD_API_CALL int GLAD_GL_EXT_sRGB_write_control;
+#define GL_EXT_semaphore 1
+GLAD_API_CALL int GLAD_GL_EXT_semaphore;
+#define GL_EXT_semaphore_fd 1
+GLAD_API_CALL int GLAD_GL_EXT_semaphore_fd;
+#define GL_EXT_semaphore_win32 1
+GLAD_API_CALL int GLAD_GL_EXT_semaphore_win32;
+#define GL_EXT_separate_depth_stencil 1
+GLAD_API_CALL int GLAD_GL_EXT_separate_depth_stencil;
+#define GL_EXT_separate_shader_objects 1
+GLAD_API_CALL int GLAD_GL_EXT_separate_shader_objects;
+#define GL_EXT_shader_framebuffer_fetch 1
+GLAD_API_CALL int GLAD_GL_EXT_shader_framebuffer_fetch;
+#define GL_EXT_shader_framebuffer_fetch_non_coherent 1
+GLAD_API_CALL int GLAD_GL_EXT_shader_framebuffer_fetch_non_coherent;
+#define GL_EXT_shader_group_vote 1
+GLAD_API_CALL int GLAD_GL_EXT_shader_group_vote;
+#define GL_EXT_shader_implicit_conversions 1
+GLAD_API_CALL int GLAD_GL_EXT_shader_implicit_conversions;
+#define GL_EXT_shader_integer_mix 1
+GLAD_API_CALL int GLAD_GL_EXT_shader_integer_mix;
+#define GL_EXT_shader_io_blocks 1
+GLAD_API_CALL int GLAD_GL_EXT_shader_io_blocks;
+#define GL_EXT_shader_non_constant_global_initializers 1
+GLAD_API_CALL int GLAD_GL_EXT_shader_non_constant_global_initializers;
+#define GL_EXT_shader_pixel_local_storage 1
+GLAD_API_CALL int GLAD_GL_EXT_shader_pixel_local_storage;
+#define GL_EXT_shader_pixel_local_storage2 1
+GLAD_API_CALL int GLAD_GL_EXT_shader_pixel_local_storage2;
+#define GL_EXT_shader_samples_identical 1
+GLAD_API_CALL int GLAD_GL_EXT_shader_samples_identical;
+#define GL_EXT_shader_texture_lod 1
+GLAD_API_CALL int GLAD_GL_EXT_shader_texture_lod;
+#define GL_EXT_shadow_samplers 1
+GLAD_API_CALL int GLAD_GL_EXT_shadow_samplers;
+#define GL_EXT_sparse_texture 1
+GLAD_API_CALL int GLAD_GL_EXT_sparse_texture;
+#define GL_EXT_sparse_texture2 1
+GLAD_API_CALL int GLAD_GL_EXT_sparse_texture2;
+#define GL_EXT_tessellation_point_size 1
+GLAD_API_CALL int GLAD_GL_EXT_tessellation_point_size;
+#define GL_EXT_tessellation_shader 1
+GLAD_API_CALL int GLAD_GL_EXT_tessellation_shader;
+#define GL_EXT_texture_border_clamp 1
+GLAD_API_CALL int GLAD_GL_EXT_texture_border_clamp;
+#define GL_EXT_texture_buffer 1
+GLAD_API_CALL int GLAD_GL_EXT_texture_buffer;
+#define GL_EXT_texture_compression_astc_decode_mode 1
+GLAD_API_CALL int GLAD_GL_EXT_texture_compression_astc_decode_mode;
+#define GL_EXT_texture_compression_bptc 1
+GLAD_API_CALL int GLAD_GL_EXT_texture_compression_bptc;
+#define GL_EXT_texture_compression_dxt1 1
+GLAD_API_CALL int GLAD_GL_EXT_texture_compression_dxt1;
+#define GL_EXT_texture_compression_rgtc 1
+GLAD_API_CALL int GLAD_GL_EXT_texture_compression_rgtc;
+#define GL_EXT_texture_compression_s3tc 1
+GLAD_API_CALL int GLAD_GL_EXT_texture_compression_s3tc;
+#define GL_EXT_texture_compression_s3tc_srgb 1
+GLAD_API_CALL int GLAD_GL_EXT_texture_compression_s3tc_srgb;
+#define GL_EXT_texture_cube_map_array 1
+GLAD_API_CALL int GLAD_GL_EXT_texture_cube_map_array;
+#define GL_EXT_texture_filter_anisotropic 1
+GLAD_API_CALL int GLAD_GL_EXT_texture_filter_anisotropic;
+#define GL_EXT_texture_filter_minmax 1
+GLAD_API_CALL int GLAD_GL_EXT_texture_filter_minmax;
+#define GL_EXT_texture_format_BGRA8888 1
+GLAD_API_CALL int GLAD_GL_EXT_texture_format_BGRA8888;
+#define GL_EXT_texture_format_sRGB_override 1
+GLAD_API_CALL int GLAD_GL_EXT_texture_format_sRGB_override;
+#define GL_EXT_texture_mirror_clamp_to_edge 1
+GLAD_API_CALL int GLAD_GL_EXT_texture_mirror_clamp_to_edge;
+#define GL_EXT_texture_norm16 1
+GLAD_API_CALL int GLAD_GL_EXT_texture_norm16;
+#define GL_EXT_texture_query_lod 1
+GLAD_API_CALL int GLAD_GL_EXT_texture_query_lod;
+#define GL_EXT_texture_rg 1
+GLAD_API_CALL int GLAD_GL_EXT_texture_rg;
+#define GL_EXT_texture_sRGB_R8 1
+GLAD_API_CALL int GLAD_GL_EXT_texture_sRGB_R8;
+#define GL_EXT_texture_sRGB_RG8 1
+GLAD_API_CALL int GLAD_GL_EXT_texture_sRGB_RG8;
+#define GL_EXT_texture_sRGB_decode 1
+GLAD_API_CALL int GLAD_GL_EXT_texture_sRGB_decode;
+#define GL_EXT_texture_shadow_lod 1
+GLAD_API_CALL int GLAD_GL_EXT_texture_shadow_lod;
+#define GL_EXT_texture_storage 1
+GLAD_API_CALL int GLAD_GL_EXT_texture_storage;
+#define GL_EXT_texture_storage_compression 1
+GLAD_API_CALL int GLAD_GL_EXT_texture_storage_compression;
+#define GL_EXT_texture_type_2_10_10_10_REV 1
+GLAD_API_CALL int GLAD_GL_EXT_texture_type_2_10_10_10_REV;
+#define GL_EXT_texture_view 1
+GLAD_API_CALL int GLAD_GL_EXT_texture_view;
+#define GL_EXT_unpack_subimage 1
+GLAD_API_CALL int GLAD_GL_EXT_unpack_subimage;
+#define GL_EXT_win32_keyed_mutex 1
+GLAD_API_CALL int GLAD_GL_EXT_win32_keyed_mutex;
+#define GL_EXT_window_rectangles 1
+GLAD_API_CALL int GLAD_GL_EXT_window_rectangles;
+#define GL_KHR_blend_equation_advanced 1
+GLAD_API_CALL int GLAD_GL_KHR_blend_equation_advanced;
+#define GL_KHR_blend_equation_advanced_coherent 1
+GLAD_API_CALL int GLAD_GL_KHR_blend_equation_advanced_coherent;
+#define GL_KHR_context_flush_control 1
+GLAD_API_CALL int GLAD_GL_KHR_context_flush_control;
+#define GL_KHR_debug 1
+GLAD_API_CALL int GLAD_GL_KHR_debug;
+#define GL_KHR_no_error 1
+GLAD_API_CALL int GLAD_GL_KHR_no_error;
+#define GL_KHR_parallel_shader_compile 1
+GLAD_API_CALL int GLAD_GL_KHR_parallel_shader_compile;
+#define GL_KHR_robust_buffer_access_behavior 1
+GLAD_API_CALL int GLAD_GL_KHR_robust_buffer_access_behavior;
+#define GL_KHR_robustness 1
+GLAD_API_CALL int GLAD_GL_KHR_robustness;
+#define GL_KHR_shader_subgroup 1
+GLAD_API_CALL int GLAD_GL_KHR_shader_subgroup;
+#define GL_KHR_texture_compression_astc_hdr 1
+GLAD_API_CALL int GLAD_GL_KHR_texture_compression_astc_hdr;
+#define GL_KHR_texture_compression_astc_ldr 1
+GLAD_API_CALL int GLAD_GL_KHR_texture_compression_astc_ldr;
+#define GL_KHR_texture_compression_astc_sliced_3d 1
+GLAD_API_CALL int GLAD_GL_KHR_texture_compression_astc_sliced_3d;
+#define GL_OES_EGL_image 1
+GLAD_API_CALL int GLAD_GL_OES_EGL_image;
+#define GL_OES_EGL_image_external 1
+GLAD_API_CALL int GLAD_GL_OES_EGL_image_external;
+#define GL_OES_EGL_image_external_essl3 1
+GLAD_API_CALL int GLAD_GL_OES_EGL_image_external_essl3;
+#define GL_OES_compressed_ETC1_RGB8_sub_texture 1
+GLAD_API_CALL int GLAD_GL_OES_compressed_ETC1_RGB8_sub_texture;
+#define GL_OES_compressed_ETC1_RGB8_texture 1
+GLAD_API_CALL int GLAD_GL_OES_compressed_ETC1_RGB8_texture;
+#define GL_OES_compressed_paletted_texture 1
+GLAD_API_CALL int GLAD_GL_OES_compressed_paletted_texture;
+#define GL_OES_copy_image 1
+GLAD_API_CALL int GLAD_GL_OES_copy_image;
+#define GL_OES_depth24 1
+GLAD_API_CALL int GLAD_GL_OES_depth24;
+#define GL_OES_depth32 1
+GLAD_API_CALL int GLAD_GL_OES_depth32;
+#define GL_OES_depth_texture 1
+GLAD_API_CALL int GLAD_GL_OES_depth_texture;
+#define GL_OES_draw_buffers_indexed 1
+GLAD_API_CALL int GLAD_GL_OES_draw_buffers_indexed;
+#define GL_OES_draw_elements_base_vertex 1
+GLAD_API_CALL int GLAD_GL_OES_draw_elements_base_vertex;
+#define GL_OES_element_index_uint 1
+GLAD_API_CALL int GLAD_GL_OES_element_index_uint;
+#define GL_OES_fbo_render_mipmap 1
+GLAD_API_CALL int GLAD_GL_OES_fbo_render_mipmap;
+#define GL_OES_fragment_precision_high 1
+GLAD_API_CALL int GLAD_GL_OES_fragment_precision_high;
+#define GL_OES_geometry_point_size 1
+GLAD_API_CALL int GLAD_GL_OES_geometry_point_size;
+#define GL_OES_geometry_shader 1
+GLAD_API_CALL int GLAD_GL_OES_geometry_shader;
+#define GL_OES_get_program_binary 1
+GLAD_API_CALL int GLAD_GL_OES_get_program_binary;
+#define GL_OES_gpu_shader5 1
+GLAD_API_CALL int GLAD_GL_OES_gpu_shader5;
+#define GL_OES_mapbuffer 1
+GLAD_API_CALL int GLAD_GL_OES_mapbuffer;
+#define GL_OES_packed_depth_stencil 1
+GLAD_API_CALL int GLAD_GL_OES_packed_depth_stencil;
+#define GL_OES_primitive_bounding_box 1
+GLAD_API_CALL int GLAD_GL_OES_primitive_bounding_box;
+#define GL_OES_required_internalformat 1
+GLAD_API_CALL int GLAD_GL_OES_required_internalformat;
+#define GL_OES_rgb8_rgba8 1
+GLAD_API_CALL int GLAD_GL_OES_rgb8_rgba8;
+#define GL_OES_sample_shading 1
+GLAD_API_CALL int GLAD_GL_OES_sample_shading;
+#define GL_OES_sample_variables 1
+GLAD_API_CALL int GLAD_GL_OES_sample_variables;
+#define GL_OES_shader_image_atomic 1
+GLAD_API_CALL int GLAD_GL_OES_shader_image_atomic;
+#define GL_OES_shader_io_blocks 1
+GLAD_API_CALL int GLAD_GL_OES_shader_io_blocks;
+#define GL_OES_shader_multisample_interpolation 1
+GLAD_API_CALL int GLAD_GL_OES_shader_multisample_interpolation;
+#define GL_OES_standard_derivatives 1
+GLAD_API_CALL int GLAD_GL_OES_standard_derivatives;
+#define GL_OES_stencil1 1
+GLAD_API_CALL int GLAD_GL_OES_stencil1;
+#define GL_OES_stencil4 1
+GLAD_API_CALL int GLAD_GL_OES_stencil4;
+#define GL_OES_surfaceless_context 1
+GLAD_API_CALL int GLAD_GL_OES_surfaceless_context;
+#define GL_OES_tessellation_point_size 1
+GLAD_API_CALL int GLAD_GL_OES_tessellation_point_size;
+#define GL_OES_tessellation_shader 1
+GLAD_API_CALL int GLAD_GL_OES_tessellation_shader;
+#define GL_OES_texture_3D 1
+GLAD_API_CALL int GLAD_GL_OES_texture_3D;
+#define GL_OES_texture_border_clamp 1
+GLAD_API_CALL int GLAD_GL_OES_texture_border_clamp;
+#define GL_OES_texture_buffer 1
+GLAD_API_CALL int GLAD_GL_OES_texture_buffer;
+#define GL_OES_texture_compression_astc 1
+GLAD_API_CALL int GLAD_GL_OES_texture_compression_astc;
+#define GL_OES_texture_cube_map_array 1
+GLAD_API_CALL int GLAD_GL_OES_texture_cube_map_array;
+#define GL_OES_texture_float 1
+GLAD_API_CALL int GLAD_GL_OES_texture_float;
+#define GL_OES_texture_float_linear 1
+GLAD_API_CALL int GLAD_GL_OES_texture_float_linear;
+#define GL_OES_texture_half_float 1
+GLAD_API_CALL int GLAD_GL_OES_texture_half_float;
+#define GL_OES_texture_half_float_linear 1
+GLAD_API_CALL int GLAD_GL_OES_texture_half_float_linear;
+#define GL_OES_texture_npot 1
+GLAD_API_CALL int GLAD_GL_OES_texture_npot;
+#define GL_OES_texture_stencil8 1
+GLAD_API_CALL int GLAD_GL_OES_texture_stencil8;
+#define GL_OES_texture_storage_multisample_2d_array 1
+GLAD_API_CALL int GLAD_GL_OES_texture_storage_multisample_2d_array;
+#define GL_OES_texture_view 1
+GLAD_API_CALL int GLAD_GL_OES_texture_view;
+#define GL_OES_vertex_array_object 1
+GLAD_API_CALL int GLAD_GL_OES_vertex_array_object;
+#define GL_OES_vertex_half_float 1
+GLAD_API_CALL int GLAD_GL_OES_vertex_half_float;
+#define GL_OES_vertex_type_10_10_10_2 1
+GLAD_API_CALL int GLAD_GL_OES_vertex_type_10_10_10_2;
+#define GL_OES_viewport_array 1
+GLAD_API_CALL int GLAD_GL_OES_viewport_array;
+
+
+typedef GLboolean (GLAD_API_PTR *PFNGLACQUIREKEYEDMUTEXWIN32EXTPROC)(GLuint memory, GLuint64 key, GLuint timeout);
+typedef void (GLAD_API_PTR *PFNGLACTIVESHADERPROGRAMEXTPROC)(GLuint pipeline, GLuint program);
+typedef void (GLAD_API_PTR *PFNGLACTIVETEXTUREPROC)(GLenum texture);
+typedef void (GLAD_API_PTR *PFNGLATTACHSHADERPROC)(GLuint program, GLuint shader);
+typedef void (GLAD_API_PTR *PFNGLBEGINQUERYEXTPROC)(GLenum target, GLuint id);
+typedef void (GLAD_API_PTR *PFNGLBINDATTRIBLOCATIONPROC)(GLuint program, GLuint index, const GLchar * name);
+typedef void (GLAD_API_PTR *PFNGLBINDBUFFERPROC)(GLenum target, GLuint buffer);
+typedef void (GLAD_API_PTR *PFNGLBINDFRAGDATALOCATIONEXTPROC)(GLuint program, GLuint color, const GLchar * name);
+typedef void (GLAD_API_PTR *PFNGLBINDFRAGDATALOCATIONINDEXEDEXTPROC)(GLuint program, GLuint colorNumber, GLuint index, const GLchar * name);
+typedef void (GLAD_API_PTR *PFNGLBINDFRAMEBUFFERPROC)(GLenum target, GLuint framebuffer);
+typedef void (GLAD_API_PTR *PFNGLBINDPROGRAMPIPELINEEXTPROC)(GLuint pipeline);
+typedef void (GLAD_API_PTR *PFNGLBINDRENDERBUFFERPROC)(GLenum target, GLuint renderbuffer);
+typedef void (GLAD_API_PTR *PFNGLBINDTEXTUREPROC)(GLenum target, GLuint texture);
+typedef void (GLAD_API_PTR *PFNGLBINDVERTEXARRAYOESPROC)(GLuint array);
+typedef void (GLAD_API_PTR *PFNGLBLENDBARRIERKHRPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLBLENDCOLORPROC)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+typedef void (GLAD_API_PTR *PFNGLBLENDEQUATIONPROC)(GLenum mode);
+typedef void (GLAD_API_PTR *PFNGLBLENDEQUATIONSEPARATEPROC)(GLenum modeRGB, GLenum modeAlpha);
+typedef void (GLAD_API_PTR *PFNGLBLENDEQUATIONSEPARATEIEXTPROC)(GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+typedef void (GLAD_API_PTR *PFNGLBLENDEQUATIONSEPARATEIOESPROC)(GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+typedef void (GLAD_API_PTR *PFNGLBLENDEQUATIONIEXTPROC)(GLuint buf, GLenum mode);
+typedef void (GLAD_API_PTR *PFNGLBLENDEQUATIONIOESPROC)(GLuint buf, GLenum mode);
+typedef void (GLAD_API_PTR *PFNGLBLENDFUNCPROC)(GLenum sfactor, GLenum dfactor);
+typedef void (GLAD_API_PTR *PFNGLBLENDFUNCSEPARATEPROC)(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+typedef void (GLAD_API_PTR *PFNGLBLENDFUNCSEPARATEIEXTPROC)(GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+typedef void (GLAD_API_PTR *PFNGLBLENDFUNCSEPARATEIOESPROC)(GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+typedef void (GLAD_API_PTR *PFNGLBLENDFUNCIEXTPROC)(GLuint buf, GLenum src, GLenum dst);
+typedef void (GLAD_API_PTR *PFNGLBLENDFUNCIOESPROC)(GLuint buf, GLenum src, GLenum dst);
+typedef void (GLAD_API_PTR *PFNGLBUFFERDATAPROC)(GLenum target, GLsizeiptr size, const void * data, GLenum usage);
+typedef void (GLAD_API_PTR *PFNGLBUFFERSTORAGEEXTPROC)(GLenum target, GLsizeiptr size, const void * data, GLbitfield flags);
+typedef void (GLAD_API_PTR *PFNGLBUFFERSTORAGEEXTERNALEXTPROC)(GLenum target, GLintptr offset, GLsizeiptr size, GLeglClientBufferEXT clientBuffer, GLbitfield flags);
+typedef void (GLAD_API_PTR *PFNGLBUFFERSTORAGEMEMEXTPROC)(GLenum target, GLsizeiptr size, GLuint memory, GLuint64 offset);
+typedef void (GLAD_API_PTR *PFNGLBUFFERSUBDATAPROC)(GLenum target, GLintptr offset, GLsizeiptr size, const void * data);
+typedef GLenum (GLAD_API_PTR *PFNGLCHECKFRAMEBUFFERSTATUSPROC)(GLenum target);
+typedef void (GLAD_API_PTR *PFNGLCLEARPROC)(GLbitfield mask);
+typedef void (GLAD_API_PTR *PFNGLCLEARCOLORPROC)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+typedef void (GLAD_API_PTR *PFNGLCLEARDEPTHFPROC)(GLfloat d);
+typedef void (GLAD_API_PTR *PFNGLCLEARPIXELLOCALSTORAGEUIEXTPROC)(GLsizei offset, GLsizei n, const GLuint * values);
+typedef void (GLAD_API_PTR *PFNGLCLEARSTENCILPROC)(GLint s);
+typedef void (GLAD_API_PTR *PFNGLCLEARTEXIMAGEEXTPROC)(GLuint texture, GLint level, GLenum format, GLenum type, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCLEARTEXSUBIMAGEEXTPROC)(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCLIPCONTROLEXTPROC)(GLenum origin, GLenum depth);
+typedef void (GLAD_API_PTR *PFNGLCOLORMASKPROC)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+typedef void (GLAD_API_PTR *PFNGLCOLORMASKIEXTPROC)(GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
+typedef void (GLAD_API_PTR *PFNGLCOLORMASKIOESPROC)(GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
+typedef void (GLAD_API_PTR *PFNGLCOMPILESHADERPROC)(GLuint shader);
+typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXIMAGE2DPROC)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXIMAGE3DOESPROC)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXSUBIMAGE3DOESPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCOPYIMAGESUBDATAEXTPROC)(GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth);
+typedef void (GLAD_API_PTR *PFNGLCOPYIMAGESUBDATAOESPROC)(GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth);
+typedef void (GLAD_API_PTR *PFNGLCOPYTEXIMAGE2DPROC)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+typedef void (GLAD_API_PTR *PFNGLCOPYTEXSUBIMAGE2DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GLAD_API_PTR *PFNGLCOPYTEXSUBIMAGE3DOESPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GLAD_API_PTR *PFNGLCREATEMEMORYOBJECTSEXTPROC)(GLsizei n, GLuint * memoryObjects);
+typedef GLuint (GLAD_API_PTR *PFNGLCREATEPROGRAMPROC)(void);
+typedef GLuint (GLAD_API_PTR *PFNGLCREATESHADERPROC)(GLenum type);
+typedef GLuint (GLAD_API_PTR *PFNGLCREATESHADERPROGRAMVEXTPROC)(GLenum type, GLsizei count, const GLchar *const* strings);
+typedef void (GLAD_API_PTR *PFNGLCULLFACEPROC)(GLenum mode);
+typedef void (GLAD_API_PTR *PFNGLDEBUGMESSAGECALLBACKKHRPROC)(GLDEBUGPROCKHR callback, const void * userParam);
+typedef void (GLAD_API_PTR *PFNGLDEBUGMESSAGECONTROLKHRPROC)(GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint * ids, GLboolean enabled);
+typedef void (GLAD_API_PTR *PFNGLDEBUGMESSAGEINSERTKHRPROC)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar * buf);
+typedef void (GLAD_API_PTR *PFNGLDELETEBUFFERSPROC)(GLsizei n, const GLuint * buffers);
+typedef void (GLAD_API_PTR *PFNGLDELETEFRAMEBUFFERSPROC)(GLsizei n, const GLuint * framebuffers);
+typedef void (GLAD_API_PTR *PFNGLDELETEMEMORYOBJECTSEXTPROC)(GLsizei n, const GLuint * memoryObjects);
+typedef void (GLAD_API_PTR *PFNGLDELETEPROGRAMPROC)(GLuint program);
+typedef void (GLAD_API_PTR *PFNGLDELETEPROGRAMPIPELINESEXTPROC)(GLsizei n, const GLuint * pipelines);
+typedef void (GLAD_API_PTR *PFNGLDELETEQUERIESEXTPROC)(GLsizei n, const GLuint * ids);
+typedef void (GLAD_API_PTR *PFNGLDELETERENDERBUFFERSPROC)(GLsizei n, const GLuint * renderbuffers);
+typedef void (GLAD_API_PTR *PFNGLDELETESEMAPHORESEXTPROC)(GLsizei n, const GLuint * semaphores);
+typedef void (GLAD_API_PTR *PFNGLDELETESHADERPROC)(GLuint shader);
+typedef void (GLAD_API_PTR *PFNGLDELETETEXTURESPROC)(GLsizei n, const GLuint * textures);
+typedef void (GLAD_API_PTR *PFNGLDELETEVERTEXARRAYSOESPROC)(GLsizei n, const GLuint * arrays);
+typedef void (GLAD_API_PTR *PFNGLDEPTHFUNCPROC)(GLenum func);
+typedef void (GLAD_API_PTR *PFNGLDEPTHMASKPROC)(GLboolean flag);
+typedef void (GLAD_API_PTR *PFNGLDEPTHRANGEARRAYFVOESPROC)(GLuint first, GLsizei count, const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLDEPTHRANGEINDEXEDFOESPROC)(GLuint index, GLfloat n, GLfloat f);
+typedef void (GLAD_API_PTR *PFNGLDEPTHRANGEFPROC)(GLfloat n, GLfloat f);
+typedef void (GLAD_API_PTR *PFNGLDETACHSHADERPROC)(GLuint program, GLuint shader);
+typedef void (GLAD_API_PTR *PFNGLDISABLEPROC)(GLenum cap);
+typedef void (GLAD_API_PTR *PFNGLDISABLEVERTEXATTRIBARRAYPROC)(GLuint index);
+typedef void (GLAD_API_PTR *PFNGLDISABLEIEXTPROC)(GLenum target, GLuint index);
+typedef void (GLAD_API_PTR *PFNGLDISABLEIOESPROC)(GLenum target, GLuint index);
+typedef void (GLAD_API_PTR *PFNGLDISCARDFRAMEBUFFEREXTPROC)(GLenum target, GLsizei numAttachments, const GLenum * attachments);
+typedef void (GLAD_API_PTR *PFNGLDRAWARRAYSPROC)(GLenum mode, GLint first, GLsizei count);
+typedef void (GLAD_API_PTR *PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEEXTPROC)(GLenum mode, GLint first, GLsizei count, GLsizei instancecount, GLuint baseinstance);
+typedef void (GLAD_API_PTR *PFNGLDRAWARRAYSINSTANCEDEXTPROC)(GLenum mode, GLint start, GLsizei count, GLsizei primcount);
+typedef void (GLAD_API_PTR *PFNGLDRAWBUFFERSEXTPROC)(GLsizei n, const GLenum * bufs);
+typedef void (GLAD_API_PTR *PFNGLDRAWBUFFERSINDEXEDEXTPROC)(GLint n, const GLenum * location, const GLint * indices);
+typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices);
+typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSBASEVERTEXEXTPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLint basevertex);
+typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSBASEVERTEXOESPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLint basevertex);
+typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEEXTPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei instancecount, GLuint baseinstance);
+typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEEXTPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei instancecount, GLint basevertex, GLuint baseinstance);
+typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXEXTPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei instancecount, GLint basevertex);
+typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXOESPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei instancecount, GLint basevertex);
+typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSINSTANCEDEXTPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei primcount);
+typedef void (GLAD_API_PTR *PFNGLDRAWRANGEELEMENTSBASEVERTEXEXTPROC)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void * indices, GLint basevertex);
+typedef void (GLAD_API_PTR *PFNGLDRAWRANGEELEMENTSBASEVERTEXOESPROC)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void * indices, GLint basevertex);
+typedef void (GLAD_API_PTR *PFNGLDRAWTRANSFORMFEEDBACKEXTPROC)(GLenum mode, GLuint id);
+typedef void (GLAD_API_PTR *PFNGLDRAWTRANSFORMFEEDBACKINSTANCEDEXTPROC)(GLenum mode, GLuint id, GLsizei instancecount);
+typedef void (GLAD_API_PTR *PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC)(GLenum target, GLeglImageOES image);
+typedef void (GLAD_API_PTR *PFNGLEGLIMAGETARGETTEXSTORAGEEXTPROC)(GLenum target, GLeglImageOES image, const GLint * attrib_list);
+typedef void (GLAD_API_PTR *PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)(GLenum target, GLeglImageOES image);
+typedef void (GLAD_API_PTR *PFNGLEGLIMAGETARGETTEXTURESTORAGEEXTPROC)(GLuint texture, GLeglImageOES image, const GLint * attrib_list);
+typedef void (GLAD_API_PTR *PFNGLENABLEPROC)(GLenum cap);
+typedef void (GLAD_API_PTR *PFNGLENABLEVERTEXATTRIBARRAYPROC)(GLuint index);
+typedef void (GLAD_API_PTR *PFNGLENABLEIEXTPROC)(GLenum target, GLuint index);
+typedef void (GLAD_API_PTR *PFNGLENABLEIOESPROC)(GLenum target, GLuint index);
+typedef void (GLAD_API_PTR *PFNGLENDQUERYEXTPROC)(GLenum target);
+typedef void (GLAD_API_PTR *PFNGLFINISHPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLFLUSHPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLFLUSHMAPPEDBUFFERRANGEEXTPROC)(GLenum target, GLintptr offset, GLsizeiptr length);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERFETCHBARRIEREXTPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERPIXELLOCALSTORAGESIZEEXTPROC)(GLuint target, GLsizei size);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERRENDERBUFFERPROC)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERSHADINGRATEEXTPROC)(GLenum target, GLenum attachment, GLuint texture, GLint baseLayer, GLsizei numLayers, GLsizei texelWidth, GLsizei texelHeight);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURE2DPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURE3DOESPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTUREEXTPROC)(GLenum target, GLenum attachment, GLuint texture, GLint level);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTUREOESPROC)(GLenum target, GLenum attachment, GLuint texture, GLint level);
+typedef void (GLAD_API_PTR *PFNGLFRONTFACEPROC)(GLenum mode);
+typedef void (GLAD_API_PTR *PFNGLGENBUFFERSPROC)(GLsizei n, GLuint * buffers);
+typedef void (GLAD_API_PTR *PFNGLGENFRAMEBUFFERSPROC)(GLsizei n, GLuint * framebuffers);
+typedef void (GLAD_API_PTR *PFNGLGENPROGRAMPIPELINESEXTPROC)(GLsizei n, GLuint * pipelines);
+typedef void (GLAD_API_PTR *PFNGLGENQUERIESEXTPROC)(GLsizei n, GLuint * ids);
+typedef void (GLAD_API_PTR *PFNGLGENRENDERBUFFERSPROC)(GLsizei n, GLuint * renderbuffers);
+typedef void (GLAD_API_PTR *PFNGLGENSEMAPHORESEXTPROC)(GLsizei n, GLuint * semaphores);
+typedef void (GLAD_API_PTR *PFNGLGENTEXTURESPROC)(GLsizei n, GLuint * textures);
+typedef void (GLAD_API_PTR *PFNGLGENVERTEXARRAYSOESPROC)(GLsizei n, GLuint * arrays);
+typedef void (GLAD_API_PTR *PFNGLGENERATEMIPMAPPROC)(GLenum target);
+typedef void (GLAD_API_PTR *PFNGLGETACTIVEATTRIBPROC)(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * name);
+typedef void (GLAD_API_PTR *PFNGLGETACTIVEUNIFORMPROC)(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * name);
+typedef void (GLAD_API_PTR *PFNGLGETATTACHEDSHADERSPROC)(GLuint program, GLsizei maxCount, GLsizei * count, GLuint * shaders);
+typedef GLint (GLAD_API_PTR *PFNGLGETATTRIBLOCATIONPROC)(GLuint program, const GLchar * name);
+typedef void (GLAD_API_PTR *PFNGLGETBOOLEANVPROC)(GLenum pname, GLboolean * data);
+typedef void (GLAD_API_PTR *PFNGLGETBUFFERPARAMETERIVPROC)(GLenum target, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETBUFFERPOINTERVOESPROC)(GLenum target, GLenum pname, void ** params);
+typedef GLuint (GLAD_API_PTR *PFNGLGETDEBUGMESSAGELOGKHRPROC)(GLuint count, GLsizei bufSize, GLenum * sources, GLenum * types, GLuint * ids, GLenum * severities, GLsizei * lengths, GLchar * messageLog);
+typedef GLenum (GLAD_API_PTR *PFNGLGETERRORPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLGETFLOATI_VOESPROC)(GLenum target, GLuint index, GLfloat * data);
+typedef void (GLAD_API_PTR *PFNGLGETFLOATVPROC)(GLenum pname, GLfloat * data);
+typedef GLint (GLAD_API_PTR *PFNGLGETFRAGDATAINDEXEXTPROC)(GLuint program, const GLchar * name);
+typedef void (GLAD_API_PTR *PFNGLGETFRAGMENTSHADINGRATESEXTPROC)(GLsizei samples, GLsizei maxCount, GLsizei * count, GLenum * shadingRates);
+typedef void (GLAD_API_PTR *PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC)(GLenum target, GLenum attachment, GLenum pname, GLint * params);
+typedef GLsizei (GLAD_API_PTR *PFNGLGETFRAMEBUFFERPIXELLOCALSTORAGESIZEEXTPROC)(GLuint target);
+typedef GLenum (GLAD_API_PTR *PFNGLGETGRAPHICSRESETSTATUSEXTPROC)(void);
+typedef GLenum (GLAD_API_PTR *PFNGLGETGRAPHICSRESETSTATUSKHRPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLGETINTEGER64VEXTPROC)(GLenum pname, GLint64 * data);
+typedef void (GLAD_API_PTR *PFNGLGETINTEGERI_VEXTPROC)(GLenum target, GLuint index, GLint * data);
+typedef void (GLAD_API_PTR *PFNGLGETINTEGERVPROC)(GLenum pname, GLint * data);
+typedef void (GLAD_API_PTR *PFNGLGETMEMORYOBJECTPARAMETERIVEXTPROC)(GLuint memoryObject, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETOBJECTLABELEXTPROC)(GLenum type, GLuint object, GLsizei bufSize, GLsizei * length, GLchar * label);
+typedef void (GLAD_API_PTR *PFNGLGETOBJECTLABELKHRPROC)(GLenum identifier, GLuint name, GLsizei bufSize, GLsizei * length, GLchar * label);
+typedef void (GLAD_API_PTR *PFNGLGETOBJECTPTRLABELKHRPROC)(const void * ptr, GLsizei bufSize, GLsizei * length, GLchar * label);
+typedef void (GLAD_API_PTR *PFNGLGETPOINTERVKHRPROC)(GLenum pname, void ** params);
+typedef void (GLAD_API_PTR *PFNGLGETPROGRAMBINARYOESPROC)(GLuint program, GLsizei bufSize, GLsizei * length, GLenum * binaryFormat, void * binary);
+typedef void (GLAD_API_PTR *PFNGLGETPROGRAMINFOLOGPROC)(GLuint program, GLsizei bufSize, GLsizei * length, GLchar * infoLog);
+typedef void (GLAD_API_PTR *PFNGLGETPROGRAMPIPELINEINFOLOGEXTPROC)(GLuint pipeline, GLsizei bufSize, GLsizei * length, GLchar * infoLog);
+typedef void (GLAD_API_PTR *PFNGLGETPROGRAMPIPELINEIVEXTPROC)(GLuint pipeline, GLenum pname, GLint * params);
+typedef GLint (GLAD_API_PTR *PFNGLGETPROGRAMRESOURCELOCATIONINDEXEXTPROC)(GLuint program, GLenum programInterface, const GLchar * name);
+typedef void (GLAD_API_PTR *PFNGLGETPROGRAMIVPROC)(GLuint program, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETQUERYOBJECTI64VEXTPROC)(GLuint id, GLenum pname, GLint64 * params);
+typedef void (GLAD_API_PTR *PFNGLGETQUERYOBJECTIVEXTPROC)(GLuint id, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETQUERYOBJECTUI64VEXTPROC)(GLuint id, GLenum pname, GLuint64 * params);
+typedef void (GLAD_API_PTR *PFNGLGETQUERYOBJECTUIVEXTPROC)(GLuint id, GLenum pname, GLuint * params);
+typedef void (GLAD_API_PTR *PFNGLGETQUERYIVEXTPROC)(GLenum target, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETRENDERBUFFERPARAMETERIVPROC)(GLenum target, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETSAMPLERPARAMETERIIVEXTPROC)(GLuint sampler, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETSAMPLERPARAMETERIIVOESPROC)(GLuint sampler, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETSAMPLERPARAMETERIUIVEXTPROC)(GLuint sampler, GLenum pname, GLuint * params);
+typedef void (GLAD_API_PTR *PFNGLGETSAMPLERPARAMETERIUIVOESPROC)(GLuint sampler, GLenum pname, GLuint * params);
+typedef void (GLAD_API_PTR *PFNGLGETSEMAPHOREPARAMETERUI64VEXTPROC)(GLuint semaphore, GLenum pname, GLuint64 * params);
+typedef void (GLAD_API_PTR *PFNGLGETSHADERINFOLOGPROC)(GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * infoLog);
+typedef void (GLAD_API_PTR *PFNGLGETSHADERPRECISIONFORMATPROC)(GLenum shadertype, GLenum precisiontype, GLint * range, GLint * precision);
+typedef void (GLAD_API_PTR *PFNGLGETSHADERSOURCEPROC)(GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * source);
+typedef void (GLAD_API_PTR *PFNGLGETSHADERIVPROC)(GLuint shader, GLenum pname, GLint * params);
+typedef const GLubyte * (GLAD_API_PTR *PFNGLGETSTRINGPROC)(GLenum name);
+typedef void (GLAD_API_PTR *PFNGLGETTEXPARAMETERIIVEXTPROC)(GLenum target, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXPARAMETERIIVOESPROC)(GLenum target, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXPARAMETERIUIVEXTPROC)(GLenum target, GLenum pname, GLuint * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXPARAMETERIUIVOESPROC)(GLenum target, GLenum pname, GLuint * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXPARAMETERFVPROC)(GLenum target, GLenum pname, GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXPARAMETERIVPROC)(GLenum target, GLenum pname, GLint * params);
+typedef GLint (GLAD_API_PTR *PFNGLGETUNIFORMLOCATIONPROC)(GLuint program, const GLchar * name);
+typedef void (GLAD_API_PTR *PFNGLGETUNIFORMFVPROC)(GLuint program, GLint location, GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLGETUNIFORMIVPROC)(GLuint program, GLint location, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETUNSIGNEDBYTEI_VEXTPROC)(GLenum target, GLuint index, GLubyte * data);
+typedef void (GLAD_API_PTR *PFNGLGETUNSIGNEDBYTEVEXTPROC)(GLenum pname, GLubyte * data);
+typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBPOINTERVPROC)(GLuint index, GLenum pname, void ** pointer);
+typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBFVPROC)(GLuint index, GLenum pname, GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBIVPROC)(GLuint index, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETNUNIFORMFVEXTPROC)(GLuint program, GLint location, GLsizei bufSize, GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLGETNUNIFORMFVKHRPROC)(GLuint program, GLint location, GLsizei bufSize, GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLGETNUNIFORMIVEXTPROC)(GLuint program, GLint location, GLsizei bufSize, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETNUNIFORMIVKHRPROC)(GLuint program, GLint location, GLsizei bufSize, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETNUNIFORMUIVKHRPROC)(GLuint program, GLint location, GLsizei bufSize, GLuint * params);
+typedef void (GLAD_API_PTR *PFNGLHINTPROC)(GLenum target, GLenum mode);
+typedef void (GLAD_API_PTR *PFNGLIMPORTMEMORYFDEXTPROC)(GLuint memory, GLuint64 size, GLenum handleType, GLint fd);
+typedef void (GLAD_API_PTR *PFNGLIMPORTMEMORYWIN32HANDLEEXTPROC)(GLuint memory, GLuint64 size, GLenum handleType, void * handle);
+typedef void (GLAD_API_PTR *PFNGLIMPORTMEMORYWIN32NAMEEXTPROC)(GLuint memory, GLuint64 size, GLenum handleType, const void * name);
+typedef void (GLAD_API_PTR *PFNGLIMPORTSEMAPHOREFDEXTPROC)(GLuint semaphore, GLenum handleType, GLint fd);
+typedef void (GLAD_API_PTR *PFNGLIMPORTSEMAPHOREWIN32HANDLEEXTPROC)(GLuint semaphore, GLenum handleType, void * handle);
+typedef void (GLAD_API_PTR *PFNGLIMPORTSEMAPHOREWIN32NAMEEXTPROC)(GLuint semaphore, GLenum handleType, const void * name);
+typedef void (GLAD_API_PTR *PFNGLINSERTEVENTMARKEREXTPROC)(GLsizei length, const GLchar * marker);
+typedef GLboolean (GLAD_API_PTR *PFNGLISBUFFERPROC)(GLuint buffer);
+typedef GLboolean (GLAD_API_PTR *PFNGLISENABLEDPROC)(GLenum cap);
+typedef GLboolean (GLAD_API_PTR *PFNGLISENABLEDIEXTPROC)(GLenum target, GLuint index);
+typedef GLboolean (GLAD_API_PTR *PFNGLISENABLEDIOESPROC)(GLenum target, GLuint index);
+typedef GLboolean (GLAD_API_PTR *PFNGLISFRAMEBUFFERPROC)(GLuint framebuffer);
+typedef GLboolean (GLAD_API_PTR *PFNGLISMEMORYOBJECTEXTPROC)(GLuint memoryObject);
+typedef GLboolean (GLAD_API_PTR *PFNGLISPROGRAMPROC)(GLuint program);
+typedef GLboolean (GLAD_API_PTR *PFNGLISPROGRAMPIPELINEEXTPROC)(GLuint pipeline);
+typedef GLboolean (GLAD_API_PTR *PFNGLISQUERYEXTPROC)(GLuint id);
+typedef GLboolean (GLAD_API_PTR *PFNGLISRENDERBUFFERPROC)(GLuint renderbuffer);
+typedef GLboolean (GLAD_API_PTR *PFNGLISSEMAPHOREEXTPROC)(GLuint semaphore);
+typedef GLboolean (GLAD_API_PTR *PFNGLISSHADERPROC)(GLuint shader);
+typedef GLboolean (GLAD_API_PTR *PFNGLISTEXTUREPROC)(GLuint texture);
+typedef GLboolean (GLAD_API_PTR *PFNGLISVERTEXARRAYOESPROC)(GLuint array);
+typedef void (GLAD_API_PTR *PFNGLLABELOBJECTEXTPROC)(GLenum type, GLuint object, GLsizei length, const GLchar * label);
+typedef void (GLAD_API_PTR *PFNGLLINEWIDTHPROC)(GLfloat width);
+typedef void (GLAD_API_PTR *PFNGLLINKPROGRAMPROC)(GLuint program);
+typedef void * (GLAD_API_PTR *PFNGLMAPBUFFEROESPROC)(GLenum target, GLenum access);
+typedef void * (GLAD_API_PTR *PFNGLMAPBUFFERRANGEEXTPROC)(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+typedef void (GLAD_API_PTR *PFNGLMAXSHADERCOMPILERTHREADSKHRPROC)(GLuint count);
+typedef void (GLAD_API_PTR *PFNGLMEMORYOBJECTPARAMETERIVEXTPROC)(GLuint memoryObject, GLenum pname, const GLint * params);
+typedef void (GLAD_API_PTR *PFNGLMINSAMPLESHADINGOESPROC)(GLfloat value);
+typedef void (GLAD_API_PTR *PFNGLMULTIDRAWARRAYSEXTPROC)(GLenum mode, const GLint * first, const GLsizei * count, GLsizei primcount);
+typedef void (GLAD_API_PTR *PFNGLMULTIDRAWARRAYSINDIRECTEXTPROC)(GLenum mode, const void * indirect, GLsizei drawcount, GLsizei stride);
+typedef void (GLAD_API_PTR *PFNGLMULTIDRAWELEMENTSBASEVERTEXEXTPROC)(GLenum mode, const GLsizei * count, GLenum type, const void *const* indices, GLsizei drawcount, const GLint * basevertex);
+typedef void (GLAD_API_PTR *PFNGLMULTIDRAWELEMENTSEXTPROC)(GLenum mode, const GLsizei * count, GLenum type, const void *const* indices, GLsizei primcount);
+typedef void (GLAD_API_PTR *PFNGLMULTIDRAWELEMENTSINDIRECTEXTPROC)(GLenum mode, GLenum type, const void * indirect, GLsizei drawcount, GLsizei stride);
+typedef void (GLAD_API_PTR *PFNGLNAMEDBUFFERSTORAGEEXTERNALEXTPROC)(GLuint buffer, GLintptr offset, GLsizeiptr size, GLeglClientBufferEXT clientBuffer, GLbitfield flags);
+typedef void (GLAD_API_PTR *PFNGLNAMEDBUFFERSTORAGEMEMEXTPROC)(GLuint buffer, GLsizeiptr size, GLuint memory, GLuint64 offset);
+typedef void (GLAD_API_PTR *PFNGLOBJECTLABELKHRPROC)(GLenum identifier, GLuint name, GLsizei length, const GLchar * label);
+typedef void (GLAD_API_PTR *PFNGLOBJECTPTRLABELKHRPROC)(const void * ptr, GLsizei length, const GLchar * label);
+typedef void (GLAD_API_PTR *PFNGLPATCHPARAMETERIEXTPROC)(GLenum pname, GLint value);
+typedef void (GLAD_API_PTR *PFNGLPATCHPARAMETERIOESPROC)(GLenum pname, GLint value);
+typedef void (GLAD_API_PTR *PFNGLPIXELSTOREIPROC)(GLenum pname, GLint param);
+typedef void (GLAD_API_PTR *PFNGLPOLYGONOFFSETPROC)(GLfloat factor, GLfloat units);
+typedef void (GLAD_API_PTR *PFNGLPOLYGONOFFSETCLAMPEXTPROC)(GLfloat factor, GLfloat units, GLfloat clamp);
+typedef void (GLAD_API_PTR *PFNGLPOPDEBUGGROUPKHRPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLPOPGROUPMARKEREXTPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLPRIMITIVEBOUNDINGBOXEXTPROC)(GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW);
+typedef void (GLAD_API_PTR *PFNGLPRIMITIVEBOUNDINGBOXOESPROC)(GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMBINARYOESPROC)(GLuint program, GLenum binaryFormat, const void * binary, GLint length);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMPARAMETERIEXTPROC)(GLuint program, GLenum pname, GLint value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM1FEXTPROC)(GLuint program, GLint location, GLfloat v0);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM1FVEXTPROC)(GLuint program, GLint location, GLsizei count, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM1IEXTPROC)(GLuint program, GLint location, GLint v0);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM1IVEXTPROC)(GLuint program, GLint location, GLsizei count, const GLint * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM1UIEXTPROC)(GLuint program, GLint location, GLuint v0);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM1UIVEXTPROC)(GLuint program, GLint location, GLsizei count, const GLuint * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM2FEXTPROC)(GLuint program, GLint location, GLfloat v0, GLfloat v1);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM2FVEXTPROC)(GLuint program, GLint location, GLsizei count, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM2IEXTPROC)(GLuint program, GLint location, GLint v0, GLint v1);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM2IVEXTPROC)(GLuint program, GLint location, GLsizei count, const GLint * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM2UIEXTPROC)(GLuint program, GLint location, GLuint v0, GLuint v1);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM2UIVEXTPROC)(GLuint program, GLint location, GLsizei count, const GLuint * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM3FEXTPROC)(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM3FVEXTPROC)(GLuint program, GLint location, GLsizei count, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM3IEXTPROC)(GLuint program, GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM3IVEXTPROC)(GLuint program, GLint location, GLsizei count, const GLint * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM3UIEXTPROC)(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM3UIVEXTPROC)(GLuint program, GLint location, GLsizei count, const GLuint * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM4FEXTPROC)(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM4FVEXTPROC)(GLuint program, GLint location, GLsizei count, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM4IEXTPROC)(GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM4IVEXTPROC)(GLuint program, GLint location, GLsizei count, const GLint * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM4UIEXTPROC)(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM4UIVEXTPROC)(GLuint program, GLint location, GLsizei count, const GLuint * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLPUSHDEBUGGROUPKHRPROC)(GLenum source, GLuint id, GLsizei length, const GLchar * message);
+typedef void (GLAD_API_PTR *PFNGLPUSHGROUPMARKEREXTPROC)(GLsizei length, const GLchar * marker);
+typedef void (GLAD_API_PTR *PFNGLQUERYCOUNTEREXTPROC)(GLuint id, GLenum target);
+typedef void (GLAD_API_PTR *PFNGLRASTERSAMPLESEXTPROC)(GLuint samples, GLboolean fixedsamplelocations);
+typedef void (GLAD_API_PTR *PFNGLREADBUFFERINDEXEDEXTPROC)(GLenum src, GLint index);
+typedef void (GLAD_API_PTR *PFNGLREADPIXELSPROC)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void * pixels);
+typedef void (GLAD_API_PTR *PFNGLREADNPIXELSEXTPROC)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void * data);
+typedef void (GLAD_API_PTR *PFNGLREADNPIXELSKHRPROC)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void * data);
+typedef GLboolean (GLAD_API_PTR *PFNGLRELEASEKEYEDMUTEXWIN32EXTPROC)(GLuint memory, GLuint64 key);
+typedef void (GLAD_API_PTR *PFNGLRELEASESHADERCOMPILERPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLRENDERBUFFERSTORAGEPROC)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GLAD_API_PTR *PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GLAD_API_PTR *PFNGLSAMPLECOVERAGEPROC)(GLfloat value, GLboolean invert);
+typedef void (GLAD_API_PTR *PFNGLSAMPLERPARAMETERIIVEXTPROC)(GLuint sampler, GLenum pname, const GLint * param);
+typedef void (GLAD_API_PTR *PFNGLSAMPLERPARAMETERIIVOESPROC)(GLuint sampler, GLenum pname, const GLint * param);
+typedef void (GLAD_API_PTR *PFNGLSAMPLERPARAMETERIUIVEXTPROC)(GLuint sampler, GLenum pname, const GLuint * param);
+typedef void (GLAD_API_PTR *PFNGLSAMPLERPARAMETERIUIVOESPROC)(GLuint sampler, GLenum pname, const GLuint * param);
+typedef void (GLAD_API_PTR *PFNGLSCISSORPROC)(GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GLAD_API_PTR *PFNGLSCISSORARRAYVOESPROC)(GLuint first, GLsizei count, const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLSCISSORINDEXEDOESPROC)(GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height);
+typedef void (GLAD_API_PTR *PFNGLSCISSORINDEXEDVOESPROC)(GLuint index, const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLSEMAPHOREPARAMETERUI64VEXTPROC)(GLuint semaphore, GLenum pname, const GLuint64 * params);
+typedef void (GLAD_API_PTR *PFNGLSHADERBINARYPROC)(GLsizei count, const GLuint * shaders, GLenum binaryFormat, const void * binary, GLsizei length);
+typedef void (GLAD_API_PTR *PFNGLSHADERSOURCEPROC)(GLuint shader, GLsizei count, const GLchar *const* string, const GLint * length);
+typedef void (GLAD_API_PTR *PFNGLSHADINGRATECOMBINEROPSEXTPROC)(GLenum combinerOp0, GLenum combinerOp1);
+typedef void (GLAD_API_PTR *PFNGLSHADINGRATEEXTPROC)(GLenum rate);
+typedef void (GLAD_API_PTR *PFNGLSIGNALSEMAPHOREEXTPROC)(GLuint semaphore, GLuint numBufferBarriers, const GLuint * buffers, GLuint numTextureBarriers, const GLuint * textures, const GLenum * dstLayouts);
+typedef void (GLAD_API_PTR *PFNGLSTENCILFUNCPROC)(GLenum func, GLint ref, GLuint mask);
+typedef void (GLAD_API_PTR *PFNGLSTENCILFUNCSEPARATEPROC)(GLenum face, GLenum func, GLint ref, GLuint mask);
+typedef void (GLAD_API_PTR *PFNGLSTENCILMASKPROC)(GLuint mask);
+typedef void (GLAD_API_PTR *PFNGLSTENCILMASKSEPARATEPROC)(GLenum face, GLuint mask);
+typedef void (GLAD_API_PTR *PFNGLSTENCILOPPROC)(GLenum fail, GLenum zfail, GLenum zpass);
+typedef void (GLAD_API_PTR *PFNGLSTENCILOPSEPARATEPROC)(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+typedef void (GLAD_API_PTR *PFNGLTEXBUFFEREXTPROC)(GLenum target, GLenum internalformat, GLuint buffer);
+typedef void (GLAD_API_PTR *PFNGLTEXBUFFEROESPROC)(GLenum target, GLenum internalformat, GLuint buffer);
+typedef void (GLAD_API_PTR *PFNGLTEXBUFFERRANGEEXTPROC)(GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size);
+typedef void (GLAD_API_PTR *PFNGLTEXBUFFERRANGEOESPROC)(GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size);
+typedef void (GLAD_API_PTR *PFNGLTEXIMAGE2DPROC)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void * pixels);
+typedef void (GLAD_API_PTR *PFNGLTEXIMAGE3DOESPROC)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void * pixels);
+typedef void (GLAD_API_PTR *PFNGLTEXPAGECOMMITMENTEXTPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean commit);
+typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERIIVEXTPROC)(GLenum target, GLenum pname, const GLint * params);
+typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERIIVOESPROC)(GLenum target, GLenum pname, const GLint * params);
+typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERIUIVEXTPROC)(GLenum target, GLenum pname, const GLuint * params);
+typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERIUIVOESPROC)(GLenum target, GLenum pname, const GLuint * params);
+typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERFPROC)(GLenum target, GLenum pname, GLfloat param);
+typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERFVPROC)(GLenum target, GLenum pname, const GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERIPROC)(GLenum target, GLenum pname, GLint param);
+typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERIVPROC)(GLenum target, GLenum pname, const GLint * params);
+typedef void (GLAD_API_PTR *PFNGLTEXSTORAGE1DEXTPROC)(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+typedef void (GLAD_API_PTR *PFNGLTEXSTORAGE2DEXTPROC)(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GLAD_API_PTR *PFNGLTEXSTORAGE3DEXTPROC)(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+typedef void (GLAD_API_PTR *PFNGLTEXSTORAGE3DMULTISAMPLEOESPROC)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+typedef void (GLAD_API_PTR *PFNGLTEXSTORAGEATTRIBS2DEXTPROC)(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, const GLint * attrib_list);
+typedef void (GLAD_API_PTR *PFNGLTEXSTORAGEATTRIBS3DEXTPROC)(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, const GLint * attrib_list);
+typedef void (GLAD_API_PTR *PFNGLTEXSTORAGEMEM2DEXTPROC)(GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLuint memory, GLuint64 offset);
+typedef void (GLAD_API_PTR *PFNGLTEXSTORAGEMEM2DMULTISAMPLEEXTPROC)(GLenum target, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations, GLuint memory, GLuint64 offset);
+typedef void (GLAD_API_PTR *PFNGLTEXSTORAGEMEM3DEXTPROC)(GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLuint memory, GLuint64 offset);
+typedef void (GLAD_API_PTR *PFNGLTEXSTORAGEMEM3DMULTISAMPLEEXTPROC)(GLenum target, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations, GLuint memory, GLuint64 offset);
+typedef void (GLAD_API_PTR *PFNGLTEXSUBIMAGE2DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void * pixels);
+typedef void (GLAD_API_PTR *PFNGLTEXSUBIMAGE3DOESPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void * pixels);
+typedef void (GLAD_API_PTR *PFNGLTEXTURESTORAGE1DEXTPROC)(GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+typedef void (GLAD_API_PTR *PFNGLTEXTURESTORAGE2DEXTPROC)(GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GLAD_API_PTR *PFNGLTEXTURESTORAGE3DEXTPROC)(GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+typedef void (GLAD_API_PTR *PFNGLTEXTURESTORAGEMEM2DEXTPROC)(GLuint texture, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLuint memory, GLuint64 offset);
+typedef void (GLAD_API_PTR *PFNGLTEXTURESTORAGEMEM2DMULTISAMPLEEXTPROC)(GLuint texture, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations, GLuint memory, GLuint64 offset);
+typedef void (GLAD_API_PTR *PFNGLTEXTURESTORAGEMEM3DEXTPROC)(GLuint texture, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLuint memory, GLuint64 offset);
+typedef void (GLAD_API_PTR *PFNGLTEXTURESTORAGEMEM3DMULTISAMPLEEXTPROC)(GLuint texture, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations, GLuint memory, GLuint64 offset);
+typedef void (GLAD_API_PTR *PFNGLTEXTUREVIEWEXTPROC)(GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers);
+typedef void (GLAD_API_PTR *PFNGLTEXTUREVIEWOESPROC)(GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM1FPROC)(GLint location, GLfloat v0);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM1FVPROC)(GLint location, GLsizei count, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM1IPROC)(GLint location, GLint v0);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM1IVPROC)(GLint location, GLsizei count, const GLint * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM2FPROC)(GLint location, GLfloat v0, GLfloat v1);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM2FVPROC)(GLint location, GLsizei count, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM2IPROC)(GLint location, GLint v0, GLint v1);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM2IVPROC)(GLint location, GLsizei count, const GLint * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM3FPROC)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM3FVPROC)(GLint location, GLsizei count, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM3IPROC)(GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM3IVPROC)(GLint location, GLsizei count, const GLint * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM4FPROC)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM4FVPROC)(GLint location, GLsizei count, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM4IPROC)(GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM4IVPROC)(GLint location, GLsizei count, const GLint * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX2FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX3FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX4FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef GLboolean (GLAD_API_PTR *PFNGLUNMAPBUFFEROESPROC)(GLenum target);
+typedef void (GLAD_API_PTR *PFNGLUSEPROGRAMPROC)(GLuint program);
+typedef void (GLAD_API_PTR *PFNGLUSEPROGRAMSTAGESEXTPROC)(GLuint pipeline, GLbitfield stages, GLuint program);
+typedef void (GLAD_API_PTR *PFNGLVALIDATEPROGRAMPROC)(GLuint program);
+typedef void (GLAD_API_PTR *PFNGLVALIDATEPROGRAMPIPELINEEXTPROC)(GLuint pipeline);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1FPROC)(GLuint index, GLfloat x);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1FVPROC)(GLuint index, const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2FPROC)(GLuint index, GLfloat x, GLfloat y);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2FVPROC)(GLuint index, const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3FPROC)(GLuint index, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3FVPROC)(GLuint index, const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4FPROC)(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4FVPROC)(GLuint index, const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBDIVISOREXTPROC)(GLuint index, GLuint divisor);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBPOINTERPROC)(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void * pointer);
+typedef void (GLAD_API_PTR *PFNGLVIEWPORTPROC)(GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GLAD_API_PTR *PFNGLVIEWPORTARRAYVOESPROC)(GLuint first, GLsizei count, const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLVIEWPORTINDEXEDFOESPROC)(GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h);
+typedef void (GLAD_API_PTR *PFNGLVIEWPORTINDEXEDFVOESPROC)(GLuint index, const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLWAITSEMAPHOREEXTPROC)(GLuint semaphore, GLuint numBufferBarriers, const GLuint * buffers, GLuint numTextureBarriers, const GLuint * textures, const GLenum * srcLayouts);
+typedef void (GLAD_API_PTR *PFNGLWINDOWRECTANGLESEXTPROC)(GLenum mode, GLsizei count, const GLint * box);
+
+GLAD_API_CALL PFNGLACQUIREKEYEDMUTEXWIN32EXTPROC glad_glAcquireKeyedMutexWin32EXT;
+#define glAcquireKeyedMutexWin32EXT glad_glAcquireKeyedMutexWin32EXT
+GLAD_API_CALL PFNGLACTIVESHADERPROGRAMEXTPROC glad_glActiveShaderProgramEXT;
+#define glActiveShaderProgramEXT glad_glActiveShaderProgramEXT
+GLAD_API_CALL PFNGLACTIVETEXTUREPROC glad_glActiveTexture;
+#define glActiveTexture glad_glActiveTexture
+GLAD_API_CALL PFNGLATTACHSHADERPROC glad_glAttachShader;
+#define glAttachShader glad_glAttachShader
+GLAD_API_CALL PFNGLBEGINQUERYEXTPROC glad_glBeginQueryEXT;
+#define glBeginQueryEXT glad_glBeginQueryEXT
+GLAD_API_CALL PFNGLBINDATTRIBLOCATIONPROC glad_glBindAttribLocation;
+#define glBindAttribLocation glad_glBindAttribLocation
+GLAD_API_CALL PFNGLBINDBUFFERPROC glad_glBindBuffer;
+#define glBindBuffer glad_glBindBuffer
+GLAD_API_CALL PFNGLBINDFRAGDATALOCATIONEXTPROC glad_glBindFragDataLocationEXT;
+#define glBindFragDataLocationEXT glad_glBindFragDataLocationEXT
+GLAD_API_CALL PFNGLBINDFRAGDATALOCATIONINDEXEDEXTPROC glad_glBindFragDataLocationIndexedEXT;
+#define glBindFragDataLocationIndexedEXT glad_glBindFragDataLocationIndexedEXT
+GLAD_API_CALL PFNGLBINDFRAMEBUFFERPROC glad_glBindFramebuffer;
+#define glBindFramebuffer glad_glBindFramebuffer
+GLAD_API_CALL PFNGLBINDPROGRAMPIPELINEEXTPROC glad_glBindProgramPipelineEXT;
+#define glBindProgramPipelineEXT glad_glBindProgramPipelineEXT
+GLAD_API_CALL PFNGLBINDRENDERBUFFERPROC glad_glBindRenderbuffer;
+#define glBindRenderbuffer glad_glBindRenderbuffer
+GLAD_API_CALL PFNGLBINDTEXTUREPROC glad_glBindTexture;
+#define glBindTexture glad_glBindTexture
+GLAD_API_CALL PFNGLBINDVERTEXARRAYOESPROC glad_glBindVertexArrayOES;
+#define glBindVertexArrayOES glad_glBindVertexArrayOES
+GLAD_API_CALL PFNGLBLENDBARRIERKHRPROC glad_glBlendBarrierKHR;
+#define glBlendBarrierKHR glad_glBlendBarrierKHR
+GLAD_API_CALL PFNGLBLENDCOLORPROC glad_glBlendColor;
+#define glBlendColor glad_glBlendColor
+GLAD_API_CALL PFNGLBLENDEQUATIONPROC glad_glBlendEquation;
+#define glBlendEquation glad_glBlendEquation
+GLAD_API_CALL PFNGLBLENDEQUATIONSEPARATEPROC glad_glBlendEquationSeparate;
+#define glBlendEquationSeparate glad_glBlendEquationSeparate
+GLAD_API_CALL PFNGLBLENDEQUATIONSEPARATEIEXTPROC glad_glBlendEquationSeparateiEXT;
+#define glBlendEquationSeparateiEXT glad_glBlendEquationSeparateiEXT
+GLAD_API_CALL PFNGLBLENDEQUATIONSEPARATEIOESPROC glad_glBlendEquationSeparateiOES;
+#define glBlendEquationSeparateiOES glad_glBlendEquationSeparateiOES
+GLAD_API_CALL PFNGLBLENDEQUATIONIEXTPROC glad_glBlendEquationiEXT;
+#define glBlendEquationiEXT glad_glBlendEquationiEXT
+GLAD_API_CALL PFNGLBLENDEQUATIONIOESPROC glad_glBlendEquationiOES;
+#define glBlendEquationiOES glad_glBlendEquationiOES
+GLAD_API_CALL PFNGLBLENDFUNCPROC glad_glBlendFunc;
+#define glBlendFunc glad_glBlendFunc
+GLAD_API_CALL PFNGLBLENDFUNCSEPARATEPROC glad_glBlendFuncSeparate;
+#define glBlendFuncSeparate glad_glBlendFuncSeparate
+GLAD_API_CALL PFNGLBLENDFUNCSEPARATEIEXTPROC glad_glBlendFuncSeparateiEXT;
+#define glBlendFuncSeparateiEXT glad_glBlendFuncSeparateiEXT
+GLAD_API_CALL PFNGLBLENDFUNCSEPARATEIOESPROC glad_glBlendFuncSeparateiOES;
+#define glBlendFuncSeparateiOES glad_glBlendFuncSeparateiOES
+GLAD_API_CALL PFNGLBLENDFUNCIEXTPROC glad_glBlendFunciEXT;
+#define glBlendFunciEXT glad_glBlendFunciEXT
+GLAD_API_CALL PFNGLBLENDFUNCIOESPROC glad_glBlendFunciOES;
+#define glBlendFunciOES glad_glBlendFunciOES
+GLAD_API_CALL PFNGLBUFFERDATAPROC glad_glBufferData;
+#define glBufferData glad_glBufferData
+GLAD_API_CALL PFNGLBUFFERSTORAGEEXTPROC glad_glBufferStorageEXT;
+#define glBufferStorageEXT glad_glBufferStorageEXT
+GLAD_API_CALL PFNGLBUFFERSTORAGEEXTERNALEXTPROC glad_glBufferStorageExternalEXT;
+#define glBufferStorageExternalEXT glad_glBufferStorageExternalEXT
+GLAD_API_CALL PFNGLBUFFERSTORAGEMEMEXTPROC glad_glBufferStorageMemEXT;
+#define glBufferStorageMemEXT glad_glBufferStorageMemEXT
+GLAD_API_CALL PFNGLBUFFERSUBDATAPROC glad_glBufferSubData;
+#define glBufferSubData glad_glBufferSubData
+GLAD_API_CALL PFNGLCHECKFRAMEBUFFERSTATUSPROC glad_glCheckFramebufferStatus;
+#define glCheckFramebufferStatus glad_glCheckFramebufferStatus
+GLAD_API_CALL PFNGLCLEARPROC glad_glClear;
+#define glClear glad_glClear
+GLAD_API_CALL PFNGLCLEARCOLORPROC glad_glClearColor;
+#define glClearColor glad_glClearColor
+GLAD_API_CALL PFNGLCLEARDEPTHFPROC glad_glClearDepthf;
+#define glClearDepthf glad_glClearDepthf
+GLAD_API_CALL PFNGLCLEARPIXELLOCALSTORAGEUIEXTPROC glad_glClearPixelLocalStorageuiEXT;
+#define glClearPixelLocalStorageuiEXT glad_glClearPixelLocalStorageuiEXT
+GLAD_API_CALL PFNGLCLEARSTENCILPROC glad_glClearStencil;
+#define glClearStencil glad_glClearStencil
+GLAD_API_CALL PFNGLCLEARTEXIMAGEEXTPROC glad_glClearTexImageEXT;
+#define glClearTexImageEXT glad_glClearTexImageEXT
+GLAD_API_CALL PFNGLCLEARTEXSUBIMAGEEXTPROC glad_glClearTexSubImageEXT;
+#define glClearTexSubImageEXT glad_glClearTexSubImageEXT
+GLAD_API_CALL PFNGLCLIPCONTROLEXTPROC glad_glClipControlEXT;
+#define glClipControlEXT glad_glClipControlEXT
+GLAD_API_CALL PFNGLCOLORMASKPROC glad_glColorMask;
+#define glColorMask glad_glColorMask
+GLAD_API_CALL PFNGLCOLORMASKIEXTPROC glad_glColorMaskiEXT;
+#define glColorMaskiEXT glad_glColorMaskiEXT
+GLAD_API_CALL PFNGLCOLORMASKIOESPROC glad_glColorMaskiOES;
+#define glColorMaskiOES glad_glColorMaskiOES
+GLAD_API_CALL PFNGLCOMPILESHADERPROC glad_glCompileShader;
+#define glCompileShader glad_glCompileShader
+GLAD_API_CALL PFNGLCOMPRESSEDTEXIMAGE2DPROC glad_glCompressedTexImage2D;
+#define glCompressedTexImage2D glad_glCompressedTexImage2D
+GLAD_API_CALL PFNGLCOMPRESSEDTEXIMAGE3DOESPROC glad_glCompressedTexImage3DOES;
+#define glCompressedTexImage3DOES glad_glCompressedTexImage3DOES
+GLAD_API_CALL PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC glad_glCompressedTexSubImage2D;
+#define glCompressedTexSubImage2D glad_glCompressedTexSubImage2D
+GLAD_API_CALL PFNGLCOMPRESSEDTEXSUBIMAGE3DOESPROC glad_glCompressedTexSubImage3DOES;
+#define glCompressedTexSubImage3DOES glad_glCompressedTexSubImage3DOES
+GLAD_API_CALL PFNGLCOPYIMAGESUBDATAEXTPROC glad_glCopyImageSubDataEXT;
+#define glCopyImageSubDataEXT glad_glCopyImageSubDataEXT
+GLAD_API_CALL PFNGLCOPYIMAGESUBDATAOESPROC glad_glCopyImageSubDataOES;
+#define glCopyImageSubDataOES glad_glCopyImageSubDataOES
+GLAD_API_CALL PFNGLCOPYTEXIMAGE2DPROC glad_glCopyTexImage2D;
+#define glCopyTexImage2D glad_glCopyTexImage2D
+GLAD_API_CALL PFNGLCOPYTEXSUBIMAGE2DPROC glad_glCopyTexSubImage2D;
+#define glCopyTexSubImage2D glad_glCopyTexSubImage2D
+GLAD_API_CALL PFNGLCOPYTEXSUBIMAGE3DOESPROC glad_glCopyTexSubImage3DOES;
+#define glCopyTexSubImage3DOES glad_glCopyTexSubImage3DOES
+GLAD_API_CALL PFNGLCREATEMEMORYOBJECTSEXTPROC glad_glCreateMemoryObjectsEXT;
+#define glCreateMemoryObjectsEXT glad_glCreateMemoryObjectsEXT
+GLAD_API_CALL PFNGLCREATEPROGRAMPROC glad_glCreateProgram;
+#define glCreateProgram glad_glCreateProgram
+GLAD_API_CALL PFNGLCREATESHADERPROC glad_glCreateShader;
+#define glCreateShader glad_glCreateShader
+GLAD_API_CALL PFNGLCREATESHADERPROGRAMVEXTPROC glad_glCreateShaderProgramvEXT;
+#define glCreateShaderProgramvEXT glad_glCreateShaderProgramvEXT
+GLAD_API_CALL PFNGLCULLFACEPROC glad_glCullFace;
+#define glCullFace glad_glCullFace
+GLAD_API_CALL PFNGLDEBUGMESSAGECALLBACKKHRPROC glad_glDebugMessageCallbackKHR;
+#define glDebugMessageCallbackKHR glad_glDebugMessageCallbackKHR
+GLAD_API_CALL PFNGLDEBUGMESSAGECONTROLKHRPROC glad_glDebugMessageControlKHR;
+#define glDebugMessageControlKHR glad_glDebugMessageControlKHR
+GLAD_API_CALL PFNGLDEBUGMESSAGEINSERTKHRPROC glad_glDebugMessageInsertKHR;
+#define glDebugMessageInsertKHR glad_glDebugMessageInsertKHR
+GLAD_API_CALL PFNGLDELETEBUFFERSPROC glad_glDeleteBuffers;
+#define glDeleteBuffers glad_glDeleteBuffers
+GLAD_API_CALL PFNGLDELETEFRAMEBUFFERSPROC glad_glDeleteFramebuffers;
+#define glDeleteFramebuffers glad_glDeleteFramebuffers
+GLAD_API_CALL PFNGLDELETEMEMORYOBJECTSEXTPROC glad_glDeleteMemoryObjectsEXT;
+#define glDeleteMemoryObjectsEXT glad_glDeleteMemoryObjectsEXT
+GLAD_API_CALL PFNGLDELETEPROGRAMPROC glad_glDeleteProgram;
+#define glDeleteProgram glad_glDeleteProgram
+GLAD_API_CALL PFNGLDELETEPROGRAMPIPELINESEXTPROC glad_glDeleteProgramPipelinesEXT;
+#define glDeleteProgramPipelinesEXT glad_glDeleteProgramPipelinesEXT
+GLAD_API_CALL PFNGLDELETEQUERIESEXTPROC glad_glDeleteQueriesEXT;
+#define glDeleteQueriesEXT glad_glDeleteQueriesEXT
+GLAD_API_CALL PFNGLDELETERENDERBUFFERSPROC glad_glDeleteRenderbuffers;
+#define glDeleteRenderbuffers glad_glDeleteRenderbuffers
+GLAD_API_CALL PFNGLDELETESEMAPHORESEXTPROC glad_glDeleteSemaphoresEXT;
+#define glDeleteSemaphoresEXT glad_glDeleteSemaphoresEXT
+GLAD_API_CALL PFNGLDELETESHADERPROC glad_glDeleteShader;
+#define glDeleteShader glad_glDeleteShader
+GLAD_API_CALL PFNGLDELETETEXTURESPROC glad_glDeleteTextures;
+#define glDeleteTextures glad_glDeleteTextures
+GLAD_API_CALL PFNGLDELETEVERTEXARRAYSOESPROC glad_glDeleteVertexArraysOES;
+#define glDeleteVertexArraysOES glad_glDeleteVertexArraysOES
+GLAD_API_CALL PFNGLDEPTHFUNCPROC glad_glDepthFunc;
+#define glDepthFunc glad_glDepthFunc
+GLAD_API_CALL PFNGLDEPTHMASKPROC glad_glDepthMask;
+#define glDepthMask glad_glDepthMask
+GLAD_API_CALL PFNGLDEPTHRANGEARRAYFVOESPROC glad_glDepthRangeArrayfvOES;
+#define glDepthRangeArrayfvOES glad_glDepthRangeArrayfvOES
+GLAD_API_CALL PFNGLDEPTHRANGEINDEXEDFOESPROC glad_glDepthRangeIndexedfOES;
+#define glDepthRangeIndexedfOES glad_glDepthRangeIndexedfOES
+GLAD_API_CALL PFNGLDEPTHRANGEFPROC glad_glDepthRangef;
+#define glDepthRangef glad_glDepthRangef
+GLAD_API_CALL PFNGLDETACHSHADERPROC glad_glDetachShader;
+#define glDetachShader glad_glDetachShader
+GLAD_API_CALL PFNGLDISABLEPROC glad_glDisable;
+#define glDisable glad_glDisable
+GLAD_API_CALL PFNGLDISABLEVERTEXATTRIBARRAYPROC glad_glDisableVertexAttribArray;
+#define glDisableVertexAttribArray glad_glDisableVertexAttribArray
+GLAD_API_CALL PFNGLDISABLEIEXTPROC glad_glDisableiEXT;
+#define glDisableiEXT glad_glDisableiEXT
+GLAD_API_CALL PFNGLDISABLEIOESPROC glad_glDisableiOES;
+#define glDisableiOES glad_glDisableiOES
+GLAD_API_CALL PFNGLDISCARDFRAMEBUFFEREXTPROC glad_glDiscardFramebufferEXT;
+#define glDiscardFramebufferEXT glad_glDiscardFramebufferEXT
+GLAD_API_CALL PFNGLDRAWARRAYSPROC glad_glDrawArrays;
+#define glDrawArrays glad_glDrawArrays
+GLAD_API_CALL PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEEXTPROC glad_glDrawArraysInstancedBaseInstanceEXT;
+#define glDrawArraysInstancedBaseInstanceEXT glad_glDrawArraysInstancedBaseInstanceEXT
+GLAD_API_CALL PFNGLDRAWARRAYSINSTANCEDEXTPROC glad_glDrawArraysInstancedEXT;
+#define glDrawArraysInstancedEXT glad_glDrawArraysInstancedEXT
+GLAD_API_CALL PFNGLDRAWBUFFERSEXTPROC glad_glDrawBuffersEXT;
+#define glDrawBuffersEXT glad_glDrawBuffersEXT
+GLAD_API_CALL PFNGLDRAWBUFFERSINDEXEDEXTPROC glad_glDrawBuffersIndexedEXT;
+#define glDrawBuffersIndexedEXT glad_glDrawBuffersIndexedEXT
+GLAD_API_CALL PFNGLDRAWELEMENTSPROC glad_glDrawElements;
+#define glDrawElements glad_glDrawElements
+GLAD_API_CALL PFNGLDRAWELEMENTSBASEVERTEXEXTPROC glad_glDrawElementsBaseVertexEXT;
+#define glDrawElementsBaseVertexEXT glad_glDrawElementsBaseVertexEXT
+GLAD_API_CALL PFNGLDRAWELEMENTSBASEVERTEXOESPROC glad_glDrawElementsBaseVertexOES;
+#define glDrawElementsBaseVertexOES glad_glDrawElementsBaseVertexOES
+GLAD_API_CALL PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEEXTPROC glad_glDrawElementsInstancedBaseInstanceEXT;
+#define glDrawElementsInstancedBaseInstanceEXT glad_glDrawElementsInstancedBaseInstanceEXT
+GLAD_API_CALL PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEEXTPROC glad_glDrawElementsInstancedBaseVertexBaseInstanceEXT;
+#define glDrawElementsInstancedBaseVertexBaseInstanceEXT glad_glDrawElementsInstancedBaseVertexBaseInstanceEXT
+GLAD_API_CALL PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXEXTPROC glad_glDrawElementsInstancedBaseVertexEXT;
+#define glDrawElementsInstancedBaseVertexEXT glad_glDrawElementsInstancedBaseVertexEXT
+GLAD_API_CALL PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXOESPROC glad_glDrawElementsInstancedBaseVertexOES;
+#define glDrawElementsInstancedBaseVertexOES glad_glDrawElementsInstancedBaseVertexOES
+GLAD_API_CALL PFNGLDRAWELEMENTSINSTANCEDEXTPROC glad_glDrawElementsInstancedEXT;
+#define glDrawElementsInstancedEXT glad_glDrawElementsInstancedEXT
+GLAD_API_CALL PFNGLDRAWRANGEELEMENTSBASEVERTEXEXTPROC glad_glDrawRangeElementsBaseVertexEXT;
+#define glDrawRangeElementsBaseVertexEXT glad_glDrawRangeElementsBaseVertexEXT
+GLAD_API_CALL PFNGLDRAWRANGEELEMENTSBASEVERTEXOESPROC glad_glDrawRangeElementsBaseVertexOES;
+#define glDrawRangeElementsBaseVertexOES glad_glDrawRangeElementsBaseVertexOES
+GLAD_API_CALL PFNGLDRAWTRANSFORMFEEDBACKEXTPROC glad_glDrawTransformFeedbackEXT;
+#define glDrawTransformFeedbackEXT glad_glDrawTransformFeedbackEXT
+GLAD_API_CALL PFNGLDRAWTRANSFORMFEEDBACKINSTANCEDEXTPROC glad_glDrawTransformFeedbackInstancedEXT;
+#define glDrawTransformFeedbackInstancedEXT glad_glDrawTransformFeedbackInstancedEXT
+GLAD_API_CALL PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC glad_glEGLImageTargetRenderbufferStorageOES;
+#define glEGLImageTargetRenderbufferStorageOES glad_glEGLImageTargetRenderbufferStorageOES
+GLAD_API_CALL PFNGLEGLIMAGETARGETTEXSTORAGEEXTPROC glad_glEGLImageTargetTexStorageEXT;
+#define glEGLImageTargetTexStorageEXT glad_glEGLImageTargetTexStorageEXT
+GLAD_API_CALL PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glad_glEGLImageTargetTexture2DOES;
+#define glEGLImageTargetTexture2DOES glad_glEGLImageTargetTexture2DOES
+GLAD_API_CALL PFNGLEGLIMAGETARGETTEXTURESTORAGEEXTPROC glad_glEGLImageTargetTextureStorageEXT;
+#define glEGLImageTargetTextureStorageEXT glad_glEGLImageTargetTextureStorageEXT
+GLAD_API_CALL PFNGLENABLEPROC glad_glEnable;
+#define glEnable glad_glEnable
+GLAD_API_CALL PFNGLENABLEVERTEXATTRIBARRAYPROC glad_glEnableVertexAttribArray;
+#define glEnableVertexAttribArray glad_glEnableVertexAttribArray
+GLAD_API_CALL PFNGLENABLEIEXTPROC glad_glEnableiEXT;
+#define glEnableiEXT glad_glEnableiEXT
+GLAD_API_CALL PFNGLENABLEIOESPROC glad_glEnableiOES;
+#define glEnableiOES glad_glEnableiOES
+GLAD_API_CALL PFNGLENDQUERYEXTPROC glad_glEndQueryEXT;
+#define glEndQueryEXT glad_glEndQueryEXT
+GLAD_API_CALL PFNGLFINISHPROC glad_glFinish;
+#define glFinish glad_glFinish
+GLAD_API_CALL PFNGLFLUSHPROC glad_glFlush;
+#define glFlush glad_glFlush
+GLAD_API_CALL PFNGLFLUSHMAPPEDBUFFERRANGEEXTPROC glad_glFlushMappedBufferRangeEXT;
+#define glFlushMappedBufferRangeEXT glad_glFlushMappedBufferRangeEXT
+GLAD_API_CALL PFNGLFRAMEBUFFERFETCHBARRIEREXTPROC glad_glFramebufferFetchBarrierEXT;
+#define glFramebufferFetchBarrierEXT glad_glFramebufferFetchBarrierEXT
+GLAD_API_CALL PFNGLFRAMEBUFFERPIXELLOCALSTORAGESIZEEXTPROC glad_glFramebufferPixelLocalStorageSizeEXT;
+#define glFramebufferPixelLocalStorageSizeEXT glad_glFramebufferPixelLocalStorageSizeEXT
+GLAD_API_CALL PFNGLFRAMEBUFFERRENDERBUFFERPROC glad_glFramebufferRenderbuffer;
+#define glFramebufferRenderbuffer glad_glFramebufferRenderbuffer
+GLAD_API_CALL PFNGLFRAMEBUFFERSHADINGRATEEXTPROC glad_glFramebufferShadingRateEXT;
+#define glFramebufferShadingRateEXT glad_glFramebufferShadingRateEXT
+GLAD_API_CALL PFNGLFRAMEBUFFERTEXTURE2DPROC glad_glFramebufferTexture2D;
+#define glFramebufferTexture2D glad_glFramebufferTexture2D
+GLAD_API_CALL PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC glad_glFramebufferTexture2DMultisampleEXT;
+#define glFramebufferTexture2DMultisampleEXT glad_glFramebufferTexture2DMultisampleEXT
+GLAD_API_CALL PFNGLFRAMEBUFFERTEXTURE3DOESPROC glad_glFramebufferTexture3DOES;
+#define glFramebufferTexture3DOES glad_glFramebufferTexture3DOES
+GLAD_API_CALL PFNGLFRAMEBUFFERTEXTUREEXTPROC glad_glFramebufferTextureEXT;
+#define glFramebufferTextureEXT glad_glFramebufferTextureEXT
+GLAD_API_CALL PFNGLFRAMEBUFFERTEXTUREOESPROC glad_glFramebufferTextureOES;
+#define glFramebufferTextureOES glad_glFramebufferTextureOES
+GLAD_API_CALL PFNGLFRONTFACEPROC glad_glFrontFace;
+#define glFrontFace glad_glFrontFace
+GLAD_API_CALL PFNGLGENBUFFERSPROC glad_glGenBuffers;
+#define glGenBuffers glad_glGenBuffers
+GLAD_API_CALL PFNGLGENFRAMEBUFFERSPROC glad_glGenFramebuffers;
+#define glGenFramebuffers glad_glGenFramebuffers
+GLAD_API_CALL PFNGLGENPROGRAMPIPELINESEXTPROC glad_glGenProgramPipelinesEXT;
+#define glGenProgramPipelinesEXT glad_glGenProgramPipelinesEXT
+GLAD_API_CALL PFNGLGENQUERIESEXTPROC glad_glGenQueriesEXT;
+#define glGenQueriesEXT glad_glGenQueriesEXT
+GLAD_API_CALL PFNGLGENRENDERBUFFERSPROC glad_glGenRenderbuffers;
+#define glGenRenderbuffers glad_glGenRenderbuffers
+GLAD_API_CALL PFNGLGENSEMAPHORESEXTPROC glad_glGenSemaphoresEXT;
+#define glGenSemaphoresEXT glad_glGenSemaphoresEXT
+GLAD_API_CALL PFNGLGENTEXTURESPROC glad_glGenTextures;
+#define glGenTextures glad_glGenTextures
+GLAD_API_CALL PFNGLGENVERTEXARRAYSOESPROC glad_glGenVertexArraysOES;
+#define glGenVertexArraysOES glad_glGenVertexArraysOES
+GLAD_API_CALL PFNGLGENERATEMIPMAPPROC glad_glGenerateMipmap;
+#define glGenerateMipmap glad_glGenerateMipmap
+GLAD_API_CALL PFNGLGETACTIVEATTRIBPROC glad_glGetActiveAttrib;
+#define glGetActiveAttrib glad_glGetActiveAttrib
+GLAD_API_CALL PFNGLGETACTIVEUNIFORMPROC glad_glGetActiveUniform;
+#define glGetActiveUniform glad_glGetActiveUniform
+GLAD_API_CALL PFNGLGETATTACHEDSHADERSPROC glad_glGetAttachedShaders;
+#define glGetAttachedShaders glad_glGetAttachedShaders
+GLAD_API_CALL PFNGLGETATTRIBLOCATIONPROC glad_glGetAttribLocation;
+#define glGetAttribLocation glad_glGetAttribLocation
+GLAD_API_CALL PFNGLGETBOOLEANVPROC glad_glGetBooleanv;
+#define glGetBooleanv glad_glGetBooleanv
+GLAD_API_CALL PFNGLGETBUFFERPARAMETERIVPROC glad_glGetBufferParameteriv;
+#define glGetBufferParameteriv glad_glGetBufferParameteriv
+GLAD_API_CALL PFNGLGETBUFFERPOINTERVOESPROC glad_glGetBufferPointervOES;
+#define glGetBufferPointervOES glad_glGetBufferPointervOES
+GLAD_API_CALL PFNGLGETDEBUGMESSAGELOGKHRPROC glad_glGetDebugMessageLogKHR;
+#define glGetDebugMessageLogKHR glad_glGetDebugMessageLogKHR
+GLAD_API_CALL PFNGLGETERRORPROC glad_glGetError;
+#define glGetError glad_glGetError
+GLAD_API_CALL PFNGLGETFLOATI_VOESPROC glad_glGetFloati_vOES;
+#define glGetFloati_vOES glad_glGetFloati_vOES
+GLAD_API_CALL PFNGLGETFLOATVPROC glad_glGetFloatv;
+#define glGetFloatv glad_glGetFloatv
+GLAD_API_CALL PFNGLGETFRAGDATAINDEXEXTPROC glad_glGetFragDataIndexEXT;
+#define glGetFragDataIndexEXT glad_glGetFragDataIndexEXT
+GLAD_API_CALL PFNGLGETFRAGMENTSHADINGRATESEXTPROC glad_glGetFragmentShadingRatesEXT;
+#define glGetFragmentShadingRatesEXT glad_glGetFragmentShadingRatesEXT
+GLAD_API_CALL PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glad_glGetFramebufferAttachmentParameteriv;
+#define glGetFramebufferAttachmentParameteriv glad_glGetFramebufferAttachmentParameteriv
+GLAD_API_CALL PFNGLGETFRAMEBUFFERPIXELLOCALSTORAGESIZEEXTPROC glad_glGetFramebufferPixelLocalStorageSizeEXT;
+#define glGetFramebufferPixelLocalStorageSizeEXT glad_glGetFramebufferPixelLocalStorageSizeEXT
+GLAD_API_CALL PFNGLGETGRAPHICSRESETSTATUSEXTPROC glad_glGetGraphicsResetStatusEXT;
+#define glGetGraphicsResetStatusEXT glad_glGetGraphicsResetStatusEXT
+GLAD_API_CALL PFNGLGETGRAPHICSRESETSTATUSKHRPROC glad_glGetGraphicsResetStatusKHR;
+#define glGetGraphicsResetStatusKHR glad_glGetGraphicsResetStatusKHR
+GLAD_API_CALL PFNGLGETINTEGER64VEXTPROC glad_glGetInteger64vEXT;
+#define glGetInteger64vEXT glad_glGetInteger64vEXT
+GLAD_API_CALL PFNGLGETINTEGERI_VEXTPROC glad_glGetIntegeri_vEXT;
+#define glGetIntegeri_vEXT glad_glGetIntegeri_vEXT
+GLAD_API_CALL PFNGLGETINTEGERVPROC glad_glGetIntegerv;
+#define glGetIntegerv glad_glGetIntegerv
+GLAD_API_CALL PFNGLGETMEMORYOBJECTPARAMETERIVEXTPROC glad_glGetMemoryObjectParameterivEXT;
+#define glGetMemoryObjectParameterivEXT glad_glGetMemoryObjectParameterivEXT
+GLAD_API_CALL PFNGLGETOBJECTLABELEXTPROC glad_glGetObjectLabelEXT;
+#define glGetObjectLabelEXT glad_glGetObjectLabelEXT
+GLAD_API_CALL PFNGLGETOBJECTLABELKHRPROC glad_glGetObjectLabelKHR;
+#define glGetObjectLabelKHR glad_glGetObjectLabelKHR
+GLAD_API_CALL PFNGLGETOBJECTPTRLABELKHRPROC glad_glGetObjectPtrLabelKHR;
+#define glGetObjectPtrLabelKHR glad_glGetObjectPtrLabelKHR
+GLAD_API_CALL PFNGLGETPOINTERVKHRPROC glad_glGetPointervKHR;
+#define glGetPointervKHR glad_glGetPointervKHR
+GLAD_API_CALL PFNGLGETPROGRAMBINARYOESPROC glad_glGetProgramBinaryOES;
+#define glGetProgramBinaryOES glad_glGetProgramBinaryOES
+GLAD_API_CALL PFNGLGETPROGRAMINFOLOGPROC glad_glGetProgramInfoLog;
+#define glGetProgramInfoLog glad_glGetProgramInfoLog
+GLAD_API_CALL PFNGLGETPROGRAMPIPELINEINFOLOGEXTPROC glad_glGetProgramPipelineInfoLogEXT;
+#define glGetProgramPipelineInfoLogEXT glad_glGetProgramPipelineInfoLogEXT
+GLAD_API_CALL PFNGLGETPROGRAMPIPELINEIVEXTPROC glad_glGetProgramPipelineivEXT;
+#define glGetProgramPipelineivEXT glad_glGetProgramPipelineivEXT
+GLAD_API_CALL PFNGLGETPROGRAMRESOURCELOCATIONINDEXEXTPROC glad_glGetProgramResourceLocationIndexEXT;
+#define glGetProgramResourceLocationIndexEXT glad_glGetProgramResourceLocationIndexEXT
+GLAD_API_CALL PFNGLGETPROGRAMIVPROC glad_glGetProgramiv;
+#define glGetProgramiv glad_glGetProgramiv
+GLAD_API_CALL PFNGLGETQUERYOBJECTI64VEXTPROC glad_glGetQueryObjecti64vEXT;
+#define glGetQueryObjecti64vEXT glad_glGetQueryObjecti64vEXT
+GLAD_API_CALL PFNGLGETQUERYOBJECTIVEXTPROC glad_glGetQueryObjectivEXT;
+#define glGetQueryObjectivEXT glad_glGetQueryObjectivEXT
+GLAD_API_CALL PFNGLGETQUERYOBJECTUI64VEXTPROC glad_glGetQueryObjectui64vEXT;
+#define glGetQueryObjectui64vEXT glad_glGetQueryObjectui64vEXT
+GLAD_API_CALL PFNGLGETQUERYOBJECTUIVEXTPROC glad_glGetQueryObjectuivEXT;
+#define glGetQueryObjectuivEXT glad_glGetQueryObjectuivEXT
+GLAD_API_CALL PFNGLGETQUERYIVEXTPROC glad_glGetQueryivEXT;
+#define glGetQueryivEXT glad_glGetQueryivEXT
+GLAD_API_CALL PFNGLGETRENDERBUFFERPARAMETERIVPROC glad_glGetRenderbufferParameteriv;
+#define glGetRenderbufferParameteriv glad_glGetRenderbufferParameteriv
+GLAD_API_CALL PFNGLGETSAMPLERPARAMETERIIVEXTPROC glad_glGetSamplerParameterIivEXT;
+#define glGetSamplerParameterIivEXT glad_glGetSamplerParameterIivEXT
+GLAD_API_CALL PFNGLGETSAMPLERPARAMETERIIVOESPROC glad_glGetSamplerParameterIivOES;
+#define glGetSamplerParameterIivOES glad_glGetSamplerParameterIivOES
+GLAD_API_CALL PFNGLGETSAMPLERPARAMETERIUIVEXTPROC glad_glGetSamplerParameterIuivEXT;
+#define glGetSamplerParameterIuivEXT glad_glGetSamplerParameterIuivEXT
+GLAD_API_CALL PFNGLGETSAMPLERPARAMETERIUIVOESPROC glad_glGetSamplerParameterIuivOES;
+#define glGetSamplerParameterIuivOES glad_glGetSamplerParameterIuivOES
+GLAD_API_CALL PFNGLGETSEMAPHOREPARAMETERUI64VEXTPROC glad_glGetSemaphoreParameterui64vEXT;
+#define glGetSemaphoreParameterui64vEXT glad_glGetSemaphoreParameterui64vEXT
+GLAD_API_CALL PFNGLGETSHADERINFOLOGPROC glad_glGetShaderInfoLog;
+#define glGetShaderInfoLog glad_glGetShaderInfoLog
+GLAD_API_CALL PFNGLGETSHADERPRECISIONFORMATPROC glad_glGetShaderPrecisionFormat;
+#define glGetShaderPrecisionFormat glad_glGetShaderPrecisionFormat
+GLAD_API_CALL PFNGLGETSHADERSOURCEPROC glad_glGetShaderSource;
+#define glGetShaderSource glad_glGetShaderSource
+GLAD_API_CALL PFNGLGETSHADERIVPROC glad_glGetShaderiv;
+#define glGetShaderiv glad_glGetShaderiv
+GLAD_API_CALL PFNGLGETSTRINGPROC glad_glGetString;
+#define glGetString glad_glGetString
+GLAD_API_CALL PFNGLGETTEXPARAMETERIIVEXTPROC glad_glGetTexParameterIivEXT;
+#define glGetTexParameterIivEXT glad_glGetTexParameterIivEXT
+GLAD_API_CALL PFNGLGETTEXPARAMETERIIVOESPROC glad_glGetTexParameterIivOES;
+#define glGetTexParameterIivOES glad_glGetTexParameterIivOES
+GLAD_API_CALL PFNGLGETTEXPARAMETERIUIVEXTPROC glad_glGetTexParameterIuivEXT;
+#define glGetTexParameterIuivEXT glad_glGetTexParameterIuivEXT
+GLAD_API_CALL PFNGLGETTEXPARAMETERIUIVOESPROC glad_glGetTexParameterIuivOES;
+#define glGetTexParameterIuivOES glad_glGetTexParameterIuivOES
+GLAD_API_CALL PFNGLGETTEXPARAMETERFVPROC glad_glGetTexParameterfv;
+#define glGetTexParameterfv glad_glGetTexParameterfv
+GLAD_API_CALL PFNGLGETTEXPARAMETERIVPROC glad_glGetTexParameteriv;
+#define glGetTexParameteriv glad_glGetTexParameteriv
+GLAD_API_CALL PFNGLGETUNIFORMLOCATIONPROC glad_glGetUniformLocation;
+#define glGetUniformLocation glad_glGetUniformLocation
+GLAD_API_CALL PFNGLGETUNIFORMFVPROC glad_glGetUniformfv;
+#define glGetUniformfv glad_glGetUniformfv
+GLAD_API_CALL PFNGLGETUNIFORMIVPROC glad_glGetUniformiv;
+#define glGetUniformiv glad_glGetUniformiv
+GLAD_API_CALL PFNGLGETUNSIGNEDBYTEI_VEXTPROC glad_glGetUnsignedBytei_vEXT;
+#define glGetUnsignedBytei_vEXT glad_glGetUnsignedBytei_vEXT
+GLAD_API_CALL PFNGLGETUNSIGNEDBYTEVEXTPROC glad_glGetUnsignedBytevEXT;
+#define glGetUnsignedBytevEXT glad_glGetUnsignedBytevEXT
+GLAD_API_CALL PFNGLGETVERTEXATTRIBPOINTERVPROC glad_glGetVertexAttribPointerv;
+#define glGetVertexAttribPointerv glad_glGetVertexAttribPointerv
+GLAD_API_CALL PFNGLGETVERTEXATTRIBFVPROC glad_glGetVertexAttribfv;
+#define glGetVertexAttribfv glad_glGetVertexAttribfv
+GLAD_API_CALL PFNGLGETVERTEXATTRIBIVPROC glad_glGetVertexAttribiv;
+#define glGetVertexAttribiv glad_glGetVertexAttribiv
+GLAD_API_CALL PFNGLGETNUNIFORMFVEXTPROC glad_glGetnUniformfvEXT;
+#define glGetnUniformfvEXT glad_glGetnUniformfvEXT
+GLAD_API_CALL PFNGLGETNUNIFORMFVKHRPROC glad_glGetnUniformfvKHR;
+#define glGetnUniformfvKHR glad_glGetnUniformfvKHR
+GLAD_API_CALL PFNGLGETNUNIFORMIVEXTPROC glad_glGetnUniformivEXT;
+#define glGetnUniformivEXT glad_glGetnUniformivEXT
+GLAD_API_CALL PFNGLGETNUNIFORMIVKHRPROC glad_glGetnUniformivKHR;
+#define glGetnUniformivKHR glad_glGetnUniformivKHR
+GLAD_API_CALL PFNGLGETNUNIFORMUIVKHRPROC glad_glGetnUniformuivKHR;
+#define glGetnUniformuivKHR glad_glGetnUniformuivKHR
+GLAD_API_CALL PFNGLHINTPROC glad_glHint;
+#define glHint glad_glHint
+GLAD_API_CALL PFNGLIMPORTMEMORYFDEXTPROC glad_glImportMemoryFdEXT;
+#define glImportMemoryFdEXT glad_glImportMemoryFdEXT
+GLAD_API_CALL PFNGLIMPORTMEMORYWIN32HANDLEEXTPROC glad_glImportMemoryWin32HandleEXT;
+#define glImportMemoryWin32HandleEXT glad_glImportMemoryWin32HandleEXT
+GLAD_API_CALL PFNGLIMPORTMEMORYWIN32NAMEEXTPROC glad_glImportMemoryWin32NameEXT;
+#define glImportMemoryWin32NameEXT glad_glImportMemoryWin32NameEXT
+GLAD_API_CALL PFNGLIMPORTSEMAPHOREFDEXTPROC glad_glImportSemaphoreFdEXT;
+#define glImportSemaphoreFdEXT glad_glImportSemaphoreFdEXT
+GLAD_API_CALL PFNGLIMPORTSEMAPHOREWIN32HANDLEEXTPROC glad_glImportSemaphoreWin32HandleEXT;
+#define glImportSemaphoreWin32HandleEXT glad_glImportSemaphoreWin32HandleEXT
+GLAD_API_CALL PFNGLIMPORTSEMAPHOREWIN32NAMEEXTPROC glad_glImportSemaphoreWin32NameEXT;
+#define glImportSemaphoreWin32NameEXT glad_glImportSemaphoreWin32NameEXT
+GLAD_API_CALL PFNGLINSERTEVENTMARKEREXTPROC glad_glInsertEventMarkerEXT;
+#define glInsertEventMarkerEXT glad_glInsertEventMarkerEXT
+GLAD_API_CALL PFNGLISBUFFERPROC glad_glIsBuffer;
+#define glIsBuffer glad_glIsBuffer
+GLAD_API_CALL PFNGLISENABLEDPROC glad_glIsEnabled;
+#define glIsEnabled glad_glIsEnabled
+GLAD_API_CALL PFNGLISENABLEDIEXTPROC glad_glIsEnablediEXT;
+#define glIsEnablediEXT glad_glIsEnablediEXT
+GLAD_API_CALL PFNGLISENABLEDIOESPROC glad_glIsEnablediOES;
+#define glIsEnablediOES glad_glIsEnablediOES
+GLAD_API_CALL PFNGLISFRAMEBUFFERPROC glad_glIsFramebuffer;
+#define glIsFramebuffer glad_glIsFramebuffer
+GLAD_API_CALL PFNGLISMEMORYOBJECTEXTPROC glad_glIsMemoryObjectEXT;
+#define glIsMemoryObjectEXT glad_glIsMemoryObjectEXT
+GLAD_API_CALL PFNGLISPROGRAMPROC glad_glIsProgram;
+#define glIsProgram glad_glIsProgram
+GLAD_API_CALL PFNGLISPROGRAMPIPELINEEXTPROC glad_glIsProgramPipelineEXT;
+#define glIsProgramPipelineEXT glad_glIsProgramPipelineEXT
+GLAD_API_CALL PFNGLISQUERYEXTPROC glad_glIsQueryEXT;
+#define glIsQueryEXT glad_glIsQueryEXT
+GLAD_API_CALL PFNGLISRENDERBUFFERPROC glad_glIsRenderbuffer;
+#define glIsRenderbuffer glad_glIsRenderbuffer
+GLAD_API_CALL PFNGLISSEMAPHOREEXTPROC glad_glIsSemaphoreEXT;
+#define glIsSemaphoreEXT glad_glIsSemaphoreEXT
+GLAD_API_CALL PFNGLISSHADERPROC glad_glIsShader;
+#define glIsShader glad_glIsShader
+GLAD_API_CALL PFNGLISTEXTUREPROC glad_glIsTexture;
+#define glIsTexture glad_glIsTexture
+GLAD_API_CALL PFNGLISVERTEXARRAYOESPROC glad_glIsVertexArrayOES;
+#define glIsVertexArrayOES glad_glIsVertexArrayOES
+GLAD_API_CALL PFNGLLABELOBJECTEXTPROC glad_glLabelObjectEXT;
+#define glLabelObjectEXT glad_glLabelObjectEXT
+GLAD_API_CALL PFNGLLINEWIDTHPROC glad_glLineWidth;
+#define glLineWidth glad_glLineWidth
+GLAD_API_CALL PFNGLLINKPROGRAMPROC glad_glLinkProgram;
+#define glLinkProgram glad_glLinkProgram
+GLAD_API_CALL PFNGLMAPBUFFEROESPROC glad_glMapBufferOES;
+#define glMapBufferOES glad_glMapBufferOES
+GLAD_API_CALL PFNGLMAPBUFFERRANGEEXTPROC glad_glMapBufferRangeEXT;
+#define glMapBufferRangeEXT glad_glMapBufferRangeEXT
+GLAD_API_CALL PFNGLMAXSHADERCOMPILERTHREADSKHRPROC glad_glMaxShaderCompilerThreadsKHR;
+#define glMaxShaderCompilerThreadsKHR glad_glMaxShaderCompilerThreadsKHR
+GLAD_API_CALL PFNGLMEMORYOBJECTPARAMETERIVEXTPROC glad_glMemoryObjectParameterivEXT;
+#define glMemoryObjectParameterivEXT glad_glMemoryObjectParameterivEXT
+GLAD_API_CALL PFNGLMINSAMPLESHADINGOESPROC glad_glMinSampleShadingOES;
+#define glMinSampleShadingOES glad_glMinSampleShadingOES
+GLAD_API_CALL PFNGLMULTIDRAWARRAYSEXTPROC glad_glMultiDrawArraysEXT;
+#define glMultiDrawArraysEXT glad_glMultiDrawArraysEXT
+GLAD_API_CALL PFNGLMULTIDRAWARRAYSINDIRECTEXTPROC glad_glMultiDrawArraysIndirectEXT;
+#define glMultiDrawArraysIndirectEXT glad_glMultiDrawArraysIndirectEXT
+GLAD_API_CALL PFNGLMULTIDRAWELEMENTSBASEVERTEXEXTPROC glad_glMultiDrawElementsBaseVertexEXT;
+#define glMultiDrawElementsBaseVertexEXT glad_glMultiDrawElementsBaseVertexEXT
+GLAD_API_CALL PFNGLMULTIDRAWELEMENTSEXTPROC glad_glMultiDrawElementsEXT;
+#define glMultiDrawElementsEXT glad_glMultiDrawElementsEXT
+GLAD_API_CALL PFNGLMULTIDRAWELEMENTSINDIRECTEXTPROC glad_glMultiDrawElementsIndirectEXT;
+#define glMultiDrawElementsIndirectEXT glad_glMultiDrawElementsIndirectEXT
+GLAD_API_CALL PFNGLNAMEDBUFFERSTORAGEEXTERNALEXTPROC glad_glNamedBufferStorageExternalEXT;
+#define glNamedBufferStorageExternalEXT glad_glNamedBufferStorageExternalEXT
+GLAD_API_CALL PFNGLNAMEDBUFFERSTORAGEMEMEXTPROC glad_glNamedBufferStorageMemEXT;
+#define glNamedBufferStorageMemEXT glad_glNamedBufferStorageMemEXT
+GLAD_API_CALL PFNGLOBJECTLABELKHRPROC glad_glObjectLabelKHR;
+#define glObjectLabelKHR glad_glObjectLabelKHR
+GLAD_API_CALL PFNGLOBJECTPTRLABELKHRPROC glad_glObjectPtrLabelKHR;
+#define glObjectPtrLabelKHR glad_glObjectPtrLabelKHR
+GLAD_API_CALL PFNGLPATCHPARAMETERIEXTPROC glad_glPatchParameteriEXT;
+#define glPatchParameteriEXT glad_glPatchParameteriEXT
+GLAD_API_CALL PFNGLPATCHPARAMETERIOESPROC glad_glPatchParameteriOES;
+#define glPatchParameteriOES glad_glPatchParameteriOES
+GLAD_API_CALL PFNGLPIXELSTOREIPROC glad_glPixelStorei;
+#define glPixelStorei glad_glPixelStorei
+GLAD_API_CALL PFNGLPOLYGONOFFSETPROC glad_glPolygonOffset;
+#define glPolygonOffset glad_glPolygonOffset
+GLAD_API_CALL PFNGLPOLYGONOFFSETCLAMPEXTPROC glad_glPolygonOffsetClampEXT;
+#define glPolygonOffsetClampEXT glad_glPolygonOffsetClampEXT
+GLAD_API_CALL PFNGLPOPDEBUGGROUPKHRPROC glad_glPopDebugGroupKHR;
+#define glPopDebugGroupKHR glad_glPopDebugGroupKHR
+GLAD_API_CALL PFNGLPOPGROUPMARKEREXTPROC glad_glPopGroupMarkerEXT;
+#define glPopGroupMarkerEXT glad_glPopGroupMarkerEXT
+GLAD_API_CALL PFNGLPRIMITIVEBOUNDINGBOXEXTPROC glad_glPrimitiveBoundingBoxEXT;
+#define glPrimitiveBoundingBoxEXT glad_glPrimitiveBoundingBoxEXT
+GLAD_API_CALL PFNGLPRIMITIVEBOUNDINGBOXOESPROC glad_glPrimitiveBoundingBoxOES;
+#define glPrimitiveBoundingBoxOES glad_glPrimitiveBoundingBoxOES
+GLAD_API_CALL PFNGLPROGRAMBINARYOESPROC glad_glProgramBinaryOES;
+#define glProgramBinaryOES glad_glProgramBinaryOES
+GLAD_API_CALL PFNGLPROGRAMPARAMETERIEXTPROC glad_glProgramParameteriEXT;
+#define glProgramParameteriEXT glad_glProgramParameteriEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORM1FEXTPROC glad_glProgramUniform1fEXT;
+#define glProgramUniform1fEXT glad_glProgramUniform1fEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORM1FVEXTPROC glad_glProgramUniform1fvEXT;
+#define glProgramUniform1fvEXT glad_glProgramUniform1fvEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORM1IEXTPROC glad_glProgramUniform1iEXT;
+#define glProgramUniform1iEXT glad_glProgramUniform1iEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORM1IVEXTPROC glad_glProgramUniform1ivEXT;
+#define glProgramUniform1ivEXT glad_glProgramUniform1ivEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORM1UIEXTPROC glad_glProgramUniform1uiEXT;
+#define glProgramUniform1uiEXT glad_glProgramUniform1uiEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORM1UIVEXTPROC glad_glProgramUniform1uivEXT;
+#define glProgramUniform1uivEXT glad_glProgramUniform1uivEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORM2FEXTPROC glad_glProgramUniform2fEXT;
+#define glProgramUniform2fEXT glad_glProgramUniform2fEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORM2FVEXTPROC glad_glProgramUniform2fvEXT;
+#define glProgramUniform2fvEXT glad_glProgramUniform2fvEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORM2IEXTPROC glad_glProgramUniform2iEXT;
+#define glProgramUniform2iEXT glad_glProgramUniform2iEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORM2IVEXTPROC glad_glProgramUniform2ivEXT;
+#define glProgramUniform2ivEXT glad_glProgramUniform2ivEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORM2UIEXTPROC glad_glProgramUniform2uiEXT;
+#define glProgramUniform2uiEXT glad_glProgramUniform2uiEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORM2UIVEXTPROC glad_glProgramUniform2uivEXT;
+#define glProgramUniform2uivEXT glad_glProgramUniform2uivEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORM3FEXTPROC glad_glProgramUniform3fEXT;
+#define glProgramUniform3fEXT glad_glProgramUniform3fEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORM3FVEXTPROC glad_glProgramUniform3fvEXT;
+#define glProgramUniform3fvEXT glad_glProgramUniform3fvEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORM3IEXTPROC glad_glProgramUniform3iEXT;
+#define glProgramUniform3iEXT glad_glProgramUniform3iEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORM3IVEXTPROC glad_glProgramUniform3ivEXT;
+#define glProgramUniform3ivEXT glad_glProgramUniform3ivEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORM3UIEXTPROC glad_glProgramUniform3uiEXT;
+#define glProgramUniform3uiEXT glad_glProgramUniform3uiEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORM3UIVEXTPROC glad_glProgramUniform3uivEXT;
+#define glProgramUniform3uivEXT glad_glProgramUniform3uivEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORM4FEXTPROC glad_glProgramUniform4fEXT;
+#define glProgramUniform4fEXT glad_glProgramUniform4fEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORM4FVEXTPROC glad_glProgramUniform4fvEXT;
+#define glProgramUniform4fvEXT glad_glProgramUniform4fvEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORM4IEXTPROC glad_glProgramUniform4iEXT;
+#define glProgramUniform4iEXT glad_glProgramUniform4iEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORM4IVEXTPROC glad_glProgramUniform4ivEXT;
+#define glProgramUniform4ivEXT glad_glProgramUniform4ivEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORM4UIEXTPROC glad_glProgramUniform4uiEXT;
+#define glProgramUniform4uiEXT glad_glProgramUniform4uiEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORM4UIVEXTPROC glad_glProgramUniform4uivEXT;
+#define glProgramUniform4uivEXT glad_glProgramUniform4uivEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC glad_glProgramUniformMatrix2fvEXT;
+#define glProgramUniformMatrix2fvEXT glad_glProgramUniformMatrix2fvEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC glad_glProgramUniformMatrix2x3fvEXT;
+#define glProgramUniformMatrix2x3fvEXT glad_glProgramUniformMatrix2x3fvEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC glad_glProgramUniformMatrix2x4fvEXT;
+#define glProgramUniformMatrix2x4fvEXT glad_glProgramUniformMatrix2x4fvEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC glad_glProgramUniformMatrix3fvEXT;
+#define glProgramUniformMatrix3fvEXT glad_glProgramUniformMatrix3fvEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC glad_glProgramUniformMatrix3x2fvEXT;
+#define glProgramUniformMatrix3x2fvEXT glad_glProgramUniformMatrix3x2fvEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC glad_glProgramUniformMatrix3x4fvEXT;
+#define glProgramUniformMatrix3x4fvEXT glad_glProgramUniformMatrix3x4fvEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC glad_glProgramUniformMatrix4fvEXT;
+#define glProgramUniformMatrix4fvEXT glad_glProgramUniformMatrix4fvEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC glad_glProgramUniformMatrix4x2fvEXT;
+#define glProgramUniformMatrix4x2fvEXT glad_glProgramUniformMatrix4x2fvEXT
+GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC glad_glProgramUniformMatrix4x3fvEXT;
+#define glProgramUniformMatrix4x3fvEXT glad_glProgramUniformMatrix4x3fvEXT
+GLAD_API_CALL PFNGLPUSHDEBUGGROUPKHRPROC glad_glPushDebugGroupKHR;
+#define glPushDebugGroupKHR glad_glPushDebugGroupKHR
+GLAD_API_CALL PFNGLPUSHGROUPMARKEREXTPROC glad_glPushGroupMarkerEXT;
+#define glPushGroupMarkerEXT glad_glPushGroupMarkerEXT
+GLAD_API_CALL PFNGLQUERYCOUNTEREXTPROC glad_glQueryCounterEXT;
+#define glQueryCounterEXT glad_glQueryCounterEXT
+GLAD_API_CALL PFNGLRASTERSAMPLESEXTPROC glad_glRasterSamplesEXT;
+#define glRasterSamplesEXT glad_glRasterSamplesEXT
+GLAD_API_CALL PFNGLREADBUFFERINDEXEDEXTPROC glad_glReadBufferIndexedEXT;
+#define glReadBufferIndexedEXT glad_glReadBufferIndexedEXT
+GLAD_API_CALL PFNGLREADPIXELSPROC glad_glReadPixels;
+#define glReadPixels glad_glReadPixels
+GLAD_API_CALL PFNGLREADNPIXELSEXTPROC glad_glReadnPixelsEXT;
+#define glReadnPixelsEXT glad_glReadnPixelsEXT
+GLAD_API_CALL PFNGLREADNPIXELSKHRPROC glad_glReadnPixelsKHR;
+#define glReadnPixelsKHR glad_glReadnPixelsKHR
+GLAD_API_CALL PFNGLRELEASEKEYEDMUTEXWIN32EXTPROC glad_glReleaseKeyedMutexWin32EXT;
+#define glReleaseKeyedMutexWin32EXT glad_glReleaseKeyedMutexWin32EXT
+GLAD_API_CALL PFNGLRELEASESHADERCOMPILERPROC glad_glReleaseShaderCompiler;
+#define glReleaseShaderCompiler glad_glReleaseShaderCompiler
+GLAD_API_CALL PFNGLRENDERBUFFERSTORAGEPROC glad_glRenderbufferStorage;
+#define glRenderbufferStorage glad_glRenderbufferStorage
+GLAD_API_CALL PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glad_glRenderbufferStorageMultisampleEXT;
+#define glRenderbufferStorageMultisampleEXT glad_glRenderbufferStorageMultisampleEXT
+GLAD_API_CALL PFNGLSAMPLECOVERAGEPROC glad_glSampleCoverage;
+#define glSampleCoverage glad_glSampleCoverage
+GLAD_API_CALL PFNGLSAMPLERPARAMETERIIVEXTPROC glad_glSamplerParameterIivEXT;
+#define glSamplerParameterIivEXT glad_glSamplerParameterIivEXT
+GLAD_API_CALL PFNGLSAMPLERPARAMETERIIVOESPROC glad_glSamplerParameterIivOES;
+#define glSamplerParameterIivOES glad_glSamplerParameterIivOES
+GLAD_API_CALL PFNGLSAMPLERPARAMETERIUIVEXTPROC glad_glSamplerParameterIuivEXT;
+#define glSamplerParameterIuivEXT glad_glSamplerParameterIuivEXT
+GLAD_API_CALL PFNGLSAMPLERPARAMETERIUIVOESPROC glad_glSamplerParameterIuivOES;
+#define glSamplerParameterIuivOES glad_glSamplerParameterIuivOES
+GLAD_API_CALL PFNGLSCISSORPROC glad_glScissor;
+#define glScissor glad_glScissor
+GLAD_API_CALL PFNGLSCISSORARRAYVOESPROC glad_glScissorArrayvOES;
+#define glScissorArrayvOES glad_glScissorArrayvOES
+GLAD_API_CALL PFNGLSCISSORINDEXEDOESPROC glad_glScissorIndexedOES;
+#define glScissorIndexedOES glad_glScissorIndexedOES
+GLAD_API_CALL PFNGLSCISSORINDEXEDVOESPROC glad_glScissorIndexedvOES;
+#define glScissorIndexedvOES glad_glScissorIndexedvOES
+GLAD_API_CALL PFNGLSEMAPHOREPARAMETERUI64VEXTPROC glad_glSemaphoreParameterui64vEXT;
+#define glSemaphoreParameterui64vEXT glad_glSemaphoreParameterui64vEXT
+GLAD_API_CALL PFNGLSHADERBINARYPROC glad_glShaderBinary;
+#define glShaderBinary glad_glShaderBinary
+GLAD_API_CALL PFNGLSHADERSOURCEPROC glad_glShaderSource;
+#define glShaderSource glad_glShaderSource
+GLAD_API_CALL PFNGLSHADINGRATECOMBINEROPSEXTPROC glad_glShadingRateCombinerOpsEXT;
+#define glShadingRateCombinerOpsEXT glad_glShadingRateCombinerOpsEXT
+GLAD_API_CALL PFNGLSHADINGRATEEXTPROC glad_glShadingRateEXT;
+#define glShadingRateEXT glad_glShadingRateEXT
+GLAD_API_CALL PFNGLSIGNALSEMAPHOREEXTPROC glad_glSignalSemaphoreEXT;
+#define glSignalSemaphoreEXT glad_glSignalSemaphoreEXT
+GLAD_API_CALL PFNGLSTENCILFUNCPROC glad_glStencilFunc;
+#define glStencilFunc glad_glStencilFunc
+GLAD_API_CALL PFNGLSTENCILFUNCSEPARATEPROC glad_glStencilFuncSeparate;
+#define glStencilFuncSeparate glad_glStencilFuncSeparate
+GLAD_API_CALL PFNGLSTENCILMASKPROC glad_glStencilMask;
+#define glStencilMask glad_glStencilMask
+GLAD_API_CALL PFNGLSTENCILMASKSEPARATEPROC glad_glStencilMaskSeparate;
+#define glStencilMaskSeparate glad_glStencilMaskSeparate
+GLAD_API_CALL PFNGLSTENCILOPPROC glad_glStencilOp;
+#define glStencilOp glad_glStencilOp
+GLAD_API_CALL PFNGLSTENCILOPSEPARATEPROC glad_glStencilOpSeparate;
+#define glStencilOpSeparate glad_glStencilOpSeparate
+GLAD_API_CALL PFNGLTEXBUFFEREXTPROC glad_glTexBufferEXT;
+#define glTexBufferEXT glad_glTexBufferEXT
+GLAD_API_CALL PFNGLTEXBUFFEROESPROC glad_glTexBufferOES;
+#define glTexBufferOES glad_glTexBufferOES
+GLAD_API_CALL PFNGLTEXBUFFERRANGEEXTPROC glad_glTexBufferRangeEXT;
+#define glTexBufferRangeEXT glad_glTexBufferRangeEXT
+GLAD_API_CALL PFNGLTEXBUFFERRANGEOESPROC glad_glTexBufferRangeOES;
+#define glTexBufferRangeOES glad_glTexBufferRangeOES
+GLAD_API_CALL PFNGLTEXIMAGE2DPROC glad_glTexImage2D;
+#define glTexImage2D glad_glTexImage2D
+GLAD_API_CALL PFNGLTEXIMAGE3DOESPROC glad_glTexImage3DOES;
+#define glTexImage3DOES glad_glTexImage3DOES
+GLAD_API_CALL PFNGLTEXPAGECOMMITMENTEXTPROC glad_glTexPageCommitmentEXT;
+#define glTexPageCommitmentEXT glad_glTexPageCommitmentEXT
+GLAD_API_CALL PFNGLTEXPARAMETERIIVEXTPROC glad_glTexParameterIivEXT;
+#define glTexParameterIivEXT glad_glTexParameterIivEXT
+GLAD_API_CALL PFNGLTEXPARAMETERIIVOESPROC glad_glTexParameterIivOES;
+#define glTexParameterIivOES glad_glTexParameterIivOES
+GLAD_API_CALL PFNGLTEXPARAMETERIUIVEXTPROC glad_glTexParameterIuivEXT;
+#define glTexParameterIuivEXT glad_glTexParameterIuivEXT
+GLAD_API_CALL PFNGLTEXPARAMETERIUIVOESPROC glad_glTexParameterIuivOES;
+#define glTexParameterIuivOES glad_glTexParameterIuivOES
+GLAD_API_CALL PFNGLTEXPARAMETERFPROC glad_glTexParameterf;
+#define glTexParameterf glad_glTexParameterf
+GLAD_API_CALL PFNGLTEXPARAMETERFVPROC glad_glTexParameterfv;
+#define glTexParameterfv glad_glTexParameterfv
+GLAD_API_CALL PFNGLTEXPARAMETERIPROC glad_glTexParameteri;
+#define glTexParameteri glad_glTexParameteri
+GLAD_API_CALL PFNGLTEXPARAMETERIVPROC glad_glTexParameteriv;
+#define glTexParameteriv glad_glTexParameteriv
+GLAD_API_CALL PFNGLTEXSTORAGE1DEXTPROC glad_glTexStorage1DEXT;
+#define glTexStorage1DEXT glad_glTexStorage1DEXT
+GLAD_API_CALL PFNGLTEXSTORAGE2DEXTPROC glad_glTexStorage2DEXT;
+#define glTexStorage2DEXT glad_glTexStorage2DEXT
+GLAD_API_CALL PFNGLTEXSTORAGE3DEXTPROC glad_glTexStorage3DEXT;
+#define glTexStorage3DEXT glad_glTexStorage3DEXT
+GLAD_API_CALL PFNGLTEXSTORAGE3DMULTISAMPLEOESPROC glad_glTexStorage3DMultisampleOES;
+#define glTexStorage3DMultisampleOES glad_glTexStorage3DMultisampleOES
+GLAD_API_CALL PFNGLTEXSTORAGEATTRIBS2DEXTPROC glad_glTexStorageAttribs2DEXT;
+#define glTexStorageAttribs2DEXT glad_glTexStorageAttribs2DEXT
+GLAD_API_CALL PFNGLTEXSTORAGEATTRIBS3DEXTPROC glad_glTexStorageAttribs3DEXT;
+#define glTexStorageAttribs3DEXT glad_glTexStorageAttribs3DEXT
+GLAD_API_CALL PFNGLTEXSTORAGEMEM2DEXTPROC glad_glTexStorageMem2DEXT;
+#define glTexStorageMem2DEXT glad_glTexStorageMem2DEXT
+GLAD_API_CALL PFNGLTEXSTORAGEMEM2DMULTISAMPLEEXTPROC glad_glTexStorageMem2DMultisampleEXT;
+#define glTexStorageMem2DMultisampleEXT glad_glTexStorageMem2DMultisampleEXT
+GLAD_API_CALL PFNGLTEXSTORAGEMEM3DEXTPROC glad_glTexStorageMem3DEXT;
+#define glTexStorageMem3DEXT glad_glTexStorageMem3DEXT
+GLAD_API_CALL PFNGLTEXSTORAGEMEM3DMULTISAMPLEEXTPROC glad_glTexStorageMem3DMultisampleEXT;
+#define glTexStorageMem3DMultisampleEXT glad_glTexStorageMem3DMultisampleEXT
+GLAD_API_CALL PFNGLTEXSUBIMAGE2DPROC glad_glTexSubImage2D;
+#define glTexSubImage2D glad_glTexSubImage2D
+GLAD_API_CALL PFNGLTEXSUBIMAGE3DOESPROC glad_glTexSubImage3DOES;
+#define glTexSubImage3DOES glad_glTexSubImage3DOES
+GLAD_API_CALL PFNGLTEXTURESTORAGE1DEXTPROC glad_glTextureStorage1DEXT;
+#define glTextureStorage1DEXT glad_glTextureStorage1DEXT
+GLAD_API_CALL PFNGLTEXTURESTORAGE2DEXTPROC glad_glTextureStorage2DEXT;
+#define glTextureStorage2DEXT glad_glTextureStorage2DEXT
+GLAD_API_CALL PFNGLTEXTURESTORAGE3DEXTPROC glad_glTextureStorage3DEXT;
+#define glTextureStorage3DEXT glad_glTextureStorage3DEXT
+GLAD_API_CALL PFNGLTEXTURESTORAGEMEM2DEXTPROC glad_glTextureStorageMem2DEXT;
+#define glTextureStorageMem2DEXT glad_glTextureStorageMem2DEXT
+GLAD_API_CALL PFNGLTEXTURESTORAGEMEM2DMULTISAMPLEEXTPROC glad_glTextureStorageMem2DMultisampleEXT;
+#define glTextureStorageMem2DMultisampleEXT glad_glTextureStorageMem2DMultisampleEXT
+GLAD_API_CALL PFNGLTEXTURESTORAGEMEM3DEXTPROC glad_glTextureStorageMem3DEXT;
+#define glTextureStorageMem3DEXT glad_glTextureStorageMem3DEXT
+GLAD_API_CALL PFNGLTEXTURESTORAGEMEM3DMULTISAMPLEEXTPROC glad_glTextureStorageMem3DMultisampleEXT;
+#define glTextureStorageMem3DMultisampleEXT glad_glTextureStorageMem3DMultisampleEXT
+GLAD_API_CALL PFNGLTEXTUREVIEWEXTPROC glad_glTextureViewEXT;
+#define glTextureViewEXT glad_glTextureViewEXT
+GLAD_API_CALL PFNGLTEXTUREVIEWOESPROC glad_glTextureViewOES;
+#define glTextureViewOES glad_glTextureViewOES
+GLAD_API_CALL PFNGLUNIFORM1FPROC glad_glUniform1f;
+#define glUniform1f glad_glUniform1f
+GLAD_API_CALL PFNGLUNIFORM1FVPROC glad_glUniform1fv;
+#define glUniform1fv glad_glUniform1fv
+GLAD_API_CALL PFNGLUNIFORM1IPROC glad_glUniform1i;
+#define glUniform1i glad_glUniform1i
+GLAD_API_CALL PFNGLUNIFORM1IVPROC glad_glUniform1iv;
+#define glUniform1iv glad_glUniform1iv
+GLAD_API_CALL PFNGLUNIFORM2FPROC glad_glUniform2f;
+#define glUniform2f glad_glUniform2f
+GLAD_API_CALL PFNGLUNIFORM2FVPROC glad_glUniform2fv;
+#define glUniform2fv glad_glUniform2fv
+GLAD_API_CALL PFNGLUNIFORM2IPROC glad_glUniform2i;
+#define glUniform2i glad_glUniform2i
+GLAD_API_CALL PFNGLUNIFORM2IVPROC glad_glUniform2iv;
+#define glUniform2iv glad_glUniform2iv
+GLAD_API_CALL PFNGLUNIFORM3FPROC glad_glUniform3f;
+#define glUniform3f glad_glUniform3f
+GLAD_API_CALL PFNGLUNIFORM3FVPROC glad_glUniform3fv;
+#define glUniform3fv glad_glUniform3fv
+GLAD_API_CALL PFNGLUNIFORM3IPROC glad_glUniform3i;
+#define glUniform3i glad_glUniform3i
+GLAD_API_CALL PFNGLUNIFORM3IVPROC glad_glUniform3iv;
+#define glUniform3iv glad_glUniform3iv
+GLAD_API_CALL PFNGLUNIFORM4FPROC glad_glUniform4f;
+#define glUniform4f glad_glUniform4f
+GLAD_API_CALL PFNGLUNIFORM4FVPROC glad_glUniform4fv;
+#define glUniform4fv glad_glUniform4fv
+GLAD_API_CALL PFNGLUNIFORM4IPROC glad_glUniform4i;
+#define glUniform4i glad_glUniform4i
+GLAD_API_CALL PFNGLUNIFORM4IVPROC glad_glUniform4iv;
+#define glUniform4iv glad_glUniform4iv
+GLAD_API_CALL PFNGLUNIFORMMATRIX2FVPROC glad_glUniformMatrix2fv;
+#define glUniformMatrix2fv glad_glUniformMatrix2fv
+GLAD_API_CALL PFNGLUNIFORMMATRIX3FVPROC glad_glUniformMatrix3fv;
+#define glUniformMatrix3fv glad_glUniformMatrix3fv
+GLAD_API_CALL PFNGLUNIFORMMATRIX4FVPROC glad_glUniformMatrix4fv;
+#define glUniformMatrix4fv glad_glUniformMatrix4fv
+GLAD_API_CALL PFNGLUNMAPBUFFEROESPROC glad_glUnmapBufferOES;
+#define glUnmapBufferOES glad_glUnmapBufferOES
+GLAD_API_CALL PFNGLUSEPROGRAMPROC glad_glUseProgram;
+#define glUseProgram glad_glUseProgram
+GLAD_API_CALL PFNGLUSEPROGRAMSTAGESEXTPROC glad_glUseProgramStagesEXT;
+#define glUseProgramStagesEXT glad_glUseProgramStagesEXT
+GLAD_API_CALL PFNGLVALIDATEPROGRAMPROC glad_glValidateProgram;
+#define glValidateProgram glad_glValidateProgram
+GLAD_API_CALL PFNGLVALIDATEPROGRAMPIPELINEEXTPROC glad_glValidateProgramPipelineEXT;
+#define glValidateProgramPipelineEXT glad_glValidateProgramPipelineEXT
+GLAD_API_CALL PFNGLVERTEXATTRIB1FPROC glad_glVertexAttrib1f;
+#define glVertexAttrib1f glad_glVertexAttrib1f
+GLAD_API_CALL PFNGLVERTEXATTRIB1FVPROC glad_glVertexAttrib1fv;
+#define glVertexAttrib1fv glad_glVertexAttrib1fv
+GLAD_API_CALL PFNGLVERTEXATTRIB2FPROC glad_glVertexAttrib2f;
+#define glVertexAttrib2f glad_glVertexAttrib2f
+GLAD_API_CALL PFNGLVERTEXATTRIB2FVPROC glad_glVertexAttrib2fv;
+#define glVertexAttrib2fv glad_glVertexAttrib2fv
+GLAD_API_CALL PFNGLVERTEXATTRIB3FPROC glad_glVertexAttrib3f;
+#define glVertexAttrib3f glad_glVertexAttrib3f
+GLAD_API_CALL PFNGLVERTEXATTRIB3FVPROC glad_glVertexAttrib3fv;
+#define glVertexAttrib3fv glad_glVertexAttrib3fv
+GLAD_API_CALL PFNGLVERTEXATTRIB4FPROC glad_glVertexAttrib4f;
+#define glVertexAttrib4f glad_glVertexAttrib4f
+GLAD_API_CALL PFNGLVERTEXATTRIB4FVPROC glad_glVertexAttrib4fv;
+#define glVertexAttrib4fv glad_glVertexAttrib4fv
+GLAD_API_CALL PFNGLVERTEXATTRIBDIVISOREXTPROC glad_glVertexAttribDivisorEXT;
+#define glVertexAttribDivisorEXT glad_glVertexAttribDivisorEXT
+GLAD_API_CALL PFNGLVERTEXATTRIBPOINTERPROC glad_glVertexAttribPointer;
+#define glVertexAttribPointer glad_glVertexAttribPointer
+GLAD_API_CALL PFNGLVIEWPORTPROC glad_glViewport;
+#define glViewport glad_glViewport
+GLAD_API_CALL PFNGLVIEWPORTARRAYVOESPROC glad_glViewportArrayvOES;
+#define glViewportArrayvOES glad_glViewportArrayvOES
+GLAD_API_CALL PFNGLVIEWPORTINDEXEDFOESPROC glad_glViewportIndexedfOES;
+#define glViewportIndexedfOES glad_glViewportIndexedfOES
+GLAD_API_CALL PFNGLVIEWPORTINDEXEDFVOESPROC glad_glViewportIndexedfvOES;
+#define glViewportIndexedfvOES glad_glViewportIndexedfvOES
+GLAD_API_CALL PFNGLWAITSEMAPHOREEXTPROC glad_glWaitSemaphoreEXT;
+#define glWaitSemaphoreEXT glad_glWaitSemaphoreEXT
+GLAD_API_CALL PFNGLWINDOWRECTANGLESEXTPROC glad_glWindowRectanglesEXT;
+#define glWindowRectanglesEXT glad_glWindowRectanglesEXT
+
+
+
+
+
+GLAD_API_CALL int gladLoadGLES2UserPtr( GLADuserptrloadfunc load, void *userptr);
+GLAD_API_CALL int gladLoadGLES2( GLADloadfunc load);
+
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+/* Source */
+#ifdef GLAD_GLES2_IMPLEMENTATION
+/**
+ * SPDX-License-Identifier: (WTFPL OR CC0-1.0) AND Apache-2.0
+ */
+#include
+#include
+#include
+
+#ifndef GLAD_IMPL_UTIL_C_
+#define GLAD_IMPL_UTIL_C_
+
+#ifdef _MSC_VER
+#define GLAD_IMPL_UTIL_SSCANF sscanf_s
+#else
+#define GLAD_IMPL_UTIL_SSCANF sscanf
+#endif
+
+#endif /* GLAD_IMPL_UTIL_C_ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+
+int GLAD_GL_ES_VERSION_2_0 = 0;
+int GLAD_GL_EXT_EGL_image_array = 0;
+int GLAD_GL_EXT_EGL_image_storage = 0;
+int GLAD_GL_EXT_EGL_image_storage_compression = 0;
+int GLAD_GL_EXT_YUV_target = 0;
+int GLAD_GL_EXT_base_instance = 0;
+int GLAD_GL_EXT_blend_func_extended = 0;
+int GLAD_GL_EXT_blend_minmax = 0;
+int GLAD_GL_EXT_buffer_storage = 0;
+int GLAD_GL_EXT_clear_texture = 0;
+int GLAD_GL_EXT_clip_control = 0;
+int GLAD_GL_EXT_clip_cull_distance = 0;
+int GLAD_GL_EXT_color_buffer_float = 0;
+int GLAD_GL_EXT_color_buffer_half_float = 0;
+int GLAD_GL_EXT_conservative_depth = 0;
+int GLAD_GL_EXT_copy_image = 0;
+int GLAD_GL_EXT_debug_label = 0;
+int GLAD_GL_EXT_debug_marker = 0;
+int GLAD_GL_EXT_depth_clamp = 0;
+int GLAD_GL_EXT_discard_framebuffer = 0;
+int GLAD_GL_EXT_disjoint_timer_query = 0;
+int GLAD_GL_EXT_draw_buffers = 0;
+int GLAD_GL_EXT_draw_buffers_indexed = 0;
+int GLAD_GL_EXT_draw_elements_base_vertex = 0;
+int GLAD_GL_EXT_draw_instanced = 0;
+int GLAD_GL_EXT_draw_transform_feedback = 0;
+int GLAD_GL_EXT_external_buffer = 0;
+int GLAD_GL_EXT_float_blend = 0;
+int GLAD_GL_EXT_fragment_shading_rate = 0;
+int GLAD_GL_EXT_geometry_point_size = 0;
+int GLAD_GL_EXT_geometry_shader = 0;
+int GLAD_GL_EXT_gpu_shader5 = 0;
+int GLAD_GL_EXT_instanced_arrays = 0;
+int GLAD_GL_EXT_map_buffer_range = 0;
+int GLAD_GL_EXT_memory_object = 0;
+int GLAD_GL_EXT_memory_object_fd = 0;
+int GLAD_GL_EXT_memory_object_win32 = 0;
+int GLAD_GL_EXT_multi_draw_arrays = 0;
+int GLAD_GL_EXT_multi_draw_indirect = 0;
+int GLAD_GL_EXT_multisampled_compatibility = 0;
+int GLAD_GL_EXT_multisampled_render_to_texture = 0;
+int GLAD_GL_EXT_multisampled_render_to_texture2 = 0;
+int GLAD_GL_EXT_multiview_draw_buffers = 0;
+int GLAD_GL_EXT_multiview_tessellation_geometry_shader = 0;
+int GLAD_GL_EXT_multiview_texture_multisample = 0;
+int GLAD_GL_EXT_multiview_timer_query = 0;
+int GLAD_GL_EXT_occlusion_query_boolean = 0;
+int GLAD_GL_EXT_polygon_offset_clamp = 0;
+int GLAD_GL_EXT_post_depth_coverage = 0;
+int GLAD_GL_EXT_primitive_bounding_box = 0;
+int GLAD_GL_EXT_protected_textures = 0;
+int GLAD_GL_EXT_pvrtc_sRGB = 0;
+int GLAD_GL_EXT_raster_multisample = 0;
+int GLAD_GL_EXT_read_format_bgra = 0;
+int GLAD_GL_EXT_render_snorm = 0;
+int GLAD_GL_EXT_robustness = 0;
+int GLAD_GL_EXT_sRGB = 0;
+int GLAD_GL_EXT_sRGB_write_control = 0;
+int GLAD_GL_EXT_semaphore = 0;
+int GLAD_GL_EXT_semaphore_fd = 0;
+int GLAD_GL_EXT_semaphore_win32 = 0;
+int GLAD_GL_EXT_separate_depth_stencil = 0;
+int GLAD_GL_EXT_separate_shader_objects = 0;
+int GLAD_GL_EXT_shader_framebuffer_fetch = 0;
+int GLAD_GL_EXT_shader_framebuffer_fetch_non_coherent = 0;
+int GLAD_GL_EXT_shader_group_vote = 0;
+int GLAD_GL_EXT_shader_implicit_conversions = 0;
+int GLAD_GL_EXT_shader_integer_mix = 0;
+int GLAD_GL_EXT_shader_io_blocks = 0;
+int GLAD_GL_EXT_shader_non_constant_global_initializers = 0;
+int GLAD_GL_EXT_shader_pixel_local_storage = 0;
+int GLAD_GL_EXT_shader_pixel_local_storage2 = 0;
+int GLAD_GL_EXT_shader_samples_identical = 0;
+int GLAD_GL_EXT_shader_texture_lod = 0;
+int GLAD_GL_EXT_shadow_samplers = 0;
+int GLAD_GL_EXT_sparse_texture = 0;
+int GLAD_GL_EXT_sparse_texture2 = 0;
+int GLAD_GL_EXT_tessellation_point_size = 0;
+int GLAD_GL_EXT_tessellation_shader = 0;
+int GLAD_GL_EXT_texture_border_clamp = 0;
+int GLAD_GL_EXT_texture_buffer = 0;
+int GLAD_GL_EXT_texture_compression_astc_decode_mode = 0;
+int GLAD_GL_EXT_texture_compression_bptc = 0;
+int GLAD_GL_EXT_texture_compression_dxt1 = 0;
+int GLAD_GL_EXT_texture_compression_rgtc = 0;
+int GLAD_GL_EXT_texture_compression_s3tc = 0;
+int GLAD_GL_EXT_texture_compression_s3tc_srgb = 0;
+int GLAD_GL_EXT_texture_cube_map_array = 0;
+int GLAD_GL_EXT_texture_filter_anisotropic = 0;
+int GLAD_GL_EXT_texture_filter_minmax = 0;
+int GLAD_GL_EXT_texture_format_BGRA8888 = 0;
+int GLAD_GL_EXT_texture_format_sRGB_override = 0;
+int GLAD_GL_EXT_texture_mirror_clamp_to_edge = 0;
+int GLAD_GL_EXT_texture_norm16 = 0;
+int GLAD_GL_EXT_texture_query_lod = 0;
+int GLAD_GL_EXT_texture_rg = 0;
+int GLAD_GL_EXT_texture_sRGB_R8 = 0;
+int GLAD_GL_EXT_texture_sRGB_RG8 = 0;
+int GLAD_GL_EXT_texture_sRGB_decode = 0;
+int GLAD_GL_EXT_texture_shadow_lod = 0;
+int GLAD_GL_EXT_texture_storage = 0;
+int GLAD_GL_EXT_texture_storage_compression = 0;
+int GLAD_GL_EXT_texture_type_2_10_10_10_REV = 0;
+int GLAD_GL_EXT_texture_view = 0;
+int GLAD_GL_EXT_unpack_subimage = 0;
+int GLAD_GL_EXT_win32_keyed_mutex = 0;
+int GLAD_GL_EXT_window_rectangles = 0;
+int GLAD_GL_KHR_blend_equation_advanced = 0;
+int GLAD_GL_KHR_blend_equation_advanced_coherent = 0;
+int GLAD_GL_KHR_context_flush_control = 0;
+int GLAD_GL_KHR_debug = 0;
+int GLAD_GL_KHR_no_error = 0;
+int GLAD_GL_KHR_parallel_shader_compile = 0;
+int GLAD_GL_KHR_robust_buffer_access_behavior = 0;
+int GLAD_GL_KHR_robustness = 0;
+int GLAD_GL_KHR_shader_subgroup = 0;
+int GLAD_GL_KHR_texture_compression_astc_hdr = 0;
+int GLAD_GL_KHR_texture_compression_astc_ldr = 0;
+int GLAD_GL_KHR_texture_compression_astc_sliced_3d = 0;
+int GLAD_GL_OES_EGL_image = 0;
+int GLAD_GL_OES_EGL_image_external = 0;
+int GLAD_GL_OES_EGL_image_external_essl3 = 0;
+int GLAD_GL_OES_compressed_ETC1_RGB8_sub_texture = 0;
+int GLAD_GL_OES_compressed_ETC1_RGB8_texture = 0;
+int GLAD_GL_OES_compressed_paletted_texture = 0;
+int GLAD_GL_OES_copy_image = 0;
+int GLAD_GL_OES_depth24 = 0;
+int GLAD_GL_OES_depth32 = 0;
+int GLAD_GL_OES_depth_texture = 0;
+int GLAD_GL_OES_draw_buffers_indexed = 0;
+int GLAD_GL_OES_draw_elements_base_vertex = 0;
+int GLAD_GL_OES_element_index_uint = 0;
+int GLAD_GL_OES_fbo_render_mipmap = 0;
+int GLAD_GL_OES_fragment_precision_high = 0;
+int GLAD_GL_OES_geometry_point_size = 0;
+int GLAD_GL_OES_geometry_shader = 0;
+int GLAD_GL_OES_get_program_binary = 0;
+int GLAD_GL_OES_gpu_shader5 = 0;
+int GLAD_GL_OES_mapbuffer = 0;
+int GLAD_GL_OES_packed_depth_stencil = 0;
+int GLAD_GL_OES_primitive_bounding_box = 0;
+int GLAD_GL_OES_required_internalformat = 0;
+int GLAD_GL_OES_rgb8_rgba8 = 0;
+int GLAD_GL_OES_sample_shading = 0;
+int GLAD_GL_OES_sample_variables = 0;
+int GLAD_GL_OES_shader_image_atomic = 0;
+int GLAD_GL_OES_shader_io_blocks = 0;
+int GLAD_GL_OES_shader_multisample_interpolation = 0;
+int GLAD_GL_OES_standard_derivatives = 0;
+int GLAD_GL_OES_stencil1 = 0;
+int GLAD_GL_OES_stencil4 = 0;
+int GLAD_GL_OES_surfaceless_context = 0;
+int GLAD_GL_OES_tessellation_point_size = 0;
+int GLAD_GL_OES_tessellation_shader = 0;
+int GLAD_GL_OES_texture_3D = 0;
+int GLAD_GL_OES_texture_border_clamp = 0;
+int GLAD_GL_OES_texture_buffer = 0;
+int GLAD_GL_OES_texture_compression_astc = 0;
+int GLAD_GL_OES_texture_cube_map_array = 0;
+int GLAD_GL_OES_texture_float = 0;
+int GLAD_GL_OES_texture_float_linear = 0;
+int GLAD_GL_OES_texture_half_float = 0;
+int GLAD_GL_OES_texture_half_float_linear = 0;
+int GLAD_GL_OES_texture_npot = 0;
+int GLAD_GL_OES_texture_stencil8 = 0;
+int GLAD_GL_OES_texture_storage_multisample_2d_array = 0;
+int GLAD_GL_OES_texture_view = 0;
+int GLAD_GL_OES_vertex_array_object = 0;
+int GLAD_GL_OES_vertex_half_float = 0;
+int GLAD_GL_OES_vertex_type_10_10_10_2 = 0;
+int GLAD_GL_OES_viewport_array = 0;
+
+
+
+PFNGLACQUIREKEYEDMUTEXWIN32EXTPROC glad_glAcquireKeyedMutexWin32EXT = NULL;
+PFNGLACTIVESHADERPROGRAMEXTPROC glad_glActiveShaderProgramEXT = NULL;
+PFNGLACTIVETEXTUREPROC glad_glActiveTexture = NULL;
+PFNGLATTACHSHADERPROC glad_glAttachShader = NULL;
+PFNGLBEGINQUERYEXTPROC glad_glBeginQueryEXT = NULL;
+PFNGLBINDATTRIBLOCATIONPROC glad_glBindAttribLocation = NULL;
+PFNGLBINDBUFFERPROC glad_glBindBuffer = NULL;
+PFNGLBINDFRAGDATALOCATIONEXTPROC glad_glBindFragDataLocationEXT = NULL;
+PFNGLBINDFRAGDATALOCATIONINDEXEDEXTPROC glad_glBindFragDataLocationIndexedEXT = NULL;
+PFNGLBINDFRAMEBUFFERPROC glad_glBindFramebuffer = NULL;
+PFNGLBINDPROGRAMPIPELINEEXTPROC glad_glBindProgramPipelineEXT = NULL;
+PFNGLBINDRENDERBUFFERPROC glad_glBindRenderbuffer = NULL;
+PFNGLBINDTEXTUREPROC glad_glBindTexture = NULL;
+PFNGLBINDVERTEXARRAYOESPROC glad_glBindVertexArrayOES = NULL;
+PFNGLBLENDBARRIERKHRPROC glad_glBlendBarrierKHR = NULL;
+PFNGLBLENDCOLORPROC glad_glBlendColor = NULL;
+PFNGLBLENDEQUATIONPROC glad_glBlendEquation = NULL;
+PFNGLBLENDEQUATIONSEPARATEPROC glad_glBlendEquationSeparate = NULL;
+PFNGLBLENDEQUATIONSEPARATEIEXTPROC glad_glBlendEquationSeparateiEXT = NULL;
+PFNGLBLENDEQUATIONSEPARATEIOESPROC glad_glBlendEquationSeparateiOES = NULL;
+PFNGLBLENDEQUATIONIEXTPROC glad_glBlendEquationiEXT = NULL;
+PFNGLBLENDEQUATIONIOESPROC glad_glBlendEquationiOES = NULL;
+PFNGLBLENDFUNCPROC glad_glBlendFunc = NULL;
+PFNGLBLENDFUNCSEPARATEPROC glad_glBlendFuncSeparate = NULL;
+PFNGLBLENDFUNCSEPARATEIEXTPROC glad_glBlendFuncSeparateiEXT = NULL;
+PFNGLBLENDFUNCSEPARATEIOESPROC glad_glBlendFuncSeparateiOES = NULL;
+PFNGLBLENDFUNCIEXTPROC glad_glBlendFunciEXT = NULL;
+PFNGLBLENDFUNCIOESPROC glad_glBlendFunciOES = NULL;
+PFNGLBUFFERDATAPROC glad_glBufferData = NULL;
+PFNGLBUFFERSTORAGEEXTPROC glad_glBufferStorageEXT = NULL;
+PFNGLBUFFERSTORAGEEXTERNALEXTPROC glad_glBufferStorageExternalEXT = NULL;
+PFNGLBUFFERSTORAGEMEMEXTPROC glad_glBufferStorageMemEXT = NULL;
+PFNGLBUFFERSUBDATAPROC glad_glBufferSubData = NULL;
+PFNGLCHECKFRAMEBUFFERSTATUSPROC glad_glCheckFramebufferStatus = NULL;
+PFNGLCLEARPROC glad_glClear = NULL;
+PFNGLCLEARCOLORPROC glad_glClearColor = NULL;
+PFNGLCLEARDEPTHFPROC glad_glClearDepthf = NULL;
+PFNGLCLEARPIXELLOCALSTORAGEUIEXTPROC glad_glClearPixelLocalStorageuiEXT = NULL;
+PFNGLCLEARSTENCILPROC glad_glClearStencil = NULL;
+PFNGLCLEARTEXIMAGEEXTPROC glad_glClearTexImageEXT = NULL;
+PFNGLCLEARTEXSUBIMAGEEXTPROC glad_glClearTexSubImageEXT = NULL;
+PFNGLCLIPCONTROLEXTPROC glad_glClipControlEXT = NULL;
+PFNGLCOLORMASKPROC glad_glColorMask = NULL;
+PFNGLCOLORMASKIEXTPROC glad_glColorMaskiEXT = NULL;
+PFNGLCOLORMASKIOESPROC glad_glColorMaskiOES = NULL;
+PFNGLCOMPILESHADERPROC glad_glCompileShader = NULL;
+PFNGLCOMPRESSEDTEXIMAGE2DPROC glad_glCompressedTexImage2D = NULL;
+PFNGLCOMPRESSEDTEXIMAGE3DOESPROC glad_glCompressedTexImage3DOES = NULL;
+PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC glad_glCompressedTexSubImage2D = NULL;
+PFNGLCOMPRESSEDTEXSUBIMAGE3DOESPROC glad_glCompressedTexSubImage3DOES = NULL;
+PFNGLCOPYIMAGESUBDATAEXTPROC glad_glCopyImageSubDataEXT = NULL;
+PFNGLCOPYIMAGESUBDATAOESPROC glad_glCopyImageSubDataOES = NULL;
+PFNGLCOPYTEXIMAGE2DPROC glad_glCopyTexImage2D = NULL;
+PFNGLCOPYTEXSUBIMAGE2DPROC glad_glCopyTexSubImage2D = NULL;
+PFNGLCOPYTEXSUBIMAGE3DOESPROC glad_glCopyTexSubImage3DOES = NULL;
+PFNGLCREATEMEMORYOBJECTSEXTPROC glad_glCreateMemoryObjectsEXT = NULL;
+PFNGLCREATEPROGRAMPROC glad_glCreateProgram = NULL;
+PFNGLCREATESHADERPROC glad_glCreateShader = NULL;
+PFNGLCREATESHADERPROGRAMVEXTPROC glad_glCreateShaderProgramvEXT = NULL;
+PFNGLCULLFACEPROC glad_glCullFace = NULL;
+PFNGLDEBUGMESSAGECALLBACKKHRPROC glad_glDebugMessageCallbackKHR = NULL;
+PFNGLDEBUGMESSAGECONTROLKHRPROC glad_glDebugMessageControlKHR = NULL;
+PFNGLDEBUGMESSAGEINSERTKHRPROC glad_glDebugMessageInsertKHR = NULL;
+PFNGLDELETEBUFFERSPROC glad_glDeleteBuffers = NULL;
+PFNGLDELETEFRAMEBUFFERSPROC glad_glDeleteFramebuffers = NULL;
+PFNGLDELETEMEMORYOBJECTSEXTPROC glad_glDeleteMemoryObjectsEXT = NULL;
+PFNGLDELETEPROGRAMPROC glad_glDeleteProgram = NULL;
+PFNGLDELETEPROGRAMPIPELINESEXTPROC glad_glDeleteProgramPipelinesEXT = NULL;
+PFNGLDELETEQUERIESEXTPROC glad_glDeleteQueriesEXT = NULL;
+PFNGLDELETERENDERBUFFERSPROC glad_glDeleteRenderbuffers = NULL;
+PFNGLDELETESEMAPHORESEXTPROC glad_glDeleteSemaphoresEXT = NULL;
+PFNGLDELETESHADERPROC glad_glDeleteShader = NULL;
+PFNGLDELETETEXTURESPROC glad_glDeleteTextures = NULL;
+PFNGLDELETEVERTEXARRAYSOESPROC glad_glDeleteVertexArraysOES = NULL;
+PFNGLDEPTHFUNCPROC glad_glDepthFunc = NULL;
+PFNGLDEPTHMASKPROC glad_glDepthMask = NULL;
+PFNGLDEPTHRANGEARRAYFVOESPROC glad_glDepthRangeArrayfvOES = NULL;
+PFNGLDEPTHRANGEINDEXEDFOESPROC glad_glDepthRangeIndexedfOES = NULL;
+PFNGLDEPTHRANGEFPROC glad_glDepthRangef = NULL;
+PFNGLDETACHSHADERPROC glad_glDetachShader = NULL;
+PFNGLDISABLEPROC glad_glDisable = NULL;
+PFNGLDISABLEVERTEXATTRIBARRAYPROC glad_glDisableVertexAttribArray = NULL;
+PFNGLDISABLEIEXTPROC glad_glDisableiEXT = NULL;
+PFNGLDISABLEIOESPROC glad_glDisableiOES = NULL;
+PFNGLDISCARDFRAMEBUFFEREXTPROC glad_glDiscardFramebufferEXT = NULL;
+PFNGLDRAWARRAYSPROC glad_glDrawArrays = NULL;
+PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEEXTPROC glad_glDrawArraysInstancedBaseInstanceEXT = NULL;
+PFNGLDRAWARRAYSINSTANCEDEXTPROC glad_glDrawArraysInstancedEXT = NULL;
+PFNGLDRAWBUFFERSEXTPROC glad_glDrawBuffersEXT = NULL;
+PFNGLDRAWBUFFERSINDEXEDEXTPROC glad_glDrawBuffersIndexedEXT = NULL;
+PFNGLDRAWELEMENTSPROC glad_glDrawElements = NULL;
+PFNGLDRAWELEMENTSBASEVERTEXEXTPROC glad_glDrawElementsBaseVertexEXT = NULL;
+PFNGLDRAWELEMENTSBASEVERTEXOESPROC glad_glDrawElementsBaseVertexOES = NULL;
+PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEEXTPROC glad_glDrawElementsInstancedBaseInstanceEXT = NULL;
+PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEEXTPROC glad_glDrawElementsInstancedBaseVertexBaseInstanceEXT = NULL;
+PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXEXTPROC glad_glDrawElementsInstancedBaseVertexEXT = NULL;
+PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXOESPROC glad_glDrawElementsInstancedBaseVertexOES = NULL;
+PFNGLDRAWELEMENTSINSTANCEDEXTPROC glad_glDrawElementsInstancedEXT = NULL;
+PFNGLDRAWRANGEELEMENTSBASEVERTEXEXTPROC glad_glDrawRangeElementsBaseVertexEXT = NULL;
+PFNGLDRAWRANGEELEMENTSBASEVERTEXOESPROC glad_glDrawRangeElementsBaseVertexOES = NULL;
+PFNGLDRAWTRANSFORMFEEDBACKEXTPROC glad_glDrawTransformFeedbackEXT = NULL;
+PFNGLDRAWTRANSFORMFEEDBACKINSTANCEDEXTPROC glad_glDrawTransformFeedbackInstancedEXT = NULL;
+PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC glad_glEGLImageTargetRenderbufferStorageOES = NULL;
+PFNGLEGLIMAGETARGETTEXSTORAGEEXTPROC glad_glEGLImageTargetTexStorageEXT = NULL;
+PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glad_glEGLImageTargetTexture2DOES = NULL;
+PFNGLEGLIMAGETARGETTEXTURESTORAGEEXTPROC glad_glEGLImageTargetTextureStorageEXT = NULL;
+PFNGLENABLEPROC glad_glEnable = NULL;
+PFNGLENABLEVERTEXATTRIBARRAYPROC glad_glEnableVertexAttribArray = NULL;
+PFNGLENABLEIEXTPROC glad_glEnableiEXT = NULL;
+PFNGLENABLEIOESPROC glad_glEnableiOES = NULL;
+PFNGLENDQUERYEXTPROC glad_glEndQueryEXT = NULL;
+PFNGLFINISHPROC glad_glFinish = NULL;
+PFNGLFLUSHPROC glad_glFlush = NULL;
+PFNGLFLUSHMAPPEDBUFFERRANGEEXTPROC glad_glFlushMappedBufferRangeEXT = NULL;
+PFNGLFRAMEBUFFERFETCHBARRIEREXTPROC glad_glFramebufferFetchBarrierEXT = NULL;
+PFNGLFRAMEBUFFERPIXELLOCALSTORAGESIZEEXTPROC glad_glFramebufferPixelLocalStorageSizeEXT = NULL;
+PFNGLFRAMEBUFFERRENDERBUFFERPROC glad_glFramebufferRenderbuffer = NULL;
+PFNGLFRAMEBUFFERSHADINGRATEEXTPROC glad_glFramebufferShadingRateEXT = NULL;
+PFNGLFRAMEBUFFERTEXTURE2DPROC glad_glFramebufferTexture2D = NULL;
+PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC glad_glFramebufferTexture2DMultisampleEXT = NULL;
+PFNGLFRAMEBUFFERTEXTURE3DOESPROC glad_glFramebufferTexture3DOES = NULL;
+PFNGLFRAMEBUFFERTEXTUREEXTPROC glad_glFramebufferTextureEXT = NULL;
+PFNGLFRAMEBUFFERTEXTUREOESPROC glad_glFramebufferTextureOES = NULL;
+PFNGLFRONTFACEPROC glad_glFrontFace = NULL;
+PFNGLGENBUFFERSPROC glad_glGenBuffers = NULL;
+PFNGLGENFRAMEBUFFERSPROC glad_glGenFramebuffers = NULL;
+PFNGLGENPROGRAMPIPELINESEXTPROC glad_glGenProgramPipelinesEXT = NULL;
+PFNGLGENQUERIESEXTPROC glad_glGenQueriesEXT = NULL;
+PFNGLGENRENDERBUFFERSPROC glad_glGenRenderbuffers = NULL;
+PFNGLGENSEMAPHORESEXTPROC glad_glGenSemaphoresEXT = NULL;
+PFNGLGENTEXTURESPROC glad_glGenTextures = NULL;
+PFNGLGENVERTEXARRAYSOESPROC glad_glGenVertexArraysOES = NULL;
+PFNGLGENERATEMIPMAPPROC glad_glGenerateMipmap = NULL;
+PFNGLGETACTIVEATTRIBPROC glad_glGetActiveAttrib = NULL;
+PFNGLGETACTIVEUNIFORMPROC glad_glGetActiveUniform = NULL;
+PFNGLGETATTACHEDSHADERSPROC glad_glGetAttachedShaders = NULL;
+PFNGLGETATTRIBLOCATIONPROC glad_glGetAttribLocation = NULL;
+PFNGLGETBOOLEANVPROC glad_glGetBooleanv = NULL;
+PFNGLGETBUFFERPARAMETERIVPROC glad_glGetBufferParameteriv = NULL;
+PFNGLGETBUFFERPOINTERVOESPROC glad_glGetBufferPointervOES = NULL;
+PFNGLGETDEBUGMESSAGELOGKHRPROC glad_glGetDebugMessageLogKHR = NULL;
+PFNGLGETERRORPROC glad_glGetError = NULL;
+PFNGLGETFLOATI_VOESPROC glad_glGetFloati_vOES = NULL;
+PFNGLGETFLOATVPROC glad_glGetFloatv = NULL;
+PFNGLGETFRAGDATAINDEXEXTPROC glad_glGetFragDataIndexEXT = NULL;
+PFNGLGETFRAGMENTSHADINGRATESEXTPROC glad_glGetFragmentShadingRatesEXT = NULL;
+PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glad_glGetFramebufferAttachmentParameteriv = NULL;
+PFNGLGETFRAMEBUFFERPIXELLOCALSTORAGESIZEEXTPROC glad_glGetFramebufferPixelLocalStorageSizeEXT = NULL;
+PFNGLGETGRAPHICSRESETSTATUSEXTPROC glad_glGetGraphicsResetStatusEXT = NULL;
+PFNGLGETGRAPHICSRESETSTATUSKHRPROC glad_glGetGraphicsResetStatusKHR = NULL;
+PFNGLGETINTEGER64VEXTPROC glad_glGetInteger64vEXT = NULL;
+PFNGLGETINTEGERI_VEXTPROC glad_glGetIntegeri_vEXT = NULL;
+PFNGLGETINTEGERVPROC glad_glGetIntegerv = NULL;
+PFNGLGETMEMORYOBJECTPARAMETERIVEXTPROC glad_glGetMemoryObjectParameterivEXT = NULL;
+PFNGLGETOBJECTLABELEXTPROC glad_glGetObjectLabelEXT = NULL;
+PFNGLGETOBJECTLABELKHRPROC glad_glGetObjectLabelKHR = NULL;
+PFNGLGETOBJECTPTRLABELKHRPROC glad_glGetObjectPtrLabelKHR = NULL;
+PFNGLGETPOINTERVKHRPROC glad_glGetPointervKHR = NULL;
+PFNGLGETPROGRAMBINARYOESPROC glad_glGetProgramBinaryOES = NULL;
+PFNGLGETPROGRAMINFOLOGPROC glad_glGetProgramInfoLog = NULL;
+PFNGLGETPROGRAMPIPELINEINFOLOGEXTPROC glad_glGetProgramPipelineInfoLogEXT = NULL;
+PFNGLGETPROGRAMPIPELINEIVEXTPROC glad_glGetProgramPipelineivEXT = NULL;
+PFNGLGETPROGRAMRESOURCELOCATIONINDEXEXTPROC glad_glGetProgramResourceLocationIndexEXT = NULL;
+PFNGLGETPROGRAMIVPROC glad_glGetProgramiv = NULL;
+PFNGLGETQUERYOBJECTI64VEXTPROC glad_glGetQueryObjecti64vEXT = NULL;
+PFNGLGETQUERYOBJECTIVEXTPROC glad_glGetQueryObjectivEXT = NULL;
+PFNGLGETQUERYOBJECTUI64VEXTPROC glad_glGetQueryObjectui64vEXT = NULL;
+PFNGLGETQUERYOBJECTUIVEXTPROC glad_glGetQueryObjectuivEXT = NULL;
+PFNGLGETQUERYIVEXTPROC glad_glGetQueryivEXT = NULL;
+PFNGLGETRENDERBUFFERPARAMETERIVPROC glad_glGetRenderbufferParameteriv = NULL;
+PFNGLGETSAMPLERPARAMETERIIVEXTPROC glad_glGetSamplerParameterIivEXT = NULL;
+PFNGLGETSAMPLERPARAMETERIIVOESPROC glad_glGetSamplerParameterIivOES = NULL;
+PFNGLGETSAMPLERPARAMETERIUIVEXTPROC glad_glGetSamplerParameterIuivEXT = NULL;
+PFNGLGETSAMPLERPARAMETERIUIVOESPROC glad_glGetSamplerParameterIuivOES = NULL;
+PFNGLGETSEMAPHOREPARAMETERUI64VEXTPROC glad_glGetSemaphoreParameterui64vEXT = NULL;
+PFNGLGETSHADERINFOLOGPROC glad_glGetShaderInfoLog = NULL;
+PFNGLGETSHADERPRECISIONFORMATPROC glad_glGetShaderPrecisionFormat = NULL;
+PFNGLGETSHADERSOURCEPROC glad_glGetShaderSource = NULL;
+PFNGLGETSHADERIVPROC glad_glGetShaderiv = NULL;
+PFNGLGETSTRINGPROC glad_glGetString = NULL;
+PFNGLGETTEXPARAMETERIIVEXTPROC glad_glGetTexParameterIivEXT = NULL;
+PFNGLGETTEXPARAMETERIIVOESPROC glad_glGetTexParameterIivOES = NULL;
+PFNGLGETTEXPARAMETERIUIVEXTPROC glad_glGetTexParameterIuivEXT = NULL;
+PFNGLGETTEXPARAMETERIUIVOESPROC glad_glGetTexParameterIuivOES = NULL;
+PFNGLGETTEXPARAMETERFVPROC glad_glGetTexParameterfv = NULL;
+PFNGLGETTEXPARAMETERIVPROC glad_glGetTexParameteriv = NULL;
+PFNGLGETUNIFORMLOCATIONPROC glad_glGetUniformLocation = NULL;
+PFNGLGETUNIFORMFVPROC glad_glGetUniformfv = NULL;
+PFNGLGETUNIFORMIVPROC glad_glGetUniformiv = NULL;
+PFNGLGETUNSIGNEDBYTEI_VEXTPROC glad_glGetUnsignedBytei_vEXT = NULL;
+PFNGLGETUNSIGNEDBYTEVEXTPROC glad_glGetUnsignedBytevEXT = NULL;
+PFNGLGETVERTEXATTRIBPOINTERVPROC glad_glGetVertexAttribPointerv = NULL;
+PFNGLGETVERTEXATTRIBFVPROC glad_glGetVertexAttribfv = NULL;
+PFNGLGETVERTEXATTRIBIVPROC glad_glGetVertexAttribiv = NULL;
+PFNGLGETNUNIFORMFVEXTPROC glad_glGetnUniformfvEXT = NULL;
+PFNGLGETNUNIFORMFVKHRPROC glad_glGetnUniformfvKHR = NULL;
+PFNGLGETNUNIFORMIVEXTPROC glad_glGetnUniformivEXT = NULL;
+PFNGLGETNUNIFORMIVKHRPROC glad_glGetnUniformivKHR = NULL;
+PFNGLGETNUNIFORMUIVKHRPROC glad_glGetnUniformuivKHR = NULL;
+PFNGLHINTPROC glad_glHint = NULL;
+PFNGLIMPORTMEMORYFDEXTPROC glad_glImportMemoryFdEXT = NULL;
+PFNGLIMPORTMEMORYWIN32HANDLEEXTPROC glad_glImportMemoryWin32HandleEXT = NULL;
+PFNGLIMPORTMEMORYWIN32NAMEEXTPROC glad_glImportMemoryWin32NameEXT = NULL;
+PFNGLIMPORTSEMAPHOREFDEXTPROC glad_glImportSemaphoreFdEXT = NULL;
+PFNGLIMPORTSEMAPHOREWIN32HANDLEEXTPROC glad_glImportSemaphoreWin32HandleEXT = NULL;
+PFNGLIMPORTSEMAPHOREWIN32NAMEEXTPROC glad_glImportSemaphoreWin32NameEXT = NULL;
+PFNGLINSERTEVENTMARKEREXTPROC glad_glInsertEventMarkerEXT = NULL;
+PFNGLISBUFFERPROC glad_glIsBuffer = NULL;
+PFNGLISENABLEDPROC glad_glIsEnabled = NULL;
+PFNGLISENABLEDIEXTPROC glad_glIsEnablediEXT = NULL;
+PFNGLISENABLEDIOESPROC glad_glIsEnablediOES = NULL;
+PFNGLISFRAMEBUFFERPROC glad_glIsFramebuffer = NULL;
+PFNGLISMEMORYOBJECTEXTPROC glad_glIsMemoryObjectEXT = NULL;
+PFNGLISPROGRAMPROC glad_glIsProgram = NULL;
+PFNGLISPROGRAMPIPELINEEXTPROC glad_glIsProgramPipelineEXT = NULL;
+PFNGLISQUERYEXTPROC glad_glIsQueryEXT = NULL;
+PFNGLISRENDERBUFFERPROC glad_glIsRenderbuffer = NULL;
+PFNGLISSEMAPHOREEXTPROC glad_glIsSemaphoreEXT = NULL;
+PFNGLISSHADERPROC glad_glIsShader = NULL;
+PFNGLISTEXTUREPROC glad_glIsTexture = NULL;
+PFNGLISVERTEXARRAYOESPROC glad_glIsVertexArrayOES = NULL;
+PFNGLLABELOBJECTEXTPROC glad_glLabelObjectEXT = NULL;
+PFNGLLINEWIDTHPROC glad_glLineWidth = NULL;
+PFNGLLINKPROGRAMPROC glad_glLinkProgram = NULL;
+PFNGLMAPBUFFEROESPROC glad_glMapBufferOES = NULL;
+PFNGLMAPBUFFERRANGEEXTPROC glad_glMapBufferRangeEXT = NULL;
+PFNGLMAXSHADERCOMPILERTHREADSKHRPROC glad_glMaxShaderCompilerThreadsKHR = NULL;
+PFNGLMEMORYOBJECTPARAMETERIVEXTPROC glad_glMemoryObjectParameterivEXT = NULL;
+PFNGLMINSAMPLESHADINGOESPROC glad_glMinSampleShadingOES = NULL;
+PFNGLMULTIDRAWARRAYSEXTPROC glad_glMultiDrawArraysEXT = NULL;
+PFNGLMULTIDRAWARRAYSINDIRECTEXTPROC glad_glMultiDrawArraysIndirectEXT = NULL;
+PFNGLMULTIDRAWELEMENTSBASEVERTEXEXTPROC glad_glMultiDrawElementsBaseVertexEXT = NULL;
+PFNGLMULTIDRAWELEMENTSEXTPROC glad_glMultiDrawElementsEXT = NULL;
+PFNGLMULTIDRAWELEMENTSINDIRECTEXTPROC glad_glMultiDrawElementsIndirectEXT = NULL;
+PFNGLNAMEDBUFFERSTORAGEEXTERNALEXTPROC glad_glNamedBufferStorageExternalEXT = NULL;
+PFNGLNAMEDBUFFERSTORAGEMEMEXTPROC glad_glNamedBufferStorageMemEXT = NULL;
+PFNGLOBJECTLABELKHRPROC glad_glObjectLabelKHR = NULL;
+PFNGLOBJECTPTRLABELKHRPROC glad_glObjectPtrLabelKHR = NULL;
+PFNGLPATCHPARAMETERIEXTPROC glad_glPatchParameteriEXT = NULL;
+PFNGLPATCHPARAMETERIOESPROC glad_glPatchParameteriOES = NULL;
+PFNGLPIXELSTOREIPROC glad_glPixelStorei = NULL;
+PFNGLPOLYGONOFFSETPROC glad_glPolygonOffset = NULL;
+PFNGLPOLYGONOFFSETCLAMPEXTPROC glad_glPolygonOffsetClampEXT = NULL;
+PFNGLPOPDEBUGGROUPKHRPROC glad_glPopDebugGroupKHR = NULL;
+PFNGLPOPGROUPMARKEREXTPROC glad_glPopGroupMarkerEXT = NULL;
+PFNGLPRIMITIVEBOUNDINGBOXEXTPROC glad_glPrimitiveBoundingBoxEXT = NULL;
+PFNGLPRIMITIVEBOUNDINGBOXOESPROC glad_glPrimitiveBoundingBoxOES = NULL;
+PFNGLPROGRAMBINARYOESPROC glad_glProgramBinaryOES = NULL;
+PFNGLPROGRAMPARAMETERIEXTPROC glad_glProgramParameteriEXT = NULL;
+PFNGLPROGRAMUNIFORM1FEXTPROC glad_glProgramUniform1fEXT = NULL;
+PFNGLPROGRAMUNIFORM1FVEXTPROC glad_glProgramUniform1fvEXT = NULL;
+PFNGLPROGRAMUNIFORM1IEXTPROC glad_glProgramUniform1iEXT = NULL;
+PFNGLPROGRAMUNIFORM1IVEXTPROC glad_glProgramUniform1ivEXT = NULL;
+PFNGLPROGRAMUNIFORM1UIEXTPROC glad_glProgramUniform1uiEXT = NULL;
+PFNGLPROGRAMUNIFORM1UIVEXTPROC glad_glProgramUniform1uivEXT = NULL;
+PFNGLPROGRAMUNIFORM2FEXTPROC glad_glProgramUniform2fEXT = NULL;
+PFNGLPROGRAMUNIFORM2FVEXTPROC glad_glProgramUniform2fvEXT = NULL;
+PFNGLPROGRAMUNIFORM2IEXTPROC glad_glProgramUniform2iEXT = NULL;
+PFNGLPROGRAMUNIFORM2IVEXTPROC glad_glProgramUniform2ivEXT = NULL;
+PFNGLPROGRAMUNIFORM2UIEXTPROC glad_glProgramUniform2uiEXT = NULL;
+PFNGLPROGRAMUNIFORM2UIVEXTPROC glad_glProgramUniform2uivEXT = NULL;
+PFNGLPROGRAMUNIFORM3FEXTPROC glad_glProgramUniform3fEXT = NULL;
+PFNGLPROGRAMUNIFORM3FVEXTPROC glad_glProgramUniform3fvEXT = NULL;
+PFNGLPROGRAMUNIFORM3IEXTPROC glad_glProgramUniform3iEXT = NULL;
+PFNGLPROGRAMUNIFORM3IVEXTPROC glad_glProgramUniform3ivEXT = NULL;
+PFNGLPROGRAMUNIFORM3UIEXTPROC glad_glProgramUniform3uiEXT = NULL;
+PFNGLPROGRAMUNIFORM3UIVEXTPROC glad_glProgramUniform3uivEXT = NULL;
+PFNGLPROGRAMUNIFORM4FEXTPROC glad_glProgramUniform4fEXT = NULL;
+PFNGLPROGRAMUNIFORM4FVEXTPROC glad_glProgramUniform4fvEXT = NULL;
+PFNGLPROGRAMUNIFORM4IEXTPROC glad_glProgramUniform4iEXT = NULL;
+PFNGLPROGRAMUNIFORM4IVEXTPROC glad_glProgramUniform4ivEXT = NULL;
+PFNGLPROGRAMUNIFORM4UIEXTPROC glad_glProgramUniform4uiEXT = NULL;
+PFNGLPROGRAMUNIFORM4UIVEXTPROC glad_glProgramUniform4uivEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC glad_glProgramUniformMatrix2fvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC glad_glProgramUniformMatrix2x3fvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC glad_glProgramUniformMatrix2x4fvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC glad_glProgramUniformMatrix3fvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC glad_glProgramUniformMatrix3x2fvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC glad_glProgramUniformMatrix3x4fvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC glad_glProgramUniformMatrix4fvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC glad_glProgramUniformMatrix4x2fvEXT = NULL;
+PFNGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC glad_glProgramUniformMatrix4x3fvEXT = NULL;
+PFNGLPUSHDEBUGGROUPKHRPROC glad_glPushDebugGroupKHR = NULL;
+PFNGLPUSHGROUPMARKEREXTPROC glad_glPushGroupMarkerEXT = NULL;
+PFNGLQUERYCOUNTEREXTPROC glad_glQueryCounterEXT = NULL;
+PFNGLRASTERSAMPLESEXTPROC glad_glRasterSamplesEXT = NULL;
+PFNGLREADBUFFERINDEXEDEXTPROC glad_glReadBufferIndexedEXT = NULL;
+PFNGLREADPIXELSPROC glad_glReadPixels = NULL;
+PFNGLREADNPIXELSEXTPROC glad_glReadnPixelsEXT = NULL;
+PFNGLREADNPIXELSKHRPROC glad_glReadnPixelsKHR = NULL;
+PFNGLRELEASEKEYEDMUTEXWIN32EXTPROC glad_glReleaseKeyedMutexWin32EXT = NULL;
+PFNGLRELEASESHADERCOMPILERPROC glad_glReleaseShaderCompiler = NULL;
+PFNGLRENDERBUFFERSTORAGEPROC glad_glRenderbufferStorage = NULL;
+PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glad_glRenderbufferStorageMultisampleEXT = NULL;
+PFNGLSAMPLECOVERAGEPROC glad_glSampleCoverage = NULL;
+PFNGLSAMPLERPARAMETERIIVEXTPROC glad_glSamplerParameterIivEXT = NULL;
+PFNGLSAMPLERPARAMETERIIVOESPROC glad_glSamplerParameterIivOES = NULL;
+PFNGLSAMPLERPARAMETERIUIVEXTPROC glad_glSamplerParameterIuivEXT = NULL;
+PFNGLSAMPLERPARAMETERIUIVOESPROC glad_glSamplerParameterIuivOES = NULL;
+PFNGLSCISSORPROC glad_glScissor = NULL;
+PFNGLSCISSORARRAYVOESPROC glad_glScissorArrayvOES = NULL;
+PFNGLSCISSORINDEXEDOESPROC glad_glScissorIndexedOES = NULL;
+PFNGLSCISSORINDEXEDVOESPROC glad_glScissorIndexedvOES = NULL;
+PFNGLSEMAPHOREPARAMETERUI64VEXTPROC glad_glSemaphoreParameterui64vEXT = NULL;
+PFNGLSHADERBINARYPROC glad_glShaderBinary = NULL;
+PFNGLSHADERSOURCEPROC glad_glShaderSource = NULL;
+PFNGLSHADINGRATECOMBINEROPSEXTPROC glad_glShadingRateCombinerOpsEXT = NULL;
+PFNGLSHADINGRATEEXTPROC glad_glShadingRateEXT = NULL;
+PFNGLSIGNALSEMAPHOREEXTPROC glad_glSignalSemaphoreEXT = NULL;
+PFNGLSTENCILFUNCPROC glad_glStencilFunc = NULL;
+PFNGLSTENCILFUNCSEPARATEPROC glad_glStencilFuncSeparate = NULL;
+PFNGLSTENCILMASKPROC glad_glStencilMask = NULL;
+PFNGLSTENCILMASKSEPARATEPROC glad_glStencilMaskSeparate = NULL;
+PFNGLSTENCILOPPROC glad_glStencilOp = NULL;
+PFNGLSTENCILOPSEPARATEPROC glad_glStencilOpSeparate = NULL;
+PFNGLTEXBUFFEREXTPROC glad_glTexBufferEXT = NULL;
+PFNGLTEXBUFFEROESPROC glad_glTexBufferOES = NULL;
+PFNGLTEXBUFFERRANGEEXTPROC glad_glTexBufferRangeEXT = NULL;
+PFNGLTEXBUFFERRANGEOESPROC glad_glTexBufferRangeOES = NULL;
+PFNGLTEXIMAGE2DPROC glad_glTexImage2D = NULL;
+PFNGLTEXIMAGE3DOESPROC glad_glTexImage3DOES = NULL;
+PFNGLTEXPAGECOMMITMENTEXTPROC glad_glTexPageCommitmentEXT = NULL;
+PFNGLTEXPARAMETERIIVEXTPROC glad_glTexParameterIivEXT = NULL;
+PFNGLTEXPARAMETERIIVOESPROC glad_glTexParameterIivOES = NULL;
+PFNGLTEXPARAMETERIUIVEXTPROC glad_glTexParameterIuivEXT = NULL;
+PFNGLTEXPARAMETERIUIVOESPROC glad_glTexParameterIuivOES = NULL;
+PFNGLTEXPARAMETERFPROC glad_glTexParameterf = NULL;
+PFNGLTEXPARAMETERFVPROC glad_glTexParameterfv = NULL;
+PFNGLTEXPARAMETERIPROC glad_glTexParameteri = NULL;
+PFNGLTEXPARAMETERIVPROC glad_glTexParameteriv = NULL;
+PFNGLTEXSTORAGE1DEXTPROC glad_glTexStorage1DEXT = NULL;
+PFNGLTEXSTORAGE2DEXTPROC glad_glTexStorage2DEXT = NULL;
+PFNGLTEXSTORAGE3DEXTPROC glad_glTexStorage3DEXT = NULL;
+PFNGLTEXSTORAGE3DMULTISAMPLEOESPROC glad_glTexStorage3DMultisampleOES = NULL;
+PFNGLTEXSTORAGEATTRIBS2DEXTPROC glad_glTexStorageAttribs2DEXT = NULL;
+PFNGLTEXSTORAGEATTRIBS3DEXTPROC glad_glTexStorageAttribs3DEXT = NULL;
+PFNGLTEXSTORAGEMEM2DEXTPROC glad_glTexStorageMem2DEXT = NULL;
+PFNGLTEXSTORAGEMEM2DMULTISAMPLEEXTPROC glad_glTexStorageMem2DMultisampleEXT = NULL;
+PFNGLTEXSTORAGEMEM3DEXTPROC glad_glTexStorageMem3DEXT = NULL;
+PFNGLTEXSTORAGEMEM3DMULTISAMPLEEXTPROC glad_glTexStorageMem3DMultisampleEXT = NULL;
+PFNGLTEXSUBIMAGE2DPROC glad_glTexSubImage2D = NULL;
+PFNGLTEXSUBIMAGE3DOESPROC glad_glTexSubImage3DOES = NULL;
+PFNGLTEXTURESTORAGE1DEXTPROC glad_glTextureStorage1DEXT = NULL;
+PFNGLTEXTURESTORAGE2DEXTPROC glad_glTextureStorage2DEXT = NULL;
+PFNGLTEXTURESTORAGE3DEXTPROC glad_glTextureStorage3DEXT = NULL;
+PFNGLTEXTURESTORAGEMEM2DEXTPROC glad_glTextureStorageMem2DEXT = NULL;
+PFNGLTEXTURESTORAGEMEM2DMULTISAMPLEEXTPROC glad_glTextureStorageMem2DMultisampleEXT = NULL;
+PFNGLTEXTURESTORAGEMEM3DEXTPROC glad_glTextureStorageMem3DEXT = NULL;
+PFNGLTEXTURESTORAGEMEM3DMULTISAMPLEEXTPROC glad_glTextureStorageMem3DMultisampleEXT = NULL;
+PFNGLTEXTUREVIEWEXTPROC glad_glTextureViewEXT = NULL;
+PFNGLTEXTUREVIEWOESPROC glad_glTextureViewOES = NULL;
+PFNGLUNIFORM1FPROC glad_glUniform1f = NULL;
+PFNGLUNIFORM1FVPROC glad_glUniform1fv = NULL;
+PFNGLUNIFORM1IPROC glad_glUniform1i = NULL;
+PFNGLUNIFORM1IVPROC glad_glUniform1iv = NULL;
+PFNGLUNIFORM2FPROC glad_glUniform2f = NULL;
+PFNGLUNIFORM2FVPROC glad_glUniform2fv = NULL;
+PFNGLUNIFORM2IPROC glad_glUniform2i = NULL;
+PFNGLUNIFORM2IVPROC glad_glUniform2iv = NULL;
+PFNGLUNIFORM3FPROC glad_glUniform3f = NULL;
+PFNGLUNIFORM3FVPROC glad_glUniform3fv = NULL;
+PFNGLUNIFORM3IPROC glad_glUniform3i = NULL;
+PFNGLUNIFORM3IVPROC glad_glUniform3iv = NULL;
+PFNGLUNIFORM4FPROC glad_glUniform4f = NULL;
+PFNGLUNIFORM4FVPROC glad_glUniform4fv = NULL;
+PFNGLUNIFORM4IPROC glad_glUniform4i = NULL;
+PFNGLUNIFORM4IVPROC glad_glUniform4iv = NULL;
+PFNGLUNIFORMMATRIX2FVPROC glad_glUniformMatrix2fv = NULL;
+PFNGLUNIFORMMATRIX3FVPROC glad_glUniformMatrix3fv = NULL;
+PFNGLUNIFORMMATRIX4FVPROC glad_glUniformMatrix4fv = NULL;
+PFNGLUNMAPBUFFEROESPROC glad_glUnmapBufferOES = NULL;
+PFNGLUSEPROGRAMPROC glad_glUseProgram = NULL;
+PFNGLUSEPROGRAMSTAGESEXTPROC glad_glUseProgramStagesEXT = NULL;
+PFNGLVALIDATEPROGRAMPROC glad_glValidateProgram = NULL;
+PFNGLVALIDATEPROGRAMPIPELINEEXTPROC glad_glValidateProgramPipelineEXT = NULL;
+PFNGLVERTEXATTRIB1FPROC glad_glVertexAttrib1f = NULL;
+PFNGLVERTEXATTRIB1FVPROC glad_glVertexAttrib1fv = NULL;
+PFNGLVERTEXATTRIB2FPROC glad_glVertexAttrib2f = NULL;
+PFNGLVERTEXATTRIB2FVPROC glad_glVertexAttrib2fv = NULL;
+PFNGLVERTEXATTRIB3FPROC glad_glVertexAttrib3f = NULL;
+PFNGLVERTEXATTRIB3FVPROC glad_glVertexAttrib3fv = NULL;
+PFNGLVERTEXATTRIB4FPROC glad_glVertexAttrib4f = NULL;
+PFNGLVERTEXATTRIB4FVPROC glad_glVertexAttrib4fv = NULL;
+PFNGLVERTEXATTRIBDIVISOREXTPROC glad_glVertexAttribDivisorEXT = NULL;
+PFNGLVERTEXATTRIBPOINTERPROC glad_glVertexAttribPointer = NULL;
+PFNGLVIEWPORTPROC glad_glViewport = NULL;
+PFNGLVIEWPORTARRAYVOESPROC glad_glViewportArrayvOES = NULL;
+PFNGLVIEWPORTINDEXEDFOESPROC glad_glViewportIndexedfOES = NULL;
+PFNGLVIEWPORTINDEXEDFVOESPROC glad_glViewportIndexedfvOES = NULL;
+PFNGLWAITSEMAPHOREEXTPROC glad_glWaitSemaphoreEXT = NULL;
+PFNGLWINDOWRECTANGLESEXTPROC glad_glWindowRectanglesEXT = NULL;
+
+
+static void glad_gl_load_GL_ES_VERSION_2_0( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_ES_VERSION_2_0) return;
+ glad_glActiveTexture = (PFNGLACTIVETEXTUREPROC) load(userptr, "glActiveTexture");
+ glad_glAttachShader = (PFNGLATTACHSHADERPROC) load(userptr, "glAttachShader");
+ glad_glBindAttribLocation = (PFNGLBINDATTRIBLOCATIONPROC) load(userptr, "glBindAttribLocation");
+ glad_glBindBuffer = (PFNGLBINDBUFFERPROC) load(userptr, "glBindBuffer");
+ glad_glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC) load(userptr, "glBindFramebuffer");
+ glad_glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC) load(userptr, "glBindRenderbuffer");
+ glad_glBindTexture = (PFNGLBINDTEXTUREPROC) load(userptr, "glBindTexture");
+ glad_glBlendColor = (PFNGLBLENDCOLORPROC) load(userptr, "glBlendColor");
+ glad_glBlendEquation = (PFNGLBLENDEQUATIONPROC) load(userptr, "glBlendEquation");
+ glad_glBlendEquationSeparate = (PFNGLBLENDEQUATIONSEPARATEPROC) load(userptr, "glBlendEquationSeparate");
+ glad_glBlendFunc = (PFNGLBLENDFUNCPROC) load(userptr, "glBlendFunc");
+ glad_glBlendFuncSeparate = (PFNGLBLENDFUNCSEPARATEPROC) load(userptr, "glBlendFuncSeparate");
+ glad_glBufferData = (PFNGLBUFFERDATAPROC) load(userptr, "glBufferData");
+ glad_glBufferSubData = (PFNGLBUFFERSUBDATAPROC) load(userptr, "glBufferSubData");
+ glad_glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC) load(userptr, "glCheckFramebufferStatus");
+ glad_glClear = (PFNGLCLEARPROC) load(userptr, "glClear");
+ glad_glClearColor = (PFNGLCLEARCOLORPROC) load(userptr, "glClearColor");
+ glad_glClearDepthf = (PFNGLCLEARDEPTHFPROC) load(userptr, "glClearDepthf");
+ glad_glClearStencil = (PFNGLCLEARSTENCILPROC) load(userptr, "glClearStencil");
+ glad_glColorMask = (PFNGLCOLORMASKPROC) load(userptr, "glColorMask");
+ glad_glCompileShader = (PFNGLCOMPILESHADERPROC) load(userptr, "glCompileShader");
+ glad_glCompressedTexImage2D = (PFNGLCOMPRESSEDTEXIMAGE2DPROC) load(userptr, "glCompressedTexImage2D");
+ glad_glCompressedTexSubImage2D = (PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) load(userptr, "glCompressedTexSubImage2D");
+ glad_glCopyTexImage2D = (PFNGLCOPYTEXIMAGE2DPROC) load(userptr, "glCopyTexImage2D");
+ glad_glCopyTexSubImage2D = (PFNGLCOPYTEXSUBIMAGE2DPROC) load(userptr, "glCopyTexSubImage2D");
+ glad_glCreateProgram = (PFNGLCREATEPROGRAMPROC) load(userptr, "glCreateProgram");
+ glad_glCreateShader = (PFNGLCREATESHADERPROC) load(userptr, "glCreateShader");
+ glad_glCullFace = (PFNGLCULLFACEPROC) load(userptr, "glCullFace");
+ glad_glDeleteBuffers = (PFNGLDELETEBUFFERSPROC) load(userptr, "glDeleteBuffers");
+ glad_glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC) load(userptr, "glDeleteFramebuffers");
+ glad_glDeleteProgram = (PFNGLDELETEPROGRAMPROC) load(userptr, "glDeleteProgram");
+ glad_glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC) load(userptr, "glDeleteRenderbuffers");
+ glad_glDeleteShader = (PFNGLDELETESHADERPROC) load(userptr, "glDeleteShader");
+ glad_glDeleteTextures = (PFNGLDELETETEXTURESPROC) load(userptr, "glDeleteTextures");
+ glad_glDepthFunc = (PFNGLDEPTHFUNCPROC) load(userptr, "glDepthFunc");
+ glad_glDepthMask = (PFNGLDEPTHMASKPROC) load(userptr, "glDepthMask");
+ glad_glDepthRangef = (PFNGLDEPTHRANGEFPROC) load(userptr, "glDepthRangef");
+ glad_glDetachShader = (PFNGLDETACHSHADERPROC) load(userptr, "glDetachShader");
+ glad_glDisable = (PFNGLDISABLEPROC) load(userptr, "glDisable");
+ glad_glDisableVertexAttribArray = (PFNGLDISABLEVERTEXATTRIBARRAYPROC) load(userptr, "glDisableVertexAttribArray");
+ glad_glDrawArrays = (PFNGLDRAWARRAYSPROC) load(userptr, "glDrawArrays");
+ glad_glDrawElements = (PFNGLDRAWELEMENTSPROC) load(userptr, "glDrawElements");
+ glad_glEnable = (PFNGLENABLEPROC) load(userptr, "glEnable");
+ glad_glEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC) load(userptr, "glEnableVertexAttribArray");
+ glad_glFinish = (PFNGLFINISHPROC) load(userptr, "glFinish");
+ glad_glFlush = (PFNGLFLUSHPROC) load(userptr, "glFlush");
+ glad_glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC) load(userptr, "glFramebufferRenderbuffer");
+ glad_glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC) load(userptr, "glFramebufferTexture2D");
+ glad_glFrontFace = (PFNGLFRONTFACEPROC) load(userptr, "glFrontFace");
+ glad_glGenBuffers = (PFNGLGENBUFFERSPROC) load(userptr, "glGenBuffers");
+ glad_glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC) load(userptr, "glGenFramebuffers");
+ glad_glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC) load(userptr, "glGenRenderbuffers");
+ glad_glGenTextures = (PFNGLGENTEXTURESPROC) load(userptr, "glGenTextures");
+ glad_glGenerateMipmap = (PFNGLGENERATEMIPMAPPROC) load(userptr, "glGenerateMipmap");
+ glad_glGetActiveAttrib = (PFNGLGETACTIVEATTRIBPROC) load(userptr, "glGetActiveAttrib");
+ glad_glGetActiveUniform = (PFNGLGETACTIVEUNIFORMPROC) load(userptr, "glGetActiveUniform");
+ glad_glGetAttachedShaders = (PFNGLGETATTACHEDSHADERSPROC) load(userptr, "glGetAttachedShaders");
+ glad_glGetAttribLocation = (PFNGLGETATTRIBLOCATIONPROC) load(userptr, "glGetAttribLocation");
+ glad_glGetBooleanv = (PFNGLGETBOOLEANVPROC) load(userptr, "glGetBooleanv");
+ glad_glGetBufferParameteriv = (PFNGLGETBUFFERPARAMETERIVPROC) load(userptr, "glGetBufferParameteriv");
+ glad_glGetError = (PFNGLGETERRORPROC) load(userptr, "glGetError");
+ glad_glGetFloatv = (PFNGLGETFLOATVPROC) load(userptr, "glGetFloatv");
+ glad_glGetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) load(userptr, "glGetFramebufferAttachmentParameteriv");
+ glad_glGetIntegerv = (PFNGLGETINTEGERVPROC) load(userptr, "glGetIntegerv");
+ glad_glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC) load(userptr, "glGetProgramInfoLog");
+ glad_glGetProgramiv = (PFNGLGETPROGRAMIVPROC) load(userptr, "glGetProgramiv");
+ glad_glGetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIVPROC) load(userptr, "glGetRenderbufferParameteriv");
+ glad_glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC) load(userptr, "glGetShaderInfoLog");
+ glad_glGetShaderPrecisionFormat = (PFNGLGETSHADERPRECISIONFORMATPROC) load(userptr, "glGetShaderPrecisionFormat");
+ glad_glGetShaderSource = (PFNGLGETSHADERSOURCEPROC) load(userptr, "glGetShaderSource");
+ glad_glGetShaderiv = (PFNGLGETSHADERIVPROC) load(userptr, "glGetShaderiv");
+ glad_glGetString = (PFNGLGETSTRINGPROC) load(userptr, "glGetString");
+ glad_glGetTexParameterfv = (PFNGLGETTEXPARAMETERFVPROC) load(userptr, "glGetTexParameterfv");
+ glad_glGetTexParameteriv = (PFNGLGETTEXPARAMETERIVPROC) load(userptr, "glGetTexParameteriv");
+ glad_glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC) load(userptr, "glGetUniformLocation");
+ glad_glGetUniformfv = (PFNGLGETUNIFORMFVPROC) load(userptr, "glGetUniformfv");
+ glad_glGetUniformiv = (PFNGLGETUNIFORMIVPROC) load(userptr, "glGetUniformiv");
+ glad_glGetVertexAttribPointerv = (PFNGLGETVERTEXATTRIBPOINTERVPROC) load(userptr, "glGetVertexAttribPointerv");
+ glad_glGetVertexAttribfv = (PFNGLGETVERTEXATTRIBFVPROC) load(userptr, "glGetVertexAttribfv");
+ glad_glGetVertexAttribiv = (PFNGLGETVERTEXATTRIBIVPROC) load(userptr, "glGetVertexAttribiv");
+ glad_glHint = (PFNGLHINTPROC) load(userptr, "glHint");
+ glad_glIsBuffer = (PFNGLISBUFFERPROC) load(userptr, "glIsBuffer");
+ glad_glIsEnabled = (PFNGLISENABLEDPROC) load(userptr, "glIsEnabled");
+ glad_glIsFramebuffer = (PFNGLISFRAMEBUFFERPROC) load(userptr, "glIsFramebuffer");
+ glad_glIsProgram = (PFNGLISPROGRAMPROC) load(userptr, "glIsProgram");
+ glad_glIsRenderbuffer = (PFNGLISRENDERBUFFERPROC) load(userptr, "glIsRenderbuffer");
+ glad_glIsShader = (PFNGLISSHADERPROC) load(userptr, "glIsShader");
+ glad_glIsTexture = (PFNGLISTEXTUREPROC) load(userptr, "glIsTexture");
+ glad_glLineWidth = (PFNGLLINEWIDTHPROC) load(userptr, "glLineWidth");
+ glad_glLinkProgram = (PFNGLLINKPROGRAMPROC) load(userptr, "glLinkProgram");
+ glad_glPixelStorei = (PFNGLPIXELSTOREIPROC) load(userptr, "glPixelStorei");
+ glad_glPolygonOffset = (PFNGLPOLYGONOFFSETPROC) load(userptr, "glPolygonOffset");
+ glad_glReadPixels = (PFNGLREADPIXELSPROC) load(userptr, "glReadPixels");
+ glad_glReleaseShaderCompiler = (PFNGLRELEASESHADERCOMPILERPROC) load(userptr, "glReleaseShaderCompiler");
+ glad_glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC) load(userptr, "glRenderbufferStorage");
+ glad_glSampleCoverage = (PFNGLSAMPLECOVERAGEPROC) load(userptr, "glSampleCoverage");
+ glad_glScissor = (PFNGLSCISSORPROC) load(userptr, "glScissor");
+ glad_glShaderBinary = (PFNGLSHADERBINARYPROC) load(userptr, "glShaderBinary");
+ glad_glShaderSource = (PFNGLSHADERSOURCEPROC) load(userptr, "glShaderSource");
+ glad_glStencilFunc = (PFNGLSTENCILFUNCPROC) load(userptr, "glStencilFunc");
+ glad_glStencilFuncSeparate = (PFNGLSTENCILFUNCSEPARATEPROC) load(userptr, "glStencilFuncSeparate");
+ glad_glStencilMask = (PFNGLSTENCILMASKPROC) load(userptr, "glStencilMask");
+ glad_glStencilMaskSeparate = (PFNGLSTENCILMASKSEPARATEPROC) load(userptr, "glStencilMaskSeparate");
+ glad_glStencilOp = (PFNGLSTENCILOPPROC) load(userptr, "glStencilOp");
+ glad_glStencilOpSeparate = (PFNGLSTENCILOPSEPARATEPROC) load(userptr, "glStencilOpSeparate");
+ glad_glTexImage2D = (PFNGLTEXIMAGE2DPROC) load(userptr, "glTexImage2D");
+ glad_glTexParameterf = (PFNGLTEXPARAMETERFPROC) load(userptr, "glTexParameterf");
+ glad_glTexParameterfv = (PFNGLTEXPARAMETERFVPROC) load(userptr, "glTexParameterfv");
+ glad_glTexParameteri = (PFNGLTEXPARAMETERIPROC) load(userptr, "glTexParameteri");
+ glad_glTexParameteriv = (PFNGLTEXPARAMETERIVPROC) load(userptr, "glTexParameteriv");
+ glad_glTexSubImage2D = (PFNGLTEXSUBIMAGE2DPROC) load(userptr, "glTexSubImage2D");
+ glad_glUniform1f = (PFNGLUNIFORM1FPROC) load(userptr, "glUniform1f");
+ glad_glUniform1fv = (PFNGLUNIFORM1FVPROC) load(userptr, "glUniform1fv");
+ glad_glUniform1i = (PFNGLUNIFORM1IPROC) load(userptr, "glUniform1i");
+ glad_glUniform1iv = (PFNGLUNIFORM1IVPROC) load(userptr, "glUniform1iv");
+ glad_glUniform2f = (PFNGLUNIFORM2FPROC) load(userptr, "glUniform2f");
+ glad_glUniform2fv = (PFNGLUNIFORM2FVPROC) load(userptr, "glUniform2fv");
+ glad_glUniform2i = (PFNGLUNIFORM2IPROC) load(userptr, "glUniform2i");
+ glad_glUniform2iv = (PFNGLUNIFORM2IVPROC) load(userptr, "glUniform2iv");
+ glad_glUniform3f = (PFNGLUNIFORM3FPROC) load(userptr, "glUniform3f");
+ glad_glUniform3fv = (PFNGLUNIFORM3FVPROC) load(userptr, "glUniform3fv");
+ glad_glUniform3i = (PFNGLUNIFORM3IPROC) load(userptr, "glUniform3i");
+ glad_glUniform3iv = (PFNGLUNIFORM3IVPROC) load(userptr, "glUniform3iv");
+ glad_glUniform4f = (PFNGLUNIFORM4FPROC) load(userptr, "glUniform4f");
+ glad_glUniform4fv = (PFNGLUNIFORM4FVPROC) load(userptr, "glUniform4fv");
+ glad_glUniform4i = (PFNGLUNIFORM4IPROC) load(userptr, "glUniform4i");
+ glad_glUniform4iv = (PFNGLUNIFORM4IVPROC) load(userptr, "glUniform4iv");
+ glad_glUniformMatrix2fv = (PFNGLUNIFORMMATRIX2FVPROC) load(userptr, "glUniformMatrix2fv");
+ glad_glUniformMatrix3fv = (PFNGLUNIFORMMATRIX3FVPROC) load(userptr, "glUniformMatrix3fv");
+ glad_glUniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVPROC) load(userptr, "glUniformMatrix4fv");
+ glad_glUseProgram = (PFNGLUSEPROGRAMPROC) load(userptr, "glUseProgram");
+ glad_glValidateProgram = (PFNGLVALIDATEPROGRAMPROC) load(userptr, "glValidateProgram");
+ glad_glVertexAttrib1f = (PFNGLVERTEXATTRIB1FPROC) load(userptr, "glVertexAttrib1f");
+ glad_glVertexAttrib1fv = (PFNGLVERTEXATTRIB1FVPROC) load(userptr, "glVertexAttrib1fv");
+ glad_glVertexAttrib2f = (PFNGLVERTEXATTRIB2FPROC) load(userptr, "glVertexAttrib2f");
+ glad_glVertexAttrib2fv = (PFNGLVERTEXATTRIB2FVPROC) load(userptr, "glVertexAttrib2fv");
+ glad_glVertexAttrib3f = (PFNGLVERTEXATTRIB3FPROC) load(userptr, "glVertexAttrib3f");
+ glad_glVertexAttrib3fv = (PFNGLVERTEXATTRIB3FVPROC) load(userptr, "glVertexAttrib3fv");
+ glad_glVertexAttrib4f = (PFNGLVERTEXATTRIB4FPROC) load(userptr, "glVertexAttrib4f");
+ glad_glVertexAttrib4fv = (PFNGLVERTEXATTRIB4FVPROC) load(userptr, "glVertexAttrib4fv");
+ glad_glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC) load(userptr, "glVertexAttribPointer");
+ glad_glViewport = (PFNGLVIEWPORTPROC) load(userptr, "glViewport");
+}
+static void glad_gl_load_GL_EXT_EGL_image_storage( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_EGL_image_storage) return;
+ glad_glEGLImageTargetTexStorageEXT = (PFNGLEGLIMAGETARGETTEXSTORAGEEXTPROC) load(userptr, "glEGLImageTargetTexStorageEXT");
+ glad_glEGLImageTargetTextureStorageEXT = (PFNGLEGLIMAGETARGETTEXTURESTORAGEEXTPROC) load(userptr, "glEGLImageTargetTextureStorageEXT");
+}
+static void glad_gl_load_GL_EXT_base_instance( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_base_instance) return;
+ glad_glDrawArraysInstancedBaseInstanceEXT = (PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEEXTPROC) load(userptr, "glDrawArraysInstancedBaseInstanceEXT");
+ glad_glDrawElementsInstancedBaseInstanceEXT = (PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEEXTPROC) load(userptr, "glDrawElementsInstancedBaseInstanceEXT");
+ glad_glDrawElementsInstancedBaseVertexBaseInstanceEXT = (PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEEXTPROC) load(userptr, "glDrawElementsInstancedBaseVertexBaseInstanceEXT");
+}
+static void glad_gl_load_GL_EXT_blend_func_extended( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_blend_func_extended) return;
+ glad_glBindFragDataLocationEXT = (PFNGLBINDFRAGDATALOCATIONEXTPROC) load(userptr, "glBindFragDataLocationEXT");
+ glad_glBindFragDataLocationIndexedEXT = (PFNGLBINDFRAGDATALOCATIONINDEXEDEXTPROC) load(userptr, "glBindFragDataLocationIndexedEXT");
+ glad_glGetFragDataIndexEXT = (PFNGLGETFRAGDATAINDEXEXTPROC) load(userptr, "glGetFragDataIndexEXT");
+ glad_glGetProgramResourceLocationIndexEXT = (PFNGLGETPROGRAMRESOURCELOCATIONINDEXEXTPROC) load(userptr, "glGetProgramResourceLocationIndexEXT");
+}
+static void glad_gl_load_GL_EXT_buffer_storage( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_buffer_storage) return;
+ glad_glBufferStorageEXT = (PFNGLBUFFERSTORAGEEXTPROC) load(userptr, "glBufferStorageEXT");
+}
+static void glad_gl_load_GL_EXT_clear_texture( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_clear_texture) return;
+ glad_glClearTexImageEXT = (PFNGLCLEARTEXIMAGEEXTPROC) load(userptr, "glClearTexImageEXT");
+ glad_glClearTexSubImageEXT = (PFNGLCLEARTEXSUBIMAGEEXTPROC) load(userptr, "glClearTexSubImageEXT");
+}
+static void glad_gl_load_GL_EXT_clip_control( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_clip_control) return;
+ glad_glClipControlEXT = (PFNGLCLIPCONTROLEXTPROC) load(userptr, "glClipControlEXT");
+}
+static void glad_gl_load_GL_EXT_copy_image( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_copy_image) return;
+ glad_glCopyImageSubDataEXT = (PFNGLCOPYIMAGESUBDATAEXTPROC) load(userptr, "glCopyImageSubDataEXT");
+}
+static void glad_gl_load_GL_EXT_debug_label( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_debug_label) return;
+ glad_glGetObjectLabelEXT = (PFNGLGETOBJECTLABELEXTPROC) load(userptr, "glGetObjectLabelEXT");
+ glad_glLabelObjectEXT = (PFNGLLABELOBJECTEXTPROC) load(userptr, "glLabelObjectEXT");
+}
+static void glad_gl_load_GL_EXT_debug_marker( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_debug_marker) return;
+ glad_glInsertEventMarkerEXT = (PFNGLINSERTEVENTMARKEREXTPROC) load(userptr, "glInsertEventMarkerEXT");
+ glad_glPopGroupMarkerEXT = (PFNGLPOPGROUPMARKEREXTPROC) load(userptr, "glPopGroupMarkerEXT");
+ glad_glPushGroupMarkerEXT = (PFNGLPUSHGROUPMARKEREXTPROC) load(userptr, "glPushGroupMarkerEXT");
+}
+static void glad_gl_load_GL_EXT_discard_framebuffer( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_discard_framebuffer) return;
+ glad_glDiscardFramebufferEXT = (PFNGLDISCARDFRAMEBUFFEREXTPROC) load(userptr, "glDiscardFramebufferEXT");
+}
+static void glad_gl_load_GL_EXT_disjoint_timer_query( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_disjoint_timer_query) return;
+ glad_glBeginQueryEXT = (PFNGLBEGINQUERYEXTPROC) load(userptr, "glBeginQueryEXT");
+ glad_glDeleteQueriesEXT = (PFNGLDELETEQUERIESEXTPROC) load(userptr, "glDeleteQueriesEXT");
+ glad_glEndQueryEXT = (PFNGLENDQUERYEXTPROC) load(userptr, "glEndQueryEXT");
+ glad_glGenQueriesEXT = (PFNGLGENQUERIESEXTPROC) load(userptr, "glGenQueriesEXT");
+ glad_glGetInteger64vEXT = (PFNGLGETINTEGER64VEXTPROC) load(userptr, "glGetInteger64vEXT");
+ glad_glGetQueryObjecti64vEXT = (PFNGLGETQUERYOBJECTI64VEXTPROC) load(userptr, "glGetQueryObjecti64vEXT");
+ glad_glGetQueryObjectivEXT = (PFNGLGETQUERYOBJECTIVEXTPROC) load(userptr, "glGetQueryObjectivEXT");
+ glad_glGetQueryObjectui64vEXT = (PFNGLGETQUERYOBJECTUI64VEXTPROC) load(userptr, "glGetQueryObjectui64vEXT");
+ glad_glGetQueryObjectuivEXT = (PFNGLGETQUERYOBJECTUIVEXTPROC) load(userptr, "glGetQueryObjectuivEXT");
+ glad_glGetQueryivEXT = (PFNGLGETQUERYIVEXTPROC) load(userptr, "glGetQueryivEXT");
+ glad_glIsQueryEXT = (PFNGLISQUERYEXTPROC) load(userptr, "glIsQueryEXT");
+ glad_glQueryCounterEXT = (PFNGLQUERYCOUNTEREXTPROC) load(userptr, "glQueryCounterEXT");
+}
+static void glad_gl_load_GL_EXT_draw_buffers( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_draw_buffers) return;
+ glad_glDrawBuffersEXT = (PFNGLDRAWBUFFERSEXTPROC) load(userptr, "glDrawBuffersEXT");
+}
+static void glad_gl_load_GL_EXT_draw_buffers_indexed( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_draw_buffers_indexed) return;
+ glad_glBlendEquationSeparateiEXT = (PFNGLBLENDEQUATIONSEPARATEIEXTPROC) load(userptr, "glBlendEquationSeparateiEXT");
+ glad_glBlendEquationiEXT = (PFNGLBLENDEQUATIONIEXTPROC) load(userptr, "glBlendEquationiEXT");
+ glad_glBlendFuncSeparateiEXT = (PFNGLBLENDFUNCSEPARATEIEXTPROC) load(userptr, "glBlendFuncSeparateiEXT");
+ glad_glBlendFunciEXT = (PFNGLBLENDFUNCIEXTPROC) load(userptr, "glBlendFunciEXT");
+ glad_glColorMaskiEXT = (PFNGLCOLORMASKIEXTPROC) load(userptr, "glColorMaskiEXT");
+ glad_glDisableiEXT = (PFNGLDISABLEIEXTPROC) load(userptr, "glDisableiEXT");
+ glad_glEnableiEXT = (PFNGLENABLEIEXTPROC) load(userptr, "glEnableiEXT");
+ glad_glIsEnablediEXT = (PFNGLISENABLEDIEXTPROC) load(userptr, "glIsEnablediEXT");
+}
+static void glad_gl_load_GL_EXT_draw_elements_base_vertex( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_draw_elements_base_vertex) return;
+ glad_glDrawElementsBaseVertexEXT = (PFNGLDRAWELEMENTSBASEVERTEXEXTPROC) load(userptr, "glDrawElementsBaseVertexEXT");
+ glad_glDrawElementsInstancedBaseVertexEXT = (PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXEXTPROC) load(userptr, "glDrawElementsInstancedBaseVertexEXT");
+ glad_glDrawRangeElementsBaseVertexEXT = (PFNGLDRAWRANGEELEMENTSBASEVERTEXEXTPROC) load(userptr, "glDrawRangeElementsBaseVertexEXT");
+ glad_glMultiDrawElementsBaseVertexEXT = (PFNGLMULTIDRAWELEMENTSBASEVERTEXEXTPROC) load(userptr, "glMultiDrawElementsBaseVertexEXT");
+}
+static void glad_gl_load_GL_EXT_draw_instanced( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_draw_instanced) return;
+ glad_glDrawArraysInstancedEXT = (PFNGLDRAWARRAYSINSTANCEDEXTPROC) load(userptr, "glDrawArraysInstancedEXT");
+ glad_glDrawElementsInstancedEXT = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC) load(userptr, "glDrawElementsInstancedEXT");
+}
+static void glad_gl_load_GL_EXT_draw_transform_feedback( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_draw_transform_feedback) return;
+ glad_glDrawTransformFeedbackEXT = (PFNGLDRAWTRANSFORMFEEDBACKEXTPROC) load(userptr, "glDrawTransformFeedbackEXT");
+ glad_glDrawTransformFeedbackInstancedEXT = (PFNGLDRAWTRANSFORMFEEDBACKINSTANCEDEXTPROC) load(userptr, "glDrawTransformFeedbackInstancedEXT");
+}
+static void glad_gl_load_GL_EXT_external_buffer( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_external_buffer) return;
+ glad_glBufferStorageExternalEXT = (PFNGLBUFFERSTORAGEEXTERNALEXTPROC) load(userptr, "glBufferStorageExternalEXT");
+ glad_glNamedBufferStorageExternalEXT = (PFNGLNAMEDBUFFERSTORAGEEXTERNALEXTPROC) load(userptr, "glNamedBufferStorageExternalEXT");
+}
+static void glad_gl_load_GL_EXT_fragment_shading_rate( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_fragment_shading_rate) return;
+ glad_glFramebufferShadingRateEXT = (PFNGLFRAMEBUFFERSHADINGRATEEXTPROC) load(userptr, "glFramebufferShadingRateEXT");
+ glad_glGetFragmentShadingRatesEXT = (PFNGLGETFRAGMENTSHADINGRATESEXTPROC) load(userptr, "glGetFragmentShadingRatesEXT");
+ glad_glShadingRateCombinerOpsEXT = (PFNGLSHADINGRATECOMBINEROPSEXTPROC) load(userptr, "glShadingRateCombinerOpsEXT");
+ glad_glShadingRateEXT = (PFNGLSHADINGRATEEXTPROC) load(userptr, "glShadingRateEXT");
+}
+static void glad_gl_load_GL_EXT_geometry_shader( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_geometry_shader) return;
+ glad_glFramebufferTextureEXT = (PFNGLFRAMEBUFFERTEXTUREEXTPROC) load(userptr, "glFramebufferTextureEXT");
+}
+static void glad_gl_load_GL_EXT_instanced_arrays( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_instanced_arrays) return;
+ glad_glDrawArraysInstancedEXT = (PFNGLDRAWARRAYSINSTANCEDEXTPROC) load(userptr, "glDrawArraysInstancedEXT");
+ glad_glDrawElementsInstancedEXT = (PFNGLDRAWELEMENTSINSTANCEDEXTPROC) load(userptr, "glDrawElementsInstancedEXT");
+ glad_glVertexAttribDivisorEXT = (PFNGLVERTEXATTRIBDIVISOREXTPROC) load(userptr, "glVertexAttribDivisorEXT");
+}
+static void glad_gl_load_GL_EXT_map_buffer_range( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_map_buffer_range) return;
+ glad_glFlushMappedBufferRangeEXT = (PFNGLFLUSHMAPPEDBUFFERRANGEEXTPROC) load(userptr, "glFlushMappedBufferRangeEXT");
+ glad_glMapBufferRangeEXT = (PFNGLMAPBUFFERRANGEEXTPROC) load(userptr, "glMapBufferRangeEXT");
+}
+static void glad_gl_load_GL_EXT_memory_object( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_memory_object) return;
+ glad_glBufferStorageMemEXT = (PFNGLBUFFERSTORAGEMEMEXTPROC) load(userptr, "glBufferStorageMemEXT");
+ glad_glCreateMemoryObjectsEXT = (PFNGLCREATEMEMORYOBJECTSEXTPROC) load(userptr, "glCreateMemoryObjectsEXT");
+ glad_glDeleteMemoryObjectsEXT = (PFNGLDELETEMEMORYOBJECTSEXTPROC) load(userptr, "glDeleteMemoryObjectsEXT");
+ glad_glGetMemoryObjectParameterivEXT = (PFNGLGETMEMORYOBJECTPARAMETERIVEXTPROC) load(userptr, "glGetMemoryObjectParameterivEXT");
+ glad_glGetUnsignedBytei_vEXT = (PFNGLGETUNSIGNEDBYTEI_VEXTPROC) load(userptr, "glGetUnsignedBytei_vEXT");
+ glad_glGetUnsignedBytevEXT = (PFNGLGETUNSIGNEDBYTEVEXTPROC) load(userptr, "glGetUnsignedBytevEXT");
+ glad_glIsMemoryObjectEXT = (PFNGLISMEMORYOBJECTEXTPROC) load(userptr, "glIsMemoryObjectEXT");
+ glad_glMemoryObjectParameterivEXT = (PFNGLMEMORYOBJECTPARAMETERIVEXTPROC) load(userptr, "glMemoryObjectParameterivEXT");
+ glad_glNamedBufferStorageMemEXT = (PFNGLNAMEDBUFFERSTORAGEMEMEXTPROC) load(userptr, "glNamedBufferStorageMemEXT");
+ glad_glTexStorageMem2DEXT = (PFNGLTEXSTORAGEMEM2DEXTPROC) load(userptr, "glTexStorageMem2DEXT");
+ glad_glTexStorageMem2DMultisampleEXT = (PFNGLTEXSTORAGEMEM2DMULTISAMPLEEXTPROC) load(userptr, "glTexStorageMem2DMultisampleEXT");
+ glad_glTexStorageMem3DEXT = (PFNGLTEXSTORAGEMEM3DEXTPROC) load(userptr, "glTexStorageMem3DEXT");
+ glad_glTexStorageMem3DMultisampleEXT = (PFNGLTEXSTORAGEMEM3DMULTISAMPLEEXTPROC) load(userptr, "glTexStorageMem3DMultisampleEXT");
+ glad_glTextureStorageMem2DEXT = (PFNGLTEXTURESTORAGEMEM2DEXTPROC) load(userptr, "glTextureStorageMem2DEXT");
+ glad_glTextureStorageMem2DMultisampleEXT = (PFNGLTEXTURESTORAGEMEM2DMULTISAMPLEEXTPROC) load(userptr, "glTextureStorageMem2DMultisampleEXT");
+ glad_glTextureStorageMem3DEXT = (PFNGLTEXTURESTORAGEMEM3DEXTPROC) load(userptr, "glTextureStorageMem3DEXT");
+ glad_glTextureStorageMem3DMultisampleEXT = (PFNGLTEXTURESTORAGEMEM3DMULTISAMPLEEXTPROC) load(userptr, "glTextureStorageMem3DMultisampleEXT");
+}
+static void glad_gl_load_GL_EXT_memory_object_fd( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_memory_object_fd) return;
+ glad_glImportMemoryFdEXT = (PFNGLIMPORTMEMORYFDEXTPROC) load(userptr, "glImportMemoryFdEXT");
+}
+static void glad_gl_load_GL_EXT_memory_object_win32( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_memory_object_win32) return;
+ glad_glImportMemoryWin32HandleEXT = (PFNGLIMPORTMEMORYWIN32HANDLEEXTPROC) load(userptr, "glImportMemoryWin32HandleEXT");
+ glad_glImportMemoryWin32NameEXT = (PFNGLIMPORTMEMORYWIN32NAMEEXTPROC) load(userptr, "glImportMemoryWin32NameEXT");
+}
+static void glad_gl_load_GL_EXT_multi_draw_arrays( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_multi_draw_arrays) return;
+ glad_glMultiDrawArraysEXT = (PFNGLMULTIDRAWARRAYSEXTPROC) load(userptr, "glMultiDrawArraysEXT");
+ glad_glMultiDrawElementsEXT = (PFNGLMULTIDRAWELEMENTSEXTPROC) load(userptr, "glMultiDrawElementsEXT");
+}
+static void glad_gl_load_GL_EXT_multi_draw_indirect( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_multi_draw_indirect) return;
+ glad_glMultiDrawArraysIndirectEXT = (PFNGLMULTIDRAWARRAYSINDIRECTEXTPROC) load(userptr, "glMultiDrawArraysIndirectEXT");
+ glad_glMultiDrawElementsIndirectEXT = (PFNGLMULTIDRAWELEMENTSINDIRECTEXTPROC) load(userptr, "glMultiDrawElementsIndirectEXT");
+}
+static void glad_gl_load_GL_EXT_multisampled_render_to_texture( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_multisampled_render_to_texture) return;
+ glad_glFramebufferTexture2DMultisampleEXT = (PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC) load(userptr, "glFramebufferTexture2DMultisampleEXT");
+ glad_glRenderbufferStorageMultisampleEXT = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) load(userptr, "glRenderbufferStorageMultisampleEXT");
+}
+static void glad_gl_load_GL_EXT_multiview_draw_buffers( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_multiview_draw_buffers) return;
+ glad_glDrawBuffersIndexedEXT = (PFNGLDRAWBUFFERSINDEXEDEXTPROC) load(userptr, "glDrawBuffersIndexedEXT");
+ glad_glGetIntegeri_vEXT = (PFNGLGETINTEGERI_VEXTPROC) load(userptr, "glGetIntegeri_vEXT");
+ glad_glReadBufferIndexedEXT = (PFNGLREADBUFFERINDEXEDEXTPROC) load(userptr, "glReadBufferIndexedEXT");
+}
+static void glad_gl_load_GL_EXT_occlusion_query_boolean( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_occlusion_query_boolean) return;
+ glad_glBeginQueryEXT = (PFNGLBEGINQUERYEXTPROC) load(userptr, "glBeginQueryEXT");
+ glad_glDeleteQueriesEXT = (PFNGLDELETEQUERIESEXTPROC) load(userptr, "glDeleteQueriesEXT");
+ glad_glEndQueryEXT = (PFNGLENDQUERYEXTPROC) load(userptr, "glEndQueryEXT");
+ glad_glGenQueriesEXT = (PFNGLGENQUERIESEXTPROC) load(userptr, "glGenQueriesEXT");
+ glad_glGetQueryObjectuivEXT = (PFNGLGETQUERYOBJECTUIVEXTPROC) load(userptr, "glGetQueryObjectuivEXT");
+ glad_glGetQueryivEXT = (PFNGLGETQUERYIVEXTPROC) load(userptr, "glGetQueryivEXT");
+ glad_glIsQueryEXT = (PFNGLISQUERYEXTPROC) load(userptr, "glIsQueryEXT");
+}
+static void glad_gl_load_GL_EXT_polygon_offset_clamp( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_polygon_offset_clamp) return;
+ glad_glPolygonOffsetClampEXT = (PFNGLPOLYGONOFFSETCLAMPEXTPROC) load(userptr, "glPolygonOffsetClampEXT");
+}
+static void glad_gl_load_GL_EXT_primitive_bounding_box( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_primitive_bounding_box) return;
+ glad_glPrimitiveBoundingBoxEXT = (PFNGLPRIMITIVEBOUNDINGBOXEXTPROC) load(userptr, "glPrimitiveBoundingBoxEXT");
+}
+static void glad_gl_load_GL_EXT_raster_multisample( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_raster_multisample) return;
+ glad_glRasterSamplesEXT = (PFNGLRASTERSAMPLESEXTPROC) load(userptr, "glRasterSamplesEXT");
+}
+static void glad_gl_load_GL_EXT_robustness( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_robustness) return;
+ glad_glGetGraphicsResetStatusEXT = (PFNGLGETGRAPHICSRESETSTATUSEXTPROC) load(userptr, "glGetGraphicsResetStatusEXT");
+ glad_glGetnUniformfvEXT = (PFNGLGETNUNIFORMFVEXTPROC) load(userptr, "glGetnUniformfvEXT");
+ glad_glGetnUniformivEXT = (PFNGLGETNUNIFORMIVEXTPROC) load(userptr, "glGetnUniformivEXT");
+ glad_glReadnPixelsEXT = (PFNGLREADNPIXELSEXTPROC) load(userptr, "glReadnPixelsEXT");
+}
+static void glad_gl_load_GL_EXT_semaphore( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_semaphore) return;
+ glad_glDeleteSemaphoresEXT = (PFNGLDELETESEMAPHORESEXTPROC) load(userptr, "glDeleteSemaphoresEXT");
+ glad_glGenSemaphoresEXT = (PFNGLGENSEMAPHORESEXTPROC) load(userptr, "glGenSemaphoresEXT");
+ glad_glGetSemaphoreParameterui64vEXT = (PFNGLGETSEMAPHOREPARAMETERUI64VEXTPROC) load(userptr, "glGetSemaphoreParameterui64vEXT");
+ glad_glGetUnsignedBytei_vEXT = (PFNGLGETUNSIGNEDBYTEI_VEXTPROC) load(userptr, "glGetUnsignedBytei_vEXT");
+ glad_glGetUnsignedBytevEXT = (PFNGLGETUNSIGNEDBYTEVEXTPROC) load(userptr, "glGetUnsignedBytevEXT");
+ glad_glIsSemaphoreEXT = (PFNGLISSEMAPHOREEXTPROC) load(userptr, "glIsSemaphoreEXT");
+ glad_glSemaphoreParameterui64vEXT = (PFNGLSEMAPHOREPARAMETERUI64VEXTPROC) load(userptr, "glSemaphoreParameterui64vEXT");
+ glad_glSignalSemaphoreEXT = (PFNGLSIGNALSEMAPHOREEXTPROC) load(userptr, "glSignalSemaphoreEXT");
+ glad_glWaitSemaphoreEXT = (PFNGLWAITSEMAPHOREEXTPROC) load(userptr, "glWaitSemaphoreEXT");
+}
+static void glad_gl_load_GL_EXT_semaphore_fd( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_semaphore_fd) return;
+ glad_glImportSemaphoreFdEXT = (PFNGLIMPORTSEMAPHOREFDEXTPROC) load(userptr, "glImportSemaphoreFdEXT");
+}
+static void glad_gl_load_GL_EXT_semaphore_win32( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_semaphore_win32) return;
+ glad_glImportSemaphoreWin32HandleEXT = (PFNGLIMPORTSEMAPHOREWIN32HANDLEEXTPROC) load(userptr, "glImportSemaphoreWin32HandleEXT");
+ glad_glImportSemaphoreWin32NameEXT = (PFNGLIMPORTSEMAPHOREWIN32NAMEEXTPROC) load(userptr, "glImportSemaphoreWin32NameEXT");
+}
+static void glad_gl_load_GL_EXT_separate_shader_objects( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_separate_shader_objects) return;
+ glad_glActiveShaderProgramEXT = (PFNGLACTIVESHADERPROGRAMEXTPROC) load(userptr, "glActiveShaderProgramEXT");
+ glad_glBindProgramPipelineEXT = (PFNGLBINDPROGRAMPIPELINEEXTPROC) load(userptr, "glBindProgramPipelineEXT");
+ glad_glCreateShaderProgramvEXT = (PFNGLCREATESHADERPROGRAMVEXTPROC) load(userptr, "glCreateShaderProgramvEXT");
+ glad_glDeleteProgramPipelinesEXT = (PFNGLDELETEPROGRAMPIPELINESEXTPROC) load(userptr, "glDeleteProgramPipelinesEXT");
+ glad_glGenProgramPipelinesEXT = (PFNGLGENPROGRAMPIPELINESEXTPROC) load(userptr, "glGenProgramPipelinesEXT");
+ glad_glGetProgramPipelineInfoLogEXT = (PFNGLGETPROGRAMPIPELINEINFOLOGEXTPROC) load(userptr, "glGetProgramPipelineInfoLogEXT");
+ glad_glGetProgramPipelineivEXT = (PFNGLGETPROGRAMPIPELINEIVEXTPROC) load(userptr, "glGetProgramPipelineivEXT");
+ glad_glIsProgramPipelineEXT = (PFNGLISPROGRAMPIPELINEEXTPROC) load(userptr, "glIsProgramPipelineEXT");
+ glad_glProgramParameteriEXT = (PFNGLPROGRAMPARAMETERIEXTPROC) load(userptr, "glProgramParameteriEXT");
+ glad_glProgramUniform1fEXT = (PFNGLPROGRAMUNIFORM1FEXTPROC) load(userptr, "glProgramUniform1fEXT");
+ glad_glProgramUniform1fvEXT = (PFNGLPROGRAMUNIFORM1FVEXTPROC) load(userptr, "glProgramUniform1fvEXT");
+ glad_glProgramUniform1iEXT = (PFNGLPROGRAMUNIFORM1IEXTPROC) load(userptr, "glProgramUniform1iEXT");
+ glad_glProgramUniform1ivEXT = (PFNGLPROGRAMUNIFORM1IVEXTPROC) load(userptr, "glProgramUniform1ivEXT");
+ glad_glProgramUniform1uiEXT = (PFNGLPROGRAMUNIFORM1UIEXTPROC) load(userptr, "glProgramUniform1uiEXT");
+ glad_glProgramUniform1uivEXT = (PFNGLPROGRAMUNIFORM1UIVEXTPROC) load(userptr, "glProgramUniform1uivEXT");
+ glad_glProgramUniform2fEXT = (PFNGLPROGRAMUNIFORM2FEXTPROC) load(userptr, "glProgramUniform2fEXT");
+ glad_glProgramUniform2fvEXT = (PFNGLPROGRAMUNIFORM2FVEXTPROC) load(userptr, "glProgramUniform2fvEXT");
+ glad_glProgramUniform2iEXT = (PFNGLPROGRAMUNIFORM2IEXTPROC) load(userptr, "glProgramUniform2iEXT");
+ glad_glProgramUniform2ivEXT = (PFNGLPROGRAMUNIFORM2IVEXTPROC) load(userptr, "glProgramUniform2ivEXT");
+ glad_glProgramUniform2uiEXT = (PFNGLPROGRAMUNIFORM2UIEXTPROC) load(userptr, "glProgramUniform2uiEXT");
+ glad_glProgramUniform2uivEXT = (PFNGLPROGRAMUNIFORM2UIVEXTPROC) load(userptr, "glProgramUniform2uivEXT");
+ glad_glProgramUniform3fEXT = (PFNGLPROGRAMUNIFORM3FEXTPROC) load(userptr, "glProgramUniform3fEXT");
+ glad_glProgramUniform3fvEXT = (PFNGLPROGRAMUNIFORM3FVEXTPROC) load(userptr, "glProgramUniform3fvEXT");
+ glad_glProgramUniform3iEXT = (PFNGLPROGRAMUNIFORM3IEXTPROC) load(userptr, "glProgramUniform3iEXT");
+ glad_glProgramUniform3ivEXT = (PFNGLPROGRAMUNIFORM3IVEXTPROC) load(userptr, "glProgramUniform3ivEXT");
+ glad_glProgramUniform3uiEXT = (PFNGLPROGRAMUNIFORM3UIEXTPROC) load(userptr, "glProgramUniform3uiEXT");
+ glad_glProgramUniform3uivEXT = (PFNGLPROGRAMUNIFORM3UIVEXTPROC) load(userptr, "glProgramUniform3uivEXT");
+ glad_glProgramUniform4fEXT = (PFNGLPROGRAMUNIFORM4FEXTPROC) load(userptr, "glProgramUniform4fEXT");
+ glad_glProgramUniform4fvEXT = (PFNGLPROGRAMUNIFORM4FVEXTPROC) load(userptr, "glProgramUniform4fvEXT");
+ glad_glProgramUniform4iEXT = (PFNGLPROGRAMUNIFORM4IEXTPROC) load(userptr, "glProgramUniform4iEXT");
+ glad_glProgramUniform4ivEXT = (PFNGLPROGRAMUNIFORM4IVEXTPROC) load(userptr, "glProgramUniform4ivEXT");
+ glad_glProgramUniform4uiEXT = (PFNGLPROGRAMUNIFORM4UIEXTPROC) load(userptr, "glProgramUniform4uiEXT");
+ glad_glProgramUniform4uivEXT = (PFNGLPROGRAMUNIFORM4UIVEXTPROC) load(userptr, "glProgramUniform4uivEXT");
+ glad_glProgramUniformMatrix2fvEXT = (PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC) load(userptr, "glProgramUniformMatrix2fvEXT");
+ glad_glProgramUniformMatrix2x3fvEXT = (PFNGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC) load(userptr, "glProgramUniformMatrix2x3fvEXT");
+ glad_glProgramUniformMatrix2x4fvEXT = (PFNGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC) load(userptr, "glProgramUniformMatrix2x4fvEXT");
+ glad_glProgramUniformMatrix3fvEXT = (PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC) load(userptr, "glProgramUniformMatrix3fvEXT");
+ glad_glProgramUniformMatrix3x2fvEXT = (PFNGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC) load(userptr, "glProgramUniformMatrix3x2fvEXT");
+ glad_glProgramUniformMatrix3x4fvEXT = (PFNGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC) load(userptr, "glProgramUniformMatrix3x4fvEXT");
+ glad_glProgramUniformMatrix4fvEXT = (PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC) load(userptr, "glProgramUniformMatrix4fvEXT");
+ glad_glProgramUniformMatrix4x2fvEXT = (PFNGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC) load(userptr, "glProgramUniformMatrix4x2fvEXT");
+ glad_glProgramUniformMatrix4x3fvEXT = (PFNGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC) load(userptr, "glProgramUniformMatrix4x3fvEXT");
+ glad_glUseProgramStagesEXT = (PFNGLUSEPROGRAMSTAGESEXTPROC) load(userptr, "glUseProgramStagesEXT");
+ glad_glValidateProgramPipelineEXT = (PFNGLVALIDATEPROGRAMPIPELINEEXTPROC) load(userptr, "glValidateProgramPipelineEXT");
+}
+static void glad_gl_load_GL_EXT_shader_framebuffer_fetch_non_coherent( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_shader_framebuffer_fetch_non_coherent) return;
+ glad_glFramebufferFetchBarrierEXT = (PFNGLFRAMEBUFFERFETCHBARRIEREXTPROC) load(userptr, "glFramebufferFetchBarrierEXT");
+}
+static void glad_gl_load_GL_EXT_shader_pixel_local_storage2( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_shader_pixel_local_storage2) return;
+ glad_glClearPixelLocalStorageuiEXT = (PFNGLCLEARPIXELLOCALSTORAGEUIEXTPROC) load(userptr, "glClearPixelLocalStorageuiEXT");
+ glad_glFramebufferPixelLocalStorageSizeEXT = (PFNGLFRAMEBUFFERPIXELLOCALSTORAGESIZEEXTPROC) load(userptr, "glFramebufferPixelLocalStorageSizeEXT");
+ glad_glGetFramebufferPixelLocalStorageSizeEXT = (PFNGLGETFRAMEBUFFERPIXELLOCALSTORAGESIZEEXTPROC) load(userptr, "glGetFramebufferPixelLocalStorageSizeEXT");
+}
+static void glad_gl_load_GL_EXT_sparse_texture( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_sparse_texture) return;
+ glad_glTexPageCommitmentEXT = (PFNGLTEXPAGECOMMITMENTEXTPROC) load(userptr, "glTexPageCommitmentEXT");
+}
+static void glad_gl_load_GL_EXT_tessellation_shader( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_tessellation_shader) return;
+ glad_glPatchParameteriEXT = (PFNGLPATCHPARAMETERIEXTPROC) load(userptr, "glPatchParameteriEXT");
+}
+static void glad_gl_load_GL_EXT_texture_border_clamp( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_texture_border_clamp) return;
+ glad_glGetSamplerParameterIivEXT = (PFNGLGETSAMPLERPARAMETERIIVEXTPROC) load(userptr, "glGetSamplerParameterIivEXT");
+ glad_glGetSamplerParameterIuivEXT = (PFNGLGETSAMPLERPARAMETERIUIVEXTPROC) load(userptr, "glGetSamplerParameterIuivEXT");
+ glad_glGetTexParameterIivEXT = (PFNGLGETTEXPARAMETERIIVEXTPROC) load(userptr, "glGetTexParameterIivEXT");
+ glad_glGetTexParameterIuivEXT = (PFNGLGETTEXPARAMETERIUIVEXTPROC) load(userptr, "glGetTexParameterIuivEXT");
+ glad_glSamplerParameterIivEXT = (PFNGLSAMPLERPARAMETERIIVEXTPROC) load(userptr, "glSamplerParameterIivEXT");
+ glad_glSamplerParameterIuivEXT = (PFNGLSAMPLERPARAMETERIUIVEXTPROC) load(userptr, "glSamplerParameterIuivEXT");
+ glad_glTexParameterIivEXT = (PFNGLTEXPARAMETERIIVEXTPROC) load(userptr, "glTexParameterIivEXT");
+ glad_glTexParameterIuivEXT = (PFNGLTEXPARAMETERIUIVEXTPROC) load(userptr, "glTexParameterIuivEXT");
+}
+static void glad_gl_load_GL_EXT_texture_buffer( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_texture_buffer) return;
+ glad_glTexBufferEXT = (PFNGLTEXBUFFEREXTPROC) load(userptr, "glTexBufferEXT");
+ glad_glTexBufferRangeEXT = (PFNGLTEXBUFFERRANGEEXTPROC) load(userptr, "glTexBufferRangeEXT");
+}
+static void glad_gl_load_GL_EXT_texture_storage( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_texture_storage) return;
+ glad_glTexStorage1DEXT = (PFNGLTEXSTORAGE1DEXTPROC) load(userptr, "glTexStorage1DEXT");
+ glad_glTexStorage2DEXT = (PFNGLTEXSTORAGE2DEXTPROC) load(userptr, "glTexStorage2DEXT");
+ glad_glTexStorage3DEXT = (PFNGLTEXSTORAGE3DEXTPROC) load(userptr, "glTexStorage3DEXT");
+ glad_glTextureStorage1DEXT = (PFNGLTEXTURESTORAGE1DEXTPROC) load(userptr, "glTextureStorage1DEXT");
+ glad_glTextureStorage2DEXT = (PFNGLTEXTURESTORAGE2DEXTPROC) load(userptr, "glTextureStorage2DEXT");
+ glad_glTextureStorage3DEXT = (PFNGLTEXTURESTORAGE3DEXTPROC) load(userptr, "glTextureStorage3DEXT");
+}
+static void glad_gl_load_GL_EXT_texture_storage_compression( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_texture_storage_compression) return;
+ glad_glTexStorageAttribs2DEXT = (PFNGLTEXSTORAGEATTRIBS2DEXTPROC) load(userptr, "glTexStorageAttribs2DEXT");
+ glad_glTexStorageAttribs3DEXT = (PFNGLTEXSTORAGEATTRIBS3DEXTPROC) load(userptr, "glTexStorageAttribs3DEXT");
+}
+static void glad_gl_load_GL_EXT_texture_view( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_texture_view) return;
+ glad_glTextureViewEXT = (PFNGLTEXTUREVIEWEXTPROC) load(userptr, "glTextureViewEXT");
+}
+static void glad_gl_load_GL_EXT_win32_keyed_mutex( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_win32_keyed_mutex) return;
+ glad_glAcquireKeyedMutexWin32EXT = (PFNGLACQUIREKEYEDMUTEXWIN32EXTPROC) load(userptr, "glAcquireKeyedMutexWin32EXT");
+ glad_glReleaseKeyedMutexWin32EXT = (PFNGLRELEASEKEYEDMUTEXWIN32EXTPROC) load(userptr, "glReleaseKeyedMutexWin32EXT");
+}
+static void glad_gl_load_GL_EXT_window_rectangles( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_EXT_window_rectangles) return;
+ glad_glWindowRectanglesEXT = (PFNGLWINDOWRECTANGLESEXTPROC) load(userptr, "glWindowRectanglesEXT");
+}
+static void glad_gl_load_GL_KHR_blend_equation_advanced( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_KHR_blend_equation_advanced) return;
+ glad_glBlendBarrierKHR = (PFNGLBLENDBARRIERKHRPROC) load(userptr, "glBlendBarrierKHR");
+}
+static void glad_gl_load_GL_KHR_debug( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_KHR_debug) return;
+ glad_glDebugMessageCallbackKHR = (PFNGLDEBUGMESSAGECALLBACKKHRPROC) load(userptr, "glDebugMessageCallbackKHR");
+ glad_glDebugMessageControlKHR = (PFNGLDEBUGMESSAGECONTROLKHRPROC) load(userptr, "glDebugMessageControlKHR");
+ glad_glDebugMessageInsertKHR = (PFNGLDEBUGMESSAGEINSERTKHRPROC) load(userptr, "glDebugMessageInsertKHR");
+ glad_glGetDebugMessageLogKHR = (PFNGLGETDEBUGMESSAGELOGKHRPROC) load(userptr, "glGetDebugMessageLogKHR");
+ glad_glGetObjectLabelKHR = (PFNGLGETOBJECTLABELKHRPROC) load(userptr, "glGetObjectLabelKHR");
+ glad_glGetObjectPtrLabelKHR = (PFNGLGETOBJECTPTRLABELKHRPROC) load(userptr, "glGetObjectPtrLabelKHR");
+ glad_glGetPointervKHR = (PFNGLGETPOINTERVKHRPROC) load(userptr, "glGetPointervKHR");
+ glad_glObjectLabelKHR = (PFNGLOBJECTLABELKHRPROC) load(userptr, "glObjectLabelKHR");
+ glad_glObjectPtrLabelKHR = (PFNGLOBJECTPTRLABELKHRPROC) load(userptr, "glObjectPtrLabelKHR");
+ glad_glPopDebugGroupKHR = (PFNGLPOPDEBUGGROUPKHRPROC) load(userptr, "glPopDebugGroupKHR");
+ glad_glPushDebugGroupKHR = (PFNGLPUSHDEBUGGROUPKHRPROC) load(userptr, "glPushDebugGroupKHR");
+}
+static void glad_gl_load_GL_KHR_parallel_shader_compile( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_KHR_parallel_shader_compile) return;
+ glad_glMaxShaderCompilerThreadsKHR = (PFNGLMAXSHADERCOMPILERTHREADSKHRPROC) load(userptr, "glMaxShaderCompilerThreadsKHR");
+}
+static void glad_gl_load_GL_KHR_robustness( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_KHR_robustness) return;
+ glad_glGetGraphicsResetStatusKHR = (PFNGLGETGRAPHICSRESETSTATUSKHRPROC) load(userptr, "glGetGraphicsResetStatusKHR");
+ glad_glGetnUniformfvKHR = (PFNGLGETNUNIFORMFVKHRPROC) load(userptr, "glGetnUniformfvKHR");
+ glad_glGetnUniformivKHR = (PFNGLGETNUNIFORMIVKHRPROC) load(userptr, "glGetnUniformivKHR");
+ glad_glGetnUniformuivKHR = (PFNGLGETNUNIFORMUIVKHRPROC) load(userptr, "glGetnUniformuivKHR");
+ glad_glReadnPixelsKHR = (PFNGLREADNPIXELSKHRPROC) load(userptr, "glReadnPixelsKHR");
+}
+static void glad_gl_load_GL_OES_EGL_image( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_OES_EGL_image) return;
+ glad_glEGLImageTargetRenderbufferStorageOES = (PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) load(userptr, "glEGLImageTargetRenderbufferStorageOES");
+ glad_glEGLImageTargetTexture2DOES = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) load(userptr, "glEGLImageTargetTexture2DOES");
+}
+static void glad_gl_load_GL_OES_copy_image( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_OES_copy_image) return;
+ glad_glCopyImageSubDataOES = (PFNGLCOPYIMAGESUBDATAOESPROC) load(userptr, "glCopyImageSubDataOES");
+}
+static void glad_gl_load_GL_OES_draw_buffers_indexed( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_OES_draw_buffers_indexed) return;
+ glad_glBlendEquationSeparateiOES = (PFNGLBLENDEQUATIONSEPARATEIOESPROC) load(userptr, "glBlendEquationSeparateiOES");
+ glad_glBlendEquationiOES = (PFNGLBLENDEQUATIONIOESPROC) load(userptr, "glBlendEquationiOES");
+ glad_glBlendFuncSeparateiOES = (PFNGLBLENDFUNCSEPARATEIOESPROC) load(userptr, "glBlendFuncSeparateiOES");
+ glad_glBlendFunciOES = (PFNGLBLENDFUNCIOESPROC) load(userptr, "glBlendFunciOES");
+ glad_glColorMaskiOES = (PFNGLCOLORMASKIOESPROC) load(userptr, "glColorMaskiOES");
+ glad_glDisableiOES = (PFNGLDISABLEIOESPROC) load(userptr, "glDisableiOES");
+ glad_glEnableiOES = (PFNGLENABLEIOESPROC) load(userptr, "glEnableiOES");
+ glad_glIsEnablediOES = (PFNGLISENABLEDIOESPROC) load(userptr, "glIsEnablediOES");
+}
+static void glad_gl_load_GL_OES_draw_elements_base_vertex( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_OES_draw_elements_base_vertex) return;
+ glad_glDrawElementsBaseVertexOES = (PFNGLDRAWELEMENTSBASEVERTEXOESPROC) load(userptr, "glDrawElementsBaseVertexOES");
+ glad_glDrawElementsInstancedBaseVertexOES = (PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXOESPROC) load(userptr, "glDrawElementsInstancedBaseVertexOES");
+ glad_glDrawRangeElementsBaseVertexOES = (PFNGLDRAWRANGEELEMENTSBASEVERTEXOESPROC) load(userptr, "glDrawRangeElementsBaseVertexOES");
+ glad_glMultiDrawElementsBaseVertexEXT = (PFNGLMULTIDRAWELEMENTSBASEVERTEXEXTPROC) load(userptr, "glMultiDrawElementsBaseVertexEXT");
+}
+static void glad_gl_load_GL_OES_geometry_shader( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_OES_geometry_shader) return;
+ glad_glFramebufferTextureOES = (PFNGLFRAMEBUFFERTEXTUREOESPROC) load(userptr, "glFramebufferTextureOES");
+}
+static void glad_gl_load_GL_OES_get_program_binary( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_OES_get_program_binary) return;
+ glad_glGetProgramBinaryOES = (PFNGLGETPROGRAMBINARYOESPROC) load(userptr, "glGetProgramBinaryOES");
+ glad_glProgramBinaryOES = (PFNGLPROGRAMBINARYOESPROC) load(userptr, "glProgramBinaryOES");
+}
+static void glad_gl_load_GL_OES_mapbuffer( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_OES_mapbuffer) return;
+ glad_glGetBufferPointervOES = (PFNGLGETBUFFERPOINTERVOESPROC) load(userptr, "glGetBufferPointervOES");
+ glad_glMapBufferOES = (PFNGLMAPBUFFEROESPROC) load(userptr, "glMapBufferOES");
+ glad_glUnmapBufferOES = (PFNGLUNMAPBUFFEROESPROC) load(userptr, "glUnmapBufferOES");
+}
+static void glad_gl_load_GL_OES_primitive_bounding_box( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_OES_primitive_bounding_box) return;
+ glad_glPrimitiveBoundingBoxOES = (PFNGLPRIMITIVEBOUNDINGBOXOESPROC) load(userptr, "glPrimitiveBoundingBoxOES");
+}
+static void glad_gl_load_GL_OES_sample_shading( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_OES_sample_shading) return;
+ glad_glMinSampleShadingOES = (PFNGLMINSAMPLESHADINGOESPROC) load(userptr, "glMinSampleShadingOES");
+}
+static void glad_gl_load_GL_OES_tessellation_shader( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_OES_tessellation_shader) return;
+ glad_glPatchParameteriOES = (PFNGLPATCHPARAMETERIOESPROC) load(userptr, "glPatchParameteriOES");
+}
+static void glad_gl_load_GL_OES_texture_3D( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_OES_texture_3D) return;
+ glad_glCompressedTexImage3DOES = (PFNGLCOMPRESSEDTEXIMAGE3DOESPROC) load(userptr, "glCompressedTexImage3DOES");
+ glad_glCompressedTexSubImage3DOES = (PFNGLCOMPRESSEDTEXSUBIMAGE3DOESPROC) load(userptr, "glCompressedTexSubImage3DOES");
+ glad_glCopyTexSubImage3DOES = (PFNGLCOPYTEXSUBIMAGE3DOESPROC) load(userptr, "glCopyTexSubImage3DOES");
+ glad_glFramebufferTexture3DOES = (PFNGLFRAMEBUFFERTEXTURE3DOESPROC) load(userptr, "glFramebufferTexture3DOES");
+ glad_glTexImage3DOES = (PFNGLTEXIMAGE3DOESPROC) load(userptr, "glTexImage3DOES");
+ glad_glTexSubImage3DOES = (PFNGLTEXSUBIMAGE3DOESPROC) load(userptr, "glTexSubImage3DOES");
+}
+static void glad_gl_load_GL_OES_texture_border_clamp( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_OES_texture_border_clamp) return;
+ glad_glGetSamplerParameterIivOES = (PFNGLGETSAMPLERPARAMETERIIVOESPROC) load(userptr, "glGetSamplerParameterIivOES");
+ glad_glGetSamplerParameterIuivOES = (PFNGLGETSAMPLERPARAMETERIUIVOESPROC) load(userptr, "glGetSamplerParameterIuivOES");
+ glad_glGetTexParameterIivOES = (PFNGLGETTEXPARAMETERIIVOESPROC) load(userptr, "glGetTexParameterIivOES");
+ glad_glGetTexParameterIuivOES = (PFNGLGETTEXPARAMETERIUIVOESPROC) load(userptr, "glGetTexParameterIuivOES");
+ glad_glSamplerParameterIivOES = (PFNGLSAMPLERPARAMETERIIVOESPROC) load(userptr, "glSamplerParameterIivOES");
+ glad_glSamplerParameterIuivOES = (PFNGLSAMPLERPARAMETERIUIVOESPROC) load(userptr, "glSamplerParameterIuivOES");
+ glad_glTexParameterIivOES = (PFNGLTEXPARAMETERIIVOESPROC) load(userptr, "glTexParameterIivOES");
+ glad_glTexParameterIuivOES = (PFNGLTEXPARAMETERIUIVOESPROC) load(userptr, "glTexParameterIuivOES");
+}
+static void glad_gl_load_GL_OES_texture_buffer( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_OES_texture_buffer) return;
+ glad_glTexBufferOES = (PFNGLTEXBUFFEROESPROC) load(userptr, "glTexBufferOES");
+ glad_glTexBufferRangeOES = (PFNGLTEXBUFFERRANGEOESPROC) load(userptr, "glTexBufferRangeOES");
+}
+static void glad_gl_load_GL_OES_texture_storage_multisample_2d_array( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_OES_texture_storage_multisample_2d_array) return;
+ glad_glTexStorage3DMultisampleOES = (PFNGLTEXSTORAGE3DMULTISAMPLEOESPROC) load(userptr, "glTexStorage3DMultisampleOES");
+}
+static void glad_gl_load_GL_OES_texture_view( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_OES_texture_view) return;
+ glad_glTextureViewOES = (PFNGLTEXTUREVIEWOESPROC) load(userptr, "glTextureViewOES");
+}
+static void glad_gl_load_GL_OES_vertex_array_object( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_OES_vertex_array_object) return;
+ glad_glBindVertexArrayOES = (PFNGLBINDVERTEXARRAYOESPROC) load(userptr, "glBindVertexArrayOES");
+ glad_glDeleteVertexArraysOES = (PFNGLDELETEVERTEXARRAYSOESPROC) load(userptr, "glDeleteVertexArraysOES");
+ glad_glGenVertexArraysOES = (PFNGLGENVERTEXARRAYSOESPROC) load(userptr, "glGenVertexArraysOES");
+ glad_glIsVertexArrayOES = (PFNGLISVERTEXARRAYOESPROC) load(userptr, "glIsVertexArrayOES");
+}
+static void glad_gl_load_GL_OES_viewport_array( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_OES_viewport_array) return;
+ glad_glDepthRangeArrayfvOES = (PFNGLDEPTHRANGEARRAYFVOESPROC) load(userptr, "glDepthRangeArrayfvOES");
+ glad_glDepthRangeIndexedfOES = (PFNGLDEPTHRANGEINDEXEDFOESPROC) load(userptr, "glDepthRangeIndexedfOES");
+ glad_glDisableiOES = (PFNGLDISABLEIOESPROC) load(userptr, "glDisableiOES");
+ glad_glEnableiOES = (PFNGLENABLEIOESPROC) load(userptr, "glEnableiOES");
+ glad_glGetFloati_vOES = (PFNGLGETFLOATI_VOESPROC) load(userptr, "glGetFloati_vOES");
+ glad_glIsEnablediOES = (PFNGLISENABLEDIOESPROC) load(userptr, "glIsEnablediOES");
+ glad_glScissorArrayvOES = (PFNGLSCISSORARRAYVOESPROC) load(userptr, "glScissorArrayvOES");
+ glad_glScissorIndexedOES = (PFNGLSCISSORINDEXEDOESPROC) load(userptr, "glScissorIndexedOES");
+ glad_glScissorIndexedvOES = (PFNGLSCISSORINDEXEDVOESPROC) load(userptr, "glScissorIndexedvOES");
+ glad_glViewportArrayvOES = (PFNGLVIEWPORTARRAYVOESPROC) load(userptr, "glViewportArrayvOES");
+ glad_glViewportIndexedfOES = (PFNGLVIEWPORTINDEXEDFOESPROC) load(userptr, "glViewportIndexedfOES");
+ glad_glViewportIndexedfvOES = (PFNGLVIEWPORTINDEXEDFVOESPROC) load(userptr, "glViewportIndexedfvOES");
+}
+
+
+
+#if defined(GL_ES_VERSION_3_0) || defined(GL_VERSION_3_0)
+#define GLAD_GL_IS_SOME_NEW_VERSION 1
+#else
+#define GLAD_GL_IS_SOME_NEW_VERSION 0
+#endif
+
+static int glad_gl_get_extensions( int version, const char **out_exts, unsigned int *out_num_exts_i, char ***out_exts_i) {
+#if GLAD_GL_IS_SOME_NEW_VERSION
+ if(GLAD_VERSION_MAJOR(version) < 3) {
+#else
+ GLAD_UNUSED(version);
+ GLAD_UNUSED(out_num_exts_i);
+ GLAD_UNUSED(out_exts_i);
+#endif
+ if (glad_glGetString == NULL) {
+ return 0;
+ }
+ *out_exts = (const char *)glad_glGetString(GL_EXTENSIONS);
+#if GLAD_GL_IS_SOME_NEW_VERSION
+ } else {
+ unsigned int index = 0;
+ unsigned int num_exts_i = 0;
+ char **exts_i = NULL;
+ if (glad_glGetStringi == NULL || glad_glGetIntegerv == NULL) {
+ return 0;
+ }
+ glad_glGetIntegerv(GL_NUM_EXTENSIONS, (int*) &num_exts_i);
+ if (num_exts_i > 0) {
+ exts_i = (char **) malloc(num_exts_i * (sizeof *exts_i));
+ }
+ if (exts_i == NULL) {
+ return 0;
+ }
+ for(index = 0; index < num_exts_i; index++) {
+ const char *gl_str_tmp = (const char*) glad_glGetStringi(GL_EXTENSIONS, index);
+ size_t len = strlen(gl_str_tmp) + 1;
+
+ char *local_str = (char*) malloc(len * sizeof(char));
+ if(local_str != NULL) {
+ memcpy(local_str, gl_str_tmp, len * sizeof(char));
+ }
+
+ exts_i[index] = local_str;
+ }
+
+ *out_num_exts_i = num_exts_i;
+ *out_exts_i = exts_i;
+ }
+#endif
+ return 1;
+}
+static void glad_gl_free_extensions(char **exts_i, unsigned int num_exts_i) {
+ if (exts_i != NULL) {
+ unsigned int index;
+ for(index = 0; index < num_exts_i; index++) {
+ free((void *) (exts_i[index]));
+ }
+ free((void *)exts_i);
+ exts_i = NULL;
+ }
+}
+static int glad_gl_has_extension(int version, const char *exts, unsigned int num_exts_i, char **exts_i, const char *ext) {
+ if(GLAD_VERSION_MAJOR(version) < 3 || !GLAD_GL_IS_SOME_NEW_VERSION) {
+ const char *extensions;
+ const char *loc;
+ const char *terminator;
+ extensions = exts;
+ if(extensions == NULL || ext == NULL) {
+ return 0;
+ }
+ while(1) {
+ loc = strstr(extensions, ext);
+ if(loc == NULL) {
+ return 0;
+ }
+ terminator = loc + strlen(ext);
+ if((loc == extensions || *(loc - 1) == ' ') &&
+ (*terminator == ' ' || *terminator == '\0')) {
+ return 1;
+ }
+ extensions = terminator;
+ }
+ } else {
+ unsigned int index;
+ for(index = 0; index < num_exts_i; index++) {
+ const char *e = exts_i[index];
+ if(strcmp(e, ext) == 0) {
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+static GLADapiproc glad_gl_get_proc_from_userptr(void *userptr, const char* name) {
+ return (GLAD_GNUC_EXTENSION (GLADapiproc (*)(const char *name)) userptr)(name);
+}
+
+static int glad_gl_find_extensions_gles2( int version) {
+ const char *exts = NULL;
+ unsigned int num_exts_i = 0;
+ char **exts_i = NULL;
+ if (!glad_gl_get_extensions(version, &exts, &num_exts_i, &exts_i)) return 0;
+
+ GLAD_GL_EXT_EGL_image_array = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_EGL_image_array");
+ GLAD_GL_EXT_EGL_image_storage = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_EGL_image_storage");
+ GLAD_GL_EXT_EGL_image_storage_compression = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_EGL_image_storage_compression");
+ GLAD_GL_EXT_YUV_target = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_YUV_target");
+ GLAD_GL_EXT_base_instance = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_base_instance");
+ GLAD_GL_EXT_blend_func_extended = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_blend_func_extended");
+ GLAD_GL_EXT_blend_minmax = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_blend_minmax");
+ GLAD_GL_EXT_buffer_storage = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_buffer_storage");
+ GLAD_GL_EXT_clear_texture = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_clear_texture");
+ GLAD_GL_EXT_clip_control = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_clip_control");
+ GLAD_GL_EXT_clip_cull_distance = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_clip_cull_distance");
+ GLAD_GL_EXT_color_buffer_float = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_color_buffer_float");
+ GLAD_GL_EXT_color_buffer_half_float = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_color_buffer_half_float");
+ GLAD_GL_EXT_conservative_depth = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_conservative_depth");
+ GLAD_GL_EXT_copy_image = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_copy_image");
+ GLAD_GL_EXT_debug_label = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_debug_label");
+ GLAD_GL_EXT_debug_marker = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_debug_marker");
+ GLAD_GL_EXT_depth_clamp = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_depth_clamp");
+ GLAD_GL_EXT_discard_framebuffer = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_discard_framebuffer");
+ GLAD_GL_EXT_disjoint_timer_query = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_disjoint_timer_query");
+ GLAD_GL_EXT_draw_buffers = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_draw_buffers");
+ GLAD_GL_EXT_draw_buffers_indexed = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_draw_buffers_indexed");
+ GLAD_GL_EXT_draw_elements_base_vertex = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_draw_elements_base_vertex");
+ GLAD_GL_EXT_draw_instanced = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_draw_instanced");
+ GLAD_GL_EXT_draw_transform_feedback = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_draw_transform_feedback");
+ GLAD_GL_EXT_external_buffer = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_external_buffer");
+ GLAD_GL_EXT_float_blend = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_float_blend");
+ GLAD_GL_EXT_fragment_shading_rate = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_fragment_shading_rate");
+ GLAD_GL_EXT_geometry_point_size = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_geometry_point_size");
+ GLAD_GL_EXT_geometry_shader = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_geometry_shader");
+ GLAD_GL_EXT_gpu_shader5 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_gpu_shader5");
+ GLAD_GL_EXT_instanced_arrays = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_instanced_arrays");
+ GLAD_GL_EXT_map_buffer_range = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_map_buffer_range");
+ GLAD_GL_EXT_memory_object = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_memory_object");
+ GLAD_GL_EXT_memory_object_fd = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_memory_object_fd");
+ GLAD_GL_EXT_memory_object_win32 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_memory_object_win32");
+ GLAD_GL_EXT_multi_draw_arrays = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_multi_draw_arrays");
+ GLAD_GL_EXT_multi_draw_indirect = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_multi_draw_indirect");
+ GLAD_GL_EXT_multisampled_compatibility = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_multisampled_compatibility");
+ GLAD_GL_EXT_multisampled_render_to_texture = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_multisampled_render_to_texture");
+ GLAD_GL_EXT_multisampled_render_to_texture2 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_multisampled_render_to_texture2");
+ GLAD_GL_EXT_multiview_draw_buffers = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_multiview_draw_buffers");
+ GLAD_GL_EXT_multiview_tessellation_geometry_shader = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_multiview_tessellation_geometry_shader");
+ GLAD_GL_EXT_multiview_texture_multisample = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_multiview_texture_multisample");
+ GLAD_GL_EXT_multiview_timer_query = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_multiview_timer_query");
+ GLAD_GL_EXT_occlusion_query_boolean = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_occlusion_query_boolean");
+ GLAD_GL_EXT_polygon_offset_clamp = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_polygon_offset_clamp");
+ GLAD_GL_EXT_post_depth_coverage = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_post_depth_coverage");
+ GLAD_GL_EXT_primitive_bounding_box = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_primitive_bounding_box");
+ GLAD_GL_EXT_protected_textures = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_protected_textures");
+ GLAD_GL_EXT_pvrtc_sRGB = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_pvrtc_sRGB");
+ GLAD_GL_EXT_raster_multisample = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_raster_multisample");
+ GLAD_GL_EXT_read_format_bgra = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_read_format_bgra");
+ GLAD_GL_EXT_render_snorm = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_render_snorm");
+ GLAD_GL_EXT_robustness = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_robustness");
+ GLAD_GL_EXT_sRGB = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_sRGB");
+ GLAD_GL_EXT_sRGB_write_control = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_sRGB_write_control");
+ GLAD_GL_EXT_semaphore = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_semaphore");
+ GLAD_GL_EXT_semaphore_fd = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_semaphore_fd");
+ GLAD_GL_EXT_semaphore_win32 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_semaphore_win32");
+ GLAD_GL_EXT_separate_depth_stencil = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_separate_depth_stencil");
+ GLAD_GL_EXT_separate_shader_objects = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_separate_shader_objects");
+ GLAD_GL_EXT_shader_framebuffer_fetch = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_shader_framebuffer_fetch");
+ GLAD_GL_EXT_shader_framebuffer_fetch_non_coherent = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_shader_framebuffer_fetch_non_coherent");
+ GLAD_GL_EXT_shader_group_vote = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_shader_group_vote");
+ GLAD_GL_EXT_shader_implicit_conversions = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_shader_implicit_conversions");
+ GLAD_GL_EXT_shader_integer_mix = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_shader_integer_mix");
+ GLAD_GL_EXT_shader_io_blocks = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_shader_io_blocks");
+ GLAD_GL_EXT_shader_non_constant_global_initializers = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_shader_non_constant_global_initializers");
+ GLAD_GL_EXT_shader_pixel_local_storage = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_shader_pixel_local_storage");
+ GLAD_GL_EXT_shader_pixel_local_storage2 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_shader_pixel_local_storage2");
+ GLAD_GL_EXT_shader_samples_identical = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_shader_samples_identical");
+ GLAD_GL_EXT_shader_texture_lod = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_shader_texture_lod");
+ GLAD_GL_EXT_shadow_samplers = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_shadow_samplers");
+ GLAD_GL_EXT_sparse_texture = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_sparse_texture");
+ GLAD_GL_EXT_sparse_texture2 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_sparse_texture2");
+ GLAD_GL_EXT_tessellation_point_size = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_tessellation_point_size");
+ GLAD_GL_EXT_tessellation_shader = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_tessellation_shader");
+ GLAD_GL_EXT_texture_border_clamp = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_border_clamp");
+ GLAD_GL_EXT_texture_buffer = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_buffer");
+ GLAD_GL_EXT_texture_compression_astc_decode_mode = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_compression_astc_decode_mode");
+ GLAD_GL_EXT_texture_compression_bptc = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_compression_bptc");
+ GLAD_GL_EXT_texture_compression_dxt1 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_compression_dxt1");
+ GLAD_GL_EXT_texture_compression_rgtc = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_compression_rgtc");
+ GLAD_GL_EXT_texture_compression_s3tc = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_compression_s3tc");
+ GLAD_GL_EXT_texture_compression_s3tc_srgb = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_compression_s3tc_srgb");
+ GLAD_GL_EXT_texture_cube_map_array = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_cube_map_array");
+ GLAD_GL_EXT_texture_filter_anisotropic = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_filter_anisotropic");
+ GLAD_GL_EXT_texture_filter_minmax = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_filter_minmax");
+ GLAD_GL_EXT_texture_format_BGRA8888 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_format_BGRA8888");
+ GLAD_GL_EXT_texture_format_sRGB_override = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_format_sRGB_override");
+ GLAD_GL_EXT_texture_mirror_clamp_to_edge = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_mirror_clamp_to_edge");
+ GLAD_GL_EXT_texture_norm16 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_norm16");
+ GLAD_GL_EXT_texture_query_lod = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_query_lod");
+ GLAD_GL_EXT_texture_rg = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_rg");
+ GLAD_GL_EXT_texture_sRGB_R8 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_sRGB_R8");
+ GLAD_GL_EXT_texture_sRGB_RG8 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_sRGB_RG8");
+ GLAD_GL_EXT_texture_sRGB_decode = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_sRGB_decode");
+ GLAD_GL_EXT_texture_shadow_lod = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_shadow_lod");
+ GLAD_GL_EXT_texture_storage = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_storage");
+ GLAD_GL_EXT_texture_storage_compression = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_storage_compression");
+ GLAD_GL_EXT_texture_type_2_10_10_10_REV = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_type_2_10_10_10_REV");
+ GLAD_GL_EXT_texture_view = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_texture_view");
+ GLAD_GL_EXT_unpack_subimage = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_unpack_subimage");
+ GLAD_GL_EXT_win32_keyed_mutex = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_win32_keyed_mutex");
+ GLAD_GL_EXT_window_rectangles = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_EXT_window_rectangles");
+ GLAD_GL_KHR_blend_equation_advanced = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_KHR_blend_equation_advanced");
+ GLAD_GL_KHR_blend_equation_advanced_coherent = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_KHR_blend_equation_advanced_coherent");
+ GLAD_GL_KHR_context_flush_control = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_KHR_context_flush_control");
+ GLAD_GL_KHR_debug = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_KHR_debug");
+ GLAD_GL_KHR_no_error = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_KHR_no_error");
+ GLAD_GL_KHR_parallel_shader_compile = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_KHR_parallel_shader_compile");
+ GLAD_GL_KHR_robust_buffer_access_behavior = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_KHR_robust_buffer_access_behavior");
+ GLAD_GL_KHR_robustness = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_KHR_robustness");
+ GLAD_GL_KHR_shader_subgroup = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_KHR_shader_subgroup");
+ GLAD_GL_KHR_texture_compression_astc_hdr = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_KHR_texture_compression_astc_hdr");
+ GLAD_GL_KHR_texture_compression_astc_ldr = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_KHR_texture_compression_astc_ldr");
+ GLAD_GL_KHR_texture_compression_astc_sliced_3d = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_KHR_texture_compression_astc_sliced_3d");
+ GLAD_GL_OES_EGL_image = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_EGL_image");
+ GLAD_GL_OES_EGL_image_external = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_EGL_image_external");
+ GLAD_GL_OES_EGL_image_external_essl3 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_EGL_image_external_essl3");
+ GLAD_GL_OES_compressed_ETC1_RGB8_sub_texture = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_compressed_ETC1_RGB8_sub_texture");
+ GLAD_GL_OES_compressed_ETC1_RGB8_texture = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_compressed_ETC1_RGB8_texture");
+ GLAD_GL_OES_compressed_paletted_texture = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_compressed_paletted_texture");
+ GLAD_GL_OES_copy_image = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_copy_image");
+ GLAD_GL_OES_depth24 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_depth24");
+ GLAD_GL_OES_depth32 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_depth32");
+ GLAD_GL_OES_depth_texture = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_depth_texture");
+ GLAD_GL_OES_draw_buffers_indexed = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_draw_buffers_indexed");
+ GLAD_GL_OES_draw_elements_base_vertex = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_draw_elements_base_vertex");
+ GLAD_GL_OES_element_index_uint = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_element_index_uint");
+ GLAD_GL_OES_fbo_render_mipmap = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_fbo_render_mipmap");
+ GLAD_GL_OES_fragment_precision_high = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_fragment_precision_high");
+ GLAD_GL_OES_geometry_point_size = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_geometry_point_size");
+ GLAD_GL_OES_geometry_shader = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_geometry_shader");
+ GLAD_GL_OES_get_program_binary = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_get_program_binary");
+ GLAD_GL_OES_gpu_shader5 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_gpu_shader5");
+ GLAD_GL_OES_mapbuffer = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_mapbuffer");
+ GLAD_GL_OES_packed_depth_stencil = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_packed_depth_stencil");
+ GLAD_GL_OES_primitive_bounding_box = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_primitive_bounding_box");
+ GLAD_GL_OES_required_internalformat = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_required_internalformat");
+ GLAD_GL_OES_rgb8_rgba8 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_rgb8_rgba8");
+ GLAD_GL_OES_sample_shading = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_sample_shading");
+ GLAD_GL_OES_sample_variables = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_sample_variables");
+ GLAD_GL_OES_shader_image_atomic = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_shader_image_atomic");
+ GLAD_GL_OES_shader_io_blocks = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_shader_io_blocks");
+ GLAD_GL_OES_shader_multisample_interpolation = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_shader_multisample_interpolation");
+ GLAD_GL_OES_standard_derivatives = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_standard_derivatives");
+ GLAD_GL_OES_stencil1 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_stencil1");
+ GLAD_GL_OES_stencil4 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_stencil4");
+ GLAD_GL_OES_surfaceless_context = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_surfaceless_context");
+ GLAD_GL_OES_tessellation_point_size = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_tessellation_point_size");
+ GLAD_GL_OES_tessellation_shader = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_tessellation_shader");
+ GLAD_GL_OES_texture_3D = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_texture_3D");
+ GLAD_GL_OES_texture_border_clamp = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_texture_border_clamp");
+ GLAD_GL_OES_texture_buffer = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_texture_buffer");
+ GLAD_GL_OES_texture_compression_astc = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_texture_compression_astc");
+ GLAD_GL_OES_texture_cube_map_array = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_texture_cube_map_array");
+ GLAD_GL_OES_texture_float = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_texture_float");
+ GLAD_GL_OES_texture_float_linear = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_texture_float_linear");
+ GLAD_GL_OES_texture_half_float = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_texture_half_float");
+ GLAD_GL_OES_texture_half_float_linear = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_texture_half_float_linear");
+ GLAD_GL_OES_texture_npot = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_texture_npot");
+ GLAD_GL_OES_texture_stencil8 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_texture_stencil8");
+ GLAD_GL_OES_texture_storage_multisample_2d_array = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_texture_storage_multisample_2d_array");
+ GLAD_GL_OES_texture_view = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_texture_view");
+ GLAD_GL_OES_vertex_array_object = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_vertex_array_object");
+ GLAD_GL_OES_vertex_half_float = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_vertex_half_float");
+ GLAD_GL_OES_vertex_type_10_10_10_2 = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_vertex_type_10_10_10_2");
+ GLAD_GL_OES_viewport_array = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_OES_viewport_array");
+
+ glad_gl_free_extensions(exts_i, num_exts_i);
+
+ return 1;
+}
+
+static int glad_gl_find_core_gles2(void) {
+ int i;
+ const char* version;
+ const char* prefixes[] = {
+ "OpenGL ES-CM ",
+ "OpenGL ES-CL ",
+ "OpenGL ES ",
+ "OpenGL SC ",
+ NULL
+ };
+ int major = 0;
+ int minor = 0;
+ version = (const char*) glad_glGetString(GL_VERSION);
+ if (!version) return 0;
+ for (i = 0; prefixes[i]; i++) {
+ const size_t length = strlen(prefixes[i]);
+ if (strncmp(version, prefixes[i], length) == 0) {
+ version += length;
+ break;
+ }
+ }
+
+ GLAD_IMPL_UTIL_SSCANF(version, "%d.%d", &major, &minor);
+
+ GLAD_GL_ES_VERSION_2_0 = (major == 2 && minor >= 0) || major > 2;
+
+ return GLAD_MAKE_VERSION(major, minor);
+}
+
+int gladLoadGLES2UserPtr( GLADuserptrloadfunc load, void *userptr) {
+ int version;
+
+ glad_glGetString = (PFNGLGETSTRINGPROC) load(userptr, "glGetString");
+ if(glad_glGetString == NULL) return 0;
+ if(glad_glGetString(GL_VERSION) == NULL) return 0;
+ version = glad_gl_find_core_gles2();
+
+ glad_gl_load_GL_ES_VERSION_2_0(load, userptr);
+
+ if (!glad_gl_find_extensions_gles2(version)) return 0;
+ glad_gl_load_GL_EXT_EGL_image_storage(load, userptr);
+ glad_gl_load_GL_EXT_base_instance(load, userptr);
+ glad_gl_load_GL_EXT_blend_func_extended(load, userptr);
+ glad_gl_load_GL_EXT_buffer_storage(load, userptr);
+ glad_gl_load_GL_EXT_clear_texture(load, userptr);
+ glad_gl_load_GL_EXT_clip_control(load, userptr);
+ glad_gl_load_GL_EXT_copy_image(load, userptr);
+ glad_gl_load_GL_EXT_debug_label(load, userptr);
+ glad_gl_load_GL_EXT_debug_marker(load, userptr);
+ glad_gl_load_GL_EXT_discard_framebuffer(load, userptr);
+ glad_gl_load_GL_EXT_disjoint_timer_query(load, userptr);
+ glad_gl_load_GL_EXT_draw_buffers(load, userptr);
+ glad_gl_load_GL_EXT_draw_buffers_indexed(load, userptr);
+ glad_gl_load_GL_EXT_draw_elements_base_vertex(load, userptr);
+ glad_gl_load_GL_EXT_draw_instanced(load, userptr);
+ glad_gl_load_GL_EXT_draw_transform_feedback(load, userptr);
+ glad_gl_load_GL_EXT_external_buffer(load, userptr);
+ glad_gl_load_GL_EXT_fragment_shading_rate(load, userptr);
+ glad_gl_load_GL_EXT_geometry_shader(load, userptr);
+ glad_gl_load_GL_EXT_instanced_arrays(load, userptr);
+ glad_gl_load_GL_EXT_map_buffer_range(load, userptr);
+ glad_gl_load_GL_EXT_memory_object(load, userptr);
+ glad_gl_load_GL_EXT_memory_object_fd(load, userptr);
+ glad_gl_load_GL_EXT_memory_object_win32(load, userptr);
+ glad_gl_load_GL_EXT_multi_draw_arrays(load, userptr);
+ glad_gl_load_GL_EXT_multi_draw_indirect(load, userptr);
+ glad_gl_load_GL_EXT_multisampled_render_to_texture(load, userptr);
+ glad_gl_load_GL_EXT_multiview_draw_buffers(load, userptr);
+ glad_gl_load_GL_EXT_occlusion_query_boolean(load, userptr);
+ glad_gl_load_GL_EXT_polygon_offset_clamp(load, userptr);
+ glad_gl_load_GL_EXT_primitive_bounding_box(load, userptr);
+ glad_gl_load_GL_EXT_raster_multisample(load, userptr);
+ glad_gl_load_GL_EXT_robustness(load, userptr);
+ glad_gl_load_GL_EXT_semaphore(load, userptr);
+ glad_gl_load_GL_EXT_semaphore_fd(load, userptr);
+ glad_gl_load_GL_EXT_semaphore_win32(load, userptr);
+ glad_gl_load_GL_EXT_separate_shader_objects(load, userptr);
+ glad_gl_load_GL_EXT_shader_framebuffer_fetch_non_coherent(load, userptr);
+ glad_gl_load_GL_EXT_shader_pixel_local_storage2(load, userptr);
+ glad_gl_load_GL_EXT_sparse_texture(load, userptr);
+ glad_gl_load_GL_EXT_tessellation_shader(load, userptr);
+ glad_gl_load_GL_EXT_texture_border_clamp(load, userptr);
+ glad_gl_load_GL_EXT_texture_buffer(load, userptr);
+ glad_gl_load_GL_EXT_texture_storage(load, userptr);
+ glad_gl_load_GL_EXT_texture_storage_compression(load, userptr);
+ glad_gl_load_GL_EXT_texture_view(load, userptr);
+ glad_gl_load_GL_EXT_win32_keyed_mutex(load, userptr);
+ glad_gl_load_GL_EXT_window_rectangles(load, userptr);
+ glad_gl_load_GL_KHR_blend_equation_advanced(load, userptr);
+ glad_gl_load_GL_KHR_debug(load, userptr);
+ glad_gl_load_GL_KHR_parallel_shader_compile(load, userptr);
+ glad_gl_load_GL_KHR_robustness(load, userptr);
+ glad_gl_load_GL_OES_EGL_image(load, userptr);
+ glad_gl_load_GL_OES_copy_image(load, userptr);
+ glad_gl_load_GL_OES_draw_buffers_indexed(load, userptr);
+ glad_gl_load_GL_OES_draw_elements_base_vertex(load, userptr);
+ glad_gl_load_GL_OES_geometry_shader(load, userptr);
+ glad_gl_load_GL_OES_get_program_binary(load, userptr);
+ glad_gl_load_GL_OES_mapbuffer(load, userptr);
+ glad_gl_load_GL_OES_primitive_bounding_box(load, userptr);
+ glad_gl_load_GL_OES_sample_shading(load, userptr);
+ glad_gl_load_GL_OES_tessellation_shader(load, userptr);
+ glad_gl_load_GL_OES_texture_3D(load, userptr);
+ glad_gl_load_GL_OES_texture_border_clamp(load, userptr);
+ glad_gl_load_GL_OES_texture_buffer(load, userptr);
+ glad_gl_load_GL_OES_texture_storage_multisample_2d_array(load, userptr);
+ glad_gl_load_GL_OES_texture_view(load, userptr);
+ glad_gl_load_GL_OES_vertex_array_object(load, userptr);
+ glad_gl_load_GL_OES_viewport_array(load, userptr);
+
+
+
+ return version;
+}
+
+
+int gladLoadGLES2( GLADloadfunc load) {
+ return gladLoadGLES2UserPtr( glad_gl_get_proc_from_userptr, GLAD_GNUC_EXTENSION (void*) load);
+}
+
+
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GLAD_GLES2_IMPLEMENTATION */
+
diff --git a/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/glfw/LICENSE.md b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/glfw/LICENSE.md
new file mode 100644
index 0000000..7494a3f
--- /dev/null
+++ b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/glfw/LICENSE.md
@@ -0,0 +1,23 @@
+Copyright (c) 2002-2006 Marcus Geelnard
+
+Copyright (c) 2006-2019 Camilla Löwy
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would
+ be appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and must not
+ be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source
+ distribution.
+
diff --git a/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/glfw/include/GLFW/glfw3.h b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/glfw/include/GLFW/glfw3.h
new file mode 100644
index 0000000..9c55ac9
--- /dev/null
+++ b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/glfw/include/GLFW/glfw3.h
@@ -0,0 +1,6547 @@
+/*************************************************************************
+ * GLFW 3.4 - www.glfw.org
+ * A library for OpenGL, window and input
+ *------------------------------------------------------------------------
+ * Copyright (c) 2002-2006 Marcus Geelnard
+ * Copyright (c) 2006-2019 Camilla Löwy
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would
+ * be appreciated but is not required.
+ *
+ * 2. Altered source versions must be plainly marked as such, and must not
+ * be misrepresented as being the original software.
+ *
+ * 3. This notice may not be removed or altered from any source
+ * distribution.
+ *
+ *************************************************************************/
+
+#ifndef _glfw3_h_
+#define _glfw3_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*************************************************************************
+ * Doxygen documentation
+ *************************************************************************/
+
+/*! @file glfw3.h
+ * @brief The header of the GLFW 3 API.
+ *
+ * This is the header file of the GLFW 3 API. It defines all its types and
+ * declares all its functions.
+ *
+ * For more information about how to use this file, see @ref build_include.
+ */
+/*! @defgroup context Context reference
+ * @brief Functions and types related to OpenGL and OpenGL ES contexts.
+ *
+ * This is the reference documentation for OpenGL and OpenGL ES context related
+ * functions. For more task-oriented information, see the @ref context_guide.
+ */
+/*! @defgroup vulkan Vulkan support reference
+ * @brief Functions and types related to Vulkan.
+ *
+ * This is the reference documentation for Vulkan related functions and types.
+ * For more task-oriented information, see the @ref vulkan_guide.
+ */
+/*! @defgroup init Initialization, version and error reference
+ * @brief Functions and types related to initialization and error handling.
+ *
+ * This is the reference documentation for initialization and termination of
+ * the library, version management and error handling. For more task-oriented
+ * information, see the @ref intro_guide.
+ */
+/*! @defgroup input Input reference
+ * @brief Functions and types related to input handling.
+ *
+ * This is the reference documentation for input related functions and types.
+ * For more task-oriented information, see the @ref input_guide.
+ */
+/*! @defgroup monitor Monitor reference
+ * @brief Functions and types related to monitors.
+ *
+ * This is the reference documentation for monitor related functions and types.
+ * For more task-oriented information, see the @ref monitor_guide.
+ */
+/*! @defgroup window Window reference
+ * @brief Functions and types related to windows.
+ *
+ * This is the reference documentation for window related functions and types,
+ * including creation, deletion and event polling. For more task-oriented
+ * information, see the @ref window_guide.
+ */
+
+
+/*************************************************************************
+ * Compiler- and platform-specific preprocessor work
+ *************************************************************************/
+
+/* If we are we on Windows, we want a single define for it.
+ */
+#if !defined(_WIN32) && (defined(__WIN32__) || defined(WIN32) || defined(__MINGW32__))
+ #define _WIN32
+#endif /* _WIN32 */
+
+/* Include because most Windows GLU headers need wchar_t and
+ * the macOS OpenGL header blocks the definition of ptrdiff_t by glext.h.
+ * Include it unconditionally to avoid surprising side-effects.
+ */
+#include
+
+/* Include because it is needed by Vulkan and related functions.
+ * Include it unconditionally to avoid surprising side-effects.
+ */
+#include
+
+#if defined(GLFW_INCLUDE_VULKAN)
+ #include
+#endif /* Vulkan header */
+
+/* The Vulkan header may have indirectly included windows.h (because of
+ * VK_USE_PLATFORM_WIN32_KHR) so we offer our replacement symbols after it.
+ */
+
+/* It is customary to use APIENTRY for OpenGL function pointer declarations on
+ * all platforms. Additionally, the Windows OpenGL header needs APIENTRY.
+ */
+#if !defined(APIENTRY)
+ #if defined(_WIN32)
+ #define APIENTRY __stdcall
+ #else
+ #define APIENTRY
+ #endif
+ #define GLFW_APIENTRY_DEFINED
+#endif /* APIENTRY */
+
+/* Some Windows OpenGL headers need this.
+ */
+#if !defined(WINGDIAPI) && defined(_WIN32)
+ #define WINGDIAPI __declspec(dllimport)
+ #define GLFW_WINGDIAPI_DEFINED
+#endif /* WINGDIAPI */
+
+/* Some Windows GLU headers need this.
+ */
+#if !defined(CALLBACK) && defined(_WIN32)
+ #define CALLBACK __stdcall
+ #define GLFW_CALLBACK_DEFINED
+#endif /* CALLBACK */
+
+/* Include the chosen OpenGL or OpenGL ES headers.
+ */
+#if defined(GLFW_INCLUDE_ES1)
+
+ #include
+ #if defined(GLFW_INCLUDE_GLEXT)
+ #include
+ #endif
+
+#elif defined(GLFW_INCLUDE_ES2)
+
+ #include
+ #if defined(GLFW_INCLUDE_GLEXT)
+ #include
+ #endif
+
+#elif defined(GLFW_INCLUDE_ES3)
+
+ #include
+ #if defined(GLFW_INCLUDE_GLEXT)
+ #include
+ #endif
+
+#elif defined(GLFW_INCLUDE_ES31)
+
+ #include
+ #if defined(GLFW_INCLUDE_GLEXT)
+ #include
+ #endif
+
+#elif defined(GLFW_INCLUDE_ES32)
+
+ #include
+ #if defined(GLFW_INCLUDE_GLEXT)
+ #include
+ #endif
+
+#elif defined(GLFW_INCLUDE_GLCOREARB)
+
+ #if defined(__APPLE__)
+
+ #include
+ #if defined(GLFW_INCLUDE_GLEXT)
+ #include
+ #endif /*GLFW_INCLUDE_GLEXT*/
+
+ #else /*__APPLE__*/
+
+ #include
+ #if defined(GLFW_INCLUDE_GLEXT)
+ #include
+ #endif
+
+ #endif /*__APPLE__*/
+
+#elif defined(GLFW_INCLUDE_GLU)
+
+ #if defined(__APPLE__)
+
+ #if defined(GLFW_INCLUDE_GLU)
+ #include
+ #endif
+
+ #else /*__APPLE__*/
+
+ #if defined(GLFW_INCLUDE_GLU)
+ #include
+ #endif
+
+ #endif /*__APPLE__*/
+
+#elif !defined(GLFW_INCLUDE_NONE) && \
+ !defined(__gl_h_) && \
+ !defined(__gles1_gl_h_) && \
+ !defined(__gles2_gl2_h_) && \
+ !defined(__gles2_gl3_h_) && \
+ !defined(__gles2_gl31_h_) && \
+ !defined(__gles2_gl32_h_) && \
+ !defined(__gl_glcorearb_h_) && \
+ !defined(__gl2_h_) /*legacy*/ && \
+ !defined(__gl3_h_) /*legacy*/ && \
+ !defined(__gl31_h_) /*legacy*/ && \
+ !defined(__gl32_h_) /*legacy*/ && \
+ !defined(__glcorearb_h_) /*legacy*/ && \
+ !defined(__GL_H__) /*non-standard*/ && \
+ !defined(__gltypes_h_) /*non-standard*/ && \
+ !defined(__glee_h_) /*non-standard*/
+
+ #if defined(__APPLE__)
+
+ #if !defined(GLFW_INCLUDE_GLEXT)
+ #define GL_GLEXT_LEGACY
+ #endif
+ #include
+
+ #else /*__APPLE__*/
+
+ #include
+ #if defined(GLFW_INCLUDE_GLEXT)
+ #include
+ #endif
+
+ #endif /*__APPLE__*/
+
+#endif /* OpenGL and OpenGL ES headers */
+
+#if defined(GLFW_DLL) && defined(_GLFW_BUILD_DLL)
+ /* GLFW_DLL must be defined by applications that are linking against the DLL
+ * version of the GLFW library. _GLFW_BUILD_DLL is defined by the GLFW
+ * configuration header when compiling the DLL version of the library.
+ */
+ #error "You must not have both GLFW_DLL and _GLFW_BUILD_DLL defined"
+#endif
+
+/* GLFWAPI is used to declare public API functions for export
+ * from the DLL / shared library / dynamic library.
+ */
+#if defined(_WIN32) && defined(_GLFW_BUILD_DLL)
+ /* We are building GLFW as a Win32 DLL */
+ #define GLFWAPI __declspec(dllexport)
+#elif defined(_WIN32) && defined(GLFW_DLL)
+ /* We are calling a GLFW Win32 DLL */
+ #define GLFWAPI __declspec(dllimport)
+#elif defined(__GNUC__) && defined(_GLFW_BUILD_DLL)
+ /* We are building GLFW as a Unix shared library */
+ #define GLFWAPI __attribute__((visibility("default")))
+#else
+ #define GLFWAPI
+#endif
+
+
+/*************************************************************************
+ * GLFW API tokens
+ *************************************************************************/
+
+/*! @name GLFW version macros
+ * @{ */
+/*! @brief The major version number of the GLFW header.
+ *
+ * The major version number of the GLFW header. This is incremented when the
+ * API is changed in non-compatible ways.
+ * @ingroup init
+ */
+#define GLFW_VERSION_MAJOR 3
+/*! @brief The minor version number of the GLFW header.
+ *
+ * The minor version number of the GLFW header. This is incremented when
+ * features are added to the API but it remains backward-compatible.
+ * @ingroup init
+ */
+#define GLFW_VERSION_MINOR 4
+/*! @brief The revision number of the GLFW header.
+ *
+ * The revision number of the GLFW header. This is incremented when a bug fix
+ * release is made that does not contain any API changes.
+ * @ingroup init
+ */
+#define GLFW_VERSION_REVISION 0
+/*! @} */
+
+/*! @brief One.
+ *
+ * This is only semantic sugar for the number 1. You can instead use `1` or
+ * `true` or `_True` or `GL_TRUE` or `VK_TRUE` or anything else that is equal
+ * to one.
+ *
+ * @ingroup init
+ */
+#define GLFW_TRUE 1
+/*! @brief Zero.
+ *
+ * This is only semantic sugar for the number 0. You can instead use `0` or
+ * `false` or `_False` or `GL_FALSE` or `VK_FALSE` or anything else that is
+ * equal to zero.
+ *
+ * @ingroup init
+ */
+#define GLFW_FALSE 0
+
+/*! @name Key and button actions
+ * @{ */
+/*! @brief The key or mouse button was released.
+ *
+ * The key or mouse button was released.
+ *
+ * @ingroup input
+ */
+#define GLFW_RELEASE 0
+/*! @brief The key or mouse button was pressed.
+ *
+ * The key or mouse button was pressed.
+ *
+ * @ingroup input
+ */
+#define GLFW_PRESS 1
+/*! @brief The key was held down until it repeated.
+ *
+ * The key was held down until it repeated.
+ *
+ * @ingroup input
+ */
+#define GLFW_REPEAT 2
+/*! @} */
+
+/*! @defgroup hat_state Joystick hat states
+ * @brief Joystick hat states.
+ *
+ * See [joystick hat input](@ref joystick_hat) for how these are used.
+ *
+ * @ingroup input
+ * @{ */
+#define GLFW_HAT_CENTERED 0
+#define GLFW_HAT_UP 1
+#define GLFW_HAT_RIGHT 2
+#define GLFW_HAT_DOWN 4
+#define GLFW_HAT_LEFT 8
+#define GLFW_HAT_RIGHT_UP (GLFW_HAT_RIGHT | GLFW_HAT_UP)
+#define GLFW_HAT_RIGHT_DOWN (GLFW_HAT_RIGHT | GLFW_HAT_DOWN)
+#define GLFW_HAT_LEFT_UP (GLFW_HAT_LEFT | GLFW_HAT_UP)
+#define GLFW_HAT_LEFT_DOWN (GLFW_HAT_LEFT | GLFW_HAT_DOWN)
+
+/*! @ingroup input
+ */
+#define GLFW_KEY_UNKNOWN -1
+
+/*! @} */
+
+/*! @defgroup keys Keyboard key tokens
+ * @brief Keyboard key tokens.
+ *
+ * See [key input](@ref input_key) for how these are used.
+ *
+ * These key codes are inspired by the _USB HID Usage Tables v1.12_ (p. 53-60),
+ * but re-arranged to map to 7-bit ASCII for printable keys (function keys are
+ * put in the 256+ range).
+ *
+ * The naming of the key codes follow these rules:
+ * - The US keyboard layout is used
+ * - Names of printable alphanumeric characters are used (e.g. "A", "R",
+ * "3", etc.)
+ * - For non-alphanumeric characters, Unicode:ish names are used (e.g.
+ * "COMMA", "LEFT_SQUARE_BRACKET", etc.). Note that some names do not
+ * correspond to the Unicode standard (usually for brevity)
+ * - Keys that lack a clear US mapping are named "WORLD_x"
+ * - For non-printable keys, custom names are used (e.g. "F4",
+ * "BACKSPACE", etc.)
+ *
+ * @ingroup input
+ * @{
+ */
+
+/* Printable keys */
+#define GLFW_KEY_SPACE 32
+#define GLFW_KEY_APOSTROPHE 39 /* ' */
+#define GLFW_KEY_COMMA 44 /* , */
+#define GLFW_KEY_MINUS 45 /* - */
+#define GLFW_KEY_PERIOD 46 /* . */
+#define GLFW_KEY_SLASH 47 /* / */
+#define GLFW_KEY_0 48
+#define GLFW_KEY_1 49
+#define GLFW_KEY_2 50
+#define GLFW_KEY_3 51
+#define GLFW_KEY_4 52
+#define GLFW_KEY_5 53
+#define GLFW_KEY_6 54
+#define GLFW_KEY_7 55
+#define GLFW_KEY_8 56
+#define GLFW_KEY_9 57
+#define GLFW_KEY_SEMICOLON 59 /* ; */
+#define GLFW_KEY_EQUAL 61 /* = */
+#define GLFW_KEY_A 65
+#define GLFW_KEY_B 66
+#define GLFW_KEY_C 67
+#define GLFW_KEY_D 68
+#define GLFW_KEY_E 69
+#define GLFW_KEY_F 70
+#define GLFW_KEY_G 71
+#define GLFW_KEY_H 72
+#define GLFW_KEY_I 73
+#define GLFW_KEY_J 74
+#define GLFW_KEY_K 75
+#define GLFW_KEY_L 76
+#define GLFW_KEY_M 77
+#define GLFW_KEY_N 78
+#define GLFW_KEY_O 79
+#define GLFW_KEY_P 80
+#define GLFW_KEY_Q 81
+#define GLFW_KEY_R 82
+#define GLFW_KEY_S 83
+#define GLFW_KEY_T 84
+#define GLFW_KEY_U 85
+#define GLFW_KEY_V 86
+#define GLFW_KEY_W 87
+#define GLFW_KEY_X 88
+#define GLFW_KEY_Y 89
+#define GLFW_KEY_Z 90
+#define GLFW_KEY_LEFT_BRACKET 91 /* [ */
+#define GLFW_KEY_BACKSLASH 92 /* \ */
+#define GLFW_KEY_RIGHT_BRACKET 93 /* ] */
+#define GLFW_KEY_GRAVE_ACCENT 96 /* ` */
+#define GLFW_KEY_WORLD_1 161 /* non-US #1 */
+#define GLFW_KEY_WORLD_2 162 /* non-US #2 */
+
+/* Function keys */
+#define GLFW_KEY_ESCAPE 256
+#define GLFW_KEY_ENTER 257
+#define GLFW_KEY_TAB 258
+#define GLFW_KEY_BACKSPACE 259
+#define GLFW_KEY_INSERT 260
+#define GLFW_KEY_DELETE 261
+#define GLFW_KEY_RIGHT 262
+#define GLFW_KEY_LEFT 263
+#define GLFW_KEY_DOWN 264
+#define GLFW_KEY_UP 265
+#define GLFW_KEY_PAGE_UP 266
+#define GLFW_KEY_PAGE_DOWN 267
+#define GLFW_KEY_HOME 268
+#define GLFW_KEY_END 269
+#define GLFW_KEY_CAPS_LOCK 280
+#define GLFW_KEY_SCROLL_LOCK 281
+#define GLFW_KEY_NUM_LOCK 282
+#define GLFW_KEY_PRINT_SCREEN 283
+#define GLFW_KEY_PAUSE 284
+#define GLFW_KEY_F1 290
+#define GLFW_KEY_F2 291
+#define GLFW_KEY_F3 292
+#define GLFW_KEY_F4 293
+#define GLFW_KEY_F5 294
+#define GLFW_KEY_F6 295
+#define GLFW_KEY_F7 296
+#define GLFW_KEY_F8 297
+#define GLFW_KEY_F9 298
+#define GLFW_KEY_F10 299
+#define GLFW_KEY_F11 300
+#define GLFW_KEY_F12 301
+#define GLFW_KEY_F13 302
+#define GLFW_KEY_F14 303
+#define GLFW_KEY_F15 304
+#define GLFW_KEY_F16 305
+#define GLFW_KEY_F17 306
+#define GLFW_KEY_F18 307
+#define GLFW_KEY_F19 308
+#define GLFW_KEY_F20 309
+#define GLFW_KEY_F21 310
+#define GLFW_KEY_F22 311
+#define GLFW_KEY_F23 312
+#define GLFW_KEY_F24 313
+#define GLFW_KEY_F25 314
+#define GLFW_KEY_KP_0 320
+#define GLFW_KEY_KP_1 321
+#define GLFW_KEY_KP_2 322
+#define GLFW_KEY_KP_3 323
+#define GLFW_KEY_KP_4 324
+#define GLFW_KEY_KP_5 325
+#define GLFW_KEY_KP_6 326
+#define GLFW_KEY_KP_7 327
+#define GLFW_KEY_KP_8 328
+#define GLFW_KEY_KP_9 329
+#define GLFW_KEY_KP_DECIMAL 330
+#define GLFW_KEY_KP_DIVIDE 331
+#define GLFW_KEY_KP_MULTIPLY 332
+#define GLFW_KEY_KP_SUBTRACT 333
+#define GLFW_KEY_KP_ADD 334
+#define GLFW_KEY_KP_ENTER 335
+#define GLFW_KEY_KP_EQUAL 336
+#define GLFW_KEY_LEFT_SHIFT 340
+#define GLFW_KEY_LEFT_CONTROL 341
+#define GLFW_KEY_LEFT_ALT 342
+#define GLFW_KEY_LEFT_SUPER 343
+#define GLFW_KEY_RIGHT_SHIFT 344
+#define GLFW_KEY_RIGHT_CONTROL 345
+#define GLFW_KEY_RIGHT_ALT 346
+#define GLFW_KEY_RIGHT_SUPER 347
+#define GLFW_KEY_MENU 348
+
+#define GLFW_KEY_LAST GLFW_KEY_MENU
+
+/*! @} */
+
+/*! @defgroup mods Modifier key flags
+ * @brief Modifier key flags.
+ *
+ * See [key input](@ref input_key) for how these are used.
+ *
+ * @ingroup input
+ * @{ */
+
+/*! @brief If this bit is set one or more Shift keys were held down.
+ *
+ * If this bit is set one or more Shift keys were held down.
+ */
+#define GLFW_MOD_SHIFT 0x0001
+/*! @brief If this bit is set one or more Control keys were held down.
+ *
+ * If this bit is set one or more Control keys were held down.
+ */
+#define GLFW_MOD_CONTROL 0x0002
+/*! @brief If this bit is set one or more Alt keys were held down.
+ *
+ * If this bit is set one or more Alt keys were held down.
+ */
+#define GLFW_MOD_ALT 0x0004
+/*! @brief If this bit is set one or more Super keys were held down.
+ *
+ * If this bit is set one or more Super keys were held down.
+ */
+#define GLFW_MOD_SUPER 0x0008
+/*! @brief If this bit is set the Caps Lock key is enabled.
+ *
+ * If this bit is set the Caps Lock key is enabled and the @ref
+ * GLFW_LOCK_KEY_MODS input mode is set.
+ */
+#define GLFW_MOD_CAPS_LOCK 0x0010
+/*! @brief If this bit is set the Num Lock key is enabled.
+ *
+ * If this bit is set the Num Lock key is enabled and the @ref
+ * GLFW_LOCK_KEY_MODS input mode is set.
+ */
+#define GLFW_MOD_NUM_LOCK 0x0020
+
+/*! @} */
+
+/*! @defgroup buttons Mouse buttons
+ * @brief Mouse button IDs.
+ *
+ * See [mouse button input](@ref input_mouse_button) for how these are used.
+ *
+ * @ingroup input
+ * @{ */
+#define GLFW_MOUSE_BUTTON_1 0
+#define GLFW_MOUSE_BUTTON_2 1
+#define GLFW_MOUSE_BUTTON_3 2
+#define GLFW_MOUSE_BUTTON_4 3
+#define GLFW_MOUSE_BUTTON_5 4
+#define GLFW_MOUSE_BUTTON_6 5
+#define GLFW_MOUSE_BUTTON_7 6
+#define GLFW_MOUSE_BUTTON_8 7
+#define GLFW_MOUSE_BUTTON_LAST GLFW_MOUSE_BUTTON_8
+#define GLFW_MOUSE_BUTTON_LEFT GLFW_MOUSE_BUTTON_1
+#define GLFW_MOUSE_BUTTON_RIGHT GLFW_MOUSE_BUTTON_2
+#define GLFW_MOUSE_BUTTON_MIDDLE GLFW_MOUSE_BUTTON_3
+/*! @} */
+
+/*! @defgroup joysticks Joysticks
+ * @brief Joystick IDs.
+ *
+ * See [joystick input](@ref joystick) for how these are used.
+ *
+ * @ingroup input
+ * @{ */
+#define GLFW_JOYSTICK_1 0
+#define GLFW_JOYSTICK_2 1
+#define GLFW_JOYSTICK_3 2
+#define GLFW_JOYSTICK_4 3
+#define GLFW_JOYSTICK_5 4
+#define GLFW_JOYSTICK_6 5
+#define GLFW_JOYSTICK_7 6
+#define GLFW_JOYSTICK_8 7
+#define GLFW_JOYSTICK_9 8
+#define GLFW_JOYSTICK_10 9
+#define GLFW_JOYSTICK_11 10
+#define GLFW_JOYSTICK_12 11
+#define GLFW_JOYSTICK_13 12
+#define GLFW_JOYSTICK_14 13
+#define GLFW_JOYSTICK_15 14
+#define GLFW_JOYSTICK_16 15
+#define GLFW_JOYSTICK_LAST GLFW_JOYSTICK_16
+/*! @} */
+
+/*! @defgroup gamepad_buttons Gamepad buttons
+ * @brief Gamepad buttons.
+ *
+ * See @ref gamepad for how these are used.
+ *
+ * @ingroup input
+ * @{ */
+#define GLFW_GAMEPAD_BUTTON_A 0
+#define GLFW_GAMEPAD_BUTTON_B 1
+#define GLFW_GAMEPAD_BUTTON_X 2
+#define GLFW_GAMEPAD_BUTTON_Y 3
+#define GLFW_GAMEPAD_BUTTON_LEFT_BUMPER 4
+#define GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER 5
+#define GLFW_GAMEPAD_BUTTON_BACK 6
+#define GLFW_GAMEPAD_BUTTON_START 7
+#define GLFW_GAMEPAD_BUTTON_GUIDE 8
+#define GLFW_GAMEPAD_BUTTON_LEFT_THUMB 9
+#define GLFW_GAMEPAD_BUTTON_RIGHT_THUMB 10
+#define GLFW_GAMEPAD_BUTTON_DPAD_UP 11
+#define GLFW_GAMEPAD_BUTTON_DPAD_RIGHT 12
+#define GLFW_GAMEPAD_BUTTON_DPAD_DOWN 13
+#define GLFW_GAMEPAD_BUTTON_DPAD_LEFT 14
+#define GLFW_GAMEPAD_BUTTON_LAST GLFW_GAMEPAD_BUTTON_DPAD_LEFT
+
+#define GLFW_GAMEPAD_BUTTON_CROSS GLFW_GAMEPAD_BUTTON_A
+#define GLFW_GAMEPAD_BUTTON_CIRCLE GLFW_GAMEPAD_BUTTON_B
+#define GLFW_GAMEPAD_BUTTON_SQUARE GLFW_GAMEPAD_BUTTON_X
+#define GLFW_GAMEPAD_BUTTON_TRIANGLE GLFW_GAMEPAD_BUTTON_Y
+/*! @} */
+
+/*! @defgroup gamepad_axes Gamepad axes
+ * @brief Gamepad axes.
+ *
+ * See @ref gamepad for how these are used.
+ *
+ * @ingroup input
+ * @{ */
+#define GLFW_GAMEPAD_AXIS_LEFT_X 0
+#define GLFW_GAMEPAD_AXIS_LEFT_Y 1
+#define GLFW_GAMEPAD_AXIS_RIGHT_X 2
+#define GLFW_GAMEPAD_AXIS_RIGHT_Y 3
+#define GLFW_GAMEPAD_AXIS_LEFT_TRIGGER 4
+#define GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER 5
+#define GLFW_GAMEPAD_AXIS_LAST GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER
+/*! @} */
+
+/*! @defgroup errors Error codes
+ * @brief Error codes.
+ *
+ * See [error handling](@ref error_handling) for how these are used.
+ *
+ * @ingroup init
+ * @{ */
+/*! @brief No error has occurred.
+ *
+ * No error has occurred.
+ *
+ * @analysis Yay.
+ */
+#define GLFW_NO_ERROR 0
+/*! @brief GLFW has not been initialized.
+ *
+ * This occurs if a GLFW function was called that must not be called unless the
+ * library is [initialized](@ref intro_init).
+ *
+ * @analysis Application programmer error. Initialize GLFW before calling any
+ * function that requires initialization.
+ */
+#define GLFW_NOT_INITIALIZED 0x00010001
+/*! @brief No context is current for this thread.
+ *
+ * This occurs if a GLFW function was called that needs and operates on the
+ * current OpenGL or OpenGL ES context but no context is current on the calling
+ * thread. One such function is @ref glfwSwapInterval.
+ *
+ * @analysis Application programmer error. Ensure a context is current before
+ * calling functions that require a current context.
+ */
+#define GLFW_NO_CURRENT_CONTEXT 0x00010002
+/*! @brief One of the arguments to the function was an invalid enum value.
+ *
+ * One of the arguments to the function was an invalid enum value, for example
+ * requesting @ref GLFW_RED_BITS with @ref glfwGetWindowAttrib.
+ *
+ * @analysis Application programmer error. Fix the offending call.
+ */
+#define GLFW_INVALID_ENUM 0x00010003
+/*! @brief One of the arguments to the function was an invalid value.
+ *
+ * One of the arguments to the function was an invalid value, for example
+ * requesting a non-existent OpenGL or OpenGL ES version like 2.7.
+ *
+ * Requesting a valid but unavailable OpenGL or OpenGL ES version will instead
+ * result in a @ref GLFW_VERSION_UNAVAILABLE error.
+ *
+ * @analysis Application programmer error. Fix the offending call.
+ */
+#define GLFW_INVALID_VALUE 0x00010004
+/*! @brief A memory allocation failed.
+ *
+ * A memory allocation failed.
+ *
+ * @analysis A bug in GLFW or the underlying operating system. Report the bug
+ * to our [issue tracker](https://github.com/glfw/glfw/issues).
+ */
+#define GLFW_OUT_OF_MEMORY 0x00010005
+/*! @brief GLFW could not find support for the requested API on the system.
+ *
+ * GLFW could not find support for the requested API on the system.
+ *
+ * @analysis The installed graphics driver does not support the requested
+ * API, or does not support it via the chosen context creation API.
+ * Below are a few examples.
+ *
+ * @par
+ * Some pre-installed Windows graphics drivers do not support OpenGL. AMD only
+ * supports OpenGL ES via EGL, while Nvidia and Intel only support it via
+ * a WGL or GLX extension. macOS does not provide OpenGL ES at all. The Mesa
+ * EGL, OpenGL and OpenGL ES libraries do not interface with the Nvidia binary
+ * driver. Older graphics drivers do not support Vulkan.
+ */
+#define GLFW_API_UNAVAILABLE 0x00010006
+/*! @brief The requested OpenGL or OpenGL ES version is not available.
+ *
+ * The requested OpenGL or OpenGL ES version (including any requested context
+ * or framebuffer hints) is not available on this machine.
+ *
+ * @analysis The machine does not support your requirements. If your
+ * application is sufficiently flexible, downgrade your requirements and try
+ * again. Otherwise, inform the user that their machine does not match your
+ * requirements.
+ *
+ * @par
+ * Future invalid OpenGL and OpenGL ES versions, for example OpenGL 4.8 if 5.0
+ * comes out before the 4.x series gets that far, also fail with this error and
+ * not @ref GLFW_INVALID_VALUE, because GLFW cannot know what future versions
+ * will exist.
+ */
+#define GLFW_VERSION_UNAVAILABLE 0x00010007
+/*! @brief A platform-specific error occurred that does not match any of the
+ * more specific categories.
+ *
+ * A platform-specific error occurred that does not match any of the more
+ * specific categories.
+ *
+ * @analysis A bug or configuration error in GLFW, the underlying operating
+ * system or its drivers, or a lack of required resources. Report the issue to
+ * our [issue tracker](https://github.com/glfw/glfw/issues).
+ */
+#define GLFW_PLATFORM_ERROR 0x00010008
+/*! @brief The requested format is not supported or available.
+ *
+ * If emitted during window creation, the requested pixel format is not
+ * supported.
+ *
+ * If emitted when querying the clipboard, the contents of the clipboard could
+ * not be converted to the requested format.
+ *
+ * @analysis If emitted during window creation, one or more
+ * [hard constraints](@ref window_hints_hard) did not match any of the
+ * available pixel formats. If your application is sufficiently flexible,
+ * downgrade your requirements and try again. Otherwise, inform the user that
+ * their machine does not match your requirements.
+ *
+ * @par
+ * If emitted when querying the clipboard, ignore the error or report it to
+ * the user, as appropriate.
+ */
+#define GLFW_FORMAT_UNAVAILABLE 0x00010009
+/*! @brief The specified window does not have an OpenGL or OpenGL ES context.
+ *
+ * A window that does not have an OpenGL or OpenGL ES context was passed to
+ * a function that requires it to have one.
+ *
+ * @analysis Application programmer error. Fix the offending call.
+ */
+#define GLFW_NO_WINDOW_CONTEXT 0x0001000A
+/*! @brief The specified cursor shape is not available.
+ *
+ * The specified standard cursor shape is not available, either because the
+ * current platform cursor theme does not provide it or because it is not
+ * available on the platform.
+ *
+ * @analysis Platform or system settings limitation. Pick another
+ * [standard cursor shape](@ref shapes) or create a
+ * [custom cursor](@ref cursor_custom).
+ */
+#define GLFW_CURSOR_UNAVAILABLE 0x0001000B
+/*! @brief The requested feature is not provided by the platform.
+ *
+ * The requested feature is not provided by the platform, so GLFW is unable to
+ * implement it. The documentation for each function notes if it could emit
+ * this error.
+ *
+ * @analysis Platform or platform version limitation. The error can be ignored
+ * unless the feature is critical to the application.
+ *
+ * @par
+ * A function call that emits this error has no effect other than the error and
+ * updating any existing out parameters.
+ */
+#define GLFW_FEATURE_UNAVAILABLE 0x0001000C
+/*! @brief The requested feature is not implemented for the platform.
+ *
+ * The requested feature has not yet been implemented in GLFW for this platform.
+ *
+ * @analysis An incomplete implementation of GLFW for this platform, hopefully
+ * fixed in a future release. The error can be ignored unless the feature is
+ * critical to the application.
+ *
+ * @par
+ * A function call that emits this error has no effect other than the error and
+ * updating any existing out parameters.
+ */
+#define GLFW_FEATURE_UNIMPLEMENTED 0x0001000D
+/*! @brief Platform unavailable or no matching platform was found.
+ *
+ * If emitted during initialization, no matching platform was found. If the @ref
+ * GLFW_PLATFORM init hint was set to `GLFW_ANY_PLATFORM`, GLFW could not detect any of
+ * the platforms supported by this library binary, except for the Null platform. If the
+ * init hint was set to a specific platform, it is either not supported by this library
+ * binary or GLFW was not able to detect it.
+ *
+ * If emitted by a native access function, GLFW was initialized for a different platform
+ * than the function is for.
+ *
+ * @analysis Failure to detect any platform usually only happens on non-macOS Unix
+ * systems, either when no window system is running or the program was run from
+ * a terminal that does not have the necessary environment variables. Fall back to
+ * a different platform if possible or notify the user that no usable platform was
+ * detected.
+ *
+ * Failure to detect a specific platform may have the same cause as above or be because
+ * support for that platform was not compiled in. Call @ref glfwPlatformSupported to
+ * check whether a specific platform is supported by a library binary.
+ */
+#define GLFW_PLATFORM_UNAVAILABLE 0x0001000E
+/*! @} */
+
+/*! @addtogroup window
+ * @{ */
+/*! @brief Input focus window hint and attribute
+ *
+ * Input focus [window hint](@ref GLFW_FOCUSED_hint) or
+ * [window attribute](@ref GLFW_FOCUSED_attrib).
+ */
+#define GLFW_FOCUSED 0x00020001
+/*! @brief Window iconification window attribute
+ *
+ * Window iconification [window attribute](@ref GLFW_ICONIFIED_attrib).
+ */
+#define GLFW_ICONIFIED 0x00020002
+/*! @brief Window resize-ability window hint and attribute
+ *
+ * Window resize-ability [window hint](@ref GLFW_RESIZABLE_hint) and
+ * [window attribute](@ref GLFW_RESIZABLE_attrib).
+ */
+#define GLFW_RESIZABLE 0x00020003
+/*! @brief Window visibility window hint and attribute
+ *
+ * Window visibility [window hint](@ref GLFW_VISIBLE_hint) and
+ * [window attribute](@ref GLFW_VISIBLE_attrib).
+ */
+#define GLFW_VISIBLE 0x00020004
+/*! @brief Window decoration window hint and attribute
+ *
+ * Window decoration [window hint](@ref GLFW_DECORATED_hint) and
+ * [window attribute](@ref GLFW_DECORATED_attrib).
+ */
+#define GLFW_DECORATED 0x00020005
+/*! @brief Window auto-iconification window hint and attribute
+ *
+ * Window auto-iconification [window hint](@ref GLFW_AUTO_ICONIFY_hint) and
+ * [window attribute](@ref GLFW_AUTO_ICONIFY_attrib).
+ */
+#define GLFW_AUTO_ICONIFY 0x00020006
+/*! @brief Window decoration window hint and attribute
+ *
+ * Window decoration [window hint](@ref GLFW_FLOATING_hint) and
+ * [window attribute](@ref GLFW_FLOATING_attrib).
+ */
+#define GLFW_FLOATING 0x00020007
+/*! @brief Window maximization window hint and attribute
+ *
+ * Window maximization [window hint](@ref GLFW_MAXIMIZED_hint) and
+ * [window attribute](@ref GLFW_MAXIMIZED_attrib).
+ */
+#define GLFW_MAXIMIZED 0x00020008
+/*! @brief Cursor centering window hint
+ *
+ * Cursor centering [window hint](@ref GLFW_CENTER_CURSOR_hint).
+ */
+#define GLFW_CENTER_CURSOR 0x00020009
+/*! @brief Window framebuffer transparency hint and attribute
+ *
+ * Window framebuffer transparency
+ * [window hint](@ref GLFW_TRANSPARENT_FRAMEBUFFER_hint) and
+ * [window attribute](@ref GLFW_TRANSPARENT_FRAMEBUFFER_attrib).
+ */
+#define GLFW_TRANSPARENT_FRAMEBUFFER 0x0002000A
+/*! @brief Mouse cursor hover window attribute.
+ *
+ * Mouse cursor hover [window attribute](@ref GLFW_HOVERED_attrib).
+ */
+#define GLFW_HOVERED 0x0002000B
+/*! @brief Input focus on calling show window hint and attribute
+ *
+ * Input focus [window hint](@ref GLFW_FOCUS_ON_SHOW_hint) or
+ * [window attribute](@ref GLFW_FOCUS_ON_SHOW_attrib).
+ */
+#define GLFW_FOCUS_ON_SHOW 0x0002000C
+
+/*! @brief Mouse input transparency window hint and attribute
+ *
+ * Mouse input transparency [window hint](@ref GLFW_MOUSE_PASSTHROUGH_hint) or
+ * [window attribute](@ref GLFW_MOUSE_PASSTHROUGH_attrib).
+ */
+#define GLFW_MOUSE_PASSTHROUGH 0x0002000D
+
+/*! @brief Initial position x-coordinate window hint.
+ *
+ * Initial position x-coordinate [window hint](@ref GLFW_POSITION_X).
+ */
+#define GLFW_POSITION_X 0x0002000E
+
+/*! @brief Initial position y-coordinate window hint.
+ *
+ * Initial position y-coordinate [window hint](@ref GLFW_POSITION_Y).
+ */
+#define GLFW_POSITION_Y 0x0002000F
+
+/*! @brief Framebuffer bit depth hint.
+ *
+ * Framebuffer bit depth [hint](@ref GLFW_RED_BITS).
+ */
+#define GLFW_RED_BITS 0x00021001
+/*! @brief Framebuffer bit depth hint.
+ *
+ * Framebuffer bit depth [hint](@ref GLFW_GREEN_BITS).
+ */
+#define GLFW_GREEN_BITS 0x00021002
+/*! @brief Framebuffer bit depth hint.
+ *
+ * Framebuffer bit depth [hint](@ref GLFW_BLUE_BITS).
+ */
+#define GLFW_BLUE_BITS 0x00021003
+/*! @brief Framebuffer bit depth hint.
+ *
+ * Framebuffer bit depth [hint](@ref GLFW_ALPHA_BITS).
+ */
+#define GLFW_ALPHA_BITS 0x00021004
+/*! @brief Framebuffer bit depth hint.
+ *
+ * Framebuffer bit depth [hint](@ref GLFW_DEPTH_BITS).
+ */
+#define GLFW_DEPTH_BITS 0x00021005
+/*! @brief Framebuffer bit depth hint.
+ *
+ * Framebuffer bit depth [hint](@ref GLFW_STENCIL_BITS).
+ */
+#define GLFW_STENCIL_BITS 0x00021006
+/*! @brief Framebuffer bit depth hint.
+ *
+ * Framebuffer bit depth [hint](@ref GLFW_ACCUM_RED_BITS).
+ */
+#define GLFW_ACCUM_RED_BITS 0x00021007
+/*! @brief Framebuffer bit depth hint.
+ *
+ * Framebuffer bit depth [hint](@ref GLFW_ACCUM_GREEN_BITS).
+ */
+#define GLFW_ACCUM_GREEN_BITS 0x00021008
+/*! @brief Framebuffer bit depth hint.
+ *
+ * Framebuffer bit depth [hint](@ref GLFW_ACCUM_BLUE_BITS).
+ */
+#define GLFW_ACCUM_BLUE_BITS 0x00021009
+/*! @brief Framebuffer bit depth hint.
+ *
+ * Framebuffer bit depth [hint](@ref GLFW_ACCUM_ALPHA_BITS).
+ */
+#define GLFW_ACCUM_ALPHA_BITS 0x0002100A
+/*! @brief Framebuffer auxiliary buffer hint.
+ *
+ * Framebuffer auxiliary buffer [hint](@ref GLFW_AUX_BUFFERS).
+ */
+#define GLFW_AUX_BUFFERS 0x0002100B
+/*! @brief OpenGL stereoscopic rendering hint.
+ *
+ * OpenGL stereoscopic rendering [hint](@ref GLFW_STEREO).
+ */
+#define GLFW_STEREO 0x0002100C
+/*! @brief Framebuffer MSAA samples hint.
+ *
+ * Framebuffer MSAA samples [hint](@ref GLFW_SAMPLES).
+ */
+#define GLFW_SAMPLES 0x0002100D
+/*! @brief Framebuffer sRGB hint.
+ *
+ * Framebuffer sRGB [hint](@ref GLFW_SRGB_CAPABLE).
+ */
+#define GLFW_SRGB_CAPABLE 0x0002100E
+/*! @brief Monitor refresh rate hint.
+ *
+ * Monitor refresh rate [hint](@ref GLFW_REFRESH_RATE).
+ */
+#define GLFW_REFRESH_RATE 0x0002100F
+/*! @brief Framebuffer double buffering hint and attribute.
+ *
+ * Framebuffer double buffering [hint](@ref GLFW_DOUBLEBUFFER_hint) and
+ * [attribute](@ref GLFW_DOUBLEBUFFER_attrib).
+ */
+#define GLFW_DOUBLEBUFFER 0x00021010
+
+/*! @brief Context client API hint and attribute.
+ *
+ * Context client API [hint](@ref GLFW_CLIENT_API_hint) and
+ * [attribute](@ref GLFW_CLIENT_API_attrib).
+ */
+#define GLFW_CLIENT_API 0x00022001
+/*! @brief Context client API major version hint and attribute.
+ *
+ * Context client API major version [hint](@ref GLFW_CONTEXT_VERSION_MAJOR_hint)
+ * and [attribute](@ref GLFW_CONTEXT_VERSION_MAJOR_attrib).
+ */
+#define GLFW_CONTEXT_VERSION_MAJOR 0x00022002
+/*! @brief Context client API minor version hint and attribute.
+ *
+ * Context client API minor version [hint](@ref GLFW_CONTEXT_VERSION_MINOR_hint)
+ * and [attribute](@ref GLFW_CONTEXT_VERSION_MINOR_attrib).
+ */
+#define GLFW_CONTEXT_VERSION_MINOR 0x00022003
+/*! @brief Context client API revision number attribute.
+ *
+ * Context client API revision number
+ * [attribute](@ref GLFW_CONTEXT_REVISION_attrib).
+ */
+#define GLFW_CONTEXT_REVISION 0x00022004
+/*! @brief Context robustness hint and attribute.
+ *
+ * Context client API revision number [hint](@ref GLFW_CONTEXT_ROBUSTNESS_hint)
+ * and [attribute](@ref GLFW_CONTEXT_ROBUSTNESS_attrib).
+ */
+#define GLFW_CONTEXT_ROBUSTNESS 0x00022005
+/*! @brief OpenGL forward-compatibility hint and attribute.
+ *
+ * OpenGL forward-compatibility [hint](@ref GLFW_OPENGL_FORWARD_COMPAT_hint)
+ * and [attribute](@ref GLFW_OPENGL_FORWARD_COMPAT_attrib).
+ */
+#define GLFW_OPENGL_FORWARD_COMPAT 0x00022006
+/*! @brief Debug mode context hint and attribute.
+ *
+ * Debug mode context [hint](@ref GLFW_CONTEXT_DEBUG_hint) and
+ * [attribute](@ref GLFW_CONTEXT_DEBUG_attrib).
+ */
+#define GLFW_CONTEXT_DEBUG 0x00022007
+/*! @brief Legacy name for compatibility.
+ *
+ * This is an alias for compatibility with earlier versions.
+ */
+#define GLFW_OPENGL_DEBUG_CONTEXT GLFW_CONTEXT_DEBUG
+/*! @brief OpenGL profile hint and attribute.
+ *
+ * OpenGL profile [hint](@ref GLFW_OPENGL_PROFILE_hint) and
+ * [attribute](@ref GLFW_OPENGL_PROFILE_attrib).
+ */
+#define GLFW_OPENGL_PROFILE 0x00022008
+/*! @brief Context flush-on-release hint and attribute.
+ *
+ * Context flush-on-release [hint](@ref GLFW_CONTEXT_RELEASE_BEHAVIOR_hint) and
+ * [attribute](@ref GLFW_CONTEXT_RELEASE_BEHAVIOR_attrib).
+ */
+#define GLFW_CONTEXT_RELEASE_BEHAVIOR 0x00022009
+/*! @brief Context error suppression hint and attribute.
+ *
+ * Context error suppression [hint](@ref GLFW_CONTEXT_NO_ERROR_hint) and
+ * [attribute](@ref GLFW_CONTEXT_NO_ERROR_attrib).
+ */
+#define GLFW_CONTEXT_NO_ERROR 0x0002200A
+/*! @brief Context creation API hint and attribute.
+ *
+ * Context creation API [hint](@ref GLFW_CONTEXT_CREATION_API_hint) and
+ * [attribute](@ref GLFW_CONTEXT_CREATION_API_attrib).
+ */
+#define GLFW_CONTEXT_CREATION_API 0x0002200B
+/*! @brief Window content area scaling window
+ * [window hint](@ref GLFW_SCALE_TO_MONITOR).
+ */
+#define GLFW_SCALE_TO_MONITOR 0x0002200C
+/*! @brief Window framebuffer scaling
+ * [window hint](@ref GLFW_SCALE_FRAMEBUFFER_hint).
+ */
+#define GLFW_SCALE_FRAMEBUFFER 0x0002200D
+/*! @brief Legacy name for compatibility.
+ *
+ * This is an alias for the
+ * [GLFW_SCALE_FRAMEBUFFER](@ref GLFW_SCALE_FRAMEBUFFER_hint) window hint for
+ * compatibility with earlier versions.
+ */
+#define GLFW_COCOA_RETINA_FRAMEBUFFER 0x00023001
+/*! @brief macOS specific
+ * [window hint](@ref GLFW_COCOA_FRAME_NAME_hint).
+ */
+#define GLFW_COCOA_FRAME_NAME 0x00023002
+/*! @brief macOS specific
+ * [window hint](@ref GLFW_COCOA_GRAPHICS_SWITCHING_hint).
+ */
+#define GLFW_COCOA_GRAPHICS_SWITCHING 0x00023003
+/*! @brief X11 specific
+ * [window hint](@ref GLFW_X11_CLASS_NAME_hint).
+ */
+#define GLFW_X11_CLASS_NAME 0x00024001
+/*! @brief X11 specific
+ * [window hint](@ref GLFW_X11_CLASS_NAME_hint).
+ */
+#define GLFW_X11_INSTANCE_NAME 0x00024002
+#define GLFW_WIN32_KEYBOARD_MENU 0x00025001
+/*! @brief Win32 specific [window hint](@ref GLFW_WIN32_SHOWDEFAULT_hint).
+ */
+#define GLFW_WIN32_SHOWDEFAULT 0x00025002
+/*! @brief Wayland specific
+ * [window hint](@ref GLFW_WAYLAND_APP_ID_hint).
+ *
+ * Allows specification of the Wayland app_id.
+ */
+#define GLFW_WAYLAND_APP_ID 0x00026001
+/*! @} */
+
+#define GLFW_NO_API 0
+#define GLFW_OPENGL_API 0x00030001
+#define GLFW_OPENGL_ES_API 0x00030002
+
+#define GLFW_NO_ROBUSTNESS 0
+#define GLFW_NO_RESET_NOTIFICATION 0x00031001
+#define GLFW_LOSE_CONTEXT_ON_RESET 0x00031002
+
+#define GLFW_OPENGL_ANY_PROFILE 0
+#define GLFW_OPENGL_CORE_PROFILE 0x00032001
+#define GLFW_OPENGL_COMPAT_PROFILE 0x00032002
+
+#define GLFW_CURSOR 0x00033001
+#define GLFW_STICKY_KEYS 0x00033002
+#define GLFW_STICKY_MOUSE_BUTTONS 0x00033003
+#define GLFW_LOCK_KEY_MODS 0x00033004
+#define GLFW_RAW_MOUSE_MOTION 0x00033005
+
+#define GLFW_CURSOR_NORMAL 0x00034001
+#define GLFW_CURSOR_HIDDEN 0x00034002
+#define GLFW_CURSOR_DISABLED 0x00034003
+#define GLFW_CURSOR_CAPTURED 0x00034004
+
+#define GLFW_ANY_RELEASE_BEHAVIOR 0
+#define GLFW_RELEASE_BEHAVIOR_FLUSH 0x00035001
+#define GLFW_RELEASE_BEHAVIOR_NONE 0x00035002
+
+#define GLFW_NATIVE_CONTEXT_API 0x00036001
+#define GLFW_EGL_CONTEXT_API 0x00036002
+#define GLFW_OSMESA_CONTEXT_API 0x00036003
+
+#define GLFW_ANGLE_PLATFORM_TYPE_NONE 0x00037001
+#define GLFW_ANGLE_PLATFORM_TYPE_OPENGL 0x00037002
+#define GLFW_ANGLE_PLATFORM_TYPE_OPENGLES 0x00037003
+#define GLFW_ANGLE_PLATFORM_TYPE_D3D9 0x00037004
+#define GLFW_ANGLE_PLATFORM_TYPE_D3D11 0x00037005
+#define GLFW_ANGLE_PLATFORM_TYPE_VULKAN 0x00037007
+#define GLFW_ANGLE_PLATFORM_TYPE_METAL 0x00037008
+
+#define GLFW_WAYLAND_PREFER_LIBDECOR 0x00038001
+#define GLFW_WAYLAND_DISABLE_LIBDECOR 0x00038002
+
+#define GLFW_ANY_POSITION 0x80000000
+
+/*! @defgroup shapes Standard cursor shapes
+ * @brief Standard system cursor shapes.
+ *
+ * These are the [standard cursor shapes](@ref cursor_standard) that can be
+ * requested from the platform (window system).
+ *
+ * @ingroup input
+ * @{ */
+
+/*! @brief The regular arrow cursor shape.
+ *
+ * The regular arrow cursor shape.
+ */
+#define GLFW_ARROW_CURSOR 0x00036001
+/*! @brief The text input I-beam cursor shape.
+ *
+ * The text input I-beam cursor shape.
+ */
+#define GLFW_IBEAM_CURSOR 0x00036002
+/*! @brief The crosshair cursor shape.
+ *
+ * The crosshair cursor shape.
+ */
+#define GLFW_CROSSHAIR_CURSOR 0x00036003
+/*! @brief The pointing hand cursor shape.
+ *
+ * The pointing hand cursor shape.
+ */
+#define GLFW_POINTING_HAND_CURSOR 0x00036004
+/*! @brief The horizontal resize/move arrow shape.
+ *
+ * The horizontal resize/move arrow shape. This is usually a horizontal
+ * double-headed arrow.
+ */
+#define GLFW_RESIZE_EW_CURSOR 0x00036005
+/*! @brief The vertical resize/move arrow shape.
+ *
+ * The vertical resize/move shape. This is usually a vertical double-headed
+ * arrow.
+ */
+#define GLFW_RESIZE_NS_CURSOR 0x00036006
+/*! @brief The top-left to bottom-right diagonal resize/move arrow shape.
+ *
+ * The top-left to bottom-right diagonal resize/move shape. This is usually
+ * a diagonal double-headed arrow.
+ *
+ * @note @macos This shape is provided by a private system API and may fail
+ * with @ref GLFW_CURSOR_UNAVAILABLE in the future.
+ *
+ * @note @wayland This shape is provided by a newer standard not supported by
+ * all cursor themes.
+ *
+ * @note @x11 This shape is provided by a newer standard not supported by all
+ * cursor themes.
+ */
+#define GLFW_RESIZE_NWSE_CURSOR 0x00036007
+/*! @brief The top-right to bottom-left diagonal resize/move arrow shape.
+ *
+ * The top-right to bottom-left diagonal resize/move shape. This is usually
+ * a diagonal double-headed arrow.
+ *
+ * @note @macos This shape is provided by a private system API and may fail
+ * with @ref GLFW_CURSOR_UNAVAILABLE in the future.
+ *
+ * @note @wayland This shape is provided by a newer standard not supported by
+ * all cursor themes.
+ *
+ * @note @x11 This shape is provided by a newer standard not supported by all
+ * cursor themes.
+ */
+#define GLFW_RESIZE_NESW_CURSOR 0x00036008
+/*! @brief The omni-directional resize/move cursor shape.
+ *
+ * The omni-directional resize cursor/move shape. This is usually either
+ * a combined horizontal and vertical double-headed arrow or a grabbing hand.
+ */
+#define GLFW_RESIZE_ALL_CURSOR 0x00036009
+/*! @brief The operation-not-allowed shape.
+ *
+ * The operation-not-allowed shape. This is usually a circle with a diagonal
+ * line through it.
+ *
+ * @note @wayland This shape is provided by a newer standard not supported by
+ * all cursor themes.
+ *
+ * @note @x11 This shape is provided by a newer standard not supported by all
+ * cursor themes.
+ */
+#define GLFW_NOT_ALLOWED_CURSOR 0x0003600A
+/*! @brief Legacy name for compatibility.
+ *
+ * This is an alias for compatibility with earlier versions.
+ */
+#define GLFW_HRESIZE_CURSOR GLFW_RESIZE_EW_CURSOR
+/*! @brief Legacy name for compatibility.
+ *
+ * This is an alias for compatibility with earlier versions.
+ */
+#define GLFW_VRESIZE_CURSOR GLFW_RESIZE_NS_CURSOR
+/*! @brief Legacy name for compatibility.
+ *
+ * This is an alias for compatibility with earlier versions.
+ */
+#define GLFW_HAND_CURSOR GLFW_POINTING_HAND_CURSOR
+/*! @} */
+
+#define GLFW_CONNECTED 0x00040001
+#define GLFW_DISCONNECTED 0x00040002
+
+/*! @addtogroup init
+ * @{ */
+/*! @brief Joystick hat buttons init hint.
+ *
+ * Joystick hat buttons [init hint](@ref GLFW_JOYSTICK_HAT_BUTTONS).
+ */
+#define GLFW_JOYSTICK_HAT_BUTTONS 0x00050001
+/*! @brief ANGLE rendering backend init hint.
+ *
+ * ANGLE rendering backend [init hint](@ref GLFW_ANGLE_PLATFORM_TYPE_hint).
+ */
+#define GLFW_ANGLE_PLATFORM_TYPE 0x00050002
+/*! @brief Platform selection init hint.
+ *
+ * Platform selection [init hint](@ref GLFW_PLATFORM).
+ */
+#define GLFW_PLATFORM 0x00050003
+/*! @brief macOS specific init hint.
+ *
+ * macOS specific [init hint](@ref GLFW_COCOA_CHDIR_RESOURCES_hint).
+ */
+#define GLFW_COCOA_CHDIR_RESOURCES 0x00051001
+/*! @brief macOS specific init hint.
+ *
+ * macOS specific [init hint](@ref GLFW_COCOA_MENUBAR_hint).
+ */
+#define GLFW_COCOA_MENUBAR 0x00051002
+/*! @brief X11 specific init hint.
+ *
+ * X11 specific [init hint](@ref GLFW_X11_XCB_VULKAN_SURFACE_hint).
+ */
+#define GLFW_X11_XCB_VULKAN_SURFACE 0x00052001
+/*! @brief Wayland specific init hint.
+ *
+ * Wayland specific [init hint](@ref GLFW_WAYLAND_LIBDECOR_hint).
+ */
+#define GLFW_WAYLAND_LIBDECOR 0x00053001
+/*! @} */
+
+/*! @addtogroup init
+ * @{ */
+/*! @brief Hint value that enables automatic platform selection.
+ *
+ * Hint value for @ref GLFW_PLATFORM that enables automatic platform selection.
+ */
+#define GLFW_ANY_PLATFORM 0x00060000
+#define GLFW_PLATFORM_WIN32 0x00060001
+#define GLFW_PLATFORM_COCOA 0x00060002
+#define GLFW_PLATFORM_WAYLAND 0x00060003
+#define GLFW_PLATFORM_X11 0x00060004
+#define GLFW_PLATFORM_NULL 0x00060005
+/*! @} */
+
+#define GLFW_DONT_CARE -1
+
+
+/*************************************************************************
+ * GLFW API types
+ *************************************************************************/
+
+/*! @brief Client API function pointer type.
+ *
+ * Generic function pointer used for returning client API function pointers
+ * without forcing a cast from a regular pointer.
+ *
+ * @sa @ref context_glext
+ * @sa @ref glfwGetProcAddress
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup context
+ */
+typedef void (*GLFWglproc)(void);
+
+/*! @brief Vulkan API function pointer type.
+ *
+ * Generic function pointer used for returning Vulkan API function pointers
+ * without forcing a cast from a regular pointer.
+ *
+ * @sa @ref vulkan_proc
+ * @sa @ref glfwGetInstanceProcAddress
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup vulkan
+ */
+typedef void (*GLFWvkproc)(void);
+
+/*! @brief Opaque monitor object.
+ *
+ * Opaque monitor object.
+ *
+ * @see @ref monitor_object
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup monitor
+ */
+typedef struct GLFWmonitor GLFWmonitor;
+
+/*! @brief Opaque window object.
+ *
+ * Opaque window object.
+ *
+ * @see @ref window_object
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+typedef struct GLFWwindow GLFWwindow;
+
+/*! @brief Opaque cursor object.
+ *
+ * Opaque cursor object.
+ *
+ * @see @ref cursor_object
+ *
+ * @since Added in version 3.1.
+ *
+ * @ingroup input
+ */
+typedef struct GLFWcursor GLFWcursor;
+
+/*! @brief The function pointer type for memory allocation callbacks.
+ *
+ * This is the function pointer type for memory allocation callbacks. A memory
+ * allocation callback function has the following signature:
+ * @code
+ * void* function_name(size_t size, void* user)
+ * @endcode
+ *
+ * This function must return either a memory block at least `size` bytes long,
+ * or `NULL` if allocation failed. Note that not all parts of GLFW handle allocation
+ * failures gracefully yet.
+ *
+ * This function must support being called during @ref glfwInit but before the library is
+ * flagged as initialized, as well as during @ref glfwTerminate after the library is no
+ * longer flagged as initialized.
+ *
+ * Any memory allocated via this function will be deallocated via the same allocator
+ * during library termination or earlier.
+ *
+ * Any memory allocated via this function must be suitably aligned for any object type.
+ * If you are using C99 or earlier, this alignment is platform-dependent but will be the
+ * same as what `malloc` provides. If you are using C11 or later, this is the value of
+ * `alignof(max_align_t)`.
+ *
+ * The size will always be greater than zero. Allocations of size zero are filtered out
+ * before reaching the custom allocator.
+ *
+ * If this function returns `NULL`, GLFW will emit @ref GLFW_OUT_OF_MEMORY.
+ *
+ * This function must not call any GLFW function.
+ *
+ * @param[in] size The minimum size, in bytes, of the memory block.
+ * @param[in] user The user-defined pointer from the allocator.
+ * @return The address of the newly allocated memory block, or `NULL` if an
+ * error occurred.
+ *
+ * @pointer_lifetime The returned memory block must be valid at least until it
+ * is deallocated.
+ *
+ * @reentrancy This function should not call any GLFW function.
+ *
+ * @thread_safety This function must support being called from any thread that calls GLFW
+ * functions.
+ *
+ * @sa @ref init_allocator
+ * @sa @ref GLFWallocator
+ *
+ * @since Added in version 3.4.
+ *
+ * @ingroup init
+ */
+typedef void* (* GLFWallocatefun)(size_t size, void* user);
+
+/*! @brief The function pointer type for memory reallocation callbacks.
+ *
+ * This is the function pointer type for memory reallocation callbacks.
+ * A memory reallocation callback function has the following signature:
+ * @code
+ * void* function_name(void* block, size_t size, void* user)
+ * @endcode
+ *
+ * This function must return a memory block at least `size` bytes long, or
+ * `NULL` if allocation failed. Note that not all parts of GLFW handle allocation
+ * failures gracefully yet.
+ *
+ * This function must support being called during @ref glfwInit but before the library is
+ * flagged as initialized, as well as during @ref glfwTerminate after the library is no
+ * longer flagged as initialized.
+ *
+ * Any memory allocated via this function will be deallocated via the same allocator
+ * during library termination or earlier.
+ *
+ * Any memory allocated via this function must be suitably aligned for any object type.
+ * If you are using C99 or earlier, this alignment is platform-dependent but will be the
+ * same as what `realloc` provides. If you are using C11 or later, this is the value of
+ * `alignof(max_align_t)`.
+ *
+ * The block address will never be `NULL` and the size will always be greater than zero.
+ * Reallocations of a block to size zero are converted into deallocations before reaching
+ * the custom allocator. Reallocations of `NULL` to a non-zero size are converted into
+ * regular allocations before reaching the custom allocator.
+ *
+ * If this function returns `NULL`, GLFW will emit @ref GLFW_OUT_OF_MEMORY.
+ *
+ * This function must not call any GLFW function.
+ *
+ * @param[in] block The address of the memory block to reallocate.
+ * @param[in] size The new minimum size, in bytes, of the memory block.
+ * @param[in] user The user-defined pointer from the allocator.
+ * @return The address of the newly allocated or resized memory block, or
+ * `NULL` if an error occurred.
+ *
+ * @pointer_lifetime The returned memory block must be valid at least until it
+ * is deallocated.
+ *
+ * @reentrancy This function should not call any GLFW function.
+ *
+ * @thread_safety This function must support being called from any thread that calls GLFW
+ * functions.
+ *
+ * @sa @ref init_allocator
+ * @sa @ref GLFWallocator
+ *
+ * @since Added in version 3.4.
+ *
+ * @ingroup init
+ */
+typedef void* (* GLFWreallocatefun)(void* block, size_t size, void* user);
+
+/*! @brief The function pointer type for memory deallocation callbacks.
+ *
+ * This is the function pointer type for memory deallocation callbacks.
+ * A memory deallocation callback function has the following signature:
+ * @code
+ * void function_name(void* block, void* user)
+ * @endcode
+ *
+ * This function may deallocate the specified memory block. This memory block
+ * will have been allocated with the same allocator.
+ *
+ * This function must support being called during @ref glfwInit but before the library is
+ * flagged as initialized, as well as during @ref glfwTerminate after the library is no
+ * longer flagged as initialized.
+ *
+ * The block address will never be `NULL`. Deallocations of `NULL` are filtered out
+ * before reaching the custom allocator.
+ *
+ * If this function returns `NULL`, GLFW will emit @ref GLFW_OUT_OF_MEMORY.
+ *
+ * This function must not call any GLFW function.
+ *
+ * @param[in] block The address of the memory block to deallocate.
+ * @param[in] user The user-defined pointer from the allocator.
+ *
+ * @pointer_lifetime The specified memory block will not be accessed by GLFW
+ * after this function is called.
+ *
+ * @reentrancy This function should not call any GLFW function.
+ *
+ * @thread_safety This function must support being called from any thread that calls GLFW
+ * functions.
+ *
+ * @sa @ref init_allocator
+ * @sa @ref GLFWallocator
+ *
+ * @since Added in version 3.4.
+ *
+ * @ingroup init
+ */
+typedef void (* GLFWdeallocatefun)(void* block, void* user);
+
+/*! @brief The function pointer type for error callbacks.
+ *
+ * This is the function pointer type for error callbacks. An error callback
+ * function has the following signature:
+ * @code
+ * void callback_name(int error_code, const char* description)
+ * @endcode
+ *
+ * @param[in] error_code An [error code](@ref errors). Future releases may add
+ * more error codes.
+ * @param[in] description A UTF-8 encoded string describing the error.
+ *
+ * @pointer_lifetime The error description string is valid until the callback
+ * function returns.
+ *
+ * @sa @ref error_handling
+ * @sa @ref glfwSetErrorCallback
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup init
+ */
+typedef void (* GLFWerrorfun)(int error_code, const char* description);
+
+/*! @brief The function pointer type for window position callbacks.
+ *
+ * This is the function pointer type for window position callbacks. A window
+ * position callback function has the following signature:
+ * @code
+ * void callback_name(GLFWwindow* window, int xpos, int ypos)
+ * @endcode
+ *
+ * @param[in] window The window that was moved.
+ * @param[in] xpos The new x-coordinate, in screen coordinates, of the
+ * upper-left corner of the content area of the window.
+ * @param[in] ypos The new y-coordinate, in screen coordinates, of the
+ * upper-left corner of the content area of the window.
+ *
+ * @sa @ref window_pos
+ * @sa @ref glfwSetWindowPosCallback
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+typedef void (* GLFWwindowposfun)(GLFWwindow* window, int xpos, int ypos);
+
+/*! @brief The function pointer type for window size callbacks.
+ *
+ * This is the function pointer type for window size callbacks. A window size
+ * callback function has the following signature:
+ * @code
+ * void callback_name(GLFWwindow* window, int width, int height)
+ * @endcode
+ *
+ * @param[in] window The window that was resized.
+ * @param[in] width The new width, in screen coordinates, of the window.
+ * @param[in] height The new height, in screen coordinates, of the window.
+ *
+ * @sa @ref window_size
+ * @sa @ref glfwSetWindowSizeCallback
+ *
+ * @since Added in version 1.0.
+ * @glfw3 Added window handle parameter.
+ *
+ * @ingroup window
+ */
+typedef void (* GLFWwindowsizefun)(GLFWwindow* window, int width, int height);
+
+/*! @brief The function pointer type for window close callbacks.
+ *
+ * This is the function pointer type for window close callbacks. A window
+ * close callback function has the following signature:
+ * @code
+ * void function_name(GLFWwindow* window)
+ * @endcode
+ *
+ * @param[in] window The window that the user attempted to close.
+ *
+ * @sa @ref window_close
+ * @sa @ref glfwSetWindowCloseCallback
+ *
+ * @since Added in version 2.5.
+ * @glfw3 Added window handle parameter.
+ *
+ * @ingroup window
+ */
+typedef void (* GLFWwindowclosefun)(GLFWwindow* window);
+
+/*! @brief The function pointer type for window content refresh callbacks.
+ *
+ * This is the function pointer type for window content refresh callbacks.
+ * A window content refresh callback function has the following signature:
+ * @code
+ * void function_name(GLFWwindow* window);
+ * @endcode
+ *
+ * @param[in] window The window whose content needs to be refreshed.
+ *
+ * @sa @ref window_refresh
+ * @sa @ref glfwSetWindowRefreshCallback
+ *
+ * @since Added in version 2.5.
+ * @glfw3 Added window handle parameter.
+ *
+ * @ingroup window
+ */
+typedef void (* GLFWwindowrefreshfun)(GLFWwindow* window);
+
+/*! @brief The function pointer type for window focus callbacks.
+ *
+ * This is the function pointer type for window focus callbacks. A window
+ * focus callback function has the following signature:
+ * @code
+ * void function_name(GLFWwindow* window, int focused)
+ * @endcode
+ *
+ * @param[in] window The window that gained or lost input focus.
+ * @param[in] focused `GLFW_TRUE` if the window was given input focus, or
+ * `GLFW_FALSE` if it lost it.
+ *
+ * @sa @ref window_focus
+ * @sa @ref glfwSetWindowFocusCallback
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+typedef void (* GLFWwindowfocusfun)(GLFWwindow* window, int focused);
+
+/*! @brief The function pointer type for window iconify callbacks.
+ *
+ * This is the function pointer type for window iconify callbacks. A window
+ * iconify callback function has the following signature:
+ * @code
+ * void function_name(GLFWwindow* window, int iconified)
+ * @endcode
+ *
+ * @param[in] window The window that was iconified or restored.
+ * @param[in] iconified `GLFW_TRUE` if the window was iconified, or
+ * `GLFW_FALSE` if it was restored.
+ *
+ * @sa @ref window_iconify
+ * @sa @ref glfwSetWindowIconifyCallback
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+typedef void (* GLFWwindowiconifyfun)(GLFWwindow* window, int iconified);
+
+/*! @brief The function pointer type for window maximize callbacks.
+ *
+ * This is the function pointer type for window maximize callbacks. A window
+ * maximize callback function has the following signature:
+ * @code
+ * void function_name(GLFWwindow* window, int maximized)
+ * @endcode
+ *
+ * @param[in] window The window that was maximized or restored.
+ * @param[in] maximized `GLFW_TRUE` if the window was maximized, or
+ * `GLFW_FALSE` if it was restored.
+ *
+ * @sa @ref window_maximize
+ * @sa glfwSetWindowMaximizeCallback
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup window
+ */
+typedef void (* GLFWwindowmaximizefun)(GLFWwindow* window, int maximized);
+
+/*! @brief The function pointer type for framebuffer size callbacks.
+ *
+ * This is the function pointer type for framebuffer size callbacks.
+ * A framebuffer size callback function has the following signature:
+ * @code
+ * void function_name(GLFWwindow* window, int width, int height)
+ * @endcode
+ *
+ * @param[in] window The window whose framebuffer was resized.
+ * @param[in] width The new width, in pixels, of the framebuffer.
+ * @param[in] height The new height, in pixels, of the framebuffer.
+ *
+ * @sa @ref window_fbsize
+ * @sa @ref glfwSetFramebufferSizeCallback
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+typedef void (* GLFWframebuffersizefun)(GLFWwindow* window, int width, int height);
+
+/*! @brief The function pointer type for window content scale callbacks.
+ *
+ * This is the function pointer type for window content scale callbacks.
+ * A window content scale callback function has the following signature:
+ * @code
+ * void function_name(GLFWwindow* window, float xscale, float yscale)
+ * @endcode
+ *
+ * @param[in] window The window whose content scale changed.
+ * @param[in] xscale The new x-axis content scale of the window.
+ * @param[in] yscale The new y-axis content scale of the window.
+ *
+ * @sa @ref window_scale
+ * @sa @ref glfwSetWindowContentScaleCallback
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup window
+ */
+typedef void (* GLFWwindowcontentscalefun)(GLFWwindow* window, float xscale, float yscale);
+
+/*! @brief The function pointer type for mouse button callbacks.
+ *
+ * This is the function pointer type for mouse button callback functions.
+ * A mouse button callback function has the following signature:
+ * @code
+ * void function_name(GLFWwindow* window, int button, int action, int mods)
+ * @endcode
+ *
+ * @param[in] window The window that received the event.
+ * @param[in] button The [mouse button](@ref buttons) that was pressed or
+ * released.
+ * @param[in] action One of `GLFW_PRESS` or `GLFW_RELEASE`. Future releases
+ * may add more actions.
+ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were
+ * held down.
+ *
+ * @sa @ref input_mouse_button
+ * @sa @ref glfwSetMouseButtonCallback
+ *
+ * @since Added in version 1.0.
+ * @glfw3 Added window handle and modifier mask parameters.
+ *
+ * @ingroup input
+ */
+typedef void (* GLFWmousebuttonfun)(GLFWwindow* window, int button, int action, int mods);
+
+/*! @brief The function pointer type for cursor position callbacks.
+ *
+ * This is the function pointer type for cursor position callbacks. A cursor
+ * position callback function has the following signature:
+ * @code
+ * void function_name(GLFWwindow* window, double xpos, double ypos);
+ * @endcode
+ *
+ * @param[in] window The window that received the event.
+ * @param[in] xpos The new cursor x-coordinate, relative to the left edge of
+ * the content area.
+ * @param[in] ypos The new cursor y-coordinate, relative to the top edge of the
+ * content area.
+ *
+ * @sa @ref cursor_pos
+ * @sa @ref glfwSetCursorPosCallback
+ *
+ * @since Added in version 3.0. Replaces `GLFWmouseposfun`.
+ *
+ * @ingroup input
+ */
+typedef void (* GLFWcursorposfun)(GLFWwindow* window, double xpos, double ypos);
+
+/*! @brief The function pointer type for cursor enter/leave callbacks.
+ *
+ * This is the function pointer type for cursor enter/leave callbacks.
+ * A cursor enter/leave callback function has the following signature:
+ * @code
+ * void function_name(GLFWwindow* window, int entered)
+ * @endcode
+ *
+ * @param[in] window The window that received the event.
+ * @param[in] entered `GLFW_TRUE` if the cursor entered the window's content
+ * area, or `GLFW_FALSE` if it left it.
+ *
+ * @sa @ref cursor_enter
+ * @sa @ref glfwSetCursorEnterCallback
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup input
+ */
+typedef void (* GLFWcursorenterfun)(GLFWwindow* window, int entered);
+
+/*! @brief The function pointer type for scroll callbacks.
+ *
+ * This is the function pointer type for scroll callbacks. A scroll callback
+ * function has the following signature:
+ * @code
+ * void function_name(GLFWwindow* window, double xoffset, double yoffset)
+ * @endcode
+ *
+ * @param[in] window The window that received the event.
+ * @param[in] xoffset The scroll offset along the x-axis.
+ * @param[in] yoffset The scroll offset along the y-axis.
+ *
+ * @sa @ref scrolling
+ * @sa @ref glfwSetScrollCallback
+ *
+ * @since Added in version 3.0. Replaces `GLFWmousewheelfun`.
+ *
+ * @ingroup input
+ */
+typedef void (* GLFWscrollfun)(GLFWwindow* window, double xoffset, double yoffset);
+
+/*! @brief The function pointer type for keyboard key callbacks.
+ *
+ * This is the function pointer type for keyboard key callbacks. A keyboard
+ * key callback function has the following signature:
+ * @code
+ * void function_name(GLFWwindow* window, int key, int scancode, int action, int mods)
+ * @endcode
+ *
+ * @param[in] window The window that received the event.
+ * @param[in] key The [keyboard key](@ref keys) that was pressed or released.
+ * @param[in] scancode The platform-specific scancode of the key.
+ * @param[in] action `GLFW_PRESS`, `GLFW_RELEASE` or `GLFW_REPEAT`. Future
+ * releases may add more actions.
+ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were
+ * held down.
+ *
+ * @sa @ref input_key
+ * @sa @ref glfwSetKeyCallback
+ *
+ * @since Added in version 1.0.
+ * @glfw3 Added window handle, scancode and modifier mask parameters.
+ *
+ * @ingroup input
+ */
+typedef void (* GLFWkeyfun)(GLFWwindow* window, int key, int scancode, int action, int mods);
+
+/*! @brief The function pointer type for Unicode character callbacks.
+ *
+ * This is the function pointer type for Unicode character callbacks.
+ * A Unicode character callback function has the following signature:
+ * @code
+ * void function_name(GLFWwindow* window, unsigned int codepoint)
+ * @endcode
+ *
+ * @param[in] window The window that received the event.
+ * @param[in] codepoint The Unicode code point of the character.
+ *
+ * @sa @ref input_char
+ * @sa @ref glfwSetCharCallback
+ *
+ * @since Added in version 2.4.
+ * @glfw3 Added window handle parameter.
+ *
+ * @ingroup input
+ */
+typedef void (* GLFWcharfun)(GLFWwindow* window, unsigned int codepoint);
+
+/*! @brief The function pointer type for Unicode character with modifiers
+ * callbacks.
+ *
+ * This is the function pointer type for Unicode character with modifiers
+ * callbacks. It is called for each input character, regardless of what
+ * modifier keys are held down. A Unicode character with modifiers callback
+ * function has the following signature:
+ * @code
+ * void function_name(GLFWwindow* window, unsigned int codepoint, int mods)
+ * @endcode
+ *
+ * @param[in] window The window that received the event.
+ * @param[in] codepoint The Unicode code point of the character.
+ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were
+ * held down.
+ *
+ * @sa @ref input_char
+ * @sa @ref glfwSetCharModsCallback
+ *
+ * @deprecated Scheduled for removal in version 4.0.
+ *
+ * @since Added in version 3.1.
+ *
+ * @ingroup input
+ */
+typedef void (* GLFWcharmodsfun)(GLFWwindow* window, unsigned int codepoint, int mods);
+
+/*! @brief The function pointer type for path drop callbacks.
+ *
+ * This is the function pointer type for path drop callbacks. A path drop
+ * callback function has the following signature:
+ * @code
+ * void function_name(GLFWwindow* window, int path_count, const char* paths[])
+ * @endcode
+ *
+ * @param[in] window The window that received the event.
+ * @param[in] path_count The number of dropped paths.
+ * @param[in] paths The UTF-8 encoded file and/or directory path names.
+ *
+ * @pointer_lifetime The path array and its strings are valid until the
+ * callback function returns.
+ *
+ * @sa @ref path_drop
+ * @sa @ref glfwSetDropCallback
+ *
+ * @since Added in version 3.1.
+ *
+ * @ingroup input
+ */
+typedef void (* GLFWdropfun)(GLFWwindow* window, int path_count, const char* paths[]);
+
+/*! @brief The function pointer type for monitor configuration callbacks.
+ *
+ * This is the function pointer type for monitor configuration callbacks.
+ * A monitor callback function has the following signature:
+ * @code
+ * void function_name(GLFWmonitor* monitor, int event)
+ * @endcode
+ *
+ * @param[in] monitor The monitor that was connected or disconnected.
+ * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`. Future
+ * releases may add more events.
+ *
+ * @sa @ref monitor_event
+ * @sa @ref glfwSetMonitorCallback
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup monitor
+ */
+typedef void (* GLFWmonitorfun)(GLFWmonitor* monitor, int event);
+
+/*! @brief The function pointer type for joystick configuration callbacks.
+ *
+ * This is the function pointer type for joystick configuration callbacks.
+ * A joystick configuration callback function has the following signature:
+ * @code
+ * void function_name(int jid, int event)
+ * @endcode
+ *
+ * @param[in] jid The joystick that was connected or disconnected.
+ * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`. Future
+ * releases may add more events.
+ *
+ * @sa @ref joystick_event
+ * @sa @ref glfwSetJoystickCallback
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup input
+ */
+typedef void (* GLFWjoystickfun)(int jid, int event);
+
+/*! @brief Video mode type.
+ *
+ * This describes a single video mode.
+ *
+ * @sa @ref monitor_modes
+ * @sa @ref glfwGetVideoMode
+ * @sa @ref glfwGetVideoModes
+ *
+ * @since Added in version 1.0.
+ * @glfw3 Added refresh rate member.
+ *
+ * @ingroup monitor
+ */
+typedef struct GLFWvidmode
+{
+ /*! The width, in screen coordinates, of the video mode.
+ */
+ int width;
+ /*! The height, in screen coordinates, of the video mode.
+ */
+ int height;
+ /*! The bit depth of the red channel of the video mode.
+ */
+ int redBits;
+ /*! The bit depth of the green channel of the video mode.
+ */
+ int greenBits;
+ /*! The bit depth of the blue channel of the video mode.
+ */
+ int blueBits;
+ /*! The refresh rate, in Hz, of the video mode.
+ */
+ int refreshRate;
+} GLFWvidmode;
+
+/*! @brief Gamma ramp.
+ *
+ * This describes the gamma ramp for a monitor.
+ *
+ * @sa @ref monitor_gamma
+ * @sa @ref glfwGetGammaRamp
+ * @sa @ref glfwSetGammaRamp
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup monitor
+ */
+typedef struct GLFWgammaramp
+{
+ /*! An array of value describing the response of the red channel.
+ */
+ unsigned short* red;
+ /*! An array of value describing the response of the green channel.
+ */
+ unsigned short* green;
+ /*! An array of value describing the response of the blue channel.
+ */
+ unsigned short* blue;
+ /*! The number of elements in each array.
+ */
+ unsigned int size;
+} GLFWgammaramp;
+
+/*! @brief Image data.
+ *
+ * This describes a single 2D image. See the documentation for each related
+ * function what the expected pixel format is.
+ *
+ * @sa @ref cursor_custom
+ * @sa @ref window_icon
+ *
+ * @since Added in version 2.1.
+ * @glfw3 Removed format and bytes-per-pixel members.
+ *
+ * @ingroup window
+ */
+typedef struct GLFWimage
+{
+ /*! The width, in pixels, of this image.
+ */
+ int width;
+ /*! The height, in pixels, of this image.
+ */
+ int height;
+ /*! The pixel data of this image, arranged left-to-right, top-to-bottom.
+ */
+ unsigned char* pixels;
+} GLFWimage;
+
+/*! @brief Gamepad input state
+ *
+ * This describes the input state of a gamepad.
+ *
+ * @sa @ref gamepad
+ * @sa @ref glfwGetGamepadState
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup input
+ */
+typedef struct GLFWgamepadstate
+{
+ /*! The states of each [gamepad button](@ref gamepad_buttons), `GLFW_PRESS`
+ * or `GLFW_RELEASE`.
+ */
+ unsigned char buttons[15];
+ /*! The states of each [gamepad axis](@ref gamepad_axes), in the range -1.0
+ * to 1.0 inclusive.
+ */
+ float axes[6];
+} GLFWgamepadstate;
+
+/*! @brief Custom heap memory allocator.
+ *
+ * This describes a custom heap memory allocator for GLFW. To set an allocator, pass it
+ * to @ref glfwInitAllocator before initializing the library.
+ *
+ * @sa @ref init_allocator
+ * @sa @ref glfwInitAllocator
+ *
+ * @since Added in version 3.4.
+ *
+ * @ingroup init
+ */
+typedef struct GLFWallocator
+{
+ /*! The memory allocation function. See @ref GLFWallocatefun for details about
+ * allocation function.
+ */
+ GLFWallocatefun allocate;
+ /*! The memory reallocation function. See @ref GLFWreallocatefun for details about
+ * reallocation function.
+ */
+ GLFWreallocatefun reallocate;
+ /*! The memory deallocation function. See @ref GLFWdeallocatefun for details about
+ * deallocation function.
+ */
+ GLFWdeallocatefun deallocate;
+ /*! The user pointer for this custom allocator. This value will be passed to the
+ * allocator functions.
+ */
+ void* user;
+} GLFWallocator;
+
+
+/*************************************************************************
+ * GLFW API functions
+ *************************************************************************/
+
+/*! @brief Initializes the GLFW library.
+ *
+ * This function initializes the GLFW library. Before most GLFW functions can
+ * be used, GLFW must be initialized, and before an application terminates GLFW
+ * should be terminated in order to free any resources allocated during or
+ * after initialization.
+ *
+ * If this function fails, it calls @ref glfwTerminate before returning. If it
+ * succeeds, you should call @ref glfwTerminate before the application exits.
+ *
+ * Additional calls to this function after successful initialization but before
+ * termination will return `GLFW_TRUE` immediately.
+ *
+ * The @ref GLFW_PLATFORM init hint controls which platforms are considered during
+ * initialization. This also depends on which platforms the library was compiled to
+ * support.
+ *
+ * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_PLATFORM_UNAVAILABLE and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @remark @macos This function will change the current directory of the
+ * application to the `Contents/Resources` subdirectory of the application's
+ * bundle, if present. This can be disabled with the @ref
+ * GLFW_COCOA_CHDIR_RESOURCES init hint.
+ *
+ * @remark @macos This function will create the main menu and dock icon for the
+ * application. If GLFW finds a `MainMenu.nib` it is loaded and assumed to
+ * contain a menu bar. Otherwise a minimal menu bar is created manually with
+ * common commands like Hide, Quit and About. The About entry opens a minimal
+ * about dialog with information from the application's bundle. The menu bar
+ * and dock icon can be disabled entirely with the @ref GLFW_COCOA_MENUBAR init
+ * hint.
+ *
+ * @remark __Wayland, X11:__ If the library was compiled with support for both
+ * Wayland and X11, and the @ref GLFW_PLATFORM init hint is set to
+ * `GLFW_ANY_PLATFORM`, the `XDG_SESSION_TYPE` environment variable affects
+ * which platform is picked. If the environment variable is not set, or is set
+ * to something other than `wayland` or `x11`, the regular detection mechanism
+ * will be used instead.
+ *
+ * @remark @x11 This function will set the `LC_CTYPE` category of the
+ * application locale according to the current environment if that category is
+ * still "C". This is because the "C" locale breaks Unicode text input.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref intro_init
+ * @sa @ref glfwInitHint
+ * @sa @ref glfwInitAllocator
+ * @sa @ref glfwTerminate
+ *
+ * @since Added in version 1.0.
+ *
+ * @ingroup init
+ */
+GLFWAPI int glfwInit(void);
+
+/*! @brief Terminates the GLFW library.
+ *
+ * This function destroys all remaining windows and cursors, restores any
+ * modified gamma ramps and frees any other allocated resources. Once this
+ * function is called, you must again call @ref glfwInit successfully before
+ * you will be able to use most GLFW functions.
+ *
+ * If GLFW has been successfully initialized, this function should be called
+ * before the application exits. If initialization fails, there is no need to
+ * call this function, as it is called by @ref glfwInit before it returns
+ * failure.
+ *
+ * This function has no effect if GLFW is not initialized.
+ *
+ * @errors Possible errors include @ref GLFW_PLATFORM_ERROR.
+ *
+ * @remark This function may be called before @ref glfwInit.
+ *
+ * @warning The contexts of any remaining windows must not be current on any
+ * other thread when this function is called.
+ *
+ * @reentrancy This function must not be called from a callback.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref intro_init
+ * @sa @ref glfwInit
+ *
+ * @since Added in version 1.0.
+ *
+ * @ingroup init
+ */
+GLFWAPI void glfwTerminate(void);
+
+/*! @brief Sets the specified init hint to the desired value.
+ *
+ * This function sets hints for the next initialization of GLFW.
+ *
+ * The values you set hints to are never reset by GLFW, but they only take
+ * effect during initialization. Once GLFW has been initialized, any values
+ * you set will be ignored until the library is terminated and initialized
+ * again.
+ *
+ * Some hints are platform specific. These may be set on any platform but they
+ * will only affect their specific platform. Other platforms will ignore them.
+ * Setting these hints requires no platform specific headers or functions.
+ *
+ * @param[in] hint The [init hint](@ref init_hints) to set.
+ * @param[in] value The new value of the init hint.
+ *
+ * @errors Possible errors include @ref GLFW_INVALID_ENUM and @ref
+ * GLFW_INVALID_VALUE.
+ *
+ * @remarks This function may be called before @ref glfwInit.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa init_hints
+ * @sa glfwInit
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup init
+ */
+GLFWAPI void glfwInitHint(int hint, int value);
+
+/*! @brief Sets the init allocator to the desired value.
+ *
+ * To use the default allocator, call this function with a `NULL` argument.
+ *
+ * If you specify an allocator struct, every member must be a valid function
+ * pointer. If any member is `NULL`, this function will emit @ref
+ * GLFW_INVALID_VALUE and the init allocator will be unchanged.
+ *
+ * The functions in the allocator must fulfil a number of requirements. See the
+ * documentation for @ref GLFWallocatefun, @ref GLFWreallocatefun and @ref
+ * GLFWdeallocatefun for details.
+ *
+ * @param[in] allocator The allocator to use at the next initialization, or
+ * `NULL` to use the default one.
+ *
+ * @errors Possible errors include @ref GLFW_INVALID_VALUE.
+ *
+ * @pointer_lifetime The specified allocator is copied before this function
+ * returns.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref init_allocator
+ * @sa @ref glfwInit
+ *
+ * @since Added in version 3.4.
+ *
+ * @ingroup init
+ */
+GLFWAPI void glfwInitAllocator(const GLFWallocator* allocator);
+
+#if defined(VK_VERSION_1_0)
+
+/*! @brief Sets the desired Vulkan `vkGetInstanceProcAddr` function.
+ *
+ * This function sets the `vkGetInstanceProcAddr` function that GLFW will use for all
+ * Vulkan related entry point queries.
+ *
+ * This feature is mostly useful on macOS, if your copy of the Vulkan loader is in
+ * a location where GLFW cannot find it through dynamic loading, or if you are still
+ * using the static library version of the loader.
+ *
+ * If set to `NULL`, GLFW will try to load the Vulkan loader dynamically by its standard
+ * name and get this function from there. This is the default behavior.
+ *
+ * The standard name of the loader is `vulkan-1.dll` on Windows, `libvulkan.so.1` on
+ * Linux and other Unix-like systems and `libvulkan.1.dylib` on macOS. If your code is
+ * also loading it via these names then you probably don't need to use this function.
+ *
+ * The function address you set is never reset by GLFW, but it only takes effect during
+ * initialization. Once GLFW has been initialized, any updates will be ignored until the
+ * library is terminated and initialized again.
+ *
+ * @param[in] loader The address of the function to use, or `NULL`.
+ *
+ * @par Loader function signature
+ * @code
+ * PFN_vkVoidFunction vkGetInstanceProcAddr(VkInstance instance, const char* name)
+ * @endcode
+ * For more information about this function, see the
+ * [Vulkan Registry](https://www.khronos.org/registry/vulkan/).
+ *
+ * @errors None.
+ *
+ * @remark This function may be called before @ref glfwInit.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref vulkan_loader
+ * @sa @ref glfwInit
+ *
+ * @since Added in version 3.4.
+ *
+ * @ingroup init
+ */
+GLFWAPI void glfwInitVulkanLoader(PFN_vkGetInstanceProcAddr loader);
+
+#endif /*VK_VERSION_1_0*/
+
+/*! @brief Retrieves the version of the GLFW library.
+ *
+ * This function retrieves the major, minor and revision numbers of the GLFW
+ * library. It is intended for when you are using GLFW as a shared library and
+ * want to ensure that you are using the minimum required version.
+ *
+ * Any or all of the version arguments may be `NULL`.
+ *
+ * @param[out] major Where to store the major version number, or `NULL`.
+ * @param[out] minor Where to store the minor version number, or `NULL`.
+ * @param[out] rev Where to store the revision number, or `NULL`.
+ *
+ * @errors None.
+ *
+ * @remark This function may be called before @ref glfwInit.
+ *
+ * @thread_safety This function may be called from any thread.
+ *
+ * @sa @ref intro_version
+ * @sa @ref glfwGetVersionString
+ *
+ * @since Added in version 1.0.
+ *
+ * @ingroup init
+ */
+GLFWAPI void glfwGetVersion(int* major, int* minor, int* rev);
+
+/*! @brief Returns a string describing the compile-time configuration.
+ *
+ * This function returns the compile-time generated
+ * [version string](@ref intro_version_string) of the GLFW library binary. It describes
+ * the version, platforms, compiler and any platform or operating system specific
+ * compile-time options. It should not be confused with the OpenGL or OpenGL ES version
+ * string, queried with `glGetString`.
+ *
+ * __Do not use the version string__ to parse the GLFW library version. The
+ * @ref glfwGetVersion function provides the version of the running library
+ * binary in numerical format.
+ *
+ * __Do not use the version string__ to parse what platforms are supported. The @ref
+ * glfwPlatformSupported function lets you query platform support.
+ *
+ * @return The ASCII encoded GLFW version string.
+ *
+ * @errors None.
+ *
+ * @remark This function may be called before @ref glfwInit.
+ *
+ * @pointer_lifetime The returned string is static and compile-time generated.
+ *
+ * @thread_safety This function may be called from any thread.
+ *
+ * @sa @ref intro_version
+ * @sa @ref glfwGetVersion
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup init
+ */
+GLFWAPI const char* glfwGetVersionString(void);
+
+/*! @brief Returns and clears the last error for the calling thread.
+ *
+ * This function returns and clears the [error code](@ref errors) of the last
+ * error that occurred on the calling thread, and optionally a UTF-8 encoded
+ * human-readable description of it. If no error has occurred since the last
+ * call, it returns @ref GLFW_NO_ERROR (zero) and the description pointer is
+ * set to `NULL`.
+ *
+ * @param[in] description Where to store the error description pointer, or `NULL`.
+ * @return The last error code for the calling thread, or @ref GLFW_NO_ERROR
+ * (zero).
+ *
+ * @errors None.
+ *
+ * @pointer_lifetime The returned string is allocated and freed by GLFW. You
+ * should not free it yourself. It is guaranteed to be valid only until the
+ * next error occurs or the library is terminated.
+ *
+ * @remark This function may be called before @ref glfwInit.
+ *
+ * @thread_safety This function may be called from any thread.
+ *
+ * @sa @ref error_handling
+ * @sa @ref glfwSetErrorCallback
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup init
+ */
+GLFWAPI int glfwGetError(const char** description);
+
+/*! @brief Sets the error callback.
+ *
+ * This function sets the error callback, which is called with an error code
+ * and a human-readable description each time a GLFW error occurs.
+ *
+ * The error code is set before the callback is called. Calling @ref
+ * glfwGetError from the error callback will return the same value as the error
+ * code argument.
+ *
+ * The error callback is called on the thread where the error occurred. If you
+ * are using GLFW from multiple threads, your error callback needs to be
+ * written accordingly.
+ *
+ * Because the description string may have been generated specifically for that
+ * error, it is not guaranteed to be valid after the callback has returned. If
+ * you wish to use it after the callback returns, you need to make a copy.
+ *
+ * Once set, the error callback remains set even after the library has been
+ * terminated.
+ *
+ * @param[in] callback The new callback, or `NULL` to remove the currently set
+ * callback.
+ * @return The previously set callback, or `NULL` if no callback was set.
+ *
+ * @callback_signature
+ * @code
+ * void callback_name(int error_code, const char* description)
+ * @endcode
+ * For more information about the callback parameters, see the
+ * [callback pointer type](@ref GLFWerrorfun).
+ *
+ * @errors None.
+ *
+ * @remark This function may be called before @ref glfwInit.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref error_handling
+ * @sa @ref glfwGetError
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup init
+ */
+GLFWAPI GLFWerrorfun glfwSetErrorCallback(GLFWerrorfun callback);
+
+/*! @brief Returns the currently selected platform.
+ *
+ * This function returns the platform that was selected during initialization. The
+ * returned value will be one of `GLFW_PLATFORM_WIN32`, `GLFW_PLATFORM_COCOA`,
+ * `GLFW_PLATFORM_WAYLAND`, `GLFW_PLATFORM_X11` or `GLFW_PLATFORM_NULL`.
+ *
+ * @return The currently selected platform, or zero if an error occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function may be called from any thread.
+ *
+ * @sa @ref platform
+ * @sa @ref glfwPlatformSupported
+ *
+ * @since Added in version 3.4.
+ *
+ * @ingroup init
+ */
+GLFWAPI int glfwGetPlatform(void);
+
+/*! @brief Returns whether the library includes support for the specified platform.
+ *
+ * This function returns whether the library was compiled with support for the specified
+ * platform. The platform must be one of `GLFW_PLATFORM_WIN32`, `GLFW_PLATFORM_COCOA`,
+ * `GLFW_PLATFORM_WAYLAND`, `GLFW_PLATFORM_X11` or `GLFW_PLATFORM_NULL`.
+ *
+ * @param[in] platform The platform to query.
+ * @return `GLFW_TRUE` if the platform is supported, or `GLFW_FALSE` otherwise.
+ *
+ * @errors Possible errors include @ref GLFW_INVALID_ENUM.
+ *
+ * @remark This function may be called before @ref glfwInit.
+ *
+ * @thread_safety This function may be called from any thread.
+ *
+ * @sa @ref platform
+ * @sa @ref glfwGetPlatform
+ *
+ * @since Added in version 3.4.
+ *
+ * @ingroup init
+ */
+GLFWAPI int glfwPlatformSupported(int platform);
+
+/*! @brief Returns the currently connected monitors.
+ *
+ * This function returns an array of handles for all currently connected
+ * monitors. The primary monitor is always first in the returned array. If no
+ * monitors were found, this function returns `NULL`.
+ *
+ * @param[out] count Where to store the number of monitors in the returned
+ * array. This is set to zero if an error occurred.
+ * @return An array of monitor handles, or `NULL` if no monitors were found or
+ * if an [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @pointer_lifetime The returned array is allocated and freed by GLFW. You
+ * should not free it yourself. It is guaranteed to be valid only until the
+ * monitor configuration changes or the library is terminated.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref monitor_monitors
+ * @sa @ref monitor_event
+ * @sa @ref glfwGetPrimaryMonitor
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup monitor
+ */
+GLFWAPI GLFWmonitor** glfwGetMonitors(int* count);
+
+/*! @brief Returns the primary monitor.
+ *
+ * This function returns the primary monitor. This is usually the monitor
+ * where elements like the task bar or global menu bar are located.
+ *
+ * @return The primary monitor, or `NULL` if no monitors were found or if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @remark The primary monitor is always first in the array returned by @ref
+ * glfwGetMonitors.
+ *
+ * @sa @ref monitor_monitors
+ * @sa @ref glfwGetMonitors
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup monitor
+ */
+GLFWAPI GLFWmonitor* glfwGetPrimaryMonitor(void);
+
+/*! @brief Returns the position of the monitor's viewport on the virtual screen.
+ *
+ * This function returns the position, in screen coordinates, of the upper-left
+ * corner of the specified monitor.
+ *
+ * Any or all of the position arguments may be `NULL`. If an error occurs, all
+ * non-`NULL` position arguments will be set to zero.
+ *
+ * @param[in] monitor The monitor to query.
+ * @param[out] xpos Where to store the monitor x-coordinate, or `NULL`.
+ * @param[out] ypos Where to store the monitor y-coordinate, or `NULL`.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref monitor_properties
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup monitor
+ */
+GLFWAPI void glfwGetMonitorPos(GLFWmonitor* monitor, int* xpos, int* ypos);
+
+/*! @brief Retrieves the work area of the monitor.
+ *
+ * This function returns the position, in screen coordinates, of the upper-left
+ * corner of the work area of the specified monitor along with the work area
+ * size in screen coordinates. The work area is defined as the area of the
+ * monitor not occluded by the window system task bar where present. If no
+ * task bar exists then the work area is the monitor resolution in screen
+ * coordinates.
+ *
+ * Any or all of the position and size arguments may be `NULL`. If an error
+ * occurs, all non-`NULL` position and size arguments will be set to zero.
+ *
+ * @param[in] monitor The monitor to query.
+ * @param[out] xpos Where to store the monitor x-coordinate, or `NULL`.
+ * @param[out] ypos Where to store the monitor y-coordinate, or `NULL`.
+ * @param[out] width Where to store the monitor width, or `NULL`.
+ * @param[out] height Where to store the monitor height, or `NULL`.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref monitor_workarea
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup monitor
+ */
+GLFWAPI void glfwGetMonitorWorkarea(GLFWmonitor* monitor, int* xpos, int* ypos, int* width, int* height);
+
+/*! @brief Returns the physical size of the monitor.
+ *
+ * This function returns the size, in millimetres, of the display area of the
+ * specified monitor.
+ *
+ * Some platforms do not provide accurate monitor size information, either
+ * because the monitor [EDID][] data is incorrect or because the driver does
+ * not report it accurately.
+ *
+ * [EDID]: https://en.wikipedia.org/wiki/Extended_display_identification_data
+ *
+ * Any or all of the size arguments may be `NULL`. If an error occurs, all
+ * non-`NULL` size arguments will be set to zero.
+ *
+ * @param[in] monitor The monitor to query.
+ * @param[out] widthMM Where to store the width, in millimetres, of the
+ * monitor's display area, or `NULL`.
+ * @param[out] heightMM Where to store the height, in millimetres, of the
+ * monitor's display area, or `NULL`.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @remark @win32 On Windows 8 and earlier the physical size is calculated from
+ * the current resolution and system DPI instead of querying the monitor EDID data.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref monitor_properties
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup monitor
+ */
+GLFWAPI void glfwGetMonitorPhysicalSize(GLFWmonitor* monitor, int* widthMM, int* heightMM);
+
+/*! @brief Retrieves the content scale for the specified monitor.
+ *
+ * This function retrieves the content scale for the specified monitor. The
+ * content scale is the ratio between the current DPI and the platform's
+ * default DPI. This is especially important for text and any UI elements. If
+ * the pixel dimensions of your UI scaled by this look appropriate on your
+ * machine then it should appear at a reasonable size on other machines
+ * regardless of their DPI and scaling settings. This relies on the system DPI
+ * and scaling settings being somewhat correct.
+ *
+ * The content scale may depend on both the monitor resolution and pixel
+ * density and on user settings. It may be very different from the raw DPI
+ * calculated from the physical size and current resolution.
+ *
+ * @param[in] monitor The monitor to query.
+ * @param[out] xscale Where to store the x-axis content scale, or `NULL`.
+ * @param[out] yscale Where to store the y-axis content scale, or `NULL`.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @remark @wayland Fractional scaling information is not yet available for
+ * monitors, so this function only returns integer content scales.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref monitor_scale
+ * @sa @ref glfwGetWindowContentScale
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup monitor
+ */
+GLFWAPI void glfwGetMonitorContentScale(GLFWmonitor* monitor, float* xscale, float* yscale);
+
+/*! @brief Returns the name of the specified monitor.
+ *
+ * This function returns a human-readable name, encoded as UTF-8, of the
+ * specified monitor. The name typically reflects the make and model of the
+ * monitor and is not guaranteed to be unique among the connected monitors.
+ *
+ * @param[in] monitor The monitor to query.
+ * @return The UTF-8 encoded name of the monitor, or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @pointer_lifetime The returned string is allocated and freed by GLFW. You
+ * should not free it yourself. It is valid until the specified monitor is
+ * disconnected or the library is terminated.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref monitor_properties
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup monitor
+ */
+GLFWAPI const char* glfwGetMonitorName(GLFWmonitor* monitor);
+
+/*! @brief Sets the user pointer of the specified monitor.
+ *
+ * This function sets the user-defined pointer of the specified monitor. The
+ * current value is retained until the monitor is disconnected. The initial
+ * value is `NULL`.
+ *
+ * This function may be called from the monitor callback, even for a monitor
+ * that is being disconnected.
+ *
+ * @param[in] monitor The monitor whose pointer to set.
+ * @param[in] pointer The new value.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @sa @ref monitor_userptr
+ * @sa @ref glfwGetMonitorUserPointer
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup monitor
+ */
+GLFWAPI void glfwSetMonitorUserPointer(GLFWmonitor* monitor, void* pointer);
+
+/*! @brief Returns the user pointer of the specified monitor.
+ *
+ * This function returns the current value of the user-defined pointer of the
+ * specified monitor. The initial value is `NULL`.
+ *
+ * This function may be called from the monitor callback, even for a monitor
+ * that is being disconnected.
+ *
+ * @param[in] monitor The monitor whose pointer to return.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @sa @ref monitor_userptr
+ * @sa @ref glfwSetMonitorUserPointer
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup monitor
+ */
+GLFWAPI void* glfwGetMonitorUserPointer(GLFWmonitor* monitor);
+
+/*! @brief Sets the monitor configuration callback.
+ *
+ * This function sets the monitor configuration callback, or removes the
+ * currently set callback. This is called when a monitor is connected to or
+ * disconnected from the system.
+ *
+ * @param[in] callback The new callback, or `NULL` to remove the currently set
+ * callback.
+ * @return The previously set callback, or `NULL` if no callback was set or the
+ * library had not been [initialized](@ref intro_init).
+ *
+ * @callback_signature
+ * @code
+ * void function_name(GLFWmonitor* monitor, int event)
+ * @endcode
+ * For more information about the callback parameters, see the
+ * [function pointer type](@ref GLFWmonitorfun).
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref monitor_event
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup monitor
+ */
+GLFWAPI GLFWmonitorfun glfwSetMonitorCallback(GLFWmonitorfun callback);
+
+/*! @brief Returns the available video modes for the specified monitor.
+ *
+ * This function returns an array of all video modes supported by the specified
+ * monitor. The returned array is sorted in ascending order, first by color
+ * bit depth (the sum of all channel depths), then by resolution area (the
+ * product of width and height), then resolution width and finally by refresh
+ * rate.
+ *
+ * @param[in] monitor The monitor to query.
+ * @param[out] count Where to store the number of video modes in the returned
+ * array. This is set to zero if an error occurred.
+ * @return An array of video modes, or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @pointer_lifetime The returned array is allocated and freed by GLFW. You
+ * should not free it yourself. It is valid until the specified monitor is
+ * disconnected, this function is called again for that monitor or the library
+ * is terminated.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref monitor_modes
+ * @sa @ref glfwGetVideoMode
+ *
+ * @since Added in version 1.0.
+ * @glfw3 Changed to return an array of modes for a specific monitor.
+ *
+ * @ingroup monitor
+ */
+GLFWAPI const GLFWvidmode* glfwGetVideoModes(GLFWmonitor* monitor, int* count);
+
+/*! @brief Returns the current mode of the specified monitor.
+ *
+ * This function returns the current video mode of the specified monitor. If
+ * you have created a full screen window for that monitor, the return value
+ * will depend on whether that window is iconified.
+ *
+ * @param[in] monitor The monitor to query.
+ * @return The current mode of the monitor, or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @pointer_lifetime The returned array is allocated and freed by GLFW. You
+ * should not free it yourself. It is valid until the specified monitor is
+ * disconnected or the library is terminated.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref monitor_modes
+ * @sa @ref glfwGetVideoModes
+ *
+ * @since Added in version 3.0. Replaces `glfwGetDesktopMode`.
+ *
+ * @ingroup monitor
+ */
+GLFWAPI const GLFWvidmode* glfwGetVideoMode(GLFWmonitor* monitor);
+
+/*! @brief Generates a gamma ramp and sets it for the specified monitor.
+ *
+ * This function generates an appropriately sized gamma ramp from the specified
+ * exponent and then calls @ref glfwSetGammaRamp with it. The value must be
+ * a finite number greater than zero.
+ *
+ * The software controlled gamma ramp is applied _in addition_ to the hardware
+ * gamma correction, which today is usually an approximation of sRGB gamma.
+ * This means that setting a perfectly linear ramp, or gamma 1.0, will produce
+ * the default (usually sRGB-like) behavior.
+ *
+ * For gamma correct rendering with OpenGL or OpenGL ES, see the @ref
+ * GLFW_SRGB_CAPABLE hint.
+ *
+ * @param[in] monitor The monitor whose gamma ramp to set.
+ * @param[in] gamma The desired exponent.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref GLFW_INVALID_VALUE,
+ * @ref GLFW_PLATFORM_ERROR and @ref GLFW_FEATURE_UNAVAILABLE (see remarks).
+ *
+ * @remark @wayland Gamma handling is a privileged protocol, this function
+ * will thus never be implemented and emits @ref GLFW_FEATURE_UNAVAILABLE.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref monitor_gamma
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup monitor
+ */
+GLFWAPI void glfwSetGamma(GLFWmonitor* monitor, float gamma);
+
+/*! @brief Returns the current gamma ramp for the specified monitor.
+ *
+ * This function returns the current gamma ramp of the specified monitor.
+ *
+ * @param[in] monitor The monitor to query.
+ * @return The current gamma ramp, or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref GLFW_PLATFORM_ERROR
+ * and @ref GLFW_FEATURE_UNAVAILABLE (see remarks).
+ *
+ * @remark @wayland Gamma handling is a privileged protocol, this function
+ * will thus never be implemented and emits @ref GLFW_FEATURE_UNAVAILABLE while
+ * returning `NULL`.
+ *
+ * @pointer_lifetime The returned structure and its arrays are allocated and
+ * freed by GLFW. You should not free them yourself. They are valid until the
+ * specified monitor is disconnected, this function is called again for that
+ * monitor or the library is terminated.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref monitor_gamma
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup monitor
+ */
+GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* monitor);
+
+/*! @brief Sets the current gamma ramp for the specified monitor.
+ *
+ * This function sets the current gamma ramp for the specified monitor. The
+ * original gamma ramp for that monitor is saved by GLFW the first time this
+ * function is called and is restored by @ref glfwTerminate.
+ *
+ * The software controlled gamma ramp is applied _in addition_ to the hardware
+ * gamma correction, which today is usually an approximation of sRGB gamma.
+ * This means that setting a perfectly linear ramp, or gamma 1.0, will produce
+ * the default (usually sRGB-like) behavior.
+ *
+ * For gamma correct rendering with OpenGL or OpenGL ES, see the @ref
+ * GLFW_SRGB_CAPABLE hint.
+ *
+ * @param[in] monitor The monitor whose gamma ramp to set.
+ * @param[in] ramp The gamma ramp to use.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref GLFW_PLATFORM_ERROR
+ * and @ref GLFW_FEATURE_UNAVAILABLE (see remarks).
+ *
+ * @remark The size of the specified gamma ramp should match the size of the
+ * current ramp for that monitor.
+ *
+ * @remark @win32 The gamma ramp size must be 256.
+ *
+ * @remark @wayland Gamma handling is a privileged protocol, this function
+ * will thus never be implemented and emits @ref GLFW_FEATURE_UNAVAILABLE.
+ *
+ * @pointer_lifetime The specified gamma ramp is copied before this function
+ * returns.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref monitor_gamma
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup monitor
+ */
+GLFWAPI void glfwSetGammaRamp(GLFWmonitor* monitor, const GLFWgammaramp* ramp);
+
+/*! @brief Resets all window hints to their default values.
+ *
+ * This function resets all window hints to their
+ * [default values](@ref window_hints_values).
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_hints
+ * @sa @ref glfwWindowHint
+ * @sa @ref glfwWindowHintString
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwDefaultWindowHints(void);
+
+/*! @brief Sets the specified window hint to the desired value.
+ *
+ * This function sets hints for the next call to @ref glfwCreateWindow. The
+ * hints, once set, retain their values until changed by a call to this
+ * function or @ref glfwDefaultWindowHints, or until the library is terminated.
+ *
+ * Only integer value hints can be set with this function. String value hints
+ * are set with @ref glfwWindowHintString.
+ *
+ * This function does not check whether the specified hint values are valid.
+ * If you set hints to invalid values this will instead be reported by the next
+ * call to @ref glfwCreateWindow.
+ *
+ * Some hints are platform specific. These may be set on any platform but they
+ * will only affect their specific platform. Other platforms will ignore them.
+ * Setting these hints requires no platform specific headers or functions.
+ *
+ * @param[in] hint The [window hint](@ref window_hints) to set.
+ * @param[in] value The new value of the window hint.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_INVALID_ENUM.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_hints
+ * @sa @ref glfwWindowHintString
+ * @sa @ref glfwDefaultWindowHints
+ *
+ * @since Added in version 3.0. Replaces `glfwOpenWindowHint`.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwWindowHint(int hint, int value);
+
+/*! @brief Sets the specified window hint to the desired value.
+ *
+ * This function sets hints for the next call to @ref glfwCreateWindow. The
+ * hints, once set, retain their values until changed by a call to this
+ * function or @ref glfwDefaultWindowHints, or until the library is terminated.
+ *
+ * Only string type hints can be set with this function. Integer value hints
+ * are set with @ref glfwWindowHint.
+ *
+ * This function does not check whether the specified hint values are valid.
+ * If you set hints to invalid values this will instead be reported by the next
+ * call to @ref glfwCreateWindow.
+ *
+ * Some hints are platform specific. These may be set on any platform but they
+ * will only affect their specific platform. Other platforms will ignore them.
+ * Setting these hints requires no platform specific headers or functions.
+ *
+ * @param[in] hint The [window hint](@ref window_hints) to set.
+ * @param[in] value The new value of the window hint.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_INVALID_ENUM.
+ *
+ * @pointer_lifetime The specified string is copied before this function
+ * returns.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_hints
+ * @sa @ref glfwWindowHint
+ * @sa @ref glfwDefaultWindowHints
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwWindowHintString(int hint, const char* value);
+
+/*! @brief Creates a window and its associated context.
+ *
+ * This function creates a window and its associated OpenGL or OpenGL ES
+ * context. Most of the options controlling how the window and its context
+ * should be created are specified with [window hints](@ref window_hints).
+ *
+ * Successful creation does not change which context is current. Before you
+ * can use the newly created context, you need to
+ * [make it current](@ref context_current). For information about the `share`
+ * parameter, see @ref context_sharing.
+ *
+ * The created window, framebuffer and context may differ from what you
+ * requested, as not all parameters and hints are
+ * [hard constraints](@ref window_hints_hard). This includes the size of the
+ * window, especially for full screen windows. To query the actual attributes
+ * of the created window, framebuffer and context, see @ref
+ * glfwGetWindowAttrib, @ref glfwGetWindowSize and @ref glfwGetFramebufferSize.
+ *
+ * To create a full screen window, you need to specify the monitor the window
+ * will cover. If no monitor is specified, the window will be windowed mode.
+ * Unless you have a way for the user to choose a specific monitor, it is
+ * recommended that you pick the primary monitor. For more information on how
+ * to query connected monitors, see @ref monitor_monitors.
+ *
+ * For full screen windows, the specified size becomes the resolution of the
+ * window's _desired video mode_. As long as a full screen window is not
+ * iconified, the supported video mode most closely matching the desired video
+ * mode is set for the specified monitor. For more information about full
+ * screen windows, including the creation of so called _windowed full screen_
+ * or _borderless full screen_ windows, see @ref window_windowed_full_screen.
+ *
+ * Once you have created the window, you can switch it between windowed and
+ * full screen mode with @ref glfwSetWindowMonitor. This will not affect its
+ * OpenGL or OpenGL ES context.
+ *
+ * By default, newly created windows use the placement recommended by the
+ * window system. To create the window at a specific position, set the @ref
+ * GLFW_POSITION_X and @ref GLFW_POSITION_Y window hints before creation. To
+ * restore the default behavior, set either or both hints back to
+ * `GLFW_ANY_POSITION`.
+ *
+ * As long as at least one full screen window is not iconified, the screensaver
+ * is prohibited from starting.
+ *
+ * Window systems put limits on window sizes. Very large or very small window
+ * dimensions may be overridden by the window system on creation. Check the
+ * actual [size](@ref window_size) after creation.
+ *
+ * The [swap interval](@ref buffer_swap) is not set during window creation and
+ * the initial value may vary depending on driver settings and defaults.
+ *
+ * @param[in] width The desired width, in screen coordinates, of the window.
+ * This must be greater than zero.
+ * @param[in] height The desired height, in screen coordinates, of the window.
+ * This must be greater than zero.
+ * @param[in] title The initial, UTF-8 encoded window title.
+ * @param[in] monitor The monitor to use for full screen mode, or `NULL` for
+ * windowed mode.
+ * @param[in] share The window whose context to share resources with, or `NULL`
+ * to not share resources.
+ * @return The handle of the created window, or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_INVALID_ENUM, @ref GLFW_INVALID_VALUE, @ref GLFW_API_UNAVAILABLE, @ref
+ * GLFW_VERSION_UNAVAILABLE, @ref GLFW_FORMAT_UNAVAILABLE, @ref
+ * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR.
+ *
+ * @remark @win32 Window creation will fail if the Microsoft GDI software
+ * OpenGL implementation is the only one available.
+ *
+ * @remark @win32 If the executable has an icon resource named `GLFW_ICON,` it
+ * will be set as the initial icon for the window. If no such icon is present,
+ * the `IDI_APPLICATION` icon will be used instead. To set a different icon,
+ * see @ref glfwSetWindowIcon.
+ *
+ * @remark @win32 The context to share resources with must not be current on
+ * any other thread.
+ *
+ * @remark @macos The OS only supports core profile contexts for OpenGL
+ * versions 3.2 and later. Before creating an OpenGL context of version 3.2 or
+ * later you must set the [GLFW_OPENGL_PROFILE](@ref GLFW_OPENGL_PROFILE_hint)
+ * hint accordingly. OpenGL 3.0 and 3.1 contexts are not supported at all
+ * on macOS.
+ *
+ * @remark @macos The GLFW window has no icon, as it is not a document
+ * window, but the dock icon will be the same as the application bundle's icon.
+ * For more information on bundles, see the
+ * [Bundle Programming Guide][bundle-guide] in the Mac Developer Library.
+ *
+ * [bundle-guide]: https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/
+ *
+ * @remark @macos On OS X 10.10 and later the window frame will not be rendered
+ * at full resolution on Retina displays unless the
+ * [GLFW_SCALE_FRAMEBUFFER](@ref GLFW_SCALE_FRAMEBUFFER_hint)
+ * hint is `GLFW_TRUE` and the `NSHighResolutionCapable` key is enabled in the
+ * application bundle's `Info.plist`. For more information, see
+ * [High Resolution Guidelines for OS X][hidpi-guide] in the Mac Developer
+ * Library. The GLFW test and example programs use a custom `Info.plist`
+ * template for this, which can be found as `CMake/Info.plist.in` in the source
+ * tree.
+ *
+ * [hidpi-guide]: https://developer.apple.com/library/mac/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html
+ *
+ * @remark @macos When activating frame autosaving with
+ * [GLFW_COCOA_FRAME_NAME](@ref GLFW_COCOA_FRAME_NAME_hint), the specified
+ * window size and position may be overridden by previously saved values.
+ *
+ * @remark @wayland GLFW uses [libdecor][] where available to create its window
+ * decorations. This in turn uses server-side XDG decorations where available
+ * and provides high quality client-side decorations on compositors like GNOME.
+ * If both XDG decorations and libdecor are unavailable, GLFW falls back to
+ * a very simple set of window decorations that only support moving, resizing
+ * and the window manager's right-click menu.
+ *
+ * [libdecor]: https://gitlab.freedesktop.org/libdecor/libdecor
+ *
+ * @remark @x11 Some window managers will not respect the placement of
+ * initially hidden windows.
+ *
+ * @remark @x11 Due to the asynchronous nature of X11, it may take a moment for
+ * a window to reach its requested state. This means you may not be able to
+ * query the final size, position or other attributes directly after window
+ * creation.
+ *
+ * @remark @x11 The class part of the `WM_CLASS` window property will by
+ * default be set to the window title passed to this function. The instance
+ * part will use the contents of the `RESOURCE_NAME` environment variable, if
+ * present and not empty, or fall back to the window title. Set the
+ * [GLFW_X11_CLASS_NAME](@ref GLFW_X11_CLASS_NAME_hint) and
+ * [GLFW_X11_INSTANCE_NAME](@ref GLFW_X11_INSTANCE_NAME_hint) window hints to
+ * override this.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_creation
+ * @sa @ref glfwDestroyWindow
+ *
+ * @since Added in version 3.0. Replaces `glfwOpenWindow`.
+ *
+ * @ingroup window
+ */
+GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height, const char* title, GLFWmonitor* monitor, GLFWwindow* share);
+
+/*! @brief Destroys the specified window and its context.
+ *
+ * This function destroys the specified window and its context. On calling
+ * this function, no further callbacks will be called for that window.
+ *
+ * If the context of the specified window is current on the main thread, it is
+ * detached before being destroyed.
+ *
+ * @param[in] window The window to destroy.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @note The context of the specified window must not be current on any other
+ * thread when this function is called.
+ *
+ * @reentrancy This function must not be called from a callback.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_creation
+ * @sa @ref glfwCreateWindow
+ *
+ * @since Added in version 3.0. Replaces `glfwCloseWindow`.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwDestroyWindow(GLFWwindow* window);
+
+/*! @brief Checks the close flag of the specified window.
+ *
+ * This function returns the value of the close flag of the specified window.
+ *
+ * @param[in] window The window to query.
+ * @return The value of the close flag.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @sa @ref window_close
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+GLFWAPI int glfwWindowShouldClose(GLFWwindow* window);
+
+/*! @brief Sets the close flag of the specified window.
+ *
+ * This function sets the value of the close flag of the specified window.
+ * This can be used to override the user's attempt to close the window, or
+ * to signal that it should be closed.
+ *
+ * @param[in] window The window whose flag to change.
+ * @param[in] value The new value.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @sa @ref window_close
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwSetWindowShouldClose(GLFWwindow* window, int value);
+
+/*! @brief Returns the title of the specified window.
+ *
+ * This function returns the window title, encoded as UTF-8, of the specified
+ * window. This is the title set previously by @ref glfwCreateWindow
+ * or @ref glfwSetWindowTitle.
+ *
+ * @param[in] window The window to query.
+ * @return The UTF-8 encoded window title, or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @remark The returned title is currently a copy of the title last set by @ref
+ * glfwCreateWindow or @ref glfwSetWindowTitle. It does not include any
+ * additional text which may be appended by the platform or another program.
+ *
+ * @pointer_lifetime The returned string is allocated and freed by GLFW. You
+ * should not free it yourself. It is valid until the next call to @ref
+ * glfwGetWindowTitle or @ref glfwSetWindowTitle, or until the library is
+ * terminated.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_title
+ * @sa @ref glfwSetWindowTitle
+ *
+ * @since Added in version 3.4.
+ *
+ * @ingroup window
+ */
+GLFWAPI const char* glfwGetWindowTitle(GLFWwindow* window);
+
+/*! @brief Sets the title of the specified window.
+ *
+ * This function sets the window title, encoded as UTF-8, of the specified
+ * window.
+ *
+ * @param[in] window The window whose title to change.
+ * @param[in] title The UTF-8 encoded window title.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @remark @macos The window title will not be updated until the next time you
+ * process events.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_title
+ * @sa @ref glfwGetWindowTitle
+ *
+ * @since Added in version 1.0.
+ * @glfw3 Added window handle parameter.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwSetWindowTitle(GLFWwindow* window, const char* title);
+
+/*! @brief Sets the icon for the specified window.
+ *
+ * This function sets the icon of the specified window. If passed an array of
+ * candidate images, those of or closest to the sizes desired by the system are
+ * selected. If no images are specified, the window reverts to its default
+ * icon.
+ *
+ * The pixels are 32-bit, little-endian, non-premultiplied RGBA, i.e. eight
+ * bits per channel with the red channel first. They are arranged canonically
+ * as packed sequential rows, starting from the top-left corner.
+ *
+ * The desired image sizes varies depending on platform and system settings.
+ * The selected images will be rescaled as needed. Good sizes include 16x16,
+ * 32x32 and 48x48.
+ *
+ * @param[in] window The window whose icon to set.
+ * @param[in] count The number of images in the specified array, or zero to
+ * revert to the default window icon.
+ * @param[in] images The images to create the icon from. This is ignored if
+ * count is zero.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_INVALID_VALUE, @ref GLFW_PLATFORM_ERROR and @ref
+ * GLFW_FEATURE_UNAVAILABLE (see remarks).
+ *
+ * @pointer_lifetime The specified image data is copied before this function
+ * returns.
+ *
+ * @remark @macos Regular windows do not have icons on macOS. This function
+ * will emit @ref GLFW_FEATURE_UNAVAILABLE. The dock icon will be the same as
+ * the application bundle's icon. For more information on bundles, see the
+ * [Bundle Programming Guide][bundle-guide] in the Mac Developer Library.
+ *
+ * [bundle-guide]: https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/
+ *
+ * @remark @wayland There is no existing protocol to change an icon, the
+ * window will thus inherit the one defined in the application's desktop file.
+ * This function will emit @ref GLFW_FEATURE_UNAVAILABLE.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_icon
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwSetWindowIcon(GLFWwindow* window, int count, const GLFWimage* images);
+
+/*! @brief Retrieves the position of the content area of the specified window.
+ *
+ * This function retrieves the position, in screen coordinates, of the
+ * upper-left corner of the content area of the specified window.
+ *
+ * Any or all of the position arguments may be `NULL`. If an error occurs, all
+ * non-`NULL` position arguments will be set to zero.
+ *
+ * @param[in] window The window to query.
+ * @param[out] xpos Where to store the x-coordinate of the upper-left corner of
+ * the content area, or `NULL`.
+ * @param[out] ypos Where to store the y-coordinate of the upper-left corner of
+ * the content area, or `NULL`.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_PLATFORM_ERROR and @ref GLFW_FEATURE_UNAVAILABLE (see remarks).
+ *
+ * @remark @wayland There is no way for an application to retrieve the global
+ * position of its windows. This function will emit @ref
+ * GLFW_FEATURE_UNAVAILABLE.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_pos
+ * @sa @ref glfwSetWindowPos
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwGetWindowPos(GLFWwindow* window, int* xpos, int* ypos);
+
+/*! @brief Sets the position of the content area of the specified window.
+ *
+ * This function sets the position, in screen coordinates, of the upper-left
+ * corner of the content area of the specified windowed mode window. If the
+ * window is a full screen window, this function does nothing.
+ *
+ * __Do not use this function__ to move an already visible window unless you
+ * have very good reasons for doing so, as it will confuse and annoy the user.
+ *
+ * The window manager may put limits on what positions are allowed. GLFW
+ * cannot and should not override these limits.
+ *
+ * @param[in] window The window to query.
+ * @param[in] xpos The x-coordinate of the upper-left corner of the content area.
+ * @param[in] ypos The y-coordinate of the upper-left corner of the content area.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_PLATFORM_ERROR and @ref GLFW_FEATURE_UNAVAILABLE (see remarks).
+ *
+ * @remark @wayland There is no way for an application to set the global
+ * position of its windows. This function will emit @ref
+ * GLFW_FEATURE_UNAVAILABLE.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_pos
+ * @sa @ref glfwGetWindowPos
+ *
+ * @since Added in version 1.0.
+ * @glfw3 Added window handle parameter.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwSetWindowPos(GLFWwindow* window, int xpos, int ypos);
+
+/*! @brief Retrieves the size of the content area of the specified window.
+ *
+ * This function retrieves the size, in screen coordinates, of the content area
+ * of the specified window. If you wish to retrieve the size of the
+ * framebuffer of the window in pixels, see @ref glfwGetFramebufferSize.
+ *
+ * Any or all of the size arguments may be `NULL`. If an error occurs, all
+ * non-`NULL` size arguments will be set to zero.
+ *
+ * @param[in] window The window whose size to retrieve.
+ * @param[out] width Where to store the width, in screen coordinates, of the
+ * content area, or `NULL`.
+ * @param[out] height Where to store the height, in screen coordinates, of the
+ * content area, or `NULL`.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_size
+ * @sa @ref glfwSetWindowSize
+ *
+ * @since Added in version 1.0.
+ * @glfw3 Added window handle parameter.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwGetWindowSize(GLFWwindow* window, int* width, int* height);
+
+/*! @brief Sets the size limits of the specified window.
+ *
+ * This function sets the size limits of the content area of the specified
+ * window. If the window is full screen, the size limits only take effect
+ * once it is made windowed. If the window is not resizable, this function
+ * does nothing.
+ *
+ * The size limits are applied immediately to a windowed mode window and may
+ * cause it to be resized.
+ *
+ * The maximum dimensions must be greater than or equal to the minimum
+ * dimensions and all must be greater than or equal to zero.
+ *
+ * @param[in] window The window to set limits for.
+ * @param[in] minwidth The minimum width, in screen coordinates, of the content
+ * area, or `GLFW_DONT_CARE`.
+ * @param[in] minheight The minimum height, in screen coordinates, of the
+ * content area, or `GLFW_DONT_CARE`.
+ * @param[in] maxwidth The maximum width, in screen coordinates, of the content
+ * area, or `GLFW_DONT_CARE`.
+ * @param[in] maxheight The maximum height, in screen coordinates, of the
+ * content area, or `GLFW_DONT_CARE`.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR.
+ *
+ * @remark If you set size limits and an aspect ratio that conflict, the
+ * results are undefined.
+ *
+ * @remark @wayland The size limits will not be applied until the window is
+ * actually resized, either by the user or by the compositor.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_sizelimits
+ * @sa @ref glfwSetWindowAspectRatio
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* window, int minwidth, int minheight, int maxwidth, int maxheight);
+
+/*! @brief Sets the aspect ratio of the specified window.
+ *
+ * This function sets the required aspect ratio of the content area of the
+ * specified window. If the window is full screen, the aspect ratio only takes
+ * effect once it is made windowed. If the window is not resizable, this
+ * function does nothing.
+ *
+ * The aspect ratio is specified as a numerator and a denominator and both
+ * values must be greater than zero. For example, the common 16:9 aspect ratio
+ * is specified as 16 and 9, respectively.
+ *
+ * If the numerator and denominator is set to `GLFW_DONT_CARE` then the aspect
+ * ratio limit is disabled.
+ *
+ * The aspect ratio is applied immediately to a windowed mode window and may
+ * cause it to be resized.
+ *
+ * @param[in] window The window to set limits for.
+ * @param[in] numer The numerator of the desired aspect ratio, or
+ * `GLFW_DONT_CARE`.
+ * @param[in] denom The denominator of the desired aspect ratio, or
+ * `GLFW_DONT_CARE`.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR.
+ *
+ * @remark If you set size limits and an aspect ratio that conflict, the
+ * results are undefined.
+ *
+ * @remark @wayland The aspect ratio will not be applied until the window is
+ * actually resized, either by the user or by the compositor.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_sizelimits
+ * @sa @ref glfwSetWindowSizeLimits
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* window, int numer, int denom);
+
+/*! @brief Sets the size of the content area of the specified window.
+ *
+ * This function sets the size, in screen coordinates, of the content area of
+ * the specified window.
+ *
+ * For full screen windows, this function updates the resolution of its desired
+ * video mode and switches to the video mode closest to it, without affecting
+ * the window's context. As the context is unaffected, the bit depths of the
+ * framebuffer remain unchanged.
+ *
+ * If you wish to update the refresh rate of the desired video mode in addition
+ * to its resolution, see @ref glfwSetWindowMonitor.
+ *
+ * The window manager may put limits on what sizes are allowed. GLFW cannot
+ * and should not override these limits.
+ *
+ * @param[in] window The window to resize.
+ * @param[in] width The desired width, in screen coordinates, of the window
+ * content area.
+ * @param[in] height The desired height, in screen coordinates, of the window
+ * content area.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_size
+ * @sa @ref glfwGetWindowSize
+ * @sa @ref glfwSetWindowMonitor
+ *
+ * @since Added in version 1.0.
+ * @glfw3 Added window handle parameter.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwSetWindowSize(GLFWwindow* window, int width, int height);
+
+/*! @brief Retrieves the size of the framebuffer of the specified window.
+ *
+ * This function retrieves the size, in pixels, of the framebuffer of the
+ * specified window. If you wish to retrieve the size of the window in screen
+ * coordinates, see @ref glfwGetWindowSize.
+ *
+ * Any or all of the size arguments may be `NULL`. If an error occurs, all
+ * non-`NULL` size arguments will be set to zero.
+ *
+ * @param[in] window The window whose framebuffer to query.
+ * @param[out] width Where to store the width, in pixels, of the framebuffer,
+ * or `NULL`.
+ * @param[out] height Where to store the height, in pixels, of the framebuffer,
+ * or `NULL`.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_fbsize
+ * @sa @ref glfwSetFramebufferSizeCallback
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwGetFramebufferSize(GLFWwindow* window, int* width, int* height);
+
+/*! @brief Retrieves the size of the frame of the window.
+ *
+ * This function retrieves the size, in screen coordinates, of each edge of the
+ * frame of the specified window. This size includes the title bar, if the
+ * window has one. The size of the frame may vary depending on the
+ * [window-related hints](@ref window_hints_wnd) used to create it.
+ *
+ * Because this function retrieves the size of each window frame edge and not
+ * the offset along a particular coordinate axis, the retrieved values will
+ * always be zero or positive.
+ *
+ * Any or all of the size arguments may be `NULL`. If an error occurs, all
+ * non-`NULL` size arguments will be set to zero.
+ *
+ * @param[in] window The window whose frame size to query.
+ * @param[out] left Where to store the size, in screen coordinates, of the left
+ * edge of the window frame, or `NULL`.
+ * @param[out] top Where to store the size, in screen coordinates, of the top
+ * edge of the window frame, or `NULL`.
+ * @param[out] right Where to store the size, in screen coordinates, of the
+ * right edge of the window frame, or `NULL`.
+ * @param[out] bottom Where to store the size, in screen coordinates, of the
+ * bottom edge of the window frame, or `NULL`.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_size
+ *
+ * @since Added in version 3.1.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwGetWindowFrameSize(GLFWwindow* window, int* left, int* top, int* right, int* bottom);
+
+/*! @brief Retrieves the content scale for the specified window.
+ *
+ * This function retrieves the content scale for the specified window. The
+ * content scale is the ratio between the current DPI and the platform's
+ * default DPI. This is especially important for text and any UI elements. If
+ * the pixel dimensions of your UI scaled by this look appropriate on your
+ * machine then it should appear at a reasonable size on other machines
+ * regardless of their DPI and scaling settings. This relies on the system DPI
+ * and scaling settings being somewhat correct.
+ *
+ * On platforms where each monitors can have its own content scale, the window
+ * content scale will depend on which monitor the system considers the window
+ * to be on.
+ *
+ * @param[in] window The window to query.
+ * @param[out] xscale Where to store the x-axis content scale, or `NULL`.
+ * @param[out] yscale Where to store the y-axis content scale, or `NULL`.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_scale
+ * @sa @ref glfwSetWindowContentScaleCallback
+ * @sa @ref glfwGetMonitorContentScale
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwGetWindowContentScale(GLFWwindow* window, float* xscale, float* yscale);
+
+/*! @brief Returns the opacity of the whole window.
+ *
+ * This function returns the opacity of the window, including any decorations.
+ *
+ * The opacity (or alpha) value is a positive finite number between zero and
+ * one, where zero is fully transparent and one is fully opaque. If the system
+ * does not support whole window transparency, this function always returns one.
+ *
+ * The initial opacity value for newly created windows is one.
+ *
+ * @param[in] window The window to query.
+ * @return The opacity value of the specified window.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_transparency
+ * @sa @ref glfwSetWindowOpacity
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup window
+ */
+GLFWAPI float glfwGetWindowOpacity(GLFWwindow* window);
+
+/*! @brief Sets the opacity of the whole window.
+ *
+ * This function sets the opacity of the window, including any decorations.
+ *
+ * The opacity (or alpha) value is a positive finite number between zero and
+ * one, where zero is fully transparent and one is fully opaque.
+ *
+ * The initial opacity value for newly created windows is one.
+ *
+ * A window created with framebuffer transparency may not use whole window
+ * transparency. The results of doing this are undefined.
+ *
+ * @param[in] window The window to set the opacity for.
+ * @param[in] opacity The desired opacity of the specified window.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_PLATFORM_ERROR and @ref GLFW_FEATURE_UNAVAILABLE (see remarks).
+ *
+ * @remark @wayland There is no way to set an opacity factor for a window.
+ * This function will emit @ref GLFW_FEATURE_UNAVAILABLE.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_transparency
+ * @sa @ref glfwGetWindowOpacity
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwSetWindowOpacity(GLFWwindow* window, float opacity);
+
+/*! @brief Iconifies the specified window.
+ *
+ * This function iconifies (minimizes) the specified window if it was
+ * previously restored. If the window is already iconified, this function does
+ * nothing.
+ *
+ * If the specified window is a full screen window, GLFW restores the original
+ * video mode of the monitor. The window's desired video mode is set again
+ * when the window is restored.
+ *
+ * @param[in] window The window to iconify.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @remark @wayland Once a window is iconified, @ref glfwRestoreWindow won’t
+ * be able to restore it. This is a design decision of the xdg-shell
+ * protocol.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_iconify
+ * @sa @ref glfwRestoreWindow
+ * @sa @ref glfwMaximizeWindow
+ *
+ * @since Added in version 2.1.
+ * @glfw3 Added window handle parameter.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwIconifyWindow(GLFWwindow* window);
+
+/*! @brief Restores the specified window.
+ *
+ * This function restores the specified window if it was previously iconified
+ * (minimized) or maximized. If the window is already restored, this function
+ * does nothing.
+ *
+ * If the specified window is an iconified full screen window, its desired
+ * video mode is set again for its monitor when the window is restored.
+ *
+ * @param[in] window The window to restore.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_iconify
+ * @sa @ref glfwIconifyWindow
+ * @sa @ref glfwMaximizeWindow
+ *
+ * @since Added in version 2.1.
+ * @glfw3 Added window handle parameter.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwRestoreWindow(GLFWwindow* window);
+
+/*! @brief Maximizes the specified window.
+ *
+ * This function maximizes the specified window if it was previously not
+ * maximized. If the window is already maximized, this function does nothing.
+ *
+ * If the specified window is a full screen window, this function does nothing.
+ *
+ * @param[in] window The window to maximize.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @par Thread Safety
+ * This function may only be called from the main thread.
+ *
+ * @sa @ref window_iconify
+ * @sa @ref glfwIconifyWindow
+ * @sa @ref glfwRestoreWindow
+ *
+ * @since Added in GLFW 3.2.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwMaximizeWindow(GLFWwindow* window);
+
+/*! @brief Makes the specified window visible.
+ *
+ * This function makes the specified window visible if it was previously
+ * hidden. If the window is already visible or is in full screen mode, this
+ * function does nothing.
+ *
+ * By default, windowed mode windows are focused when shown
+ * Set the [GLFW_FOCUS_ON_SHOW](@ref GLFW_FOCUS_ON_SHOW_hint) window hint
+ * to change this behavior for all newly created windows, or change the
+ * behavior for an existing window with @ref glfwSetWindowAttrib.
+ *
+ * @param[in] window The window to make visible.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @remark @wayland Because Wayland wants every frame of the desktop to be
+ * complete, this function does not immediately make the window visible.
+ * Instead it will become visible the next time the window framebuffer is
+ * updated after this call.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_hide
+ * @sa @ref glfwHideWindow
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwShowWindow(GLFWwindow* window);
+
+/*! @brief Hides the specified window.
+ *
+ * This function hides the specified window if it was previously visible. If
+ * the window is already hidden or is in full screen mode, this function does
+ * nothing.
+ *
+ * @param[in] window The window to hide.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_hide
+ * @sa @ref glfwShowWindow
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwHideWindow(GLFWwindow* window);
+
+/*! @brief Brings the specified window to front and sets input focus.
+ *
+ * This function brings the specified window to front and sets input focus.
+ * The window should already be visible and not iconified.
+ *
+ * By default, both windowed and full screen mode windows are focused when
+ * initially created. Set the [GLFW_FOCUSED](@ref GLFW_FOCUSED_hint) to
+ * disable this behavior.
+ *
+ * Also by default, windowed mode windows are focused when shown
+ * with @ref glfwShowWindow. Set the
+ * [GLFW_FOCUS_ON_SHOW](@ref GLFW_FOCUS_ON_SHOW_hint) to disable this behavior.
+ *
+ * __Do not use this function__ to steal focus from other applications unless
+ * you are certain that is what the user wants. Focus stealing can be
+ * extremely disruptive.
+ *
+ * For a less disruptive way of getting the user's attention, see
+ * [attention requests](@ref window_attention).
+ *
+ * @param[in] window The window to give input focus.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @remark @wayland The compositor will likely ignore focus requests unless
+ * another window created by the same application already has input focus.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_focus
+ * @sa @ref window_attention
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwFocusWindow(GLFWwindow* window);
+
+/*! @brief Requests user attention to the specified window.
+ *
+ * This function requests user attention to the specified window. On
+ * platforms where this is not supported, attention is requested to the
+ * application as a whole.
+ *
+ * Once the user has given attention, usually by focusing the window or
+ * application, the system will end the request automatically.
+ *
+ * @param[in] window The window to request attention to.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @remark @macos Attention is requested to the application as a whole, not the
+ * specific window.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_attention
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwRequestWindowAttention(GLFWwindow* window);
+
+/*! @brief Returns the monitor that the window uses for full screen mode.
+ *
+ * This function returns the handle of the monitor that the specified window is
+ * in full screen on.
+ *
+ * @param[in] window The window to query.
+ * @return The monitor, or `NULL` if the window is in windowed mode or an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_monitor
+ * @sa @ref glfwSetWindowMonitor
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* window);
+
+/*! @brief Sets the mode, monitor, video mode and placement of a window.
+ *
+ * This function sets the monitor that the window uses for full screen mode or,
+ * if the monitor is `NULL`, makes it windowed mode.
+ *
+ * When setting a monitor, this function updates the width, height and refresh
+ * rate of the desired video mode and switches to the video mode closest to it.
+ * The window position is ignored when setting a monitor.
+ *
+ * When the monitor is `NULL`, the position, width and height are used to
+ * place the window content area. The refresh rate is ignored when no monitor
+ * is specified.
+ *
+ * If you only wish to update the resolution of a full screen window or the
+ * size of a windowed mode window, see @ref glfwSetWindowSize.
+ *
+ * When a window transitions from full screen to windowed mode, this function
+ * restores any previous window settings such as whether it is decorated,
+ * floating, resizable, has size or aspect ratio limits, etc.
+ *
+ * @param[in] window The window whose monitor, size or video mode to set.
+ * @param[in] monitor The desired monitor, or `NULL` to set windowed mode.
+ * @param[in] xpos The desired x-coordinate of the upper-left corner of the
+ * content area.
+ * @param[in] ypos The desired y-coordinate of the upper-left corner of the
+ * content area.
+ * @param[in] width The desired with, in screen coordinates, of the content
+ * area or video mode.
+ * @param[in] height The desired height, in screen coordinates, of the content
+ * area or video mode.
+ * @param[in] refreshRate The desired refresh rate, in Hz, of the video mode,
+ * or `GLFW_DONT_CARE`.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @remark The OpenGL or OpenGL ES context will not be destroyed or otherwise
+ * affected by any resizing or mode switching, although you may need to update
+ * your viewport if the framebuffer size has changed.
+ *
+ * @remark @wayland The desired window position is ignored, as there is no way
+ * for an application to set this property.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_monitor
+ * @sa @ref window_full_screen
+ * @sa @ref glfwGetWindowMonitor
+ * @sa @ref glfwSetWindowSize
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwSetWindowMonitor(GLFWwindow* window, GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate);
+
+/*! @brief Returns an attribute of the specified window.
+ *
+ * This function returns the value of an attribute of the specified window or
+ * its OpenGL or OpenGL ES context.
+ *
+ * @param[in] window The window to query.
+ * @param[in] attrib The [window attribute](@ref window_attribs) whose value to
+ * return.
+ * @return The value of the attribute, or zero if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR.
+ *
+ * @remark Framebuffer related hints are not window attributes. See @ref
+ * window_attribs_fb for more information.
+ *
+ * @remark Zero is a valid value for many window and context related
+ * attributes so you cannot use a return value of zero as an indication of
+ * errors. However, this function should not fail as long as it is passed
+ * valid arguments and the library has been [initialized](@ref intro_init).
+ *
+ * @remark @wayland The Wayland protocol provides no way to check whether a
+ * window is iconfied, so @ref GLFW_ICONIFIED always returns `GLFW_FALSE`.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_attribs
+ * @sa @ref glfwSetWindowAttrib
+ *
+ * @since Added in version 3.0. Replaces `glfwGetWindowParam` and
+ * `glfwGetGLVersion`.
+ *
+ * @ingroup window
+ */
+GLFWAPI int glfwGetWindowAttrib(GLFWwindow* window, int attrib);
+
+/*! @brief Sets an attribute of the specified window.
+ *
+ * This function sets the value of an attribute of the specified window.
+ *
+ * The supported attributes are [GLFW_DECORATED](@ref GLFW_DECORATED_attrib),
+ * [GLFW_RESIZABLE](@ref GLFW_RESIZABLE_attrib),
+ * [GLFW_FLOATING](@ref GLFW_FLOATING_attrib),
+ * [GLFW_AUTO_ICONIFY](@ref GLFW_AUTO_ICONIFY_attrib) and
+ * [GLFW_FOCUS_ON_SHOW](@ref GLFW_FOCUS_ON_SHOW_attrib).
+ * [GLFW_MOUSE_PASSTHROUGH](@ref GLFW_MOUSE_PASSTHROUGH_attrib)
+ *
+ * Some of these attributes are ignored for full screen windows. The new
+ * value will take effect if the window is later made windowed.
+ *
+ * Some of these attributes are ignored for windowed mode windows. The new
+ * value will take effect if the window is later made full screen.
+ *
+ * @param[in] window The window to set the attribute for.
+ * @param[in] attrib A supported window attribute.
+ * @param[in] value `GLFW_TRUE` or `GLFW_FALSE`.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_INVALID_ENUM, @ref GLFW_INVALID_VALUE, @ref GLFW_PLATFORM_ERROR and @ref
+ * GLFW_FEATURE_UNAVAILABLE (see remarks).
+ *
+ * @remark Calling @ref glfwGetWindowAttrib will always return the latest
+ * value, even if that value is ignored by the current mode of the window.
+ *
+ * @remark @wayland The [GLFW_FLOATING](@ref GLFW_FLOATING_attrib) window attribute is
+ * not supported. Setting this will emit @ref GLFW_FEATURE_UNAVAILABLE.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_attribs
+ * @sa @ref glfwGetWindowAttrib
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwSetWindowAttrib(GLFWwindow* window, int attrib, int value);
+
+/*! @brief Sets the user pointer of the specified window.
+ *
+ * This function sets the user-defined pointer of the specified window. The
+ * current value is retained until the window is destroyed. The initial value
+ * is `NULL`.
+ *
+ * @param[in] window The window whose pointer to set.
+ * @param[in] pointer The new value.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @sa @ref window_userptr
+ * @sa @ref glfwGetWindowUserPointer
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwSetWindowUserPointer(GLFWwindow* window, void* pointer);
+
+/*! @brief Returns the user pointer of the specified window.
+ *
+ * This function returns the current value of the user-defined pointer of the
+ * specified window. The initial value is `NULL`.
+ *
+ * @param[in] window The window whose pointer to return.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @sa @ref window_userptr
+ * @sa @ref glfwSetWindowUserPointer
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+GLFWAPI void* glfwGetWindowUserPointer(GLFWwindow* window);
+
+/*! @brief Sets the position callback for the specified window.
+ *
+ * This function sets the position callback of the specified window, which is
+ * called when the window is moved. The callback is provided with the
+ * position, in screen coordinates, of the upper-left corner of the content
+ * area of the window.
+ *
+ * @param[in] window The window whose callback to set.
+ * @param[in] callback The new callback, or `NULL` to remove the currently set
+ * callback.
+ * @return The previously set callback, or `NULL` if no callback was set or the
+ * library had not been [initialized](@ref intro_init).
+ *
+ * @callback_signature
+ * @code
+ * void function_name(GLFWwindow* window, int xpos, int ypos)
+ * @endcode
+ * For more information about the callback parameters, see the
+ * [function pointer type](@ref GLFWwindowposfun).
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @remark @wayland This callback will never be called, as there is no way for
+ * an application to know its global position.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_pos
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+GLFWAPI GLFWwindowposfun glfwSetWindowPosCallback(GLFWwindow* window, GLFWwindowposfun callback);
+
+/*! @brief Sets the size callback for the specified window.
+ *
+ * This function sets the size callback of the specified window, which is
+ * called when the window is resized. The callback is provided with the size,
+ * in screen coordinates, of the content area of the window.
+ *
+ * @param[in] window The window whose callback to set.
+ * @param[in] callback The new callback, or `NULL` to remove the currently set
+ * callback.
+ * @return The previously set callback, or `NULL` if no callback was set or the
+ * library had not been [initialized](@ref intro_init).
+ *
+ * @callback_signature
+ * @code
+ * void function_name(GLFWwindow* window, int width, int height)
+ * @endcode
+ * For more information about the callback parameters, see the
+ * [function pointer type](@ref GLFWwindowsizefun).
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_size
+ *
+ * @since Added in version 1.0.
+ * @glfw3 Added window handle parameter and return value.
+ *
+ * @ingroup window
+ */
+GLFWAPI GLFWwindowsizefun glfwSetWindowSizeCallback(GLFWwindow* window, GLFWwindowsizefun callback);
+
+/*! @brief Sets the close callback for the specified window.
+ *
+ * This function sets the close callback of the specified window, which is
+ * called when the user attempts to close the window, for example by clicking
+ * the close widget in the title bar.
+ *
+ * The close flag is set before this callback is called, but you can modify it
+ * at any time with @ref glfwSetWindowShouldClose.
+ *
+ * The close callback is not triggered by @ref glfwDestroyWindow.
+ *
+ * @param[in] window The window whose callback to set.
+ * @param[in] callback The new callback, or `NULL` to remove the currently set
+ * callback.
+ * @return The previously set callback, or `NULL` if no callback was set or the
+ * library had not been [initialized](@ref intro_init).
+ *
+ * @callback_signature
+ * @code
+ * void function_name(GLFWwindow* window)
+ * @endcode
+ * For more information about the callback parameters, see the
+ * [function pointer type](@ref GLFWwindowclosefun).
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @remark @macos Selecting Quit from the application menu will trigger the
+ * close callback for all windows.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_close
+ *
+ * @since Added in version 2.5.
+ * @glfw3 Added window handle parameter and return value.
+ *
+ * @ingroup window
+ */
+GLFWAPI GLFWwindowclosefun glfwSetWindowCloseCallback(GLFWwindow* window, GLFWwindowclosefun callback);
+
+/*! @brief Sets the refresh callback for the specified window.
+ *
+ * This function sets the refresh callback of the specified window, which is
+ * called when the content area of the window needs to be redrawn, for example
+ * if the window has been exposed after having been covered by another window.
+ *
+ * On compositing window systems such as Aero, Compiz, Aqua or Wayland, where
+ * the window contents are saved off-screen, this callback may be called only
+ * very infrequently or never at all.
+ *
+ * @param[in] window The window whose callback to set.
+ * @param[in] callback The new callback, or `NULL` to remove the currently set
+ * callback.
+ * @return The previously set callback, or `NULL` if no callback was set or the
+ * library had not been [initialized](@ref intro_init).
+ *
+ * @callback_signature
+ * @code
+ * void function_name(GLFWwindow* window);
+ * @endcode
+ * For more information about the callback parameters, see the
+ * [function pointer type](@ref GLFWwindowrefreshfun).
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_refresh
+ *
+ * @since Added in version 2.5.
+ * @glfw3 Added window handle parameter and return value.
+ *
+ * @ingroup window
+ */
+GLFWAPI GLFWwindowrefreshfun glfwSetWindowRefreshCallback(GLFWwindow* window, GLFWwindowrefreshfun callback);
+
+/*! @brief Sets the focus callback for the specified window.
+ *
+ * This function sets the focus callback of the specified window, which is
+ * called when the window gains or loses input focus.
+ *
+ * After the focus callback is called for a window that lost input focus,
+ * synthetic key and mouse button release events will be generated for all such
+ * that had been pressed. For more information, see @ref glfwSetKeyCallback
+ * and @ref glfwSetMouseButtonCallback.
+ *
+ * @param[in] window The window whose callback to set.
+ * @param[in] callback The new callback, or `NULL` to remove the currently set
+ * callback.
+ * @return The previously set callback, or `NULL` if no callback was set or the
+ * library had not been [initialized](@ref intro_init).
+ *
+ * @callback_signature
+ * @code
+ * void function_name(GLFWwindow* window, int focused)
+ * @endcode
+ * For more information about the callback parameters, see the
+ * [function pointer type](@ref GLFWwindowfocusfun).
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_focus
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+GLFWAPI GLFWwindowfocusfun glfwSetWindowFocusCallback(GLFWwindow* window, GLFWwindowfocusfun callback);
+
+/*! @brief Sets the iconify callback for the specified window.
+ *
+ * This function sets the iconification callback of the specified window, which
+ * is called when the window is iconified or restored.
+ *
+ * @param[in] window The window whose callback to set.
+ * @param[in] callback The new callback, or `NULL` to remove the currently set
+ * callback.
+ * @return The previously set callback, or `NULL` if no callback was set or the
+ * library had not been [initialized](@ref intro_init).
+ *
+ * @callback_signature
+ * @code
+ * void function_name(GLFWwindow* window, int iconified)
+ * @endcode
+ * For more information about the callback parameters, see the
+ * [function pointer type](@ref GLFWwindowiconifyfun).
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_iconify
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+GLFWAPI GLFWwindowiconifyfun glfwSetWindowIconifyCallback(GLFWwindow* window, GLFWwindowiconifyfun callback);
+
+/*! @brief Sets the maximize callback for the specified window.
+ *
+ * This function sets the maximization callback of the specified window, which
+ * is called when the window is maximized or restored.
+ *
+ * @param[in] window The window whose callback to set.
+ * @param[in] callback The new callback, or `NULL` to remove the currently set
+ * callback.
+ * @return The previously set callback, or `NULL` if no callback was set or the
+ * library had not been [initialized](@ref intro_init).
+ *
+ * @callback_signature
+ * @code
+ * void function_name(GLFWwindow* window, int maximized)
+ * @endcode
+ * For more information about the callback parameters, see the
+ * [function pointer type](@ref GLFWwindowmaximizefun).
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_maximize
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup window
+ */
+GLFWAPI GLFWwindowmaximizefun glfwSetWindowMaximizeCallback(GLFWwindow* window, GLFWwindowmaximizefun callback);
+
+/*! @brief Sets the framebuffer resize callback for the specified window.
+ *
+ * This function sets the framebuffer resize callback of the specified window,
+ * which is called when the framebuffer of the specified window is resized.
+ *
+ * @param[in] window The window whose callback to set.
+ * @param[in] callback The new callback, or `NULL` to remove the currently set
+ * callback.
+ * @return The previously set callback, or `NULL` if no callback was set or the
+ * library had not been [initialized](@ref intro_init).
+ *
+ * @callback_signature
+ * @code
+ * void function_name(GLFWwindow* window, int width, int height)
+ * @endcode
+ * For more information about the callback parameters, see the
+ * [function pointer type](@ref GLFWframebuffersizefun).
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_fbsize
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* window, GLFWframebuffersizefun callback);
+
+/*! @brief Sets the window content scale callback for the specified window.
+ *
+ * This function sets the window content scale callback of the specified window,
+ * which is called when the content scale of the specified window changes.
+ *
+ * @param[in] window The window whose callback to set.
+ * @param[in] callback The new callback, or `NULL` to remove the currently set
+ * callback.
+ * @return The previously set callback, or `NULL` if no callback was set or the
+ * library had not been [initialized](@ref intro_init).
+ *
+ * @callback_signature
+ * @code
+ * void function_name(GLFWwindow* window, float xscale, float yscale)
+ * @endcode
+ * For more information about the callback parameters, see the
+ * [function pointer type](@ref GLFWwindowcontentscalefun).
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_scale
+ * @sa @ref glfwGetWindowContentScale
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup window
+ */
+GLFWAPI GLFWwindowcontentscalefun glfwSetWindowContentScaleCallback(GLFWwindow* window, GLFWwindowcontentscalefun callback);
+
+/*! @brief Processes all pending events.
+ *
+ * This function processes only those events that are already in the event
+ * queue and then returns immediately. Processing events will cause the window
+ * and input callbacks associated with those events to be called.
+ *
+ * On some platforms, a window move, resize or menu operation will cause event
+ * processing to block. This is due to how event processing is designed on
+ * those platforms. You can use the
+ * [window refresh callback](@ref window_refresh) to redraw the contents of
+ * your window when necessary during such operations.
+ *
+ * Do not assume that callbacks you set will _only_ be called in response to
+ * event processing functions like this one. While it is necessary to poll for
+ * events, window systems that require GLFW to register callbacks of its own
+ * can pass events to GLFW in response to many window system function calls.
+ * GLFW will pass those events on to the application callbacks before
+ * returning.
+ *
+ * Event processing is not required for joystick input to work.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @reentrancy This function must not be called from a callback.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref events
+ * @sa @ref glfwWaitEvents
+ * @sa @ref glfwWaitEventsTimeout
+ *
+ * @since Added in version 1.0.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwPollEvents(void);
+
+/*! @brief Waits until events are queued and processes them.
+ *
+ * This function puts the calling thread to sleep until at least one event is
+ * available in the event queue. Once one or more events are available,
+ * it behaves exactly like @ref glfwPollEvents, i.e. the events in the queue
+ * are processed and the function then returns immediately. Processing events
+ * will cause the window and input callbacks associated with those events to be
+ * called.
+ *
+ * Since not all events are associated with callbacks, this function may return
+ * without a callback having been called even if you are monitoring all
+ * callbacks.
+ *
+ * On some platforms, a window move, resize or menu operation will cause event
+ * processing to block. This is due to how event processing is designed on
+ * those platforms. You can use the
+ * [window refresh callback](@ref window_refresh) to redraw the contents of
+ * your window when necessary during such operations.
+ *
+ * Do not assume that callbacks you set will _only_ be called in response to
+ * event processing functions like this one. While it is necessary to poll for
+ * events, window systems that require GLFW to register callbacks of its own
+ * can pass events to GLFW in response to many window system function calls.
+ * GLFW will pass those events on to the application callbacks before
+ * returning.
+ *
+ * Event processing is not required for joystick input to work.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @reentrancy This function must not be called from a callback.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref events
+ * @sa @ref glfwPollEvents
+ * @sa @ref glfwWaitEventsTimeout
+ *
+ * @since Added in version 2.5.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwWaitEvents(void);
+
+/*! @brief Waits with timeout until events are queued and processes them.
+ *
+ * This function puts the calling thread to sleep until at least one event is
+ * available in the event queue, or until the specified timeout is reached. If
+ * one or more events are available, it behaves exactly like @ref
+ * glfwPollEvents, i.e. the events in the queue are processed and the function
+ * then returns immediately. Processing events will cause the window and input
+ * callbacks associated with those events to be called.
+ *
+ * The timeout value must be a positive finite number.
+ *
+ * Since not all events are associated with callbacks, this function may return
+ * without a callback having been called even if you are monitoring all
+ * callbacks.
+ *
+ * On some platforms, a window move, resize or menu operation will cause event
+ * processing to block. This is due to how event processing is designed on
+ * those platforms. You can use the
+ * [window refresh callback](@ref window_refresh) to redraw the contents of
+ * your window when necessary during such operations.
+ *
+ * Do not assume that callbacks you set will _only_ be called in response to
+ * event processing functions like this one. While it is necessary to poll for
+ * events, window systems that require GLFW to register callbacks of its own
+ * can pass events to GLFW in response to many window system function calls.
+ * GLFW will pass those events on to the application callbacks before
+ * returning.
+ *
+ * Event processing is not required for joystick input to work.
+ *
+ * @param[in] timeout The maximum amount of time, in seconds, to wait.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR.
+ *
+ * @reentrancy This function must not be called from a callback.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref events
+ * @sa @ref glfwPollEvents
+ * @sa @ref glfwWaitEvents
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwWaitEventsTimeout(double timeout);
+
+/*! @brief Posts an empty event to the event queue.
+ *
+ * This function posts an empty event from the current thread to the event
+ * queue, causing @ref glfwWaitEvents or @ref glfwWaitEventsTimeout to return.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function may be called from any thread.
+ *
+ * @sa @ref events
+ * @sa @ref glfwWaitEvents
+ * @sa @ref glfwWaitEventsTimeout
+ *
+ * @since Added in version 3.1.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwPostEmptyEvent(void);
+
+/*! @brief Returns the value of an input option for the specified window.
+ *
+ * This function returns the value of an input option for the specified window.
+ * The mode must be one of @ref GLFW_CURSOR, @ref GLFW_STICKY_KEYS,
+ * @ref GLFW_STICKY_MOUSE_BUTTONS, @ref GLFW_LOCK_KEY_MODS or
+ * @ref GLFW_RAW_MOUSE_MOTION.
+ *
+ * @param[in] window The window to query.
+ * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS`,
+ * `GLFW_STICKY_MOUSE_BUTTONS`, `GLFW_LOCK_KEY_MODS` or
+ * `GLFW_RAW_MOUSE_MOTION`.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_INVALID_ENUM.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref glfwSetInputMode
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup input
+ */
+GLFWAPI int glfwGetInputMode(GLFWwindow* window, int mode);
+
+/*! @brief Sets an input option for the specified window.
+ *
+ * This function sets an input mode option for the specified window. The mode
+ * must be one of @ref GLFW_CURSOR, @ref GLFW_STICKY_KEYS,
+ * @ref GLFW_STICKY_MOUSE_BUTTONS, @ref GLFW_LOCK_KEY_MODS or
+ * @ref GLFW_RAW_MOUSE_MOTION.
+ *
+ * If the mode is `GLFW_CURSOR`, the value must be one of the following cursor
+ * modes:
+ * - `GLFW_CURSOR_NORMAL` makes the cursor visible and behaving normally.
+ * - `GLFW_CURSOR_HIDDEN` makes the cursor invisible when it is over the
+ * content area of the window but does not restrict the cursor from leaving.
+ * - `GLFW_CURSOR_DISABLED` hides and grabs the cursor, providing virtual
+ * and unlimited cursor movement. This is useful for implementing for
+ * example 3D camera controls.
+ * - `GLFW_CURSOR_CAPTURED` makes the cursor visible and confines it to the
+ * content area of the window.
+ *
+ * If the mode is `GLFW_STICKY_KEYS`, the value must be either `GLFW_TRUE` to
+ * enable sticky keys, or `GLFW_FALSE` to disable it. If sticky keys are
+ * enabled, a key press will ensure that @ref glfwGetKey returns `GLFW_PRESS`
+ * the next time it is called even if the key had been released before the
+ * call. This is useful when you are only interested in whether keys have been
+ * pressed but not when or in which order.
+ *
+ * If the mode is `GLFW_STICKY_MOUSE_BUTTONS`, the value must be either
+ * `GLFW_TRUE` to enable sticky mouse buttons, or `GLFW_FALSE` to disable it.
+ * If sticky mouse buttons are enabled, a mouse button press will ensure that
+ * @ref glfwGetMouseButton returns `GLFW_PRESS` the next time it is called even
+ * if the mouse button had been released before the call. This is useful when
+ * you are only interested in whether mouse buttons have been pressed but not
+ * when or in which order.
+ *
+ * If the mode is `GLFW_LOCK_KEY_MODS`, the value must be either `GLFW_TRUE` to
+ * enable lock key modifier bits, or `GLFW_FALSE` to disable them. If enabled,
+ * callbacks that receive modifier bits will also have the @ref
+ * GLFW_MOD_CAPS_LOCK bit set when the event was generated with Caps Lock on,
+ * and the @ref GLFW_MOD_NUM_LOCK bit when Num Lock was on.
+ *
+ * If the mode is `GLFW_RAW_MOUSE_MOTION`, the value must be either `GLFW_TRUE`
+ * to enable raw (unscaled and unaccelerated) mouse motion when the cursor is
+ * disabled, or `GLFW_FALSE` to disable it. If raw motion is not supported,
+ * attempting to set this will emit @ref GLFW_FEATURE_UNAVAILABLE. Call @ref
+ * glfwRawMouseMotionSupported to check for support.
+ *
+ * @param[in] window The window whose input mode to set.
+ * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS`,
+ * `GLFW_STICKY_MOUSE_BUTTONS`, `GLFW_LOCK_KEY_MODS` or
+ * `GLFW_RAW_MOUSE_MOTION`.
+ * @param[in] value The new value of the specified input mode.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_INVALID_ENUM, @ref GLFW_PLATFORM_ERROR and @ref
+ * GLFW_FEATURE_UNAVAILABLE (see above).
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref glfwGetInputMode
+ *
+ * @since Added in version 3.0. Replaces `glfwEnable` and `glfwDisable`.
+ *
+ * @ingroup input
+ */
+GLFWAPI void glfwSetInputMode(GLFWwindow* window, int mode, int value);
+
+/*! @brief Returns whether raw mouse motion is supported.
+ *
+ * This function returns whether raw mouse motion is supported on the current
+ * system. This status does not change after GLFW has been initialized so you
+ * only need to check this once. If you attempt to enable raw motion on
+ * a system that does not support it, @ref GLFW_PLATFORM_ERROR will be emitted.
+ *
+ * Raw mouse motion is closer to the actual motion of the mouse across
+ * a surface. It is not affected by the scaling and acceleration applied to
+ * the motion of the desktop cursor. That processing is suitable for a cursor
+ * while raw motion is better for controlling for example a 3D camera. Because
+ * of this, raw mouse motion is only provided when the cursor is disabled.
+ *
+ * @return `GLFW_TRUE` if raw mouse motion is supported on the current machine,
+ * or `GLFW_FALSE` otherwise.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref raw_mouse_motion
+ * @sa @ref glfwSetInputMode
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup input
+ */
+GLFWAPI int glfwRawMouseMotionSupported(void);
+
+/*! @brief Returns the layout-specific name of the specified printable key.
+ *
+ * This function returns the name of the specified printable key, encoded as
+ * UTF-8. This is typically the character that key would produce without any
+ * modifier keys, intended for displaying key bindings to the user. For dead
+ * keys, it is typically the diacritic it would add to a character.
+ *
+ * __Do not use this function__ for [text input](@ref input_char). You will
+ * break text input for many languages even if it happens to work for yours.
+ *
+ * If the key is `GLFW_KEY_UNKNOWN`, the scancode is used to identify the key,
+ * otherwise the scancode is ignored. If you specify a non-printable key, or
+ * `GLFW_KEY_UNKNOWN` and a scancode that maps to a non-printable key, this
+ * function returns `NULL` but does not emit an error.
+ *
+ * This behavior allows you to always pass in the arguments in the
+ * [key callback](@ref input_key) without modification.
+ *
+ * The printable keys are:
+ * - `GLFW_KEY_APOSTROPHE`
+ * - `GLFW_KEY_COMMA`
+ * - `GLFW_KEY_MINUS`
+ * - `GLFW_KEY_PERIOD`
+ * - `GLFW_KEY_SLASH`
+ * - `GLFW_KEY_SEMICOLON`
+ * - `GLFW_KEY_EQUAL`
+ * - `GLFW_KEY_LEFT_BRACKET`
+ * - `GLFW_KEY_RIGHT_BRACKET`
+ * - `GLFW_KEY_BACKSLASH`
+ * - `GLFW_KEY_WORLD_1`
+ * - `GLFW_KEY_WORLD_2`
+ * - `GLFW_KEY_0` to `GLFW_KEY_9`
+ * - `GLFW_KEY_A` to `GLFW_KEY_Z`
+ * - `GLFW_KEY_KP_0` to `GLFW_KEY_KP_9`
+ * - `GLFW_KEY_KP_DECIMAL`
+ * - `GLFW_KEY_KP_DIVIDE`
+ * - `GLFW_KEY_KP_MULTIPLY`
+ * - `GLFW_KEY_KP_SUBTRACT`
+ * - `GLFW_KEY_KP_ADD`
+ * - `GLFW_KEY_KP_EQUAL`
+ *
+ * Names for printable keys depend on keyboard layout, while names for
+ * non-printable keys are the same across layouts but depend on the application
+ * language and should be localized along with other user interface text.
+ *
+ * @param[in] key The key to query, or `GLFW_KEY_UNKNOWN`.
+ * @param[in] scancode The scancode of the key to query.
+ * @return The UTF-8 encoded, layout-specific name of the key, or `NULL`.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_INVALID_VALUE, @ref GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR.
+ *
+ * @remark The contents of the returned string may change when a keyboard
+ * layout change event is received.
+ *
+ * @pointer_lifetime The returned string is allocated and freed by GLFW. You
+ * should not free it yourself. It is valid until the library is terminated.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref input_key_name
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup input
+ */
+GLFWAPI const char* glfwGetKeyName(int key, int scancode);
+
+/*! @brief Returns the platform-specific scancode of the specified key.
+ *
+ * This function returns the platform-specific scancode of the specified key.
+ *
+ * If the specified [key token](@ref keys) corresponds to a physical key not
+ * supported on the current platform then this method will return `-1`.
+ * Calling this function with anything other than a key token will return `-1`
+ * and generate a @ref GLFW_INVALID_ENUM error.
+ *
+ * @param[in] key Any [key token](@ref keys).
+ * @return The platform-specific scancode for the key, or `-1` if the key is
+ * not supported on the current platform or an [error](@ref error_handling)
+ * occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_INVALID_ENUM.
+ *
+ * @thread_safety This function may be called from any thread.
+ *
+ * @sa @ref input_key
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup input
+ */
+GLFWAPI int glfwGetKeyScancode(int key);
+
+/*! @brief Returns the last reported state of a keyboard key for the specified
+ * window.
+ *
+ * This function returns the last state reported for the specified key to the
+ * specified window. The returned state is one of `GLFW_PRESS` or
+ * `GLFW_RELEASE`. The action `GLFW_REPEAT` is only reported to the key callback.
+ *
+ * If the @ref GLFW_STICKY_KEYS input mode is enabled, this function returns
+ * `GLFW_PRESS` the first time you call it for a key that was pressed, even if
+ * that key has already been released.
+ *
+ * The key functions deal with physical keys, with [key tokens](@ref keys)
+ * named after their use on the standard US keyboard layout. If you want to
+ * input text, use the Unicode character callback instead.
+ *
+ * The [modifier key bit masks](@ref mods) are not key tokens and cannot be
+ * used with this function.
+ *
+ * __Do not use this function__ to implement [text input](@ref input_char).
+ *
+ * @param[in] window The desired window.
+ * @param[in] key The desired [keyboard key](@ref keys). `GLFW_KEY_UNKNOWN` is
+ * not a valid key for this function.
+ * @return One of `GLFW_PRESS` or `GLFW_RELEASE`.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_INVALID_ENUM.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref input_key
+ *
+ * @since Added in version 1.0.
+ * @glfw3 Added window handle parameter.
+ *
+ * @ingroup input
+ */
+GLFWAPI int glfwGetKey(GLFWwindow* window, int key);
+
+/*! @brief Returns the last reported state of a mouse button for the specified
+ * window.
+ *
+ * This function returns the last state reported for the specified mouse button
+ * to the specified window. The returned state is one of `GLFW_PRESS` or
+ * `GLFW_RELEASE`.
+ *
+ * If the @ref GLFW_STICKY_MOUSE_BUTTONS input mode is enabled, this function
+ * returns `GLFW_PRESS` the first time you call it for a mouse button that was
+ * pressed, even if that mouse button has already been released.
+ *
+ * @param[in] window The desired window.
+ * @param[in] button The desired [mouse button](@ref buttons).
+ * @return One of `GLFW_PRESS` or `GLFW_RELEASE`.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_INVALID_ENUM.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref input_mouse_button
+ *
+ * @since Added in version 1.0.
+ * @glfw3 Added window handle parameter.
+ *
+ * @ingroup input
+ */
+GLFWAPI int glfwGetMouseButton(GLFWwindow* window, int button);
+
+/*! @brief Retrieves the position of the cursor relative to the content area of
+ * the window.
+ *
+ * This function returns the position of the cursor, in screen coordinates,
+ * relative to the upper-left corner of the content area of the specified
+ * window.
+ *
+ * If the cursor is disabled (with `GLFW_CURSOR_DISABLED`) then the cursor
+ * position is unbounded and limited only by the minimum and maximum values of
+ * a `double`.
+ *
+ * The coordinate can be converted to their integer equivalents with the
+ * `floor` function. Casting directly to an integer type works for positive
+ * coordinates, but fails for negative ones.
+ *
+ * Any or all of the position arguments may be `NULL`. If an error occurs, all
+ * non-`NULL` position arguments will be set to zero.
+ *
+ * @param[in] window The desired window.
+ * @param[out] xpos Where to store the cursor x-coordinate, relative to the
+ * left edge of the content area, or `NULL`.
+ * @param[out] ypos Where to store the cursor y-coordinate, relative to the to
+ * top edge of the content area, or `NULL`.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref cursor_pos
+ * @sa @ref glfwSetCursorPos
+ *
+ * @since Added in version 3.0. Replaces `glfwGetMousePos`.
+ *
+ * @ingroup input
+ */
+GLFWAPI void glfwGetCursorPos(GLFWwindow* window, double* xpos, double* ypos);
+
+/*! @brief Sets the position of the cursor, relative to the content area of the
+ * window.
+ *
+ * This function sets the position, in screen coordinates, of the cursor
+ * relative to the upper-left corner of the content area of the specified
+ * window. The window must have input focus. If the window does not have
+ * input focus when this function is called, it fails silently.
+ *
+ * __Do not use this function__ to implement things like camera controls. GLFW
+ * already provides the `GLFW_CURSOR_DISABLED` cursor mode that hides the
+ * cursor, transparently re-centers it and provides unconstrained cursor
+ * motion. See @ref glfwSetInputMode for more information.
+ *
+ * If the cursor mode is `GLFW_CURSOR_DISABLED` then the cursor position is
+ * unconstrained and limited only by the minimum and maximum values of
+ * a `double`.
+ *
+ * @param[in] window The desired window.
+ * @param[in] xpos The desired x-coordinate, relative to the left edge of the
+ * content area.
+ * @param[in] ypos The desired y-coordinate, relative to the top edge of the
+ * content area.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_PLATFORM_ERROR and @ref GLFW_FEATURE_UNAVAILABLE (see remarks).
+ *
+ * @remark @wayland This function will only work when the cursor mode is
+ * `GLFW_CURSOR_DISABLED`, otherwise it will emit @ref GLFW_FEATURE_UNAVAILABLE.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref cursor_pos
+ * @sa @ref glfwGetCursorPos
+ *
+ * @since Added in version 3.0. Replaces `glfwSetMousePos`.
+ *
+ * @ingroup input
+ */
+GLFWAPI void glfwSetCursorPos(GLFWwindow* window, double xpos, double ypos);
+
+/*! @brief Creates a custom cursor.
+ *
+ * Creates a new custom cursor image that can be set for a window with @ref
+ * glfwSetCursor. The cursor can be destroyed with @ref glfwDestroyCursor.
+ * Any remaining cursors are destroyed by @ref glfwTerminate.
+ *
+ * The pixels are 32-bit, little-endian, non-premultiplied RGBA, i.e. eight
+ * bits per channel with the red channel first. They are arranged canonically
+ * as packed sequential rows, starting from the top-left corner.
+ *
+ * The cursor hotspot is specified in pixels, relative to the upper-left corner
+ * of the cursor image. Like all other coordinate systems in GLFW, the X-axis
+ * points to the right and the Y-axis points down.
+ *
+ * @param[in] image The desired cursor image.
+ * @param[in] xhot The desired x-coordinate, in pixels, of the cursor hotspot.
+ * @param[in] yhot The desired y-coordinate, in pixels, of the cursor hotspot.
+ * @return The handle of the created cursor, or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR.
+ *
+ * @pointer_lifetime The specified image data is copied before this function
+ * returns.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref cursor_object
+ * @sa @ref glfwDestroyCursor
+ * @sa @ref glfwCreateStandardCursor
+ *
+ * @since Added in version 3.1.
+ *
+ * @ingroup input
+ */
+GLFWAPI GLFWcursor* glfwCreateCursor(const GLFWimage* image, int xhot, int yhot);
+
+/*! @brief Creates a cursor with a standard shape.
+ *
+ * Returns a cursor with a standard shape, that can be set for a window with
+ * @ref glfwSetCursor. The images for these cursors come from the system
+ * cursor theme and their exact appearance will vary between platforms.
+ *
+ * Most of these shapes are guaranteed to exist on every supported platform but
+ * a few may not be present. See the table below for details.
+ *
+ * Cursor shape | Windows | macOS | X11 | Wayland
+ * ------------------------------ | ------- | ----- | ------ | -------
+ * @ref GLFW_ARROW_CURSOR | Yes | Yes | Yes | Yes
+ * @ref GLFW_IBEAM_CURSOR | Yes | Yes | Yes | Yes
+ * @ref GLFW_CROSSHAIR_CURSOR | Yes | Yes | Yes | Yes
+ * @ref GLFW_POINTING_HAND_CURSOR | Yes | Yes | Yes | Yes
+ * @ref GLFW_RESIZE_EW_CURSOR | Yes | Yes | Yes | Yes
+ * @ref GLFW_RESIZE_NS_CURSOR | Yes | Yes | Yes | Yes
+ * @ref GLFW_RESIZE_NWSE_CURSOR | Yes | Yes1 | Maybe2 | Maybe2
+ * @ref GLFW_RESIZE_NESW_CURSOR | Yes | Yes1 | Maybe2 | Maybe2
+ * @ref GLFW_RESIZE_ALL_CURSOR | Yes | Yes | Yes | Yes
+ * @ref GLFW_NOT_ALLOWED_CURSOR | Yes | Yes | Maybe2 | Maybe2
+ *
+ * 1) This uses a private system API and may fail in the future.
+ *
+ * 2) This uses a newer standard that not all cursor themes support.
+ *
+ * If the requested shape is not available, this function emits a @ref
+ * GLFW_CURSOR_UNAVAILABLE error and returns `NULL`.
+ *
+ * @param[in] shape One of the [standard shapes](@ref shapes).
+ * @return A new cursor ready to use or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_INVALID_ENUM, @ref GLFW_CURSOR_UNAVAILABLE and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref cursor_standard
+ * @sa @ref glfwCreateCursor
+ *
+ * @since Added in version 3.1.
+ *
+ * @ingroup input
+ */
+GLFWAPI GLFWcursor* glfwCreateStandardCursor(int shape);
+
+/*! @brief Destroys a cursor.
+ *
+ * This function destroys a cursor previously created with @ref
+ * glfwCreateCursor. Any remaining cursors will be destroyed by @ref
+ * glfwTerminate.
+ *
+ * If the specified cursor is current for any window, that window will be
+ * reverted to the default cursor. This does not affect the cursor mode.
+ *
+ * @param[in] cursor The cursor object to destroy.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @reentrancy This function must not be called from a callback.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref cursor_object
+ * @sa @ref glfwCreateCursor
+ *
+ * @since Added in version 3.1.
+ *
+ * @ingroup input
+ */
+GLFWAPI void glfwDestroyCursor(GLFWcursor* cursor);
+
+/*! @brief Sets the cursor for the window.
+ *
+ * This function sets the cursor image to be used when the cursor is over the
+ * content area of the specified window. The set cursor will only be visible
+ * when the [cursor mode](@ref cursor_mode) of the window is
+ * `GLFW_CURSOR_NORMAL`.
+ *
+ * On some platforms, the set cursor may not be visible unless the window also
+ * has input focus.
+ *
+ * @param[in] window The window to set the cursor for.
+ * @param[in] cursor The cursor to set, or `NULL` to switch back to the default
+ * arrow cursor.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref cursor_object
+ *
+ * @since Added in version 3.1.
+ *
+ * @ingroup input
+ */
+GLFWAPI void glfwSetCursor(GLFWwindow* window, GLFWcursor* cursor);
+
+/*! @brief Sets the key callback.
+ *
+ * This function sets the key callback of the specified window, which is called
+ * when a key is pressed, repeated or released.
+ *
+ * The key functions deal with physical keys, with layout independent
+ * [key tokens](@ref keys) named after their values in the standard US keyboard
+ * layout. If you want to input text, use the
+ * [character callback](@ref glfwSetCharCallback) instead.
+ *
+ * When a window loses input focus, it will generate synthetic key release
+ * events for all pressed keys with associated key tokens. You can tell these
+ * events from user-generated events by the fact that the synthetic ones are
+ * generated after the focus loss event has been processed, i.e. after the
+ * [window focus callback](@ref glfwSetWindowFocusCallback) has been called.
+ *
+ * The scancode of a key is specific to that platform or sometimes even to that
+ * machine. Scancodes are intended to allow users to bind keys that don't have
+ * a GLFW key token. Such keys have `key` set to `GLFW_KEY_UNKNOWN`, their
+ * state is not saved and so it cannot be queried with @ref glfwGetKey.
+ *
+ * Sometimes GLFW needs to generate synthetic key events, in which case the
+ * scancode may be zero.
+ *
+ * @param[in] window The window whose callback to set.
+ * @param[in] callback The new key callback, or `NULL` to remove the currently
+ * set callback.
+ * @return The previously set callback, or `NULL` if no callback was set or the
+ * library had not been [initialized](@ref intro_init).
+ *
+ * @callback_signature
+ * @code
+ * void function_name(GLFWwindow* window, int key, int scancode, int action, int mods)
+ * @endcode
+ * For more information about the callback parameters, see the
+ * [function pointer type](@ref GLFWkeyfun).
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref input_key
+ *
+ * @since Added in version 1.0.
+ * @glfw3 Added window handle parameter and return value.
+ *
+ * @ingroup input
+ */
+GLFWAPI GLFWkeyfun glfwSetKeyCallback(GLFWwindow* window, GLFWkeyfun callback);
+
+/*! @brief Sets the Unicode character callback.
+ *
+ * This function sets the character callback of the specified window, which is
+ * called when a Unicode character is input.
+ *
+ * The character callback is intended for Unicode text input. As it deals with
+ * characters, it is keyboard layout dependent, whereas the
+ * [key callback](@ref glfwSetKeyCallback) is not. Characters do not map 1:1
+ * to physical keys, as a key may produce zero, one or more characters. If you
+ * want to know whether a specific physical key was pressed or released, see
+ * the key callback instead.
+ *
+ * The character callback behaves as system text input normally does and will
+ * not be called if modifier keys are held down that would prevent normal text
+ * input on that platform, for example a Super (Command) key on macOS or Alt key
+ * on Windows.
+ *
+ * @param[in] window The window whose callback to set.
+ * @param[in] callback The new callback, or `NULL` to remove the currently set
+ * callback.
+ * @return The previously set callback, or `NULL` if no callback was set or the
+ * library had not been [initialized](@ref intro_init).
+ *
+ * @callback_signature
+ * @code
+ * void function_name(GLFWwindow* window, unsigned int codepoint)
+ * @endcode
+ * For more information about the callback parameters, see the
+ * [function pointer type](@ref GLFWcharfun).
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref input_char
+ *
+ * @since Added in version 2.4.
+ * @glfw3 Added window handle parameter and return value.
+ *
+ * @ingroup input
+ */
+GLFWAPI GLFWcharfun glfwSetCharCallback(GLFWwindow* window, GLFWcharfun callback);
+
+/*! @brief Sets the Unicode character with modifiers callback.
+ *
+ * This function sets the character with modifiers callback of the specified
+ * window, which is called when a Unicode character is input regardless of what
+ * modifier keys are used.
+ *
+ * The character with modifiers callback is intended for implementing custom
+ * Unicode character input. For regular Unicode text input, see the
+ * [character callback](@ref glfwSetCharCallback). Like the character
+ * callback, the character with modifiers callback deals with characters and is
+ * keyboard layout dependent. Characters do not map 1:1 to physical keys, as
+ * a key may produce zero, one or more characters. If you want to know whether
+ * a specific physical key was pressed or released, see the
+ * [key callback](@ref glfwSetKeyCallback) instead.
+ *
+ * @param[in] window The window whose callback to set.
+ * @param[in] callback The new callback, or `NULL` to remove the currently set
+ * callback.
+ * @return The previously set callback, or `NULL` if no callback was set or an
+ * [error](@ref error_handling) occurred.
+ *
+ * @callback_signature
+ * @code
+ * void function_name(GLFWwindow* window, unsigned int codepoint, int mods)
+ * @endcode
+ * For more information about the callback parameters, see the
+ * [function pointer type](@ref GLFWcharmodsfun).
+ *
+ * @deprecated Scheduled for removal in version 4.0.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref input_char
+ *
+ * @since Added in version 3.1.
+ *
+ * @ingroup input
+ */
+GLFWAPI GLFWcharmodsfun glfwSetCharModsCallback(GLFWwindow* window, GLFWcharmodsfun callback);
+
+/*! @brief Sets the mouse button callback.
+ *
+ * This function sets the mouse button callback of the specified window, which
+ * is called when a mouse button is pressed or released.
+ *
+ * When a window loses input focus, it will generate synthetic mouse button
+ * release events for all pressed mouse buttons. You can tell these events
+ * from user-generated events by the fact that the synthetic ones are generated
+ * after the focus loss event has been processed, i.e. after the
+ * [window focus callback](@ref glfwSetWindowFocusCallback) has been called.
+ *
+ * @param[in] window The window whose callback to set.
+ * @param[in] callback The new callback, or `NULL` to remove the currently set
+ * callback.
+ * @return The previously set callback, or `NULL` if no callback was set or the
+ * library had not been [initialized](@ref intro_init).
+ *
+ * @callback_signature
+ * @code
+ * void function_name(GLFWwindow* window, int button, int action, int mods)
+ * @endcode
+ * For more information about the callback parameters, see the
+ * [function pointer type](@ref GLFWmousebuttonfun).
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref input_mouse_button
+ *
+ * @since Added in version 1.0.
+ * @glfw3 Added window handle parameter and return value.
+ *
+ * @ingroup input
+ */
+GLFWAPI GLFWmousebuttonfun glfwSetMouseButtonCallback(GLFWwindow* window, GLFWmousebuttonfun callback);
+
+/*! @brief Sets the cursor position callback.
+ *
+ * This function sets the cursor position callback of the specified window,
+ * which is called when the cursor is moved. The callback is provided with the
+ * position, in screen coordinates, relative to the upper-left corner of the
+ * content area of the window.
+ *
+ * @param[in] window The window whose callback to set.
+ * @param[in] callback The new callback, or `NULL` to remove the currently set
+ * callback.
+ * @return The previously set callback, or `NULL` if no callback was set or the
+ * library had not been [initialized](@ref intro_init).
+ *
+ * @callback_signature
+ * @code
+ * void function_name(GLFWwindow* window, double xpos, double ypos);
+ * @endcode
+ * For more information about the callback parameters, see the
+ * [function pointer type](@ref GLFWcursorposfun).
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref cursor_pos
+ *
+ * @since Added in version 3.0. Replaces `glfwSetMousePosCallback`.
+ *
+ * @ingroup input
+ */
+GLFWAPI GLFWcursorposfun glfwSetCursorPosCallback(GLFWwindow* window, GLFWcursorposfun callback);
+
+/*! @brief Sets the cursor enter/leave callback.
+ *
+ * This function sets the cursor boundary crossing callback of the specified
+ * window, which is called when the cursor enters or leaves the content area of
+ * the window.
+ *
+ * @param[in] window The window whose callback to set.
+ * @param[in] callback The new callback, or `NULL` to remove the currently set
+ * callback.
+ * @return The previously set callback, or `NULL` if no callback was set or the
+ * library had not been [initialized](@ref intro_init).
+ *
+ * @callback_signature
+ * @code
+ * void function_name(GLFWwindow* window, int entered)
+ * @endcode
+ * For more information about the callback parameters, see the
+ * [function pointer type](@ref GLFWcursorenterfun).
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref cursor_enter
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup input
+ */
+GLFWAPI GLFWcursorenterfun glfwSetCursorEnterCallback(GLFWwindow* window, GLFWcursorenterfun callback);
+
+/*! @brief Sets the scroll callback.
+ *
+ * This function sets the scroll callback of the specified window, which is
+ * called when a scrolling device is used, such as a mouse wheel or scrolling
+ * area of a touchpad.
+ *
+ * The scroll callback receives all scrolling input, like that from a mouse
+ * wheel or a touchpad scrolling area.
+ *
+ * @param[in] window The window whose callback to set.
+ * @param[in] callback The new scroll callback, or `NULL` to remove the
+ * currently set callback.
+ * @return The previously set callback, or `NULL` if no callback was set or the
+ * library had not been [initialized](@ref intro_init).
+ *
+ * @callback_signature
+ * @code
+ * void function_name(GLFWwindow* window, double xoffset, double yoffset)
+ * @endcode
+ * For more information about the callback parameters, see the
+ * [function pointer type](@ref GLFWscrollfun).
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref scrolling
+ *
+ * @since Added in version 3.0. Replaces `glfwSetMouseWheelCallback`.
+ *
+ * @ingroup input
+ */
+GLFWAPI GLFWscrollfun glfwSetScrollCallback(GLFWwindow* window, GLFWscrollfun callback);
+
+/*! @brief Sets the path drop callback.
+ *
+ * This function sets the path drop callback of the specified window, which is
+ * called when one or more dragged paths are dropped on the window.
+ *
+ * Because the path array and its strings may have been generated specifically
+ * for that event, they are not guaranteed to be valid after the callback has
+ * returned. If you wish to use them after the callback returns, you need to
+ * make a deep copy.
+ *
+ * @param[in] window The window whose callback to set.
+ * @param[in] callback The new file drop callback, or `NULL` to remove the
+ * currently set callback.
+ * @return The previously set callback, or `NULL` if no callback was set or the
+ * library had not been [initialized](@ref intro_init).
+ *
+ * @callback_signature
+ * @code
+ * void function_name(GLFWwindow* window, int path_count, const char* paths[])
+ * @endcode
+ * For more information about the callback parameters, see the
+ * [function pointer type](@ref GLFWdropfun).
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref path_drop
+ *
+ * @since Added in version 3.1.
+ *
+ * @ingroup input
+ */
+GLFWAPI GLFWdropfun glfwSetDropCallback(GLFWwindow* window, GLFWdropfun callback);
+
+/*! @brief Returns whether the specified joystick is present.
+ *
+ * This function returns whether the specified joystick is present.
+ *
+ * There is no need to call this function before other functions that accept
+ * a joystick ID, as they all check for presence before performing any other
+ * work.
+ *
+ * @param[in] jid The [joystick](@ref joysticks) to query.
+ * @return `GLFW_TRUE` if the joystick is present, or `GLFW_FALSE` otherwise.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref joystick
+ *
+ * @since Added in version 3.0. Replaces `glfwGetJoystickParam`.
+ *
+ * @ingroup input
+ */
+GLFWAPI int glfwJoystickPresent(int jid);
+
+/*! @brief Returns the values of all axes of the specified joystick.
+ *
+ * This function returns the values of all axes of the specified joystick.
+ * Each element in the array is a value between -1.0 and 1.0.
+ *
+ * If the specified joystick is not present this function will return `NULL`
+ * but will not generate an error. This can be used instead of first calling
+ * @ref glfwJoystickPresent.
+ *
+ * @param[in] jid The [joystick](@ref joysticks) to query.
+ * @param[out] count Where to store the number of axis values in the returned
+ * array. This is set to zero if the joystick is not present or an error
+ * occurred.
+ * @return An array of axis values, or `NULL` if the joystick is not present or
+ * an [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR.
+ *
+ * @pointer_lifetime The returned array is allocated and freed by GLFW. You
+ * should not free it yourself. It is valid until the specified joystick is
+ * disconnected or the library is terminated.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref joystick_axis
+ *
+ * @since Added in version 3.0. Replaces `glfwGetJoystickPos`.
+ *
+ * @ingroup input
+ */
+GLFWAPI const float* glfwGetJoystickAxes(int jid, int* count);
+
+/*! @brief Returns the state of all buttons of the specified joystick.
+ *
+ * This function returns the state of all buttons of the specified joystick.
+ * Each element in the array is either `GLFW_PRESS` or `GLFW_RELEASE`.
+ *
+ * For backward compatibility with earlier versions that did not have @ref
+ * glfwGetJoystickHats, the button array also includes all hats, each
+ * represented as four buttons. The hats are in the same order as returned by
+ * __glfwGetJoystickHats__ and are in the order _up_, _right_, _down_ and
+ * _left_. To disable these extra buttons, set the @ref
+ * GLFW_JOYSTICK_HAT_BUTTONS init hint before initialization.
+ *
+ * If the specified joystick is not present this function will return `NULL`
+ * but will not generate an error. This can be used instead of first calling
+ * @ref glfwJoystickPresent.
+ *
+ * @param[in] jid The [joystick](@ref joysticks) to query.
+ * @param[out] count Where to store the number of button states in the returned
+ * array. This is set to zero if the joystick is not present or an error
+ * occurred.
+ * @return An array of button states, or `NULL` if the joystick is not present
+ * or an [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR.
+ *
+ * @pointer_lifetime The returned array is allocated and freed by GLFW. You
+ * should not free it yourself. It is valid until the specified joystick is
+ * disconnected or the library is terminated.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref joystick_button
+ *
+ * @since Added in version 2.2.
+ * @glfw3 Changed to return a dynamic array.
+ *
+ * @ingroup input
+ */
+GLFWAPI const unsigned char* glfwGetJoystickButtons(int jid, int* count);
+
+/*! @brief Returns the state of all hats of the specified joystick.
+ *
+ * This function returns the state of all hats of the specified joystick.
+ * Each element in the array is one of the following values:
+ *
+ * Name | Value
+ * ---- | -----
+ * `GLFW_HAT_CENTERED` | 0
+ * `GLFW_HAT_UP` | 1
+ * `GLFW_HAT_RIGHT` | 2
+ * `GLFW_HAT_DOWN` | 4
+ * `GLFW_HAT_LEFT` | 8
+ * `GLFW_HAT_RIGHT_UP` | `GLFW_HAT_RIGHT` \| `GLFW_HAT_UP`
+ * `GLFW_HAT_RIGHT_DOWN` | `GLFW_HAT_RIGHT` \| `GLFW_HAT_DOWN`
+ * `GLFW_HAT_LEFT_UP` | `GLFW_HAT_LEFT` \| `GLFW_HAT_UP`
+ * `GLFW_HAT_LEFT_DOWN` | `GLFW_HAT_LEFT` \| `GLFW_HAT_DOWN`
+ *
+ * The diagonal directions are bitwise combinations of the primary (up, right,
+ * down and left) directions and you can test for these individually by ANDing
+ * it with the corresponding direction.
+ *
+ * @code
+ * if (hats[2] & GLFW_HAT_RIGHT)
+ * {
+ * // State of hat 2 could be right-up, right or right-down
+ * }
+ * @endcode
+ *
+ * If the specified joystick is not present this function will return `NULL`
+ * but will not generate an error. This can be used instead of first calling
+ * @ref glfwJoystickPresent.
+ *
+ * @param[in] jid The [joystick](@ref joysticks) to query.
+ * @param[out] count Where to store the number of hat states in the returned
+ * array. This is set to zero if the joystick is not present or an error
+ * occurred.
+ * @return An array of hat states, or `NULL` if the joystick is not present
+ * or an [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR.
+ *
+ * @pointer_lifetime The returned array is allocated and freed by GLFW. You
+ * should not free it yourself. It is valid until the specified joystick is
+ * disconnected, this function is called again for that joystick or the library
+ * is terminated.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref joystick_hat
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup input
+ */
+GLFWAPI const unsigned char* glfwGetJoystickHats(int jid, int* count);
+
+/*! @brief Returns the name of the specified joystick.
+ *
+ * This function returns the name, encoded as UTF-8, of the specified joystick.
+ * The returned string is allocated and freed by GLFW. You should not free it
+ * yourself.
+ *
+ * If the specified joystick is not present this function will return `NULL`
+ * but will not generate an error. This can be used instead of first calling
+ * @ref glfwJoystickPresent.
+ *
+ * @param[in] jid The [joystick](@ref joysticks) to query.
+ * @return The UTF-8 encoded name of the joystick, or `NULL` if the joystick
+ * is not present or an [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR.
+ *
+ * @pointer_lifetime The returned string is allocated and freed by GLFW. You
+ * should not free it yourself. It is valid until the specified joystick is
+ * disconnected or the library is terminated.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref joystick_name
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup input
+ */
+GLFWAPI const char* glfwGetJoystickName(int jid);
+
+/*! @brief Returns the SDL compatible GUID of the specified joystick.
+ *
+ * This function returns the SDL compatible GUID, as a UTF-8 encoded
+ * hexadecimal string, of the specified joystick. The returned string is
+ * allocated and freed by GLFW. You should not free it yourself.
+ *
+ * The GUID is what connects a joystick to a gamepad mapping. A connected
+ * joystick will always have a GUID even if there is no gamepad mapping
+ * assigned to it.
+ *
+ * If the specified joystick is not present this function will return `NULL`
+ * but will not generate an error. This can be used instead of first calling
+ * @ref glfwJoystickPresent.
+ *
+ * The GUID uses the format introduced in SDL 2.0.5. This GUID tries to
+ * uniquely identify the make and model of a joystick but does not identify
+ * a specific unit, e.g. all wired Xbox 360 controllers will have the same
+ * GUID on that platform. The GUID for a unit may vary between platforms
+ * depending on what hardware information the platform specific APIs provide.
+ *
+ * @param[in] jid The [joystick](@ref joysticks) to query.
+ * @return The UTF-8 encoded GUID of the joystick, or `NULL` if the joystick
+ * is not present or an [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR.
+ *
+ * @pointer_lifetime The returned string is allocated and freed by GLFW. You
+ * should not free it yourself. It is valid until the specified joystick is
+ * disconnected or the library is terminated.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref gamepad
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup input
+ */
+GLFWAPI const char* glfwGetJoystickGUID(int jid);
+
+/*! @brief Sets the user pointer of the specified joystick.
+ *
+ * This function sets the user-defined pointer of the specified joystick. The
+ * current value is retained until the joystick is disconnected. The initial
+ * value is `NULL`.
+ *
+ * This function may be called from the joystick callback, even for a joystick
+ * that is being disconnected.
+ *
+ * @param[in] jid The joystick whose pointer to set.
+ * @param[in] pointer The new value.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @sa @ref joystick_userptr
+ * @sa @ref glfwGetJoystickUserPointer
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup input
+ */
+GLFWAPI void glfwSetJoystickUserPointer(int jid, void* pointer);
+
+/*! @brief Returns the user pointer of the specified joystick.
+ *
+ * This function returns the current value of the user-defined pointer of the
+ * specified joystick. The initial value is `NULL`.
+ *
+ * This function may be called from the joystick callback, even for a joystick
+ * that is being disconnected.
+ *
+ * @param[in] jid The joystick whose pointer to return.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @sa @ref joystick_userptr
+ * @sa @ref glfwSetJoystickUserPointer
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup input
+ */
+GLFWAPI void* glfwGetJoystickUserPointer(int jid);
+
+/*! @brief Returns whether the specified joystick has a gamepad mapping.
+ *
+ * This function returns whether the specified joystick is both present and has
+ * a gamepad mapping.
+ *
+ * If the specified joystick is present but does not have a gamepad mapping
+ * this function will return `GLFW_FALSE` but will not generate an error. Call
+ * @ref glfwJoystickPresent to check if a joystick is present regardless of
+ * whether it has a mapping.
+ *
+ * @param[in] jid The [joystick](@ref joysticks) to query.
+ * @return `GLFW_TRUE` if a joystick is both present and has a gamepad mapping,
+ * or `GLFW_FALSE` otherwise.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_INVALID_ENUM.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref gamepad
+ * @sa @ref glfwGetGamepadState
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup input
+ */
+GLFWAPI int glfwJoystickIsGamepad(int jid);
+
+/*! @brief Sets the joystick configuration callback.
+ *
+ * This function sets the joystick configuration callback, or removes the
+ * currently set callback. This is called when a joystick is connected to or
+ * disconnected from the system.
+ *
+ * For joystick connection and disconnection events to be delivered on all
+ * platforms, you need to call one of the [event processing](@ref events)
+ * functions. Joystick disconnection may also be detected and the callback
+ * called by joystick functions. The function will then return whatever it
+ * returns if the joystick is not present.
+ *
+ * @param[in] callback The new callback, or `NULL` to remove the currently set
+ * callback.
+ * @return The previously set callback, or `NULL` if no callback was set or the
+ * library had not been [initialized](@ref intro_init).
+ *
+ * @callback_signature
+ * @code
+ * void function_name(int jid, int event)
+ * @endcode
+ * For more information about the callback parameters, see the
+ * [function pointer type](@ref GLFWjoystickfun).
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref joystick_event
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup input
+ */
+GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun callback);
+
+/*! @brief Adds the specified SDL_GameControllerDB gamepad mappings.
+ *
+ * This function parses the specified ASCII encoded string and updates the
+ * internal list with any gamepad mappings it finds. This string may
+ * contain either a single gamepad mapping or many mappings separated by
+ * newlines. The parser supports the full format of the `gamecontrollerdb.txt`
+ * source file including empty lines and comments.
+ *
+ * See @ref gamepad_mapping for a description of the format.
+ *
+ * If there is already a gamepad mapping for a given GUID in the internal list,
+ * it will be replaced by the one passed to this function. If the library is
+ * terminated and re-initialized the internal list will revert to the built-in
+ * default.
+ *
+ * @param[in] string The string containing the gamepad mappings.
+ * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_INVALID_VALUE.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref gamepad
+ * @sa @ref glfwJoystickIsGamepad
+ * @sa @ref glfwGetGamepadName
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup input
+ */
+GLFWAPI int glfwUpdateGamepadMappings(const char* string);
+
+/*! @brief Returns the human-readable gamepad name for the specified joystick.
+ *
+ * This function returns the human-readable name of the gamepad from the
+ * gamepad mapping assigned to the specified joystick.
+ *
+ * If the specified joystick is not present or does not have a gamepad mapping
+ * this function will return `NULL` but will not generate an error. Call
+ * @ref glfwJoystickPresent to check whether it is present regardless of
+ * whether it has a mapping.
+ *
+ * @param[in] jid The [joystick](@ref joysticks) to query.
+ * @return The UTF-8 encoded name of the gamepad, or `NULL` if the
+ * joystick is not present, does not have a mapping or an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref GLFW_INVALID_ENUM.
+ *
+ * @pointer_lifetime The returned string is allocated and freed by GLFW. You
+ * should not free it yourself. It is valid until the specified joystick is
+ * disconnected, the gamepad mappings are updated or the library is terminated.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref gamepad
+ * @sa @ref glfwJoystickIsGamepad
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup input
+ */
+GLFWAPI const char* glfwGetGamepadName(int jid);
+
+/*! @brief Retrieves the state of the specified joystick remapped as a gamepad.
+ *
+ * This function retrieves the state of the specified joystick remapped to
+ * an Xbox-like gamepad.
+ *
+ * If the specified joystick is not present or does not have a gamepad mapping
+ * this function will return `GLFW_FALSE` but will not generate an error. Call
+ * @ref glfwJoystickPresent to check whether it is present regardless of
+ * whether it has a mapping.
+ *
+ * The Guide button may not be available for input as it is often hooked by the
+ * system or the Steam client.
+ *
+ * Not all devices have all the buttons or axes provided by @ref
+ * GLFWgamepadstate. Unavailable buttons and axes will always report
+ * `GLFW_RELEASE` and 0.0 respectively.
+ *
+ * @param[in] jid The [joystick](@ref joysticks) to query.
+ * @param[out] state The gamepad input state of the joystick.
+ * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if no joystick is
+ * connected, it has no gamepad mapping or an [error](@ref error_handling)
+ * occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_INVALID_ENUM.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref gamepad
+ * @sa @ref glfwUpdateGamepadMappings
+ * @sa @ref glfwJoystickIsGamepad
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup input
+ */
+GLFWAPI int glfwGetGamepadState(int jid, GLFWgamepadstate* state);
+
+/*! @brief Sets the clipboard to the specified string.
+ *
+ * This function sets the system clipboard to the specified, UTF-8 encoded
+ * string.
+ *
+ * @param[in] window Deprecated. Any valid window or `NULL`.
+ * @param[in] string A UTF-8 encoded string.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @remark @win32 The clipboard on Windows has a single global lock for reading and
+ * writing. GLFW tries to acquire it a few times, which is almost always enough. If it
+ * cannot acquire the lock then this function emits @ref GLFW_PLATFORM_ERROR and returns.
+ * It is safe to try this multiple times.
+ *
+ * @pointer_lifetime The specified string is copied before this function
+ * returns.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref clipboard
+ * @sa @ref glfwGetClipboardString
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup input
+ */
+GLFWAPI void glfwSetClipboardString(GLFWwindow* window, const char* string);
+
+/*! @brief Returns the contents of the clipboard as a string.
+ *
+ * This function returns the contents of the system clipboard, if it contains
+ * or is convertible to a UTF-8 encoded string. If the clipboard is empty or
+ * if its contents cannot be converted, `NULL` is returned and a @ref
+ * GLFW_FORMAT_UNAVAILABLE error is generated.
+ *
+ * @param[in] window Deprecated. Any valid window or `NULL`.
+ * @return The contents of the clipboard as a UTF-8 encoded string, or `NULL`
+ * if an [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_FORMAT_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR.
+ *
+ * @remark @win32 The clipboard on Windows has a single global lock for reading and
+ * writing. GLFW tries to acquire it a few times, which is almost always enough. If it
+ * cannot acquire the lock then this function emits @ref GLFW_PLATFORM_ERROR and returns.
+ * It is safe to try this multiple times.
+ *
+ * @pointer_lifetime The returned string is allocated and freed by GLFW. You
+ * should not free it yourself. It is valid until the next call to @ref
+ * glfwGetClipboardString or @ref glfwSetClipboardString, or until the library
+ * is terminated.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref clipboard
+ * @sa @ref glfwSetClipboardString
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup input
+ */
+GLFWAPI const char* glfwGetClipboardString(GLFWwindow* window);
+
+/*! @brief Returns the GLFW time.
+ *
+ * This function returns the current GLFW time, in seconds. Unless the time
+ * has been set using @ref glfwSetTime it measures time elapsed since GLFW was
+ * initialized.
+ *
+ * This function and @ref glfwSetTime are helper functions on top of @ref
+ * glfwGetTimerFrequency and @ref glfwGetTimerValue.
+ *
+ * The resolution of the timer is system dependent, but is usually on the order
+ * of a few micro- or nanoseconds. It uses the highest-resolution monotonic
+ * time source on each operating system.
+ *
+ * @return The current time, in seconds, or zero if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function may be called from any thread. Reading and
+ * writing of the internal base time is not atomic, so it needs to be
+ * externally synchronized with calls to @ref glfwSetTime.
+ *
+ * @sa @ref time
+ *
+ * @since Added in version 1.0.
+ *
+ * @ingroup input
+ */
+GLFWAPI double glfwGetTime(void);
+
+/*! @brief Sets the GLFW time.
+ *
+ * This function sets the current GLFW time, in seconds. The value must be
+ * a positive finite number less than or equal to 18446744073.0, which is
+ * approximately 584.5 years.
+ *
+ * This function and @ref glfwGetTime are helper functions on top of @ref
+ * glfwGetTimerFrequency and @ref glfwGetTimerValue.
+ *
+ * @param[in] time The new value, in seconds.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_INVALID_VALUE.
+ *
+ * @remark The upper limit of GLFW time is calculated as
+ * floor((264 - 1) / 109) and is due to implementations
+ * storing nanoseconds in 64 bits. The limit may be increased in the future.
+ *
+ * @thread_safety This function may be called from any thread. Reading and
+ * writing of the internal base time is not atomic, so it needs to be
+ * externally synchronized with calls to @ref glfwGetTime.
+ *
+ * @sa @ref time
+ *
+ * @since Added in version 2.2.
+ *
+ * @ingroup input
+ */
+GLFWAPI void glfwSetTime(double time);
+
+/*! @brief Returns the current value of the raw timer.
+ *
+ * This function returns the current value of the raw timer, measured in
+ * 1 / frequency seconds. To get the frequency, call @ref
+ * glfwGetTimerFrequency.
+ *
+ * @return The value of the timer, or zero if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function may be called from any thread.
+ *
+ * @sa @ref time
+ * @sa @ref glfwGetTimerFrequency
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup input
+ */
+GLFWAPI uint64_t glfwGetTimerValue(void);
+
+/*! @brief Returns the frequency, in Hz, of the raw timer.
+ *
+ * This function returns the frequency, in Hz, of the raw timer.
+ *
+ * @return The frequency of the timer, in Hz, or zero if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function may be called from any thread.
+ *
+ * @sa @ref time
+ * @sa @ref glfwGetTimerValue
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup input
+ */
+GLFWAPI uint64_t glfwGetTimerFrequency(void);
+
+/*! @brief Makes the context of the specified window current for the calling
+ * thread.
+ *
+ * This function makes the OpenGL or OpenGL ES context of the specified window
+ * current on the calling thread. It can also detach the current context from
+ * the calling thread without making a new one current by passing in `NULL`.
+ *
+ * A context must only be made current on a single thread at a time and each
+ * thread can have only a single current context at a time. Making a context
+ * current detaches any previously current context on the calling thread.
+ *
+ * When moving a context between threads, you must detach it (make it
+ * non-current) on the old thread before making it current on the new one.
+ *
+ * By default, making a context non-current implicitly forces a pipeline flush.
+ * On machines that support `GL_KHR_context_flush_control`, you can control
+ * whether a context performs this flush by setting the
+ * [GLFW_CONTEXT_RELEASE_BEHAVIOR](@ref GLFW_CONTEXT_RELEASE_BEHAVIOR_hint)
+ * hint.
+ *
+ * The specified window must have an OpenGL or OpenGL ES context. Specifying
+ * a window without a context will generate a @ref GLFW_NO_WINDOW_CONTEXT
+ * error.
+ *
+ * @param[in] window The window whose context to make current, or `NULL` to
+ * detach the current context.
+ *
+ * @remarks If the previously current context was created via a different
+ * context creation API than the one passed to this function, GLFW will still
+ * detach the previous one from its API before making the new one current.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function may be called from any thread.
+ *
+ * @sa @ref context_current
+ * @sa @ref glfwGetCurrentContext
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup context
+ */
+GLFWAPI void glfwMakeContextCurrent(GLFWwindow* window);
+
+/*! @brief Returns the window whose context is current on the calling thread.
+ *
+ * This function returns the window whose OpenGL or OpenGL ES context is
+ * current on the calling thread.
+ *
+ * @return The window whose context is current, or `NULL` if no window's
+ * context is current.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function may be called from any thread.
+ *
+ * @sa @ref context_current
+ * @sa @ref glfwMakeContextCurrent
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup context
+ */
+GLFWAPI GLFWwindow* glfwGetCurrentContext(void);
+
+/*! @brief Swaps the front and back buffers of the specified window.
+ *
+ * This function swaps the front and back buffers of the specified window when
+ * rendering with OpenGL or OpenGL ES. If the swap interval is greater than
+ * zero, the GPU driver waits the specified number of screen updates before
+ * swapping the buffers.
+ *
+ * The specified window must have an OpenGL or OpenGL ES context. Specifying
+ * a window without a context will generate a @ref GLFW_NO_WINDOW_CONTEXT
+ * error.
+ *
+ * This function does not apply to Vulkan. If you are rendering with Vulkan,
+ * see `vkQueuePresentKHR` instead.
+ *
+ * @param[in] window The window whose buffers to swap.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR.
+ *
+ * @remark __EGL:__ The context of the specified window must be current on the
+ * calling thread.
+ *
+ * @thread_safety This function may be called from any thread.
+ *
+ * @sa @ref buffer_swap
+ * @sa @ref glfwSwapInterval
+ *
+ * @since Added in version 1.0.
+ * @glfw3 Added window handle parameter.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwSwapBuffers(GLFWwindow* window);
+
+/*! @brief Sets the swap interval for the current context.
+ *
+ * This function sets the swap interval for the current OpenGL or OpenGL ES
+ * context, i.e. the number of screen updates to wait from the time @ref
+ * glfwSwapBuffers was called before swapping the buffers and returning. This
+ * is sometimes called _vertical synchronization_, _vertical retrace
+ * synchronization_ or just _vsync_.
+ *
+ * A context that supports either of the `WGL_EXT_swap_control_tear` and
+ * `GLX_EXT_swap_control_tear` extensions also accepts _negative_ swap
+ * intervals, which allows the driver to swap immediately even if a frame
+ * arrives a little bit late. You can check for these extensions with @ref
+ * glfwExtensionSupported.
+ *
+ * A context must be current on the calling thread. Calling this function
+ * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error.
+ *
+ * This function does not apply to Vulkan. If you are rendering with Vulkan,
+ * see the present mode of your swapchain instead.
+ *
+ * @param[in] interval The minimum number of screen updates to wait for
+ * until the buffers are swapped by @ref glfwSwapBuffers.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_NO_CURRENT_CONTEXT and @ref GLFW_PLATFORM_ERROR.
+ *
+ * @remark This function is not called during context creation, leaving the
+ * swap interval set to whatever is the default for that API. This is done
+ * because some swap interval extensions used by GLFW do not allow the swap
+ * interval to be reset to zero once it has been set to a non-zero value.
+ *
+ * @remark Some GPU drivers do not honor the requested swap interval, either
+ * because of a user setting that overrides the application's request or due to
+ * bugs in the driver.
+ *
+ * @thread_safety This function may be called from any thread.
+ *
+ * @sa @ref buffer_swap
+ * @sa @ref glfwSwapBuffers
+ *
+ * @since Added in version 1.0.
+ *
+ * @ingroup context
+ */
+GLFWAPI void glfwSwapInterval(int interval);
+
+/*! @brief Returns whether the specified extension is available.
+ *
+ * This function returns whether the specified
+ * [API extension](@ref context_glext) is supported by the current OpenGL or
+ * OpenGL ES context. It searches both for client API extension and context
+ * creation API extensions.
+ *
+ * A context must be current on the calling thread. Calling this function
+ * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error.
+ *
+ * As this functions retrieves and searches one or more extension strings each
+ * call, it is recommended that you cache its results if it is going to be used
+ * frequently. The extension strings will not change during the lifetime of
+ * a context, so there is no danger in doing this.
+ *
+ * This function does not apply to Vulkan. If you are using Vulkan, see @ref
+ * glfwGetRequiredInstanceExtensions, `vkEnumerateInstanceExtensionProperties`
+ * and `vkEnumerateDeviceExtensionProperties` instead.
+ *
+ * @param[in] extension The ASCII encoded name of the extension.
+ * @return `GLFW_TRUE` if the extension is available, or `GLFW_FALSE`
+ * otherwise.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_NO_CURRENT_CONTEXT, @ref GLFW_INVALID_VALUE and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function may be called from any thread.
+ *
+ * @sa @ref context_glext
+ * @sa @ref glfwGetProcAddress
+ *
+ * @since Added in version 1.0.
+ *
+ * @ingroup context
+ */
+GLFWAPI int glfwExtensionSupported(const char* extension);
+
+/*! @brief Returns the address of the specified function for the current
+ * context.
+ *
+ * This function returns the address of the specified OpenGL or OpenGL ES
+ * [core or extension function](@ref context_glext), if it is supported
+ * by the current context.
+ *
+ * A context must be current on the calling thread. Calling this function
+ * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error.
+ *
+ * This function does not apply to Vulkan. If you are rendering with Vulkan,
+ * see @ref glfwGetInstanceProcAddress, `vkGetInstanceProcAddr` and
+ * `vkGetDeviceProcAddr` instead.
+ *
+ * @param[in] procname The ASCII encoded name of the function.
+ * @return The address of the function, or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_NO_CURRENT_CONTEXT and @ref GLFW_PLATFORM_ERROR.
+ *
+ * @remark The address of a given function is not guaranteed to be the same
+ * between contexts.
+ *
+ * @remark This function may return a non-`NULL` address despite the
+ * associated version or extension not being available. Always check the
+ * context version or extension string first.
+ *
+ * @pointer_lifetime The returned function pointer is valid until the context
+ * is destroyed or the library is terminated.
+ *
+ * @thread_safety This function may be called from any thread.
+ *
+ * @sa @ref context_glext
+ * @sa @ref glfwExtensionSupported
+ *
+ * @since Added in version 1.0.
+ *
+ * @ingroup context
+ */
+GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname);
+
+/*! @brief Returns whether the Vulkan loader and an ICD have been found.
+ *
+ * This function returns whether the Vulkan loader and any minimally functional
+ * ICD have been found.
+ *
+ * The availability of a Vulkan loader and even an ICD does not by itself guarantee that
+ * surface creation or even instance creation is possible. Call @ref
+ * glfwGetRequiredInstanceExtensions to check whether the extensions necessary for Vulkan
+ * surface creation are available and @ref glfwGetPhysicalDevicePresentationSupport to
+ * check whether a queue family of a physical device supports image presentation.
+ *
+ * @return `GLFW_TRUE` if Vulkan is minimally available, or `GLFW_FALSE`
+ * otherwise.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function may be called from any thread.
+ *
+ * @sa @ref vulkan_support
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup vulkan
+ */
+GLFWAPI int glfwVulkanSupported(void);
+
+/*! @brief Returns the Vulkan instance extensions required by GLFW.
+ *
+ * This function returns an array of names of Vulkan instance extensions required
+ * by GLFW for creating Vulkan surfaces for GLFW windows. If successful, the
+ * list will always contain `VK_KHR_surface`, so if you don't require any
+ * additional extensions you can pass this list directly to the
+ * `VkInstanceCreateInfo` struct.
+ *
+ * If Vulkan is not available on the machine, this function returns `NULL` and
+ * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported
+ * to check whether Vulkan is at least minimally available.
+ *
+ * If Vulkan is available but no set of extensions allowing window surface
+ * creation was found, this function returns `NULL`. You may still use Vulkan
+ * for off-screen rendering and compute work.
+ *
+ * @param[out] count Where to store the number of extensions in the returned
+ * array. This is set to zero if an error occurred.
+ * @return An array of ASCII encoded extension names, or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_API_UNAVAILABLE.
+ *
+ * @remark Additional extensions may be required by future versions of GLFW.
+ * You should check if any extensions you wish to enable are already in the
+ * returned array, as it is an error to specify an extension more than once in
+ * the `VkInstanceCreateInfo` struct.
+ *
+ * @pointer_lifetime The returned array is allocated and freed by GLFW. You
+ * should not free it yourself. It is guaranteed to be valid only until the
+ * library is terminated.
+ *
+ * @thread_safety This function may be called from any thread.
+ *
+ * @sa @ref vulkan_ext
+ * @sa @ref glfwCreateWindowSurface
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup vulkan
+ */
+GLFWAPI const char** glfwGetRequiredInstanceExtensions(uint32_t* count);
+
+#if defined(VK_VERSION_1_0)
+
+/*! @brief Returns the address of the specified Vulkan instance function.
+ *
+ * This function returns the address of the specified Vulkan core or extension
+ * function for the specified instance. If instance is set to `NULL` it can
+ * return any function exported from the Vulkan loader, including at least the
+ * following functions:
+ *
+ * - `vkEnumerateInstanceExtensionProperties`
+ * - `vkEnumerateInstanceLayerProperties`
+ * - `vkCreateInstance`
+ * - `vkGetInstanceProcAddr`
+ *
+ * If Vulkan is not available on the machine, this function returns `NULL` and
+ * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported
+ * to check whether Vulkan is at least minimally available.
+ *
+ * This function is equivalent to calling `vkGetInstanceProcAddr` with
+ * a platform-specific query of the Vulkan loader as a fallback.
+ *
+ * @param[in] instance The Vulkan instance to query, or `NULL` to retrieve
+ * functions related to instance creation.
+ * @param[in] procname The ASCII encoded name of the function.
+ * @return The address of the function, or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_API_UNAVAILABLE.
+ *
+ * @pointer_lifetime The returned function pointer is valid until the library
+ * is terminated.
+ *
+ * @thread_safety This function may be called from any thread.
+ *
+ * @sa @ref vulkan_proc
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup vulkan
+ */
+GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance, const char* procname);
+
+/*! @brief Returns whether the specified queue family can present images.
+ *
+ * This function returns whether the specified queue family of the specified
+ * physical device supports presentation to the platform GLFW was built for.
+ *
+ * If Vulkan or the required window surface creation instance extensions are
+ * not available on the machine, or if the specified instance was not created
+ * with the required extensions, this function returns `GLFW_FALSE` and
+ * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported
+ * to check whether Vulkan is at least minimally available and @ref
+ * glfwGetRequiredInstanceExtensions to check what instance extensions are
+ * required.
+ *
+ * @param[in] instance The instance that the physical device belongs to.
+ * @param[in] device The physical device that the queue family belongs to.
+ * @param[in] queuefamily The index of the queue family to query.
+ * @return `GLFW_TRUE` if the queue family supports presentation, or
+ * `GLFW_FALSE` otherwise.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR.
+ *
+ * @remark @macos This function currently always returns `GLFW_TRUE`, as the
+ * `VK_MVK_macos_surface` and `VK_EXT_metal_surface` extensions do not provide
+ * a `vkGetPhysicalDevice*PresentationSupport` type function.
+ *
+ * @thread_safety This function may be called from any thread. For
+ * synchronization details of Vulkan objects, see the Vulkan specification.
+ *
+ * @sa @ref vulkan_present
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup vulkan
+ */
+GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily);
+
+/*! @brief Creates a Vulkan surface for the specified window.
+ *
+ * This function creates a Vulkan surface for the specified window.
+ *
+ * If the Vulkan loader or at least one minimally functional ICD were not found,
+ * this function returns `VK_ERROR_INITIALIZATION_FAILED` and generates a @ref
+ * GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported to check whether
+ * Vulkan is at least minimally available.
+ *
+ * If the required window surface creation instance extensions are not
+ * available or if the specified instance was not created with these extensions
+ * enabled, this function returns `VK_ERROR_EXTENSION_NOT_PRESENT` and
+ * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref
+ * glfwGetRequiredInstanceExtensions to check what instance extensions are
+ * required.
+ *
+ * The window surface cannot be shared with another API so the window must
+ * have been created with the [client api hint](@ref GLFW_CLIENT_API_attrib)
+ * set to `GLFW_NO_API` otherwise it generates a @ref GLFW_INVALID_VALUE error
+ * and returns `VK_ERROR_NATIVE_WINDOW_IN_USE_KHR`.
+ *
+ * The window surface must be destroyed before the specified Vulkan instance.
+ * It is the responsibility of the caller to destroy the window surface. GLFW
+ * does not destroy it for you. Call `vkDestroySurfaceKHR` to destroy the
+ * surface.
+ *
+ * @param[in] instance The Vulkan instance to create the surface in.
+ * @param[in] window The window to create the surface for.
+ * @param[in] allocator The allocator to use, or `NULL` to use the default
+ * allocator.
+ * @param[out] surface Where to store the handle of the surface. This is set
+ * to `VK_NULL_HANDLE` if an error occurred.
+ * @return `VK_SUCCESS` if successful, or a Vulkan error code if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_API_UNAVAILABLE, @ref GLFW_PLATFORM_ERROR and @ref GLFW_INVALID_VALUE
+ *
+ * @remark If an error occurs before the creation call is made, GLFW returns
+ * the Vulkan error code most appropriate for the error. Appropriate use of
+ * @ref glfwVulkanSupported and @ref glfwGetRequiredInstanceExtensions should
+ * eliminate almost all occurrences of these errors.
+ *
+ * @remark @macos GLFW prefers the `VK_EXT_metal_surface` extension, with the
+ * `VK_MVK_macos_surface` extension as a fallback. The name of the selected
+ * extension, if any, is included in the array returned by @ref
+ * glfwGetRequiredInstanceExtensions.
+ *
+ * @remark @macos This function creates and sets a `CAMetalLayer` instance for
+ * the window content view, which is required for MoltenVK to function.
+ *
+ * @remark @x11 By default GLFW prefers the `VK_KHR_xcb_surface` extension,
+ * with the `VK_KHR_xlib_surface` extension as a fallback. You can make
+ * `VK_KHR_xlib_surface` the preferred extension by setting the
+ * [GLFW_X11_XCB_VULKAN_SURFACE](@ref GLFW_X11_XCB_VULKAN_SURFACE_hint) init
+ * hint. The name of the selected extension, if any, is included in the array
+ * returned by @ref glfwGetRequiredInstanceExtensions.
+ *
+ * @thread_safety This function may be called from any thread. For
+ * synchronization details of Vulkan objects, see the Vulkan specification.
+ *
+ * @sa @ref vulkan_surface
+ * @sa @ref glfwGetRequiredInstanceExtensions
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup vulkan
+ */
+GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance, GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface);
+
+#endif /*VK_VERSION_1_0*/
+
+
+/*************************************************************************
+ * Global definition cleanup
+ *************************************************************************/
+
+/* ------------------- BEGIN SYSTEM/COMPILER SPECIFIC -------------------- */
+
+#ifdef GLFW_WINGDIAPI_DEFINED
+ #undef WINGDIAPI
+ #undef GLFW_WINGDIAPI_DEFINED
+#endif
+
+#ifdef GLFW_CALLBACK_DEFINED
+ #undef CALLBACK
+ #undef GLFW_CALLBACK_DEFINED
+#endif
+
+/* Some OpenGL related headers need GLAPIENTRY, but it is unconditionally
+ * defined by some gl.h variants (OpenBSD) so define it after if needed.
+ */
+#ifndef GLAPIENTRY
+ #define GLAPIENTRY APIENTRY
+ #define GLFW_GLAPIENTRY_DEFINED
+#endif
+
+/* -------------------- END SYSTEM/COMPILER SPECIFIC --------------------- */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _glfw3_h_ */
+
diff --git a/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/glfw/include/GLFW/glfw3native.h b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/glfw/include/GLFW/glfw3native.h
new file mode 100644
index 0000000..92f0d32
--- /dev/null
+++ b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/glfw/include/GLFW/glfw3native.h
@@ -0,0 +1,663 @@
+/*************************************************************************
+ * GLFW 3.4 - www.glfw.org
+ * A library for OpenGL, window and input
+ *------------------------------------------------------------------------
+ * Copyright (c) 2002-2006 Marcus Geelnard
+ * Copyright (c) 2006-2018 Camilla Löwy
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would
+ * be appreciated but is not required.
+ *
+ * 2. Altered source versions must be plainly marked as such, and must not
+ * be misrepresented as being the original software.
+ *
+ * 3. This notice may not be removed or altered from any source
+ * distribution.
+ *
+ *************************************************************************/
+
+#ifndef _glfw3_native_h_
+#define _glfw3_native_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*************************************************************************
+ * Doxygen documentation
+ *************************************************************************/
+
+/*! @file glfw3native.h
+ * @brief The header of the native access functions.
+ *
+ * This is the header file of the native access functions. See @ref native for
+ * more information.
+ */
+/*! @defgroup native Native access
+ * @brief Functions related to accessing native handles.
+ *
+ * **By using the native access functions you assert that you know what you're
+ * doing and how to fix problems caused by using them. If you don't, you
+ * shouldn't be using them.**
+ *
+ * Before the inclusion of @ref glfw3native.h, you may define zero or more
+ * window system API macro and zero or more context creation API macros.
+ *
+ * The chosen backends must match those the library was compiled for. Failure
+ * to do this will cause a link-time error.
+ *
+ * The available window API macros are:
+ * * `GLFW_EXPOSE_NATIVE_WIN32`
+ * * `GLFW_EXPOSE_NATIVE_COCOA`
+ * * `GLFW_EXPOSE_NATIVE_X11`
+ * * `GLFW_EXPOSE_NATIVE_WAYLAND`
+ *
+ * The available context API macros are:
+ * * `GLFW_EXPOSE_NATIVE_WGL`
+ * * `GLFW_EXPOSE_NATIVE_NSGL`
+ * * `GLFW_EXPOSE_NATIVE_GLX`
+ * * `GLFW_EXPOSE_NATIVE_EGL`
+ * * `GLFW_EXPOSE_NATIVE_OSMESA`
+ *
+ * These macros select which of the native access functions that are declared
+ * and which platform-specific headers to include. It is then up your (by
+ * definition platform-specific) code to handle which of these should be
+ * defined.
+ *
+ * If you do not want the platform-specific headers to be included, define
+ * `GLFW_NATIVE_INCLUDE_NONE` before including the @ref glfw3native.h header.
+ *
+ * @code
+ * #define GLFW_EXPOSE_NATIVE_WIN32
+ * #define GLFW_EXPOSE_NATIVE_WGL
+ * #define GLFW_NATIVE_INCLUDE_NONE
+ * #include
+ * @endcode
+ */
+
+
+/*************************************************************************
+ * System headers and types
+ *************************************************************************/
+
+#if !defined(GLFW_NATIVE_INCLUDE_NONE)
+
+ #if defined(GLFW_EXPOSE_NATIVE_WIN32) || defined(GLFW_EXPOSE_NATIVE_WGL)
+ /* This is a workaround for the fact that glfw3.h needs to export APIENTRY (for
+ * example to allow applications to correctly declare a GL_KHR_debug callback)
+ * but windows.h assumes no one will define APIENTRY before it does
+ */
+ #if defined(GLFW_APIENTRY_DEFINED)
+ #undef APIENTRY
+ #undef GLFW_APIENTRY_DEFINED
+ #endif
+ #include
+ #endif
+
+ #if defined(GLFW_EXPOSE_NATIVE_COCOA) || defined(GLFW_EXPOSE_NATIVE_NSGL)
+ #if defined(__OBJC__)
+ #import
+ #else
+ #include
+ #include
+ #endif
+ #endif
+
+ #if defined(GLFW_EXPOSE_NATIVE_X11) || defined(GLFW_EXPOSE_NATIVE_GLX)
+ #include
+ #include
+ #endif
+
+ #if defined(GLFW_EXPOSE_NATIVE_WAYLAND)
+ #include
+ #endif
+
+ #if defined(GLFW_EXPOSE_NATIVE_WGL)
+ /* WGL is declared by windows.h */
+ #endif
+ #if defined(GLFW_EXPOSE_NATIVE_NSGL)
+ /* NSGL is declared by Cocoa.h */
+ #endif
+ #if defined(GLFW_EXPOSE_NATIVE_GLX)
+ /* This is a workaround for the fact that glfw3.h defines GLAPIENTRY because by
+ * default it also acts as an OpenGL header
+ * However, glx.h will include gl.h, which will define it unconditionally
+ */
+ #if defined(GLFW_GLAPIENTRY_DEFINED)
+ #undef GLAPIENTRY
+ #undef GLFW_GLAPIENTRY_DEFINED
+ #endif
+ #include
+ #endif
+ #if defined(GLFW_EXPOSE_NATIVE_EGL)
+ #include
+ #endif
+ #if defined(GLFW_EXPOSE_NATIVE_OSMESA)
+ /* This is a workaround for the fact that glfw3.h defines GLAPIENTRY because by
+ * default it also acts as an OpenGL header
+ * However, osmesa.h will include gl.h, which will define it unconditionally
+ */
+ #if defined(GLFW_GLAPIENTRY_DEFINED)
+ #undef GLAPIENTRY
+ #undef GLFW_GLAPIENTRY_DEFINED
+ #endif
+ #include
+ #endif
+
+#endif /*GLFW_NATIVE_INCLUDE_NONE*/
+
+
+/*************************************************************************
+ * Functions
+ *************************************************************************/
+
+#if defined(GLFW_EXPOSE_NATIVE_WIN32)
+/*! @brief Returns the adapter device name of the specified monitor.
+ *
+ * @return The UTF-8 encoded adapter device name (for example `\\.\DISPLAY1`)
+ * of the specified monitor, or `NULL` if an [error](@ref error_handling)
+ * occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_UNAVAILABLE.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.1.
+ *
+ * @ingroup native
+ */
+GLFWAPI const char* glfwGetWin32Adapter(GLFWmonitor* monitor);
+
+/*! @brief Returns the display device name of the specified monitor.
+ *
+ * @return The UTF-8 encoded display device name (for example
+ * `\\.\DISPLAY1\Monitor0`) of the specified monitor, or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_UNAVAILABLE.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.1.
+ *
+ * @ingroup native
+ */
+GLFWAPI const char* glfwGetWin32Monitor(GLFWmonitor* monitor);
+
+/*! @brief Returns the `HWND` of the specified window.
+ *
+ * @return The `HWND` of the specified window, or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_UNAVAILABLE.
+ *
+ * @remark The `HDC` associated with the window can be queried with the
+ * [GetDC](https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdc)
+ * function.
+ * @code
+ * HDC dc = GetDC(glfwGetWin32Window(window));
+ * @endcode
+ * This DC is private and does not need to be released.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup native
+ */
+GLFWAPI HWND glfwGetWin32Window(GLFWwindow* window);
+#endif
+
+#if defined(GLFW_EXPOSE_NATIVE_WGL)
+/*! @brief Returns the `HGLRC` of the specified window.
+ *
+ * @return The `HGLRC` of the specified window, or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_PLATFORM_UNAVAILABLE and @ref GLFW_NO_WINDOW_CONTEXT.
+ *
+ * @remark The `HDC` associated with the window can be queried with the
+ * [GetDC](https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdc)
+ * function.
+ * @code
+ * HDC dc = GetDC(glfwGetWin32Window(window));
+ * @endcode
+ * This DC is private and does not need to be released.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup native
+ */
+GLFWAPI HGLRC glfwGetWGLContext(GLFWwindow* window);
+#endif
+
+#if defined(GLFW_EXPOSE_NATIVE_COCOA)
+/*! @brief Returns the `CGDirectDisplayID` of the specified monitor.
+ *
+ * @return The `CGDirectDisplayID` of the specified monitor, or
+ * `kCGNullDirectDisplay` if an [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_UNAVAILABLE.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.1.
+ *
+ * @ingroup native
+ */
+GLFWAPI CGDirectDisplayID glfwGetCocoaMonitor(GLFWmonitor* monitor);
+
+/*! @brief Returns the `NSWindow` of the specified window.
+ *
+ * @return The `NSWindow` of the specified window, or `nil` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_UNAVAILABLE.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup native
+ */
+GLFWAPI id glfwGetCocoaWindow(GLFWwindow* window);
+
+/*! @brief Returns the `NSView` of the specified window.
+ *
+ * @return The `NSView` of the specified window, or `nil` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_UNAVAILABLE.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.4.
+ *
+ * @ingroup native
+ */
+GLFWAPI id glfwGetCocoaView(GLFWwindow* window);
+#endif
+
+#if defined(GLFW_EXPOSE_NATIVE_NSGL)
+/*! @brief Returns the `NSOpenGLContext` of the specified window.
+ *
+ * @return The `NSOpenGLContext` of the specified window, or `nil` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_PLATFORM_UNAVAILABLE and @ref GLFW_NO_WINDOW_CONTEXT.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup native
+ */
+GLFWAPI id glfwGetNSGLContext(GLFWwindow* window);
+#endif
+
+#if defined(GLFW_EXPOSE_NATIVE_X11)
+/*! @brief Returns the `Display` used by GLFW.
+ *
+ * @return The `Display` used by GLFW, or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_UNAVAILABLE.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup native
+ */
+GLFWAPI Display* glfwGetX11Display(void);
+
+/*! @brief Returns the `RRCrtc` of the specified monitor.
+ *
+ * @return The `RRCrtc` of the specified monitor, or `None` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_UNAVAILABLE.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.1.
+ *
+ * @ingroup native
+ */
+GLFWAPI RRCrtc glfwGetX11Adapter(GLFWmonitor* monitor);
+
+/*! @brief Returns the `RROutput` of the specified monitor.
+ *
+ * @return The `RROutput` of the specified monitor, or `None` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_UNAVAILABLE.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.1.
+ *
+ * @ingroup native
+ */
+GLFWAPI RROutput glfwGetX11Monitor(GLFWmonitor* monitor);
+
+/*! @brief Returns the `Window` of the specified window.
+ *
+ * @return The `Window` of the specified window, or `None` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_UNAVAILABLE.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup native
+ */
+GLFWAPI Window glfwGetX11Window(GLFWwindow* window);
+
+/*! @brief Sets the current primary selection to the specified string.
+ *
+ * @param[in] string A UTF-8 encoded string.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_PLATFORM_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR.
+ *
+ * @pointer_lifetime The specified string is copied before this function
+ * returns.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref clipboard
+ * @sa glfwGetX11SelectionString
+ * @sa glfwSetClipboardString
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup native
+ */
+GLFWAPI void glfwSetX11SelectionString(const char* string);
+
+/*! @brief Returns the contents of the current primary selection as a string.
+ *
+ * If the selection is empty or if its contents cannot be converted, `NULL`
+ * is returned and a @ref GLFW_FORMAT_UNAVAILABLE error is generated.
+ *
+ * @return The contents of the selection as a UTF-8 encoded string, or `NULL`
+ * if an [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_PLATFORM_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR.
+ *
+ * @pointer_lifetime The returned string is allocated and freed by GLFW. You
+ * should not free it yourself. It is valid until the next call to @ref
+ * glfwGetX11SelectionString or @ref glfwSetX11SelectionString, or until the
+ * library is terminated.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref clipboard
+ * @sa glfwSetX11SelectionString
+ * @sa glfwGetClipboardString
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup native
+ */
+GLFWAPI const char* glfwGetX11SelectionString(void);
+#endif
+
+#if defined(GLFW_EXPOSE_NATIVE_GLX)
+/*! @brief Returns the `GLXContext` of the specified window.
+ *
+ * @return The `GLXContext` of the specified window, or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_UNAVAILABLE.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup native
+ */
+GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* window);
+
+/*! @brief Returns the `GLXWindow` of the specified window.
+ *
+ * @return The `GLXWindow` of the specified window, or `None` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_UNAVAILABLE.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup native
+ */
+GLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* window);
+#endif
+
+#if defined(GLFW_EXPOSE_NATIVE_WAYLAND)
+/*! @brief Returns the `struct wl_display*` used by GLFW.
+ *
+ * @return The `struct wl_display*` used by GLFW, or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_UNAVAILABLE.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup native
+ */
+GLFWAPI struct wl_display* glfwGetWaylandDisplay(void);
+
+/*! @brief Returns the `struct wl_output*` of the specified monitor.
+ *
+ * @return The `struct wl_output*` of the specified monitor, or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_UNAVAILABLE.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup native
+ */
+GLFWAPI struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* monitor);
+
+/*! @brief Returns the main `struct wl_surface*` of the specified window.
+ *
+ * @return The main `struct wl_surface*` of the specified window, or `NULL` if
+ * an [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_UNAVAILABLE.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup native
+ */
+GLFWAPI struct wl_surface* glfwGetWaylandWindow(GLFWwindow* window);
+#endif
+
+#if defined(GLFW_EXPOSE_NATIVE_EGL)
+/*! @brief Returns the `EGLDisplay` used by GLFW.
+ *
+ * @return The `EGLDisplay` used by GLFW, or `EGL_NO_DISPLAY` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @remark Because EGL is initialized on demand, this function will return
+ * `EGL_NO_DISPLAY` until the first context has been created via EGL.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup native
+ */
+GLFWAPI EGLDisplay glfwGetEGLDisplay(void);
+
+/*! @brief Returns the `EGLContext` of the specified window.
+ *
+ * @return The `EGLContext` of the specified window, or `EGL_NO_CONTEXT` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_NO_WINDOW_CONTEXT.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup native
+ */
+GLFWAPI EGLContext glfwGetEGLContext(GLFWwindow* window);
+
+/*! @brief Returns the `EGLSurface` of the specified window.
+ *
+ * @return The `EGLSurface` of the specified window, or `EGL_NO_SURFACE` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_NO_WINDOW_CONTEXT.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup native
+ */
+GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* window);
+#endif
+
+#if defined(GLFW_EXPOSE_NATIVE_OSMESA)
+/*! @brief Retrieves the color buffer associated with the specified window.
+ *
+ * @param[in] window The window whose color buffer to retrieve.
+ * @param[out] width Where to store the width of the color buffer, or `NULL`.
+ * @param[out] height Where to store the height of the color buffer, or `NULL`.
+ * @param[out] format Where to store the OSMesa pixel format of the color
+ * buffer, or `NULL`.
+ * @param[out] buffer Where to store the address of the color buffer, or
+ * `NULL`.
+ * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_NO_WINDOW_CONTEXT.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup native
+ */
+GLFWAPI int glfwGetOSMesaColorBuffer(GLFWwindow* window, int* width, int* height, int* format, void** buffer);
+
+/*! @brief Retrieves the depth buffer associated with the specified window.
+ *
+ * @param[in] window The window whose depth buffer to retrieve.
+ * @param[out] width Where to store the width of the depth buffer, or `NULL`.
+ * @param[out] height Where to store the height of the depth buffer, or `NULL`.
+ * @param[out] bytesPerValue Where to store the number of bytes per depth
+ * buffer element, or `NULL`.
+ * @param[out] buffer Where to store the address of the depth buffer, or
+ * `NULL`.
+ * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_NO_WINDOW_CONTEXT.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup native
+ */
+GLFWAPI int glfwGetOSMesaDepthBuffer(GLFWwindow* window, int* width, int* height, int* bytesPerValue, void** buffer);
+
+/*! @brief Returns the `OSMesaContext` of the specified window.
+ *
+ * @return The `OSMesaContext` of the specified window, or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_NO_WINDOW_CONTEXT.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup native
+ */
+GLFWAPI OSMesaContext glfwGetOSMesaContext(GLFWwindow* window);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _glfw3_native_h_ */
+
diff --git a/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/glfw/include/GLFW/vendor.go b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/glfw/include/GLFW/vendor.go
new file mode 100644
index 0000000..0fb2a0f
--- /dev/null
+++ b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/glfw/include/GLFW/vendor.go
@@ -0,0 +1,4 @@
+//go:build required
+// +build required
+
+package vendor
diff --git a/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/glfw/src/cocoa_init.m b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/glfw/src/cocoa_init.m
new file mode 100644
index 0000000..f34d985
--- /dev/null
+++ b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/glfw/src/cocoa_init.m
@@ -0,0 +1,696 @@
+//========================================================================
+// GLFW 3.4 macOS (modified for raylib) - www.glfw.org; www.raylib.com
+//------------------------------------------------------------------------
+// Copyright (c) 2009-2019 Camilla Löwy
+// Copyright (c) 2024 M374LX
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+#if defined(_GLFW_COCOA)
+
+#include // For MAXPATHLEN
+
+// Needed for _NSGetProgname
+#include
+
+// Change to our application bundle's resources directory, if present
+//
+static void changeToResourcesDirectory(void)
+{
+ char resourcesPath[MAXPATHLEN];
+
+ CFBundleRef bundle = CFBundleGetMainBundle();
+ if (!bundle)
+ return;
+
+ CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(bundle);
+
+ CFStringRef last = CFURLCopyLastPathComponent(resourcesURL);
+ if (CFStringCompare(CFSTR("Resources"), last, 0) != kCFCompareEqualTo)
+ {
+ CFRelease(last);
+ CFRelease(resourcesURL);
+ return;
+ }
+
+ CFRelease(last);
+
+ if (!CFURLGetFileSystemRepresentation(resourcesURL,
+ true,
+ (UInt8*) resourcesPath,
+ MAXPATHLEN))
+ {
+ CFRelease(resourcesURL);
+ return;
+ }
+
+ CFRelease(resourcesURL);
+
+ chdir(resourcesPath);
+}
+
+// Set up the menu bar (manually)
+// This is nasty, nasty stuff -- calls to undocumented semi-private APIs that
+// could go away at any moment, lots of stuff that really should be
+// localize(d|able), etc. Add a nib to save us this horror.
+//
+static void createMenuBar(void)
+{
+ NSString* appName = nil;
+ NSDictionary* bundleInfo = [[NSBundle mainBundle] infoDictionary];
+ NSString* nameKeys[] =
+ {
+ @"CFBundleDisplayName",
+ @"CFBundleName",
+ @"CFBundleExecutable",
+ };
+
+ // Try to figure out what the calling application is called
+
+ for (size_t i = 0; i < sizeof(nameKeys) / sizeof(nameKeys[0]); i++)
+ {
+ id name = bundleInfo[nameKeys[i]];
+ if (name &&
+ [name isKindOfClass:[NSString class]] &&
+ ![name isEqualToString:@""])
+ {
+ appName = name;
+ break;
+ }
+ }
+
+ if (!appName)
+ {
+ char** progname = _NSGetProgname();
+ if (progname && *progname)
+ appName = @(*progname);
+ else
+ appName = @"GLFW Application";
+ }
+
+ NSMenu* bar = [[NSMenu alloc] init];
+ [NSApp setMainMenu:bar];
+
+ NSMenuItem* appMenuItem =
+ [bar addItemWithTitle:@"" action:NULL keyEquivalent:@""];
+ NSMenu* appMenu = [[NSMenu alloc] init];
+ [appMenuItem setSubmenu:appMenu];
+
+ [appMenu addItemWithTitle:[NSString stringWithFormat:@"About %@", appName]
+ action:@selector(orderFrontStandardAboutPanel:)
+ keyEquivalent:@""];
+ [appMenu addItem:[NSMenuItem separatorItem]];
+ NSMenu* servicesMenu = [[NSMenu alloc] init];
+ [NSApp setServicesMenu:servicesMenu];
+ [[appMenu addItemWithTitle:@"Services"
+ action:NULL
+ keyEquivalent:@""] setSubmenu:servicesMenu];
+ [servicesMenu release];
+ [appMenu addItem:[NSMenuItem separatorItem]];
+ [appMenu addItemWithTitle:[NSString stringWithFormat:@"Hide %@", appName]
+ action:@selector(hide:)
+ keyEquivalent:@"h"];
+ [[appMenu addItemWithTitle:@"Hide Others"
+ action:@selector(hideOtherApplications:)
+ keyEquivalent:@"h"]
+ setKeyEquivalentModifierMask:NSEventModifierFlagOption | NSEventModifierFlagCommand];
+ [appMenu addItemWithTitle:@"Show All"
+ action:@selector(unhideAllApplications:)
+ keyEquivalent:@""];
+ [appMenu addItem:[NSMenuItem separatorItem]];
+ [appMenu addItemWithTitle:[NSString stringWithFormat:@"Quit %@", appName]
+ action:@selector(terminate:)
+ keyEquivalent:@"q"];
+
+ NSMenuItem* windowMenuItem =
+ [bar addItemWithTitle:@"" action:NULL keyEquivalent:@""];
+ [bar release];
+ NSMenu* windowMenu = [[NSMenu alloc] initWithTitle:@"Window"];
+ [NSApp setWindowsMenu:windowMenu];
+ [windowMenuItem setSubmenu:windowMenu];
+
+ [windowMenu addItemWithTitle:@"Minimize"
+ action:@selector(performMiniaturize:)
+ keyEquivalent:@"m"];
+ [windowMenu addItemWithTitle:@"Zoom"
+ action:@selector(performZoom:)
+ keyEquivalent:@""];
+ [windowMenu addItem:[NSMenuItem separatorItem]];
+ [windowMenu addItemWithTitle:@"Bring All to Front"
+ action:@selector(arrangeInFront:)
+ keyEquivalent:@""];
+
+ // TODO: Make this appear at the bottom of the menu (for consistency)
+ [windowMenu addItem:[NSMenuItem separatorItem]];
+ [[windowMenu addItemWithTitle:@"Enter Full Screen"
+ action:@selector(toggleFullScreen:)
+ keyEquivalent:@"f"]
+ setKeyEquivalentModifierMask:NSEventModifierFlagControl | NSEventModifierFlagCommand];
+
+ // Prior to Snow Leopard, we need to use this oddly-named semi-private API
+ // to get the application menu working properly.
+ SEL setAppleMenuSelector = NSSelectorFromString(@"setAppleMenu:");
+ [NSApp performSelector:setAppleMenuSelector withObject:appMenu];
+}
+
+// Create key code translation tables
+//
+static void createKeyTablesCocoa(void)
+{
+ memset(_glfw.ns.keycodes, -1, sizeof(_glfw.ns.keycodes));
+ memset(_glfw.ns.scancodes, -1, sizeof(_glfw.ns.scancodes));
+
+ _glfw.ns.keycodes[0x1D] = GLFW_KEY_0;
+ _glfw.ns.keycodes[0x12] = GLFW_KEY_1;
+ _glfw.ns.keycodes[0x13] = GLFW_KEY_2;
+ _glfw.ns.keycodes[0x14] = GLFW_KEY_3;
+ _glfw.ns.keycodes[0x15] = GLFW_KEY_4;
+ _glfw.ns.keycodes[0x17] = GLFW_KEY_5;
+ _glfw.ns.keycodes[0x16] = GLFW_KEY_6;
+ _glfw.ns.keycodes[0x1A] = GLFW_KEY_7;
+ _glfw.ns.keycodes[0x1C] = GLFW_KEY_8;
+ _glfw.ns.keycodes[0x19] = GLFW_KEY_9;
+ _glfw.ns.keycodes[0x00] = GLFW_KEY_A;
+ _glfw.ns.keycodes[0x0B] = GLFW_KEY_B;
+ _glfw.ns.keycodes[0x08] = GLFW_KEY_C;
+ _glfw.ns.keycodes[0x02] = GLFW_KEY_D;
+ _glfw.ns.keycodes[0x0E] = GLFW_KEY_E;
+ _glfw.ns.keycodes[0x03] = GLFW_KEY_F;
+ _glfw.ns.keycodes[0x05] = GLFW_KEY_G;
+ _glfw.ns.keycodes[0x04] = GLFW_KEY_H;
+ _glfw.ns.keycodes[0x22] = GLFW_KEY_I;
+ _glfw.ns.keycodes[0x26] = GLFW_KEY_J;
+ _glfw.ns.keycodes[0x28] = GLFW_KEY_K;
+ _glfw.ns.keycodes[0x25] = GLFW_KEY_L;
+ _glfw.ns.keycodes[0x2E] = GLFW_KEY_M;
+ _glfw.ns.keycodes[0x2D] = GLFW_KEY_N;
+ _glfw.ns.keycodes[0x1F] = GLFW_KEY_O;
+ _glfw.ns.keycodes[0x23] = GLFW_KEY_P;
+ _glfw.ns.keycodes[0x0C] = GLFW_KEY_Q;
+ _glfw.ns.keycodes[0x0F] = GLFW_KEY_R;
+ _glfw.ns.keycodes[0x01] = GLFW_KEY_S;
+ _glfw.ns.keycodes[0x11] = GLFW_KEY_T;
+ _glfw.ns.keycodes[0x20] = GLFW_KEY_U;
+ _glfw.ns.keycodes[0x09] = GLFW_KEY_V;
+ _glfw.ns.keycodes[0x0D] = GLFW_KEY_W;
+ _glfw.ns.keycodes[0x07] = GLFW_KEY_X;
+ _glfw.ns.keycodes[0x10] = GLFW_KEY_Y;
+ _glfw.ns.keycodes[0x06] = GLFW_KEY_Z;
+
+ _glfw.ns.keycodes[0x27] = GLFW_KEY_APOSTROPHE;
+ _glfw.ns.keycodes[0x2A] = GLFW_KEY_BACKSLASH;
+ _glfw.ns.keycodes[0x2B] = GLFW_KEY_COMMA;
+ _glfw.ns.keycodes[0x18] = GLFW_KEY_EQUAL;
+ _glfw.ns.keycodes[0x32] = GLFW_KEY_GRAVE_ACCENT;
+ _glfw.ns.keycodes[0x21] = GLFW_KEY_LEFT_BRACKET;
+ _glfw.ns.keycodes[0x1B] = GLFW_KEY_MINUS;
+ _glfw.ns.keycodes[0x2F] = GLFW_KEY_PERIOD;
+ _glfw.ns.keycodes[0x1E] = GLFW_KEY_RIGHT_BRACKET;
+ _glfw.ns.keycodes[0x29] = GLFW_KEY_SEMICOLON;
+ _glfw.ns.keycodes[0x2C] = GLFW_KEY_SLASH;
+ _glfw.ns.keycodes[0x0A] = GLFW_KEY_WORLD_1;
+
+ _glfw.ns.keycodes[0x33] = GLFW_KEY_BACKSPACE;
+ _glfw.ns.keycodes[0x39] = GLFW_KEY_CAPS_LOCK;
+ _glfw.ns.keycodes[0x75] = GLFW_KEY_DELETE;
+ _glfw.ns.keycodes[0x7D] = GLFW_KEY_DOWN;
+ _glfw.ns.keycodes[0x77] = GLFW_KEY_END;
+ _glfw.ns.keycodes[0x24] = GLFW_KEY_ENTER;
+ _glfw.ns.keycodes[0x35] = GLFW_KEY_ESCAPE;
+ _glfw.ns.keycodes[0x7A] = GLFW_KEY_F1;
+ _glfw.ns.keycodes[0x78] = GLFW_KEY_F2;
+ _glfw.ns.keycodes[0x63] = GLFW_KEY_F3;
+ _glfw.ns.keycodes[0x76] = GLFW_KEY_F4;
+ _glfw.ns.keycodes[0x60] = GLFW_KEY_F5;
+ _glfw.ns.keycodes[0x61] = GLFW_KEY_F6;
+ _glfw.ns.keycodes[0x62] = GLFW_KEY_F7;
+ _glfw.ns.keycodes[0x64] = GLFW_KEY_F8;
+ _glfw.ns.keycodes[0x65] = GLFW_KEY_F9;
+ _glfw.ns.keycodes[0x6D] = GLFW_KEY_F10;
+ _glfw.ns.keycodes[0x67] = GLFW_KEY_F11;
+ _glfw.ns.keycodes[0x6F] = GLFW_KEY_F12;
+ _glfw.ns.keycodes[0x69] = GLFW_KEY_PRINT_SCREEN;
+ _glfw.ns.keycodes[0x6B] = GLFW_KEY_F14;
+ _glfw.ns.keycodes[0x71] = GLFW_KEY_F15;
+ _glfw.ns.keycodes[0x6A] = GLFW_KEY_F16;
+ _glfw.ns.keycodes[0x40] = GLFW_KEY_F17;
+ _glfw.ns.keycodes[0x4F] = GLFW_KEY_F18;
+ _glfw.ns.keycodes[0x50] = GLFW_KEY_F19;
+ _glfw.ns.keycodes[0x5A] = GLFW_KEY_F20;
+ _glfw.ns.keycodes[0x73] = GLFW_KEY_HOME;
+ _glfw.ns.keycodes[0x72] = GLFW_KEY_INSERT;
+ _glfw.ns.keycodes[0x7B] = GLFW_KEY_LEFT;
+ _glfw.ns.keycodes[0x3A] = GLFW_KEY_LEFT_ALT;
+ _glfw.ns.keycodes[0x3B] = GLFW_KEY_LEFT_CONTROL;
+ _glfw.ns.keycodes[0x38] = GLFW_KEY_LEFT_SHIFT;
+ _glfw.ns.keycodes[0x37] = GLFW_KEY_LEFT_SUPER;
+ _glfw.ns.keycodes[0x6E] = GLFW_KEY_MENU;
+ _glfw.ns.keycodes[0x47] = GLFW_KEY_NUM_LOCK;
+ _glfw.ns.keycodes[0x79] = GLFW_KEY_PAGE_DOWN;
+ _glfw.ns.keycodes[0x74] = GLFW_KEY_PAGE_UP;
+ _glfw.ns.keycodes[0x7C] = GLFW_KEY_RIGHT;
+ _glfw.ns.keycodes[0x3D] = GLFW_KEY_RIGHT_ALT;
+ _glfw.ns.keycodes[0x3E] = GLFW_KEY_RIGHT_CONTROL;
+ _glfw.ns.keycodes[0x3C] = GLFW_KEY_RIGHT_SHIFT;
+ _glfw.ns.keycodes[0x36] = GLFW_KEY_RIGHT_SUPER;
+ _glfw.ns.keycodes[0x31] = GLFW_KEY_SPACE;
+ _glfw.ns.keycodes[0x30] = GLFW_KEY_TAB;
+ _glfw.ns.keycodes[0x7E] = GLFW_KEY_UP;
+
+ _glfw.ns.keycodes[0x52] = GLFW_KEY_KP_0;
+ _glfw.ns.keycodes[0x53] = GLFW_KEY_KP_1;
+ _glfw.ns.keycodes[0x54] = GLFW_KEY_KP_2;
+ _glfw.ns.keycodes[0x55] = GLFW_KEY_KP_3;
+ _glfw.ns.keycodes[0x56] = GLFW_KEY_KP_4;
+ _glfw.ns.keycodes[0x57] = GLFW_KEY_KP_5;
+ _glfw.ns.keycodes[0x58] = GLFW_KEY_KP_6;
+ _glfw.ns.keycodes[0x59] = GLFW_KEY_KP_7;
+ _glfw.ns.keycodes[0x5B] = GLFW_KEY_KP_8;
+ _glfw.ns.keycodes[0x5C] = GLFW_KEY_KP_9;
+ _glfw.ns.keycodes[0x45] = GLFW_KEY_KP_ADD;
+ _glfw.ns.keycodes[0x41] = GLFW_KEY_KP_DECIMAL;
+ _glfw.ns.keycodes[0x4B] = GLFW_KEY_KP_DIVIDE;
+ _glfw.ns.keycodes[0x4C] = GLFW_KEY_KP_ENTER;
+ _glfw.ns.keycodes[0x51] = GLFW_KEY_KP_EQUAL;
+ _glfw.ns.keycodes[0x43] = GLFW_KEY_KP_MULTIPLY;
+ _glfw.ns.keycodes[0x4E] = GLFW_KEY_KP_SUBTRACT;
+
+ for (int scancode = 0; scancode < 256; scancode++)
+ {
+ // Store the reverse translation for faster key name lookup
+ if (_glfw.ns.keycodes[scancode] >= 0)
+ _glfw.ns.scancodes[_glfw.ns.keycodes[scancode]] = scancode;
+ }
+}
+
+// Retrieve Unicode data for the current keyboard layout
+//
+static GLFWbool updateUnicodeData(void)
+{
+ if (_glfw.ns.inputSource)
+ {
+ CFRelease(_glfw.ns.inputSource);
+ _glfw.ns.inputSource = NULL;
+ _glfw.ns.unicodeData = nil;
+ }
+
+ _glfw.ns.inputSource = TISCopyCurrentKeyboardLayoutInputSource();
+ if (!_glfw.ns.inputSource)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Cocoa: Failed to retrieve keyboard layout input source");
+ return GLFW_FALSE;
+ }
+
+ _glfw.ns.unicodeData =
+ TISGetInputSourceProperty(_glfw.ns.inputSource,
+ kTISPropertyUnicodeKeyLayoutData);
+ if (!_glfw.ns.unicodeData)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Cocoa: Failed to retrieve keyboard layout Unicode data");
+ return GLFW_FALSE;
+ }
+
+ return GLFW_TRUE;
+}
+
+// Load HIToolbox.framework and the TIS symbols we need from it
+//
+static GLFWbool initializeTIS(void)
+{
+ // This works only because Cocoa has already loaded it properly
+ _glfw.ns.tis.bundle =
+ CFBundleGetBundleWithIdentifier(CFSTR("com.apple.HIToolbox"));
+ if (!_glfw.ns.tis.bundle)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Cocoa: Failed to load HIToolbox.framework");
+ return GLFW_FALSE;
+ }
+
+ CFStringRef* kPropertyUnicodeKeyLayoutData =
+ CFBundleGetDataPointerForName(_glfw.ns.tis.bundle,
+ CFSTR("kTISPropertyUnicodeKeyLayoutData"));
+ _glfw.ns.tis.CopyCurrentKeyboardLayoutInputSource =
+ CFBundleGetFunctionPointerForName(_glfw.ns.tis.bundle,
+ CFSTR("TISCopyCurrentKeyboardLayoutInputSource"));
+ _glfw.ns.tis.GetInputSourceProperty =
+ CFBundleGetFunctionPointerForName(_glfw.ns.tis.bundle,
+ CFSTR("TISGetInputSourceProperty"));
+ _glfw.ns.tis.GetKbdType =
+ CFBundleGetFunctionPointerForName(_glfw.ns.tis.bundle,
+ CFSTR("LMGetKbdType"));
+
+ if (!kPropertyUnicodeKeyLayoutData ||
+ !TISCopyCurrentKeyboardLayoutInputSource ||
+ !TISGetInputSourceProperty ||
+ !LMGetKbdType)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Cocoa: Failed to load TIS API symbols");
+ return GLFW_FALSE;
+ }
+
+ _glfw.ns.tis.kPropertyUnicodeKeyLayoutData =
+ *kPropertyUnicodeKeyLayoutData;
+
+ return updateUnicodeData();
+}
+
+@interface GLFWHelper : NSObject
+@end
+
+@implementation GLFWHelper
+
+- (void)selectedKeyboardInputSourceChanged:(NSObject* )object
+{
+ updateUnicodeData();
+}
+
+- (void)doNothing:(id)object
+{
+}
+
+@end // GLFWHelper
+
+@interface GLFWApplicationDelegate : NSObject
+@end
+
+@implementation GLFWApplicationDelegate
+
+- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
+{
+ for (_GLFWwindow* window = _glfw.windowListHead; window; window = window->next)
+ _glfwInputWindowCloseRequest(window);
+
+ return NSTerminateCancel;
+}
+
+- (void)applicationDidChangeScreenParameters:(NSNotification *) notification
+{
+ for (_GLFWwindow* window = _glfw.windowListHead; window; window = window->next)
+ {
+ if (window->context.client != GLFW_NO_API)
+ [window->context.nsgl.object update];
+ }
+
+ _glfwPollMonitorsCocoa();
+}
+
+- (void)applicationWillFinishLaunching:(NSNotification *)notification
+{
+ if (_glfw.hints.init.ns.menubar)
+ {
+ // Menu bar setup must go between sharedApplication and finishLaunching
+ // in order to properly emulate the behavior of NSApplicationMain
+
+ if ([[NSBundle mainBundle] pathForResource:@"MainMenu" ofType:@"nib"])
+ {
+ [[NSBundle mainBundle] loadNibNamed:@"MainMenu"
+ owner:NSApp
+ topLevelObjects:&_glfw.ns.nibObjects];
+ }
+ else
+ createMenuBar();
+ }
+}
+
+- (void)applicationDidFinishLaunching:(NSNotification *)notification
+{
+ _glfwPostEmptyEventCocoa();
+ [NSApp stop:nil];
+}
+
+- (void)applicationDidHide:(NSNotification *)notification
+{
+ for (int i = 0; i < _glfw.monitorCount; i++)
+ _glfwRestoreVideoModeCocoa(_glfw.monitors[i]);
+}
+
+@end // GLFWApplicationDelegate
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW internal API //////
+//////////////////////////////////////////////////////////////////////////
+
+void* _glfwLoadLocalVulkanLoaderCocoa(void)
+{
+ CFBundleRef bundle = CFBundleGetMainBundle();
+ if (!bundle)
+ return NULL;
+
+ CFURLRef frameworksUrl = CFBundleCopyPrivateFrameworksURL(bundle);
+ if (!frameworksUrl)
+ return NULL;
+
+ CFURLRef loaderUrl = CFURLCreateCopyAppendingPathComponent(
+ kCFAllocatorDefault, frameworksUrl, CFSTR("libvulkan.1.dylib"), false);
+ if (!loaderUrl)
+ {
+ CFRelease(frameworksUrl);
+ return NULL;
+ }
+
+ char path[PATH_MAX];
+ void* handle = NULL;
+
+ if (CFURLGetFileSystemRepresentation(loaderUrl, true, (UInt8*) path, sizeof(path) - 1))
+ handle = _glfwPlatformLoadModule(path);
+
+ CFRelease(loaderUrl);
+ CFRelease(frameworksUrl);
+ return handle;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW platform API //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWbool _glfwConnectCocoa(int platformID, _GLFWplatform* platform)
+{
+ const _GLFWplatform cocoa =
+ {
+ .platformID = GLFW_PLATFORM_COCOA,
+ .init = _glfwInitCocoa,
+ .terminate = _glfwTerminateCocoa,
+ .getCursorPos = _glfwGetCursorPosCocoa,
+ .setCursorPos = _glfwSetCursorPosCocoa,
+ .setCursorMode = _glfwSetCursorModeCocoa,
+ .setRawMouseMotion = _glfwSetRawMouseMotionCocoa,
+ .rawMouseMotionSupported = _glfwRawMouseMotionSupportedCocoa,
+ .createCursor = _glfwCreateCursorCocoa,
+ .createStandardCursor = _glfwCreateStandardCursorCocoa,
+ .destroyCursor = _glfwDestroyCursorCocoa,
+ .setCursor = _glfwSetCursorCocoa,
+ .getScancodeName = _glfwGetScancodeNameCocoa,
+ .getKeyScancode = _glfwGetKeyScancodeCocoa,
+ .setClipboardString = _glfwSetClipboardStringCocoa,
+ .getClipboardString = _glfwGetClipboardStringCocoa,
+ .initJoysticks = _glfwInitJoysticksCocoa,
+ .terminateJoysticks = _glfwTerminateJoysticksCocoa,
+ .pollJoystick = _glfwPollJoystickCocoa,
+ .getMappingName = _glfwGetMappingNameCocoa,
+ .updateGamepadGUID = _glfwUpdateGamepadGUIDCocoa,
+ .freeMonitor = _glfwFreeMonitorCocoa,
+ .getMonitorPos = _glfwGetMonitorPosCocoa,
+ .getMonitorContentScale = _glfwGetMonitorContentScaleCocoa,
+ .getMonitorWorkarea = _glfwGetMonitorWorkareaCocoa,
+ .getVideoModes = _glfwGetVideoModesCocoa,
+ .getVideoMode = _glfwGetVideoModeCocoa,
+ .getGammaRamp = _glfwGetGammaRampCocoa,
+ .setGammaRamp = _glfwSetGammaRampCocoa,
+ .createWindow = _glfwCreateWindowCocoa,
+ .destroyWindow = _glfwDestroyWindowCocoa,
+ .setWindowTitle = _glfwSetWindowTitleCocoa,
+ .setWindowIcon = _glfwSetWindowIconCocoa,
+ .getWindowPos = _glfwGetWindowPosCocoa,
+ .setWindowPos = _glfwSetWindowPosCocoa,
+ .getWindowSize = _glfwGetWindowSizeCocoa,
+ .setWindowSize = _glfwSetWindowSizeCocoa,
+ .setWindowSizeLimits = _glfwSetWindowSizeLimitsCocoa,
+ .setWindowAspectRatio = _glfwSetWindowAspectRatioCocoa,
+ .getFramebufferSize = _glfwGetFramebufferSizeCocoa,
+ .getWindowFrameSize = _glfwGetWindowFrameSizeCocoa,
+ .getWindowContentScale = _glfwGetWindowContentScaleCocoa,
+ .iconifyWindow = _glfwIconifyWindowCocoa,
+ .restoreWindow = _glfwRestoreWindowCocoa,
+ .maximizeWindow = _glfwMaximizeWindowCocoa,
+ .showWindow = _glfwShowWindowCocoa,
+ .hideWindow = _glfwHideWindowCocoa,
+ .requestWindowAttention = _glfwRequestWindowAttentionCocoa,
+ .focusWindow = _glfwFocusWindowCocoa,
+ .setWindowMonitor = _glfwSetWindowMonitorCocoa,
+ .windowFocused = _glfwWindowFocusedCocoa,
+ .windowIconified = _glfwWindowIconifiedCocoa,
+ .windowVisible = _glfwWindowVisibleCocoa,
+ .windowMaximized = _glfwWindowMaximizedCocoa,
+ .windowHovered = _glfwWindowHoveredCocoa,
+ .framebufferTransparent = _glfwFramebufferTransparentCocoa,
+ .getWindowOpacity = _glfwGetWindowOpacityCocoa,
+ .setWindowResizable = _glfwSetWindowResizableCocoa,
+ .setWindowDecorated = _glfwSetWindowDecoratedCocoa,
+ .setWindowFloating = _glfwSetWindowFloatingCocoa,
+ .setWindowOpacity = _glfwSetWindowOpacityCocoa,
+ .setWindowMousePassthrough = _glfwSetWindowMousePassthroughCocoa,
+ .pollEvents = _glfwPollEventsCocoa,
+ .waitEvents = _glfwWaitEventsCocoa,
+ .waitEventsTimeout = _glfwWaitEventsTimeoutCocoa,
+ .postEmptyEvent = _glfwPostEmptyEventCocoa,
+ .getEGLPlatform = _glfwGetEGLPlatformCocoa,
+ .getEGLNativeDisplay = _glfwGetEGLNativeDisplayCocoa,
+ .getEGLNativeWindow = _glfwGetEGLNativeWindowCocoa,
+ .getRequiredInstanceExtensions = _glfwGetRequiredInstanceExtensionsCocoa,
+ .getPhysicalDevicePresentationSupport = _glfwGetPhysicalDevicePresentationSupportCocoa,
+ .createWindowSurface = _glfwCreateWindowSurfaceCocoa
+ };
+
+ *platform = cocoa;
+ return GLFW_TRUE;
+}
+
+int _glfwInitCocoa(void)
+{
+ @autoreleasepool {
+
+ _glfw.ns.helper = [[GLFWHelper alloc] init];
+
+ [NSThread detachNewThreadSelector:@selector(doNothing:)
+ toTarget:_glfw.ns.helper
+ withObject:nil];
+
+ [NSApplication sharedApplication];
+
+ _glfw.ns.delegate = [[GLFWApplicationDelegate alloc] init];
+ if (_glfw.ns.delegate == nil)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Cocoa: Failed to create application delegate");
+ return GLFW_FALSE;
+ }
+
+ [NSApp setDelegate:_glfw.ns.delegate];
+
+ NSEvent* (^block)(NSEvent*) = ^ NSEvent* (NSEvent* event)
+ {
+ if ([event modifierFlags] & NSEventModifierFlagCommand)
+ [[NSApp keyWindow] sendEvent:event];
+
+ return event;
+ };
+
+ _glfw.ns.keyUpMonitor =
+ [NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskKeyUp
+ handler:block];
+
+ if (_glfw.hints.init.ns.chdir)
+ changeToResourcesDirectory();
+
+ // Press and Hold prevents some keys from emitting repeated characters
+ NSDictionary* defaults = @{@"ApplePressAndHoldEnabled":@NO};
+ [[NSUserDefaults standardUserDefaults] registerDefaults:defaults];
+
+ [[NSNotificationCenter defaultCenter]
+ addObserver:_glfw.ns.helper
+ selector:@selector(selectedKeyboardInputSourceChanged:)
+ name:NSTextInputContextKeyboardSelectionDidChangeNotification
+ object:nil];
+
+ createKeyTablesCocoa();
+
+ _glfw.ns.eventSource = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
+ if (!_glfw.ns.eventSource)
+ return GLFW_FALSE;
+
+ CGEventSourceSetLocalEventsSuppressionInterval(_glfw.ns.eventSource, 0.0);
+
+ if (!initializeTIS())
+ return GLFW_FALSE;
+
+ _glfwPollMonitorsCocoa();
+
+ if (![[NSRunningApplication currentApplication] isFinishedLaunching])
+ [NSApp run];
+
+ // In case we are unbundled, make us a proper UI application
+ if (_glfw.hints.init.ns.menubar)
+ [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
+
+ return GLFW_TRUE;
+
+ } // autoreleasepool
+}
+
+void _glfwTerminateCocoa(void)
+{
+ @autoreleasepool {
+
+ if (_glfw.ns.inputSource)
+ {
+ CFRelease(_glfw.ns.inputSource);
+ _glfw.ns.inputSource = NULL;
+ _glfw.ns.unicodeData = nil;
+ }
+
+ if (_glfw.ns.eventSource)
+ {
+ CFRelease(_glfw.ns.eventSource);
+ _glfw.ns.eventSource = NULL;
+ }
+
+ if (_glfw.ns.delegate)
+ {
+ [NSApp setDelegate:nil];
+ [_glfw.ns.delegate release];
+ _glfw.ns.delegate = nil;
+ }
+
+ if (_glfw.ns.helper)
+ {
+ [[NSNotificationCenter defaultCenter]
+ removeObserver:_glfw.ns.helper
+ name:NSTextInputContextKeyboardSelectionDidChangeNotification
+ object:nil];
+ [[NSNotificationCenter defaultCenter]
+ removeObserver:_glfw.ns.helper];
+ [_glfw.ns.helper release];
+ _glfw.ns.helper = nil;
+ }
+
+ if (_glfw.ns.keyUpMonitor)
+ [NSEvent removeMonitor:_glfw.ns.keyUpMonitor];
+
+ _glfw_free(_glfw.ns.clipboardString);
+
+ _glfwTerminateNSGL();
+ _glfwTerminateEGL();
+ _glfwTerminateOSMesa();
+
+ } // autoreleasepool
+}
+
+#endif // _GLFW_COCOA
+
diff --git a/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/glfw/src/cocoa_joystick.h b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/glfw/src/cocoa_joystick.h
new file mode 100644
index 0000000..2f46dfc
--- /dev/null
+++ b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/glfw/src/cocoa_joystick.h
@@ -0,0 +1,49 @@
+//========================================================================
+// GLFW 3.4 Cocoa - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2006-2017 Camilla Löwy
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include
+#include
+#include
+
+#define GLFW_COCOA_JOYSTICK_STATE _GLFWjoystickNS ns;
+#define GLFW_COCOA_LIBRARY_JOYSTICK_STATE
+
+// Cocoa-specific per-joystick data
+//
+typedef struct _GLFWjoystickNS
+{
+ IOHIDDeviceRef device;
+ CFMutableArrayRef axes;
+ CFMutableArrayRef buttons;
+ CFMutableArrayRef hats;
+} _GLFWjoystickNS;
+
+GLFWbool _glfwInitJoysticksCocoa(void);
+void _glfwTerminateJoysticksCocoa(void);
+GLFWbool _glfwPollJoystickCocoa(_GLFWjoystick* js, int mode);
+const char* _glfwGetMappingNameCocoa(void);
+void _glfwUpdateGamepadGUIDCocoa(char* guid);
+
diff --git a/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/glfw/src/cocoa_joystick.m b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/glfw/src/cocoa_joystick.m
new file mode 100644
index 0000000..d5de479
--- /dev/null
+++ b/raymenu/vendor/github.com/gen2brain/raylib-go/raylib/external/glfw/src/cocoa_joystick.m
@@ -0,0 +1,485 @@
+//========================================================================
+// GLFW 3.4 Cocoa - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2009-2019 Camilla Löwy
+// Copyright (c) 2012 Torsten Walluhn
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+#if defined(_GLFW_COCOA)
+
+#include
+#include
+#include
+
+#include