diff --git a/Juliet.sln b/Juliet.sln
index 5d65aa0..ae5e343 100644
--- a/Juliet.sln
+++ b/Juliet.sln
@@ -1,4 +1,4 @@
-Microsoft Visual Studio Solution File, Format Version 12.00
+Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.22823.1
MinimumVisualStudioVersion = 10.0.40219.1
@@ -7,11 +7,6 @@ EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Game", "Game\Game.vcxproj", "{B1D040D0-6C94-4F93-BC2A-7F5284B7D434}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "JulietApp", "JulietApp\JulietApp.vcxproj", "{1DEE51CA-6C94-4F93-BC2A-7F5284B7D434}"
- ProjectSection(ProjectDependencies) = postProject
- {AB9C7E88-6C94-4F93-BC2A-7F5284B7D434} = {AB9C7E88-6C94-4F93-BC2A-7F5284B7D434}
- {C16FFE36-6C94-4F93-BC2A-7F5284B7D434} = {C16FFE36-6C94-4F93-BC2A-7F5284B7D434}
- {B1D040D0-6C94-4F93-BC2A-7F5284B7D434} = {B1D040D0-6C94-4F93-BC2A-7F5284B7D434}
- EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Juliet", "Juliet\Juliet.vcxproj", "{AB9C7E88-6C94-4F93-BC2A-7F5284B7D434}"
EndProject
diff --git a/Juliet/Juliet.vcxproj b/Juliet/Juliet.vcxproj
index 64bcda9..3ee2bbb 100644
--- a/Juliet/Juliet.vcxproj
+++ b/Juliet/Juliet.vcxproj
@@ -72,12 +72,14 @@
+
+
@@ -140,6 +142,9 @@
+
+
+
diff --git a/Juliet/Juliet.vcxproj.filters b/Juliet/Juliet.vcxproj.filters
index 8b26a25..863a7bf 100644
--- a/Juliet/Juliet.vcxproj.filters
+++ b/Juliet/Juliet.vcxproj.filters
@@ -64,6 +64,9 @@
include\Core\HAL\Mouse
+
+ include\Core\HAL\OS
+
include\Core\HotReload
@@ -82,6 +85,9 @@
include\Core\Logging
+
+ include\Core
+
include\Core\Math
@@ -267,6 +273,15 @@
src\Core\HAL\IO\Win32
+
+ src\Core\HAL\OS
+
+
+ src\Core\HAL\OS
+
+
+ src\Core\HAL\OS\Win32
+
src\Core\HAL
@@ -552,6 +567,11 @@
{4c7d6b5f-6c94-4f93-bc2a-7f5284b7d434}
+
+
+ {8d491e18-6c94-4f93-bc2a-7f5284b7d434}
+
+
{fe4e9898-6c94-4f93-bc2a-7f5284b7d434}
@@ -672,6 +692,16 @@
{37523cd5-6c94-4f93-bc2a-7f5284b7d434}
+
+
+ {d679d621-6c94-4f93-bc2a-7f5284b7d434}
+
+
+
+
+ {f6713825-6c94-4f93-bc2a-7f5284b7d434}
+
+
{35231af8-6c94-4f93-bc2a-7f5284b7d434}
diff --git a/Juliet/include/Core/Common/CoreUtils.h b/Juliet/include/Core/Common/CoreUtils.h
index ce1dbb4..caefd05 100644
--- a/Juliet/include/Core/Common/CoreUtils.h
+++ b/Juliet/include/Core/Common/CoreUtils.h
@@ -4,11 +4,16 @@
#include
#include
+#include
+#include
+#include
#include
namespace Juliet
{
+#define global static
+
#if JULIET_DEBUG
#define JULIET_ASSERT_INTERNAL(expression, message) \
__pragma(warning(push)) __pragma(warning(disable : 4127)) __pragma(warning(disable : 4548)) do \
@@ -100,4 +105,38 @@ namespace Juliet
}
extern JULIET_API void Free(ByteBuffer& buffer);
+
+ template
+ [[nodiscard]] constexpr T AlignPow2(T x, T alignment)
+ {
+ // Safety Check:
+ Assert(std::has_single_bit(static_cast(alignment)));
+
+ return (x + alignment - 1) & ~(alignment - 1);
+ }
+
+ // Move to another file dedicated to those
+#if defined(__clang__)
+#define COMPILER_CLANG 1
+#elif defined(_MSC_VER)
+#define COMPILER_MSVC 1
+#endif
+
+ // Undef anything not defined
+#if !defined(COMPILER_CLANG)
+#define COMPILER_CLANG 0
+#endif
+#if !defined(COMPILER_MSVC)
+#define COMPILER_MSVC 0
+#endif
+
+#if COMPILER_MSVC
+#define AlignOf(T) __alignof(T)
+#elif COMPILER_CLANG
+#define AlignOf(T) __alignof(T)
+#elif COMPILER_GCC
+#define AlignOf(T) __alignof__(T)
+#else
+#error AlignOf not defined for this compiler.
+#endif
} // namespace Juliet
diff --git a/Juliet/include/Core/HAL/OS/OS.h b/Juliet/include/Core/HAL/OS/OS.h
new file mode 100644
index 0000000..3cf8a54
--- /dev/null
+++ b/Juliet/include/Core/HAL/OS/OS.h
@@ -0,0 +1,36 @@
+#pragma once
+
+#include
+#include
+
+namespace Juliet
+{
+ namespace Memory
+ {
+ Byte* OS_Reserve(size_t size);
+ bool OS_Commit(Byte* ptr, size_t size);
+ void OS_Release(Byte* ptr, size_t size);
+
+ template
+ Type* OS_Reserve(size_t size)
+ {
+ return reinterpret_cast(OS_Reserve(size));
+ }
+
+ template
+ bool OS_Commit(Type* ptr, size_t size)
+ {
+ return OS_Commit(reinterpret_cast(ptr), size);
+ }
+
+ template
+ void OS_Release(Type* ptr, size_t size)
+ {
+ OS_Release(reinterpret_cast(ptr), size);
+ }
+
+ } // namespace Memory
+
+ using EntryPointFunc = int (*)(int, wchar_t**);
+ JULIET_API int Bootstrap(EntryPointFunc entryPointFunc, int argc, wchar_t** argv);
+} // namespace Juliet
diff --git a/Juliet/include/Core/Logging/LogManager.h b/Juliet/include/Core/Logging/LogManager.h
index 48dfd61..edb2ee0 100644
--- a/Juliet/include/Core/Logging/LogManager.h
+++ b/Juliet/include/Core/Logging/LogManager.h
@@ -6,7 +6,13 @@
// TODO : Juliet strings
#include
// TODO Juliet Containers + Allocators...
+// TODO: Juliet chrono, because it prevents me from doing #define global static
+#ifdef global
+#undef global
+#endif
#include
+#define global static
+
#include
namespace Juliet
diff --git a/Juliet/include/Core/Main.h b/Juliet/include/Core/Main.h
new file mode 100644
index 0000000..31e0b03
--- /dev/null
+++ b/Juliet/include/Core/Main.h
@@ -0,0 +1,47 @@
+#pragma once
+
+#include
+
+extern int JulietMain(int, wchar_t**);
+
+#if JULIET_WIN32
+#ifndef WINAPI
+#define WINAPI __stdcall
+#endif
+
+#if COMPILER_MSVC
+#if UNICODE
+int wmain(int argc, wchar_t** argv)
+{
+ return Juliet::Bootstrap(JulietMain, argc, argv);
+}
+#else
+int main(int argc, char** argv)
+{
+ return Juliet::Bootstrap(JulietMain, argc, argv);
+}
+#endif
+#endif
+
+extern "C" {
+
+typedef struct HINSTANCE__* HINSTANCE;
+typedef char* LPSTR;
+typedef wchar_t* PWSTR;
+
+#if UNICODE
+int WINAPI wWinMain(HINSTANCE hInst, HINSTANCE hPrev, PWSTR szCmdLine, int sw)
+#else
+int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
+#endif
+{
+ (void)hInst;
+ (void)hPrev;
+ (void)szCmdLine;
+ (void)sw;
+ return Juliet::Bootstrap(JulietMain, __argc, __wargv);
+}
+}
+#else
+#error "Only windows main is implemented"
+#endif
diff --git a/Juliet/include/Core/Math/MathUtils.h b/Juliet/include/Core/Math/MathUtils.h
index f301591..f7b6aff 100644
--- a/Juliet/include/Core/Math/MathUtils.h
+++ b/Juliet/include/Core/Math/MathUtils.h
@@ -24,6 +24,18 @@ namespace Juliet
return lhs < rhs ? rhs : lhs;
}
+ template
+ constexpr Type ClampTop(Type value, Type X)
+ {
+ return Min(value, X);
+ }
+
+ template
+ constexpr Type ClampBottom(Type value, Type X)
+ {
+ return Max(value, X);
+ }
+
template
constexpr Type Clamp(Type val, Type min, Type max)
{
diff --git a/Juliet/include/Core/Memory/MemoryArena.h b/Juliet/include/Core/Memory/MemoryArena.h
index b5f005b..f89c5c8 100644
--- a/Juliet/include/Core/Memory/MemoryArena.h
+++ b/Juliet/include/Core/Memory/MemoryArena.h
@@ -2,12 +2,58 @@
#include
#include
+#include
#include
#include
#include
namespace Juliet
{
+ constexpr global uint64 g_Arena_Default_Reserve_Size = Megabytes(64);
+ constexpr global uint64 g_Arena_Default_Commit_Size = Kilobytes(64);
+ constexpr global uint64 k_ArenaHeaderSize = 128;
+
+ // Refactor
+ struct Arena
+ {
+ Arena* Previous;
+ Arena* Current;
+
+ uint64 BasePosition;
+ uint64 Position;
+ uint64 Capacity;
+ uint64 Alignment;
+
+ uint64 CommitSize;
+ uint64 ReserveSize;
+
+ uint64 Committed;
+ uint64 Reserved;
+ };
+ static_assert(sizeof(Arena) <= k_ArenaHeaderSize);
+
+ struct ArenaParams
+ {
+ uint64 ReserveSize = g_Arena_Default_Reserve_Size;
+ uint64 CommitSize = g_Arena_Default_Commit_Size;
+ };
+
+ [[nodiscard]] Arena* ArenaAllocate(const ArenaParams& params = {},
+ const std::source_location& loc = std::source_location::current());
+ void ArenaRelease(NonNullPtr arena);
+
+ // Raw Push, can be used but templated helpers exists below
+ [[nodiscard]] void* ArenaPush(NonNullPtr arena, size_t size, size_t align, bool shouldBeZeroed);
+ void ArenaPopTo(NonNullPtr arena, size_t position);
+ void ArenaPop(NonNullPtr arena, size_t amount);
+ void ArenaClear(NonNullPtr arena);
+ [[nodiscard]] size_t ArenaPos(NonNullPtr arena);
+
+ template
+ [[nodiscard]] Type* ArenaPushStruct(NonNullPtr arena)
+ {
+ return static_cast(ArenaPush(arena, sizeof(Type) * 1, AlignOf(Type), true));
+ }
// --- Paged Memory Architecture ---
struct ArenaAllocation
@@ -25,23 +71,23 @@ namespace Juliet
MemoryBlock* Next; // Next block in the chain (Arena) or FreeList (Pool)
size_t TotalSize; // Total size of this block (including header)
size_t Used; // Offset relative to the start of Data
-
+
#if JULIET_DEBUG
ArenaAllocation* FirstAllocation = nullptr;
uint64 Pad; // Ensure 16-byte alignment (Size 40 -> 48)
#endif
- // Data follows immediately.
+ // Data follows immediately.
// We use a helper to access it to avoid C++ flexible array warning issues if strict
- uint8* GetData() { return reinterpret_cast(this + 1); }
+ uint8* GetData() { return reinterpret_cast(this + 1); }
const uint8* GetData() const { return reinterpret_cast(this + 1); }
};
struct MemoryPool
{
void* BaseAddress = nullptr;
- size_t TotalSize = 0;
- MemoryBlock* FreeList = nullptr;
+ size_t TotalSize = 0;
+ MemoryBlock* FreeList = nullptr;
[[nodiscard]] MemoryBlock* AllocateBlock(size_t minCapacity);
void FreeBlock(MemoryBlock* block);
@@ -52,7 +98,7 @@ namespace Juliet
MemoryPool* BackingPool;
MemoryBlock* CurrentBlock;
MemoryBlock* FirstBlock;
- // Marker behavior is now tricky with pages.
+ // Marker behavior is now tricky with pages.
// Simple Marker = { Block*, Offset }
};
@@ -62,12 +108,11 @@ namespace Juliet
size_t Offset;
};
-
- JULIET_API void MemoryArenaCreate(MemoryArena* arena, MemoryPool* pool);
+ JULIET_API void MemoryArenaCreate(MemoryArena* arena, MemoryPool* pool);
JULIET_API void* ArenaPush(MemoryArena* arena, size_t size, size_t alignment, String tag);
- JULIET_API void* ArenaRealloc(MemoryArena* arena, void* oldPtr, size_t oldSize, size_t newSize, size_t alignment, String tag);
- JULIET_API bool ArenaPop(MemoryArena* arena, void* ptr, size_t size);
- JULIET_API void ArenaReset(MemoryArena* arena);
+ JULIET_API void* ArenaRealloc(MemoryArena* arena, void* oldPtr, size_t oldSize, size_t newSize, size_t alignment, String tag);
+ JULIET_API bool ArenaPop(MemoryArena* arena, void* ptr, size_t size);
+ JULIET_API void ArenaReset(MemoryArena* arena);
JULIET_API ArenaMarker ArenaGetMarker(MemoryArena* arena);
JULIET_API void ArenaResetToMarker(MemoryArena* arena, ArenaMarker marker);
diff --git a/Juliet/include/Core/Memory/Utils.h b/Juliet/include/Core/Memory/Utils.h
index de0c966..01f438d 100644
--- a/Juliet/include/Core/Memory/Utils.h
+++ b/Juliet/include/Core/Memory/Utils.h
@@ -22,4 +22,6 @@ namespace Juliet
// TODO: homemade versions
#define MemSet memset
#define MemCopy memcpy
+
+#define MemoryZero(dst, size) MemSet(dst, 0, size)
} // namespace Juliet
diff --git a/Juliet/src/Core/HAL/OS/OS.cpp b/Juliet/src/Core/HAL/OS/OS.cpp
new file mode 100644
index 0000000..fc0b655
--- /dev/null
+++ b/Juliet/src/Core/HAL/OS/OS.cpp
@@ -0,0 +1,29 @@
+#include
+#include
+
+namespace Juliet
+{
+ namespace Memory
+ {
+ Byte* OS_Reserve(size_t size)
+ {
+ return Internal::OS_Reserve(size);
+ }
+
+ bool OS_Commit(Byte* ptr, size_t size)
+ {
+ return Internal::OS_Commit(ptr, size);
+ }
+
+ void OS_Release(Byte* ptr, size_t size)
+ {
+ Internal::OS_Release(ptr, size);
+ }
+ } // namespace Memory
+
+ int Bootstrap(EntryPointFunc entryPointFunc, int argc, wchar_t** argv)
+ {
+ return Internal::OS_Main(entryPointFunc, argc, argv);
+ }
+
+} // namespace Juliet
diff --git a/Juliet/src/Core/HAL/OS/OS_Private.h b/Juliet/src/Core/HAL/OS/OS_Private.h
new file mode 100644
index 0000000..4c67ab7
--- /dev/null
+++ b/Juliet/src/Core/HAL/OS/OS_Private.h
@@ -0,0 +1,19 @@
+#pragma once
+
+namespace Juliet
+{
+ namespace Memory
+ {
+ namespace Internal
+ {
+ Byte* OS_Reserve(size_t size);
+ bool OS_Commit(Byte* ptr, size_t size);
+ void OS_Release(Byte* ptr, size_t size);
+ } // namespace Internal
+ } // namespace Memory
+
+ namespace Internal
+ {
+ int OS_Main(EntryPointFunc entryPointFunc, int argc, wchar_t** argv);
+ }
+} // namespace Juliet
diff --git a/Juliet/src/Core/HAL/OS/Win32/Win32OS.cpp b/Juliet/src/Core/HAL/OS/Win32/Win32OS.cpp
new file mode 100644
index 0000000..642497e
--- /dev/null
+++ b/Juliet/src/Core/HAL/OS/Win32/Win32OS.cpp
@@ -0,0 +1,84 @@
+#include
+#include
+#include
+#include
+#include
+
+namespace Juliet
+{
+ namespace
+ {
+ global RIO_EXTENSION_FUNCTION_TABLE w32_rio_functions = {};
+ }
+
+ namespace Memory::Internal
+ {
+ Byte* OS_Reserve(size_t size)
+ {
+ auto result = static_cast(VirtualAlloc(nullptr, size, MEM_RESERVE, PAGE_READWRITE));
+ return result;
+ }
+
+ bool OS_Commit(Byte* ptr, size_t size)
+ {
+ bool result = (VirtualAlloc(ptr, size, MEM_COMMIT, PAGE_READWRITE) != nullptr);
+
+ Assert(size <= static_cast(MaxValueOf()));
+
+ w32_rio_functions.RIODeregisterBuffer(
+ w32_rio_functions.RIORegisterBuffer(reinterpret_cast(ptr), static_cast(size)));
+ return result;
+ }
+
+ void OS_Release(Byte* ptr, size_t size)
+ {
+ // size not used on windows
+ std::ignore = size;
+
+ VirtualFree(ptr, 0, MEM_RELEASE);
+ }
+ } // namespace Memory::Internal
+
+ namespace
+ {
+ // Used to handle a crash/exception
+ LONG WINAPI ExceptionFilter(EXCEPTION_POINTERS* exceptionPtrs)
+ {
+ (void)exceptionPtrs;
+ // See for more info https://github.com/EpicGamesExt/raddebugger/blob/master/src/os/core/win32/os_core_win32.c
+ ExitProcess(1);
+ }
+ } // namespace
+
+ namespace Internal
+ {
+ int OS_Main(EntryPointFunc entryPointFunc, int argc, wchar_t** argv)
+ {
+ (void)argc;
+ (void)argv;
+ SetUnhandledExceptionFilter(&ExceptionFilter);
+
+ // Allow only one instance to be launched.
+ CreateMutex(nullptr, false, L"Local\\Juliet.App");
+ if (GetLastError() == ERROR_ALREADY_EXISTS)
+ {
+ MessageBox(nullptr, L"An instance of Juliet is already running.", L"Juliet", MB_OK | MB_ICONEXCLAMATION);
+ return EXIT_FAILURE;
+ }
+
+ // Create a dummy socket to access RIO functions. Those will be used to do fine memory management
+ {
+ WSADATA WinSockData;
+ WSAStartup(MAKEWORD(2, 2), &WinSockData);
+ GUID guid = WSAID_MULTIPLE_RIO;
+ DWORD rio_byte = 0;
+ SOCKET Sock = socket(AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP);
+ WSAIoctl(Sock, SIO_GET_MULTIPLE_EXTENSION_FUNCTION_POINTER, &guid, sizeof(guid),
+ (void**)&w32_rio_functions, sizeof(w32_rio_functions), &rio_byte, nullptr, nullptr);
+ closesocket(Sock);
+ }
+
+ return entryPointFunc(argc, argv);
+ }
+ } // namespace Internal
+} // namespace Juliet
diff --git a/Juliet/src/Core/HAL/Win32.h b/Juliet/src/Core/HAL/Win32.h
index f551b44..42d933d 100644
--- a/Juliet/src/Core/HAL/Win32.h
+++ b/Juliet/src/Core/HAL/Win32.h
@@ -26,7 +26,7 @@
#define WINVER _WIN32_WINNT
#ifdef __clang__
- #pragma clang diagnostic pop
+#pragma clang diagnostic pop
#endif
#define NOIME
@@ -66,6 +66,11 @@
#define NOTAPE
#define ANSI_ONLY
+// Keep includes in that order
+#include
+
+#include
+
#include
#undef min
diff --git a/Juliet/src/Core/Juliet.cpp b/Juliet/src/Core/Juliet.cpp
index 7577b64..a05a8d6 100644
--- a/Juliet/src/Core/Juliet.cpp
+++ b/Juliet/src/Core/Juliet.cpp
@@ -3,6 +3,7 @@
#include
#include
#include
+#include
#include
namespace Juliet
@@ -41,11 +42,6 @@ namespace Juliet
void JulietInit(JulietInit_Flags flags)
{
- // Mandatory systems
- MemoryArenasInit();
-
- InitFilesystem();
-
// Optional systems
if ((flags & JulietInit_Flags::Display) != JulietInit_Flags::None)
{
@@ -62,9 +58,6 @@ namespace Juliet
DecrementSystemRefCount(JulietInit_Flags::Display);
ShutdownDisplaySystem();
}
-
- ShutdownFilesystem();
- MemoryArenasShutdown();
}
} // namespace Juliet
diff --git a/Juliet/src/Core/Memory/MemoryArena.cpp b/Juliet/src/Core/Memory/MemoryArena.cpp
index 174d460..12a0707 100644
--- a/Juliet/src/Core/Memory/MemoryArena.cpp
+++ b/Juliet/src/Core/Memory/MemoryArena.cpp
@@ -4,10 +4,181 @@
#include
#include // For std::max
+#include
+#include
+#include
#include
namespace Juliet
{
+
+ // TODO Get page size from os kernel call (dwPageSize)
+ namespace
+ {
+ constexpr uint64 k_PageSize = Kilobytes(4);
+ } // namespace
+
+ // https://github.com/EpicGamesExt/raddebugger/blob/master/src/base/base_arena.c
+
+ Arena* ArenaAllocate(const ArenaParams& params, const std::source_location& loc)
+ {
+ Log(LogLevel::Message, LogCategory::Core, "Allocating from %s : %ul", loc.file_name(), loc.line());
+
+ Byte* baseMem = nullptr;
+
+ uint64 reserve_size = AlignPow2(params.ReserveSize, k_PageSize);
+ uint64 commit_size = AlignPow2(params.CommitSize, k_PageSize);
+
+ // TODO: handle large pages
+ baseMem = Memory::OS_Reserve(reserve_size);
+ Memory::OS_Commit(baseMem, commit_size);
+
+ Arena* arena = reinterpret_cast(baseMem);
+ arena->Current = arena;
+
+ arena->CommitSize = commit_size;
+ arena->ReserveSize = reserve_size;
+
+ arena->Committed = commit_size;
+ arena->Reserved = reserve_size;
+
+ arena->BasePosition = 0;
+ arena->Position = k_ArenaHeaderSize;
+
+ return arena;
+ }
+
+ void ArenaRelease(NonNullPtr arena)
+ {
+ for (Arena *node = arena->Current, *previous = nullptr; node != nullptr; node = previous)
+ {
+ previous = node->Previous;
+ Memory::OS_Release(node, node->Reserved);
+ }
+ }
+
+ void* ArenaPush(NonNullPtr arena, size_t size, size_t align, bool shouldBeZeroed)
+ {
+ Arena* current = arena->Current;
+ size_t positionPrePush = AlignPow2(current->Position, align);
+ size_t positionPostPush = positionPrePush + size;
+
+ // If allowed and needed, add a new block and chain it to the arena.
+ if (current->Reserved < positionPostPush /* flags : chaining allowed */)
+ {
+ Arena* newBlock = nullptr;
+ // TODO : use the free list
+
+ if (newBlock == nullptr)
+ {
+ size_t reserveSize = current->ReserveSize;
+ size_t commitSize = current->CommitSize;
+
+ if (size + k_ArenaHeaderSize > reserveSize)
+ {
+ reserveSize = AlignPow2(size + k_ArenaHeaderSize, align);
+ commitSize = AlignPow2(size + k_ArenaHeaderSize, align);
+ }
+ newBlock = ArenaAllocate({ .ReserveSize = reserveSize, .CommitSize = commitSize });
+ }
+
+ newBlock->BasePosition = current->BasePosition + current->Reserved;
+ // Push on the linkedlist
+ newBlock->Previous = arena->Current;
+ arena->Current = newBlock;
+
+ // TODO: Think about ryan fleur way to push:
+ // SLLStackPush_N(arena->current, new_block, prev);
+ // #define SLLStackPush_N(f,n,next) ((n)->next=(f), (f)=(n))
+
+ current = newBlock;
+ positionPrePush = AlignPow2(current->Position, align);
+ positionPostPush = positionPrePush + size;
+ }
+
+ size_t sizeToZero = 0;
+ if (shouldBeZeroed)
+ {
+ sizeToZero = Min(current->Committed, positionPostPush) - positionPrePush;
+ }
+
+ // If needed commit new pages
+ if (current->Committed < positionPostPush)
+ {
+ size_t commitPostAligned = positionPostPush + current->CommitSize - 1;
+ commitPostAligned -= commitPostAligned % current->CommitSize;
+ size_t commitPostClamped = ClampTop(commitPostAligned, current->Reserved);
+ // size_t commitSize = commitPostClamped - current->Committed;
+ // Byte* commitPtr = reinterpret_cast(current) + current->Committed;
+
+ // TODO os_commit / commit_large
+ // os_commit(commitPtr, commitSize);
+
+ current->Committed = commitPostClamped;
+ }
+
+ // Push on the current block
+ void* result = nullptr;
+ if (current->Committed >= positionPostPush)
+ {
+ result = reinterpret_cast(current) + positionPrePush;
+ current->Position = positionPostPush;
+ if (sizeToZero != 0)
+ {
+ MemoryZero(result, sizeToZero);
+ }
+ }
+
+ // If alloc failed, log and assert
+ if (result == nullptr) [[unlikely]]
+ {
+ Assert(false, "Fatal Allocation Failure - Unexpected allocation failure");
+ }
+
+ return result;
+ }
+
+ void ArenaPopTo(NonNullPtr arena, size_t position)
+ {
+ size_t bbbPosition = ClampBottom(k_ArenaHeaderSize, position);
+ Arena* current = arena->Current;
+
+ // TODO : Free list
+ for (Arena* previous = nullptr; current->BasePosition >= bbbPosition; current = previous)
+ {
+ previous = current->Previous;
+ Memory::OS_Release(current, current->Reserved);
+ }
+
+ arena->Current = current;
+ size_t newPosition = bbbPosition - current->BasePosition;
+ Assert(newPosition <= current->Position);
+ current->Position = newPosition;
+ }
+
+ void ArenaPop(NonNullPtr arena, size_t amount)
+ {
+ size_t oldPosition = ArenaPos(arena);
+ size_t newPosition = oldPosition;
+ if (amount < oldPosition)
+ {
+ newPosition = oldPosition - amount;
+ }
+ ArenaPopTo(arena, newPosition);
+ }
+
+ void ArenaClear(NonNullPtr arena)
+ {
+ ArenaPopTo(arena, 0);
+ }
+
+ size_t ArenaPos(NonNullPtr arena)
+ {
+ Arena* current = arena->Current;
+ size_t position = current->BasePosition + current->Position;
+ return position;
+ }
+
namespace UnitTest
{
extern void TestMemoryArena();
@@ -18,7 +189,10 @@ namespace Juliet
#if JULIET_DEBUG
static void FreeDebugAllocations(MemoryBlock* blk)
{
- if (!blk) return;
+ if (!blk)
+ {
+ return;
+ }
ArenaAllocation* curr = blk->FirstAllocation;
while (curr)
{
@@ -188,23 +362,25 @@ namespace Juliet
// Commit
blk->Used += alignmentOffset;
void* ptr = blk->GetData() + blk->Used;
-
+
#if JULIET_DEBUG
ArenaAllocation* node = (ArenaAllocation*)Malloc(sizeof(ArenaAllocation));
- node->Offset = blk->Used;
- node->Size = size;
- node->Tag = tag;
- node->Next = nullptr;
-
- if (!blk->FirstAllocation) blk->FirstAllocation = node;
+ node->Offset = blk->Used;
+ node->Size = size;
+ node->Tag = tag;
+ node->Next = nullptr;
+
+ if (!blk->FirstAllocation)
+ blk->FirstAllocation = node;
else
{
- ArenaAllocation* t = blk->FirstAllocation;
- while(t->Next) t = t->Next;
- t->Next = node;
+ ArenaAllocation* t = blk->FirstAllocation;
+ while (t->Next)
+ t = t->Next;
+ t->Next = node;
}
#endif
-
+
blk->Used += size;
return ptr;
@@ -234,7 +410,8 @@ namespace Juliet
#if JULIET_DEBUG
{
ArenaAllocation* t = blk->FirstAllocation;
- while (t && t->Next) t = t->Next;
+ while (t && t->Next)
+ t = t->Next;
if (t) t->Size += (newSize - oldSize);
}
#endif
@@ -268,13 +445,24 @@ namespace Juliet
blk->Used -= size;
#if JULIET_DEBUG
{
- ArenaAllocation* t = blk->FirstAllocation;
+ ArenaAllocation* t = blk->FirstAllocation;
ArenaAllocation* prev = nullptr;
- while (t && t->Next) { prev = t; t = t->Next; }
- if (t) {
+ while (t && t->Next)
+ {
+ prev = t;
+ t = t->Next;
+ }
+ if (t)
+ {
SafeFree(t);
- if (prev) prev->Next = nullptr;
- else blk->FirstAllocation = nullptr;
+ if (prev)
+ {
+ prev->Next = nullptr;
+ }
+ else
+ {
+ blk->FirstAllocation = nullptr;
+ }
}
}
#endif
diff --git a/Juliet/src/Core/Memory/MemoryArenaTests.cpp b/Juliet/src/Core/Memory/MemoryArenaTests.cpp
index 4afc055..f1a153a 100644
--- a/Juliet/src/Core/Memory/MemoryArenaTests.cpp
+++ b/Juliet/src/Core/Memory/MemoryArenaTests.cpp
@@ -7,12 +7,56 @@
namespace Juliet::UnitTest
{
+ struct TestStruct
+ {
+ uint8 First;
+ uint16 Second;
+ };
// Need access to internal Pool functions? They are in the header now!
// MemoryPool is declared in header.
void TestMemoryArena()
{
printf("Running Paged Memory Arena Tests...\n");
+ // New Arena!
+ Arena* testArena = ArenaAllocate();
+
+ size_t pos = ArenaPos(testArena);
+ Assert(pos == k_ArenaHeaderSize);
+
+ TestStruct* myStruct = ArenaPushStruct(testArena);
+ Assert(myStruct->First == 0);
+ Assert(myStruct->Second == 0);
+ pos = ArenaPos(testArena);
+ Assert(pos == k_ArenaHeaderSize + sizeof(TestStruct));
+
+ TestStruct* myStruct2 = ArenaPushStruct(testArena);
+ Assert(myStruct2->First == 0);
+ Assert(myStruct2->Second == 0);
+
+ myStruct->First = 5;
+ myStruct->Second = 125;
+ myStruct2->First = 5;
+ myStruct2->Second = 125;
+
+ ArenaClear(testArena);
+ pos = ArenaPos(testArena);
+ Assert(pos == k_ArenaHeaderSize);
+
+ myStruct = ArenaPushStruct(testArena);
+ Assert(myStruct->First == 0);
+ Assert(myStruct->Second == 0);
+ pos = ArenaPos(testArena);
+ Assert(pos == k_ArenaHeaderSize + sizeof(TestStruct));
+
+ TestStruct* myStruct3 = ArenaPushStruct(testArena);
+ Assert(myStruct3->First == 0);
+ Assert(myStruct3->Second == 0);
+ pos = ArenaPos(testArena);
+ Assert(pos == k_ArenaHeaderSize + sizeof(TestStruct) * 2);
+
+ ArenaRelease(testArena);
+
// Setup Pool and Arena for Pop Tests
size_t testPoolSize = Megabytes(1);
void* testBacking = Calloc(1, testPoolSize);
diff --git a/Juliet/src/Core/Networking/SocketPlatformImpl.h b/Juliet/src/Core/Networking/SocketPlatformImpl.h
index b185804..b86dff5 100644
--- a/Juliet/src/Core/Networking/SocketPlatformImpl.h
+++ b/Juliet/src/Core/Networking/SocketPlatformImpl.h
@@ -5,13 +5,11 @@
// Windows uses a non standard header to define its socket types.
// Because of that we need to include those in this header.
// TODO : implement for other platforms
-#if JULIET_WIN32
-
-#include
-
-#else
-// UNIMPLEMENT_SOCKETS
-#endif
+// #if JULIET_WIN32
+// #include
+// #else
+// // UNIMPLEMENT_SOCKETS
+// #endif
namespace Juliet::SocketImpl
{
diff --git a/Juliet/src/Core/Networking/Win32/Win32SocketPlatformImpl.cpp b/Juliet/src/Core/Networking/Win32/Win32SocketPlatformImpl.cpp
index b7fff31..494ee13 100644
--- a/Juliet/src/Core/Networking/Win32/Win32SocketPlatformImpl.cpp
+++ b/Juliet/src/Core/Networking/Win32/Win32SocketPlatformImpl.cpp
@@ -1,3 +1,4 @@
+#include
#include
#include
#include
diff --git a/Juliet/src/Engine/Engine.cpp b/Juliet/src/Engine/Engine.cpp
index 1934ae7..c37685c 100644
--- a/Juliet/src/Engine/Engine.cpp
+++ b/Juliet/src/Engine/Engine.cpp
@@ -1,4 +1,5 @@
#include
+#include
#include
#include
#include
@@ -129,12 +130,18 @@ namespace Juliet
void InitializeEngine(JulietInit_Flags flags)
{
InitializeLogManager();
+ MemoryArenasInit();
+ InitFilesystem();
+
JulietInit(flags);
}
void ShutdownEngine()
{
JulietShutdown();
+
+ ShutdownFilesystem();
+ MemoryArenasShutdown();
ShutdownLogManager();
}
diff --git a/JulietApp/JulietApp.bff b/JulietApp/JulietApp.bff
index a14b5dc..4c22f30 100644
--- a/JulietApp/JulietApp.bff
+++ b/JulietApp/JulietApp.bff
@@ -80,6 +80,15 @@
}
.LinkerOptions + .CRTLibs
+ // Pointing the entry point
+ .SubSystem = ' /SUBSYSTEM:WINDOWS'
+ If ( .BuildConfigName == 'Debug' )
+ {
+ ^SubSystem = ' /SUBSYSTEM:WINDOWS' // We use console in debug
+
+ }
+ .LinkerOptions + .SubSystem
+
// Manifest
.LinkerAssemblyResources = .ManifestFile
.LinkerOptions + ' /MANIFEST:EMBED'
diff --git a/JulietApp/main.cpp b/JulietApp/main.cpp
index 8bfe4f1..be29479 100644
--- a/JulietApp/main.cpp
+++ b/JulietApp/main.cpp
@@ -9,6 +9,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -23,7 +24,6 @@
#include
#ifdef JULIET_ENABLE_IMGUI
-#include
#include
#endif
@@ -454,19 +454,8 @@ JulietApplication& GetEditorApplication()
return EditorApplication;
}
-int main(int /*argc*/, char** /*argv*/)
+int JulietMain(int, wchar_t**)
{
- // Allow only one instance to be launched.
- // Need to create Mutex code in the lib because i dont want to include windows.h in this file anymore
- // CreateMutex(0, false, L"Local\\Juliet.App");
- // if (GetLastError() == ERROR_ALREADY_EXISTS)
- // {
- // MessageBox(nullptr, L"An instance of Juliet is already running.", L"Juliet", MB_OK | MB_ICONEXCLAMATION);
- // return EXIT_FAILURE;
- // }
-
- setvbuf(stdout, nullptr, _IONBF, 0);
-
if (__argc > 1)
{
for (int i = 1; i < __argc; ++i)