#include //----------------------------------------------------------------------------- // Memory //----------------------------------------------------------------------------- const size_t os_page_size = 4096; CORE_Static OS_Memory os_reserve(size_t size) { OS_Memory result = {}; size_t adjusted_size = align_up(size, os_page_size); result.data = (U8 *)VirtualAlloc(0, adjusted_size, MEM_RESERVE, PAGE_READWRITE); assert_message(result.data, "Failed to reserve virtual memory"); result.reserve = adjusted_size; return result; } CORE_Static B32 os_commit(OS_Memory *m, size_t size) { size_t commit = align_up(size, os_page_size); size_t total_commit = m->commit + commit; total_commit = clamp_top(total_commit, m->reserve); size_t adjusted_commit = total_commit - m->commit; if (adjusted_commit != 0) { void *result = VirtualAlloc((U8 *)m->data + m->commit, adjusted_commit, MEM_COMMIT, PAGE_READWRITE); assert_message(result, "Failed to commit more memory"); m->commit += adjusted_commit; return true; } return false; } CORE_Static void os_release(OS_Memory *m) { BOOL result = VirtualFree(m->data, 0, MEM_RELEASE); assert_message(result != 0, "Failed to release OS_Memory"); if (result) { m->data = 0; m->commit = 0; m->reserve = 0; } } CORE_Static B32 os_decommit_pos(OS_Memory *m, size_t pos) { size_t aligned = align_down(pos, os_page_size); size_t adjusted_pos = clamp_top(aligned, m->commit); size_t size_to_decommit = m->commit - adjusted_pos; if (size_to_decommit) { U8 *base_address = m->data + adjusted_pos; BOOL result = VirtualFree(base_address, size_to_decommit, MEM_DECOMMIT); if (result) { m->commit -= size_to_decommit; return true; } } return false; } //----------------------------------------------------------------------------- // Time //----------------------------------------------------------------------------- global S64 Global_counts_per_second; api F64 os_time() { if (Global_counts_per_second == 0) { LARGE_INTEGER freq; QueryPerformanceFrequency(&freq); Global_counts_per_second = freq.QuadPart; } LARGE_INTEGER time; QueryPerformanceCounter(&time); F64 result = (F64)time.QuadPart / (F64)Global_counts_per_second; return result; } //----------------------------------------------------------------------------- // Filesystem //----------------------------------------------------------------------------- CORE_Static B32 os_write_file(String filename, String filecontent) { FILE *f = fopen((const char *)filename.str, "w"); if (f) { fwrite(filecontent.str, 1, filecontent.len, f); fclose(f); return true; } return false; } CORE_Static String os_read_file(Allocator *a, String name) { String result = {0}; FILE *f = fopen((char *)name.str, "rb"); if (f) { fseek(f, 0, SEEK_END); result.len = ftell(f); fseek(f, 0, SEEK_SET); result.str = (U8 *)allocate_size(a, result.len + 1, false); fread(result.str, result.len, 1, f); fclose(f); result.str[result.len] = 0; } return result; } CORE_Static String os_get_working_dir(Allocator *a) { wchar_t buffer[2048]; DWORD written = GetCurrentDirectoryW(2048, buffer); assert(written != 0); String16 string16 = string16_from_widechar(buffer); String result = string16_to_string8(a, string16); string_path_normalize(result); return result; } CORE_Static String os_get_exe_dir(Allocator *a) { wchar_t buffer[2048]; DWORD written = GetModuleFileNameW(0, buffer, 2048); assert(written != 0); String16 string16 = string16_from_widechar(buffer); String result = string16_to_string8(a, string16); string_path_normalize(result); result = string_chop_last_slash(result); if (string16.len > result.len) result.str[result.len] = 0; string_path_normalize(result); return result; } CORE_Static String os_get_absolute_path(Allocator *a, String path) { char buff[2048]; Arena scratch = arena_from_buffer(buff, 2048); String16 path16 = string8_to_string16(&scratch, path); wchar_t *buffer = allocate_array(&scratch, wchar_t, 512); DWORD written = GetFullPathNameW((wchar_t *)path16.str, 512, buffer, 0); if (written == 0) return {}; String16 absolute16 = string16_from_widechar(buffer); String absolute = string16_to_string8(a, absolute16); string_path_normalize(absolute); return absolute; } CORE_Static B32 os_does_file_exist(String path) { char buff[2048]; Arena scratch = arena_from_buffer(buff, buff_cap(buff)); String16 path16 = string8_to_string16(&scratch, path); DWORD attribs = GetFileAttributesW((wchar_t *)path16.str); B32 result = attribs == INVALID_FILE_ATTRIBUTES ? false : true; return result; } CORE_Static Array os_list_dir(Arena *scratch, Allocator *a, String dir, U32 flags = LIST_NO_FLAGS) { Scoped_Arena _scope(scratch); Array dirs_to_read = {scratch}; dirs_to_read.add(dir); Array result = {a}; for (auto it = dirs_to_read.begin(); it != dirs_to_read.end(); it++) { String modified_path = string_fmt(scratch, "%Q\\*", it); String16 path16 = string8_to_string16(scratch, modified_path); WIN32_FIND_DATAW ffd; HANDLE handle = FindFirstFileW((wchar_t *)path16.str, &ffd); if (handle == INVALID_HANDLE_VALUE) continue; do { // // Skip '.' and '..' // if (ffd.cFileName[0] == '.') { if (ffd.cFileName[1] == '.') { if (ffd.cFileName[2] == 0) continue; } if (ffd.cFileName[1] == 0) continue; } String16 filename16 = string16_from_widechar(ffd.cFileName); String filename = string16_to_string8(scratch, filename16); String full_file_path = string_fmt(a, "%Q/%Q", dir, filename); OS_File_Info listing = {full_file_path, os_get_absolute_path(a, full_file_path)}; if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { listing.is_directory = true; if (flags & LIST_RECURSE_INTO_DIRS) { dirs_to_read.add(full_file_path); } } result.add(listing); } while (FindNextFileW(handle, &ffd) != 0); DWORD error = GetLastError(); if (error != ERROR_NO_MORE_FILES) { // Not sure what to do here hmmm } FindClose(handle); } return result; } bool os_enable_console_colors() { // Set output mode to handle virtual terminal sequences HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); if (hOut != INVALID_HANDLE_VALUE) { DWORD dwMode = 0; if (GetConsoleMode(hOut, &dwMode)) { dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; if (SetConsoleMode(hOut, dwMode)) { return true; } else { printf("Failed to enable colored terminal output C\n"); } } else { printf("Failed to enable colored terminal output B\n"); } } else { printf("Failed to enable colored terminal output A\n"); } return false; }