diff --git a/base/builtin/builtin.odin b/base/builtin/builtin.odin index 14da9603d..0196e2030 100644 --- a/base/builtin/builtin.odin +++ b/base/builtin/builtin.odin @@ -7,13 +7,232 @@ nil :: nil false :: 0!=0 true :: 0==0 -ODIN_OS :: ODIN_OS -ODIN_ARCH :: ODIN_ARCH -ODIN_ENDIAN :: ODIN_ENDIAN -ODIN_VENDOR :: ODIN_VENDOR -ODIN_VERSION :: ODIN_VERSION -ODIN_ROOT :: ODIN_ROOT -ODIN_DEBUG :: ODIN_DEBUG +// The following constants are added in `checker.cpp`'s `init_universal` procedure. + +/* + An `enum` value indicating the target's CPU architecture. + Possible values are: `.amd64`, `.i386`, `.arm32`, `.arm64`, `.wasm32`, `.wasm64p32`, and `.riscv64`. +*/ +ODIN_ARCH :: ODIN_ARCH + +/* + A `string` indicating the target's CPU architecture. + Possible values are: "amd64", "i386", "arm32", "arm64", "wasm32", "wasm64p32", "riscv64". +*/ +ODIN_ARCH_STRING :: ODIN_ARCH_STRING + +/* + An `enum` value indicating the type of compiled output, chosen using `-build-mode`. + Possible values are: `.Executable`, `.Dynamic`, `.Static`, `.Object`, `.Assembly`, and `.LLVM_IR`. +*/ +ODIN_BUILD_MODE :: ODIN_BUILD_MODE + +/* + A `string` containing the name of the folder that contains the entry point, + e.g. for `%ODIN_ROOT%/examples/demo`, this would contain `demo`. +*/ +ODIN_BUILD_PROJECT_NAME :: ODIN_BUILD_PROJECT_NAME + +/* + An `i64` containing the time at which the executable was compiled, in nanoseconds. + This is compatible with the `time.Time` type, i.e. `time.Time{_nsec=ODIN_COMPILE_TIMESTAMP}` +*/ +ODIN_COMPILE_TIMESTAMP :: ODIN_COMPILE_TIMESTAMP + +/* + `true` if the `-debug` command line switch is passed, which enables debug info generation. +*/ +ODIN_DEBUG :: ODIN_DEBUG + +/* + `true` if the `-default-to-nil-allocator` command line switch is passed, + which sets the initial `context.allocator` to an allocator that does nothing. +*/ +ODIN_DEFAULT_TO_NIL_ALLOCATOR :: ODIN_DEFAULT_TO_NIL_ALLOCATOR + +/* + `true` if the `-default-to-panic-allocator` command line switch is passed, + which sets the initial `context.allocator` to an allocator that panics if allocated from. +*/ +ODIN_DEFAULT_TO_PANIC_ALLOCATOR :: ODIN_DEFAULT_TO_PANIC_ALLOCATOR + +/* + `true` if the `-disable-assert` command line switch is passed, + which removes all calls to `assert` from the program. +*/ +ODIN_DISABLE_ASSERT :: ODIN_DISABLE_ASSERT + +/* + An `enum` value indicating the endianness of the target. + Possible values are: `.Little` and `.Big`. +*/ +ODIN_ENDIAN :: ODIN_ENDIAN + +/* + An `string` indicating the endianness of the target. + Possible values are: "little" and "big". +*/ +ODIN_ENDIAN_STRING :: ODIN_ENDIAN_STRING + +/* + An `enum` value set using the `-error-pos-style` switch, indicating the source location style used for compile errors and warnings. + Possible values are: `.Default` (Odin-style) and `.Unix`. +*/ +ODIN_ERROR_POS_STYLE :: ODIN_ERROR_POS_STYLE + +/* + `true` if the `-foreign-error-procedures` command line switch is passed, + which inhibits generation of runtime error procedures, so that they can be in a separate compilation unit. +*/ +ODIN_FOREIGN_ERROR_PROCEDURES :: ODIN_FOREIGN_ERROR_PROCEDURES + +/* + A `string` describing the microarchitecture used for code generation. + If not set using the `-microarch` command line switch, the compiler will pick a default. + Possible values include, but are not limited to: "sandybridge", "x86-64-v2". +*/ +ODIN_MICROARCH_STRING :: ODIN_MICROARCH_STRING + +/* + An `int` value representing the minimum OS version given to the linker, calculated as `major * 10_000 + minor * 100 + revision`. + If not set using the `-minimum-os-version` command line switch, it defaults to `0`, except on Darwin, where it's `11_00_00`. +*/ +ODIN_MINIMUM_OS_VERSION :: ODIN_MINIMUM_OS_VERSION + +/* + `true` if the `-no-bounds-check` command line switch is passed, which disables bounds checking at runtime. +*/ +ODIN_NO_BOUNDS_CHECK :: ODIN_NO_BOUNDS_CHECK + +/* + `true` if the `-no-crt` command line switch is passed, which inhibits linking with the C Runtime Library, a.k.a. LibC. +*/ +ODIN_NO_CRT :: ODIN_NO_CRT + +/* + `true` if the `-no-entry-point` command line switch is passed, which makes the declaration of a `main` procedure optional. +*/ +ODIN_NO_ENTRY_POINT :: ODIN_NO_ENTRY_POINT + +/* + `true` if the `-no-rtti` command line switch is passed, which inhibits generation of full Runtime Type Information. +*/ +ODIN_NO_RTTI :: ODIN_NO_RTTI + +/* + `true` if the `-no-type-assert` command line switch is passed, which disables type assertion checking program wide. +*/ +ODIN_NO_TYPE_ASSERT :: ODIN_NO_TYPE_ASSERT + +/* + An `enum` value indicating the optimization level selected using the `-o` command line switch. + Possible values are: `.None`, `.Minimal`, `.Size`, `.Speed`, and `.Aggressive`. + + If `ODIN_OPTIMIZATION_MODE` is anything other than `.None` or `.Minimal`, the compiler will also perform a unity build, + and `ODIN_USE_SEPARATE_MODULES` will be set to `false` as a result. +*/ +ODIN_OPTIMIZATION_MODE :: ODIN_OPTIMIZATION_MODE + +/* + An `enum` value indicating what the target operating system is. +*/ +ODIN_OS :: ODIN_OS + +/* + A `string` indicating what the target operating system is. +*/ +ODIN_OS_STRING :: ODIN_OS_STRING + +/* + An `enum` value indicating the platform subtarget, chosen using the `-subtarget` switch. + Possible values are: `.Default` `.iOS`, and `.Android`. +*/ +ODIN_PLATFORM_SUBTARGET :: ODIN_PLATFORM_SUBTARGET + +/* + A `string` representing the path of the folder containing the Odin compiler, + relative to which we expect to find the `base` and `core` package collections. +*/ +ODIN_ROOT :: ODIN_ROOT + +/* + A `bit_set` indicating the sanitizer flags set using the `-sanitize` command line switch. + Supported flags are `.Address`, `.Memory`, and `.Thread`. +*/ +ODIN_SANITIZER_FLAGS :: ODIN_SANITIZER_FLAGS + +/* + `true` if the code is being compiled via an invocation of `odin test`. +*/ +ODIN_TEST :: ODIN_TEST + +/* + `true` if built using the experimental Tilde backend. +*/ +ODIN_TILDE :: ODIN_TILDE + +/* + `true` by default, meaning each each package is built into its own object file, and then linked together. + `false` if the `-use-single-module` command line switch to force a unity build is provided. + + If `ODIN_OPTIMIZATION_MODE` is anything other than `.None` or `.Minimal`, the compiler will also perform a unity build, + and this constant will also be set to `false`. +*/ +ODIN_USE_SEPARATE_MODULES :: ODIN_USE_SEPARATE_MODULES + +/* + `true` if Valgrind integration is supported on the target. +*/ +ODIN_VALGRIND_SUPPORT :: ODIN_VALGRIND_SUPPORT + +/* + A `string` which identifies the compiler being used. The official compiler sets this to `"odin"`. +*/ +ODIN_VENDOR :: ODIN_VENDOR + +/* + A `string` containing the version of the Odin compiler, typically in the format `dev-YYYY-MM`. +*/ +ODIN_VERSION :: ODIN_VERSION + +/* + A `string` containing the Git hash part of the Odin version. + Empty if `.git` could not be detected at the time the compiler was built. +*/ +ODIN_VERSION_HASH :: ODIN_VERSION_HASH + +/* + An `enum` set by the `-subsystem` flag, specifying which Windows subsystem the PE file was created for. + Possible values are: + `.Unknown` - Default and only value on non-Windows platforms + `.Console` - Default on Windows + `.Windows` - Can be used by graphical applications so Windows doesn't open an empty console + + There are some other possible values for e.g. EFI applications, but only Console and Windows are supported. + + See also: https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-image_optional_header64 +*/ +ODIN_WINDOWS_SUBSYSTEM :: ODIN_WINDOWS_SUBSYSTEM + +/* + An `string` set by the `-subsystem` flag, specifying which Windows subsystem the PE file was created for. + Possible values are: + "UNKNOWN" - Default and only value on non-Windows platforms + "CONSOLE" - Default on Windows + "WINDOWS" - Can be used by graphical applications so Windows doesn't open an empty console + + There are some other possible values for e.g. EFI applications, but only Console and Windows are supported. + + See also: https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-image_optional_header64 +*/ +ODIN_WINDOWS_SUBSYSTEM_STRING :: ODIN_WINDOWS_SUBSYSTEM_STRING + +/* + `true` if LLVM supports the f16 type. +*/ +__ODIN_LLVM_F16_SUPPORTED :: __ODIN_LLVM_F16_SUPPORTED + + byte :: u8 // alias @@ -131,3 +350,6 @@ soa_zip :: proc(slices: ...) -> #soa[]Struct --- soa_unzip :: proc(value: $S/#soa[]$E) -> (slices: ...) --- unreachable :: proc() -> ! --- + +// Where T is a string, slice, dynamic array, or pointer to an array type +raw_data :: proc(t: $T) -> rawptr \ No newline at end of file diff --git a/base/runtime/internal.odin b/base/runtime/internal.odin index 38b7f662c..907b187f1 100644 --- a/base/runtime/internal.odin +++ b/base/runtime/internal.odin @@ -16,6 +16,12 @@ RUNTIME_REQUIRE :: false // !ODIN_TILDE @(private) __float16 :: f16 when __ODIN_LLVM_F16_SUPPORTED else u16 +HAS_HARDWARE_SIMD :: false when (ODIN_ARCH == .amd64 || ODIN_ARCH == .i386) && !intrinsics.has_target_feature("sse2") else + false when (ODIN_ARCH == .arm64 || ODIN_ARCH == .arm32) && !intrinsics.has_target_feature("neon") else + false when (ODIN_ARCH == .wasm64p32 || ODIN_ARCH == .wasm32) && !intrinsics.has_target_feature("simd128") else + false when (ODIN_ARCH == .riscv64) && !intrinsics.has_target_feature("v") else + true + @(private) byte_slice :: #force_inline proc "contextless" (data: rawptr, len: int) -> []byte #no_bounds_check { @@ -229,151 +235,242 @@ memory_equal :: proc "contextless" (x, y: rawptr, n: int) -> bool { case n == 0: return true case x == y: return true } - a, b := ([^]byte)(x), ([^]byte)(y) - length := uint(n) + a, b := cast([^]byte)x, cast([^]byte)y - for i := uint(0); i < length; i += 1 { + n := uint(n) + i := uint(0) + m := uint(0) + + if n >= 8 { + when HAS_HARDWARE_SIMD { + // Avoid using 256-bit SIMD on platforms where its emulation is + // likely to be less than ideal. + when ODIN_ARCH == .amd64 && intrinsics.has_target_feature("avx2") { + m = n / 32 * 32 + for /**/; i < m; i += 32 { + load_a := intrinsics.unaligned_load(cast(^#simd[32]u8)&a[i]) + load_b := intrinsics.unaligned_load(cast(^#simd[32]u8)&b[i]) + ne := intrinsics.simd_lanes_ne(load_a, load_b) + if intrinsics.simd_reduce_or(ne) != 0 { + return false + } + } + } + } + + m = (n-i) / 16 * 16 + for /**/; i < m; i += 16 { + load_a := intrinsics.unaligned_load(cast(^#simd[16]u8)&a[i]) + load_b := intrinsics.unaligned_load(cast(^#simd[16]u8)&b[i]) + ne := intrinsics.simd_lanes_ne(load_a, load_b) + if intrinsics.simd_reduce_or(ne) != 0 { + return false + } + } + + m = (n-i) / 8 * 8 + for /**/; i < m; i += 8 { + if intrinsics.unaligned_load(cast(^uintptr)&a[i]) != intrinsics.unaligned_load(cast(^uintptr)&b[i]) { + return false + } + } + } + + for /**/; i < n; i += 1 { if a[i] != b[i] { return false } } return true - -/* - - when size_of(uint) == 8 { - if word_length := length >> 3; word_length != 0 { - for _ in 0..> 2; word_length != 0 { - for _ in 0.. int #no_bounds_check { + +memory_compare :: proc "contextless" (x, y: rawptr, n: int) -> int #no_bounds_check { switch { - case a == b: return 0 - case a == nil: return -1 - case b == nil: return +1 + case x == y: return 0 + case x == nil: return -1 + case y == nil: return +1 } + a, b := cast([^]byte)x, cast([^]byte)y + + n := uint(n) + i := uint(0) + m := uint(0) - x := uintptr(a) - y := uintptr(b) - n := uintptr(n) - - SU :: size_of(uintptr) - fast := n/SU + 1 - offset := (fast-1)*SU - curr_block := uintptr(0) - if n < SU { - fast = 0 - } - - for /**/; curr_block < fast; curr_block += 1 { - va := (^uintptr)(x + curr_block * size_of(uintptr))^ - vb := (^uintptr)(y + curr_block * size_of(uintptr))^ - if va ~ vb != 0 { - for pos := curr_block*SU; pos < n; pos += 1 { - a := (^byte)(x+pos)^ - b := (^byte)(y+pos)^ - if a ~ b != 0 { - return -1 if (int(a) - int(b)) < 0 else +1 + when HAS_HARDWARE_SIMD { + when ODIN_ARCH == .amd64 && intrinsics.has_target_feature("avx2") { + m = n / 32 * 32 + for /**/; i < m; i += 32 { + load_a := intrinsics.unaligned_load(cast(^#simd[32]u8)&a[i]) + load_b := intrinsics.unaligned_load(cast(^#simd[32]u8)&b[i]) + comparison := intrinsics.simd_lanes_ne(load_a, load_b) + if intrinsics.simd_reduce_or(comparison) != 0 { + sentinel: #simd[32]u8 = u8(0xFF) + indices := intrinsics.simd_indices(#simd[32]u8) + index_select := intrinsics.simd_select(comparison, indices, sentinel) + index_reduce := cast(uint)intrinsics.simd_reduce_min(index_select) + return -1 if a[i+index_reduce] < b[i+index_reduce] else +1 } } } } - for /**/; offset < n; offset += 1 { - a := (^byte)(x+offset)^ - b := (^byte)(y+offset)^ - if a ~ b != 0 { - return -1 if (int(a) - int(b)) < 0 else +1 + m = (n-i) / 16 * 16 + for /**/; i < m; i += 16 { + load_a := intrinsics.unaligned_load(cast(^#simd[16]u8)&a[i]) + load_b := intrinsics.unaligned_load(cast(^#simd[16]u8)&b[i]) + comparison := intrinsics.simd_lanes_ne(load_a, load_b) + if intrinsics.simd_reduce_or(comparison) != 0 { + sentinel: #simd[16]u8 = u8(0xFF) + indices := intrinsics.simd_indices(#simd[16]u8) + index_select := intrinsics.simd_select(comparison, indices, sentinel) + index_reduce := cast(uint)intrinsics.simd_reduce_min(index_select) + return -1 if a[i+index_reduce] < b[i+index_reduce] else +1 } } + // 64-bit SIMD is faster than using a `uintptr` to detect a difference then + // re-iterating with the byte-by-byte loop, at least on AMD64. + m = (n-i) / 8 * 8 + for /**/; i < m; i += 8 { + load_a := intrinsics.unaligned_load(cast(^#simd[8]u8)&a[i]) + load_b := intrinsics.unaligned_load(cast(^#simd[8]u8)&b[i]) + comparison := intrinsics.simd_lanes_ne(load_a, load_b) + if intrinsics.simd_reduce_or(comparison) != 0 { + sentinel: #simd[8]u8 = u8(0xFF) + indices := intrinsics.simd_indices(#simd[8]u8) + index_select := intrinsics.simd_select(comparison, indices, sentinel) + index_reduce := cast(uint)intrinsics.simd_reduce_min(index_select) + return -1 if a[i+index_reduce] < b[i+index_reduce] else +1 + } + } + + for /**/; i < n; i += 1 { + if a[i] ~ b[i] != 0 { + return -1 if int(a[i]) - int(b[i]) < 0 else +1 + } + } return 0 } memory_compare_zero :: proc "contextless" (a: rawptr, n: int) -> int #no_bounds_check { - x := uintptr(a) - n := uintptr(n) + n := uint(n) + i := uint(0) + m := uint(0) - SU :: size_of(uintptr) - fast := n/SU + 1 - offset := (fast-1)*SU - curr_block := uintptr(0) - if n < SU { - fast = 0 + // Because we're comparing against zero, we never return -1, as that would + // indicate the compared value is less than zero. + // + // Note that a zero return value here means equality. + + bytes := ([^]u8)(a) + + if n >= 8 { + when HAS_HARDWARE_SIMD { + when ODIN_ARCH == .amd64 && intrinsics.has_target_feature("avx2") { + scanner32: #simd[32]u8 + m = n / 32 * 32 + for /**/; i < m; i += 32 { + load := intrinsics.unaligned_load(cast(^#simd[32]u8)&bytes[i]) + ne := intrinsics.simd_lanes_ne(scanner32, load) + if intrinsics.simd_reduce_or(ne) > 0 { + return 1 + } + } + } + } + + scanner16: #simd[16]u8 + m = (n-i) / 16 * 16 + for /**/; i < m; i += 16 { + load := intrinsics.unaligned_load(cast(^#simd[16]u8)&bytes[i]) + ne := intrinsics.simd_lanes_ne(scanner16, load) + if intrinsics.simd_reduce_or(ne) != 0 { + return 1 + } + } + + m = (n-i) / 8 * 8 + for /**/; i < m; i += 8 { + if intrinsics.unaligned_load(cast(^uintptr)&bytes[i]) != 0 { + return 1 + } + } } - for /**/; curr_block < fast; curr_block += 1 { - va := (^uintptr)(x + curr_block * size_of(uintptr))^ - if va ~ 0 != 0 { - for pos := curr_block*SU; pos < n; pos += 1 { - a := (^byte)(x+pos)^ - if a ~ 0 != 0 { - return -1 if int(a) < 0 else +1 + for /**/; i < n; i += 1 { + if bytes[i] != 0 { + return 1 + } + } + return 0 +} + +memory_prefix_length :: proc "contextless" (x, y: rawptr, n: int) -> (idx: int) #no_bounds_check { + switch { + case x == y: return n + case x == nil: return 0 + case y == nil: return 0 + } + a, b := cast([^]byte)x, cast([^]byte)y + + n := uint(n) + i := uint(0) + m := uint(0) + + when HAS_HARDWARE_SIMD { + when ODIN_ARCH == .amd64 && intrinsics.has_target_feature("avx2") { + m = n / 32 * 32 + for /**/; i < m; i += 32 { + load_a := intrinsics.unaligned_load(cast(^#simd[32]u8)&a[i]) + load_b := intrinsics.unaligned_load(cast(^#simd[32]u8)&b[i]) + comparison := intrinsics.simd_lanes_ne(load_a, load_b) + if intrinsics.simd_reduce_or(comparison) != 0 { + sentinel: #simd[32]u8 = u8(0xFF) + indices := intrinsics.simd_indices(#simd[32]u8) + index_select := intrinsics.simd_select(comparison, indices, sentinel) + index_reduce := cast(uint)intrinsics.simd_reduce_min(index_select) + return int(i + index_reduce) } } } } - for /**/; offset < n; offset += 1 { - a := (^byte)(x+offset)^ - if a ~ 0 != 0 { - return -1 if int(a) < 0 else +1 + m = (n-i) / 16 * 16 + for /**/; i < m; i += 16 { + load_a := intrinsics.unaligned_load(cast(^#simd[16]u8)&a[i]) + load_b := intrinsics.unaligned_load(cast(^#simd[16]u8)&b[i]) + comparison := intrinsics.simd_lanes_ne(load_a, load_b) + if intrinsics.simd_reduce_or(comparison) != 0 { + sentinel: #simd[16]u8 = u8(0xFF) + indices := intrinsics.simd_indices(#simd[16]u8) + index_select := intrinsics.simd_select(comparison, indices, sentinel) + index_reduce := cast(uint)intrinsics.simd_reduce_min(index_select) + return int(i + index_reduce) } } - return 0 + // 64-bit SIMD is faster than using a `uintptr` to detect a difference then + // re-iterating with the byte-by-byte loop, at least on AMD64. + m = (n-i) / 8 * 8 + for /**/; i < m; i += 8 { + load_a := intrinsics.unaligned_load(cast(^#simd[8]u8)&a[i]) + load_b := intrinsics.unaligned_load(cast(^#simd[8]u8)&b[i]) + comparison := intrinsics.simd_lanes_ne(load_a, load_b) + if intrinsics.simd_reduce_or(comparison) != 0 { + sentinel: #simd[8]u8 = u8(0xFF) + indices := intrinsics.simd_indices(#simd[8]u8) + index_select := intrinsics.simd_select(comparison, indices, sentinel) + index_reduce := cast(uint)intrinsics.simd_reduce_min(index_select) + return int(i + index_reduce) + } + } + + for /**/; i < n; i += 1 { + if a[i] ~ b[i] != 0 { + return int(i) + } + } + return int(n) } string_eq :: proc "contextless" (lhs, rhs: string) -> bool { diff --git a/core/bytes/bytes.odin b/core/bytes/bytes.odin index c0d25bcce..71b6ef70c 100644 --- a/core/bytes/bytes.odin +++ b/core/bytes/bytes.odin @@ -350,7 +350,7 @@ index_byte :: proc "contextless" (s: []byte, c: byte) -> (index: int) #no_bounds } c_vec: simd.u8x16 = c - when !simd.IS_EMULATED { + when simd.HAS_HARDWARE_SIMD { // Note: While this is something that could also logically take // advantage of AVX512, the various downclocking and power // consumption related woes make premature to have a dedicated @@ -485,7 +485,7 @@ last_index_byte :: proc "contextless" (s: []byte, c: byte) -> int #no_bounds_che } c_vec: simd.u8x16 = c - when !simd.IS_EMULATED { + when simd.HAS_HARDWARE_SIMD { // Note: While this is something that could also logically take // advantage of AVX512, the various downclocking and power // consumption related woes make premature to have a dedicated diff --git a/core/crypto/_aes/hw_intel/api.odin b/core/crypto/_aes/hw_intel/api.odin index 52669cb35..502d56213 100644 --- a/core/crypto/_aes/hw_intel/api.odin +++ b/core/crypto/_aes/hw_intel/api.odin @@ -6,7 +6,7 @@ import "core:sys/info" // is_supported returns true iff hardware accelerated AES // is supported. is_supported :: proc "contextless" () -> bool { - features, ok := info.cpu_features.? + features, ok := info.cpu.features.? if !ok { return false } diff --git a/core/crypto/_chacha20/simd128/chacha20_simd128.odin b/core/crypto/_chacha20/simd128/chacha20_simd128.odin index cf78541d1..4bf40e240 100644 --- a/core/crypto/_chacha20/simd128/chacha20_simd128.odin +++ b/core/crypto/_chacha20/simd128/chacha20_simd128.odin @@ -39,7 +39,7 @@ when ODIN_ARCH == .arm64 || ODIN_ARCH == .arm32 { // Some targets lack runtime feature detection, and will flat out refuse // to load binaries that have unknown instructions. This is distinct from -// `simd.IS_EMULATED` as actually good designs support runtime feature +// `simd.HAS_HARDWARE_SIMD` as actually good designs support runtime feature // detection and that constant establishes a baseline. // // See: @@ -227,7 +227,7 @@ is_performant :: proc "contextless" () -> bool { req_features :: info.CPU_Features{.V} } - features, ok := info.cpu_features.? + features, ok := info.cpu.features.? if !ok { return false } diff --git a/core/crypto/_chacha20/simd256/chacha20_simd256.odin b/core/crypto/_chacha20/simd256/chacha20_simd256.odin index ccb02a947..12fffeb2f 100644 --- a/core/crypto/_chacha20/simd256/chacha20_simd256.odin +++ b/core/crypto/_chacha20/simd256/chacha20_simd256.odin @@ -41,7 +41,7 @@ _VEC_TWO: simd.u64x4 : {2, 0, 2, 0} is_performant :: proc "contextless" () -> bool { req_features :: info.CPU_Features{.avx, .avx2} - features, ok := info.cpu_features.? + features, ok := info.cpu.features.? if !ok { return false } diff --git a/core/crypto/sha2/sha2_impl_hw_intel.odin b/core/crypto/sha2/sha2_impl_hw_intel.odin index f16f353df..cb29a3a20 100644 --- a/core/crypto/sha2/sha2_impl_hw_intel.odin +++ b/core/crypto/sha2/sha2_impl_hw_intel.odin @@ -52,7 +52,7 @@ K_15 :: simd.u64x2{0xa4506ceb90befffa, 0xc67178f2bef9a3f7} // is_hardware_accelerated_256 returns true iff hardware accelerated // SHA-224/SHA-256 is supported. is_hardware_accelerated_256 :: proc "contextless" () -> bool { - features, ok := info.cpu_features.? + features, ok := info.cpu.features.? if !ok { return false } diff --git a/core/encoding/csv/doc.odin b/core/encoding/csv/doc.odin index bfeadafd6..7abe2be49 100644 --- a/core/encoding/csv/doc.odin +++ b/core/encoding/csv/doc.odin @@ -63,8 +63,6 @@ Example: read_csv_from_string :: proc(filename: string) { r: csv.Reader r.trim_leading_space = true - r.reuse_record = true // Without it you have to delete(record) - r.reuse_record_buffer = true // Without it you have to each of the fields within it defer csv.reader_destroy(&r) csv_data, ok := os.read_entire_file(filename) diff --git a/core/encoding/csv/reader.odin b/core/encoding/csv/reader.odin index 5348624d5..577ef219d 100644 --- a/core/encoding/csv/reader.odin +++ b/core/encoding/csv/reader.odin @@ -130,7 +130,7 @@ reader_destroy :: proc(r: ^Reader) { for record, row_idx in csv.iterator_next(&r) { ... } TIP: If you process the results within the loop and don't need to own the results, - you can set the Reader's `reuse_record` and `reuse_record_reuse_record_buffer` to true; + you can set the Reader's `reuse_record` and `reuse_record_buffer` to true; you won't need to delete the record or its fields. */ iterator_next :: proc(r: ^Reader) -> (record: []string, idx: int, err: Error, more: bool) { diff --git a/core/hash/crc32.odin b/core/hash/crc32.odin index a7f68207e..0a4617f6d 100644 --- a/core/hash/crc32.odin +++ b/core/hash/crc32.odin @@ -317,85 +317,4 @@ crc32_table := [8][256]u32{ 0xff6b144a, 0x33c114d4, 0xbd4e1337, 0x71e413a9, 0x7b211ab0, 0xb78b1a2e, 0x39041dcd, 0xf5ae1d53, 0x2c8e0fff, 0xe0240f61, 0x6eab0882, 0xa201081c, 0xa8c40105, 0x646e019b, 0xeae10678, 0x264b06e6, }, -} - - - -/* -@(optimization_mode="speed") -crc32 :: proc "contextless" (data: []byte, seed := u32(0)) -> u32 { - result := ~u32(seed); - #no_bounds_check for b in data { - result = result>>8 ~ _crc32_table[(result ~ u32(b)) & 0xff]; - } - return ~result; -} - - -@private _crc32_table := [256]u32{ - 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, - 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, - 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, - 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, - 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, - 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, - 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, - 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, - 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, - 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, - 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, - 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, - 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, - 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, - 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, - 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, - 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, - 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, - 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, - 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, - 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, - 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, - 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, - 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, - 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, - 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, - 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, - 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, - 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, - 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, - 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, - 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, - 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, - 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, - 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, - 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, - 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, - 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, - 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, - 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, - 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, - 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, - 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, - 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, - 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, - 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, - 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, - 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, - 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, - 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, - 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, - 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, - 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, - 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, - 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, - 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, - 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, - 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, - 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, - 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, - 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, - 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, - 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, - 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d, -}; -*/ +} \ No newline at end of file diff --git a/core/image/png/png.odin b/core/image/png/png.odin index 2d3665e94..3eb56c245 100644 --- a/core/image/png/png.odin +++ b/core/image/png/png.odin @@ -1212,7 +1212,6 @@ Filter_Params :: struct #packed { depth_scale_table :: []u8{0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x01} -// @(optimization_mode="speed") defilter_8 :: proc(params: ^Filter_Params) -> (ok: bool) { using params @@ -1273,7 +1272,6 @@ defilter_8 :: proc(params: ^Filter_Params) -> (ok: bool) { return } -// @(optimization_mode="speed") defilter_less_than_8 :: proc(params: ^Filter_Params) -> bool #no_bounds_check { using params @@ -1436,7 +1434,6 @@ defilter_less_than_8 :: proc(params: ^Filter_Params) -> bool #no_bounds_check { return true } -// @(optimization_mode="speed") defilter_16 :: proc(params: ^Filter_Params) -> bool { using params diff --git a/core/math/big/radix.odin b/core/math/big/radix.odin index a5100e478..a1c25b55e 100644 --- a/core/math/big/radix.odin +++ b/core/math/big/radix.odin @@ -280,7 +280,7 @@ int_atoi :: proc(res: ^Int, input: string, radix := i8(10), allocator := context } pos := ch - '+' - if RADIX_TABLE_REVERSE_SIZE <= pos { + if RADIX_TABLE_REVERSE_SIZE <= u32(pos) { break } y := RADIX_TABLE_REVERSE[pos] diff --git a/core/math/rand/rand.odin b/core/math/rand/rand.odin index 56208931f..ece864f35 100644 --- a/core/math/rand/rand.odin +++ b/core/math/rand/rand.odin @@ -350,7 +350,7 @@ Example: Possible Output: 6 - 500 + 13 */ @(require_results) diff --git a/core/mem/mem.odin b/core/mem/mem.odin index 5789309f7..96ec1990a 100644 --- a/core/mem/mem.odin +++ b/core/mem/mem.odin @@ -315,18 +315,38 @@ check_zero_ptr :: proc(ptr: rawptr, len: int) -> bool { Offset a given pointer by a given amount. This procedure offsets the pointer `ptr` to an object of type `T`, by the amount -of bytes specified by `offset*size_of(T)`, and returns the pointer `ptr`. +of bytes specified by `offset * size_of(T)`, and returns the pointer `ptr`. **Note**: Prefer to use multipointer types, if possible. */ ptr_offset :: intrinsics.ptr_offset /* -Offset a given pointer by a given amount backwards. +Subtract two pointers of the same type, and return the number of `T` between them. -This procedure offsets the pointer `ptr` to an object of type `T`, by the amount -of bytes specified by `offset*size_of(T)` in the negative direction, and -returns the pointer `ptr`. +This procedure subtracts pointer `b` from pointer `a`, both of type `^T`, +and returns an integer count of the `T` between them. + +**Inputs** +- `a`: A pointer to a type T +- `b`: A pointer to a type T + +**Returns** +- `b` - `a` in items of T as an `int`. + +Example: + + import "core:mem" + import "core:fmt" + + ptr_sub_example :: proc() { + arr: [2]int + fmt.println(mem.ptr_sub(&arr[1], &arr[0])) + } + +Output: + + 1 */ ptr_sub :: intrinsics.ptr_sub diff --git a/core/mem/tlsf/tlsf_internal.odin b/core/mem/tlsf/tlsf_internal.odin index 89b875679..460cc4fb6 100644 --- a/core/mem/tlsf/tlsf_internal.odin +++ b/core/mem/tlsf/tlsf_internal.odin @@ -477,7 +477,7 @@ block_mark_as_free :: proc(block: ^Block_Header) { } @(private, no_sanitize_address) -block_mark_as_used :: proc(block: ^Block_Header, ) { +block_mark_as_used :: proc(block: ^Block_Header) { next := block_next(block) block_set_prev_used(next) block_set_used(block) diff --git a/core/simd/simd.odin b/core/simd/simd.odin index a97155f58..b4779b5ff 100644 --- a/core/simd/simd.odin +++ b/core/simd/simd.odin @@ -21,20 +21,17 @@ package simd import "base:builtin" import "base:intrinsics" +import "base:runtime" /* Check if SIMD is software-emulated on a target platform. -This value is `false`, when the compile-time target has the hardware support for -at 128-bit (or wider) SIMD. If the compile-time target lacks the hardware support -for 128-bit SIMD, this value is `true`, and all SIMD operations will likely be +This value is `true`, when the compile-time target has the hardware support for +at least 128-bit (or wider) SIMD. If the compile-time target lacks the hardware support +for 128-bit SIMD, this value is `false`, and all SIMD operations will likely be emulated. */ -IS_EMULATED :: true when (ODIN_ARCH == .amd64 || ODIN_ARCH == .i386) && !intrinsics.has_target_feature("sse2") else - true when (ODIN_ARCH == .arm64 || ODIN_ARCH == .arm32) && !intrinsics.has_target_feature("neon") else - true when (ODIN_ARCH == .wasm64p32 || ODIN_ARCH == .wasm32) && !intrinsics.has_target_feature("simd128") else - true when (ODIN_ARCH == .riscv64) && !intrinsics.has_target_feature("v") else - false +HAS_HARDWARE_SIMD :: runtime.HAS_HARDWARE_SIMD /* Vector of 16 `u8` lanes (128 bits). diff --git a/core/strings/strings.odin b/core/strings/strings.odin index e15754dff..e45b177d7 100644 --- a/core/strings/strings.odin +++ b/core/strings/strings.odin @@ -2,6 +2,7 @@ package strings import "base:intrinsics" +import "base:runtime" import "core:bytes" import "core:io" import "core:mem" @@ -458,6 +459,7 @@ equal_fold :: proc(u, v: string) -> (res: bool) { return s == t } + /* Returns the prefix length common between strings `a` and `b` @@ -488,30 +490,57 @@ Output: 0 */ -prefix_length :: proc(a, b: string) -> (n: int) { - _len := min(len(a), len(b)) +prefix_length :: proc "contextless" (a, b: string) -> (n: int) { + RUNE_ERROR :: '\ufffd' + RUNE_SELF :: 0x80 + UTF_MAX :: 4 - // Scan for matches including partial codepoints. - #no_bounds_check for n < _len && a[n] == b[n] { - n += 1 - } - - // Now scan to ignore partial codepoints. - if n > 0 { - s := a[:n] - n = 0 - for { - r0, w := utf8.decode_rune(s[n:]) - if r0 != utf8.RUNE_ERROR { - n += w - } else { - break + n = runtime.memory_prefix_length(raw_data(a), raw_data(b), min(len(a), len(b))) + lim := max(n - UTF_MAX + 1, 0) + for l := n; l > lim; l -= 1 { + r, _ := runtime.string_decode_rune(a[l - 1:]) + if r != RUNE_ERROR { + if l > 0 && (a[l - 1] & 0xc0 == 0xc0) { + return l - 1 } + return l } } return } /* +Returns the common prefix between strings `a` and `b` + +Inputs: +- a: The first input string +- b: The second input string + +Returns: +- n: The string prefix common between strings `a` and `b` + +Example: + + import "core:fmt" + import "core:strings" + + common_prefix_example :: proc() { + fmt.println(strings.common_prefix("testing", "test")) + fmt.println(strings.common_prefix("testing", "te")) + fmt.println(strings.common_prefix("telephone", "te")) + } + +Output: + + test + te + te + + +*/ +common_prefix :: proc(a, b: string) -> string { + return a[:prefix_length(a, b)] +} +/* Determines if a string `s` starts with a given `prefix` Inputs: diff --git a/core/sys/darwin/Foundation/NSApplication.odin b/core/sys/darwin/Foundation/NSApplication.odin index 7b14d8ebc..cad2ba777 100644 --- a/core/sys/darwin/Foundation/NSApplication.odin +++ b/core/sys/darwin/Foundation/NSApplication.odin @@ -256,7 +256,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem return nil } if template.applicationWillFinishLaunching != nil { - applicationWillFinishLaunching :: proc "c" (self: id, notification: ^Notification) { + applicationWillFinishLaunching :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context del.applicationWillFinishLaunching(notification) @@ -264,7 +264,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("applicationWillFinishLaunching:"), auto_cast applicationWillFinishLaunching, "v@:@") } if template.applicationDidFinishLaunching != nil { - applicationDidFinishLaunching :: proc "c" (self: id, notification: ^Notification) { + applicationDidFinishLaunching :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context del.applicationDidFinishLaunching(notification) @@ -272,7 +272,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("applicationDidFinishLaunching:"), auto_cast applicationDidFinishLaunching, "v@:@") } if template.applicationWillBecomeActive != nil { - applicationWillBecomeActive :: proc "c" (self: id, notification: ^Notification) { + applicationWillBecomeActive :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context del.applicationWillBecomeActive(notification) @@ -280,7 +280,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("applicationWillBecomeActive:"), auto_cast applicationWillBecomeActive, "v@:@") } if template.applicationDidBecomeActive != nil { - applicationDidBecomeActive :: proc "c" (self: id, notification: ^Notification) { + applicationDidBecomeActive :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context del.applicationDidBecomeActive(notification) @@ -288,7 +288,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("applicationDidBecomeActive:"), auto_cast applicationDidBecomeActive, "v@:@") } if template.applicationWillResignActive != nil { - applicationWillResignActive :: proc "c" (self: id, notification: ^Notification) { + applicationWillResignActive :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context del.applicationWillResignActive(notification) @@ -296,7 +296,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("applicationWillResignActive:"), auto_cast applicationWillResignActive, "v@:@") } if template.applicationDidResignActive != nil { - applicationDidResignActive :: proc "c" (self: id, notification: ^Notification) { + applicationDidResignActive :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context del.applicationDidResignActive(notification) @@ -304,7 +304,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("applicationDidResignActive:"), auto_cast applicationDidResignActive, "v@:@") } if template.applicationShouldTerminate != nil { - applicationShouldTerminate :: proc "c" (self: id, sender: ^Application) -> ApplicationTerminateReply { + applicationShouldTerminate :: proc "c" (self: id, cmd: SEL, sender: ^Application) -> ApplicationTerminateReply { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context return del.applicationShouldTerminate(sender) @@ -312,7 +312,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("applicationShouldTerminate:"), auto_cast applicationShouldTerminate, _UINTEGER_ENCODING+"@:@") } if template.applicationShouldTerminateAfterLastWindowClosed != nil { - applicationShouldTerminateAfterLastWindowClosed :: proc "c" (self: id, sender: ^Application) -> BOOL { + applicationShouldTerminateAfterLastWindowClosed :: proc "c" (self: id, cmd: SEL, sender: ^Application) -> BOOL { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context return del.applicationShouldTerminateAfterLastWindowClosed(sender) @@ -320,7 +320,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("applicationShouldTerminateAfterLastWindowClosed:"), auto_cast applicationShouldTerminateAfterLastWindowClosed, "B@:@") } if template.applicationWillTerminate != nil { - applicationWillTerminate :: proc "c" (self: id, notification: ^Notification) { + applicationWillTerminate :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context del.applicationWillTerminate(notification) @@ -328,7 +328,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("applicationWillTerminate:"), auto_cast applicationWillTerminate, "v@:@") } if template.applicationWillHide != nil { - applicationWillHide :: proc "c" (self: id, notification: ^Notification) { + applicationWillHide :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context del.applicationWillHide(notification) @@ -336,7 +336,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("applicationWillHide:"), auto_cast applicationWillHide, "v@:@") } if template.applicationDidHide != nil { - applicationDidHide :: proc "c" (self: id, notification: ^Notification) { + applicationDidHide :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context del.applicationDidHide(notification) @@ -344,7 +344,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("applicationDidHide:"), auto_cast applicationDidHide, "v@:@") } if template.applicationWillUnhide != nil { - applicationWillUnhide :: proc "c" (self: id, notification: ^Notification) { + applicationWillUnhide :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context del.applicationWillUnhide(notification) @@ -352,7 +352,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("applicationWillUnhide:"), auto_cast applicationWillUnhide, "v@:@") } if template.applicationDidUnhide != nil { - applicationDidUnhide :: proc "c" (self: id, notification: ^Notification) { + applicationDidUnhide :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context del.applicationDidUnhide(notification) @@ -360,7 +360,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("applicationDidUnhide:"), auto_cast applicationDidUnhide, "v@:@") } if template.applicationWillUpdate != nil { - applicationWillUpdate :: proc "c" (self: id, notification: ^Notification) { + applicationWillUpdate :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context del.applicationWillUpdate(notification) @@ -368,7 +368,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("applicationWillUpdate:"), auto_cast applicationWillUpdate, "v@:@") } if template.applicationDidUpdate != nil { - applicationDidUpdate :: proc "c" (self: id, notification: ^Notification) { + applicationDidUpdate :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context del.applicationDidUpdate(notification) @@ -376,7 +376,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("applicationDidUpdate:"), auto_cast applicationDidUpdate, "v@:@") } if template.applicationShouldHandleReopenHasVisibleWindows != nil { - applicationShouldHandleReopenHasVisibleWindows :: proc "c" (self: id, sender: ^Application, flag: BOOL) -> BOOL { + applicationShouldHandleReopenHasVisibleWindows :: proc "c" (self: id, cmd: SEL, sender: ^Application, flag: BOOL) -> BOOL { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context return del.applicationShouldHandleReopenHasVisibleWindows(sender, flag) @@ -384,7 +384,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("applicationShouldHandleReopen:hasVisibleWindows:"), auto_cast applicationShouldHandleReopenHasVisibleWindows, "B@:@B") } if template.applicationDockMenu != nil { - applicationDockMenu :: proc "c" (self: id, sender: ^Application) -> ^Menu { + applicationDockMenu :: proc "c" (self: id, cmd: SEL, sender: ^Application) -> ^Menu { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context return del.applicationDockMenu(sender) @@ -392,7 +392,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("applicationDockMenu:"), auto_cast applicationDockMenu, "@@:@") } if template.applicationShouldAutomaticallyLocalizeKeyEquivalents != nil { - applicationShouldAutomaticallyLocalizeKeyEquivalents :: proc "c" (self: id, application: ^Application) -> BOOL { + applicationShouldAutomaticallyLocalizeKeyEquivalents :: proc "c" (self: id, cmd: SEL, application: ^Application) -> BOOL { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context return del.applicationShouldAutomaticallyLocalizeKeyEquivalents(application) @@ -400,7 +400,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("applicationShouldAutomaticallyLocalizeKeyEquivalents:"), auto_cast applicationShouldAutomaticallyLocalizeKeyEquivalents, "B@:@") } if template.applicationWillPresentError != nil { - applicationWillPresentError :: proc "c" (self: id, application: ^Application, error: ^Error) -> ^Error { + applicationWillPresentError :: proc "c" (self: id, cmd: SEL, application: ^Application, error: ^Error) -> ^Error { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context return del.applicationWillPresentError(application, error) @@ -408,7 +408,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("application:willPresentError:"), auto_cast applicationWillPresentError, "@@:@@") } if template.applicationDidChangeScreenParameters != nil { - applicationDidChangeScreenParameters :: proc "c" (self: id, notification: ^Notification) { + applicationDidChangeScreenParameters :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context del.applicationDidChangeScreenParameters(notification) @@ -416,7 +416,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("applicationDidChangeScreenParameters:"), auto_cast applicationDidChangeScreenParameters, "v@:@") } if template.applicationWillContinueUserActivityWithType != nil { - applicationWillContinueUserActivityWithType :: proc "c" (self: id, application: ^Application, userActivityType: ^String) -> BOOL { + applicationWillContinueUserActivityWithType :: proc "c" (self: id, cmd: SEL, application: ^Application, userActivityType: ^String) -> BOOL { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context return del.applicationWillContinueUserActivityWithType(application, userActivityType) @@ -424,7 +424,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("application:willContinueUserActivityWithType:"), auto_cast applicationWillContinueUserActivityWithType, "B@:@@") } if template.applicationContinueUserActivityRestorationHandler != nil { - applicationContinueUserActivityRestorationHandler :: proc "c" (self: id, application: ^Application, userActivity: ^UserActivity, restorationHandler: ^Block) -> BOOL { + applicationContinueUserActivityRestorationHandler :: proc "c" (self: id, cmd: SEL, application: ^Application, userActivity: ^UserActivity, restorationHandler: ^Block) -> BOOL { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context return del.applicationContinueUserActivityRestorationHandler(application, userActivity, restorationHandler) @@ -432,7 +432,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("application:continueUserActivity:restorationHandler:"), auto_cast applicationContinueUserActivityRestorationHandler, "B@:@@?") } if template.applicationDidFailToContinueUserActivityWithTypeError != nil { - applicationDidFailToContinueUserActivityWithTypeError :: proc "c" (self: id, application: ^Application, userActivityType: ^String, error: ^Error) { + applicationDidFailToContinueUserActivityWithTypeError :: proc "c" (self: id, cmd: SEL, application: ^Application, userActivityType: ^String, error: ^Error) { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context del.applicationDidFailToContinueUserActivityWithTypeError(application, userActivityType, error) @@ -440,7 +440,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("application:didFailToContinueUserActivityWithType:error:"), auto_cast applicationDidFailToContinueUserActivityWithTypeError, "v@:@@@") } if template.applicationDidUpdateUserActivity != nil { - applicationDidUpdateUserActivity :: proc "c" (self: id, application: ^Application, userActivity: ^UserActivity) { + applicationDidUpdateUserActivity :: proc "c" (self: id, cmd: SEL, application: ^Application, userActivity: ^UserActivity) { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context del.applicationDidUpdateUserActivity(application, userActivity) @@ -448,7 +448,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("application:didUpdateUserActivity:"), auto_cast applicationDidUpdateUserActivity, "v@:@@") } if template.applicationDidRegisterForRemoteNotificationsWithDeviceToken != nil { - applicationDidRegisterForRemoteNotificationsWithDeviceToken :: proc "c" (self: id, application: ^Application, deviceToken: ^Data) { + applicationDidRegisterForRemoteNotificationsWithDeviceToken :: proc "c" (self: id, cmd: SEL, application: ^Application, deviceToken: ^Data) { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context del.applicationDidRegisterForRemoteNotificationsWithDeviceToken(application, deviceToken) @@ -456,7 +456,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("application:didRegisterForRemoteNotificationsWithDeviceToken:"), auto_cast applicationDidRegisterForRemoteNotificationsWithDeviceToken, "v@:@@") } if template.applicationDidFailToRegisterForRemoteNotificationsWithError != nil { - applicationDidFailToRegisterForRemoteNotificationsWithError :: proc "c" (self: id, application: ^Application, error: ^Error) { + applicationDidFailToRegisterForRemoteNotificationsWithError :: proc "c" (self: id, cmd: SEL, application: ^Application, error: ^Error) { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context del.applicationDidFailToRegisterForRemoteNotificationsWithError(application, error) @@ -464,7 +464,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("application:didFailToRegisterForRemoteNotificationsWithError:"), auto_cast applicationDidFailToRegisterForRemoteNotificationsWithError, "v@:@@") } if template.applicationDidReceiveRemoteNotification != nil { - applicationDidReceiveRemoteNotification :: proc "c" (self: id, application: ^Application, userInfo: ^Dictionary) { + applicationDidReceiveRemoteNotification :: proc "c" (self: id, cmd: SEL, application: ^Application, userInfo: ^Dictionary) { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context del.applicationDidReceiveRemoteNotification(application, userInfo) @@ -472,7 +472,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("application:didReceiveRemoteNotification:"), auto_cast applicationDidReceiveRemoteNotification, "v@:@@") } // if template.applicationUserDidAcceptCloudKitShareWithMetadata != nil { - // applicationUserDidAcceptCloudKitShareWithMetadata :: proc "c" (self: id, application: ^Application, metadata: ^CKShareMetadata) { + // applicationUserDidAcceptCloudKitShareWithMetadata :: proc "c" (self: id, cmd: SEL, application: ^Application, metadata: ^CKShareMetadata) { // del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) // context = del._context // del.applicationUserDidAcceptCloudKitShareWithMetadata(application, metadata) @@ -480,7 +480,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem // class_addMethod(class, intrinsics.objc_find_selector("application:userDidAcceptCloudKitShareWithMetadata:"), auto_cast applicationUserDidAcceptCloudKitShareWithMetadata, "v@:@@") // } // if template.applicationHandlerForIntent != nil { - // applicationHandlerForIntent :: proc "c" (self: id, application: ^Application, intent: ^INIntent) -> id { + // applicationHandlerForIntent :: proc "c" (self: id, cmd: SEL, application: ^Application, intent: ^INIntent) -> id { // del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) // context = del._context // return del.applicationHandlerForIntent(application, intent) @@ -488,7 +488,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem // class_addMethod(class, intrinsics.objc_find_selector("application:handlerForIntent:"), auto_cast applicationHandlerForIntent, "@@:@@") // } if template.applicationOpenURLs != nil { - applicationOpenURLs :: proc "c" (self: id, application: ^Application, urls: ^Array) { + applicationOpenURLs :: proc "c" (self: id, cmd: SEL, application: ^Application, urls: ^Array) { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context del.applicationOpenURLs(application, urls) @@ -496,7 +496,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("application:openURLs:"), auto_cast applicationOpenURLs, "v@:@@") } if template.applicationOpenFile != nil { - applicationOpenFile :: proc "c" (self: id, sender: ^Application, filename: ^String) -> BOOL { + applicationOpenFile :: proc "c" (self: id, cmd: SEL, sender: ^Application, filename: ^String) -> BOOL { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context return del.applicationOpenFile(sender, filename) @@ -504,7 +504,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("application:openFile:"), auto_cast applicationOpenFile, "B@:@@") } if template.applicationOpenFileWithoutUI != nil { - applicationOpenFileWithoutUI :: proc "c" (self: id, sender: id, filename: ^String) -> BOOL { + applicationOpenFileWithoutUI :: proc "c" (self: id, cmd: SEL, sender: id, filename: ^String) -> BOOL { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context return del.applicationOpenFileWithoutUI(sender, filename) @@ -512,7 +512,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("application:openFileWithoutUI:"), auto_cast applicationOpenFileWithoutUI, "B@:@@") } if template.applicationOpenTempFile != nil { - applicationOpenTempFile :: proc "c" (self: id, sender: ^Application, filename: ^String) -> BOOL { + applicationOpenTempFile :: proc "c" (self: id, cmd: SEL, sender: ^Application, filename: ^String) -> BOOL { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context return del.applicationOpenTempFile(sender, filename) @@ -520,7 +520,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("application:openTempFile:"), auto_cast applicationOpenTempFile, "B@:@@") } if template.applicationOpenFiles != nil { - applicationOpenFiles :: proc "c" (self: id, sender: ^Application, filenames: ^Array) { + applicationOpenFiles :: proc "c" (self: id, cmd: SEL, sender: ^Application, filenames: ^Array) { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context del.applicationOpenFiles(sender, filenames) @@ -528,7 +528,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("application:openFiles:"), auto_cast applicationOpenFiles, "v@:@@") } if template.applicationShouldOpenUntitledFile != nil { - applicationShouldOpenUntitledFile :: proc "c" (self: id, sender: ^Application) -> BOOL { + applicationShouldOpenUntitledFile :: proc "c" (self: id, cmd: SEL, sender: ^Application) -> BOOL { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context return del.applicationShouldOpenUntitledFile(sender) @@ -536,7 +536,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("applicationShouldOpenUntitledFile:"), auto_cast applicationShouldOpenUntitledFile, "B@:@") } if template.applicationOpenUntitledFile != nil { - applicationOpenUntitledFile :: proc "c" (self: id, sender: ^Application) -> BOOL { + applicationOpenUntitledFile :: proc "c" (self: id, cmd: SEL, sender: ^Application) -> BOOL { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context return del.applicationOpenUntitledFile(sender) @@ -544,7 +544,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("applicationOpenUntitledFile:"), auto_cast applicationOpenUntitledFile, "B@:@") } if template.applicationPrintFile != nil { - applicationPrintFile :: proc "c" (self: id, sender: ^Application, filename: ^String) -> BOOL { + applicationPrintFile :: proc "c" (self: id, cmd: SEL, sender: ^Application, filename: ^String) -> BOOL { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context return del.applicationPrintFile(sender, filename) @@ -552,7 +552,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("application:printFile:"), auto_cast applicationPrintFile, "B@:@@") } if template.applicationPrintFilesWithSettingsShowPrintPanels != nil { - applicationPrintFilesWithSettingsShowPrintPanels :: proc "c" (self: id, application: ^Application, fileNames: ^Array, printSettings: ^Dictionary, showPrintPanels: BOOL) -> ApplicationPrintReply { + applicationPrintFilesWithSettingsShowPrintPanels :: proc "c" (self: id, cmd: SEL, application: ^Application, fileNames: ^Array, printSettings: ^Dictionary, showPrintPanels: BOOL) -> ApplicationPrintReply { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context return del.applicationPrintFilesWithSettingsShowPrintPanels(application, fileNames, printSettings, showPrintPanels) @@ -560,7 +560,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("application:printFiles:withSettings:showPrintPanels:"), auto_cast applicationPrintFilesWithSettingsShowPrintPanels, _UINTEGER_ENCODING+"@:@@@B") } if template.applicationSupportsSecureRestorableState != nil { - applicationSupportsSecureRestorableState :: proc "c" (self: id, app: ^Application) -> BOOL { + applicationSupportsSecureRestorableState :: proc "c" (self: id, cmd: SEL, app: ^Application) -> BOOL { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context return del.applicationSupportsSecureRestorableState(app) @@ -568,7 +568,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("applicationSupportsSecureRestorableState:"), auto_cast applicationSupportsSecureRestorableState, "B@:@") } if template.applicationProtectedDataDidBecomeAvailable != nil { - applicationProtectedDataDidBecomeAvailable :: proc "c" (self: id, notification: ^Notification) { + applicationProtectedDataDidBecomeAvailable :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context del.applicationProtectedDataDidBecomeAvailable(notification) @@ -576,7 +576,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("applicationProtectedDataDidBecomeAvailable:"), auto_cast applicationProtectedDataDidBecomeAvailable, "v@:@") } if template.applicationProtectedDataWillBecomeUnavailable != nil { - applicationProtectedDataWillBecomeUnavailable :: proc "c" (self: id, notification: ^Notification) { + applicationProtectedDataWillBecomeUnavailable :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context del.applicationProtectedDataWillBecomeUnavailable(notification) @@ -584,7 +584,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("applicationProtectedDataWillBecomeUnavailable:"), auto_cast applicationProtectedDataWillBecomeUnavailable, "v@:@") } if template.applicationWillEncodeRestorableState != nil { - applicationWillEncodeRestorableState :: proc "c" (self: id, app: ^Application, coder: ^Coder) { + applicationWillEncodeRestorableState :: proc "c" (self: id, cmd: SEL, app: ^Application, coder: ^Coder) { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context del.applicationWillEncodeRestorableState(app, coder) @@ -592,7 +592,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("application:willEncodeRestorableState:"), auto_cast applicationWillEncodeRestorableState, "v@:@@") } if template.applicationDidDecodeRestorableState != nil { - applicationDidDecodeRestorableState :: proc "c" (self: id, app: ^Application, coder: ^Coder) { + applicationDidDecodeRestorableState :: proc "c" (self: id, cmd: SEL, app: ^Application, coder: ^Coder) { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context del.applicationDidDecodeRestorableState(app, coder) @@ -600,7 +600,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("application:didDecodeRestorableState:"), auto_cast applicationDidDecodeRestorableState, "v@:@@") } if template.applicationDidChangeOcclusionState != nil { - applicationDidChangeOcclusionState :: proc "c" (self: id, notification: ^Notification) { + applicationDidChangeOcclusionState :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context del.applicationDidChangeOcclusionState(notification) @@ -608,7 +608,7 @@ application_delegate_register_and_alloc :: proc(template: ApplicationDelegateTem class_addMethod(class, intrinsics.objc_find_selector("applicationDidChangeOcclusionState:"), auto_cast applicationDidChangeOcclusionState, "v@:@") } if template.applicationDelegateHandlesKey != nil { - applicationDelegateHandlesKey :: proc "c" (self: id, sender: ^Application, key: ^String) -> BOOL { + applicationDelegateHandlesKey :: proc "c" (self: id, cmd: SEL, sender: ^Application, key: ^String) -> BOOL { del := cast(^_ApplicationDelegateInternal)object_getIndexedIvars(self) context = del._context return del.applicationDelegateHandlesKey(sender, key) diff --git a/core/sys/darwin/Foundation/NSWindow.odin b/core/sys/darwin/Foundation/NSWindow.odin index 57ac2b6f6..f113dd3df 100644 --- a/core/sys/darwin/Foundation/NSWindow.odin +++ b/core/sys/darwin/Foundation/NSWindow.odin @@ -146,7 +146,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla return nil } if template.windowWillPositionSheetUsingRect != nil { - windowWillPositionSheetUsingRect :: proc "c" (self: id, window: ^Window, sheet: ^Window, rect: Rect) -> Rect { + windowWillPositionSheetUsingRect :: proc "c" (self: id, cmd: SEL, window: ^Window, sheet: ^Window, rect: Rect) -> Rect { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context return del.windowWillPositionSheetUsingRect(window, sheet, rect) @@ -154,7 +154,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("window:willPositionSheet:usingRect:"), auto_cast windowWillPositionSheetUsingRect, _RECT_ENCODING+"@:@@"+_RECT_ENCODING) } if template.windowWillBeginSheet != nil { - windowWillBeginSheet :: proc "c" (self: id, notification: ^Notification) { + windowWillBeginSheet :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowWillBeginSheet(notification) @@ -162,7 +162,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowWillBeginSheet:"), auto_cast windowWillBeginSheet, "v@:@") } if template.windowDidEndSheet != nil { - windowDidEndSheet :: proc "c" (self: id, notification: ^Notification) { + windowDidEndSheet :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowDidEndSheet(notification) @@ -170,7 +170,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowDidEndSheet:"), auto_cast windowDidEndSheet, "v@:@") } if template.windowWillResizeToSize != nil { - windowWillResizeToSize :: proc "c" (self: id, sender: ^Window, frameSize: Size) -> Size { + windowWillResizeToSize :: proc "c" (self: id, cmd: SEL, sender: ^Window, frameSize: Size) -> Size { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context return del.windowWillResizeToSize(sender, frameSize) @@ -178,7 +178,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowWillResize:toSize:"), auto_cast windowWillResizeToSize, _SIZE_ENCODING+"@:@"+_SIZE_ENCODING) } if template.windowDidResize != nil { - windowDidResize :: proc "c" (self: id, notification: ^Notification) { + windowDidResize :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowDidResize(notification) @@ -186,7 +186,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowDidResize:"), auto_cast windowDidResize, "v@:@") } if template.windowWillStartLiveResize != nil { - windowWillStartLiveResize :: proc "c" (self: id, notification: ^Notification) { + windowWillStartLiveResize :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowWillStartLiveResize(notification) @@ -194,7 +194,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowWillStartLiveResize:"), auto_cast windowWillStartLiveResize, "v@:@") } if template.windowDidEndLiveResize != nil { - windowDidEndLiveResize :: proc "c" (self: id, notification: ^Notification) { + windowDidEndLiveResize :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowDidEndLiveResize(notification) @@ -202,7 +202,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowDidEndLiveResize:"), auto_cast windowDidEndLiveResize, "v@:@") } if template.windowWillMiniaturize != nil { - windowWillMiniaturize :: proc "c" (self: id, notification: ^Notification) { + windowWillMiniaturize :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowWillMiniaturize(notification) @@ -210,7 +210,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowWillMiniaturize:"), auto_cast windowWillMiniaturize, "v@:@") } if template.windowDidMiniaturize != nil { - windowDidMiniaturize :: proc "c" (self: id, notification: ^Notification) { + windowDidMiniaturize :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowDidMiniaturize(notification) @@ -218,7 +218,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowDidMiniaturize:"), auto_cast windowDidMiniaturize, "v@:@") } if template.windowDidDeminiaturize != nil { - windowDidDeminiaturize :: proc "c" (self: id, notification: ^Notification) { + windowDidDeminiaturize :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowDidDeminiaturize(notification) @@ -226,7 +226,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowDidDeminiaturize:"), auto_cast windowDidDeminiaturize, "v@:@") } if template.windowWillUseStandardFrameDefaultFrame != nil { - windowWillUseStandardFrameDefaultFrame :: proc(self: id, window: ^Window, newFrame: Rect) -> Rect { + windowWillUseStandardFrameDefaultFrame :: proc(self: id, cmd: SEL, window: ^Window, newFrame: Rect) -> Rect { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context return del.windowWillUseStandardFrameDefaultFrame(window, newFrame) @@ -234,7 +234,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowWillUseStandardFrame:defaultFrame:"), auto_cast windowWillUseStandardFrameDefaultFrame, _RECT_ENCODING+"@:@"+_RECT_ENCODING) } if template.windowShouldZoomToFrame != nil { - windowShouldZoomToFrame :: proc "c" (self: id, window: ^Window, newFrame: Rect) -> BOOL { + windowShouldZoomToFrame :: proc "c" (self: id, cmd: SEL, window: ^Window, newFrame: Rect) -> BOOL { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context return del.windowShouldZoomToFrame(window, newFrame) @@ -242,7 +242,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowShouldZoom:toFrame:"), auto_cast windowShouldZoomToFrame, "B@:@"+_RECT_ENCODING) } if template.windowWillUseFullScreenContentSize != nil { - windowWillUseFullScreenContentSize :: proc "c" (self: id, window: ^Window, proposedSize: Size) -> Size { + windowWillUseFullScreenContentSize :: proc "c" (self: id, cmd: SEL, window: ^Window, proposedSize: Size) -> Size { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context return del.windowWillUseFullScreenContentSize(window, proposedSize) @@ -250,7 +250,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("window:willUseFullScreenContentSize:"), auto_cast windowWillUseFullScreenContentSize, _SIZE_ENCODING+"@:@"+_SIZE_ENCODING) } if template.windowWillUseFullScreenPresentationOptions != nil { - windowWillUseFullScreenPresentationOptions :: proc(self: id, window: ^Window, proposedOptions: ApplicationPresentationOptions) -> ApplicationPresentationOptions { + windowWillUseFullScreenPresentationOptions :: proc(self: id, cmd: SEL, window: ^Window, proposedOptions: ApplicationPresentationOptions) -> ApplicationPresentationOptions { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context return del.windowWillUseFullScreenPresentationOptions(window, proposedOptions) @@ -258,7 +258,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("window:willUseFullScreenPresentationOptions:"), auto_cast windowWillUseFullScreenPresentationOptions, _UINTEGER_ENCODING+"@:@"+_UINTEGER_ENCODING) } if template.windowWillEnterFullScreen != nil { - windowWillEnterFullScreen :: proc "c" (self: id, notification: ^Notification) { + windowWillEnterFullScreen :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowWillEnterFullScreen(notification) @@ -266,7 +266,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowWillEnterFullScreen:"), auto_cast windowWillEnterFullScreen, "v@:@") } if template.windowDidEnterFullScreen != nil { - windowDidEnterFullScreen :: proc "c" (self: id, notification: ^Notification) { + windowDidEnterFullScreen :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowDidEnterFullScreen(notification) @@ -274,7 +274,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowDidEnterFullScreen:"), auto_cast windowDidEnterFullScreen, "v@:@") } if template.windowWillExitFullScreen != nil { - windowWillExitFullScreen :: proc "c" (self: id, notification: ^Notification) { + windowWillExitFullScreen :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowWillExitFullScreen(notification) @@ -282,7 +282,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowWillExitFullScreen:"), auto_cast windowWillExitFullScreen, "v@:@") } if template.windowDidExitFullScreen != nil { - windowDidExitFullScreen :: proc "c" (self: id, notification: ^Notification) { + windowDidExitFullScreen :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowDidExitFullScreen(notification) @@ -290,7 +290,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowDidExitFullScreen:"), auto_cast windowDidExitFullScreen, "v@:@") } if template.customWindowsToEnterFullScreenForWindow != nil { - customWindowsToEnterFullScreenForWindow :: proc "c" (self: id, window: ^Window) -> ^Array { + customWindowsToEnterFullScreenForWindow :: proc "c" (self: id, cmd: SEL, window: ^Window) -> ^Array { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context return del.customWindowsToEnterFullScreenForWindow(window) @@ -298,7 +298,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("customWindowsToEnterFullScreenForWindow:"), auto_cast customWindowsToEnterFullScreenForWindow, "@@:@") } if template.customWindowsToEnterFullScreenForWindowOnScreen != nil { - customWindowsToEnterFullScreenForWindowOnScreen :: proc(self: id, window: ^Window, screen: ^Screen) -> ^Array { + customWindowsToEnterFullScreenForWindowOnScreen :: proc(self: id, cmd: SEL, window: ^Window, screen: ^Screen) -> ^Array { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context return del.customWindowsToEnterFullScreenForWindowOnScreen(window, screen) @@ -306,7 +306,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("customWindowsToEnterFullScreenForWindow:onScreen:"), auto_cast customWindowsToEnterFullScreenForWindowOnScreen, "@@:@@") } if template.windowStartCustomAnimationToEnterFullScreenWithDuration != nil { - windowStartCustomAnimationToEnterFullScreenWithDuration :: proc "c" (self: id, window: ^Window, duration: TimeInterval) { + windowStartCustomAnimationToEnterFullScreenWithDuration :: proc "c" (self: id, cmd: SEL, window: ^Window, duration: TimeInterval) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowStartCustomAnimationToEnterFullScreenWithDuration(window, duration) @@ -314,7 +314,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("window:startCustomAnimationToEnterFullScreenWithDuration:"), auto_cast windowStartCustomAnimationToEnterFullScreenWithDuration, "v@:@@") } if template.windowStartCustomAnimationToEnterFullScreenOnScreenWithDuration != nil { - windowStartCustomAnimationToEnterFullScreenOnScreenWithDuration :: proc(self: id, window: ^Window, screen: ^Screen, duration: TimeInterval) { + windowStartCustomAnimationToEnterFullScreenOnScreenWithDuration :: proc(self: id, cmd: SEL, window: ^Window, screen: ^Screen, duration: TimeInterval) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowStartCustomAnimationToEnterFullScreenOnScreenWithDuration(window, screen, duration) @@ -322,7 +322,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("window:startCustomAnimationToEnterFullScreenOnScreen:withDuration:"), auto_cast windowStartCustomAnimationToEnterFullScreenOnScreenWithDuration, "v@:@@d") } if template.windowDidFailToEnterFullScreen != nil { - windowDidFailToEnterFullScreen :: proc "c" (self: id, window: ^Window) { + windowDidFailToEnterFullScreen :: proc "c" (self: id, cmd: SEL, window: ^Window) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowDidFailToEnterFullScreen(window) @@ -330,7 +330,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowDidFailToEnterFullScreen:"), auto_cast windowDidFailToEnterFullScreen, "v@:@") } if template.customWindowsToExitFullScreenForWindow != nil { - customWindowsToExitFullScreenForWindow :: proc "c" (self: id, window: ^Window) -> ^Array { + customWindowsToExitFullScreenForWindow :: proc "c" (self: id, cmd: SEL, window: ^Window) -> ^Array { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context return del.customWindowsToExitFullScreenForWindow(window) @@ -338,7 +338,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("customWindowsToExitFullScreenForWindow:"), auto_cast customWindowsToExitFullScreenForWindow, "@@:@") } if template.windowStartCustomAnimationToExitFullScreenWithDuration != nil { - windowStartCustomAnimationToExitFullScreenWithDuration :: proc "c" (self: id, window: ^Window, duration: TimeInterval) { + windowStartCustomAnimationToExitFullScreenWithDuration :: proc "c" (self: id, cmd: SEL, window: ^Window, duration: TimeInterval) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowStartCustomAnimationToExitFullScreenWithDuration(window, duration) @@ -346,7 +346,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("window:startCustomAnimationToExitFullScreenWithDuration:"), auto_cast windowStartCustomAnimationToExitFullScreenWithDuration, "v@:@d") } if template.windowDidFailToExitFullScreen != nil { - windowDidFailToExitFullScreen :: proc "c" (self: id, window: ^Window) { + windowDidFailToExitFullScreen :: proc "c" (self: id, cmd: SEL, window: ^Window) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowDidFailToExitFullScreen(window) @@ -354,7 +354,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowDidFailToExitFullScreen:"), auto_cast windowDidFailToExitFullScreen, "v@:@") } if template.windowWillMove != nil { - windowWillMove :: proc "c" (self: id, notification: ^Notification) { + windowWillMove :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowWillMove(notification) @@ -362,7 +362,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowWillMove:"), auto_cast windowWillMove, "v@:@") } if template.windowDidMove != nil { - windowDidMove :: proc "c" (self: id, notification: ^Notification) { + windowDidMove :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowDidMove(notification) @@ -370,7 +370,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowDidMove:"), auto_cast windowDidMove, "v@:@") } if template.windowDidChangeScreen != nil { - windowDidChangeScreen :: proc "c" (self: id, notification: ^Notification) { + windowDidChangeScreen :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowDidChangeScreen(notification) @@ -378,7 +378,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowDidChangeScreen:"), auto_cast windowDidChangeScreen, "v@:@") } if template.windowDidChangeScreenProfile != nil { - windowDidChangeScreenProfile :: proc "c" (self: id, notification: ^Notification) { + windowDidChangeScreenProfile :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowDidChangeScreenProfile(notification) @@ -386,7 +386,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowDidChangeScreenProfile:"), auto_cast windowDidChangeScreenProfile, "v@:@") } if template.windowDidChangeBackingProperties != nil { - windowDidChangeBackingProperties :: proc "c" (self: id, notification: ^Notification) { + windowDidChangeBackingProperties :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowDidChangeBackingProperties(notification) @@ -394,7 +394,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowDidChangeBackingProperties:"), auto_cast windowDidChangeBackingProperties, "v@:@") } if template.windowShouldClose != nil { - windowShouldClose :: proc "c" (self:id, sender: ^Window) -> BOOL { + windowShouldClose :: proc "c" (self:id, cmd: SEL, sender: ^Window) -> BOOL { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context return del.windowShouldClose(sender) @@ -402,7 +402,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowShouldClose:"), auto_cast windowShouldClose, "B@:@") } if template.windowWillClose != nil { - windowWillClose :: proc "c" (self:id, notification: ^Notification) { + windowWillClose :: proc "c" (self:id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowWillClose(notification) @@ -410,7 +410,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowWillClose:"), auto_cast windowWillClose, "v@:@") } if template.windowDidBecomeKey != nil { - windowDidBecomeKey :: proc "c" (self: id, notification: ^Notification) { + windowDidBecomeKey :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowDidBecomeKey(notification) @@ -418,7 +418,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowDidBecomeKey:"), auto_cast windowDidBecomeKey, "v@:@") } if template.windowDidResignKey != nil { - windowDidResignKey :: proc "c" (self: id, notification: ^Notification) { + windowDidResignKey :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowDidResignKey(notification) @@ -426,7 +426,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowDidResignKey:"), auto_cast windowDidResignKey, "v@:@") } if template.windowDidBecomeMain != nil { - windowDidBecomeMain :: proc "c" (self: id, notification: ^Notification) { + windowDidBecomeMain :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowDidBecomeMain(notification) @@ -434,7 +434,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowDidBecomeMain:"), auto_cast windowDidBecomeMain, "v@:@") } if template.windowDidResignMain != nil { - windowDidResignMain :: proc "c" (self: id, notification: ^Notification) { + windowDidResignMain :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowDidResignMain(notification) @@ -442,7 +442,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowDidResignMain:"), auto_cast windowDidResignMain, "v@:@") } if template.windowWillReturnFieldEditorToObject != nil { - windowWillReturnFieldEditorToObject :: proc "c" (self:id, sender: ^Window, client: id) -> id { + windowWillReturnFieldEditorToObject :: proc "c" (self:id, cmd: SEL, sender: ^Window, client: id) -> id { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context return del.windowWillReturnFieldEditorToObject(sender, client) @@ -450,7 +450,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowWillReturnFieldEditor:toObject:"), auto_cast windowWillReturnFieldEditorToObject, "@@:@@") } if template.windowDidUpdate != nil { - windowDidUpdate :: proc "c" (self: id, notification: ^Notification) { + windowDidUpdate :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowDidUpdate(notification) @@ -458,7 +458,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowDidUpdate:"), auto_cast windowDidUpdate, "v@:@") } if template.windowDidExpose != nil { - windowDidExpose :: proc "c" (self: id, notification: ^Notification) { + windowDidExpose :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowDidExpose(notification) @@ -466,7 +466,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowDidExpose:"), auto_cast windowDidExpose, "v@:@") } if template.windowDidChangeOcclusionState != nil { - windowDidChangeOcclusionState :: proc "c" (self: id, notification: ^Notification) { + windowDidChangeOcclusionState :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowDidChangeOcclusionState(notification) @@ -474,7 +474,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowDidChangeOcclusionState:"), auto_cast windowDidChangeOcclusionState, "v@:@") } if template.windowShouldDragDocumentWithEventFromWithPasteboard != nil { - windowShouldDragDocumentWithEventFromWithPasteboard :: proc "c" (self: id, window: ^Window, event: ^Event, dragImageLocation: Point, pasteboard: ^Pasteboard) -> BOOL { + windowShouldDragDocumentWithEventFromWithPasteboard :: proc "c" (self: id, cmd: SEL, window: ^Window, event: ^Event, dragImageLocation: Point, pasteboard: ^Pasteboard) -> BOOL { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context return del.windowShouldDragDocumentWithEventFromWithPasteboard(window, event, dragImageLocation, pasteboard) @@ -482,7 +482,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("window:shouldDragDocumentWithEvent:from:withPasteboard:"), auto_cast windowShouldDragDocumentWithEventFromWithPasteboard, "B@:@@"+_POINT_ENCODING+"@") } if template.windowWillReturnUndoManager != nil { - windowWillReturnUndoManager :: proc "c" (self: id, window: ^Window) -> ^UndoManager { + windowWillReturnUndoManager :: proc "c" (self: id, cmd: SEL, window: ^Window) -> ^UndoManager { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context return del.windowWillReturnUndoManager(window) @@ -490,7 +490,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowWillReturnUndoManager:"), auto_cast windowWillReturnUndoManager, "@@:@") } if template.windowShouldPopUpDocumentPathMenu != nil { - windowShouldPopUpDocumentPathMenu :: proc "c" (self: id, window: ^Window, menu: ^Menu) -> BOOL { + windowShouldPopUpDocumentPathMenu :: proc "c" (self: id, cmd: SEL, window: ^Window, menu: ^Menu) -> BOOL { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context return del.windowShouldPopUpDocumentPathMenu(window, menu) @@ -498,7 +498,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("window:shouldPopUpDocumentPathMenu:"), auto_cast windowShouldPopUpDocumentPathMenu, "B@:@@") } if template.windowWillEncodeRestorableState != nil { - windowWillEncodeRestorableState :: proc "c" (self: id, window: ^Window, state: ^Coder) { + windowWillEncodeRestorableState :: proc "c" (self: id, cmd: SEL, window: ^Window, state: ^Coder) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowWillEncodeRestorableState(window, state) @@ -506,7 +506,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("window:willEncodeRestorableState:"), auto_cast windowWillEncodeRestorableState, "v@:@@") } if template.windowDidEncodeRestorableState != nil { - windowDidEncodeRestorableState :: proc "c" (self: id, window: ^Window, state: ^Coder) { + windowDidEncodeRestorableState :: proc "c" (self: id, cmd: SEL, window: ^Window, state: ^Coder) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowDidEncodeRestorableState(window, state) @@ -514,7 +514,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("window:didDecodeRestorableState:"), auto_cast windowDidEncodeRestorableState, "v@:@@") } if template.windowWillResizeForVersionBrowserWithMaxPreferredSizeMaxAllowedSize != nil { - windowWillResizeForVersionBrowserWithMaxPreferredSizeMaxAllowedSize :: proc "c" (self: id, window: ^Window, maxPreferredFrameSize: Size, maxAllowedFrameSize: Size) -> Size { + windowWillResizeForVersionBrowserWithMaxPreferredSizeMaxAllowedSize :: proc "c" (self: id, cmd: SEL, window: ^Window, maxPreferredFrameSize: Size, maxAllowedFrameSize: Size) -> Size { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context return del.windowWillResizeForVersionBrowserWithMaxPreferredSizeMaxAllowedSize(window, maxPreferredFrameSize, maxPreferredFrameSize) @@ -522,7 +522,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("window:willResizeForVersionBrowserWithMaxPreferredSize:maxAllowedSize:"), auto_cast windowWillResizeForVersionBrowserWithMaxPreferredSizeMaxAllowedSize, _SIZE_ENCODING+"@:@"+_SIZE_ENCODING+_SIZE_ENCODING) } if template.windowWillEnterVersionBrowser != nil { - windowWillEnterVersionBrowser :: proc "c" (self: id, notification: ^Notification) { + windowWillEnterVersionBrowser :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowWillEnterVersionBrowser(notification) @@ -530,7 +530,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowWillEnterVersionBrowser:"), auto_cast windowWillEnterVersionBrowser, "v@:@") } if template.windowDidEnterVersionBrowser != nil { - windowDidEnterVersionBrowser :: proc "c" (self: id, notification: ^Notification) { + windowDidEnterVersionBrowser :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowDidEnterVersionBrowser(notification) @@ -538,7 +538,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowDidEnterVersionBrowser:"), auto_cast windowDidEnterVersionBrowser, "v@:@") } if template.windowWillExitVersionBrowser != nil { - windowWillExitVersionBrowser :: proc "c" (self: id, notification: ^Notification) { + windowWillExitVersionBrowser :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowWillExitVersionBrowser(notification) @@ -546,7 +546,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla class_addMethod(class, intrinsics.objc_find_selector("windowWillExitVersionBrowser:"), auto_cast windowWillExitVersionBrowser, "v@:@") } if template.windowDidExitVersionBrowser != nil { - windowDidExitVersionBrowser :: proc "c" (self: id, notification: ^Notification) { + windowDidExitVersionBrowser :: proc "c" (self: id, cmd: SEL, notification: ^Notification) { del := cast(^_WindowDelegateInternal)object_getIndexedIvars(self) context = del._context del.windowDidExitVersionBrowser(notification) @@ -780,4 +780,4 @@ Window_performWindowDragWithEvent :: proc "c" (self: ^Window, event: ^Event) { @(objc_type=Window, objc_name="setToolbar") Window_setToolbar :: proc "c" (self: ^Window, toolbar: ^Toolbar) { msgSend(nil, self, "setToolbar:", toolbar) -} \ No newline at end of file +} diff --git a/core/sys/freebsd/syscalls.odin b/core/sys/freebsd/syscalls.odin index 405d1e47c..96fd9ac3f 100644 --- a/core/sys/freebsd/syscalls.odin +++ b/core/sys/freebsd/syscalls.odin @@ -204,21 +204,21 @@ accept_nil :: proc "contextless" (s: Fd) -> (Fd, Errno) { accept :: proc { accept_T, accept_nil } getsockname_or_peername :: proc "contextless" (s: Fd, sockaddr: ^$T, is_peer: bool) -> Errno { - // sockaddr must contain a valid pointer, or this will segfault because - // we're telling the syscall that there's memory available to write to. - addrlen: socklen_t = size_of(T) + // sockaddr must contain a valid pointer, or this will segfault because + // we're telling the syscall that there's memory available to write to. + addrlen: socklen_t = size_of(T) - result, ok := intrinsics.syscall_bsd( - is_peer ? SYS_getpeername : SYS_getsockname, - cast(uintptr)s, - cast(uintptr)sockaddr, - cast(uintptr)&addrlen) + result, ok := intrinsics.syscall_bsd( + is_peer ? SYS_getpeername : SYS_getsockname, + cast(uintptr)s, + cast(uintptr)sockaddr, + cast(uintptr)&addrlen) - if !ok { - return cast(Errno)result - } + if !ok { + return cast(Errno)result + } - return nil + return nil } // Get name of connected peer diff --git a/core/sys/info/cpu_arm.odin b/core/sys/info/cpu_arm.odin index 960e55a56..8f5143394 100644 --- a/core/sys/info/cpu_arm.odin +++ b/core/sys/info/cpu_arm.odin @@ -40,9 +40,13 @@ CPU_Feature :: enum u64 { } CPU_Features :: distinct bit_set[CPU_Feature; u64] - -cpu_features: Maybe(CPU_Features) -cpu_name: Maybe(string) +CPU :: struct { + name: Maybe(string), + features: Maybe(CPU_Features), + physical_cores: int, + logical_cores: int, +} +cpu: CPU @(private) cpu_name_buf: [128]byte @@ -53,7 +57,7 @@ init_cpu_name :: proc "contextless" () { when ODIN_OS == .Darwin { if unix.sysctlbyname("machdep.cpu.brand_string", &cpu_name_buf) { - cpu_name = string(cstring(rawptr(&cpu_name_buf))) + cpu.name = string(cstring(rawptr(&cpu_name_buf))) generic = false } } @@ -61,10 +65,10 @@ init_cpu_name :: proc "contextless" () { if generic { when ODIN_ARCH == .arm64 { copy(cpu_name_buf[:], "ARM64") - cpu_name = string(cpu_name_buf[:len("ARM64")]) + cpu.name = string(cpu_name_buf[:len("ARM64")]) } else { copy(cpu_name_buf[:], "ARM") - cpu_name = string(cpu_name_buf[:len("ARM")]) + cpu.name = string(cpu_name_buf[:len("ARM")]) } } } diff --git a/core/sys/info/cpu_darwin.odin b/core/sys/info/cpu_darwin.odin new file mode 100644 index 000000000..c4a209f6d --- /dev/null +++ b/core/sys/info/cpu_darwin.odin @@ -0,0 +1,12 @@ +package sysinfo + +import "core:sys/unix" + +@(init, private) +init_cpu_core_count :: proc "contextless" () { + physical, logical: i64 + unix.sysctlbyname("hw.physicalcpu", &physical) + unix.sysctlbyname("hw.logicalcpu", &logical) + cpu.physical_cores = int(physical) + cpu.logical_cores = int(logical) +} diff --git a/core/sys/info/cpu_darwin_arm64.odin b/core/sys/info/cpu_darwin_arm64.odin index ffa60d1cb..aaeef9ad9 100644 --- a/core/sys/info/cpu_darwin_arm64.odin +++ b/core/sys/info/cpu_darwin_arm64.odin @@ -5,7 +5,7 @@ import "core:sys/unix" @(init, private) init_cpu_features :: proc "contextless" () { @(static) features: CPU_Features - defer cpu_features = features + defer cpu.features = features try_set :: proc "contextless" (name: cstring, feature: CPU_Feature) -> (ok: bool) { support: b32 diff --git a/core/sys/info/cpu_intel.odin b/core/sys/info/cpu_intel.odin index c8b8282fe..7c5b38ca4 100644 --- a/core/sys/info/cpu_intel.odin +++ b/core/sys/info/cpu_intel.odin @@ -3,12 +3,6 @@ package sysinfo import "base:intrinsics" -// cpuid :: proc(ax, cx: u32) -> (eax, ebc, ecx, edx: u32) --- -cpuid :: intrinsics.x86_cpuid - -// xgetbv :: proc(cx: u32) -> (eax, edx: u32) --- -xgetbv :: intrinsics.x86_xgetbv - CPU_Feature :: enum u64 { aes, // AES hardware implementation (AES NI) adx, // Multi-precision add-carry instruction extensions @@ -49,9 +43,13 @@ CPU_Feature :: enum u64 { } CPU_Features :: distinct bit_set[CPU_Feature; u64] - -cpu_features: Maybe(CPU_Features) -cpu_name: Maybe(string) +CPU :: struct { + name: Maybe(string), + features: Maybe(CPU_Features), + physical_cores: int, // Initialized by cpu_.odin + logical_cores: int, // Initialized by cpu_.odin +} +cpu: CPU @(init, private) init_cpu_features :: proc "c" () { @@ -88,7 +86,7 @@ init_cpu_features :: proc "c" () { when ODIN_OS == .FreeBSD || ODIN_OS == .OpenBSD || ODIN_OS == .NetBSD { // xgetbv is an illegal instruction under FreeBSD 13, OpenBSD 7.1 and NetBSD 10 // return before probing further - cpu_features = set + cpu.features = set return } @@ -151,7 +149,7 @@ init_cpu_features :: proc "c" () { try_set(&set, .rdseed, 18, ebx7) try_set(&set, .adx, 19, ebx7) - cpu_features = set + cpu.features = set } @(private) @@ -179,5 +177,11 @@ init_cpu_name :: proc "c" () { for len(brand) > 0 && brand[len(brand) - 1] == 0 || brand[len(brand) - 1] == ' ' { brand = brand[:len(brand) - 1] } - cpu_name = brand + cpu.name = brand } + +// cpuid :: proc(ax, cx: u32) -> (eax, ebc, ecx, edx: u32) --- +cpuid :: intrinsics.x86_cpuid + +// xgetbv :: proc(cx: u32) -> (eax, edx: u32) --- +xgetbv :: intrinsics.x86_xgetbv \ No newline at end of file diff --git a/core/sys/info/cpu_linux_arm.odin b/core/sys/info/cpu_linux_arm.odin index 6408decb7..cde76a83d 100644 --- a/core/sys/info/cpu_linux_arm.odin +++ b/core/sys/info/cpu_linux_arm.odin @@ -17,7 +17,7 @@ init_cpu_features :: proc() { if rerr != .NONE || n == 0 { return } features: CPU_Features - defer cpu_features = features + defer cpu.features = features str := string(buf[:n]) for line in strings.split_lines_iterator(&str) { diff --git a/core/sys/info/cpu_linux_intel.odin b/core/sys/info/cpu_linux_intel.odin new file mode 100644 index 000000000..e43737475 --- /dev/null +++ b/core/sys/info/cpu_linux_intel.odin @@ -0,0 +1,38 @@ +#+build i386, amd64 +#+build linux +package sysinfo + +import "core:sys/linux" +import "core:strings" +import "core:strconv" + +@(init, private) +init_cpu_core_count :: proc() { + fd, err := linux.open("/proc/cpuinfo", {}) + if err != .NONE { return } + defer linux.close(fd) + + // This is probably enough right? + buf: [4096]byte + n, rerr := linux.read(fd, buf[:]) + if rerr != .NONE || n == 0 { return } + + str := string(buf[:n]) + for line in strings.split_lines_iterator(&str) { + key, _, value := strings.partition(line, ":") + key = strings.trim_space(key) + value = strings.trim_space(value) + + if key == "cpu cores" { + if num_physical_cores, ok := strconv.parse_int(value); ok { + cpu.physical_cores = num_physical_cores + } + } + + if key == "siblings" { + if num_logical_cores, ok := strconv.parse_int(value); ok { + cpu.logical_cores = num_logical_cores + } + } + } +} \ No newline at end of file diff --git a/core/sys/info/cpu_linux_riscv64.odin b/core/sys/info/cpu_linux_riscv64.odin index 84f6134d4..3d36d126d 100644 --- a/core/sys/info/cpu_linux_riscv64.odin +++ b/core/sys/info/cpu_linux_riscv64.odin @@ -9,7 +9,7 @@ import "core:sys/linux" @(init, private) init_cpu_features :: proc() { _features: CPU_Features - defer cpu_features = _features + defer cpu.features = _features HWCAP_Bits :: enum u64 { I = 'I' - 'A', @@ -109,5 +109,5 @@ init_cpu_features :: proc() { @(init, private) init_cpu_name :: proc() { - cpu_name = "RISCV64" + cpu.name = "RISCV64" } diff --git a/core/sys/info/cpu_riscv64.odin b/core/sys/info/cpu_riscv64.odin index c3319c48c..64f2edfd3 100644 --- a/core/sys/info/cpu_riscv64.odin +++ b/core/sys/info/cpu_riscv64.odin @@ -95,6 +95,10 @@ CPU_Feature :: enum u64 { } CPU_Features :: distinct bit_set[CPU_Feature; u64] - -cpu_features: Maybe(CPU_Features) -cpu_name: Maybe(string) +CPU :: struct { + name: Maybe(string), + features: Maybe(CPU_Features), + physical_cores: int, + logical_cores: int, +} +cpu: CPU \ No newline at end of file diff --git a/core/sys/info/cpu_windows.odin b/core/sys/info/cpu_windows.odin new file mode 100644 index 000000000..7dd2d2a8c --- /dev/null +++ b/core/sys/info/cpu_windows.odin @@ -0,0 +1,28 @@ +package sysinfo + +import sys "core:sys/windows" +import "base:intrinsics" + +@(init, private) +init_cpu_core_count :: proc() { + infos: []sys.SYSTEM_LOGICAL_PROCESSOR_INFORMATION + defer delete(infos) + + returned_length: sys.DWORD + // Query for the required buffer size. + if ok := sys.GetLogicalProcessorInformation(raw_data(infos), &returned_length); !ok { + infos = make([]sys.SYSTEM_LOGICAL_PROCESSOR_INFORMATION, returned_length / size_of(sys.SYSTEM_LOGICAL_PROCESSOR_INFORMATION)) + } + + // If it still doesn't work, return + if ok := sys.GetLogicalProcessorInformation(raw_data(infos), &returned_length); !ok { + return + } + + for info in infos { + #partial switch info.Relationship { + case .RelationProcessorCore: cpu.physical_cores += 1 + case .RelationNumaNode: cpu.logical_cores += int(intrinsics.count_ones(info.ProcessorMask)) + } + } +} \ No newline at end of file diff --git a/core/sys/info/doc.odin b/core/sys/info/doc.odin index 2fd34b864..aef444f98 100644 --- a/core/sys/info/doc.odin +++ b/core/sys/info/doc.odin @@ -26,13 +26,15 @@ Example: import si "core:sys/info" main :: proc() { - fmt.printfln("Odin: %v", ODIN_VERSION) - fmt.printfln("OS: %v", si.os_version.as_string) - fmt.printfln("OS: %#v", si.os_version) - fmt.printfln("CPU: %v", si.cpu_name) - fmt.printfln("RAM: %#.1M", si.ram.total_ram) + fmt.printfln("Odin: %v", ODIN_VERSION) + fmt.printfln("OS: %v", si.os_version.as_string) + fmt.printfln("OS: %#v", si.os_version) + fmt.printfln("CPU: %v", si.cpu.name) + fmt.printfln("CPU: %v", si.cpu.name) + fmt.printfln("CPU cores: %vc/%vt", si.cpu.physical_cores, si.cpu.logical_cores) + fmt.printfln("RAM: %#.1M", si.ram.total_ram) - // fmt.printfln("Features: %v", si.cpu_features) + // fmt.printfln("Features: %v", si.cpu.features) // fmt.printfln("MacOS version: %v", si.macos_version) fmt.println() diff --git a/core/sys/posix/signal.odin b/core/sys/posix/signal.odin index d2f737946..882cd9fa8 100644 --- a/core/sys/posix/signal.odin +++ b/core/sys/posix/signal.odin @@ -50,7 +50,7 @@ foreign lib { /* Send a signal to a thread. - + As with kill, if sig is 0, only validation (of the pthread_t given) is done and no signal is sent. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_kill.html ]] @@ -124,7 +124,7 @@ foreign lib { sigignore :: proc(sig: Signal) -> result --- /* - Removes sig from the signal mask of the calling process and suspend the calling process until + Removes sig from the signal mask of the calling process and suspend the calling process until a signal is received. [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/sighold.html ]] @@ -166,7 +166,7 @@ foreign lib { [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigpending.html ]] */ @(link_name=LSIGPENDING) - sigpending :: proc(set: ^sigset_t) -> result --- + sigpending :: proc(set: ^sigset_t) -> result --- /* Wait for one of the given signals. @@ -333,7 +333,7 @@ SS_Flag_Bits :: enum c.int { SS_Flags :: bit_set[SS_Flag_Bits; c.int] Sig :: enum c.int { - // Resulting set is the union of the current set and the signal set and the complement of + // Resulting set is the union of the current set and the signal set and the complement of // the signal set pointed to by the argument. BLOCK = SIG_BLOCK, // Resulting set is the intersection of the current set and the complement of the signal set @@ -395,6 +395,7 @@ when ODIN_OS == .Darwin { SIGXFSZ :: 25 SIGVTALRM :: 26 SIGPROF :: 27 + SIGWINCH :: 28 SIGUSR1 :: 30 SIGUSR2 :: 31 @@ -535,6 +536,7 @@ when ODIN_OS == .Darwin { SIGXFSZ :: 25 SIGVTALRM :: 26 SIGPROF :: 27 + SIGWINCH :: 28 SIGUSR1 :: 30 SIGUSR2 :: 31 @@ -699,6 +701,7 @@ when ODIN_OS == .Darwin { SIGXFSZ :: 25 SIGVTALRM :: 26 SIGPROF :: 27 + SIGWINCH :: 28 SIGUSR1 :: 30 SIGUSR2 :: 31 @@ -876,6 +879,7 @@ when ODIN_OS == .Darwin { SIGXFSZ :: 25 SIGVTALRM :: 26 SIGPROF :: 27 + SIGWINCH :: 28 SIGUSR1 :: 30 SIGUSR2 :: 31 @@ -1036,6 +1040,7 @@ when ODIN_OS == .Darwin { SIGXFSZ :: 25 SIGVTALRM :: 26 SIGPROF :: 27 + SIGWINCH :: 28 SIGPOLL :: 29 SIGSYS :: 31 @@ -1084,7 +1089,7 @@ when ODIN_OS == .Darwin { @(private) __SI_MAX_SIZE :: 128 - when size_of(int) == 8 { + when size_of(int) == 8 { @(private) _pad0 :: struct { _pad0: c.int, diff --git a/core/sys/wasm/js/odin.js b/core/sys/wasm/js/odin.js index d5faa5210..37a57a59d 100644 --- a/core/sys/wasm/js/odin.js +++ b/core/sys/wasm/js/odin.js @@ -110,16 +110,12 @@ class WasmMemoryInterface { } loadCstring(ptr) { - return this.loadCstringDirect(this.loadPtr(ptr)); - } - - loadCstringDirect(start) { - if (start == 0) { + if (ptr == 0) { return null; } let len = 0; - for (; this.mem.getUint8(start+len) != 0; len += 1) {} - return this.loadString(start, len); + for (; this.mem.getUint8(ptr+len) != 0; len += 1) {} + return this.loadString(ptr, len); } storeU8(addr, value) { this.mem.setUint8 (addr, value); } diff --git a/core/sys/windows/kernel32.odin b/core/sys/windows/kernel32.odin index 266dcdbf4..ed32c7a9f 100644 --- a/core/sys/windows/kernel32.odin +++ b/core/sys/windows/kernel32.odin @@ -857,7 +857,6 @@ MEMORY_RESOURCE_NOTIFICATION_TYPE :: enum c_int { LowMemoryResourceNotification :: MEMORY_RESOURCE_NOTIFICATION_TYPE.LowMemoryResourceNotification HighMemoryResourceNotification :: MEMORY_RESOURCE_NOTIFICATION_TYPE.HighMemoryResourceNotification - @(default_calling_convention="system") foreign kernel32 { CreateMemoryResourceNotification :: proc( @@ -1194,7 +1193,7 @@ DUMMYUNIONNAME_u :: struct #raw_union { SYSTEM_LOGICAL_PROCESSOR_INFORMATION :: struct { ProcessorMask: ULONG_PTR, Relationship: LOGICAL_PROCESSOR_RELATIONSHIP, - DummyUnion: DUMMYUNIONNAME_u, + using DummyUnion: DUMMYUNIONNAME_u, } SYSTEM_POWER_STATUS :: struct { diff --git a/core/sys/windows/ole32.odin b/core/sys/windows/ole32.odin index 8535a6f87..7409d40dc 100644 --- a/core/sys/windows/ole32.odin +++ b/core/sys/windows/ole32.odin @@ -52,6 +52,8 @@ foreign Ole32 { ppv: ^LPVOID, ) -> HRESULT --- + CoTaskMemAlloc :: proc(cb: SIZE_T) -> rawptr --- + CoTaskMemRealloc :: proc(pv: rawptr, cb: SIZE_T) -> rawptr --- CoTaskMemFree :: proc(pv: rawptr) --- CLSIDFromProgID :: proc(lpszProgID: LPCOLESTR, lpclsid: LPCLSID) -> HRESULT --- diff --git a/core/sys/windows/winerror.odin b/core/sys/windows/winerror.odin index 61a7d9d86..05ab3d028 100644 --- a/core/sys/windows/winerror.odin +++ b/core/sys/windows/winerror.odin @@ -173,6 +173,9 @@ FACILITY :: enum DWORD { EAS = 85, WEB = 885, WEB_SOCKET = 886, + XAUDIO2 = 896, + XAPO = 897, + GAMEINPUT = 906, MOBILE = 1793, SQLITE = 1967, SERVICE_FABRIC = 1968, @@ -231,6 +234,7 @@ ERROR_PIPE_BUSY : DWORD : 231 // https://learn.microsoft.com/en-us/windows/win32/seccrypto/common-hresult-values S_OK :: 0x00000000 // Operation successful +S_FALSE :: 0x00000001 E_NOTIMPL :: 0x80004001 // Not implemented E_NOINTERFACE :: 0x80004002 // No such interface supported E_POINTER :: 0x80004003 // Pointer that is not valid @@ -270,6 +274,10 @@ MAKE_HRESULT :: #force_inline proc "contextless" (#any_int sev: int, #any_int fa return HRESULT((uint(sev)<<31) | (uint(fac)<<16) | (uint(code))) } +HRESULT_FROM_WIN32 :: #force_inline proc "contextless" (#any_int code: int) -> HRESULT { + return HRESULT(code) <= 0 ? HRESULT(code) : HRESULT(uint(code & 0x0000FFFF) | (uint(FACILITY.WIN32) << 16) | 0x80000000) +} + DECODE_HRESULT :: #force_inline proc "contextless" (#any_int hr: int) -> (SEVERITY, FACILITY, int) { return HRESULT_SEVERITY(hr), HRESULT_FACILITY(hr), HRESULT_CODE(hr) } diff --git a/core/sys/windows/winmm.odin b/core/sys/windows/winmm.odin index 3c7ec80e7..204ab99c8 100644 --- a/core/sys/windows/winmm.odin +++ b/core/sys/windows/winmm.odin @@ -265,7 +265,7 @@ HWAVE :: distinct HANDLE HWAVEIN :: distinct HANDLE HWAVEOUT :: distinct HANDLE -LPHWAVEIN :: ^HWAVEIN +LPHWAVEIN :: ^HWAVEIN LPHWAVEOUT :: ^HWAVEOUT // https://learn.microsoft.com/en-us/windows/win32/multimedia/multimedia-timer-structures @@ -311,9 +311,284 @@ MAXPNAMELEN :: 32 MAXERRORLENGTH :: 256 MMVERSION :: UINT +// Input is four characters string +// Output is little-endian u32 representation +MAKEFOURCC :: #force_inline proc "contextless" (s: [4]byte) -> DWORD { + return (DWORD(s[0])) | (DWORD(s[1]) << 8) | (DWORD(s[2]) << 16) | (DWORD(s[3]) << 24 ) +} + /* flags for wFormatTag field of WAVEFORMAT */ WAVE_FORMAT_PCM :: 1 +WAVE_FORMAT_UNKNOWN :: 0x0000 /* Microsoft Corporation */ +WAVE_FORMAT_ADPCM :: 0x0002 /* Microsoft Corporation */ +WAVE_FORMAT_IEEE_FLOAT :: 0x0003 /* Microsoft Corporation */ +WAVE_FORMAT_VSELP :: 0x0004 /* Compaq Computer Corp. */ +WAVE_FORMAT_IBM_CVSD :: 0x0005 /* IBM Corporation */ +WAVE_FORMAT_ALAW :: 0x0006 /* Microsoft Corporation */ +WAVE_FORMAT_MULAW :: 0x0007 /* Microsoft Corporation */ +WAVE_FORMAT_DTS :: 0x0008 /* Microsoft Corporation */ +WAVE_FORMAT_DRM :: 0x0009 /* Microsoft Corporation */ +WAVE_FORMAT_WMAVOICE9 :: 0x000A /* Microsoft Corporation */ +WAVE_FORMAT_WMAVOICE10 :: 0x000B /* Microsoft Corporation */ +WAVE_FORMAT_OKI_ADPCM :: 0x0010 /* OKI */ +WAVE_FORMAT_DVI_ADPCM :: 0x0011 /* Intel Corporation */ +WAVE_FORMAT_IMA_ADPCM :: WAVE_FORMAT_DVI_ADPCM /* Intel Corporation */ +WAVE_FORMAT_MEDIASPACE_ADPCM :: 0x0012 /* Videologic */ +WAVE_FORMAT_SIERRA_ADPCM :: 0x0013 /* Sierra Semiconductor Corp */ +WAVE_FORMAT_G723_ADPCM :: 0x0014 /* Antex Electronics Corporation */ +WAVE_FORMAT_DIGISTD :: 0x0015 /* DSP Solutions, Inc. */ +WAVE_FORMAT_DIGIFIX :: 0x0016 /* DSP Solutions, Inc. */ +WAVE_FORMAT_DIALOGIC_OKI_ADPCM :: 0x0017 /* Dialogic Corporation */ +WAVE_FORMAT_MEDIAVISION_ADPCM :: 0x0018 /* Media Vision, Inc. */ +WAVE_FORMAT_CU_CODEC :: 0x0019 /* Hewlett-Packard Company */ +WAVE_FORMAT_HP_DYN_VOICE :: 0x001A /* Hewlett-Packard Company */ +WAVE_FORMAT_YAMAHA_ADPCM :: 0x0020 /* Yamaha Corporation of America */ +WAVE_FORMAT_SONARC :: 0x0021 /* Speech Compression */ +WAVE_FORMAT_DSPGROUP_TRUESPEECH :: 0x0022 /* DSP Group, Inc */ +WAVE_FORMAT_ECHOSC1 :: 0x0023 /* Echo Speech Corporation */ +WAVE_FORMAT_AUDIOFILE_AF36 :: 0x0024 /* Virtual Music, Inc. */ +WAVE_FORMAT_APTX :: 0x0025 /* Audio Processing Technology */ +WAVE_FORMAT_AUDIOFILE_AF10 :: 0x0026 /* Virtual Music, Inc. */ +WAVE_FORMAT_PROSODY_1612 :: 0x0027 /* Aculab plc */ +WAVE_FORMAT_LRC :: 0x0028 /* Merging Technologies S.A. */ +WAVE_FORMAT_DOLBY_AC2 :: 0x0030 /* Dolby Laboratories */ +WAVE_FORMAT_GSM610 :: 0x0031 /* Microsoft Corporation */ +WAVE_FORMAT_MSNAUDIO :: 0x0032 /* Microsoft Corporation */ +WAVE_FORMAT_ANTEX_ADPCME :: 0x0033 /* Antex Electronics Corporation */ +WAVE_FORMAT_CONTROL_RES_VQLPC :: 0x0034 /* Control Resources Limited */ +WAVE_FORMAT_DIGIREAL :: 0x0035 /* DSP Solutions, Inc. */ +WAVE_FORMAT_DIGIADPCM :: 0x0036 /* DSP Solutions, Inc. */ +WAVE_FORMAT_CONTROL_RES_CR10 :: 0x0037 /* Control Resources Limited */ +WAVE_FORMAT_NMS_VBXADPCM :: 0x0038 /* Natural MicroSystems */ +WAVE_FORMAT_CS_IMAADPCM :: 0x0039 /* Crystal Semiconductor IMA ADPCM */ +WAVE_FORMAT_ECHOSC3 :: 0x003A /* Echo Speech Corporation */ +WAVE_FORMAT_ROCKWELL_ADPCM :: 0x003B /* Rockwell International */ +WAVE_FORMAT_ROCKWELL_DIGITALK :: 0x003C /* Rockwell International */ +WAVE_FORMAT_XEBEC :: 0x003D /* Xebec Multimedia Solutions Limited */ +WAVE_FORMAT_G721_ADPCM :: 0x0040 /* Antex Electronics Corporation */ +WAVE_FORMAT_G728_CELP :: 0x0041 /* Antex Electronics Corporation */ +WAVE_FORMAT_MSG723 :: 0x0042 /* Microsoft Corporation */ +WAVE_FORMAT_INTEL_G723_1 :: 0x0043 /* Intel Corp. */ +WAVE_FORMAT_INTEL_G729 :: 0x0044 /* Intel Corp. */ +WAVE_FORMAT_SHARP_G726 :: 0x0045 /* Sharp */ +WAVE_FORMAT_MPEG :: 0x0050 /* Microsoft Corporation */ +WAVE_FORMAT_RT24 :: 0x0052 /* InSoft, Inc. */ +WAVE_FORMAT_PAC :: 0x0053 /* InSoft, Inc. */ +WAVE_FORMAT_MPEGLAYER3 :: 0x0055 /* ISO/MPEG Layer3 Format Tag */ +WAVE_FORMAT_LUCENT_G723 :: 0x0059 /* Lucent Technologies */ +WAVE_FORMAT_CIRRUS :: 0x0060 /* Cirrus Logic */ +WAVE_FORMAT_ESPCM :: 0x0061 /* ESS Technology */ +WAVE_FORMAT_VOXWARE :: 0x0062 /* Voxware Inc */ +WAVE_FORMAT_CANOPUS_ATRAC :: 0x0063 /* Canopus, co., Ltd. */ +WAVE_FORMAT_G726_ADPCM :: 0x0064 /* APICOM */ +WAVE_FORMAT_G722_ADPCM :: 0x0065 /* APICOM */ +WAVE_FORMAT_DSAT :: 0x0066 /* Microsoft Corporation */ +WAVE_FORMAT_DSAT_DISPLAY :: 0x0067 /* Microsoft Corporation */ +WAVE_FORMAT_VOXWARE_BYTE_ALIGNED :: 0x0069 /* Voxware Inc */ +WAVE_FORMAT_VOXWARE_AC8 :: 0x0070 /* Voxware Inc */ +WAVE_FORMAT_VOXWARE_AC10 :: 0x0071 /* Voxware Inc */ +WAVE_FORMAT_VOXWARE_AC16 :: 0x0072 /* Voxware Inc */ +WAVE_FORMAT_VOXWARE_AC20 :: 0x0073 /* Voxware Inc */ +WAVE_FORMAT_VOXWARE_RT24 :: 0x0074 /* Voxware Inc */ +WAVE_FORMAT_VOXWARE_RT29 :: 0x0075 /* Voxware Inc */ +WAVE_FORMAT_VOXWARE_RT29HW :: 0x0076 /* Voxware Inc */ +WAVE_FORMAT_VOXWARE_VR12 :: 0x0077 /* Voxware Inc */ +WAVE_FORMAT_VOXWARE_VR18 :: 0x0078 /* Voxware Inc */ +WAVE_FORMAT_VOXWARE_TQ40 :: 0x0079 /* Voxware Inc */ +WAVE_FORMAT_VOXWARE_SC3 :: 0x007A /* Voxware Inc */ +WAVE_FORMAT_VOXWARE_SC3_1 :: 0x007B /* Voxware Inc */ +WAVE_FORMAT_SOFTSOUND :: 0x0080 /* Softsound, Ltd. */ +WAVE_FORMAT_VOXWARE_TQ60 :: 0x0081 /* Voxware Inc */ +WAVE_FORMAT_MSRT24 :: 0x0082 /* Microsoft Corporation */ +WAVE_FORMAT_G729A :: 0x0083 /* AT&T Labs, Inc. */ +WAVE_FORMAT_MVI_MVI2 :: 0x0084 /* Motion Pixels */ +WAVE_FORMAT_DF_G726 :: 0x0085 /* DataFusion Systems (Pty) (Ltd) */ +WAVE_FORMAT_DF_GSM610 :: 0x0086 /* DataFusion Systems (Pty) (Ltd) */ +WAVE_FORMAT_ISIAUDIO :: 0x0088 /* Iterated Systems, Inc. */ +WAVE_FORMAT_ONLIVE :: 0x0089 /* OnLive! Technologies, Inc. */ +WAVE_FORMAT_MULTITUDE_FT_SX20 :: 0x008A /* Multitude Inc. */ +WAVE_FORMAT_INFOCOM_ITS_G721_ADPCM :: 0x008B /* Infocom */ +WAVE_FORMAT_CONVEDIA_G729 :: 0x008C /* Convedia Corp. */ +WAVE_FORMAT_CONGRUENCY :: 0x008D /* Congruency Inc. */ +WAVE_FORMAT_SBC24 :: 0x0091 /* Siemens Business Communications Sys */ +WAVE_FORMAT_DOLBY_AC3_SPDIF :: 0x0092 /* Sonic Foundry */ +WAVE_FORMAT_MEDIASONIC_G723 :: 0x0093 /* MediaSonic */ +WAVE_FORMAT_PROSODY_8KBPS :: 0x0094 /* Aculab plc */ +WAVE_FORMAT_ZYXEL_ADPCM :: 0x0097 /* ZyXEL Communications, Inc. */ +WAVE_FORMAT_PHILIPS_LPCBB :: 0x0098 /* Philips Speech Processing */ +WAVE_FORMAT_PACKED :: 0x0099 /* Studer Professional Audio AG */ +WAVE_FORMAT_MALDEN_PHONYTALK :: 0x00A0 /* Malden Electronics Ltd. */ +WAVE_FORMAT_RACAL_RECORDER_GSM :: 0x00A1 /* Racal recorders */ +WAVE_FORMAT_RACAL_RECORDER_G720_A :: 0x00A2 /* Racal recorders */ +WAVE_FORMAT_RACAL_RECORDER_G723_1 :: 0x00A3 /* Racal recorders */ +WAVE_FORMAT_RACAL_RECORDER_TETRA_ACELP :: 0x00A4 /* Racal recorders */ +WAVE_FORMAT_NEC_AAC :: 0x00B0 /* NEC Corp. */ +WAVE_FORMAT_RAW_AAC1 :: 0x00FF /* For Raw AAC, with format block AudioSpecificConfig() (as defined by MPEG-4), that follows WAVEFORMATEX */ +WAVE_FORMAT_RHETOREX_ADPCM :: 0x0100 /* Rhetorex Inc. */ +WAVE_FORMAT_IRAT :: 0x0101 /* BeCubed Software Inc. */ +WAVE_FORMAT_VIVO_G723 :: 0x0111 /* Vivo Software */ +WAVE_FORMAT_VIVO_SIREN :: 0x0112 /* Vivo Software */ +WAVE_FORMAT_PHILIPS_CELP :: 0x0120 /* Philips Speech Processing */ +WAVE_FORMAT_PHILIPS_GRUNDIG :: 0x0121 /* Philips Speech Processing */ +WAVE_FORMAT_DIGITAL_G723 :: 0x0123 /* Digital Equipment Corporation */ +WAVE_FORMAT_SANYO_LD_ADPCM :: 0x0125 /* Sanyo Electric Co., Ltd. */ +WAVE_FORMAT_SIPROLAB_ACEPLNET :: 0x0130 /* Sipro Lab Telecom Inc. */ +WAVE_FORMAT_SIPROLAB_ACELP4800 :: 0x0131 /* Sipro Lab Telecom Inc. */ +WAVE_FORMAT_SIPROLAB_ACELP8V3 :: 0x0132 /* Sipro Lab Telecom Inc. */ +WAVE_FORMAT_SIPROLAB_G729 :: 0x0133 /* Sipro Lab Telecom Inc. */ +WAVE_FORMAT_SIPROLAB_G729A :: 0x0134 /* Sipro Lab Telecom Inc. */ +WAVE_FORMAT_SIPROLAB_KELVIN :: 0x0135 /* Sipro Lab Telecom Inc. */ +WAVE_FORMAT_VOICEAGE_AMR :: 0x0136 /* VoiceAge Corp. */ +WAVE_FORMAT_G726ADPCM :: 0x0140 /* Dictaphone Corporation */ +WAVE_FORMAT_DICTAPHONE_CELP68 :: 0x0141 /* Dictaphone Corporation */ +WAVE_FORMAT_DICTAPHONE_CELP54 :: 0x0142 /* Dictaphone Corporation */ +WAVE_FORMAT_QUALCOMM_PUREVOICE :: 0x0150 /* Qualcomm, Inc. */ +WAVE_FORMAT_QUALCOMM_HALFRATE :: 0x0151 /* Qualcomm, Inc. */ +WAVE_FORMAT_TUBGSM :: 0x0155 /* Ring Zero Systems, Inc. */ +WAVE_FORMAT_MSAUDIO1 :: 0x0160 /* Microsoft Corporation */ +WAVE_FORMAT_WMAUDIO2 :: 0x0161 /* Microsoft Corporation */ +WAVE_FORMAT_WMAUDIO3 :: 0x0162 /* Microsoft Corporation */ +WAVE_FORMAT_WMAUDIO_LOSSLESS :: 0x0163 /* Microsoft Corporation */ +WAVE_FORMAT_WMASPDIF :: 0x0164 /* Microsoft Corporation */ +WAVE_FORMAT_UNISYS_NAP_ADPCM :: 0x0170 /* Unisys Corp. */ +WAVE_FORMAT_UNISYS_NAP_ULAW :: 0x0171 /* Unisys Corp. */ +WAVE_FORMAT_UNISYS_NAP_ALAW :: 0x0172 /* Unisys Corp. */ +WAVE_FORMAT_UNISYS_NAP_16K :: 0x0173 /* Unisys Corp. */ +WAVE_FORMAT_SYCOM_ACM_SYC008 :: 0x0174 /* SyCom Technologies */ +WAVE_FORMAT_SYCOM_ACM_SYC701_G726L :: 0x0175 /* SyCom Technologies */ +WAVE_FORMAT_SYCOM_ACM_SYC701_CELP54 :: 0x0176 /* SyCom Technologies */ +WAVE_FORMAT_SYCOM_ACM_SYC701_CELP68 :: 0x0177 /* SyCom Technologies */ +WAVE_FORMAT_KNOWLEDGE_ADVENTURE_ADPCM :: 0x0178 /* Knowledge Adventure, Inc. */ +WAVE_FORMAT_FRAUNHOFER_IIS_MPEG2_AAC :: 0x0180 /* Fraunhofer IIS */ +WAVE_FORMAT_DTS_DS :: 0x0190 /* Digital Theatre Systems, Inc. */ +WAVE_FORMAT_CREATIVE_ADPCM :: 0x0200 /* Creative Labs, Inc */ +WAVE_FORMAT_CREATIVE_FASTSPEECH8 :: 0x0202 /* Creative Labs, Inc */ +WAVE_FORMAT_CREATIVE_FASTSPEECH10 :: 0x0203 /* Creative Labs, Inc */ +WAVE_FORMAT_UHER_ADPCM :: 0x0210 /* UHER informatic GmbH */ +WAVE_FORMAT_ULEAD_DV_AUDIO :: 0x0215 /* Ulead Systems, Inc. */ +WAVE_FORMAT_ULEAD_DV_AUDIO_1 :: 0x0216 /* Ulead Systems, Inc. */ +WAVE_FORMAT_QUARTERDECK :: 0x0220 /* Quarterdeck Corporation */ +WAVE_FORMAT_ILINK_VC :: 0x0230 /* I-link Worldwide */ +WAVE_FORMAT_RAW_SPORT :: 0x0240 /* Aureal Semiconductor */ +WAVE_FORMAT_ESST_AC3 :: 0x0241 /* ESS Technology, Inc. */ +WAVE_FORMAT_GENERIC_PASSTHRU :: 0x0249 +WAVE_FORMAT_IPI_HSX :: 0x0250 /* Interactive Products, Inc. */ +WAVE_FORMAT_IPI_RPELP :: 0x0251 /* Interactive Products, Inc. */ +WAVE_FORMAT_CS2 :: 0x0260 /* Consistent Software */ +WAVE_FORMAT_SONY_SCX :: 0x0270 /* Sony Corp. */ +WAVE_FORMAT_SONY_SCY :: 0x0271 /* Sony Corp. */ +WAVE_FORMAT_SONY_ATRAC3 :: 0x0272 /* Sony Corp. */ +WAVE_FORMAT_SONY_SPC :: 0x0273 /* Sony Corp. */ +WAVE_FORMAT_TELUM_AUDIO :: 0x0280 /* Telum Inc. */ +WAVE_FORMAT_TELUM_IA_AUDIO :: 0x0281 /* Telum Inc. */ +WAVE_FORMAT_NORCOM_VOICE_SYSTEMS_ADPCM :: 0x0285 /* Norcom Electronics Corp. */ +WAVE_FORMAT_FM_TOWNS_SND :: 0x0300 /* Fujitsu Corp. */ +WAVE_FORMAT_MICRONAS :: 0x0350 /* Micronas Semiconductors, Inc. */ +WAVE_FORMAT_MICRONAS_CELP833 :: 0x0351 /* Micronas Semiconductors, Inc. */ +WAVE_FORMAT_BTV_DIGITAL :: 0x0400 /* Brooktree Corporation */ +WAVE_FORMAT_INTEL_MUSIC_CODER :: 0x0401 /* Intel Corp. */ +WAVE_FORMAT_INDEO_AUDIO :: 0x0402 /* Ligos */ +WAVE_FORMAT_QDESIGN_MUSIC :: 0x0450 /* QDesign Corporation */ +WAVE_FORMAT_ON2_VP7_AUDIO :: 0x0500 /* On2 Technologies */ +WAVE_FORMAT_ON2_VP6_AUDIO :: 0x0501 /* On2 Technologies */ +WAVE_FORMAT_VME_VMPCM :: 0x0680 /* AT&T Labs, Inc. */ +WAVE_FORMAT_TPC :: 0x0681 /* AT&T Labs, Inc. */ +WAVE_FORMAT_LIGHTWAVE_LOSSLESS :: 0x08AE /* Clearjump */ +WAVE_FORMAT_OLIGSM :: 0x1000 /* Ing C. Olivetti & C., S.p.A. */ +WAVE_FORMAT_OLIADPCM :: 0x1001 /* Ing C. Olivetti & C., S.p.A. */ +WAVE_FORMAT_OLICELP :: 0x1002 /* Ing C. Olivetti & C., S.p.A. */ +WAVE_FORMAT_OLISBC :: 0x1003 /* Ing C. Olivetti & C., S.p.A. */ +WAVE_FORMAT_OLIOPR :: 0x1004 /* Ing C. Olivetti & C., S.p.A. */ +WAVE_FORMAT_LH_CODEC :: 0x1100 /* Lernout & Hauspie */ +WAVE_FORMAT_LH_CODEC_CELP :: 0x1101 /* Lernout & Hauspie */ +WAVE_FORMAT_LH_CODEC_SBC8 :: 0x1102 /* Lernout & Hauspie */ +WAVE_FORMAT_LH_CODEC_SBC12 :: 0x1103 /* Lernout & Hauspie */ +WAVE_FORMAT_LH_CODEC_SBC16 :: 0x1104 /* Lernout & Hauspie */ +WAVE_FORMAT_NORRIS :: 0x1400 /* Norris Communications, Inc. */ +WAVE_FORMAT_ISIAUDIO_2 :: 0x1401 /* ISIAudio */ +WAVE_FORMAT_SOUNDSPACE_MUSICOMPRESS :: 0x1500 /* AT&T Labs, Inc. */ +WAVE_FORMAT_MPEG_ADTS_AAC :: 0x1600 /* Microsoft Corporation */ +WAVE_FORMAT_MPEG_RAW_AAC :: 0x1601 /* Microsoft Corporation */ +WAVE_FORMAT_MPEG_LOAS :: 0x1602 /* Microsoft Corporation (MPEG-4 Audio Transport Streams (LOAS/LATM) */ +WAVE_FORMAT_NOKIA_MPEG_ADTS_AAC :: 0x1608 /* Microsoft Corporation */ +WAVE_FORMAT_NOKIA_MPEG_RAW_AAC :: 0x1609 /* Microsoft Corporation */ +WAVE_FORMAT_VODAFONE_MPEG_ADTS_AAC :: 0x160A /* Microsoft Corporation */ +WAVE_FORMAT_VODAFONE_MPEG_RAW_AAC :: 0x160B /* Microsoft Corporation */ +WAVE_FORMAT_MPEG_HEAAC :: 0x1610 /* Microsoft Corporation (MPEG-2 AAC or MPEG-4 HE-AAC v1/v2 streams with any payload (ADTS, ADIF, LOAS/LATM, RAW). Format block includes MP4 AudioSpecificConfig() -- see HEAACWAVEFORMAT below */ +WAVE_FORMAT_VOXWARE_RT24_SPEECH :: 0x181C /* Voxware Inc. */ +WAVE_FORMAT_SONICFOUNDRY_LOSSLESS :: 0x1971 /* Sonic Foundry */ +WAVE_FORMAT_INNINGS_TELECOM_ADPCM :: 0x1979 /* Innings Telecom Inc. */ +WAVE_FORMAT_LUCENT_SX8300P :: 0x1C07 /* Lucent Technologies */ +WAVE_FORMAT_LUCENT_SX5363S :: 0x1C0C /* Lucent Technologies */ +WAVE_FORMAT_CUSEEME :: 0x1F03 /* CUSeeMe */ +WAVE_FORMAT_NTCSOFT_ALF2CM_ACM :: 0x1FC4 /* NTCSoft */ +WAVE_FORMAT_DVM :: 0x2000 /* FAST Multimedia AG */ +WAVE_FORMAT_DTS2 :: 0x2001 +WAVE_FORMAT_MAKEAVIS :: 0x3313 +WAVE_FORMAT_DIVIO_MPEG4_AAC :: 0x4143 /* Divio, Inc. */ +WAVE_FORMAT_NOKIA_ADAPTIVE_MULTIRATE :: 0x4201 /* Nokia */ +WAVE_FORMAT_DIVIO_G726 :: 0x4243 /* Divio, Inc. */ +WAVE_FORMAT_LEAD_SPEECH :: 0x434C /* LEAD Technologies */ +WAVE_FORMAT_LEAD_VORBIS :: 0x564C /* LEAD Technologies */ +WAVE_FORMAT_WAVPACK_AUDIO :: 0x5756 /* xiph.org */ +WAVE_FORMAT_ALAC :: 0x6C61 /* Apple Lossless */ +WAVE_FORMAT_OGG_VORBIS_MODE_1 :: 0x674F /* Ogg Vorbis */ +WAVE_FORMAT_OGG_VORBIS_MODE_2 :: 0x6750 /* Ogg Vorbis */ +WAVE_FORMAT_OGG_VORBIS_MODE_3 :: 0x6751 /* Ogg Vorbis */ +WAVE_FORMAT_OGG_VORBIS_MODE_1_PLUS :: 0x676F /* Ogg Vorbis */ +WAVE_FORMAT_OGG_VORBIS_MODE_2_PLUS :: 0x6770 /* Ogg Vorbis */ +WAVE_FORMAT_OGG_VORBIS_MODE_3_PLUS :: 0x6771 /* Ogg Vorbis */ +WAVE_FORMAT_3COM_NBX :: 0x7000 /* 3COM Corp. */ +WAVE_FORMAT_OPUS :: 0x704F /* Opus */ +WAVE_FORMAT_FAAD_AAC :: 0x706D +WAVE_FORMAT_AMR_NB :: 0x7361 /* AMR Narrowband */ +WAVE_FORMAT_AMR_WB :: 0x7362 /* AMR Wideband */ +WAVE_FORMAT_AMR_WP :: 0x7363 /* AMR Wideband Plus */ +WAVE_FORMAT_GSM_AMR_CBR :: 0x7A21 /* GSMA/3GPP */ +WAVE_FORMAT_GSM_AMR_VBR_SID :: 0x7A22 /* GSMA/3GPP */ +WAVE_FORMAT_COMVERSE_INFOSYS_G723_1 :: 0xA100 /* Comverse Infosys */ +WAVE_FORMAT_COMVERSE_INFOSYS_AVQSBC :: 0xA101 /* Comverse Infosys */ +WAVE_FORMAT_COMVERSE_INFOSYS_SBC :: 0xA102 /* Comverse Infosys */ +WAVE_FORMAT_SYMBOL_G729_A :: 0xA103 /* Symbol Technologies */ +WAVE_FORMAT_VOICEAGE_AMR_WB :: 0xA104 /* VoiceAge Corp. */ +WAVE_FORMAT_INGENIENT_G726 :: 0xA105 /* Ingenient Technologies, Inc. */ +WAVE_FORMAT_MPEG4_AAC :: 0xA106 /* ISO/MPEG-4 */ +WAVE_FORMAT_ENCORE_G726 :: 0xA107 /* Encore Software */ +WAVE_FORMAT_ZOLL_ASAO :: 0xA108 /* ZOLL Medical Corp. */ +WAVE_FORMAT_SPEEX_VOICE :: 0xA109 /* xiph.org */ +WAVE_FORMAT_VIANIX_MASC :: 0xA10A /* Vianix LLC */ +WAVE_FORMAT_WM9_SPECTRUM_ANALYZER :: 0xA10B /* Microsoft */ +WAVE_FORMAT_WMF_SPECTRUM_ANAYZER :: 0xA10C /* Microsoft */ +WAVE_FORMAT_GSM_610 :: 0xA10D +WAVE_FORMAT_GSM_620 :: 0xA10E +WAVE_FORMAT_GSM_660 :: 0xA10F +WAVE_FORMAT_GSM_690 :: 0xA110 +WAVE_FORMAT_GSM_ADAPTIVE_MULTIRATE_WB :: 0xA111 +WAVE_FORMAT_POLYCOM_G722 :: 0xA112 /* Polycom */ +WAVE_FORMAT_POLYCOM_G728 :: 0xA113 /* Polycom */ +WAVE_FORMAT_POLYCOM_G729_A :: 0xA114 /* Polycom */ +WAVE_FORMAT_POLYCOM_SIREN :: 0xA115 /* Polycom */ +WAVE_FORMAT_GLOBAL_IP_ILBC :: 0xA116 /* Global IP */ +WAVE_FORMAT_RADIOTIME_TIME_SHIFT_RADIO :: 0xA117 /* RadioTime */ +WAVE_FORMAT_NICE_ACA :: 0xA118 /* Nice Systems */ +WAVE_FORMAT_NICE_ADPCM :: 0xA119 /* Nice Systems */ +WAVE_FORMAT_VOCORD_G721 :: 0xA11A /* Vocord Telecom */ +WAVE_FORMAT_VOCORD_G726 :: 0xA11B /* Vocord Telecom */ +WAVE_FORMAT_VOCORD_G722_1 :: 0xA11C /* Vocord Telecom */ +WAVE_FORMAT_VOCORD_G728 :: 0xA11D /* Vocord Telecom */ +WAVE_FORMAT_VOCORD_G729 :: 0xA11E /* Vocord Telecom */ +WAVE_FORMAT_VOCORD_G729_A :: 0xA11F /* Vocord Telecom */ +WAVE_FORMAT_VOCORD_G723_1 :: 0xA120 /* Vocord Telecom */ +WAVE_FORMAT_VOCORD_LBC :: 0xA121 /* Vocord Telecom */ +WAVE_FORMAT_NICE_G728 :: 0xA122 /* Nice Systems */ +WAVE_FORMAT_FRACE_TELECOM_G729 :: 0xA123 /* France Telecom */ +WAVE_FORMAT_CODIAN :: 0xA124 /* CODIAN */ +WAVE_FORMAT_DOLBY_AC4 :: 0xAC40 /* Dolby AC-4 */ +WAVE_FORMAT_FLAC :: 0xF1AC /* flac.sourceforge.net */ +WAVE_FORMAT_EXTENSIBLE :: 0xFFFE /* Microsoft */ + + WAVEFORMATEX :: struct { wFormatTag: WORD, nChannels: WORD, @@ -325,6 +600,20 @@ WAVEFORMATEX :: struct { } LPCWAVEFORMATEX :: ^WAVEFORMATEX +// New wave format development should be based on the WAVEFORMATEXTENSIBLE structure. +// WAVEFORMATEXTENSIBLE allows you to avoid having to register a new format tag with Microsoft. +// Simply define a new GUID value for the WAVEFORMATEXTENSIBLE.SubFormat field and use WAVE_FORMAT_EXTENSIBLE in the WAVEFORMATEXTENSIBLE.Format.wFormatTag field. +WAVEFORMATEXTENSIBLE :: struct { + using Format: WAVEFORMATEX, + Samples: struct #raw_union { + wValidBitsPerSample: WORD, /* bits of precision */ + wSamplesPerBlock: WORD, /* valid if wBitsPerSample==0 */ + wReserved: WORD, /* If neither applies, set to zero. */ + }, + dwChannelMask: SPEAKER_FLAGS, /* which channels are present in stream */ + SubFormat: GUID, +} + WAVEHDR :: struct { lpData: LPSTR, /* pointer to locked data buffer */ dwBufferLength: DWORD, /* length of data buffer */ @@ -360,26 +649,50 @@ WAVEOUTCAPSW :: struct { } LPWAVEOUTCAPSW :: ^WAVEOUTCAPSW +SPEAKER_FLAGS :: distinct bit_set[SPEAKER_FLAG; DWORD] +SPEAKER_FLAG :: enum DWORD { + FRONT_LEFT = 0, + FRONT_RIGHT = 1, + FRONT_CENTER = 2, + LOW_FREQUENCY = 3, + BACK_LEFT = 4, + BACK_RIGHT = 5, + FRONT_LEFT_OF_CENTER = 6, + FRONT_RIGHT_OF_CENTER = 7, + BACK_CENTER = 8, + SIDE_LEFT = 9, + SIDE_RIGHT = 10, + TOP_CENTER = 11, + TOP_FRONT_LEFT = 12, + TOP_FRONT_CENTER = 13, + TOP_FRONT_RIGHT = 14, + TOP_BACK_LEFT = 15, + TOP_BACK_CENTER = 16, + TOP_BACK_RIGHT = 17, + //RESERVED = 0x7FFC0000, // bit mask locations reserved for future use + ALL = 31, // used to specify that any possible permutation of speaker configurations +} + // flag values for PlaySound -SND_SYNC :: 0x0000 /* play synchronously (default) */ -SND_ASYNC :: 0x0001 /* play asynchronously */ -SND_NODEFAULT :: 0x0002 /* silence (!default) if sound not found */ -SND_MEMORY :: 0x0004 /* pszSound points to a memory file */ -SND_LOOP :: 0x0008 /* loop the sound until next sndPlaySound */ -SND_NOSTOP :: 0x0010 /* don't stop any currently playing sound */ +SND_SYNC :: 0x0000 /* play synchronously (default) */ +SND_ASYNC :: 0x0001 /* play asynchronously */ +SND_NODEFAULT :: 0x0002 /* silence (!default) if sound not found */ +SND_MEMORY :: 0x0004 /* pszSound points to a memory file */ +SND_LOOP :: 0x0008 /* loop the sound until next sndPlaySound */ +SND_NOSTOP :: 0x0010 /* don't stop any currently playing sound */ -SND_NOWAIT :: 0x00002000 /* don't wait if the driver is busy */ -SND_ALIAS :: 0x00010000 /* name is a registry alias */ -SND_ALIAS_ID :: 0x00110000 /* alias is a predefined ID */ -SND_FILENAME :: 0x00020000 /* name is file name */ -SND_RESOURCE :: 0x00040004 /* name is resource name or atom */ +SND_NOWAIT :: 0x00002000 /* don't wait if the driver is busy */ +SND_ALIAS :: 0x00010000 /* name is a registry alias */ +SND_ALIAS_ID :: 0x00110000 /* alias is a predefined ID */ +SND_FILENAME :: 0x00020000 /* name is file name */ +SND_RESOURCE :: 0x00040004 /* name is resource name or atom */ -SND_PURGE :: 0x0040 /* purge non-static events for task */ -SND_APPLICATION :: 0x0080 /* look for application specific association */ +SND_PURGE :: 0x0040 /* purge non-static events for task */ +SND_APPLICATION :: 0x0080 /* look for application specific association */ -SND_SENTRY :: 0x00080000 /* Generate a SoundSentry event with this sound */ -SND_RING :: 0x00100000 /* Treat this as a "ring" from a communications app - don't duck me */ -SND_SYSTEM :: 0x00200000 /* Treat this as a system sound */ +SND_SENTRY :: 0x00080000 /* Generate a SoundSentry event with this sound */ +SND_RING :: 0x00100000 /* Treat this as a "ring" from a communications app - don't duck me */ +SND_SYSTEM :: 0x00200000 /* Treat this as a system sound */ CALLBACK_TYPEMASK :: 0x00070000 /* callback type mask */ diff --git a/core/text/regex/common/common.odin b/core/text/regex/common/common.odin index 4a303e0a3..e60bef58f 100644 --- a/core/text/regex/common/common.odin +++ b/core/text/regex/common/common.odin @@ -15,8 +15,6 @@ MAX_PROGRAM_SIZE :: int(max(i16)) MAX_CLASSES :: int(max(u8)) Flag :: enum u8 { - // Global: try to match the pattern anywhere in the string. - Global, // Multiline: treat `^` and `$` as if they also match newlines. Multiline, // Case Insensitive: treat `a-z` as if it was also `A-Z`. @@ -36,7 +34,6 @@ Flags :: bit_set[Flag; u8] @(rodata) Flag_To_Letter := #sparse[Flag]u8 { - .Global = 'g', .Multiline = 'm', .Case_Insensitive = 'i', .Ignore_Whitespace = 'x', diff --git a/core/text/regex/compiler/compiler.odin b/core/text/regex/compiler/compiler.odin index b3ded0104..2f0f183e9 100644 --- a/core/text/regex/compiler/compiler.odin +++ b/core/text/regex/compiler/compiler.odin @@ -195,8 +195,12 @@ generate_code :: proc(c: ^Compiler, node: Node) -> (code: Program) { case ^Node_Anchor: if .Multiline in c.flags { - append(&code, Opcode.Multiline_Open) - append(&code, Opcode.Multiline_Close) + if specific.start { + append(&code, Opcode.Assert_Start_Multiline) + } else { + append(&code, Opcode.Multiline_Open) + append(&code, Opcode.Multiline_Close) + } } else { if specific.start { append(&code, Opcode.Assert_Start) @@ -401,7 +405,7 @@ compile :: proc(tree: Node, flags: common.Flags) -> (code: Program, class_data: pc_open := 0 - add_global: if .Global in flags { + optimize_opening: { // Check if the opening to the pattern is predictable. // If so, use one of the optimized Wait opcodes. iter := virtual_machine.Opcode_Iterator{ code[:], 0 } @@ -412,7 +416,7 @@ compile :: proc(tree: Node, flags: common.Flags) -> (code: Program, class_data: pc_open += size_of(Opcode) inject_at(&code, pc_open, Opcode(code[pc + size_of(Opcode) + pc_open])) pc_open += size_of(u8) - break add_global + break optimize_opening case .Rune: operand := intrinsics.unaligned_load(cast(^rune)&code[pc+1]) @@ -420,24 +424,28 @@ compile :: proc(tree: Node, flags: common.Flags) -> (code: Program, class_data: pc_open += size_of(Opcode) inject_raw(&code, pc_open, operand) pc_open += size_of(rune) - break add_global + break optimize_opening case .Rune_Class: inject_at(&code, pc_open, Opcode.Wait_For_Rune_Class) pc_open += size_of(Opcode) inject_at(&code, pc_open, Opcode(code[pc + size_of(Opcode) + pc_open])) pc_open += size_of(u8) - break add_global + break optimize_opening case .Rune_Class_Negated: inject_at(&code, pc_open, Opcode.Wait_For_Rune_Class_Negated) pc_open += size_of(Opcode) inject_at(&code, pc_open, Opcode(code[pc + size_of(Opcode) + pc_open])) pc_open += size_of(u8) - break add_global + break optimize_opening case .Save: continue + + case .Assert_Start, .Assert_Start_Multiline: + break optimize_opening + case: break seek_loop } diff --git a/core/text/regex/regex.odin b/core/text/regex/regex.odin index c805740f7..7456634ac 100644 --- a/core/text/regex/regex.odin +++ b/core/text/regex/regex.odin @@ -77,6 +77,8 @@ Match_Iterator :: struct { vm: virtual_machine.Machine, idx: int, temp: runtime.Allocator, + threads: int, + done: bool, } /* @@ -101,7 +103,6 @@ create :: proc( permanent_allocator := context.allocator, temporary_allocator := context.temp_allocator, ) -> (result: Regular_Expression, err: Error) { - // For the sake of speed and simplicity, we first run all the intermediate // processes such as parsing and compilation through the temporary // allocator. @@ -166,7 +167,6 @@ to escape the delimiter if found in the middle of the string. All runes after the closing delimiter will be parsed as flags: -- 'g': Global - 'm': Multiline - 'i': Case_Insensitive - 'x': Ignore_Whitespace @@ -243,7 +243,6 @@ create_by_user :: proc( // to `end` here. for r in pattern[start + end:] { switch r { - case 'g': flags += { .Global } case 'm': flags += { .Multiline } case 'i': flags += { .Case_Insensitive } case 'x': flags += { .Ignore_Whitespace } @@ -282,18 +281,13 @@ create_iterator :: proc( permanent_allocator := context.allocator, temporary_allocator := context.temp_allocator, ) -> (result: Match_Iterator, err: Error) { - flags := flags - flags += {.Global} // We're iterating over a string, so the next match could start anywhere - - if .Multiline in flags { - return {}, .Unsupported_Flag - } result.regex = create(pattern, flags, permanent_allocator, temporary_allocator) or_return result.capture = preallocate_capture() result.temp = temporary_allocator result.vm = virtual_machine.create(result.regex.program, str) result.vm.class_data = result.regex.class_data + result.threads = max(1, virtual_machine.opcode_count(result.vm.code) - 1) return } @@ -457,8 +451,27 @@ match_iterator :: proc(it: ^Match_Iterator) -> (result: Capture, index: int, ok: assert(len(it.capture.pos) >= common.MAX_CAPTURE_GROUPS, "Pre-allocated RegEx capture `pos` must be at least 10 elements long.") + // Guard against situations in which the iterator should finish. + if it.done { + return + } + runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() + if it.idx > 0 { + // Reset the state needed to `virtual_machine.run` again. + it.vm.top_thread = 0 + it.vm.current_rune = rune(0) + it.vm.current_rune_size = 0 + for i in 0.. (result: Capture, index: int, ok: } } + if !ok { + // Match failed, bail out. + return + } + + if it.vm.string_pointer == sp_before { + // The string pointer did not move, but there was a match. + // + // At this point, the pattern supplied to the iterator will infinitely + // loop if we do not intervene. + it.done = true + } + if it.vm.string_pointer == len(it.vm.memory) { + // The VM hit the end of the string. + // + // We do not check at the start, because a match of pattern `$` + // against string "" is valid and must return a match. + // + // This check prevents a double-match of `$` against a non-empty string. + it.done = true + } + str := string(it.vm.memory) num_groups: int @@ -488,9 +523,7 @@ match_iterator :: proc(it: ^Match_Iterator) -> (result: Capture, index: int, ok: num_groups = n } - defer if ok { - it.idx += 1 - } + defer it.idx += 1 if num_groups > 0 { result = {it.capture.pos[:num_groups], it.capture.groups[:num_groups]} @@ -504,8 +537,25 @@ match :: proc { match_iterator, } +/* +Reset an iterator, allowing it to be run again as if new. + +Inputs: +- it: The iterator to reset. +*/ reset :: proc(it: ^Match_Iterator) { - it.idx = 0 + it.done = false + it.idx = 0 + it.vm.string_pointer = 0 + + it.vm.top_thread = 0 + it.vm.current_rune = rune(0) + it.vm.current_rune_size = 0 + it.vm.last_rune = rune(0) + for i in 0.. (opcode: Opcode, pc: int, ok: case .Split: iter.pc += size_of(Opcode) + 2 * size_of(u16) case .Save: iter.pc += size_of(Opcode) + size_of(u8) case .Assert_Start: iter.pc += size_of(Opcode) + case .Assert_Start_Multiline: iter.pc += size_of(Opcode) case .Assert_End: iter.pc += size_of(Opcode) case .Assert_Word_Boundary: iter.pc += size_of(Opcode) case .Assert_Non_Word_Boundary: iter.pc += size_of(Opcode) @@ -64,6 +65,7 @@ opcode_to_name :: proc(opcode: Opcode) -> (str: string) { case .Split: str = "Split" case .Save: str = "Save" case .Assert_Start: str = "Assert_Start" + case .Assert_Start_Multiline: str = "Assert_Start_Multiline" case .Assert_End: str = "Assert_End" case .Assert_Word_Boundary: str = "Assert_Word_Boundary" case .Assert_Non_Word_Boundary: str = "Assert_Non_Word_Boundary" diff --git a/core/text/regex/virtual_machine/virtual_machine.odin b/core/text/regex/virtual_machine/virtual_machine.odin index ab1dfbec1..c292b0e99 100644 --- a/core/text/regex/virtual_machine/virtual_machine.odin +++ b/core/text/regex/virtual_machine/virtual_machine.odin @@ -37,16 +37,17 @@ Opcode :: enum u8 { Split = 0x08, // | u16, u16 Save = 0x09, // | u8 Assert_Start = 0x0A, // | - Assert_End = 0x0B, // | - Assert_Word_Boundary = 0x0C, // | - Assert_Non_Word_Boundary = 0x0D, // | - Multiline_Open = 0x0E, // | - Multiline_Close = 0x0F, // | - Wait_For_Byte = 0x10, // | u8 - Wait_For_Rune = 0x11, // | i32 - Wait_For_Rune_Class = 0x12, // | u8 - Wait_For_Rune_Class_Negated = 0x13, // | u8 - Match_All_And_Escape = 0x14, // | + Assert_Start_Multiline = 0x0B, // | + Assert_End = 0x0C, // | + Assert_Word_Boundary = 0x0D, // | + Assert_Non_Word_Boundary = 0x0E, // | + Multiline_Open = 0x0F, // | + Multiline_Close = 0x10, // | + Wait_For_Byte = 0x11, // | u8 + Wait_For_Rune = 0x12, // | i32 + Wait_For_Rune_Class = 0x13, // | u8 + Wait_For_Rune_Class_Negated = 0x14, // | u8 + Match_All_And_Escape = 0x15, // | } Thread :: struct { @@ -77,6 +78,8 @@ Machine :: struct { current_rune_size: int, next_rune: rune, next_rune_size: int, + + last_rune: rune, } @@ -169,6 +172,12 @@ add_thread :: proc(vm: ^Machine, saved: ^[2 * common.MAX_CAPTURE_GROUPS]int, pc: pc += size_of(Opcode) continue } + case .Assert_Start_Multiline: + sp := vm.string_pointer+vm.current_rune_size + if sp == 0 || vm.last_rune == '\n' || vm.last_rune == '\r' { + pc += size_of(Opcode) + continue + } case .Assert_End: sp := vm.string_pointer+vm.current_rune_size if sp == len(vm.memory) { @@ -177,24 +186,12 @@ add_thread :: proc(vm: ^Machine, saved: ^[2 * common.MAX_CAPTURE_GROUPS]int, pc: } case .Multiline_Open: sp := vm.string_pointer+vm.current_rune_size - if sp == 0 || sp == len(vm.memory) { - if vm.next_rune == '\r' || vm.next_rune == '\n' { - // The VM is currently on a newline at the string boundary, - // so consume the newline next frame. - when common.ODIN_DEBUG_REGEX { - io.write_string(common.debug_stream, "*** New thread added [PC:") - common.write_padded_hex(common.debug_stream, pc, 4) - io.write_string(common.debug_stream, "]\n") - } - vm.next_threads[vm.top_thread] = Thread{ pc = pc, saved = saved } - vm.top_thread += 1 - } else { - // Skip the `Multiline_Close` opcode. - pc += 2 * size_of(Opcode) - continue - } + if sp == len(vm.memory) { + // Skip the `Multiline_Close` opcode. + pc += 2 * size_of(Opcode) + continue } else { - // Not on a string boundary. + // Not at the end of the string. // Try to consume a newline next frame in the other opcode loop. when common.ODIN_DEBUG_REGEX { io.write_string(common.debug_stream, "*** New thread added [PC:") @@ -329,10 +326,10 @@ add_thread :: proc(vm: ^Machine, saved: ^[2 * common.MAX_CAPTURE_GROUPS]int, pc: run :: proc(vm: ^Machine, $UNICODE_MODE: bool) -> (saved: ^[2 * common.MAX_CAPTURE_GROUPS]int, ok: bool) #no_bounds_check { when UNICODE_MODE { - vm.next_rune, vm.next_rune_size = utf8.decode_rune_in_string(vm.memory) + vm.next_rune, vm.next_rune_size = utf8.decode_rune_in_string(vm.memory[vm.string_pointer:]) } else { if len(vm.memory) > 0 { - vm.next_rune = cast(rune)vm.memory[0] + vm.next_rune = cast(rune)vm.memory[vm.string_pointer] vm.next_rune_size = 1 } } @@ -613,6 +610,7 @@ run :: proc(vm: ^Machine, $UNICODE_MODE: bool) -> (saved: ^[2 * common.MAX_CAPTU break } + vm.last_rune = vm.current_rune vm.string_pointer += vm.current_rune_size } @@ -652,4 +650,4 @@ destroy :: proc(vm: Machine, allocator := context.allocator) { delete(vm.busy_map) free(vm.threads) free(vm.next_threads) -} \ No newline at end of file +} diff --git a/core/text/scanner/scanner.odin b/core/text/scanner/scanner.odin index 24dbcc8a4..96109f614 100644 --- a/core/text/scanner/scanner.odin +++ b/core/text/scanner/scanner.odin @@ -285,6 +285,7 @@ scan_number :: proc(s: ^Scanner, ch: rune, seen_dot: bool) -> (rune, rune) { case 'o': return "octal literal" case 'z': return "dozenal literal" case 'x': return "hexadecimal literal" + case 'h': return "hexadecimal literal" } return "decimal literal" } @@ -360,7 +361,8 @@ scan_number :: proc(s: ^Scanner, ch: rune, seen_dot: bool) -> (rune, rune) { base, prefix = 12, 'z' case 'h': tok = Float - fallthrough + ch = advance(s) + base, prefix = 16, 'h' case 'x': ch = advance(s) base, prefix = 16, 'x' @@ -447,7 +449,7 @@ scan_string :: proc(s: ^Scanner, quote: rune) -> (n: int) { ch := advance(s) for ch != quote { if ch == '\n' || ch < 0 { - error(s, "literal no terminated") + error(s, "literal not terminated") return } if ch == '\\' { diff --git a/src/build_settings.cpp b/src/build_settings.cpp index b3bbf726b..05709902a 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -31,6 +31,24 @@ enum TargetOsKind : u16 { TargetOs_COUNT, }; +gb_global String target_os_names[TargetOs_COUNT] = { + str_lit(""), + str_lit("windows"), + str_lit("darwin"), + str_lit("linux"), + str_lit("essence"), + str_lit("freebsd"), + str_lit("openbsd"), + str_lit("netbsd"), + str_lit("haiku"), + + str_lit("wasi"), + str_lit("js"), + str_lit("orca"), + + str_lit("freestanding"), +}; + enum TargetArchKind : u16 { TargetArch_Invalid, @@ -45,6 +63,17 @@ enum TargetArchKind : u16 { TargetArch_COUNT, }; +gb_global String target_arch_names[TargetArch_COUNT] = { + str_lit(""), + str_lit("amd64"), + str_lit("i386"), + str_lit("arm32"), + str_lit("arm64"), + str_lit("wasm32"), + str_lit("wasm64p32"), + str_lit("riscv64"), +}; + enum TargetEndianKind : u8 { TargetEndian_Little, TargetEndian_Big, @@ -52,6 +81,11 @@ enum TargetEndianKind : u8 { TargetEndian_COUNT, }; +gb_global String target_endian_names[TargetEndian_COUNT] = { + str_lit("little"), + str_lit("big"), +}; + enum TargetABIKind : u16 { TargetABI_Default, @@ -61,7 +95,14 @@ enum TargetABIKind : u16 { TargetABI_COUNT, }; +gb_global String target_abi_names[TargetABI_COUNT] = { + str_lit(""), + str_lit("win64"), + str_lit("sysv"), +}; + enum Windows_Subsystem : u8 { + Windows_Subsystem_UNKNOWN, Windows_Subsystem_BOOT_APPLICATION, Windows_Subsystem_CONSOLE, // Default, Windows_Subsystem_EFI_APPLICATION, @@ -75,59 +116,32 @@ enum Windows_Subsystem : u8 { Windows_Subsystem_COUNT, }; +gb_global String windows_subsystem_names[Windows_Subsystem_COUNT] = { + str_lit(""), + str_lit("BOOT_APPLICATION"), + str_lit("CONSOLE"), // Default + str_lit("EFI_APPLICATION"), + str_lit("EFI_BOOT_SERVICE_DRIVER"), + str_lit("EFI_ROM"), + str_lit("EFI_RUNTIME_DRIVER"), + str_lit("NATIVE"), + str_lit("POSIX"), + str_lit("WINDOWS"), + str_lit("WINDOWSCE"), +}; + struct MicroarchFeatureList { String microarch; String features; }; -gb_global String target_os_names[TargetOs_COUNT] = { - str_lit(""), - str_lit("windows"), - str_lit("darwin"), - str_lit("linux"), - str_lit("essence"), - str_lit("freebsd"), - str_lit("openbsd"), - str_lit("netbsd"), - str_lit("haiku"), - - str_lit("wasi"), - str_lit("js"), - str_lit("orca"), - - str_lit("freestanding"), -}; - -gb_global String target_arch_names[TargetArch_COUNT] = { - str_lit(""), - str_lit("amd64"), - str_lit("i386"), - str_lit("arm32"), - str_lit("arm64"), - str_lit("wasm32"), - str_lit("wasm64p32"), - str_lit("riscv64"), -}; - #if defined(GB_SYSTEM_WINDOWS) #include #else #include #endif - #include "build_settings_microarch.cpp" -gb_global String target_endian_names[TargetEndian_COUNT] = { - str_lit("little"), - str_lit("big"), -}; - -gb_global String target_abi_names[TargetABI_COUNT] = { - str_lit(""), - str_lit("win64"), - str_lit("sysv"), -}; - gb_global TargetEndianKind target_endians[TargetArch_COUNT] = { TargetEndian_Little, TargetEndian_Little, @@ -138,19 +152,6 @@ gb_global TargetEndianKind target_endians[TargetArch_COUNT] = { TargetEndian_Little, }; -gb_global String windows_subsystem_names[Windows_Subsystem_COUNT] = { - str_lit("BOOT_APPLICATION"), - str_lit("CONSOLE"), // Default - str_lit("EFI_APPLICATION"), - str_lit("EFI_BOOT_SERVICE_DRIVER"), - str_lit("EFI_ROM"), - str_lit("EFI_RUNTIME_DRIVER"), - str_lit("NATIVE"), - str_lit("POSIX"), - str_lit("WINDOWS"), - str_lit("WINDOWSCE"), -}; - #ifndef ODIN_VERSION_RAW #define ODIN_VERSION_RAW "dev-unknown-unknown" #endif @@ -287,7 +288,7 @@ enum BuildPath : u8 { BuildPath_VS_LIB, // vs_library_path BuildPath_Output, // Output Path for .exe, .dll, .so, etc. Can be overridden with `-out:`. - BuildPath_PDB, // Output Path for .pdb file, can be overridden with `-pdb-name:`. + BuildPath_Symbols, // Output Path for .pdb or .dSym file, can be overridden with `-pdb-name:`. BuildPathCOUNT, }; @@ -393,17 +394,17 @@ String linker_choices[Linker_COUNT] = { // This stores the information for the specify architecture of this build struct BuildContext { // Constants - String ODIN_OS; // Target operating system - String ODIN_ARCH; // Target architecture - String ODIN_VENDOR; // Compiler vendor - String ODIN_VERSION; // Compiler version - String ODIN_ROOT; // Odin ROOT - String ODIN_BUILD_PROJECT_NAME; // Odin main/initial package's directory name - String ODIN_WINDOWS_SUBSYSTEM; // Empty string for non-Windows targets - bool ODIN_DEBUG; // Odin in debug mode - bool ODIN_DISABLE_ASSERT; // Whether the default 'assert' et al is disabled in code or not - bool ODIN_DEFAULT_TO_NIL_ALLOCATOR; // Whether the default allocator is a "nil" allocator or not (i.e. it does nothing) - bool ODIN_DEFAULT_TO_PANIC_ALLOCATOR; // Whether the default allocator is a "panic" allocator or not (i.e. panics on any call to it) + String ODIN_OS; // Target operating system + String ODIN_ARCH; // Target architecture + String ODIN_VENDOR; // Compiler vendor + String ODIN_VERSION; // Compiler version + String ODIN_ROOT; // Odin ROOT + String ODIN_BUILD_PROJECT_NAME; // Odin main/initial package's directory name + Windows_Subsystem ODIN_WINDOWS_SUBSYSTEM; // .Console, .Windows + bool ODIN_DEBUG; // Odin in debug mode + bool ODIN_DISABLE_ASSERT; // Whether the default 'assert' et al is disabled in code or not + bool ODIN_DEFAULT_TO_NIL_ALLOCATOR; // Whether the default allocator is a "nil" allocator or not (i.e. it does nothing) + bool ODIN_DEFAULT_TO_PANIC_ALLOCATOR; // Whether the default allocator is a "panic" allocator or not (i.e. panics on any call to it) bool ODIN_FOREIGN_ERROR_PROCEDURES; bool ODIN_VALGRIND_SUPPORT; @@ -441,6 +442,7 @@ struct BuildContext { String extra_assembler_flags; String microarch; BuildModeKind build_mode; + bool keep_executable; bool generate_docs; bool custom_optimization_level; i32 optimization_level; @@ -1787,8 +1789,8 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta } // Default to subsystem:CONSOLE on Windows targets - if (bc->ODIN_WINDOWS_SUBSYSTEM == "" && bc->metrics.os == TargetOs_windows) { - bc->ODIN_WINDOWS_SUBSYSTEM = windows_subsystem_names[Windows_Subsystem_CONSOLE]; + if (bc->ODIN_WINDOWS_SUBSYSTEM == Windows_Subsystem_UNKNOWN && bc->metrics.os == TargetOs_windows) { + bc->ODIN_WINDOWS_SUBSYSTEM = Windows_Subsystem_CONSOLE; } if (subtarget == Subtarget_Android) { @@ -2021,6 +2023,39 @@ gb_internal bool check_target_feature_is_superset_of(String const &superset, Str return true; } +gb_internal String infer_object_extension_from_build_context() { + String output_extension = {}; + if (is_arch_wasm()) { + output_extension = STR_LIT("wasm.o"); + } else { + switch (build_context.metrics.os) { + case TargetOs_windows: + output_extension = STR_LIT("obj"); + break; + default: + case TargetOs_darwin: + case TargetOs_linux: + case TargetOs_essence: + output_extension = STR_LIT("o"); + break; + + case TargetOs_freestanding: + switch (build_context.metrics.abi) { + default: + case TargetABI_Default: + case TargetABI_SysV: + output_extension = STR_LIT("o"); + break; + case TargetABI_Win64: + output_extension = STR_LIT("obj"); + break; + } + break; + } + } + return output_extension; +} + // NOTE(Jeroen): Set/create the output and other paths and report an error as appropriate. // We've previously called `parse_build_flags`, so `out_filepath` should be set. gb_internal bool init_build_paths(String init_filename) { @@ -2064,10 +2099,6 @@ gb_internal bool init_build_paths(String init_filename) { } } - if (bc->pdb_filepath.len > 0) { - bc->build_paths[BuildPath_PDB] = path_from_string(ha, bc->pdb_filepath); - } - if ((bc->command_kind & Command__does_build) && (!bc->ignore_microsoft_magic)) { // NOTE(ic): It would be nice to extend this so that we could specify the Visual Studio version that we want instead of defaulting to the latest. Find_Result find_result = find_visual_studio_and_windows_sdk(); @@ -2157,13 +2188,8 @@ gb_internal bool init_build_paths(String init_filename) { if (build_context.metrics.os == TargetOs_windows) { output_extension = STR_LIT("lib"); } - }else if (build_context.build_mode == BuildMode_Object) { - // By default use a .o object extension. - output_extension = STR_LIT("o"); - - if (build_context.metrics.os == TargetOs_windows) { - output_extension = STR_LIT("obj"); - } + } else if (build_context.build_mode == BuildMode_Object) { + output_extension = infer_object_extension_from_build_context(); } else if (build_context.build_mode == BuildMode_Assembly) { // By default use a .S asm extension. output_extension = STR_LIT("S"); @@ -2183,7 +2209,7 @@ gb_internal bool init_build_paths(String init_filename) { return false; } else if (bc->build_paths[BuildPath_Output].ext.len == 0) { gb_printf_err("Output path %.*s must have an appropriate extension.\n", LIT(output_file)); - return false; + return false; } } } else { @@ -2266,6 +2292,26 @@ gb_internal bool init_build_paths(String init_filename) { bc->build_paths[BuildPath_Output] = output_path; } + if (build_context.ODIN_DEBUG) { + if (build_context.metrics.os == TargetOs_windows) { + if (bc->pdb_filepath.len > 0) { + bc->build_paths[BuildPath_Symbols] = path_from_string(ha, bc->pdb_filepath); + } else { + Path symbol_path; + symbol_path.basename = copy_string(ha, bc->build_paths[BuildPath_Output].basename); + symbol_path.name = copy_string(ha, bc->build_paths[BuildPath_Output].name); + symbol_path.ext = copy_string(ha, STR_LIT("pdb")); + bc->build_paths[BuildPath_Symbols] = symbol_path; + } + } else if (build_context.metrics.os == TargetOs_darwin) { + Path symbol_path; + symbol_path.basename = copy_string(ha, bc->build_paths[BuildPath_Output].basename); + symbol_path.name = copy_string(ha, bc->build_paths[BuildPath_Output].name); + symbol_path.ext = copy_string(ha, STR_LIT("dSYM")); + bc->build_paths[BuildPath_Symbols] = symbol_path; + } + } + // Do we have an extension? We might not if the output filename was supplied. if (bc->build_paths[BuildPath_Output].ext.len == 0) { if (build_context.metrics.os == TargetOs_windows || is_arch_wasm() || build_context.build_mode != BuildMode_Executable) { @@ -2301,9 +2347,10 @@ gb_internal bool init_build_paths(String init_filename) { case TargetOs_windows: case TargetOs_linux: case TargetOs_darwin: + case TargetOs_freebsd: break; default: - gb_printf_err("-sanitize:address is only supported on windows, linux, and darwin\n"); + gb_printf_err("-sanitize:address is only supported on Windows, Linux, Darwin, and FreeBSD\n"); return false; } } @@ -2311,12 +2358,10 @@ gb_internal bool init_build_paths(String init_filename) { if (build_context.sanitizer_flags & SanitizerFlag_Memory) { switch (build_context.metrics.os) { case TargetOs_linux: + case TargetOs_freebsd: break; default: - gb_printf_err("-sanitize:memory is only supported on linux\n"); - return false; - } - if (build_context.metrics.os != TargetOs_linux) { + gb_printf_err("-sanitize:memory is only supported on Linux and FreeBSD\n"); return false; } } @@ -2325,9 +2370,10 @@ gb_internal bool init_build_paths(String init_filename) { switch (build_context.metrics.os) { case TargetOs_linux: case TargetOs_darwin: + case TargetOs_freebsd: break; default: - gb_printf_err("-sanitize:thread is only supported on linux and darwin\n"); + gb_printf_err("-sanitize:thread is only supported on Linux, Darwin, and FreeBSD\n"); return false; } } diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index 71906d9c6..26e013c74 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -2885,8 +2885,6 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As // quaternion :: proc(imag, jmag, kmag, real: float_type) -> complex_type Operand xyzw[4] = {}; - u32 first_index = 0; - // NOTE(bill): Invalid will be the default till fixed operand->type = t_invalid; operand->mode = Addressing_Invalid; @@ -2931,6 +2929,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As if (fields_set[*index]) { error(field->field, "Previously assigned field: '%.*s'", LIT(name)); + return false; } fields_set[*index] = style; @@ -2947,7 +2946,6 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As if (!ok || index < 0) { return false; } - first_index = cast(u32)index; *refs[index] = o; } @@ -2972,12 +2970,17 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As } - for (u32 i = 0; i < 4; i++ ){ - u32 j = (i + first_index) % 4; - if (j == first_index) { - convert_to_typed(c, &xyzw[j], xyzw[(first_index+1)%4].type); if (xyzw[j].mode == Addressing_Invalid) return false; - } else { - convert_to_typed(c, &xyzw[j], xyzw[first_index].type); if (xyzw[j].mode == Addressing_Invalid) return false; + // The first typed value found, if any exist, will dictate the type for all untyped values. + for (u32 i = 0; i < 4; i++) { + if (is_type_typed(xyzw[i].type)) { + for (u32 j = 0; j < 4; j++) { + // `convert_to_typed` should check if it is typed already. + convert_to_typed(c, &xyzw[j], xyzw[i].type); + if (xyzw[j].mode == Addressing_Invalid) { + return false; + } + } + break; } } if (xyzw[0].mode == Addressing_Constant && @@ -3001,7 +3004,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As gbString ty = type_to_string(xyzw[1].type); gbString tz = type_to_string(xyzw[2].type); gbString tw = type_to_string(xyzw[3].type); - error(call, "Mismatched types to 'quaternion', 'x=%s' vs 'y=%s' vs 'z=%s' vs 'w=%s'", tx, ty, tz, tw); + error(call, "Mismatched types to 'quaternion', 'w=%s' vs 'x=%s' vs 'y=%s' vs 'z=%s'", tw, tx, ty, tz); gb_string_free(tw); gb_string_free(tz); gb_string_free(ty); @@ -3037,7 +3040,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As operand->mode = Addressing_Constant; } - BasicKind kind = core_type(xyzw[first_index].type)->Basic.kind; + BasicKind kind = core_type(xyzw[0].type)->Basic.kind; switch (kind) { case Basic_f16: operand->type = t_quaternion64; break; case Basic_f32: operand->type = t_quaternion128; break; diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 72aa07e42..561182f61 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -7962,7 +7962,27 @@ gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *c default: { gbString str = type_to_string(t); - error(call, "Too many arguments in conversion to '%s'", str); + if (t->kind == Type_Basic) { + ERROR_BLOCK(); + switch (t->Basic.kind) { + case Basic_complex32: + case Basic_complex64: + case Basic_complex128: + error(call, "Too many arguments in conversion to '%s'", str); + error_line("\tSuggestion: %s(1+2i) or construct with 'complex'\n", str); + break; + case Basic_quaternion64: + case Basic_quaternion128: + case Basic_quaternion256: + error(call, "Too many arguments in conversion to '%s'", str); + error_line("\tSuggestion: %s(1+2i+3j+4k) or construct with 'quaternion'\n", str); + break; + default: + error(call, "Too many arguments in conversion to '%s'", str); + } + } else { + error(call, "Too many arguments in conversion to '%s'", str); + } gb_string_free(str); } break; case 1: { @@ -8078,7 +8098,9 @@ gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *c if (pt->kind == Type_Proc && pt->Proc.calling_convention == ProcCC_Odin) { if ((c->scope->flags & ScopeFlag_ContextDefined) == 0) { + ERROR_BLOCK(); error(call, "'context' has not been defined within this scope, but is required for this procedure call"); + error_line("\tSuggestion: 'context = runtime.default_context()'"); } } diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index 0460f5bec..6cacef3ee 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -2855,6 +2855,7 @@ gb_internal void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) case Ast_BlockStmt: case Ast_IfStmt: case Ast_SwitchStmt: + case Ast_TypeSwitchStmt: if (token.kind != Token_break) { error(bs->label, "Label '%.*s' can only be used with 'break'", LIT(e->token.string)); } diff --git a/src/check_type.cpp b/src/check_type.cpp index 431698459..450b5e100 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -3805,7 +3805,11 @@ gb_internal Type *check_type_expr(CheckerContext *ctx, Ast *e, Type *named_type) #if 0 error(e, "Invalid type definition of '%.*s'", LIT(type->Named.name)); #endif - type->Named.base = t_invalid; + if (type->Named.type_name->TypeName.is_type_alias) { + // NOTE(laytan): keep it null, type declaration is a mini "cycle" to be filled later. + } else { + type->Named.base = t_invalid; + } } if (is_type_polymorphic(type)) { @@ -3823,7 +3827,7 @@ gb_internal Type *check_type_expr(CheckerContext *ctx, Ast *e, Type *named_type) } #endif - if (is_type_typed(type)) { + if (type->kind == Type_Named && type->Named.base == nullptr || is_type_typed(type)) { add_type_and_value(ctx, e, Addressing_Type, type, empty_exact_value); } else { gbString name = type_to_string(type); diff --git a/src/checker.cpp b/src/checker.cpp index aaa815365..9bc02cd87 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -1078,11 +1078,30 @@ gb_internal void init_universal(void) { add_global_bool_constant("true", true); add_global_bool_constant("false", false); - add_global_string_constant("ODIN_VENDOR", bc->ODIN_VENDOR); - add_global_string_constant("ODIN_VERSION", bc->ODIN_VERSION); - add_global_string_constant("ODIN_ROOT", bc->ODIN_ROOT); - add_global_string_constant("ODIN_BUILD_PROJECT_NAME", bc->ODIN_BUILD_PROJECT_NAME); - add_global_string_constant("ODIN_WINDOWS_SUBSYSTEM", bc->ODIN_WINDOWS_SUBSYSTEM); + add_global_string_constant("ODIN_VENDOR", bc->ODIN_VENDOR); + add_global_string_constant("ODIN_VERSION", bc->ODIN_VERSION); + add_global_string_constant("ODIN_ROOT", bc->ODIN_ROOT); + add_global_string_constant("ODIN_BUILD_PROJECT_NAME", bc->ODIN_BUILD_PROJECT_NAME); + + { + GlobalEnumValue values[Windows_Subsystem_COUNT] = { + {"Unknown", Windows_Subsystem_UNKNOWN}, + {"Boot_Application", Windows_Subsystem_BOOT_APPLICATION}, + {"Console", Windows_Subsystem_CONSOLE}, + {"EFI_Application", Windows_Subsystem_EFI_APPLICATION}, + {"EFI_Boot_Service_Driver", Windows_Subsystem_EFI_BOOT_SERVICE_DRIVER}, + {"EFI_Rom", Windows_Subsystem_EFI_ROM}, + {"EFI_Runtime_Driver", Windows_Subsystem_EFI_RUNTIME_DRIVER}, + {"Native", Windows_Subsystem_NATIVE}, + {"Posix", Windows_Subsystem_POSIX}, + {"Windows", Windows_Subsystem_WINDOWS}, + {"Windows_CE", Windows_Subsystem_WINDOWSCE}, + }; + + auto fields = add_global_enum_type(str_lit("Odin_Windows_Subsystem_Type"), values, gb_count_of(values)); + add_global_enum_constant(fields, "ODIN_WINDOWS_SUBSYSTEM", bc->ODIN_WINDOWS_SUBSYSTEM); + add_global_string_constant("ODIN_WINDOWS_SUBSYSTEM_STRING", windows_subsystem_names[bc->ODIN_WINDOWS_SUBSYSTEM]); + } { GlobalEnumValue values[TargetOs_COUNT] = { @@ -1102,7 +1121,7 @@ gb_internal void init_universal(void) { }; auto fields = add_global_enum_type(str_lit("Odin_OS_Type"), values, gb_count_of(values)); - add_global_enum_constant(fields, "ODIN_OS", bc->metrics.os); + add_global_enum_constant(fields, "ODIN_OS", bc->metrics.os); add_global_string_constant("ODIN_OS_STRING", target_os_names[bc->metrics.os]); } diff --git a/src/linker.cpp b/src/linker.cpp index 41d4a13a1..2210c1306 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -281,9 +281,9 @@ try_cross_linking:; link_settings = gb_string_append_fmt(link_settings, " /ENTRY:mainCRTStartup"); } - if (build_context.pdb_filepath != "") { - String pdb_path = path_to_string(heap_allocator(), build_context.build_paths[BuildPath_PDB]); - link_settings = gb_string_append_fmt(link_settings, " /PDB:\"%.*s\"", LIT(pdb_path)); + if (build_context.build_paths[BuildPath_Symbols].name != "") { + String symbol_path = path_to_string(heap_allocator(), build_context.build_paths[BuildPath_Symbols]); + link_settings = gb_string_append_fmt(link_settings, " /PDB:\"%.*s\"", LIT(symbol_path)); } if (build_context.build_mode != BuildMode_StaticLibrary) { @@ -321,7 +321,7 @@ try_cross_linking:; "", LIT(build_context.ODIN_ROOT), object_files, LIT(output_filename), link_settings, - LIT(build_context.ODIN_WINDOWS_SUBSYSTEM), + LIT(windows_subsystem_names[build_context.ODIN_WINDOWS_SUBSYSTEM]), LIT(build_context.link_flags), LIT(build_context.extra_linker_flags), lib_str @@ -341,7 +341,7 @@ try_cross_linking:; "", LIT(build_context.ODIN_ROOT), object_files, LIT(output_filename), link_settings, - LIT(build_context.ODIN_WINDOWS_SUBSYSTEM), + LIT(windows_subsystem_names[build_context.ODIN_WINDOWS_SUBSYSTEM]), LIT(build_context.link_flags), LIT(build_context.extra_linker_flags), lib_str @@ -404,7 +404,7 @@ try_cross_linking:; "", LIT(vs_exe_path), LIT(linker_name), object_files, LIT(res_path), LIT(output_filename), link_settings, - LIT(build_context.ODIN_WINDOWS_SUBSYSTEM), + LIT(windows_subsystem_names[build_context.ODIN_WINDOWS_SUBSYSTEM]), LIT(build_context.link_flags), LIT(build_context.extra_linker_flags), lib_str @@ -802,6 +802,18 @@ try_cross_linking:; link_settings = gb_string_appendc(link_settings, "-e _main "); } } else if (build_context.metrics.os == TargetOs_freebsd) { + if (build_context.sanitizer_flags & (SanitizerFlag_Address | SanitizerFlag_Memory)) { + // It's imperative that `pthread` is linked before `libc`, + // otherwise ASan/MSan will be unable to call `pthread_key_create` + // because FreeBSD's `libthr` implementation of `pthread` + // needs to replace the relevant stubs first. + // + // (Presumably TSan implements its own `pthread` interface, + // which is why it isn't required.) + // + // See: https://reviews.llvm.org/D39254 + platform_lib_str = gb_string_appendc(platform_lib_str, "-lpthread "); + } // FreeBSD pkg installs third-party shared libraries in /usr/local/lib. platform_lib_str = gb_string_appendc(platform_lib_str, "-Wl,-L/usr/local/lib "); } else if (build_context.metrics.os == TargetOs_openbsd) { diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index c73552d57..3cf77256b 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -2504,7 +2504,6 @@ gb_internal String lb_filepath_obj_for_module(lbModule *m) { gbString path = gb_string_make_length(heap_allocator(), basename.text, basename.len); path = gb_string_appendc(path, "/"); - path = gb_string_append_length(path, name.text, name.len); if (USE_SEPARATE_MODULES) { GB_ASSERT(m->module_name != nullptr); @@ -2516,6 +2515,8 @@ gb_internal String lb_filepath_obj_for_module(lbModule *m) { } path = gb_string_append_length(path, s.text, s.len); + } else { + path = gb_string_append_length(path, name.text, name.len); } if (use_temporary_directory) { @@ -2526,38 +2527,15 @@ gb_internal String lb_filepath_obj_for_module(lbModule *m) { String ext = {}; if (build_context.build_mode == BuildMode_Assembly) { - ext = STR_LIT(".S"); + ext = STR_LIT("S"); + } else if (build_context.build_mode == BuildMode_Object) { + // Allow a user override for the object extension. + ext = build_context.build_paths[BuildPath_Output].ext; } else { - if (is_arch_wasm()) { - ext = STR_LIT(".wasm.o"); - } else { - switch (build_context.metrics.os) { - case TargetOs_windows: - ext = STR_LIT(".obj"); - break; - default: - case TargetOs_darwin: - case TargetOs_linux: - case TargetOs_essence: - ext = STR_LIT(".o"); - break; - - case TargetOs_freestanding: - switch (build_context.metrics.abi) { - default: - case TargetABI_Default: - case TargetABI_SysV: - ext = STR_LIT(".o"); - break; - case TargetABI_Win64: - ext = STR_LIT(".obj"); - break; - } - break; - } - } + ext = infer_object_extension_from_build_context(); } + path = gb_string_append_length(path, ".", 1); path = gb_string_append_length(path, ext.text, ext.len); return make_string(cast(u8 *)path, gb_string_length(path)); @@ -3376,40 +3354,40 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { lb_add_raddbg_string(m, "type_view: {type: \"string\", expr: \"array(data, len)\"}"); // column major matrices - lb_add_raddbg_string(m, "type_view: {type: \"matrix[1, ?]?\", expr: \"table($.data, $[0])\"}"); - lb_add_raddbg_string(m, "type_view: {type: \"matrix[2, ?]?\", expr: \"table($.data, $[0], $[1])\"}"); - lb_add_raddbg_string(m, "type_view: {type: \"matrix[3, ?]?\", expr: \"table($.data, $[0], $[1], $[2])\"}"); - lb_add_raddbg_string(m, "type_view: {type: \"matrix[4, ?]?\", expr: \"table($.data, $[0], $[1], $[2], $[3])\"}"); - lb_add_raddbg_string(m, "type_view: {type: \"matrix[5, ?]?\", expr: \"table($.data, $[0], $[1], $[2], $[3], $[4])\"}"); - lb_add_raddbg_string(m, "type_view: {type: \"matrix[6, ?]?\", expr: \"table($.data, $[0], $[1], $[2], $[3], $[4], $[5])\"}"); - lb_add_raddbg_string(m, "type_view: {type: \"matrix[7, ?]?\", expr: \"table($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6])\"}"); - lb_add_raddbg_string(m, "type_view: {type: \"matrix[8, ?]?\", expr: \"table($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7])\"}"); - lb_add_raddbg_string(m, "type_view: {type: \"matrix[9, ?]?\", expr: \"table($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8])\"}"); - lb_add_raddbg_string(m, "type_view: {type: \"matrix[10, ?]?\", expr: \"table($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9])\"}"); - lb_add_raddbg_string(m, "type_view: {type: \"matrix[11, ?]?\", expr: \"table($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10])\"}"); - lb_add_raddbg_string(m, "type_view: {type: \"matrix[12, ?]?\", expr: \"table($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10], $[11])\"}"); - lb_add_raddbg_string(m, "type_view: {type: \"matrix[13, ?]?\", expr: \"table($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10], $[11], $[12])\"}"); - lb_add_raddbg_string(m, "type_view: {type: \"matrix[14, ?]?\", expr: \"table($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10], $[11], $[12], $[13])\"}"); - lb_add_raddbg_string(m, "type_view: {type: \"matrix[15, ?]?\", expr: \"table($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10], $[11], $[12], $[13], $[14])\"}"); - lb_add_raddbg_string(m, "type_view: {type: \"matrix[16, ?]?\", expr: \"table($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10], $[11], $[12], $[13], $[14], $[15])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"matrix[1, ?]?\", expr: \"columns($.data, $[0])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"matrix[2, ?]?\", expr: \"columns($.data, $[0], $[1])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"matrix[3, ?]?\", expr: \"columns($.data, $[0], $[1], $[2])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"matrix[4, ?]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"matrix[5, ?]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"matrix[6, ?]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"matrix[7, ?]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"matrix[8, ?]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"matrix[9, ?]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"matrix[10, ?]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"matrix[11, ?]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"matrix[12, ?]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10], $[11])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"matrix[13, ?]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10], $[11], $[12])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"matrix[14, ?]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10], $[11], $[12], $[13])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"matrix[15, ?]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10], $[11], $[12], $[13], $[14])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"matrix[16, ?]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10], $[11], $[12], $[13], $[14], $[15])\"}"); // row major matrices - lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 1]?\", expr: \"table($.data, $[0])\"}"); - lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 2]?\", expr: \"table($.data, $[0], $[1])\"}"); - lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 3]?\", expr: \"table($.data, $[0], $[1], $[2])\"}"); - lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 4]?\", expr: \"table($.data, $[0], $[1], $[2], $[3])\"}"); - lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 5]?\", expr: \"table($.data, $[0], $[1], $[2], $[3], $[4])\"}"); - lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 6]?\", expr: \"table($.data, $[0], $[1], $[2], $[3], $[4], $[5])\"}"); - lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 7]?\", expr: \"table($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6])\"}"); - lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 8]?\", expr: \"table($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7])\"}"); - lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 9]?\", expr: \"table($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8])\"}"); - lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 10]?\", expr: \"table($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9])\"}"); - lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 11]?\", expr: \"table($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10])\"}"); - lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 12]?\", expr: \"table($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10], $[11])\"}"); - lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 13]?\", expr: \"table($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10], $[11], $[12])\"}"); - lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 14]?\", expr: \"table($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10], $[11], $[12], $[13])\"}"); - lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 15]?\", expr: \"table($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10], $[11], $[12], $[13], $[14])\"}"); - lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 16]?\", expr: \"table($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10], $[11], $[12], $[13], $[14], $[15])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 1]?\", expr: \"columns($.data, $[0])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 2]?\", expr: \"columns($.data, $[0], $[1])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 3]?\", expr: \"columns($.data, $[0], $[1], $[2])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 4]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 5]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 6]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 7]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 8]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 9]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 10]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 11]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 12]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10], $[11])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 13]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10], $[11], $[12])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 14]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10], $[11], $[12], $[13])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 15]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10], $[11], $[12], $[13], $[14])\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"#row_major matrix[?, 16]?\", expr: \"columns($.data, $[0], $[1], $[2], $[3], $[4], $[5], $[6], $[7], $[8], $[9], $[10], $[11], $[12], $[13], $[14], $[15])\"}"); TEMPORARY_ALLOCATOR_GUARD(); @@ -3513,36 +3491,48 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { if (build_context.sanitizer_flags & SanitizerFlag_Address) { - if (build_context.metrics.os == TargetOs_windows) { + switch (build_context.metrics.os) { + case TargetOs_windows: { auto paths = array_make(heap_allocator(), 0, 1); String path = concatenate_strings(permanent_allocator(), build_context.ODIN_ROOT, str_lit("\\bin\\llvm\\windows\\clang_rt.asan-x86_64.lib")); array_add(&paths, path); Entity *lib = alloc_entity_library_name(nullptr, make_token_ident("asan_lib"), nullptr, slice_from_array(paths), str_lit("asan_lib")); array_add(&gen->foreign_libraries, lib); - } else if (build_context.metrics.os == TargetOs_darwin || build_context.metrics.os == TargetOs_linux) { + } break; + case TargetOs_darwin: + case TargetOs_linux: + case TargetOs_freebsd: if (!build_context.extra_linker_flags.text) { build_context.extra_linker_flags = str_lit("-fsanitize=address"); } else { build_context.extra_linker_flags = concatenate_strings(permanent_allocator(), build_context.extra_linker_flags, str_lit(" -fsanitize=address")); } + break; } } if (build_context.sanitizer_flags & SanitizerFlag_Memory) { - if (build_context.metrics.os == TargetOs_darwin || build_context.metrics.os == TargetOs_linux) { + switch (build_context.metrics.os) { + case TargetOs_linux: + case TargetOs_freebsd: if (!build_context.extra_linker_flags.text) { build_context.extra_linker_flags = str_lit("-fsanitize=memory"); } else { build_context.extra_linker_flags = concatenate_strings(permanent_allocator(), build_context.extra_linker_flags, str_lit(" -fsanitize=memory")); } + break; } } if (build_context.sanitizer_flags & SanitizerFlag_Thread) { - if (build_context.metrics.os == TargetOs_darwin || build_context.metrics.os == TargetOs_linux) { + switch (build_context.metrics.os) { + case TargetOs_darwin: + case TargetOs_linux: + case TargetOs_freebsd: if (!build_context.extra_linker_flags.text) { build_context.extra_linker_flags = str_lit("-fsanitize=thread"); } else { build_context.extra_linker_flags = concatenate_strings(permanent_allocator(), build_context.extra_linker_flags, str_lit(" -fsanitize=thread")); } + break; } } diff --git a/src/main.cpp b/src/main.cpp index 90f2aad7a..af321258c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -312,6 +312,7 @@ enum BuildFlagKind { BuildFlag_Collection, BuildFlag_Define, BuildFlag_BuildMode, + BuildFlag_KeepExecutable, BuildFlag_Target, BuildFlag_Subtarget, BuildFlag_Debug, @@ -531,6 +532,7 @@ gb_internal bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_Collection, str_lit("collection"), BuildFlagParam_String, Command__does_check); add_flag(&build_flags, BuildFlag_Define, str_lit("define"), BuildFlagParam_String, Command__does_check, true); add_flag(&build_flags, BuildFlag_BuildMode, str_lit("build-mode"), BuildFlagParam_String, Command__does_build); // Commands_build is not used to allow for a better error message + add_flag(&build_flags, BuildFlag_KeepExecutable, str_lit("keep-executable"), BuildFlagParam_None, Command__does_build | Command_test); add_flag(&build_flags, BuildFlag_Target, str_lit("target"), BuildFlagParam_String, Command__does_check); add_flag(&build_flags, BuildFlag_Subtarget, str_lit("subtarget"), BuildFlagParam_String, Command__does_check); add_flag(&build_flags, BuildFlag_Debug, str_lit("debug"), BuildFlagParam_None, Command__does_check); @@ -1193,6 +1195,9 @@ gb_internal bool parse_build_flags(Array args) { break; } + case BuildFlag_KeepExecutable: + build_context.keep_executable = true; + break; case BuildFlag_Debug: build_context.ODIN_DEBUG = true; @@ -1622,9 +1627,9 @@ gb_internal bool parse_build_flags(Array args) { GB_ASSERT(value.kind == ExactValue_String); String subsystem = value.value_string; bool subsystem_found = false; - for (int i = 0; i < Windows_Subsystem_COUNT; i++) { + for (int i = 1; i < Windows_Subsystem_COUNT; i++) { if (str_eq_ignore_case(subsystem, windows_subsystem_names[i])) { - build_context.ODIN_WINDOWS_SUBSYSTEM = windows_subsystem_names[i]; + build_context.ODIN_WINDOWS_SUBSYSTEM = Windows_Subsystem(i); subsystem_found = true; break; } @@ -1633,7 +1638,7 @@ gb_internal bool parse_build_flags(Array args) { // WINDOW is a hidden alias for WINDOWS. Check it. String subsystem_windows_alias = str_lit("WINDOW"); if (!subsystem_found && str_eq_ignore_case(subsystem, subsystem_windows_alias)) { - build_context.ODIN_WINDOWS_SUBSYSTEM = windows_subsystem_names[Windows_Subsystem_WINDOWS]; + build_context.ODIN_WINDOWS_SUBSYSTEM = Windows_Subsystem_WINDOWS; subsystem_found = true; break; } @@ -1641,8 +1646,8 @@ gb_internal bool parse_build_flags(Array args) { if (!subsystem_found) { gb_printf_err("Invalid -subsystem string, got %.*s. Expected one of:\n", LIT(subsystem)); gb_printf_err("\t"); - for (int i = 0; i < Windows_Subsystem_COUNT; i++) { - if (i > 0) { + for (int i = 1; i < Windows_Subsystem_COUNT; i++) { + if (i > 1) { gb_printf_err(", "); } gb_printf_err("%.*s", LIT(windows_subsystem_names[i])); @@ -2381,6 +2386,12 @@ gb_internal int print_show_help(String const arg0, String command, String option } } + if (test_only) { + if (print_flag("-build-only")) { + print_usage_line(2, "Only builds the test executable; does not automatically run it afterwards."); + } + } + if (check) { if (print_flag("-collection:=")) { print_usage_line(2, "Defines a library collection used for imports."); @@ -2543,6 +2554,14 @@ gb_internal int print_show_help(String const arg0, String command, String option } } + if (test_only || run_or_build) { + if (print_flag("-keep-executable")) { + print_usage_line(2, "Keep the executable generated by `odin test` or `odin run` after running it. We clean it up by default."); + print_usage_line(2, "If you build your program or test using `odin build`, the compiler does not automatically execute"); + print_usage_line(2, "the resulting program, and this option is not applicable."); + } + } + if (run_or_build) { if (print_flag("-linker:")) { print_usage_line(2, "Specify the linker to use."); @@ -3866,6 +3885,21 @@ end_of_code_gen:; defer (gb_free(heap_allocator(), exe_name.text)); system_must_exec_command_line_app("odin run", "\"%.*s\" %.*s", LIT(exe_name), LIT(run_args_string)); + + if (!build_context.keep_executable) { + char const *filename = cast(char const *)exe_name.text; + gb_file_remove(filename); + + if (build_context.ODIN_DEBUG) { + if (build_context.metrics.os == TargetOs_windows || build_context.metrics.os == TargetOs_darwin) { + String symbol_path = path_to_string(heap_allocator(), build_context.build_paths[BuildPath_Symbols]); + defer (gb_free(heap_allocator(), symbol_path.text)); + + filename = cast(char const *)symbol_path.text; + gb_file_remove(filename); + } + } + } } return 0; } diff --git a/src/parser.cpp b/src/parser.cpp index 7bb480cbd..758c4948f 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -3274,6 +3274,8 @@ gb_internal Ast *parse_atom_expr(AstFile *f, Ast *operand, bool lhs) { case Token_OpenBracket: { bool prev_allow_range = f->allow_range; f->allow_range = false; + defer (f->allow_range = prev_allow_range); + Token open = {}, close = {}, interval = {}; Ast *indices[2] = {}; @@ -3282,6 +3284,13 @@ gb_internal Ast *parse_atom_expr(AstFile *f, Ast *operand, bool lhs) { f->expr_level++; open = expect_token(f, Token_OpenBracket); + if (f->curr_token.kind == Token_CloseBracket) { + error(f->curr_token, "Expected an operand, got ]"); + close = expect_token(f, Token_CloseBracket); + operand = ast_index_expr(f, operand, nullptr, open, close); + break; + } + switch (f->curr_token.kind) { case Token_Ellipsis: case Token_RangeFull: @@ -3331,7 +3340,6 @@ gb_internal Ast *parse_atom_expr(AstFile *f, Ast *operand, bool lhs) { operand = ast_index_expr(f, operand, indices[0], open, close); } - f->allow_range = prev_allow_range; } break; case Token_Pointer: // Deference diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp index 53f6135d0..ffa53abb5 100644 --- a/src/tokenizer.cpp +++ b/src/tokenizer.cpp @@ -968,6 +968,7 @@ gb_internal void tokenizer_get_token(Tokenizer *t, Token *token, int repeat=0) { advance_to_next_rune(t); for (isize comment_scope = 1; comment_scope > 0; /**/) { if (t->curr_rune == GB_RUNE_EOF) { + tokenizer_err(t, "Multi-line comment not terminated"); break; } else if (t->curr_rune == '/') { advance_to_next_rune(t); diff --git a/tests/benchmark/all.odin b/tests/benchmark/all.odin index a48872cc6..30640ac87 100644 --- a/tests/benchmark/all.odin +++ b/tests/benchmark/all.odin @@ -4,3 +4,4 @@ package benchmarks @(require) import "crypto" @(require) import "hash" @(require) import "text/regex" +@(require) import "strings" \ No newline at end of file diff --git a/tests/benchmark/bytes/benchmark_bytes.odin b/tests/benchmark/bytes/benchmark_bytes.odin index 13ef8f9a5..ee3a91d64 100644 --- a/tests/benchmark/bytes/benchmark_bytes.odin +++ b/tests/benchmark/bytes/benchmark_bytes.odin @@ -54,14 +54,15 @@ run_trial_size :: proc(p: proc "contextless" ([]u8, byte) -> int, size: int, idx accumulator: int - for _ in 0.. bool { + switch { + case n == 0: return true + case x == y: return true + } + a, b := ([^]byte)(x), ([^]byte)(y) + length := uint(n) + + for i := uint(0); i < length; i += 1 { + if a[i] != b[i] { + return false + } + } + return true +} + +plain_memory_compare :: proc "contextless" (a, b: rawptr, n: int) -> int #no_bounds_check { + switch { + case a == b: return 0 + case a == nil: return -1 + case b == nil: return +1 + } + + x := uintptr(a) + y := uintptr(b) + n := uintptr(n) + + SU :: size_of(uintptr) + fast := n/SU + 1 + offset := (fast-1)*SU + curr_block := uintptr(0) + if n < SU { + fast = 0 + } + + for /**/; curr_block < fast; curr_block += 1 { + va := (^uintptr)(x + curr_block * size_of(uintptr))^ + vb := (^uintptr)(y + curr_block * size_of(uintptr))^ + if va ~ vb != 0 { + for pos := curr_block*SU; pos < n; pos += 1 { + a := (^byte)(x+pos)^ + b := (^byte)(y+pos)^ + if a ~ b != 0 { + return -1 if (int(a) - int(b)) < 0 else +1 + } + } + } + } + + for /**/; offset < n; offset += 1 { + a := (^byte)(x+offset)^ + b := (^byte)(y+offset)^ + if a ~ b != 0 { + return -1 if (int(a) - int(b)) < 0 else +1 + } + } + + return 0 +} + +plain_memory_compare_zero :: proc "contextless" (a: rawptr, n: int) -> int #no_bounds_check { + x := uintptr(a) + n := uintptr(n) + + SU :: size_of(uintptr) + fast := n/SU + 1 + offset := (fast-1)*SU + curr_block := uintptr(0) + if n < SU { + fast = 0 + } + + for /**/; curr_block < fast; curr_block += 1 { + va := (^uintptr)(x + curr_block * size_of(uintptr))^ + if va ~ 0 != 0 { + for pos := curr_block*SU; pos < n; pos += 1 { + a := (^byte)(x+pos)^ + if a ~ 0 != 0 { + return -1 if int(a) < 0 else +1 + } + } + } + } + + for /**/; offset < n; offset += 1 { + a := (^byte)(x+offset)^ + if a ~ 0 != 0 { + return -1 if int(a) < 0 else +1 + } + } + + return 0 +} + +run_trial_size_cmp :: proc(p: proc "contextless" (rawptr, rawptr, int) -> $R, size: int, idx: int, runs: int, loc := #caller_location) -> (timing: time.Duration) { + left := make([]u8, size) + right := make([]u8, size) + defer { + delete(left) + delete(right) + } + + right[idx] = 0x01 + + accumulator: int + + watch: time.Stopwatch + + time.stopwatch_start(&watch) + for _ in 0.. int, size: int, idx: int, runs: int, loc := #caller_location) -> (timing: time.Duration) { + data := make([]u8, size) + defer delete(data) + + data[idx] = 0x01 + + accumulator: int + + watch: time.Stopwatch + + time.stopwatch_start(&watch) + for _ in 0.. (n: int) { + _len := min(len(a), len(b)) + + // Scan for matches including partial codepoints. + #no_bounds_check for n < _len && a[n] == b[n] { + n += 1 + } + + // Now scan to ignore partial codepoints. + if n > 0 { + s := a[:n] + n = 0 + for { + r0, w := utf8.decode_rune(s[n:]) + if r0 != utf8.RUNE_ERROR { + n += w + } else { + break + } + } + } + return +} + +run_trial_size_prefix :: proc(p: proc "contextless" (string, string) -> $R, suffix: string, size: int, idx: int, runs: int, loc := #caller_location) -> (timing: time.Duration) { + left := make([]u8, size) + right := make([]u8, size) + defer { + delete(left) + delete(right) + } + + if len(suffix) > 0 { + copy(left [idx:], suffix) + copy(right[idx:], suffix) + + } else { + right[idx] = 'A' + } + + accumulator: int + + watch: time.Stopwatch + + time.stopwatch_start(&watch) + for _ in 0.. (n: int) { + _len := min(len(a), len(b)) + + // Scan for matches including partial codepoints. + #no_bounds_check for n < _len && a[n] == b[n] { + n += 1 + } + + // Now scan to ignore partial codepoints. + if n > 0 { + s := a[:n] + n = 0 + for { + r0, w := utf8.decode_rune(s[n:]) + if r0 != utf8.RUNE_ERROR { + n += w + } else { + break + } + } + } + return + } + + cases := [][2]string{ + {"Hellope, there!", "Hellope, world!"}, + {"Hellope, there!", "Foozle"}, + {"Hellope, there!", "Hell"}, + {"Hellope! 🦉", "Hellope! 🦉"}, + } + + for v in cases { + p_scalar := prefix_length(v[0], v[1]) + p_simd := strings.prefix_length(v[0], v[1]) + testing.expect_value(t, p_simd, p_scalar) + + s := v[0] + for len(s) > 0 { + p_scalar = prefix_length(v[0], s) + p_simd = strings.prefix_length(v[0], s) + testing.expect_value(t, p_simd, p_scalar) + s = s[:len(s) - 1] + } + } +} \ No newline at end of file diff --git a/tests/core/text/regex/test_core_text_regex.odin b/tests/core/text/regex/test_core_text_regex.odin index 913e716e5..8369444b9 100644 --- a/tests/core/text/regex/test_core_text_regex.odin +++ b/tests/core/text/regex/test_core_text_regex.odin @@ -51,13 +51,13 @@ check_expression_with_flags :: proc(t: ^testing.T, pattern: string, flags: regex } check_expression :: proc(t: ^testing.T, pattern, haystack: string, needles: ..string, extra_flags := regex.Flags{}, loc := #caller_location) { - check_expression_with_flags(t, pattern, { .Global } + extra_flags, + check_expression_with_flags(t, pattern, extra_flags, haystack, ..needles, loc = loc) - check_expression_with_flags(t, pattern, { .Global, .No_Optimization } + extra_flags, + check_expression_with_flags(t, pattern, { .No_Optimization } + extra_flags, haystack, ..needles, loc = loc) - check_expression_with_flags(t, pattern, { .Global, .Unicode } + extra_flags, + check_expression_with_flags(t, pattern, { .Unicode } + extra_flags, haystack, ..needles, loc = loc) - check_expression_with_flags(t, pattern, { .Global, .Unicode, .No_Optimization } + extra_flags, + check_expression_with_flags(t, pattern, { .Unicode, .No_Optimization } + extra_flags, haystack, ..needles, loc = loc) } @@ -72,17 +72,18 @@ expect_error :: proc(t: ^testing.T, pattern: string, expected_error: typeid, fla testing.expect_value(t, variant_ti, expected_ti, loc = loc) } -check_capture :: proc(t: ^testing.T, got, expected: regex.Capture, loc := #caller_location) { - testing.expect_value(t, len(got.pos), len(got.groups), loc = loc) - testing.expect_value(t, len(got.pos), len(expected.pos), loc = loc) - testing.expect_value(t, len(got.groups), len(expected.groups), loc = loc) +check_capture :: proc(t: ^testing.T, got, expected: regex.Capture, loc := #caller_location) -> (ok: bool) { + testing.expect_value(t, len(got.pos), len(got.groups), loc = loc) or_return + testing.expect_value(t, len(got.pos), len(expected.pos), loc = loc) or_return + testing.expect_value(t, len(got.groups), len(expected.groups), loc = loc) or_return if len(got.pos) == len(expected.pos) { for i in 0..= len(test.expected) { + log.errorf("got more than expected number of captures for matching string %q against pattern %q\n\tidx %i = %v", test.haystack, test.pattern, idx, capture) + continue vector + } + if !check_capture(t, capture, test.expected[idx]) { + log.errorf("capture check failed on string %q against pattern %q", test.haystack, test.pattern) + } + } + testing.expectf(t, it.idx == len(test.expected), "expected idx to be %i, got %i on string %q against pattern %q", len(test.expected), it.idx, test.haystack, test.pattern) + } +} + +@test +test_iterator_reset :: proc(t: ^testing.T) { + test := Iterator_Test{ + `aaa`, `a`, {}, + { + {pos = {{0, 1}}, groups = {"a"}}, + {pos = {{1, 2}}, groups = {"a"}}, + {pos = {{2, 3}}, groups = {"a"}}, + }, + } + + out: { + it, err := regex.create_iterator(`aaa`, `a`) + defer regex.destroy(it) + + testing.expect_value(t, err, nil) + (err == nil) or_break out + + for capture, idx in regex.match(&it) { + if idx >= len(test.expected) { + log.errorf("got more than expected number of captures for matching string %q against pattern %q\n\tidx %i = %v", test.haystack, test.pattern, idx, capture) break } check_capture(t, capture, test.expected[idx]) } testing.expect_value(t, it.idx, len(test.expected)) + + // Do it again. + iterations := 0 + regex.reset(&it) + + // Mind that this loop can do nothing if it wasn't reset but leave us + // with the expected `idx` state. + // + // That's why we count iterations this time around. + for capture, idx in regex.match(&it) { + iterations += 1 + if idx >= len(test.expected) { + log.errorf("got more than expected number of captures for matching string %q against pattern %q\n\tidx %i = %v", test.haystack, test.pattern, idx, capture) + break + } + check_capture(t, capture, test.expected[idx]) + } + testing.expect_value(t, it.idx, len(test.expected)) + testing.expect_value(t, iterations, len(test.expected)) } -} \ No newline at end of file +} diff --git a/tests/issues/run.bat b/tests/issues/run.bat index 267a2e030..db941b55a 100644 --- a/tests/issues/run.bat +++ b/tests/issues/run.bat @@ -19,6 +19,7 @@ set COMMON=-define:ODIN_TEST_FANCY=false -file -vet -strict-style ..\..\..\odin test ..\test_issue_4584.odin %COMMON% || exit /b ..\..\..\odin build ..\test_issue_5043.odin %COMMON% || exit /b ..\..\..\odin build ..\test_issue_5097.odin %COMMON% || exit /b +..\..\..\odin build ..\test_issue_5097-2.odin %COMMON% || exit /b @echo off diff --git a/tests/issues/run.sh b/tests/issues/run.sh index 5102ee307..db0864c3e 100755 --- a/tests/issues/run.sh +++ b/tests/issues/run.sh @@ -26,6 +26,7 @@ else fi $ODIN build ../test_issue_5043.odin $COMMON $ODIN build ../test_issue_5097.odin $COMMON +$ODIN build ../test_issue_5097-2.odin $COMMON set +x diff --git a/tests/issues/test_issue_5097-2.odin b/tests/issues/test_issue_5097-2.odin new file mode 100644 index 000000000..1e4ad59c9 --- /dev/null +++ b/tests/issues/test_issue_5097-2.odin @@ -0,0 +1,24 @@ +// Tests another variation of, this should compile #5097 https://github.com/odin-lang/Odin/issues/5097 +package test_issues + +Face :: ^FaceRec +GlyphSlot :: ^GlyphSlotRec +Size :: ^SizeRec + +SizeRec :: struct { + face: Face, +} + +GlyphSlotRec :: struct { + face: Face, +} + +FaceRec :: struct { + glyph: GlyphSlot, + size: Size, +} + +main :: proc() { + face: Face + _ = face +} diff --git a/vendor/glfw/bindings/bindings.odin b/vendor/glfw/bindings/bindings.odin index 75cdab4cd..abf6c2150 100644 --- a/vendor/glfw/bindings/bindings.odin +++ b/vendor/glfw/bindings/bindings.odin @@ -163,9 +163,9 @@ foreign glfw { SetJoystickUserPointer :: proc(jid: c.int, pointer: rawptr) --- GetJoystickUserPointer :: proc(jid: c.int) -> rawptr --- JoystickIsGamepad :: proc(jid: c.int) -> b32 --- - UpdateGamepadMappings :: proc(str: cstring) -> c.int --- + UpdateGamepadMappings :: proc(str: cstring) -> b32 --- GetGamepadName :: proc(jid: c.int) -> cstring --- - GetGamepadState :: proc(jid: c.int, state: ^GamepadState) -> c.int --- + GetGamepadState :: proc(jid: c.int, state: ^GamepadState) -> b32 --- SetClipboardString :: proc(window: WindowHandle, str: cstring) --- @@ -177,12 +177,12 @@ foreign glfw { MakeContextCurrent :: proc(window: WindowHandle) --- GetCurrentContext :: proc() -> WindowHandle --- GetProcAddress :: proc(name: cstring) -> rawptr --- - ExtensionSupported :: proc(extension: cstring) -> c.int --- + ExtensionSupported :: proc(extension: cstring) -> b32 --- VulkanSupported :: proc() -> b32 --- GetRequiredInstanceExtensions :: proc(count: ^u32) -> [^]cstring --- GetInstanceProcAddress :: proc(instance: vk.Instance, procname: cstring) -> rawptr --- - GetPhysicalDevicePresentationSupport :: proc(instance: vk.Instance, device: vk.PhysicalDevice, queuefamily: u32) -> c.int --- + GetPhysicalDevicePresentationSupport :: proc(instance: vk.Instance, device: vk.PhysicalDevice, queuefamily: u32) -> b32 --- CreateWindowSurface :: proc(instance: vk.Instance, window: WindowHandle, allocator: ^vk.AllocationCallbacks, surface: ^vk.SurfaceKHR) -> vk.Result --- SetWindowIconifyCallback :: proc(window: WindowHandle, cbfun: WindowIconifyProc) -> WindowIconifyProc --- diff --git a/vendor/raylib/rlgl/rlgl.odin b/vendor/raylib/rlgl/rlgl.odin index b6cc23c48..14a7cf5b0 100644 --- a/vendor/raylib/rlgl/rlgl.odin +++ b/vendor/raylib/rlgl/rlgl.odin @@ -538,7 +538,7 @@ foreign lib { ReadScreenPixels :: proc(width, height: c.int) -> [^]byte --- // Read screen pixel data (color buffer) // Framebuffer management (fbo) - LoadFramebuffer :: proc(width, height: c.int) -> c.uint --- // Load an empty framebuffer + LoadFramebuffer :: proc() -> c.uint --- // Load an empty framebuffer FramebufferAttach :: proc(fboId, texId: c.uint, attachType: c.int, texType: c.int, mipLevel: c.int) --- // Attach texture/renderbuffer to a framebuffer FramebufferComplete :: proc(id: c.uint) -> bool --- // Verify framebuffer is complete UnloadFramebuffer :: proc(id: c.uint) --- // Delete framebuffer from GPU diff --git a/vendor/sdl2/sdl_rwops.odin b/vendor/sdl2/sdl_rwops.odin index ca7fa0bea..d3986f4b3 100644 --- a/vendor/sdl2/sdl_rwops.odin +++ b/vendor/sdl2/sdl_rwops.odin @@ -87,7 +87,7 @@ foreign lib { RWseek :: proc(ctx: ^RWops, offset: i64, whence: c.int) -> i64 --- RWtell :: proc(ctx: ^RWops) -> i64 --- RWread :: proc(ctx: ^RWops, ptr: rawptr, size: c.size_t, maxnum: c.size_t) -> c.size_t --- - RWwrite :: proc(ctx: ^RWops, size: c.size_t, num: c.size_t) -> c.size_t --- + RWwrite :: proc(ctx: ^RWops, ptr: rawptr, size: c.size_t, num: c.size_t) -> c.size_t --- RWclose :: proc(ctx: ^RWops) -> c.int --- LoadFile_RW :: proc(src: ^RWops, datasize: ^c.size_t, freesrc: bool) -> rawptr --- diff --git a/vendor/wgpu/doc.odin b/vendor/wgpu/doc.odin index a538c53c1..23f5dfc39 100644 --- a/vendor/wgpu/doc.odin +++ b/vendor/wgpu/doc.odin @@ -12,8 +12,8 @@ You can find a number of examples on [[Odin's official examples repository; http **Getting the wgpu-native libraries** For native support (not the browser), some libraries are required. Fortunately this is -extremely easy, just download them from the [[releases on GitHub; https://github.com/gfx-rs/wgpu-native/releases/tag/v24.0.0.2]]. -the bindings are for v24.0.0.2 at the moment. +extremely easy, just download them from the [[releases on GitHub; https://github.com/gfx-rs/wgpu-native/releases/tag/v25.0.2.1]]. +the bindings are for v25.0.2.1 at the moment. These are expected in the `lib` folder under the same name as they are released (just unzipped). By default it will look for a static release version (`wgpu-OS-ARCH-release.a|lib`), diff --git a/vendor/wgpu/lib/wgpu-windows-x86_64-msvc-release/lib/wgpu_native.dll b/vendor/wgpu/lib/wgpu-windows-x86_64-msvc-release/lib/wgpu_native.dll index 7fa1c8398..3c4e1b5a6 100644 Binary files a/vendor/wgpu/lib/wgpu-windows-x86_64-msvc-release/lib/wgpu_native.dll and b/vendor/wgpu/lib/wgpu-windows-x86_64-msvc-release/lib/wgpu_native.dll differ diff --git a/vendor/wgpu/lib/wgpu-windows-x86_64-msvc-release/lib/wgpu_native.lib b/vendor/wgpu/lib/wgpu-windows-x86_64-msvc-release/lib/wgpu_native.lib index 787feaede..3ea8453f9 100644 Binary files a/vendor/wgpu/lib/wgpu-windows-x86_64-msvc-release/lib/wgpu_native.lib and b/vendor/wgpu/lib/wgpu-windows-x86_64-msvc-release/lib/wgpu_native.lib differ diff --git a/vendor/wgpu/wgpu.js b/vendor/wgpu/wgpu.js index 578c1aefc..6104417df 100644 --- a/vendor/wgpu/wgpu.js +++ b/vendor/wgpu/wgpu.js @@ -2033,7 +2033,7 @@ class WebGPUInterface { addressModeW: this.enumeration("AddressMode", off(4)), magFilter: this.enumeration("FilterMode", off(4)), minFilter: this.enumeration("FilterMode", off(4)), - mipMapFilter: this.enumeration("MipmapFilterMode", off(4)), + mipmapFilter: this.enumeration("MipmapFilterMode", off(4)), lodMinClamp: this.mem.loadF32(off(4)), lodMaxClamp: this.mem.loadF32(off(4)), compare: this.enumeration("CompareFunction", off(4)), diff --git a/vendor/wgpu/wgpu.odin b/vendor/wgpu/wgpu.odin index 4bbe67d1f..c44bb2cbb 100644 --- a/vendor/wgpu/wgpu.odin +++ b/vendor/wgpu/wgpu.odin @@ -13,7 +13,7 @@ when ODIN_OS == .Windows { @(private) LIB :: "lib/wgpu-windows-" + ARCH + "-msvc-" + TYPE + "/lib/wgpu_native" + EXT when !#exists(LIB) { - #panic("Could not find the compiled WGPU Native library at '" + #directory + LIB + "', these can be downloaded from https://github.com/gfx-rs/wgpu-native/releases/tag/v24.0.0.2, make sure to read the README at '" + #directory + "README.md'") + #panic("Could not find the compiled WGPU Native library at '" + #directory + LIB + "', these can be downloaded from https://github.com/gfx-rs/wgpu-native/releases/tag/v25.0.2.1, make sure to read the README at '" + #directory + "README.md'") } @(export) @@ -39,12 +39,13 @@ when ODIN_OS == .Windows { @(private) LIB :: "lib/wgpu-macos-" + ARCH + "-" + TYPE + "/lib/libwgpu_native" + EXT when !#exists(LIB) { - #panic("Could not find the compiled WGPU Native library at '" + #directory + LIB + "', these can be downloaded from https://github.com/gfx-rs/wgpu-native/releases/tag/v24.0.0.2, make sure to read the README at '" + #directory + "README.md'") + #panic("Could not find the compiled WGPU Native library at '" + #directory + LIB + "', these can be downloaded from https://github.com/gfx-rs/wgpu-native/releases/tag/v25.0.2.1, make sure to read the README at '" + #directory + "README.md'") } @(export) foreign import libwgpu { LIB, + "system:Foundation.framework", "system:CoreFoundation.framework", "system:QuartzCore.framework", "system:Metal.framework", @@ -55,7 +56,7 @@ when ODIN_OS == .Windows { @(private) LIB :: "lib/wgpu-linux-" + ARCH + "-" + TYPE + "/lib/libwgpu_native" + EXT when !#exists(LIB) { - #panic("Could not find the compiled WGPU Native library at '" + #directory + LIB + "', these can be downloaded from https://github.com/gfx-rs/wgpu-native/releases/tag/v24.0.0.2, make sure to read the README at '" + #directory + "README.md'") + #panic("Could not find the compiled WGPU Native library at '" + #directory + LIB + "', these can be downloaded from https://github.com/gfx-rs/wgpu-native/releases/tag/v25.0.2.1, make sure to read the README at '" + #directory + "README.md'") } @(export) @@ -438,7 +439,7 @@ SType :: enum i32 { DeviceExtras = 0x00030001, NativeLimits, PipelineLayoutExtras, - ShaderModuleGLSLDescriptor, + ShaderSourceGLSL, SupportedLimitsExtras, InstanceExtras, BindGroupEntryExtras, diff --git a/vendor/wgpu/wgpu_native.odin b/vendor/wgpu/wgpu_native.odin index def095e07..c58a8c90e 100644 --- a/vendor/wgpu/wgpu_native.odin +++ b/vendor/wgpu/wgpu_native.odin @@ -12,7 +12,7 @@ foreign libwgpu { RawQueueSubmitForIndex :: proc(queue: Queue, commandCount: uint, commands: [^]CommandBuffer) -> SubmissionIndex --- // Returns true if the queue is empty, or false if there are more queue submissions still in flight. - DevicePoll :: proc(device: Device, wait: b32, /* NULLABLE */ wrappedSubmissionIndex: /* const */ ^SubmissionIndex = nil) -> b32 --- + DevicePoll :: proc(device: Device, wait: b32, /* NULLABLE */ submissionIndex: /* const */ ^SubmissionIndex = nil) -> b32 --- DeviceCreateShaderModuleSpirV :: proc(device: Device, descriptor: ^ShaderModuleDescriptorSpirV) -> ShaderModule --- SetLogCallback :: proc(callback: LogCallback, userdata: rawptr) --- diff --git a/vendor/wgpu/wgpu_native_types.odin b/vendor/wgpu/wgpu_native_types.odin index 025004c0c..a9340affe 100644 --- a/vendor/wgpu/wgpu_native_types.odin +++ b/vendor/wgpu/wgpu_native_types.odin @@ -2,8 +2,8 @@ package wgpu import "base:runtime" -BINDINGS_VERSION :: [4]u8{24, 0, 0, 2} -BINDINGS_VERSION_STRING :: "24.0.0.2" +BINDINGS_VERSION :: [4]u8{25, 0, 2, 1} +BINDINGS_VERSION_STRING :: "25.0.2.1" LogLevel :: enum i32 { Off, @@ -56,14 +56,32 @@ PipelineStatisticName :: enum i32 { ComputeShaderInvocations, } +DxcMaxShaderModel :: enum i32 { + V6_0, + V6_1, + V6_2, + V6_3, + V6_4, + V6_5, + V6_6, + V6_7, +} + +GLFenceBehaviour :: enum i32 { + Normal, + AutoFinish, +} + InstanceExtras :: struct { using chain: ChainedStruct, backends: InstanceBackendFlags, flags: InstanceFlags, dx12ShaderCompiler: Dx12Compiler, gles3MinorVersion: Gles3MinorVersion, + glFenceBehaviour: GLFenceBehaviour, dxilPath: StringView, dxcPath: StringView, + dcxMaxShaderModel: DxcMaxShaderModel, } DeviceExtras :: struct { @@ -96,7 +114,7 @@ ShaderDefine :: struct { value: StringView, } -ShaderModuleGLSLDescriptor :: struct { +ShaderSourceGLSL :: struct { using chain: ChainedStruct, stage: ShaderStage, code: StringView, diff --git a/vendor/windows/GameInput/windows_game_input.odin b/vendor/windows/GameInput/windows_game_input.odin index f4e7a4e3c..5a47d47ef 100644 --- a/vendor/windows/GameInput/windows_game_input.odin +++ b/vendor/windows/GameInput/windows_game_input.odin @@ -7,15 +7,115 @@ */ package windows_game_input -foreign import wgi { - "system:gameinput.lib", +foreign import wgi "system:gameinput.lib" + +import win "core:sys/windows" + +HRESULT :: win.HRESULT +HANDLE :: win.HANDLE +IUnknown :: win.IUnknown +IUnknown_VTable :: win.IUnknown_VTable +IID :: win.IID + +APP_LOCAL_DEVICE_ID :: distinct [32]byte + +Kind :: distinct bit_set[KindFlag; u32] +KindFlag :: enum u32 { + RawDeviceReport = 0, + ControllerAxis = 1, + ControllerButton = 2, + ControllerSwitch = 3, + Keyboard = 4, + Mouse = 5, + Touch = 8, + Motion = 12, + ArcadeStick = 16, + FlightStick = 17, + Gamepad = 18, + RacingWheel = 19, + UiNavigation = 20, +} +KindUnknown :: Kind{} +KindController :: Kind{ .ControllerAxis, .ControllerButton, .ControllerSwitch } + +EnumerationKind :: enum i32 { + NoEnumeration = 0, + AsyncEnumeration = 1, + BlockingEnumeration = 2, } -import "core:c" -import "core:sys/windows" +FocusPolicy :: distinct bit_set[FocusPolicyFlag; u32] +FocusPolicyFlag :: enum u32 { + DisableBackgroundInput = 0, + ExclusiveForegroundInput = 1, + DisableBackgroundGuideButton = 2, + ExclusiveForegroundGuideButton = 3, + DisableBackgroundShareButton = 4, + ExclusiveForegroundShareButton = 5, +} +DefaultFocusPolicy :: FocusPolicy{} -// Enums -ArcadeStickButtonsFlag :: enum c.int { +SwitchKind :: enum i32 { + UnknownSwitchKind = -1, + TwoWaySwitch = 0, + FourWaySwitch = 1, + EightWaySwitch = 2, +} + +SwitchPosition :: enum i32 { + Center = 0, + Up = 1, + UpRight = 2, + Right = 3, + DownRight = 4, + Down = 5, + DownLeft = 6, + Left = 7, + UpLeft = 8, +} + +KeyboardKind :: enum i32 { + UnknownKeyboard = -1, + AnsiKeyboard = 0, + IsoKeyboard = 1, + KsKeyboard = 2, + AbntKeyboard = 3, + JisKeyboard = 4, +} + +MouseButtons :: distinct bit_set[MouseButtonsFlag; u32] +MouseButtonsFlag :: enum u32 { + LeftButton = 0, + RightButton = 1, + MiddleButton = 2, + Button4 = 3, + Button5 = 4, + WheelTiltLeft = 5, + WheelTiltRight = 6, +} +MouseNone :: MouseButtons{} + +TouchShape :: enum i32 { + Unknown = -1, + Point = 0, + Linear1D = 1, + Radial1D = 2, + Irregular1D = 3, + Rectangular2D = 4, + Elliptical2D = 5, + Irregular2D = 6, +} + +MotionAccuracy :: enum i32 { + AccuracyUnknown = -1, + Unavailable = 0, + Unreliable = 1, + Approximate = 2, + Accurate = 3, +} + +ArcadeStickButtons :: distinct bit_set[ArcadeStickButtonsFlag; u32] +ArcadeStickButtonsFlag :: enum u32 { Menu = 0, View = 1, Up = 2, @@ -31,104 +131,19 @@ ArcadeStickButtonsFlag :: enum c.int { Special1 = 12, Special2 = 13, } -ArcadeStickButtons :: distinct bit_set[ArcadeStickButtonsFlag; c.int] +ArcadeStickNone :: ArcadeStickButtons{} -BatteryStatus :: enum c.int { - Unknown = -1, - NotPresent = 0, - Discharging = 1, - Idle = 2, - Charging = 3, +FlightStickButtons :: distinct bit_set[FlightStickButtonsFlag; u32] +FlightStickButtonsFlag :: enum u32 { + Menu = 0, + View = 1, + FirePrimary = 2, + FireSecondary = 3, } +FlightStickNone :: FlightStickButtons{} -DeviceCapabilitiesFlag :: enum c.int { - Audio = 0, - PluginModule = 1, - PowerOff = 2, - Synchronization = 3, - Wireless = 4, -} -DeviceCapabilities :: distinct bit_set[DeviceCapabilitiesFlag; c.int] - -DeviceFamily :: enum c.int { - Virtual = -1, - Aggregate = 0, - XboxOne = 1, - Xbox360 = 2, - Hid = 3, - I8042 = 4, -} - -DeviceStatusFlag :: enum c.int { - Connected = 0, - InputEnabled = 1, - OutputEnabled = 2, - RawIoEnabled = 3, - AudioCapture = 4, - AudioRender = 5, - Synchronized = 6, - Wireless = 7, - UserIdle = 20, -} -DeviceStatus :: distinct bit_set[DeviceStatusFlag; c.int] - -EnumerationKind :: enum c.int { - NoEnumeration = 0, - AsyncEnumeration = 1, - BlockingEnumeration = 2, -} - -FeedbackAxesFlag :: enum c.int { - LinearX = 0, - LinearY = 1, - LinearZ = 2, - AngularX = 3, - AngularY = 4, - AngularZ = 5, - Normal = 6, -} -FeedbackAxes :: distinct bit_set[FeedbackAxesFlag; c.int] - -FeedbackEffectState :: enum c.int { - Stopped = 0, - Running = 1, - Paused = 2, -} - -FlightStickButtonsFlag :: enum c.int { - None = 0, - Menu = 1, - View = 2, - FirePrimary = 3, - FireSecondary = 4, -} -FlightStickButtons :: distinct bit_set[FlightStickButtonsFlag; c.int] - -FocusPolicyFlag :: enum c.int { - DisableBackgroundInput = 0, - ExclusiveForegroundInput = 1, - DisableBackgroundGuideButton = 2, - ExclusiveForegroundGuideButton = 3, - DisableBackgroundShareButton = 4, - ExclusiveForegroundShareButton = 5, -} -FocusPolicy :: distinct bit_set[FocusPolicyFlag; c.int] - -ForceFeedbackEffectKind :: enum c.int { - Constant = 0, - Ramp = 1, - SineWave = 2, - SquareWave = 3, - TriangleWave = 4, - SawtoothUpWave = 5, - SawtoothDownWave = 6, - Spring = 7, - Friction = 8, - Damper = 9, - Inertia = 10, -} - -GamepadButtonsFlag :: enum c.int { +GamepadButtons :: distinct bit_set[GamepadButtonsFlag; u32] +GamepadButtonsFlag :: enum u32 { Menu = 0, View = 1, A = 2, @@ -144,36 +159,156 @@ GamepadButtonsFlag :: enum c.int { LeftThumbstick = 12, RightThumbstick = 13, } -GamepadButtons :: distinct bit_set[GamepadButtonsFlag; c.int] +GamepadNone :: GamepadButtons{} -KeyboardKind :: enum c.int { - UnknownKeyboard = -1, - AnsiKeyboard = 0, - IsoKeyboard = 1, - KsKeyboard = 2, - AbntKeyboard = 3, - JisKeyboard = 4, +RacingWheelButtons :: distinct bit_set[RacingWheelButtonsFlag; u32] +RacingWheelButtonsFlag :: enum u32 { + Menu = 0, + View = 1, + PreviousGear = 2, + NextGear = 3, + DpadUp = 4, + DpadDown = 5, + DpadLeft = 6, + DpadRight = 7, +} +RacingWheelNone :: RacingWheelButtons{} + +UiNavigationButtons :: distinct bit_set[UiNavigationButtonsFlag; u32] +UiNavigationButtonsFlag :: enum u32 { + Menu = 0, + View = 1, + Accept = 2, + Cancel = 3, + Up = 4, + Down = 5, + Left = 6, + Right = 7, + Context1 = 8, + Context2 = 9, + Context3 = 10, + Context4 = 11, + PageUp = 12, + PageDown = 13, + PageLeft = 14, + PageRight = 15, + ScrollUp = 16, + ScrollDown = 17, + ScrollLeft = 18, + ScrollRight = 19, +} +UiNavigationNone :: UiNavigationButtons{} + +SystemButtons :: distinct bit_set[SystemButtonsFlag; u32] +SystemButtonsFlag :: enum u32 { + Guide = 0, + Share = 1, +} +SystemButtonNone :: SystemButtons{} + +DeviceStatus :: distinct bit_set[DeviceStatusFlag; u32] +DeviceStatusFlag :: enum u32 { + Connected = 0, + InputEnabled = 1, + OutputEnabled = 2, + RawIoEnabled = 3, + AudioCapture = 4, + AudioRender = 5, + Synchronized = 6, + Wireless = 7, + UserIdle = 20, +} +DeviceNoStatus :: DeviceStatus{} +//DeviceAnyStatus :: 0x00FFFFFF + +BatteryStatus :: enum i32 { + Unknown = -1, + NotPresent = 0, + Discharging = 1, + Idle = 2, + Charging = 3, } -KindFlag :: enum c.int { - RawDeviceReport = 0, - ControllerAxis = 1, - ControllerButton = 2, - ControllerSwitch = 3, - Keyboard = 4, - Mouse = 5, - Touch = 8, - Motion = 12, - ArcadeStick = 16, - FlightStick = 17, - Gamepad = 18, - RacingWheel = 19, - UiNavigation = 20, +DeviceFamily :: enum i32 { + Virtual = -1, + Aggregate = 0, + XboxOne = 1, + Xbox360 = 2, + Hid = 3, + I8042 = 4, } -Kind :: distinct bit_set[KindFlag; c.int] -Kind_Controller : Kind : { .ControllerAxis, .ControllerButton, .ControllerSwitch } -Label :: enum c.int { +DeviceCapabilities :: distinct bit_set[DeviceCapabilitiesFlag; u32] +DeviceCapabilitiesFlag :: enum u32 { + Audio = 0, + PluginModule = 1, + PowerOff = 2, + Synchronization = 3, + Wireless = 4, +} +DeviceCapabilityNone :: DeviceCapabilities{} + +RawDeviceReportKind :: enum i32 { + InputReport = 0, + OutputReport = 1, + FeatureReport = 2, +} + +RawDeviceReportItemFlags :: distinct bit_set[RawDeviceReportItemFlag; u32] +RawDeviceReportItemFlag :: enum u32 { + ConstantItem = 0, + ArrayItem = 1, + RelativeItem = 2, + WraparoundItem = 3, + NonlinearItem = 4, + StableItem = 5, + NullableItem = 6, + VolatileItem = 7, + BufferedItem = 8, +} +RawDeviceDefaultItem :: RawDeviceReportItemFlags{} + +RawDeviceItemCollectionKind :: enum i32 { + UnknownItemCollection = -1, + PhysicalItemCollection = 0, + ApplicationItemCollection = 1, + LogicalItemCollection = 2, + ReportItemCollection = 3, + NamedArrayItemCollection = 4, + UsageSwitchItemCollection = 5, + UsageModifierItemCollection = 6, +} + +RawDevicePhysicalUnitKind :: enum i32 { + Unknown = -1, + None = 0, + Time = 1, + Frequency = 2, + Length = 3, + Velocity = 4, + Acceleration = 5, + Mass = 6, + Momentum = 7, + Force = 8, + Pressure = 9, + Angle = 10, + AngularVelocity = 11, + AngularAcceleration = 12, + AngularMass = 13, + AngularMomentum = 14, + AngularTorque = 15, + ElectricCurrent = 16, + ElectricCharge = 17, + ElectricPotential = 18, + Energy = 19, + Power = 20, + Temperature = 21, + LuminousIntensity = 22, + LuminousFlux = 23, + Illuminance = 24, +} + +Label :: enum i32 { Unknown = -1, None = 0, XboxGuide = 1, @@ -301,7 +436,7 @@ Label :: enum c.int { P4 = 124, } -Location :: enum c.int { +Location :: enum i32 { Unknown = -1, Chassis = 0, Display = 1, @@ -312,189 +447,142 @@ Location :: enum c.int { TouchPad = 6, } -MotionAccuracy :: enum c.int { - AccuracyUnknown = -1, - Unavailable = 0, - Unreliable = 1, - Approximate = 2, - Accurate = 3, +FeedbackAxes :: distinct bit_set[FeedbackAxesFlag; u32] +FeedbackAxesFlag :: enum u32 { + LinearX = 0, + LinearY = 1, + LinearZ = 2, + AngularX = 3, + AngularY = 4, + AngularZ = 5, + Normal = 6, +} +FeedbackAxisNone :: FeedbackAxes{} + +FeedbackEffectState :: enum i32 { + Stopped = 0, + Running = 1, + Paused = 2, } -MouseButtonsFlag :: enum c.int { - LeftButton = 0, - RightButton = 1, - MiddleButton = 2, - Button4 = 3, - Button5 = 4, - WheelTiltLeft = 5, - WheelTiltRight = 6, -} -MouseButtons :: distinct bit_set[MouseButtonsFlag; c.int] - -RacingWheelButtonsFlag :: enum c.int { - Menu = 0, - View = 1, - PreviousGear = 2, - NextGear = 3, - DpadUp = 4, - DpadDown = 5, - DpadLeft = 6, - DpadRight = 7, -} -RacingWheelButtons :: distinct bit_set[RacingWheelButtonsFlag; c.int] - -RawDeviceItemCollectionKind :: enum c.int { - UnknownItemCollection = -1, - PhysicalItemCollection = 0, - ApplicationItemCollection = 1, - LogicalItemCollection = 2, - ReportItemCollection = 3, - NamedArrayItemCollection = 4, - UsageSwitchItemCollection = 5, - UsageModifierItemCollection = 6, +ForceFeedbackEffectKind :: enum i32 { + Constant = 0, + Ramp = 1, + SineWave = 2, + SquareWave = 3, + TriangleWave = 4, + SawtoothUpWave = 5, + SawtoothDownWave = 6, + Spring = 7, + Friction = 8, + Damper = 9, + Inertia = 10, } -RawDevicePhysicalUnitKind :: enum c.int { - Unknown = -1, - None = 0, - Time = 1, - Frequency = 2, - Length = 3, - Velocity = 4, - Acceleration = 5, - Mass = 6, - Momentum = 7, - Force = 8, - Pressure = 9, - Angle = 10, - AngularVelocity = 11, - AngularAcceleration = 12, - AngularMass = 13, - AngularMomentum = 14, - AngularTorque = 15, - ElectricCurrent = 16, - ElectricCharge = 17, - ElectricPotential = 18, - Energy = 19, - Power = 20, - Temperature = 21, - LuminousIntensity = 22, - LuminousFlux = 23, - Illuminance = 24, -} - -RawDeviceReportItemFlag :: enum c.int { - ConstantItem = 0, - ArrayItem = 1, - RelativeItem = 2, - WraparoundItem = 3, - NonlinearItem = 4, - StableItem = 5, - NullableItem = 6, - VolatileItem = 7, - BufferedItem = 8, -} -RawDeviceReportItemFlags :: distinct bit_set[RawDeviceReportItemFlag; c.int] - -RawDeviceReportKind :: enum c.int { - InputReport = 0, - OutputReport = 1, - FeatureReport = 2, -} - -RumbleMotorsFlag :: enum c.int { +RumbleMotors :: distinct bit_set[RumbleMotorsFlag; u32] +RumbleMotorsFlag :: enum u32 { LowFrequency = 0, HighFrequency = 1, LeftTrigger = 2, RightTrigger = 3, } -RumbleMotors :: distinct bit_set[RumbleMotorsFlag; c.int] +RumbleNone :: RumbleMotors{} -SwitchKind :: enum c.int { - UnknownSwitchKind = -1, - TwoWaySwitch = 0, - FourWaySwitch = 1, - EightWaySwitch = 2, +CallbackToken :: distinct u64 + +CURRENT_CALLBACK_TOKEN_VALUE :: CallbackToken(0xFFFFFFFFFFFFFFFF) +INVALID_CALLBACK_TOKEN_VALUE :: CallbackToken(0x0000000000000000) + +ReadingCallback :: #type proc "stdcall" (callbackToken: CallbackToken, ctx: rawptr, reading: ^IGameInputReading, hasOverrunOccured: bool) +DeviceCallback :: #type proc "stdcall" (callbackToken: CallbackToken, ctx: rawptr, device: ^IGameInputDevice, timestamp: u64, currentStatus: DeviceStatus, previousStatus: DeviceStatus) +SystemButtonCallback :: #type proc "stdcall" (callbackToken: CallbackToken, ctx: rawptr, device: ^IGameInputDevice, timestamp: u64, currentButtons: SystemButtons, previousButtons: SystemButtons) +KeyboardLayoutCallback :: #type proc "stdcall" (callbackToken: CallbackToken, ctx: rawptr, device: ^IGameInputDevice, timestamp: u64, currentLayout: u32, previousLayout: u32) + +KeyState :: struct { + scanCode: u32, + codePoint: u32, + virtualKey: u8, + isDeadKey: bool, } -SwitchPosition :: enum c.int { - Center = 0, - Up = 1, - UpRight = 2, - Right = 3, - DownRight = 4, - Down = 5, - DownLeft = 6, - Left = 7, - UpLeft = 8, +MouseState :: struct { + buttons: MouseButtons, + positionX: i64, + positionY: i64, + wheelX: i64, + wheelY: i64, } -SystemButtonsFlag :: enum c.int { - Guide = 0, - Share = 1 , -} -SystemButtons :: distinct bit_set[SystemButtonsFlag; c.int] - -TouchShape :: enum c.int { - Unknown = -1, - Point = 0, - Shape1DLinear = 1, - Shape1DRadial = 2, - Shape1DIrregular = 3, - Shape2DRectangular = 4, - Shape2DElliptical = 5, - Shape2DIrregular = 6, +TouchState :: struct { + touchId: u64, + sensorIndex: u32, + positionX: f32, + positionY: f32, + pressure: f32, + proximity: f32, + contactRectTop: f32, + contactRectLeft: f32, + contactRectRight: f32, + contactRectBottom: f32, } -UiNavigationButtonsFlag :: enum c.int { - Menu = 0, - View = 1, - Accept = 2, - Cancel = 3, - Up = 4, - Down = 5, - Left = 6, - Right = 7, - Context1 = 8, - Context2 = 9, - Context3 = 10, - Context4 = 11, - PageUp = 12, - PageDown = 13, - PageLeft = 14, - PageRight = 15, - ScrollUp = 16, - ScrollDown = 17, - ScrollLeft = 18, - ScrollRight = 19, -} -UiNavigationButtons :: distinct bit_set[UiNavigationButtonsFlag; c.int] - -// Structs - -APP_LOCAL_DEVICE_ID :: distinct [32]byte - -ArcadeStickInfo :: struct { - menuButtonLabel: Label, - viewButtonLabel: Label, - stickUpLabel: Label, - stickDownLabel: Label, - stickLeftLabel: Label, - stickRightLabel: Label, - actionButton1Label: Label, - actionButton2Label: Label, - actionButton3Label: Label, - actionButton4Label: Label, - actionButton5Label: Label, - actionButton6Label: Label, - specialButton1Label: Label, - specialButton2Label: Label, +MotionState :: struct { + accelerationX: f32, + accelerationY: f32, + accelerationZ: f32, + angularVelocityX: f32, + angularVelocityY: f32, + angularVelocityZ: f32, + magneticFieldX: f32, + magneticFieldY: f32, + magneticFieldZ: f32, + orientationW: f32, + orientationX: f32, + orientationY: f32, + orientationZ: f32, + accelerometerAccuracy: MotionAccuracy, + gyroscopeAccuracy: MotionAccuracy, + magnetometerAccuracy: MotionAccuracy, + orientationAccuracy: MotionAccuracy, } ArcadeStickState :: struct { buttons: ArcadeStickButtons, } +FlightStickState :: struct { + buttons: FlightStickButtons, + hatSwitch: SwitchPosition, + roll: f32, + pitch: f32, + yaw: f32, + throttle: f32, +} + +GamepadState :: struct { + buttons: GamepadButtons, + leftTrigger: f32, + rightTrigger: f32, + leftThumbstickX: f32, + leftThumbstickY: f32, + rightThumbstickX: f32, + rightThumbstickY: f32, +} + +RacingWheelState :: struct { + buttons: RacingWheelButtons, + patternShifterGear: i32, + wheel: f32, + throttle: f32, + brake: f32, + clutch: f32, + handbrake: f32, +} + +UiNavigationState :: struct { + buttons: UiNavigationButtons, +} + BatteryState :: struct { chargeRate: f32, maxChargeRate: f32, @@ -503,6 +591,64 @@ BatteryState :: struct { status: BatteryStatus, } +String :: struct { + sizeInBytes: u32, + codePointCount: u32, + data: [^]byte, +} + +Usage :: struct { + page: u16, + id: u16, +} + +Version :: struct { + major: u16, + minor: u16, + build: u16, + revision: u16, +} + +RawDeviceItemCollectionInfo :: struct { + kind: RawDeviceItemCollectionKind, + childCount: u32, + siblingCount: u32, + usageCount: u32, + usages: [^]Usage `fmt:"v,usageCount"`, + parent: ^RawDeviceItemCollectionInfo, + firstSibling: ^RawDeviceItemCollectionInfo, + previousSibling: ^RawDeviceItemCollectionInfo, + nextSibling: ^RawDeviceItemCollectionInfo, + lastSibling: ^RawDeviceItemCollectionInfo, + firstChild: ^RawDeviceItemCollectionInfo, + lastChild: ^RawDeviceItemCollectionInfo, +} + +RawDeviceReportItemInfo :: struct { + bitOffset: u32, + bitSize: u32, + logicalMin: i64, + logicalMax: i64, + physicalMin: f64, + physicalMax: f64, + physicalUnits: RawDevicePhysicalUnitKind, + rawPhysicalUnits: u32, + rawPhysicalUnitsExponent: i32, + flags: RawDeviceReportItemFlags, + usageCount: u32, + usages: [^]Usage `fmt:"v,usageCount"`, + collection: ^RawDeviceItemCollectionInfo, + itemString: ^String, +} + +RawDeviceReportInfo :: struct { + kind: RawDeviceReportKind, + id: u32, + size: u32, + itemCount: u32, + items: [^]RawDeviceReportItemInfo `fmt:"v,itemCount"`, +} + ControllerAxisInfo :: struct { mappedInputKinds: Kind, label: Label, @@ -541,6 +687,166 @@ ControllerSwitchInfo :: struct { inputReportItem: ^RawDeviceReportItemInfo, } +KeyboardInfo :: struct { + kind: KeyboardKind, + layout: u32, + keyCount: u32, + functionKeyCount: u32, + maxSimultaneousKeys: u32, + platformType: u32, + platformSubtype: u32, + nativeLanguage: ^String, +} + +MouseInfo :: struct { + supportedButtons: MouseButtons, + sampleRate: u32, + sensorDpi: u32, + hasWheelX: bool, + hasWheelY: bool, +} + +TouchSensorInfo :: struct { + mappedInputKinds: Kind, + label: Label, + location: Location, + locationId: u32, + resolutionX: u64, + resolutionY: u64, + shape: TouchShape, + aspectRatio: f32, + orientation: f32, + physicalWidth: f32, + physicalHeight: f32, + maxPressure: f32, + maxProximity: f32, + maxTouchPoints: u32, +} + +MotionInfo :: struct { + maxAcceleration: f32, + maxAngularVelocity: f32, + maxMagneticFieldStrength: f32, +} + +ArcadeStickInfo :: struct { + menuButtonLabel: Label, + viewButtonLabel: Label, + stickUpLabel: Label, + stickDownLabel: Label, + stickLeftLabel: Label, + stickRightLabel: Label, + actionButton1Label: Label, + actionButton2Label: Label, + actionButton3Label: Label, + actionButton4Label: Label, + actionButton5Label: Label, + actionButton6Label: Label, + specialButton1Label: Label, + specialButton2Label: Label, +} + +FlightStickInfo :: struct { + menuButtonLabel: Label, + viewButtonLabel: Label, + firePrimaryButtonLabel: Label, + fireSecondaryButtonLabel: Label, + hatSwitchKind: SwitchKind, +} + +GamepadInfo :: struct { + menuButtonLabel: Label, + viewButtonLabel: Label, + aButtonLabel: Label, + bButtonLabel: Label, + xButtonLabel: Label, + yButtonLabel: Label, + dpadUpLabel: Label, + dpadDownLabel: Label, + dpadLeftLabel: Label, + dpadRightLabel: Label, + leftShoulderButtonLabel: Label, + rightShoulderButtonLabel: Label, + leftThumbstickButtonLabel: Label, + rightThumbstickButtonLabel: Label, +} + +RacingWheelInfo :: struct { + menuButtonLabel: Label, + viewButtonLabel: Label, + previousGearButtonLabel: Label, + nextGearButtonLabel: Label, + dpadUpLabel: Label, + dpadDownLabel: Label, + dpadLeftLabel: Label, + dpadRightLabel: Label, + hasClutch: bool, + hasHandbrake: bool, + hasPatternShifter: bool, + minPatternShifterGear: i32, + maxPatternShifterGear: i32, + maxWheelAngle: f32, +} + +UiNavigationInfo :: struct { + menuButtonLabel: Label, + viewButtonLabel: Label, + acceptButtonLabel: Label, + cancelButtonLabel: Label, + upButtonLabel: Label, + downButtonLabel: Label, + leftButtonLabel: Label, + rightButtonLabel: Label, + contextButton1Label: Label, + contextButton2Label: Label, + contextButton3Label: Label, + contextButton4Label: Label, + pageUpButtonLabel: Label, + pageDownButtonLabel: Label, + pageLeftButtonLabel: Label, + pageRightButtonLabel: Label, + scrollUpButtonLabel: Label, + scrollDownButtonLabel: Label, + scrollLeftButtonLabel: Label, + scrollRightButtonLabel: Label, + guideButtonLabel: Label, +} + +ForceFeedbackMotorInfo :: struct { + supportedAxes: FeedbackAxes, + location: Location, + locationId: u32, + maxSimultaneousEffects: u32, + isConstantEffectSupported: bool, + isRampEffectSupported: bool, + isSineWaveEffectSupported: bool, + isSquareWaveEffectSupported: bool, + isTriangleWaveEffectSupported: bool, + isSawtoothUpWaveEffectSupported: bool, + isSawtoothDownWaveEffectSupported: bool, + isSpringEffectSupported: bool, + isFrictionEffectSupported: bool, + isDamperEffectSupported: bool, + isInertiaEffectSupported: bool, +} + +HapticWaveformInfo :: struct { + usage: Usage, + isDurationSupported: bool, + isIntensitySupported: bool, + isRepeatSupported: bool, + isRepeatDelaySupported: bool, + defaultDuration: u64, +} + +HapticFeedbackMotorInfo :: struct { + mappedRumbleMotor: RumbleMotors, + location: Location, + locationId: u32, + waveformCount: u32, + waveformInfo: [^]HapticWaveformInfo `fmt:"v,waveformCount"`, +} + DeviceInfo :: struct { infoSize: u32, vendorId: u16, @@ -569,60 +875,28 @@ DeviceInfo :: struct { hapticFeedbackMotorCount: u32, deviceStringCount: u32, deviceDescriptorSize: u32, - inputReportInfo: ^RawDeviceReportInfo, - outputReportInfo: ^RawDeviceReportInfo, - featureReportInfo: ^RawDeviceReportInfo, - controllerAxisInfo: ^ControllerAxisInfo, - controllerButtonInfo: ^ControllerButtonInfo, - controllerSwitchInfo: ^ControllerSwitchInfo, + inputReportInfo: [^]RawDeviceReportInfo `fmt:"v,inputReportCount"`, + outputReportInfo: [^]RawDeviceReportInfo `fmt:"v,outputReportCount"`, + featureReportInfo: [^]RawDeviceReportInfo `fmt:"v,featureReportCount"`, + controllerAxisInfo: [^]ControllerAxisInfo `fmt:"v,controllerAxisCount"`, + controllerButtonInfo: [^]ControllerButtonInfo `fmt:"v,controllerButtonCount"`, + controllerSwitchInfo: [^]ControllerSwitchInfo `fmt:"v,controllerSwitchCount"`, keyboardInfo: ^KeyboardInfo, mouseInfo: ^MouseInfo, - touchSensorInfo: ^TouchSensorInfo, + touchSensorInfo: [^]TouchSensorInfo `fmt:"v,touchSensorCount"`, motionInfo: ^MotionInfo, arcadeStickInfo: ^ArcadeStickInfo, flightStickInfo: ^FlightStickInfo, gamepadInfo: ^GamepadInfo, racingWheelInfo: ^RacingWheelInfo, uiNavigationInfo: ^UiNavigationInfo, - forceFeedbackMotorInfo: ^ForceFeedbackMotorInfo, - hapticFeedbackMotorInfo: ^HapticFeedbackMotorInfo, + forceFeedbackMotorInfo: [^]ForceFeedbackMotorInfo `fmt:"v,forceFeedbackMotorCount"`, + hapticFeedbackMotorInfo: [^]HapticFeedbackMotorInfo `fmt:"v,hapticFeedbackMotorCount"`, displayName: ^String, - deviceStrings: ^String, + deviceStrings: [^]String `fmt:"v,deviceStringCount"`, deviceDescriptorData: rawptr, } -FlightStickInfo :: struct { - menuButtonLabel: Label, - viewButtonLabel: Label, - firePrimaryButtonLabel: Label, - fireSecondaryButtonLabel: Label, - hatSwitchKind: SwitchKind, -} - -FlightStickState :: struct { - buttons: FlightStickButtons, - hatSwitch: SwitchPosition, - roll: f32, - pitch: f32, - yaw: f32, - throttle: f32, -} - -ForceFeedbackConditionParams :: struct { - magnitude: ForceFeedbackMagnitude, - positiveCoefficient: f32, - negativeCoefficient: f32, - maxPositiveMagnitude: f32, - maxNegativeMagnitude: f32, - deadZone: f32, - bias: f32, -} - -ForceFeedbackConstantParams :: struct { - envelope: ForceFeedbackEnvelope, - magnitude: ForceFeedbackMagnitude, -} - ForceFeedbackEnvelope :: struct { attackDuration: u64, sustainDuration: u64, @@ -644,39 +918,19 @@ ForceFeedbackMagnitude :: struct { normal: f32, } -ForceFeedbackMotorInfo :: struct { - supportedAxes: FeedbackAxes, - location: Location, - locationId: u32, - maxSimultaneousEffects: u32, - isConstantEffectSupported: bool, - isRampEffectSupported: bool, - isSineWaveEffectSupported: bool, - isSquareWaveEffectSupported: bool, - isTriangleWaveEffectSupported: bool, - isSawtoothUpWaveEffectSupported: bool, - isSawtoothDownWaveEffectSupported: bool, - isSpringEffectSupported: bool, - isFrictionEffectSupported: bool, - isDamperEffectSupported: bool, - isInertiaEffectSupported: bool, +ForceFeedbackConditionParams :: struct { + magnitude: ForceFeedbackMagnitude, + positiveCoefficient: f32, + negativeCoefficient: f32, + maxPositiveMagnitude: f32, + maxNegativeMagnitude: f32, + deadZone: f32, + bias: f32, } -ForceFeedbackParams :: struct { - kind: ForceFeedbackEffectKind, - using _: struct #raw_union { - constant: ForceFeedbackConstantParams, - ramp: ForceFeedbackRampParams, - sineWave: ForceFeedbackPeriodicParams, - squareWave: ForceFeedbackPeriodicParams, - triangleWave: ForceFeedbackPeriodicParams, - sawtoothUpWave: ForceFeedbackPeriodicParams, - sawtoothDownWave: ForceFeedbackPeriodicParams, - spring: ForceFeedbackConditionParams, - friction: ForceFeedbackConditionParams, - damper: ForceFeedbackConditionParams, - inertia: ForceFeedbackConditionParams, - }, +ForceFeedbackConstantParams :: struct { + envelope: ForceFeedbackEnvelope, + magnitude: ForceFeedbackMagnitude, } ForceFeedbackPeriodicParams :: struct { @@ -693,39 +947,21 @@ ForceFeedbackRampParams :: struct { endMagnitude: ForceFeedbackMagnitude, } -GamepadInfo :: struct { - menuButtonLabel: Label, - viewButtonLabel: Label, - aButtonLabel: Label, - bButtonLabel: Label, - xButtonLabel: Label, - yButtonLabel: Label, - dpadUpLabel: Label, - dpadDownLabel: Label, - dpadLeftLabel: Label, - dpadRightLabel: Label, - leftShoulderButtonLabel: Label, - rightShoulderButtonLabel: Label, - leftThumbstickButtonLabel: Label, - rightThumbstickButtonLabel: Label, -} - -GamepadState :: struct { - buttons: GamepadButtons, - leftTrigger: f32, - rightTrigger: f32, - leftThumbstickX: f32, - leftThumbstickY: f32, - rightThumbstickX: f32, - rightThumbstickY: f32, -} - -HapticFeedbackMotorInfo :: struct { - mappedRumbleMotor: RumbleMotors, - location: Location, - locationId: u32, - waveformCount: u32, - waveformInfo: [^]HapticWaveformInfo `fmt:"v,waveformCount"`, +ForceFeedbackParams :: struct { + kind: ForceFeedbackEffectKind, + using data: struct #raw_union { + constant: ForceFeedbackConstantParams, + ramp: ForceFeedbackRampParams, + sineWave: ForceFeedbackPeriodicParams, + squareWave: ForceFeedbackPeriodicParams, + triangleWave: ForceFeedbackPeriodicParams, + sawtoothUpWave: ForceFeedbackPeriodicParams, + sawtoothDownWave: ForceFeedbackPeriodicParams, + spring: ForceFeedbackConditionParams, + friction: ForceFeedbackConditionParams, + damper: ForceFeedbackConditionParams, + inertia: ForceFeedbackConditionParams, + }, } HapticFeedbackParams :: struct { @@ -736,142 +972,6 @@ HapticFeedbackParams :: struct { repeatDelay: u64, } -HapticWaveformInfo :: struct { - usage: Usage, - isDurationSupported: bool, - isIntensitySupported: bool, - isRepeatSupported: bool, - isRepeatDelaySupported: bool, - defaultDuration: u64, -} - -KeyboardInfo :: struct { - kind: KeyboardKind, - layout: u32, - keyCount: u32, - functionKeyCount: u32, - maxSimultaneousKeys: u32, - platformType: u32, - platformSubtype: u32, - nativeLanguage: ^String, -} - -KeyState :: struct { - scanCode: u32, - codePoint: u32, - virtualKey: u8, - isDeadKey: bool, -} - -MotionInfo :: struct { - maxAcceleration: f32, - maxAngularVelocity: f32, - maxMagneticFieldStrength: f32, -} - -MotionState :: struct { - accelerationX: f32, - accelerationY: f32, - accelerationZ: f32, - angularVelocityX: f32, - angularVelocityY: f32, - angularVelocityZ: f32, - magneticFieldX: f32, - magneticFieldY: f32, - magneticFieldZ: f32, - orientationW: f32, - orientationX: f32, - orientationY: f32, - orientationZ: f32, - accelerometerAccuracy: MotionAccuracy, - gyroscopeAccuracy: MotionAccuracy, - magnetometerAccuracy: MotionAccuracy, - orientationAccuracy: MotionAccuracy, -} - -MouseInfo :: struct { - supportedButtons: MouseButtons, - sampleRate: u32, - sensorDpi: u32, - hasWheelX: bool, - hasWheelY: bool, -} - -MouseState :: struct { - buttons: MouseButtons, - positionX: i64, - positionY: i64, - wheelX: i64, - wheelY: i64, -} - -RacingWheelInfo :: struct { - menuButtonLabel: Label, - viewButtonLabel: Label, - previousGearButtonLabel: Label, - nextGearButtonLabel: Label, - dpadUpLabel: Label, - dpadDownLabel: Label, - dpadLeftLabel: Label, - dpadRightLabel: Label, - hasClutch: bool, - hasHandbrake: bool, - hasPatternShifter: bool, - minPatternShifterGear: i32, - maxPatternShifterGear: i32, - maxWheelAngle: f32, -} - -RacingWheelState :: struct { - buttons: RacingWheelButtons, - patternShifterGear: i32, - wheel: f32, - throttle: f32, - brake: f32, - clutch: f32, - handbrake: f32, -} - -RawDeviceItemCollectionInfo :: struct { - kind: RawDeviceItemCollectionKind, - childCount: u32, - siblingCount: u32, - usageCount: u32, - usages: [^]Usage `fmt:v,usageCount`, - parent: ^RawDeviceItemCollectionInfo, - firstSibling: ^RawDeviceItemCollectionInfo, - previousSibling: ^RawDeviceItemCollectionInfo, - nextSibling: ^RawDeviceItemCollectionInfo, - lastSibling: ^RawDeviceItemCollectionInfo, - firstChild: ^RawDeviceItemCollectionInfo, - lastChild: ^RawDeviceItemCollectionInfo, -} - -RawDeviceReportInfo :: struct { - kind: RawDeviceReportKind, - id: u32, - size: u32, - itemCount: u32, - items: [^]RawDeviceReportItemInfo `fmt:"v,itemCount"`, -} - -RawDeviceReportItemInfo :: struct { - bitOffset: u32, - bitSize: u32, - logicalMin: i64, - logicalMax: i64, - physicalMin: f64, - physicalMax: f64, - physicalUnits: RawDevicePhysicalUnitKind, - rawPhysicalUnits: u32, - rawPhysicalUnitsExponent: i32, - flags: RawDeviceReportItemFlags, - usageCount: u32, - usages: [^]Usage `fmt:"v,usageCount"`, - collection: ^RawDeviceItemCollectionInfo, - itemString: ^String, -} - RumbleParams :: struct { lowFrequency: f32, highFrequency: f32, @@ -879,88 +979,6 @@ RumbleParams :: struct { rightTrigger: f32, } -String :: struct { - sizeInBytes: u32, - codePointCount: u32, - data: [^]byte, -} - -TouchSensorInfo :: struct { - mappedInputKinds: Kind, - label: Label, - location: Location, - locationId: u32, - resolutionX: u64, - resolutionY: u64, - shape: TouchShape, - aspectRatio: f32, - orientation: f32, - physicalWidth: f32, - physicalHeight: f32, - maxPressure: f32, - maxProximity: f32, - maxTouchPoints: u32, -} - -TouchState :: struct { - touchId: u64, - sensorIndex: u32, - positionX: f32, - positionY: f32, - pressure: f32, - proximity: f32, - contactRectTop: f32, - contactRectLeft: f32, - contactRectRight: f32, - contactRectBottom: f32, -} - -UiNavigationInfo :: struct { - menuButtonLabel: Label, - viewButtonLabel: Label, - acceptButtonLabel: Label, - cancelButtonLabel: Label, - upButtonLabel: Label, - downButtonLabel: Label, - leftButtonLabel: Label, - rightButtonLabel: Label, - contextButton1Label: Label, - contextButton2Label: Label, - contextButton3Label: Label, - contextButton4Label: Label, - pageUpButtonLabel: Label, - pageDownButtonLabel: Label, - pageLeftButtonLabel: Label, - pageRightButtonLabel: Label, - scrollUpButtonLabel: Label, - scrollDownButtonLabel: Label, - scrollLeftButtonLabel: Label, - scrollRightButtonLabel: Label, - guideButtonLabel: Label, -} - -UiNavigationState :: struct { - buttons: UiNavigationButtons, -} - -Usage :: struct { - page: u16, - id: u16, -} - -Version :: struct { - major: u16, - minor: u16, - build: u16, - revision: u16, -} - -// COM Interfaces - -IUnknown :: windows.IUnknown -IUnknown_VTable :: windows.IUnknown_VTable -IID :: windows.GUID - IGameInput_UUID_STRING :: "11BE2A7E-4254-445A-9C09-FFC40F006918" IGameInput_UUID := &IID{0x11BE2A7E, 0x4254, 0x445A, {0x9C, 0x09, 0xFF, 0xC4, 0x0F, 0x00, 0x69, 0x18}} IGameInput :: struct #raw_union { @@ -985,7 +1003,7 @@ IGameInput_VTable :: struct { FindDeviceFromId: proc "system" (this: ^IGameInput, value: ^APP_LOCAL_DEVICE_ID, device: ^^IGameInputDevice) -> HRESULT, FindDeviceFromObject: proc "system" (this: ^IGameInput, value: ^IUnknown, device: ^^IGameInputDevice) -> HRESULT, FindDeviceFromPlatformHandle: proc "system" (this: ^IGameInput, value: HANDLE, device: ^^IGameInputDevice) -> HRESULT, - FindDeviceFromPlatformString: proc "system" (this: ^IGameInput, value: windows.LPCWSTR, device: ^^IGameInputDevice) -> HRESULT, + FindDeviceFromPlatformString: proc "system" (this: ^IGameInput, value: win.LPCWSTR, device: ^^IGameInputDevice) -> HRESULT, EnableOemDeviceSupport: proc "system" (this: ^IGameInput, vendorId: u16, productId: u16, interfaceNumber: u8, collectionNumber: u8) -> HRESULT, SetFocusPolicy: proc "system" (this: ^IGameInput, policy: FocusPolicy), } @@ -999,7 +1017,7 @@ IGameInputReading :: struct #raw_union { IGameInputReading_VTable :: struct { using iunknown_vtable: IUnknown_VTable, GetInputKind: proc "system" (this: ^IGameInputReading) -> Kind, - GetSequenceNumber: proc "system" (this: ^IGameInputReading) -> u64, + GetSequenceNumber: proc "system" (this: ^IGameInputReading, inputKind: Kind) -> u64, GetTimestamp: proc "system" (this: ^IGameInputReading) -> u64, GetDevice: proc "system" (this: ^IGameInputReading, device: ^^IGameInputDevice), GetRawReport: proc "system" (this: ^IGameInputReading, report: ^^IGameInputRawDeviceReport) -> bool, @@ -1046,7 +1064,7 @@ IGameInputDevice_Vtable :: struct { SetRawDeviceFeature: proc "system" (this: ^IGameInputDevice, report: ^IGameInputRawDeviceReport) -> HRESULT, SendRawDeviceOutput: proc "system" (this: ^IGameInputDevice, report: ^IGameInputRawDeviceReport) -> HRESULT, SendRawDeviceOutputWithResponse: proc "system" (this: ^IGameInputDevice, requestReport: ^IGameInputRawDeviceReport, responseReport: ^^IGameInputRawDeviceReport) -> HRESULT, - ExecuteRawDeviceIoControl: proc "system" (this: ^IGameInputDevice, controlCode: u32, inputBufferSize: c.size_t, inputBuffer: rawptr, outputBufferSize: c.size_t, outputBuffer: rawptr, outputSize: ^c.size_t) -> HRESULT, + ExecuteRawDeviceIoControl: proc "system" (this: ^IGameInputDevice, controlCode: u32, inputBufferSize: win.SIZE_T, inputBuffer: rawptr, outputBufferSize: win.SIZE_T, outputBuffer: rawptr, outputSize: ^win.SIZE_T) -> HRESULT, AcquireExclusiveRawDeviceAccess: proc "system" (this: ^IGameInputDevice, timeoutInMicroseconds: u64) -> bool, ReleaseExclusiveRawDeviceAccess: proc "system" (this: ^IGameInputDevice), } @@ -1091,18 +1109,19 @@ IGameInputRawDeviceReport_Vtable :: struct { using iunknown_vtable: IUnknown_VTable, GetDevice: proc "system" (this: ^IGameInputRawDeviceReport, device: ^^IGameInputDevice), GetReportInfo: proc "system" (this: ^IGameInputRawDeviceReport) -> ^RawDeviceReportInfo, - GetRawDataSize: proc "system" (this: ^IGameInputRawDeviceReport) -> c.size_t, - GetRawData: proc "system" (this: ^IGameInputRawDeviceReport, bufferSize: c.size_t, buffer: rawptr) -> c.size_t, - SetRawData: proc "system" (this: ^IGameInputRawDeviceReport, bufferSize: c.size_t, buffer: rawptr) -> bool, + GetRawDataSize: proc "system" (this: ^IGameInputRawDeviceReport) -> win.SIZE_T, + GetRawData: proc "system" (this: ^IGameInputRawDeviceReport, bufferSize: win.SIZE_T, buffer: rawptr) -> win.SIZE_T, + SetRawData: proc "system" (this: ^IGameInputRawDeviceReport, bufferSize: win.SIZE_T, buffer: rawptr) -> bool, GetItemValue: proc "system" (this: ^IGameInputRawDeviceReport, itemIndex: u32, value: ^u64) -> bool, SetItemValue: proc "system" (this: ^IGameInputRawDeviceReport, itemIndex: u32, value: u64) -> bool, ResetItemValue: proc "system" (this: ^IGameInputRawDeviceReport, itemIndex: u32) -> bool, ResetAllItems: proc "system" (this: ^IGameInputRawDeviceReport) -> bool, } -// Functions -HRESULT :: windows.HRESULT -HANDLE :: windows.HANDLE +@(default_calling_convention="system", link_prefix="GameInput") +foreign wgi { + Create :: proc(gameInput: ^^IGameInput) -> HRESULT --- +} DEVICE_DISCONNECTED :: HRESULT(-0x7C75FFFF) DEVICE_NOT_FOUND :: HRESULT(-0x7C75FFFE) @@ -1110,20 +1129,3 @@ READING_NOT_FOUND :: HRESULT(-0x7C75FFFD) REFERENCE_READING_TOO_OLD :: HRESULT(-0x7C75FFFC) TIMESTAMP_OUT_OF_RANGE :: HRESULT(-0x7C75FFFB) INSUFFICIENT_FORCE_FEEDBACK_RESOURCES :: HRESULT(-0x7C75FFFA) - -CallbackToken :: distinct u64 - -CURRENT_CALLBACK_TOKEN_VALUE :: CallbackToken(0xFFFFFFFFFFFFFFFF) -INVALID_CALLBACK_TOKEN_VALUE :: CallbackToken(0x0000000000000000) - -@(default_calling_convention="system", link_prefix="GameInput") -foreign wgi { - Create :: proc(gameInput: ^^IGameInput) -> HRESULT --- -} - -DeviceCallback :: #type proc "system" (callbackToken: CallbackToken, ctx: rawptr, device: ^IGameInputDevice, timestamp: u64, currentState: DeviceStatus, previousState: DeviceStatus) -GuideButtonCallback :: #type proc "system" (callbackToken: CallbackToken, ctx: rawptr, device: ^IGameInputDevice, timestamp: u64, isPressed: bool) -SystemButtonCallback :: #type proc "system" (callbackToken: CallbackToken, ctx: rawptr, device: ^IGameInputDevice, timestamp: u64, currentState: DeviceStatus, previousState: DeviceStatus) -ReadingCallback :: #type proc "system" (callbackToken: CallbackToken, ctx: rawptr, reading: ^IGameInputReading, hasOverrunOccured: bool) -KeyboardLayoutCallback :: #type proc "system" (callbackToken: CallbackToken, ctx: rawptr, device: ^IGameInputDevice, timestamp: u64, currentState: DeviceStatus, previousState: DeviceStatus) - diff --git a/vendor/windows/XAudio2/hrtfapoapi.odin b/vendor/windows/XAudio2/hrtfapoapi.odin new file mode 100644 index 000000000..45f1cdb42 --- /dev/null +++ b/vendor/windows/XAudio2/hrtfapoapi.odin @@ -0,0 +1,149 @@ +#+build windows + +package windows_xaudio2 + +import win "core:sys/windows" + +foreign import hrtf "system:hrtfapo.lib" + +HRTF_MAX_GAIN_LIMIT :: 12.0 +HRTF_MIN_GAIN_LIMIT :: -96.0 +HRTF_MIN_UNITY_GAIN_DISTANCE :: 0.05 +HRTF_DEFAULT_UNITY_GAIN_DISTANCE :: 1.0 +HRTF_DEFAULT_CUTOFF_DISTANCE :: 3.402823466e+38 + +//! Represents a position in 3D space, using a right-handed coordinate system. +HrtfPosition :: struct { + x: f32, + y: f32, + z: f32, +} + +//! Indicates the orientation of an HRTF directivity object. This is a row-major 3x3 rotation matrix. +HrtfOrientation :: struct { + element: [9]f32, +} + +//! Indicates one of several stock directivity patterns. +HrtfDirectivityType :: enum i32 { + //! The sound emission is in all directions. + OmniDirectional = 0, + //! The sound emission is a cardiod shape. + Cardioid, + //! The sound emission is a cone. + Cone, +} + +//! Indicates one of several stock environment types. +HrtfEnvironment :: enum i32 { + //! A small room. + Small = 0, + //! A medium-sized room. + Medium, + //! A large enclosed space. + Large, + //! An outdoor space. + Outdoors, +} + +//! Base directivity pattern descriptor. Describes the type of directivity applied to a sound. +//! The scaling parameter is used to interpolate between directivity behavior and omnidirectional, it determines how much attenuation is applied to the source outside of the directivity pattern and controls how directional the source is. +HrtfDirectivity :: struct { + //! Indicates the type of directivity. + type: HrtfDirectivityType, + //! A normalized value between zero and one. Specifies the amount of linear interpolation between omnidirectional sound and the full directivity pattern, where 0 is fully omnidirectional and 1 is fully directional. + scaling: f32, +} + +//! Describes a cardioid directivity pattern. +HrtfDirectivityCardioid :: struct { + //! Descriptor for the cardioid pattern. The type parameter must be set to HrtfDirectivityType.Cardioid. + directivity: HrtfDirectivity, + //! Order controls the shape of the cardioid. The higher order the shape, the narrower it is. Must be greater than 0 and less than or equal to 32. + order: f32, +} + +//! Describes a cone directivity. +//! Attenuation is 0 inside the inner cone. +//! Attenuation is linearly interpolated between the inner cone, which is defined by innerAngle, and the outer cone, which is defined by outerAngle. +HrtfDirectivityCone :: struct { + //! Descriptor for the cone pattern. The type parameter must be set to HrtfDirectivityType.Cone. + directivity: HrtfDirectivity, + //! Angle, in radians, that defines the inner cone. Must be between 0 and TAU. + innerAngle: f32, + //! Angle, in radians, that defines the outer cone. Must be between 0 and TAU. + outerAngle: f32, +} + +//! Indicates a distance-based decay type applied to a sound. +HrtfDistanceDecayType :: enum i32 { + //! Simulates natural decay with distance, as constrained by minimum and maximum gain distance limits. Drops to silence at rolloff distance. + NaturalDecay = 0, + //! Used to set up a custom gain curve, within the maximum and minimum gain limit. + CustomDecay, +} + +//! Describes a distance-based decay behavior. +HrtfDistanceDecay :: struct { + //! The type of decay behavior, natural or custom. + type: HrtfDistanceDecayType, + //! The maximum gain limit applied at any distance. Applies to both natural and custom decay. This value is specified in dB, with a range from -96 to 12 inclusive. The default value is 12 dB. + maxGain: f32, + //! The minimum gain limit applied at any distance. Applies to both natural and custom decay. This value is specified in dB, with a range from -96 to 12 inclusive. The default value is -96 dB. + minGain: f32, + //! The distance at which the gain is 0dB. Applies to natural decay only. This value is specified in meters, with a range from 0.05 to infinity (max(f32)). The default value is 1 meter. + unityGainDistance: f32, + //! The distance at which output is silent. Applies to natural decay only. This value is specified in meters, with a range from zero (non-inclusive) to infinity (max(f32)). The default value is infinity. + cutoffDistance: f32, +} + +//! Specifies parameters used to initialize HRTF. +//! Instances of the XAPO interface are created by using the CreateHrtfApo() API: +//! ```CreateHrtfApo :: proc(pInit: HrtfApoInit, ppXapo: ^^IXAPO) -> HRESULT``` +HrtfApoInit :: struct { + //! The decay type. If you pass in nil, the default value will be used. The default is natural decay. + distanceDecay: ^HrtfDistanceDecay, + //! The directivity type. If you pass in nil, the default value will be used. The default directivity is omni-directional. + directivity: ^HrtfDirectivity, +} + +//! Creates an instance of the XAPO object. +//! Format requirements: +//! * Input: mono, 48 kHz, 32-bit float PCM. +//! * Output: stereo, 48 kHz, 32-bit float PCM. +//! Audio is processed in blocks of 1024 samples. +//! Returns: +//! S_OK for success, any other value indicates failure. +//! Returns E_NOTIMPL on unsupported platforms. +@(default_calling_convention="system") +foreign hrtf { + CreateHrtfApo :: proc( + //! Pointer to an HrtfApoInit struct. Specifies parameters for XAPO interface initialization. + #by_ptr init: HrtfApoInit, + //! Returns the new instance of the XAPO interface. + xApo: ^^IXAPO, + ) -> HRESULT --- +} + +//! The interface used to set parameters that control how HRTF is applied to a sound. +IXAPOHrtfParameters_UUID_STRING :: "15B3CD66-E9DE-4464-B6E6-2BC3CF63D455" +IXAPOHrtfParameters_UUID := &win.IID{0x15B3CD66, 0xE9DE, 0x4464, {0xB6, 0xE6, 0x2B, 0xC3, 0xCF, 0x63, 0xD4, 0x55}} +IXAPOHrtfParameters :: struct #raw_union { + #subtype iunknown: IUnknown, + using ixapohrtfparameters_vtable: ^IXAPOHrtfParameters_VTable, +} +IXAPOHrtfParameters_VTable :: struct { + using iunknown_vtable: IUnknown_VTable, + + // HRTF params + //! The position of the sound relative to the listener. + SetSourcePosition: proc "system" (this: ^IXAPOHrtfParameters, position: ^HrtfPosition) -> HRESULT, + //! The rotation matrix for the source orientation, with respect to the listener's frame of reference (the listener's coordinate system). + SetSourceOrientation: proc "system" (this: ^IXAPOHrtfParameters, orientation: ^HrtfOrientation) -> HRESULT, + //! The custom direct path gain value for the current source position. Valid only for sounds played with the HrtfDistanceDecayType. Custom decay type. + SetSourceGain: proc "system" (this: ^IXAPOHrtfParameters, gain: f32) -> HRESULT, + + // Distance cue params + //! Selects the acoustic environment to simulate. + SetEnvironment: proc "system" (this: ^IXAPOHrtfParameters, environment: HrtfEnvironment) -> HRESULT, +} diff --git a/vendor/windows/XAudio2/x3daudio.odin b/vendor/windows/XAudio2/x3daudio.odin index 27c4dc9fa..c24e627e2 100644 --- a/vendor/windows/XAudio2/x3daudio.odin +++ b/vendor/windows/XAudio2/x3daudio.odin @@ -1,7 +1,7 @@ #+build windows /* NOTES: - 1. Definition of terms: + 1. Definition of terms: LFE: Low Frequency Effect -- always omnidirectional. LPF: Low Pass Filter, divided into two classifications: Direct -- Applied to the direct signal path, @@ -9,15 +9,15 @@ Reverb -- Applied to the reverb signal path, used for occlusion effects only. - 2. Volume level is expressed as a linear amplitude scaler: - 1.0f represents no attenuation applied to the original signal, - 0.5f denotes an attenuation of 6dB, and 0.0f results in silence. - Amplification (volume > 1.0f) is also allowed, and is not clamped. + 2. Volume level is expressed as a linear amplitude scaler: + 1.0 represents no attenuation applied to the original signal, + 0.5 denotes an attenuation of 6dB, and 0.0 results in silence. + Amplification (volume > 1.0) is also allowed, and is not clamped. - LPF values range from 1.0f representing all frequencies pass through, - to 0.0f which results in silence as all frequencies are filtered out. + LPF values range from 1.0 representing all frequencies pass through, + to 0.0 which results in silence as all frequencies are filtered out. - 3. X3DAudio uses a left-handed Cartesian coordinate system with values + 3. X3DAudio uses a left-handed Cartesian coordinate system with values on the x-axis increasing from left to right, on the y-axis from bottom to top, and on the z-axis from near to far. Azimuths are measured clockwise from a given reference direction. @@ -29,7 +29,7 @@ Metric constants are supplied only as a convenience. Distance is calculated using the Euclidean norm formula. - 4. Only real values are permissible with functions using 32-bit + 4. Only real values are permissible with functions using 32-bit float parameters -- NAN and infinite values are not accepted. All computation occurs in 32-bit precision mode. */ @@ -37,34 +37,13 @@ package windows_xaudio2 import "core:math" +import win "core:sys/windows" foreign import xa2 "system:xaudio2.lib" +SPEAKER_FLAGS :: win.SPEAKER_FLAGS + //---------------------------------------------------// -// speaker geometry configuration flags, specifies assignment of channels to speaker positions, defined as per WAVEFORMATEXTENSIBLE.dwChannelMask -SPEAKER_FLAGS :: distinct bit_set[SPEAKER_FLAG; u32] -SPEAKER_FLAG :: enum u32 { - FRONT_LEFT = 0, - FRONT_RIGHT = 1, - FRONT_CENTER = 2, - LOW_FREQUENCY = 3, - BACK_LEFT = 4, - BACK_RIGHT = 5, - FRONT_LEFT_OF_CENTER = 6, - FRONT_RIGHT_OF_CENTER = 7, - BACK_CENTER = 8, - SIDE_LEFT = 9, - SIDE_RIGHT = 10, - TOP_CENTER = 11, - TOP_FRONT_LEFT = 12, - TOP_FRONT_CENTER = 13, - TOP_FRONT_RIGHT = 14, - TOP_BACK_LEFT = 15, - TOP_BACK_CENTER = 16, - TOP_BACK_RIGHT = 17, - //RESERVED = 0x7FFC0000, // bit mask locations reserved for future use - ALL = 31, // used to specify that any possible permutation of speaker configurations -} // standard speaker geometry configurations, used with Initialize SPEAKER_MONO :: SPEAKER_FLAGS{.FRONT_CENTER} @@ -100,7 +79,7 @@ CALCULATE_FLAG :: enum u32 { } //-----------------------------------------------------// -VECTOR :: [3]f32 // float 3D vector +VECTOR :: distinct [3]f32 // float 3D vector // instance handle of precalculated constants HANDLE :: distinct [HANDLE_BYTESIZE]byte @@ -108,75 +87,74 @@ HANDLE :: distinct [HANDLE_BYTESIZE]byte // Distance curve point: // Defines a DSP setting at a given normalized distance. DISTANCE_CURVE_POINT :: struct #packed { - Distance: f32, // normalized distance, must be within [0.0f, 1.0f] + Distance: f32, // normalized distance, must be within [0.0, 1.0] DSPSetting: f32, // DSP setting } // Distance curve: // A piecewise curve made up of linear segments used to define DSP behaviour with respect to normalized distance. // -// Note that curve point distances are normalized within [0.0f, 1.0f]. +// Note that curve point distances are normalized within [0.0, 1.0]. // EMITTER.CurveDistanceScaler must be used to scale the normalized distances to user-defined world units. -// For distances beyond CurveDistanceScaler * 1.0f, pPoints[PointCount-1].DSPSetting is used as the DSP setting. +// For distances beyond CurveDistanceScaler * 1.0, pPoints[PointCount-1].DSPSetting is used as the DSP setting. // // All distance curve spans must be such that: // pPoints[k-1].DSPSetting + ((pPoints[k].DSPSetting-pPoints[k-1].DSPSetting) / (pPoints[k].Distance-pPoints[k-1].Distance)) * (pPoints[k].Distance-pPoints[k-1].Distance) != NAN or infinite values // For all points in the distance curve where 1 <= k < PointCount. DISTANCE_CURVE :: struct #packed { - pPoints: [^]DISTANCE_CURVE_POINT `fmt:"v,PointCount"`, // distance curve point array, must have at least PointCount elements with no duplicates and be sorted in ascending order with respect to Distance - PointCount: u32, // number of distance curve points, must be >= 2 as all distance curves must have at least two endpoints, defining DSP settings at 0.0f and 1.0f normalized distance + pPoints: [^]DISTANCE_CURVE_POINT `fmt:"v,PointCount"`, // distance curve point array, must have at least PointCount elements with no duplicates and be sorted in ascending order with respect to Distance + PointCount: u32, // number of distance curve points, must be >= 2 as all distance curves must have at least two endpoints, defining DSP settings at 0.0 and 1.0 normalized distance } Default_LinearCurvePoints := [2]DISTANCE_CURVE_POINT{{0.0, 1.0}, {1.0, 0.0}} Default_LinearCurve := DISTANCE_CURVE{&Default_LinearCurvePoints[0], 2} +// Cone: +// Specifies directionality for a listener or single-channel emitter by modifying DSP behaviour with respect to its front orientation. +// This is modeled using two sound cones: an inner cone and an outer cone. On/within the inner cone, DSP settings are scaled by the inner values. +// On/beyond the outer cone, DSP settings are scaled by the outer values. If on both the cones, DSP settings are scaled by the inner values only. +// Between the two cones, the scaler is linearly interpolated between the inner and outer values. Set both cone angles to 0 or TAU for omnidirectionality using only the outer or inner values respectively. CONE :: struct #packed { - InnerAngle: f32, // inner cone angle in radians, must be within [0.0f, TAU] - OuterAngle: f32, // outer cone angle in radians, must be within [InnerAngle, TAU] + InnerAngle: f32, // inner cone angle in radians, must be within [0.0, TAU] + OuterAngle: f32, // outer cone angle in radians, must be within [InnerAngle, TAU] - InnerVolume: f32, // volume level scaler on/within inner cone, used only for matrix calculations, must be within [0.0f, 2.0f] when used - OuterVolume: f32, // volume level scaler on/beyond outer cone, used only for matrix calculations, must be within [0.0f, 2.0f] when used - InnerLPF: f32, // LPF (both direct and reverb paths) coefficient subtrahend on/within inner cone, used only for LPF (both direct and reverb paths) calculations, must be within [0.0f, 1.0f] when used - OuterLPF: f32, // LPF (both direct and reverb paths) coefficient subtrahend on/beyond outer cone, used only for LPF (both direct and reverb paths) calculations, must be within [0.0f, 1.0f] when used - InnerReverb: f32, // reverb send level scaler on/within inner cone, used only for reverb calculations, must be within [0.0f, 2.0f] when used - OuterReverb: f32, // reverb send level scaler on/beyond outer cone, used only for reverb calculations, must be within [0.0f, 2.0f] when used + InnerVolume: f32, // volume level scaler on/within inner cone, used only for matrix calculations, must be within [0.0, 2.0] when used + OuterVolume: f32, // volume level scaler on/beyond outer cone, used only for matrix calculations, must be within [0.0, 2.0] when used + InnerLPF: f32, // LPF (both direct and reverb paths) coefficient subtrahend on/within inner cone, used only for LPF (both direct and reverb paths) calculations, must be within [0.0, 1.0] when used + OuterLPF: f32, // LPF (both direct and reverb paths) coefficient subtrahend on/beyond outer cone, used only for LPF (both direct and reverb paths) calculations, must be within [0.0, 1.0] when used + InnerReverb: f32, // reverb send level scaler on/within inner cone, used only for reverb calculations, must be within [0.0, 2.0] when used + OuterReverb: f32, // reverb send level scaler on/beyond outer cone, used only for reverb calculations, must be within [0.0, 2.0] when used } Default_DirectionalCone := CONE{math.PI / 2, math.PI, 1.0, 0.708, 0.0, 0.25, 0.708, 1.0} // Listener: // Defines a point of 3D audio reception. -// // The cone is directed by the listener's front orientation. LISTENER :: struct #packed { - OrientFront: VECTOR, // orientation of front direction, used only for matrix and delay calculations or listeners with cones for matrix, LPF (both direct and reverb paths), and reverb calculations, must be normalized when used - OrientTop: VECTOR, // orientation of top direction, used only for matrix and delay calculations, must be orthonormal with OrientFront when used + OrientFront: VECTOR, // orientation of front direction, used only for matrix and delay calculations or listeners with cones for matrix, LPF (both direct and reverb paths), and reverb calculations, must be normalized when used + OrientTop: VECTOR, // orientation of top direction, used only for matrix and delay calculations, must be orthonormal with OrientFront when used - Position: VECTOR, // position in user-defined world units, does not affect Velocity - Velocity: VECTOR, // velocity vector in user-defined world units/second, used only for doppler calculations, does not affect Position + Position: VECTOR, // position in user-defined world units, does not affect Velocity + Velocity: VECTOR, // velocity vector in user-defined world units/second, used only for doppler calculations, does not affect Position - pCone: ^CONE, // sound cone, used only for matrix, LPF (both direct and reverb paths), and reverb calculations, NULL specifies omnidirectionality + pCone: ^CONE, // sound cone, used only for matrix, LPF (both direct and reverb paths), and reverb calculations, nil specifies omnidirectionality } // Emitter: // Defines a 3D audio source, divided into two classifications: -// // Single-point -- For use with single-channel sounds. // Positioned at the emitter base, i.e. the channel radius and azimuth are ignored if the number of channels == 1. -// // May be omnidirectional or directional using a cone. // The cone originates from the emitter base position, and is directed by the emitter's front orientation. -// // Multi-point -- For use with multi-channel sounds. // Each non-LFE channel is positioned using an azimuth along the channel radius with respect to the front orientation vector in the plane orthogonal to the top orientation vector. // An azimuth of TAU specifies a channel is an LFE. Such channels are positioned at the emitter base and are calculated with respect to pLFECurve only, never pVolumeCurve. -// // Multi-point emitters are always omnidirectional, i.e. the cone is ignored if the number of channels > 1. -// // Note that many properties are shared among all channel points, locking certain behaviour with respect to the emitter base position. // For example, doppler shift is always calculated with respect to the emitter base position and so is constant for all its channel points. // Distance curve calculations are also with respect to the emitter base position, with the curves being calculated independently of each other. // For instance, volume and LFE calculations do not affect one another. EMITTER :: struct #packed { - pCone: ^CONE, // sound cone, used only with single-channel emitters for matrix, LPF (both direct and reverb paths), and reverb calculations, NULL specifies omnidirectionality + pCone: ^CONE, // sound cone, used only with single-channel emitters for matrix, LPF (both direct and reverb paths), and reverb calculations, nil specifies omnidirectionality OrientFront: VECTOR, // orientation of front direction, used only for emitter angle calculations or with multi-channel emitters for matrix calculations or single-channel emitters with cones for matrix, LPF (both direct and reverb paths), and reverb calculations, must be normalized when used OrientTop: VECTOR, // orientation of top direction, used only with multi-channel emitters for matrix calculations, must be orthonormal with OrientFront when used @@ -184,26 +162,25 @@ EMITTER :: struct #packed { Position: VECTOR, // position in user-defined world units, does not affect Velocity Velocity: VECTOR, // velocity vector in user-defined world units/second, used only for doppler calculations, does not affect Position - InnerRadius: f32, // inner radius, must be within [0.0f, max(f32)] - InnerRadiusAngle: f32, // inner radius angle, must be within [0.0f, PI/4.0) + InnerRadius: f32, // inner radius, must be within [0.0, max(f32)] + InnerRadiusAngle: f32, // inner radius angle, must be within [0.0, PI/4.0) - ChannelCount: u32, // number of sound channels, must be > 0 - ChannelRadius: f32, // channel radius, used only with multi-channel emitters for matrix calculations, must be >= 0.0f when used - pChannelAzimuths: [^]f32 `fmt:"v,ChannelCount"`, // channel azimuth array, used only with multi-channel emitters for matrix calculations, contains positions of each channel expressed in radians along the channel radius with respect to the front orientation vector in the plane orthogonal to the top orientation vector, or TAU to specify an LFE channel, must have at least ChannelCount elements, all within [0.0f, TAU] when used + ChannelCount: u32, // number of sound channels, must be > 0 + ChannelRadius: f32, // channel radius, used only with multi-channel emitters for matrix calculations, must be >= 0.0 when used + pChannelAzimuths: [^]f32 `fmt:"v,ChannelCount"`, // channel azimuth array, used only with multi-channel emitters for matrix calculations, contains positions of each channel expressed in radians along the channel radius with respect to the front orientation vector in the plane orthogonal to the top orientation vector, or TAU to specify an LFE channel, must have at least ChannelCount elements, all within [0.0, TAU] when used - pVolumeCurve: ^DISTANCE_CURVE, // volume level distance curve, used only for matrix calculations, NULL specifies a default curve that conforms to the inverse square law, calculated in user-defined world units with distances <= CurveDistanceScaler clamped to no attenuation - pLFECurve: ^DISTANCE_CURVE, // LFE level distance curve, used only for matrix calculations, NULL specifies a default curve that conforms to the inverse square law, calculated in user-defined world units with distances <= CurveDistanceScaler clamped to no attenuation - pLPFDirectCurve: ^DISTANCE_CURVE, // LPF direct-path coefficient distance curve, used only for LPF direct-path calculations, NULL specifies the default curve: [0.0f,1.0f], [1.0f,0.75f] - pLPFReverbCurve: ^DISTANCE_CURVE, // LPF reverb-path coefficient distance curve, used only for LPF reverb-path calculations, NULL specifies the default curve: [0.0f,0.75f], [1.0f,0.75f] - pReverbCurve: ^DISTANCE_CURVE, // reverb send level distance curve, used only for reverb calculations, NULL specifies the default curve: [0.0f,1.0f], [1.0f,0.0f] + pVolumeCurve: ^DISTANCE_CURVE, // volume level distance curve, used only for matrix calculations, nil specifies a default curve that conforms to the inverse square law, calculated in user-defined world units with distances <= CurveDistanceScaler clamped to no attenuation + pLFECurve: ^DISTANCE_CURVE, // LFE level distance curve, used only for matrix calculations, nil specifies a default curve that conforms to the inverse square law, calculated in user-defined world units with distances <= CurveDistanceScaler clamped to no attenuation + pLPFDirectCurve: ^DISTANCE_CURVE, // LPF direct-path coefficient distance curve, used only for LPF direct-path calculations, nil specifies the default curve: [0.0,1.0], [1.0,0.75] + pLPFReverbCurve: ^DISTANCE_CURVE, // LPF reverb-path coefficient distance curve, used only for LPF reverb-path calculations, nil specifies the default curve: [0.0,0.75], [1.0,0.75] + pReverbCurve: ^DISTANCE_CURVE, // reverb send level distance curve, used only for reverb calculations, nil specifies the default curve: [0.0,1.0], [1.0,0.0] CurveDistanceScaler: f32, // curve distance scaler, used to scale normalized distance curves to user-defined world units and/or exaggerate their effect, used only for matrix, LPF (both direct and reverb paths), and reverb calculations, must be within [min(f32), max(f32)] when used - DopplerScaler: f32, // doppler shift scaler, used to exaggerate doppler shift effect, used only for doppler calculations, must be within [0.0f, max(f32)] when used + DopplerScaler: f32, // doppler shift scaler, used to exaggerate doppler shift effect, used only for doppler calculations, must be within [0.0, max(f32)] when used } // DSP settings: // Receives results from a call to Calculate to be sent to the low-level audio rendering API for 3D signal processing. -// // The user is responsible for allocating the matrix coefficient table, delay time array, and initializing the channel counts when used. DSP_SETTINGS :: struct #packed { pMatrixCoefficients: [^]f32, // [inout] matrix coefficient table, receives an array representing the volume level used to send from source channel S to destination channel D, stored as pMatrixCoefficients[SrcChannelCount * D + S], must have at least SrcChannelCount*DstChannelCount elements diff --git a/vendor/windows/XAudio2/xapo.odin b/vendor/windows/XAudio2/xapo.odin index 54fb420ca..510eeb514 100644 --- a/vendor/windows/XAudio2/xapo.odin +++ b/vendor/windows/XAudio2/xapo.odin @@ -1,75 +1,45 @@ #+build windows /* NOTES: - 1. Definition of terms: + 1. Definition of terms: DSP: Digital Signal Processing. - CBR: Constant BitRate -- DSP that consumes a constant number of - input samples to produce an output sample. - For example, a 22kHz to 44kHz resampler is CBR DSP. - Even though the number of input to output samples differ, - the ratio between input to output rate remains constant. - All user-defined XAPOs are assumed to be CBR as - XAudio2 only allows CBR DSP to be added to an effect chain. + CBR: Constant BitRate -- DSP that consumes a constant number of input samples to produce an output sample. + For example, a 22kHz to 44kHz resampler is CBR DSP. Even though the number of input to output samples differ, the ratio between input to output rate remains constant. + All user-defined XAPOs are assumed to be CBR as XAudio2 only allows CBR DSP to be added to an effect chain. XAPO: Cross-platform Audio Processing Object -- - a thin wrapper that manages DSP code, allowing it - to be easily plugged into an XAudio2 effect chain. + a thin wrapper that manages DSP code, allowing it to be easily plugged into an XAudio2 effect chain. - Frame: A block of samples, one per channel, - to be played simultaneously. + Frame: A block of samples, one per channel, to be played simultaneously. E.g. a mono stream has one sample per frame. - In-Place: Processing such that the input buffer equals the - output buffer (i.e. input data modified directly). - This form of processing is generally more efficient - than using separate memory for input and output. - However, an XAPO may not perform format conversion - when processing in-place. + In-Place: Processing such that the input buffer equals the output buffer (i.e. input data modified directly). + This form of processing is generally more efficient than using separate memory for input and output. + However, an XAPO may not perform format conversion when processing in-place. - 2. XAPO member variables are divided into three classifications: - Immutable: Set once via IXAPO.Initialize and remain - constant during the lifespan of the XAPO. + 2. XAPO member variables are divided into three classifications: + Immutable: Set once via IXAPO.Initialize and remain constant during the lifespan of the XAPO. Locked: May change before the XAPO is locked via - IXAPO.LockForProcess but remain constant - until IXAPO.UnlockForProcess is called. + IXAPO.LockForProcess but remain constant until IXAPO.UnlockForProcess is called. - Dynamic: May change from one processing pass to the next, - usually via IXAPOParameters.SetParameters. - XAPOs should assign reasonable defaults to their dynamic - variables during IXAPO.Initialize/LockForProcess so - that calling IXAPOParameters.SetParameters is not - required before processing begins. + Dynamic: May change from one processing pass to the next, usually via IXAPOParameters.SetParameters. + XAPOs should assign reasonable defaults to their dynamic variables during IXAPO.Initialize/LockForProcess so that calling IXAPOParameters.SetParameters is not required before processing begins. - When implementing an XAPO, determine the type of each variable and - initialize them in the appropriate method. Immutable variables are - generally preferable over locked which are preferable over dynamic. - That is, one should strive to minimize XAPO state changes for - best performance, maintainability, and ease of use. + When implementing an XAPO, determine the type of each variable and initialize them in the appropriate method. Immutable variables are generally preferable over locked which are preferable over dynamic. + That is, one should strive to minimize XAPO state changes for best performance, maintainability, and ease of use. - 3. To minimize glitches, the realtime audio processing thread must - not block. XAPO methods called by the realtime thread are commented - as non-blocking and therefore should not use blocking synchronization, - allocate memory, access the disk, etc. The XAPO interfaces were - designed to allow an effect implementer to move such operations - into other methods called on an application controlled thread. + 3. To minimize glitches, the realtime audio processing thread must not block. XAPO methods called by the realtime thread are commented as non-blocking and therefore should not use blocking synchronization, allocate memory, access the disk, etc. + The XAPO interfaces were designed to allow an effect implementer to move such operations into other methods called on an application controlled thread. - 4. Extending functionality is accomplished through the addition of new - COM interfaces. For example, if a new member is added to a parameter - structure, a new interface using the new structure should be added, - leaving the original interface unchanged. - This ensures consistent communication between future versions of - XAudio2 and various versions of XAPOs that may exist in an application. + 4. Extending functionality is accomplished through the addition of new COM interfaces. For example, if a new member is added to a parameter structure, a new interface using the new structure should be added, leaving the original interface unchanged. + This ensures consistent communication between future versions of XAudio2 and various versions of XAPOs that may exist in an application. - 5. All audio data is interleaved in XAudio2. + 5. All audio data is interleaved in XAudio2. The default audio format for an effect chain is WAVE_FORMAT_IEEE_FLOAT. - 6. User-defined XAPOs should assume all input and output buffers are - 16-byte aligned. - - 7. See XAPOBase.odin for an XAPO base class which provides a default - implementation for most of the interface methods defined below. */ + 6. User-defined XAPOs should assume all input and output buffers are 16-byte aligned. */ package windows_xaudio2 @@ -77,8 +47,7 @@ import win "core:sys/windows" //---------------------------------------------------// -// XAPO error codes -FORMAT_UNSUPPORTED := win.MAKE_HRESULT(win.SEVERITY.ERROR, 0x897, 0x01) // requested audio format unsupported +FORMAT_UNSUPPORTED := win.MAKE_HRESULT(win.SEVERITY.ERROR, win.FACILITY.XAPO, 0x01) // requested audio format unsupported // supported number of channels (samples per frame) range XAPO_MIN_CHANNELS :: 1 @@ -111,11 +80,11 @@ XAPO_FLAG :: enum u32 { // XAPO must be run in-place. Use this flag only if your DSP implementation cannot process separate input and output buffers. // If set, the following flags must also be set: - // XAPO_FLAG_CHANNELS_MUST_MATCH - // XAPO_FLAG_FRAMERATE_MUST_MATCH - // XAPO_FLAG_BITSPERSAMPLE_MUST_MATCH - // XAPO_FLAG_BUFFERCOUNT_MUST_MATCH - // XAPO_FLAG_INPLACE_SUPPORTED + // CHANNELS_MUST_MATCH + // FRAMERATE_MUST_MATCH + // BITSPERSAMPLE_MUST_MATCH + // BUFFERCOUNT_MUST_MATCH + // INPLACE_SUPPORTED // Multiple input and output buffers may be used with in-place XAPOs, though the input buffer count must equal the output buffer count. // When multiple input/output buffers are used, the XAPO may assume input buffer [N] equals output buffer [N] for in-place processing. INPLACE_REQUIRED = 5, @@ -139,18 +108,18 @@ XAPO_REGISTRATION_PROPERTIES :: struct #packed { Flags: XAPO_FLAGS, // XAPO property flags, describes supported input/output configuration MinInputBufferCount: u32, // minimum number of input buffers required for processing, can be 0 MaxInputBufferCount: u32, // maximum number of input buffers supported for processing, must be >= MinInputBufferCount - MinOutputBufferCount: u32, // minimum number of output buffers required for processing, can be 0, must match MinInputBufferCount when XAPO_FLAG_BUFFERCOUNT_MUST_MATCH used - MaxOutputBufferCount: u32, // maximum number of output buffers supported for processing, must be >= MinOutputBufferCount, must match MaxInputBufferCount when XAPO_FLAG_BUFFERCOUNT_MUST_MATCH used + MinOutputBufferCount: u32, // minimum number of output buffers required for processing, can be 0, must match MinInputBufferCount when XAPO_FLAG.BUFFERCOUNT_MUST_MATCH used + MaxOutputBufferCount: u32, // maximum number of output buffers supported for processing, must be >= MinOutputBufferCount, must match MaxInputBufferCount when XAPO_FLAG.BUFFERCOUNT_MUST_MATCH used } // LockForProcess buffer parameters: // Defines buffer parameters that remain constant while an XAPO is locked. -// Used with IXAPO::LockForProcess. +// Used with IXAPO.LockForProcess. // For CBR XAPOs, MaxFrameCount is the only number of frames -// IXAPO::Process would have to handle for the respective buffer. +// IXAPO.Process would have to handle for the respective buffer. XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS :: struct #packed { pFormat: ^WAVEFORMATEX, // buffer audio format - MaxFrameCount: u32, // maximum number of frames in respective buffer that IXAPO::Process would have to handle, irrespective of dynamic variable settings, can be 0 + MaxFrameCount: u32, // maximum number of frames in respective buffer that IXAPO.Process would have to handle, irrespective of dynamic variable settings, can be 0 } // Buffer flags: @@ -161,31 +130,25 @@ XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS :: struct #packed { // If silent, the XAPO may simply set the flag on the output buffer to silent and return, optimizing out the work of processing silent data: XAPOs that generate silence for any reason may set the buffer's flag accordingly rather than writing out silent frames to the buffer itself. // The flags represent what should be assumed is in the respective buffer. The flags may not reflect what is actually stored in memory. XAPO_BUFFER_FLAGS :: enum i32 { - XAPO_BUFFER_SILENT, // silent data should be assumed, respective memory may be uninitialized - XAPO_BUFFER_VALID, // arbitrary data should be assumed (may or may not be silent frames), respective memory initialized + SILENT, // silent data should be assumed, respective memory may be uninitialized + VALID, // arbitrary data should be assumed (may or may not be silent frames), respective memory initialized } // Process buffer parameters: -// Defines buffer parameters that may change from one -// processing pass to the next. Used with IXAPO::Process. -// +// Defines buffer parameters that may change from one processing pass to the next. Used with IXAPO.Process. // Note the byte size of the respective buffer must be at least: -// XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS.MaxFrameCount * XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS.pFormat->nBlockAlign -// -// Although the audio format and maximum size of the respective -// buffer is locked (defined by XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS), -// the actual memory address of the buffer given is permitted to change -// from one processing pass to the next. -// -// For CBR XAPOs, ValidFrameCount is constant while locked and equals -// the respective XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS.MaxFrameCount. +// XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS.MaxFrameCount * XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS.pFormat.nBlockAlign +// Although the audio format and maximum size of the respective buffer is locked (defined by XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS), the actual memory address of the buffer given is permitted to change from one processing pass to the next. +// For CBR XAPOs, ValidFrameCount is constant while locked and equals the respective XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS.MaxFrameCount. XAPO_PROCESS_BUFFER_PARAMETERS :: struct #packed { - pBuffer: rawptr, // audio data buffer, must be non-NULL + pBuffer: rawptr, // audio data buffer, must be non-nil BufferFlags: XAPO_BUFFER_FLAGS, // describes assumed content of pBuffer, does not affect ValidFrameCount ValidFrameCount: u32, // number of frames of valid data, must be within respective [0, XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS.MaxFrameCount], always XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS.MaxFrameCount for CBR/user-defined XAPOs, does not affect BufferFlags } -XAPOFree :: win.CoTaskMemFree +// Used by IXAPO methods that must allocate arbitrary sized structures such as WAVEFORMATEX that are subsequently returned to the application. +XAPOAlloc :: win.CoTaskMemAlloc +XAPOFree :: win.CoTaskMemFree IXAPO_UUID_STRING :: "A410B984-9839-4819-A0BE-2856AE6B3ADB" IXAPO_UUID := &win.IID{0xA410B984, 0x9839, 0x4819, {0xA0, 0xBE, 0x28, 0x56, 0xAE, 0x6B, 0x3A, 0xDB}} @@ -214,11 +177,11 @@ IXAPO_VTable :: struct { // PARAMETERS: // pOutputFormat - [in] output format known to be supported // pRequestedInputFormat - [in] input format to examine - // ppSupportedInputFormat - [out] receives pointer to nearest input format supported if not NULL and input/output configuration unsupported, use XAPOFree to free structure, left untouched on any failure except XAPO_E_FORMAT_UNSUPPORTED + // ppSupportedInputFormat - [out] receives pointer to nearest input format supported if not nil and input/output configuration unsupported, use XAPOFree to free structure, left untouched on any failure except FORMAT_UNSUPPORTED // RETURN VALUE: // COM error code, including: // S_OK - input/output configuration supported, ppSupportedInputFormat left untouched - // FORMAT_UNSUPPORTED - input/output configuration unsupported, ppSupportedInputFormat receives pointer to nearest input format supported if not NULL + // FORMAT_UNSUPPORTED - input/output configuration unsupported, ppSupportedInputFormat receives pointer to nearest input format supported if not nil // E_INVALIDARG - either audio format invalid, ppSupportedInputFormat left untouched IsInputFormatSupported: proc "system" (this: ^IXAPO, pOutputFormat: ^WAVEFORMATEX, pRequestedInputFormat: ^WAVEFORMATEX, ppSupportedInputFormat: ^^WAVEFORMATEX) -> HRESULT, @@ -232,11 +195,11 @@ IXAPO_VTable :: struct { // PARAMETERS: // pInputFormat - [in] input format known to be supported // pRequestedOutputFormat - [in] output format to examine - // ppSupportedOutputFormat - [out] receives pointer to nearest output format supported if not NULL and input/output configuration unsupported, use XAPOFree to free structure, left untouched on any failure except XAPO_E_FORMAT_UNSUPPORTED + // ppSupportedOutputFormat - [out] receives pointer to nearest output format supported if not nil and input/output configuration unsupported, use XAPOFree to free structure, left untouched on any failure except FORMAT_UNSUPPORTED // RETURN VALUE: // COM error code, including: // S_OK - input/output configuration supported, ppSupportedOutputFormat left untouched - // FORMAT_UNSUPPORTED - input/output configuration unsupported, ppSupportedOutputFormat receives pointer to nearest output format supported if not NULL + // FORMAT_UNSUPPORTED - input/output configuration unsupported, ppSupportedOutputFormat receives pointer to nearest output format supported if not nil // E_INVALIDARG - either audio format invalid, ppSupportedOutputFormat left untouched IsOutputFormatSupported: proc "system" (this: ^IXAPO, pInputFormat: ^WAVEFORMATEX, pRequestedOutputFormat: ^WAVEFORMATEX, ppSupportedOutputFormat: ^^WAVEFORMATEX) -> HRESULT, @@ -246,10 +209,10 @@ IXAPO_VTable :: struct { // The contents of pData are defined by the XAPO. // Immutable variables (constant during the lifespan of the XAPO) should be set once via this method. // Once initialized, an XAPO cannot be initialized again. - // An XAPO should be initialized before passing it to XAudio2 as part of an effect chain. XAudio2 will not call this method; it exists for future content-driven initialization. + // An XAPO should be initialized before passing it to XAudio2 as part of an effect chain. XAudio2 will not call this method; it exists for future content-driven initialization. // PARAMETERS: - // pData - [in] effect-specific initialization parameters, may be NULL if DataByteSize == 0 - // DataByteSize - [in] size of pData in bytes, may be 0 if pData is NULL + // pData - [in] effect-specific initialization parameters, may be nil if DataByteSize == 0 + // DataByteSize - [in] size of pData in bytes, may be 0 if pData is nil // RETURN VALUE: // COM error code Initialize: proc "system" (this: ^IXAPO, pData: rawptr, DataByteSize: u32) -> HRESULT, @@ -279,9 +242,9 @@ IXAPO_VTable :: struct { // Once locked, an XAPO cannot be locked again until UnLockForProcess is called. // PARAMETERS: // InputLockedParameterCount - [in] number of input buffers, must be within [XAPO_REGISTRATION_PROPERTIES.MinInputBufferCount, XAPO_REGISTRATION_PROPERTIES.MaxInputBufferCount] - // pInputLockedParameters - [in] array of input locked buffer parameter structures, may be NULL if InputLockedParameterCount == 0, otherwise must have InputLockedParameterCount elements - // OutputLockedParameterCount - [in] number of output buffers, must be within [XAPO_REGISTRATION_PROPERTIES.MinOutputBufferCount, XAPO_REGISTRATION_PROPERTIES.MaxOutputBufferCount], must match InputLockedParameterCount when XAPO_FLAG_BUFFERCOUNT_MUST_MATCH used - // pOutputLockedParameters - [in] array of output locked buffer parameter structures, may be NULL if OutputLockedParameterCount == 0, otherwise must have OutputLockedParameterCount elements + // pInputLockedParameters - [in] array of input locked buffer parameter structures, may be nil if InputLockedParameterCount == 0, otherwise must have InputLockedParameterCount elements + // OutputLockedParameterCount - [in] number of output buffers, must be within [XAPO_REGISTRATION_PROPERTIES.MinOutputBufferCount, XAPO_REGISTRATION_PROPERTIES.MaxOutputBufferCount], must match InputLockedParameterCount when XAPO_FLAG.BUFFERCOUNT_MUST_MATCH used + // pOutputLockedParameters - [in] array of output locked buffer parameter structures, may be nil if OutputLockedParameterCount == 0, otherwise must have OutputLockedParameterCount elements // RETURN VALUE: // COM error code LockForProcess: proc "system" (this: ^IXAPO, InputLockedParameterCount: u32, pInputLockedParameters: [^]XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS, OutputLockedParameterCount: u32, pOutputLockedParameters: [^]XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS) -> HRESULT, @@ -303,16 +266,16 @@ IXAPO_VTable :: struct { // ppInputProcessParameters will not necessarily be the same as ppOutputProcessParameters for in-place processing, rather the pBuffer members of each will point to the same memory. // Multiple input/output buffers may be used with in-place XAPOs, though the input buffer count must equal the output buffer count. // When multiple input/output buffers are used with in-place XAPOs, the XAPO may assume input buffer [N] equals output buffer [N]. - // When IsEnabled is FALSE, the XAPO should process thru. Thru processing means an XAPO should not apply its normal processing to the given input/output buffers during Process. - // It should instead pass data from input to output with as little modification possible. Effects that perform format conversion should continue to do so. + // When IsEnabled is false, the XAPO should process thru. Thru processing means an XAPO should not apply its normal processing to the given input/output buffers during Process. + // It should instead pass data from input to output with as little modification possible. Effects that perform format conversion should continue to do so. // The effect must ensure transitions between normal and thru processing do not introduce discontinuities into the signal. // XAudio2 calls this method only if the XAPO is locked. This method should not block as it is called from the realtime thread. // PARAMETERS: // InputProcessParameterCount - [in] number of input buffers, matches respective InputLockedParameterCount parameter given to LockForProcess - // pInputProcessParameters - [in] array of input process buffer parameter structures, may be NULL if InputProcessParameterCount == 0, otherwise must have InputProcessParameterCount elements + // pInputProcessParameters - [in] array of input process buffer parameter structures, may be nil if InputProcessParameterCount == 0, otherwise must have InputProcessParameterCount elements // OutputProcessParameterCount - [in] number of output buffers, matches respective OutputLockedParameterCount parameter given to LockForProcess - // pOutputProcessParameters - [in/out] array of output process buffer parameter structures, may be NULL if OutputProcessParameterCount == 0, otherwise must have OutputProcessParameterCount elements - // IsEnabled - [in] TRUE to process normally, FALSE to process thru + // pOutputProcessParameters - [in/out] array of output process buffer parameter structures, may be nil if OutputProcessParameterCount == 0, otherwise must have OutputProcessParameterCount elements + // IsEnabled - [in] true to process normally, false to process thru // RETURN VALUE: // void Process: proc "system" (this: ^IXAPO, InputProcessParameterCount: u32, pInputProcessParameters: [^]XAPO_PROCESS_BUFFER_PARAMETERS, OutputProcessParameterCount: u32, pOutputProcessParameters: [^]XAPO_PROCESS_BUFFER_PARAMETERS, IsEnabled: b32), @@ -358,7 +321,7 @@ IXAPOParameters_VTable :: struct { // This method may only be called on the realtime thread; no synchronization between it and IXAPO.Process is necessary. // This method should not block as it is called from the realtime thread. // PARAMETERS: - // pParameters - [in] effect-specific parameter block, must be != NULL + // pParameters - [in] effect-specific parameter block, must be != nil // ParameterByteSize - [in] size of pParameters in bytes, must be > 0 // RETURN VALUE: // void @@ -369,7 +332,7 @@ IXAPOParameters_VTable :: struct { // REMARKS: // Unlike SetParameters, XAudio2 does not call this method on the realtime thread. Thus, the XAPO must protect variables shared with SetParameters/Process using appropriate synchronization. // PARAMETERS: - // pParameters - [out] receives effect-specific parameter block, must be != NULL + // pParameters - [out] receives effect-specific parameter block, must be != nil // ParameterByteSize - [in] size of pParameters in bytes, must be > 0 // RETURN VALUE: // void diff --git a/vendor/windows/XAudio2/xapofx.odin b/vendor/windows/XAudio2/xapofx.odin index 5c4c8c7ec..5ab9d57a8 100644 --- a/vendor/windows/XAudio2/xapofx.odin +++ b/vendor/windows/XAudio2/xapofx.odin @@ -132,7 +132,7 @@ FXECHO_PARAMETERS :: struct #packed { @(default_calling_convention="cdecl") foreign xa2 { // creates instance of requested XAPO, use Release to free instance - // pInitData - [in] effect-specific initialization parameters, may be NULL if InitDataByteSize == 0 - // InitDataByteSize - [in] size of pInitData in bytes, may be 0 if pInitData is NULL + // pInitData - [in] effect-specific initialization parameters, may be nil if InitDataByteSize == 0 + // InitDataByteSize - [in] size of pInitData in bytes, may be 0 if pInitData is nil CreateFX :: proc(clsid: win.REFCLSID, pEffect: ^^IUnknown, pInitDat: rawptr = nil, InitDataByteSize: u32 = 0) -> HRESULT --- } diff --git a/vendor/windows/XAudio2/xaudio2.odin b/vendor/windows/XAudio2/xaudio2.odin index 078ec4095..6187b63fe 100644 --- a/vendor/windows/XAudio2/xaudio2.odin +++ b/vendor/windows/XAudio2/xaudio2.odin @@ -11,6 +11,8 @@ package windows_xaudio2 import win "core:sys/windows" import "core:math" +foreign import xa2 "system:xaudio2.lib" + HRESULT :: win.HRESULT IUnknown :: win.IUnknown IUnknown_VTable :: win.IUnknown_VTable @@ -93,8 +95,8 @@ DEVICE_INVALIDATED :: HRESULT(-2003435516) // 0x88960004 An audio device be **************************************************************************/ // Used in Create, specifies which CPU(s) to use. -PROCESSOR_FLAGS :: distinct bit_set[PROCESOR_FLAG; u32] -PROCESOR_FLAG :: enum u32 { +PROCESSOR_FLAGS :: distinct bit_set[PROCESSOR_FLAG; u32] +PROCESSOR_FLAG :: enum u32 { Processor1 = 0, Processor2 = 1, Processor3 = 2, @@ -128,7 +130,7 @@ PROCESOR_FLAG :: enum u32 { Processor31 = 30, Processor32 = 31, } - +//ANY_PROCESSOR :: 0xffffffff USE_DEFAULT_PROCESSOR :: PROCESSOR_FLAGS{} // Returned by IXAudio2Voice.GetVoiceDetails @@ -147,8 +149,8 @@ SEND_DESCRIPTOR :: struct #packed { // Used in the voice creation functions and in IXAudio2Voice.SetOutputVoices VOICE_SENDS :: struct #packed { - SendCount: u32, // Number of sends from this voice. - pSends: [^]SEND_DESCRIPTOR, // Array of SendCount send descriptors. + SendCount: u32, // Number of sends from this voice. + pSends: [^]SEND_DESCRIPTOR `fmt:"v,SendCount"`, // Array of SendCount send descriptors. } // Used in EFFECT_CHAIN below @@ -160,8 +162,8 @@ EFFECT_DESCRIPTOR :: struct #packed { // Used in the voice creation functions and in IXAudio2Voice.SetEffectChain EFFECT_CHAIN :: struct #packed { - EffectCount: u32, // Number of effects in this voice's effect chain. - pEffectDescriptors: [^]EFFECT_DESCRIPTOR, // Array of effect descriptors. + EffectCount: u32, // Number of effects in this voice's effect chain. + pEffectDescriptors: [^]EFFECT_DESCRIPTOR `fmt:"v,EffectCount"`, // Array of effect descriptors. } // Used in FILTER_PARAMETERS below @@ -183,28 +185,28 @@ FILTER_PARAMETERS :: struct #packed { // Used in IXAudio2SourceVoice.SubmitSourceBuffer BUFFER :: struct #packed { - Flags: FLAGS, // Either 0 or END_OF_STREAM. - AudioBytes: u32, // Size of the audio data buffer in bytes. - pAudioData: [^]byte, // Pointer to the audio data buffer. - PlayBegin: u32, // First sample in this buffer to be played. - PlayLength: u32, // Length of the region to be played in samples, or 0 to play the whole buffer. - LoopBegin: u32, // First sample of the region to be looped. - LoopLength: u32, // Length of the desired loop region in samples, or 0 to loop the entire buffer. - LoopCount: u32, // Number of times to repeat the loop region, or LOOP_INFINITE to loop forever. - pContext: rawptr, // Context value to be passed back in callbacks. + Flags: FLAGS, // Either 0 or END_OF_STREAM. + AudioBytes: u32, // Size of the audio data buffer in bytes. + pAudioData: [^]byte `fmt:"v,AudioBytes"`, // Pointer to the audio data buffer. + PlayBegin: u32, // First sample in this buffer to be played. + PlayLength: u32, // Length of the region to be played in samples, or 0 to play the whole buffer. + LoopBegin: u32, // First sample of the region to be looped. + LoopLength: u32, // Length of the desired loop region in samples, or 0 to loop the entire buffer. + LoopCount: u32, // Number of times to repeat the loop region, or LOOP_INFINITE to loop forever. + pContext: rawptr, // Context value to be passed back in callbacks. } // Used in IXAudio2SourceVoice.SubmitSourceBuffer when submitting XWMA data. // NOTE: If an XWMA sound is submitted in more than one buffer, each buffer's pDecodedPacketCumulativeBytes[PacketCount-1] value must be subtracted from all the entries in the next buffer's pDecodedPacketCumulativeBytes array. // And whether a sound is submitted in more than one buffer or not, the final buffer of the sound should use the END_OF_STREAM flag, or else the client must call IXAudio2SourceVoice.Discontinuity after submitting it. BUFFER_WMA :: struct #packed { - pDecodedPacketCumulativeBytes: [^]u32, // Decoded packet's cumulative size array. Each element is the number of bytes accumulated when the corresponding XWMA packet is decoded in order. The array must have PacketCount elements. - PacketCount: u32, // Number of XWMA packets submitted. Must be >= 1 and divide evenly into BUFFER.AudioBytes. + pDecodedPacketCumulativeBytes: [^]u32 `fmt:"v,PacketCount"`, // Decoded packet's cumulative size array. Each element is the number of bytes accumulated when the corresponding XWMA packet is decoded in order. The array must have PacketCount elements. + PacketCount: u32, // Number of XWMA packets submitted. Must be >= 1 and divide evenly into BUFFER.AudioBytes. } // Returned by IXAudio2SourceVoice.GetState VOICE_STATE :: struct #packed { - pCurrentBufferContext: rawptr, // The pContext value provided in the BUFFER that is currently being processed, or NULL if there are no buffers in the queue. + pCurrentBufferContext: rawptr, // The pContext value provided in the BUFFER that is currently being processed, or nil if there are no buffers in the queue. BuffersQueued: u32, // Number of buffers currently queued on the voice (including the one that is being processed). SamplesPlayed: u64, // Total number of samples produced by the voice since it began processing the current audio stream. If VOICE_NOSAMPLESPLAYED is specified in the call to IXAudio2SourceVoice.GetState, this member will not be calculated, saving CPU. } @@ -336,8 +338,7 @@ IXAudio2_VTable :: struct { StopEngine: proc "system" (this: ^IXAudio2), // NAME: IXAudio2.CommitChanges - // DESCRIPTION: Atomically applies a set of operations previously tagged - // with a given identifier. + // DESCRIPTION: Atomically applies a set of operations previously tagged with a given identifier. // ARGUMENTS: // OperationSet - Identifier of the set of operations to be applied. CommitChanges: proc "system" (this: ^IXAudio2, OperationSet: u32) -> HRESULT, @@ -352,7 +353,7 @@ IXAudio2_VTable :: struct { // DESCRIPTION: Configures XAudio2's debug output (in debug builds only). // ARGUMENTS: // pDebugConfiguration - Structure describing the debug output behavior. - // pReserved - Optional parameter; must be NULL. + // pReserved - Optional parameter; must be nil. SetDebugConfiguration: proc "system" (this: ^IXAudio2, pDebugConfiguration: ^DEBUG_CONFIGURATION, pReserved: rawptr = nil), } @@ -399,8 +400,7 @@ IXAudio2Voice_VTable :: struct { GetVoiceDetails: proc "system" (this: ^IXAudio2Voice, pVoiceDetails: ^VOICE_DETAILS), // NAME: IXAudio2Voice.SetOutputVoices - // DESCRIPTION: Replaces the set of submix/mastering voices that receive - // this voice's output. + // DESCRIPTION: Replaces the set of submix/mastering voices that receive this voice's output. // ARGUMENTS: // pSendList - Optional list of voices this voice should send audio to. SetOutputVoices: proc "system" (this: ^IXAudio2Voice, pSendList: [^]VOICE_SENDS) -> HRESULT, @@ -709,37 +709,15 @@ IXAudio2VoiceCallback_VTable :: struct { * * Flags - Flags specifying the XAudio2 object's behavior. * - * XAudio2Processor - A PROCESSOR_FLAGS value that specifies the hardware threads (Xbox) or processors (Windows) that XAudio2 will use. + * Processor - A PROCESSOR_FLAGS value that specifies the hardware threads (Xbox) or processors (Windows) that XAudio2 will use. * Note that XAudio2 supports concurrent processing on multiple threads, using any combination of PROCESSOR_FLAGS flags. * The values are platform-specific; platform-independent code can use USE_DEFAULT_PROCESSOR to use the default on each platform. * **************************************************************************/ -Create :: proc "stdcall" (ppXAudio2: ^^IXAudio2, Flags: FLAGS = {}, XAudio2Processor: PROCESSOR_FLAGS = {.Processor1}) -> HRESULT { - CreateWithVersionInfoFunc :: #type proc "c" (a0: ^^IXAudio2, a1: FLAGS, a2: PROCESSOR_FLAGS, a3: win.DWORD) -> HRESULT - CreateInfoFunc :: #type proc "c" (a0: ^^IXAudio2, a1: FLAGS, a2: PROCESSOR_FLAGS) -> HRESULT - - dll_Instance: win.HMODULE - create_with_version_info: CreateWithVersionInfoFunc - create_info: CreateInfoFunc - - if dll_Instance == nil { - dll_Instance = win.LoadLibraryExW(win.L("xaudio2_9.dll"), nil, {.LOAD_LIBRARY_SEARCH_DEFAULT_DIRS}) - if dll_Instance == nil { - return HRESULT(win.GetLastError()) - } - create_with_version_info = cast(CreateWithVersionInfoFunc)win.GetProcAddress(dll_Instance, "XAudio2CreateWithVersionInfo") - if create_with_version_info == nil { - create_info = cast(CreateInfoFunc)win.GetProcAddress(dll_Instance, "XAudio2Create") - if create_info == nil { - return HRESULT(win.GetLastError()) - } - } - } - if create_with_version_info != nil { - return create_with_version_info(ppXAudio2, Flags, XAudio2Processor, 0x0A000010) - } - return create_info(ppXAudio2, Flags, XAudio2Processor) +@(default_calling_convention="system", link_prefix="XAudio2") +foreign xa2 { + Create :: proc(ppXaudio2: ^^IXAudio2, Flags: FLAGS = {}, Processor: PROCESSOR_FLAGS = {.Processor1}) -> HRESULT --- } /************************************************************************** @@ -749,12 +727,12 @@ Create :: proc "stdcall" (ppXAudio2: ^^IXAudio2, Flags: FLAGS = {}, XAudio2Proce **************************************************************************/ // Calculate the argument to SetVolume from a decibel value -DecibelsToAmplitudeRatio :: proc "contextless" (Decibels: f32) -> f32 { +DecibelsToAmplitudeRatio :: #force_inline proc "contextless" (Decibels: f32) -> f32 { return math.pow_f32(10.0, Decibels / 20.0) } // Recover a volume in decibels from an amplitude factor -AmplitudeRatioToDecibels :: proc "contextless" (Volume: f32) -> f32 { +AmplitudeRatioToDecibels :: #force_inline proc "contextless" (Volume: f32) -> f32 { if Volume == 0 { return min(f32) } @@ -762,14 +740,14 @@ AmplitudeRatioToDecibels :: proc "contextless" (Volume: f32) -> f32 { } // Calculate the argument to SetFrequencyRatio from a semitone value -SemitonesToFrequencyRatio :: proc "contextless" (Semitones: f32) -> f32 { +SemitonesToFrequencyRatio :: #force_inline proc "contextless" (Semitones: f32) -> f32 { // FrequencyRatio = 2 ^ Octaves // = 2 ^ (Semitones / 12) return math.pow_f32(2.0, Semitones / 12.0) } // Recover a pitch in semitones from a frequency ratio -FrequencyRatioToSemitones :: proc "contextless" (FrequencyRatio: f32) -> f32 { +FrequencyRatioToSemitones :: #force_inline proc "contextless" (FrequencyRatio: f32) -> f32 { // Semitones = 12 * log2(FrequencyRatio) // = 12 * log2(10) * log10(FrequencyRatio) return 12.0 * math.log2_f32(FrequencyRatio) @@ -779,7 +757,7 @@ FrequencyRatioToSemitones :: proc "contextless" (FrequencyRatio: f32) -> f32 { // Use CutoffFrequencyToOnePoleCoefficient() for one-pole filter types. // Note that the highest CutoffFrequency supported is SampleRate/6. // Higher values of CutoffFrequency will return MAX_FILTER_FREQUENCY. -CutoffFrequencyToRadians :: proc "contextless" (CutoffFrequency: f32, SampleRate: u32) -> f32 { +CutoffFrequencyToRadians :: #force_inline proc "contextless" (CutoffFrequency: f32, SampleRate: u32) -> f32 { if u32(CutoffFrequency * 6.0) >= SampleRate { return MAX_FILTER_FREQUENCY } @@ -787,14 +765,14 @@ CutoffFrequencyToRadians :: proc "contextless" (CutoffFrequency: f32, SampleRate } // Convert from radian frequencies back to absolute frequencies in Hertz -RadiansToCutoffFrequency :: proc "contextless" (Radians: f32, SampleRate: f32) -> f32 { +RadiansToCutoffFrequency :: #force_inline proc "contextless" (Radians: f32, SampleRate: f32) -> f32 { return SampleRate * math.asin_f32(Radians / 2.0) / math.PI } // Convert from filter cutoff frequencies expressed in Hertz to the filter coefficients used with FILTER_PARAMETERS.Frequency, // LowPassOnePoleFilter and HighPassOnePoleFilter filter types only. // Use CutoffFrequencyToRadians() for state-variable filter types. -CutoffFrequencyToOnePoleCoefficient :: proc "contextless" (CutoffFrequency: f32, SampleRate: u32) -> f32 { +CutoffFrequencyToOnePoleCoefficient :: #force_inline proc "contextless" (CutoffFrequency: f32, SampleRate: u32) -> f32 { if u32(CutoffFrequency) >= SampleRate { return MAX_FILTER_FREQUENCY } diff --git a/vendor/windows/XAudio2/xaudio2fx.odin b/vendor/windows/XAudio2/xaudio2fx.odin index 1449ed4ea..90bd9745b 100644 --- a/vendor/windows/XAudio2/xaudio2fx.odin +++ b/vendor/windows/XAudio2/xaudio2fx.odin @@ -10,8 +10,7 @@ foreign import xa2 "system:xaudio2.lib" * * Effect creation functions. * - * On Xbox the application can link with the debug library to use the debug - * functionality. + * On Xbox the application can link with the debug library to use the debug functionality. * **************************************************************************/ @@ -32,9 +31,9 @@ foreign xa2 { // The user is responsible for allocating pPeakLevels, pRMSLevels, and initializing ChannelCount accordingly. // The volume meter does not support SetEffectParameters(). VOLUMEMETER_LEVELS :: struct #packed { - pPeakLevels: [^]f32 `fmt:"v,ChannelCount"`, // Peak levels table: receives maximum absolute level for each channel over a processing pass, may be NULL if pRMSLevls != NULL, otherwise must have at least ChannelCount elements. - pRMSLevels: [^]f32 `fmt:"v,ChannelCount"`, // Root mean square levels table: receives RMS level for each channel over a processing pass, may be NULL if pPeakLevels != NULL, otherwise must have at least ChannelCount elements. - ChannelCount: u32, // Number of channels being processed by the volume meter APO + pPeakLevels: [^]f32 `fmt:"v,ChannelCount"`, // Peak levels table: receives maximum absolute level for each channel over a processing pass, may be nil if pRMSLevls != nil, otherwise must have at least ChannelCount elements. + pRMSLevels: [^]f32 `fmt:"v,ChannelCount"`, // Root mean square levels table: receives RMS level for each channel over a processing pass, may be nil if pPeakLevels != nil, otherwise must have at least ChannelCount elements. + ChannelCount: u32, // Number of channels being processed by the volume meter APO } /************************************************************************** @@ -87,7 +86,7 @@ REVERB_PARAMETERS :: struct #packed { Density: f32, // [0, 100] (percentage) RoomSize: f32, // [1, 100] in feet // component control - DisableLateField: b32, // TRUE to disable late field reflections + DisableLateField: b32, // true to disable late field reflections } // Maximum, minimum and default values for the parameters above @@ -244,13 +243,13 @@ ReverbConvertI3DL2ToNative :: proc "contextless" (pI3DL2: ^REVERB_I3DL2_PARAMETE if pI3DL2.DecayHFRatio >= 1.0 { index := i32(-4.0 * math.log10_f32(pI3DL2.DecayHFRatio)) - if index < -8 { index = -8 } + if index < -8 {index = -8} pNative.LowEQGain = byte((index < 0) ? index + 8 : 8) pNative.HighEQGain = 8 pNative.DecayTime = pI3DL2.DecayTime * pI3DL2.DecayHFRatio } else { index := i32(4.0 * math.log10_f32(pI3DL2.DecayHFRatio)) - if index < -8 { index = -8 } + if index < -8 {index = -8} pNative.LowEQGain = 8 pNative.HighEQGain = byte((index < 0) ? index + 8 : 8) pNative.DecayTime = pI3DL2.DecayTime