Compare commits

...
6 Commits
Author SHA1 Message Date
tobid7 dac78d9c82 yet another memory debugger fix 2026-01-11 16:12:47 +01:00
tobid7 a16bce419d Add safe Memory Freeing
(cause in some cases random crashes could happen)
2026-01-10 12:58:04 +01:00
tobid7 bed24ff28a Add Memory debugger 2026-01-04 18:02:45 +01:00
tobid7 1acecd03ee Merge branch 'main' of github.com:tobid7/amethyst 2026-01-01 21:37:05 +01:00
tobid7 99b330b136 # Compile time hexcolor support ported from palladium 2026-01-01 21:36:15 +01:00
tobid7 5e5907ed30 Rename to DrawFromAtlas 2025-12-31 10:30:20 +01:00
11 changed files with 182 additions and 60 deletions
+9 -9
View File
@@ -7,9 +7,8 @@ set(CMAKE_CXX_STANDARD_REQUIRED true)
option(AMY_GOD_DEV "Turn this on if you think you are god" OFF)
# THis option should be disabled if you use STB_IMAGE in you main project
set(AMY_BUILD_STB_IMAGE 0)
set(AMY_BUILD_STB_TRUETYPE 1)
set(AMY_WITH_MPG123 "Include MP3 Support" CACHE BOOL 1)
option(AMY_BUILD_STB_IMAGE ON)
option(AMY_BUILD_STB_TRUETYPE ON)
add_subdirectory(vendor/libpicasso)
@@ -38,12 +37,13 @@ target_include_directories(${PROJECT_NAME} PRIVATE
)
target_link_libraries(${PROJECT_NAME} PUBLIC pica::pica)
target_link_libraries(${PROJECT_NAME} PUBLIC m z ctru citro3d mpg123)
target_compile_definitions(${PROJECT_NAME} PUBLIC
AMY_3DS
AMY_STB_IMAGE=${AMY_BUILD_STB_IMAGE}
AMY_STB_TT=${AMY_BUILD_STB_TRUETYPE}
AMY_WITH_MPG123=${AMY_WITH_MPG123}
)
if(${AMY_BUILD_STB_IMAGE})
target_compile_definitions(${PROJECT_NAME} PUBLIC AMY_STB_IMAGE)
endif()
if(${AMY_BUILD_STB_TRUETYPE})
target_compile_definitions(${PROJECT_NAME} PUBLIC AMY_STB_TT)
endif()
target_compile_options(${PROJECT_NAME} PUBLIC -Wno-psabi)
add_subdirectory(example)
-1
View File
@@ -51,7 +51,6 @@ class Example : public Amy::App {
Top->Use();
dl->DrawTex(Mgr->Get<Amy::Texture>("icon"));
dl->DrawRectFilled(Amy::fvec2(50, 0), 48, Amy::Color(255, 255, 255, 160));
// Color only at runtime...yet (Palladium 0.6.0 dev is targeting this)
dl->DrawCircleFilled(Amy::fvec2(200, 120), 50, Amy::Color("#ffffff"), 40);
dl->DrawSolid();
dl->DrawRectFilled(0, 50, Amy::Color(0.f, 1.f, 0.f, 1.f));
+18 -1
View File
@@ -10,10 +10,27 @@
#include <amethyst/renderer.hpp>
#include <amethyst/texture.hpp>
#include <amethyst/utils.hpp>
#include <atomic>
namespace Amy {
void RegisterCxxExceptionHandler();
}
void* Malloc(size_t size);
void Free(void* ptr);
namespace Memory {
struct MemMetrics {
std::atomic<ull> Allocated = 0; ///< Total Allocated Memory
std::atomic<ull> Current = 0; ///< Current Allocated Memory
std::atomic<ull> Deleted = 0; ///< Total Deleted Memory
std::atomic<ull> Allocations = 0; ///< Current Allocations count
/// @brief Gets the Currently Allocated Memory
ull CurrentlyAllocated() { return Current; }
};
ull GetTotalAllocated();
ull GetTotalFreed();
ull GetCurrent();
ull GetAllocationCount();
} // namespace Memory
} // namespace Amy
using Iron = Amy::Iron;
using C3D = Amy::C3D;
+16 -2
View File
@@ -1,6 +1,7 @@
#pragma once
#include <amethyst/types.hpp>
#include <amethyst/utils.hpp>
// We all know where the code is from ... RenderD7 -> Palladium/Amy
@@ -47,14 +48,27 @@ class Color {
* Constructor for Hex Input
* @param hex Hex String in `#ffffff` or `#ffffffff` format
*/
Color(const std::string& hex) { Hex(hex); }
constexpr Color(const std::string& hex) { Hex(hex); }
/**
* Create Color Object by Hex String
* @param hex Hex String in `#ffffff` or `#ffffffff` format
* @return Color class itself
*/
Color& Hex(const std::string& hex);
constexpr Color& Hex(const std::string& hex) {
if (!(hex.length() == 7 || hex.length() == 9)) {
throw "[PD] Color: hex string is not rgb or rgba!";
}
r = Utils::HexChar2Int(hex[1]) * 16 + Utils::HexChar2Int(hex[2]);
g = Utils::HexChar2Int(hex[3]) * 16 + Utils::HexChar2Int(hex[4]);
b = Utils::HexChar2Int(hex[5]) * 16 + Utils::HexChar2Int(hex[6]);
if (hex.length() == 9) {
a = Utils::HexChar2Int(hex[7]) * 16 + Utils::HexChar2Int(hex[8]);
} else {
a = 255;
}
return *this;
}
/**
* Convert this Color Object to Hex string
* @param rgba [default false] sets if 8 or 6 digit color should be returned
+3 -3
View File
@@ -122,12 +122,12 @@ class Iron {
void DrawSolid();
void DrawTex(Texture::Ref tex) { pTex = tex; }
void DrawCutTex(fvec2 pos, fvec2 size, fvec4 cut_rect,
void DrawFromAtlas(fvec2 pos, fvec2 size, fvec4 cut_rect,
ui color = 0xffffffff);
void DrawCutTex(fvec2 pos, fvec2 size, fvec4 cut_rect, Texture::Ref tex,
void DrawFromAtlas(fvec2 pos, fvec2 size, fvec4 cut_rect, Texture::Ref tex,
ui color = 0xffffffff) {
DrawTex(tex);
DrawCutTex(pos, size, cut_rect, color);
DrawFromAtlas(pos, size, cut_rect, color);
DrawSolid();
}
void SetFont(Font::Ref fnt) { pCurrentFont = fnt; }
+7
View File
@@ -8,6 +8,13 @@ class Error : public std::runtime_error {
Error(ksr str) : std::runtime_error("[amy] " + str) {}
};
namespace Utils {
constexpr int HexChar2Int(char c) {
/** Imagine man hat ne lookup table dafür verwendet :/ */
if (c >= '0' && c <= '9') return c - '0';
if (c >= 'a' && c <= 'f') return 10 + (c - 'a');
if (c >= 'A' && c <= 'F') return 10 + (c - 'A');
return -1; // Error
}
vec<uc> LoadFile2Mem(ksr path);
str FormatBytes(ull bytes);
ui HashMemory(kvr<uc> data);
+120 -1
View File
@@ -1,6 +1,10 @@
#include <amethyst.hpp>
#include <exception>
#include <iostream>
#include <map>
#include <vector>
#define TRACK_NEW_DELETE
#ifdef AMY_3DS
#include <3ds.h>
@@ -11,7 +15,7 @@ void NpiD7CxxExceptionHandler() {
std::cout << "[C++ Error Handler]" << std::endl;
try {
std::rethrow_exception(std::current_exception());
} catch (const std::exception& e) {
} catch (const std::exception &e) {
std::cout << "\n\n" << e.what() << std::endl;
}
aptSetHomeAllowed(false);
@@ -26,6 +30,103 @@ void NpiD7CxxExceptionHandler() {
}
#endif
static Amy::Memory::MemMetrics metrics;
#ifdef TRACK_NEW_DELETE
constexpr uint32_t MemDBGMagic = 0x774733d7;
struct MemDBGHeader {
MemDBGHeader(size_t s) {
Magic = MemDBGMagic;
Size = s;
}
uint32_t Magic = MemDBGMagic;
size_t Size = 0;
};
void *MemDBGAllocate(size_t size) {
void *ptr = malloc(size + sizeof(MemDBGHeader));
if (!ptr) return reinterpret_cast<void *>(ptr);
MemDBGHeader *hdr = reinterpret_cast<MemDBGHeader *>(ptr);
hdr->Magic = MemDBGMagic;
hdr->Size = size;
metrics.Allocated.fetch_add(hdr->Size, std::memory_order_relaxed);
metrics.Current.fetch_add(hdr->Size, std::memory_order_relaxed);
metrics.Allocations.fetch_add(1, std::memory_order_relaxed);
return reinterpret_cast<void *>(hdr + 1);
}
void MemDBGFree(void *ptr) {
if (!ptr) return;
MemDBGHeader *hdr = reinterpret_cast<MemDBGHeader *>(ptr) - 1;
if (hdr->Magic == MemDBGMagic) {
hdr->Magic = 0;
size_t szs = hdr->Size;
metrics.Deleted.fetch_add(szs, std::memory_order_relaxed);
metrics.Current.fetch_sub(szs, std::memory_order_relaxed);
metrics.Allocations.fetch_sub(1, std::memory_order_relaxed);
free(reinterpret_cast<void *>(hdr));
} else {
std::abort();
}
}
void *operator new(size_t size) { return MemDBGAllocate(size); }
void *operator new[](size_t size) { return MemDBGAllocate(size); }
void operator delete(void *ptr) noexcept { MemDBGFree(ptr); }
void operator delete(void *ptr, size_t) noexcept { MemDBGFree(ptr); }
void operator delete[](void *ptr) noexcept { MemDBGFree(ptr); }
void operator delete[](void *ptr, size_t) noexcept { MemDBGFree(ptr); }
void *operator new(size_t size, const std::nothrow_t &) noexcept {
return MemDBGAllocate(size);
}
void *operator new[](size_t size, const std::nothrow_t &) noexcept {
return MemDBGAllocate(size);
}
void operator delete(void *ptr, const std::nothrow_t &) noexcept {
MemDBGFree(ptr);
}
void operator delete[](void *ptr, const std::nothrow_t &) noexcept {
MemDBGFree(ptr);
}
void *operator new(size_t size, std::align_val_t) {
return MemDBGAllocate(size);
}
void *operator new[](size_t size, std::align_val_t) {
return MemDBGAllocate(size);
}
void operator delete(void *ptr, std::align_val_t) noexcept { MemDBGFree(ptr); }
void operator delete[](void *ptr, std::align_val_t) noexcept {
MemDBGFree(ptr);
}
void *operator new(size_t size, std::align_val_t,
const std::nothrow_t &) noexcept {
return MemDBGAllocate(size);
}
void *operator new[](size_t size, std::align_val_t,
const std::nothrow_t &) noexcept {
return MemDBGAllocate(size);
}
void operator delete(void *ptr, size_t, std::align_val_t) noexcept {
MemDBGFree(ptr);
}
void operator delete[](void *ptr, size_t, std::align_val_t) noexcept {
MemDBGFree(ptr);
}
void operator delete(void *ptr, size_t, std::align_val_t,
const std::nothrow_t &) noexcept {
MemDBGFree(ptr);
}
void operator delete[](void *ptr, size_t, std::align_val_t,
const std::nothrow_t &) noexcept {
MemDBGFree(ptr);
}
#endif
namespace Amy {
void RegisterCxxExceptionHandler() {
@@ -33,4 +134,22 @@ void RegisterCxxExceptionHandler() {
std::set_terminate(NpiD7CxxExceptionHandler);
#endif
}
void *Malloc(size_t size) {
#ifdef TRACK_NEW_DELETE
return MemDBGAllocate(size);
#else
return malloc(size);
#endif
}
void Free(void *ptr) {
#ifdef TRACK_NEW_DELETE
MemDBGFree(ptr);
#else
free(ptr);
#endif
}
ull Memory::GetTotalAllocated() { return metrics.Allocated; }
ull Memory::GetTotalFreed() { return metrics.Deleted; }
ull Memory::GetCurrent() { return metrics.CurrentlyAllocated(); }
ull Memory::GetAllocationCount() { return metrics.Allocations; }
} // namespace Amy
-34
View File
@@ -1,40 +1,6 @@
#include <amethyst/color.hpp>
namespace Amy {
// The Solution of the biggest performance issue
// A Simple Lookup table
static const std::unordered_map<char, int> HEX_DEC = {
{'0', 0}, {'1', 1}, {'2', 2}, {'3', 3}, {'4', 4}, {'5', 5},
{'6', 6}, {'7', 7}, {'8', 8}, {'9', 9}, {'a', 10}, {'b', 11},
{'c', 12}, {'d', 13}, {'e', 14}, {'f', 15}, {'A', 10}, {'B', 11},
{'C', 12}, {'D', 13}, {'E', 14}, {'F', 15}};
Color& Color::Hex(const std::string& hex) {
// zu dumm nen safetey check zu schreiben wadafuk
/**#ifndef AMY_GOD_DEV
/// Safetey check (not required if you just program well xd)
if (hex.length() != 7 || hex.length() != 9 || hex.length() != 6 ||
hex.length() != 8 || std::find_if(hex.begin(), hex.end(), [](char c) {
return !std::isxdigit(c);
}) != hex.end()) {
return *this;
}
#endif*/
int offset = ((hex.length() == 7 || hex.length() == 9) ? 1 : 0);
r = HEX_DEC.at(hex[offset]) * 16 + HEX_DEC.at(hex[offset + 1]);
offset += 2;
g = HEX_DEC.at(hex[offset]) * 16 + HEX_DEC.at(hex[offset + 1]);
offset += 2;
b = HEX_DEC.at(hex[offset]) * 16 + HEX_DEC.at(hex[offset + 1]);
offset += 2;
if (hex.length() == 9) {
a = HEX_DEC.at(hex[offset]) * 16 + HEX_DEC.at(hex[offset + 1]);
} else {
a = 255;
}
return *this;
}
std::string Color::Hex(bool rgba) const {
/** Need to int cast (so it is used as num and not char...) */
std::stringstream s;
+1 -1
View File
@@ -4,7 +4,7 @@
// Only include stb Code if we need it
// Otherwise we just build the header
#if AMY_STB_IMAGE == 1
#ifdef AMY_STB_IMAGE
#define STB_IMAGE_IMPLEMENTATION
#endif
#include <stb_image.h>
+1 -1
View File
@@ -209,7 +209,7 @@ void Iron::Drawlist::DrawCircleFilled(const fvec2& center, float rad, ui color,
PathFill(color);
}
void Iron::Drawlist::DrawCutTex(fvec2 pos, fvec2 size, fvec4 cut_rect,
void Iron::Drawlist::DrawFromAtlas(fvec2 pos, fvec2 size, fvec4 cut_rect,
ui color) {
auto r = Iron::PrimRect(pos, size);
auto cmd = NewCommand();
+2 -2
View File
@@ -3,9 +3,9 @@
#include <filesystem>
#include <fstream>
#if AMY_STB_TT == 1
//#ifdef AMY_STB_TT
#define STB_TRUETYPE_IMPLEMENTATION
#endif
//#endif
#include <stb_truetype.h>
namespace Amy {