From fffc66f18b84ea1771d9d9a3cf1fc532247fd94d Mon Sep 17 00:00:00 2001 From: Gary Talent Date: Tue, 11 Feb 2020 21:17:10 -0600 Subject: [PATCH] [nostalgia/core/gba] Add test for malloc and unify panic systems --- src/nostalgia/core/gba/CMakeLists.txt | 56 +++++++++++++--------- src/nostalgia/core/gba/gfx.cpp | 3 +- src/nostalgia/core/gba/mem.cpp | 67 +++++++++++++++++---------- src/nostalgia/core/gba/panic.cpp | 12 +++-- src/nostalgia/core/gba/panic.hpp | 16 ------- src/nostalgia/core/gba/tests.cpp | 54 +++++++++++++++++++++ 6 files changed, 141 insertions(+), 67 deletions(-) delete mode 100644 src/nostalgia/core/gba/panic.hpp create mode 100644 src/nostalgia/core/gba/tests.cpp diff --git a/src/nostalgia/core/gba/CMakeLists.txt b/src/nostalgia/core/gba/CMakeLists.txt index e5a80d68..a1a57942 100644 --- a/src/nostalgia/core/gba/CMakeLists.txt +++ b/src/nostalgia/core/gba/CMakeLists.txt @@ -1,23 +1,35 @@ -add_library( - NostalgiaCore-GBA - core.cpp - gfx.cpp - media.cpp - mem.cpp - panic.cpp -) - -target_link_libraries( - NostalgiaCore-GBA PUBLIC - NostalgiaCore - GbaStartup - OxFS - OxStd -) - -install( - TARGETS +if(NOSTALGIA_BUILD_TYPE STREQUAL "GBA") + add_library( NostalgiaCore-GBA - DESTINATION - include/nostalgia/core -) + core.cpp + gfx.cpp + media.cpp + mem.cpp + panic.cpp + ) + + target_link_libraries( + NostalgiaCore-GBA PUBLIC + NostalgiaCore + GbaStartup + OxFS + OxStd + ) + + install( + TARGETS + NostalgiaCore-GBA + DESTINATION + include/nostalgia/core + ) +endif() + +# tests +if(NOSTALGIA_BUILD_TYPE STREQUAL "Native") + add_executable(NostalgiaCore-GBA_Test + tests.cpp + mem.cpp + ) + target_link_libraries(NostalgiaCore-GBA_Test NostalgiaCore) + add_test("NostalgiaCore-GBA\\ Test\\ malloc" NostalgiaCore-GBA_Test malloc) +endif() \ No newline at end of file diff --git a/src/nostalgia/core/gba/gfx.cpp b/src/nostalgia/core/gba/gfx.cpp index 81678c85..5dac22da 100644 --- a/src/nostalgia/core/gba/gfx.cpp +++ b/src/nostalgia/core/gba/gfx.cpp @@ -14,7 +14,6 @@ #include #include "addresses.hpp" -#include "panic.hpp" namespace nostalgia::core { @@ -102,7 +101,7 @@ ox::Error shutdownGfx() { case 3: return REG_BG3CNT; default: - panic("Looking up non-existent register"); + oxPanic("Looking up non-existent register", OxError(1)); return REG_BG0CNT; } } diff --git a/src/nostalgia/core/gba/mem.cpp b/src/nostalgia/core/gba/mem.cpp index a2d351d3..33206430 100644 --- a/src/nostalgia/core/gba/mem.cpp +++ b/src/nostalgia/core/gba/mem.cpp @@ -7,11 +7,9 @@ */ #include "addresses.hpp" -#include "ox/std/bit.hpp" -#include "ox/std/types.hpp" -#include "panic.hpp" -#include +#include +#include // this warning is too dumb to realize that it can actually confirm the hard // coded address aligns with the requirement of HeapSegment, so it must be @@ -25,6 +23,10 @@ namespace nostalgia::core { +static class HeapSegment *volatile g_heapBegin = nullptr; +static class HeapSegment *volatile g_heapEnd = nullptr; +static class HeapSegment *volatile heapIdx = nullptr; + static constexpr std::size_t alignedSize(std::size_t sz) { return sz + (sz & 7); } @@ -38,39 +40,35 @@ struct HeapSegment { std::size_t size; uint8_t inUse; - void init(std::size_t maxSize = ox::bit_cast(HEAP_END)) { - this->size = maxSize - reinterpret_cast(this); + void init(std::size_t maxSize = ox::bit_cast(g_heapEnd)) { + this->size = maxSize - ox::bit_cast(this); this->inUse = false; } template T *data() { - return reinterpret_cast(reinterpret_cast(this) + alignedSize(this)); + return ox::bit_cast(ox::bit_cast(this) + alignedSize(this)); } template T *end() { const auto size = alignedSize(this) + alignedSize(this->size); - auto e = reinterpret_cast(reinterpret_cast(this) + size); - return reinterpret_cast(e); + auto e = ox::bit_cast(ox::bit_cast(this) + size); + return ox::bit_cast(e); } }; -static HeapSegment *volatile heapIdx = nullptr; - -void initHeap() { - heapIdx = HEAP_BEGIN; - heapIdx->init(); +void initHeap(char *heapBegin, char *heapEnd) { + g_heapBegin = ox::bit_cast(heapBegin); + g_heapEnd = ox::bit_cast(heapEnd); + heapIdx = g_heapBegin; + heapIdx->size = ox::bit_cast(heapEnd) - ox::bit_cast(heapIdx); + heapIdx->inUse = false; } -static HeapSegment *findSegmentFor(std::size_t sz) { - for (auto s = HEAP_BEGIN; s + sz < HEAP_END; s = s->end()) { - if (s->size >= sz && !s->inUse) { - return s; - } - } - return nullptr; +void initHeap() { + initHeap(ox::bit_cast(HEAP_BEGIN), ox::bit_cast(HEAP_END)); } struct SegmentPair { @@ -90,6 +88,16 @@ static SegmentPair findSegmentOf(void *ptr) { return {}; } +static HeapSegment *findSegmentFor(std::size_t sz) { + for (auto s = g_heapBegin; s <= g_heapEnd; s = s->end()) { + if (s->size >= sz && !s->inUse) { + return s; + } + } + oxPanic("malloc: could not find segment", OxError(1)); + return nullptr; +} + [[nodiscard]] void *malloc(std::size_t allocSize) { const auto targetSize = alignedSize(sizeof(HeapSegment)) + alignedSize(allocSize); auto seg = findSegmentFor(targetSize); @@ -99,9 +107,8 @@ static SegmentPair findSegmentOf(void *ptr) { const auto bytesRemaining = seg->size - targetSize; seg->size = targetSize; seg->inUse = true; - auto out = seg->data(); seg->end()->init(bytesRemaining); - return out; + return seg->data(); } void free(void *ptr) { @@ -111,12 +118,14 @@ void free(void *ptr) { } else if (p.segment) { p.segment->inUse = false; } else { - panic("Bad heap free"); + oxPanic("Bad heap free", OxError(1)); } } } +#ifndef OX_USE_STDLIB + using namespace nostalgia; void *operator new(std::size_t allocSize) { @@ -142,3 +151,13 @@ void operator delete(void *ptr, unsigned) { void operator delete[](void *ptr, unsigned) { core::free(ptr); } + +void operator delete(void *ptr, unsigned long int) { + core::free(ptr); +} + +void operator delete[](void *ptr, unsigned long int) { + core::free(ptr); +} + +#endif \ No newline at end of file diff --git a/src/nostalgia/core/gba/panic.cpp b/src/nostalgia/core/gba/panic.cpp index 9f6b2d07..95ab46ba 100644 --- a/src/nostalgia/core/gba/panic.cpp +++ b/src/nostalgia/core/gba/panic.cpp @@ -7,15 +7,21 @@ */ #include "../core.hpp" -#include "panic.hpp" +#include "../gfx.hpp" -namespace nostalgia::core { +namespace ox { -void panic(const char *msg) { +using namespace nostalgia::core; + +void panic(const char*, int, const char *msg, ox::Error err) { + oxIgnoreError(initGfx(nullptr)); oxIgnoreError(initConsole(nullptr)); + ox::BString<23> serr = "Error code: "; + serr += err; puts(nullptr, 32 + 0, 1, "SADNESS..."); puts(nullptr, 32 + 0, 4, "UNEXPECTED STATE:"); puts(nullptr, 32 + 2, 6, msg); + puts(nullptr, 32 + 2, 7, serr.c_str()); puts(nullptr, 32 + 0, 10, "PLEASE RESTART THE SYSTEM"); // TODO: properly end program execution, this wastes power while (1); diff --git a/src/nostalgia/core/gba/panic.hpp b/src/nostalgia/core/gba/panic.hpp deleted file mode 100644 index c4373ce6..00000000 --- a/src/nostalgia/core/gba/panic.hpp +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright 2016 - 2019 gtalent2@gmail.com - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -#pragma once - -namespace nostalgia::core { - -void panic(const char *msg); - -} - diff --git a/src/nostalgia/core/gba/tests.cpp b/src/nostalgia/core/gba/tests.cpp new file mode 100644 index 00000000..bd0e4ff1 --- /dev/null +++ b/src/nostalgia/core/gba/tests.cpp @@ -0,0 +1,54 @@ + +#include +#include +#include + +#include + +#include + +namespace nostalgia::core { + +[[nodiscard]] void *malloc(std::size_t allocSize); + +void free(void *ptr); + +void panic(const char *msg) { + oxPanic(msg, OxError(1)); +} + +void initHeap(char *heapBegin, char *heapEnd); + +} + +using namespace nostalgia; + +int testMalloc(std::string) { + std::vector buff(ox::units::MB); + core::initHeap(&buff.front(), &buff.back()); + oxAssert(core::malloc(5) != nullptr, "malloc is broken"); + oxAssert(core::malloc(5) != nullptr, "malloc is broken"); + return 0; +} + +std::map tests = { + { + { "malloc", testMalloc }, + } +}; + +int main(int argc, const char **args) { + int retval = -1; + if (argc > 1) { + auto testName = args[1]; + std::string testArg = ""; + if (args[2]) { + testArg = args[2]; + } + if (tests.find(testName) != tests.end()) { + retval = tests[testName](testArg); + } + } + return retval; +} +