Compare commits
31 Commits
e9965a63ce
...
2c7e134606
Author | SHA1 | Date | |
---|---|---|---|
2c7e134606 | |||
dd12509d7d | |||
546ce9b253 | |||
fddc6c2d04 | |||
7194f81b5b | |||
9af8530e24 | |||
b8c0bbe03a | |||
a36a642cf5 | |||
834d01226d | |||
651db7a842 | |||
b56d3692d0 | |||
2a8f7e074f | |||
bccc58c463 | |||
272aba8eb5 | |||
ab7dd9189e | |||
7beb3cc6fc | |||
4a95a79926 | |||
986ee3d7b0 | |||
ae9272841f | |||
19d5641c6e | |||
21131a35a3 | |||
b58431c09a | |||
488f73f60f | |||
a5547487f8 | |||
9583b223ca | |||
aab02f25c0 | |||
c75ff7881f | |||
3510e38ae5 | |||
06f6656c85 | |||
b576a7ec12 | |||
8c1ad5ed63 |
2
deps/glfw/src/CMakeLists.txt
vendored
2
deps/glfw/src/CMakeLists.txt
vendored
@ -88,7 +88,7 @@ if (CMAKE_VERSION VERSION_LESS "3.16" AND APPLE)
|
||||
LANGUAGE C)
|
||||
endif()
|
||||
|
||||
add_library(glfw ${glfw_SOURCES} ${glfw_HEADERS})
|
||||
add_library(glfw OBJECT ${glfw_SOURCES} ${glfw_HEADERS})
|
||||
set_target_properties(glfw PROPERTIES
|
||||
OUTPUT_NAME ${GLFW_LIB_NAME}
|
||||
VERSION ${GLFW_VERSION_MAJOR}.${GLFW_VERSION_MINOR}
|
||||
|
2
deps/ox/CMakeLists.txt
vendored
2
deps/ox/CMakeLists.txt
vendored
@ -76,7 +76,7 @@ enable_testing()
|
||||
|
||||
include_directories(src)
|
||||
|
||||
install(FILES OxConfig.cmake DESTINATION lib/ox)
|
||||
install(FILES OxConfig.cmake DESTINATION lib/cmake/ox)
|
||||
|
||||
if(OX_USE_STDLIB)
|
||||
set(JSONCPP_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/deps/jsoncpp/include")
|
||||
|
25
deps/ox/OxConfig.cmake
vendored
25
deps/ox/OxConfig.cmake
vendored
@ -1,15 +1,16 @@
|
||||
if("${CMAKE_FIND_ROOT_PATH}" STREQUAL "")
|
||||
set(Ox_INCLUDE_DIRS /usr/local/include/)
|
||||
set(OxStd_LIBRARY /usr/local/lib/ox/libOxStd.a)
|
||||
set(OxFS_LIBRARY /usr/local/lib/ox/libOxFS.a)
|
||||
set(OxClArgs_LIBRARY /usr/local/lib/ox/libOxClArgs.a)
|
||||
set(OxMetalClaw_LIBRARY /usr/local/lib/ox/libOxMetalClaw.a)
|
||||
set(OxModel_LIBRARY /usr/local/lib/ox/libOxModelClaw.a)
|
||||
set(OX_PATH /usr/local/include/)
|
||||
else("${CMAKE_FIND_ROOT_PATH}" STREQUAL "")
|
||||
set(Ox_INCLUDE_DIRS ${CMAKE_FIND_ROOT_PATH}/include/)
|
||||
set(OxStd_LIBRARY ${CMAKE_FIND_ROOT_PATH}/lib/ox/libOxStd.a)
|
||||
set(OxFS_LIBRARY ${CMAKE_FIND_ROOT_PATH}/lib/ox/libOxFS.a)
|
||||
set(OxClArgs_LIBRARY ${CMAKE_FIND_ROOT_PATH}/lib/ox/libOxClArgs.a)
|
||||
set(OxMetalClaw_LIBRARY ${CMAKE_FIND_ROOT_PATH}/lib/ox/libOxMetalClaw.a)
|
||||
set(OxModel_LIBRARY ${CMAKE_FIND_ROOT_PATH}/lib/ox/libOxModel.a)
|
||||
set(OX_PATH ${CMAKE_FIND_ROOT_PATH})
|
||||
endif("${CMAKE_FIND_ROOT_PATH}" STREQUAL "")
|
||||
|
||||
set(OxClArgs_LIBRARY ${OX_PATH}/lib/ox/libOxClArgs.a)
|
||||
set(OxEvent_LIBRARY ${OX_PATH}/lib/ox/libOxEvent.a)
|
||||
set(OxFS_LIBRARY ${OX_PATH}/lib/ox/libOxFS.a)
|
||||
set(OxLogConn_LIBRARY ${OX_PATH}/lib/ox/libOxLogConn.a)
|
||||
set(OxMetalClaw_LIBRARY ${OX_PATH}/lib/ox/libOxMetalClaw.a)
|
||||
set(OxModel_LIBRARY ${OX_PATH}/lib/ox/libOxModel.a)
|
||||
set(OxOrganicClaw_LIBRARY ${OX_PATH}/lib/ox/libOxOrganicClaw.a)
|
||||
set(OxPreloader_LIBRARY ${OX_PATH}/lib/ox/libOxPreloader.a)
|
||||
set(OxStd_LIBRARY ${OX_PATH}/lib/ox/libOxStd.a)
|
||||
set(Ox_INCLUDE_DIRS ${OX_PATH}/include/)
|
||||
|
4
deps/ox/src/ox/clargs/CMakeLists.txt
vendored
4
deps/ox/src/ox/clargs/CMakeLists.txt
vendored
@ -27,6 +27,6 @@ install(
|
||||
install(
|
||||
TARGETS
|
||||
OxClArgs
|
||||
LIBRARY DESTINATION lib/ox
|
||||
ARCHIVE DESTINATION lib/ox
|
||||
LIBRARY DESTINATION lib
|
||||
ARCHIVE DESTINATION lib
|
||||
)
|
||||
|
7
deps/ox/src/ox/claw/CMakeLists.txt
vendored
7
deps/ox/src/ox/claw/CMakeLists.txt
vendored
@ -12,6 +12,11 @@ target_link_libraries(
|
||||
$<$<BOOL:${OX_USE_STDLIB}>:OxOrganicClaw>
|
||||
)
|
||||
|
||||
install(TARGETS OxClaw
|
||||
LIBRARY DESTINATION lib
|
||||
ARCHIVE DESTINATION lib
|
||||
)
|
||||
|
||||
if(OX_RUN_TESTS)
|
||||
add_subdirectory(test)
|
||||
endif()
|
||||
endif()
|
||||
|
6
deps/ox/src/ox/event/CMakeLists.txt
vendored
6
deps/ox/src/ox/event/CMakeLists.txt
vendored
@ -36,10 +36,10 @@ install(
|
||||
)
|
||||
|
||||
install(TARGETS OxEvent
|
||||
LIBRARY DESTINATION lib/ox
|
||||
ARCHIVE DESTINATION lib/ox
|
||||
LIBRARY DESTINATION lib
|
||||
ARCHIVE DESTINATION lib
|
||||
)
|
||||
|
||||
if(OX_RUN_TESTS)
|
||||
add_subdirectory(test)
|
||||
endif()
|
||||
endif()
|
||||
|
4
deps/ox/src/ox/fs/CMakeLists.txt
vendored
4
deps/ox/src/ox/fs/CMakeLists.txt
vendored
@ -75,8 +75,8 @@ install(
|
||||
install(
|
||||
TARGETS
|
||||
OxFS
|
||||
LIBRARY DESTINATION lib/ox
|
||||
ARCHIVE DESTINATION lib/ox
|
||||
LIBRARY DESTINATION lib
|
||||
ARCHIVE DESTINATION lib
|
||||
)
|
||||
|
||||
if(OX_RUN_TESTS)
|
||||
|
4
deps/ox/src/ox/logconn/CMakeLists.txt
vendored
4
deps/ox/src/ox/logconn/CMakeLists.txt
vendored
@ -29,6 +29,6 @@ install(
|
||||
install(
|
||||
TARGETS
|
||||
OxLogConn
|
||||
LIBRARY DESTINATION lib/ox
|
||||
ARCHIVE DESTINATION lib/ox
|
||||
LIBRARY DESTINATION lib
|
||||
ARCHIVE DESTINATION lib
|
||||
)
|
||||
|
4
deps/ox/src/ox/mc/CMakeLists.txt
vendored
4
deps/ox/src/ox/mc/CMakeLists.txt
vendored
@ -38,8 +38,8 @@ install(
|
||||
)
|
||||
|
||||
install(TARGETS OxMetalClaw
|
||||
LIBRARY DESTINATION lib/ox
|
||||
ARCHIVE DESTINATION lib/ox
|
||||
LIBRARY DESTINATION lib
|
||||
ARCHIVE DESTINATION lib
|
||||
)
|
||||
|
||||
if(OX_RUN_TESTS)
|
||||
|
4
deps/ox/src/ox/model/CMakeLists.txt
vendored
4
deps/ox/src/ox/model/CMakeLists.txt
vendored
@ -40,8 +40,8 @@ install(
|
||||
)
|
||||
|
||||
install(TARGETS OxModel
|
||||
LIBRARY DESTINATION lib/ox
|
||||
ARCHIVE DESTINATION lib/ox
|
||||
LIBRARY DESTINATION lib
|
||||
ARCHIVE DESTINATION lib
|
||||
)
|
||||
|
||||
if(OX_RUN_TESTS)
|
||||
|
4
deps/ox/src/ox/oc/CMakeLists.txt
vendored
4
deps/ox/src/ox/oc/CMakeLists.txt
vendored
@ -36,8 +36,8 @@ install(
|
||||
)
|
||||
|
||||
install(TARGETS OxOrganicClaw
|
||||
LIBRARY DESTINATION lib/ox
|
||||
ARCHIVE DESTINATION lib/ox
|
||||
LIBRARY DESTINATION lib
|
||||
ARCHIVE DESTINATION lib
|
||||
)
|
||||
|
||||
if(OX_RUN_TESTS)
|
||||
|
2
deps/ox/src/ox/oc/write.cpp
vendored
2
deps/ox/src/ox/oc/write.cpp
vendored
@ -14,7 +14,7 @@ OrganicClawWriter::OrganicClawWriter(int unionIdx) noexcept: m_unionIdx(unionIdx
|
||||
}
|
||||
|
||||
OrganicClawWriter::OrganicClawWriter(Json::Value json, int unionIdx) noexcept:
|
||||
m_json(json),
|
||||
m_json(std::move(json)),
|
||||
m_unionIdx(unionIdx) {
|
||||
}
|
||||
|
||||
|
9
deps/ox/src/ox/preloader/CMakeLists.txt
vendored
9
deps/ox/src/ox/preloader/CMakeLists.txt
vendored
@ -1,6 +1,6 @@
|
||||
|
||||
add_library(
|
||||
OxPreloader
|
||||
OxPreloader STATIC
|
||||
preloader.cpp
|
||||
)
|
||||
|
||||
@ -20,3 +20,10 @@ install(
|
||||
DESTINATION
|
||||
include/nostalgia/preloader
|
||||
)
|
||||
|
||||
install(
|
||||
TARGETS
|
||||
OxPreloader
|
||||
LIBRARY DESTINATION lib
|
||||
ARCHIVE DESTINATION lib
|
||||
)
|
||||
|
5
deps/ox/src/ox/preloader/platspecs.hpp
vendored
5
deps/ox/src/ox/preloader/platspecs.hpp
vendored
@ -16,16 +16,13 @@ struct NativePlatSpec {
|
||||
using PtrType = uintptr_t;
|
||||
using size_t = std::size_t;
|
||||
|
||||
static constexpr auto PtrAlign = alignof(void*);
|
||||
static constexpr PtrType RomStart = 0x08000000;
|
||||
|
||||
template<typename T>
|
||||
[[nodiscard]]
|
||||
static constexpr std::size_t alignOf(const T &v) noexcept {
|
||||
if constexpr(ox::is_integral_v<T>) {
|
||||
return alignof(T);
|
||||
} else if constexpr(ox::is_pointer_v<T>) {
|
||||
PtrType p = 0;
|
||||
const PtrType p = 0;
|
||||
return alignOf(p);
|
||||
} else {
|
||||
AlignmentCatcher<NativePlatSpec> c;
|
||||
|
5
deps/ox/src/ox/std/CMakeLists.txt
vendored
5
deps/ox/src/ox/std/CMakeLists.txt
vendored
@ -97,6 +97,7 @@ install(
|
||||
new.hpp
|
||||
optional.hpp
|
||||
random.hpp
|
||||
ranges.hpp
|
||||
serialize.hpp
|
||||
std.hpp
|
||||
stddef.hpp
|
||||
@ -118,8 +119,8 @@ install(
|
||||
)
|
||||
|
||||
install(TARGETS OxStd OxTraceHook
|
||||
LIBRARY DESTINATION lib/ox
|
||||
ARCHIVE DESTINATION lib/ox
|
||||
LIBRARY DESTINATION lib
|
||||
ARCHIVE DESTINATION lib
|
||||
)
|
||||
|
||||
if(OX_RUN_TESTS)
|
||||
|
4
deps/ox/src/ox/std/bit.hpp
vendored
4
deps/ox/src/ox/std/bit.hpp
vendored
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015 - 2022 gary@drinkingtea.net
|
||||
* Copyright 2015 - 2023 gary@drinkingtea.net
|
||||
*
|
||||
* 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
|
||||
@ -17,7 +17,7 @@
|
||||
#include "types.hpp"
|
||||
#include "typetraits.hpp"
|
||||
|
||||
#if defined(OX_OS_Darwin) || !defined(OX_USE_STDLIB)
|
||||
#if !defined(OX_USE_STDLIB)
|
||||
namespace std {
|
||||
|
||||
template<typename To, typename From>
|
||||
|
2
deps/ox/src/ox/std/error.hpp
vendored
2
deps/ox/src/ox/std/error.hpp
vendored
@ -101,7 +101,7 @@ struct Exception: public std::exception {
|
||||
this->errCode = errCode;
|
||||
}
|
||||
|
||||
inline explicit Exception(const Error &err) {
|
||||
explicit inline Exception(const Error &err) {
|
||||
if (err.msg) {
|
||||
this->msg = err.msg;
|
||||
} else {
|
||||
|
17
deps/ox/src/ox/std/memops.cpp
vendored
17
deps/ox/src/ox/std/memops.cpp
vendored
@ -27,13 +27,8 @@ void *ox_inhibit_loop_to_libcall memset(void *ptr, int val, std::size_t size) {
|
||||
return ox_memset(ptr, val, size);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#undef ox_inhibit_loop_to_libcall
|
||||
|
||||
#endif
|
||||
|
||||
int ox_memcmp(const void *ptr1, const void *ptr2, std::size_t size) noexcept {
|
||||
int ox_inhibit_loop_to_libcall memcmp(const void *ptr1, const void *ptr2, std::size_t size) noexcept {
|
||||
int retval = 0;
|
||||
auto block1 = reinterpret_cast<const uint8_t*>(ptr1);
|
||||
auto block2 = reinterpret_cast<const uint8_t*>(ptr2);
|
||||
@ -48,3 +43,13 @@ int ox_memcmp(const void *ptr1, const void *ptr2, std::size_t size) noexcept {
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#undef ox_inhibit_loop_to_libcall
|
||||
|
||||
#endif
|
||||
|
||||
int ox_memcmp(const void *ptr1, const void *ptr2, std::size_t size) noexcept {
|
||||
return memcmp(ptr1, ptr2, size);
|
||||
}
|
||||
|
14
deps/ox/src/ox/std/memops.hpp
vendored
14
deps/ox/src/ox/std/memops.hpp
vendored
@ -23,6 +23,8 @@ void *memmove(void *dest, const void *src, std::size_t size);
|
||||
|
||||
void *memset(void *ptr, int val, std::size_t size);
|
||||
|
||||
int memcmp(const void *ptr1, const void *ptr2, std::size_t size) noexcept;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -68,10 +70,22 @@ constexpr void *ox_memset(void *ptr, int val, std::size_t size) noexcept {
|
||||
|
||||
namespace ox {
|
||||
|
||||
constexpr void *memmove(void *dest, const void *src, std::size_t size) {
|
||||
return ox_memmove(dest, src, size);
|
||||
}
|
||||
|
||||
constexpr void *memset(void *ptr, int val, std::size_t size) noexcept {
|
||||
return ox_memset(ptr, val, size);
|
||||
}
|
||||
|
||||
constexpr void *memcpy(void *dest, const void *src, std::size_t size) noexcept {
|
||||
return ox_memcpy(dest, src, size);
|
||||
}
|
||||
|
||||
inline int memcmp(const void *ptr1, const void *ptr2, std::size_t size) noexcept {
|
||||
return ox_memcmp(ptr1, ptr2, size);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void *memsetElements(T *ptr, T val, std::size_t elements) noexcept {
|
||||
return memset(ptr, val, elements * sizeof(T));
|
||||
|
1
deps/ox/src/ox/std/random.hpp
vendored
1
deps/ox/src/ox/std/random.hpp
vendored
@ -8,6 +8,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "bit.hpp"
|
||||
#include "stddef.hpp"
|
||||
#include "types.hpp"
|
||||
|
||||
|
35
deps/ox/src/ox/std/ranges.hpp
vendored
Normal file
35
deps/ox/src/ox/std/ranges.hpp
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2015 - 2023 gary@drinkingtea.net
|
||||
*
|
||||
* 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 https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ox {
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr bool all_of(auto begin, auto end, auto pred) noexcept {
|
||||
while (begin != end) {
|
||||
if (!pred(*begin)) {
|
||||
return false;
|
||||
}
|
||||
++begin;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr bool any_of(auto begin, auto end, auto pred) noexcept {
|
||||
while (begin != end) {
|
||||
if (pred(*begin)) {
|
||||
return true;
|
||||
}
|
||||
++begin;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
16
deps/ox/src/ox/std/stringview.hpp
vendored
16
deps/ox/src/ox/std/stringview.hpp
vendored
@ -352,3 +352,19 @@ constexpr auto toStdStringView(CRStringView sv) noexcept {
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
constexpr ox::Result<int> ox_atoi(ox::CRStringView str) noexcept {
|
||||
int total = 0;
|
||||
int multiplier = 1;
|
||||
for (auto i = static_cast<int64_t>(str.len()) - 1; i != -1; --i) {
|
||||
auto s = static_cast<uint64_t>(i);
|
||||
if (str[s] >= '0' && str[s] <= '9') {
|
||||
total += (str[s] - '0') * multiplier;
|
||||
multiplier *= 10;
|
||||
} else {
|
||||
return OxError(1);
|
||||
}
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
|
14
deps/ox/src/ox/std/strops.hpp
vendored
14
deps/ox/src/ox/std/strops.hpp
vendored
@ -125,20 +125,6 @@ constexpr int ox_lastIndexOf(const auto &str, int character, std::size_t maxLen
|
||||
return retval;
|
||||
}
|
||||
|
||||
constexpr ox::Result<int> ox_atoi(const char *str) noexcept {
|
||||
int total = 0;
|
||||
int multiplier = 1;
|
||||
for (auto i = static_cast<int64_t>(ox_strlen(str)) - 1; i != -1; i--) {
|
||||
if (str[i] >= '0' && str[i] <= '9') {
|
||||
total += (str[i] - '0') * multiplier;
|
||||
multiplier *= 10;
|
||||
} else {
|
||||
return OxError(1);
|
||||
}
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
template<typename Integer, typename T>
|
||||
constexpr T ox_itoa(Integer v, T str) noexcept {
|
||||
if (v) {
|
||||
|
8
deps/ox/src/ox/std/test/tests.cpp
vendored
8
deps/ox/src/ox/std/test/tests.cpp
vendored
@ -207,6 +207,8 @@ static std::map<ox::String, ox::Error(*)()> tests = {
|
||||
constexpr ox::StringView uuidStr = "8d814442-f46e-4cc3-8edc-ca3c01cc86db";
|
||||
oxRequire(uuid, ox::UUID::fromString(uuidStr));
|
||||
oxExpect(uuid.toString(), uuidStr);
|
||||
oxExpect(ox::UUID{}.isNull(), true);
|
||||
oxExpect(ox::UUID::fromString(uuidStr).value.isNull(), false);
|
||||
return OxError(0);
|
||||
}
|
||||
},
|
||||
@ -214,9 +216,9 @@ static std::map<ox::String, ox::Error(*)()> tests = {
|
||||
"UUID::generate",
|
||||
[] {
|
||||
ox::UUID::seedGenerator({1234, 4321});
|
||||
oxExpect(ox::UUID::generate().unwrap().toString(), "c8f4bff1-d403-4576-fd3b-0c41f1cd8b7d");
|
||||
oxExpect(ox::UUID::generate().unwrap().toString(), "0d1b7dad-7d50-49b6-916d-c3d811b5af0a");
|
||||
oxExpect(ox::UUID::generate().unwrap().toString(), "e3889e0b-4dcd-47b2-b3eb-492ea958d3e4");
|
||||
oxExpect(ox::UUID::generate().unwrap().toString(), "5c3f4b5e-ccbf-4727-7f03-3053dedc8827");
|
||||
oxExpect(ox::UUID::generate().unwrap().toString(), "90d0274a-2774-4afa-88e5-0c1d60ba3abf");
|
||||
oxExpect(ox::UUID::generate().unwrap().toString(), "7df77910-841c-48ba-ea2e-44521ac47c2e");
|
||||
return OxError(0);
|
||||
}
|
||||
},
|
||||
|
7
deps/ox/src/ox/std/uuid.cpp
vendored
7
deps/ox/src/ox/std/uuid.cpp
vendored
@ -25,11 +25,16 @@ Result<UUID> UUID::generate() noexcept {
|
||||
}
|
||||
UUID out;
|
||||
for (auto &v : out.m_value) {
|
||||
v = static_cast<uint8_t>(s_rand.gen() % 255);
|
||||
// shift away 4 lowest bits, as Xoroshiro128+ randomness is weaker there
|
||||
const auto rand = s_rand.gen() >> 4;
|
||||
v = static_cast<uint8_t>(rand % 255);
|
||||
}
|
||||
out.m_value[6] &= 0x0f;
|
||||
out.m_value[6] |= 4 << 4;
|
||||
return out;
|
||||
}
|
||||
|
||||
static_assert(UUID{}.isNull());
|
||||
static_assert(!UUID::fromString("34af4809-043d-4348-b720-2b454e5678c7").value.isNull());
|
||||
|
||||
}
|
||||
|
25
deps/ox/src/ox/std/uuid.hpp
vendored
25
deps/ox/src/ox/std/uuid.hpp
vendored
@ -11,6 +11,7 @@
|
||||
#include "array.hpp"
|
||||
#include "bstring.hpp"
|
||||
#include "random.hpp"
|
||||
#include "ranges.hpp"
|
||||
#include "stringview.hpp"
|
||||
#include "strops.hpp"
|
||||
#include "trace.hpp"
|
||||
@ -56,8 +57,8 @@ constexpr ox::Result<uint8_t> fromHex(ox::CRStringView v) noexcept {
|
||||
return OxError(2);
|
||||
}
|
||||
uint8_t out = 0;
|
||||
out += valMap[static_cast<unsigned>(v[0])] * 16u;
|
||||
out += valMap[static_cast<unsigned>(v[1])];
|
||||
out += valMap[static_cast<unsigned char>(v[0])] * 16u;
|
||||
out += valMap[static_cast<unsigned char>(v[1])];
|
||||
return out;
|
||||
}
|
||||
|
||||
@ -95,7 +96,7 @@ class UUID {
|
||||
protected:
|
||||
static bool s_seeded;
|
||||
static Random s_rand;
|
||||
ox::Array<uint8_t, 16> m_value;
|
||||
ox::Array<uint8_t, 16> m_value{};
|
||||
|
||||
public:
|
||||
static void seedGenerator(const RandomSeed &seed) noexcept;
|
||||
@ -107,9 +108,23 @@ class UUID {
|
||||
return m_value;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto isNull() const noexcept {
|
||||
if (std::is_constant_evaluated()) {
|
||||
if (ox::all_of(m_value.begin(), m_value.end(), [](auto v) { return v == 0; })) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
constexpr uint64_t zero = 0;
|
||||
return ox::memcmp(&zero, m_value.data() + 0, 8) == 0
|
||||
&& ox::memcmp(&zero, m_value.data() + 8, 8) == 0;
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr ox::Result<ox::UUID> fromString(ox::CRStringView s) noexcept {
|
||||
if (s.len() < 36) {
|
||||
return OxError(1, "Insufficient data contain complete UUID");
|
||||
return OxError(1, "Insufficient data to contain a complete UUID");
|
||||
}
|
||||
UUID out;
|
||||
auto valueI = 0u;
|
||||
@ -135,7 +150,7 @@ class UUID {
|
||||
UUIDStr out;
|
||||
auto valueI = 0u;
|
||||
constexpr auto printChars = [](
|
||||
ox::BString<36> *out,
|
||||
UUIDStr *out,
|
||||
const Array<uint8_t, 16> &value,
|
||||
std::size_t cnt,
|
||||
unsigned valueI) {
|
||||
|
Binary file not shown.
@ -1 +1 @@
|
||||
N1;14fc3dd8-42ff-4bf9-81f1-a010cc5ac251;M2;net.drinkingtea.nostalgia.core.Palette;1;ûÿ³Ö
|
||||
K1;14fc3dd8-42ff-4bf9-81f1-a010cc5ac251;M2;net.drinkingtea.nostalgia.core.Palette;1;ûÿ³Ö
|
||||
|
@ -1 +1 @@
|
||||
N1;0f75977f-1c52-45f8-9793-52ea2dc200a0;M2;net.drinkingtea.nostalgia.core.Palette;1;ûÿ³Ö
|
||||
K1;0f75977f-1c52-45f8-9793-52ea2dc200a0;M2;net.drinkingtea.nostalgia.core.Palette;1;ûÿ³Ö
|
||||
|
@ -1 +1 @@
|
||||
N1;c79f21e2-f74f-4ad9-90ed-32b0ef7da6ed;M2;net.drinkingtea.nostalgia.core.Palette;1;PÛ{³ÖCˆ
|
||||
K1;c79f21e2-f74f-4ad9-90ed-32b0ef7da6ed;M2;net.drinkingtea.nostalgia.core.Palette;1;PÛ{³ÖCˆ
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -7,7 +7,7 @@ OS=$(uname | tr [:upper:] [:lower:])
|
||||
HOST_ENV=${OS}-$(uname -m)
|
||||
|
||||
BIN=./dist/${HOST_ENV}-$(cat .current_build)/bin/
|
||||
NOSTALGIA_BIN=build/$(hostname)/gba-*/src/nostalgia/player/nostalgia.bin
|
||||
NOSTALGIA_BIN=build/$(uname -n)/gba-*/src/nostalgia/player/nostalgia.bin
|
||||
NOSTALGIA_PROJECT=$1
|
||||
NOSTALGIA_GBA=nostalgia.gba
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
include_directories(".")
|
||||
|
||||
add_subdirectory(keel)
|
||||
add_subdirectory(nostalgia)
|
||||
|
@ -1,30 +1,41 @@
|
||||
|
||||
add_library(
|
||||
NostalgiaFoundation
|
||||
Keel
|
||||
asset.cpp
|
||||
media.cpp
|
||||
module.cpp
|
||||
pack.cpp
|
||||
typeconv.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
NostalgiaFoundation PUBLIC
|
||||
Keel PUBLIC
|
||||
OxClaw
|
||||
OxEvent
|
||||
OxFS
|
||||
OxModel
|
||||
OxPreloader
|
||||
OxStd
|
||||
)
|
||||
|
||||
install(
|
||||
FILES
|
||||
asset.hpp
|
||||
assetmanager.hpp
|
||||
context.hpp
|
||||
foundation.hpp
|
||||
asset.hpp
|
||||
keel.hpp
|
||||
media.hpp
|
||||
module.hpp
|
||||
pack.hpp
|
||||
typeconv.hpp
|
||||
DESTINATION
|
||||
include/nostalgia/foundation
|
||||
include/keel
|
||||
)
|
||||
|
||||
install(
|
||||
TARGETS
|
||||
Keel
|
||||
DESTINATION
|
||||
LIBRARY DESTINATION lib
|
||||
ARCHIVE DESTINATION lib
|
||||
)
|
@ -4,26 +4,27 @@
|
||||
|
||||
#include "asset.hpp"
|
||||
|
||||
namespace nostalgia::foundation {
|
||||
namespace keel {
|
||||
|
||||
ox::Result<ox::UUID> readUuidHeader(const ox::Buffer &buff) noexcept {
|
||||
return readUuidHeader(buff.data(), buff.size());
|
||||
}
|
||||
|
||||
ox::Result<ox::UUID> readUuidHeader(const char *buff, std::size_t buffLen) noexcept {
|
||||
if (buffLen < 40) {
|
||||
return OxError(1, "Insufficient data contain complete Nostalgia header");
|
||||
if (buffLen < K1HdrSz) {
|
||||
return OxError(1, "Insufficient data to contain complete Nostalgia header");
|
||||
}
|
||||
if (ox_memcmp(buff, "N1;", 3) != 0) {
|
||||
return OxError(2, "No Nostalgia header data");
|
||||
constexpr ox::StringView k1Hdr = "K1;";
|
||||
if (k1Hdr == buff) {
|
||||
return OxError(2, "No Nostalgia asset header data");
|
||||
}
|
||||
return ox::UUID::fromString(ox::StringView(buff + 3, 36));
|
||||
return ox::UUID::fromString(ox::StringView(buff + k1Hdr.bytes(), 36));
|
||||
}
|
||||
|
||||
ox::Result<ox::ModelObject> readAsset(ox::TypeStore *ts, const ox::Buffer &buff) noexcept {
|
||||
std::size_t offset = 0;
|
||||
if (!readUuidHeader(buff).error) {
|
||||
offset = 40; // the size of N1 headers
|
||||
offset = K1HdrSz;
|
||||
}
|
||||
return ox::readClaw(ts, buff.data() + offset, buff.size() - offset);
|
||||
}
|
||||
@ -31,7 +32,7 @@ ox::Result<ox::ModelObject> readAsset(ox::TypeStore *ts, const ox::Buffer &buff)
|
||||
ox::Result<AssetHdr> readAssetHeader(const char *buff, std::size_t buffLen) noexcept {
|
||||
AssetHdr out;
|
||||
const auto err = readUuidHeader(buff, buffLen).moveTo(&out.uuid);
|
||||
const auto offset = err ? 0 : 40;
|
||||
const auto offset = err ? 0 : K1HdrSz;
|
||||
buff = buff + offset;
|
||||
buffLen = buffLen - offset;
|
||||
oxReturnError(ox::readClawHeader(buff, buffLen).moveTo(&out.clawHdr));
|
@ -9,17 +9,16 @@
|
||||
#include <ox/claw/claw.hpp>
|
||||
#include <ox/fs/fs.hpp>
|
||||
|
||||
#include <nostalgia/foundation/context.hpp>
|
||||
namespace keel {
|
||||
|
||||
namespace nostalgia::foundation {
|
||||
constexpr auto K1HdrSz = 40;
|
||||
|
||||
[[nodiscard]]
|
||||
ox::Result<ox::UUID> readUuidHeader(const ox::Buffer &buff) noexcept;
|
||||
|
||||
ox::Result<ox::UUID> readUuidHeader(const char *buff, std::size_t buffLen) noexcept;
|
||||
|
||||
ox::Error writeUuidHeader(ox::Writer_c auto *writer, const ox::UUID &uuid) noexcept {
|
||||
const auto hdr = ox::sfmt<ox::BString<40>>("N1;{};", uuid.toString());
|
||||
const auto hdr = ox::sfmt<ox::BString<K1HdrSz>>("K1;{};", uuid.toString());
|
||||
return write(writer, hdr);
|
||||
}
|
||||
|
||||
@ -28,7 +27,7 @@ ox::Result<T> readAsset(const ox::Buffer &buff) noexcept {
|
||||
std::size_t offset = 0;
|
||||
const auto err = readUuidHeader(buff).error;
|
||||
if (!err) {
|
||||
offset = 40; // the size of N1 headers
|
||||
offset = K1HdrSz; // the size of K1 headers
|
||||
}
|
||||
return ox::readClaw<T>(buff.data() + offset, buff.size() - offset);
|
||||
}
|
@ -10,7 +10,7 @@
|
||||
#include <ox/std/hashmap.hpp>
|
||||
#include <ox/std/utility.hpp>
|
||||
|
||||
namespace nostalgia::foundation {
|
||||
namespace keel {
|
||||
|
||||
class AssetManager;
|
||||
|
||||
@ -28,7 +28,6 @@ class AssetContainer {
|
||||
ox::Signal<ox::Error()> updated;
|
||||
|
||||
private:
|
||||
ox::UUID uuid;
|
||||
T m_obj;
|
||||
mutable int m_references = 0;
|
||||
|
||||
@ -42,10 +41,12 @@ class AssetContainer {
|
||||
AssetContainer& operator=(AssetContainer&) = delete;
|
||||
AssetContainer& operator=(AssetContainer&&) = delete;
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr T *get() noexcept {
|
||||
return &m_obj;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr const T *get() const noexcept {
|
||||
return &m_obj;
|
||||
}
|
||||
@ -67,6 +68,7 @@ class AssetContainer {
|
||||
--m_references;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr int references() const noexcept {
|
||||
return m_references;
|
||||
}
|
||||
@ -93,6 +95,7 @@ class AssetRef: public ox::SignalHandler {
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr const T *get() const noexcept {
|
||||
if (m_ctr) {
|
||||
return m_ctr->get();
|
@ -10,7 +10,7 @@
|
||||
|
||||
#include "assetmanager.hpp"
|
||||
|
||||
namespace nostalgia::foundation {
|
||||
namespace keel {
|
||||
|
||||
class Context;
|
||||
using PackTransform = ox::Error(*)(Context*, ox::Buffer *clawData);
|
@ -9,25 +9,24 @@
|
||||
#include "context.hpp"
|
||||
#include "media.hpp"
|
||||
#include "module.hpp"
|
||||
#include "pack.hpp"
|
||||
|
||||
namespace nostalgia::foundation {
|
||||
namespace keel {
|
||||
|
||||
template<typename Ctx = foundation::Context>
|
||||
template<typename Ctx = keel::Context>
|
||||
ox::Result<ox::UPtr<Ctx>> init(ox::UPtr<ox::FileSystem> &&fs, ox::CRStringView appName) noexcept {
|
||||
auto ctx = ox::make_unique<Ctx>();
|
||||
ctx->appName = appName;
|
||||
oxIgnoreError(setRomFs(ctx.get(), std::move(fs)));
|
||||
auto mods = modules();
|
||||
if (mods) {
|
||||
for (auto &mod : *mods) {
|
||||
// register type converters
|
||||
for (auto c : mod->converters()) {
|
||||
ctx->converters.emplace_back(c);
|
||||
}
|
||||
// register pack transforms
|
||||
for (auto c : mod->packTransforms()) {
|
||||
ctx->packTransforms.emplace_back(c);
|
||||
}
|
||||
const auto &mods = modules();
|
||||
for (auto &mod : mods) {
|
||||
// register type converters
|
||||
for (auto c : mod->converters()) {
|
||||
ctx->converters.emplace_back(c);
|
||||
}
|
||||
// register pack transforms
|
||||
for (auto c : mod->packTransforms()) {
|
||||
ctx->packTransforms.emplace_back(c);
|
||||
}
|
||||
}
|
||||
return ctx;
|
@ -10,9 +10,7 @@
|
||||
|
||||
#include <ox/std/trace.hpp>
|
||||
|
||||
#include <nostalgia/foundation/media.hpp>
|
||||
|
||||
namespace nostalgia::foundation {
|
||||
namespace keel {
|
||||
|
||||
ox::Result<char*> loadRom(ox::CRStringView path) noexcept {
|
||||
std::ifstream file(std::string(toStdStringView(path)), std::ios::binary | std::ios::ate);
|
||||
@ -85,7 +83,7 @@ ox::Error buildUuidMap(Context *ctx) noexcept {
|
||||
|
||||
#define MEM_ROM reinterpret_cast<char*>(0x0800'0000)
|
||||
|
||||
namespace nostalgia::foundation {
|
||||
namespace keel {
|
||||
|
||||
static void clearUuidMap(Context*) noexcept {
|
||||
}
|
||||
@ -97,8 +95,8 @@ ox::Error buildUuidMap(Context*) noexcept {
|
||||
ox::Result<char*> loadRom(ox::CRStringView) noexcept {
|
||||
// put the header in the wrong order to prevent mistaking this code for the
|
||||
// media section
|
||||
constexpr auto headerP2 = "HEADER__________";
|
||||
constexpr auto headerP1 = "NOSTALGIA_MEDIA_";
|
||||
constexpr auto headerP2 = "R_______________";
|
||||
constexpr auto headerP1 = "KEEL_MEDIA_HEADE";
|
||||
constexpr auto headerP1Len = ox_strlen(headerP2);
|
||||
constexpr auto headerP2Len = ox_strlen(headerP1);
|
||||
constexpr auto headerLen = headerP1Len + headerP2Len;
|
||||
@ -114,27 +112,27 @@ ox::Result<char*> loadRom(ox::CRStringView) noexcept {
|
||||
void unloadRom(char*) noexcept {
|
||||
}
|
||||
|
||||
ox::Result<std::size_t> getPreloadAddr(foundation::Context *ctx, ox::CRStringView path) noexcept {
|
||||
ox::Result<std::size_t> getPreloadAddr(keel::Context *ctx, ox::CRStringView path) noexcept {
|
||||
oxRequire(stat, ctx->rom->stat(path));
|
||||
oxRequire(buff, static_cast<ox::MemFS*>(ctx->rom.get())->directAccess(path));
|
||||
PreloadPtr p;
|
||||
oxReturnError(ox::readMC(buff, stat.size, &p));
|
||||
return p.preloadAddr + ctx->preloadSectionOffset;
|
||||
return static_cast<std::size_t>(p.preloadAddr) + ctx->preloadSectionOffset;
|
||||
}
|
||||
|
||||
ox::Result<std::size_t> getPreloadAddr(foundation::Context *ctx, const ox::FileAddress &file) noexcept {
|
||||
ox::Result<std::size_t> getPreloadAddr(keel::Context *ctx, const ox::FileAddress &file) noexcept {
|
||||
oxRequire(stat, ctx->rom->stat(file));
|
||||
oxRequire(buff, static_cast<ox::MemFS*>(ctx->rom.get())->directAccess(file));
|
||||
PreloadPtr p;
|
||||
oxReturnError(ox::readMC(buff, stat.size, &p));
|
||||
return p.preloadAddr + ctx->preloadSectionOffset;
|
||||
return static_cast<std::size_t>(p.preloadAddr) + ctx->preloadSectionOffset;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
namespace nostalgia::foundation {
|
||||
namespace keel {
|
||||
|
||||
ox::Error setRomFs(Context *ctx, ox::UPtr<ox::FileSystem> fs) noexcept {
|
||||
ctx->rom = std::move(fs);
|
@ -15,28 +15,28 @@
|
||||
#include "context.hpp"
|
||||
#include "typeconv.hpp"
|
||||
|
||||
namespace nostalgia::foundation {
|
||||
namespace keel {
|
||||
|
||||
// Pointer to preloaded data that can be stored in FS in place of the actual
|
||||
// data.
|
||||
struct PreloadPtr {
|
||||
static constexpr auto TypeName = "net.drinkingtea.ox.PreloadPtr";
|
||||
static constexpr auto TypeVersion = 1;
|
||||
uint32_t preloadAddr = 0;
|
||||
static constexpr auto TypeName = "net.drinkingtea.keel.PreloadPtr";
|
||||
static constexpr auto TypeVersion = 2;
|
||||
uint64_t preloadAddr = 0;
|
||||
};
|
||||
|
||||
oxModelBegin(PreloadPtr)
|
||||
oxModelField(preloadAddr)
|
||||
oxModelEnd()
|
||||
|
||||
ox::Result<std::size_t> getPreloadAddr(foundation::Context *ctx, const ox::FileAddress &file) noexcept;
|
||||
ox::Result<std::size_t> getPreloadAddr(foundation::Context *ctx, ox::CRStringView file) noexcept;
|
||||
ox::Result<std::size_t> getPreloadAddr(keel::Context *ctx, const ox::FileAddress &file) noexcept;
|
||||
ox::Result<std::size_t> getPreloadAddr(keel::Context *ctx, ox::CRStringView file) noexcept;
|
||||
|
||||
#ifndef OX_BARE_METAL
|
||||
|
||||
template<typename T>
|
||||
ox::Result<foundation::AssetRef<T>> readObjFile(
|
||||
foundation::Context *ctx,
|
||||
ox::Result<keel::AssetRef<T>> readObjFile(
|
||||
keel::Context *ctx,
|
||||
ox::StringView assetId,
|
||||
bool forceLoad) noexcept {
|
||||
constexpr auto readConvert = [](Context *ctx, const ox::Buffer &buff) -> ox::Result<T> {
|
||||
@ -78,12 +78,12 @@ ox::Result<foundation::AssetRef<T>> readObjFile(
|
||||
#else
|
||||
|
||||
template<typename T>
|
||||
ox::Result<foundation::AssetRef<T>> readObjNoCache(
|
||||
foundation::Context *ctx,
|
||||
ox::Result<keel::AssetRef<T>> readObjNoCache(
|
||||
keel::Context *ctx,
|
||||
ox::CRStringView assetId) noexcept {
|
||||
if constexpr(ox::preloadable<T>::value) {
|
||||
oxRequire(addr, getPreloadAddr(ctx, assetId));
|
||||
return foundation::AssetRef<T>(reinterpret_cast<const T*>(addr));
|
||||
return keel::AssetRef<T>(reinterpret_cast<const T*>(addr));
|
||||
} else {
|
||||
return OxError(1);
|
||||
}
|
||||
@ -96,9 +96,9 @@ void createUuidMapping(Context *ctx, const ox::String &filePath, const ox::UUID
|
||||
ox::Error buildUuidMap(Context *ctx) noexcept;
|
||||
|
||||
template<typename T>
|
||||
ox::Result<foundation::AssetRef<T>> readObj(
|
||||
[[maybe_unused]] foundation::Context *ctx,
|
||||
[[maybe_unused]] ox::CRStringView assetId,
|
||||
ox::Result<keel::AssetRef<T>> readObj(
|
||||
keel::Context *ctx,
|
||||
ox::CRStringView assetId,
|
||||
[[maybe_unused]] bool forceLoad = false) noexcept {
|
||||
#ifndef OX_BARE_METAL
|
||||
return readObjFile<T>(ctx, assetId, forceLoad);
|
||||
@ -108,8 +108,8 @@ ox::Result<foundation::AssetRef<T>> readObj(
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ox::Result<foundation::AssetRef<T>> readObj(
|
||||
foundation::Context *ctx,
|
||||
ox::Result<keel::AssetRef<T>> readObj(
|
||||
keel::Context *ctx,
|
||||
const ox::FileAddress &file,
|
||||
[[maybe_unused]] bool forceLoad = false) noexcept {
|
||||
#ifndef OX_BARE_METAL
|
||||
@ -118,7 +118,7 @@ ox::Result<foundation::AssetRef<T>> readObj(
|
||||
#else
|
||||
if constexpr(ox::preloadable<T>::value) {
|
||||
oxRequire(addr, getPreloadAddr(ctx, file));
|
||||
return foundation::AssetRef<T>(reinterpret_cast<const T*>(addr));
|
||||
return keel::AssetRef<T>(reinterpret_cast<const T*>(addr));
|
||||
} else {
|
||||
return OxError(1);
|
||||
}
|
||||
@ -127,7 +127,7 @@ ox::Result<foundation::AssetRef<T>> readObj(
|
||||
|
||||
template<typename T>
|
||||
ox::Error writeObj(
|
||||
foundation::Context *ctx,
|
||||
keel::Context *ctx,
|
||||
const ox::FileAddress &file,
|
||||
const T &obj,
|
||||
ox::ClawFormat fmt = ox::ClawFormat::Metal) noexcept {
|
||||
@ -139,7 +139,7 @@ ox::Error setRomFs(Context *ctx, ox::UPtr<ox::FileSystem> fs) noexcept;
|
||||
|
||||
ox::Result<ox::UniquePtr<ox::FileSystem>> loadRomFs(ox::CRStringView path) noexcept;
|
||||
|
||||
ox::Result<char*> loadRom(ox::CRStringView assetId = "") noexcept;
|
||||
ox::Result<char*> loadRom(ox::CRStringView path = "") noexcept;
|
||||
|
||||
void unloadRom(char*) noexcept;
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
#include "module.hpp"
|
||||
|
||||
namespace nostalgia::foundation {
|
||||
namespace keel {
|
||||
|
||||
static ox::Vector<const Module*> mods;
|
||||
|
||||
@ -13,8 +13,8 @@ void registerModule(const Module *mod) noexcept {
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
const ox::Vector<const Module*> *modules() noexcept {
|
||||
return &mods;
|
||||
const ox::Vector<const Module*> &modules() noexcept {
|
||||
return mods;
|
||||
}
|
||||
|
||||
|
||||
@ -22,7 +22,7 @@ ox::Vector<TypeDescGenerator> Module::types() const noexcept {
|
||||
return {};
|
||||
}
|
||||
|
||||
ox::Vector<const foundation::BaseConverter*> Module::converters() const noexcept {
|
||||
ox::Vector<const keel::BaseConverter*> Module::converters() const noexcept {
|
||||
return {};
|
||||
}
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
#include "typeconv.hpp"
|
||||
|
||||
namespace nostalgia::foundation {
|
||||
namespace keel {
|
||||
|
||||
using TypeDescGenerator = ox::Error(*)(ox::TypeStore*);
|
||||
|
||||
@ -30,7 +30,7 @@ class Module {
|
||||
[[nodiscard]]
|
||||
virtual ox::Vector<TypeDescGenerator> types() const noexcept;
|
||||
[[nodiscard]]
|
||||
virtual ox::Vector<const foundation::BaseConverter*> converters() const noexcept;
|
||||
virtual ox::Vector<const keel::BaseConverter*> converters() const noexcept;
|
||||
[[nodiscard]]
|
||||
virtual ox::Vector<PackTransform> packTransforms() const noexcept;
|
||||
};
|
||||
@ -38,6 +38,6 @@ class Module {
|
||||
void registerModule(const Module *mod) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
const ox::Vector<const foundation::Module*> *modules() noexcept;
|
||||
const ox::Vector<const keel::Module*> &modules() noexcept;
|
||||
|
||||
}
|
@ -2,18 +2,20 @@
|
||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef OX_BARE_METAL
|
||||
|
||||
#include <ox/claw/read.hpp>
|
||||
#include <ox/fs/fs.hpp>
|
||||
#include <ox/model/descwrite.hpp>
|
||||
#include <ox/model/modelvalue.hpp>
|
||||
|
||||
#include <nostalgia/foundation/media.hpp>
|
||||
#include <keel/media.hpp>
|
||||
|
||||
#include "pack.hpp"
|
||||
|
||||
namespace nostalgia {
|
||||
namespace keel {
|
||||
|
||||
static ox::Error pathToInode(foundation::Context *ctx, ox::FileSystem *dest, ox::ModelObject *obj) noexcept {
|
||||
static ox::Error pathToInode(keel::Context *ctx, ox::FileSystem *dest, ox::ModelObject *obj) noexcept {
|
||||
auto &o = *obj;
|
||||
auto type = static_cast<ox::FileAddressType>(o["type"].get<int8_t>());
|
||||
auto &data = o["data"].get<ox::ModelUnion>();
|
||||
@ -38,10 +40,10 @@ static ox::Error pathToInode(foundation::Context *ctx, ox::FileSystem *dest, ox:
|
||||
return data.set(2, s.inode);
|
||||
}
|
||||
|
||||
static ox::Error transformFileAddressesObj(foundation::Context *ctx, ox::FileSystem *dest, ox::ModelObject *obj) noexcept;
|
||||
static ox::Error transformFileAddressesVec(foundation::Context *ctx, ox::FileSystem *dest, ox::ModelValueVector *v) noexcept;
|
||||
static ox::Error transformFileAddressesObj(keel::Context *ctx, ox::FileSystem *dest, ox::ModelObject *obj) noexcept;
|
||||
static ox::Error transformFileAddressesVec(keel::Context *ctx, ox::FileSystem *dest, ox::ModelValueVector *v) noexcept;
|
||||
|
||||
static ox::Error transformFileAddresses(foundation::Context *ctx, ox::FileSystem *dest, ox::ModelValue *v) noexcept {
|
||||
static ox::Error transformFileAddresses(keel::Context *ctx, ox::FileSystem *dest, ox::ModelValue *v) noexcept {
|
||||
if (v->type() == ox::ModelValue::Type::Object) {
|
||||
auto &obj = v->get<ox::ModelObject>();
|
||||
return transformFileAddressesObj(ctx, dest, &obj);
|
||||
@ -52,7 +54,7 @@ static ox::Error transformFileAddresses(foundation::Context *ctx, ox::FileSystem
|
||||
return {};
|
||||
}
|
||||
|
||||
static ox::Error transformFileAddressesVec(foundation::Context *ctx, ox::FileSystem *dest, ox::ModelValueVector *v) noexcept {
|
||||
static ox::Error transformFileAddressesVec(keel::Context *ctx, ox::FileSystem *dest, ox::ModelValueVector *v) noexcept {
|
||||
for (auto &f : *v) {
|
||||
oxReturnError(transformFileAddresses(ctx, dest, &f));
|
||||
}
|
||||
@ -63,7 +65,7 @@ static ox::Error transformFileAddressesVec(foundation::Context *ctx, ox::FileSys
|
||||
* Convert path references in Claw data to inodes to save space
|
||||
* @return error
|
||||
*/
|
||||
static ox::Error transformFileAddressesObj(foundation::Context *ctx, ox::FileSystem *dest, ox::ModelObject *obj) noexcept {
|
||||
static ox::Error transformFileAddressesObj(keel::Context *ctx, ox::FileSystem *dest, ox::ModelObject *obj) noexcept {
|
||||
if (obj->typeName() == "net.drinkingtea.ox.FileAddress" && obj->typeVersion() == 1) {
|
||||
return pathToInode(ctx, dest, obj);
|
||||
}
|
||||
@ -74,7 +76,7 @@ static ox::Error transformFileAddressesObj(foundation::Context *ctx, ox::FileSys
|
||||
return {};
|
||||
}
|
||||
|
||||
static ox::Error doTransformations(foundation::Context *ctx, ox::TypeStore *ts, ox::FileSystem *dest, ox::CRStringView filePath) noexcept {
|
||||
static ox::Error doTransformations(keel::Context *ctx, ox::TypeStore *ts, ox::FileSystem *dest, ox::CRStringView filePath) noexcept {
|
||||
// load file
|
||||
oxRequire(s, dest->stat(filePath));
|
||||
// do transformations
|
||||
@ -83,7 +85,7 @@ static ox::Error doTransformations(foundation::Context *ctx, ox::TypeStore *ts,
|
||||
oxReturnError(tr(ctx, &buff));
|
||||
}
|
||||
// transform FileAddresses
|
||||
oxRequireM(obj, foundation::readAsset(ts, buff));
|
||||
oxRequireM(obj, keel::readAsset(ts, buff));
|
||||
oxReturnError(transformFileAddressesObj(ctx, dest, &obj));
|
||||
oxReturnError(ox::writeClaw(&obj).moveTo(&buff));
|
||||
// write file to dest
|
||||
@ -93,7 +95,7 @@ static ox::Error doTransformations(foundation::Context *ctx, ox::TypeStore *ts,
|
||||
|
||||
// claw file transformations are broken out from copy because path to inode
|
||||
// transformations need to be done after the copy to the new FS is complete
|
||||
static ox::Error transformClaw(foundation::Context *ctx, ox::TypeStore *ts, ox::FileSystem *dest, ox::CRStringView path) noexcept {
|
||||
static ox::Error transformClaw(keel::Context *ctx, ox::TypeStore *ts, ox::FileSystem *dest, ox::CRStringView path) noexcept {
|
||||
// copy
|
||||
oxTracef("pack::transformClaw", "path: {}", path);
|
||||
oxRequire(fileList, dest->ls(path));
|
||||
@ -131,7 +133,7 @@ static ox::Error copy(ox::FileSystem *src, ox::FileSystem *dest, ox::CRStringVie
|
||||
oxRequire(fileList, src->ls(path));
|
||||
for (const auto &name : fileList) {
|
||||
auto currentFile = ox::sfmt("{}{}", path, name);
|
||||
if (currentFile == "/.nostalgia") {
|
||||
if (beginsWith(name, ".")) {
|
||||
continue;
|
||||
}
|
||||
oxOutf("reading {}\n", currentFile);
|
||||
@ -163,81 +165,13 @@ static ox::Error copyFS(ox::FileSystem *src, ox::FileSystem *dest) noexcept {
|
||||
return {};
|
||||
}
|
||||
|
||||
// transformations need to be done after the copy to the new FS is complete
|
||||
static ox::Error preloadObj(
|
||||
ox::TypeStore *ts, ox::FileSystem *romFs,
|
||||
GbaPreloader *pl, ox::CRStringView path) noexcept {
|
||||
// load file
|
||||
oxRequireM(buff, romFs->read(path));
|
||||
oxRequireM(obj, foundation::readAsset(ts, buff));
|
||||
if (obj.type()->preloadable) {
|
||||
oxOutf("preloading {}\n", path);
|
||||
// preload
|
||||
oxRequire(a, pl->startAlloc(ox::sizeOf<GbaPlatSpec>(&obj)));
|
||||
const auto err = ox::preload<GbaPlatSpec, decltype(obj)>(pl, &obj);
|
||||
oxReturnError(pl->endAlloc());
|
||||
oxReturnError(err);
|
||||
const foundation::PreloadPtr p{.preloadAddr = static_cast<uint32_t>(a)};
|
||||
oxReturnError(ox::writeMC(&p).moveTo(&buff));
|
||||
} else {
|
||||
// strip the Claw header (it is not needed after preloading) and write back out to dest fs
|
||||
oxReturnError(ox::writeMC(&obj).moveTo(&buff));
|
||||
}
|
||||
oxReturnError(romFs->write(path, buff.data(), buff.size()));
|
||||
return {};
|
||||
}
|
||||
|
||||
// claw file transformations are broken out because path to inode
|
||||
// transformations need to be done after the copy to the new FS is complete
|
||||
static ox::Error preloadDir(ox::TypeStore *ts, ox::FileSystem *romFs, GbaPreloader *pl, ox::CRStringView path) noexcept {
|
||||
// copy
|
||||
oxTracef("pack::preload", "path: {}", path);
|
||||
oxRequire(fileList, romFs->ls(path));
|
||||
for (const auto &name : fileList) {
|
||||
const auto filePath = ox::sfmt("{}{}", path, name);
|
||||
oxRequire(stat, romFs->stat(filePath));
|
||||
if (stat.fileType == ox::FileType::Directory) {
|
||||
const auto dir = ox::sfmt("{}{}/", path, name);
|
||||
oxReturnError(preloadDir(ts, romFs, pl, dir));
|
||||
} else {
|
||||
oxReturnError(preloadObj(ts, romFs, pl, filePath));
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
static ox::Error padbin(ox::BufferWriter *w, unsigned factor) noexcept {
|
||||
return w->write(nullptr, factor - w->buff().size() % factor);
|
||||
}
|
||||
|
||||
ox::Error appendBinary(ox::Buffer *binBuff, ox::Buffer *fsBuff, GbaPreloader *pl) noexcept {
|
||||
constexpr ox::StringView mediaHdr = "NOSTALGIA_MEDIA_HEADER__________";
|
||||
constexpr ox::StringView preloadHdr = "NOSTALGIA_PRELOAD_HEADER________";
|
||||
constexpr auto hdrSize = 32u;
|
||||
static_assert(mediaHdr.bytes() == hdrSize);
|
||||
static_assert(preloadHdr.bytes() == hdrSize);
|
||||
ox::BufferWriter w(binBuff);
|
||||
oxReturnError(padbin(&w, hdrSize));
|
||||
oxReturnError(w.write(mediaHdr.data(), mediaHdr.bytes()));
|
||||
oxReturnError(w.write(fsBuff->data(), fsBuff->size()));
|
||||
oxReturnError(padbin(&w, hdrSize));
|
||||
oxReturnError(w.write(preloadHdr.data(), preloadHdr.bytes()));
|
||||
const auto &plBuff = pl->buff();
|
||||
oxReturnError(pl->offsetPtrs(binBuff->size()));
|
||||
oxReturnError(w.write(plBuff.data(), plBuff.size()));
|
||||
return {};
|
||||
}
|
||||
|
||||
ox::Error pack(foundation::Context *ctx, ox::TypeStore *ts, ox::FileSystem *dest) noexcept {
|
||||
ox::Error pack(keel::Context *ctx, ox::TypeStore *ts, ox::FileSystem *dest) noexcept {
|
||||
oxReturnError(copyFS(ctx->rom.get(), dest));
|
||||
oxOut("Doing transforms\n");
|
||||
oxReturnError(transformClaw(ctx, ts, dest, "/"));
|
||||
return {};
|
||||
}
|
||||
|
||||
ox::Error preload(ox::TypeStore *ts, ox::FileSystem *src, GbaPreloader *pl) noexcept {
|
||||
oxOut("Preloading\n");
|
||||
return preloadDir(ts, src, pl, "/");
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
166
src/keel/pack.hpp
Normal file
166
src/keel/pack.hpp
Normal file
@ -0,0 +1,166 @@
|
||||
/*
|
||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ox/fs/fs.hpp>
|
||||
#include <ox/preloader/preloader.hpp>
|
||||
|
||||
#include "asset.hpp"
|
||||
#include "media.hpp"
|
||||
|
||||
namespace keel {
|
||||
|
||||
class Context;
|
||||
|
||||
struct GbaPlatSpec {
|
||||
using PtrType = uint32_t;
|
||||
using size_t = uint32_t;
|
||||
|
||||
static constexpr PtrType RomStart = 0x08000000;
|
||||
|
||||
[[nodiscard]]
|
||||
static constexpr std::size_t alignOf(const bool) noexcept {
|
||||
return 1;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
static constexpr std::size_t alignOf(const uint8_t) noexcept {
|
||||
return 1;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
static constexpr std::size_t alignOf(const uint16_t) noexcept {
|
||||
return 2;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
static constexpr std::size_t alignOf(const uint32_t) noexcept {
|
||||
return 4;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
static constexpr std::size_t alignOf(const uint64_t) noexcept {
|
||||
return 8;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
static constexpr std::size_t alignOf(const int8_t) noexcept {
|
||||
return 1;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
static constexpr std::size_t alignOf(const int16_t) noexcept {
|
||||
return 2;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
static constexpr std::size_t alignOf(const int32_t) noexcept {
|
||||
return 4;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
static constexpr std::size_t alignOf(const int64_t) noexcept {
|
||||
return 8;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
static constexpr std::size_t alignOf(const auto*) noexcept {
|
||||
return 4;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
static constexpr auto correctEndianness(auto v) noexcept {
|
||||
return ox::toLittleEndian(v);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
using GbaPreloader = ox::Preloader<GbaPlatSpec>;
|
||||
|
||||
namespace detail {
|
||||
// transformations need to be done after the copy to the new FS is complete
|
||||
template<typename PlatSpec>
|
||||
ox::Error preloadObj(
|
||||
ox::TypeStore *ts,
|
||||
ox::FileSystem *romFs,
|
||||
ox::Preloader<PlatSpec> *pl,
|
||||
ox::CRStringView path) noexcept {
|
||||
// load file
|
||||
oxRequireM(buff, romFs->read(path));
|
||||
oxRequireM(obj, keel::readAsset(ts, buff));
|
||||
if (obj.type()->preloadable) {
|
||||
oxOutf("preloading {}\n", path);
|
||||
// preload
|
||||
oxRequire(a, pl->startAlloc(ox::sizeOf<GbaPlatSpec>(&obj)));
|
||||
const auto err = ox::preload<GbaPlatSpec, decltype(obj)>(pl, &obj);
|
||||
oxReturnError(pl->endAlloc());
|
||||
oxReturnError(err);
|
||||
const keel::PreloadPtr p{.preloadAddr = static_cast<uint32_t>(a)};
|
||||
oxReturnError(ox::writeMC(&p).moveTo(&buff));
|
||||
} else {
|
||||
// strip the Claw header (it is not needed after preloading) and write back out to dest fs
|
||||
oxReturnError(ox::writeMC(&obj).moveTo(&buff));
|
||||
}
|
||||
oxReturnError(romFs->write(path, buff.data(), buff.size()));
|
||||
return {};
|
||||
}
|
||||
|
||||
// claw file transformations are broken out because path to inode
|
||||
// transformations need to be done after the copy to the new FS is complete
|
||||
template<typename PlatSpec>
|
||||
ox::Error preloadDir(
|
||||
ox::TypeStore *ts,
|
||||
ox::FileSystem *romFs,
|
||||
ox::Preloader<PlatSpec> *pl,
|
||||
ox::CRStringView path) noexcept {
|
||||
// copy
|
||||
oxTracef("pack::preload", "path: {}", path);
|
||||
oxRequire(fileList, romFs->ls(path));
|
||||
for (const auto &name : fileList) {
|
||||
const auto filePath = ox::sfmt("{}{}", path, name);
|
||||
oxRequire(stat, romFs->stat(filePath));
|
||||
if (stat.fileType == ox::FileType::Directory) {
|
||||
const auto dir = ox::sfmt("{}{}/", path, name);
|
||||
oxReturnError(preloadDir(ts, romFs, pl, dir));
|
||||
} else {
|
||||
oxReturnError(preloadObj(ts, romFs, pl, filePath));
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<typename PlatSpec>
|
||||
ox::Error appendBinary(ox::Buffer *binBuff, ox::Buffer *fsBuff, ox::Preloader<PlatSpec> *pl) noexcept {
|
||||
constexpr auto padbin = [](ox::BufferWriter *w, unsigned factor) noexcept -> ox::Error {
|
||||
return w->write(nullptr, factor - w->buff().size() % factor);
|
||||
};
|
||||
constexpr ox::StringView mediaHdr = "KEEL_MEDIA_HEADER_______________";
|
||||
constexpr ox::StringView preloadHdr = "KEEL_PRELOAD_HEADER_____________";
|
||||
constexpr auto hdrSize = 32u;
|
||||
static_assert(mediaHdr.bytes() == hdrSize);
|
||||
static_assert(preloadHdr.bytes() == hdrSize);
|
||||
ox::BufferWriter w(binBuff);
|
||||
oxReturnError(padbin(&w, hdrSize));
|
||||
oxReturnError(w.write(mediaHdr.data(), mediaHdr.bytes()));
|
||||
oxReturnError(w.write(fsBuff->data(), fsBuff->size()));
|
||||
oxReturnError(padbin(&w, hdrSize));
|
||||
oxReturnError(w.write(preloadHdr.data(), preloadHdr.bytes()));
|
||||
oxReturnError(pl->offsetPtrs(binBuff->size()));
|
||||
const auto &plBuff = pl->buff();
|
||||
oxReturnError(w.write(plBuff.data(), plBuff.size()));
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename PlatSpec>
|
||||
ox::Error preload(ox::TypeStore *ts, ox::FileSystem *src, ox::Preloader<PlatSpec> *pl) noexcept {
|
||||
oxOut("Preloading\n");
|
||||
return detail::preloadDir(ts, src, pl, "/");
|
||||
}
|
||||
|
||||
ox::Error pack(keel::Context *ctx, ox::TypeStore *ts, ox::FileSystem *dest) noexcept;
|
||||
|
||||
}
|
@ -7,13 +7,13 @@
|
||||
#include "media.hpp"
|
||||
#include "typeconv.hpp"
|
||||
|
||||
namespace nostalgia::foundation {
|
||||
namespace keel {
|
||||
|
||||
#ifndef OX_BARE_METAL
|
||||
|
||||
[[nodiscard]]
|
||||
static ox::Result<const BaseConverter*> findConverter(
|
||||
foundation::Context *ctx,
|
||||
keel::Context *ctx,
|
||||
ox::CRStringView srcTypeName, int srcTypeVersion,
|
||||
ox::CRStringView dstTypeName, int dstTypeVersion) noexcept {
|
||||
for (auto &c : ctx->converters) {
|
||||
@ -25,7 +25,7 @@ static ox::Result<const BaseConverter*> findConverter(
|
||||
};
|
||||
|
||||
static ox::Result<ox::UniquePtr<Wrap>> convert(
|
||||
foundation::Context *ctx, const ox::Buffer &srcBuffer,
|
||||
keel::Context *ctx, const ox::Buffer &srcBuffer,
|
||||
ox::CRStringView srcTypeName, int srcTypeVersion,
|
||||
ox::CRStringView dstTypeName, int dstTypeVersion) noexcept {
|
||||
// look for direct converter
|
||||
@ -49,7 +49,7 @@ static ox::Result<ox::UniquePtr<Wrap>> convert(
|
||||
}
|
||||
|
||||
ox::Result<ox::UniquePtr<Wrap>> convert(
|
||||
foundation::Context *ctx,
|
||||
keel::Context *ctx,
|
||||
const ox::Buffer &srcBuffer,
|
||||
ox::CRStringView dstTypeName,
|
||||
int dstTypeVersion) noexcept {
|
@ -10,10 +10,10 @@
|
||||
#include <ox/claw/read.hpp>
|
||||
#include <ox/claw/write.hpp>
|
||||
|
||||
#include "asset.hpp"
|
||||
#include "context.hpp"
|
||||
#include "media.hpp"
|
||||
|
||||
namespace nostalgia::foundation {
|
||||
namespace keel {
|
||||
|
||||
class Wrap {
|
||||
public:
|
||||
@ -87,9 +87,9 @@ class BaseConverter {
|
||||
[[nodiscard]]
|
||||
virtual bool dstMatches(ox::CRStringView dstTypeName, int dstTypeVersion) const noexcept = 0;
|
||||
|
||||
virtual ox::Result<ox::UniquePtr<Wrap>> convertPtrToPtr(foundation::Context *ctx, Wrap *src) const noexcept = 0;
|
||||
virtual ox::Result<ox::UniquePtr<Wrap>> convertPtrToPtr(keel::Context *ctx, Wrap *src) const noexcept = 0;
|
||||
|
||||
virtual ox::Result<ox::UniquePtr<Wrap>> convertBuffToPtr(foundation::Context *ctx, const ox::Buffer &srcBuff) const noexcept = 0;
|
||||
virtual ox::Result<ox::UniquePtr<Wrap>> convertBuffToPtr(keel::Context *ctx, const ox::Buffer &srcBuff) const noexcept = 0;
|
||||
|
||||
[[nodiscard]]
|
||||
inline bool matches(ox::CRStringView srcTypeName, int srcTypeVersion,
|
||||
@ -129,13 +129,13 @@ class Converter: public BaseConverter {
|
||||
&& dstTypeVersion == DstTypeVersion;
|
||||
}
|
||||
|
||||
ox::Result<ox::UniquePtr<Wrap>> convertPtrToPtr(foundation::Context *ctx, Wrap *src) const noexcept final {
|
||||
ox::Result<ox::UniquePtr<Wrap>> convertPtrToPtr(keel::Context *ctx, Wrap *src) const noexcept final {
|
||||
auto dst = makeWrap<DstType>();
|
||||
oxReturnError(convert(ctx, wrapCast<SrcType>(src), wrapCast<DstType>(dst.get())));
|
||||
return ox::Result<ox::UniquePtr<Wrap>>(std::move(dst));
|
||||
}
|
||||
|
||||
ox::Result<ox::UniquePtr<Wrap>> convertBuffToPtr(foundation::Context *ctx, const ox::Buffer &srcBuff) const noexcept final {
|
||||
ox::Result<ox::UniquePtr<Wrap>> convertBuffToPtr(keel::Context *ctx, const ox::Buffer &srcBuff) const noexcept final {
|
||||
oxRequireM(src, readAsset<SrcType>(srcBuff));
|
||||
auto dst = makeWrap<DstType>();
|
||||
oxReturnError(convert(ctx, &src, wrapCast<DstType>(dst.get())));
|
||||
@ -143,15 +143,15 @@ class Converter: public BaseConverter {
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual ox::Error convert(foundation::Context *ctx, SrcType*, DstType*) const noexcept = 0;
|
||||
virtual ox::Error convert(keel::Context *ctx, SrcType*, DstType*) const noexcept = 0;
|
||||
|
||||
};
|
||||
|
||||
ox::Result<ox::UniquePtr<Wrap>> convert(foundation::Context *ctx, const ox::Buffer &srcBuffer,
|
||||
ox::Result<ox::UniquePtr<Wrap>> convert(keel::Context *ctx, const ox::Buffer &srcBuffer,
|
||||
ox::CRStringView dstTypeName, int dstTypeVersion) noexcept;
|
||||
|
||||
template<typename DstType>
|
||||
ox::Result<DstType> convert(foundation::Context *ctx, const ox::Buffer &srcBuffer) noexcept {
|
||||
ox::Result<DstType> convert(keel::Context *ctx, const ox::Buffer &srcBuffer) noexcept {
|
||||
static constexpr auto DstTypeName = ox::requireModelTypeName<DstType>();
|
||||
static constexpr auto DstTypeVersion = ox::requireModelTypeVersion<DstType>();
|
||||
oxRequire(out, convert(ctx, srcBuffer, DstTypeName, DstTypeVersion));
|
||||
@ -159,7 +159,7 @@ ox::Result<DstType> convert(foundation::Context *ctx, const ox::Buffer &srcBuffe
|
||||
}
|
||||
|
||||
template<typename DstType>
|
||||
ox::Error convert(foundation::Context *ctx, const ox::Buffer &buff, DstType *outObj) noexcept {
|
||||
ox::Error convert(keel::Context *ctx, const ox::Buffer &buff, DstType *outObj) noexcept {
|
||||
static constexpr auto DstTypeName = ox::requireModelTypeName<DstType>();
|
||||
static constexpr auto DstTypeVersion = ox::requireModelTypeVersion<DstType>();
|
||||
oxRequire(outPtr, convert(ctx, buff, DstTypeName, DstTypeVersion));
|
||||
@ -168,7 +168,7 @@ ox::Error convert(foundation::Context *ctx, const ox::Buffer &buff, DstType *out
|
||||
}
|
||||
|
||||
template<typename DstType>
|
||||
ox::Result<ox::Buffer> convertBuffToBuff(foundation::Context *ctx, const ox::Buffer &srcBuffer, ox::ClawFormat fmt) noexcept {
|
||||
ox::Result<ox::Buffer> convertBuffToBuff(keel::Context *ctx, const ox::Buffer &srcBuffer, ox::ClawFormat fmt) noexcept {
|
||||
static constexpr auto DstTypeName = ox::requireModelTypeName<DstType>();
|
||||
static constexpr auto DstTypeVersion = ox::requireModelTypeVersion<DstType>();
|
||||
oxRequire(out, convert(ctx, srcBuffer, DstTypeName, DstTypeVersion));
|
||||
@ -176,12 +176,12 @@ ox::Result<ox::Buffer> convertBuffToBuff(foundation::Context *ctx, const ox::Buf
|
||||
}
|
||||
|
||||
template<typename From, typename To, ox::ClawFormat fmt = ox::ClawFormat::Metal>
|
||||
auto transformRule(foundation::Context *ctx, ox::Buffer *buff) -> ox::Error {
|
||||
auto transformRule(keel::Context *ctx, ox::Buffer *buff) noexcept -> ox::Error {
|
||||
oxRequire(hdr, readAssetHeader(*buff));
|
||||
const auto typeId = ox::buildTypeId(
|
||||
hdr.clawHdr.typeName, hdr.clawHdr.typeVersion, hdr.clawHdr.typeParams);
|
||||
if (typeId == ox::buildTypeId<From>()) {
|
||||
oxReturnError(foundation::convertBuffToBuff<To>(ctx, *buff, fmt).moveTo(buff));
|
||||
oxReturnError(keel::convertBuffToBuff<To>(ctx, *buff, fmt).moveTo(buff));
|
||||
}
|
||||
return {};
|
||||
};
|
@ -3,7 +3,6 @@
|
||||
|
||||
add_subdirectory(appmodules)
|
||||
add_subdirectory(core)
|
||||
add_subdirectory(foundation)
|
||||
add_subdirectory(geo)
|
||||
add_subdirectory(scene)
|
||||
|
||||
|
@ -10,7 +10,7 @@ endif()
|
||||
target_link_libraries(
|
||||
NostalgiaAppModules PUBLIC
|
||||
NostalgiaCore
|
||||
NostalgiaFoundation
|
||||
Keel
|
||||
NostalgiaScene
|
||||
)
|
||||
|
||||
|
@ -2,9 +2,7 @@
|
||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#include <ox/std/array.hpp>
|
||||
|
||||
#include <nostalgia/foundation/module.hpp>
|
||||
#include <keel/module.hpp>
|
||||
|
||||
#include <nostalgia/core/module.hpp>
|
||||
#include <nostalgia/scene/scenemodule.hpp>
|
||||
@ -16,13 +14,8 @@ void loadModules() noexcept {
|
||||
if (modulesLoaded) {
|
||||
return;
|
||||
}
|
||||
const ox::Array<foundation::Module*, 2> mods = {
|
||||
&core::CoreModule::mod,
|
||||
&scene::SceneModule::mod,
|
||||
};
|
||||
for (const auto m : mods) {
|
||||
foundation::registerModule(m);
|
||||
}
|
||||
keel::registerModule(core::module());
|
||||
keel::registerModule(scene::module());
|
||||
modulesLoaded = true;
|
||||
}
|
||||
|
||||
|
@ -7,12 +7,6 @@ add_library(
|
||||
typestore.cpp
|
||||
)
|
||||
|
||||
add_library(
|
||||
NostalgiaCore-Headless
|
||||
headless/core.cpp
|
||||
headless/gfx.cpp
|
||||
)
|
||||
|
||||
add_library(NostalgiaCore)
|
||||
|
||||
if(NOT NOSTALGIA_BUILD_TYPE STREQUAL "GBA")
|
||||
@ -21,8 +15,8 @@ if(NOT NOSTALGIA_BUILD_TYPE STREQUAL "GBA")
|
||||
glfw/clipboard.cpp
|
||||
glfw/core.cpp
|
||||
glfw/gfx.cpp
|
||||
userland/gfx.cpp
|
||||
userland/gfx_opengl.cpp
|
||||
opengl/gfx.cpp
|
||||
opengl/gfx_opengl.cpp
|
||||
)
|
||||
target_link_libraries(
|
||||
NostalgiaCore PUBLIC
|
||||
@ -57,7 +51,7 @@ endif()
|
||||
|
||||
target_link_libraries(
|
||||
NostalgiaCore-Common PUBLIC
|
||||
NostalgiaFoundation
|
||||
Keel
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
@ -65,11 +59,6 @@ target_link_libraries(
|
||||
NostalgiaCore-Common
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
NostalgiaCore-Headless PUBLIC
|
||||
NostalgiaCore-Common
|
||||
)
|
||||
|
||||
if(NOSTALGIA_BUILD_STUDIO)
|
||||
add_subdirectory(studio)
|
||||
endif()
|
||||
@ -84,7 +73,9 @@ install(
|
||||
core.hpp
|
||||
event.hpp
|
||||
gfx.hpp
|
||||
ptidxconv.hpp
|
||||
input.hpp
|
||||
tilesheet.hpp
|
||||
typeconv.hpp
|
||||
typestore.hpp
|
||||
DESTINATION
|
||||
@ -94,8 +85,7 @@ install(
|
||||
install(
|
||||
TARGETS
|
||||
NostalgiaCore
|
||||
NostalgiaCore-Headless
|
||||
DESTINATION
|
||||
LIBRARY DESTINATION lib/nostalgia
|
||||
ARCHIVE DESTINATION lib/nostalgia
|
||||
LIBRARY DESTINATION lib
|
||||
ARCHIVE DESTINATION lib
|
||||
)
|
||||
|
@ -10,7 +10,7 @@ constexpr auto TileWidth = 8;
|
||||
constexpr auto TileHeight = 8;
|
||||
constexpr auto PixelsPerTile = TileWidth * TileHeight;
|
||||
|
||||
constexpr auto FileExt_ng = ".ng";
|
||||
constexpr auto FileExt_npal = ".npal";
|
||||
constexpr auto FileExt_ng = "ng";
|
||||
constexpr auto FileExt_npal = "npal";
|
||||
|
||||
}
|
||||
|
@ -8,11 +8,23 @@
|
||||
#include <ox/model/desctypes.hpp>
|
||||
#include <ox/std/buffer.hpp>
|
||||
|
||||
#include <nostalgia/foundation/context.hpp>
|
||||
#include <keel/context.hpp>
|
||||
#include <nostalgia/geo/size.hpp>
|
||||
|
||||
#include "event.hpp"
|
||||
#include "input.hpp"
|
||||
|
||||
namespace nostalgia::core::gl {
|
||||
void drawMainView(core::Context*) noexcept;
|
||||
void setRenderSize(core::Context*, int width, int height) noexcept;
|
||||
geo::Size getRenderSize(core::Context*) noexcept;
|
||||
void clearRenderSize(core::Context *ctx) noexcept;
|
||||
}
|
||||
|
||||
namespace nostalgia::core::renderer {
|
||||
ox::Error init(Context *ctx) noexcept;
|
||||
}
|
||||
|
||||
namespace nostalgia::geo {
|
||||
class Size;
|
||||
}
|
||||
@ -47,7 +59,7 @@ struct BgCbbData {
|
||||
};
|
||||
|
||||
// User Input Output
|
||||
class Context: public foundation::Context {
|
||||
class Context: public keel::Context {
|
||||
friend constexpr void setApplicationData(Context *ctx, void *applicationData) noexcept;
|
||||
template<typename T>
|
||||
friend constexpr T *applicationData(Context *ctx) noexcept;
|
||||
@ -58,6 +70,7 @@ class Context: public foundation::Context {
|
||||
friend int getScreenHeight(Context *ctx) noexcept;
|
||||
friend int getScreenWidth(Context *ctx) noexcept;
|
||||
friend ox::Error initGfx(Context *ctx) noexcept;
|
||||
friend ox::Error renderer::init(Context *ctx) noexcept;
|
||||
friend ox::Error loadBgTileSheet(Context *ctx,
|
||||
unsigned cbb,
|
||||
const ox::FileAddress &tilesheetPath,
|
||||
@ -84,14 +97,18 @@ class Context: public foundation::Context {
|
||||
friend constexpr KeyEventHandler keyEventHandler(Context *ctx) noexcept;
|
||||
friend void setTile(Context *ctx, unsigned bgIdx, int column, int row, uint8_t tile) noexcept;
|
||||
friend void setSprite(Context *ctx,
|
||||
unsigned idx,
|
||||
int x,
|
||||
int y,
|
||||
unsigned tileIdx,
|
||||
unsigned spriteShape,
|
||||
unsigned spriteSize,
|
||||
unsigned flipX) noexcept;
|
||||
unsigned idx,
|
||||
int x,
|
||||
int y,
|
||||
unsigned tileIdx,
|
||||
unsigned spriteShape,
|
||||
unsigned spriteSize,
|
||||
unsigned flipX) noexcept;
|
||||
friend void hideSprite(Context *ctx, unsigned idx) noexcept;
|
||||
friend void gl::drawMainView(core::Context*) noexcept;
|
||||
friend void gl::setRenderSize(core::Context*, int width, int height) noexcept;
|
||||
friend geo::Size gl::getRenderSize(core::Context*) noexcept;
|
||||
friend void gl::clearRenderSize(core::Context *ctx) noexcept;
|
||||
|
||||
public:
|
||||
ox::Vector<Drawer*, 5> drawers;
|
||||
|
@ -40,8 +40,8 @@ static void initTimer() noexcept {
|
||||
static ox::Result<std::size_t> findPreloadSection() noexcept {
|
||||
// put the header in the wrong order to prevent mistaking this code for the
|
||||
// media section
|
||||
constexpr auto headerP2 = "D_HEADER________";
|
||||
constexpr auto headerP1 = "NOSTALGIA_PRELOA";
|
||||
constexpr auto headerP2 = "DER_____________";
|
||||
constexpr auto headerP1 = "KEEL_PRELOAD_HEA";
|
||||
constexpr auto headerP1Len = ox_strlen(headerP2);
|
||||
constexpr auto headerP2Len = ox_strlen(headerP1);
|
||||
constexpr auto headerLen = headerP1Len + headerP2Len;
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include <ox/mc/mc.hpp>
|
||||
#include <ox/std/array.hpp>
|
||||
|
||||
#include <nostalgia/foundation/media.hpp>
|
||||
#include <keel/media.hpp>
|
||||
#include <nostalgia/core/context.hpp>
|
||||
#include <nostalgia/core/gfx.hpp>
|
||||
|
||||
@ -130,7 +130,7 @@ ox::Error initConsole(Context *ctx) noexcept {
|
||||
setBgStatus(ctx, 0b0001);
|
||||
if (!ctx) {
|
||||
ctx = new (ox_alloca(sizeof(Context))) Context();
|
||||
oxRequire(rom, foundation::loadRom());
|
||||
oxRequire(rom, keel::loadRom());
|
||||
ox::FileStore32 fs(rom, 32 * ox::units::MB);
|
||||
auto romFs = new (ox_alloca(sizeof(ox::FileSystem32))) ox::FileSystem32(fs);
|
||||
new (&ctx->rom) ox::UniquePtr<ox::FileSystem>(romFs);
|
||||
|
@ -18,6 +18,12 @@
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
namespace gl {
|
||||
|
||||
void setMainViewEnabled(bool) noexcept;
|
||||
|
||||
}
|
||||
|
||||
extern ox::Array<char, 128> charMap;
|
||||
|
||||
class Drawer {
|
||||
|
@ -5,17 +5,17 @@
|
||||
#include <glad/glad.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include <nostalgia/foundation/foundation.hpp>
|
||||
#include <keel/keel.hpp>
|
||||
#include <nostalgia/core/gfx.hpp>
|
||||
#include <nostalgia/core/input.hpp>
|
||||
#include <nostalgia/core/userland/gfx.hpp>
|
||||
#include <nostalgia/core/opengl/gfx.hpp>
|
||||
|
||||
#include "core.hpp"
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
ox::Result<ox::UPtr<Context>> init(ox::UPtr<ox::FileSystem> fs, ox::CRStringView appName) noexcept {
|
||||
oxRequireM(ctx, foundation::init<Context>(std::move(fs), appName));
|
||||
oxRequireM(ctx, keel::init<Context>(std::move(fs), appName));
|
||||
const auto id = ox::make<GlfwImplData>();
|
||||
ctx->setWindowerData(id);
|
||||
using namespace std::chrono;
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include <ox/std/defines.hpp>
|
||||
|
||||
#include <nostalgia/core/config.hpp>
|
||||
#include <nostalgia/core/userland/gfx.hpp>
|
||||
#include <nostalgia/core/opengl/gfx.hpp>
|
||||
|
||||
#include "core.hpp"
|
||||
|
||||
@ -216,9 +216,7 @@ ox::Error initGfx(Context *ctx) noexcept {
|
||||
ImGui_ImplGlfw_InitForOpenGL(id->window, true);
|
||||
}
|
||||
themeImgui();
|
||||
void *rendererData = nullptr;
|
||||
oxReturnError(renderer::init(ctx, &rendererData));
|
||||
ctx->setRendererData(rendererData);
|
||||
oxReturnError(renderer::init(ctx));
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
|
@ -1,25 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#include <nostalgia/core/core.hpp>
|
||||
#include <nostalgia/core/input.hpp>
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
ox::Result<ox::UniquePtr<Context>> init(ox::UniquePtr<ox::FileSystem>, ox::CRStringView) noexcept {
|
||||
return OxError(1);
|
||||
}
|
||||
|
||||
void setUpdateHandler(Context*, UpdateHandler) noexcept {
|
||||
}
|
||||
|
||||
uint64_t ticksMs(Context*) noexcept {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool buttonDown(Context*, Key) noexcept {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
@ -1,101 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#include <nostalgia/core/context.hpp>
|
||||
#include <nostalgia/core/gfx.hpp>
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
ox::Error initGfx(Context*) noexcept {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
ox::Error shutdownGfx(Context*) noexcept {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
void setWindowTitle(Context*, ox::CRStringView) noexcept {
|
||||
}
|
||||
|
||||
void focusWindow(Context*) noexcept {
|
||||
}
|
||||
|
||||
int getScreenWidth(Context*) noexcept {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int getScreenHeight(Context*) noexcept {
|
||||
return 0;
|
||||
}
|
||||
|
||||
geo::Size getScreenSize(Context*) noexcept {
|
||||
return {0, 0};
|
||||
}
|
||||
|
||||
uint8_t bgStatus(Context*) noexcept {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void setBgStatus(Context*, uint32_t) noexcept {
|
||||
}
|
||||
|
||||
bool bgStatus(Context*, unsigned) noexcept {
|
||||
return false;
|
||||
}
|
||||
|
||||
void setBgStatus(Context*, unsigned, bool) noexcept {
|
||||
}
|
||||
|
||||
// Do NOT rely on Context in the GBA version of this function.
|
||||
ox::Error initConsole(Context*) noexcept {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
ox::Error loadBgTileSheet(Context*,
|
||||
int,
|
||||
const ox::FileAddress&,
|
||||
const ox::FileAddress&) noexcept {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
ox::Error loadSpriteTileSheet(Context*,
|
||||
const ox::FileAddress&,
|
||||
const ox::FileAddress&) noexcept {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
ox::Error loadBgPalette(Context*, int, const ox::FileAddress&) noexcept {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
ox::Error loadSpritePalette(Context*, int, const ox::FileAddress&) noexcept {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
// Do NOT use Context in the GBA version of this function.
|
||||
void puts(Context*, int, int, ox::CRStringView) noexcept {
|
||||
}
|
||||
|
||||
void setTile(Context*, int, int, int, uint8_t) noexcept {
|
||||
}
|
||||
|
||||
// Do NOT use Context in the GBA version of this function.
|
||||
void clearTileLayer(Context*, int) noexcept {
|
||||
}
|
||||
|
||||
[[maybe_unused]]
|
||||
void hideSprite(Context*, unsigned) noexcept {
|
||||
}
|
||||
|
||||
void setSprite(Context*,
|
||||
unsigned,
|
||||
int,
|
||||
int,
|
||||
unsigned,
|
||||
unsigned,
|
||||
unsigned,
|
||||
unsigned) noexcept {
|
||||
}
|
||||
|
||||
}
|
@ -4,8 +4,8 @@
|
||||
|
||||
#include <ox/model/model.hpp>
|
||||
|
||||
#include <nostalgia/foundation/asset.hpp>
|
||||
#include <nostalgia/foundation/module.hpp>
|
||||
#include <keel/asset.hpp>
|
||||
#include <keel/module.hpp>
|
||||
|
||||
#include "gfx.hpp"
|
||||
#include "typeconv.hpp"
|
||||
@ -14,20 +14,41 @@
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
class CoreModule: public keel::Module {
|
||||
private:
|
||||
NostalgiaPaletteToPaletteConverter nostalgiaPaletteToPaletteConverter;
|
||||
TileSheetV1ToTileSheetConverter nostalgiaGraphicToTileSheetConverter;
|
||||
TileSheetToCompactTileSheetConverter tileSheetToCompactTileSheetConverter;
|
||||
TileSheetV2ToTileSheetConverter tileSheetV2ToTileSheetConverter;
|
||||
|
||||
public:
|
||||
static CoreModule mod;
|
||||
[[nodiscard]]
|
||||
ox::Vector<keel::TypeDescGenerator> types() const noexcept override;
|
||||
[[nodiscard]]
|
||||
ox::Vector<const keel::BaseConverter*> converters() const noexcept override;
|
||||
[[nodiscard]]
|
||||
ox::Vector<keel::PackTransform> packTransforms() const noexcept override;
|
||||
};
|
||||
|
||||
CoreModule CoreModule::mod;
|
||||
|
||||
ox::Vector<foundation::TypeDescGenerator> CoreModule::types() const noexcept {
|
||||
const keel::Module *module() noexcept {
|
||||
return &CoreModule::mod;
|
||||
}
|
||||
|
||||
ox::Vector<keel::TypeDescGenerator> CoreModule::types() const noexcept {
|
||||
return {
|
||||
foundation::generateTypeDesc<TileSheetV1>,
|
||||
foundation::generateTypeDesc<TileSheetV2>,
|
||||
foundation::generateTypeDesc<TileSheet>,
|
||||
foundation::generateTypeDesc<CompactTileSheet>,
|
||||
foundation::generateTypeDesc<NostalgiaPalette>,
|
||||
foundation::generateTypeDesc<Palette>,
|
||||
keel::generateTypeDesc<TileSheetV1>,
|
||||
keel::generateTypeDesc<TileSheetV2>,
|
||||
keel::generateTypeDesc<TileSheet>,
|
||||
keel::generateTypeDesc<CompactTileSheet>,
|
||||
keel::generateTypeDesc<NostalgiaPalette>,
|
||||
keel::generateTypeDesc<Palette>,
|
||||
};
|
||||
}
|
||||
|
||||
ox::Vector<const foundation::BaseConverter*> CoreModule::converters() const noexcept {
|
||||
ox::Vector<const keel::BaseConverter*> CoreModule::converters() const noexcept {
|
||||
return {
|
||||
&nostalgiaPaletteToPaletteConverter,
|
||||
&nostalgiaGraphicToTileSheetConverter,
|
||||
@ -36,16 +57,16 @@ ox::Vector<const foundation::BaseConverter*> CoreModule::converters() const noex
|
||||
};
|
||||
}
|
||||
|
||||
ox::Vector<foundation::PackTransform> CoreModule::packTransforms() const noexcept {
|
||||
ox::Vector<keel::PackTransform> CoreModule::packTransforms() const noexcept {
|
||||
return {
|
||||
// convert tilesheets to CompactTileSheets
|
||||
[](foundation::Context *ctx, ox::Buffer *buff) -> ox::Error {
|
||||
oxRequire(hdr, foundation::readAssetHeader(*buff));
|
||||
[](keel::Context *ctx, ox::Buffer *buff) -> ox::Error {
|
||||
oxRequire(hdr, keel::readAssetHeader(*buff));
|
||||
const auto typeId = ox::buildTypeId(hdr.clawHdr.typeName, hdr.clawHdr.typeVersion, hdr.clawHdr.typeParams);
|
||||
if (typeId == ox::buildTypeId<TileSheetV1>() ||
|
||||
typeId == ox::buildTypeId<TileSheetV2>() ||
|
||||
typeId == ox::buildTypeId<TileSheet>()) {
|
||||
oxReturnError(foundation::convertBuffToBuff<core::CompactTileSheet>(
|
||||
oxReturnError(keel::convertBuffToBuff<core::CompactTileSheet>(
|
||||
ctx, *buff, ox::ClawFormat::Metal).moveTo(buff));
|
||||
}
|
||||
return {};
|
||||
|
@ -4,27 +4,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <nostalgia/foundation/module.hpp>
|
||||
|
||||
#include "typeconv.hpp"
|
||||
#include <keel/module.hpp>
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
class CoreModule: public foundation::Module {
|
||||
private:
|
||||
NostalgiaPaletteToPaletteConverter nostalgiaPaletteToPaletteConverter;
|
||||
TileSheetV1ToTileSheetConverter nostalgiaGraphicToTileSheetConverter;
|
||||
TileSheetToCompactTileSheetConverter tileSheetToCompactTileSheetConverter;
|
||||
TileSheetV2ToTileSheetConverter tileSheetV2ToTileSheetConverter;
|
||||
|
||||
public:
|
||||
static CoreModule mod;
|
||||
[[nodiscard]]
|
||||
ox::Vector<foundation::TypeDescGenerator> types() const noexcept override;
|
||||
[[nodiscard]]
|
||||
ox::Vector<const foundation::BaseConverter*> converters() const noexcept override;
|
||||
[[nodiscard]]
|
||||
ox::Vector<foundation::PackTransform> packTransforms() const noexcept override;
|
||||
};
|
||||
const keel::Module *module() noexcept;
|
||||
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
*/
|
||||
|
||||
#include <nostalgia/core/gfx.hpp>
|
||||
#include <nostalgia/foundation/media.hpp>
|
||||
#include <keel/media.hpp>
|
||||
|
||||
#include "gfx.hpp"
|
||||
|
@ -18,6 +18,16 @@ namespace nostalgia::core {
|
||||
|
||||
void ImGui_Impl_NewFrame() noexcept;
|
||||
|
||||
namespace gl {
|
||||
|
||||
static bool mainViewEnabled = true;
|
||||
|
||||
void setMainViewEnabled(bool enabled) noexcept {
|
||||
mainViewEnabled = enabled;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace renderer {
|
||||
|
||||
constexpr uint64_t TileRows = 128;
|
||||
@ -67,6 +77,7 @@ struct GlImplData {
|
||||
SpriteBlockset spriteBlocks;
|
||||
ox::Array<Sprite, 128> spriteStates;
|
||||
ox::Array<Background, 4> backgrounds;
|
||||
ox::Optional<geo::Size> renderSize;
|
||||
};
|
||||
|
||||
constexpr ox::StringView bgvshadTmpl = R"(
|
||||
@ -74,9 +85,13 @@ constexpr ox::StringView bgvshadTmpl = R"(
|
||||
in vec2 vTexCoord;
|
||||
in vec2 vPosition;
|
||||
out vec2 fTexCoord;
|
||||
uniform float vXScale;
|
||||
uniform float vTileHeight;
|
||||
void main() {
|
||||
gl_Position = vec4(vPosition, 0.0, 1.0);
|
||||
float xScaleInvert = 1.0 - vXScale;
|
||||
gl_Position = vec4(
|
||||
vPosition.x * vXScale - xScaleInvert, vPosition.y,
|
||||
0.0, 1.0);
|
||||
fTexCoord = vTexCoord * vec2(1, vTileHeight);
|
||||
})";
|
||||
|
||||
@ -98,9 +113,13 @@ constexpr ox::StringView spritevshadTmpl = R"(
|
||||
in vec2 vTexCoord;
|
||||
in vec2 vPosition;
|
||||
out vec2 fTexCoord;
|
||||
uniform float vXScale;
|
||||
uniform float vTileHeight;
|
||||
void main() {
|
||||
gl_Position = vec4(vPosition, 0.0, 1.0);
|
||||
float xScaleInvert = 1.0 - vXScale;
|
||||
gl_Position = vec4(
|
||||
vPosition.x * vXScale - xScaleInvert, vPosition.y,
|
||||
0.0, 1.0);
|
||||
fTexCoord = vTexCoord * vec2(1, vTileHeight) * vec2(vEnabled, vEnabled);
|
||||
})";
|
||||
|
||||
@ -111,7 +130,7 @@ static constexpr auto bgVertexRow(unsigned x, unsigned y) noexcept {
|
||||
return y * TileRows + x;
|
||||
}
|
||||
|
||||
static void setSpriteBufferObject(Context *ctx,
|
||||
static void setSpriteBufferObject(Context*,
|
||||
unsigned vi,
|
||||
float enabled,
|
||||
float x, float y,
|
||||
@ -120,9 +139,8 @@ static void setSpriteBufferObject(Context *ctx,
|
||||
float *vbo,
|
||||
GLuint *ebo) noexcept {
|
||||
// don't worry, this memcpy gets optimized to something much more ideal
|
||||
const auto [sw, sh] = getScreenSize(ctx);
|
||||
constexpr float xmod = 0.1f;
|
||||
constexpr float ymod = 0.1f;
|
||||
const auto xmod = ymod * static_cast<float>(sh) / static_cast<float>(sw);
|
||||
x *= xmod;
|
||||
y *= -ymod;
|
||||
x -= 1.f;
|
||||
@ -144,7 +162,7 @@ static void setSpriteBufferObject(Context *ctx,
|
||||
memcpy(ebo, elms.data(), sizeof(elms));
|
||||
}
|
||||
|
||||
static void setTileBufferObject(Context *ctx,
|
||||
static void setTileBufferObject(Context*,
|
||||
unsigned vi,
|
||||
float x,
|
||||
float y,
|
||||
@ -152,9 +170,8 @@ static void setTileBufferObject(Context *ctx,
|
||||
float *vbo,
|
||||
GLuint *ebo) noexcept {
|
||||
// don't worry, this memcpy gets optimized to something much more ideal
|
||||
const auto [sw, sh] = getScreenSize(ctx);
|
||||
constexpr float ymod = 2.0f / 20.0f;
|
||||
const float xmod = ymod * static_cast<float>(sh) / static_cast<float>(sw);
|
||||
constexpr float ymod = 0.1f;
|
||||
constexpr float xmod = 0.1f;
|
||||
x *= xmod;
|
||||
y *= -ymod;
|
||||
x -= 1.0f;
|
||||
@ -279,11 +296,15 @@ static void drawBackground(CBB *cbb) noexcept {
|
||||
glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(cbb->elements.size()), GL_UNSIGNED_INT, nullptr);
|
||||
}
|
||||
|
||||
static void drawBackgrounds(GlImplData *id) noexcept {
|
||||
static void drawBackgrounds(core::Context *ctx, GlImplData *id) noexcept {
|
||||
// load background shader and its uniforms
|
||||
glUseProgram(id->bgShader);
|
||||
const auto uniformXScale = static_cast<GLint>(glGetUniformLocation(id->bgShader, "vXScale"));
|
||||
const auto uniformTileHeight = static_cast<GLint>(glGetUniformLocation(id->bgShader, "vTileHeight"));
|
||||
//glUniform3fv(uniformPalette, GlImplData::ColorCnt, id->palette.data());
|
||||
const auto [wi, hi] = gl::getRenderSize(ctx);
|
||||
const auto wf = static_cast<float>(wi);
|
||||
const auto hf = static_cast<float>(hi);
|
||||
glUniform1f(uniformXScale, hf / wf);
|
||||
for (const auto &bg : id->backgrounds) {
|
||||
if (bg.enabled) {
|
||||
auto &cbb = id->cbbs[bg.cbbIdx];
|
||||
@ -294,10 +315,15 @@ static void drawBackgrounds(GlImplData *id) noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
static void drawSprites(GlImplData *id) noexcept {
|
||||
static void drawSprites(core::Context *ctx, GlImplData *id) noexcept {
|
||||
glUseProgram(id->spriteShader);
|
||||
auto &sb = id->spriteBlocks;
|
||||
const auto uniformXScale = static_cast<GLint>(glGetUniformLocation(id->bgShader, "vXScale"));
|
||||
const auto uniformTileHeight = static_cast<GLint>(glGetUniformLocation(id->spriteShader, "vTileHeight"));
|
||||
const auto [wi, hi] = gl::getRenderSize(ctx);
|
||||
const auto wf = static_cast<float>(wi);
|
||||
const auto hf = static_cast<float>(hi);
|
||||
glUniform1f(uniformXScale, hf / wf);
|
||||
// update vbo
|
||||
glBindVertexArray(sb.vao);
|
||||
if (sb.updated) {
|
||||
@ -312,7 +338,7 @@ static void drawSprites(GlImplData *id) noexcept {
|
||||
glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(sb.elements.size()), GL_UNSIGNED_INT, nullptr);
|
||||
}
|
||||
|
||||
ox::Error init(Context *ctx, void **rendererData) noexcept {
|
||||
ox::Error init(Context *ctx) noexcept {
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
const auto bgVshad = ox::sfmt(bgvshadTmpl, glutils::GlslVersion);
|
||||
@ -320,7 +346,7 @@ ox::Error init(Context *ctx, void **rendererData) noexcept {
|
||||
const auto spriteVshad = ox::sfmt(spritevshadTmpl, glutils::GlslVersion);
|
||||
const auto spriteFshad = ox::sfmt(spritefshadTmpl, glutils::GlslVersion);
|
||||
const auto id = ox::make<GlImplData>();
|
||||
*rendererData = id;
|
||||
ctx->setRendererData(id);
|
||||
oxReturnError(glutils::buildShaderProgram(bgVshad.c_str(), bgFshad.c_str()).moveTo(&id->bgShader));
|
||||
oxReturnError(glutils::buildShaderProgram(spriteVshad.c_str(), spriteFshad.c_str()).moveTo(&id->spriteShader));
|
||||
for (auto &bg : id->cbbs) {
|
||||
@ -328,7 +354,7 @@ ox::Error init(Context *ctx, void **rendererData) noexcept {
|
||||
}
|
||||
initSpritesBufferset(ctx, id->spriteShader, &id->spriteBlocks);
|
||||
ImGui_ImplOpenGL3_Init(glutils::GlslVersion);
|
||||
return OxError(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
void shutdown(Context*, void *rendererData) noexcept {
|
||||
@ -422,9 +448,8 @@ void draw(Context *ctx) noexcept {
|
||||
glClearColor(0, 0, 0, 1);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
// render
|
||||
renderer::drawBackgrounds(id);
|
||||
if (id->spriteBlocks.tex) {
|
||||
renderer::drawSprites(id);
|
||||
if (gl::mainViewEnabled) {
|
||||
gl::drawMainView(ctx);
|
||||
}
|
||||
for (const auto cd : ctx->drawers) {
|
||||
cd->draw(ctx);
|
||||
@ -530,4 +555,35 @@ void setTile(Context *ctx, unsigned bgIdx, int column, int row, uint8_t tile) no
|
||||
bg.updated = true;
|
||||
}
|
||||
|
||||
namespace gl {
|
||||
|
||||
void drawMainView(core::Context *ctx) noexcept {
|
||||
const auto id = ctx->rendererData<renderer::GlImplData>();
|
||||
renderer::drawBackgrounds(ctx, id);
|
||||
if (id->spriteBlocks.tex) {
|
||||
renderer::drawSprites(ctx, id);
|
||||
}
|
||||
}
|
||||
|
||||
void setRenderSize(core::Context *ctx, int width, int height) noexcept {
|
||||
const auto id = ctx->rendererData<renderer::GlImplData>();
|
||||
id->renderSize.emplace(width, height);
|
||||
}
|
||||
|
||||
void clearRenderSize(core::Context *ctx) noexcept {
|
||||
auto id = ctx->rendererData<renderer::GlImplData>();
|
||||
id->renderSize.reset();
|
||||
}
|
||||
|
||||
geo::Size getRenderSize(core::Context *ctx) noexcept {
|
||||
const auto id = ctx->rendererData<renderer::GlImplData>();
|
||||
if (id->renderSize.has_value()) {
|
||||
return id->renderSize.value();
|
||||
} else {
|
||||
return core::getScreenSize(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
constexpr auto ModuleName = "NostalgiaCore";
|
||||
constexpr auto TileSheetDir = "/TileSheets/";
|
||||
constexpr auto PaletteDir = "/Palettes/";
|
||||
|
||||
}
|
@ -14,7 +14,7 @@ namespace nostalgia::core {
|
||||
ox::Vector<studio::EditorMaker> StudioModule::editors(core::Context *ctx) noexcept {
|
||||
return {
|
||||
{
|
||||
{"ng"},
|
||||
{FileExt_ng},
|
||||
[ctx](ox::CRStringView path) -> ox::Result<studio::BaseEditor*> {
|
||||
try {
|
||||
return ox::make<TileSheetEditorImGui>(ctx, path);
|
||||
@ -24,7 +24,7 @@ ox::Vector<studio::EditorMaker> StudioModule::editors(core::Context *ctx) noexce
|
||||
}
|
||||
},
|
||||
{
|
||||
{"npal"},
|
||||
{FileExt_npal},
|
||||
[ctx](ox::CRStringView path) -> ox::Result<studio::BaseEditor*> {
|
||||
return PaletteEditorImGui::make(ctx, path);
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include <imgui.h>
|
||||
|
||||
#include <nostalgia/core/gfx.hpp>
|
||||
#include <nostalgia/foundation/media.hpp>
|
||||
#include <keel/media.hpp>
|
||||
#include <ox/std/memory.hpp>
|
||||
|
||||
#include "paletteeditor.hpp"
|
||||
@ -19,7 +19,7 @@ ox::Result<PaletteEditorImGui*> PaletteEditorImGui::make(Context *ctx, ox::CRStr
|
||||
out->m_itemPath = path;
|
||||
const auto lastSlash = std::find(out->m_itemPath.rbegin(), out->m_itemPath.rend(), '/').offset();
|
||||
out->m_itemName = out->m_itemPath.substr(lastSlash + 1);
|
||||
oxRequire(pal, foundation::readObj<Palette>(out->m_ctx, ox::FileAddress(out->m_itemPath.c_str())));
|
||||
oxRequire(pal, keel::readObj<Palette>(out->m_ctx, ox::FileAddress(out->m_itemPath.c_str())));
|
||||
out->m_pal = *pal;
|
||||
return out.release();
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include <imgui.h>
|
||||
#include <lodepng.h>
|
||||
|
||||
#include <nostalgia/foundation/media.hpp>
|
||||
#include <keel/media.hpp>
|
||||
#include <nostalgia/geo/point.hpp>
|
||||
|
||||
#include "tilesheeteditor-imgui.hpp"
|
||||
@ -46,7 +46,7 @@ TileSheetEditorImGui::TileSheetEditorImGui(Context *ctx, ox::CRStringView path):
|
||||
// init palette idx
|
||||
const auto &palPath = model()->palPath();
|
||||
auto sctx = applicationData<studio::StudioContext>(m_ctx);
|
||||
const auto &palList = sctx->project->fileList(core::FileExt_npal + 1);
|
||||
const auto &palList = sctx->project->fileList(core::FileExt_npal);
|
||||
for (std::size_t i = 0; const auto &pal : palList) {
|
||||
if (palPath == pal) {
|
||||
m_selectedPaletteIdx = i;
|
||||
@ -278,10 +278,9 @@ void TileSheetEditorImGui::drawTileSheet(const geo::Vec2 &fbSize) noexcept {
|
||||
const auto winPos = ImGui::GetWindowPos();
|
||||
const auto fbSizei = geo::Size(static_cast<int>(fbSize.x), static_cast<int>(fbSize.y));
|
||||
if (m_framebuffer.width != fbSizei.width || m_framebuffer.height != fbSizei.height) {
|
||||
m_framebuffer = glutils::generateFrameBuffer(fbSizei.width, fbSizei.height);
|
||||
glutils::resizeInitFrameBuffer(&m_framebuffer, fbSizei.width, fbSizei.height);
|
||||
m_tileSheetEditor.resizeView(fbSize);
|
||||
} else if (m_tileSheetEditor.updated()) {
|
||||
m_tileSheetEditor.resizeView(fbSize);
|
||||
m_tileSheetEditor.ackUpdate();
|
||||
}
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
|
||||
@ -344,7 +343,7 @@ void TileSheetEditorImGui::drawTileSheet(const geo::Vec2 &fbSize) noexcept {
|
||||
|
||||
void TileSheetEditorImGui::drawPaletteSelector() noexcept {
|
||||
auto sctx = applicationData<studio::StudioContext>(m_ctx);
|
||||
const auto &files = sctx->project->fileList(core::FileExt_npal + 1);
|
||||
const auto &files = sctx->project->fileList(core::FileExt_npal);
|
||||
const auto first = m_selectedPaletteIdx < files.size() ?
|
||||
files[m_selectedPaletteIdx].c_str() : "";
|
||||
if (ImGui::BeginCombo("Palette", first, 0)) {
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include <ox/std/memory.hpp>
|
||||
|
||||
#include <nostalgia/core/clipboard.hpp>
|
||||
#include <nostalgia/foundation/media.hpp>
|
||||
#include <keel/media.hpp>
|
||||
|
||||
#include "tilesheeteditormodel.hpp"
|
||||
|
||||
|
@ -23,7 +23,7 @@ class TileSheetEditorModel: public ox::SignalHandler {
|
||||
static const Palette s_defaultPalette;
|
||||
TileSheet m_img;
|
||||
TileSheet::SubSheetIdx m_activeSubsSheetIdx;
|
||||
foundation::AssetRef<Palette> m_pal;
|
||||
keel::AssetRef<Palette> m_pal;
|
||||
studio::UndoStack m_undoStack;
|
||||
class DrawCommand *m_ongoingDrawCommand = nullptr;
|
||||
bool m_updated = false;
|
||||
|
@ -3,7 +3,7 @@
|
||||
*/
|
||||
|
||||
#include <nostalgia/core/consts.hpp>
|
||||
#include <nostalgia/foundation/media.hpp>
|
||||
#include <keel/media.hpp>
|
||||
#include <nostalgia/geo/point.hpp>
|
||||
|
||||
#include "tilesheeteditorview.hpp"
|
||||
@ -76,7 +76,7 @@ void TileSheetEditorView::clickSelect(const geo::Vec2 &paneSize, const geo::Vec2
|
||||
|
||||
void TileSheetEditorView::clickFill(const geo::Vec2 &paneSize, const geo::Vec2 &clickPos) noexcept {
|
||||
const auto pt = clickPoint(paneSize, clickPos);
|
||||
m_model.fill(pt, m_palIdx);
|
||||
m_model.fill(pt, static_cast<int>(m_palIdx));
|
||||
}
|
||||
|
||||
void TileSheetEditorView::releaseMouseButton() noexcept {
|
||||
@ -100,6 +100,7 @@ ox::Error TileSheetEditorView::markUpdated() noexcept {
|
||||
|
||||
void TileSheetEditorView::ackUpdate() noexcept {
|
||||
m_updated = false;
|
||||
m_pixelsDrawer.update(m_viewSize);
|
||||
m_model.ackUpdate();
|
||||
}
|
||||
|
||||
@ -122,7 +123,7 @@ geo::Point TileSheetEditorView::clickPoint(const geo::Vec2 &paneSize, const geo:
|
||||
|
||||
ox::Error TileSheetEditorView::setActiveSubsheet(const TileSheet::SubSheetIdx&) noexcept {
|
||||
initView();
|
||||
return OxError(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -28,6 +28,8 @@ void TileSheetGrid::draw(bool update, const geo::Vec2 &scroll) noexcept {
|
||||
const auto uniformScroll = glGetUniformLocation(m_shader, "gScroll");
|
||||
glUniform2f(uniformScroll, scroll.x, scroll.y);
|
||||
glDrawArrays(GL_POINTS, 0, static_cast<GLsizei>(m_bufferSet.vertices.size() / VertexVboRowLength));
|
||||
glBindVertexArray(0);
|
||||
glUseProgram(0);
|
||||
}
|
||||
|
||||
void TileSheetGrid::initBufferSet(const geo::Vec2 &paneSize, const TileSheet::SubSheet &subsheet) noexcept {
|
||||
|
@ -31,18 +31,15 @@ void TileSheetPixels::draw(bool update, const geo::Vec2 &scroll) noexcept {
|
||||
const auto uniformScroll = glGetUniformLocation(m_shader, "vScroll");
|
||||
glUniform2f(uniformScroll, scroll.x, scroll.y);
|
||||
glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(m_bufferSet.elements.size()), GL_UNSIGNED_INT, nullptr);
|
||||
glBindVertexArray(0);
|
||||
glUseProgram(0);
|
||||
}
|
||||
|
||||
void TileSheetPixels::initBufferSet(const geo::Vec2 &paneSize) noexcept {
|
||||
// vao
|
||||
void TileSheetPixels::initBufferSet(geo::Vec2 const&paneSize) noexcept {
|
||||
m_bufferSet.vao = glutils::generateVertexArrayObject();
|
||||
glBindVertexArray(m_bufferSet.vao);
|
||||
// vbo & ebo
|
||||
m_bufferSet.vbo = glutils::generateBuffer();
|
||||
m_bufferSet.ebo = glutils::generateBuffer();
|
||||
setBufferObjects(paneSize);
|
||||
glutils::sendVbo(m_bufferSet);
|
||||
glutils::sendEbo(m_bufferSet);
|
||||
update(paneSize);
|
||||
// vbo layout
|
||||
const auto posAttr = static_cast<GLuint>(glGetAttribLocation(m_shader, "vPosition"));
|
||||
glEnableVertexAttribArray(posAttr);
|
||||
@ -53,6 +50,13 @@ void TileSheetPixels::initBufferSet(const geo::Vec2 &paneSize) noexcept {
|
||||
reinterpret_cast<void*>(2 * sizeof(float)));
|
||||
}
|
||||
|
||||
void TileSheetPixels::update(geo::Vec2 const&paneSize) noexcept {
|
||||
glBindVertexArray(m_bufferSet.vao);
|
||||
setBufferObjects(paneSize);
|
||||
glutils::sendVbo(m_bufferSet);
|
||||
glutils::sendEbo(m_bufferSet);
|
||||
}
|
||||
|
||||
geo::Vec2 TileSheetPixels::pixelSize(const geo::Vec2 &paneSize) const noexcept {
|
||||
const auto [sw, sh] = paneSize;
|
||||
constexpr float ymod = 0.35f / 10.0f;
|
||||
@ -60,7 +64,13 @@ geo::Vec2 TileSheetPixels::pixelSize(const geo::Vec2 &paneSize) const noexcept {
|
||||
return {xmod * m_pixelSizeMod, ymod * m_pixelSizeMod};
|
||||
}
|
||||
|
||||
void TileSheetPixels::setPixelBufferObject(const geo::Vec2 &paneSize, unsigned vertexRow, float x, float y, Color16 color, float *vbo, GLuint *ebo) const noexcept {
|
||||
void TileSheetPixels::setPixelBufferObject(
|
||||
geo::Vec2 const&paneSize,
|
||||
unsigned vertexRow,
|
||||
float x, float y,
|
||||
Color16 color,
|
||||
float *vbo,
|
||||
GLuint *ebo) const noexcept {
|
||||
const auto [xmod, ymod] = pixelSize(paneSize);
|
||||
x *= xmod;
|
||||
y *= -ymod;
|
||||
@ -68,18 +78,18 @@ void TileSheetPixels::setPixelBufferObject(const geo::Vec2 &paneSize, unsigned v
|
||||
y += 1.0f - ymod;
|
||||
const auto r = redf(color), g = greenf(color), b = bluef(color);
|
||||
// don't worry, these memcpys gets optimized to something much more ideal
|
||||
const float vertices[VertexVboLength] = {
|
||||
const ox::Array<float, VertexVboLength> vertices = {
|
||||
x, y, r, g, b, // bottom left
|
||||
x + xmod, y, r, g, b, // bottom right
|
||||
x + xmod, y + ymod, r, g, b, // top right
|
||||
x, y + ymod, r, g, b, // top left
|
||||
};
|
||||
memcpy(vbo, vertices, sizeof(vertices));
|
||||
const GLuint elms[VertexEboLength] = {
|
||||
memcpy(vbo, vertices.data(), sizeof(vertices));
|
||||
const ox::Array<GLuint, VertexEboLength> elms = {
|
||||
vertexRow + 0, vertexRow + 1, vertexRow + 2,
|
||||
vertexRow + 2, vertexRow + 3, vertexRow + 0,
|
||||
};
|
||||
memcpy(ebo, elms, sizeof(elms));
|
||||
memcpy(ebo, elms.data(), sizeof(elms));
|
||||
}
|
||||
|
||||
void TileSheetPixels::setBufferObjects(const geo::Vec2 &paneSize) noexcept {
|
||||
|
@ -51,7 +51,9 @@ class TileSheetPixels {
|
||||
|
||||
void draw(bool update, const geo::Vec2 &scroll) noexcept;
|
||||
|
||||
void initBufferSet(const geo::Vec2 &paneSize) noexcept;
|
||||
void initBufferSet(geo::Vec2 const&paneSize) noexcept;
|
||||
|
||||
void update(geo::Vec2 const&paneSize) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
geo::Vec2 pixelSize(const geo::Vec2 &paneSize) const noexcept;
|
||||
|
@ -7,7 +7,7 @@
|
||||
namespace nostalgia::core {
|
||||
|
||||
ox::Error NostalgiaPaletteToPaletteConverter::convert(
|
||||
foundation::Context*,
|
||||
keel::Context*,
|
||||
NostalgiaPalette *src,
|
||||
Palette *dst) const noexcept {
|
||||
dst->colors = std::move(src->colors);
|
||||
@ -15,7 +15,7 @@ ox::Error NostalgiaPaletteToPaletteConverter::convert(
|
||||
}
|
||||
|
||||
ox::Error TileSheetV1ToTileSheetConverter::convert(
|
||||
foundation::Context*,
|
||||
keel::Context*,
|
||||
TileSheetV1 *src,
|
||||
TileSheet *dst) const noexcept {
|
||||
dst->bpp = src->bpp;
|
||||
@ -28,7 +28,7 @@ ox::Error TileSheetV1ToTileSheetConverter::convert(
|
||||
}
|
||||
|
||||
ox::Error TileSheetToCompactTileSheetConverter::convert(
|
||||
foundation::Context*,
|
||||
keel::Context*,
|
||||
TileSheet *src,
|
||||
CompactTileSheet *dst) const noexcept {
|
||||
dst->bpp = src->bpp;
|
||||
@ -55,7 +55,7 @@ void TileSheetV2ToTileSheetConverter::convertSubsheet(
|
||||
}
|
||||
|
||||
ox::Error TileSheetV2ToTileSheetConverter::convert(
|
||||
foundation::Context*,
|
||||
keel::Context*,
|
||||
TileSheetV2 *src,
|
||||
TileSheet *dst) const noexcept {
|
||||
dst->bpp = src->bpp;
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
#include <ox/std/def.hpp>
|
||||
|
||||
#include <nostalgia/foundation/typeconv.hpp>
|
||||
#include <keel/typeconv.hpp>
|
||||
|
||||
#include "context.hpp"
|
||||
#include "gfx.hpp"
|
||||
@ -15,25 +15,25 @@ namespace nostalgia::core {
|
||||
|
||||
// Type converters
|
||||
|
||||
class NostalgiaPaletteToPaletteConverter: public foundation::Converter<NostalgiaPalette, Palette> {
|
||||
ox::Error convert(foundation::Context*, NostalgiaPalette *src, Palette *dst) const noexcept final;
|
||||
class NostalgiaPaletteToPaletteConverter: public keel::Converter<NostalgiaPalette, Palette> {
|
||||
ox::Error convert(keel::Context*, NostalgiaPalette *src, Palette *dst) const noexcept final;
|
||||
};
|
||||
|
||||
class TileSheetV1ToTileSheetConverter: public foundation::Converter<TileSheetV1, TileSheet> {
|
||||
ox::Error convert(foundation::Context*, TileSheetV1 *src, TileSheet *dst) const noexcept final;
|
||||
class TileSheetV1ToTileSheetConverter: public keel::Converter<TileSheetV1, TileSheet> {
|
||||
ox::Error convert(keel::Context*, TileSheetV1 *src, TileSheet *dst) const noexcept final;
|
||||
};
|
||||
|
||||
class TileSheetToCompactTileSheetConverter: public foundation::Converter<TileSheet, CompactTileSheet> {
|
||||
ox::Error convert(foundation::Context*, TileSheet *src, CompactTileSheet *dst) const noexcept final;
|
||||
class TileSheetToCompactTileSheetConverter: public keel::Converter<TileSheet, CompactTileSheet> {
|
||||
ox::Error convert(keel::Context*, TileSheet *src, CompactTileSheet *dst) const noexcept final;
|
||||
};
|
||||
|
||||
class TileSheetV2ToTileSheetConverter: public foundation::Converter<TileSheetV2, TileSheet> {
|
||||
class TileSheetV2ToTileSheetConverter: public keel::Converter<TileSheetV2, TileSheet> {
|
||||
static void convertSubsheet(
|
||||
TileSheetV2::SubSheet *src,
|
||||
TileSheet::SubSheet *dst,
|
||||
SubSheetId *idIt) noexcept;
|
||||
|
||||
ox::Error convert(foundation::Context*, TileSheetV2 *src, TileSheet *dst) const noexcept final;
|
||||
ox::Error convert(keel::Context*, TileSheetV2 *src, TileSheet *dst) const noexcept final;
|
||||
|
||||
};
|
||||
|
||||
|
@ -30,12 +30,12 @@ void deleteVertexArray(GLuint v) noexcept {
|
||||
glDeleteVertexArrays(1, &v);
|
||||
}
|
||||
|
||||
void deleteProgram(GLuint v) noexcept {
|
||||
glDeleteProgram(v);
|
||||
void deleteProgram(GLuint p) noexcept {
|
||||
glDeleteProgram(p);
|
||||
}
|
||||
|
||||
void deleteShader(GLuint v) noexcept {
|
||||
glDeleteShader(v);
|
||||
void deleteShader(GLuint s) noexcept {
|
||||
glDeleteShader(s);
|
||||
}
|
||||
|
||||
template struct GLObject<deleteBuffer>;
|
||||
@ -46,7 +46,6 @@ template struct GLObject<deleteVertexArray>;
|
||||
template struct GLObject<deleteProgram>;
|
||||
template struct GLObject<deleteShader>;
|
||||
|
||||
[[nodiscard]]
|
||||
static ox::Result<GLShader> buildShader(GLuint shaderType, const GLchar *src, ox::CRStringView shaderName) noexcept {
|
||||
GLShader shader(glCreateShader(shaderType));
|
||||
glShaderSource(shader, 1, &src, nullptr);
|
||||
@ -54,7 +53,7 @@ static ox::Result<GLShader> buildShader(GLuint shaderType, const GLchar *src, ox
|
||||
GLint status;
|
||||
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
|
||||
if (status != GL_TRUE) {
|
||||
ox::Vector<char, 1000> errMsg(1000);
|
||||
ox::Vector<char> errMsg(ox::units::KB);
|
||||
glGetShaderInfoLog(shader, static_cast<GLsizei>(errMsg.size()), nullptr, errMsg.data());
|
||||
oxErrorf("shader compile error in {}: {}", shaderName, errMsg.data());
|
||||
return OxError(1, "shader compile error");
|
||||
@ -62,7 +61,7 @@ static ox::Result<GLShader> buildShader(GLuint shaderType, const GLchar *src, ox
|
||||
return shader;
|
||||
}
|
||||
|
||||
ox::Result<GLProgram> buildShaderProgram(const GLchar *vert, const GLchar *frag, [[maybe_unused]] const GLchar *geo) noexcept {
|
||||
ox::Result<GLProgram> buildShaderProgram(const GLchar *vert, const GLchar *frag, const GLchar *geo) noexcept {
|
||||
GLProgram prgm(glCreateProgram());
|
||||
oxRequire(vs, buildShader(GL_VERTEX_SHADER, vert, "vshad"));
|
||||
glAttachShader(prgm, vs);
|
||||
@ -116,19 +115,43 @@ FrameBuffer generateFrameBuffer(int width, int height) noexcept {
|
||||
oxAssert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE, "Frame Buffer is incomplete");
|
||||
// restore primary FB
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
return fb;
|
||||
}
|
||||
|
||||
void sendVbo(const BufferSet &bg) noexcept {
|
||||
const auto bufferSize = static_cast<GLsizeiptr>(sizeof(decltype(bg.vertices)::value_type) * bg.vertices.size());
|
||||
glBindBuffer(GL_ARRAY_BUFFER, bg.vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, bufferSize, bg.vertices.data(), GL_DYNAMIC_DRAW);
|
||||
void resizeInitFrameBuffer(FrameBuffer *fb, int width, int height) noexcept {
|
||||
if (!*fb) {
|
||||
*fb = generateFrameBuffer(width, height);
|
||||
return;
|
||||
}
|
||||
width = ox::max(1, width);
|
||||
height = ox::max(1, height);
|
||||
fb->width = width;
|
||||
fb->height = height;
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, *fb);
|
||||
// color texture
|
||||
glBindTexture(GL_TEXTURE_2D, fb->color);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
|
||||
// depth texture
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, fb->depth);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
|
||||
// restore primary FB
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
}
|
||||
|
||||
void sendEbo(const BufferSet &bg) noexcept {
|
||||
const auto bufferSize = static_cast<GLsizeiptr>(sizeof(decltype(bg.elements)::value_type) * bg.elements.size());
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bg.ebo);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, bufferSize, bg.elements.data(), GL_STATIC_DRAW);
|
||||
void sendVbo(const BufferSet &bs) noexcept {
|
||||
const auto bufferSize = static_cast<GLsizeiptr>(sizeof(decltype(bs.vertices)::value_type) * bs.vertices.size());
|
||||
glBindBuffer(GL_ARRAY_BUFFER, bs.vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, bufferSize, bs.vertices.data(), GL_DYNAMIC_DRAW);
|
||||
}
|
||||
|
||||
void sendEbo(const BufferSet &bs) noexcept {
|
||||
const auto bufferSize = static_cast<GLsizeiptr>(sizeof(decltype(bs.elements)::value_type) * bs.elements.size());
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bs.ebo);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, bufferSize, bs.elements.data(), GL_STATIC_DRAW);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -146,6 +146,11 @@ glutils::GLBuffer generateBuffer() noexcept;
|
||||
[[nodiscard]]
|
||||
FrameBuffer generateFrameBuffer(int width, int height) noexcept;
|
||||
|
||||
/**
|
||||
* Resizes a FrameBuffer, and creates if it does not already exist.
|
||||
*/
|
||||
void resizeInitFrameBuffer(FrameBuffer *fb, int width, int height) noexcept;
|
||||
|
||||
struct BufferSet {
|
||||
glutils::GLVertexArray vao;
|
||||
glutils::GLBuffer vbo;
|
||||
@ -155,8 +160,8 @@ struct BufferSet {
|
||||
ox::Vector<GLuint> elements;
|
||||
};
|
||||
|
||||
void sendVbo(const BufferSet &bg) noexcept;
|
||||
void sendVbo(const BufferSet &bs) noexcept;
|
||||
|
||||
void sendEbo(const BufferSet &bg) noexcept;
|
||||
void sendEbo(const BufferSet &bs) noexcept;
|
||||
|
||||
}
|
||||
|
@ -2,8 +2,9 @@
|
||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#include <keel/media.hpp>
|
||||
|
||||
#include <nostalgia/core/core.hpp>
|
||||
#include <nostalgia/foundation/media.hpp>
|
||||
#include <nostalgia/scene/scene.hpp>
|
||||
|
||||
using namespace nostalgia;
|
||||
@ -34,10 +35,10 @@ ox::Error run(ox::UniquePtr<ox::FileSystem> fs) noexcept {
|
||||
oxTraceInitHook();
|
||||
oxRequireM(ctx, core::init(std::move(fs)));
|
||||
constexpr ox::FileAddress SceneAddr("/Scenes/Chester.nscn");
|
||||
oxRequire(scn, foundation::readObj<scene::SceneStatic>(ctx.get(), SceneAddr));
|
||||
oxRequire(scn, keel::readObj<scene::SceneStatic>(ctx.get(), SceneAddr));
|
||||
core::setUpdateHandler(ctx.get(), updateHandler);
|
||||
core::setKeyEventHandler(ctx.get(), keyEventHandler);
|
||||
s_scene.emplace(scn.get());
|
||||
s_scene.emplace(*scn);
|
||||
oxReturnError(s_scene->setupDisplay(ctx.get()));
|
||||
return core::run(ctx.get());
|
||||
}
|
||||
|
@ -4,8 +4,9 @@
|
||||
|
||||
#include <ox/logconn/logconn.hpp>
|
||||
|
||||
#include <keel/media.hpp>
|
||||
|
||||
#include <nostalgia/core/core.hpp>
|
||||
#include <nostalgia/foundation/media.hpp>
|
||||
|
||||
#include <nostalgia/appmodules/appmodules.hpp>
|
||||
|
||||
@ -23,7 +24,7 @@ static ox::Error run(int argc, const char **argv) noexcept {
|
||||
return OxError(1);
|
||||
}
|
||||
const auto path = argv[1];
|
||||
oxRequireM(fs, nostalgia::foundation::loadRomFs(path));
|
||||
oxRequireM(fs, keel::loadRomFs(path));
|
||||
return run(std::move(fs));
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,6 @@ install(
|
||||
include/nostalgia/scene
|
||||
)
|
||||
|
||||
#if(NOSTALGIA_BUILD_STUDIO)
|
||||
# add_subdirectory(studio)
|
||||
#endif()
|
||||
if(NOSTALGIA_BUILD_STUDIO)
|
||||
add_subdirectory(studio)
|
||||
endif()
|
||||
|
@ -8,25 +8,25 @@
|
||||
|
||||
namespace nostalgia::scene {
|
||||
|
||||
Scene::Scene(const SceneStatic *sceneStatic) noexcept:
|
||||
Scene::Scene(const SceneStatic &sceneStatic) noexcept:
|
||||
m_sceneStatic(sceneStatic) {
|
||||
}
|
||||
|
||||
ox::Error Scene::setupDisplay(core::Context *ctx) noexcept {
|
||||
if (m_sceneStatic->palettes.empty()) {
|
||||
if (m_sceneStatic.palettes.empty()) {
|
||||
return OxError(1, "Scene has no palettes");
|
||||
}
|
||||
const auto &palette = m_sceneStatic->palettes[0];
|
||||
const auto &palette = m_sceneStatic.palettes[0];
|
||||
oxReturnError(core::loadBgTileSheet(
|
||||
ctx, 0, m_sceneStatic->tilesheet, palette));
|
||||
ctx, 0, m_sceneStatic.tilesheet, palette));
|
||||
// disable all backgrounds
|
||||
core::setBgStatus(ctx, 0);
|
||||
for (auto layerNo = 0u; const auto &layer : m_sceneStatic->tileMapIdx) {
|
||||
for (auto layerNo = 0u; const auto &layer : m_sceneStatic.tileMapIdx) {
|
||||
core::setBgStatus(ctx, layerNo, true);
|
||||
core::setBgCbb(ctx, layerNo, 0);
|
||||
auto x = 0;
|
||||
auto y = 0;
|
||||
auto width = m_sceneStatic->rows[layerNo];
|
||||
auto width = m_sceneStatic.rows[layerNo];
|
||||
for (const auto &tile : layer) {
|
||||
core::setTile(ctx, layerNo, x, y, tile);
|
||||
core::setTile(ctx, layerNo, x + 1, y, tile + 1);
|
||||
|
@ -10,10 +10,10 @@ namespace nostalgia::scene {
|
||||
|
||||
class Scene {
|
||||
private:
|
||||
const SceneStatic *m_sceneStatic = nullptr;
|
||||
const SceneStatic &m_sceneStatic;
|
||||
|
||||
public:
|
||||
explicit Scene(const SceneStatic *sceneStatic) noexcept;
|
||||
explicit Scene(const SceneStatic &sceneStatic) noexcept;
|
||||
|
||||
ox::Error setupDisplay(core::Context *ctx) noexcept;
|
||||
|
||||
|
@ -5,29 +5,44 @@
|
||||
#include <ox/model/model.hpp>
|
||||
|
||||
#include "scenestatic.hpp"
|
||||
#include "typeconv.hpp"
|
||||
|
||||
#include "scenemodule.hpp"
|
||||
|
||||
namespace nostalgia::scene {
|
||||
|
||||
SceneModule SceneModule::mod;
|
||||
class SceneModule: public keel::Module {
|
||||
private:
|
||||
SceneDocToSceneStaticConverter sceneDocToSceneStaticConverter;
|
||||
|
||||
ox::Vector<foundation::TypeDescGenerator> SceneModule::types() const noexcept {
|
||||
return {
|
||||
foundation::generateTypeDesc<SceneDoc>,
|
||||
foundation::generateTypeDesc<SceneStatic>,
|
||||
};
|
||||
}
|
||||
public:
|
||||
[[nodiscard]]
|
||||
ox::Vector<keel::TypeDescGenerator> types() const noexcept override {
|
||||
return {
|
||||
keel::generateTypeDesc<SceneDoc>,
|
||||
keel::generateTypeDesc<SceneStatic>,
|
||||
};
|
||||
}
|
||||
|
||||
ox::Vector<const foundation::BaseConverter*> SceneModule::converters() const noexcept {
|
||||
return {
|
||||
&sceneDocToSceneStaticConverter,
|
||||
};
|
||||
}
|
||||
[[nodiscard]]
|
||||
ox::Vector<const keel::BaseConverter*> converters() const noexcept override {
|
||||
return {
|
||||
&sceneDocToSceneStaticConverter,
|
||||
};
|
||||
}
|
||||
|
||||
ox::Vector<foundation::PackTransform> SceneModule::packTransforms() const noexcept {
|
||||
return {
|
||||
foundation::transformRule<SceneDoc, SceneStatic>,
|
||||
};
|
||||
[[nodiscard]]
|
||||
ox::Vector<keel::PackTransform> packTransforms() const noexcept override {
|
||||
return {
|
||||
keel::transformRule<SceneDoc, SceneStatic>,
|
||||
};
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
static SceneModule mod;
|
||||
const keel::Module *module() noexcept {
|
||||
return &mod;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -4,24 +4,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <nostalgia/foundation/module.hpp>
|
||||
|
||||
#include "typeconv.hpp"
|
||||
#include <keel/module.hpp>
|
||||
|
||||
namespace nostalgia::scene {
|
||||
|
||||
class SceneModule: public foundation::Module {
|
||||
private:
|
||||
SceneDocToSceneStaticConverter sceneDocToSceneStaticConverter;
|
||||
|
||||
public:
|
||||
static SceneModule mod;
|
||||
[[nodiscard]]
|
||||
ox::Vector<foundation::TypeDescGenerator> types() const noexcept override;
|
||||
[[nodiscard]]
|
||||
ox::Vector<const foundation::BaseConverter*> converters() const noexcept override;
|
||||
[[nodiscard]]
|
||||
ox::Vector<foundation::PackTransform> packTransforms() const noexcept override;
|
||||
};
|
||||
const keel::Module *module() noexcept;
|
||||
|
||||
}
|
||||
|
@ -14,6 +14,17 @@
|
||||
|
||||
namespace nostalgia::scene {
|
||||
|
||||
struct SpriteDoc {
|
||||
|
||||
constexpr static auto TypeName = "net.drinkingtea.nostalgia.scene.SpriteDoc";
|
||||
constexpr static auto TypeVersion = 1;
|
||||
constexpr static auto Preloadable = true;
|
||||
|
||||
ox::String tilesheetPath;
|
||||
ox::Vector<core::SubSheetId> subsheetId;
|
||||
|
||||
};
|
||||
|
||||
struct TileDoc {
|
||||
|
||||
constexpr static auto TypeName = "net.drinkingtea.nostalgia.scene.TileDoc";
|
||||
@ -23,6 +34,7 @@ struct TileDoc {
|
||||
core::SubSheetId subsheetId = -1;
|
||||
ox::String subsheetPath;
|
||||
uint8_t type = 0;
|
||||
ox::Array<uint8_t, 4> layerAttachments;
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr ox::Result<core::SubSheetId> getSubsheetId(const core::TileSheet &ts) const noexcept {
|
||||
@ -88,6 +100,38 @@ oxModelBegin(SceneDoc)
|
||||
oxModelField(tiles)
|
||||
oxModelEnd()
|
||||
|
||||
|
||||
constexpr void setTopEdge(uint8_t &layerAttachments, unsigned val) noexcept {
|
||||
layerAttachments = (layerAttachments & 0b11111100) | val;
|
||||
}
|
||||
constexpr void setBottomEdge(uint8_t &layerAttachments, unsigned val) noexcept {
|
||||
layerAttachments = (layerAttachments & 0b11110011) | (val << 2);
|
||||
}
|
||||
constexpr void setLeftEdge(uint8_t &layerAttachments, unsigned val) noexcept {
|
||||
layerAttachments = (layerAttachments & 0b11001111) | (val << 4);
|
||||
}
|
||||
constexpr void setRightEdge(uint8_t &layerAttachments, unsigned val) noexcept {
|
||||
layerAttachments = (layerAttachments & 0b00111111) | (val << 6);
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr unsigned topEdge(uint8_t layerAttachments) noexcept {
|
||||
return layerAttachments & 0b11;
|
||||
}
|
||||
[[nodiscard]]
|
||||
constexpr unsigned bottomEdge(uint8_t layerAttachments) noexcept {
|
||||
return (layerAttachments >> 2) & 0b11;
|
||||
}
|
||||
[[nodiscard]]
|
||||
constexpr unsigned leftEdge(uint8_t layerAttachments) noexcept {
|
||||
return (layerAttachments >> 4) & 0b11;
|
||||
}
|
||||
[[nodiscard]]
|
||||
constexpr unsigned rightEdge(uint8_t layerAttachments) noexcept {
|
||||
return (layerAttachments >> 6) & 0b11;
|
||||
}
|
||||
|
||||
|
||||
struct SceneStatic {
|
||||
|
||||
constexpr static auto TypeName = "net.drinkingtea.nostalgia.scene.SceneStatic";
|
||||
@ -97,9 +141,11 @@ struct SceneStatic {
|
||||
struct Tile {
|
||||
uint16_t &tileMapIdx;
|
||||
uint8_t &tileType;
|
||||
constexpr Tile(uint16_t *pTileMapIdx, uint8_t *pTileType) noexcept:
|
||||
tileMapIdx(*pTileMapIdx),
|
||||
tileType(*pTileType) {
|
||||
uint8_t &layerAttachments;
|
||||
constexpr Tile(uint16_t &pTileMapIdx, uint8_t &pTileType, uint8_t &pLayerAttachments) noexcept:
|
||||
tileMapIdx(pTileMapIdx),
|
||||
tileType(pTileType),
|
||||
layerAttachments(pLayerAttachments) {
|
||||
}
|
||||
};
|
||||
struct Layer {
|
||||
@ -107,19 +153,22 @@ struct SceneStatic {
|
||||
uint16_t &rows;
|
||||
ox::Vector<uint16_t> &tileMapIdx;
|
||||
ox::Vector<uint8_t> &tileType;
|
||||
ox::Vector<uint8_t> &layerAttachments;
|
||||
constexpr Layer(
|
||||
uint16_t *pColumns,
|
||||
uint16_t *pRows,
|
||||
ox::Vector<uint16_t> *pTileMapIdx,
|
||||
ox::Vector<uint8_t> *pTileType) noexcept:
|
||||
columns(*pColumns),
|
||||
rows(*pRows),
|
||||
tileMapIdx(*pTileMapIdx),
|
||||
tileType(*pTileType) {
|
||||
uint16_t &pColumns,
|
||||
uint16_t &pRows,
|
||||
ox::Vector<uint16_t> &pTileMapIdx,
|
||||
ox::Vector<uint8_t> &pTileType,
|
||||
ox::Vector<uint8_t> &pLayerAttachments) noexcept:
|
||||
columns(pColumns),
|
||||
rows(pRows),
|
||||
tileMapIdx(pTileMapIdx),
|
||||
tileType(pTileType),
|
||||
layerAttachments(pLayerAttachments) {
|
||||
}
|
||||
[[nodiscard]]
|
||||
constexpr Tile tile(std::size_t i) noexcept {
|
||||
return {&tileMapIdx[i], &tileType[i]};
|
||||
return {tileMapIdx[i], tileType[i], layerAttachments[i]};
|
||||
}
|
||||
constexpr auto setDimensions(geo::Size dim) noexcept {
|
||||
columns = dim.width;
|
||||
@ -127,6 +176,7 @@ struct SceneStatic {
|
||||
const auto tileCnt = static_cast<unsigned>(columns * rows);
|
||||
tileMapIdx.resize(tileCnt);
|
||||
tileType.resize(tileCnt);
|
||||
layerAttachments.resize(tileCnt);
|
||||
}
|
||||
};
|
||||
|
||||
@ -137,13 +187,21 @@ struct SceneStatic {
|
||||
ox::Vector<uint16_t> rows;
|
||||
ox::Vector<ox::Vector<uint16_t>> tileMapIdx;
|
||||
ox::Vector<ox::Vector<uint8_t>> tileType;
|
||||
ox::Vector<ox::Vector<uint8_t>> layerAttachments;
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr Layer layer(std::size_t i) noexcept {
|
||||
return {&columns[i], &rows[i], &tileMapIdx[i], &tileType[i]};
|
||||
return {
|
||||
columns[i],
|
||||
rows[i],
|
||||
tileMapIdx[i],
|
||||
tileType[i],
|
||||
layerAttachments[i],
|
||||
};
|
||||
}
|
||||
|
||||
constexpr auto setLayerCnt(std::size_t layerCnt) noexcept {
|
||||
this->layerAttachments.resize(layerCnt);
|
||||
this->columns.resize(layerCnt);
|
||||
this->rows.resize(layerCnt);
|
||||
this->tileMapIdx.resize(layerCnt);
|
||||
@ -157,8 +215,9 @@ oxModelBegin(SceneStatic)
|
||||
oxModelField(palettes)
|
||||
oxModelField(columns)
|
||||
oxModelField(rows)
|
||||
oxModelFieldRename(tile_map_idx, tileMapIdx)
|
||||
oxModelFieldRename(tile_type, tileType)
|
||||
oxModelField(tileMapIdx)
|
||||
oxModelField(tileType)
|
||||
oxModelField(layerAttachments)
|
||||
oxModelEnd()
|
||||
|
||||
}
|
||||
|
25
src/nostalgia/scene/studio/CMakeLists.txt
Normal file
25
src/nostalgia/scene/studio/CMakeLists.txt
Normal file
@ -0,0 +1,25 @@
|
||||
add_library(
|
||||
NostalgiaScene-Studio OBJECT
|
||||
module.cpp
|
||||
sceneeditor-imgui.cpp
|
||||
sceneeditor.cpp
|
||||
sceneeditorview.cpp
|
||||
)
|
||||
|
||||
if(NOT MSVC)
|
||||
target_compile_options(NostalgiaScene-Studio PRIVATE -Wsign-conversion)
|
||||
endif()
|
||||
|
||||
target_link_libraries(
|
||||
NostalgiaScene-Studio PUBLIC
|
||||
NostalgiaGlUtils
|
||||
NostalgiaStudio
|
||||
NostalgiaScene
|
||||
)
|
||||
|
||||
install(
|
||||
TARGETS
|
||||
NostalgiaScene-Studio
|
||||
LIBRARY DESTINATION
|
||||
${NOSTALGIA_DIST_MODULE}
|
||||
)
|
32
src/nostalgia/scene/studio/module.cpp
Normal file
32
src/nostalgia/scene/studio/module.cpp
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#include <ox/std/memory.hpp>
|
||||
|
||||
#include "sceneeditor-imgui.hpp"
|
||||
#include "module.hpp"
|
||||
|
||||
namespace nostalgia::scene {
|
||||
|
||||
ox::Vector<studio::EditorMaker> StudioModule::editors(core::Context *ctx) noexcept {
|
||||
return {
|
||||
{
|
||||
{"nscn"},
|
||||
[ctx](ox::CRStringView path) -> ox::Result<studio::BaseEditor*> {
|
||||
try {
|
||||
return ox::make<SceneEditorImGui>(ctx, path);
|
||||
} catch (const ox::Exception &ex) {
|
||||
return ex.toError();
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
ox::Vector<ox::UPtr<studio::ItemMaker>> StudioModule::itemMakers(core::Context*) noexcept {
|
||||
ox::Vector<ox::UPtr<studio::ItemMaker>> out;
|
||||
return out;
|
||||
}
|
||||
|
||||
}
|
17
src/nostalgia/scene/studio/module.hpp
Normal file
17
src/nostalgia/scene/studio/module.hpp
Normal file
@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <nostalgia/studio/studio.hpp>
|
||||
|
||||
namespace nostalgia::scene {
|
||||
|
||||
class StudioModule: public studio::Module {
|
||||
public:
|
||||
ox::Vector<studio::EditorMaker> editors(core::Context *ctx) noexcept override;
|
||||
ox::Vector<ox::UPtr<studio::ItemMaker>> itemMakers(core::Context*) noexcept override;
|
||||
};
|
||||
|
||||
}
|
59
src/nostalgia/scene/studio/sceneeditor-imgui.cpp
Normal file
59
src/nostalgia/scene/studio/sceneeditor-imgui.cpp
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#include <imgui.h>
|
||||
|
||||
#include <nostalgia/core/gfx.hpp>
|
||||
#include <keel/media.hpp>
|
||||
#include <ox/std/memory.hpp>
|
||||
|
||||
#include "sceneeditor-imgui.hpp"
|
||||
|
||||
namespace nostalgia::scene {
|
||||
|
||||
SceneEditorImGui::SceneEditorImGui(core::Context *ctx, ox::CRStringView path):
|
||||
m_editor(ctx, path),
|
||||
m_view(ctx, m_editor.scene()) {
|
||||
m_ctx = ctx;
|
||||
m_itemPath = path;
|
||||
const auto lastSlash = std::find(m_itemPath.rbegin(), m_itemPath.rend(), '/').offset();
|
||||
m_itemName = m_itemPath.substr(lastSlash + 1);
|
||||
setRequiresConstantRefresh(false);
|
||||
}
|
||||
|
||||
ox::CRString SceneEditorImGui::itemName() const noexcept {
|
||||
return m_itemPath;
|
||||
}
|
||||
|
||||
ox::CRString SceneEditorImGui::itemDisplayName() const noexcept {
|
||||
return m_itemName;
|
||||
}
|
||||
|
||||
void SceneEditorImGui::draw(core::Context*) noexcept {
|
||||
const auto paneSize = ImGui::GetContentRegionAvail();
|
||||
const geo::Size fbSize{
|
||||
static_cast<int>(paneSize.x),
|
||||
static_cast<int>(paneSize.y)};
|
||||
m_view.draw(fbSize.width, fbSize.height);
|
||||
auto &fb = m_view.framebuffer();
|
||||
const uintptr_t buffId = fb.color.id;
|
||||
ImGui::Image(
|
||||
reinterpret_cast<void*>(buffId),
|
||||
paneSize,
|
||||
ImVec2(0, 1),
|
||||
ImVec2(1, 0));
|
||||
}
|
||||
|
||||
void SceneEditorImGui::onActivated() noexcept {
|
||||
m_view.setupScene();
|
||||
}
|
||||
|
||||
ox::Error SceneEditorImGui::saveItem() noexcept {
|
||||
const auto sctx = applicationData<studio::StudioContext>(m_ctx);
|
||||
oxReturnError(sctx->project->writeObj(m_itemPath, &m_editor.scene()));
|
||||
oxReturnError(m_ctx->assetManager.setAsset(m_itemPath, m_editor.scene()));
|
||||
return {};
|
||||
}
|
||||
|
||||
}
|
43
src/nostalgia/scene/studio/sceneeditor-imgui.hpp
Normal file
43
src/nostalgia/scene/studio/sceneeditor-imgui.hpp
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <nostalgia/core/gfx.hpp>
|
||||
#include <nostalgia/studio/studio.hpp>
|
||||
|
||||
#include "sceneeditor.hpp"
|
||||
#include "sceneeditorview.hpp"
|
||||
|
||||
namespace nostalgia::scene {
|
||||
|
||||
class SceneEditorImGui: public studio::Editor {
|
||||
|
||||
private:
|
||||
core::Context *m_ctx = nullptr;
|
||||
ox::String m_itemName;
|
||||
ox::String m_itemPath;
|
||||
SceneEditor m_editor;
|
||||
SceneEditorView m_view;
|
||||
|
||||
public:
|
||||
SceneEditorImGui(core::Context *ctx, ox::CRStringView path);
|
||||
|
||||
/**
|
||||
* Returns the name of item being edited.
|
||||
*/
|
||||
ox::CRString itemName() const noexcept final;
|
||||
|
||||
ox::CRString itemDisplayName() const noexcept final;
|
||||
|
||||
void draw(core::Context*) noexcept final;
|
||||
|
||||
void onActivated() noexcept override;
|
||||
|
||||
protected:
|
||||
ox::Error saveItem() noexcept final;
|
||||
|
||||
};
|
||||
|
||||
}
|
15
src/nostalgia/scene/studio/sceneeditor.cpp
Normal file
15
src/nostalgia/scene/studio/sceneeditor.cpp
Normal file
@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#include "sceneeditor.hpp"
|
||||
|
||||
namespace nostalgia::scene {
|
||||
|
||||
SceneEditor::SceneEditor(core::Context *ctx, ox::CRStringView path) {
|
||||
m_ctx = ctx;
|
||||
oxRequireT(scn, keel::readObj<SceneStatic>(m_ctx, path));
|
||||
m_scene = *scn;
|
||||
}
|
||||
|
||||
}
|
33
src/nostalgia/scene/studio/sceneeditor.hpp
Normal file
33
src/nostalgia/scene/studio/sceneeditor.hpp
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <nostalgia/core/gfx.hpp>
|
||||
#include <nostalgia/studio/studio.hpp>
|
||||
#include <nostalgia/scene/scene.hpp>
|
||||
|
||||
namespace nostalgia::scene {
|
||||
|
||||
class SceneEditor {
|
||||
|
||||
private:
|
||||
core::Context *m_ctx = nullptr;
|
||||
ox::String m_itemName;
|
||||
ox::String m_itemPath;
|
||||
SceneStatic m_scene;
|
||||
|
||||
public:
|
||||
SceneEditor(core::Context *ctx, ox::CRStringView path);
|
||||
|
||||
const SceneStatic &scene() noexcept {
|
||||
return m_scene;
|
||||
}
|
||||
|
||||
protected:
|
||||
ox::Error saveItem() noexcept;
|
||||
|
||||
};
|
||||
|
||||
}
|
37
src/nostalgia/scene/studio/sceneeditorview.cpp
Normal file
37
src/nostalgia/scene/studio/sceneeditorview.cpp
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#include "sceneeditorview.hpp"
|
||||
|
||||
namespace nostalgia::scene {
|
||||
|
||||
SceneEditorView::SceneEditorView(core::Context *ctx, const SceneStatic &sceneStatic) noexcept:
|
||||
m_ctx(*ctx),
|
||||
m_sceneStatic(sceneStatic),
|
||||
m_scene(m_sceneStatic) {
|
||||
}
|
||||
|
||||
void SceneEditorView::setupScene() noexcept {
|
||||
oxIgnoreError(m_scene.setupDisplay(&m_ctx));
|
||||
}
|
||||
|
||||
void SceneEditorView::draw(int width, int height) noexcept {
|
||||
if (width != m_frameBuffer.width || height != m_frameBuffer.height) {
|
||||
glutils::resizeInitFrameBuffer(&m_frameBuffer, width, height);
|
||||
core::gl::setRenderSize(&m_ctx, width, height);
|
||||
oxIgnoreError(m_scene.setupDisplay(&m_ctx));
|
||||
}
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_frameBuffer);
|
||||
glViewport(0, 0, m_frameBuffer.width, m_frameBuffer.height);
|
||||
// draw begin
|
||||
core::gl::drawMainView(&m_ctx);
|
||||
// draw end
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
const glutils::FrameBuffer &SceneEditorView::framebuffer() const noexcept {
|
||||
return m_frameBuffer;
|
||||
}
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user