Compare commits

..

19 Commits

Author SHA1 Message Date
144d234d09 [nostalgia/studio] Change version to release-d2024.12
All checks were successful
Build / build (push) Successful in 3m20s
2025-01-12 21:03:34 -06:00
465fb06f76 [nostalgia/core] Fix TileSheet validation/repair to ensure pixels gets cleared if there are subsheets
Some checks failed
Build / build (push) Has been cancelled
2025-01-12 20:58:19 -06:00
db953dd0d1 [studio] Fix new project menu to return an appropriately sized string for name 2025-01-12 20:58:19 -06:00
daab4dc4f5 [nostalgia/core/studio] Fix SubSheet editor to return an appropriately sized string 2025-01-12 20:58:19 -06:00
83cbac5cca [nostalgia/studio] Update version to d2024.12.1
All checks were successful
Build / build (push) Successful in 3m19s
2025-01-11 17:22:02 -06:00
74e518fee0 [nostalgia/core/studio/tilesheeteditor] Fix select all not to go beyond end 2025-01-11 17:07:50 -06:00
6b0ce40c02 [nostalgia/core/studio] Fix crash that occurs when a non-leaf node subsheet is selected 2025-01-11 17:07:50 -06:00
4f55964dd9 [nostalgia/core/studio] Fix tile insert to correct input when inserting past the last tile 2025-01-11 17:07:50 -06:00
cb597cf92e [nostalgia/core/studio] Fix tile insert to work on last tile 2025-01-11 17:07:50 -06:00
6906c66ba7 [keel] Fix reloadAsset 2025-01-11 17:07:50 -06:00
ba00d10dfc [nostalgia] Update liccor file 2025-01-11 17:07:50 -06:00
cdfbfe48b7 [ox] Update liccor file 2025-01-11 17:07:50 -06:00
21ae2a14e9 [ox] Run liccor 2025-01-11 17:07:50 -06:00
81b120b1ce [nostalgia,olympic] Run liccor 2025-01-11 17:07:50 -06:00
40938958de [turbine/glfw] Ensure window opens with a standard mandatory refresh period 2025-01-11 17:07:50 -06:00
df190c05a0 [studio] Make first tab not draw before selected tab when window opens 2025-01-11 17:07:50 -06:00
3fe3b08eca [ox/std] Add hash.hpp to install 2025-01-11 17:07:50 -06:00
ecc5ae6b2f [studio] Make selection tracker not go below 0 2025-01-11 17:07:50 -06:00
a863bfc181 [nostalgia/studio] Update version to d2024.12.0
All checks were successful
Build / build (push) Successful in 3m20s
2024-12-21 19:27:00 -06:00
41 changed files with 206 additions and 489 deletions

2
.gitignore vendored
View File

@ -6,7 +6,7 @@
.mypy_cache .mypy_cache
.stfolder .stfolder
.stignore .stignore
util/scripts/__pycache__ scripts/__pycache__
pyenv pyenv
CMakeLists.txt.user CMakeLists.txt.user
ROM.oxfs ROM.oxfs

View File

@ -1,4 +1,4 @@
FROM fedora:41 FROM fedora:36
RUN dnf update -y RUN dnf update -y

View File

@ -1,6 +1,5 @@
BC_VAR_PROJECT_NAME=nostalgia BC_VAR_PROJECT_NAME=nostalgia
BC_VAR_PROJECT_NAME_CAP=Nostalgia BC_VAR_PROJECT_NAME_CAP=Nostalgia
BC_VAR_DEVENV_ROOT=util
BUILDCORE_PATH=deps/buildcore BUILDCORE_PATH=deps/buildcore
include ${BUILDCORE_PATH}/base.mk include ${BUILDCORE_PATH}/base.mk
@ -14,7 +13,7 @@ endif
.PHONY: pkg-gba .PHONY: pkg-gba
pkg-gba: build pkg-gba: build
${BC_CMD_ENVRUN} ${BC_PY3} ./util/scripts/pkg-gba.py sample_project ${BC_VAR_PROJECT_NAME} ${BC_CMD_ENVRUN} ${BC_PY3} ./scripts/pkg-gba.py sample_project ${BC_VAR_PROJECT_NAME}
.PHONY: run .PHONY: run
run: build run: build

View File

@ -1,8 +1,8 @@
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake/modules) list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake/modules)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -nostdlib") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -nostdlib")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -nostdinc++") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -nostdinc++")
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-unwind-tables") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-unwind-tables")
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-strict-aliasing") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-strict-aliasing")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mthumb-interwork") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mthumb-interwork")

View File

@ -1,11 +1,2 @@
add_library(glad src/glad.c) add_library(glad OBJECT src/glad.c)
target_include_directories(glad PUBLIC include) target_include_directories(glad PUBLIC include)
install(
TARGETS
glad
DESTINATION
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
)

View File

@ -6,7 +6,7 @@ endif()
# DrinkingTea: end # DrinkingTea: end
add_library( add_library(
imgui imgui OBJECT
imgui.cpp imgui.cpp
imgui_demo.cpp imgui_demo.cpp
imgui_draw.cpp imgui_draw.cpp
@ -20,11 +20,3 @@ target_include_directories(
imgui SYSTEM PUBLIC imgui SYSTEM PUBLIC
. .
) )
install(
TARGETS
imgui
DESTINATION
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
)

View File

@ -215,7 +215,7 @@ Error Signal<Args...>::emitCheckError(Args... args) const noexcept {
} }
return ox::Error(0); return ox::Error(0);
} catch (const ox::Exception &ex) { } catch (const ox::Exception &ex) {
return ox::Error(ex.errCode, ex.msg, ex.src); return ox::Error(ex.file, ex.line, ex.errCode, ex.msg);
} }
} }

View File

@ -14,7 +14,7 @@
{ \ { \
const auto loggerErr = (loggerName).initConn(appName); \ const auto loggerErr = (loggerName).initConn(appName); \
if (loggerErr) { \ if (loggerErr) { \
oxErrf("Could not connect to logger: {} ({}:{})\n", toStr(loggerErr), loggerErr.src.file_name(), loggerErr.src.line()); \ oxErrf("Could not connect to logger: {} ({}:{})\n", toStr(loggerErr), loggerErr.file, loggerErr.line); \
} else { \ } else { \
ox::trace::setLogger(&(loggerName)); \ ox::trace::setLogger(&(loggerName)); \
} \ } \

View File

@ -9,25 +9,13 @@
#pragma once #pragma once
#include "def.hpp" #include "def.hpp"
#include "error.hpp"
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage) OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
namespace ox { namespace ox {
template<typename It, typename T> template<typename It, typename T>
constexpr ox::Result<size_t> findIdx(It begin, It end, T const&value) { constexpr It find(It begin, It end, const T &value) {
auto it = begin;
for (; it != end; ++it) {
if (*it == value) {
return it.offset();
}
}
return ox::Error{1, "item not found"};
}
template<typename It, typename T>
constexpr It find(It begin, It end, T const&value) {
for (; begin != end; ++begin) { for (; begin != end; ++begin) {
if (*begin == value) { if (*begin == value) {
return begin; return begin;

View File

@ -7,7 +7,6 @@
*/ */
#include "fmt.hpp" #include "fmt.hpp"
#include "realstd.hpp"
#include "stacktrace.hpp" #include "stacktrace.hpp"
#include "trace.hpp" #include "trace.hpp"
@ -15,14 +14,14 @@
namespace ox { namespace ox {
void panic(StringViewCR file, int const line, StringViewCR panicMsg, Error const&err) noexcept { void panic(StringViewCR file, int line, StringViewCR panicMsg, const Error &err) noexcept {
oxErrf("\033[31;1;1mPANIC:\033[0m [{}:{}]: {}\n", file, line, panicMsg); oxErrf("\033[31;1;1mPANIC:\033[0m [{}:{}]: {}\n", file, line, panicMsg);
if (err.msg) { if (err.msg) {
oxErrf("\tError Message:\t{}\n", err.msg); oxErrf("\tError Message:\t{}\n", err.msg);
} }
oxErrf("\tError Code:\t{}\n", static_cast<ErrorCode>(err)); oxErrf("\tError Code:\t{}\n", static_cast<ErrorCode>(err));
if (err.src.file_name() != nullptr) { if (err.file != nullptr) {
oxErrf("\tError Location:\t{}:{}\n", err.src.file_name(), err.src.line()); oxErrf("\tError Location:\t{}:{}\n", err.file, err.line);
} }
#ifdef OX_USE_STDLIB #ifdef OX_USE_STDLIB
printStackTrace(2); printStackTrace(2);
@ -33,19 +32,16 @@ void panic(StringViewCR file, int const line, StringViewCR panicMsg, Error const
#endif #endif
} }
void panic(const char *file, int const line, char const*panicMsg, Error const&err) noexcept { void panic(const char *file, int line, const char *panicMsg, const Error &err) noexcept {
panic(StringView{file}, line, StringView{panicMsg}, err); panic(StringView{file}, line, StringView{panicMsg}, err);
} }
void assertFailFuncRuntime( void assertFailFuncRuntime(StringViewCR file, int line, StringViewCR assertTxt, StringViewCR msg) noexcept {
StringViewCR file,
int const line,
StringViewCR assertTxt,
StringViewCR msg) noexcept {
#ifdef OX_USE_STDLIB #ifdef OX_USE_STDLIB
auto const st = genStackTrace(2); auto output = sfmt("\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n", file, line, msg);
oxTracef("assert", "Failed assert: {} ({}) [{}:{}]:\n{}", msg, assertTxt, file, line, st); output += genStackTrace(2);
abort(); oxTracef("assert", "Failed assert: {} ({}) [{}:{}]", msg, assertTxt, file, line);
std::abort();
#else #else
oxErrf("\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n", file, line, msg); oxErrf("\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n", file, line, msg);
oxTracef("assert", "Failed assert: {} ({}) [{}:{}]", msg, assertTxt, file, line); oxTracef("assert", "Failed assert: {} ({}) [{}:{}]", msg, assertTxt, file, line);
@ -53,25 +49,20 @@ void assertFailFuncRuntime(
#endif #endif
} }
void assertFailFuncRuntime( void assertFailFuncRuntime(StringViewCR file, int line, [[maybe_unused]] const Error &err, StringViewCR, StringViewCR assertMsg) noexcept {
StringViewCR file,
int const line,
[[maybe_unused]] Error const&err,
StringViewCR,
StringViewCR assertMsg) noexcept {
#if defined(OX_USE_STDLIB) #if defined(OX_USE_STDLIB)
auto msg = sfmt("\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n", file, line, assertMsg); auto msg = sfmt("\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n", file, line, assertMsg);
if (err.msg) { if (err.msg) {
msg += sfmt("\tError Message:\t{}\n", err.msg); msg += sfmt("\tError Message:\t{}\n", err.msg);
} }
msg += sfmt("\tError Code:\t{}\n", static_cast<ErrorCode>(err)); msg += sfmt("\tError Code:\t{}\n", static_cast<ErrorCode>(err));
if (err.src.file_name() != nullptr) { if (err.file != nullptr) {
msg += sfmt("\tError Location:\t{}:{}\n", err.src.file_name(), err.src.line()); msg += sfmt("\tError Location:\t{}:{}\n", err.file, err.line);
} }
msg += genStackTrace(2); msg += genStackTrace(2);
oxErr(msg); oxErr(msg);
oxTracef("assert", "Failed assert: {} [{}:{}]", assertMsg, file, line); oxTracef("assert", "Failed assert: {} [{}:{}]", assertMsg, file, line);
abort(); std::abort();
#else #else
constexprPanic(file, line, assertMsg); constexprPanic(file, line, assertMsg);
#endif #endif

View File

@ -22,15 +22,9 @@
namespace ox { namespace ox {
[[noreturn]] void panic(StringViewCR file, int line, StringViewCR panicMsg, const Error &err = ox::Error(0)) noexcept;
void panic(StringViewCR file, int line, StringViewCR panicMsg, Error const&err = {}) noexcept;
[[noreturn]] constexpr void constexprPanic(StringViewCR file, int line, StringViewCR panicMsg, const Error &err = ox::Error(0)) noexcept {
constexpr void constexprPanic(
StringViewCR file,
int const line,
StringViewCR panicMsg,
Error const&err = {}) noexcept {
if (!std::is_constant_evaluated()) { if (!std::is_constant_evaluated()) {
panic(file, line, panicMsg, err); panic(file, line, panicMsg, err);
} else { } else {
@ -38,24 +32,10 @@ constexpr void constexprPanic(
} }
} }
void assertFailFuncRuntime( void assertFailFuncRuntime(StringViewCR file, int line, StringViewCR assertTxt, StringViewCR msg) noexcept;
StringViewCR file, void assertFailFuncRuntime(StringViewCR file, int line, const Error &err, StringViewCR, StringViewCR assertMsg) noexcept;
int line,
StringViewCR assertTxt,
StringViewCR msg) noexcept;
void assertFailFuncRuntime(
StringViewCR file,
int line,
Error const&err,
StringViewCR,
StringViewCR assertMsg) noexcept;
constexpr void assertFunc( constexpr void assertFunc(StringViewCR file, int line, bool pass, [[maybe_unused]]StringViewCR assertTxt, [[maybe_unused]]StringViewCR msg) noexcept {
StringViewCR file,
int const line,
bool const pass,
[[maybe_unused]]StringViewCR assertTxt,
[[maybe_unused]]StringViewCR msg) noexcept {
if (!pass) { if (!pass) {
if (!std::is_constant_evaluated()) { if (!std::is_constant_evaluated()) {
assertFailFuncRuntime(file, line, assertTxt, msg); assertFailFuncRuntime(file, line, assertTxt, msg);
@ -65,12 +45,7 @@ constexpr void assertFunc(
} }
} }
constexpr void assertFunc( constexpr void assertFunc(StringViewCR file, int line, const Error &err, StringViewCR, StringViewCR assertMsg) noexcept {
StringViewCR file,
int const line,
Error const&err,
StringViewCR,
StringViewCR assertMsg) noexcept {
if (err) { if (err) {
if (!std::is_constant_evaluated()) { if (!std::is_constant_evaluated()) {
assertFailFuncRuntime(file, line, err, {}, assertMsg); assertFailFuncRuntime(file, line, err, {}, assertMsg);
@ -80,11 +55,7 @@ constexpr void assertFunc(
} }
} }
constexpr void expect( constexpr void expect(StringViewCR file, int line, const auto &actual, const auto &expected) noexcept {
StringViewCR file,
int const line,
auto const&actual,
auto const&expected) noexcept {
if (actual != expected) { if (actual != expected) {
if (!std::is_constant_evaluated()) { if (!std::is_constant_evaluated()) {
#if defined(OX_USE_STDLIB) #if defined(OX_USE_STDLIB)

View File

@ -36,16 +36,28 @@ using ErrorCode = uint16_t;
struct [[nodiscard]] Error { struct [[nodiscard]] Error {
std::source_location src;
ox::CString msg = nullptr; ox::CString msg = nullptr;
ox::CString file = nullptr;
uint16_t line = 0;
ErrorCode errCode = 0; ErrorCode errCode = 0;
constexpr Error() noexcept = default; constexpr Error() noexcept = default;
explicit constexpr Error(
ox::CString file,
uint32_t const line,
ErrorCode const errCode,
ox::CString msg = nullptr) noexcept:
msg{msg},
file{file},
line{static_cast<uint16_t>(line)},
errCode{errCode} {}
explicit constexpr Error( explicit constexpr Error(
ErrorCode const errCode, ErrorCode const errCode,
std::source_location const&src = std::source_location::current()) noexcept: std::source_location const&src = std::source_location::current()) noexcept:
src{src}, file{src.file_name()},
line{static_cast<uint16_t>(src.line())},
errCode{errCode} errCode{errCode}
{} {}
@ -53,8 +65,9 @@ struct [[nodiscard]] Error {
ErrorCode const errCode, ErrorCode const errCode,
ox::CString msg, ox::CString msg,
std::source_location const&src = std::source_location::current()) noexcept: std::source_location const&src = std::source_location::current()) noexcept:
src{src},
msg{msg}, msg{msg},
file{src.file_name()},
line{static_cast<uint16_t>(src.line())},
errCode{errCode} errCode{errCode}
{} {}
@ -76,31 +89,42 @@ constexpr auto toStr(Error const&err) noexcept {
} }
struct Exception: public std::exception { struct Exception: public std::exception {
std::source_location src;
ox::CString msg = nullptr; ox::CString msg = nullptr;
ox::CString file = nullptr;
uint16_t line = 0;
ErrorCode errCode = 0; ErrorCode errCode = 0;
explicit Exception( explicit inline Exception(ox::CString file, uint32_t line, ErrorCode errCode, char const*msg = "") noexcept {
this->file = file;
this->line = static_cast<uint16_t>(line);
this->msg = msg;
this->errCode = errCode;
}
explicit inline Exception(
ErrorCode const errCode, ErrorCode const errCode,
std::source_location const&src = std::source_location::current()) noexcept: std::source_location const&src = std::source_location::current()) noexcept:
src{src}, file{src.file_name()},
line{static_cast<uint16_t>(src.line())},
errCode{errCode} {} errCode{errCode} {}
explicit Exception( explicit inline Exception(
ErrorCode const errCode, ErrorCode const errCode,
ox::CString msg, ox::CString msg,
std::source_location const&src = std::source_location::current()) noexcept: std::source_location const&src = std::source_location::current()) noexcept:
src{src},
msg{msg}, msg{msg},
file{src.file_name()},
line{static_cast<uint16_t>(src.line())},
errCode{errCode} {} errCode{errCode} {}
explicit Exception(Error const&err) noexcept: explicit inline Exception(Error const&err) noexcept:
src{err.src},
msg{err.msg ? err.msg : ""}, msg{err.msg ? err.msg : ""},
file{err.file},
line{err.line},
errCode{err.errCode} {} errCode{err.errCode} {}
constexpr Error toError() const noexcept { constexpr Error toError() const noexcept {
return Error(errCode, msg, src); return Error(file, line, errCode, msg);
} }
[[nodiscard]] [[nodiscard]]
@ -109,7 +133,6 @@ struct Exception: public std::exception {
} }
}; };
[[noreturn]]
void panic(char const*file, int line, char const*panicMsg, Error const&err) noexcept; void panic(char const*file, int line, char const*panicMsg, Error const&err) noexcept;
template<typename T> template<typename T>

View File

@ -31,6 +31,7 @@ concept Reader_c = requires(T v) {
class Reader_v { class Reader_v {
public: public:
virtual constexpr ~Reader_v() noexcept = default; virtual constexpr ~Reader_v() noexcept = default;
[[nodiscard]]
virtual constexpr ox::Result<char> peek() const noexcept = 0; virtual constexpr ox::Result<char> peek() const noexcept = 0;
virtual constexpr ox::Result<std::size_t> read(char*, std::size_t) noexcept = 0; virtual constexpr ox::Result<std::size_t> read(char*, std::size_t) noexcept = 0;
virtual constexpr ox::Result<std::size_t> tellg() noexcept = 0; virtual constexpr ox::Result<std::size_t> tellg() noexcept = 0;

View File

@ -13,12 +13,3 @@
#else #else
#define assert(e) while (!(e)); #define assert(e) while (!(e));
#endif #endif
#if __has_include(<cstdlib>)
#include <cstdlib>
#else
extern "C" {
[[noreturn]]
void abort();
}
#endif

View File

@ -62,9 +62,6 @@ class SmallMap {
[[nodiscard]] [[nodiscard]]
constexpr Vector<K> keys() const noexcept; constexpr Vector<K> keys() const noexcept;
[[nodiscard]]
constexpr Vector<T> values() const noexcept;
[[nodiscard]] [[nodiscard]]
constexpr K const&key(size_t i) const noexcept; constexpr K const&key(size_t i) const noexcept;
@ -85,22 +82,14 @@ class SmallMap {
return m_pairs; return m_pairs;
} }
[[nodiscard]]
constexpr ox::Span<Pair> pairs() noexcept {
return m_pairs;
}
constexpr void clear(); constexpr void clear();
private: private:
template<typename KK> template<typename KK>
constexpr Pair const*access(PairVector const&pairs, KK const&key, bool &isNew) const; constexpr Pair const&access(PairVector const&pairs, KK const&key, bool &isNew) const;
template<typename KK> template<typename KK>
constexpr Pair *access(PairVector &pairs, KK const&key, bool &isNew); constexpr Pair &access(PairVector &pairs, KK const&key, bool &isNew);
template<typename KK>
constexpr Pair *accessNoCreate(PairVector &pairs, KK const&key);
}; };
@ -140,7 +129,7 @@ constexpr SmallMap<K, T, SmallSz> &SmallMap<K, T, SmallSz>::operator=(SmallMap<K
template<typename K, typename T, size_t SmallSz> template<typename K, typename T, size_t SmallSz>
constexpr T &SmallMap<K, T, SmallSz>::operator[](MaybeView_t<K> const&k) { constexpr T &SmallMap<K, T, SmallSz>::operator[](MaybeView_t<K> const&k) {
bool isNew{}; bool isNew{};
auto p = access(m_pairs, k, isNew); auto p = &access(m_pairs, k, isNew);
if (isNew) { if (isNew) {
p->key = k; p->key = k;
} }
@ -149,7 +138,7 @@ constexpr T &SmallMap<K, T, SmallSz>::operator[](MaybeView_t<K> const&k) {
template<typename K, typename T, size_t SmallSz> template<typename K, typename T, size_t SmallSz>
constexpr Result<T*> SmallMap<K, T, SmallSz>::at(MaybeView_t<K> const&k) noexcept { constexpr Result<T*> SmallMap<K, T, SmallSz>::at(MaybeView_t<K> const&k) noexcept {
auto const p = accessNoCreate(m_pairs, k); auto p = access(m_pairs, k);
if (!p) { if (!p) {
return {nullptr, ox::Error(1, "value not found for given key")}; return {nullptr, ox::Error(1, "value not found for given key")};
} }
@ -158,8 +147,7 @@ constexpr Result<T*> SmallMap<K, T, SmallSz>::at(MaybeView_t<K> const&k) noexcep
template<typename K, typename T, size_t SmallSz> template<typename K, typename T, size_t SmallSz>
constexpr Result<const T*> SmallMap<K, T, SmallSz>::at(MaybeView_t<K> const&k) const noexcept { constexpr Result<const T*> SmallMap<K, T, SmallSz>::at(MaybeView_t<K> const&k) const noexcept {
bool isNew{}; auto p = access(m_pairs, k);
auto p = access(m_pairs, k, isNew);
if (!p) { if (!p) {
return {nullptr, ox::Error(1, "value not found for given key")}; return {nullptr, ox::Error(1, "value not found for given key")};
} }
@ -180,8 +168,7 @@ constexpr void SmallMap<K, T, SmallSz>::erase(MaybeView_t<K> const&k) {
template<typename K, typename T, size_t SmallSz> template<typename K, typename T, size_t SmallSz>
constexpr bool SmallMap<K, T, SmallSz>::contains(MaybeView_t<K> const&k) const noexcept { constexpr bool SmallMap<K, T, SmallSz>::contains(MaybeView_t<K> const&k) const noexcept {
bool isNew{}; return access(m_pairs, k) != nullptr;
return access(m_pairs, k, isNew) != nullptr;
} }
template<typename K, typename T, size_t SmallSz> template<typename K, typename T, size_t SmallSz>
@ -199,16 +186,6 @@ constexpr Vector<K> SmallMap<K, T, SmallSz>::keys() const noexcept {
return keys; return keys;
} }
template<typename K, typename T, size_t SmallSz>
constexpr Vector<T> SmallMap<K, T, SmallSz>::values() const noexcept {
ox::Vector<T> keys;
keys.reserve(m_pairs.size());
for (auto const&p : m_pairs) {
keys.emplace_back(p.key);
}
return keys;
}
template<typename K, typename T, size_t SmallSz> template<typename K, typename T, size_t SmallSz>
constexpr K const&SmallMap<K, T, SmallSz>::key(size_t i) const noexcept { constexpr K const&SmallMap<K, T, SmallSz>::key(size_t i) const noexcept {
return m_pairs[i].key; return m_pairs[i].key;
@ -241,42 +218,30 @@ constexpr void SmallMap<K, T, SmallSz>::clear() {
template<typename K, typename T, size_t SmallSz> template<typename K, typename T, size_t SmallSz>
template<typename KK> template<typename KK>
constexpr typename SmallMap<K, T, SmallSz>::Pair const*SmallMap<K, T, SmallSz>::access( constexpr typename SmallMap<K, T, SmallSz>::Pair const&SmallMap<K, T, SmallSz>::access(
PairVector const&pairs, KK const&k, bool &isNew) const { PairVector const&pairs, KK const&k, bool &isNew) const {
for (auto const&p : pairs) { for (auto const&p : pairs) {
if (p.key == k) { if (p.key == k) {
isNew = false; isNew = false;
return &p; return p;
} }
} }
isNew = true; isNew = true;
return nullptr; return pairs.emplace_back();
} }
template<typename K, typename T, size_t SmallSz> template<typename K, typename T, size_t SmallSz>
template<typename KK> template<typename KK>
constexpr typename SmallMap<K, T, SmallSz>::Pair *SmallMap<K, T, SmallSz>::access( constexpr typename SmallMap<K, T, SmallSz>::Pair &SmallMap<K, T, SmallSz>::access(
PairVector &pairs, KK const&k, bool &isNew) { PairVector &pairs, KK const&k, bool &isNew) {
for (auto &p : pairs) { for (auto &p : pairs) {
if (p.key == k) { if (p.key == k) {
isNew = false; isNew = false;
return &p; return p;
} }
} }
isNew = true; isNew = true;
return &pairs.emplace_back(); return pairs.emplace_back();
}
template<typename K, typename T, size_t SmallSz>
template<typename KK>
constexpr typename SmallMap<K, T, SmallSz>::Pair *SmallMap<K, T, SmallSz>::accessNoCreate(
PairVector &pairs, KK const&k) {
for (auto &p : pairs) {
if (p.key == k) {
return &p;
}
}
return nullptr;
} }
template<typename T, typename K, typename V, size_t SmallSz> template<typename T, typename K, typename V, size_t SmallSz>

View File

@ -14,7 +14,7 @@
#include "iterator.hpp" #include "iterator.hpp"
#include "vector.hpp" #include "vector.hpp"
OX_ALLOW_UNSAFE_BUFFERS_BEGIN OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
namespace ox { namespace ox {
@ -133,7 +133,7 @@ class Span {
return m_items[i]; return m_items[i];
} }
constexpr T const&operator[](std::size_t i) const noexcept { constexpr const T &operator[](std::size_t i) const noexcept {
ox::primitiveAssert(__FILE__, __LINE__, i < size(), "Span access overflow"); ox::primitiveAssert(__FILE__, __LINE__, i < size(), "Span access overflow");
return m_items[i]; return m_items[i];
} }
@ -168,20 +168,8 @@ class Span {
}; };
template<typename T> template<typename T>
using SpanView = Span<T const>; using SpanView = Span<const T>;
template<typename T>
constexpr void spancpy(ox::Span<T> const dst, ox::SpanView<T> const src) noexcept {
auto const sz = ox::min(dst.size(), src.size());
if (std::is_constant_evaluated() || std::is_trivially_copyable_v<T>) {
for (size_t i{}; i < sz; ++i) {
dst.data()[i] = src.data()[i];
}
} else {
memcpy(dst.data(), src.data(), sz * sizeof(T));
}
}
} }
OX_ALLOW_UNSAFE_BUFFERS_END OX_CLANG_NOWARN_END

View File

@ -17,8 +17,6 @@ add_test("[ox/std] String" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "String")
add_test("[ox/std] SmallMap" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "SmallMap") add_test("[ox/std] SmallMap" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "SmallMap")
add_test("[ox/std] SmallMap2" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "SmallMap2") add_test("[ox/std] SmallMap2" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "SmallMap2")
add_test("[ox/std] Vector" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "Vector") add_test("[ox/std] Vector" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "Vector")
add_test("[ox/std] Vector::shrink_to_fit" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "Vector::shrink_to_fit")
add_test("[ox/std] findIdx" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "findIdx")
add_test("[ox/std] HashMap" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "HashMap") add_test("[ox/std] HashMap" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "HashMap")
add_test("[ox/std] HeapMgr" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest malloc) add_test("[ox/std] HeapMgr" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest malloc)
add_test("[ox/std] Serialize-Int" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "Serialize-Int") add_test("[ox/std] Serialize-Int" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "Serialize-Int")

View File

@ -237,50 +237,6 @@ OX_CLANG_NOWARN_END
return ox::Error(0); return ox::Error(0);
} }
}, },
{
"Vector::shrink_to_fit",
[] {
{
ox::Vector<ox::IString<8>> v;
v.reserve(50);
v.emplace_back("asdf");
v.emplace_back("aoeu");
auto const origData = v.data();
v.shrink_to_fit();
oxExpect(v[0], "asdf");
oxExpect(v[1], "aoeu");
oxExpect(v.capacity(), 2u);
oxAssert(origData != v.data(), "shrink_to_fit did not create a new allocation");
}
{
ox::Vector<ox::IString<8>> v;
v.reserve(2);
v.emplace_back("asdf");
v.emplace_back("aoeu");
auto const origData = v.data();
v.shrink_to_fit();
oxExpect(v[0], "asdf");
oxExpect(v[1], "aoeu");
oxExpect(v.capacity(), 2u);
oxAssert(origData == v.data(), "shrink_to_fit inappropriately created a new allocation");
}
return ox::Error{};
}
},
{
"findIdx",
[] {
ox::Vector<ox::IString<8>> const v {"zero", "one", "two", "three", "four"};
oxExpect(ox::findIdx(v.begin(), v.end(), "zero").or_value(5), 0u);
oxExpect(ox::findIdx(v.begin(), v.end(), "one").or_value(5), 1u);
oxExpect(ox::findIdx(v.begin(), v.end(), "two").or_value(5), 2u);
oxExpect(ox::findIdx(v.begin(), v.end(), "three").or_value(5), 3u);
oxExpect(ox::findIdx(v.begin(), v.end(), "four").or_value(5), 4u);
oxExpect(ox::findIdx(v.begin(), v.end(), "five").or_value(5), 5u);
oxExpect(ox::findIdx(v.begin(), v.end(), "six").or_value(6), 6u);
return ox::Error{};
}
},
{ {
"SmallMap", "SmallMap",
[] { [] {
@ -290,18 +246,7 @@ OX_CLANG_NOWARN_END
oxExpect(map.size(), 1u); oxExpect(map.size(), 1u);
oxExpect(map["aoeu"], ""); oxExpect(map["aoeu"], "");
oxExpect(map.size(), 2u); oxExpect(map.size(), 2u);
ox::SmallMap<ox::String, ox::String> cmap; return ox::Error(0);
cmap["asdf"] = "aoeu";
auto constexpr constTest = [](ox::SmallMap<ox::String, ox::String> const&map) {
OX_REQUIRE(asdf, map.at("asdf"));
oxExpect(*asdf, "aoeu");
oxExpect(map.size(), 1u);
auto const aoeu = map.at("aoeu");
oxExpect(aoeu.ok(), false);
oxExpect(map.size(), 1u);
return ox::Error{};
};
return constTest(cmap);
} }
}, },
{ {

View File

@ -269,8 +269,8 @@ using TraceStream = NullStream;
inline void logError(const char *file, int line, const char *fmt, const Error &err) noexcept { inline void logError(const char *file, int line, const char *fmt, const Error &err) noexcept {
if (err) { if (err) {
TraceStream trc(file, line, "ox::error"); TraceStream trc(file, line, "ox::error");
if (err.src.file_name() != nullptr) { if (err.file != nullptr) {
trc << "Error: (" << err.src.file_name() << ":" << err.src.line() << "):"; trc << "Error: (" << err.file << ":" << err.line << "):";
} else { } else {
trc << "Error:"; trc << "Error:";
} }
@ -282,8 +282,8 @@ inline void logError(const char *file, int line, const Error &err) noexcept {
if (err) { if (err) {
TraceStream trc(file, line, "ox::error"); TraceStream trc(file, line, "ox::error");
trc << "Error:" << err; trc << "Error:" << err;
if (err.src.file_name() != nullptr) { if (err.file != nullptr) {
trc << "(" << err.src.file_name() << ":" << err.src.line() << ")"; trc << "(" << err.file << ":" << err.line << ")";
} }
} }
} }

View File

@ -19,15 +19,12 @@
namespace std { namespace std {
template<typename T> template<typename T>
inline constexpr bool is_union_v = __is_union(T); constexpr bool is_union_v = __is_union(T);
inline constexpr bool is_constant_evaluated() noexcept { constexpr bool is_constant_evaluated() noexcept {
return __builtin_is_constant_evaluated(); return __builtin_is_constant_evaluated();
} }
template<typename T>
inline constexpr bool is_trivially_copyable_v = __is_trivially_copyable(T);
} }
#endif #endif
@ -159,9 +156,6 @@ static_assert(is_class<int>::value == false);
template<typename T> template<typename T>
constexpr bool is_class_v = is_class<T>(); constexpr bool is_class_v = is_class<T>();
template<typename T>
inline constexpr bool is_trivially_copyable_v = std::is_trivially_copyable_v<T>;
template<typename T> template<typename T>
constexpr bool is_signed_v = integral_constant<bool, T(-1) < T(0)>::value; constexpr bool is_signed_v = integral_constant<bool, T(-1) < T(0)>::value;

View File

@ -313,8 +313,6 @@ class Vector: detail::VectorAllocator<T, Allocator, SmallVectorSize> {
constexpr void reserve(std::size_t cap) noexcept(useNoexcept); constexpr void reserve(std::size_t cap) noexcept(useNoexcept);
constexpr void shrink_to_fit() noexcept(useNoexcept);
private: private:
constexpr void reserveInsert( constexpr void reserveInsert(
std::size_t cap, std::size_t pos, std::size_t offset = 1) noexcept(useNoexcept); std::size_t cap, std::size_t pos, std::size_t offset = 1) noexcept(useNoexcept);
@ -343,7 +341,6 @@ constexpr Vector<T, SmallVectorSize, Allocator>::Vector(std::size_t size) noexce
template<typename T, std::size_t SmallVectorSize, typename Allocator> template<typename T, std::size_t SmallVectorSize, typename Allocator>
constexpr Vector<T, SmallVectorSize, Allocator>::Vector(std::initializer_list<T> list) noexcept { constexpr Vector<T, SmallVectorSize, Allocator>::Vector(std::initializer_list<T> list) noexcept {
reserve(list.size());
for (auto &item : list) { for (auto &item : list) {
emplace_back(std::move(item)); emplace_back(std::move(item));
} }
@ -678,24 +675,6 @@ constexpr void Vector<T, SmallVectorSize, Allocator>::reserve(std::size_t cap) n
} }
} }
template<typename T, std::size_t SmallVectorSize, typename Allocator>
constexpr void Vector<T, SmallVectorSize, Allocator>::shrink_to_fit() noexcept(useNoexcept) {
if (m_size == m_cap) {
return;
}
const auto oldItems = m_items;
const auto oldCap = m_cap;
m_cap = m_size;
this->allocate(&m_items, m_size);
if (oldItems) { // move over old items
for (std::size_t i = 0; i < m_size; ++i) {
std::construct_at(&m_items[i], std::move(oldItems[i]));
oldItems[i].~T();
}
this->deallocate(oldItems, oldCap);
}
}
template<typename T, std::size_t SmallVectorSize, typename Allocator> template<typename T, std::size_t SmallVectorSize, typename Allocator>
constexpr void Vector<T, SmallVectorSize, Allocator>::reserveInsert( constexpr void Vector<T, SmallVectorSize, Allocator>::reserveInsert(
std::size_t cap, std::size_t cap,

View File

@ -4,20 +4,17 @@
#include <ox/std/heapmgr.hpp> #include <ox/std/heapmgr.hpp>
#include <teagba/bios.hpp>
#include <teagba/registers.hpp>
namespace mgba { namespace mgba {
void initConsole(); void initConsole();
} }
#define MEM_HEAP_BEGIN reinterpret_cast<char*>(0x02000000) #define MEM_EWRAM_BEGIN reinterpret_cast<char*>(0x02000000)
#define MEM_HEAP_END reinterpret_cast<char*>(0x0203FFFF) #define MEM_EWRAM_END reinterpret_cast<char*>(0x0203FFFF)
#define HEAP_BEGIN reinterpret_cast<char*>(MEM_HEAP_BEGIN) #define HEAP_BEGIN reinterpret_cast<char*>(MEM_EWRAM_BEGIN)
// set size to half of EWRAM // set size to half of EWRAM
#define HEAP_SIZE ((MEM_HEAP_END - MEM_HEAP_BEGIN) / 2) #define HEAP_SIZE ((MEM_EWRAM_END - MEM_EWRAM_BEGIN) / 2)
#define HEAP_END reinterpret_cast<char*>(MEM_HEAP_BEGIN + HEAP_SIZE) #define HEAP_END reinterpret_cast<char*>(MEM_EWRAM_BEGIN + HEAP_SIZE)
extern void (*__preinit_array_start[]) (void); extern void (*__preinit_array_start[]) (void);
extern void (*__preinit_array_end[]) (void); extern void (*__preinit_array_end[]) (void);
@ -28,14 +25,6 @@ int main(int argc, const char **argv);
extern "C" { extern "C" {
void abort() {
REG_IE = 0;
teagba::intrwait(0, 0);
while (true);
}
void *__gxx_personality_v0{};
void __libc_init_array() { void __libc_init_array() {
auto preInits = __preinit_array_end - __preinit_array_start; auto preInits = __preinit_array_end - __preinit_array_start;
for (decltype(preInits) i = 0; i < preInits; i++) { for (decltype(preInits) i = 0; i < preInits; i++) {

View File

@ -162,9 +162,11 @@ The Ox way of doing things is the Olympic way of doing things.
### Error Handling ### Error Handling
Instead of throwing exceptions, generally try to use The GBA build has exceptions disabled.
[ox::Errors](deps/ox/ox-docs.md#error-handling) for error reporting, Instead of throwing exceptions, all engine code should return
but exceptions may be used where they make sense. [ox::Errors](deps/ox/ox-docs.md#error-handling) for error reporting.
For the sake of consistency, try to stick to ```ox::Error``` in non-engine code
as well, but non-engine code is free to use exceptions when they make sense.
Exceptions should generally just use ```OxException```, which is bascially an Exceptions should generally just use ```OxException```, which is bascially an
exception form of ```ox::Error```. exception form of ```ox::Error```.

View File

@ -28,11 +28,11 @@ project_name = sys.argv[2]
bin = f'./build/{host_env}-{current_build}/bin/' bin = f'./build/{host_env}-{current_build}/bin/'
project_bin = f'build/gba-release/bin/{project_name}.bin' project_bin = f'build/gba-release/bin/{project_name}.bin'
project_gba = f'{project_name}.gba' project_gba = f'{project_name}.gba'
project_manifest = f'{project_name.lower()}-manifest.json' project_manifest = f'{project_name}-manifest.json'
shutil.copyfile(project_bin, project_gba) shutil.copyfile(project_bin, project_gba)
subprocess.run([ subprocess.run([
f'{bin}/{project_name.lower()}-pack', f'{bin}/{project_name}-pack',
'-src', project_dir, '-src', project_dir,
'-rom-bin', project_gba, '-rom-bin', project_gba,
'-manifest', project_manifest]) '-manifest', project_manifest])

View File

@ -102,6 +102,8 @@ OX_MODEL_BEGIN(TileSheetSet)
OX_MODEL_FIELD(entries) OX_MODEL_FIELD(entries)
OX_MODEL_END() OX_MODEL_END()
void addEntry(TileSheetSet &set, ox::FileAddress path, int32_t begin = 0, int32_t size = -1) noexcept;
[[nodiscard]] [[nodiscard]]
int tileColumns(Context&) noexcept; int tileColumns(Context&) noexcept;
@ -142,10 +144,6 @@ ox::Error loadBgTileSheet(
unsigned cbb, unsigned cbb,
TileSheetSet const&set) noexcept; TileSheetSet const&set) noexcept;
void clearCbb(Context &ctx, unsigned cbb) noexcept;
void clearCbbs(Context &ctx) noexcept;
ox::Error loadBgTileSheet( ox::Error loadBgTileSheet(
Context &ctx, Context &ctx,
unsigned cbb, unsigned cbb,

View File

@ -1,11 +0,0 @@
/*
* Copyright 2016 - 2025 Gary Talent (gary@drinkingtea.net). All rights reserved.
*/
#pragma once
#include <studio/studio.hpp>
namespace nostalgia::core {
}

View File

@ -18,23 +18,6 @@
namespace nostalgia::core { namespace nostalgia::core {
struct SubSheetTemplate {
static constexpr auto TypeName = "net.drinkingtea.nostalgia.gfx.SubSheetTemplate";
static constexpr auto TypeVersion = 1;
ox::String name;
int32_t width{};
int32_t height{};
ox::Vector<SubSheetTemplate> subsheets;
};
OX_MODEL_BEGIN(SubSheetTemplate)
OX_MODEL_FIELD(name)
OX_MODEL_FIELD(width)
OX_MODEL_FIELD(height)
OX_MODEL_FIELD(subsheets)
OX_MODEL_END()
// Predecessor to TileSheet, kept for backward compatibility // Predecessor to TileSheet, kept for backward compatibility
struct TileSheetV1 { struct TileSheetV1 {
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.NostalgiaGraphic"; static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.NostalgiaGraphic";
@ -229,10 +212,6 @@ struct TileSheetV4 {
pixels(std::move(pPixels)) { pixels(std::move(pPixels)) {
} }
/**
*
* @return the dimensional size of the SubSheet (e.g. width * height)
*/
[[nodiscard]] [[nodiscard]]
constexpr std::size_t size() const noexcept { constexpr std::size_t size() const noexcept {
return static_cast<std::size_t>(columns) * static_cast<std::size_t>(rows); return static_cast<std::size_t>(columns) * static_cast<std::size_t>(rows);
@ -302,7 +281,7 @@ size_t getTileCnt(TileSheet const&ts) noexcept;
TileSheet::SubSheet const*getSubsheet(TileSheet const&ts, SubSheetId id) noexcept; TileSheet::SubSheet const*getSubsheet(TileSheet const&ts, SubSheetId id) noexcept;
[[nodiscard]] [[nodiscard]]
ox::Optional<size_t> getTileIdx(TileSheet const&ts, SubSheetId id) noexcept; size_t getTileIdx(TileSheet const&ts, SubSheetId id) noexcept;
[[nodiscard]] [[nodiscard]]
uint8_t getPixel4Bpp(TileSheet::SubSheet const&ss, std::size_t idx) noexcept; uint8_t getPixel4Bpp(TileSheet::SubSheet const&ss, std::size_t idx) noexcept;
@ -421,8 +400,6 @@ ox::Result<SubSheetId> getIdFor(TileSheet const&ts, ox::StringViewCR path) noexc
ox::Result<unsigned> getTileOffset(TileSheet const&ts, ox::StringViewCR pNamePath) noexcept; ox::Result<unsigned> getTileOffset(TileSheet const&ts, ox::StringViewCR pNamePath) noexcept;
ox::Result<uint32_t> getTileOffset(TileSheet const&ts, SubSheetId pId) noexcept;
ox::Result<ox::StringView> getNameFor(TileSheet::SubSheet const&ss, SubSheetId pId) noexcept; ox::Result<ox::StringView> getNameFor(TileSheet::SubSheet const&ss, SubSheetId pId) noexcept;
ox::Result<ox::StringView> getNameFor(TileSheet const&ts, SubSheetId pId) noexcept; ox::Result<ox::StringView> getNameFor(TileSheet const&ts, SubSheetId pId) noexcept;

View File

@ -63,19 +63,6 @@ ox::Error loadSpritePalette(
return {}; return {};
} }
void clearCbb(Context&, unsigned const cbb) noexcept {
for (auto &v : MEM_BG_TILES[cbb]) {
v = 0;
}
}
void clearCbbs(Context &ctx) noexcept {
clearCbb(ctx, 0);
clearCbb(ctx, 1);
clearCbb(ctx, 2);
clearCbb(ctx, 3);
}
static ox::Error loadTileSheetSet( static ox::Error loadTileSheetSet(
Context &ctx, Context &ctx,
ox::Span<uint16_t> tileMapTargetMem, ox::Span<uint16_t> tileMapTargetMem,
@ -112,10 +99,10 @@ ox::Error loadBgTileSheet(
size_t const tileCnt) noexcept { size_t const tileCnt) noexcept {
size_t const bppMod = ts.bpp == 4; size_t const bppMod = ts.bpp == 4;
size_t const bytesPerTile = PixelsPerTile >> bppMod; size_t const bytesPerTile = PixelsPerTile >> bppMod;
auto const cnt = (tileCnt * bytesPerTile) / 2; auto const pixCnt = tileCnt * bytesPerTile;
auto const srcPxIdx = srcTileIdx * bytesPerTile; auto const srcPxIdx = srcTileIdx * bytesPerTile;
auto const dstPxIdx = (dstTileIdx * bytesPerTile) / 2; auto const dstPxIdx = (dstTileIdx * bytesPerTile) / 2;
for (size_t i = 0; i < cnt; ++i) { for (size_t i = 0; i < pixCnt; ++i) {
auto const srcIdx = srcPxIdx + i * 2; auto const srcIdx = srcPxIdx + i * 2;
auto const p1 = static_cast<uint16_t>(ts.pixels[srcIdx]); auto const p1 = static_cast<uint16_t>(ts.pixels[srcIdx]);
auto const p2 = static_cast<uint16_t>(ts.pixels[srcIdx + 1]); auto const p2 = static_cast<uint16_t>(ts.pixels[srcIdx + 1]);

View File

@ -4,7 +4,6 @@
#include <ox/std/def.hpp> #include <ox/std/def.hpp>
#include <ox/std/realstd.hpp>
#include <keel/media.hpp> #include <keel/media.hpp>
#include <turbine/turbine.hpp> #include <turbine/turbine.hpp>
@ -49,10 +48,12 @@ OX_ALLOW_UNSAFE_BUFFERS_END
oxErrf("\tError Message:\t{}\n", err.msg); oxErrf("\tError Message:\t{}\n", err.msg);
} }
oxErrf("\tError Code:\t{}\n", static_cast<ErrorCode>(err)); oxErrf("\tError Code:\t{}\n", static_cast<ErrorCode>(err));
if (err.src.file_name() != nullptr) { if (err.file != nullptr) {
oxErrf("\tError Location:\t{}:{}\n", err.src.file_name(), err.src.line()); oxErrf("\tError Location:\t{}:{}\n", err.file, err.line);
} }
abort(); // disable all interrupt handling and IntrWait on no interrupts
REG_IE = 0;
teagba::intrwait(0, 0);
} }
} }

View File

@ -118,8 +118,8 @@ static void setSpriteBufferObject(
uint_t textureRow, uint_t textureRow,
uint_t flipX, uint_t flipX,
uint_t priority, uint_t priority,
ox::Span<float> vbo, float *vbo,
ox::Span<GLuint> ebo) noexcept { GLuint *ebo) noexcept {
// don't worry, this memcpy gets optimized to something much more ideal // don't worry, this memcpy gets optimized to something much more ideal
constexpr float xmod = 0.1f; constexpr float xmod = 0.1f;
constexpr float ymod = 0.1f; constexpr float ymod = 0.1f;
@ -138,12 +138,12 @@ static void setSpriteBufferObject(
enabled, x + xmod, y + ymod, prif, R, textureRowf + 0, // top right enabled, x + xmod, y + ymod, prif, R, textureRowf + 0, // top right
enabled, x, y + ymod, prif, L, textureRowf + 0, // top left enabled, x, y + ymod, prif, L, textureRowf + 0, // top left
}; };
ox::spancpy<float>(vbo, vertices); memcpy(vbo, vertices.data(), sizeof(vertices));
ox::Array<GLuint, SpriteVertexEboLength> const elms { ox::Array<GLuint, SpriteVertexEboLength> const elms {
vi + 0, vi + 1, vi + 2, vi + 0, vi + 1, vi + 2,
vi + 2, vi + 3, vi + 0, vi + 2, vi + 3, vi + 0,
}; };
ox::spancpy<GLuint>(ebo, elms); memcpy(ebo, elms.data(), sizeof(elms));
} }
static void setTileBufferObject( static void setTileBufferObject(
@ -155,8 +155,8 @@ static void setTileBufferObject(
float palOffset, float palOffset,
bool flipX, bool flipX,
bool flipY, bool flipY,
ox::Span<float> vbo, float *vbo,
ox::Span<GLuint> ebo) noexcept { GLuint *ebo) noexcept {
// don't worry, this memcpy gets optimized to something much more ideal // don't worry, this memcpy gets optimized to something much more ideal
constexpr float ymod = 0.1f; constexpr float ymod = 0.1f;
constexpr float xmod = 0.1f; constexpr float xmod = 0.1f;
@ -170,35 +170,24 @@ static void setTileBufferObject(
float const T = flipY ? 1 : 0; float const T = flipY ? 1 : 0;
float const B = flipY ? 0 : 1; float const B = flipY ? 0 : 1;
ox::Array<float, BgVertexVboLength> const vertices { ox::Array<float, BgVertexVboLength> const vertices {
x, y, prif, L, B, textureTileIdx, palOffset, // bottom left x, y, prif, L, B, textureTileIdx, palOffset, // bottom left
x + xmod, y, prif, R, B, textureTileIdx, palOffset, // bottom right x + xmod, y, prif, R, B, textureTileIdx, palOffset, // bottom right
x + xmod, y + ymod, prif, R, T, textureTileIdx, palOffset, // top right x + xmod, y + ymod, prif, R, T, textureTileIdx, palOffset, // top right
x, y + ymod, prif, L, T, textureTileIdx, palOffset, // top left x, y + ymod, prif, L, T, textureTileIdx, palOffset, // top left
}; };
ox::spancpy<float>(vbo, vertices); memcpy(vbo, vertices.data(), sizeof(vertices));
ox::Array<GLuint, BgVertexEboLength> const elms { ox::Array<GLuint, BgVertexEboLength> const elms {
vi + 0, vi + 1, vi + 2, vi + 0, vi + 1, vi + 2,
vi + 2, vi + 3, vi + 0, vi + 2, vi + 3, vi + 0,
}; };
ox::spancpy<GLuint>(ebo, elms); memcpy(ebo, elms.data(), sizeof(elms));
} }
static void initSpriteBufferObjects(Context &ctx, glutils::BufferSet &bs) noexcept { static void initSpriteBufferObjects(Context &ctx, glutils::BufferSet &bs) noexcept {
for (auto i = 0u; i < ctx.spriteCount; ++i) { for (auto i = 0u; i < ctx.spriteCount; ++i) {
auto const vbo = ox::Span{bs.vertices} auto vbo = &bs.vertices[i * static_cast<std::size_t>(SpriteVertexVboLength)];
+ i * static_cast<std::size_t>(SpriteVertexVboLength); auto ebo = &bs.elements[i * static_cast<std::size_t>(SpriteVertexEboLength)];
auto const ebo = ox::Span{bs.elements} setSpriteBufferObject(i * static_cast<uint_t>(SpriteVertexVboRows) * ctx.blocksPerSprite, 0, 0, 0, 0, false, 0, vbo, ebo);
+ i * static_cast<std::size_t>(SpriteVertexEboLength);
setSpriteBufferObject(
i * static_cast<uint_t>(SpriteVertexVboRows) * ctx.blocksPerSprite,
0,
0,
0,
0,
false,
0,
vbo,
ebo);
} }
} }
@ -206,10 +195,8 @@ static void initBackgroundBufferObjects(glutils::BufferSet &bs) noexcept {
for (auto x = 0u; x < TileColumns; ++x) { for (auto x = 0u; x < TileColumns; ++x) {
for (auto y = 0u; y < TileRows; ++y) { for (auto y = 0u; y < TileRows; ++y) {
const auto i = bgVertexRow(x, y); const auto i = bgVertexRow(x, y);
auto const vbo = ox::Span{bs.vertices} auto vbo = &bs.vertices[i * static_cast<std::size_t>(BgVertexVboLength)];
+ i * static_cast<std::size_t>(BgVertexVboLength); auto ebo = &bs.elements[i * static_cast<std::size_t>(BgVertexEboLength)];
auto const ebo = ox::Span{bs.elements}
+ i * static_cast<std::size_t>(BgVertexEboLength);
setTileBufferObject( setTileBufferObject(
static_cast<uint_t>(i * BgVertexVboRows), static_cast<uint_t>(i * BgVertexVboRows),
static_cast<float>(x), static_cast<float>(x),
@ -434,8 +421,8 @@ static void setSprite(
auto const eboIdx = eboBase + renderer::SpriteVertexEboLength * i; auto const eboIdx = eboBase + renderer::SpriteVertexEboLength * i;
oxAssert(vboIdx < ctx.spriteBlocks.vertices.size(), "vbo overflow"); oxAssert(vboIdx < ctx.spriteBlocks.vertices.size(), "vbo overflow");
oxAssert(eboIdx < ctx.spriteBlocks.elements.size(), "ebo overflow"); oxAssert(eboIdx < ctx.spriteBlocks.elements.size(), "ebo overflow");
auto const vbo = ox::Span{ctx.spriteBlocks.vertices} + vboIdx; auto const vbo = &ctx.spriteBlocks.vertices[vboIdx];
auto const ebo = ox::Span{ctx.spriteBlocks.elements} + eboIdx; auto const ebo = &ctx.spriteBlocks.elements[eboIdx];
renderer::setSpriteBufferObject( renderer::setSpriteBufferObject(
static_cast<uint_t>(vboIdx), static_cast<uint_t>(vboIdx),
enabled, enabled,
@ -569,7 +556,7 @@ static void copyPixels(
CompactTileSheet const&ts, CompactTileSheet const&ts,
ox::Span<uint32_t> dst, ox::Span<uint32_t> dst,
size_t const srcPxIdx, size_t const srcPxIdx,
size_t const pxlCnt) noexcept { size_t pxlCnt) noexcept {
size_t idx{}; size_t idx{};
if (ts.bpp == 4) { if (ts.bpp == 4) {
for (size_t i = 0; i < pxlCnt; i += 2) { for (size_t i = 0; i < pxlCnt; i += 2) {
@ -586,18 +573,6 @@ static void copyPixels(
} }
} }
void clearCbb(Context &ctx, unsigned const cbb) noexcept {
for (auto &v : ctx.cbbs[cbb].pixels) {
v = 0;
}
}
void clearCbbs(Context &ctx) noexcept {
for (unsigned i = 0 ; i < ctx.cbbs.size(); ++i) {
clearCbb(ctx, i);
}
}
ox::Error loadBgTileSheet( ox::Error loadBgTileSheet(
Context &ctx, Context &ctx,
unsigned const cbb, unsigned const cbb,
@ -681,8 +656,8 @@ void setBgTile(
const auto x = static_cast<uint_t>(column); const auto x = static_cast<uint_t>(column);
const auto i = renderer::bgVertexRow(x, y); const auto i = renderer::bgVertexRow(x, y);
auto &cbb = ctx.cbbs[z]; auto &cbb = ctx.cbbs[z];
const auto vbo = ox::Span{cbb.vertices} + i * renderer::BgVertexVboLength; const auto vbo = &cbb.vertices[i * renderer::BgVertexVboLength];
const auto ebo = ox::Span{cbb.elements} + i * renderer::BgVertexEboLength; const auto ebo = &cbb.elements[i * renderer::BgVertexEboLength];
auto &bg = ctx.backgrounds[bgIdx]; auto &bg = ctx.backgrounds[bgIdx];
renderer::setTileBufferObject( renderer::setTileBufferObject(
static_cast<uint_t>(i * renderer::BgVertexVboRows), static_cast<uint_t>(i * renderer::BgVertexVboRows),

View File

@ -66,10 +66,10 @@ static ox::Optional<size_t> getPixelIdx(
return ox::Optional<size_t>{}; return ox::Optional<size_t>{};
} }
ox::Optional<size_t> getTileIdx(TileSheet const&ts, SubSheetId const id) noexcept { size_t getTileIdx(TileSheet const&ts, SubSheetId const id) noexcept {
size_t idx{}; size_t idx{};
auto const out = getPixelIdx(ts.subsheet, id, idx, ts.bpp); auto const out = getPixelIdx(ts.subsheet, id, idx, ts.bpp);
return out ? ox::Optional<size_t>{ox::in_place, *out / PixelsPerTile} : out; return out.or_value(0) / PixelsPerTile;
} }
uint8_t getPixel4Bpp(TileSheet::SubSheet const&ss, std::size_t idx) noexcept { uint8_t getPixel4Bpp(TileSheet::SubSheet const&ss, std::size_t idx) noexcept {
@ -355,12 +355,12 @@ ox::Result<SubSheetId> getIdFor(TileSheet const&ts, ox::StringViewCR path) noexc
/** /**
* Gets the offset in tiles of the desired subsheet. * Gets the offset in tiles of the desired subsheet.
*/ */
static ox::Result<uint32_t> getTileOffset( static ox::Result<unsigned> getTileOffset(
TileSheet::SubSheet const&ss, TileSheet::SubSheet const&ss,
ox::SpanView<ox::StringView> const&pNamePath, ox::SpanView<ox::StringView> const&pNamePath,
int8_t pBpp, int8_t pBpp,
std::size_t pIt = 0, std::size_t pIt = 0,
uint32_t pCurrentTotal = 0) noexcept { unsigned pCurrentTotal = 0) noexcept {
// pIt == pNamePath.size() - 1 && // pIt == pNamePath.size() - 1 &&
if (ss.name != pNamePath[pIt]) { if (ss.name != pNamePath[pIt]) {
return ox::Error(2, "Wrong branch"); return ox::Error(2, "Wrong branch");
@ -374,14 +374,12 @@ static ox::Result<uint32_t> getTileOffset(
if (!err) { if (!err) {
return offset; return offset;
} }
// Possible bug? Shoud this be usinga a recursive version of
// pixelCnt will count pixels in subsheets of sub as well.
pCurrentTotal += pixelCnt(sub, pBpp) / PixelsPerTile; pCurrentTotal += pixelCnt(sub, pBpp) / PixelsPerTile;
} }
return ox::Error(1, "SubSheet not found"); return ox::Error(1, "SubSheet not found");
} }
ox::Result<uint32_t> getTileOffset(TileSheet const&ts, ox::StringViewCR pNamePath) noexcept { ox::Result<unsigned> getTileOffset(TileSheet const&ts, ox::StringViewCR pNamePath) noexcept {
return core::getTileOffset(ts.subsheet, ox::split<8>(pNamePath, '.'), ts.bpp); return core::getTileOffset(ts.subsheet, ox::split<8>(pNamePath, '.'), ts.bpp);
} }

View File

@ -11,7 +11,7 @@ target_link_libraries(
target_compile_definitions( target_compile_definitions(
NostalgiaStudio PUBLIC NostalgiaStudio PUBLIC
OLYMPIC_APP_VERSION="dev build" OLYMPIC_APP_VERSION="d2024.12.2"
) )
install( install(

View File

@ -196,15 +196,15 @@ class AssetManager {
template<typename T> template<typename T>
class AssetTypeManager: public AssetTypeManagerBase { class AssetTypeManager: public AssetTypeManagerBase {
public: public:
using Loader = std::function<ox::Result<T>(ox::StringViewCR assetId)>; using Loader = std::function<ox::Result<T>(ox::StringView assetId)>;
private: private:
Loader m_loader{}; Loader m_loader{};
ox::HashMap<ox::String, ox::UPtr<AssetContainer<T>>> m_cache; ox::HashMap<ox::String, ox::UPtr<AssetContainer<T>>> m_cache;
public: public:
AssetTypeManager(Loader &&loader) noexcept: m_loader(std::move(loader)) {} AssetTypeManager(Loader loader) noexcept: m_loader(loader) {}
ox::Result<AssetRef<T>> getAsset(ox::StringViewCR assetId) const noexcept { ox::Result<AssetRef<T>> getAsset(ox::StringView const assetId) const noexcept {
OX_REQUIRE(out, m_cache.at(assetId)); OX_REQUIRE(out, m_cache.at(assetId));
if (!out || !*out) { if (!out || !*out) {
return ox::Error(1, "asset is null"); return ox::Error(1, "asset is null");
@ -212,7 +212,7 @@ class AssetManager {
return AssetRef<T>(out->get()); return AssetRef<T>(out->get());
} }
ox::Result<AssetRef<T>> loadAsset(ox::StringViewCR assetId) noexcept { ox::Result<AssetRef<T>> loadAsset(ox::StringView const assetId) noexcept {
auto &p = m_cache[assetId]; auto &p = m_cache[assetId];
OX_REQUIRE_M(obj, m_loader(assetId)); OX_REQUIRE_M(obj, m_loader(assetId));
if (!p) { if (!p) {
@ -224,7 +224,7 @@ class AssetManager {
return AssetRef<T>(p.get()); return AssetRef<T>(p.get());
} }
ox::Error reloadAsset(ox::StringViewCR assetId) noexcept { ox::Error reloadAsset(ox::StringView const assetId) noexcept {
auto &p = m_cache[assetId]; auto &p = m_cache[assetId];
OX_REQUIRE_M(obj, m_loader(assetId)); OX_REQUIRE_M(obj, m_loader(assetId));
if (!p) { if (!p) {
@ -247,7 +247,7 @@ class AssetManager {
}; };
ox::HashMap<ox::String, ox::UPtr<AssetTypeManagerBase>> m_assetTypeManagers; ox::HashMap<ox::String, ox::UPtr<AssetTypeManagerBase>> m_assetTypeManagers;
ox::HashMap<ox::String, ox::Signal<ox::Error(ox::StringViewCR assetId)>> m_fileUpdated; ox::HashMap<ox::String, ox::Signal<ox::Error(ox::StringView assetId)>> m_fileUpdated;
template<typename T> template<typename T>
ox::Result<AssetTypeManager<T>*> getTypeManager() noexcept { ox::Result<AssetTypeManager<T>*> getTypeManager() noexcept {
@ -273,18 +273,18 @@ class AssetManager {
} }
template<typename T> template<typename T>
ox::Result<AssetRef<T>> getAsset(ox::StringViewCR assetId) noexcept { ox::Result<AssetRef<T>> getAsset(ox::StringView assetId) noexcept {
OX_REQUIRE(m, getTypeManager<T>()); OX_REQUIRE(m, getTypeManager<T>());
return m->getAsset(assetId); return m->getAsset(assetId);
} }
ox::Error reloadAsset(ox::StringViewCR assetId) noexcept { ox::Error reloadAsset(ox::StringView assetId) noexcept {
m_fileUpdated[assetId].emit(assetId); m_fileUpdated[assetId].emit(assetId);
return {}; return {};
} }
template<typename T> template<typename T>
ox::Result<AssetRef<T>> loadAsset(ox::StringViewCR assetId) noexcept { ox::Result<AssetRef<T>> loadAsset(ox::StringView assetId) noexcept {
OX_REQUIRE(m, getTypeManager<T>()); OX_REQUIRE(m, getTypeManager<T>());
OX_REQUIRE(out, m->loadAsset(assetId)); OX_REQUIRE(out, m->loadAsset(assetId));
m_fileUpdated[assetId].connect(m, &AssetTypeManager<T>::reloadAsset); m_fileUpdated[assetId].connect(m, &AssetTypeManager<T>::reloadAsset);

View File

@ -18,9 +18,9 @@
namespace studio { namespace studio {
static ox::Vector<Module const*> modules; static ox::Vector<studio::Module const*> modules;
void registerModule(Module const*mod) noexcept { void registerModule(studio::Module const*mod) noexcept {
if (mod) { if (mod) {
modules.emplace_back(mod); modules.emplace_back(mod);
} }
@ -45,25 +45,25 @@ OX_MODEL_END()
StudioUI::StudioUI(turbine::Context &ctx, ox::StringParam projectDataDir) noexcept: StudioUI::StudioUI(turbine::Context &ctx, ox::StringParam projectDataDir) noexcept:
m_sctx(*this, ctx), m_sctx(*this, ctx),
m_tctx(ctx), m_ctx(ctx),
m_projectDataDir(std::move(projectDataDir)), m_projectDataDir(std::move(projectDataDir)),
m_projectExplorer(m_tctx), m_projectExplorer(m_ctx),
m_newProject(m_projectDataDir), m_newProject(m_projectDataDir),
m_aboutPopup(m_tctx) { m_aboutPopup(m_ctx) {
turbine::setApplicationData(m_tctx, &m_sctx); turbine::setApplicationData(m_ctx, &m_sctx);
m_projectExplorer.fileChosen.connect(this, &StudioUI::openFile); m_projectExplorer.fileChosen.connect(this, &StudioUI::openFile);
m_newProject.finished.connect(this, &StudioUI::createOpenProject); m_newProject.finished.connect(this, &StudioUI::createOpenProject);
m_newMenu.finished.connect(this, &StudioUI::openFile); m_newMenu.finished.connect(this, &StudioUI::openFile);
ImGui::GetIO().IniFilename = nullptr; ImGui::GetIO().IniFilename = nullptr;
loadModules(); loadModules();
// open project and files // open project and files
auto const [config, err] = studio::readConfig<StudioConfig>(keelCtx(m_tctx)); auto const [config, err] = studio::readConfig<StudioConfig>(keelCtx(m_ctx));
m_showProjectExplorer = config.showProjectExplorer; m_showProjectExplorer = config.showProjectExplorer;
if (!err) { if (!err) {
auto const openProjErr = openProjectPath(config.projectPath); auto const openProjErr = openProjectPath(config.projectPath);
if (!openProjErr) { if (!openProjErr) {
for (auto const&f: config.openFiles) { for (auto const&f: config.openFiles) {
auto const openFileErr = openFileActiveTab(f, config.activeTabItemName == f); auto openFileErr = openFileActiveTab(f, config.activeTabItemName == f);
if (openFileErr) { if (openFileErr) {
oxErrorf("\nCould not open editor for file:\n\t{}\nReason:\n\t{}\n", f, toStr(openFileErr)); oxErrorf("\nCould not open editor for file:\n\t{}\nReason:\n\t{}\n", f, toStr(openFileErr));
continue; continue;
@ -77,13 +77,13 @@ StudioUI::StudioUI(turbine::Context &ctx, ox::StringParam projectDataDir) noexce
} else { } else {
oxErrf( oxErrf(
"Could not open studio config file: {}: {} ({}:{})\n", "Could not open studio config file: {}: {} ({}:{})\n",
err.errCode, toStr(err), err.src.file_name(), err.src.line()); err.errCode, toStr(err), err.file, err.line);
} }
} }
} }
void StudioUI::handleKeyEvent(turbine::Key const key, bool const down) noexcept { void StudioUI::handleKeyEvent(turbine::Key key, bool down) noexcept {
for (auto const p : m_popups) { for (auto p : m_popups) {
if (p->isOpen()) { if (p->isOpen()) {
if (key == turbine::Key::Escape) { if (key == turbine::Key::Escape) {
p->close(); p->close();
@ -118,13 +118,13 @@ void StudioUI::draw() noexcept {
for (auto &w: m_widgets) { for (auto &w: m_widgets) {
w->draw(m_sctx); w->draw(m_sctx);
} }
for (auto const p: m_popups) { for (auto p: m_popups) {
p->draw(m_sctx); p->draw(m_sctx);
} }
} }
ImGui::End(); ImGui::End();
handleKeyInput(); handleKeyInput();
m_taskRunner.update(m_tctx); m_taskRunner.update(m_ctx);
} }
void StudioUI::drawMenu() noexcept { void StudioUI::drawMenu() noexcept {
@ -143,7 +143,7 @@ void StudioUI::drawMenu() noexcept {
m_activeEditor->save(); m_activeEditor->save();
} }
if (ImGui::MenuItem("Quit", "Ctrl+Q")) { if (ImGui::MenuItem("Quit", "Ctrl+Q")) {
turbine::requestShutdown(m_tctx); turbine::requestShutdown(m_ctx);
} }
ImGui::EndMenu(); ImGui::EndMenu();
} }
@ -168,7 +168,7 @@ void StudioUI::drawMenu() noexcept {
ImGui::EndMenu(); ImGui::EndMenu();
} }
if (ImGui::BeginMenu("View")) { if (ImGui::BeginMenu("View")) {
if (ImGui::MenuItem("Project Explorer", "Ctrl+Shift+1", m_showProjectExplorer)) { if (ImGui::MenuItem("Project Explorer", "Ctrl+1", m_showProjectExplorer)) {
toggleProjectExplorer(); toggleProjectExplorer();
} }
ImGui::EndMenu(); ImGui::EndMenu();
@ -204,10 +204,9 @@ void StudioUI::drawTabs() noexcept {
if (ImGui::BeginTabItem(e->itemDisplayName().c_str(), &open, flags)) { if (ImGui::BeginTabItem(e->itemDisplayName().c_str(), &open, flags)) {
if (m_activeEditor != e.get()) [[unlikely]] { if (m_activeEditor != e.get()) [[unlikely]] {
m_activeEditor = e.get(); m_activeEditor = e.get();
studio::editConfig<StudioConfig>(keelCtx(m_tctx), [&](StudioConfig &config) { studio::editConfig<StudioConfig>(keelCtx(m_ctx), [&](StudioConfig &config) {
config.activeTabItemName = m_activeEditor->itemPath(); config.activeTabItemName = m_activeEditor->itemPath();
}); });
turbine::setRefreshWithin(m_tctx, 0);
} else [[likely]] { } else [[likely]] {
if (m_activeEditorUpdatePending == e.get()) [[unlikely]] { if (m_activeEditorUpdatePending == e.get()) [[unlikely]] {
m_activeEditorUpdatePending = nullptr; m_activeEditorUpdatePending = nullptr;
@ -228,7 +227,7 @@ void StudioUI::drawTabs() noexcept {
try { try {
OX_THROW_ERROR(m_editors.erase(it).moveTo(it)); OX_THROW_ERROR(m_editors.erase(it).moveTo(it));
} catch (ox::Exception const&ex) { } catch (ox::Exception const&ex) {
oxErrf("Editor tab deletion failed: {} ({}:{})\n", ex.what(), ex.src.file_name(), ex.src.line()); oxErrf("Editor tab deletion failed: {} ({}:{})\n", ex.what(), ex.file, ex.line);
} catch (std::exception const&ex) { } catch (std::exception const&ex) {
oxErrf("Editor tab deletion failed: {}\n", ex.what()); oxErrf("Editor tab deletion failed: {}\n", ex.what());
} }
@ -238,13 +237,13 @@ void StudioUI::drawTabs() noexcept {
} }
} }
void StudioUI::loadEditorMaker(EditorMaker const&editorMaker) noexcept { void StudioUI::loadEditorMaker(studio::EditorMaker const&editorMaker) noexcept {
for (auto const&ext : editorMaker.fileTypes) { for (auto const&ext : editorMaker.fileTypes) {
m_editorMakers[ext] = editorMaker.make; m_editorMakers[ext] = editorMaker.make;
} }
} }
void StudioUI::loadModule(Module const&mod) noexcept { void StudioUI::loadModule(studio::Module const&mod) noexcept {
for (auto const&editorMaker : mod.editors(m_sctx)) { for (auto const&editorMaker : mod.editors(m_sctx)) {
loadEditorMaker(editorMaker); loadEditorMaker(editorMaker);
} }
@ -261,20 +260,20 @@ void StudioUI::loadModules() noexcept {
void StudioUI::toggleProjectExplorer() noexcept { void StudioUI::toggleProjectExplorer() noexcept {
m_showProjectExplorer = !m_showProjectExplorer; m_showProjectExplorer = !m_showProjectExplorer;
editConfig<StudioConfig>(keelCtx(m_tctx), [&](StudioConfig &config) { studio::editConfig<StudioConfig>(keelCtx(m_ctx), [&](StudioConfig &config) {
config.showProjectExplorer = m_showProjectExplorer; config.showProjectExplorer = m_showProjectExplorer;
}); });
} }
void StudioUI::redo() noexcept { void StudioUI::redo() noexcept {
auto const undoStack = m_activeEditor ? m_activeEditor->undoStack() : nullptr; auto undoStack = m_activeEditor ? m_activeEditor->undoStack() : nullptr;
if (undoStack && undoStack->canRedo()) { if (undoStack && undoStack->canRedo()) {
oxLogError(m_activeEditor->undoStack()->redo()); oxLogError(m_activeEditor->undoStack()->redo());
} }
} }
void StudioUI::undo() noexcept { void StudioUI::undo() noexcept {
auto const undoStack = m_activeEditor ? m_activeEditor->undoStack() : nullptr; auto undoStack = m_activeEditor ? m_activeEditor->undoStack() : nullptr;
if (undoStack && undoStack->canUndo()) { if (undoStack && undoStack->canUndo()) {
oxLogError(m_activeEditor->undoStack()->undo()); oxLogError(m_activeEditor->undoStack()->undo());
} }
@ -293,7 +292,7 @@ void StudioUI::handleKeyInput() noexcept {
m_activeEditor->copy(); m_activeEditor->copy();
} }
} else if (ImGui::IsKeyPressed(ImGuiKey_N)) { } else if (ImGui::IsKeyPressed(ImGuiKey_N)) {
if (turbine::buttonDown(m_tctx, turbine::Key::Mod_Shift)) { if (turbine::buttonDown(m_ctx, turbine::Key::Mod_Shift)) {
m_newProject.open(); m_newProject.open();
} else { } else {
m_newMenu.open(); m_newMenu.open();
@ -303,7 +302,7 @@ void StudioUI::handleKeyInput() noexcept {
} else if (ImGui::IsKeyPressed(ImGuiKey_S)) { } else if (ImGui::IsKeyPressed(ImGuiKey_S)) {
save(); save();
} else if (ImGui::IsKeyPressed(ImGuiKey_Q)) { } else if (ImGui::IsKeyPressed(ImGuiKey_Q)) {
turbine::requestShutdown(m_tctx); turbine::requestShutdown(m_ctx);
} else if (ImGui::IsKeyPressed(ImGuiKey_V)) { } else if (ImGui::IsKeyPressed(ImGuiKey_V)) {
if (m_activeEditor && m_activeEditor->pasteEnabled()) { if (m_activeEditor && m_activeEditor->pasteEnabled()) {
m_activeEditor->paste(); m_activeEditor->paste();
@ -318,22 +317,8 @@ void StudioUI::handleKeyInput() noexcept {
} else if (ImGui::IsKeyPressed(ImGuiKey_Z)) { } else if (ImGui::IsKeyPressed(ImGuiKey_Z)) {
auto const undoStack = m_activeEditor ? m_activeEditor->undoStack() : nullptr; auto const undoStack = m_activeEditor ? m_activeEditor->undoStack() : nullptr;
if (undoStack) { oxLogError(undoStack->undo()); } if (undoStack) { oxLogError(undoStack->undo()); }
} else if (ImGui::IsKeyPressed(ImGuiKey_1) && ImGui::IsKeyDown(ImGuiKey_ModShift)) { } else if (ImGui::IsKeyPressed(ImGuiKey_1)) {
toggleProjectExplorer(); toggleProjectExplorer();
} else {
if (!m_editors.empty()) {
auto const range = ox::min<size_t>(9u, m_editors.size()) - 1;
for (auto i = 0u; i < 9; ++i) {
if (ImGui::IsKeyPressed(static_cast<ImGuiKey>(static_cast<int>(ImGuiKey_1) + i))) {
m_activeEditor = m_editors[i < m_editors.size() ? i : range].get();
m_activeEditorUpdatePending = m_activeEditor;
}
}
if (ImGui::IsKeyPressed(ImGuiKey_0)) {
m_activeEditor = m_editors[10 < m_editors.size() ? 10 : range].get();
m_activeEditorUpdatePending = m_activeEditor;
}
}
} }
} }
} }
@ -348,18 +333,18 @@ ox::Error StudioUI::createOpenProject(ox::StringViewCR path) noexcept {
ox::Error StudioUI::openProjectPath(ox::StringParam path) noexcept { ox::Error StudioUI::openProjectPath(ox::StringParam path) noexcept {
OX_REQUIRE_M(fs, keel::loadRomFs(path.view())); OX_REQUIRE_M(fs, keel::loadRomFs(path.view()));
OX_RETURN_ERROR(keel::setRomFs(keelCtx(m_tctx), std::move(fs))); OX_RETURN_ERROR(keel::setRomFs(keelCtx(m_ctx), std::move(fs)));
OX_RETURN_ERROR( OX_RETURN_ERROR(
ox::make_unique_catch<Project>(keelCtx(m_tctx), std::move(path), m_projectDataDir) ox::make_unique_catch<studio::Project>(keelCtx(m_ctx), std::move(path), m_projectDataDir)
.moveTo(m_project)); .moveTo(m_project));
auto const sctx = applicationData<StudioContext>(m_tctx); auto const sctx = applicationData<studio::StudioContext>(m_ctx);
sctx->project = m_project.get(); sctx->project = m_project.get();
turbine::setWindowTitle(m_tctx, ox::sfmt("{} - {}", keelCtx(m_tctx).appName, m_project->projectPath())); turbine::setWindowTitle(m_ctx, ox::sfmt("{} - {}", keelCtx(m_ctx).appName, m_project->projectPath()));
m_project->fileAdded.connect(&m_projectExplorer, &ProjectExplorer::refreshProjectTreeModel); m_project->fileAdded.connect(&m_projectExplorer, &ProjectExplorer::refreshProjectTreeModel);
m_project->fileDeleted.connect(&m_projectExplorer, &ProjectExplorer::refreshProjectTreeModel); m_project->fileDeleted.connect(&m_projectExplorer, &ProjectExplorer::refreshProjectTreeModel);
m_openFiles.clear(); m_openFiles.clear();
m_editors.clear(); m_editors.clear();
studio::editConfig<StudioConfig>(keelCtx(m_tctx), [&](StudioConfig &config) { studio::editConfig<StudioConfig>(keelCtx(m_ctx), [&](StudioConfig &config) {
config.projectPath = ox::String(m_project->projectPath()); config.projectPath = ox::String(m_project->projectPath());
config.openFiles.clear(); config.openFiles.clear();
}); });
@ -370,7 +355,7 @@ ox::Error StudioUI::openFile(ox::StringViewCR path) noexcept {
return openFileActiveTab(path, true); return openFileActiveTab(path, true);
} }
ox::Error StudioUI::openFileActiveTab(ox::StringViewCR path, bool const makeActiveTab) noexcept { ox::Error StudioUI::openFileActiveTab(ox::StringViewCR path, bool makeActiveTab) noexcept {
if (!m_project) { if (!m_project) {
return ox::Error(1, "No project open to open a file from"); return ox::Error(1, "No project open to open a file from");
} }
@ -384,7 +369,7 @@ ox::Error StudioUI::openFileActiveTab(ox::StringViewCR path, bool const makeActi
} }
return {}; return {};
} }
OX_REQUIRE(ext, fileExt(path)); OX_REQUIRE(ext, studio::fileExt(path));
// create Editor // create Editor
BaseEditor *editor = nullptr; BaseEditor *editor = nullptr;
auto const err = m_editorMakers.contains(ext) ? auto const err = m_editorMakers.contains(ext) ?
@ -394,7 +379,7 @@ ox::Error StudioUI::openFileActiveTab(ox::StringViewCR path, bool const makeActi
if constexpr(!ox::defines::Debug) { if constexpr(!ox::defines::Debug) {
oxErrf("Could not open Editor: {}\n", toStr(err)); oxErrf("Could not open Editor: {}\n", toStr(err));
} else { } else {
oxErrf("Could not open Editor: {} ({}:{})\n", err.errCode, err.src.file_name(), err.src.line()); oxErrf("Could not open Editor: {} ({}:{})\n", err.errCode, err.file, err.line);
} }
return err; return err;
} }
@ -406,7 +391,7 @@ ox::Error StudioUI::openFileActiveTab(ox::StringViewCR path, bool const makeActi
m_activeEditorUpdatePending = editor; m_activeEditorUpdatePending = editor;
} }
// save to config // save to config
studio::editConfig<StudioConfig>(keelCtx(m_tctx), [&path](StudioConfig &config) { studio::editConfig<StudioConfig>(keelCtx(m_ctx), [&path](StudioConfig &config) {
if (!config.openFiles.contains(path)) { if (!config.openFiles.contains(path)) {
config.openFiles.emplace_back(path); config.openFiles.emplace_back(path);
} }
@ -420,7 +405,7 @@ ox::Error StudioUI::closeFile(ox::StringViewCR path) noexcept {
} }
std::ignore = m_openFiles.erase(std::remove(m_openFiles.begin(), m_openFiles.end(), path)); std::ignore = m_openFiles.erase(std::remove(m_openFiles.begin(), m_openFiles.end(), path));
// save to config // save to config
studio::editConfig<StudioConfig>(keelCtx(m_tctx), [&](StudioConfig &config) { studio::editConfig<StudioConfig>(keelCtx(m_ctx), [&](StudioConfig &config) {
std::ignore = config.openFiles.erase(std::remove(config.openFiles.begin(), config.openFiles.end(), path)); std::ignore = config.openFiles.erase(std::remove(config.openFiles.begin(), config.openFiles.end(), path));
}); });
return {}; return {};

View File

@ -24,23 +24,23 @@ class StudioUI: public ox::SignalHandler {
friend class StudioUIDrawer; friend class StudioUIDrawer;
private: private:
StudioContext m_sctx; studio::StudioContext m_sctx;
turbine::Context &m_tctx; turbine::Context &m_ctx;
ox::String m_projectDataDir; ox::String m_projectDataDir;
ox::UPtr<Project> m_project; ox::UPtr<studio::Project> m_project;
TaskRunner m_taskRunner; studio::TaskRunner m_taskRunner;
ox::Vector<ox::UPtr<BaseEditor>> m_editors; ox::Vector<ox::UPtr<studio::BaseEditor>> m_editors;
ox::Vector<ox::UPtr<Widget>> m_widgets; ox::Vector<ox::UPtr<studio::Widget>> m_widgets;
ox::HashMap<ox::String, EditorMaker::Func> m_editorMakers; ox::HashMap<ox::String, studio::EditorMaker::Func> m_editorMakers;
ProjectExplorer m_projectExplorer; ProjectExplorer m_projectExplorer;
ox::Vector<ox::String> m_openFiles; ox::Vector<ox::String> m_openFiles;
BaseEditor *m_activeEditorOnLastDraw = nullptr; studio::BaseEditor *m_activeEditorOnLastDraw = nullptr;
BaseEditor *m_activeEditor = nullptr; studio::BaseEditor *m_activeEditor = nullptr;
BaseEditor *m_activeEditorUpdatePending = nullptr; studio::BaseEditor *m_activeEditorUpdatePending = nullptr;
NewMenu m_newMenu; NewMenu m_newMenu;
NewProject m_newProject; NewProject m_newProject;
AboutPopup m_aboutPopup; AboutPopup m_aboutPopup;
ox::Array<Popup*, 3> const m_popups = { ox::Array<studio::Popup*, 3> const m_popups = {
&m_newMenu, &m_newMenu,
&m_newProject, &m_newProject,
&m_aboutPopup &m_aboutPopup
@ -53,7 +53,7 @@ class StudioUI: public ox::SignalHandler {
void handleKeyEvent(turbine::Key, bool down) noexcept; void handleKeyEvent(turbine::Key, bool down) noexcept;
[[nodiscard]] [[nodiscard]]
constexpr Project *project() noexcept { constexpr studio::Project *project() noexcept {
return m_project.get(); return m_project.get();
} }
@ -67,9 +67,9 @@ class StudioUI: public ox::SignalHandler {
void drawTabs() noexcept; void drawTabs() noexcept;
void loadEditorMaker(EditorMaker const&editorMaker) noexcept; void loadEditorMaker(studio::EditorMaker const&editorMaker) noexcept;
void loadModule(Module const&mod) noexcept; void loadModule(studio::Module const&mod) noexcept;
void loadModules() noexcept; void loadModules() noexcept;

View File

@ -13,7 +13,7 @@ namespace studio {
class NoChangesException: public ox::Exception { class NoChangesException: public ox::Exception {
public: public:
inline NoChangesException(std::source_location sloc = std::source_location::current()): inline NoChangesException(std::source_location sloc = std::source_location::current()):
ox::Exception(1, "Command makes no changes.", sloc) {} ox::Exception(sloc.file_name(), sloc.line(), 1, "Command makes no changes.") {}
}; };
class UndoCommand { class UndoCommand {

View File

@ -46,7 +46,7 @@ void BaseEditor::save() noexcept {
setUnsavedChanges(false); setUnsavedChanges(false);
} else { } else {
if constexpr(ox::defines::Debug) { if constexpr(ox::defines::Debug) {
oxErrorf("Could not save file {}: {} ({}:{})", itemPath(), toStr(err), err.src.file_name(), err.src.line()); oxErrorf("Could not save file {}: {} ({}:{})", itemPath(), toStr(err), err.file, err.line);
} else { } else {
oxErrorf("Could not save file {}: {}", itemPath(), toStr(err)); oxErrorf("Could not save file {}: {}", itemPath(), toStr(err));
} }

View File

@ -19,7 +19,7 @@ target_include_directories(
) )
target_sources( target_sources(
Turbine PRIVATE Turbine PUBLIC
turbine.cpp turbine.cpp
) )