diff --git a/core/fmt/fmt.odin b/core/fmt/fmt.odin index cadc9f1dd..e3e7a2bb5 100644 --- a/core/fmt/fmt.odin +++ b/core/fmt/fmt.odin @@ -972,7 +972,7 @@ fmt_bad_verb :: proc(fi: ^Info, verb: rune) { // fmt_bool :: proc(fi: ^Info, b: bool, verb: rune) { switch verb { - case 't', 'v': + case 't', 'v', 'w': fmt_string(fi, b ? "true" : "false", 's') case: fmt_bad_verb(fi, verb) @@ -1209,7 +1209,7 @@ fmt_rune :: proc(fi: ^Info, r: rune, verb: rune) { switch verb { case 'c', 'r', 'v': io.write_rune(fi.writer, r, &fi.n) - case 'q': + case 'q', 'w': fi.n += io.write_quoted_rune(fi.writer, r) case: fmt_int(fi, u64(r), false, 32, verb) @@ -1226,7 +1226,8 @@ fmt_rune :: proc(fi: ^Info, r: rune, verb: rune) { // fmt_int :: proc(fi: ^Info, u: u64, is_signed: bool, bit_size: int, verb: rune) { switch verb { - case 'v': _fmt_int(fi, u, 10, is_signed, bit_size, __DIGITS_LOWER) + case 'v', 'w': + _fmt_int(fi, u, 10, is_signed, bit_size, __DIGITS_LOWER) case 'b': _fmt_int(fi, u, 2, is_signed, bit_size, __DIGITS_LOWER) case 'o': _fmt_int(fi, u, 8, is_signed, bit_size, __DIGITS_LOWER) case 'i', 'd': _fmt_int(fi, u, 10, is_signed, bit_size, __DIGITS_LOWER) @@ -1261,7 +1262,8 @@ fmt_int :: proc(fi: ^Info, u: u64, is_signed: bool, bit_size: int, verb: rune) { // fmt_int_128 :: proc(fi: ^Info, u: u128, is_signed: bool, bit_size: int, verb: rune) { switch verb { - case 'v': _fmt_int_128(fi, u, 10, is_signed, bit_size, __DIGITS_LOWER) + case 'v', 'w': + _fmt_int_128(fi, u, 10, is_signed, bit_size, __DIGITS_LOWER) case 'b': _fmt_int_128(fi, u, 2, is_signed, bit_size, __DIGITS_LOWER) case 'o': _fmt_int_128(fi, u, 8, is_signed, bit_size, __DIGITS_LOWER) case 'i', 'd': _fmt_int_128(fi, u, 10, is_signed, bit_size, __DIGITS_LOWER) @@ -1351,7 +1353,7 @@ _fmt_float_as :: proc(fi: ^Info, v: f64, bit_size: int, verb: rune, float_fmt: b // fmt_float :: proc(fi: ^Info, v: f64, bit_size: int, verb: rune) { switch verb { - case 'g', 'G', 'v': + case 'g', 'G', 'v', 'w': _fmt_float_as(fi, v, bit_size, verb, 'g', -1) case 'f', 'F': _fmt_float_as(fi, v, bit_size, verb, 'f', 3) @@ -1424,7 +1426,7 @@ fmt_string :: proc(fi: ^Info, s: string, verb: rune) { io.write_string(fi.writer, s, &fi.n) } - case 'q': // quoted string + case 'q', 'w': // quoted string io.write_quoted_string(fi.writer, s, '"', &fi.n) case 'x', 'X': @@ -1467,7 +1469,7 @@ fmt_cstring :: proc(fi: ^Info, s: cstring, verb: rune) { fmt_pointer :: proc(fi: ^Info, p: rawptr, verb: rune) { u := u64(uintptr(p)) switch verb { - case 'p', 'v': + case 'p', 'v', 'w': if !fi.hash && verb == 'v' { io.write_string(fi.writer, "0x", &fi.n) } @@ -1535,7 +1537,7 @@ string_to_enum_value :: proc($T: typeid, s: string) -> (T, bool) { // Inputs: // - fi: Pointer to the Info struct containing format settings. // - v: The enum value to format. -// - verb: The format specifier character (e.g. 'i','d','f','s','v','q'). +// - verb: The format specifier character (e.g. 'i','d','f','s','v','q','w'). // fmt_enum :: proc(fi: ^Info, v: any, verb: rune) { if v.id == nil || v.data == nil { @@ -1559,6 +1561,15 @@ fmt_enum :: proc(fi: ^Info, v: any, verb: rune) { fmt_arg(fi, any{v.data, runtime.type_info_base(e.base).id}, 'i') io.write_string(fi.writer, ")", &fi.n) } + case 'w': + if str, ok := enum_value_to_string(v); ok { + io.write_byte(fi.writer, '.', &fi.n) + io.write_string(fi.writer, str, &fi.n) + } else { + io.write_string(fi.writer, "%!(BAD ENUM VALUE=", &fi.n) + fmt_arg(fi, any{v.data, runtime.type_info_base(e.base).id}, 'i') + io.write_string(fi.writer, ")", &fi.n) + } } } } @@ -1747,8 +1758,8 @@ fmt_write_indent :: proc(fi: ^Info) { // - verb: The formatting verb to be used for the array elements. // fmt_write_array :: proc(fi: ^Info, array_data: rawptr, count: int, elem_size: int, elem_id: typeid, verb: rune) { - io.write_byte(fi.writer, '[', &fi.n) - defer io.write_byte(fi.writer, ']', &fi.n) + io.write_byte(fi.writer, '[' if verb != 'w' else '{', &fi.n) + defer io.write_byte(fi.writer, ']' if verb != 'w' else '}', &fi.n) if count <= 0 { return @@ -1821,6 +1832,13 @@ handle_tag :: proc(data: rawptr, info: reflect.Type_Info_Struct, idx: int, verb: r, w := utf8.decode_rune_in_string(value) value = value[w:] if value == "" || value[0] == ',' { + if verb^ == 'w' { + // TODO(bill): is this a good idea overriding that field tags if 'w' is used? + switch r { + case 's': r = 'q' + case: r = 'w' + } + } verb^ = r if len(value) > 0 && value[0] == ',' { field_name := value[1:] @@ -1832,7 +1850,7 @@ handle_tag :: proc(data: rawptr, info: reflect.Type_Info_Struct, idx: int, verb: switch r { case 's', 'q': handle_optional_len(data, info, field_name, optional_len) - case 'v': + case 'v', 'w': #partial switch reflect.type_kind(info.types[idx].id) { case .String, .Multi_Pointer, .Array, .Slice, .Dynamic_Array: handle_optional_len(data, info, field_name, optional_len) @@ -1854,7 +1872,7 @@ handle_tag :: proc(data: rawptr, info: reflect.Type_Info_Struct, idx: int, verb: // - type_name: The name of the type being formatted // fmt_struct :: proc(fi: ^Info, v: any, the_verb: rune, info: runtime.Type_Info_Struct, type_name: string) { - if the_verb != 'v' { + if the_verb != 'v' && the_verb != 'w' { fmt_bad_verb(fi, the_verb) return } @@ -1871,7 +1889,7 @@ fmt_struct :: proc(fi: ^Info, v: any, the_verb: rune, info: runtime.Type_Info_St is_soa := info.soa_kind != .None io.write_string(fi.writer, type_name, &fi.n) - io.write_byte(fi.writer, '[' if is_soa else '{', &fi.n) + io.write_byte(fi.writer, '[' if is_soa && the_verb == 'v' else '{', &fi.n) fi.record_level += 1 defer fi.record_level -= 1 @@ -1889,7 +1907,7 @@ fmt_struct :: proc(fi: ^Info, v: any, the_verb: rune, info: runtime.Type_Info_St if hash { for _ in 0.. 0 { @@ -2130,141 +2148,143 @@ fmt_named :: proc(fi: ^Info, v: any, verb: rune, info: runtime.Type_Info_Named) } // Built-in Custom Formatters for core library types - switch a in v { - case runtime.Source_Code_Location: - io.write_string(fi.writer, a.file_path, &fi.n) + if verb != 'w' { + switch a in v { + case runtime.Source_Code_Location: + io.write_string(fi.writer, a.file_path, &fi.n) - when ODIN_ERROR_POS_STYLE == .Default { - io.write_byte(fi.writer, '(', &fi.n) - io.write_int(fi.writer, int(a.line), 10, &fi.n) - io.write_byte(fi.writer, ':', &fi.n) - io.write_int(fi.writer, int(a.column), 10, &fi.n) - io.write_byte(fi.writer, ')', &fi.n) - } else when ODIN_ERROR_POS_STYLE == .Unix { - io.write_byte(fi.writer, ':', &fi.n) - io.write_int(fi.writer, int(a.line), 10, &fi.n) - io.write_byte(fi.writer, ':', &fi.n) - io.write_int(fi.writer, int(a.column), 10, &fi.n) - io.write_byte(fi.writer, ':', &fi.n) - } else { - #panic("Unhandled ODIN_ERROR_POS_STYLE") - } - return - - case time.Duration: - ffrac :: proc(buf: []byte, v: u64, prec: int) -> (nw: int, nv: u64) { - v := v - w := len(buf) - print := false - for _ in 0.. int { - v := v - w := len(buf) - if v == 0 { - w -= 1 - buf[w] = '0' + when ODIN_ERROR_POS_STYLE == .Default { + io.write_byte(fi.writer, '(', &fi.n) + io.write_int(fi.writer, int(a.line), 10, &fi.n) + io.write_byte(fi.writer, ':', &fi.n) + io.write_int(fi.writer, int(a.column), 10, &fi.n) + io.write_byte(fi.writer, ')', &fi.n) + } else when ODIN_ERROR_POS_STYLE == .Unix { + io.write_byte(fi.writer, ':', &fi.n) + io.write_int(fi.writer, int(a.line), 10, &fi.n) + io.write_byte(fi.writer, ':', &fi.n) + io.write_int(fi.writer, int(a.column), 10, &fi.n) + io.write_byte(fi.writer, ':', &fi.n) } else { - for v > 0 { - w -= 1 - buf[w] = byte(v%10) + '0' + #panic("Unhandled ODIN_ERROR_POS_STYLE") + } + return + + case time.Duration: + ffrac :: proc(buf: []byte, v: u64, prec: int) -> (nw: int, nv: u64) { + v := v + w := len(buf) + print := false + for _ in 0.. int { + v := v + w := len(buf) + if v == 0 { + w -= 1 + buf[w] = '0' + } else { + for v > 0 { + w -= 1 + buf[w] = byte(v%10) + '0' + v /= 10 + } + } + return w } - w, u = ffrac(buf[:w], u, prec) - w = fint(buf[:w], u) - } else { - w -= 1 - buf[w] = 's' - w, u = ffrac(buf[:w], u, 9) - w = fint(buf[:w], u%60) - u /= 60 - if u > 0 { + + buf: [32]byte + w := len(buf) + u := u64(a) + neg := a < 0 + if neg { + u = -u + } + + if u < u64(time.Second) { + prec: int w -= 1 - buf[w] = 'm' + buf[w] = 's' + w -= 1 + switch { + case u == 0: + io.write_string(fi.writer, "0s", &fi.n) + return + case u < u64(time.Microsecond): + prec = 0 + buf[w] = 'n' + case u < u64(time.Millisecond): + prec = 3 + // U+00B5 'µ' micro sign == 0xC2 0xB5 + w -= 1 // Need room for two bytes + copy(buf[w:], "µ") + case: + prec = 6 + buf[w] = 'm' + } + w, u = ffrac(buf[:w], u, prec) + w = fint(buf[:w], u) + } else { + w -= 1 + buf[w] = 's' + w, u = ffrac(buf[:w], u, 9) w = fint(buf[:w], u%60) u /= 60 if u > 0 { w -= 1 - buf[w] = 'h' - w = fint(buf[:w], u) + buf[w] = 'm' + w = fint(buf[:w], u%60) + u /= 60 + if u > 0 { + w -= 1 + buf[w] = 'h' + w = fint(buf[:w], u) + } } } + + if neg { + w -= 1 + buf[w] = '-' + } + io.write_string(fi.writer, string(buf[w:]), &fi.n) + return + + case time.Time: + t := a + y, mon, d := time.date(t) + h, min, s := time.clock(t) + ns := (t._nsec - (t._nsec/1e9 + time.UNIX_TO_ABSOLUTE)*1e9) % 1e9 + write_padded_number(fi, i64(y), 4) + io.write_byte(fi.writer, '-', &fi.n) + write_padded_number(fi, i64(mon), 2) + io.write_byte(fi.writer, '-', &fi.n) + write_padded_number(fi, i64(d), 2) + io.write_byte(fi.writer, ' ', &fi.n) + + write_padded_number(fi, i64(h), 2) + io.write_byte(fi.writer, ':', &fi.n) + write_padded_number(fi, i64(min), 2) + io.write_byte(fi.writer, ':', &fi.n) + write_padded_number(fi, i64(s), 2) + io.write_byte(fi.writer, '.', &fi.n) + write_padded_number(fi, (ns), 9) + io.write_string(fi.writer, " +0000 UTC", &fi.n) + return } - - if neg { - w -= 1 - buf[w] = '-' - } - io.write_string(fi.writer, string(buf[w:]), &fi.n) - return - - case time.Time: - t := a - y, mon, d := time.date(t) - h, min, s := time.clock(t) - ns := (t._nsec - (t._nsec/1e9 + time.UNIX_TO_ABSOLUTE)*1e9) % 1e9 - write_padded_number(fi, i64(y), 4) - io.write_byte(fi.writer, '-', &fi.n) - write_padded_number(fi, i64(mon), 2) - io.write_byte(fi.writer, '-', &fi.n) - write_padded_number(fi, i64(d), 2) - io.write_byte(fi.writer, ' ', &fi.n) - - write_padded_number(fi, i64(h), 2) - io.write_byte(fi.writer, ':', &fi.n) - write_padded_number(fi, i64(min), 2) - io.write_byte(fi.writer, ':', &fi.n) - write_padded_number(fi, i64(s), 2) - io.write_byte(fi.writer, '.', &fi.n) - write_padded_number(fi, (ns), 9) - io.write_string(fi.writer, " +0000 UTC", &fi.n) - return } #partial switch b in info.base.variant { @@ -2275,6 +2295,23 @@ fmt_named :: proc(fi: ^Info, v: any, verb: rune, info: runtime.Type_Info_Named) case runtime.Type_Info_Bit_Set: fmt_bit_set(fi, v, verb = verb) case: + if verb == 'w' { + #partial switch _ in info.base.variant { + case runtime.Type_Info_Array, + runtime.Type_Info_Enumerated_Array, + runtime.Type_Info_Dynamic_Array, + runtime.Type_Info_Slice, + runtime.Type_Info_Struct, + runtime.Type_Info_Union, + runtime.Type_Info_Enum, + runtime.Type_Info_Map, + runtime.Type_Info_Bit_Set, + runtime.Type_Info_Simd_Vector, + runtime.Type_Info_Matrix, + runtime.Type_Info_Bit_Field: + io.write_string(fi.writer, info.name, &fi.n) + } + } fmt_value(fi, any{v.data, info.base.id}, verb) } } @@ -2341,8 +2378,13 @@ fmt_union :: proc(fi: ^Info, v: any, verb: rune, info: runtime.Type_Info_Union, // - info: A runtime.Type_Info_Matrix struct containing matrix type information. // fmt_matrix :: proc(fi: ^Info, v: any, verb: rune, info: runtime.Type_Info_Matrix) { - io.write_string(fi.writer, "matrix[", &fi.n) - defer io.write_byte(fi.writer, ']', &fi.n) + if verb == 'w' { + io.write_byte(fi.writer, '{', &fi.n) + } else { + io.write_string(fi.writer, "matrix", &fi.n) + io.write_byte(fi.writer, '[', &fi.n) + } + defer io.write_byte(fi.writer, ']' if verb != 'w' else '}', &fi.n) fi.indent += 1 @@ -2413,8 +2455,8 @@ fmt_bit_field :: proc(fi: ^Info, v: any, verb: rune, info: runtime.Type_Info_Bit return false } - io.write_string(fi.writer, type_name if len(type_name) != 0 else "bit_field", &fi.n) - io.write_string(fi.writer, "{", &fi.n) + io.write_string(fi.writer, type_name if len(type_name) != 0 || verb == 'w' else "bit_field", &fi.n) + io.write_byte(fi.writer, '{', &fi.n) hash := fi.hash; defer fi.hash = hash indent := fi.indent; defer fi.indent -= 1 @@ -2631,11 +2673,12 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) { defer fi.record_level -= 1 if fi.hash { - io.write_string(fi.writer, "[\n", &fi.n) + io.write_byte(fi.writer, '[' if verb != 'w' else '{', &fi.n) + io.write_byte(fi.writer, '\n', &fi.n) defer { io.write_byte(fi.writer, '\n', &fi.n) fmt_write_indent(fi) - io.write_byte(fi.writer, ']', &fi.n) + io.write_byte(fi.writer, ']' if verb != 'w' else '}', &fi.n) } indent := fi.indent fi.indent += 1 @@ -2659,8 +2702,8 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) { io.write_string(fi.writer, ",\n", &fi.n) } } else { - io.write_byte(fi.writer, '[', &fi.n) - defer io.write_byte(fi.writer, ']', &fi.n) + io.write_byte(fi.writer, '[' if verb != 'w' else '{', &fi.n) + io.write_byte(fi.writer, ']' if verb != 'w' else '}', &fi.n) for i in 0.. 0 { io.write_string(fi.writer, ", ", &fi.n) } @@ -2725,38 +2768,61 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) { case runtime.Type_Info_Map: - if verb != 'v' { + switch verb { + case: fmt_bad_verb(fi, verb) - return - } - - io.write_string(fi.writer, "map[", &fi.n) - defer io.write_byte(fi.writer, ']', &fi.n) - fi.record_level += 1 - defer fi.record_level -= 1 - - m := (^mem.Raw_Map)(v.data) - if m != nil { - if info.map_info == nil { - return + case 'v', 'w': + if verb == 'v' { + io.write_string(fi.writer, "map", &fi.n) } - map_cap := uintptr(runtime.map_cap(m^)) - ks, vs, hs, _, _ := runtime.map_kvh_data_dynamic(m^, info.map_info) - j := 0 - for bucket_index in 0.. 0 { - io.write_string(fi.writer, ", ", &fi.n) + + hash := fi.hash; defer fi.hash = hash + indent := fi.indent; defer fi.indent -= 1 + do_trailing_comma := hash + + fi.indent += 1 + if hash { + io.write_byte(fi.writer, '\n', &fi.n) + } + defer { + if hash { + for _ in 0..= 0 { @@ -2835,11 +2901,11 @@ fmt_complex :: proc(fi: ^Info, c: complex128, bits: int, verb: rune) { // - fi: A pointer to an Info struct containing formatting information. // - q: The quaternion256 value to be formatted. // - bits: The number of bits in the quaternion number (64, 128, or 256). -// - verb: The formatting verb rune ('f', 'F', 'v', 'h', 'H'). +// - verb: The formatting verb rune ('f', 'F', 'v', 'h', 'H', 'w'). // fmt_quaternion :: proc(fi: ^Info, q: quaternion256, bits: int, verb: rune) { switch verb { - case 'f', 'F', 'v', 'h', 'H': + case 'f', 'F', 'v', 'h', 'H', 'w': r, i, j, k := real(q), imag(q), jmag(q), kmag(q) fmt_float(fi, r, bits/4, verb) diff --git a/core/mem/virtual/arena.odin b/core/mem/virtual/arena.odin index 5d8df2057..80c231c31 100644 --- a/core/mem/virtual/arena.odin +++ b/core/mem/virtual/arena.odin @@ -17,18 +17,23 @@ Arena_Kind :: enum uint { Buffer: A single `Memory_Block` created from a user provided []byte. */ Arena :: struct { - kind: Arena_Kind, - curr_block: ^Memory_Block, - total_used: uint, - total_reserved: uint, - minimum_block_size: uint, - temp_count: uint, - mutex: sync.Mutex, + kind: Arena_Kind, + curr_block: ^Memory_Block, + + total_used: uint, + total_reserved: uint, + + default_commit_size: uint, // commit size <= reservation size + minimum_block_size: uint, // block size == total reservation + + temp_count: uint, + mutex: sync.Mutex, } // 1 MiB should be enough to start with DEFAULT_ARENA_STATIC_COMMIT_SIZE :: mem.Megabyte +DEFAULT_ARENA_GROWING_COMMIT_SIZE :: 8*mem.Megabyte DEFAULT_ARENA_GROWING_MINIMUM_BLOCK_SIZE :: DEFAULT_ARENA_STATIC_COMMIT_SIZE // 1 GiB on 64-bit systems, 128 MiB on 32-bit systems by default @@ -102,8 +107,20 @@ arena_alloc :: proc(arena: ^Arena, size: uint, alignment: uint, loc := #caller_l if arena.curr_block == nil || (safe_add(arena.curr_block.used, needed) or_else 0) > arena.curr_block.reserved { if arena.minimum_block_size == 0 { arena.minimum_block_size = DEFAULT_ARENA_GROWING_MINIMUM_BLOCK_SIZE + arena.minimum_block_size = mem.align_forward_uint(arena.minimum_block_size, DEFAULT_PAGE_SIZE) + } + if arena.default_commit_size == 0 { + arena.default_commit_size = min(DEFAULT_ARENA_GROWING_COMMIT_SIZE, arena.minimum_block_size) + arena.default_commit_size = mem.align_forward_uint(arena.default_commit_size, DEFAULT_PAGE_SIZE) } + if arena.default_commit_size != 0 { + arena.default_commit_size, arena.minimum_block_size = + min(arena.default_commit_size, arena.minimum_block_size), + max(arena.default_commit_size, arena.minimum_block_size) + } + + needed = max(needed, arena.default_commit_size) block_size := max(needed, arena.minimum_block_size) new_block := memory_block_alloc(needed, block_size, alignment, {}) or_return @@ -113,7 +130,7 @@ arena_alloc :: proc(arena: ^Arena, size: uint, alignment: uint, loc := #caller_l } prev_used := arena.curr_block.used - data, err = alloc_from_memory_block(arena.curr_block, size, alignment) + data, err = alloc_from_memory_block(arena.curr_block, size, alignment, default_commit_size=arena.default_commit_size) arena.total_used += arena.curr_block.used - prev_used case .Static: if arena.curr_block == nil { @@ -122,12 +139,17 @@ arena_alloc :: proc(arena: ^Arena, size: uint, alignment: uint, loc := #caller_l } arena_init_static(arena, reserved=arena.minimum_block_size, commit_size=DEFAULT_ARENA_STATIC_COMMIT_SIZE) or_return } - fallthrough + if arena.curr_block == nil { + return nil, .Out_Of_Memory + } + data, err = alloc_from_memory_block(arena.curr_block, size, alignment, default_commit_size=arena.default_commit_size) + arena.total_used = arena.curr_block.used + case .Buffer: if arena.curr_block == nil { return nil, .Out_Of_Memory } - data, err = alloc_from_memory_block(arena.curr_block, size, alignment) + data, err = alloc_from_memory_block(arena.curr_block, size, alignment, default_commit_size=0) arena.total_used = arena.curr_block.used } return diff --git a/core/mem/virtual/virtual.odin b/core/mem/virtual/virtual.odin index efbdefcf6..4e53aba66 100644 --- a/core/mem/virtual/virtual.odin +++ b/core/mem/virtual/virtual.odin @@ -112,7 +112,7 @@ memory_block_alloc :: proc(committed, reserved: uint, alignment: uint = 0, flags } @(require_results) -alloc_from_memory_block :: proc(block: ^Memory_Block, min_size, alignment: uint) -> (data: []byte, err: Allocator_Error) { +alloc_from_memory_block :: proc(block: ^Memory_Block, min_size, alignment: uint, default_commit_size: uint = 0) -> (data: []byte, err: Allocator_Error) { calc_alignment_offset :: proc "contextless" (block: ^Memory_Block, alignment: uintptr) -> uint { alignment_offset := uint(0) ptr := uintptr(block.base[block.used:]) @@ -123,7 +123,7 @@ alloc_from_memory_block :: proc(block: ^Memory_Block, min_size, alignment: uint) return alignment_offset } - do_commit_if_necessary :: proc(block: ^Memory_Block, size: uint) -> (err: Allocator_Error) { + do_commit_if_necessary :: proc(block: ^Memory_Block, size: uint, default_commit_size: uint) -> (err: Allocator_Error) { if block.committed - block.used < size { pmblock := (^Platform_Memory_Block)(block) base_offset := uint(uintptr(pmblock.block.base) - uintptr(pmblock)) @@ -133,7 +133,7 @@ alloc_from_memory_block :: proc(block: ^Memory_Block, min_size, alignment: uint) extra_size := max(size, block.committed>>1) platform_total_commit := base_offset + block.used + extra_size platform_total_commit = align_formula(platform_total_commit, DEFAULT_PAGE_SIZE) - platform_total_commit = min(platform_total_commit, pmblock.reserved) + platform_total_commit = min(max(platform_total_commit, default_commit_size), pmblock.reserved) assert(pmblock.committed <= pmblock.reserved) assert(pmblock.committed < platform_total_commit) @@ -163,7 +163,7 @@ alloc_from_memory_block :: proc(block: ^Memory_Block, min_size, alignment: uint) return } assert(block.committed <= block.reserved) - do_commit_if_necessary(block, size) or_return + do_commit_if_necessary(block, size, default_commit_size) or_return data = block.base[block.used+alignment_offset:][:min_size] block.used += size diff --git a/core/sys/windows/gdi32.odin b/core/sys/windows/gdi32.odin index 1d2be6dab..6d53845de 100644 --- a/core/sys/windows/gdi32.odin +++ b/core/sys/windows/gdi32.odin @@ -1,6 +1,8 @@ // +build windows package sys_windows +import "core:math/fixed" + foreign import gdi32 "system:Gdi32.lib" @(default_calling_convention="system") @@ -11,6 +13,7 @@ foreign gdi32 { SetBkColor :: proc(hdc: HDC, color: COLORREF) -> COLORREF --- CreateCompatibleDC :: proc(hdc: HDC) -> HDC --- + DeleteDC :: proc(hdc: HDC) -> BOOL --- CreateDIBPatternBrush :: proc(h: HGLOBAL, iUsage: UINT) -> HBRUSH --- @@ -93,3 +96,45 @@ foreign gdi32 { RGB :: #force_inline proc "contextless" (r, g, b: u8) -> COLORREF { return transmute(COLORREF)[4]u8{r, g, b, 0} } + +FXPT2DOT30 :: distinct fixed.Fixed(i32, 30) + +CIEXYZ :: struct { + ciexyzX: FXPT2DOT30, + ciexyzY: FXPT2DOT30, + ciexyzZ: FXPT2DOT30, +} + +CIEXYZTRIPLE :: struct { + ciexyzRed: CIEXYZ, + ciexyzGreen: CIEXYZ, + ciexyzBlue: CIEXYZ, +} + +// https://learn.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-bitmapv5header +BITMAPV5HEADER :: struct { + bV5Size: DWORD, + bV5Width: LONG, + bV5Height: LONG, + bV5Planes: WORD, + bV5BitCount: WORD, + bV5Compression: DWORD, + bV5SizeImage: DWORD, + bV5XPelsPerMeter: LONG, + bV5YPelsPerMeter: LONG, + bV5ClrUsed: DWORD, + bV5ClrImportant: DWORD, + bV5RedMask: DWORD, + bV5GreenMask: DWORD, + bV5BlueMask: DWORD, + bV5AlphaMask: DWORD, + bV5CSType: DWORD, + bV5Endpoints: CIEXYZTRIPLE, + bV5GammaRed: DWORD, + bV5GammaGreen: DWORD, + bV5GammaBlue: DWORD, + bV5Intent: DWORD, + bV5ProfileData: DWORD, + bV5ProfileSize: DWORD, + bV5Reserved: DWORD, +} diff --git a/core/sys/windows/kernel32.odin b/core/sys/windows/kernel32.odin index 33422370c..952d5bb31 100644 --- a/core/sys/windows/kernel32.odin +++ b/core/sys/windows/kernel32.odin @@ -1200,3 +1200,22 @@ SYSTEM_LOGICAL_PROCESSOR_INFORMATION :: struct { Relationship: LOGICAL_PROCESSOR_RELATIONSHIP, DummyUnion: DUMMYUNIONNAME_u, } + +/* Global Memory Flags */ +GMEM_FIXED :: 0x0000 +GMEM_MOVEABLE :: 0x0002 +GMEM_NOCOMPACT :: 0x0010 +GMEM_NODISCARD :: 0x0020 +GMEM_ZEROINIT :: 0x0040 +GMEM_MODIFY :: 0x0080 +GMEM_DISCARDABLE :: 0x0100 +GMEM_NOT_BANKED :: 0x1000 +GMEM_SHARE :: 0x2000 +GMEM_DDESHARE :: 0x2000 +GMEM_NOTIFY :: 0x4000 +GMEM_LOWER :: GMEM_NOT_BANKED +GMEM_VALID_FLAGS :: 0x7F72 +GMEM_INVALID_HANDLE :: 0x8000 + +GHND :: (GMEM_MOVEABLE | GMEM_ZEROINIT) +GPTR :: (GMEM_FIXED | GMEM_ZEROINIT) diff --git a/core/sys/windows/shell32.odin b/core/sys/windows/shell32.odin index 358b8482f..4108d54d8 100644 --- a/core/sys/windows/shell32.odin +++ b/core/sys/windows/shell32.odin @@ -25,6 +25,7 @@ foreign shell32 { SHAppBarMessage :: proc(dwMessage: DWORD, pData: PAPPBARDATA) -> UINT_PTR --- Shell_NotifyIconW :: proc(dwMessage: DWORD, lpData: ^NOTIFYICONDATAW) -> BOOL --- + SHChangeNotify :: proc(wEventId: LONG, uFlags: UINT, dwItem1: LPCVOID, dwItem2: LPCVOID) --- SHGetKnownFolderIDList :: proc(rfid: REFKNOWNFOLDERID, dwFlags: /* KNOWN_FOLDER_FLAG */ DWORD, hToken: HANDLE, ppidl: rawptr) -> HRESULT --- SHSetKnownFolderPath :: proc(rfid: REFKNOWNFOLDERID, dwFlags: /* KNOWN_FOLDER_FLAG */ DWORD, hToken: HANDLE, pszPath: PCWSTR ) -> HRESULT --- @@ -91,3 +92,53 @@ KNOWN_FOLDER_FLAG :: enum u32 { SIMPLE_IDLIST = 0x00000100, ALIAS_ONLY = 0x80000000, } + +SHCNRF_InterruptLevel :: 0x0001 +SHCNRF_ShellLevel :: 0x0002 +SHCNRF_RecursiveInterrupt :: 0x1000 +SHCNRF_NewDelivery :: 0x8000 + +SHCNE_RENAMEITEM :: 0x00000001 +SHCNE_CREATE :: 0x00000002 +SHCNE_DELETE :: 0x00000004 +SHCNE_MKDIR :: 0x00000008 +SHCNE_RMDIR :: 0x00000010 +SHCNE_MEDIAINSERTED :: 0x00000020 +SHCNE_MEDIAREMOVED :: 0x00000040 +SHCNE_DRIVEREMOVED :: 0x00000080 +SHCNE_DRIVEADD :: 0x00000100 +SHCNE_NETSHARE :: 0x00000200 +SHCNE_NETUNSHARE :: 0x00000400 +SHCNE_ATTRIBUTES :: 0x00000800 +SHCNE_UPDATEDIR :: 0x00001000 +SHCNE_UPDATEITEM :: 0x00002000 +SHCNE_SERVERDISCONNECT :: 0x00004000 +SHCNE_UPDATEIMAGE :: 0x00008000 +SHCNE_DRIVEADDGUI :: 0x00010000 +SHCNE_RENAMEFOLDER :: 0x00020000 +SHCNE_FREESPACE :: 0x00040000 + +SHCNE_EXTENDED_EVENT :: 0x04000000 + +SHCNE_ASSOCCHANGED :: 0x08000000 + +SHCNE_DISKEVENTS :: 0x0002381F +SHCNE_GLOBALEVENTS :: 0x0C0581E0 +SHCNE_ALLEVENTS :: 0x7FFFFFFF +SHCNE_INTERRUPT :: 0x80000000 + +SHCNEE_ORDERCHANGED :: 2 +SHCNEE_MSI_CHANGE :: 4 +SHCNEE_MSI_UNINSTALL :: 5 + +SHCNF_IDLIST :: 0x0000 +SHCNF_PATHA :: 0x0001 +SHCNF_PRINTERA :: 0x0002 +SHCNF_DWORD :: 0x0003 +SHCNF_PATHW :: 0x0005 +SHCNF_PRINTERW :: 0x0006 +SHCNF_TYPE :: 0x00FF +SHCNF_FLUSH :: 0x1000 +SHCNF_FLUSHNOWAIT :: 0x3000 + +SHCNF_NOTIFYRECURSIVE :: 0x10000 diff --git a/core/sys/windows/user32.odin b/core/sys/windows/user32.odin index 8c0fa246d..a589c3ec9 100644 --- a/core/sys/windows/user32.odin +++ b/core/sys/windows/user32.odin @@ -47,6 +47,7 @@ foreign user32 { UpdateWindow :: proc(hWnd: HWND) -> BOOL --- SetActiveWindow :: proc(hWnd: HWND) -> HWND --- GetActiveWindow :: proc() -> HWND --- + RedrawWindow :: proc(hwnd: HWND, lprcUpdate: LPRECT, hrgnUpdate: HRGN, flags: RedrawWindowFlags) -> BOOL --- GetMessageW :: proc(lpMsg: ^MSG, hWnd: HWND, wMsgFilterMin: UINT, wMsgFilterMax: UINT) -> BOOL --- @@ -85,6 +86,14 @@ foreign user32 { LoadCursorW :: proc(hInstance: HINSTANCE, lpCursorName: LPCWSTR) -> HCURSOR --- LoadImageW :: proc(hInst: HINSTANCE, name: LPCWSTR, type: UINT, cx: c_int, cy: c_int, fuLoad: UINT) -> HANDLE --- + CreateIcon :: proc(hInstance: HINSTANCE, nWidth: c_int, nHeight: c_int, cPlanes: BYTE, cBitsPixel: BYTE, lpbANDbits: PBYTE, lpbXORbits: PBYTE) -> HICON --- + CreateIconFromResource :: proc(presbits: PBYTE, dwResSize: DWORD, fIcon: BOOL, dwVer: DWORD) -> HICON --- + DestroyIcon :: proc(hIcon: HICON) -> BOOL --- + DrawIcon :: proc(hDC: HDC, X: c_int, Y: c_int, hIcon: HICON) -> BOOL --- + + CreateCursor :: proc(hInst: HINSTANCE, xHotSpot: c_int, yHotSpot: c_int, nWidth: c_int, nHeight: c_int, pvANDPlane: PVOID, pvXORPlane: PVOID) -> HCURSOR --- + DestroyCursor :: proc(hCursor: HCURSOR) -> BOOL --- + GetWindowRect :: proc(hWnd: HWND, lpRect: LPRECT) -> BOOL --- GetClientRect :: proc(hWnd: HWND, lpRect: LPRECT) -> BOOL --- ClientToScreen :: proc(hWnd: HWND, lpPoint: LPPOINT) -> BOOL --- @@ -134,7 +143,7 @@ foreign user32 { GetKeyState :: proc(nVirtKey: c_int) -> SHORT --- GetAsyncKeyState :: proc(vKey: c_int) -> SHORT --- - + GetKeyboardState :: proc(lpKeyState: PBYTE) -> BOOL --- MapVirtualKeyW :: proc(uCode: UINT, uMapType: UINT) -> UINT --- @@ -166,7 +175,7 @@ foreign user32 { MonitorFromRect :: proc(lprc: LPRECT, dwFlags: Monitor_From_Flags) -> HMONITOR --- MonitorFromWindow :: proc(hwnd: HWND, dwFlags: Monitor_From_Flags) -> HMONITOR --- EnumDisplayMonitors :: proc(hdc: HDC, lprcClip: LPRECT, lpfnEnum: Monitor_Enum_Proc, dwData: LPARAM) -> BOOL --- - + EnumWindows :: proc(lpEnumFunc: Window_Enum_Proc, lParam: LPARAM) -> BOOL --- SetThreadDpiAwarenessContext :: proc(dpiContext: DPI_AWARENESS_CONTEXT) -> DPI_AWARENESS_CONTEXT --- @@ -239,6 +248,9 @@ foreign user32 { GetSystemMenu :: proc(hWnd: HWND, bRevert: BOOL) -> HMENU --- EnableMenuItem :: proc(hMenu: HMENU, uIDEnableItem: UINT, uEnable: UINT) -> BOOL --- + + DrawTextW :: proc(hdc: HDC, lpchText: LPCWSTR, cchText: INT, lprc: LPRECT, format: DrawTextFormat) -> INT --- + DrawTextExW :: proc(hdc: HDC, lpchText: LPCWSTR, cchText: INT, lprc: LPRECT, format: DrawTextFormat, lpdtp: PDRAWTEXTPARAMS) -> INT --- } CreateWindowW :: #force_inline proc "system" ( @@ -471,6 +483,19 @@ RI_MOUSE_BUTTON_5_UP :: 0x0200 RI_MOUSE_WHEEL :: 0x0400 RI_MOUSE_HWHEEL :: 0x0800 +HID_USAGE_PAGE_GENERIC :: 0x01 +HID_USAGE_PAGE_GAME :: 0x05 +HID_USAGE_PAGE_LED :: 0x08 +HID_USAGE_PAGE_BUTTON :: 0x09 + +HID_USAGE_GENERIC_POINTER :: 0x01 +HID_USAGE_GENERIC_MOUSE :: 0x02 +HID_USAGE_GENERIC_JOYSTICK :: 0x04 +HID_USAGE_GENERIC_GAMEPAD :: 0x05 +HID_USAGE_GENERIC_KEYBOARD :: 0x06 +HID_USAGE_GENERIC_KEYPAD :: 0x07 +HID_USAGE_GENERIC_MULTI_AXIS_CONTROLLER :: 0x08 + WINDOWPLACEMENT :: struct { length: UINT, flags: UINT, @@ -493,3 +518,54 @@ WINDOWINFO :: struct { wCreatorVersion: WORD, } PWINDOWINFO :: ^WINDOWINFO + +DRAWTEXTPARAMS :: struct { + cbSize : UINT , + iTabLength: int , + iLeftMargin: int , + iRightMargin: int , + uiLengthDrawn: UINT , +} +PDRAWTEXTPARAMS :: ^DRAWTEXTPARAMS + +DrawTextFormat :: enum UINT { + DT_TOP = 0x00000000, + DT_LEFT = 0x00000000, + DT_CENTER = 0x00000001, + DT_RIGHT = 0x00000002, + DT_VCENTER = 0x00000004, + DT_BOTTOM = 0x00000008, + DT_WORDBREAK = 0x00000010, + DT_SINGLELINE = 0x00000020, + DT_EXPANDTABS = 0x00000040, + DT_TABSTOP = 0x00000080, + DT_NOCLIP = 0x00000100, + DT_EXTERNALLEADING = 0x00000200, + DT_CALCRECT = 0x00000400, + DT_NOPREFIX = 0x00000800, + DT_INTERNAL = 0x00001000, + DT_EDITCONTROL = 0x00002000, + DT_PATH_ELLIPSIS = 0x00004000, + DT_END_ELLIPSIS = 0x00008000, + DT_MODIFYSTRING = 0x00010000, + DT_RTLREADING = 0x00020000, + DT_WORD_ELLIPSIS = 0x00040000, + DT_NOFULLWIDTHCHARBREAK = 0x00080000, + DT_HIDEPREFIX = 0x00100000, + DT_PREFIXONLY = 0x00200000, +} + +RedrawWindowFlags :: enum UINT { + RDW_INVALIDATE = 0x0001, + RDW_INTERNALPAINT = 0x0002, + RDW_ERASE = 0x0004, + RDW_VALIDATE = 0x0008, + RDW_NOINTERNALPAINT = 0x0010, + RDW_NOERASE = 0x0020, + RDW_NOCHILDREN = 0x0040, + RDW_ALLCHILDREN = 0x0080, + RDW_UPDATENOW = 0x0100, + RDW_ERASENOW = 0x0200, + RDW_FRAME = 0x0400, + RDW_NOFRAME = 0x0800, +} diff --git a/core/sys/windows/winmm.odin b/core/sys/windows/winmm.odin index 0807df8de..8ddef29c0 100644 --- a/core/sys/windows/winmm.odin +++ b/core/sys/windows/winmm.odin @@ -11,6 +11,32 @@ foreign winmm { timeBeginPeriod :: proc(uPeriod: UINT) -> MMRESULT --- timeEndPeriod :: proc(uPeriod: UINT) -> MMRESULT --- timeGetTime :: proc() -> DWORD --- + + waveOutGetNumDevs :: proc() -> UINT --- + waveOutGetDevCapsW :: proc(uDeviceID: UINT_PTR, pwoc: LPWAVEOUTCAPSW, cbwoc: UINT) -> MMRESULT --- + waveOutGetVolume :: proc(hwo: HWAVEOUT, pdwVolume: LPDWORD) -> MMRESULT --- + waveOutSetVolume :: proc(hwo: HWAVEOUT, dwVolume: DWORD) -> MMRESULT --- + waveOutGetErrorTextW :: proc(mmrError: MMRESULT, pszText: LPWSTR, cchText: UINT) -> MMRESULT --- + waveOutOpen :: proc(phwo: LPHWAVEOUT, uDeviceID: UINT, pwfx: LPCWAVEFORMATEX, dwCallback: DWORD_PTR, dwInstance: DWORD_PTR, fdwOpen: DWORD) -> MMRESULT --- + waveOutClose :: proc(hwo: HWAVEOUT) -> MMRESULT --- + waveOutPrepareHeader :: proc(hwo: HWAVEOUT, pwh: LPWAVEHDR, cbwh: UINT) -> MMRESULT --- + waveOutUnprepareHeader :: proc(hwo: HWAVEOUT, pwh: LPWAVEHDR, cbwh: UINT) -> MMRESULT --- + waveOutWrite :: proc(hwo: HWAVEOUT, pwh: LPWAVEHDR, cbwh: UINT) -> MMRESULT --- + waveOutPause :: proc(hwo: HWAVEOUT) -> MMRESULT --- + waveOutRestart :: proc(hwo: HWAVEOUT) -> MMRESULT --- + waveOutReset :: proc(hwo: HWAVEOUT) -> MMRESULT --- + waveOutBreakLoop :: proc(hwo: HWAVEOUT) -> MMRESULT --- + waveOutGetPosition :: proc(hwo: HWAVEOUT, pmmt: LPMMTIME, cbmmt: UINT) -> MMRESULT --- + waveOutGetPitch :: proc(hwo: HWAVEOUT, pdwPitch: LPDWORD) -> MMRESULT --- + waveOutSetPitch :: proc(hwo: HWAVEOUT, pdwPitch: DWORD) -> MMRESULT --- + waveOutGetPlaybackRate :: proc(hwo: HWAVEOUT, pdwRate: LPDWORD) -> MMRESULT --- + waveOutSetPlaybackRate :: proc(hwo: HWAVEOUT, pdwRate: DWORD) -> MMRESULT --- + waveOutGetID :: proc(hwo: HWAVEOUT, puDeviceID: LPUINT) -> MMRESULT --- + + waveInGetNumDevs :: proc() -> UINT --- + waveInGetDevCapsW :: proc(uDeviceID: UINT_PTR, pwic: LPWAVEINCAPSW, cbwic: UINT) -> MMRESULT --- + + PlaySoundW :: proc(pszSound: LPCWSTR, hmod: HMODULE, fdwSound: DWORD) -> BOOL --- } LPTIMECAPS :: ^TIMECAPS @@ -169,4 +195,182 @@ MCIERR_NO_IDENTITY :: MCIERR_BASE + 94 MIXERR_INVALLINE :: (MIXERR_BASE + 0) MIXERR_INVALCONTROL :: (MIXERR_BASE + 1) MIXERR_INVALVALUE :: (MIXERR_BASE + 2) -MIXERR_LASTERROR :: (MIXERR_BASE + 2) \ No newline at end of file +MIXERR_LASTERROR :: (MIXERR_BASE + 2) + +/* waveform output */ +MM_WOM_OPEN :: 0x3BB +MM_WOM_CLOSE :: 0x3BC +MM_WOM_DONE :: 0x3BD +/* waveform input */ +MM_WIM_OPEN :: 0x3BE +MM_WIM_CLOSE :: 0x3BF +MM_WIM_DATA :: 0x3C0 + +WOM_OPEN :: MM_WOM_OPEN +WOM_CLOSE :: MM_WOM_CLOSE +WOM_DONE :: MM_WOM_DONE +WIM_OPEN :: MM_WIM_OPEN +WIM_CLOSE :: MM_WIM_CLOSE +WIM_DATA :: MM_WIM_DATA + +WAVE_MAPPER : UINT : 0xFFFFFFFF // -1 + +WAVE_FORMAT_QUERY :: 0x0001 +WAVE_ALLOWSYNC :: 0x0002 +WAVE_MAPPED :: 0x0004 +WAVE_FORMAT_DIRECT :: 0x0008 +WAVE_FORMAT_DIRECT_QUERY :: (WAVE_FORMAT_QUERY | WAVE_FORMAT_DIRECT) +WAVE_MAPPED_DEFAULT_COMMUNICATION_DEVICE :: 0x0010 + +WHDR_DONE :: 0x00000001 /* done bit */ +WHDR_PREPARED :: 0x00000002 /* set if this header has been prepared */ +WHDR_BEGINLOOP :: 0x00000004 /* loop start block */ +WHDR_ENDLOOP :: 0x00000008 /* loop end block */ +WHDR_INQUEUE :: 0x00000010 /* reserved for driver */ + +WAVECAPS_PITCH :: 0x0001 /* supports pitch control */ +WAVECAPS_PLAYBACKRATE :: 0x0002 /* supports playback rate control */ +WAVECAPS_VOLUME :: 0x0004 /* supports volume control */ +WAVECAPS_LRVOLUME :: 0x0008 /* separate left-right volume control */ +WAVECAPS_SYNC :: 0x0010 +WAVECAPS_SAMPLEACCURATE :: 0x0020 + +WAVE_INVALIDFORMAT :: 0x00000000 /* invalid format */ +WAVE_FORMAT_1M08 :: 0x00000001 /* 11.025 kHz, Mono, 8-bit */ +WAVE_FORMAT_1S08 :: 0x00000002 /* 11.025 kHz, Stereo, 8-bit */ +WAVE_FORMAT_1M16 :: 0x00000004 /* 11.025 kHz, Mono, 16-bit */ +WAVE_FORMAT_1S16 :: 0x00000008 /* 11.025 kHz, Stereo, 16-bit */ +WAVE_FORMAT_2M08 :: 0x00000010 /* 22.05 kHz, Mono, 8-bit */ +WAVE_FORMAT_2S08 :: 0x00000020 /* 22.05 kHz, Stereo, 8-bit */ +WAVE_FORMAT_2M16 :: 0x00000040 /* 22.05 kHz, Mono, 16-bit */ +WAVE_FORMAT_2S16 :: 0x00000080 /* 22.05 kHz, Stereo, 16-bit */ +WAVE_FORMAT_4M08 :: 0x00000100 /* 44.1 kHz, Mono, 8-bit */ +WAVE_FORMAT_4S08 :: 0x00000200 /* 44.1 kHz, Stereo, 8-bit */ +WAVE_FORMAT_4M16 :: 0x00000400 /* 44.1 kHz, Mono, 16-bit */ +WAVE_FORMAT_4S16 :: 0x00000800 /* 44.1 kHz, Stereo, 16-bit */ +WAVE_FORMAT_44M08 :: 0x00000100 /* 44.1 kHz, Mono, 8-bit */ +WAVE_FORMAT_44S08 :: 0x00000200 /* 44.1 kHz, Stereo, 8-bit */ +WAVE_FORMAT_44M16 :: 0x00000400 /* 44.1 kHz, Mono, 16-bit */ +WAVE_FORMAT_44S16 :: 0x00000800 /* 44.1 kHz, Stereo, 16-bit */ +WAVE_FORMAT_48M08 :: 0x00001000 /* 48 kHz, Mono, 8-bit */ +WAVE_FORMAT_48S08 :: 0x00002000 /* 48 kHz, Stereo, 8-bit */ +WAVE_FORMAT_48M16 :: 0x00004000 /* 48 kHz, Mono, 16-bit */ +WAVE_FORMAT_48S16 :: 0x00008000 /* 48 kHz, Stereo, 16-bit */ +WAVE_FORMAT_96M08 :: 0x00010000 /* 96 kHz, Mono, 8-bit */ +WAVE_FORMAT_96S08 :: 0x00020000 /* 96 kHz, Stereo, 8-bit */ +WAVE_FORMAT_96M16 :: 0x00040000 /* 96 kHz, Mono, 16-bit */ +WAVE_FORMAT_96S16 :: 0x00080000 /* 96 kHz, Stereo, 16-bit */ + +HWAVE :: distinct HANDLE +HWAVEIN :: distinct HANDLE +HWAVEOUT :: distinct HANDLE + +LPHWAVEIN :: ^HWAVEIN +LPHWAVEOUT :: ^HWAVEOUT + +// https://learn.microsoft.com/en-us/windows/win32/multimedia/multimedia-timer-structures +MMTIME :: struct { + wType: UINT, + u: struct #raw_union { + ms: DWORD, + sample: DWORD, + cb: DWORD, + ticks: DWORD, + smpte: struct { + hour: BYTE, + min: BYTE, + sec: BYTE, + frame: BYTE, + fps: BYTE, + dummy: BYTE, + pad: [2]BYTE, + }, + midi: struct { + songptrpos: DWORD, + }, + }, +} +LPMMTIME :: ^MMTIME + +MAXPNAMELEN :: 32 +MAXERRORLENGTH :: 256 +MMVERSION :: UINT + +/* flags for wFormatTag field of WAVEFORMAT */ +WAVE_FORMAT_PCM :: 1 + +WAVEFORMATEX :: struct { + wFormatTag: WORD, + nChannels: WORD, + nSamplesPerSec: DWORD, + nAvgBytesPerSec: DWORD, + nBlockAlign: WORD, + wBitsPerSample: WORD, + cbSize: WORD, +} +LPCWAVEFORMATEX :: ^WAVEFORMATEX + +WAVEHDR :: struct { + lpData: LPSTR, /* pointer to locked data buffer */ + dwBufferLength: DWORD, /* length of data buffer */ + dwBytesRecorded: DWORD, /* used for input only */ + dwUser: DWORD_PTR, /* for client's use */ + dwFlags: DWORD, /* assorted flags (see defines) */ + dwLoops: DWORD, /* loop control counter */ + lpNext: LPWAVEHDR, /* reserved for driver */ + reserved: DWORD_PTR, /* reserved for driver */ +} +LPWAVEHDR :: ^WAVEHDR + +WAVEINCAPSW :: struct { + wMid: WORD, /* manufacturer ID */ + wPid: WORD, /* product ID */ + vDriverVersion: MMVERSION, /* version of the driver */ + szPname: [MAXPNAMELEN]WCHAR, /* product name (NULL terminated string) */ + dwFormats: DWORD, /* formats supported */ + wChannels: WORD, /* number of channels supported */ + wReserved1: WORD, /* structure packing */ +} +LPWAVEINCAPSW :: ^WAVEINCAPSW + +WAVEOUTCAPSW :: struct { + wMid: WORD, /* manufacturer ID */ + wPid: WORD, /* product ID */ + vDriverVersion: MMVERSION, /* version of the driver */ + szPname: [MAXPNAMELEN]WCHAR, /* product name (NULL terminated string) */ + dwFormats: DWORD, /* formats supported */ + wChannels: WORD, /* number of sources supported */ + wReserved1: WORD, /* packing */ + dwSupport: DWORD, /* functionality supported by driver */ +} +LPWAVEOUTCAPSW :: ^WAVEOUTCAPSW + +// 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_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_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 */ +CALLBACK_NULL :: 0x00000000 /* no callback */ +CALLBACK_WINDOW :: 0x00010000 /* dwCallback is a HWND */ +CALLBACK_TASK :: 0x00020000 /* dwCallback is a HTASK */ +CALLBACK_FUNCTION :: 0x00030000 /* dwCallback is a FARPROC */ +CALLBACK_THREAD :: CALLBACK_TASK /* thread ID replaces 16 bit task */ +CALLBACK_EVENT :: 0x00050000 /* dwCallback is an EVENT Handle */ diff --git a/src/types.cpp b/src/types.cpp index b442acd53..e9e91dcd4 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -932,6 +932,9 @@ gb_internal Type *core_type(Type *t) { case Type_Enum: t = t->Enum.base_type; continue; + case Type_BitField: + t = t->BitField.backing_type; + continue; } break; }