Compare commits
118 Commits
dd16577b50
...
d056323679
Author | SHA1 | Date | |
---|---|---|---|
d056323679 | |||
b10d9b6118 | |||
bd44fcf6ad | |||
a1de7fbd8a | |||
debeb83119 | |||
e2545a956b | |||
a60765b338 | |||
dc233286b4 | |||
5b929b8796 | |||
aea1aabcd7 | |||
3b8a9af97b | |||
d54853a8b5 | |||
d06412a6fe | |||
937e88ce7a | |||
9a5bdebbd7 | |||
a2361c3fd9 | |||
d6f0fe0cc8 | |||
e3b2c66d70 | |||
6dec1bf5ed | |||
af1f674bc0 | |||
6a1e2f7566 | |||
393259a010 | |||
b6b59e77f5 | |||
4a94672fdc | |||
d22c968561 | |||
79c85c2a33 | |||
3ac3b7b5e6 | |||
8c9ebbedae | |||
dbd98fe18b | |||
7418a7126a | |||
d5a1e11ec5 | |||
f4a93d8419 | |||
e923c73c91 | |||
4a9f035014 | |||
b5ee68c90b | |||
e906237d76 | |||
6bcf29b8f2 | |||
406388c042 | |||
371044d63d | |||
62c671e823 | |||
0ac494998f | |||
500c012713 | |||
1c4fb80702 | |||
a4fac4c1d3 | |||
115941a787 | |||
65a179e314 | |||
eed240eacc | |||
cc7c7ac9d7 | |||
9a80196fa6 | |||
8804819e17 | |||
ade6af8698 | |||
cd0958c691 | |||
40a3c28fbf | |||
def994f406 | |||
e808859e29 | |||
9e9f30fb18 | |||
facde6bdce | |||
1298051a1a | |||
f169c96e78 | |||
1547e8e550 | |||
795b1add64 | |||
db91ea6a63 | |||
7e19f45c69 | |||
57ba1caf90 | |||
a5bdad448f | |||
54fcbb1a33 | |||
195fd7a113 | |||
0d606643f5 | |||
402f54b3e3 | |||
ed5fc079ee | |||
140005799f | |||
7d9a1676e8 | |||
b61f81abf0 | |||
775efbddc8 | |||
1505d7ea37 | |||
26a2d340d6 | |||
ce514d586c | |||
5cbf789374 | |||
3f83a254d2 | |||
348193ae9e | |||
6b7c002a10 | |||
34081a0414 | |||
d23b69ce17 | |||
5717d67462 | |||
7666bcc2db | |||
8f5173e52a | |||
9ab3543b32 | |||
d16bbef282 | |||
a8db357360 | |||
566b724d36 | |||
b13eb0ef70 | |||
9855a0bcf0 | |||
611e2fa7cb | |||
95d9aee0cf | |||
3de03bf1fd | |||
742427584a | |||
91fd0d0786 | |||
53262c53c4 | |||
b212385b17 | |||
453e08497d | |||
72c130d8a9 | |||
9904399724 | |||
1a1c8ae6cc | |||
e9822bf124 | |||
644abd7f22 | |||
1e8d8c8b9e | |||
eccb8c4fb3 | |||
6b3974eb93 | |||
f6058f4e07 | |||
ecb09930db | |||
fc5e63a4d7 | |||
232a166833 | |||
95ba8eb138 | |||
a37df08c19 | |||
0fc7e7005c | |||
68a0dd9660 | |||
d635a954fa | |||
d0f19fd51d |
@ -4,10 +4,9 @@ Checks: '-*,
|
||||
cppcoreguidelines-interfaces-global-init,
|
||||
cppcoreguidelines-narrowing-conversions,
|
||||
cppcoreguidelines-pro-type-member-init,
|
||||
cppcoreguidelines-pro-type-static-cast-downcast,
|
||||
-cppcoreguidelines-pro-type-static-cast-downcast,
|
||||
cppcoreguidelines-slicing,
|
||||
google-default-arguments,
|
||||
google-explicit-constructor,
|
||||
google-runtime-operator,
|
||||
hicpp-exception-baseclass,
|
||||
hicpp-multiway-paths-covered,
|
||||
@ -53,6 +52,7 @@ readability-uniqueptr-delete-release,
|
||||
readability-use-anyofallof,
|
||||
cert-*,
|
||||
misc-*,
|
||||
-misc-include-cleaner
|
||||
-misc-use-anonymous-namespace,
|
||||
readability-duplicate-include,
|
||||
-misc-non-private-member-variables-in-classes,
|
||||
|
24
.gitlab-ci.yml
Normal file
24
.gitlab-ci.yml
Normal file
@ -0,0 +1,24 @@
|
||||
# This file is a template, and might need editing before it works on your project.
|
||||
# You can copy and paste this template into a new `.gitlab-ci.yml` file.
|
||||
# You should not add this template to an existing `.gitlab-ci.yml` file by using the `include:` keyword.
|
||||
#
|
||||
# To contribute improvements to CI/CD templates, please follow the Development guide at:
|
||||
# https://docs.gitlab.com/ee/development/cicd/templates.html
|
||||
# This specific template is located at:
|
||||
# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/C++.gitlab-ci.yml
|
||||
|
||||
# use the official gcc image, based on debian
|
||||
# can use versions as well, like gcc:5.2
|
||||
# see https://hub.docker.com/_/gcc/
|
||||
|
||||
image: gcc
|
||||
|
||||
build:
|
||||
stage: build
|
||||
variables:
|
||||
OX_NODEBUG: 1
|
||||
before_script:
|
||||
- apt update && apt -y install make cmake ninja-build pkg-config xorg-dev libgtk-3-dev python3 python3-mypy
|
||||
script:
|
||||
- make purge configure-release test install
|
||||
- make purge configure-asan test install
|
@ -65,7 +65,11 @@ if(NOT BUILDCORE_TARGET STREQUAL "gba")
|
||||
/usr/local/include
|
||||
)
|
||||
add_subdirectory(deps/glad)
|
||||
set(GLFW_BUILD_EXAMPLES OFF)
|
||||
set(GLFW_BUILD_TESTS OFF)
|
||||
set(GLFW_BUILD_DOCS OFF)
|
||||
add_subdirectory(deps/glfw)
|
||||
add_subdirectory(deps/glutils)
|
||||
add_subdirectory(deps/imgui)
|
||||
add_subdirectory(deps/lodepng)
|
||||
add_subdirectory(deps/nfde)
|
||||
|
12
Makefile
12
Makefile
@ -3,29 +3,29 @@ BUILDCORE_PATH=deps/buildcore
|
||||
include ${BUILDCORE_PATH}/base.mk
|
||||
|
||||
ifeq ($(BC_VAR_OS),darwin)
|
||||
NOSTALGIA_STUDIO=./build/${BC_VAR_CURRENT_BUILD}/bin/nostalgia-studio.app/Contents/MacOS/nostalgia-studio
|
||||
NOSTALGIA_STUDIO=./build/${BC_VAR_CURRENT_BUILD}/bin/${BC_VAR_PROJECT_NAME}-studio.app/Contents/MacOS/${BC_VAR_PROJECT_NAME}-studio
|
||||
MGBA=/Applications/mGBA.app/Contents/MacOS/mGBA
|
||||
else
|
||||
NOSTALGIA_STUDIO=./build/${BC_VAR_CURRENT_BUILD}/bin/nostalgia-studio
|
||||
NOSTALGIA_STUDIO=./build/${BC_VAR_CURRENT_BUILD}/bin/${BC_VAR_PROJECT_NAME}-studio
|
||||
MGBA=mgba-qt
|
||||
endif
|
||||
|
||||
.PHONY: pkg-gba
|
||||
pkg-gba: build
|
||||
${BC_CMD_ENVRUN} ${BC_PY3} ./scripts/pkg-gba.py sample_project
|
||||
${BC_CMD_ENVRUN} ${BC_PY3} ./scripts/pkg-gba.py sample_project ${BC_VAR_PROJECT_NAME}
|
||||
|
||||
.PHONY: run
|
||||
run: build
|
||||
./build/${BC_VAR_CURRENT_BUILD}/bin/nostalgia sample_project
|
||||
./build/${BC_VAR_CURRENT_BUILD}/bin/${BC_VAR_PROJECT_NAME} sample_project
|
||||
.PHONY: run-studio
|
||||
run-studio: build
|
||||
${NOSTALGIA_STUDIO}
|
||||
.PHONY: gba-run
|
||||
gba-run: pkg-gba
|
||||
${MGBA} nostalgia.gba
|
||||
${MGBA} ${BC_VAR_PROJECT_NAME}.gba
|
||||
.PHONY: debug
|
||||
debug: build
|
||||
${BC_CMD_HOST_DEBUGGER} ./build/${BC_VAR_CURRENT_BUILD}/bin/nostalgia sample_project
|
||||
${BC_CMD_HOST_DEBUGGER} ./build/${BC_VAR_CURRENT_BUILD}/bin/${BC_VAR_PROJECT_NAME} sample_project
|
||||
.PHONY: debug-studio
|
||||
debug-studio: build
|
||||
${BC_CMD_HOST_DEBUGGER} ${NOSTALGIA_STUDIO}
|
||||
|
@ -14,6 +14,7 @@ For Debian (and probably other Linux distros, but the package names will
|
||||
probably differ), install the following additional packages:
|
||||
* pkg-config
|
||||
* xorg-dev
|
||||
* libgtk-3-dev
|
||||
|
||||
## Build
|
||||
|
||||
|
2
deps/buildcore/base.mk
vendored
2
deps/buildcore/base.mk
vendored
@ -89,7 +89,7 @@ purge:
|
||||
${BC_CMD_RM_RF} compile_commands.json
|
||||
.PHONY: test
|
||||
test: build
|
||||
${BC_CMD_ENVRUN} mypy ${BC_VAR_SCRIPTS}
|
||||
${BC_CMD_ENVRUN} ${BC_CMD_PY3} -m mypy ${BC_VAR_SCRIPTS}
|
||||
${BC_CMD_CMAKE_BUILD} ${BC_VAR_BUILD_PATH} test
|
||||
.PHONY: test-verbose
|
||||
test-verbose: build
|
||||
|
10
deps/glutils/CMakeLists.txt
vendored
Normal file
10
deps/glutils/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
project(GlUtils CXX)
|
||||
|
||||
add_subdirectory(src)
|
||||
|
||||
install(
|
||||
DIRECTORY
|
||||
include/glutils
|
||||
DESTINATION
|
||||
include
|
||||
)
|
@ -9,14 +9,14 @@
|
||||
#include <glad/glad.h>
|
||||
|
||||
#include <ox/std/bounds.hpp>
|
||||
#include <ox/std/cstringview.hpp>
|
||||
#include <ox/std/error.hpp>
|
||||
#include <ox/std/size.hpp>
|
||||
#include <ox/std/string.hpp>
|
||||
#include <ox/std/vector.hpp>
|
||||
|
||||
namespace glutils {
|
||||
|
||||
constexpr ox::StringView GlslVersion = "#version 330";
|
||||
|
||||
struct Empty {
|
||||
virtual ~Empty() noexcept = default;
|
||||
};
|
||||
@ -151,9 +151,7 @@ class FrameBufferBind {
|
||||
void bind(const FrameBuffer &fb) noexcept;
|
||||
|
||||
|
||||
ox::Result<GLProgram> buildShaderProgram(const GLchar *vert, const GLchar *frag, const GLchar *geo = nullptr) noexcept;
|
||||
|
||||
ox::Result<GLProgram> buildShaderProgram(const ox::String &vert, const ox::String &frag, const ox::String &geo = "") noexcept;
|
||||
ox::Result<GLProgram> buildShaderProgram(ox::CStringView const&vert, ox::CStringView const&frag, ox::CStringView const&geo = "") noexcept;
|
||||
|
||||
glutils::GLVertexArray generateVertexArrayObject() noexcept;
|
||||
|
||||
@ -165,7 +163,9 @@ 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;
|
||||
void resizeInitFrameBuffer(FrameBuffer &fb, int width, int height) noexcept;
|
||||
|
||||
void resizeInitFrameBuffer(FrameBuffer &fb, ox::Size const&sz) noexcept;
|
||||
|
||||
struct BufferSet {
|
||||
glutils::GLVertexArray vao;
|
||||
@ -176,9 +176,9 @@ struct BufferSet {
|
||||
ox::Vector<GLuint> elements;
|
||||
};
|
||||
|
||||
void sendVbo(const BufferSet &bs) noexcept;
|
||||
|
||||
void sendEbo(const BufferSet &bs) noexcept;
|
||||
void sendVbo(BufferSet const&bs) noexcept;
|
||||
|
||||
void sendEbo(BufferSet const&bs) noexcept;
|
||||
|
||||
void clearScreen() noexcept;
|
||||
|
@ -3,23 +3,21 @@ add_library(
|
||||
glutils.cpp
|
||||
)
|
||||
|
||||
target_include_directories(
|
||||
GlUtils PUBLIC
|
||||
../include
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
GlUtils PUBLIC
|
||||
OxStd
|
||||
glad
|
||||
)
|
||||
|
||||
install(
|
||||
FILES
|
||||
glutils.hpp
|
||||
DESTINATION
|
||||
include/glutils
|
||||
)
|
||||
|
||||
install(
|
||||
TARGETS
|
||||
GlUtils
|
||||
DESTINATION
|
||||
LIBRARY DESTINATION lib
|
||||
ARCHIVE DESTINATION lib
|
||||
)
|
||||
)
|
@ -6,7 +6,7 @@
|
||||
#include <ox/std/bstring.hpp>
|
||||
#include <ox/std/trace.hpp>
|
||||
|
||||
#include "glutils.hpp"
|
||||
#include "glutils/glutils.hpp"
|
||||
|
||||
namespace glutils {
|
||||
|
||||
@ -88,27 +88,23 @@ static ox::Result<GLShader> buildShader(
|
||||
return shader;
|
||||
}
|
||||
|
||||
ox::Result<GLProgram> buildShaderProgram(const GLchar *vert, const GLchar *frag, const GLchar *geo) noexcept {
|
||||
ox::Result<GLProgram> buildShaderProgram(
|
||||
ox::CStringView const&vert,
|
||||
ox::CStringView const&frag,
|
||||
ox::CStringView const&geo) noexcept {
|
||||
GLProgram prgm(glCreateProgram());
|
||||
oxRequire(vs, buildShader(GL_VERTEX_SHADER, vert, "vshad"));
|
||||
oxRequire(vs, buildShader(GL_VERTEX_SHADER, vert.c_str(), "vshad"));
|
||||
glAttachShader(prgm, vs);
|
||||
if (geo && ox_strlen(geo) != 0) {
|
||||
oxRequire(gs, buildShader(GL_GEOMETRY_SHADER, geo, "gshad"));
|
||||
if (geo.c_str() && geo.bytes() != 0) {
|
||||
oxRequire(gs, buildShader(GL_GEOMETRY_SHADER, geo.c_str(), "gshad"));
|
||||
glAttachShader(prgm, gs);
|
||||
}
|
||||
oxRequire(fs, buildShader(GL_FRAGMENT_SHADER, frag, "fshad"));
|
||||
oxRequire(fs, buildShader(GL_FRAGMENT_SHADER, frag.c_str(), "fshad"));
|
||||
glAttachShader(prgm, fs);
|
||||
glLinkProgram(prgm);
|
||||
return prgm;
|
||||
}
|
||||
|
||||
ox::Result<GLProgram> buildShaderProgram(
|
||||
const ox::String &vert,
|
||||
const ox::String &frag,
|
||||
const ox::String &geo) noexcept {
|
||||
return buildShaderProgram(vert.c_str(), frag.c_str(), geo.c_str());
|
||||
}
|
||||
|
||||
GLVertexArray generateVertexArrayObject() noexcept {
|
||||
GLVertexArray vao;
|
||||
glGenVertexArrays(1, &vao.id);
|
||||
@ -133,8 +129,9 @@ FrameBuffer generateFrameBuffer(int width, int height) noexcept {
|
||||
glGenTextures(1, &fb.color.id);
|
||||
glBindTexture(GL_TEXTURE_2D, fb.color);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb.color, 0);
|
||||
// depth texture
|
||||
glGenRenderbuffers(1, &fb.depth.id);
|
||||
@ -150,21 +147,23 @@ FrameBuffer generateFrameBuffer(int width, int height) noexcept {
|
||||
return fb;
|
||||
}
|
||||
|
||||
void resizeInitFrameBuffer(FrameBuffer *fb, int width, int height) noexcept {
|
||||
if (!*fb) {
|
||||
*fb = generateFrameBuffer(width, height);
|
||||
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);
|
||||
fb.width = width;
|
||||
fb.height = height;
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fb);
|
||||
// color texture
|
||||
glBindTexture(GL_TEXTURE_2D, fb->color);
|
||||
glBindTexture(GL_TEXTURE_2D, fb.color);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
// depth texture
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, fb->depth);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, fb.depth);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
|
||||
// restore primary FB
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
@ -172,13 +171,17 @@ void resizeInitFrameBuffer(FrameBuffer *fb, int width, int height) noexcept {
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
}
|
||||
|
||||
void sendVbo(const BufferSet &bs) noexcept {
|
||||
void resizeInitFrameBuffer(FrameBuffer &fb, ox::Size const&sz) noexcept {
|
||||
resizeInitFrameBuffer(fb, sz.width, sz.height);
|
||||
}
|
||||
|
||||
void sendVbo(BufferSet const&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 {
|
||||
void sendEbo(BufferSet const&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);
|
2
deps/nfde/CMakeLists.txt
vendored
2
deps/nfde/CMakeLists.txt
vendored
@ -1,4 +1,4 @@
|
||||
cmake_minimum_required(VERSION 3.2)
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
project(nativefiledialog-extended)
|
||||
|
||||
if(NOT MSVC)
|
||||
|
18
deps/ox/src/ox/clargs/clargs.cpp
vendored
18
deps/ox/src/ox/clargs/clargs.cpp
vendored
@ -13,7 +13,7 @@ namespace ox {
|
||||
|
||||
ClArgs::ClArgs(int argc, const char **args) noexcept {
|
||||
for (auto i = 0u; i < static_cast<unsigned>(argc); ++i) {
|
||||
String arg = args[i];
|
||||
auto arg = String(args[i]);
|
||||
if (arg[0] == '-') {
|
||||
while (arg[0] == '-' && arg.len()) {
|
||||
arg = arg.substr(1);
|
||||
@ -21,7 +21,7 @@ ClArgs::ClArgs(int argc, const char **args) noexcept {
|
||||
m_bools[arg] = true;
|
||||
// parse additional arguments
|
||||
if (i < static_cast<unsigned>(argc) && args[i + 1]) {
|
||||
String val = args[i + 1];
|
||||
auto val = String(args[i + 1]);
|
||||
if (val.len() && val[i] != '-') {
|
||||
if (val == "false") {
|
||||
m_bools[arg] = false;
|
||||
@ -37,32 +37,32 @@ ClArgs::ClArgs(int argc, const char **args) noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
bool ClArgs::getBool(ox::CRString arg, bool defaultValue) const noexcept {
|
||||
bool ClArgs::getBool(ox::CRStringView arg, bool defaultValue) const noexcept {
|
||||
auto [value, err] = m_ints.at(arg);
|
||||
return !err ? *value : defaultValue;
|
||||
}
|
||||
|
||||
String ClArgs::getString(ox::CRString arg, const char *defaultValue) const noexcept {
|
||||
String ClArgs::getString(ox::CRStringView arg, const char *defaultValue) const noexcept {
|
||||
auto [value, err] = m_strings.at(arg);
|
||||
return !err ? *value : defaultValue;
|
||||
return !err ? ox::String(std::move(*value)) : ox::String(defaultValue);
|
||||
}
|
||||
|
||||
int ClArgs::getInt(ox::CRString arg, int defaultValue) const noexcept {
|
||||
int ClArgs::getInt(ox::CRStringView arg, int defaultValue) const noexcept {
|
||||
auto [value, err] = m_ints.at(arg);
|
||||
return !err ? *value : defaultValue;
|
||||
}
|
||||
|
||||
Result<bool> ClArgs::getBool(ox::CRString arg) const noexcept {
|
||||
Result<bool> ClArgs::getBool(ox::CRStringView arg) const noexcept {
|
||||
oxRequire(out, m_bools.at(arg));
|
||||
return *out;
|
||||
}
|
||||
|
||||
Result<String> ClArgs::getString(ox::CRString argName) const noexcept {
|
||||
Result<String> ClArgs::getString(ox::CRStringView argName) const noexcept {
|
||||
oxRequire(out, m_strings.at(argName));
|
||||
return *out;
|
||||
}
|
||||
|
||||
Result<int> ClArgs::getInt(ox::CRString arg) const noexcept {
|
||||
Result<int> ClArgs::getInt(ox::CRStringView arg) const noexcept {
|
||||
oxRequire(out, m_ints.at(arg));
|
||||
return *out;
|
||||
}
|
||||
|
12
deps/ox/src/ox/clargs/clargs.hpp
vendored
12
deps/ox/src/ox/clargs/clargs.hpp
vendored
@ -23,21 +23,21 @@ class ClArgs {
|
||||
ClArgs(int argc, const char **args) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
bool getBool(ox::CRString arg, bool defaultValue) const noexcept;
|
||||
bool getBool(ox::CRStringView arg, bool defaultValue) const noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
String getString(ox::CRString argName, const char *defaultValue) const noexcept;
|
||||
String getString(ox::CRStringView argName, const char *defaultValue) const noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
int getInt(ox::CRString arg, int defaultValue) const noexcept;
|
||||
int getInt(ox::CRStringView arg, int defaultValue) const noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
Result<bool> getBool(ox::CRString arg) const noexcept;
|
||||
Result<bool> getBool(ox::CRStringView arg) const noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
Result<String> getString(ox::CRString argName) const noexcept;
|
||||
Result<String> getString(ox::CRStringView argName) const noexcept;
|
||||
|
||||
Result<int> getInt(ox::CRString arg) const noexcept;
|
||||
Result<int> getInt(ox::CRStringView arg) const noexcept;
|
||||
|
||||
};
|
||||
|
||||
|
20
deps/ox/src/ox/claw/CMakeLists.txt
vendored
20
deps/ox/src/ox/claw/CMakeLists.txt
vendored
@ -16,16 +16,16 @@ target_link_libraries(
|
||||
$<$<BOOL:${OX_USE_STDLIB}>:OxOrganicClaw>
|
||||
)
|
||||
|
||||
if(OX_USE_STDLIB)
|
||||
add_executable(
|
||||
readclaw
|
||||
readclaw.cpp
|
||||
)
|
||||
target_link_libraries(
|
||||
readclaw PUBLIC
|
||||
OxClaw
|
||||
)
|
||||
endif()
|
||||
#if(OX_USE_STDLIB)
|
||||
# add_executable(
|
||||
# readclaw
|
||||
# readclaw.cpp
|
||||
# )
|
||||
# target_link_libraries(
|
||||
# readclaw PUBLIC
|
||||
# OxClaw
|
||||
# )
|
||||
#endif()
|
||||
|
||||
install(TARGETS OxClaw
|
||||
LIBRARY DESTINATION lib
|
||||
|
28
deps/ox/src/ox/claw/test/tests.cpp
vendored
28
deps/ox/src/ox/claw/test/tests.cpp
vendored
@ -8,11 +8,7 @@
|
||||
|
||||
#undef NDEBUG
|
||||
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <ox/claw/format.hpp>
|
||||
#include <ox/claw/read.hpp>
|
||||
#include <ox/claw/write.hpp>
|
||||
@ -107,12 +103,12 @@ constexpr ox::Error model(T *io, ox::CommonPtrWith<TestStruct> auto *obj) {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
static std::map<std::string_view, ox::Error(*)()> tests = {
|
||||
static std::map<ox::StringView, ox::Error(*)()> tests = {
|
||||
{
|
||||
{
|
||||
"ClawHeaderReader",
|
||||
[] {
|
||||
ox::String hdr = "O1;com.drinkingtea.ox.claw.test.Header;2;";
|
||||
constexpr auto hdr = ox::StringLiteral("O1;com.drinkingtea.ox.claw.test.Header;2;");
|
||||
auto [ch, err] = ox::readClawHeader(hdr.c_str(), hdr.len() + 1);
|
||||
oxAssert(err, "Error parsing header");
|
||||
oxAssert(ch.fmt == ox::ClawFormat::Organic, "Format wrong");
|
||||
@ -124,7 +120,7 @@ static std::map<std::string_view, ox::Error(*)()> tests = {
|
||||
{
|
||||
"ClawHeaderReader2",
|
||||
[] {
|
||||
ox::String hdr = "M2;com.drinkingtea.ox.claw.test.Header2;3;";
|
||||
constexpr auto hdr = ox::StringLiteral("M2;com.drinkingtea.ox.claw.test.Header2;3;");
|
||||
auto [ch, err] = ox::readClawHeader(hdr.c_str(), hdr.len() + 1);
|
||||
oxAssert(err, "Error parsing header");
|
||||
oxAssert(ch.fmt == ox::ClawFormat::Metal, "Format wrong");
|
||||
@ -192,14 +188,14 @@ static std::map<std::string_view, ox::Error(*)()> tests = {
|
||||
};
|
||||
|
||||
int main(int argc, const char **args) {
|
||||
int retval = -1;
|
||||
if (argc > 0) {
|
||||
auto testName = args[1];
|
||||
if (tests.find(testName) != tests.end()) {
|
||||
retval = static_cast<int>(tests[testName]());
|
||||
} else {
|
||||
retval = 1;
|
||||
}
|
||||
if (argc < 2) {
|
||||
oxError("Must specify test to run");
|
||||
}
|
||||
return retval;
|
||||
auto const testName = args[1];
|
||||
auto const func = tests.find(testName);
|
||||
if (func != tests.end()) {
|
||||
oxAssert(func->second(), "Test returned Error");
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
16
deps/ox/src/ox/event/test/tests.cpp
vendored
16
deps/ox/src/ox/event/test/tests.cpp
vendored
@ -21,7 +21,7 @@ struct TestStruct: public ox::SignalHandler {
|
||||
}
|
||||
};
|
||||
|
||||
std::map<std::string, std::function<ox::Error()>> tests = {
|
||||
std::map<ox::StringView, std::function<ox::Error()>> tests = {
|
||||
{
|
||||
"test1",
|
||||
[] {
|
||||
@ -39,12 +39,14 @@ std::map<std::string, std::function<ox::Error()>> tests = {
|
||||
};
|
||||
|
||||
int main(int argc, const char **args) {
|
||||
if (argc > 1) {
|
||||
auto testName = args[1];
|
||||
if (tests.find(testName) != tests.end()) {
|
||||
oxAssert(tests[testName](), "Test returned Error");
|
||||
return 0;
|
||||
}
|
||||
if (argc < 2) {
|
||||
oxError("Must specify test to run");
|
||||
}
|
||||
auto const testName = args[1];
|
||||
auto const func = tests.find(testName);
|
||||
if (func != tests.end()) {
|
||||
oxAssert(func->second(), "Test returned Error");
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
@ -36,13 +36,6 @@ FileAddress::FileAddress(ox::CRStringView path) noexcept {
|
||||
m_type = FileAddressType::Path;
|
||||
}
|
||||
|
||||
FileAddress::FileAddress(char *path) noexcept {
|
||||
auto pathSize = ox_strlen(path) + 1;
|
||||
m_data.path = new char[pathSize];
|
||||
memcpy(m_data.path, path, pathSize);
|
||||
m_type = FileAddressType::Path;
|
||||
}
|
||||
|
||||
FileAddress &FileAddress::operator=(const FileAddress &other) noexcept {
|
||||
if (this == &other) {
|
||||
return *this;
|
||||
|
93
deps/ox/src/ox/fs/filesystem/filelocation.hpp
vendored
93
deps/ox/src/ox/fs/filesystem/filelocation.hpp
vendored
@ -25,7 +25,7 @@ enum class FileAddressType: int8_t {
|
||||
class FileAddress {
|
||||
|
||||
template<typename T>
|
||||
friend constexpr Error model(T*, CommonPtrWith<FileAddress> auto*) noexcept;
|
||||
friend constexpr Error model(T *h, CommonPtrWith<FileAddress> auto *fa) noexcept;
|
||||
|
||||
public:
|
||||
static constexpr auto TypeName = "net.drinkingtea.ox.FileAddress";
|
||||
@ -59,13 +59,7 @@ class FileAddress {
|
||||
|
||||
explicit FileAddress(CRStringView path) noexcept;
|
||||
|
||||
template<std::size_t SmallStrSz>
|
||||
explicit FileAddress(const ox::BasicString<SmallStrSz> &path) noexcept: FileAddress(StringView(path)) {
|
||||
}
|
||||
|
||||
explicit FileAddress(char *path) noexcept;
|
||||
|
||||
explicit constexpr FileAddress(const char *path) noexcept;
|
||||
constexpr FileAddress(ox::StringLiteral path) noexcept;
|
||||
|
||||
constexpr ~FileAddress() noexcept;
|
||||
|
||||
@ -86,7 +80,6 @@ class FileAddress {
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr Result<uint64_t> getInode() const noexcept {
|
||||
switch (m_type) {
|
||||
case FileAddressType::Inode:
|
||||
@ -124,8 +117,8 @@ class FileAddress {
|
||||
|
||||
};
|
||||
|
||||
constexpr FileAddress::FileAddress(const char *path) noexcept {
|
||||
m_data.constPath = path;
|
||||
constexpr FileAddress::FileAddress(ox::StringLiteral path) noexcept {
|
||||
m_data.constPath = path.c_str();
|
||||
m_type = FileAddressType::ConstPath;
|
||||
}
|
||||
|
||||
@ -133,45 +126,6 @@ constexpr FileAddress::~FileAddress() noexcept {
|
||||
cleanup();
|
||||
}
|
||||
|
||||
template<>
|
||||
constexpr const char *getModelTypeName<FileAddress::Data>() noexcept {
|
||||
return FileAddress::Data::TypeName;
|
||||
}
|
||||
|
||||
template<>
|
||||
constexpr const char *getModelTypeName<FileAddress>() noexcept {
|
||||
return FileAddress::TypeName;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Error model(T *io, CommonPtrWith<FileAddress::Data> auto *obj) noexcept {
|
||||
oxReturnError(io->template setTypeInfo<FileAddress::Data>());
|
||||
oxReturnError(io->fieldCString("path", &obj->path));
|
||||
oxReturnError(io->fieldCString("constPath", &obj->path));
|
||||
oxReturnError(io->field("inode", &obj->inode));
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Error model(T *io, CommonPtrWith<FileAddress> auto *fa) noexcept {
|
||||
oxReturnError(io->template setTypeInfo<FileAddress>());
|
||||
if constexpr(T::opType() == OpType::Reflect) {
|
||||
int8_t type = 0;
|
||||
oxReturnError(io->field("type", &type));
|
||||
oxReturnError(io->field("data", UnionView(&fa->m_data, 0)));
|
||||
} else if constexpr(T::opType() == OpType::Read) {
|
||||
auto type = static_cast<int8_t>(fa->m_type);
|
||||
oxReturnError(io->field("type", &type));
|
||||
fa->m_type = static_cast<FileAddressType>(type);
|
||||
oxReturnError(io->field("data", UnionView(&fa->m_data, static_cast<int>(fa->m_type))));
|
||||
} else if constexpr(T::opType() == OpType::Write) {
|
||||
auto type = static_cast<int8_t>(fa->m_type);
|
||||
oxReturnError(io->field("type", &type));
|
||||
oxReturnError(io->field("data", UnionView(&fa->m_data, static_cast<int>(fa->m_type))));
|
||||
}
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
constexpr void FileAddress::cleanup() noexcept {
|
||||
if (m_type == FileAddressType::Path) {
|
||||
safeDeleteArray(m_data.path);
|
||||
@ -184,4 +138,43 @@ constexpr void FileAddress::clear() noexcept {
|
||||
m_type = FileAddressType::None;
|
||||
}
|
||||
|
||||
template<>
|
||||
constexpr const char *getModelTypeName<FileAddress::Data>() noexcept {
|
||||
return FileAddress::Data::TypeName;
|
||||
}
|
||||
|
||||
template<>
|
||||
constexpr const char *getModelTypeName<FileAddress>() noexcept {
|
||||
return FileAddress::TypeName;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Error model(T *h, CommonPtrWith<FileAddress::Data> auto *obj) noexcept {
|
||||
oxReturnError(h->template setTypeInfo<FileAddress::Data>());
|
||||
oxReturnError(h->fieldCString("path", &obj->path));
|
||||
oxReturnError(h->fieldCString("constPath", &obj->path));
|
||||
oxReturnError(h->field("inode", &obj->inode));
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Error model(T *h, CommonPtrWith<FileAddress> auto *fa) noexcept {
|
||||
oxReturnError(h->template setTypeInfo<FileAddress>());
|
||||
if constexpr(T::opType() == OpType::Reflect) {
|
||||
int8_t type = 0;
|
||||
oxReturnError(h->field("type", &type));
|
||||
oxReturnError(h->field("data", UnionView(&fa->m_data, 0)));
|
||||
} else if constexpr(T::opType() == OpType::Read) {
|
||||
auto type = static_cast<int8_t>(fa->m_type);
|
||||
oxReturnError(h->field("type", &type));
|
||||
fa->m_type = static_cast<FileAddressType>(type);
|
||||
oxReturnError(h->field("data", UnionView(&fa->m_data, static_cast<int>(fa->m_type))));
|
||||
} else if constexpr(T::opType() == OpType::Write) {
|
||||
auto type = static_cast<int8_t>(fa->m_type);
|
||||
oxReturnError(h->field("type", &type));
|
||||
oxReturnError(h->field("data", UnionView(&fa->m_data, static_cast<int>(fa->m_type))));
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ PassThroughFS::PassThroughFS(CRStringView dirPath) {
|
||||
PassThroughFS::~PassThroughFS() noexcept = default;
|
||||
|
||||
String PassThroughFS::basePath() const noexcept {
|
||||
return m_path.string().c_str();
|
||||
return ox::String(m_path.string().c_str());
|
||||
}
|
||||
|
||||
Error PassThroughFS::mkdir(CRStringView path, bool recursive) noexcept {
|
||||
|
65
deps/ox/src/ox/fs/test/tests.cpp
vendored
65
deps/ox/src/ox/fs/test/tests.cpp
vendored
@ -26,11 +26,11 @@ struct OX_PACKED NodeType: public ox::ptrarith::Item<T> {
|
||||
}
|
||||
};
|
||||
|
||||
const std::map<std::string_view, std::function<ox::Error(std::string_view)>> tests = {
|
||||
const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests = {
|
||||
{
|
||||
{
|
||||
"PtrArith::setSize",
|
||||
[](std::string_view) {
|
||||
[](ox::StringView) {
|
||||
using BuffPtr_t = uint32_t;
|
||||
ox::Vector<char> buff(5 * ox::units::MB);
|
||||
auto buffer = new (buff.data()) ox::ptrarith::NodeBuffer<BuffPtr_t, NodeType<BuffPtr_t>>(buff.size());
|
||||
@ -57,8 +57,8 @@ const std::map<std::string_view, std::function<ox::Error(std::string_view)>> tes
|
||||
},
|
||||
{
|
||||
"PathIterator::next1",
|
||||
[](std::string_view) {
|
||||
ox::String path = "/usr/share/charset.gbag";
|
||||
[](ox::StringView) {
|
||||
auto const path = ox::String("/usr/share/charset.gbag");
|
||||
ox::PathIterator it(path.c_str(), path.len());
|
||||
auto buff = static_cast<char*>(ox_alloca(path.len() + 1));
|
||||
oxAssert(it.next(buff, path.len()) == 0 && ox_strcmp(buff, "usr") == 0, "PathIterator shows wrong next");
|
||||
@ -69,8 +69,8 @@ const std::map<std::string_view, std::function<ox::Error(std::string_view)>> tes
|
||||
},
|
||||
{
|
||||
"PathIterator::next2",
|
||||
[](std::string_view) {
|
||||
ox::String path = "/usr/share/";
|
||||
[](ox::StringView) {
|
||||
auto const path = ox::String("/usr/share/");
|
||||
ox::PathIterator it(path.c_str(), path.len());
|
||||
auto buff = static_cast<char*>(ox_alloca(path.len() + 1));
|
||||
oxAssert(it.next(buff, path.len()) == 0 && ox_strcmp(buff, "usr") == 0, "PathIterator shows wrong next");
|
||||
@ -80,8 +80,8 @@ const std::map<std::string_view, std::function<ox::Error(std::string_view)>> tes
|
||||
},
|
||||
{
|
||||
"PathIterator::next3",
|
||||
[](std::string_view) {
|
||||
ox::String path = "/";
|
||||
[](ox::StringView) {
|
||||
auto const path = ox::String("/");
|
||||
ox::PathIterator it(path.c_str(), path.len());
|
||||
auto buff = static_cast<char*>(ox_alloca(path.len() + 1));
|
||||
oxAssert(it.next(buff, path.len()) == 0 && ox_strcmp(buff, "\0") == 0, "PathIterator shows wrong next");
|
||||
@ -90,8 +90,8 @@ const std::map<std::string_view, std::function<ox::Error(std::string_view)>> tes
|
||||
},
|
||||
{
|
||||
"PathIterator::next4",
|
||||
[](std::string_view) {
|
||||
ox::String path = "usr/share/charset.gbag";
|
||||
[](ox::StringView) {
|
||||
auto const path = ox::String("usr/share/charset.gbag");
|
||||
ox::PathIterator it(path.c_str(), path.len());
|
||||
auto buff = static_cast<char*>(ox_alloca(path.len() + 1));
|
||||
oxAssert(it.next(buff, path.len()) == 0 && ox_strcmp(buff, "usr") == 0, "PathIterator shows wrong next");
|
||||
@ -102,8 +102,8 @@ const std::map<std::string_view, std::function<ox::Error(std::string_view)>> tes
|
||||
},
|
||||
{
|
||||
"PathIterator::next5",
|
||||
[](std::string_view) {
|
||||
ox::String path = "usr/share/";
|
||||
[](ox::StringView) {
|
||||
auto const path = ox::String("usr/share/");
|
||||
ox::PathIterator it(path.c_str(), path.len());
|
||||
auto buff = static_cast<char*>(ox_alloca(path.len() + 1));
|
||||
oxAssert(it.next(buff, path.len()) == 0 && ox_strcmp(buff, "usr") == 0, "PathIterator shows wrong next");
|
||||
@ -113,8 +113,8 @@ const std::map<std::string_view, std::function<ox::Error(std::string_view)>> tes
|
||||
},
|
||||
{
|
||||
"PathIterator::dirPath",
|
||||
[] (std::string_view) {
|
||||
ox::String path = "/usr/share/charset.gbag";
|
||||
[] (ox::StringView) {
|
||||
auto const path = ox::String("/usr/share/charset.gbag");
|
||||
ox::PathIterator it(path.c_str(), path.len());
|
||||
auto buff = static_cast<char*>(ox_alloca(path.len() + 1));
|
||||
oxAssert(it.dirPath(buff, path.len()) == 0 && ox_strcmp(buff, "/usr/share/") == 0, "PathIterator shows incorrect dir path");
|
||||
@ -123,8 +123,8 @@ const std::map<std::string_view, std::function<ox::Error(std::string_view)>> tes
|
||||
},
|
||||
{
|
||||
"PathIterator::fileName",
|
||||
[](std::string_view) {
|
||||
ox::String path = "/usr/share/charset.gbag";
|
||||
[](ox::StringView) {
|
||||
auto const path = ox::String("/usr/share/charset.gbag");
|
||||
ox::PathIterator it(path.c_str(), path.len());
|
||||
auto buff = static_cast<char*>(ox_alloca(path.len() + 1));
|
||||
oxAssert(it.fileName(buff, path.len()) == 0 && ox_strcmp(buff, "charset.gbag") == 0, "PathIterator shows incorrect file name");
|
||||
@ -133,7 +133,7 @@ const std::map<std::string_view, std::function<ox::Error(std::string_view)>> tes
|
||||
},
|
||||
{
|
||||
"PathIterator::hasNext",
|
||||
[](std::string_view) {
|
||||
[](ox::StringView) {
|
||||
const auto path = "/file1";
|
||||
ox::PathIterator it(path, ox_strlen(path));
|
||||
oxAssert(it.hasNext(), "PathIterator shows incorrect hasNext");
|
||||
@ -143,7 +143,7 @@ const std::map<std::string_view, std::function<ox::Error(std::string_view)>> tes
|
||||
},
|
||||
{
|
||||
"Ptr::subPtr",
|
||||
[](std::string_view) {
|
||||
[](ox::StringView) {
|
||||
constexpr auto buffLen = 5000;
|
||||
ox::ptrarith::Ptr<uint8_t, uint32_t> p(ox_alloca(buffLen), buffLen, 500, 500);
|
||||
oxAssert(p.valid(), "Ptr::subPtr: Ptr p is invalid.");
|
||||
@ -155,7 +155,7 @@ const std::map<std::string_view, std::function<ox::Error(std::string_view)>> tes
|
||||
},
|
||||
{
|
||||
"NodeBuffer::insert",
|
||||
[](std::string_view) {
|
||||
[](ox::StringView) {
|
||||
constexpr auto buffLen = 5000;
|
||||
auto list = new (ox_alloca(buffLen)) ox::ptrarith::NodeBuffer<uint32_t, ox::FileStoreItem<uint32_t>>(buffLen);
|
||||
oxAssert(list->malloc(50).value.valid(), "NodeBuffer::insert: malloc 1 failed");
|
||||
@ -168,7 +168,7 @@ const std::map<std::string_view, std::function<ox::Error(std::string_view)>> tes
|
||||
},
|
||||
{
|
||||
"FileStore::readWrite",
|
||||
[](std::string_view) {
|
||||
[](ox::StringView) {
|
||||
constexpr auto buffLen = 5000;
|
||||
constexpr auto str1 = "Hello, World!";
|
||||
constexpr auto str1Len = ox_strlen(str1) + 1;
|
||||
@ -189,7 +189,7 @@ const std::map<std::string_view, std::function<ox::Error(std::string_view)>> tes
|
||||
},
|
||||
{
|
||||
"Directory",
|
||||
[](std::string_view) {
|
||||
[](ox::StringView) {
|
||||
ox::Vector<uint8_t> fsBuff(5000);
|
||||
oxAssert(ox::FileStore32::format(fsBuff.data(), fsBuff.size()), "FS format failed");
|
||||
ox::FileStore32 fileStore(fsBuff.data(), fsBuff.size());
|
||||
@ -216,7 +216,7 @@ const std::map<std::string_view, std::function<ox::Error(std::string_view)>> tes
|
||||
},
|
||||
{
|
||||
"FileSystem",
|
||||
[](std::string_view) {
|
||||
[](ox::StringView) {
|
||||
ox::Vector<uint8_t> fsBuff(5000);
|
||||
oxTrace("ox.fs.test.FileSystem") << "format";
|
||||
oxAssert(ox::FileSystem32::format(fsBuff.data(), fsBuff.size()), "FileSystem format failed");
|
||||
@ -237,16 +237,15 @@ const std::map<std::string_view, std::function<ox::Error(std::string_view)>> tes
|
||||
};
|
||||
|
||||
int main(int argc, const char **args) {
|
||||
int retval = -1;
|
||||
if (argc > 1) {
|
||||
std::string_view testName = args[1];
|
||||
std::string_view testArg;
|
||||
if (args[2]) {
|
||||
testArg = args[2];
|
||||
}
|
||||
if (tests.find(testName) != tests.end()) {
|
||||
retval = static_cast<int>(tests.at(testName)(testArg));
|
||||
}
|
||||
if (argc < 3) {
|
||||
oxError("Must specify test to run and test argument");
|
||||
}
|
||||
return retval;
|
||||
ox::StringView const testName = args[1];
|
||||
ox::StringView const testArg = args[2] ? args[2] : nullptr;
|
||||
auto const func = tests.find(testName);
|
||||
if (func != tests.end()) {
|
||||
oxAssert(func->second(testArg), "Test returned Error");
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
2
deps/ox/src/ox/fs/tool.cpp
vendored
2
deps/ox/src/ox/fs/tool.cpp
vendored
@ -67,7 +67,7 @@ static ox::Error run(int argc, const char **argv) noexcept {
|
||||
return OxError(1);
|
||||
}
|
||||
const auto fsPath = argv[1];
|
||||
ox::String subCmd = argv[2];
|
||||
ox::String subCmd(argv[2]);
|
||||
oxRequire(fs, loadFs(fsPath));
|
||||
if (subCmd == "ls") {
|
||||
return runLs(fs.get(), argc - 2, argv + 2);
|
||||
|
2
deps/ox/src/ox/mc/read.hpp
vendored
2
deps/ox/src/ox/mc/read.hpp
vendored
@ -276,8 +276,8 @@ constexpr Error MetalClawReaderTemplate<Reader>::field(const char *name, T *val)
|
||||
val->resize(len);
|
||||
return field(name, val->data(), val->size());
|
||||
}
|
||||
val->resize(0);
|
||||
}
|
||||
val->resize(0);
|
||||
++m_field;
|
||||
return {};
|
||||
} else if constexpr(isArray_v<T>) {
|
||||
|
19
deps/ox/src/ox/mc/test/tests.cpp
vendored
19
deps/ox/src/ox/mc/test/tests.cpp
vendored
@ -45,7 +45,7 @@ struct TestStruct {
|
||||
int32_t Int8 = 0;
|
||||
int unionIdx = 1;
|
||||
TestUnion Union;
|
||||
ox::String String = "";
|
||||
ox::String String;
|
||||
ox::BString<32> BString = "";
|
||||
uint32_t List[4] = {0, 0, 0, 0};
|
||||
ox::Vector<uint32_t> Vector = {1, 2, 3, 4, 5};
|
||||
@ -105,7 +105,7 @@ constexpr ox::Error model(T *io, ox::CommonPtrWith<TestStruct> auto *obj) noexce
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
std::map<ox::String, ox::Error(*)()> tests = {
|
||||
std::map<ox::StringView, ox::Error(*)()> tests = {
|
||||
{
|
||||
{
|
||||
"MetalClawWriter",
|
||||
@ -460,11 +460,14 @@ std::map<ox::String, ox::Error(*)()> tests = {
|
||||
};
|
||||
|
||||
int main(int argc, const char **args) {
|
||||
if (argc > 0) {
|
||||
auto testName = args[1];
|
||||
if (tests.find(testName) != tests.end()) {
|
||||
oxAssert(tests[testName](), "Test failed...");
|
||||
}
|
||||
if (argc < 2) {
|
||||
oxError("Must specify test to run");
|
||||
}
|
||||
return 0;
|
||||
auto const testName = args[1];
|
||||
auto const func = tests.find(testName);
|
||||
if (func != tests.end()) {
|
||||
oxAssert(func->second(), "Test returned Error");
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
89
deps/ox/src/ox/mc/write.hpp
vendored
89
deps/ox/src/ox/mc/write.hpp
vendored
@ -43,39 +43,30 @@ class MetalClawWriter {
|
||||
|
||||
constexpr ~MetalClawWriter() noexcept = default;
|
||||
|
||||
constexpr Error field(const char*, CommonPtrWith<int8_t> auto *val) noexcept;
|
||||
constexpr Error field(const char*, CommonPtrWith<int16_t> auto *val) noexcept;
|
||||
constexpr Error field(const char*, CommonPtrWith<int32_t> auto *val) noexcept;
|
||||
constexpr Error field(const char*, CommonPtrWith<int64_t> auto *val) noexcept;
|
||||
constexpr Error field(const char*, const int8_t *val) noexcept;
|
||||
constexpr Error field(const char*, const int16_t *val) noexcept;
|
||||
constexpr Error field(const char*, const int32_t *val) noexcept;
|
||||
constexpr Error field(const char*, const int64_t *val) noexcept;
|
||||
|
||||
constexpr Error field(const char*, CommonPtrWith<uint8_t> auto *val) noexcept;
|
||||
constexpr Error field(const char*, CommonPtrWith<uint16_t> auto *val) noexcept;
|
||||
constexpr Error field(const char*, CommonPtrWith<uint32_t> auto *val) noexcept;
|
||||
constexpr Error field(const char*, CommonPtrWith<uint64_t> auto *val) noexcept;
|
||||
constexpr Error field(const char*, const uint8_t *val) noexcept;
|
||||
constexpr Error field(const char*, const uint16_t *val) noexcept;
|
||||
constexpr Error field(const char*, const uint32_t *val) noexcept;
|
||||
constexpr Error field(const char*, const uint64_t *val) noexcept;
|
||||
|
||||
constexpr Error field(const char*, CommonPtrWith<bool> auto *val) noexcept;
|
||||
constexpr Error field(const char*, const bool *val) noexcept;
|
||||
|
||||
template<typename T>
|
||||
constexpr Error field(const char*, T *val, std::size_t len) noexcept;
|
||||
constexpr Error field(const char*, const T *val, std::size_t len) noexcept;
|
||||
|
||||
template<typename T>
|
||||
constexpr Error field(const char *name, const HashMap<String, T> *val) noexcept;
|
||||
|
||||
template<typename T>
|
||||
constexpr Error field(const char*, HashMap<String, T> *val) noexcept;
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr Error field(const char*, const BasicString<SmallStringSize> *val) noexcept;
|
||||
|
||||
template<std::size_t L>
|
||||
constexpr Error field(const char*, const BString<L> *val) noexcept;
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr Error field(const char*, BasicString<SmallStringSize> *val) noexcept;
|
||||
|
||||
template<std::size_t L>
|
||||
constexpr Error field(const char*, BString<L> *val) noexcept;
|
||||
|
||||
constexpr Error fieldCString(const char *name, const char *const*val, std::size_t buffLen) noexcept;
|
||||
|
||||
constexpr Error fieldCString(const char *name, const char **val) noexcept;
|
||||
@ -84,20 +75,8 @@ class MetalClawWriter {
|
||||
|
||||
constexpr Error fieldCString(const char *name, const char *val, std::size_t len) noexcept;
|
||||
|
||||
constexpr Error fieldCString(const char *name, char **val, std::size_t buffLen) noexcept {
|
||||
return fieldCString(name, const_cast<const char**>(val), buffLen);
|
||||
}
|
||||
|
||||
constexpr Error fieldCString(const char *name, char **val) noexcept {
|
||||
return fieldCString(name, const_cast<const char**>(val));
|
||||
}
|
||||
|
||||
constexpr Error fieldCString(const char *name, char *val, std::size_t buffLen) noexcept {
|
||||
return fieldCString(name, const_cast<const char*>(val), buffLen);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Error field(const char*, T *val) noexcept;
|
||||
constexpr Error field(const char*, const T *val) noexcept;
|
||||
|
||||
template<typename U, bool force = false>
|
||||
constexpr Error field(const char*, UnionView<U, force> val) noexcept;
|
||||
@ -159,47 +138,47 @@ constexpr MetalClawWriter<Writer>::MetalClawWriter(Writer &writer, int unionIdx)
|
||||
}
|
||||
|
||||
template<Writer_c Writer>
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char*, CommonPtrWith<int8_t> auto *val) noexcept {
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char*, const int8_t *val) noexcept {
|
||||
return appendInteger(*val);
|
||||
}
|
||||
|
||||
template<Writer_c Writer>
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char*, CommonPtrWith<int16_t> auto *val) noexcept {
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char*, const int16_t *val) noexcept {
|
||||
return appendInteger(*val);
|
||||
}
|
||||
|
||||
template<Writer_c Writer>
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char*, CommonPtrWith<int32_t> auto *val) noexcept {
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char*, const int32_t *val) noexcept {
|
||||
return appendInteger(*val);
|
||||
}
|
||||
|
||||
template<Writer_c Writer>
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char*, CommonPtrWith<int64_t> auto *val) noexcept {
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char*, const int64_t *val) noexcept {
|
||||
return appendInteger(*val);
|
||||
}
|
||||
|
||||
template<Writer_c Writer>
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char*, CommonPtrWith<uint8_t> auto *val) noexcept {
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char*, const uint8_t *val) noexcept {
|
||||
return appendInteger(*val);
|
||||
}
|
||||
|
||||
template<Writer_c Writer>
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char*, CommonPtrWith<uint16_t> auto *val) noexcept {
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char*, const uint16_t *val) noexcept {
|
||||
return appendInteger(*val);
|
||||
}
|
||||
|
||||
template<Writer_c Writer>
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char*, CommonPtrWith<uint32_t> auto *val) noexcept {
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char*, const uint32_t *val) noexcept {
|
||||
return appendInteger(*val);
|
||||
}
|
||||
|
||||
template<Writer_c Writer>
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char*, CommonPtrWith<uint64_t> auto *val) noexcept {
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char*, const uint64_t *val) noexcept {
|
||||
return appendInteger(*val);
|
||||
}
|
||||
|
||||
template<Writer_c Writer>
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char*, CommonPtrWith<bool> auto *val) noexcept {
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char*, const bool *val) noexcept {
|
||||
if (m_unionIdx == -1 || m_unionIdx == m_field) {
|
||||
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), *val));
|
||||
}
|
||||
@ -230,18 +209,6 @@ constexpr Error MetalClawWriter<Writer>::field(const char *name, const BString<L
|
||||
return fieldCString(name, val->data(), val->cap());
|
||||
}
|
||||
|
||||
template<Writer_c Writer>
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char *name, BasicString<SmallStringSize> *val) noexcept {
|
||||
return field(name, const_cast<const BasicString<SmallStringSize>*>(val));
|
||||
}
|
||||
|
||||
template<Writer_c Writer>
|
||||
template<std::size_t L>
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char *name, BString<L> *val) noexcept {
|
||||
return fieldCString(name, val->data(), val->cap());
|
||||
}
|
||||
|
||||
template<Writer_c Writer>
|
||||
constexpr Error MetalClawWriter<Writer>::fieldCString(const char*, const char *const*val, std::size_t) noexcept {
|
||||
bool fieldSet = false;
|
||||
@ -287,7 +254,7 @@ constexpr Error MetalClawWriter<Writer>::fieldCString(const char*, const char *v
|
||||
|
||||
template<Writer_c Writer>
|
||||
template<typename T>
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char*, T *val) noexcept {
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char*, const T *val) noexcept {
|
||||
if constexpr(isVector_v<T> || isArray_v<T>) {
|
||||
return field(nullptr, val->data(), val->size());
|
||||
} else {
|
||||
@ -323,7 +290,7 @@ constexpr Error MetalClawWriter<Writer>::field(const char*, UnionView<U, force>
|
||||
|
||||
template<Writer_c Writer>
|
||||
template<typename T>
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char*, T *val, std::size_t len) noexcept {
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char*, const T *val, std::size_t len) noexcept {
|
||||
bool fieldSet = false;
|
||||
if (len && (m_unionIdx == -1 || m_unionIdx == m_field)) {
|
||||
// write the length
|
||||
@ -361,7 +328,7 @@ constexpr Error MetalClawWriter<Writer>::field(const char*, const HashMap<String
|
||||
oxReturnError(handler.setTypeInfo("Map", 0, {}, len * 2));
|
||||
// this loop body needs to be in a lambda because of the potential alloca call
|
||||
constexpr auto loopBody = [](auto &handler, auto const&key, auto const&val) -> ox::Error {
|
||||
const auto keyLen = ox_strlen(key);
|
||||
const auto keyLen = key.len();
|
||||
auto wkey = ox_malloca(keyLen + 1, char, 0);
|
||||
memcpy(wkey.get(), key.c_str(), keyLen + 1);
|
||||
oxReturnError(handler.fieldCString("", wkey.get(), keyLen));
|
||||
@ -381,12 +348,6 @@ constexpr Error MetalClawWriter<Writer>::field(const char*, const HashMap<String
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<Writer_c Writer>
|
||||
template<typename T>
|
||||
constexpr Error MetalClawWriter<Writer>::field(const char *name, HashMap<String, T> *val) noexcept {
|
||||
return field(name, const_cast<const HashMap<String, T>*>(val));
|
||||
}
|
||||
|
||||
template<Writer_c Writer>
|
||||
template<typename T>
|
||||
constexpr ox::Error MetalClawWriter<Writer>::setTypeInfo(
|
||||
@ -421,7 +382,7 @@ Result<Buffer> writeMC(Writer_c auto &writer, const auto &val) noexcept {
|
||||
return {};
|
||||
}
|
||||
|
||||
Result<Buffer> writeMC(const auto &val, std::size_t buffReserveSz = 2 * units::KB) noexcept {
|
||||
Result<Buffer> writeMC(auto const&val, std::size_t buffReserveSz = 2 * units::KB) noexcept {
|
||||
Buffer buff(buffReserveSz);
|
||||
BufferWriter bw(&buff, 0);
|
||||
oxReturnError(writeMC(bw, val));
|
||||
@ -429,7 +390,7 @@ Result<Buffer> writeMC(const auto &val, std::size_t buffReserveSz = 2 * units::K
|
||||
return buff;
|
||||
}
|
||||
|
||||
Error writeMC(char *buff, std::size_t buffLen, const auto &val, std::size_t *sizeOut = nullptr) noexcept {
|
||||
Error writeMC(char *buff, std::size_t buffLen, auto const&val, std::size_t *sizeOut = nullptr) noexcept {
|
||||
CharBuffWriter bw(buff, buffLen);
|
||||
oxReturnError(writeMC(bw, val));
|
||||
if (sizeOut) {
|
||||
|
4
deps/ox/src/ox/model/descwrite.hpp
vendored
4
deps/ox/src/ox/model/descwrite.hpp
vendored
@ -209,7 +209,7 @@ constexpr Error TypeDescWriter::field(CRStringView name, UnionView<T, force> val
|
||||
if (m_type) {
|
||||
const auto t = type(val);
|
||||
oxAssert(t != nullptr, "field(const char *name, T val): Type not found or generated");
|
||||
m_type->fieldList.emplace_back(t, String(name), 0, SubscriptStack{}, t->typeName);
|
||||
m_type->fieldList.emplace_back(t, String(name), 0, SubscriptStack{}, ox::String(t->typeName));
|
||||
return OxError(0);
|
||||
}
|
||||
return OxError(1);
|
||||
@ -238,7 +238,7 @@ template<typename ...Args>
|
||||
constexpr Error TypeDescWriter::fieldCString(CRStringView name, Args&&...) noexcept {
|
||||
constexpr auto s = "";
|
||||
const auto t = type(s);
|
||||
m_type->fieldList.emplace_back(t, String(name), 0, SubscriptStack{}, t->typeName);
|
||||
m_type->fieldList.emplace_back(t, String(name), 0, SubscriptStack{}, ox::String(t->typeName));
|
||||
return {};
|
||||
}
|
||||
|
||||
|
19
deps/ox/src/ox/model/modelvalue.hpp
vendored
19
deps/ox/src/ox/model/modelvalue.hpp
vendored
@ -144,8 +144,6 @@ class ModelValue {
|
||||
|
||||
constexpr ModelValue(const ModelValue &other) noexcept;
|
||||
|
||||
constexpr ModelValue(ModelValue &other) noexcept;
|
||||
|
||||
constexpr ModelValue(ModelValue &&other) noexcept;
|
||||
|
||||
template<typename T>
|
||||
@ -350,7 +348,7 @@ class ModelObject {
|
||||
|
||||
constexpr ModelObject(const ModelObject &other) noexcept {
|
||||
for (const auto &f : other.m_fieldsOrder) {
|
||||
auto &field = m_fieldsOrder.emplace_back(new Field{f->name, f->value});
|
||||
auto &field = m_fieldsOrder.emplace_back(new Field{ox::String(f->name), f->value});
|
||||
m_fields[field->name] = &field->value;
|
||||
}
|
||||
m_type = other.m_type;
|
||||
@ -427,7 +425,7 @@ class ModelObject {
|
||||
return *this;
|
||||
}
|
||||
for (const auto &f : other.m_fieldsOrder) {
|
||||
auto &field = m_fieldsOrder.emplace_back(new Field{f->name, f->value});
|
||||
auto &field = m_fieldsOrder.emplace_back(new Field{ox::String(f->name), f->value});
|
||||
m_fields[field->name] = &field->value;
|
||||
}
|
||||
m_type = other.m_type;
|
||||
@ -450,7 +448,7 @@ class ModelObject {
|
||||
f = val;
|
||||
}
|
||||
|
||||
constexpr Result<const ModelValue*> get(const String &k) const noexcept {
|
||||
constexpr Result<const ModelValue*> get(StringView const&k) const noexcept {
|
||||
if (m_fields.contains(k)) {
|
||||
return *m_fields.at(k).value;
|
||||
}
|
||||
@ -464,7 +462,7 @@ class ModelObject {
|
||||
return {};
|
||||
}
|
||||
|
||||
constexpr auto &operator[](const String &k) noexcept {
|
||||
constexpr auto &operator[](StringView const&k) noexcept {
|
||||
auto [v, err] = m_fields.at(k);
|
||||
if (err) [[unlikely]] {
|
||||
oxPanic(err, ox::sfmt("field {} does not exist in type {}", k, buildTypeId(*m_type)).c_str());
|
||||
@ -528,7 +526,7 @@ class ModelUnion {
|
||||
public:
|
||||
constexpr ModelUnion(const ModelUnion &other) noexcept {
|
||||
for (auto i = 0; const auto &f : other.m_fieldsOrder) {
|
||||
auto &field = m_fieldsOrder.emplace_back(new Field{i, f->name, f->value});
|
||||
auto &field = m_fieldsOrder.emplace_back(new Field{i, ox::String(f->name), f->value});
|
||||
m_fields[field->name] = field.get();
|
||||
++i;
|
||||
}
|
||||
@ -553,7 +551,7 @@ class ModelUnion {
|
||||
return UniquePtr<ModelUnion>(new ModelUnion(other));
|
||||
}
|
||||
|
||||
constexpr auto &operator[](const String &k) noexcept {
|
||||
constexpr auto &operator[](StringView const&k) noexcept {
|
||||
const auto [v, err] = m_fields.at(k);
|
||||
if (err) [[unlikely]] {
|
||||
oxPanic(err, ox::sfmt("field {} does not exist in type {}", k, buildTypeId(*m_type)).c_str());
|
||||
@ -588,7 +586,7 @@ class ModelUnion {
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr Result<const ModelValue*> get(const String &k) const noexcept {
|
||||
constexpr Result<const ModelValue*> get(StringView const&k) const noexcept {
|
||||
oxRequire(t, m_fields.at(k));
|
||||
return &(*t)->value;
|
||||
}
|
||||
@ -814,9 +812,6 @@ constexpr ModelValue::ModelValue(const ModelValue &other) noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
constexpr ModelValue::ModelValue(ModelValue &other) noexcept: ModelValue(const_cast<const ModelValue&>(other)) {
|
||||
}
|
||||
|
||||
constexpr ModelValue::ModelValue(ModelValue &&other) noexcept {
|
||||
m_type = other.m_type;
|
||||
switch (m_type) {
|
||||
|
19
deps/ox/src/ox/model/test/tests.cpp
vendored
19
deps/ox/src/ox/model/test/tests.cpp
vendored
@ -32,7 +32,7 @@ constexpr auto getModelTypeVersion(TestType2*) noexcept {
|
||||
return 2;
|
||||
}
|
||||
|
||||
std::map<ox::String, ox::Error(*)()> tests = {
|
||||
std::map<ox::StringView, ox::Error(*)()> tests = {
|
||||
{
|
||||
{
|
||||
"ModelValue",
|
||||
@ -47,6 +47,7 @@ std::map<ox::String, ox::Error(*)()> tests = {
|
||||
return ox::Error{};
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"getModelTypeName",
|
||||
[] {
|
||||
@ -55,6 +56,7 @@ std::map<ox::String, ox::Error(*)()> tests = {
|
||||
return ox::Error{};
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"getModelTypeVersion",
|
||||
[] {
|
||||
@ -67,11 +69,14 @@ std::map<ox::String, ox::Error(*)()> tests = {
|
||||
};
|
||||
|
||||
int main(int argc, const char **args) {
|
||||
if (argc > 0) {
|
||||
auto testName = args[1];
|
||||
if (tests.find(testName) != tests.end()) {
|
||||
oxAssert(tests[testName](), "Test failed...");
|
||||
}
|
||||
if (argc < 2) {
|
||||
oxError("Must specify test to run");
|
||||
}
|
||||
return 0;
|
||||
auto const testName = args[1];
|
||||
auto const func = tests.find(testName);
|
||||
if (func != tests.end()) {
|
||||
oxAssert(func->second(), "Test returned Error");
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
112
deps/ox/src/ox/oc/test/tests.cpp
vendored
112
deps/ox/src/ox/oc/test/tests.cpp
vendored
@ -53,7 +53,7 @@ struct TestStruct {
|
||||
int32_t Int8 = 0;
|
||||
int unionIdx = 1;
|
||||
TestUnion Union;
|
||||
ox::String String = "";
|
||||
ox::String String{""};
|
||||
uint32_t List[4] = {0, 0, 0, 0};
|
||||
ox::HashMap<ox::String, int> Map;
|
||||
TestStructNest EmptyStruct;
|
||||
@ -124,7 +124,7 @@ constexpr TestStruct &TestStruct::operator=(TestStruct &&other) noexcept {
|
||||
return *this;
|
||||
}
|
||||
|
||||
const std::map<std::string_view, ox::Error(*)()> tests = {
|
||||
const std::map<ox::StringView, ox::Error(*)()> tests = {
|
||||
{
|
||||
{
|
||||
"OrganicClawWriter",
|
||||
@ -189,53 +189,53 @@ const std::map<std::string_view, ox::Error(*)()> tests = {
|
||||
},
|
||||
|
||||
{
|
||||
"OrganicClawModelValue",
|
||||
[] {
|
||||
ox::Buffer dataBuff;
|
||||
TestStruct testIn;
|
||||
testIn.Bool = true;
|
||||
testIn.Int = 42;
|
||||
testIn.String = "Test String 1";
|
||||
testIn.List[0] = 1;
|
||||
testIn.List[1] = 2;
|
||||
testIn.List[2] = 3;
|
||||
testIn.List[3] = 4;
|
||||
testIn.Struct.Bool = false;
|
||||
testIn.Struct.Int = 300;
|
||||
testIn.Struct.String = "Test String 2";
|
||||
testIn.unionIdx = 1;
|
||||
testIn.Union.Int = 93;
|
||||
oxAssert(ox::writeOC(testIn).moveTo(&dataBuff), "Data generation failed");
|
||||
ox::TypeStore typeStore;
|
||||
auto type = ox::buildTypeDef(&typeStore, &testIn);
|
||||
oxAssert(type.error, "Descriptor write failed");
|
||||
ox::ModelObject testOut;
|
||||
oxReturnError(testOut.setType(type.value));
|
||||
oxAssert(ox::readOC(dataBuff.data(), dataBuff.size(), &testOut), "Data read failed");
|
||||
oxAssert(testOut.get("Int").unwrap()->get<int>() == testIn.Int, "testOut.Int failed");
|
||||
oxAssert(testOut.get("Bool").unwrap()->get<bool>() == testIn.Bool, "testOut.Bool failed");
|
||||
oxAssert(testOut.get("String").unwrap()->get<ox::String>() == testIn.String, "testOut.String failed");
|
||||
auto &testOutStruct = testOut.get("Struct").unwrap()->get<ox::ModelObject>();
|
||||
auto &testOutUnion = testOut.get("Union").unwrap()->get<ox::ModelUnion>();
|
||||
auto &testOutList = testOut.get("List").unwrap()->get<ox::ModelValueVector>();
|
||||
auto testOutStructCopy = testOut.get("Struct").unwrap()->get<ox::ModelObject>();
|
||||
auto testOutUnionCopy = testOut.get("Union").unwrap()->get<ox::ModelUnion>();
|
||||
auto testOutListCopy = testOut.get("List").unwrap()->get<ox::ModelValueVector>();
|
||||
oxAssert(testOutStruct.typeName() == TestStructNest::TypeName, "ModelObject TypeName failed");
|
||||
oxAssert(testOutStruct.typeVersion() == TestStructNest::TypeVersion, "ModelObject TypeVersion failed");
|
||||
oxAssert(testOutStruct.get("Bool").unwrap()->get<bool>() == testIn.Struct.Bool, "testOut.Struct.Bool failed");
|
||||
oxAssert(testOutStruct.get("String").unwrap()->get<ox::String>() == testIn.Struct.String.c_str(), "testOut.Struct.String failed");
|
||||
oxAssert(testOut.get("unionIdx").unwrap()->get<int>() == testIn.unionIdx, "testOut.unionIdx failed");
|
||||
oxAssert(testOutUnion.unionIdx() == testIn.unionIdx, "testOut.Union idx wrong");
|
||||
oxAssert(testOutUnion.get("Int").unwrap()->get<uint32_t>() == testIn.Union.Int, "testOut.Union.Int failed");
|
||||
oxAssert(testOutList[0].get<uint32_t>() == testIn.List[0], "testOut.List[0] failed");
|
||||
oxAssert(testOutList[1].get<uint32_t>() == testIn.List[1], "testOut.Struct.List[1] failed");
|
||||
oxAssert(testOutStructCopy.get("Bool").unwrap()->get<bool>() == testIn.Struct.Bool, "testOut.Struct.Bool (copy) failed");
|
||||
oxAssert(testOutStructCopy.get("String").unwrap()->get<ox::String>() == testIn.Struct.String.c_str(), "testOut.Struct.String (copy) failed");
|
||||
oxAssert(testOutListCopy[0].get<uint32_t>() == testIn.List[0], "testOut.Struct.List[0] (copy) failed");
|
||||
oxAssert(testOutListCopy[1].get<uint32_t>() == testIn.List[1], "testOut.Struct.List[1] (copy) failed");
|
||||
return OxError(0);
|
||||
}
|
||||
"OrganicClawModelValue",
|
||||
[] {
|
||||
ox::Buffer dataBuff;
|
||||
TestStruct testIn;
|
||||
testIn.Bool = true;
|
||||
testIn.Int = 42;
|
||||
testIn.String = "Test String 1";
|
||||
testIn.List[0] = 1;
|
||||
testIn.List[1] = 2;
|
||||
testIn.List[2] = 3;
|
||||
testIn.List[3] = 4;
|
||||
testIn.Struct.Bool = false;
|
||||
testIn.Struct.Int = 300;
|
||||
testIn.Struct.String = "Test String 2";
|
||||
testIn.unionIdx = 1;
|
||||
testIn.Union.Int = 93;
|
||||
oxAssert(ox::writeOC(testIn).moveTo(&dataBuff), "Data generation failed");
|
||||
ox::TypeStore typeStore;
|
||||
auto type = ox::buildTypeDef(&typeStore, &testIn);
|
||||
oxAssert(type.error, "Descriptor write failed");
|
||||
ox::ModelObject testOut;
|
||||
oxReturnError(testOut.setType(type.value));
|
||||
oxAssert(ox::readOC(dataBuff.data(), dataBuff.size(), &testOut), "Data read failed");
|
||||
oxAssert(testOut.get("Int").unwrap()->get<int>() == testIn.Int, "testOut.Int failed");
|
||||
oxAssert(testOut.get("Bool").unwrap()->get<bool>() == testIn.Bool, "testOut.Bool failed");
|
||||
oxAssert(testOut.get("String").unwrap()->get<ox::String>() == testIn.String, "testOut.String failed");
|
||||
auto &testOutStruct = testOut.get("Struct").unwrap()->get<ox::ModelObject>();
|
||||
auto &testOutUnion = testOut.get("Union").unwrap()->get<ox::ModelUnion>();
|
||||
auto &testOutList = testOut.get("List").unwrap()->get<ox::ModelValueVector>();
|
||||
auto testOutStructCopy = testOut.get("Struct").unwrap()->get<ox::ModelObject>();
|
||||
auto testOutUnionCopy = testOut.get("Union").unwrap()->get<ox::ModelUnion>();
|
||||
auto testOutListCopy = testOut.get("List").unwrap()->get<ox::ModelValueVector>();
|
||||
oxAssert(testOutStruct.typeName() == TestStructNest::TypeName, "ModelObject TypeName failed");
|
||||
oxAssert(testOutStruct.typeVersion() == TestStructNest::TypeVersion, "ModelObject TypeVersion failed");
|
||||
oxAssert(testOutStruct.get("Bool").unwrap()->get<bool>() == testIn.Struct.Bool, "testOut.Struct.Bool failed");
|
||||
oxAssert(testOutStruct.get("String").unwrap()->get<ox::String>() == testIn.Struct.String.c_str(), "testOut.Struct.String failed");
|
||||
oxAssert(testOut.get("unionIdx").unwrap()->get<int>() == testIn.unionIdx, "testOut.unionIdx failed");
|
||||
oxAssert(testOutUnion.unionIdx() == testIn.unionIdx, "testOut.Union idx wrong");
|
||||
oxAssert(testOutUnion.get("Int").unwrap()->get<uint32_t>() == testIn.Union.Int, "testOut.Union.Int failed");
|
||||
oxAssert(testOutList[0].get<uint32_t>() == testIn.List[0], "testOut.List[0] failed");
|
||||
oxAssert(testOutList[1].get<uint32_t>() == testIn.List[1], "testOut.Struct.List[1] failed");
|
||||
oxAssert(testOutStructCopy.get("Bool").unwrap()->get<bool>() == testIn.Struct.Bool, "testOut.Struct.Bool (copy) failed");
|
||||
oxAssert(testOutStructCopy.get("String").unwrap()->get<ox::String>() == testIn.Struct.String.c_str(), "testOut.Struct.String (copy) failed");
|
||||
oxAssert(testOutListCopy[0].get<uint32_t>() == testIn.List[0], "testOut.Struct.List[0] (copy) failed");
|
||||
oxAssert(testOutListCopy[1].get<uint32_t>() == testIn.List[1], "testOut.Struct.List[1] (copy) failed");
|
||||
return OxError(0);
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
@ -354,13 +354,11 @@ int main(int argc, const char **args) {
|
||||
if (argc < 2) {
|
||||
oxError("Must specify test to run");
|
||||
}
|
||||
const auto testName = args[1];
|
||||
ox::Error(*test)();
|
||||
try {
|
||||
test = tests.at(testName);
|
||||
} catch (const std::out_of_range&) {
|
||||
oxErrorf("Test {} not found", testName);
|
||||
return 1;
|
||||
auto const testName = args[1];
|
||||
auto const func = tests.find(testName);
|
||||
if (func != tests.end()) {
|
||||
oxAssert(func->second(), "Test returned Error");
|
||||
return 0;
|
||||
}
|
||||
return static_cast<int>(test());
|
||||
return -1;
|
||||
}
|
||||
|
8
deps/ox/src/ox/oc/write.cpp
vendored
8
deps/ox/src/ox/oc/write.cpp
vendored
@ -26,18 +26,10 @@ Error OrganicClawWriter::fieldCString(const char *key, const char *const*val, in
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
Error OrganicClawWriter::fieldCString(const char *key, char **val, int len) noexcept {
|
||||
return fieldCString(key, const_cast<const char**>(val), len);
|
||||
}
|
||||
|
||||
Error OrganicClawWriter::fieldCString(const char *key, const char *const*val) noexcept {
|
||||
return fieldCString(key, const_cast<const char**>(val), {});
|
||||
}
|
||||
|
||||
Error OrganicClawWriter::fieldCString(const char *key, char **val) noexcept {
|
||||
return fieldCString(key, const_cast<const char**>(val), {});
|
||||
}
|
||||
|
||||
Error OrganicClawWriter::field(const char *key, const UUID *uuid) noexcept {
|
||||
const auto uuidStr = uuid->toString();
|
||||
if (targetValid() && uuidStr.len()) {
|
||||
|
54
deps/ox/src/ox/oc/write.hpp
vendored
54
deps/ox/src/ox/oc/write.hpp
vendored
@ -36,7 +36,7 @@ class OrganicClawWriter {
|
||||
|
||||
explicit OrganicClawWriter(Json::Value json, int unionIdx = -1) noexcept;
|
||||
|
||||
Error field(const char *key, CommonPtrWith<int8_t> auto *val) noexcept {
|
||||
Error field(const char *key, const int8_t *val) noexcept {
|
||||
if (*val) {
|
||||
value(key) = *val;
|
||||
}
|
||||
@ -44,7 +44,7 @@ class OrganicClawWriter {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
Error field(const char *key, CommonPtrWith<int16_t> auto *val) noexcept {
|
||||
Error field(const char *key, const int16_t *val) noexcept {
|
||||
if (*val) {
|
||||
value(key) = *val;
|
||||
}
|
||||
@ -52,7 +52,7 @@ class OrganicClawWriter {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
Error field(const char *key, CommonPtrWith<int32_t> auto *val) noexcept {
|
||||
Error field(const char *key, const int32_t *val) noexcept {
|
||||
if (*val) {
|
||||
value(key) = *val;
|
||||
}
|
||||
@ -60,7 +60,7 @@ class OrganicClawWriter {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
Error field(const char *key, CommonPtrWith<int64_t> auto *val) noexcept {
|
||||
Error field(const char *key, const int64_t *val) noexcept {
|
||||
if (*val) {
|
||||
value(key) = *val;
|
||||
}
|
||||
@ -69,7 +69,7 @@ class OrganicClawWriter {
|
||||
}
|
||||
|
||||
|
||||
Error field(const char *key, CommonPtrWith<uint8_t> auto *val) noexcept {
|
||||
Error field(const char *key, const uint8_t *val) noexcept {
|
||||
if (*val) {
|
||||
value(key) = *val;
|
||||
}
|
||||
@ -77,7 +77,7 @@ class OrganicClawWriter {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
Error field(const char *key, CommonPtrWith<uint16_t> auto *val) noexcept {
|
||||
Error field(const char *key, const uint16_t *val) noexcept {
|
||||
if (targetValid() && *val) {
|
||||
value(key) = *val;
|
||||
}
|
||||
@ -85,7 +85,7 @@ class OrganicClawWriter {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
Error field(const char *key, CommonPtrWith<uint32_t> auto *val) noexcept {
|
||||
Error field(const char *key, const uint32_t *val) noexcept {
|
||||
if (targetValid() && *val) {
|
||||
value(key) = *val;
|
||||
}
|
||||
@ -93,7 +93,7 @@ class OrganicClawWriter {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
Error field(const char *key, CommonPtrWith<uint64_t> auto *val) noexcept {
|
||||
Error field(const char *key, const uint64_t *val) noexcept {
|
||||
if (targetValid() && *val) {
|
||||
value(key) = *val;
|
||||
}
|
||||
@ -101,7 +101,7 @@ class OrganicClawWriter {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
Error field(const char *key, CommonPtrWith<bool> auto *val) noexcept {
|
||||
Error field(const char *key, const bool *val) noexcept {
|
||||
if (targetValid() && *val) {
|
||||
value(key) = *val;
|
||||
}
|
||||
@ -109,9 +109,6 @@ class OrganicClawWriter {
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Error field(const char*, T *val, std::size_t len) noexcept;
|
||||
|
||||
template<typename U, bool force = true>
|
||||
Error field(const char*, UnionView<U, force> val) noexcept;
|
||||
|
||||
@ -134,11 +131,6 @@ class OrganicClawWriter {
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Error field(const char *key, HashMap<String, T> *val) noexcept {
|
||||
return field(key, const_cast<const HashMap<String, T>*>(val));
|
||||
}
|
||||
|
||||
template<std::size_t L>
|
||||
Error field(const char *key, const BString<L> *val) noexcept {
|
||||
if (targetValid() && val->len()) {
|
||||
@ -148,15 +140,6 @@ class OrganicClawWriter {
|
||||
return {};
|
||||
}
|
||||
|
||||
template<std::size_t L>
|
||||
Error field(const char *key, BString<L> *val) noexcept {
|
||||
if (targetValid() && val->len()) {
|
||||
value(key) = val->c_str();
|
||||
}
|
||||
++m_fieldIt;
|
||||
return {};
|
||||
}
|
||||
|
||||
template<std::size_t L>
|
||||
Error field(const char *key, const BasicString<L> *val) noexcept {
|
||||
if (targetValid() && val->len()) {
|
||||
@ -166,23 +149,17 @@ class OrganicClawWriter {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<std::size_t L>
|
||||
Error field(const char *key, BasicString<L> *val) noexcept {
|
||||
return field(key, const_cast<const BasicString<L>*>(val));
|
||||
}
|
||||
|
||||
Error fieldCString(const char*, const char *const*val, int len) noexcept;
|
||||
|
||||
Error fieldCString(const char *name, char **val, int len) noexcept;
|
||||
|
||||
Error fieldCString(const char *name, const char *const*val) noexcept;
|
||||
|
||||
Error fieldCString(const char *name, char **val) noexcept;
|
||||
|
||||
Error field(const char *key, const UUID *uuid) noexcept;
|
||||
|
||||
template<typename T>
|
||||
Error field(const char*, T *val) noexcept;
|
||||
Error field(const char*, const T *val, std::size_t len) noexcept;
|
||||
|
||||
template<typename T>
|
||||
Error field(const char*, const T *val) noexcept;
|
||||
|
||||
template<typename T>
|
||||
constexpr ox::Error setTypeInfo(
|
||||
@ -200,6 +177,7 @@ class OrganicClawWriter {
|
||||
return {};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
static constexpr auto opType() noexcept {
|
||||
return OpType::Write;
|
||||
}
|
||||
@ -216,7 +194,7 @@ class OrganicClawWriter {
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
Error OrganicClawWriter::field(const char *key, T *val, std::size_t len) noexcept {
|
||||
Error OrganicClawWriter::field(const char *key, const T *val, std::size_t len) noexcept {
|
||||
if (targetValid() && len) {
|
||||
OrganicClawWriter w((Json::Value(Json::arrayValue)));
|
||||
ModelHandlerInterface handler{&w};
|
||||
@ -230,7 +208,7 @@ Error OrganicClawWriter::field(const char *key, T *val, std::size_t len) noexcep
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Error OrganicClawWriter::field(const char *key, T *val) noexcept {
|
||||
Error OrganicClawWriter::field(const char *key, const T *val) noexcept {
|
||||
if constexpr(isVector_v<T> || isArray_v<T>) {
|
||||
return field(key, val->data(), val->size());
|
||||
} else if (val && targetValid()) {
|
||||
|
217
deps/ox/src/ox/std/basestringview.hpp
vendored
Normal file
217
deps/ox/src/ox/std/basestringview.hpp
vendored
Normal file
@ -0,0 +1,217 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
#include "bit.hpp"
|
||||
#include "cstrops.hpp"
|
||||
#include "iterator.hpp"
|
||||
|
||||
namespace ox::detail {
|
||||
|
||||
class BaseStringView {
|
||||
public:
|
||||
template<typename RefType = char&, typename PtrType = char*, bool reverse = false>
|
||||
struct iterator: public Iterator<std::bidirectional_iterator_tag, char> {
|
||||
private:
|
||||
PtrType m_t = nullptr;
|
||||
std::size_t m_offset = 0;
|
||||
std::size_t m_max = 0;
|
||||
|
||||
public:
|
||||
constexpr iterator() noexcept = default;
|
||||
|
||||
constexpr iterator(PtrType t, std::size_t offset, std::size_t max) noexcept {
|
||||
m_t = t;
|
||||
m_offset = offset;
|
||||
m_max = max;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto offset() const noexcept {
|
||||
return m_offset;
|
||||
}
|
||||
|
||||
constexpr iterator operator+(std::size_t s) const noexcept {
|
||||
if constexpr(reverse) {
|
||||
return iterator(m_t, max<std::size_t>(m_offset - s, 0), m_max);
|
||||
} else {
|
||||
return iterator(m_t, min<std::size_t>(m_offset + s, m_max), m_max);
|
||||
}
|
||||
}
|
||||
|
||||
constexpr auto operator-(const iterator &other) const noexcept {
|
||||
if constexpr(reverse) {
|
||||
return m_offset + other.m_offset;
|
||||
} else {
|
||||
return m_offset - other.m_offset;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr iterator operator-(std::size_t s) const noexcept {
|
||||
if constexpr(reverse) {
|
||||
return iterator(m_t, min<std::size_t>(m_offset + s, m_max), m_max);
|
||||
} else {
|
||||
return iterator(m_t, max<std::size_t>(m_offset - s, 0), m_max);
|
||||
}
|
||||
}
|
||||
|
||||
constexpr iterator &operator+=(std::size_t s) noexcept {
|
||||
if constexpr(reverse) {
|
||||
m_offset = max<std::size_t>(m_offset - s, 0);
|
||||
} else {
|
||||
m_offset = min(m_offset + s, m_max);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr iterator &operator-=(std::size_t s) noexcept {
|
||||
if constexpr(reverse) {
|
||||
m_offset = min(m_offset + s, m_max);
|
||||
} else {
|
||||
m_offset = max<std::size_t>(m_offset - s, 0);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr iterator &operator++() noexcept {
|
||||
return operator+=(1);
|
||||
}
|
||||
|
||||
constexpr iterator &operator--() noexcept {
|
||||
return operator-=(1);
|
||||
}
|
||||
|
||||
constexpr RefType operator*() const noexcept {
|
||||
return m_t[m_offset];
|
||||
}
|
||||
|
||||
constexpr RefType operator[](std::size_t s) const noexcept {
|
||||
return m_t[s];
|
||||
}
|
||||
|
||||
constexpr bool operator<(const iterator &other) const noexcept {
|
||||
return m_offset < other.m_offset;
|
||||
}
|
||||
|
||||
constexpr bool operator>(const iterator &other) const noexcept {
|
||||
return m_offset > other.m_offset;
|
||||
}
|
||||
|
||||
constexpr bool operator<=(const iterator &other) const noexcept {
|
||||
return m_offset <= other.m_offset;
|
||||
}
|
||||
|
||||
constexpr bool operator>=(const iterator &other) const noexcept {
|
||||
return m_offset >= other.m_offset;
|
||||
}
|
||||
|
||||
constexpr bool operator==(const iterator &other) const noexcept {
|
||||
return m_t == other.m_t && m_offset == other.m_offset && m_max == other.m_max;
|
||||
}
|
||||
|
||||
constexpr bool operator!=(const iterator &other) const noexcept {
|
||||
return m_t != other.m_t || m_offset != other.m_offset || m_max != other.m_max;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
private:
|
||||
const char *m_str = nullptr;
|
||||
std::size_t m_len = 0;
|
||||
protected:
|
||||
constexpr BaseStringView() noexcept = default;
|
||||
|
||||
constexpr BaseStringView(BaseStringView const&sv) noexcept = default;
|
||||
|
||||
constexpr explicit BaseStringView(std::nullptr_t) noexcept {}
|
||||
|
||||
constexpr explicit BaseStringView(const char *str) noexcept: m_str(str), m_len(str ? ox_strlen(str) : 0) {}
|
||||
|
||||
constexpr explicit BaseStringView(const char *str, std::size_t len) noexcept: m_str(str), m_len(len) {}
|
||||
|
||||
public:
|
||||
[[nodiscard]]
|
||||
constexpr iterator<const char&, const char*> begin() const noexcept {
|
||||
return {m_str, 0, m_len};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr iterator<const char&, const char*> end() const noexcept {
|
||||
return {m_str, m_len, m_len};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr iterator<const char&, const char*> cbegin() const noexcept {
|
||||
return {m_str, 0, m_len};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr iterator<const char&, const char*> cend() const noexcept {
|
||||
return {m_str, m_len, m_len};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr iterator<const char&, const char*, true> crbegin() const noexcept {
|
||||
return {m_str, m_len - 1, m_len};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr iterator<const char&, const char*, true> crend() const noexcept {
|
||||
return {m_str, MaxValue<std::size_t>, m_len};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr iterator<const char&, const char*, true> rbegin() const noexcept {
|
||||
return {m_str, m_len - 1, m_len};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr iterator<const char&, const char*, true> rend() const noexcept {
|
||||
return {m_str, MaxValue<std::size_t>, m_len};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto bytes() const noexcept {
|
||||
return m_len;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto len() const noexcept {
|
||||
return m_len;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto *data() const noexcept {
|
||||
return &m_str[0];
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto &front() const noexcept {
|
||||
return m_str[0];
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto &back() const noexcept {
|
||||
return m_str[m_len - 1];
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto operator[](std::size_t i) const noexcept {
|
||||
return m_str[i];
|
||||
}
|
||||
|
||||
protected:
|
||||
constexpr void set(const char *str, std::size_t len) noexcept {
|
||||
m_str = str;
|
||||
m_len = len;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
53
deps/ox/src/ox/std/cstringview.hpp
vendored
Normal file
53
deps/ox/src/ox/std/cstringview.hpp
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
#include "basestringview.hpp"
|
||||
#include "bstring.hpp"
|
||||
#include "string.hpp"
|
||||
#include "stringliteral.hpp"
|
||||
|
||||
namespace ox {
|
||||
|
||||
class CStringView: public detail::BaseStringView {
|
||||
public:
|
||||
constexpr CStringView() noexcept = default;
|
||||
|
||||
constexpr CStringView(CStringView const&sv) noexcept = default;
|
||||
|
||||
constexpr CStringView(StringLiteral const&str) noexcept: BaseStringView(str.data(), str.len()) {}
|
||||
|
||||
template<std::size_t SmallStrSz>
|
||||
constexpr CStringView(BasicString<SmallStrSz> const&str) noexcept: BaseStringView(str.data(), str.len()) {}
|
||||
|
||||
template<std::size_t SmallStrSz>
|
||||
constexpr CStringView(BString<SmallStrSz> const&str) noexcept: BaseStringView(str.data(), str.len()) {}
|
||||
|
||||
constexpr CStringView(std::nullptr_t) noexcept {}
|
||||
|
||||
constexpr CStringView(const char *str) noexcept: BaseStringView(str) {}
|
||||
|
||||
constexpr CStringView(const char *str, std::size_t len) noexcept: BaseStringView(str, len) {}
|
||||
|
||||
constexpr auto &operator=(CStringView const&other) noexcept {
|
||||
if (&other != this) {
|
||||
set(other.data(), other.len());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr const char *c_str() const noexcept {
|
||||
return data();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
145
deps/ox/src/ox/std/cstrops.hpp
vendored
Normal file
145
deps/ox/src/ox/std/cstrops.hpp
vendored
Normal file
@ -0,0 +1,145 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
#include "types.hpp"
|
||||
#include "typetraits.hpp"
|
||||
|
||||
template<typename T1, typename T2>
|
||||
constexpr T1 ox_strncpy(T1 dest, T2 src, std::size_t maxLen) noexcept {
|
||||
using T1Type = typename ox::remove_reference<decltype(dest[0])>::type;
|
||||
std::size_t i = 0;
|
||||
while (i < maxLen && src[i]) {
|
||||
dest[i] = static_cast<T1Type>(src[i]);
|
||||
++i;
|
||||
}
|
||||
// set null terminator
|
||||
dest[i] = 0;
|
||||
return dest;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto ox_strnlen(const char *str1, std::size_t maxLen) noexcept {
|
||||
std::size_t len = 0;
|
||||
for (; len < maxLen && str1[len]; len++);
|
||||
return len;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
[[nodiscard]]
|
||||
constexpr auto ox_strlen(T const&str1) noexcept {
|
||||
std::size_t len = 0;
|
||||
for (; str1[len]; len++);
|
||||
return len;
|
||||
}
|
||||
|
||||
template<typename T1, typename T2>
|
||||
[[nodiscard]]
|
||||
constexpr int ox_strcmp(const T1 &str1, const T2 &str2) noexcept {
|
||||
auto retval = 0;
|
||||
auto i = 0u;
|
||||
while (str1[i] || str2[i]) {
|
||||
if (str1[i] < str2[i]) {
|
||||
retval = -1;
|
||||
break;
|
||||
} else if (str1[i] > str2[i]) {
|
||||
retval = 1;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
template<typename T1, typename T2>
|
||||
[[nodiscard]]
|
||||
constexpr int ox_strncmp(T1 const&str1, T2 const&str2, const std::size_t maxLen) noexcept {
|
||||
auto retval = 0;
|
||||
std::size_t i = 0;
|
||||
while (i < maxLen && (str1[i] || str2[i])) {
|
||||
if (str1[i] < str2[i]) {
|
||||
retval = -1;
|
||||
break;
|
||||
} else if (str1[i] > str2[i]) {
|
||||
retval = 1;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr const char *ox_strchr(const char *str, int character, std::size_t maxLen = 0xFFFFFFFF) noexcept {
|
||||
for (std::size_t i = 0; i <= maxLen; i++) {
|
||||
if (str[i] == character) {
|
||||
return &str[i];
|
||||
} else if (str[i] == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr char *ox_strchr(char *str, int character, std::size_t maxLen = 0xFFFFFFFF) noexcept {
|
||||
for (std::size_t i = 0; i < maxLen; i++) {
|
||||
if (str[i] == character) {
|
||||
return &str[i];
|
||||
} else if (str[i] == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr int ox_lastIndexOf(const auto &str, int character, std::size_t maxLen = 0xFFFFFFFF) noexcept {
|
||||
int retval = -1;
|
||||
for (std::size_t i = 0; i < maxLen && str[i]; i++) {
|
||||
if (str[i] == character) {
|
||||
retval = static_cast<int>(i);
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
template<typename Integer, typename T>
|
||||
constexpr T ox_itoa(Integer v, T str) noexcept {
|
||||
if (v) {
|
||||
ox::ResizedInt_t<Integer, 64> mod = 1000000000000000000;
|
||||
ox::ResizedInt_t<Integer, 64> val = v;
|
||||
constexpr auto base = 10;
|
||||
auto it = 0;
|
||||
if (val < 0) {
|
||||
str[static_cast<std::size_t>(it)] = '-';
|
||||
it++;
|
||||
}
|
||||
while (mod) {
|
||||
auto digit = val / mod;
|
||||
val %= mod;
|
||||
mod /= base;
|
||||
if (it || digit) {
|
||||
ox::ResizedInt_t<Integer, 64> start = '0';
|
||||
if (digit >= 10) {
|
||||
start = 'a';
|
||||
digit -= 10;
|
||||
}
|
||||
str[static_cast<std::size_t>(it)] = static_cast<typename ox::remove_reference<decltype(str[0])>::type>(start + digit);
|
||||
it++;
|
||||
}
|
||||
}
|
||||
str[static_cast<std::size_t>(it)] = 0;
|
||||
} else {
|
||||
// 0 is a special case
|
||||
str[0] = '0';
|
||||
str[1] = 0;
|
||||
}
|
||||
return str;
|
||||
}
|
20
deps/ox/src/ox/std/def.hpp
vendored
20
deps/ox/src/ox/std/def.hpp
vendored
@ -17,16 +17,9 @@
|
||||
#define oxOut(...) ox::trace::OutStream(__FILE__, __LINE__, "stdout", __VA_ARGS__)
|
||||
#define oxErr(...) ox::trace::OutStream(__FILE__, __LINE__, "stderr", __VA_ARGS__)
|
||||
|
||||
#ifdef OX_USE_STDLIB
|
||||
// Non-GCC compilers don't like ##__VA_ARGS__, so use initializer list, which relies on std lib
|
||||
#define oxTracef(ch, fmt, ...) ox::trace::TraceStream(__FILE__, __LINE__, ch, ox::detail::fmtSegments<ox::detail::argCount(fmt)+1>(fmt), {__VA_ARGS__})
|
||||
#define oxOutf(fmt, ...) ox::trace::OutStream(__FILE__, __LINE__, "stdout", ox::detail::fmtSegments<ox::detail::argCount(fmt)+1>(fmt), {__VA_ARGS__})
|
||||
#define oxErrf(fmt, ...) ox::trace::OutStream(__FILE__, __LINE__, "stderr", ox::detail::fmtSegments<ox::detail::argCount(fmt)+1>(fmt), {__VA_ARGS__})
|
||||
#else
|
||||
#define oxTracef(ch, fmt, ...) ox::trace::TraceStream(__FILE__, __LINE__, ch, ox::detail::fmtSegments<ox::detail::argCount(fmt)+1>(fmt), ##__VA_ARGS__)
|
||||
#define oxOutf(fmt, ...) ox::trace::OutStream(__FILE__, __LINE__, "stdout", ox::detail::fmtSegments<ox::detail::argCount(fmt)+1>(fmt), ##__VA_ARGS__)
|
||||
#define oxErrf(fmt, ...) ox::trace::OutStream(__FILE__, __LINE__, "stderr", ox::detail::fmtSegments<ox::detail::argCount(fmt)+1>(fmt), ##__VA_ARGS__)
|
||||
#endif
|
||||
#define oxTracef(ch, fmt, ...) ox::trace::TraceStream(__FILE__, __LINE__, ch, ox::detail::fmtSegments<ox::detail::argCount(fmt)+1>(fmt), __VA_ARGS__)
|
||||
#define oxOutf(fmt, ...) ox::trace::OutStream(__FILE__, __LINE__, "stdout", ox::detail::fmtSegments<ox::detail::argCount(fmt)+1>(fmt), __VA_ARGS__)
|
||||
#define oxErrf(fmt, ...) ox::trace::OutStream(__FILE__, __LINE__, "stderr", ox::detail::fmtSegments<ox::detail::argCount(fmt)+1>(fmt), __VA_ARGS__)
|
||||
|
||||
#define oxInfo(...) oxTrace("info", __VA_ARGS__)
|
||||
#define oxInfof(...) oxTracef("info", __VA_ARGS__)
|
||||
@ -35,12 +28,7 @@
|
||||
|
||||
#ifndef OX_NODEBUG
|
||||
#define oxDebug(...) ox::trace::OutStream(__FILE__, __LINE__, "debug", __VA_ARGS__)
|
||||
#ifdef OX_USE_STDLIB
|
||||
// Non-GCC compilers don't like ##__VA_ARGS__, so use initializer list, which relies on std lib
|
||||
#define oxDebugf(fmt, ...) ox::trace::OutStream(__FILE__, __LINE__, "debug", ox::detail::fmtSegments<ox::detail::argCount(fmt)+1>(fmt), {__VA_ARGS__})
|
||||
#else
|
||||
#define oxDebugf(fmt, ...) ox::trace::OutStream(__FILE__, __LINE__, "debug", ox::detail::fmtSegments<ox::detail::argCount(fmt)+1>(fmt), ##__VA_ARGS__)
|
||||
#endif
|
||||
#define oxDebugf(fmt, ...) ox::trace::OutStream(__FILE__, __LINE__, "debug", ox::detail::fmtSegments<ox::detail::argCount(fmt)+1>(fmt), __VA_ARGS__)
|
||||
#else
|
||||
#define oxDebug(...) static_assert(false, "Debug prints were checked in.");
|
||||
#define oxDebugf(...) static_assert(false, "Debug prints were checked in.");
|
||||
|
41
deps/ox/src/ox/std/error.hpp
vendored
41
deps/ox/src/ox/std/error.hpp
vendored
@ -138,16 +138,16 @@ struct [[nodiscard]] Result {
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
constexpr Result(const Result<U> &&other) noexcept: value(std::move(other.value)), error(std::move(other.error)) {
|
||||
constexpr Result(Result<U> &&other) noexcept: value(std::move(other.value)), error(std::move(other.error)) {
|
||||
}
|
||||
|
||||
constexpr Result(const Error &error) noexcept: value(), error(error) {
|
||||
}
|
||||
|
||||
constexpr Result(const type &value, const Error &error = OxError(0)) noexcept: value(const_cast<type&>(value)), error(error) {
|
||||
constexpr Result(const type &value, const Error &error = OxError(0)) noexcept: value(value), error(error) {
|
||||
}
|
||||
|
||||
constexpr Result(type &&value, const Error &error = OxError(0)) noexcept: value(ox::forward<type>(value)), error(error) {
|
||||
constexpr Result(type &&value, const Error &error = OxError(0)) noexcept: value(std::move(value)), error(error) {
|
||||
}
|
||||
|
||||
constexpr ~Result() noexcept = default;
|
||||
@ -165,12 +165,12 @@ struct [[nodiscard]] Result {
|
||||
return error == 0;
|
||||
}
|
||||
|
||||
constexpr Error get(type *val) const noexcept {
|
||||
constexpr Error copyTo(type *val) const noexcept {
|
||||
*val = value;
|
||||
return error;
|
||||
}
|
||||
|
||||
constexpr Error get(type *val) noexcept {
|
||||
constexpr Error copyTo(type *val) noexcept {
|
||||
*val = value;
|
||||
return error;
|
||||
}
|
||||
@ -182,23 +182,44 @@ struct [[nodiscard]] Result {
|
||||
return error;
|
||||
}
|
||||
|
||||
constexpr auto &unwrap() noexcept {
|
||||
constexpr T &unwrap() & noexcept {
|
||||
if (error) {
|
||||
oxPanic(error, "Failed unwrap");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
constexpr auto &unwrapThrow() {
|
||||
constexpr T &&unwrap() && noexcept {
|
||||
if (error) {
|
||||
oxPanic(error, "Failed unwrap");
|
||||
}
|
||||
return std::move(value);
|
||||
}
|
||||
|
||||
constexpr T const&unwrap() const & noexcept {
|
||||
if (error) [[unlikely]] {
|
||||
oxPanic(error, "Failed unwrap");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
constexpr T &unwrapThrow() & {
|
||||
if (error) {
|
||||
throw ox::Exception(error);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
constexpr const auto &unwrap() const noexcept {
|
||||
if (error) [[unlikely]] {
|
||||
oxPanic(error, "Failed unwrap");
|
||||
constexpr T &&unwrapThrow() && {
|
||||
if (error) {
|
||||
throw ox::Exception(error);
|
||||
}
|
||||
return std::move(value);
|
||||
}
|
||||
|
||||
constexpr T const&unwrapThrow() const & {
|
||||
if (error) {
|
||||
throw ox::Exception(error);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
2
deps/ox/src/ox/std/fmt.hpp
vendored
2
deps/ox/src/ox/std/fmt.hpp
vendored
@ -186,7 +186,7 @@ constexpr Fmt<segementCnt> fmtSegments(StringView fmt) noexcept {
|
||||
|
||||
template<typename StringType = String, typename ...Args>
|
||||
[[nodiscard]]
|
||||
constexpr StringType sfmt(StringView fmt, Args... args) noexcept {
|
||||
constexpr StringType sfmt(StringView fmt, Args&&... args) noexcept {
|
||||
assert(ox::detail::argCount(fmt) == sizeof...(args));
|
||||
StringType out;
|
||||
const auto fmtSegments = ox::detail::fmtSegments<sizeof...(args)+1>(fmt);
|
||||
|
43
deps/ox/src/ox/std/hashmap.hpp
vendored
43
deps/ox/src/ox/std/hashmap.hpp
vendored
@ -18,25 +18,11 @@ namespace ox {
|
||||
template<typename K, typename T>
|
||||
class HashMap {
|
||||
|
||||
using key_t = K;
|
||||
using value_t = T;
|
||||
public:
|
||||
using key_t = K;
|
||||
using value_t = T;
|
||||
|
||||
private:
|
||||
// Maybe StringView. If K (or KK for MaybeSV) is a string type,
|
||||
// MaybeSV::type/MaybeSV_t is a StringView.
|
||||
// This avoids creating unnecessary Strings when taking a StringView or C
|
||||
// string in lookups.
|
||||
template<typename KK, bool isStr = isOxString_v<KK>>
|
||||
struct MaybeSV {
|
||||
using type = KK;
|
||||
};
|
||||
template<typename KK>
|
||||
struct MaybeSV<KK, true> {
|
||||
using type = ox::StringView;
|
||||
};
|
||||
template<typename KK>
|
||||
using MaybeSV_t = MaybeSV<KK>::type;
|
||||
|
||||
struct Pair {
|
||||
K key = {};
|
||||
T value{};
|
||||
@ -85,15 +71,9 @@ class HashMap {
|
||||
|
||||
constexpr static uint64_t hash(StringView const&) noexcept;
|
||||
|
||||
/**
|
||||
* K is assumed to be a null terminated string.
|
||||
*/
|
||||
template<typename KK>
|
||||
constexpr Pair *const&access(Vector<Pair*> const&pairs, KK const&key) const;
|
||||
|
||||
/**
|
||||
* K is assumed to be a null terminated string.
|
||||
*/
|
||||
template<typename KK>
|
||||
constexpr Pair *&access(Vector<Pair*> &pairs, KK const&key);
|
||||
|
||||
@ -124,7 +104,7 @@ constexpr bool HashMap<K, T>::operator==(HashMap const&other) const {
|
||||
if (m_keys != other.m_keys) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < m_keys.size(); i++) {
|
||||
for (int i = 0; i < m_keys.size(); ++i) {
|
||||
auto &k = m_keys[i];
|
||||
if (at(k) != other.at(k)) {
|
||||
return false;
|
||||
@ -194,7 +174,7 @@ constexpr void HashMap<K, T>::erase(MaybeSV_t<K> const&k) {
|
||||
auto h = hash(k) % m_pairs.size();
|
||||
while (true) {
|
||||
const auto &p = m_pairs[h];
|
||||
if (p == nullptr || ox_strcmp(p->key, k) == 0) {
|
||||
if (p == nullptr || p->key == k) {
|
||||
oxIgnoreError(m_pairs.erase(h));
|
||||
break;
|
||||
} else {
|
||||
@ -232,7 +212,7 @@ template<typename K, typename T>
|
||||
constexpr void HashMap<K, T>::expand() {
|
||||
Vector<Pair*> r;
|
||||
for (std::size_t i = 0; i < m_keys.size(); ++i) {
|
||||
auto k = m_keys[i];
|
||||
K k{m_keys[i]};
|
||||
access(r, k) = std::move(access(m_pairs, k));
|
||||
}
|
||||
m_pairs = std::move(r);
|
||||
@ -264,7 +244,7 @@ constexpr typename HashMap<K, T>::Pair *const&HashMap<K, T>::access(Vector<Pair*
|
||||
auto h = static_cast<std::size_t>(hash(k) % pairs.size());
|
||||
while (true) {
|
||||
const auto &p = pairs[h];
|
||||
if (p == nullptr || ox_strcmp(p->key, k) == 0) {
|
||||
if (p == nullptr || p->key == k) {
|
||||
return p;
|
||||
} else {
|
||||
h = (h + 1) % pairs.size();
|
||||
@ -278,14 +258,7 @@ constexpr typename HashMap<K, T>::Pair *&HashMap<K, T>::access(Vector<Pair*> &pa
|
||||
auto h = static_cast<std::size_t>(hash(k) % pairs.size());
|
||||
while (true) {
|
||||
auto &p = pairs[h];
|
||||
bool matches = [&] {
|
||||
if constexpr (is_integral_v<KK>) {
|
||||
return p == nullptr || k == p->key;
|
||||
} else {
|
||||
return p == nullptr || ox_strcmp(p->key, k) == 0;
|
||||
}
|
||||
}();
|
||||
if (matches) {
|
||||
if (p == nullptr || p->key == k) {
|
||||
return p;
|
||||
} else {
|
||||
h = (h + 1) % pairs.size();
|
||||
|
24
deps/ox/src/ox/std/memory.hpp
vendored
24
deps/ox/src/ox/std/memory.hpp
vendored
@ -180,7 +180,7 @@ template<typename T, typename Deleter = DefaultDelete>
|
||||
class UniquePtr {
|
||||
|
||||
private:
|
||||
T *m_t;
|
||||
T *m_t = nullptr;
|
||||
|
||||
public:
|
||||
explicit constexpr UniquePtr(T *t = nullptr) noexcept: m_t(t) {
|
||||
@ -190,8 +190,8 @@ class UniquePtr {
|
||||
|
||||
constexpr UniquePtr(const UniquePtr&) = delete;
|
||||
|
||||
template<typename U>
|
||||
constexpr UniquePtr(UniquePtr<U> &&other) noexcept {
|
||||
template<typename U, typename UDeleter>
|
||||
constexpr UniquePtr(UniquePtr<U, UDeleter> &&other) noexcept {
|
||||
m_t = other.release();
|
||||
}
|
||||
|
||||
@ -210,25 +210,25 @@ class UniquePtr {
|
||||
return m_t;
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
constexpr void reset(UniquePtr<U> &&other = UniquePtr()) {
|
||||
template<typename U, typename UDeleter>
|
||||
constexpr void reset(UniquePtr<U, UDeleter> &&other = UniquePtr()) {
|
||||
auto t = m_t;
|
||||
m_t = other.release();
|
||||
Deleter()(t);
|
||||
}
|
||||
|
||||
constexpr UniquePtr &operator=(const UniquePtr<T> &other) = delete;
|
||||
constexpr UniquePtr &operator=(UniquePtr const&other) = delete;
|
||||
|
||||
template<typename U>
|
||||
constexpr UniquePtr &operator=(const UniquePtr<U> &other) = delete;
|
||||
template<typename U, typename UDeleter>
|
||||
constexpr UniquePtr &operator=(UniquePtr<U, UDeleter> const&other) = delete;
|
||||
|
||||
constexpr UniquePtr &operator=(UniquePtr<T> &&other) noexcept {
|
||||
reset(std::move(other));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
constexpr UniquePtr &operator=(UniquePtr<U> &&other) noexcept {
|
||||
template<typename U, typename UDeleter>
|
||||
constexpr UniquePtr &operator=(UniquePtr<U, UDeleter> &&other) noexcept {
|
||||
reset(std::move(other));
|
||||
return *this;
|
||||
}
|
||||
@ -247,8 +247,8 @@ class UniquePtr {
|
||||
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
using UPtr = UniquePtr<T>;
|
||||
template<typename T, typename Deleter = DefaultDelete>
|
||||
using UPtr = UniquePtr<T, Deleter>;
|
||||
|
||||
template<typename T>
|
||||
constexpr bool operator==(const UniquePtr<T> &p1, const UniquePtr<T> &p2) noexcept {
|
||||
|
7
deps/ox/src/ox/std/span.hpp
vendored
7
deps/ox/src/ox/std/span.hpp
vendored
@ -25,7 +25,7 @@ class SpanView {
|
||||
using value_type = T;
|
||||
using size_type = std::size_t;
|
||||
|
||||
template<typename RefType = T&, typename PtrType = T*, bool reverse = false>
|
||||
template<typename RefType = T const&, typename PtrType = T const*, bool reverse = false>
|
||||
using iterator = SpanIterator<T, RefType, PtrType, reverse>;
|
||||
|
||||
template<std::size_t sz>
|
||||
@ -103,6 +103,11 @@ class SpanView {
|
||||
return m_items[i];
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr T const*data() const noexcept {
|
||||
return m_items;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr std::size_t size() const noexcept {
|
||||
return m_size;
|
||||
|
3
deps/ox/src/ox/std/std.hpp
vendored
3
deps/ox/src/ox/std/std.hpp
vendored
@ -15,6 +15,8 @@
|
||||
#include "bstring.hpp"
|
||||
#include "byteswap.hpp"
|
||||
#include "concepts.hpp"
|
||||
#include "cstringview.hpp"
|
||||
#include "cstrops.hpp"
|
||||
#include "def.hpp"
|
||||
#include "defer.hpp"
|
||||
#include "defines.hpp"
|
||||
@ -37,6 +39,7 @@
|
||||
#include "stacktrace.hpp"
|
||||
#include "stddef.hpp"
|
||||
#include "string.hpp"
|
||||
#include "stringliteral.hpp"
|
||||
#include "stringview.hpp"
|
||||
#include "strongint.hpp"
|
||||
#include "strops.hpp"
|
||||
|
83
deps/ox/src/ox/std/string.hpp
vendored
83
deps/ox/src/ox/std/string.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
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if defined(OX_USE_STDLIB)
|
||||
#if __has_include(<string>)
|
||||
#include <string>
|
||||
#endif
|
||||
|
||||
@ -32,15 +32,15 @@ class BasicString {
|
||||
|
||||
constexpr explicit BasicString(std::size_t cap) noexcept;
|
||||
|
||||
constexpr BasicString(const char *str) noexcept;
|
||||
constexpr explicit BasicString(const char *str) noexcept;
|
||||
|
||||
constexpr BasicString(const char8_t *str) noexcept;
|
||||
constexpr explicit BasicString(const char8_t *str) noexcept;
|
||||
|
||||
constexpr BasicString(const char *str, std::size_t size) noexcept;
|
||||
|
||||
constexpr explicit BasicString(CRStringView str) noexcept;
|
||||
|
||||
constexpr BasicString(const BasicString&) noexcept;
|
||||
constexpr explicit BasicString(BasicString const&) noexcept;
|
||||
|
||||
constexpr BasicString(BasicString&&) noexcept;
|
||||
|
||||
@ -130,7 +130,7 @@ class BasicString {
|
||||
|
||||
constexpr BasicString &operator+=(StringView src) noexcept;
|
||||
|
||||
constexpr BasicString &operator+=(const BasicString &src) noexcept;
|
||||
constexpr BasicString &operator+=(BasicString const&src) noexcept;
|
||||
|
||||
constexpr BasicString operator+(const char *str) const noexcept;
|
||||
|
||||
@ -142,23 +142,23 @@ class BasicString {
|
||||
|
||||
constexpr BasicString operator+(CRStringView src) const noexcept;
|
||||
|
||||
constexpr BasicString operator+(const BasicString &src) const noexcept;
|
||||
constexpr BasicString operator+(BasicString const&src) const noexcept;
|
||||
|
||||
constexpr bool operator==(const char *other) const noexcept;
|
||||
|
||||
constexpr bool operator==(const OxString_c auto &other) const noexcept;
|
||||
constexpr bool operator==(OxString_c auto const&other) const noexcept;
|
||||
|
||||
constexpr bool operator!=(const char *other) const noexcept;
|
||||
|
||||
constexpr bool operator!=(const OxString_c auto &other) const noexcept;
|
||||
constexpr bool operator!=(OxString_c auto const&other) const noexcept;
|
||||
|
||||
constexpr bool operator<(const BasicString &other) const noexcept;
|
||||
constexpr bool operator<(BasicString const&other) const noexcept;
|
||||
|
||||
constexpr bool operator>(const BasicString &other) const noexcept;
|
||||
constexpr bool operator>(BasicString const&other) const noexcept;
|
||||
|
||||
constexpr bool operator<=(const BasicString &other) const noexcept;
|
||||
constexpr bool operator<=(BasicString const&other) const noexcept;
|
||||
|
||||
constexpr bool operator>=(const BasicString &other) const noexcept;
|
||||
constexpr bool operator>=(BasicString const&other) const noexcept;
|
||||
|
||||
constexpr char operator[](std::size_t i) const noexcept;
|
||||
|
||||
@ -200,7 +200,7 @@ class BasicString {
|
||||
return c_str();
|
||||
}
|
||||
|
||||
#ifdef OX_USE_STDLIB
|
||||
#if __has_include(<string>)
|
||||
[[nodiscard]]
|
||||
inline std::string toStdString() const {
|
||||
return c_str();
|
||||
@ -225,19 +225,14 @@ class BasicString {
|
||||
constexpr std::size_t bytes() const noexcept;
|
||||
|
||||
private:
|
||||
template<std::size_t OtherSize>
|
||||
constexpr void set(const BasicString<OtherSize> &src) noexcept;
|
||||
|
||||
constexpr void set(CRStringView str) noexcept;
|
||||
|
||||
constexpr void set(const char *str) noexcept;
|
||||
|
||||
constexpr void set(const char8_t *str) noexcept;
|
||||
};
|
||||
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr BasicString<SmallStringSize_v>::BasicString() noexcept {
|
||||
if (m_buff.size()) {
|
||||
if (!m_buff.empty()) {
|
||||
m_buff[0] = 0;
|
||||
} else {
|
||||
m_buff.push_back(0);
|
||||
@ -247,14 +242,14 @@ constexpr BasicString<SmallStringSize_v>::BasicString() noexcept {
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr BasicString<SmallStringSize_v>::BasicString(std::size_t cap) noexcept: m_buff(cap + 1) {
|
||||
// GCC complains if you don't do this pretty unnecessary size check
|
||||
if (m_buff.size()) {
|
||||
if (!m_buff.empty()) {
|
||||
m_buff[0] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr BasicString<SmallStringSize_v>::BasicString(const char *str) noexcept {
|
||||
if (m_buff.size()) {
|
||||
if (!m_buff.empty()) {
|
||||
m_buff[0] = 0;
|
||||
} else {
|
||||
m_buff.push_back(0);
|
||||
@ -264,7 +259,7 @@ constexpr BasicString<SmallStringSize_v>::BasicString(const char *str) noexcept
|
||||
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr BasicString<SmallStringSize_v>::BasicString(const char8_t *str) noexcept {
|
||||
if (m_buff.size()) {
|
||||
if (!m_buff.empty()) {
|
||||
m_buff[0] = 0;
|
||||
} else {
|
||||
m_buff.push_back(0);
|
||||
@ -388,7 +383,7 @@ constexpr BasicString<SmallStringSize_v> &BasicString<SmallStringSize_v>::operat
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr BasicString<SmallStringSize_v> &BasicString<SmallStringSize_v>::operator+=(const BasicString &src) noexcept {
|
||||
constexpr BasicString<SmallStringSize_v> &BasicString<SmallStringSize_v>::operator+=(BasicString const&src) noexcept {
|
||||
oxIgnoreError(append(src.c_str(), src.len()));
|
||||
return *this;
|
||||
}
|
||||
@ -436,7 +431,7 @@ constexpr BasicString<SmallStringSize_v> BasicString<SmallStringSize_v>::operato
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr BasicString<SmallStringSize_v> BasicString<SmallStringSize_v>::operator+(const BasicString &src) const noexcept {
|
||||
constexpr BasicString<SmallStringSize_v> BasicString<SmallStringSize_v>::operator+(BasicString const&src) const noexcept {
|
||||
const std::size_t strLen = src.len();
|
||||
const auto currentLen = len();
|
||||
BasicString<SmallStringSize_v> cpy(currentLen + strLen);
|
||||
@ -459,7 +454,7 @@ constexpr bool BasicString<SmallStringSize_v>::operator==(const char *other) con
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr bool BasicString<SmallStringSize_v>::operator==(const OxString_c auto &other) const noexcept {
|
||||
constexpr bool BasicString<SmallStringSize_v>::operator==(OxString_c auto const&other) const noexcept {
|
||||
return ox::StringView(*this) == ox::StringView(other);
|
||||
}
|
||||
|
||||
@ -469,27 +464,27 @@ constexpr bool BasicString<SmallStringSize_v>::operator!=(const char *other) con
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr bool BasicString<SmallStringSize_v>::operator!=(const OxString_c auto &other) const noexcept {
|
||||
constexpr bool BasicString<SmallStringSize_v>::operator!=(OxString_c auto const&other) const noexcept {
|
||||
return !operator==(other);
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr bool BasicString<SmallStringSize_v>::operator<(const BasicString &other) const noexcept {
|
||||
constexpr bool BasicString<SmallStringSize_v>::operator<(BasicString const&other) const noexcept {
|
||||
return ox_strcmp(c_str(), other.c_str()) < 0;
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr bool BasicString<SmallStringSize_v>::operator>(const BasicString &other) const noexcept {
|
||||
constexpr bool BasicString<SmallStringSize_v>::operator>(BasicString const&other) const noexcept {
|
||||
return ox_strcmp(c_str(), other.c_str()) > 0;
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr bool BasicString<SmallStringSize_v>::operator<=(const BasicString &other) const noexcept {
|
||||
constexpr bool BasicString<SmallStringSize_v>::operator<=(BasicString const&other) const noexcept {
|
||||
return ox_strcmp(c_str(), other.c_str()) < 1;
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr bool BasicString<SmallStringSize_v>::operator>=(const BasicString &other) const noexcept {
|
||||
constexpr bool BasicString<SmallStringSize_v>::operator>=(BasicString const&other) const noexcept {
|
||||
return ox_strcmp(c_str(), other.c_str()) > -1;
|
||||
}
|
||||
|
||||
@ -543,31 +538,14 @@ constexpr std::size_t BasicString<SmallStringSize_v>::len() const noexcept {
|
||||
return length;
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize_v>
|
||||
template<std::size_t OtherSize>
|
||||
constexpr void BasicString<SmallStringSize_v>::set(const BasicString<OtherSize> &src) noexcept {
|
||||
std::size_t strBytes = src.bytes();
|
||||
m_buff.resize(strBytes);
|
||||
copy_n(src.begin(), strBytes, m_buff.data());
|
||||
*m_buff.back().value = 0;
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr void BasicString<SmallStringSize_v>::set(CRStringView str) noexcept {
|
||||
std::size_t strBytes = str.bytes();
|
||||
std::size_t const strBytes = str.bytes();
|
||||
m_buff.resize(strBytes + 1);
|
||||
copy_n(str.data(), strBytes, m_buff.data());
|
||||
*m_buff.back().value = 0;
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr void BasicString<SmallStringSize_v>::set(const char *str) noexcept {
|
||||
std::size_t strBytes = ox_strlen(str) + 1;
|
||||
m_buff.resize(strBytes);
|
||||
copy_n(str, strBytes, m_buff.data());
|
||||
*m_buff.back().value = 0;
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr void BasicString<SmallStringSize_v>::set(const char8_t *str) noexcept {
|
||||
std::size_t strBytes = ox_strlen(str) + 1;
|
||||
@ -581,6 +559,13 @@ extern template class BasicString<8>;
|
||||
using String = BasicString<8>;
|
||||
using CRString = String const&;
|
||||
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr ox::String toString(ox::CRStringView sv) noexcept {
|
||||
return ox::String(sv);
|
||||
}
|
||||
|
||||
|
||||
template<typename PlatSpec, std::size_t SmallStringSize_v>
|
||||
[[nodiscard]]
|
||||
constexpr auto sizeOf(const ox::BasicString<SmallStringSize_v>*) noexcept {
|
||||
|
4
deps/ox/src/ox/std/stringliteral.hpp
vendored
4
deps/ox/src/ox/std/stringliteral.hpp
vendored
@ -41,6 +41,10 @@ class StringLiteral: public detail::BaseStringView {
|
||||
return *this;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr const char *c_str() const noexcept {
|
||||
return data();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
89
deps/ox/src/ox/std/stringview.hpp
vendored
89
deps/ox/src/ox/std/stringview.hpp
vendored
@ -12,12 +12,9 @@
|
||||
#include <string_view>
|
||||
#endif
|
||||
|
||||
#include "bit.hpp"
|
||||
#include "concepts.hpp"
|
||||
#include "iterator.hpp"
|
||||
#include "stringliteral.hpp"
|
||||
#include "strops.hpp"
|
||||
#include "vector.hpp"
|
||||
#include "basestringview.hpp"
|
||||
#include "cstrops.hpp"
|
||||
#include "writer.hpp"
|
||||
|
||||
namespace ox {
|
||||
|
||||
@ -89,70 +86,6 @@ constexpr auto operator<=>(CRStringView s1, CRStringView s2) noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr bool beginsWith(CRStringView base, CRStringView beginning) noexcept {
|
||||
const auto beginningLen = ox::min(beginning.len(), base.len());
|
||||
return base.len() >= beginning.len() && ox_strncmp(base.data(), beginning, beginningLen) == 0;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr bool endsWith(CRStringView base, CRStringView ending) noexcept {
|
||||
const auto endingLen = ending.len();
|
||||
return base.len() >= endingLen && ox_strcmp(base.data() + (base.len() - endingLen), ending) == 0;
|
||||
}
|
||||
|
||||
constexpr std::size_t find(CRStringView str, char search) noexcept {
|
||||
std::size_t i = 0;
|
||||
for (; i < str.len(); ++i) {
|
||||
if (str[i] == search) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
constexpr std::size_t find(CRStringView str, CRStringView search) noexcept {
|
||||
std::size_t i = 0;
|
||||
for (; i < str.len(); ++i) {
|
||||
if (beginsWith(substr(str, i), search)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
template<std::size_t smallSz = 0>
|
||||
constexpr ox::Vector<ox::StringView, smallSz> split(CRStringView str, char del) noexcept {
|
||||
ox::Vector<ox::StringView, smallSz> out;
|
||||
constexpr auto nextSeg = [](CRStringView current, char del) {
|
||||
return substr(current, find(current, del) + 1);
|
||||
};
|
||||
for (auto current = str; current.len(); current = nextSeg(current, del)) {
|
||||
const auto next = find(current, del);
|
||||
if (const auto s = substr(current, 0, next); s.len()) {
|
||||
out.emplace_back(s);
|
||||
}
|
||||
current = substr(current, next);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
template<std::size_t smallSz = 0>
|
||||
constexpr ox::Vector<ox::StringView, smallSz> split(CRStringView str, CRStringView del) noexcept {
|
||||
ox::Vector<ox::StringView, smallSz> out;
|
||||
constexpr auto nextSeg = [](CRStringView current, CRStringView del) {
|
||||
return substr(current, find(current, del) + del.len());
|
||||
};
|
||||
for (auto current = str; current.len(); current = nextSeg(current, del)) {
|
||||
const auto next = find(current, del);
|
||||
if (const auto s = substr(current, 0, next); s.len()) {
|
||||
out.emplace_back(s);
|
||||
}
|
||||
current = substr(current, next);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
constexpr auto write(Writer_c auto &writer, ox::CRStringView sv) noexcept {
|
||||
return writer.write(sv.data(), sv.bytes());
|
||||
}
|
||||
@ -163,6 +96,22 @@ constexpr auto toStdStringView(CRStringView sv) noexcept {
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// Maybe StringView. If T is a string type, MaybeType::type/MaybeSV_t is a
|
||||
// StringView. This avoids creating unnecessary Strings when taking a
|
||||
// StringView or C string as a function argument.
|
||||
template<typename T, bool isStr = isOxString_v<T>>
|
||||
struct MaybeSV {
|
||||
using type = T;
|
||||
};
|
||||
template<typename T>
|
||||
struct MaybeSV<T, true> {
|
||||
using type = ox::StringView;
|
||||
};
|
||||
template<typename T>
|
||||
using MaybeSV_t = typename MaybeSV<T>::type;
|
||||
|
||||
|
||||
}
|
||||
|
||||
constexpr ox::Result<int> ox_atoi(ox::CRStringView str) noexcept {
|
||||
|
226
deps/ox/src/ox/std/strops.hpp
vendored
226
deps/ox/src/ox/std/strops.hpp
vendored
@ -8,130 +8,19 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "concepts.hpp"
|
||||
#include "cstrops.hpp"
|
||||
#include "error.hpp"
|
||||
#include "math.hpp"
|
||||
#include "stringview.hpp"
|
||||
#include "types.hpp"
|
||||
#include "typetraits.hpp"
|
||||
#include "vector.hpp"
|
||||
#include "writer.hpp"
|
||||
|
||||
template<typename T1, typename T2>
|
||||
constexpr T1 ox_strcpy(T1 dest, T2 src) noexcept {
|
||||
using T1Type = typename ox::remove_reference<decltype(dest[0])>::type;
|
||||
std::size_t i = 0;
|
||||
while (src[i]) {
|
||||
dest[i] = static_cast<T1Type>(src[i]);
|
||||
++i;
|
||||
}
|
||||
// set null terminator
|
||||
dest[i] = 0;
|
||||
return dest;
|
||||
}
|
||||
|
||||
template<typename T1, typename T2>
|
||||
constexpr T1 ox_strncpy(T1 dest, T2 src, std::size_t maxLen) noexcept {
|
||||
using T1Type = typename ox::remove_reference<decltype(dest[0])>::type;
|
||||
std::size_t i = 0;
|
||||
while (i < maxLen && src[i]) {
|
||||
dest[i] = static_cast<T1Type>(src[i]);
|
||||
++i;
|
||||
}
|
||||
// set null terminator
|
||||
dest[i] = 0;
|
||||
return dest;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto ox_strnlen(const char *str1, std::size_t maxLen) noexcept {
|
||||
std::size_t len = 0;
|
||||
for (; len < maxLen && str1[len]; len++);
|
||||
return len;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
[[nodiscard]]
|
||||
constexpr auto ox_strlen(T str1) noexcept {
|
||||
std::size_t len = 0;
|
||||
for (; str1[len]; len++);
|
||||
return len;
|
||||
}
|
||||
|
||||
template<typename T1, typename T2>
|
||||
[[nodiscard]]
|
||||
constexpr int ox_strcmp(const T1 &str1, const T2 &str2) noexcept {
|
||||
auto retval = 0;
|
||||
auto i = 0u;
|
||||
while (str1[i] || str2[i]) {
|
||||
if (str1[i] < str2[i]) {
|
||||
retval = -1;
|
||||
break;
|
||||
} else if (str1[i] > str2[i]) {
|
||||
retval = 1;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
template<typename T1, typename T2>
|
||||
[[nodiscard]]
|
||||
constexpr int ox_strncmp(T1 str1, T2 str2, const std::size_t maxLen) noexcept {
|
||||
auto retval = 0;
|
||||
std::size_t i = 0;
|
||||
while (i < maxLen && (str1[i] || str2[i])) {
|
||||
if (str1[i] < str2[i]) {
|
||||
retval = -1;
|
||||
break;
|
||||
} else if (str1[i] > str2[i]) {
|
||||
retval = 1;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr const char *ox_strchr(const char *str, int character, std::size_t maxLen = 0xFFFFFFFF) noexcept {
|
||||
for (std::size_t i = 0; i <= maxLen; i++) {
|
||||
if (str[i] == character) {
|
||||
return &str[i];
|
||||
} else if (str[i] == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr char *ox_strchr(char *str, int character, std::size_t maxLen = 0xFFFFFFFF) noexcept {
|
||||
for (std::size_t i = 0; i < maxLen; i++) {
|
||||
if (str[i] == character) {
|
||||
return &str[i];
|
||||
} else if (str[i] == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr int ox_lastIndexOf(const auto &str, int character, std::size_t maxLen = 0xFFFFFFFF) noexcept {
|
||||
int retval = -1;
|
||||
for (std::size_t i = 0; i < maxLen && str[i]; i++) {
|
||||
if (str[i] == character) {
|
||||
retval = static_cast<int>(i);
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
namespace ox {
|
||||
|
||||
template<OxString_c Str>
|
||||
[[nodiscard]]
|
||||
constexpr Str substr(Str const&str, std::size_t pos) noexcept {
|
||||
constexpr ox::StringView substr(Str const&str, std::size_t pos) noexcept {
|
||||
if (str.len() >= pos) {
|
||||
return Str(str.data() + pos, str.len() - pos);
|
||||
}
|
||||
@ -140,7 +29,7 @@ constexpr Str substr(Str const&str, std::size_t pos) noexcept {
|
||||
|
||||
template<OxString_c Str>
|
||||
[[nodiscard]]
|
||||
constexpr Str substr(Str const&str, std::size_t start, std::size_t end) noexcept {
|
||||
constexpr ox::StringView substr(Str const&str, std::size_t start, std::size_t end) noexcept {
|
||||
if (str.len() >= start && end >= start) {
|
||||
return Str(str.data() + start, end - start);
|
||||
}
|
||||
@ -179,38 +68,79 @@ constexpr ox::Error itoa(Integer v, ox::Writer_c auto &writer) noexcept {
|
||||
return {};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr bool beginsWith(CRStringView base, CRStringView beginning) noexcept {
|
||||
const auto beginningLen = ox::min(beginning.len(), base.len());
|
||||
return base.len() >= beginning.len() && ox_strncmp(base.data(), beginning, beginningLen) == 0;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr bool endsWith(CRStringView base, CRStringView ending) noexcept {
|
||||
const auto endingLen = ending.len();
|
||||
return base.len() >= endingLen && ox_strcmp(base.data() + (base.len() - endingLen), ending) == 0;
|
||||
}
|
||||
|
||||
constexpr std::size_t find(CRStringView str, char search) noexcept {
|
||||
std::size_t i = 0;
|
||||
for (; i < str.len(); ++i) {
|
||||
if (str[i] == search) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
constexpr std::size_t find(CRStringView str, CRStringView search) noexcept {
|
||||
std::size_t i = 0;
|
||||
for (; i < str.len(); ++i) {
|
||||
if (beginsWith(substr(str, i), search)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
template<std::size_t smallSz = 0>
|
||||
constexpr ox::Vector<ox::StringView, smallSz> split(CRStringView str, char del) noexcept {
|
||||
ox::Vector<ox::StringView, smallSz> out;
|
||||
constexpr auto nextSeg = [](CRStringView current, char del) {
|
||||
return substr(current, find(current, del) + 1);
|
||||
};
|
||||
for (auto current = str; current.len(); current = nextSeg(current, del)) {
|
||||
const auto next = find(current, del);
|
||||
if (const auto s = substr(current, 0, next); s.len()) {
|
||||
out.emplace_back(s);
|
||||
}
|
||||
current = substr(current, next);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
template<std::size_t smallSz = 0>
|
||||
constexpr ox::Vector<ox::StringView, smallSz> split(CRStringView str, CRStringView del) noexcept {
|
||||
ox::Vector<ox::StringView, smallSz> out;
|
||||
constexpr auto nextSeg = [](CRStringView current, CRStringView del) {
|
||||
return substr(current, find(current, del) + del.len());
|
||||
};
|
||||
for (auto current = str; current.len(); current = nextSeg(current, del)) {
|
||||
const auto next = find(current, del);
|
||||
if (const auto s = substr(current, 0, next); s.len()) {
|
||||
out.emplace_back(s);
|
||||
}
|
||||
current = substr(current, next);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr ox::Result<std::size_t> lastIndexOf(ox::CRStringView str, int character) noexcept {
|
||||
ox::Result<std::size_t> retval = OxError(1, "Character not found");
|
||||
for (auto i = static_cast<int>(str.bytes() - 1); i >= 0; --i) {
|
||||
if (str[static_cast<std::size_t>(i)] == character) {
|
||||
retval = static_cast<std::size_t>(i);
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
template<typename Integer, typename T>
|
||||
constexpr T ox_itoa(Integer v, T str) noexcept {
|
||||
if (v) {
|
||||
ox::ResizedInt_t<Integer, 64> mod = 1000000000000000000;
|
||||
ox::ResizedInt_t<Integer, 64> val = v;
|
||||
constexpr auto base = 10;
|
||||
auto it = 0;
|
||||
if (val < 0) {
|
||||
str[static_cast<std::size_t>(it)] = '-';
|
||||
it++;
|
||||
}
|
||||
while (mod) {
|
||||
auto digit = val / mod;
|
||||
val %= mod;
|
||||
mod /= base;
|
||||
if (it || digit) {
|
||||
ox::ResizedInt_t<Integer, 64> start = '0';
|
||||
if (digit >= 10) {
|
||||
start = 'a';
|
||||
digit -= 10;
|
||||
}
|
||||
str[static_cast<std::size_t>(it)] = static_cast<typename ox::remove_reference<decltype(str[0])>::type>(start + digit);
|
||||
it++;
|
||||
}
|
||||
}
|
||||
str[static_cast<std::size_t>(it)] = 0;
|
||||
} else {
|
||||
// 0 is a special case
|
||||
str[0] = '0';
|
||||
str[1] = 0;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
19
deps/ox/src/ox/std/test/tests.cpp
vendored
19
deps/ox/src/ox/std/test/tests.cpp
vendored
@ -12,7 +12,7 @@
|
||||
#include <ox/std/uuid.hpp>
|
||||
#include <ox/std/std.hpp>
|
||||
|
||||
static std::map<ox::String, ox::Error(*)()> tests = {
|
||||
static std::map<ox::StringView, ox::Error(*)()> tests = {
|
||||
{
|
||||
"malloc",
|
||||
[] {
|
||||
@ -117,6 +117,7 @@ static std::map<ox::String, ox::Error(*)()> tests = {
|
||||
[] {
|
||||
ox::Vector<int> v;
|
||||
oxAssert(v.size() == 0, "Initial Vector size not 0");
|
||||
oxAssert(v.empty(), "Vector::empty() is broken");
|
||||
auto insertTest = [&v](int val, [[maybe_unused]] std::size_t size) {
|
||||
v.push_back(val);
|
||||
oxReturnError(OxError(v.size() != size, "Vector size incorrect"));
|
||||
@ -172,7 +173,7 @@ static std::map<ox::String, ox::Error(*)()> tests = {
|
||||
oxAssert(w.write("aoeu", 4), "write failed");
|
||||
oxExpect(b.size(), 8u);
|
||||
oxExpect(ox::StringView(b.data(), b.size()), "asdfaoeu");
|
||||
ox::StringView qwerty = "qwerty";
|
||||
ox::StringView constexpr qwerty = "qwerty";
|
||||
oxAssert(w.write(qwerty.data(), qwerty.bytes()), "write failed");
|
||||
oxExpect(b.size(), 14u);
|
||||
oxExpect(ox::StringView(b.data(), b.size()), "asdfaoeuqwerty");
|
||||
@ -313,12 +314,14 @@ static std::map<ox::String, ox::Error(*)()> tests = {
|
||||
};
|
||||
|
||||
int main(int argc, const char **args) {
|
||||
if (argc > 1) {
|
||||
auto testName = args[1];
|
||||
if (tests.find(testName) != tests.end()) {
|
||||
oxAssert(tests[testName](), "Test returned Error");
|
||||
return 0;
|
||||
}
|
||||
if (argc < 2) {
|
||||
oxError("Must specify test to run");
|
||||
}
|
||||
auto const testName = args[1];
|
||||
auto const func = tests.find(testName);
|
||||
if (func != tests.end()) {
|
||||
oxAssert(func->second(), "Test returned Error");
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
42
deps/ox/src/ox/std/trace.hpp
vendored
42
deps/ox/src/ox/std/trace.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
|
||||
@ -39,10 +39,10 @@ enum class MsgId: char {
|
||||
struct TraceMsgRcv {
|
||||
static constexpr auto TypeName = "net.drinkingtea.ox.trace.TraceMsg";
|
||||
static constexpr auto TypeVersion = 1;
|
||||
BasicString<50> file = "";
|
||||
BasicString<50> file{""};
|
||||
int line = 0;
|
||||
uint64_t time = 0;
|
||||
BasicString<50> ch = "";
|
||||
BasicString<50> ch{""};
|
||||
BasicString<100> msg;
|
||||
};
|
||||
|
||||
@ -141,39 +141,22 @@ class OutStream {
|
||||
m_msg.msg = msg;
|
||||
}
|
||||
|
||||
#ifdef OX_USE_STDLIB
|
||||
template<std::size_t fmtSegmentCnt, typename ...Args>
|
||||
constexpr OutStream(const char *file, int line, const char *ch, detail::Fmt<fmtSegmentCnt> fmtSegments, std::array<detail::FmtArg, fmtSegmentCnt - 1> elements) noexcept {
|
||||
//static_assert(sizeof...(args) == fmtSegmentCnt - 1, "Wrong number of trace arguments for format.");
|
||||
constexpr OutStream(const char *file, int line, const char *ch, detail::Fmt<fmtSegmentCnt> fmtSegments, Args const&...elements) noexcept {
|
||||
static_assert(sizeof...(elements) == fmtSegmentCnt - 1, "Wrong number of trace arguments for format.");
|
||||
m_msg.file = file;
|
||||
m_msg.line = line;
|
||||
m_msg.ch = ch;
|
||||
const auto &firstSegment = fmtSegments.segments[0];
|
||||
oxIgnoreError(m_msg.msg.append(firstSegment.str, firstSegment.length));
|
||||
//const detail::FmtArg elements[sizeof...(args)] = {args...};
|
||||
for (size_t i = 0; i < fmtSegments.size - 1; ++i) {
|
||||
m_msg.msg += elements[i].out;
|
||||
for (size_t i = 0; auto const&e : std::initializer_list<detail::FmtArg>{elements...}) {
|
||||
m_msg.msg += e.out;
|
||||
const auto &s = fmtSegments.segments[i + 1];
|
||||
oxIgnoreError(m_msg.msg.append(s.str, s.length));
|
||||
++i;
|
||||
}
|
||||
}
|
||||
#else
|
||||
template<std::size_t fmtSegmentCnt, typename ...Args>
|
||||
constexpr OutStream(const char *file, int line, const char *ch, detail::Fmt<fmtSegmentCnt> fmtSegments, Args... args) noexcept {
|
||||
//static_assert(sizeof...(args) == fmtSegmentCnt - 1, "Wrong number of trace arguments for format.");
|
||||
m_msg.file = file;
|
||||
m_msg.line = line;
|
||||
m_msg.ch = ch;
|
||||
const auto &firstSegment = fmtSegments.segments[0];
|
||||
oxIgnoreError(m_msg.msg.append(firstSegment.str, firstSegment.length));
|
||||
const detail::FmtArg elements[sizeof...(args)] = {args...};
|
||||
for (auto i = 0u; i < fmtSegments.size - 1; ++i) {
|
||||
m_msg.msg += elements[i].out;
|
||||
const auto &s = fmtSegments.segments[i + 1];
|
||||
oxIgnoreError(m_msg.msg.append(s.str, s.length));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
inline ~OutStream() noexcept {
|
||||
oxTraceHook(m_msg.file, m_msg.line, m_msg.ch, m_msg.msg.c_str());
|
||||
@ -257,15 +240,10 @@ class NullStream {
|
||||
constexpr NullStream(const char*, int, const char*, const char* = "") noexcept {
|
||||
}
|
||||
|
||||
#ifdef OX_USE_STDLIB
|
||||
template<std::size_t fmtSegmentCnt, typename ...Args>
|
||||
constexpr NullStream(const char*, int, const char*, detail::Fmt<fmtSegmentCnt>, std::array<detail::FmtArg, fmtSegmentCnt - 1>) noexcept {
|
||||
constexpr NullStream(const char*, int, const char*, detail::Fmt<fmtSegmentCnt>, Args const&...elements) noexcept {
|
||||
static_assert(sizeof...(elements) == fmtSegmentCnt - 1, "Wrong number of trace arguments for format.");
|
||||
}
|
||||
#else
|
||||
template<std::size_t fmtSegmentCnt, typename ...Args>
|
||||
constexpr NullStream(const char*, int, const char*, detail::Fmt<fmtSegmentCnt>, Args...) noexcept {
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
constexpr const NullStream &operator<<(const T&) const noexcept {
|
||||
|
5
deps/ox/src/ox/std/typetraits.hpp
vendored
5
deps/ox/src/ox/std/typetraits.hpp
vendored
@ -273,6 +273,7 @@ template<std::size_t SmallStringSize>
|
||||
class BasicString;
|
||||
template<std::size_t sz>
|
||||
class BString;
|
||||
class CStringView;
|
||||
class StringLiteral;
|
||||
class StringView;
|
||||
|
||||
@ -292,6 +293,10 @@ constexpr auto isOxString(const BString<sz>*) noexcept {
|
||||
return true;
|
||||
}
|
||||
|
||||
constexpr auto isOxString(const CStringView*) noexcept {
|
||||
return true;
|
||||
}
|
||||
|
||||
constexpr auto isOxString(const StringLiteral*) noexcept {
|
||||
return true;
|
||||
}
|
||||
|
29
deps/ox/src/ox/std/vector.hpp
vendored
29
deps/ox/src/ox/std/vector.hpp
vendored
@ -16,7 +16,7 @@
|
||||
#include "iterator.hpp"
|
||||
#include "math.hpp"
|
||||
#include "memory.hpp"
|
||||
#include "new.hpp"
|
||||
#include "stringview.hpp"
|
||||
#include "types.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
@ -254,12 +254,12 @@ class Vector: detail::VectorAllocator<T, Allocator, SmallVectorSize> {
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr bool contains(const T&) const noexcept(useNoexcept);
|
||||
constexpr bool contains(MaybeSV_t<T> const&) const noexcept(useNoexcept);
|
||||
|
||||
constexpr iterator<T&, T*, false> insert(
|
||||
std::size_t pos, std::size_t cnt, const T &val) noexcept(useNoexcept);
|
||||
std::size_t pos, std::size_t cnt, MaybeSV_t<T> const&val) noexcept(useNoexcept);
|
||||
|
||||
constexpr iterator<T&, T*, false> insert(std::size_t pos, const T &val) noexcept(useNoexcept);
|
||||
constexpr iterator<T&, T*, false> insert(std::size_t pos, MaybeSV_t<T> const&val) noexcept(useNoexcept);
|
||||
|
||||
template<typename... Args>
|
||||
constexpr iterator<T&, T*, false> emplace(std::size_t pos, Args&&... args) noexcept(useNoexcept);
|
||||
@ -267,7 +267,9 @@ class Vector: detail::VectorAllocator<T, Allocator, SmallVectorSize> {
|
||||
template<typename... Args>
|
||||
constexpr T &emplace_back(Args&&... args) noexcept(useNoexcept);
|
||||
|
||||
constexpr void push_back(const T &item) noexcept(useNoexcept);
|
||||
constexpr void push_back(T &&item) noexcept(useNoexcept);
|
||||
|
||||
constexpr void push_back(MaybeSV_t<T> const&item) noexcept(useNoexcept);
|
||||
|
||||
constexpr void pop_back() noexcept(useNoexcept);
|
||||
|
||||
@ -484,7 +486,7 @@ constexpr void Vector<T, SmallVectorSize, Allocator>::resize(std::size_t size) n
|
||||
}
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
constexpr bool Vector<T, SmallVectorSize, Allocator>::contains(const T &v) const noexcept(useNoexcept) {
|
||||
constexpr bool Vector<T, SmallVectorSize, Allocator>::contains(MaybeSV_t<T> const&v) const noexcept(useNoexcept) {
|
||||
for (std::size_t i = 0; i < m_size; i++) {
|
||||
if (m_items[i] == v) {
|
||||
return true;
|
||||
@ -496,7 +498,7 @@ constexpr bool Vector<T, SmallVectorSize, Allocator>::contains(const T &v) const
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
constexpr typename Vector<T, SmallVectorSize, Allocator>::template iterator<T&, T*, false>
|
||||
Vector<T, SmallVectorSize, Allocator>::insert(
|
||||
std::size_t pos, std::size_t cnt, const T &val) noexcept(useNoexcept) {
|
||||
std::size_t pos, std::size_t cnt, MaybeSV_t<T> const&val) noexcept(useNoexcept) {
|
||||
if (m_size + cnt > m_cap) {
|
||||
reserveInsert(m_cap ? m_size + cnt : initialCap, pos, cnt);
|
||||
if (pos < m_size) {
|
||||
@ -524,7 +526,7 @@ Vector<T, SmallVectorSize, Allocator>::insert(
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
constexpr typename Vector<T, SmallVectorSize, Allocator>::template iterator<T&, T*, false>
|
||||
Vector<T, SmallVectorSize, Allocator>::insert(std::size_t pos, const T &val) noexcept(useNoexcept) {
|
||||
Vector<T, SmallVectorSize, Allocator>::insert(std::size_t pos, MaybeSV_t<T> const&val) noexcept(useNoexcept) {
|
||||
if (m_size == m_cap) {
|
||||
reserveInsert(m_cap ? m_cap * 2 : initialCap, pos);
|
||||
if (pos < m_size) {
|
||||
@ -581,7 +583,16 @@ constexpr T &Vector<T, SmallVectorSize, Allocator>::emplace_back(Args&&... args)
|
||||
}
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
constexpr void Vector<T, SmallVectorSize, Allocator>::push_back(const T &item) noexcept(useNoexcept) {
|
||||
constexpr void Vector<T, SmallVectorSize, Allocator>::push_back(T &&item) noexcept(useNoexcept) {
|
||||
if (m_size == m_cap) {
|
||||
reserve(m_cap ? m_cap * 2 : initialCap);
|
||||
}
|
||||
std::construct_at(&m_items[m_size], std::move(item));
|
||||
++m_size;
|
||||
}
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
constexpr void Vector<T, SmallVectorSize, Allocator>::push_back(MaybeSV_t<T> const&item) noexcept(useNoexcept) {
|
||||
if (m_size == m_cap) {
|
||||
reserve(m_cap ? m_cap * 2 : initialCap);
|
||||
}
|
||||
|
3
deps/teagba/include/teagba/gfx.hpp
vendored
3
deps/teagba/include/teagba/gfx.hpp
vendored
@ -36,9 +36,6 @@ struct OX_ALIGN8 GbaSpriteAttrUpdate {
|
||||
|
||||
};
|
||||
|
||||
extern volatile uint16_t g_spriteUpdates;
|
||||
extern ox::Array<GbaSpriteAttrUpdate, 128> g_spriteBuffer;
|
||||
|
||||
void addSpriteUpdate(const GbaSpriteAttrUpdate &upd) noexcept;
|
||||
|
||||
void applySpriteUpdates() noexcept;
|
||||
|
4
deps/teagba/src/gfx.cpp
vendored
4
deps/teagba/src/gfx.cpp
vendored
@ -10,8 +10,8 @@
|
||||
|
||||
namespace teagba {
|
||||
|
||||
volatile uint16_t g_spriteUpdates = 0;
|
||||
ox::Array<GbaSpriteAttrUpdate, 128> g_spriteBuffer;
|
||||
static volatile uint16_t g_spriteUpdates = 0;
|
||||
static ox::Array<GbaSpriteAttrUpdate, 128> g_spriteBuffer;
|
||||
|
||||
void addSpriteUpdate(const GbaSpriteAttrUpdate &upd) noexcept {
|
||||
// block until g_spriteUpdates is less than buffer len
|
||||
|
@ -485,17 +485,14 @@ implements a superset of JSON.
|
||||
OrganicClaw requires support for 64 bit integers, whereas normal JSON
|
||||
technically does not.
|
||||
|
||||
These formats do not currently support floats.
|
||||
|
||||
There is also a wrapper format called Claw that provides a header at the
|
||||
beginning of the file and can dynamically switch between the two depending on
|
||||
what the header says is present.
|
||||
The Claw header also includes information about the type and type version of
|
||||
the data.
|
||||
|
||||
Except when the data is exported for loading on the GBA, Claw is always used as
|
||||
a wrapper around the bare formats.
|
||||
|
||||
These formats do not currently support ```float```s.
|
||||
|
||||
Claw header: ```M1;net.drinkingtea.nostalgia.core.NostalgiaPalette;1;```
|
||||
|
||||
That reads:
|
||||
@ -504,6 +501,9 @@ That reads:
|
||||
* Type ID is net.drinkingtea.nostalgia.core.NostalgiaPalette
|
||||
* Type version is 1
|
||||
|
||||
Except when the data is exported for loading on the GBA, Claw is always used as
|
||||
a wrapper around the bare formats.
|
||||
|
||||
#### Metal Claw Example
|
||||
|
||||
##### Read
|
||||
|
@ -14,7 +14,6 @@ O1;net.drinkingtea.ox.TypeDescriptor;1;{
|
||||
"typeId" : "B.uint64;0"
|
||||
}
|
||||
],
|
||||
"preloadable" : true,
|
||||
"primitiveType" : 6,
|
||||
"typeName" : "net.drinkingtea.ox.FileAddress.Data",
|
||||
"typeVersion" : 1
|
||||
|
@ -10,7 +10,6 @@ O1;net.drinkingtea.ox.TypeDescriptor;1;{
|
||||
"typeId" : "net.drinkingtea.ox.FileAddress.Data"
|
||||
}
|
||||
],
|
||||
"preloadable" : true,
|
||||
"primitiveType" : 5,
|
||||
"typeName" : "net.drinkingtea.ox.FileAddress",
|
||||
"typeVersion" : 1
|
||||
|
Binary file not shown.
@ -21,12 +21,13 @@ host_env = f'{os}-{arch}'
|
||||
with open(".current_build","r") as f:
|
||||
current_build = f.readlines()[0]
|
||||
|
||||
project_dir = sys.argv[1]
|
||||
project_name = sys.argv[2]
|
||||
bin = f'./build/{host_env}-{current_build}/bin/'
|
||||
nostalgia_bin = 'build/gba-release/bin/nostalgia.bin'
|
||||
nostalgia_project = sys.argv[1]
|
||||
nostalgia_gba = 'nostalgia.gba'
|
||||
project_bin = f'build/gba-release/bin/{project_name}.bin'
|
||||
project_gba = f'{project_name}.gba'
|
||||
|
||||
shutil.copyfile(nostalgia_bin, nostalgia_gba)
|
||||
shutil.copyfile(project_bin, project_gba)
|
||||
subprocess.run([
|
||||
f'{bin}/nost-pack', '-src', nostalgia_project, '-rom-bin', nostalgia_gba])
|
||||
subprocess.run(['gbafix', nostalgia_gba])
|
||||
f'{bin}/{project_name}-pack', '-src', project_dir, '-rom-bin', project_gba])
|
||||
subprocess.run(['gbafix', project_gba])
|
||||
|
@ -1,9 +1,2 @@
|
||||
include_directories(".")
|
||||
|
||||
if(TURBINE_BUILD_TYPE STREQUAL "Native")
|
||||
add_subdirectory(glutils)
|
||||
add_subdirectory(studio)
|
||||
endif()
|
||||
add_subdirectory(keel)
|
||||
add_subdirectory(nostalgia)
|
||||
add_subdirectory(turbine)
|
||||
add_subdirectory(olympic)
|
||||
|
@ -1,47 +0,0 @@
|
||||
|
||||
add_library(
|
||||
Keel
|
||||
asset.cpp
|
||||
keel.cpp
|
||||
media.cpp
|
||||
module.cpp
|
||||
pack.cpp
|
||||
typeconv.cpp
|
||||
typestore.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
Keel PUBLIC
|
||||
OxClaw
|
||||
OxEvent
|
||||
OxFS
|
||||
OxModel
|
||||
OxPreloader
|
||||
)
|
||||
|
||||
install(
|
||||
FILES
|
||||
asset.hpp
|
||||
assetmanager.hpp
|
||||
context.hpp
|
||||
keel.hpp
|
||||
media.hpp
|
||||
module.hpp
|
||||
pack.hpp
|
||||
typeconv.hpp
|
||||
typestore.hpp
|
||||
DESTINATION
|
||||
include/keel
|
||||
)
|
||||
|
||||
install(
|
||||
TARGETS
|
||||
Keel
|
||||
DESTINATION
|
||||
LIBRARY DESTINATION lib
|
||||
ARCHIVE DESTINATION lib
|
||||
)
|
||||
|
||||
if(TURBINE_BUILD_TYPE STREQUAL "Native")
|
||||
add_subdirectory(test)
|
||||
endif()
|
@ -3,7 +3,6 @@
|
||||
add_subdirectory(core)
|
||||
add_subdirectory(scene)
|
||||
|
||||
|
||||
# module libraries
|
||||
|
||||
# Keel
|
||||
@ -43,3 +42,11 @@ if(TURBINE_BUILD_TYPE STREQUAL "Native")
|
||||
include/nostalgia/modules
|
||||
)
|
||||
endif()
|
||||
|
||||
add_library(NostalgiaProfile INTERFACE)
|
||||
target_compile_definitions(
|
||||
NostalgiaProfile INTERFACE
|
||||
OLYMPIC_PROJECT_NAME="Nostalgia"
|
||||
OLYMPIC_PROJECT_NAMESPACE=nostalgia
|
||||
OLYMPIC_PROJECT_DATADIR=".nostalgia"
|
||||
)
|
||||
|
@ -5,9 +5,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <ox/std/types.hpp>
|
||||
#include <ox/std/point.hpp>
|
||||
|
||||
#include "context.hpp"
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
|
@ -15,19 +15,15 @@
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
// User Input Output
|
||||
class Context {
|
||||
|
||||
public:
|
||||
Context() noexcept = default;
|
||||
Context(Context &other) noexcept = delete;
|
||||
Context(const Context &other) noexcept = delete;
|
||||
Context(const Context &&other) noexcept = delete;
|
||||
virtual ~Context() noexcept = default;
|
||||
class Context;
|
||||
|
||||
struct ContextDeleter {
|
||||
void operator()(Context *p) noexcept;
|
||||
};
|
||||
|
||||
ox::Result<ox::UniquePtr<Context>> init(turbine::Context *tctx, const InitParams& = {}) noexcept;
|
||||
using ContextUPtr = ox::UPtr<Context, ContextDeleter>;
|
||||
|
||||
ox::Result<ContextUPtr> init(turbine::Context &tctx, InitParams const¶ms = {}) noexcept;
|
||||
|
||||
}
|
||||
|
||||
|
@ -36,48 +36,56 @@ oxModelBegin(Sprite)
|
||||
oxModelEnd()
|
||||
|
||||
[[nodiscard]]
|
||||
uint8_t bgStatus(Context *ctx) noexcept;
|
||||
uint8_t bgStatus(Context &ctx) noexcept;
|
||||
|
||||
void setBgStatus(Context *ctx, uint32_t status) noexcept;
|
||||
void setBgStatus(Context &ctx, uint32_t status) noexcept;
|
||||
|
||||
bool bgStatus(Context *ctx, unsigned bg) noexcept;
|
||||
bool bgStatus(Context &ctx, unsigned bg) noexcept;
|
||||
|
||||
void setBgStatus(Context *ctx, unsigned bg, bool status) noexcept;
|
||||
void setBgStatus(Context &ctx, unsigned bg, bool status) noexcept;
|
||||
|
||||
void setBgCbb(Context *ctx, unsigned bgIdx, unsigned cbb) noexcept;
|
||||
void setBgCbb(Context &ctx, unsigned bgIdx, unsigned cbb) noexcept;
|
||||
|
||||
/**
|
||||
* @param section describes which section of the selected TileSheetSpace to use (e.g. MEM_PALLETE_BG[section])
|
||||
*/
|
||||
ox::Error loadBgTileSheet(
|
||||
Context *ctx,
|
||||
Context &ctx,
|
||||
unsigned cbb,
|
||||
ox::FileAddress const&tilesheetAddr,
|
||||
ox::FileAddress const&paletteAddr = nullptr) noexcept;
|
||||
|
||||
ox::Error loadSpriteTileSheet(
|
||||
Context *ctx,
|
||||
Context &ctx,
|
||||
ox::FileAddress const&tilesheetAddr,
|
||||
ox::FileAddress const&paletteAddr) noexcept;
|
||||
|
||||
ox::Error initConsole(Context *ctx) noexcept;
|
||||
ox::Error initConsole(Context &ctx) noexcept;
|
||||
|
||||
void puts(Context *ctx, int column, int row, ox::CRStringView str) noexcept;
|
||||
void puts(Context &ctx, int column, int row, ox::CRStringView str) noexcept;
|
||||
|
||||
void setTile(Context *ctx, unsigned bgIdx, int column, int row, uint8_t tile) noexcept;
|
||||
void setTile(Context &ctx, unsigned bgIdx, int column, int row, uint8_t tile) noexcept;
|
||||
|
||||
void clearTileLayer(Context *ctx, unsigned bgIdx) noexcept;
|
||||
void clearTileLayer(Context &ctx, unsigned bgIdx) noexcept;
|
||||
|
||||
void hideSprite(Context *ctx, unsigned) noexcept;
|
||||
void hideSprite(Context &ctx, unsigned) noexcept;
|
||||
|
||||
void setSprite(Context *ctx, unsigned idx, int x, int y, unsigned tileIdx,
|
||||
void setSprite(Context &ctx, unsigned idx, int x, int y, unsigned tileIdx,
|
||||
unsigned spriteShape = 0, unsigned spriteSize = 0, unsigned flipX = 0) noexcept;
|
||||
|
||||
void setSprite(Context *ctx, Sprite const&s) noexcept;
|
||||
void setSprite(Context &ctx, Sprite const&s) noexcept;
|
||||
|
||||
}
|
||||
|
||||
namespace nostalgia::core::gl {
|
||||
void drawMainView(core::Context&, ox::Size const&) noexcept;
|
||||
}
|
||||
|
||||
constexpr ox::CStringView GlslVersion = "#version 330";
|
||||
|
||||
[[nodiscard]]
|
||||
ox::Size drawSize(int scale = 5) noexcept;
|
||||
|
||||
void draw(core::Context &ctx, ox::Size const&renderSz) noexcept;
|
||||
|
||||
void draw(core::Context&, int scale = 5) noexcept;
|
||||
|
||||
}
|
||||
|
@ -8,12 +8,11 @@
|
||||
#include <ox/std/point.hpp>
|
||||
#include <ox/std/size.hpp>
|
||||
#include <ox/std/types.hpp>
|
||||
#include <ox/std/vector.hpp>
|
||||
#include <ox/model/def.hpp>
|
||||
|
||||
|
||||
#include "color.hpp"
|
||||
#include "context.hpp"
|
||||
#include "ptidxconv.hpp"
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ox/fs/fs.hpp>
|
||||
#include <ox/std/array.hpp>
|
||||
#include <ox/std/point.hpp>
|
||||
#include <ox/std/size.hpp>
|
||||
@ -11,10 +12,8 @@
|
||||
#include <ox/std/types.hpp>
|
||||
#include <ox/model/def.hpp>
|
||||
|
||||
#include <nostalgia/core/ptidxconv.hpp>
|
||||
|
||||
#include "color.hpp"
|
||||
#include "context.hpp"
|
||||
#include "ptidxconv.hpp"
|
||||
#include "palette.hpp"
|
||||
|
||||
namespace nostalgia::core {
|
||||
@ -96,7 +95,7 @@ struct TileSheet {
|
||||
SubSheet &operator=(SubSheet &&other) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
std::size_t idx(const ox::Point &pt) const noexcept;
|
||||
std::size_t idx(ox::Point const&pt) const noexcept;
|
||||
|
||||
/**
|
||||
* Reads all pixels of this sheet or its children into the given pixel list
|
||||
@ -160,7 +159,7 @@ struct TileSheet {
|
||||
|
||||
void setPixel(int8_t pBpp, uint64_t idx, uint8_t palIdx) noexcept;
|
||||
|
||||
void setPixel(int8_t pBpp, const ox::Point &pt, uint8_t palIdx) noexcept;
|
||||
void setPixel(int8_t pBpp, ox::Point const&pt, uint8_t palIdx) noexcept;
|
||||
|
||||
ox::Error setPixelCount(int8_t pBpp, std::size_t cnt) noexcept;
|
||||
|
||||
@ -175,19 +174,16 @@ struct TileSheet {
|
||||
/**
|
||||
* Gets the offset in tiles of the desired subsheet.
|
||||
*/
|
||||
[[nodiscard]]
|
||||
ox::Result<unsigned> getTileOffset(
|
||||
ox::SpanView<ox::StringView> const&pNamePath,
|
||||
int8_t pBpp,
|
||||
std::size_t pIt = 0,
|
||||
unsigned pCurrentTotal = 0) const noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
ox::Result<SubSheetId> getIdFor(
|
||||
ox::SpanView<ox::StringView> const&pNamePath,
|
||||
std::size_t pIt = 0) const noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
ox::Result<ox::StringView> getNameFor(SubSheetId pId) const noexcept;
|
||||
|
||||
};
|
||||
@ -200,7 +196,7 @@ struct TileSheet {
|
||||
SubSheet subsheet{0, "Root", 1, 1, bpp};
|
||||
|
||||
constexpr TileSheet() noexcept = default;
|
||||
TileSheet(const TileSheet &other) noexcept = default;
|
||||
TileSheet(TileSheet const&other) noexcept = default;
|
||||
inline TileSheet(TileSheet &&other) noexcept:
|
||||
bpp(other.bpp),
|
||||
idIt(other.idIt),
|
||||
@ -208,13 +204,13 @@ struct TileSheet {
|
||||
subsheet(std::move(other.subsheet)) {
|
||||
}
|
||||
|
||||
TileSheet &operator=(const TileSheet &other) noexcept;
|
||||
TileSheet &operator=(TileSheet const&other) noexcept;
|
||||
|
||||
TileSheet &operator=(TileSheet &&other) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
SubSheetIdx validateSubSheetIdx(
|
||||
const SubSheetIdx &pIdx,
|
||||
SubSheetIdx const&pIdx,
|
||||
std::size_t pIdxIt,
|
||||
const SubSheet *pSubsheet) noexcept;
|
||||
|
||||
@ -229,43 +225,43 @@ struct TileSheet {
|
||||
SubSheetIdx validateSubSheetIdx(const SubSheetIdx &idx) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
static const SubSheet &getSubSheet(
|
||||
const SubSheetIdx &idx,
|
||||
static SubSheet const&getSubSheet(
|
||||
SubSheetIdx const&idx,
|
||||
std::size_t idxIt,
|
||||
const SubSheet *pSubsheet) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
static SubSheet &getSubSheet(
|
||||
const SubSheetIdx &idx,
|
||||
SubSheetIdx const&idx,
|
||||
std::size_t idxIt,
|
||||
SubSheet *pSubsheet) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
const SubSheet &getSubSheet(const SubSheetIdx &idx) const noexcept;
|
||||
const SubSheet &getSubSheet(SubSheetIdx const&idx) const noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
SubSheet &getSubSheet(const SubSheetIdx &idx) noexcept;
|
||||
SubSheet &getSubSheet(SubSheetIdx const&idx) noexcept;
|
||||
|
||||
ox::Error addSubSheet(const SubSheetIdx &idx) noexcept;
|
||||
ox::Error addSubSheet(SubSheetIdx const&idx) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
static ox::Error rmSubSheet(
|
||||
const SubSheetIdx &idx,
|
||||
SubSheetIdx const&idx,
|
||||
std::size_t idxIt,
|
||||
SubSheet *pSubsheet) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
ox::Error rmSubSheet(const SubSheetIdx &idx) noexcept;
|
||||
ox::Error rmSubSheet(SubSheetIdx const&idx) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
uint8_t getPixel4Bpp(
|
||||
const ox::Point &pt,
|
||||
const SubSheetIdx &subsheetIdx) const noexcept;
|
||||
ox::Point const&pt,
|
||||
SubSheetIdx const&subsheetIdx) const noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
uint8_t getPixel8Bpp(
|
||||
const ox::Point &pt,
|
||||
const SubSheetIdx &subsheetIdx) const noexcept;
|
||||
ox::Point const&pt,
|
||||
SubSheetIdx const&subsheetIdx) const noexcept;
|
||||
|
||||
ox::Result<SubSheetId> getIdFor(ox::CRStringView path) const noexcept;
|
||||
|
||||
@ -278,6 +274,8 @@ struct TileSheet {
|
||||
|
||||
};
|
||||
|
||||
using TileSheetV3 = TileSheet;
|
||||
|
||||
struct CompactTileSheet {
|
||||
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.CompactTileSheet";
|
||||
static constexpr auto TypeVersion = 1;
|
||||
@ -309,7 +307,7 @@ oxModelBegin(TileSheetV2)
|
||||
oxModelField(subsheet)
|
||||
oxModelEnd()
|
||||
|
||||
oxModelBegin(TileSheet::SubSheet)
|
||||
oxModelBegin(TileSheetV3::SubSheet)
|
||||
oxModelField(name);
|
||||
oxModelField(rows);
|
||||
oxModelField(columns);
|
||||
@ -317,7 +315,7 @@ oxModelBegin(TileSheet::SubSheet)
|
||||
oxModelField(pixels)
|
||||
oxModelEnd()
|
||||
|
||||
oxModelBegin(TileSheet)
|
||||
oxModelBegin(TileSheetV3)
|
||||
oxModelField(bpp)
|
||||
oxModelField(idIt)
|
||||
oxModelField(defaultPalette)
|
||||
|
@ -12,9 +12,10 @@ target_link_libraries(
|
||||
NostalgiaCore-GBA PUBLIC
|
||||
TeaGBA
|
||||
Keel
|
||||
Turbine
|
||||
)
|
||||
|
||||
if(TURBINE_BUILD_TYPE STREQUAL "GBA")
|
||||
set_source_files_properties(gfx.cpp PROPERTIES COMPILE_FLAGS -marm)
|
||||
target_link_libraries(NostalgiaCore PUBLIC NostalgiaCore-GBA)
|
||||
endif()
|
||||
endif()
|
||||
|
@ -8,15 +8,19 @@
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
GbaContext::GbaContext(turbine::Context *tctx) noexcept: turbineCtx(tctx) {
|
||||
void ContextDeleter::operator()(Context *p) noexcept {
|
||||
ox::safeDelete(p);
|
||||
}
|
||||
|
||||
ox::Error initGfx(Context *ctx, InitParams const&) noexcept;
|
||||
Context::Context(turbine::Context &tctx) noexcept: turbineCtx(tctx) {
|
||||
}
|
||||
|
||||
ox::Result<ox::UniquePtr<Context>> init(turbine::Context *tctx, InitParams const¶ms) noexcept {
|
||||
auto ctx = ox::make_unique<GbaContext>(tctx);
|
||||
oxReturnError(initGfx(ctx.get(), params));
|
||||
return ox::UPtr<Context>(ctx.release());
|
||||
ox::Error initGfx(Context &ctx, InitParams const&) noexcept;
|
||||
|
||||
ox::Result<ContextUPtr> init(turbine::Context &tctx, InitParams const¶ms) noexcept {
|
||||
auto ctx = ox::make_unique<Context>(tctx);
|
||||
oxReturnError(initGfx(*ctx, params));
|
||||
return ContextUPtr(std::move(ctx));
|
||||
}
|
||||
|
||||
}
|
@ -8,16 +8,21 @@
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
struct GbaContext: public core::Context {
|
||||
class Context {
|
||||
|
||||
turbine::Context const*turbineCtx = nullptr;
|
||||
public:
|
||||
turbine::Context &turbineCtx;
|
||||
|
||||
explicit GbaContext(turbine::Context *tctx) noexcept;
|
||||
explicit Context(turbine::Context &tctx) noexcept;
|
||||
Context(Context &other) noexcept = delete;
|
||||
Context(Context const&other) noexcept = delete;
|
||||
Context(Context const&&other) noexcept = delete;
|
||||
virtual ~Context() noexcept = default;
|
||||
|
||||
[[nodiscard]]
|
||||
auto const&rom() const noexcept {
|
||||
return *turbine::rom(*turbineCtx);
|
||||
}
|
||||
[[nodiscard]]
|
||||
ox::MemFS const&rom() const noexcept {
|
||||
return static_cast<ox::MemFS const&>(*turbine::rom(turbineCtx));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
@ -71,44 +71,45 @@ constexpr ox::Error model(auto *io, ox::CommonPtrWith<GbaTileMapTarget> auto *t)
|
||||
return io->template field<uint8_t, decltype(handleTileMap)>("tileMap", handleTileMap);
|
||||
}
|
||||
|
||||
ox::Error initGfx(Context*, InitParams const&) noexcept {
|
||||
ox::Error initGfx(Context&, InitParams const&) noexcept {
|
||||
for (auto bgCtl = ®_BG0CTL; bgCtl <= ®_BG3CTL; bgCtl += 2) {
|
||||
teagba::bgSetSbb(bgCtl, 28);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void shutdownGfx(Context*) noexcept {
|
||||
}
|
||||
|
||||
uint8_t bgStatus(Context*) noexcept {
|
||||
uint8_t bgStatus(Context&) noexcept {
|
||||
return (REG_DISPCTL >> 8u) & 0b1111u;
|
||||
}
|
||||
|
||||
void setBgStatus(Context*, uint32_t status) noexcept {
|
||||
void setBgStatus(Context&, uint32_t status) noexcept {
|
||||
constexpr auto BgStatus = 8;
|
||||
REG_DISPCTL = (REG_DISPCTL & ~0b111100000000u) | status << BgStatus;
|
||||
}
|
||||
|
||||
bool bgStatus(Context*, unsigned bg) noexcept {
|
||||
bool bgStatus(Context&, unsigned bg) noexcept {
|
||||
return (REG_DISPCTL >> (8 + bg)) & 1;
|
||||
}
|
||||
|
||||
void setBgStatus(Context*, unsigned bg, bool status) noexcept {
|
||||
void setBgStatus(Context&, unsigned bg, bool status) noexcept {
|
||||
constexpr auto Bg0Status = 8;
|
||||
const auto mask = static_cast<uint32_t>(status) << (Bg0Status + bg);
|
||||
REG_DISPCTL = REG_DISPCTL | ((REG_DISPCTL & ~mask) | mask);
|
||||
}
|
||||
|
||||
void setBgCbb(Context*, unsigned bgIdx, unsigned cbb) noexcept {
|
||||
static void setBgCbb(Context*, unsigned bgIdx, unsigned cbb) noexcept {
|
||||
auto &bgCtl = regBgCtl(bgIdx);
|
||||
const auto &cbbData = g_cbbData[cbb];
|
||||
teagba::bgSetBpp(&bgCtl, cbbData.bpp);
|
||||
teagba::bgSetCbb(&bgCtl, cbb);
|
||||
}
|
||||
|
||||
void setBgCbb(Context&, unsigned bgIdx, unsigned cbb) noexcept {
|
||||
setBgCbb(nullptr, bgIdx, cbb);
|
||||
}
|
||||
|
||||
static ox::Error loadBgTileSheet(
|
||||
const ox::MemFS &rom,
|
||||
ox::MemFS const&rom,
|
||||
unsigned cbb,
|
||||
ox::FileAddress const&tilesheetAddr,
|
||||
ox::FileAddress const&paletteAddr) noexcept {
|
||||
@ -136,22 +137,20 @@ static ox::Error loadBgTileSheet(
|
||||
}
|
||||
|
||||
ox::Error loadBgTileSheet(
|
||||
Context *ctx,
|
||||
Context &ctx,
|
||||
unsigned cbb,
|
||||
ox::FileAddress const&tilesheetAddr,
|
||||
ox::FileAddress const&paletteAddr) noexcept {
|
||||
auto &gctx = static_cast<GbaContext&>(*ctx);
|
||||
auto &rom = static_cast<const ox::MemFS&>(gctx.rom());
|
||||
auto &rom = ctx.rom();
|
||||
return loadBgTileSheet(rom, cbb, tilesheetAddr, paletteAddr);
|
||||
}
|
||||
|
||||
ox::Error loadSpriteTileSheet(
|
||||
Context *ctx,
|
||||
Context &ctx,
|
||||
ox::FileAddress const&tilesheetAddr,
|
||||
ox::FileAddress const&paletteAddr) noexcept {
|
||||
auto &gctx = static_cast<GbaContext&>(*ctx);
|
||||
auto &rom = static_cast<const ox::MemFS&>(gctx.rom());
|
||||
oxRequire(tsStat, gctx.rom().stat(tilesheetAddr));
|
||||
auto &rom = ctx.rom();
|
||||
oxRequire(tsStat, ctx.rom().stat(tilesheetAddr));
|
||||
oxRequire(ts, rom.directAccess(tilesheetAddr));
|
||||
GbaTileMapTarget target;
|
||||
target.pal.palette = MEM_SPRITE_PALETTE;
|
||||
@ -159,27 +158,25 @@ ox::Error loadSpriteTileSheet(
|
||||
oxReturnError(ox::readMC(ts, static_cast<std::size_t>(tsStat.size), &target));
|
||||
// load external palette if available
|
||||
if (paletteAddr) {
|
||||
oxRequire(palStat, gctx.rom().stat(paletteAddr));
|
||||
oxRequire(palStat, ctx.rom().stat(paletteAddr));
|
||||
oxRequire(pal, rom.directAccess(paletteAddr));
|
||||
oxReturnError(ox::readMC(pal, static_cast<std::size_t>(palStat.size), &target.pal));
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
ox::Error loadBgPalette(Context *ctx, unsigned, ox::FileAddress const&paletteAddr) noexcept {
|
||||
auto &gctx = static_cast<GbaContext&>(*ctx);
|
||||
auto &rom = static_cast<const ox::MemFS&>(gctx.rom());
|
||||
ox::Error loadBgPalette(Context &ctx, unsigned, ox::FileAddress const&paletteAddr) noexcept {
|
||||
auto &rom = ctx.rom();
|
||||
GbaPaletteTarget target;
|
||||
target.palette = MEM_BG_PALETTE;
|
||||
oxRequire(palStat, gctx.rom().stat(paletteAddr));
|
||||
oxRequire(palStat, ctx.rom().stat(paletteAddr));
|
||||
oxRequire(pal, rom.directAccess(paletteAddr));
|
||||
oxReturnError(ox::readMC(pal, static_cast<std::size_t>(palStat.size), &target));
|
||||
return {};
|
||||
}
|
||||
|
||||
ox::Error loadSpritePalette(Context *ctx, unsigned cbb, ox::FileAddress const&paletteAddr) noexcept {
|
||||
auto &gctx = static_cast<GbaContext&>(*ctx);
|
||||
auto &rom = static_cast<const ox::MemFS&>(gctx.rom());
|
||||
ox::Error loadSpritePalette(Context &ctx, unsigned cbb, ox::FileAddress const&paletteAddr) noexcept {
|
||||
auto &rom = ctx.rom();
|
||||
GbaPaletteTarget target;
|
||||
target.palette = &MEM_SPRITE_PALETTE[cbb];
|
||||
oxRequire(palStat, rom.stat(paletteAddr));
|
||||
@ -188,25 +185,16 @@ ox::Error loadSpritePalette(Context *ctx, unsigned cbb, ox::FileAddress const&pa
|
||||
return {};
|
||||
}
|
||||
|
||||
// Do NOT rely on Context in the GBA version of this function.
|
||||
ox::Error initConsole(Context *ctx) noexcept {
|
||||
constexpr ox::FileAddress TilesheetAddr("/TileSheets/Charset.ng");
|
||||
constexpr ox::FileAddress PaletteAddr("/Palettes/Charset.npal");
|
||||
ox::Error initConsole(Context &ctx) noexcept {
|
||||
constexpr ox::FileAddress TilesheetAddr = ox::StringLiteral("/TileSheets/Charset.ng");
|
||||
constexpr ox::FileAddress PaletteAddr = ox::StringLiteral("/Palettes/Charset.npal");
|
||||
setBgStatus(ctx, 0b0001);
|
||||
if (!ctx) {
|
||||
oxRequire(rom, keel::loadRom());
|
||||
const ox::FileSystem32 romFs(ox::FileStore32(rom, 32 * ox::units::MB));
|
||||
oxReturnError(loadBgTileSheet(romFs, 0, TilesheetAddr, PaletteAddr));
|
||||
setBgCbb(nullptr, 0, 0);
|
||||
return {};
|
||||
} else {
|
||||
oxReturnError(loadBgTileSheet(ctx, 0, TilesheetAddr, PaletteAddr));
|
||||
setBgCbb(ctx, 0, 0);
|
||||
return {};
|
||||
}
|
||||
oxReturnError(loadBgTileSheet(ctx, 0, TilesheetAddr, PaletteAddr));
|
||||
setBgCbb(ctx, 0, 0);
|
||||
return {};
|
||||
}
|
||||
|
||||
void puts(Context *ctx, int column, int row, ox::CRStringView str) noexcept {
|
||||
void puts(Context &ctx, int column, int row, ox::CRStringView str) noexcept {
|
||||
const auto col = static_cast<unsigned>(column);
|
||||
for (auto i = 0u; i < str.bytes(); i++) {
|
||||
const auto c = charMap[static_cast<std::size_t>(str[i])];
|
||||
@ -214,18 +202,18 @@ void puts(Context *ctx, int column, int row, ox::CRStringView str) noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
void setTile(Context*, unsigned bgIdx, int column, int row, uint8_t tile) noexcept {
|
||||
void setTile(Context&, unsigned bgIdx, int column, int row, uint8_t tile) noexcept {
|
||||
const auto tileIdx = static_cast<std::size_t>(row * GbaTileColumns + column);
|
||||
MEM_BG_MAP[bgIdx][tileIdx] = tile;
|
||||
}
|
||||
|
||||
// Do NOT use Context in the GBA version of this function.
|
||||
void clearTileLayer(Context*, unsigned bgIdx) noexcept {
|
||||
void clearTileLayer(Context&, unsigned bgIdx) noexcept {
|
||||
memset(MEM_BG_MAP[bgIdx].data(), 0, GbaTileRows * GbaTileColumns);
|
||||
}
|
||||
|
||||
[[maybe_unused]]
|
||||
void hideSprite(Context*, unsigned idx) noexcept {
|
||||
void hideSprite(Context&, unsigned idx) noexcept {
|
||||
//oxAssert(g_spriteUpdates < config::GbaSpriteBufferLen, "Sprite update buffer overflow");
|
||||
teagba::GbaSpriteAttrUpdate oa;
|
||||
oa.attr0 = 2 << 8;
|
||||
@ -233,7 +221,7 @@ void hideSprite(Context*, unsigned idx) noexcept {
|
||||
teagba::addSpriteUpdate(oa);
|
||||
}
|
||||
|
||||
void setSprite(Context*,
|
||||
void setSprite(Context&,
|
||||
unsigned idx,
|
||||
int x,
|
||||
int y,
|
||||
|
@ -7,5 +7,5 @@
|
||||
#include <nostalgia/core/context.hpp>
|
||||
|
||||
namespace nostalgia::core {
|
||||
ox::Error initGfx(Context *ctx, InitParams const&) noexcept;
|
||||
ox::Error initGfx(Context &ctx, InitParams const&) noexcept;
|
||||
}
|
||||
|
@ -3,33 +3,44 @@
|
||||
*/
|
||||
|
||||
|
||||
#include <nostalgia/core/core.hpp>
|
||||
#include <ox/std/def.hpp>
|
||||
|
||||
#include <keel/media.hpp>
|
||||
#include <turbine/turbine.hpp>
|
||||
|
||||
#include <teagba/addresses.hpp>
|
||||
#include <teagba/bios.hpp>
|
||||
#include <teagba/gfx.hpp>
|
||||
|
||||
#include <nostalgia/core/core.hpp>
|
||||
|
||||
#include "gfx.hpp"
|
||||
|
||||
#define HEAP_BEGIN (reinterpret_cast<char*>(MEM_EWRAM_BEGIN))
|
||||
#define HEAP_SIZE ((MEM_EWRAM_END - MEM_EWRAM_BEGIN) / 2)
|
||||
#define HEAP_END (reinterpret_cast<char*>(MEM_EWRAM_BEGIN + HEAP_SIZE))
|
||||
|
||||
namespace ox {
|
||||
|
||||
using namespace nostalgia::core;
|
||||
|
||||
void panic(const char *file, int line, const char *panicMsg, ox::Error const&err) noexcept {
|
||||
oxIgnoreError(initGfx(nullptr, {}));
|
||||
oxIgnoreError(initConsole(nullptr));
|
||||
// enable only BG 0
|
||||
REG_DISPCTL = teagba::DispCtl_Bg0;
|
||||
clearTileLayer(nullptr, 0);
|
||||
// reset heap to make sure we have enough memory to allocate context data
|
||||
ox::heapmgr::initHeap(HEAP_BEGIN, HEAP_END);
|
||||
auto tctx = turbine::init(keel::loadRomFs("").unwrap(), "Nostalgia").unwrap();
|
||||
auto ctx = init(*tctx).unwrap();
|
||||
oxIgnoreError(initGfx(*ctx, {}));
|
||||
oxIgnoreError(initConsole(*ctx));
|
||||
setBgStatus(*ctx, 0, true);
|
||||
clearTileLayer(*ctx, 0);
|
||||
ox::BString<23> serr = "Error code: ";
|
||||
serr += static_cast<int64_t>(err);
|
||||
puts(nullptr, 32 + 1, 1, "SADNESS...");
|
||||
puts(nullptr, 32 + 1, 4, "UNEXPECTED STATE:");
|
||||
puts(nullptr, 32 + 2, 6, panicMsg);
|
||||
puts(*ctx, 32 + 1, 1, "SADNESS...");
|
||||
puts(*ctx, 32 + 1, 4, "UNEXPECTED STATE:");
|
||||
puts(*ctx, 32 + 2, 6, panicMsg);
|
||||
if (err) {
|
||||
puts(nullptr, 32 + 2, 8, serr);
|
||||
puts(*ctx, 32 + 2, 8, serr);
|
||||
}
|
||||
puts(nullptr, 32 + 1, 15, "PLEASE RESTART THE SYSTEM");
|
||||
puts(*ctx, 32 + 1, 15, "PLEASE RESTART THE SYSTEM");
|
||||
// print to terminal if in mGBA
|
||||
oxErrf("\033[31;1;1mPANIC:\033[0m [{}:{}]: {}\n", file, line, panicMsg);
|
||||
if (err.msg) {
|
||||
|
@ -43,7 +43,7 @@ ox::Array<char, 128> charMap = {
|
||||
0, // space
|
||||
38, // !
|
||||
0, // "
|
||||
0, // #
|
||||
49, // #
|
||||
0, // $
|
||||
0, // %
|
||||
0, // &
|
||||
@ -132,12 +132,12 @@ ox::Array<char, 128> charMap = {
|
||||
25, // y
|
||||
26, // z
|
||||
46, // {
|
||||
0, // |
|
||||
51, // |
|
||||
48, // }
|
||||
0, // ~
|
||||
50, // ~
|
||||
};
|
||||
|
||||
void setSprite(Context *c, const Sprite &s) noexcept {
|
||||
void setSprite(Context &c, Sprite const&s) noexcept {
|
||||
setSprite(c, s.idx, s.x, s.y, s.tileIdx, s.spriteShape, s.spriteSize, s.flipX);
|
||||
}
|
||||
|
||||
|
@ -17,14 +17,14 @@ namespace nostalgia::core {
|
||||
class KeelModule: public keel::Module {
|
||||
private:
|
||||
NostalgiaPaletteToPaletteConverter m_nostalgiaPaletteToPaletteConverter;
|
||||
TileSheetV1ToTileSheetConverter m_tileSheetV1ToTileSheetV2Converter;
|
||||
TileSheetV1ToTileSheetV2Converter m_tileSheetV1ToTileSheetV2Converter;
|
||||
TileSheetV2ToTileSheetV3Converter m_tileSheetV2ToTileSheetConverter;
|
||||
TileSheetToCompactTileSheetConverter m_tileSheetToCompactTileSheetConverter;
|
||||
TileSheetV2ToTileSheetConverter m_tileSheetV2ToTileSheetConverter;
|
||||
|
||||
public:
|
||||
[[nodiscard]]
|
||||
ox::String id() const noexcept override {
|
||||
return "net.drinkingtea.nostalgia.core";
|
||||
return ox::String("net.drinkingtea.nostalgia.core");
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
@ -52,15 +52,15 @@ class KeelModule: public keel::Module {
|
||||
ox::Vector<keel::PackTransform> packTransforms() const noexcept final {
|
||||
return {
|
||||
// convert tilesheets to CompactTileSheets
|
||||
[](keel::Context *ctx, ox::Buffer *buff) -> ox::Error {
|
||||
oxRequire(hdr, keel::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(keel::convertBuffToBuff<core::CompactTileSheet>(
|
||||
ctx, *buff, ox::ClawFormat::Metal).moveTo(buff));
|
||||
ctx, buff, ox::ClawFormat::Metal).moveTo(&buff));
|
||||
}
|
||||
return {};
|
||||
},
|
||||
|
@ -7,60 +7,59 @@
|
||||
namespace nostalgia::core {
|
||||
|
||||
ox::Error NostalgiaPaletteToPaletteConverter::convert(
|
||||
keel::Context*,
|
||||
NostalgiaPalette *src,
|
||||
Palette *dst) const noexcept {
|
||||
dst->colors = std::move(src->colors);
|
||||
keel::Context&,
|
||||
NostalgiaPalette &src,
|
||||
Palette &dst) const noexcept {
|
||||
dst.colors = std::move(src.colors);
|
||||
return {};
|
||||
}
|
||||
|
||||
ox::Error TileSheetV1ToTileSheetConverter::convert(
|
||||
keel::Context*,
|
||||
TileSheetV1 *src,
|
||||
TileSheet *dst) const noexcept {
|
||||
dst->bpp = src->bpp;
|
||||
dst->defaultPalette = std::move(src->defaultPalette);
|
||||
dst->subsheet.name = "Root";
|
||||
dst->subsheet.rows = src->rows;
|
||||
dst->subsheet.columns = src->columns;
|
||||
dst->subsheet.pixels = std::move(src->pixels);
|
||||
ox::Error TileSheetV1ToTileSheetV2Converter::convert(
|
||||
keel::Context&,
|
||||
TileSheetV1 &src,
|
||||
TileSheetV2 &dst) const noexcept {
|
||||
dst.bpp = src.bpp;
|
||||
dst.defaultPalette = std::move(src.defaultPalette);
|
||||
dst.subsheet.name = "Root";
|
||||
dst.subsheet.rows = src.rows;
|
||||
dst.subsheet.columns = src.columns;
|
||||
dst.subsheet.pixels = std::move(src.pixels);
|
||||
return {};
|
||||
}
|
||||
|
||||
void TileSheetV2ToTileSheetV3Converter::convertSubsheet(
|
||||
TileSheetV2::SubSheet &src,
|
||||
TileSheetV3::SubSheet &dst,
|
||||
SubSheetId &idIt) noexcept {
|
||||
dst.id = idIt;
|
||||
dst.name = std::move(src.name);
|
||||
dst.columns = src.columns;
|
||||
dst.rows = src.rows;
|
||||
dst.pixels = std::move(src.pixels);
|
||||
++idIt;
|
||||
dst.subsheets.resize(src.subsheets.size());
|
||||
for (auto i = 0u; i < src.subsheets.size(); ++i) {
|
||||
convertSubsheet(src.subsheets[i], dst.subsheets[i], idIt);
|
||||
}
|
||||
}
|
||||
|
||||
ox::Error TileSheetV2ToTileSheetV3Converter::convert(
|
||||
keel::Context&,
|
||||
TileSheetV2 &src,
|
||||
TileSheetV3 &dst) const noexcept {
|
||||
dst.bpp = src.bpp;
|
||||
dst.defaultPalette = std::move(src.defaultPalette);
|
||||
convertSubsheet(src.subsheet, dst.subsheet, dst.idIt);
|
||||
return {};
|
||||
}
|
||||
|
||||
ox::Error TileSheetToCompactTileSheetConverter::convert(
|
||||
keel::Context*,
|
||||
TileSheet *src,
|
||||
CompactTileSheet *dst) const noexcept {
|
||||
dst->bpp = src->bpp;
|
||||
dst->defaultPalette = std::move(src->defaultPalette);
|
||||
dst->pixels = src->pixels();
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
void TileSheetV2ToTileSheetConverter::convertSubsheet(
|
||||
TileSheetV2::SubSheet *src,
|
||||
TileSheet::SubSheet *dst,
|
||||
SubSheetId *idIt) noexcept {
|
||||
dst->id = *idIt;
|
||||
dst->name = std::move(src->name);
|
||||
dst->columns = src->columns;
|
||||
dst->rows = src->rows;
|
||||
dst->pixels = std::move(src->pixels);
|
||||
++*idIt;
|
||||
dst->subsheets.resize(src->subsheets.size());
|
||||
for (auto i = 0u; i < src->subsheets.size(); ++i) {
|
||||
convertSubsheet(&src->subsheets[i], &dst->subsheets[i], idIt);
|
||||
}
|
||||
}
|
||||
|
||||
ox::Error TileSheetV2ToTileSheetConverter::convert(
|
||||
keel::Context*,
|
||||
TileSheetV2 *src,
|
||||
TileSheet *dst) const noexcept {
|
||||
dst->bpp = src->bpp;
|
||||
dst->defaultPalette = std::move(src->defaultPalette);
|
||||
convertSubsheet(&src->subsheet, &dst->subsheet, &dst->idIt);
|
||||
keel::Context&,
|
||||
TileSheet &src,
|
||||
CompactTileSheet &dst) const noexcept {
|
||||
dst.bpp = src.bpp;
|
||||
dst.defaultPalette = std::move(src.defaultPalette);
|
||||
dst.pixels = src.pixels();
|
||||
return {};
|
||||
}
|
||||
|
||||
|
@ -17,25 +17,23 @@ namespace nostalgia::core {
|
||||
// Type converters
|
||||
|
||||
class NostalgiaPaletteToPaletteConverter: public keel::Converter<NostalgiaPalette, Palette> {
|
||||
ox::Error convert(keel::Context*, NostalgiaPalette *src, Palette *dst) const noexcept final;
|
||||
ox::Error convert(keel::Context&, NostalgiaPalette &src, Palette &dst) const noexcept final;
|
||||
};
|
||||
|
||||
class TileSheetV1ToTileSheetConverter: public keel::Converter<TileSheetV1, TileSheet> {
|
||||
ox::Error convert(keel::Context*, TileSheetV1 *src, TileSheet *dst) const noexcept final;
|
||||
class TileSheetV1ToTileSheetV2Converter: public keel::Converter<TileSheetV1, TileSheetV2> {
|
||||
ox::Error convert(keel::Context&, TileSheetV1 &src, TileSheetV2 &dst) const noexcept final;
|
||||
};
|
||||
|
||||
class TileSheetV2ToTileSheetV3Converter: public keel::Converter<TileSheetV2, TileSheetV3> {
|
||||
static void convertSubsheet(
|
||||
TileSheetV2::SubSheet &src,
|
||||
TileSheetV3::SubSheet &dst,
|
||||
SubSheetId &idIt) noexcept;
|
||||
ox::Error convert(keel::Context&, TileSheetV2 &src, TileSheetV3 &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 keel::Converter<TileSheetV2, TileSheet> {
|
||||
static void convertSubsheet(
|
||||
TileSheetV2::SubSheet *src,
|
||||
TileSheet::SubSheet *dst,
|
||||
SubSheetId *idIt) noexcept;
|
||||
|
||||
ox::Error convert(keel::Context*, TileSheetV2 *src, TileSheet *dst) const noexcept final;
|
||||
|
||||
ox::Error convert(keel::Context&, TileSheet &src, CompactTileSheet &dst) const noexcept final;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -7,19 +7,23 @@
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
GlContext::GlContext(turbine::Context &tctx) noexcept:
|
||||
void ContextDeleter::operator()(Context *p) noexcept {
|
||||
ox::safeDelete(p);
|
||||
}
|
||||
|
||||
Context::Context(turbine::Context &tctx) noexcept:
|
||||
turbineCtx(tctx),
|
||||
drawer(*this) {
|
||||
}
|
||||
|
||||
GlContext::~GlContext() noexcept {
|
||||
Context::~Context() noexcept {
|
||||
shutdownGfx(*this);
|
||||
}
|
||||
|
||||
ox::Result<ox::UniquePtr<Context>> init(turbine::Context *tctx, InitParams const¶ms) noexcept {
|
||||
auto ctx = ox::make_unique<GlContext>(*tctx);
|
||||
oxReturnError(initGfx(ctx.get(), params));
|
||||
return ox::UPtr<Context>(ctx.release());
|
||||
ox::Result<ContextUPtr> init(turbine::Context &tctx, InitParams const¶ms) noexcept {
|
||||
auto ctx = ox::make_unique<Context>(tctx);
|
||||
oxReturnError(initGfx(*ctx, params));
|
||||
return ContextUPtr(ctx.release());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -15,18 +15,19 @@
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
struct GlContext: public core::Context {
|
||||
turbine::Context &turbineCtx;
|
||||
glutils::GLProgram bgShader;
|
||||
glutils::GLProgram spriteShader;
|
||||
ox::Array<renderer::CBB, 4> cbbs;
|
||||
renderer::SpriteBlockset spriteBlocks;
|
||||
ox::Array<Sprite, 128> spriteStates;
|
||||
ox::Array<renderer::Background, 4> backgrounds;
|
||||
ox::Optional<ox::Size> renderSize;
|
||||
renderer::Drawer drawer;
|
||||
explicit GlContext(turbine::Context &tctx) noexcept;
|
||||
~GlContext() noexcept override;
|
||||
class Context {
|
||||
|
||||
public:
|
||||
turbine::Context &turbineCtx;
|
||||
glutils::GLProgram bgShader;
|
||||
glutils::GLProgram spriteShader;
|
||||
ox::Array<renderer::CBB, 4> cbbs;
|
||||
renderer::SpriteBlockset spriteBlocks;
|
||||
ox::Array<Sprite, 128> spriteStates;
|
||||
ox::Array<renderer::Background, 4> backgrounds;
|
||||
renderer::Drawer drawer;
|
||||
explicit Context(turbine::Context &tctx) noexcept;
|
||||
~Context() noexcept;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -15,32 +15,25 @@
|
||||
#include <nostalgia/core/tilesheet.hpp>
|
||||
|
||||
#include "context.hpp"
|
||||
#include "gfx.hpp"
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
[[nodiscard]]
|
||||
inline GlContext &glctx(Context &ctx) noexcept {
|
||||
if constexpr(ox::defines::Debug) {
|
||||
return dynamic_cast<GlContext&>(ctx);
|
||||
} else {
|
||||
return static_cast<GlContext&>(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
constexpr auto Scale = 5;
|
||||
constexpr auto Scale = 1;
|
||||
|
||||
namespace renderer {
|
||||
|
||||
Drawer::Drawer(Context &ctx) noexcept: m_ctx(ctx) {}
|
||||
|
||||
void Drawer::draw(turbine::Context &tctx) noexcept {
|
||||
core::gl::drawMainView(m_ctx, turbine::getScreenSize(tctx));
|
||||
core::gl::draw(m_ctx, turbine::getScreenSize(tctx));
|
||||
}
|
||||
|
||||
constexpr ox::StringView bgvshadTmpl = R"(
|
||||
constexpr ox::StringView bgvshadTmpl = R"glsl(
|
||||
{}
|
||||
in vec2 vTexCoord;
|
||||
in vec2 vPosition;
|
||||
in float vTileIdx;
|
||||
out vec2 fTexCoord;
|
||||
uniform float vXScale;
|
||||
uniform float vTileHeight;
|
||||
@ -49,10 +42,12 @@ constexpr ox::StringView bgvshadTmpl = R"(
|
||||
gl_Position = vec4(
|
||||
vPosition.x * vXScale - xScaleInvert, vPosition.y,
|
||||
0.0, 1.0);
|
||||
fTexCoord = vTexCoord;
|
||||
})";
|
||||
fTexCoord = vec2(
|
||||
vTexCoord.x,
|
||||
vTexCoord.y * vTileHeight + vTileIdx * vTileHeight);
|
||||
})glsl";
|
||||
|
||||
constexpr ox::StringView bgfshadTmpl = R"(
|
||||
constexpr ox::StringView bgfshadTmpl = R"glsl(
|
||||
{}
|
||||
out vec4 outColor;
|
||||
in vec2 fTexCoord;
|
||||
@ -68,21 +63,11 @@ constexpr ox::StringView bgfshadTmpl = R"(
|
||||
void main() {
|
||||
pixelSz = vec2(1, 1) / (fSrcImgSz);
|
||||
vec2 pixelCoord = floor(fTexCoord / pixelSz) * pixelSz;
|
||||
vec4 c0 = getColor(pixelCoord + pixelSz * vec2(0, 0));
|
||||
vec4 c1 = getColor(pixelCoord + pixelSz * vec2(0.75, 0));
|
||||
vec4 c2 = getColor(pixelCoord + pixelSz * vec2(0, 0.75));
|
||||
vec4 c3 = getColor(pixelCoord + pixelSz * vec2(0.75, 0.75));
|
||||
float u = fTexCoord.x - fTexCoord.x / pixelSz.x;
|
||||
float v = fTexCoord.y - fTexCoord.y / pixelSz.y;
|
||||
vec4 b0 = (1.0 - u) * c0 + u * c1;
|
||||
vec4 b1 = (1.0 - u) * c2 + u * c3;
|
||||
outColor = (1.0 - v) * b0 + u * b1;
|
||||
outColor = fPalette[int(texture(image, fTexCoord).rgb.r * 256)];
|
||||
//outColor = fPalette[int(texture(image, pixelCoord).rgb.r * 256)];
|
||||
//outColor = vec4(0.0, 0.7, 1.0, 1.0);
|
||||
})";
|
||||
})glsl";
|
||||
|
||||
constexpr ox::StringView spritevshadTmpl = R"(
|
||||
constexpr ox::StringView spritevshadTmpl = R"glsl(
|
||||
{}
|
||||
in float vEnabled;
|
||||
in vec2 vTexCoord;
|
||||
@ -96,7 +81,7 @@ constexpr ox::StringView spritevshadTmpl = R"(
|
||||
vPosition.x * vXScale - xScaleInvert, vPosition.y,
|
||||
0.0, 1.0);
|
||||
fTexCoord = vTexCoord * vec2(1, vTileHeight) * vec2(vEnabled, vEnabled);
|
||||
})";
|
||||
})glsl";
|
||||
|
||||
constexpr ox::StringView spritefshadTmpl = bgfshadTmpl;
|
||||
|
||||
@ -142,8 +127,7 @@ static void setTileBufferObject(
|
||||
uint_t vi,
|
||||
float x,
|
||||
float y,
|
||||
float textureYOffset,
|
||||
float tileHeight,
|
||||
float textureTileIdx,
|
||||
float *vbo,
|
||||
GLuint *ebo) noexcept {
|
||||
// don't worry, this memcpy gets optimized to something much more ideal
|
||||
@ -153,14 +137,14 @@ static void setTileBufferObject(
|
||||
y *= -ymod;
|
||||
x -= 1.0f;
|
||||
y += 1.0f - ymod;
|
||||
const ox::Array<float, BgVertexVboLength> vertices {
|
||||
x, y, 0, tileHeight + textureYOffset, // bottom left
|
||||
x + xmod, y, 1, tileHeight + textureYOffset, // bottom right
|
||||
x + xmod, y + ymod, 1, 0 + textureYOffset, // top right
|
||||
x, y + ymod, 0, 0 + textureYOffset, // top left
|
||||
ox::Array<float, BgVertexVboLength> const vertices {
|
||||
x, y, 0, 1, textureTileIdx, // bottom left
|
||||
x + xmod, y, 1, 1, textureTileIdx, // bottom right
|
||||
x + xmod, y + ymod, 1, 0, textureTileIdx, // top right
|
||||
x, y + ymod, 0, 0, textureTileIdx, // top left
|
||||
};
|
||||
memcpy(vbo, vertices.data(), sizeof(vertices));
|
||||
const ox::Array<GLuint, BgVertexEboLength> elms {
|
||||
ox::Array<GLuint, BgVertexEboLength> const elms {
|
||||
vi + 0, vi + 1, vi + 2,
|
||||
vi + 2, vi + 3, vi + 0,
|
||||
};
|
||||
@ -186,7 +170,6 @@ static void initBackgroundBufferObjects(glutils::BufferSet &bg) noexcept {
|
||||
static_cast<float>(x),
|
||||
static_cast<float>(y),
|
||||
0,
|
||||
0,
|
||||
vbo,
|
||||
ebo);
|
||||
}
|
||||
@ -236,11 +219,16 @@ static void initBackgroundBufferset(
|
||||
auto const texCoordAttr = static_cast<GLuint>(glGetAttribLocation(shader, "vTexCoord"));
|
||||
glEnableVertexAttribArray(texCoordAttr);
|
||||
glVertexAttribPointer(
|
||||
texCoordAttr, 2, GL_FLOAT, GL_FALSE, BgVertexVboRowLength * sizeof(bg.vertices[0]),
|
||||
reinterpret_cast<void*>(2 * sizeof(bg.vertices[0])));
|
||||
texCoordAttr, 2, GL_FLOAT, GL_FALSE, BgVertexVboRowLength * sizeof(float),
|
||||
reinterpret_cast<void*>(2 * sizeof(float)));
|
||||
auto const heightMultAttr = static_cast<GLuint>(glGetAttribLocation(shader, "vTileIdx"));
|
||||
glEnableVertexAttribArray(heightMultAttr);
|
||||
glVertexAttribPointer(
|
||||
heightMultAttr, 1, GL_FLOAT, GL_FALSE, BgVertexVboRowLength * sizeof(float),
|
||||
reinterpret_cast<void*>(4 * sizeof(float)));
|
||||
}
|
||||
|
||||
static glutils::GLTexture loadTexture(
|
||||
static glutils::GLTexture createTexture(
|
||||
GLsizei w,
|
||||
GLsizei h,
|
||||
const void *pixels) noexcept {
|
||||
@ -252,8 +240,8 @@ static glutils::GLTexture loadTexture(
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, tex.id);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width, tex.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
return tex;
|
||||
@ -270,20 +258,20 @@ static void drawBackground(CBB &cbb) noexcept {
|
||||
}
|
||||
|
||||
static void drawBackgrounds(
|
||||
GlContext &gctx,
|
||||
Context &ctx,
|
||||
ox::Size const&renderSz) noexcept {
|
||||
// load background shader and its uniforms
|
||||
glUseProgram(gctx.bgShader);
|
||||
const auto uniformSrcImgSz = glGetUniformLocation(gctx.bgShader, "fSrcImgSz");
|
||||
const auto uniformXScale = static_cast<GLint>(glGetUniformLocation(gctx.bgShader, "vXScale"));
|
||||
const auto uniformTileHeight = static_cast<GLint>(glGetUniformLocation(gctx.bgShader, "vTileHeight"));
|
||||
glUseProgram(ctx.bgShader);
|
||||
const auto uniformSrcImgSz = glGetUniformLocation(ctx.bgShader, "fSrcImgSz");
|
||||
const auto uniformXScale = static_cast<GLint>(glGetUniformLocation(ctx.bgShader, "vXScale"));
|
||||
const auto uniformTileHeight = static_cast<GLint>(glGetUniformLocation(ctx.bgShader, "vTileHeight"));
|
||||
const auto [wi, hi] = renderSz;
|
||||
const auto wf = static_cast<float>(wi);
|
||||
const auto hf = static_cast<float>(hi);
|
||||
glUniform1f(uniformXScale, hf / wf);
|
||||
for (const auto &bg : gctx.backgrounds) {
|
||||
for (const auto &bg : ctx.backgrounds) {
|
||||
if (bg.enabled) {
|
||||
auto &cbb = gctx.cbbs[bg.cbbIdx];
|
||||
auto &cbb = ctx.cbbs[bg.cbbIdx];
|
||||
const auto tileRows = cbb.tex.height / (TileHeight * Scale);
|
||||
glUniform1f(uniformTileHeight, 1.0f / static_cast<float>(tileRows));
|
||||
glUniform2f(
|
||||
@ -295,11 +283,11 @@ static void drawBackgrounds(
|
||||
}
|
||||
}
|
||||
|
||||
static void drawSprites(GlContext &gctx, ox::Size const&renderSz) noexcept {
|
||||
glUseProgram(gctx.spriteShader);
|
||||
auto &sb = gctx.spriteBlocks;
|
||||
const auto uniformXScale = glGetUniformLocation(gctx.bgShader, "vXScale");
|
||||
const auto uniformTileHeight = glGetUniformLocation(gctx.spriteShader, "vTileHeight");
|
||||
static void drawSprites(Context &ctx, ox::Size const&renderSz) noexcept {
|
||||
glUseProgram(ctx.spriteShader);
|
||||
auto &sb = ctx.spriteBlocks;
|
||||
const auto uniformXScale = glGetUniformLocation(ctx.bgShader, "vXScale");
|
||||
const auto uniformTileHeight = glGetUniformLocation(ctx.spriteShader, "vTileHeight");
|
||||
const auto [wi, hi] = renderSz;
|
||||
const auto wf = static_cast<float>(wi);
|
||||
const auto hf = static_cast<float>(hi);
|
||||
@ -338,61 +326,59 @@ static void loadPalette(
|
||||
glUniform4fv(uniformPalette, ColorCnt, palette.data());
|
||||
}
|
||||
|
||||
static void loadBgPalette(GlContext &gctx, Palette const&pal) noexcept {
|
||||
loadPalette(gctx.bgShader, pal);
|
||||
static void loadBgPalette(Context &ctx, Palette const&pal) noexcept {
|
||||
loadPalette(ctx.bgShader, pal);
|
||||
}
|
||||
|
||||
static void loadSpritePalette(GlContext &gctx, Palette const&pal) noexcept {
|
||||
loadPalette(gctx.spriteShader, pal, true);
|
||||
static void loadSpritePalette(Context &ctx, Palette const&pal) noexcept {
|
||||
loadPalette(ctx.spriteShader, pal, true);
|
||||
}
|
||||
|
||||
static void loadBgTexture(
|
||||
GlContext &gctx,
|
||||
Context &ctx,
|
||||
uint_t cbbIdx,
|
||||
const void *pixels,
|
||||
int w,
|
||||
int h) noexcept {
|
||||
oxTracef("nostalgia.core.gfx.gl", "loadBgTexture: { cbbIdx: {}, w: {}, h: {} }", cbbIdx, w, h);
|
||||
gctx.cbbs[cbbIdx].tex = loadTexture(w, h, pixels);
|
||||
ctx.cbbs[cbbIdx].tex = createTexture(w, h, pixels);
|
||||
}
|
||||
|
||||
static void loadSpriteTexture(
|
||||
GlContext &gctx,
|
||||
Context &ctx,
|
||||
const void *pixels,
|
||||
int w,
|
||||
int h) noexcept {
|
||||
oxTracef("nostalgia.core.gfx.gl", "loadSpriteTexture: { w: {}, h: {} }", w, h);
|
||||
gctx.spriteBlocks.tex = loadTexture(w, h, pixels);
|
||||
ctx.spriteBlocks.tex = createTexture(w, h, pixels);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ox::Error initGfx(
|
||||
Context *ctx,
|
||||
Context &ctx,
|
||||
InitParams const&initParams) noexcept {
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
const auto bgVshad = ox::sfmt(renderer::bgvshadTmpl, glutils::GlslVersion);
|
||||
const auto bgFshad = ox::sfmt(renderer::bgfshadTmpl, glutils::GlslVersion);
|
||||
const auto spriteVshad = ox::sfmt(renderer::spritevshadTmpl, glutils::GlslVersion);
|
||||
const auto spriteFshad = ox::sfmt(renderer::spritefshadTmpl, glutils::GlslVersion);
|
||||
auto &gctx = glctx(*ctx);
|
||||
oxReturnError(glutils::buildShaderProgram(bgVshad.c_str(), bgFshad.c_str()).moveTo(&gctx.bgShader));
|
||||
const auto bgVshad = ox::sfmt(renderer::bgvshadTmpl, gl::GlslVersion);
|
||||
const auto bgFshad = ox::sfmt(renderer::bgfshadTmpl, gl::GlslVersion);
|
||||
const auto spriteVshad = ox::sfmt(renderer::spritevshadTmpl, gl::GlslVersion);
|
||||
const auto spriteFshad = ox::sfmt(renderer::spritefshadTmpl, gl::GlslVersion);
|
||||
oxReturnError(glutils::buildShaderProgram(bgVshad, bgFshad).moveTo(&ctx.bgShader));
|
||||
oxReturnError(
|
||||
glutils::buildShaderProgram(spriteVshad.c_str(), spriteFshad.c_str()).moveTo(&gctx.spriteShader));
|
||||
for (auto &bg : gctx.cbbs) {
|
||||
initBackgroundBufferset(gctx.bgShader, bg);
|
||||
glutils::buildShaderProgram(spriteVshad, spriteFshad).moveTo(&ctx.spriteShader));
|
||||
for (auto &bg : ctx.cbbs) {
|
||||
initBackgroundBufferset(ctx.bgShader, bg);
|
||||
}
|
||||
initSpritesBufferset(gctx.spriteShader, gctx.spriteBlocks);
|
||||
initSpritesBufferset(ctx.spriteShader, ctx.spriteBlocks);
|
||||
if (initParams.glInstallDrawer) {
|
||||
turbine::gl::addDrawer(gctx.turbineCtx, &gctx.drawer);
|
||||
turbine::gl::addDrawer(ctx.turbineCtx, &ctx.drawer);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void shutdownGfx(Context &ctx) noexcept {
|
||||
auto &gctx = glctx(ctx);
|
||||
turbine::gl::removeDrawer(gctx.turbineCtx, &gctx.drawer);
|
||||
turbine::gl::removeDrawer(ctx.turbineCtx, &ctx.drawer);
|
||||
}
|
||||
|
||||
struct TileSheetData {
|
||||
@ -406,8 +392,8 @@ struct TileSheetData {
|
||||
};
|
||||
|
||||
static ox::Result<TileSheetData> loadTileSheet(
|
||||
Context &ctx, CompactTileSheet const&tilesheet) noexcept {
|
||||
auto &gctx = glctx(ctx);
|
||||
Context &ctx,
|
||||
CompactTileSheet const&tilesheet) noexcept {
|
||||
const uint_t bytesPerTile = tilesheet.bpp == 8 ? PixelsPerTile : PixelsPerTile / 2;
|
||||
const auto tiles = tilesheet.pixels.size() / bytesPerTile;
|
||||
constexpr int width = 8;
|
||||
@ -425,54 +411,52 @@ static ox::Result<TileSheetData> loadTileSheet(
|
||||
pixels[i * 2 + 1] = tilesheet.pixels[i] >> 4;
|
||||
}
|
||||
}
|
||||
renderer::loadSpriteTexture(gctx, pixels.data(), width, height);
|
||||
renderer::loadSpriteTexture(ctx, pixels.data(), width, height);
|
||||
return TileSheetData{std::move(pixels), width, height};
|
||||
}
|
||||
|
||||
ox::Error loadBgTileSheet(
|
||||
Context *ctx,
|
||||
Context &ctx,
|
||||
uint_t cbb,
|
||||
ox::FileAddress const&tilesheetAddr,
|
||||
ox::FileAddress const&paletteAddr) noexcept {
|
||||
auto &gctx = glctx(*ctx);
|
||||
auto &kctx = gctx.turbineCtx.keelCtx;
|
||||
oxRequire(tilesheet, readObj<CompactTileSheet>(&kctx, tilesheetAddr));
|
||||
oxRequire(palette, readObj<Palette>(&kctx, paletteAddr ? paletteAddr : tilesheet->defaultPalette));
|
||||
oxRequire(tsd, loadTileSheet(*ctx, *tilesheet).to([](TileSheetData const&t) -> TileSheetData {
|
||||
auto &kctx = keelCtx(ctx.turbineCtx);
|
||||
oxRequire(tilesheet, readObj<CompactTileSheet>(kctx, tilesheetAddr));
|
||||
oxRequire(palette, readObj<Palette>(kctx, paletteAddr ? paletteAddr : tilesheet->defaultPalette));
|
||||
oxRequire(tsd, loadTileSheet(ctx, *tilesheet).to([](TileSheetData const&t) -> TileSheetData {
|
||||
return {
|
||||
.pixels = resizeTileSheetData(t.pixels, t.size(), Scale),
|
||||
.width = t.width * Scale,
|
||||
.height = t.height * Scale,
|
||||
};
|
||||
}));
|
||||
renderer::loadBgTexture(gctx, cbb, tsd.pixels.data(), tsd.width, tsd.height);
|
||||
renderer::loadBgPalette(gctx, *palette);
|
||||
renderer::loadBgTexture(ctx, cbb, tsd.pixels.data(), tsd.width, tsd.height);
|
||||
renderer::loadBgPalette(ctx, *palette);
|
||||
return {};
|
||||
}
|
||||
|
||||
ox::Error loadSpriteTileSheet(
|
||||
Context *ctx,
|
||||
Context &ctx,
|
||||
ox::FileAddress const&tilesheetAddr,
|
||||
ox::FileAddress const&paletteAddr) noexcept {
|
||||
auto &gctx = glctx(*ctx);
|
||||
auto &kctx = gctx.turbineCtx.keelCtx;
|
||||
oxRequire(tilesheet, readObj<CompactTileSheet>(&kctx, tilesheetAddr));
|
||||
oxRequire(palette, readObj<Palette>(&kctx, paletteAddr ? paletteAddr : tilesheet->defaultPalette));
|
||||
oxRequire(tsd, loadTileSheet(*ctx, *tilesheet));
|
||||
renderer::loadSpriteTexture(gctx, tsd.pixels.data(), tsd.width, tsd.height);
|
||||
renderer::loadSpritePalette(gctx, *palette);
|
||||
auto &kctx = keelCtx(ctx.turbineCtx);
|
||||
oxRequire(tilesheet, readObj<CompactTileSheet>(kctx, tilesheetAddr));
|
||||
oxRequire(palette, readObj<Palette>(kctx, paletteAddr ? paletteAddr : tilesheet->defaultPalette));
|
||||
oxRequire(tsd, loadTileSheet(ctx, *tilesheet));
|
||||
renderer::loadSpriteTexture(ctx, tsd.pixels.data(), tsd.width, tsd.height);
|
||||
renderer::loadSpritePalette(ctx, *palette);
|
||||
return {};
|
||||
}
|
||||
|
||||
ox::Error initConsole(Context *ctx) noexcept {
|
||||
constexpr ox::FileAddress TilesheetAddr("/TileSheets/Charset.ng");
|
||||
constexpr ox::FileAddress PaletteAddr("/Palettes/Charset.npal");
|
||||
ox::Error initConsole(Context &ctx) noexcept {
|
||||
constexpr ox::FileAddress TilesheetAddr = ox::StringLiteral("/TileSheets/Charset.ng");
|
||||
constexpr ox::FileAddress PaletteAddr = ox::StringLiteral("/Palettes/Charset.npal");
|
||||
setBgStatus(ctx, 0b0001);
|
||||
setBgCbb(ctx, 0, 0);
|
||||
return loadBgTileSheet(ctx, 0, TilesheetAddr, PaletteAddr);
|
||||
}
|
||||
|
||||
void puts(Context *ctx, int column, int row, ox::CRStringView str) noexcept {
|
||||
void puts(Context &ctx, int column, int row, ox::CRStringView str) noexcept {
|
||||
const auto col = static_cast<uint_t>(column);
|
||||
for (auto i = 0u; i < str.bytes(); ++i) {
|
||||
setTile(
|
||||
@ -484,57 +468,50 @@ void puts(Context *ctx, int column, int row, ox::CRStringView str) noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
void setBgCbb(Context *ctx, uint_t bgIdx, uint_t cbbIdx) noexcept {
|
||||
auto &gctx = glctx(*ctx);
|
||||
auto &bg = gctx.backgrounds[bgIdx];
|
||||
void setBgCbb(Context &ctx, uint_t bgIdx, uint_t cbbIdx) noexcept {
|
||||
auto &bg = ctx.backgrounds[bgIdx];
|
||||
bg.cbbIdx = cbbIdx;
|
||||
}
|
||||
|
||||
uint8_t bgStatus(Context *ctx) noexcept {
|
||||
const auto &gctx = glctx(*ctx);
|
||||
uint8_t bgStatus(Context &ctx) noexcept {
|
||||
uint8_t out = 0;
|
||||
for (uint_t i = 0; i < gctx.cbbs.size(); ++i) {
|
||||
out |= static_cast<uint8_t>(static_cast<uint_t>(gctx.backgrounds[i].enabled) << i);
|
||||
for (uint_t i = 0; i < ctx.cbbs.size(); ++i) {
|
||||
out |= static_cast<uint8_t>(static_cast<uint_t>(ctx.backgrounds[i].enabled) << i);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
void setBgStatus(Context *ctx, uint32_t status) noexcept {
|
||||
auto &gctx = glctx(*ctx);
|
||||
for (uint_t i = 0; i < gctx.cbbs.size(); ++i) {
|
||||
gctx.backgrounds[i].enabled = (status >> i) & 1;
|
||||
void setBgStatus(Context &ctx, uint32_t status) noexcept {
|
||||
for (uint_t i = 0; i < ctx.cbbs.size(); ++i) {
|
||||
ctx.backgrounds[i].enabled = (status >> i) & 1;
|
||||
}
|
||||
}
|
||||
|
||||
bool bgStatus(Context *ctx, uint_t bg) noexcept {
|
||||
const auto &gctx = glctx(*ctx);
|
||||
return gctx.backgrounds[bg].enabled;
|
||||
bool bgStatus(Context &ctx, uint_t bg) noexcept {
|
||||
return ctx.backgrounds[bg].enabled;
|
||||
}
|
||||
|
||||
void setBgStatus(Context *ctx, uint_t bg, bool status) noexcept {
|
||||
auto &gctx = glctx(*ctx);
|
||||
gctx.backgrounds[bg].enabled = status;
|
||||
void setBgStatus(Context &ctx, uint_t bg, bool status) noexcept {
|
||||
ctx.backgrounds[bg].enabled = status;
|
||||
}
|
||||
|
||||
|
||||
void clearTileLayer(Context *ctx, uint_t bgIdx) noexcept {
|
||||
auto &gctx = glctx(*ctx);
|
||||
auto &bg = gctx.cbbs[static_cast<std::size_t>(bgIdx)];
|
||||
void clearTileLayer(Context &ctx, uint_t bgIdx) noexcept {
|
||||
auto &bg = ctx.cbbs[static_cast<std::size_t>(bgIdx)];
|
||||
initBackgroundBufferObjects(bg);
|
||||
bg.updated = true;
|
||||
}
|
||||
|
||||
void hideSprite(Context *ctx, uint_t idx) noexcept {
|
||||
auto &gctx = glctx(*ctx);
|
||||
auto vbo = &gctx.spriteBlocks.vertices[idx * renderer::SpriteVertexVboLength];
|
||||
auto ebo = &gctx.spriteBlocks.elements[idx * renderer::SpriteVertexEboLength];
|
||||
renderer::setSpriteBufferObject(idx * renderer::SpriteVertexVboRows, 0,
|
||||
0, 0, 0, false, vbo, ebo);
|
||||
gctx.spriteBlocks.updated = true;
|
||||
void hideSprite(Context &ctx, uint_t idx) noexcept {
|
||||
auto vbo = &ctx.spriteBlocks.vertices[idx * renderer::SpriteVertexVboLength];
|
||||
auto ebo = &ctx.spriteBlocks.elements[idx * renderer::SpriteVertexEboLength];
|
||||
renderer::setSpriteBufferObject(
|
||||
idx * renderer::SpriteVertexVboRows, 0, 0, 0, 0, false, vbo, ebo);
|
||||
ctx.spriteBlocks.updated = true;
|
||||
}
|
||||
|
||||
void setSprite(
|
||||
Context *ctx,
|
||||
Context &ctx,
|
||||
uint_t idx,
|
||||
int x,
|
||||
int y,
|
||||
@ -565,14 +542,13 @@ void setSprite(
|
||||
const auto dim = dimensions[(spriteShape << 2) | spriteSize];
|
||||
const auto uX = static_cast<int>(x) % 255;
|
||||
const auto uY = static_cast<int>(y + 8) % 255 - 8;
|
||||
auto &gctx = glctx(*ctx);
|
||||
auto i = 0u;
|
||||
const auto set = [&](int xIt, int yIt) {
|
||||
const auto fX = static_cast<float>(uX + xIt * 8) / 8;
|
||||
const auto fY = static_cast<float>(uY + yIt * 8) / 8;
|
||||
const auto cidx = idx + i;
|
||||
auto vbo = &gctx.spriteBlocks.vertices[cidx * renderer::SpriteVertexVboLength];
|
||||
auto ebo = &gctx.spriteBlocks.elements[cidx * renderer::SpriteVertexEboLength];
|
||||
auto vbo = &ctx.spriteBlocks.vertices[cidx * renderer::SpriteVertexVboLength];
|
||||
auto ebo = &ctx.spriteBlocks.elements[cidx * renderer::SpriteVertexEboLength];
|
||||
renderer::setSpriteBufferObject(
|
||||
cidx * renderer::SpriteVertexVboRows,
|
||||
1,
|
||||
@ -597,11 +573,11 @@ void setSprite(
|
||||
}
|
||||
}
|
||||
}
|
||||
gctx.spriteBlocks.updated = true;
|
||||
ctx.spriteBlocks.updated = true;
|
||||
}
|
||||
|
||||
void setTile(
|
||||
Context *ctx,
|
||||
Context &ctx,
|
||||
uint_t bgIdx,
|
||||
int column,
|
||||
int row,
|
||||
@ -610,22 +586,18 @@ void setTile(
|
||||
"nostalgia.core.gfx.setTile",
|
||||
"bgIdx: {}, column: {}, row: {}, tile: {}",
|
||||
bgIdx, column, row, tile);
|
||||
auto &gctx = glctx(*ctx);
|
||||
const auto z = static_cast<uint_t>(bgIdx);
|
||||
const auto y = static_cast<uint_t>(row);
|
||||
const auto x = static_cast<uint_t>(column);
|
||||
const auto i = renderer::bgVertexRow(x, y);
|
||||
auto &bg = gctx.cbbs[z];
|
||||
auto &bg = ctx.cbbs[z];
|
||||
const auto vbo = &bg.vertices[i * renderer::BgVertexVboLength];
|
||||
const auto ebo = &bg.elements[i * renderer::BgVertexEboLength];
|
||||
const auto tileHeight = static_cast<float>(TileHeight * Scale) / static_cast<float>(bg.tex.height);
|
||||
const auto tileOffset = tileHeight * static_cast<float>(tile);
|
||||
renderer::setTileBufferObject(
|
||||
static_cast<uint_t>(i * renderer::BgVertexVboRows),
|
||||
static_cast<float>(x),
|
||||
static_cast<float>(y),
|
||||
tileOffset,
|
||||
tileHeight,
|
||||
static_cast<float>(tile),
|
||||
vbo,
|
||||
ebo);
|
||||
bg.updated = true;
|
||||
@ -633,16 +605,23 @@ void setTile(
|
||||
|
||||
namespace gl {
|
||||
|
||||
void drawMainView(core::Context &ctx, ox::Size const&renderSz) noexcept {
|
||||
ox::Size drawSize(int scale) noexcept {
|
||||
return {240 * scale, 160 * scale};
|
||||
}
|
||||
|
||||
void draw(core::Context &ctx, ox::Size const&renderSz) noexcept {
|
||||
glViewport(0, 0, renderSz.width, renderSz.height);
|
||||
glutils::clearScreen();
|
||||
auto &gctx = glctx(ctx);
|
||||
renderer::drawBackgrounds(gctx, renderSz);
|
||||
if (gctx.spriteBlocks.tex) {
|
||||
renderer::drawSprites(gctx, renderSz);
|
||||
renderer::drawBackgrounds(ctx, renderSz);
|
||||
if (ctx.spriteBlocks.tex) {
|
||||
renderer::drawSprites(ctx, renderSz);
|
||||
}
|
||||
}
|
||||
|
||||
void draw(core::Context &ctx, int scale) noexcept {
|
||||
draw(ctx, drawSize(scale));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ constexpr uint64_t TileColumns = 128;
|
||||
constexpr uint64_t TileCount = TileRows * TileColumns;
|
||||
constexpr uint64_t SpriteCount = 128;
|
||||
constexpr uint64_t BgVertexVboRows = 4;
|
||||
constexpr uint64_t BgVertexVboRowLength = 4;
|
||||
constexpr uint64_t BgVertexVboRowLength = 5;
|
||||
constexpr uint64_t BgVertexVboLength = BgVertexVboRows * BgVertexVboRowLength;
|
||||
constexpr uint64_t BgVertexEboLength = 6;
|
||||
constexpr uint64_t SpriteVertexVboRows = 256;
|
||||
@ -63,6 +63,6 @@ class Drawer: public turbine::gl::Drawer {
|
||||
}
|
||||
|
||||
namespace nostalgia::core {
|
||||
ox::Error initGfx(Context *ctx, InitParams const&) noexcept;
|
||||
ox::Error initGfx(Context &ctx, InitParams const&) noexcept;
|
||||
void shutdownGfx(Context &ctx) noexcept;
|
||||
}
|
@ -1,17 +1,9 @@
|
||||
add_library(
|
||||
NostalgiaCore-Studio
|
||||
paletteeditor.cpp
|
||||
tilesheeteditorview.cpp
|
||||
tilesheeteditormodel.cpp
|
||||
tilesheetpixelgrid.cpp
|
||||
tilesheetpixels.cpp
|
||||
)
|
||||
add_library(NostalgiaCore-Studio)
|
||||
|
||||
add_library(
|
||||
NostalgiaCore-Studio-ImGui
|
||||
studiomodule.cpp
|
||||
paletteeditor-imgui.cpp
|
||||
tilesheeteditor-imgui.cpp
|
||||
tilesheeteditor/tilesheeteditor-imgui.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
@ -24,7 +16,6 @@ target_link_libraries(
|
||||
NostalgiaCore-Studio-ImGui PUBLIC
|
||||
NostalgiaCore-Studio
|
||||
Studio
|
||||
lodepng
|
||||
)
|
||||
|
||||
install(
|
||||
@ -34,3 +25,6 @@ install(
|
||||
LIBRARY DESTINATION
|
||||
${NOSTALGIA_DIST_MODULE}
|
||||
)
|
||||
|
||||
add_subdirectory(paletteeditor)
|
||||
add_subdirectory(tilesheeteditor)
|
||||
|
@ -0,0 +1,5 @@
|
||||
target_sources(
|
||||
NostalgiaCore-Studio PRIVATE
|
||||
paletteeditor.cpp
|
||||
paletteeditor-imgui.cpp
|
||||
)
|
@ -15,22 +15,22 @@
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
PaletteEditorImGui::PaletteEditorImGui(turbine::Context *ctx, ox::String path):
|
||||
PaletteEditorImGui::PaletteEditorImGui(turbine::Context &ctx, ox::CRStringView path):
|
||||
m_ctx(ctx),
|
||||
m_itemPath(std::move(path)),
|
||||
m_itemPath(path),
|
||||
m_itemName(m_itemPath.substr(std::find(m_itemPath.rbegin(), m_itemPath.rend(), '/').offset() + 1)),
|
||||
m_pal(*keel::readObj<Palette>(&m_ctx->keelCtx, ox::FileAddress(m_itemPath.c_str())).unwrapThrow()) {
|
||||
m_pal(*keel::readObj<Palette>(keelCtx(m_ctx), ox::FileAddress(m_itemPath.c_str())).unwrapThrow()) {
|
||||
}
|
||||
|
||||
const ox::String &PaletteEditorImGui::itemName() const noexcept {
|
||||
ox::CStringView PaletteEditorImGui::itemName() const noexcept {
|
||||
return m_itemPath;
|
||||
}
|
||||
|
||||
const ox::String &PaletteEditorImGui::itemDisplayName() const noexcept {
|
||||
ox::CStringView PaletteEditorImGui::itemDisplayName() const noexcept {
|
||||
return m_itemName;
|
||||
}
|
||||
|
||||
void PaletteEditorImGui::draw(turbine::Context*) noexcept {
|
||||
void PaletteEditorImGui::draw(turbine::Context&) noexcept {
|
||||
static constexpr auto flags = ImGuiTableFlags_RowBg;
|
||||
const auto paneSize = ImGui::GetContentRegionAvail();
|
||||
ImGui::BeginChild("Colors", ImVec2(paneSize.x - 208, paneSize.y), true);
|
||||
@ -42,14 +42,14 @@ void PaletteEditorImGui::draw(turbine::Context*) noexcept {
|
||||
if (ImGui::Button("Add", sz)) {
|
||||
const auto colorSz = static_cast<int>(m_pal.colors.size());
|
||||
constexpr Color16 c = 0;
|
||||
undoStack()->push(ox::make<AddColorCommand>(&m_pal, c, colorSz));
|
||||
undoStack()->push(ox::make_unique<AddColorCommand>(&m_pal, c, colorSz));
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::BeginDisabled(m_selectedRow >= m_pal.colors.size());
|
||||
{
|
||||
if (ImGui::Button("Remove", sz)) {
|
||||
undoStack()->push(
|
||||
ox::make<RemoveColorCommand>(
|
||||
ox::make_unique<RemoveColorCommand>(
|
||||
&m_pal,
|
||||
m_pal.colors[static_cast<std::size_t>(m_selectedRow)],
|
||||
static_cast<int>(m_selectedRow)));
|
||||
@ -59,7 +59,7 @@ void PaletteEditorImGui::draw(turbine::Context*) noexcept {
|
||||
ImGui::BeginDisabled(m_selectedRow <= 0);
|
||||
{
|
||||
if (ImGui::Button("Move Up", sz)) {
|
||||
undoStack()->push(ox::make<MoveColorCommand>(&m_pal, m_selectedRow, -1));
|
||||
undoStack()->push(ox::make_unique<MoveColorCommand>(&m_pal, m_selectedRow, -1));
|
||||
--m_selectedRow;
|
||||
}
|
||||
}
|
||||
@ -68,7 +68,7 @@ void PaletteEditorImGui::draw(turbine::Context*) noexcept {
|
||||
ImGui::BeginDisabled(m_selectedRow >= m_pal.colors.size() - 1);
|
||||
{
|
||||
if (ImGui::Button("Move Down", sz)) {
|
||||
undoStack()->push(ox::make<MoveColorCommand>(&m_pal, m_selectedRow, 1));
|
||||
undoStack()->push(ox::make_unique<MoveColorCommand>(&m_pal, m_selectedRow, 1));
|
||||
++m_selectedRow;
|
||||
}
|
||||
}
|
||||
@ -125,13 +125,13 @@ void PaletteEditorImGui::draw(turbine::Context*) noexcept {
|
||||
int r = red16(c);
|
||||
int g = green16(c);
|
||||
int b = blue16(c);
|
||||
int a = alpha16(c);
|
||||
int const a = alpha16(c);
|
||||
ImGui::InputInt("Red", &r, 1, 5);
|
||||
ImGui::InputInt("Green", &g, 1, 5);
|
||||
ImGui::InputInt("Blue", &b, 1, 5);
|
||||
const auto newColor = color16(r, g, b, a);
|
||||
if (c != newColor) {
|
||||
undoStack()->push(ox::make<UpdateColorCommand>(&m_pal, static_cast<int>(m_selectedRow), c, newColor));
|
||||
undoStack()->push(ox::make_unique<UpdateColorCommand>(&m_pal, static_cast<int>(m_selectedRow), c, newColor));
|
||||
}
|
||||
}
|
||||
ImGui::EndChild();
|
||||
@ -139,7 +139,7 @@ void PaletteEditorImGui::draw(turbine::Context*) noexcept {
|
||||
}
|
||||
|
||||
ox::Error PaletteEditorImGui::saveItem() noexcept {
|
||||
const auto sctx = applicationData<studio::StudioContext>(*m_ctx);
|
||||
const auto sctx = applicationData<studio::StudioContext>(m_ctx);
|
||||
return sctx->project->writeObj(m_itemPath, m_pal);
|
||||
}
|
||||
|
@ -14,25 +14,23 @@ namespace nostalgia::core {
|
||||
class PaletteEditorImGui: public studio::Editor {
|
||||
|
||||
private:
|
||||
turbine::Context *m_ctx = nullptr;
|
||||
turbine::Context &m_ctx;
|
||||
ox::String m_itemPath;
|
||||
ox::String m_itemName;
|
||||
Palette m_pal;
|
||||
std::size_t m_selectedRow = 0;
|
||||
|
||||
PaletteEditorImGui() noexcept = default;
|
||||
|
||||
public:
|
||||
PaletteEditorImGui(turbine::Context *ctx, ox::String path);
|
||||
PaletteEditorImGui(turbine::Context &ctx, ox::CRStringView path);
|
||||
|
||||
/**
|
||||
* Returns the name of item being edited.
|
||||
*/
|
||||
const ox::String &itemName() const noexcept final;
|
||||
ox::CStringView itemName() const noexcept final;
|
||||
|
||||
const ox::String &itemDisplayName() const noexcept final;
|
||||
ox::CStringView itemDisplayName() const noexcept final;
|
||||
|
||||
void draw(turbine::Context*) noexcept final;
|
||||
void draw(turbine::Context&) noexcept final;
|
||||
|
||||
protected:
|
||||
ox::Error saveItem() noexcept final;
|
@ -6,20 +6,20 @@
|
||||
|
||||
#include <studio/studio.hpp>
|
||||
|
||||
#include "paletteeditor-imgui.hpp"
|
||||
#include "tilesheeteditor-imgui.hpp"
|
||||
#include "paletteeditor/paletteeditor-imgui.hpp"
|
||||
#include "tilesheeteditor/tilesheeteditor-imgui.hpp"
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
class StudioModule: public studio::Module {
|
||||
ox::Vector<studio::EditorMaker> editors(turbine::Context *ctx) const noexcept final {
|
||||
ox::Vector<studio::EditorMaker> editors(turbine::Context &ctx) const noexcept final {
|
||||
return {
|
||||
studio::editorMaker<TileSheetEditorImGui>(ctx, FileExt_ng),
|
||||
studio::editorMaker<PaletteEditorImGui>(ctx, FileExt_npal),
|
||||
};
|
||||
}
|
||||
|
||||
ox::Vector<ox::UPtr<studio::ItemMaker>> itemMakers(turbine::Context*) const noexcept final {
|
||||
ox::Vector<ox::UPtr<studio::ItemMaker>> itemMakers(turbine::Context&) const noexcept final {
|
||||
ox::Vector<ox::UniquePtr<studio::ItemMaker>> out;
|
||||
out.emplace_back(ox::make<studio::ItemMakerT<core::TileSheet>>("Tile Sheet", "TileSheets", FileExt_ng));
|
||||
out.emplace_back(ox::make<studio::ItemMakerT<core::Palette>>("Palette", "Palettes", FileExt_npal));
|
||||
|
@ -0,0 +1,14 @@
|
||||
target_sources(
|
||||
NostalgiaCore-Studio PRIVATE
|
||||
tilesheeteditorview.cpp
|
||||
tilesheeteditormodel.cpp
|
||||
tilesheetpixelgrid.cpp
|
||||
tilesheetpixels.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
NostalgiaCore-Studio-ImGui PUBLIC
|
||||
lodepng
|
||||
)
|
||||
|
||||
add_subdirectory(commands)
|
@ -0,0 +1,11 @@
|
||||
target_sources(
|
||||
NostalgiaCore-Studio PRIVATE
|
||||
addsubsheetcommand.cpp
|
||||
cutpastecommand.cpp
|
||||
deletetilescommand.cpp
|
||||
drawcommand.cpp
|
||||
inserttilescommand.cpp
|
||||
palettechangecommand.cpp
|
||||
rmsubsheetcommand.cpp
|
||||
updatesubsheetcommand.cpp
|
||||
)
|
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#include "addsubsheetcommand.hpp"
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
AddSubSheetCommand::AddSubSheetCommand(
|
||||
TileSheet &img,
|
||||
TileSheet::SubSheetIdx parentIdx) noexcept:
|
||||
m_img(img), m_parentIdx(std::move(parentIdx)) {
|
||||
auto &parent = m_img.getSubSheet(m_parentIdx);
|
||||
if (!parent.subsheets.empty()) {
|
||||
auto idx = m_parentIdx;
|
||||
idx.emplace_back(parent.subsheets.size());
|
||||
m_addedSheets.push_back(idx);
|
||||
} else {
|
||||
auto idx = m_parentIdx;
|
||||
idx.emplace_back(0u);
|
||||
m_addedSheets.push_back(idx);
|
||||
*idx.back().value = 1;
|
||||
m_addedSheets.push_back(idx);
|
||||
}
|
||||
}
|
||||
|
||||
void AddSubSheetCommand::redo() noexcept {
|
||||
auto &parent = m_img.getSubSheet(m_parentIdx);
|
||||
if (m_addedSheets.size() < 2) {
|
||||
auto i = parent.subsheets.size();
|
||||
parent.subsheets.emplace_back(m_img.idIt++, ox::sfmt("Subsheet {}", i), 1, 1, m_img.bpp);
|
||||
} else {
|
||||
parent.subsheets.emplace_back(m_img.idIt++, "Subsheet 0", parent.columns, parent.rows, std::move(parent.pixels));
|
||||
parent.rows = 0;
|
||||
parent.columns = 0;
|
||||
parent.subsheets.emplace_back(m_img.idIt++, "Subsheet 1", 1, 1, m_img.bpp);
|
||||
}
|
||||
}
|
||||
|
||||
void AddSubSheetCommand::undo() noexcept {
|
||||
auto &parent = m_img.getSubSheet(m_parentIdx);
|
||||
if (parent.subsheets.size() == 2) {
|
||||
auto s = parent.subsheets[0];
|
||||
parent.rows = s.rows;
|
||||
parent.columns = s.columns;
|
||||
parent.pixels = std::move(s.pixels);
|
||||
parent.subsheets.clear();
|
||||
} else {
|
||||
for (auto idx = m_addedSheets.rbegin(); idx != m_addedSheets.rend(); ++idx) {
|
||||
oxLogError(m_img.rmSubSheet(*idx));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int AddSubSheetCommand::commandId() const noexcept {
|
||||
return static_cast<int>(CommandId::AddSubSheet);
|
||||
}
|
||||
|
||||
TileSheet::SubSheetIdx const&AddSubSheetCommand::subsheetIdx() const noexcept {
|
||||
return m_parentIdx;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "commands.hpp"
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
class AddSubSheetCommand: public TileSheetCommand {
|
||||
private:
|
||||
TileSheet &m_img;
|
||||
TileSheet::SubSheetIdx m_parentIdx;
|
||||
ox::Vector<TileSheet::SubSheetIdx, 2> m_addedSheets;
|
||||
|
||||
public:
|
||||
AddSubSheetCommand(TileSheet &img, TileSheet::SubSheetIdx parentIdx) noexcept;
|
||||
|
||||
void redo() noexcept final;
|
||||
|
||||
void undo() noexcept final;
|
||||
|
||||
[[nodiscard]]
|
||||
int commandId() const noexcept final;
|
||||
|
||||
[[nodiscard]]
|
||||
TileSheet::SubSheetIdx const&subsheetIdx() const noexcept override;
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <studio/undostack.hpp>
|
||||
#include <nostalgia/core/tilesheet.hpp>
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
// Command IDs to use with QUndoCommand::id()
|
||||
enum class CommandId {
|
||||
Draw = 1,
|
||||
AddSubSheet = 2,
|
||||
RmSubSheet = 3,
|
||||
DeleteTile = 4,
|
||||
InsertTile = 4,
|
||||
UpdateSubSheet = 5,
|
||||
Cut = 6,
|
||||
Paste = 7,
|
||||
PaletteChange = 8,
|
||||
};
|
||||
|
||||
constexpr bool operator==(CommandId c, int i) noexcept {
|
||||
return static_cast<int>(c) == i;
|
||||
}
|
||||
|
||||
constexpr bool operator==(int i, CommandId c) noexcept {
|
||||
return static_cast<int>(c) == i;
|
||||
}
|
||||
|
||||
class TileSheetCommand: public studio::UndoCommand {
|
||||
public:
|
||||
[[nodiscard]]
|
||||
virtual TileSheet::SubSheetIdx const&subsheetIdx() const noexcept = 0;
|
||||
};
|
||||
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#include "cutpastecommand.hpp"
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
TileSheetClipboard::Pixel::Pixel(uint16_t pColorIdx, ox::Point pPt) noexcept {
|
||||
colorIdx = pColorIdx;
|
||||
pt = pPt;
|
||||
}
|
||||
|
||||
|
||||
void TileSheetClipboard::addPixel(const ox::Point &pt, uint16_t colorIdx) noexcept {
|
||||
m_pixels.emplace_back(colorIdx, pt);
|
||||
}
|
||||
|
||||
const ox::Vector<TileSheetClipboard::Pixel> &TileSheetClipboard::pixels() const noexcept {
|
||||
return m_pixels;
|
||||
}
|
||||
|
||||
|
||||
CutPasteCommand::CutPasteCommand(
|
||||
CommandId commandId,
|
||||
TileSheet &img,
|
||||
TileSheet::SubSheetIdx subSheetIdx,
|
||||
const ox::Point &dstStart,
|
||||
const ox::Point &dstEnd,
|
||||
const TileSheetClipboard &cb) noexcept:
|
||||
m_commandId(commandId),
|
||||
m_img(img),
|
||||
m_subSheetIdx(std::move(subSheetIdx)) {
|
||||
const auto &subsheet = m_img.getSubSheet(m_subSheetIdx);
|
||||
for (const auto &p : cb.pixels()) {
|
||||
const auto dstPt = p.pt + dstStart;
|
||||
if (dstPt.x <= dstEnd.x && dstPt.y <= dstEnd.y) {
|
||||
const auto idx = subsheet.idx(dstPt);
|
||||
m_changes.emplace_back(static_cast<uint32_t>(idx), p.colorIdx, subsheet.getPixel(m_img.bpp, idx));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CutPasteCommand::redo() noexcept {
|
||||
auto &subsheet = m_img.getSubSheet(m_subSheetIdx);
|
||||
for (const auto &c : m_changes) {
|
||||
subsheet.setPixel(m_img.bpp, c.idx, static_cast<uint8_t>(c.newPalIdx));
|
||||
}
|
||||
}
|
||||
|
||||
void CutPasteCommand::undo() noexcept {
|
||||
auto &subsheet = m_img.getSubSheet(m_subSheetIdx);
|
||||
for (const auto &c : m_changes) {
|
||||
subsheet.setPixel(m_img.bpp, c.idx, static_cast<uint8_t>(c.oldPalIdx));
|
||||
}
|
||||
}
|
||||
|
||||
int CutPasteCommand::commandId() const noexcept {
|
||||
return static_cast<int>(m_commandId);
|
||||
}
|
||||
|
||||
TileSheet::SubSheetIdx const&CutPasteCommand::subsheetIdx() const noexcept {
|
||||
return m_subSheetIdx;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <turbine/clipboard.hpp>
|
||||
|
||||
#include "commands.hpp"
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
class TileSheetClipboard: public turbine::ClipboardObject<TileSheetClipboard> {
|
||||
public:
|
||||
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.studio.TileSheetClipboard";
|
||||
static constexpr auto TypeVersion = 1;
|
||||
|
||||
oxModelFriend(TileSheetClipboard);
|
||||
|
||||
struct Pixel {
|
||||
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.studio.TileSheetClipboard.Pixel";
|
||||
static constexpr auto TypeVersion = 1;
|
||||
uint16_t colorIdx = 0;
|
||||
ox::Point pt;
|
||||
Pixel(uint16_t pColorIdx, ox::Point pPt) noexcept;
|
||||
};
|
||||
protected:
|
||||
ox::Vector<Pixel> m_pixels;
|
||||
|
||||
public:
|
||||
void addPixel(ox::Point const&pt, uint16_t colorIdx) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
ox::Vector<Pixel> const&pixels() const noexcept;
|
||||
};
|
||||
|
||||
oxModelBegin(TileSheetClipboard::Pixel)
|
||||
oxModelField(colorIdx)
|
||||
oxModelField(pt)
|
||||
oxModelEnd()
|
||||
|
||||
oxModelBegin(TileSheetClipboard)
|
||||
oxModelFieldRename(pixels, m_pixels)
|
||||
oxModelEnd()
|
||||
|
||||
class CutPasteCommand: public TileSheetCommand {
|
||||
private:
|
||||
struct Change {
|
||||
uint32_t idx = 0;
|
||||
uint16_t newPalIdx = 0;
|
||||
uint16_t oldPalIdx = 0;
|
||||
constexpr Change(uint32_t pIdx, uint16_t pNewPalIdx, uint16_t pOldPalIdx) noexcept {
|
||||
idx = pIdx;
|
||||
newPalIdx = pNewPalIdx;
|
||||
oldPalIdx = pOldPalIdx;
|
||||
}
|
||||
};
|
||||
CommandId m_commandId;
|
||||
TileSheet &m_img;
|
||||
TileSheet::SubSheetIdx m_subSheetIdx;
|
||||
ox::Vector<Change> m_changes;
|
||||
|
||||
public:
|
||||
CutPasteCommand(
|
||||
CommandId commandId,
|
||||
TileSheet &img,
|
||||
TileSheet::SubSheetIdx subSheetIdx,
|
||||
ox::Point const&dstStart,
|
||||
ox::Point const&dstEnd,
|
||||
TileSheetClipboard const&cb) noexcept;
|
||||
|
||||
void redo() noexcept final;
|
||||
|
||||
void undo() noexcept final;
|
||||
|
||||
[[nodiscard]]
|
||||
int commandId() const noexcept final;
|
||||
|
||||
[[nodiscard]]
|
||||
TileSheet::SubSheetIdx const&subsheetIdx() const noexcept override;
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#include "deletetilescommand.hpp"
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
core::DeleteTilesCommand::DeleteTilesCommand(
|
||||
TileSheet &img,
|
||||
TileSheet::SubSheetIdx idx,
|
||||
std::size_t tileIdx,
|
||||
std::size_t tileCnt) noexcept:
|
||||
m_img(img),
|
||||
m_idx(std::move(idx)) {
|
||||
const unsigned bytesPerTile = m_img.bpp == 4 ? PixelsPerTile / 2 : PixelsPerTile;
|
||||
m_deletePos = tileIdx * bytesPerTile;
|
||||
m_deleteSz = tileCnt * bytesPerTile;
|
||||
m_deletedPixels.resize(m_deleteSz);
|
||||
// copy pixels to be erased
|
||||
{
|
||||
auto &s = m_img.getSubSheet(m_idx);
|
||||
auto &p = s.pixels;
|
||||
auto dst = m_deletedPixels.data();
|
||||
auto src = p.data() + m_deletePos;
|
||||
const auto sz = m_deleteSz * sizeof(decltype(p[0]));
|
||||
ox_memcpy(dst, src, sz);
|
||||
}
|
||||
}
|
||||
|
||||
void core::DeleteTilesCommand::redo() noexcept {
|
||||
auto &s = m_img.getSubSheet(m_idx);
|
||||
auto &p = s.pixels;
|
||||
auto srcPos = m_deletePos + m_deleteSz;
|
||||
const auto src = p.data() + srcPos;
|
||||
const auto dst1 = p.data() + m_deletePos;
|
||||
const auto dst2 = p.data() + (p.size() - m_deleteSz);
|
||||
ox_memmove(dst1, src, p.size() - srcPos);
|
||||
ox_memset(dst2, 0, m_deleteSz * sizeof(decltype(p[0])));
|
||||
}
|
||||
|
||||
void DeleteTilesCommand::undo() noexcept {
|
||||
auto &s = m_img.getSubSheet(m_idx);
|
||||
auto &p = s.pixels;
|
||||
const auto src = p.data() + m_deletePos;
|
||||
const auto dst1 = p.data() + m_deletePos + m_deleteSz;
|
||||
const auto dst2 = src;
|
||||
const auto sz = p.size() - m_deletePos - m_deleteSz;
|
||||
ox_memmove(dst1, src, sz);
|
||||
ox_memcpy(dst2, m_deletedPixels.data(), m_deletedPixels.size());
|
||||
}
|
||||
|
||||
int DeleteTilesCommand::commandId() const noexcept {
|
||||
return static_cast<int>(CommandId::DeleteTile);
|
||||
}
|
||||
|
||||
TileSheet::SubSheetIdx const&DeleteTilesCommand::subsheetIdx() const noexcept {
|
||||
return m_idx;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "commands.hpp"
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
class DeleteTilesCommand: public TileSheetCommand {
|
||||
private:
|
||||
TileSheet &m_img;
|
||||
TileSheet::SubSheetIdx m_idx;
|
||||
std::size_t m_deletePos = 0;
|
||||
std::size_t m_deleteSz = 0;
|
||||
ox::Vector<uint8_t> m_deletedPixels = {};
|
||||
|
||||
public:
|
||||
DeleteTilesCommand(
|
||||
TileSheet &img,
|
||||
TileSheet::SubSheetIdx idx,
|
||||
std::size_t tileIdx,
|
||||
std::size_t tileCnt) noexcept;
|
||||
|
||||
void redo() noexcept final;
|
||||
|
||||
void undo() noexcept final;
|
||||
|
||||
[[nodiscard]]
|
||||
int commandId() const noexcept final;
|
||||
|
||||
[[nodiscard]]
|
||||
TileSheet::SubSheetIdx const&subsheetIdx() const noexcept override;
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#include "drawcommand.hpp"
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
DrawCommand::DrawCommand(
|
||||
TileSheet &img,
|
||||
TileSheet::SubSheetIdx subSheetIdx,
|
||||
std::size_t idx,
|
||||
int palIdx) noexcept:
|
||||
m_img(img),
|
||||
m_subSheetIdx(std::move(subSheetIdx)),
|
||||
m_palIdx(palIdx) {
|
||||
auto &subsheet = m_img.getSubSheet(m_subSheetIdx);
|
||||
m_changes.emplace_back(static_cast<uint32_t>(idx), subsheet.getPixel(m_img.bpp, idx));
|
||||
}
|
||||
|
||||
DrawCommand::DrawCommand(
|
||||
TileSheet &img,
|
||||
TileSheet::SubSheetIdx subSheetIdx,
|
||||
const ox::Vector<std::size_t> &idxList,
|
||||
int palIdx) noexcept:
|
||||
m_img(img),
|
||||
m_subSheetIdx(std::move(subSheetIdx)),
|
||||
m_palIdx(palIdx) {
|
||||
auto &subsheet = m_img.getSubSheet(m_subSheetIdx);
|
||||
for (const auto idx : idxList) {
|
||||
m_changes.emplace_back(static_cast<uint32_t>(idx), subsheet.getPixel(m_img.bpp, idx));
|
||||
}
|
||||
}
|
||||
|
||||
bool DrawCommand::append(std::size_t idx) noexcept {
|
||||
auto &subsheet = m_img.getSubSheet(m_subSheetIdx);
|
||||
if (m_changes.back().value->idx != idx && subsheet.getPixel(m_img.bpp, idx) != m_palIdx) {
|
||||
// duplicate entries are bad
|
||||
auto existing = ox::find_if(m_changes.cbegin(), m_changes.cend(), [idx](const auto &c) {
|
||||
return c.idx == idx;
|
||||
});
|
||||
if (existing == m_changes.cend()) {
|
||||
m_changes.emplace_back(static_cast<uint32_t>(idx), subsheet.getPixel(m_img.bpp, idx));
|
||||
subsheet.setPixel(m_img.bpp, idx, static_cast<uint8_t>(m_palIdx));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DrawCommand::append(const ox::Vector<std::size_t> &idxList) noexcept {
|
||||
auto out = false;
|
||||
for (auto idx : idxList) {
|
||||
out = append(idx) || out;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
void DrawCommand::redo() noexcept {
|
||||
auto &subsheet = m_img.getSubSheet(m_subSheetIdx);
|
||||
for (const auto &c : m_changes) {
|
||||
subsheet.setPixel(m_img.bpp, c.idx, static_cast<uint8_t>(m_palIdx));
|
||||
}
|
||||
}
|
||||
|
||||
void DrawCommand::undo() noexcept {
|
||||
auto &subsheet = m_img.getSubSheet(m_subSheetIdx);
|
||||
for (const auto &c : m_changes) {
|
||||
subsheet.setPixel(m_img.bpp, c.idx, static_cast<uint8_t>(c.oldPalIdx));
|
||||
}
|
||||
}
|
||||
|
||||
int DrawCommand::commandId() const noexcept {
|
||||
return static_cast<int>(CommandId::Draw);
|
||||
}
|
||||
|
||||
TileSheet::SubSheetIdx const&DrawCommand::subsheetIdx() const noexcept {
|
||||
return m_subSheetIdx;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "commands.hpp"
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
class DrawCommand: public TileSheetCommand {
|
||||
private:
|
||||
struct Change {
|
||||
uint32_t idx = 0;
|
||||
uint16_t oldPalIdx = 0;
|
||||
constexpr Change(uint32_t pIdx, uint16_t pOldPalIdx) noexcept {
|
||||
idx = pIdx;
|
||||
oldPalIdx = pOldPalIdx;
|
||||
}
|
||||
};
|
||||
TileSheet &m_img;
|
||||
TileSheet::SubSheetIdx m_subSheetIdx;
|
||||
ox::Vector<Change, 8> m_changes;
|
||||
int m_palIdx = 0;
|
||||
|
||||
public:
|
||||
DrawCommand(
|
||||
TileSheet &img,
|
||||
TileSheet::SubSheetIdx subSheetIdx,
|
||||
std::size_t idx,
|
||||
int palIdx) noexcept;
|
||||
|
||||
DrawCommand(
|
||||
TileSheet &img,
|
||||
TileSheet::SubSheetIdx subSheetIdx,
|
||||
const ox::Vector<std::size_t> &idxList,
|
||||
int palIdx) noexcept;
|
||||
|
||||
bool append(std::size_t idx) noexcept;
|
||||
|
||||
bool append(const ox::Vector<std::size_t> &idxList) noexcept;
|
||||
|
||||
void redo() noexcept final;
|
||||
|
||||
void undo() noexcept final;
|
||||
|
||||
[[nodiscard]]
|
||||
int commandId() const noexcept final;
|
||||
|
||||
[[nodiscard]]
|
||||
TileSheet::SubSheetIdx const&subsheetIdx() const noexcept override;
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#include "inserttilescommand.hpp"
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
core::InsertTilesCommand::InsertTilesCommand(
|
||||
TileSheet &img,
|
||||
TileSheet::SubSheetIdx idx,
|
||||
std::size_t tileIdx,
|
||||
std::size_t tileCnt) noexcept:
|
||||
m_img(img),
|
||||
m_idx(std::move(idx)) {
|
||||
const unsigned bytesPerTile = m_img.bpp == 4 ? PixelsPerTile / 2 : PixelsPerTile;
|
||||
m_insertPos = tileIdx * bytesPerTile;
|
||||
m_insertCnt = tileCnt * bytesPerTile;
|
||||
m_deletedPixels.resize(m_insertCnt);
|
||||
// copy pixels to be erased
|
||||
{
|
||||
auto &s = m_img.getSubSheet(m_idx);
|
||||
auto &p = s.pixels;
|
||||
auto dst = m_deletedPixels.data();
|
||||
auto src = p.data() + p.size() - m_insertCnt;
|
||||
const auto sz = m_insertCnt * sizeof(decltype(p[0]));
|
||||
ox_memcpy(dst, src, sz);
|
||||
}
|
||||
}
|
||||
|
||||
void InsertTilesCommand::redo() noexcept {
|
||||
auto &s = m_img.getSubSheet(m_idx);
|
||||
auto &p = s.pixels;
|
||||
auto dstPos = m_insertPos + m_insertCnt;
|
||||
const auto dst = p.data() + dstPos;
|
||||
const auto src = p.data() + m_insertPos;
|
||||
ox_memmove(dst, src, p.size() - dstPos);
|
||||
ox_memset(src, 0, m_insertCnt * sizeof(decltype(p[0])));
|
||||
}
|
||||
|
||||
void InsertTilesCommand::undo() noexcept {
|
||||
auto &s = m_img.getSubSheet(m_idx);
|
||||
auto &p = s.pixels;
|
||||
const auto srcIdx = m_insertPos + m_insertCnt;
|
||||
const auto src = p.data() + srcIdx;
|
||||
const auto dst1 = p.data() + m_insertPos;
|
||||
const auto dst2 = p.data() + p.size() - m_insertCnt;
|
||||
const auto sz = p.size() - srcIdx;
|
||||
ox_memmove(dst1, src, sz);
|
||||
ox_memcpy(dst2, m_deletedPixels.data(), m_deletedPixels.size());
|
||||
}
|
||||
|
||||
int InsertTilesCommand::commandId() const noexcept {
|
||||
return static_cast<int>(CommandId::InsertTile);
|
||||
}
|
||||
|
||||
TileSheet::SubSheetIdx const&InsertTilesCommand::subsheetIdx() const noexcept {
|
||||
return m_idx;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "commands.hpp"
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
class InsertTilesCommand: public TileSheetCommand {
|
||||
private:
|
||||
TileSheet &m_img;
|
||||
TileSheet::SubSheetIdx m_idx;
|
||||
std::size_t m_insertPos = 0;
|
||||
std::size_t m_insertCnt = 0;
|
||||
ox::Vector<uint8_t> m_deletedPixels = {};
|
||||
|
||||
public:
|
||||
InsertTilesCommand(
|
||||
TileSheet &img,
|
||||
TileSheet::SubSheetIdx idx,
|
||||
std::size_t tileIdx,
|
||||
std::size_t tileCnt) noexcept;
|
||||
|
||||
void redo() noexcept final;
|
||||
|
||||
void undo() noexcept final;
|
||||
|
||||
[[nodiscard]]
|
||||
int commandId() const noexcept final;
|
||||
|
||||
[[nodiscard]]
|
||||
TileSheet::SubSheetIdx const&subsheetIdx() const noexcept override;
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#include "palettechangecommand.hpp"
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
core::PaletteChangeCommand::PaletteChangeCommand(
|
||||
TileSheet::SubSheetIdx idx,
|
||||
TileSheet &img,
|
||||
ox::CRStringView newPalette) noexcept:
|
||||
m_img(img),
|
||||
m_idx(std::move(idx)),
|
||||
m_oldPalette(m_img.defaultPalette),
|
||||
m_newPalette(ox::FileAddress(ox::sfmt<ox::BString<43>>("uuid://{}", newPalette))) {
|
||||
}
|
||||
|
||||
void PaletteChangeCommand::redo() noexcept {
|
||||
m_img.defaultPalette = m_newPalette;
|
||||
}
|
||||
|
||||
void PaletteChangeCommand::undo() noexcept {
|
||||
m_img.defaultPalette = m_oldPalette;
|
||||
}
|
||||
|
||||
int PaletteChangeCommand::commandId() const noexcept {
|
||||
return static_cast<int>(CommandId::PaletteChange);
|
||||
}
|
||||
|
||||
TileSheet::SubSheetIdx const&PaletteChangeCommand::subsheetIdx() const noexcept {
|
||||
return m_idx;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "commands.hpp"
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
class PaletteChangeCommand: public TileSheetCommand {
|
||||
private:
|
||||
TileSheet &m_img;
|
||||
TileSheet::SubSheetIdx m_idx;
|
||||
ox::FileAddress m_oldPalette;
|
||||
ox::FileAddress m_newPalette;
|
||||
|
||||
public:
|
||||
PaletteChangeCommand(
|
||||
TileSheet::SubSheetIdx idx,
|
||||
TileSheet &img,
|
||||
ox::CRStringView newPalette) noexcept;
|
||||
|
||||
void redo() noexcept final;
|
||||
|
||||
void undo() noexcept final;
|
||||
|
||||
[[nodiscard]]
|
||||
int commandId() const noexcept final;
|
||||
|
||||
[[nodiscard]]
|
||||
TileSheet::SubSheetIdx const&subsheetIdx() const noexcept override;
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#include "rmsubsheetcommand.hpp"
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
core::RmSubSheetCommand::RmSubSheetCommand(TileSheet &img, TileSheet::SubSheetIdx idx) noexcept:
|
||||
m_img(img),
|
||||
m_idx(std::move(idx)),
|
||||
m_parentIdx(m_idx) {
|
||||
m_parentIdx.pop_back();
|
||||
auto &parent = m_img.getSubSheet(m_parentIdx);
|
||||
m_sheet = parent.subsheets[*m_idx.back().value];
|
||||
}
|
||||
|
||||
void RmSubSheetCommand::redo() noexcept {
|
||||
auto &parent = m_img.getSubSheet(m_parentIdx);
|
||||
oxLogError(parent.subsheets.erase(*m_idx.back().value).error);
|
||||
}
|
||||
|
||||
void RmSubSheetCommand::undo() noexcept {
|
||||
auto &parent = m_img.getSubSheet(m_parentIdx);
|
||||
auto i = *m_idx.back().value;
|
||||
parent.subsheets.insert(i, m_sheet);
|
||||
}
|
||||
|
||||
int RmSubSheetCommand::commandId() const noexcept {
|
||||
return static_cast<int>(CommandId::RmSubSheet);
|
||||
}
|
||||
|
||||
TileSheet::SubSheetIdx const&RmSubSheetCommand::subsheetIdx() const noexcept {
|
||||
return m_idx;
|
||||
}
|
||||
|
||||
}
|
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