diff --git a/Game of Life/Game of Life/Game of Life.vcxproj b/Game of Life/Game of Life/Game of Life.vcxproj index ee714ae..166cc1d 100644 --- a/Game of Life/Game of Life/Game of Life.vcxproj +++ b/Game of Life/Game of Life/Game of Life.vcxproj @@ -122,6 +122,7 @@ NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true $(SolutionDir)\include + Default Console @@ -133,11 +134,15 @@ + + + + diff --git a/Game of Life/Game of Life/Game of Life.vcxproj.filters b/Game of Life/Game of Life/Game of Life.vcxproj.filters index e0d929c..983ee57 100644 --- a/Game of Life/Game of Life/Game of Life.vcxproj.filters +++ b/Game of Life/Game of Life/Game of Life.vcxproj.filters @@ -24,6 +24,15 @@ Файлы заголовков + + Файлы заголовков + + + Файлы заголовков + + + Файлы заголовков + @@ -32,5 +41,8 @@ Исходные файлы + + Исходные файлы + \ No newline at end of file diff --git a/Game of Life/include/resource_dir.h b/Game of Life/include/resource_dir.h new file mode 100644 index 0000000..65096f0 --- /dev/null +++ b/Game of Life/include/resource_dir.h @@ -0,0 +1,95 @@ +/********************************************************************************************** +* +* raylibExtras * Utilities and Shared Components for Raylib +* +* Resource Dir * function to help find resource dir in common locations +* +* LICENSE: MIT +* +* Copyright (c) 2022 Jeffery Myers +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all +* copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +**********************************************************************************************/ + +#pragma once + +#include "raylib.h" + +#if defined(__cplusplus) +extern "C" { // Prevents name mangling of functions +#endif + /// + /// Looks for the specified resource dir in several common locations + /// The working dir + /// The app dir + /// Up to 3 levels above the app dir + /// When found the dir will be set as the working dir so that assets can be loaded relative to that. + /// + /// The name of the resources dir to look for + /// True if a dir with the name was found, false if no change was made to the working dir + inline static bool SearchAndSetResourceDir(const char* folderName) + { + // check the working dir + if (DirectoryExists(folderName)) + { + ChangeDirectory(TextFormat("%s/%s", GetWorkingDirectory(), folderName)); + return true; + } + + const char* appDir = GetApplicationDirectory(); + + // check the applicationDir + const char* dir = TextFormat("%s%s", appDir, folderName); + if (DirectoryExists(dir)) + { + ChangeDirectory(dir); + return true; + } + + // check one up from the app dir + dir = TextFormat("%s../%s", appDir, folderName); + if (DirectoryExists(dir)) + { + ChangeDirectory(dir); + return true; + } + + // check two up from the app dir + dir = TextFormat("%s../../%s", appDir, folderName); + if (DirectoryExists(dir)) + { + ChangeDirectory(dir); + return true; + } + + // check three up from the app dir + dir = TextFormat("%s../../../%s", appDir, folderName); + if (DirectoryExists(dir)) + { + ChangeDirectory(dir); + return true; + } + + return false; + } + +#if defined(__cplusplus) +} +#endif \ No newline at end of file diff --git a/Game of Life/lib/raylib.lib b/Game of Life/lib/raylib.lib index 736bdec..77a853a 100644 Binary files a/Game of Life/lib/raylib.lib and b/Game of Life/lib/raylib.lib differ diff --git a/Game of Life/src/game.c b/Game of Life/src/game.c new file mode 100644 index 0000000..9d243c1 --- /dev/null +++ b/Game of Life/src/game.c @@ -0,0 +1,141 @@ +//#include "raylib.h" +//#include +// +//#include "game.h" +// +//#define PUREBLUE CLITERAL(Color){ 0, 0, 255, 255 } +//#define BLACKGRAY CLITERAL(Color){30, 30, 30, 255} +//#define VSGREEN CLITERAL(Color){78, 201, 176, 255} +//#define WATERBLUE CLITERAL(Color){200, 240, 255, 255} +// +// +//static float simSpeed = 1.0f; +//static frameCounter = 0; +// +//static Vector2 mousePos = { 0 }; +//static int mouseCellX = 0; +//static int mouseCellY = 0; +// +//static bool editMap = true; +//static bool netToggle = true; +// +//static inline int CheckCell(int x, int y) { +// if (x < 0 or y < 0 or x > MAP_X - 1 or y > MAP_Y - 1) { +// return 0; +// } +// else { +// return map[x][y]; +// } +//} +// +//static void GameOfLife() +//{ +// for (int x = 0; x < MAP_X; x++) { +// for (int y = 0; y < MAP_Y; y++) { +// int neighbours = 0; +// +// neighbours += CheckCell(x - 1, y); +// neighbours += CheckCell(x - 1, y + 1); +// neighbours += CheckCell(x - 1, y - 1); +// neighbours += CheckCell(x + 1, y); +// neighbours += CheckCell(x + 1, y + 1); +// neighbours += CheckCell(x + 1, y - 1); +// neighbours += CheckCell(x, y + 1); +// neighbours += CheckCell(x, y - 1); +// +// if (neighbours == 3) { +// tempMap[x][y] = true; +// } +// else if (neighbours == 2) { +// tempMap[x][y] = map[x][y]; +// } +// else { +// tempMap[x][y] = false; +// } +// +// } +// } +// memcpy(map, tempMap, MAP_X * MAP_Y * sizeof(bool)); +//} +// +//static void DrawMap() +//{ +// for (int x = 0; x < MAP_X; x++) { +// for (int y = 0; y < MAP_Y; y++) { +// if (map[x][y]) { +// int posX = x * CELL_SIZE; +// int posY = y * CELL_SIZE; +// DrawRectangle(posX, posY, CELL_SIZE, CELL_SIZE, BLACK); +// } +// } +// } +//} +// +//static void DrawNet() { +// for (int i = 0; i <= MAP_X * CELL_SIZE; i += CELL_SIZE) { +// DrawLine(i, 0, i, MAP_Y * CELL_SIZE, GRAY); +// DrawLine(i + 1, 0, i + 1, MAP_Y * CELL_SIZE, GRAY); +// } +// +// for (int i = 0; i <= MAP_Y * CELL_SIZE; i += CELL_SIZE) { +// DrawLine(0, i, MAP_X * CELL_SIZE, i, GRAY); +// DrawLine(0, i - 1, MAP_X * CELL_SIZE, i - 1, GRAY); +// } +//} +// +//void UpdateGame() { +// frameCounter++; +// +// if (IsKeyPressed(KEY_SPACE)) { +// editMap = !editMap; +// } +// if (IsKeyPressed(KEY_N)) { +// netToggle = !netToggle; +// } +// if (IsKeyPressed(KEY_EQUAL)) { +// simSpeed *= 2.0f; +// } +// if (IsKeyPressed(KEY_MINUS)) { +// simSpeed *= 0.5f; +// } +// +// if (editMap) +// { +// mousePos = GetMousePosition(); +// mouseCellX = (int)(Clamp(mousePos.x, 0, (float)(MAP_X * CELL_SIZE - 1)) / CELL_SIZE); +// mouseCellY = (int)(Clamp(mousePos.y, 0, (float)(MAP_Y * CELL_SIZE - 1)) / CELL_SIZE); +// +// if (IsMouseButtonDown(MOUSE_BUTTON_LEFT)) { +// map[mouseCellX][mouseCellY] = true; +// } +// else if (IsMouseButtonDown(MOUSE_BUTTON_RIGHT)) { +// map[mouseCellX][mouseCellY] = false; +// } +// } +// else if (FloatEquals(simSpeed, 1.0f)) { +// celluralAutomata(); +// } +// else if (simSpeed < 1.0f and frameCounter >= 1 / simSpeed) { +// celluralAutomata(); +// //printf("%d %d\n", frameCounter, (int)(1 / simSpeed)); +// frameCounter = 0; +// } +// else if (simSpeed > 1.0f) { +// for (int i = 0; i < (int)simSpeed; i++) { +// celluralAutomata(); +// } +// //printf("%f speed\n", simSpeed); +// } +//} +// +//void DrawGame() { +// DrawMap(); +// +// if (netToggle) DrawNet(); +// +// if (editMap) +// { +// Rectangle rec = { mouseCellX * FCELL_SIZE, mouseCellY * FCELL_SIZE, FCELL_SIZE, FCELL_SIZE }; +// DrawRectangleLinesEx(rec, 2, GREEN); +// } +//} \ No newline at end of file diff --git a/Game of Life/src/game.h b/Game of Life/src/game.h new file mode 100644 index 0000000..e69de29 diff --git a/Game of Life/src/main.c b/Game of Life/src/main.c index 966db86..2d204f4 100644 --- a/Game of Life/src/main.c +++ b/Game of Life/src/main.c @@ -1,13 +1,19 @@ +#define _CRT_SECURE_NO_WARNINGS + #include "raylib.h" #include "raymath.h" +#include "resource_dir.h" #include #include #include #include -#define MAP_X 100 -#define MAP_Y 50 -#define CELL_SIZE 20 +#define RAYGUI_IMPLEMENTATION +#include "raygui.h" + +#define MAP_X 200 +#define MAP_Y 100 +#define CELL_SIZE 12 #define FCELL_SIZE (float)CELL_SIZE #define BOTTOM_BAR_HEIGHT 60 @@ -17,8 +23,31 @@ #define VSGREEN CLITERAL(Color){78, 201, 176, 255} #define WATERBLUE CLITERAL(Color){200, 240, 255, 255} -static bool map[MAP_X][MAP_Y] = { 0 }; -static bool tempMap[MAP_X][MAP_Y] = { 0 }; +//static bool map[MAP_X][MAP_Y] = { 0 }; +//static bool tempMap[MAP_X][MAP_Y] = { 0 }; + +bool** map; +bool** tempMap; + +void* SafeMalloc(size_t size) +{ + void* buffer = malloc(size); + if (buffer == NULL) { + fprintf(stderr, "Fatal: failed to allocate %zu bytes.\n", size); + abort(); + } + return buffer; +} + +void* SafeCalloc(size_t count, size_t size) +{ + void* buffer = calloc(count, size); + if (buffer == NULL) { + fprintf(stderr, "Fatal: failed to allocate %zu bytes.\n", count * size); + abort(); + } + return buffer; +} static inline int checkCell(int x, int y) { if (x < 0 or y < 0 or x > MAP_X - 1 or y > MAP_Y - 1) { @@ -56,7 +85,15 @@ void celluralAutomata() } } - memcpy(map, tempMap, MAP_X * MAP_Y * sizeof(bool)); + for (int x = 0; x < MAP_X; x++) { + memcpy(map[x], tempMap[x], MAP_Y * sizeof(bool)); + } +} + +void ClearMap() { + for (int x = 0; x < MAP_X; x++) { + memset(map[x], 0, MAP_Y * sizeof(bool)); + } } void drawMap() @@ -89,16 +126,40 @@ void drawBottomBar() DrawRectangle(0, MAP_Y * CELL_SIZE, MAP_X * CELL_SIZE, BOTTOM_BAR_HEIGHT, BLACKGRAY); } +#define CPSIZE 213 int main() { + map = (bool**)SafeMalloc(MAP_X * sizeof(bool*)); + tempMap = (bool**)SafeMalloc(MAP_X * sizeof(bool*)); + for (int x = 0; x < MAP_X; x++) { + map[x] = (bool*)SafeCalloc(MAP_Y, sizeof(bool)); + tempMap[x] = (bool*)SafeCalloc(MAP_Y, sizeof(bool)); + } + const int screenWidth = MAP_X * CELL_SIZE; const int screenHeight = MAP_Y * CELL_SIZE + BOTTOM_BAR_HEIGHT; - SetConfigFlags(FLAG_VSYNC_HINT); - InitWindow(screenWidth, screenHeight, "Game of Life"); - //SetTargetFPS(60); + SearchAndSetResourceDir("resources"); + + int codepoints[CPSIZE] = { 0 }; + for (int i = 0; i < 127 - 32; i++) codepoints[i] = 32 + i; // Basic ASCII characters + for (int i = 0; i < 118; i++) codepoints[95 + i] = 1024 + i; // Cyrillic characters + + Font InconsolataBold = LoadFontEx("Inconsolata-LGC-Bold.ttf", 36, codepoints, CPSIZE); + SetTextureFilter(InconsolataBold.texture, TEXTURE_FILTER_BILINEAR); + + GuiSetFont(InconsolataBold); + GuiSetStyle(DEFAULT, TEXT_SIZE, (int)(24)); + GuiSetStyle(DEFAULT, TEXT_SPACING, 0); + GuiSetStyle(DEFAULT, TEXT_LINE_SPACING, (int)(24)); + GuiSetStyle(STATUSBAR, BORDER_WIDTH, 2); + + int monitor = GetCurrentMonitor(); + int monitorFPS = GetMonitorRefreshRate(monitor); + + SetTargetFPS(monitorFPS); Vector2 mousePos = { 0 }; int mouseCellX = 0; @@ -107,14 +168,30 @@ int main() bool editMap = true; bool netToggle = false; + float simSpeed = 1.0f; + int frameCounter = 0; + + int guyScreenWidth = 720; + while (!WindowShouldClose()) { + frameCounter++; + if (IsKeyPressed(KEY_SPACE)) { editMap = !editMap; } if (IsKeyPressed(KEY_N)) { netToggle = !netToggle; } + if (IsKeyPressed(KEY_EQUAL)) { + simSpeed *= 2.0f; + } + if (IsKeyPressed(KEY_MINUS)) { + simSpeed *= 0.5f; + } + if (IsKeyPressed(KEY_C)) { + ClearMap(); + } if (editMap) { @@ -129,12 +206,23 @@ int main() map[mouseCellX][mouseCellY] = false; } } - else { + else if (FloatEquals(simSpeed, 1.0f)) { celluralAutomata(); } + else if (simSpeed < 1.0f and frameCounter >= 1 / simSpeed) { + celluralAutomata(); + //printf("%d %d\n", frameCounter, (int)(1 / simSpeed)); + frameCounter = 0; + } + else if (simSpeed > 1.0f) { + for (int i = 0; i < (int)simSpeed; i++) { + celluralAutomata(); + } + //printf("%f speed\n", simSpeed); + } BeginDrawing(); - ClearBackground(RAYWHITE); + ClearBackground(WHITE); drawMap(); drawBottomBar(); @@ -143,21 +231,29 @@ int main() if (editMap) { - Rectangle rec = { - mouseCellX * FCELL_SIZE, - mouseCellY * FCELL_SIZE, - FCELL_SIZE, FCELL_SIZE - }; - + Rectangle rec = { mouseCellX * FCELL_SIZE, mouseCellY * FCELL_SIZE, FCELL_SIZE, FCELL_SIZE }; DrawRectangleLinesEx(rec, 2, GREEN); } + //Rectangle settingsBox = { 400, 400, 400, 200 }; + //GuiGroupBox(settingsBox, u8"Init game"); + //Rectangle valueBox1 = { 620, 420, 100, 40 }; + //GuiValueBox(valueBox1, u8"screen Width ", &guyScreenWidth, 120, 2560, true); - DrawFPS(0, 0); + DrawFPS(0, MAP_Y * CELL_SIZE); + DrawText(TextFormat("%.4fx", simSpeed), 0, MAP_Y * CELL_SIZE + 20, 20, ORANGE); + DrawText(TextFormat("%.1f TPS", monitorFPS * simSpeed), 0, MAP_Y * CELL_SIZE + 40, 20, BLUE); EndDrawing(); } + /*for (int x = 0; x < MAP_X; x++) { + free(map[x]); + } + free(map);*/ + + UnloadFont(InconsolataBold); + CloseWindow(); return 0; diff --git a/lab16 with raylib/resources/screenshot1.jpg b/lab16 with raylib/resources/screenshot1.jpg new file mode 100644 index 0000000..7b239dd Binary files /dev/null and b/lab16 with raylib/resources/screenshot1.jpg differ diff --git a/lab16 with raylib/src/main.c b/lab16 with raylib/src/main.c index 3751d8a..ee117e9 100644 --- a/lab16 with raylib/src/main.c +++ b/lab16 with raylib/src/main.c @@ -17,7 +17,7 @@ #define RAYLIB_NUKLEAR_IMPLEMENTATION #define NK_INCLUDE_VERTEX_BUFFER_OUTPUT //#define RAYLIB_NUKLEAR_DEFAULT_ARC_SEGMENTS 1 -#pragma warning(disable: 4116) +//#pragma warning(disable: 4116) #include "raylib-nuklear.h" Vector2 scaleDPI = { 1.0f, 1.0f }; @@ -281,6 +281,7 @@ void load() { "Ошибка загрузки", MB_ICONERROR );*/ + tinyfd_messageBox( u8"Ошибка сохранения", u8"Невозможно создать файл\nПроверьте целостность сохранения", @@ -566,6 +567,11 @@ int main() int blur13direction = GetShaderLocation(blur13, "direction"); SetShaderValue(blur13, blur13resolution, &resolution, SHADER_UNIFORM_VEC2); + Image baroImage = LoadImage("screenshot1.jpg"); + ImageResize(&baroImage, screenWidth, screenHeight); + Texture baroTextrue = LoadTextureFromImage(baroImage); + SetTextureFilter(baroTextrue, TEXTURE_FILTER_BILINEAR); + GuiSetFont(InconsolataBold); GuiSetStyle(DEFAULT, TEXT_SIZE, (int)(24 * scaleDPI.x)); GuiSetStyle(DEFAULT, TEXT_SPACING, 0); @@ -674,10 +680,12 @@ int main() SetShaderValue(watershader, watershaderSecondsLoc, &timeF, SHADER_UNIFORM_FLOAT); Rectangle rec = { 0, 0, (float)canvas.texture.width, (float)(-canvas.texture.height) }; + Rectangle rec1 = { 0, 0, screenWidthF, screenHeightF }; BeginShaderMode(watershader); { SetShaderValueTexture(watershader, waterBumpMapLoc, waterBump); DrawTextureRec(canvas.texture, rec, (Vector2) { 0.0f, 0.0f }, WHITE); + //DrawTextureRec(baroTextrue, rec1, (Vector2) { 0.0f, 0.0f }, WHITE); } EndShaderMode(); @@ -732,10 +740,15 @@ int main() //UnloadFont(InconsolataBold); UnloadRenderTexture(canvas); + UnloadRenderTexture(canvasBlurX); UnloadShader(blur); + UnloadShader(blur13); UnloadShader(watershader); UnloadTexture(waterBump); + + UnloadImage(baroImage); + UnloadTexture(baroTextrue); // De-initialize the Nuklear GUI UnloadNuklear(ctx); diff --git a/memory_arena/memory_arena.sln b/memory_arena/memory_arena.sln new file mode 100644 index 0000000..126bdb5 --- /dev/null +++ b/memory_arena/memory_arena.sln @@ -0,0 +1,28 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.12.35527.113 d17.12 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "memory_arena", "memory_arena\memory_arena.vcxproj", "{F0089BFD-617E-4271-A571-06CA4FC43A22}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F0089BFD-617E-4271-A571-06CA4FC43A22}.Debug|x64.ActiveCfg = Debug|x64 + {F0089BFD-617E-4271-A571-06CA4FC43A22}.Debug|x64.Build.0 = Debug|x64 + {F0089BFD-617E-4271-A571-06CA4FC43A22}.Debug|x86.ActiveCfg = Debug|Win32 + {F0089BFD-617E-4271-A571-06CA4FC43A22}.Debug|x86.Build.0 = Debug|Win32 + {F0089BFD-617E-4271-A571-06CA4FC43A22}.Release|x64.ActiveCfg = Release|x64 + {F0089BFD-617E-4271-A571-06CA4FC43A22}.Release|x64.Build.0 = Release|x64 + {F0089BFD-617E-4271-A571-06CA4FC43A22}.Release|x86.ActiveCfg = Release|Win32 + {F0089BFD-617E-4271-A571-06CA4FC43A22}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/memory_arena/memory_arena/memory_arena.vcxproj b/memory_arena/memory_arena/memory_arena.vcxproj new file mode 100644 index 0000000..6bb2ce6 --- /dev/null +++ b/memory_arena/memory_arena/memory_arena.vcxproj @@ -0,0 +1,139 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 17.0 + Win32Proj + {f0089bfd-617e-4271-a571-06ca4fc43a22} + memoryarena + 10.0 + + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + + + + + + + + + \ No newline at end of file diff --git a/memory_arena/memory_arena/memory_arena.vcxproj.filters b/memory_arena/memory_arena/memory_arena.vcxproj.filters new file mode 100644 index 0000000..3944ec1 --- /dev/null +++ b/memory_arena/memory_arena/memory_arena.vcxproj.filters @@ -0,0 +1,30 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Исходные файлы + + + Исходные файлы + + + + + Файлы заголовков + + + \ No newline at end of file diff --git a/memory_arena/src/main.c b/memory_arena/src/main.c new file mode 100644 index 0000000..41092c2 --- /dev/null +++ b/memory_arena/src/main.c @@ -0,0 +1,35 @@ +#define _CRT_SECURE_NO_WARNINGS + +#include +#include + +#include "memory_arena.h" + + +int main() { + + Arena arena = ArenaInit(1024 * 1024); + + char* str1 = ArenaAllocAligned(&arena, 5, sizeof(char)); + strcpy(str1, "Hell"); + printf("%s\n", str1); + + + int* int2 = ArenaAllocAligned(&arena, 2 * sizeof(int), sizeof(int)); + int2[0] = 123; + int2[1] = 789; + printf("%d %d\n\n", int2[0], int2[1]); + + for (int i = 0; i < 16; i++) { + printf("%d) %d\n", i, *((char*)(arena.buffer) + i)); + } + + scanf("%s", str1); + + /*char* str3 = ArenaAllocAligned(&arena, 8, sizeof(char)); + strcpy(str3, "ByeBye!!"); + printf("%s", str3);*/ + + + return 0; +} \ No newline at end of file diff --git a/memory_arena/src/memory_arena.c b/memory_arena/src/memory_arena.c new file mode 100644 index 0000000..dd04141 --- /dev/null +++ b/memory_arena/src/memory_arena.c @@ -0,0 +1,64 @@ +#include +#include +#include +#include + +#include "memory_arena.h" + +static void* SafeMalloc(size_t size) +{ + void* buffer = malloc(size); + if (buffer == NULL) { + fprintf(stderr, "\nError in SafeMalloc: failed to allocate %zu bytes.\n", size); + abort(); + } + return buffer; +} + +static bool is_power_of_two(uintptr_t x) { + return (x & (x - 1)) == 0; +} + +static uintptr_t AlignForward(uintptr_t ptr, size_t alignment) { + uintptr_t p, a, modulo; + + assert(is_power_of_two(alignment)); + + p = ptr; + a = (uintptr_t)alignment; + // Same as (p % a) but faster as 'a' is a power of two + modulo = p & (a - 1); + + if (modulo != 0) { + // If 'p' address is not aligned, push the address to the + // next value which is aligned + p += a - modulo; + } + return p; +} + +void* ArenaAllocAligned(Arena* arena, size_t size, size_t alignment) +{ + uintptr_t aligned_offset_ptr = AlignForward(arena->offset_ptr, alignment); + uintptr_t next_offset_ptr = aligned_offset_ptr + size; + + if (next_offset_ptr - (uintptr_t)arena->buffer <= arena->size) + { + arena->offset_ptr = next_offset_ptr; + return (void*)aligned_offset_ptr; + } + + fprintf(stderr, "\nError in ArenaAllocAligned: reached arena end.\n"); + abort(); +} + +void* ArenaAlloc(Arena* arena, size_t size) +{ + return ArenaAllocAligned(arena, size, DEFAULT_ALIGNMENT); +} + +Arena ArenaInit(size_t buffer_size) +{ + void* buffer = SafeMalloc(buffer_size); + return (Arena) { buffer, buffer_size, (uintptr_t)buffer }; +} \ No newline at end of file diff --git a/memory_arena/src/memory_arena.h b/memory_arena/src/memory_arena.h new file mode 100644 index 0000000..d12b88e --- /dev/null +++ b/memory_arena/src/memory_arena.h @@ -0,0 +1,20 @@ +#pragma once + +#include +#include + +#define ARENA_ALIGNMENT(type) offsetof(struct { char c; type x; }, x) // generates C4116 warning + +#ifndef DEFAULT_ALIGNMENT +#define DEFAULT_ALIGNMENT (2 * sizeof(void*)) +#endif + +typedef struct { + void* buffer; + size_t size; + uintptr_t offset_ptr; +} Arena; + +Arena ArenaInit(size_t buffer_size); +void* ArenaAlloc(Arena* arena, size_t size); +void* ArenaAllocAligned(Arena* arena, size_t size, size_t alignment);