aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeroen van Rijn <Kelimion@users.noreply.github.com>2026-02-02 13:22:38 +0100
committerGitHub <noreply@github.com>2026-02-02 13:22:38 +0100
commit13f26f4645b8b0bb6d2848daa5721300dc7b2e60 (patch)
tree2c084158d207285972878fe564f2cdc32ac9ff15
parent80c948277455eb9deaf79ac910fdc8957038fb75 (diff)
parent98413ad15450ac871c1181d656a1afd717d482bb (diff)
Merge pull request #6218 from Kelimion/fix-6204
Fix #6204
-rw-r--r--core/sys/info/platform_bsd.odin3
-rw-r--r--core/sys/info/platform_darwin.odin3
-rw-r--r--core/sys/info/platform_freebsd.odin3
-rw-r--r--core/sys/info/platform_linux.odin3
-rw-r--r--core/sys/info/platform_windows.odin152
-rw-r--r--core/sys/info/sysinfo.odin29
-rw-r--r--core/unicode/utf16/utf16.odin22
7 files changed, 118 insertions, 97 deletions
diff --git a/core/sys/info/platform_bsd.odin b/core/sys/info/platform_bsd.odin
index 2f8d7f5bb..349b74002 100644
--- a/core/sys/info/platform_bsd.odin
+++ b/core/sys/info/platform_bsd.odin
@@ -6,9 +6,6 @@ import "core:strings"
import "core:strconv"
import "base:runtime"
-@(private)
-version_string_buf: [1024]u8
-
@(init, private)
init_os_version :: proc "contextless" () {
context = runtime.default_context()
diff --git a/core/sys/info/platform_darwin.odin b/core/sys/info/platform_darwin.odin
index 07c26ec28..498c21846 100644
--- a/core/sys/info/platform_darwin.odin
+++ b/core/sys/info/platform_darwin.odin
@@ -7,9 +7,6 @@ import "core:strings"
import "core:sys/unix"
import NS "core:sys/darwin/Foundation"
-@(private)
-version_string_buf: [1024]u8
-
@(init, private)
init_platform :: proc "contextless" () {
context = runtime.default_context()
diff --git a/core/sys/info/platform_freebsd.odin b/core/sys/info/platform_freebsd.odin
index eb39769de..ed5db6243 100644
--- a/core/sys/info/platform_freebsd.odin
+++ b/core/sys/info/platform_freebsd.odin
@@ -5,9 +5,6 @@ import "core:strings"
import "core:strconv"
import "base:runtime"
-@(private)
-version_string_buf: [1024]u8
-
@(init, private)
init_os_version :: proc "contextless" () {
context = runtime.default_context()
diff --git a/core/sys/info/platform_linux.odin b/core/sys/info/platform_linux.odin
index 43cd580c1..671600640 100644
--- a/core/sys/info/platform_linux.odin
+++ b/core/sys/info/platform_linux.odin
@@ -7,9 +7,6 @@ import "core:strconv"
import "core:strings"
import "core:sys/linux"
-@(private)
-version_string_buf: [1024]u8
-
@(init, private)
init_os_version :: proc "contextless" () {
context = runtime.default_context()
diff --git a/core/sys/info/platform_windows.odin b/core/sys/info/platform_windows.odin
index bad99f811..c28170919 100644
--- a/core/sys/info/platform_windows.odin
+++ b/core/sys/info/platform_windows.odin
@@ -3,17 +3,12 @@ package sysinfo
import sys "core:sys/windows"
import "base:intrinsics"
import "core:strings"
-import "core:strconv"
import "core:unicode/utf16"
-
-// import "core:fmt"
import "base:runtime"
-@(private)
-version_string_buf: [1024]u8
-
@(init, private)
init_os_version :: proc "contextless" () {
+ // NOTE(Jeroen): Only needed for the string builder.
context = runtime.default_context()
/*
@@ -226,14 +221,14 @@ init_os_version :: proc "contextless" () {
// Grab Windows DisplayVersion (like 20H02)
format_display_version :: proc (b: ^strings.Builder) -> (version: string) {
- dv, ok := read_reg_string(
+ scratch: [512]u8
+
+ if dv, ok := read_reg_string(
sys.HKEY_LOCAL_MACHINE,
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
"DisplayVersion",
- )
- defer delete(dv) // It'll be interned into `version_string_buf`
-
- if ok {
+ scratch[:],
+ ); ok {
strings.write_string(b, " (version: ")
l := strings.builder_len(b^)
strings.write_string(b, dv)
@@ -245,13 +240,11 @@ init_os_version :: proc "contextless" () {
// Grab build number and UBR
format_build_number :: proc (b: ^strings.Builder, major_build: int) -> (ubr: int) {
- res, ok := read_reg_i32(
+ if res, ok := read_reg_i32(
sys.HKEY_LOCAL_MACHINE,
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
"UBR",
- )
-
- if ok {
+ ); ok {
ubr = int(res)
strings.write_string(b, ", build: ")
strings.write_int(b, major_build)
@@ -283,9 +276,6 @@ init_ram :: proc "contextless" () {
init_gpu_info :: proc "contextless" () {
GPU_ROOT_KEY :: `SYSTEM\ControlSet001\Control\Class\{4d36e968-e325-11ce-bfc1-08002be10318}`
- context = runtime.default_context()
- runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
-
gpu_key: sys.HKEY
if status := sys.RegOpenKeyExW(
sys.HKEY_LOCAL_MACHINE,
@@ -298,16 +288,18 @@ init_gpu_info :: proc "contextless" () {
}
defer sys.RegCloseKey(gpu_key)
- gpu_list: [dynamic]GPU
gpu: ^GPU
+ gpu_count := 0
index := sys.DWORD(0)
- for {
+ gpu_loop: for {
defer index += 1
buf_wstring: [100]u16
buf_len := u32(len(buf_wstring))
- buf_utf8: [4 * len(buf_wstring)]u8
+ buf_key: [4 * len(buf_wstring)]u8
+ buf_leaf: [100]u8
+ buf_scratch: [100]u8
if status := sys.RegEnumKeyW(
gpu_key,
@@ -318,59 +310,71 @@ init_gpu_info :: proc "contextless" () {
break
}
- utf16.decode_to_utf8(buf_utf8[:], buf_wstring[:])
- leaf := string(cstring(&buf_utf8[0]))
+ utf16.decode_to_utf8(buf_leaf[:], buf_wstring[:])
+ leaf := string(cstring(&buf_leaf[0]))
// Skip leafs that are not of the form 000x
- if _, is_integer := strconv.parse_int(leaf, 10); !is_integer {
+ if !is_integer(leaf) {
continue
}
- key := strings.concatenate({GPU_ROOT_KEY, "\\", leaf}, context.temp_allocator)
+ n := copy(buf_key[:], GPU_ROOT_KEY)
+ buf_key[n] = '\\'
+ copy(buf_key[n+1:], leaf)
+
+ key_len := len(GPU_ROOT_KEY) + len(leaf) + 1
- if vendor, ok := read_reg_string(sys.HKEY_LOCAL_MACHINE, key, "ProviderName"); ok {
- idx := append(&gpu_list, GPU{vendor_name = vendor})
- gpu = &gpu_list[idx - 1]
+ utf16.encode_string(buf_wstring[:], string(buf_key[:key_len]))
+ key := cstring16(&buf_wstring[0])
+
+ if res, ok := read_reg_string(sys.HKEY_LOCAL_MACHINE, key, "ProviderName", buf_scratch[:]); ok {
+ if vendor, s_ok := intern_gpu_string(res); s_ok {
+ gpu = &_gpus[gpu_count]
+ gpu.vendor_name = vendor
+ } else {
+ break gpu_loop
+ }
} else {
continue
}
- if desc, ok := read_reg_string(sys.HKEY_LOCAL_MACHINE, key, "DriverDesc"); ok {
- gpu.model_name = desc
+ if res, ok := read_reg_string(sys.HKEY_LOCAL_MACHINE, key, "DriverDesc", buf_scratch[:]); ok {
+ if model_name, s_ok := intern_gpu_string(res); s_ok {
+ gpu = &_gpus[gpu_count]
+ gpu.model_name = model_name
+ } else {
+ break gpu_loop
+ }
}
if vram, ok := read_reg_i64(sys.HKEY_LOCAL_MACHINE, key, "HardwareInformation.qwMemorySize"); ok {
gpu.total_ram = int(vram)
}
+
+ gpu_count += 1
+ if gpu_count > MAX_GPUS {
+ break gpu_loop
+ }
}
- gpus = gpu_list[:]
+ gpus = _gpus[:gpu_count]
}
@(private)
-read_reg_string :: proc(hkey: sys.HKEY, subkey, val: string) -> (res: string, ok: bool) {
+read_reg_string :: proc "contextless" (hkey: sys.HKEY, subkey, val: cstring16, res_buf: []u8) -> (res: string, ok: bool) {
if len(subkey) == 0 || len(val) == 0 {
return
}
- runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
-
- BUF_SIZE :: 1024
- key_name_wide := make([]u16, BUF_SIZE, context.temp_allocator)
- val_name_wide := make([]u16, BUF_SIZE, context.temp_allocator)
-
- utf16.encode_string(key_name_wide, subkey)
- utf16.encode_string(val_name_wide, val)
-
- result_wide := make([]u16, BUF_SIZE, context.temp_allocator)
- result_size := sys.DWORD(BUF_SIZE * size_of(u16))
+ buf_utf16: [1024]u16
+ result_size := sys.DWORD(size_of(buf_utf16))
status := sys.RegGetValueW(
hkey,
- cstring16(&key_name_wide[0]),
- cstring16(&val_name_wide[0]),
+ subkey,
+ val,
sys.RRF_RT_REG_SZ,
nil,
- raw_data(result_wide[:]),
+ raw_data(buf_utf16[:]),
&result_size,
)
if status != 0 {
@@ -378,31 +382,22 @@ read_reg_string :: proc(hkey: sys.HKEY, subkey, val: string) -> (res: string, ok
return
}
- // Result string will be allocated for the caller.
- result_utf8 := make([]u8, BUF_SIZE * 4, context.temp_allocator)
- utf16.decode_to_utf8(result_utf8, result_wide[:result_size])
- return strings.clone_from_cstring(cstring(raw_data(result_utf8))), true
+ utf16.decode_to_utf8(res_buf[:result_size], buf_utf16[:])
+ res = string(cstring(&res_buf[0]))
+ return res, true
}
+
@(private)
-read_reg_i32 :: proc(hkey: sys.HKEY, subkey, val: string) -> (res: i32, ok: bool) {
+read_reg_i32 :: proc "contextless" (hkey: sys.HKEY, subkey, val: cstring16) -> (res: i32, ok: bool) {
if len(subkey) == 0 || len(val) == 0 {
return
}
- runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
-
- BUF_SIZE :: 1024
- key_name_wide := make([]u16, BUF_SIZE, context.temp_allocator)
- val_name_wide := make([]u16, BUF_SIZE, context.temp_allocator)
-
- utf16.encode_string(key_name_wide, subkey)
- utf16.encode_string(val_name_wide, val)
-
result_size := sys.DWORD(size_of(i32))
status := sys.RegGetValueW(
hkey,
- cstring16(&key_name_wide[0]),
- cstring16(&val_name_wide[0]),
+ subkey,
+ val,
sys.RRF_RT_REG_DWORD,
nil,
&res,
@@ -410,26 +405,18 @@ read_reg_i32 :: proc(hkey: sys.HKEY, subkey, val: string) -> (res: i32, ok: bool
)
return res, status == 0
}
+
@(private)
-read_reg_i64 :: proc(hkey: sys.HKEY, subkey, val: string) -> (res: i64, ok: bool) {
+read_reg_i64 :: proc "contextless" (hkey: sys.HKEY, subkey, val: cstring16) -> (res: i64, ok: bool) {
if len(subkey) == 0 || len(val) == 0 {
return
}
- runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
-
- BUF_SIZE :: 1024
- key_name_wide := make([]u16, BUF_SIZE, context.temp_allocator)
- val_name_wide := make([]u16, BUF_SIZE, context.temp_allocator)
-
- utf16.encode_string(key_name_wide, subkey)
- utf16.encode_string(val_name_wide, val)
-
result_size := sys.DWORD(size_of(i64))
status := sys.RegGetValueW(
hkey,
- cstring16(&key_name_wide[0]),
- cstring16(&val_name_wide[0]),
+ subkey,
+ val,
sys.RRF_RT_REG_QWORD,
nil,
&res,
@@ -437,3 +424,20 @@ read_reg_i64 :: proc(hkey: sys.HKEY, subkey, val: string) -> (res: i64, ok: bool
)
return res, status == 0
}
+
+@(private)
+is_integer :: proc "contextless" (s: string) -> (ok: bool) {
+ if s == "" {
+ return
+ }
+
+ ok = true
+
+ for r in s {
+ switch r {
+ case '0'..='9': continue
+ case: return false
+ }
+ }
+ return
+} \ No newline at end of file
diff --git a/core/sys/info/sysinfo.odin b/core/sys/info/sysinfo.odin
index 75cc237c6..07f8f0c81 100644
--- a/core/sys/info/sysinfo.odin
+++ b/core/sys/info/sysinfo.odin
@@ -48,3 +48,32 @@ GPU :: struct {
model_name: string,
total_ram: int,
}
+
+@(private)
+version_string_buf: [1024]u8
+
+@(private)
+MAX_GPUS :: 16
+
+@(private)
+_gpus: [MAX_GPUS]GPU
+
+@(private)
+_gpu_string_buf: [MAX_GPUS * 256 * 2]u8 // Reserve up to 256 bytes for each GPU's vendor and model name
+
+@(private)
+_gpu_string_offset: int
+
+@(private)
+intern_gpu_string :: proc "contextless" (str: string) -> (res: string, ok: bool) {
+ if _gpu_string_offset + len(str) + 1 > size_of(_gpu_string_buf) {
+ return "", false
+ }
+
+ n := copy(_gpu_string_buf[_gpu_string_offset:], str)
+ _gpu_string_buf[_gpu_string_offset + len(str)] = 0
+ res = string(_gpu_string_buf[_gpu_string_offset:][:len(str)])
+ _gpu_string_offset += n + 1
+
+ return res, true
+} \ No newline at end of file
diff --git a/core/unicode/utf16/utf16.odin b/core/unicode/utf16/utf16.odin
index 990d5bafa..5cc996f8b 100644
--- a/core/unicode/utf16/utf16.odin
+++ b/core/unicode/utf16/utf16.odin
@@ -12,11 +12,11 @@ _surr3 :: 0xe000
_surr_self :: 0x10000
-is_surrogate :: proc(r: rune) -> bool {
+is_surrogate :: proc "contextless" (r: rune) -> bool {
return _surr1 <= r && r < _surr3
}
-decode_surrogate_pair :: proc(r1, r2: rune) -> rune {
+decode_surrogate_pair :: proc "contextless" (r1, r2: rune) -> rune {
if _surr1 <= r1 && r1 < _surr2 && _surr2 <= r2 && r2 < _surr3 {
return (r1-_surr1)<<10 | (r2 - _surr2) + _surr_self
}
@@ -24,7 +24,7 @@ decode_surrogate_pair :: proc(r1, r2: rune) -> rune {
}
-encode_surrogate_pair :: proc(c: rune) -> (r1, r2: rune) {
+encode_surrogate_pair :: proc "contextless" (c: rune) -> (r1, r2: rune) {
r := c
if r < _surr_self || r > MAX_RUNE {
return REPLACEMENT_CHAR, REPLACEMENT_CHAR
@@ -33,7 +33,7 @@ encode_surrogate_pair :: proc(c: rune) -> (r1, r2: rune) {
return _surr1 + (r>>10)&0x3ff, _surr2 + r&0x3ff
}
-encode :: proc(d: []u16, s: []rune) -> int {
+encode :: proc "contextless" (d: []u16, s: []rune) -> int {
n, m := 0, len(d)
loop: for r in s {
switch r {
@@ -59,7 +59,7 @@ encode :: proc(d: []u16, s: []rune) -> int {
}
-encode_string :: proc(d: []u16, s: string) -> int {
+encode_string :: proc "contextless" (d: []u16, s: string) -> int {
n, m := 0, len(d)
loop: for r in s {
switch r {
@@ -84,7 +84,7 @@ encode_string :: proc(d: []u16, s: string) -> int {
return n
}
-decode :: proc(d: []rune, s: []u16) -> (n: int) {
+decode :: proc "contextless" (d: []rune, s: []u16) -> (n: int) {
for i := 0; i < len(s); i += 1 {
if n >= len(d) {
return
@@ -107,7 +107,7 @@ decode :: proc(d: []rune, s: []u16) -> (n: int) {
return
}
-decode_rune_in_string :: proc(s: string16) -> (r: rune, width: int) {
+decode_rune_in_string :: proc "contextless" (s: string16) -> (r: rune, width: int) {
r = rune(REPLACEMENT_CHAR)
n := len(s)
if n < 1 {
@@ -144,7 +144,7 @@ rune_count :: proc{
rune_count_in_string,
rune_count_in_slice,
}
-rune_count_in_string :: proc(s: string16) -> (n: int) {
+rune_count_in_string :: proc "contextless" (s: string16) -> (n: int) {
for i := 0; i < len(s); i += 1 {
c := s[i]
if _surr1 <= c && c < _surr2 && i+1 < len(s) &&
@@ -157,7 +157,7 @@ rune_count_in_string :: proc(s: string16) -> (n: int) {
}
-rune_count_in_slice :: proc(s: []u16) -> (n: int) {
+rune_count_in_slice :: proc "contextless" (s: []u16) -> (n: int) {
for i := 0; i < len(s); i += 1 {
c := s[i]
if _surr1 <= c && c < _surr2 && i+1 < len(s) &&
@@ -170,7 +170,7 @@ rune_count_in_slice :: proc(s: []u16) -> (n: int) {
}
-decode_to_utf8 :: proc(d: []byte, s: []u16) -> (n: int) {
+decode_to_utf8 :: proc "contextless" (d: []byte, s: []u16) -> (n: int) {
for i := 0; i < len(s); i += 1 {
if n >= len(d) {
return
@@ -190,4 +190,4 @@ decode_to_utf8 :: proc(d: []byte, s: []u16) -> (n: int) {
n += copy(d[n:], b[:w])
}
return
-}
+} \ No newline at end of file