got it compiling again (still quite a bit todo)
This commit is contained in:
33
code2/grime/chrono.odin
Normal file
33
code2/grime/chrono.odin
Normal file
@@ -0,0 +1,33 @@
|
||||
package grime
|
||||
|
||||
Nanosecond_To_Microsecond :: 1.0 / (1000.0)
|
||||
Nanosecond_To_Millisecond :: 1.0 / (1000.0 * 1000.0)
|
||||
Nanosecond_To_Second :: 1.0 / (1000.0 * 1000.0 * 1000.0)
|
||||
|
||||
Microsecond_To_Nanosecond :: 1000.0
|
||||
Microsecond_To_Millisecond :: 1.0 / 1000.0
|
||||
Microsecond_To_Second :: 1.0 / (1000.0 * 1000.0)
|
||||
|
||||
Millisecond_To_Nanosecond :: 1000.0 * 1000.0
|
||||
Millisecond_To_Microsecond :: 1000.0
|
||||
Millisecond_To_Second :: 1.0 / 1000.0
|
||||
|
||||
Second_To_Nanosecond :: 1000.0 * 1000.0 * 1000.0
|
||||
Second_To_Microsecnd :: 1000.0 * 1000.0
|
||||
Second_To_Millisecond :: 1000.0
|
||||
|
||||
NS_To_MS :: Nanosecond_To_Millisecond
|
||||
NS_To_US :: Nanosecond_To_Microsecond
|
||||
NS_To_S :: Nanosecond_To_Second
|
||||
|
||||
US_To_NS :: Microsecond_To_Nanosecond
|
||||
US_To_MS :: Microsecond_To_Millisecond
|
||||
US_To_S :: Microsecond_To_Second
|
||||
|
||||
MS_To_NS :: Millisecond_To_Nanosecond
|
||||
MS_To_US :: Millisecond_To_Microsecond
|
||||
MS_To_S :: Millisecond_To_Second
|
||||
|
||||
S_To_NS :: Second_To_Nanosecond
|
||||
S_To_US :: Second_To_Microsecnd
|
||||
S_To_MS :: Second_To_Millisecond
|
63
code2/grime/dynamic_array.odin
Normal file
63
code2/grime/dynamic_array.odin
Normal file
@@ -0,0 +1,63 @@
|
||||
package grime
|
||||
|
||||
/*
|
||||
Based on gencpp's and thus zpl's Array implementation
|
||||
Made becasue of the map issue with fonts during hot-reload.
|
||||
I didn't want to make the HMapZPL impl with the [dynamic] array for now to isolate the hot-reload issue (when I was diagnoising)
|
||||
|
||||
Update 2024-5-26:
|
||||
TODO(Ed): Raw_Dynamic_Array is defined within base:runtime/core.odin and exposes what we need for worst case hot-reloads.
|
||||
So its best to go back to regular dynamic arrays at some point.
|
||||
|
||||
Update 2025-5-12:
|
||||
I can use either... so I'll just keep both
|
||||
*/
|
||||
|
||||
ArrayHeader :: struct ( $ Type : typeid ) {
|
||||
backing : Odin_Allocator,
|
||||
dbg_name : string,
|
||||
fixed_cap : b32,
|
||||
capacity : int,
|
||||
num : int,
|
||||
data : [^]Type,
|
||||
}
|
||||
|
||||
Array :: struct ( $ Type : typeid ) {
|
||||
using header : ^ArrayHeader(Type),
|
||||
}
|
||||
|
||||
array_underlying_slice :: proc(s: []($ Type)) -> Array(Type) {
|
||||
assert(len(slice) != 0)
|
||||
header_size :: size_of( ArrayHeader(Type))
|
||||
array := cursor(to_bytes(s))[ - header_size]
|
||||
return
|
||||
}
|
||||
|
||||
array_to_slice :: #force_inline proc "contextless" ( using self : Array($ Type) ) -> []Type { return slice( data, int(num)) }
|
||||
array_to_slice_capacity :: #force_inline proc "contextless" ( using self : Array($ Type) ) -> []Type { return slice( data, int(capacity)) }
|
||||
|
||||
array_grow_formula :: proc( value : u64 ) -> u64 {
|
||||
result := (2 * value) + 8
|
||||
return result
|
||||
}
|
||||
|
||||
array_init :: proc( $Array_Type : typeid/Array($Type), capacity : u64,
|
||||
allocator := context.allocator, fixed_cap : b32 = false, dbg_name : string = ""
|
||||
) -> ( result : Array(Type), alloc_error : AllocatorError )
|
||||
{
|
||||
header_size := size_of(ArrayHeader(Type))
|
||||
array_size := header_size + int(capacity) * size_of(Type)
|
||||
|
||||
raw_mem : rawptr
|
||||
raw_mem, alloc_error = alloc( array_size, allocator = allocator )
|
||||
// log( str_fmt_tmp("array reserved: %d", header_size + int(capacity) * size_of(Type) ))
|
||||
if alloc_error != AllocatorError.None do return
|
||||
|
||||
result.header = cast( ^ArrayHeader(Type)) raw_mem
|
||||
result.backing = allocator
|
||||
result.dbg_name = dbg_name
|
||||
result.fixed_cap = fixed_cap
|
||||
result.capacity = capacity
|
||||
result.data = cast( [^]Type ) (cast( [^]ArrayHeader(Type)) result.header)[ 1:]
|
||||
return
|
||||
}
|
@@ -38,7 +38,6 @@ KT1CX_ByteMeta :: struct {
|
||||
type: typeid,
|
||||
}
|
||||
KT1CX_InfoMeta :: struct {
|
||||
cell_pool_size: int,
|
||||
table_size: int,
|
||||
slot_size: int,
|
||||
slot_key_offset: uintptr,
|
||||
@@ -50,14 +49,11 @@ KT1CX_InfoMeta :: struct {
|
||||
}
|
||||
KT1CX_Info :: struct {
|
||||
backing_table: AllocatorInfo,
|
||||
backing_cells: AllocatorInfo,
|
||||
}
|
||||
kt1cx_init :: proc(info: KT1CX_Info, m: KT1CX_InfoMeta, result: ^KT1CX_Byte) {
|
||||
assert(result != nil)
|
||||
assert(info.backing_cells.procedure != nil)
|
||||
assert(info.backing_table.procedure != nil)
|
||||
assert(m.cell_depth > 0)
|
||||
assert(m.cell_pool_size >= 4 * Kilo)
|
||||
assert(m.table_size >= 4 * Kilo)
|
||||
assert(m.type_width > 0)
|
||||
table_raw := transmute(SliceByte) mem_alloc(m.table_size * m.cell_size, ainfo = odin_allocator(info.backing_table))
|
||||
@@ -75,7 +71,7 @@ kt1cx_clear :: proc(kt: KT1CX_Byte, m: KT1CX_ByteMeta) {
|
||||
for;; {
|
||||
slot := slice(slot_cursor, m.slot_size) // slot = slots[slot_id]
|
||||
zero(slot) // slot = {}
|
||||
if slot_cursor == end(transmute([]byte) slots) { // if slot == end(slot)
|
||||
if slot_cursor == end(slots) { // if slot == end(slot)
|
||||
next := slot_cursor[m.cell_next_offset:] // next = kt.table.cells[cell_id + 1]
|
||||
if next != nil { // if next != nil
|
||||
slots.data = next // slots = next.slots
|
||||
@@ -105,7 +101,7 @@ kt1cx_get :: proc(kt: KT1CX_Byte, key: u64, m: KT1CX_ByteMeta) -> ^byte {
|
||||
if slot.occupied && slot.key == key {
|
||||
return cast(^byte) slot_cursor
|
||||
}
|
||||
if slot_cursor == end(transmute([]byte) slots)
|
||||
if slot_cursor == end(slots)
|
||||
{
|
||||
cell_next := cell_cursor[m.cell_next_offset:] // cell.next
|
||||
if cell_next != nil {
|
||||
@@ -140,7 +136,7 @@ kt1cx_set :: proc(kt: KT1CX_Byte, key: u64, value: []byte, backing_cells: Alloca
|
||||
else if slot.key == key {
|
||||
return cast(^byte) slot_cursor
|
||||
}
|
||||
if slot_cursor == end(transmute([]byte) slots) {
|
||||
if slot_cursor == end(slots) {
|
||||
curr_cell := transmute(^KT1CX_Byte_Cell) (uintptr(cell_cursor) + m.cell_next_offset) // curr_cell = cell
|
||||
if curr_cell != nil {
|
||||
slots.data = curr_cell.next
|
||||
@@ -163,7 +159,6 @@ kt1cx_set :: proc(kt: KT1CX_Byte, key: u64, value: []byte, backing_cells: Alloca
|
||||
}
|
||||
}
|
||||
kt1cx_assert :: proc(kt: $type / KT1CX) {
|
||||
slice_assert(kt.cell_pool)
|
||||
slice_assert(kt.table)
|
||||
}
|
||||
kt1cx_byte :: proc(kt: $type / KT1CX) -> KT1CX_Byte { return { to_bytes(kt.cell_pool), slice( transmute([^]byte) cursor(kt.table), len(kt.table)) } }
|
||||
kt1cx_byte :: proc(kt: $type / KT1CX) -> KT1CX_Byte { return { slice( transmute([^]byte) cursor(kt.table), len(kt.table)) } }
|
||||
|
@@ -27,7 +27,8 @@ slice_assert :: #force_inline proc (s: $SliceType / []$Type) {
|
||||
assert(len(s) > 0)
|
||||
assert(s != nil)
|
||||
}
|
||||
slice_end :: #force_inline proc "contextless" (s : $SliceType / []$Type) -> ^Type { return & cursor(s)[len(s)] }
|
||||
slice_end :: #force_inline proc "contextless" (s : $SliceType / []$Type) -> ^Type { return cursor(s)[len(s):] }
|
||||
slice_byte_end :: #force_inline proc "contextless" (s : SliceByte) -> ^byte { return s.data[s.len:] }
|
||||
|
||||
slice_copy :: #force_inline proc "contextless" (dst, src: $SliceType / []$Type) -> int {
|
||||
n := max(0, min(len(dst), len(src)))
|
||||
@@ -37,8 +38,8 @@ slice_copy :: #force_inline proc "contextless" (dst, src: $SliceType / []$Type)
|
||||
return n
|
||||
}
|
||||
|
||||
@(require_results) slice_to_bytes :: #force_inline proc "contextless" (s: []$Type) -> []byte { return ([^]byte)(raw_data(s))[:len(s) * size_of(Type)] }
|
||||
@(require_results) slice_raw :: #force_inline proc "contextless" (s: []$Type) -> SliceRaw(Type) { return transmute(SliceRaw(Type)) s }
|
||||
@(require_results) slice_to_bytes :: #force_inline proc "contextless" (s: []$Type) -> []byte { return ([^]byte)(raw_data(s))[:len(s) * size_of(Type)] }
|
||||
@(require_results) slice_raw :: #force_inline proc "contextless" (s: []$Type) -> SliceRaw(Type) { return transmute(SliceRaw(Type)) s }
|
||||
|
||||
//region Memory Math
|
||||
|
||||
|
@@ -51,6 +51,9 @@ import "core:mem"
|
||||
|
||||
align_pow2 :: mem.align_forward_int
|
||||
|
||||
import "core:mem/virtual"
|
||||
VirtualProtectFlags :: virtual.Protect_Flags
|
||||
|
||||
import core_os "core:os"
|
||||
FS_Open_Readonly :: core_os.O_RDONLY
|
||||
FS_Open_Writeonly :: core_os.O_WRONLY
|
||||
@@ -102,6 +105,7 @@ cursor :: proc {
|
||||
|
||||
end :: proc {
|
||||
slice_end,
|
||||
slice_byte_end,
|
||||
string_end,
|
||||
}
|
||||
|
||||
|
@@ -18,16 +18,16 @@ thread__highres_wait :: proc( desired_ms : f64, loc := #caller_location ) -> b32
|
||||
|
||||
timer := win32.CreateWaitableTimerExW( nil, nil, win32.CREATE_WAITABLE_TIMER_HIGH_RESOLUTION, win32.TIMER_ALL_ACCESS )
|
||||
if timer == nil {
|
||||
msg := str_fmt("Failed to create win32 timer - ErrorCode: %v", win32.GetLastError() )
|
||||
log( msg, LogLevel.Warning, loc)
|
||||
msg := str_pfmt("Failed to create win32 timer - ErrorCode: %v", win32.GetLastError() )
|
||||
log( msg, LoggerLevel.Warning, loc)
|
||||
return false
|
||||
}
|
||||
|
||||
due_time := win32.LARGE_INTEGER(desired_ms * MS_To_NS)
|
||||
result := win32.SetWaitableTimerEx( timer, & due_time, 0, nil, nil, nil, 0 )
|
||||
if ! result {
|
||||
msg := str_fmt("Failed to set win32 timer - ErrorCode: %v", win32.GetLastError() )
|
||||
log( msg, LogLevel.Warning, loc)
|
||||
msg := str_pfmt("Failed to set win32 timer - ErrorCode: %v", win32.GetLastError() )
|
||||
log( msg, LoggerLevel.Warning, loc)
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -41,23 +41,23 @@ thread__highres_wait :: proc( desired_ms : f64, loc := #caller_location ) -> b32
|
||||
switch wait_result
|
||||
{
|
||||
case WAIT_ABANDONED:
|
||||
msg := str_fmt("Failed to wait for win32 timer - Error: WAIT_ABANDONED" )
|
||||
log( msg, LogLevel.Error, loc)
|
||||
msg := str_pfmt("Failed to wait for win32 timer - Error: WAIT_ABANDONED" )
|
||||
log( msg, LoggerLevel.Error, loc)
|
||||
return false
|
||||
|
||||
case WAIT_IO_COMPLETION:
|
||||
msg := str_fmt("Waited for win32 timer: Ended by APC queued to the thread" )
|
||||
log( msg, LogLevel.Error, loc)
|
||||
msg := str_pfmt("Waited for win32 timer: Ended by APC queued to the thread" )
|
||||
log( msg, LoggerLevel.Error, loc)
|
||||
return false
|
||||
|
||||
case WAIT_OBJECT_0:
|
||||
msg := str_fmt("Waited for win32 timer- Reason : WAIT_OBJECT_0" )
|
||||
msg := str_pfmt("Waited for win32 timer- Reason : WAIT_OBJECT_0" )
|
||||
log( msg, loc = loc)
|
||||
return false
|
||||
|
||||
case WAIT_FAILED:
|
||||
msg := str_fmt("Waited for win32 timer failed - ErrorCode: $v", win32.GetLastError() )
|
||||
log( msg, LogLevel.Error, loc)
|
||||
msg := str_pfmt("Waited for win32 timer failed - ErrorCode: $v", win32.GetLastError() )
|
||||
log( msg, LoggerLevel.Error, loc)
|
||||
return false
|
||||
}
|
||||
|
||||
|
@@ -2,6 +2,7 @@ package grime
|
||||
|
||||
rune16 :: distinct u16
|
||||
|
||||
when false {
|
||||
// Exposing the alloc_error
|
||||
@(require_results)
|
||||
string_to_runes :: proc ( content : string, allocator := context.allocator) -> (runes : []rune, alloc_error: Odin_AllocatorError) #optional_allocator_error {
|
||||
@@ -36,3 +37,5 @@ string_to_runes_array :: proc( content : string, allocator := context.allocator
|
||||
}
|
||||
return runes, alloc_error
|
||||
}
|
||||
|
||||
}
|
@@ -95,7 +95,7 @@ virtual_release :: proc "contextless" ( vmem : VirtualMemoryRegion ) {
|
||||
}
|
||||
|
||||
// If the OS is not windows, we just use the library's interface which does not support base_address.
|
||||
when ODIN_OS != OS_Type.Windows {
|
||||
when ODIN_OS != .Windows {
|
||||
|
||||
virtual_resreve__platform_impl :: proc "contextless" ( base_address : uintptr, size : uint ) -> ( vmem : VirtualMemoryRegion, alloc_error : AllocatorError )
|
||||
{
|
||||
|
Reference in New Issue
Block a user