dynamic map allocation in GameOfLife & created memory_arena.c

This commit is contained in:
Kaehvaman 2024-12-29 20:42:30 +04:00
parent 8471945a65
commit 84cb7fba0c
15 changed files with 697 additions and 19 deletions

View File

@ -122,6 +122,7 @@
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode> <ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(SolutionDir)\include</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>$(SolutionDir)\include</AdditionalIncludeDirectories>
<LanguageStandard_C>Default</LanguageStandard_C>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Console</SubSystem> <SubSystem>Console</SubSystem>
@ -133,11 +134,15 @@
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\include\raygui.h" />
<ClInclude Include="..\include\raylib.h" /> <ClInclude Include="..\include\raylib.h" />
<ClInclude Include="..\include\raymath.h" /> <ClInclude Include="..\include\raymath.h" />
<ClInclude Include="..\include\resource_dir.h" />
<ClInclude Include="..\include\tinyfiledialogs.h" /> <ClInclude Include="..\include\tinyfiledialogs.h" />
<ClInclude Include="..\src\game.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="..\src\game.c" />
<ClCompile Include="..\src\main.c" /> <ClCompile Include="..\src\main.c" />
<ClCompile Include="..\src\tinyfiledialogs.c" /> <ClCompile Include="..\src\tinyfiledialogs.c" />
</ItemGroup> </ItemGroup>

View File

@ -24,6 +24,15 @@
<ClInclude Include="..\include\raymath.h"> <ClInclude Include="..\include\raymath.h">
<Filter>Файлы заголовков</Filter> <Filter>Файлы заголовков</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\include\raygui.h">
<Filter>Файлы заголовков</Filter>
</ClInclude>
<ClInclude Include="..\include\resource_dir.h">
<Filter>Файлы заголовков</Filter>
</ClInclude>
<ClInclude Include="..\src\game.h">
<Filter>Файлы заголовков</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="..\src\main.c"> <ClCompile Include="..\src\main.c">
@ -32,5 +41,8 @@
<ClCompile Include="..\src\tinyfiledialogs.c"> <ClCompile Include="..\src\tinyfiledialogs.c">
<Filter>Исходные файлы</Filter> <Filter>Исходные файлы</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\src\game.c">
<Filter>Исходные файлы</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -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
/// <summary>
/// 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.
/// </summary>
/// <param name="folderName">The name of the resources dir to look for</param>
/// <returns>True if a dir with the name was found, false if no change was made to the working dir</returns>
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

Binary file not shown.

141
Game of Life/src/game.c Normal file
View File

@ -0,0 +1,141 @@
//#include "raylib.h"
//#include <iso646.h>
//
//#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);
// }
//}

0
Game of Life/src/game.h Normal file
View File

View File

@ -1,13 +1,19 @@
#define _CRT_SECURE_NO_WARNINGS
#include "raylib.h" #include "raylib.h"
#include "raymath.h" #include "raymath.h"
#include "resource_dir.h"
#include <stdbool.h> #include <stdbool.h>
#include <iso646.h> #include <iso646.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#define MAP_X 100 #define RAYGUI_IMPLEMENTATION
#define MAP_Y 50 #include "raygui.h"
#define CELL_SIZE 20
#define MAP_X 200
#define MAP_Y 100
#define CELL_SIZE 12
#define FCELL_SIZE (float)CELL_SIZE #define FCELL_SIZE (float)CELL_SIZE
#define BOTTOM_BAR_HEIGHT 60 #define BOTTOM_BAR_HEIGHT 60
@ -17,8 +23,31 @@
#define VSGREEN CLITERAL(Color){78, 201, 176, 255} #define VSGREEN CLITERAL(Color){78, 201, 176, 255}
#define WATERBLUE CLITERAL(Color){200, 240, 255, 255} #define WATERBLUE CLITERAL(Color){200, 240, 255, 255}
static bool map[MAP_X][MAP_Y] = { 0 }; //static bool map[MAP_X][MAP_Y] = { 0 };
static bool tempMap[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) { static inline int checkCell(int x, int y) {
if (x < 0 or y < 0 or x > MAP_X - 1 or y > MAP_Y - 1) { 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() void drawMap()
@ -89,16 +126,40 @@ void drawBottomBar()
DrawRectangle(0, MAP_Y * CELL_SIZE, MAP_X * CELL_SIZE, BOTTOM_BAR_HEIGHT, BLACKGRAY); DrawRectangle(0, MAP_Y * CELL_SIZE, MAP_X * CELL_SIZE, BOTTOM_BAR_HEIGHT, BLACKGRAY);
} }
#define CPSIZE 213
int main() 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 screenWidth = MAP_X * CELL_SIZE;
const int screenHeight = MAP_Y * CELL_SIZE + BOTTOM_BAR_HEIGHT; const int screenHeight = MAP_Y * CELL_SIZE + BOTTOM_BAR_HEIGHT;
SetConfigFlags(FLAG_VSYNC_HINT);
InitWindow(screenWidth, screenHeight, "Game of Life"); 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 }; Vector2 mousePos = { 0 };
int mouseCellX = 0; int mouseCellX = 0;
@ -107,14 +168,30 @@ int main()
bool editMap = true; bool editMap = true;
bool netToggle = false; bool netToggle = false;
float simSpeed = 1.0f;
int frameCounter = 0;
int guyScreenWidth = 720;
while (!WindowShouldClose()) while (!WindowShouldClose())
{ {
frameCounter++;
if (IsKeyPressed(KEY_SPACE)) { if (IsKeyPressed(KEY_SPACE)) {
editMap = !editMap; editMap = !editMap;
} }
if (IsKeyPressed(KEY_N)) { if (IsKeyPressed(KEY_N)) {
netToggle = !netToggle; netToggle = !netToggle;
} }
if (IsKeyPressed(KEY_EQUAL)) {
simSpeed *= 2.0f;
}
if (IsKeyPressed(KEY_MINUS)) {
simSpeed *= 0.5f;
}
if (IsKeyPressed(KEY_C)) {
ClearMap();
}
if (editMap) if (editMap)
{ {
@ -129,12 +206,23 @@ int main()
map[mouseCellX][mouseCellY] = false; map[mouseCellX][mouseCellY] = false;
} }
} }
else { else if (FloatEquals(simSpeed, 1.0f)) {
celluralAutomata(); 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(); BeginDrawing();
ClearBackground(RAYWHITE); ClearBackground(WHITE);
drawMap(); drawMap();
drawBottomBar(); drawBottomBar();
@ -143,21 +231,29 @@ int main()
if (editMap) if (editMap)
{ {
Rectangle rec = { Rectangle rec = { mouseCellX * FCELL_SIZE, mouseCellY * FCELL_SIZE, FCELL_SIZE, FCELL_SIZE };
mouseCellX * FCELL_SIZE,
mouseCellY * FCELL_SIZE,
FCELL_SIZE, FCELL_SIZE
};
DrawRectangleLinesEx(rec, 2, GREEN); 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(); EndDrawing();
} }
/*for (int x = 0; x < MAP_X; x++) {
free(map[x]);
}
free(map);*/
UnloadFont(InconsolataBold);
CloseWindow(); CloseWindow();
return 0; return 0;

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

View File

@ -17,7 +17,7 @@
#define RAYLIB_NUKLEAR_IMPLEMENTATION #define RAYLIB_NUKLEAR_IMPLEMENTATION
#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT #define NK_INCLUDE_VERTEX_BUFFER_OUTPUT
//#define RAYLIB_NUKLEAR_DEFAULT_ARC_SEGMENTS 1 //#define RAYLIB_NUKLEAR_DEFAULT_ARC_SEGMENTS 1
#pragma warning(disable: 4116) //#pragma warning(disable: 4116)
#include "raylib-nuklear.h" #include "raylib-nuklear.h"
Vector2 scaleDPI = { 1.0f, 1.0f }; Vector2 scaleDPI = { 1.0f, 1.0f };
@ -281,6 +281,7 @@ void load() {
"Ошибка загрузки", "Ошибка загрузки",
MB_ICONERROR MB_ICONERROR
);*/ );*/
tinyfd_messageBox( tinyfd_messageBox(
u8"Ошибка сохранения", u8"Ошибка сохранения",
u8"Невозможно создать файл\nПроверьте целостность сохранения", u8"Невозможно создать файл\nПроверьте целостность сохранения",
@ -566,6 +567,11 @@ int main()
int blur13direction = GetShaderLocation(blur13, "direction"); int blur13direction = GetShaderLocation(blur13, "direction");
SetShaderValue(blur13, blur13resolution, &resolution, SHADER_UNIFORM_VEC2); 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); GuiSetFont(InconsolataBold);
GuiSetStyle(DEFAULT, TEXT_SIZE, (int)(24 * scaleDPI.x)); GuiSetStyle(DEFAULT, TEXT_SIZE, (int)(24 * scaleDPI.x));
GuiSetStyle(DEFAULT, TEXT_SPACING, 0); GuiSetStyle(DEFAULT, TEXT_SPACING, 0);
@ -674,10 +680,12 @@ int main()
SetShaderValue(watershader, watershaderSecondsLoc, &timeF, SHADER_UNIFORM_FLOAT); SetShaderValue(watershader, watershaderSecondsLoc, &timeF, SHADER_UNIFORM_FLOAT);
Rectangle rec = { 0, 0, (float)canvas.texture.width, (float)(-canvas.texture.height) }; Rectangle rec = { 0, 0, (float)canvas.texture.width, (float)(-canvas.texture.height) };
Rectangle rec1 = { 0, 0, screenWidthF, screenHeightF };
BeginShaderMode(watershader); BeginShaderMode(watershader);
{ {
SetShaderValueTexture(watershader, waterBumpMapLoc, waterBump); SetShaderValueTexture(watershader, waterBumpMapLoc, waterBump);
DrawTextureRec(canvas.texture, rec, (Vector2) { 0.0f, 0.0f }, WHITE); DrawTextureRec(canvas.texture, rec, (Vector2) { 0.0f, 0.0f }, WHITE);
//DrawTextureRec(baroTextrue, rec1, (Vector2) { 0.0f, 0.0f }, WHITE);
} }
EndShaderMode(); EndShaderMode();
@ -732,10 +740,15 @@ int main()
//UnloadFont(InconsolataBold); //UnloadFont(InconsolataBold);
UnloadRenderTexture(canvas); UnloadRenderTexture(canvas);
UnloadRenderTexture(canvasBlurX);
UnloadShader(blur); UnloadShader(blur);
UnloadShader(blur13);
UnloadShader(watershader); UnloadShader(watershader);
UnloadTexture(waterBump); UnloadTexture(waterBump);
UnloadImage(baroImage);
UnloadTexture(baroTextrue);
// De-initialize the Nuklear GUI // De-initialize the Nuklear GUI
UnloadNuklear(ctx); UnloadNuklear(ctx);

View File

@ -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

View File

@ -0,0 +1,139 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>17.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{f0089bfd-617e-4271-a571-06ca4fc43a22}</ProjectGuid>
<RootNamespace>memoryarena</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\src\main.c" />
<ClCompile Include="..\src\memory_arena.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\src\memory_arena.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Исходные файлы">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Файлы заголовков">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Файлы ресурсов">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\memory_arena.c">
<Filter>Исходные файлы</Filter>
</ClCompile>
<ClCompile Include="..\src\main.c">
<Filter>Исходные файлы</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\src\memory_arena.h">
<Filter>Файлы заголовков</Filter>
</ClInclude>
</ItemGroup>
</Project>

35
memory_arena/src/main.c Normal file
View File

@ -0,0 +1,35 @@
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#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;
}

View File

@ -0,0 +1,64 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>
#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 };
}

View File

@ -0,0 +1,20 @@
#pragma once
#include <stdint.h>
#include <stddef.h>
#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);