Ooga'd some boogas

This commit is contained in:
Charlie 2024-07-02 19:12:31 +02:00
parent b15c7c6e41
commit 1f2809d23e
12 changed files with 124 additions and 22 deletions

12
build.c
View file

@ -2,6 +2,7 @@
///
// Build config stuff
#define RUN_TESTS 0
// This is only for people developing oogabooga!
@ -9,6 +10,8 @@
#define ENABLE_PROFILING 0
#define INITIAL_PROGRAM_MEMORY_SIZE MB(5)
// When we need very debug
// #define CONFIGURATION VERY_DEBUG
@ -20,12 +23,15 @@ typedef struct Context_Extra {
#define GFX_RENDERER GFX_RENDERER_D3D11
// This defaults to "entry", but we can set it to anything (except "main" or other existing proc names"
#define ENTRY_PROC entry
#include "oogabooga/oogabooga.c"
//
// Comment & Uncomment to swap projects
// #include "entry_engine_test.c"
// #include "entry_minimal_example.c"
#include "entry_randygame.c"
// #include "oogabooga/examples/renderer_stress_test.c"
// #include "oogabooga/examples/minimal_game_loop.c"
#include "entry_randygame.c"

View file

@ -11,6 +11,7 @@ int entry(int argc, char **argv) {
Gfx_Image* player = load_image_from_disk(STR("player.png"), get_heap_allocator());
assert(player, "fuckie wucky happen");
Vector2 player_pos = v2(0, 0);
float64 seconds_counter = 0.0;
s32 frame_count = 0;

View file

@ -196,7 +196,15 @@ thread_local u64 num_contexts = 0;
forward_global thread_local Allocator temp;
void* memset(void* dest, int value, size_t amount);
void* alloc(Allocator allocator, u64 size) {
void *p = allocator.proc(size, 0, ALLOCATOR_ALLOCATE, allocator.data);
#if DO_ZERO_INITIALIZATION
memset(p, 0, size);
#endif
return p;
}
void* alloc_uninitialized(Allocator allocator, u64 size) {
return allocator.proc(size, 0, ALLOCATOR_ALLOCATE, allocator.data);
}
void dealloc(Allocator allocator, void *p) {

View file

Before

Width:  |  Height:  |  Size: 556 B

After

Width:  |  Height:  |  Size: 556 B

View file

Before

Width:  |  Height:  |  Size: 287 B

After

Width:  |  Height:  |  Size: 287 B

View file

@ -10,9 +10,9 @@ int entry(int argc, char **argv) {
window.clear_color = hex_to_rgba(0x2a2d3aff);
Gfx_Image *bush_image = load_image_from_disk(STR("berry_bush.png"), get_heap_allocator());
Gfx_Image *bush_image = load_image_from_disk(STR("oogabooga/examples/berry_bush.png"), get_heap_allocator());
assert(bush_image, "Failed loading berry_bush.png");
Gfx_Image *hammer_image = load_image_from_disk(STR("hammer.png"), get_heap_allocator());
Gfx_Image *hammer_image = load_image_from_disk(STR("oogabooga/examples/hammer.png"), get_heap_allocator());
assert(hammer_image, "Failed loading hammer.png");
seed_for_random = os_get_current_cycle_count();
@ -50,7 +50,7 @@ int entry(int argc, char **argv) {
if (is_key_just_released('Q')) {
delete_image(bush_image);
bush_image = load_image_from_disk(STR("berry_bush.png"), get_heap_allocator());
bush_image = load_image_from_disk(STR("oogabooga/examples/berry_bush.png"), get_heap_allocator());
assert(bush_image, "Failed loading berry_bush.png");
}

View file

@ -1,11 +1,15 @@
#define KB(x) (x*1024ull)
#define MB(x) ((KB(x))*1024ull)
#define GB(x) ((MB(x))*1024ull)
void* program_memory = 0;
u64 program_memory_size = 0;
#ifndef INIT_MEMORY_SIZE
#define INIT_MEMORY_SIZE (1024*50)
#define INIT_MEMORY_SIZE KB(50)
#endif
// We may need to allocate stuff in initialization time before the heap is ready.
// That's what this is for.
@ -50,7 +54,8 @@ Allocator get_initialization_allocator() {
// We could fix it by merging free nodes every now and then
// BUT: We aren't really supposed to allocate/deallocate directly on the heap too much anyways...
#define DEFAULT_HEAP_BLOCK_SIZE min((os.page_size * 1024ULL * 50ULL), program_memory_size)
#define MAX_HEAP_BLOCK_SIZE ((MB(500)+os.page_size)& ~(os.page_size-1))
#define DEFAULT_HEAP_BLOCK_SIZE (min(MAX_HEAP_BLOCK_SIZE, program_memory_size))
#define HEAP_ALIGNMENT (sizeof(Heap_Free_Node))
typedef struct Heap_Free_Node Heap_Free_Node;
typedef struct Heap_Block Heap_Block;
@ -187,7 +192,7 @@ Heap_Block *make_heap_block(Heap_Block *parent, u64 size) {
// #Speed #Cleanup
if (((u8*)block)+size >= ((u8*)program_memory)+program_memory_size) {
u64 minimum_size = ((u8*)block+size) - (u8*)program_memory + 1;
u64 new_program_size = (cast(u64)(minimum_size * 1.5));
u64 new_program_size = max((cast(u64)(minimum_size*2)), program_memory_size*2);
assert(new_program_size >= minimum_size, "Bröd");
const u64 ATTEMPTS = 1000;
for (u64 i = 0; i <= ATTEMPTS; i++) {
@ -226,7 +231,7 @@ void *heap_alloc(u64 size) {
size = (size+HEAP_ALIGNMENT) & ~(HEAP_ALIGNMENT-1);
assert(size < DEFAULT_HEAP_BLOCK_SIZE, "Past Charlie has been lazy and did not handle large allocations like this. I apologize on behalf of past Charlie. A quick fix could be to increase the heap block size for now.");
assert(size < MAX_HEAP_BLOCK_SIZE, "Past Charlie has been lazy and did not handle large allocations like this. I apologize on behalf of past Charlie. A quick fix could be to increase the heap block size for now.");
Heap_Block *block = heap_head;
Heap_Block *last_block = 0;
@ -237,6 +242,13 @@ void *heap_alloc(u64 size) {
// #Speed
// Maybe instead of going through EVERY free node to find best fit we do a good-enough fit
while (block != 0) {
if (block->size < size) {
last_block = block;
block = block->next;
continue;
}
Heap_Search_Result result = search_heap_block(block, size);
Heap_Free_Node *node = result.best_fit;
if (node) {
@ -263,7 +275,7 @@ void *heap_alloc(u64 size) {
}
if (!best_fit) {
block = make_heap_block(last_block, DEFAULT_HEAP_BLOCK_SIZE);
block = make_heap_block(last_block, max(DEFAULT_HEAP_BLOCK_SIZE, size));
previous = 0;
best_fit = block->free_head;
best_fit_block = block;
@ -423,7 +435,7 @@ Allocator get_heap_allocator() {
///
#ifndef TEMPORARY_STORAGE_SIZE
#define TEMPORARY_STORAGE_SIZE (1024ULL*1024ULL*16ULL) // 16mb
#define TEMPORARY_STORAGE_SIZE (1024ULL*1024ULL*2ULL) // 2mb
#endif
void* talloc(u64);

View file

@ -1,4 +1,5 @@
#define DEBUG 0
#define VERY_DEBUG 1
#define RELEASE 2
@ -17,6 +18,10 @@
#define ENTRY_PROC entry
#endif
#ifndef DO_ZERO_INITIALIZATION
#define DO_ZERO_INITIALIZATION 1
#endif
#define WINDOWS 0
#define LINUX 1
#define MACOS 2
@ -213,7 +218,7 @@ void oogabooga_init(u64 program_memory_size) {
}
#ifndef INITIAL_PROGRAM_MEMORY_SIZE
#define INITIAL_PROGRAM_MEMORY_SIZE (1024ULL * 1024ULL * 100ULL) // Start with 100mb program memory
#define INITIAL_PROGRAM_MEMORY_SIZE (max((1024ULL * 1024ULL * 100ULL), TEMPORARY_STORAGE_SIZE*2))
#endif
#ifndef RUN_TESTS
#define RUN_TESTS 0
@ -223,8 +228,12 @@ void oogabooga_init(u64 program_memory_size) {
int ENTRY_PROC(int argc, char **argv);
int main(int argc, char **argv) {
oogabooga_init(INITIAL_PROGRAM_MEMORY_SIZE);
printf("Ooga booga program started\n");
oogabooga_init(INITIAL_PROGRAM_MEMORY_SIZE);
assert(main != ENTRY_PROC, "You've ooga'd your last booga");
// This can be disabled in build.c
#if RUN_TESTS

View file

@ -1,6 +1,6 @@
#define VIRTUAL_MEMORY_BASE ((void*)0x0000010000000000ULL)
#define VIRTUAL_MEMORY_BASE ((void*)0x0000690000000000ULL)
void* heap_alloc(u64);
void heap_dealloc(void*);
@ -238,6 +238,48 @@ void os_init(u64 program_memory_size) {
}
void s64_to_null_terminated_string_reverse(char str[], int length)
{
int start = 0;
int end = length - 1;
while (start < end) {
char temp = str[start];
str[start] = str[end];
str[end] = temp;
end--;
start++;
}
}
void s64_to_null_terminated_string(s64 num, char* str, int base)
{
int i = 0;
bool neg = false;
if (num == 0) {
str[i++] = '0';
str[i] = '\0';
return;
}
if (num < 0 && base == 10) {
neg = true;
num = -num;
}
while (num != 0) {
int rem = num % base;
str[i++] = (rem > 9) ? (rem - 10) + 'a' : rem + '0';
num = num / base;
}
if (neg)
str[i++] = '-';
str[i] = '\0';
s64_to_null_terminated_string_reverse(str, i);
}
bool os_grow_program_memory(u64 new_size) {
@ -275,6 +317,10 @@ bool os_grow_program_memory(u64 new_size) {
assert(m == 0, "amount_to_allocate is not aligned to granularity!");
// Just keep allocating at the tail of the current chunk
void* result = VirtualAlloc(tail, amount_to_allocate, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
assert(result == tail);
#if CONFIGURATION == DEBUG
volatile u8 a = *(u8*)tail = 69;
#endif
memset(result, 0xBA, amount_to_allocate);
if (result == 0) {
os_unlock_mutex(program_memory_mutex); // #Sync
@ -289,7 +335,12 @@ bool os_grow_program_memory(u64 new_size) {
}
char size_str[32];
s64_to_null_terminated_string(program_memory_size/1024, size_str, 10);
os_write_string_to_stdout(STR("Program memory grew to "));
os_write_string_to_stdout(STR(size_str));
os_write_string_to_stdout(STR(" kb\n"));
os_unlock_mutex(program_memory_mutex); // #Sync
return true;
}
@ -440,7 +491,7 @@ void os_high_precision_sleep(f64 ms) {
f64 start = os_get_current_time_in_seconds();
f64 end = start + (f64)s;
u32 sleep_time = (u32)((end-start)-1.0);
s32 sleep_time = (s32)((end-start)-1.0);
bool do_sleep = sleep_time >= 1;
timeBeginPeriod(1); // I don't see a reason to reset this

View file

@ -91,6 +91,8 @@ inline int crt_vprintf(const char* fmt, va_list args) {
}
#endif
inline bool bytes_match(void *a, void *b, u64 count) { return memcmp(a, b, count) == 0; }
inline int vsnprintf(char* buffer, size_t n, const char* fmt, va_list args) {
return os.crt_vsnprintf(buffer, n, fmt, args);
}

View file

@ -47,15 +47,23 @@ void test_allocator(bool do_log_heap) {
assert(*c == 1337, "Test failed: Memory corrupted");
// Test growing memory
os_grow_program_memory(1024 * 1024 * 1000);
//os_grow_program_memory(1024 * 1024 * 1000);
assert(*a == 69, "Test failed: Memory corrupted");
assert(*b == 420, "Test failed: Memory corrupted");
assert(*c == 1337, "Test failed: Memory corrupted");
u8 check_bytes[1024];
for (u64 i = 0; i < 1024; i += 4) {
*((int*)&check_bytes[i]) = (int)get_random();
}
u8 *check_bytes_copy = (u8*)alloc(heap, 1024);
memcpy(check_bytes_copy, check_bytes, 1024);
// Allocate and free large block
void* large_block = alloc(heap, 1024 * 1024 * 100);
dealloc(heap, large_block);
//void* large_block = alloc(heap, 1024 * 1024 * 100);
//dealloc(heap, large_block);
// Allocate multiple small blocks
void* blocks[100];
@ -75,6 +83,7 @@ void test_allocator(bool do_log_heap) {
dealloc(heap, p);
}
// Free in reverse order
for (int i = 0; i < 100; ++i) {
blocks[i] = alloc(heap, 128);
@ -102,8 +111,10 @@ void test_allocator(bool do_log_heap) {
}
reset_temporary_storage();
int* foo = (int*)alloc(temp, 72);
*foo = 1337;
void* bar = alloc(temp, 69);
@ -174,6 +185,8 @@ void test_allocator(bool do_log_heap) {
dealloc(heap, blocks[i]);
}
assert(bytes_match(check_bytes, check_bytes_copy, 1024), "Memory corrupt");
if (do_log_heap) log_heap();
}